diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..9fd870b859 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +*.log +cmake_targets/log/ +cmake_targets/ran_build/ +common/utils/T/T_IDs.h +common/utils/T/T_messages.txt.h +common/utils/T/genids +common/utils/T/genids.o +targets/bin/ diff --git a/.gitignore b/.gitignore index 8f8ff1f454..ff947966a2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,9 @@ targets/bin/ # vscode .vscode + +# Tags for vim/global +GPATH +GRTAGS +GTAGS +tags diff --git a/.vscode/launch.json b/.vscode/launch.json index 6757ed47f6..4b563febde 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,4 +25,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/CHANGELOG.md b/CHANGELOG.md old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/NOTICE.md b/NOTICE.md index 96b5d4c552..39dd33795d 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -21,3 +21,7 @@ The Regents of the University of California: BSD 3-Clause Licence. Niels Provos : BSD 2-Clause Licence. +## Credits for source code openair3/GTPV1-U/nw-gtpv1u: ## + +Amit Chawre : BSD 2-Clause Licence. + diff --git a/README.md b/README.md index 7651aea5c9..62f8576e81 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,24 @@ +

+ OAI +

+ +

+ License + Supported OS + Supported OS +

+ +

+ +

+ +

+ Docker Pulls + Docker Pulls + Docker Pulls + Docker Pulls +

+ # OpenAirInterface License # OpenAirInterface is under OpenAirInterface Software Alliance license. diff --git a/charts/physims/Chart.yaml b/charts/physims/Chart.yaml new file mode 100644 index 0000000000..bef28aac27 --- /dev/null +++ b/charts/physims/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-physim +description: A Helm chart for physical simulators network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulators + - RAN + - 4G + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/dlsim/Chart.yaml b/charts/physims/charts/dlsim/Chart.yaml new file mode 100644 index 0000000000..de7f5958b2 --- /dev/null +++ b/charts/physims/charts/dlsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-dlsim +description: A Helm subchart for dlsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - dlsim + - RAN + - 4G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/dlsim/templates/NOTES.txt b/charts/physims/charts/dlsim/templates/NOTES.txt new file mode 100644 index 0000000000..75b79e3dd4 --- /dev/null +++ b/charts/physims/charts/dlsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-dlsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-dlsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-dlsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-dlsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/dlsim/templates/_helpers.tpl b/charts/physims/charts/dlsim/templates/_helpers.tpl new file mode 100644 index 0000000000..7ae142b671 --- /dev/null +++ b/charts/physims/charts/dlsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-dlsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-dlsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-dlsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-dlsim.labels" -}} +helm.sh/chart: {{ include "oai-dlsim.chart" . }} +{{ include "oai-dlsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-dlsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-dlsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-dlsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-dlsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/dlsim/templates/deployment.yaml b/charts/physims/charts/dlsim/templates/deployment.yaml new file mode 100644 index 0000000000..9cbdd383b3 --- /dev/null +++ b/charts/physims/charts/dlsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-dlsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-dlsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-dlsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-dlsim + # volumeMounts: + # - mountPath: /opt/oai-dlsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015100" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/dlsim/templates/service.yaml b/charts/physims/charts/dlsim/templates/service.yaml new file mode 100644 index 0000000000..6aeb0dbf53 --- /dev/null +++ b/charts/physims/charts/dlsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-dlsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-dlsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-dlsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/dlsim/values.yaml b/charts/physims/charts/dlsim/values.yaml new file mode 100644 index 0000000000..c0142b50ae --- /dev/null +++ b/charts/physims/charts/dlsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-dlsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-dlsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/ldpctest/Chart.yaml b/charts/physims/charts/ldpctest/Chart.yaml new file mode 100644 index 0000000000..667bd3d8aa --- /dev/null +++ b/charts/physims/charts/ldpctest/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-ldpctest +description: A Helm subchart for ldpctest network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - ldpctest + - RAN + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/ldpctest/templates/NOTES.txt b/charts/physims/charts/ldpctest/templates/NOTES.txt new file mode 100644 index 0000000000..bda83c2f9e --- /dev/null +++ b/charts/physims/charts/ldpctest/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-ldpctest.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-ldpctest.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-ldpctest.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-ldpctest.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/ldpctest/templates/_helpers.tpl b/charts/physims/charts/ldpctest/templates/_helpers.tpl new file mode 100644 index 0000000000..018eaa5af5 --- /dev/null +++ b/charts/physims/charts/ldpctest/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-ldpctest.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-ldpctest.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-ldpctest.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-ldpctest.labels" -}} +helm.sh/chart: {{ include "oai-ldpctest.chart" . }} +{{ include "oai-ldpctest.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-ldpctest.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-ldpctest.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-ldpctest.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-ldpctest.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/ldpctest/templates/deployment.yaml b/charts/physims/charts/ldpctest/templates/deployment.yaml new file mode 100644 index 0000000000..ef30d9c08a --- /dev/null +++ b/charts/physims/charts/ldpctest/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-ldpctest.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-ldpctest.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-ldpctest.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-ldpctest + # volumeMounts: + # - mountPath: /opt/oai-ldpctest/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015102" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/ldpctest/templates/service.yaml b/charts/physims/charts/ldpctest/templates/service.yaml new file mode 100644 index 0000000000..eb0db8ce00 --- /dev/null +++ b/charts/physims/charts/ldpctest/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-ldpctest.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-ldpctest + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-ldpctest.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/ldpctest/values.yaml b/charts/physims/charts/ldpctest/values.yaml new file mode 100644 index 0000000000..91eab91af5 --- /dev/null +++ b/charts/physims/charts/ldpctest/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-ldpctest. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-ldpctest-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/nr-dlschsim/Chart.yaml b/charts/physims/charts/nr-dlschsim/Chart.yaml new file mode 100644 index 0000000000..3837f0cd2b --- /dev/null +++ b/charts/physims/charts/nr-dlschsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-nr-dlschsim +description: A Helm subchart for nr-dlschsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - nr-dlschsim + - RAN + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/nr-dlschsim/templates/NOTES.txt b/charts/physims/charts/nr-dlschsim/templates/NOTES.txt new file mode 100644 index 0000000000..1f88d64976 --- /dev/null +++ b/charts/physims/charts/nr-dlschsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-nr-dlschsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-nr-dlschsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-nr-dlschsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-nr-dlschsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/nr-dlschsim/templates/_helpers.tpl b/charts/physims/charts/nr-dlschsim/templates/_helpers.tpl new file mode 100644 index 0000000000..6b6a5181e9 --- /dev/null +++ b/charts/physims/charts/nr-dlschsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-nr-dlschsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-nr-dlschsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-nr-dlschsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-nr-dlschsim.labels" -}} +helm.sh/chart: {{ include "oai-nr-dlschsim.chart" . }} +{{ include "oai-nr-dlschsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-nr-dlschsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-nr-dlschsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-nr-dlschsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-nr-dlschsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/nr-dlschsim/templates/deployment.yaml b/charts/physims/charts/nr-dlschsim/templates/deployment.yaml new file mode 100644 index 0000000000..06f01a0f0b --- /dev/null +++ b/charts/physims/charts/nr-dlschsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-dlschsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-nr-dlschsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-nr-dlschsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-nr-dlschsim + # volumeMounts: + # - mountPath: /opt/oai-nr-dlschsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015106" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/nr-dlschsim/templates/service.yaml b/charts/physims/charts/nr-dlschsim/templates/service.yaml new file mode 100644 index 0000000000..0dd065c9e0 --- /dev/null +++ b/charts/physims/charts/nr-dlschsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-dlschsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-nr-dlschsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-nr-dlschsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/nr-dlschsim/values.yaml b/charts/physims/charts/nr-dlschsim/values.yaml new file mode 100644 index 0000000000..e96541102c --- /dev/null +++ b/charts/physims/charts/nr-dlschsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-nr-dlschsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-nr-dlschsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/nr-dlsim/Chart.yaml b/charts/physims/charts/nr-dlsim/Chart.yaml new file mode 100644 index 0000000000..2ec4b7eabd --- /dev/null +++ b/charts/physims/charts/nr-dlsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-nr-dlsim +description: A Helm subchart for nr-dlsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - nr-dlsim + - RAN + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/nr-dlsim/templates/NOTES.txt b/charts/physims/charts/nr-dlsim/templates/NOTES.txt new file mode 100644 index 0000000000..79027454cf --- /dev/null +++ b/charts/physims/charts/nr-dlsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-nr-dlsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-nr-dlsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-nr-dlsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-nr-dlsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/nr-dlsim/templates/_helpers.tpl b/charts/physims/charts/nr-dlsim/templates/_helpers.tpl new file mode 100644 index 0000000000..1dd7fbd3fd --- /dev/null +++ b/charts/physims/charts/nr-dlsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-nr-dlsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-nr-dlsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-nr-dlsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-nr-dlsim.labels" -}} +helm.sh/chart: {{ include "oai-nr-dlsim.chart" . }} +{{ include "oai-nr-dlsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-nr-dlsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-nr-dlsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-nr-dlsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-nr-dlsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/nr-dlsim/templates/deployment.yaml b/charts/physims/charts/nr-dlsim/templates/deployment.yaml new file mode 100644 index 0000000000..4c38664e61 --- /dev/null +++ b/charts/physims/charts/nr-dlsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-dlsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-nr-dlsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-nr-dlsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-nr-dlsim + # volumeMounts: + # - mountPath: /opt/oai-nr-dlsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015105" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/nr-dlsim/templates/service.yaml b/charts/physims/charts/nr-dlsim/templates/service.yaml new file mode 100644 index 0000000000..c58433f3b2 --- /dev/null +++ b/charts/physims/charts/nr-dlsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-dlsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-nr-dlsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-nr-dlsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/nr-dlsim/values.yaml b/charts/physims/charts/nr-dlsim/values.yaml new file mode 100644 index 0000000000..c86fc96cff --- /dev/null +++ b/charts/physims/charts/nr-dlsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-nr-dlsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-nr-dlsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/nr-pbchsim/Chart.yaml b/charts/physims/charts/nr-pbchsim/Chart.yaml new file mode 100644 index 0000000000..6d8359598d --- /dev/null +++ b/charts/physims/charts/nr-pbchsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-nr-pbchsim +description: A Helm subchart for nr-pbchsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - nr-pbchsim + - RAN + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/nr-pbchsim/templates/NOTES.txt b/charts/physims/charts/nr-pbchsim/templates/NOTES.txt new file mode 100644 index 0000000000..cee233d4f3 --- /dev/null +++ b/charts/physims/charts/nr-pbchsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-nr-pbchsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-nr-pbchsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-nr-pbchsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-nr-pbchsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/nr-pbchsim/templates/_helpers.tpl b/charts/physims/charts/nr-pbchsim/templates/_helpers.tpl new file mode 100644 index 0000000000..0e31033343 --- /dev/null +++ b/charts/physims/charts/nr-pbchsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-nr-pbchsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-nr-pbchsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-nr-pbchsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-nr-pbchsim.labels" -}} +helm.sh/chart: {{ include "oai-nr-pbchsim.chart" . }} +{{ include "oai-nr-pbchsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-nr-pbchsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-nr-pbchsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-nr-pbchsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-nr-pbchsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/nr-pbchsim/templates/deployment.yaml b/charts/physims/charts/nr-pbchsim/templates/deployment.yaml new file mode 100644 index 0000000000..551785abc0 --- /dev/null +++ b/charts/physims/charts/nr-pbchsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-pbchsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-nr-pbchsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-nr-pbchsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-nr-pbchsim + # volumeMounts: + # - mountPath: /opt/oai-nr-pbchsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015104" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/nr-pbchsim/templates/service.yaml b/charts/physims/charts/nr-pbchsim/templates/service.yaml new file mode 100644 index 0000000000..35faf3c33d --- /dev/null +++ b/charts/physims/charts/nr-pbchsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-pbchsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-nr-pbchsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-nr-pbchsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/nr-pbchsim/values.yaml b/charts/physims/charts/nr-pbchsim/values.yaml new file mode 100644 index 0000000000..62d89f9632 --- /dev/null +++ b/charts/physims/charts/nr-pbchsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-nr-pbchsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-nr-pbchsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/nr-prachsim/Chart.yaml b/charts/physims/charts/nr-prachsim/Chart.yaml new file mode 100644 index 0000000000..8c88587a7f --- /dev/null +++ b/charts/physims/charts/nr-prachsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-nr-prachsim +description: A Helm subchart for nr-prachsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - nr-prachsim + - RAN + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/nr-prachsim/templates/NOTES.txt b/charts/physims/charts/nr-prachsim/templates/NOTES.txt new file mode 100644 index 0000000000..376694e7e4 --- /dev/null +++ b/charts/physims/charts/nr-prachsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-nr-prachsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-nr-prachsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-nr-prachsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-nr-prachsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/nr-prachsim/templates/_helpers.tpl b/charts/physims/charts/nr-prachsim/templates/_helpers.tpl new file mode 100644 index 0000000000..6362c72b2a --- /dev/null +++ b/charts/physims/charts/nr-prachsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-nr-prachsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-nr-prachsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-nr-prachsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-nr-prachsim.labels" -}} +helm.sh/chart: {{ include "oai-nr-prachsim.chart" . }} +{{ include "oai-nr-prachsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-nr-prachsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-nr-prachsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-nr-prachsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-nr-prachsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/nr-prachsim/templates/deployment.yaml b/charts/physims/charts/nr-prachsim/templates/deployment.yaml new file mode 100644 index 0000000000..52bc030c45 --- /dev/null +++ b/charts/physims/charts/nr-prachsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-prachsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-nr-prachsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-nr-prachsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-nr-prachsim + # volumeMounts: + # - mountPath: /opt/oai-nr-prachsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015112" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/nr-prachsim/templates/service.yaml b/charts/physims/charts/nr-prachsim/templates/service.yaml new file mode 100644 index 0000000000..71bfe7b9fe --- /dev/null +++ b/charts/physims/charts/nr-prachsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-prachsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-nr-prachsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-nr-prachsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/nr-prachsim/values.yaml b/charts/physims/charts/nr-prachsim/values.yaml new file mode 100644 index 0000000000..3ea9787f7a --- /dev/null +++ b/charts/physims/charts/nr-prachsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-nr-prachsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-nr-prachsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/nr-pucchsim/Chart.yaml b/charts/physims/charts/nr-pucchsim/Chart.yaml new file mode 100644 index 0000000000..bb0033175f --- /dev/null +++ b/charts/physims/charts/nr-pucchsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-nr-pucchsim +description: A Helm subchart for nr-pucchsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - nr-pucchsim + - RAN + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/nr-pucchsim/templates/NOTES.txt b/charts/physims/charts/nr-pucchsim/templates/NOTES.txt new file mode 100644 index 0000000000..7c2cfa9155 --- /dev/null +++ b/charts/physims/charts/nr-pucchsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-nr-pucchsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-nr-pucchsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-nr-pucchsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-nr-pucchsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/nr-pucchsim/templates/_helpers.tpl b/charts/physims/charts/nr-pucchsim/templates/_helpers.tpl new file mode 100644 index 0000000000..210ba26db2 --- /dev/null +++ b/charts/physims/charts/nr-pucchsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-nr-pucchsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-nr-pucchsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-nr-pucchsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-nr-pucchsim.labels" -}} +helm.sh/chart: {{ include "oai-nr-pucchsim.chart" . }} +{{ include "oai-nr-pucchsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-nr-pucchsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-nr-pucchsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-nr-pucchsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-nr-pucchsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/nr-pucchsim/templates/deployment.yaml b/charts/physims/charts/nr-pucchsim/templates/deployment.yaml new file mode 100644 index 0000000000..d783991e0b --- /dev/null +++ b/charts/physims/charts/nr-pucchsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-pucchsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-nr-pucchsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-nr-pucchsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-nr-pucchsim + # volumeMounts: + # - mountPath: /opt/oai-nr-pucchsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015109" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/nr-pucchsim/templates/service.yaml b/charts/physims/charts/nr-pucchsim/templates/service.yaml new file mode 100644 index 0000000000..9e8760e76b --- /dev/null +++ b/charts/physims/charts/nr-pucchsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-pucchsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-nr-pucchsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-nr-pucchsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/nr-pucchsim/values.yaml b/charts/physims/charts/nr-pucchsim/values.yaml new file mode 100644 index 0000000000..cf50c0bd3c --- /dev/null +++ b/charts/physims/charts/nr-pucchsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-nr-pucchsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-nr-pucchsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/nr-ulschsim/Chart.yaml b/charts/physims/charts/nr-ulschsim/Chart.yaml new file mode 100644 index 0000000000..e2525f0032 --- /dev/null +++ b/charts/physims/charts/nr-ulschsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-nr-ulschsim +description: A Helm subchart for nr-ulschsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - nr-ulschsim + - RAN + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/nr-ulschsim/templates/NOTES.txt b/charts/physims/charts/nr-ulschsim/templates/NOTES.txt new file mode 100644 index 0000000000..65566932cd --- /dev/null +++ b/charts/physims/charts/nr-ulschsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-nr-ulschsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-nr-ulschsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-nr-ulschsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-nr-ulschsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/nr-ulschsim/templates/_helpers.tpl b/charts/physims/charts/nr-ulschsim/templates/_helpers.tpl new file mode 100644 index 0000000000..9aa13a81f0 --- /dev/null +++ b/charts/physims/charts/nr-ulschsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-nr-ulschsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-nr-ulschsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-nr-ulschsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-nr-ulschsim.labels" -}} +helm.sh/chart: {{ include "oai-nr-ulschsim.chart" . }} +{{ include "oai-nr-ulschsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-nr-ulschsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-nr-ulschsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-nr-ulschsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-nr-ulschsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/nr-ulschsim/templates/deployment.yaml b/charts/physims/charts/nr-ulschsim/templates/deployment.yaml new file mode 100644 index 0000000000..56fb0de5b8 --- /dev/null +++ b/charts/physims/charts/nr-ulschsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-ulschsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-nr-ulschsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-nr-ulschsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-nr-ulschsim + # volumeMounts: + # - mountPath: /opt/oai-nr-ulschsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015108" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/nr-ulschsim/templates/service.yaml b/charts/physims/charts/nr-ulschsim/templates/service.yaml new file mode 100644 index 0000000000..d34882700e --- /dev/null +++ b/charts/physims/charts/nr-ulschsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-ulschsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-nr-ulschsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-nr-ulschsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/nr-ulschsim/values.yaml b/charts/physims/charts/nr-ulschsim/values.yaml new file mode 100644 index 0000000000..420b154596 --- /dev/null +++ b/charts/physims/charts/nr-ulschsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-nr-ulschsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-nr-ulschsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/nr-ulsim/Chart.yaml b/charts/physims/charts/nr-ulsim/Chart.yaml new file mode 100644 index 0000000000..ede87ea7e4 --- /dev/null +++ b/charts/physims/charts/nr-ulsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-nr-ulsim +description: A Helm subchart for nr-ulsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - nr-ulsim + - RAN + - 5G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/nr-ulsim/templates/NOTES.txt b/charts/physims/charts/nr-ulsim/templates/NOTES.txt new file mode 100644 index 0000000000..6865eeaedf --- /dev/null +++ b/charts/physims/charts/nr-ulsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-nr-ulsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-nr-ulsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-nr-ulsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-nr-ulsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/nr-ulsim/templates/_helpers.tpl b/charts/physims/charts/nr-ulsim/templates/_helpers.tpl new file mode 100644 index 0000000000..90f0bd0e36 --- /dev/null +++ b/charts/physims/charts/nr-ulsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-nr-ulsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-nr-ulsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-nr-ulsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-nr-ulsim.labels" -}} +helm.sh/chart: {{ include "oai-nr-ulsim.chart" . }} +{{ include "oai-nr-ulsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-nr-ulsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-nr-ulsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-nr-ulsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-nr-ulsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/nr-ulsim/templates/deployment.yaml b/charts/physims/charts/nr-ulsim/templates/deployment.yaml new file mode 100644 index 0000000000..c0fa5ceb3b --- /dev/null +++ b/charts/physims/charts/nr-ulsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-ulsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-nr-ulsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-nr-ulsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-nr-ulsim + # volumeMounts: + # - mountPath: /opt/oai-nr-ulsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015111" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/nr-ulsim/templates/service.yaml b/charts/physims/charts/nr-ulsim/templates/service.yaml new file mode 100644 index 0000000000..95f198d1b1 --- /dev/null +++ b/charts/physims/charts/nr-ulsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-nr-ulsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-nr-ulsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-nr-ulsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/nr-ulsim/values.yaml b/charts/physims/charts/nr-ulsim/values.yaml new file mode 100644 index 0000000000..7eb8e33fcb --- /dev/null +++ b/charts/physims/charts/nr-ulsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-nr-ulsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-nr-ulsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/polartest/Chart.yaml b/charts/physims/charts/polartest/Chart.yaml new file mode 100644 index 0000000000..ae5f5ca263 --- /dev/null +++ b/charts/physims/charts/polartest/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-polartest +description: A Helm subchart for polartest network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - polartest + - RAN + - 4G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/polartest/templates/NOTES.txt b/charts/physims/charts/polartest/templates/NOTES.txt new file mode 100644 index 0000000000..9c2c978de0 --- /dev/null +++ b/charts/physims/charts/polartest/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-polartest.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-polartest.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-polartest.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-polartest.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/polartest/templates/_helpers.tpl b/charts/physims/charts/polartest/templates/_helpers.tpl new file mode 100644 index 0000000000..ce81dbe525 --- /dev/null +++ b/charts/physims/charts/polartest/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-polartest.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-polartest.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-polartest.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-polartest.labels" -}} +helm.sh/chart: {{ include "oai-polartest.chart" . }} +{{ include "oai-polartest.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-polartest.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-polartest.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-polartest.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-polartest.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/polartest/templates/deployment.yaml b/charts/physims/charts/polartest/templates/deployment.yaml new file mode 100644 index 0000000000..01a6efc815 --- /dev/null +++ b/charts/physims/charts/polartest/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-polartest.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-polartest.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-polartest.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-polartest + # volumeMounts: + # - mountPath: /opt/oai-polartest/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015103" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/polartest/templates/service.yaml b/charts/physims/charts/polartest/templates/service.yaml new file mode 100644 index 0000000000..40abb6769e --- /dev/null +++ b/charts/physims/charts/polartest/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-polartest.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-polartest + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-polartest.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/polartest/values.yaml b/charts/physims/charts/polartest/values.yaml new file mode 100644 index 0000000000..496dc8afba --- /dev/null +++ b/charts/physims/charts/polartest/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-polartest. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-polartest-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/smallblocktest/Chart.yaml b/charts/physims/charts/smallblocktest/Chart.yaml new file mode 100644 index 0000000000..74092783ae --- /dev/null +++ b/charts/physims/charts/smallblocktest/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-smallblocktest +description: A Helm subchart for smallblocktest network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - smallblocktest + - RAN + - 4G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/smallblocktest/templates/NOTES.txt b/charts/physims/charts/smallblocktest/templates/NOTES.txt new file mode 100644 index 0000000000..c593dbfe22 --- /dev/null +++ b/charts/physims/charts/smallblocktest/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-smallblocktest.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-smallblocktest.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-smallblocktest.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-smallblocktest.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/smallblocktest/templates/_helpers.tpl b/charts/physims/charts/smallblocktest/templates/_helpers.tpl new file mode 100644 index 0000000000..a3c264b33e --- /dev/null +++ b/charts/physims/charts/smallblocktest/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-smallblocktest.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-smallblocktest.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-smallblocktest.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-smallblocktest.labels" -}} +helm.sh/chart: {{ include "oai-smallblocktest.chart" . }} +{{ include "oai-smallblocktest.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-smallblocktest.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-smallblocktest.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-smallblocktest.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-smallblocktest.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/smallblocktest/templates/deployment.yaml b/charts/physims/charts/smallblocktest/templates/deployment.yaml new file mode 100644 index 0000000000..3439c2597e --- /dev/null +++ b/charts/physims/charts/smallblocktest/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-smallblocktest.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-smallblocktest.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-smallblocktest.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-smallblock + # volumeMounts: + # - mountPath: /opt/oai-smallblocktest/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015107" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/smallblocktest/templates/service.yaml b/charts/physims/charts/smallblocktest/templates/service.yaml new file mode 100644 index 0000000000..d51bf21ce4 --- /dev/null +++ b/charts/physims/charts/smallblocktest/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-smallblocktest.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-smallblocktest + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-smallblocktest.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/smallblocktest/values.yaml b/charts/physims/charts/smallblocktest/values.yaml new file mode 100644 index 0000000000..9dd791265f --- /dev/null +++ b/charts/physims/charts/smallblocktest/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-smallblocktest. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-smallblocktest-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/charts/ulsim/Chart.yaml b/charts/physims/charts/ulsim/Chart.yaml new file mode 100644 index 0000000000..2311d729b4 --- /dev/null +++ b/charts/physims/charts/ulsim/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +name: oai-ulsim +description: A Helm subchart for ulsim network function + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +icon: http://www.openairinterface.org/wp-content/uploads/2015/06/cropped-oai_final_logo.png + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 0.1.1 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: v1 + +keywords: + - Physical Simulator + - ulsim + - RAN + - 4G + +sources: + - https://gitlab.eurecom.fr/oai/openairinterface5g + +maintainers: + - name: OPENAIRINTERFACE + email: contact@openairinterface.org diff --git a/charts/physims/charts/ulsim/templates/NOTES.txt b/charts/physims/charts/ulsim/templates/NOTES.txt new file mode 100644 index 0000000000..91ab3ce0b7 --- /dev/null +++ b/charts/physims/charts/ulsim/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "oai-ulsim.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "oai-ulsim.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "oai-ulsim.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "oai-ulsim.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/physims/charts/ulsim/templates/_helpers.tpl b/charts/physims/charts/ulsim/templates/_helpers.tpl new file mode 100644 index 0000000000..67b6500479 --- /dev/null +++ b/charts/physims/charts/ulsim/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "oai-ulsim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "oai-ulsim.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "oai-ulsim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "oai-ulsim.labels" -}} +helm.sh/chart: {{ include "oai-ulsim.chart" . }} +{{ include "oai-ulsim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "oai-ulsim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "oai-ulsim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "oai-ulsim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "oai-ulsim.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/physims/charts/ulsim/templates/deployment.yaml b/charts/physims/charts/ulsim/templates/deployment.yaml new file mode 100644 index 0000000000..e8c90dabc1 --- /dev/null +++ b/charts/physims/charts/ulsim/templates/deployment.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-ulsim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "oai-ulsim.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "oai-ulsim.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: physim + image: "{{ .Values.global.image.repository }}:{{ .Values.global.image.version }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + ports: + - containerPort: 80 + name: oai-ulsim + # volumeMounts: + # - mountPath: /opt/oai-ulsim/certs + # name: certs + command: ["/bin/sh", "-c"] + args: + - > + export OPENAIR_DIR=/opt/oai-physim && + cd cmake_targets/autotests && + ./run_exec_autotests.bash -g "015101" -q -np -b && + echo "FINISHED" && + sleep infinity + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: {{ .Values.global.serviceAccountName }} + terminationGracePeriodSeconds: 30 diff --git a/charts/physims/charts/ulsim/templates/service.yaml b/charts/physims/charts/ulsim/templates/service.yaml new file mode 100644 index 0000000000..dcc37d6299 --- /dev/null +++ b/charts/physims/charts/ulsim/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "oai-ulsim.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if contains "ClusterIP" .Values.service.type }} + clusterIP: None +{{- end }} + ports: + - name: oai-ulsim + # Port accessible outside cluster + port: {{ .Values.service.port }} + # Port to forward to inside the pod + targetPort: {{ .Values.service.Port }} + protocol: TCP + selector: + {{- include "oai-ulsim.selectorLabels" . | nindent 4 }} diff --git a/charts/physims/charts/ulsim/values.yaml b/charts/physims/charts/ulsim/values.yaml new file mode 100644 index 0000000000..f5110989d8 --- /dev/null +++ b/charts/physims/charts/ulsim/values.yaml @@ -0,0 +1,63 @@ +# Default values for oai-ulsim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +namespace: "oaicicd-ran-tmp" + +image: + registry: local + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: temp + # pullPolicy: IfNotPresent or Never or Always + pullPolicy: Always + +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "oai-ulsim-sa" + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/physims/templates/rbac.yaml b/charts/physims/templates/rbac.yaml new file mode 100644 index 0000000000..35f956a203 --- /dev/null +++ b/charts/physims/templates/rbac.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: {{ .Chart.Name }}-{{ .Values.global.namespace }}-rbac +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: {{ .Values.global.serviceAccountName }} + namespace: {{ .Values.global.namespace }} diff --git a/charts/physims/templates/serviceaccount.yaml b/charts/physims/templates/serviceaccount.yaml new file mode 100644 index 0000000000..21d094ad38 --- /dev/null +++ b/charts/physims/templates/serviceaccount.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.global.serviceAccountName }} diff --git a/charts/physims/values.yaml b/charts/physims/values.yaml new file mode 100644 index 0000000000..b348e822bb --- /dev/null +++ b/charts/physims/values.yaml @@ -0,0 +1,84 @@ +# Default values for oai-physim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + serviceAccountName: oai-physim-sa + namespace: "oaicicd-ran-tmp" + image: + repository: image-registry.openshift-image-registry.svc:5000/oaicicd-ran-tmp/oai-physim + version: TAG + +## Declaring values specific to coressponding physim to overwrite + +dlsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +ulsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +ldpctest: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +polartest: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +nr-pbchsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +nr-dlsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +nr-dlschsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +smallblocktest: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +nr-ulschsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +nr-pucchsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +nr-ulsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 + +nr-prachsim: + replicaCount: 1 + service: + type: ClusterIP + port: 80 diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container new file mode 100644 index 0000000000..654ad23230 --- /dev/null +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -0,0 +1,377 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Location of the executor node +def nodeExecutor = params.nodeExecutor + +// Tags to shorten pipeline duration +def doMandatoryTests = false +def doFullTestsuite = false + +// +def gitCommitAuthorEmailAddr + +pipeline { + agent { + label nodeExecutor + } + options { + disableConcurrentBuilds() + timestamps() + gitLabConnection('OAI GitLab') + ansiColor('xterm') + } + + stages { + stage ("Verify Parameters") { + steps { + script { + JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"' + JOB_TIMESTAMP = JOB_TIMESTAMP.trim() + + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + echo '\u2705 \u001B[32mVerify Labels\u001B[0m' + if ("MERGE".equals(env.gitlabActionType)) { + LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid + LABEL_CHECK = LABEL_CHECK.trim() + if (LABEL_CHECK == 'NONE') { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request has none of the mandatory labels:\n\n" + message += " - BUILD-ONLY\n" + message += " - 4G-LTE\n" + message += " - 5G-NR\n" + message += " - CI\n\n" + message += "Not performing CI due to lack of labels" + addGitLabMRComment comment: message + error('Not performing CI due to lack of labels') + } else if (LABEL_CHECK == 'FULL') { + doMandatoryTests = true + doFullTestsuite = true + } else if (LABEL_CHECK == 'SHORTEN-5G') { + doMandatoryTests = true + } else { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): We will perform only build stages on your Merge Request" + addGitLabMRComment comment: message + } + } else { + doMandatoryTests = true + doFullTestsuite = true + } + } + } + } + stage ("Verify Guidelines") { + steps { + echo "Git URL is ${GIT_URL}" + echo "GitLab Act is ${env.gitlabActionType}" + script { + if ("MERGE".equals(env.gitlabActionType)) { + // since a bit, in push events, gitlabUserEmail is not populated + gitCommitAuthorEmailAddr = env.gitlabUserEmail + echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}" + // GitLab-Jenkins plugin integration is lacking to perform the merge by itself + // Doing it manually --> it may have merge conflicts + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" + } else { + echo "Git Branch is ${GIT_BRANCH}" + echo "Git Commit is ${GIT_COMMIT}" + // since a bit, in push events, gitlabUserEmail is not populated + gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}' + gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim() + echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}" + sh "git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG" + } + } + } + post { + failure { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI" + addGitLabMRComment comment: message + currentBuild.result = 'FAILURE' + } + } + } + } + // Build Stages are Mandatory + // Later we will add a Ubuntu20 build + stage ("Image Building Processes") { + parallel { + stage ("Ubuntu18 Build") { + steps { + script { + triggerSlaveJob ('RAN-Ubuntu18-Image-Builder', 'Ubuntu18-Images-Build') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-Ubuntu18-Image-Builder') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + stage ("RHEL8 Build") { + steps { + script { + triggerSlaveJob ('RAN-RHEL8-Image-Builder', 'RHEL8-Images-Build') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-RHEL8-Image-Builder') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + stage ("CppCheck Analysis") { + steps { + script { + triggerSlaveJob ('RAN-cppcheck', 'CppCheck Analysis') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-cppcheck') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + } + } + stage ("Image Test Processes") { + parallel { + stage ("Physical Simulators") { + when { expression {doMandatoryTests} } + steps { + script { + triggerSlaveJob ('RAN-PhySim-Cluster', 'Test-Physim-Cluster') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-PhySim-Cluster') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + stage ("RF Simulators") { + when { expression {doMandatoryTests} } + steps { + script { + triggerSlaveJob ('RAN-RF-Sim-Test', 'Test-RF-Sim-Container') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-RF-Sim-Test') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + stage ("NSA B200 Sanity Check") { + when { expression {doMandatoryTests} } + steps { + script { + triggerSlaveJob ('RAN-NSA-B200-Module-LTEBOX-Container', 'Test-NSA-B200') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-NSA-B200-Module-LTEBOX-Container') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + } + } + stage ("Images Push to Registries") { + when { expression {"PUSH".equals(env.gitlabActionType)} } + steps { + script { + triggerSlaveJob ('RAN-DockerHub-Push', 'Push-to-Docker-Hub') + } + } + post { + failure { + script { + echo "Push to Docker-Hub KO" + currentBuild.result = 'FAILURE' + } + } + } + } + } + post { + always { + script { + def eSubject = JOB_NAME + ' - Build # ' + BUILD_ID + ' - ' + currentBuild.result + '!' + def eBody = "Hi,\n\n" + eBody += "Here are attached HTML report files for " + JOB_NAME + " - Build # " + BUILD_ID + " - " + currentBuild.result + "!\n\n" + eBody += "Regards,\n" + eBody += "OAI CI Team" + emailext attachmentsPattern: '*results*.html', + body: eBody, + replyTo: 'no-reply@openairinterface.org', + subject: eSubject, + to: gitCommitAuthorEmailAddr + + if (fileExists('.git/CI_COMMIT_MSG')) { + sh "rm -f .git/CI_COMMIT_MSG" + } + } + } + success { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + } + echo "Pipeline is SUCCESSFUL" + } + } + failure { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + } + echo "Pipeline FAILED" + } + } + } +} + +// ---- Slave Job functions + +def triggerSlaveJob (jobName, gitlabStatusName) { + if ("MERGE".equals(env.gitlabActionType)) { + MR_NUMBER = env.gitlabMergeRequestIid + } else { + MR_NUMBER = 'develop' + } + // Workaround for the "cancelled" GitLab pipeline notification + // The slave job is triggered with the propagate false so the following commands are executed + // Its status is now PASS/SUCCESS from a stage pipeline point of view + // localStatus variable MUST be analyzed to properly assess the status + localStatus = build job: jobName, + parameters: [ + string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)), + string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)), + string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)), + string(name: 'eNB_MR', value: String.valueOf(MR_NUMBER)), + booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)), + string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch)) + ], propagate: false + localResult = localStatus.getResult() + echo "${jobName} Slave Job status is ${localResult}" + gitlabCommitStatus(name: gitlabStatusName) { + if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) { + echo "${jobName} Slave Job is OK" + } else { + echo "${jobName} Slave Job is KO" + sh "ci-scripts/fail.sh" + } + } +} + +def triggerSlaveJobNoGitLab (jobName) { + if ("MERGE".equals(env.gitlabActionType)) { + MR_NUMBER = env.gitlabMergeRequestIid + } else { + MR_NUMBER = 'develop' + } + // Workaround for the "cancelled" GitLab pipeline notification + // The slave job is triggered with the propagate false so the following commands are executed + // Its status is now PASS/SUCCESS from a stage pipeline point of view + // localStatus variable MUST be analyzed to properly assess the status + localStatus = build job: jobName, + parameters: [ + string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)), + string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)), + string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)), + string(name: 'eNB_MR', value: String.valueOf(MR_NUMBER)), + booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)), + string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch)) + ], propagate: false + localResult = localStatus.getResult() + echo "${jobName} Slave Job status is ${localResult}" + if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) { + echo "${jobName} Slave Job is OK" + } else { + echo "${jobName} Slave Job is KO" + sh "ci-scripts/fail.sh" + } +} + +def finalizeSlaveJob(jobName) { + // In case of any non-success, we are retrieving the HTML report of the last completed + // slave job. The only drop-back is that we may retrieve the HTML report of a previous build + fileName = "test_results-${jobName}.html" + if (!fileExists(fileName)) { + copyArtifacts(projectName: jobName, + filter: 'test_results*.html', + selector: lastCompleted()) + if (fileExists(fileName)) { + sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' ${fileName}" + archiveArtifacts artifacts: fileName + } + } +} diff --git a/ci-scripts/Jenkinsfile-git-dashboard b/ci-scripts/Jenkinsfile-git-dashboard new file mode 100644 index 0000000000..87e781fe8a --- /dev/null +++ b/ci-scripts/Jenkinsfile-git-dashboard @@ -0,0 +1,48 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + + +pipeline { + agent { + label pythonExecutor + } + stages { + stage ("gDashboard") { + steps { + script { + dir ("ci-scripts/ran_dashboard") { + //retrieve MR data from gitlab / mySQL db, build HTML pages and load them to AWS S3 bucket (configured as static web page hosting) + //deprecated method : sh returnStdout: true, script: 'python3 ran_dashboard.py' + sh returnStdout: true, script: 'python3 Hdashboard.py' + } + } + } + } + } +} + + diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index c3b997a4e8..a0284edb71 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -30,12 +30,16 @@ def sendSocialMediaMessage(pipeChannel, pipeColor, pipeMessage) { } } -def doRedHatBuild = false -def doFlexranCtrlTest = false - // Location of the executor node def nodeExecutor = params.nodeExecutor +// VM Lockable resources +def vmResource = params.vmLockableResource + +// Tags to shorten pipeline duration +def doMandatoryTests = false +def doFullTestsuite = false + pipeline { agent { label nodeExecutor @@ -44,31 +48,6 @@ pipeline { disableConcurrentBuilds() timestamps() gitLabConnection('OAI GitLab') - gitlabBuilds(builds: [ - "Build gNB-USRP", - "Build nr-UE-USRP", - "Build eNB-USRP", - "Build basic-sim", - "Build phy-sim", - "Build eNB-ethernet", - "Build UE-ethernet", - "Analysis with cppcheck", - "Test phy-sim", - "Test basic-sim", - "Test L1-sim", - "Test RF-sim", - "Test L2-sim", - "Test-Mono-FDD-Band7", - "Test-Mono-TDD-Band40", - "Test-IF4p5-FDD-Band7", - "Test-IF4p5-TDD-Band40", - "Test-Mono-FDD-Band13-LTE-M", - "Test-IF4p5-TDD-Band38-Multi-RRU", - "Test-eNB-OAI-UE-FDD-Band7", - "Test-Mono-FDD-Band13-X2-HO", - "Test-TDD-Band78-gNB-NR-UE", - "Test-OCP-FDD-Band7" - ]) ansiColor('xterm') } @@ -85,27 +64,36 @@ pipeline { echo "Platform is ${env.TESTPLATFORM_OWNER}" } - if (params.RedHatRemoteServer == null) { - allParametersPresent = false - } - if (params.RedHatRemoteCredentials == null) { - allParametersPresent = false - } - if (params.RedHatWorkingPath == null) { - allParametersPresent = false - } - if (allParametersPresent) { - echo "Performing Red Hat Build" - doRedHatBuild = true - } else { - doRedHatBuild = false - } - if (params.FlexRanRtcGitLabRepository_Credentials != null) { - doFlexranCtrlTest = true - } if (fileExists("flexran")) { sh "rm -Rf flexran > /dev/null 2>&1" } + + echo '\u2705 \u001B[32mVerify Labels\u001B[0m' + if ("MERGE".equals(env.gitlabActionType)) { + LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid + LABEL_CHECK = LABEL_CHECK.trim() + if (LABEL_CHECK == 'NONE') { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request has none of the mandatory labels:\n\n" + message += " - BUILD-ONLY\n" + message += " - 4G-LTE\n" + message += " - 5G-NR\n" + message += " - CI\n\n" + message += "Not performing CI due to lack of labels" + addGitLabMRComment comment: message + error('Not performing CI due to lack of labels') + } else if (LABEL_CHECK == 'FULL') { + doMandatoryTests = true + doFullTestsuite = true + } else if (LABEL_CHECK == 'SHORTEN-5G') { + doMandatoryTests = true + } else { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): We will perform only build stages on your Merge Request" + addGitLabMRComment comment: message + } + } else { + doMandatoryTests = true + doFullTestsuite = true + } } } } @@ -148,15 +136,13 @@ pipeline { // For the moment, there is no fail criteria. Just a notification of number of files that do not follow sh "./ci-scripts/checkCodingFormattingRules.sh" } - if (doFlexranCtrlTest) { + // With Mosaic 5G being part of OSA and making all it's repositories public + // No need to pass credentials to clone flexran-rtc + if (doMandatoryTests) { sh "mkdir flexran" dir ('flexran') { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.FlexRanRtcGitLabRepository_Credentials}", usernameVariable: 'git_username', passwordVariable: 'git_password'] - ]) { - sh "git clone https://${git_username}:${git_password}@gitlab.eurecom.fr/flexran/flexran-rtc.git . > ../git_clone.log 2>&1" - sh "git checkout develop >> ../git_clone.log 2>&1" - } + sh "git clone https://gitlab.eurecom.fr/flexran/flexran-rtc.git . > ../git_clone.log 2>&1" + sh "git checkout develop >> ../git_clone.log 2>&1" sh "zip -r -qq flexran.zip ." } } @@ -175,83 +161,60 @@ pipeline { stage ("Start VM -- basic-sim") { steps { + lock (vmResource) { timeout (time: 5, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant basic-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" } + } } } stage ("Start VM -- gnb-usrp") { steps { + lock (vmResource) { timeout (time: 5, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" } + } } } stage ("Start VM -- nr-ue-usrp") { steps { + lock (vmResource) { timeout (time: 5, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" } + } } } - stage ("Start VM -- enb-usrp") { - steps { - timeout (time: 5, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" - } - } - } - - stage ("Start VM -- phy-sim") { - steps { - timeout (time: 5, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" - } - } - } - stage ("Start VM -- enb-ethernet") { steps { - timeout (time: 5, unit: 'MINUTES') { + lock (vmResource) { + timeout (time: 7, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" } + } } } stage ("Start VM -- ue-ethernet") { steps { - timeout (time: 5, unit: 'MINUTES') { + lock (vmResource) { + timeout (time: 7, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" } + } } - } + } - stage ("Start VM -- cppcheck") { - steps { - timeout (time: 5, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" - } - } - } - stage ("Variant Builds") { parallel { - stage ("Analysis with cppcheck") { - steps { - gitlabCommitStatus(name: "Analysis with cppcheck") { - timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID}" - } - } - } - } stage ("Build basic simulator") { steps { gitlabCommitStatus(name: "Build basic-sim") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 45, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant basic-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -260,7 +223,7 @@ pipeline { stage ("Build 5G gNB-USRP") { steps { gitlabCommitStatus(name: "Build gNB-USRP") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 45, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -269,34 +232,16 @@ pipeline { stage ("Build 5G NR-UE-USRP") { steps { gitlabCommitStatus(name: "Build nr-UE-USRP") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 45, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } } } - stage ("Build eNB-USRP") { - steps { - gitlabCommitStatus(name: "Build eNB-USRP") { - timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" - } - } - } - } - stage ("Build physical simulators") { - steps { - gitlabCommitStatus(name: "Build phy-sim") { - timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" - } - } - } - } stage ("Build eNB-ethernet") { steps { gitlabCommitStatus(name: "Build eNB-ethernet") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 45, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -304,33 +249,14 @@ pipeline { } stage ("Build UE-ethernet") { steps { + // This is typically the last one to finish. + lock (vmResource) { gitlabCommitStatus(name: "Build UE-ethernet") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 45, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } - } - } - stage ("Build eNB-USRP on Red Hat") { - when { - expression {doRedHatBuild} - } - steps { - gitlabCommitStatus(name: "Build eNB-USRP-RHE") { - script { - try { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.RedHatRemoteCredentials}", usernameVariable: 'RH_Username', passwordVariable: 'RH_Password'] - ]) { - timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/buildOnRH.sh --workspace $WORKSPACE --job-name ${JOB_NAME} --build-id ${BUILD_ID} --remote-host ${params.RedHatRemoteServer} --remote-path ${params.RedHatWorkingPath} --remote-user-name ${RH_Username} --remote-password ${RH_Password}" - } - } - } catch (Exception e) { - echo "Red Hat build failed but we could keep running pipeline if all ubuntu-based build passed" - } - } - } + } } } } @@ -344,9 +270,9 @@ pipeline { script { dir ('archives') { if (fileExists('red_hat')) { - sh "zip -r -qq vm_build_logs.zip basic_sim enb_usrp phy_sim cppcheck enb_eth ue_eth gnb_usrp nr_ue_usrp red_hat" + sh "zip -r -qq vm_build_logs.zip basic_sim enb_eth ue_eth gnb_usrp nr_ue_usrp red_hat" } else { - sh "zip -r -qq vm_build_logs.zip basic_sim enb_usrp phy_sim cppcheck enb_eth ue_eth gnb_usrp nr_ue_usrp" + sh "zip -r -qq vm_build_logs.zip basic_sim enb_eth ue_eth gnb_usrp nr_ue_usrp" } } if(fileExists('archives/vm_build_logs.zip')) { @@ -354,16 +280,6 @@ pipeline { } if ("MERGE".equals(env.gitlabActionType)) { sh "./ci-scripts/oai-ci-vm-tool report-build --workspace $WORKSPACE --git-url ${GIT_URL} --job-name ${JOB_NAME} --build-id ${BUILD_ID} --trigger merge-request --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" - // If the merge request has introduced more CPPCHECK errors or warnings, notifications in GitLab - if (fileExists('oai_cppcheck_added_errors.txt')) { - def ret=readFile('./oai_cppcheck_added_errors.txt').trim(); - if ("0".equals(ret)) { - echo "No added cppcheck warnings/errors in this merge request" - } else { - def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Some modified files in Merge Request MAY have INTRODUCED up to " + ret + " CPPCHECK errors/warnings" - addGitLabMRComment comment: message - } - } // If the merge request has introduced compilation warnings, notifications in GitLab sh "./ci-scripts/checkAddedWarnings.sh --src-branch ${env.gitlabSourceBranch} --target-branch ${env.gitlabTargetBranch}" def res=readFile('./oai_warning_files.txt').trim(); @@ -390,26 +306,12 @@ pipeline { parallel { stage ("VM-based tests") { stages { - stage ("Test physical simulators") { - steps { - script { - timeout (time: 90, unit: 'MINUTES') { - try { - gitlabCommitStatus(name: "Test phy-sim") { - sh "./ci-scripts/oai-ci-vm-tool test --workspace $WORKSPACE --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID}" - } - } catch (Exception e) { - currentBuild.result = 'FAILURE' - } - } - } - } - } stage ("Build Flexran Controller") { when { - expression {doFlexranCtrlTest} + expression {doMandatoryTests} } steps { + lock (vmResource) { script { timeout (time: 20, unit: 'MINUTES') { try { @@ -419,10 +321,15 @@ pipeline { } } } + } } } stage ("Test basic simulator") { + when { + expression {doMandatoryTests} + } steps { + lock (vmResource) { script { timeout (time: 30, unit: 'MINUTES') { try { @@ -434,10 +341,15 @@ pipeline { } } } + } } } stage ("Test L1 simulator") { + when { + expression {doMandatoryTests} + } steps { + lock (vmResource) { script { timeout (time: 30, unit: 'MINUTES') { try { @@ -449,12 +361,17 @@ pipeline { } } } + } } } stage ("Test RF simulator") { + when { + expression {doMandatoryTests} + } steps { + lock (vmResource) { script { - timeout (time: 30, unit: 'MINUTES') { + timeout (time: 40, unit: 'MINUTES') { try { gitlabCommitStatus(name: "Test RF-sim") { sh "./ci-scripts/oai-ci-vm-tool test --workspace $WORKSPACE --variant rf-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" @@ -464,10 +381,35 @@ pipeline { } } } + } + } + } + stage ("Test 5G RF simulator") { + when { + expression {doMandatoryTests} + } + steps { + lock (vmResource) { + script { + timeout (time: 40, unit: 'MINUTES') { + try { + gitlabCommitStatus(name: "Test 5G RF-sim") { + sh "./ci-scripts/oai-ci-vm-tool test --workspace $WORKSPACE --variant rf5g-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + } + } + } + } } } stage ("Test L2 simulator") { + when { + expression {doFullTestsuite} + } steps { + lock (vmResource) { script { timeout (time: 30, unit: 'MINUTES') { try { @@ -479,16 +421,25 @@ pipeline { } } } + } } } stage ("Destroy all Virtual Machines") { + when { + expression {doMandatoryTests} + } steps { + lock (vmResource) { sh "./ci-scripts/oai-ci-vm-tool destroy --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + } } } } } stage ("Test MONOLITHIC - FDD - Band 7 - B210") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJob ('eNB-CI-FDD-Band7-B210', 'Test-Mono-FDD-Band7') @@ -508,6 +459,9 @@ pipeline { } } stage ("Test MONOLITHIC - TDD - Band 40 - B210") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJob ('eNB-CI-TDD-Band40-B210', 'Test-Mono-TDD-Band40') @@ -527,6 +481,9 @@ pipeline { } } stage ("Test IF4p5 - FDD - Band 7 - B210") { + when { + expression {doFullTestsuite} + } steps { script { sh "sleep 60" @@ -546,7 +503,33 @@ pipeline { } } } + stage ("Test F1 - FDD - Band 7 - B210") { + when { + expression {doFullTestsuite} + } + steps { + script { + sh "sleep 60" + triggerSlaveJob ('eNB-CI-F1-FDD-Band7-B210', 'Test-F1-FDD-Band7') + } + } + post { + always { + script { + finalizeSlaveJob('eNB-CI-F1-FDD-Band7-B210') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } stage ("Test IF4p5 - TDD - Band 40 - B210") { + when { + expression {doFullTestsuite} + } steps { script { sh "sleep 60" @@ -567,6 +550,9 @@ pipeline { } } stage ("Test MONOLITHIC - FDD - Band 13 - B210") { + when { + expression {doFullTestsuite} + } steps { script { sh "sleep 60" @@ -587,6 +573,9 @@ pipeline { } } stage ("Test X2 Handover - FDD - Band 13 - B210") { + when { + expression {doFullTestsuite} + } steps { script { sh "sleep 60" @@ -607,6 +596,9 @@ pipeline { } } stage ("Test IF4p5 - TDD - Band 38 - B210 - MultiRRU") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJob ('eNB-CI-IF4p5-TDD-Band38-MultiRRU-B210', 'Test-IF4p5-TDD-Band38-Multi-RRU') @@ -626,6 +618,9 @@ pipeline { } } stage ("Test OAI UE - FDD - Band 20 - B200") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJobNoGitLab ('UE-CI-FDD-Band20-B200') @@ -645,6 +640,9 @@ pipeline { } } stage ("Test OAI UE - OAI eNB - FDD - Band 7 - B200") { + when { + expression {doFullTestsuite} + } steps { script { // Delayed trigger on slave job, so it is always the last one to run @@ -666,6 +664,9 @@ pipeline { } } stage ("Test OAI NR UE - OAI gNB - TDD - Band 78 - N300") { + when { + expression {doMandatoryTests} + } steps { script { triggerSlaveJob ('gNB-nrUE-MONO-TDD-Band78-N300', 'Test-TDD-Band78-gNB-NR-UE') @@ -685,6 +686,9 @@ pipeline { } } stage ("Test OAI OCP-eNB - FDD - Band 7 - B210") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJob ('OCPeNB-FDD-Band7-B210', 'Test-OCP-FDD-Band7') @@ -707,8 +711,9 @@ pipeline { post { always { script { + if (doMandatoryTests) { dir ('archives') { - sh "if [ -d basic_sim/test ] || [ -d phy_sim/test ] || [ -d l2_sim/test ]; then zip -r -qq vm_tests_logs.zip */test ; fi" + sh "if [ -d basic_sim/test ] || [ -d rf_sim/test ] || [ -d l2_sim/test ]; then zip -r -qq vm_tests_logs.zip */test ; fi" } if(fileExists('archives/vm_tests_logs.zip')) { archiveArtifacts artifacts: 'archives/vm_tests_logs.zip' @@ -722,6 +727,7 @@ pipeline { archiveArtifacts artifacts: 'test_simulator_results.html' } } + } } } } diff --git a/ci-scripts/Jenkinsfile-physim-deploy b/ci-scripts/Jenkinsfile-physim-deploy new file mode 100644 index 0000000000..eac572e6cd --- /dev/null +++ b/ci-scripts/Jenkinsfile-physim-deploy @@ -0,0 +1,233 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Location of the executor node +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the resource +def ciEpcResource = params.epcResource + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess = false +def eNB_TargetBranch + +// Flags +def scmEvent = false +def upstreamEvent = false + +//------------------------------------------------------------------------------- +// Pipeline start +pipeline { + agent { + label pythonExecutor + } + options { + disableConcurrentBuilds() + timestamps() + ansiColor('xterm') + lock(ciEpcResource) + } + + stages { + stage ('Verify Parameters') { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + + JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"' + JOB_TIMESTAMP = JOB_TIMESTAMP.trim() + + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + + if (params.smartphonesResource == null) { + allParametersPresent = false + } + if (params.eNB_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB_Credentials == null) { + allParametersPresent = false + } + // the following 4 parameters should be pushed by the master trigger + // if not present, take the job GIT variables (used for developing) + if (params.eNB_Repository == null) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_mergeRequest != null) { + eNB_AllowMergeRequestProcess = params.eNB_mergeRequest + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + + if (params.ADB_IPAddress == null) { + allParametersPresent = false + } + if (params.ADB_Credentials == null) { + allParametersPresent = false + } + if (params.OC_Credentials == null) { + allParametersPresent = false + } + if (params.OC_ProjectName == null) { + allParametersPresent = false + } + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + + stage ("Deploy and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile} --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + } + } + } + } + } + stage ("Log Collection") { + steps { + script { + dir ('ci-scripts') { + // Zipping all archived log files + sh "zip -r -qq physim_deploytest_logs_${env.BUILD_ID}.zip physim_test_logs_*/*" + sh "rm -rf physim_test_logs_*/" + if (fileExists("physim_deploytest_logs_${env.BUILD_ID}.zip")) { + archiveArtifacts artifacts: "physim_deploytest_logs_${env.BUILD_ID}.zip" + } + if (fileExists("test_results.html")) { + sh "mv test_results.html test_results-${env.JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-push-registry b/ci-scripts/Jenkinsfile-push-registry new file mode 100644 index 0000000000..91d6136e0a --- /dev/null +++ b/ci-scripts/Jenkinsfile-push-registry @@ -0,0 +1,86 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Location of the python executor node shall be in the same subnet as the others servers +def nodeExecutor = params.nodeExecutor + +// Name of the phone resource +def ciServerResource = params.serverResource + +pipeline { + agent { + label nodeExecutor + } + options { + disableConcurrentBuilds() + ansiColor('xterm') + lock (ciServerResource) + } + stages { + stage ("Verify Parameters") { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + // It is already to late to check it + if (params.nodeExecutor != null) { + echo "Docker Push executor node : ${nodeExecutor}" + } + if (params.serverResource == null) { + allParametersPresent = false + } + } + } + } + stage ("Push to DockerHub") { + steps { + script { + WEEK_TAG = sh returnStdout: true, script: 'date +"%Y.w%U"' + WEEK_TAG = WEEK_TAG.trim() + + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.DH_Credentials}", usernameVariable: 'DH_Username', passwordVariable: 'DH_Password'] + ]) { + def listOfImages = ["oai-enb", "oai-gnb", "oai-lte-ue", "oai-nr-ue"] + sh "docker login -u ${DH_Username} -p ${DH_Password} > /dev/null 2>&1" + listOfImages.eachWithIndex { item, iindex -> + sh "docker image tag ${item}:develop ${DH_Username}/${item}:develop" + sh "docker image tag ${item}:develop ${DH_Username}/${item}:${WEEK_TAG}" + sh "docker push --quiet ${DH_Username}/${item}:${WEEK_TAG}" + sh "docker push --quiet ${DH_Username}/${item}:develop" + sh "docker rmi ${DH_Username}/${item}:${WEEK_TAG} ${DH_Username}/${item}:develop" + } + sh "docker logout > /dev/null 2>&1" + } + } + } + } + } + post { + always { + script { + echo "End of Registry Push" + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-tmp-full-ran b/ci-scripts/Jenkinsfile-tmp-full-ran index 15ad0379af..c3323f792d 100644 --- a/ci-scripts/Jenkinsfile-tmp-full-ran +++ b/ci-scripts/Jenkinsfile-tmp-full-ran @@ -266,6 +266,42 @@ pipeline { } stage('Log Collection') { parallel { + stage('Log Collection (eNB - Build)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("build.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "build.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (OAI UE - Build)') { + steps { + echo '\u2705 \u001B[32mLog Collection (OAI UE - Build)\u001B[0m' + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password'] + ]) { + sh "python3 ci-scripts/main.py --mode=LogCollectBuild --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (UE - Build)\u001B[0m' + sh "sshpass -p \'${UE_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${UE_Username}@${params.UE_IPAddress}:${UE_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("build.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "build.log.${env.BUILD_ID}.zip" + } + } + } + } stage('Log Collection (eNB - Run)') { steps { withCredentials([ diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel new file mode 100644 index 0000000000..195456da11 --- /dev/null +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel @@ -0,0 +1,293 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the phone resource +def ciSmartPhonesResource1 = params.SmartPhonesResource1 +def ciSmartPhonesResource2 = params.SmartPhonesResource2 + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess +def eNB_TargetBranch + +pipeline { + agent { + label pythonExecutor + } + options { + disableConcurrentBuilds() + ansiColor('xterm') + lock(extra: [[resource: ciSmartPhonesResource2]], resource: ciSmartPhonesResource1) + } + stages { + stage("Build Init") { + steps { + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${params.eNB_Branch}" + } + } + stage ("Verify Parameters") { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + + if (params.SmartPhonesResource1 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource2 == null) { + allParametersPresent = false + } + // 1st eNB parameters + if (params.eNB_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB_Credentials == null) { + allParametersPresent = false + } + // 2nd eNB parameters + if (params.eNB1_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB1_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB1_Credentials == null) { + allParametersPresent = false + } + // 3rd eNB parameters + if (params.eNB2_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB2_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB2_Credentials == null) { + allParametersPresent = false + } + // the following 4 parameters should be pushed by the master trigger + // if not present, take the job GIT variables (used for developing) + if (params.eNB_Repository == null) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_mergeRequest!= null) { + eNB_AllowMergeRequestProcess = params.eNB_mergeRequest + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + + if (params.ADB_IPAddress == null) { + allParametersPresent = false + } + if (params.ADB_Credentials == null) { + allParametersPresent = false + } + + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + stage ("Build and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + } + } + } + } + } + stage('Log Collection') { + parallel { + stage('Log Collection (eNB - Build)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("build.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "build.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (eNB - Run)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("enb.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "enb.log.${env.BUILD_ID}.zip" + } + if(fileExists("ci-scripts/test_results.html")) { + sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts "test_results-${JOB_NAME}.html" + } + } + } + } + } + } + } + + post { + always { + script { + if (params.pipelineZipsConsoleLog != null) { + if (params.pipelineZipsConsoleLog) { + echo "Archiving Jenkins console log" + sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true" + sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true" + if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel-long b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel-long new file mode 100644 index 0000000000..3a002b3748 --- /dev/null +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel-long @@ -0,0 +1,304 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the phone resource +def ciSmartPhonesResource1 = params.SmartPhonesResource1 +def ciSmartPhonesResource2 = params.SmartPhonesResource2 + +// Global Parameters. Populated when the master job +// triggers the slave job with parameters +def eNB_Repository = "https://gitlab.eurecom.fr/oai/openairinterface5g.git" +def eNB_Branch = "develop" +def eNB_CommitID +def eNB_AllowMergeRequestProcess = false +def eNB_TargetBranch = "develop" +def eNB_MR = "develop" + +pipeline { + agent { + label pythonExecutor + } + options { + disableConcurrentBuilds() + ansiColor('xterm') + lock(extra: [[resource: ciSmartPhonesResource2]], resource: ciSmartPhonesResource1) + } + stages { + stage("Build Init") { + steps { + script { + //retrieve latest commit ID from branch + latest_commit_from_branch= sh returnStdout: true, script: 'git log -1 origin/${eNB_Branch} | grep commit' + echo "Branch ${eNB_Branch}" + echo "${latest_commit_from_branch}" + tmp=latest_commit_from_branch.split() + echo "${tmp}" + eNB_CommitID = tmp[1] + echo "eNB_CommitID ${eNB_CommitID}" + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Commit : ${eNB_CommitID}" + } + } + } + stage ("Verify Parameters") { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + + if (params.SmartPhonesResource1 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource2 == null) { + allParametersPresent = false + } + // 1st eNB parameters + if (params.eNB_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB_Credentials == null) { + allParametersPresent = false + } + // 2nd eNB parameters + if (params.eNB1_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB1_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB1_Credentials == null) { + allParametersPresent = false + } + // 3rd eNB parameters + if (params.eNB2_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB2_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB2_Credentials == null) { + allParametersPresent = false + } + // the following 4 parameters should be pushed by the master trigger + // if not present, take the job GIT variables (used for developing) + if (params.eNB_Repository == null) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + //if (params.eNB_CommitID == null) { + // eNB_CommitID = env.GIT_COMMIT + //} else { + // eNB_CommitID = params.eNB_CommitID + //} + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_mergeRequest!= null) { + eNB_AllowMergeRequestProcess = params.eNB_mergeRequest + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + + if (params.ADB_IPAddress == null) { + allParametersPresent = false + } + if (params.ADB_Credentials == null) { + allParametersPresent = false + } + + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + stage ("Build and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + } + } + } + } + } + stage('Log Collection') { + parallel { + stage('Log Collection (eNB - Build)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("build.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "build.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (eNB - Run)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("enb.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "enb.log.${env.BUILD_ID}.zip" + } + if(fileExists("ci-scripts/test_results.html")) { + sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts "test_results-${JOB_NAME}.html" + } + } + } + } + } + } + } + + post { + always { + script { + if (params.pipelineZipsConsoleLog != null) { + if (params.pipelineZipsConsoleLog) { + echo "Archiving Jenkins console log" + sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true" + sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true" + if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa new file mode 100644 index 0000000000..a3939d832d --- /dev/null +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa @@ -0,0 +1,423 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor +def DataBaseHost = params.DataBaseHost + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the phone/server resource +def ciSmartPhonesResource1 = params.SmartPhonesResource1 +def ciSmartPhonesResource2 = params.SmartPhonesResource2 +def ciSmartPhonesResource3 = params.SmartPhonesResource3 + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess +def eNB_TargetBranch + +//Status fed to the database +def StatusForDb = "" + + +pipeline { + agent {label pythonExecutor} + options { + disableConcurrentBuilds() + ansiColor('xterm') + lock(extra: [[resource: ciSmartPhonesResource2],[resource: ciSmartPhonesResource1]],resource: ciSmartPhonesResource3) + } + stages { + stage("Build Init") { + steps { + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${params.eNB_Branch}" + } + } + stage ("Verify Parameters") { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + + if (params.SmartPhonesResource1 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource2 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource3 == null) { + allParametersPresent = false + } + // 1st eNB parameters + if (params.eNB_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB_Credentials == null) { + allParametersPresent = false + } + // 2nd eNB parameters + if (params.eNB1_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB1_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB1_Credentials == null) { + allParametersPresent = false + } + // 3rd eNB parameters + if (params.eNB2_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB2_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB2_Credentials == null) { + allParametersPresent = false + } + if (params.UE_IPAddress == null) { + allParametersPresent = false + } + if (params.UE_SourceCodePath == null) { + allParametersPresent = false + } + if (params.UE_Credentials == null) { + allParametersPresent = false + } + // the following 4 parameters should be pushed by the master trigger + // if not present, take the job GIT variables (used for developing) + if (params.eNB_Repository == null) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_mergeRequest!= null) { + eNB_AllowMergeRequestProcess = params.eNB_mergeRequest + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + + if (params.ADB_IPAddress == null) { + allParametersPresent = false + } + if (params.ADB_Credentials == null) { + allParametersPresent = false + } + if (params.DataBaseHost == "none") { + DataBaseHost = pythonExecutor + } + + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + stage ("Build and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password}" + } + } + } + } + } + stage('Log Collection') { + parallel { + stage('Log Collection (eNB - Build)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("build.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "build.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (OAI UE - Build)') { + steps { + echo '\u2705 \u001B[32mLog Collection (OAI UE - Build)\u001B[0m' + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password'] + ]) { + sh "python3 ci-scripts/main.py --mode=LogCollectBuild --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (UE - Build)\u001B[0m' + sh "sshpass -p \'${UE_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${UE_Username}@${params.UE_IPAddress}:${UE_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("build.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "build.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (eNB - Run)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("enb.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "enb.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (OAI UE - Run)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (OAI UE - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectOAIUE --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (OAI UE - Run)\u001B[0m' + sh "sshpass -p \'${UE_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${UE_Username}@${params.UE_IPAddress}:${UE_SourceCodePath}/cmake_targets/ue.log.zip ./ue.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("ue.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "ue.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (CN)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } + steps { + script { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (HSS)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectHSS --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --EPCType=${params.EPC_Type}" + if (params.EPC_Type != 'OAICN5G') { + sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/hss.log.zip ./hss.log.${env.BUILD_ID}.zip || true" + } + echo '\u2705 \u001B[32mLog Collection (MME or AMF)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectMME --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --EPCType=${params.EPC_Type}" + if (params.EPC_Type == 'OAICN5G') { + sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/mme.log.zip ./amf.log.${env.BUILD_ID}.zip || true" + } else { + sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/mme.log.zip ./mme.log.${env.BUILD_ID}.zip || true" + } + echo '\u2705 \u001B[32mLog Collection (SPGW or SMF/UPF)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectSPGW --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --EPCType=${params.EPC_Type}" + if (params.EPC_Type == 'OAICN5G') { + sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/spgw.log.zip ./smf-upf.log.${env.BUILD_ID}.zip || true" + } else { + sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/spgw.log.zip ./spgw.log.${env.BUILD_ID}.zip || true" + } + } + if(fileExists("hss.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "hss.log.${env.BUILD_ID}.zip" + } + if(fileExists("mme.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "mme.log.${env.BUILD_ID}.zip" + } + if(fileExists("spgw.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "spgw.log.${env.BUILD_ID}.zip" + } + if(fileExists("amf.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "amf.log.${env.BUILD_ID}.zip" + } + if(fileExists("smf-upf.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "smf-upf.log.${env.BUILD_ID}.zip" + } + echo '\u2705 \u001B[32mLog Collection for CoreNetwork Done!\u001B[0m' + } + } + } + stage ("SQL Collect"){ + when { + expression { params.DataBaseHost != "none" } + } + agent {label DataBaseHost} + steps { + script { + if (currentBuild.result=='FAILURE') {StatusForDb = 'FAIL'} else {StatusForDb = 'PASS'} + sh "python3 /home/oaicicd/mysql/sql_connect.py ${JOB_NAME} ${params.eNB_MR} ${params.eNB_Branch} ${env.BUILD_ID} ${env.BUILD_URL} ${StatusForDb} ''" + } + } + } + stage ("Result Update"){ + when { + expression { params.DataBaseHost != "none" } + } + agent {label DataBaseHost} + steps { + script { + dir ('ci-scripts/ran_dashboard') { + sh "python3 Hdashboard.py testevent ${params.eNB_MR} ${JOB_NAME} ${env.BUILD_URL} ${env.BUILD_ID} ${StatusForDb} " + } + } + } + } + } + } + } + + post { + always { + script { + if(fileExists("ci-scripts/test_results.html")) { + sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts "test_results-${JOB_NAME}.html" + } + if (params.pipelineZipsConsoleLog != null) { + if (params.pipelineZipsConsoleLog) { + echo "Archiving Jenkins console log" + sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true" + sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true" + if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran index ab1573de7f..a0d0f13871 100644 --- a/ci-scripts/Jenkinsfile-tmp-ran +++ b/ci-scripts/Jenkinsfile-tmp-ran @@ -241,6 +241,10 @@ pipeline { stage ("Terminate") { parallel { stage('Terminate UE') { + // Bypassing this stage if there are no abd server defined + when { + expression { params.ADB_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate UE\u001B[0m' withCredentials([ @@ -275,6 +279,10 @@ pipeline { } } stage('Terminate SPGW') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate SPGW\u001B[0m' withCredentials([ @@ -292,6 +300,10 @@ pipeline { } } stage('Terminate MME') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate MME\u001B[0m' withCredentials([ @@ -309,6 +321,10 @@ pipeline { } } stage('Terminate HSS') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate HSS\u001B[0m' withCredentials([ @@ -353,7 +369,7 @@ pipeline { [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] ]) { echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" @@ -371,6 +387,10 @@ pipeline { } } stage('Log Collection (SPGW)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -389,6 +409,10 @@ pipeline { } } stage('Log Collection (MME)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -407,6 +431,10 @@ pipeline { } } stage('Log Collection (HSS)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -425,6 +453,10 @@ pipeline { } } stage('Log Collection (Ping)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -443,6 +475,10 @@ pipeline { } } stage('Log Collection (Iperf)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -482,7 +518,7 @@ pipeline { // Making sure that we really shutdown every thing before leaving failure { script { - if (!termStatusArray[termUE]) { + if ((!termStatusArray[termUE]) && (params.ADB_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] ]) { @@ -496,21 +532,21 @@ pipeline { sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" } } - if (!termStatusArray[termSPGW]) { + if ((!termStatusArray[termSPGW]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { sh "python3 ci-scripts/main.py --mode=TerminateSPGW --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCType=${params.EPC_Type} --EPCSourceCodePath=${params.EPC_SourceCodePath}" } } - if (!termStatusArray[termMME]) { + if ((!termStatusArray[termMME]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { sh "python3 ci-scripts/main.py --mode=TerminateMME --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCType=${params.EPC_Type} --EPCSourceCodePath=${params.EPC_SourceCodePath}" } } - if (!termStatusArray[termHSS]) { + if ((!termStatusArray[termHSS]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { diff --git a/ci-scripts/Jenkinsfile-trig-nsa b/ci-scripts/Jenkinsfile-trig-nsa new file mode 100644 index 0000000000..7b4238d678 --- /dev/null +++ b/ci-scripts/Jenkinsfile-trig-nsa @@ -0,0 +1,114 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +def TARGET_BRANCH = "develop" +def ALLOW_MERGE = true + +pipeline { + agent { + label pythonExecutor + } + stages { + stage ("Launcher") { + steps { + script { + //retrieve MR that are opened nd with tag NSA + MR_LIST= sh returnStdout: true, script: 'curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100&labels=NSA" | jq ".[].iid" || true ' + echo "List of selected MR:\n${MR_LIST}" + def MR_ARRAY = MR_LIST.split('\n') + //for every selected MR, retrieve the branch name and the latest commit + for (MR in MR_ARRAY) { + SRC_BRANCH=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".source_branch" || true """ + SRC_BRANCH=SRC_BRANCH.trim() + COMMIT_ID=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".sha" || true """ + COMMIT_ID=COMMIT_ID.trim() + echo "Testing NSA on : ${MR} ${SRC_BRANCH} ${COMMIT_ID}" + //calling NSA B200 + build job: "RAN-NSA-B200-Module-LTEBOX", wait : true, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE)) + ] + //calling NSA 2x2 + build job: "RAN-NSA-2x2-Module-OAIEPC", wait : true, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE)) + ] + //calling LTE 2x2 + build job: "RAN-LTE-2x2-Module-OAIEPC", wait : true, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE)) + ] + //calling SA + build job: "RAN-SA-Module-CN5G", wait : true, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE)) + ] + //calling OAIUE B200 + //build job: "RAN-SA-OAIUE-B200-CN5G", wait : true, propagate : false, parameters: [ + // string(name: 'eNB_MR', value: String.valueOf(MR)), + // string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + // string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + // string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + // booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE)) + //] + //calling OAIUE N310 + //build job: "RAN-SA-OAIUE-N310-CN5G", wait : true, propagate : false, parameters: [ + // string(name: 'eNB_MR', value: String.valueOf(MR)), + // string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + // string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + // string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + // booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE)) + //] + //calling OAIUE N310-X300 + build job: "RAN-SA-OAIUE-N310-X300-CN5G", wait : true, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_mergeRequest', value: Boolean.valueOf(ALLOW_MERGE)) + ] + + } + } + } + } + } +} + + diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 1249f52172..c0203a4c98 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -34,14 +34,14 @@ import sys # arg import re # reg import yaml - +import constants as CONST #----------------------------------------------------------- # Parsing Command Line Arguements #----------------------------------------------------------- -def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): +def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP,SCA,PHYSIM): py_param_file_present = False @@ -79,6 +79,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): RAN.ranRepository=matchReg.group(1) HTML.ranRepository=matchReg.group(1) ldpc.ranRepository=matchReg.group(1) + CONTAINERS.ranRepository=matchReg.group(1) + SCA.ranRepository=matchReg.group(1) + PHYSIM.ranRepository=matchReg.group(1) elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) @@ -90,6 +93,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): CiTestObj.ranAllowMerge = True RAN.ranAllowMerge=True HTML.ranAllowMerge=True + CONTAINERS.ranAllowMerge=True + SCA.ranAllowMerge=True + PHYSIM.ranAllowMerge=True elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) @@ -99,6 +105,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): RAN.ranBranch=matchReg.group(1) HTML.ranBranch=matchReg.group(1) ldpc.ranBranch=matchReg.group(1) + CONTAINERS.ranBranch=matchReg.group(1) + SCA.ranBranch=matchReg.group(1) + PHYSIM.ranBranch=matchReg.group(1) elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) @@ -108,6 +117,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): RAN.ranCommitID=matchReg.group(1) HTML.ranCommitID=matchReg.group(1) ldpc.ranCommitID=matchReg.group(1) + CONTAINERS.ranCommitID=matchReg.group(1) + SCA.ranCommitID=matchReg.group(1) + PHYSIM.ranCommitID=matchReg.group(1) elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) @@ -117,50 +129,73 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): RAN.ranTargetBranch=matchReg.group(1) HTML.ranTargetBranch=matchReg.group(1) ldpc.ranTargetBranch=matchReg.group(1) + CONTAINERS.ranTargetBranch=matchReg.group(1) + SCA.ranTargetBranch=matchReg.group(1) + PHYSIM.ranTargetBranch=matchReg.group(1) elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNBIPAddress=matchReg.group(1) ldpc.eNBIpAddr=matchReg.group(1) + CONTAINERS.eNBIPAddress=matchReg.group(1) + SCA.eNBIPAddress=matchReg.group(1) + PHYSIM.eNBIPAddress=matchReg.group(1) elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1IPAddress=matchReg.group(1) + CONTAINERS.eNB1IPAddress=matchReg.group(1) elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNB2IPAddress=matchReg.group(1) + CONTAINERS.eNB2IPAddress=matchReg.group(1) elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNBUserName=matchReg.group(1) ldpc.eNBUserName=matchReg.group(1) + CONTAINERS.eNBUserName=matchReg.group(1) + SCA.eNBUserName=matchReg.group(1) + PHYSIM.eNBUserName=matchReg.group(1) elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1UserName=matchReg.group(1) + CONTAINERS.eNB1UserName=matchReg.group(1) elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNB2UserName=matchReg.group(1) + CONTAINERS.eNB2UserName=matchReg.group(1) elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) RAN.eNBPassword=matchReg.group(1) ldpc.eNBPassWord=matchReg.group(1) + CONTAINERS.eNBPassword=matchReg.group(1) + SCA.eNBPassword=matchReg.group(1) + PHYSIM.eNBPassword=matchReg.group(1) elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1Password=matchReg.group(1) + CONTAINERS.eNB1Password=matchReg.group(1) elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) RAN.eNB2Password=matchReg.group(1) + CONTAINERS.eNB2Password=matchReg.group(1) elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) RAN.eNBSourceCodePath=matchReg.group(1) ldpc.eNBSourceCodePath=matchReg.group(1) + CONTAINERS.eNBSourceCodePath=matchReg.group(1) + SCA.eNBSourceCodePath=matchReg.group(1) + PHYSIM.eNBSourceCodePath=matchReg.group(1) elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1SourceCodePath=matchReg.group(1) + CONTAINERS.eNB1SourceCodePath=matchReg.group(1) elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) RAN.eNB2SourceCodePath=matchReg.group(1) + CONTAINERS.eNB2SourceCodePath=matchReg.group(1) elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) EPC.IPAddress=matchReg.group(1) @@ -222,6 +257,18 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): finalStatus = matchReg.group(1) if ((finalStatus == 'true') or (finalStatus == 'True')): CiTestObj.finalStatus = True + elif re.match('^\-\-OCUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-OCUserName=(.+)$', myArgv, re.IGNORECASE) + PHYSIM.OCUserName = matchReg.group(1) + elif re.match('^\-\-OCPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-OCPassword=(.+)$', myArgv, re.IGNORECASE) + PHYSIM.OCPassword = matchReg.group(1) + elif re.match('^\-\-OCProjectName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-OCProjectName=(.+)$', myArgv, re.IGNORECASE) + PHYSIM.OCProjectName = matchReg.group(1) + elif re.match('^\-\-BuildId=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-BuildId=(.+)$', myArgv, re.IGNORECASE) + RAN.BuildId = matchReg.group(1) else: HELP.GenericHelp(CONST.Version) sys.exit('Invalid Parameter: ' + myArgv) diff --git a/ci-scripts/auto_start_gnb.sh b/ci-scripts/auto_start_gnb.sh new file mode 100644 index 0000000000..86ffc66d18 --- /dev/null +++ b/ci-scripts/auto_start_gnb.sh @@ -0,0 +1,7 @@ +#!/bin/bash +while true +do + echo "gNB will be started automatically..." + sleep 1 + sudo .././cmake_targets/ran_build/build/nr-softmodem -E -O ../targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf +done diff --git a/ci-scripts/buildOnRH.sh b/ci-scripts/buildOnRH.sh deleted file mode 100755 index eaff097c88..0000000000 --- a/ci-scripts/buildOnRH.sh +++ /dev/null @@ -1,216 +0,0 @@ -#!/bin/bash -#/* -# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -# * contributor license agreements. See the NOTICE file distributed with -# * this work for additional information regarding copyright ownership. -# * The OpenAirInterface Software Alliance licenses this file to You under -# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 -# * -# * 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. -# *------------------------------------------------------------------------------- -# * For more information about the OpenAirInterface (OAI) Software Alliance: -# * contact@openairinterface.org -# */ - -function usage { - echo "OAI RedHat Build Check script" - echo " Original Author: Raphael Defosseux" - - echo "" - echo "Usage:" - echo "------" - echo " buildOnRH.sh [OPTIONS]" - echo "" - echo "Options:" - echo "--------" - echo " --job-name #### OR -jn ####" - echo " Specify the name of the Jenkins job." - echo "" - echo " --build-id #### OR -id ####" - echo " Specify the build ID of the Jenkins job." - echo "" - echo " --workspace #### OR -ws ####" - echo " Specify the workspace." - echo "" - echo " --remote-host #### OR -rh ####" - echo " Specify the RedHat remote server." - echo "" - echo " --remote-user-name #### OR -ru ####" - echo " Specify the RedHat remote server username." - echo "" - echo " --remote-password #### OR -rp ####" - echo " Specify the RedHat remote server password." - echo "" - echo " --remote-path #### OR -ra ####" - echo " Specify the RedHat remote server path to work on." - echo "" -} - -if [ $# -lt 1 ] || [ $# -gt 14 ] -then - echo "Syntax Error: not the correct number of arguments" - echo "" - usage - exit 1 -fi - -RH_HOST=XX -RH_USER=XX -RH_PASSWD=XX -RH_PATH=XX -JOB_NAME=XX -BUILD_ID=XX - -while [[ $# -gt 0 ]] -do -key="$1" - -case $key in - -h|--help) - shift - usage - exit 0 - ;; - -jn|--job-name) - JOB_NAME="$2" - shift - shift - ;; - -id|--build-id) - BUILD_ID="$2" - shift - shift - ;; - -ws|--workspace) - JENKINS_WKSP="$2" - shift - shift - ;; - -rh|--remote-host) - RH_HOST="$2" - shift - shift - ;; - -ru|--remote-user-name) - RH_USER="$2" - shift - shift - ;; - -rp|--remote-password) - RH_PASSWD="$2" - shift - shift - ;; - -ra|--remote-path) - RH_PATH="$2" - shift - shift - ;; - *) - echo "Syntax Error: unknown option: $key" - echo "" - usage - exit 1 -esac -done - -if [ ! -f $JENKINS_WKSP/localZip.zip ] -then - echo "Missing localZip.zip file!" - exit 1 -fi - -if [ "$JOB_NAME" == "XX" ] || [ "$BUILD_ID" == "XX" ] || [ "$RH_HOST" == "XX" ] || [ "$RH_USER" == "XX" ] || [ "$RH_PASSWD" == "XX" ] || [ "$RH_PATH" == "XX" ] -then - echo "Missing options" - usage - exit 1 -fi - -echo "############################################################" -echo "Copying GIT repo into RedHat Server" -echo "############################################################" -echo "rm -Rf ${RH_PATH}" >> rh-cmd.txt -echo "mkdir -p ${RH_PATH}" >> rh-cmd.txt - -sshpass -p ${RH_PASSWD} ssh -o 'StrictHostKeyChecking no' ${RH_USER}@${RH_HOST} < rh-cmd.txt -rm -f rh-cmd.txt - -echo "############################################################" -echo "Running install and build script on RedHat Server" -echo "############################################################" -sshpass -p ${RH_PASSWD} scp -o 'StrictHostKeyChecking no' $JENKINS_WKSP/localZip.zip ${RH_USER}@${RH_HOST}:${RH_PATH} - -echo "cd ${RH_PATH}" > rh-cmd.txt -echo "unzip -qq localZip.zip" >> rh-cmd.txt -echo "source oaienv" >> rh-cmd.txt -echo "cd cmake_targets" >> rh-cmd.txt -echo "mkdir -p log" >> rh-cmd.txt -echo "./build_oai -I -w USRP --eNB > log/install-build.txt 2>&1" >> rh-cmd.txt -sshpass -p ${RH_PASSWD} ssh -o 'StrictHostKeyChecking no' ${RH_USER}@${RH_HOST} < rh-cmd.txt - -rm -f rh-cmd.txt - -echo "############################################################" -echo "Creating a tmp folder to store results and artifacts" -echo "############################################################" -if [ ! -d $JENKINS_WKSP/archives ] -then - mkdir -p $JENKINS_WKSP/archives -fi - -ARCHIVES_LOC=$JENKINS_WKSP/archives/red_hat -if [ ! -d $ARCHIVES_LOC ] -then - mkdir -p $ARCHIVES_LOC -fi - -sshpass -p ${RH_PASSWD} scp -o 'StrictHostKeyChecking no' ${RH_USER}@${RH_HOST}:${RH_PATH}/cmake_targets/log/*.txt $ARCHIVES_LOC - -echo "############################################################" -echo "Checking build status" -echo "############################################################" - -LOG_PATTERN=.Rel15.txt -NB_PATTERN_FILES=7 - -LOG_FILES=`ls $ARCHIVES_LOC/*.txt` -STATUS=0 -NB_FOUND_FILES=0 - -for FULLFILE in $LOG_FILES -do - if [[ $FULLFILE == *"$LOG_PATTERN"* ]] - then - filename=$(basename -- "$FULLFILE") - PASS_PATTERN=`echo $filename | sed -e "s#$LOG_PATTERN##"` - LOCAL_STAT=`egrep -c "Built target $PASS_PATTERN" $FULLFILE` - if [ $LOCAL_STAT -eq 0 ]; then STATUS=-1; fi - NB_FOUND_FILES=$((NB_FOUND_FILES + 1)) - fi -done - -if [ $NB_PATTERN_FILES -ne $NB_FOUND_FILES ] -then - echo "Expecting $NB_PATTERN_FILES log files and found $NB_FOUND_FILES" - STATUS=-1 -fi - -echo "COMMAND: build_oai -I -w USRP --eNB" > $ARCHIVES_LOC/build_final_status.log -if [ $STATUS -eq 0 ] -then - echo "BUILD_OK" >> $ARCHIVES_LOC/build_final_status.log - echo "STATUS seems OK" -else - echo "BUILD_KO" >> $ARCHIVES_LOC/build_final_status.log - echo "STATUS failed?" -fi -exit $STATUS diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh index 72fa29aa39..f4cf3931dd 100755 --- a/ci-scripts/buildOnVM.sh +++ b/ci-scripts/buildOnVM.sh @@ -62,6 +62,12 @@ function build_on_vm { echo "ARCHIVES_LOC = $ARCHIVES_LOC" echo "BUILD_OPTIONS = $BUILD_OPTIONS" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] || [[ "$VM_NAME" == *"-phy-sim"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME` if [ $IS_VM_ALIVE -eq 0 ] @@ -158,6 +164,9 @@ function build_on_vm { echo "cd tmp" >> $VM_CMDS echo "echo \"unzip -qq -DD ../localZip.zip\"" >> $VM_CMDS echo "unzip -qq -DD ../localZip.zip" >> $VM_CMDS + # Trying to make some room on filesystem before building + echo "rm ../localZip.zip" >> $VM_CMDS + echo "export CI_ENV=True" >> $VM_CMDS if [[ "$VM_NAME" == *"-cppcheck"* ]] then echo "mkdir cmake_targets/log" >> $VM_CMDS @@ -178,6 +187,8 @@ function build_on_vm { echo "mkdir -p cmake_targets/log" >> $VM_CMDS echo "chmod 777 cmake_targets/log" >> $VM_CMDS echo "cp /home/ubuntu/zip-install.txt cmake_targets/log" >> $VM_CMDS + # Patching the pistache build for Xenial (cmake too old for new commits) + echo "sed -i -e 's@cd pistache@cd pistache \&\& git checkout -f 9a65f40975fafca5bb5370ba6d0d00f42cbc4356@' ./tools/install_dependencies" >> $VM_CMDS echo "echo \"./tools/install_dependencies \"" >> $VM_CMDS echo "./tools/install_dependencies > cmake_targets/log/install-build.txt 2>&1" >> $VM_CMDS echo "echo \"mkdir build\"" >> $VM_CMDS @@ -206,7 +217,15 @@ function build_on_vm { echo "echo \"./build_oai -I $BUILD_OPTIONS \"" >> $VM_CMDS echo "./build_oai -I $BUILD_OPTIONS > log/install-build.txt 2>&1" >> $VM_CMDS else - echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + if [[ "$VM_NAME" == *"-enb-ethernet"* ]] + then + echo "echo \"sleep 170 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + elif [[ "$VM_NAME" == *"-ue-ethernet"* ]] + then + echo "echo \"sleep 60 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + else + echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + fi echo "chmod 775 ./my-vm-build.sh " >> $VM_CMDS echo "echo \"sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh\"" >> $VM_CMDS echo "sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh" >> $VM_CMDS diff --git a/ci-scripts/build_fr1_from_yaml.py b/ci-scripts/build_fr1_from_yaml.py new file mode 100755 index 0000000000..a5492df6f6 --- /dev/null +++ b/ci-scripts/build_fr1_from_yaml.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Jul 7 23:04:51 2020 + +@author: hardy +""" + + + +import yaml +import sys +import subprocess + + + +def main(): + f_yaml=sys.argv[1] + f_sh=sys.argv[2] + #filename='py_params_template.yaml' + with open(f_yaml,'r') as file: + # The FullLoader parameter handles the conversion from YAML + # scalar values to Python the dictionary format + print('Loading '+f_yaml) + params = yaml.load(file,Loader=yaml.FullLoader) + + + with open(f_sh,'w') as f: + f.write('#!/bin/sh\n') + for i in range (0, len(params['steps'])): + step=params['steps'][i].split(',') + mode=step[0] + f_xml=step[1] + line='python3 main.py ' + \ + '--mode='+ mode + ' ' + \ + '--ranRepository=' + params['ranRepository'] + ' ' + \ + '--ranBranch=' + params['ranBranch'] + ' ' + \ + '--ranCommitID=' + params['ranCommitID'] + ' ' + \ + '--ranAllowMerge=' + params['ranAllowMerge'] + ' ' + \ + '--ranTargetBranch=' + params['ranTargetBranch'] + ' ' + \ + \ + '--ADBIPAddress=' + params['ADB']['ADBIPAddress'] + ' ' + \ + '--ADBUserName=' + params['ADB']['ADBUserName'] + ' ' + \ + '--ADBPassword=' + params['ADB']['ADBPassword'] + ' ' + \ + \ + '--UEIPAddress=' + params['UE']['UEIPAddress'] + ' ' + \ + '--UEUserName=' + params['UE']['UEUserName'] + ' ' + \ + '--UEPassword=' + params['UE']['UEPassword'] + ' ' + \ + '--UESourceCodePath=' + params['UE']['UESourceCodePath'] + ' ' + \ + \ + '--EPCIPAddress=' + params['EPC']['EPCIPAddress'] + ' ' + \ + '--EPCUserName=' + params['EPC']['EPCUserName'] + ' ' + \ + '--EPCPassword=' + params['EPC']['EPCPassword'] + ' ' + \ + '--EPCSourceCodePath=' + params['EPC']['EPCSourceCodePath'] + ' ' + \ + '--EPCType=' + params['EPC']['EPCType'] + ' ' + \ + \ + '--eNBIPAddress=' + params['RAN'][0]['eNBIPAddress'] + ' ' + \ + '--eNBUserName=' + params['RAN'][0]['eNBUserName'] + ' ' + \ + '--eNBPassword=' + params['RAN'][0]['eNBPassword'] + ' ' + \ + '--eNBSourceCodePath=' + params['RAN'][0]['eNBSourceCodePath'] + ' ' + \ + \ + '--eNB1IPAddress=' + params['RAN'][1]['eNB1IPAddress'] + ' ' + \ + '--eNB1UserName=' + params['RAN'][1]['eNB1UserName'] + ' ' + \ + '--eNB1Password=' + params['RAN'][1]['eNB1Password'] + ' ' + \ + '--eNB1SourceCodePath=' + params['RAN'][1]['eNB1SourceCodePath'] + ' ' + if mode!="InitiateHtml": + line+='--XMLTestFile=' + f_xml + #if mode is InitiateHTML we have a special processing to mention all xml files from the list + #loop starting at 1 to avoid the xml file mentioned with InitiateHtml in yaml file (file is none) + else: + for i in range (1, len(params['steps'])): + step=params['steps'][i].split(',') + f_xml=step[1] + line+='--XMLTestFile=' + f_xml+' ' + line+='\n' + print(line) + f.write(line) + subprocess.call(['chmod','777',f_sh]) + +if __name__ == "__main__": + main() + + diff --git a/ci-scripts/build_fr1_template.yaml b/ci-scripts/build_fr1_template.yaml new file mode 100755 index 0000000000..02e49bc4b5 --- /dev/null +++ b/ci-scripts/build_fr1_template.yaml @@ -0,0 +1,46 @@ + +ranRepository : https://gitlab.eurecom.fr/oai/openairinterface5g.git +ranBranch : integration_2021_wk13_a +ranCommitID : 104aa7eed5d6702c1b9da663414079ef698da206 +ranAllowMerge : 'yes' +ranTargetBranch : develop + +steps: + - InitiateHtml,none + - TesteNB,xml_files/fr1_multi_node_build.xml + - TesteNB,xml_files/fr1_epc_start.xml + - TesteNB,xml_files/fr1_nsa_base_next.xml #ue toggle, nodes initialize, ue toggle, ping, nodes terminate + - TesteNB,xml_files/fr1_epc_closure.xml + + +ADB: #on Caracal + ADBIPAddress : 192.168.18.196 + ADBUserName : oaici + ADBPassword : KkexF6CErOi1fNuebCPsuIVK + +RAN: + - eNBIPAddress : 192.168.18.199 #eNB on Minimassive + eNBUserName : oaicicd + eNBPassword : HzB*nkryaITdVd08TKlT#2Z5a!7M#~qn + eNBSourceCodePath : /tmp/CI-FR1-eNB + - eNB1IPAddress : 192.168.18.198 #gNB on Mozart + eNB1UserName : oaicicd + eNB1Password : 7zkDOFgh@w3HvRBMPTMh@BAx + eNB1SourceCodePath : /tmp/CI-FR1-gNB + + +EPC: #on Nikaia + EPCIPAddress : 192.168.18.99 + EPCUserName : nikaia + EPCPassword : linux + EPCSourceCodePath : /tmp/CI-FR1-EPC + EPCType : ltebox + + +UE: + UEIPAddress : none + UEUserName : none + UEPassword : none + UESourceCodePath : none + + diff --git a/ci-scripts/checkCodingFormattingRules.sh b/ci-scripts/checkCodingFormattingRules.sh index fb159d4da0..a805f765df 100755 --- a/ci-scripts/checkCodingFormattingRules.sh +++ b/ci-scripts/checkCodingFormattingRules.sh @@ -59,7 +59,7 @@ if [ $# -eq 0 ] then echo " ---- Checking the whole repository ----" echo "" - NB_FILES_TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt --recursive *.c *.h | grep -c Formatted ` + NB_FILES_TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt --recursive *.c *.h | grep -c Formatted || true` echo "Nb Files that do NOT follow OAI rules: $NB_FILES_TO_FORMAT" echo $NB_FILES_TO_FORMAT > ./oai_rules_result.txt @@ -67,17 +67,17 @@ then awk '/#[ \t]*ifndef/ { gsub("^.*ifndef *",""); if (names[$1]!="") print "files with same {define ", FILENAME, names[$1]; names[$1]=FILENAME } /#[ \t]*define/ { gsub("^.*define *",""); if(names[$1]!=FILENAME) print "error in declaration", FILENAME, $1, names[$1]; nextfile }' `find openair* common targets executables -name *.h |grep -v LFDS` > header-files-w-incorrect-define.txt # Testing if explicit GNU GPL license banner - egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "General Public License" . > files-w-gnu-gpl-license-banner.txt + egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "General Public License" . | egrep -v "openair3/NAS/COMMON/milenage.h" > files-w-gnu-gpl-license-banner.txt # Looking at exotic/suspect banner LIST_OF_FILES_W_BANNER=`egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "Copyright|copyleft" .` if [ -f ./files-w-suspect-banner.txt ]; then rm -f ./files-w-suspect-banner.txt; fi for FILE in $LIST_OF_FILES_W_BANNER do - IS_NFAPI=`echo $FILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext"` - IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FILE` - IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence" $FILE` - IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h"` + IS_NFAPI=`echo $FILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true` + IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FILE || true` + IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FILE || true` + IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h|openair3/GTPV1-U/nw-gtpv1u|openair2/UTIL/OPT/ws_|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc|openair1/PHY/CODING/types.h" || true` if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] then if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ] @@ -178,7 +178,7 @@ do EXT="${filename##*.}" if [ $EXT = "c" ] || [ $EXT = "h" ] || [ $EXT = "cpp" ] || [ $EXT = "hpp" ] then - TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt $FULLFILE | grep -c Formatted ` + TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt $FULLFILE | grep -c Formatted || true` NB_TO_FORMAT=$((NB_TO_FORMAT + TO_FORMAT)) if [ $TO_FORMAT -ne 0 ] then @@ -186,20 +186,24 @@ do echo $FULLFILE >> ./oai_rules_result_list.txt fi # Testing if explicit GNU GPL license banner - egrep -i "General Public License" $FULLFILE >> files-w-gnu-gpl-license-banner.txt + GNU_EXCEPTION=`echo $FULLFILE | egrep -c "openair3/NAS/COMMON/milenage.h" || true` + if [ $GNU_EXCEPTION -eq 0 ] + then + egrep -il "General Public License" $FULLFILE >> files-w-gnu-gpl-license-banner.txt + fi # Looking at exotic/suspect banner - IS_BANNER=`egrep -i -c "Copyright|copyleft" $FULLFILE` + IS_BANNER=`egrep -i -c "Copyright|copyleft" $FULLFILE || true` if [ $IS_BANNER -ne 0 ] then - IS_NFAPI=`echo $FULLFILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext"` - IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FULLFILE` - IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence" $FULLFILE` - IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h"` + IS_NFAPI=`echo $FULLFILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true` + IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FULLFILE || true` + IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FULLFILE || true` + IS_EXCEPTION=`echo $FULLFILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h|openair3/GTPV1-U/nw-gtpv1u|openair2/UTIL/OPT/ws_|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc|openair1/PHY/CODING/types.h" || true` if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] then if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ] then - echo $FILE >> ./files-w-suspect-banner.txt + echo $FULLFILE >> ./files-w-suspect-banner.txt fi fi fi diff --git a/ci-scripts/checkGitLabMergeRequestLabels.sh b/ci-scripts/checkGitLabMergeRequestLabels.sh new file mode 100755 index 0000000000..7e4ea1c7de --- /dev/null +++ b/ci-scripts/checkGitLabMergeRequestLabels.sh @@ -0,0 +1,108 @@ +#!/bin/bash +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +function usage { + echo "OAI GitLab merge request applying script" + echo " Original Author: Raphael Defosseux" + echo "" + echo "Usage:" + echo "------" + echo "" + echo " checkGitLabMergeRequestLabels.sh [OPTIONS]" + echo "" + echo "Options:" + echo "------------------" + echo "" + echo " --mr-id ####" + echo " Specify the ID of the merge request." + echo "" + echo " --help OR -h" + echo " Print this help message." + echo "" +} + +if [ $# -ne 2 ] && [ $# -ne 1 ] +then + echo "Syntax Error: not the correct number of arguments" + echo "" + usage + exit 1 +fi + +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + shift + usage + exit 0 + ;; + --mr-id) + MERGE_REQUEST_ID="$2" + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 +esac +done + +LABELS=`curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/$MERGE_REQUEST_ID" | jq '.labels' || true` + +IS_MR_BUILD_ONLY=`echo $LABELS | grep -c BUILD-ONLY || true` +IS_MR_CI=`echo $LABELS | grep -c CI || true` +IS_MR_4G=`echo $LABELS | grep -c 4G-LTE || true` +IS_MR_5G=`echo $LABELS | grep -c 5G-NR || true` + +# First case: none is present! No CI +if [ $IS_MR_BUILD_ONLY -eq 0 ] && [ $IS_MR_CI -eq 0 ] && [ $IS_MR_4G -eq 0 ] && [ $IS_MR_5G -eq 0 ] +then + echo "NONE" + exit 0 +fi + +# Second case: Build-Only +if [ $IS_MR_BUILD_ONLY -eq 1 ] +then + echo "BUILD-ONLY" + exit 0 +fi + +# Third case: CI or 4G label --> Full CI run +if [ $IS_MR_4G -eq 1 ] || [ $IS_MR_CI -eq 1 ] +then + echo "FULL" + exit 0 +fi + +# Fourth case: 5G label +if [ $IS_MR_BUILD_ONLY -eq 0 ] && [ $IS_MR_CI -eq 0 ] && [ $IS_MR_4G -eq 0 ] && [ $IS_MR_5G -eq 1 ] +then + echo "SHORTEN-5G" + exit 0 +fi + diff --git a/ci-scripts/ci_ctl_qtel.py b/ci-scripts/ci_ctl_qtel.py new file mode 100644 index 0000000000..3785d7ee89 --- /dev/null +++ b/ci-scripts/ci_ctl_qtel.py @@ -0,0 +1,86 @@ +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Required Python Version +# Python 3.x +# +#--------------------------------------------------------------------- + +#usage example: +#sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 wup +#sudo python3 ci_ctl_qtel.py /dev/ttyUSB2 detach + + +import sys +import time +import serial + + +class qtel_ctl: + #--------------- + #private methods + #--------------- + def __init__(self, usb_port_at): + self.QUECTEL_USB_PORT_AT = usb_port_at #ex : '/dev/ttyUSB2' + self.modem = serial.Serial(self.QUECTEL_USB_PORT_AT, timeout=1) + self.cmd_dict= {"wup": self.wup,"detach":self.detach}#dictionary of function pointers + + def __set_modem_state(self,ser,state): + self.__send_command(ser,"AT+CFUN={}\r".format(state)) + + def __send_command(self,ser,com): + ser.write(com.encode()) + time.sleep(0.1) + ret=[] + while ser.inWaiting()>0: + print("waiting") + msg=ser.readline() + msg=msg.decode("utf-8") + msg=msg.replace("\r","") + msg=msg.replace("\n","") + print(msg) + if msg!="": + ret.append(msg) + else: + print("msg empty") + return ret + + #-------------- + #public methods + #-------------- + def wup(self):#sending AT+CFUN=0, then AT+CFUN=1 + self.__set_modem_state(self.modem,'0') + time.sleep(3) + self.__set_modem_state(self.modem,'1') + + def detach(self):#sending AT+CFUN=0 + self.__set_modem_state(self.modem,'0') + + + + +if __name__ == "__main__": + #argv[1] : usb port + #argv[2] : qtel command (see function pointers dict "wup", "detach" etc ...) + command = sys.argv[2] + Module=qtel_ctl(sys.argv[1]) + #calling the function to be applied + Module.cmd_dict[command]() diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml new file mode 100644 index 0000000000..51acb75968 --- /dev/null +++ b/ci-scripts/ci_ueinfra.yaml @@ -0,0 +1,58 @@ +idefix: + ID: idefix + State : enabled + Kind : quectel + Process : + Name : quectel-CM + Cmd : /home/oaicicd/quectel-CM/quectel-CM -4 -s + Apn : + ltebox : oai.ipv4 + WakeupScript : ci_ctl_qtel.py /dev/ttyUSB2 wup + DetachScript : ci_ctl_qtel.py /dev/ttyUSB2 detach + LogStore : /media/usb-drive/ci_qlogs + PLMN : 22201 + UENetwork : wwan0 + HostIPAddress : 192.168.18.188 + HostUsername : oaicicd + HostPassword : oaicicd + HostSourceCodePath : none + MTU : 1500 +nrmodule2_quectel: + ID: nrmodule2_quectel + State : enabled + Kind : quectel + Process : + Name : quectel-CM + Cmd : /home/nrmodule2/quectel-CM/quectel-CM -4 -s + Apn : + OAICN5G : oai + OAI-Rel14-Docker : oai.ipv4 + WakeupScript : ci_ctl_qtel.py /dev/ttyUSB7 wup + DetachScript : ci_ctl_qtel.py /dev/ttyUSB7 detach + LogStore : /media/ci_qlogs + PLMN : 20897 + UENetwork : wwan1 + HostIPAddress : 192.168.18.189 + HostUsername : nrmodule2 + HostPassword : linux + HostSourceCodePath : none + StartCommands : + - sudo -S ip link set dev wwan1 mtu 1500 + MTU : 1500 +dummy: + ID: '' + State : '' + Kind : '' + Process : + Name : '' + Cmd : '' + WakeupScript : '' + DetachScript : '' + PLMN : 22201 + UENetwork : wwan0 + HostIPAddress : 192.168.18.188 + HostUsername : oaicicd + HostPassword : oaicicd + HostSourceCodePath : none + + diff --git a/ci-scripts/cls_ci_ueinfra.py b/ci-scripts/cls_ci_ueinfra.py new file mode 100644 index 0000000000..0326a92a4f --- /dev/null +++ b/ci-scripts/cls_ci_ueinfra.py @@ -0,0 +1,57 @@ +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Required Python Version +# Python 3.x +# +#--------------------------------------------------------------------- + +#to use isfile +import os +import sys +import logging +#to create a SSH object locally in the methods +import sshconnection +#time.sleep +import time +#to load ue infrastructure dictionary +import yaml + +class InfraUE: + def __init__(self): + self.ci_ue_infra ={} + + +#-----------------$ +#PUBLIC Methods$ +#-----------------$ + + #This method reads the yaml file describing the multi-UE infrastructure + #and stores the infra permanently in the related class attribute self.ci_ue_infra + def Get_UE_Infra(self,ue_infra_filename): + f_yaml=ue_infra_filename + with open(f_yaml,'r') as file: + logging.debug('Loading UE infrastructure from file '+f_yaml) + #load it permanently in the class attribute + self.ci_ue_infra = yaml.load(file,Loader=yaml.FullLoader) + + + diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py new file mode 100644 index 0000000000..41747f1bc2 --- /dev/null +++ b/ci-scripts/cls_containerize.py @@ -0,0 +1,1021 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import logging +import os +import shutil +import subprocess +import time +from multiprocessing import Process, Lock, SimpleQueue +from zipfile import ZipFile + +#----------------------------------------------------------- +# OAI Testing modules +#----------------------------------------------------------- +import sshconnection as SSH +import helpreadme as HELP +import constants as CONST + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class Containerize(): + + def __init__(self): + + self.ranRepository = '' + self.ranBranch = '' + self.ranAllowMerge = False + self.ranCommitID = '' + self.ranTargetBranch = '' + self.eNBIPAddress = '' + self.eNBUserName = '' + self.eNBPassword = '' + self.eNBSourceCodePath = '' + self.eNB1IPAddress = '' + self.eNB1UserName = '' + self.eNB1Password = '' + self.eNB1SourceCodePath = '' + self.eNB2IPAddress = '' + self.eNB2UserName = '' + self.eNB2Password = '' + self.eNB2SourceCodePath = '' + self.forcedWorkspaceCleanup = False + self.imageKind = '' + self.eNB_instance = 0 + self.eNB_serverId = ['', '', ''] + self.yamlPath = ['', '', ''] + self.services = ['', '', ''] + self.nb_healthy = [0, 0, 0] + self.exitStatus = 0 + self.eNB_logFile = ['', '', ''] + + self.testCase_id = '' + + self.flexranCtrlDeployed = False + self.flexranCtrlIpAddress = '' + self.cli = '' + self.cliBuildOptions = '' + self.dockerfileprefix = '' + self.host = '' + self.allImagesSize = {} + self.collectInfo = {} + + self.pingContName = '' + self.pingOptions = '' + self.pingLossThreshold = '' + self.svrContName = '' + self.svrOptions = '' + self.cliContName = '' + self.cliOptions = '' + + self.imageToCopy = '' + self.registrySvrId = '' + self.testSvrId = '' + +#----------------------------------------------------------- +# Container management functions +#----------------------------------------------------------- + + def _createWorkspace(self, sshSession, password, sourcePath): + # on RedHat/CentOS .git extension is mandatory + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository.replace('git/', 'git') + else: + full_ran_repo_name = self.ranRepository + '.git' + sshSession.command('mkdir -p ' + sourcePath, '\$', 5) + sshSession.command('cd ' + sourcePath, '\$', 5) + sshSession.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + sshSession.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + sshSession.command('git config user.name "OAI Jenkins"', '\$', 5) + + sshSession.command('echo ' + password + ' | sudo -S git clean -x -d -ff', '\$', 30) + sshSession.command('mkdir -p cmake_targets/log', '\$', 5) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + sshSession.command('git checkout -f ' + self.ranCommitID, '\$', 30) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if (self.ranAllowMerge): + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + sshSession.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + sshSession.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + + def BuildImage(self, HTML): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + if self.eNB_serverId[self.eNB_instance] == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('Building on server: ' + lIpAddr) + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + + # Checking the hostname to get adapted on cli and dockerfileprefixes + mySSH.command('hostnamectl', '\$', 5) + result = re.search('Ubuntu|Red Hat', mySSH.getBefore()) + self.host = result.group(0) + if self.host == 'Ubuntu': + self.cli = 'docker' + self.dockerfileprefix = '.ubuntu18' + self.cliBuildOptions = '--no-cache' + elif self.host == 'Red Hat': + self.cli = 'sudo podman' + self.dockerfileprefix = '.rhel8.2' + self.cliBuildOptions = '--no-cache --disable-compression' + + # we always build the ran-build image with all targets + imageNames = [('ran-build', 'build')] + result = re.search('eNB', self.imageKind) + # Creating a tupple with the imageName and the DockerFile prefix pattern on obelix + if result is not None: + imageNames.append(('oai-enb', 'eNB')) + else: + result = re.search('gNB', self.imageKind) + if result is not None: + imageNames.append(('oai-gnb', 'gNB')) + else: + result = re.search('all', self.imageKind) + if result is not None: + imageNames.append(('oai-enb', 'eNB')) + imageNames.append(('oai-gnb', 'gNB')) + imageNames.append(('oai-lte-ue', 'lteUE')) + imageNames.append(('oai-nr-ue', 'nrUE')) + if self.host == 'Red Hat': + imageNames.append(('oai-physim', 'phySim')) + if self.host == 'Ubuntu': + imageNames.append(('oai-lte-ru', 'lteRU')) + + # Workaround for some servers, we need to erase completely the workspace + if self.forcedWorkspaceCleanup: + mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) + + self.testCase_id = HTML.testCase_id + + self._createWorkspace(mySSH, lPassWord, lSourcePath) + + # if asterix, copy the entitlement and subscription manager configurations + if self.host == 'Red Hat': + mySSH.command('mkdir -p tmp/ca/ tmp/entitlement/', '\$', 5) + mySSH.command('sudo cp /etc/rhsm/ca/redhat-uep.pem tmp/ca/', '\$', 5) + mySSH.command('sudo cp /etc/pki/entitlement/*.pem tmp/entitlement/', '\$', 5) + + baseImage = 'ran-base' + baseTag = 'develop' + forceBaseImageBuild = False + imageTag = 'develop' + if (self.ranAllowMerge): + imageTag = 'ci-temp' + if self.ranTargetBranch == 'develop': + mySSH.command('git diff HEAD..origin/develop -- docker/Dockerfile.base' + self.dockerfileprefix + ' | grep --colour=never -i INDEX', '\$', 5) + result = re.search('index', mySSH.getBefore()) + if result is not None: + forceBaseImageBuild = True + baseTag = 'ci-temp' + else: + forceBaseImageBuild = True + + # Let's remove any previous run artifacts if still there + mySSH.command(self.cli + ' image prune --force', '\$', 30) + if forceBaseImageBuild: + mySSH.command(self.cli + ' image rm ' + baseImage + ':' + baseTag + ' || true', '\$', 30) + for image,pattern in imageNames: + mySSH.command(self.cli + ' image rm ' + image + ':' + imageTag + ' || true', '\$', 30) + + # Build the base image only on Push Events (not on Merge Requests) + # On when the base image docker file is being modified. + if forceBaseImageBuild: + mySSH.command(self.cli + ' build ' + self.cliBuildOptions + ' --target ' + baseImage + ' --tag ' + baseImage + ':' + baseTag + ' --file docker/Dockerfile.base' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-base.log 2>&1', '\$', 1600) + # First verify if the base image was properly created. + status = True + mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + baseImage + ':' + baseTag, '\$', 5) + if mySSH.getBefore().count('o such image') != 0: + logging.error('\u001B[1m Could not build properly ran-base\u001B[0m') + status = False + else: + result = re.search('Size *= *(?P[0-9\-]+) *bytes', mySSH.getBefore()) + if result is not None: + imageSize = float(result.group('size')) + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ran-base size is ' + ('%.0f' % imageSize) + ' kbytes\u001B[0m') + self.allImagesSize['ran-base'] = str(round(imageSize,1)) + ' kbytes' + else: + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ran-base size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m') + self.allImagesSize['ran-base'] = str(round(imageSize,1)) + ' Mbytes' + else: + imageSize = imageSize / 1000 + logging.debug('\u001B[1m ran-base size is ' + ('%.3f' % imageSize) + ' Gbytes\u001B[0m') + self.allImagesSize['ran-base'] = str(round(imageSize,1)) + ' Gbytes' + else: + logging.debug('ran-base size is unknown') + # If the base image failed, no need to continue + if not status: + # Recover the name of the failed container? + mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5) + mySSH.command(self.cli + ' image prune --force', '\$', 30) + mySSH.close() + logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTabFooter(False) + sys.exit(1) + else: + # Recover build logs, for the moment only possible when build is successful + mySSH.command(self.cli + ' create --name test ' + baseImage + ':' + baseTag, '\$', 5) + mySSH.command('mkdir -p cmake_targets/log/ran-base', '\$', 5) + mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-base', '\$', 5) + mySSH.command(self.cli + ' rm -f test', '\$', 5) + + # Build the target image(s) + for image,pattern in imageNames: + # the archived Dockerfiles have "ran-base:latest" as base image + # we need to update them with proper tag + mySSH.command('sed -i -e "s#' + baseImage + ':latest#' + baseImage + ':' + baseTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5) + if image != 'ran-build': + mySSH.command('sed -i -e "s#' + "ran-build" + ':latest#' + "ran-build" + ':' + imageTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5) + mySSH.command(self.cli + ' build ' + self.cliBuildOptions + ' --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200) + # split the log + mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5) + mySSH.command('python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/' + image + '.log', '\$', 5) + # checking the status of the build + mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + image + ':' + imageTag, '\$', 5) + if mySSH.getBefore().count('o such image') != 0: + logging.error('\u001B[1m Could not build properly ' + image + '\u001B[0m') + status = False + # Here we should check if the last container corresponds to a failed command and destroy it + mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5) + self.allImagesSize[image] = 'N/A -- Build Failed' + else: + result = re.search('Size *= *(?P[0-9\-]+) *bytes', mySSH.getBefore()) + if result is not None: + imageSize = float(result.group('size')) + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.0f' % imageSize) + ' kbytes\u001B[0m') + self.allImagesSize[image] = str(round(imageSize,1)) + ' kbytes' + else: + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m') + self.allImagesSize[image] = str(round(imageSize,1)) + ' Mbytes' + else: + imageSize = imageSize / 1000 + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.3f' % imageSize) + ' Gbytes\u001B[0m') + self.allImagesSize[image] = str(round(imageSize,1)) + ' Gbytes' + else: + logging.debug('ran-base size is unknown') + self.allImagesSize[image] = 'unknown' + # Now pruning dangling images in between target builds + mySSH.command(self.cli + ' image prune --force', '\$', 30) + + # Analyzing the logs + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + mySSH.command('rm -f build_log_' + self.testCase_id + '.zip || true', '\$', 5) + if (os.path.isfile('./build_log_' + self.testCase_id + '.zip')): + os.remove('./build_log_' + self.testCase_id + '.zip') + if (os.path.isdir('./build_log_' + self.testCase_id)): + shutil.rmtree('./build_log_' + self.testCase_id) + mySSH.command('zip -r -qq build_log_' + self.testCase_id + '.zip build_log_' + self.testCase_id, '\$', 5) + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '.zip', '.') + mySSH.command('rm -f build_log_' + self.testCase_id + '.zip','\$', 5) + # Remove all intermediate build images + if self.ranAllowMerge and forceBaseImageBuild: + mySSH.command(self.cli + ' image rm ' + baseImage + ':' + baseTag + ' || true', '\$', 30) + mySSH.command(self.cli + ' image rm ran-build:' + imageTag + ' || true','\$', 5) + mySSH.close() + ZipFile('build_log_' + self.testCase_id + '.zip').extractall('.') + + #Trying to identify the errors and warnings for each built images + imageNames1 = imageNames + base = ('ran-base','ran') + imageNames1.insert(0, base) + for image,pattern in imageNames1: + files = {} + file_list = [f for f in os.listdir('build_log_' + self.testCase_id + '/' + image) if os.path.isfile(os.path.join('build_log_' + self.testCase_id + '/' + image, f)) and f.endswith('.txt')] + for fil in file_list: + errorandwarnings = {} + warningsNo = 0 + errorsNo = 0 + with open('build_log_{}/{}/{}'.format(self.testCase_id,image,fil), mode='r') as inputfile: + for line in inputfile: + result = re.search(' ERROR ', str(line)) + if result is not None: + errorsNo += 1 + result = re.search(' error:', str(line)) + if result is not None: + errorsNo += 1 + result = re.search(' WARNING ', str(line)) + if result is not None: + warningsNo += 1 + result = re.search(' warning:', str(line)) + if result is not None: + warningsNo += 1 + errorandwarnings['errors'] = errorsNo + errorandwarnings['warnings'] = warningsNo + errorandwarnings['status'] = status + files[fil] = errorandwarnings + # Let analyze the target image creation part + if os.path.isfile('build_log_{}/{}.log'.format(self.testCase_id,image)): + errorandwarnings = {} + with open('build_log_{}/{}.log'.format(self.testCase_id,image), mode='r') as inputfile: + startOfTargetImageCreation = False + buildStatus = False + for line in inputfile: + result = re.search('FROM .* [aA][sS] ' + image + '$', str(line)) + if result is not None: + startOfTargetImageCreation = True + if startOfTargetImageCreation: + result = re.search('Successfully tagged ' + image + ':', str(line)) + if result is not None: + buildStatus = True + result = re.search('COMMIT ' + image + ':', str(line)) + if result is not None: + buildStatus = True + inputfile.close() + if buildStatus: + errorandwarnings['errors'] = 0 + else: + errorandwarnings['errors'] = 1 + errorandwarnings['warnings'] = 0 + errorandwarnings['status'] = buildStatus + files['Target Image Creation'] = errorandwarnings + self.collectInfo[image] = files + + if status: + logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) + else: + logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) + HTML.CreateHtmlTabFooter(False) + sys.exit(1) + + def Copy_Image_to_Test_Server(self, HTML): + imageTag = 'develop' + if (self.ranAllowMerge): + imageTag = 'ci-temp' + + lSsh = SSH.SSHConnection() + # Going to the Docker Registry server + if self.registrySvrId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + elif self.registrySvrId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + elif self.registrySvrId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSsh.open(lIpAddr, lUserName, lPassWord) + lSsh.command('docker save ' + self.imageToCopy + ':' + imageTag + ' | gzip > ' + self.imageToCopy + '-' + imageTag + '.tar.gz', '\$', 60) + lSsh.copyin(lIpAddr, lUserName, lPassWord, '~/' + self.imageToCopy + '-' + imageTag + '.tar.gz', '.') + lSsh.command('rm ' + self.imageToCopy + '-' + imageTag + '.tar.gz', '\$', 60) + lSsh.close() + + # Going to the Test Server + if self.testSvrId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + elif self.testSvrId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + elif self.testSvrId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSsh.open(lIpAddr, lUserName, lPassWord) + lSsh.copyout(lIpAddr, lUserName, lPassWord, './' + self.imageToCopy + '-' + imageTag + '.tar.gz', '~') + lSsh.command('docker rmi ' + self.imageToCopy + ':' + imageTag, '\$', 10) + lSsh.command('docker load < ' + self.imageToCopy + '-' + imageTag + '.tar.gz', '\$', 60) + lSsh.command('rm ' + self.imageToCopy + '-' + imageTag + '.tar.gz', '\$', 60) + lSsh.close() + + if os.path.isfile('./' + self.imageToCopy + '-' + imageTag + '.tar.gz'): + os.remove('./' + self.imageToCopy + '-' + imageTag + '.tar.gz') + + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def DeployObject(self, HTML, EPC): + if self.eNB_serverId[self.eNB_instance] == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('\u001B[1m Deploying OAI Object on server: ' + lIpAddr + '\u001B[0m') + + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + + self._createWorkspace(mySSH, lPassWord, lSourcePath) + + mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) + mySSH.command('cp docker-compose.yml ci-docker-compose.yml', '\$', 5) + imageTag = 'develop' + if (self.ranAllowMerge): + imageTag = 'ci-temp' + mySSH.command('sed -i -e "s/image: oai-enb:latest/image: oai-enb:' + imageTag + '/" ci-docker-compose.yml', '\$', 2) + mySSH.command('sed -i -e "s/image: oai-gnb:latest/image: oai-gnb:' + imageTag + '/" ci-docker-compose.yml', '\$', 2) + localMmeIpAddr = EPC.MmeIPAddress + mySSH.command('sed -i -e "s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/" ci-docker-compose.yml', '\$', 2) +# if self.flexranCtrlDeployed: +# mySSH.command('sed -i -e "s/FLEXRAN_ENABLED:.*/FLEXRAN_ENABLED: \'yes\'/" ci-docker-compose.yml', '\$', 2) +# mySSH.command('sed -i -e "s/CI_FLEXRAN_CTL_IP_ADDR/' + self.flexranCtrlIpAddress + '/" ci-docker-compose.yml', '\$', 2) +# else: +# mySSH.command('sed -i -e "s/FLEXRAN_ENABLED:.*$/FLEXRAN_ENABLED: \'no\'/" ci-docker-compose.yml', '\$', 2) +# mySSH.command('sed -i -e "s/CI_FLEXRAN_CTL_IP_ADDR/127.0.0.1/" ci-docker-compose.yml', '\$', 2) + # Currently support only one + mySSH.command('docker-compose --file ci-docker-compose.yml config --services | sed -e "s@^@service=@" 2>&1', '\$', 10) + result = re.search('service=(?P[a-zA-Z0-9\_]+)', mySSH.getBefore()) + if result is not None: + svcName = result.group('svc_name') + mySSH.command('docker-compose --file ci-docker-compose.yml up -d ' + svcName, '\$', 10) + + # Checking Status + mySSH.command('docker-compose --file ci-docker-compose.yml config', '\$', 5) + result = re.search('container_name: (?P[a-zA-Z0-9\-\_]+)', mySSH.getBefore()) + unhealthyNb = 0 + healthyNb = 0 + startingNb = 0 + containerName = '' + if result is not None: + containerName = result.group('container_name') + time.sleep(5) + cnt = 0 + while (cnt < 3): + mySSH.command('docker inspect --format="{{.State.Health.Status}}" ' + containerName, '\$', 5) + unhealthyNb = mySSH.getBefore().count('unhealthy') + healthyNb = mySSH.getBefore().count('healthy') - unhealthyNb + startingNb = mySSH.getBefore().count('starting') + if healthyNb == 1: + cnt = 10 + else: + time.sleep(10) + cnt += 1 + logging.debug(' -- ' + str(healthyNb) + ' healthy container(s)') + logging.debug(' -- ' + str(unhealthyNb) + ' unhealthy container(s)') + logging.debug(' -- ' + str(startingNb) + ' still starting container(s)') + + status = False + if healthyNb == 1: + cnt = 0 + while (cnt < 20): + mySSH.command('docker logs ' + containerName + ' | egrep --text --color=never -i "wait|sync|Starting"', '\$', 30) + result = re.search('got sync|Starting F1AP at CU', mySSH.getBefore()) + if result is None: + time.sleep(6) + cnt += 1 + else: + cnt = 100 + status = True + logging.info('\u001B[1m Deploying OAI object Pass\u001B[0m') + time.sleep(10) + mySSH.close() + + self.testCase_id = HTML.testCase_id + self.eNB_logFile[self.eNB_instance] = 'enb_' + self.testCase_id + '.log' + + if status: + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + else: + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) + + def UndeployObject(self, HTML, RAN): + if self.eNB_serverId[self.eNB_instance] == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('\u001B[1m Deploying OAI Object on server: ' + lIpAddr + '\u001B[0m') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) + # Currently support only one + mySSH.command('docker-compose --file ci-docker-compose.yml config', '\$', 5) + result = re.search('container_name: (?P[a-zA-Z0-9\-\_]+)', mySSH.getBefore()) + if self.eNB_logFile[self.eNB_instance] == '': + self.eNB_logFile[self.eNB_instance] = 'enb_' + HTML.testCase_id + '.log' + if result is not None: + containerName = result.group('container_name') + mySSH.command('docker kill --signal INT ' + containerName, '\$', 30) + time.sleep(5) + mySSH.command('docker logs ' + containerName + ' > ' + lSourcePath + '/cmake_targets/' + self.eNB_logFile[self.eNB_instance], '\$', 30) + mySSH.command('docker rm -f ' + containerName, '\$', 30) + # Forcing the down now to remove the networks and any artifacts + mySSH.command('docker-compose --file ci-docker-compose.yml down', '\$', 5) + + mySSH.close() + + # Analyzing log file! + copyin_res = mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + self.eNB_logFile[self.eNB_instance], '.') + nodeB_prefix = 'e' + if (copyin_res == -1): + HTML.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + else: + logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + self.eNB_logFile[self.eNB_instance]) + logStatus = RAN.AnalyzeLogFile_eNB(self.eNB_logFile[self.eNB_instance], HTML) + if (logStatus < 0): + HTML.CreateHtmlTestRow(RAN.runtime_stats, 'KO', logStatus) + else: + HTML.CreateHtmlTestRow(RAN.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) + # all the xNB run logs shall be on the server 0 for logCollecting + if self.eNB_serverId[self.eNB_instance] != '0': + mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + self.eNB_logFile[self.eNB_instance], self.eNBSourceCodePath + '/cmake_targets/') + logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m') + + def DeployGenObject(self, HTML): + self.exitStatus = 0 + logging.info('\u001B[1m Checking Services to deploy\u001B[0m') + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose config --services' + logging.debug(cmd) + try: + listServices = subprocess.check_output(cmd, shell=True, universal_newlines=True) + except Exception as e: + self.exitStatus = 1 + HTML.CreateHtmlTestRow('SVC not Found', 'KO', CONST.ALL_PROCESSES_OK) + return + for reqSvc in self.services[0].split(' '): + res = re.search(reqSvc, listServices) + if res is None: + logging.error(reqSvc + ' not found in specified docker-compose') + self.exitStatus = 1 + if (self.exitStatus == 1): + HTML.CreateHtmlTestRow('SVC not Found', 'KO', CONST.ALL_PROCESSES_OK) + return + + if (self.ranAllowMerge): + cmd = 'cd ' + self.yamlPath[0] + ' && sed -e "s@develop@ci-temp@" docker-compose.y*ml > docker-compose-ci.yml' + else: + cmd = 'cd ' + self.yamlPath[0] + ' && sed -e "s@develop@develop@" docker-compose.y*ml > docker-compose-ci.yml' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml up -d ' + self.services[0] + logging.debug(cmd) + try: + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100) + except Exception as e: + self.exitStatus = 1 + logging.error('Could not deploy') + HTML.CreateHtmlTestRow('Could not deploy', 'KO', CONST.ALL_PROCESSES_OK) + return + + logging.info('\u001B[1m Checking if all deployed healthy\u001B[0m') + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml ps -a' + count = 0 + healthy = 0 + while (count < 10): + count += 1 + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) + healthy = 0 + for state in deployStatus.split('\n'): + res = re.search('Up \(healthy\)', state) + if res is not None: + healthy += 1 + if healthy == self.nb_healthy[0]: + count = 100 + else: + time.sleep(10) + + if count == 100 and healthy == self.nb_healthy[0]: + HTML.CreateHtmlTestRow('n/a', 'OK', CONST.ALL_PROCESSES_OK) + logging.info('\u001B[1m Deploying OAI Object(s) PASS\u001B[0m') + else: + self.exitStatus = 1 + HTML.CreateHtmlTestRow('Could not deploy in time', 'KO', CONST.ALL_PROCESSES_OK) + logging.error('\u001B[1m Deploying OAI Object(s) FAILED\u001B[0m') + + def UndeployGenObject(self, HTML): + self.exitStatus = 0 + + if (self.ranAllowMerge): + cmd = 'cd ' + self.yamlPath[0] + ' && sed -e "s@develop@ci-temp@" docker-compose.y*ml > docker-compose-ci.yml' + else: + cmd = 'cd ' + self.yamlPath[0] + ' && sed -e "s@develop@develop@" docker-compose.y*ml > docker-compose-ci.yml' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + + # if the containers are running, recover the logs! + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml ps --all' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) + anyLogs = False + for state in deployStatus.split('\n'): + res = re.search('Name|----------', state) + if res is not None: + continue + if len(state) == 0: + continue + res = re.search('^(?P[a-zA-Z0-9\-\_]+) ', state) + if res is not None: + anyLogs = True + cName = res.group('container_name') + cmd = 'cd ' + self.yamlPath[0] + ' && docker logs ' + cName + ' > ' + cName + '.log 2>&1' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) + if anyLogs: + cmd = 'mkdir -p ../cmake_targets/log && mv ' + self.yamlPath[0] + '/*.log ../cmake_targets/log' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml down' + logging.debug(cmd) + try: + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100) + except Exception as e: + self.exitStatus = 1 + logging.error('Could not undeploy') + HTML.CreateHtmlTestRow('Could not undeploy', 'KO', CONST.ALL_PROCESSES_OK) + logging.error('\u001B[1m Undeploying OAI Object(s) FAILED\u001B[0m') + return + + HTML.CreateHtmlTestRow('n/a', 'OK', CONST.ALL_PROCESSES_OK) + logging.info('\u001B[1m Undeploying OAI Object(s) PASS\u001B[0m') + + def PingFromContainer(self, HTML): + self.exitStatus = 0 + cmd = 'mkdir -p ../cmake_targets/log' + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + + cmd = 'docker exec ' + self.pingContName + ' /bin/bash -c "ping ' + self.pingOptions + '" 2>&1 | tee ../cmake_targets/log/ping_' + HTML.testCase_id + '.log || true' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100) + + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', deployStatus) + if result is None: + self.PingExit(HTML, False, 'Packet Loss Not Found') + return + + packetloss = result.group('packetloss') + if float(packetloss) == 100: + self.PingExit(HTML, False, 'Packet Loss is 100%') + return + + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', deployStatus) + if result is None: + self.PingExit(HTML, False, 'Ping RTT_Min RTT_Avg RTT_Max Not Found!') + return + + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + + message = 'ping result\n' + message += ' ' + pal_msg + '\n' + message += ' ' + min_msg + '\n' + message += ' ' + avg_msg + '\n' + message += ' ' + max_msg + '\n' + packetLossOK = True + if float(packetloss) > float(self.pingLossThreshold): + message += '\nPacket Loss too high' + packetLossOK = False + elif float(packetloss) > 0: + message += '\nPacket Loss is not 0%' + self.PingExit(HTML, packetLossOK, message) + + if packetLossOK: + logging.debug('\u001B[1;37;44m ping result \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + logging.info('\u001B[1m Ping Test PASS\u001B[0m') + + def PingExit(self, HTML, status, message): + html_queue = SimpleQueue() + html_cell = '
UE\n' + message + '
' + html_queue.put(html_cell) + if status: + HTML.CreateHtmlTestRowQueue(self.pingOptions, 'OK', 1, html_queue) + else: + self.exitStatus = 1 + logging.error('\u001B[1;37;41m ' + message + ' \u001B[0m') + HTML.CreateHtmlTestRowQueue(self.pingOptions, 'KO', 1, html_queue) + + def IperfFromContainer(self, HTML): + self.exitStatus = 0 + + cmd = 'mkdir -p ../cmake_targets/log' + logStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + + # Start the server process + cmd = 'docker exec -d ' + self.svrContName + ' /bin/bash -c "nohup iperf ' + self.svrOptions + ' > /tmp/iperf_server.log 2>&1" || true' + logging.debug(cmd) + serverStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + time.sleep(5) + + # Start the client process + cmd = 'docker exec ' + self.cliContName + ' /bin/bash -c "iperf ' + self.cliOptions + '" 2>&1 | tee ../cmake_targets/log/iperf_client_' + HTML.testCase_id + '.log || true' + logging.debug(cmd) + clientStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100) + + # Stop the server process + cmd = 'docker exec ' + self.svrContName + ' /bin/bash -c "pkill iperf" || true' + logging.debug(cmd) + serverStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + time.sleep(5) + cmd = 'docker cp ' + self.svrContName + ':/tmp/iperf_server.log ../cmake_targets/log/iperf_server_' + HTML.testCase_id + '.log' + logging.debug(cmd) + serverStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) + + # Analyze client output + result = re.search('Server Report:', clientStatus) + if result is None: + result = re.search('read failed: Connection refused', clientStatus) + if result is not None: + message = 'Could not connect to iperf server!' + else: + message = 'Server Report and Connection refused Not Found!' + self.IperfExit(HTML, False, message) + logging.error('\u001B[1;37;41m Iperf Test FAIL\u001B[0m') + return + + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', self.cliOptions) + if result is not None: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', self.cliOptions) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', self.cliOptions) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + + reportLine = None + reportLineFound = False + for iLine in clientStatus.split('\n'): + if reportLineFound: + reportLine = iLine + reportLineFound = False + res = re.search('Server Report:', iLine) + if res is not None: + reportLineFound = True + result = None + if reportLine is not None: + result = re.search('(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/ ..\d+) +(\((?P[0-9\.]+)%\))', reportLine) + iperfStatus = True + if result is not None: + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + jitter = result.group('jitter') + logging.debug('\u001B[1;37;44m iperf result \u001B[0m') + iperfStatus = True + msg = 'Req Bitrate : ' + req_bandwidth + '\n' + logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') + if bitrate is not None: + msg += 'Bitrate : ' + bitrate + '\n' + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) + if result is not None: + actual_bw = float(str(result.group('real_bw'))) + result = re.search('[0-9\.]+ K', bitrate) + if result is not None: + actual_bw = actual_bw * 1000 + result = re.search('[0-9\.]+ M', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000 + br_loss = 100 * actual_bw / req_bw + if br_loss < 90: + iperfStatus = False + bitperf = '%.2f ' % br_loss + msg += 'Bitrate Perf: ' + bitperf + '%\n' + logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') + if packetloss is not None: + msg += 'Packet Loss : ' + packetloss + '%\n' + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + if float(packetloss) > float(5): + msg += 'Packet Loss too high!\n' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + iperfStatus = False + if jitter is not None: + msg += 'Jitter : ' + jitter + '\n' + logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') + self.IperfExit(HTML, iperfStatus, msg) + else: + iperfStatus = False + logging.error('problem?') + self.IperfExit(HTML, iperfStatus, 'problem?') + if iperfStatus: + logging.info('\u001B[1m Iperf Test PASS\u001B[0m') + else: + logging.error('\u001B[1;37;41m Iperf Test FAIL\u001B[0m') + + def IperfExit(self, HTML, status, message): + html_queue = SimpleQueue() + html_cell = '
UE\n' + message + '
' + html_queue.put(html_cell) + if status: + HTML.CreateHtmlTestRowQueue(self.cliOptions, 'OK', 1, html_queue) + else: + self.exitStatus = 1 + HTML.CreateHtmlTestRowQueue(self.cliOptions, 'KO', 1, html_queue) + + def CheckAndAddRoute(self, svrName, ipAddr, userName, password): + logging.debug('Checking IP routing on ' + svrName) + mySSH = SSH.SSHConnection() + if svrName == 'porcepix': + mySSH.open(ipAddr, userName, password) + # Check if route to asterix gnb exists + mySSH.command('ip route | grep --colour=never "192.168.68.64/26"', '\$', 10) + result = re.search('192.168.18.194', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.68.64/26 via 192.168.18.194 dev eno1', '\$', 10) + # Check if route to obelix enb exists + mySSH.command('ip route | grep --colour=never "192.168.68.128/26"', '\$', 10) + result = re.search('192.168.18.193', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.68.128/26 via 192.168.18.193 dev eno1', '\$', 10) + # Check if route to nepes gnb exists + mySSH.command('ip route | grep --colour=never "192.168.68.192/26"', '\$', 10) + result = re.search('192.168.18.209', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.68.192/26 via 192.168.18.209 dev eno1', '\$', 10) + # Check if forwarding is enabled + mySSH.command('sysctl net.ipv4.conf.all.forwarding', '\$', 10) + result = re.search('net.ipv4.conf.all.forwarding = 1', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S sysctl net.ipv4.conf.all.forwarding=1', '\$', 10) + # Check if iptables forwarding is accepted + mySSH.command('echo ' + password + ' | sudo -S iptables -L FORWARD', '\$', 10) + result = re.search('Chain FORWARD .*policy ACCEPT', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S iptables -P FORWARD ACCEPT', '\$', 10) + mySSH.close() + if svrName == 'asterix': + mySSH.open(ipAddr, userName, password) + # Check if route to porcepix epc exists + mySSH.command('ip route | grep --colour=never "192.168.61.192/26"', '\$', 10) + result = re.search('192.168.18.210', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.61.192/26 via 192.168.18.210 dev em1', '\$', 10) + # Check if route to porcepix cn5g exists + mySSH.command('ip route | grep --colour=never "192.168.70.128/26"', '\$', 10) + result = re.search('192.168.18.210', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.70.128/26 via 192.168.18.210 dev em1', '\$', 10) + # Check if X2 route to obelix enb exists + mySSH.command('ip route | grep --colour=never "192.168.68.128/26"', '\$', 10) + result = re.search('192.168.18.193', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.68.128/26 via 192.168.18.193 dev em1', '\$', 10) + # Check if forwarding is enabled + mySSH.command('sysctl net.ipv4.conf.all.forwarding', '\$', 10) + result = re.search('net.ipv4.conf.all.forwarding = 1', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S sysctl net.ipv4.conf.all.forwarding=1', '\$', 10) + # Check if iptables forwarding is accepted + mySSH.command('echo ' + password + ' | sudo -S iptables -L FORWARD', '\$', 10) + result = re.search('Chain FORWARD .*policy ACCEPT', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S iptables -P FORWARD ACCEPT', '\$', 10) + mySSH.close() + if svrName == 'obelix': + mySSH.open(ipAddr, userName, password) + # Check if route to porcepix epc exists + mySSH.command('ip route | grep --colour=never "192.168.61.192/26"', '\$', 10) + result = re.search('192.168.18.210', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.61.192/26 via 192.168.18.210 dev eno1', '\$', 10) + # Check if X2 route to asterix gnb exists + mySSH.command('ip route | grep --colour=never "192.168.68.64/26"', '\$', 10) + result = re.search('192.168.18.194', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.68.64/26 via 192.168.18.194 dev eno1', '\$', 10) + # Check if X2 route to nepes gnb exists + mySSH.command('ip route | grep --colour=never "192.168.68.192/26"', '\$', 10) + result = re.search('192.168.18.209', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.68.192/26 via 192.168.18.209 dev eno1', '\$', 10) + # Check if forwarding is enabled + mySSH.command('sysctl net.ipv4.conf.all.forwarding', '\$', 10) + result = re.search('net.ipv4.conf.all.forwarding = 1', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S sysctl net.ipv4.conf.all.forwarding=1', '\$', 10) + # Check if iptables forwarding is accepted + mySSH.command('echo ' + password + ' | sudo -S iptables -L FORWARD', '\$', 10) + result = re.search('Chain FORWARD .*policy ACCEPT', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S iptables -P FORWARD ACCEPT', '\$', 10) + mySSH.close() + if svrName == 'nepes': + mySSH.open(ipAddr, userName, password) + # Check if route to porcepix epc exists + mySSH.command('ip route | grep --colour=never "192.168.61.192/26"', '\$', 10) + result = re.search('192.168.18.210', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.61.192/26 via 192.168.18.210 dev enp0s31f6', '\$', 10) + # Check if X2 route to obelix enb exists + mySSH.command('ip route | grep --colour=never "192.168.68.128/26"', '\$', 10) + result = re.search('192.168.18.193', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.68.128/26 via 192.168.18.193 dev enp0s31f6', '\$', 10) + # Check if forwarding is enabled + mySSH.command('sysctl net.ipv4.conf.all.forwarding', '\$', 10) + result = re.search('net.ipv4.conf.all.forwarding = 1', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S sysctl net.ipv4.conf.all.forwarding=1', '\$', 10) + # Check if iptables forwarding is accepted + mySSH.command('echo ' + password + ' | sudo -S iptables -L FORWARD', '\$', 10) + result = re.search('Chain FORWARD .*policy ACCEPT', mySSH.getBefore()) + if result is None: + mySSH.command('echo ' + password + ' | sudo -S iptables -P FORWARD ACCEPT', '\$', 10) + mySSH.close() diff --git a/ci-scripts/cls_cots_ue.py b/ci-scripts/cls_cots_ue.py index 6954aa3927..59c2713b47 100644 --- a/ci-scripts/cls_cots_ue.py +++ b/ci-scripts/cls_cots_ue.py @@ -27,61 +27,111 @@ # pexpect #--------------------------------------------------------------------- +#to use isfile +import os +import sys #to use logging.info() import logging #to create a SSH object locally in the methods import sshconnection #time.sleep import time +#to load cots_ue dictionary +import yaml class CotsUe: - def __init__(self,model,UEIPAddr,UEUserName,UEPassWord): - self.model = model - self.UEIPAddr = UEIPAddr - self.UEUserName = UEUserName - self.UEPassWord = UEPassWord - self.runargs = '' #on of off to toggle airplane mode on/off + def __init__(self,ADBIPAddr,ADBUserName,ADBPassWord): + self.cots_id = '' #cots id from yaml oppo, s10 etc... + self.ADBIPAddr = ADBIPAddr + self.ADBUserName = ADBUserName + self.ADBPassWord = ADBPassWord + self.cots_run_mode = '' #on of off to toggle airplane mode on/off + self.__cots_cde_dict_file = 'cots_ue_ctl.yaml' self.__SetAirplaneRetry = 3 + #-----------------$ #PUBLIC Methods$ #-----------------$ def Check_Airplane(self): mySSH = sshconnection.SSHConnection() - mySSH.open(self.UEIPAddr, self.UEUserName, self.UEPassWord) - status=mySSH.cde_check_value('sudo adb shell settings get global airplane_mode_on ', ['0','1'],5) + mySSH.open(self.ADBIPAddr, self.ADBUserName, self.ADBPassWord) + status=mySSH.cde_check_value('adb shell settings get global airplane_mode_on ', ['0','1'],5) mySSH.close() return status - - def Set_Airplane(self,target_state_str): - mySSH = sshconnection.SSHConnection() - mySSH.open(self.UEIPAddr, self.UEUserName, self.UEPassWord) - mySSH.command('sudo adb start-server','$',5) - logging.info("Toggling COTS UE Airplane mode to : "+target_state_str) - current_state = self.Check_Airplane() - if target_state_str.lower()=="on": - target_state=1 + #simply check if the device id exists in the dictionary + #returns true if it exists, false otherwise + def Check_Exists(self,target_id): + #load cots commands dictionary + if (os.path.isfile(self.__cots_cde_dict_file)): + yaml_file=self.__cots_cde_dict_file + elif (os.path.isfile('ci-scripts/'+self.__cots_cde_dict_file)): + yaml_file='ci-scripts/'+self.__cots_cde_dict_file else: - target_state=0 - if current_state != target_state: - #toggle state - retry = 0 - while (current_state!=target_state) and (retry < self.__SetAirplaneRetry): - mySSH.command('sudo adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS', '\$', 5) - mySSH.command('sudo adb shell input keyevent 20', '\$', 5) - mySSH.command('sudo adb shell input tap 968 324', '\$', 5) - time.sleep(1) - current_state = self.Check_Airplane() - retry+=1 + logging.error("COTS UE dictionary yaml file cannot be found") + sys.exit("COTS UE dictionary yaml file cannot be found") + + #load cots commands dictionary + with open(yaml_file,'r') as file: + cots_ue_ctl = yaml.load(file,Loader=yaml.FullLoader) + #check if ue id is in the dictionary + if target_id in cots_ue_ctl: + return True + else: + return False + + def Set_Airplane(self, target_id, target_state_str): + #loading cots commands dictionary + + if (os.path.isfile(self.__cots_cde_dict_file)): + yaml_file=self.__cots_cde_dict_file + elif (os.path.isfile('ci-scripts/'+self.__cots_cde_dict_file)): + yaml_file='ci-scripts/'+self.__cots_cde_dict_file + else: + logging.error("COTS UE dictionary yaml file cannot be found") + sys.exit("COTS UE dictionary yaml file cannot be found") + + #load cots commands dictionary + with open(yaml_file,'r') as file: + cots_ue_ctl = yaml.load(file,Loader=yaml.FullLoader) + #check if ue id is in the dictionary + if target_id in cots_ue_ctl: + mySSH = sshconnection.SSHConnection() + mySSH.open(self.ADBIPAddr, self.ADBUserName, self.ADBPassWord) + logging.info(str(self.ADBIPAddr)+' '+str(self.ADBUserName)+' '+str(self.ADBPassWord)) + mySSH.command('adb start-server','\$',5) + mySSH.command('adb devices','\$',5) + logging.info("Toggling COTS UE Airplane mode to : "+target_state_str) + #get current state + current_state = self.Check_Airplane() + if target_state_str.lower()=="on": + target_state=1 + else: + target_state=0 if current_state != target_state: - logging.error("ATTENTION : Could not toggle to : "+target_state_str) - logging.error("Current state is : "+ str(current_state)) + #toggle state + retry = 0 + while (current_state!=target_state) and (retry < self.__SetAirplaneRetry): + #loop over the command list from dictionary for the selected ue, to switch to required state + for i in range (0,len(cots_ue_ctl[target_id])): + mySSH.command(cots_ue_ctl[target_id][i], '\$', 5) + time.sleep(1) + current_state = self.Check_Airplane() + retry+=1 + #could not toggle despite the retry + if current_state != target_state: + logging.error("ATTENTION : Could not toggle to : "+target_state_str) + logging.error("Current state is : "+ str(current_state)) + else: + logging.info("Airplane mode is already "+ target_state_str) + mySSH.command('adb kill-server','\$',5) + mySSH.close() + #ue id is NOT in the dictionary else: - print("Airplane mode is already "+ target_state_str) - mySSH.command('sudo adb kill-server','$',5) - mySSH.close() + logging.error("COTS UE Id from XML could not be found in UE YAML dictionary " + self.__cots_cde_dict_file) + sys.exit("COTS UE Id from XML could not be found in UE YAML dictionary " + self.__cots_cde_dict_file) diff --git a/ci-scripts/cls_log_mgt.py b/ci-scripts/cls_log_mgt.py new file mode 100644 index 0000000000..7fb45ed3ea --- /dev/null +++ b/ci-scripts/cls_log_mgt.py @@ -0,0 +1,107 @@ +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Required Python Version +# Python 3.x +# +#--------------------------------------------------------------------- + +#USAGE: +# log=Log_Mgt(Username,IPAddress,Password,Path) +# log.LogRotation() + + + + +import re +import subprocess +import logging +import math + +class Log_Mgt: + + def __init__(self,Username, IPAddress,Password,Path): + self.Username=Username + self.IPAddress=IPAddress + self.Password=Password + self.path=Path + +#-----------------$ +#PRIVATE# Methods$ +#-----------------$ + + + def __CheckAvailSpace(self): + HOST=self.Username+'@'+self.IPAddress + COMMAND="df "+ self.path + ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + result = ssh.stdout.readlines() + s=result[1].decode('utf-8').rstrip()#result[1] is the second line with the results we are looking for + tmp=s.split() + return tmp[3] #return avail space from the line + + def __GetOldestFile(self): + HOST=self.Username+'@'+self.IPAddress + COMMAND="ls -rtl "+ self.path #-rtl will bring oldest file on top + ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + result = ssh.stdout.readlines() + s=result[1].decode('utf-8').rstrip() + tmp=s.split() + return tmp[8]#return filename from the line + + + def __AvgSize(self): + HOST=self.Username+'@'+self.IPAddress + COMMAND="ls -rtl "+ self.path + ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + result = ssh.stdout.readlines() + if len(result)>1: #at least 1 file present + total_size=0 + for i in range(1,len(result)): + s=result[i].decode('utf-8').rstrip() + tmp=s.split() + total_size+=int(tmp[4]) #get filesize + return math.floor(total_size/(len(result)-1)) #compute average file/artifact size + else:#empty,no files + return 0 + + +#-----------------$ +#PUBLIC Methods$ +#-----------------$ + + + def LogRotation(self): + avail_space =int(self.__CheckAvailSpace())*1000 #avail space in target folder, initially displayed in Gb + avg_size=self.__AvgSize() #average size of artifacts in the target folder + logging.debug("Avail Space : " + str(avail_space) + " / Artifact Avg Size : " + str(avg_size)) + if avail_space < 2*avg_size: #reserved space is 2x artifact file ; oldest file will be deleted + oldestfile=self.__GetOldestFile() + HOST=self.Username+'@'+self.IPAddress + COMMAND="echo " + self.Password + " | sudo -S rm "+ self.path + "/" + oldestfile + logging.debug(COMMAND) + ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + else: + logging.debug("Still some space left for artifacts storage") + + + + diff --git a/ci-scripts/cls_module_ue.py b/ci-scripts/cls_module_ue.py new file mode 100644 index 0000000000..cabd0a045d --- /dev/null +++ b/ci-scripts/cls_module_ue.py @@ -0,0 +1,202 @@ +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Required Python Version +# Python 3.x +# +#--------------------------------------------------------------------- + +#to use isfile +import os +import sys +import logging +#to create a SSH object locally in the methods +import sshconnection +#time.sleep +import time + + +import re +import subprocess + +from datetime import datetime + +#for log rotation mgt +import cls_log_mgt + +class Module_UE: + + def __init__(self,Module): + #create attributes as in the Module dictionary + for k, v in Module.items(): + setattr(self, k, v) + self.UEIPAddress = "" + #dictionary linking command names and related module scripts + self.cmd_dict= {"wup": self.WakeupScript,"detach":self.DetachScript}#dictionary of function scripts + self.ue_trace='' + + + +#-----------------$ +#PUBLIC Methods$ +#-----------------$ + + #this method checks if the specified Process is running on the server hosting the module + #if not it will be started + def CheckCMProcess(self,CNType): + HOST=self.HostUsername+'@'+self.HostIPAddress + COMMAND="ps aux | grep --colour=never " + self.Process['Name'] + " | grep -v grep " + logging.debug(COMMAND) + ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + result = ssh.stdout.readlines() + if len(result)!=0: + logging.debug(self.Process['Name'] + " process found") + return True + else:#start process and check again + logging.debug(self.Process['Name'] + " process NOT found") + #starting the process + logging.debug('Starting ' + self.Process['Name']) + mySSH = sshconnection.SSHConnection() + mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword) + mySSH.command('echo $USER; echo ' + self.HostPassword + ' | nohup sudo -S ' + self.Process['Cmd'] + ' ' + self.Process['Apn'][CNType] + ' > /dev/null 2>&1 &','\$',5) + mySSH.close() + #checking the process + time.sleep(5) + HOST=self.HostUsername+'@'+self.HostIPAddress + COMMAND="ps aux | grep --colour=never " + self.Process['Name'] + " | grep -v grep " + logging.debug(COMMAND) + ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + result = ssh.stdout.readlines() + if len(result)!=0: + logging.debug(self.Process['Name'] + " process found") + return True + else: + logging.debug(self.Process['Name'] + " process NOT found") + return False + + #Generic command function, using function pointers dictionary + def Command(self,cmd): + mySSH = sshconnection.SSHConnection() + mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword) + mySSH.command('echo ' + self.HostPassword + ' | sudo -S python3 ' + self.cmd_dict[cmd],'\$',10) + time.sleep(5) + logging.debug("Module "+ cmd) + mySSH.close() + + + #this method retrieves the Module IP address (not the Host IP address) + def GetModuleIPAddress(self): + HOST=self.HostUsername+'@'+self.HostIPAddress + response= [] + tentative = 3 + while (len(response)==0) and (tentative>0): + COMMAND="ip a show dev " + self.UENetwork + " | grep --colour=never inet | grep " + self.UENetwork + logging.debug(COMMAND) + ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + response = ssh.stdout.readlines() + tentative-=1 + time.sleep(10) + if (tentative==0) and (len(response)==0): + logging.debug('\u001B[1;37;41m Module IP Address Not Found! Time expired \u001B[0m') + return -1 + else: #check response + result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', response[0].decode("utf-8") ) + if result is not None: + if result.group('moduleipaddress') is not None: + self.UEIPAddress = result.group('moduleipaddress') + logging.debug('\u001B[1mUE Module IP Address is ' + self.UEIPAddress + '\u001B[0m') + return 0 + else: + logging.debug('\u001B[1;37;41m Module IP Address Not Found! \u001B[0m') + return -1 + else: + logging.debug('\u001B[1;37;41m Module IP Address Not Found! \u001B[0m') + return -1 + + def CheckModuleMTU(self): + HOST=self.HostUsername+'@'+self.HostIPAddress + response= [] + tentative = 3 + while (len(response)==0) and (tentative>0): + COMMAND="ip a show dev " + self.UENetwork + " | grep --colour=never mtu" + logging.debug(COMMAND) + ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + response = ssh.stdout.readlines() + tentative-=1 + time.sleep(10) + if (tentative==0) and (len(response)==0): + logging.debug('\u001B[1;37;41m Module NIC MTU Not Found! Time expired \u001B[0m') + return -1 + else: #check response + result = re.search('mtu (?P[0-9]+)', response[0].decode("utf-8") ) + if result is not None: + if (result.group('mtu') is not None) and (str(result.group('mtu'))==str(self.MTU)) : + logging.debug('\u001B[1mUE Module NIC MTU is ' + str(self.MTU) + ' as expected\u001B[0m') + return 0 + else: + logging.debug('\u001B[1;37;41m Incorrect Module NIC MTU ' + str(result.group('mtu')) + '! Expected : ' + str(self.MTU) + '\u001B[0m') + return -1 + else: + logging.debug('\u001B[1;37;41m Module NIC MTU Not Found! \u001B[0m') + return -1 + + def EnableTrace(self): + if self.ue_trace=="yes": + mySSH = sshconnection.SSHConnection() + mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword) + #delete old artifacts + mySSH.command('echo ' + self.HostPassword + ' | sudo -S rm -rf ci_qlog','\$',5) + #start Trace, artifact is created in home dir + mySSH.command('echo $USER; nohup sudo -E QLog/QLog -s ci_qlog -f NR5G.cfg > /dev/null 2>&1 &','\$', 5) + mySSH.close() + + def DisableTrace(self): + mySSH = sshconnection.SSHConnection() + mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword) + mySSH.command('echo ' + self.HostPassword + ' | sudo -S killall --signal=SIGINT *QLog*', '\$',5) + mySSH.close() + + + def DisableCM(self): + mySSH = sshconnection.SSHConnection() + mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword) + mySSH.command('echo ' + self.HostPassword + ' | sudo -S killall --signal SIGKILL *'+self.Process['Name']+'*', '\$', 5) + mySSH.close() + + + def LogCollect(self): + if self.ue_trace=="yes": + mySSH = sshconnection.SSHConnection() + mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword) + #archive qlog to USB stick in /media/usb-drive/ci_qlogs with datetime suffix + now=datetime.now() + now_string = now.strftime("%Y%m%d-%H%M") + source='ci_qlog' + destination= self.LogStore + '/ci_qlog_'+now_string+'.zip' + #qlog artifact is zipped into the target folder + mySSH.command('echo $USER; echo ' + self.HostPassword + ' | nohup sudo -S zip -r '+destination+' '+source+' > /dev/null 2>&1 &','\$', 10) + mySSH.close() + #post action : log cleaning to make sure enough space is reserved for the next run + Log_Mgt=cls_log_mgt.Log_Mgt(self.HostUsername,self.HostIPAddress, self.HostPassword, self.LogStore) + Log_Mgt.LogRotation() + else: + destination="" + return destination diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py new file mode 100644 index 0000000000..b8b99a053b --- /dev/null +++ b/ci-scripts/cls_oaicitest.py @@ -0,0 +1,3664 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + + +#----------------------------------------------------------- +# Import Libs +#----------------------------------------------------------- +import sys # arg +import re # reg +import pexpect # pexpect +import time # sleep +import os +import subprocess +import xml.etree.ElementTree as ET +import logging +import datetime +import signal +import statistics as stat +from multiprocessing import Process, Lock, SimpleQueue +logging.basicConfig( + level=logging.DEBUG, + format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" +) + +#import our libs +import helpreadme as HELP +import constants as CONST +import sshconnection + +import cls_module_ue +import cls_ci_ueinfra #class defining the multi Ue infrastrucure + + +#----------------------------------------------------------- +# Utility functions +#----------------------------------------------------------- + +def GetPingTimeAnalysis(ping_log_file): + #ping time values read from file + t_ping=[] + #ping stats (dictionary) to be returned by the function + ping_stat={} + if (os.path.isfile(ping_log_file)): + with open(ping_log_file,"r") as f: + for line in f: + #looking for time=xxx ms field + result=re.match('^.+time=(?P[0-9\.]+)',line) + if result != None: + t_ping.append(float(result.group('ping_time'))) + + #initial stats + ping_stat['min_0']=min(t_ping) + ping_stat['mean_0']=stat.mean(t_ping) + ping_stat['median_0']=stat.median(t_ping) + ping_stat['max_0']=max(t_ping) + + #get index of max value + + max_loc=t_ping.index(max(t_ping)) + ping_stat['max_loc']=max_loc + #remove it + t_ping.pop(max_loc) + #new stats after removing max value + ping_stat['min_1']=min(t_ping) + ping_stat['mean_1']=stat.mean(t_ping) + ping_stat['median_1']=stat.median(t_ping) + ping_stat['max_1']=max(t_ping) + + return ping_stat + + else: + logging.error("Ping log file does not exist") + return -1 + + + +#----------------------------------------------------------- +# OaiCiTest Class Definition +#----------------------------------------------------------- +class OaiCiTest(): + + def __init__(self): + self.ranRepository = '' + self.ranBranch = '' + self.ranCommitID = '' + self.ranAllowMerge = False + self.ranTargetBranch = '' + + self.FailReportCnt = 0 + self.ADBIPAddress = '' + self.ADBUserName = '' + self.ADBPassword = '' + self.ADBCentralized = True + self.testCase_id = '' + self.testXMLfiles = [] + self.testUnstable = False + self.testMinStableId = '999999' + self.testStabilityPointReached = False + self.desc = '' + self.ping_args = '' + self.ping_packetloss_threshold = '' + self.ping_rttavg_threshold ='' + self.iperf_args = '' + self.iperf_packetloss_threshold = '' + self.iperf_profile = '' + self.iperf_options = '' + self.iperf_direction = '' + self.nbMaxUEtoAttach = -1 + self.UEDevices = [] + self.UEDevicesStatus = [] + self.UEDevicesRemoteServer = [] + self.UEDevicesRemoteUser = [] + self.UEDevicesOffCmd = [] + self.UEDevicesOnCmd = [] + self.UEDevicesRebootCmd = [] + self.CatMDevices = [] + self.UEIPAddresses = [] + self.idle_sleep_time = 0 + self.x2_ho_options = 'network' + self.x2NbENBs = 0 + self.x2ENBBsIds = [] + self.x2ENBConnectedUEs = [] + self.repeatCounts = [] + self.finalStatus = False + self.UEIPAddress = '' + self.UEUserName = '' + self.UEPassword = '' + self.UE_instance = 0 + self.UESourceCodePath = '' + self.UELogFile = '' + self.Build_OAI_UE_args = '' + self.Initialize_OAI_UE_args = '' + self.clean_repository = True + self.air_interface='' + self.expectedNbOfConnectedUEs = 0 + self.ue_id = '' #used for module identification + self.ue_trace ='' #used to enable QLog trace for Module UE, passed to Module UE object at InitializeUE() + + + def BuildOAIUE(self,HTML): + if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + SSH = sshconnection.SSHConnection() + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + result = re.search('--nrUE', self.Build_OAI_UE_args) + if result is not None: + self.air_interface='nr-uesoftmodem' + ue_prefix = 'NR ' + else: + self.air_interface='lte-uesoftmodem' + ue_prefix = '' + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository.replace('git/', 'git') + else: + full_ran_repo_name = self.ranRepository + '.git' + SSH.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # here add a check if git clone or git fetch went smoothly + SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + SSH.command('git config user.name "OAI Jenkins"', '\$', 5) + if self.clean_repository: + SSH.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', SSH.getBefore()) + if result is not None: + mismatch = False + SSH.command('grep --colour=never SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, SSH.getBefore()) + if result is None: + mismatch = True + SSH.command('grep --colour=never MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranAllowMerge: + result = re.search('YES', SSH.getBefore()) + if result is None: + mismatch = True + SSH.command('grep --colour=never TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + result = re.search('develop', SSH.getBefore()) + else: + result = re.search(self.ranTargetBranch, SSH.getBefore()) + if result is None: + mismatch = True + else: + result = re.search('NO', SSH.getBefore()) + if result is None: + mismatch = True + if not mismatch: + SSH.close() + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK) + return + + SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) + + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + SSH.command('git checkout -f ' + self.ranCommitID, '\$', 30) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if self.ranAllowMerge: + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + SSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('mkdir -p log', '\$', 5) + SSH.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + SSH.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 1200) + SSH.command('ls ran_build/build', '\$', 3) + SSH.command('ls ran_build/build', '\$', 3) + buildStatus = True + result = re.search(self.air_interface, SSH.getBefore()) + if result is None: + buildStatus = False + SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + SSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + SSH.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) + if buildStatus: + # Generating a BUILD INFO file + SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranAllowMerge: + SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + SSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.close() + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') + else: + SSH.close() + logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', CONST.ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTabFooter(False) + self.ConditionalExit() + + def CheckFlexranCtrlInstallation(self,RAN,EPC,CONTAINERS): + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': + return + SSH = sshconnection.SSHConnection() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) + result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) + if result is not None: + RAN.flexranCtrlInstalled=True + RAN.flexranCtrlIpAddress=EPC.IPAddress + logging.debug('Flexran Controller is installed') + else: + # Maybe flexran-rtc is deployed into a container + SSH.command('docker inspect --format="FLEX_RTC_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" prod-flexran-rtc', '\$', 5) + result = re.search('FLEX_RTC_IP_ADDR = (?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + RAN.flexranCtrlDeployed=True + RAN.flexranCtrlIpAddress=result.group('flex_ip_addr') + CONTAINERS.flexranCtrlDeployed=True + CONTAINERS.flexranCtrlIpAddress=result.group('flex_ip_addr') + logging.debug('Flexran Controller is deployed: ' + RAN.flexranCtrlIpAddress) + SSH.close() + + def InitializeFlexranCtrl(self, HTML,RAN,EPC): + if RAN.flexranCtrlInstalled == False: + return + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + SSH = sshconnection.SSHConnection() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd /opt/flexran_rtc', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S rm -f log/*.log', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) + result = re.search('rt_controller -c ', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') + RAN.flexranCtrlStarted=True + SSH.close() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def InitializeUE_common(self, device_id, idx,COTS_UE): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if not self.ADBCentralized: + # Reboot UE + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) + # Wait + #time.sleep(60) + # Put in LTE-Mode only + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) + # enable data service + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + # we need to do radio on/off cycle to make sure of above changes + # airplane mode off // radio on + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + #time.sleep(10) + # airplane mode on // radio off + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + + # normal procedure without reboot + # enable data service + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + # airplane mode on // radio off + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.close() + return + + #RH quick add-on to integrate cots control defined by yaml + #if device_id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + logging.debug('Device id ' + str(device_id) + ', in COTS UE dict : ' + str(COTS_UE.Check_Exists(device_id))) + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode ON (ie Radio OFF) + COTS_UE.Set_Airplane(device_id, 'ON') + else: + # enable data service + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + + # The following commands are deprecated since we no longer work on Android 7+ + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) + # a dedicated script has to be installed inside the UE + # airplane mode on means call /data/local/tmp/off + if device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + #airplane mode off means call /data/local/tmp/on + logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def InitializeUE(self,HTML,RAN,EPC, COTS_UE, InfraUE,ue_trace,CONTAINERS): + if self.ue_id=='':#no ID specified, then it is a COTS controlled by ADB + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.InitializeUE_common, args = (device_id,i,COTS_UE,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + else: #if an ID is specified, it is a module from the yaml infrastructure file + #RH + Module_UE = cls_module_ue.Module_UE(InfraUE.ci_ue_infra[self.ue_id]) + Module_UE.ue_trace=ue_trace + is_module=Module_UE.CheckCMProcess(EPC.Type) + if is_module: + Module_UE.EnableTrace() + time.sleep(5) + + # Looping attach / detach / wait to be successful at least once + cnt = 0 + status = -1 + while cnt < 4: + Module_UE.Command("wup") + logging.debug("Waiting for IP address to be assigned") + time.sleep(20) + logging.debug("Retrieve IP address") + status=Module_UE.GetModuleIPAddress() + if status==0: + cnt = 10 + else: + cnt += 1 + Module_UE.Command("detach") + time.sleep(20) + + if cnt == 10 and status == 0: + HTML.CreateHtmlTestRow(Module_UE.UEIPAddress, 'OK', CONST.ALL_PROCESSES_OK) + logging.debug('UE IP addresss : '+ Module_UE.UEIPAddress) + #execute additional commands from yaml file after UE attach + SSH = sshconnection.SSHConnection() + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + if hasattr(Module_UE,'StartCommands'): + for startcommand in Module_UE.StartCommands: + cmd = 'echo ' + Module_UE.HostPassword + ' | ' + startcommand + SSH.command(cmd,'\$',5) + SSH.close() + #check that the MTU is as expected / requested + Module_UE.CheckModuleMTU() + else: #status==-1 failed to retrieve IP address + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + + + + def InitializeOAIUE(self,HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS): + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + + + if self.air_interface == 'lte-uesoftmodem': + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is None: + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) + self.ConditionalExit() + UE_prefix = '' + else: + UE_prefix = 'NR ' + SSH = sshconnection.SSHConnection() + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + # b2xx_fx3_utils reset procedure + SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 180) + result = re.search('type: b200', SSH.getBefore()) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + SSH.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 180) + result = re.search('type: n3xx', str(SSH.getBefore())) + if result is not None: + logging.debug('Found a N3xx device --> resetting it') + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + # Initialize_OAI_UE_args usually start with -C and followed by the location in repository + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets/ran_build/build', '\$', 5) + if self.air_interface == 'lte-uesoftmodem': + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + # We may have to regenerate the .u* files + if result is None: + SSH.command('ls /tmp/*.sed', '\$', 5) + result = re.search('adapt_usim_parameters', SSH.getBefore()) + if result is not None: + SSH.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + else: + SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) + else: + SSH.command('if [ -e rbconfig.raw ]; then echo ' + self.UEPassword + ' | sudo -S rm rbconfig.raw; fi', '\$', 5) + SSH.command('if [ -e reconfig.raw ]; then echo ' + self.UEPassword + ' | sudo -S rm reconfig.raw; fi', '\$', 5) + # Copy the RAW files from gNB running directory (maybe on another machine) + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/rbconfig.raw', '.') + if (copyin_res == 0): + SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './rbconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build') + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/reconfig.raw', '.') + if (copyin_res == 0): + SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './reconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build') + SSH.command('echo "ulimit -c unlimited && ./'+ self.air_interface +' ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + self.UELogFile = 'ue_' + self.testCase_id + '.log' + + # We are now looping several times to hope we really sync w/ an eNB + doOutterLoop = True + outterLoopCounter = 5 + gotSyncStatus = True + fullSyncStatus = True + while (doOutterLoop): + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/ran_build/build', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup sudo -E ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) + time.sleep(6) + SSH.command('cd ../..', '\$', 5) + doLoop = True + loopCounter = 10 + gotSyncStatus = True + # the 'got sync' message is for the UE threads synchronization + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # Here should never occur + logging.error('"got sync" message never showed!') + gotSyncStatus = False + doLoop = False + continue + SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + if self.air_interface == 'nr-uesoftmodem': + result = re.search('Starting sync detection', SSH.getBefore()) + else: + result = re.search('got sync', SSH.getBefore()) + if result is None: + time.sleep(10) + else: + doLoop = False + logging.debug('Found "got sync" message!') + if gotSyncStatus == False: + # we certainly need to stop the lte-uesoftmodem process if it is still running! + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT -r *-uesoftmodem', '\$', 4) + time.sleep(3) + outterLoopCounter = outterLoopCounter - 1 + if (outterLoopCounter == 0): + doOutterLoop = False + continue + # We are now checking if sync w/ eNB DOES NOT OCCUR + # Usually during the cell synchronization stage, the UE returns with No cell synchronization message + # That is the case for LTE + # In NR case, it's a positive message that will show if synchronization occurs + doLoop = True + if self.air_interface == 'nr-uesoftmodem': + loopCounter = 10 + else: + # We are now checking if sync w/ eNB DOES NOT OCCUR + # Usually during the cell synchronization stage, the UE returns with No cell synchronization message + loopCounter = 10 + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + if self.air_interface == 'nr-uesoftmodem': + # Here we do have great chances that UE did NOT cell-sync w/ gNB + doLoop = False + fullSyncStatus = False + logging.debug('Never seen the NR-Sync message (Measured Carrier Frequency) --> try again') + time.sleep(6) + # Stopping the NR-UE + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('nr-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT nr-uesoftmodem', '\$', 4) + time.sleep(6) + else: + # Here we do have a great chance that the UE did cell-sync w/ eNB + doLoop = False + doOutterLoop = False + fullSyncStatus = True + continue + SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Frequency"', '\$', 4) + if self.air_interface == 'nr-uesoftmodem': + # Positive messaging --> + result = re.search('Measured Carrier Frequency', SSH.getBefore()) + if result is not None: + doLoop = False + doOutterLoop = False + fullSyncStatus = True + else: + time.sleep(6) + else: + # Negative messaging --> + result = re.search('No cell synchronization found', SSH.getBefore()) + if result is None: + time.sleep(6) + else: + doLoop = False + fullSyncStatus = False + logging.debug('Found: "No cell synchronization" message! --> try again') + time.sleep(6) + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('lte-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + outterLoopCounter = outterLoopCounter - 1 + if (outterLoopCounter == 0): + doOutterLoop = False + + if fullSyncStatus and gotSyncStatus: + doInterfaceCheck = False + if self.air_interface == 'lte-uesoftmodem': + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is None: + doInterfaceCheck = True + # For the moment, only in explicit noS1 without kernel module (ie w/ tunnel interface) + if self.air_interface == 'nr-uesoftmodem': + result = re.search('--noS1 --nokrnmod 1', str(self.Initialize_OAI_UE_args)) + if result is not None: + doInterfaceCheck = True + if doInterfaceCheck: + SSH.command('ifconfig oaitun_ue1', '\$', 4) + SSH.command('ifconfig oaitun_ue1', '\$', 4) + # ifconfig output is different between ubuntu 16 and ubuntu 18 + result = re.search('inet addr:[0-9]|inet [0-9]', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') + tunnelInterfaceStatus = True + else: + logging.debug(SSH.getBefore()) + logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') + tunnelInterfaceStatus = False + if RAN.eNBmbmsEnables[0]: + SSH.command('ifconfig oaitun_uem1', '\$', 4) + result = re.search('inet addr', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_uem1 interface is mounted and configured\u001B[0m') + tunnelInterfaceStatus = tunnelInterfaceStatus and True + else: + logging.error('\u001B[1m oaitun_uem1 interface is either NOT mounted or NOT configured\u001B[0m') + tunnelInterfaceStatus = False + else: + tunnelInterfaceStatus = True + else: + tunnelInterfaceStatus = True + + SSH.close() + if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') + logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') + if (self.ADBIPAddress != 'none'): + self.UEDevices = [] + self.UEDevices.append('OAI-UE') + self.UEDevicesStatus = [] + self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) + else: + if self.air_interface == 'lte-uesoftmodem': + if RAN.eNBmbmsEnables[0]: + HTML.htmlUEFailureMsg='oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' + else: + HTML.htmlUEFailureMsg='oaitun_ue1 interface is either NOT mounted or NOT configured' + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + else: + HTML.htmlUEFailureMsg='nr-uesoftmodem did NOT synced' + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') + logging.error('\033[91mInitialize OAI UE Failed! \033[0m') + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + + def checkDevTTYisUnlocked(self): + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + count = 0 + while count < 5: + SSH.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep --colour=never ttyUSB0', '\$', 10) + result = re.search('picocom', SSH.getBefore()) + if result is None: + count = 10 + else: + time.sleep(5) + count = count + 1 + SSH.close() + + def InitializeCatM(self,HTML): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + SSH = sshconnection.SSHConnection() + SSH.enablePicocomClosure() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + # Doing a power cycle + SSH.command('AT^RESET', 'SIMSTORE,READY', 15) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + SSH.command('ATE1', 'OK', 5) + # Disabling the Radio + SSH.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + # Checking if auto-attach is enabled + SSH.command('AT^AUTOATT?', 'OK', 5) + result = re.search('AUTOATT: (?P[0-9\-]+)', SSH.getBefore()) + if result is not None: + if result.group('state') is not None: + autoAttachState = int(result.group('state')) + if autoAttachState is not None: + if autoAttachState == 0: + SSH.command('AT^AUTOATT=1', 'OK', 5) + logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') + # Force closure of picocom but device might still be locked + SSH.close() + SSH.disablePicocomClosure() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def TerminateCatM(self,HTML): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + SSH = sshconnection.SSHConnection() + SSH.enablePicocomClosure() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + # Disabling the Radio + SSH.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + SSH.close() + SSH.disablePicocomClosure() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def AttachCatM(self,HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + SSH = sshconnection.SSHConnection() + SSH.enablePicocomClosure() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + # Enabling the Radio + SSH.command('AT+CFUN=1', 'SIMSTORE,READY', 5) + logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') + time.sleep(4) + # We should check if we register + count = 0 + attach_cnt = 0 + attach_status = False + while count < 5: + SSH.command('AT+CEREG?', 'OK', 5) + result = re.search('CEREG: 2,(?P[0-9\-]+),', SSH.getBefore()) + if result is not None: + mDataConnectionState = int(result.group('state')) + if mDataConnectionState is not None: + if mDataConnectionState == 1: + count = 10 + attach_status = True + result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', SSH.getBefore()) + if result is not None: + networky = result.group('networky') + networkz = result.group('networkz') + logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m') + else: + logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m') + else: + logging.debug('+CEREG: 2,' + str(mDataConnectionState)) + attach_cnt = attach_cnt + 1 + else: + logging.debug(SSH.getBefore()) + attach_cnt = attach_cnt + 1 + count = count + 1 + time.sleep(1) + if attach_status: + SSH.command('AT+CESQ', 'OK', 5) + result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', SSH.getBefore()) + if result is not None: + nRSRQ = int(result.group('rsrq')) + nRSRP = int(result.group('rsrp')) + if (nRSRQ is not None) and (nRSRP is not None): + logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') + logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') + SSH.close() + SSH.disablePicocomClosure() + html_queue = SimpleQueue() + self.checkDevTTYisUnlocked() + if attach_status: + html_cell = '
CAT-M module Attachment Completed in ' + str(attach_cnt+4) + ' seconds'
+			if (nRSRQ is not None) and (nRSRP is not None):
+				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
+				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm
' + else: + html_cell += '' + html_queue.put(html_cell) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) + else: + logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') + html_cell = '
CAT-M module Attachment Failed
' + html_queue.put(html_cell) + HTML.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + + def PingCatM(self,HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS): + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + try: + statusQueue = SimpleQueue() + lock = Lock() + SSH = sshconnection.SSHConnection() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) + if re.match('OAI', EPC.Type, re.IGNORECASE): + logging.debug('Using the OAI EPC HSS: not implemented yet') + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) + self.ConditionalExit() + else: + SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) + result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', SSH.getBefore()) + if result is not None: + moduleIPAddr = result.group('ipaddr') + else: + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + device_id = 'catm' + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + lock.acquire() + logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + lock.release() + SSH.close() + html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' + statusQueue.put(html_cell) + if (packetLossOK): + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) + else: + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AttachUE_common(self, device_id, statusQueue, lock, idx,COTS_UE): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + #RH quick add on to integrate cots control defined by yaml + #if device Id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode OFF (ie Radio ON) + COTS_UE.Set_Airplane(device_id, 'OFF') + elif device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + else: + # airplane mode off // radio on + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + time.sleep(2) + max_count = 45 + count = max_count + while count > 0: + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put('mDataConnectionState Not Found!') + lock.release() + break + mDataConnectionState = int(result.group('state')) + if mDataConnectionState == 2: + logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') + lock.acquire() + statusQueue.put(max_count - count) + statusQueue.put(device_id) + statusQueue.put('Attach Completed') + lock.release() + break + count = count - 1 + if count == 15 or count == 30: + logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') + if self.ADBCentralized: + #RH quick add on to intgrate cots control defined by yaml + #if device id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode ON (ie Radio OFF) + COTS_UE.Set_Airplane(device_id, 'ON') + elif device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + time.sleep(0.5) + if self.ADBCentralized: + #RH quick add on to integrate cots control defined by yaml + #if device id exists in yaml dictionary, we execute the new procedre defined incots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode OFF (ie Radio ON) + COTS_UE.Set_Airplane(device_id, 'OFF') + elif device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + time.sleep(0.5) + logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') + time.sleep(1) + if count == 0: + logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m') + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put('Attach Failed') + lock.release() + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AttachUE(self,HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS): + if self.ue_id=='':#no ID specified, then it is a COTS controlled by ADB + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + multi_jobs = [] + status_queue = SimpleQueue() + lock = Lock() + nb_ue_to_connect = 0 + for device_id in self.UEDevices: + if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): + self.UEDevicesStatus[nb_ue_to_connect] = CONST.UE_STATUS_ATTACHING + p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,COTS_UE,)) + p.daemon = True + p.start() + multi_jobs.append(p) + nb_ue_to_connect = nb_ue_to_connect + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + else: + attach_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + attach_status = False + device_id = status_queue.get() + message = status_queue.get() + if (count < 0): + html_cell = '
UE (' + device_id + ')\n' + message + '
' + else: + html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' + html_queue.put(html_cell) + if (attach_status): + cnt = 0 + while cnt < len(self.UEDevices): + if self.UEDevicesStatus[cnt] == CONST.UE_STATUS_ATTACHING: + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_ATTACHED + cnt += 1 + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + result = re.search('T_stdout', str(RAN.Initialize_eNB_args)) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) + else: + HTML.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + + else: #if an ID is specified, it is a module from the yaml infrastructure file + #Attention, as opposed to InitializeUE, the connect manager process is not checked as it is supposed to be active already + #only 1- module wakeup, 2- check IP address + Module_UE = cls_module_ue.Module_UE(InfraUE.ci_ue_infra[self.ue_id]) + status = -1 + cnt = 0 + while cnt < 4: + Module_UE.Command("wup") + logging.debug("Waiting for IP address to be assigned") + time.sleep(20) + logging.debug("Retrieve IP address") + status=Module_UE.GetModuleIPAddress() + if status==0: + cnt = 10 + else: + cnt += 1 + Module_UE.Command("detach") + time.sleep(20) + + if cnt == 10 and status == 0: + HTML.CreateHtmlTestRow(Module_UE.UEIPAddress, 'OK', CONST.ALL_PROCESSES_OK) + logging.debug('UE IP addresss : '+ Module_UE.UEIPAddress) + #execute additional commands from yaml file after UE attach + SSH = sshconnection.SSHConnection() + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + if hasattr(Module_UE,'StartCommands'): + for startcommand in Module_UE.StartCommands: + cmd = 'echo ' + Module_UE.HostPassword + ' | ' + startcommand + SSH.command(cmd,'\$',5) + SSH.close() + #check that the MTU is as expected / requested + Module_UE.CheckModuleMTU() + else: #status==-1 failed to retrieve IP address + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + + def DetachUE_common(self, device_id, idx,COTS_UE): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + #RH quick add on to integrate cots control defined by yaml + #if device id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode ON (ie Radio OFF) + COTS_UE.Set_Airplane(device_id,'ON') + elif device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DetachUE(self,HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS): + if self.ue_id=='':#no ID specified, then it is a COTS controlled by ADB + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + multi_jobs = [] + cnt = 0 + for device_id in self.UEDevices: + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHING + p = Process(target = self.DetachUE_common, args = (device_id,cnt,COTS_UE,)) + p.daemon = True + p.start() + multi_jobs.append(p) + cnt += 1 + for job in multi_jobs: + job.join() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + result = re.search('T_stdout', str(RAN.Initialize_eNB_args)) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) + cnt = 0 + while cnt < len(self.UEDevices): + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHED + cnt += 1 + else:#if an ID is specified, it is a module from the yaml infrastructure file + Module_UE = cls_module_ue.Module_UE(InfraUE.ci_ue_infra[self.ue_id]) + Module_UE.Command("detach") + HTML.CreateHtmlTestRow('NA', 'OK', CONST.ALL_PROCESSES_OK) + + + + def RebootUE_common(self, device_id): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + previousmDataConnectionStates = [] + # Save mDataConnectionState + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') + sys.exit(1) + previousmDataConnectionStates.append(int(result.group('state'))) + # Reboot UE + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) + time.sleep(60) + previousmDataConnectionState = previousmDataConnectionStates.pop(0) + count = 180 + while count > 0: + count = count - 1 + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) + if result is None: + mDataConnectionState = None + else: + mDataConnectionState = int(result.group('state')) + logging.debug('mDataConnectionState = ' + result.group('state')) + if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2): + logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m') + time.sleep(1) + else: + logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m') + break + if count == 0: + logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') + sys.exit(1) + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def RebootUE(self,HTML,RAN,EPC): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) + self.ConditionalExit() + multi_jobs = [] + for device_id in self.UEDevices: + p = Process(target = self.RebootUE_common, args = (device_id,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def DataDisableUE_common(self, device_id, idx): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # disable data service + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DataDisableUE(self,HTML): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.DataDisableUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def DataEnableUE_common(self, device_id, idx): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # enable data service + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DataEnableUE(self,HTML): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.DataEnableUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def GetAllUEDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + SSH.command('adb devices', '\$', 15) + self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) + #report number and id of devices found + msg = "UEDevices found by GetAllUEDevices : " + " ".join(self.UEDevices) + logging.debug(msg) + SSH.close() + else: + if (os.path.isfile('./phones_list.txt')): + os.remove('./phones_list.txt') + SSH.command('ls /etc/*/phones*.txt', '\$', 5) + result = re.search('/etc/ci/phones_list.txt', SSH.getBefore()) + SSH.close() + if (result is not None) and (len(self.UEDevices) == 0): + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') + if (os.path.isfile('./phones_list.txt')): + phone_list_file = open('./phones_list.txt', 'r') + for line in phone_list_file.readlines(): + line = line.strip() + result = re.search('^#', line) + if result is not None: + continue + comma_split = line.split(",") + self.UEDevices.append(comma_split[0]) + self.UEDevicesRemoteServer.append(comma_split[1]) + self.UEDevicesRemoteUser.append(comma_split[2]) + self.UEDevicesOffCmd.append(comma_split[3]) + self.UEDevicesOnCmd.append(comma_split[4]) + self.UEDevicesRebootCmd.append(comma_split[5]) + phone_list_file.close() + + # better handling of the case when no UE detected + # Sys-exit is now dealt by the calling function + if terminate_ue_flag == True: + if len(self.UEDevices) == 0: + logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') + return False + if len(self.UEDevicesStatus) == 0: + cnt = 0 + while cnt < len(self.UEDevices): + self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) + cnt += 1 + return True + + def GetAllCatMDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + SSH.command('lsusb | egrep --colour=never "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) + #self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) + self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) + else: + if (os.path.isfile('./modules_list.txt')): + os.remove('./modules_list.txt') + SSH.command('ls /etc/*/modules*.txt', '\$', 5) + result = re.search('/etc/ci/modules_list.txt', SSH.getBefore()) + SSH.close() + if result is not None: + logging.debug('Found a module list file on ADB server') + if terminate_ue_flag == True: + if len(self.CatMDevices) == 0: + logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') + sys.exit(1) + SSH.close() + + def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) + result = re.search('mServiceState=(?P[0-9]+)', SSH.getBefore()) + serviceState = 'Service State: UNKNOWN' + if result is not None: + lServiceState = int(result.group('serviceState')) + if lServiceState == 3: + serviceState = 'Service State: RADIO_POWERED_OFF' + if lServiceState == 1: + serviceState = 'Service State: OUT_OF_SERVICE' + if lServiceState == 0: + serviceState = 'Service State: IN_SERVICE' + if lServiceState == 2: + serviceState = 'Service State: EMERGENCY_ONLY' + result = re.search('mDataConnectionState=(?P[0-9]+)', SSH.getBefore()) + dataConnectionState = 'Data State: UNKNOWN' + if result is not None: + lDataConnectionState = int(result.group('dataConnectionState')) + if lDataConnectionState == 0: + dataConnectionState = 'Data State: DISCONNECTED' + if lDataConnectionState == 1: + dataConnectionState = 'Data State: CONNECTING' + if lDataConnectionState == 2: + dataConnectionState = 'Data State: CONNECTED' + if lDataConnectionState == 3: + dataConnectionState = 'Data State: SUSPENDED' + result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', SSH.getBefore()) + time.sleep(1) + SSH.close() + dataConnectionReason = 'Data Reason: UNKNOWN' + if result is not None: + dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') + lock.acquire() + logging.debug('\u001B[1;37;44m Status Check (' + str(device_id) + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + serviceState + '\u001B[0m') + logging.debug('\u001B[1;34m ' + dataConnectionState + '\u001B[0m') + logging.debug('\u001B[1;34m ' + dataConnectionReason + '\u001B[0m') + statusQueue.put(0) + statusQueue.put(device_id) + qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason + statusQueue.put(qMsg) + lock.release() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckStatusUE(self,HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) + self.ConditionalExit() + multi_jobs = [] + lock = Lock() + status_queue = SimpleQueue() + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.CheckUEStatus_common, args = (lock,device_id,status_queue,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + if (RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted) or RAN.flexranCtrlDeployed: + SSH = sshconnection.SSHConnection() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) + SSH.command('curl http://' + RAN.flexranCtrlIpAddress + ':9999/stats | jq \'.\' > check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) + SSH.command('cat check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) + result = re.search('Nb Connected UE = (?P[0-9]+)', SSH.getBefore()) + passStatus = True + if result is not None: + nb_ues = int(result.group('nb_ues')) + htmlOptions = 'Nb Connected UE(s) to eNB = ' + str(nb_ues) + logging.debug('\u001B[1;37;44m ' + htmlOptions + ' \u001B[0m') + if self.expectedNbOfConnectedUEs > -1: + if nb_ues != self.expectedNbOfConnectedUEs: + passStatus = False + else: + htmlOptions = 'N/A' + SSH.close() + else: + passStatus = True + htmlOptions = 'N/A' + + if (status_queue.empty()): + HTML.CreateHtmlTestRow(htmlOptions, 'KO', CONST.ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + else: + check_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + check_status = False + device_id = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\n' + message + '
' + html_queue.put(html_cell) + if check_status and passStatus: + HTML.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) + else: + HTML.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + + def GetAllUEIPAddresses(self): + SSH = sshconnection.SSHConnection() + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + ue_ip_status = 0 + self.UEIPAddresses = [] + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('ifconfig oaitun_ue1', '\$', 4) + result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', SSH.getBefore()) + if result is not None: + if result.group('ueipaddress') is not None: + UE_IPAddress = result.group('ueipaddress') + else: + UE_IPAddress = result.group('ueipaddress2') + logging.debug('\u001B[1mUE (' + self.UEDevices[0] + ') IP Address is ' + UE_IPAddress + '\u001B[0m') + self.UEIPAddresses.append(UE_IPAddress) + else: + logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') + ue_ip_status -= 1 + SSH.close() + return ue_ip_status + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + idx = 0 + for device_id in self.UEDevices: + if self.UEDevicesStatus[idx] != CONST.UE_STATUS_ATTACHED: + idx += 1 + continue + count = 0 + while count < 4: + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) + result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') + time.sleep(1) + count += 1 + else: + count = 10 + if count < 9: + ue_ip_status -= 1 + continue + UE_IPAddress = result.group('ueipaddress') + logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m') + for ueipaddress in self.UEIPAddresses: + if ueipaddress == UE_IPAddress: + logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + ': has already been allocated to another device !' + '\u001B[0m') + ue_ip_status -= 1 + continue + self.UEIPAddresses.append(UE_IPAddress) + idx += 1 + SSH.close() + return ue_ip_status + + def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(message) + lock.release() + + def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue,EPC, Module_UE): + try: + SSH = sshconnection.SSHConnection() + # Launch ping on the EPC side (true for ltebox and old open-air-cn) + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + launchFromModule = False + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): + launchFromEpc = False + #if module, ping from module to EPC + if self.ue_id!='': + launchFromEpc = False + launchfromModule = True + + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + + if launchFromEpc: + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) + # In case of a docker-based deployment, we need to ping from the trf-gen container + launchFromTrfContainer = False + if (re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE)) or (re.match('OAICN5G', EPC.Type, re.IGNORECASE)): + launchFromTrfContainer = True + if launchFromTrfContainer: + ping_status = SSH.command('docker exec -it prod-trf-gen /bin/bash -c "ping ' + self.ping_args + ' ' + UE_IPAddress + '" 2>&1 | tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + else: + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + #copy the ping log file to have it locally for analysis (ping stats) + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '.') + else: + if launchfromModule == False: + #ping log file is on the python executor + cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + ping_status = ret.returncode + #copy the ping log file to an other folder for log collection (source and destination are EPC) + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + #copy the ping log file to have it locally for analysis (ping stats) + logging.debug(EPC.SourceCodePath + 'ping_' + self.testCase_id + '_' + device_id + '.log') + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath +'/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '.') + + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + #cat is executed on EPC + SSH.command('cat ' + EPC.SourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + else: #launch from Module + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + #target address is different depending on EPC type + if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): + Target = EPC.MmeIPAddress + elif re.match('OAICN5G', EPC.Type, re.IGNORECASE): + Target = EPC.MmeIPAddress + else: + Target = EPC.IPAddress + #ping from module NIC rather than IP address to make sure round trip is over the air + cmd = 'ping -I ' + Module_UE.UENetwork + ' ' + self.ping_args + ' ' + Target + ' 2>&1 > ping_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.command(cmd,'\$',int(ping_time[0])*1.5) + #copy the ping log file to have it locally for analysis (ping stats) + SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, 'ping_' + self.testCase_id + '_' + self.ue_id + '.log', '.') + + #cat is executed locally + SSH.command('cat ping_' + self.testCase_id + '_' + self.ue_id + '.log', '\$', 5) + ping_status=0 + + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + #search is done on cat result + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + + lock.acquire() + logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + + #adding extra ping stats from local file + ping_log_file='ping_' + self.testCase_id + '_' + device_id + '.log' + logging.debug('Analyzing Ping log file : ' + os.getcwd() + '/' + ping_log_file) + ping_stat=GetPingTimeAnalysis(ping_log_file) + ping_stat_msg='' + if (ping_stat!=-1) and (len(ping_stat)!=0): + ping_stat_msg+='Ping stats before removing largest value : \n' + ping_stat_msg+='RTT(Min) : ' + str("{:.2f}".format(ping_stat['min_0'])) + 'ms \n' + ping_stat_msg+='RTT(Mean) : ' + str("{:.2f}".format(ping_stat['mean_0'])) + 'ms \n' + ping_stat_msg+='RTT(Median) : ' + str("{:.2f}".format(ping_stat['median_0'])) + 'ms \n' + ping_stat_msg+='RTT(Max) : ' + str("{:.2f}".format(ping_stat['max_0'])) + 'ms \n' + ping_stat_msg+='Max Index : ' + str(ping_stat['max_loc']) + '\n' + ping_stat_msg+='Ping stats after removing largest value : \n' + ping_stat_msg+='RTT(Min) : ' + str("{:.2f}".format(ping_stat['min_1'])) + 'ms \n' + ping_stat_msg+='RTT(Mean) : ' + str("{:.2f}".format(ping_stat['mean_1'])) + 'ms \n' + ping_stat_msg+='RTT(Median) : ' + str("{:.2f}".format(ping_stat['median_1'])) + 'ms \n' + ping_stat_msg+='RTT(Max) : ' + str("{:.2f}".format(ping_stat['max_1'])) + 'ms \n' + + #building html message + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + '\n' + ping_stat_msg + + #checking packet loss compliance + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high; Target: '+ self.ping_packetloss_threshold + '%\u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + + #checking RTT avg compliance + rttavgOK = True + if self.ping_rttavg_threshold != '': + if float(rtt_avg)>float(self.ping_rttavg_threshold): + ping_rttavg_error_msg = 'RTT(Avg) too high: ' + rtt_avg + ' ms; Target: '+ self.ping_rttavg_threshold+ ' ms' + qMsg += '\n'+ping_rttavg_error_msg + logging.debug('\u001B[1;37;41m'+ ping_rttavg_error_msg +' \u001B[0m') + rttavgOK = False + + if packetLossOK and rttavgOK: + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(qMsg) + lock.release() + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def PingNoS1_wrong_exit(self, qMsg,HTML): + html_queue = SimpleQueue() + html_cell = '
OAI UE ping result\n' + qMsg + '
' + html_queue.put(html_cell) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + + def PingNoS1(self,HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS): + SSH=sshconnection.SSHConnection() + check_eNB = True + check_OAI_UE = True + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) + if ping_from_eNB is not None: + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + else: + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + try: + if ping_from_eNB is not None: + SSH.open(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword) + SSH.command('cd ' + RAN.eNBSourceCodePath + '/cmake_targets/', '\$', 5) + else: + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with OAI UE crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message,HTML) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message,HTML) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message,HTML) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message,HTML) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + SSH.close() + html_queue = SimpleQueue() + ip_addr = 'TBD' + html_cell = '
OAI UE ping result\n' + qMsg + '
' + html_queue.put(html_cell) + if packetLossOK: + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + else: + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + + # copying on the EPC server for logCollection + if ping_from_eNB is not None: + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + else: + copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + if (copyin_res == 0): + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '.log', EPC.SourceCodePath + '/scripts') + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def Ping(self,HTML,RAN,EPC,COTS_UE, InfraUE, CONTAINERS): + result = re.search('noS1', str(RAN.Initialize_eNB_args)) + if result is not None: + self.PingNoS1(HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS) + return + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + check_eNB = True + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + check_OAI_UE = True + else: + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + + if self.ue_id=="": + Module_UE = cls_module_ue.Module_UE(InfraUE.ci_ue_infra['dummy']) #RH, temporary, we need a dummy Module_UE object to pass to Ping_common + ueIpStatus = self.GetAllUEIPAddresses() + if (ueIpStatus < 0): + HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + else: + self.UEIPAddresses=[] + Module_UE = cls_module_ue.Module_UE(InfraUE.ci_ue_infra[self.ue_id]) + Module_UE.GetModuleIPAddress() + self.UEIPAddresses.append(Module_UE.UEIPAddress) + logging.debug(self.UEIPAddresses) + multi_jobs = [] + i = 0 + lock = Lock() + status_queue = SimpleQueue() + for UE_IPAddress in self.UEIPAddresses: + if self.ue_id=="": + device_id = self.UEDevices[i] + else: + device_id = Module_UE.ID + "-" + Module_UE.Kind + p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,EPC,Module_UE,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i = i + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + else: + ping_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + ping_status = False + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (ping_status): + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + else: + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + + def Iperf_ComputeTime(self): + result = re.search('-t (?P\d+)', str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m') + sys.exit(1) + return result.group('iperf_time') + + def Iperf_ComputeModifiedBW(self, idx, ue_num): + result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') + sys.exit(1) + iperf_bandwidth = result.group('iperf_bandwidth') + if self.iperf_profile == 'balanced': + iperf_bandwidth_new = float(iperf_bandwidth)/ue_num + if self.iperf_profile == 'single-ue': + iperf_bandwidth_new = float(iperf_bandwidth) + if self.iperf_profile == 'unbalanced': + # residual is 2% of max bw + residualBW = float(iperf_bandwidth) / 50 + if idx == 0: + iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW) + else: + iperf_bandwidth_new = residualBW + iperf_bandwidth_str = '-b ' + iperf_bandwidth + iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new) + result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') + sys.exit(1) + return result + + def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options,EPC,SSH): + + SSH.command('awk -f /tmp/tcp_iperf_stats.awk ' + EPC.SourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', SSH.getBefore()) + if result is not None: + avgbitrate = result.group('average') + maxbitrate = result.group('maximum') + minbitrate = result.group('minimum') + lock.acquire() + logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m') + msg = 'TCP Stats :\n' + if avgbitrate is not None: + logging.debug('\u001B[1;34m Avg Bitrate : ' + avgbitrate + '\u001B[0m') + msg += 'Avg Bitrate : ' + avgbitrate + '\n' + if maxbitrate is not None: + logging.debug('\u001B[1;34m Max Bitrate : ' + maxbitrate + '\u001B[0m') + msg += 'Max Bitrate : ' + maxbitrate + '\n' + if minbitrate is not None: + logging.debug('\u001B[1;34m Min Bitrate : ' + minbitrate + '\u001B[0m') + msg += 'Min Bitrate : ' + minbitrate + '\n' + statusQueue.put(0) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + + return 0 + + def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options,EPC,SSH): + + result = re.search('-u', str(iperf_real_options)) + if result is None: + logging.debug('Into Iperf_analyzeV2TCPOutput client') + response = self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options,EPC,SSH) + logging.debug('Iperf_analyzeV2TCPOutput response returned value = ' + str(response)) + return response + + result = re.search('Server Report:', SSH.getBefore()) + if result is None: + result = re.search('read failed: Connection refused', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') + else: + logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') + return -1 + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) + if result is not None: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + result = re.search('-b [0-9\.]+G', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Gbits/sec' % req_bw + req_bw = req_bw * 1000000000 + + result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', SSH.getBefore()) + if result is not None: + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + jitter = result.group('jitter') + lock.acquire() + logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') + iperfStatus = True + msg = 'Req Bitrate : ' + req_bandwidth + '\n' + logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') + if bitrate is not None: + msg += 'Bitrate : ' + bitrate + '\n' + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) + if result is not None: + actual_bw = float(str(result.group('real_bw'))) + result = re.search('[0-9\.]+ K', bitrate) + if result is not None: + actual_bw = actual_bw * 1000 + result = re.search('[0-9\.]+ M', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000 + result = re.search('[0-9\.]+ G', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000000 + br_loss = 100 * actual_bw / req_bw + bitperf = '%.2f ' % br_loss + msg += 'Bitrate Perf: ' + bitperf + '%\n' + logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') + if packetloss is not None: + msg += 'Packet Loss : ' + packetloss + '%\n' + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + if float(packetloss) > float(self.iperf_packetloss_threshold): + msg += 'Packet Loss too high!\n' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + iperfStatus = False + if jitter is not None: + msg += 'Jitter : ' + jitter + '\n' + logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') + if (iperfStatus): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + return 0 + else: + return -2 + + def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options, filename,type): + if (not os.path.isfile(filename)): + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + return + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) + if result is None: + logging.debug('Iperf bandwidth Not Found!') + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') + return + else: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + result = re.search('-b [0-9\.]+G', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Gbits/sec' % req_bw + req_bw = req_bw * 1000000000 + + server_file = open(filename, 'r') + br_sum = 0.0 + ji_sum = 0.0 + pl_sum = 0 + ps_sum = 0 + row_idx = 0 + for line in server_file.readlines(): + if type==0: + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)/ +(?P[0-9]+)', str(line)) + else: + result = re.search('^\[\s+\d\].+ (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)\/\s*(?P[0-9]+)', str(line)) + + if result is not None: + bitrate = result.group('bitrate') + jitter = result.group('jitter') + packetlost = result.group('lostPack') + packetsent = result.group('sentPack') + br = bitrate.split(' ') + ji = jitter.split(' ') + row_idx = row_idx + 1 + curr_br = float(br[0]) + pl_sum = pl_sum + int(packetlost) + ps_sum = ps_sum + int(packetsent) + if (br[1] == 'Kbits/sec'): + curr_br = curr_br * 1000 + if (br[1] == 'Mbits/sec'): + curr_br = curr_br * 1000 * 1000 + br_sum = curr_br + br_sum + ji_sum = float(ji[0]) + ji_sum + + if (row_idx > 0): + br_sum = br_sum / row_idx + ji_sum = ji_sum / row_idx + br_loss = 100 * br_sum / req_bw + if (br_sum > 1000): + br_sum = br_sum / 1000 + if (br_sum > 1000): + br_sum = br_sum / 1000 + bitrate = '%.2f Mbits/sec' % br_sum + else: + bitrate = '%.2f Kbits/sec' % br_sum + else: + bitrate = '%.2f bits/sec' % br_sum + bitperf = '%.2f ' % br_loss + bitperf += '%' + jitter = '%.2f ms' % (ji_sum) + if (ps_sum > 0): + pl = float(100 * pl_sum / ps_sum) + packetloss = '%2.1f ' % (pl) + packetloss += '%' + if float(pl) > float(self.iperf_packetloss_threshold): + pal_too_high_msg = 'Packet Loss too high : actual = '+packetloss+', target = '+self.iperf_packetloss_threshold+'%\n' + else: + pal_too_high_msg='' + lock.acquire() + if (br_loss < 90) or (float(pl) > float(self.iperf_packetloss_threshold)): + statusQueue.put(1) + else: + statusQueue.put(0) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + req_msg = 'Req Bitrate : ' + req_bandwidth + bir_msg = 'Bitrate : ' + bitrate + brl_msg = 'Bitrate Perf: ' + bitperf + jit_msg = 'Jitter : ' + jitter + pal_msg = 'Packet Loss : ' + packetloss + statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n' + pal_too_high_msg + '\n') + logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + pal_too_high_msg + '\u001B[0m') + lock.release() + else: + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + + server_file.close() + + + def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue,SSH): + + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', SSH.getBefore()) + if result is None: + result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', SSH.getBefore()) + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + if result is not None: + logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m') + statusQueue.put(result.group('error')) + else: + logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') + statusQueue.put('Bitrate and/or Packet Loss Not Found!') + lock.release() + + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + lock.acquire() + logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + msg = 'Bitrate : ' + bitrate + '\n' + iperfStatus = True + if packetloss is not None: + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + msg += 'Packet Loss : ' + packetloss + '%\n' + if float(packetloss) > float(self.iperf_packetloss_threshold): + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + msg += 'Packet Loss too high!\n' + iperfStatus = False + if (iperfStatus): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + + def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue,EPC): + SSH = sshconnection.SSHConnection() + udpIperf = True + result = re.search('-u', str(self.iperf_args)) + if result is None: + udpIperf = False + ipnumbers = UE_IPAddress.split('.') + if (len(ipnumbers) == 4): + ipnumbers[3] = '1' + EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3] + + # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 + # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): + launchFromEpc = False + cmd = 'hostname -I' + ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') + if ret.stdout is not None: + EPC_Iperf_UE_IPAddress = ret.stdout.strip() + # When using a docker-based deployment, IPERF client shall be launched from trf container + launchFromTrfContainer = False + if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): + launchFromTrfContainer = True + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('docker inspect --format="TRF_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" prod-trf-gen', '\$', 5) + result = re.search('TRF_IP_ADDR = (?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + EPC_Iperf_UE_IPAddress = result.group('trf_ip_addr') + SSH.close() + port = 5001 + idx + udpOptions = '' + if udpIperf: + udpOptions = '-u ' + if launchFromEpc: + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if launchFromTrfContainer: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/iperf-2.0.5/bin/' + SSH.command('docker exec -d prod-trf-gen /bin/bash -c "nohup ' + prefix + 'iperf ' + udpOptions + '-s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &"', '\$', 5) + else: + SSH.command('echo $USER; nohup iperf ' + udpOptions + '-s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) + SSH.close() + else: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + cmd = 'nohup ' + prefix + 'iperf ' + udpOptions + '-s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + logging.debug(cmd) + subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') + time.sleep(0.5) + + # Launch iperf client on UE + if (device_id == 'OAI-UE'): + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + else: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.command('cd ' + EPC.SourceCodePath+ '/scripts', '\$', 5) + iperf_time = self.Iperf_ComputeTime() + time.sleep(0.5) + + if udpIperf: + modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) + else: + modified_options = str(self.iperf_args) + modified_options = modified_options.replace('-R','') + time.sleep(0.5) + + SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if (device_id == 'OAI-UE'): + iperf_status = SSH.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + if self.ADBCentralized: + iperf_status = SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + iperf_status = SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + SSH.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # TIMEOUT Case + if iperf_status < 0: + SSH.close() + message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options,EPC,SSH) + SSH.close() + + # Kill iperf server on EPC side + if launchFromEpc: + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + if launchFromTrfContainer: + SSH.command('docker exec -it prod-trf-gen /bin/bash -c "killall --signal SIGKILL iperf"', '\$', 5) + else: + SSH.command('killall --signal SIGKILL iperf', EPC.UserName, 5) + SSH.close() + else: + cmd = 'killall --signal SIGKILL iperf' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + time.sleep(1) + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + # in case of failure, retrieve server log + if (clientStatus == -1) or (clientStatus == -2): + if launchFromEpc: + time.sleep(1) + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + if launchFromTrfContainer: + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('docker cp prod-trf-gen:/iperf-2.0.5/iperf_server_' + self.testCase_id + '_' + device_id + '.log ' + EPC.SourceCodePath + '/scripts', '\$', 5) + SSH.close() + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath+ '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + filename='iperf_server_' + self.testCase_id + '_' + device_id + '.log' + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options,filename,0) + # in case of OAI-UE + if (device_id == 'OAI-UE'): + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + + + def Iperf_Module(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue,EPC, Module_UE): + if (re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE)) or (re.match('OAICN5G', EPC.Type, re.IGNORECASE)): + #retrieve trf-gen container IP address + SSH = sshconnection.SSHConnection() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('docker inspect --format="TRF_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" prod-trf-gen', '\$', 5) + result = re.search('TRF_IP_ADDR = (?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + trf_gen_IP = result.group('trf_ip_addr') + SSH.close() + #kill iperf processes on UE side before (in case there are still some remaining) + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + cmd = 'killall --signal=SIGKILL iperf' + SSH.command(cmd,'\$',5) + SSH.close() + + iperf_time = self.Iperf_ComputeTime() + if self.iperf_direction=="DL": + logging.debug("Iperf for Module in DL mode detected") + #server side UE + server_filename='iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + cmd = 'rm ' + server_filename + SSH.command(cmd,'\$',5) + cmd = 'echo $USER; nohup iperf -s -B ' + UE_IPAddress + ' -u 2>&1 > ' + server_filename + ' &' + SSH.command(cmd,'\$',5) + SSH.close() + #client side EPC + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + client_filename = 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.command('docker exec -it prod-trf-gen /bin/bash -c "killall --signal SIGKILL iperf"', '\$', 5) + iperf_cmd = 'bin/iperf -c ' + UE_IPAddress + ' ' + self.iperf_args + ' 2>&1 > ' + client_filename + cmd = 'docker exec -it prod-trf-gen /bin/bash -c \"' + iperf_cmd + '\"' + SSH.command(cmd,'\$',int(iperf_time)*5.0) + SSH.command('docker cp prod-trf-gen:/iperf-2.0.13/'+ client_filename + ' ' + EPC.SourceCodePath, '\$', 5) + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath + '/' + client_filename, '.') + SSH.close() + + #copy the 2 resulting files locally + SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, server_filename, '.') + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, client_filename, '.') + #send for analysis + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,server_filename,1) + + elif self.iperf_direction=="UL": + logging.debug("Iperf for Module in UL mode detected") + #server side EPC + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + server_filename = 'iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.command('docker exec -it prod-trf-gen /bin/bash -c "killall --signal SIGKILL iperf"', '\$', 5) + iperf_cmd = 'echo $USER; nohup bin/iperf -s -u 2>&1 > ' + server_filename + cmd = 'docker exec -d prod-trf-gen /bin/bash -c \"' + iperf_cmd + '\"' + SSH.command(cmd,'\$',5) + SSH.close() + + #client side UE + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + client_filename = 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log' + cmd = 'rm '+ client_filename + SSH.command(cmd,'\$',5) + SSH.command('iperf -B ' + UE_IPAddress + ' -c ' + trf_gen_IP + ' ' + self.iperf_args + ' 2>&1 > ' + client_filename, '\$', int(iperf_time)*5.0) + SSH.close() + + #once client is done, retrieve the server file from container to EPC Host + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('docker cp prod-trf-gen:/iperf-2.0.13/' + server_filename + ' ' + EPC.SourceCodePath, '\$', 5) + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath + '/' + server_filename, '.') + SSH.close() + + #copy the 2 resulting files locally + SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, client_filename, '.') + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, server_filename, '.') + #send for analysis + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,server_filename,1) + else : + logging.debug("Incorrect or missing IPERF direction in XML") + + else: #default is ltebox + + SSH = sshconnection.SSHConnection() + + #kill iperf processes before (in case there are still some remaining) + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + cmd = 'killall --signal=SIGKILL iperf' + SSH.command(cmd,'\$',5) + SSH.close() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + cmd = 'killall --signal=SIGKILL iperf' + SSH.command(cmd,'\$',5) + SSH.close() + + + iperf_time = self.Iperf_ComputeTime() + if self.iperf_direction=="DL": + logging.debug("Iperf for Module in DL mode detected") + #server side UE + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + cmd = 'rm iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.command(cmd,'\$',5) + cmd = 'echo $USER; nohup /opt/iperf-2.0.10/iperf -s -B ' + UE_IPAddress + ' -u 2>&1 > iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log &' + SSH.command(cmd,'\$',5) + SSH.close() + #client side EPC + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + cmd = 'rm iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.command(cmd,'\$',5) + cmd = 'iperf -c ' + UE_IPAddress + ' ' + self.iperf_args + ' 2>&1 > iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.command(cmd,'\$',int(iperf_time)*5.0) + SSH.close() + #copy the 2 resulting files locally + SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, 'iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log', '.') + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '.') + #send for analysis + filename='iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log' + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,filename,1) + + elif self.iperf_direction=="UL": + logging.debug("Iperf for Module in UL mode detected") + #server side EPC + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + cmd = 'rm iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.command(cmd,'\$',5) + cmd = 'echo $USER; nohup iperf -s -u 2>&1 > iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log &' + SSH.command(cmd,'\$',5) + SSH.close() + + #client side UE + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + cmd = 'rm iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log' + SSH.command(cmd,'\$',5) + SSH.command('/opt/iperf-2.0.10/iperf -c 192.172.0.1 ' + self.iperf_args + ' 2>&1 > iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '\$', int(iperf_time)*5.0) + SSH.close() + + #copy the 2 resulting files locally + SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '.') + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log', '.') + #send for analysis + filename='iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log' + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,filename,1) + else : + logging.debug("Incorrect or missing IPERF direction in XML") + + #kill iperf processes after to be clean + SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword) + cmd = 'killall --signal=SIGKILL iperf' + SSH.command(cmd,'\$',5) + SSH.close() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + cmd = 'killall --signal=SIGKILL iperf' + SSH.command(cmd,'\$',5) + SSH.close() + return + + def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue,EPC): + try: + SSH = sshconnection.SSHConnection() + # Single-UE profile -- iperf only on one UE + if self.iperf_profile == 'single-ue' and idx != 0: + return + useIperf3 = False + udpIperf = True + + self.ueIperfVersion = '2.0.5' + if (device_id != 'OAI-UE'): + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it + SSH.command('if [ ! -d ' + EPC.SourceCodePath + '/scripts ]; then mkdir -p ' + EPC.SourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) + # Checking if iperf / iperf3 are installed + if self.ADBCentralized: + SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) + # DEBUG: disabling iperf3 usage for the moment + result = re.search('iperf4', SSH.getBefore()) + if result is None: + result = re.search('iperf', SSH.getBefore()) + if result is None: + message = 'Neither iperf nor iperf3 installed on UE!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + else: + if self.ADBCentralized: + SSH.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) + result = re.search('iperf version 2.0.5', SSH.getBefore()) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', SSH.getBefore()) + if result is not None: + self.ueIperfVersion = '2.0.10' + else: + useIperf3 = True + SSH.close() + else: + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('iperf --version', '\$', 5) + result = re.search('iperf version 2.0.5', SSH.getBefore()) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', SSH.getBefore()) + if result is not None: + self.ueIperfVersion = '2.0.10' + SSH.close() + # in case of iperf, UL has its own function + if (not useIperf3): + result = re.search('-R', str(self.iperf_args)) + if result is not None: + self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue,EPC) + return + + # Launch the IPERF server on the UE side for DL + if (device_id == 'OAI-UE'): + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('-u', str(self.iperf_args)) + if result is None: + SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + udpIperf = False + else: + SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + else: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) + if self.ADBCentralized: + if (useIperf3): + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) + else: + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('-u', str(self.iperf_args)) + if result is None: + SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + udpIperf = False + else: + SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + else: + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) + + time.sleep(0.5) + SSH.close() + + # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + launchFromModule = False + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): + launchFromEpc = False + #if module + if self.ue_id!='' and self.iperf : + launchFromEpc = False + launchfromModule = True + # When using a docker-based deployment, IPERF client shall be launched from trf container + launchFromTrfContainer = False + if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): + launchFromTrfContainer = True + if launchFromEpc: + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) + iperf_time = self.Iperf_ComputeTime() + time.sleep(0.5) + + if udpIperf: + modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) + else: + modified_options = str(self.iperf_args) + time.sleep(0.5) + + if launchFromEpc: + SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + else: + if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') + if (useIperf3): + SSH.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + + clientStatus = 0 + self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue,SSH) + else: + if launchFromEpc: + if launchFromTrfContainer: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/iperf-2.0.5/bin/' + iperf_status = SSH.command('docker exec -it prod-trf-gen /bin/bash -c "' + prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + '" 2>&1 | tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + iperf_status = SSH.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + iperf_status = ret.returncode + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cat ' + EPC.SourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if iperf_status < 0: + if launchFromEpc: + SSH.close() + message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + logging.debug('Into Iperf_analyzeV2Output client') + clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options, EPC,SSH) + logging.debug('Iperf_analyzeV2Output clientStatus returned value = ' + str(clientStatus)) + SSH.close() + + # Kill the IPERF server that runs in background + if (device_id == 'OAI-UE'): + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('killall iperf', '\$', 5) + else: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) + result = re.search('shell +(?P\d+)', SSH.getBefore()) + if result is not None: + pid_iperf = result.group('pid') + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + SSH.close() + # if the client report is absent, try to analyze the server log file + if (clientStatus == -1): + time.sleep(1) + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + if (device_id == 'OAI-UE'): + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + else: + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.SourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + # fromdos has to be called on the python executor not on ADB server + cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 > /dev/null' + try: + subprocess.run(cmd, shell=True) + except: + pass + cmd = 'dos2unix -o iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 > /dev/null' + try: + subprocess.run(cmd, shell=True) + except: + pass + filename='iperf_server_' + self.testCase_id + '_' + device_id + '.log' + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options,filename,0) + + # in case of OAI UE: + if (device_id == 'OAI-UE'): + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + if not launchFromEpc: + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + else: + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def IperfNoS1(self,HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS): + SSH = sshconnection.SSHConnection() + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = True + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + server_on_enb = re.search('-R', str(self.iperf_args)) + if server_on_enb is not None: + iServerIPAddr = RAN.eNBIPAddress + iServerUser = RAN.eNBUserName + iServerPasswd = RAN.eNBPassword + iClientIPAddr = self.UEIPAddress + iClientUser = self.UEUserName + iClientPasswd = self.UEPassword + else: + iServerIPAddr = self.UEIPAddress + iServerUser = self.UEUserName + iServerPasswd = self.UEPassword + iClientIPAddr = RAN.eNBIPAddress + iClientUser = RAN.eNBUserName + iClientPasswd = RAN.eNBPassword + if self.iperf_options != 'sink': + # Starting the iperf server + SSH.open(iServerIPAddr, iServerUser, iServerPasswd) + # args SHALL be "-c client -u any" + # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 + # -B 10.0.1.1 -u -s -i 1 -fm + server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) + server_options = server_options.replace('-c','-B') + SSH.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) + time.sleep(0.5) + SSH.close() + + # Starting the iperf client + modified_options = self.Iperf_ComputeModifiedBW(0, 1) + modified_options = modified_options.replace('-R','') + iperf_time = self.Iperf_ComputeTime() + SSH.open(iClientIPAddr, iClientUser, iClientPasswd) + SSH.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) + iperf_status = SSH.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) + status_queue = SimpleQueue() + lock = Lock() + if iperf_status < 0: + message = 'iperf on OAI UE crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + clientStatus = -2 + else: + if self.iperf_options == 'sink': + clientStatus = 0 + status_queue.put(0) + status_queue.put('OAI-UE') + status_queue.put('10.0.1.2') + status_queue.put('Sink Test : no check') + else: + clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options, EPC,SSH) + SSH.close() + + # Stopping the iperf server + if self.iperf_options != 'sink': + SSH.open(iServerIPAddr, iServerUser, iServerPasswd) + SSH.command('killall --signal SIGKILL iperf', '\$', 5) + time.sleep(0.5) + SSH.close() + + if (clientStatus == -1): + if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '.log') + SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + filename='iperf_server_' + self.testCase_id + '_OAI-UE.log' + self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options,filename,0) + + # copying on the EPC server for logCollection + if (clientStatus == -1): + copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + if (copyin_res == 0): + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.SourceCodePath + '/scripts') + copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') + if (copyin_res == 0): + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.SourceCodePath + '/scripts') + iperf_noperf = False + if status_queue.empty(): + iperf_status = False + else: + iperf_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + iperf_status = False + if (count > 0): + iperf_noperf = True + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (iperf_noperf and iperf_status): + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + elif (iperf_status): + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + else: + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + + def Iperf(self,HTML,RAN,EPC,COTS_UE, InfraUE,CONTAINERS): + result = re.search('noS1', str(RAN.Initialize_eNB_args)) + if result is not None: + self.IperfNoS1(HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS) + return + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + check_eNB = True + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + check_OAI_UE = True + else: + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + if (pStatus < 0): + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + + if self.ue_id=="":#is not a module, follow legacy code + ueIpStatus = self.GetAllUEIPAddresses() + if (ueIpStatus < 0): + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + return + else: #is a module + self.UEIPAddresses=[] + Module_UE = cls_module_ue.Module_UE(InfraUE.ci_ue_infra[self.ue_id]) + Module_UE.GetModuleIPAddress() + self.UEIPAddresses.append(Module_UE.UEIPAddress) + + + + + self.dummyIperfVersion = '2.0.10' + #cmd = 'iperf --version' + #logging.debug(cmd + '\n') + #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) + #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.5' + #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.10' + + multi_jobs = [] + i = 0 + ue_num = len(self.UEIPAddresses) + lock = Lock() + status_queue = SimpleQueue() + logging.debug(self.UEIPAddresses) + for UE_IPAddress in self.UEIPAddresses: + device_id = self.UEDevices[i] + #special quick and dirty treatment for modules, iperf to be restructured + if self.ue_id!="": #is module + device_id = Module_UE.ID + "-" + Module_UE.Kind + p = Process(target = self.Iperf_Module ,args = (lock, UE_IPAddress, device_id, i, ue_num, status_queue, EPC, Module_UE,)) + else: #legacy code + p = Process(target = self.Iperf_common, args = (lock, UE_IPAddress, device_id, i, ue_num, status_queue, EPC, )) + p.daemon = True + p.start() + multi_jobs.append(p) + i = i + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + else: + iperf_status = True + iperf_noperf = False + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + iperf_status = False + if (count > 0): + iperf_noperf = True + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (iperf_noperf and iperf_status): + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + elif (iperf_status): + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + else: + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + + def CheckProcessExist(self, check_eNB, check_OAI_UE,RAN,EPC): + multi_jobs = [] + status_queue = SimpleQueue() + # in noS1 config, no need to check status from EPC + # in gNB also currently no need to check + result = re.search('noS1|band78', str(RAN.Initialize_eNB_args)) + if result is None: + p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + p = Process(target = EPC.CheckMMEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + p = Process(target = EPC.CheckSPGWProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + else: + if (check_eNB == False) and (check_OAI_UE == False): + return 0 + if check_eNB: + p = Process(target = RAN.CheckeNBProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + if check_OAI_UE: + p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + return -15 + else: + result = 0 + while (not status_queue.empty()): + status = status_queue.get() + if (status < 0): + result = status + if result == CONST.ENB_PROCESS_FAILED: + fileCheck = re.search('enb_', str(RAN.eNBLogFiles[0])) + if fileCheck is not None: + SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/' + RAN.eNBLogFiles[0], '.') + logStatus = RAN.AnalyzeLogFile_eNB(RAN.eNBLogFiles[0]) + if logStatus < 0: + result = logStatus + RAN.eNBLogFiles[0]='' + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: + self.TerminateFlexranCtrl() + return result + + def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag,HTML,RAN): + multi_jobs = [] + status_queue = SimpleQueue() + if initialize_OAI_UE_flag == False: + p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + return -15 + else: + result = 0 + while (not status_queue.empty()): + status = status_queue.get() + if (status < 0): + result = status + if result == CONST.OAI_UE_PROCESS_FAILED: + fileCheck = re.search('ue_', str(self.UELogFile)) + if fileCheck is not None: + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + logStatus = self.AnalyzeLogFile_UE(self.UELogFile,HTML,RAN) + if logStatus < 0: + result = logStatus + return result + + def CheckOAIUEProcess(self, status_queue): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + ' | grep -v grep', '\$', 5) + result = re.search(self.air_interface, SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') + status_queue.put(CONST.OAI_UE_PROCESS_FAILED) + else: + status_queue.put(CONST.OAI_UE_PROCESS_OK) + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + + def AnalyzeLogFile_UE(self, UElogFile,HTML,RAN): + if (not os.path.isfile('./' + UElogFile)): + return -1 + ue_log_file = open('./' + UElogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + uciStatMsgCount = 0 + pdcpDataReqFailedCount = 0 + badDciCount = 0 + f1aRetransmissionCount = 0 + fatalErrorCount = 0 + macBsrTimerExpiredCount = 0 + rrcConnectionRecfgComplete = 0 + no_cell_sync_found = False + mib_found = False + frequency_found = False + plmn_found = False + nrUEFlag = False + nrDecodeMib = 0 + nrFoundDCI = 0 + nrCRCOK = 0 + mbms_messages = 0 + HTML.htmlUEFailureMsg='' + global_status = CONST.ALL_PROCESSES_OK + for line in ue_log_file.readlines(): + result = re.search('nr_synchro_time', str(line)) + if result is not None: + nrUEFlag = True + if nrUEFlag: + result = re.search('decode mib', str(line)) + if result is not None: + nrDecodeMib += 1 + result = re.search('found 1 DCIs', str(line)) + if result is not None: + nrFoundDCI += 1 + result = re.search('CRC OK', str(line)) + if result is not None: + nrCRCOK += 1 + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('[Cc]ore [dD]ump', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('./lte-uesoftmodem', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('[Aa]ssertion', str(line)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('uci->stat', str(line)) + if result is not None and not exitSignalReceived: + uciStatMsgCount += 1 + result = re.search('PDCP data request failed', str(line)) + if result is not None and not exitSignalReceived: + pdcpDataReqFailedCount += 1 + result = re.search('bad DCI 1', str(line)) + if result is not None and not exitSignalReceived: + badDciCount += 1 + result = re.search('Format1A Retransmission but TBS are different', str(line)) + if result is not None and not exitSignalReceived: + f1aRetransmissionCount += 1 + result = re.search('FATAL ERROR', str(line)) + if result is not None and not exitSignalReceived: + fatalErrorCount += 1 + result = re.search('MAC BSR Triggered ReTxBSR Timer expiry', str(line)) + if result is not None and not exitSignalReceived: + macBsrTimerExpiredCount += 1 + result = re.search('Generating RRCConnectionReconfigurationComplete', str(line)) + if result is not None: + rrcConnectionRecfgComplete += 1 + # No cell synchronization found, abandoning + result = re.search('No cell synchronization found, abandoning', str(line)) + if result is not None: + no_cell_sync_found = True + if RAN.eNBmbmsEnables[0]: + result = re.search('TRIED TO PUSH MBMS DATA', str(line)) + if result is not None: + mbms_messages += 1 + result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P\d{1,3}), N_RB_DL (?P\d{1,3}), PHICH DURATION (?P\d), PHICH RESOURCE (?P.{1,4}), TX_ANT (?P\d)", str(line)) + if result is not None and (not mib_found): + try: + mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " nidcell = " + result.group('nidcell') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " n_rb_dl = " + result.group('n_rb_dl') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " phich_duration = " + result.group('phich_duration') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " phich_resource = " + result.group('phich_resource') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " tx_ant = " + result.group('tx_ant') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mib_found = True + except Exception as e: + logging.error('\033[91m' + "MIB marker was not found" + '\033[0m') + result = re.search("Measured Carrier Frequency (?P\d{1,15}) Hz", str(line)) + if result is not None and (not frequency_found): + try: + mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + frequency_found = True + except Exception as e: + logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m') + result = re.search("PLMN MCC (?P\d{1,3}), MNC (?P\d{1,3}), TAC", str(line)) + if result is not None and (not plmn_found): + try: + mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + plmn_found = True + except Exception as e: + logging.error('\033[91m' + "PLMN not found" + '\033[0m') + result = re.search("Found (?P[\w,\s]{1,15}) \(name from internal table\)", str(line)) + if result is not None: + try: + mibMsg = "The operator is: " + result.group('operator') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + except Exception as e: + logging.error('\033[91m' + "Operator name not found" + '\033[0m') + result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line)) + if result is not None: + try: + mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + ' -> ' + logging.debug('\033[94m' + mibMsg + '\033[0m') + except Exception as e: + logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') + result = re.search("DL Carrier Frequency/ARFCN : \-*(?P\d{1,15}/\d{1,4})", str(line)) + if result is not None: + try: + freq = result.group('carrier_frequency') + new_freq = re.sub('/[0-9]+','',freq) + float_freq = float(new_freq) / 1000000 + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' + logging.debug('\033[94m' + " DL Carrier Frequency is: " + str(freq) + '\033[0m') + except Exception as e: + logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') + result = re.search("AllowedMeasBandwidth : (?P\d{1,7})", str(line)) + if result is not None: + try: + prb = result.group('allowed_bandwidth') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + ' -- PRB: ' + prb + '\n' + logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') + except Exception as e: + logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') + ue_log_file.close() + if rrcConnectionRecfgComplete > 0: + statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' + logging.debug('\033[94m' + statMsg + '\033[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if nrUEFlag: + if nrDecodeMib > 0: + statMsg = 'UE showed ' + str(nrDecodeMib) + ' MIB decode message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if nrFoundDCI > 0: + statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if nrCRCOK > 0: + statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if not frequency_found: + statMsg = 'NR-UE could NOT synch!' + logging.error('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if uciStatMsgCount > 0: + statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if pdcpDataReqFailedCount > 0: + statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if badDciCount > 0: + statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1(A)" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if f1aRetransmissionCount > 0: + statMsg = 'UE showed ' + str(f1aRetransmissionCount) + ' "Format1A Retransmission but TBS are different" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if fatalErrorCount > 0: + statMsg = 'UE showed ' + str(fatalErrorCount) + ' "FATAL ERROR:" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if macBsrTimerExpiredCount > 0: + statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if RAN.eNBmbmsEnables[0]: + if mbms_messages > 0: + statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + else: + statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)' + logging.debug('\u001B[1;30;41m ' + statMsg + ' \u001B[0m') + global_status = CONST.OAI_UE_PROCESS_NO_MBMS_MSGS + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if foundSegFault: + logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') + if not nrUEFlag: + global_status = CONST.OAI_UE_PROCESS_SEG_FAULT + else: + if not frequency_found: + global_status = CONST.OAI_UE_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE showed an assertion!\n' + if not nrUEFlag: + if not mib_found or not frequency_found: + global_status = CONST.OAI_UE_PROCESS_ASSERTION + else: + if not frequency_found: + global_status = CONST.OAI_UE_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE faced real time issues!\n' + if nrUEFlag: + if not frequency_found: + global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC + else: + if no_cell_sync_found and not mib_found: + logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE could not synchronize!\n' + global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC + return global_status + + + def TerminateFlexranCtrl(self,HTML,RAN,EPC): + if RAN.flexranCtrlInstalled == False or RAN.flexranCtrlStarted == False: + return + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + SSH = sshconnection.SSHConnection() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('echo ' + EPC.Password + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + time.sleep(1) + SSH.command('echo ' + EPC.Password + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + time.sleep(1) + SSH.close() + RAN.flexranCtrlStarted=False + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def TerminateUE_common(self, device_id, idx,COTS_UE): + try: + SSH = sshconnection.SSHConnection() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # back in airplane mode on (ie radio off) + if self.ADBCentralized: + #RH quick add on to intgrate cots control defined by yaml + #if device Id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode ON (ie Radio OFF) + COTS_UE.Set_Airplane(device_id, 'ON') + elif device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') + + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) + result = re.search('shell +(?P\d+)', SSH.getBefore()) + if result is not None: + pid_iperf = result.group('pid') + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def TerminateUE(self,HTML,COTS_UE,InfraUE,ue_trace): + if self.ue_id=='':#no ID specified, then it is a COTS controlled by ADB + terminate_ue_flag = False + self.GetAllUEDevices(terminate_ue_flag) + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target= self.TerminateUE_common, args = (device_id,i,COTS_UE,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + else: #if an ID is specified, it is a module from the yaml infrastructure file + Module_UE = cls_module_ue.Module_UE(InfraUE.ci_ue_infra[self.ue_id]) + Module_UE.ue_trace=ue_trace + Module_UE.Command("detach") + Module_UE.DisableTrace() + Module_UE.DisableCM() + archive_destination=Module_UE.LogCollect() + if Module_UE.ue_trace=='yes': + HTML.CreateHtmlTestRow('QLog at : '+archive_destination, 'OK', CONST.ALL_PROCESSES_OK) + else: + HTML.CreateHtmlTestRow('QLog trace is disabled', 'OK', CONST.ALL_PROCESSES_OK) + + def TerminateOAIUE(self,HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS): + SSH = sshconnection.SSHConnection() + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT -r .*-uesoftmodem || true', '\$', 5) + time.sleep(10) + SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL -r .*-uesoftmodem || true', '\$', 5) + time.sleep(5) + SSH.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.close() + result = re.search('ue_', str(self.UELogFile)) + if result is not None: + copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + if (copyin_res == -1): + logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') + HTML.htmlUEFailureMsg='Could not copy UE logfile to analyze it!' + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') + self.UELogFile = '' + return + logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_UE(self.UELogFile,HTML,RAN) + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is not None: + ueAction = 'Sniffing' + else: + ueAction = 'Connection' + if (logStatus < 0): + logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') + HTML.htmlUEFailureMsg='' + ueAction + ' Failed\n' + HTML.htmlUEFailureMsg + HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') + if self.air_interface == 'lte-uesoftmodem': + # In case of sniffing on commercial eNBs we have random results + # Not an error then + if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): + self.Initialize_OAI_UE_args = '' + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + else: + if (logStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): + self.Initialize_OAI_UE_args = '' + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + else: + logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') + HTML.htmlUEFailureMsg='' + ueAction + ' Completed\n' + HTML.htmlUEFailureMsg + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + self.UELogFile = '' + else: + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def AutoTerminateUEandeNB(self,HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS): + if (self.ADBIPAddress != 'none'): + self.testCase_id = 'AUTO-KILL-UE' + HTML.testCase_id = self.testCase_id + self.desc = 'Automatic Termination of UE' + HTML.desc = self.desc + self.ShowTestID() + self.TerminateUE(HTML,COTS_UE,InfraUE,self.ue_trace) + if (self.Initialize_OAI_UE_args != ''): + self.testCase_id = 'AUTO-KILL-OAI-UE' + HTML.testCase_id = self.testCase_id + self.desc = 'Automatic Termination of OAI-UE' + HTML.desc = self.desc + self.ShowTestID() + self.TerminateOAIUE(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) + if (RAN.Initialize_eNB_args != ''): + self.testCase_id = 'AUTO-KILL-RAN' + HTML.testCase_id = self.testCase_id + self.desc = 'Automatic Termination of all RAN nodes' + HTML.desc = self.desc + self.ShowTestID() + #terminate all RAN nodes eNB/gNB/OCP + for instance in range(0, len(RAN.air_interface)): + if RAN.air_interface[instance]!='': + logging.debug('Auto Termination of Instance ' + str(instance) + ' : ' + RAN.air_interface[instance]) + RAN.eNB_instance=instance + RAN.TerminateeNB(HTML,EPC) + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: + self.testCase_id = 'AUTO-KILL-flexran-ctl' + HTML.testCase_id = self.testCase_id + self.desc = 'Automatic Termination of FlexRan CTL' + HTML.desc = self.desc + self.ShowTestID() + self.TerminateFlexranCtrl(HTML,RAN,EPC) + if CONTAINERS.yamlPath[0] != '': + self.testCase_id = 'AUTO-KILL-CONTAINERS' + HTML.testCase_id = self.testCase_id + self.desc = 'Automatic Termination of all RAN containers' + HTML.desc = self.desc + self.ShowTestID() + for instance in range(0, len(CONTAINERS.yamlPath)): + if CONTAINERS.yamlPath[instance]!='': + CONTAINERS.eNB_instance=instance + CONTAINERS.UndeployObject(HTML,RAN) + RAN.prematureExit=True + + def IdleSleep(self,HTML): + time.sleep(self.idle_sleep_time) + HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK) + + def X2_Status(self, idx, fileName): + cmd = "curl --silent http://" + EPC.IPAddress + ":9999/stats | jq '.' > " + fileName + message = cmd + '\n' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + if idx == 0: + cmd = "jq '.mac_stats | length' " + fileName + strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2NbENBs = int(strNbEnbs.strip()) + cnt = 0 + while cnt < self.x2NbENBs: + cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName + bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2ENBBsIds[idx].append(bs_id.strip()) + cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName + stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) + nbUEs = int(stNbUEs.strip()) + ueIdx = 0 + self.x2ENBConnectedUEs[idx].append([]) + while ueIdx < nbUEs: + cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName + rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip()) + ueIdx += 1 + cnt += 1 + + msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" + logging.debug(msg) + message += msg + '\n' + cnt = 0 + while cnt < self.x2NbENBs: + msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][cnt])) + " UE(s)" + logging.debug(msg) + message += msg + '\n' + ueIdx = 0 + while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]): + msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx]) + logging.debug(msg) + message += msg + '\n' + ueIdx += 1 + cnt += 1 + return message + + def Perform_X2_Handover(self,HTML,RAN,EPC): + html_queue = SimpleQueue() + fullMessage = '
'
+		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
+		logging.debug(msg)
+		fullMessage += msg + '\n'
+		if self.x2_ho_options == 'network':
+			if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted:
+				self.x2ENBBsIds = []
+				self.x2ENBConnectedUEs = []
+				self.x2ENBBsIds.append([])
+				self.x2ENBBsIds.append([])
+				self.x2ENBConnectedUEs.append([])
+				self.x2ENBConnectedUEs.append([])
+				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
+
+				msg = "Activating the X2 Net control on each eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				eNB_cnt = self.x2NbENBs
+				cnt = 0
+				while cnt < eNB_cnt:
+					cmd = "curl -XPOST http://" + EPC.IPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1"
+					logging.debug(cmd)
+					fullMessage += cmd + '\n'
+					subprocess.run(cmd, shell=True)
+					cnt += 1
+				# Waiting for the activation to be active
+				time.sleep(10)
+				msg = "Switching UE(s) from eNB to eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				cnt = 0
+				while cnt < eNB_cnt:
+					ueIdx = 0
+					while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]):
+						cmd = "curl -XPOST http://" + EPC.IPAddress() + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
+						logging.debug(cmd)
+						fullMessage += cmd + '\n'
+						subprocess.run(cmd, shell=True)
+						ueIdx += 1
+					cnt += 1
+				time.sleep(10)
+				# check
+				logging.debug("Checking the Status after X2 Handover")
+				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
+				cnt = 0
+				x2Status = True
+				while cnt < eNB_cnt:
+					if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
+						x2Status = False
+					cnt += 1
+				if x2Status:
+					msg = "X2 Handover was successful"
+					logging.debug(msg)
+					fullMessage += msg + '
' + html_queue.put(fullMessage) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + else: + msg = "X2 Handover FAILED" + logging.error(msg) + fullMessage += msg + '' + html_queue.put(fullMessage) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + else: + HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK) + + def LogCollectBuild(self,RAN): + SSH = sshconnection.SSHConnection() + if (RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != ''): + IPAddress = RAN.eNBIPAddress + UserName = RAN.eNBUserName + Password = RAN.eNBPassword + SourceCodePath = RAN.eNBSourceCodePath + elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): + IPAddress = self.UEIPAddress + UserName = self.UEUserName + Password = self.UEPassword + SourceCodePath = self.UESourceCodePath + else: + sys.exit('Insufficient Parameter') + SSH.open(IPAddress, UserName, Password) + SSH.command('cd ' + SourceCodePath, '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('rm -f build.log.zip', '\$', 5) + SSH.command('zip -r build.log.zip build_log_*/*', '\$', 60) + SSH.close() + + def LogCollectPing(self,EPC): + SSH = sshconnection.SSHConnection() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('rm -f ping.log.zip', '\$', 5) + SSH.command('zip ping.log.zip ping*.log', '\$', 60) + SSH.command('rm ping*.log', '\$', 5) + SSH.close() + + def LogCollectIperf(self,EPC): + SSH = sshconnection.SSHConnection() + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('rm -f iperf.log.zip', '\$', 5) + SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) + SSH.command('rm iperf*.log', '\$', 5) + SSH.close() + + def LogCollectOAIUE(self): + SSH = sshconnection.SSHConnection() + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) + SSH.close() + + def RetrieveSystemVersion(self, machine,HTML,RAN): + if RAN.eNBIPAddress == 'none' or self.UEIPAddress == 'none': + HTML.OsVersion[0]='Ubuntu 16.04.5 LTS' + HTML.KernelVersion[0]='4.15.0-45-generic' + HTML.UhdVersion[0]='3.13.0.1-0' + HTML.UsrpBoard[0]='B210' + HTML.CpuNb[0]='4' + HTML.CpuModel[0]='Intel(R) Core(TM) i5-6200U' + HTML.CpuMHz[0]='2399.996 MHz' + return 0 + if machine == 'eNB': + if RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != '': + IPAddress = RAN.eNBIPAddress + UserName = RAN.eNBUserName + Password = RAN.eNBPassword + idx = 0 + else: + return -1 + if machine == 'UE': + if self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '': + IPAddress = self.UEIPAddress + UserName = self.UEUserName + Password = self.UEPassword + idx = 1 + else: + return -1 + + SSH = sshconnection.SSHConnection() + SSH.open(IPAddress, UserName, Password) + SSH.command('lsb_release -a', '\$', 5) + result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) + if result is not None: + OsVersion = result.group('os_type') + logging.debug('OS is: ' + OsVersion) + HTML.OsVersion[idx]=OsVersion + else: + SSH.command('hostnamectl', '\$', 5) + result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) + if result is not None: + OsVersion = result.group('os_type') + if OsVersion == 'CentOS Linux 7 ': + SSH.command('cat /etc/redhat-release', '\$', 5) + result = re.search('CentOS Linux release (?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + OsVersion = OsVersion.replace('7 ', result.group('os_version')) + logging.debug('OS is: ' + OsVersion) + HTML.OsVersion[idx]=OsVersion + SSH.command('uname -r', '\$', 5) + result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) + if result is not None: + KernelVersion = result.group('kernel_version') + logging.debug('Kernel Version is: ' + KernelVersion) + HTML.KernelVersion[idx]=KernelVersion + SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) + result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + UhdVersion) + HTML.UhdVersion[idx]=UhdVersion + else: + SSH.command('uhd_config_info --version', '\$', 5) + result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', SSH.getBefore()) + if result is not None: + UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + UhdVersion) + HTML.UhdVersion[idx]=UhdVersion + SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 180) + usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', SSH.getBefore()) + count = 0 + for board in usrp_boards: + if count == 0: + UsrpBoard = board + else: + UsrpBoard += ',' + board + count += 1 + if count > 0: + logging.debug('USRP Board(s) : ' + UsrpBoard) + HTML.UsrpBoard[idx]=UsrpBoard + SSH.command('lscpu', '\$', 5) + result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + CpuNb = result.group('nb_cpus') + logging.debug('nb_cpus: ' + CpuNb) + HTML.CpuNb[idx]=CpuNb + CpuModel = result.group('model') + logging.debug('model: ' + CpuModel) + HTML.CpuModel[idx]=CpuModel + CpuMHz = result.group('cpu_mhz') + ' MHz' + logging.debug('cpu_mhz: ' + CpuMHz) + HTML.CpuMHz[idx]=CpuMHz + SSH.close() + + def ConditionalExit(self): + if self.testUnstable: + if self.testStabilityPointReached or self.testMinStableId == '999999': + sys.exit(0) + sys.exit(1) + + def ShowTestID(self): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') + logging.debug('\u001B[1m' + self.desc + '\u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') diff --git a/ci-scripts/cls_physim.py b/ci-scripts/cls_physim.py index 4ca36b8cf0..e825b2f7bd 100644 --- a/ci-scripts/cls_physim.py +++ b/ci-scripts/cls_physim.py @@ -1,191 +1,191 @@ -# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -# * contributor license agreements. See the NOTICE file distributed with -# * this work for additional information regarding copyright ownership. -# * The OpenAirInterface Software Alliance licenses this file to You under -# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 -# * -# * 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. -# *------------------------------------------------------------------------------- -# * For more information about the OpenAirInterface (OAI) Software Alliance: -# * contact@openairinterface.org -# */ -#--------------------------------------------------------------------- -# Python for CI of OAI-eNB + COTS-UE -# -# Required Python Version -# Python 3.x -# -# Required Python Package -# pexpect -#--------------------------------------------------------------------- - -#to use logging.info() -import logging -#to create a SSH object locally in the methods -import sshconnection -#to update the HTML object -import html -from multiprocessing import SimpleQueue -#for log folder maintenance -import os - -class PhySim: - def __init__(self): - self.buildargs = "" - self.runargs = "" - self.eNBIpAddr = "" - self.eNBUserName = "" - self.eNBPassWord = "" - self.eNBSourceCodePath = "" - self.ranRepository = "" - self.ranBranch = "" - self.ranCommitID= "" - self.ranAllowMerge= "" - self.ranTargetBranch= "" - self.exitStatus=0 - self.forced_workspace_cleanup=False - #private attributes - self.__workSpacePath='' - self.__buildLogFile='compile_phy_sim.log' - self.__runLogFile='' - self.__runResults=[] - self.__runLogPath='phy_sim_logs' - - -#----------------- -#PRIVATE Methods -#----------------- - - def __CheckResults_PhySim(self,HTML,CONST,testcase_id): - mySSH = sshconnection.SSHConnection() - mySSH.open(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord) - #retrieve run log file and store it locally$ - mySSH.copyin(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord, self.__workSpacePath+self.__runLogFile, '.') - mySSH.close() - #parse results looking for Encoding and Decoding mean values - self.__runResults=[] - with open(self.__runLogFile) as f: - for line in f: - if 'mean' in line: - self.__runResults.append(line) - #the values are appended for each mean value (2), so we take these 2 values from the list - info=self.__runResults[0]+self.__runResults[1] - - #once parsed move the local logfile to its folder for tidiness - os.system('mv '+self.__runLogFile+' '+ self.__runLogPath+'/.') - - #updating the HTML with results - html_cell = '
' + info  + '
' - html_queue=SimpleQueue() - html_queue.put(html_cell) - HTML.CreateHtmlTestRowQueue(self.runargs, 'OK', 1, html_queue) - return HTML - - - def __CheckBuild_PhySim(self, HTML, CONST): - self.__workSpacePath=self.eNBSourceCodePath+'/cmake_targets/' - mySSH = sshconnection.SSHConnection() - mySSH.open(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord) - #retrieve compile log file and store it locally - mySSH.copyin(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord, self.__workSpacePath+self.__buildLogFile, '.') - #delete older run log file - mySSH.command('rm ' + self.__workSpacePath+self.__runLogFile, '\$', 5) - mySSH.close() - #check build result from local compile log file - buildStatus=False - with open(self.__buildLogFile) as f: - #nr_prachsim is the last compile step - if 'nr_prachsim compiled' in f.read(): - buildStatus=True - #update HTML based on build status - if buildStatus: - HTML.CreateHtmlTestRow(self.buildargs, 'OK', CONST.ALL_PROCESSES_OK, 'LDPC') - self.exitStatus=0 - else: - logging.error('\u001B[1m Building Physical Simulators Failed\u001B[0m') - HTML.CreateHtmlTestRow(self.buildargs, 'KO', CONST.ALL_PROCESSES_OK, 'LDPC') - HTML.CreateHtmlTabFooter(False) - #exitStatus=1 will do a sys.exit in main - self.exitStatus=1 - return HTML - - -#-----------------$ -#PUBLIC Methods$ -#-----------------$ - - def Build_PhySim(self,htmlObj,constObj): - mySSH = sshconnection.SSHConnection() - mySSH.open(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord) - - #create working dir - mySSH.command('mkdir -p ' + self.eNBSourceCodePath, '\$', 5) - mySSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) - - if not self.ranRepository.lower().endswith('.git'): - self.ranRepository+='.git' - - #git clone - mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) - #git config - mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) - - #git clean depending on self.forced_workspace_cleanup captured in xml - if self.forced_workspace_cleanup==True: - logging.info('Cleaning workspace ...') - mySSH.command('echo ' + self.eNBPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) - else: - logging.info('Workspace cleaning was disabled') - - # if the commit ID is provided, use it to point to it - if self.ranCommitID != '': - mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should have already been checked earlier - if (self.ranAllowMerge): - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - mySSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.info('Merging with the target branch: ' + self.ranTargetBranch) - mySSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - - #build - mySSH.command('source oaienv', '\$', 5) - mySSH.command('cd cmake_targets', '\$', 5) - mySSH.command('mkdir -p log', '\$', 5) - mySSH.command('chmod 777 log', '\$', 5) - mySSH.command('stdbuf -o0 ./build_oai ' + self.buildargs + ' 2>&1 | stdbuf -o0 tee ' + self.__buildLogFile, 'Bypassing the Tests|build have failed', 1500) - - mySSH.close() - #check build status and update HTML object - lHTML = html.HTMLManagement() - lHTML=self.__CheckBuild_PhySim(htmlObj,constObj) - return lHTML - - - def Run_PhySim(self,htmlObj,constObj,testcase_id): - #create run logs folder locally - os.system('mkdir -p ./'+self.__runLogPath) - #log file is tc_.log remotely - self.__runLogFile='physim_'+str(testcase_id)+'.log' - #open a session for test run - mySSH = sshconnection.SSHConnection() - mySSH.open(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord) - mySSH.command('cd '+self.__workSpacePath,'\$',5) - #run and redirect the results to a log file - mySSH.command(self.__workSpacePath+'phy_simulators/build/ldpctest ' + self.runargs + ' >> '+self.__runLogFile, '\$', 30) - mySSH.close() - #return updated HTML to main - lHTML = html.HTMLManagement() - lHTML=self.__CheckResults_PhySim(htmlObj,constObj,testcase_id) - return lHTML +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#to use logging.info() +import logging +#to create a SSH object locally in the methods +import sshconnection +#to update the HTML object +import html +from multiprocessing import SimpleQueue +#for log folder maintenance +import os + +class PhySim: + def __init__(self): + self.buildargs = "" + self.runargs = "" + self.eNBIpAddr = "" + self.eNBUserName = "" + self.eNBPassWord = "" + self.eNBSourceCodePath = "" + self.ranRepository = "" + self.ranBranch = "" + self.ranCommitID= "" + self.ranAllowMerge= "" + self.ranTargetBranch= "" + self.exitStatus=0 + self.forced_workspace_cleanup=False + #private attributes + self.__workSpacePath='' + self.__buildLogFile='compile_phy_sim.log' + self.__runLogFile='' + self.__runResults=[] + self.__runLogPath='phy_sim_logs' + + +#----------------- +#PRIVATE Methods +#----------------- + + def __CheckResults_PhySim(self,HTML,CONST,testcase_id): + mySSH = sshconnection.SSHConnection() + mySSH.open(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord) + #retrieve run log file and store it locally$ + mySSH.copyin(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord, self.__workSpacePath+self.__runLogFile, '.') + mySSH.close() + #parse results looking for Encoding and Decoding mean values + self.__runResults=[] + with open(self.__runLogFile) as f: + for line in f: + if 'mean' in line: + self.__runResults.append(line) + #the values are appended for each mean value (2), so we take these 2 values from the list + info=self.__runResults[0]+self.__runResults[1] + + #once parsed move the local logfile to its folder for tidiness + os.system('mv '+self.__runLogFile+' '+ self.__runLogPath+'/.') + + #updating the HTML with results + html_cell = '
' + info  + '
' + html_queue=SimpleQueue() + html_queue.put(html_cell) + HTML.CreateHtmlTestRowQueue(self.runargs, 'OK', 1, html_queue) + return HTML + + + def __CheckBuild_PhySim(self, HTML, CONST): + self.__workSpacePath=self.eNBSourceCodePath+'/cmake_targets/' + mySSH = sshconnection.SSHConnection() + mySSH.open(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord) + #retrieve compile log file and store it locally + mySSH.copyin(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord, self.__workSpacePath+self.__buildLogFile, '.') + #delete older run log file + mySSH.command('rm ' + self.__workSpacePath+self.__runLogFile, '\$', 5) + mySSH.close() + #check build result from local compile log file + buildStatus=False + with open(self.__buildLogFile) as f: + #nr_prachsim is the last compile step + if 'nr_prachsim compiled' in f.read(): + buildStatus=True + #update HTML based on build status + if buildStatus: + HTML.CreateHtmlTestRow(self.buildargs, 'OK', CONST.ALL_PROCESSES_OK, 'LDPC') + self.exitStatus=0 + else: + logging.error('\u001B[1m Building Physical Simulators Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.buildargs, 'KO', CONST.ALL_PROCESSES_OK, 'LDPC') + HTML.CreateHtmlTabFooter(False) + #exitStatus=1 will do a sys.exit in main + self.exitStatus=1 + return HTML + + +#-----------------$ +#PUBLIC Methods$ +#-----------------$ + + def Build_PhySim(self,htmlObj,constObj): + mySSH = sshconnection.SSHConnection() + mySSH.open(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord) + + #create working dir + mySSH.command('mkdir -p ' + self.eNBSourceCodePath, '\$', 5) + mySSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) + + if not self.ranRepository.lower().endswith('.git'): + self.ranRepository+='.git' + + #git clone + mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + #git config + mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) + + #git clean depending on self.forced_workspace_cleanup captured in xml + if self.forced_workspace_cleanup==True: + logging.info('Cleaning workspace ...') + mySSH.command('echo ' + self.eNBPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + else: + logging.info('Workspace cleaning was disabled') + + # if the commit ID is provided, use it to point to it + if self.ranCommitID != '': + mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 30) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should have already been checked earlier + if (self.ranAllowMerge): + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + mySSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.info('Merging with the target branch: ' + self.ranTargetBranch) + mySSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + + #build + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('mkdir -p log', '\$', 5) + mySSH.command('chmod 777 log', '\$', 5) + mySSH.command('stdbuf -o0 ./build_oai ' + self.buildargs + ' 2>&1 | stdbuf -o0 tee ' + self.__buildLogFile, 'Bypassing the Tests|build have failed', 1500) + + mySSH.close() + #check build status and update HTML object + lHTML = html.HTMLManagement() + lHTML=self.__CheckBuild_PhySim(htmlObj,constObj) + return lHTML + + + def Run_PhySim(self,htmlObj,constObj,testcase_id): + #create run logs folder locally + os.system('mkdir -p ./'+self.__runLogPath) + #log file is tc_.log remotely + self.__runLogFile='physim_'+str(testcase_id)+'.log' + #open a session for test run + mySSH = sshconnection.SSHConnection() + mySSH.open(self.eNBIpAddr, self.eNBUserName, self.eNBPassWord) + mySSH.command('cd '+self.__workSpacePath,'\$',5) + #run and redirect the results to a log file + mySSH.command(self.__workSpacePath+'phy_simulators/build/ldpctest ' + self.runargs + ' >> '+self.__runLogFile, '\$', 30) + mySSH.close() + #return updated HTML to main + lHTML = html.HTMLManagement() + lHTML=self.__CheckResults_PhySim(htmlObj,constObj,testcase_id) + return lHTML diff --git a/ci-scripts/cls_physim1.py b/ci-scripts/cls_physim1.py new file mode 100644 index 0000000000..b7a730e91c --- /dev/null +++ b/ci-scripts/cls_physim1.py @@ -0,0 +1,361 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import logging +import sshconnection as SSH +import html +import os +import re +import time +import subprocess +import sys +import constants as CONST +import helpreadme as HELP + +class PhySim: + def __init__(self): + self.eNBIpAddr = "" + self.eNBUserName = "" + self.eNBPassword = "" + self.OCUserName = "" + self.OCPassword = "" + self.OCProjectName = "" + self.eNBSourceCodePath = "" + self.ranRepository = "" + self.ranBranch = "" + self.ranCommitID= "" + self.ranAllowMerge= False + self.ranTargetBranch= "" + self.testResult = {} + self.testCount = [0,0,0] + self.testSummary = {} + self.testStatus = False + +#-----------------$ +#PUBLIC Methods$ +#-----------------$ + + def Deploy_PhySim(self, HTML, RAN): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + ocUserName = self.OCUserName + ocPassword = self.OCPassword + ocProjectName = self.OCProjectName + + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '' or ocUserName == '' or ocPassword == '' or ocProjectName == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('Building on server: ' + lIpAddr) + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + + self.testCase_id = HTML.testCase_id + + # on RedHat/CentOS .git extension is mandatory + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository.replace('git/', 'git') + else: + full_ran_repo_name = self.ranRepository + '.git' + mySSH.command('echo ' + lPassWord + ' | sudo rm -Rf ' + lSourcePath, '\$', 30) + mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) + mySSH.command('cd ' + lSourcePath, '\$', 5) + mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) + + mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + mySSH.command('mkdir -p cmake_targets/log', '\$', 5) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 30) + if self.ranAllowMerge: + imageTag = "ci-temp" + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + mySSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + mySSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + else: + imageTag = "develop" + # Check if image is exist on the Red Hat server, before pushing it to OC cluster + mySSH.command('sudo podman image inspect --format="Size = {{.Size}} bytes" oai-physim:' + imageTag, '\$', 60) + if mySSH.getBefore().count('no such image') != 0: + logging.error('\u001B[1m No such image oai-physim\u001B[0m') + mySSH.close() + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.PHYSIM_IMAGE_ABSENT) + RAN.prematureExit = True + return + else: + result = re.search('Size *= *(?P[0-9\-]+) *bytes', mySSH.getBefore()) + if result is not None: + imageSize = float(result.group('size')) + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m oai-physim size is ' + ('%.0f' % imageSize) + ' kbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m oai-physim size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + logging.debug('\u001B[1m oai-physim is ' + ('%.3f' % imageSize) + ' Gbytes\u001B[0m') + else: + logging.debug('oai-physim size is unknown') + + # logging to OC Cluster and then switch to corresponding project + mySSH.command(f'oc login -u {ocUserName} -p {ocPassword}', '\$', 30) + if mySSH.getBefore().count('Login successful.') == 0: + logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m') + mySSH.close() + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL) + RAN.prematureExit = True + return + else: + logging.debug('\u001B[1m Login to OC Cluster Successfully\u001B[0m') + mySSH.command(f'oc project {ocProjectName}', '\$', 30) + if mySSH.getBefore().count(f'Already on project "{ocProjectName}"') == 0 and mySSH.getBefore().count(f'Now using project "{self.OCProjectName}"') == 0: + logging.error(f'\u001B[1m Unable to access OC project {ocProjectName}\u001B[0m') + mySSH.close() + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_PROJECT_FAIL) + RAN.prematureExit = True + return + else: + logging.debug(f'\u001B[1m Now using project {ocProjectName}\u001B[0m') + + # Tag the image and push to the OC cluster + mySSH.command('oc whoami -t | sudo podman login -u ' + ocUserName + ' --password-stdin https://default-route-openshift-image-registry.apps.5glab.nsa.eurecom.fr/ --tls-verify=false', '\$', 30) + if mySSH.getBefore().count('Login Succeeded!') == 0: + logging.error('\u001B[1m Podman Login to OC Cluster Registry Failed\u001B[0m') + mySSH.close() + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL) + RAN.prematureExit = True + return + else: + logging.debug('\u001B[1m Podman Login to OC Cluster Registry Successfully\u001B[0m') + time.sleep(2) + mySSH.command('oc create -f openshift/oai-physim-image-stream.yml', '\$', 30) + if mySSH.getBefore().count('(AlreadyExists):') == 0 and mySSH.getBefore().count('created') == 0: + logging.error(f'\u001B[1m Image Stream "oai-physim" Creation Failed on OC Cluster {ocProjectName}\u001B[0m') + mySSH.close() + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_IS_FAIL) + RAN.prematureExit = True + return + else: + logging.debug(f'\u001B[1m Image Stream "oai-physim" created on OC project {ocProjectName}\u001B[0m') + time.sleep(2) + mySSH.command(f'sudo podman tag oai-physim:{imageTag} default-route-openshift-image-registry.apps.5glab.nsa.eurecom.fr/{self.OCProjectName}/oai-physim:{imageTag}', '\$', 30) + time.sleep(2) + mySSH.command(f'sudo podman push default-route-openshift-image-registry.apps.5glab.nsa.eurecom.fr/{self.OCProjectName}/oai-physim:{imageTag} --tls-verify=false', '\$', 180) + if mySSH.getBefore().count('Storing signatures') == 0: + logging.error('\u001B[1m Image "oai-physim" push to OC Cluster Registry Failed\u001B[0m') + mySSH.close() + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_IS_FAIL) + RAN.prematureExit = True + return + else: + logging.debug('\u001B[1m Image "oai-physim" push to OC Cluster Registry Successfully\u001B[0m') + + # Using helm charts deployment + time.sleep(5) + mySSH.command(f'sed -i -e "s#TAG#{imageTag}#g" ./charts/physims/values.yaml', '\$', 6) + mySSH.command('helm install physim ./charts/physims/ | tee -a cmake_targets/log/physim_helm_summary.txt 2>&1', '\$', 30) + if mySSH.getBefore().count('STATUS: deployed') == 0: + logging.error('\u001B[1m Deploying PhySim Failed using helm chart on OC Cluster\u001B[0m') + mySSH.command('helm uninstall physim >> cmake_targets/log/physim_helm_summary.txt 2>&1', '\$', 30) + isFinished1 = False + while(isFinished1 == False): + time.sleep(20) + mySSH.command('oc get pods -l app.kubernetes.io/instance=physim', '\$', 6, resync=True) + if re.search('No resources found', mySSH.getBefore()): + isFinished1 = True + mySSH.command(f'sudo podman rmi default-route-openshift-image-registry.apps.5glab.nsa.eurecom.fr/{self.OCProjectName}/oai-physim:{imageTag}', '\$', 30) + mySSH.command('oc delete is oai-physim', '\$', 30) + mySSH.close() + self.AnalyzeLogFile_phySim(HTML) + RAN.prematureExit = True + return + else: + logging.debug('\u001B[1m Deployed PhySim Successfully using helm chart\u001B[0m') + isRunning = False + count = 0 + while(count < 2 and isRunning == False): + time.sleep(60) + mySSH.command('oc get pods -o wide -l app.kubernetes.io/instance=physim | tee -a cmake_targets/log/physim_pods_summary.txt', '\$', 30, resync=True) + if mySSH.getBefore().count('Running') == 12: + logging.debug('\u001B[1m Running the physim test Scenarios\u001B[0m') + isRunning = True + podNames = re.findall('oai-[\S\d\w]+', mySSH.getBefore()) + count +=1 + if isRunning == False: + logging.error('\u001B[1m Some PODS Running FAILED \u001B[0m') + mySSH.command('oc get pods -l app.kubernetes.io/instance=physim 2>&1 | tee -a cmake_targets/log/physim_pods_summary.txt', '\$', 6) + mySSH.command('helm uninstall physim >> cmake_targets/log/physim_helm_summary.txt 2>&1', '\$', 6) + self.AnalyzeLogFile_phySim(HTML) + isFinished1 = False + while(isFinished1 == False): + time.sleep(20) + mySSH.command('oc get pods -l app.kubernetes.io/instance=physim', '\$', 6, resync=True) + if re.search('No resources found', mySSH.getBefore()): + isFinished1 = True + mySSH.command(f'sudo podman rmi default-route-openshift-image-registry.apps.5glab.nsa.eurecom.fr/{self.OCProjectName}/oai-physim:{imageTag}', '\$', 6) + mySSH.command('oc delete is oai-physim', '\$', 6) + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_PHYSIM_DEPLOY_FAIL) + HTML.CreateHtmlTestRowPhySimTestResult(self.testSummary,self.testResult) + RAN.prematureExit = True + return + # Waiting to complete the running test + count = 0 + isFinished = False + # doing a deep copy! + tmpPodNames = podNames.copy() + while(count < 32 and isFinished == False): + time.sleep(60) + for podName in tmpPodNames: + mySSH.command2(f'oc logs --tail=1 {podName} 2>&1', 6, silent=True) + if mySSH.cmd2Results.count('FINISHED') != 0: + logging.debug(podName + ' is finished') + tmpPodNames.remove(podName) + if not tmpPodNames: + isFinished = True + count += 1 + if isFinished: + logging.debug('\u001B[1m PhySim test is Complete\u001B[0m') + else: + logging.error('\u001B[1m PhySim test Timed-out!\u001B[0m') + + # Getting the logs of each executables running in individual pods + for podName in podNames: + mySSH.command(f'oc logs {podName} >> cmake_targets/log/physim_test.txt 2>&1', '\$', 15, resync=True) + time.sleep(30) + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/log/physim_test.txt', '.') + try: + listLogFiles = subprocess.check_output('egrep --colour=never "Execution Log file|Linux oai-" physim_test.txt', shell=True, universal_newlines=True) + for line in listLogFiles.split('\n'): + res1 = re.search('Linux (?Poai-[a-zA-Z0-9\-]+) ', str(line)) + res2 = re.search('Execution Log file = (?P[a-zA-Z0-9\-\/\.\_]+)', str(line)) + if res1 is not None: + podName = res1.group('pod') + if res2 is not None: + logFileInPod = res2.group('name') + folderName = re.sub('/opt/oai-physim/cmake_targets/autotests/log/', '', logFileInPod) + folderName = re.sub('/test.*', '', folderName) + fileName = re.sub('/opt/oai-physim/cmake_targets/autotests/log/' + folderName + '/', '', logFileInPod) + mySSH.command('mkdir -p cmake_targets/log/' + folderName, '\$', 5, silent=True) + mySSH.command('oc cp ' + podName + ':' + logFileInPod + ' cmake_targets/log/' + folderName + '/' + fileName, '\$', 20, silent=True) + except Exception as e: + pass + + # UnDeploy the physical simulator pods + mySSH.command('helm uninstall physim | tee -a cmake_targets/log/physim_helm_summary.txt 2>&1', '\$', 6) + isFinished1 = False + while(isFinished1 == False): + time.sleep(20) + mySSH.command('oc get pods -l app.kubernetes.io/instance=physim', '\$', 6, resync=True) + if re.search('No resources found', mySSH.getBefore()): + isFinished1 = True + if isFinished1 == True: + logging.debug('\u001B[1m UnDeployed PhySim Successfully on OC Cluster\u001B[0m') + mySSH.command(f'sudo podman rmi default-route-openshift-image-registry.apps.5glab.nsa.eurecom.fr/{self.OCProjectName}/oai-physim:{imageTag}', '\$', 6) + mySSH.command('oc delete is oai-physim', '\$', 6) + logging.debug('\u001B[1m Deleted the Image and ImageStream\u001B[0m') + mySSH.command('oc logout', '\$', 6) + mySSH.close() + self.AnalyzeLogFile_phySim(HTML) + if self.testStatus and isFinished: + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRowPhySimTestResult(self.testSummary,self.testResult) + logging.info('\u001B[1m Physical Simulator Pass\u001B[0m') + else: + RAN.prematureExit = True + if isFinished: + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) + else: + HTML.CreateHtmlTestRow('Some test(s) timed-out!', 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRowPhySimTestResult(self.testSummary,self.testResult) + logging.error('\u001B[1m Physical Simulator Fail\u001B[0m') + + def AnalyzeLogFile_phySim(self, HTML): + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath, '\$', 5) + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + mySSH.command('mkdir -p physim_test_log_' + self.testCase_id, '\$', 5) + mySSH.command('cp log/physim_* ' + 'physim_test_log_' + self.testCase_id, '\$', 5) + mySSH.command('tar cvf physim_test_log_' + self.testCase_id + '/physim_log.tar log/015*', '\$', 180) + if not os.path.exists(f'./physim_test_logs_{self.testCase_id}'): + os.mkdir(f'./physim_test_logs_{self.testCase_id}') + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/physim_test_log_' + self.testCase_id + '/*', './physim_test_logs_' + self.testCase_id) + mySSH.command('rm -rf ./physim_test_log_'+ self.testCase_id, '\$', 5) + mySSH.close() + # physim test log analysis + nextt = 0 + if (os.path.isfile(f'./physim_test_logs_{self.testCase_id}/physim_test.txt')): + with open(f'./physim_test_logs_{self.testCase_id}/physim_test.txt', 'r') as logfile: + for line in logfile: + if re.search('execution 015', str(line)) or re.search('Bypassing compilation', str(line)): + nextt = 1 + elif nextt == 1: + if not re.search('Test Results', str(line)): + nextt = 0 + ret2 = re.search('T[^\n]*', str(line)) + if ret2 is not None: + ret3 = ret2.group() + ret3 = ret3.replace("", "") + if re.search('execution 015', str(line)): + self.testCount[0] += 1 + testName = line.split() + ret1 = re.search('Result = PASS', str(line)) + if ret1 is not None: + self.testResult[testName[1]] = [ret3, 'PASS'] + self.testCount[1] += 1 + else: + self.testResult[testName[1]] = [ret3, 'FAIL'] + self.testCount[2] += 1 + self.testSummary['Nbtests'] = self.testCount[0] + self.testSummary['Nbpass'] = self.testCount[1] + self.testSummary['Nbfail'] = self.testCount[2] + if self.testSummary['Nbfail'] == 0: + self.testStatus = True + return 0 diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py new file mode 100644 index 0000000000..1680f3e560 --- /dev/null +++ b/ci-scripts/cls_static_code_analysis.py @@ -0,0 +1,192 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import logging +import os +import time + +#----------------------------------------------------------- +# OAI Testing modules +#----------------------------------------------------------- +import sshconnection as SSH +import helpreadme as HELP +import constants as CONST + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class CppCheckResults(): + + def __init__(self): + + self.variants = ['xenial', 'bionic'] + self.versions = ['',''] + self.nbErrors = [0,0] + self.nbWarnings = [0,0] + self.nbNullPtrs = [0,0] + self.nbMemLeaks = [0,0] + self.nbUninitVars = [0,0] + self.nbInvalidPrintf = [0,0] + self.nbModuloAlways = [0,0] + self.nbTooManyBitsShift = [0,0] + self.nbIntegerOverflow = [0,0] + self.nbWrongScanfArg = [0,0] + self.nbPtrAddNotNull = [0,0] + self.nbOppoInnerCondition = [0,0] + +class StaticCodeAnalysis(): + + def __init__(self): + + self.ranRepository = '' + self.ranBranch = '' + self.ranAllowMerge = False + self.ranCommitID = '' + self.ranTargetBranch = '' + self.eNBIPAddress = '' + self.eNBUserName = '' + self.eNBPassword = '' + self.eNBSourceCodePath = '' + + def CppCheckAnalysis(self, HTML): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('Building on server: ' + lIpAddr) + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + + self.testCase_id = HTML.testCase_id + + # on RedHat/CentOS .git extension is mandatory + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository.replace('git/', 'git') + else: + full_ran_repo_name = self.ranRepository + '.git' + mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) + mySSH.command('cd ' + lSourcePath, '\$', 5) + mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) + + mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + mySSH.command('mkdir -p cmake_targets/log', '\$', 5) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 30) + + mySSH.command('docker image rm oai-cppcheck:bionic oai-cppcheck:xenial || true', '\$', 60) + mySSH.command('docker build --tag oai-cppcheck:xenial --file ci-scripts/docker/Dockerfile.cppcheck.xenial . > cmake_targets/log/cppcheck-xenial.txt 2>&1', '\$', 600) + mySSH.command('sed -e "s@xenial@bionic@" ci-scripts/docker/Dockerfile.cppcheck.xenial > ci-scripts/docker/Dockerfile.cppcheck.bionic', '\$', 6) + mySSH.command('docker build --tag oai-cppcheck:bionic --file ci-scripts/docker/Dockerfile.cppcheck.bionic . > cmake_targets/log/cppcheck-bionic.txt 2>&1', '\$', 600) + mySSH.command('docker image rm oai-cppcheck:bionic oai-cppcheck:xenial || true', '\$', 60) + + # Analyzing the logs + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + mySSH.close() + + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '/*', '.') + CCR = CppCheckResults() + vId = 0 + for variant in CCR.variants: + if (os.path.isfile('./cppcheck-'+ variant + '.txt')): + xmlStart = False + with open('./cppcheck-'+ variant + '.txt', 'r') as logfile: + for line in logfile: + ret = re.search('Unpacking cppcheck \((?P[0-9\.]+)', str(line)) + if ret is not None: + CCR.versions[vId] = ret.group('version') + if re.search('RUN cat cmake_targets/log/cppcheck.xml', str(line)) is not None: + xmlStart = True + if xmlStart: + if re.search('severity="error"', str(line)) is not None: + CCR.nbErrors[vId] += 1 + if re.search('severity="warning"', str(line)) is not None: + CCR.nbWarnings[vId] += 1 + if re.search('id="memleak"', str(line)) is not None: + CCR.nbMemLeaks[vId] += 1 + if re.search('id="nullPointer"', str(line)) is not None: + CCR.nbNullPtrs[vId] += 1 + if re.search('id="uninitvar"', str(line)) is not None: + CCR.nbUninitVars[vId] += 1 + if re.search('id="invalidPrintfArgType_sint"|id="invalidPrintfArgType_uint"', str(line)) is not None: + CCR.nbInvalidPrintf[vId] += 1 + if re.search('id="moduloAlwaysTrueFalse"', str(line)) is not None: + CCR.nbModuloAlways[vId] += 1 + if re.search('id="shiftTooManyBitsSigned"', str(line)) is not None: + CCR.nbTooManyBitsShift[vId] += 1 + if re.search('id="integerOverflow"', str(line)) is not None: + CCR.nbIntegerOverflow[vId] += 1 + if re.search('id="wrongPrintfScanfArgNum"|id="invalidScanfArgType_int"', str(line)) is not None: + CCR.nbWrongScanfArg[vId] += 1 + if re.search('id="pointerAdditionResultNotNull"', str(line)) is not None: + CCR.nbPtrAddNotNull[vId] += 1 + if re.search('id="oppositeInnerCondition"', str(line)) is not None: + CCR.nbOppoInnerCondition[vId] += 1 + logging.debug('======== Variant ' + variant + ' - ' + CCR.versions[vId] + ' ========') + logging.debug(' ' + str(CCR.nbErrors[vId]) + ' errors') + logging.debug(' ' + str(CCR.nbWarnings[vId]) + ' warnings') + logging.debug(' -- Details --') + logging.debug(' Memory leak: ' + str(CCR.nbMemLeaks[vId])) + logging.debug(' Possible null pointer deference: ' + str(CCR.nbNullPtrs[vId])) + logging.debug(' Uninitialized variable: ' + str(CCR.nbUninitVars[vId])) + logging.debug(' Undefined behaviour shifting: ' + str(CCR.nbTooManyBitsShift[vId])) + logging.debug(' Signed integer overflow: ' + str(CCR.nbIntegerOverflow[vId])) + logging.debug('') + logging.debug(' Printf formatting issue: ' + str(CCR.nbInvalidPrintf[vId])) + logging.debug(' Modulo result is predetermined: ' + str(CCR.nbModuloAlways[vId])) + logging.debug(' Opposite Condition -> dead code: ' + str(CCR.nbOppoInnerCondition[vId])) + logging.debug(' Wrong Scanf Nb Args: ' + str(CCR.nbWrongScanfArg[vId])) + logging.debug('') + vId += 1 + + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRowCppCheckResults(CCR) + logging.info('\u001B[1m Static Code Analysis Pass\u001B[0m') + + return 0 + diff --git a/ci-scripts/conf_files/benetel-4g.conf b/ci-scripts/conf_files/benetel-4g.conf new file mode 100644 index 0000000000..9423ebe56e --- /dev/null +++ b/ci-scripts/conf_files/benetel-4g.conf @@ -0,0 +1,285 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2655000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 90; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -10; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 640000; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "yes"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.1"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 150; + } +); + +RUs = ( + { + //local_if_name = "enp129s0f0"; + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 35 -n 2 -b 0000:81:00.3 --proc-type auto --file-prefix ggg -- -p 0x1"; + #sdr_addrs = "softmodem -l 8 -n 2 -- -p 0x2"; + #remote_address = "127.0.0.2"; + #local_address = "127.0.0.1"; + #local_portc = 50000; + #remote_portc = 50000; + #local_portd = 50001; + #remote_portd = 50001; + local_rf = "no" + tr_preference = "raw_if4p5" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + eNB_instances = [0]; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + #parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/benetel-5g.conf b/ci-scripts/conf_files/benetel-5g.conf new file mode 100644 index 0000000000..79b2f7f877 --- /dev/null +++ b/ci-scripts/conf_files/benetel-5g.conf @@ -0,0 +1,279 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is is the central frequency of SSB + absoluteFrequencySSB = 640000; //641272 + dl_frequencyBand = 78; + # the carrier frequency is assumed to be in the middle of the carrier, i.e. dl_absoluteFrequencyPointA_kHz + dl_carrierBandwidth*12*SCS_kHz/2 + dl_absoluteFrequencyPointA = 638728; //640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 4; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 74; + zeroCorrelationZoneConfig = 13; + #preambleReceivedTargetPower = -118; + #preambleReceivedTargetPower = -104; + preambleReceivedTargetPower = -108; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 2; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 1; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + #msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + #p0_NominalWithGrant =-90; + p0_NominalWithGrant =-118; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + #p0_nominal = -90; + p0_nominal = -118; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + #ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -35; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "127.0.0.1"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "127.0.0.2/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "no" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + //clock_src = "internal"; + clock_src = "external"; + + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 34 -n 3 -b 0000:81:00.2 --proc-type auto --file-prefix hhh -- -p 0x1"; + remote_address = "127.0.0.2"; + local_address = "127.0.0.1"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + tr_preference = "raw_if4p5" + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + //parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/channelmod_rfsimu.conf b/ci-scripts/conf_files/channelmod_rfsimu.conf new file mode 100644 index 0000000000..cd4490d9ba --- /dev/null +++ b/ci-scripts/conf_files/channelmod_rfsimu.conf @@ -0,0 +1,57 @@ +#/* configuration for channel modelisation */ +#/* To be included in main config file when */ +#/* channel modelisation is used (rfsimulator with chanmod options enabled) */ +channelmod = { + max_chan=10; + modellist="modellist_rfsimu_1"; + modellist_rfsimu_1 = ( + { + model_name = "rfsimu_channel_enB0" + type = "AWGN"; + ploss_dB = 0; + noise_power_dB = -10; + forgetfact = 0; + offset = 0; + ds_tdl = 0; + }, + { + model_name = "rfsimu_channel_ue0" + type = "AWGN"; + ploss_dB = 0; + noise_power_dB = 0; + forgetfact = 0; + offset = 0; + ds_tdl = 0; + } + ); + modellist_rfsimu_2 = ( + { + model_name = "rfsimu_channel_ue0" + type = "AWGN"; + ploss_dB = 0; + noise_power_dB = 0; + forgetfact = 0; + offset = 0; + ds_tdl = 0; + }, + { + model_name = "rfsimu_channel_ue1" + type = "AWGN"; + ploss_dB = 0; + noise_power_dB = 0; + forgetfact = 0; + offset = 0; + ds_tdl = 0; + }, + { + model_name = "rfsimu_channel_ue2" + type = "AWGN"; + ploss_dB = 0; + noise_power_dB = 0; + forgetfact = 0; + offset = 0; + ds_tdl = 0; + } + ); +}; + diff --git a/ci-scripts/conf_files/cu.band7.tm1.100PRB.conf b/ci-scripts/conf_files/cu.band7.tm1.100PRB.conf index becd484c56..e2c94b14ab 100644 --- a/ci-scripts/conf_files/cu.band7.tm1.100PRB.conf +++ b/ci-scripts/conf_files/cu.band7.tm1.100PRB.conf @@ -181,6 +181,7 @@ eNBs = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -214,7 +215,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/cu.band7.tm1.25PRB.conf b/ci-scripts/conf_files/cu.band7.tm1.25PRB.conf index 7e4dfc6de6..5b994ed29b 100644 --- a/ci-scripts/conf_files/cu.band7.tm1.25PRB.conf +++ b/ci-scripts/conf_files/cu.band7.tm1.25PRB.conf @@ -181,6 +181,7 @@ eNBs = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -214,7 +215,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/cu.band7.tm1.50PRB.conf b/ci-scripts/conf_files/cu.band7.tm1.50PRB.conf index b1c4774aba..148c5a9903 100644 --- a/ci-scripts/conf_files/cu.band7.tm1.50PRB.conf +++ b/ci-scripts/conf_files/cu.band7.tm1.50PRB.conf @@ -181,6 +181,7 @@ eNBs = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -214,7 +215,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/du.band7.tm1.100PRB.usrpb210.conf b/ci-scripts/conf_files/du.band7.tm1.100PRB.usrpb210.conf index 7167bffa6d..a3ecffb9be 100644 --- a/ci-scripts/conf_files/du.band7.tm1.100PRB.usrpb210.conf +++ b/ci-scripts/conf_files/du.band7.tm1.100PRB.usrpb210.conf @@ -112,7 +112,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/du.band7.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/du.band7.tm1.25PRB.usrpb210.conf index 3c951a2a6e..1920992d70 100644 --- a/ci-scripts/conf_files/du.band7.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/du.band7.tm1.25PRB.usrpb210.conf @@ -112,7 +112,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/du.band7.tm1.50PRB.usrpb210.conf b/ci-scripts/conf_files/du.band7.tm1.50PRB.usrpb210.conf index 4726269312..5df8da05a3 100644 --- a/ci-scripts/conf_files/du.band7.tm1.50PRB.usrpb210.conf +++ b/ci-scripts/conf_files/du.band7.tm1.50PRB.usrpb210.conf @@ -112,7 +112,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf index 2a7783da08..e70ca78205 100644 --- a/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf @@ -175,6 +175,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -184,6 +185,8 @@ eNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -236,7 +239,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf b/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf index ab89d13193..400d1a6c9d 100644 --- a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf +++ b/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf @@ -356,6 +356,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -367,6 +368,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -445,7 +448,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf index d834b23e30..bd2999b5d5 100644 --- a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf @@ -177,6 +177,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -188,6 +189,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -248,7 +251,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf index a9ccb9f783..19ef6d0797 100644 --- a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf @@ -178,6 +178,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -189,6 +190,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ ///M2 target_mce_m2_ip_address = ( { ipv4 = "127.0.0.7"; @@ -392,7 +395,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf new file mode 100644 index 0000000000..758bb44879 --- /dev/null +++ b/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf @@ -0,0 +1,281 @@ +Active_eNBs = ( "eNB-Eurecom-B38"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe02; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-B38"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( { mcc = 208; mnc = 97; mnc_length = 2; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "3GPP_eNODEB"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 1; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2605000000L; + nr_scg_ssb_freq = 624608; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 2; + nb_antennas_rx = 2; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "no"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eno1"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + ENB_INTERFACE_NAME_FOR_S1U = "eno1"; + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + scheduler_mode = "fairRR"; + bler_target_upper = 20.0; + bler_target_lower = 10.0; + max_ul_rb_index = 27; + puSch10xSnr = 200; + puCch10xSnr = 150; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 200; + pucch1_dtx_threshold = 5 + pucch1ab_dtx_threshold =0; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 2 + nb_rx = 2 + att_tx = 0 + att_rx = 0; + bands = [38]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.18.241,addr=192.168.10.2"; + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf new file mode 100644 index 0000000000..d1d32e2b58 --- /dev/null +++ b/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf @@ -0,0 +1,281 @@ +Active_eNBs = ( "eNB-Eurecom-B38"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe04; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-B38"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( { mcc = 208; mnc = 97; mnc_length = 2; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "3GPP_eNODEB"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 1; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2605000000L; + nr_scg_ssb_freq = 624608; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 2; + nb_antennas_rx = 2; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "no"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eno1"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + ENB_INTERFACE_NAME_FOR_S1U = "eno1"; + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + scheduler_mode = "fairRR"; + bler_target_upper = 20.0; + bler_target_lower = 10.0; + max_ul_rb_index = 27; + puSch10xSnr = 200; + puCch10xSnr = 150; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 200; + pucch1_dtx_threshold = 5 + pucch1ab_dtx_threshold =0; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 2 + nb_rx = 2 + att_tx = 0 + att_rx = 0; + bands = [38]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.18.241,addr=192.168.10.2"; + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf index f6a22c8375..f34878c569 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf @@ -136,6 +136,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -147,6 +148,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -225,7 +228,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf index 15a7fa6fa8..e2e482a7c7 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf @@ -136,6 +136,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -147,6 +148,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -225,7 +228,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf index 7d2ee42185..bfea139e92 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf @@ -136,6 +136,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -147,6 +148,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -225,7 +228,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf index 475ffe9218..4e0025770b 100644 --- a/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf @@ -136,6 +136,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -145,6 +146,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -223,7 +226,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf index 517c916c85..1627d21e1a 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf @@ -173,6 +173,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -184,6 +185,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -244,7 +247,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf index 46ab966017..efa1fa64b8 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf @@ -176,6 +176,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -187,6 +188,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ target_enb_x2_ip_address = ( { ipv4 = "CI_RCC_IP_ADDR"; ipv6 = "192:168:30::17"; @@ -253,7 +256,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf index 6560fa41c5..6fc8401236 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf @@ -6,10 +6,8 @@ eNBs = ( { ////////// Identification parameters: - eNB_ID = 0xe00; - + eNB_ID = 0xe01; cell_type = "CELL_MACRO_ENB"; - eNB_name = "eNB-Eurecom-LTEBox"; // Tracking area code, 0x0000 and 0xfffe are reserved values @@ -28,83 +26,85 @@ eNBs = node_function = "3GPP_eNODEB"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2680000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - pbch_repetition = "FALSE"; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 0; - pucch_nCS_AN = 0; - pucch_n1_AN = 0; - pdsch_referenceSignalPower = -25; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -96; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -104; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower= -25; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; /* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; + srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =; */ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - ue_TransmissionMode = 1; + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; //Parameters for SIB18 rxPool_sc_CP_Len = "normal"; @@ -116,13 +116,14 @@ eNBs = rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; rxPool_ResourceConfig_offsetIndicator_choice = 0; rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; - rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; -/* rxPool_dataHoppingConfig_hoppingParameter = 0; - rxPool_dataHoppingConfig_numSubbands = "ns1"; - rxPool_dataHoppingConfig_rbOffset = 0; - rxPool_commTxResourceUC-ReqAllowed = "TRUE"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* + rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; */ // Parameters for SIB19 discRxPool_cp_Len = "normal" @@ -139,10 +140,11 @@ eNBs = discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 641272; } ); - srb1_parameters : { # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] @@ -172,21 +174,23 @@ eNBs = SCTP_OUTSTREAMS = 2; }; + enable_measurement_reports = "no"; ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } ); - enable_measurement_reports = "no"; - ///X2 - enable_x2 = "no"; + enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -201,40 +205,43 @@ eNBs = } ); -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - phy_test_mode = 0; - puSch10xSnr = 160; - puCch10xSnr = 160; - } +MACRLCs = +( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } ); -L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } +L1s = +( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } ); -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 125; - eNB_instances = [0]; - - } +RUs = +( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 125; + eNB_instances = [0]; + } ); -THREAD_STRUCT = ( +THREAD_STRUCT = +( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_SINGLE_THREAD"; @@ -247,27 +254,27 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; }; - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; +}; diff --git a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf index bdcc201fd9..087ee37f01 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf @@ -181,6 +181,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -192,6 +193,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -252,12 +255,11 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; }; - log_config : { global_log_level ="info"; @@ -276,3 +278,4 @@ NETWORK_CONTROLLER : rrc_log_verbosity ="medium"; }; +@include "channelmod_rfsimu.conf" diff --git a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf old mode 100755 new mode 100644 index 5b2c90a714..64bcb4b35f --- a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf @@ -5,110 +5,106 @@ Asn1_verbosity = "none"; eNBs = ( { - # real_time choice in {hard, rt-preempt, no} - real_time = "no"; ////////// Identification parameters: eNB_ID = 0xe01; cell_type = "CELL_MACRO_ENB"; eNB_name = "eNB-Eurecom-LTEBox"; // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - plmn_list = ( - { mcc = 222; mnc = 01; mnc_length = 2; } - ); + tracking_area_code = 1; + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); tr_s_preference = "local_mac" + // In seconds + rrc_inactivity_threshold = 0; + ////////// Physical parameters: component_carriers = ( { - node_function = "eNodeB_3GPP"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - nb_antenna_ports = 1; - ue_TransmissionMode = 1; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2680000000L; - uplink_frequency_offset = -120000000; - - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - prach_root = 0; - tx_gain = 90; - rx_gain = 115; - pbch_repetition = "FALSE"; - - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - - pucch_delta_shift = 1; - pucch_nRB_CQI = 0; - pucch_nCS_AN = 0; - pucch_n1_AN = 0; - pdsch_referenceSignalPower = -29; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; + node_function = "3GPP_eNODEB"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 115; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower= -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; /* - srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =; + srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =; */ - pusch_p0_Nominal = -96; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; /* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; */ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; //Parameters for SIB18 rxPool_sc_CP_Len = "normal"; @@ -120,30 +116,32 @@ eNBs = rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; rxPool_ResourceConfig_offsetIndicator_choice = 0; rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; - rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; /* - rxPool_dataHoppingConfig_hoppingParameter = 0; - rxPool_dataHoppingConfig_numSubbands = "ns1"; - rxPool_dataHoppingConfig_rbOffset = 0; - rxPool_commTxResourceUC-ReqAllowed = "TRUE"; + rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; */ // Parameters for SIB19 discRxPool_cp_Len = "normal" discRxPool_discPeriod = "rf32" - discRxPool_numRetx = 1; + discRxPool_numRetx = 1; discRxPool_numRepetition = 2; - discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Num = 5; discRxPool_ResourceConfig_prb_Start = 3; discRxPool_ResourceConfig_prb_End = 21; discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; - discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 641272; } ); @@ -181,51 +179,34 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } ); ///X2 - enable_x2 = "yes"; + enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; - - ENB_INTERFACE_NAME_FOR_S1U = "eth1"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 - ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; ENB_PORT_FOR_X2C = 36422; # Spec 36422 }; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="high"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="debug"; - rlc_log_verbosity ="high"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="high"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - } ); -MACRLCs = ( +MACRLCs = +( { num_cc = 1; tr_s_preference = "local_L1"; @@ -233,37 +214,52 @@ MACRLCs = ( phy_test_mode = 0; puSch10xSnr = 160; puCch10xSnr = 160; - } -); - -THREAD_STRUCT = ( - { - parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; - worker_config = "ENABLE"; } ); -L1s = ( +L1s = +( { - num_cc = 1; + num_cc = 1; tr_n_preference = "local_mac"; - } + } ); -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - bands = [7]; +RUs = +( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 3 + att_rx = 0; + bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 118; - eNB_instances = [0]; - clock_src = "external"; + max_rxgain = 115; + eNB_instances = [0]; +# clock_src = "external"; } -); +); + +THREAD_STRUCT = +( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "eth0"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; log_config : { @@ -281,4 +277,5 @@ log_config : pdcp_log_verbosity ="high"; rrc_log_level ="info"; rrc_log_verbosity ="medium"; - }; +}; + diff --git a/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf index e045ec4ca9..72754165d0 100644 --- a/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf @@ -176,6 +176,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -187,6 +188,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -246,7 +249,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf index c76a664c15..da65aad775 100644 --- a/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf @@ -175,6 +175,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -183,6 +184,8 @@ eNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ target_enb_x2_ip_address = ( { ipv4 = "CI_RCC_IP_ADDR"; ipv6 = "192:168:30::17"; @@ -241,7 +244,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/gNB_SA_n78_106PRB.2x2_usrpn310.conf b/ci-scripts/conf_files/gNB_SA_n78_106PRB.2x2_usrpn310.conf new file mode 100644 index 0000000000..77693d5f72 --- /dev/null +++ b/ci-scripts/conf_files/gNB_SA_n78_106PRB.2x2_usrpn310.conf @@ -0,0 +1,309 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x010203; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + }); + + nr_cellid = 12345678L + +# tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 2; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 11; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 + #absoluteFrequencySSB = 620640; + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB = 621312; + # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 + #absoluteFrequencySSB = 634080; + # this is 3600.48 MHz + #absoluteFrequencySSB = 640032; + #dl_frequencyBand = 78; + # this is 3301.68 MHz + #dl_absoluteFrequencyPointA = 620112; + # this is 3300.60 MHz + dl_absoluteFrequencyPointA = 620040; + # this is 3502.56 MHz + #dl_absoluteFrequencyPointA = 633552; + # this is 3600.48 MHz + #dl_absoluteFrequencyPointA = 640032; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -104; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.69.131"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "em1"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.18.194/24"; + GNB_INTERFACE_NAME_FOR_NGU = "em1"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.18.194/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 150; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 2; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 2 + nb_rx = 2 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "mgmt_addr=192.168.18.240,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal" + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/gNB_SA_n78_133PRB.2x2_usrpn310.conf b/ci-scripts/conf_files/gNB_SA_n78_133PRB.2x2_usrpn310.conf new file mode 100644 index 0000000000..c9b369eaff --- /dev/null +++ b/ci-scripts/conf_files/gNB_SA_n78_133PRB.2x2_usrpn310.conf @@ -0,0 +1,305 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; +Num_Threads_PUSCH = 8; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x010203; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + }); + + nr_cellid = 12345678L + +# tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 2; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 10; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 + absoluteFrequencySSB = 620640; + # this is 3502.56 MHz + #absoluteFrequencySSB = 633504; + # this is 3600.48 MHz + #absoluteFrequencySSB = 640032; + #dl_frequencyBand = 78; + # this is 3301.68 MHz + dl_absoluteFrequencyPointA = 620112; + # this is 3502.56 MHz + #dl_absoluteFrequencyPointA = 633504; + # this is 3600.48 MHz + #dl_absoluteFrequencyPointA = 640032; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 133; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=133 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 36300; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 10; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 133; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 36300; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -108; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.69.131"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "em1"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.18.194/24"; + GNB_INTERFACE_NAME_FOR_NGU = "em1"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.18.194/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 150; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 2; + prach_dtx_threshold = 120; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 2 + nb_rx = 2 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "mgmt_addr=192.168.18.240,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal" + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf new file mode 100644 index 0000000000..4338c00b36 --- /dev/null +++ b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf @@ -0,0 +1,283 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 311; mnc = 480; mnc_length = 3;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + min_rxtxtime = 6; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is pointA + 23 PRBs@120kHz SCS (same as initial BWP) + absoluteFrequencySSB = 2071241; + dl_frequencyBand = 261; + # this is 27.900 GHz + dl_absoluteFrequencyPointA = 2070833; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 32; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=32 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 8525; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 261; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 3; + ul_carrierBandwidth = 32; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 8525; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 3; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 52; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 7; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 7; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 3; + ssb_PositionsInBurst_Bitmap = 0x0001000100010001L; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 3; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 3; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 3; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; + if_freq = 5124520000L; + clock_src = "external"; + time_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf new file mode 100644 index 0000000000..1c2133bebe --- /dev/null +++ b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf @@ -0,0 +1,276 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + min_rxtxtime = 6; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 2150 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 433096; + dl_frequencyBand = 66; + # this is 2150 MHz + dl_absoluteFrequencyPointA = 430000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 66; + ul_absoluteFrequencyPointA = 350000; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf new file mode 100644 index 0000000000..b0a757c9d0 --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf @@ -0,0 +1,283 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({mcc = 208; mnc = 97; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 2; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + ul_prbblacklist = "51,52,53,54" + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3350.04 MHz + 53 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 624608; + dl_frequencyBand = 78; + # this is 3350.04 MHz + dl_absoluteFrequencyPointA = 623336; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=43,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -100; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + amf_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "eth0"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_NGU = "eth0"; + GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + ulsch_max_frame_inactivity = 1; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + prach_dtx_threshold = 120; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 2 + nb_rx = 2 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + bf_weights = [0x00007fff, 0x00007fff]; + #clock_src = "external"; + sf_extension = 0 + sdr_addrs = "mgmt_addr=192.168.18.240,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal" + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf new file mode 100644 index 0000000000..16456f939c --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf @@ -0,0 +1,311 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({ + mcc = 208; + mnc = 97; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x010203; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + }); + + nr_cellid = 12345678L + +# tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 2; + ul_prbblacklist = "51,52,53,54" + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 11; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 + #absoluteFrequencySSB = 620640; + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB = 621312; + # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 + #absoluteFrequencySSB = 634080; + # this is 3600.48 MHz + #absoluteFrequencySSB = 640032; + #dl_frequencyBand = 78; + # this is 3301.68 MHz + #dl_absoluteFrequencyPointA = 620112; + # this is 3300.60 MHz + dl_absoluteFrequencyPointA = 620040; + # this is 3502.56 MHz + #dl_absoluteFrequencyPointA = 633552; + # this is 3600.48 MHz + #dl_absoluteFrequencyPointA = 640032; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -104; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "em1"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_NGU = "em1"; + GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; +# pusch_TargetSNRx10 = 200; +# pucch_TargetSNRx10 = 150; + ulsch_max_frame_inactivity = 1; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 4; + prach_dtx_threshold = 120; +# pucch0_dtx_threshold = 150; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 2 + nb_rx = 2 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sf_extension = 0 + sdr_addrs = "mgmt_addr=192.168.18.240,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal" + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf new file mode 100644 index 0000000000..ff05aa6e65 --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf @@ -0,0 +1,316 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + min_rxtxtime_pdsch = 6; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({ + mcc = 208; + mnc = 97; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x010203; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + }); + + nr_cellid = 12345678L + +# tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + #pusch_TargetSNRx10 = 200; + #pucch_TargetSNRx10 = 200; + ul_prbblacklist = "51,52,53,54" + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 11; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 + #absoluteFrequencySSB = 620640; + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB = 621312; + # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 + #absoluteFrequencySSB = 634080; + # this is 3600.48 MHz + #absoluteFrequencySSB = 640032; + #dl_frequencyBand = 78; + # this is 3301.68 MHz + #dl_absoluteFrequencyPointA = 620112; + # this is 3300.60 MHz + dl_absoluteFrequencyPointA = 620040; + # this is 3502.56 MHz + #dl_absoluteFrequencyPointA = 633552; + # this is 3600.48 MHz + #dl_absoluteFrequencyPointA = 640032; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + + + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -104; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "em1"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_NGU = "em1"; + GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 4; + prach_dtx_threshold = 120; +# pucch0_dtx_threshold = 150; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sf_extension = 0 + sdr_addrs = "mgmt_addr=192.168.18.240,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal" + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.usrpn310.conf new file mode 100644 index 0000000000..ff05aa6e65 --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.usrpn310.conf @@ -0,0 +1,316 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + min_rxtxtime_pdsch = 6; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({ + mcc = 208; + mnc = 97; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x010203; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + }); + + nr_cellid = 12345678L + +# tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + #pusch_TargetSNRx10 = 200; + #pucch_TargetSNRx10 = 200; + ul_prbblacklist = "51,52,53,54" + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 11; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3301.68 MHz + 22*12*30e-3 MHz = 3309.6 + #absoluteFrequencySSB = 620640; + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB = 621312; + # this is 3503.28 MHz + 22*12*30e-3 MHz = 3511.2 + #absoluteFrequencySSB = 634080; + # this is 3600.48 MHz + #absoluteFrequencySSB = 640032; + #dl_frequencyBand = 78; + # this is 3301.68 MHz + #dl_absoluteFrequencyPointA = 620112; + # this is 3300.60 MHz + dl_absoluteFrequencyPointA = 620040; + # this is 3502.56 MHz + #dl_absoluteFrequencyPointA = 633552; + # this is 3600.48 MHz + #dl_absoluteFrequencyPointA = 640032; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + + + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -104; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "em1"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_NGU = "em1"; + GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 4; + prach_dtx_threshold = 120; +# pucch0_dtx_threshold = 150; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sf_extension = 0 + sdr_addrs = "mgmt_addr=192.168.18.240,addr=192.168.10.2,second_addr=192.168.20.2,clock_source=internal,time_source=internal" + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf index d92804ae44..6ade355053 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf @@ -21,9 +21,11 @@ gNBs = ////////// Physical parameters: - ssb_SubcarrierOffset = 0; - pdsch_AntennaPorts = 1; - + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + min_rxtxtime = 6; + servingCellConfigCommon = ( { #spCellConfigCommon @@ -45,32 +47,15 @@ gNBs = dl_carrierBandwidth = 106; #initialDownlinkBWP #genericParameters - # this is RBstart=0,L=50 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 13475; + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 12; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=2,L=3 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -83,7 +68,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 13475; + initialULBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -105,8 +90,8 @@ gNBs = #1,2,4,8,10,20,40,80 ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR -#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; #oneHalf (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; #ra_ContentionResolutionTimer @@ -114,27 +99,15 @@ gNBs = ra_ContentionResolutionTimer = 7; rsrp_ThresholdSSB = 19; #prach-RootSequenceIndex_PR -#0 = 839, 1 = 139 - prach_RootSequenceIndex_PR = 1; +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; prach_RootSequenceIndex = 1; # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex # msg1_SubcarrierSpacing = 1, - # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -176,7 +149,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -194,6 +167,7 @@ gNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "192.168.12.26"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -216,28 +190,38 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( { - local_rf = "yes" + local_rf = "yes" nb_tx = 1 nb_rx = 1 att_tx = 0 att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 50; eNB_instances = [0]; - sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "addr=192.168.30.2,mgmt_addr=192.168.30.2,second_addr=192.168.50.2"; clock_src = "external"; } ); @@ -251,6 +235,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf old mode 100755 new mode 100644 index 92af74c300..b7a04b1f36 --- a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -2,12 +2,12 @@ Active_gNBs = ( "gNB-Eurecom-5GNRBox"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; + gNBs = ( { ////////// Identification parameters: gNB_ID = 0xe00; - cell_type = "CELL_MACRO_GNB"; gNB_name = "gNB-Eurecom-5GNRBox"; @@ -21,7 +21,8 @@ gNBs = ssb_SubcarrierOffset = 31; //0; pdsch_AntennaPorts = 1; - + pusch_AntennaPorts = 1; + servingCellConfigCommon = ( { #spCellConfigCommon @@ -44,36 +45,14 @@ gNBs = #initialDownlinkBWP #genericParameters # this is RBstart=84,L=13 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; + initialDLBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 0; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) - initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -86,7 +65,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; + initialULBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -127,21 +106,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - - initialULBWPk2_2 = 7; - initialULBWPmappingType_2 = 1; - # this is SS=10 L=4 - initialULBWPstartSymbolAndLength_2 = 52; msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -199,93 +163,121 @@ gNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); +# mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; +# ipv6 = "192:168:30::17"; +# port = 36412 ; +# active = "yes"; +# preference = "ipv4"; +# } +# ); ///X2 - enable_x2 = "yes"; + enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ - target_enb_x2_ip_address = ( - { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; - ipv6 = "192:168:30::17"; - preference = "ipv4"; - } - ); + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + target_enb_x2_ip_address = ( { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); NETWORK_INTERFACES : { - - GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; - GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; - GNB_PORT_FOR_X2C = 36422; # Spec 36422 + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 }; + } ); MACRLCs = ( { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - } + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; + } ); L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 6; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 114; - eNB_instances = [0]; - clock_src = "external"; - } + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 3 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 111; + eNB_instances = [0]; +# sdr_addrs = "serial=30C51D4"; +# clock_src = "external"; + } ); THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; - //parallel_config = "PARALLEL_SINGLE_THREAD"; #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" worker_config = "WORKER_ENABLE"; } ); - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; +}; + +uicc: { + opc = "testopc"; +}; diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpn310.conf new file mode 100644 index 0000000000..299a19cc4e --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpn310.conf @@ -0,0 +1,284 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641272; //641032; #641968; 641968=start of ssb at 3600MHz + 82 RBs 641032=center of SSB at center of cell + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -90; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = -15; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + port = 36412 ; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 6; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; #114 + eNB_instances = [0]; + sdr_addrs = "addr=192.168.80.50" + clock_src = "internal" + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + +uicc: { +opc = "testopc"; +}; diff --git a/ci-scripts/conf_files/lte-fdd-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-basic-sim.conf index 24a2b400e6..a4d8e007dc 100644 --- a/ci-scripts/conf_files/lte-fdd-basic-sim.conf +++ b/ci-scripts/conf_files/lte-fdd-basic-sim.conf @@ -173,6 +173,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -184,6 +185,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf index e3adedbf4a..458ab7cf89 100644 --- a/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf +++ b/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf @@ -174,6 +174,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -185,6 +186,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ ////////// MCE parameters: target_mce_m2_ip_address = ( { ipv4 = "127.0.0.7"; diff --git a/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf index 3d5a859156..e80ff2b9cb 100644 --- a/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf +++ b/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf @@ -174,6 +174,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -185,6 +186,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ ////////// MCE parameters: target_mce_m2_ip_address = ( { ipv4 = "127.0.0.7"; diff --git a/ci-scripts/conf_files/lte-tdd-basic-sim.conf b/ci-scripts/conf_files/lte-tdd-basic-sim.conf index 3afdb5df60..f443a907f2 100644 --- a/ci-scripts/conf_files/lte-tdd-basic-sim.conf +++ b/ci-scripts/conf_files/lte-tdd-basic-sim.conf @@ -136,6 +136,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -147,6 +148,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/ci-scripts/conf_files/nr-ue-sim.conf b/ci-scripts/conf_files/nr-ue-sim.conf new file mode 100644 index 0000000000..05ac825db4 --- /dev/null +++ b/ci-scripts/conf_files/nr-ue-sim.conf @@ -0,0 +1,8 @@ +uicc0 = { + imsi = "@FULL_IMSI@"; + key = "@FULL_KEY@"; + opc= "@OPC@"; + dnn= "@DNN@"; + nssai_sst=@NSSAI_SST@; + nssai_sd=@NSSAI_SD@; +} diff --git a/ci-scripts/conf_files/rcc.band38.tm1.50PRB.multi.rru.conf b/ci-scripts/conf_files/rcc.band38.tm1.50PRB.multi.rru.conf index b3899fdb6a..502e3c548a 100644 --- a/ci-scripts/conf_files/rcc.band38.tm1.50PRB.multi.rru.conf +++ b/ci-scripts/conf_files/rcc.band38.tm1.50PRB.multi.rru.conf @@ -141,6 +141,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } diff --git a/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf index 8ad65b6278..d01e4e1c4e 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf @@ -139,6 +139,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -150,6 +151,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -232,7 +235,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf index 891301128f..7f6bff304d 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf @@ -19,54 +19,54 @@ eNBs = tracking_area_code = 1; plmn_list = ( { mcc = 208; mnc = 92; mnc_length = 2; } ); - ////////// Physical parameters: + ////////// Physical parameters: component_carriers = ( { - node_function = "NGFI_RCC_IF4p5"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "TDD"; - tdd_config = 1; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 40; - downlink_frequency = 2350000000L; - uplink_frequency_offset = 0; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 0; - pdsch_referenceSignalPower =-27; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 1; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 40; + downlink_frequency = 2350000000L; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower =-27; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ pusch_p0_Nominal = -96; pusch_alpha = "AL1"; @@ -76,7 +76,7 @@ eNBs = pucch_deltaF_Format1b = "deltaF3"; pucch_deltaF_Format2 = "deltaF0"; pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; rach_numberOfRA_Preambles = 64; rach_preamblesGroupAConfig = "DISABLE"; @@ -92,17 +92,17 @@ eNBs = rach_macContentionResolutionTimer = 48; rach_maxHARQ_Msg3Tx = 4; - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; - ue_TransmissionMode = 1; + ue_TransmissionMode = 1; } ); @@ -139,6 +139,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -147,9 +148,11 @@ eNBs = enable_measurement_reports = "no"; ///X2 - enable_x2 = "no"; + enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -183,41 +186,41 @@ eNBs = } ); MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - scheduler_mode = "fairRR"; - puSch10xSnr = 200; - puCch10xSnr = 200; - } + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + scheduler_mode = "fairRR"; + puSch10xSnr = 200; + puCch10xSnr = 200; + } ); L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + } ); RUs = ( - { - local_if_name = "lo"; - remote_address = "127.0.0.2"; - local_address = "127.0.0.1"; - local_portc = 50000; - remote_portc = 50000; - local_portd = 50001; - remote_portd = 50001; - local_rf = "no" - tr_preference = "udp_if4p5" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - eNB_instances = [0]; - } -); + { + local_if_name = "lo"; + remote_address = "127.0.0.2"; + local_address = "127.0.0.1"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + local_rf = "no" + tr_preference = "udp_if4p5" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + eNB_instances = [0]; + } +); THREAD_STRUCT = ( { @@ -232,7 +235,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf index 76df9ffde5..d4f2eb9ef2 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf @@ -139,6 +139,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -150,6 +151,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -232,7 +235,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf index b842480e5d..683fff0bc8 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf @@ -176,6 +176,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -187,6 +188,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -251,7 +254,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf index 98a546e8b5..574c8b2545 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf @@ -25,51 +25,51 @@ eNBs = component_carriers = ( { - node_function = "NGFI_RCC_IF4p5"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2680000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - pbch_repetition = "FALSE"; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 0; - pucch_nCS_AN = 0; - pucch_n1_AN = 0; - pdsch_referenceSignalPower = -25; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -25; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ pusch_p0_Nominal = -96; pusch_alpha = "AL1"; @@ -79,7 +79,7 @@ eNBs = pucch_deltaF_Format1b = "deltaF3"; pucch_deltaF_Format2 = "deltaF0"; pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; rach_numberOfRA_Preambles = 64; rach_preamblesGroupAConfig = "DISABLE"; @@ -97,25 +97,25 @@ eNBs = pcch_default_PagingCycle = 128; pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - ue_TransmissionMode = 1; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; //Parameters for SIB18 - rxPool_sc_CP_Len = "normal"; - rxPool_sc_Period = "sf40"; - rxPool_data_CP_Len = "normal"; - rxPool_ResourceConfig_prb_Num = 20; - rxPool_ResourceConfig_prb_Start = 5; - rxPool_ResourceConfig_prb_End = 44; - rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; - rxPool_ResourceConfig_offsetIndicator_choice = 0; - rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; @@ -176,6 +176,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -184,9 +185,11 @@ eNBs = enable_measurement_reports = "no"; ///X2 - enable_x2 = "no"; + enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -202,21 +205,21 @@ eNBs = ); MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - phy_test_mode = 0; - puSch10xSnr = 160; - puCch10xSnr = 160; - } + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } ); L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + } ); RUs = ( @@ -251,26 +254,26 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; }; - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; +}; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf index 2a8506a660..49365a1f61 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf @@ -176,6 +176,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -187,6 +188,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -251,7 +254,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf b/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf index b61e5e05b1..640b85930a 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.mbms-s1ap.if4p5.50PRB.lo.conf @@ -144,6 +144,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "192.168.15.130"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -155,6 +156,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ ////////// MCE parameters: diff --git a/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf b/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf index 5daaa8d13a..7fe682f29e 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.mbms.if4p5.50PRB.lo.conf @@ -144,6 +144,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "127.0.0.3"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -155,6 +156,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ ////////// MCE parameters: diff --git a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf index 28bfd91560..281f7433af 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf @@ -174,6 +174,7 @@ eNBs = ////////// MME parameters: mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; ipv6 = "192:168:30::17"; + port = 36412 ; active = "yes"; preference = "ipv4"; } @@ -185,6 +186,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/ci-scripts/conf_files/rru.fdd.band7.conf b/ci-scripts/conf_files/rru.fdd.band7.conf index ea923ae371..057f518046 100644 --- a/ci-scripts/conf_files/rru.fdd.band7.conf +++ b/ci-scripts/conf_files/rru.fdd.band7.conf @@ -1,23 +1,25 @@ -RUs = ( - { - local_if_name = "lo"; - remote_address = "127.0.0.1" - local_address = "127.0.0.2"; - local_portc = 50000; - remote_portc = 50000; - local_portd = 50001; - remote_portd = 50001; - local_rf = "yes" - tr_preference = "udp_if4p5"; - nb_tx = 1; - nb_rx = 1; - max_pdschReferenceSignalPower = -27; - max_rxgain = 115; - bands = [7]; - } +RUs = +( + { + local_if_name = "lo"; + remote_address = "127.0.0.1" + local_address = "127.0.0.2"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + local_rf = "yes" + tr_preference = "udp_if4p5"; + nb_tx = 1; + nb_rx = 1; + max_pdschReferenceSignalPower = -27; + max_rxgain = 115; + bands = [7]; + } ); -THREAD_STRUCT = ( +THREAD_STRUCT = +( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_SINGLE_THREAD"; @@ -26,19 +28,20 @@ THREAD_STRUCT = ( } ); -log_config = { - global_log_level ="error"; - global_log_verbosity ="medium"; - hw_log_level ="error"; - hw_log_verbosity ="medium"; - phy_log_level ="error"; - phy_log_verbosity ="medium"; - mac_log_level ="error"; - mac_log_verbosity ="high"; - rlc_log_level ="error"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="error"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="error"; - rrc_log_verbosity ="medium"; +log_config = +{ + global_log_level ="error"; + global_log_verbosity ="medium"; + hw_log_level ="error"; + hw_log_verbosity ="medium"; + phy_log_level ="error"; + phy_log_verbosity ="medium"; + mac_log_level ="error"; + mac_log_verbosity ="high"; + rlc_log_level ="error"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="error"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="error"; + rrc_log_verbosity ="medium"; }; diff --git a/ci-scripts/conf_files/rru.tdd.band40.conf b/ci-scripts/conf_files/rru.tdd.band40.conf index 904f8c9598..5ce3a515f5 100644 --- a/ci-scripts/conf_files/rru.tdd.band40.conf +++ b/ci-scripts/conf_files/rru.tdd.band40.conf @@ -1,23 +1,25 @@ -RUs = ( - { - local_if_name = "lo"; - remote_address = "127.0.0.1" - local_address = "127.0.0.2"; - local_portc = 50000; - remote_portc = 50000; - local_portd = 50001; - remote_portd = 50001; - local_rf = "yes" - tr_preference = "udp_if4p5"; - nb_tx = 1; - nb_rx = 1; - max_pdschReferenceSignalPower = -27; - max_rxgain = 115; - bands = [40]; - } +RUs = +( + { + local_if_name = "lo"; + remote_address = "127.0.0.1" + local_address = "127.0.0.2"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + local_rf = "yes" + tr_preference = "udp_if4p5"; + nb_tx = 1; + nb_rx = 1; + max_pdschReferenceSignalPower = -27; + max_rxgain = 115; + bands = [40]; + } ); -THREAD_STRUCT = ( +THREAD_STRUCT = +( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_SINGLE_THREAD"; @@ -26,19 +28,20 @@ THREAD_STRUCT = ( } ); -log_config = { - global_log_level ="error"; - global_log_verbosity ="medium"; - hw_log_level ="error"; - hw_log_verbosity ="medium"; - phy_log_level ="error"; - phy_log_verbosity ="medium"; - mac_log_level ="error"; - mac_log_verbosity ="high"; - rlc_log_level ="error"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="error"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="error"; - rrc_log_verbosity ="medium"; +log_config = +{ + global_log_level ="error"; + global_log_verbosity ="medium"; + hw_log_level ="error"; + hw_log_verbosity ="medium"; + phy_log_level ="error"; + phy_log_verbosity ="medium"; + mac_log_level ="error"; + mac_log_verbosity ="high"; + rlc_log_level ="error"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="error"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="error"; + rrc_log_verbosity ="medium"; }; diff --git a/ci-scripts/conf_files/ue.sa.conf b/ci-scripts/conf_files/ue.sa.conf new file mode 100644 index 0000000000..3e6f78f709 --- /dev/null +++ b/ci-scripts/conf_files/ue.sa.conf @@ -0,0 +1,8 @@ +uicc0 = { + imsi = "208970100001127"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "c42449363bbad02b66d16bc975d77cc1"; + dnn= "oai"; + nssai_sst=1; + nssai_sd=66051; +} diff --git a/ci-scripts/constants.py b/ci-scripts/constants.py index c5698c5a3e..bb110bc0e8 100644 --- a/ci-scripts/constants.py +++ b/ci-scripts/constants.py @@ -59,6 +59,12 @@ OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 OAI_UE_PROCESS_SEG_FAULT = -25 OAI_UE_PROCESS_NO_MBMS_MSGS = -26 OAI_UE_PROCESS_OK = +6 +INVALID_PARAMETER = -50 +PHYSIM_IMAGE_ABSENT = -60 +OC_LOGIN_FAIL = -61 +OC_PROJECT_FAIL = -62 +OC_IS_FAIL = -63 +OC_PHYSIM_DEPLOY_FAIL = -64 UE_STATUS_DETACHED = 0 UE_STATUS_DETACHING = 1 diff --git a/ci-scripts/cots_ue_ctl.yaml b/ci-scripts/cots_ue_ctl.yaml new file mode 100644 index 0000000000..c22fca246b --- /dev/null +++ b/ci-scripts/cots_ue_ctl.yaml @@ -0,0 +1,20 @@ +9d690a12: #oppo + - adb shell input keyevent KEYCODE_POWER + - adb shell input swipe 300 700 300 0 + - adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS + - adb shell input keyevent 20 + - adb shell input tap 968 324 +002: #s10 + - adb shell input keyevent KEYCODE_POWER + - adb shell input swipe 200 900 200 300 + - adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS + - adb shell input tap 968 324 +003: #s20 + - adb shell input keyevent KEYCODE_POWER + - adb shell input swipe 200 900 200 300 + - adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS + - adb shell input tap 968 324 +004: #xperia + - tbd + - tbd + - tbd diff --git a/ci-scripts/cppcheck_suppressions.list b/ci-scripts/cppcheck_suppressions.list index 727fd22e74..f8438a4276 100644 --- a/ci-scripts/cppcheck_suppressions.list +++ b/ci-scripts/cppcheck_suppressions.list @@ -83,6 +83,16 @@ nullPointer:common/utils/T/tracer/multi.c:265 // the tests arrayIndexOutOfBounds:openair2/LAYER2/rlc_v2/tests/test.c:401 // +//----------------------------------------------------------------------------- +// this file is used for testing the NR RLC implementation, this error is +// not a problem, the programmer has to know what she does when writing +// the tests +arrayIndexOutOfBounds:openair2/LAYER2/nr_rlc/tests/test.c:451 +// +//----------------------------------------------------------------------------- +// cppcheck does not understand the different lengths of arrays +arrayIndexOutOfBounds:openair1/SIMULATION/TOOLS/random_channel.c:705 +arrayIndexOutOfBounds:openair1/SIMULATION/TOOLS/random_channel.c:706 //***************************************************************************** // // True problems we don't know how to fix, Suppression is commented out, diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh index 237a1a5d5e..f3f8ddaca2 100755 --- a/ci-scripts/createVM.sh +++ b/ci-scripts/createVM.sh @@ -87,6 +87,12 @@ function create_vm { echo "VM_CPU = $VM_CPU" echo "VM_DISK = $VM_DISK GBytes" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] || [[ "$VM_NAME" == *"-phy-sim"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + echo "############################################################" echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" diff --git a/ci-scripts/datalog_rt_stats.yaml b/ci-scripts/datalog_rt_stats.yaml new file mode 100644 index 0000000000..a2d4768752 --- /dev/null +++ b/ci-scripts/datalog_rt_stats.yaml @@ -0,0 +1,35 @@ +#this is a configuration file +#used to build real time processing statistics +#for 5G NR phy test (gNB terminate) +Title : Processing Time (us) +ColNames : + - Metric + - Average + - Max + - Average vs Reference Deviation (Reference Value ; Acceptability Threshold) +Ref : + feprx : 60.0 + feptx_prec : 8.0 + feptx_ofdm : 50.0 + feptx_total : 75.0 + L1 Tx processing thread 0 : 300.0 + L1 Tx processing thread 1 : 300.0 + DLSCH encoding : 230.0 + L1 Rx processing : 175.0 + PUSCH inner-receiver : 100.0 + PUSCH decoding : 180.0 + DL & UL scheduling timing stats : 37.0 + UL Indication : 38.0 +Threshold : + feprx : 1.25 + feptx_prec : 1.25 + feptx_ofdm : 1.25 + feptx_total : 1.25 + L1 Tx processing thread 0 : 1.25 + L1 Tx processing thread 1 : 1.25 + DLSCH encoding : 1.25 + L1 Rx processing : 1.25 + PUSCH inner-receiver : 1.25 + PUSCH decoding : 1.25 + DL & UL scheduling timing stats : 1.25 + UL Indication : 1.25 diff --git a/ci-scripts/docker/Dockerfile.cppcheck.xenial b/ci-scripts/docker/Dockerfile.cppcheck.xenial new file mode 100644 index 0000000000..0aecc62037 --- /dev/null +++ b/ci-scripts/docker/Dockerfile.cppcheck.xenial @@ -0,0 +1,31 @@ +FROM ubuntu:xenial AS oai-cppcheck + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + build-essential \ + vim \ + cppcheck + +WORKDIR /oai-ran +COPY . . + +WORKDIR /oai-ran/common/utils/T +RUN make + +WORKDIR /oai-ran +RUN mkdir -p cmake_targets/log && \ + cppcheck --enable=warning --force --xml --xml-version=2 \ + -i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c \ + --suppressions-list=ci-scripts/cppcheck_suppressions.list \ + -I common/utils \ + -I openair3/NAS/COMMON/UTIL \ + -j`nproc` . 2> cmake_targets/log/cppcheck.xml 1> cmake_targets/log/cppcheck_build.txt + +RUN egrep -c 'severity="error' cmake_targets/log/cppcheck.xml + +RUN egrep -c 'severity="warning' cmake_targets/log/cppcheck.xml + +RUN cat cmake_targets/log/cppcheck.xml diff --git a/ci-scripts/docker_log_split.py b/ci-scripts/docker_log_split.py new file mode 100644 index 0000000000..8c3c9e41dc --- /dev/null +++ b/ci-scripts/docker_log_split.py @@ -0,0 +1,92 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + + +#----------------------------------------------------------- +# Import Libs +#----------------------------------------------------------- +import sys # arg +import re # reg +import os +import subprocess + + +class SplitReport(): + def __init__(self): + self.logfilename = '' + self.destinationFolder = '' + + def split(self): + self.destinationFolder = self.logfilename.replace(".log","") + if os.path.isfile(self.logfilename): + newImageLog = open(self.logfilename + '.new', 'w') + copyFlag = True + with open(self.logfilename, 'r') as imageLog: + for line in imageLog: + header = False + ret = re.search('====== Start of log for ([0-9\.A-Za-z\-\_]+) ======', line) + if ret is not None: + copyFlag = False + header = True + detailedLogFile = open(self.destinationFolder + '/' + ret.group(1), 'w') + if copyFlag: + newImageLog.write(line) + ret = re.search('====== End of log for ([0-9\.A-Za-z\-\_]+) ======', line) + if ret is not None: + copyFlag = True + detailedLogFile.close() + elif not copyFlag and not header: + detailedLogFile.write(line) + imageLog.close() + newImageLog.close() + os.rename(self.logfilename + '.new', self.logfilename) + else: + print('Cannot split unfound file') + +#-------------------------------------------------------------------------------------------------------- +# +# Start of main +# +#-------------------------------------------------------------------------------------------------------- + +argvs = sys.argv +argc = len(argvs) + +SP = SplitReport() + +while len(argvs) > 1: + myArgv = argvs.pop(1) + if re.match('^\-\-logfilename=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-logfilename=(.+)$', myArgv, re.IGNORECASE) + SP.logfilename = matchReg.group(1) + +SP.split() + +sys.exit(0) diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 25bbbba091..a7d923ca90 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -46,7 +46,6 @@ from multiprocessing import Process, Lock, SimpleQueue import sshconnection as SSH import helpreadme as HELP import constants as CONST -import html #----------------------------------------------------------- # Class Declaration @@ -54,29 +53,31 @@ import html class EPCManagement(): def __init__(self): - + self.IPAddress = '' self.UserName = '' self.Password = '' self.SourceCodePath = '' self.Type = '' self.PcapFileName = '' - self.htmlObj = None self.testCase_id = '' self.MmeIPAddress = '' self.containerPrefix = 'prod' + self.mmeConfFile = 'mme.conf' + self.yamlPath = '' + self.isMagmaUsed = False #----------------------------------------------------------- # EPC management functions #----------------------------------------------------------- - def InitializeHSS(self): + def InitializeHSS(self, HTML): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) sys.exit('Insufficient EPC Parameters') - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS in Docker') @@ -107,27 +108,34 @@ class EPCManagement(): logging.debug('Using the ltebox simulated HSS') mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5) mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5) + result = re.search('hss_sim s6as diam_hss', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.Password + ' | sudo -S killall hss_sim', '\$', 5) + mySSH.command('ps aux | grep --colour=never xGw | grep -v grep', '\$', 5, silent=True) + result = re.search('root.*xGw', mySSH.getBefore()) + if result is not None: + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S ./stop_ltebox', '\$', 5) mySSH.command('cd /opt/hss_sim0609', '\$', 5) mySSH.command('echo ' + self.Password + ' | sudo -S rm -f hss.log', '\$', 5) mySSH.command('echo ' + self.Password + ' | sudo -S echo "Starting sudo session" && sudo su -c "screen -dm -S simulated_hss ./starthss"', '\$', 5) else: logging.error('This option should not occur!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) - def InitializeMME(self): + def InitializeMME(self, HTML): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) sys.exit('Insufficient EPC Parameters') - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 MME in Docker') mySSH.command('docker exec -d ' + self.containerPrefix + '-oai-mme /bin/bash -c "nohup tshark -i eth0 -i lo:s10 -w /tmp/mme_check_run.pcap 2>&1 > /dev/null"', '\$', 5) time.sleep(5) - mySSH.command('docker exec -d ' + self.containerPrefix + '-oai-mme /bin/bash -c "nohup ./bin/oai_mme -c ./etc/mme.conf > mme_check_run.log 2>&1"', '\$', 5) + mySSH.command('docker exec -d ' + self.containerPrefix + '-oai-mme /bin/bash -c "nohup ./bin/oai_mme -c ./etc/' + self.mmeConfFile + ' > mme_check_run.log 2>&1"', '\$', 5) elif re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 MME') mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) @@ -152,8 +160,7 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) def SetMmeIPAddress(self): # Not an error if we don't need an EPC @@ -163,9 +170,17 @@ class EPCManagement(): return # Only in case of Docker containers, MME IP address is not the EPC HOST IP address if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) - mySSH.command('docker inspect --format="MME_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" ' + self.containerPrefix + '-oai-mme', '\$', 5) + self.isMagmaUsed = False + mySSH.command('docker ps -a', '\$', 5) + result = re.search('magma', mySSH.getBefore()) + if result is not None: + self.isMagmaUsed = True + if self.isMagmaUsed: + mySSH.command('docker inspect --format="MME_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" ' + self.containerPrefix + '-magma-mme', '\$', 5) + else: + mySSH.command('docker inspect --format="MME_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" ' + self.containerPrefix + '-oai-mme', '\$', 5) result = re.search('MME_IP_ADDR = (?P[0-9\.]+)', mySSH.getBefore()) if result is not None: self.MmeIPAddress = result.group('mme_ip_addr') @@ -174,12 +189,12 @@ class EPCManagement(): else: self.MmeIPAddress = self.IPAddress - def InitializeSPGW(self): + def InitializeSPGW(self, HTML): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) sys.exit('Insufficient EPC Parameters') - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 SPGW-CUPS in Docker') @@ -211,15 +226,94 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + + def Initialize5GCN(self, HTML): + if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': + HELP.GenericHelp(CONST.Version) + HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) + sys.exit('Insufficient EPC Parameters') + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + html_cell = '
\n'
+		if re.match('ltebox', self.Type, re.IGNORECASE):
+			logging.debug('Using the SABOX simulated HSS')
+			mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5)
+			mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5)
+			mySSH.command('cd /opt/hss_sim0609', '\$', 5)
+			mySSH.command('echo ' + self.Password + ' | sudo -S rm -f hss.log', '\$', 5)
+			mySSH.command('echo ' + self.Password + ' | sudo -S echo "Starting sudo session" && sudo su -c "screen -dm -S simulated_5g_hss ./start_5g_hss"', '\$', 5)
+			logging.debug('Using the sabox')
+			mySSH.command('cd /opt/ltebox/tools', '\$', 5)
+			mySSH.command('echo ' + self.Password + ' | sudo -S ./start_sabox', '\$', 5)
+			html_cell += 'N/A\n'
+		elif re.match('OAICN5G', self.Type, re.IGNORECASE):
+			logging.debug('Starting OAI CN5G')
+			mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5)
+			mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5)
+			mySSH.command('cd /opt/oai-cn5g-fed/docker-compose', '\$', 5)
+			mySSH.command('./core-network.sh start nrf spgwu', '\$', 60)
+			time.sleep(2)
+			mySSH.command('docker-compose -p 5gcn ps -a', '\$', 60)
+			if mySSH.getBefore().count('Up (healthy)') != 6:
+				logging.error('Not all container healthy')
+			else:
+				logging.debug('OK')
+			mySSH.command('docker-compose config | grep --colour=never image', '\$', 10)
+			listOfImages = mySSH.getBefore()
+			for imageLine in listOfImages.split('\\r\\n'):
+				res1 = re.search('image: (?P[a-zA-Z0-9\-]+):(?P[a-zA-Z0-9\-]+)', str(imageLine))
+				res2 = re.search('mysql', str(imageLine))
+				if res1 is not None and res2 is None:
+					html_cell += res1.group('name') + ':' + res1.group('tag') + ' '
+					nbChars = len(res1.group('name')) + len(res1.group('tag')) + 2
+					while (nbChars < 32):
+						html_cell += ' '
+						nbChars += 1
+					mySSH.command('docker image inspect --format="Size = {{.Size}} bytes" ' + res1.group('name') + ':' + res1.group('tag'), '\$', 10)
+					res3 = re.search('Size *= *(?P[0-9\-]*) *bytes', mySSH.getBefore())
+					if res3 is not None:
+						imageSize = int(res3.group('size'))
+						imageSize = int(imageSize/(1024*1024))
+						html_cell += str(imageSize) + ' MBytes '
+					mySSH.command('docker image inspect --format="Date = {{.Created}}" ' + res1.group('name') + ':' + res1.group('tag'), '\$', 10)
+					res4 = re.search('Date *= *(?P[0-9\-]*)T', mySSH.getBefore())
+					if res4 is not None:
+						html_cell += '(' + res4.group('date') + ')'
+					html_cell += '\n'
+		else:
+			logging.error('This option should not occur!')
+		html_cell += '
' + mySSH.close() + html_queue = SimpleQueue() + html_queue.put(html_cell) + HTML.CreateHtmlTestRowQueue(self.Type, 'OK', 1, html_queue) + + def SetAmfIPAddress(self): + # Not an error if we don't need an 5GCN + if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': + return + if self.IPAddress == 'none': + return + if re.match('ltebox', self.Type, re.IGNORECASE): + self.MmeIPAddress = self.IPAddress + elif re.match('OAICN5G', self.Type, re.IGNORECASE): + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + response=mySSH.command3('docker container ls -f name=oai-amf', 10) + if len(response)>1: + response=mySSH.command3('docker inspect --format=\'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}\' oai-amf', 10) + tmp = str(response[0],'utf-8') + self.MmeIPAddress = tmp.rstrip() + logging.debug('AMF IP Address ' + self.MmeIPAddress) + mySSH.close() def CheckHSSProcess(self, status_queue): try: - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-hss /bin/bash -c "ps aux | grep oai_hss"', '\$', 5) + mySSH.command('docker top ' + self.containerPrefix + '-oai-hss', '\$', 5) else: mySSH.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): @@ -241,10 +335,18 @@ class EPCManagement(): def CheckMMEProcess(self, status_queue): try: - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-mme /bin/bash -c "ps aux | grep oai_mme"', '\$', 5) + self.isMagmaUsed = False + mySSH.command('docker ps -a', '\$', 5) + result = re.search('magma', mySSH.getBefore()) + if result is not None: + self.isMagmaUsed = True + if self.isMagmaUsed: + mySSH.command('docker top ' + self.containerPrefix + '-magma-mme', '\$', 5) + else: + mySSH.command('docker top ' + self.containerPrefix + '-oai-mme', '\$', 5) else: mySSH.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): @@ -254,11 +356,11 @@ class EPCManagement(): elif re.match('OAI', self.Type, re.IGNORECASE): result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) elif re.match('ltebox', self.Type, re.IGNORECASE): - result = re.search('mme', mySSH.getBefore()) + result = re.search('mme|amf', mySSH.getBefore()) else: logging.error('This should not happen!') if result is None: - logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') + logging.debug('\u001B[1;37;41m MME|AMF Process Not Found! \u001B[0m') status_queue.put(CONST.MME_PROCESS_FAILED) else: status_queue.put(CONST.MME_PROCESS_OK) @@ -268,14 +370,14 @@ class EPCManagement(): def CheckSPGWProcess(self, status_queue): try: - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-spgwc /bin/bash -c "ps aux | grep oai_spgwc"', '\$', 5) - result = re.search('oai_spgwc -o -c ', mySSH.getBefore()) + mySSH.command('docker top ' + self.containerPrefix + '-oai-spgwc', '\$', 5) + result = re.search('oai_spgwc -', mySSH.getBefore()) if result is not None: - mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-spgwu-tiny /bin/bash -c "ps aux | grep oai_spgwu"', '\$', 5) - result = re.search('oai_spgwu -o -c ', mySSH.getBefore()) + mySSH.command('docker top ' + self.containerPrefix + '-oai-spgwu-tiny', '\$', 5) + result = re.search('oai_spgwu -', mySSH.getBefore()) elif re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) result = re.search('spgwu -c ', mySSH.getBefore()) @@ -284,11 +386,11 @@ class EPCManagement(): result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) elif re.match('ltebox', self.Type, re.IGNORECASE): mySSH.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) - result = re.search('xGw', mySSH.getBefore()) + result = re.search('xGw|upf', mySSH.getBefore()) else: logging.error('This should not happen!') if result is None: - logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') + logging.debug('\u001B[1;37;41m SPGW|UPF Process Not Found! \u001B[0m') status_queue.put(CONST.SPGW_PROCESS_FAILED) else: status_queue.put(CONST.SPGW_PROCESS_OK) @@ -296,8 +398,8 @@ class EPCManagement(): except: os.kill(os.getppid(),signal.SIGUSR1) - def TerminateHSS(self): - mySSH = SSH.SSHConnection() + def TerminateHSS(self, HTML): + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-hss /bin/bash -c "killall --signal SIGINT oai_hss tshark"', '\$', 5) @@ -309,7 +411,7 @@ class EPCManagement(): elif re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) time.sleep(2) - mySSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + mySSH.command('stdbuf -o0 ps -aux | grep --colour=never hss | grep -v grep', '\$', 5) result = re.search('oai_hss -j', mySSH.getBefore()) if result is not None: mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) @@ -317,7 +419,7 @@ class EPCManagement(): elif re.match('OAI', self.Type, re.IGNORECASE): mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) time.sleep(2) - mySSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + mySSH.command('stdbuf -o0 ps -aux | grep --colour=never hss | grep -v grep', '\$', 5) result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) if result is not None: mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) @@ -325,15 +427,19 @@ class EPCManagement(): mySSH.command('cd ' + self.SourceCodePath, '\$', 5) mySSH.command('cd scripts', '\$', 5) time.sleep(1) - mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S screen -S simulated_hss -X quit', '\$', 5) + time.sleep(5) + mySSH.command('ps aux | grep --colour=never hss_sim | grep -v grep', '\$', 5, silent=True) + result = re.search('hss_sim s6as diam_hss', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.Password + ' | sudo -S killall hss_sim', '\$', 5) else: logging.error('This should not happen!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - def TerminateMME(self): - mySSH = SSH.SSHConnection() + def TerminateMME(self, HTML): + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-mme /bin/bash -c "killall --signal SIGINT oai_mme tshark"', '\$', 5) @@ -353,14 +459,14 @@ class EPCManagement(): elif re.match('ltebox', self.Type, re.IGNORECASE): mySSH.command('cd /opt/ltebox/tools', '\$', 5) mySSH.command('echo ' + self.Password + ' | sudo -S ./stop_mme', '\$', 5) + time.sleep(5) else: logging.error('This should not happen!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - def TerminateSPGW(self): - mySSH = SSH.SSHConnection() + def TerminateSPGW(self, HTML): + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-spgwc /bin/bash -c "killall --signal SIGINT oai_spgwc tshark"', '\$', 5) @@ -400,18 +506,294 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def Terminate5GCN(self, HTML): + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + message = '' + if re.match('ltebox', self.Type, re.IGNORECASE): + logging.debug('Terminating SA BOX') + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S ./stop_sabox', '\$', 5) + time.sleep(1) + mySSH.command('cd ' + self.SourceCodePath, '\$', 5) + mySSH.command('cd scripts', '\$', 5) + time.sleep(1) + mySSH.command('echo ' + self.Password + ' | sudo -S screen -S simulated_5g_hss -X quit', '\$', 5) + elif re.match('OAICN5G', self.Type, re.IGNORECASE): + logging.debug('OAI CN5G Collecting Log files to workspace') + mySSH.command('echo ' + self.Password + ' | sudo rm -rf ' + self.SourceCodePath + '/logs', '\$', 5) + mySSH.command('mkdir ' + self.SourceCodePath + '/logs','\$', 5) + containers_list=['oai-smf','oai-spgwu','oai-amf','oai-nrf'] + for c in containers_list: + mySSH.command('docker logs ' + c + ' > ' + self.SourceCodePath + '/logs/' + c + '.log', '\$', 5) + + logging.debug('Terminating OAI CN5G') + mySSH.command('cd /opt/oai-cn5g-fed/docker-compose', '\$', 5) + mySSH.command('./core-network.sh stop nrf spgwu', '\$', 60) + time.sleep(2) + mySSH.command('tshark -r /tmp/oai-cn5g.pcap | egrep --colour=never "Tracking area update" ','\$', 30) + result = re.search('Tracking area update request', mySSH.getBefore()) + if result is not None: + message = 'UE requested ' + str(mySSH.getBefore().count('Tracking area update request')) + 'Tracking area update request(s)' + else: + message = 'No Tracking area update request' + logging.debug(message) + else: + logging.error('This should not happen!') + mySSH.close() + html_queue = SimpleQueue() + html_cell = '
' + message + '
' + html_queue.put(html_cell) + HTML.CreateHtmlTestRowQueue(self.Type, 'OK', 1, html_queue) + + def DeployEpc(self, HTML): + logging.debug('Trying to deploy') + if not re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): + HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) + HTML.CreateHtmlTabFooter(False) + sys.exit('Deploy not possible with this EPC type: ' + self.Type) + + if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': + HELP.GenericHelp(CONST.Version) + HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) + sys.exit('Insufficient EPC Parameters') + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + mySSH.command('docker-compose --version', '\$', 5) + result = re.search('docker-compose version 1', mySSH.getBefore()) + if result is None: + mySSH.close() + HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) + HTML.CreateHtmlTabFooter(False) + sys.exit('docker-compose not installed on ' + self.IPAddress) + + # Checking if it is a MAGMA deployment + self.isMagmaUsed = False + if os.path.isfile('./' + self.yamlPath + '/redis_extern.conf'): + self.isMagmaUsed = True + logging.debug('MAGMA MME is used!') + + mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5) + mySSH.command('if [ -d ' + self.SourceCodePath + '/logs ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/logs ; fi', '\$', 5) + mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts ' + self.SourceCodePath + '/logs', '\$', 5) + + # deploying and configuring the cassandra database + # container names and services are currently hard-coded. + # they could be recovered by: + # - docker-compose config --services + # - docker-compose config | grep container_name + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.copyout(self.IPAddress, self.UserName, self.Password, './' + self.yamlPath + '/docker-compose.yml', self.SourceCodePath + '/scripts') + if self.isMagmaUsed: + mySSH.copyout(self.IPAddress, self.UserName, self.Password, './' + self.yamlPath + '/entrypoint.sh', self.SourceCodePath + '/scripts') + mySSH.copyout(self.IPAddress, self.UserName, self.Password, './' + self.yamlPath + '/mme.conf', self.SourceCodePath + '/scripts') + mySSH.copyout(self.IPAddress, self.UserName, self.Password, './' + self.yamlPath + '/mme_fd.sprint.conf', self.SourceCodePath + '/scripts') + mySSH.copyout(self.IPAddress, self.UserName, self.Password, './' + self.yamlPath + '/redis_extern.conf', self.SourceCodePath + '/scripts') + mySSH.command('chmod a+x ' + self.SourceCodePath + '/scripts/entrypoint.sh', '\$', 5) + else: + mySSH.copyout(self.IPAddress, self.UserName, self.Password, './' + self.yamlPath + '/entrypoint.sh', self.SourceCodePath + '/scripts') + mySSH.copyout(self.IPAddress, self.UserName, self.Password, './' + self.yamlPath + '/mme.conf', self.SourceCodePath + '/scripts') + mySSH.command('chmod 775 entrypoint.sh', '\$', 60) + mySSH.command('wget --quiet --tries=3 --retry-connrefused https://raw.githubusercontent.com/OPENAIRINTERFACE/openair-hss/develop/src/hss_rel14/db/oai_db.cql', '\$', 30) + mySSH.command('docker-compose down', '\$', 60) + mySSH.command('docker-compose up -d db_init', '\$', 60) + # databases take time... + time.sleep(10) + cnt = 0 + db_init_status = False + while (cnt < 10): + mySSH.command('docker logs prod-db-init', '\$', 5) + result = re.search('OK', mySSH.getBefore()) + if result is not None: + cnt = 10 + db_init_status = True + else: + time.sleep(5) + cnt += 1 + mySSH.command('docker rm -f prod-db-init', '\$', 5) + if not db_init_status: + HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) + HTML.CreateHtmlTabFooter(False) + sys.exit('Cassandra DB deployment/configuration went wrong!') + + # deploying EPC cNFs + mySSH.command('docker-compose up -d oai_spgwu', '\$', 60) + if self.isMagmaUsed: + listOfContainers = 'prod-cassandra prod-oai-hss prod-magma-mme prod-oai-spgwc prod-oai-spgwu-tiny prod-redis' + expectedHealthyContainers = 6 + else: + listOfContainers = 'prod-cassandra prod-oai-hss prod-oai-mme prod-oai-spgwc prod-oai-spgwu-tiny' + expectedHealthyContainers = 5 + + # Checking for additional services + mySSH.command('docker-compose config', '\$', 5) + configResponse = mySSH.getBefore() + if configResponse.count('flexran_rtc') == 1: + mySSH.command('docker-compose up -d flexran_rtc', '\$', 60) + listOfContainers += ' prod-flexran-rtc' + expectedHealthyContainers += 1 + if configResponse.count('trf_gen') == 1: + mySSH.command('docker-compose up -d trf_gen', '\$', 60) + listOfContainers += ' prod-trf-gen' + expectedHealthyContainers += 1 + + mySSH.command('docker-compose config | grep --colour=never image', '\$', 10) + html_cell = '
\n'
+		listOfImages = mySSH.getBefore()
+		for imageLine in listOfImages.split('\\r\\n'):
+			res1 = re.search('image: (?P[a-zA-Z0-9\-]+):(?P[a-zA-Z0-9\-]+)', str(imageLine))
+			res2 = re.search('cassandra|redis', str(imageLine))
+			if res1 is not None and res2 is None:
+				html_cell += res1.group('name') + ':' + res1.group('tag') + ' '
+				nbChars = len(res1.group('name')) + len(res1.group('tag')) + 2
+				while (nbChars < 32):
+					html_cell += ' '
+					nbChars += 1
+				mySSH.command('docker image inspect --format="Size = {{.Size}} bytes" ' + res1.group('name') + ':' + res1.group('tag'), '\$', 10)
+				res3 = re.search('Size *= *(?P[0-9\-]*) *bytes', mySSH.getBefore())
+				if res3 is not None:
+					imageSize = int(res3.group('size'))
+					imageSize = int(imageSize/(1024*1024))
+					html_cell += str(imageSize) + ' MBytes '
+				mySSH.command('docker image inspect --format="Date = {{.Created}}" ' + res1.group('name') + ':' + res1.group('tag'), '\$', 10)
+				res4 = re.search('Date *= *(?P[0-9\-]*)T', mySSH.getBefore())
+				if res4 is not None:
+					html_cell += '(' + res4.group('date') + ')'
+				html_cell += '\n'
+		html_cell += '
' + # Checking if all are healthy + cnt = 0 + while (cnt < 3): + mySSH.command('docker inspect --format=\'{{.State.Health.Status}}\' ' + listOfContainers, '\$', 10) + unhealthyNb = mySSH.getBefore().count('unhealthy') + healthyNb = mySSH.getBefore().count('healthy') - unhealthyNb + startingNb = mySSH.getBefore().count('starting') + if healthyNb == expectedHealthyContainers: + cnt = 10 + else: + time.sleep(10) + cnt += 1 + logging.debug(' -- ' + str(healthyNb) + ' healthy container(s)') + logging.debug(' -- ' + str(unhealthyNb) + ' unhealthy container(s)') + logging.debug(' -- ' + str(startingNb) + ' still starting container(s)') + html_queue = SimpleQueue() + html_queue.put(html_cell) + if healthyNb == expectedHealthyContainers: + mySSH.command('docker exec -d prod-oai-hss /bin/bash -c "nohup tshark -i any -f \'port 9042 or port 3868\' -w /tmp/hss_check_run.pcap 2>&1 > /dev/null"', '\$', 5) + if self.isMagmaUsed: + mySSH.command('docker exec -d prod-magma-mme /bin/bash -c "nohup tshark -i any -f \'port 3868 or port 2123 or port 36412\' -w /tmp/mme_check_run.pcap 2>&1 > /dev/null"', '\$', 10) + else: + mySSH.command('docker exec -d prod-oai-mme /bin/bash -c "nohup tshark -i any -f \'port 3868 or port 2123 or port 36412\' -w /tmp/mme_check_run.pcap 2>&1 > /dev/null"', '\$', 10) + mySSH.command('docker exec -d prod-oai-spgwc /bin/bash -c "nohup tshark -i any -f \'port 2123 or port 8805\' -w /tmp/spgwc_check_run.pcap 2>&1 > /dev/null"', '\$', 10) + # on SPGW-U, not capturing on SGI to avoid huge file + mySSH.command('docker exec -d prod-oai-spgwu-tiny /bin/bash -c "nohup tshark -i any -f \'port 8805\' -w /tmp/spgwu_check_run.pcap 2>&1 > /dev/null"', '\$', 10) + mySSH.close() + logging.debug('Deployment OK') + HTML.CreateHtmlTestRowQueue(self.Type, 'OK', 1, html_queue) + else: + mySSH.close() + logging.debug('Deployment went wrong') + HTML.CreateHtmlTestRowQueue(self.Type, 'KO', 1, html_queue) + + def UndeployEpc(self, HTML): + logging.debug('Trying to undeploy') + # No check down, we suppose everything done before. + + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + # Checking if it is a MAGMA deployment. + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.command('docker-compose ps -a', '\$', 5) + self.isMagmaUsed = False + result = re.search('magma', mySSH.getBefore()) + if result is not None: + self.isMagmaUsed = True + logging.debug('MAGMA MME is used!') + # Recovering logs and pcap files + mySSH.command('cd ' + self.SourceCodePath + '/logs', '\$', 5) + mySSH.command('docker exec -it prod-oai-hss /bin/bash -c "killall --signal SIGINT oai_hss tshark"', '\$', 5) + if self.isMagmaUsed: + mySSH.command('docker exec -it prod-magma-mme /bin/bash -c "killall --signal SIGINT tshark"', '\$', 5) + else: + mySSH.command('docker exec -it prod-oai-mme /bin/bash -c "killall --signal SIGINT tshark"', '\$', 5) + mySSH.command('docker exec -it prod-oai-spgwc /bin/bash -c "killall --signal SIGINT oai_spgwc tshark"', '\$', 5) + mySSH.command('docker exec -it prod-oai-spgwu-tiny /bin/bash -c "killall --signal SIGINT tshark"', '\$', 5) + mySSH.command('docker logs prod-oai-hss > hss_' + self.testCase_id + '.log', '\$', 5) + if self.isMagmaUsed: + mySSH.command('docker cp --follow-link prod-magma-mme:/var/log/mme.log mme_' + self.testCase_id + '.log', '\$', 15) + else: + mySSH.command('docker logs prod-oai-mme > mme_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('docker logs prod-oai-spgwc > spgwc_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('docker logs prod-oai-spgwu-tiny > spgwu_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('docker cp prod-oai-hss:/tmp/hss_check_run.pcap hss_' + self.testCase_id + '.pcap', '\$', 60) + if self.isMagmaUsed: + mySSH.command('docker cp prod-magma-mme:/tmp/mme_check_run.pcap mme_' + self.testCase_id + '.pcap', '\$', 60) + else: + mySSH.command('docker cp prod-oai-mme:/tmp/mme_check_run.pcap mme_' + self.testCase_id + '.pcap', '\$', 60) + mySSH.command('tshark -r mme_' + self.testCase_id + '.pcap | egrep --colour=never "Tracking area update"', '\$', 60) + result = re.search('Tracking area update request', mySSH.getBefore()) + if result is not None: + message = 'UE requested ' + str(mySSH.getBefore().count('Tracking area update request')) + 'Tracking area update request(s)' + else: + message = 'No Tracking area update request' + logging.debug(message) + mySSH.command('docker cp prod-oai-spgwc:/tmp/spgwc_check_run.pcap spgwc_' + self.testCase_id + '.pcap', '\$', 60) + mySSH.command('docker cp prod-oai-spgwu-tiny:/tmp/spgwu_check_run.pcap spgwu_' + self.testCase_id + '.pcap', '\$', 60) + # Remove all + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + if self.isMagmaUsed: + listOfContainers = 'prod-cassandra prod-oai-hss prod-magma-mme prod-oai-spgwc prod-oai-spgwu-tiny prod-redis' + nbContainers = 6 + else: + listOfContainers = 'prod-cassandra prod-oai-hss prod-oai-mme prod-oai-spgwc prod-oai-spgwu-tiny' + nbContainers = 5 + # Checking for additional services + mySSH.command('docker-compose config', '\$', 5) + configResponse = mySSH.getBefore() + if configResponse.count('flexran_rtc') == 1: + listOfContainers += ' prod-flexran-rtc' + nbContainers += 1 + if configResponse.count('trf_gen') == 1: + listOfContainers += ' prod-trf-gen' + nbContainers += 1 + + mySSH.command('docker-compose down', '\$', 60) + mySSH.command('docker inspect --format=\'{{.State.Health.Status}}\' ' + listOfContainers, '\$', 10) + noMoreContainerNb = mySSH.getBefore().count('No such object') + mySSH.command('docker inspect --format=\'{{.Name}}\' prod-oai-public-net prod-oai-private-net', '\$', 10) + noMoreNetworkNb = mySSH.getBefore().count('No such object') + mySSH.close() + html_queue = SimpleQueue() + html_cell = '
' + message + '
' + html_queue.put(html_cell) + if noMoreContainerNb == nbContainers and noMoreNetworkNb == 2: + logging.debug('Undeployment OK') + HTML.CreateHtmlTestRowQueue(self.Type, 'OK', 1, html_queue) + else: + logging.debug('Undeployment went wrong') + HTML.CreateHtmlTestRowQueue(self.Type, 'KO', 1, html_queue) def LogCollectHSS(self): - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) mySSH.command('rm -f hss.log.zip', '\$', 5) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker cp ' + self.containerPrefix + '-oai-hss:/openair-hss/hss_check_run.log .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-hss:/tmp/hss_check_run.pcap .', '\$', 60) - mySSH.command('zip hss.log.zip hss_check_run.*', '\$', 60) + mySSH.command('docker inspect prod-oai-hss', '\$', 10) + result = re.search('No such object', mySSH.getBefore()) + if result is not None: + mySSH.command('cd ../logs', '\$', 5) + mySSH.command('rm -f hss.log.zip', '\$', 5) + mySSH.command('zip hss.log.zip hss_*.*', '\$', 60) + mySSH.command('mv hss.log.zip ../scripts', '\$', 60) + else: + mySSH.command('docker cp ' + self.containerPrefix + '-oai-hss:/openair-hss/hss_check_run.log .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-hss:/tmp/hss_check_run.pcap .', '\$', 60) + mySSH.command('zip hss.log.zip hss_check_run.*', '\$', 60) + elif re.match('OAICN5G', self.Type, re.IGNORECASE): + logging.debug('LogCollect is bypassed for that variant') elif re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('zip hss.log.zip hss*.log', '\$', 60) mySSH.command('echo ' + self.Password + ' | sudo -S rm hss*.log', '\$', 5) @@ -426,42 +808,66 @@ class EPCManagement(): mySSH.close() def LogCollectMME(self): - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) mySSH.command('rm -f mme.log.zip', '\$', 5) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker cp ' + self.containerPrefix + '-oai-mme:/openair-mme/mme_check_run.log .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-mme:/tmp/mme_check_run.pcap .', '\$', 60) - mySSH.command('zip mme.log.zip mme_check_run.*', '\$', 60) + mySSH.command('docker inspect prod-oai-mme', '\$', 10) + result = re.search('No such object', mySSH.getBefore()) + if result is not None: + mySSH.command('cd ../logs', '\$', 5) + mySSH.command('rm -f mme.log.zip', '\$', 5) + mySSH.command('zip mme.log.zip mme_*.*', '\$', 60) + mySSH.command('mv mme.log.zip ../scripts', '\$', 60) + else: + mySSH.command('docker cp ' + self.containerPrefix + '-oai-mme:/openair-mme/mme_check_run.log .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-mme:/tmp/mme_check_run.pcap .', '\$', 60) + mySSH.command('zip mme.log.zip mme_check_run.*', '\$', 60) + elif re.match('OAICN5G', self.Type, re.IGNORECASE): + mySSH.command('cd ' + self.SourceCodePath + '/logs','\$', 5) + mySSH.command('cp -f /tmp/oai-cn5g.pcap .','\$', 30) + mySSH.command('zip mme.log.zip oai-amf.log oai-nrf.log oai-cn5g.pcap','\$', 30) + mySSH.command('mv mme.log.zip ' + self.SourceCodePath + '/scripts','\$', 30) elif re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('zip mme.log.zip mme*.log', '\$', 60) mySSH.command('echo ' + self.Password + ' | sudo -S rm mme*.log', '\$', 5) elif re.match('ltebox', self.Type, re.IGNORECASE): mySSH.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) - mySSH.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) + mySSH.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0 amfLog.0 ngapcLog.0 ngapcommonLog.0 ngapsLog.0', '\$', 60) else: logging.error('This option should not occur!') mySSH.close() def LogCollectSPGW(self): - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) mySSH.command('rm -f spgw.log.zip', '\$', 5) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwc:/openair-spgwc/spgwc_check_run.log .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwu-tiny:/openair-spgwu-tiny/spgwu_check_run.log .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwc:/tmp/spgwc_check_run.pcap .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwu-tiny:/tmp/spgwu_check_run.pcap .', '\$', 60) - mySSH.command('zip spgw.log.zip spgw*_check_run.*', '\$', 60) + mySSH.command('docker inspect prod-oai-mme', '\$', 10) + result = re.search('No such object', mySSH.getBefore()) + if result is not None: + mySSH.command('cd ../logs', '\$', 5) + mySSH.command('rm -f spgw.log.zip', '\$', 5) + mySSH.command('zip spgw.log.zip spgw*.*', '\$', 60) + mySSH.command('mv spgw.log.zip ../scripts', '\$', 60) + else: + mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwc:/openair-spgwc/spgwc_check_run.log .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwu-tiny:/openair-spgwu-tiny/spgwu_check_run.log .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwc:/tmp/spgwc_check_run.pcap .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwu-tiny:/tmp/spgwu_check_run.pcap .', '\$', 60) + mySSH.command('zip spgw.log.zip spgw*_check_run.*', '\$', 60) + elif re.match('OAICN5G', self.Type, re.IGNORECASE): + mySSH.command('cd ' + self.SourceCodePath + '/logs','\$', 5) + mySSH.command('zip spgw.log.zip oai-smf.log oai-spgwu.log','\$', 30) + mySSH.command('mv spgw.log.zip ' + self.SourceCodePath + '/scripts','\$', 30) elif re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('zip spgw.log.zip spgw*.log', '\$', 60) mySSH.command('echo ' + self.Password + ' | sudo -S rm spgw*.log', '\$', 5) elif re.match('ltebox', self.Type, re.IGNORECASE): - mySSH.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) - mySSH.command('zip spgw.log.zip xGwLog.0', '\$', 60) + mySSH.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) + mySSH.command('zip spgw.log.zip xGwLog.0 upfLog.0', '\$', 60) else: logging.error('This option should not occur!') mySSH.close() - diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 8f2d38cced..b172ffb711 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -47,7 +47,7 @@ import constants as CONST class HTMLManagement(): def __init__(self): - + self.htmlFile = '' self.htmlHeaderCreated = False self.htmlFooterCreated = False @@ -64,6 +64,10 @@ class HTMLManagement(): self.htmlTabIcons = [] self.testXMLfiles = [] + self.testUnstable = False + self.testMinStableId = '999999' + self.testStabilityPointReached = False + self.htmleNBFailureMsg = '' self.htmlUEFailureMsg = '' @@ -82,13 +86,13 @@ class HTMLManagement(): #----------------------------------------------------------- # Setters and Getters #----------------------------------------------------------- - + def SethtmlUEConnected(self, nbUEs): if nbUEs > 0: self.htmlUEConnected = nbUEs else: self.htmlUEConnected = 1 - + #----------------------------------------------------------- @@ -178,9 +182,12 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.write(' \n') - if (ADBIPAddress != 'none'): + if (ADBIPAddress != 'none') and (ADBIPAddress != 'modules'): self.htmlFile.write('

' + str(self.htmlNb_Smartphones) + ' UE(s) is(are) connected to ADB bench server

\n') self.htmlFile.write('

' + str(self.htmlNb_CATM_Modules) + ' CAT-M UE(s) is(are) connected to bench server

\n') + elif (ADBIPAddress == 'modules'): + self.htmlUEConnected = 1 + self.htmlFile.write('

1 commercial module is connected to CI bench

\n') else: self.htmlUEConnected = 1 self.htmlFile.write('

1 OAI UE(s) is(are) connected to CI bench

\n') @@ -214,7 +221,7 @@ class HTMLManagement(): self.htmlFile.write('
\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') @@ -230,13 +237,20 @@ class HTMLManagement(): def CreateHtmlTabFooter(self, passStatus): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + testOkEvenIfUnstable = False + if self.testUnstable and not passStatus: + if self.testStabilityPointReached or self.testMinStableId == '999999': + testOkEvenIfUnstable = True self.htmlFile = open('test_results.html', 'a') self.htmlFile.write(' \n') self.htmlFile.write(' \n') if passStatus: self.htmlFile.write(' \n') else: - self.htmlFile.write(' \n') + if testOkEvenIfUnstable: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('
Relative Time (ms)Relative Time (s)Test IdTest DescTest Options
Final Tab StatusPASS FAIL KNOWN UNSTABLE SCENARIO FAIL
\n') self.htmlFile.write('
\n') @@ -246,7 +260,10 @@ class HTMLManagement(): cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" subprocess.run(cmd, shell=True) else: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" + if testOkEvenIfUnstable: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" + else: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" subprocess.run(cmd, shell=True) self.htmlFooterCreated = False @@ -351,6 +368,16 @@ class HTMLManagement(): self.htmlFile.write(' KO - SPGW process not found\n') elif (processesStatus == CONST.UE_IP_ADDRESS_ISSUE): self.htmlFile.write(' KO - Could not retrieve UE IP address\n') + elif (processesStatus == CONST.PHYSIM_IMAGE_ABSENT): + self.htmlFile.write(' KO - No such image oai-physim\n') + elif (processesStatus == CONST.OC_LOGIN_FAIL): + self.htmlFile.write(' KO - Could not log onto cluster\n') + elif (processesStatus == CONST.OC_PROJECT_FAIL): + self.htmlFile.write(' KO - Could not register into cluster project\n') + elif (processesStatus == CONST.OC_IS_FAIL): + self.htmlFile.write(' KO - Could not create Image Stream\n') + elif (processesStatus == CONST.OC_PHYSIM_DEPLOY_FAIL): + self.htmlFile.write(' KO - Could not properly deploy physim on cluster\n') else: self.htmlFile.write(' ' + str(status) + '\n') else: @@ -385,6 +412,91 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.close() + + def CreateHtmlNextTabHeaderTestRow(self, collectInfo, allImagesSize, machine='eNB'): + if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): + return + self.htmlFile = open('test_results.html', 'a') + if bool(collectInfo) == False: + self.htmlFile.write(' \n') + self.htmlFile.write(' ----IMAGES BUILDING FAILED - Unable to recover the image logs ---- \n') + self.htmlFile.write(' \n') + else: + for image in collectInfo: + files = collectInfo[image] + # TabHeader for image logs on built shared and target images + if allImagesSize[image].count('unknown') > 0: + self.htmlFile.write(' \n') + elif allImagesSize[image].count('Build Failed') > 0: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' ---- ' + image + ' IMAGE STATUS ----> Size ' + allImagesSize[image] + ' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Element\n') + self.htmlFile.write(' Nb Errors\n') + self.htmlFile.write(' Nb Warnings\n') + self.htmlFile.write(' Status\n') + self.htmlFile.write(' \n') + + for fil in files: + parameters = files[fil] + # TestRow for image logs on built shared and target images + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + fil + ' \n') + if (parameters['errors'] == 0): + self.htmlFile.write(' ' + str(parameters['errors']) + '\n') + else: + self.htmlFile.write(' ' + str(parameters['errors']) + '\n') + if (parameters['errors'] > 0): + self.htmlFile.write(' ' + str(parameters['warnings']) + '\n') + elif (parameters['warnings'] == 0): + self.htmlFile.write(' ' + str(parameters['warnings']) + '\n') + elif ((parameters['warnings'] > 0) and (parameters['warnings'] <= 20)): + self.htmlFile.write(' ' + str(parameters['warnings']) + '\n') + else: + self.htmlFile.write(' ' + str(parameters['warnings']) + '\n') + if (parameters['errors'] == 0) and (parameters['warnings'] == 0): + self.htmlFile.write(' OK \n') + elif (parameters['errors'] == 0) and ((parameters['warnings'] > 0) and (parameters['warnings'] <= 20)): + self.htmlFile.write(' OK \n') + else: + self.htmlFile.write(' NOT OK \n') + self.htmlFile.write(' \n') + self.htmlFile.close() + + #for the moment it is limited to 4 columns, to be made generic later + def CreateHtmlDataLogTable(self, DataLog): + if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): + return + self.htmlFile = open('test_results.html', 'a') + + # TabHeader + self.htmlFile.write(' \n') + self.htmlFile.write(' ---- ' + DataLog['Title'] + ' ---- \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' '+ DataLog['ColNames'][0] +'\n') + self.htmlFile.write(' ' + DataLog['ColNames'][1] + '\n') + self.htmlFile.write(' ' + DataLog['ColNames'][2] + '\n') + self.htmlFile.write(' '+ DataLog['ColNames'][3] +'\n') + self.htmlFile.write(' \n') + + for k in DataLog['Data']: + # TestRow + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + k + ' \n') + self.htmlFile.write(' ' + DataLog['Data'][k][0] + ' \n') + self.htmlFile.write(' ' + DataLog['Data'][k][1] + ' \n') + if float(DataLog['Data'][k][2])> DataLog['Threshold'][k]: + self.htmlFile.write(' ' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '\n') + else: + self.htmlFile.write(' ' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '\n') + self.htmlFile.write(' \n') + self.htmlFile.close() + + def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): self.htmlFile = open('test_results.html', 'a') @@ -418,3 +530,140 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.close() + def CreateHtmlTestRowCppCheckResults(self, CCR): + if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): + return + self.htmlFile = open('test_results.html', 'a') + vId = 0 + for version in CCR.versions: + self.htmlFile.write(' \n') + self.htmlFile.write(' Results for cppcheck v ' + version + ' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' NB ERRORS\n') + if CCR.nbErrors[vId] == 0: + myColor = 'lightgreen' + elif CCR.nbErrors[vId] < 20: + myColor = 'orange' + else: + myColor = 'lightcoral' + self.htmlFile.write(' ' + str(CCR.nbErrors[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' NB WARNINGS\n') + if CCR.nbWarnings[vId] == 0: + myColor = 'lightgreen' + elif CCR.nbWarnings[vId] < 20: + myColor = 'orange' + else: + myColor = 'lightcoral' + self.htmlFile.write(' ' + str(CCR.nbWarnings[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' ----------------- \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Memory leak\n') + self.htmlFile.write(' ' + str(CCR.nbMemLeaks[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Possible null pointer deference\n') + self.htmlFile.write(' ' + str(CCR.nbNullPtrs[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Uninitialized variable\n') + self.htmlFile.write(' ' + str(CCR.nbUninitVars[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Undefined behaviour shifting\n') + self.htmlFile.write(' ' + str(CCR.nbTooManyBitsShift[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Signed integer overflow\n') + self.htmlFile.write(' ' + str(CCR.nbIntegerOverflow[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Printf formatting issues\n') + self.htmlFile.write(' ' + str(CCR.nbInvalidPrintf[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Modulo result is predetermined\n') + self.htmlFile.write(' ' + str(CCR.nbModuloAlways[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Opposite Condition -> dead code\n') + self.htmlFile.write(' ' + str(CCR.nbOppoInnerCondition[vId]) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Wrong Scanf Nb Args\n') + self.htmlFile.write(' ' + str(CCR.nbWrongScanfArg[vId]) + '\n') + self.htmlFile.write(' \n') + vId += 1 + + def CreateHtmlTestRowPhySimTestResult(self, testSummary, testResult): + if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): + return + self.htmlFile = open('test_results.html', 'a') + if bool(testResult) == False and bool(testSummary) == False: + self.htmlFile.write(' \n') + self.htmlFile.write(' ----PHYSIM TESTING FAILED - Unable to recover the test logs ---- \n') + self.htmlFile.write(' \n') + else: + # Tab header + self.htmlFile.write(' \n') + self.htmlFile.write(' ---- PHYSIM TEST SUMMARY---- \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' LogFile Name\n') + self.htmlFile.write(' Nb Tests\n') + self.htmlFile.write(' Nb Failure\n') + self.htmlFile.write(' Nb Pass\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' physim_test.txt \n') + self.htmlFile.write(' ' + str(testSummary['Nbtests']) + ' \n') + if testSummary['Nbfail'] == 0: + self.htmlFile.write(' ' + str(testSummary['Nbfail']) + ' \n') + else: + self.htmlFile.write(' ' + str(testSummary['Nbfail']) + ' \n') + self.htmlFile.write(' ' + str(testSummary['Nbpass']) + ' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' ---- PHYSIM TEST DETAIL INFO---- \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Test Name\n') + self.htmlFile.write(' Test Description\n') + self.htmlFile.write(' Result\n') + self.htmlFile.write(' \n') + y = '' + for key, value in testResult.items(): + x = key.split(".") + if x[0] != y: + self.htmlFile.write(' \n') + self.htmlFile.write(' "' + x[0] + '" series \n') + self.htmlFile.write(' \n') + y = x[0] + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + key + ' \n') + self.htmlFile.write(' ' + value[0] + '\n') + if 'PASS' in value: + self.htmlFile.write(' ' + value[1] + '\n') + else: + self.htmlFile.write(' ' + value[1] + '\n') + + self.htmlFile.close() diff --git a/ci-scripts/main.py b/ci-scripts/main.py index d37f205f4e..ddf9bb531e 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -37,8 +37,14 @@ import helpreadme as HELP import constants as CONST -import cls_physim #class PhySim for physical simulators build and test -import cls_cots_ue #class CotsUe for Airplane mode control + +import cls_oaicitest #main class for OAI CI test framework +import cls_physim #class PhySim for physical simulators build and test +import cls_cots_ue #class CotsUe for Airplane mode control +import cls_containerize #class Containerize for all container-based operations on RAN/UE objects +import cls_static_code_analysis #class for static code analysis +import cls_ci_ueinfra #class defining the multi Ue infrastrucure +import cls_physim1 #class PhySim for physical simulators deploy and run import sshconnection import epc @@ -59,6 +65,7 @@ import xml.etree.ElementTree as ET import logging import datetime import signal +import subprocess from multiprocessing import Process, Lock, SimpleQueue logging.basicConfig( level=logging.DEBUG, @@ -67,3017 +74,6 @@ logging.basicConfig( -#----------------------------------------------------------- -# OaiCiTest Class Definition -#----------------------------------------------------------- -class OaiCiTest(): - - def __init__(self): - self.ranRepository = '' - self.ranBranch = '' - self.ranCommitID = '' - self.ranAllowMerge = False - self.ranTargetBranch = '' - - self.FailReportCnt = 0 - self.ADBIPAddress = '' - self.ADBUserName = '' - self.ADBPassword = '' - self.ADBCentralized = True - self.testCase_id = '' - self.testXMLfiles = [] - self.desc = '' - self.ping_args = '' - self.ping_packetloss_threshold = '' - self.iperf_args = '' - self.iperf_packetloss_threshold = '' - self.iperf_profile = '' - self.iperf_options = '' - self.nbMaxUEtoAttach = -1 - self.UEDevices = [] - self.UEDevicesStatus = [] - self.UEDevicesRemoteServer = [] - self.UEDevicesRemoteUser = [] - self.UEDevicesOffCmd = [] - self.UEDevicesOnCmd = [] - self.UEDevicesRebootCmd = [] - self.CatMDevices = [] - self.UEIPAddresses = [] - self.idle_sleep_time = 0 - self.x2_ho_options = 'network' - self.x2NbENBs = 0 - self.x2ENBBsIds = [] - self.x2ENBConnectedUEs = [] - self.repeatCounts = [] - self.finalStatus = False - self.UEIPAddress = '' - self.UEUserName = '' - self.UEPassword = '' - self.UE_instance = 0 - self.UESourceCodePath = '' - self.UELogFile = '' - self.Build_OAI_UE_args = '' - self.Initialize_OAI_UE_args = '' - self.clean_repository = True - self.air_interface='' - self.expectedNbOfConnectedUEs = 0 - - def BuildOAIUE(self): - if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - result = re.search('--nrUE', self.Build_OAI_UE_args) - if result is not None: - self.air_interface='nr-uesoftmodem' - ue_prefix = 'NR ' - else: - self.air_interface='lte-uesoftmodem' - ue_prefix = '' - result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) - if result is not None: - full_ran_repo_name = self.ranRepository - else: - full_ran_repo_name = self.ranRepository + '.git' - SSH.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) - SSH.command('cd ' + self.UESourceCodePath, '\$', 5) - SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) - # here add a check if git clone or git fetch went smoothly - SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - SSH.command('git config user.name "OAI Jenkins"', '\$', 5) - if self.clean_repository: - SSH.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', SSH.getBefore()) - if result is not None: - mismatch = False - SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, SSH.getBefore()) - if result is None: - mismatch = True - SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranAllowMerge: - result = re.search('YES', SSH.getBefore()) - if result is None: - mismatch = True - SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - result = re.search('develop', SSH.getBefore()) - else: - result = re.search(self.ranTargetBranch, SSH.getBefore()) - if result is None: - mismatch = True - else: - result = re.search('NO', SSH.getBefore()) - if result is None: - mismatch = True - if not mismatch: - SSH.close() - HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK) - return - - SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) - - # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should already been checked earlier - if self.ranAllowMerge: - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - SSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - SSH.command('source oaienv', '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('mkdir -p log', '\$', 5) - SSH.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - SSH.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 900) - SSH.command('ls ran_build/build', '\$', 3) - SSH.command('ls ran_build/build', '\$', 3) - buildStatus = True - result = re.search(self.air_interface, SSH.getBefore()) - if result is None: - buildStatus = False - SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) - SSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) - SSH.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) - if buildStatus: - # Generating a BUILD INFO file - SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranAllowMerge: - SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - SSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.close() - HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') - else: - SSH.close() - logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') - HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', CONST.ALL_PROCESSES_OK, 'OAI UE') - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - - def CheckFlexranCtrlInstallation(self): - if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': - return - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) - result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) - if result is not None: - RAN.flexranCtrlInstalled=True - logging.debug('Flexran Controller is installed') - SSH.close() - - def InitializeFlexranCtrl(self): - if RAN.flexranCtrlInstalled == False: - return - if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd /opt/flexran_rtc', '\$', 5) - SSH.command('echo ' + EPC.Password + ' | sudo -S rm -f log/*.log', '\$', 5) - SSH.command('echo ' + EPC.Password + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + EPC.Password + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + EPC.Password + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) - SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) - result = re.search('rt_controller -c ', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') - RAN.flexranCtrlStarted=True - SSH.close() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def InitializeUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if not self.ADBCentralized: - # Reboot UE - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) - # Wait - #time.sleep(60) - # Put in LTE-Mode only - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) - # enable data service - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - # we need to do radio on/off cycle to make sure of above changes - # airplane mode off // radio on - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - #time.sleep(10) - # airplane mode on // radio off - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - - # normal procedure without reboot - # enable data service - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - # airplane mode on // radio off - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - SSH.close() - return - # enable data service - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - - # The following commands are deprecated since we no longer work on Android 7+ - # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) - # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) - # a dedicated script has to be installed inside the UE - # airplane mode on means call /data/local/tmp/off - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - #airplane mode off means call /data/local/tmp/on - logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def InitializeUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.InitializeUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def InitializeOAIUE(self): - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - if self.air_interface == 'lte-uesoftmodem': - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is None: - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', pStatus) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - UE_prefix = '' - else: - UE_prefix = 'NR ' - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - # b2xx_fx3_utils reset procedure - SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 60) - result = re.search('type: b200', SSH.getBefore()) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - SSH.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 60) - result = re.search('type: n3xx', str(SSH.getBefore())) - if result is not None: - logging.debug('Found a N3xx device --> resetting it') - SSH.command('cd ' + self.UESourceCodePath, '\$', 5) - # Initialize_OAI_UE_args usually start with -C and followed by the location in repository - SSH.command('source oaienv', '\$', 5) - SSH.command('cd cmake_targets/ran_build/build', '\$', 5) - if self.air_interface == 'lte-uesoftmodem': - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - # We may have to regenerate the .u* files - if result is None: - SSH.command('ls /tmp/*.sed', '\$', 5) - result = re.search('adapt_usim_parameters', SSH.getBefore()) - if result is not None: - SSH.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - else: - SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) - else: - SSH.command('if [ -e rbconfig.raw ]; then echo ' + self.UEPassword + ' | sudo -S rm rbconfig.raw; fi', '\$', 5) - SSH.command('if [ -e reconfig.raw ]; then echo ' + self.UEPassword + ' | sudo -S rm reconfig.raw; fi', '\$', 5) - # Copy the RAW files from gNB running directory (maybe on another machine) - copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/rbconfig.raw', '.') - if (copyin_res == 0): - SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './rbconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build') - copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/reconfig.raw', '.') - if (copyin_res == 0): - SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './reconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build') - SSH.command('echo "ulimit -c unlimited && ./'+ self.air_interface +' ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - self.UELogFile = 'ue_' + self.testCase_id + '.log' - - # We are now looping several times to hope we really sync w/ an eNB - doOutterLoop = True - outterLoopCounter = 5 - gotSyncStatus = True - fullSyncStatus = True - while (doOutterLoop): - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/ran_build/build', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - SSH.command('echo $USER; nohup sudo -E ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) - time.sleep(6) - SSH.command('cd ../..', '\$', 5) - doLoop = True - loopCounter = 10 - gotSyncStatus = True - # the 'got sync' message is for the UE threads synchronization - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # Here should never occur - logging.error('"got sync" message never showed!') - gotSyncStatus = False - doLoop = False - continue - SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - if self.air_interface == 'nr-uesoftmodem': - result = re.search('Starting sync detection', SSH.getBefore()) - else: - result = re.search('got sync', SSH.getBefore()) - if result is None: - time.sleep(10) - else: - doLoop = False - logging.debug('Found "got sync" message!') - if gotSyncStatus == False: - # we certainly need to stop the lte-uesoftmodem process if it is still running! - SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT -r *-uesoftmodem', '\$', 4) - time.sleep(3) - outterLoopCounter = outterLoopCounter - 1 - if (outterLoopCounter == 0): - doOutterLoop = False - continue - # We are now checking if sync w/ eNB DOES NOT OCCUR - # Usually during the cell synchronization stage, the UE returns with No cell synchronization message - # That is the case for LTE - # In NR case, it's a positive message that will show if synchronization occurs - doLoop = True - if self.air_interface == 'nr-uesoftmodem': - loopCounter = 10 - else: - # We are now checking if sync w/ eNB DOES NOT OCCUR - # Usually during the cell synchronization stage, the UE returns with No cell synchronization message - loopCounter = 10 - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - if self.air_interface == 'nr-uesoftmodem': - # Here we do have great chances that UE did NOT cell-sync w/ gNB - doLoop = False - fullSyncStatus = False - logging.debug('Never seen the NR-Sync message (Measured Carrier Frequency) --> try again') - time.sleep(6) - # Stopping the NR-UE - SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('nr-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT nr-uesoftmodem', '\$', 4) - time.sleep(6) - else: - # Here we do have a great chance that the UE did cell-sync w/ eNB - doLoop = False - doOutterLoop = False - fullSyncStatus = True - continue - SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Frequency"', '\$', 4) - if self.air_interface == 'nr-uesoftmodem': - # Positive messaging --> - result = re.search('Measured Carrier Frequency', SSH.getBefore()) - if result is not None: - doLoop = False - doOutterLoop = False - fullSyncStatus = True - else: - time.sleep(6) - else: - # Negative messaging --> - result = re.search('No cell synchronization found', SSH.getBefore()) - if result is None: - time.sleep(6) - else: - doLoop = False - fullSyncStatus = False - logging.debug('Found: "No cell synchronization" message! --> try again') - time.sleep(6) - SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) - outterLoopCounter = outterLoopCounter - 1 - if (outterLoopCounter == 0): - doOutterLoop = False - - if fullSyncStatus and gotSyncStatus: - doInterfaceCheck = False - if self.air_interface == 'lte-uesoftmodem': - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is None: - doInterfaceCheck = True - # For the moment, only in explicit noS1 without kernel module (ie w/ tunnel interface) - if self.air_interface == 'nr-uesoftmodem': - result = re.search('--noS1 --nokrnmod 1', str(self.Initialize_OAI_UE_args)) - if result is not None: - doInterfaceCheck = True - if doInterfaceCheck: - SSH.command('ifconfig oaitun_ue1', '\$', 4) - SSH.command('ifconfig oaitun_ue1', '\$', 4) - # ifconfig output is different between ubuntu 16 and ubuntu 18 - result = re.search('inet addr:1|inet 1', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') - tunnelInterfaceStatus = True - else: - logging.debug(SSH.getBefore()) - logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') - tunnelInterfaceStatus = False - if RAN.eNBmbmsEnables[0]: - SSH.command('ifconfig oaitun_uem1', '\$', 4) - result = re.search('inet addr', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_uem1 interface is mounted and configured\u001B[0m') - tunnelInterfaceStatus = tunnelInterfaceStatus and True - else: - logging.error('\u001B[1m oaitun_uem1 interface is either NOT mounted or NOT configured\u001B[0m') - tunnelInterfaceStatus = False - else: - tunnelInterfaceStatus = True - else: - tunnelInterfaceStatus = True - - SSH.close() - if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') - logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') - if (self.ADBIPAddress != 'none'): - self.UEDevices = [] - self.UEDevices.append('OAI-UE') - self.UEDevicesStatus = [] - self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) - else: - if self.air_interface == 'lte-uesoftmodem': - if RAN.eNBmbmsEnables[0]: - HTML.htmlUEFailureMsg='oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' - else: - HTML.htmlUEFailureMsg='oaitun_ue1 interface is either NOT mounted or NOT configured' - HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') - else: - HTML.htmlUEFailureMsg='nr-uesoftmodem did NOT synced' - HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') - logging.error('\033[91mInitialize OAI UE Failed! \033[0m') - self.AutoTerminateUEandeNB() - - def checkDevTTYisUnlocked(self): - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - count = 0 - while count < 5: - SSH.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) - result = re.search('picocom', SSH.getBefore()) - if result is None: - count = 10 - else: - time.sleep(5) - count = count + 1 - SSH.close() - - def InitializeCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.enablePicocomClosure() - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - SSH.command('AT', 'OK|ERROR', 5) - SSH.command('AT', 'OK', 5) - # Doing a power cycle - SSH.command('AT^RESET', 'SIMSTORE,READY', 15) - SSH.command('AT', 'OK|ERROR', 5) - SSH.command('AT', 'OK', 5) - SSH.command('ATE1', 'OK', 5) - # Disabling the Radio - SSH.command('AT+CFUN=0', 'OK', 5) - logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - # Checking if auto-attach is enabled - SSH.command('AT^AUTOATT?', 'OK', 5) - result = re.search('AUTOATT: (?P[0-9\-]+)', SSH.getBefore()) - if result is not None: - if result.group('state') is not None: - autoAttachState = int(result.group('state')) - if autoAttachState is not None: - if autoAttachState == 0: - SSH.command('AT^AUTOATT=1', 'OK', 5) - logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') - else: - logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') - # Force closure of picocom but device might still be locked - SSH.close() - SSH.disablePicocomClosure() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - self.checkDevTTYisUnlocked() - - def TerminateCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.enablePicocomClosure() - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - SSH.command('AT', 'OK|ERROR', 5) - SSH.command('AT', 'OK', 5) - # Disabling the Radio - SSH.command('AT+CFUN=0', 'OK', 5) - logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - SSH.close() - SSH.disablePicocomClosure() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - self.checkDevTTYisUnlocked() - - def AttachCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.enablePicocomClosure() - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - SSH.command('AT', 'OK|ERROR', 5) - SSH.command('AT', 'OK', 5) - # Enabling the Radio - SSH.command('AT+CFUN=1', 'SIMSTORE,READY', 5) - logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') - time.sleep(4) - # We should check if we register - count = 0 - attach_cnt = 0 - attach_status = False - while count < 5: - SSH.command('AT+CEREG?', 'OK', 5) - result = re.search('CEREG: 2,(?P[0-9\-]+),', SSH.getBefore()) - if result is not None: - mDataConnectionState = int(result.group('state')) - if mDataConnectionState is not None: - if mDataConnectionState == 1: - count = 10 - attach_status = True - result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', SSH.getBefore()) - if result is not None: - networky = result.group('networky') - networkz = result.group('networkz') - logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m') - else: - logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m') - else: - logging.debug('+CEREG: 2,' + str(mDataConnectionState)) - attach_cnt = attach_cnt + 1 - else: - logging.debug(SSH.getBefore()) - attach_cnt = attach_cnt + 1 - count = count + 1 - time.sleep(1) - if attach_status: - SSH.command('AT+CESQ', 'OK', 5) - result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', SSH.getBefore()) - if result is not None: - nRSRQ = int(result.group('rsrq')) - nRSRP = int(result.group('rsrp')) - if (nRSRQ is not None) and (nRSRP is not None): - logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') - logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') - SSH.close() - SSH.disablePicocomClosure() - html_queue = SimpleQueue() - self.checkDevTTYisUnlocked() - if attach_status: - html_cell = '
CAT-M module Attachment Completed in ' + str(attach_cnt+4) + ' seconds'
-			if (nRSRQ is not None) and (nRSRP is not None):
-				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
-				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm
' - else: - html_cell += '' - html_queue.put(html_cell) - HTML.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) - else: - logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') - html_cell = '
CAT-M module Attachment Failed
' - html_queue.put(html_cell) - HTML.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) - self.AutoTerminateUEandeNB() - - def PingCatM(self): - if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - try: - statusQueue = SimpleQueue() - lock = Lock() - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) - SSH.command('cd scripts', '\$', 5) - if re.match('OAI', EPC.Type, re.IGNORECASE): - logging.debug('Using the OAI EPC HSS: not implemented yet') - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - else: - SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) - result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', SSH.getBefore()) - if result is not None: - moduleIPAddr = result.group('ipaddr') - else: - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - device_id = 'catm' - ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - lock.acquire() - logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - lock.release() - SSH.close() - html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' - statusQueue.put(html_cell) - if (packetLossOK): - HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) - else: - HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) - self.AutoTerminateUEandeNB() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AttachUE_common(self, device_id, statusQueue, lock, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) - else: - # airplane mode off // radio on - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(2) - max_count = 45 - count = max_count - while count > 0: - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put('mDataConnectionState Not Found!') - lock.release() - break - mDataConnectionState = int(result.group('state')) - if mDataConnectionState == 2: - logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') - lock.acquire() - statusQueue.put(max_count - count) - statusQueue.put(device_id) - statusQueue.put('Attach Completed') - lock.release() - break - count = count - 1 - if count == 15 or count == 30: - logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - time.sleep(0.5) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(0.5) - logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') - time.sleep(1) - if count == 0: - logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m') - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put('Attach Failed') - lock.release() - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AttachUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - status_queue = SimpleQueue() - lock = Lock() - nb_ue_to_connect = 0 - for device_id in self.UEDevices: - if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): - self.UEDevicesStatus[nb_ue_to_connect] = CONST.UE_STATUS_ATTACHING - p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) - p.daemon = True - p.start() - multi_jobs.append(p) - nb_ue_to_connect = nb_ue_to_connect + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - return - else: - attach_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - attach_status = False - device_id = status_queue.get() - message = status_queue.get() - if (count < 0): - html_cell = '
UE (' + device_id + ')\n' + message + '
' - else: - html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' - html_queue.put(html_cell) - if (attach_status): - cnt = 0 - while cnt < len(self.UEDevices): - if self.UEDevicesStatus[cnt] == CONST.UE_STATUS_ATTACHING: - self.UEDevicesStatus[cnt] = CONST.UE_STATUS_ATTACHED - cnt += 1 - HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - result = re.search('T_stdout', str(RAN.Initialize_eNB_args)) - if result is not None: - logging.debug('Waiting 5 seconds to fill up record file') - time.sleep(5) - else: - HTML.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def DetachUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DetachUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - cnt = 0 - for device_id in self.UEDevices: - self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHING - p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) - p.daemon = True - p.start() - multi_jobs.append(p) - cnt += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - result = re.search('T_stdout', str(RAN.Initialize_eNB_args)) - if result is not None: - logging.debug('Waiting 5 seconds to fill up record file') - time.sleep(5) - cnt = 0 - while cnt < len(self.UEDevices): - self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHED - cnt += 1 - - def RebootUE_common(self, device_id): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - previousmDataConnectionStates = [] - # Save mDataConnectionState - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') - sys.exit(1) - previousmDataConnectionStates.append(int(result.group('state'))) - # Reboot UE - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) - time.sleep(60) - previousmDataConnectionState = previousmDataConnectionStates.pop(0) - count = 180 - while count > 0: - count = count - 1 - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) - if result is None: - mDataConnectionState = None - else: - mDataConnectionState = int(result.group('state')) - logging.debug('mDataConnectionState = ' + result.group('state')) - if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2): - logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m') - time.sleep(1) - else: - logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m') - break - if count == 0: - logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') - sys.exit(1) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def RebootUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - multi_jobs = [] - for device_id in self.UEDevices: - p = Process(target = self.RebootUE_common, args = (device_id,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def DataDisableUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # disable data service - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DataDisableUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.DataDisableUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def DataEnableUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # enable data service - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DataEnableUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.DataEnableUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def GetAllUEDevices(self, terminate_ue_flag): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - SSH.command('adb devices', '\$', 15) - self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) - SSH.close() - else: - if (os.path.isfile('./phones_list.txt')): - os.remove('./phones_list.txt') - SSH.command('ls /etc/*/phones*.txt', '\$', 5) - result = re.search('/etc/ci/phones_list.txt', SSH.getBefore()) - SSH.close() - if (result is not None) and (len(self.UEDevices) == 0): - SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') - if (os.path.isfile('./phones_list.txt')): - phone_list_file = open('./phones_list.txt', 'r') - for line in phone_list_file.readlines(): - line = line.strip() - result = re.search('^#', line) - if result is not None: - continue - comma_split = line.split(",") - self.UEDevices.append(comma_split[0]) - self.UEDevicesRemoteServer.append(comma_split[1]) - self.UEDevicesRemoteUser.append(comma_split[2]) - self.UEDevicesOffCmd.append(comma_split[3]) - self.UEDevicesOnCmd.append(comma_split[4]) - self.UEDevicesRebootCmd.append(comma_split[5]) - phone_list_file.close() - - if terminate_ue_flag == True: - if len(self.UEDevices) == 0: - logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') - sys.exit(1) - if len(self.UEDevicesStatus) == 0: - cnt = 0 - while cnt < len(self.UEDevices): - self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) - cnt += 1 - - def GetAllCatMDevices(self, terminate_ue_flag): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - SSH.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) - #self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) - self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) - else: - if (os.path.isfile('./modules_list.txt')): - os.remove('./modules_list.txt') - SSH.command('ls /etc/*/modules*.txt', '\$', 5) - result = re.search('/etc/ci/modules_list.txt', SSH.getBefore()) - SSH.close() - if result is not None: - logging.debug('Found a module list file on ADB server') - if terminate_ue_flag == True: - if len(self.CatMDevices) == 0: - logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') - sys.exit(1) - SSH.close() - - def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) - result = re.search('mServiceState=(?P[0-9]+)', SSH.getBefore()) - serviceState = 'Service State: UNKNOWN' - if result is not None: - lServiceState = int(result.group('serviceState')) - if lServiceState == 3: - serviceState = 'Service State: RADIO_POWERED_OFF' - if lServiceState == 1: - serviceState = 'Service State: OUT_OF_SERVICE' - if lServiceState == 0: - serviceState = 'Service State: IN_SERVICE' - if lServiceState == 2: - serviceState = 'Service State: EMERGENCY_ONLY' - result = re.search('mDataConnectionState=(?P[0-9]+)', SSH.getBefore()) - dataConnectionState = 'Data State: UNKNOWN' - if result is not None: - lDataConnectionState = int(result.group('dataConnectionState')) - if lDataConnectionState == 0: - dataConnectionState = 'Data State: DISCONNECTED' - if lDataConnectionState == 1: - dataConnectionState = 'Data State: CONNECTING' - if lDataConnectionState == 2: - dataConnectionState = 'Data State: CONNECTED' - if lDataConnectionState == 3: - dataConnectionState = 'Data State: SUSPENDED' - result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', SSH.getBefore()) - dataConnectionReason = 'Data Reason: UNKNOWN' - if result is not None: - dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') - lock.acquire() - logging.debug('\u001B[1;37;44m Status Check (' + str(device_id) + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + serviceState + '\u001B[0m') - logging.debug('\u001B[1;34m ' + dataConnectionState + '\u001B[0m') - logging.debug('\u001B[1;34m ' + dataConnectionReason + '\u001B[0m') - statusQueue.put(0) - statusQueue.put(device_id) - qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason - statusQueue.put(qMsg) - lock.release() - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckStatusUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - multi_jobs = [] - lock = Lock() - status_queue = SimpleQueue() - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.CheckUEStatus_common, args = (lock,device_id,status_queue,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd /opt/flexran_rtc', '\$', 5) - SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) - SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) - result = re.search('Nb Connected UE = (?P[0-9]+)', SSH.getBefore()) - passStatus = True - if result is not None: - nb_ues = int(result.group('nb_ues')) - htmlOptions = 'Nb Connected UE(s) to eNB = ' + str(nb_ues) - logging.debug('\u001B[1;37;44m ' + htmlOptions + ' \u001B[0m') - if self.expectedNbOfConnectedUEs > -1: - if nb_ues != self.expectedNbOfConnectedUEs: - passStatus = False - else: - htmlOptions = 'N/A' - SSH.close() - else: - passStatus = True - htmlOptions = 'N/A' - - if (status_queue.empty()): - HTML.CreateHtmlTestRow(htmlOptions, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - check_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - check_status = False - device_id = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\n' + message + '
' - html_queue.put(html_cell) - if check_status and passStatus: - HTML.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def GetAllUEIPAddresses(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - ue_ip_status = 0 - self.UEIPAddresses = [] - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('ifconfig oaitun_ue1', '\$', 4) - result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', SSH.getBefore()) - if result is not None: - if result.group('ueipaddress') is not None: - UE_IPAddress = result.group('ueipaddress') - else: - UE_IPAddress = result.group('ueipaddress2') - logging.debug('\u001B[1mUE (' + self.UEDevices[0] + ') IP Address is ' + UE_IPAddress + '\u001B[0m') - self.UEIPAddresses.append(UE_IPAddress) - else: - logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') - ue_ip_status -= 1 - SSH.close() - return ue_ip_status - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - idx = 0 - for device_id in self.UEDevices: - if self.UEDevicesStatus[idx] != CONST.UE_STATUS_ATTACHED: - idx += 1 - continue - count = 0 - while count < 4: - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) - result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') - time.sleep(1) - count += 1 - else: - count = 10 - if count < 9: - ue_ip_status -= 1 - continue - UE_IPAddress = result.group('ueipaddress') - logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m') - for ueipaddress in self.UEIPAddresses: - if ueipaddress == UE_IPAddress: - logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + ': has already been allocated to another device !' + '\u001B[0m') - ue_ip_status -= 1 - continue - self.UEIPAddresses.append(UE_IPAddress) - idx += 1 - SSH.close() - return ue_ip_status - - def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(message) - lock.release() - - def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue): - try: - # Launch ping on the EPC side (true for ltebox and old open-air-cn) - # But for OAI-Rel14-CUPS, we launch from python executor - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): - launchFromEpc = False - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - - if launchFromEpc: - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) - SSH.command('cd scripts', '\$', 5) - ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) - else: - cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' - message = cmd + '\n' - logging.debug(cmd) - ret = subprocess.run(cmd, shell=True) - ping_status = ret.returncode - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cat ' + EPC.SourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - lock.acquire() - logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - if (packetLossOK): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(qMsg) - lock.release() - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def PingNoS1_wrong_exit(self, qMsg): - html_queue = SimpleQueue() - html_cell = '
OAI UE ping result\n' + qMsg + '
' - html_queue.put(html_cell) - HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - - def PingNoS1(self): - check_eNB = True - check_OAI_UE = True - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) - if ping_from_eNB is not None: - if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - else: - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - try: - if ping_from_eNB is not None: - SSH.open(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword) - SSH.command('cd ' + RAN.eNBSourceCodePath + '/cmake_targets/', '\$', 5) - else: - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with OAI UE crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - SSH.close() - html_queue = SimpleQueue() - ip_addr = 'TBD' - html_cell = '
OAI UE ping result\n' + qMsg + '
' - html_queue.put(html_cell) - if packetLossOK: - HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - - # copying on the EPC server for logCollection - if ping_from_eNB is not None: - copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') - else: - copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') - if (copyin_res == 0): - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '.log', EPC.SourceCodePath + '/scripts') - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def Ping(self): - result = re.search('noS1', str(RAN.Initialize_eNB_args)) - if result is not None: - self.PingNoS1() - return - if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - check_OAI_UE = True - else: - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ueIpStatus = self.GetAllUEIPAddresses() - if (ueIpStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - i = 0 - lock = Lock() - status_queue = SimpleQueue() - for UE_IPAddress in self.UEIPAddresses: - device_id = self.UEDevices[i] - p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - ping_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - ping_status = False - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (ping_status): - HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def Iperf_ComputeTime(self): - result = re.search('-t (?P\d+)', str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m') - sys.exit(1) - return result.group('iperf_time') - - def Iperf_ComputeModifiedBW(self, idx, ue_num): - result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') - sys.exit(1) - iperf_bandwidth = result.group('iperf_bandwidth') - if self.iperf_profile == 'balanced': - iperf_bandwidth_new = float(iperf_bandwidth)/ue_num - if self.iperf_profile == 'single-ue': - iperf_bandwidth_new = float(iperf_bandwidth) - if self.iperf_profile == 'unbalanced': - # residual is 2% of max bw - residualBW = float(iperf_bandwidth) / 50 - if idx == 0: - iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW) - else: - iperf_bandwidth_new = residualBW - iperf_bandwidth_str = '-b ' + iperf_bandwidth - iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new) - result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') - sys.exit(1) - return result - - def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - SSH.command('awk -f /tmp/tcp_iperf_stats.awk ' + EPC.SourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', SSH.getBefore()) - if result is not None: - avgbitrate = result.group('average') - maxbitrate = result.group('maximum') - minbitrate = result.group('minimum') - lock.acquire() - logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m') - msg = 'TCP Stats :\n' - if avgbitrate is not None: - logging.debug('\u001B[1;34m Avg Bitrate : ' + avgbitrate + '\u001B[0m') - msg += 'Avg Bitrate : ' + avgbitrate + '\n' - if maxbitrate is not None: - logging.debug('\u001B[1;34m Max Bitrate : ' + maxbitrate + '\u001B[0m') - msg += 'Max Bitrate : ' + maxbitrate + '\n' - if minbitrate is not None: - logging.debug('\u001B[1;34m Min Bitrate : ' + minbitrate + '\u001B[0m') - msg += 'Min Bitrate : ' + minbitrate + '\n' - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 - - def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - result = re.search('-u', str(iperf_real_options)) - if result is None: - return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) - - result = re.search('Server Report:', SSH.getBefore()) - if result is None: - result = re.search('read failed: Connection refused', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') - else: - logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') - return -1 - # Computing the requested bandwidth in float - result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) - if result is not None: - req_bandwidth = result.group('iperf_bandwidth') - req_bw = float(req_bandwidth) - result = re.search('-b [0-9\.]+K', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Kbits/sec' % req_bw - req_bw = req_bw * 1000 - result = re.search('-b [0-9\.]+M', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Mbits/sec' % req_bw - req_bw = req_bw * 1000000 - result = re.search('-b [0-9\.]+G', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Gbits/sec' % req_bw - req_bw = req_bw * 1000000000 - - result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', SSH.getBefore()) - if result is not None: - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - jitter = result.group('jitter') - lock.acquire() - logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') - iperfStatus = True - msg = 'Req Bitrate : ' + req_bandwidth + '\n' - logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') - if bitrate is not None: - msg += 'Bitrate : ' + bitrate + '\n' - logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') - result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) - if result is not None: - actual_bw = float(str(result.group('real_bw'))) - result = re.search('[0-9\.]+ K', bitrate) - if result is not None: - actual_bw = actual_bw * 1000 - result = re.search('[0-9\.]+ M', bitrate) - if result is not None: - actual_bw = actual_bw * 1000000 - result = re.search('[0-9\.]+ G', bitrate) - if result is not None: - actual_bw = actual_bw * 1000000000 - br_loss = 100 * actual_bw / req_bw - bitperf = '%.2f ' % br_loss - msg += 'Bitrate Perf: ' + bitperf + '%\n' - logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') - if packetloss is not None: - msg += 'Packet Loss : ' + packetloss + '%\n' - logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') - if float(packetloss) > float(self.iperf_packetloss_threshold): - msg += 'Packet Loss too high!\n' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - iperfStatus = False - if jitter is not None: - msg += 'Jitter : ' + jitter + '\n' - logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 - else: - return -2 - - def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - return - # Computing the requested bandwidth in float - result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) - if result is None: - logging.debug('Iperf bandwidth Not Found!') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') - return - else: - req_bandwidth = result.group('iperf_bandwidth') - req_bw = float(req_bandwidth) - result = re.search('-b [0-9\.]+K', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Kbits/sec' % req_bw - req_bw = req_bw * 1000 - result = re.search('-b [0-9\.]+M', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Mbits/sec' % req_bw - req_bw = req_bw * 1000000 - result = re.search('-b [0-9\.]+G', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Gbits/sec' % req_bw - req_bw = req_bw * 1000000000 - - server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r') - br_sum = 0.0 - ji_sum = 0.0 - pl_sum = 0 - ps_sum = 0 - row_idx = 0 - for line in server_file.readlines(): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)/ +(?P[0-9]+)', str(line)) - if result is not None: - bitrate = result.group('bitrate') - jitter = result.group('jitter') - packetlost = result.group('lostPack') - packetsent = result.group('sentPack') - br = bitrate.split(' ') - ji = jitter.split(' ') - row_idx = row_idx + 1 - curr_br = float(br[0]) - pl_sum = pl_sum + int(packetlost) - ps_sum = ps_sum + int(packetsent) - if (br[1] == 'Kbits/sec'): - curr_br = curr_br * 1000 - if (br[1] == 'Mbits/sec'): - curr_br = curr_br * 1000 * 1000 - br_sum = curr_br + br_sum - ji_sum = float(ji[0]) + ji_sum - if (row_idx > 0): - br_sum = br_sum / row_idx - ji_sum = ji_sum / row_idx - br_loss = 100 * br_sum / req_bw - if (br_sum > 1000): - br_sum = br_sum / 1000 - if (br_sum > 1000): - br_sum = br_sum / 1000 - bitrate = '%.2f Mbits/sec' % br_sum - else: - bitrate = '%.2f Kbits/sec' % br_sum - else: - bitrate = '%.2f bits/sec' % br_sum - bitperf = '%.2f ' % br_loss - bitperf += '%' - jitter = '%.2f ms' % (ji_sum) - if (ps_sum > 0): - pl = float(100 * pl_sum / ps_sum) - packetloss = '%2.1f ' % (pl) - packetloss += '%' - else: - packetloss = 'unknown' - lock.acquire() - if (br_loss < 90): - statusQueue.put(1) - else: - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - req_msg = 'Req Bitrate : ' + req_bandwidth - bir_msg = 'Bitrate : ' + bitrate - brl_msg = 'Bitrate Perf: ' + bitperf - jit_msg = 'Jitter : ' + jitter - pal_msg = 'Packet Loss : ' + packetloss - statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n') - logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') - lock.release() - else: - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - - server_file.close() - - - def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', SSH.getBefore()) - if result is None: - result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', SSH.getBefore()) - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - if result is not None: - logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m') - statusQueue.put(result.group('error')) - else: - logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') - statusQueue.put('Bitrate and/or Packet Loss Not Found!') - lock.release() - - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - lock.acquire() - logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') - msg = 'Bitrate : ' + bitrate + '\n' - iperfStatus = True - if packetloss is not None: - logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') - msg += 'Packet Loss : ' + packetloss + '%\n' - if float(packetloss) > float(self.iperf_packetloss_threshold): - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - msg += 'Packet Loss too high!\n' - iperfStatus = False - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - - def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): - udpIperf = True - result = re.search('-u', str(self.iperf_args)) - if result is None: - udpIperf = False - ipnumbers = UE_IPAddress.split('.') - if (len(ipnumbers) == 4): - ipnumbers[3] = '1' - EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3] - - # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 - # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): - launchFromEpc = False - cmd = 'hostname -I' - ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') - if ret.stdout is not None: - EPC_Iperf_UE_IPAddress = ret.stdout.strip() - port = 5001 + idx - if launchFromEpc: - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) - SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if udpIperf: - SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) - else: - SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) - SSH.close() - else: - if self.ueIperfVersion == self.dummyIperfVersion: - prefix = '' - else: - prefix = '' - if self.ueIperfVersion == '2.0.5': - prefix = '/opt/iperf-2.0.5/bin/' - if udpIperf: - cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - else: - cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - logging.debug(cmd) - subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') - time.sleep(0.5) - - # Launch iperf client on UE - if (device_id == 'OAI-UE'): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - else: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.SourceCodePath+ '/scripts', '\$', 5) - iperf_time = self.Iperf_ComputeTime() - time.sleep(0.5) - - if udpIperf: - modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) - else: - modified_options = str(self.iperf_args) - modified_options = modified_options.replace('-R','') - time.sleep(0.5) - - SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if (device_id == 'OAI-UE'): - iperf_status = SSH.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - if self.ADBCentralized: - iperf_status = SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - iperf_status = SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - SSH.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - SSH.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # TIMEOUT Case - if iperf_status < 0: - SSH.close() - message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - SSH.close() - - # Kill iperf server on EPC side - if launchFromEpc: - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('killall --signal SIGKILL iperf', EPC.UserName, 5) - SSH.close() - else: - cmd = 'killall --signal SIGKILL iperf' - logging.debug(cmd) - subprocess.run(cmd, shell=True) - time.sleep(1) - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') - # in case of failure, retrieve server log - if (clientStatus == -1) or (clientStatus == -2): - if launchFromEpc: - time.sleep(1) - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath+ '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) - # in case of OAI-UE - if (device_id == 'OAI-UE'): - SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') - - def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): - try: - # Single-UE profile -- iperf only on one UE - if self.iperf_profile == 'single-ue' and idx != 0: - return - useIperf3 = False - udpIperf = True - - self.ueIperfVersion = '2.0.5' - if (device_id != 'OAI-UE'): - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - SSH.command('if [ ! -d ' + EPC.SourceCodePath + '/scripts ]; then mkdir -p ' + EPC.SourceCodePath + '/scripts ; fi', '\$', 5) - SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) - # Checking if iperf / iperf3 are installed - if self.ADBCentralized: - SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) - result = re.search('iperf3', SSH.getBefore()) - if result is None: - result = re.search('iperf', SSH.getBefore()) - if result is None: - message = 'Neither iperf nor iperf3 installed on UE!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - else: - if self.ADBCentralized: - SSH.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) - result = re.search('iperf version 2.0.5', SSH.getBefore()) - if result is not None: - self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', SSH.getBefore()) - if result is not None: - self.ueIperfVersion = '2.0.10' - else: - useIperf3 = True - SSH.close() - else: - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('iperf --version', '\$', 5) - result = re.search('iperf version 2.0.5', SSH.getBefore()) - if result is not None: - self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', SSH.getBefore()) - if result is not None: - self.ueIperfVersion = '2.0.10' - SSH.close() - # in case of iperf, UL has its own function - if (not useIperf3): - result = re.search('-R', str(self.iperf_args)) - if result is not None: - self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue) - return - - # Launch the IPERF server on the UE side for DL - if (device_id == 'OAI-UE'): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('-u', str(self.iperf_args)) - if result is None: - SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) - udpIperf = False - else: - SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) - else: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) - if self.ADBCentralized: - if (useIperf3): - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) - else: - SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('-u', str(self.iperf_args)) - if result is None: - SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) - udpIperf = False - else: - SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) - else: - SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - SSH.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) - - time.sleep(0.5) - SSH.close() - - # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn - # But for OAI-Rel14-CUPS, we launch from python executor - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): - launchFromEpc = False - if launchFromEpc: - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) - iperf_time = self.Iperf_ComputeTime() - time.sleep(0.5) - - if udpIperf: - modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) - else: - modified_options = str(self.iperf_args) - time.sleep(0.5) - - if launchFromEpc: - SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - else: - if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') - if (useIperf3): - SSH.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - - clientStatus = 0 - self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) - else: - if launchFromEpc: - iperf_status = SSH.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - if self.ueIperfVersion == self.dummyIperfVersion: - prefix = '' - else: - prefix = '' - if self.ueIperfVersion == '2.0.5': - prefix = '/opt/iperf-2.0.5/bin/' - cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' - message = cmd + '\n' - logging.debug(cmd) - ret = subprocess.run(cmd, shell=True) - iperf_status = ret.returncode - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cat ' + EPC.SourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if iperf_status < 0: - if launchFromEpc: - SSH.close() - message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - SSH.close() - - # Kill the IPERF server that runs in background - if (device_id == 'OAI-UE'): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('killall iperf', '\$', 5) - else: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) - result = re.search('shell +(?P\d+)', SSH.getBefore()) - if result is not None: - pid_iperf = result.group('pid') - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - SSH.close() - # if the client report is absent, try to analyze the server log file - if (clientStatus == -1): - time.sleep(1) - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - if (device_id == 'OAI-UE'): - SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - else: - SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.SourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - # fromdos has to be called on the python executor not on ADB server - cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' - subprocess.run(cmd, shell=True) - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) - - # in case of OAI UE: - if (device_id == 'OAI-UE'): - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - if not launchFromEpc: - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') - else: - SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def IperfNoS1(self): - if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = True - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - server_on_enb = re.search('-R', str(self.iperf_args)) - if server_on_enb is not None: - iServerIPAddr = RAN.eNBIPAddress - iServerUser = RAN.eNBUserName - iServerPasswd = RAN.eNBPassword - iClientIPAddr = self.UEIPAddress - iClientUser = self.UEUserName - iClientPasswd = self.UEPassword - else: - iServerIPAddr = self.UEIPAddress - iServerUser = self.UEUserName - iServerPasswd = self.UEPassword - iClientIPAddr = RAN.eNBIPAddress - iClientUser = RAN.eNBUserName - iClientPasswd = RAN.eNBPassword - if self.iperf_options != 'sink': - # Starting the iperf server - SSH.open(iServerIPAddr, iServerUser, iServerPasswd) - # args SHALL be "-c client -u any" - # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 - # -B 10.0.1.1 -u -s -i 1 -fm - server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) - server_options = server_options.replace('-c','-B') - SSH.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) - SSH.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) - time.sleep(0.5) - SSH.close() - - # Starting the iperf client - modified_options = self.Iperf_ComputeModifiedBW(0, 1) - modified_options = modified_options.replace('-R','') - iperf_time = self.Iperf_ComputeTime() - SSH.open(iClientIPAddr, iClientUser, iClientPasswd) - SSH.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) - iperf_status = SSH.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) - status_queue = SimpleQueue() - lock = Lock() - if iperf_status < 0: - message = 'iperf on OAI UE crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - clientStatus = -2 - else: - if self.iperf_options == 'sink': - clientStatus = 0 - status_queue.put(0) - status_queue.put('OAI-UE') - status_queue.put('10.0.1.2') - status_queue.put('Sink Test : no check') - else: - clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - SSH.close() - - # Stopping the iperf server - if self.iperf_options != 'sink': - SSH.open(iServerIPAddr, iServerUser, iServerPasswd) - SSH.command('killall --signal SIGKILL iperf', '\$', 5) - time.sleep(0.5) - SSH.close() - - if (clientStatus == -1): - if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '.log') - SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') - self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - - # copying on the EPC server for logCollection - if (clientStatus == -1): - copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') - if (copyin_res == 0): - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.SourceCodePath + '/scripts') - copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') - if (copyin_res == 0): - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.SourceCodePath + '/scripts') - iperf_noperf = False - if status_queue.empty(): - iperf_status = False - else: - iperf_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (iperf_noperf and iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) - elif (iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def Iperf(self): - result = re.search('noS1', str(RAN.Initialize_eNB_args)) - if result is not None: - self.IperfNoS1() - return - if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - check_OAI_UE = True - else: - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ueIpStatus = self.GetAllUEIPAddresses() - if (ueIpStatus < 0): - logging.debug('going here') - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB() - return - - self.dummyIperfVersion = '2.0.10' - #cmd = 'iperf --version' - #logging.debug(cmd + '\n') - #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) - #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.5' - #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.10' - - multi_jobs = [] - i = 0 - ue_num = len(self.UEIPAddresses) - lock = Lock() - status_queue = SimpleQueue() - for UE_IPAddress in self.UEIPAddresses: - device_id = self.UEDevices[i] - p = Process(target = self.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - iperf_status = True - iperf_noperf = False - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (iperf_noperf and iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) - elif (iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def CheckProcessExist(self, check_eNB, check_OAI_UE): - multi_jobs = [] - status_queue = SimpleQueue() - # in noS1 config, no need to check status from EPC - # in gNB also currently no need to check - result = re.search('noS1|band78', str(RAN.Initialize_eNB_args)) - if result is None: - p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - p = Process(target = EPC.CheckMMEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - p = Process(target = EPC.CheckSPGWProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - else: - if (check_eNB == False) and (check_OAI_UE == False): - return 0 - if check_eNB: - p = Process(target = RAN.CheckeNBProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - if check_OAI_UE: - p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - return -15 - else: - result = 0 - while (not status_queue.empty()): - status = status_queue.get() - if (status < 0): - result = status - if result == CONST.ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(RAN.eNBLogFiles[0])) - if fileCheck is not None: - SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/' + RAN.eNBLogFiles[0], '.') - logStatus = RAN.AnalyzeLogFile_eNB(RAN.eNBLogFiles[0]) - if logStatus < 0: - result = logStatus - RAN.eNBLogFiles[0]='' - if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: - self.TerminateFlexranCtrl() - return result - - def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag): - multi_jobs = [] - status_queue = SimpleQueue() - if initialize_OAI_UE_flag == False: - p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - return -15 - else: - result = 0 - while (not status_queue.empty()): - status = status_queue.get() - if (status < 0): - result = status - if result == CONST.OAI_UE_PROCESS_FAILED: - fileCheck = re.search('ue_', str(self.UELogFile)) - if fileCheck is not None: - SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') - logStatus = self.AnalyzeLogFile_UE(self.UELogFile) - if logStatus < 0: - result = logStatus - return result - - def CheckOAIUEProcess(self, status_queue): - try: - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + ' | grep -v grep', '\$', 5) - result = re.search(self.air_interface, SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') - status_queue.put(CONST.OAI_UE_PROCESS_FAILED) - else: - status_queue.put(CONST.OAI_UE_PROCESS_OK) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - - def AnalyzeLogFile_UE(self, UElogFile): - if (not os.path.isfile('./' + UElogFile)): - return -1 - ue_log_file = open('./' + UElogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - uciStatMsgCount = 0 - pdcpDataReqFailedCount = 0 - badDciCount = 0 - f1aRetransmissionCount = 0 - fatalErrorCount = 0 - macBsrTimerExpiredCount = 0 - rrcConnectionRecfgComplete = 0 - no_cell_sync_found = False - mib_found = False - frequency_found = False - plmn_found = False - nrUEFlag = False - nrDecodeMib = 0 - nrFoundDCI = 0 - nrCRCOK = 0 - mbms_messages = 0 - HTML.htmlUEFailureMsg='' - global_status = CONST.ALL_PROCESSES_OK - for line in ue_log_file.readlines(): - result = re.search('nr_synchro_time', str(line)) - if result is not None: - nrUEFlag = True - if nrUEFlag: - result = re.search('decode mib', str(line)) - if result is not None: - nrDecodeMib += 1 - result = re.search('found 1 DCIs', str(line)) - if result is not None: - nrFoundDCI += 1 - result = re.search('CRC OK', str(line)) - if result is not None: - nrCRCOK += 1 - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line)) - if result is not None and not exitSignalReceived: - foundSegFault = True - result = re.search('[Cc]ore [dD]ump', str(line)) - if result is not None and not exitSignalReceived: - foundSegFault = True - result = re.search('./lte-uesoftmodem', str(line)) - if result is not None and not exitSignalReceived: - foundSegFault = True - result = re.search('[Aa]ssertion', str(line)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('uci->stat', str(line)) - if result is not None and not exitSignalReceived: - uciStatMsgCount += 1 - result = re.search('PDCP data request failed', str(line)) - if result is not None and not exitSignalReceived: - pdcpDataReqFailedCount += 1 - result = re.search('bad DCI 1', str(line)) - if result is not None and not exitSignalReceived: - badDciCount += 1 - result = re.search('Format1A Retransmission but TBS are different', str(line)) - if result is not None and not exitSignalReceived: - f1aRetransmissionCount += 1 - result = re.search('FATAL ERROR', str(line)) - if result is not None and not exitSignalReceived: - fatalErrorCount += 1 - result = re.search('MAC BSR Triggered ReTxBSR Timer expiry', str(line)) - if result is not None and not exitSignalReceived: - macBsrTimerExpiredCount += 1 - result = re.search('Generating RRCConnectionReconfigurationComplete', str(line)) - if result is not None: - rrcConnectionRecfgComplete += 1 - # No cell synchronization found, abandoning - result = re.search('No cell synchronization found, abandoning', str(line)) - if result is not None: - no_cell_sync_found = True - if RAN.eNBmbmsEnables[0]: - result = re.search('TRIED TO PUSH MBMS DATA', str(line)) - if result is not None: - mbms_messages += 1 - result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P\d{1,3}), N_RB_DL (?P\d{1,3}), PHICH DURATION (?P\d), PHICH RESOURCE (?P.{1,4}), TX_ANT (?P\d)", str(line)) - if result is not None and (not mib_found): - try: - mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " nidcell = " + result.group('nidcell') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " n_rb_dl = " + result.group('n_rb_dl') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " phich_duration = " + result.group('phich_duration') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " phich_resource = " + result.group('phich_resource') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " tx_ant = " + result.group('tx_ant') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mib_found = True - except Exception as e: - logging.error('\033[91m' + "MIB marker was not found" + '\033[0m') - result = re.search("Measured Carrier Frequency (?P\d{1,15}) Hz", str(line)) - if result is not None and (not frequency_found): - try: - mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - frequency_found = True - except Exception as e: - logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m') - result = re.search("PLMN MCC (?P\d{1,3}), MNC (?P\d{1,3}), TAC", str(line)) - if result is not None and (not plmn_found): - try: - mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - plmn_found = True - except Exception as e: - logging.error('\033[91m' + "PLMN not found" + '\033[0m') - result = re.search("Found (?P[\w,\s]{1,15}) \(name from internal table\)", str(line)) - if result is not None: - try: - mibMsg = "The operator is: " + result.group('operator') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - except Exception as e: - logging.error('\033[91m' + "Operator name not found" + '\033[0m') - result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line)) - if result is not None: - try: - mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + ' -> ' - logging.debug('\033[94m' + mibMsg + '\033[0m') - except Exception as e: - logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') - result = re.search("DL Carrier Frequency/ARFCN : \-*(?P\d{1,15}/\d{1,4})", str(line)) - if result is not None: - try: - freq = result.group('carrier_frequency') - new_freq = re.sub('/[0-9]+','',freq) - float_freq = float(new_freq) / 1000000 - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' - logging.debug('\033[94m' + " DL Carrier Frequency is: " + str(freq) + '\033[0m') - except Exception as e: - logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') - result = re.search("AllowedMeasBandwidth : (?P\d{1,7})", str(line)) - if result is not None: - try: - prb = result.group('allowed_bandwidth') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + ' -- PRB: ' + prb + '\n' - logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') - except Exception as e: - logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') - ue_log_file.close() - if rrcConnectionRecfgComplete > 0: - statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' - logging.debug('\033[94m' + statMsg + '\033[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if nrUEFlag: - if nrDecodeMib > 0: - statMsg = 'UE showed ' + str(nrDecodeMib) + ' MIB decode message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if nrFoundDCI > 0: - statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if nrCRCOK > 0: - statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if not frequency_found: - statMsg = 'NR-UE could NOT synch!' - logging.error('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if uciStatMsgCount > 0: - statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if pdcpDataReqFailedCount > 0: - statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if badDciCount > 0: - statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1(A)" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if f1aRetransmissionCount > 0: - statMsg = 'UE showed ' + str(f1aRetransmissionCount) + ' "Format1A Retransmission but TBS are different" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if fatalErrorCount > 0: - statMsg = 'UE showed ' + str(fatalErrorCount) + ' "FATAL ERROR:" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if macBsrTimerExpiredCount > 0: - statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if RAN.eNBmbmsEnables[0]: - if mbms_messages > 0: - statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - else: - statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)' - logging.debug('\u001B[1;30;41m ' + statMsg + ' \u001B[0m') - global_status = CONST.OAI_UE_PROCESS_NO_MBMS_MSGS - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' - if foundSegFault: - logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') - if not nrUEFlag: - global_status = CONST.OAI_UE_PROCESS_SEG_FAULT - else: - if not frequency_found: - global_status = CONST.OAI_UE_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE showed an assertion!\n' - if not nrUEFlag: - if not mib_found or not frequency_found: - global_status = CONST.OAI_UE_PROCESS_ASSERTION - else: - if not frequency_found: - global_status = CONST.OAI_UE_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE faced real time issues!\n' - if nrUEFlag: - if not frequency_found: - global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC - else: - if no_cell_sync_found and not mib_found: - logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') - HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE could not synchronize!\n' - global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC - return global_status - - - def TerminateFlexranCtrl(self): - if RAN.flexranCtrlInstalled == False or RAN.flexranCtrlStarted == False: - return - if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('echo ' + EPC.Password + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) - time.sleep(1) - SSH.command('echo ' + EPC.Password + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) - time.sleep(1) - SSH.close() - RAN.flexranCtrlStarted=False - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def TerminateUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # back in airplane mode on (ie radio off) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) - result = re.search('shell +(?P\d+)', SSH.getBefore()) - if result is not None: - pid_iperf = result.group('pid') - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def TerminateUE(self): - terminate_ue_flag = False - self.GetAllUEDevices(terminate_ue_flag) - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target= self.TerminateUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def TerminateOAIUE(self): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT -r .*-uesoftmodem || true', '\$', 5) - time.sleep(10) - SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL -r .*-uesoftmodem || true', '\$', 5) - time.sleep(5) - SSH.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - SSH.close() - result = re.search('ue_', str(self.UELogFile)) - if result is not None: - copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') - if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') - HTML.htmlUEFailureMsg='Could not copy UE logfile to analyze it!' - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') - self.UELogFile = '' - return - logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_UE(self.UELogFile) - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is not None: - ueAction = 'Sniffing' - else: - ueAction = 'Connection' - if (logStatus < 0): - logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') - HTML.htmlUEFailureMsg='' + ueAction + ' Failed\n' + HTML.htmlUEFailureMsg - HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') - if self.air_interface == 'lte-uesoftmodem': - # In case of sniffing on commercial eNBs we have random results - # Not an error then - if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): - self.Initialize_OAI_UE_args = '' - self.AutoTerminateUEandeNB() - else: - if (logStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): - self.Initialize_OAI_UE_args = '' - self.AutoTerminateUEandeNB() - else: - logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') - HTML.htmlUEFailureMsg='' + ueAction + ' Completed\n' + HTML.htmlUEFailureMsg - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - self.UELogFile = '' - else: - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def AutoTerminateUEandeNB(self): - if (self.ADBIPAddress != 'none'): - self.testCase_id = 'AUTO-KILL-UE' - HTML.testCase_id=self.testCase_id - self.desc = 'Automatic Termination of UE' - HTML.desc='Automatic Termination of UE' - self.ShowTestID() - self.TerminateUE() - if (self.Initialize_OAI_UE_args != ''): - self.testCase_id = 'AUTO-KILL-OAI-UE' - HTML.testCase_id=self.testCase_id - self.desc = 'Automatic Termination of OAI-UE' - HTML.desc='Automatic Termination of OAI-UE' - self.ShowTestID() - self.TerminateOAIUE() - if (RAN.Initialize_eNB_args != ''): - self.testCase_id = 'AUTO-KILL-eNB' - HTML.testCase_id=self.testCase_id - self.desc = 'Automatic Termination of eNB' - HTML.desc='Automatic Termination of eNB' - self.ShowTestID() - RAN.eNB_instance=0 - RAN.TerminateeNB() - if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: - self.testCase_id = 'AUTO-KILL-flexran-ctl' - HTML.testCase_id=self.testCase_id - self.desc = 'Automatic Termination of FlexRan CTL' - HTML.desc='Automatic Termination of FlexRan CTL' - self.ShowTestID() - self.TerminateFlexranCtrl() - RAN.prematureExit=True - - def IdleSleep(self): - time.sleep(self.idle_sleep_time) - HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK) - - def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + EPC.IPAddress + ":9999/stats | jq '.' > " + fileName - message = cmd + '\n' - logging.debug(cmd) - subprocess.run(cmd, shell=True) - if idx == 0: - cmd = "jq '.mac_stats | length' " + fileName - strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2NbENBs = int(strNbEnbs.strip()) - cnt = 0 - while cnt < self.x2NbENBs: - cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName - bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBBsIds[idx].append(bs_id.strip()) - cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName - stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) - nbUEs = int(stNbUEs.strip()) - ueIdx = 0 - self.x2ENBConnectedUEs[idx].append([]) - while ueIdx < nbUEs: - cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName - rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip()) - ueIdx += 1 - cnt += 1 - - msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" - logging.debug(msg) - message += msg + '\n' - cnt = 0 - while cnt < self.x2NbENBs: - msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][cnt])) + " UE(s)" - logging.debug(msg) - message += msg + '\n' - ueIdx = 0 - while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]): - msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx]) - logging.debug(msg) - message += msg + '\n' - ueIdx += 1 - cnt += 1 - return message - - def Perform_X2_Handover(self): - html_queue = SimpleQueue() - fullMessage = '
'
-		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
-		logging.debug(msg)
-		fullMessage += msg + '\n'
-		if self.x2_ho_options == 'network':
-			if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted:
-				self.x2ENBBsIds = []
-				self.x2ENBConnectedUEs = []
-				self.x2ENBBsIds.append([])
-				self.x2ENBBsIds.append([])
-				self.x2ENBConnectedUEs.append([])
-				self.x2ENBConnectedUEs.append([])
-				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
-
-				msg = "Activating the X2 Net control on each eNB"
-				logging.debug(msg)
-				fullMessage += msg + '\n'
-				eNB_cnt = self.x2NbENBs
-				cnt = 0
-				while cnt < eNB_cnt:
-					cmd = "curl -XPOST http://" + EPC.IPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1"
-					logging.debug(cmd)
-					fullMessage += cmd + '\n'
-					subprocess.run(cmd, shell=True)
-					cnt += 1
-				# Waiting for the activation to be active
-				time.sleep(10)
-				msg = "Switching UE(s) from eNB to eNB"
-				logging.debug(msg)
-				fullMessage += msg + '\n'
-				cnt = 0
-				while cnt < eNB_cnt:
-					ueIdx = 0
-					while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]):
-						cmd = "curl -XPOST http://" + EPC.IPAddress() + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
-						logging.debug(cmd)
-						fullMessage += cmd + '\n'
-						subprocess.run(cmd, shell=True)
-						ueIdx += 1
-					cnt += 1
-				time.sleep(10)
-				# check
-				logging.debug("Checking the Status after X2 Handover")
-				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
-				cnt = 0
-				x2Status = True
-				while cnt < eNB_cnt:
-					if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
-						x2Status = False
-					cnt += 1
-				if x2Status:
-					msg = "X2 Handover was successful"
-					logging.debug(msg)
-					fullMessage += msg + '
' - html_queue.put(fullMessage) - HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - else: - msg = "X2 Handover FAILED" - logging.error(msg) - fullMessage += msg + '' - html_queue.put(fullMessage) - HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK) - - def LogCollectBuild(self): - if (RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != ''): - IPAddress = RAN.eNBIPAddress - UserName = RAN.eNBUserName - Password = RAN.eNBPassword - SourceCodePath = RAN.eNBSourceCodePath - elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): - IPAddress = self.UEIPAddress - UserName = self.UEUserName - Password = self.UEPassword - SourceCodePath = self.UESourceCodePath - else: - sys.exit('Insufficient Parameter') - SSH.open(IPAddress, UserName, Password) - SSH.command('cd ' + SourceCodePath, '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('rm -f build.log.zip', '\$', 5) - SSH.command('zip build.log.zip build_log_*/*', '\$', 60) - SSH.close() - def LogCollectPing(self): - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) - SSH.command('cd scripts', '\$', 5) - SSH.command('rm -f ping.log.zip', '\$', 5) - SSH.command('zip ping.log.zip ping*.log', '\$', 60) - SSH.command('rm ping*.log', '\$', 5) - SSH.close() - - def LogCollectIperf(self): - SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) - SSH.command('cd scripts', '\$', 5) - SSH.command('rm -f iperf.log.zip', '\$', 5) - SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) - SSH.command('rm iperf*.log', '\$', 5) - SSH.close() - - def LogCollectOAIUE(self): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath, '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) - SSH.close() - - def RetrieveSystemVersion(self, machine): - if RAN.eNBIPAddress == 'none' or self.UEIPAddress == 'none': - HTML.OsVersion[0]='Ubuntu 16.04.5 LTS' - HTML.KernelVersion[0]='4.15.0-45-generic' - HTML.UhdVersion[0]='3.13.0.1-0' - HTML.UsrpBoard[0]='B210' - HTML.CpuNb[0]='4' - HTML.CpuModel[0]='Intel(R) Core(TM) i5-6200U' - HTML.CpuMHz[0]='2399.996 MHz' - return 0 - if machine == 'eNB': - if RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != '': - IPAddress = RAN.eNBIPAddress - UserName = RAN.eNBUserName - Password = RAN.eNBPassword - idx = 0 - else: - return -1 - if machine == 'UE': - if self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '': - IPAddress = self.UEIPAddress - UserName = self.UEUserName - Password = self.UEPassword - idx = 1 - else: - return -1 - - SSH.open(IPAddress, UserName, Password) - SSH.command('lsb_release -a', '\$', 5) - result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) - if result is not None: - OsVersion = result.group('os_type') - logging.debug('OS is: ' + OsVersion) - HTML.OsVersion[idx]=OsVersion - else: - SSH.command('hostnamectl', '\$', 5) - result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) - if result is not None: - OsVersion = result.group('os_type') - if OsVersion == 'CentOS Linux 7 ': - SSH.command('cat /etc/redhat-release', '\$', 5) - result = re.search('CentOS Linux release (?P[0-9\.]+)', SSH.getBefore()) - if result is not None: - OsVersion = OsVersion.replace('7 ', result.group('os_version')) - logging.debug('OS is: ' + OsVersion) - HTML.OsVersion[idx]=OsVersion - SSH.command('uname -r', '\$', 5) - result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) - if result is not None: - KernelVersion = result.group('kernel_version') - logging.debug('Kernel Version is: ' + KernelVersion) - HTML.KernelVersion[idx]=KernelVersion - SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) - result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) - if result is not None: - UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + UhdVersion) - HTML.UhdVersion[idx]=UhdVersion - else: - SSH.command('uhd_config_info --version', '\$', 5) - result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', SSH.getBefore()) - if result is not None: - UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + UhdVersion) - HTML.UhdVersion[idx]=UhdVersion - SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 60) - usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', SSH.getBefore()) - count = 0 - for board in usrp_boards: - if count == 0: - UsrpBoard = board - else: - UsrpBoard += ',' + board - count += 1 - if count > 0: - logging.debug('USRP Board(s) : ' + UsrpBoard) - HTML.UsrpBoard[idx]=UsrpBoard - SSH.command('lscpu', '\$', 5) - result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', SSH.getBefore()) - if result is not None: - CpuNb = result.group('nb_cpus') - logging.debug('nb_cpus: ' + CpuNb) - HTML.CpuNb[idx]=CpuNb - CpuModel = result.group('model') - logging.debug('model: ' + CpuModel) - HTML.CpuModel[idx]=CpuModel - CpuMHz = result.group('cpu_mhz') + ' MHz' - logging.debug('cpu_mhz: ' + CpuMHz) - HTML.CpuMHz[idx]=CpuMHz - SSH.close() - - def ShowTestID(self): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') - logging.debug('\u001B[1m' + self.desc + '\u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - - #----------------------------------------------------------- # General Functions @@ -3106,24 +102,34 @@ def AssignParams(params_dict): def GetParametersFromXML(action): - if action == 'Build_eNB': + if action == 'Build_eNB' or action == 'Build_Image': RAN.Build_eNB_args=test.findtext('Build_eNB_args') + CONTAINERS.imageKind=test.findtext('kind') forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): RAN.Build_eNB_forced_workspace_cleanup=False + CONTAINERS.forcedWorkspaceCleanup=False else: if re.match('true', forced_workspace_cleanup, re.IGNORECASE): RAN.Build_eNB_forced_workspace_cleanup=True + CONTAINERS.forcedWorkspaceCleanup=True else: - RAN.Build_eNB_forced_workspace_cleanup=False + RAN.Build_eNB_forced_workspace_cleanup=True + CONTAINERS.forcedWorkspaceCleanup=False eNB_instance=test.findtext('eNB_instance') if (eNB_instance is None): RAN.eNB_instance=0 + CONTAINERS.eNB_instance=0 else: RAN.eNB_instance=int(eNB_instance) - RAN.eNB_serverId=test.findtext('eNB_serverId') - if (RAN.eNB_serverId is None): - RAN.eNB_serverId='0' + CONTAINERS.eNB_instance=int(eNB_instance) + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + RAN.eNB_serverId[RAN.eNB_instance]='0' + CONTAINERS.eNB_serverId[RAN.eNB_instance]='0' + else: + RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId + CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId xmlBgBuildField = test.findtext('backgroundBuild') if (xmlBgBuildField is None): RAN.backgroundBuild=False @@ -3133,27 +139,38 @@ def GetParametersFromXML(action): else: RAN.backgroundBuild=False - if action == 'WaitEndBuild_eNB': + elif action == 'WaitEndBuild_eNB': RAN.Build_eNB_args=test.findtext('Build_eNB_args') eNB_instance=test.findtext('eNB_instance') if (eNB_instance is None): RAN.eNB_instance=0 else: RAN.eNB_instance=int(eNB_instance) - RAN.eNB_serverId=test.findtext('eNB_serverId') - if (RAN.eNB_serverId is None): - RAN.eNB_serverId='0' + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + RAN.eNB_serverId[RAN.eNB_instance]='0' + else: + RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId - if action == 'Initialize_eNB': + elif action == 'Initialize_eNB': + RAN.eNB_Trace=test.findtext('eNB_Trace') + RAN.eNB_Stats=test.findtext('eNB_Stats') RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args') eNB_instance=test.findtext('eNB_instance') + USRPIPAddress=test.findtext('USRP_IPAddress') + if USRPIPAddress is None: + RAN.USRPIPAddress='' + else: + RAN.USRPIPAddress=USRPIPAddress if (eNB_instance is None): RAN.eNB_instance=0 else: RAN.eNB_instance=int(eNB_instance) - RAN.eNB_serverId=test.findtext('eNB_serverId') - if (RAN.eNB_serverId is None): - RAN.eNB_serverId='0' + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + RAN.eNB_serverId[RAN.eNB_instance]='0' + else: + RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId #local variable air_interface air_interface = test.findtext('air_interface') @@ -3164,16 +181,18 @@ def GetParametersFromXML(action): else : RAN.air_interface[RAN.eNB_instance] = 'ocp-enb' - if action == 'Terminate_eNB': + elif action == 'Terminate_eNB': eNB_instance=test.findtext('eNB_instance') if (eNB_instance is None): RAN.eNB_instance=0 else: RAN.eNB_instance=int(eNB_instance) - RAN.eNB_serverId=test.findtext('eNB_serverId') - if (RAN.eNB_serverId is None): - RAN.eNB_serverId='0' - + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + RAN.eNB_serverId[RAN.eNB_instance]='0' + else: + RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId + #local variable air_interface air_interface = test.findtext('air_interface') if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): @@ -3183,21 +202,49 @@ def GetParametersFromXML(action): else : RAN.air_interface[RAN.eNB_instance] = 'ocp-enb' - if action == 'Attach_UE': + elif action == 'Initialize_UE': + ue_id = test.findtext('id') + CiTestObj.ue_trace=test.findtext('UE_Trace')#temporary variable, to be passed to Module_UE in Initialize_UE call + if (ue_id is None): + CiTestObj.ue_id = "" + else: + CiTestObj.ue_id = ue_id + + elif action == 'Detach_UE': + ue_id = test.findtext('id') + if (ue_id is None): + CiTestObj.ue_id = "" + else: + CiTestObj.ue_id = ue_id + + elif action == 'Attach_UE': + ue_id = test.findtext('id') + if (ue_id is None): + CiTestObj.ue_id = "" + else: + CiTestObj.ue_id = ue_id nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') if (nbMaxUEtoAttach is None): CiTestObj.nbMaxUEtoAttach = -1 else: CiTestObj.nbMaxUEtoAttach = int(nbMaxUEtoAttach) - if action == 'CheckStatusUE': + elif action == 'Terminate_UE': + ue_id = test.findtext('id') + if (ue_id is None): + CiTestObj.ue_id = "" + else: + CiTestObj.ue_id = ue_id + + + elif action == 'CheckStatusUE': expectedNBUE = test.findtext('expectedNbOfConnectedUEs') if (expectedNBUE is None): CiTestObj.expectedNbOfConnectedUEs = -1 else: CiTestObj.expectedNbOfConnectedUEs = int(expectedNBUE) - if action == 'Build_OAI_UE': + elif action == 'Build_OAI_UE': CiTestObj.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') CiTestObj.clean_repository = test.findtext('clean_repository') if (CiTestObj.clean_repository == 'false'): @@ -3205,7 +252,7 @@ def GetParametersFromXML(action): else: CiTestObj.clean_repository = True - if action == 'Initialize_OAI_UE': + elif action == 'Initialize_OAI_UE': CiTestObj.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') UE_instance = test.findtext('UE_instance') if (UE_instance is None): @@ -3223,7 +270,7 @@ def GetParametersFromXML(action): #CiTestObj.air_interface = 'ocp-enb' logging.error('OCP UE -- NOT SUPPORTED') - if action == 'Terminate_OAI_UE': + elif action == 'Terminate_OAI_UE': UE_instance=test.findtext('UE_instance') if (UE_instance is None): CiTestObj.UE_instance = '0' @@ -3240,12 +287,28 @@ def GetParametersFromXML(action): #CiTestObj.air_interface = 'ocp-enb' logging.error('OCP UE -- NOT SUPPORTED') - if action == 'Ping' or action == 'Ping_CatM_module': + elif (action == 'Ping') or (action == 'Ping_CatM_module'): CiTestObj.ping_args = test.findtext('ping_args') CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') + ue_id = test.findtext('id') + if (ue_id is None): + CiTestObj.ue_id = "" + else: + CiTestObj.ue_id = ue_id + ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') + if (ping_rttavg_threshold is None): + CiTestObj.ping_rttavg_threshold = "" + else: + CiTestObj.ping_rttavg_threshold = ping_rttavg_threshold - if action == 'Iperf': + elif action == 'Iperf': CiTestObj.iperf_args = test.findtext('iperf_args') + ue_id = test.findtext('id') + if (ue_id is None): + CiTestObj.ue_id = "" + else: + CiTestObj.ue_id = ue_id + CiTestObj.iperf_direction = test.findtext('direction')#used for modules only CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') CiTestObj.iperf_profile = test.findtext('iperf_profile') if (CiTestObj.iperf_profile is None): @@ -3262,14 +325,14 @@ def GetParametersFromXML(action): logging.debug('ERROR: test-case has wrong option ' + CiTestObj.iperf_options) CiTestObj.iperf_options = 'check' - if action == 'IdleSleep': + elif action == 'IdleSleep': string_field = test.findtext('idle_sleep_time_in_sec') if (string_field is None): CiTestObj.idle_sleep_time = 5 else: CiTestObj.idle_sleep_time = int(string_field) - if action == 'Perform_X2_Handover': + elif action == 'Perform_X2_Handover': string_field = test.findtext('x2_ho_options') if (string_field is None): CiTestObj.x2_ho_options = 'network' @@ -3280,7 +343,7 @@ def GetParametersFromXML(action): else: CiTestObj.x2_ho_options = string_field - if action == 'Build_PhySim': + elif action == 'Build_PhySim': ldpc.buildargs = test.findtext('physim_build_args') forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): @@ -3291,11 +354,81 @@ def GetParametersFromXML(action): else: ldpc.forced_workspace_cleanup=False - if action == 'Run_PhySim': + elif action == 'Initialize_MME': + string_field = test.findtext('option') + if (string_field is not None): + EPC.mmeConfFile = string_field + + elif action == 'Deploy_EPC': + string_field = test.findtext('parameters') + if (string_field is not None): + EPC.yamlPath = string_field + + elif action == 'Deploy_Object' or action == 'Undeploy_Object': + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + CONTAINERS.eNB_instance=0 + else: + CONTAINERS.eNB_instance=int(eNB_instance) + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]='0' + else: + CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId + string_field = test.findtext('yaml_path') + if (string_field is not None): + CONTAINERS.yamlPath[CONTAINERS.eNB_instance] = string_field + + elif action == 'DeployGenObject' or action == 'UndeployGenObject': + string_field=test.findtext('yaml_path') + if (string_field is not None): + CONTAINERS.yamlPath[0] = string_field + string_field=test.findtext('services') + if (string_field is not None): + CONTAINERS.services[0] = string_field + string_field=test.findtext('nb_healthy') + if (string_field is not None): + CONTAINERS.nb_healthy[0] = int(string_field) + + elif action == 'PingFromContainer': + string_field = test.findtext('container_name') + if (string_field is not None): + CONTAINERS.pingContName = string_field + string_field = test.findtext('options') + if (string_field is not None): + CONTAINERS.pingOptions = string_field + string_field = test.findtext('loss_threshold') + if (string_field is not None): + CONTAINERS.pingLossThreshold = string_field + + elif action == 'IperfFromContainer': + string_field = test.findtext('server_container_name') + if (string_field is not None): + CONTAINERS.svrContName = string_field + string_field = test.findtext('server_options') + if (string_field is not None): + CONTAINERS.svrOptions = string_field + string_field = test.findtext('client_container_name') + if (string_field is not None): + CONTAINERS.cliContName = string_field + string_field = test.findtext('client_options') + if (string_field is not None): + CONTAINERS.cliOptions = string_field + + elif action == 'Copy_Image_to_Test': + string_field = test.findtext('image_name') + if (string_field is not None): + CONTAINERS.imageToCopy = string_field + string_field = test.findtext('registry_svr_id') + if (string_field is not None): + CONTAINERS.registrySvrId = string_field + string_field = test.findtext('test_svr_id') + if (string_field is not None): + CONTAINERS.testSvrId = string_field + + else: # ie action == 'Run_PhySim': ldpc.runargs = test.findtext('physim_run_args') - if action == 'COTS_UE_Airplane': - COTS_UE.runargs = test.findtext('cots_ue_airplane_args') #check if given test is in list #it is in list if one of the strings in 'list' is at the beginning of 'test' @@ -3320,67 +453,78 @@ def receive_signal(signum, frame): #loading xml action list from yaml import yaml -xml_class_list_file='' -if (os.path.isfile('xml_class_list.yml')): - xml_class_list_file='xml_class_list.yml' -if (os.path.isfile('ci-scripts/xml_class_list.yml')): - xml_class_list_file='ci-scripts/xml_class_list.yml' -with open(xml_class_list_file,'r') as file: - # The FullLoader parameter handles the conversion from YAML - # scalar values to Python the dictionary format - xml_class_list = yaml.load(file,Loader=yaml.FullLoader) +xml_class_list_file='xml_class_list.yml' +if (os.path.isfile(xml_class_list_file)): + yaml_file=xml_class_list_file +elif (os.path.isfile('ci-scripts/'+xml_class_list_file)): + yaml_file='ci-scripts/'+xml_class_list_file +else: + logging.error("XML action list yaml file cannot be found") + sys.exit("XML action list yaml file cannot be found") + +with open(yaml_file,'r') as f: + # The FullLoader parameter handles the conversion-$ + #from YAML scalar values to Python dictionary format$ + xml_class_list = yaml.load(f,Loader=yaml.FullLoader) + + + +#loading UE infrastructure from yaml +ue_infra_file='ci_ueinfra.yaml' +if (os.path.isfile(ue_infra_file)): + yaml_file=ue_infra_file +elif (os.path.isfile('ci-scripts/'+ue_infra_file)): + yaml_file='ci-scripts/'+ue_infra_file +else: + logging.error("UE infrastructure yaml file cannot be found") + sys.exit("UE infrastructure file cannot be found") +InfraUE=cls_ci_ueinfra.InfraUE() #initialize UE infrastructure class +InfraUE.Get_UE_Infra(yaml_file) #read the UE infra, filename is hardcoded and unique for the moment but should be passed as parameter from the test suite + + mode = '' -CiTestObj = OaiCiTest() +CiTestObj = cls_oaicitest.OaiCiTest() SSH = sshconnection.SSHConnection() EPC = epc.EPCManagement() RAN = ran.RANManagement() HTML = html.HTMLManagement() - -EPC.htmlObj=HTML -RAN.htmlObj=HTML -RAN.epcObj=EPC - +CONTAINERS = cls_containerize.Containerize() +SCA = cls_static_code_analysis.StaticCodeAnalysis() +PHYSIM = cls_physim1.PhySim() ldpc=cls_physim.PhySim() #create an instance for LDPC test using GPU or CPU build - #----------------------------------------------------------- # Parsing Command Line Arguments #----------------------------------------------------------- import args_parse -py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,HELP) +py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP,SCA,PHYSIM) #----------------------------------------------------------- -# TEMPORARY params management +# TEMPORARY params management (UNUSED) #----------------------------------------------------------- #temporary solution for testing: if py_param_file_present == True: AssignParams(py_params) -#for debug -#print(RAN.__dict__) -#print(CiTestObj.__dict__) -#print(HTML.__dict__) -#print(ldpc.__dict__) -#for debug - #----------------------------------------------------------- # COTS UE instanciation #----------------------------------------------------------- -#COTS_UE instanciation can only be done here for the moment, due to code architecture -COTS_UE=cls_cots_ue.CotsUe('oppo', CiTestObj.UEIPAddress, CiTestObj.UEUserName,CiTestObj.UEPassword) +#COTS_UE instanciation and ADB server init +#ue id and ue mode are retrieved from xml +COTS_UE=cls_cots_ue.CotsUe(CiTestObj.ADBIPAddress, CiTestObj.ADBUserName,CiTestObj.ADBPassword) #----------------------------------------------------------- -# XML class (action) analysis +# mode amd XML class (action) analysis #----------------------------------------------------------- cwd = os.getcwd() @@ -3388,46 +532,55 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE): if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - RAN.eNB_serverId='0' + if RAN.eNBIPAddress == 'none': + sys.exit(0) RAN.eNB_instance=0 + RAN.eNB_serverId[0]='0' RAN.eNBSourceCodePath='/tmp/' - RAN.TerminateeNB() + RAN.TerminateeNB(HTML, EPC) elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) - CiTestObj.TerminateUE() + CiTestObj.TerminateUE(HTML,COTS_UE,InfraUE,CiTestObj.ue_trace) elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) - CiTestObj.TerminateOAIUE() + CiTestObj.TerminateOAIUE(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) elif re.match('^TerminateHSS$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - EPC.TerminateHSS() + EPC.TerminateHSS(HTML) elif re.match('^TerminateMME$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - EPC.TerminateMME() + EPC.TerminateMME(HTML) elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath== '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - EPC.TerminateSPGW() + EPC.TerminateSPGW(HTML) elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): if (RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - CiTestObj.LogCollectBuild() + if RAN.eNBIPAddress == 'none': + sys.exit(0) + CiTestObj.LogCollectBuild(RAN) elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + if RAN.eNBIPAddress == 'none': + cmd = 'zip -r enb.log.' + RAN.BuildId + '.zip cmake_targets/log' + logging.debug(cmd) + zipStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=60) + sys.exit(0) RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': @@ -3448,12 +601,12 @@ elif re.match('^LogCollectPing$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - CiTestObj.LogCollectPing() + CiTestObj.LogCollectPing(EPC) elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - CiTestObj.LogCollectIperf() + CiTestObj.LogCollectIperf(EPC) elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': HELP.GenericHelp(CONST.Version) @@ -3482,7 +635,7 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): if foundCount != HTML.nbTestXMLfiles: HTML.nbTestXMLfiles=foundCount - if (CiTestObj.ADBIPAddress != 'none'): + if (CiTestObj.ADBIPAddress != 'none') and (CiTestObj.ADBIPAddress != 'modules'): terminate_ue_flag = False CiTestObj.GetAllUEDevices(terminate_ue_flag) CiTestObj.GetAllCatMDevices(terminate_ue_flag) @@ -3495,10 +648,13 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): logging.debug('\u001B[1m Creating HTML footer \u001B[0m') logging.debug('\u001B[1m----------------------------------------\u001B[0m') - CiTestObj.RetrieveSystemVersion('eNB') - CiTestObj.RetrieveSystemVersion('UE') + CiTestObj.RetrieveSystemVersion('eNB',HTML,RAN) + CiTestObj.RetrieveSystemVersion('UE',HTML,RAN) HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Starting Scenario: ' + CiTestObj.testXMLfiles[0] + '\u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') if re.match('^TesteNB$', mode, re.IGNORECASE): if RAN.eNBIPAddress == '' or RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '' or EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': HELP.GenericHelp(CONST.Version) @@ -3534,7 +690,14 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) repeatCount = xmlRoot.findtext('repeatCount',default='1') + testStability = xmlRoot.findtext('TestUnstable',default='False') CiTestObj.repeatCounts.append(int(repeatCount)) + if testStability == 'True': + CiTestObj.testUnstable = True + HTML.testUnstable = True + CiTestObj.testMinStableId = xmlRoot.findtext('TestMinId',default='999999') + HTML.testMinStableId = CiTestObj.testMinStableId + logging.debug('Test is tagged as Unstable -- starting from TestID ' + str(CiTestObj.testMinStableId)) all_tests=xmlRoot.findall('testCase') exclusion_tests=exclusion_tests.split() @@ -3561,8 +724,9 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re logging.debug('ERROR: requested test is invalidly formatted: ' + test) sys.exit(1) if (EPC.IPAddress != '') and (EPC.IPAddress != 'none'): - CiTestObj.CheckFlexranCtrlInstallation() + CiTestObj.CheckFlexranCtrlInstallation(RAN,EPC,CONTAINERS) EPC.SetMmeIPAddress() + EPC.SetAmfIPAddress() #get the list of tests to be done todo_tests=[] @@ -3575,15 +739,33 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re signal.signal(signal.SIGUSR1, receive_signal) - if (CiTestObj.ADBIPAddress != 'none'): + if (CiTestObj.ADBIPAddress != 'none') and (CiTestObj.ADBIPAddress != 'modules'): terminate_ue_flag = False CiTestObj.GetAllUEDevices(terminate_ue_flag) CiTestObj.GetAllCatMDevices(terminate_ue_flag) + elif (CiTestObj.ADBIPAddress == 'modules'): + CiTestObj.UEDevices.append('COTS-Module') else: CiTestObj.UEDevices.append('OAI-UE') HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) HTML.CreateHtmlTabHeader() + # On CI bench w/ containers, we need to validate if IP routes are set + if EPC.IPAddress == '192.168.18.210': + CONTAINERS.CheckAndAddRoute('porcepix', EPC.IPAddress, EPC.UserName, EPC.Password) + if CONTAINERS.eNBIPAddress == '192.168.18.194': + CONTAINERS.CheckAndAddRoute('asterix', CONTAINERS.eNBIPAddress, CONTAINERS.eNBUserName, CONTAINERS.eNBPassword) + if CONTAINERS.eNB1IPAddress == '192.168.18.194': + CONTAINERS.CheckAndAddRoute('asterix', CONTAINERS.eNB1IPAddress, CONTAINERS.eNB1UserName, CONTAINERS.eNB1Password) + if CONTAINERS.eNBIPAddress == '192.168.18.193': + CONTAINERS.CheckAndAddRoute('obelix', CONTAINERS.eNBIPAddress, CONTAINERS.eNBUserName, CONTAINERS.eNBPassword) + if CONTAINERS.eNB1IPAddress == '192.168.18.193': + CONTAINERS.CheckAndAddRoute('obelix', CONTAINERS.eNB1IPAddress, CONTAINERS.eNB1UserName, CONTAINERS.eNB1Password) + if CONTAINERS.eNBIPAddress == '192.168.18.209': + CONTAINERS.CheckAndAddRoute('nepes', CONTAINERS.eNBIPAddress, CONTAINERS.eNBUserName, CONTAINERS.eNBPassword) + if CONTAINERS.eNB1IPAddress == '192.168.18.209': + CONTAINERS.CheckAndAddRoute('nepes', CONTAINERS.eNB1IPAddress, CONTAINERS.eNB1UserName, CONTAINERS.eNB1Password) + CiTestObj.FailReportCnt = 0 RAN.prematureExit=True HTML.startTime=int(round(time.time() * 1000)) @@ -3612,93 +794,140 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CiTestObj.ShowTestID() GetParametersFromXML(action) if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': - if (CiTestObj.ADBIPAddress != 'none'): - terminate_ue_flag = False - CiTestObj.GetAllUEDevices(terminate_ue_flag) + if (CiTestObj.ADBIPAddress != 'none') and (CiTestObj.ADBIPAddress != 'modules'): + #in these cases, having no devices is critical, GetAllUEDevices function has to manage it as a critical error, reason why terminate_ue_flag is set to True + terminate_ue_flag = True + # Now we stop properly the test-suite --> clean reporting + status = CiTestObj.GetAllUEDevices(terminate_ue_flag) + if not status: + RAN.prematureExit = True + break if action == 'Build_eNB': - RAN.BuildeNB() + RAN.BuildeNB(HTML) elif action == 'WaitEndBuild_eNB': - RAN.WaitBuildeNBisFinished() + RAN.WaitBuildeNBisFinished(HTML) elif action == 'Initialize_eNB': check_eNB = False check_OAI_UE = False - RAN.pStatus=CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE) - - RAN.InitializeeNB() + RAN.pStatus=CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) + RAN.InitializeeNB(HTML, EPC) elif action == 'Terminate_eNB': - RAN.TerminateeNB() + RAN.TerminateeNB(HTML, EPC) elif action == 'Initialize_UE': - CiTestObj.InitializeUE() + CiTestObj.InitializeUE(HTML,RAN, EPC, COTS_UE, InfraUE, CiTestObj.ue_trace, CONTAINERS) elif action == 'Terminate_UE': - CiTestObj.TerminateUE() + CiTestObj.TerminateUE(HTML,COTS_UE, InfraUE, CiTestObj.ue_trace) elif action == 'Attach_UE': - CiTestObj.AttachUE() + CiTestObj.AttachUE(HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS) elif action == 'Detach_UE': - CiTestObj.DetachUE() + CiTestObj.DetachUE(HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS) elif action == 'DataDisable_UE': - CiTestObj.DataDisableUE() + CiTestObj.DataDisableUE(HTML) elif action == 'DataEnable_UE': - CiTestObj.DataEnableUE() + CiTestObj.DataEnableUE(HTML) elif action == 'CheckStatusUE': - CiTestObj.CheckStatusUE() + CiTestObj.CheckStatusUE(HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS) elif action == 'Build_OAI_UE': - CiTestObj.BuildOAIUE() + CiTestObj.BuildOAIUE(HTML) elif action == 'Initialize_OAI_UE': - CiTestObj.InitializeOAIUE() + CiTestObj.InitializeOAIUE(HTML,RAN,EPC,COTS_UE,InfraUE,CONTAINERS) elif action == 'Terminate_OAI_UE': - CiTestObj.TerminateOAIUE() + CiTestObj.TerminateOAIUE(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) elif action == 'Initialize_CatM_module': - CiTestObj.InitializeCatM() + CiTestObj.InitializeCatM(HTML) elif action == 'Terminate_CatM_module': - CiTestObj.TerminateCatM() + CiTestObj.TerminateCatM(HTML) elif action == 'Attach_CatM_module': - CiTestObj.AttachCatM() + CiTestObj.AttachCatM(HTML,RAN,COTS_UE,EPC,InfraUE,CONTAINERS) elif action == 'Detach_CatM_module': - CiTestObj.TerminateCatM() + CiTestObj.TerminateCatM(HTML) elif action == 'Ping_CatM_module': - CiTestObj.PingCatM() + CiTestObj.PingCatM(HTML,RAN,EPC,COTS_UE,EPC,InfraUE,CONTAINERS) elif action == 'Ping': - CiTestObj.Ping() + CiTestObj.Ping(HTML,RAN,EPC,COTS_UE, InfraUE, CONTAINERS) elif action == 'Iperf': - CiTestObj.Iperf() + CiTestObj.Iperf(HTML,RAN,EPC,COTS_UE, InfraUE, CONTAINERS) elif action == 'Reboot_UE': - CiTestObj.RebootUE() + CiTestObj.RebootUE(HTML,RAN,EPC) elif action == 'Initialize_HSS': - EPC.InitializeHSS() + EPC.InitializeHSS(HTML) elif action == 'Terminate_HSS': - EPC.TerminateHSS() + EPC.TerminateHSS(HTML) elif action == 'Initialize_MME': - EPC.InitializeMME() + EPC.InitializeMME(HTML) elif action == 'Terminate_MME': - EPC.TerminateMME() + EPC.TerminateMME(HTML) elif action == 'Initialize_SPGW': - EPC.InitializeSPGW() + EPC.InitializeSPGW(HTML) elif action == 'Terminate_SPGW': - EPC.TerminateSPGW() + EPC.TerminateSPGW(HTML) + elif action == 'Initialize_5GCN': + EPC.Initialize5GCN(HTML) + elif action == 'Terminate_5GCN': + EPC.Terminate5GCN(HTML) + elif action == 'Deploy_EPC': + EPC.DeployEpc(HTML) + elif action == 'Undeploy_EPC': + EPC.UndeployEpc(HTML) elif action == 'Initialize_FlexranCtrl': - CiTestObj.InitializeFlexranCtrl() + CiTestObj.InitializeFlexranCtrl(HTML,RAN,EPC) elif action == 'Terminate_FlexranCtrl': - CiTestObj.TerminateFlexranCtrl() + CiTestObj.TerminateFlexranCtrl(HTML,RAN,EPC) elif action == 'IdleSleep': - CiTestObj.IdleSleep() + CiTestObj.IdleSleep(HTML) elif action == 'Perform_X2_Handover': - CiTestObj.Perform_X2_Handover() + CiTestObj.Perform_X2_Handover(HTML,RAN,EPC) elif action == 'Build_PhySim': HTML=ldpc.Build_PhySim(HTML,CONST) - if ldpc.exitStatus==1:sys.exit() + if ldpc.exitStatus==1: + RAN.prematureExit = True elif action == 'Run_PhySim': HTML=ldpc.Run_PhySim(HTML,CONST,id) - elif action == 'COTS_UE_Airplane': - COTS_UE.Set_Airplane(COTS_UE.runargs) + elif action == 'Build_Image': + CONTAINERS.BuildImage(HTML) + elif action == 'Copy_Image_to_Test': + CONTAINERS.Copy_Image_to_Test_Server(HTML) + elif action == 'Deploy_Object': + CONTAINERS.DeployObject(HTML, EPC) + elif action == 'Undeploy_Object': + CONTAINERS.UndeployObject(HTML, RAN) + elif action == 'Cppcheck_Analysis': + SCA.CppCheckAnalysis(HTML) + elif action == 'Deploy_Run_PhySim': + PHYSIM.Deploy_PhySim(HTML, RAN) + elif action == 'DeployGenObject': + CONTAINERS.DeployGenObject(HTML) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True + elif action == 'UndeployGenObject': + CONTAINERS.UndeployGenObject(HTML) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True + elif action == 'PingFromContainer': + CONTAINERS.PingFromContainer(HTML) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True + elif action == 'IperfFromContainer': + CONTAINERS.IperfFromContainer(HTML) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True else: sys.exit('Invalid class (action) from xml') + if RAN.prematureExit: + if CiTestObj.testCase_id == CiTestObj.testMinStableId: + logging.debug('Scenario has reached minimal stability point') + CiTestObj.testStabilityPointReached = True + HTML.testStabilityPointReached = True CiTestObj.FailReportCnt += 1 if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.prematureExit: - logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') + logging.debug('Scenario failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(False) - sys.exit('Failed Scenario') + if CiTestObj.testUnstable and (CiTestObj.testStabilityPointReached or CiTestObj.testMinStableId == '999999'): + logging.debug('Scenario has reached minimal stability point -- Not a Failure') + else: + sys.exit('Failed Scenario') else: - logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') + logging.info('Scenario passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(True) elif re.match('^LoadParams$', mode, re.IGNORECASE): pass diff --git a/ci-scripts/mysql4testresults/docker-compose.yml b/ci-scripts/mysql4testresults/docker-compose.yml new file mode 100644 index 0000000000..1c60057ab2 --- /dev/null +++ b/ci-scripts/mysql4testresults/docker-compose.yml @@ -0,0 +1,12 @@ +version: '2' +services: + mysql: + container_name: oaicicd_mysql + restart: always + image: mysql:latest + environment: + MYSQL_ROOT_PASSWORD: 'ucZBc2XRYdvEm59F' + ports: + - "3307:3306" + volumes: + - /home/oaicicd/mysql/data:/var/lib/mysql diff --git a/ci-scripts/mysql4testresults/sql_connect.py b/ci-scripts/mysql4testresults/sql_connect.py new file mode 100644 index 0000000000..333e573e78 --- /dev/null +++ b/ci-scripts/mysql4testresults/sql_connect.py @@ -0,0 +1,33 @@ +import pymysql +import sys +from datetime import datetime + +#This is the script used to write the test results to the mysql DB +#Called by Jenkins pipeline (jenkinsfile) +#Must be located in /home/oaicicid/mysql on the database host +#Usage from Jenkinsfile : +#python3 /home/oaicicd/mysql/sql_connect.py ${JOB_NAME} ${params.eNB_MR} ${params.eNB_Branch} ${env.BUILD_ID} ${env.BUILD_URL} ${StatusForDb} '' + +class SQLConnect: + def __init__(self): + self.connection = pymysql.connect( + host='172.22.0.2', + user='root', + password = 'ucZBc2XRYdvEm59F', + db='oaicicd_tests', + port=3306 + ) + + def put(self,TEST,MR,BRANCH,BUILD,BUILD_LINK,STATUS): + now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + cur=self.connection.cursor() + cur.execute ('INSERT INTO test_results (TEST,MR,BRANCH,BUILD,BUILD_LINK,STATUS,DATE) VALUES (%s,%s,%s,%s,%s,%s,%s);' , (TEST, MR, BRANCH, BUILD, BUILD_LINK, STATUS, now)) + self.connection.commit() + self.connection.close() + + +if __name__ == "__main__": + mydb=SQLConnect() + mydb.put(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],sys.argv[5],sys.argv[6]) + + diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool index 9b9fe462f1..5ee653c8e1 100755 --- a/ci-scripts/oai-ci-vm-tool +++ b/ci-scripts/oai-ci-vm-tool @@ -170,19 +170,20 @@ function setvar_usage { # for compatibility reasons function variant__v1__enb_usrp { - NB_PATTERN_FILES=9 + NB_PATTERN_FILES=7 BUILD_OPTIONS="--eNB -w USRP --mu" + VM_MEMORY=3072 } function variant__v2__basic_sim { - NB_PATTERN_FILES=13 + NB_PATTERN_FILES=11 BUILD_OPTIONS="--eNB --UE" VM_MEMORY=8192 RUN_OPTIONS="complex" } function variant__v3__phy_sim { - NB_PATTERN_FILES=13 + NB_PATTERN_FILES=11 BUILD_OPTIONS="--phy_simulators" VM_MEMORY=8192 VM_DISK=20 @@ -199,29 +200,29 @@ function variant__v4__cppcheck { function variant__v5__gnb_usrp { VM_MEMORY=10240 VM_CPU=8 - NB_PATTERN_FILES=9 + NB_PATTERN_FILES=7 BUILD_OPTIONS="--gNB -w USRP" } function variant__v6__nr_ue_usrp { VM_MEMORY=4096 VM_CPU=4 - NB_PATTERN_FILES=9 + NB_PATTERN_FILES=7 BUILD_OPTIONS="--nrUE -w USRP" } function variant__v7__enb_ethernet { VM_MEMORY=4096 ARCHIVES_LOC=enb_eth - NB_PATTERN_FILES=8 - BUILD_OPTIONS="--eNB" + NB_PATTERN_FILES=7 + BUILD_OPTIONS="--eNB -w USRP" } function variant__v8__ue_ethernet { VM_MEMORY=4096 ARCHIVES_LOC=ue_eth - NB_PATTERN_FILES=12 - BUILD_OPTIONS="--UE" + NB_PATTERN_FILES=11 + BUILD_OPTIONS="--UE -w USRP" } function variant__v10__flexran_rtc { @@ -246,6 +247,11 @@ function variant__v22__l2_sim { RUN_OPTIONS="complex" } +function variant__v23__rf5g_sim { + ARCHIVES_LOC=rf5g_sim + RUN_OPTIONS="complex" +} + # Following function lists all variant__v__ functions # and set the VARIANTS_SHORT and VARIANTS_LONG arrays from # the function names diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 96f28e21fe..95066d168d 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -37,15 +37,14 @@ import logging import os import time from multiprocessing import Process, Lock, SimpleQueue +import yaml #----------------------------------------------------------- # OAI Testing modules #----------------------------------------------------------- import sshconnection as SSH -import epc import helpreadme as HELP import constants as CONST -import html #----------------------------------------------------------- # Class Declaration @@ -77,19 +76,25 @@ class RANManagement(): self.backgroundBuildTestId = ['', '', ''] self.Build_eNB_forced_workspace_cleanup = False self.Initialize_eNB_args = '' + self.imageKind = '' self.air_interface = ['', '', ''] #changed from 'lte' to '' may lead to side effects in main self.eNB_instance = 0 - self.eNB_serverId = '' + self.eNB_serverId = ['', '', ''] self.eNBLogFiles = ['', '', ''] self.eNBOptions = ['', '', ''] self.eNBmbmsEnables = [False, False, False] self.eNBstatuses = [-1, -1, -1] self.flexranCtrlInstalled = False self.flexranCtrlStarted = False + self.flexranCtrlDeployed = False + self.flexranCtrlIpAddress = '' self.testCase_id = '' self.epcPcapFile = '' - self.htmlObj = None - self.epcObj = None + self.runtime_stats= '' + self.datalog_rt_stats={} + self.eNB_Trace = '' #if 'yes', Tshark will be launched at initialization + self.eNB_Stats = '' #if 'yes', Statistics Monitor will be launched at initialization + self.USRPIPAddress = '' @@ -97,21 +102,21 @@ class RANManagement(): # RAN management functions #----------------------------------------------------------- - def BuildeNB(self): + def BuildeNB(self, HTML): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - if self.eNB_serverId == '0': + if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': + elif self.eNB_serverId[self.eNB_instance] == '1': lIpAddr = self.eNB1IPAddress lUserName = self.eNB1UserName lPassWord = self.eNB1Password lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': + elif self.eNB_serverId[self.eNB_instance] == '2': lIpAddr = self.eNB2IPAddress lUserName = self.eNB2UserName lPassWord = self.eNB2Password @@ -119,6 +124,7 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('Building on server: ' + lIpAddr) mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) @@ -126,24 +132,25 @@ class RANManagement(): result = re.search('--eNBocp', self.Build_eNB_args) if result is not None: self.air_interface[self.eNB_instance] = 'ocp-enb' - else: - result = re.search('--gNB', self.Build_eNB_args) + else: + result = re.search('--RU', self.Build_eNB_args) if result is not None: - self.air_interface[self.eNB_instance] = 'nr-softmodem' + self.air_interface[self.eNB_instance] = 'oairu' else: - self.air_interface[self.eNB_instance] = 'lte-softmodem' - + result = re.search('--gNB', self.Build_eNB_args) + if result is not None: + self.air_interface[self.eNB_instance] = 'nr-softmodem' + else: + self.air_interface[self.eNB_instance] = 'lte-softmodem' + # Worakround for some servers, we need to erase completely the workspace if self.Build_eNB_forced_workspace_cleanup: mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) - if self.htmlObj is not None: - self.testCase_id = self.htmlObj.testCase_id - else: - self.testCase_id = '000000' + self.testCase_id = HTML.testCase_id # on RedHat/CentOS .git extension is mandatory result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) if result is not None: - full_ran_repo_name = self.ranRepository + full_ran_repo_name = self.ranRepository.replace('git/', 'git') else: full_ran_repo_name = self.ranRepository + '.git' mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) @@ -158,16 +165,16 @@ class RANManagement(): result = re.search('LAST_BUILD_INFO', mySSH.getBefore()) if result is not None: mismatch = False - mySSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + mySSH.command('grep --colour=never SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) result = re.search(self.ranCommitID, mySSH.getBefore()) if result is None: mismatch = True - mySSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + mySSH.command('grep --colour=never MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if (self.ranAllowMerge): result = re.search('YES', mySSH.getBefore()) if result is None: mismatch = True - mySSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + mySSH.command('grep --colour=never TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': result = re.search('develop', mySSH.getBefore()) else: @@ -180,14 +187,13 @@ class RANManagement(): mismatch = True if not mismatch: mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) return mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) # if the commit ID is provided use it to point to it if self.ranCommitID != '': - mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) + mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 30) # if the branch is not develop, then it is a merge request and we need to do # the potential merge. Note that merge conflicts should already been checked earlier if (self.ranAllowMerge): @@ -208,26 +214,25 @@ class RANManagement(): mySSH.command('echo ' + lPassWord + ' | sudo -S ls', '\$', 5) mySSH.command('echo $USER; nohup sudo -E ./my-lte-softmodem-build.sh' + ' > ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ' + ' 2>&1 &', lUserName, 5) mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id return mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) mySSH.close() - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id, HTML) - def WaitBuildeNBisFinished(self): - if self.eNB_serverId == '0': + def WaitBuildeNBisFinished(self, HTML): + if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': + elif self.eNB_serverId[self.eNB_instance] == '1': lIpAddr = self.eNB1IPAddress lUserName = self.eNB1UserName lPassWord = self.eNB1Password lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': + elif self.eNB_serverId[self.eNB_instance] == '2': lIpAddr = self.eNB2IPAddress lUserName = self.eNB2UserName lPassWord = self.eNB2Password @@ -235,6 +240,7 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('Waiting for end of build on server: ' + lIpAddr) mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) count = 40 @@ -248,11 +254,10 @@ class RANManagement(): count -= 1 time.sleep(30) mySSH.close() - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)], HTML) - def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - if self.htmlObj is not None: - self.htmlObj.testCase_id=testcaseId + def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId, HTML): + HTML.testCase_id=testcaseId mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) @@ -283,7 +288,7 @@ class RANManagement(): mySSH.command('mkdir -p build_log_' + testcaseId, '\$', 5) mySSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) mySSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) - if self.eNB_serverId != '0': + if self.eNB_serverId[self.eNB_instance] != '0': mySSH.command('cd cmake_targets', '\$', 5) mySSH.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) mySSH.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) @@ -297,7 +302,7 @@ class RANManagement(): mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) mySSH.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) #-qq quiet / -u update orcreate files - mySSH.command('unzip -u -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) + mySSH.command('unzip -o -u -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) mySSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) mySSH.close() else: @@ -306,27 +311,25 @@ class RANManagement(): #generate logging info depending on buildStatus and air interface if buildStatus: logging.info('\u001B[1m Building OAI ' + self.air_interface[self.eNB_instance] + ' Pass\u001B[0m') - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) else: logging.error('\u001B[1m Building OAI ' + self.air_interface[self.eNB_instance] + ' Failed\u001B[0m') - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) - self.htmlObj.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTabFooter(False) sys.exit(1) - def InitializeeNB(self): - if self.eNB_serverId == '0': + def InitializeeNB(self, HTML, EPC): + if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': + elif self.eNB_serverId[self.eNB_instance] == '1': lIpAddr = self.eNB1IPAddress lUserName = self.eNB1UserName lPassWord = self.eNB1Password lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': + elif self.eNB_serverId[self.eNB_instance] == '2': lIpAddr = self.eNB2IPAddress lUserName = self.eNB2UserName lPassWord = self.eNB2Password @@ -334,24 +337,54 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('Starting eNB/gNB on server: ' + lIpAddr) - if self.htmlObj is not None: - self.testCase_id = self.htmlObj.testCase_id - else: - self.testCase_id = '000000' + self.testCase_id = HTML.testCase_id mySSH = SSH.SSHConnection() + cwd = os.getcwd() + mySSH.copyout(lIpAddr,lUserName,lPassWord, cwd + "/active_net_interfaces.awk", "/tmp") + #reboot USRP if requested in xml + if self.USRPIPAddress!='': + logging.debug('USRP '+ self.USRPIPAddress +'reboot request') + mySSH.open(lIpAddr, lUserName, lPassWord) + cmd2usrp='ssh root@'+self.USRPIPAddress+' reboot' + mySSH.command2(cmd2usrp,1) + mySSH.close() + logging.debug('Waiting for USRP to be ready') + time.sleep(120) + + if (self.pStatus < 0): - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' ' + self.Initialize_eNB_args, 'KO', self.pStatus) - self.htmlObj.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' ' + self.Initialize_eNB_args, 'KO', self.pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) + + #Get pcap on enb and/or gnb if enabled in the xml + if self.eNB_Trace=='yes': + if ((self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb')): + pcapfile_prefix="enb_" + else: + pcapfile_prefix="gnb_" + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) + result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', mySSH.getBefore()) + if result is not None: + eth_interface = result.group('eth_interface') + logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') + pcapfile = pcapfile_prefix + self.testCase_id + '_log.pcap' + mySSH.command('echo ' + lPassWord + ' | sudo -S rm -f /tmp/' + pcapfile , '\$', 5) + mySSH.command('echo $USER; nohup sudo -E tshark -i ' + eth_interface + ' -w /tmp/' + pcapfile + ' > /dev/null 2>&1 &','\$', 5) + mySSH.close() + + + # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if (result is not None) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.IPAddress - localEpcUserName = self.epcObj.UserName - localEpcPassword = self.epcObj.Password + if (result is not None): + localEpcIpAddr = EPC.IPAddress + localEpcUserName = EPC.UserName + localEpcPassword = EPC.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) mySSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', mySSH.getBefore()) @@ -390,30 +423,30 @@ class RANManagement(): # do not reset board twice in IF4.5 case result = re.search('^rru|^enb|^du.band', str(config_file)) if result is not None: - mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) + mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 180) result = re.search('type: b200', mySSH.getBefore()) if result is not None: logging.debug('Found a B2xx device --> resetting it') mySSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) # Reloading FGPA bin firmware - mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) + mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 180) # Make a copy and adapt to EPC / eNB IP addresses mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - if self.epcObj is not None: - localMmeIpAddr = self.epcObj.MmeIPAddress - mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + localMmeIpAddr = EPC.MmeIPAddress + mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_GNB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_FR1_CTL_ENB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + if (self.flexranCtrlInstalled and self.flexranCtrlStarted) or self.flexranCtrlDeployed: mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_FLEXRAN_CTL_IP_ADDR/' + self.flexranCtrlIpAddress + '/\' ' + ci_full_config_file, '\$', 2); else: mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); self.eNBmbmsEnables[int(self.eNB_instance)] = False - mySSH.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2); + mySSH.command('grep --colour=never enable_enb_m2 ' + ci_full_config_file, '\$', 2); result = re.search('yes', mySSH.getBefore()) if result is not None: self.eNBmbmsEnables[int(self.eNB_instance)] = True @@ -426,14 +459,40 @@ class RANManagement(): # Launch eNB with the modified config file mySSH.command('source oaienv', '\$', 5) mySSH.command('cd cmake_targets', '\$', 5) - if self.air_interface == 'nr': + if self.air_interface[self.eNB_instance] == 'nr-softmodem': mySSH.command('if [ -e rbconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm rbconfig.raw; fi', '\$', 5) mySSH.command('if [ -e reconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm reconfig.raw; fi', '\$', 5) # NOTE: WE SHALL do a check if the executable is present (in case build went wrong) - mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface[self.eNB_instance] + ' -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + + #hack UHD_RFNOC_DIR variable for gNB / N310 on RHEL8 server: + #if the USRP address is in the xml then we are using an eth USRP (N3xx) + if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): + gNB = False + else: + gNB = True + if ((self.USRPIPAddress!='') and (gNB==True)): + mySSH.command('echo ' + lPassWord + ' | echo "ulimit -c unlimited && sudo UHD_RFNOC_DIR=/usr/local/share/uhd/rfnoc ./ran_build/build/' + self.air_interface[self.eNB_instance] + ' -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + #otherwise the regular command is ok + else: + mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface[self.eNB_instance] + ' -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + mySSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) mySSH.command('echo $USER; nohup sudo -E ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) + + + #stats monitoring during runtime + time.sleep(20) + monitor_file='../ci-scripts/stats_monitor.py' + conf_file='../ci-scripts/stats_monitor_conf.yaml' + if self.eNB_Stats=='yes': + if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): + mySSH.command('echo $USER; nohup python3 ' + monitor_file + ' ' + conf_file + ' enb 2>&1 > enb_stats_monitor_execution.log &', '\$', 5) + else: + mySSH.command('echo $USER; nohup python3 ' + monitor_file + ' ' + conf_file + ' gnb 2>&1 > gnb_stats_monitor_execution.log &', '\$', 5) + + + self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' if extra_options != '': self.eNBOptions[int(self.eNB_instance)] = extra_options @@ -451,14 +510,13 @@ class RANManagement(): mySSH.close() doLoop = False logging.error('\u001B[1;37;41m eNB/gNB/ocp-eNB logging system did not show got sync! \u001B[0m') - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if (result is not None) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.IPAddress - localEpcUserName = self.epcObj.UserName - localEpcPassword = self.epcObj.Password + if (result is not None): + localEpcIpAddr = EPC.IPAddress + localEpcUserName = EPC.UserName + localEpcPassword = EPC.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) @@ -474,7 +532,7 @@ class RANManagement(): self.prematureExit = True return else: - mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting|Started"', '\$', 4) if rruCheck: result = re.search('wait RUs', mySSH.getBefore()) else: @@ -506,11 +564,12 @@ class RANManagement(): else: logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m') if enbDidSync: - self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) + self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId[self.eNB_instance]) mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) + + + HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) logging.debug('\u001B[1m Initialize eNB/gNB/ocp-eNB Completed\u001B[0m') def CheckeNBProcess(self, status_queue): @@ -534,8 +593,12 @@ class RANManagement(): lPassWord = self.eNBPassword mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) - mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface[self.eNB_instance] + ' | grep -v grep', '\$', 5) - result = re.search(self.air_interface[self.eNB_instance], mySSH.getBefore()) + if self.air_interface[self.eNB_instance] == '': + pattern = 'softmodem' + else: + pattern = self.air_interface[self.eNB_instance] + mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + pattern + ' | grep -v grep', '\$', 5) + result = re.search(pattern, mySSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') status_queue.put(CONST.ENB_PROCESS_FAILED) @@ -545,18 +608,18 @@ class RANManagement(): except: os.kill(os.getppid(),signal.SIGUSR1) - def TerminateeNB(self): - if self.eNB_serverId == '0': + def TerminateeNB(self, HTML, EPC): + if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': + elif self.eNB_serverId[self.eNB_instance] == '1': lIpAddr = self.eNB1IPAddress lUserName = self.eNB1UserName lPassWord = self.eNB1Password lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': + elif self.eNB_serverId[self.eNB_instance] == '2': lIpAddr = self.eNB2IPAddress lUserName = self.eNB2UserName lPassWord = self.eNB2Password @@ -564,6 +627,7 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('Stopping eNB/gNB on server: ' + lIpAddr) mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) @@ -582,13 +646,17 @@ class RANManagement(): mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem ocp-enb || true', '\$', 5) time.sleep(5) mySSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + #stopping tshark (valid if eNB and enabled in xml, will not harm otherwise) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + time.sleep(1) mySSH.close() # If tracer options is on, stopping tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if (result is not None) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.IPAddress - localEpcUserName = self.epcObj.UserName - localEpcPassword = self.epcObj.Password + if (result is not None): + localEpcIpAddr = EPC.IPAddress + localEpcUserName = EPC.UserName + localEpcPassword = EPC.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) @@ -600,6 +668,7 @@ class RANManagement(): mySSH.close() logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('killall --signal SIGKILL record', '\$', 5) mySSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] raw_record_file = enbLogFile.replace('.log', '_record.raw') @@ -612,9 +681,8 @@ class RANManagement(): mySSH.close() mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + logStatus = self.AnalyzeLogFile_eNB(extracted_log_file, HTML) + HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) self.eNBLogFiles[int(self.eNB_instance)] = '' else: analyzeFile = False @@ -623,30 +691,42 @@ class RANManagement(): fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] self.eNBLogFiles[int(self.eNB_instance)] = '' if analyzeFile: + #*stats.log files + pickle + png + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*stats.log', '.') + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*.pickle', '.') + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*.png', '.') + # copyin_res = mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') - if self.htmlObj is not None: - self.htmlObj.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - self.htmlObj.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + HTML.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.eNBmbmsEnables[int(self.eNB_instance)] = False return - if self.eNB_serverId != '0': + if self.eNB_serverId[self.eNB_instance] != '0': + #*stats.log files + pickle + png + + #debug / tentative + mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './nrL1_stats.log', self.eNBSourceCodePath + '/cmake_targets/') + mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './nrMAC_stats.log', self.eNBSourceCodePath + '/cmake_targets/') + mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './gnb_stats_monitor.pickle', self.eNBSourceCodePath + '/cmake_targets/') + mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './gnb_stats_monitor.png', self.eNBSourceCodePath + '/cmake_targets/') + # mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) - logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) + logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze, HTML) if (logStatus < 0): - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'KO', logStatus) - self.preamtureExit = True + HTML.CreateHtmlTestRow('N/A', 'KO', logStatus) + self.prematureExit = True self.eNBmbmsEnables[int(self.eNB_instance)] = False return else: - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) else: - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) + #display rt stats for gNB only + if len(self.datalog_rt_stats)!=0 and nodeB_prefix == 'g': + HTML.CreateHtmlDataLogTable(self.datalog_rt_stats) self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 @@ -655,12 +735,14 @@ class RANManagement(): mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) mySSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S mv /tmp/enb_*.pcap .','\$',20) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S mv /tmp/gnb_*.pcap .','\$',20) mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt physim_*.log', '\$', 60) - mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap gnb_*.pcap enb_*txt physim_*.log *stats.log *monitor.pickle *monitor*.png log/*/*.log log/*/*.pcap', '\$', 60) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap gnb_*.pcap enb_*txt physim_*.log *stats.log *monitor.pickle *monitor*.png log/*/*.log log/*/*.pcap', '\$', 15) mySSH.close() - def AnalyzeLogFile_eNB(self, eNBlogFile): + def AnalyzeLogFile_eNB(self, eNBlogFile, HTML): if (not os.path.isfile('./' + eNBlogFile)): return -1 enb_log_file = open('./' + eNBlogFile, 'r') @@ -670,6 +752,7 @@ class RANManagement(): msgLine = 0 foundSegFault = False foundRealTimeIssue = False + foundRealTimeIssue_cnt = 0 rrcSetupComplete = 0 rrcReleaseRequest = 0 rrcReconfigRequest = 0 @@ -704,7 +787,35 @@ class RANManagement(): systemTime = '' maxPhyMemUsage = '' nbContextSwitches = '' + #NSA FR1 check + NSA_RAPROC_PUSCH_check = 0 + #dlsch and ulsch statistics (dictionary) + dlsch_ulsch_stats = {} + #real time statistics (dictionary) + real_time_stats = {} + #count "problem receiving samples" msg + pb_receiving_samples_cnt = 0 + #count "removing UE" msg + removing_ue = 0 + #count"X2AP-PDU" + x2ap_pdu = 0 + #NSA specific log markers + nsa_markers ={'SgNBReleaseRequestAcknowledge': [],'FAILURE': [], 'scgFailureInformationNR-r15': [], 'SgNBReleaseRequest': []} + nodeB_prefix_found = False + + line_cnt=0 #log file line counter for line in enb_log_file.readlines(): + line_cnt+=1 + # Detection of eNB/gNB from a container log + result = re.search('Starting eNB soft modem', str(line)) + if result is not None: + nodeB_prefix_found = True + nodeB_prefix = 'e' + result = re.search('Starting gNB soft modem', str(line)) + if result is not None: + nodeB_prefix_found = True + nodeB_prefix = 'g' + result = re.search('Run time:' ,str(line)) # Runtime statistics result = re.search('Run time:' ,str(line)) if result is not None: @@ -712,16 +823,20 @@ class RANManagement(): if runTime != '': result = re.search('Time executing user inst', str(line)) if result is not None: - userTime = 'to be decoded - 1' + fields=line.split(':') + userTime = 'userTime : ' + fields[1].replace('\n','') result = re.search('Time executing system inst', str(line)) if result is not None: - systemTime = 'to be decoded - 2' + fields=line.split(':') + systemTime = 'systemTime : ' + fields[1].replace('\n','') result = re.search('Max. Phy. memory usage:', str(line)) if result is not None: - maxPhyMemUsage = 'to be decoded - 3' + fields=line.split(':') + maxPhyMemUsage = 'maxPhyMemUsage : ' + fields[1].replace('\n','') result = re.search('Number of context switch.*process origin', str(line)) if result is not None: - nbContextSwitches = 'to be decoded - 4' + fields=line.split(':') + nbContextSwitches = 'nbContextSwitches : ' + fields[1].replace('\n','') if X2HO_state == CONST.X2_HO_REQ_STATE__IDLE: result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) if result is not None: @@ -776,6 +891,7 @@ class RANManagement(): result = re.search('LLL', str(line)) if result is not None and not exitSignalReceived: foundRealTimeIssue = True + foundRealTimeIssue_cnt += 1 if foundAssertion and (msgLine < 3): msgLine += 1 msgAssertion += str(line) @@ -850,13 +966,97 @@ class RANManagement(): result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line)) if result is not None: mbmsRequestMsg += 1 + #FR1 NSA test : add new markers to make sure gNB is used + result = re.search('\[gNB [0-9]+\]\[RAPROC\] PUSCH with TC_RNTI 0x[0-9a-fA-F]+ received correctly, adding UE MAC Context UE_id [0-9]+\/RNTI 0x[0-9a-fA-F]+', str(line)) + if result is not None: + NSA_RAPROC_PUSCH_check = 1 + #dlsch and ulsch statistics + #keys below are the markers we are loooking for, loop over this keys list + #everytime these markers are found in the log file, the previous ones are overwritten in the dict + #eventually we record and print only the last occurence + keys = {'UE ID','dlsch_rounds','dlsch_total_bytes','ulsch_rounds','ulsch_total_bytes_scheduled'} + for k in keys: + result = re.search(k, line) + if result is not None: + #remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char + dlsch_ulsch_stats[k]=re.sub(r'^.*\]\s+', r'' , line.rstrip()) + + + #count "problem receiving samples" msg + result = re.search('\[PHY\]\s+problem receiving samples', str(line)) + if result is not None: + pb_receiving_samples_cnt += 1 + #count "Removing UE" msg + result = re.search('\[MAC\]\s+Removing UE', str(line)) + if result is not None: + removing_ue += 1 + #count "X2AP-PDU" + result = re.search('X2AP-PDU', str(line)) + if result is not None: + x2ap_pdu += 1 + #nsa markers logging + for k in nsa_markers: + result = re.search(k, line) + if result is not None: + nsa_markers[k].append(line_cnt) + enb_log_file.close() - logging.debug(' File analysis completed') - if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): - nodeB_prefix = 'e' + + + #the following part takes the *_stats.log files as source (not the stdout log file) + + #the datalog config file has to be loaded + datalog_rt_stats_file='datalog_rt_stats.yaml' + if (os.path.isfile(datalog_rt_stats_file)): + yaml_file=datalog_rt_stats_file + elif (os.path.isfile('ci-scripts/'+datalog_rt_stats_file)): + yaml_file='ci-scripts/'+datalog_rt_stats_file else: - nodeB_prefix = 'g' - if self.air_interface[self.eNB_instance] == 'nr-softmodem': + logging.error("Datalog RT stats yaml file cannot be found") + sys.exit("Datalog RT stats yaml file cannot be found") + + with open(yaml_file,'r') as f: + datalog_rt_stats = yaml.load(f,Loader=yaml.FullLoader) + rt_keys = datalog_rt_stats['Ref'] #we use the keys from the Ref field + + if (os.path.isfile('./nrL1_stats.log')) and (os.path.isfile('./nrL1_stats.log')): + stat_files_present=True + else: + stat_files_present=False + logging.debug("NR Stats files for RT analysis not found") + if stat_files_present: + nrL1_stats = open('./nrL1_stats.log', 'r') + nrMAC_stats = open('./nrMAC_stats.log', 'r') + for line in nrL1_stats.readlines(): + for k in rt_keys: + result = re.search(k, line) + if result is not None: + #remove 1- all useless char before relevant info 2- trailing char + tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex + if tmp!=None: + real_time_stats[k]=tmp.group(1) + for line in nrMAC_stats.readlines(): + for k in rt_keys: + result = re.search(k, line) + if result is not None: + #remove 1- all useless char before relevant info 2- trailing char + tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex + if tmp!=None: + real_time_stats[k]=tmp.group(1) + nrL1_stats.close() + nrMAC_stats.close() + + #stdout log file and stat log files analysis completed + logging.debug(' File analysis (stdout, stats) completed') + + #post processing depending on the node type + if not nodeB_prefix_found: + if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' + + if nodeB_prefix == 'g': if ulschReceiveOK > 0: statMsg = nodeB_prefix + 'NB showed ' + str(ulschReceiveOK) + ' "ULSCH received ok" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') @@ -869,6 +1069,96 @@ class RANManagement(): statMsg = nodeB_prefix + 'NB ran with TX Write thread enabled' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') htmleNBFailureMsg += statMsg + '\n' + #FR1 NSA test : add new markers to make sure gNB is used + if NSA_RAPROC_PUSCH_check: + statMsg = '[RAPROC] PUSCH with TC_RNTI message check for ' + nodeB_prefix + 'NB : PASS ' + htmlMsg = statMsg+'\n' + else: + statMsg = '[RAPROC] PUSCH with TC_RNTI message check for ' + nodeB_prefix + 'NB : FAIL or not relevant' + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + #problem receiving samples log + statMsg = '[PHY] problem receiving samples msg count = '+str(pb_receiving_samples_cnt) + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + #nsa markers + statMsg = 'logfile line count = ' + str(line_cnt) + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + if len(nsa_markers['SgNBReleaseRequestAcknowledge'])!=0: + statMsg = 'SgNBReleaseRequestAcknowledge = ' + str(len(nsa_markers['SgNBReleaseRequestAcknowledge'])) + ' occurences , starting line ' + str(nsa_markers['SgNBReleaseRequestAcknowledge'][0]) + else: + statMsg = 'SgNBReleaseRequestAcknowledge = ' + str(len(nsa_markers['SgNBReleaseRequestAcknowledge'])) + ' occurences' + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + statMsg = 'FAILURE = ' + str(len(nsa_markers['FAILURE'])) + ' occurences' + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + + #ulsch and dlsch statistics + if len(dlsch_ulsch_stats)!=0: #check if dictionary is not empty + statMsg='' + for key in dlsch_ulsch_stats: #for each dictionary key + statMsg += dlsch_ulsch_stats[key] + '\n' + logging.debug(dlsch_ulsch_stats[key]) + htmleNBFailureMsg += statMsg + + #real time statistics + datalog_rt_stats['Data']={} + if len(real_time_stats)!=0: #check if dictionary is not empty + for k in real_time_stats: + tmp=re.match(r'^(?P.*):\s+(?P\d+\.\d+) us;\s+\d+;\s+(?P\d+\.\d+) us;',real_time_stats[k]) + if tmp is not None: + metric=tmp.group('metric') + avg=float(tmp.group('avg')) + max=float(tmp.group('max')) + datalog_rt_stats['Data'][metric]=["{:.0f}".format(avg),"{:.0f}".format(max),"{:.2f}".format(avg/datalog_rt_stats['Ref'][metric])] + #once all metrics are collected, store the data as a class attribute to build a dedicated HTML table afterward + self.datalog_rt_stats=datalog_rt_stats + #check if there is a fail => will render the test as failed + for k in datalog_rt_stats['Data']: + if float(datalog_rt_stats['Data'][k][2])> datalog_rt_stats['Threshold'][k]: #condition for fail : avg/ref is greater than the fixed threshold + #setting prematureExit is ok although not the best option + self.prematureExit=False #temp for debug : do not stop the test if RT stats are excedeed + else: + statMsg = 'No real time stats found in the log file\n' + logging.debug('No real time stats found in the log file') + htmleNBFailureMsg += statMsg + + else: + #Removing UE log + statMsg = '[MAC] Removing UE msg count = '+str(removing_ue) + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + #X2AP-PDU log + statMsg = 'X2AP-PDU msg count = '+str(x2ap_pdu) + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + #nsa markers + statMsg = 'logfile line count = ' + str(line_cnt) + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + if len(nsa_markers['SgNBReleaseRequest'])!=0: + statMsg = 'SgNBReleaseRequest = ' + str(len(nsa_markers['SgNBReleaseRequest'])) + ' occurences , starting line ' + str(nsa_markers['SgNBReleaseRequest'][0]) + else: + statMsg = 'SgNBReleaseRequest = ' + str(len(nsa_markers['SgNBReleaseRequest'])) + ' occurences' + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + statMsg = 'scgFailureInformationNR-r15 = ' + str(len(nsa_markers['scgFailureInformationNR-r15'])) + ' occurences' + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + + if uciStatMsgCount > 0: statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') @@ -970,19 +1260,19 @@ class RANManagement(): global_status = CONST.ENB_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') - htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' + htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues! COUNT = '+ str(foundRealTimeIssue_cnt) +' lines\n' if rlcDiscardBuffer > 0: rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') htmleNBFailureMsg += rlcMsg + '\n' global_status = CONST.ENB_PROCESS_REALTIME_ISSUE - if self.htmlObj is not None: - self.htmlObj.htmleNBFailureMsg=htmleNBFailureMsg - # Runtime statistics + HTML.htmleNBFailureMsg=htmleNBFailureMsg + # Runtime statistics for console output and HTML if runTime != '': logging.debug(runTime) - logging.debug('Time executing user inst : ' + userTime) - logging.debug('Time executing system inst : ' + systemTime) - logging.debug('Max Physical Memory Usage : ' + maxPhyMemUsage) - logging.debug('Nb Context Switches : ' + nbContextSwitches) + logging.debug(userTime) + logging.debug(systemTime) + logging.debug(maxPhyMemUsage) + logging.debug(nbContextSwitches) + self.runtime_stats='
'+runTime + '\n'+ userTime + '\n' + systemTime + '\n' + maxPhyMemUsage + '\n' + nbContextSwitches+'
' return global_status diff --git a/ci-scripts/ran_dashboard/Hdashboard.py b/ci-scripts/ran_dashboard/Hdashboard.py new file mode 100644 index 0000000000..0cfae97c76 --- /dev/null +++ b/ci-scripts/ran_dashboard/Hdashboard.py @@ -0,0 +1,559 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Merge Requests Dashboard for RAN on googleSheet +# +# Required Python Version +# Python 3.x +# +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- + + +#Author Remi +import boto3 +import shlex +import subprocess +import json #json structures +import datetime #now() and date formating +from datetime import datetime +import re +import gitlab +import yaml +import os +import time +import sys + +from sqlconnect import SQLConnect + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- + +class Dashboard: + def __init__(self): + + + #init with data sources : git, yaml config file, test results databases + print("Collecting Data") + cmd="""curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100" """ + self.git = self.__getGitData(cmd) #git data from Gitlab + self.tests = self.__loadCfg('ran_dashboard_cfg.yaml') #tests table setup from yaml + self.db = self.__loadFromDB() #test results from database + self.mr_list=[] #mr list in string format + for x in range(len(self.git)): + self.mr_list.append(str(self.git[x]['iid'])) + + def __loadCfg(self,yaml_file): + with open(yaml_file,'r') as f: + tests = yaml.load(f) + return tests + + def __getGitData(self,cmd): + #cmd="""curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100" """ + process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE) + output = process.stdout.readline() + tmp=output.decode("utf-8") + d = json.loads(tmp) + return d + + def __loadFromDB(self): + mr_list=[] + for x in range(len(self.git)): + mr_list.append(str(self.git[x]['iid'])) + mydb=SQLConnect() + for MR in mr_list: + mydb.get(MR) + mydb.close_connection() + return mydb.data + + def singleMR_initHTML(self, date): + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('Test Dashboard\n') + self.f_html.write('\n') + self.f_html.write('
\n') + self.f_html.write('
\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('
OAI RAN TEST Status Dashboard
Update : '+date+'
\n') + self.f_html.write('
\n') + self.f_html.write('
\n') + + + def Test_initHTML(self, date): + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('Test Dashboard\n') + self.f_html.write('\n') + self.f_html.write('
\n') + self.f_html.write('
\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('
OAI RAN TEST Status Dashboard
Update : '+date+'
\n') + self.f_html.write('
\n') + self.f_html.write('
\n') + + def Test_terminateHTML(self): + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.close() + + + def MR_initHTML(self,date): + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('MR Dashboard\n') + self.f_html.write('\n') + self.f_html.write('
\n') + self.f_html.write('
\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('
OAI RAN MR Status Dashboard
Update : '+date+'
\n') + self.f_html.write('
\n') + self.f_html.write('
\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + + def MR_terminateHTML(self): + self.f_html.write('
MRCreated_AtAuthorTitleAssigneeReviewerCAN STARTIN PROGRESSCOMPLETEDReview FormOK MergeMerge Conflicts
\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.close() + + + def MR_rowHTML(self,row): + self.f_html.write('\n') + self.f_html.write(''+row[1]+'\n') + self.f_html.write(''+row[2]+'\n') + self.f_html.write(''+row[3]+'\n') + self.f_html.write(''+row[4]+'\n') + self.f_html.write(''+row[5]+'\n') + self.f_html.write(''+row[6]+'\n') + if row[7]=='X': + self.f_html.write(''+row[7]+'\n') + else: + self.f_html.write('\n') + if row[8]=='X': + self.f_html.write(''+row[8]+'\n') + else: + self.f_html.write('\n') + if row[9]=='X': + self.f_html.write(''+row[9]+'\n') + else: + self.f_html.write('\n') + if row[10]=='X': + self.f_html.write(''+row[10]+'\n') + else: + self.f_html.write('\n') + if row[11]=='X': + self.f_html.write(''+row[11]+'\n') + else: + self.f_html.write('\n') + if row[12]=='YES': + self.f_html.write(''+row[12]+'\n') + else: + self.f_html.write('\n') + self.f_html.write('\n') + + + def Build(self, type, mr, htmlfilename): + if type=='MR': + self.Build_MR_Table(htmlfilename) + elif type=='Tests': + self.Build_Test_Table(htmlfilename) + elif type=='singleMR': + self.Build_singleMR_Table(mr,htmlfilename) + else : + print("Undefined Dashboard Type, options : MR or Tests") + + + def Build_Test_Table(self,htmlfilename): + print("Building Tests Dashboard...") + + self.f_html=open(htmlfilename,'w') + + ###update date/time, format dd/mm/YY H:M:S + now = datetime.now() + dt_string = now.strftime("%d/%m/%Y %H:%M") + #HTML table header + self.Test_initHTML(dt_string) + + + #1 table per MR if test results exist + for x in range(len(self.git)): + mr=str(self.git[x]['iid']) + if 'PASS' not in self.db[mr]: + self.f_html.write('

'+mr+''+' '+self.git[x]['title'] + '

\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write(' \n') + self.f_html.write(' \n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + + #parsing the tests + for t in self.tests: + + row=[] + short_name= t + hyperlink= self.tests[t]['link'] + job=self.tests[t]['job'] + + + if job in self.db[mr]: + if 'PASS' in self.db[mr][job]: + row.append(self.db[mr][job]['PASS']) + else: + row.append('') + if 'FAIL' in self.db[mr][job]: + row.append(self.db[mr][job]['FAIL']) + else: + row.append('') + #2 columns for last_pass and last_fail links + if 'last_pass' in self.db[mr][job]: + lastpasshyperlink= self.db[mr][job]['last_pass'][1] + lastpasstext= self.db[mr][job]['last_pass'][0] + else: + lastpasshyperlink='' + lastpasstext='' + + if 'last_fail' in self.db[mr][job]: + lastfailhyperlink= self.db[mr][job]['last_fail'][1] + lastfailtext= self.db[mr][job]['last_fail'][0] + else: + lastfailhyperlink='' + lastfailtext='' + + + + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + if row[0]!='': + self.f_html.write('\n') + else: + self.f_html.write('\n') + if row[1]!='': + self.f_html.write('\n') + else: + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + + self.f_html.write('
Test NameBenchTest# Pass# FailLast PassLast Fail
'+short_name+''+self.tests[t]['bench']+''+self.tests[t]['test']+''+str(row[0])+''+str(row[1])+''+lastpasstext+''+lastfailtext+'
\n') + + #terminate HTML table and close file + self.Test_terminateHTML() + + + def Build_singleMR_Table(self,singlemr,htmlfilename): + print("Building single MR Tests Results...") + + self.f_html=open(htmlfilename,'w') + + ###update date/time, format dd/mm/YY H:M:S + now = datetime.now() + dt_string = now.strftime("%d/%m/%Y %H:%M") + #HTML table header + self.singleMR_initHTML(dt_string) + + + #1 table per MR if test results exist => 1 table for matching mr + for x in range(len(self.git)): + mr=str(self.git[x]['iid']) + if mr==singlemr: + #if 'PASS' not in self.db[mr]: + self.f_html.write('

'+mr+''+' '+self.git[x]['title'] + '

\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write(' \n') + self.f_html.write(' \n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + + #parsing the tests + for t in self.tests: + + row=[] + short_name= t + hyperlink= self.tests[t]['link'] + job=self.tests[t]['job'] + + + if job in self.db[mr]: + if 'PASS' in self.db[mr][job]: + row.append(self.db[mr][job]['PASS']) + else: + row.append('') + if 'FAIL' in self.db[mr][job]: + row.append(self.db[mr][job]['FAIL']) + else: + row.append('') + #2 columns for last_pass and last_fail links + if 'last_pass' in self.db[mr][job]: + lastpasshyperlink= self.db[mr][job]['last_pass'][1] + lastpasstext= self.db[mr][job]['last_pass'][0] + else: + lastpasshyperlink='' + lastpasstext='' + + if 'last_fail' in self.db[mr][job]: + lastfailhyperlink= self.db[mr][job]['last_fail'][1] + lastfailtext= self.db[mr][job]['last_fail'][0] + else: + lastfailhyperlink='' + lastfailtext='' + + + + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + if row[0]!='': + self.f_html.write('\n') + else: + self.f_html.write('\n') + if row[1]!='': + self.f_html.write('\n') + else: + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + self.f_html.write('\n') + + self.f_html.write('
Test NameBenchTest# Pass# FailLast PassLast Fail
'+short_name+''+self.tests[t]['bench']+''+self.tests[t]['test']+''+str(row[0])+''+str(row[1])+''+lastpasstext+''+lastfailtext+'
\n') + + #terminate HTML table and close file + self.Test_terminateHTML() + + + + def Build_MR_Table(self,htmlfilename): + + print("Building Merge Requests Dashboard...") + + self.f_html=open(htmlfilename,'w') + + ###update date/time, format dd/mm/YY H:M:S + now = datetime.now() + dt_string = now.strftime("%d/%m/%Y %H:%M") + + #HTML table header + self.MR_initHTML(dt_string) + + + ###MR data lines + for x in range(len(self.git)): + + + hyperlink= 'https://gitlab.eurecom.fr/oai/openairinterface5g/-/merge_requests/'+ str(self.git[x]['iid']) + text= str(self.git[x]['iid']) + + + date_time_str = self.git[x]['created_at'] + date_time_obj = datetime.strptime(date_time_str, '%Y-%m-%dT%H:%M:%S.%fZ') + + milestone1=milestone2=milestone3=milestone4="" + if self.git[x]['milestone']!=None: + if self.git[x]['milestone']['title']=="REVIEW_CAN_START": + milestone1="X" + elif self.git[x]['milestone']['title']=="REVIEW_IN_PROGRESS": + milestone2="X" + elif self.git[x]['milestone']['title']=="REVIEW_COMPLETED_AND_APPROVED": + milestone3="X" + elif self.git[x]['milestone']['title']=="OK_TO_BE_MERGED": + milestone4="X" + else: + pass + else: + pass + + #check if empty or not + if self.git[x]['assignee']!=None: + assignee = str(self.git[x]['assignee']['name']) + else: + assignee = "" + + #check if empty or not + if len(self.git[x]['reviewers'])!=0: + reviewer = str(self.git[x]['reviewers'][0]['name']) + else: + reviewer = "" + + if self.git[x]['has_conflicts']==True: + conflicts = "YES" + else: + conflicts = "" + + + #add a column flagging that the review form is present + #we use gitlab API to parse the MR notes + gl = gitlab.Gitlab.from_config('OAI') + project_id = 223 + project = gl.projects.get(project_id) + #get the opened MR in the project + mrs = project.mergerequests.list(state='opened',per_page=100) + review_form='' + for m in range (0,len(mrs)): + if mrs[m].iid==self.git[x]['iid']:#check the iid is the one we are on + mr_notes = mrs[m].notes.list(all=True) + n=0 + found=False + while found==False and n'+status+', '+\ + '('+buildid+')
'+\ + 'Consolidated Test Results' + }) + editable_mr.save() + + +def main(): + + #call from Jenkinsfile : sh "python3 Hdashboard.py testevent ${params.eNB_MR} ${JOB_NAME} ${env.BUILD_URL} ${env.BUILD_ID} ${StatusForDb} " + + #individual MR test results + test dashboard, event based (end of jenkins pipeline) + if len(sys.argv)>1: + if sys.argv[1]=="testevent" : + mr=sys.argv[2] + jobname=sys.argv[3] + buildurl=sys.argv[4] + buildid=sys.argv[5] + status=sys.argv[6] + htmlDash=Dashboard() + if mr in htmlDash.mr_list: + htmlDash.Build('singleMR',mr,'/tmp/MR'+mr+'_index.html') + htmlDash.CopyToS3('/tmp/MR'+mr+'_index.html','oaitestdashboard','MR'+mr+'/index.html') + htmlDash.Build('Tests','0000','/tmp/Tests_index.html') + htmlDash.CopyToS3('/tmp/Tests_index.html','oaitestdashboard','index.html') + htmlDash.PostGitNote(mr,jobname,buildurl,buildid,status) + else: + print("Not a Merge Request => this build is for testing/debug purpose, no report to git") + #test and MR status dash boards, cron based + else: + htmlDash=Dashboard() + htmlDash.Build('MR','0000','/tmp/MR_index.html') + htmlDash.CopyToS3('/tmp/MR_index.html','oairandashboard','index.html') + htmlDash.Build('Tests','0000','/tmp/Tests_index.html') + htmlDash.CopyToS3('/tmp/Tests_index.html','oaitestdashboard','index.html') + + + +if __name__ == "__main__": + # execute only if run as a script + main() diff --git a/ci-scripts/ran_dashboard/mr_styles.css b/ci-scripts/ran_dashboard/mr_styles.css new file mode 100755 index 0000000000..5d938669cb --- /dev/null +++ b/ci-scripts/ran_dashboard/mr_styles.css @@ -0,0 +1,136 @@ +body { + font-family: 'lato', sans-serif; + } + + +.Main { + text-align:left; + font-size: 30px; + font-weight: bold; +} + +.DashLink { + text-align:left; + font-size: 16px; +} + +.DashLink:hover { + font-weight: bold; +} + +.Date { + text-align:left; + font-size: 16px; + font-weight: bold; +} + + +a { text-decoration: none; } +a:visited { text-decoration: none; color:blue} +a:hover { text-decoration: none; font-weight: bold; color:blue} + + +.MR_Table { + border-collapse: collapse; +} + +.MR_Table tr { + font-size: 12px; + text-align:center; +} + + +.MR_Table tr:hover { + background-color:lightgray; +} + +.MR_Table td { + border: 1px solid black; + padding : 5px; +} +.MR_Table td:hover { +font-weight : bold; +} + +.MR_Table th { + font-size: 14px; + text-align:center; + padding : 5px; +} + + +.title_cell { + text-align:left; +} + + +.MR { + table-layout: fixed; + width: 50px; + background-color: rgb(143, 154, 216); +} + +.CREATED_AT { + table-layout: fixed; + width: 100px; + background-color: rgb(143, 154, 216); +} + +.AUTHOR { + table-layout: fixed; + width: 150px; + background-color: rgb(143, 154, 216); +} + +.TITLE { + table-layout: fixed; + width: 500px; + background-color: rgb(143, 154, 216); +} + +.ASSIGNEE { + table-layout: fixed; + width: 150px; + background-color: rgb(143, 154, 216); +} + +.REVIEWER { + table-layout: fixed; + width: 150px; + background-color: rgb(143, 154, 216); +} + +.CAN_START { + background-color: orange; + table-layout: fixed; + width: 150px; +} +.IN_PROGRESS { + background-color: yellow; + table-layout: fixed; + width: 150px; +} +.COMPLETED { + background-color: rgb(144, 221, 231); + table-layout: fixed; + width: 150px; +} + +.REVIEW_FORM { + table-layout: fixed; + width: 100px; + background-color: rgb(143, 154, 216); +} + +.OK_MERGE { + background-color: rgb(58, 236, 58); + table-layout: fixed; + width: 150px; +} + +.MERGE_CONFLICTS { + table-layout: fixed; + width: 100px; + background-color: rgb(143, 154, 216); +} + diff --git a/ci-scripts/ran_dashboard/ran_dashboard.py b/ci-scripts/ran_dashboard/ran_dashboard.py new file mode 100644 index 0000000000..54a98ec878 --- /dev/null +++ b/ci-scripts/ran_dashboard/ran_dashboard.py @@ -0,0 +1,405 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Merge Requests Dashboard for RAN on googleSheet +# +# Required Python Version +# Python 3.x +# +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- + +#author Remi + +#import google spreadsheet API +import gspread +from oauth2client.service_account import ServiceAccountCredentials + + +import subprocess +import shlex #lexical analysis +import json #json structures +import datetime #now() and date formating +from datetime import datetime +import re +import gitlab +import yaml +import os +import pickle +import time + + +from sqlconnect import SQLConnect + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- + +class gDashboard: + def __init__(self, creds_file, spreadsheet, worksheet): #"creds.json", 'OAI RAN Dashboard', 'MR Status' + self.scope = ["https://spreadsheets.google.com/feeds",'https://www.googleapis.com/auth/spreadsheets',"https://www.googleapis.com/auth/drive.file","https://www.googleapis.com/auth/drive"] + self.creds = ServiceAccountCredentials.from_json_keyfile_name(creds_file, self.scope) + self.client = gspread.authorize(self.creds) + #spreadsheet + self.ss = self.client.open(spreadsheet) + #worksheet + self.sheet = self.ss.worksheet(worksheet) + self.ss.del_worksheet(self.sheet) #start by deleting the old sheet + self.sheet = self.ss.add_worksheet(title=worksheet, rows="100", cols="30") #create a new one + + #init with data sources : git, yaml config file, test results databases + cmd="""curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100" """ + self.git = self.__getGitData(cmd) #git data from Gitlab + self.tests = self.__loadCfg('ran_dashboard_cfg.yaml') #tests table setup from yaml + self.db = self.__loadFromDB() #test results from database + + + def __loadCfg(self,yaml_file): + with open(yaml_file,'r') as f: + tests = yaml.load(f) + return tests + + def __getGitData(self,cmd): + #cmd="""curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100" """ + process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE) + output = process.stdout.readline() + tmp=output.decode("utf-8") + d = json.loads(tmp) + return d + + def __loadFromDB(self): + mr_list=[] + for x in range(len(self.git)): + mr_list.append(str(self.git[x]['iid'])) + mydb=SQLConnect() + for MR in mr_list: + mydb.get(MR) + mydb.close_connection() + return mydb.data + + + + def gBuild(self, destinationSheetName): + + ###line 1 : update date/time, format dd/mm/YY H:M:S + now = datetime.now() + dt_string = "Update : " + now.strftime("%d/%m/%Y %H:%M") + row =[dt_string] + self.sheet.insert_row(row, index=1, value_input_option='RAW') + + ###line 2 is for the test short names (links to jenkins pipeline), updated at the end + + ###line 3 is for the column names + i=3 + row =["MR","Created_at","Author","Title","Assignee", "Reviewer", "CAN START","IN PROGRESS","COMPLETED","Review Form","OK MERGE","Merge conflicts",""] + + #tests + for t in range(0,len(self.tests)): + row.append("# PASS") + row.append("# FAIL") + row.append("Last Pass") + row.append("Last Fail") + + self.sheet.insert_row(row, index=i, value_input_option='RAW') + + ###line 4 onward, MR data lines + for x in range(len(self.git)): + i=i+1 + date_time_str = self.git[x]['created_at'] + date_time_obj = datetime.strptime(date_time_str, '%Y-%m-%dT%H:%M:%S.%fZ') + + milestone1=milestone2=milestone3=milestone4="" + if self.git[x]['milestone']!=None: + if self.git[x]['milestone']['title']=="REVIEW_CAN_START": + milestone1="X" + elif self.git[x]['milestone']['title']=="REVIEW_IN_PROGRESS": + milestone2="X" + elif self.git[x]['milestone']['title']=="REVIEW_COMPLETED_AND_APPROVED": + milestone3="X" + elif self.git[x]['milestone']['title']=="OK_TO_BE_MERGED": + milestone4="X" + else: + pass + else: + pass + + #check if empty or not + if self.git[x]['assignee']!=None: + assignee = str(self.git[x]['assignee']['name']) + else: + assignee = "" + + #check if empty or not + if len(self.git[x]['reviewers'])!=0: + reviewer = str(self.git[x]['reviewers'][0]['name']) + else: + reviewer = "" + + if self.git[x]['has_conflicts']==True: + conflicts = "YES" + else: + conflicts = "" + + + #add a column flagging that the review form is present + #we use gitlab API to parse the MR notes + gl = gitlab.Gitlab.from_config('OAI') + project_id = 223 + project = gl.projects.get(project_id) + #get the opened MR in the project + mrs = project.mergerequests.list(state='opened',per_page=100) + review_form='' + for m in range (0,len(mrs)): + if mrs[m].iid==self.git[x]['iid']:#check the iid is the one we are on + mr_notes = mrs[m].notes.list(all=True) + n=0 + found=False + while found==False and nUbuntu 16.04 LTS -- Summary" >> ./build_results.html - sca_summary_table_header ./archives/cppcheck/cppcheck.xml "OAI Static Code Analysis with CPPCHECK" - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Uninitialized variable" uninitvar - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Uninitialized struct member" uninitStructMember - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Memory leak" memleak - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Memory is freed twice" doubleFree - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Resource leak" resourceLeak - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Possible null pointer dereference" nullPointer - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Array access out of bounds" arrayIndexOutOfBounds - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Buffer is accessed out of bounds" bufferAccessOutOfBounds - sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Expression depends on order of evaluation of side effects" unknownEvaluationOrder - sca_summary_table_footer ./archives/cppcheck/cppcheck.xml - - summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_usrp - summary_table_row "LTE SoftModem - Release 15" ./archives/enb_usrp/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_usrp_row1.html - summary_table_row "Coding - Release 15" ./archives/enb_usrp/coding.Rel15.txt "Built target coding" ./enb_usrp_row2.html - summary_table_row "OAI USRP device if - Release 15" ./archives/enb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_usrp_row3.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_usrp_row4.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_usrp_row5.html - summary_table_row "NASMESH - Release 15" ./archives/enb_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./enb_usrp_row6.html - summary_table_row "RB Tool - Release 15" ./archives/enb_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./enb_usrp_row7.html - summary_table_row "RF Simulator - Release 15" ./archives/enb_usrp/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_usrp_row8.html - summary_table_row "TCP Bridge - Release 15" ./archives/enb_usrp/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_usrp_row9.html - summary_table_footer - - summary_table_header "OAI Build: 4G LTE basic simulator option" ./archives/basic_sim - summary_table_row "LTE SoftModem - Release 15" ./archives/basic_sim/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./basic_sim_row1.html - summary_table_row "LTE UE SoftModem - Release 15" ./archives/basic_sim/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./basic_sim_row2.htm - summary_table_row "Coding - Release 15" ./archives/basic_sim/coding.Rel15.txt "Built target coding" ./basic_sim_row3.html - summary_table_row "Conf 2 UE data - Release 15" ./archives/basic_sim/conf2uedata.Rel15.txt "Built target conf2uedata" ./basic_sim_row4.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/basic_sim/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./basic_sim_row5.html - summary_table_row "NASMESH - Release 15" ./archives/basic_sim/nasmesh.Rel15.txt "Built target nasmesh" ./basic_sim_row6.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/basic_sim/params_libconfig.Rel15.txt "Built target params_libconfig" ./basic_sim_row7.html - summary_table_row "RB Tool - Release 15" ./archives/basic_sim/rb_tool.Rel15.txt "Built target rb_tool" ./basic_sim_row8.html - summary_table_row "RF Simulator - Release 15" ./archives/basic_sim/rfsimulator.Rel15.txt "Built target rfsimulator" ./basic_sim_row9.html - summary_table_row "TCP Bridge - Release 15" ./archives/basic_sim/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./basic_sim_row10.html - summary_table_row "UE IP - Release 15" ./archives/basic_sim/ue_ip.Rel15.txt "Built target ue_ip" ./basic_sim_row11.html - summary_table_row "USIM - Release 15" ./archives/basic_sim/usim.Rel15.txt "Built target usim" ./basic_sim_row12.html - summary_table_row "NVRAM - Release 15" ./archives/basic_sim/nvram.Rel15.txt "Built target nvram" ./basic_sim_row13.html - summary_table_footer - - summary_table_header "OAI Build: 4G LTE / 5G NR Physical simulators option" ./archives/phy_sim - summary_table_row "LTE DL Simulator - Release 15" ./archives/phy_sim/dlsim.Rel15.txt "Built target dlsim" ./phy_sim_row1.html - summary_table_row "LTE UL Simulator - Release 15" ./archives/phy_sim/ulsim.Rel15.txt "Built target ulsim" ./phy_sim_row2.html - summary_table_row "Coding - Release 15" ./archives/phy_sim/coding.Rel15.txt "Built target coding" ./phy_sim_row3.html - if [ -f ./archives/phy_sim/ldpctest.Rel15.txt ] - then - summary_table_row "NR LDPC Test - Release 15" ./archives/phy_sim/ldpctest.Rel15.txt "Built target ldpctest" ./phy_sim_row4.html - fi - if [ -f ./archives/phy_sim/polartest.Rel15.txt ] - then - summary_table_row "NR Polar Test - Release 15" ./archives/phy_sim/polartest.Rel15.txt "Built target polartest" ./phy_sim_row5.html - fi - if [ -f ./archives/phy_sim/nr_pbchsim.Rel15.txt ] - then - summary_table_row "NR PBCH Test - Release 15" ./archives/phy_sim/nr_pbchsim.Rel15.txt "Built target nr_pbchsim" ./phy_sim_row6.html - fi - if [ -f ./archives/phy_sim/nr_dlschsim.Rel15.txt ] - then - summary_table_row "NR DLSCH Test - Release 15" ./archives/phy_sim/nr_dlschsim.Rel15.txt "Built target nr_dlschsim" ./phy_sim_row7.html - fi - if [ -f ./archives/phy_sim/nr_pucchsim.Rel15.txt ] - then - summary_table_row "NR PUCCH Test - Release 15" ./archives/phy_sim/nr_pucchsim.Rel15.txt "Built target nr_pucchsim" ./phy_sim_row8.html - fi - if [ -f ./archives/phy_sim/smallblocktest.Rel15.txt ] - then - summary_table_row "NR Small Block Test - Release 15" ./archives/phy_sim/smallblocktest.Rel15.txt "Built target smallblocktest" ./phy_sim_row9.html - fi - if [ -f ./archives/phy_sim/nr_dlsim.Rel15.txt ] - then - summary_table_row "NR DL Sim Test - Release 15" ./archives/phy_sim/nr_dlsim.Rel15.txt "Built target nr_dlsim" ./phy_sim_row10.html - fi - if [ -f ./archives/phy_sim/nr_ulschsim.Rel15.txt ] - then - summary_table_row "NR ULSCH Test - Release 15" ./archives/phy_sim/nr_ulschsim.Rel15.txt "Built target nr_ulschsim" ./phy_sim_row11.html - fi - if [ -f ./archives/phy_sim/nr_ulsim.Rel15.txt ] - then - summary_table_row "NR UL Sim Test - Release 15" ./archives/phy_sim/nr_ulsim.Rel15.txt "Built target nr_ulsim" ./phy_sim_row12.html - fi - summary_table_footer - - if [ -f archives/gnb_usrp/nr-softmodem.Rel15.txt ] - then - summary_table_header "OAI Build: 5G NR gNB -- USRP option" ./archives/gnb_usrp - summary_table_row "5G NR SoftModem - Release 15" ./archives/gnb_usrp/nr-softmodem.Rel15.txt "Built target nr-softmodem" ./gnb_usrp_row1.html - summary_table_row "Coding - Release 15" ./archives/gnb_usrp/coding.Rel15.txt "Built target coding" ./gnb_usrp_row2.html - summary_table_row "OAI USRP device if - Release 15" ./archives/gnb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./gnb_usrp_row3.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/gnb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./gnb_usrp_row4.html - summary_table_row "NASMESH - Release 15" ./archives/gnb_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./gnb_usrp_row5.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/gnb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./gnb_usrp_row6.html - summary_table_row "RB Tool - Release 15" ./archives/gnb_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./gnb_usrp_row7.html - summary_table_footer - fi - - if [ -f archives/nr_ue_usrp/nr-uesoftmodem.Rel15.txt ] - then - summary_table_header "OAI Build: 5G NR UE -- USRP option" ./archives/nr_ue_usrp - summary_table_row "5G NR UE SoftModem - Release 15" ./archives/nr_ue_usrp/nr-uesoftmodem.Rel15.txt "Built target nr-uesoftmodem" ./nr_ue_usrp_row1.html - summary_table_row "Coding - Release 15" ./archives/nr_ue_usrp/coding.Rel15.txt "Built target coding" ./nr_ue_usrp_row2.html - summary_table_row "OAI USRP device if - Release 15" ./archives/nr_ue_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./nr_ue_usrp_row3.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/nr_ue_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./nr_ue_usrp_row4.html - summary_table_row "NASMESH - Release 15" ./archives/nr_ue_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./nr_ue_usrp_row5.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/nr_ue_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./nr_ue_usrp_row6.html - summary_table_row "RB Tool - Release 15" ./archives/nr_ue_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./nr_ue_usrp_row7.html - summary_table_footer - fi - - summary_table_header "OAI Build: 4G LTE eNB -- ETHERNET transport option" ./archives/enb_eth + summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_eth summary_table_row "LTE SoftModem - Release 15" ./archives/enb_eth/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_eth_row1.html summary_table_row "Coding - Release 15" ./archives/enb_eth/coding.Rel15.txt "Built target coding" ./enb_eth_row2.html summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_eth_row3.html summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_eth_row4.html summary_table_row "RF Simulator - Release 15" ./archives/enb_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_eth_row5.html summary_table_row "TCP OAI Bridge - Release 15" ./archives/enb_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_eth_row6.html + summary_table_row "OAI USRP device if - Release 15" ./archives/enb_eth/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_eth_row7.html summary_table_footer - summary_table_header "OAI Build: 4G LTE UE -- ETHERNET transport option" ./archives/ue_eth + summary_table_header "OAI Build: 4G LTE UE -- USRP option" ./archives/ue_eth summary_table_row "LTE UE SoftModem - Release 15" ./archives/ue_eth/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./ue_eth_row1.html summary_table_row "Coding - Release 15" ./archives/ue_eth/coding.Rel15.txt "Built target coding" ./ue_eth_row2.html summary_table_row "OAI ETHERNET transport - Release 15" ./archives/ue_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./ue_eth_row3.html @@ -696,8 +589,45 @@ function report_build { summary_table_row "NVRAM - Release 15" ./archives/ue_eth/nvram.Rel15.txt "Built target nvram" ./ue_eth_row8.html summary_table_row "UE IP - Release 15" ./archives/ue_eth/ue_ip.Rel15.txt "Built target ue_ip" ./ue_eth_row9.html summary_table_row "USIM - Release 15" ./archives/ue_eth/usim.Rel15.txt "Built target usim" ./ue_eth_row9a.html + summary_table_row "OAI USRP device if - Release 15" ./archives/ue_eth/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./ue_eth_row9b.html summary_table_footer + summary_table_header "OAI Build: 4G LTE basic simulator option" ./archives/basic_sim + summary_table_row "LTE SoftModem - Release 15" ./archives/basic_sim/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./basic_sim_row1.html + summary_table_row "LTE UE SoftModem - Release 15" ./archives/basic_sim/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./basic_sim_row2.htm + summary_table_row "Coding - Release 15" ./archives/basic_sim/coding.Rel15.txt "Built target coding" ./basic_sim_row3.html + summary_table_row "Conf 2 UE data - Release 15" ./archives/basic_sim/conf2uedata.Rel15.txt "Built target conf2uedata" ./basic_sim_row4.html + summary_table_row "OAI ETHERNET transport - Release 15" ./archives/basic_sim/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./basic_sim_row5.html + summary_table_row "Parameters Lib Config - Release 15" ./archives/basic_sim/params_libconfig.Rel15.txt "Built target params_libconfig" ./basic_sim_row7.html + summary_table_row "RF Simulator - Release 15" ./archives/basic_sim/rfsimulator.Rel15.txt "Built target rfsimulator" ./basic_sim_row9.html + summary_table_row "TCP Bridge - Release 15" ./archives/basic_sim/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./basic_sim_row10.html + summary_table_row "UE IP - Release 15" ./archives/basic_sim/ue_ip.Rel15.txt "Built target ue_ip" ./basic_sim_row11.html + summary_table_row "USIM - Release 15" ./archives/basic_sim/usim.Rel15.txt "Built target usim" ./basic_sim_row12.html + summary_table_row "NVRAM - Release 15" ./archives/basic_sim/nvram.Rel15.txt "Built target nvram" ./basic_sim_row13.html + summary_table_footer + + if [ -f archives/gnb_usrp/nr-softmodem.Rel15.txt ] + then + summary_table_header "OAI Build: 5G NR gNB -- USRP option" ./archives/gnb_usrp + summary_table_row "5G NR SoftModem - Release 15" ./archives/gnb_usrp/nr-softmodem.Rel15.txt "Built target nr-softmodem" ./gnb_usrp_row1.html + summary_table_row "Coding - Release 15" ./archives/gnb_usrp/coding.Rel15.txt "Built target coding" ./gnb_usrp_row2.html + summary_table_row "OAI USRP device if - Release 15" ./archives/gnb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./gnb_usrp_row3.html + summary_table_row "OAI ETHERNET transport - Release 15" ./archives/gnb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./gnb_usrp_row4.html + summary_table_row "Parameters Lib Config - Release 15" ./archives/gnb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./gnb_usrp_row6.html + summary_table_footer + fi + + if [ -f archives/nr_ue_usrp/nr-uesoftmodem.Rel15.txt ] + then + summary_table_header "OAI Build: 5G NR UE -- USRP option" ./archives/nr_ue_usrp + summary_table_row "5G NR UE SoftModem - Release 15" ./archives/nr_ue_usrp/nr-uesoftmodem.Rel15.txt "Built target nr-uesoftmodem" ./nr_ue_usrp_row1.html + summary_table_row "Coding - Release 15" ./archives/nr_ue_usrp/coding.Rel15.txt "Built target coding" ./nr_ue_usrp_row2.html + summary_table_row "OAI USRP device if - Release 15" ./archives/nr_ue_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./nr_ue_usrp_row3.html + summary_table_row "OAI ETHERNET transport - Release 15" ./archives/nr_ue_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./nr_ue_usrp_row4.html + summary_table_row "Parameters Lib Config - Release 15" ./archives/nr_ue_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./nr_ue_usrp_row6.html + summary_table_footer + fi + if [ -e ./archives/red_hat ] then echo "

Red Hat Enterprise Linux Server release 7.6) -- Summary

" >> ./build_results.html @@ -714,9 +644,16 @@ function report_build { echo " " >> ./build_results.html echo "
" >> ./build_results.html - if [ -f ./enb_usrp_row1.html ] || [ -f ./enb_usrp_row2.html ] || [ -f ./enb_usrp_row3.html ] || [ -f ./enb_usrp_row4.html ] + if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ] || [ -f ./enb_eth_row7.html ] then - for DETAILS_TABLE in `ls ./enb_usrp_row*.html` + for DETAILS_TABLE in `ls ./enb_eth_row*.html` + do + cat $DETAILS_TABLE >> ./build_results.html + done + fi + if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ] || [ -f ./ue_eth_row7.html ] || [ -f ./ue_eth_row8.html ] || [ -f ./ue_eth_row9.html ] || [ -f ./ue_eth_row9a.html ] || [ -f ./ue_eth_row9b.html ] + then + for DETAILS_TABLE in `ls ./ue_eth_row*.html` do cat $DETAILS_TABLE >> ./build_results.html done @@ -728,13 +665,6 @@ function report_build { cat $DETAILS_TABLE >> ./build_results.html done fi - if [ -f ./phy_sim_row1.html ] || [ -f ./phy_sim_row2.html ] || [ -f ./phy_sim_row3.html ] || [ -f ./phy_sim_row4.html ] || [ -f ./phy_sim_row5.html ] || [ -f ./phy_sim_row6.html ] || [ -f ./phy_sim_row7.html ] || [ -f ./phy_sim_row8.html ] - then - for DETAILS_TABLE in `ls ./phy_sim_row*.html` - do - cat $DETAILS_TABLE >> ./build_results.html - done - fi if [ -f ./gnb_usrp_row1.html ] || [ -f ./gnb_usrp_row2.html ] || [ -f ./gnb_usrp_row3.html ] || [ -f ./gnb_usrp_row4.html ] then for DETAILS_TABLE in `ls ./gnb_usrp_row*.html` @@ -749,27 +679,6 @@ function report_build { cat $DETAILS_TABLE >> ./build_results.html done fi - if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ] - then - for DETAILS_TABLE in `ls ./enb_eth_row*.html` - do - cat $DETAILS_TABLE >> ./build_results.html - done - fi - if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ] - then - for DETAILS_TABLE in `ls ./ue_eth_row*.html` - do - cat $DETAILS_TABLE >> ./build_results.html - done - fi - if [ -f ./enb_usrp_rh_row1.html ] || [ -f ./enb_usrp_rh_row2.html ] || [ -f ./enb_usrp_rh_row3.html ] || [ -f ./enb_usrp_rh_row4.html ] - then - for DETAILS_TABLE in `ls ./enb_usrp_rh_row*.html` - do - cat $DETAILS_TABLE >> ./build_results.html - done - fi rm -f ./*_row*.html echo "
" >> ./build_results.html diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh index b05ccf39db..19fac7fd78 100755 --- a/ci-scripts/reportTestLocally.sh +++ b/ci-scripts/reportTestLocally.sh @@ -309,14 +309,14 @@ function report_test { NB_ENB_GOT_SYNC=`egrep -c "got sync" $ENB_LOG` NB_UE_GOT_SYNC=`egrep -c "got sync" $UE_LOG` NB_ENB_SYNCED_WITH_UE=`egrep -c "got UE capabilities for UE" $ENB_LOG` - if [ $NB_ENB_GOT_SYNC -eq 1 ] && [ $NB_UE_GOT_SYNC -eq 2 ] && [ $NB_ENB_SYNCED_WITH_UE -eq 1 ] + if [ $NB_ENB_GOT_SYNC -gt 0 ] && [ $NB_UE_GOT_SYNC -eq 2 ] && [ $NB_ENB_SYNCED_WITH_UE -eq 1 ] then echo " OK" >> ./test_simulator_results.html else echo " KO" >> ./test_simulator_results.html fi echo "
" >> ./test_simulator_results.html
-                    if [ $NB_ENB_GOT_SYNC -eq 1 ]
+                    if [ $NB_ENB_GOT_SYNC -gt 0 ]
                     then
                         echo "- eNB --> got sync" >> ./test_simulator_results.html
                     else
@@ -470,7 +470,7 @@ function report_test {
                     then
                         NB_UE_TUNNEL_UP=`egrep -c "Interface oaitun_ue1 successfully configured" $UE_LOG`
                     else
-                        NB_UE_TUNNEL_UP=`egrep -c "executing ifconfig oaitun_ue1" $UE_LOG`
+                        NB_UE_TUNNEL_UP=`egrep -c "ip link set oaitun_ue1 up" $UE_LOG`
                     fi
                     if [ $NB_ENB_GOT_SYNC -gt 0 ] && [ $NB_UE_GOT_SYNC -gt 0 ] && [ $NB_ENB_SYNCED_WITH_UE -gt 0 ]
                     then
@@ -717,7 +717,11 @@ function report_test {
         done
         echo "   " >> ./test_simulator_results.html
         echo "   " >> ./test_simulator_results.html
+    fi
 
+    ARCHIVES_LOC=archives/rf5g_sim/test
+    if [ -d $ARCHIVES_LOC ]
+    then
         echo "   

5G NR RF Simulator Check

" >> ./test_simulator_results.html if [ -f $ARCHIVES_LOC/test_final_status.log ] @@ -748,8 +752,10 @@ function report_test { echo " Statistics" >> ./test_simulator_results.html echo " " >> ./test_simulator_results.html + #SA EPC_CONFIGS=("noS1") TRANS_MODES=("tdd") + FR_MODE=("SA") BW_CASES=(106) for CN_CONFIG in ${EPC_CONFIGS[@]} do @@ -760,11 +766,203 @@ function report_test { echo " " >> ./test_simulator_results.html if [[ $CN_CONFIG =~ .*wS1.* ]] then - echo " Test with EPC (aka withS1): ${TMODE} -- ${BW}PRB " >> ./test_simulator_results.html + echo " Test with CN5G : ${TMODE} -- ${BW}PRB -- ${FR_MODE}" >> ./test_simulator_results.html else - echo " Test without EPC (aka noS1): ${TMODE} -- ${BW}PRB " >> ./test_simulator_results.html + echo " Test without CN5G : ${TMODE} -- ${BW}PRB -- ${FR_MODE}" >> ./test_simulator_results.html fi echo " " >> ./test_simulator_results.html + + + #SA test (--sa option) + + SA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_sa_test.log + SA_UE_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_ue_sa_test.log + if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ] + then + #get rid of full path + NAME_ENB=`echo $SA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"` + NAME_UE=`echo $SA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"` + echo " " >> ./test_simulator_results.html + echo " $NAME_ENB --- $NAME_UE" >> ./test_simulator_results.html + echo " Check if SA proc succeeded" >> ./test_simulator_results.html + + + RRC_CHECK=`egrep -c "Received rrcSetupComplete" $SA_ENB_LOG` + CBRA_CHECK=`egrep -c "Received Ack of RA-Msg4\. CBRA procedure succeeded" $SA_ENB_LOG` + SIB1_CHECK=`egrep -c "SIB1 decoded" $SA_UE_LOG` + + + if [ $RRC_CHECK -gt 0 ] && [ $CBRA_CHECK -gt 0 ] && [ $SIB1_CHECK -gt 0 ] + then + echo " OK" >> ./test_simulator_results.html + else + echo " KO" >> ./test_simulator_results.html + fi + + echo "
" >> ./test_simulator_results.html
+                    if [ $RRC_CHECK -gt 0 ]
+                    then
+                        echo "- Received rrcSetupComplete OK" >> ./test_simulator_results.html
+                    else
+                        echo "- Received rrcSetupComplete KO" >> ./test_simulator_results.html
+                    fi
+                    if [ $CBRA_CHECK -gt 0 ]
+                    then
+                        echo "- CBRA procedure succeeded OK" >> ./test_simulator_results.html
+                    else
+                        echo "- CBRA procedure succeeded KO" >> ./test_simulator_results.html
+                    fi
+                    if [ $SIB1_CHECK -gt 0 ]
+                    then
+                        echo "- SIB1 decoded OK" >> ./test_simulator_results.html
+                    else
+                        echo "- SIB1 decoded KO" >> ./test_simulator_results.html
+                    fi
+
+                    echo "        
" >> ./test_simulator_results.html + echo " " >> ./test_simulator_results.html + fi + + done + done + done + + + EPC_CONFIGS=("noS1") + TRANS_MODES=("tdd") + FR_MODE=("FR2") + BW_CASES=(32) + for CN_CONFIG in ${EPC_CONFIGS[@]} + do + for TMODE in ${TRANS_MODES[@]} + do + for BW in ${BW_CASES[@]} + do + echo " " >> ./test_simulator_results.html + if [[ $CN_CONFIG =~ .*wS1.* ]] + then + echo " Test with CN5G : ${TMODE} -- ${BW}PRB -- ${FR_MODE}" >> ./test_simulator_results.html + else + echo " Test without CN5G : ${TMODE} -- ${BW}PRB -- ${FR_MODE}" >> ./test_simulator_results.html + fi + echo " " >> ./test_simulator_results.html + + + #FR2 RA test (--do-ra option) + + #build log files names tdd_${PRB}prb_${CN_CONFIG}_gnb_ra_fr2_test.log + + RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_fr2_test.log + RA_UE_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_fr2_test.log + if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ] + then + #get rid of full path + NAME_ENB=`echo $RA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"` + NAME_UE=`echo $RA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"` + echo " " >> ./test_simulator_results.html + echo " $NAME_ENB --- $NAME_UE" >> ./test_simulator_results.html + echo " Check if FR2 RA proc succeeded" >> ./test_simulator_results.html + + #gNB RA check + GNB_RECEIVED=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $RA_ENB_LOG` + #UE RA check + UE_RA_PROC_OK=`egrep -c "\[RAPROC\] RA procedure succeeded" $RA_UE_LOG` + + + if [ $GNB_RECEIVED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ] + then + echo " OK" >> ./test_simulator_results.html + else + echo " KO" >> ./test_simulator_results.html + fi + + echo "
" >> ./test_simulator_results.html
+                    if [ $GNB_RECEIVED -gt 0 ]
+                    then
+                        echo "- gNB --> RA received" >> ./test_simulator_results.html
+                    else
+                        echo "- gNB RA NOT RECEIVED" >> ./test_simulator_results.html
+                    fi
+                    if [ $UE_RA_PROC_OK -gt 0 ]
+                    then
+                        echo "- NR UE  --> RA procedure succeded" >> ./test_simulator_results.html
+                    else
+                        echo "- NR UE RA procedure failed" >> ./test_simulator_results.html
+                    fi
+                    echo "        
" >> ./test_simulator_results.html + echo " " >> ./test_simulator_results.html + fi + + done + done + done + + + EPC_CONFIGS=("noS1") + FR_MODE=("FR1") + TRANS_MODES=("fdd" "tdd") + BW_CASES=(106) + for CN_CONFIG in ${EPC_CONFIGS[@]} + do + for TMODE in ${TRANS_MODES[@]} + do + for BW in ${BW_CASES[@]} + do + echo " " >> ./test_simulator_results.html + if [[ $CN_CONFIG =~ .*wS1.* ]] + then + echo " Test with CN5G : ${TMODE} -- ${BW}PRB -- ${FR_MODE}" >> ./test_simulator_results.html + else + echo " Test without CN5G : ${TMODE} -- ${BW}PRB -- ${FR_MODE}" >> ./test_simulator_results.html + fi + echo " " >> ./test_simulator_results.html + + + #FR1 RA test (--do-ra option) + + #build log files names + RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_test.log + RA_UE_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log + if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ] + then + #get rid of full path + NAME_ENB=`echo $RA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"` + NAME_UE=`echo $RA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"` + echo " " >> ./test_simulator_results.html + echo " $NAME_ENB --- $NAME_UE" >> ./test_simulator_results.html + echo " Check if FR1 RA proc succeeded" >> ./test_simulator_results.html + + #gNB RA check + GNB_RECEIVED=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $RA_ENB_LOG` + #UE RA check + UE_RA_PROC_OK=`egrep -c "\[RAPROC\] RA procedure succeeded" $RA_UE_LOG` + + + if [ $GNB_RECEIVED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ] + then + echo " OK" >> ./test_simulator_results.html + else + echo " KO" >> ./test_simulator_results.html + fi + + echo "
" >> ./test_simulator_results.html
+                    if [ $GNB_RECEIVED -gt 0 ]
+                    then
+                        echo "- gNB --> RA received" >> ./test_simulator_results.html
+                    else
+                        echo "- gNB RA NOT RECEIVED" >> ./test_simulator_results.html
+                    fi
+                    if [ $UE_RA_PROC_OK -gt 0 ]
+                    then
+                        echo "- NR UE  --> RA procedure succeded" >> ./test_simulator_results.html
+                    else
+                        echo "- NR UE RA procedure failed" >> ./test_simulator_results.html
+                    fi
+                    echo "        
" >> ./test_simulator_results.html + echo " " >> ./test_simulator_results.html + fi + + #SYNC test ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb.log UE_LOG=`echo $ENB_LOG | sed -e "s#gnb#ue#"` if [ -f $ENB_LOG ] && [ -f $UE_LOG ] diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index b9b9a2bafa..de696cdc64 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -276,6 +276,83 @@ function check_ping_result { fi } + +function check_sa_result { + local LOC_GNB_LOG=$1 + local LOC_UE_LOG=$2 + + #if log files exist + if [ -f $LOC_GNB_LOG ] && [ -f $LOC_UE_LOG ] + then + + #gNB SA test + #console check + echo "Checking gNB Log for SA success" + egrep "Received rrcSetupComplete" $1 + egrep "Received Ack of RA-Msg4\. CBRA procedure succeeded" $1 + + #script check + local RRC_CHECK=`egrep -c "Received rrcSetupComplete" $1` + local CBRA_CHECK=`egrep -c "Received Ack of RA-Msg4\. CBRA procedure succeeded" $1` + + #UE SA test + #console check + echo 'Checking UE Log for SA success' + egrep "SIB1 decoded" $2 + #script check + local SIB1_CHECK=`egrep -c "SIB1 decoded" $2` + + #generate status + if [ $RRC_CHECK -eq 0 ] || [ $CBRA_CHECK -eq 0 ] || [ $SIB1_CHECK -eq 0 ] + then + SA_STATUS=-1 + echo "SA test FAILED, could not find the markers" + fi + #case where log files do not exist + else + echo "SA test log files not present" + SA_STATUS=-1 + fi + +} + + +function check_ra_result { + local LOC_GNB_LOG=$1 + local LOC_UE_LOG=$2 + + #if log files exist + if [ -f $LOC_GNB_LOG ] && [ -f $LOC_UE_LOG ] + then + + #gNB RA test + #console check + echo "Checking gNB Log for RA success" + egrep "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1 + #script check + local GNB_COMPLETE=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1` + + #UE RA test + #console check + echo 'Checking UE Log for RA success' + egrep "\[RAPROC\] RA procedure succeeded" $2 + #script check + local UE_COMPLETE=`egrep -c "\[RAPROC\] RA procedure succeeded" $2` + + #generate status + if [ $GNB_COMPLETE -eq 0 ] || [ $UE_COMPLETE -eq 0 ] + then + RA_STATUS=-1 + echo "RA test FAILED, could not find the markers" + fi + #case where log files do not exist + else + echo "RA test log files not present" + RA_STATUS=-1 + fi + +} + # In DL: iperf server should be on UE side # -B oaitun_ue{j}-IP-Addr # iperf client should be on EPC (S1) or eNB (noS1) side @@ -342,7 +419,7 @@ function check_iperf { local LOC_IS_DL=`echo $LOC_BASE_LOG | grep -c _dl` local LOC_IS_BASIC_SIM=`echo $LOC_BASE_LOG | grep -c basic_sim` local LOC_IS_RF_SIM=`echo $LOC_BASE_LOG | grep -c rf_sim` - local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c tdd_106prb` + local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c _106prb` if [ -f ${LOC_BASE_LOG}_client.txt ] then local FILE_COMPLETE=`egrep -c "Server Report" ${LOC_BASE_LOG}_client.txt` @@ -927,6 +1004,12 @@ function start_l2_sim_ue { echo "ifconfig" > $1 ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_UE_VM_IP_ADDR < $1 rm $1 + else + echo "Setting Routes for all UEs" + echo "cd /home/ubuntu/tmp/cmake_targets/tools" > $1 + echo "./setup_routes.sh $LOC_NB_UES" >> $1 + ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_UE_VM_IP_ADDR < $1 + rm $1 fi } @@ -1172,6 +1255,8 @@ function start_rf_sim_gnb { local LOC_CONF_FILE=$5 # 1 is with S1 and 0 without S1 aka noS1 local LOC_S1_CONFIGURATION=$6 + #LOC_RA_SA_TEST=1 will run the RA test check ; =2 will run the SA test + local LOC_RA_SA_TEST=$7 if [ -e rbconfig.raw ]; then rm -f rbconfig.raw; fi if [ -e reconfig.raw ]; then rm -f reconfig.raw; fi @@ -1181,6 +1266,8 @@ function start_rf_sim_gnb { echo "sudo apt-get --yes install daemon >> /home/ubuntu/tmp/cmake_targets/log/daemon-install.txt 2>&1" >> $1 echo "echo \"source oaienv\"" >> $1 echo "source oaienv" >> $1 + echo "echo \"export RFSIMULATOR=server\"" >> $1 + echo "export RFSIMULATOR=server" >> $1 echo "cd ci-scripts/conf_files/" >> $1 echo "cp $LOC_CONF_FILE ci-$LOC_CONF_FILE" >> $1 #echo "sed -i -e 's#N_RB_DL.*=.*;#N_RB_DL = $LOC_NB_RBS;#' -e 's#CI_MME_IP_ADDR#$LOC_EPC_IP_ADDR#' -e 's#CI_ENB_IP_ADDR#$LOC_ENB_VM_IP_ADDR#' -e 's#CI_UE_IP_ADDR#$LOC_UE_VM_IP_ADDR#' ci-$LOC_CONF_FILE" >> $1 @@ -1192,7 +1279,15 @@ function start_rf_sim_gnb { echo "sudo rm -f r*config.raw" >> $1 if [ $LOC_S1_CONFIGURATION -eq 0 ] then - echo "echo \"RFSIMULATOR=server ./nr-softmodem -O /home/ubuntu/tmp/ci-scripts/conf_files/ci-$LOC_CONF_FILE --log_config.global_log_options level,nocolor --parallel-config PARALLEL_SINGLE_THREAD --noS1 --nokrnmod 1 --rfsim --phy-test\" > ./my-nr-softmodem-run.sh " >> $1 + if [ $LOC_RA_SA_TEST -eq 0 ] #no RA test => use --phy-test option + then + echo "echo \"./nr-softmodem -O /home/ubuntu/tmp/ci-scripts/conf_files/ci-$LOC_CONF_FILE --log_config.global_log_options level,nocolor --parallel-config PARALLEL_SINGLE_THREAD --noS1 --nokrnmod 1 --rfsim --phy-test --lowmem --noS1\" > ./my-nr-softmodem-run.sh " >> $1 + elif [ $LOC_RA_SA_TEST -eq 1 ] #RA test => use --do-ra option + then + echo "echo \"./nr-softmodem -O /home/ubuntu/tmp/ci-scripts/conf_files/ci-$LOC_CONF_FILE --log_config.global_log_options level,nocolor --parallel-config PARALLEL_SINGLE_THREAD --rfsim --do-ra --lowmem --noS1\" > ./my-nr-softmodem-run.sh " >> $1 + else #SA test => use --sa option + echo "echo \"./nr-softmodem -O /home/ubuntu/tmp/ci-scripts/conf_files/ci-$LOC_CONF_FILE --log_config.global_log_options level,nocolor --parallel-config PARALLEL_SINGLE_THREAD --rfsim --sa --lowmem \" > ./my-nr-softmodem-run.sh " >> $1 + fi fi echo "chmod 775 ./my-nr-softmodem-run.sh" >> $1 echo "cat ./my-nr-softmodem-run.sh" >> $1 @@ -1202,6 +1297,7 @@ function start_rf_sim_gnb { ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1 rm $1 + local i="0" echo "egrep -c \"got sync\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1 while [ $i -lt 10 ] @@ -1224,7 +1320,9 @@ function start_rf_sim_gnb { GNB_SYNC=1 echo "RF-SIM gNB is sync'ed: waiting for UE(s) to connect" fi - if [ $LOC_S1_CONFIGURATION -eq 0 ] + + # check noS1 config only outside RA test (as it does not support noS1) + if [ $LOC_S1_CONFIGURATION -eq 0 ] && [ $LOC_RA_SA_TEST -eq 0 ] then echo "ifconfig oaitun_enb1 | egrep -c \"inet addr\"" > $1 # Checking oaitun_enb1 interface has now an IP address @@ -1249,14 +1347,19 @@ function start_rf_sim_gnb { echo "RF-SIM gNB oaitun_enb1 is UP and CONFIGURED" fi fi + + sleep 10 echo "echo \"free -m\"" > $1 echo "free -m" >> $1 ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1 rm $1 # Copy the RAW files from the gNB run for the NR-UE - scp -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/ran_build/build/rbconfig.raw . - scp -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/ran_build/build/reconfig.raw . + if [ $LOC_RA_SA_TEST -ne 2 ] + then + scp -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/ran_build/build/rbconfig.raw . + scp -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/ran_build/build/reconfig.raw . + fi } function start_rf_sim_nr_ue { @@ -1267,21 +1370,40 @@ function start_rf_sim_nr_ue { local LOC_FREQUENCY=$6 # 1 is with S1 and 0 without S1 aka noS1 local LOC_S1_CONFIGURATION=$7 + #LOC_RA_SA_TEST=1 will run the RA test check ; =2 will run the SA test + local LOC_RA_SA_TEST=$8 # Copy the RAW files from the gNB run - scp -o StrictHostKeyChecking=no rbconfig.raw ubuntu@$LOC_NR_UE_VM_IP_ADDR:/home/ubuntu/tmp - scp -o StrictHostKeyChecking=no reconfig.raw ubuntu@$LOC_NR_UE_VM_IP_ADDR:/home/ubuntu/tmp + if [ $LOC_RA_SA_TEST -ne 2 ] + then + scp -o StrictHostKeyChecking=no rbconfig.raw ubuntu@$LOC_NR_UE_VM_IP_ADDR:/home/ubuntu/tmp + scp -o StrictHostKeyChecking=no reconfig.raw ubuntu@$LOC_NR_UE_VM_IP_ADDR:/home/ubuntu/tmp + fi echo "echo \"sudo apt-get --yes --quiet install daemon \"" > $1 echo "sudo apt-get --yes install daemon >> /home/ubuntu/tmp/cmake_targets/log/daemon-install.txt 2>&1" >> $1 + echo "echo \"export RFSIMULATOR=${LOC_GNB_VM_IP_ADDR}\"" >> $1 + echo "export RFSIMULATOR=${LOC_GNB_VM_IP_ADDR}" >> $1 echo "echo \"cd /home/ubuntu/tmp/cmake_targets/ran_build/build/\"" >> $1 echo "sudo chmod 777 /home/ubuntu/tmp/cmake_targets/ran_build/build/" >> $1 - echo "sudo cp /home/ubuntu/tmp/r*config.raw /home/ubuntu/tmp/cmake_targets/ran_build/build/" >> $1 - echo "sudo chmod 666 /home/ubuntu/tmp/cmake_targets/ran_build/build/r*config.raw" >> $1 + echo "sudo rm -f /home/ubuntu/tmp/cmake_targets/ran_build/build/r*config.raw" >> $1 + if [ $LOC_RA_SA_TEST -ne 2 ] + then + echo "sudo cp /home/ubuntu/tmp/r*config.raw /home/ubuntu/tmp/cmake_targets/ran_build/build/" >> $1 + echo "sudo chmod 666 /home/ubuntu/tmp/cmake_targets/ran_build/build/r*config.raw" >> $1 + fi echo "cd /home/ubuntu/tmp/cmake_targets/ran_build/build/" >> $1 if [ $LOC_S1_CONFIGURATION -eq 0 ] then - echo "echo \"RFSIMULATOR=${LOC_GNB_VM_IP_ADDR} ./nr-uesoftmodem --nokrnmod 1 --rfsim --phy-test --rrc_config_path /home/ubuntu/tmp/cmake_targets/ran_build/build/ --log_config.global_log_options level,nocolor --noS1\" > ./my-nr-softmodem-run.sh " >> $1 + if [ $LOC_RA_SA_TEST -eq 0 ] #no RA test => use --phy-test option + then + echo "echo \"./nr-uesoftmodem --nokrnmod 1 --rfsim --phy-test --rrc_config_path /home/ubuntu/tmp/cmake_targets/ran_build/build/ --log_config.global_log_options level,nocolor --noS1\" > ./my-nr-softmodem-run.sh " >> $1 + elif [ $LOC_RA_SA_TEST -eq 1 ] #RA test => use --do-ra option + then + echo "echo \"./nr-uesoftmodem --rfsim --do-ra --log_config.global_log_options level,nocolor --rrc_config_path /home/ubuntu/tmp/cmake_targets/ran_build/build/\" > ./my-nr-softmodem-run.sh " >> $1 + else #SA test => use --sa option + echo "echo \"./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --log_config.global_log_options level,nocolor\" > ./my-nr-softmodem-run.sh " >> $1 + fi fi echo "chmod 775 ./my-nr-softmodem-run.sh" >> $1 echo "cat ./my-nr-softmodem-run.sh" >> $1 @@ -1314,11 +1436,13 @@ function start_rf_sim_nr_ue { else echo "RF-SIM NR-UE is sync'ed w/ gNB" fi - # Checking oaitun_ue1 interface has now an IP address - i="0" - echo "ifconfig oaitun_ue1 | egrep -c \"inet addr\"" > $1 - while [ $i -lt 10 ] - do + # Checking oaitun_ue1 interface has now an IP address (only outside RA test) + if [ $LOC_RA_SA_TEST -eq 0 ] + then + i="0" + echo "ifconfig oaitun_ue1 | egrep -c \"inet addr\"" > $1 + while [ $i -lt 10 ] + do sleep 5 CONNECTED=`ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1` if [ $CONNECTED -eq 1 ] @@ -1327,19 +1451,20 @@ function start_rf_sim_nr_ue { else i=$[$i+1] fi - done - echo "echo \"free -m\"" > $1 - echo "free -m" >> $1 - ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1 - rm $1 - if [ $i -lt 50 ] - then + done + echo "echo \"free -m\"" > $1 + echo "free -m" >> $1 + ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1 + rm $1 + if [ $i -lt 50 ] + then NR_UE_SYNC=0 echo "RF-SIM NR-UE oaitun_ue1 is DOWN or NOT CONFIGURED" - else + else echo "RF-SIM NR-UE oaitun_ue1 is UP and CONFIGURED" - fi - sleep 10 + fi + sleep 10 + fi } @@ -1357,11 +1482,13 @@ function run_test_on_vm { UE_VM_CMDS=${UE_VM_NAME}_cmds.txt echo "UE_VM_NAME = $UE_VM_NAME" echo "UE_VM_CMD_FILE = $UE_VM_CMDS" - GNB_VM_NAME=`echo $VM_NAME | sed -e "s#l2-sim#gnb-usrp#" -e "s#rf-sim#gnb-usrp#"` + elif [[ (( "$RUN_OPTIONS" == "complex" ) && ( $VM_NAME =~ .*-rf5g-sim.* )) ]] + then + GNB_VM_NAME=`echo $VM_NAME | sed -e "s#rf5g-sim#gnb-usrp#"` GNB_VM_CMDS=${GNB_VM_NAME}_cmds.txt echo "GNB_VM_NAME = $GNB_VM_NAME" echo "GNB_VM_CMD_FILE = $GNB_VM_CMDS" - NR_UE_VM_NAME=`echo $VM_NAME | sed -e "s#l2-sim#nr-ue-usrp#" -e "s#rf-sim#nr-ue-usrp#"` + NR_UE_VM_NAME=`echo $VM_NAME | sed -e "s#rf5g-sim#nr-ue-usrp#"` NR_UE_VM_CMDS=${UE_VM_NAME}_cmds.txt echo "NR_UE_VM_NAME = $NR_UE_VM_NAME" echo "NR_UE_VM_CMD_FILE = $NR_UE_VM_CMDS" @@ -1390,6 +1517,8 @@ function run_test_on_vm { UE_VM_IP_ADDR=`uvt-kvm ip $UE_VM_NAME` echo "$UE_VM_NAME has for IP addr = $UE_VM_IP_ADDR" + elif [[ (( "$RUN_OPTIONS" == "complex" ) && ( $VM_NAME =~ .*-rf5g-sim.* )) ]] + then echo "############################################################" echo "Waiting for GNB VM to be started" echo "############################################################" @@ -1415,13 +1544,13 @@ function run_test_on_vm { echo "$VM_NAME has for IP addr = $VM_IP_ADDR" fi - if [ "$RUN_OPTIONS" == "none" ] + if [ "$RUN_OPTIONS" == "none" ] || [[ $RUN_OPTIONS =~ .*run_exec_autotests.* ]] then echo "No run on VM testing for this variant currently" return fi - if [[ $RUN_OPTIONS =~ .*run_exec_autotests.* ]] + if [[ $RUN_OPTIONS =~ .*run_XXXX_autotests.* ]] then echo "############################################################" echo "Running test script on VM ($VM_NAME)" @@ -2027,30 +2156,6 @@ function run_test_on_vm { done - full_l2_sim_destroy - - echo "############################################################" - echo "Checking run status" - echo "############################################################" - - if [ $PING_STATUS -ne 0 ]; then STATUS=-1; fi - if [ $IPERF_STATUS -ne 0 ]; then STATUS=-1; fi - if [ $MBMS_STATUS -eq 0 ] - then - echo "LTE MBMS RFSIM seems OK" - else - echo "LTE MBMS RFSIM seems to FAIL" - STATUS=-1 - fi - if [ $STATUS -eq 0 ] - then - echo "LTE RFSIM seems OK" - echo "LTE: TEST_OK" > $ARCHIVES_LOC/test_final_status.log - else - echo "LTE RFSIM seems to FAIL" - echo "LTE: TEST_KO" > $ARCHIVES_LOC/test_final_status.log - fi - #################### ## FeMBMS CASE noS1 ## #################### @@ -2123,6 +2228,13 @@ function run_test_on_vm { if [ $PING_STATUS -ne 0 ]; then STATUS=-1; fi if [ $IPERF_STATUS -ne 0 ]; then STATUS=-1; fi + if [ $MBMS_STATUS -eq 0 ] + then + echo "LTE MBMS RFSIM seems OK" + else + echo "LTE MBMS RFSIM seems to FAIL" + STATUS=-1 + fi if [ $FeMBMS_STATUS -eq 0 ] then echo "LTE FeMBMS RFSIM seems OK" @@ -2141,35 +2253,55 @@ function run_test_on_vm { fi - if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]] + if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf5g-sim.* ]] then + PING_STATUS=0 + IPERF_STATUS=0 + NR_STATUS=0 + if [ -d $ARCHIVES_LOC ] + then + rm -Rf $ARCHIVES_LOC + fi + mkdir --parents $ARCHIVES_LOC + + echo "############################################################" + echo "SA TEST" + echo "############################################################" + #SA test, attention : has a different config file from the rest of the test CN_CONFIG="noS1" - CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf + CONF_FILE=gnb.band78.sa.fr1.106PRB.usrpn310.conf S1_NOS1_CFG=0 PRB=106 FREQUENCY=3510 - local try_cnt="0" - NR_STATUS=0 + if [ ! -d $ARCHIVES_LOC ] + then + mkdir --parents $ARCHIVES_LOC + fi - ######### start of loop - while [ $try_cnt -lt 1 ] + local try_cnt=0 + + ######### start of SA TEST loop + while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI do + SYNC_STATUS=0 - PING_STATUS=0 - IPERF_STATUS=0 + SA_STATUS=0 + rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}*sa_test.log echo "############################################################" echo "${CN_CONFIG} : Starting the gNB" echo "############################################################" - CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log - start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG + CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb_sa_test.log + #last argument = 2 is to enable --sa for SA test + start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 2 echo "############################################################" echo "${CN_CONFIG} : Starting the NR-UE" echo "############################################################" - CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log - start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG + CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue_sa_test.log + #last argument = 2 is to enable --sa for SA test + start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 2 if [ $NR_UE_SYNC -eq 0 ] then echo "Problem w/ gNB and NR-UE not syncing" @@ -2178,7 +2310,273 @@ function run_test_on_vm { scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC SYNC_STATUS=-1 - try_cnt=$[$try_cnt+1] + try_cnt=$((try_cnt+1)) + continue + fi + + echo "############################################################" + echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators" + echo "############################################################" + sleep 20 + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC + + #check SA markers in gNB and NR UE log files + echo "############################################################" + echo "${CN_CONFIG} : Checking SA on gNB / NR-UE" + echo "############################################################" + + # Proper check to be done when SA test is working! + check_sa_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE + if [ $SA_STATUS -ne 0 ] + then + echo "SA test NOT OK" + echo "try_cnt = " $try_cnt + try_cnt=$((try_cnt+1)) + else + echo "SA test OK" + try_cnt=$((try_cnt+10)) + fi + done + ########### end SA test + + sleep 30 + + + + echo "############################################################" + echo "RA TEST FR2" + echo "############################################################" + #RA FR2 test, attention : has a different config file from the rest of the test + CN_CONFIG="noS1" + CONF_FILE=gnb.band261.tm1.32PRB.usrpn300.conf + S1_NOS1_CFG=0 + PRB=32 + FREQUENCY=28000 #28GHz + + if [ ! -d $ARCHIVES_LOC ] + then + mkdir --parents $ARCHIVES_LOC + fi + + local try_cnt=0 + + ######### start of RA TEST loop + RA_FR2_STATUS=0 + while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI + do + + SYNC_STATUS=0 + RA_STATUS=0 + rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}*ra_fr2_test.log + + echo "############################################################" + echo "${CN_CONFIG} : Starting the gNB" + echo "############################################################" + CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb_ra_fr2_test.log + #last argument = 1 is to enable --do-ra for RA test + start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1 + + echo "############################################################" + echo "${CN_CONFIG} : Starting the NR-UE" + echo "############################################################" + CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue_ra_fr2_test.log + #last argument = 1 is to enable --do-ra for RA test + start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1 + if [ $NR_UE_SYNC -eq 0 ] + then + echo "Problem w/ gNB and NR-UE not syncing" + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC + SYNC_STATUS=-1 + try_cnt=$((try_cnt+1)) + continue + fi + + echo "############################################################" + echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators" + echo "############################################################" + sleep 20 + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC + + #check RA markers in gNB and NR UE log files + echo "############################################################" + echo "${CN_CONFIG} : Checking FR2 RA on gNB / NR-UE" + echo "############################################################" + + # Proper check to be done when RA test is working! + check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE + if [ $RA_STATUS -ne 0 ] + then + echo "RA FR2 test NOT OK" + echo "try_cnt = " $try_cnt + try_cnt=$((try_cnt+1)) + RA_FR2_STATUS=-1 + else + echo "RA FR2 test OK" + RA_FR2_STATUS=0 + try_cnt=$((try_cnt+10)) + fi + done + ########### end RA FR2 test + + sleep 30 + + + echo "############################################################" + echo "RA TEST FR1" + echo "############################################################" + ######### redefine config for the rest of the test + + CN_CONFIG="noS1" + CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf + S1_NOS1_CFG=0 + PRB=106 + FREQUENCY=3510 + + if [ ! -d $ARCHIVES_LOC ] + then + mkdir --parents $ARCHIVES_LOC + fi + + CN_CONFIG="noS1" + S1_NOS1_CFG=0 + + ######### start of RA TEST loop + # for the moment only TDD + TRANS_MODES=("tdd") + for TMODE in ${TRANS_MODES[@]} + do + if [[ $TMODE =~ .*fdd.* ]] + then + CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=37000 + else + CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=3510 + fi + + RA_FR1_STATUS=0 + local try_cnt=0 + while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI + + do + SYNC_STATUS=0 + RA_STATUS=0 + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}*ra_test.log + + echo "############################################################" + echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (RA TEST)" + echo "############################################################" + CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log + #last argument = 1 is to enable --do-ra for RA test + start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1 + + echo "############################################################" + echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (RA TEST)" + echo "############################################################" + CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue_ra_test.log + #last argument = 1 is to enable --do-ra for RA test + start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1 + if [ $NR_UE_SYNC -eq 0 ] + then + echo "Problem w/ gNB and NR-UE not syncing" + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC + SYNC_STATUS=-1 + try_cnt=$((try_cnt+1)) + continue + fi + + echo "############################################################" + echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators" + echo "############################################################" + sleep 20 + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC + + #check RA markers in gNB and NR UE log files + echo "############################################################" + echo "${CN_CONFIG} : Checking FR1 RA on gNB / NR-UE" + echo "############################################################" + + # Proper check to be done when RA test is working! + check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE + if [ $RA_STATUS -ne 0 ] + then + echo "RA FR1 test NOT OK" + echo "try_cnt = " $try_cnt + RA_FR1_STATUS=-1 + try_cnt=$((try_cnt+1)) + else + echo "RA FR1 test OK" + RA_FR1_STATUS=0 + try_cnt=$((try_cnt+10)) + fi + done + done + ########### end RA test + + sleep 30 + + ######### start of PHY TEST loop + SYNC_STATUS=0 + PING_STATUS=0 + IPERF_STATUS=0 + TRANS_MODES=("fdd tdd") + for TMODE in ${TRANS_MODES[@]} + do + if [[ $TMODE =~ .*fdd.* ]] + then + CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=37000 + else + CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=3510 + fi + + try_cnt=0 + while [ $try_cnt -lt 4 ] + do + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul*txt + + echo "############################################################" + echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (PHY TEST)" + echo "############################################################" + CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log + start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 0 + + echo "############################################################" + echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (PHY TEST)" + echo "############################################################" + CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log + start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 0 + if [ $NR_UE_SYNC -eq 0 ] + then + echo "Problem w/ gNB and NR-UE not syncing" + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC + SYNC_STATUS=-1 + try_cnt=$((try_cnt+1)) continue fi @@ -2186,7 +2584,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : Pinging the gNB from NR-UE" echo "############################################################" get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR - PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log + PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log ping_epc_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $ENB_IP_ADDR $PING_LOG_FILE 1 0 scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 @@ -2195,7 +2593,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : Pinging the NR-UE from gNB" echo "############################################################" get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 - PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log + PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log ping_enb_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR $UE_IP_ADDR $PING_LOG_FILE 0 scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 @@ -2204,7 +2602,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client" echo "############################################################" THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl + CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 @@ -2218,7 +2616,7 @@ function run_test_on_vm { terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC - try_cnt=$[$try_cnt+1] + try_cnt=$((try_cnt+1)) continue fi @@ -2226,7 +2624,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client" echo "############################################################" THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul + CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 @@ -2244,10 +2642,11 @@ function run_test_on_vm { if [ $IPERF_STATUS -ne 0 ] then echo "UL test not OK" - try_cnt=$[$try_cnt+1] + try_cnt=$((try_cnt+1)) else - try_cnt=$[$try_cnt+10] + try_cnt=$((try_cnt+10)) fi + done done ######### end of loop full_l2_sim_destroy @@ -2257,16 +2656,19 @@ function run_test_on_vm { echo "Checking run status" echo "############################################################" + if [ $SA_STATUS -ne 0 ]; then NR_STATUS=-1; fi + if [ $RA_FR2_STATUS -ne 0 ]; then NR_STATUS=-1; fi + if [ $RA_FR1_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $SYNC_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $PING_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $IPERF_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $NR_STATUS -eq 0 ] then echo "5G-NR RFSIM seems OK" - echo "5G-NR: TEST_OK" >> $ARCHIVES_LOC/test_final_status.log + echo "5G-NR: TEST_OK" > $ARCHIVES_LOC/test_final_status.log else echo "5G-NR RFSIM seems to FAIL" - echo "5G-NR: TEST_KO" >> $ARCHIVES_LOC/test_final_status.log + echo "5G-NR: TEST_KO" > $ARCHIVES_LOC/test_final_status.log STATUS=-1 fi fi diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index ed0cf5379a..67e0b832e6 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -35,6 +35,7 @@ import pexpect # pexpect import logging import time # sleep import re +import subprocess import sys #----------------------------------------------------------- @@ -44,6 +45,9 @@ class SSHConnection(): def __init__(self): self.ssh = '' self.picocom_closure = False + self.ipaddress = '' + self.username = '' + self.cmd2Results = '' def disablePicocomClosure(self): self.picocom_closure = False @@ -52,13 +56,12 @@ class SSHConnection(): self.picocom_closure = True def open(self, ipaddress, username, password): - extraSshOptions = '' count = 0 connect_status = False - if ipaddress == '192.168.18.197': - extraSshOptions = ' -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' while count < 4: - self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress + extraSshOptions], timeout = 5) + self.ssh = pexpect.spawn('ssh -o PubkeyAuthentication=no {}@{}'.format(username,ipaddress)) + # Longer timeout at connection due to asterix slowness + self.ssh.timeout = 25 self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) if self.sshresponse == 0: self.ssh.sendline('yes') @@ -97,9 +100,11 @@ class SSHConnection(): time.sleep(1) count += 1 if connect_status: - pass + self.command('unset HISTFILE', '\$', 5, silent=True) else: sys.exit('SSH Connection Failed') + self.ipaddress = ipaddress + self.username = username @@ -113,11 +118,20 @@ class SSHConnection(): self.sshresponse = self.ssh.expect(expected) return self.sshresponse - def command(self, commandline, expectedline, timeout): - logging.debug(commandline) + def command(self, commandline, expectedline, timeout, silent=False, resync=False): + if not silent: + logging.debug(commandline) self.ssh.timeout = timeout - self.ssh.sendline(commandline) - self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) + # Nasty patch when pexpect output is out of sync. + # Much pronounced when running back-to-back-back oc commands + if resync: + self.ssh.send(commandline) + self.ssh.expect([commandline, pexpect.TIMEOUT]) + self.ssh.send('\r\n') + self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) + else: + self.ssh.sendline(commandline) + self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) if self.sshresponse == 0: return 0 elif self.sshresponse == 1: @@ -139,10 +153,35 @@ class SSHConnection(): logging.debug('Expected Line : ' + expectedline) sys.exit(self.sshresponse) + def command2(self, commandline, timeout, silent=False): + if not silent: + logging.debug(commandline) + self.cmd2Results = '' + myHost = self.username + '@' + self.ipaddress + # CAUTION: THIS METHOD IMPLIES THAT THERE ARE VALID SSH KEYS + # BETWEEN THE PYTHON EXECUTOR NODE AND THE REMOTE HOST + # OTHERWISE IT WON'T WORK + lSsh = subprocess.Popen(["ssh", "%s" % myHost, commandline],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + self.cmd2Results = str(lSsh.stdout.readlines()) + + def command3(self, commandline, timeout, silent=False): + if not silent: + logging.debug(commandline) + self.cmd2Results = '' + myHost = self.username + '@' + self.ipaddress + # CAUTION: THIS METHOD IMPLIES THAT THERE ARE VALID SSH KEYS + # BETWEEN THE PYTHON EXECUTOR NODE AND THE REMOTE HOST + # OTHERWISE IT WON'T WORK + lSsh = subprocess.Popen(["ssh", "%s" % myHost, commandline],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + return lSsh.stdout.readlines() + + def close(self): self.ssh.timeout = 5 self.ssh.sendline('exit') self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) + self.ipaddress = '' + self.username = '' if self.sshresponse == 0: pass elif self.sshresponse == 1: diff --git a/ci-scripts/stats_monitor.py b/ci-scripts/stats_monitor.py new file mode 100755 index 0000000000..933bf13203 --- /dev/null +++ b/ci-scripts/stats_monitor.py @@ -0,0 +1,127 @@ +""" +To create graphs and pickle from runtime statistics in L1,MAC,RRC,PDCP files +""" + +import subprocess +import time +import shlex +import re +import sys +import pickle +import matplotlib.pyplot as plt +import numpy as np +import yaml + + +class StatMonitor(): + def __init__(self,cfg_file): + with open(cfg_file,'r') as file: + self.d = yaml.load(file) + for node in self.d:#so far we have enb or gnb as nodes + for metric_l1 in self.d[node]: #first level of metric keys + if metric_l1!="graph": #graph is a reserved word to configure graph paging, so it is disregarded + if self.d[node][metric_l1] is None:#first level is None -> create array + self.d[node][metric_l1]=[] + else: #first level is not None -> there is a second level -> create array + for metric_l2 in self.d[node][metric_l1]: + self.d[node][metric_l1][metric_l2]=[] + + + + def process_gnb (self,node_type,output): + for line in output: + tmp=line.decode("utf-8") + result=re.match(r'^.*\bdlsch_rounds\b ([0-9]+)\/([0-9]+).*\bdlsch_errors\b ([0-9]+)',tmp) + if result is not None: + self.d[node_type]['dlsch_err'].append(int(result.group(3))) + percentage=float(result.group(2))/float(result.group(1)) + self.d[node_type]['dlsch_err_perc_round_1'].append(percentage) + result=re.match(r'^.*\bulsch_rounds\b ([0-9]+)\/([0-9]+).*\bulsch_errors\b ([0-9]+)',tmp) + if result is not None: + self.d[node_type]['ulsch_err'].append(int(result.group(3))) + percentage=float(result.group(2))/float(result.group(1)) + self.d[node_type]['ulsch_err_perc_round_1'].append(percentage) + + for k in self.d[node_type]['rt']: + result=re.match(rf'^.*\b{k}\b:\s+([0-9\.]+) us;\s+([0-9]+);\s+([0-9\.]+) us;',tmp) + if result is not None: + self.d[node_type]['rt'][k].append(float(result.group(3))) + + + def process_enb (self,node_type,output): + for line in output: + tmp=line.decode("utf-8") + result=re.match(r'^.*\bPHR\b ([0-9]+).+\bbler\b ([0-9]+\.[0-9]+).+\bmcsoff\b ([0-9]+).+\bmcs\b ([0-9]+)',tmp) + if result is not None: + self.d[node_type]['PHR'].append(int(result.group(1))) + self.d[node_type]['bler'].append(float(result.group(2))) + self.d[node_type]['mcsoff'].append(int(result.group(3))) + self.d[node_type]['mcs'].append(int(result.group(4))) + + + def collect(self,node_type): + if node_type=='enb': + cmd='cat L1_stats.log MAC_stats.log PDCP_stats.log RRC_stats.log' + else: #'gnb' + cmd='cat nrL1_stats.log nrMAC_stats.log nrPDCP_stats.log nrRRC_stats.log' + process=subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE) + output = process.stdout.readlines() + if node_type=='enb': + self.process_enb(node_type,output) + else: #'gnb' + self.process_gnb(node_type,output) + + + def graph(self,node_type): + for page in self.d[node_type]['graph']:#work out a set a graphs per page + col = 1 + figure, axis = plt.subplots(len(self.d[node_type]['graph'][page]), col ,figsize=(10, 10)) + i=0 + for m in self.d[node_type]['graph'][page]:#metric may refer to 1 level or 2 levels + metric_path=m.split('.') + if len(metric_path)==1:#1 level + metric_l1=metric_path[0] + major_ticks = np.arange(0, len(self.d[node_type][metric_l1])+1, 1) + axis[i].set_xticks(major_ticks) + axis[i].set_xticklabels([]) + axis[i].plot(self.d[node_type][metric_l1],marker='o') + axis[i].set_xlabel('time') + axis[i].set_ylabel(metric_l1) + axis[i].set_title(metric_l1) + + else:#2 levels + metric_l1=metric_path[0] + metric_l2=metric_path[1] + major_ticks = np.arange(0, len(self.d[node_type][metric_l1][metric_l2])+1, 1) + axis[i].set_xticks(major_ticks) + axis[i].set_xticklabels([]) + axis[i].plot(self.d[node_type][metric_l1][metric_l2],marker='o') + axis[i].set_xlabel('time') + axis[i].set_ylabel(metric_l2) + axis[i].set_title(metric_l2) + i+=1 + + plt.tight_layout() + #save as png + plt.savefig(node_type+'_stats_monitor_'+page+'.png') + + +if __name__ == "__main__": + + cfg_filename = sys.argv[1] #yaml file as metrics config + node = sys.argv[2]#enb or gnb + mon=StatMonitor(cfg_filename) + + #collecting stats when modem process is stopped + CMD='ps aux | grep modem | grep -v grep' + process=subprocess.Popen(CMD, shell=True, stdout=subprocess.PIPE) + output = process.stdout.readlines() + while len(output)!=0 : + mon.collect(node) + process=subprocess.Popen(CMD, shell=True, stdout=subprocess.PIPE) + output = process.stdout.readlines() + time.sleep(1) + print('Process stopped') + with open(node+'_stats_monitor.pickle', 'wb') as handle: + pickle.dump(mon.d, handle, protocol=pickle.HIGHEST_PROTOCOL) + mon.graph(node) diff --git a/ci-scripts/stats_monitor.py.old b/ci-scripts/stats_monitor.py.old new file mode 100755 index 0000000000..ae9b39bfa6 --- /dev/null +++ b/ci-scripts/stats_monitor.py.old @@ -0,0 +1,94 @@ +import subprocess +import time +import shlex +import re +import sys +import matplotlib.pyplot as plt +import pickle +import numpy as np +import os + +def collect(d, node_type): + if node_type=='enb': + cmd='cat L1_stats.log MAC_stats.log PDCP_stats.log RRC_stats.log' + else: #'gnb' + cmd='cat nrL1_stats.log nrMAC_stats.log nrPDCP_stats.log nrRRC_stats.log' + process=subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE) + output = process.stdout.readlines() + for l in output: + tmp=l.decode("utf-8") + result=re.match(rf'^.*\bPHR\b ([0-9]+).+\bbler\b ([0-9]+\.[0-9]+).+\bmcsoff\b ([0-9]+).+\bmcs\b ([0-9]+)',tmp) + if result is not None: + d['PHR'].append(int(result.group(1))) + d['bler'].append(float(result.group(2))) + d['mcsoff'].append(int(result.group(3))) + d['mcs'].append(int(result.group(4))) + + +def graph(d, node_type): + + + figure, axis = plt.subplots(4, 1,figsize=(10, 10)) + + major_ticks = np.arange(0, len(d['PHR'])+1, 1) + axis[0].set_xticks(major_ticks) + axis[0].set_xticklabels([]) + axis[0].plot(d['PHR'],marker='o') + axis[0].set_xlabel('time') + axis[0].set_ylabel('PHR') + axis[0].set_title("PHR") + + major_ticks = np.arange(0, len(d['bler'])+1, 1) + axis[1].set_xticks(major_ticks) + axis[1].set_xticklabels([]) + axis[1].plot(d['bler'],marker='o') + axis[1].set_xlabel('time') + axis[1].set_ylabel('bler') + axis[1].set_title("bler") + + major_ticks = np.arange(0, len(d['mcsoff'])+1, 1) + axis[2].set_xticks(major_ticks) + axis[2].set_xticklabels([]) + axis[2].plot(d['mcsoff'],marker='o') + axis[2].set_xlabel('time') + axis[2].set_ylabel('mcsoff') + axis[2].set_title("mcsoff") + + major_ticks = np.arange(0, len(d['mcs'])+1, 1) + axis[3].set_xticks(major_ticks) + axis[3].set_xticklabels([]) + axis[3].plot(d['mcs'],marker='o') + axis[3].set_xlabel('time') + axis[3].set_ylabel('mcs') + axis[3].set_title("mcs") + + plt.tight_layout() + # Combine all the operations and display + plt.savefig(node_type+'_stats_monitor.png') + plt.show() + +if __name__ == "__main__": + + node_type = sys.argv[1]#enb or gnb + + d={} + d['PHR']=[] + d['bler']=[] + d['mcsoff']=[] + d['mcs']=[] + + + cmd='ps aux | grep modem | grep -v grep' + process=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) + output = process.stdout.readlines() + while len(output)!=0 : + collect(d, node_type) + process=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) + output = process.stdout.readlines() + time.sleep(1) + print('process stopped') + with open(node_type+'_stats_monitor.pickle', 'wb') as handle: + pickle.dump(d, handle, protocol=pickle.HIGHEST_PROTOCOL) + graph(d, node_type) + + diff --git a/ci-scripts/stats_monitor_conf.yaml b/ci-scripts/stats_monitor_conf.yaml new file mode 100644 index 0000000000..8760c067fc --- /dev/null +++ b/ci-scripts/stats_monitor_conf.yaml @@ -0,0 +1,51 @@ +enb : + PHR: + bler: + mcsoff: + mcs: + graph: + page1: + PHR: + bler: + mcsoff: + mcs: + +gnb : + dlsch_err: + dlsch_err_perc_round_1: + ulsch_err: + ulsch_err_perc_round_1: + rt : + feprx: + feptx_prec: + feptx_ofdm: + feptx_total: + L1 Tx processing thread 0: + L1 Tx processing thread 1: + DLSCH encoding: + L1 Rx processing: + PUSCH inner-receiver: + PUSCH decoding: + DL & UL scheduling timing stats: + UL Indication: + graph : + page1: + dlsch_err: + dlsch_err_perc_round_1: + ulsch_err: + ulsch_err_perc_round_1: + page2: + rt.feprx: + rt.feptx_prec: + rt.feptx_ofdm: + rt.feptx_total: + page3: + rt.L1 Tx processing thread 0: + rt.L1 Tx processing thread 1: + rt.DLSCH encoding: + rt.L1 Rx processing: + page4: + rt.PUSCH inner-receiver: + rt.PUSCH decoding: + rt.DL & UL scheduling timing stats: + rt.UL Indication: \ No newline at end of file diff --git a/ci-scripts/stats_monitor_dev.py b/ci-scripts/stats_monitor_dev.py new file mode 100755 index 0000000000..83de20f5d2 --- /dev/null +++ b/ci-scripts/stats_monitor_dev.py @@ -0,0 +1,101 @@ +""" +To create graphs and pickle from runtime statistics in L1,MAC,RRC,PDCP files +""" + +import subprocess +import time +import shlex +import re +import sys +import pickle +import matplotlib.pyplot as plt +import numpy as np +import yaml + + +class StatMonitor(): + def __init__(self,): + with open('stats_monitor_conf.yaml','r') as file: + self.d = yaml.load(file) + for node in self.d: + for metric in self.d[node]: + self.d[node][metric]=[] + + + def process_gnb (self,node_type,output): + for line in output: + tmp=line.decode("utf-8") + result=re.match(r'^.*\bdlsch_rounds\b ([0-9]+)\/([0-9]+).*\bdlsch_errors\b ([0-9]+)',tmp) + if result is not None: + self.d[node_type]['dlsch_err'].append(int(result.group(3))) + percentage=float(result.group(2))/float(result.group(1)) + self.d[node_type]['dlsch_err_perc_round_1'].append(percentage) + result=re.match(r'^.*\bulsch_rounds\b ([0-9]+)\/([0-9]+).*\bulsch_errors\b ([0-9]+)',tmp) + if result is not None: + self.d[node_type]['ulsch_err'].append(int(result.group(3))) + percentage=float(result.group(2))/float(result.group(1)) + self.d[node_type]['ulsch_err_perc_round_1'].append(percentage) + + + def process_enb (self,node_type,output): + for line in output: + tmp=line.decode("utf-8") + result=re.match(r'^.*\bPHR\b ([0-9]+).+\bbler\b ([0-9]+\.[0-9]+).+\bmcsoff\b ([0-9]+).+\bmcs\b ([0-9]+)',tmp) + if result is not None: + self.d[node_type]['PHR'].append(int(result.group(1))) + self.d[node_type]['bler'].append(float(result.group(2))) + self.d[node_type]['mcsoff'].append(int(result.group(3))) + self.d[node_type]['mcs'].append(int(result.group(4))) + + + def collect(self,node_type): + if node_type=='enb': + cmd='cat L1_stats.log MAC_stats.log PDCP_stats.log RRC_stats.log' + else: #'gnb' + cmd='cat nrL1_stats.log nrMAC_stats.log nrPDCP_stats.log nrRRC_stats.log' + process=subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE) + output = process.stdout.readlines() + if node_type=='enb': + self.process_enb(node_type,output) + else: #'gnb' + self.process_gnb(node_type,output) + + + def graph(self,node_type): + col = 1 + figure, axis = plt.subplots(len(self.d[node_type]), col ,figsize=(10, 10)) + i=0 + for metric in self.d[node_type]: + major_ticks = np.arange(0, len(self.d[node_type][metric])+1, 1) + axis[i].set_xticks(major_ticks) + axis[i].set_xticklabels([]) + axis[i].plot(self.d[node_type][metric],marker='o') + axis[i].set_xlabel('time') + axis[i].set_ylabel(metric) + axis[i].set_title(metric) + i+=1 + + plt.tight_layout() + # Combine all the operations and display + plt.savefig(node_type+'_stats_monitor.png') + plt.show() + + +if __name__ == "__main__": + + node = sys.argv[1]#enb or gnb + mon=StatMonitor() + + #collecting stats when modem process is stopped + CMD='ps aux | grep mode | grep -v grep' + process=subprocess.Popen(CMD, shell=True, stdout=subprocess.PIPE) + output = process.stdout.readlines() + while len(output)!=0 : + mon.collect(node) + process=subprocess.Popen(CMD, shell=True, stdout=subprocess.PIPE) + output = process.stdout.readlines() + time.sleep(1) + print('Process stopped') + with open(node+'_stats_monitor.pickle', 'wb') as handle: + pickle.dump(mon.d, handle, protocol=pickle.HIGHEST_PROTOCOL) + mon.graph(node) diff --git a/ci-scripts/tcp_iperf_stats.awk b/ci-scripts/tcp_iperf_stats.awk index 3a00e4555f..b21bf16a2f 100644 --- a/ci-scripts/tcp_iperf_stats.awk +++ b/ci-scripts/tcp_iperf_stats.awk @@ -21,7 +21,11 @@ BEGIN{max=0;min=10000} { if ($0 ~/Mbits/) { - split($0,a,"MBytes") + if ($0 ~/KBytes/) { + split($0,a,"KBytes") + } else { + split($0,a,"MBytes") + } split(a[2],b) if (b[1]>max) { max=b[1] diff --git a/ci-scripts/waitBuildOnVM.sh b/ci-scripts/waitBuildOnVM.sh index f066dacd81..4a604a1fe9 100755 --- a/ci-scripts/waitBuildOnVM.sh +++ b/ci-scripts/waitBuildOnVM.sh @@ -47,6 +47,12 @@ function wait_on_vm_build { echo "ARCHIVES_LOC = $ARCHIVES_LOC" echo "BUILD_OPTIONS = $BUILD_OPTIONS" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] || [[ "$VM_NAME" == *"-phy-sim"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME` if [ $IS_VM_ALIVE -eq 0 ] @@ -67,6 +73,9 @@ function wait_on_vm_build { echo "############################################################" echo "Waiting build process to end on VM ($VM_NAME)" echo "############################################################" + # Since the last VM was cppcheck and is removed + # we are going too fast in wait and the build_oai is not yet started + sleep 120 if [[ "$VM_NAME" == *"-cppcheck"* ]] then @@ -84,6 +93,12 @@ function wait_on_vm_build { } function check_on_vm_build { + if [[ "$VM_NAME" == *"-enb-usrp"* ]] || [[ "$VM_NAME" == *"-cppcheck"* ]] || [[ "$VM_NAME" == *"-phy-sim"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + echo "############################################################" echo "Creating a tmp folder to store results and artifacts" echo "############################################################" diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index e80063a120..9e33ee468d 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -1,4 +1,3 @@ - - COTS_UE_Airplane - Build_PhySim - Run_PhySim - Build_eNB @@ -20,12 +19,16 @@ - Reboot_UE - Initialize_FlexranCtrl - Terminate_FlexranCtrl + - Deploy_EPC + - Undeploy_EPC - Initialize_HSS - Terminate_HSS - Initialize_MME - Terminate_MME - Initialize_SPGW - Terminate_SPGW + - Initialize_5GCN + - Terminate_5GCN - Initialize_CatM_module - Terminate_CatM_module - Attach_CatM_module @@ -33,3 +36,13 @@ - Ping_CatM_module - IdleSleep - Perform_X2_Handover + - Build_Image + - Copy_Image_to_Test + - Deploy_Object + - Undeploy_Object + - Cppcheck_Analysis + - Deploy_Run_PhySim + - DeployGenObject + - UndeployGenObject + - PingFromContainer + - IperfFromContainer diff --git a/ci-scripts/xml_files/benetel_multi_node_build.xml b/ci-scripts/xml_files/benetel_multi_node_build.xml new file mode 100644 index 0000000000..5ac28951b4 --- /dev/null +++ b/ci-scripts/xml_files/benetel_multi_node_build.xml @@ -0,0 +1,54 @@ + + + build-tab + Build + wrench + + 000001 000002 + + + + + Build_eNB + Build eNB + --eNB -t benetel4g -w None + True + 0 + 0 + + + + + Build_eNB + Build gNB + --gNB -t benetel5g -w None + True + 1 + 1 + + + + + + diff --git a/ci-scripts/xml_files/benetel_nsa_quectel.xml b/ci-scripts/xml_files/benetel_nsa_quectel.xml new file mode 100644 index 0000000000..ed93f59e81 --- /dev/null +++ b/ci-scripts/xml_files/benetel_nsa_quectel.xml @@ -0,0 +1,147 @@ + + + TEST-NSA-FR1-TM1 + NSA Ping DL UL with QUECTEL + tasks + 3 + + 030000 + 040000 + 000002 + 010000 + 050000 + 050001 + 000001 + 070000 + 000001 + 070001 + 000001 + 010002 + 000001 + 080001 + 080000 + + + + + Initialize_UE + Initialize Quectel + idefix + + + + + Detach_UE + Detach UE + idefix + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/benetel-4g.conf + 0 + 0 + lte + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/benetel-5g.conf -q + 1 + 1 + nr + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 + 50 + + + + Ping + Ping: 100pings in 20sec + idefix + -c 100 -i 0.2 + 50 + + + + Iperf + iperf (DL/20Mbps/UDP)(60 sec)(single-ue profile) + -u -b 20M -t 60 -i 1 + DL + idefix + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile) + -u -b 3M -t 60 -i 1 + UL + idefix + 50 + single-ue + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/benetel_nsa_quectel_longrun.xml b/ci-scripts/xml_files/benetel_nsa_quectel_longrun.xml new file mode 100644 index 0000000000..93c0c5a00a --- /dev/null +++ b/ci-scripts/xml_files/benetel_nsa_quectel_longrun.xml @@ -0,0 +1,149 @@ + + + TEST-NSA-FR1-TM1 + NSA Ping DL UL with QUECTEL + tasks + 3 + + 030000 + 040000 + 000002 + 010000 + 000001 + 050000 + 050001 + 000001 + 070000 + 000001 + 070001 + 000001 + 010002 + 000001 + 080001 + 080000 + + + + + + Initialize_UE + Initialize Quectel + idefix + + + + + Detach_UE + Detach UE + idefix + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/benetel-4g.conf + 0 + 0 + lte + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/benetel-5g.conf -q + 1 + 1 + nr + + + + IdleSleep + Sleep + 10 + + + + IdleSleep + Sleep + 30 + + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 + 50 + + + + Ping + Ping: 100pings in 20sec + idefix + -c 100 -i 0.2 + 50 + + + + Iperf + iperf (DL/20Mbps/UDP)(20 min)(single-ue profile) + -u -b 20M -t 1200 -i 1 + DL + idefix + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(20 min)(single-ue profile) + -u -b 2M -t 1200 -i 1 + UL + idefix + 50 + single-ue + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/container_4g_rfsim.xml b/ci-scripts/xml_files/container_4g_rfsim.xml new file mode 100644 index 0000000000..7f13d599b8 --- /dev/null +++ b/ci-scripts/xml_files/container_4g_rfsim.xml @@ -0,0 +1,130 @@ + + + rfsim-4glte + Testing 4G LTE RF sim in containers + wrench + 2 + + 100011 + 000011 + 000001 + 000012 + 000002 + 000013 + 000001 + 000014 + 000002 + 020011 + 020012 + 030011 + 030012 + 100011 + + + + + DeployGenObject + Deploy Cassandra Database + yaml_files/4g_rfsimulator + cassandra db_init + 1 + + + + IdleSleep + Sleep + 30 + + + + IdleSleep + Sleep + 10 + + + + DeployGenObject + Deploy OAI 4G CoreNetwork + yaml_files/4g_rfsimulator + oai_hss oai_mme oai_spgwc oai_spgwu trf_gen + 6 + + + + DeployGenObject + Deploy OAI 4G eNB RF sim + yaml_files/4g_rfsimulator + enb + 7 + + + + DeployGenObject + Deploy OAI 4G NR-UE RF sim + yaml_files/4g_rfsimulator + oai_ue0 + 8 + + + + PingFromContainer + Ping Traffic-Gen from LTE-UE + rfsim4g-oai-lte-ue0 + -I oaitun_ue1 -c 20 192.168.61.11 + 5 + + + + PingFromContainer + Ping LTE-UE from Traffic-Gen + rfsim4g-trf-gen + -c 20 12.0.0.2 + 5 + + + + IperfFromContainer + Iperf UDP Downlink + rfsim4g-oai-lte-ue0 + rfsim4g-trf-gen + -B 12.0.0.2 -u -i 1 -s + -c 12.0.0.2 -u -i 1 -t 30 -b 2M + + + + IperfFromContainer + Iperf UDP Uplink + rfsim4g-trf-gen + rfsim4g-oai-lte-ue0 + -u -i 1 -s + -B 12.0.0.2 -c 192.168.61.11 -u -i 1 -t 30 -b 1M + + + + UndeployGenObject + Undeploy all OAI 4G stack + yaml_files/4g_rfsimulator + + + diff --git a/ci-scripts/xml_files/container_4g_rfsim_down.xml b/ci-scripts/xml_files/container_4g_rfsim_down.xml new file mode 100644 index 0000000000..dee516d924 --- /dev/null +++ b/ci-scripts/xml_files/container_4g_rfsim_down.xml @@ -0,0 +1,38 @@ + + + rfsim-4glte-down + CleanUp 4G RF + trash + + 100011 + + + + + UndeployGenObject + Undeploy all OAI 4G stack + yaml_files/4g_rfsimulator + + + diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml new file mode 100644 index 0000000000..11f85688ec --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -0,0 +1,105 @@ + + + rfsim-5gnr + Testing 5G NR RF sim in containers + wrench + 4 + + 100001 + 000001 + 000002 + 000003 + 020001 + 020002 + 030001 + 030002 + 100001 + + + + + DeployGenObject + Deploy OAI 5G CoreNetwork + yaml_files/5g_rfsimulator + mysql oai-nrf oai-amf oai-smf oai-spgwu oai-ext-dn + 6 + + + + DeployGenObject + Deploy OAI 5G gNB RF sim SA + yaml_files/5g_rfsimulator + oai-gnb + 7 + + + + DeployGenObject + Deploy OAI 5G NR-UE RF sim SA + yaml_files/5g_rfsimulator + oai-nr-ue + 8 + + + + PingFromContainer + Ping ext-dn from NR-UE + rfsim5g-oai-nr-ue + -I oaitun_ue1 -c 20 192.168.72.135 + 5 + + + + PingFromContainer + Ping NR-UE from ext-dn + rfsim5g-oai-ext-dn + -c 20 12.1.1.2 + 5 + + + + IperfFromContainer + Iperf UDP Downlink + rfsim5g-oai-nr-ue + rfsim5g-oai-ext-dn + -B 12.1.1.2 -u -i 1 -s + -c 12.1.1.2 -u -i 1 -t 30 -b 400K + + + + IperfFromContainer + Iperf UDP Uplink + rfsim5g-oai-ext-dn + rfsim5g-oai-nr-ue + -u -i 1 -s + -B 12.1.1.2 -c 192.168.72.135 -u -i 1 -t 30 -b 20K + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator + + + diff --git a/ci-scripts/xml_files/container_5g_rfsim_down.xml b/ci-scripts/xml_files/container_5g_rfsim_down.xml new file mode 100644 index 0000000000..57b0f67a21 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_down.xml @@ -0,0 +1,38 @@ + + + rfsim-5gnr-down + CleanUp 5G RF + trash + + 100002 + + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator + + + diff --git a/ci-scripts/xml_files/fr1_multi_node_terminate.xml b/ci-scripts/xml_files/container_image_build.xml similarity index 70% rename from ci-scripts/xml_files/fr1_multi_node_terminate.xml rename to ci-scripts/xml_files/container_image_build.xml index cbaaf8ba99..e7eabc0794 100644 --- a/ci-scripts/xml_files/fr1_multi_node_terminate.xml +++ b/ci-scripts/xml_files/container_image_build.xml @@ -21,30 +21,21 @@ --> - test-fr1-tm1 - Test-FR1-TM1 - tasks - 1 + build-tab + Build Container Images + wrench - 070001 - 070000 + 000001 - - + - - Terminate_eNB - Terminate eNB + + Build_Image + Build all Images + all 0 0 - - - - Terminate_eNB - Terminate gNB - 1 - 1 + True - diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml new file mode 100644 index 0000000000..0af0d9bd70 --- /dev/null +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -0,0 +1,157 @@ + + + TEST-NSA-FR1-TM1-B200 + NSA SanityCheck with QUECTEL + tasks + 1 + + 000001 + 010002 + 030000 + 030101 + 000001 + 030102 + 000001 + 010000 + 000001 + 050000 + 050001 + 070000 + 070001 + 050000 + 050001 + 010002 + 000001 + 030202 + 030201 + + + + + Initialize_UE + Initialize Quectel + idefix + yes + + + + + Terminate_UE + Terminate Quectel + idefix + + + + Copy_Image_to_Test + Copy gNB image to test server + oai-gnb + 0 + 1 + + + + Deploy_Object + Deploy eNB (FDD/Band7/5MHz/B200) in a container + ci-scripts/yaml_files/nsa_b200_enb + 0 + 0 + + + + Deploy_Object + Deploy gNB (TDD/Band78/40MHz/B200) in a container + ci-scripts/yaml_files/nsa_b200_gnb + 1 + 1 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 + 1 + 15 + + + + Ping + Ping: 100pings in 20sec + idefix + -c 100 -i 0.2 + 1 + 15 + + + + Iperf + iperf (DL/40Mbps/UDP)(60 sec)(single-ue profile) + -u -b 40M -t 60 + DL + idefix + 3 + single-ue + + + + Iperf + iperf (UL/2Mbps/UDP)(60 sec)(single-ue profile) + -u -b 2M -t 60 + UL + idefix + 1 + single-ue + + + + Undeploy_Object + Undeploy eNB + ci-scripts/yaml_files/nsa_b200_enb + 0 + 0 + + + + Undeploy_Object + Undeploy gNB + ci-scripts/yaml_files/nsa_b200_gnb + 1 + 1 + + + + diff --git a/ci-scripts/xml_files/container_nsa_b200_terminate.xml b/ci-scripts/xml_files/container_nsa_b200_terminate.xml new file mode 100644 index 0000000000..4b446988cd --- /dev/null +++ b/ci-scripts/xml_files/container_nsa_b200_terminate.xml @@ -0,0 +1,51 @@ + + + TEST-NSA-FR1-TM1-B200-terminate + NSA tear-down in case of problem + tasks + 1 + + 030202 + 030201 + + + + + Undeploy_Object + Undeploy eNB + ci-scripts/yaml_files/nsa_b200_enb + 0 + 0 + + + + Undeploy_Object + Undeploy gNB + ci-scripts/yaml_files/nsa_b200_gnb + 1 + 1 + + + + diff --git a/ci-scripts/xml_files/fr1_toggle_cots_ue.xml b/ci-scripts/xml_files/cppcheck.xml similarity index 79% rename from ci-scripts/xml_files/fr1_toggle_cots_ue.xml rename to ci-scripts/xml_files/cppcheck.xml index b2267efc77..dd90d88f7e 100644 --- a/ci-scripts/xml_files/fr1_toggle_cots_ue.xml +++ b/ci-scripts/xml_files/cppcheck.xml @@ -21,19 +21,17 @@ --> - test-airplane-mode - AirplaneToggle - tasks + build-tab + CPPCHECK Analysis + wrench - 010000 + 000001 - - COTS_UE_Airplane - Toggle COTS Airplane mode ON - ON + + Cppcheck_Analysis + Static Code Analysis with cppcheck - diff --git a/ci-scripts/xml_files/enb_ue_usrp210_band7_build.xml b/ci-scripts/xml_files/enb_ue_usrp210_band7_build.xml index 64c3517166..bfaaceaa2d 100644 --- a/ci-scripts/xml_files/enb_ue_usrp210_band7_build.xml +++ b/ci-scripts/xml_files/enb_ue_usrp210_band7_build.xml @@ -32,7 +32,7 @@ Build_eNB Build eNB (USRP) - -w USRP -c --eNB + -w USRP -c --eNB --ninja diff --git a/ci-scripts/xml_files/enb_ue_usrp210_band7_ue_build.xml b/ci-scripts/xml_files/enb_ue_usrp210_band7_ue_build.xml index 7280a87fb8..d73a1e26e9 100644 --- a/ci-scripts/xml_files/enb_ue_usrp210_band7_ue_build.xml +++ b/ci-scripts/xml_files/enb_ue_usrp210_band7_ue_build.xml @@ -32,7 +32,7 @@ Build_OAI_UE Build OAI UE - -w USRP --UE + -w USRP --UE --ninja diff --git a/ci-scripts/xml_files/enb_usrp210_band13_build.xml b/ci-scripts/xml_files/enb_usrp210_band13_build.xml index 888a1230ae..53066573c8 100644 --- a/ci-scripts/xml_files/enb_usrp210_band13_build.xml +++ b/ci-scripts/xml_files/enb_usrp210_band13_build.xml @@ -33,7 +33,7 @@ Build_eNB Build eNB (USRP) - -w USRP -c --eNB + -w USRP -c --eNB --ninja diff --git a/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml index 611492b0bc..cdba0723df 100644 --- a/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml +++ b/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml @@ -25,6 +25,7 @@ Test-LTE-M-10MHz-TM1 tasks 1 + True 030201 040102 diff --git a/ci-scripts/xml_files/enb_usrp210_band40_build.xml b/ci-scripts/xml_files/enb_usrp210_band40_build.xml index 64c3517166..bfaaceaa2d 100644 --- a/ci-scripts/xml_files/enb_usrp210_band40_build.xml +++ b/ci-scripts/xml_files/enb_usrp210_band40_build.xml @@ -32,7 +32,7 @@ Build_eNB Build eNB (USRP) - -w USRP -c --eNB + -w USRP -c --eNB --ninja diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml index 09aa0b04a2..5ece10d37e 100644 --- a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml @@ -26,6 +26,8 @@ Test-05MHz-TM2 tasks 2 + True + 040608 030201 040101 diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_10mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_10mhz_tm1.xml index 29699d3b3d..b1d87e598e 100644 --- a/ci-scripts/xml_files/enb_usrp210_band40_test_10mhz_tm1.xml +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_10mhz_tm1.xml @@ -24,6 +24,8 @@ test-10-tm1 Test-10MHz-TM1 tasks + True + 040615 030201 040101 diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1.xml index f98ed1600a..d75704aceb 100644 --- a/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1.xml +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1.xml @@ -25,6 +25,8 @@ Test-20MHz-TM1 tasks 4 + True + 040623 030201 040101 diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml index fd018f7a9c..a6530a920c 100644 --- a/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml @@ -24,6 +24,8 @@ test-20-tm1-defSched Test-20MHz-TM1-default-scheduler tasks + True + 040522 030201 040101 diff --git a/ci-scripts/xml_files/enb_usrp210_band7_build.xml b/ci-scripts/xml_files/enb_usrp210_band7_build.xml index 64c3517166..bfaaceaa2d 100644 --- a/ci-scripts/xml_files/enb_usrp210_band7_build.xml +++ b/ci-scripts/xml_files/enb_usrp210_band7_build.xml @@ -32,7 +32,7 @@ Build_eNB Build eNB (USRP) - -w USRP -c --eNB + -w USRP -c --eNB --ninja diff --git a/ci-scripts/xml_files/fr1_enb_build.xml b/ci-scripts/xml_files/fr1_enb_build.xml new file mode 100644 index 0000000000..084f58a591 --- /dev/null +++ b/ci-scripts/xml_files/fr1_enb_build.xml @@ -0,0 +1,50 @@ + + + build-tab + Build + wrench + + 000001 + 000002 + + + + + Build_eNB + Build eNB + -w USRP -c --eNB --ninja + 0 + 0 + True + True + + + + WaitEndBuild_eNB + Wait for end of Build eNB + 0 + 0 + + + diff --git a/ci-scripts/xml_files/fr1_epc_closure.xml b/ci-scripts/xml_files/fr1_epc_closure.xml new file mode 100644 index 0000000000..2fd8031936 --- /dev/null +++ b/ci-scripts/xml_files/fr1_epc_closure.xml @@ -0,0 +1,47 @@ + + + epc-closure + EPC-Closure + log-out + +060000 060001 060002 + + + + + Terminate_HSS + Terminate HSS + + + + Terminate_MME + Terminate MME + + + + Terminate_SPGW + Terminate SPGW + + + diff --git a/ci-scripts/xml_files/fr1_epc_start.xml b/ci-scripts/xml_files/fr1_epc_start.xml new file mode 100644 index 0000000000..5cef2b5a6a --- /dev/null +++ b/ci-scripts/xml_files/fr1_epc_start.xml @@ -0,0 +1,48 @@ + + + epc-start-tab + EPC-Start + log-in + + 000100 000101 000102 + + + + + + Initialize_HSS + Initialize HSS + + + + Initialize_MME + Initialize MME + + + + Initialize_SPGW + Initialize SPGW + + + diff --git a/ci-scripts/xml_files/fr1_epc_start_verizon.xml b/ci-scripts/xml_files/fr1_epc_start_verizon.xml new file mode 100644 index 0000000000..19f5c03985 --- /dev/null +++ b/ci-scripts/xml_files/fr1_epc_start_verizon.xml @@ -0,0 +1,49 @@ + + + epc-start-tab + EPC-Start + log-in + + 000100 000101 000102 + + + + + + Initialize_HSS + Initialize HSS + + + + Initialize_MME + Initialize MME + + + + + Initialize_SPGW + Initialize SPGW + + + diff --git a/ci-scripts/xml_files/fr1_gnb_build.xml b/ci-scripts/xml_files/fr1_gnb_build.xml new file mode 100644 index 0000000000..13d85fccc4 --- /dev/null +++ b/ci-scripts/xml_files/fr1_gnb_build.xml @@ -0,0 +1,41 @@ + + + build-tab + Build + wrench + + 000001 + + + + + Build_eNB + Build gNB + -w USRP -c --gNB --ninja + 0 + 0 + True + + + diff --git a/ci-scripts/xml_files/fr1_lte_2x2_quectel.xml b/ci-scripts/xml_files/fr1_lte_2x2_quectel.xml new file mode 100644 index 0000000000..ae7a4c92be --- /dev/null +++ b/ci-scripts/xml_files/fr1_lte_2x2_quectel.xml @@ -0,0 +1,143 @@ + + + TEST-LTE-TM2 + LTE 2x2 Ping DL UL with QUECTEL + tasks + 1 + + 030000 + 000002 + 010000 + 000001 + 050000 + 050001 + 000002 + 070000 + 070001 + 000001 + 010002 + 080000 + + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + yes + + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 + 0 + 0 + lte + yes + yes + 192.168.18.241 + + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20 pings + nrmodule2_quectel + -c 20 + 1 + 40 + + + Ping + Ping: 100 pings, size 1024 + nrmodule2_quectel + -c 100 -s 1024 -i 0,2 + 1 + 30 + + + + + Iperf + iperf (DL/26Mbps/UDP)(60 sec)(single-ue profile) + -u -b 26M -t 60 + DL + nrmodule2_quectel + 5 + single-ue + + + + Iperf + iperf (UL/7Mbps/UDP)(60 sec)(single-ue profile) + -u -b 7M -t 60 + UL + nrmodule2_quectel + 5 + single-ue + + + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_multi_node_build.xml b/ci-scripts/xml_files/fr1_multi_node_build.xml index 7b4eacef3a..60bc734e65 100644 --- a/ci-scripts/xml_files/fr1_multi_node_build.xml +++ b/ci-scripts/xml_files/fr1_multi_node_build.xml @@ -26,7 +26,7 @@ wrench 000001 000002 - 000003 000004 + 000004 000005 000003 @@ -37,6 +37,7 @@ 0 0 True + True @@ -53,6 +54,7 @@ 1 1 True + True @@ -62,5 +64,10 @@ 1 + + IdleSleep + Sleep + 120 + diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml new file mode 100644 index 0000000000..2516af9429 --- /dev/null +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml @@ -0,0 +1,152 @@ + + + TEST-NSA-FR1-TM2-Tab1 + NSA 2x2 Ping DL UL with QUECTEL + tasks + 1 + + 030000 + 040000 + 000002 + 010000 + 000001 + 050000 + 050001 + 000002 + 070000 + 070001 + 000001 + 010002 + 080001 + 080000 + + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + yes + + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 + 0 + 0 + lte + yes + yes + 192.168.18.241 + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf -q --usrp-tx-thread-config 1 + 1 + 1 + nr + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 60 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + nrmodule2_quectel + -c 20 + 5 + + + + Ping + Ping: 100pings in 20sec + nrmodule2_quectel + -c 100 -i 0,2 + 5 + + + + Iperf + iperf (DL/60Mbps/UDP)(60 sec)(single-ue profile) + -u -b 60M -t 60 + DL + nrmodule2_quectel + 5 + single-ue + + + + Iperf + iperf (UL/1Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 60 + UL + nrmodule2_quectel + 5 + single-ue + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml new file mode 100644 index 0000000000..52cf1ec6e8 --- /dev/null +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml @@ -0,0 +1,145 @@ + + + TEST-NSA-FR1-TM2-Tab2 + NSA 2x2 Attach-Detach with QUECTEL + tasks + 1 + + 031000 + 041000 + 000002 + 010000 + 000001 + 050000 + 000002 + 010004 + 000002 + 010003 + 000001 + 050000 + 000002 + 010004 + 000002 + 010003 + 000001 + 050000 + 000002 + 010002 + 080001 + 080000 + + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + yes + + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + Attach_UE + Attach Quectel + nrmodule2_quectel + + + + Detach_UE + Detach Quectel + nrmodule2_quectel + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 + 0 + 0 + lte + yes + yes + 192.168.18.241 + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf -q --usrp-tx-thread-config 1 + 1 + 1 + nr + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 60 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + nrmodule2_quectel + -c 20 + 5 + + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_nsa_base.xml b/ci-scripts/xml_files/fr1_nsa_base.xml new file mode 100644 index 0000000000..96bdc79f0f --- /dev/null +++ b/ci-scripts/xml_files/fr1_nsa_base.xml @@ -0,0 +1,162 @@ + + + TEST-NSA-FR1-TM1 + NSA FULL + tasks + + 010000 + 030000 + 040000 + 010001 + 000001 + 050000 + 050001 + 000001 + 060000 + 060001 + 000001 + 070000 + 070001 + 010002 + 000001 + 080001 + 080000 + 010003 + + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf + 0 + 0 + lte + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E + 1 + 1 + nr + + + + IdleSleep + Sleep + 20 + + + + Ping + Ping: 20pings in 20sec + -c 20 + 50 + + + + Ping + Ping: 100pings in 20sec + -c 100 -i 0.2 + 50 + + + + + Iperf + iperf (DL/2.5Mbps/UDP)(60 sec)(single-ue profile) + -u -b 2.5M -t 60 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/1.5Mbps/UDP)(60 sec)(single-ue profile) + -u -b 1.5M -t 60 -i 1 -R + 50 + single-ue + + + + + Iperf + iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) + -u -b 20M -t 20 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 -R + 50 + single-ue + + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_nsa_quectel.xml b/ci-scripts/xml_files/fr1_nsa_quectel.xml new file mode 100644 index 0000000000..6414f09b6b --- /dev/null +++ b/ci-scripts/xml_files/fr1_nsa_quectel.xml @@ -0,0 +1,153 @@ + + + TEST-NSA-FR1-TM1 + NSA Ping DL UL with QUECTEL + tasks + 1 + + 030000 + 040000 + 000002 + 010000 + 000001 + 050000 + 050001 + 000001 + 070000 + 000001 + 070001 + 000001 + 050000 + 050001 + 010002 + 080001 + 080000 + + + + + Initialize_UE + Initialize Quectel + idefix + yes + + + + + Terminate_UE + Terminate Quectel + idefix + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf + 0 + 0 + lte + yes + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E -q --RUs.[0].sdr_addrs "serial=30C51D4" + 1 + 1 + nr + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 + 1 + 15 + + + + Ping + Ping: 100pings in 20sec + idefix + -c 100 -i 0.2 + 1 + 15 + + + + Iperf + iperf (DL/60Mbps/UDP)(60 sec)(single-ue profile) + -u -b 60M -t 60 + DL + idefix + 3 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile) + -u -b 3M -t 60 + UL + idefix + 1 + single-ue + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml new file mode 100644 index 0000000000..2263f731c5 --- /dev/null +++ b/ci-scripts/xml_files/fr1_nsa_quectel_attach_detach.xml @@ -0,0 +1,168 @@ + + + TEST-NSA-FR1-TM1 + NSA Ping Attach Detach with QUECTEL + tasks + 1 + + 030000 + 040000 + 000002 + 010000 + 000001 + 050000 + 000001 + 010004 + 000001 + 010003 + 000001 + 050000 + 000001 + 010004 + 000001 + 010003 + 000001 + 050000 + 000001 + 010002 + 080001 + 080000 + + + + + Initialize_UE + Initialize Quectel + idefix + yes + + + + + Terminate_UE + Terminate Quectel + idefix + + + + Attach_UE + Attach Quectel + idefix + + + + Detach_UE + Detach Quectel + idefix + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf + 0 + 0 + lte + yes + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E -q + 1 + 1 + nr + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 + 50 + + + + Ping + Ping: 100pings in 20sec + idefix + -c 100 -i 0.2 + 50 + + + + Iperf + iperf (DL/20Mbps/UDP)(60 sec)(single-ue profile) + -u -b 20M -t 60 + DL + idefix + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile) + -u -b 3M -t 60 + UL + idefix + 50 + single-ue + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_multi_node_test.xml b/ci-scripts/xml_files/fr1_nsa_quectel_long.xml similarity index 52% rename from ci-scripts/xml_files/fr1_multi_node_test.xml rename to ci-scripts/xml_files/fr1_nsa_quectel_long.xml index 8c56f0bcec..21ff7a63c5 100644 --- a/ci-scripts/xml_files/fr1_multi_node_test.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel_long.xml @@ -21,19 +21,42 @@ --> - test-fr1-tm1 - Test-FR1-TM1 + TEST-NSA-FR1-TM1 + NSA Ping DL UL with QUECTEL (Longer) tasks 1 030000 040000 + 000002 + 010000 + 000001 + 050000 + 050001 + 000001 + 070000 000001 070001 - 070000 + 000001 + 010002 + 080001 + 080000 - - + + + + Initialize_UE + Initialize Quectel + idefix + + + + + Terminate_UE + Terminate Quectel + idefix + + Initialize_eNB @@ -42,12 +65,14 @@ 0 0 lte + yes + Initialize_eNB - Initialize gNB (3/4 sampling rate) - -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E -q 1 1 nr @@ -56,21 +81,67 @@ IdleSleep Sleep - 30 + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 + 50 + + + + Ping + Ping: 100pings in 20sec + idefix + -c 100 -i 0.2 + 50 + Iperf + iperf (DL/20Mbps/UDP)(600 sec)(single-ue profile) + -u -b 20M -t 600 + DL + idefix + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(600 sec)(single-ue profile) + -u -b 3M -t 600 + UL + idefix + 50 + single-ue + + + + Terminate_eNB Terminate eNB 0 0 + lte - + Terminate_eNB Terminate gNB 1 1 + nr diff --git a/ci-scripts/xml_files/fr1_oai_cn_deploy.xml b/ci-scripts/xml_files/fr1_oai_cn_deploy.xml new file mode 100644 index 0000000000..26dbebc329 --- /dev/null +++ b/ci-scripts/xml_files/fr1_oai_cn_deploy.xml @@ -0,0 +1,39 @@ + + + epc-deploy-tab + EPC-Deploy + log-in + + 000100 + + + + + + Deploy_EPC + Deploy all EPC containers + yaml_files/magma_nsa_20897 + + + diff --git a/ci-scripts/xml_files/fr1_oai_cn_undeploy.xml b/ci-scripts/xml_files/fr1_oai_cn_undeploy.xml new file mode 100644 index 0000000000..76192efea1 --- /dev/null +++ b/ci-scripts/xml_files/fr1_oai_cn_undeploy.xml @@ -0,0 +1,38 @@ + + + epc-undeploy-tab + EPC-Undeploy + log-out + + 000200 + + + + + + Undeploy_EPC + Undeploy all EPC containers + + + diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml b/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml new file mode 100644 index 0000000000..6c359abb8d --- /dev/null +++ b/ci-scripts/xml_files/fr1_sa_oaiue_b200.xml @@ -0,0 +1,123 @@ + + + TEST-SA-FR1-Tab1 + SA Ping DL UL with OAI NR UE + tasks + 1 + + 040000 + 000002 + 010000 + 000002 + 050000 + 050001 + 000001 + 010002 + 080000 + + + + + Initialize_OAI_UE + Initialize OAI UE + nr + --sa -O ../../../ci-scripts/conf_files/ue.sa.conf --usrp-args "serial=30C51D1" --numerology 1 -r 106 --band 78 -C 3319680000 --nokrnmod 1 --ue-txgain 0 -E + + + + Terminate_OAI_UE + Terminate OAI UE + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf --sa -q --usrp-tx-thread-config 1 + 0 + 0 + nr + yes + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping from CN to UE: 20pings in 20sec + -c 20 + 5 + + + + Ping + Ping from CN to UE: 100pings in 20sec + -c 100 -i 0.2 + 5 + + + + Iperf + iperf (DL/60Mbps/UDP)(60 sec)(single-ue profile) + -u -b 60M -t 60 + DL + nrmodule2_quectel + 5 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile) + -u -b 3M -t 60 + UL + nrmodule2_quectel + 5 + single-ue + + + + + Terminate_eNB + Terminate gNB + 0 + 0 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml new file mode 100644 index 0000000000..cd79e49f2c --- /dev/null +++ b/ci-scripts/xml_files/fr1_sa_oaiue_n310.xml @@ -0,0 +1,123 @@ + + + TEST-SA-FR1-Tab1 + SA Ping DL UL with OAI NR UE (N310) + tasks + 1 + + 040000 + 000002 + 010000 + 000002 + 050000 + 050001 + 000001 + 010002 + 080000 + + + + + Initialize_OAI_UE + Initialize OAI UE (N310) + nr + --sa -O ../../../ci-scripts/conf_files/ue.sa.conf --usrp-args "mgmt_addr=192.168.18.241,second_addr=192.168.10.2" --numerology 1 -r 106 --band 78 -C 3319680000 --nokrnmod 1 --ue-txgain 0 --ue-rxgain 70 --ue-fo-compensation + + + + Terminate_OAI_UE + Terminate OAI UE + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf --sa --usrp-tx-thread-config 1 + 0 + 0 + nr + yes + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping from CN to UE: 20pings in 20sec + -c 20 + 5 + + + + Ping + Ping from CN to UE: 100pings in 20sec + -c 100 -i 0.2 + 5 + + + + Iperf + iperf (DL/60Mbps/UDP)(60 sec)(single-ue profile) + -u -b 60M -t 60 + DL + nrmodule2_quectel + 5 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile) + -u -b 3M -t 60 + UL + nrmodule2_quectel + 5 + single-ue + + + + + Terminate_eNB + Terminate gNB + 0 + 0 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml b/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml new file mode 100644 index 0000000000..d527737b3c --- /dev/null +++ b/ci-scripts/xml_files/fr1_sa_oaiue_x300.xml @@ -0,0 +1,123 @@ + + + TEST-SA-FR1-Tab2 + SA Ping DL UL with OAI NR UE (X300) + tasks + 1 + + 040000 + 000002 + 010000 + 000002 + 050000 + 050001 + 000001 + 010002 + 080000 + + + + + Initialize_OAI_UE + Initialize OAI UE (X300) + nr + --sa -O ../../../ci-scripts/conf_files/ue.sa.conf --usrp-args "addr=192.168.60.2" --numerology 1 -r 106 --band 78 -C 3319680000 --nokrnmod 1 --ue-txgain 0 --ue-rxgain 70 --ue-fo-compensation + + + + Terminate_OAI_UE + Terminate OAI UE + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf --sa --usrp-tx-thread-config 1 + 0 + 0 + nr + yes + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping from CN to UE: 20pings in 20sec + -c 20 + 5 + + + + Ping + Ping from CN to UE: 100pings in 20sec + -c 100 -i 0.2 + 5 + + + + Iperf + iperf (DL/60Mbps/UDP)(60 sec)(single-ue profile) + -u -b 60M -t 60 + DL + nrmodule2_quectel + 5 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile) + -u -b 3M -t 60 + UL + nrmodule2_quectel + 5 + single-ue + + + + + Terminate_eNB + Terminate gNB + 0 + 0 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml new file mode 100644 index 0000000000..4db5bb64a5 --- /dev/null +++ b/ci-scripts/xml_files/fr1_sa_quectel.xml @@ -0,0 +1,131 @@ + + + TEST-SA-FR1-Tab1 + SA Ping DL UL with QUECTEL + tasks + 1 + + 040000 + 000002 + 010000 + 000001 + 050000 + 050001 + 070000 + 070001 + 000001 + 010002 + 080000 + + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + yes + + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 + 0 + 0 + nr + yes + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + nrmodule2_quectel + -c 20 + 1 + 15 + + + + Ping + Ping: 100pings in 20sec + nrmodule2_quectel + -c 100 -i 0,2 + 1 + 15 + + + + Iperf + iperf (DL/60Mbps/UDP)(60 sec)(single-ue profile) + -u -b 60M -t 60 + DL + nrmodule2_quectel + 5 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile) + -u -b 3M -t 60 + UL + nrmodule2_quectel + 5 + single-ue + + + + + Terminate_eNB + Terminate gNB + 0 + 0 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml new file mode 100644 index 0000000000..2088678707 --- /dev/null +++ b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml @@ -0,0 +1,129 @@ + + + TEST-SA-FR1-Tab3 + SA Ping DL UL with QUECTEL + tasks + 1 + + 040000 + 000002 + 010000 + 000001 + 050000 + 050001 + 070000 + 070001 + 000001 + 010002 + 080000 + + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + yes + + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 + 0 + 0 + nr + yes + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + nrmodule2_quectel + -c 20 + 5 + + + + Ping + Ping: 100pings in 20sec + nrmodule2_quectel + -c 100 -i 0,2 + 5 + + + + Iperf + iperf (DL/140Mbps/UDP)(60 sec)(single-ue profile) + -u -b 140M -t 60 + DL + nrmodule2_quectel + 5 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile) + -u -b 3M -t 60 + UL + nrmodule2_quectel + 5 + single-ue + + + + + Terminate_eNB + Terminate gNB + 0 + 0 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml new file mode 100644 index 0000000000..a9922bec52 --- /dev/null +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml @@ -0,0 +1,157 @@ + + + TEST-SA-FR1-Tab2 + SA Staged DL with QUECTEL + tasks + 1 + + 040000 + 000002 + 010000 + 000001 + 050000 + 000001 + 070000 + 000001 + 070001 + 000001 + 070002 + 000001 + 070003 + 000001 + 070004 + 000001 + 010002 + 080000 + + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + yes + + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 + 0 + 0 + nr + yes + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + nrmodule2_quectel + -c 20 + 1 + 15 + + + + + Iperf + iperf (DL/10Mbps/UDP)(30 sec)(single-ue profile) + -u -b 10M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/20Mbps/UDP)(30 sec)(single-ue profile) + -u -b 20M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/40Mbps/UDP)(30 sec)(single-ue profile) + -u -b 40M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/60Mbps/UDP)(30 sec)(single-ue profile) + -u -b 60M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/90Mbps/UDP)(30 sec)(single-ue profile) + -u -b 90M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + + + + Terminate_eNB + Terminate gNB + 0 + 0 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages_162prb.xml new file mode 100644 index 0000000000..4b2400a4ac --- /dev/null +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages_162prb.xml @@ -0,0 +1,166 @@ + + + TEST-SA-FR1-Tab4 + SA Staged DL with QUECTEL + tasks + 1 + + 040000 + 000002 + 010000 + 000001 + 050000 + 000001 + 070000 + 000001 + 070001 + 000001 + 070002 + 000001 + 070003 + 000001 + 070004 + 000001 + 070005 + 000001 + 010002 + 080000 + + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + yes + + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 + 0 + 0 + nr + yes + yes + 192.168.18.240 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + nrmodule2_quectel + -c 20 + 5 + + + + + Iperf + iperf (DL/10Mbps/UDP)(30 sec)(single-ue profile) + -u -b 10M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/20Mbps/UDP)(30 sec)(single-ue profile) + -u -b 20M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/40Mbps/UDP)(30 sec)(single-ue profile) + -u -b 40M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/60Mbps/UDP)(30 sec)(single-ue profile) + -u -b 60M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/90Mbps/UDP)(30 sec)(single-ue profile) + -u -b 90M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + Iperf + iperf (DL/140Mbps/UDP)(30 sec)(single-ue profile) + -u -b 140M -t 30 + DL + nrmodule2_quectel + 5 + single-ue + + + + + Terminate_eNB + Terminate gNB + 0 + 0 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_usrp210_band7_deploy_test_05mhz_tm1.xml b/ci-scripts/xml_files/fr1_usrp210_band7_deploy_test_05mhz_tm1.xml new file mode 100644 index 0000000000..3d04fdeb29 --- /dev/null +++ b/ci-scripts/xml_files/fr1_usrp210_band7_deploy_test_05mhz_tm1.xml @@ -0,0 +1,133 @@ + + + test-deploy-enb-mono + Test-Deploy-eNB-Mono + tasks + 1 + + 040101 + 030101 000020 040301 000021 040501 040601 040611 040641 040651 040401 040201 030201 + + + + + IdleSleep + Waiting for 60 seconds + 60 + + + + IdleSleep + Waiting for 10 seconds + 10 + + + + CheckStatusUE + Check UE(s) status before attachment + 0 + + + + CheckStatusUE + Check UE(s) status after attachment + 1 + + + + Deploy_Object + Deploy eNB (FDD/Band7/5MHz) in a container + ci-scripts/yaml_files/fr1_enb_mono_fdd_tim + 0 + 0 + + + + Undeploy_Object + Undeploy eNB + ci-scripts/yaml_files/fr1_enb_mono_fdd_tim + 0 + 0 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec) + -u -b 15M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/TCP)(30 sec) + -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/7.5Mbps/UDP)(30 sec) + -u -b 7.5M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/TCP)(30 sec) + -t 30 -i 1 -R + 50 + single-ue + + + diff --git a/ci-scripts/xml_files/fr1_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/fr1_usrp210_band7_test_05mhz_tm1.xml new file mode 100644 index 0000000000..ea25d5b694 --- /dev/null +++ b/ci-scripts/xml_files/fr1_usrp210_band7_test_05mhz_tm1.xml @@ -0,0 +1,151 @@ + + + test-05-tm1 + Test-05MHz-TM1 + tasks + + 030201 + 040101 + 030101 040301 000001 040501 040603 040401 030201 + + + + + IdleSleep + Sleep + 5 + + + + Initialize_eNB + Initialize eNB (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].plmn_list.[0].mcc 311 --eNBs.[0].plmn_list.[0].mnc 480 --eNBs.[0].plmn_list.[0].mnc_length 3 --eNBs.[0].component_carriers.[0].Nid_cell 10 + + + + Terminate_eNB + Terminate eNB + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(balanced profile) + -u -b 15M -t 30 -i 1 + 50 + balanced + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(single-ue profile) + -u -b 15M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(unbalanced profile) + -u -b 15M -t 30 -i 1 + 50 + unbalanced + + + + Iperf + iperf (5MHz - DL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm + 50 + balanced + + + + Iperf + iperf (5MHz - UL/9Mbps/UDP)(30 sec)(balanced profile) + -u -b 9M -t 30 -i 1 -R + 50 + balanced + + + + Iperf + iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile) + -u -b 9M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm -R + 50 + balanced + + + diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml index c51093c178..b1e9697be2 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml @@ -52,7 +52,7 @@ Initialize_OAI_UE Initialize NR UE USRP - --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --threadoffset 16 --rrc_config_path . + --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 50 --rrc_config_path . --dlsch-parallel 4 NR diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml index b4290ae6a3..2c44ead8ea 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml @@ -52,7 +52,7 @@ Initialize_OAI_UE Initialize NR UE USRP - --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --threadoffset 16 --rrc_config_path . + --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 75 --rrc_config_path . --dlsch-parallel 4 NR diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml new file mode 100644 index 0000000000..9e798afdc4 --- /dev/null +++ b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml @@ -0,0 +1,53 @@ + + + gNB-PHY-Test + Run-gNB-PHY-Test + tasks + 3 + +090101 000001 090109 + + + + + Initialize_eNB + Initialize gNB USRP + -O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test -q -U 787200 -T 106 -t 28 -D 130175 -m 28 -M 106 + NR + + + + IdleSleep + Sleep + 300 + + + + + Terminate_eNB + Terminate gNB + NR + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40_build.xml b/ci-scripts/xml_files/if4p5_usrp210_band40_build.xml index ab221c918d..d383dbb61b 100644 --- a/ci-scripts/xml_files/if4p5_usrp210_band40_build.xml +++ b/ci-scripts/xml_files/if4p5_usrp210_band40_build.xml @@ -33,7 +33,7 @@ Build_eNB Build eNB (USRP -- Ethernet Fronthaul) - -w USRP -c --eNB + -w USRP -c --eNB --ninja diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40_test_10mhz.xml b/ci-scripts/xml_files/if4p5_usrp210_band40_test_10mhz.xml index 8276294e9a..9224c67fe7 100644 --- a/ci-scripts/xml_files/if4p5_usrp210_band40_test_10mhz.xml +++ b/ci-scripts/xml_files/if4p5_usrp210_band40_test_10mhz.xml @@ -25,6 +25,8 @@ Test-10MHz tasks 2 + True + 040612 030201 040101 diff --git a/ci-scripts/xml_files/if4p5_usrp210_band7_build.xml b/ci-scripts/xml_files/if4p5_usrp210_band7_build.xml index ab221c918d..d383dbb61b 100644 --- a/ci-scripts/xml_files/if4p5_usrp210_band7_build.xml +++ b/ci-scripts/xml_files/if4p5_usrp210_band7_build.xml @@ -33,7 +33,7 @@ Build_eNB Build eNB (USRP -- Ethernet Fronthaul) - -w USRP -c --eNB + -w USRP -c --eNB --ninja diff --git a/ci-scripts/xml_files/multi_rru_band38_build.xml b/ci-scripts/xml_files/multi_rru_band38_build.xml index ba45eab10a..1370a3a396 100644 --- a/ci-scripts/xml_files/multi_rru_band38_build.xml +++ b/ci-scripts/xml_files/multi_rru_band38_build.xml @@ -26,7 +26,7 @@ wrench 010101 010102 010103 - 000101 000102 000103 + 000102 000103 000101 @@ -50,7 +50,7 @@ Build_eNB Build Master RRU - -w USRP -c --eNB --ninja + -w USRP -c --RU --ninja 1 1 True @@ -59,7 +59,7 @@ WaitEndBuild_eNB Wait for end of Build Master RRU - -w USRP -c --eNB --ninja + -w USRP -c --RU --ninja 1 1 @@ -67,7 +67,7 @@ Build_eNB Build Slave RRU - -w USRP -c --eNB --ninja + -w USRP -c --RU --ninja 2 2 True @@ -76,7 +76,7 @@ WaitEndBuild_eNB Wait for end of Build Slave RRU - -w USRP -c --eNB --ninja + -w USRP -c --RU --ninja 2 2 diff --git a/ci-scripts/xml_files/physim_deploy_run.xml b/ci-scripts/xml_files/physim_deploy_run.xml new file mode 100644 index 0000000000..63152c1fb5 --- /dev/null +++ b/ci-scripts/xml_files/physim_deploy_run.xml @@ -0,0 +1,37 @@ + + + build-tab + Physical Simulators Check + wrench + + 010201 + + + + + Deploy_Run_PhySim + Deploy and run physical simulator on openshift + + + diff --git a/ci-scripts/xml_files/sa_cn5g_closure.xml b/ci-scripts/xml_files/sa_cn5g_closure.xml new file mode 100644 index 0000000000..7174da3b7b --- /dev/null +++ b/ci-scripts/xml_files/sa_cn5g_closure.xml @@ -0,0 +1,37 @@ + + + cn5g-closure + CN5G-Closure + log-out + +060000 + + + + + Terminate_5GCN + Terminate 5G Core + + + diff --git a/ci-scripts/xml_files/sa_cn5g_start.xml b/ci-scripts/xml_files/sa_cn5g_start.xml new file mode 100644 index 0000000000..a524610569 --- /dev/null +++ b/ci-scripts/xml_files/sa_cn5g_start.xml @@ -0,0 +1,38 @@ + + + cn5g-start-tab + CN5G-Start + log-in + + 000100 + + + + + + Initialize_5GCN + Initialize 5G Core + + + diff --git a/ci-scripts/xml_files/ue_band20_build.xml b/ci-scripts/xml_files/ue_band20_build.xml index 9ca1a2b234..d867929630 100644 --- a/ci-scripts/xml_files/ue_band20_build.xml +++ b/ci-scripts/xml_files/ue_band20_build.xml @@ -32,7 +32,7 @@ Build_OAI_UE Build OAI UE - -w USRP --UE + -w USRP --UE --ninja diff --git a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_build.xml b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_build.xml index c5a912a33d..0ac6bfcc0d 100644 --- a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_build.xml +++ b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_build.xml @@ -42,7 +42,7 @@ Build_eNB Build Slave eNB (USRP) - -w USRP -c --eNB + -w USRP -c --eNB --ninja 1 1 diff --git a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_test_05mhz_tm1.xml b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_test_05mhz_tm1.xml index c43be75a87..7256c985c5 100644 --- a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_test_05mhz_tm1.xml +++ b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_test_05mhz_tm1.xml @@ -26,6 +26,7 @@ Test-X2-HO-FDD-05MHz-TM1 tasks 2 + True 030201 030202 040101 diff --git a/ci-scripts/yaml_files/4g_rfsimulator/README.md b/ci-scripts/yaml_files/4g_rfsimulator/README.md new file mode 100644 index 0000000000..b2a7f8e30c --- /dev/null +++ b/ci-scripts/yaml_files/4g_rfsimulator/README.md @@ -0,0 +1,504 @@ + + + + + +
+ + + + + + OAI Full Stack 4G-LTE RF simulation with containers +
+ +This page is only valid for an `Ubuntu18` host. + +**TABLE OF CONTENTS** + +1. [Retrieving the images on Docker-Hub](#1-retrieving-the-images-on-docker-hub) +2. [Deploy containers](#2-deploy-containers) + 1. [Deploy and Configure Cassandra Database](#21-deploy-and-configure-cassandra-database) + 2. [Deploy OAI CN4G containers](#22-deploy-oai-cn4g-containers) + 3. [Deploy OAI eNB in RF simulator mode](#23-deploy-oai-enb-in-rf-simulator-mode) + 4. [Deploy OAI LTE UE in RF simulator mode](#24-deploy-oai-lte-ue-in-rf-simulator-mode) +3. [Check traffic](#3-check-traffic) +4. [Un-deployment](#4-un-deployment) +5. [Explanation on the configuration](#5-explanation-on-the-configuration) + 1. [UE IMSI and Keys](#51-ue-imsi-and-keys) + 2. [PLMN and TAI](#52-plmn-and-tai) + 3. [Access to Internet](#53-access-to-internet) + +# 1. Retrieving the images on Docker-Hub # + +Currently the images are hosted under the user account `rdefosseoai`. + +This may change in the future. + +Once again you may need to log on [docker-hub](https://hub.docker.com/) if your organization has reached pulling limit as `anonymous`. + +```bash +$ docker login +Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. +Username: +Password: +``` + +Now pull images. + +```bash +$ docker pull cassandra:2.1 +$ docker pull rdefosseoai/oai-hss:latest +$ docker pull rdefosseoai/oai-mme:latest +$ docker pull rdefosseoai/oai-spgwc:latest +$ docker pull rdefosseoai/oai-spgwu-tiny:latest + +$ docker pull rdefosseoai/oai-enb:develop +$ docker pull rdefosseoai/oai-lte-ue:develop +``` + +And **re-tag** them for tutorials' docker-compose file to work. + +```bash +$ docker image tag rdefosseoai/oai-spgwc:latest oai-spgwc:latest +$ docker image tag rdefosseoai/oai-hss:latest oai-hss:latest +$ docker image tag rdefosseoai/oai-spgwu-tiny:latest oai-spgwu-tiny:latest +$ docker image tag rdefosseoai/oai-mme:latest oai-mme:latest + +$ docker image tag rdefosseoai/oai-enb:develop oai-enb:develop +$ docker image tag rdefosseoai/oai-lte-ue:develop oai-lte-ue:develop +``` + +```bash +$ docker logout +``` + +How to build the Traffic-Generator image is explained [here](https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/GENERATE_TRAFFIC.md#1-build-a-traffic-generator-image). + +# 2. Deploy containers # + +**CAUTION: this SHALL be done in multiple steps.** + +**Just `docker-compose up -d` WILL NOT WORK!** + +All the following commands **SHALL** be run from the `ci-scripts/yaml_files/4g_rfsimulator` folder. + +## 2.1. Deploy and Configure Cassandra Database ## + +It is very crutial that the Cassandra DB is fully configured before you do anything else! + +```bash +$ cd ci-scripts/yaml_files/4g_rfsimulator +$ docker-compose up -d db_init +Creating network "rfsim4g-oai-private-net" with the default driver +Creating network "rfsim4g-oai-public-net" with the default driver +Creating rfsim4g-cassandra ... done +Creating rfsim4g-db-init ... done + +$ docker logs rfsim4g-db-init --follow +Connection error: ('Unable to connect to any servers', {'192.168.68.2': error(111, "Tried connecting to [('192.168.68.2', 9042)]. Last error: Connection refused")}) +... +Connection error: ('Unable to connect to any servers', {'192.168.68.2': error(111, "Tried connecting to [('192.168.68.2', 9042)]. Last error: Connection refused")}) +OK +``` + +**You SHALL wait until you HAVE the `OK` message in the logs!** + +```bash +$ docker rm rfsim4g-db-init +``` + +At this point, you can prepare a capture on the newly-created public docker bridge: + +```bash +$ ifconfig rfsim4g-public + inet 192.168.61.1 netmask 255.255.255.192 broadcast 192.168.61.63 + ether 02:42:8f:dd:ba:5a txqueuelen 0 (Ethernet) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +$ sudo tshark -i rfsim4g-public -f 'port 3868 or port 2123 or port 36412 or port 36422 or port 46520 or port 8805' -w /tmp/my-oai-control-plane.pcap +``` + +**BE CAREFUL: please use that filter or you will also capture the data-plane with IQ samples between `eNB` and `LTE-UE`.** + +**and your capture WILL become huge (10s of Gbytes).** + +## 2.2. Deploy OAI CN4G containers ## + +```bash +$ docker-compose up -d oai_mme oai_spgwu trf_gen +rfsim4g-cassandra is up-to-date +Creating rfsim4g-trf-gen ... done +Creating rfsim4g-oai-hss ... done +Creating rfsim4g-oai-mme ... done +Creating rfsim4g-oai-spgwc ... done +Creating rfsim4g-oai-spgwu-tiny ... done +``` + +You shall wait until all containers are `healthy`. About 10 seconds! + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------------------------------- +rfsim4g-cassandra docker-entrypoint.sh cassa ... Up (healthy) 7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp +rfsim4g-oai-hss /openair-hss/bin/entrypoin ... Up (healthy) 5868/tcp, 9042/tcp, 9080/tcp, 9081/tcp +rfsim4g-oai-mme /openair-mme/bin/entrypoin ... Up (healthy) 2123/udp, 3870/tcp, 5870/tcp +rfsim4g-oai-spgwc /openair-spgwc/bin/entrypo ... Up (healthy) 2123/udp, 8805/udp +rfsim4g-oai-spgwu-tiny /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +rfsim4g-trf-gen /bin/bash -c ip route add ... Up (healthy) +``` + +## 2.3. Deploy OAI eNB in RF simulator mode ## + +```bash +$ docker-compose up -d enb +Creating rfsim4g-oai-enb ... done +``` + +Again wait for the healthy state: + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------------------------------- +rfsim4g-cassandra docker-entrypoint.sh cassa ... Up (healthy) 7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp +rfsim4g-oai-enb /opt/oai-enb/bin/entrypoin ... Up (healthy) 2152/udp, 36412/udp, 36422/udp +rfsim4g-oai-hss /openair-hss/bin/entrypoin ... Up (healthy) 5868/tcp, 9042/tcp, 9080/tcp, 9081/tcp +rfsim4g-oai-mme /openair-mme/bin/entrypoin ... Up (healthy) 2123/udp, 3870/tcp, 5870/tcp +rfsim4g-oai-spgwc /openair-spgwc/bin/entrypo ... Up (healthy) 2123/udp, 8805/udp +rfsim4g-oai-spgwu-tiny /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +rfsim4g-trf-gen /bin/bash -c ip route add ... Up (healthy) +``` + +Check if the eNB connected to MME: + +```bash +$ docker logs rfsim4g-oai-mme +... +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0039 ======================================= STATISTICS ============================================ + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0042 | Current Status| Added since last display| Removed since last display | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0048 Connected eNBs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0054 Attached UEs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0060 Connected UEs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0066 Default Bearers| 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0072 S1-U Bearers | 0 | 0 | 0 | + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0075 ======================================= STATISTICS ============================================ + +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0469 Client association changed: 0 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0101 ---------------------- +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0102 SCTP Status: +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0103 assoc id .....: 675 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0104 state ........: 4 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0105 instrms ......: 2 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0106 outstrms .....: 2 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0108 fragmentation : 1452 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0109 pending data .: 0 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0110 unack data ...: 0 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0111 rwnd .........: 106496 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0112 peer info : +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0114 state ....: 2 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0116 cwnd .....: 4380 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0118 srtt .....: 0 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0120 rto ......: 3000 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0122 mtu ......: 1500 +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0123 ---------------------- +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0479 New connection +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0205 ---------------------- +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0206 Local addresses: +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0217 - [192.168.61.3] +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0234 ---------------------- +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0151 ---------------------- +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0152 Peer addresses: +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0163 - [192.168.61.20] +DEBUG SCTP enair-mme/src/sctp/sctp_common.c:0178 ---------------------- +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0554 SCTP RETURNING!! +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0547 [675][44] Msg of length 51 received from port 36412, on stream 0, PPID 18 +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0554 SCTP RETURNING!! +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:2826 Create eNB context for assoc_id: 675 +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:0361 S1-Setup-Request macroENB_ID.size 3 (should be 20) +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:0321 New s1 setup request incoming from macro eNB id: 00e01 +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:0423 Adding eNB to the list of served eNBs +DEBUG S1AP mme/src/s1ap/s1ap_mme_handlers.c:0438 Adding eNB id 3585 to the list of served eNBs +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0283 [44][675] Sending buffer 0x7f9394009f90 of 27 bytes on stream 0 with ppid 18 +DEBUG SCTP rc/sctp/sctp_primitives_server.c:0296 Successfully sent 27 bytes on stream 0 +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0039 ======================================= STATISTICS ============================================ + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0042 | Current Status| Added since last display| Removed since last display | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0048 Connected eNBs | 1 | 1 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0054 Attached UEs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0060 Connected UEs | 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0066 Default Bearers| 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0072 S1-U Bearers | 0 | 0 | 0 | + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0075 ======================================= STATISTICS ============================================ +... +``` + +## 2.4. Deploy OAI LTE UE in RF simulator mode ## + +```bash +$ docker-compose up -d oai_ue0 +Creating rfsim4g-oai-lte-ue0 ... done +``` + +Again a bit of patience: + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------------------------------- +rfsim4g-cassandra docker-entrypoint.sh cassa ... Up (healthy) 7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp +rfsim4g-oai-enb /opt/oai-enb/bin/entrypoin ... Up (healthy) 2152/udp, 36412/udp, 36422/udp +rfsim4g-oai-hss /openair-hss/bin/entrypoin ... Up (healthy) 5868/tcp, 9042/tcp, 9080/tcp, 9081/tcp +rfsim4g-oai-lte-ue0 /opt/oai-lte-ue/bin/entryp ... Up (healthy) 10000/tcp +rfsim4g-oai-mme /openair-mme/bin/entrypoin ... Up (healthy) 2123/udp, 3870/tcp, 5870/tcp +rfsim4g-oai-spgwc /openair-spgwc/bin/entrypo ... Up (healthy) 2123/udp, 8805/udp +rfsim4g-oai-spgwu-tiny /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +rfsim4g-trf-gen /bin/bash -c ip route add ... Up (healthy) +Creating rfsim4g-oai-enb ... done +``` + +Making sure the OAI UE is connected: + +```bash +$ docker logs rfsim4g-oai-enb +... +[RRC] RRCConnectionReconfiguration Encoded 1098 bits (138 bytes) +[RRC] [eNB 0] Frame 0, Logical Channel DL-DCCH, Generate LTE_RRCConnectionReconfiguration (bytes 138, UE id 617b) +[RRC] sent RRC_DCCH_DATA_REQ to TASK_PDCP_ENB +[PDCP] [FRAME 00000][eNB][MOD 00][RNTI 617b][SRB 02] Action ADD LCID 2 (SRB id 2) configured with SN size 5 bits and RLC AM +[PDCP] [FRAME 00000][eNB][MOD 00][RNTI 617b][DRB 01] Action ADD LCID 3 (DRB id 1) configured with SN size 12 bits and RLC AM +[SCTP] Successfully sent 46 bytes on stream 1 for assoc_id 676 +[RRC] [FRAME 00000][eNB][MOD 00][RNTI 617b] UE State = RRC_RECONFIGURED (default DRB, xid 0) +[PDCP] [FRAME 00000][eNB][MOD 00][RNTI 617b][SRB 02] Action MODIFY LCID 2 RB id 2 reconfigured with SN size 5 and RLC AM +[PDCP] [FRAME 00000][eNB][MOD 00][RNTI 617b][DRB 01] Action MODIFY LCID 3 RB id 1 reconfigured with SN size 1 and RLC AM +[RRC] [eNB 0] Frame 0 CC 0 : SRB2 is now active +[RRC] [eNB 0] Frame 0 : Logical Channel UL-DCCH, Received LTE_RRCConnectionReconfigurationComplete from UE rnti 617b, reconfiguring DRB 1/LCID 3 +[RRC] [eNB 0] Frame 0 : Logical Channel UL-DCCH, Received LTE_RRCConnectionReconfigurationComplete, reconfiguring DRB 1/LCID 3 +[MAC] UE 0 RNTI 617b adding LC 3 idx 2 to scheduling control (total 3) +[MAC] Added physicalConfigDedicated 0x7f98e0004950 for 0.0 +[S1AP] initial_ctxt_resp_p: e_rab ID 5, enb_addr 192.168.61.20, SIZE 4 +[SCTP] Successfully sent 40 bytes on stream 1 for assoc_id 676 +[SCTP] Successfully sent 61 bytes on stream 1 for assoc_id 676 +... +``` + +On the MME: + +```bash +$ docker logs rfsim4g-oai-mme +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0039 ======================================= STATISTICS ============================================ + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0042 | Current Status| Added since last display| Removed since last display | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0048 Connected eNBs | 1 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0054 Attached UEs | 1 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0060 Connected UEs | 1 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0066 Default Bearers| 0 | 0 | 0 | +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0072 S1-U Bearers | 0 | 0 | 0 | + +DEBUG MME-AP src/mme_app/mme_app_statistics.c:0075 ======================================= STATISTICS ============================================ +``` + +On the LTE UE: + +```bash +$ docker exec rfsim4g-oai-lte-ue0 /bin/bash -c "ifconfig" +eth0: flags=4163 mtu 1500 + inet 192.168.61.30 netmask 255.255.255.192 broadcast 192.168.61.63 + ether 02:42:c0:a8:3d:1e txqueuelen 0 (Ethernet) + RX packets 1109931 bytes 8078031934 (8.0 GB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 1232068 bytes 7798928848 (7.7 GB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +lo: flags=73 mtu 65536 + inet 127.0.0.1 netmask 255.0.0.0 + loop txqueuelen 1000 (Local Loopback) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +oaitun_ue1: flags=4305 mtu 1500 + inet 12.0.0.2 netmask 255.0.0.0 destination 12.0.0.2 + unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +oaitun_uem1: flags=4305 mtu 1500 + inet 10.0.2.2 netmask 255.255.255.0 destination 10.0.2.2 + unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +``` + +The tunnel `oaitun_ue1` SHALL be mounted and with an IP address in the `12.0.0.xxx` range. + +# 3. Check traffic # + +```bash +$ docker exec rfsim4g-oai-lte-ue0 /bin/bash -c "ping -c 2 www.lemonde.fr" +PING s2.shared.global.fastly.net (151.101.122.217) 56(84) bytes of data. +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=1 ttl=54 time=12.9 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=2 ttl=54 time=12.9 ms + +--- s2.shared.global.fastly.net ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 12.940/12.965/12.990/0.025 ms + +$ docker exec rfsim4g-oai-lte-ue0 /bin/bash -c "ping -I oaitun_ue1 -c 2 www.lemonde.fr" +PING s2.shared.global.fastly.net (151.101.122.217) from 12.0.0.2 oaitun_ue1: 56(84) bytes of data. +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=1 ttl=53 time=23.6 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=2 ttl=53 time=29.5 ms + +--- s2.shared.global.fastly.net ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 23.659/26.626/29.593/2.967 ms +``` + +The 1st ping command is NOT using the OAI stack. My network infrastructure has a response of `13 ms` to reach this website. + +The 2nd ping command is using the OAI stack. So the stack takes `26.6 - 12.9 = 13.7 ms`. + +# 4. Un-deployment # + +```bash +$ docker-compose down +Stopping rfsim4g-oai-lte-ue0 ... done +Stopping rfsim4g-oai-enb ... done +Stopping rfsim4g-oai-spgwu-tiny ... done +Stopping rfsim4g-oai-spgwc ... done +Stopping rfsim4g-oai-mme ... done +Stopping rfsim4g-oai-hss ... done +Stopping rfsim4g-trf-gen ... done +Stopping rfsim4g-cassandra ... done +Removing rfsim4g-oai-lte-ue0 ... done +Removing rfsim4g-oai-enb ... done +Removing rfsim4g-oai-spgwu-tiny ... done +Removing rfsim4g-oai-spgwc ... done +Removing rfsim4g-oai-mme ... done +Removing rfsim4g-oai-hss ... done +Removing rfsim4g-trf-gen ... done +Removing rfsim4g-cassandra ... done +Removing network rfsim4g-oai-private-net +Removing network rfsim4g-oai-public-net +``` + +# 5. Explanation on the configuration # + +With a single `docker-compose.yml` file, it is easier to explain how I made the full connection. + +Try to modify as little as possible. And if you don't understand a field/value, you'd better NOT modify it. + +## 5.1. UE IMSI and Keys ## + +in HSS config: + +```yaml + OP_KEY: 1006020f0a478bf6b699f15c062e42b3 + LTE_K: fec86ba6eb707ed08905757b1bb44b8f + APN1: oai.ipv4 + APN2: internet + FIRST_IMSI: 208960100000001 + NB_USERS: 10 +``` + +in UE config: + +```yaml + MCC: '208' + MNC: '96' + SHORT_IMSI: '0100000001' + LTE_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'c42449363bbad02b66d16bc975d77cc1' + MSISDN: '001011234561010' + HPLMN: 20896 +``` + +As you can see: `LTE_K` and `LTE_KEY` are the same value. And `OP_KEY` and `OPC` can be deduced from each other. Look in HSS logs. + +```bash +$ docker logs rfsim4g-oai-hss +... +Compute opc: + K: FEC86BA6EB707ED08905757B1BB44B8F <== `LTE_K` + In: 1006020F0A478BF6B699F15C062E42B3 <== `OP_KEY` + Rinj: D4224B3931FD5BDDD0489A9573F93E72 + Out: C42449363BBAD02B66D16BC975D77CC1 <== `OPC` +... +``` + +In HSS, I've provisioned 10 users starting at `208960100000001` (`FIRST_IMSI` and `NB_USERS`). + +My 1st UE IMSI is an aggregation of `MCC`, `MNC`, `SHORT_IMSI`. + +## 5.2. PLMN and TAI ## + +in MME config: + +```yaml + REALM: openairinterface.org +.. + MCC: '208' + MNC: '96' + MME_GID: 32768 + MME_CODE: 3 + TAC_0: 1 + TAC_1: 2 + TAC_2: 3 + MME_FQDN: mme.openairinterface.org +``` + +in SPGW-C/-U configs: + +```yaml + MCC: '208' + MNC: '96' + MNC03: '096' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org +``` + +in eNB config: + +```yaml + MCC: '208' + MNC: '96' + MNC_LENGTH: 2 + TAC: 1 +``` + +The values SHALL match, and `TAC` shall match `TAC_0` from MME. + +## 5.3. Access to Internet ## + +In my traffic test, I was able to ping outside of my local network. + +in SPGW-C config: + +```yaml + DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129 + DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 + PUSH_PROTOCOL_OPTION: 'true' +``` + +in SPGW-U config: + +```yaml + NETWORK_UE_NAT_OPTION: 'yes' +``` + +Please put your own DNS server IP adress. + +And you may have to play with `PUSH_PROTOCOL_OPTION` and `NETWORK_UE_NAT_OPTION` depending on your network. + diff --git a/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml new file mode 100644 index 0000000000..32e4bd41e8 --- /dev/null +++ b/ci-scripts/yaml_files/4g_rfsimulator/docker-compose.yml @@ -0,0 +1,272 @@ +version: '3.8' + +services: + cassandra: + image: cassandra:2.1 + container_name: rfsim4g-cassandra + networks: + private_net: + ipv4_address: 192.168.68.2 + environment: + CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster" + CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch + healthcheck: + test: /bin/bash -c "nodetool status" + interval: 10s + timeout: 5s + retries: 5 + + db_init: + image: cassandra:2.1 + container_name: rfsim4g-db-init + depends_on: [cassandra] + deploy: + restart_policy: + condition: on-failure + max_attempts: 10 + networks: + private_net: + ipv4_address: 192.168.68.4 + volumes: + - ./oai_db.cql:/home/oai_db.cql + entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.2 && echo 'OK'" + + oai_hss: + image: oai-hss:latest + container_name: rfsim4g-oai-hss + privileged: true + depends_on: [cassandra] + networks: + private_net: + ipv4_address: 192.168.68.3 + public_net: + ipv4_address: 192.168.61.2 + environment: + REALM: openairinterface.org + HSS_FQDN: hss.openairinterface.org + PREFIX: /openair-hss/etc + cassandra_Server_IP: 192.168.68.2 + OP_KEY: 1006020f0a478bf6b699f15c062e42b3 + LTE_K: fec86ba6eb707ed08905757b1bb44b8f + APN1: oai.ipv4 + APN2: internet + FIRST_IMSI: 208960100000001 + NB_USERS: 10 + healthcheck: + test: /bin/bash -c "pgrep oai_hss" + interval: 10s + timeout: 5s + retries: 5 + + oai_mme: + image: oai-mme:latest + container_name: rfsim4g-oai-mme + privileged: true + depends_on: [oai_hss] + networks: + public_net: + ipv4_address: 192.168.61.3 + environment: + REALM: openairinterface.org + PREFIX: /openair-mme/etc + INSTANCE: 1 + PID_DIRECTORY: /var/run + HSS_IP_ADDR: 192.168.61.2 + HSS_HOSTNAME: hss + HSS_FQDN: hss.openairinterface.org + HSS_REALM: openairinterface.org + MCC: '208' + MNC: '96' + MME_GID: 32768 + MME_CODE: 3 + TAC_0: 1 + TAC_1: 2 + TAC_2: 3 + MME_FQDN: mme.openairinterface.org + MME_S6A_IP_ADDR: 192.168.61.3 + MME_INTERFACE_NAME_FOR_S1_MME: eth0 + MME_IPV4_ADDRESS_FOR_S1_MME: 192.168.61.3 + MME_INTERFACE_NAME_FOR_S11: eth0 + MME_IPV4_ADDRESS_FOR_S11: 192.168.61.3 + MME_INTERFACE_NAME_FOR_S10: lo + MME_IPV4_ADDRESS_FOR_S10: 127.0.0.10 + OUTPUT: CONSOLE + SGW_IPV4_ADDRESS_FOR_S11_0: 192.168.61.4 + PEER_MME_IPV4_ADDRESS_FOR_S10_0: 0.0.0.0 + PEER_MME_IPV4_ADDRESS_FOR_S10_1: 0.0.0.0 + MCC_SGW_0: '208' + MNC3_SGW_0: '096' + TAC_LB_SGW_0: '01' + TAC_HB_SGW_0: '00' + MCC_MME_0: '208' + MNC3_MME_0: '096' + TAC_LB_MME_0: '02' + TAC_HB_MME_0: '00' + MCC_MME_1: '208' + MNC3_MME_1: '096' + TAC_LB_MME_1: '03' + TAC_HB_MME_1: '00' + TAC_LB_SGW_TEST_0: '03' + TAC_HB_SGW_TEST_0: '00' + SGW_IPV4_ADDRESS_FOR_S11_TEST_0: 0.0.0.0 + healthcheck: + test: /bin/bash -c "pgrep oai_mme" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwc: + image: oai-spgwc:latest + privileged: true + depends_on: [oai_mme] + container_name: rfsim4g-oai-spgwc + networks: + public_net: + ipv4_address: 192.168.61.4 + environment: + TZ: Europe/Paris + SGW_INTERFACE_NAME_FOR_S11: eth0 + PGW_INTERFACE_NAME_FOR_SX: eth0 + DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129 + DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 + PUSH_PROTOCOL_OPTION: 'true' + APN_NI_1: oai.ipv4 + APN_NI_2: oai.ipv4_2 + DEFAULT_APN_NI_1: oai.ipv4 + UE_IP_ADDRESS_POOL_1: '12.0.0.2 - 12.0.0.254' + UE_IP_ADDRESS_POOL_2: '12.1.1.2 - 12.1.1.254' + MCC: '208' + MNC: '96' + MNC03: '096' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org + healthcheck: + test: /bin/bash -c "pgrep oai_spgwc" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwu: + image: oai-spgwu-tiny:latest + privileged: true + container_name: rfsim4g-oai-spgwu-tiny + depends_on: [oai_spgwc] + networks: + public_net: + ipv4_address: 192.168.61.5 + environment: + TZ: Europe/Paris + PID_DIRECTORY: /var/run + INSTANCE: 1 + SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0 + PGW_INTERFACE_NAME_FOR_SGI: eth0 + SGW_INTERFACE_NAME_FOR_SX: eth0 + SPGWC0_IP_ADDRESS: 192.168.61.4 + NETWORK_UE_IP: '12.0.0.0/24' + NETWORK_UE_NAT_OPTION: 'yes' + MCC: '208' + MNC: '96' + MNC03: '096' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org + healthcheck: + test: /bin/bash -c "pgrep oai_spgwu" + interval: 10s + timeout: 5s + retries: 5 + + trf_gen: + image: trf-gen:production + privileged: true + container_name: rfsim4g-trf-gen + networks: + public_net: + ipv4_address: 192.168.61.11 + entrypoint: /bin/bash -c "ip route add 12.0.0.0/24 via 192.168.61.5 dev eth0; sleep infinity" + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.61.5" + interval: 10s + timeout: 5s + retries: 5 + + enb: + image: oai-enb:develop + privileged: true + container_name: rfsim4g-oai-enb + networks: + public_net: + ipv4_address: 192.168.61.20 + environment: + TZ: Europe/Paris + USE_FDD_MONO: 'yes' + RFSIMULATOR: enb + ENB_NAME: eNB-rf-sim + MCC: '208' + MNC: '96' + MNC_LENGTH: 2 + TAC: 1 + UTRA_BAND_ID: 7 + DL_FREQUENCY_IN_MHZ: 2680 + UL_FREQUENCY_OFFSET_IN_MHZ: 120 + NID_CELL: 10 + NB_PRB: 25 + MME_S1C_IP_ADDRESS: 192.168.61.3 + ENB_S1C_IF_NAME: eth0 + ENB_S1C_IP_ADDRESS: 192.168.61.20 + ENB_S1U_IF_NAME: eth0 + ENB_S1U_IP_ADDRESS: 192.168.61.20 + ENB_X2_IP_ADDRESS: 192.168.61.20 + FLEXRAN_ENABLED: 'no' + FLEXRAN_INTERFACE_NAME: eth0 + FLEXRAN_IPV4_ADDRESS: 192.168.61.10 + USE_ADDITIONAL_OPTIONS: --rfsim + healthcheck: + test: /bin/bash -c "pgrep lte-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai_ue0: + image: oai-lte-ue:develop + privileged: true + container_name: rfsim4g-oai-lte-ue0 + networks: + public_net: + ipv4_address: 192.168.61.30 + expose: + - "10000" + environment: + TZ: Europe/Paris + HOSTNAME: oai_ue0 + RFSIMULATOR: 192.168.61.20 + MCC: '208' + MNC: '96' + SHORT_IMSI: '0100000001' + LTE_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'c42449363bbad02b66d16bc975d77cc1' + MSISDN: '001011234561010' + HPLMN: 20896 + USE_ADDITIONAL_OPTIONS: --rfsim -C 2680000000 -r 25 --ue-rxgain 140 --ue-txgain 120 --nokrnmod 1 + healthcheck: + test: /bin/bash -c "pgrep lte-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + private_net: + name: rfsim4g-oai-private-net + ipam: + config: + - subnet: 192.168.68.0/26 + driver_opts: + com.docker.network.bridge.name: "rfsim4g-private" + public_net: + name: rfsim4g-oai-public-net + ipam: + config: + - subnet: 192.168.61.0/26 + driver_opts: + com.docker.network.bridge.name: "rfsim4g-public" diff --git a/ci-scripts/yaml_files/4g_rfsimulator/oai_db.cql b/ci-scripts/yaml_files/4g_rfsimulator/oai_db.cql new file mode 100644 index 0000000000..2be0a8e2e9 --- /dev/null +++ b/ci-scripts/yaml_files/4g_rfsimulator/oai_db.cql @@ -0,0 +1,93 @@ +CREATE KEYSPACE IF NOT EXISTS vhss WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1': '1'}; + +CREATE TABLE IF NOT EXISTS vhss.users_imsi ( + imsi text PRIMARY KEY, + access_restriction int, + idmmeidentity int, + imei text, + imei_sv text, + key text, + lipa_permissions text, + mme_cap int, + mmehost text, + mmeidentity_idmmeidentity int, + mmerealm text, + ms_ps_status text, + msisdn bigint, + niddvalidity text, + nir_dest_host text, + nir_dest_realm text, + opc text, + pgw_id int, + rand text, + rfsp_index varint, + sqn bigint, + subscription_data text, + ue_reachability varint, + urrp_mme varint, + user_identifier text, + visited_plmnid text); + +CREATE TABLE IF NOT EXISTS vhss.msisdn_imsi ( + msisdn bigint PRIMARY KEY, + imsi text +); + +CREATE TABLE IF NOT EXISTS vhss.global_ids ( + table_name text PRIMARY KEY, + id counter); + +CREATE TABLE IF NOT EXISTS vhss.mmeidentity_host ( + mmehost text PRIMARY KEY, + idmmeidentity int, + mmerealm text, + ue_reachability varint, + mmeisdn text); + +CREATE TABLE IF NOT EXISTS vhss.mmeidentity ( + idmmeidentity int PRIMARY KEY, + mmehost text, + mmerealm text, + ue_reachability varint, + mmeisdn text); + +CREATE TABLE IF NOT EXISTS vhss.events ( + scef_id text, + scef_ref_id bigint, + extid text, + monitoring_event_configuration text, + monitoring_type int, + msisdn bigint, + user_identifier text, + primary key (scef_id, scef_ref_id) +); + +CREATE TABLE IF NOT EXISTS vhss.events_msisdn ( + msisdn bigint, + scef_id text, + scef_ref_id bigint, + primary key (msisdn, scef_id, scef_ref_id) +); + +CREATE TABLE IF NOT EXISTS vhss.events_extid ( + extid text, + scef_id text, + scef_ref_id bigint, + primary key (extid, scef_id, scef_ref_id) +); + +CREATE TABLE IF NOT EXISTS vhss.extid ( + extid text primary key +); + +CREATE TABLE IF NOT EXISTS vhss.extid_imsi ( + extid text, + imsi text, + primary key (extid, imsi) +); + +CREATE TABLE IF NOT EXISTS vhss.extid_imsi_xref ( + imsi text, + extid text, + primary key (imsi, extid) +); diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md new file mode 100644 index 0000000000..915b71296f --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -0,0 +1,435 @@ + + + + + +
+ + + + + + OAI Full Stack 5G-NR RF simulation with containers +
+ +This page is only valid for an `Ubuntu18` host. + +**NOTE: this version (2021-10-05) is valid for the `v1.1.0` and `v1.2.0` versions of the `OAI 5G CN`.** + +**TABLE OF CONTENTS** + +1. [Retrieving the images on Docker-Hub](#1-retrieving-the-images-on-docker-hub) +2. [Deploy containers](#2-deploy-containers) + 1. [Deploy OAI 5G Core Network](#21-deploy-oai-5g-core-network) + 2. [Deploy OAI gNB in RF simulator mode and in Standalone Mode](#22-deploy-oai-gnb-in-rf-simulator-mode-and-in-standalone-mode) + 3. [Deploy OAI NR-UE in RF simulator mode and in Standalone Mode](#23-deploy-oai-nr-ue-in-rf-simulator-mode-and-in-standalone-mode) +3. [Check traffic](#3-check-traffic) + 1. [Check your Internet connectivity](#31-check-your-internet-connectivity) + 2. [Start the iperf server inside the NR-UE container](#32-start-the-iperf-server-inside-the-nr-ue-container) + 3. [Start the iperf client inside the ext-dn container](#33-start-the-iperf-client-inside-the-ext-dn-container) +4. [Un-deployment](#4-un-deployment) +5. [Explanations on the configuration in the docker-compose.yaml](##5-explanations-on-the-configuration-in-the-docker-composeyaml) + 1. [Making the NR-UE connect to the core network](#51-making-the-nr-ue-connect-to-the-core-network) + 2. [Making the gNB connect to the core network](#52-making-the-gnb-connect-to-the-core-network) + +# 1. Retrieving the images on Docker-Hub # + +Currently the images are hosted under the user account `rdefosseoai`. + +This may change in the future. + +Once again you may need to log on [docker-hub](https://hub.docker.com/) if your organization has reached pulling limit as `anonymous`. + +```bash +$ docker login +Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. +Username: +Password: +``` + +Now pull images. + +```bash +$ docker pull mysql:5.7 +$ docker pull rdefosseoai/oai-amf:latest +$ docker pull rdefosseoai/oai-nrf:latest +$ docker pull rdefosseoai/oai-smf:latest +$ docker pull rdefosseoai/oai-spgwu-tiny:latest + +$ docker pull rdefosseoai/oai-gnb:develop +$ docker pull rdefosseoai/oai-nr-ue:develop +``` + +And **re-tag** them for tutorials' docker-compose file to work. + +```bash +$ docker image tag rdefosseoai/oai-amf:latest oai-amf:latest +$ docker image tag rdefosseoai/oai-nrf:latest oai-nrf:latest +$ docker image tag rdefosseoai/oai-smf:latest oai-smf:latest +$ docker image tag rdefosseoai/oai-spgwu-tiny:latest oai-spgwu-tiny:latest + +$ docker image tag rdefosseoai/oai-gnb:develop oai-gnb:develop +$ docker image tag rdefosseoai/oai-nr-ue:develop oai-nr-ue:develop +``` + +```bash +$ docker logout +``` + +**CAUTION: 2021/10/05 with the release `v1.2.0` of the `CN5G`, the previous version was not compatible any-more.** + +**This new version is working for both the `v1.1.0` and `v1.2.0` of the `CN5G`.** + +# 2. Deploy containers # + +![Deployment](./oai-end-to-end.jpg) + +**CAUTION: this SHALL be done in multiple steps.** + +**Just `docker-compose up -d` WILL NOT WORK!** + +All the following commands **SHALL** be run from the `ci-scripts/yaml_files/5g_rfsimulator` folder. + +## 2.1. Deploy OAI 5G Core Network ## + +```bash +$ cd ci-scripts/yaml_files/5g_rfsimulator +$ docker-compose up -d mysql oai-nrf oai-amf oai-smf oai-spgwu oai-ext-dn +Creating network "rfsim5g-oai-public-net" with driver "bridge" +Creating network "rfsim5g-oai-traffic_net-net" with driver "bridge" +Creating rfsim5g-oai-nrf ... done +Creating rfsim5g-mysql ... done +Creating rfsim5g-oai-spgwu ... done +Creating rfsim5g-oai-amf ... done +Creating rfsim5g-oai-smf ... done +Creating rfsim5g-oai-ext-dn ... done +``` + +Wait for a bit. + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------- +rfsim5g-mysql docker-entrypoint.sh mysqld Up (healthy) 3306/tcp, 33060/tcp +rfsim5g-oai-amf /bin/bash /openair-amf/bin ... Up (healthy) 38412/sctp, 80/tcp, 9090/tcp +rfsim5g-oai-ext-dn /bin/bash -c apt update; ... Up (healthy) +rfsim5g-oai-nrf /bin/bash /openair-nrf/bin ... Up (healthy) 80/tcp, 9090/tcp +rfsim5g-oai-smf /bin/bash -c /openair-smf/ ... Up (healthy) 80/tcp, 8805/udp, 9090/tcp +rfsim5g-oai-spgwu /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +``` + +At this point, you can prepare a capture on the newly-created public docker bridges: + +```bash +$ ifconfig +... +rfsim5g-public: flags=4163 mtu 1500 + inet 192.168.71.129 netmask 255.255.255.192 broadcast 192.168.71.191 + inet6 fe80::42:c4ff:fe2b:3d38 prefixlen 64 scopeid 0x20 + ether 02:42:c4:2b:3d:38 txqueuelen 0 (Ethernet) + RX packets 4 bytes 112 (112.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 7 bytes 626 (626.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +rfsim5g-traffic: flags=4163 mtu 1500 + inet 192.168.72.129 netmask 255.255.255.192 broadcast 192.168.72.191 + inet6 fe80::42:b5ff:fed3:e732 prefixlen 64 scopeid 0x20 + ether 02:42:b5:d3:e7:32 txqueuelen 0 (Ethernet) + RX packets 2652 bytes 142335 (142.3 KB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 3999 bytes 23367972 (23.3 MB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +... +``` + +## 2.2. Deploy OAI gNB in RF simulator mode and in Standalone Mode ## + +**CAUTION: To execute this 2nd step, the whole `CN5G` SHALL be in `healthy` state (especially the `mysql` container).** + +```bash +$ docker-compose up -d oai-gnb +rfsim5g-oai-nrf is up-to-date +rfsim5g-oai-spgwu is up-to-date +rfsim5g-oai-ext-dn is up-to-date +Creating rfsim5g-oai-gnb ... done +``` + +Wait for a bit. + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------- +rfsim5g-mysql docker-entrypoint.sh mysqld Up (healthy) 3306/tcp, 33060/tcp +rfsim5g-oai-amf /bin/bash /openair-amf/bin ... Up (healthy) 38412/sctp, 80/tcp, 9090/tcp +rfsim5g-oai-ext-dn /bin/bash -c apt update; ... Up (healthy) +rfsim5g-oai-gnb /opt/oai-gnb/bin/entrypoin ... Up (healthy) +rfsim5g-oai-nrf /bin/bash /openair-nrf/bin ... Up (healthy) 80/tcp, 9090/tcp +rfsim5g-oai-smf /bin/bash -c /openair-smf/ ... Up (healthy) 80/tcp, 8805/udp, 9090/tcp +rfsim5g-oai-spgwu /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +``` + +You can verify that the `gNB` is connected with the `AMF`: + +```bagh +$ docker logs rfsim5g-oai-amf +... +[AMF] [amf_app] [info ] |----------------------------------------------------gNBs' information-------------------------------------------| +[AMF] [amf_app] [info ] | Index | Status | Global ID | gNB Name | PLMN | +[AMF] [amf_app] [info ] | 1 | Connected | 0x0 | gnb-rfsim | 208, 99 | +[AMF] [amf_app] [info ] |----------------------------------------------------------------------------------------------------------------| +... +``` + +## 2.3. Deploy OAI NR-UE in RF simulator mode and in Standalone Mode ## + +```bash +$ docker-compose up -d oai-nr-ue +rfsim5g-mysql is up-to-date +rfsim5g-oai-nrf is up-to-date +rfsim5g-oai-spgwu is up-to-date +rfsim5g-oai-ext-dn is up-to-date +rfsim5g-oai-gnb is up-to-date +Creating rfsim5g-oai-nr-ue ... done +``` + +Wait for a bit. + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------- +rfsim5g-mysql docker-entrypoint.sh mysqld Up (healthy) 3306/tcp, 33060/tcp +rfsim5g-oai-amf /bin/bash /openair-amf/bin ... Up (healthy) 38412/sctp, 80/tcp, 9090/tcp +rfsim5g-oai-ext-dn /bin/bash -c apt update; ... Up (healthy) +rfsim5g-oai-gnb /opt/oai-gnb/bin/entrypoin ... Up (healthy) +rfsim5g-oai-nr-ue /opt/oai-nr-ue/bin/entrypo ... Up (healthy) +rfsim5g-oai-nrf /bin/bash /openair-nrf/bin ... Up (healthy) 80/tcp, 9090/tcp +rfsim5g-oai-smf /bin/bash -c /openair-smf/ ... Up (healthy) 80/tcp, 8805/udp, 9090/tcp +rfsim5g-oai-spgwu /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +``` + +Making sure the OAI UE is connected: + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash +root@bb4d400a832d:/opt/oai-nr-ue# ifconfig +eth0: flags=4163 mtu 1500 + inet 192.168.71.137 netmask 255.255.255.192 broadcast 192.168.71.191 + ether 02:42:c0:a8:47:89 txqueuelen 0 (Ethernet) + RX packets 224259 bytes 5821372018 (5.8 GB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 235916 bytes 7848786376 (7.8 GB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +lo: flags=73 mtu 65536 + inet 127.0.0.1 netmask 255.0.0.0 + loop txqueuelen 1000 (Local Loopback) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +oaitun_ue1: flags=4305 mtu 1500 + inet 12.1.1.2 netmask 255.255.255.0 destination 12.1.1.2 + unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +``` + +# 3. Check traffic # + +## 3.1. Check your Internet connectivity ## + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash +root@bb4d400a832d:/opt/oai-nr-ue# ping -I oaitun_ue1 -c 10 www.lemonde.fr +PING s2.shared.global.fastly.net (151.101.122.217) from 12.1.1.2 oaitun_ue1: 56(84) bytes of data. +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=1 ttl=53 time=64.5 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=2 ttl=53 time=37.0 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=3 ttl=53 time=43.2 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=4 ttl=53 time=43.2 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=5 ttl=53 time=54.3 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=6 ttl=53 time=24.0 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=7 ttl=53 time=32.5 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=8 ttl=53 time=37.0 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=9 ttl=53 time=41.2 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=10 ttl=53 time=50.3 ms + +--- s2.shared.global.fastly.net ping statistics --- +10 packets transmitted, 10 received, 0% packet loss, time 9011ms +rtt min/avg/max/mdev = 24.035/42.765/64.557/10.904 ms +``` + +If it does not work, certainly you need to modify the DNS values in the docker-compose. + +But you can also check with the `ext-dn` container (IP address is `192.168.72.135` in docker-compose) + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash +root@bb4d400a832d# ping -I oaitun_ue1 -c 2 192.168.72.135 +PING 192.168.72.135 (192.168.72.135) from 12.1.1.2 oaitun_ue1: 56(84) bytes of data. +64 bytes from 192.168.72.135: icmp_seq=1 ttl=63 time=10.9 ms +64 bytes from 192.168.72.135: icmp_seq=2 ttl=63 time=16.5 ms + +--- 192.168.72.135 ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 10.939/13.747/16.556/2.810 ms +``` + +Let now try to check UDP traffic in Downlink. + +You will need 2 terminals: one in the NR-UE container, one in the ext-dn container. + +## 3.2. Start the `iperf` server inside the NR-UE container ## + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash +root@bb4d400a832d:/opt/oai-nr-ue# iperf -B 12.1.1.2 -u -i 1 -s +------------------------------------------------------------ +Server listening on UDP port 5001 +Binding to local address 12.1.1.2 +Receiving 1470 byte datagrams +UDP buffer size: 208 KByte (default) +------------------------------------------------------------ +``` + +## 3.3. Start the `iperf` client inside the ext-dn container ## + +```bash +$ docker exec -it rfsim5g-oai-ext-dn /bin/bash +root@f239e31a0bd0:/# iperf -c 12.1.1.2 -u -i 1 -t 20 -b 500K +------------------------------------------------------------ +Client connecting to 12.1.1.2, UDP port 5001 +Sending 1470 byte datagrams, IPG target: 22968.75 us (kalman adjust) +UDP buffer size: 208 KByte (default) +------------------------------------------------------------ +[ 3] local 192.168.72.135 port 58800 connected with 12.1.1.2 port 5001 +[ ID] Interval Transfer Bandwidth +[ 3] 0.0- 1.0 sec 64.6 KBytes 529 Kbits/sec +[ 3] 1.0- 2.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 2.0- 3.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 3.0- 4.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 4.0- 5.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 5.0- 6.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 6.0- 7.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 7.0- 8.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 8.0- 9.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 9.0-10.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 10.0-11.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 11.0-12.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 12.0-13.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 13.0-14.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 14.0-15.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 15.0-16.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 16.0-17.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 17.0-18.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 18.0-19.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 19.0-20.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 0.0-20.0 sec 1.22 MBytes 512 Kbits/sec +[ 3] Sent 872 datagrams +[ 3] Server Report: +[ 3] 0.0-20.0 sec 1.22 MBytes 510 Kbits/sec 0.000 ms 3/ 872 (0%) +``` + +Back on your NR-UE terminal you shall see: + +```bash +[ 3] local 12.1.1.2 port 5001 connected with 192.168.72.135 port 58800 +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams +[ 3] 0.0- 1.0 sec 63.2 KBytes 517 Kbits/sec 1.113 ms 0/ 44 (0%) +[ 3] 1.0- 2.0 sec 61.7 KBytes 506 Kbits/sec 1.466 ms 0/ 43 (0%) +[ 3] 2.0- 3.0 sec 63.2 KBytes 517 Kbits/sec 1.770 ms 0/ 44 (0%) +[ 3] 3.0- 4.0 sec 61.7 KBytes 506 Kbits/sec 1.378 ms 0/ 43 (0%) +[ 3] 4.0- 5.0 sec 63.2 KBytes 517 Kbits/sec 1.614 ms 0/ 44 (0%) +[ 3] 5.0- 6.0 sec 63.2 KBytes 517 Kbits/sec 1.427 ms 0/ 44 (0%) +[ 3] 6.0- 7.0 sec 60.3 KBytes 494 Kbits/sec 1.507 ms 1/ 43 (2.3%) +[ 3] 7.0- 8.0 sec 63.2 KBytes 517 Kbits/sec 1.409 ms 0/ 44 (0%) +[ 3] 8.0- 9.0 sec 61.7 KBytes 506 Kbits/sec 1.525 ms 0/ 43 (0%) +[ 3] 9.0-10.0 sec 63.2 KBytes 517 Kbits/sec 1.393 ms 0/ 44 (0%) +[ 3] 10.0-11.0 sec 61.7 KBytes 506 Kbits/sec 1.377 ms 0/ 43 (0%) +[ 3] 11.0-12.0 sec 63.2 KBytes 517 Kbits/sec 1.501 ms 0/ 44 (0%) +[ 3] 12.0-13.0 sec 61.7 KBytes 506 Kbits/sec 1.788 ms 0/ 43 (0%) +[ 3] 13.0-14.0 sec 63.2 KBytes 517 Kbits/sec 1.466 ms 0/ 44 (0%) +[ 3] 14.0-15.0 sec 61.7 KBytes 506 Kbits/sec 1.381 ms 0/ 43 (0%) +[ 3] 15.0-16.0 sec 61.7 KBytes 506 Kbits/sec 1.417 ms 1/ 44 (2.3%) +[ 3] 16.0-17.0 sec 61.7 KBytes 506 Kbits/sec 1.569 ms 0/ 43 (0%) +[ 3] 17.0-18.0 sec 63.2 KBytes 517 Kbits/sec 1.492 ms 1/ 45 (2.2%) +[ 3] 18.0-19.0 sec 61.7 KBytes 506 Kbits/sec 1.376 ms 0/ 43 (0%) +[ 3] 19.0-20.0 sec 61.7 KBytes 506 Kbits/sec 1.589 ms 0/ 43 (0%) +[ 3] 0.0-20.0 sec 1.22 MBytes 510 Kbits/sec 1.551 ms 3/ 872 (0.34%) +``` + +The `500 Kbits/sec` value may change depending on your CPU power! + +# 4. Un-deployment # + +```bash +$ docker-compose down +Stopping rfsim5g-oai-nr-ue ... done +Stopping rfsim5g-oai-gnb ... done +Stopping rfsim5g-oai-ext-dn ... done +Stopping rfsim5g-oai-smf ... done +Stopping rfsim5g-oai-amf ... done +Stopping rfsim5g-oai-spgwu ... done +Stopping rfsim5g-oai-nrf ... done +Stopping rfsim5g-mysql ... done +Removing rfsim5g-oai-nr-ue ... done +Removing rfsim5g-oai-gnb ... done +Removing rfsim5g-oai-ext-dn ... done +Removing rfsim5g-oai-smf ... done +Removing rfsim5g-oai-amf ... done +Removing rfsim5g-oai-spgwu ... done +Removing rfsim5g-oai-nrf ... done +Removing rfsim5g-mysql ... done +Removing network rfsim5g-oai-public-net +Removing network rfsim5g-oai-traffic_net-net +``` + +# 5. Explanations on the configuration in the `docker-compose.yaml` # + +## 5.1. Making the NR-UE connect to the core network ## + +The NR-UE **SHALL** be provisioned in the core network, especially in the `SQL` database and in the `AMF`. + +* in AMF section of `docker-compose.yaml` --> `OPERATOR_KEY=c42449363bbad02b66d16bc975d77cc1` +* in NR-UE section --> `OPC: 'C42449363BBAD02B66D16BC975D77CC1' + +Both values shall match! + +This value is also present in the `oai_db.sql` file: + +```bash +INSERT INTO `users` VALUES ('208990100001100','1','55000000000000',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0xfec86ba6eb707ed08905757b1bb44b8f,0,0,0x40,'ebd07771ace8677a',0xc42449363bbad02b66d16bc975d77cc1); +``` + +As you can see, 2 other values shall match in the NR-UE section of `docker-compose.yaml`: + +* `FULL_IMSI: '208990100001100'` +* `FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f'` + +We are also using a dedicated `oai-smf.conf` for the `SMF` container: the `oai` DNN shall match the one in the NR-UE section of `docker-compose.yaml` (`DNN: oai`). + +## 5.2. Making the gNB connect to the core network ## + +Mainly you need to match the PLMN in `gNB`, `AMF` and `SPGWU` parameters: + +* `AMF` + - `MCC=208` + - `MNC=99` + - `PLMN_SUPPORT_TAC=0x0001` + - ... +* `SPGWU` + - `MCC=208` + - `MNC=99` + - `TAC=1` +* `gNB` + - `MCC: '208'` + - `MNC: '99'` + - `TAC: 1` + +The `ST` and `SD` values shall also match. diff --git a/ci-scripts/yaml_files/5g_rfsimulator/amf-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/amf-healthcheck.sh new file mode 100755 index 0000000000..8bfdee2aac --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/amf-healthcheck.sh @@ -0,0 +1,57 @@ +#!/bin/bash +set -eo pipefail + +STATUS=0 +AMF_PORT_FOR_NGAP=38412 +AMF_PORT_FOR_N11_HTTP=80 +AMF_IP_NGAP_INTERFACE=$(ifconfig $AMF_INTERFACE_NAME_FOR_NGAP | grep inet | awk {'print $2'}) +AMF_IP_N11_INTERFACE=$(ifconfig $AMF_INTERFACE_NAME_FOR_N11 | grep inet | awk {'print $2'}) +N2_PORT_STATUS=$(netstat -Snpl | grep -o "$AMF_IP_NGAP_INTERFACE:$AMF_PORT_FOR_NGAP") +N11_PORT_STATUS=$(netstat -tnpl | grep -o "$AMF_IP_N11_INTERFACE:$AMF_PORT_FOR_N11_HTTP") +#Check if entrypoint properly configured the conf file and no parameter is unset (optional) +NB_UNREPLACED_AT=`cat /openair-amf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` + +if [ $NB_UNREPLACED_AT -ne 0 ]; then + STATUS=1 + echo "Healthcheck error: configuration file is not configured properly" +fi + +if [[ -z $N2_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: N2 SCTP port $AMF_PORT_FOR_NGAP is not listening" +fi + +if [[ -z $N11_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: N11/SBI TCP/HTTP port $AMF_PORT_FOR_N11_HTTP is not listening" +fi + +#host="${MYSQL_SERVER}" +#user="${MYSQL_USER:-root}" +#export MYSQL_PWD="${MYSQL_PASS}" + +#args=( +# -h"$host" +# -u"$user" +# --silent +#) + +#if ! command -v mysql &> /dev/null; then +# echo "Installing mysql command" +# apt update +# apt-get -y install mysql-client +#else +# if select="$(echo 'SELECT 1' | mysql "${args[@]}")" && [ "$select" = '1' ]; then +# database_check=$(mysql -h$host -u$user -D oai_db --silent -e "SELECT * FROM users;") +# if [[ -z $database_check ]]; then +# echo "Healthcheck error: oai_db not populated" +# STATUS=1 +# fi +# STATUS=0 +# else +# echo "Healthcheck error: Mysql port inactive" +# STATUS=1 +# fi +#fi + +exit $STATUS diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml new file mode 100644 index 0000000000..31d64f35dc --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -0,0 +1,298 @@ +version: '3.8' +services: + oai-nrf: + container_name: "rfsim5g-oai-nrf" + image: oai-nrf:latest + environment: + - NRF_INTERFACE_NAME_FOR_SBI=eth0 + - NRF_INTERFACE_PORT_FOR_SBI=80 + - NRF_INTERFACE_HTTP2_PORT_FOR_SBI=9090 + - NRF_API_VERSION=v1 + - INSTANCE=0 + - PID_DIRECTORY=/var/run + networks: + public_net: + ipv4_address: 192.168.71.130 + volumes: + - ./nrf-healthcheck.sh:/openair-nrf/bin/nrf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-nrf/bin/nrf-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + mysql: + container_name: "rfsim5g-mysql" + image: mysql:5.7 + volumes: + - ./oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ./mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + public_net: + ipv4_address: 192.168.71.131 + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oai-amf:latest + environment: + - TZ=Europe/paris + - INSTANCE=0 + - PID_DIRECTORY=/var/run + - MCC=208 + - MNC=99 + - REGION_ID=128 + - AMF_SET_ID=1 + - SERVED_GUAMI_MCC_0=208 + - SERVED_GUAMI_MNC_0=99 + - SERVED_GUAMI_REGION_ID_0=128 + - SERVED_GUAMI_AMF_SET_ID_0=1 + - SERVED_GUAMI_MCC_1=460 + - SERVED_GUAMI_MNC_1=11 + - SERVED_GUAMI_REGION_ID_1=10 + - SERVED_GUAMI_AMF_SET_ID_1=1 + - PLMN_SUPPORT_MCC=208 + - PLMN_SUPPORT_MNC=99 + - PLMN_SUPPORT_TAC=0x0001 + - SST_0=1 + - SD_0=1 + - SST_1=1 + - SD_1=12 + - AMF_INTERFACE_NAME_FOR_NGAP=eth0 + - AMF_INTERFACE_NAME_FOR_N11=eth0 + - SMF_INSTANCE_ID_0=1 + - SMF_FQDN_0=oai-smf + - SMF_IPV4_ADDR_0=0.0.0.0 + - SMF_HTTP_VERSION_0=v1 + - SELECTED_0=true + - SMF_INSTANCE_ID_1=2 + - SMF_FQDN_1=oai-smf + - SMF_IPV4_ADDR_1=0.0.0.0 + - SMF_HTTP_VERSION_1=v1 + - SELECTED_1=false + - MYSQL_SERVER=192.168.71.131 + - MYSQL_USER=root + - MYSQL_PASS=linux + - MYSQL_DB=oai_db + - OPERATOR_KEY=c42449363bbad02b66d16bc975d77cc1 + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NF_REGISTRATION=yes + - SMF_SELECTION=yes + - USE_FQDN_DNS=yes + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - EXTERNAL_AUSF=no + - AUSF_IPV4_ADDRESS=0.0.0.0 + - AUSF_PORT=80 + - AUSF_API_VERSION=v1 + - AUSF_FQDN=localhost + depends_on: + - oai-nrf + - mysql + volumes: + - ./amf-healthcheck.sh:/openair-amf/bin/amf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-amf/bin/amf-healthcheck.sh" + interval: 10s + timeout: 15s + retries: 5 + networks: + public_net: + ipv4_address: 192.168.71.132 + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oai-smf:latest + entrypoint: /bin/bash -c "/openair-smf/bin/oai_smf -c /openair-smf/bin/oai-smf.conf -o" + environment: + - TZ=Europe/Paris + - INSTANCE=0 + - PID_DIRECTORY=/var/run + - SMF_INTERFACE_NAME_FOR_N4=eth0 + - SMF_INTERFACE_NAME_FOR_SBI=eth0 + - SMF_INTERFACE_PORT_FOR_SBI=80 + - SMF_INTERFACE_HTTP2_PORT_FOR_SBI=9090 + - SMF_API_VERSION=v1 + - DEFAULT_DNS_IPV4_ADDRESS=192.168.18.129 + - DEFAULT_DNS_SEC_IPV4_ADDRESS=4.4.4.4 + - AMF_IPV4_ADDRESS=0.0.0.0 + - AMF_PORT=80 + - AMF_API_VERSION=v1 + - AMF_FQDN=oai-amf + - UDM_IPV4_ADDRESS=127.0.0.1 + - UDM_PORT=80 + - UDM_API_VERSION=v1 + - UDM_FQDN=localhost + - UPF_IPV4_ADDRESS=192.168.71.134 + - UPF_FQDN_0=oai-spgwu + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - REGISTER_NRF=yes + - DISCOVER_UPF=yes + - USE_FQDN_DNS=yes + depends_on: + - oai-nrf + - oai-amf + volumes: + - ./smf-healthcheck.sh:/openair-smf/bin/smf-healthcheck.sh + - ./oai-smf.conf:/openair-smf/bin/oai-smf.conf + healthcheck: + test: /bin/bash -c "/openair-smf/bin/smf-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + public_net: + ipv4_address: 192.168.71.133 + oai-spgwu: + container_name: "rfsim5g-oai-spgwu" + image: oai-spgwu-tiny:latest + environment: + - TZ=Europe/Paris + - PID_DIRECTORY=/var/run + - SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0 + - SGW_INTERFACE_NAME_FOR_SX=eth0 + - PGW_INTERFACE_NAME_FOR_SGI=eth0 + - NETWORK_UE_NAT_OPTION=yes + - NETWORK_UE_IP=12.1.1.0/24 + - SPGWC0_IP_ADDRESS=192.168.71.133 + - BYPASS_UL_PFCP_RULES=no + - MCC=208 + - MNC=99 + - MNC03=099 + - TAC=1 + - GTP_EXTENSION_HEADER_PRESENT=yes + - GW_ID=1 + - REALM=openairinterface.org + - ENABLE_5G_FEATURES=yes + - REGISTER_NRF=yes + - USE_FQDN_NRF=yes + - UPF_FQDN_5G=oai-spgwu + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - NSSAI_SST_0=1 + - NSSAI_SD_0=1 + - DNN_0=oai + depends_on: + - oai-nrf + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + volumes: + - ./spgwu-healthcheck.sh:/openair-spgwu-tiny/bin/spgwu-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-spgwu-tiny/bin/spgwu-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + public_net: + ipv4_address: 192.168.71.134 + traffic_net: + ipv4_address: 192.168.72.134 + oai-ext-dn: + image: ubuntu:bionic + privileged: true + container_name: rfsim5g-oai-ext-dn + entrypoint: /bin/bash -c \ + "apt update; apt install -y procps iptables iproute2 iperf iputils-ping;"\ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" + depends_on: + - oai-spgwu + networks: + traffic_net: + ipv4_address: 192.168.72.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.72.134" + interval: 10s + timeout: 5s + retries: 5 + oai-gnb: + image: oai-gnb:develop + privileged: true + container_name: rfsim5g-oai-gnb + environment: + RFSIMULATOR: server + USE_SA_TDD_MONO: 'yes' + GNB_NAME: gnb-rfsim + TAC: 1 + MCC: '208' + MNC: '99' + MNC_LENGTH: 2 + NSSAI_SST: 1 + NSSAI_SD0: 1 + NSSAI_SD1: 112233 + AMF_IP_ADDRESS: 192.168.71.132 + GNB_NGA_IF_NAME: eth0 + GNB_NGA_IP_ADDRESS: 192.168.71.136 + GNB_NGU_IF_NAME: eth0 + GNB_NGU_IP_ADDRESS: 192.168.71.136 + USE_ADDITIONAL_OPTIONS: --sa -E --rfsim + depends_on: + - oai-ext-dn + networks: + public_net: + ipv4_address: 192.168.71.136 + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + oai-nr-ue: + image: oai-nr-ue:develop + privileged: true + container_name: rfsim5g-oai-nr-ue + environment: + RFSIMULATOR: 192.168.71.136 + FULL_IMSI: '208990100001100' + FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'C42449363BBAD02B66D16BC975D77CC1' + DNN: oai + NSSAI_SST: 1 + NSSAI_SD: 1 + USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 -C 3619200000 --nokrnmod + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.137 + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" diff --git a/ci-scripts/yaml_files/5g_rfsimulator/mysql-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/mysql-healthcheck.sh new file mode 100755 index 0000000000..c92efb9f00 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/mysql-healthcheck.sh @@ -0,0 +1,46 @@ +#!/bin/bash +set -eo pipefail + +if [ "$MYSQL_ROOT_PASSWORD" ] && [ -z "$MYSQL_USER" ] && [ -z "$MYSQL_PASSWORD" ]; then + echo >&2 'Healthcheck error: cannot determine root password (and MYSQL_USER and MYSQL_PASSWORD were not set)' + exit 0 +fi + +host="$(hostname --ip-address || echo '127.0.0.1')" +user="${MYSQL_USER:-root}" +export MYSQL_PWD="${MYSQL_PASSWORD:-$MYSQL_ROOT_PASSWORD}" + +args=( + # force mysql to not use the local "mysqld.sock" (test "external" connectivity) + -h"$host" + -u"$user" + --silent +) + +STATUS=0 +if command -v mysqladmin &> /dev/null; then + if mysqladmin "${args[@]}" ping > /dev/null; then + database_check=$(mysql -u$user -D oai_db --silent -e "SELECT * FROM users;") + if [[ -z $database_check ]]; then + echo "Healthcheck error: oai_db not populated" + STATUS=1 + fi + STATUS=0 + else + echo "Healthcheck error: Mysql port inactive" + STATUS=1 + fi +else + if select="$(echo 'SELECT 1' | mysql "${args[@]}")" && [ "$select" = '1' ]; then + database_check=$(mysql -u$user -D oai_db --silent -e "SELECT * FROM users;") + if [[ -z $database_check ]]; then + echo "Healthcheck error: oai_db not populated" + STATUS=1 + fi + STATUS=0 + else + echo "Healthcheck error: Mysql port inactive" + STATUS=1 + fi +fi +exit $STATUS diff --git a/ci-scripts/yaml_files/5g_rfsimulator/nrf-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/nrf-healthcheck.sh new file mode 100755 index 0000000000..3479c092e8 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/nrf-healthcheck.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -eo pipefail + +STATUS=0 +NRF_IP_SBI_INTERFACE=$(ifconfig $NRF_INTERFACE_NAME_FOR_SBI | grep inet | awk {'print $2'}) +NRF_SBI_PORT_STATUS=$(netstat -tnpl | grep -o "$NRF_IP_SBI_INTERFACE:$NRF_INTERFACE_PORT_FOR_SBI") +#Check if entrypoint properly configured the conf file and no parameter is unset(optional) +NB_UNREPLACED_AT=`cat /openair-nrf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` + +if [ $NB_UNREPLACED_AT -ne 0 ]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY configuration file is not configured properly" +fi + +if [[ -z $NRF_SBI_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY SBI TCP/HTTP port $NRF_INTERFACE_PORT_FOR_SBI is not listening." +fi + +exit $STATUS \ No newline at end of file diff --git a/ci-scripts/yaml_files/5g_rfsimulator/oai-end-to-end.jpg b/ci-scripts/yaml_files/5g_rfsimulator/oai-end-to-end.jpg new file mode 100644 index 0000000000..f454a016f6 Binary files /dev/null and b/ci-scripts/yaml_files/5g_rfsimulator/oai-end-to-end.jpg differ diff --git a/ci-scripts/yaml_files/5g_rfsimulator/oai-smf.conf b/ci-scripts/yaml_files/5g_rfsimulator/oai-smf.conf new file mode 100644 index 0000000000..0c83ab8be9 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/oai-smf.conf @@ -0,0 +1,133 @@ +################################################################################ +# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The OpenAirInterface Software Alliance licenses this file to You under +# the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# +# 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. +#------------------------------------------------------------------------------- +# For more information about the OpenAirInterface (OAI) Software Alliance: +# contact@openairinterface.org +################################################################################ + +SMF = +{ + FQDN = "oai-smf-svc"; + INSTANCE = 0; # 0 is the default + PID_DIRECTORY = "/var/run"; # /var/run is the default + + INTERFACES : + { + N4 : + { + # SMF binded interface for N4 communication (UPF) + INTERFACE_NAME = "eth0"; # YOUR NETWORK CONFIG HERE + IPV4_ADDRESS = "read"; + }; + + SBI : + { + # SMF binded interface for SBI interface (e.g., communication with AMF, UDM) + INTERFACE_NAME = "eth0"; # YOUR NETWORK CONFIG HERE + IPV4_ADDRESS = "read"; + PORT = 80; # YOUR NETWORK CONFIG HERE (default: 80) + HTTP2_PORT = 9090; # YOUR NETWORK CONFIG HERE + API_VERSION = "v1"; # YOUR SMF API VERSION CONFIG HERE + }; + + }; + + + # Pool of UE assigned IP addresses + # Do not make IP pools overlap + # first IPv4 address X.Y.Z.1 is reserved for GTP network device on UPF + IP_ADDRESS_POOL : + { + IPV4_LIST = ( + {RANGE = "12.1.1.2 - 12.1.1.128";}, # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE. + {RANGE = "12.1.1.129 - 12.1.1.224";}, # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE. + {RANGE = "10.10.10.2 - 10.10.10.253";} # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE. + + ); + IPV6_LIST = ( + {PREFIX = "2001:1:2::/64";}, # STRING, IPv6 prefix, YOUR NETWORK CONFIG HERE. + {PREFIX = "3001:1:2::/64";}, # STRING, IPv6 prefix, YOUR NETWORK CONFIG HERE. + {PREFIX = "4001:1:2::/64";} # STRING, IPv6 prefix, YOUR NETWORK CONFIG HERE. + ); + }; + + DNN_LIST = ( + # IPV4_POOL, IPV6_POOL are index in IPV4_LIST, IPV6_LIST, PDU_SESSION_TYPE choice in {IPv4, IPv6, IPv4v6} + {DNN_NI = "default"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1}, + {DNN_NI = "carrier.com"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1}, + {DNN_NI = "oai"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1} + ); + + # DNS address communicated to UEs + DEFAULT_DNS_IPV4_ADDRESS = "192.168.18.129"; # YOUR DNS CONFIG HERE + DEFAULT_DNS_SEC_IPV4_ADDRESS = "192.168.18.129"; # YOUR DNS CONFIG HERE + DEFAULT_DNS_IPV6_ADDRESS = "2001:4860:4860::8888"; # YOUR DNS CONFIG HERE + DEFAULT_DNS_SEC_IPV6_ADDRESS = "2001:4860:4860::8844"; # YOUR DNS CONFIG HERE + + SUPPORT_FEATURES: + { + # STRING, {"yes", "no"}, + REGISTER_NRF = "yes"; # Set to yes if SMF resgisters to an NRF + DISCOVER_UPF = "yes"; # Set to yes to enable UPF discovery and selection + FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS = "no"; # Non standard feature, normally should be set to "no", + # but you may need to set to yes for UE that do not explicitly request a PDN address through NAS signalling + USE_LOCAL_SUBSCRIPTION_INFO = "yes"; # Set to yes if SMF uses local subscription information instead of from an UDM + USE_FQDN_DNS = "yes"; # Set to yes if AMF/UDM/NRF/UPF will relying on a DNS to resolve FQDN + } + + AMF : + { + IPV4_ADDRESS = "0.0.0.0"; # YOUR AMF CONFIG HERE + PORT = 80; # YOUR AMF CONFIG HERE (default: 80) + API_VERSION = "v1"; # YOUR AMF API VERSION FOR SBI CONFIG HERE + FQDN = "oai-amf" # YOUR AMF FQDN CONFIG HERE + }; + + UDM : + { + IPV4_ADDRESS = "127.0.0.1"; # YOUR UDM CONFIG HERE + PORT = 80; # YOUR UDM CONFIG HERE (default: 80) + API_VERSION = "v1"; # YOUR UDM API VERSION FOR SBI CONFIG HERE + FQDN = "localhost" # YOUR UDM FQDN CONFIG HERE + }; + + NRF : + { + IPV4_ADDRESS = "192.168.71.130"; # YOUR NRF CONFIG HERE + PORT = 80; # YOUR NRF CONFIG HERE (default: 80) + API_VERSION = "v1"; # YOUR NRF API VERSION FOR SBI CONFIG HERE + FQDN = "oai-nrf" # YOUR NRF FQDN CONFIG HERE + }; + + UPF_LIST = ( + {IPV4_ADDRESS = "192.168.71.134" ; FQDN = "oai-spgwu"} # YOUR UPF CONFIG HERE + ); + + LOCAL_CONFIGURATION : + { + SESSION_MANAGEMENT_SUBSCRIPTION_LIST = ( + { NSSAI_SST = 222, NSSAI_SD = "123", DNN = "default", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1, + QOS_PROFILE_5QI = 7, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT", + QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"}, + { NSSAI_SST = 1; NSSAI_SD = "1", DNN = "oai", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1, + QOS_PROFILE_5QI = 6, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT", + QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"} + ); + }; + +}; + diff --git a/ci-scripts/yaml_files/5g_rfsimulator/oai_db.sql b/ci-scripts/yaml_files/5g_rfsimulator/oai_db.sql new file mode 100755 index 0000000000..fbd7907a71 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/oai_db.sql @@ -0,0 +1,217 @@ +-- MySQL dump 10.13 Distrib 5.5.46, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: oai_db +-- ------------------------------------------------------ +-- Server version 5.5.46-0ubuntu0.14.04.2 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `apn` +-- + +DROP TABLE IF EXISTS `apn`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `apn` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `apn-name` varchar(60) NOT NULL, + `pdn-type` enum('IPv4','IPv6','IPv4v6','IPv4_or_IPv6') NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `apn-name` (`apn-name`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `apn` +-- + +LOCK TABLES `apn` WRITE; +/*!40000 ALTER TABLE `apn` DISABLE KEYS */; +/*!40000 ALTER TABLE `apn` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `mmeidentity` +-- + +DROP TABLE IF EXISTS `mmeidentity`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `mmeidentity` ( + `idmmeidentity` int(11) NOT NULL AUTO_INCREMENT, + `mmehost` varchar(255) DEFAULT NULL, + `mmerealm` varchar(200) DEFAULT NULL, + `UE-Reachability` tinyint(1) NOT NULL COMMENT 'Indicates whether the MME supports UE Reachability Notifcation', + PRIMARY KEY (`idmmeidentity`) +) ENGINE=MyISAM AUTO_INCREMENT=46 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `mmeidentity` +-- + +LOCK TABLES `mmeidentity` WRITE; +/*!40000 ALTER TABLE `mmeidentity` DISABLE KEYS */; +INSERT INTO `mmeidentity` VALUES (2,'mme2.openair4G.eur','openair4G.eur',0),(1,'nano.openair4G.eur','openair4G.eur',0),(5,'abeille.openair4G.eur','openair4G.eur',0),(4,'yang.openair4G.eur','openair4G.eur',0),(3,'mme3.openair4G.eur','openair4G.eur',0),(6,'calisson.openair4G.eur','openair4G.eur',0); +/*!40000 ALTER TABLE `mmeidentity` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pdn` +-- + +DROP TABLE IF EXISTS `pdn`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pdn` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `apn` varchar(60) NOT NULL, + `pdn_type` enum('IPv4','IPv6','IPv4v6','IPv4_or_IPv6') NOT NULL DEFAULT 'IPv4', + `pdn_ipv4` varchar(15) DEFAULT '0.0.0.0', + `pdn_ipv6` varchar(45) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT '0:0:0:0:0:0:0:0', + `aggregate_ambr_ul` int(10) unsigned DEFAULT '50000000', + `aggregate_ambr_dl` int(10) unsigned DEFAULT '100000000', + `pgw_id` int(11) NOT NULL, + `users_imsi` varchar(15) NOT NULL, + `qci` tinyint(3) unsigned NOT NULL DEFAULT '9', + `priority_level` tinyint(3) unsigned NOT NULL DEFAULT '15', + `pre_emp_cap` enum('ENABLED','DISABLED') DEFAULT 'DISABLED', + `pre_emp_vul` enum('ENABLED','DISABLED') DEFAULT 'DISABLED', + `LIPA-Permissions` enum('LIPA-prohibited','LIPA-only','LIPA-conditional') NOT NULL DEFAULT 'LIPA-only', + PRIMARY KEY (`id`,`pgw_id`,`users_imsi`), + KEY `fk_pdn_pgw1_idx` (`pgw_id`), + KEY `fk_pdn_users1_idx` (`users_imsi`) +) ENGINE=MyISAM AUTO_INCREMENT=60 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `pdn` +-- + +LOCK TABLES `pdn` WRITE; +/*!40000 ALTER TABLE `pdn` DISABLE KEYS */; +INSERT INTO `pdn` VALUES (1,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000001',9,15,'DISABLED','ENABLED','LIPA-only'),(41,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'20834123456789',9,15,'DISABLED','ENABLED','LIPA-only'),(40,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'20810000001234',9,15,'DISABLED','ENABLED','LIPA-only'),(42,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'31002890832150',9,15,'DISABLED','ENABLED','LIPA-only'),(16,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000002',9,15,'DISABLED','ENABLED','LIPA-only'),(43,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'001010123456789',9,15,'DISABLED','ENABLED','LIPA-only'),(2,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000002',9,15,'DISABLED','ENABLED','LIPA-only'),(3,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000003',9,15,'DISABLED','ENABLED','LIPA-only'),(4,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000004',9,15,'DISABLED','ENABLED','LIPA-only'),(5,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000005',9,15,'DISABLED','ENABLED','LIPA-only'),(6,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000006',9,15,'DISABLED','ENABLED','LIPA-only'),(7,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930000000007',9,15,'DISABLED','ENABLED','LIPA-only'),(8,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000001',9,15,'DISABLED','ENABLED','LIPA-only'),(9,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000002',9,15,'DISABLED','ENABLED','LIPA-only'),(10,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000003',9,15,'DISABLED','ENABLED','LIPA-only'),(11,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000004',9,15,'DISABLED','ENABLED','LIPA-only'),(12,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000005',9,15,'DISABLED','ENABLED','LIPA-only'),(13,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000006',9,15,'DISABLED','ENABLED','LIPA-only'),(14,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208940000000007',9,15,'DISABLED','ENABLED','LIPA-only'),(15,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000001',9,15,'DISABLED','ENABLED','LIPA-only'),(17,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000003',9,15,'DISABLED','ENABLED','LIPA-only'),(18,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000004',9,15,'DISABLED','ENABLED','LIPA-only'),(19,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000005',9,15,'DISABLED','ENABLED','LIPA-only'),(20,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000006',9,15,'DISABLED','ENABLED','LIPA-only'),(21,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000007',9,15,'DISABLED','ENABLED','LIPA-only'),(22,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001100',9,15,'DISABLED','ENABLED','LIPA-only'),(23,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001101',9,15,'DISABLED','ENABLED','LIPA-only'),(24,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001102',9,15,'DISABLED','ENABLED','LIPA-only'),(25,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001103',9,15,'DISABLED','ENABLED','LIPA-only'),(26,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001104',9,15,'DISABLED','ENABLED','LIPA-only'),(27,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001105',9,15,'DISABLED','ENABLED','LIPA-only'),(28,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001106',9,15,'DISABLED','ENABLED','LIPA-only'),(29,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001107',9,15,'DISABLED','ENABLED','LIPA-only'),(30,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001108',9,15,'DISABLED','ENABLED','LIPA-only'),(31,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001109',9,15,'DISABLED','ENABLED','LIPA-only'),(32,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001110',9,15,'DISABLED','ENABLED','LIPA-only'),(33,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001111',9,15,'DISABLED','ENABLED','LIPA-only'),(34,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001112',9,15,'DISABLED','ENABLED','LIPA-only'),(35,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001113',9,15,'DISABLED','ENABLED','LIPA-only'),(44,'operator','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001113',9,15,'DISABLED','ENABLED','LIPA-only'),(45,'operator','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001112',9,15,'DISABLED','ENABLED','LIPA-only'),(46,'operator','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208930100001111',9,15,'DISABLED','ENABLED','LIPA-only'),(47,'operator','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000002',9,15,'DISABLED','ENABLED','LIPA-only'),(48,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000008',9,15,'DISABLED','ENABLED','LIPA-only'),(49,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000009',9,15,'DISABLED','ENABLED','LIPA-only'),(50,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000010',9,15,'DISABLED','ENABLED','LIPA-only'),(51,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000011',9,15,'DISABLED','ENABLED','LIPA-only'),(52,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000012',9,15,'DISABLED','ENABLED','LIPA-only'),(53,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000013',9,15,'DISABLED','ENABLED','LIPA-only'),(54,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000014',9,15,'DISABLED','ENABLED','LIPA-only'),(55,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208950000000015',9,15,'DISABLED','ENABLED','LIPA-only'),(56,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001118',9,15,'DISABLED','ENABLED','LIPA-only'),(57,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001121',9,15,'DISABLED','ENABLED','LIPA-only'),(58,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001120',9,15,'DISABLED','ENABLED','LIPA-only'),(59,'oai.ipv4','IPv4','0.0.0.0','0:0:0:0:0:0:0:0',50000000,100000000,3,'208920100001119',9,15,'DISABLED','ENABLED','LIPA-only'); +/*!40000 ALTER TABLE `pdn` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pgw` +-- + +DROP TABLE IF EXISTS `pgw`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pgw` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ipv4` varchar(15) NOT NULL, + `ipv6` varchar(39) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `ipv4` (`ipv4`), + UNIQUE KEY `ipv6` (`ipv6`) +) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `pgw` +-- + +LOCK TABLES `pgw` WRITE; +/*!40000 ALTER TABLE `pgw` DISABLE KEYS */; +INSERT INTO `pgw` VALUES (1,'127.0.0.1','0:0:0:0:0:0:0:1'),(2,'192.168.56.101',''),(3,'10.0.0.2','0'); +/*!40000 ALTER TABLE `pgw` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `terminal-info` +-- + +DROP TABLE IF EXISTS `terminal-info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `terminal-info` ( + `imei` varchar(15) NOT NULL, + `sv` varchar(2) NOT NULL, + UNIQUE KEY `imei` (`imei`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `terminal-info` +-- + +LOCK TABLES `terminal-info` WRITE; +/*!40000 ALTER TABLE `terminal-info` DISABLE KEYS */; +/*!40000 ALTER TABLE `terminal-info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `users` +-- + +DROP TABLE IF EXISTS `users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `users` ( + `imsi` varchar(15) NOT NULL COMMENT 'IMSI is the main reference key.', + `msisdn` varchar(46) DEFAULT NULL COMMENT 'The basic MSISDN of the UE (Presence of MSISDN is optional).', + `imei` varchar(15) DEFAULT NULL COMMENT 'International Mobile Equipment Identity', + `imei_sv` varchar(2) DEFAULT NULL COMMENT 'International Mobile Equipment Identity Software Version Number', + `ms_ps_status` enum('PURGED','NOT_PURGED') DEFAULT 'PURGED' COMMENT 'Indicates that ESM and EMM status are purged from MME', + `rau_tau_timer` int(10) unsigned DEFAULT '120', + `ue_ambr_ul` bigint(20) unsigned DEFAULT '50000000' COMMENT 'The Maximum Aggregated uplink MBRs to be shared across all Non-GBR bearers according to the subscription of the user.', + `ue_ambr_dl` bigint(20) unsigned DEFAULT '100000000' COMMENT 'The Maximum Aggregated downlink MBRs to be shared across all Non-GBR bearers according to the subscription of the user.', + `access_restriction` int(10) unsigned DEFAULT '60' COMMENT 'Indicates the access restriction subscription information. 3GPP TS.29272 #7.3.31', + `mme_cap` int(10) unsigned zerofill DEFAULT NULL COMMENT 'Indicates the capabilities of the MME with respect to core functionality e.g. regional access restrictions.', + `mmeidentity_idmmeidentity` int(11) NOT NULL DEFAULT '0', + `key` varbinary(16) NOT NULL DEFAULT '0' COMMENT 'UE security key', + `RFSP-Index` smallint(5) unsigned NOT NULL DEFAULT '1' COMMENT 'An index to specific RRM configuration in the E-UTRAN. Possible values from 1 to 256', + `urrp_mme` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'UE Reachability Request Parameter indicating that UE activity notification from MME has been requested by the HSS.', + `sqn` bigint(20) unsigned zerofill NOT NULL, + `rand` varbinary(16) NOT NULL, + `OPc` varbinary(16) DEFAULT NULL COMMENT 'Can be computed by HSS', + PRIMARY KEY (`imsi`,`mmeidentity_idmmeidentity`), + KEY `fk_users_mmeidentity_idx1` (`mmeidentity_idmmeidentity`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `users` +-- + +LOCK TABLES `users` WRITE; +/*!40000 ALTER TABLE `users` DISABLE KEYS */; +INSERT INTO `users` VALUES ('20834123456789','380561234567','35609204079300',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,'+�E��ų\0�,IH��H',0,0,00000000000000000096,'Px�X \Z1��x��','^��K�����FeU���'),('20810000001234','33611123456','35609204079299',NULL,'PURGED',120,40000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000281454575616225,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0','�4�s@���z��~�'),('31002890832150','33638060059','35611302209414',NULL,'PURGED',120,40000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012416,'`�F�݆��D��ϛ���','�4�s@���z��~�'),('001010123456789','33600101789','35609204079298',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'\0 \n \r',1,0,00000000000000000351,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0','L�*\\�����^��]� '),('208930000000001','33638030001','35609204079301',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208950000000002','33638050002','35609204079502',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000020471,'\0 \n \r','�4�s@���z��~�'),('208950000000003','33638050003','35609204079503',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012343,'\0 \n \r','�4�s@���z��~�'),('208950000000004','33638050004','35609204079504',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000005','33638050005','35609204079505',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000001','33638050001','35609204079501',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208950000000006','33638050006','35609204079506',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000007','33638050007','35609204079507',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208930000000002','33638030002','35609204079302',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208930000000003','33638030003','35609204079303',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208930000000004','33638030004','35609204079304',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208930000000005','33638030005','35609204079305',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208930000000006','33638030006','35609204079306',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208930000000007','33638030007','35609204079307',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208940000000007','33638040007','35609204079407',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208940000000006','33638040006','35609204079406',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208940000000005','33638040005','35609204079405',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208940000000004','33638040004','35609204079404',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208940000000003','33638040003','35609204079403',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208940000000002','33638040002','35609204079402',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208940000000001','33638040001','35609204079401',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'��wq��gzW����Z]','�4�s@���z��~�'),('208920100001100','33638020001','35609204079201',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001101','33638020001','35609204079201',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204937234,'\0 \n \r','�$I6;��+f�k�u�|�'),('208920100001102','33638020002','35609204079202',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001103','33638020003','35609204079203',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001104','33638020004','35609204079204',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001105','33638020005','35609204079205',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001106','33638020006','35609204079206',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000000000000006103,'ebd07771ace8677a','�$I6;��+f�k�u�|�'),('208920100001107','33638020007','35609204079207',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001108','33638020008','35609204079208',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001109','33638020009','35609204079209',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208920100001110','33638020010','35609204079210',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208930100001111','33638030011','35609304079211',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208930100001112','33638030012','35609304079212',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006103,'ebd07771ace8677a','�4�s@���z��~�'),('208930100001113','33638030013','35609304079213',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000006263,'�SNܒ�Iv��e�6','�4�s@���z��~�'),('208950000000008','33638050008','35609204079508',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000009','33638050009','35609204079509',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000010','33638050010','35609204079510',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000011','33638050011','35609204079511',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000012','33638050012','35609204079512',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000013','33638050013','35609204079513',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000014','33638050014','35609204079514',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000012215,'56f0261d9d051063','�4�s@���z��~�'),('208950000000015','33638050015','35609204079515',NULL,'PURGED',120,50000000,100000000,47,0000000000,1,'��G?/�Д���� |hb',1,0,00000000000000000000,'3536663032363164','�4�s@���z��~�'),('208920100001118','33638020010','35609204079210',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204934762,'~?03�u-%�ey�y�','�$I6;��+f�k�u�|�'),('208920100001121','33638020010','35609204079210',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204935293,'&��@xg�]���\n��Vp','�$I6;��+f�k�u�|�'),('208920100001119','33638020010','35609204079210',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204935293,'269482407867805d','�$I6;��+f�k�u�|�'),('208920100001120','33638020010','35609204079210',NULL,'NOT_PURGED',120,50000000,100000000,47,0000000000,1,'��k��p~Љu{�K�',1,0,00000281044204935293,'3236393438323430','�$I6;��+f�k�u�|�'); +INSERT INTO `users` VALUES ('208990100001100','1','55000000000000',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0xfec86ba6eb707ed08905757b1bb44b8f,0,0,0x40,'ebd07771ace8677a',0xc42449363bbad02b66d16bc975d77cc1); +INSERT INTO `users` VALUES ('208950000000031','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000032','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000033','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000034','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000035','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000036','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000037','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000038','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000039','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +INSERT INTO `users` VALUES ('208950000000040','380561234567','55000000000001',NULL,'PURGED',50,40000000,100000000,47,0000000000,1,0x0C0A34601D4F07677303652C0462535B,0,0,0x40,'ebd07771ace8677a',0x63bfa50ee6523365ff14c1f45f88737d); +/*!40000 ALTER TABLE `users` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2016-06-28 11:41:40 diff --git a/ci-scripts/yaml_files/5g_rfsimulator/smf-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/smf-healthcheck.sh new file mode 100755 index 0000000000..d9ff7608e8 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/smf-healthcheck.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -eo pipefail + +STATUS=0 +SMF_IP_SBI_INTERFACE=$(ifconfig $SMF_INTERFACE_NAME_FOR_SBI | grep inet | awk {'print $2'}) +SMF_SBI_PORT_STATUS=$(netstat -tnpl | grep -o "$SMF_IP_SBI_INTERFACE:$SMF_INTERFACE_PORT_FOR_SBI") + +#Check if entrypoint properly configured the conf file and no parameter is unset(optional) +#NB_UNREPLACED_AT=`cat /openair-smf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` + +#if [ $NB_UNREPLACED_AT -ne 0 ]; then +# STATUS=-1 +# echo "Healthcheck error: UNHEALTHY configuration file is not configured properly" +#fi +# +if [[ -z $SMF_SBI_PORT_STATUS ]]; then + STATUS=-1 + echo "Healthcheck error: UNHEALTHY SBI TCP/HTTP port $SMF_INTERFACE_PORT_FOR_SBI is not listening." +fi + +exit $STATUS diff --git a/ci-scripts/yaml_files/5g_rfsimulator/spgwu-healthcheck.sh b/ci-scripts/yaml_files/5g_rfsimulator/spgwu-healthcheck.sh new file mode 100755 index 0000000000..0e3b67ee7e --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/spgwu-healthcheck.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -eo pipefail + +STATUS=0 +SGW_PORT_FOR_S1U_S12_S4_UP=2152 +SGW_PORT_FOR_SX=8805 +SGW_IP_S1U_INTERFACE=$(ifconfig $SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP | grep inet | awk {'print $2'}) +SGW_IP_SX_INTERFACE=$(ifconfig $SGW_INTERFACE_NAME_FOR_SX | grep inet | awk {'print $2'}) +S1U_S12_S4_UP_PORT_STATUS=$(netstat -unpl | grep -o "$SGW_IP_S1U_INTERFACE:$SGW_PORT_FOR_S1U_S12_S4_UP") +SX_PORT_STATUS=$(netstat -unpl | grep -o "$SGW_IP_SX_INTERFACE:$SGW_PORT_FOR_SX") +#Check if entrypoint properly configured the conf file and no parameter is unset (optional) +NB_UNREPLACED_AT=`cat /openair-spgwu/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true` +if [ $NB_UNREPLACED_AT -ne 0 ]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY configuration file is not configured properly" +fi + +if [[ -z $S1U_S12_S4_UP_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY S1U port $SGW_PORT_FOR_S1U_S12_S4_UP is not listening." +fi + +if [[ -z $SX_PORT_STATUS ]]; then + STATUS=1 + echo "Healthcheck error: UNHEALTHY SX port $SGW_PORT_FOR_SX is not listening." +fi + +exit $STATUS \ No newline at end of file diff --git a/ci-scripts/yaml_files/fr1_enb_mono_fdd_tim/docker-compose.yml b/ci-scripts/yaml_files/fr1_enb_mono_fdd_tim/docker-compose.yml new file mode 100644 index 0000000000..2df277d78b --- /dev/null +++ b/ci-scripts/yaml_files/fr1_enb_mono_fdd_tim/docker-compose.yml @@ -0,0 +1,49 @@ +version: '3.8' + +services: + enb_mono_fdd: + image: oai-enb:latest + privileged: true + container_name: prod-enb-mono-fdd + environment: + USE_FDD_MONO: 'yes' + USE_B2XX: 'yes' + ENB_NAME: eNB-in-docker + MCC: '222' + MNC: '01' + MNC_LENGTH: 2 + TAC: 1 + UTRA_BAND_ID: 7 + DL_FREQUENCY_IN_MHZ: 2680 + UL_FREQUENCY_OFFSET_IN_MHZ: 120 + NID_CELL: 10 + NB_PRB: 25 + MME_S1C_IP_ADDRESS: CI_MME_IP_ADDR + ENB_S1C_IF_NAME: eth0 + ENB_S1C_IP_ADDRESS: 192.168.61.30 + ENB_S1U_IF_NAME: eth0 + ENB_S1U_IP_ADDRESS: 192.168.61.30 + ENB_X2_IP_ADDRESS: 192.168.61.30 + FLEXRAN_ENABLED: 'no' + FLEXRAN_INTERFACE_NAME: eth0 + FLEXRAN_IPV4_ADDRESS: CI_FLEXRAN_CTL_IP_ADDR + USE_ADDITIONAL_OPTIONS: '--RUs.[0].max_rxgain 115 --RUs.[0].max_pdschReferenceSignalPower -27 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96' + volumes: + - /dev:/dev + networks: + public_net: + ipv4_address: 192.168.61.30 + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + name: prod-oai-public-net + ipam: + config: + - subnet: 192.168.61.0/26 + diff --git a/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml b/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml new file mode 100644 index 0000000000..a3675dc78e --- /dev/null +++ b/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml @@ -0,0 +1,210 @@ +version: '3.8' + +services: + cassandra: + image: cassandra:2.1 + container_name: prod-cassandra + networks: + private_net: + ipv4_address: 192.168.68.2 + environment: + CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster" + CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch + healthcheck: + test: /bin/bash -c "nodetool status" + interval: 10s + timeout: 5s + retries: 5 + + db_init: + image: cassandra:2.1 + container_name: prod-db-init + depends_on: [cassandra] + deploy: + restart_policy: + condition: on-failure + max_attempts: 10 + networks: + private_net: + ipv4_address: 192.168.68.4 + volumes: + - ./oai_db.cql:/home/oai_db.cql + entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.2 && echo 'OK'" + + oai_hss: + image: oai-hss:production + container_name: prod-oai-hss + privileged: true + depends_on: [cassandra] + networks: + private_net: + ipv4_address: 192.168.68.3 + public_net: + ipv4_address: 192.168.61.194 + environment: + TZ: Europe/Paris + REALM: openairinterface.org + HSS_FQDN: hss.openairinterface.org + PREFIX: /openair-hss/etc + cassandra_Server_IP: 192.168.68.2 + OP_KEY: 1006020f0a478bf6b699f15c062e42b3 + LTE_K: FEC86BA6EB707ED08905757B1BB44B8F + APN1: oai.ipv4 + APN2: oai2.ipv4 + FIRST_IMSI: 208970100001127 + NB_USERS: 5 + healthcheck: + test: /bin/bash -c "pgrep oai_hss" + interval: 10s + timeout: 5s + retries: 5 + + oai_mme: + image: oai-mme:production + container_name: prod-oai-mme + privileged: true + depends_on: [oai_hss] + networks: + public_net: + ipv4_address: 192.168.61.195 + environment: + TZ: Europe/Paris + REALM: openairinterface.org + PREFIX: /openair-mme/etc + INSTANCE: 1 + PID_DIRECTORY: /var/run + HSS_IP_ADDR: 192.168.61.194 + HSS_HOSTNAME: hss + HSS_FQDN: hss.openairinterface.org + HSS_REALM: openairinterface.org + MCC: '208' + MNC: '97' + MME_GID: 32768 + MME_CODE: 3 + TAC_0: 1 + TAC_1: 2 + TAC_2: 3 + MME_FQDN: mme.openairinterface.org + MME_S6A_IP_ADDR: 192.168.61.195 + MME_INTERFACE_NAME_FOR_S1_MME: eth0 + MME_IPV4_ADDRESS_FOR_S1_MME: 192.168.61.195 + MME_INTERFACE_NAME_FOR_S11: eth0 + MME_IPV4_ADDRESS_FOR_S11: 192.168.61.195 + MME_INTERFACE_NAME_FOR_S10: lo + MME_IPV4_ADDRESS_FOR_S10: 127.0.0.10 + OUTPUT: CONSOLE + SGW_IPV4_ADDRESS_FOR_S11_0: 192.168.61.196 + PEER_MME_IPV4_ADDRESS_FOR_S10_0: 0.0.0.0 + PEER_MME_IPV4_ADDRESS_FOR_S10_1: 0.0.0.0 + MCC_SGW_0: '208' + MNC3_SGW_0: '097' + TAC_LB_SGW_0: '01' + TAC_HB_SGW_0: '00' + MCC_MME_0: '208' + MNC3_MME_0: '097' + TAC_LB_MME_0: '02' + TAC_HB_MME_0: '00' + MCC_MME_1: '208' + MNC3_MME_1: '097' + TAC_LB_MME_1: '03' + TAC_HB_MME_1: '00' + TAC_LB_SGW_TEST_0: '03' + TAC_HB_SGW_TEST_0: '00' + SGW_IPV4_ADDRESS_FOR_S11_TEST_0: 0.0.0.0 + volumes: + - ./mme.conf:/openair-mme/etc/mme.conf + - ./entrypoint.sh:/openair-mme/bin/entrypoint.sh + healthcheck: + test: /bin/bash -c "pgrep oai_mme" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwc: + image: oai-spgwc:production + privileged: true + depends_on: [oai_mme] + container_name: prod-oai-spgwc + networks: + public_net: + ipv4_address: 192.168.61.196 + environment: + TZ: Europe/Paris + SGW_INTERFACE_NAME_FOR_S11: eth0 + PGW_INTERFACE_NAME_FOR_SX: eth0 + DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129 + DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 + PUSH_PROTOCOL_OPTION: 'true' + APN_NI_1: oai.ipv4 + APN_NI_2: oai2.ipv4 + DEFAULT_APN_NI_1: oai.ipv4 + UE_IP_ADDRESS_POOL_1: '12.1.1.2 - 12.1.1.254' + UE_IP_ADDRESS_POOL_2: '12.0.0.2 - 12.0.0.254' + MCC: '208' + MNC: '97' + MNC03: '097' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org + UE_MTU_IPV4: 1500 + healthcheck: + test: /bin/bash -c "pgrep oai_spgwc" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwu: + image: oai-spgwu-tiny:production + privileged: true + container_name: prod-oai-spgwu-tiny + depends_on: [oai_spgwc] + networks: + public_net: + ipv4_address: 192.168.61.197 + environment: + TZ: Europe/Paris + PID_DIRECTORY: /var/run + INSTANCE: 1 + SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0 + PGW_INTERFACE_NAME_FOR_SGI: eth0 + SGW_INTERFACE_NAME_FOR_SX: eth0 + SPGWC0_IP_ADDRESS: 192.168.61.196 + NETWORK_UE_IP: '12.1.1.0/24' + NETWORK_UE_NAT_OPTION: 'yes' + MCC: '208' + MNC: '97' + MNC03: '097' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org + healthcheck: + test: /bin/bash -c "pgrep oai_spgwu" + interval: 10s + timeout: 5s + retries: 5 + + trf_gen: + image: trf-gen:production + privileged: true + container_name: prod-trf-gen + networks: + public_net: + ipv4_address: 192.168.61.200 + entrypoint: /bin/bash -c "ip route add 12.1.1.0/24 via 192.168.61.197 dev eth0; sleep infinity" + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.61.197" + interval: 10s + timeout: 5s + retries: 5 + +networks: + private_net: + name: prod-oai-private-net + ipam: + config: + - subnet: 192.168.68.0/26 + public_net: + name: prod-oai-public-net + ipam: + config: + - subnet: 192.168.61.192/26 diff --git a/ci-scripts/yaml_files/fr1_epc_20897/entrypoint.sh b/ci-scripts/yaml_files/fr1_epc_20897/entrypoint.sh new file mode 100755 index 0000000000..27c6c401a6 --- /dev/null +++ b/ci-scripts/yaml_files/fr1_epc_20897/entrypoint.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +set -euo pipefail + +# First see if all interfaces are up +ifconfig + +# S10 might be on loopback --> needs bring-up +if [[ "$MME_INTERFACE_NAME_FOR_S10" == *"lo:"* ]] +then + ifconfig ${MME_INTERFACE_NAME_FOR_S10} ${MME_IPV4_ADDRESS_FOR_S10} up +fi + +LIST_OF_NETWORKS=`ifconfig -s | egrep -v "^Iface|^lo" | cut -d' ' -f1` + +for if_name in $LIST_OF_NETWORKS +do + IF_IP_ADDR=`ifconfig $if_name | grep inet | sed -e "s# *inet#inet#" | cut -d' ' -f2` + if [[ "${IF_IP_ADDR}" == "${MME_IPV4_ADDRESS_FOR_S1_MME}" ]]; then + echo "S1C is on $if_name" + MME_INTERFACE_NAME_FOR_S1_MME=$if_name + fi + if [[ "${IF_IP_ADDR}" == "${MME_IPV4_ADDRESS_FOR_S10}" ]]; then + echo "S10 is on $if_name" + MME_INTERFACE_NAME_FOR_S10=$if_name + fi + if [[ "${IF_IP_ADDR}" == "${MME_IPV4_ADDRESS_FOR_S11}" ]]; then + echo "S11 is on $if_name" + MME_INTERFACE_NAME_FOR_S11=$if_name + fi +done + +CONFIG_DIR="/openair-mme/etc" + +for c in ${CONFIG_DIR}/mme_fd.conf; do + #echo "entrypoint.sh process config file $c" + sed -i -e "s#@TAC-LB#@TAC_LB#" -e "s#TAC-HB_#TAC_HB_#" ${c} + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + #echo "entrypoint.sh process vars $VARS" + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + #echo "var is $v" + NEW_VAR=`echo $v | sed -e "s#@##g"` + #echo "NEW_VAR is $NEW_VAR" + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + # Some fields require CIDR format + if [[ "${NEW_VAR}" == "MME_IPV4_ADDRESS_FOR_S1_MME" ]] || \ + [[ "${NEW_VAR}" == "MME_IPV4_ADDRESS_FOR_S11" ]] || \ + [[ "${NEW_VAR}" == "MME_IPV4_ADDRESS_FOR_S10" ]]; then + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}/24|g" + else + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + fi + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +pushd /openair-mme/scripts +./check_mme_s6a_certificate ${PREFIX} ${MME_FQDN} +popd + +exec "$@" diff --git a/ci-scripts/yaml_files/fr1_epc_20897/mme.conf b/ci-scripts/yaml_files/fr1_epc_20897/mme.conf new file mode 100644 index 0000000000..9dcb44ef2a --- /dev/null +++ b/ci-scripts/yaml_files/fr1_epc_20897/mme.conf @@ -0,0 +1,133 @@ +MME : +{ + REALM = "openairinterface.org"; # YOUR REALM HERE + INSTANCE = 1; # 0 is the default + PID_DIRECTORY = "/var/run"; # /var/run is the default + MAX_S1_ENB = 64; + MAX_UE = 4096; + RELATIVE_CAPACITY = 10; + EMERGENCY_ATTACH_SUPPORTED = "no"; + UNAUTHENTICATED_IMSI_SUPPORTED = "no"; + DUMMY_HANDOVER_FORWARDING_ENABLED = "yes"; + EPS_NETWORK_FEATURE_SUPPORT_IMS_VOICE_OVER_PS_SESSION_IN_S1 = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_EMERGENCY_BEARER_SERVICES_IN_S1_MODE = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_LOCATION_SERVICES_VIA_EPC = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_EXTENDED_SERVICE_REQUEST = "no"; # DO NOT CHANGE + + # Display statistics about whole system (expressed in seconds) + MME_STATISTIC_TIMER = 10; + MME_MOBILITY_COMPLETION_TIMER = 2; # Amount of time in seconds the source MME waits to release resources after HANDOVER/TAU is complete (with or without. + MME_S10_HANDOVER_COMPLETION_TIMER = 2; # Amount of time in soconds the target MME waits to check if a handover/tau process has completed successfully. + + IP_CAPABILITY = "IPV4V6"; + INTERTASK_INTERFACE : + { + ITTI_QUEUE_SIZE = 2000000; + }; + + S6A : + { + S6A_CONF = "/openair-mme/etc/mme_fd.conf"; + HSS_HOSTNAME = "hss.openairinterface.org"; # THE HSS FQDN ex: hss.epc.mnc001.mcc001.3gppnetwork.org + HSS_REALM = "openairinterface.org"; # THE HSS REALM ex: epc.mnc001.mcc001.3gppnetwork.org + }; + + SCTP : + { + SCTP_INSTREAMS = 8; + SCTP_OUTSTREAMS = 8; + }; + + S1AP : + { + S1AP_OUTCOME_TIMER = 10; + }; + + GUMMEI_LIST = ( + {MCC="208" ; MNC="97"; MME_GID="32768" ; MME_CODE="3"; } # YOUR GUMMEI CONFIG HERE + ); + + TAI_LIST = ( + {MCC="208" ; MNC="97"; TAC = "1"; }, # YOUR TAI CONFIG HERE + {MCC="208" ; MNC="97"; TAC = "2"; }, # YOUR TAI CONFIG HERE + {MCC="208" ; MNC="97"; TAC = "3"; } # YOUR TAI CONFIG HERE + ); + + NAS : + { + ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST = [ "EIA2" , "EIA1" , "EIA0" ]; + ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST = [ "EEA0" , "EEA1" , "EEA2" ]; + T3402 = 12 + T3412 = 0 + T3422 = 6 + T3450 = 6 + T3460 = 6 + T3470 = 6 + T3485 = 3 + T3486 = 3 + T3489 = 4 + T3495 = 3 + NAS_FORCE_TAU = 0 + STRICT_FILLER_BITS_CHECK = "yes"; + }; + + NETWORK_INTERFACES : + { + # MME binded interface for S1-C or S1-MME communication (S1AP), can be ethernet interface, virtual ethernet interface, we don't advise wireless interfaces + MME_INTERFACE_NAME_FOR_S1_MME = "eth0"; # YOUR NETWORK CONFIG HERE + MME_IPV4_ADDRESS_FOR_S1_MME = "192.168.61.195/24"; # CIDR, YOUR NETWORK CONFIG HERE +# MME_IPV6_ADDRESS_FOR_S1_MME = "fd00::191/118"; # YOUR NETWORK CONFIG HERE + # MME binded interface for S11 communication (GTPV2-C) + MME_INTERFACE_NAME_FOR_S11 = "eth0"; # YOUR NETWORK CONFIG HERE + MME_IPV4_ADDRESS_FOR_S11 = "192.168.61.195/24"; # CIDR, YOUR NETWORK CONFIG HERE +# MME_IPV6_ADDRESS_FOR_S11 = "fd00:0:0:4::191/64"; + MME_PORT_FOR_S11 = 2123; # YOUR NETWORK CONFIG HERE + + + #S10 Interface + MME_INTERFACE_NAME_FOR_S10 = "lo"; # YOUR NETWORK CONFIG HERE + MME_IPV4_ADDRESS_FOR_S10 = "127.0.0.10/24"; # CIDR, YOUR NETWORK CONFIG HERE +# MME_IPV6_ADDRESS_FOR_S10 = "fd00:0:0:4::191/64"; + MME_PORT_FOR_S10 = 2123; # YOUR NETWORK CONFIG HERE + }; + + LOGGING : + { + # OUTPUT choice in { "CONSOLE", `path to file`", "`IPv4@`:`TCP port num`"} + # `path to file` must start with '.' or '/' + # if TCP stream choice, then you can easily dump the traffic on the remote or local host: nc -l `TCP port num` > received.txt + OUTPUT = "CONSOLE"; + THREAD_SAFE = "no"; # THREAD_SAFE choice in { "yes", "no" }, safe to let 'no' + COLOR = "yes"; # COLOR choice in { "yes", "no" } means use of ANSI styling codes or no + # Log level choice in { "EMERGENCY", "ALERT", "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG", "TRACE"} + SCTP_LOG_LEVEL = "TRACE"; + S10_LOG_LEVEL = "TRACE"; + S11_LOG_LEVEL = "TRACE"; + # NEW LOGS FOR MCE + SM_LOG_LEVEL = "TRACE"; + MCE_APP_LOG_LEVEL = "TRACE"; + M2AP_LOG_LEVEL = "TRACE"; + GTPV2C_LOG_LEVEL = "TRACE"; + UDP_LOG_LEVEL = "DEBUG"; + S1AP_LOG_LEVEL = "DEBUG"; + NAS_LOG_LEVEL = "TRACE"; + MME_APP_LOG_LEVEL = "TRACE"; + S6A_LOG_LEVEL = "TRACE"; + UTIL_LOG_LEVEL = "ERROR"; + MSC_LOG_LEVEL = "ERROR"; + ITTI_LOG_LEVEL = "ERROR"; + ASN1_VERBOSITY = "annoying"; + }; + + +# WRR_LIST_SELECTION = ( +# {ID="tac-lb03.tac-hb00.tac.epc.mnc001.mcc001.3gppnetwork.org" ; SGW_IP_ADDRESS_FOR_S11="192.168.61.196";}, +# {ID="tac-lb01.tac-hb00.tac.epc.mnc097.mcc208.3gppnetwork.org" ; SGW_IP_ADDRESS_FOR_S11="192.168.61.196";}, +# {ID="tac-lb02.tac-hb00.tac.epc.mnc097.mcc208.3gppnetwork.org" ; MME_IP_ADDRESS_FOR_S10="0.0.0.0";}, +# {ID="tac-lb03.tac-hb00.tac.epc.mnc097.mcc208.3gppnetwork.org" ; MME_IP_ADDRESS_FOR_S10="0.0.0.0";} +# ); + WRR_LIST_SELECTION = ( + {ID="tac-lb01.tac-hb00.tac.epc.mnc097.mcc208.3gppnetwork.org" ; SGW_IP_ADDRESS_FOR_S11="192.168.61.196";} + ); +}; + diff --git a/ci-scripts/yaml_files/magma_nsa_20897/docker-compose.yml b/ci-scripts/yaml_files/magma_nsa_20897/docker-compose.yml new file mode 100644 index 0000000000..df14e900e7 --- /dev/null +++ b/ci-scripts/yaml_files/magma_nsa_20897/docker-compose.yml @@ -0,0 +1,198 @@ +version: '3.8' + +services: + cassandra: + image: cassandra:2.1 + container_name: prod-cassandra + networks: + private_net: + ipv4_address: 192.168.68.2 + environment: + CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster" + CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch + healthcheck: + test: /bin/bash -c "nodetool status" + interval: 10s + timeout: 5s + retries: 5 + + db_init: + image: cassandra:2.1 + container_name: prod-db-init + depends_on: [cassandra] + deploy: + restart_policy: + condition: on-failure + max_attempts: 10 + networks: + private_net: + ipv4_address: 192.168.68.4 + volumes: + - ./oai_db.cql:/home/oai_db.cql + entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.2 && echo 'OK'" + + oai_hss: + image: oai-hss:production + container_name: prod-oai-hss + privileged: true + depends_on: [cassandra] + networks: + private_net: + ipv4_address: 192.168.68.3 + public_net: + ipv4_address: 192.168.61.194 + environment: + TZ: Europe/Paris + REALM: openairinterface.org + HSS_FQDN: hss.openairinterface.org + PREFIX: /openair-hss/etc + cassandra_Server_IP: 192.168.68.2 + OP_KEY: 1006020f0a478bf6b699f15c062e42b3 + LTE_K: FEC86BA6EB707ED08905757B1BB44B8F + APN1: oai.ipv4 + APN2: oai2.ipv4 + FIRST_IMSI: 208970100001127 + NB_USERS: 10 + healthcheck: + test: /bin/bash -c "pgrep oai_hss" + interval: 10s + timeout: 5s + retries: 5 + + redis: + image: redis:6.0.5 + container_name: prod-redis + privileged: true + networks: + public_net: + ipv4_address: 192.168.61.198 + volumes: + - ./redis_extern.conf:/usr/local/etc/redis/redis.conf + entrypoint: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf" + healthcheck: + test: /bin/bash -c "redis-cli -h 192.168.61.198 -p 6380 ping" + interval: 10s + timeout: 5s + retries: 5 + + magma_mme: + image: magma-mme:production + container_name: prod-magma-mme + hostname: mme + privileged: true + depends_on: [oai_hss, redis] + networks: + public_net: + ipv4_address: 192.168.61.195 + environment: + TZ: Europe/Paris + REALM: openairinterface.org + PREFIX: /openair-mme/etc + HSS_HOSTNAME: hss + HSS_FQDN: hss.openairinterface.org + HSS_REALM: openairinterface.org + MME_FQDN: mme.openairinterface.org + FEATURES: mme_oai + volumes: + - ./mme_fd.sprint.conf:/magma-mme/etc/mme_fd.conf.tmplt + - ./mme.conf:/magma-mme/etc/mme.conf + - ./entrypoint.sh:/magma-mme/bin/entrypoint.sh + entrypoint: /bin/bash -c "/magma-mme/bin/entrypoint.sh" + healthcheck: + test: /bin/bash -c "pgrep oai_mme" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwc: + image: oai-spgwc:production + privileged: true + depends_on: [magma_mme] + container_name: prod-oai-spgwc + networks: + public_net: + ipv4_address: 192.168.61.196 + environment: + TZ: Europe/Paris + SGW_INTERFACE_NAME_FOR_S11: eth0 + PGW_INTERFACE_NAME_FOR_SX: eth0 + DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129 + DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 + PUSH_PROTOCOL_OPTION: 'true' + APN_NI_1: oai.ipv4 + APN_NI_2: oai2.ipv4 + DEFAULT_APN_NI_1: oai.ipv4 + UE_IP_ADDRESS_POOL_1: '12.1.1.2 - 12.1.1.254' + UE_IP_ADDRESS_POOL_2: '12.0.0.2 - 12.0.0.254' + MCC: '208' + MNC: '97' + MNC03: '097' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org + UE_MTU_IPV4: 1500 + healthcheck: + test: /bin/bash -c "pgrep oai_spgwc" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwu: + image: oai-spgwu-tiny:production + privileged: true + container_name: prod-oai-spgwu-tiny + depends_on: [oai_spgwc] + networks: + public_net: + ipv4_address: 192.168.61.197 + environment: + TZ: Europe/Paris + PID_DIRECTORY: /var/run + INSTANCE: 1 + SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0 + PGW_INTERFACE_NAME_FOR_SGI: eth0 + SGW_INTERFACE_NAME_FOR_SX: eth0 + SPGWC0_IP_ADDRESS: 192.168.61.196 + NETWORK_UE_IP: '12.1.1.0/24' + NETWORK_UE_NAT_OPTION: 'yes' + MCC: '208' + MNC: '97' + MNC03: '097' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org + healthcheck: + test: /bin/bash -c "pgrep oai_spgwu" + interval: 10s + timeout: 5s + retries: 5 + + trf_gen: + image: trf-gen:production + privileged: true + container_name: prod-trf-gen + networks: + public_net: + ipv4_address: 192.168.61.200 + entrypoint: /bin/bash -c "ip route add 12.1.1.0/24 via 192.168.61.197 dev eth0; sleep infinity" + healthcheck: + test: /bin/bash -c "ip route | grep '12.1.1.0'" + interval: 10s + timeout: 5s + retries: 5 + +networks: + private_net: + name: prod-oai-private-net + ipam: + config: + - subnet: 192.168.68.0/26 + driver_opts: + com.docker.network.bridge.name: "oai-priv-net" + public_net: + name: prod-oai-public-net + ipam: + config: + - subnet: 192.168.61.192/26 + driver_opts: + com.docker.network.bridge.name: "oai-pub-net" diff --git a/ci-scripts/yaml_files/magma_nsa_20897/entrypoint.sh b/ci-scripts/yaml_files/magma_nsa_20897/entrypoint.sh new file mode 100755 index 0000000000..859ff7d98f --- /dev/null +++ b/ci-scripts/yaml_files/magma_nsa_20897/entrypoint.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +INSTANCE=1 +PREFIX='/magma-mme/etc' +MY_REALM='openairinterface.org' + +declare -A MME_CONF + +pushd $PREFIX +MME_CONF[@MME_S6A_IP_ADDR@]="192.168.61.195" +MME_CONF[@INSTANCE@]=$INSTANCE +MME_CONF[@PREFIX@]=$PREFIX +MME_CONF[@REALM@]=$MY_REALM +MME_CONF[@MME_FQDN@]="mme.${MME_CONF[@REALM@]}" +MME_CONF[@HSS_HOSTNAME@]='hss' +MME_CONF[@HSS_FQDN@]="${MME_CONF[@HSS_HOSTNAME@]}.${MME_CONF[@REALM@]}" +MME_CONF[@HSS_IP_ADDR@]="192.168.61.194" + +cp mme_fd.conf.tmplt $PREFIX/mme_fd.conf + +for K in "${!MME_CONF[@]}"; do + egrep -lRZ "$K" $PREFIX/mme_fd.conf | xargs -0 -l sed -i -e "s|$K|${MME_CONF[$K]}|g" + ret=$?;[[ ret -ne 0 ]] && echo "Tried to replace $K with ${MME_CONF[$K]}" +done + +sed -i -e "s@etc/freeDiameter@etc@" /magma-mme/etc/mme_fd.conf +sed -i -e "s@bind: 127.0.0.1@bind: 192.168.61.198@" /etc/magma/redis.yml +# Generate freeDiameter certificate +popd +cd /magma-mme/scripts +./check_mme_s6a_certificate $PREFIX mme.${MME_CONF[@REALM@]} + +cd /magma-mme +nohup /magma-mme/bin/sctpd > /var/log/sctpd.log 2>&1 & +sleep 5 +/magma-mme/bin/oai_mme -c /magma-mme/etc/mme.conf diff --git a/ci-scripts/yaml_files/magma_nsa_20897/mme.conf b/ci-scripts/yaml_files/magma_nsa_20897/mme.conf new file mode 100644 index 0000000000..242b780a40 --- /dev/null +++ b/ci-scripts/yaml_files/magma_nsa_20897/mme.conf @@ -0,0 +1,134 @@ +# generated by generate_mme_config_script.py +MME : +{ + REALM = "openairinterface.org" + PID_DIRECTORY = "/var/run"; + MAXENB = 8; # power of 2 + MAXUE = 16; # power of 2 + RELATIVE_CAPACITY = 10; + + EMERGENCY_ATTACH_SUPPORTED = "no"; + UNAUTHENTICATED_IMSI_SUPPORTED = "no"; + + # EPS network feature support + EPS_NETWORK_FEATURE_SUPPORT_IMS_VOICE_OVER_PS_SESSION_IN_S1 = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_EMERGENCY_BEARER_SERVICES_IN_S1_MODE = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_LOCATION_SERVICES_VIA_EPC = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_EXTENDED_SERVICE_REQUEST = "no"; # DO NOT CHANGE + + # Display statistics about whole system (expressed in seconds) + MME_STATISTIC_TIMER = 10; + IP_CAPABILITY = "IPV4"; # UE PDN_TYPE + USE_STATELESS = ""; + + INTERTASK_INTERFACE : + { + # max queue size per task + ITTI_QUEUE_SIZE = 2000000; + }; + + S6A : + { + S6A_CONF = "/magma-mme/etc/mme_fd.conf"; # YOUR MME freeDiameter config file path + HSS_HOSTNAME = "hss.openairinterface.org"; + HSS_REALM = "openairinterface.org"; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 8; + SCTP_OUTSTREAMS = 8; + }; + + # ------- S1AP definitions + S1AP : + { + # outcome drop timer value (seconds) + S1AP_OUTCOME_TIMER = 10; + }; + + # ------- MME served GUMMEIs + GUMMEI_LIST = ( + { MCC="208" ; MNC="97"; MME_GID="32768" ; MME_CODE="3"; } + ); + + # ------- MME served TAIs + TAI_LIST = ( + {MCC="208" ; MNC="97"; TAC = "1"; } + ); + + TAC_LIST = ( + {MCC="208" ; MNC="97"; TAC = "1"; } + ); + + CSFB : + { + NON_EPS_SERVICE_CONTROL = "OFF"; + CSFB_MCC = "208"; + CSFB_MNC = "97"; + LAC = "1"; + }; + NAS : + { + ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST = [ "EIA2" , "EIA1" , "EIA0" ]; + ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST = [ "EEA0" , "EEA1" , "EEA2" ]; + T3402 = 1 # in minutes (default is 12 minutes) + T3412 = 54 # in minutes (default is 54 minutes, network dependent) + T3422 = 6 # in seconds (default is 6s) + T3450 = 6 # in seconds (default is 6s) + T3460 = 6 # in seconds (default is 6s) + T3470 = 6 # in seconds (default is 6s) + T3485 = 8 # UNUSED in seconds (default is 8s) + T3486 = 8 # UNUSED in seconds (default is 8s) + T3489 = 4 # UNUSED in seconds (default is 4s) + T3495 = 8 # UNUSED in seconds (default is 8s) + }; + + SGS : + { + TS6_1 = 10 # in seconds (default is 10s) + TS8 = 4 # in seconds (default is 4s) + TS9 = 2 # in seconds (default is 4s) + TS10 = 4 # in seconds (default is 4s) + TS13 = 4 # in seconds (default is 4s) + }; + + NETWORK_INTERFACES : + { + MME_INTERFACE_NAME_FOR_S1_MME = "eth0"; + MME_IPV4_ADDRESS_FOR_S1_MME = "192.168.61.195/24"; + MME_INTERFACE_NAME_FOR_S11_MME = "eth0"; + MME_IPV4_ADDRESS_FOR_S11_MME = "192.168.61.195/24"; + MME_PORT_FOR_S11_MME = 2123; + }; + + LOGGING : + { + OUTPUT = "CONSOLE"; + THREAD_SAFE = "no"; + COLOR = "no"; + + SCTP_LOG_LEVEL = "ERROR"; + GTPV1U_LOG_LEVEL = "INFO"; + SPGW_APP_LOG_LEVEL = "INFO"; + UDP_LOG_LEVEL = "INFO"; + S1AP_LOG_LEVEL = "DEBUG"; + NAS_LOG_LEVEL = "INFO"; + MME_APP_LOG_LEVEL = "DEBUG"; + GTPV2C_LOG_LEVEL = "INFO"; + S11_LOG_LEVEL = "DEBUG"; + S6A_LOG_LEVEL = "DEBUG"; + UTIL_LOG_LEVEL = "INFO"; + MSC_LOG_LEVEL = "ERROR"; + ITTI_LOG_LEVEL = "ERROR"; + MME_SCENARIO_PLAYER_LOG_LEVEL = "ERROR"; + ASN1_VERBOSITY = "INFO"; + }; + + S-GW : + { + SGW_IPV4_ADDRESS_FOR_S11 = "192.168.61.196"; + }; +}; diff --git a/ci-scripts/yaml_files/magma_nsa_20897/mme_fd.sprint.conf b/ci-scripts/yaml_files/magma_nsa_20897/mme_fd.sprint.conf new file mode 100644 index 0000000000..6f87ed8c2b --- /dev/null +++ b/ci-scripts/yaml_files/magma_nsa_20897/mme_fd.sprint.conf @@ -0,0 +1,169 @@ +# -------- Local --------- + +# Uncomment if the framework cannot resolv it. +Identity = "@MME_FQDN@"; +Realm = "@REALM@"; + +# TLS configuration (see previous section) +TLS_Cred = "@PREFIX@/freeDiameter/mme.cert.pem", + "@PREFIX@/freeDiameter/mme.key.pem"; +TLS_CA = "@PREFIX@/freeDiameter/mme.cacert.pem"; + +# Disable use of TCP protocol (only listen and connect in SCTP) +# Default : TCP enabled +No_SCTP; + +# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. +# Prefer TCP instead of SCTP for establishing new connections. +# This setting may be overwritten per peer in peer configuration blocs. +# Default : SCTP is attempted first. +Prefer_TCP; + + +No_IPv6; + +# Overwrite the number of SCTP streams. This value should be kept low, +# especially if you are using TLS over SCTP, because it consumes a lot of +# resources in that case. See tickets 19 and 27 for some additional details on +# this. +# Limit the number of SCTP streams +SCTP_streams = 3; + + +# By default, freeDiameter acts as a Diameter Relay Agent by forwarding all +# messages it cannot handle locally. This parameter disables this behavior. +NoRelay; + +# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed +# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the +# CER/CEA exchange on a dedicated secure port. +# This parameter only affects outgoing connections. +# The setting can be also defined per-peer (see Peers configuration section). +# Default: use RFC6733 method with separate port for TLS. + +#TLS_old_method; + +AppServThreads = 4; + +# Specify the addresses on which to bind the listening server. This must be +# specified if the framework is unable to auto-detect these addresses, or if the +# auto-detected values are incorrect. Note that the list of addresses is sent +# in CER or CEA message, so one should pay attention to this parameter if some +# adresses should be kept hidden. +ListenOn = "@MME_S6A_IP_ADDR@"; + +Port = 3870; +SecPort = 5870; + +# -------- Extensions --------- + +# Uncomment (and create rtd.conf) to specify routing table for this peer. +#LoadExtension = "/usr/local/lib/freeDiameter/rt_default.fdx" : "rtd.conf"; + +#LoadExtension = "/usr/local/lib/freeDiameter/_sample.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_acct.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_diameap.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_radgw.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_redirect.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_sip.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_interactive.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_monitor.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_msg_dumps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_msg_timings.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_rt.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_3gpp2_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_CreditControl.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_CxDx.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Gx.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_NAS.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Ro.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Rx.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_S6mS6n.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_SGd.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_SLh.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Sd.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Sh.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_T4.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_T6aT6bT7.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Tsp.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca_starent.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_draftload_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_eap.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_etsi283034_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_legacy_xml.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_mip6a.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_mip6i.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_nas_mipv6.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4004_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4006bis_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4072_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4590_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5447_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5580_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5777_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5778_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6734_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6942_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7155_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7683_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7944_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_sip.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29061_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29128_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29154_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29173_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29212_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29214_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29215_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29217_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29229_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29272_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29273_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29329_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29336_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29337_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29338_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29343_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29344_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29345_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29368_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29468_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts32299_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_busypeers.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_default.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_ereg.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_ignore_dh.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_load_balance.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_randomize.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_redirect.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_acct.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_app.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_hss.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_netemul.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_rt_any.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_sip.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Rf.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_S6as6d.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_S6t.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_S6c.fdx"; + + +# -------- Peers --------- + +# The framework will actively attempt to establish and maintain a connection +# with the peers listed here. +# For only accepting incoming connections, see the acl_wl.fx extension. + +# ConnectPeer +# Declare a remote peer to which this peer must maintain a connection. +# In addition, this allows specifying non-default parameters for this peer only +# (for example disable SCTP with this peer, or use RFC3588-flavour TLS). +# Note that by default, if a peer is not listed as a ConnectPeer entry, an +# incoming connection from this peer will be rejected. If you want to accept +# incoming connections from other peers, see the acl_wl.fdx? extension which +# allows exactly this. + +ConnectPeer= "@HSS_FQDN@" { ConnectTo = "@HSS_IP_ADDR@"; No_SCTP ; No_IPv6; Prefer_TCP; No_TLS; port = 3868;}; diff --git a/ci-scripts/yaml_files/magma_nsa_20897/redis_extern.conf b/ci-scripts/yaml_files/magma_nsa_20897/redis_extern.conf new file mode 100644 index 0000000000..565524080a --- /dev/null +++ b/ci-scripts/yaml_files/magma_nsa_20897/redis_extern.conf @@ -0,0 +1,33 @@ +# +# Copyright (c) 2016-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +# Jinja template for Redis configuration +# See the default config file for options and explanations: +# https://github.com/antirez/redis/blob/unstable/redis.conf + +# TODO: make sensible, production-aware config decisions + +bind 192.168.61.198 +port 6380 + +daemonize no +loglevel notice + +timeout 0 +databases 1 + +dbfilename redis_dump.rdb +dir /data + +# Save the DB on disk + +save 900 1 + +save 300 10 + +save 60 1000 diff --git a/ci-scripts/yaml_files/nsa_b200_enb/docker-compose.yml b/ci-scripts/yaml_files/nsa_b200_enb/docker-compose.yml new file mode 100644 index 0000000000..9bd08aeabc --- /dev/null +++ b/ci-scripts/yaml_files/nsa_b200_enb/docker-compose.yml @@ -0,0 +1,53 @@ +version: '3.8' + +services: + enb_mono_fdd: + image: oai-enb:latest + privileged: true + container_name: nsa-b200-enb + environment: + USE_FDD_MONO: 'yes' + USE_B2XX: 'yes' + ENB_NAME: eNB-in-docker + MCC: '222' + MNC: '01' + MNC_LENGTH: 2 + TAC: 1 + UTRA_BAND_ID: 7 + DL_FREQUENCY_IN_MHZ: 2680 + UL_FREQUENCY_OFFSET_IN_MHZ: 120 + NID_CELL: 0 + NB_PRB: 25 + ENABLE_MEASUREMENT_REPORTS: 'yes' + ENABLE_X2: 'yes' + MME_S1C_IP_ADDRESS: 192.168.18.210 + ENB_S1C_IF_NAME: eth0 + ENB_S1C_IP_ADDRESS: 192.168.68.130 + ENB_S1U_IF_NAME: eth0 + ENB_S1U_IP_ADDRESS: 192.168.68.130 + ENB_X2_IP_ADDRESS: 192.168.68.130 + RRC_INACTIVITY_THRESHOLD: 0 + FLEXRAN_ENABLED: 'no' + FLEXRAN_INTERFACE_NAME: eth0 + FLEXRAN_IPV4_ADDRESS: 192.168.18.210 + THREAD_PARALLEL_CONFIG: PARALLEL_SINGLE_THREAD + volumes: + - /dev:/dev + networks: + public_net: + ipv4_address: 192.168.68.130 + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + name: nsa-b200-enb-net + ipam: + config: + - subnet: 192.168.68.128/26 + driver_opts: + com.docker.network.bridge.name: "nsa-enb-net" diff --git a/ci-scripts/yaml_files/nsa_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/nsa_b200_gnb/docker-compose.yml new file mode 100644 index 0000000000..4ae51158ac --- /dev/null +++ b/ci-scripts/yaml_files/nsa_b200_gnb/docker-compose.yml @@ -0,0 +1,50 @@ +version: '3.8' + +services: + gnb_mono_tdd: + image: oai-gnb:latest + privileged: true + container_name: nsa-b200-gnb + environment: + USE_NSA_TDD_MONO: 'yes' + USE_B2XX: 'yes' + GNB_NAME: gNB-in-docker + MCC: '222' + MNC: '01' + MNC_LENGTH: 2 + TAC: 1 + ENABLE_X2: 'yes' + ENB_X2_IP_ADDRESS: 192.168.68.130 + MME_S1C_IP_ADDRESS: 192.168.18.210 + GNB_S1C_IF_NAME: eth0 + GNB_S1C_IP_ADDRESS: 192.168.68.194 + GNB_S1U_IF_NAME: eth0 + GNB_S1U_IP_ADDRESS: 192.168.68.194 + GNB_X2_IP_ADDRESS: 192.168.68.194 + RRC_INACTIVITY_THRESHOLD: 0 + FLEXRAN_ENABLED: 'no' + FLEXRAN_INTERFACE_NAME: eth0 + FLEXRAN_IPV4_ADDRESS: 192.168.18.210 + THREAD_PARALLEL_CONFIG: PARALLEL_RU_L1_TRX_SPLIT + USE_ADDITIONAL_OPTIONS: -E -q --RUs.[0].sdr_addrs serial=30C51D4 + volumes: + - /dev:/dev + networks: + public_net: + ipv4_address: 192.168.68.194 + #entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + name: nsa-b200-gnb-net + ipam: + config: + - subnet: 192.168.68.192/26 + driver_opts: + com.docker.network.bridge.name: "nsa-gnb-net" diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 29c1dc9ad5..6a8add6379 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1,4 +1,4 @@ -#/* +#/* # * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more # * contributor license agreements. See the NOTICE file distributed with # * this work for additional information regarding copyright ownership. @@ -23,6 +23,123 @@ cmake_minimum_required (VERSION 3.0) + +# System packages that are required +# We use either the cmake buildin, in ubuntu are in: /usr/share/cmake*/Modules/ +# or cmake provide a generic interface to pkg-config that widely used +################################### +include(FindPkgConfig) + +pkg_search_module(LIBXML2 libxml-2.0 REQUIRED) +include_directories(${LIBXML2_INCLUDE_DIRS}) + +pkg_search_module(LIBXSLT libxslt REQUIRED) +include_directories(${LIBXSLT_INCLUDE_DIRS}) + +pkg_search_module(OPENSSL openssl REQUIRED) +include_directories(${OPENSSL_INCLUDE_DIRS}) + +pkg_search_module(CONFIG libconfig REQUIRED) +include_directories(${CONFIG_INCLUDE_DIRS}) + +pkg_search_module(CRYPTO libcrypto REQUIRED) +include_directories(${CRYPTO_INCLUDE_DIRS}) + +#uhd 4.0 and iris installs by default in /usr/local +include_directories("/usr/local/include/") +#use native cmake method as this package is not in pkg-config +if (${RF_BOARD} STREQUAL "OAI_USRP") + find_package(Boost REQUIRED) + include_directories(${LIBBOOST_INCLUDE_DIR}) + +elseif (${RF_BOARD} STREQUAL "OAI_IRIS") + include_directories("${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/") + + set(HW_SOURCE ${HW_SOURCE} + ${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp) + LINK_DIRECTORIES("/usr/local/lib") + set(option_HW_lib "-lSoapySDR -rdynamic -ldl") + +elseif (${RF_BOARD} STREQUAL "OAI_AW2SORI") + include_directories("${OPENAIR_TARGETS}/ARCH/AW2SORI") + set(HW_SOURCE ${HW_SOURCE} + ${OPENAIR_TARGETS}/ARCH/AW2SORI/ARCH/AW2SORI/oaiori.c) + LINK_DIRECTORIES("/usr/local/lib") + set(openair_HW_lib "-shared -fPIC -msse4 -g -ggdb -lori") + +endif (${RF_BOARD} STREQUAL "OAI_USRP") + +pkg_search_module(OPENPGM openpgm-5.1 openpgm-5.2) +if(NOT ${OPENPGM_FOUND}) + message("PACKAGE openpgm-5.1 is required by binaries such as oaisim: will fail later if this target is built") +else() + include_directories(${OPENPGM_INCLUDE_DIRS}) +endif() + +pkg_search_module(NETTLE nettle) +if(NOT ${NETTLE_FOUND}) + message( FATAL_ERROR "PACKAGE nettle not found: some targets will fail. Run build_oai -I again!") +else() + include_directories(${NETTLE_INCLUDE_DIRS}) +endif() + +message ("NETTLE VERSION_INSTALLED = ${NETTLE_VERSION}") + +string(REGEX REPLACE "([0-9]+).*" "\\1" NETTLE_VERSION_MAJOR ${NETTLE_VERSION}) +string(REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" NETTLE_VERSION_MINOR ${NETTLE_VERSION}) +message ("NETTLE_VERSION_MAJOR = ${NETTLE_VERSION_MAJOR}") +message ("NETTLE_VERSION_MINOR = ${NETTLE_VERSION_MINOR}") + +if ("${NETTLE_VERSION_MAJOR}" STREQUAL "" OR "${NETTLE_VERSION_MINOR}" STREQUAL "") + message( FATAL_ERROR "The nettle version not detected properly. Try to run build_oai -I again" ) +endif() + +add_definitions("-DNETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}") +add_definitions("-DNETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}") + +pkg_search_module(XPM xpm) +if(NOT ${XPM_FOUND}) + message("PACKAGE xpm not found: some targets will fail") +else() + include_directories(${XPM_INCLUDE_DIRS}) +endif() + +# Atlas is required by some packages, but not found in pkg-config +# So, here are some hacks here. Hope this gets fixed in future! +if(EXISTS "/usr/include/atlas/cblas.h" OR EXISTS "/usr/include/cblas.h") + include_directories("/usr/include/atlas") + LINK_DIRECTORIES("/usr/lib/lapack") + LINK_DIRECTORIES("/usr/lib64") + LINK_DIRECTORIES("/usr/lib64/atlas") #Added because atlas libraries in CentOS 7 are here! + + if(EXISTS "/usr/lib64/libblas.so" OR EXISTS "/usr/lib/libblas.so") #Case for CentOS7 + list(APPEND ATLAS_LIBRARIES blas) + + else() # Case for Ubuntu + list(APPEND ATLAS_LIBRARIES cblas) + endif() + + if(EXISTS "/usr/lib/atlas/libtatlas.so" OR EXISTS "/usr/lib64/atlas/libtatlas.so") #Case for CentOS7 + list(APPEND ATLAS_LIBRARIES tatlas) + else() + list(APPEND ATLAS_LIBRARIES atlas) #Case for Ubuntu + endif() + + list(APPEND ATLAS_LIBRARIES lapack) + +# for ubuntu 17.10, directories are different +elseif(EXISTS "/usr/include/x86_64-linux-gnu/cblas.h") + + include_directories("/usr/include/x86_64-linux-gnu") + LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") + list(APPEND ATLAS_LIBRARIES cblas) + list(APPEND ATLAS_LIBRARIES atlas) + list(APPEND ATLAS_LIBRARIES lapack) + +else() + message("No Blas/Atlas libs found, some targets will fail") +endif() + ######################################################### # Base directories, compatible with legacy OAI building # ######################################################### @@ -43,8 +160,6 @@ set (OPENAIR_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) project (OpenAirInterface) - - ############################################## # Base CUDA setting ############################################## @@ -145,6 +260,7 @@ macro(add_list_string_option name val helpstr) endif() endmacro(add_list_string_option) +# this function should produce the same value as the macro MAKE_VERSION defined in the C code (file types.h) function(make_version VERSION_VALUE) math(EXPR RESULT "0") foreach (ARG ${ARGN}) @@ -152,6 +268,22 @@ function(make_version VERSION_VALUE) endforeach() set(${VERSION_VALUE} "${RESULT}" PARENT_SCOPE) endfunction() + +macro(compile_asn1 asn1Source asn1cCmd ResultFlag) + # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make + execute_process(COMMAND ${asn1cCmd} ${asn1Source} RESULT_VARIABLE ret) + + if (NOT ${ret} STREQUAL 0) + message(FATAL_ERROR "${ret}: error") + endif (NOT ${ret} STREQUAL 0) + + add_custom_target ( + ${ResultFlag} ALL + ${asn1cCmd} ${asn1Source} + DEPENDS ${asn1Source} + ) +endmacro(compile_asn1) + #################################################### # compilation flags ############################################# @@ -169,7 +301,12 @@ if (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l") else (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l") if(EXISTS "/proc/cpuinfo") file(STRINGS "/proc/cpuinfo" CPUINFO REGEX flags LIMIT_COUNT 1) +<<<<<<< HEAD if (CPUINFO MATCHES "avx512bw") +======= + message("NOAVX512 is ${NOAVX512}") + if (CPUINFO MATCHES "avx512bw" AND "${NOAVX512}" STREQUAL "False") +>>>>>>> 74ce2cf4be34a6c62ea74116c4b1c45d3cbf1536 set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512 " ) set(COMPILATION_AVX2 "True") else() @@ -180,7 +317,7 @@ else (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l") set(COMPILATION_AVX2 "False") endif() if (CPUINFO MATCHES "sse4_1") - set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1") + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -msse4.1 -mpclmul") endif() if (CPUINFO MATCHES "ssse3") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -mssse3") @@ -202,44 +339,35 @@ Message("C_FLAGS_PROCESSOR is ${C_FLAGS_PROCESSOR}") #endif() # -set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -pipe -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC") # add autotools definitions that were maybe used! -if (CUDA_FOUND) - set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") - set(CUDA_CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D CUDA_FLAG" - ) - set(CUDA_CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11 -D CUDA_FLAG" - ) - - set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D${MKVER} -D CUDA_FLAG" - ) - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11 -D${MKVER} -D CUDA_FLAG" - ) -else (CUDA_FOUND) - set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") - set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D${MKVER}" - ) - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11 -D${MKVER}" - ) + +add_definitions("-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP") + +set(commonOpts "-pipe -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic") + +set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=gnu99 -funroll-loops") +set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} ${commonOpts} -std=c++11") + + + +if (SANITIZE_ADDRESS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-common") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-common") endif () add_definitions("-DASN_DISABLE_OER_SUPPORT") ######################### -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb2 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}") ######################### # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O2") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") +set(debugOpt "-ggdb2 -DMALLOC_CHECK_=3 -fno-delete-null-pointer-checks") +set(CMAKE_C_FLAGS_DEBUG "${debugOpt} -O0") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${debugOpt} -O2") +set(CMAKE_C_FLAGS_RELEASE "-O3") set(GIT_BRANCH "UNKNOWN") set(GIT_COMMIT_HASH "UNKNOWN") @@ -273,7 +401,6 @@ if(GIT_FOUND) ) endif() - # Below is a hard-coded info set (FIRMWARE_VERSION "No svn information") add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"") @@ -294,25 +421,19 @@ add_boolean_option(PDCP_MSG_PRINT False "print PDCP messages to /tmp/pdcp.l add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace -add_boolean_option(TEST_OMG False "???") -add_boolean_option(DEBUG_OMG False "???") add_boolean_option(PRINT_STATS False "This adds the possibility to see the status") add_boolean_option(T_TRACER True "Activate the T tracer, a debugging/monitoring framework" ) add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs") add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace") add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace") -add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering") +add_boolean_option(DEBUG_CONSOLE False "disables stdout/stderr buffering") set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti) add_library(ITTI ${OCP_ITTI}/intertask_interface.cpp ${OPENAIR_DIR}/common/utils/backtrace.c - ${OPENAIR_DIR}/common/utils/memory_pools.c ) add_dependencies(ITTI rrc_flag) - set(ITTI_LIB ITTI) - set(GTPU_need_ITTI ${OPENAIR3_DIR}/GTPV1-U/gtpv1u_eNB.c) - ################################################## # ASN.1 grammar C code generation & dependencies # @@ -328,7 +449,6 @@ set(asn1_generated_dir ${OPENAIR_BIN_DIR}) set(protoc_call "${OPENAIR_CMAKE}/tools/generate_protobuf") set(protobuf_generated_dir ${OPENAIR_BIN_DIR}) - # RRC ###### set (RRC_ASN1_VERSION "Rel15") @@ -338,20 +458,11 @@ set (RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1c/ASN1_files/lte-rrc-15.6. add_definitions(-DLTE_RRC_VERSION=${LTE_RRC_VERSION}) set (RRC_FULL_DIR ${asn1_generated_dir}/RRC_${RRC_ASN1_VERSION}) -# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make -execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${RRC_FULL_DIR}" "${RRC_GRAMMAR}" "LTE_" - RESULT_VARIABLE ret) -if (NOT ${ret} STREQUAL 0) - message(FATAL_ERROR "${ret}: error") -endif (NOT ${ret} STREQUAL 0) -file(GLOB rrc_source ${RRC_FULL_DIR}/*.c) -add_custom_target ( - rrc_flag ALL - ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${RRC_FULL_DIR}" "${RRC_GRAMMAR}" "LTE_" - DEPENDS ${RRC_GRAMMAR} - ) +set(rrc_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "LTE_" " " "${RRC_FULL_DIR}") -set_source_files_properties(${rrc_source} PROPERTIES COMPILE_FLAGS -w) # suppress warnings from generated code +compile_asn1("${RRC_GRAMMAR}" "${rrc_cmd}" rrc_flag) + +file(GLOB rrc_source ${RRC_FULL_DIR}/*.c) add_library(RRC_LIB ${rrc_source} ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg.c ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.c) @@ -361,27 +472,20 @@ include_directories ("${RRC_FULL_DIR}") #NR RRC ####### -set (NR_RRC_ASN1_VERSION "NR_Rel15" ) -make_version(NR_RRC_VERSION 15 6 0) -set (NR_RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-15.6.0.asn1) +set (NR_RRC_ASN1_VERSION "NR_Rel16" ) +make_version(NR_RRC_VERSION 16 4 1) +set (NR_RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1) add_definitions(-DNR_RRC_VERSION=${NR_RRC_VERSION}) set (NR_RRC_FULL_DIR ${asn1_generated_dir}/RRC_${NR_RRC_ASN1_VERSION}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make -execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${NR_RRC_FULL_DIR}" "${NR_RRC_GRAMMAR}" "NR_" "-findirect-choice" - RESULT_VARIABLE ret) -if (NOT ${ret} STREQUAL 0) - message(FATAL_ERROR "${ret}: error") -endif () +set(nr_rrc_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "NR_" "-findirect-choice" "${NR_RRC_FULL_DIR}") + +compile_asn1("${NR_RRC_GRAMMAR}" "${nr_rrc_cmd}" nr_rrc_flag) + file(GLOB nr_rrc_source ${NR_RRC_FULL_DIR}/*.c) file(GLOB nr_rrc_h ${NR_RRC_FULL_DIR}/*.h) -add_custom_target ( - nr_rrc_flag ALL - ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${NR_RRC_FULL_DIR}" "${NR_RRC_GRAMMAR}" "NR_" "-findirect-choice" - DEPENDS ${NR_RRC_GRAMMAR} - ) - -add_library(NR_RRC_LIB ${nr_rrc_h} ${nr_rrc_source} +add_library(NR_RRC_LIB ${nr_rrc_h} ${nr_rrc_source} ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c ) add_dependencies(NR_RRC_LIB nr_rrc_flag) @@ -402,19 +506,11 @@ set(S1AP_ASN_DIR ${S1AP_DIR}/MESSAGES/ASN1/${S1AP_RELEASE}) set(S1AP_C_DIR ${asn1_generated_dir}/S1AP_${S1AP_RELEASE}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make -execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${S1AP_C_DIR}" "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" "S1AP_" -fno-include-deps - RESULT_VARIABLE ret) -if (NOT ${ret} STREQUAL 0) - message(FATAL_ERROR "${ret}: error") -endif (NOT ${ret} STREQUAL 0) +set(s1ap_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "S1AP_" -fno-include-deps "${S1AP_C_DIR}") + +compile_asn1("${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" "${s1ap_cmd}" s1ap_flag) + file(GLOB S1AP_source ${S1AP_C_DIR}/*.c) - -add_custom_target ( - s1ap_flag ALL - ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${S1AP_C_DIR}" "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" "S1AP_" -fno-include-deps - DEPENDS "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" -) - add_library(S1AP_LIB ${S1AP_source} ${S1AP_DIR}/s1ap_common.c @@ -441,6 +537,51 @@ add_library(S1AP_ENB add_dependencies(S1AP_ENB rrc_flag s1ap_flag) +# NGAP +# Same limitation as described in RRC: unknown generated file list +# so we generate it at cmake time +############## +set (NGAP_RELEASE R15) + +set(NGAP_DIR ${OPENAIR3_DIR}/NGAP) +make_version(NGAP_VERSION 15 8 0) +set(NGAP_ASN_FILES "ngap-15.8.0.asn1") + +add_definitions(-DNGAP_VERSION=${NGAP_VERSION}) +set(NGAP_ASN_DIR ${NGAP_DIR}/MESSAGES/ASN1/ASN1_files) +set(NGAP_C_DIR ${asn1_generated_dir}/NGAP_${NGAP_RELEASE}) + +# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make +set (ngap_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "NGAP_" "-fno-include-deps -findirect-choice" "${NGAP_C_DIR}") + +compile_asn1("${NGAP_ASN_DIR}/${NGAP_ASN_FILES}" "${ngap_cmd}" ngap_flag) + +file(GLOB NGAP_source ${NGAP_C_DIR}/*.c) +add_library(NGAP_LIB + ${NGAP_source} +# ${NGAP_DIR}/ngap_common.c + ) +add_dependencies(NGAP_LIB rrc_flag ngap_flag) + +include_directories ("${NGAP_C_DIR}") +include_directories ("${NGAP_DIR}") + +add_library(NGAP_GNB + ${NGAP_DIR}/ngap_gNB.c + ${NGAP_DIR}/ngap_gNB_context_management_procedures.c + ${NGAP_DIR}/ngap_gNB_decoder.c + ${NGAP_DIR}/ngap_gNB_encoder.c + ${NGAP_DIR}/ngap_gNB_handlers.c + ${NGAP_DIR}/ngap_gNB_itti_messaging.c + ${NGAP_DIR}/ngap_gNB_management_procedures.c + ${NGAP_DIR}/ngap_gNB_nas_procedures.c + ${NGAP_DIR}/ngap_gNB_nnsf.c + ${NGAP_DIR}/ngap_gNB_overload.c + ${NGAP_DIR}/ngap_gNB_trace.c + ${NGAP_DIR}/ngap_gNB_ue_context.c + ) +add_dependencies(NGAP_GNB rrc_flag ngap_flag) + #M2AP # Same limitation as described in RRC/S1AP: unknown generated file list # so we generate it at cmake time @@ -469,20 +610,10 @@ set(M2AP_ASN_DIR ${M2AP_DIR}/MESSAGES/ASN1/${M2AP_RELEASE}) set(M2AP_C_DIR ${asn1_generated_dir}/M2AP_${M2AP_RELEASE}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make -execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${M2AP_C_DIR}" "${M2AP_ASN_DIR}/${M2AP_ASN_FILES}" "M2AP_" -fno-include-deps -DEMIT_ASN_DEBUG=1 - RESULT_VARIABLE ret) -if (NOT ${ret} STREQUAL 0) - message(FATAL_ERROR "${ret}: error") -endif (NOT ${ret} STREQUAL 0) +set(m2ap_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "M2AP_" "-fno-include-deps -DEMIT_ASN_DEBUG=1" "${M2AP_C_DIR}") +compile_asn1("${M2AP_ASN_DIR}/${M2AP_ASN_FILES}" "${m2ap_cmd}" m2_flag) file(GLOB M2AP_source ${M2AP_C_DIR}/*.c) - -add_custom_target ( - m2_flag ALL - COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${M2AP_C_DIR}" "${M2AP_ASN_DIR}/${M2AP_ASN_FILES}" "M2AP_" -fno-include-deps - DEPENDS ${M2AP_ASN_DIR}/${M2AP_ASN_FILES} - ) - add_library(M2AP_LIB ${M2AP_source} ${M2AP_DIR}/m2ap_common.c @@ -539,20 +670,12 @@ set(M3AP_ASN_DIR ${M3AP_DIR}/MESSAGES/ASN1/${M3AP_RELEASE}) set(M3AP_C_DIR ${asn1_generated_dir}/M3AP_${M3AP_RELEASE}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make -execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${M3AP_C_DIR}" "${M3AP_ASN_DIR}/${M3AP_ASN_FILES}" "M3AP_" -fno-include-deps - RESULT_VARIABLE ret) -if (NOT ${ret} STREQUAL 0) - message(FATAL_ERROR "${ret}: error") -endif (NOT ${ret} STREQUAL 0) +set(m3_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "M3AP_" -fno-include-deps "${M3AP_C_DIR}") + +compile_asn1("${M3AP_ASN_DIR}/${M3AP_ASN_FILES}" "${m3_cmd}" m3_flag) file(GLOB M3AP_source ${M3AP_C_DIR}/*.c) -add_custom_target ( - m3_flag ALL - COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${M3AP_C_DIR}" "${M3AP_ASN_DIR}/${M3AP_ASN_FILES}" "M3AP_" -fno-include-deps - DEPENDS ${M3AP_ASN_DIR}/${M3AP_ASN_FILES} - ) - add_library(M3AP_LIB ${M3AP_source} ${M3AP_DIR}/m3ap_common.c @@ -593,20 +716,12 @@ add_definitions(-DX2AP_VERSION=${X2AP_VERSION}) set(X2AP_ASN_DIR ${X2AP_DIR}/MESSAGES/ASN1/${X2AP_RELEASE}) set(X2AP_C_DIR ${asn1_generated_dir}/X2AP_${X2AP_RELEASE}) # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make -execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${X2AP_C_DIR}" "${X2AP_ASN_DIR}/${X2AP_ASN_FILES}" "X2AP_" -fno-include-deps - RESULT_VARIABLE ret) -if (NOT ${ret} STREQUAL 0) - message(FATAL_ERROR "${ret}: error") -endif (NOT ${ret} STREQUAL 0) +set(x2_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "X2AP_" -fno-include-deps "${X2AP_C_DIR}") + +compile_asn1("${X2AP_ASN_DIR}/${X2AP_ASN_FILES}" "${x2_cmd}" x2_flag) file(GLOB X2AP_source ${X2AP_C_DIR}/*.c) -add_custom_target ( - x2_flag ALL - COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${X2AP_C_DIR}" "${X2AP_ASN_DIR}/${X2AP_ASN_FILES}" "X2AP_" -fno-include-deps - DEPENDS ${X2AP_ASN_DIR}/${X2AP_ASN_FILES} - ) - add_library(X2AP_LIB ${X2AP_source} ${X2AP_DIR}/x2ap_common.c @@ -627,17 +742,18 @@ add_library(X2AP_ENB ${X2AP_DIR}/x2ap_ids.c ${X2AP_DIR}/x2ap_timers.c ) -add_dependencies(X2AP_ENB rrc_flag x2_flag) +add_dependencies(X2AP_ENB X2AP_LIB rrc_flag x2_flag) # F1AP ############## -add_list1_option(F1AP_RELEASE R15 "F1AP ASN.1 grammar version" R15) +set (F1AP_RELEASE R16) +add_list1_option(F1AP_RELEASE R16 "F1AP ASN.1 grammar version" R16) set(F1AP_DIR ${OPENAIR2_DIR}/F1AP) -if (${F1AP_RELEASE} STREQUAL "R15") - make_version(F1AP_VERSION 15 2 1) - set (ASN1RELDIR R15.2.1) -endif(${F1AP_RELEASE} STREQUAL "R15") +if (${F1AP_RELEASE} STREQUAL "R16") + make_version(F1AP_VERSION 16 3 1) + set (ASN1RELDIR R16.3.1) +endif(${F1AP_RELEASE} STREQUAL "R16") add_definitions(-DF1AP_VERSION=${F1AP_VERSION}) set(F1AP_ASN_DIR ${F1AP_DIR}/MESSAGES/ASN1/${ASN1RELDIR}) set(F1AP_ASN_FILES @@ -650,59 +766,49 @@ set(F1AP_ASN_FILES ) set(F1AP_ASN_GENERATED_C_DIR ${asn1_generated_dir}/F1AP_${ASN1RELDIR}) -message("calling ASN1C_PREFIX=F1AP_ asn1c -gen-PER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${F1AP_ASN_GENERATED_C_DIR} ${F1AP_ASN_FILES}") -execute_process(COMMAND mkdir -p ${F1AP_ASN_GENERATED_C_DIR} - COMMAND env "ASN1C_PREFIX=F1AP_" asn1c -gen-PER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${F1AP_ASN_GENERATED_C_DIR} ${F1AP_ASN_FILES} - RESULT_VARIABLE ret - OUTPUT_QUIET - ERROR_QUIET) -if (NOT ${ret} STREQUAL 0) - message(FATAL_ERROR "asn1c: error") -endif (NOT ${ret} STREQUAL 0) +set(f1_cmd ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "F1AP_" "-findirect-choice -fno-include-deps" "${F1AP_ASN_GENERATED_C_DIR}") + +compile_asn1("${F1AP_ASN_FILES}" "${f1_cmd}" f1_flag) file(GLOB F1AP_ASN_GENERATED_C_FILES ${F1AP_ASN_GENERATED_C_DIR}/*.c) add_library(F1AP_LIB ${F1AP_ASN_GENERATED_C_FILES} -) + ) +add_dependencies (F1AP_LIB f1_flag) include_directories ("${F1AP_ASN_GENERATED_C_DIR}") include_directories ("${F1AP_DIR}") file(GLOB F1AP_C_FILES ${F1AP_DIR}/*.c) -add_library(F1AP - ${F1AP_C_FILES} -) - +add_library(F1AP ${F1AP_C_FILES} ) # Hardware dependant options ################################### -add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4") +add_list1_option(NB_ANTENNAS_RX "4" "Number of antennas in reception" "1" "2" "4") add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4") add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "OAI_USRP" "OAI_BLADERF" "OAI_LMSSDR" "OAI_SIMU") - - add_list2_option(TRANSP_PRO "None" "Transport protocol type" "None" "ETHERNET") #NOKIA config enhancement set (CONFIG_ROOTDIR - ${OPENAIR_DIR}/common/config - ) + ${OPENAIR_DIR}/common/config + ) set (CONFIG_SOURCES - ${CONFIG_ROOTDIR}/config_load_configmodule.c - ${CONFIG_ROOTDIR}/config_userapi.c - ${CONFIG_ROOTDIR}/config_cmdline.c - ) + ${CONFIG_ROOTDIR}/config_load_configmodule.c + ${CONFIG_ROOTDIR}/config_userapi.c + ${CONFIG_ROOTDIR}/config_cmdline.c + ) set (CONFIG_LIBCONFIG_SOURCES - ${CONFIG_ROOTDIR}/libconfig/config_libconfig.c - ) + ${CONFIG_ROOTDIR}/libconfig/config_libconfig.c + ) add_library(CONFIG_LIB ${CONFIG_SOURCES}) add_library(params_libconfig MODULE ${CONFIG_LIBCONFIG_SOURCES} ) target_link_libraries(params_libconfig config) # shared library loader set (SHLIB_LOADER_SOURCES - ${OPENAIR_DIR}/common/utils/load_module_shlib.c + ${OPENAIR_DIR}/common/utils/load_module_shlib.c ) # include RF devices / transport protocols library modules ###################################################################### @@ -730,6 +836,7 @@ add_library(oai_lmssdrdevif MODULE ${HWLIB_LMSSDR_SOURCE} ) target_include_directories(oai_lmssdrdevif PRIVATE /usr/local/include/lime) target_link_libraries(oai_lmssdrdevif LimeSuite ) + include_directories("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/") set(TPLIB_ETHERNET_SOURCE ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -738,11 +845,20 @@ set(TPLIB_ETHERNET_SOURCE ) add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} ) +include_directories("${OPENAIR_TARGETS}/ARCH/AW2SORI/") +link_directories("/usr/local/lib") +set(HWLIB_AW2SORI_SOURCE + ${OPENAIR_TARGETS}/ARCH/AW2SORI/oaiori.c + ) +add_library(aw2sori_transpro MODULE ${HWLIB_AW2SORI_SOURCE}) +target_compile_options(aw2sori_transpro PRIVATE -shared -fPIC -msse4 -g -ggdb -DLITE_COMPILATION) +target_link_libraries(aw2sori_transpro libori.so) + include_directories("${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/") set(option_HWIRISLIB_lib "-l SoapySDR") set(HWLIB_IRIS_SOURCE - ${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp - ) + ${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp + ) add_library(oai_irisdevif MODULE ${HWLIB_IRIS_SOURCE}) target_include_directories(oai_irisdevif PRIVATE /usr/local/lib/SoapySDR/modules0.7/) target_link_libraries(oai_irisdevif SoapySDR) @@ -768,6 +884,45 @@ set(HWLIB_TCP_BRIDGE_OAI_SOURCE add_library(tcp_bridge_oai MODULE ${HWLIB_TCP_BRIDGE_OAI_SOURCE} ) set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") +# Benetel 4G library +###################################################################### + + +include_directories ("/usr/include/dpdk") + +set(HWLIB_BENETEL_4G_SOURCE + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/benetel.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/shared_buffers.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/low.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/low_dpdk.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/dpdk_driver.c + ) +add_library(benetel_4g MODULE ${HWLIB_BENETEL_4G_SOURCE} ) + +set_target_properties(benetel_4g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") + +SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") +TARGET_LINK_LIBRARIES(benetel_4g ${DPDK_LIBS}) +TARGET_LINK_LIBRARIES(benetel_4g pthread dl rt m numa) + +# Benetel 5G library +###################################################################### + +set(HWLIB_BENETEL_5G_SOURCE + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/benetel.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/shared_buffers.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/low.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/low_dpdk.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/dpdk_driver.c + ) +add_library(benetel_5g MODULE ${HWLIB_BENETEL_5G_SOURCE} ) + +set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") + +SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") +TARGET_LINK_LIBRARIES(benetel_5g ${DPDK_LIBS}) +TARGET_LINK_LIBRARIES(benetel_5g pthread dl rt m numa) + ########################################################## include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON") @@ -779,10 +934,8 @@ Message("CPU_Affinity flag is ${CPU_AFFINITY}") # ???!!! TO BE DOCUMENTED OPTIONS !!!??? ############################################################## -add_boolean_option(NO_RRM True "DO WE HAVE A RADIO RESSOURCE MANAGER: NO") - add_boolean_option(OAI_NW_DRIVER_TYPE_ETHERNET False "????") -add_boolean_option(DEADLINE_SCHEDULER True "Use the Linux scheduler SCHED_DEADLINE: kernel >= 3.14") +add_boolean_option(DEADLINE_SCHEDULER False "Use the Linux scheduler SCHED_DEADLINE: kernel >= 3.14") add_boolean_option(CPU_AFFINITY False "Enable CPU Affinity of threads (only valid without deadline scheduler). It is enabled only with >2 CPUs") add_boolean_option(NAS_NETLINK False "useless ??? Must be True to compile nasmesh driver without rtai ????") add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????") @@ -795,6 +948,7 @@ add_boolean_option(UE_EXPANSION False "enable UE_EXPANSION w add_boolean_option(PHY_TX_THREAD False "enable UE_EXPANSION with max 256 UE") add_boolean_option(PRE_SCD_THREAD False "enable UE_EXPANSION with max 256 UE") add_boolean_option(UESIM_EXPANSION False "enable UESIM_EXPANSION with max 256 UE") +add_boolean_option(ITTI_SIM False "enable itti simulator") ######################## # Include order @@ -804,12 +958,11 @@ add_boolean_option(ENB_MODE True "Swap the include directories between openair2 ########################## # SCHEDULING/REAL-TIME/PERF options ########################## -add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME True "Add data in vcd traces: disable it if perf issues") -add_boolean_option(ENABLE_VCD True "always true now, time measurements of proc calls and var displays") -add_boolean_option(ENABLE_VCD_FIFO True "time measurements of proc calls and var displays sent to FIFO (one more thread)") +add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME False "Add data in vcd traces: disable it if perf issues") +add_boolean_option(ENABLE_VCD False "always true now, time measurements of proc calls and var displays") +add_boolean_option(ENABLE_VCD_FIFO False "time measurements of proc calls and var displays sent to FIFO (one more thread)") add_boolean_option(LINUX False "used in weird memcpy() in pdcp.c ???") add_boolean_option(LINUX_LIST False "used only in lists.c: either use OAI implementation of lists or Linux one (should be True, but it is False") -add_boolean_option(OPENAIR_LTE True "Seems legacy: keep it to true") ########################## # PHY options @@ -818,10 +971,6 @@ add_boolean_option(DRIVER2013 True "only relevant for EXMIMO") add_boolean_option(EXMIMO_IOT True "????") add_boolean_option(LOCALIZATION False "???") add_integer_option(MAX_NUM_CCs 1 "????") -add_boolean_option(MU_RECEIVER False "????") -add_boolean_option(PHYSIM False "for L1 simulators (dlsim, ulsim, ...)") -add_boolean_option(PHY_CONTEXT True "not clear: must remain False for dlsim") -add_boolean_option(PHY_EMUL False "not clear: must remain False for dlsim") add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator") add_boolean_option(DEBUG_PHY False "Enable PHY layer debugging options") add_boolean_option(DEBUG_PHY_PROC False "Enable debugging of PHY layer procedures") @@ -844,7 +993,6 @@ add_boolean_option(JUMBO_FRAME True "ENABLE LARGE SDU in ACCESS STR ########################## # RLC LAYER OPTIONS ########################## -add_boolean_option(OPENAIR2 True "Access Stratum layer 2 built in executable") add_boolean_option(TRACE_RLC_PAYLOAD False "Fatal assert in this case") add_boolean_option(RLC_STOP_ON_LOST_PDU False "Fatal assert in this case") @@ -855,7 +1003,6 @@ add_boolean_option(TRACE_RLC_AM_HOLE False "TRACE for RLC AM, TO BE CHANGE add_boolean_option(TRACE_RLC_AM_PDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") add_boolean_option(TRACE_RLC_AM_RESEGMENT False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") add_boolean_option(TRACE_RLC_AM_RX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") -add_boolean_option(TRACE_RLC_AM_RX_DECODE False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") add_boolean_option(TRACE_RLC_AM_TX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") add_boolean_option(TRACE_RLC_AM_TX_STATUS False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") add_boolean_option(TRACE_RLC_AM_STATUS_CREATION False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG") @@ -872,8 +1019,6 @@ add_boolean_option(TRACE_RLC_UM_TX_STATUS False "TRACE for RLC UM, TO BE CHANGE ########################## # PDCP LAYER OPTIONS ########################## -#add_boolean_option(PDCP_USE_NETLINK False "For eNB, PDCP communicate with a NETLINK socket if connected to network driver, else could use a RT-FIFO") -#add_boolean_option(PDCP_USE_NETLINK_QUEUES False "When PDCP_USE_NETLINK is true, incoming IP packets are stored in queues") #add_boolean_option(LINK_ENB_PDCP_TO_IP_DRIVER False "For eNB, PDCP communicate with a IP driver") #add_boolean_option(LINK_ENB_PDCP_TO_GTPV1U True "For eNB, PDCP communicate with GTP-U protocol (eNB<->S-GW)") @@ -1064,9 +1209,22 @@ add_library(FLEXRAN_AGENT ${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c + ${OPENAIR2_DIR}/ENB_APP/flexran_agent_app.c ) add_dependencies(FLEXRAN_AGENT rrc_flag) set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT) +add_library(flapp_sample SHARED + ${OPENAIR2_DIR}/ENB_APP/flexran_apps/sample.c +) +set_target_properties(flapp_sample PROPERTIES C_VISIBILITY_PRESET hidden) +add_library(flapp_imsi SHARED + ${OPENAIR2_DIR}/ENB_APP/flexran_apps/imsi.c +) +set_target_properties(flapp_imsi PROPERTIES C_VISIBILITY_PRESET hidden) +add_custom_target(flapp_all DEPENDS + flapp_sample + flapp_imsi +) #include_directories(${OPENAIR2_DIR}/ENB_APP) set(PROTOBUF_LIB "protobuf-c") @@ -1150,42 +1308,42 @@ target_link_libraries (msc LFDS) include_directories(${OPENAIR_DIR}/common/utils/msc) set(UTIL_SRC -# ${OPENAIR2_DIR}/UTIL/CLI/cli.c -# ${OPENAIR2_DIR}/UTIL/CLI/cli_cmd.c -# ${OPENAIR2_DIR}/UTIL/CLI/cli_server.c + # ${OPENAIR2_DIR}/UTIL/CLI/cli.c + # ${OPENAIR2_DIR}/UTIL/CLI/cli_cmd.c + # ${OPENAIR2_DIR}/UTIL/CLI/cli_server.c ${OPENAIR2_DIR}/UTIL/FIFO/pad_list.c ${OPENAIR2_DIR}/UTIL/LISTS/list.c ${OPENAIR2_DIR}/UTIL/LISTS/list2.c ${OPENAIR_DIR}/common/utils/LOG/log.c ${OPENAIR_DIR}/common/utils/LOG/vcd_signal_dumper.c ${OPENAIR2_DIR}/UTIL/MATH/oml.c -# ${OPENAIR2_DIR}/UTIL/MEM/mem_block.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_create_dir.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_detect_file.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_generate_report.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_filename.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_XML.c -# ${OPENAIR2_DIR}/UTIL/OCG/OCG_save_XML.c -# ${OPENAIR2_DIR}/UTIL/OMG/common.c -# ${OPENAIR2_DIR}/UTIL/OMG/grid.c -# ${OPENAIR2_DIR}/UTIL/OMG/job.c -# ${OPENAIR2_DIR}/UTIL/OMG/mobility_parser.c -# ${OPENAIR2_DIR}/UTIL/OMG/omg.c -# ${OPENAIR2_DIR}/UTIL/OMG/omg_hashtable.c -# ${OPENAIR2_DIR}/UTIL/OMG/rwalk.c -# ${OPENAIR2_DIR}/UTIL/OMG/rwp.c -# ${OPENAIR2_DIR}/UTIL/OMG/static.c -# ${OPENAIR2_DIR}/UTIL/OMG/steadystaterwp.c -# ${OPENAIR2_DIR}/UTIL/OMG/trace.c -# ${OPENAIR2_DIR}/UTIL/OMG/trace_hashtable.c + # ${OPENAIR2_DIR}/UTIL/MEM/mem_block.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_create_dir.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_detect_file.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_generate_report.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_filename.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_parse_XML.c + # ${OPENAIR2_DIR}/UTIL/OCG/OCG_save_XML.c + # ${OPENAIR2_DIR}/UTIL/OMG/common.c + # ${OPENAIR2_DIR}/UTIL/OMG/grid.c + # ${OPENAIR2_DIR}/UTIL/OMG/job.c + # ${OPENAIR2_DIR}/UTIL/OMG/mobility_parser.c + # ${OPENAIR2_DIR}/UTIL/OMG/omg.c + # ${OPENAIR2_DIR}/UTIL/OMG/omg_hashtable.c + # ${OPENAIR2_DIR}/UTIL/OMG/rwalk.c + # ${OPENAIR2_DIR}/UTIL/OMG/rwp.c + # ${OPENAIR2_DIR}/UTIL/OMG/static.c + # ${OPENAIR2_DIR}/UTIL/OMG/steadystaterwp.c + # ${OPENAIR2_DIR}/UTIL/OMG/trace.c + # ${OPENAIR2_DIR}/UTIL/OMG/trace_hashtable.c ${OPENAIR2_DIR}/UTIL/OPT/probe.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_tx.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_kpi.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_models.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_form.c -# ${OPENAIR2_DIR}/UTIL/OTG/otg_rx.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_tx.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_kpi.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_models.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_form.c + # ${OPENAIR2_DIR}/UTIL/OTG/otg_rx.c ) add_library(UTIL ${UTIL_SRC}) add_dependencies(UTIL rrc_flag) @@ -1207,6 +1365,7 @@ set(SECU_OSA_SRC ${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c ) add_library(SECU_OSA ${SECU_OSA_SRC}) +target_link_libraries(SECU_OSA ${NETTLE_LIBRARIES}) set(SECU_CN_SRC ${OPENAIR3_DIR}/SECU/kdf.c @@ -1220,6 +1379,8 @@ set(SECU_CN_SRC ) add_library(SECU_CN ${SECU_CN_SRC}) +target_link_libraries(SECU_CN ${NETTLE_LIBRARIES}) + # Physical Channel Procedures Scheduling ################################" set(SCHED_SRC @@ -1260,11 +1421,10 @@ add_dependencies(SCHED_UE_LIB rrc_flag) set(SCHED_SRC_NR_UE ${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c - ${OPENAIR1_DIR}/SCHED_NR_UE/fapi_nr_ue_l1.c + ${OPENAIR1_DIR}/SCHED_NR_UE/fapi_nr_ue_l1.c ${OPENAIR1_DIR}/SCHED_NR_UE/phy_frame_config_nr_ue.c ${OPENAIR1_DIR}/SCHED_NR_UE/harq_nr.c ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_uci_ue_nr.c - ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_power_control_ue_nr.c ) add_library(SCHED_NR_UE_LIB ${SCHED_SRC_NR_UE}) @@ -1273,7 +1433,7 @@ add_library(SCHED_NR_UE_LIB ${SCHED_SRC_NR_UE}) ################################# set(NFAPI_COMMON_SRC ${NFAPI_DIR}/common/src/debug.c -) + ) add_library(NFAPI_COMMON_LIB ${NFAPI_COMMON_SRC}) include_directories(${NFAPI_DIR}/common/public_inc) @@ -1372,6 +1532,16 @@ set(PHY_LDPC_OPTIM8SEGMULTI_SRC ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c ) +set(PHY_LDPC_CUDA_SRC + ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu + ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c +) + +set(PHY_LDPC_CL_SRC + ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c + ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c +) + set(PHY_NR_CODINGIF ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_load.c; ) @@ -1379,8 +1549,18 @@ set(PHY_NR_CODINGIF add_library(ldpc_orig MODULE ${PHY_LDPC_ORIG_SRC} ) add_library(ldpc_optim MODULE ${PHY_LDPC_OPTIM_SRC} ) add_library(ldpc_optim8seg MODULE ${PHY_LDPC_OPTIM8SEG_SRC} ) +add_library(ldpc_cl MODULE ${PHY_LDPC_CL_SRC} ) +target_link_libraries(ldpc_cl OpenCL) + +if (CUDA_FOUND) + cuda_add_library(ldpc_cuda MODULE ${PHY_LDPC_CUDA_SRC} ) + set_target_properties(ldpc_cuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON) +# CUDA_ADD_CUFFT_TO_TARGET(ldpc_cuda) +endif (CUDA_FOUND) + add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} ) + add_library(coding MODULE ${PHY_TURBOSRC} ) add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ) @@ -1401,7 +1581,6 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach_common.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pucch_common.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_scrambling.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_gold_generic.c ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/srs_modulation.c ${OPENAIR1_DIR}/PHY/MODULATION/ofdm_mod.c ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_time.c @@ -1424,7 +1603,6 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c ${OPENAIR1_DIR}/PHY/INIT/init_top.c ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c - ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c ${OPENAIR1_DIR}/PHY/TOOLS/dfts_load.c ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c @@ -1527,7 +1705,6 @@ set(PHY_SRC_UE set(PHY_NR_SRC_COMMON ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c - ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci_tools_common.c ) set(PHY_NR_SRC @@ -1549,7 +1726,9 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c + ${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_csi_rs.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c @@ -1557,7 +1736,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/filt16a_32.c ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c - ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c + ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_measurements_gNB.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c #${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c @@ -1573,7 +1752,7 @@ set(PHY_SRC_UE ${PHY_POLARSRC} ${PHY_SMALLBLOCKSRC} ${PHY_NR_CODINGIF} - ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_uci_tools_common.c ) set(PHY_NR_UE_SRC @@ -1584,6 +1763,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c + ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -1752,8 +1932,22 @@ set(NR_RLC_SRC ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_ue_manager.c ) +set(NR_PDCP_SRC + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_sdu.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c + ) + +set(NR_SDAP_SRC + ${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap_gnb.c + ) + set(L2_SRC - ${OPENAIR2_DIR}/LAYER2/openair2_proc.c ${PDCP_DIR}/pdcp.c ${PDCP_DIR}/pdcp_fifo.c ${PDCP_DIR}/pdcp_sequence_manager.c @@ -1761,7 +1955,23 @@ set(L2_SRC ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c + ${OPENAIR2_DIR}/LAYER2/openair2_proc.c # ${RRC_DIR}/rrc_UE.c + ${RRC_DIR}/rrc_eNB.c + ${RRC_DIR}/rrc_eNB_endc.c + ${RRC_DIR}/rrc_eNB_S1AP.c + ${RRC_DIR}/rrc_eNB_M2AP.c + ${RRC_DIR}/rrc_eNB_UE_context.c + ${NR_RRC_DIR}/rrc_gNB_UE_context.c + ${RRC_DIR}/rrc_common.c + ${RRC_DIR}/L2_interface.c + ${RRC_DIR}/L2_interface_common.c + ${RRC_DIR}/L2_interface_ue.c + ) + +set(L2_RRC_SRC + ${OPENAIR2_DIR}/LAYER2/openair2_proc.c + # ${RRC_DIR}/rrc_UE.c ${RRC_DIR}/rrc_eNB.c ${RRC_DIR}/rrc_eNB_endc.c ${RRC_DIR}/rrc_eNB_S1AP.c @@ -1779,6 +1989,8 @@ set(L2_LTE_SRC set(L2_NR_SRC ${NR_RLC_SRC} + ${NR_PDCP_SRC} + ${NR_SDAP_SRC} ${NR_RRC_DIR}/rrc_gNB.c ${NR_RRC_DIR}/nr_rrc_common.c ${NR_RRC_DIR}/L2_nr_interface.c @@ -1787,6 +1999,7 @@ set(L2_NR_SRC ${NR_RRC_DIR}/rrc_gNB_internode.c ${NR_RRC_DIR}/rrc_gNB_reconfig.c ${NR_RRC_DIR}/rrc_gNB_UE_context.c + ${NR_RRC_DIR}/rrc_gNB_NGAP.c ) set(L2_SRC_UE @@ -1802,20 +2015,18 @@ set(L2_SRC_UE ${RRC_DIR}/L2_interface_common.c ${RRC_DIR}/L2_interface_ue.c ) - -set(LTE_NR_L2_SRC_UE - ${PDCP_DIR}/pdcp.c - ${PDCP_DIR}/pdcp_fifo.c - ${PDCP_DIR}/pdcp_sequence_manager.c - ${PDCP_DIR}/pdcp_primitives.c - ${PDCP_DIR}/pdcp_util.c - ${PDCP_DIR}/pdcp_security.c - ${PDCP_DIR}/pdcp_netlink.c - ${RLC_V2} + +set(L2_RRC_SRC_UE + ${RRC_DIR}/rrc_UE.c + ${RRC_DIR}/rrc_common.c + ${RRC_DIR}/L2_interface_common.c + ${RRC_DIR}/L2_interface_ue.c ) set(NR_L2_SRC_UE ${NR_RLC_SRC} + ${NR_PDCP_SRC} + ${NR_SDAP_SRC} ${NR_UE_RRC_DIR}/L2_interface_ue.c ${NR_UE_RRC_DIR}/main_ue.c ${NR_UE_RRC_DIR}/rrc_UE.c @@ -1856,6 +2067,7 @@ set (MAC_NR_SRC ${NR_GNB_MAC_DIR}/gNB_scheduler_ulsch.c ${NR_GNB_MAC_DIR}/gNB_scheduler_primitives.c ${NR_GNB_MAC_DIR}/gNB_scheduler_phytest.c + ${NR_GNB_MAC_DIR}/gNB_scheduler_uci.c ${NR_GNB_MAC_DIR}/gNB_scheduler_RA.c ) @@ -1869,17 +2081,17 @@ set (MAC_SRC_UE ${MAC_DIR}/rar_tools_ue.c ${MAC_DIR}/config_ue.c ) - + set (MAC_NR_SRC_UE ${NR_UE_PHY_INTERFACE_DIR}/NR_IF_Module.c ${NR_UE_MAC_DIR}/config_ue.c ${NR_UE_MAC_DIR}/mac_vars.c ${NR_UE_MAC_DIR}/main_ue_nr.c ${NR_UE_MAC_DIR}/nr_ue_procedures.c + ${NR_UE_MAC_DIR}/nr_ue_scheduler.c ${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c ${NR_UE_MAC_DIR}/nr_l1_helpers.c ${NR_UE_MAC_DIR}/nr_ra_procedures.c - ${NR_UE_MAC_DIR}/rar_tools_nrUE.c ) set (ENB_APP_SRC @@ -1899,7 +2111,21 @@ set (MCE_APP_SRC ${OPENAIR2_DIR}/MCE_APP/mce_app.c ${OPENAIR2_DIR}/MCE_APP/mce_config.c ) +set (MISC_NFAPI_LTE + ${OPENAIR1_DIR}/SCHED/nfapi_lte_dummy.c + ) +add_library(MISC_NFAPI_LTE_LIB + ${MISC_NFAPI_LTE} + ) + +set (MISC_NFAPI_NR + ${OPENAIR1_DIR}/SCHED/nfapi_nr_dummy.c + ) + +add_library(MISC_NFAPI_NR_LIB + ${MISC_NFAPI_NR} + ) add_library(L2 ${L2_SRC} ${MAC_SRC} @@ -1925,6 +2151,16 @@ add_library(L2_NR ${MAC_NR_SRC} ${GNB_APP_SRC} ) +target_compile_definitions(L2_NR PUBLIC NEW_GTPU) + +add_library(L2_LTE_NR + ${L2_RRC_SRC} + ${MAC_SRC} + ${ENB_APP_SRC} + ${MCE_APP_SRC} +) +target_compile_definitions(L2_LTE_NR PUBLIC NEW_GTPU) + add_dependencies(L2_NR rrc_flag nr_rrc_flag s1ap_flag x2_flag) add_library(L2_UE @@ -1932,6 +2168,11 @@ add_library(L2_UE ${MAC_SRC_UE} ) +add_library(L2_UE_LTE_NR + ${L2_RRC_SRC_UE} + ${MAC_SRC_UE} +) + if (NOT ${NOS1}) target_compile_definitions(L2_UE PUBLIC -DPDCP_USE_NETLINK) endif() @@ -1940,7 +2181,7 @@ add_dependencies(L2_UE rrc_flag s1ap_flag x2_flag) add_library( NR_L2_UE ${NR_L2_SRC_UE} ${MAC_NR_SRC_UE} ) -add_library( MAC_NR_COMMON ${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c ${OPENAIR2_DIR}/LAYER2/NR_MAC_gNB/nr_compute_tbs_common.c) +add_library( MAC_NR_COMMON ${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c ${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c) include_directories("${OPENAIR2_DIR}/NR_UE_PHY_INTERFACE") include_directories("${OPENAIR2_DIR}/LAYER2") @@ -1960,27 +2201,28 @@ add_library(CN_UTILS ) set(GTPV1U_DIR ${OPENAIR3_DIR}/GTPV1-U) -set (GTPV1U_SRC + +add_library (GTPV1U_OCP + ${NR_RRC_DIR}/rrc_gNB_GTPV1U.c ${RRC_DIR}/rrc_eNB_GTPV1U.c - ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTunnelEndPoint.c - ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTrxn.c - ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uMsg.c - ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1u.c - ${GTPV1U_DIR}/gtpv1u_teid_pool.c -) -add_library(GTPV1U ${GTPV1U_SRC}) -add_dependencies(GTPV1U rrc_flag) + ${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp + ) +target_compile_definitions(GTPV1U_OCP PUBLIC NEW_GTPU) +add_dependencies(GTPV1U_OCP rrc_flag) +include_directories(${OPENAIR3_DIR}/ocp-gtp) #NR case set (NR_GTPV1U_SRC ${NR_RRC_DIR}/rrc_gNB_GTPV1U.c ${RRC_DIR}/rrc_eNB_GTPV1U.c + ${GTPV1U_DIR}/gtpv1u_eNB.c + ${GTPV1U_DIR}/gtpv1u_gNB.c ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTunnelEndPoint.c ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTrxn.c ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uMsg.c ${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1u.c ${GTPV1U_DIR}/gtpv1u_teid_pool.c -) + ) add_library(NR_GTPV1U ${NR_GTPV1U_SRC}) add_dependencies(NR_GTPV1U rrc_flag) @@ -2002,7 +2244,6 @@ add_dependencies(SCTP_CLIENT rrc_flag) add_library(UDP ${OPENAIR3_DIR}/UDP/udp_eNB_task.c) add_dependencies(UDP rrc_flag) - set(NAS_SRC ${OPENAIR3_DIR}/NAS/) set(libnas_api_OBJS ${NAS_SRC}COMMON/API/NETWORK/as_message.c @@ -2161,118 +2402,172 @@ set (libnas_utils_OBJS ${NAS_SRC}COMMON/UTIL/OctetString.c ) -if(NAS_UE) - set(libnas_ue_api_OBJS - ${NAS_SRC}UE/API/USER/at_command.c - ${NAS_SRC}UE/API/USER/at_error.c - ${NAS_SRC}UE/API/USER/at_response.c - ${NAS_SRC}UE/API/USER/user_api.c - ${NAS_SRC}UE/API/USER/user_indication.c - ${NAS_SRC}UE/API/USIM/aka_functions.c - ${NAS_SRC}UE/API/USIM/usim_api.c +set(libnas_ue_api_OBJS + ${NAS_SRC}UE/API/USER/at_command.c + ${NAS_SRC}UE/API/USER/at_error.c + ${NAS_SRC}UE/API/USER/at_response.c + ${NAS_SRC}UE/API/USER/user_api.c + ${NAS_SRC}UE/API/USER/user_indication.c + ${NAS_SRC}UE/API/USIM/aka_functions.c + ${NAS_SRC}UE/API/USIM/usim_api.c ) - set(libnas_ue_emm_OBJS - ${NAS_SRC}UE/EMM/Attach.c - ${NAS_SRC}UE/EMM/Authentication.c - ${NAS_SRC}UE/EMM/Detach.c - ${NAS_SRC}UE/EMM/emm_main.c - ${NAS_SRC}UE/EMM/EmmStatusHdl.c - ${NAS_SRC}UE/EMM/Identification.c - ${NAS_SRC}UE/EMM/IdleMode.c - ${NAS_SRC}UE/EMM/LowerLayer.c - ${NAS_SRC}UE/EMM/SecurityModeControl.c - ${NAS_SRC}UE/EMM/ServiceRequestHdl.c - ${NAS_SRC}UE/EMM/TrackingAreaUpdate.c +set(libnas_ue_emm_OBJS + ${NAS_SRC}UE/EMM/Attach.c + ${NAS_SRC}UE/EMM/Authentication.c + ${NAS_SRC}UE/EMM/Detach.c + ${NAS_SRC}UE/EMM/emm_main.c + ${NAS_SRC}UE/EMM/EmmStatusHdl.c + ${NAS_SRC}UE/EMM/Identification.c + ${NAS_SRC}UE/EMM/IdleMode.c + ${NAS_SRC}UE/EMM/LowerLayer.c + ${NAS_SRC}UE/EMM/SecurityModeControl.c + ${NAS_SRC}UE/EMM/ServiceRequestHdl.c + ${NAS_SRC}UE/EMM/TrackingAreaUpdate.c ) - set(libnas_ue_emm_sap_OBJS - ${NAS_SRC}UE/EMM/SAP/emm_as.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttachNeeded.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregistered.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredLimitedService.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoImsi.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNormalService.c - ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredPlmnSearch.c - ${NAS_SRC}UE/EMM/SAP/emm_esm.c - ${NAS_SRC}UE/EMM/SAP/emm_fsm.c - ${NAS_SRC}UE/EMM/SAP/EmmNull.c - ${NAS_SRC}UE/EMM/SAP/emm_recv.c - ${NAS_SRC}UE/EMM/SAP/emm_reg.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c - ${NAS_SRC}UE/EMM/SAP/EmmRegistered.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredLimitedService.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNoCellAvailable.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNormalService.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredPlmnSearch.c - ${NAS_SRC}UE/EMM/SAP/EmmRegisteredUpdateNeeded.c - ${NAS_SRC}UE/EMM/SAP/emm_sap.c - ${NAS_SRC}UE/EMM/SAP/emm_send.c - ${NAS_SRC}UE/EMM/SAP/EmmServiceRequestInitiated.c - ${NAS_SRC}UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c +set(libnas_ue_emm_sap_OBJS + ${NAS_SRC}UE/EMM/SAP/emm_as.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttachNeeded.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregistered.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredLimitedService.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoCellAvailable.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNoImsi.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredNormalService.c + ${NAS_SRC}UE/EMM/SAP/EmmDeregisteredPlmnSearch.c + ${NAS_SRC}UE/EMM/SAP/emm_esm.c + ${NAS_SRC}UE/EMM/SAP/emm_fsm.c + ${NAS_SRC}UE/EMM/SAP/EmmNull.c + ${NAS_SRC}UE/EMM/SAP/emm_recv.c + ${NAS_SRC}UE/EMM/SAP/emm_reg.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredAttemptingToUpdate.c + ${NAS_SRC}UE/EMM/SAP/EmmRegistered.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredImsiDetachInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredLimitedService.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNoCellAvailable.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredNormalService.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredPlmnSearch.c + ${NAS_SRC}UE/EMM/SAP/EmmRegisteredUpdateNeeded.c + ${NAS_SRC}UE/EMM/SAP/emm_sap.c + ${NAS_SRC}UE/EMM/SAP/emm_send.c + ${NAS_SRC}UE/EMM/SAP/EmmServiceRequestInitiated.c + ${NAS_SRC}UE/EMM/SAP/EmmTrackingAreaUpdatingInitiated.c ) - set (libnas_ue_esm_OBJS - ${NAS_SRC}UE/ESM/DedicatedEpsBearerContextActivation.c - ${NAS_SRC}UE/ESM/DefaultEpsBearerContextActivation.c - ${NAS_SRC}UE/ESM/EpsBearerContextDeactivation.c - ${NAS_SRC}UE/ESM/esm_ebr.c - ${NAS_SRC}UE/ESM/esm_ebr_context.c - ${NAS_SRC}UE/ESM/esm_ip.c - ${NAS_SRC}UE/ESM/esm_main.c - ${NAS_SRC}UE/ESM/esm_pt.c - ${NAS_SRC}UE/ESM/EsmStatusHdl.c - ${NAS_SRC}UE/ESM/PdnConnectivity.c - ${NAS_SRC}UE/ESM/PdnDisconnect.c +set (libnas_ue_esm_OBJS + ${NAS_SRC}UE/ESM/DedicatedEpsBearerContextActivation.c + ${NAS_SRC}UE/ESM/DefaultEpsBearerContextActivation.c + ${NAS_SRC}UE/ESM/EpsBearerContextDeactivation.c + ${NAS_SRC}UE/ESM/esm_ebr.c + ${NAS_SRC}UE/ESM/esm_ebr_context.c + ${NAS_SRC}UE/ESM/esm_ip.c + ${NAS_SRC}UE/ESM/esm_main.c + ${NAS_SRC}UE/ESM/esm_pt.c + ${NAS_SRC}UE/ESM/EsmStatusHdl.c + ${NAS_SRC}UE/ESM/PdnConnectivity.c + ${NAS_SRC}UE/ESM/PdnDisconnect.c ) - set(libnas_ue_esm_sap_OBJS - ${NAS_SRC}UE/ESM/SAP/esm_recv.c - ${NAS_SRC}UE/ESM/SAP/esm_send.c - ${NAS_SRC}UE/ESM/SAP/esm_sap.c +set(libnas_ue_esm_sap_OBJS + ${NAS_SRC}UE/ESM/SAP/esm_recv.c + ${NAS_SRC}UE/ESM/SAP/esm_send.c + ${NAS_SRC}UE/ESM/SAP/esm_sap.c ) - add_library(LIB_NAS_UE - ${NAS_SRC}UE/nas_itti_messaging.c - ${NAS_SRC}UE/nas_network.c - ${NAS_SRC}UE/nas_parser.c - ${NAS_SRC}UE/nas_proc.c - ${NAS_SRC}UE/nas_user.c - ${libnas_api_OBJS} - ${libnas_ue_api_OBJS} - ${libnas_emm_msg_OBJS} - ${libnas_esm_msg_OBJS} - ${libnas_ies_OBJS} - ${libnas_utils_OBJS} - ${libnas_ue_emm_OBJS} - ${libnas_ue_emm_sap_OBJS} - ${libnas_ue_esm_OBJS} - ${libnas_ue_esm_sap_OBJS} - ) - add_dependencies(LIB_NAS_UE rrc_flag) - set(NAS_UE_LIB LIB_NAS_UE) - include_directories(${NAS_SRC}UE) - include_directories(${NAS_SRC}UE/API/USER) - include_directories(${NAS_SRC}UE/API/USIM) - include_directories(${NAS_SRC}UE/EMM) - include_directories(${NAS_SRC}UE/EMM/SAP) - include_directories(${NAS_SRC}UE/ESM) - include_directories(${NAS_SRC}UE/ESM/SAP) -endif() +set(libnrnas_emm_msg_OBJS + ${NAS_SRC}COMMON/EMM/MSG/RegistrationRequest.c + ${NAS_SRC}COMMON/EMM/MSG/RegistrationAccept.c + ${NAS_SRC}COMMON/EMM/MSG/FGSIdentityResponse.c + ${NAS_SRC}COMMON/EMM/MSG/FGSAuthenticationResponse.c + ${NAS_SRC}COMMON/EMM/MSG/FGSNASSecurityModeComplete.c + ${NAS_SRC}COMMON/EMM/MSG/RegistrationComplete.c + ${NAS_SRC}COMMON/EMM/MSG/FGSUplinkNasTransport.c + ${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishRequest.c + ) +set(libnrnas_ies_OBJS + ${NAS_SRC}COMMON/IES/ExtendedProtocolDiscriminator.c + ${NAS_SRC}COMMON/IES/FGSMobileIdentity.c + ${NAS_SRC}COMMON/IES/FGSRegistrationType.c + ${NAS_SRC}COMMON/IES/SpareHalfOctet.c + ${NAS_SRC}COMMON/IES/FGSRegistrationResult.c + ${NAS_SRC}COMMON/IES/FGMMCapability.c + ${NAS_SRC}COMMON/IES/NrUESecurityCapability.c + ${NAS_SRC}COMMON/IES/FGCNasMessageContainer.c + ${NAS_SRC}COMMON/IES/SORTransparentContainer.c + ) + +add_library(LIB_NAS_SIMUE + ${NAS_SRC}UE/nas_itti_messaging.c + ${NAS_SRC}UE/nas_network.c + ${NAS_SRC}UE/nas_parser.c + ${NAS_SRC}UE/nas_proc.c + ${NAS_SRC}UE/nas_user.c + ${NAS_SRC}NR_UE/nr_nas_msg_sim.c + ${libnas_api_OBJS} + ${libnas_ue_api_OBJS} + ${libnas_emm_msg_OBJS} + ${libnas_esm_msg_OBJS} + ${libnas_ies_OBJS} + ${libnas_utils_OBJS} + ${libnas_ue_emm_OBJS} + ${libnas_ue_emm_sap_OBJS} + ${libnas_ue_esm_OBJS} + ${libnas_ue_esm_sap_OBJS} + ${libnrnas_emm_msg_OBJS} + ${libnrnas_ies_OBJS} + ) +add_dependencies(LIB_NAS_SIMUE rrc_flag) +set(NAS_SIM_LIB LIB_NAS_SIMUE) + +add_library(LIB_NAS_UE + ${NAS_SRC}UE/nas_itti_messaging.c + ${NAS_SRC}UE/nas_network.c + ${NAS_SRC}UE/nas_parser.c + ${NAS_SRC}UE/nas_proc.c + ${NAS_SRC}UE/nas_user.c + ${libnas_api_OBJS} + ${libnas_ue_api_OBJS} + ${libnas_emm_msg_OBJS} + ${libnas_esm_msg_OBJS} + ${libnas_ies_OBJS} + ${libnas_utils_OBJS} + ${libnas_ue_emm_OBJS} + ${libnas_ue_emm_sap_OBJS} + ${libnas_ue_esm_OBJS} + ${libnas_ue_esm_sap_OBJS} + ) +add_dependencies(LIB_NAS_UE rrc_flag) +set(NAS_UE_LIB LIB_NAS_UE) + + +include_directories(${NAS_SRC}NR_UE) +include_directories(${NAS_SRC}UE) +include_directories(${NAS_SRC}UE/API/USER) +include_directories(${NAS_SRC}UE/API/USIM) +include_directories(${NAS_SRC}UE/EMM) +include_directories(${NAS_SRC}UE/EMM/SAP) +include_directories(${NAS_SRC}UE/ESM) +include_directories(${NAS_SRC}UE/ESM/SAP) # nbiot add_definitions("-DNUMBER_OF_UE_MAX_NB_IoT=16") set (NBIOT_SOURCES - ${OPENAIR2_DIR}/ENB_APP/NB_IoT_config.c -) + ${OPENAIR2_DIR}/ENB_APP/NB_IoT_config.c + ) add_library(NB_IoT MODULE ${NBIOT_SOURCES} ) # shared library loader set (SHLIB_LOADER_SOURCES - ${OPENAIR_DIR}/common/utils/load_module_shlib.c -) + ${OPENAIR_DIR}/common/utils/load_module_shlib.c + ) + +add_library(LIB_5GNAS_GNB + ${NAS_SRC}/COMMON/nr_common.c + ${NAS_SRC}/gNB/network_process_nas.c + ${NAS_SRC}/NR_UE/ue_process_nas.c + ${OPENAIR3_DIR}//UICC/usim_interface.c + ) +target_link_libraries(LIB_5GNAS_GNB SECU_CN ${CRYPTO_LIBRARIES}) # Make lfds as a own source code (even if it is a outside library) # For better intergration with compilation flags & structure of cmake @@ -2314,11 +2609,12 @@ add_library(LFDS7 add_library(SIMU_COMMON ${OPENAIR1_DIR}/SIMULATION/TOOLS/random_channel.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/rangen_double.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/phase_noise.c ) # Simulation library ########################## -set (SIMUSRC +set (SIMUSRC ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/multipath_channel.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/multipath_tv_channel.c @@ -2349,114 +2645,6 @@ include_directories("${NFAPI_DIR}/nfapi/inc") include_directories("${NFAPI_DIR}/sim_common/inc") include_directories("${NFAPI_DIR}/pnf_sim/inc") - -# System packages that are required -# We use either the cmake buildin, in ubuntu are in: /usr/share/cmake*/Modules/ -# or cmake provide a generic interface to pkg-config that widely used -################################### -include(FindPkgConfig) - -pkg_search_module(LIBXML2 libxml-2.0 REQUIRED) -include_directories(${LIBXML2_INCLUDE_DIRS}) - -pkg_search_module(LIBXSLT libxslt REQUIRED) -include_directories(${LIBXSLT_INCLUDE_DIRS}) - -pkg_search_module(OPENSSL openssl REQUIRED) -include_directories(${OPENSSL_INCLUDE_DIRS}) - -pkg_search_module(CONFIG libconfig REQUIRED) -include_directories(${CONFIG_INCLUDE_DIRS}) - -pkg_search_module(CRYPTO libcrypto REQUIRED) -include_directories(${CRYPTO_INCLUDE_DIRS}) - -#use native cmake method as this package is not in pkg-config -if (${RF_BOARD} STREQUAL "OAI_USRP") - find_package(Boost REQUIRED) - include_directories(${LIBBOOST_INCLUDE_DIR}) - -elseif (${RF_BOARD} STREQUAL "OAI_IRIS") - include_directories("${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/") - include_directories("/usr/local/include/") - set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp) - LINK_DIRECTORIES("/usr/local/lib") - set(option_HW_lib "-lSoapySDR -rdynamic -ldl") - -endif (${RF_BOARD} STREQUAL "OAI_USRP") - -pkg_search_module(OPENPGM openpgm-5.1 openpgm-5.2) -if(NOT ${OPENPGM_FOUND}) - message("PACKAGE openpgm-5.1 is required by binaries such as oaisim: will fail later if this target is built") -else() - include_directories(${OPENPGM_INCLUDE_DIRS}) -endif() - -pkg_search_module(NETTLE nettle) -if(NOT ${NETTLE_FOUND}) - message( FATAL_ERROR "PACKAGE nettle not found: some targets will fail. Run build_oai -I again!") -else() - include_directories(${NETTLE_INCLUDE_DIRS}) -endif() - -message ("NETTLE VERSION_INSTALLED = ${NETTLE_VERSION}") - -string(REGEX REPLACE "([0-9]+).*" "\\1" NETTLE_VERSION_MAJOR ${NETTLE_VERSION}) -string(REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" NETTLE_VERSION_MINOR ${NETTLE_VERSION}) -message ("NETTLE_VERSION_MAJOR = ${NETTLE_VERSION_MAJOR}") -message ("NETTLE_VERSION_MINOR = ${NETTLE_VERSION_MINOR}") - -if ("${NETTLE_VERSION_MAJOR}" STREQUAL "" OR "${NETTLE_VERSION_MINOR}" STREQUAL "") - message( FATAL_ERROR "The nettle version not detected properly. Try to run build_oai -I again" ) -endif() - -add_definitions("-DNETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}") -add_definitions("-DNETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}") - -pkg_search_module(XPM xpm) -if(NOT ${XPM_FOUND}) - message("PACKAGE xpm not found: some targets will fail") -else() - include_directories(${XPM_INCLUDE_DIRS}) -endif() - -# Atlas is required by some packages, but not found in pkg-config -# So, here are some hacks here. Hope this gets fixed in future! -if(EXISTS "/usr/include/atlas/cblas.h" OR EXISTS "/usr/include/cblas.h") - include_directories("/usr/include/atlas") - LINK_DIRECTORIES("/usr/lib/lapack") - LINK_DIRECTORIES("/usr/lib64") - LINK_DIRECTORIES("/usr/lib64/atlas") #Added because atlas libraries in CentOS 7 are here! - - if(EXISTS "/usr/lib64/libblas.so" OR EXISTS "/usr/lib/libblas.so") #Case for CentOS7 - list(APPEND ATLAS_LIBRARIES blas) - - else() # Case for Ubuntu - list(APPEND ATLAS_LIBRARIES cblas) - endif() - - if(EXISTS "/usr/lib/atlas/libtatlas.so" OR EXISTS "/usr/lib64/atlas/libtatlas.so") #Case for CentOS7 - list(APPEND ATLAS_LIBRARIES tatlas) - else() - list(APPEND ATLAS_LIBRARIES atlas) #Case for Ubuntu - endif() - - list(APPEND ATLAS_LIBRARIES lapack) - -# for ubuntu 17.10, directories are different -elseif(EXISTS "/usr/include/x86_64-linux-gnu/cblas.h") - - include_directories("/usr/include/x86_64-linux-gnu") - LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") - list(APPEND ATLAS_LIBRARIES cblas) - list(APPEND ATLAS_LIBRARIES atlas) - list(APPEND ATLAS_LIBRARIES lapack) - -else() - message("No Blas/Atlas libs found, some targets will fail") -endif() - list(APPEND ATLAS_LIBRARIES lapack lapacke) include_directories ("/usr/include/X11") @@ -2489,14 +2677,15 @@ add_library(nrscope MODULE ${XFORMS_SOURCE_NR}) target_link_libraries(nrscope ${XFORMS_LIBRARIES}) -add_library(rfsimulator MODULE +add_library(rfsimulator MODULE ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c ${OPENAIR_TARGETS}/ARCH/rfsimulator/apply_channelmod.c ${OPENAIR_TARGETS}/ARCH/rfsimulator/new_channel_sim.c + ${OPENAIR1_DIR}/PHY/TOOLS/signal_energy.c ) target_link_libraries(rfsimulator SIMU_COMMON ${ATLAS_LIBRARIES}) -add_library(oai_iqplayer MODULE +add_library(oai_iqplayer MODULE ${OPENAIR_TARGETS}/ARCH/iqplayer/iqplayer_lib.c ) set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}") @@ -2507,6 +2696,7 @@ include_directories("${OPENAIR_DIR}/common/utils/T") if (${T_TRACER}) set(T_SOURCE + ${OPENAIR_DIR}/common/utils/T/T_IDs.h ${OPENAIR_DIR}/common/utils/T/T.c ${OPENAIR_DIR}/common/utils/T/local_tracer.c) set(T_LIB "rt") @@ -2516,8 +2706,6 @@ endif (${T_TRACER}) #This rule and the following deal with it. add_custom_command ( OUTPUT ${OPENAIR_DIR}/common/utils/T/T_IDs.h - COMMAND make clean - COMMAND make -j2 COMMAND make check_vcd WORKING_DIRECTORY ${OPENAIR_DIR}/common/utils/T DEPENDS ${OPENAIR_DIR}/common/utils/T/T_messages.txt @@ -2525,6 +2713,10 @@ add_custom_command ( ${OPENAIR_DIR}/common/utils/LOG/vcd_signal_dumper.h ) +execute_process ( + COMMAND make check_vcd + WORKING_DIRECTORY ${OPENAIR_DIR}/common/utils/T +) #This rule is specifically needed to generate T files #before anything else in a project that uses the T. #See below, there are some 'add_dependencies' showing that. @@ -2563,6 +2755,12 @@ add_executable(measurement_display ${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c) target_link_libraries (measurement_display minimal_lib) +add_executable(test5Gnas + ${OPENAIR_DIR}/openair3/TEST/test5Gnas.c +) +target_link_libraries (test5Gnas LIB_5GNAS_GNB CONFIG_LIB minimal_lib ) + + # lte-softmodem is both eNB and UE implementation ################################################### @@ -2582,13 +2780,15 @@ add_executable(lte-softmodem ${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c ${OPENAIR2_DIR}/RRC/NAS/nas_config.c ${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR2_DIR}/F1AP/dummy_enb.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c - ${GTPU_need_ITTI} + ${OPENAIR_DIR}/common/utils/lte/ue_power.c + ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${XFORMSINTERFACE_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} @@ -2598,13 +2798,13 @@ add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag oai_iqplayer) target_link_libraries (lte-softmodem -Wl,--start-group - RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB - PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB NR_GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB + PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB LFDS7 + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} -Wl,--end-group z dl) - + target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES}) -target_link_libraries (lte-softmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES}) +target_link_libraries (lte-softmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES}) target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES}) target_link_libraries (lte-softmodem ${T_LIB}) @@ -2629,7 +2829,8 @@ add_executable(ocp-enb ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c - ${GTPU_need_ITTI} + ${OPENAIR_DIR}/common/utils/lte/ue_power.c + ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${XFORMSINTERFACE_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} @@ -2639,11 +2840,12 @@ add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer coding params_l target_link_libraries (ocp-enb -Wl,--start-group - RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB - PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} + + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB NR_GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB + PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB MISC_NFAPI_LTE_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} -Wl,--end-group z dl) -target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) +target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) add_executable(cu_test ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/cu_test.c @@ -2656,7 +2858,7 @@ add_executable(cu_test ) target_link_libraries(cu_test ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FSPT_MSG_LIB} ${PROTOBUF_LIB} - ${PROTO_AGENT_LIB} pthread UTIL ${T_LIB} dl ${ITTI_LIB} + ${PROTO_AGENT_LIB} pthread UTIL ${T_LIB} dl ITTI ) add_executable(du_test @@ -2670,9 +2872,36 @@ add_executable(du_test ) target_link_libraries(du_test ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FSPT_MSG_LIB} ${PROTOBUF_LIB} - ${PROTO_AGENT_LIB} pthread UTIL ${T_LIB} dl ${ITTI_LIB} + ${PROTO_AGENT_LIB} pthread UTIL ${T_LIB} dl ITTI ) +add_executable(oairu + ${OPENAIR_TARGETS}/RT/USER/lte-ru.c + ${OPENAIR_TARGETS}/RT/USER/ru_control.c + ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c + ${OPENAIR_DIR}/executables/softmodem-common.c + ${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/executables/main_ru.c + ${T_SOURCE} + ${OPENAIR_DIR}/common/utils/LOG/log.c + ${CONFIG_SOURCES} + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/lte/prach_utils.c + ${SHLIB_LOADER_SOURCES} +) +target_link_libraries (oairu + -Wl,--start-group + SCHED_RU_LIB + PHY_COMMON PHY_RU + -Wl,--end-group z dl) + +target_link_libraries (oairu pthread m ${CONFIG_LIB} rt ${CMAKE_DL_LIBS} ${T_LIB}) + + # lte-uesoftmodem is UE implementation ####################################### @@ -2681,9 +2910,6 @@ add_executable(lte-uesoftmodem ${OPENAIR_TARGETS}/RT/USER/lte-ue.c ${OPENAIR_TARGETS}/RT/USER/lte-uesoftmodem.c ${OPENAIR_DIR}/executables/softmodem-common.c - ${OPENAIR_TARGETS}/RT/USER/lte-ru.c - ${OPENAIR_TARGETS}/RT/USER/ru_control.c - ${OPENAIR_TARGETS}/RT/USER/rfsim.c ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c ${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c @@ -2695,6 +2921,8 @@ add_executable(lte-uesoftmodem ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/lte/ue_power.c + ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${XFORMSINTERFACE_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} @@ -2708,14 +2936,15 @@ if (NOT ${NOS1}) endif() target_link_libraries (lte-uesoftmodem -Wl,--start-group - RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP F1AP_LIB - GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON - PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES} + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP F1AP_LIB + + NR_GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON + PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES} -Wl,--end-group z dl) target_link_libraries (lte-uesoftmodem ${LIBXML2_LIBRARIES}) -target_link_libraries (lte-uesoftmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries (lte-uesoftmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES}) target_link_libraries (lte-uesoftmodem ${LIB_LMS_LIBRARIES}) target_link_libraries (lte-uesoftmodem ${T_LIB}) @@ -2728,6 +2957,7 @@ add_executable(nr-softmodem ${s1ap_h} # ${OPENAIR_BIN_DIR}/messages_xml.h ${OPENAIR_DIR}/executables/nr-gnb.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/executables/nr-ru.c ${OPENAIR_DIR}/executables/nr-softmodem.c ${OPENAIR_DIR}/executables/softmodem-common.c @@ -2736,32 +2966,74 @@ add_executable(nr-softmodem ${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c ${OPENAIR2_DIR}/RRC/NAS/nas_config.c ${OPENAIR2_DIR}/RRC/NAS/rb_config.c - ${OPENAIR3_DIR}/GTPV1-U/gtpv1u_gNB.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/lte/ue_power.c + ${OPENAIR_DIR}/common/utils/lte/prach_utils.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c - ${GTPU_need_ITTI} ${XFORMSINTERFACE_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} + ${OPENAIR2_DIR}/ENB_APP/flexran_agent_ran_api_to_fix.c ) +target_compile_definitions(nr-softmodem PUBLIC NEW_GTPU) target_link_libraries (nr-softmodem -Wl,--start-group - UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS NR_GTPV1U SECU_CN SECU_OSA - ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB - S1AP_LIB S1AP_ENB L2 L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB + UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U_OCP SECU_CN SECU_OSA + ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB + NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB} -Wl,--end-group z dl) target_link_libraries (nr-softmodem ${LIBXML2_LIBRARIES}) -target_link_libraries (nr-softmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries (nr-softmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES}) target_link_libraries (nr-softmodem ${LIB_LMS_LIBRARIES}) target_link_libraries (nr-softmodem ${T_LIB}) add_dependencies( nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc ) + +add_executable(ocp-gnb + ${rrc_h} + ${nr_rrc_h} + ${s1ap_h} +# ${OPENAIR_BIN_DIR}/messages_xml.h + ${OPENAIR_DIR}/executables/ocp-gnb.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/executables/softmodem-common.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR_DIR}/common/utils/nr/nr_common.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c + ${XFORMS_SOURCE_NR} + ${T_SOURCE} + ${CONFIG_SOURCES} + ${SHLIB_LOADER_SOURCES} + ${XFORMSINTERFACE_SOURCE} + ) + +target_link_libraries (ocp-gnb + -Wl,--start-group + UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U_OCP SECU_CN SECU_OSA + ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB + NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB + X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB SIMU_COMMON + -Wl,--end-group z dl) + +target_link_libraries (ocp-gnb ${LIBXML2_LIBRARIES} ) +target_link_libraries (ocp-gnb pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries (ocp-gnb ${LIB_LMS_LIBRARIES}) +target_link_libraries (ocp-gnb ${T_LIB}) +add_dependencies(ocp-gnb ldpc_orig ldpc_optim ldpc_optim8seg ldpc params_libconfig rfsimulator oai_usrpdevif rfsimulator nrscope) + + # nr-uesoftmodem is UE implementation ####################################### @@ -2793,19 +3065,25 @@ add_executable(nr-uesoftmodem target_link_libraries (nr-uesoftmodem -Wl,--start-group - RRC_LIB NR_RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB - PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB + RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB + PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB + NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} NFAPI_USER_LIB S1AP_LIB S1AP_ENB - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} -Wl,--end-group z dl) target_link_libraries (nr-uesoftmodem ${LIBXML2_LIBRARIES}) -target_link_libraries (nr-uesoftmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries (nr-uesoftmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES}) target_link_libraries (nr-uesoftmodem ${LIB_LMS_LIBRARIES}) target_link_libraries (nr-uesoftmodem ${T_LIB}) add_dependencies( nr-uesoftmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc ) - +if (CUDA_FOUND) + add_dependencies( nr-uesoftmodem ldpc_cuda) + add_dependencies( nr-softmodem ldpc_cuda) + add_dependencies( ocp-gnb ldpc_cuda) +endif (CUDA_FOUND) ###################################" # Addexecutables for tests #################################### @@ -2822,11 +3100,22 @@ add_executable(dlsim_tm4 ${T_SOURCE} ) target_link_libraries (dlsim_tm4 - -Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group + -Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY LFDS ITTI -Wl,--end-group pthread m rt ${CONFIG_LIB} ${ATLAS_LIBRARIES} ${T_LIB} ) -add_executable(polartest +add_executable(rftest + ${OPENAIR_DIR}/openair1/PHY/TOOLS/calibration_test.c + ${OPENAIR_DIR}/openair1/PHY/TOOLS/calibration_scope.c + ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${OPENAIR_DIR}/executables/softmodem-common.c + ${CONFIG_SOURCES} + ${SHLIB_LOADER_SOURCES} +) +target_link_libraries(rftest minimal_lib PHY_NR_COMMON pthread dl m forms ${T_LIB} ) + +add_executable(polartest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c @@ -2839,7 +3128,7 @@ target_link_libraries(polartest m pthread ${ATLAS_LIBRARIES} dl ) -add_executable(smallblocktest +add_executable(smallblocktest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/smallblocktest.c ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c @@ -2855,129 +3144,110 @@ target_link_libraries(smallblocktest ) -# temp_C_flag = CMAKE_C_FLAGS -#set(CMAKE_C_FLAGS " ") -set (TEMP_C_FLAG ${CMAKE_C_FLAGS}) -set (CMAKE_C_FLAGS ${CUDA_CMAKE_C_FLAGS}) +add_executable(ldpctest + ${PHY_NR_CODINGIF} + ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c + ${T_SOURCE} + ${SHLIB_LOADER_SOURCES} + ) -set (TEMP_CXX_FLAG ${CMAKE_CXX_FLAGS}) -set (CMAKE_CXX_FLAGS ${CUDA_CMAKE_CXX_FLAGS}) +add_dependencies( ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc ) if (CUDA_FOUND) -################################################### -# For CUDA library -################################################### - - CUDA_ADD_LIBRARY(LDPC_CU - ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu - ) - CUDA_ADD_CUFFT_TO_TARGET(LDPC_CU) - cuda_add_executable(ldpctest - ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c - ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} - ) - target_link_libraries(ldpctest -ldl - -Wl,--start-group - LDPC_CU UTIL SIMU PHY_NR CONFIG_LIB - -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} dl - ) - -else (CUDA_FOUND) - add_executable(ldpctest - ${PHY_NR_CODINGIF} - ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c - ${T_SOURCE} - ${SHLIB_LOADER_SOURCES} - ) - -endif () -set (CMAKE_C_FLAGS ${TEMP_C_FLAG}) -set (CMAKE_CXX_FLAGS ${TEMP_CXX_FLAG}) - - -# add_executable(ldpctest - # ${PHY_NR_CODINGIF} - # ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c - # ${T_SOURCE} - # ${SHLIB_LOADER_SOURCES} - # ) -add_dependencies( ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc ) - + add_dependencies( ldpctest ldpc_cuda) +endif (CUDA_FOUND) target_link_libraries(ldpctest -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_NR PHY_COMMON PHY_NR_COMMON CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} dl ) -add_executable(nr_dlschsim - ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c +add_executable(nr_dlschsim + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} ) -target_link_libraries(nr_dlschsim +target_link_libraries(nr_dlschsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) -add_executable(nr_pbchsim - ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c +add_executable(nr_pbchsim + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_pbchsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) #PUCCH ---> Prashanth -add_executable(nr_pucchsim - ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pucchsim.c +add_executable(nr_pucchsim + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pucchsim.c ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_pucchsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) add_executable(nr_dlsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlsim.c + ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR_DIR}/executables/softmodem-common.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${NFAPI_USER_DIR}/nfapi.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} - ) + ) target_link_libraries(nr_dlsim - -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_NR -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl ) target_compile_definitions(nr_dlsim PUBLIC -DPHYSICAL_SIMULATOR) add_executable(nr_prachsim - ${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c + ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${NFAPI_USER_DIR}/nfapi.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES}) -target_link_libraries(nr_prachsim - -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB MAC_UE_NR SCHED_NR_UE_LIB RRC_LIB NR_RRC_LIB L2_NR CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl) +target_link_libraries(nr_prachsim + -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl) add_executable(nr_ulschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${UTIL_SRC} @@ -2986,31 +3256,40 @@ add_executable(nr_ulschsim ) target_link_libraries(nr_ulschsim -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI dl ) add_executable(nr_ulsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR_DIR}/executables/softmodem-common.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${NFAPI_USER_DIR}/nfapi.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_ulsim - -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR PHY_NR_COMMON PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_NR -Wl,--end-group - m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl + -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group + m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl ) target_compile_definitions(nr_ulsim PUBLIC -DPHYSICAL_SIMULATOR) foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim) - + add_executable(${myExe} ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/lte/ue_power.c + ${OPENAIR_DIR}/common/utils/lte/prach_utils.c + ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${XFORMS_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} @@ -3018,10 +3297,10 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr ${NFAPI_USER_DIR}/nfapi.c ) target_link_libraries (${myExe} - -Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU LFDS ${ITTI_LIB} LFDS7 -Wl,--end-group + -Wl,--start-group SIMU_COMMON SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_NR_COMMON PHY PHY_UE PHY_RU LFDS ITTI LFDS7 -Wl,--end-group pthread m rt ${CONFIG_LIB} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB} dl ) - + endforeach(myExe) add_executable(test_epc_generate_scenario @@ -3033,7 +3312,7 @@ add_executable(test_epc_generate_scenario ${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h ) target_link_libraries (test_epc_generate_scenario - -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIB} + -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP NR_GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY LFDS ITTI ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB} ) add_executable(test_epc_play_scenario @@ -3052,7 +3331,7 @@ add_executable(test_epc_play_scenario ) target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c) target_link_libraries (test_epc_play_scenario - -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY_NR_COMMON PHY_COMMON PHY PHY_UE LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIB} + -Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP NR_GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY_NR_COMMON PHY_COMMON PHY PHY_UE LFDS ITTI ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB} ) @@ -3072,7 +3351,7 @@ foreach(myExe s1ap ${OPENAIR3_DIR}/TEST/test_${myExe}.c ) target_link_libraries (test_${myExe} - -Wl,--start-group SECU_CN UTIL LFDS -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIB} + -Wl,--start-group SECU_CN UTIL LFDS -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB} ) endforeach(myExe) @@ -3084,21 +3363,21 @@ endforeach(myExe) if (${T_TRACER}) foreach(i #all "add_executable" definitions (except tests, rb_tool, updatefw) - lte-softmodem lte-uesoftmodem nr-softmodem - nr-uesoftmodem dlsim dlsim_tm4 dlsim_tm7 + lte-softmodem lte-uesoftmodem nr-softmodem + nr-uesoftmodem dlsim dlsim_tm4 dlsim_tm7 nr-ittisim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim nr_ulsim nr_dlsim nr_dlschsim nr_pbchsim nr_pucchsim nr_ulschsim ldpctest polartest smallblocktest cu_test du_test #all "add_library" definitions - ITTI RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP + ITTI RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP params_libconfig oai_exmimodevif oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer oai_eth_transpro oai_mobipass tcp_bridge tcp_bridge_oai coding FLPT_MSG ASYNC_IF FLEXRAN_AGENT HASHTABLE MSC UTIL OMG_SUMO SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX - L2 L2_LTE L2_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_NR MAC_UE_NR - CN_UTILS GTPV1U NR_GTPV1U SCTP_CLIENT MME_APP UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU_COMMON SIMU SIMU_ETH OPENAIR0_LIB + L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR NGAP_GNB + CN_UTILS NR_GTPV1U GTPV1U_OCP SCTP_CLIENT MME_APP UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU_COMMON SIMU SIMU_ETH OPENAIR0_LIB ldpc_orig ldpc_optim ldpc_optim8seg ldpc PROTO_AGENT dfts) if (TARGET ${i}) add_dependencies(${i} generate_T) @@ -3154,7 +3433,7 @@ endfunction(make_driver name dir src) # nashmesh module ################ list(APPEND nasmesh_src device.c common.c ioctl.c classifier.c tool.c mesh.c) -set(module_cc_opt "${module_cc_opt} -DNAS_NETLINK -DPDCP_USE_NETLINK -D${MKVER}") +set(module_cc_opt "${module_cc_opt} -DNAS_NETLINK -DPDCP_USE_NETLINK") # legacy Makefile was using NAS_NETLINK flag, but other drivers the hereafter flag # so, this cmake use OAI_NW_DRIVER_USE_NETLINK everywhere if (OAI_NW_DRIVER_USE_NETLINK) @@ -3172,6 +3451,55 @@ add_executable(rb_tool ) target_include_directories(rb_tool PRIVATE ${OPENAIR2_DIR}/NETWORK_DRIVER/MESH/) +# nr-ittisim +################################################### + +add_executable(nr-ittisim + ${rrc_h} + ${nr_rrc_h} + ${OPENAIR2_DIR}/GNB_APP/gnb_app.c + ${OPENAIR2_DIR}/GNB_APP/gnb_config.c + ${OPENAIR_DIR}/executables/nr-gnb.c + ${OPENAIR_DIR}/executables/nr-ru.c + ${OPENAIR2_DIR}/SIMULATION/NR_RRC/itti_sim.c + ${OPENAIR_DIR}/executables/softmodem-common.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/nr/nr_common.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/common/utils/lte/ue_power.c + ${OPENAIR_DIR}/common/utils/lte/prach_utils.c + ${OPENAIR2_DIR}/ENB_APP/flexran_agent_ran_api_to_fix.c + ${XFORMSINTERFACE_SOURCE} + ${T_SOURCE} + ${CONFIG_SOURCES} + ${SHLIB_LOADER_SOURCES} + ) +target_compile_definitions(nr-ittisim PUBLIC NEW_GTPU) + +target_link_libraries (nr-ittisim + -Wl,--start-group + UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS GTPV1U_OCP SECU_CN SECU_OSA + ITTI ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_SIM_LIB} RRC_LIB NR_RRC_LIB + NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB + X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB} + PHY_NR_UE SCHED_NR_UE_LIB NR_L2_UE + -Wl,--end-group z dl) + +target_link_libraries (nr-ittisim ${LIBXML2_LIBRARIES}) +target_link_libraries (nr-ittisim pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES}) +target_link_libraries (nr-ittisim ${LIB_LMS_LIBRARIES}) +target_link_libraries (nr-ittisim ${T_LIB}) + +add_dependencies( nr-ittisim ldpc_orig ldpc_optim ldpc_optim8seg ldpc ) + # ??? #################### list(APPEND oai_nw_drv_src device.c common.c ioctl.c classifier.c tool.c) diff --git a/cmake_targets/at_commands/CMakeLists.txt b/cmake_targets/at_commands/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/README.txt b/cmake_targets/autotests/README.txt old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/core.py b/cmake_targets/autotests/core.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/log.py b/cmake_targets/autotests/log.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/openair.py b/cmake_targets/autotests/openair.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/templates/index.html b/cmake_targets/autotests/templates/index.html old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/templates/testcase_report.html b/cmake_targets/autotests/templates/testcase_report.html old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml old mode 100644 new mode 100755 index 786002e982..3472b14efc --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1095,7 +1095,15 @@ (Test10: 106 PRBs 50 PDSCH-PRBs MCS Index 16), (Test11: HARQ test 25% TP (4 rounds), (Test12: HARQ test 33% TP (3 rounds), - (Test13: HARQ test 50% TP (2 rounds) + (Test13: HARQ test 50% TP (2 rounds), + (Test14: 3 PTRS, 8 Interpolated Symbols), + (Test15: 6 PTRS, 5 Interpolated Symbols), + (Test16: 11 PTRS, 0 Interpolated Symbols), + (Test17: Mapping type A, 2 DMRS Symbols), + (Test18: Mapping type A, 3 DMRS Symbols), + (Test19: Mapping type B, 4 DMRS Symbols), + (Test20: 4x4 MIMO, 1 Layer), + (Test21: 4x4 MIMO, 2 Layers) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1114,8 +1122,16 @@ -n100 -e16 -s10 -n100 -s1 -t25 -n100 -s1 -t33 - -n100 -s1 -t50 - nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13 + -n100 -s1 -t50 + -n100 -s5 -T 2 2 2 + -n100 -s5 -T 2 1 2 + -n100 -s5 -T 2 0 4 + -n100 -s2 -U 2 0 1 + -n100 -s2 -U 2 0 2 + -n100 -s2 -U 2 1 3 + -n10 -s20 -U 3 0 0 2 -gR -x1 -y4 -z4 + -n10 -s20 -U 3 0 0 2 -gR -x2 -y4 -z4 + nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13 nr_dlsim.test14 nr_dlsim.test15 nr_dlsim.test16 nr_dlsim.test17 nr_dlsim.test18 nr_dlsim.test19 nr_dlsim.test20 nr_dlsim.test21 PDSCH test OK segmentation fault|assertion|exiting|fatal 3 @@ -1276,7 +1292,17 @@ (Test2: MCS 16 50 PRBs), (Test3: MCS 28 50 PRBs), (Test4: MCS 9 217 PRBs), - (Test5: MCS 9 273 PRBs) + (Test5: MCS 9 273 PRBs), + (Test6: DMRS Type A, 2 DMRS Symbols), + (Test7: DMRS Type A, 3 DMRS, 4 PTRS, 5 Interpolated Symbols), + (Test8: DMRS Type B, 3 DMRS, 2 PTRS, 7 Interpolated Symbols), + (Test9: DMRS Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols), + (Test10: SC-FDMA, 50 PRBs), + (Test11: SC-FDMA, 75 PRBs), + (Test12: SC-FDMA, 216 PRBs), + (Test13: SC-FDMA, 273 PRBs), + (Test14: SC-FDMA, 3 DMRS), + (Test15: MCS 16 50 PRBs 2 RX_Antenna) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1287,8 +1313,19 @@ -n100 -m16 -s10 -n100 -m28 -s20 -n100 -m9 -R217 -r217 -s5 - -n100 -m9 -R273 -r273 -s5 - nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 + -n100 -m9 -R273 -r273 -s5 + -n100 -s5 -U 2 0 1 + -n100 -s5 -T 2 1 2 -U 2 0 2 + -n100 -s5 -T 2 2 2 -U 2 1 2 + -n100 -s5 -a4 -b8 -T 2 1 2 -U 2 1 3 + -n100 -s5 -Z + -n100 -s5 -Z -r75 + -n50 -s5 -Z -r216 -R217 + -n50 -s5 -Z -r270 -R273 + -n100 -s5 -Z -U 2 0 2 + -n100 -m16 -s10 -z2 + + nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13 nr_ulsim.test14 nr_ulsim.test15 PUSCH test OK segmentation fault|assertion|exiting|fatal 3 @@ -1296,10 +1333,13 @@ execution - nr_prachsim Test cases. (Test1: 106 PRBs - Prach format A2), - (Test2: 217 PRBs - Prach format A2), - (Test3: 273 PRBs - Prach format A2), - (Test4: 106 PRBs - Prach format 0) + nr_prachsim Test cases. (Test1: 30kHz SCS, 106 PRBs, Prach format A2), + (Test2: 30kHz SCS, 217 PRBs, Prach format A2), + (Test3: 30kHz SCS, 273 PRBs, Prach format A2), + (Test4: 30kHz SCS, 106 PRBs, Prach format 0), + (Test5: 120kHz SCS, 32 PRBs, Prach format A2), + (Test6: 120kHz SCS, 66 PRBs, Prach format A2), + (Test7: 120kHz SCS, 66 PRBs, High Speed Enabled) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1309,8 +1349,11 @@ -a -s -30 -n 100 -p 63 -R 106 -a -s -30 -n 100 -p 63 -R 217 -a -s -30 -n 100 -p 63 -R 273 - -a -s -30 -n 100 -p 63 -R 106 -c 4 - nr_prachsim.test1 nr_prachsim.test2 nr_prachsim.test3 nr_prachsim.test4 + -a -s -30 -n 100 -p 63 -R 106 -c 4 + -a -s -30 -n 100 -p 32 -R 32 -m 3 -c52 + -a -s -30 -n 100 -p 32 -R 66 -m 3 -c52 + -a -s -30 -n 100 -R 66 -m 3 -c52 -H + nr_prachsim.test1 nr_prachsim.test2 nr_prachsim.test3 nr_prachsim.test4 nr_prachsim.test5 nr_prachsim.test6 nr_prachsim.test7 PRACH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/cmake_targets/autotests/testsuite_ue_noS1.xml b/cmake_targets/autotests/testsuite_ue_noS1.xml old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/testsuite_ue_noS1_TCL.xml b/cmake_targets/autotests/testsuite_ue_noS1_TCL.xml old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/tools/lib_autotest.py b/cmake_targets/autotests/tools/lib_autotest.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/tools/lib_autotest_analyser.py b/cmake_targets/autotests/tools/lib_autotest_analyser.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/tools/wdial.bandrich.conf b/cmake_targets/autotests/tools/wdial.bandrich.conf old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/3276.txt b/cmake_targets/autotests/v2/actions/3276.txt old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/alu_epc.bash b/cmake_targets/autotests/v2/actions/alu_epc.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/alu_epc_stop.bash b/cmake_targets/autotests/v2/actions/alu_epc_stop.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/alu_hss.bash b/cmake_targets/autotests/v2/actions/alu_hss.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/bandrich.txt b/cmake_targets/autotests/v2/actions/bandrich.txt old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/client_tcp.bash b/cmake_targets/autotests/v2/actions/client_tcp.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/client_udp.bash b/cmake_targets/autotests/v2/actions/client_udp.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/clone_repository.bash b/cmake_targets/autotests/v2/actions/clone_repository.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/compilation.bash b/cmake_targets/autotests/v2/actions/compilation.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/execution.bash b/cmake_targets/autotests/v2/actions/execution.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/execution_compile.bash b/cmake_targets/autotests/v2/actions/execution_compile.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/modem.py b/cmake_targets/autotests/v2/actions/modem.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/run_enb.bash b/cmake_targets/autotests/v2/actions/run_enb.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/server_tcp.bash b/cmake_targets/autotests/v2/actions/server_tcp.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/server_udp.bash b/cmake_targets/autotests/v2/actions/server_udp.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/start_3276.bash b/cmake_targets/autotests/v2/actions/start_3276.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/start_3276.py b/cmake_targets/autotests/v2/actions/start_3276.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/start_bandrich.bash b/cmake_targets/autotests/v2/actions/start_bandrich.bash old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/start_bandrich.py b/cmake_targets/autotests/v2/actions/start_bandrich.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/stop_3276.py b/cmake_targets/autotests/v2/actions/stop_3276.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/stop_bandrich.py b/cmake_targets/autotests/v2/actions/stop_bandrich.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/wvdial.3276.conf b/cmake_targets/autotests/v2/actions/wvdial.3276.conf old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/actions/wvdial.bandrich.conf b/cmake_targets/autotests/v2/actions/wvdial.bandrich.conf old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/alu_test.py b/cmake_targets/autotests/v2/alu_test.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf old mode 100644 new mode 100755 index 7f920e7e38..7158790b28 --- a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.10MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf old mode 100644 new mode 100755 index e5c57ffda5..70819d0e29 --- a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.20MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf old mode 100644 new mode 100755 index 17a3380567..7381fefc1a --- a/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band38.tm1.usrpb210.tdd.5MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf old mode 100644 new mode 100755 index 6721504f36..8eecfa2ac5 --- a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.10MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf old mode 100644 new mode 100755 index 4919ad3117..ce2b71bdd2 --- a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.20MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf old mode 100644 new mode 100755 index c26a0ad698..11e6e24418 --- a/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf +++ b/cmake_targets/autotests/v2/config/enb.band7.tm1.usrpb210.fdd.5MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf old mode 100644 new mode 100755 index ff0d3d7a00..11f6adbb4d --- a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.10MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf old mode 100644 new mode 100755 index 8195b21157..3bf79f94bf --- a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.20MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf old mode 100644 new mode 100755 index 8b172a7d73..67a2bae08c --- a/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf +++ b/cmake_targets/autotests/v2/config/rcc.band7.tm1.if4p5.5MHz.conf @@ -147,6 +147,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf old mode 100644 new mode 100755 index 0d9a243b31..02f29c4c2e --- a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.10MHz.udp.usrpb210.conf @@ -149,6 +149,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf old mode 100644 new mode 100755 index ac8591841e..71a479a512 --- a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.20MHz.udp.usrpb210.conf @@ -149,6 +149,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf old mode 100644 new mode 100755 index 93bfc2449f..09958d62e4 --- a/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf +++ b/cmake_targets/autotests/v2/config/rru.band7.tm1.if4p5.5MHz.udp.usrpb210.conf @@ -149,6 +149,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/cmake_targets/autotests/v2/connection.py b/cmake_targets/autotests/v2/connection.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/machine_list.py b/cmake_targets/autotests/v2/machine_list.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/main.py b/cmake_targets/autotests/v2/main.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/task.py b/cmake_targets/autotests/v2/task.py old mode 100644 new mode 100755 diff --git a/cmake_targets/autotests/v2/utils.py b/cmake_targets/autotests/v2/utils.py old mode 100644 new mode 100755 diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 36af9eaee4..2ef0c31210 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -27,9 +27,8 @@ set -e # Include helper functions -ORIGIN_PATH=$PWD -THIS_SCRIPT_PATH=$(dirname $(readlink -f $0)) -source $THIS_SCRIPT_PATH/tools/build_helper +THIS_SCRIPT_PATH=$(dirname $(readlink -f "$0")) +source "$THIS_SCRIPT_PATH"/tools/build_helper # Set environment variables (OPENAIR_HOME, ...) set_openair_env @@ -38,19 +37,18 @@ set_openair_env gen_nvram_path=$OPENAIR_DIR/targets/bin conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -MSC_GEN=0 XFORMS="True" SKIP_SHARED_LIB_FLAG="False" UE_EXPANSION="False" -UESIM_EXPANSION="False" PRINT_STATS="False" VCD_TIMING="False" DEADLINE_SCHEDULER_FLAG_USER="" CPU_AFFINITY_FLAG_USER="False" #Only valid when low-latency flag is set to False REL="Rel15" HW="None" -TP="None" +TP="Ethernet" EPC=0 +VERBOSE_CI=0 VERBOSE_COMPILE=0 CFLAGS_PROCESSOR_USER="" RUN_GROUP=0 @@ -64,10 +62,14 @@ CMAKE_CMD="$CMAKE" UE_AUTOTEST_TRACE="False" UE_DEBUG_TRACE="False" UE_TIMING_TRACE="False" +NOAVX512="False" USRP_REC_PLAY="False" BUILD_ECLIPSE=0 NR="False" +ITTI_SIM="False" +SANITIZE_ADDRESS="False" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope msc" +RU=0 trap handle_ctrl_c INT function print_help() { @@ -102,6 +104,8 @@ Options Makes the NR softmodem --nrUE Makes the NR UE softmodem +--RU + Makes the OAI RRU --UE Makes the UE specific parts (ue_ip, usim, nvram) from the given configuration file --UE-conf-nvram [configuration file] @@ -113,7 +117,7 @@ Options -a | --agent Enables agent for software-defined control of the eNB -w | --hardware - EXMIMO, USRP, BLADERF, LMSSDR, IRIS, ADRV9371_ZC706, SIMU, None (Default) + EXMIMO, USRP, BLADERF, LMSSDR, IRIS, ADRV9371_ZC706, SIMU, AW2SORI, None (Default) Adds this RF board support (in external packages installation and in compilation) -P | --phy_simulators Makes the unitary tests Layer 1 simulators @@ -158,8 +162,12 @@ Options Build optional shared library, can be one or several of $OPTIONAL_LIBRARIES or \"all\" --usrp-recplay Build for I/Q record-playback modes +--noavx512 + Build without AVX512 if it is present on CPU -k | --skip-shared-libraries Skip build for shared libraries to reduce compilation time when building frequently for debugging purposes +--ittiSIM + Makes the itti simulator -h | --help Print this help @@ -201,28 +209,24 @@ function main() { -g | --run-with-gdb) case "$2" in "Release") - GDB=0 CMAKE_BUILD_TYPE="Release" echo_info "Will Compile without gdb symbols and with compiler optimization" CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Release" shift ;; "RelWithDebInfo") - GDB=0 CMAKE_BUILD_TYPE="RelWithDebInfo" echo_info "Will Compile with gdb symbols" - CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=RelWithDebInfo" + CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_EXPORT_COMPILE_COMMANDS=1" shift ;; "MinSizeRel") - GDB=0 CMAKE_BUILD_TYPE="MinSizeRel" echo_info "Will Compile for minimal exec size" CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=MinSizeRel" shift ;; "Debug" | *) - GDB=1 CMAKE_BUILD_TYPE="Debug" echo_info "Will Compile with gdb symbols and disable compiler optimization" CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Debug" @@ -245,9 +249,12 @@ function main() { shift;; --gNB) gNB=1 - NR="True" echo_info "Will compile gNB" shift;; + --RU) + RU=1 + echo_info "Will compile RRU" + shift;; -a | --agent) echo_info "FlexRAN support is always compiled into the eNB" shift;; @@ -257,22 +264,18 @@ function main() { shift;; --nrUE) nrUE=1 - NR="True" + rfsimNas=1 echo_info "Will compile NR UE" shift;; --mu) UE_EXPANSION="True" echo_info "Will compile with UE_EXPANSION" shift;; - --musim) - UESIM_EXPANSION="True" - echo_info "Will compile with UESIM_EXPANSION" - shift;; --UE-conf-nvram) - conf_nvram_path=$(readlink -f $2) + conf_nvram_path=$(readlink -f "$2") shift 2;; --UE-gen-nvram) - gen_nvram_path=$(readlink -f $2) + gen_nvram_path=$(readlink -f "$2") shift 2;; -w | --hardware) # Use OAI_USRP as the key word USRP is used inside UHD driver @@ -280,7 +283,7 @@ function main() { "EXMIMO") HW="EXMIMO" ;; - "USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "ADRV9371_ZC706" | "SIMU") + "USRP" | "BLADERF" | "LMSSDR" | "IRIS" | "ADRV9371_ZC706" | "SIMU" | "AW2SORI") HW="OAI_"$2 ;; "None") @@ -291,6 +294,9 @@ function main() { esac echo_info "Setting hardware to: $HW" shift 2;; + -t | --transport) + TP=$2 + shift 2;; -P | --phy_simulators) SIMUS_PHY=1 echo_info "Will compile dlsim, ulsim, ..." @@ -326,8 +332,12 @@ function main() { HWLAT_TEST=1 echo_info "Will compile hw latency test program" shift;; + --verbose-ci) + VERBOSE_CI=1 + echo_info "Will compile with verbose instructions in CI Docker env" + shift;; --verbose-compile) - VERBOSE_COMPILE=1 + VERBOSE_COMPILE=1 echo_info "Will compile with verbose instructions" shift;; --cflags_processor) @@ -410,6 +420,10 @@ function main() { USRP_REC_PLAY="True" echo_info "Enabling USRP record playback mode" shift 1;; + --noavx512) + NOAVX512="True" + echo_info "Disabling AVX512" + shift 1;; -k | --skip-shared-libraries) SKIP_SHARED_LIB_FLAG="True" echo_info "Skipping build of shared libraries, rfsimulator and transport protocol libraries" @@ -418,6 +432,14 @@ function main() { CMAKE_CMD="$CMAKE_CMD -GNinja" MAKE_CMD=ninja shift;; + --sanitize-address | -fsanitize=address) + SANITIZE_ADDRESS=True + shift;; + --ittiSIM) + ittiSIM=1 + ITTI_SIM="True" + echo_info "Will compile itti simulator" + shift;; -h | --help) print_help exit 1;; @@ -488,11 +510,6 @@ function main() { echo_info "Flags for Deadline scheduler: $DEADLINE_SCHEDULER_FLAG_USER" echo_info "Flags for CPU Affinity: $CPU_AFFINITY_FLAG_USER" - if [ -n "$UHD_IMAGES_DIR" ] && [ -z "$INSTALL_EXTERNAL" ]; then - echo_error "UHD images download settings will not be applied without -I present" - exit - fi - ####################################################### # Setting and printing OAI envs, we should check here # ####################################################### @@ -527,7 +544,7 @@ function main() { if [ "$HW" == "OAI_USRP" ] ; then echo_info "installing packages for USRP support" check_install_usrp_uhd_driver - if [ ! "$DISABLE_HARDWARE_DEPENDENCY" == "True" ]; then + if [ ! -v BUILD_UHD_FROM_SOURCE ] && [ ! "$DISABLE_HARDWARE_DEPENDENCY" == "True" ]; then install_usrp_uhd_driver $UHD_IMAGES_DIR fi fi @@ -549,9 +566,10 @@ function main() { # flash_firmware_iris #fi fi - echo_info "installing protobuf/protobuf-c for flexran agent support" + echo_info "Installing protobuf/protobuf-c for flexran agent support" install_protobuf_from_source install_protobuf_c_from_source + echo_success "protobuf/protobuf-c installation successful" fi if [ "$INSTALL_OPTIONAL" = "1" ] ; then @@ -580,7 +598,7 @@ function main() { config_libconfig_shlib=params_libconfig # first generate the CMakefile in the right directory - if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HW" = "EXMIMO" ] ; then + if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$RU" = "1" -o "$nrUE" = "1" -o "$HW" = "EXMIMO" -o "$ittiSIM" = "1" -o "$rfsimNas" = "1" ] ; then # softmodem compilation @@ -592,7 +610,6 @@ function main() { echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file # echo "set ( PHY_TX_THREAD $UE_EXPANSION )" >> $cmake_file echo "set ( PRE_SCD_THREAD $UE_EXPANSION )" >> $cmake_file - echo "set ( UESIM_EXPANSION $UESIM_EXPANSION )" >> $cmake_file echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file echo "set ( TRANSP_PRO \"${TP}\")" >> $cmake_file @@ -604,7 +621,10 @@ function main() { echo "set ( UE_DEBUG_TRACE $UE_DEBUG_TRACE )" >> $cmake_file echo "set ( UE_TIMING_TRACE $UE_TIMING_TRACE )" >> $cmake_file echo "set ( USRP_REC_PLAY $USRP_REC_PLAY )" >> $cmake_file + echo "set ( NOAVX512 $NOAVX512 )" >> $cmake_file echo "set ( SKIP_SHARED_LIB_FLAG $SKIP_SHARED_LIB_FLAG )" >> $cmake_file + echo "set ( ITTI_SIM $ITTI_SIM )" >> $cmake_file + echo "set ( SANITIZE_ADDRESS $SANITIZE_ADDRESS )" >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$build_dir/build eval $CMAKE_CMD @@ -619,6 +639,9 @@ function main() { if [ "$gNB" = "1" ] ; then execlist="$execlist nr-softmodem" fi + if [ "$RU" = "1" ] ; then + execlist="$execlist oairu" + fi if [ "$UE" = 1 ] ; then execlist="$execlist lte-uesoftmodem" fi @@ -626,6 +649,10 @@ function main() { execlist="$execlist nr-uesoftmodem" fi + if [ "$ittiSIM" = "1" ] ; then + execlist="$execlist nr-ittisim" + fi + for f in $execlist ; do echo_info "Compiling $f..." compilations \ @@ -643,28 +670,26 @@ function main() { $build_dir $config_libconfig_shlib \ lib$config_libconfig_shlib.so $dbin/lib$config_libconfig_shlib.so - compilations \ - $build_dir coding \ - libcoding.so $dbin/libcoding.so + compilations \ + $build_dir coding \ + libcoding.so $dbin/libcoding.so - compilations \ - $build_dir nasmesh \ - CMakeFiles/nasmesh/nasmesh.ko $dbin/nasmesh.ko - - compilations \ - $build_dir rb_tool \ - rb_tool $dbin/rb_tool - cp $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 $dbin fi - fi if [ "$UE" = 1 ] ; then echo_info "Compiling UE specific part" - compilations \ - $build_dir ue_ip \ - CMakeFiles/ue_ip/ue_ip.ko $dbin/ue_ip.ko + + if [ $IS_CONTAINER -eq 0 ] + then + echo_info "Building ue_ip module" + compilations \ + $build_dir ue_ip \ + CMakeFiles/ue_ip/ue_ip.ko $dbin/ue_ip.ko + else + echo_info "Bypassing ue_ip build" + fi #IS_CONTAINER # mkdir -p $DIR/at_commands/build # cd $DIR/at_commands/build @@ -831,7 +856,7 @@ function main() { #################################################### # Build RF device and transport protocol libraries # #################################################### - if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HWLAT" = "1" ] ; then + if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$RU" = "1" -o "$nrUE" = "1" -o "$HWLAT" = "1" ] ; then # build RF device libraries if [ "$HW" != "None" ] ; then @@ -895,6 +920,14 @@ function main() { echo_error "== FAILED == Unexpected Kernel $SYRIQ_KMAJ.$SYRIQ_KMIN" fi echo_info "liboai_device.so is linked to ADRV9371_ZC706 device library for Kernel $SYRIQ_KMAJ.$SYRIQ_KMIN" + elif [ "$HW" == "OAI_AW2SORI" ] ; then + compilations \ + $build_dir aw2sori_transpro \ + libaw2sori_transpro.so $dbin/libaw2sori_transpro.so.$REL + + ln -sf libaw2sori_transpro.so libthirdparty_transpro.so + ln -sf $dbin/libaw2sori_transpro.so.$REL $dbin/libaw2sori_transpro.so + echo_info "build libthirdparty_transpro.so for AW2SORI fronthaul" else echo_info "liboai_device.so is not linked to any device library" fi @@ -918,12 +951,30 @@ function main() { echo_info "Building transport protocol libraries" rm -f liboai_transpro.so rm -f $dbin/liboai_transpro.so - compilations \ - $build_dir oai_eth_transpro \ - liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL - ln -sf liboai_eth_transpro.so liboai_transpro.so - ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so - echo_info "liboai_transpro.so is linked to ETHERNET transport" + if [ "$TP" == "Ethernet" ]; then + compilations \ + $build_dir oai_eth_transpro \ + liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL + ln -sf liboai_eth_transpro.so liboai_transpro.so + ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to ETHERNET transport" + fi + if [ "$TP" == "benetel4g" ]; then + compilations \ + $build_dir benetel_4g \ + libbenetel_4g.so $dbin/libbenetel_4g.$REL + ln -sf libbenetel_4g.so liboai_transpro.so + ln -sf $dbin/libbenetel_4g.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to BENETEL4G transport" + fi + if [ "$TP" == "benetel5g" ]; then + compilations \ + $build_dir benetel_5g \ + libbenetel_5g.so $dbin/libbenetel_5g.$REL + ln -sf libbenetel_5g.so liboai_transpro.so + ln -sf $dbin/libbenetel_5g.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to BENETEL4G transport" + fi fi fi diff --git a/cmake_targets/doxygen/CMakeLists.txt b/cmake_targets/doxygen/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/cmake_targets/epc_test/CMakeLists.template b/cmake_targets/epc_test/CMakeLists.template old mode 100644 new mode 100755 diff --git a/cmake_targets/install_external_packages.ubuntu20 b/cmake_targets/install_external_packages.ubuntu20 new file mode 100755 index 0000000000..f0314ca575 --- /dev/null +++ b/cmake_targets/install_external_packages.ubuntu20 @@ -0,0 +1,510 @@ +#!/bin/bash +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +# brief +# authors Laurent Thomas +# +####################################### +if [ ! -f /etc/os-release ]; then + echo "No /etc/os-release file found. You're likely on an unsupported distro." + exit 1 +fi +OS_DISTRO=$(grep "^ID=" /etc/os-release | sed "s/ID=//" | sed "s/\"//g") +OS_RELEASE=$(grep "^VERSION_ID=" /etc/os-release | sed "s/VERSION_ID=//" | sed "s/\"//g") +case "$OS_DISTRO" in + ubuntu) OS_BASEDISTRO="debian"; INSTALLER="apt"; CMAKE="cmake" ;; +esac + +SUDO='sudo -E' + +############################### +## echo and family +############################### +black='\E[30m' +red='\E[31m' +green='\E[32m' +yellow='\E[33m' +blue='\E[1;34m' +magenta='\E[35m' +cyan='\E[36m' +white='\E[37m' +reset_color='\E[00m' +COLORIZE=1 + +cecho() { + # Color-echo + # arg1 = message + # arg2 = color + local default_msg="No Message." + message=${1:-$default_msg} + color=${2:-$green} + [ "$COLORIZE" = "1" ] && message="$color$message$reset_color" + echo -e "$message" + return +} + +echo_error() { cecho "$* $red" ;} +echo_fatal() { cecho "$* $red"; exit 1 ;} +echo_warning() { cecho "$* $yellow" ;} +echo_success() { cecho "$* $green" ;} +echo_info() { cecho "$* $blue" ;} + +######################## +# distribution helpers # +######################## + +# This function return a string to identify the distribution we are running +# Examples: +# ubuntu16.04 +# debian8.5 +get_distribution_release() { + echo "$OS_DISTRO$OS_RELEASE" +} + +check_supported_distribution() { + case $(get_distribution_release) in + "ubuntu20.04") return 0 ;; + "ubuntu20.10") return 0 ;; + "ubuntu21.04") return 0 ;; + esac + return 1 +} + +################## +# Error handlers # +################## + +handler_EXIT() { + local exit_code=$? + [ "$exit_code" -eq 0 ] || echo_error "build have failed" + exit $exit_code +} + +trap handler_EXIT EXIT + +########################### +# Cleaners +########################### + +clean_kernel() { + $SUDO modprobe ip_tables + $SUDO modprobe x_tables + $SUDO iptables -P INPUT ACCEPT + $SUDO iptables -F INPUT + $SUDO iptables -P OUTPUT ACCEPT + $SUDO iptables -F OUTPUT + $SUDO iptables -P FORWARD ACCEPT + $SUDO iptables -F FORWARD + $SUDO iptables -t nat -F + $SUDO iptables -t mangle -F + $SUDO iptables -t filter -F + $SUDO iptables -t raw -F + echo_info "Flushed iptables" + $SUDO rmmod nasmesh > /dev/null 2>&1 + $SUDO rmmod oai_nw_drv > /dev/null 2>&1 + $SUDO rmmod openair_rf > /dev/null 2>&1 + $SUDO rmmod ue_ip > /dev/null 2>&1 + echo_info "removed drivers from kernel" +} + +clean_all_files() { + set_openair_env + rm -rf "$OPENAIR_DIR"/targets/bin/* + dir="$OPENAIR_DIR/cmake_targets" + rm -rf "$dir"/log/* + rm -rf "$dir"/ran_build/build + rm -rf "$dir"/ran_build_noLOG/build + rm -rf "$dir"/lte-simulators/build + rm -rf "$dir"/phy_simulators/build + rm -rf "$dir"/nas_sim_tools/build + rm -rf "$dir"/oaisim_build_oai/build + rm -rf "$dir"/oaisim_build_oai/CMakeLists.txt + rm -rf "$dir"/autotests/bin + rm -rf "$dir"/autotests/log + rm -rf "$dir"/autotests/*/build +} + +############################################ +# External packages installers +############################################ + +install_protobuf_from_source(){ + protobuf_install_log=$OPENAIR_DIR/cmake_targets/log/protobuf_install_log.txt + echo_info "\nInstalling Google Protobuf from sources. The log file for Protobuf installation is here: $protobuf_install_log " + ( + cd /tmp || exit + echo "Downloading protobuf" + #rm -rf /tmp/protobuf-2.6.1.tar.gz* /tmp/protobuf-2.6.1 + #wget https://github.com/protocolbuffers/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz + #tar -xzvf protobuf-2.6.1.tar.gz --owner $USER --group $USER --no-same-owner + #cd protobuf-2.6.1/ + rm -rf /tmp/protobuf-cpp-3.3.0.tar.gz* /tmp/protobuf-3.3.0 + wget --tries=3 --retry-connrefused https://github.com/protocolbuffers/protobuf/releases/download/v3.3.0/protobuf-cpp-3.3.0.tar.gz + tar -xzvf protobuf-cpp-3.3.0.tar.gz --owner "$USER" --group "$(groups | cut -d" " -f1)" --no-same-owner + cd protobuf-3.3.0/ || exit + ./configure + echo "Compiling protobuf" + make -j"$(nproc)" + $SUDO make install + $SUDO ldconfig + ) >& "$protobuf_install_log" +} + +install_protobuf_c_from_source(){ + protobuf_c_install_log=$OPENAIR_DIR/cmake_targets/log/protobuf_c_install_log.txt + echo_info "\nInstalling Google Protobuf_C from sources. The log file for Protobuf_C installation is here: $protobuf_c_install_log " + ( + if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "centos" ]]; then + export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig + fi + cd /tmp || exit + echo "Downloading protobuf-c" + rm -rf /tmp/protobuf-c + git clone https://github.com/protobuf-c/protobuf-c.git + cd protobuf-c || exit + git checkout 2a46af42784abf86804d536f6e0122d47cfeea45 + ./autogen.sh + ./configure + echo "Compiling protobuf-c" + make -j"$(nproc)" + $SUDO make install + $SUDO ldconfig + ) >& "$protobuf_c_install_log" +} + +install_usrp_uhd_driver_from_source(){ + uhd_install_log=$OPENAIR_DIR/cmake_targets/log/uhd_install_log.txt + echo_info "\nInstalling UHD driver from sources. The log file for UHD driver installation is here: $uhd_install_log " + ( + cd /tmp || exit + echo "Downloading UHD driver" + rm -rf /tmp/uhd + git clone https://github.com/EttusResearch/uhd.git + cd uhd || exit + git checkout UHD-3.15.LTS + mkdir -p host/build + cd host/build || exit + $CMAKE ../ -GNinja + echo "Compiling UHD" + ninja + $SUDO ninja install + $SUDO ldconfig + $SUDO /usr/lib/uhd/utils/uhd_images_downloader.py + ) >& "$uhd_install_log" +} + +install_bladerf_driver_from_source(){ + bladerf_install_log=$OPENAIR_DIR/cmake_targets/log/bladerf_install_log.txt + echo_info "\nInstalling BladeRF driver from sources. The log file for BladeRF driver installation is here: $bladerf_install_log " + ( + cd /tmp || exit + echo "Downloading BladeRF driver" + rm -rf /tmp/bladeRF + git clone https://github.com/Nuand/bladeRF.git + cd bladeRF || exit + git checkout tags/2016.06 + mkdir -p build + cd build || exit + $CMAKE ../ + echo "Compiling BladeRF driver" + make -j"$(nproc)" + $SUDO make install + $SUDO ldconfig + echo "Downloading FPGA and firmware images" + cd /tmp/bladeRF || exit + wget --tries=3 --retry-connrefused https://www.nuand.com/fx3/bladeRF_fw_latest.img + wget --tries=3 --retry-connrefused https://www.nuand.com/fpga/hostedx40-latest.rbf + sudo mkdir -p /usr/share/Nuand/bladeRF + sudo mv bladeRF_fw_latest.img /usr/share/Nuand/bladeRF/bladeRF_fw.img + sudo mv hostedx40-latest.rbf /usr/share/Nuand/bladeRF/hostedx40.rbf + ) >& "$bladerf_install_log" +} + +check_install_bladerf_driver(){ + if [[ "$OS_DISTRO" == "ubuntu" ]]; then + $SUDO apt-get install -y bladerf libbladerf-dev + $SUDO apt-get install -y bladerf-firmware-fx3 + $SUDO apt-get install -y bladerf-fpga-hostedx40 + elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then + install_bladerf_driver_from_source + else + echo_error "BladeRF Installer for OAI does not support automatic build. Install BladeRF compiling sources manually from BladeRF website" + fi +} + +flash_firmware_bladerf() { + $SUDO bladeRF-cli --flash-firmware /usr/share/Nuand/bladeRF/bladeRF_fw.img +} + +install_soapy_from_source(){ + soapy_install_log=$OPENAIR_DIR/cmake_targets/log/soapy_install_log.txt + echo_info "\nInstalling Soapy EcoSystem from source. The log file for Soapy installation is here: $soapy_install_log " + ( + cd /tmp || exit + echo "Downloading SoapySDR" + rm -rf /tmp/soapysdr + git clone -b soapy-sdr-0.7.0 --single-branch https://github.com/pothosware/SoapySDR.git + cd SoapySDR || exit + #git checkout tags/release_003_010_001_001 + mkdir -p build + cd build || exit + $CMAKE ../ + echo "Compiling SoapySDR" + make -j"$(nproc)" + $SUDO make install + $SUDO ldconfig + cd /tmp || exit + echo "Downloading SoapyRemote" + rm -rf /tmp/soapyremote + git clone -b soapy-remote-0.5.0 --single-branch https://github.com/pothosware/SoapyRemote.git + cd SoapyRemote || exit + #git checkout tags/release_003_010_001_001 + mkdir -p build + cd build || exit + cmake ../ + echo "Compiling SoapyRemote" + make -j"$(nproc)" + $SUDO make install + $SUDO ldconfig + ) >& "$soapy_install_log" +} + +install_soapy_iris_from_source(){ + iris_install_log=$OPENAIR_DIR/cmake_targets/log/iris_install_log.txt + echo_info "\nInstalling Iris driver from source. The log file for Iris driver installation is here: $iris_install_log " + ( + cd /tmp || exit + echo "Downloading SoapyIris" + rm -rf /tmp/sklk-soapyiris + git clone -b soapy-iris-2018.08.0.1 --single-branch https://github.com/skylarkwireless/sklk-soapyiris.git + cd sklk-soapyiris || exit + mkdir -p build + cd build ||exit + cmake ../ + echo "Compiling SoapyIris" + make -j"$(nproc)" + $SUDO make install + $SUDO ldconfig + ) >& "$iris_install_log" +} + +check_install_soapy () { + #if [[ "$OS_DISTRO" == "ubuntu" ]]; then + #first we remove old installation + $SUDO apt-get remove -y soapysdr soapysdr-server libsoapysdr-dev python-soapysdr python3-soapysdr soapysdr-module-remote || true + #$SUDO add-apt-repository -y ppa:myriadrf/drivers + #$SUDO apt-get update + #$SUDO apt-get install -y soapysdr soapysdr-server libsoapysdr-dev python-soapysdr python3-soapysdr soapysdr-module-remote + + #elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then + # $SUDO $INSTALLER -y install software-properties-common python3-software-properties python-software-properties subversion git python3 python-numpy python3-numpy cmake swig python-dev + install_soapy_from_source + #fi + install_soapy_iris_from_source + +} + +check_install_ubuntu_packages() { + $SUDO $INSTALLER update -y + if [[ "$OS_DISTRO" == "ubuntu" ]]; then + local LAPACK_LIBNAME="liblapack.so" + local LAPACK_TARGET="/usr/lib/atlas-base/atlas/liblapack.so" + $SUDO apt install -y software-properties-common + case "$(get_distribution_release)" in + "ubuntu20.04") + specific_packages="libtasn1-6-dev libgnutls28-dev iproute2 libconfig-dev" + LAPACK_LIBNAME="liblapack.so-x86_64-linux-gnu" + LAPACK_TARGET="/usr/lib/x86_64-linux-gnu/atlas/liblapack.so" + ;; + "ubuntu21.04") + specific_packages="libtasn1-6-dev libgnutls28-dev iproute2 libconfig-dev" + LAPACK_LIBNAME="liblapack.so-x86_64-linux-gnu" + LAPACK_TARGET="/usr/lib/x86_64-linux-gnu/atlas/liblapack.so" + ;; + esac + $SUDO $INSTALLER install -y \ + $specific_packages \ + check \ + dialog \ + dkms \ + gawk \ + libboost-all-dev \ + libpthread-stubs0-dev \ + openvpn \ + pkg-config \ + python3-dev \ + sshfs \ + swig \ + tshark \ + uml-utilities \ + unzip \ + valgrind \ + vlan \ + exuberant-ctags \ + ntpdate \ + iperf3 \ + android-tools-adb \ + wvdial \ + sshpass \ + nscd \ + bc \ + ntp \ + python3-scipy \ + python3-matplotlib \ + bison \ + build-essential \ + cmake \ + cmake-curses-gui \ + ninja-build \ + doxygen \ + doxygen-gui \ + texlive-latex-base \ + ethtool \ + flex \ + gdb \ + git \ + graphviz \ + gtkwave \ + iperf \ + iptables \ + libxtables-dev \ + libatlas-base-dev \ + libblas-dev \ + liblapack-dev\ + liblapacke-dev\ + libffi-dev \ + libforms-bin \ + libforms-dev \ + libgcrypt20-dev \ + libgmp-dev \ + libgtk-3-dev \ + libidn2-0-dev \ + libidn11-dev \ + libmysqlclient-dev \ + libpython2.7-dev \ + libsctp1 \ + libsctp-dev \ + libssl-dev \ + libtool \ + libusb-1.0-0-dev \ + libxml2 \ + libxml2-dev \ + libxslt1-dev \ + mscgen \ + octave-signal \ + openssh-client \ + openssh-server \ + openssl \ + python3 \ + subversion \ + xmlstarlet \ + python3-pip \ + libyaml-dev \ + wget \ + libxpm-dev \ + libboost-all-dev \ + nettle-dev \ + nettle-bin \ + libreadline-dev + fi + + $SUDO update-alternatives --set "$LAPACK_LIBNAME" "$LAPACK_TARGET" + +} + +install_asn1c_from_source(){ + asn1_install_log=$OPENAIR_DIR/cmake_targets/log/asn1c_install_log.txt + echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_log " + ( + $SUDO rm -rf /tmp/asn1c + # GIT_SSL_NO_VERIFY=true git clone https://gitlab.eurecom.fr/oai/asn1c.git /tmp/asn1c + git clone https://gitlab.eurecom.fr/oai/asn1c.git /tmp/asn1c + cd /tmp/asn1c || exit + # better to use a given commit than a branch in case the branch + # is updated and requires modifications in the source of OAI + #git checkout velichkov_s1ap_plus_option_group + git checkout f12568d617dbf48497588f8e227d70388fa217c9 + autoreconf -iv + ./configure + make -j"$(nproc)" + $SUDO make install + cd - || exit + $SUDO ldconfig + ) > "$asn1_install_log" 2>&1 +} + +################################################# +# 2. compile +################################################ + +install_nas_tools() { + echo_success "generate .ue_emm.nvram .ue.nvram" + ./nvram --gen -c "$1" -o "$2" + ./usim --gen -c "$1" -o "$2" +} + + +################################ +# set_openair_env +############################### +set_openair_env(){ + fullpath=$(readlink -f "${BASH_SOURCE[0]}") + [ -f "/.$fullpath" ] || fullpath=$(readlink -f "$PWD/$fullpath") + openair_path=${fullpath%/cmake_targets/*} + openair_path=${openair_path%/targets/*} + openair_path=${openair_path%/openair[123]/*} + export OPENAIR_DIR=$openair_path + export OPENAIR1_DIR=$openair_path/openair1 + export OPENAIR2_DIR=$openair_path/openair2 + export OPENAIR3_DIR=$openair_path/openair3 + export OPENAIR_TARGETS=$openair_path/targets +} + +if ! check_supported_distribution; then + echo_error "Your distribution $(get_distribution_release) is not supported by oai !" + exit 1 +fi + +echo_info "Installing packages" +check_install_ubuntu_packages + +echo_info "installing ASN.1 compiler" +install_asn1c_from_source + +echo_info "installing protobuf/protobuf-c for flexran agent support" +install_protobuf_from_source +install_protobuf_c_from_source + +if [ "$1" == "USRP" ] ; then + echo_info "installing packages for USRP support" + install_usrp_uhd_driver +fi +if [ "$1" == "BLADERF" ] ; then + echo_info "installing packages for BLADERF support" + check_install_bladerf_driver + flash_firmware_bladerf +fi +if [ "$1" == "IRIS" ] ; then + echo_info "installing packages for IRIS support" + check_install_soapy + # flash_firmware_iris +fi diff --git a/cmake_targets/nas_sim_tools/CMakeLists.txt b/cmake_targets/nas_sim_tools/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/cmake_targets/phy_simulators/CMakeLists.txt b/cmake_targets/phy_simulators/CMakeLists.txt old mode 100644 new mode 100755 index 5f2d34883e..b3e4267060 --- a/cmake_targets/phy_simulators/CMakeLists.txt +++ b/cmake_targets/phy_simulators/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 2.8) +project (OpenAirInterface) set ( CMAKE_BUILD_TYPE ) set ( CFLAGS_PROCESSOR_USER "" ) set ( UE_EXPANSION False ) set ( PRE_SCD_THREAD False ) -set ( UESIM_EXPANSION False ) set ( ENABLE_VCD_FIFO False ) -set ( RF_BOARD "OAI_USRP") +set ( RF_BOARD "None") set ( TRANSP_PRO "None") set ( PACKAGE_NAME "") set ( DEADLINE_SCHEDULER "False" ) @@ -15,5 +15,8 @@ set ( UE_AUTOTEST_TRACE False ) set ( UE_DEBUG_TRACE False ) set ( UE_TIMING_TRACE False ) set ( USRP_REC_PLAY False ) +set ( NOAVX512 True ) set ( SKIP_SHARED_LIB_FLAG False ) +set ( PHYSIM True) +set ( RU 0) include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt) diff --git a/cmake_targets/s1c_mme_test/CMakeLists.template b/cmake_targets/s1c_mme_test/CMakeLists.template old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/Kbuild.cmake b/cmake_targets/tools/Kbuild.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/CMakeParseArguments.cmake b/cmake_targets/tools/MODULES/CMakeParseArguments.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/CMakeUserFindMySQL.cmake b/cmake_targets/tools/MODULES/CMakeUserFindMySQL.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/CMakeUserUseBison.cmake b/cmake_targets/tools/MODULES/CMakeUserUseBison.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/CMakeUserUseFlex.cmake b/cmake_targets/tools/MODULES/CMakeUserUseFlex.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindFreeDiameter.cmake b/cmake_targets/tools/MODULES/FindFreeDiameter.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindGCCXML.cmake b/cmake_targets/tools/MODULES/FindGCCXML.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindGcrypt.cmake b/cmake_targets/tools/MODULES/FindGcrypt.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindGnuTLS.cmake b/cmake_targets/tools/MODULES/FindGnuTLS.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindKbuild.cmake b/cmake_targets/tools/MODULES/FindKbuild.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindLibXml2.cmake b/cmake_targets/tools/MODULES/FindLibXml2.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindMySQL.cmake b/cmake_targets/tools/MODULES/FindMySQL.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindNettle.cmake b/cmake_targets/tools/MODULES/FindNettle.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindPostgreSQL.cmake b/cmake_targets/tools/MODULES/FindPostgreSQL.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/FindSCTP.cmake b/cmake_targets/tools/MODULES/FindSCTP.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/Kbuild.cmake b/cmake_targets/tools/MODULES/Kbuild.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/cmake_useful.cmake b/cmake_targets/tools/MODULES/cmake_useful.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/kbuild_system.cmake b/cmake_targets/tools/MODULES/kbuild_system.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/kmodule.cmake b/cmake_targets/tools/MODULES/kmodule.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/MODULES/path_prefixes.cmake b/cmake_targets/tools/MODULES/path_prefixes.cmake old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/asn1tostruct.py b/cmake_targets/tools/asn1tostruct.py old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index b8f0125b10..06f32183b7 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -40,7 +40,15 @@ esac KERNEL_VERSION=$(uname -r | cut -d '.' -f1) KERNEL_MAJOR=$(uname -r | cut -d '.' -f2) -SUDO='sudo -E' +#check if we run inside a container +IS_CONTAINER=`egrep -c "docker|podman|kubepods|libpod|buildah" /proc/self/cgroup || true` +#sudo is not needed when we are root +if [ "$UID" = 0 ] +then + SUDO='' +else + SUDO='sudo -S -E' +fi ############################### ## echo and family @@ -104,6 +112,14 @@ check_supported_distribution() { "rhel7") return 0 ;; "rhel7.6") return 0 ;; "rhel7.7") return 0 ;; + "rhel7.8") return 0 ;; + "rhel7.9") return 0 ;; + "rhel8.2") return 0 ;; + "rhel8.3") return 0 ;; + "rhel8.4") return 0 ;; + "rhel8.5") return 0 ;; + "rhel8.6") return 0 ;; + "rhel8.7") return 0 ;; "centos7") return 0 ;; esac return 1 @@ -209,6 +225,11 @@ compilations() { ret=$? } > $dlog/$2.$REL.txt 2>&1 set -e + if [ "$VERBOSE_CI" == "1" ]; then + echo_info "====== Start of log for $2.$REL.txt ======" + cat $dlog/$2.$REL.txt + echo_info "====== End of log for $2.$REL.txt ======" + fi if [[ $ret -ne 0 ]]; then check_warnings "$dlog/$2.$REL.txt" check_errors "$dlog/$2.$REL.txt" @@ -238,18 +259,33 @@ install_protobuf_from_source(){ cd /tmp echo "Downloading protobuf" #rm -rf /tmp/protobuf-2.6.1.tar.gz* /tmp/protobuf-2.6.1 - #wget https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz + #wget https://github.com/protocolbuffers/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz #tar -xzvf protobuf-2.6.1.tar.gz --owner $USER --group $USER --no-same-owner #cd protobuf-2.6.1/ - rm -rf /tmp/protobuf-cpp-3.3.0.tar.gz* /tmp/protobuf-3.3.0 - wget --tries=3 --retry-connrefused https://github.com/google/protobuf/releases/download/v3.3.0/protobuf-cpp-3.3.0.tar.gz - tar -xzvf protobuf-cpp-3.3.0.tar.gz --owner $USER --group $(groups | cut -d" " -f1) --no-same-owner - cd protobuf-3.3.0/ + + if [ $IS_CONTAINER -eq 0 ] + then + rm -rf /tmp/protobuf-cpp-3.3.0.tar.gz* /tmp/protobuf-3.3.0 + wget --tries=3 --retry-connrefused https://github.com/protocolbuffers/protobuf/releases/download/v3.3.0/protobuf-cpp-3.3.0.tar.gz + tar -xzvf protobuf-cpp-3.3.0.tar.gz --owner $(id -u) --group $(id -g) --no-same-owner + cd protobuf-3.3.0/ + else + export LD_LIBRARY_PATH=/usr/local/lib #protoc needs to know where toclook for shared libs + rm -rf /tmp/protobuf + git clone --depth=1 --branch=v3.3.0 https://github.com/protocolbuffers/protobuf.git /tmp/protobuf + cd /tmp/protobuf + git submodule update --init --recursive + ./autogen.sh + fi ./configure echo "Compiling protobuf" make -j`nproc` $SUDO make install $SUDO ldconfig + if [[ -v CI_ENV ]]; then + cd /tmp + $SUDO rm -rf protobuf* + fi ) >& $protobuf_install_log } @@ -272,6 +308,10 @@ install_protobuf_c_from_source(){ make -j`nproc` $SUDO make install $SUDO ldconfig + if [[ -v CI_ENV ]]; then + cd /tmp + $SUDO rm -rf protobuf* + fi ) >& $protobuf_c_install_log } @@ -279,30 +319,59 @@ install_usrp_uhd_driver_from_source(){ uhd_install_log=$OPENAIR_DIR/cmake_targets/log/uhd_install_log.txt echo_info "\nInstalling UHD driver from sources. The log file for UHD driver installation is here: $uhd_install_log " ( - cd /tmp - echo "Downloading UHD driver" + pushd /tmp + echo "Cloning UHD driver repository" rm -rf /tmp/uhd git clone https://github.com/EttusResearch/uhd.git cd uhd - git checkout tags/v3.13.0.2 + if [[ -v UHD_VERSION ]]; then + git checkout tags/v${UHD_VERSION} + else + git checkout tags/v4.0.0.0 + fi mkdir -p host/build - cd host/build - $CMAKE ../ + cd host/build || true + $CMAKE ../ -GNinja echo "Compiling UHD" - make -j`nproc` - make test - $SUDO make install - $SUDO ldconfig + ninja + $SUDO ninja install + $SUDO ldconfig -v + if [ $IS_CONTAINER -eq 0 ]; then + if [[ "$OS_DISTRO" == "ubuntu" ]]; then + $SUDO /usr/local/lib/uhd/utils/uhd_images_downloader.py + fi + if [[ "$OS_DISTRO" == "rhel" ]]; then + $SUDO /usr/local/lib64/uhd/utils/uhd_images_downloader.py + fi + fi + popd + rm -rf /tmp/uhd ) >& $uhd_install_log } check_install_usrp_uhd_driver(){ if [[ "$OS_DISTRO" == "ubuntu" ]]; then #first we remove old installation - $SUDO apt-get remove -y uhd || true - $SUDO apt-get remove libuhd-dev libuhd003 uhd-host -y || true + $SUDO apt-get remove uhd -y || true + $SUDO apt-get remove uhd-host -y || true + $SUDO apt-get remove libuhd-dev -y || true + $SUDO apt-get remove libuhd003 -y || true + $SUDO apt-get remove libuhd3.13.1 -y || true + $SUDO apt-get remove libuhd3.14.0 -y || true + $SUDO apt-get remove libuhd3.14.1 -y || true + $SUDO apt-get remove libuhd3.15.0 -y || true + local distribution=$(get_distribution_release) + if [[ "$distribution" == "ubuntu18.04" ]]; then + $SUDO apt-get remove libuhd4.0.0 -y || true + $SUDO apt-get remove libuhd4.1.0 -y || true + fi v=$(lsb_release -cs) $SUDO apt-add-repository --remove "deb http://files.ettus.com/binaries/uhd/repo/uhd/ubuntu/$v $v main" + if [[ -v BUILD_UHD_FROM_SOURCE ]]; then + $SUDO apt-get install -y libboost-all-dev libusb-1.0-0-dev doxygen python3-docutils python3-mako python3-numpy python3-requests python3-setuptools ninja-build + install_usrp_uhd_driver_from_source + return + fi # The new USRP repository # Raphael Defosseux: Adding a loop on adding PPA because in CI the gpg key retrieve may # timeout due to proxy / network latencies in Eurecom on VM @@ -322,13 +391,27 @@ check_install_usrp_uhd_driver(){ done $SUDO apt-get update $SUDO apt-get -y install python python-tk libboost-all-dev libusb-1.0-0-dev - $SUDO apt-get -y install libuhd-dev libuhd003 uhd-host + if [[ "$distribution" == "ubuntu16.04" ]]; then + $SUDO apt-get -y install libuhd-dev libuhd3.15.0 uhd-host + fi + if [[ "$distribution" == "ubuntu18.04" ]]; then + $SUDO apt-get -y install libuhd-dev libuhd4.1.0 uhd-host + fi elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then - $SUDO $INSTALLER -y install python boost libusb-devel libusbx-devel boost-devel python-mako python-docutils cmake - $SUDO -H pip install requests + if [ $IS_CONTAINER -eq 0 ] + then + $SUDO $INSTALLER -y install python boost libusb-devel libusbx-devel boost-devel python-mako python-docutils $CMAKE + $SUDO -H pip install requests + else + $SUDO $INSTALLER -y install boost boost-devel $CMAKE + $SUDO pip3 install mako requests + fi if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "centos" ]]; then - # until EPEL repo hasn't bumped UHD driver to >=3.10 in EPEL, build driver from source - $SUDO $INSTALLER -y remove uhd uhd-devel uhd-firmware + if [ $IS_CONTAINER -eq 0 ] + then + # until EPEL repo hasn't bumped UHD driver to >=3.10 in EPEL, build driver from source + $SUDO $INSTALLER -y remove uhd uhd-devel uhd-firmware + fi install_usrp_uhd_driver_from_source else $SUDO $INSTALLER -y install uhd uhd-devel uhd-firmware @@ -446,7 +529,7 @@ install_soapy_from_source(){ #git checkout tags/release_003_010_001_001 mkdir -p build cd build - cmake ../ + $CMAKE ../ echo "Compiling SoapyRemote" make -j`nproc` $SUDO make install @@ -465,7 +548,7 @@ install_soapy_iris_from_source(){ cd sklk-soapyiris mkdir -p build cd build - cmake ../ + $CMAKE ../ echo "Compiling SoapyIris" make -j`nproc` $SUDO make install @@ -642,8 +725,9 @@ check_install_oai_software() { automake \ bison \ build-essential \ - cmake \ + $CMAKE \ cmake-curses-gui \ + curl \ ninja-build \ doxygen \ doxygen-gui \ @@ -750,6 +834,8 @@ check_install_oai_software() { libxml2 \ libxml2-devel \ libxslt-devel \ + ninja-build \ + make \ openssh-clients \ openssh-server \ openssl \ @@ -795,6 +881,9 @@ install_asn1c_from_source(){ $SUDO make install cd - $SUDO ldconfig + if [[ -v CI_ENV ]]; then + $SUDO rm -rf /tmp/asn1c + fi ) > $asn1_install_log 2>&1 } diff --git a/cmake_targets/tools/example_enb_exmimo_mme_hss.txt b/cmake_targets/tools/example_enb_exmimo_mme_hss.txt old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/example_oaisim_enb_ue_mme_virtual.txt b/cmake_targets/tools/example_oaisim_enb_ue_mme_virtual.txt old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/exmimo2_2arxg.lime b/cmake_targets/tools/exmimo2_2arxg.lime old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/exmimo2_2brxg.lime b/cmake_targets/tools/exmimo2_2brxg.lime old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/exmimo_stop_octave.m b/cmake_targets/tools/exmimo_stop_octave.m old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/fix_asn1.data/RRC.rel10/SystemInformation-r8-IEs.h.diff b/cmake_targets/tools/fix_asn1.data/RRC.rel10/SystemInformation-r8-IEs.h.diff old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/fix_asn1.data/RRC.rel14/SystemInformation-NB-r13-IEs.h.diff b/cmake_targets/tools/fix_asn1.data/RRC.rel14/SystemInformation-NB-r13-IEs.h.diff old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/fix_asn1.data/RRC.rel14/SystemInformation-r8-IEs.h.diff b/cmake_targets/tools/fix_asn1.data/RRC.rel14/SystemInformation-r8-IEs.h.diff old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/X2ap-CriticalityDiagnostics-IE-List.h.diff b/cmake_targets/tools/fix_asn1.data/X2AP.rel11.2/X2ap-CriticalityDiagnostics-IE-List.h.diff old mode 100644 new mode 100755 diff --git a/cmake_targets/tools/make_asn1c_includes.sh b/cmake_targets/tools/make_asn1c_includes.sh index cf18f0fa3e..00c88d6497 100755 --- a/cmake_targets/tools/make_asn1c_includes.sh +++ b/cmake_targets/tools/make_asn1c_includes.sh @@ -1,13 +1,19 @@ #!/bin/bash -GENERATED_FULL_DIR=$1 -shift -ASN1_SOURCE_DIR=$1 -shift export ASN1C_PREFIX=$1 shift -options=$* +options=$1 +shift +GENERATED_FULL_DIR=$1 +shift +ASN1_SOURCE_DIR=$* done_flag="$GENERATED_FULL_DIR"/done -if [ "$done_flag" -ot $ASN1_SOURCE_DIR ] ; then +rebuild=0 +for f in $ASN1_SOURCE_DIR ; do + if [ "$done_flag" -ot "$f" ] ; then + rebuild=1 + fi +done +if [ $rebuild -eq 1 ] ; then rm -f "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}*.c "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}*.h mkdir -p "$GENERATED_FULL_DIR" asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example $options -D $GENERATED_FULL_DIR $ASN1_SOURCE_DIR |& egrep -v "^Copied|^Compiled" | sort -u @@ -19,6 +25,10 @@ if [ "$done_flag" -ot $ASN1_SOURCE_DIR ] ; then sed -i 's/18446744073709551615))/18446744073709551615U))/g' "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}E-RABUsageReportItem.c sed -i 's/18446744073709551615 }/18446744073709551615U }/g' "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}E-RABUsageReportItem.c fi + if [ "$ASN1C_PREFIX" = "NGAP_" ] ; then + sed -i 's/18446744073709551615))/18446744073709551615U))/g' "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}VolumeTimedReport-Item.c + sed -i 's/18446744073709551615 }/18446744073709551615U }/g' "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}VolumeTimedReport-Item.c + fi fi touch $done_flag diff --git a/cmake_targets/tools/run_enb_s1_usrp b/cmake_targets/tools/run_enb_s1_usrp index e119126683..1a4c6b10b8 100755 --- a/cmake_targets/tools/run_enb_s1_usrp +++ b/cmake_targets/tools/run_enb_s1_usrp @@ -101,7 +101,6 @@ function main() local -i run_gdb=0 local -i show_stdout=0 local exe_arguments="" - local itti_dump_file="" until [ -z "$1" ] do @@ -154,18 +153,6 @@ function main() exe_arguments="$exe_arguments --rf-config-file=$rf_config_file" fi ;; - -K | --itti-dump-file) - itti_dump_file=$2 - # can omit file name if last arg on the line - if [ "x$itti_dump_file" = "x" ]; then - itti_dump_file="/tmp/enb_s1_usrp_itti.log" - shift 1; - else - shift 2; - fi - echo "setting ITTI dump file to: $itti_dump_file" - exe_arguments="$exe_arguments -K $itti_dump_file" - ;; -m | --mscgen) g_msc_dir=$2 # can omit file name if last arg on the line diff --git a/cmake_targets/tools/setup_routes.sh b/cmake_targets/tools/setup_routes.sh new file mode 100755 index 0000000000..67fe250be7 --- /dev/null +++ b/cmake_targets/tools/setup_routes.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +for i in $(seq 1 $1); +do + let table=1000+$i + echo "sudo ip route add 10.0.1.0/24 dev oaitun_ue$i table $table" + sudo ip route add 10.0.1.0/24 dev oaitun_ue$i table $table + echo "sudo ip route add default via 10.0.1.1 dev oaitun_ue$i table $table" + sudo ip route add default via 10.0.1.1 dev oaitun_ue$i table $table + let octet=$i+1 + echo "sudo ip rule add from 10.0.1.$octet table $table" + sudo ip rule add from 10.0.1.$octet table $table +done diff --git a/cmake_targets/tools/test_helper b/cmake_targets/tools/test_helper old mode 100644 new mode 100755 diff --git a/common/config/config_cmdline.c b/common/config/config_cmdline.c index 6d01d98c65..f5dfae06b6 100644 --- a/common/config/config_cmdline.c +++ b/common/config/config_cmdline.c @@ -211,7 +211,7 @@ int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix) while (c > 0 ) { char *oneargv = strdup(config_get_if()->argv[i]); /* we use strtok_r which modifies its string paramater, and we don't want argv to be modified */ - + if(!oneargv) abort(); /* first check help options, either --help, -h or --help_
*/ if (strncmp(oneargv, "-h",2) == 0 || strncmp(oneargv, "--help",6) == 0 ) { char *tokctx = NULL; @@ -255,7 +255,7 @@ int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix) if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */ ((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) || /* long option beginning with "--" */ ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgoptions[n].optname) == 0) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) || - ((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 ) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ) { + ((strlen(oneargv) > 2) && (strcmp(oneargv + 2, cfgoptions[n].optname) == 0 ) && (cfgoptions[n].paramflags & PARAMFLAG_CMDLINE_NOPREFIXENABLED )) ) { char *valptr=NULL; int ret; config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED; diff --git a/common/config/config_load_configmodule.c b/common/config/config_load_configmodule.c index 61a3984347..740c6e240b 100644 --- a/common/config/config_load_configmodule.c +++ b/common/config/config_load_configmodule.c @@ -43,7 +43,7 @@ #include "config_userapi.h" #include "../utils/LOG/log.h" #define CONFIG_SHAREDLIBFORMAT "libparams_%s.so" - +#include "nfapi/oai_integration/vendor_ext.h" int load_config_sharedlib(configmodule_interface_t *cfgptr) { void *lib_handle; @@ -331,9 +331,10 @@ void end_configmodule(void) { printf ("[CONFIG] free %u config value pointers\n",cfgptr->numptrs); for(int i=0; inumptrs ; i++) { - if (cfgptr->ptrs[i] != NULL) { + if (cfgptr->ptrs[i] != NULL && cfgptr->ptrsAllocated[i] == true) { free(cfgptr->ptrs[i]); cfgptr->ptrs[i]=NULL; + cfgptr->ptrsAllocated[i] = false; } } diff --git a/common/config/config_load_configmodule.h b/common/config/config_load_configmodule.h index d0309c62c3..0688f6531f 100644 --- a/common/config/config_load_configmodule.h +++ b/common/config/config_load_configmodule.h @@ -36,6 +36,8 @@ #include #include +#include +#include #include "common/config/config_paramdesc.h" #include "common/utils/T/T.h" #define CONFIG_MAX_OOPT_PARAMS 10 // maximum number of parameters in the -O option (-O :P1:P2... @@ -74,15 +76,18 @@ typedef struct configmodule_interface { uint32_t numptrs; uint32_t rtflags; char *ptrs[CONFIG_MAX_ALLOCATEDPTRS]; + bool ptrsAllocated[CONFIG_MAX_ALLOCATEDPTRS]; } configmodule_interface_t; #ifdef CONFIG_LOADCONFIG_MAIN configmodule_interface_t *cfgptr=NULL; -static char config_helpstr [] = "\n lte-softmodem -O [config mode]<:dbgl[debugflags]> \n \ - debugflags can also be defined in the config_libconfig section of the config file\n \ +static char config_helpstr [] = "\n lte-softmodem -O [config mode]<:dbgl[debugflags]><:incp[path]>\n \ + debugflags can also be defined in the config section of the config file\n \ debugflags: mask, 1->print parameters, 2->print memory allocations debug messages\n \ - 4->print command line processing debug messages\n "; + 4->print command line processing debug messages\n \ + incp parameter can be used to define the include path used for config files (@include directive)\n \ + defaults is set to the path of the main config file.\n"; #define CONFIG_SECTIONNAME "config" #define CONFIGPARAM_DEBUGFLAGS_IDX 0 diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c index 33d6408828..462299b893 100644 --- a/common/config/config_userapi.c +++ b/common/config/config_userapi.c @@ -62,6 +62,7 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) { if ( (cfgoptions->paramflags & PARAMFLAG_NOFREE) == 0) { config_get_if()->ptrs[config_get_if()->numptrs] = (char *)ptr; + config_get_if()->ptrsAllocated[config_get_if()->numptrs] = true; config_get_if()->numptrs++; } } else { @@ -82,7 +83,14 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) { } if (*ptr == NULL) { - *ptr = malloc(length>40?length:40); // LTS: dummy fix, waiting Francois full fix in 4G branch + // LTS: dummy fix, waiting Francois full fix in 4G branch + // the issue is we don't know at this point the size we will get + // for parmeters on the command line, + // The length sould probably managed, in a later version + // 100 is a very large value for a string parameter of today OAI + if (length<100) + length=100; + *ptr = malloc(length); if ( *ptr != NULL) { memset(*ptr,0,length); diff --git a/common/config/libconfig/config_libconfig.c b/common/config/libconfig/config_libconfig.c index 2e9fd614c5..17266246f0 100644 --- a/common/config/libconfig/config_libconfig.c +++ b/common/config/libconfig/config_libconfig.c @@ -33,8 +33,9 @@ #include #include +#include + #include -#include #include "config_libconfig.h" #include "config_libconfig_private.h" @@ -346,17 +347,36 @@ int config_libconfig_init(char *cfgP[], int numP) { libconfig_privdata.configfile = strdup((char *)cfgP[0]); config_get_if()->numptrs=0; memset(config_get_if()->ptrs,0,sizeof(void *) * CONFIG_MAX_ALLOCATEDPTRS); - + memset(config_get_if()->ptrsAllocated, 0, sizeof(config_get_if()->ptrsAllocated)); + /* search for include path parameter and set config file include path accordingly */ + for (int i=0; i_getfarray` symbol, calls the corresponding function when the symbol is found. `< modname >_getfarray` takes one argument, a pointer to a `loader_shlibfunc_t` array, and returns the number of items in this array, as defined by the `getfarrayfunc_t` type. The `loader_shlibfunc_t` array returned by the shared library must be fully filled (both `fname` and `fptr` fields). * looks for the `numf` function symbols listed in the `farray[i].fname` arguments and set the corresponding `farray[i].fptr`function pointers +```c +int load_module_version_shlib(char *modname, char *version, loader_shlibfunc_t *farray, int numf) +``` +Allows loading a specific library version, as specified by the `version` parameter. When version is not NULL the version that is possibly specified as a config module parameter is ignored. This call has been introduced for phy simulators executables which do not use the config module. It is used, for example, by the ldcp initialization (`load_nrLDPClib` function in [nrLDPC_load.c](../../../../../openair1/PHY/CODING/nrLDPC_load.c) to allow the `ldpctest` simulator to select the cuda accelerated ldcp implementation. `load_module_shlib` is just a define macro to switch to a `load_module_version_shlib` call, adding a NULL pointer for the version parameter. ```c void * get_shlibmodule_fptr(char *modname, char *fname) diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index f6d57bd791..d0a53a755b 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -88,17 +88,20 @@ int write_file_matlab(const char *fname, void *data, int length, int dec, - char format) + unsigned int format, + int multiVec) { FILE *fp=NULL; int i; + AssertFatal((format&~MATLAB_RAW) <16,""); + if (data == NULL) return -1; //printf("Writing %d elements of type %d to %s\n",length,format,fname); - if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) { + if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) { fp = fopen(fname,"a+"); } else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) { fp = fopen(fname,"w+"); @@ -109,7 +112,32 @@ int write_file_matlab(const char *fname, return(-1); } - if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) + if ( (format&MATLAB_RAW) == MATLAB_RAW ) { + int sz[16]={sizeof(short), 2*sizeof(short), + sizeof(int), 2*sizeof(int), + sizeof(char), 2*sizeof(char), + sizeof(long long), + sizeof(double), 2*sizeof(double), + sizeof(unsigned char), + sizeof(short), + sizeof(short), + sizeof(short), + sizeof(short), + sizeof(short), + sizeof(short) + }; + int eltSz= sz[format&~MATLAB_RAW]; + if (dec==1) + fwrite(data, eltSz, length, fp); + else + for (i=0; ilevel2string[i] = toupper(log_level_names[i].name[0]); // uppercased first letter of level name diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index 8e74f4148c..fa95d5a6fe 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -148,6 +148,7 @@ extern "C" { #define DEBUG_SECURITY (1<<11) #define DEBUG_NAS (1<<12) #define DEBUG_RLC (1<<13) +#define DEBUG_DLSCH_DECOD (1<<14) #define UE_TIMING (1<<20) @@ -166,6 +167,7 @@ extern "C" { {"SECURITY", DEBUG_SECURITY},\ {"NAS", DEBUG_NAS},\ {"RLC", DEBUG_RLC},\ + {"DLSCH_DECOD", DEBUG_DLSCH_DECOD},\ {"UE_TIMING", UE_TIMING},\ {NULL,-1}\ } @@ -226,6 +228,7 @@ typedef enum { X2AP, M2AP, M3AP, + NGAP, GNB_APP, NR_RRC, NR_MAC, @@ -332,8 +335,27 @@ typedef struct { @param length length of data vector to output @param dec decimation level @param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit) +@param multiVec create new file or append to existing (useful for writing multiple vectors to same file. Just call the function multiple times with same file name and with this parameter set to 1) */ -int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format); +#define MATLAB_RAW (1<<31) +#define MATLAB_SHORT 0 +#define MATLAB_CSHORT 1 +#define MATLAB_INT 2 +#define MATLAB_CINT 3 +#define MATLAB_INT8 4 +#define MATLAB_CINT8 5 +#define MATLAB_LLONG 6 +#define MATLAB_DOUBLE 7 +#define MATLAB_CDOUBLE 8 +#define MATLAB_UINT8 9 +#define MATLEB_EREN1 10 +#define MATLEB_EREN2 11 +#define MATLEB_EREN3 12 +#define MATLAB_CSHORT_BRACKET1 13 +#define MATLAB_CSHORT_BRACKET2 14 +#define MATLAB_CSHORT_BRACKET3 15 + +int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format, int multiVec); /*----------------macro definitions for reading log configuration from the config module */ #define CONFIG_STRING_LOG_PREFIX "log_config" @@ -393,31 +415,36 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int /* bitmask dependent macros, to generate debug file such as matlab file or message dump */ # define LOG_DUMPFLAG(D) (g_log->dump_mask & D) -# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)/* */ +# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)/* */ /* define variable only used in LOG macro's */ # define LOG_VAR(A,B) A B # else /* T_TRACER: remove all debugging and tracing messages, except errors */ -# define LOG_I(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ; } while(0)/* */ -# define LOG_W(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_WARNING, x) ; } while(0)/* */ -# define LOG_E(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_ERR, x) ; } while(0)/* */ -# define LOG_D(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_DEBUG, x) ; } while(0)/* */ -# define LOG_T(c, x...) /* */ -# define LOG_DUMPMSG(c, b, s, x...) /* */ +# define LOG_E(c, x...) do { if( g_log->log_component[c].level >= OAILOG_ERR ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_ERR, x) ;} while (0) +# define LOG_W(c, x...) do { if( g_log->log_component[c].level >= OAILOG_WARNING) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_WARNING, x) ;} while (0) +# define LOG_I(c, x...) do { if( g_log->log_component[c].level >= OAILOG_INFO ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ;} while (0) +# define LOG_D(c, x...) do { if( g_log->log_component[c].level >= OAILOG_DEBUG ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_DEBUG, x) ;} while (0) +# define LOG_T(c, x...) do { if( g_log->log_component[c].level >= OAILOG_TRACE ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_TRACE, x) ;} while (0) +# define VLOG(c,l, f, args) do { if( g_log->log_component[c].level >= l ) vlogRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, l, f, args) ; } while (0) + # define nfapi_log(FILE, FNC, LN, COMP, LVL, FMT...) -# define LOG_DEBUGFLAG(D) ( 0 ) -# define LOG_DUMPFLAG(D) ( 0 ) -# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0) -# define LOG_VAR(A,B) +# define LOG_DEBUGFLAG(D) (g_log->dump_mask & D) +# define LOG_DUMPFLAG(D) (g_log->debug_mask & D) +# define LOG_DUMPMSG(c, f, b, s, x...) do { if(g_log->dump_mask & f) log_dump(c, b, s, LOG_DUMP_CHAR, x) ;} while (0) /* */ + +# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0) +# define LOG_VAR(A,B) A B +# define T_ACTIVE(a) (0) # endif /* T_TRACER */ /* avoid warnings for variables only used in LOG macro's but set outside debug section */ #define GCC_NOTUSED __attribute__((unused)) #define LOG_USEDINLOG_VAR(A,B) GCC_NOTUSED A B /* unfiltered macros, useful for simulators or messages at init time, before log is configured */ -#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0) +#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0) #define LOG_UI(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ; } while(0) #define LOG_UDUMPMSG(c, b, s, f, x...) do { log_dump(c, b, s, f, x) ;} while (0) /* */ +# define LOG_MM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 1);} while(0) /* @}*/ diff --git a/common/utils/LOG/log_extern.h b/common/utils/LOG/log_extern.h index f6205889dc..23f9217d7e 100644 --- a/common/utils/LOG/log_extern.h +++ b/common/utils/LOG/log_extern.h @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -#include"log.h" +#include "log.h" extern log_t *g_log; diff --git a/common/utils/LOG/vcd_signal_dumper.c b/common/utils/LOG/vcd_signal_dumper.c index 90857d7cd9..5bf9759933 100644 --- a/common/utils/LOG/vcd_signal_dumper.c +++ b/common/utils/LOG/vcd_signal_dumper.c @@ -302,6 +302,9 @@ const char* eurecomFunctionsNames[] = { /* PHY signals */ "ue_synch", "ue_slot_fep", + "ue_slot_fep_pdcch", + "ue_slot_fep_pbch", + "ue_slot_fep_pdsch", "ue_slot_fep_mbsfn", "ue_slot_fep_mbsfn_khz_1dot25", "ue_rrc_measurements", @@ -390,6 +393,8 @@ const char* eurecomFunctionsNames[] = { "rx_pmch", "rx_pmch_khz_1dot25", "pdsch_procedures", + "pdsch_procedures_crnti", + //"dlsch_procedures_crnti", "pdsch_procedures_si", "pdsch_procedures_p", "pdsch_procedures_ra", @@ -814,6 +819,7 @@ static inline unsigned long long int vcd_get_time(void) return (long long unsigned int)((time.tv_nsec - g_time_start.tv_nsec)) + ((long long unsigned int)time.tv_sec - (long long unsigned int)g_time_start.tv_sec) * 1000000000UL; #endif + return 0; } void vcd_signal_dumper_create_header(void) diff --git a/common/utils/LOG/vcd_signal_dumper.h b/common/utils/LOG/vcd_signal_dumper.h index 601465c628..fb27c19973 100644 --- a/common/utils/LOG/vcd_signal_dumper.h +++ b/common/utils/LOG/vcd_signal_dumper.h @@ -283,6 +283,9 @@ typedef enum { /* PHY signals */ VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, + VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, + VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, + VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_MBSFN, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_MBSFN_KHZ_1DOT25, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, @@ -371,9 +374,11 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PMCH, VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PMCH_KHZ_1DOT25, VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, + VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, + //VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PROC_C, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_CONFIG_SIB1_ENB, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_CONFIG_SIB2_ENB, @@ -601,11 +606,19 @@ extern int ouput_vcd; #else /* T_TRACER */ +#if ENABLE_VCD #define VCD_SIGNAL_DUMPER_INIT(aRgUmEnT) vcd_signal_dumper_init(aRgUmEnT) #define VCD_SIGNAL_DUMPER_CLOSE() vcd_signal_dumper_close() #define VCD_SIGNAL_DUMPER_CREATE_HEADER() vcd_signal_dumper_create_header() #define VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(vAr1,vAr2) vcd_signal_dumper_dump_variable_by_name(vAr1,vAr2) #define VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(vAr1,vAr2) vcd_signal_dumper_dump_function_by_name(vAr1,vAr2) +#else +#define VCD_SIGNAL_DUMPER_INIT(aRgUmEnT) +#define VCD_SIGNAL_DUMPER_CLOSE() +#define VCD_SIGNAL_DUMPER_CREATE_HEADER() +#define VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(vAr1,vAr2) +#define VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(vAr1,vAr2) +#endif #endif /* T_TRACER */ diff --git a/common/utils/T/.gitignore b/common/utils/T/.gitignore index d754ff7c38..6a6e5817c5 100644 --- a/common/utils/T/.gitignore +++ b/common/utils/T/.gitignore @@ -4,6 +4,7 @@ T_IDs.h T_messages.txt.h genids tracer/enb +tracer/gnb tracer/extract_config tracer/record tracer/replay diff --git a/common/utils/T/Makefile b/common/utils/T/Makefile index 0588c88a45..d76ab93cb8 100644 --- a/common/utils/T/Makefile +++ b/common/utils/T/Makefile @@ -18,7 +18,7 @@ T_messages.txt.h: T_messages.txt T_IDs.h: $(GENIDS) T_messages.txt ./$(GENIDS) T_messages.txt T_IDs.h -check_vcd: +check_vcd: T_IDs.h T_messages.txt.h gcc -Wall -I. -I.. -I../itti -I../../../openair2/COMMON -Itracer -o _check_vcd check_vcd.c tracer/database.c tracer/utils.c -lm -pthread ./_check_vcd || (rm -f ./_check_vcd ./T_IDs.h ./T_messages.txt.h && false) rm -f ./_check_vcd diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h index 7b5304b1cb..b74c0567ce 100644 --- a/common/utils/T/T_defs.h +++ b/common/utils/T/T_defs.h @@ -42,9 +42,9 @@ /* maximum size of a message - increase if needed */ #if BASIC_SIMULATOR /* let's have 100 RBs functional for the basic simulator */ -# define T_BUFFER_MAX (1024*64*2) +# define T_BUFFER_MAX (1024*64*4) #else -# define T_BUFFER_MAX (1024*64) +# define T_BUFFER_MAX (1024*64*4) #endif /* size of the local cache for messages (must be pow(2,something)) */ @@ -52,7 +52,7 @@ /* we don't need much space for the basic simulator */ # define T_CACHE_SIZE 1024 #else -# define T_CACHE_SIZE (8192 * 2) +# define T_CACHE_SIZE (8192) #endif /* maximum number of bytes a message can contain */ @@ -73,7 +73,7 @@ typedef struct { } T_cache_t; /* number of VCD functions (to be kept up to date! see in T_messages.txt) */ -#define VCD_NUM_FUNCTIONS (269) +#define VCD_NUM_FUNCTIONS (273) /* number of VCD variables (to be kept up to date! see in T_messages.txt) */ #define VCD_NUM_VARIABLES (187) diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index d036b40560..192bf8cc37 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -16,7 +16,7 @@ ID = ENB_PHY_DL_TICK ID = ENB_PHY_DLSCH_UE_DCI DESC = eNodeB downlink UE specific DCI as sent by the PHY layer GROUP = ALL:PHY:GRAPHIC:ENB - FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS + FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS : int,ndi : int,rv : int,rbc : int,nb_rb : int,rb_alloc ID = ENB_PHY_DLSCH_UE_ACK DESC = eNodeB downlink UE ACK as seen by the PHY layer in process_HARQ_feedback GROUP = ALL:PHY:GRAPHIC:ENB @@ -85,6 +85,18 @@ ID = ENB_PHY_MIB DESC = MIB data GROUP = ALL:PHY:ENB:WIRESHARK FORMAT = int,eNB_ID : int,frame : int,subframe : buffer,data +ID = GNB_PHY_MIB + DESC = NR MIB data + GROUP = ALL:PHY:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data +ID = GNB_PHY_PUCCH_PUSCH_IQ + DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,frame : int,slot : buffer,rxdataF +ID = GNB_PHY_PRACH_INPUT_SIGNAL + DESC = gNodeB input data in the time domain for slots with PRACH detection + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,frame : int,slot : int,antenna : buffer,rxdata #MAC logs ID = ENB_MAC_UE_DL_SDU @@ -125,12 +137,28 @@ ID = ENB_MAC_UE_DL_PDU_WITH_DATA FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data ID = ENB_MAC_SCHEDULING_REQUEST DESC = MAC scheduling request detected for an UE - GROUP = ALL:MAC:ENB + GROUP = ALL:MAC:ENB:WIRESHARK FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe : int,rnti ID = ENB_MAC_UE_DL_RAR_PDU_WITH_DATA DESC = MAC downlink PDU for an UE GROUP = ALL:MAC:ENB:WIRESHARK FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data +ID = GNB_MAC_DL_PDU_WITH_DATA + DESC = NR MAC downlink PDU for an UE + GROUP = ALL:MAC:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data +ID = GNB_MAC_UL_PDU_WITH_DATA + DESC = NR MAC uplink PDU for an UE + GROUP = ALL:MAC:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data +ID = GNB_MAC_DL_RAR_PDU_WITH_DATA + DESC = NR MAC downlink PDU for RAR + GROUP = ALL:MAC:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data +ID = GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA + DESC = NR MAC downlink retransmitted PDU for an UE + GROUP = ALL:MAC:GNB:WIRESHARK + FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : int,round : buffer,data #RLC logs ID = ENB_RLC_DL @@ -384,6 +412,27 @@ ID = LEGACY_S1AP_TRACE GROUP = ALL:LEGACY_S1AP:LEGACY_GROUP_TRACE:LEGACY FORMAT = string,log +ID = LEGACY_NGAP_INFO + DESC = NGAP legacy logs - info level + GROUP = ALL:LEGACY_NGAP:LEGACY_GROUP_INFO:LEGACY + FORMAT = string,log +ID = LEGACY_NGAP_ERROR + DESC = NGAP legacy logs - error level + GROUP = ALL:LEGACY_NGAP:LEGACY_GROUP_ERROR:LEGACY + FORMAT = string,log +ID = LEGACY_NGAP_WARNING + DESC = NGAP legacy logs - warning level + GROUP = ALL:LEGACY_NGAP:LEGACY_GROUP_WARNING:LEGACY + FORMAT = string,log +ID = LEGACY_NGAP_DEBUG + DESC = NGAP legacy logs - debug level + GROUP = ALL:LEGACY_NGAP:LEGACY_GROUP_DEBUG:LEGACY + FORMAT = string,log +ID = LEGACY_NGAP_TRACE + DESC = NGAP legacy logs - trace level + GROUP = ALL:LEGACY_NGAP:LEGACY_GROUP_TRACE:LEGACY + FORMAT = string,log + ID = LEGACY_X2AP_INFO DESC = X2AP legacy logs - info level GROUP = ALL:LEGACY_X2AP:LEGACY_GROUP_INFO:LEGACY @@ -2366,6 +2415,21 @@ ID = VCD_FUNCTION_UE_SLOT_FEP GROUP = ALL:VCD:UE:VCD_FUNCTION FORMAT = int,value VCD_NAME = ue_slot_fep +ID = VCD_FUNCTION_UE_SLOT_FEP_PDCCH + DESC = VCD function UE_SLOT_FEP_PDCCH + GROUP = ALL:VCD:UE:VCD_FUNCTION + FORMAT = int,value + VCD_NAME = ue_slot_fep_pdcch +ID = VCD_FUNCTION_UE_SLOT_FEP_PBCH + DESC = VCD function UE_SLOT_FEP_PBCH + GROUP = ALL:VCD:UE:VCD_FUNCTION + FORMAT = int,value + VCD_NAME = ue_slot_fep_pbch +ID = VCD_FUNCTION_UE_SLOT_FEP_PDSCH + DESC = VCD function UE_SLOT_FEP_PDSCH + GROUP = ALL:VCD:UE:VCD_FUNCTION + FORMAT = int,value + VCD_NAME = ue_slot_fep_pdsch ID = VCD_FUNCTION_UE_SLOT_FEP_MBSFN DESC = VCD function UE_SLOT_FEP_MBSFN GROUP = ALL:VCD:UE:VCD_FUNCTION @@ -2806,6 +2870,11 @@ ID = VCD_FUNCTION_PDSCH_PROC GROUP = ALL:VCD:UE:VCD_FUNCTION FORMAT = int,value VCD_NAME = pdsch_procedures +ID = VCD_FUNCTION_PDSCH_PROC_C + DESC = VCD function PDSCH_PROC_C + GROUP = ALL:VCD:UE:VCD_FUNCTION + FORMAT = int,value + VCD_NAME = pdsch_procedures_crnti ID = VCD_FUNCTION_PDSCH_PROC_SI DESC = VCD function PDSCH_PROC_SI GROUP = ALL:VCD:UE:VCD_FUNCTION diff --git a/common/utils/T/defs.h b/common/utils/T/defs.h index 69b379ce0b..a194e621db 100644 --- a/common/utils/T/defs.h +++ b/common/utils/T/defs.h @@ -1,5 +1,5 @@ -#ifndef _TRACER_DEFS_H_ -#define _TRACER_DEFS_H_ +#ifndef _COMMON_UTILS_T_DEFS_H_ +#define _COMMON_UTILS_T_DEFS_H_ /* types of plots */ #define PLOT_VS_TIME 0 @@ -27,4 +27,4 @@ void *forwarder(char *ip, int port); void forward(void *forwarder, char *buf, int size); void forward_start_client(void *forwarder, int socket); -#endif /* _TRACER_DEFS_H_ */ +#endif /* _COMMON_UTILS_T_DEFS_H_ */ diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile index 792c2a407c..0713d9a3df 100644 --- a/common/utils/T/tracer/Makefile +++ b/common/utils/T/tracer/Makefile @@ -7,7 +7,8 @@ LIBS=-lm XLIBS=-lX11 -lpng -lXft all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ - extract_input_subframe extract_output_subframe to_vcd extract multi + extract_input_subframe extract_output_subframe to_vcd extract multi \ + gnb record: utils.o record.o database.o config.o $(CC) $(CFLAGS) -o record $^ $(LIBS) @@ -60,6 +61,11 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \ multi: multi.o utils.o database.o config.o $(CC) $(CFLAGS) -o multi $^ $(LIBS) +gnb: utils.o gnb.o database.o event.o handler.o config.o \ + view/view.a gui/gui.a logger/logger.a \ + filter/filter.a + $(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS) + multi.o: ../T_IDs.h ../T_IDs.h: @@ -85,7 +91,7 @@ filter/filter.a: clean: rm -f *.o core tracer_remote textlog enb ue vcd record replay rm -f extract_config macpdu2wireshark extract_input_subframe - rm -f extract_output_subframe to_vcd extract multi + rm -f extract_output_subframe to_vcd extract multi gnb cd gui && $(MAKE) clean cd view && $(MAKE) clean cd logger && $(MAKE) clean diff --git a/common/utils/T/tracer/defs.h b/common/utils/T/tracer/defs.h index 443fabdde8..394351eab0 100644 --- a/common/utils/T/tracer/defs.h +++ b/common/utils/T/tracer/defs.h @@ -1,5 +1,5 @@ -#ifndef _TRACER_DEFS_H_ -#define _TRACER_DEFS_H_ +#ifndef _COMMON_UTILS_T_TRACER_DEFS_H_ +#define _COMMON_UTILS_T_TRACER_DEFS_H_ /* types of plots */ #define PLOT_VS_TIME 0 @@ -21,4 +21,4 @@ void t_gui_start(void); void t_gui_set_input_signal(int eNB, int frame, int subframe, int antenna, int size, void *buf); -#endif /* _TRACER_DEFS_H_ */ +#endif /* _COMMON_UTILS_T_TRACER_DEFS_H_ */ diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c new file mode 100644 index 0000000000..4aaa4898a1 --- /dev/null +++ b/common/utils/T/tracer/gnb.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include "database.h" +#include "handler.h" +#include "config.h" +#include "logger/logger.h" +#include "view/view.h" +#include "gui/gui.h" + +typedef struct { + widget *pucch_pusch_iq_plot; + logger *pucch_pusch_iq_logger; +} gnb_gui; + +typedef struct { + int socket; + int *is_on; + int nevents; + pthread_mutex_t lock; + gnb_gui *e; + void *database; +} gnb_data; + +void is_on_changed(void *_d) +{ + gnb_data *d = _d; + char t; + + if (pthread_mutex_lock(&d->lock)) abort(); + + if (d->socket == -1) goto no_connection; + + t = 1; + if (socket_send(d->socket, &t, 1) == -1 || + socket_send(d->socket, &d->nevents, sizeof(int)) == -1 || + socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1) + goto connection_dies; + +no_connection: + if (pthread_mutex_unlock(&d->lock)) abort(); + return; + +connection_dies: + close(d->socket); + d->socket = -1; + if (pthread_mutex_unlock(&d->lock)) abort(); +} + +void usage(void) +{ + printf( +"options:\n" +" -d this option is mandatory\n" +" -ip connect to given IP address (default %s)\n" +" -p connect to given port (default %d)\n", + DEFAULT_REMOTE_IP, + DEFAULT_REMOTE_PORT + ); + exit(1); +} + +static void *gui_thread(void *_g) +{ + gui *g = _g; + gui_loop(g); + return NULL; +} + +static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, + gnb_data *ed) +{ + widget *main_window; + widget *top_container; + widget *line; + widget *w; + logger *l; + view *v; + + main_window = new_toplevel_window(g, 500, 300, "gNB tracer"); + + top_container = new_container(g, VERTICAL); + widget_add_child(g, main_window, top_container, -1); + + line = new_container(g, HORIZONTAL); + widget_add_child(g, top_container, line, -1); + + /* PUCCH/PUSCH IQ data */ + w = new_xy_plot(g, 55, 55, "", 50); + e->pucch_pusch_iq_plot = w; + widget_add_child(g, line, w, -1); + xy_plot_set_range(g, w, -1000, 1000, -1000, 1000); + xy_plot_set_title(g, w, "rxdataF"); + l = new_iqlog_full(h, database, "GNB_PHY_PUCCH_PUSCH_IQ", "rxdataF"); + v = new_view_xy(300*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE); + logger_add_view(l, v); + e->pucch_pusch_iq_logger = l; +} + +int main(int n, char **v) +{ + char *database_filename = NULL; + void *database; + char *ip = DEFAULT_REMOTE_IP; + int port = DEFAULT_REMOTE_PORT; + int *is_on; + int number_of_events; + int i; + event_handler *h; + gnb_data gnb_data; + gui *g; + gnb_gui eg; + + for (i = 1; i < n; i++) { + if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); + if (!strcmp(v[i], "-d")) + { if (i > n-2) usage(); database_filename = v[++i]; continue; } + usage(); + } + + if (database_filename == NULL) { + printf("ERROR: provide a database file (-d)\n"); + exit(1); + } + + database = parse_database(database_filename); + + load_config_file(database_filename); + + number_of_events = number_of_ids(database); + is_on = calloc(number_of_events, sizeof(int)); + if (is_on == NULL) abort(); + + h = new_handler(database); + + on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1); + + gnb_data.database = database; + gnb_data.socket = -1; + gnb_data.is_on = is_on; + gnb_data.nevents = number_of_events; + if (pthread_mutex_init(&gnb_data.lock, NULL)) abort(); + + g = gui_init(); + new_thread(gui_thread, g); + + gnb_main_gui(&eg, g, h, database, &gnb_data); + + OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL }; + +restart: + clear_remote_config(); + if (gnb_data.socket != -1) close(gnb_data.socket); + gnb_data.socket = connect_to(ip, port); + + /* send the first message - activate selected traces */ + is_on_changed(&gnb_data); + + /* read messages */ + while (1) { + event e; + e = get_event(gnb_data.socket, &ebuf, database); + if (e.type == -1) goto restart; + if (pthread_mutex_lock(&gnb_data.lock)) abort(); + handle_event(h, e); + if (pthread_mutex_unlock(&gnb_data.lock)) abort(); + } + + return 0; +} diff --git a/common/utils/T/tracer/logger/iqlog.c b/common/utils/T/tracer/logger/iqlog.c index 168c50e39b..1947de2bca 100644 --- a/common/utils/T/tracer/logger/iqlog.c +++ b/common/utils/T/tracer/logger/iqlog.c @@ -74,6 +74,44 @@ static void _event(void *p, event e) l->common.v[i]->append(l->common.v[i], l->i, l->q, count); } +static void _event_full(void *p, event e) +{ + struct iqlog *l = p; + int i; + void *buffer; + int bsize; + int nsamples; + float *idst, *qdst; + + if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0) + return; + + buffer = e.e[l->buffer_arg].b; + bsize = e.e[l->buffer_arg].bsize; + + nsamples = bsize / 4; + + if (nsamples > l->max_length) { + l->i = realloc(l->i, nsamples * sizeof(float)); + if (l->i == NULL) abort(); + l->q = realloc(l->q, nsamples * sizeof(float)); + if (l->q == NULL) abort(); + l->max_length = nsamples; + } + + idst = l->i; + qdst = l->q; + for (i = 0; i < nsamples; i++) { + *idst = ((int16_t *)buffer)[i * 2]; + *qdst = ((int16_t *)buffer)[i * 2 + 1]; + idst++; + qdst++; + } + + for (i = 0; i < l->common.vsize; i++) + l->common.v[i]->append(l->common.v[i], l->i, l->q, nsamples); +} + logger *new_iqlog(event_handler *h, void *database, char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti, char *buffer_varname) @@ -149,3 +187,43 @@ logger *new_iqlog(event_handler *h, void *database, return ret; } + +logger *new_iqlog_full(event_handler *h, void *database, char *event_name, + char *buffer_varname) +{ + struct iqlog *ret; + int event_id; + database_event_format f; + int i; + + ret = calloc(1, sizeof(struct iqlog)); if (ret == NULL) abort(); + + ret->common.event_name = strdup(event_name); + if (ret->common.event_name == NULL) abort(); + ret->database = database; + + event_id = event_id_from_name(database, event_name); + + ret->common.handler_id = register_handler_function(h, event_id, _event_full, + ret); + + f = get_format(database, event_id); + + /* look for args */ + ret->buffer_arg = -1; + for (i = 0; i < f.count; i++) { + if (!strcmp(f.name[i], buffer_varname)) ret->buffer_arg = i; + } + if (ret->buffer_arg == -1) { + printf("%s:%d: buffer argument '%s' not found in event '%s'\n", + __FILE__, __LINE__, buffer_varname, event_name); + abort(); + } + if (strcmp(f.type[ret->buffer_arg], "buffer") != 0) { + printf("%s:%d: argument '%s' has wrong type (should be 'buffer')\n", + __FILE__, __LINE__, buffer_varname); + abort(); + } + + return ret; +} diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h index 7c019b4797..d746161e70 100644 --- a/common/utils/T/tracer/logger/logger.h +++ b/common/utils/T/tracer/logger/logger.h @@ -23,6 +23,8 @@ logger *new_ticklog(void *event_handler, void *database, logger *new_iqlog(void *event_handler, void *database, char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti, char *buffer_varname); +logger *new_iqlog_full(void *event_handler, void *database, char *event_name, + char *buffer_varname); logger *new_iqdotlog(void *event_handler, void *database, char *event_name, char *I, char *Q); diff --git a/common/utils/T/tracer/macpdu2wireshark.c b/common/utils/T/tracer/macpdu2wireshark.c index c391a99786..b9284748e4 100644 --- a/common/utils/T/tracer/macpdu2wireshark.c +++ b/common/utils/T/tracer/macpdu2wireshark.c @@ -18,11 +18,14 @@ #define DEFAULT_LIVE_PORT 2021 #define NO_PREAMBLE -1 +#define NO_SR_RNTI -1 typedef struct { int socket; struct sockaddr_in to; OBUF buf; + + /* LTE traces */ /* ul */ int ul_rnti; int ul_frame; @@ -46,6 +49,40 @@ typedef struct { int rar_frame; int rar_subframe; int rar_data; + /* SR */ + int sr_rnti; + int sr_frame; + int sr_subframe; + + /* NR traces */ + /* NR ul */ + int nr_ul_rnti; + int nr_ul_frame; + int nr_ul_slot; + int nr_ul_harq_pid; + int nr_ul_data; + /* NR dl */ + int nr_dl_rnti; + int nr_dl_frame; + int nr_dl_slot; + int nr_dl_harq_pid; + int nr_dl_data; + /* NR dl retx */ + int nr_dl_retx_rnti; + int nr_dl_retx_frame; + int nr_dl_retx_slot; + int nr_dl_retx_harq_pid; + int nr_dl_retx_data; + /* NR mib */ + int nr_mib_frame; + int nr_mib_slot; + int nr_mib_data; + /* NR RAR */ + int nr_rar_rnti; + int nr_rar_frame; + int nr_rar_slot; + int nr_rar_data; + /* config */ int no_mib; int no_sib; @@ -56,10 +93,25 @@ typedef struct { /* runtime vars */ int cur_mib; int cur_sib; + + /* hack to report UE id: + * each time we see a rnti, we allocate the next ue_id + * (two separate versions for lte and nr) + */ + int lte_rnti_to_ueid[65536]; + int lte_next_ue_id; + int nr_rnti_to_ueid[65536]; + int nr_next_ue_id; } ev_data; -void trace(ev_data *d, int direction, int rnti_type, int rnti, - int frame, int subframe, void *buf, int bufsize, int preamble) { +/****************************************************************************/ +/* LTE */ +/****************************************************************************/ + +void trace_lte(ev_data *d, int direction, int rnti_type, int rnti, + int frame, int subframe, void *buf, int bufsize, int preamble, + int sr_rnti) +{ ssize_t ret; int fsf; int i; @@ -73,6 +125,18 @@ void trace(ev_data *d, int direction, int rnti_type, int rnti, PUTC(&d->buf, MAC_LTE_RNTI_TAG); PUTC(&d->buf, (rnti>>8) & 255); PUTC(&d->buf, rnti & 255); + + /* put UE id */ + if (rnti < 0 || rnti > 65535) { printf("bad rnti!\n"); exit(1); } + /* if no UE id allocated for this rnti then allocate the next one */ + if (d->lte_rnti_to_ueid[rnti] == -1) { + d->lte_rnti_to_ueid[rnti] = d->lte_next_ue_id; + d->lte_next_ue_id++; + } + + PUTC(&d->buf, MAC_LTE_UEID_TAG); + PUTC(&d->buf, (d->lte_rnti_to_ueid[rnti]>>8) & 255); + PUTC(&d->buf, d->lte_rnti_to_ueid[rnti] & 255); } /* for newer version of wireshark? */ @@ -89,6 +153,25 @@ void trace(ev_data *d, int direction, int rnti_type, int rnti, PUTC(&d->buf, 0); /* rach attempt - always 0 for us (not sure of this) */ } + if (sr_rnti != NO_SR_RNTI) { + PUTC(&d->buf, MAC_LTE_SR_TAG); + PUTC(&d->buf, 0); /* number of items byte 1 */ + PUTC(&d->buf, 1); /* number of items byte 2 */ + + /* put UE id */ + if (sr_rnti < 0 || sr_rnti > 65535) { printf("bad sr rnti!\n"); exit(1); } + /* if no UE id allocated for this rnti then allocate the next one */ + if (d->lte_rnti_to_ueid[sr_rnti] == -1) { + d->lte_rnti_to_ueid[sr_rnti] = d->lte_next_ue_id; + d->lte_next_ue_id++; + } + PUTC(&d->buf, (d->lte_rnti_to_ueid[sr_rnti]>>8) & 255); + PUTC(&d->buf, d->lte_rnti_to_ueid[sr_rnti] & 255); + + PUTC(&d->buf, (sr_rnti>>8) & 255); + PUTC(&d->buf, sr_rnti & 255); + } + PUTC(&d->buf, MAC_LTE_PAYLOAD_TAG); for (i = 0; i < bufsize; i++) @@ -100,15 +183,17 @@ void trace(ev_data *d, int direction, int rnti_type, int rnti, if (ret != d->buf.osize) abort(); } -void ul(void *_d, event e) { +void ul(void *_d, event e) +{ ev_data *d = _d; - trace(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i, - e.e[d->ul_frame].i, e.e[d->ul_subframe].i, - e.e[d->ul_data].b, e.e[d->ul_data].bsize, - NO_PREAMBLE); + trace_lte(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i, + e.e[d->ul_frame].i, e.e[d->ul_subframe].i, + e.e[d->ul_data].b, e.e[d->ul_data].bsize, + NO_PREAMBLE, NO_SR_RNTI); } -void dl(void *_d, event e) { +void dl(void *_d, event e) +{ ev_data *d = _d; if (e.e[d->dl_rnti].i == 0xffff) { @@ -119,14 +204,15 @@ void dl(void *_d, event e) { d->cur_sib++; } - trace(d, DIRECTION_DOWNLINK, - e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i, - e.e[d->dl_frame].i, e.e[d->dl_subframe].i, - e.e[d->dl_data].b, e.e[d->dl_data].bsize, - NO_PREAMBLE); + trace_lte(d, DIRECTION_DOWNLINK, + e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i, + e.e[d->dl_frame].i, e.e[d->dl_subframe].i, + e.e[d->dl_data].b, e.e[d->dl_data].bsize, + NO_PREAMBLE, NO_SR_RNTI); } -void mib(void *_d, event e) { +void mib(void *_d, event e) +{ ev_data *d = _d; if (d->no_mib) return; @@ -134,50 +220,227 @@ void mib(void *_d, event e) { if (d->max_mib && d->cur_mib == d->max_mib) return; d->cur_mib++; - trace(d, DIRECTION_DOWNLINK, NO_RNTI, 0, - e.e[d->mib_frame].i, e.e[d->mib_subframe].i, - e.e[d->mib_data].b, e.e[d->mib_data].bsize, - NO_PREAMBLE); + trace_lte(d, DIRECTION_DOWNLINK, NO_RNTI, 0, + e.e[d->mib_frame].i, e.e[d->mib_subframe].i, + e.e[d->mib_data].b, e.e[d->mib_data].bsize, + NO_PREAMBLE, NO_SR_RNTI); } -void preamble(void *_d, event e) { +void preamble(void *_d, event e) +{ ev_data *d = _d; - trace(d, DIRECTION_UPLINK, NO_RNTI, 0, - e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i, - NULL, 0, - e.e[d->preamble_preamble].i); + trace_lte(d, DIRECTION_UPLINK, NO_RNTI, 0, + e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i, + NULL, 0, + e.e[d->preamble_preamble].i, NO_SR_RNTI); } -void rar(void *_d, event e) { +void rar(void *_d, event e) +{ ev_data *d = _d; - trace(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i, - e.e[d->rar_frame].i, e.e[d->rar_subframe].i, - e.e[d->rar_data].b, e.e[d->rar_data].bsize, - NO_PREAMBLE); + trace_lte(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i, + e.e[d->rar_frame].i, e.e[d->rar_subframe].i, + e.e[d->rar_data].b, e.e[d->rar_data].bsize, + NO_PREAMBLE, NO_SR_RNTI); } +void sr(void *_d, event e) +{ + ev_data *d = _d; + trace_lte(d, DIRECTION_UPLINK, NO_RNTI, 0, + e.e[d->sr_frame].i, e.e[d->sr_subframe].i, + NULL, 0, + NO_PREAMBLE, e.e[d->sr_rnti].i); +} + +/****************************************************************************/ +/* NR */ +/****************************************************************************/ + +#define MAC_NR_START_STRING "mac-nr" + +#define MAC_NR_PAYLOAD_TAG 0x01 +#define MAC_NR_RNTI_TAG 0x02 +#define MAC_NR_UEID_TAG 0x03 +#define MAC_NR_HARQID 0x06 +#define MAC_NR_FRAME_SLOT_TAG 0x07 + +#define NR_FDD_RADIO 1 +#define NR_TDD_RADIO 2 + +#define NR_DIRECTION_UPLINK 0 +#define NR_DIRECTION_DOWNLINK 1 + +#define NR_NO_RNTI 0 +#define NR_RA_RNTI 2 +#define NR_C_RNTI 3 + +void trace_nr(ev_data *d, int direction, int rnti_type, int rnti, + int frame, int slot, int harq_pid, void *buf, int bufsize, + int preamble) +{ + ssize_t ret; + int i; + d->buf.osize = 0; + PUTS(&d->buf, MAC_NR_START_STRING); + PUTC(&d->buf, NR_TDD_RADIO); + PUTC(&d->buf, direction); + PUTC(&d->buf, rnti_type); + + if (rnti_type == NR_C_RNTI || rnti_type == NR_RA_RNTI) { + PUTC(&d->buf, MAC_NR_RNTI_TAG); + PUTC(&d->buf, (rnti>>8) & 255); + PUTC(&d->buf, rnti & 255); + + /* put UE id */ + if (rnti < 0 || rnti > 65535) { printf("bad rnti!\n"); exit(1); } + /* if no UE id allocated for this rnti then allocate the next one */ + if (d->nr_rnti_to_ueid[rnti] == -1) { + d->nr_rnti_to_ueid[rnti] = d->nr_next_ue_id; + d->nr_next_ue_id++; + } + + PUTC(&d->buf, MAC_NR_UEID_TAG); + PUTC(&d->buf, (d->nr_rnti_to_ueid[rnti]>>8) & 255); + PUTC(&d->buf, d->nr_rnti_to_ueid[rnti] & 255); + } + +#if 0 + /* for old versions of wireshark; not sure if correct */ + int fsf = (frame << 4) + slot; + PUTC(&d->buf, 4 /* MAC_NR_FRAME_SUBFRAME_TAG */); + PUTC(&d->buf, (fsf>>8) & 255); + PUTC(&d->buf, fsf & 255); +#else + PUTC(&d->buf, MAC_NR_FRAME_SLOT_TAG); + PUTC(&d->buf, (frame>>8) & 255); + PUTC(&d->buf, frame & 255); + PUTC(&d->buf, (slot>>8) & 255); + PUTC(&d->buf, slot & 255); + PUTC(&d->buf, MAC_NR_HARQID); + PUTC(&d->buf, harq_pid); +#endif + + PUTC(&d->buf, MAC_NR_PAYLOAD_TAG); + + for (i = 0; i < bufsize; i++) + PUTC(&d->buf, ((char *)buf)[i]); + + ret = sendto(d->socket, d->buf.obuf, d->buf.osize, 0, + (struct sockaddr *)&d->to, sizeof(struct sockaddr_in)); + + if (ret != d->buf.osize) abort(); +} + +void nr_ul(void *_d, event e) +{ + ev_data *d = _d; + + trace_nr(d, NR_DIRECTION_UPLINK, NR_C_RNTI, e.e[d->nr_ul_rnti].i, + e.e[d->nr_ul_frame].i, e.e[d->nr_ul_slot].i, + e.e[d->nr_ul_harq_pid].i, e.e[d->nr_ul_data].b, + e.e[d->nr_ul_data].bsize, NO_PREAMBLE); +} + +void nr_dl(void *_d, event e) +{ + ev_data *d = _d; + + trace_nr(d, NR_DIRECTION_DOWNLINK, NR_C_RNTI, e.e[d->nr_dl_rnti].i, + e.e[d->nr_dl_frame].i, e.e[d->nr_dl_slot].i, + e.e[d->nr_dl_harq_pid].i, e.e[d->nr_dl_data].b, + e.e[d->nr_dl_data].bsize, NO_PREAMBLE); +} + +void nr_dl_retx(void *_d, event e) +{ + ev_data *d = _d; + + trace_nr(d, NR_DIRECTION_DOWNLINK, NR_C_RNTI, e.e[d->nr_dl_retx_rnti].i, + e.e[d->nr_dl_retx_frame].i, e.e[d->nr_dl_retx_slot].i, + e.e[d->nr_dl_retx_harq_pid].i, e.e[d->nr_dl_retx_data].b, + e.e[d->nr_dl_retx_data].bsize, NO_PREAMBLE); +} + +void nr_mib(void *_d, event e) +{ + ev_data *d = _d; + + if (d->no_mib) return; + + if (d->max_mib && d->cur_mib == d->max_mib) return; + + d->cur_mib++; + + trace_nr(d, NR_DIRECTION_DOWNLINK, NR_NO_RNTI, 0, + e.e[d->nr_mib_frame].i, e.e[d->nr_mib_slot].i, 0 /* harq pid */, + e.e[d->nr_mib_data].b, e.e[d->nr_mib_data].bsize, NO_PREAMBLE); +} + +void nr_rar(void *_d, event e) +{ + ev_data *d = _d; + + trace_nr(d, NR_DIRECTION_DOWNLINK, NR_RA_RNTI, e.e[d->nr_rar_rnti].i, + e.e[d->nr_rar_frame].i, e.e[d->nr_rar_slot].i, 0 /* harq pid */, + e.e[d->nr_rar_data].b, e.e[d->nr_rar_data].bsize, NO_PREAMBLE); +} + +/****************************************************************************/ +/****************************************************************************/ + void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, - int preamble_id, int rar_id) { + int preamble_id, int rar_id, int sr_id, + int nr_ul_id, int nr_dl_id, int nr_dl_retx_id, int nr_mib_id, + int nr_rar_id) +{ database_event_format f; int i; - d->ul_rnti = -1; - d->ul_frame = -1; - d->ul_subframe = -1; - d->ul_data = -1; - d->dl_rnti = -1; - d->dl_frame = -1; - d->dl_subframe = -1; - d->dl_data = -1; - d->mib_frame = -1; - d->mib_subframe = -1; - d->mib_data = -1; - d->preamble_frame = -1; - d->preamble_subframe = -1; - d->preamble_preamble = -1; - d->rar_rnti = -1; - d->rar_frame = -1; - d->rar_subframe = -1; - d->rar_data = -1; + d->ul_rnti = -1; + d->ul_frame = -1; + d->ul_subframe = -1; + d->ul_data = -1; + d->dl_rnti = -1; + d->dl_frame = -1; + d->dl_subframe = -1; + d->dl_data = -1; + d->mib_frame = -1; + d->mib_subframe = -1; + d->mib_data = -1; + d->preamble_frame = -1; + d->preamble_subframe = -1; + d->preamble_preamble = -1; + d->rar_rnti = -1; + d->rar_frame = -1; + d->rar_subframe = -1; + d->rar_data = -1; + d->sr_rnti = -1; + d->sr_frame = -1; + d->sr_subframe = -1; + + d->nr_ul_rnti = -1; + d->nr_ul_frame = -1; + d->nr_ul_slot = -1; + d->nr_ul_harq_pid = -1; + d->nr_ul_data = -1; + d->nr_dl_rnti = -1; + d->nr_dl_frame = -1; + d->nr_dl_slot = -1; + d->nr_dl_harq_pid = -1; + d->nr_dl_data = -1; + d->nr_dl_retx_rnti = -1; + d->nr_dl_retx_frame = -1; + d->nr_dl_retx_slot = -1; + d->nr_dl_retx_harq_pid = -1; + d->nr_dl_retx_data = -1; + d->nr_mib_frame = -1; + d->nr_mib_slot = -1; + d->nr_mib_data = -1; + d->nr_rar_rnti = -1; + d->nr_rar_frame = -1; + d->nr_rar_slot = -1; + d->nr_rar_data = -1; + #define G(var_name, var_type, var) \ if (!strcmp(f.name[i], var_name)) { \ if (strcmp(f.type[i], var_type)) goto error; \ @@ -247,6 +510,90 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, if (d->rar_rnti == -1 || d->rar_frame == -1 || d->rar_subframe == -1 || d->rar_data == -1) goto error; + /* sr: rnti, frame, subframe */ + f = get_format(database, sr_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->sr_rnti); + G("frame", "int", d->sr_frame); + G("subframe", "int", d->sr_subframe); + } + + if (d->sr_rnti == -1 || d->sr_frame == -1 || d->sr_subframe == -1) + goto error; + + /* NR ul: rnti, frame, slot, harq_pid, data */ + f = get_format(database, nr_ul_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_ul_rnti); + G("frame", "int", d->nr_ul_frame); + G("slot", "int", d->nr_ul_slot); + G("harq_pid", "int", d->nr_ul_harq_pid); + G("data", "buffer", d->nr_ul_data); + } + + if (d->nr_ul_rnti == -1 || d->nr_ul_frame == -1 || d->nr_ul_slot == -1 || + d->nr_ul_harq_pid == -1 || d->nr_ul_data == -1) + goto error; + + /* NR dl: rnti, frame, slot, harq_pid, data */ + f = get_format(database, nr_dl_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_dl_rnti); + G("frame", "int", d->nr_dl_frame); + G("slot", "int", d->nr_dl_slot); + G("harq_pid", "int", d->nr_dl_harq_pid); + G("data", "buffer", d->nr_dl_data); + } + + if (d->nr_dl_rnti == -1 || d->nr_dl_frame == -1 || d->nr_dl_slot == -1 || + d->nr_dl_harq_pid == -1 || d->nr_dl_data == -1) + goto error; + + /* NR dl retx: rnti, frame, slot, harq_pid, data */ + f = get_format(database, nr_dl_retx_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_dl_retx_rnti); + G("frame", "int", d->nr_dl_retx_frame); + G("slot", "int", d->nr_dl_retx_slot); + G("harq_pid", "int", d->nr_dl_retx_harq_pid); + G("data", "buffer", d->nr_dl_retx_data); + } + + if (d->nr_dl_retx_rnti == -1 || d->nr_dl_retx_frame == -1 || + d->nr_dl_retx_slot == -1 || d->nr_dl_retx_harq_pid == -1 || + d->nr_dl_retx_data == -1) + goto error; + + /* NR MIB: frame, slot, data */ + f = get_format(database, nr_mib_id); + + for (i = 0; i < f.count; i++) { + G("frame", "int", d->nr_mib_frame); + G("slot", "int", d->nr_mib_slot); + G("data", "buffer", d->nr_mib_data); + } + + if (d->nr_mib_frame == -1 || d->nr_mib_slot== -1 || d->nr_mib_data == -1) + goto error; + + /* NR RAR: rnti, frame, slot, data */ + f = get_format(database, nr_rar_id); + + for (i = 0; i < f.count; i++) { + G("rnti", "int", d->nr_rar_rnti); + G("frame", "int", d->nr_rar_frame); + G("slot", "int", d->nr_rar_slot); + G("data", "buffer", d->nr_rar_data); + } + + if (d->nr_rar_rnti == -1 || d->nr_rar_frame == -1 || d->nr_rar_slot == -1 || + d->nr_rar_data == -1) + goto error; + #undef G return; error: @@ -254,7 +601,8 @@ error: abort(); } -void *receiver(void *_d) { +void *receiver(void *_d) +{ ev_data *d = _d; int s; char buf[100000]; @@ -279,7 +627,8 @@ void *receiver(void *_d) { return 0; } -void usage(void) { +void usage(void) +{ printf( "options:\n" " -d this option is mandatory\n" @@ -304,14 +653,17 @@ void usage(void) { exit(1); } -int main(int n, char **v) { +int main(int n, char **v) +{ char *database_filename = NULL; char *input_filename = NULL; void *database; event_handler *h; int in; int i; - int ul_id, dl_id, mib_id = -1, preamble_id, rar_id; + int ul_id, dl_id, mib_id, preamble_id, rar_id; + int nr_ul_id, nr_dl_id, nr_dl_retx_id, nr_mib_id, nr_rar_id; + int sr_id; ev_data d; char *ip = DEFAULT_IP; int port = DEFAULT_PORT; @@ -320,6 +672,11 @@ int main(int n, char **v) { int live = 0; memset(&d, 0, sizeof(ev_data)); + for (i = 0; i < 65536; i++) { + d.lte_rnti_to_ueid[i] = -1; + d.nr_rnti_to_ueid[i] = -1; + } + for (i = 1; i < n; i++) { if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); if (!strcmp(v[i], "-d")) { if(i>n-2)usage(); database_filename = v[++i]; continue; } @@ -381,6 +738,13 @@ int main(int n, char **v) { on_off(database, "ENB_PHY_MIB", is_on, 1); on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1); on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1); + on_off(database, "ENB_MAC_SCHEDULING_REQUEST", is_on, 1); + + on_off(database, "GNB_MAC_UL_PDU_WITH_DATA", is_on, 1); + on_off(database, "GNB_MAC_DL_PDU_WITH_DATA", is_on, 1); + on_off(database, "GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA", is_on, 1); + on_off(database, "GNB_PHY_MIB", is_on, 1); + on_off(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA", is_on, 1); /* activate selected traces */ if (socket_send(in, &mt, 1) == -1 || @@ -398,12 +762,30 @@ int main(int n, char **v) { mib_id = event_id_from_name(database, "ENB_PHY_MIB"); preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE"); rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA"); - setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id); + sr_id = event_id_from_name(database, "ENB_MAC_SCHEDULING_REQUEST"); + + nr_ul_id = event_id_from_name(database, "GNB_MAC_UL_PDU_WITH_DATA"); + nr_dl_id = event_id_from_name(database, "GNB_MAC_DL_PDU_WITH_DATA"); + nr_dl_retx_id = event_id_from_name(database, "GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA"); + nr_mib_id = event_id_from_name(database, "GNB_PHY_MIB"); + nr_rar_id = event_id_from_name(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA"); + + setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id, sr_id, + nr_ul_id, nr_dl_id, nr_dl_retx_id, nr_mib_id, nr_rar_id); + register_handler_function(h, ul_id, ul, &d); register_handler_function(h, dl_id, dl, &d); register_handler_function(h, mib_id, mib, &d); register_handler_function(h, preamble_id, preamble, &d); register_handler_function(h, rar_id, rar, &d); + register_handler_function(h, sr_id, sr, &d); + + register_handler_function(h, nr_ul_id, nr_ul, &d); + register_handler_function(h, nr_dl_id, nr_dl, &d); + register_handler_function(h, nr_dl_retx_id, nr_dl_retx, &d); + register_handler_function(h, nr_mib_id, nr_mib, &d); + register_handler_function(h, nr_rar_id, nr_rar, &d); + d.socket = socket(AF_INET, SOCK_DGRAM, 0); if (d.socket == -1) { @@ -424,8 +806,11 @@ int main(int n, char **v) { if (e.type == -1) break; - if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id || - e.type == preamble_id || e.type == rar_id)) continue; + if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id || + e.type == preamble_id || e.type == rar_id || e.type == sr_id || + e.type == nr_ul_id || e.type == nr_dl_id || + e.type == nr_dl_retx_id || e.type == nr_mib_id || + e.type == nr_rar_id)) continue; handle_event(h, e); } diff --git a/common/utils/T/tracer/packet-mac-lte.h b/common/utils/T/tracer/packet-mac-lte.h index 54e6d1a09b..60181987a9 100644 --- a/common/utils/T/tracer/packet-mac-lte.h +++ b/common/utils/T/tracer/packet-mac-lte.h @@ -11,26 +11,7 @@ * * Copyright (C) 2009 Martin Mathieson. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE + * SPDX-License-Identifier: BSD-2-Clause */ #ifndef __COMMON_UTILS_T_TRACER_PACKET_MAC_LTE__H__ @@ -67,9 +48,9 @@ /* and implemented by this dissector, using the definitions */ /* below. A link to an example program showing you how to encode */ /* these headers and send LTE MAC PDUs on a UDP socket is */ -/* provided at https://wiki.wireshark.org/MAC-LTE */ +/* provided at https://wiki.wireshark.org/MAC-LTE */ /* */ -/* A heuristic dissecter (enabled by a preference) will */ +/* A heuristic dissector (enabled by a preference) will */ /* recognise a signature at the beginning of these frames. */ /*****************************************************************/ @@ -126,18 +107,25 @@ MCS index (1 byte), redundancy version (1 byte), resource block length (1 byte), HARQ id (1 byte), NDI (1 byte), TB (1 byte), DL reTx (1 byte) */ -#define MAC_LTE_SIMULT_PUCCH_PUSCH_PCELL 0x0C +#define MAC_LTE_SIMULT_PUCCH_PUSCH_PCELL_TAG 0x0C /* 0 byte */ -#define MAC_LTE_SIMULT_PUCCH_PUSCH_PSCELL 0x0D +#define MAC_LTE_SIMULT_PUCCH_PUSCH_PSCELL_TAG 0x0D /* 0 byte */ -#define MAC_LTE_CE_MODE 0x0E +#define MAC_LTE_CE_MODE_TAG 0x0E /* 1 byte containing mac_lte_ce_mode enum value */ -#define MAC_LTE_NB_MODE 0x0F +#define MAC_LTE_NB_MODE_TAG 0x0F /* 1 byte containing mac_lte_nb_mode enum value */ +#define MAC_LTE_N_UL_RB_TAG 0x10 +/* 1 byte containing the number of UL resource blocks: 6, 15, 25, 50, 75 or 100 */ + +#define MAC_LTE_SR_TAG 0x11 +/* 2 bytes for the number of items, followed by that number of ueid, rnti (2 bytes each) */ + + /* MAC PDU. Following this tag comes the actual MAC PDU (there is no length, the PDU continues until the end of the frame) */ #define MAC_LTE_PAYLOAD_TAG 0x01 diff --git a/common/utils/asn1_conversions.h b/common/utils/asn1_conversions.h index 050c065d9d..82dca54c08 100644 --- a/common/utils/asn1_conversions.h +++ b/common/utils/asn1_conversions.h @@ -101,11 +101,11 @@ static inline uint64_t BIT_STRING_to_uint64(BIT_STRING_t *asn) { shift = ((asn->size - 1) * 8) - asn->bits_unused; for (index = 0; index < (asn->size - 1); index++) { - result |= asn->buf[index] << shift; + result |= ((uint64_t)asn->buf[index]) << shift; shift -= 8; } - result |= asn->buf[index] >> asn->bits_unused; + result |= ((uint64_t)asn->buf[index]) >> asn->bits_unused; return result; } diff --git a/common/utils/assertions.h b/common/utils/assertions.h index 48d8df401c..06d43bdbfa 100644 --- a/common/utils/assertions.h +++ b/common/utils/assertions.h @@ -39,7 +39,7 @@ void output_log_mem(void); display_backtrace(); \ fflush(stdout); \ fflush(stderr); \ - exit(EXIT_FAILURE); \ + abort(); #define _Assert_(cOND, aCTION, fORMAT, aRGS...) \ do { \ diff --git a/common/utils/backtrace.c b/common/utils/backtrace.c index f6de74f156..f61cf0349a 100644 --- a/common/utils/backtrace.c +++ b/common/utils/backtrace.c @@ -38,7 +38,7 @@ void display_backtrace(void) { size_t i; char *test=getenv("NO_BACKTRACE"); - if (test!=0) *((int *)0)=0; + if (test!=0) abort(); size = backtrace(array, 10); strings = backtrace_symbols(array, size); diff --git a/common/utils/itti_analyzer/INSTALL b/common/utils/itti_analyzer/INSTALL deleted file mode 100644 index 2099840756..0000000000 --- a/common/utils/itti_analyzer/INSTALL +++ /dev/null @@ -1,370 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, -Inc. - - Copying and distribution of this file, with or without modification, -are permitted in any medium without royalty provided the copyright -notice and this notice are preserved. This file is offered as-is, -without warranty of any kind. - -Basic Installation -================== - - Briefly, the shell command `./configure && make && make install' -should configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. Some packages provide this -`INSTALL' file but do not implement all of the features documented -below. The lack of an optional feature in a given package is not -necessarily a bug. More recommendations for GNU packages can be found -in *note Makefile Conventions: (standards)Makefile Conventions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - - The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package, generally using the just-built uninstalled binaries. - - 4. Type `make install' to install the programs and any data files and - documentation. When installing into a prefix owned by root, it is - recommended that the package be configured and built as a regular - user, and only the `make install' phase executed with root - privileges. - - 5. Optionally, type `make installcheck' to repeat any self-tests, but - this time using the binaries in their final installed location. - This target does not install anything. Running this target as a - regular user, particularly if the prior `make install' required - root privileges, verifies that the installation completed - correctly. - - 6. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 7. Often, you can also type `make uninstall' to remove the installed - files again. In practice, not all packages have tested that - uninstallation works correctly, even though it is required by the - GNU Coding Standards. - - 8. Some packages, particularly those that use Automake, provide `make - distcheck', which can by used by developers to test that all other - targets like `make install' and `make uninstall' work correctly. - This target is generally not run by end users. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. This -is known as a "VPATH" build. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. - -Installation Names -================== - - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX', where PREFIX must be an -absolute file name. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of `${prefix}', so that -specifying just `--prefix' will affect all of the other directory -specifications that were not explicitly provided. - - The most portable way to affect installation locations is to pass the -correct locations to `configure'; however, many packages provide one or -both of the following shortcuts of passing variable assignments to the -`make install' command line to change installation locations without -having to reconfigure or recompile. - - The first method involves providing an override variable for each -affected directory. For example, `make install -prefix=/alternate/directory' will choose an alternate location for all -directory configuration variables that were expressed in terms of -`${prefix}'. Any directories that were specified during `configure', -but not in terms of `${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. - - The second method involves providing the `DESTDIR' variable. For -example, `make install DESTDIR=/alternate/directory' will prepend -`/alternate/directory' before all installation names. The approach of -`DESTDIR' overrides is not required by the GNU Coding Standards, and -does not work on platforms that have drive letters. On the other hand, -it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of `${prefix}' -at `configure' time. - -Optional Features -================= - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - - Some packages offer the ability to configure how verbose the -execution of `make' will be. For these packages, running `./configure ---enable-silent-rules' sets the default to minimal output, which can be -overridden with `make V=1'; while running `./configure ---disable-silent-rules' sets the default to verbose, which can be -overridden with `make V=0'. - -Particular systems -================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: - - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" - -and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - HP-UX `make' updates targets which have the same time stamps as -their prerequisites, which makes it generally unusable when shipped -generated files such as `configure' are involved. Use GNU `make' -instead. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try - - ./configure CC="cc" - -and if that doesn't work, try - - ./configure CC="cc -nodtk" - - On Solaris, don't put `/usr/ucb' early in your `PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. - - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: - - ./configure --prefix=/boot/common - -Specifying the System Type -========================== - - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS - KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf limitation. Until the limitation is lifted, you can use -this workaround: - - CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - - `configure' recognizes the following options to control how it -operates. - -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. - -`--help=short' -`--help=recursive' - Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - -`--no-create' -`-n' - Run the configure checks, but stop before creating any output - files. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. diff --git a/common/utils/itti_analyzer/Makefile.am b/common/utils/itti_analyzer/Makefile.am deleted file mode 100644 index b1a371cfe8..0000000000 --- a/common/utils/itti_analyzer/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -AM_CFLAGS = \ - @ADD_CFLAGS@ \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/libparser \ - -I$(top_srcdir)/libresolver \ - -I$(top_srcdir)/libbuffers \ - -I$(top_srcdir)/libui - -SUBDIRS = libparser libresolver libbuffers libui . - -itti_analyzer_LDADD = \ - $(top_builddir)/libui/libui.la \ - $(top_builddir)/libparser/libparser.la \ - $(top_builddir)/libresolver/libresolver.la \ - $(top_builddir)/libbuffers/libbuffers.la - -bin_PROGRAMS = itti_analyzer diff --git a/common/utils/itti_analyzer/README b/common/utils/itti_analyzer/README deleted file mode 100644 index 8ca077a227..0000000000 --- a/common/utils/itti_analyzer/README +++ /dev/null @@ -1,14 +0,0 @@ - -To run itti_analyzer, please perform the following actions: - -1) apt-get install autotools-dev automake libtool - -2) libtoolize - -3) ./autogen.sh - -4) ./configure - -5) make - -6) ./itti_analyzer \ No newline at end of file diff --git a/common/utils/itti_analyzer/autogen.sh b/common/utils/itti_analyzer/autogen.sh deleted file mode 100755 index 6d08b67921..0000000000 --- a/common/utils/itti_analyzer/autogen.sh +++ /dev/null @@ -1,6 +0,0 @@ -#! /bin/sh - -aclocal \ -&& autoheader \ -&& automake --add-missing \ -&& autoconf \ No newline at end of file diff --git a/common/utils/itti_analyzer/common/itti_types.h b/common/utils/itti_analyzer/common/itti_types.h deleted file mode 100644 index d405e48cbd..0000000000 --- a/common/utils/itti_analyzer/common/itti_types.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/** @brief Intertask Interface common types - * Contains type definitions used for generating and parsing ITTI messages. - * @author Laurent Winckel - */ - -#ifndef _ITTI_TYPES_H_ -#define _ITTI_TYPES_H_ - -#include - -#define CHARS_TO_UINT32(c1, c2, c3, c4) (((c4) << 24) | ((c3) << 16) | ((c2) << 8) | (c1)) - -#define MESSAGE_NUMBER_CHAR_FORMAT "%11u" - -/* Intertask message types */ -enum itti_message_types_e -{ - ITTI_DUMP_XML_DEFINITION = CHARS_TO_UINT32 ('\n', 'I', 'x', 'd'), - ITTI_DUMP_XML_DEFINITION_END = CHARS_TO_UINT32 ('i', 'X', 'D', '\n'), - - ITTI_DUMP_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 'm', 's'), - ITTI_DUMP_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'M', 'S', '\n'), - - ITTI_STATISTIC_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 's', 't'), - ITTI_STATISTIC_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'S', 'T', '\n'), - - /* This signal is not meant to be used by remote analyzer */ - ITTI_DUMP_EXIT_SIGNAL = CHARS_TO_UINT32 ('e', 'X', 'I', 'T'), -}; - -typedef uint32_t itti_message_types_t; - -/* Message header is the common part that should never change between - * remote process and this one. - */ -typedef struct { - /* The size of this structure */ - uint32_t message_size; - itti_message_types_t message_type; -} itti_socket_header_t; - -typedef struct { - char message_number_char[12]; /* 9 chars are needed to store an unsigned 32 bits value in decimal, but must be a multiple of 32 bits to avoid alignment issues */ -} itti_signal_header_t; - - -#define INSTANCE_DEFAULT (UINT16_MAX - 1) -#define INSTANCE_ALL (UINT16_MAX) - -typedef uint16_t instance_t; - -#endif diff --git a/common/utils/itti_analyzer/common/rc.h b/common/utils/itti_analyzer/common/rc.h deleted file mode 100644 index 50786f460f..0000000000 --- a/common/utils/itti_analyzer/common/rc.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include - -#ifndef RC_H_ -#define RC_H_ - -#define RC_OK 0 -#define RC_FAIL -1 -#define RC_BAD_PARAM -2 -#define RC_NULL_POINTER -3 - -static const char * const rc_strings[] = - {"Ok", "fail", "bad parameter", "null pointer"}; - -#define CHECK_FCT(fCT) \ -do { \ - int rET; \ - if ((rET = fCT) != RC_OK) { \ - fprintf(stderr, #fCT" has failed (%s:%d)\n", __FILE__, __LINE__); \ - return rET; \ - } \ -} while(0) - -#define CHECK_FCT_POSIX(fCT) \ -do { \ - if (fCT == -1) { \ - fprintf(stderr, #fCT" has failed (%d:%s) (%s:%d)\n", errno, \ - strerror(errno), __FILE__, __LINE__); \ - return RC_FAIL; \ - } \ -} while(0) - -#define CHECK_FCT_DO(fCT, dO) \ -do { \ - int rET; \ - if ((rET = fCT) != RC_OK) { \ - fprintf(stderr, #fCT" has returned %d (%s:%d)\n", rET, __FILE__, __LINE__); \ - dO; \ - } \ -} while(0) - -#define CHECK_BUFFER(bUFFER) \ -do { \ - if ((bUFFER) == NULL) { \ - fprintf(stderr, #bUFFER" is NULL (%s:%d)\n", __FILE__, __LINE__); \ - return RC_NULL_POINTER; \ - } \ -} while(0) - -#endif /* RC_H_ */ diff --git a/common/utils/itti_analyzer/configure.ac b/common/utils/itti_analyzer/configure.ac deleted file mode 100644 index c6be3e01ab..0000000000 --- a/common/utils/itti_analyzer/configure.ac +++ /dev/null @@ -1,97 +0,0 @@ -AC_PREREQ([2.68]) - -define([svnversion], esyscmd([sh -c "svnversion ..|tr -d '\n'"])) - -AC_DEFINE(SVN_REVISION, "svnversion", [SVN Revision]) - -AC_INIT([itti_analyzer], [0.2.svnversion], [openair_admin@eurecom.fr]) -AC_CANONICAL_BUILD -AC_CANONICAL_TARGET -AM_INIT_AUTOMAKE([1.11 silent-rules]) - -AC_CONFIG_MACRO_DIR([m4]) - -AC_CONFIG_HEADERS([config.h]) - -AM_MAINTAINER_MODE - -AM_SILENT_RULES([yes]) - -AM_PROG_LIBTOOL - -AC_PROG_RANLIB -AC_PROG_CXX - -AC_FUNC_ALLOCA -AC_FUNC_MALLOC -AC_FUNC_REALLOC - -AC_TYPE_SIZE_T -AC_TYPE_SSIZE_T -AC_TYPE_INT8_T -AC_TYPE_INT16_T -AC_TYPE_INT32_T -AC_TYPE_INT64_T -AC_TYPE_UINT8_T -AC_TYPE_UINT16_T -AC_TYPE_UINT32_T -AC_TYPE_UINT64_T - -AC_CHECK_FUNCS([memset]) -AC_CHECK_FUNCS([socket]) -AC_CHECK_FUNCS([strdup]) -AC_CHECK_FUNCS([strerror]) -AC_CHECK_FUNCS([select]) -AC_CHECK_FUNCS([strstr]) - -AC_CHECK_HEADERS([arpa/inet.h]) -AC_CHECK_HEADERS([fcntl.h]) -AC_CHECK_HEADERS([libintl.h]) -AC_CHECK_HEADERS([malloc.h]) -AC_CHECK_HEADERS([stddef.h]) -AC_CHECK_HEADERS([netinet/in.h]) - -AC_CHECK_LIB(m, log10) - -PKG_CHECK_MODULES(XML2, [libxml-2.0 >= 2.7.8], [HAVE_XML2=true], [AC_MSG_ERROR(lixml-2.0 not installed)]) -CFLAGS="$CFLAGS $XML2_CFLAGS" -LIBS="$LIBS $XML2_LIBS" - -AM_PATH_GTK_3_0(3.0.0, [], AC_MSG_ERROR(Requirement not met: gtk >= 3.0.0)) -CFLAGS="$CFLAGS $GTK_CFLAGS" -LIBS="$LIBS $GTK_LIBS" - -dnl Add these flags -CFLAGS="$CFLAGS -Wall" -CFLAGS="$CFLAGS -Wshadow" -CFLAGS="$CFLAGS -Wcast-align" -CFLAGS="$CFLAGS -Wchar-subscripts" -CFLAGS="$CFLAGS -Wmissing-prototypes" -CFLAGS="$CFLAGS -Wmissing-declarations" -CFLAGS="$CFLAGS -Werror=implicit-function-declaration" - -AC_SUBST([AM_CFLAGS]) -AC_SUBST(ADD_CFLAGS) - -dnl *** Autoconf support *** -AC_ARG_ENABLE(autoconf, - [ --disable-autoconf disable automatic generation of configure script ], - enable_autoconf=$enableval, enable_autoconf=yes -) -AC_PATH_PROG(AUTOCONF, autoconf, @echo autoconf not available) -AC_PATH_PROG(AUTOHEADER, autoheader, @echo autoheader not available) -if test -z "$AUTOCONF"; then enable_autoconf=no ; fi -if test -z "$AUTOHEADER"; then enable_autoconf=no ; fi -if test x$enable_autoconf = xyes; then - CONFIGURE_DEPENDS="configure.in aclocal.m4" -fi -AC_SUBST(CONFIGURE_DEPENDS) - -AC_CONFIG_FILES( - libbuffers/Makefile \ - libparser/Makefile \ - libresolver/Makefile \ - libui/Makefile \ - Makefile \ -) -AC_OUTPUT diff --git a/common/utils/itti_analyzer/filters.xml b/common/utils/itti_analyzer/filters.xml deleted file mode 100644 index 7305a2294c..0000000000 --- a/common/utils/itti_analyzer/filters.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/utils/itti_analyzer/filters_mme.xml b/common/utils/itti_analyzer/filters_mme.xml deleted file mode 100644 index 7838982613..0000000000 --- a/common/utils/itti_analyzer/filters_mme.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/utils/itti_analyzer/filters_ue_enb.xml b/common/utils/itti_analyzer/filters_ue_enb.xml deleted file mode 100644 index 77859d20b6..0000000000 --- a/common/utils/itti_analyzer/filters_ue_enb.xml +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/utils/itti_analyzer/itti_analyzer.c b/common/utils/itti_analyzer/itti_analyzer.c deleted file mode 100644 index d87deb46e2..0000000000 --- a/common/utils/itti_analyzer/itti_analyzer.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#include - -#include - -#include "xml_parse.h" -#include "resolvers.h" -#include "locate_root.h" -#include "file.h" -#include "ui_main_screen.h" - -#include "rc.h" - -#define G_LOG_LEVELS (G_LOG_LEVEL_ERROR | \ - G_LOG_LEVEL_CRITICAL | \ - G_LOG_LEVEL_WARNING | \ - G_LOG_LEVEL_MESSAGE | \ - G_LOG_LEVEL_INFO | \ - G_LOG_LEVEL_DEBUG) - -int debug_buffers = 1; -int debug_parser = 0; - -static void console_log_handler(const char *log_domain, GLogLevelFlags log_level, - const char *message, gpointer user_data) -{ - GLogLevelFlags domain_log_level = (GLogLevelFlags) user_data; - time_t curr; - struct tm *today; - const char *level; - - if (ui_main_data.log_flags & domain_log_level & log_level) - { - switch (log_level & G_LOG_LEVEL_MASK) - { - case G_LOG_LEVEL_ERROR: - level = "Err "; - break; - case G_LOG_LEVEL_CRITICAL: - level = "Crit"; - break; - case G_LOG_LEVEL_WARNING: - level = "Warn"; - break; - case G_LOG_LEVEL_MESSAGE: - level = "Msg "; - break; - case G_LOG_LEVEL_INFO: - level = "Info"; - break; - case G_LOG_LEVEL_DEBUG: - level = "Dbg "; - break; - default: - fprintf(stderr, "unknown log_level %u\n", log_level); - level = NULL; - g_assert_not_reached(); - break; - } - - /* create a "timestamp" */ - time(&curr); - today = localtime(&curr); - - fprintf(stderr, "%02u:%02u:%02u %-9s %s %s\n", today->tm_hour, today->tm_min, today->tm_sec, - log_domain != NULL ? log_domain : "", level, message); - } -} - -int main(int argc, char *argv[]) -{ - int ret = 0; - - GLogLevelFlags log_flags; - - log_flags = (GLogLevelFlags) - (G_LOG_LEVEL_ERROR | - G_LOG_LEVEL_CRITICAL | - G_LOG_LEVEL_WARNING | - G_LOG_LEVEL_MESSAGE | - G_LOG_LEVEL_INFO | - G_LOG_LEVEL_DEBUG); - - /* This initialize the library and check potential ABI mismatches - * between the version it was compiled for and the actual shared - * library used. - */ - LIBXML_TEST_VERSION; - xmlInitParser(); - - /* Initialize the widget set */ - gtk_init(&argc, &argv); - - /* Parse command line options */ - ui_gtk_parse_arg (argc, argv); - - /* Set log handlers: - * Domain, Levels, Handler, Domain enabled levels */ - g_log_set_handler( NULL, log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS)); - g_log_set_handler("BUFFERS", log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS & (~(G_LOG_LEVEL_DEBUG)))); - g_log_set_handler("PARSER", log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS & (~(G_LOG_LEVEL_DEBUG)))); - g_log_set_handler("RESOLVER", log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS & (~(G_LOG_LEVEL_DEBUG)))); - g_log_set_handler("UI", log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS & (~(G_LOG_LEVEL_DEBUG)))); - g_log_set_handler("UI_CB", log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS)); - g_log_set_handler("UI_FILTER", log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS & (~(G_LOG_LEVEL_DEBUG)))); - g_log_set_handler("UI_INTER", log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS)); - g_log_set_handler("UI_TREE", log_flags, console_log_handler, (gpointer) (G_LOG_LEVELS & (~(G_LOG_LEVEL_DEBUG)))); - - CHECK_FCT(ui_gtk_initialize(argc, argv)); - - /* Enter the main event loop, and wait for user interaction */ - gtk_main (); - - /* Free the global variables that may - * have been allocated by the parser. - */ - xmlCleanupParser (); - - return ret; -} diff --git a/common/utils/itti_analyzer/libbuffers/Makefile.am b/common/utils/itti_analyzer/libbuffers/Makefile.am deleted file mode 100644 index 7af612e5e7..0000000000 --- a/common/utils/itti_analyzer/libbuffers/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -AM_CFLAGS = \ - @ADD_CFLAGS@ \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/libparser \ - -I$(top_srcdir)/libui - -noinst_LTLIBRARIES = libbuffers.la - -libbuffers_la_LDFLAGS = -all-static -libbuffers_la_SOURCES = \ - buffers.c buffers.h \ - file.c file.h \ - socket.c socket.h diff --git a/common/utils/itti_analyzer/libbuffers/buffers.c b/common/utils/itti_analyzer/libbuffers/buffers.c deleted file mode 100644 index 870c9cd40a..0000000000 --- a/common/utils/itti_analyzer/libbuffers/buffers.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("BUFFERS") - -#include - -#include "rc.h" -#include "buffers.h" - -extern int debug_buffers; - -static -int buffer_fetch(buffer_t *buffer, uint32_t offset, int size, void *value); - -/* Try to fetch 8 bits unsigned from the buffer */ -uint8_t buffer_get_uint8_t(buffer_t *buffer, uint32_t offset) -{ - uint8_t value; - - buffer_fetch(buffer, offset, 1, &value); - - return value; -} - -/* Try to fetch 16 bits unsigned from the buffer */ -uint16_t buffer_get_uint16_t(buffer_t *buffer, uint32_t offset) -{ - uint16_t value; - - buffer_fetch(buffer, offset, 2, &value); - - return value; -} - -/* Try to fetch 32 bits unsigned from the buffer */ -uint32_t buffer_get_uint32_t(buffer_t *buffer, uint32_t offset) -{ - uint32_t value; - - buffer_fetch(buffer, offset, 4, &value); - - return value; -} - -/* Try to fetch 64 bits unsigned from the buffer */ -uint64_t buffer_get_uint64_t(buffer_t *buffer, uint32_t offset) -{ - uint64_t value; - - buffer_fetch(buffer, offset, 8, &value); - - return value; -} - -static -int buffer_fetch(buffer_t *buffer, uint32_t offset, int size, void *value) -{ - if (buffer == NULL || value == NULL) - return -1; - if (size <= 0) - return -1; - - if (buffer->size_bytes < ((offset >> 3) + size)) { - g_warning("Not enough data to fetch"); - return -1; - } - - memcpy(value, &buffer->data[offset >> 3], size); - buffer->buffer_current = &buffer->data[(offset >> 3) + size]; - - return 0; -} - -int buffer_fetch_nbytes(buffer_t *buffer, uint32_t offset, int n_bytes, uint8_t *value) -{ - if (buffer->size_bytes < ((offset >> 3) + n_bytes)) { - g_warning("Not enough data to fetch"); - return -1; - } - memcpy(&value[0], &buffer->data[offset >> 3], n_bytes); - - return 0; -} - -int buffer_fetch_bits(buffer_t *buffer, uint32_t offset, int nbits, uint32_t *value) -{ - uint32_t temp = 0; - int i; - - if (buffer == NULL || value == NULL) - return RC_BAD_PARAM; - - /* We cannot fetch more than 32 bits */ - if (nbits > 32) - return RC_BAD_PARAM; - - for (i = 0; i < nbits; i++) - { - temp |= ((buffer->data[(offset + i) / 8] >> ((offset + i) % 8)) & 1) << i; - } - - *value = temp; - - return RC_OK; -} - -/** - * @brief Create a new buffer from data - * @param buffer caller reference where created buffer will be stored - * @param data Data to attach to the new buffer - * @param length Length of data buffer - * @param data_static flag that indicates if data pointer has been statically (= 0) or not (!= 0) - */ -int buffer_new_from_data(buffer_t **buffer, uint8_t *data, const uint32_t length, - int data_static) -{ - buffer_t *new; - - if (!buffer) - return RC_BAD_PARAM; - - new = malloc(sizeof(buffer_t)); - - new->size_bytes = length; - if (data && length > 0) { - if (data_static == 0) { - new->data = malloc(sizeof(uint8_t) * new->size_bytes); - memcpy(new->data, data, new->size_bytes); - } else { - new->data = data; - } - new->buffer_current = &new->data[0]; - } else { - new->buffer_current = NULL; - } - - *buffer = new; - - return 0; -} - -#define INDENTED(fILE, x, y) \ -do { \ - int indentation = x; \ - while(indentation--) fprintf(fILE, " "); \ - y; \ -} while(0) - -#define INDENT_BREAK 20 - -void buffer_dump(buffer_t *buffer, FILE *to) -{ - FILE *file = to; - uint32_t i; - - if (!buffer) - return; - if (!to) - to = stdout; - - fprintf(file, "\n"); - INDENTED(file, 4, fprintf(file, "%u\n", buffer->size_bytes)); - INDENTED(file, 4, fprintf(file, "\n")); - for (i = 0; i < buffer->size_bytes; i++) - { - if ((i % INDENT_BREAK) == 0) - fprintf(file, " "); - fprintf(file, "0x%02x ", buffer->data[i]); - if ((i % INDENT_BREAK) == (INDENT_BREAK - 1)) - fprintf(file, "\n"); - } - if ((i % INDENT_BREAK) != (INDENT_BREAK - 1)) - fprintf(file, "\n"); - INDENTED(file, 4, fprintf(file, "\n")); - fprintf(file, "\n"); -} - -int buffer_append_data(buffer_t *buffer, const uint8_t *data, const uint32_t length) -{ - if (!buffer) - return -1; - - if (data && length > 0) { - if (!buffer->data) { - buffer->size_bytes = length; - buffer->data = malloc(sizeof(uint8_t) * buffer->size_bytes); - memcpy(buffer->data, data, buffer->size_bytes); - } else { - buffer->data = realloc(buffer->data, sizeof(uint8_t) * (buffer->size_bytes + length)); - memcpy(&buffer->data[buffer->size_bytes], data, length); - buffer->size_bytes += length; - } - buffer->buffer_current = &buffer->data[0]; - } - - return 0; -} - -int buffer_has_enouch_data(buffer_t *buffer, uint32_t offset, uint32_t to_get) -{ - int underflow; - if (!buffer) - return -1; - underflow = (buffer->size_bytes >= ((offset + to_get) / 8)) ? 0 : -1; - if (underflow && debug_buffers) - g_warning("Detected Underflow offset %u, to_get %u, buffer size %u\n", - offset, to_get, buffer->size_bytes); - return underflow; -} - -void *buffer_at_offset(buffer_t *buffer, uint32_t offset) -{ -// if (buffer_has_enouch_data(buffer, 0, offset) != 0) { -// return NULL; -// } - return &buffer->data[offset / 8]; -} diff --git a/common/utils/itti_analyzer/libbuffers/buffers.h b/common/utils/itti_analyzer/libbuffers/buffers.h deleted file mode 100644 index 34ecb355ab..0000000000 --- a/common/utils/itti_analyzer/libbuffers/buffers.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include - -#ifndef BUFFERS_H_ -#define BUFFERS_H_ - -typedef struct buffer_s { - /* The size in bytes as read from socket */ - uint32_t size_bytes; - - /* Current position */ - uint8_t *buffer_current; - - /* The complete data */ - uint8_t *data; - - /* The message number as read from socket */ - uint32_t message_number; - - uint32_t message_id; -} buffer_t; - -uint8_t buffer_get_uint8_t(buffer_t *buffer, uint32_t offset); - -uint16_t buffer_get_uint16_t(buffer_t *buffer, uint32_t offset); - -uint32_t buffer_get_uint32_t(buffer_t *buffer, uint32_t offset); - -uint64_t buffer_get_uint64_t(buffer_t *buffer, uint32_t offset); - -int buffer_fetch_bits(buffer_t *buffer, uint32_t offset, int nbits, uint32_t *value); - -int buffer_fetch_nbytes(buffer_t *buffer, uint32_t offset, int n_bytes, uint8_t *value); - -void buffer_dump(buffer_t *buffer, FILE *to); - -int buffer_append_data(buffer_t *buffer, const uint8_t *data, const uint32_t length); - -int buffer_new_from_data(buffer_t **buffer, uint8_t *data, const uint32_t length, - int data_static); - -int buffer_has_enouch_data(buffer_t *buffer, uint32_t offset, uint32_t to_get); - -void *buffer_at_offset(buffer_t *buffer, uint32_t offset); - -#endif /* BUFFERS_H_ */ diff --git a/common/utils/itti_analyzer/libbuffers/file.c b/common/utils/itti_analyzer/libbuffers/file.c deleted file mode 100644 index 291bf2d216..0000000000 --- a/common/utils/itti_analyzer/libbuffers/file.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("BUFFERS") - -#include - -#include "rc.h" -#include "buffers.h" -#include "file.h" - -#define READ_BUFFER_SIZE 1024 - -int file_read_dump(buffer_t **buffer, const char *filename) -{ - int fd = -1; - buffer_t *new_buf = NULL; - uint8_t data[READ_BUFFER_SIZE]; - ssize_t current_read; - - if (!filename) - return RC_BAD_PARAM; - - if ((fd = open(filename, O_RDONLY)) == -1) { - g_warning("Cannot open %s for reading, returned %d:%s\n", - filename, errno, strerror(errno)); - return RC_FAIL; - } - - CHECK_FCT(buffer_new_from_data(&new_buf, NULL, 0, 0)); - - do { - current_read = read(fd, data, READ_BUFFER_SIZE); - if (current_read == -1) - { - g_warning("Failed to read data from file, returned %d:%s\n", - errno, strerror(errno)); - return RC_FAIL; - } - CHECK_FCT(buffer_append_data(new_buf, data, current_read)); - } while(current_read == READ_BUFFER_SIZE); - - *buffer = new_buf; - - buffer_dump(new_buf, stdout); - - close(fd); - - return RC_OK; -} diff --git a/common/utils/itti_analyzer/libbuffers/socket.c b/common/utils/itti_analyzer/libbuffers/socket.c deleted file mode 100644 index f732af70ec..0000000000 --- a/common/utils/itti_analyzer/libbuffers/socket.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("BUFFERS") - -#include - -#include "logs.h" -#include "itti_types.h" -#include "rc.h" - -#include "ui_interface.h" -#include "ui_notifications.h" -#include "ui_notif_dlg.h" - -#include "socket.h" -#include "buffers.h" - -#include "xml_parse.h" - -/* Retry connection after 100 ms */ -#define SOCKET_US_BEFORE_CONNECT_RETRY (100 * 1000) -/* About 10 minutes time-out for connecting to peer */ -#define SOCKET_NB_CONNECT_RETRY ((10 * 60 * 1000 * 1000) / SOCKET_US_BEFORE_CONNECT_RETRY) - -#define SOCKET_NB_SIGNALS_BEFORE_SIGNALLING 10 -#define SOCKET_MS_BEFORE_SIGNALLING 100 - -gboolean socket_abort_connection = FALSE; - -void *socket_thread_fct(void *arg); - -static ssize_t socket_read_data(socket_data_t *socket_data, void *buffer, size_t size, int flags) -{ - ssize_t recv_ret; - - recv_ret = recv(socket_data->sd, buffer, size, flags); - if (recv_ret == -1) { - /* Failure case */ - switch (errno) { -// case EWOULDBLOCK: - case EAGAIN: - return -1; - default: - g_info("recv failed: %s", g_strerror(errno)); - pthread_exit(NULL); - break; - } - } else if (recv_ret == 0) { - /* We lost the connection with other peer or shutdown asked */ - ui_pipe_write_message(socket_data->pipe_fd, - UI_PIPE_CONNECTION_LOST, NULL, 0); - free(socket_data->ip_address); - free(socket_data); - pthread_exit(NULL); - } - - return recv_ret; -} - -static void socket_notify_gui_update(socket_data_t *socket_data) -{ - pipe_new_signals_list_message_t pipe_signal_list_message; - - pipe_signal_list_message.signal_list = socket_data->signal_list; - - socket_data->signal_list = NULL; - socket_data->nb_signals_since_last_update = 0; - - /* Send an update notification */ - ui_pipe_write_message(socket_data->pipe_fd, - UI_PIPE_UPDATE_SIGNAL_LIST, &pipe_signal_list_message, - sizeof(pipe_signal_list_message)); - - /* Acquire the last data notification */ - socket_data->last_data_notification = g_get_monotonic_time(); -} - -static int socket_read_itti_message(socket_data_t *socket_data, - itti_socket_header_t *message_header) -{ - itti_signal_header_t itti_signal_header; - buffer_t *buffer; - uint8_t *data; - size_t data_length; - ssize_t data_read = 0; - ssize_t total_data_read = 0; - - g_assert(message_header != NULL); - - g_debug("Attempting to read signal header from socket"); - - /* Read the sub-header of signal */ - while (data_read != sizeof(itti_signal_header_t)) { - data_read = socket_read_data(socket_data, &itti_signal_header, - sizeof(itti_signal_header_t), 0); - } - - data_length = message_header->message_size - sizeof(itti_socket_header_t) - sizeof(itti_signal_header_t); - data = malloc(sizeof(uint8_t) * data_length); - - while (total_data_read < data_length) { - data_read = socket_read_data(socket_data, &data[total_data_read], - data_length - total_data_read, 0); - /* We are waiting for data */ - if (data_read < 0) { - usleep(10); - } else { - total_data_read += data_read; - } - } - - /* Create the new buffer */ - if (buffer_new_from_data(&buffer, data, data_length - sizeof(itti_message_types_t), 1) != RC_OK) { - g_error("Failed to create new buffer"); - g_assert_not_reached(); - } - - sscanf (itti_signal_header.message_number_char, MESSAGE_NUMBER_CHAR_FORMAT, &buffer->message_number); -// buffer_dump(buffer, stdout); - - /* Update the number of signals received since last GUI update */ - socket_data->nb_signals_since_last_update++; - - socket_data->signal_list = g_list_append(socket_data->signal_list, (gpointer)buffer); - - if (socket_data->nb_signals_since_last_update >= SOCKET_NB_SIGNALS_BEFORE_SIGNALLING) { - socket_notify_gui_update(socket_data); - } - - g_debug("Successfully read new signal %u from socket", buffer->message_number); - - return total_data_read + sizeof(itti_signal_header); -} - -static int socket_read_xml_definition(socket_data_t *socket_data, - itti_socket_header_t *message_header) -{ - ssize_t data_read; - ssize_t total_data_read = 0; - char *xml_definition; - size_t xml_definition_length; - pipe_xml_definition_message_t pipe_xml_definition_message; - - xml_definition_length = message_header->message_size - sizeof(*message_header); - xml_definition = malloc(xml_definition_length * sizeof(char)); - - g_debug("Attempting to read XML definition of size %zu from socket", - xml_definition_length); - - /* XML definition is a long message... so function may take some time */ - - do { - data_read = socket_read_data(socket_data, &xml_definition[total_data_read], - xml_definition_length - total_data_read, 0); - - /* We are waiting for data */ - if (data_read < 0) { - usleep(10); - } else { - total_data_read += data_read; - } - } while (total_data_read != xml_definition_length); - - pipe_xml_definition_message.xml_definition = xml_definition; - pipe_xml_definition_message.xml_definition_length = xml_definition_length - sizeof(itti_message_types_t); - - g_debug("Received XML definition of size %zu, effectively read %zu bytes", - xml_definition_length, total_data_read); - - ui_pipe_write_message(socket_data->pipe_fd, UI_PIPE_XML_DEFINITION, - &pipe_xml_definition_message, sizeof(pipe_xml_definition_message)); - - return total_data_read; -} - -static int socket_read(socket_data_t *socket_data) -{ - int ret = 0; - itti_socket_header_t message_header; - - while (ret >= 0) { - ret = socket_read_data(socket_data, &message_header, sizeof(message_header), 0); - - if (ret == -1) { - return 0; - } - - switch(message_header.message_type) { - case ITTI_DUMP_XML_DEFINITION: - socket_read_xml_definition(socket_data, &message_header); - break; - - case ITTI_DUMP_MESSAGE_TYPE: - socket_read_itti_message(socket_data, &message_header); - break; - - case ITTI_STATISTIC_MESSAGE_TYPE: - default: - g_warning("Received unknow (or not implemented) message from socket type: %d", - message_header.message_type); - break; - } - } - - return 0; -} - -static int socket_handle_disconnect_evt(socket_data_t *socket_data) -{ - /* Send shutdown to remote host */ - CHECK_FCT_POSIX(shutdown(socket_data->sd, SHUT_RDWR)); - /* Close file descriptor */ - CHECK_FCT_POSIX(close(socket_data->sd)); - - socket_data->sd = -1; - - /* Close pipe */ - close(socket_data->pipe_fd); - - /* Leaving the thread */ - pthread_exit(NULL); - - return 0; -} - -static int pipe_read_message(socket_data_t *socket_data) -{ - pipe_input_header_t input_header; - uint8_t *input_data = NULL; - size_t input_data_length = 0; - - /* Read the header */ - if (read(socket_data->pipe_fd, &input_header, sizeof(input_header)) < 0) { - g_warning("Failed to read from pipe %d: %s", socket_data->pipe_fd, - g_strerror(errno)); - return -1; - } - - input_data_length = input_header.message_size - sizeof(input_header); - - /* Checking for non-header part */ - if (input_data_length > 0) { - input_data = malloc(sizeof(uint8_t) * input_data_length); - - if (read(socket_data->pipe_fd, input_data, input_data_length) < 0) { - g_warning("Failed to read from pipe %d: %s", socket_data->pipe_fd, - g_strerror(errno)); - return -1; - } - } - - switch (input_header.message_type) { - case UI_PIPE_DISCONNECT_EVT: - return socket_handle_disconnect_evt(socket_data); - default: - g_warning("[socket] Unhandled message type %u", input_header.message_type); - g_assert_not_reached(); - } - return 0; -} - -void *socket_thread_fct(void *arg) -{ - int ret; - struct sockaddr_in si_me; - socket_data_t *socket_data; - int retry = SOCKET_NB_CONNECT_RETRY; - - /* master file descriptor list */ - fd_set master_fds; - /* temp file descriptor list for select() */ - fd_set read_fds; - int fd_max = 0; - struct timeval tv; - - socket_data = (socket_data_t *)arg; - - g_assert(socket_data != NULL); - - /* Preparing the socket */ - if ((socket_data->sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - g_warning("socket failed: %s", g_strerror(errno)); - free(socket_data->ip_address); - free(socket_data); - pthread_exit(NULL); - } - memset((void *)&si_me, 0, sizeof(si_me)); - - si_me.sin_family = AF_INET; - si_me.sin_port = htons(socket_data->port); - if (inet_aton(socket_data->ip_address, &si_me.sin_addr) == 0) { - g_warning("inet_aton() failed\n"); - free(socket_data->ip_address); - free(socket_data); - pthread_exit(NULL); - } - - /* clear the master and temp sets */ - FD_ZERO(&master_fds); - FD_ZERO(&read_fds); - - /* Add the GUI pipe to the list of sockets to monitor */ - FD_SET(socket_data->pipe_fd, &master_fds); - - /* Add the client socket to the list of sockets to monitor */ - FD_SET(socket_data->sd, &master_fds); - - /* Update the fd_max with the MAX of socket/pipe */ - fd_max = MAX(socket_data->pipe_fd, socket_data->sd); - - /* Setup the timeout for select. - * When a timeout is caught, check for new notifications to send to GUI. - */ - tv.tv_sec = 0; - tv.tv_usec = 1000 * SOCKET_MS_BEFORE_SIGNALLING; - - do { - /* Connecting to remote peer */ - ret = connect(socket_data->sd, (struct sockaddr *) &si_me, sizeof(struct sockaddr_in)); - if (ret < 0) { - if ((socket_abort_connection) || (retry < 0)) { - if (retry < 0) { - g_warning("Failed to connect to peer %s:%d", socket_data->ip_address, socket_data->port); - ui_pipe_write_message(socket_data->pipe_fd, UI_PIPE_CONNECTION_FAILED, NULL, 0); - } - free(socket_data->ip_address); - free(socket_data); - socket_abort_connection = FALSE; - /* Quit the thread */ - pthread_exit(NULL); - } - usleep(SOCKET_US_BEFORE_CONNECT_RETRY); - retry--; - } - } while (ret < 0); - - /* Set the socket as non-blocking */ - fcntl(socket_data->sd, F_SETFL, O_NONBLOCK); - - while (1) { - memcpy(&read_fds, &master_fds, sizeof(master_fds)); - - ret = select(fd_max + 1, &read_fds, NULL, NULL, &tv); - if (ret < 0) { - g_warning("Error in select: %s", g_strerror(errno)); - free(socket_data->ip_address); - free(socket_data); - /* Quit the thread */ - pthread_exit(NULL); - } else if (ret == 0) { - /* Timeout for select: check if there is new incoming messages - * since last GUI update - */ - if (socket_data->nb_signals_since_last_update > 0) { - g_debug("Timout on select and data new signal in list"); - g_debug("-> notify GUI"); - socket_notify_gui_update(socket_data); - } - - /* Reset the timeval to the max value */ - tv.tv_usec = 1000 * SOCKET_MS_BEFORE_SIGNALLING; - } - - /* Checking if there is data to read from the pipe */ - if (FD_ISSET(socket_data->pipe_fd, &read_fds)) { - FD_CLR(socket_data->pipe_fd, &read_fds); - pipe_read_message(socket_data); - } - - /* Checking if there is data to read from the socket */ - if (FD_ISSET(socket_data->sd, &read_fds)) { - FD_CLR(socket_data->sd, &read_fds); - socket_read(socket_data); - - /* Update the timeout of select if there is data not notify to GUI */ - if (socket_data->nb_signals_since_last_update > 0) { - gint64 current_time; - - current_time = g_get_monotonic_time(); - - if ((current_time - socket_data->last_data_notification) > SOCKET_MS_BEFORE_SIGNALLING) { - socket_notify_gui_update(socket_data); - tv.tv_usec = 1000 * SOCKET_MS_BEFORE_SIGNALLING; - } else { - /* Update tv */ - tv.tv_usec = (1000 * SOCKET_MS_BEFORE_SIGNALLING) - (current_time - socket_data->last_data_notification); - } - } - } - } - - return NULL; -} - -int socket_connect_to_remote_host(const char *remote_ip, const uint16_t port, - int pipe_fd) -{ - socket_data_t *socket_data; - - socket_data = calloc(1, sizeof(*socket_data)); - - socket_data->ip_address = strdup(remote_ip); - - socket_data->pipe_fd = pipe_fd; - socket_data->port = port; - socket_data->sd = -1; - - if (pthread_create(&socket_data->thread, NULL, socket_thread_fct, socket_data) != 0) { - g_warning("Failed to create thread %d:%s", errno, strerror(errno)); - free(socket_data->ip_address); - free(socket_data); - return RC_FAIL; - } - - return RC_OK; -} diff --git a/common/utils/itti_analyzer/libparser/Makefile.am b/common/utils/itti_analyzer/libparser/Makefile.am deleted file mode 100644 index bf80db2867..0000000000 --- a/common/utils/itti_analyzer/libparser/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -AM_CFLAGS = \ - @ADD_CFLAGS@ \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/libbuffers \ - -I$(top_srcdir)/libui - -noinst_LTLIBRARIES = libparser.la - -libparser_la_LDFLAGS = -all-static -libparser_la_SOURCES = \ - xml_parse.c \ - array_type.c array_type.h \ - enum_type.c enum_type.h \ - enum_value_type.c enum_value_type.h \ - file_type.c file_type.h \ - field_type.c field_type.h \ - fundamental_type.c fundamental_type.h \ - pointer_type.h pointer_type.c \ - reference_type.c reference_type.h \ - struct_type.c struct_type.h \ - typedef_type.c typedef_type.h \ - types.h types.c \ - union_type.c union_type.h diff --git a/common/utils/itti_analyzer/libparser/array_type.c b/common/utils/itti_analyzer/libparser/array_type.c deleted file mode 100644 index 1d9f741281..0000000000 --- a/common/utils/itti_analyzer/libparser/array_type.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include -#include - -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "array_type.h" -#include "fundamental_type.h" -#include "ui_interface.h" - -int array_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - types_t *type_child; - int length = 0; - char cbuf[50]; - - DISPLAY_PARSE_INFO("array", type->name, offset, parent_offset); - - /* Ignore TYPEDEF children */ - for (type_child = type->child; type_child != NULL && type_child->type == TYPE_TYPEDEF; - type_child = type_child->child) { - } - - if (type->name) { - INDENTED(stdout, indent, fprintf(stdout, "<%s>\n", type->name)); - } - if (type->child != NULL) { - int items = type->size / type_child->size; - int i; - int zero_counter = 0; - gboolean is_string = FALSE; - char *string; - int nb_digits = 0; - - /* Factorizes trailing 0 */ - if ((items > 1) && (type_child->type == TYPE_FUNDAMENTAL)) - { - for (i = items - 1; i >= 0; i--) - { - if (fundamental_read_from_buffer(type_child, buffer, parent_offset, offset + i * type_child->size) == 0) - { - zero_counter ++; - } - else - { - break; - } - } - - /* Check if this is an array of 8 bits items and if at least the firsts ones are not null */ - if ((type_child->size == 8) && (zero_counter >= 1) && ((items - zero_counter) >= 2)) - { - int end = items - zero_counter; - - /* check if this is a printable string */ - is_string = TRUE; - string = malloc(end + 1); - - for (i = 0; i < end; i++) - { - string[i] = fundamental_read_from_buffer(type_child, buffer, parent_offset, offset + i * type_child->size); - if (isprint(string[i]) == 0) - { - /* This is not a printable string */ - is_string = FALSE; - break; - } - } - - if (is_string) - { - string[i] = '\0'; - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "[0 .. %d] \"%s\"\n", end - 1, string)); - ui_set_signal_text_cb(user_data, cbuf, length); - } - } - - /* Do not factorize if there is only one null item */ - if (zero_counter <= 1) - { - zero_counter = 0; - } - } - - if (is_string == FALSE) - { - nb_digits = log10(items - zero_counter) + 1; - - for (i = 0; i < (items - zero_counter); i++) - { - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "[%*d] ", nb_digits, i)); - ui_set_signal_text_cb(user_data, cbuf, length); - - type->child->type_dissect_from_buffer ( - type->child, ui_set_signal_text_cb, user_data, buffer, parent_offset, - offset + i * type_child->size, indent, - FALSE); - } - if (zero_counter > 0) - { - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "[%d .. %d] ", i, items -1)); - ui_set_signal_text_cb(user_data, cbuf, length); - - type->child->type_dissect_from_buffer ( - type->child, ui_set_signal_text_cb, user_data, - buffer, parent_offset, offset + i * type_child->size, indent, FALSE); - } - } - } - if (type->name) { - INDENTED(stdout, indent, fprintf(stdout, "\n", type->name)); - } - - return 0; -} - -int array_type_file_print(types_t *type, int indent, FILE *file) { - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id)); - INDENTED(file, indent+4, fprintf(file, "Min ........: %d\n", type->min)); - INDENTED(file, indent+4, fprintf(file, "Max ........: %d\n", type->max)); - INDENTED(file, indent+4, fprintf(file, "Type .......: %d\n", type->type_xml)); - INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size)); - INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align)); - if (type->file_ref != NULL) - type->file_ref->type_file_print (type->file_ref, indent + 4, file); - if (type->child != NULL) - type->child->type_file_print (type->child, indent + 4, file); - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int array_type_hr_display(types_t *type, int indent) { - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Id .........: %d\n", type->id)); - INDENTED(stdout, indent+4, printf("Min ........: %d\n", type->min)); - INDENTED(stdout, indent+4, printf("Max ........: %d\n", type->max)); - INDENTED(stdout, indent+4, printf("Type .......: %d\n", type->type_xml)); - INDENTED(stdout, indent+4, printf("Size .......: %d\n", type->size)); - INDENTED(stdout, indent+4, printf("Align ......: %d\n", type->align)); - if (type->file_ref != NULL) - type->file_ref->type_hr_display (type->file_ref, indent + 4); - if (type->child != NULL) - type->child->type_hr_display (type->child, indent + 4); - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/enum_type.c b/common/utils/itti_analyzer/libparser/enum_type.c deleted file mode 100644 index dbc99095bc..0000000000 --- a/common/utils/itti_analyzer/libparser/enum_type.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "enum_type.h" -#include "ui_interface.h" - -char *enum_type_get_name_from_value(types_t *type, uint32_t value) -{ - char *enum_name = "UNKNOWN"; - types_t *enum_value; - - /* Loop on each enumeration values */ - for (enum_value = type->child; enum_value; enum_value = enum_value->next) { - if (value == enum_value->init_value) { - enum_name = enum_value->name; - break; - } - } - return enum_name; -} - -int enum_type_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - uint32_t value = 0; - types_t *values; - - DISPLAY_PARSE_INFO("enum", type->name, offset, parent_offset); - - value = buffer_get_uint32_t(buffer, parent_offset + offset); - - for (values = type->child; values; values = values->next) { - if (value == values->init_value) { - values->parent = type; - values->type_dissect_from_buffer( - values, ui_set_signal_text_cb, user_data, buffer, offset, parent_offset, - type->name == NULL ? indent: indent + DISPLAY_TAB_SIZE, FALSE); - break; - } - } - if (values == NULL) { - int length = 0; - char cbuf[50]; - - length = sprintf(cbuf, "(0x%08x) UNKNOWN;\n", value); - ui_set_signal_text_cb(user_data, cbuf, length); - } - - return 0; -} - -int enum_type_file_print(types_t *type, int indent, FILE *file) -{ - types_t *values; - - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size)); - INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align)); - INDENTED(file, indent+4, fprintf(file, "Artificial .: %d\n", type->artificial)); - INDENTED(file, indent+4, fprintf(file, "File .......: %s\n", type->file)); - INDENTED(file, indent+4, fprintf(file, "Line .......: %d\n", type->line)); - if (type->file_ref != NULL) - type->file_ref->type_file_print(type->file_ref, indent+4, file); - /* Call enum values display */ - for (values = type->child; values; values = values->next) { - values->type_file_print(values, indent + 4, file); - } - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int enum_type_hr_display(types_t *type, int indent) -{ - types_t *values; - - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent+4, printf("Size .......: %d\n", type->size)); - INDENTED(stdout, indent+4, printf("Align ......: %d\n", type->align)); - INDENTED(stdout, indent+4, printf("Artificial .: %d\n", type->artificial)); - INDENTED(stdout, indent+4, printf("File .......: %s\n", type->file)); - INDENTED(stdout, indent+4, printf("Line .......: %d\n", type->line)); - if (type->file_ref != NULL) - type->file_ref->type_hr_display(type->file_ref, indent+4); - /* Call enum values display */ - for (values = type->child; values; values = values->next) { - values->type_hr_display(values, indent + 4); - } - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/enum_value_type.c b/common/utils/itti_analyzer/libparser/enum_value_type.c deleted file mode 100644 index 801317daaf..0000000000 --- a/common/utils/itti_analyzer/libparser/enum_value_type.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "enum_value_type.h" -#include "ui_interface.h" - -uint32_t last_enum_value; - -int enum_value_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - types_t *type_parent = NULL; - uint32_t value = 0; - - DISPLAY_PARSE_INFO("enum_value", type->name, offset, parent_offset); - - value = buffer_get_uint32_t(buffer, parent_offset + offset); - if (type->name) { - int length = 0; - char cbuf[50 + strlen(type->name)]; - - /* Search for enum variable name and check if it is used in association with a union type */ - { - if (type->parent != NULL) { - /* Ignore ENUMERATION and TYPEDEF parents */ - for (type_parent = type->parent; (type_parent != NULL) && ((type_parent->type == TYPE_ENUMERATION) || (type_parent->type == TYPE_TYPEDEF)); - type_parent = type_parent->parent) { - } - } - if ((type_parent != NULL) && (type_parent->name != NULL) && (strcmp(type_parent->name, "present") == 0)) - { - /* ASN1 union, keep the "present" member */ - last_enum_value = value; - } - else - { - last_enum_value = 0; - } - } - length = sprintf(cbuf, "(0x%08x) %s;\n", value, type->name); - ui_set_signal_text_cb(user_data, cbuf, length); - } - - return 0; -} - -int enum_value_file_print(types_t *type, int indent, FILE *file) -{ - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent+4, fprintf(file, "Value ......: %d\n", type->init_value)); - if (type->file_ref != NULL) - type->file_ref->type_file_print(type->file_ref, indent+4, file); - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int enum_value_type_hr_display(types_t *type, int indent) -{ - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent+4, printf("Value ......: %d\n", type->init_value)); - if (type->file_ref != NULL) - type->file_ref->type_hr_display(type->file_ref, indent+4); - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/field_type.c b/common/utils/itti_analyzer/libparser/field_type.c deleted file mode 100644 index b64d3bd0c1..0000000000 --- a/common/utils/itti_analyzer/libparser/field_type.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "rc.h" - -#include "field_type.h" -#include "buffers.h" -#include "ui_interface.h" - -int field_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - int length = 0; - char cbuf[50 + (type->name ? strlen (type->name) : 0)]; - types_t *type_child; - char array_info[50]; - new_line = FALSE; - - DISPLAY_PARSE_INFO("field", type->name, offset, parent_offset); - - CHECK_FCT(buffer_has_enouch_data(buffer, parent_offset + offset, type->size / 8)); - - if (type->bits == -1) { - if ((type->name != NULL) && (strcmp(type->name, "_asn_ctx") == 0)) { - /* Hide ASN1 asn_struct_ctx_t struct that hold context for parsing across buffer boundaries */ - /* - INDENTED_STRING(cbuf, indent, sprintf(cbuf, ".asn_ctx ...\n")); - length = strlen (cbuf); - - ui_set_signal_text_cb(user_data, cbuf, length); - */ - } - else { - if (type->child != NULL) { - /* Ignore TYPEDEF children */ - for (type_child = type->child; type_child != NULL && type_child->type == TYPE_TYPEDEF; type_child = - type_child->child) { - } - - if (type_child->type == TYPE_ARRAY) { - types_t *type_array_child; - - /* Ignore TYPEDEF children */ - for (type_array_child = type_child->child; - type_array_child != NULL && type_array_child->type == TYPE_TYPEDEF; type_array_child = - type_array_child->child) { - } - - sprintf (array_info, "[%d]", type_child->size / type_array_child->size); - } - else { - array_info[0] = '\0'; - } - - DISPLAY_TYPE("Fld"); - - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, ".%s%s = ", type->name ? type->name : "Field", array_info)); - ui_set_signal_text_cb(user_data, cbuf, length); - - if (type_child->type == TYPE_ARRAY) { - DISPLAY_BRACE(ui_set_signal_text_cb(user_data, "{", 1);) - ui_set_signal_text_cb(user_data, "\n", 1); - new_line = TRUE; - } - /* - if (type_child->type == TYPE_STRUCT || type_child->type == TYPE_UNION) { - DISPLAY_BRACE(ui_set_signal_text_cb(user_data, "{", 1);) - ui_set_signal_text_cb(user_data, "\n", 1); - new_line = TRUE; - } - */ - - type->child->parent = type; - type->child->type_dissect_from_buffer( - type->child, ui_set_signal_text_cb, user_data, buffer, - parent_offset, offset + type->offset, new_line ? indent + DISPLAY_TAB_SIZE : indent, new_line); - - DISPLAY_BRACE( - if (type_child->type == TYPE_ARRAY) { - DISPLAY_TYPE("Fld"); - - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "};\n")); - ui_set_signal_text_cb(user_data, cbuf, length); - }); - /* - DISPLAY_BRACE( - if (type_child->type == TYPE_STRUCT || type_child->type == TYPE_UNION) { - DISPLAY_TYPE("Fld"); - INDENTED_STRING(cbuf, indent, sprintf(cbuf, "};\n")); - length = strlen (cbuf); - - ui_set_signal_text_cb(user_data, cbuf, length); - }); - */ - } - } - } - else { - /* The field is only composed of bits */ - uint32_t value = 0; - - CHECK_FCT(buffer_fetch_bits(buffer, offset + type->offset + parent_offset, type->bits, &value)); - - DISPLAY_TYPE("Fld"); - - INDENTED_STRING(cbuf, indent, - length = sprintf(cbuf, ".%s:%d = (0x%0*x) %d;\n", type->name ? type->name : "Field", type->bits, (type->bits + 3) / 4, value, value)); - ui_set_signal_text_cb(user_data, cbuf, length); - } - - return 0; -} - -int field_type_file_print(types_t *type, int indent, FILE *file) { - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id)); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent+4, fprintf(file, "Bits .......: %d\n", type->bits)); - INDENTED(file, indent+4, fprintf(file, "Type .......: %d\n", type->type_xml)); - INDENTED(file, indent+4, fprintf(file, "Offset .....: %d\n", type->offset)); - INDENTED(file, indent+4, fprintf(file, "Context ....: %d\n", type->context)); - INDENTED(file, indent+4, fprintf(file, "File .......: %s\n", type->file)); - INDENTED(file, indent+4, fprintf(file, "Line .......: %d\n", type->line)); - if (type->file_ref != NULL) - type->file_ref->type_file_print (type->file_ref, indent + 4, file); - if (type->child != NULL) - type->child->type_file_print (type->child, indent + 4, file); - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int field_type_hr_display(types_t *type, int indent) { - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Id .........: %d\n", type->id)); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent+4, printf("Bits .......: %d\n", type->bits)); - INDENTED(stdout, indent+4, printf("Type .......: %d\n", type->type_xml)); - INDENTED(stdout, indent+4, printf("Offset .....: %d\n", type->offset)); - INDENTED(stdout, indent+4, printf("Context ....: %d\n", type->context)); - INDENTED(stdout, indent+4, printf("File .......: %s\n", type->file)); - INDENTED(stdout, indent+4, printf("Line .......: %d\n", type->line)); - if (type->file_ref != NULL) - type->file_ref->type_hr_display (type->file_ref, indent + 4); - if (type->child != NULL) - type->child->type_hr_display (type->child, indent + 4); - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/fundamental_type.c b/common/utils/itti_analyzer/libparser/fundamental_type.c deleted file mode 100644 index 92dd1c75cb..0000000000 --- a/common/utils/itti_analyzer/libparser/fundamental_type.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "fundamental_type.h" -#include "ui_interface.h" - -uint64_t fundamental_read_from_buffer(types_t *type, buffer_t *buffer, uint32_t offset, uint32_t parent_offset) { - uint64_t value; - - switch (type->size) { - case 8: - value = buffer_get_uint8_t (buffer, offset + parent_offset); - break; - - case 16: - value = buffer_get_uint16_t (buffer, offset + parent_offset); - break; - - case 32: - value = buffer_get_uint32_t (buffer, offset + parent_offset); - break; - - case 64: - value = buffer_get_uint64_t (buffer, offset + parent_offset); - break; - - default: - /* ??? */ - value = 0; - break; - } - return value; -} - -int fundamental_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - int length = 0; - char cbuf[200]; - int type_unsigned; - uint8_t value8; - uint16_t value16; - uint32_t value32; - uint64_t value64; - - DISPLAY_PARSE_INFO("fundamental", type->name, offset, parent_offset); - - memset (cbuf, 0, 200); - - type_unsigned = strstr (type->name, "unsigned") == NULL ? 0 : 1; - - value64 = fundamental_read_from_buffer(type, buffer, offset, parent_offset); - - indent = new_line ? indent : 0; - if (indent > 0) - { - DISPLAY_TYPE("Fun"); - } - switch (type->size) { - case 8: - value8 = (uint8_t) value64; - INDENTED_STRING(cbuf, indent, - length = sprintf(cbuf, type_unsigned ? "(0x%02" PRIx8 ") %3" PRIu8 ";\n" : "(0x%02" PRIx8 ") %4" PRId8 ";\n", value8, value8)); - break; - - case 16: - value16 = (uint16_t) value64; - INDENTED_STRING(cbuf, indent, - length = sprintf(cbuf, type_unsigned ? "(0x%04" PRIx16 ") %5" PRIu16 ";\n" : "(0x%04" PRIx16 ") %6" PRId16 ";\n", value16, value16)); - break; - - case 32: - value32 = (uint32_t) value64; - INDENTED_STRING(cbuf, indent, - length = sprintf(cbuf, type_unsigned ? "(0x%08" PRIx32 ") %9" PRIu32 ";\n" : "(0x%08" PRIx32 ") %10" PRId32 ";\n", value32, value32)); - break; - - case 64: - INDENTED_STRING(cbuf, indent, - length = sprintf(cbuf, type_unsigned ? "(0x%016" PRIx64 ") %20" PRIu64 ";\n" : "(0x%016" PRIx64 ") %20" PRId64 ";\n", value64, value64)); - break; - - default: - /* ??? */ - break; - } - ui_set_signal_text_cb(user_data, cbuf, length); - - return 0; -} - -int fundamental_type_file_print(types_t *type, int indent, FILE *file) { - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id)); - INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size)); - INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align)); - if (type->file_ref != NULL) - type->file_ref->type_file_print (type->file_ref, indent + 4, file); - INDENTED(file, indent, fprintf(file, "\n")); - return 0; -} - -int fundamental_type_hr_display(types_t *type, int indent) { - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent+4, printf("Id .........: %d\n", type->id)); - INDENTED(stdout, indent+4, printf("Size .......: %d\n", type->size)); - INDENTED(stdout, indent+4, printf("Align ......: %d\n", type->align)); - if (type->file_ref != NULL) - type->file_ref->type_hr_display (type->file_ref, indent + 4); - INDENTED(stdout, indent, printf("\n")); - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/fundamental_type.h b/common/utils/itti_analyzer/libparser/fundamental_type.h deleted file mode 100644 index 07ceb3b9ed..0000000000 --- a/common/utils/itti_analyzer/libparser/fundamental_type.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "types.h" - -#ifndef FUNDAMENTAL_TYPE_H_ -#define FUNDAMENTAL_TYPE_H_ - -uint64_t fundamental_read_from_buffer(types_t *type, buffer_t *buffer, uint32_t offset, uint32_t parent_offset); - -int fundamental_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); - -int fundamental_type_file_print(types_t *type, int indent, FILE *file); - -int fundamental_type_hr_display(types_t *type, int indent); - -#endif /* FUNDAMENTAL_TYPE_H_ */ diff --git a/common/utils/itti_analyzer/libparser/pointer_type.c b/common/utils/itti_analyzer/libparser/pointer_type.c deleted file mode 100644 index e4571f9f48..0000000000 --- a/common/utils/itti_analyzer/libparser/pointer_type.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "pointer_type.h" -#include "ui_interface.h" - -int pointer_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - int length = 0, i; - char cbuf[200]; - - DISPLAY_PARSE_INFO("pointer", type->name, offset, parent_offset); - - memset (cbuf, 0, 200); - - uint8_t value[type->size / 8]; - - buffer_fetch_nbytes(buffer, parent_offset + offset, type->size / 8, value); - - indent = new_line ? indent : 0; - if (indent > 0) - { - DISPLAY_TYPE("Ptr"); - } - if (type->child && type->child->name) { - /* - INDENTED(stdout, indent, fprintf(stdout, "<%s>0x%08x\n", - type->child->name, value, type->child->name)); - */ - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "(%s *) 0x", type->child->name)); - } - else { - /* - INDENTED(stdout, indent, fprintf(stdout, "0x%08x\n", - value)); - */ - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "(void *) 0x")); - } - - /* Append the value */ - for (i = type->size / 8 - 1; i >= 0; i--) { - length += sprintf(&cbuf[length], "%02x", value[i]); - } - length += sprintf(&cbuf[length], ";\n"); - ui_set_signal_text_cb(user_data, cbuf, length); - - return 0; -} - -int pointer_type_file_print(types_t *type, int indent, FILE *file) { - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id)); - INDENTED(file, indent+4, fprintf(file, "Type .......: %d\n", type->type_xml)); - INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size)); - INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align)); - if (type->child != NULL) { - if (type->child->type == TYPE_FUNCTION) { - INDENTED(file, indent+4, fprintf(file, "\n")); - INDENTED(file, indent+8, fprintf(file, "To be done\n")); - INDENTED(file, indent+4, fprintf(file, "\n")); - } else { - type->child->type_file_print (type->child, indent + 4, file); - } - } - if (type->file_ref != NULL) - type->file_ref->type_file_print (type->file_ref, indent + 4, file); - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int pointer_type_hr_display(types_t *type, int indent) { - return pointer_type_file_print(type, indent, stdout); -} diff --git a/common/utils/itti_analyzer/libparser/pointer_type.h b/common/utils/itti_analyzer/libparser/pointer_type.h deleted file mode 100644 index be2b6cc33c..0000000000 --- a/common/utils/itti_analyzer/libparser/pointer_type.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "types.h" - -#ifndef POINTER_TYPE_H_ -#define POINTER_TYPE_H_ - -int pointer_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); - -int pointer_type_file_print(types_t *type, int indent, FILE *file); - -int pointer_type_hr_display(types_t *type, int indent); - -#endif /* POINTER_TYPE_H_ */ diff --git a/common/utils/itti_analyzer/libparser/reference_type.c b/common/utils/itti_analyzer/libparser/reference_type.c deleted file mode 100644 index 8d0fec4e61..0000000000 --- a/common/utils/itti_analyzer/libparser/reference_type.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "reference_type.h" -#include "ui_interface.h" - -int reference_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - DISPLAY_PARSE_INFO("reference", type->name, offset, parent_offset); - - if (type->name) { - INDENTED(stdout, indent, fprintf(stdout, "<%s>\n", type->name)); - } - if (type->child != NULL) - type->child->type_dissect_from_buffer(type->child, ui_set_signal_text_cb, - user_data, buffer, offset, parent_offset, - type->name == NULL ? indent: indent + DISPLAY_TAB_SIZE, TRUE); - if (type->name) { - INDENTED(stdout, indent, fprintf(stdout, "\n", type->name)); - } - - return 0; -} - -int reference_type_file_print(types_t *type, int indent, FILE *file) -{ - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id)); - INDENTED(file, indent+4, fprintf(file, "Type .......: %d\n", type->type_xml)); - INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size)); - INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align)); - INDENTED(file, indent+4, fprintf(file, "Context ....: %d\n", type->context)); - INDENTED(file, indent+4, fprintf(file, "Offset .....: %d\n", type->offset)); - INDENTED(file, indent+4, fprintf(file, "Line .......: %d\n", type->line)); - INDENTED(file, indent+4, fprintf(file, "File .......: %s\n", type->file)); - if (type->child != NULL) - type->child->type_file_print(type->child, indent+4, file); - if (type->file_ref != NULL) - type->file_ref->type_file_print(type->file_ref, indent+4, file); - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int reference_type_hr_display(types_t *type, int indent) -{ - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent+4, printf("Id .........: %d\n", type->id)); - INDENTED(stdout, indent+4, printf("Type .......: %d\n", type->type_xml)); - INDENTED(stdout, indent+4, printf("Size .......: %d\n", type->size)); - INDENTED(stdout, indent+4, printf("Align ......: %d\n", type->align)); - INDENTED(stdout, indent+4, printf("Context ....: %d\n", type->context)); - INDENTED(stdout, indent+4, printf("Offset .....: %d\n", type->offset)); - INDENTED(stdout, indent+4, printf("Line .......: %d\n", type->line)); - INDENTED(stdout, indent+4, printf("File .......: %s\n", type->file)); - if (type->child != NULL) - type->child->type_hr_display(type->child, indent+4); - if (type->file_ref != NULL) - type->file_ref->type_hr_display(type->file_ref, indent+4); - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/reference_type.h b/common/utils/itti_analyzer/libparser/reference_type.h deleted file mode 100644 index da56e9f942..0000000000 --- a/common/utils/itti_analyzer/libparser/reference_type.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "types.h" - -#ifndef REFERENCE_TYPE_H_ -#define REFERENCE_TYPE_H_ - -int reference_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); - -int reference_type_file_print(types_t *type, int indent, FILE *file); - -int reference_type_hr_display(types_t *type, int indent); - -#endif /* REFERENCE_TYPE_H_ */ diff --git a/common/utils/itti_analyzer/libparser/struct_type.c b/common/utils/itti_analyzer/libparser/struct_type.c deleted file mode 100644 index 09d5280ea5..0000000000 --- a/common/utils/itti_analyzer/libparser/struct_type.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "rc.h" - -#include "struct_type.h" -#include "buffers.h" -#include "ui_callbacks.h" -#include "ui_interface.h" - -int struct_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - int i; - char cbuf[50 + (type->name ? strlen (type->name) : 0)]; - int length = 0; - char *name; - - memset (cbuf, 0, sizeof(cbuf)); - - DISPLAY_PARSE_INFO("structure", type->name, offset, parent_offset); - - if (new_line) { - DISPLAY_TYPE("Str"); - } - - if (type->name) { - name = type->name; - } - else { - name = "_anonymous_"; - } - - if ((strcmp (name, "IttiMsgText_s") == 0) && - (type->members_child[0] != NULL) && (strcmp (type->members_child[0]->name, "size") == 0) && - (type->members_child[1] != NULL) && (strcmp (type->members_child[1]->name, "text") == 0)) { - uint8_t *buf; - - length = buffer_get_uint32_t (buffer, offset + parent_offset); - buf = malloc (length + 1); - buf[0] = '\n'; - buffer_fetch_nbytes(buffer, parent_offset + offset + 32, length, &buf[1]); - length = ui_callback_check_string ((char *) &buf[1], length, 0); - ui_set_signal_text_cb(user_data, (char *) buf, length + 1); - } - else - { - INDENTED_STRING(cbuf, new_line ? indent : 0, length = sprintf (cbuf, "%s :", name)); - DISPLAY_BRACE(length += sprintf(&cbuf[length], " {");); - length += sprintf(&cbuf[length], "\n"); - ui_set_signal_text_cb(user_data, cbuf, length); - - for (i = 0; i < type->nb_members; i++) { - if (type->members_child[i] != NULL) - type->members_child[i]->type_dissect_from_buffer ( - type->members_child[i], ui_set_signal_text_cb, user_data, - buffer, offset, parent_offset, indent + DISPLAY_TAB_SIZE, TRUE); - } - } - - DISPLAY_BRACE( - DISPLAY_TYPE("Str"); - - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "};\n")); - ui_set_signal_text_cb(user_data, cbuf, length);) - - return 0; -} - -int struct_type_file_print(types_t *type, int indent, FILE *file) { - int i; - if (type == NULL) - return -1; - if (file == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id)); - INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size)); - INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align)); - INDENTED(file, indent+4, fprintf(file, "Artificial .: %d\n", type->artificial)); - INDENTED(file, indent+4, fprintf(file, "File .......: %s\n", type->file)); - INDENTED(file, indent+4, fprintf(file, "Line .......: %d\n", type->line)); - INDENTED(file, indent+4, fprintf(file, "Members ....: %s\n", type->members)); - INDENTED(file, indent+4, fprintf(file, "Mangled ....: %s\n", type->mangled)); - INDENTED(file, indent+4, fprintf(file, "Demangled ..: %s\n", type->demangled)); - if (type->file_ref != NULL) - type->file_ref->type_file_print (type->file_ref, indent + 4, file); - for (i = 0; i < type->nb_members; i++) { - if (type->members_child[i] != NULL) - type->members_child[i]->type_file_print (type->members_child[i], indent + 4, file); - } - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int struct_type_hr_display(types_t *type, int indent) { - int i; - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent+4, printf("Id .........: %d\n", type->id)); - INDENTED(stdout, indent+4, printf("Size .......: %d\n", type->size)); - INDENTED(stdout, indent+4, printf("Align ......: %d\n", type->align)); - INDENTED(stdout, indent+4, printf("Artificial .: %d\n", type->artificial)); - INDENTED(stdout, indent+4, printf("File .......: %s\n", type->file)); - INDENTED(stdout, indent+4, printf("Line .......: %d\n", type->line)); - INDENTED(stdout, indent+4, printf("Members ....: %s\n", type->members)); - INDENTED(stdout, indent+4, printf("Mangled ....: %s\n", type->mangled)); - INDENTED(stdout, indent+4, printf("Demangled ..: %s\n", type->demangled)); - if (type->file_ref != NULL) - type->file_ref->type_hr_display (type->file_ref, indent + 4); - for (i = 0; i < type->nb_members; i++) { - if (type->members_child[i] != NULL) - type->members_child[i]->type_hr_display (type->members_child[i], indent + 4); - } - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/typedef_type.c b/common/utils/itti_analyzer/libparser/typedef_type.c deleted file mode 100644 index e5cee1a1cf..0000000000 --- a/common/utils/itti_analyzer/libparser/typedef_type.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "typedef_type.h" -#include "ui_interface.h" - -int typedef_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - int length = 0; - char cbuf[50 + (type->name ? strlen (type->name) : 0)]; - types_t *type_child = NULL; - - DISPLAY_PARSE_INFO("typedef", type->name, offset, parent_offset); - - if (type->child != NULL) { - /* Ignore TYPEDEF children */ - for (type_child = type->child; type_child != NULL && type_child->type == TYPE_TYPEDEF; type_child = - type_child->child) { - } - } - - if ((type_child == NULL) || (type_child->type != TYPE_FUNDAMENTAL)) - { - INDENTED_STRING(cbuf, new_line ? indent : 0, length = sprintf (cbuf, "%s, ", type->name)); - ui_set_signal_text_cb(user_data, cbuf, length); - - new_line = FALSE; - } - - /* Simply call next_type */ - if (type->child != NULL) { - type->child->parent = type; - type->child->type_dissect_from_buffer( - type->child, ui_set_signal_text_cb, user_data, buffer, offset, parent_offset, indent, new_line); - } - - return 0; -} - -int typedef_type_file_print(types_t *type, int indent, FILE *file) -{ - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent+4, fprintf(file, "Type .......: %d\n", type->type_xml)); - INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size)); - INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align)); - INDENTED(file, indent+4, fprintf(file, "Artificial .: %d\n", type->artificial)); - INDENTED(file, indent+4, fprintf(file, "File .......: %s\n", type->file)); - INDENTED(file, indent+4, fprintf(file, "Line .......: %d\n", type->line)); - INDENTED(file, indent+4, fprintf(file, "Members ....: %s\n", type->members)); - INDENTED(file, indent+4, fprintf(file, "Mangled ....: %s\n", type->mangled)); - INDENTED(file, indent+4, fprintf(file, "Demangled ..: %s\n", type->demangled)); - if (type->file_ref != NULL) - type->file_ref->type_file_print(type->file_ref, indent+4, file); - if (type->child != NULL) - type->child->type_file_print(type->child, indent+4, file); - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int typedef_type_hr_display(types_t *type, int indent) -{ - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent+4, printf("Type .......: %d\n", type->type_xml)); - INDENTED(stdout, indent+4, printf("Size .......: %d\n", type->size)); - INDENTED(stdout, indent+4, printf("Align ......: %d\n", type->align)); - INDENTED(stdout, indent+4, printf("Artificial .: %d\n", type->artificial)); - INDENTED(stdout, indent+4, printf("File .......: %s\n", type->file)); - INDENTED(stdout, indent+4, printf("Line .......: %d\n", type->line)); - INDENTED(stdout, indent+4, printf("Members ....: %s\n", type->members)); - INDENTED(stdout, indent+4, printf("Mangled ....: %s\n", type->mangled)); - INDENTED(stdout, indent+4, printf("Demangled ..: %s\n", type->demangled)); - if (type->file_ref != NULL) - type->file_ref->type_hr_display(type->file_ref, indent+4); - if (type->child != NULL) - type->child->type_hr_display(type->child, indent+4); - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/typedef_type.h b/common/utils/itti_analyzer/libparser/typedef_type.h deleted file mode 100644 index b5710dbfcb..0000000000 --- a/common/utils/itti_analyzer/libparser/typedef_type.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "types.h" - -#ifndef TYPEDEF_TYPE_H_ -#define TYPEDEF_TYPE_H_ - -int typedef_type_file_print(types_t *type, int indent, FILE *file); - -int typedef_type_hr_display(types_t *type, int indent); - -int typedef_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); - -#endif /* TYPEDEF_TYPE_H_ */ diff --git a/common/utils/itti_analyzer/libparser/types.c b/common/utils/itti_analyzer/libparser/types.c deleted file mode 100644 index 406db5249c..0000000000 --- a/common/utils/itti_analyzer/libparser/types.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "types.h" -#include "array_type.h" -#include "enum_type.h" -#include "fundamental_type.h" -#include "struct_type.h" -#include "union_type.h" -#include "typedef_type.h" -#include "enum_value_type.h" -#include "file_type.h" -#include "field_type.h" -#include "reference_type.h" -#include "pointer_type.h" - -types_t *type_new(enum type_e type) -{ - types_t *new_p; - - new_p = calloc(1, sizeof(types_t)); - - new_p->type = type; - - switch(type) { - case TYPE_FUNCTION: - /* Nothing to do for now. Display is done by pointer type */ - break; - case TYPE_ENUMERATION: - new_p->type_hr_display = enum_type_hr_display; - new_p->type_file_print = enum_type_file_print; - new_p->type_dissect_from_buffer = enum_type_dissect_from_buffer; - break; - case TYPE_FUNDAMENTAL: - new_p->type_hr_display = fundamental_type_hr_display; - new_p->type_file_print = fundamental_type_file_print; - new_p->type_dissect_from_buffer = fundamental_dissect_from_buffer; - break; - case TYPE_STRUCT: - new_p->type_hr_display = struct_type_hr_display; - new_p->type_file_print = struct_type_file_print; - new_p->type_dissect_from_buffer = struct_dissect_from_buffer; - break; - case TYPE_UNION: - new_p->type_hr_display = union_type_hr_display; - new_p->type_file_print = union_type_file_print; - new_p->type_dissect_from_buffer = union_dissect_from_buffer; - break; - case TYPE_TYPEDEF: - new_p->type_hr_display = typedef_type_hr_display; - new_p->type_file_print = typedef_type_file_print; - new_p->type_dissect_from_buffer = typedef_dissect_from_buffer; - break; - case TYPE_ENUMERATION_VALUE: - new_p->type_hr_display = enum_value_type_hr_display; - new_p->type_file_print = enum_value_file_print; - new_p->type_dissect_from_buffer = enum_value_dissect_from_buffer; - break; - case TYPE_FILE: - new_p->type_hr_display = file_type_hr_display; - new_p->type_file_print = file_type_file_print; -// new_p->type_dissect_from_buffer = file_dissect_from_buffer; - break; - case TYPE_FIELD: - new_p->type_hr_display = field_type_hr_display; - new_p->type_file_print = field_type_file_print; - new_p->type_dissect_from_buffer = field_dissect_from_buffer; - break; - case TYPE_REFERENCE: - new_p->type_hr_display = reference_type_hr_display; - new_p->type_file_print = reference_type_file_print; - new_p->type_dissect_from_buffer = reference_dissect_from_buffer; - break; - case TYPE_ARRAY: - new_p->type_hr_display = array_type_hr_display; - new_p->type_file_print = array_type_file_print; - new_p->type_dissect_from_buffer = array_dissect_from_buffer; - break; - case TYPE_POINTER: - new_p->type_hr_display = pointer_type_hr_display; - new_p->type_file_print = pointer_type_file_print; - new_p->type_dissect_from_buffer = pointer_dissect_from_buffer; - break; - default: - break; - } - - return new_p; -} - -int types_insert_tail(types_t **head, types_t *to_insert) -{ - if (to_insert == NULL || head == NULL) - return -1; - if (*head == NULL) { - *head = to_insert; - } else { - types_t *last = *head; - while(last->next != NULL) { - last = last->next; - } - last->next = to_insert; - to_insert->previous = last; - } - to_insert->head = *head; - return 0; -} - -void types_hr_display(types_t *head) -{ - types_t *current = head; - - if (head == NULL) { - printf("Empty list\n"); - /* Empty list */ - return; - } - - while((current = current->next) != NULL) - { - current->type_hr_display(current, 0); - } -} diff --git a/common/utils/itti_analyzer/libparser/types.h b/common/utils/itti_analyzer/libparser/types.h deleted file mode 100644 index c449c445fd..0000000000 --- a/common/utils/itti_analyzer/libparser/types.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include - -#include "buffers.h" -#include "ui_main_screen.h" -#include "ui_interface.h" - -#ifndef TYPES_H_ -#define TYPES_H_ - -/* Activate to display the type at the beginning of the line (debug option) */ -#define ENABLE_DISPLAY_TYPE 0 - -/* Activate to display the parse information before processing each item (debug option) */ -#define ENABLE_DISPLAY_PARSE_INFO 0 - -/* Activate to show braces, in increase the number of displayed lines (formating option)*/ -#define ENABLE_DISPLAY_BRACE 1 - -#if (ENABLE_DISPLAY_TYPE != 0) -# define DISPLAY_TYPE(tYPE) ui_set_signal_text_cb(user_data, tYPE" ", strlen(tYPE) + 1); -#else -# define DISPLAY_TYPE(tYPE) -#endif - -#define DISPLAY_TAB_SIZE (2) - -#if (ENABLE_DISPLAY_PARSE_INFO != 0) -# define DISPLAY_PARSE_INFO(tYPE, nAME, oFFSET, pARENToFFSET) \ - { \ - char buf[200]; \ - sprintf(buf, "/* %s \"%s\" %d %d */\n", tYPE, nAME, oFFSET, pARENToFFSET); \ - ui_set_signal_text_cb(user_data, buf, strlen(buf)); \ - } -#else -# define DISPLAY_PARSE_INFO(tYPE, nAME, oFFSET, pARENToFFSET) -#endif - -#if (ENABLE_DISPLAY_BRACE != 0) -# define DISPLAY_BRACE(cODE) if (ui_main_data.display_brace) {cODE} -#else -# define DISPLAY_BRACE(cODE) -#endif - -enum type_e { - TYPE_ENUMERATION, - TYPE_ENUMERATION_VALUE, - TYPE_STRUCT, - TYPE_UNION, - TYPE_FUNDAMENTAL, - TYPE_TYPEDEF, - TYPE_ARRAY, - TYPE_REFERENCE, - TYPE_FIELD, - TYPE_FUNCTION, - TYPE_ARGUMENT, - TYPE_POINTER, - TYPE_FILE, -}; - -/* Forward declarations */ -struct types_s; - -typedef int (*type_hr_display_t)(struct types_s *type, int indent); -typedef int (*type_ui_display_t)(struct types_s *type, int indent); -typedef int (*type_file_print_t)(struct types_s *type, int indent, FILE *file); - -/** - * type_dissect_from_buffer_t - * @param type The current type - * @param ui_set_signal_text_cb GUI display function - * @param user_data Transparent data to pass to the GUI display function - * @param buffer The buffer containing data to dissect - * @param offset offset of field from the beginning of the parent - * @param parent_offset offset of the parent from begining - **/ -typedef int (*type_dissect_from_buffer_t)( - struct types_s *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); - -typedef struct types_s { - /* The type of the current description */ - enum type_e type; - - /* Printable name for the current type */ - char *name; - - int type_xml; - - int size; - int align; - int bits; - - /* Used only for arrays */ - int min; - int max; - - int context; - - /* Init value for enumerations */ - int init_value; - - int incomplete; - - /* Id of the type as defined in XML file */ - int id; - int artificial; - - char *mangled; - char *demangled; - - /* List of members in constructed types */ - char *members; - - /* The file containing the definition */ - char *file; - /* Line number of the current definition */ - int line; - - /* offset of the field in the parent type - * -1 means no parent - */ - int offset; - - struct types_s *previous; - struct types_s *next; - struct types_s *parent; - struct types_s *child; - struct types_s *file_ref; - /* Reference to the head */ - struct types_s *head; - - /* For structures or union */ - int nb_members; - struct types_s **members_child; - - /* Some procedures to display the type on terminal */ - type_hr_display_t type_hr_display; - /* Some procedures to display the type on UI */ - type_ui_display_t type_ui_display; - /* Procedure to display the type to a file */ - type_file_print_t type_file_print; - /* Dissect the type */ - type_dissect_from_buffer_t type_dissect_from_buffer; -} types_t; - -types_t *type_new(enum type_e type); - -int types_insert_tail(types_t **head, types_t *to_insert); - -void types_hr_display(types_t *head); - -#define INDENTED(fILE, x, y) \ -do { \ - int indentation = x; \ - while(indentation--) fprintf(fILE, " "); \ - y; \ -} while(0) - -#define INDENTED_STRING(sTR, x, y) \ -do { \ - int indentation = x; \ - while(indentation--) ui_set_signal_text_cb(user_data, " ", 1); \ - y; \ -} while(0) - -#endif /* TYPES_H_ */ diff --git a/common/utils/itti_analyzer/libparser/union_type.c b/common/utils/itti_analyzer/libparser/union_type.c deleted file mode 100644 index f38b7a1ccc..0000000000 --- a/common/utils/itti_analyzer/libparser/union_type.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include "rc.h" - -#include "enum_value_type.h" -#include "union_type.h" -#include "../libresolver/locate_root.h" -#include "ui_interface.h" - -/* There is only one special case of union which is associated to an index: the message id */ -int union_msg_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - uint32_t message_id; - int length = 0; - char cbuf[200]; - - DISPLAY_PARSE_INFO("union_msg", type->name, offset, parent_offset); - - CHECK_FCT(get_message_id(type->head, buffer, &message_id)); - - if (type->name) { - DISPLAY_TYPE("Uni"); - - length = sprintf(cbuf, "%s |", type->name); - DISPLAY_BRACE(length += sprintf(&cbuf[length], " {");); - length += sprintf(&cbuf[length], "\n"); - ui_set_signal_text_cb(user_data, cbuf, length); - } - - if (type->members_child[message_id] != NULL) - type->members_child[message_id]->type_dissect_from_buffer( - type->members_child[message_id], ui_set_signal_text_cb, user_data, - buffer, offset, parent_offset, type->name == NULL ? indent : indent + DISPLAY_TAB_SIZE, TRUE); - - DISPLAY_BRACE( - if (type->name) { - DISPLAY_TYPE("Uni"); - - INDENTED_STRING(cbuf, indent, length = sprintf(cbuf, "};\n")); - ui_set_signal_text_cb(user_data, cbuf, length); - }); - - return RC_OK; -} - -int union_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line) -{ - int length = 0; - char cbuf[50 + (type->name ? strlen (type->name) : 0)]; - char *name; - int union_child = 0; - - DISPLAY_PARSE_INFO("union", type->name, offset, parent_offset); - - memset (cbuf, 0, sizeof(cbuf)); - -// CHECK_FCT(buffer_has_enouch_data(buffer, offset + parent_offset, type->size / 8)); - - if (type->name) { - name = type->name; - } - else { - name = "_anonymous_"; - } - if (new_line) { - DISPLAY_TYPE("Uni"); - } - INDENTED_STRING(cbuf, new_line ? indent : 0, length = sprintf(cbuf, "%s |", name)); - DISPLAY_BRACE(length += sprintf(&cbuf[length], " {");); - length += sprintf(&cbuf[length], "\n"); - ui_set_signal_text_cb(user_data, cbuf, length); - - if (type->name) { - if (type->parent != NULL) - { - if ((type->parent->name != NULL) && (strcmp(type->parent->name, "choice") == 0)) - { - /* ASN1 union */ - - if ((last_enum_value > 0) && (last_enum_value <= type->nb_members)) - { - union_child = last_enum_value - 1; - - g_debug("ASN1 union \"%s\' detected, use member %d", type->name, union_child); - } - } - } - } - - - /* Only dissect the first field present in unions */ - if (type->members_child[union_child] != NULL) - type->members_child[union_child]->type_dissect_from_buffer( - type->members_child[union_child], ui_set_signal_text_cb, user_data, buffer, - offset, parent_offset, indent + DISPLAY_TAB_SIZE, TRUE); - - DISPLAY_BRACE( - DISPLAY_TYPE("Uni"); - INDENTED_STRING(cbuf, indent, sprintf(cbuf, "};\n")); - - length = strlen (cbuf); - - ui_set_signal_text_cb(user_data, cbuf, length);); - - return 0; -} - -int union_type_file_print(types_t *type, int indent, FILE *file) { - int i; - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id)); - INDENTED(file, indent+4, fprintf(file, "Size .......: %d\n", type->size)); - INDENTED(file, indent+4, fprintf(file, "Align ......: %d\n", type->align)); - INDENTED(file, indent+4, fprintf(file, "Artificial .: %d\n", type->artificial)); - INDENTED(file, indent+4, fprintf(file, "File .......: %s\n", type->file)); - INDENTED(file, indent+4, fprintf(file, "Line .......: %d\n", type->line)); - INDENTED(file, indent+4, fprintf(file, "Members ....: %s\n", type->members)); - INDENTED(file, indent+4, fprintf(file, "Mangled ....: %s\n", type->mangled)); - INDENTED(file, indent+4, fprintf(file, "Demangled ..: %s\n", type->demangled)); - if (type->file_ref != NULL) - type->file_ref->type_file_print (type->file_ref, indent + 4, file); - for (i = 0; i < type->nb_members; i++) { - if (type->members_child[i] != NULL) - type->members_child[i]->type_file_print (type->members_child[i], indent + 4, file); - } - INDENTED(file, indent, fprintf(file, "\n")); - - return 0; -} - -int union_type_hr_display(types_t *type, int indent) { - int i; - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent+4, printf("Id .........: %d\n", type->id)); - INDENTED(stdout, indent+4, printf("Size .......: %d\n", type->size)); - INDENTED(stdout, indent+4, printf("Align ......: %d\n", type->align)); - INDENTED(stdout, indent+4, printf("Artificial .: %d\n", type->artificial)); - INDENTED(stdout, indent+4, printf("File .......: %s\n", type->file)); - INDENTED(stdout, indent+4, printf("Line .......: %d\n", type->line)); - INDENTED(stdout, indent+4, printf("Members ....: %s\n", type->members)); - INDENTED(stdout, indent+4, printf("Mangled ....: %s\n", type->mangled)); - INDENTED(stdout, indent+4, printf("Demangled ..: %s\n", type->demangled)); - if (type->file_ref != NULL) - type->file_ref->type_hr_display (type->file_ref, indent + 4); - for (i = 0; i < type->nb_members; i++) { - if (type->members_child[i] != NULL) - type->members_child[i]->type_hr_display (type->members_child[i], indent + 4); - } - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/common/utils/itti_analyzer/libparser/union_type.h b/common/utils/itti_analyzer/libparser/union_type.h deleted file mode 100644 index ed2dca73ba..0000000000 --- a/common/utils/itti_analyzer/libparser/union_type.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "types.h" - -#ifndef UNION_TYPE_H_ -#define UNION_TYPE_H_ - -int union_msg_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); - -int union_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); - -int union_type_file_print(types_t *type, int indent, FILE *file); - -int union_type_hr_display(types_t *type, int indent); - -#endif /* UNION_TYPE_H_ */ diff --git a/common/utils/itti_analyzer/libparser/xml_parse.c b/common/utils/itti_analyzer/libparser/xml_parse.c deleted file mode 100644 index 72447e7669..0000000000 --- a/common/utils/itti_analyzer/libparser/xml_parse.c +++ /dev/null @@ -1,904 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include - -#define G_LOG_DOMAIN ("PARSER") - -#include - -#include -#include - -#include "logs.h" -#include "types.h" -#include "xml_parse.h" -#include "union_type.h" - -#include "ui_interface.h" -#include "ui_main_screen.h" -#include "ui_notif_dlg.h" -#include "ui_filters.h" - -#include "../libresolver/locate_root.h" -#include "../libresolver/resolvers.h" - -extern int debug_parser; - -#if (ENABLE_DISPLAY_PARSE_INFO != 0) -# define INDENT_START 30 -#else -# define INDENT_START 0 -#endif - -void *xml_raw_data; -uint32_t xml_raw_data_size; - -types_t *xml_head; -types_t *root; - -static int xml_parse_doc(xmlDocPtr doc); - -static int parse_attribute_name(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "name")) == NULL) { - if (mandatory) { - g_error("cannot retrieve name attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - return -1; - } - else { - g_debug("cannot retrieve name attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - return 0; - } - } - type->name = strdup ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_id(xmlNode *node, types_t *type) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "id")) == NULL) { - g_error("cannot retrieve id attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - return -1; - } - type->id = atoi ((char *) &node_attribute->children->content[1]); - return 0; -} - -static int parse_attribute_size(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "size")) == NULL) { - if (mandatory) { - g_error("cannot retrieve size attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->size = -1; - return -1; - } - else { - g_debug("cannot retrieve size attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->size = -1; - return 0; - } - } - type->size = atoi ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_align(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "align")) == NULL) { - if (mandatory) { - g_error("cannot retrieve align attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->align = -1; - return -1; - } - else { - g_debug("cannot retrieve align attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->align = -1; - return 0; - } - } - type->align = atoi ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_line(xmlNode *node, types_t *type) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "line")) == NULL) { - type->line = -1; - return 0; - } - type->line = atoi ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_file(xmlNode *node, types_t *type) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "file")) == NULL) { - type->file = NULL; - return 0; - } - type->file = strdup ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_context(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "context")) == NULL) { - if (mandatory) { - g_error("cannot retrieve context attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->context = -1; - return -1; - } - else { - type->context = -1; - return 0; - } - } - type->context = atoi ((char *) &node_attribute->children->content[1]); - return 0; -} - -static int parse_attribute_artificial(xmlNode *node, types_t *type) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "artificial")) == NULL) { - g_debug("cannot retrieve artificial attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->artificial = -1; - return 0; - } - type->artificial = atoi ((char *) &node_attribute->children->content[1]); - return 0; -} - -static int parse_attribute_init(xmlNode *node, types_t *type) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "init")) == NULL) { - g_error("cannot retrieve init attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->init_value = -1; - return 0; - } - type->init_value = atoi ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_members(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "members")) == NULL) { - if (mandatory) { - g_error("cannot retrieve members attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->members = 0; - return -1; - } - else { - g_debug("cannot retrieve members attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->members = 0; - return 0; - } - } - type->members = strdup ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_mangled(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "mangled")) == NULL) { - if (mandatory) { - g_error("cannot retrieve mangled attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->mangled = 0; - return -1; - } - else { - g_debug("cannot retrieve mangled attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->mangled = 0; - return 0; - } - } - type->mangled = strdup ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_demangled(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "mangled")) == NULL) { - if (mandatory) { - g_error("cannot retrieve demangled attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->demangled = 0; - return -1; - } - else { - g_debug("cannot retrieve demangled attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->demangled = 0; - return 0; - } - } - type->demangled = strdup ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_offset(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "offset")) == NULL) { - if (mandatory) { - g_error("cannot retrieve offset attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->offset = -1; - return -1; - } - else { - g_debug("cannot retrieve offset attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->offset = -1; - return 0; - } - } - type->offset = atoi ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_bits(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "bits")) == NULL) { - if (mandatory) { - g_error("cannot retrieve bits attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->bits = -1; - return -1; - } - else { - g_debug("cannot retrieve bits attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->bits = -1; - return 0; - } - } - type->bits = atoi ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_type(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "type")) == NULL) { - if (mandatory) { - g_error("cannot retrieve type attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->type_xml = 0; - return -1; - } - else { - g_debug("cannot retrieve type attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->type_xml = 0; - return 0; - } - } - type->type_xml = atoi ((char *) &node_attribute->children->content[1]); - return 0; -} - -static int parse_attribute_min(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "min")) == NULL) { - if (mandatory) { - g_error("cannot retrieve min attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->min = 0; - return -1; - } - else { - g_debug("cannot retrieve min attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->min = 0; - return 0; - } - } - type->min = atoi ((char *) node_attribute->children->content); - return 0; -} - -static int parse_attribute_max(xmlNode *node, types_t *type, int mandatory) { - xmlAttrPtr node_attribute; - if ((node_attribute = xmlHasProp (node, (xmlChar *) "max")) == NULL) { - if (mandatory) { - g_error("cannot retrieve max attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->max = 0; - return -1; - } - else { - g_debug("cannot retrieve max attribute in node %s, %s:%ld", - (char *)node->name, node->doc->URL, XML_GET_LINE(node)); - type->max = 0; - return 0; - } - } - type->max = atoi ((char *) &node_attribute->children->content[1]); - return 0; -} - -static int parse_enum_values(xmlNode *node, types_t *parent) { - types_t *new; - - if (node == NULL || parent == NULL) - return -1; - - new = type_new (TYPE_ENUMERATION_VALUE); - - CHECK_FCT(parse_attribute_name(node, new, 1)); - CHECK_FCT(parse_attribute_init(node, new)); - - CHECK_FCT(types_insert_tail(&parent->child, new)); - - return 0; -} - -static int parse_enumeration(xmlNode *node, types_t **head) { - types_t *new; - xmlNode *enum_value_node; - - if (node == NULL) - return -1; - - new = type_new (TYPE_ENUMERATION); - - CHECK_FCT(parse_attribute_name(node, new, 1)); - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_size(node, new, 1)); - CHECK_FCT(parse_attribute_align(node, new, 1)); - CHECK_FCT(parse_attribute_context(node, new, 0)); - CHECK_FCT(parse_attribute_line(node, new)); - CHECK_FCT(parse_attribute_file(node, new)); - CHECK_FCT(parse_attribute_artificial(node, new)); - - CHECK_FCT(types_insert_tail(head, new)); - - /* Parse enum values */ - for (enum_value_node = node->children; enum_value_node; enum_value_node = enum_value_node->next) { - if (strcmp ((char *) enum_value_node->name, "EnumValue") == 0) - CHECK_FCT(parse_enum_values(enum_value_node, new)); - } - - return 0; -} - -static int parse_union(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_UNION); - - CHECK_FCT(parse_attribute_name(node, new, 0)); - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_size(node, new, 1)); - CHECK_FCT(parse_attribute_align(node, new, 1)); - CHECK_FCT(parse_attribute_context(node, new, 0)); - CHECK_FCT(parse_attribute_members(node, new, 0)); - CHECK_FCT(parse_attribute_line(node, new)); - CHECK_FCT(parse_attribute_file(node, new)); - CHECK_FCT(parse_attribute_artificial(node, new)); - CHECK_FCT(parse_attribute_mangled(node, new, 0)); - CHECK_FCT(parse_attribute_demangled(node, new, 0)); - - if (new->name) - if (strcmp (new->name, "msg_s") == 0) - new->type_dissect_from_buffer = union_msg_dissect_from_buffer; - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_fundamental(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_FUNDAMENTAL); - - CHECK_FCT(parse_attribute_name(node, new, 1)); - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_size(node, new, 0)); - CHECK_FCT(parse_attribute_align(node, new, 0)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_struct(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_STRUCT); - - CHECK_FCT(parse_attribute_name(node, new, 0)); - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_size(node, new, 0)); - CHECK_FCT(parse_attribute_align(node, new, 0)); - CHECK_FCT(parse_attribute_file(node, new)); - CHECK_FCT(parse_attribute_line(node, new)); - CHECK_FCT(parse_attribute_context(node, new, 0)); - CHECK_FCT(parse_attribute_artificial(node, new)); - CHECK_FCT(parse_attribute_members(node, new, 0)); - CHECK_FCT(parse_attribute_mangled(node, new, 0)); - CHECK_FCT(parse_attribute_demangled(node, new, 0)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_typedef(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_TYPEDEF); - - CHECK_FCT(parse_attribute_name(node, new, 1)); - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_file(node, new)); - CHECK_FCT(parse_attribute_line(node, new)); - CHECK_FCT(parse_attribute_type(node, new, 1)); - CHECK_FCT(parse_attribute_size(node, new, 0)); - CHECK_FCT(parse_attribute_align(node, new, 0)); - CHECK_FCT(parse_attribute_context(node, new, 0)); - CHECK_FCT(parse_attribute_artificial(node, new)); - CHECK_FCT(parse_attribute_members(node, new, 0)); - CHECK_FCT(parse_attribute_mangled(node, new, 0)); - CHECK_FCT(parse_attribute_demangled(node, new, 0)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_field(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_FIELD); - - CHECK_FCT(parse_attribute_name(node, new, 1)); - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_type(node, new, 1)); - CHECK_FCT(parse_attribute_size(node, new, 0)); - CHECK_FCT(parse_attribute_bits(node, new, 0)); - CHECK_FCT(parse_attribute_offset(node, new, 0)); - CHECK_FCT(parse_attribute_align(node, new, 0)); - CHECK_FCT(parse_attribute_context(node, new, 0)); - CHECK_FCT(parse_attribute_artificial(node, new)); - CHECK_FCT(parse_attribute_members(node, new, 0)); - CHECK_FCT(parse_attribute_mangled(node, new, 0)); - CHECK_FCT(parse_attribute_demangled(node, new, 0)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_file(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_FILE); - - CHECK_FCT(parse_attribute_name(node, new, 1)); - CHECK_FCT(parse_attribute_id(node, new)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_reference_type(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_REFERENCE); - - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_type(node, new, 1)); - CHECK_FCT(parse_attribute_size(node, new, 1)); - CHECK_FCT(parse_attribute_align(node, new, 1)); - CHECK_FCT(parse_attribute_context(node, new, 0)); - CHECK_FCT(parse_attribute_offset(node, new, 0)); - CHECK_FCT(parse_attribute_file(node, new)); - CHECK_FCT(parse_attribute_line(node, new)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_array_type(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_ARRAY); - - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_type(node, new, 1)); - CHECK_FCT(parse_attribute_size(node, new, 0)); - CHECK_FCT(parse_attribute_align(node, new, 1)); - CHECK_FCT(parse_attribute_min(node, new, 1)); - CHECK_FCT(parse_attribute_max(node, new, 1)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_pointer_type(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_POINTER); - - CHECK_FCT(parse_attribute_id(node, new)); - CHECK_FCT(parse_attribute_type(node, new, 1)); - CHECK_FCT(parse_attribute_size(node, new, 1)); - CHECK_FCT(parse_attribute_align(node, new, 1)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -static int parse_function_type(xmlNode *node, types_t **head) { - types_t *new; - - if (node == NULL) - return -1; - - new = type_new (TYPE_FUNCTION); - - CHECK_FCT(parse_attribute_id(node, new)); - - CHECK_FCT(types_insert_tail(head, new)); - - return 0; -} - -/** - * print_element_names: - * @a_node: the initial xml node to consider. - * - * Prints the names of the all the xml elements - * that are siblings or children of a given xml node. - */ -static int parse_elements(xmlNode * a_node, types_t **head) { - xmlNode *cur_node = NULL; - xmlNode *child_node = NULL; - - for (cur_node = a_node; cur_node; cur_node = cur_node->next) { - for (child_node = cur_node->children; child_node; child_node = child_node->next) { - if (child_node->type == XML_ELEMENT_NODE) { - if (strcmp ((char *) child_node->name, "Enumeration") == 0) { - CHECK_FCT_DO(parse_enumeration(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "FundamentalType") == 0) { - CHECK_FCT_DO(parse_fundamental(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "Struct") == 0) { - CHECK_FCT_DO(parse_struct(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "Union") == 0) { - CHECK_FCT_DO(parse_union(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "Typedef") == 0) { - CHECK_FCT_DO(parse_typedef(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "File") == 0) { - CHECK_FCT_DO(parse_file(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "Field") == 0) { - CHECK_FCT_DO(parse_field(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "ReferenceType") == 0) { - CHECK_FCT_DO(parse_reference_type(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "ArrayType") == 0) { - CHECK_FCT_DO(parse_array_type(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "PointerType") == 0) { - CHECK_FCT_DO(parse_pointer_type(child_node, head), return RC_FAIL); - } - else - if (strcmp ((char *) child_node->name, "FunctionType") == 0) { - CHECK_FCT_DO(parse_function_type(child_node, head), return RC_FAIL); - } - } - } - } - - return RC_OK; -} - -static int free_elements(types_t *parent, int indent) { - types_t *cur_node = parent; - types_t *child_node; - - g_debug("%*s%p %s", indent, "", cur_node, cur_node->name != NULL ? cur_node->name : ""); - - for (; cur_node != NULL; cur_node = cur_node->next) { - if (cur_node->child != NULL) { - child_node = cur_node->child; - cur_node->child = NULL; /* Clear the child pointer to avoid re-processing it, we are handling a graph with loops */ - CHECK_FCT_DO(free_elements((child_node), indent + 2), return RC_FAIL); - } - } - free (cur_node); - - return RC_OK; -} - -int xml_parse_buffer(char *xml_buffer, const int size) { - xmlDocPtr doc; /* the resulting document tree */ - - if (xml_buffer == NULL) { - return RC_NULL_POINTER; - } - - if (xml_raw_data != NULL) - { - /* Free previous raw data */ - free (xml_raw_data); - } - xml_raw_data = xml_buffer; - xml_raw_data_size = size; - - if (xml_head != NULL) - { - /* Free previous definitions */ - free_elements(xml_head, 0); - - g_info("xml_parse_buffer freed previous definitions"); - } - - xml_head = NULL; - root = NULL; - messages_id_enum = NULL; - lte_time_type = NULL; - lte_time_frame_type = NULL; - lte_time_slot_type = NULL; - origin_task_id_type = NULL; - destination_task_id_type = NULL; - instance_type = NULL; - message_header_type = NULL; - message_type = NULL; - message_size_type = NULL; - - g_info("Parsing XML definition from buffer ..."); - - doc = xmlReadMemory(xml_buffer, size, NULL, NULL, 0); - - if (doc == NULL) { - g_warning("Failed to parse XML buffer: %s", xml_buffer); - ui_notification_dialog(GTK_MESSAGE_ERROR, FALSE, "parse messages format definition", "Fail to parse XML buffer"); - return RC_FAIL; - } - - return xml_parse_doc(doc); -} - -static int update_filters() { - types_t *types; - - ui_init_filters(FALSE, TRUE); - - types = messages_id_enum; - if (types != NULL) - { - types = types->child; - - while (types != NULL) - { - if (strcmp (types->name, "MESSAGES_ID_MAX") != 0) - { - ui_filters_add (FILTER_MESSAGES, types->init_value, types->name, ENTRY_ENABLED_UNDEFINED, NULL, NULL); - } - types = types->next; - } - } - - types = origin_task_id_type; - if (types != NULL) - { - types = types->child->child; - - while (types != NULL) { - if ((strcmp (types->name, "TASK_FIRST") != 0) && (strcmp (types->name, "TASK_MAX") != 0)) - { - ui_filters_add(FILTER_ORIGIN_TASKS, types->init_value, types->name, ENTRY_ENABLED_UNDEFINED, NULL, NULL); - } - types = types->next; - } - } - - types = destination_task_id_type; - if (types != NULL) - { - types = types->child->child; - - while (types != NULL) { - if ((strcmp (types->name, "TASK_FIRST") != 0) && (strcmp (types->name, "TASK_MAX") != 0)) - { - ui_filters_add(FILTER_DESTINATION_TASKS, types->init_value, types->name, ENTRY_ENABLED_UNDEFINED, NULL, NULL); - } - types = types->next; - } - } - - return RC_OK; -} - -static int xml_parse_doc(xmlDocPtr doc) { - xmlNode *root_element = NULL; - int ret = 0; - FILE *dissect_file = NULL; - - if (ui_main_data.dissect_file_name != NULL) { - dissect_file = fopen (ui_main_data.dissect_file_name, "w"); - } - - /* Get the root element node */ - root_element = xmlDocGetRootElement(doc); - - ret = parse_elements(root_element, &xml_head); - - /* Free the document */ - xmlFreeDoc(doc); - - if (ret == RC_OK) { - resolve_typedefs (&xml_head); - resolve_pointer_type (&xml_head); - resolve_field (&xml_head); - resolve_array (&xml_head); - resolve_reference (&xml_head); - resolve_struct (&xml_head); - resolve_file (&xml_head); - resolve_union (&xml_head); - resolve_function (&xml_head); - - /* Locate the root element which corresponds to the MessageDef struct */ - CHECK_FCT(locate_root("MessageDef", xml_head, &root)); - - /* Locate the LTE time fields */ - if (locate_type("lte_time", xml_head, <e_time_type) == RC_OK) - { - CHECK_FCT(locate_type("frame", lte_time_type->child->child, <e_time_frame_type)); - CHECK_FCT(locate_type("slot", lte_time_type->child->child, <e_time_slot_type)); - } - - /* Locate the message id field */ - CHECK_FCT(locate_type("MessagesIds", xml_head, &messages_id_enum)); - - /* Locate the header part of a message */ - CHECK_FCT(locate_type("ittiMsgHeader", xml_head, &message_header_type)); - /* Locate the main message part */ - CHECK_FCT(locate_type("ittiMsg", xml_head, &message_type)); - - /* Locate the origin task id field */ - CHECK_FCT(locate_type_children("originTaskId", message_header_type->child->child, &origin_task_id_type)); - /* Locate the destination task id field */ - CHECK_FCT(locate_type_children("destinationTaskId", message_header_type->child->child, &destination_task_id_type)); - /* Locate the instance field */ - CHECK_FCT(locate_type_children("instance", message_header_type->child->child, &instance_type)); - /* Locate the message size field */ - CHECK_FCT(locate_type_children("ittiMsgSize", message_header_type->child->child, &message_size_type)); - - // root->type_hr_display(root, 0); - - update_filters(); - if (dissect_file != NULL) { - g_debug("generating dissected types file \"%s\" ...", ui_main_data.dissect_file_name); - root->type_file_print (root, 0, dissect_file); - } - } - - if (dissect_file != NULL) { - fclose (dissect_file); - } - - g_message("Parsed XML definition"); - - return ret; -} - -int dissect_signal_header(buffer_t *buffer, ui_set_signal_text_cb_t ui_set_signal_text_cb, - gpointer cb_user_data) -{ - if (message_header_type == NULL) { - g_error("No messages format definition provided"); - return RC_FAIL; - } - - if (buffer == NULL) { - g_error("Failed buffer is NULL"); - return RC_FAIL; - } - - message_header_type->type_dissect_from_buffer( - message_header_type, ui_set_signal_text_cb, cb_user_data, - buffer, 0, 0, INDENT_START, TRUE); - - return RC_OK; -} - -int dissect_signal(buffer_t *buffer, ui_set_signal_text_cb_t ui_set_signal_text_cb, - gpointer cb_user_data) -{ - if (message_type == NULL) { - g_error("No messages format definition provided"); - return RC_FAIL; - } - - if (buffer == NULL) { - g_error("Failed buffer is NULL"); - return RC_FAIL; - } - - message_type->type_dissect_from_buffer(message_type, ui_set_signal_text_cb, cb_user_data, - buffer, 0, 0, INDENT_START, TRUE); - - return RC_OK; -} diff --git a/common/utils/itti_analyzer/libresolver/Makefile.am b/common/utils/itti_analyzer/libresolver/Makefile.am deleted file mode 100644 index 875fc81916..0000000000 --- a/common/utils/itti_analyzer/libresolver/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -AM_CFLAGS = \ - @ADD_CFLAGS@ \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/libparser \ - -I$(top_srcdir)/libui \ - -I$(top_srcdir)/libbuffers - -noinst_LTLIBRARIES = libresolver.la - -libresolver_la_LDFLAGS = -all-static -libresolver_la_SOURCES = \ - locate_root.c locate_root.h \ - resolvers.c resolvers.h diff --git a/common/utils/itti_analyzer/libresolver/locate_root.c b/common/utils/itti_analyzer/libresolver/locate_root.c deleted file mode 100644 index dffd489944..0000000000 --- a/common/utils/itti_analyzer/libresolver/locate_root.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include - -#define G_LOG_DOMAIN ("RESOLVER") - -#include - -#include "logs.h" -#include "rc.h" - -#include "types.h" -#include "enum_type.h" -#include "locate_root.h" -#include "xml_parse.h" - -types_t *messages_id_enum; -types_t *lte_time_type; -types_t *lte_time_frame_type; -types_t *lte_time_slot_type; -types_t *origin_task_id_type; -types_t *destination_task_id_type; -types_t *instance_type; -types_t *message_header_type; -types_t *message_type; -types_t *message_size_type; - -int locate_root(const char *root_name, types_t *head, types_t **root_elm) { - types_t *next_type; - int next_counter = 0; - - /* The root element is for example : MessageDef. - * This element is the entry for other sub-types. - */ - if (!root_name || (strlen (root_name) == 0)) { - g_warning("FATAL: no root element name provided"); - return -1; - } - if (!head) { - g_warning("Empty list detected"); - return -1; - } - if (!root_elm) { - g_warning("NULL root reference"); - return -1; - } - - for (next_type = head; next_type; next_type = next_type->next) { - if (next_type->name == NULL) - continue; - if (strcmp (root_name, next_type->name) == 0) { - /* Matching reference */ - break; - } - next_counter ++; - } - g_info("locate_root: %s %d", root_name, next_counter); - - *root_elm = next_type; - return (next_type == NULL) ? -2 : 0; -} - -int locate_type(const char *type_name, types_t *head, types_t **type) { - types_t *next_type; - int next_counter = 0; - - /* The root element is for example : MessageDef. - * This element is the entry for other sub-types. - */ - if (!type_name) { - g_warning("FATAL: no element name provided"); - return RC_BAD_PARAM; - } - if (!head) { - g_warning("Empty list detected"); - return RC_BAD_PARAM; - } - - for (next_type = head; next_type; next_type = next_type->next) { - if (next_type->name == NULL) - continue; - if (strcmp (type_name, next_type->name) == 0) { - /* Matching reference */ - break; - } - next_counter ++; - } - g_info("locate_type: %s %d %p", type_name, next_counter, next_type); - - if (type) - *type = next_type; - return (next_type == NULL) ? RC_FAIL : RC_OK; -} - -int locate_type_children(const char *type_name, types_t *head, types_t **type) { - types_t *found_type = NULL; - int i; - - /* The root element is for example : MessageDef. - * This element is the entry for other sub-types. - */ - if (!type_name) { - g_warning("FATAL: no element name provided"); - return RC_BAD_PARAM; - } - if (!head) { - g_warning("Empty list detected"); - return RC_BAD_PARAM; - } - - for (i = 0; i < head->nb_members; i++) { - if (head->members_child[i]->name == NULL) - continue; - if (strcmp (type_name, head->members_child[i]->name) == 0) { - /* Matching reference */ - found_type = head->members_child[i]; - break; - } - } - g_info("locate_type: %s %d %p", type_name, i, found_type); - - if (type) - *type = found_type; - return (found_type == NULL) ? RC_FAIL : RC_OK; -} - -uint32_t get_message_header_type_size(void) -{ - /* Typedef */ - if (message_header_type->child != NULL) { - /* Struct */ - if (message_header_type->child->child != NULL) { - return message_header_type->child->child->size; - } - } - return 0; -} - -uint32_t get_message_size(buffer_t *buffer) -{ - uint32_t value = 0; - - if (message_size_type != NULL) - { - types_t *temp = message_size_type; - - while (temp->size == -1) { - temp = temp->child; - } - - /* Fetch instance value */ - buffer_fetch_bits (buffer, message_size_type->offset, temp->size, &value); - } - - return value; -} - -uint32_t get_lte_frame(buffer_t *buffer) { - uint32_t value = 0; - - if (lte_time_type !=NULL) - { - /* Fetch instance value */ - buffer_fetch_bits (buffer, lte_time_type->offset + lte_time_frame_type->offset, lte_time_frame_type->child->child->size, &value); - } - - return value; -} - -uint32_t get_lte_slot(buffer_t *buffer) { - uint32_t value = 0; - - if (lte_time_type !=NULL) - { - /* Fetch instance value */ - buffer_fetch_bits (buffer, lte_time_type->offset + lte_time_slot_type->offset, lte_time_slot_type->child->child->size, &value); - } - - return value; -} - -uint32_t get_message_id(types_t *head, buffer_t *buffer, uint32_t *message_id) { - uint32_t value; - - g_assert(message_id != NULL); - g_assert(buffer != NULL); - - /* MessageId is an offset from start of buffer */ - value = buffer_get_uint32_t(buffer, messages_id_enum->offset); - - *message_id = value; - return RC_OK; -} - -uint32_t get_task_id(buffer_t *buffer, types_t *task_id_type) { - uint32_t task_id_value; - - /* Fetch task id value */ - if (buffer_fetch_bits (buffer, task_id_type->offset, task_id_type->child->size, &task_id_value) != RC_OK) - { - return ~0; - } - - return task_id_value; -} - -char *task_id_to_string(uint32_t task_id_value, types_t *task_id_type) { - char *task_id = "UNKNOWN"; - - if (task_id_value < ((uint32_t) ~0)) - { - /* Search task id name */ - task_id = enum_type_get_name_from_value (task_id_type->child, task_id_value); - } - - return task_id; -} - -uint32_t get_instance(buffer_t *buffer) { - uint32_t instance_value; - - /* Fetch instance value */ - buffer_fetch_bits (buffer, instance_type->offset, instance_type->child->child->child->size, &instance_value); - - return instance_value; -} - -char *message_id_to_string(uint32_t message_id) -{ - return enum_type_get_name_from_value(messages_id_enum, message_id); -} diff --git a/common/utils/itti_analyzer/libresolver/locate_root.h b/common/utils/itti_analyzer/libresolver/locate_root.h deleted file mode 100644 index 5cb2eb2588..0000000000 --- a/common/utils/itti_analyzer/libresolver/locate_root.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#ifndef LOCATE_ROOT_H_ -#define LOCATE_ROOT_H_ - -#include "types.h" - -extern types_t *messages_id_enum; -extern types_t *lte_time_type; -extern types_t *lte_time_frame_type; -extern types_t *lte_time_slot_type; -extern types_t *origin_task_id_type; -extern types_t *destination_task_id_type; -extern types_t *instance_type; -extern types_t *message_header_type; -extern types_t *message_type; -extern types_t *message_size_type; - -int locate_root(const char *root_name, types_t *head, types_t **root); - -int locate_type(const char *type_name, types_t *head, types_t **type); - -int locate_type_children(const char *type_name, types_t *head, types_t **type); - -uint32_t get_message_header_type_size(void); - -uint32_t get_message_size(buffer_t *buffer); - -uint32_t get_lte_frame(buffer_t *buffer); - -uint32_t get_lte_slot(buffer_t *buffer); - -uint32_t get_message_id(types_t *head, buffer_t *buffer, uint32_t *message_id); - -char *message_id_to_string(uint32_t message_id); - -uint32_t get_task_id(buffer_t *buffer, types_t *task_id_type); - -char *task_id_to_string(uint32_t task_id_value, types_t *task_id_type); - -uint32_t get_instance(buffer_t *buffer); - -#endif /* LOCATE_ROOT_H_ */ diff --git a/common/utils/itti_analyzer/libresolver/resolvers.c b/common/utils/itti_analyzer/libresolver/resolvers.c deleted file mode 100644 index 8702c08942..0000000000 --- a/common/utils/itti_analyzer/libresolver/resolvers.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include - -#define G_LOG_DOMAIN ("RESOLVER") - -#include - -#include "types.h" -#include "resolvers.h" - -typedef enum { - RESOLV_OK = 0, - RESOLV_ERROR = -1, - RESOLV_LIST_EMPTY = -2, - RESOLV_NOT_FOUND = -3, -} resolv_rc_e; - -static int search_id(types_t *head, types_t **found, int id) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = head; next_type; next_type = next_type->next) - { - if (next_type->id == id && next_type->type != TYPE_FILE) - break; - } - if (found) - *found = next_type; - - return next_type == NULL ? RESOLV_NOT_FOUND : RESOLV_OK; -} - -int search_file(types_t *head, types_t **found, int file_id) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = head; next_type; next_type = next_type->next) - { - if (next_type->type != TYPE_FILE) - continue; - if (file_id == next_type->id) - break; - } - if (found) - *found = next_type; - - return next_type == NULL ? RESOLV_NOT_FOUND : RESOLV_OK; -} - -int resolve_typedefs(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - /* Only resolve typedef */ - if (next_type->type != TYPE_TYPEDEF) - continue; - -// printf("Trying to resolve typedef %s with type %d\n", next_type->name, next_type->id); - - if (search_id(*head, &next_type->child, next_type->type_xml) != RESOLV_OK) { - /* We have to remove this reference */ - }/* else { - next_type->type_hr_display(next_type, 0); - }*/ - } - - return 0; -} - -int resolve_struct(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - char *member; - char *members; - - /* Only resolve typedef */ - if (next_type->type != TYPE_STRUCT) - continue; - - g_debug("Trying to resolve struct members %s with type %d", next_type->name, next_type->id); - - /* Struct may have no member */ - if (next_type->members == NULL) - continue; - - /* We have to copy the string as strtok will split the string in argument */ - members = strdup(next_type->members); - - /* Split the string on spaces and _ */ - member = strtok(members, " _"); - while(member != NULL) - { - if (next_type->nb_members == 0) { - next_type->members_child = malloc(sizeof(types_t *)); - } else { - next_type->members_child = realloc(next_type->members_child, - (next_type->nb_members + 1) * sizeof(types_t *)); - } - if (search_id(*head, &next_type->members_child[next_type->nb_members], atoi(member)) != RESOLV_OK) { - /* We have to remove this reference */ - } - if ((next_type->members_child[next_type->nb_members] != NULL) - && (next_type->members_child[next_type->nb_members]->type != TYPE_FIELD)) - { - /* Only keep field child for structure, other member can be present - * for defining types (union or struct) used by fields but should not be considered. */ - next_type->members_child[next_type->nb_members] = NULL; - /* We have to remove this reference */ - } - next_type->nb_members++; - /* Pick up the next string available */ - member = strtok(NULL, " _"); - } - - free(members); - } - - return 0; -} - -int resolve_union(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - char *member; - char *members; - - /* Only resolve typedef */ - if (next_type->type != TYPE_UNION) - continue; - - g_debug("Trying to resolve union members %s with type %d\n", next_type->name, next_type->id); - - /* Struct may have no member */ - if (next_type->members == NULL) - continue; - - /* We have to copy the string as strtok will modify the string in argument */ - members = strdup(next_type->members); - - /* Split the string on spaces and _ */ - member = strtok(members, " _"); - while(member != NULL) - { - if (next_type->nb_members == 0) { - next_type->members_child = malloc(sizeof(types_t *)); - } else { - next_type->members_child = realloc(next_type->members_child, - (next_type->nb_members + 1) * sizeof(types_t *)); - } - if (search_id(*head, &next_type->members_child[next_type->nb_members], atoi(member)) != RESOLV_OK) { - /* We have to remove this reference */ - } - next_type->nb_members++; - /* Pick up the next string available */ - member = strtok(NULL, " _"); - } - - free(members); - } - - return 0; -} - -int resolve_pointer_type(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - /* Only resolve typedef */ - if (next_type->type != TYPE_POINTER) - continue; - - g_debug("Trying to resolve pointer id %d with type %d", - next_type->id, next_type->type_xml); - - if (search_id(*head, &next_type->child, next_type->type_xml) != RESOLV_OK) { - /* We have to remove this reference */ - } -// next_type->type_hr_display(next_type, 0); - } - - return 0; -} - -int resolve_reference(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - /* Only resolve typedef */ - if (next_type->type != TYPE_REFERENCE) - continue; - - g_debug("Trying to resolve reference id %d with type %d\n", - next_type->id, next_type->type_xml); - - if (search_id(*head, &next_type->child, next_type->type_xml) != RESOLV_OK) { - /* We have to remove this reference */ - } -// next_type->type_hr_display(next_type, 0); - } - - return 0; -} - -int resolve_field(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - /* Only resolve typedef */ - if (next_type->type != TYPE_FIELD) - continue; - - g_debug("Trying to resolve pointer id %d with type %d\n", - next_type->id, next_type->type_xml); - - if (search_id(*head, &next_type->child, next_type->type_xml) != RESOLV_OK) { - /* We have to remove this reference */ - } -// next_type->type_hr_display(next_type, 0); - } - - return 0; -} - -int resolve_array(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - /* Only resolve typedef */ - if (next_type->type != TYPE_ARRAY) - continue; - - g_debug("Trying to resolve array id %d with type %d\n", - next_type->id, next_type->type_xml); - - if (search_id(*head, &next_type->child, next_type->type_xml) != RESOLV_OK) { - /* We have to remove this reference */ - } -// next_type->type_hr_display(next_type, 0); - } - - return 0; -} - -int resolve_function(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - /* Only resolve typedef */ - if (next_type->type != TYPE_FUNCTION) - continue; - - g_debug("Trying to resolve function id %d with type %d", - next_type->id, next_type->type_xml); - - if (search_id(*head, &next_type->child, next_type->type_xml) != RESOLV_OK) { - /* We have to remove this reference */ - } -// next_type->type_hr_display(next_type, 0); - } - - return 0; -} - -int resolve_file(types_t **head) -{ - types_t *next_type; - - if (!head) { - g_warning("Empty list detected"); - return RESOLV_LIST_EMPTY; - } - - for (next_type = *head; next_type; next_type = next_type->next) - { - /* Only resolve typedef */ - if (next_type->type == TYPE_FILE) - continue; - - /* No reference to a file */ - if (next_type->file == NULL) { - continue; - } - - g_debug("Trying to resolve file %s\n", next_type->file); - - if (search_file(*head, &next_type->file_ref, atoi(&next_type->file[1])) != RESOLV_OK) { - /* We have to remove this reference */ - } -// next_type->type_hr_display(next_type, 0); - } - - return 0; -} - diff --git a/common/utils/itti_analyzer/libui/Makefile.am b/common/utils/itti_analyzer/libui/Makefile.am deleted file mode 100644 index 4a0d88cb95..0000000000 --- a/common/utils/itti_analyzer/libui/Makefile.am +++ /dev/null @@ -1,21 +0,0 @@ -AM_CFLAGS = \ - @ADD_CFLAGS@ \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/libbuffers \ - -I$(top_srcdir)/libparser \ - -I$(top_srcdir)/libresolver - -noinst_LTLIBRARIES = libui.la - -libui_la_LDFLAGS = -all-static -libui_la_SOURCES = \ - ui_main_screen.c ui_main_screen.h \ - ui_menu_bar.c ui_menu_bar.h \ - ui_callbacks.c ui_callbacks.h \ - ui_tree_view.c ui_tree_view.h \ - ui_signal_dissect_view.c ui_signal_dissect_view.h \ - ui_notifications.c ui_notifications.h \ - ui_notif_dlg.c ui_notif_dlg.h \ - ui_interface.c ui_interface.h \ - ui_notebook.c ui_notebook.h \ - ui_filters.c ui_filters.h \ No newline at end of file diff --git a/common/utils/itti_analyzer/libui/ui_callbacks.c b/common/utils/itti_analyzer/libui/ui_callbacks.c deleted file mode 100644 index 6fc480e333..0000000000 --- a/common/utils/itti_analyzer/libui/ui_callbacks.c +++ /dev/null @@ -1,983 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include - -#define G_LOG_DOMAIN ("UI_CB") - -#include - -#include "logs.h" -#include "rc.h" - -#include "socket.h" - -#include "ui_notif_dlg.h" -#include "ui_main_screen.h" -#include "ui_menu_bar.h" -#include "ui_callbacks.h" -#include "ui_interface.h" -#include "ui_notifications.h" -#include "ui_tree_view.h" -#include "ui_signal_dissect_view.h" -#include "ui_filters.h" -#include "ui_notebook.h" - -#include "types.h" -#include "locate_root.h" -#include "xml_parse.h" - -static gboolean refresh_message_list = TRUE; -static gboolean filters_changed = FALSE; -static gboolean operation_running = FALSE; - -static const char *ui_ip; -static uint16_t ui_port; -static GtkWidget *dialogbox_connect; -static gboolean ui_auto_reconnect; - -gboolean ui_callback_on_open_messages(GtkWidget *widget, gpointer data) -{ - gboolean refresh = (data != NULL) ? TRUE : FALSE; - - g_message("Open messages event occurred %d", refresh); - - if (operation_running == FALSE) - { - operation_running = TRUE; - if (refresh && (ui_main_data.messages_file_name != NULL)) - { - ui_messages_read (ui_main_data.messages_file_name); - } - else - { - ui_messages_open_file_chooser (); - } - operation_running = FALSE; - } - - return TRUE; -} - -gboolean ui_callback_on_save_messages(GtkWidget *widget, gpointer data) -{ - gboolean filtered = (data != NULL) ? TRUE : FALSE; - - g_message("Save messages event occurred %d", filtered); - - if (operation_running == FALSE) - { - operation_running = TRUE; - ui_messages_save_file_chooser(filtered); - operation_running = FALSE; - } - - return TRUE; -} - -gboolean ui_callback_on_filters_enabled(GtkToolButton *button, gpointer data) -{ - gboolean enabled; - gboolean changed; - - enabled = gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON(button)); - - g_info("Filters enabled event occurred %d", enabled); - - changed = ui_filters_enable (enabled); - - if (changed) - { - /* Set the tool tip text */ - if (enabled) - { - gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(button), "Disable messages filtering"); - } - else - { - gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(button), "Enable messages filtering"); - } - ui_tree_view_refilter (); - } - - return TRUE; -} - -gboolean ui_callback_on_open_filters(GtkWidget *widget, gpointer data) -{ - gboolean refresh = (data != NULL) ? TRUE : FALSE; - - g_message("Open filters event occurred"); - - if (operation_running == FALSE) - { - operation_running = TRUE; - if (refresh && (ui_main_data.filters_file_name != NULL)) - { - ui_filters_read (ui_main_data.filters_file_name); - } - else - { - ui_filters_open_file_chooser (); - } - operation_running = FALSE; - } - - return TRUE; -} - -gboolean ui_callback_on_save_filters(GtkWidget *widget, gpointer data) -{ - if (operation_running == FALSE) - { - operation_running = TRUE; - g_message("Save filters event occurred"); - ui_filters_save_file_chooser(); - operation_running = FALSE; - } - - return TRUE; -} - -gboolean ui_callback_on_enable_filters(GtkWidget *widget, gpointer data) -{ - gboolean enabled; - - enabled = gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.filters_enabled)); - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.filters_enabled), !enabled); - - return TRUE; -} - -gboolean ui_callback_on_about(GtkWidget *widget, gpointer data) -{ -#if defined(PACKAGE_STRING) - ui_notification_dialog (GTK_MESSAGE_INFO, FALSE, "about", "Eurecom %s", PACKAGE_STRING); -#else - ui_notification_dialog (GTK_MESSAGE_INFO, FALSE, "about", "Eurecom itti_analyzer"); -#endif - - return TRUE; -} - -gint ui_callback_check_string (const char *string, const gint lenght, const guint message_number) -{ - gint real_length; - - real_length = strnlen (string, lenght); - if (lenght != real_length) - { - if (message_number) - { - g_warning("Bad string format for message %u, '\\0' found before end of string (%d/%d)\n", message_number, real_length, lenght); - } - else - { - g_warning("Bad string format, '\\0' found before end of string (%d/%d)\n", real_length, lenght); - } - return (real_length); - } - else - { - return (lenght); - } -} - -gboolean ui_callback_on_select_signal(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, - gboolean path_currently_selected, gpointer user_data) -{ - static gpointer buffer_current; - ui_text_view_t *text_view; - GtkTreeIter iter; - - g_debug("Message selected %d %p %p %s", path_currently_selected, buffer_current, path, gtk_tree_path_to_string(path)); - - if (!path_currently_selected) - { - text_view = (ui_text_view_t *) user_data; - - g_assert(text_view != NULL); - - if (gtk_tree_model_get_iter (model, &iter, path)) - { - gpointer buffer; - - uint32_t message_number; - uint32_t message_id; - uint32_t origin_task_id; - uint32_t destination_task_id; - char *instance_name; - uint32_t instance; - char label[100]; - - gtk_tree_model_get (model, &iter, COL_MSG_NUM, &message_number, COL_MESSAGE_ID, &message_id, - COL_FROM_TASK_ID, &origin_task_id, COL_TO_TASK_ID, &destination_task_id, COL_INSTANCE, &instance_name, - COL_INSTANCE_ID, &instance, COL_BUFFER, &buffer, -1); - - g_debug(" Get iter %p %p", buffer_current, buffer); - - if (ui_tree_view_last_event) - { - g_debug("last_event %p %d %d", ui_tree_view_last_event, ui_tree_view_last_event->type, ui_tree_view_last_event->button); - - if (ui_tree_view_last_event->type == GDK_BUTTON_PRESS) - { - /* Callback is due to a button click */ - if (ui_tree_view_last_event->button == 1) - { - /* It was a left mouse click */ - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.signals_go_to_last_button), FALSE); - } - - if (ui_tree_view_last_event->button == 3) - { - /* It was a right mouse click */ - int item; - - /* Clear event */ - ui_tree_view_last_event = NULL; - - /* Create filter menus to refers its items in the pop-up menu */ - ui_create_filter_menus (); - - g_info("Message selected right click %d %d %d %d", message_id, origin_task_id, destination_task_id, instance); - - /* Message Id menu */ - { - /* Invalidate associated menu item to avoid issue with call back when updating the menu item check state */ - ui_tree_view_menu_enable[MENU_MESSAGE].filter_item = NULL; - item = ui_filters_search_id (&ui_filters.messages, message_id); - /* Update the menu item check state based on message ID state */ - gtk_check_menu_item_set_active ( - GTK_CHECK_MENU_ITEM(ui_tree_view_menu_enable[MENU_MESSAGE].menu_enable), - ui_filters.messages.items[item].enabled); - /* Set menu item label */ - sprintf (label, "Message: %s", message_id_to_string (message_id)); - gtk_menu_item_set_label (GTK_MENU_ITEM(ui_tree_view_menu_enable[MENU_MESSAGE].menu_enable), - label); - /* Save menu item associated to this row */ - ui_tree_view_menu_enable[MENU_MESSAGE].filter_item = &ui_filters.messages.items[item]; - } - - /* Origin task id */ - { - /* Invalidate associated menu item to avoid issue with call back when updating the menu item check state */ - ui_tree_view_menu_enable[MENU_FROM_TASK].filter_item = NULL; - item = ui_filters_search_id (&ui_filters.origin_tasks, origin_task_id); - /* Update the menu item check state based on message ID state */ - gtk_check_menu_item_set_active ( - GTK_CHECK_MENU_ITEM(ui_tree_view_menu_enable[MENU_FROM_TASK].menu_enable), - ui_filters.origin_tasks.items[item].enabled); - /* Set menu item label */ - sprintf (label, "From: %s", task_id_to_string (origin_task_id, origin_task_id_type)); - gtk_menu_item_set_label ( - GTK_MENU_ITEM(ui_tree_view_menu_enable[MENU_FROM_TASK].menu_enable), label); - /* Save menu item associated to this row */ - ui_tree_view_menu_enable[MENU_FROM_TASK].filter_item = &ui_filters.origin_tasks.items[item]; - } - - /* Destination task id */ - { - /* Invalidate associated menu item to avoid issue with call back when updating the menu item check state */ - ui_tree_view_menu_enable[MENU_TO_TASK].filter_item = NULL; - item = ui_filters_search_id (&ui_filters.destination_tasks, destination_task_id); - /* Update the menu item check state based on message ID state */ - gtk_check_menu_item_set_active ( - GTK_CHECK_MENU_ITEM(ui_tree_view_menu_enable[MENU_TO_TASK].menu_enable), - ui_filters.destination_tasks.items[item].enabled); - /* Set menu item label */ - sprintf (label, "To: %s", - task_id_to_string (destination_task_id, destination_task_id_type)); - gtk_menu_item_set_label (GTK_MENU_ITEM(ui_tree_view_menu_enable[MENU_TO_TASK].menu_enable), - label); - /* Save menu item associated to this row */ - ui_tree_view_menu_enable[MENU_TO_TASK].filter_item = - &ui_filters.destination_tasks.items[item]; - } - - /* Instance */ - { - /* Invalidate associated menu item to avoid issue with call back when updating the menu item check state */ - ui_tree_view_menu_enable[MENU_INSTANCE].filter_item = NULL; - item = ui_filters_search_id (&ui_filters.instances, instance); - /* Update the menu item check state based on message ID state */ - gtk_check_menu_item_set_active ( - GTK_CHECK_MENU_ITEM(ui_tree_view_menu_enable[MENU_INSTANCE].menu_enable), - ui_filters.instances.items[item].enabled); - /* Set menu item label */ - sprintf (label, "Instance: %s", instance_name); - gtk_menu_item_set_label (GTK_MENU_ITEM(ui_tree_view_menu_enable[MENU_INSTANCE].menu_enable), - label); - /* Save menu item associated to this row */ - ui_tree_view_menu_enable[MENU_INSTANCE].filter_item = &ui_filters.instances.items[item]; - } - - gtk_menu_popup (GTK_MENU (ui_tree_view_menu), NULL, NULL, NULL, NULL, 0, - gtk_get_current_event_time ()); - } - } - - /* Clear event */ - ui_tree_view_last_event = NULL; - } - - if (buffer_current != buffer) - { - buffer_current = buffer; - - /* Clear the view */ - CHECK_FCT_DO(ui_signal_dissect_clear_view(text_view), return FALSE); - - if (ui_main_data.display_message_header) - { - CHECK_FCT_DO(dissect_signal_header((buffer_t*)buffer, ui_signal_set_text, text_view), return FALSE); - } - - if ((strcmp (message_id_to_string (message_id), "ERROR_LOG") == 0) - || (strcmp (message_id_to_string (message_id), "WARNING_LOG") == 0) - || (strcmp (message_id_to_string (message_id), "NOTICE_LOG") == 0) - || (strcmp (message_id_to_string (message_id), "INFO_LOG") == 0) - || (strcmp (message_id_to_string (message_id), "DEBUG_LOG") == 0) - || (strcmp (message_id_to_string (message_id), "GENERIC_LOG") == 0)) - { - gchar *data; - gint data_size; - uint32_t message_header_type_size; - - if (ui_main_data.display_message_header) - { - ui_signal_set_text (text_view, "\n", 1); - } - - message_header_type_size = get_message_header_type_size (); - data = (gchar *) buffer_at_offset ((buffer_t*) buffer, message_header_type_size); - data_size = get_message_size ((buffer_t*) buffer); - data_size = ui_callback_check_string (data, data_size, message_number); - - g_info(" dump message %d: header type size: %u, data size: %u, buffer %p, follow last %d", - message_number, message_header_type_size, data_size, buffer, ui_main_data.follow_last); - - ui_signal_set_text (text_view, data, data_size); - } - else - { - g_info(" dissect message %d: id %d, buffer %p, follow last %d", message_number, message_id, buffer, ui_main_data.follow_last); - - /* Dissect the signal */ - CHECK_FCT_DO(dissect_signal((buffer_t*)buffer, ui_signal_set_text, text_view), return FALSE); - } - } - } - } - return TRUE; -} - -gboolean ui_callback_on_menu_enable(GtkWidget *widget, gpointer data) -{ - ui_tree_view_menu_enable_t *menu_enable = data; - - if (menu_enable->filter_item != NULL) - { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_enable->filter_item->menu_item), - gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(menu_enable->menu_enable))); - menu_enable->filter_item = NULL; - } - - return TRUE; -} - -gboolean ui_callback_on_menu_color(GtkWidget *widget, gpointer data) -{ - ui_tree_view_menu_color_t *menu_color = data; - - GdkRGBA color; - GtkWidget *color_chooser; - gint response; - - color_chooser = gtk_color_chooser_dialog_new ("Select message background color", GTK_WINDOW(ui_main_data.window)); - gtk_color_chooser_set_use_alpha (GTK_COLOR_CHOOSER(color_chooser), FALSE); - response = gtk_dialog_run (GTK_DIALOG (color_chooser)); - - if (response == GTK_RESPONSE_OK) - { - int red, green, blue; - char *color_string; - - color_string = - menu_color->foreground ? - menu_color->menu_enable->filter_item->foreground : - menu_color->menu_enable->filter_item->background; - - gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER(color_chooser), &color); - - red = (int) (color.red * 255); - green = (int) (color.green * 255); - blue = (int) (color.blue * 255); - - snprintf (color_string, COLOR_SIZE, "#%02x%02x%02x", red, green, blue); - ui_tree_view_refilter (); - - g_info("Selected color for %s %f->%02x %f->%02x %f->%02x %s", - menu_color->menu_enable->filter_item->name, color.red, red, color.green, green, color.blue, blue, color_string); - } - gtk_widget_destroy (color_chooser); - - return TRUE; -} - -void ui_signal_add_to_list(gpointer data, gpointer user_data) -{ - gboolean goto_last = user_data ? TRUE : FALSE; - buffer_t *signal_buffer; - GtkTreePath *path; - GtkTreeViewColumn *focus_column; - uint32_t lte_frame; - uint32_t lte_slot; - uint32_t origin_task_id; - uint32_t destination_task_id; - uint32_t instance; - char lte_time[15]; - - g_assert(data != NULL); - g_assert(origin_task_id_type != NULL); - g_assert(destination_task_id_type != NULL); - - gtk_tree_view_get_cursor (GTK_TREE_VIEW(ui_main_data.messages_list), &path, &focus_column); - - signal_buffer = (buffer_t *) data; - - lte_frame = get_lte_frame (signal_buffer); - lte_slot = get_lte_slot (signal_buffer); - sprintf (lte_time, "%d.%02d", lte_frame, lte_slot); - - get_message_id (root, signal_buffer, &signal_buffer->message_id); - origin_task_id = get_task_id (signal_buffer, origin_task_id_type); - destination_task_id = get_task_id (signal_buffer, destination_task_id_type); - instance = get_instance (signal_buffer); - - ui_tree_view_new_signal_ind (signal_buffer->message_number, lte_time, signal_buffer->message_id, - message_id_to_string (signal_buffer->message_id), origin_task_id, - task_id_to_string (origin_task_id, origin_task_id_type), destination_task_id, - task_id_to_string (destination_task_id, destination_task_id_type), instance, data); - - if ((strcmp (message_id_to_string (signal_buffer->message_id), "ERROR_LOG") == 0) - || (strcmp (message_id_to_string (signal_buffer->message_id), "WARNING_LOG") == 0) - || (strcmp (message_id_to_string (signal_buffer->message_id), "NOTICE_LOG") == 0) - || (strcmp (message_id_to_string (signal_buffer->message_id), "INFO_LOG") == 0) - || (strcmp (message_id_to_string (signal_buffer->message_id), "DEBUG_LOG") == 0) - || (strcmp (message_id_to_string (signal_buffer->message_id), "GENERIC_LOG") == 0)) - { - gchar *string_terminal; - gint string_terminal_size; - uint32_t message_header_type_size; - - message_header_type_size = get_message_header_type_size (); - string_terminal = (gchar *) buffer_at_offset ((buffer_t*) signal_buffer, message_header_type_size); - string_terminal_size = get_message_size ((buffer_t*) signal_buffer); - string_terminal_size = ui_callback_check_string (string_terminal, string_terminal_size, signal_buffer->message_number); - ui_notebook_terminal_append_data(string_terminal, string_terminal_size); - } - - /* Increment number of messages */ - ui_main_data.nb_message_received++; - - if ((ui_main_data.follow_last) && (goto_last)) - { - /* Advance to the new last signal */ - ui_tree_view_select_row (ui_tree_view_get_filtered_number () - 1); - } -} - -static gboolean ui_handle_update_signal_list(gint fd, void *data, size_t data_length) -{ - pipe_new_signals_list_message_t *signal_list_message; - - /* Enable buttons to move in the list of signals */ - ui_set_sensitive_move_buttons (TRUE); - - signal_list_message = (pipe_new_signals_list_message_t *) data; - - g_assert(signal_list_message != NULL); - g_assert(signal_list_message->signal_list != NULL); - - g_list_foreach (signal_list_message->signal_list, ui_signal_add_to_list, (gpointer) TRUE); - - /* Free the list but not user data associated with each element */ - g_list_free (signal_list_message->signal_list); - /* Free the message */ - free (signal_list_message); - - ui_gtk_flush_events (); - - return TRUE; -} - -static gboolean ui_handle_socket_connection_failed(gint fd) -{ - gtk_dialog_response(GTK_DIALOG (dialogbox_connect), GTK_RESPONSE_REJECT); - - return TRUE; -} - -static gboolean ui_handle_socket_connection_lost(gint fd) -{ - if (operation_running) - { - operation_running = FALSE; - if (ui_auto_reconnect) - { - ui_callback_on_connect (NULL, (gpointer) FALSE); - } - else - { - ui_enable_connect_button(); - ui_set_sensitive_save_message_buttons (TRUE); - } - } - - return TRUE; -} - -static gboolean ui_handle_socket_xml_definition(gint fd, void *data, size_t data_length) -{ - pipe_xml_definition_message_t *xml_definition_message; - - xml_definition_message = (pipe_xml_definition_message_t *) data; - g_assert(xml_definition_message != NULL); - g_assert(data_length == sizeof(pipe_xml_definition_message_t)); - - xml_parse_buffer (xml_definition_message->xml_definition, xml_definition_message->xml_definition_length); - - return TRUE; -} - -gboolean ui_pipe_callback(gint source, gpointer user_data) -{ - void *input_data = NULL; - size_t input_data_length = 0; - pipe_input_header_t input_header; - - /* Read the header */ - if (read (source, &input_header, sizeof(input_header)) < 0) - { - g_warning("Failed to read from pipe %d: %s", source, g_strerror(errno)); - return FALSE; - } - - input_data_length = input_header.message_size - sizeof(input_header); - - /* Checking for non-header part */ - if (input_data_length > 0) - { - input_data = malloc (input_data_length); - - if (read (source, input_data, input_data_length) < 0) - { - g_warning("Failed to read from pipe %d: %s", source, g_strerror(errno)); - return FALSE; - } - } - - switch (input_header.message_type) - { - case UI_PIPE_CONNECTION_FAILED: - return ui_handle_socket_connection_failed (source); - - case UI_PIPE_CONNECTION_LOST: - return ui_handle_socket_connection_lost (source); - - case UI_PIPE_XML_DEFINITION: - gtk_dialog_response(GTK_DIALOG (dialogbox_connect), GTK_RESPONSE_OK); - return ui_handle_socket_xml_definition (source, input_data, input_data_length); - - case UI_PIPE_UPDATE_SIGNAL_LIST: - return ui_handle_update_signal_list (source, input_data, input_data_length); - - default: - g_warning("[gui] Unhandled message type %u", input_header.message_type); - g_assert_not_reached(); - } - return FALSE; -} - -gboolean ui_callback_on_auto_reconnect(GtkWidget *widget, gpointer data) -{ - gboolean enabled; - gboolean changed = TRUE; - - gboolean toggle = (data != NULL) ? TRUE : FALSE; - - enabled = gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.auto_reconnect)); - - if (toggle) - { - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.auto_reconnect), !enabled); - return TRUE; - } - - g_info("Auto reconnect event occurred %d %d ", toggle, enabled); - - ui_auto_reconnect = enabled; - - if (changed) - { - /* Set the tool tip text */ - if (enabled) - { - gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(ui_main_data.auto_reconnect), "Disable automatic reconnection"); - } - else - { - gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(ui_main_data.auto_reconnect), "Enable automatic reconnection"); - } - } - - return TRUE; -} - -void ui_callback_dialogbox_connect_destroy(void) -{ - if (dialogbox_connect != NULL) - { - gtk_widget_destroy (dialogbox_connect); - dialogbox_connect = NULL; - g_message("Connect dialogbox destroyed"); - } -} - -gboolean ui_callback_on_connect(GtkWidget *widget, gpointer data) -{ - /* We have to retrieve the ip address and ui_port of remote host */ - gboolean start = (data != NULL) ? TRUE : FALSE; - int pipe_fd[2]; - - if (start) - { - ui_port = atoi (gtk_entry_get_text (GTK_ENTRY(ui_main_data.port_entry))); - ui_ip = gtk_entry_get_text (GTK_ENTRY(ui_main_data.ip_entry)); - } - - g_message("Connect event occurred to %s:%d %s", ui_ip, ui_port, start ? "START" : "RETRY"); - - if (start) - { - if (strlen (ui_ip) == 0) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "Connect", "Empty host ip address"); - return FALSE; - } - - if (ui_port == 0) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "Connect", "Invalid host ui_port value"); - return FALSE; - } - } - - if (operation_running == FALSE) - { - operation_running = TRUE; - - ui_pipe_new (pipe_fd, ui_pipe_callback, NULL); - - memcpy (ui_main_data.pipe_fd, pipe_fd, sizeof(int) * 2); - - /* Disable the connect button */ - ui_disable_connect_button (); - - ui_set_title ("connecting to %s:%d ...", ui_ip, ui_port); - { - const static char *message_formats[] = - { - "Connecting to %s:%d ...", - "Connection lost!\n\n" "Trying to reconnect to %s:%d ..." - }; - gint response; - gint x, y; - gint w, h; - - if (socket_connect_to_remote_host (ui_ip, ui_port, pipe_fd[1]) != 0) - { - ui_enable_connect_button (); - operation_running = FALSE; - return FALSE; - } - - /* Create dialog box for connect message: - * - non modal mode does not seems to work, don't set the parent window to allow some interactions with it! - */ - dialogbox_connect = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_OTHER, - GTK_BUTTONS_CANCEL, message_formats[start ? 0 : 1], ui_ip, ui_port); - gtk_window_set_title (GTK_WINDOW(dialogbox_connect), "Connect"); - - /* Set the window at center of main window manually as there is no parent defined */ - gtk_window_get_position (GTK_WINDOW(ui_main_data.window), &x, &y); - gtk_window_get_size (GTK_WINDOW(ui_main_data.window), &w, &h); - g_message("Main window position: %d,%d dimension: %d,%d", x, y, w, h); - x += w / 2; - y += h / 2; - g_message("Connect window position %d,%d", x, y); - gtk_window_set_gravity (GTK_WINDOW(dialogbox_connect), GDK_GRAVITY_CENTER); - gtk_window_move (GTK_WINDOW(dialogbox_connect), x, y); - - response = gtk_dialog_run (GTK_DIALOG (dialogbox_connect)); - g_message("Connect dialog response %s (%d)", gtk_get_respose_string(response), response); - - if (response == GTK_RESPONSE_NONE) - { - /* Dialogbox has been destroyed when program is exited, do nothing */ - return (TRUE); - } - if (response == GTK_RESPONSE_OK) - { - /* Connection is established */ - ui_set_sensitive_save_message_buttons (FALSE); - ui_callback_signal_clear_list (NULL, NULL); - ui_set_title ("%s:%d", ui_ip, ui_port); - } - else - { - /* Connection can not be established */ - if (response == GTK_RESPONSE_REJECT) - { - /* Connection retry time-out */ - ui_notification_dialog (GTK_MESSAGE_WARNING, FALSE, "Connect", "Failed to connect to provided host/ip address"); - } - - /* Re-enable connect button */ - ui_enable_connect_button(); - operation_running = FALSE; - } - ui_callback_dialogbox_connect_destroy (); - } - } - - return TRUE; -} - -gboolean ui_callback_on_disconnect(GtkWidget *widget, gpointer data) -{ - g_message("Disconnect event occurred"); - - ui_pipe_write_message (ui_main_data.pipe_fd[0], UI_PIPE_DISCONNECT_EVT, NULL, 0); - - if (dialogbox_connect != NULL) - { - gtk_dialog_response(GTK_DIALOG (dialogbox_connect), GTK_RESPONSE_CLOSE); - } - else - { - ui_enable_connect_button (); - operation_running = FALSE; - } - - return TRUE; -} - -gboolean ui_callback_signal_go_to_first(GtkWidget *widget, gpointer data) -{ - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.signals_go_to_last_button), FALSE); - ui_tree_view_select_row (0); - - return TRUE; -} - -gboolean ui_callback_signal_go_to(GtkWidget *widget, gpointer data) -{ - gtk_window_set_focus (GTK_WINDOW(ui_main_data.window), ui_main_data.signals_go_to_entry); - return TRUE; -} - -gboolean ui_callback_signal_go_to_entry(GtkWidget *widget, gpointer data) -{ - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.signals_go_to_last_button), FALSE); - // gtk_entry_buffer_set_text(GTK_ENTRY(ui_main_data.signals_go_to_entry), ""); - gtk_window_set_focus (GTK_WINDOW(ui_main_data.window), ui_main_data.messages_list); - return TRUE; -} - -gboolean ui_callback_signal_go_to_last(GtkWidget *widget, gpointer data) -{ - gboolean enable = (data != NULL) ? TRUE : FALSE; - gboolean enabled; - - if (enable) - { - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.signals_go_to_last_button), TRUE); - return TRUE; - } - - enabled = gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.signals_go_to_last_button)); - - g_info("Button signal go to last event occurred %d %d", enable, enabled); - - if (enabled) - { - ui_main_data.follow_last = TRUE; - ui_tree_view_select_row (ui_tree_view_get_filtered_number () - 1); - } - else - { - ui_main_data.follow_last = FALSE; - } - - return TRUE; -} - -gboolean ui_callback_display_message_header(GtkWidget *widget, gpointer data) -{ - ui_main_data.display_message_header = !ui_main_data.display_message_header; - // TODO refresh textview. - return TRUE; -} - -gboolean ui_callback_display_brace(GtkWidget *widget, gpointer data) -{ - ui_main_data.display_brace = !ui_main_data.display_brace; - // TODO refresh textview. - return TRUE; -} - -gboolean ui_callback_signal_clear_list(GtkWidget *widget, gpointer data) -{ - /* Disable buttons to move in the list of signals */ - ui_set_sensitive_move_buttons (FALSE); - ui_set_title (""); - - /* Clear list of signals */ - ui_tree_view_destroy_list (ui_main_data.messages_list); - - if (ui_main_data.text_view != NULL) - { - ui_signal_dissect_clear_view (ui_main_data.text_view); - } - - ui_notebook_terminal_clear(); - - return TRUE; -} - -static void ui_callback_on_menu_items_selected(GtkWidget *widget, gpointer data) -{ - gboolean active = data != NULL; - - if (GTK_IS_CHECK_MENU_ITEM(widget)) - { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(widget), active); - } -} - -gboolean ui_callback_on_menu_none(GtkWidget *widget, gpointer data) -{ - GtkWidget *menu = (GtkWidget *) data; - - g_info("ui_callback_on_menu_none occurred %lx %lx)", (long) widget, (long) data); - - refresh_message_list = FALSE; - gtk_container_foreach (GTK_CONTAINER(menu), ui_callback_on_menu_items_selected, (gpointer) FALSE); - refresh_message_list = TRUE; - - if (filters_changed) - { - ui_tree_view_refilter (); - filters_changed = FALSE; - } - - return TRUE; -} - -gboolean ui_callback_on_menu_all(GtkWidget *widget, gpointer data) -{ - GtkWidget *menu = (GtkWidget *) data; - - g_info("ui_callback_on_menu_all occurred %lx %lx)", (long) widget, (long) data); - - refresh_message_list = FALSE; - gtk_container_foreach (GTK_CONTAINER(menu), ui_callback_on_menu_items_selected, (gpointer) TRUE); - refresh_message_list = TRUE; - - if (filters_changed) - { - ui_tree_view_refilter (); - filters_changed = FALSE; - } - - return TRUE; -} - -gboolean ui_callback_on_menu_item_selected(GtkWidget *widget, gpointer data) -{ - ui_filter_item_t *filter_entry = data; - gboolean enabled; - - enabled = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(widget)); - if (filter_entry->enabled != enabled) - { - filter_entry->enabled = enabled; - if (refresh_message_list) - { - ui_tree_view_refilter (); - } - else - { - filters_changed = TRUE; - } - } - g_info("ui_callback_on_menu_item_selected occurred %p %p %s %d (%d messages to display)", widget, data, filter_entry->name, enabled, ui_tree_view_get_filtered_number()); - - return TRUE; -} - -gboolean ui_callback_on_tree_column_header_click(GtkWidget *widget, gpointer data) -{ - col_type_t col = (col_type_t) data; - - g_info("ui_callback_on_tree_column_header_click %d", col); - switch (col) - { - case COL_MESSAGE: - ui_show_filter_menu (&ui_main_data.menu_filter_messages, &ui_filters.messages); - break; - - case COL_FROM_TASK: - ui_show_filter_menu (&ui_main_data.menu_filter_origin_tasks, &ui_filters.origin_tasks); - break; - - case COL_TO_TASK: - ui_show_filter_menu (&ui_main_data.menu_filter_destination_tasks, &ui_filters.destination_tasks); - break; - - case COL_INSTANCE: - ui_show_filter_menu (&ui_main_data.menu_filter_instances, &ui_filters.instances); - break; - - default: - g_warning("Unknown column filter %d in call to ui_callback_on_tree_column_header_click", col); - return FALSE; - } - - return TRUE; -} diff --git a/common/utils/itti_analyzer/libui/ui_callbacks.h b/common/utils/itti_analyzer/libui/ui_callbacks.h deleted file mode 100644 index b3d4b31c60..0000000000 --- a/common/utils/itti_analyzer/libui/ui_callbacks.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#ifndef UI_CALLBACKS_H_ -#define UI_CALLBACKS_H_ - -#include - -gboolean ui_callback_on_open_messages(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_save_messages(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_filters_enabled(GtkToolButton *button, - gpointer data); - -gboolean ui_callback_on_open_filters(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_save_filters(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_enable_filters(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_about(GtkWidget *widget, - gpointer data); - -gint ui_callback_check_string (const char *string, - const gint lenght, - const guint message_number); - -gboolean ui_pipe_callback(gint source, gpointer user_data); - -gboolean ui_callback_on_auto_reconnect(GtkWidget *widget, - gpointer data); - -void ui_callback_dialogbox_connect_destroy(void); - -gboolean ui_callback_on_connect(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_disconnect(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_tree_view_select(GtkWidget *widget, - GdkEvent *event, - gpointer data); - -gboolean ui_callback_on_select_signal(GtkTreeSelection *selection, - GtkTreeModel *model, - GtkTreePath *path, - gboolean path_currently_selected, - gpointer userdata); - -void ui_signal_add_to_list(gpointer data, - gpointer user_data); - -gboolean ui_callback_on_menu_enable (GtkWidget *widget, gpointer data); - -gboolean ui_callback_on_menu_color (GtkWidget *widget, gpointer data); - -gboolean ui_callback_signal_go_to_first(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_signal_go_to(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_signal_go_to_entry(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_signal_go_to_last(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_display_message_header(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_display_brace(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_signal_clear_list(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_menu_none(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_menu_all(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_menu_item_selected(GtkWidget *widget, - gpointer data); - -gboolean ui_callback_on_tree_column_header_click(GtkWidget *widget, - gpointer data); -#endif /* UI_CALLBACKS_H_ */ diff --git a/common/utils/itti_analyzer/libui/ui_filters.c b/common/utils/itti_analyzer/libui/ui_filters.c deleted file mode 100644 index 8a6321a538..0000000000 --- a/common/utils/itti_analyzer/libui/ui_filters.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include - -#define G_LOG_DOMAIN ("UI_FILTER") - -#include - -#include -#include - -#include "ui_callbacks.h" -#include "ui_main_screen.h" -#include "ui_filters.h" -#include "ui_tree_view.h" -#include "ui_notif_dlg.h" -#include "rc.h" - -const uint32_t FILTER_ALLOC_NUMBER = 100; -const uint32_t FILTER_ID_UNDEFINED = ~0; - -const char * const COLOR_WHITE = "#ffffff"; -const char * const COLOR_DARK_GREY = "#585858"; - -#define ENABLED_NAME "enabled" -#define FOREGROUND_NAME "foreground_color" -#define BACKGROUND_NAME "background_color" - -ui_filters_t ui_filters; - -static int ui_init_filter(ui_filter_t *filter, int reset, int clear_ids, char *name) -{ - if (filter->items == NULL) - { - filter->name = name; - - /* Allocate some filter entries */ - filter->items = malloc (FILTER_ALLOC_NUMBER * sizeof(ui_filter_item_t)); - filter->allocated = FILTER_ALLOC_NUMBER; - } - if (reset) - { - /* Reset number of used filter entries */ - filter->used = 0; - } - else - { - if (clear_ids) - { - /* Clear entries IDs */ - int item; - - for (item = 0; item < filter->used; item++) - { - filter->items[item].id = FILTER_ID_UNDEFINED; - } - } - } - - return (RC_OK); -} - -int ui_init_filters(int reset, int clear_ids) -{ - ui_init_filter (&ui_filters.messages, reset, clear_ids, "messages"); - ui_init_filter (&ui_filters.origin_tasks, reset, clear_ids, "origin_tasks"); - ui_init_filter (&ui_filters.destination_tasks, reset, clear_ids, "destination_tasks"); - ui_init_filter (&ui_filters.instances, reset, clear_ids, "instances"); - - ui_destroy_filter_menus (); - - return (RC_OK); -} - -gboolean ui_filters_enable(gboolean enabled) -{ - gboolean changed = ui_filters.filters_enabled != enabled; - - if (changed) - { - ui_filters.filters_enabled = enabled; - } - - return changed; -} - -static int ui_filters_search_name(ui_filter_t *filter, const char *name) -{ - int item; - - for (item = 0; item < filter->used; item++) - { - if (strncmp (name, filter->items[item].name, SIGNAL_NAME_LENGTH) == 0) - { - return (item); - } - } - - return (item); -} - -int ui_filters_search_id(ui_filter_t *filter, uint32_t value) -{ - int item; - - for (item = 0; item < filter->used; item++) - { - if (filter->items[item].id == value) - { - return (item); - } - } - - return (-1); -} - -static void ui_filter_set_enabled(uint8_t *enabled, ui_entry_enabled_e entry_enabled, gboolean new) -{ - if (entry_enabled == ENTRY_ENABLED_UNDEFINED) - { - if (new) - { - *enabled = TRUE; - } - } - else - { - if (entry_enabled == ENTRY_ENABLED_FALSE) - { - *enabled = FALSE; - } - else - { - *enabled = TRUE; - } - } -} - -static int ui_filter_add(ui_filter_t *filter, uint32_t value, const char *name, ui_entry_enabled_e entry_enabled, - const char *foreground, const char *background) -{ - int item = ui_filters_search_name (filter, name); - - if (item >= filter->allocated) - { - /* Increase number of filter entries */ - filter->items = realloc (filter->items, (filter->allocated + FILTER_ALLOC_NUMBER) * sizeof(ui_filter_item_t)); - filter->allocated += FILTER_ALLOC_NUMBER; - } - - if (value != FILTER_ID_UNDEFINED) - { - filter->items[item].id = value; - } - if (item >= filter->used) - { - /* New entry */ - strncpy (filter->items[item].name, name, SIGNAL_NAME_LENGTH); - ui_filter_set_enabled (&filter->items[item].enabled, entry_enabled, TRUE); - strncpy (filter->items[item].foreground, foreground != NULL ? foreground : COLOR_DARK_GREY, COLOR_SIZE); - strncpy (filter->items[item].background, background != NULL ? background : COLOR_WHITE, COLOR_SIZE); - - filter->used++; - } - else - { - ui_filter_set_enabled (&filter->items[item].enabled, entry_enabled, FALSE); - if (foreground != NULL) - { - strncpy (filter->items[item].foreground, foreground, COLOR_SIZE); - } - if (background != NULL) - { - strncpy (filter->items[item].background, background, COLOR_SIZE); - } - } - - g_debug("filter \"%s\" add %d \"%s\" %d", filter->name, value, name, entry_enabled); - - return (item); -} - -void ui_filters_add(ui_filter_e filter, uint32_t value, const char *name, ui_entry_enabled_e entry_enabled, - const char *foreground, const char *background) -{ - switch (filter) - { - case FILTER_MESSAGES: - ui_filter_add (&ui_filters.messages, value, name, entry_enabled, foreground, background); - break; - - case FILTER_ORIGIN_TASKS: - ui_filter_add (&ui_filters.origin_tasks, value, name, entry_enabled, foreground, background); - break; - - case FILTER_DESTINATION_TASKS: - ui_filter_add (&ui_filters.destination_tasks, value, name, entry_enabled, foreground, background); - break; - - case FILTER_INSTANCES: - ui_filter_add (&ui_filters.instances, value, name, entry_enabled, foreground, background); - break; - - default: - g_warning("unknown filter type %d", filter); - break; - } -} - -static gboolean ui_item_enabled(ui_filter_t *filter, const uint32_t value) -{ - int item; - - if (value != (uint32_t) ~0) - { - item = ui_filters_search_id (filter, value); - - if (item >= 0) - { - return (filter->items[item].enabled ? TRUE : FALSE); - } - } - return (FALSE); -} - -gboolean ui_filters_message_enabled(const uint32_t message, const uint32_t origin_task, const uint32_t destination_task, - const uint32_t instance) -{ - gboolean result; - - result = (ui_item_enabled (&ui_filters.messages, message) && ui_item_enabled (&ui_filters.origin_tasks, origin_task) - && ui_item_enabled (&ui_filters.destination_tasks, destination_task) - && ui_item_enabled (&ui_filters.instances, instance)); - - return result; -} - -static ui_filter_e ui_filter_from_name(const char *name) -{ - if (strcmp (name, ui_filters.messages.name) == 0) - { - return FILTER_MESSAGES; - } - if (strcmp (name, ui_filters.origin_tasks.name) == 0) - { - return FILTER_ORIGIN_TASKS; - } - if (strcmp (name, ui_filters.destination_tasks.name) == 0) - { - return FILTER_DESTINATION_TASKS; - } - if (strcmp (name, ui_filters.instances.name) == 0) - { - return FILTER_INSTANCES; - } - return FILTER_UNKNOWN; -} - -static int xml_parse_filters(xmlDocPtr doc, const char *file_name) -{ - xmlNode *root_element = NULL; - xmlNode *filter_node = NULL; - xmlNode *cur_node = NULL; - ui_filter_e filter; - guint filters_entries = 0; - int ret = RC_FAIL; - - /* Get the root element node */ - root_element = xmlDocGetRootElement (doc); - - if (root_element != NULL) - { - /* Search for the start of filters definition */ - for (cur_node = root_element; (cur_node != NULL) && (strcmp ((char *) cur_node->name, "filters") != 0); - cur_node = cur_node->next) - ; - - if (cur_node != NULL) - { - /* Search for filter header */ - for (filter_node = cur_node->children; filter_node != NULL;) - { - /* Search for next element node */ - for (; (filter_node != NULL) && (filter_node->type != XML_ELEMENT_NODE); filter_node = - filter_node->next) - ; - - if (filter_node != NULL) - { - filter = ui_filter_from_name ((const char*) filter_node->name); - g_debug("Found filter %s %d", filter_node->name, filter); - - if (filter == FILTER_UNKNOWN) - { - g_warning("Unknown filter \"%s\"", filter_node->name); - } - else - { - /* Search for entries */ - for (cur_node = filter_node->children; cur_node != NULL;) - { - /* Search for next element node */ - for (; (cur_node != NULL) && (cur_node->type != XML_ELEMENT_NODE); cur_node = - cur_node->next) - ; - - if (cur_node != NULL) - { - xmlAttr *prop_node; - ui_entry_enabled_e enabled = ENTRY_ENABLED_UNDEFINED; - char *foreground = NULL; - char *background = NULL; - - for (prop_node = cur_node->properties; prop_node != NULL; prop_node = prop_node->next) - { - if (strcmp ((char *) prop_node->name, ENABLED_NAME) == 0) - { - enabled = - prop_node->children->content[0] == '0' ? - ENTRY_ENABLED_FALSE : ENTRY_ENABLED_TRUE; - } - if (strcmp ((char *) prop_node->name, FOREGROUND_NAME) == 0) - { - foreground = (char *) prop_node->children->content; - } - if (strcmp ((char *) prop_node->name, BACKGROUND_NAME) == 0) - { - background = (char *) prop_node->children->content; - } - } - - g_debug(" Found entry %s %s", cur_node->name, cur_node->properties->children->content); - ui_filters_add (filter, FILTER_ID_UNDEFINED, (const char*) cur_node->name, enabled, - foreground, background); - - filters_entries++; - cur_node = cur_node->next; - } - } - } - filter_node = filter_node->next; - } - } - - /* Filters have changed destroy filter menus and update tree view */ - ui_destroy_filter_menus (); - - /* Reactivate filtering */ - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.filters_enabled), TRUE); - ui_tree_view_refilter (); - } - } - /* Free the document */ - xmlFreeDoc (doc); - - if (filters_entries > 0) - { - ret = RC_OK; - } - - g_message("Parsed XML filters file \"%s\", found %d entries (%d messages to display)", file_name, filters_entries, ui_tree_view_get_filtered_number()); - - return ret; -} - -int ui_filters_read(const char *file_name) -{ - xmlDocPtr doc; /* the resulting document tree */ - int ret; - - if (file_name == NULL) - { - g_warning("No name for filters file"); - return RC_FAIL; - } - - doc = xmlReadFile (file_name, NULL, 0); - if (doc == NULL) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "open filters", "Failed to parse file \"%s\"", file_name); - return RC_FAIL; - } - - ret = xml_parse_filters (doc, file_name); - if (ret != RC_OK) - { - ui_notification_dialog (GTK_MESSAGE_WARNING, FALSE, "open filters", "Found no filter definitions in \"%s\"", - file_name); - return RC_FAIL; - } - - return ret; -} - -static void write_filter(FILE *filter_file, ui_filter_t *filter, gboolean save_colors) -{ - int item; - - fprintf (filter_file, " <%s>\n", filter->name); - for (item = 0; item < filter->used; item++) - { - if (save_colors) - { - fprintf (filter_file, - " <%s " ENABLED_NAME "=\"%d\" " FOREGROUND_NAME "=\"%s\" " BACKGROUND_NAME "=\"%s\"/>\n", - filter->items[item].name, filter->items[item].enabled ? 1 : 0, filter->items[item].foreground, - filter->items[item].background); - } - else - { - fprintf (filter_file, " <%s " ENABLED_NAME "=\"%d\"/>\n", filter->items[item].name, - filter->items[item].enabled ? 1 : 0); - } - } - fprintf (filter_file, " \n", filter->name); -} - -int ui_filters_file_write(const char *file_name) -{ - FILE *filter_file; - - if (file_name == NULL) - { - g_warning("No name for filters file"); - return RC_FAIL; - } - - filter_file = fopen (file_name, "w"); - if (filter_file == NULL) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "Failed to open file \"%s\": %s", file_name, g_strerror (errno)); - return RC_FAIL; - } - - fprintf (filter_file, "\n" - "\n"); - - write_filter (filter_file, &ui_filters.messages, TRUE); - write_filter (filter_file, &ui_filters.origin_tasks, FALSE); - write_filter (filter_file, &ui_filters.destination_tasks, FALSE); - - fprintf (filter_file, "\n"); - - fclose (filter_file); - return RC_OK; -} - -static void ui_create_filter_menu(GtkWidget **menu, ui_filter_t *filter) -{ - if (*menu == NULL) - { - GtkWidget *menu_items; - int item; - gpointer data; - - *menu = gtk_menu_new (); - - /* Create the "NONE" menu-item */ - { - /* Create a new menu-item with a name */ - menu_items = gtk_menu_item_new_with_label ("NONE"); - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - - g_debug("ui_create_filter_menu %lx", (long) menu_items); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_none), *menu); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* Create the "ALL" menu-item */ - { - /* Create a new menu-item with a name */ - menu_items = gtk_menu_item_new_with_label ("ALL"); - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - - g_debug("ui_create_filter_menu %lx", (long) menu_items); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_all), *menu); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* Create separator */ - { - menu_items = gtk_menu_item_new (); - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* Creates menu-items */ - for (item = 0; item < filter->used; item++) - { - /* Create a new menu-item with a name */ - menu_items = gtk_check_menu_item_new_with_label (filter->items[item].name); - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_items), filter->items[item].enabled); - - /* Connect function to be called when the menu item is selected */ - data = &filter->items[item]; - g_debug("ui_create_filter_menu %lx %lx", (long) menu_items, (long) data); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_item_selected), data); - /* Save the menu_item reference */ - filter->items[item].menu_item = menu_items; - - /* Show the widget */ - gtk_widget_show (menu_items); - } - } -} - -void ui_create_filter_menus(void) -{ - ui_create_filter_menu (&ui_main_data.menu_filter_messages, &ui_filters.messages); - ui_create_filter_menu (&ui_main_data.menu_filter_origin_tasks, &ui_filters.origin_tasks); - ui_create_filter_menu (&ui_main_data.menu_filter_destination_tasks, &ui_filters.destination_tasks); - ui_create_filter_menu (&ui_main_data.menu_filter_instances, &ui_filters.instances); -} - -static void ui_destroy_filter_menu_item(GtkWidget *widget, gpointer data) -{ - if (GTK_IS_MENU_ITEM(widget)) - { - gtk_widget_destroy (widget); - } -} - -static void ui_destroy_filter_menu_widget(GtkWidget **menu) -{ - if (*menu != NULL) - { - gtk_container_foreach (GTK_CONTAINER(*menu), ui_destroy_filter_menu_item, NULL); - - gtk_widget_destroy (*menu); - *menu = NULL; - } -} - -void ui_destroy_filter_menus(void) -{ - ui_destroy_filter_menu_widget (&ui_main_data.menu_filter_messages); - ui_destroy_filter_menu_widget (&ui_main_data.menu_filter_origin_tasks); - ui_destroy_filter_menu_widget (&ui_main_data.menu_filter_destination_tasks); - ui_destroy_filter_menu_widget (&ui_main_data.menu_filter_instances); -} - -void ui_destroy_filter_menu(ui_filter_e filter) -{ - switch (filter) - { - case FILTER_MESSAGES: - ui_destroy_filter_menu_widget (&ui_main_data.menu_filter_messages); - break; - - case FILTER_ORIGIN_TASKS: - ui_destroy_filter_menu_widget (&ui_main_data.menu_filter_origin_tasks); - break; - - case FILTER_DESTINATION_TASKS: - ui_destroy_filter_menu_widget (&ui_main_data.menu_filter_destination_tasks); - break; - - case FILTER_INSTANCES: - ui_destroy_filter_menu_widget (&ui_main_data.menu_filter_instances); - break; - - default: - g_warning("unknown filter type %d", filter); - break; - } -} - -void ui_show_filter_menu(GtkWidget **menu, ui_filter_t *filter) -{ - ui_create_filter_menu (menu, filter); - - gtk_menu_popup (GTK_MENU (*menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ()); -} diff --git a/common/utils/itti_analyzer/libui/ui_filters.h b/common/utils/itti_analyzer/libui/ui_filters.h deleted file mode 100644 index 16bb38834b..0000000000 --- a/common/utils/itti_analyzer/libui/ui_filters.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#ifndef UI_FILTERS_H_ -#define UI_FILTERS_H_ - -#include - -#include "itti_types.h" - -#define SIGNAL_NAME_LENGTH 100 -#define COLOR_SIZE 10 - -typedef enum -{ - FILTER_UNKNOWN, FILTER_MESSAGES, FILTER_ORIGIN_TASKS, FILTER_DESTINATION_TASKS, FILTER_INSTANCES, -} ui_filter_e; - -typedef enum -{ - ENTRY_ENABLED_FALSE, ENTRY_ENABLED_TRUE, ENTRY_ENABLED_UNDEFINED, -} ui_entry_enabled_e; - -typedef struct -{ - uint32_t id; - char name[SIGNAL_NAME_LENGTH]; - uint8_t enabled; - char foreground[COLOR_SIZE]; - char background[COLOR_SIZE]; - GtkWidget *menu_item; -} ui_filter_item_t; - -typedef struct -{ - char *name; - uint32_t allocated; - uint32_t used; - ui_filter_item_t *items; -} ui_filter_t; - -typedef struct -{ - gboolean filters_enabled; - ui_filter_t messages; - ui_filter_t origin_tasks; - ui_filter_t destination_tasks; - ui_filter_t instances; -} ui_filters_t; - -extern ui_filters_t ui_filters; - -int ui_init_filters(int reset, int clear_ids); - -gboolean ui_filters_enable(gboolean enabled); - -int ui_filters_search_id(ui_filter_t *filter, uint32_t value); - -void ui_filters_add(ui_filter_e filter, uint32_t value, const char *name, ui_entry_enabled_e entry_enabled, - const char *foreground, const char *background); - -gboolean ui_filters_message_enabled(const uint32_t message, const uint32_t origin_task, const uint32_t destination_task, - const uint32_t instance); - -int ui_filters_read(const char *file_name); - -int ui_filters_file_write(const char *file_name); - -void ui_create_filter_menus(void); - -void ui_destroy_filter_menus(void); - -void ui_destroy_filter_menu(ui_filter_e filter); - -void ui_show_filter_menu(GtkWidget **menu, ui_filter_t *filter); - -#endif /* UI_FILTERS_H_ */ diff --git a/common/utils/itti_analyzer/libui/ui_interface.c b/common/utils/itti_analyzer/libui/ui_interface.c deleted file mode 100644 index 56139a8c6b..0000000000 --- a/common/utils/itti_analyzer/libui/ui_interface.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include - -#define G_LOG_DOMAIN ("UI_INTER") - -#include - -#include "ui_interface.h" - -#include "ui_tree_view.h" -#include "ui_notifications.h" -#include "ui_signal_dissect_view.h" - -#include "socket.h" -#include "xml_parse.h" - -static -gboolean ui_callback_on_pipe_notification( - GIOChannel *source, GIOCondition condition, gpointer user_data) -{ - pipe_input_t *pipe_input = (pipe_input_t *)user_data; - - /* avoid reentrancy problems and stack overflow */ - g_source_remove(pipe_input->pipe_input_id); - - g_debug("Received new data on pipe %d", pipe_input->pipe_input_id); - - if (pipe_input->input_cb(pipe_input->source_fd, pipe_input->user_data)) { - /* restore pipe handler */ - pipe_input->pipe_input_id = g_io_add_watch_full(pipe_input->pipe_channel, - G_PRIORITY_HIGH, - (GIOCondition)(G_IO_IN|G_IO_ERR|G_IO_HUP), - ui_callback_on_pipe_notification, - pipe_input, - NULL); - } - return TRUE; -} - -int ui_pipe_new(int pipe_fd[2], pipe_input_cb_t input_cb, gpointer user_data) -{ - static pipe_input_t pipe_input; - - g_assert(pipe_fd != NULL); - - /* Create a pipe between GUI and a thread or a process */ - if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pipe_fd) < 0) { - g_warning("Failed to create socketpair %s", g_strerror(errno)); - return RC_FAIL; - } - - /* Source taken from wireshark SVN repository */ - - pipe_input.source_fd = pipe_fd[0]; - pipe_input.input_cb = input_cb; - pipe_input.user_data = user_data; - - pipe_input.pipe_channel = g_io_channel_unix_new(pipe_fd[0]); - g_io_channel_set_encoding(pipe_input.pipe_channel, NULL, NULL); - pipe_input.pipe_input_id = g_io_add_watch_full(pipe_input.pipe_channel, - G_PRIORITY_HIGH, - G_IO_IN | G_IO_ERR | G_IO_HUP, - ui_callback_on_pipe_notification, - &pipe_input, - NULL); - - return RC_OK; -} - -int ui_pipe_write_message(int pipe_fd, const uint16_t message_type, - const void * const message, const uint16_t message_size) -{ - int ret; - pipe_input_header_t pipe_input_header; - - pipe_input_header.message_size = message_size + sizeof(pipe_input_header); - pipe_input_header.message_type = message_type; - - if (message_size > 0 && message == NULL) { - g_error("message size = %u but message is NULL", message_size); - g_assert_not_reached(); - } - - ret = write(pipe_fd, &pipe_input_header, sizeof(pipe_input_header)); - if (ret < 0) { - g_warning("Failed to write header to pipe: %s", g_strerror(errno)); - return ret; - } - - /* Only write the message to pipe if valid data to transmit */ - if (message_size > 0) { - ret = write(pipe_fd, message, message_size); - if (ret < 0) { - g_warning("Failed to write message of size %u at 0x%p to pipe: %s", - message_size, message, g_strerror(errno)); - return ret; - } - } - return 0; -} diff --git a/common/utils/itti_analyzer/libui/ui_interface.h b/common/utils/itti_analyzer/libui/ui_interface.h deleted file mode 100644 index f77ec144d1..0000000000 --- a/common/utils/itti_analyzer/libui/ui_interface.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include - -#ifndef UI_INTERFACE_H_ -#define UI_INTERFACE_H_ - -/******************************************************************************* - * Functions used between dissectors and GUI to update signal dissection - ******************************************************************************/ - -typedef gboolean (*ui_set_signal_text_cb_t) (gpointer user_data, gchar *text, gint length); - -/******************************************************************************* - * Pipe interface between GUI thread and other thread - ******************************************************************************/ - -typedef gboolean (*pipe_input_cb_t) (gint source, gpointer user_data); - -typedef struct { - int source_fd; - guint pipe_input_id; - GIOChannel *pipe_channel; - - pipe_input_cb_t input_cb; - gpointer user_data; -} pipe_input_t; - -int ui_pipe_new(int pipe_fd[2], pipe_input_cb_t input_cb, gpointer user_data); - -int ui_pipe_write_message(int pipe_fd, const uint16_t message_type, - const void * const message, const uint16_t message_size); - -typedef struct { - uint16_t message_size; - uint16_t message_type; -} pipe_input_header_t; - -enum ui_pipe_messages_id_e { - /* Other thread -> GUI interface ids */ - UI_PIPE_CONNECTION_FAILED, - UI_PIPE_CONNECTION_LOST, - UI_PIPE_XML_DEFINITION, - UI_PIPE_UPDATE_SIGNAL_LIST, - - /* GUI -> other threads */ - UI_PIPE_DISCONNECT_EVT -}; - -typedef struct { - char *xml_definition; - size_t xml_definition_length; -} pipe_xml_definition_message_t; - -typedef struct { - GList *signal_list; -} pipe_new_signals_list_message_t; - -#endif /* UI_INTERFACE_H_ */ diff --git a/common/utils/itti_analyzer/libui/ui_main_screen.c b/common/utils/itti_analyzer/libui/ui_main_screen.c deleted file mode 100644 index 3d6ea266be..0000000000 --- a/common/utils/itti_analyzer/libui/ui_main_screen.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("UI") - -#include - -#include "logs.h" -#include "rc.h" - -#include "ui_callbacks.h" -#include "ui_interface.h" -#include "ui_main_screen.h" -#include "ui_menu_bar.h" -#include "ui_tree_view.h" -#include "ui_notebook.h" -#include "ui_notifications.h" -#include "ui_filters.h" - -ui_main_data_t ui_main_data; - -static void ui_help(void) -{ - printf ("Usage: itti_analyser [options]\n\n" - "Options:\n" - " -d DISSECT write DISSECT file with message types parse details\n" - " -f FILTERS read filters from FILTERS file\n" - " -h display this help and exit\n" - " -i IP set ip address to IP\n" - " -l LEVEL set log level to LEVEL in the range of 2 to 7\n" - " -m MESSAGES read messages from MESSAGES file\n" - " -p PORT set port to PORT\n"); -} - -void ui_gtk_parse_arg(int argc, char *argv[]) -{ - char c; - - /* Clear of ui_main_data not needed */ - // memset (&ui_main_data, 0, sizeof(ui_main_data_t)); - - /* Set some default initialization value for the IP address */ - ui_main_data.ip_entry_init = "127.0.0.1"; - ui_main_data.port_entry_init = "10006"; - - /* Set default log level to at least warning level messages */ - ui_main_data.log_flags = (G_LOG_LEVEL_MASK & (~(G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG))); - - while ((c = getopt (argc, argv, "d:f:hi:l:m:p:")) != -1) - { - switch (c) - { - case 'd': - ui_main_data.dissect_file_name = malloc (strlen (optarg) + 1); - if (ui_main_data.dissect_file_name != NULL) - { - strcpy (ui_main_data.dissect_file_name, optarg); - } - break; - - case 'f': - ui_main_data.filters_file_name = malloc (strlen (optarg) + 1); - if (ui_main_data.filters_file_name != NULL) - { - strcpy (ui_main_data.filters_file_name, optarg); - } - break; - - case 'h': - ui_help (); - exit (0); - break; - - case 'i': - ui_main_data.ip_entry_init = optarg; - break; - - case 'l': - { - GLogLevelFlags log_flag; - - log_flag = 1 << atoi(optarg); - if (log_flag < G_LOG_LEVEL_ERROR) - { - log_flag = G_LOG_LEVEL_ERROR; - } - else - { - if (log_flag > G_LOG_LEVEL_DEBUG) - { - log_flag = G_LOG_LEVEL_DEBUG; - } - } - ui_main_data.log_flags = ((log_flag << 1) - 1) & G_LOG_LEVEL_MASK; - break; - } - - case 'm': - ui_main_data.messages_file_name = malloc (strlen (optarg) + 1); - if (ui_main_data.messages_file_name != NULL) - { - strcpy (ui_main_data.messages_file_name, optarg); - } - break; - - case 'p': - ui_main_data.port_entry_init = optarg; - break; - - default: - ui_help (); - exit (-1); - break; - } - } -} - -static int ui_idle_callback(gpointer data) -{ - g_info("Entering idle state"); - - gtk_window_set_focus (GTK_WINDOW(ui_main_data.window), ui_main_data.messages_list); - - /* Read filters file */ - if (ui_main_data.filters_file_name != NULL) - { - ui_filters_read(ui_main_data.filters_file_name); - } - - /* Read messages file */ - if (ui_main_data.messages_file_name != NULL) - { - ui_messages_read (ui_main_data.messages_file_name); - } - - /* One shot execution */ - return FALSE; -} - -void ui_set_title(const char *fmt, ...) -{ - va_list args; - char *name; - char buffer[200]; - char title[220]; - -#if defined(PACKAGE_STRING) - name = PACKAGE_NAME; -#else - name = "itti_analyzer"; -#endif - - va_start(args, fmt); - - vsnprintf (buffer, sizeof(buffer), fmt, args); - snprintf (title, sizeof(title), "%s %s", name, buffer); - va_end (args); - - gtk_window_set_title (GTK_WINDOW(ui_main_data.window), title); -} - -void ui_main_window_destroy (void) -{ - ui_callback_dialogbox_connect_destroy(); - ui_progressbar_window_destroy(); - gtk_main_quit(); -} - -int ui_gtk_initialize(int argc, char *argv[]) -{ - GtkWidget *vbox; - - /* Create the main window */ - ui_main_data.window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - ui_init_filters (TRUE, FALSE); - - // gtk_window_set_default_icon_from_file ("../analyzer.png", NULL); - gtk_window_set_default_icon_name (GTK_STOCK_FIND); - - gtk_window_set_position (GTK_WINDOW(ui_main_data.window), GTK_WIN_POS_CENTER); - gtk_window_set_default_size (GTK_WINDOW(ui_main_data.window), 1024, 800); - ui_set_title(""); - gtk_window_set_resizable (GTK_WINDOW(ui_main_data.window), TRUE); - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - - CHECK_FCT(ui_menu_bar_create(vbox)); - CHECK_FCT(ui_toolbar_create(vbox)); - CHECK_FCT(ui_notebook_create(vbox)); - - gtk_container_add (GTK_CONTAINER(ui_main_data.window), vbox); - - /* Assign the destroy event */ - g_signal_connect(ui_main_data.window, "destroy", ui_main_window_destroy, NULL); - - /* Show the application window */ - gtk_widget_show_all (ui_main_data.window); - - g_idle_add (ui_idle_callback, NULL); - - return RC_OK; -} - -void ui_gtk_flush_events(void) -{ - while (gtk_events_pending ()) - { - gtk_main_iteration(); - } -} diff --git a/common/utils/itti_analyzer/libui/ui_main_screen.h b/common/utils/itti_analyzer/libui/ui_main_screen.h deleted file mode 100644 index 0411d687be..0000000000 --- a/common/utils/itti_analyzer/libui/ui_main_screen.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#ifndef UI_MAIN_SCREEN_H_ -#define UI_MAIN_SCREEN_H_ - -#include - -#include "ui_signal_dissect_view.h" - -typedef struct { - GtkWidget *window; - GtkWidget *ip_entry; - char *ip_entry_init; - GtkWidget *port_entry; - char *port_entry_init; - - GtkWidget *progressbar_window; - GtkWidget *progressbar; - GtkWidget *messages_list; - ui_text_view_t *text_view; - - /* Buttons */ - GtkToolItem *filters_enabled; - GtkToolItem *open_filters_file; - GtkToolItem *refresh_filters_file; - GtkToolItem *save_filters_file; - - GtkToolItem *open_replay_file; - GtkToolItem *refresh_replay_file; - GtkToolItem *stop_loading; - GtkToolItem *save_replay_file; - GtkToolItem *save_replay_file_filtered; - - GtkToolItem *auto_reconnect; - GtkToolItem *connect; - GtkToolItem *disconnect; - - /* Signal list buttons */ - /* Clear signals button */ - GtkWidget *signals_go_to_entry; - GtkToolItem *signals_go_to_last_button; - GtkToolItem *signals_go_to_first_button; - gboolean display_message_header; - gboolean display_brace; - - GtkTreeSelection *selection; - gboolean follow_last; - - /* Nb of messages received */ - guint nb_message_received; - - GLogLevelFlags log_flags; - char *dissect_file_name; - char *filters_file_name; - char *messages_file_name; - - GtkWidget *menu_filter_messages; - GtkWidget *menu_filter_origin_tasks; - GtkWidget *menu_filter_destination_tasks; - GtkWidget *menu_filter_instances; - - int pipe_fd[2]; -} ui_main_data_t; - -extern ui_main_data_t ui_main_data; - -void ui_gtk_parse_arg(int argc, char *argv[]); - -void ui_set_title(const char *fmt, ...); - -void ui_main_window_destroy (void); - -int ui_gtk_initialize(int argc, char *argv[]); - -void ui_gtk_flush_events(void); - -#endif /* UI_MAIN_SCREEN_H_ */ diff --git a/common/utils/itti_analyzer/libui/ui_menu_bar.c b/common/utils/itti_analyzer/libui/ui_menu_bar.c deleted file mode 100644 index 62b51b3b9f..0000000000 --- a/common/utils/itti_analyzer/libui/ui_menu_bar.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#define G_LOG_DOMAIN ("UI") - -#include -#include - -#include "rc.h" -#include "ui_main_screen.h" -#include "ui_menu_bar.h" -#include "ui_callbacks.h" -#include "ui_notifications.h" - -static const guint BUTTON_SPACE = 0; -static const guint LABEL_SPACE = 5; -static const guint SEPARATOR_SPACE = 5; - -void ui_set_sensitive_move_buttons(gboolean enable) -{ - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_last_button), enable); - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_first_button), enable); -} - -void ui_set_sensitive_save_message_buttons(gboolean enable) -{ - if (ui_main_data.nb_message_received == 0) - { - enable = FALSE; - } - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.save_replay_file), enable); - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.save_replay_file_filtered), enable); -} - -int ui_menu_bar_create(GtkWidget *vbox) -{ - GtkAccelGroup *accel_group; - GtkWidget *menu_bar; - - GtkWidget *system_menu; - GtkWidget *system; - GtkWidget *quit; - - GtkWidget *filters_menu; - GtkWidget *filters; - GtkWidget *open_filters; - GtkWidget *reload_filters; - GtkWidget *save_filters; - GtkWidget *enable_filters; - - GtkWidget *messages_menu; - GtkWidget *messages; - GtkWidget *open_messages; - GtkWidget *reload_messages; - GtkWidget *stop_loading; - GtkWidget *save_messages; - GtkWidget *save_messages_filtered; - GtkWidget *goto_first_messages; - GtkWidget *goto_messages; - GtkWidget *goto_last_messages; - GtkWidget *display_message_header; - GtkWidget *display_brace; - - GtkWidget *connect_menu; - GtkWidget *connect; - GtkWidget *auto_reconnect; - GtkWidget *connect_to; - GtkWidget *disconnect; - - GtkWidget *help_menu; - GtkWidget *help; - GtkWidget *about; - - if (!vbox) - return RC_BAD_PARAM; - - accel_group = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(ui_main_data.window), accel_group); - - menu_bar = gtk_menu_bar_new(); - - /* Create the System sub-menu */ - { - system = gtk_menu_item_new_with_mnemonic ("_System"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu_bar), system); - - system_menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(system), system_menu); - - /* Create the Filters menu items */ - { - quit = gtk_menu_item_new_with_mnemonic ("_Quit"); - gtk_widget_add_accelerator (quit, "activate", accel_group, GDK_KEY_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(system_menu), quit); - g_signal_connect(G_OBJECT(quit), "activate", ui_main_window_destroy, NULL); - } - } - - /* Create the Filters sub-menu */ - { - filters = gtk_menu_item_new_with_mnemonic ("_Filters"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu_bar), filters); - - filters_menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(filters), filters_menu); - - /* Create the Filters menu items */ - { - open_filters = gtk_menu_item_new_with_mnemonic ("_Open filters file"); - gtk_widget_add_accelerator (open_filters, "activate", accel_group, GDK_KEY_p, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(filters_menu), open_filters); - g_signal_connect(G_OBJECT(open_filters), "activate", G_CALLBACK(ui_callback_on_open_filters), (gpointer) FALSE); - - reload_filters = gtk_menu_item_new_with_mnemonic ("_Reload filters file"); - gtk_widget_add_accelerator (reload_filters, "activate", accel_group, GDK_KEY_d, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_widget_add_accelerator (reload_filters, "activate", accel_group, GDK_KEY_F4, 0, GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(filters_menu), reload_filters); - g_signal_connect(G_OBJECT(reload_filters), "activate", G_CALLBACK(ui_callback_on_open_filters), - (gpointer) TRUE); - - save_filters = gtk_menu_item_new_with_mnemonic ("_Save filters file"); - gtk_widget_add_accelerator (save_filters, "activate", accel_group, GDK_KEY_v, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(filters_menu), save_filters); - g_signal_connect(G_OBJECT(save_filters), "activate", G_CALLBACK(ui_callback_on_save_filters), NULL); - - gtk_menu_shell_append (GTK_MENU_SHELL(filters_menu), gtk_menu_item_new ()); // Separator - - enable_filters = gtk_menu_item_new_with_mnemonic ("_Enable filtering"); - gtk_widget_add_accelerator (enable_filters, "activate", accel_group, GDK_KEY_e, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(filters_menu), enable_filters); - g_signal_connect(G_OBJECT(enable_filters), "activate", G_CALLBACK(ui_callback_on_enable_filters), NULL); - } - } - - /* Create the Messages sub-menu */ - { - messages = gtk_menu_item_new_with_mnemonic ("_Messages"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu_bar), messages); - - messages_menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(messages), messages_menu); - - /* Crate the Messages menu items */ - { - open_messages = gtk_menu_item_new_with_mnemonic ("_Open messages file"); - gtk_widget_add_accelerator (open_messages, "activate", accel_group, GDK_KEY_o, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), open_messages); - g_signal_connect(G_OBJECT(open_messages), "activate", G_CALLBACK(ui_callback_on_open_messages), - (gpointer) FALSE); - - reload_messages = gtk_menu_item_new_with_mnemonic ("_Reload messages file"); - gtk_widget_add_accelerator (reload_messages, "activate", accel_group, GDK_KEY_r, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_widget_add_accelerator (reload_messages, "activate", accel_group, GDK_KEY_F5, 0, GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), reload_messages); - g_signal_connect(G_OBJECT(reload_messages), "activate", G_CALLBACK(ui_callback_on_open_messages), - (gpointer) TRUE); - - stop_loading = gtk_menu_item_new_with_mnemonic ("S_top loading messages file"); - gtk_widget_add_accelerator (stop_loading, "activate", accel_group, GDK_KEY_x, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), stop_loading); - g_signal_connect(G_OBJECT(stop_loading), "activate", G_CALLBACK(ui_progressbar_window_destroy), - NULL); - - save_messages = gtk_menu_item_new_with_mnemonic ("S_ave messages file (all)"); - gtk_widget_add_accelerator (save_messages, "activate", accel_group, GDK_KEY_a, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), save_messages); - g_signal_connect(G_OBJECT(save_messages), "activate", G_CALLBACK(ui_callback_on_save_messages), - (gpointer) FALSE); - - save_messages_filtered = gtk_menu_item_new_with_mnemonic ("_Save messages file (filtered)"); - gtk_widget_add_accelerator (save_messages_filtered, "activate", accel_group, GDK_KEY_s, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), save_messages_filtered); - g_signal_connect(G_OBJECT(save_messages_filtered), "activate", G_CALLBACK(ui_callback_on_save_messages), - (gpointer) TRUE); - - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), gtk_menu_item_new ()); // Separator - - goto_first_messages = gtk_menu_item_new_with_mnemonic ("Go to _first message"); - gtk_widget_add_accelerator (goto_first_messages, "activate", accel_group, GDK_KEY_f, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), goto_first_messages); - g_signal_connect(G_OBJECT(goto_first_messages), "activate", G_CALLBACK(ui_callback_signal_go_to_first), - NULL); - - goto_messages = gtk_menu_item_new_with_mnemonic ("_Go to message ..."); - gtk_widget_add_accelerator (goto_messages, "activate", accel_group, GDK_KEY_g, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), goto_messages); - g_signal_connect(G_OBJECT(goto_messages), "activate", G_CALLBACK(ui_callback_signal_go_to), NULL); - - goto_last_messages = gtk_menu_item_new_with_mnemonic ("Go to _last message"); - gtk_widget_add_accelerator (goto_last_messages, "activate", accel_group, GDK_KEY_l, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), goto_last_messages); - g_signal_connect(G_OBJECT(goto_last_messages), "activate", G_CALLBACK(ui_callback_signal_go_to_last), (gpointer) TRUE); - - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), gtk_menu_item_new ()); // Separator - - display_message_header = gtk_menu_item_new_with_mnemonic ("Display message _header"); - gtk_widget_add_accelerator (display_message_header, "activate", accel_group, GDK_KEY_h, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), display_message_header); - g_signal_connect(G_OBJECT(display_message_header), "activate", - G_CALLBACK(ui_callback_display_message_header), NULL); - - display_brace = gtk_menu_item_new_with_mnemonic ("Display _brace"); - gtk_widget_add_accelerator (display_brace, "activate", accel_group, GDK_KEY_b, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(messages_menu), display_brace); - g_signal_connect(G_OBJECT(display_brace), "activate", G_CALLBACK(ui_callback_display_brace), NULL); - } - } - - /* Create the Connect sub-menu */ - { - connect = gtk_menu_item_new_with_mnemonic ("_Connect"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu_bar), connect); - - connect_menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(connect), connect_menu); - - /* Create the Help menu item */ - { - auto_reconnect = gtk_menu_item_new_with_mnemonic ("_Automatic reconnection"); - gtk_widget_add_accelerator (auto_reconnect, "activate", accel_group, GDK_KEY_t, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(connect_menu), auto_reconnect); - g_signal_connect(G_OBJECT(auto_reconnect), "activate", G_CALLBACK(ui_callback_on_auto_reconnect), (gpointer) TRUE); - - connect_to = gtk_menu_item_new_with_mnemonic ("_Connect"); - gtk_widget_add_accelerator (connect_to, "activate", accel_group, GDK_KEY_c, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(connect_menu), connect_to); - g_signal_connect(G_OBJECT(connect_to), "activate", G_CALLBACK(ui_callback_on_connect), (gpointer) TRUE); - - disconnect = gtk_menu_item_new_with_mnemonic ("_Disconnect"); - gtk_widget_add_accelerator (disconnect, "activate", accel_group, GDK_KEY_u, GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - gtk_menu_shell_append (GTK_MENU_SHELL(connect_menu), disconnect); - g_signal_connect(G_OBJECT(disconnect), "activate", G_CALLBACK(ui_callback_on_disconnect), NULL); - } - } - - /* Create the Help sub-menu */ - { - help = gtk_menu_item_new_with_mnemonic ("_Help"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu_bar), help); - - help_menu = gtk_menu_new (); - gtk_menu_item_set_submenu (GTK_MENU_ITEM(help), help_menu); - - /* Create the Help menu item */ - { - about = gtk_menu_item_new_with_mnemonic ("_About"); - gtk_menu_shell_append (GTK_MENU_SHELL(help_menu), about); - g_signal_connect(G_OBJECT(about), "activate", G_CALLBACK(ui_callback_on_about), NULL); - } - } - - /* Add the menubar to the vbox */ - gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 3); - - return RC_OK; -} - -int ui_toolbar_create(GtkWidget *vbox) -{ - GtkWidget *hbox; - GtkWidget *messages_label; - GtkWidget *ip_label; - GtkWidget *port_label; - - if (!vbox) - return RC_BAD_PARAM; - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - - messages_label = gtk_label_new("Messages"); - - /* Button to Enable filtering */ - { - ui_main_data.filters_enabled = gtk_toggle_tool_button_new(); - gtk_tool_button_set_label (GTK_TOOL_BUTTON(ui_main_data.filters_enabled), "Filters"); - g_signal_connect(G_OBJECT(ui_main_data.filters_enabled), "clicked", - G_CALLBACK(ui_callback_on_filters_enabled), NULL); - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.filters_enabled), TRUE); - } - - /* Button to open filters file */ - { - ui_main_data.open_filters_file = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.open_filters_file), "Open filters file"); - - g_signal_connect(G_OBJECT(ui_main_data.open_filters_file), "clicked", - G_CALLBACK(ui_callback_on_open_filters), (gpointer) FALSE); - } - - /* Button to refresh filters file */ - { - ui_main_data.refresh_filters_file = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.refresh_filters_file), "Reload filters file"); - - g_signal_connect(G_OBJECT(ui_main_data.refresh_filters_file), "clicked", - G_CALLBACK(ui_callback_on_open_filters), (gpointer) TRUE); - } - - /* Button to save filters file */ - { - ui_main_data.save_filters_file = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.save_filters_file), "Save filters file"); - - g_signal_connect(G_OBJECT(ui_main_data.save_filters_file), "clicked", - G_CALLBACK(ui_callback_on_save_filters), NULL); - } - - /* Button to open messages file */ - { - ui_main_data.open_replay_file = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.open_replay_file), "Open messages file"); - - g_signal_connect(G_OBJECT(ui_main_data.open_replay_file), "clicked", - G_CALLBACK(ui_callback_on_open_messages), (gpointer) FALSE); - } - - /* Button to refresh messages file */ - { - ui_main_data.refresh_replay_file = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.refresh_replay_file), "Reload messages file"); - - g_signal_connect(G_OBJECT(ui_main_data.refresh_replay_file), "clicked", - G_CALLBACK(ui_callback_on_open_messages), (gpointer) TRUE); - } - - /* Stop reading messages file */ - { - ui_main_data.stop_loading = gtk_tool_button_new_from_stock(GTK_STOCK_STOP); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.stop_loading), "Stop loading messages file"); - - g_signal_connect(G_OBJECT(ui_main_data.stop_loading), "clicked", - ui_progressbar_window_destroy, NULL); - } - - /* Button to save messages file */ - { - ui_main_data.save_replay_file = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.save_replay_file), "Save messages file (all)"); - - g_signal_connect(G_OBJECT(ui_main_data.save_replay_file), "clicked", - G_CALLBACK(ui_callback_on_save_messages), (gpointer) FALSE); - } - - /* Button to save messages file */ - { - ui_main_data.save_replay_file_filtered = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE_AS); - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.save_replay_file_filtered), "Save messages file (filtered)"); - - g_signal_connect(G_OBJECT(ui_main_data.save_replay_file_filtered), "clicked", - G_CALLBACK(ui_callback_on_save_messages), (gpointer) TRUE); - } - - /* Button to go to first signal in list */ - { - ui_main_data.signals_go_to_first_button = gtk_tool_button_new_from_stock(GTK_STOCK_GOTO_FIRST); - /* Set the tooltip text */ - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.signals_go_to_first_button), "Goto first signal"); - - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_first_button), FALSE); - - g_signal_connect(G_OBJECT(ui_main_data.signals_go_to_first_button), "clicked", - G_CALLBACK(ui_callback_signal_go_to_first), NULL); - } - - /* Entry to go to given signal number */ - { - ui_main_data.signals_go_to_entry = gtk_entry_new (); - gtk_entry_set_width_chars (GTK_ENTRY(ui_main_data.signals_go_to_entry), 10); - // gtk_entry_set_input_purpose (GTK_ENTRY(ui_main_data.signals_go_to_entry), GTK_INPUT_PURPOSE_DIGITS); - - g_signal_connect(G_OBJECT(ui_main_data.signals_go_to_entry), "activate", - G_CALLBACK(ui_callback_signal_go_to_entry), NULL); - } - - /* Button to go to last signal in list */ - { - ui_main_data.signals_go_to_last_button = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_GOTO_LAST); - /* Set the tooltip text */ - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.signals_go_to_last_button), "Goto last signal"); - - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_last_button), FALSE); - - g_signal_connect(G_OBJECT(ui_main_data.signals_go_to_last_button), "clicked", - G_CALLBACK(ui_callback_signal_go_to_last), (gpointer) FALSE); - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.signals_go_to_last_button), TRUE); - } - - /* Button to automatically try to reconnect */ - { - ui_main_data.auto_reconnect = gtk_toggle_tool_button_new(); - gtk_tool_button_set_label (GTK_TOOL_BUTTON(ui_main_data.auto_reconnect), "Auto"); - g_signal_connect(G_OBJECT(ui_main_data.auto_reconnect), "clicked", - G_CALLBACK(ui_callback_on_auto_reconnect), (gpointer) FALSE); - gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON(ui_main_data.auto_reconnect), FALSE); - } - - /* Button to connect to remote */ - { - ui_main_data.connect = gtk_tool_button_new_from_stock(GTK_STOCK_CONNECT); - /* Set the tooltip text */ - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.connect), "Connect to remote host"); - - g_signal_connect(G_OBJECT(ui_main_data.connect), "clicked", - G_CALLBACK(ui_callback_on_connect), (gpointer) TRUE); - } - - /* Button to disconnect from remote */ - { - ui_main_data.disconnect = gtk_tool_button_new_from_stock(GTK_STOCK_DISCONNECT); - /* Set the tooltip text */ - gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.disconnect), "Disconnect from remote host"); - - /* Disabled at startup. Will be activated when a connection is established */ - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.disconnect), FALSE); - - g_signal_connect(G_OBJECT(ui_main_data.disconnect), "clicked", - G_CALLBACK(ui_callback_on_disconnect), NULL); - } - - ip_label = gtk_label_new("ip:"); - port_label = gtk_label_new("port:"); - - ui_main_data.ip_entry = gtk_entry_new(); - /* Width of 15 characters for port number (ipv4 address) */ - gtk_entry_set_width_chars(GTK_ENTRY(ui_main_data.ip_entry), 15); - gtk_entry_set_text(GTK_ENTRY(ui_main_data.ip_entry), ui_main_data.ip_entry_init); - - ui_main_data.port_entry = gtk_entry_new(); - /* Width of 5 characters for port number (uint16_t) */ - gtk_entry_set_width_chars(GTK_ENTRY(ui_main_data.port_entry), 5); - gtk_entry_set_text(GTK_ENTRY(ui_main_data.port_entry), ui_main_data.port_entry_init); - - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.filters_enabled), FALSE, FALSE, LABEL_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.open_filters_file), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.refresh_filters_file), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.save_filters_file), FALSE, FALSE, BUTTON_SPACE); - - gtk_box_pack_start(GTK_BOX(hbox), gtk_separator_new(GTK_ORIENTATION_VERTICAL), FALSE, FALSE, SEPARATOR_SPACE); - - gtk_box_pack_start(GTK_BOX(hbox), messages_label, FALSE, FALSE, LABEL_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.open_replay_file), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.refresh_replay_file), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.stop_loading), FALSE, FALSE, BUTTON_SPACE); - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.stop_loading), FALSE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.save_replay_file), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.save_replay_file_filtered), FALSE, FALSE, BUTTON_SPACE); - ui_set_sensitive_save_message_buttons(FALSE); - - gtk_box_pack_start(GTK_BOX(hbox), gtk_separator_new(GTK_ORIENTATION_VERTICAL), FALSE, FALSE, SEPARATOR_SPACE); - - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.signals_go_to_first_button), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.signals_go_to_entry), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.signals_go_to_last_button), FALSE, FALSE, BUTTON_SPACE); - - gtk_box_pack_start(GTK_BOX(hbox), gtk_separator_new(GTK_ORIENTATION_VERTICAL), FALSE, FALSE, SEPARATOR_SPACE); - - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.auto_reconnect), FALSE, FALSE, LABEL_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.connect), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ui_main_data.disconnect), FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), ip_label, FALSE, FALSE, LABEL_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), ui_main_data.ip_entry, FALSE, FALSE, BUTTON_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), port_label, FALSE, FALSE, LABEL_SPACE); - gtk_box_pack_start(GTK_BOX(hbox), ui_main_data.port_entry, FALSE, FALSE, BUTTON_SPACE); - - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); - - return RC_OK; -} diff --git a/common/utils/itti_analyzer/libui/ui_notebook.c b/common/utils/itti_analyzer/libui/ui_notebook.c deleted file mode 100644 index 93a439335f..0000000000 --- a/common/utils/itti_analyzer/libui/ui_notebook.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#define G_LOG_DOMAIN ("UI") - -#include - -#include "rc.h" - -#include "ui_notebook.h" -#include "ui_tree_view.h" -#include "ui_signal_dissect_view.h" - -static ui_text_view_t *terminal_view; - -void ui_notebook_terminal_clear(void) -{ - ui_signal_dissect_clear_view(terminal_view); -} - -void ui_notebook_terminal_append_data(gchar *text, gint length) -{ - ui_signal_set_text(terminal_view, text, length); -} - -int ui_notebook_create(GtkWidget *vbox) -{ - GtkWidget *notebook; - GtkWidget *vbox_notebook, *vbox_terminal; - - if (!vbox) - return RC_BAD_PARAM; - - notebook = gtk_notebook_new(); - - vbox_notebook = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - ui_tree_view_create(NULL, vbox_notebook); - - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_notebook, NULL); - gtk_notebook_set_tab_label_text (GTK_NOTEBOOK(notebook), vbox_notebook, "Messages list"); - -#if defined (FILTERS_TAB) - vbox_notebook = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_notebook, NULL); - gtk_notebook_set_tab_label_text (GTK_NOTEBOOK(notebook), vbox_notebook, "Filters"); -#endif - - vbox_notebook = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox_notebook, NULL); - gtk_notebook_set_tab_label_text (GTK_NOTEBOOK(notebook), vbox_notebook, "Terminal"); - - vbox_terminal = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL); - - terminal_view = ui_signal_dissect_new(vbox_terminal); - - gtk_box_pack_start (GTK_BOX(vbox_notebook), vbox_terminal, TRUE, TRUE, 5); - - /* Add the notebook to the vbox of the main window */ - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); - - return RC_OK; -} diff --git a/common/utils/itti_analyzer/libui/ui_notif_dlg.c b/common/utils/itti_analyzer/libui/ui_notif_dlg.c deleted file mode 100644 index 4be4aa52cf..0000000000 --- a/common/utils/itti_analyzer/libui/ui_notif_dlg.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#define G_LOG_DOMAIN ("UI") - -#include "rc.h" - -#include "ui_notif_dlg.h" -#include "ui_main_screen.h" - -static const char * const gtk_response_strings[] = - {"GTK_RESPONSE_NONE", "GTK_RESPONSE_REJECT", "GTK_RESPONSE_ACCEPT", "GTK_RESPONSE_DELETE_EVENT", "GTK_RESPONSE_OK", - "GTK_RESPONSE_CANCEL", "GTK_RESPONSE_CLOSE", "GTK_RESPONSE_YES", "GTK_RESPONSE_NO", "GTK_RESPONSE_APPLY", "GTK_RESPONSE_HELP"}; - -static const char * const title_type_strings[] = - {"Info", "Warning", "Question", "Error", "Other"}; - -const char * gtk_get_respose_string (gint response) -{ - gint response_index = - response - 1; - - if ((0 <= response_index) && (response_index < (sizeof (gtk_response_strings) / sizeof (gtk_response_strings[0])))) - { - return (gtk_response_strings[response_index]); - } - else - { - return ("Invalid response value!"); - } -} -int ui_notification_dialog(GtkMessageType type, gboolean cancel, const char *title, const char *fmt, ...) -{ - va_list args; - GtkWidget *dialogbox; - char buffer[200]; - int result = RC_OK; - - va_start(args, fmt); - - vsnprintf (buffer, sizeof(buffer), fmt, args); - - g_warning("%s", buffer); - - dialogbox = gtk_message_dialog_new (GTK_WINDOW(ui_main_data.window), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, type, - cancel ? GTK_BUTTONS_OK_CANCEL : GTK_BUTTONS_OK, "%s", - buffer); - /* Set the window at center of main window */ - gtk_window_set_position (GTK_WINDOW(dialogbox), GTK_WIN_POS_CENTER_ON_PARENT); - - gtk_dialog_set_default_response (GTK_DIALOG(dialogbox), GTK_RESPONSE_OK); - - snprintf (buffer, sizeof(buffer), "%s: %s", title_type_strings[type], title); - gtk_window_set_title (GTK_WINDOW(dialogbox), buffer); - - if (gtk_dialog_run (GTK_DIALOG (dialogbox)) == GTK_RESPONSE_CANCEL) - { - result = RC_FAIL; - } - - gtk_widget_destroy (dialogbox); - - va_end(args); - - return result; -} diff --git a/common/utils/itti_analyzer/libui/ui_notifications.c b/common/utils/itti_analyzer/libui/ui_notifications.c deleted file mode 100644 index 6e7897c850..0000000000 --- a/common/utils/itti_analyzer/libui/ui_notifications.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -#define G_LOG_DOMAIN ("UI") - -#include - -#include - -#include "logs.h" -#include "itti_types.h" -#include "rc.h" - -#include "ui_interface.h" -#include "ui_main_screen.h" -#include "ui_menu_bar.h" -#include "ui_notifications.h" -#include "ui_notif_dlg.h" -#include "ui_callbacks.h" -#include "ui_filters.h" -#include "ui_tree_view.h" - -#include "locate_root.h" -#include "xml_parse.h" -#include "socket.h" - -static const itti_message_types_t itti_dump_xml_definition_end = ITTI_DUMP_XML_DEFINITION_END; -static const itti_message_types_t itti_dump_message_type_end = ITTI_DUMP_MESSAGE_TYPE_END; - -static FILE *messages_file; -static uint32_t message_number; -static gboolean ui_abort; - -int ui_disable_connect_button(void) -{ - /* Disable Connect button and enable disconnect button */ - gtk_widget_set_sensitive (GTK_WIDGET (ui_main_data.connect), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (ui_main_data.disconnect), TRUE); - socket_abort_connection = FALSE; - - return RC_OK; -} - -int ui_enable_connect_button(void) -{ - /* Disable Disconnect button and enable connect button */ - gtk_widget_set_sensitive (GTK_WIDGET (ui_main_data.connect), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (ui_main_data.disconnect), FALSE); - socket_abort_connection = TRUE; - ui_set_sensitive_save_message_buttons (TRUE); - ui_set_title (""); - - return RC_OK; -} - -static void ui_change_cursor(gboolean busy) -{ - static GdkWindow *window; - - if (busy) - { - GdkDisplay *display; - GdkCursor *cursor; - // gint x, y; - - cursor = gdk_cursor_new (GDK_WATCH); - display = gdk_display_get_default (); - window = gtk_widget_get_window (GTK_WIDGET(ui_main_data.window)); - // window = gdk_display_get_window_at_pointer(display, &x, &y); - - gdk_window_set_cursor (window, cursor); - gdk_display_sync (display); - g_object_unref (cursor); - // gtk_widget_set_sensitive (ui_main_data.window, FALSE); - ui_gtk_flush_events (); - } - else - { - gdk_window_set_cursor (window, NULL); - // gtk_widget_set_sensitive (ui_main_data.window, TRUE); - ui_gtk_flush_events (); - } -} - -static void gtk_filter_add(GtkWidget *file_chooser, const gchar *title, const gchar *pattern) -{ - GtkFileFilter *file_filter = gtk_file_filter_new (); - - gtk_file_filter_set_name (file_filter, title); - gtk_file_filter_add_pattern (file_filter, pattern); - gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(file_chooser), file_filter); -} - -int ui_messages_read(char *file_name) -{ - int result = RC_OK; - int source; - int read_data = 0; - void *input_data = NULL; - size_t input_data_length = 0; - int read_messages = 0; - - ui_change_cursor (TRUE); - - source = open (file_name, O_RDONLY); - if (source < 0) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "open messages", "Failed to open file \"%s\": %s", file_name, - g_strerror (errno)); - result = RC_FAIL; - } - else - { - itti_socket_header_t message_header; - struct stat st; - int size; - double read_fraction = 0.f; - - if (stat (file_name, &st) < 0) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "get file length", - "Failed to retrieve length for file \"%s\": %s", file_name, g_strerror (errno)); - result = RC_FAIL; - } - size = st.st_size; - - ui_callback_signal_clear_list (NULL, NULL); - - /* Initialize the progress bar */ - ui_abort = FALSE; - ui_progress_bar_set_fraction (0); - - do - { - read_data = read (source, &message_header, sizeof(itti_socket_header_t)); - - if (read_data == -1) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "open messages", "Failed to read from file \"%s\": %s", - file_name, g_strerror (errno)); - result = RC_FAIL; - break; - } - - if (read_data == 0) - { - break; - } - - if (read_data < sizeof(itti_socket_header_t)) - { - if (ui_notification_dialog (GTK_MESSAGE_WARNING, TRUE, "open messages", - "Failed to read a complete message header from file \"%s\": %s", file_name, g_strerror (errno)) == RC_FAIL) - { - read_data = 0; - } - } - else - { - read_fraction += (double) read_data / size; - - input_data_length = message_header.message_size - sizeof(itti_socket_header_t); - - g_debug("%x, %x, %zd", message_header.message_type, message_header.message_size, input_data_length); - - /* Checking for non-header part */ - if (input_data_length > 0) - { - input_data = malloc (input_data_length); - - read_data = read (source, input_data, input_data_length); - if (read_data < input_data_length) - { - if (ui_notification_dialog (GTK_MESSAGE_WARNING, TRUE, "open messages", - "Failed to read a complete message from file \"%s\": %s", file_name, g_strerror (errno)) == RC_FAIL) - { - read_data = 0; - } - break; - } - - read_fraction += (double) input_data_length / size; - } - - switch (message_header.message_type) - { - case ITTI_DUMP_XML_DEFINITION: - ui_gtk_flush_events (); - if (memcmp (&(((char *) input_data)[input_data_length - sizeof (itti_message_types_t)]), - &itti_dump_xml_definition_end, sizeof (itti_message_types_t)) == 0) - { - result = xml_parse_buffer (input_data, input_data_length - sizeof (itti_message_types_t)); - if (result != RC_OK) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "open messages", - "Error in parsing XML definitions in file \"%s\": %s", file_name, - rc_strings[-result]); - read_data = 0; - } - ui_gtk_flush_events (); - g_message("Parsed XML definition from file \"%s\"", file_name); - } - else - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "open messages", - "Error in parsing XML definitions in file \"%s\", end mark is missing", file_name); - } - /* Data input buffer is kept in case user when to save the log file later */ - break; - - case ITTI_DUMP_MESSAGE_TYPE: - { - itti_signal_header_t *itti_signal_header = input_data; - buffer_t *buffer; - - if (memcmp (&(((char *) input_data)[input_data_length - sizeof (itti_message_types_t)]), - &itti_dump_message_type_end, sizeof (itti_message_types_t)) == 0) - { - /* Create the new buffer */ - if (buffer_new_from_data (&buffer, input_data + sizeof(itti_signal_header_t), - input_data_length - sizeof(itti_signal_header_t) - sizeof(itti_message_types_t), 0) != RC_OK) - { - g_error("Failed to create new buffer"); - g_assert_not_reached (); - } - - sscanf (itti_signal_header->message_number_char, MESSAGE_NUMBER_CHAR_FORMAT, &buffer->message_number); - - ui_signal_add_to_list (buffer, ((read_messages % 1000) == 0) ? (gpointer) 1 : NULL); - - if ((read_messages % 100) == 0) - { - ui_progress_bar_set_fraction (read_fraction); - ui_gtk_flush_events (); - } - - read_messages++; - } - else - { - if (ui_notification_dialog (GTK_MESSAGE_WARNING, TRUE, "open messages", - "Failed to read a message from file \"%s\", end mark is missing", file_name) == RC_FAIL) - { - read_data = 0; - } - break; - } - - free (input_data); - break; - } - - case ITTI_STATISTIC_MESSAGE_TYPE: - default: - if (ui_notification_dialog (GTK_MESSAGE_WARNING, TRUE, "open messages", - "Unknown (or not implemented) record type: %d in file \"%s\"", - message_header.message_type, file_name) == RC_FAIL) - { - read_data = 0; - } - - free (input_data); - break; - } - } - } while ((ui_abort == FALSE) && (read_data > 0)); - - if (read_messages > 0) - { - char *basename; - - /* Enable buttons to move in the list of signals */ - ui_set_sensitive_move_buttons (TRUE); - - if (ui_main_data.follow_last) - { - /* Advance to the last signal */ - ui_tree_view_select_row (ui_tree_view_get_filtered_number () - 1); - } - - basename = g_path_get_basename (file_name); - ui_set_title ("\"%s\"", basename); - } - else - { - result = RC_FAIL; - } - - ui_progress_bar_terminate (); - - g_message("Read %d messages (%d to display) from file \"%s\"\n", read_messages, ui_tree_view_get_filtered_number(), file_name); - - close (source); - } - - ui_change_cursor (FALSE); - - return result; -} - -static void ui_message_write_callback(const gpointer buffer, const gchar *signal_name) -{ - buffer_t *signal_buffer = (buffer_t *) buffer; - itti_socket_header_t message_header; - itti_signal_header_t itti_signal_header; - uint32_t message_size; - - message_size = signal_buffer->size_bytes; - - message_header.message_size = sizeof(itti_socket_header_t) + sizeof(itti_signal_header) + message_size + sizeof(itti_message_types_t); - message_header.message_type = ITTI_DUMP_MESSAGE_TYPE; - - sprintf(itti_signal_header.message_number_char, MESSAGE_NUMBER_CHAR_FORMAT, message_number); - itti_signal_header.message_number_char[sizeof(itti_signal_header.message_number_char) - 1] = '\n'; - message_number++; - - fwrite (&message_header, sizeof(message_header), 1, messages_file); - fwrite (&itti_signal_header, sizeof(itti_signal_header), 1, messages_file); - fwrite (signal_buffer->data, message_size, 1, messages_file); - fwrite (&itti_dump_message_type_end, sizeof(itti_message_types_t), 1, messages_file); -} - -static int ui_messages_file_write(char *file_name, gboolean filtered) -{ - if (file_name == NULL) - { - g_warning("No name for log file"); - return RC_FAIL; - } - - messages_file = fopen (file_name, "w"); - if (messages_file == NULL) - { - ui_notification_dialog (GTK_MESSAGE_ERROR, FALSE, "Failed to open file \"%s\": %s", file_name, g_strerror (errno)); - return RC_FAIL; - } - - /* Write XML definitions */ - { - itti_socket_header_t message_header; - - message_header.message_size = sizeof(itti_socket_header_t) + xml_raw_data_size + sizeof(itti_message_types_t); - message_header.message_type = ITTI_DUMP_XML_DEFINITION; - - fwrite (&message_header, sizeof(message_header), 1, messages_file); - fwrite (xml_raw_data, xml_raw_data_size, 1, messages_file); - fwrite (&itti_dump_xml_definition_end, sizeof(itti_message_types_t), 1, messages_file); - } - - /* Write messages */ - { - message_number = 1; - ui_tree_view_foreach_message (ui_message_write_callback, filtered); - } - - fclose (messages_file); - - return RC_OK; -} - -int ui_messages_open_file_chooser(void) -{ - int result = RC_OK; - - GtkWidget *filechooser; - gboolean response_accept; - char *filename; - - filechooser = gtk_file_chooser_dialog_new ("Select file", GTK_WINDOW (ui_main_data.window), - GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, - GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); - gtk_filter_add (filechooser, "Log files", "*.log"); - gtk_filter_add (filechooser, "All files", "*"); - - /* Process the response */ - response_accept = gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT; - - if (response_accept) - { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser)); - } - gtk_widget_destroy (filechooser); - if (response_accept) - { - ui_set_sensitive_save_message_buttons (FALSE); - - result = ui_messages_read (filename); - if (result == RC_OK) - { - /* Update messages file name for future use */ - if (ui_main_data.messages_file_name != NULL) - { - g_free (ui_main_data.messages_file_name); - } - ui_main_data.messages_file_name = filename; - - ui_set_sensitive_save_message_buttons (TRUE); - } - else - { - g_free (filename); - } - } - return result; -} - -int ui_messages_save_file_chooser(gboolean filtered) -{ - int result = RC_OK; - GtkWidget *filechooser; - - /* Check if there is something to save */ - if (xml_raw_data_size > 0) - { - static const char *title[] = - { - "Save file (all messages)", - "Save file (filtered messages)", - }; - - filechooser = gtk_file_chooser_dialog_new (title[filtered], GTK_WINDOW (ui_main_data.window), - GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); - gtk_filter_add (filechooser, "Log files", "*.log"); - gtk_filter_add (filechooser, "All files", "*"); - - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (filechooser), TRUE); - - if (ui_main_data.messages_file_name != NULL) - { - gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filechooser), ui_main_data.messages_file_name); - } - else - { - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (filechooser), "messages.log"); - } - - /* Process the response */ - if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT) - { - char *filename; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser)); - result = ui_messages_file_write (filename, filtered); - if (result == RC_OK) - { - /* Update filters file name for future use */ - if (ui_main_data.messages_file_name != NULL) - { - g_free (ui_main_data.messages_file_name); - } - ui_main_data.messages_file_name = filename; - } - else - { - g_free (filename); - } - } - gtk_widget_destroy (filechooser); - } - - return result; -} - -int ui_filters_open_file_chooser(void) -{ - int result = RC_OK; - GtkWidget *filechooser; - gboolean response_accept; - char *filename; - - filechooser = gtk_file_chooser_dialog_new ("Select file", GTK_WINDOW (ui_main_data.window), - GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, - GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); - gtk_filter_add (filechooser, "Filters files", "*.xml"); - gtk_filter_add (filechooser, "All files", "*"); - - /* Process the response */ - response_accept = gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT; - - if (response_accept) - { - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser)); - } - gtk_widget_destroy (filechooser); - if (response_accept) - { - result = ui_filters_read (filename); - if (result == RC_OK) - { - /* Update filters file name for future use */ - if (ui_main_data.filters_file_name != NULL) - { - g_free (ui_main_data.filters_file_name); - } - ui_main_data.filters_file_name = filename; - } - else - { - g_free (filename); - } - } - - return result; -} - -int ui_filters_save_file_chooser(void) -{ - int result = RC_OK; - GtkWidget *filechooser; - - filechooser = gtk_file_chooser_dialog_new ("Save file", GTK_WINDOW (ui_main_data.window), - GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); - gtk_filter_add (filechooser, "Filters files", "*.xml"); - gtk_filter_add (filechooser, "All files", "*"); - - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (filechooser), TRUE); - - if (ui_main_data.filters_file_name != NULL) - { - gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filechooser), ui_main_data.filters_file_name); - } - else - { - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (filechooser), "filters.xml"); - } - - /* Process the response */ - if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT) - { - char *filename; - - filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser)); - result = ui_filters_file_write (filename); - if (result == RC_OK) - { - /* Update filters file name for future use */ - if (ui_main_data.filters_file_name != NULL) - { - g_free (ui_main_data.filters_file_name); - } - ui_main_data.filters_file_name = filename; - } - else - { - g_free (filename); - } - } - gtk_widget_destroy (filechooser); - - return result; -} - -void ui_progressbar_window_destroy (void) -{ - ui_abort = TRUE; - ui_progress_bar_terminate(); -} - -int ui_progress_bar_set_fraction(double fraction) -{ - if (ui_abort == FALSE) - { - /* If not exist instantiate */ - if (!ui_main_data.progressbar && !ui_main_data.progressbar_window) - { - ui_main_data.progressbar_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - /* Keep progress bar window on top of main window */ - gtk_window_set_transient_for (GTK_WINDOW(ui_main_data.progressbar_window), GTK_WINDOW(ui_main_data.window)); - - /* Set the window at center of main window */ - gtk_window_set_position (GTK_WINDOW(ui_main_data.progressbar_window), GTK_WIN_POS_CENTER_ON_PARENT); - gtk_window_set_title (GTK_WINDOW(ui_main_data.progressbar_window), "Processing"); - - gtk_container_set_border_width (GTK_CONTAINER (ui_main_data.progressbar_window), 10); - - ui_main_data.progressbar = gtk_progress_bar_new (); - - gtk_container_add (GTK_CONTAINER (ui_main_data.progressbar_window), ui_main_data.progressbar); - - /* Assign the destroy event */ - g_signal_connect(ui_main_data.progressbar_window, "destroy", ui_progressbar_window_destroy, NULL); - - gtk_widget_show_all (ui_main_data.progressbar_window); - - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.stop_loading), TRUE); - } - - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(ui_main_data.progressbar), fraction); - -// ui_gtk_flush_events(); - } - - return RC_OK; -} - -int ui_progress_bar_terminate(void) -{ - if (ui_main_data.progressbar) - { - gtk_widget_destroy (ui_main_data.progressbar); - ui_main_data.progressbar = NULL; - } - if (ui_main_data.progressbar_window) - { - gtk_widget_destroy (ui_main_data.progressbar_window); - ui_main_data.progressbar_window = NULL; - } - gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.stop_loading), FALSE); - - return RC_OK; -} diff --git a/common/utils/itti_analyzer/libui/ui_signal_dissect_view.c b/common/utils/itti_analyzer/libui/ui_signal_dissect_view.c deleted file mode 100644 index 859eb66b03..0000000000 --- a/common/utils/itti_analyzer/libui/ui_signal_dissect_view.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include - -#define G_LOG_DOMAIN ("UI") - -#include - -#include "rc.h" - -#include "ui_main_screen.h" -#include "ui_menu_bar.h" -#include "ui_signal_dissect_view.h" - -ui_text_view_t *ui_signal_dissect_new(GtkWidget *hbox) -{ - GtkWidget *scrolled_window; - ui_text_view_t *new_text_view; - - new_text_view = malloc(sizeof(ui_text_view_t)); - - new_text_view->text_view = gtk_text_view_new(); - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - - /* Change the font of the widget */ - new_text_view->text_view_font = pango_font_description_new(); - - g_debug("Default family is: %s\n", pango_font_description_get_family(new_text_view->text_view_font)); - - pango_font_description_set_family(new_text_view->text_view_font, "Monospace"); - pango_font_description_set_absolute_size(new_text_view->text_view_font, 10 * PANGO_SCALE); - - g_debug("Font family has been set to: %s\n", pango_font_description_get_family(new_text_view->text_view_font)); - - gtk_widget_override_font(new_text_view->text_view, new_text_view->text_view_font); - - /* Disable editable attribute */ - gtk_text_view_set_editable(GTK_TEXT_VIEW(new_text_view->text_view), FALSE); - - gtk_container_add(GTK_CONTAINER(scrolled_window), new_text_view->text_view); - - gtk_paned_pack2 (GTK_PANED (hbox), scrolled_window, TRUE, FALSE); - - return new_text_view; -} - -int ui_signal_dissect_clear_view(ui_text_view_t *text_view) -{ - GtkTextBuffer *text_buffer; - - g_assert(text_view != NULL); - - if (text_view->text_view != NULL) - { - /* Create an empty text buffer */ - text_buffer = gtk_text_buffer_new(NULL); - gtk_text_buffer_set_text(text_buffer, "", 0); - - gtk_text_view_set_buffer(GTK_TEXT_VIEW(text_view->text_view), text_buffer); - } - - return RC_OK; -} - -gboolean ui_signal_set_text(gpointer user_data, gchar *text, gint length) -{ - GtkTextBuffer *text_buffer; - ui_text_view_t *text_view; - - if (length < 0) - return FALSE; - - text_view = (ui_text_view_t *)user_data; - - g_assert(text != NULL); - g_assert(text_view != NULL); - g_assert(text_view->text_view != NULL); - - g_assert(GTK_IS_TEXT_VIEW(GTK_TEXT_VIEW(text_view->text_view))); - - text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view->text_view)); - - if (text_buffer) { - /* We already have a text buffer, use it */ - gtk_text_buffer_insert_at_cursor(text_buffer, text, length); - } else { - /* No buffer currently in use, create a new one */ - text_buffer = gtk_text_buffer_new(NULL); - gtk_text_buffer_set_text(text_buffer, text, length); - gtk_text_view_set_buffer(GTK_TEXT_VIEW(text_view->text_view), - text_buffer); - } - - return TRUE; -} diff --git a/common/utils/itti_analyzer/libui/ui_tree_view.c b/common/utils/itti_analyzer/libui/ui_tree_view.c deleted file mode 100644 index 0396e24819..0000000000 --- a/common/utils/itti_analyzer/libui/ui_tree_view.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include - -#define G_LOG_DOMAIN ("UI_TREE") - -#include - -#include "logs.h" -#include "rc.h" - -#include "buffers.h" - -#include "ui_main_screen.h" -#include "ui_tree_view.h" -#include "ui_callbacks.h" -#include "ui_filters.h" - -#include "ui_signal_dissect_view.h" - -typedef struct -{ - GtkListStore *store; - GtkTreeModelFilter *filtered; - uint32_t filtered_last_msg; - uint32_t filtered_msg_number; - uint32_t instance_number; -} ui_store_t; - -static ui_store_t ui_store; - -GtkWidget *ui_tree_view_menu; -ui_tree_view_menu_enable_t ui_tree_view_menu_enable[NUM_MENU_TYPE]; - -GdkEventButton *ui_tree_view_last_event; - -static gboolean ui_tree_filter_messages(GtkTreeModel *model, GtkTreeIter *iter, ui_store_t *store) -{ - uint32_t msg_number; - uint32_t message_id; - uint32_t origin_task_id; - uint32_t destination_task_id; - uint32_t instance; - - gboolean enabled = TRUE; - - if (ui_filters.filters_enabled) - { - gtk_tree_model_get (model, iter, COL_MSG_NUM, &msg_number, COL_MESSAGE_ID, &message_id, COL_FROM_TASK_ID, - &origin_task_id, COL_TO_TASK_ID, &destination_task_id, COL_INSTANCE_ID, &instance, -1); - if (msg_number != 0) - { - enabled = ui_filters_message_enabled (message_id, origin_task_id, destination_task_id, instance); - - if ((enabled) && (store->filtered_last_msg < msg_number)) - { - store->filtered_last_msg = msg_number; - store->filtered_msg_number++; - } - g_debug("ui_tree_filter_messages: %p %p %d m:%d o:%d d:%d i:%d %d %d", model, iter, msg_number, message_id, origin_task_id, destination_task_id, instance, enabled, store->filtered_msg_number); - } - } - - return enabled; -} - -static gboolean onButtonPressed(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) -{ - g_info("onButtonPressed %p %p %p %d %d", treeview, event, userdata, event->type, event->button); - ui_tree_view_last_event = event; - - return FALSE; -} - -/* - static gboolean onButtonRelease(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) - { - g_info("onButtonRelease %p %p %p %d %d", treeview, event, userdata, event->type, event->button); - // last_event = event; - - return FALSE; - } - */ - -static void ui_tree_view_init_list(GtkWidget *list) -{ - GtkCellRenderer *renderer_left; - GtkCellRenderer *renderer_right; - GtkTreeViewColumn *column; - - renderer_left = gtk_cell_renderer_text_new (); - gtk_cell_renderer_set_padding (renderer_left, 5, 0); - - renderer_right = gtk_cell_renderer_text_new (); - gtk_cell_renderer_set_alignment (renderer_right, 1, 0.5); - gtk_cell_renderer_set_padding (renderer_right, 5, 0); - - column = gtk_tree_view_column_new_with_attributes ("MN", renderer_right, "text", COL_MSG_NUM, "foreground", - COL_FOREGROUND, "background", COL_BACKGROUND, NULL); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_column_set_alignment (column, 0.5); - gtk_tree_view_append_column (GTK_TREE_VIEW(list), column); - - column = gtk_tree_view_column_new_with_attributes ("LTE Time", renderer_right, "text", COL_LTE_TIME, NULL); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_column_set_alignment (column, 0.5); - gtk_tree_view_append_column (GTK_TREE_VIEW(list), column); - - column = gtk_tree_view_column_new_with_attributes ("Message", renderer_left, "text", COL_MESSAGE, "foreground", - COL_FOREGROUND, "background", COL_BACKGROUND, "strikethrough", - COL_STRIKETHROUGH, "style", COL_STYLE, "weight", COL_WEIGHT, "underline", COL_UNDERLINE, NULL); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_column_set_alignment (column, 0.5); - gtk_tree_view_append_column (GTK_TREE_VIEW(list), column); - g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(ui_callback_on_tree_column_header_click), - (gpointer) COL_MESSAGE); - - column = gtk_tree_view_column_new_with_attributes ("From", renderer_left, "text", COL_FROM_TASK, NULL); - gtk_tree_view_column_set_alignment (column, 0.5); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_append_column (GTK_TREE_VIEW(list), column); - g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(ui_callback_on_tree_column_header_click), - (gpointer) COL_FROM_TASK); - - column = gtk_tree_view_column_new_with_attributes ("To", renderer_left, "text", COL_TO_TASK, NULL); - gtk_tree_view_column_set_alignment (column, 0.5); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_append_column (GTK_TREE_VIEW(list), column); - g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(ui_callback_on_tree_column_header_click), - (gpointer) COL_TO_TASK); - - column = gtk_tree_view_column_new_with_attributes ("Ins", renderer_right, "text", COL_INSTANCE, NULL); - gtk_tree_view_column_set_alignment (column, 0.5); - gtk_tree_view_append_column (GTK_TREE_VIEW(list), column); - g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(ui_callback_on_tree_column_header_click), - (gpointer) COL_INSTANCE); - - ui_store.store = gtk_list_store_new (NUM_COLS, // Number of columns - // Displayed columns - G_TYPE_UINT, // COL_MSG_NUM - G_TYPE_STRING, // COL_LTE_TIME - G_TYPE_STRING, // COL_MESSAGE - G_TYPE_STRING, // COL_FROM_TASK - G_TYPE_STRING, // COL_TO_TASK - G_TYPE_STRING, // COL_INSTANCE - // Not displayed columns - // Id of some message fields to speed-up filtering - G_TYPE_UINT, // COL_MESSAGE_ID - G_TYPE_UINT, // COL_FROM_TASK_ID - G_TYPE_UINT, // COL_TO_TASK_ID - G_TYPE_UINT, // COL_INSTANCE_ID - G_TYPE_STRING, // COL_FOREGROUND - G_TYPE_STRING, // COL_BACKGROUND - G_TYPE_BOOLEAN, // COL_STRIKETHROUGH - G_TYPE_UINT, - G_TYPE_UINT, - G_TYPE_UINT, - // Reference to the buffer here to avoid maintaining multiple lists. - G_TYPE_POINTER); - - if (ui_store.store == NULL) - { - g_error("gtk_list_store_new failed"); - } - - ui_store.filtered = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (ui_store.store), NULL)); - gtk_tree_model_filter_set_visible_func (ui_store.filtered, (GtkTreeModelFilterVisibleFunc) ui_tree_filter_messages, - &ui_store, NULL); - - gtk_tree_view_set_model (GTK_TREE_VIEW(list), GTK_TREE_MODEL(ui_store.filtered)); - - gtk_tree_view_columns_autosize (GTK_TREE_VIEW(list)); -} - -static void ui_tree_view_add_to_list(GtkWidget *list, const gchar *lte_time, const uint32_t message_number, - const uint32_t message_id, const gchar *signal_name, const uint32_t origin_task_id, - const char *origin_task_name, const uint32_t destination_task_id, - const char *destination_task_name, uint32_t instance_id, const char *instance_name, gpointer buffer) -{ - static int counter = 0; - - GtkTreeIter iter; - gboolean enabled; - int message_index; - - g_info("ui_tree_view_add_to_list: %d %d %d %d %d", message_number, message_id, origin_task_id, destination_task_id, instance_id); - - enabled = ui_filters_message_enabled (message_id, origin_task_id, destination_task_id, instance_id); - message_index = ui_filters_search_id (&ui_filters.messages, message_id); - - g_info("ui_tree_view_add_to_list: %d %d", enabled, message_index); - - gtk_list_store_append (ui_store.store, &iter); - gtk_list_store_set (ui_store.store, &iter, - /* Columns */ - COL_MSG_NUM, - message_number, COL_LTE_TIME, lte_time, COL_MESSAGE, signal_name, COL_FROM_TASK, origin_task_name, - COL_TO_TASK, destination_task_name, COL_INSTANCE, instance_name, COL_MESSAGE_ID, message_id, - COL_FROM_TASK_ID, origin_task_id, COL_TO_TASK_ID, destination_task_id, COL_INSTANCE_ID, instance_id, - COL_BUFFER, buffer, COL_FOREGROUND, ui_filters.messages.items[message_index].foreground, COL_BACKGROUND, - ui_filters.messages.items[message_index].background, COL_STRIKETHROUGH, !enabled, -// COL_STYLE, (counter % 2) == 0 ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL, -// COL_WEIGHT, ((counter + 2) % 4) < 2 ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -// COL_UNDERLINE, ((counter + 4) % 8) < 4 ?PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE, - COL_STYLE, PANGO_STYLE_NORMAL, - COL_WEIGHT, PANGO_WEIGHT_NORMAL, - COL_UNDERLINE, PANGO_UNDERLINE_NONE, - /* End of columns */ - -1); - counter++; -} - -void ui_tree_view_destroy_list(GtkWidget *list) -{ - g_assert(list != NULL); - - gtk_list_store_clear (ui_store.store); - ui_store.filtered_last_msg = 0; - ui_store.filtered_msg_number = 0; - ui_store.instance_number = 0; - - /* Reset number of messages */ - ui_main_data.nb_message_received = 0; -} - -/* Search for the message with its message number equal to the given value or the previous one */ -static gboolean ui_tree_view_search(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, - gpointer search_data) -{ - uint32_t msg_number; - uint32_t key_value = atoi (key); - - gtk_tree_model_get (model, iter, column, &msg_number, -1); - - g_debug("ui_tree_view_search %d %d", key_value, msg_number); - - if (key_value == msg_number) - { - /* Value found, use this message */ - return 0; - } - - { - GtkTreeIter iter_next = *iter; - - if (gtk_tree_model_iter_next (model, &iter_next)) - { - gtk_tree_model_get (model, &iter_next, column, &msg_number, -1); - - if (key_value < msg_number) - { - /* Next value will be greater, use this message */ - return 0; - } - } - else - { - /* Last value, use this message */ - return 0; - } - } - return 1; -} - -static void ui_tree_view_create_menu(GtkWidget **menu) -{ - GtkWidget *menu_items; - - *menu = gtk_menu_new (); - - /* Create the "Message enable" menu-item */ - { - /* Create a new menu-item */ - menu_items = gtk_check_menu_item_new (); - ui_tree_view_menu_enable[MENU_MESSAGE].menu_enable = menu_items; - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_enable), - &ui_tree_view_menu_enable[MENU_MESSAGE]); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* Create the "Destination task enable" menu-item */ - { - /* Create a new menu-item */ - menu_items = gtk_check_menu_item_new (); - ui_tree_view_menu_enable[MENU_FROM_TASK].menu_enable = menu_items; - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_enable), - &ui_tree_view_menu_enable[MENU_FROM_TASK]); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* Create the "Origin task enable" menu-item */ - { - /* Create a new menu-item */ - menu_items = gtk_check_menu_item_new (); - ui_tree_view_menu_enable[MENU_TO_TASK].menu_enable = menu_items; - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_enable), - &ui_tree_view_menu_enable[MENU_TO_TASK]); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* Create the "Instance enable" menu-item */ - { - /* Create a new menu-item */ - menu_items = gtk_check_menu_item_new (); - ui_tree_view_menu_enable[MENU_INSTANCE].menu_enable = menu_items; - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_enable), - &ui_tree_view_menu_enable[MENU_INSTANCE]); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* Create the "Foreground color" menu-item */ - { - static ui_tree_view_menu_color_t menu_color_foreground = - {TRUE, &ui_tree_view_menu_enable[MENU_MESSAGE]}; - - /* Create a new menu-item with a name */ - menu_items = gtk_menu_item_new_with_label ("Select message foreground color"); - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_color), - &menu_color_foreground); - - /* Show the widget */ - gtk_widget_show (menu_items); - } - - /* Create the "Background color" menu-item */ - { - static ui_tree_view_menu_color_t menu_color_background = - {FALSE, &ui_tree_view_menu_enable[MENU_MESSAGE]}; - - /* Create a new menu-item with a name */ - menu_items = gtk_menu_item_new_with_label ("Select message background color"); - - /* Add it to the menu. */ - gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items); - g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_color), - &menu_color_background); - - /* Show the widget */ - gtk_widget_show (menu_items); - } -} - -int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox) -{ - GtkWidget *hbox; - GtkTreeSelection *selection; - GtkWidget *scrolled_window; - - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - - ui_main_data.messages_list = gtk_tree_view_new (); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(ui_main_data.messages_list), TRUE); - gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW(ui_main_data.messages_list), ui_tree_view_search, NULL, NULL); - gtk_tree_view_set_search_entry (GTK_TREE_VIEW(ui_main_data.messages_list), - GTK_ENTRY(ui_main_data.signals_go_to_entry)); - - /* Disable multiple selection */ - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(ui_main_data.messages_list)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); - - hbox = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL); - - gtk_container_add (GTK_CONTAINER(scrolled_window), ui_main_data.messages_list); - - ui_tree_view_init_list (ui_main_data.messages_list); - gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(ui_main_data.messages_list), TRUE); - - gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW(scrolled_window), 680); - gtk_paned_pack1 (GTK_PANED (hbox), scrolled_window, FALSE, TRUE); - ui_main_data.text_view = ui_signal_dissect_new (hbox); - - gtk_box_pack_start (GTK_BOX(vbox), hbox, TRUE, TRUE, 5); - - g_signal_connect(G_OBJECT(ui_main_data.messages_list), "button-press-event", G_CALLBACK (onButtonPressed), NULL); - // g_signal_connect(G_OBJECT(ui_main_data.signalslist), "button-release-event", G_CALLBACK (onButtonRelease), NULL); - - /* Connect callback on row selection */ - gtk_tree_selection_set_select_function (selection, ui_callback_on_select_signal, ui_main_data.text_view, NULL); - - ui_store.filtered_last_msg = 0; - ui_store.filtered_msg_number = 0; - ui_store.instance_number = 0; - - ui_main_data.selection = selection; - - ui_tree_view_create_menu (&ui_tree_view_menu); - - return 0; -} - -int ui_tree_view_new_signal_ind(const uint32_t message_number, const gchar *lte_time, const uint32_t message_id, - const char *message_name, const uint32_t origin_task_id, const char *origin_task_name, - const uint32_t destination_task_id, const char *destination_task_name, uint32_t instance_id, - gpointer buffer) -{ - char *instance_name = NULL; - char instance_name_buffer[10]; - - if (((instance_t) instance_id) < INSTANCE_DEFAULT) - { - if (ui_store.instance_number < (instance_id + 1)) - { - int i; - - for (i = ui_store.instance_number; i <= instance_id; i++) - { - sprintf (instance_name_buffer, "%d", i); - ui_filters_add (FILTER_INSTANCES, i, instance_name_buffer, ENTRY_ENABLED_TRUE, NULL, NULL); - } - ui_store.instance_number = (instance_id + 1); - ui_destroy_filter_menu (FILTER_INSTANCES); - } - - sprintf (instance_name_buffer, "%d", instance_id); - instance_name = instance_name_buffer; - } - else - { - switch ((instance_t) instance_id) - { - case INSTANCE_DEFAULT: - instance_name = "DEF"; - break; - - case INSTANCE_ALL: - instance_name = "ALL"; - break; - - default: - break; - } - - if ((instance_name != NULL) && (ui_filters_search_id (&ui_filters.instances, instance_id) < 0)) - { - ui_filters_add (FILTER_INSTANCES, instance_id, instance_name, ENTRY_ENABLED_TRUE, NULL, NULL); - } - } - - ui_tree_view_add_to_list (ui_main_data.messages_list, lte_time, message_number, message_id, message_name, - origin_task_id, origin_task_name, destination_task_id, destination_task_name, instance_id, instance_name, - buffer); - - return RC_OK; -} - -void ui_tree_view_select_row(gint row) -{ - GtkTreePath *path_row; - - if (row >= 0) - { - path_row = gtk_tree_path_new_from_indices (row, -1); - - if ((ui_main_data.messages_list != NULL) && (path_row != NULL)) - { - g_info("Select row %d", row); - - /* Select the message in requested row */ - gtk_tree_view_set_cursor (GTK_TREE_VIEW(ui_main_data.messages_list), path_row, NULL, FALSE); - /* Center the message in the middle of the list if possible */ - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(ui_main_data.messages_list), path_row, NULL, TRUE, 0.5, 0.0); - } - } -} - -static gboolean updateColors(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) -{ - uint32_t message_id; - uint32_t origin_task_id; - uint32_t destination_task_id; - uint32_t instance; - - gboolean enabled = FALSE; - int message_index; - - gtk_tree_model_get (model, iter, COL_MESSAGE_ID, &message_id, COL_FROM_TASK_ID, &origin_task_id, COL_TO_TASK_ID, - &destination_task_id, COL_INSTANCE_ID, &instance, -1); - enabled = ui_filters_message_enabled (message_id, origin_task_id, destination_task_id, instance); - message_index = ui_filters_search_id (&ui_filters.messages, message_id); - - gtk_list_store_set (GTK_LIST_STORE(model), iter, COL_FOREGROUND, - ui_filters.messages.items[message_index].foreground, COL_BACKGROUND, - ui_filters.messages.items[message_index].background, COL_STRIKETHROUGH, !enabled, -1); - - return FALSE; -} - -void ui_tree_view_refilter() -{ - ui_store.filtered_last_msg = 0; - ui_store.filtered_msg_number = 0; - - /* Update foreground color of messages, this will also update filtered model */ - if (ui_store.store != NULL) - { - gtk_tree_model_foreach (GTK_TREE_MODEL(ui_store.store), updateColors, NULL); - - if (ui_main_data.messages_list != NULL) - { - GtkTreePath *path_row; - - /* Get the currently selected message */ - gtk_tree_view_get_cursor (GTK_TREE_VIEW(ui_main_data.messages_list), &path_row, NULL); - if (path_row != NULL) - { - /* Center the message in the middle of the list if possible */ - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(ui_main_data.messages_list), path_row, NULL, TRUE, 0.5, - 0.0); - g_info("ui_tree_view_refilter: center on message"); - } - } - } - - g_info("ui_tree_view_refilter: last message %d, %d messages displayed", ui_store.filtered_last_msg, ui_store.filtered_msg_number); -} - -typedef struct foreach_message_params_s -{ - message_write_callback_t callback; - gboolean filter; -} foreach_message_params_t; - -static gboolean foreach_message(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) -{ - foreach_message_params_t *params = (foreach_message_params_t *) data; - const gchar *signal_name; - uint32_t message_id; - uint32_t origin_task_id; - uint32_t destination_task_id; - uint32_t instance; - gpointer buffer = NULL; - - gtk_tree_model_get (model, iter, COL_MESSAGE, &signal_name, COL_MESSAGE_ID, &message_id, COL_FROM_TASK_ID, &origin_task_id, COL_TO_TASK_ID, - &destination_task_id, COL_INSTANCE_ID, &instance, COL_BUFFER, &buffer, -1); - - if (params->filter == TRUE) - { - gboolean enabled = FALSE; - - enabled = ui_filters_message_enabled (message_id, origin_task_id, destination_task_id, instance); - if (enabled == FALSE) - { - buffer = NULL; - } - } - - if (buffer != NULL) - { - params->callback(buffer, signal_name); - } - - return FALSE; -} - -void ui_tree_view_foreach_message(message_write_callback_t callback, gboolean filter) -{ - foreach_message_params_t params = {callback, filter}; - - gtk_tree_model_foreach (GTK_TREE_MODEL(ui_store.store), foreach_message, (void *) ¶ms); -} - -guint ui_tree_view_get_filtered_number(void) -{ - return ui_store.filtered_msg_number; -} diff --git a/common/utils/itti_analyzer/libui/ui_tree_view.h b/common/utils/itti_analyzer/libui/ui_tree_view.h deleted file mode 100644 index 88ab2fce71..0000000000 --- a/common/utils/itti_analyzer/libui/ui_tree_view.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#ifndef UI_TREE_VIEW_H_ -#define UI_TREE_VIEW_H_ - -#include "ui_filters.h" -#include "ui_notifications.h" - -typedef enum col_type_e -{ - COL_MSG_NUM = 0, - COL_LTE_TIME, - COL_MESSAGE, - COL_FROM_TASK, - COL_TO_TASK, - COL_INSTANCE, - - COL_MESSAGE_ID, - COL_FROM_TASK_ID, - COL_TO_TASK_ID, - COL_INSTANCE_ID, - COL_FOREGROUND, - COL_BACKGROUND, - COL_STRIKETHROUGH, - COL_STYLE, - COL_WEIGHT, - COL_UNDERLINE, - - COL_BUFFER, - NUM_COLS -} col_type_t; - -typedef enum ui_tree_view_menu_type_e -{ - MENU_MESSAGE = 0, - MENU_FROM_TASK, - MENU_TO_TASK, - MENU_INSTANCE, - NUM_MENU_TYPE, -} ui_tree_view_menu_type_t; - -typedef struct ui_tree_view_menu_enable_s -{ - GtkWidget *menu_enable; - ui_filter_item_t *filter_item; -} ui_tree_view_menu_enable_t; - -typedef struct ui_tree_view_menu_color_s -{ - gboolean foreground; - ui_tree_view_menu_enable_t *menu_enable; -} ui_tree_view_menu_color_t; - -extern GtkWidget *ui_tree_view_menu; -extern ui_tree_view_menu_enable_t ui_tree_view_menu_enable[NUM_MENU_TYPE]; - -extern GdkEventButton *ui_tree_view_last_event; - -int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox); - -int ui_tree_view_new_signal_ind(const uint32_t message_number, const gchar *lte_time, - const uint32_t message_id, const char *message_name, - const uint32_t origin_task_id, const char *origin_task, - const uint32_t destination_task_id, const char *to_task, - uint32_t instance, gpointer buffer); - -void ui_tree_view_destroy_list(GtkWidget *list); - -void ui_tree_view_select_row(gint row); - -void ui_tree_view_refilter(void); - -void ui_tree_view_foreach_message(message_write_callback_t callback, gboolean filter); - -guint ui_tree_view_get_filtered_number(void); - -#endif /* UI_TREE_VIEW_H_ */ diff --git a/common/utils/load_module_shlib.c b/common/utils/load_module_shlib.c index a4b4742c94..2b0d339358 100644 --- a/common/utils/load_module_shlib.c +++ b/common/utils/load_module_shlib.c @@ -63,7 +63,7 @@ void loader_init(void) { } /* build the full shared lib name from the module name */ -char *loader_format_shlibpath(char *modname) +char *loader_format_shlibpath(char *modname, char *version) { char *tmpstr; @@ -97,7 +97,10 @@ int ret; shlibpath = loader_data.shlibpath ; } /* no specific shared lib version */ - if (shlibversion == NULL) { + if (version != NULL) { // version specified as a function parameter + shlibversion=version; + } + if (shlibversion == NULL) { // no specific version specified, neither as a config param or as a function param shlibversion = "" ; } /* alloc memory for full module shared lib file name */ @@ -118,7 +121,7 @@ int ret; return tmpstr; } -int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf, void *autoinit_arg) +int load_module_version_shlib(char *modname, char *version, loader_shlibfunc_t *farray, int numf, void *autoinit_arg) { void *lib_handle = NULL; initfunc_t fpi; @@ -138,7 +141,7 @@ int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf, void * loader_init(); } - shlib_path = loader_format_shlibpath(modname); + shlib_path = loader_format_shlibpath(modname, version); for (int i = 0; i < loader_data.numshlibs; i++) { if (strcmp(loader_data.shlibs[i].name, modname) == 0) { diff --git a/common/utils/load_module_shlib.h b/common/utils/load_module_shlib.h index 685b3d1b65..0e80a5353c 100644 --- a/common/utils/load_module_shlib.h +++ b/common/utils/load_module_shlib.h @@ -84,10 +84,11 @@ loader_data_t loader_data; /*-------------------------------------------------------------------------------------------------------------*/ #else /* LOAD_MODULE_SHLIB_MAIN */ -extern int load_module_shlib(char *modname, loader_shlibfunc_t *farray, int numf, void *initfunc_arg); + +extern int load_module_version_shlib(char *modname, char *version, loader_shlibfunc_t *farray, int numf, void *initfunc_arg); extern void * get_shlibmodule_fptr(char *modname, char *fname); extern loader_data_t loader_data; #endif /* LOAD_MODULE_SHLIB_MAIN */ - +#define load_module_shlib(M, F, N, I) load_module_version_shlib(M, NULL, F, N, I) #endif diff --git a/common/utils/lte/prach_utils.c b/common/utils/lte/prach_utils.c new file mode 100644 index 0000000000..9ef29e55a5 --- /dev/null +++ b/common/utils/lte/prach_utils.c @@ -0,0 +1,425 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file common/utils/lte/prach_utils.c + * \brief utils for PRACH common to both PHY and MAC + * \author R. Knopp + * \date 2020 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr + * \note + * \warning + */ + +#include + + +#include "PHY/LTE_TRANSPORT/transport_common.h" + +// This is table 5.7.1-4 from 36.211 +PRACH_TDD_PREAMBLE_MAP tdd_preamble_map[64][7] = { + // TDD Configuration Index 0 + { {1,{{0,1,0,2}}},{1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {1,{{0,1,0,2}}}, {1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {1,{{0,1,0,2}}}}, + // TDD Configuration Index 1 + { {1,{{0,2,0,2}}},{1,{{0,2,0,1}}}, {1,{{0,2,0,0}}}, {1,{{0,2,0,2}}}, {1,{{0,2,0,1}}}, {1,{{0,2,0,0}}}, {1,{{0,2,0,2}}}}, + // TDD Configuration Index 2 + { {1,{{0,1,1,2}}},{1,{{0,1,1,1}}}, {1,{{0,1,1,0}}}, {1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,1,1}}}}, + // TDD Configuration Index 3 + { {1,{{0,0,0,2}}},{1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {1,{{0,0,0,2}}}, {1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {1,{{0,0,0,2}}}}, + // TDD Configuration Index 4 + { {1,{{0,0,1,2}}},{1,{{0,0,1,1}}}, {1,{{0,0,1,0}}}, {1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,1,1}}}}, + // TDD Configuration Index 5 + { {1,{{0,0,0,1}}},{1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}}, + // TDD Configuration Index 6 + { {2,{{0,0,0,2},{0,0,1,2}}}, {2,{{0,0,0,1},{0,0,1,1}}}, {2,{{0,0,0,0},{0,0,1,0}}}, {2,{{0,0,0,1},{0,0,0,2}}}, {2,{{0,0,0,0},{0,0,0,1}}}, {2,{{0,0,0,0},{1,0,0,0}}}, {2,{{0,0,0,2},{0,0,1,1}}}}, + // TDD Configuration Index 7 + { {2,{{0,0,0,1},{0,0,1,1}}}, {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{0,0,0,2}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{0,0,1,0}}}}, + // TDD Configuration Index 8 + { {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{0,0,0,1}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{0,0,1,1}}}}, + // TDD Configuration Index 9 + { {3,{{0,0,0,1},{0,0,0,2},{0,0,1,2}}}, {3,{{0,0,0,0},{0,0,0,1},{0,0,1,1}}}, {3,{{0,0,0,0},{0,0,1,0},{1,0,0,0}}}, {3,{{0,0,0,0},{0,0,0,1},{0,0,0,2}}}, {3,{{0,0,0,0},{0,0,0,1},{1,0,0,1}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}, {3,{{0,0,0,1},{0,0,0,2},{0,0,1,1}}}}, + // TDD Configuration Index 10 + { {3,{{0,0,0,0},{0,0,1,0},{0,0,1,1}}}, {3,{{0,0,0,1},{0,0,1,0},{0,0,1,1}}}, {3,{{0,0,0,0},{0,0,1,0},{1,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{0,0,0,1},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{0,0,0,2},{0,0,1,0}}}}, + // TDD Configuration Index 11 + { {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{0,0,0,1},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{0,0,1,0},{0,0,1,1}}}}, + // TDD Configuration Index 12 + { {4,{{0,0,0,1},{0,0,0,2},{0,0,1,1},{0,0,1,2}}}, {4,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1}}}, + {4,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0}}}, + {4,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,2}}}, + {4,{{0,0,0,0},{0,0,0,1},{1,0,0,0},{1,0,0,1}}}, + {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}}, + {4,{{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1}}} + }, + // TDD Configuration Index 13 + { {4,{{0,0,0,0},{0,0,0,2},{0,0,1,0},{0,0,1,2}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,1}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,1}}} + }, + // TDD Configuration Index 14 + { {4,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,0},{0,0,0,2},{0,0,1,0},{0,0,1,1}}} + }, + // TDD Configuration Index 15 + { {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,1},{0,0,1,2}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,0,1}}}, + {5,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,1},{1,0,0,2}}}, + {5,{{0,0,0,0},{0,0,0,1},{1,0,0,0},{1,0,0,1},{2,0,0,1}}}, {5,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0}}}, + {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1}}} + }, + // TDD Configuration Index 16 + { {5,{{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1},{0,0,1,2}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,1,1}}}, + {5,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,1,0}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,0},{1,0,0,2}}}, + {5,{{0,0,0,0},{0,0,0,1},{1,0,0,0},{1,0,0,1},{2,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}} + }, + // TDD Configuration Index 17 + { {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,2}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,0},{1,0,0,1}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}} + }, + // TDD Configuration Index 18 + { {6,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1},{0,0,1,2}}}, + {6,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,0,1},{1,0,1,1}}}, + {6,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0},{2,0,1,0}}}, + {6,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,0},{1,0,0,1},{1,0,0,2}}}, + {6,{{0,0,0,0},{0,0,0,1},{1,0,0,0},{1,0,0,1},{2,0,0,0},{2,0,0,1}}}, + {6,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0},{5,0,0,0}}}, + {6,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1},{1,0,0,2}}} + }, + // TDD Configuration Index 19 + { {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {6,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,0,0},{1,0,1,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {6,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1},{1,0,1,1}}} + }, + // TDD Configuration Index 20 + { {1,{{0,1,0,1}}},{1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,1}}}}, + // TDD Configuration Index 21 + { {1,{{0,2,0,1}}},{1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,1}}}, {1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,1}}}}, + + // TDD Configuration Index 22 + { {1,{{0,1,1,1}}},{1,{{0,1,1,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,1,0}}}}, + + // TDD Configuration Index 23 + { {1,{{0,0,0,1}}},{1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}}, + + // TDD Configuration Index 24 + { {1,{{0,0,1,1}}},{1,{{0,0,1,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,1,0}}}}, + + // TDD Configuration Index 25 + { {2,{{0,0,0,1},{0,0,1,1}}}, {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{1,0,0,1}}}, {2,{{0,0,0,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{0,0,1,0}}}}, + + // TDD Configuration Index 26 + { {3,{{0,0,0,1},{0,0,1,1},{1,0,0,1}}}, {3,{{0,0,0,0},{0,0,1,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{1,0,0,1},{2,0,0,1}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{0,0,1,0},{1,0,0,1}}}}, + + // TDD Configuration Index 27 + { {4,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1}}}, {4,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1}}}, + {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0}}} + }, + + // TDD Configuration Index 28 + { {5,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1},{2,0,0,1}}}, {5,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {5,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1},{4,0,0,1}}}, + {5,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {5,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0},{2,0,0,1}}} + }, + + // TDD Configuration Index 29 + { {6,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1},{2,0,0,1},{2,0,1,1}}}, + {6,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0},{2,0,1,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {6,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1},{4,0,0,1},{5,0,0,1}}}, + {6,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0},{5,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {6,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0},{2,0,0,1},{2,0,1,0}}} + }, + + + // TDD Configuration Index 30 + { {1,{{0,1,0,1}}},{1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,1}}}}, + + // TDD Configuration Index 31 + { {1,{{0,2,0,1}}},{1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,1}}}, {1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,1}}}}, + + // TDD Configuration Index 32 + { {1,{{0,1,1,1}}},{1,{{0,1,1,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,1,0}}}}, + + // TDD Configuration Index 33 + { {1,{{0,0,0,1}}},{1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}}, + + // TDD Configuration Index 34 + { {1,{{0,0,1,1}}},{1,{{0,0,1,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,1,0}}}}, + + // TDD Configuration Index 35 + { {2,{{0,0,0,1},{0,0,1,1}}}, {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{1,0,0,1}}}, {2,{{0,0,0,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{0,0,1,0}}}}, + + // TDD Configuration Index 36 + { {3,{{0,0,0,1},{0,0,1,1},{1,0,0,1}}}, {3,{{0,0,0,0},{0,0,1,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{1,0,0,1},{2,0,0,1}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{0,0,1,0},{1,0,0,1}}}}, + + // TDD Configuration Index 37 + { {4,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1}}}, {4,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1}}}, + {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0}}} + }, + + // TDD Configuration Index 38 + { {5,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1},{2,0,0,1}}}, {5,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {5,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1},{4,0,0,1}}}, + {5,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {5,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0},{2,0,0,1}}} + }, + + // TDD Configuration Index 39 + { {6,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1},{2,0,0,1},{2,0,1,1}}}, + {6,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0},{2,0,1,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {6,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1},{4,0,0,1},{5,0,0,1}}}, + {6,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0},{5,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {6,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0},{2,0,0,1},{2,0,1,0}}} + }, + + // TDD Configuration Index 40 + { {1,{{0,1,0,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,0}}}}, + // TDD Configuration Index 41 + { {1,{{0,2,0,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,0}}}}, + + // TDD Configuration Index 42 + { {1,{{0,1,1,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}}, + + // TDD Configuration Index 43 + { {1,{{0,0,0,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,0}}}}, + + // TDD Configuration Index 44 + { {1,{{0,0,1,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}}, + + // TDD Configuration Index 45 + { {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{1,0,0,0}}}}, + + // TDD Configuration Index 46 + { {3,{{0,0,0,0},{0,0,1,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}}, + + // TDD Configuration Index 47 + { {4,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, + {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}} + } +}; + + +uint8_t get_prach_fmt(int prach_ConfigIndex,int frame_type) { + if (frame_type == FDD) // FDD + return(prach_ConfigIndex>>4); + else { + if (prach_ConfigIndex < 20) + return (0); + + if (prach_ConfigIndex < 30) + return (1); + + if (prach_ConfigIndex < 40) + return (2); + + if (prach_ConfigIndex < 48) + return (3); + else + return (4); + } +} + +uint8_t get_prach_prb_offset(int frame_type, + int tdd_config, + int N_RB_UL, + uint8_t prach_ConfigIndex, + uint8_t n_ra_prboffset, + uint8_t tdd_mapindex, uint16_t Nf) { + uint8_t n_ra_prb; + uint8_t f_ra,t1_ra; + uint8_t prach_fmt = get_prach_fmt(prach_ConfigIndex,frame_type); + uint8_t Nsp=2; + + if (frame_type == TDD) { // TDD + if (tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach==0) { + LOG_E(PHY, "Illegal prach_ConfigIndex %"PRIu8"", prach_ConfigIndex); + return(-1); + } + + // adjust n_ra_prboffset for frequency multiplexing (p.36 36.211) + f_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[tdd_mapindex].f_ra; + + if (prach_fmt < 4) { + if ((f_ra&1) == 0) { + n_ra_prb = n_ra_prboffset + 6*(f_ra>>1); + } else { + n_ra_prb = N_RB_UL - 6 - n_ra_prboffset + 6*(f_ra>>1); + } + } else { + if ((tdd_config >2) && (tdd_config<6)) + Nsp = 2; + + t1_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t1_ra; + + if ((((Nf&1)*(2-Nsp)+t1_ra)&1) == 0) { + n_ra_prb = 6*f_ra; + } else { + n_ra_prb = N_RB_UL - 6*(f_ra+1); + } + } + } else { //FDD + n_ra_prb = n_ra_prboffset; + } + + return(n_ra_prb); +} + +int is_prach_subframe0(int tdd_config,int frame_type,uint8_t prach_ConfigIndex,uint32_t frame, uint8_t subframe) { + uint8_t t0_ra; + uint8_t t1_ra; + uint8_t t2_ra; + int prach_mask = 0; + + if (frame_type == FDD) { //FDD + //implement Table 5.7.1-2 from 36.211 (Rel-10, p.41) + if ((((frame&1) == 1) && (subframe < 9)) || + (((frame&1) == 0) && (subframe == 9))) // This is an odd frame, ignore even-only PRACH frames + if (((prach_ConfigIndex&0xf)<3) || // 0,1,2,16,17,18,32,33,34,48,49,50 + ((prach_ConfigIndex&0x1f)==18) || // 18,50 + ((prach_ConfigIndex&0xf)==15)) // 15,47 + return(0); + + switch (prach_ConfigIndex&0x1f) { + case 0: + case 3: + if (subframe==1) prach_mask = 1; + + break; + + case 1: + case 4: + if (subframe==4) prach_mask = 1; + + break; + + case 2: + case 5: + if (subframe==7) prach_mask = 1; + + break; + + case 6: + if ((subframe==1) || (subframe==6)) prach_mask=1; + + break; + + case 7: + if ((subframe==2) || (subframe==7)) prach_mask=1; + + break; + + case 8: + if ((subframe==3) || (subframe==8)) prach_mask=1; + + break; + + case 9: + if ((subframe==1) || (subframe==4) || (subframe==7)) prach_mask=1; + + break; + + case 10: + if ((subframe==2) || (subframe==5) || (subframe==8)) prach_mask=1; + + break; + + case 11: + if ((subframe==3) || (subframe==6) || (subframe==9)) prach_mask=1; + + break; + + case 12: + if ((subframe&1)==0) prach_mask=1; + + break; + + case 13: + if ((subframe&1)==1) prach_mask=1; + + break; + + case 14: + prach_mask=1; + break; + + case 15: + if (subframe==9) prach_mask=1; + + break; + } + } else { // TDD + AssertFatal(prach_ConfigIndex<64, + "Illegal prach_ConfigIndex %d for ",prach_ConfigIndex); + AssertFatal(tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach>0, + "Illegal prach_ConfigIndex %d for ",prach_ConfigIndex); + t0_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t0_ra; + t1_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t1_ra; + t2_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t2_ra; +#ifdef PRACH_DEBUG + LOG_I(PHY,"[PRACH] Checking for PRACH format (ConfigIndex %d) in TDD subframe %d (%d,%d,%d)\n", + prach_ConfigIndex, + subframe, + t0_ra,t1_ra,t2_ra); +#endif + + if ((((t0_ra == 1) && ((frame &1)==0))|| // frame is even and PRACH is in even frames + ((t0_ra == 2) && ((frame &1)==1))|| // frame is odd and PRACH is in odd frames + (t0_ra == 0)) && // PRACH is in all frames + (((subframe<5)&&(t1_ra==0)) || // PRACH is in 1st half-frame + (((subframe>4)&&(t1_ra==1))))) { // PRACH is in 2nd half-frame + if ((prach_ConfigIndex<48) && // PRACH only in normal UL subframe + (((subframe%5)-2)==t2_ra)) prach_mask=1; + else if ((prach_ConfigIndex>47) && (((subframe%5)-1)==t2_ra)) prach_mask=1; // PRACH can be in UpPTS + } + } + + return(prach_mask); +} + diff --git a/common/utils/lte/prach_utils.h b/common/utils/lte/prach_utils.h new file mode 100644 index 0000000000..995805fbd2 --- /dev/null +++ b/common/utils/lte/prach_utils.h @@ -0,0 +1,40 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file common/utils/prach_utils.h +* \brief computation of some PRACH variables used in both MAC and PHY +* \author R. Knopp +* \date 2020 +* \version 0.1 +* \company Eurecom +* \email: raymond.knopp@eurecom.fr, florian.kaltenberger@eurecom.fr, oscar.tonelli@yahoo.it +* \note +* \warning +*/ +uint8_t get_prach_fmt(int prach_ConfigIndex,int frame_type); + +uint8_t get_prach_prb_offset(int frame_type, + int tdd_config, + int N_RB_UL, + uint8_t prach_ConfigIndex, + uint8_t n_ra_prboffset, + uint8_t tdd_mapindex, uint16_t Nf); +int is_prach_subframe0(int tdd_config,int frame_type,uint8_t prach_ConfigIndex,uint32_t frame, uint8_t subframe); diff --git a/common/utils/lte/ue_power.c b/common/utils/lte/ue_power.c new file mode 100644 index 0000000000..b377abf2ff --- /dev/null +++ b/common/utils/lte/ue_power.c @@ -0,0 +1,108 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ue_power.c +* \brief Routines to compute UE TX power according to 36.213 +* \author R. Knopp, F. Kaltenberger +* \date 2020 +* \version 0.1 +* \company Eurecom +* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr +* \note +* \warning +*/ + +#include +#include +#include "PHY/defs_eNB.h" +#include "PHY/TOOLS/dB_routines.h" + +extern int16_t hundred_times_delta_TF[100]; +extern uint16_t hundred_times_log10_NPRB[100]; + +int16_t estimate_ue_tx_power(int norm,uint32_t tbs, uint32_t nb_rb, uint8_t control_only, int ncp, uint8_t use_srs) +{ + + /// The payload + CRC size in bits, "B" + uint32_t B; + /// Number of code segments + uint32_t C; + /// Number of "small" code segments + uint32_t Cminus; + /// Number of "large" code segments + uint32_t Cplus; + /// Number of bits in "small" code segments (<6144) + uint32_t Kminus; + /// Number of bits in "large" code segments (<6144) + uint32_t Kplus; + /// Total number of bits across all segments + uint32_t sumKr; + /// Number of "Filler" bits + uint32_t F; + // num resource elements + uint32_t num_re=0.0; + // num symbols + uint32_t num_symb=0.0; + /// effective spectral efficiency of the PUSCH + uint32_t MPR_x100=0; + /// beta_offset + uint16_t beta_offset_pusch_x8=8; + /// delta mcs + float delta_mcs=0.0; + /// bandwidth factor + float bw_factor=0.0; + + B= tbs+24; + lte_segmentation(NULL, + NULL, + B, + &C, + &Cplus, + &Cminus, + &Kplus, + &Kminus, + &F); + + + sumKr = Cminus*Kminus + Cplus*Kplus; + num_symb = 12-(ncp<<1)-(use_srs==0?0:1); + num_re = num_symb * nb_rb * 12; + + if (num_re == 0) + return(0); + + MPR_x100 = 100*sumKr/num_re; + + if (control_only == 1 ) + beta_offset_pusch_x8=8; // fixme + + //(beta_offset_pusch_x8=ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? ue->ulsch[eNB_id]->beta_offset_cqi_times8:8; + + // if deltamcs_enabledm + delta_mcs = ((hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch_x8)>>3))/100.0); + + bw_factor = (norm!=0) ? 0 : (hundred_times_log10_NPRB[nb_rb-1]/100.0); + LOG_D(PHY,"estimated ue tx power %d (num_re %d, sumKr %d, mpr_x100 %d, delta_mcs %f, bw_factor %f)\n", + (int16_t)ceil(delta_mcs + bw_factor), num_re, sumKr, MPR_x100, delta_mcs, bw_factor); + return (int16_t)ceil(delta_mcs + bw_factor); + +} + diff --git a/common/utils/itti_analyzer/libparser/intertask_contexts.h b/common/utils/lte/ue_power.h similarity index 74% rename from common/utils/itti_analyzer/libparser/intertask_contexts.h rename to common/utils/lte/ue_power.h index cfe8f59402..caeebec2c8 100644 --- a/common/utils/itti_analyzer/libparser/intertask_contexts.h +++ b/common/utils/lte/ue_power.h @@ -19,17 +19,16 @@ * contact@openairinterface.org */ -#include "fundamental_type.h" -#include "struct_type.h" +/*! \file ue_power.h +* \brief support routines used in MAC and PHY +* \author R. Knopp, F. Kaltenberger +* \date 2020 +* \version 0.1 +* \company Eurecom +* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr +* \note +* \warning +*/ -#ifndef INTERTASK_CONTEXTS_H_ -#define INTERTASK_CONTEXTS_H_ +int16_t estimate_ue_tx_power(int norm,uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs); -typedef struct { - /* List of fundamental types that can contruct any other type */ - fundamental_type_t *ft_list; - - struct_type_t *struct_list; -} intertask_context_t; - -#endif /* INTERTASK_CONTEXTS_H_ */ diff --git a/common/utils/memory_pools.c b/common/utils/memory_pools.c deleted file mode 100644 index 9f37e47080..0000000000 --- a/common/utils/memory_pools.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "assertions.h" -#include "memory_pools.h" - -#if T_TRACER - #include - #include "T.h" -#endif - -/*------------------------------------------------------------------------------*/ -const static int mp_debug = 0; - -# define MP_DEBUG(x, args...) do { if (mp_debug) fprintf(stdout, "[MP][D]"x, ##args); fflush (stdout); } \ - while(0) - -/*------------------------------------------------------------------------------*/ -#ifndef CHARS_TO_UINT32 - #define CHARS_TO_UINT32(c1, c2, c3, c4) (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4)) -#endif - -#define MEMORY_POOL_ITEM_INFO_NUMBER 2 - -/*------------------------------------------------------------------------------*/ -typedef int32_t items_group_position_t; -typedef int32_t items_group_index_t; - -typedef union items_group_positions_u { - uint64_t all; - struct { - items_group_position_t put; - items_group_position_t get; - } ind; -} items_group_positions_t; - -typedef struct items_group_s { - items_group_position_t number_plus_one; - volatile uint32_t minimum; - volatile items_group_positions_t positions; - volatile items_group_index_t *indexes; -} items_group_t; - -/*------------------------------------------------------------------------------*/ -//static const items_group_position_t ITEMS_GROUP_POSITION_INVALID = -1; -static const items_group_index_t ITEMS_GROUP_INDEX_INVALID = -1; - -/*------------------------------------------------------------------------------*/ -typedef uint32_t pool_item_start_mark_t; -typedef uint32_t pool_item_end_mark_t; - -typedef uint32_t memory_pool_data_t; - -typedef uint32_t pool_start_mark_t; - -typedef uint32_t pools_start_mark_t; - -typedef uint8_t pool_id_t; -typedef uint8_t item_status_t; - -typedef struct memory_pool_item_start_s { - pool_item_start_mark_t start_mark; - - pool_id_t pool_id; - item_status_t item_status; - uint16_t info[MEMORY_POOL_ITEM_INFO_NUMBER]; -} memory_pool_item_start_t; - -typedef struct memory_pool_item_end_s { - pool_item_end_mark_t end_mark; -} memory_pool_item_end_t; - -typedef struct memory_pool_item_s { - memory_pool_item_start_t start; - memory_pool_data_t data[0]; - memory_pool_item_end_t end; -} memory_pool_item_t; - -typedef struct memory_pool_s { - pool_start_mark_t start_mark; - - pool_id_t pool_id; - uint32_t item_data_number; - uint32_t pool_item_size; - items_group_t items_group_free; - memory_pool_item_t *items; -} memory_pool_t; - - -typedef struct memory_pools_s { - pools_start_mark_t start_mark; - - uint32_t pools_number; - uint32_t pools_defined; - memory_pool_t *pools; -} memory_pools_t; - -/*------------------------------------------------------------------------------*/ -static const uint32_t MAX_POOLS_NUMBER = 20; -static const uint32_t MAX_POOL_ITEMS_NUMBER = 200 * 1000; -static const uint32_t MAX_POOL_ITEM_SIZE = 100 * 1000; - -static const pool_item_start_mark_t POOL_ITEM_START_MARK = CHARS_TO_UINT32 ('P', 'I', 's', 't'); -static const pool_item_end_mark_t POOL_ITEM_END_MARK = CHARS_TO_UINT32 ('p', 'i', 'E', 'N'); - -static const item_status_t ITEM_STATUS_FREE = 'F'; -static const item_status_t ITEM_STATUS_ALLOCATED = 'a'; - -static const pool_start_mark_t POOL_START_MARK = CHARS_TO_UINT32 ('P', '_', 's', 't'); - -static const pools_start_mark_t POOLS_START_MARK = CHARS_TO_UINT32 ('P', 'S', 's', 't'); - -/*------------------------------------------------------------------------------*/ -static inline uint32_t items_group_number_items (items_group_t *items_group) { - return items_group->number_plus_one - 1; -} - -static inline uint32_t items_group_free_items (items_group_t *items_group) { - items_group_positions_t positions; - uint32_t free_items; - positions.all = items_group->positions.all; - free_items = items_group->number_plus_one + positions.ind.put - positions.ind.get; - free_items %= items_group->number_plus_one; - return free_items; -} - -static inline items_group_index_t items_group_get_free_item (items_group_t *items_group) { - items_group_position_t get_raw; - items_group_position_t put; - items_group_position_t get; - items_group_position_t free_items; - items_group_index_t index = ITEMS_GROUP_INDEX_INVALID; - /* Get current put position */ - put = items_group->positions.ind.put % items_group->number_plus_one; - /* Get current get position and increase it */ - get_raw = __sync_fetch_and_add (&items_group->positions.ind.get, 1); - get = get_raw % items_group->number_plus_one; - - if(put == get) { - /* No more item free, restore previous position */ - __sync_fetch_and_sub (&items_group->positions.ind.get, 1); - } else { - /* Get index at current get position */ - index = items_group->indexes[get]; - - if (index <= ITEMS_GROUP_INDEX_INVALID) { - /* Index has not yet been completely freed, restore previous get position */ - __sync_fetch_and_sub (&items_group->positions.ind.get, 1); - } else { - if (get_raw == items_group->number_plus_one) { - /* Wrap get position */ - __sync_fetch_and_sub (&items_group->positions.ind.get, items_group->number_plus_one); - } - - free_items = items_group_free_items(items_group); - - /* Updates minimum free items if needed */ - while (items_group->minimum > free_items) { - items_group->minimum = free_items; - } - - /* Clear index at current get position to indicate that item is free */ - items_group->indexes[get] = ITEMS_GROUP_INDEX_INVALID; - } - } - - return (index); -} - -static inline int items_group_put_free_item (items_group_t *items_group, items_group_index_t index) { - items_group_position_t put_raw; - items_group_position_t put; - /* Get current put position and increase it */ - put_raw = __sync_fetch_and_add (&items_group->positions.ind.put, 1); - put = put_raw % items_group->number_plus_one; - - if (put_raw == items_group->number_plus_one) { - /* Wrap position */ - __sync_fetch_and_sub (&items_group->positions.ind.put, items_group->number_plus_one); - } - - AssertError (items_group->indexes[put] <= ITEMS_GROUP_INDEX_INVALID, return (EXIT_FAILURE), - "Index at current put position (%d) is not marked as free (%d)!\n", put, items_group->number_plus_one); - /* Save freed item index at current put position */ - items_group->indexes[put] = index; - return (EXIT_SUCCESS); -} - -/*------------------------------------------------------------------------------*/ -static inline memory_pools_t *memory_pools_from_handler (memory_pools_handle_t memory_pools_handle) { - memory_pools_t *memory_pools; - /* Recover memory_pools */ - memory_pools = (memory_pools_t *) memory_pools_handle; - /* Sanity check on passed handle */ - AssertError (memory_pools->start_mark == POOLS_START_MARK, memory_pools = NULL, - "Handle %p is not a valid memory pools handle, start mark is missing!\n", memory_pools_handle); - return (memory_pools); -} - -static inline memory_pool_item_t *memory_pool_item_from_handler (memory_pool_item_handle_t memory_pool_item_handle) { - void *address; - memory_pool_item_t *memory_pool_item; - /* Recover memory_pools */ - address = memory_pool_item_handle - sizeof(memory_pool_item_start_t); - memory_pool_item = (memory_pool_item_t *) address; - /* Sanity check on passed handle */ - AssertError (memory_pool_item->start.start_mark == POOL_ITEM_START_MARK, memory_pool_item = NULL, - "Handle %p is not a valid memory pool item handle, start mark is missing!\n", memory_pool_item); - return (memory_pool_item); -} - -static inline memory_pool_item_t *memory_pool_item_from_index (memory_pool_t *memory_pool, items_group_index_t index) { - void *address; - address = (void *) memory_pool->items; - address += index * memory_pool->pool_item_size; - return (address); -} - -/*------------------------------------------------------------------------------*/ -memory_pools_handle_t memory_pools_create (uint32_t pools_number) { - memory_pools_t *memory_pools; - pool_id_t pool; - AssertFatal (pools_number <= MAX_POOLS_NUMBER, "Too many memory pools requested (%d/%d)!\n", pools_number, MAX_POOLS_NUMBER); /* Limit to a reasonable number of pools */ - /* Allocate memory_pools */ - memory_pools = malloc (sizeof(memory_pools_t)); - AssertFatal (memory_pools != NULL, "Memory pools structure allocation failed!\n"); - /* Initialize memory_pools */ - { - memory_pools->start_mark = POOLS_START_MARK; - memory_pools->pools_number = pools_number; - memory_pools->pools_defined = 0; - /* Allocate pools */ - memory_pools->pools = calloc (pools_number, sizeof(memory_pool_t)); - AssertFatal (memory_pools->pools != NULL, "Memory pools allocation failed!\n"); - - /* Initialize pools */ - for (pool = 0; pool < pools_number; pool++) { - memory_pools->pools[pool].start_mark = POOL_START_MARK; - } - } - return ((memory_pools_handle_t) memory_pools); -} - -char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle) { - memory_pools_t *memory_pools; - pool_id_t pool; - char *statistics; - int printed_chars; - uint32_t allocated_pool_memory; - uint32_t allocated_pools_memory = 0; - items_group_t *items_group; - uint32_t pool_items_size; - /* Recover memory_pools */ - memory_pools = memory_pools_from_handler (memory_pools_handle); - AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle); - statistics = malloc(memory_pools->pools_defined * 200); - printed_chars = sprintf (&statistics[0], "Pool: size, number, minimum, free, address space and memory used in Kbytes\n"); - - for (pool = 0; pool < memory_pools->pools_defined; pool++) { - items_group = &memory_pools->pools[pool].items_group_free; - allocated_pool_memory = items_group_number_items (items_group) * memory_pools->pools[pool].pool_item_size; - allocated_pools_memory += allocated_pool_memory; - pool_items_size = memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t); - printed_chars += sprintf (&statistics[printed_chars], " %2u: %6u, %6u, %6u, %6u, [%p-%p] %6u\n", - pool, pool_items_size, - items_group_number_items (items_group), - items_group->minimum, - items_group_free_items (items_group), - memory_pools->pools[pool].items, - ((void *) memory_pools->pools[pool].items) + allocated_pool_memory, - allocated_pool_memory / (1024)); - } - - printed_chars = sprintf (&statistics[printed_chars], "Pools memory %u Kbytes\n", allocated_pools_memory / (1024)); - return (statistics); -} - -int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size) { - memory_pools_t *memory_pools; - memory_pool_t *memory_pool; - pool_id_t pool; - items_group_index_t item_index; - memory_pool_item_t *memory_pool_item; - AssertFatal (pool_items_number <= MAX_POOL_ITEMS_NUMBER, "Too many items for a memory pool (%u/%d)!\n", pool_items_number, MAX_POOL_ITEMS_NUMBER); /* Limit to a reasonable number of items */ - AssertFatal (pool_item_size <= MAX_POOL_ITEM_SIZE, "Item size is too big for memory pool items (%u/%d)!\n", pool_item_size, MAX_POOL_ITEM_SIZE); /* Limit to a reasonable item size */ - /* Recover memory_pools */ - memory_pools = memory_pools_from_handler (memory_pools_handle); - AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle); - /* Check number of already created pools */ - AssertFatal (memory_pools->pools_defined < memory_pools->pools_number, "Can not allocate more memory pool (%d)!\n", memory_pools->pools_number); - /* Select pool */ - pool = memory_pools->pools_defined; - memory_pool = &memory_pools->pools[pool]; - /* Initialize pool */ - { - memory_pool->pool_id = pool; - /* Item size in memory_pool_data_t items by excess */ - memory_pool->item_data_number = (pool_item_size + sizeof(memory_pool_data_t) - 1) / sizeof(memory_pool_data_t); - memory_pool->pool_item_size = (memory_pool->item_data_number * sizeof(memory_pool_data_t)) + sizeof(memory_pool_item_t); - memory_pool->items_group_free.number_plus_one = pool_items_number + 1; - memory_pool->items_group_free.minimum = pool_items_number; - memory_pool->items_group_free.positions.ind.put = pool_items_number; - memory_pool->items_group_free.positions.ind.get = 0; - /* Allocate free indexes */ - memory_pool->items_group_free.indexes = malloc(memory_pool->items_group_free.number_plus_one * sizeof(items_group_index_t)); - AssertFatal (memory_pool->items_group_free.indexes != NULL, "Memory pool indexes allocation failed!\n"); - - /* Initialize free indexes */ - for (item_index = 0; item_index < pool_items_number; item_index++) { - memory_pool->items_group_free.indexes[item_index] = item_index; - } - - /* Last index is not allocated */ - memory_pool->items_group_free.indexes[item_index] = ITEMS_GROUP_INDEX_INVALID; - /* Allocate items */ - memory_pool->items = calloc (pool_items_number, memory_pool->pool_item_size); - AssertFatal (memory_pool->items != NULL, "Memory pool items allocation failed!\n"); - - /* Initialize items */ - for (item_index = 0; item_index < pool_items_number; item_index++) { - memory_pool_item = memory_pool_item_from_index (memory_pool, item_index); - memory_pool_item->start.start_mark = POOL_ITEM_START_MARK; - memory_pool_item->start.pool_id = pool; - memory_pool_item->start.item_status = ITEM_STATUS_FREE; - memory_pool_item->data[memory_pool->item_data_number] = POOL_ITEM_END_MARK; - } - } - memory_pools->pools_defined ++; - return (0); -} - -memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint16_t info_0, uint16_t info_1) { - memory_pools_t *memory_pools; - memory_pool_item_t *memory_pool_item; - memory_pool_item_handle_t memory_pool_item_handle = NULL; - pool_id_t pool; - items_group_index_t item_index = ITEMS_GROUP_INDEX_INVALID; - /* Recover memory_pools */ - memory_pools = memory_pools_from_handler (memory_pools_handle); - AssertError (memory_pools != NULL, {}, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle); - - for (pool = 0; pool < memory_pools->pools_defined; pool++) { - if ((memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t)) < item_size) { - /* This memory pool has too small items, skip it */ - continue; - } - - item_index = items_group_get_free_item(&memory_pools->pools[pool].items_group_free); - - if (item_index <= ITEMS_GROUP_INDEX_INVALID) { - /* Allocation failed, skip this pool */ - continue; - } else { - /* Allocation succeed, exit searching loop */ - break; - } - } - - if (item_index > ITEMS_GROUP_INDEX_INVALID) { - /* Convert item index into memory_pool_item address */ - memory_pool_item = memory_pool_item_from_index (&memory_pools->pools[pool], item_index); - /* Sanity check on item status, must be free */ - AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_FREE, "Item status is not set to free (%d) in pool %u, item %d!\n", - memory_pool_item->start.item_status, pool, item_index); - memory_pool_item->start.item_status = ITEM_STATUS_ALLOCATED; - memory_pool_item->start.info[0] = info_0; - memory_pool_item->start.info[1] = info_1; - memory_pool_item_handle = memory_pool_item->data; - MP_DEBUG(" Alloc [%2u][%6d]{%6d}, %3u %3u, %6u, %p, %p, %p\n", - pool, item_index, - items_group_free_items (&memory_pools->pools[pool].items_group_free), - info_0, info_1, - item_size, - memory_pools->pools[pool].items, - memory_pool_item, - memory_pool_item_handle); - } else { - MP_DEBUG(" Alloc [--][------]{------}, %3u %3u, %6u, failed!\n", info_0, info_1, item_size); - } - - return memory_pool_item_handle; -} - -int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint16_t info_0) { - memory_pools_t *memory_pools; - memory_pool_item_t *memory_pool_item; - pool_id_t pool; - items_group_index_t item_index; - uint32_t item_size; - uint32_t pool_item_size; - uint16_t info_1; - int result; - /* Recover memory_pools */ - memory_pools = memory_pools_from_handler (memory_pools_handle); - AssertError (memory_pools != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pools for handle %p!\n", memory_pools_handle); - /* Recover memory pool item */ - memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle); - AssertError (memory_pool_item != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle); - info_1 = memory_pool_item->start.info[1]; - /* Recover pool index */ - pool = memory_pool_item->start.pool_id; - AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined); - item_size = memory_pools->pools[pool].item_data_number; - pool_item_size = memory_pools->pools[pool].pool_item_size; - item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size; - MP_DEBUG(" Free [%2u][%6d]{%6d}, %3u %3u, %p, %p, %p, %u\n", - pool, item_index, - items_group_free_items (&memory_pools->pools[pool].items_group_free), - memory_pool_item->start.info[0], info_1, - memory_pool_item_handle, memory_pool_item, - memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t)))); - /* Sanity check on calculated item index */ - AssertFatal (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index), - "Incorrect memory pool item address (%p, %p) for pool %u, item %d!\n", - memory_pool_item,(void *)memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index); - /* Sanity check on end marker, must still be present (no write overflow) */ - AssertFatal (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK, - "Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index); - /* Sanity check on item status, must be allocated */ - AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED, - "Trying to free a non allocated (%x) memory pool item (pool %u, item %d)!\n", - memory_pool_item->start.item_status, pool, item_index); - memory_pool_item->start.item_status = ITEM_STATUS_FREE; - result = items_group_put_free_item(&memory_pools->pools[pool].items_group_free, item_index); - AssertError (result == EXIT_SUCCESS, {}, "Failed to free memory pool item (pool %u, item %d)!\n", pool, item_index); - return (result); -} - -void memory_pools_set_info (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, int index, uint16_t info) { - memory_pools_t *memory_pools; - memory_pool_item_t *memory_pool_item; - pool_id_t pool; - items_group_index_t item_index; - uint32_t item_size; - uint32_t pool_item_size; - AssertFatal (index < MEMORY_POOL_ITEM_INFO_NUMBER, "Incorrect info index (%d/%d)!\n", index, MEMORY_POOL_ITEM_INFO_NUMBER); - /* Recover memory pool item */ - memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle); - AssertFatal (memory_pool_item != NULL, "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle); - /* Set info[1] */ - memory_pool_item->start.info[index] = info; - - /* Check item validity and log (not mandatory) */ - if (1) { - /* Recover memory_pools */ - memory_pools = memory_pools_from_handler (memory_pools_handle); - AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle); - /* Recover pool index */ - pool = memory_pool_item->start.pool_id; - AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined); - item_size = memory_pools->pools[pool].item_data_number; - pool_item_size = memory_pools->pools[pool].pool_item_size; - item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size; - MP_DEBUG(" Info [%2u][%6d]{%6d}, %3u %3u, %p, %p, %p, %u\n", - pool, item_index, - items_group_free_items (&memory_pools->pools[pool].items_group_free), - memory_pool_item->start.info[0], memory_pool_item->start.info[1], - memory_pool_item_handle, memory_pool_item, - memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t)))); - /* Sanity check on calculated item index */ - AssertFatal (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index), - "Incorrect memory pool item address (%p, %p) for pool %u, item %d!\n", - memory_pool_item, (void *)memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index); - /* Sanity check on end marker, must still be present (no write overflow) */ - AssertFatal (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK, - "Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index); - /* Sanity check on item status, must be allocated */ - AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED, - "Trying to free a non allocated (%x) memory pool item (pool %u, item %d)\n", - memory_pool_item->start.item_status, pool, item_index); - } -} diff --git a/common/utils/minimal_stub.c b/common/utils/minimal_stub.c index 86454fe53f..79e35bf7a6 100644 --- a/common/utils/minimal_stub.c +++ b/common/utils/minimal_stub.c @@ -1,4 +1,6 @@ +#ifndef T_TRACER int T_stdout; +#endif void exit_function(const char *file, const char *function, const int line, const char *s) { } diff --git a/common/utils/msc/msc.c b/common/utils/msc/msc.c index ae87a8e326..84b723b022 100644 --- a/common/utils/msc/msc.c +++ b/common/utils/msc/msc.c @@ -52,6 +52,7 @@ FILE *g_msc_fd; char g_msc_proto2str[MAX_MSC_PROTOS][MSC_MAX_PROTO_NAME_LENGTH]; +msc_interface_t msc_interface; typedef unsigned long msc_message_number_t; typedef struct msc_queue_item_s { @@ -88,7 +89,7 @@ void *msc_task(void *args_p) if (received_message_p != NULL) { // msg_name = ITTI_MSG_NAME (received_message_p); - // instance = ITTI_MSG_INSTANCE (received_message_p); + // instance = ITTI_MSG_DESTINATION_INSTANCE (received_message_p); switch (ITTI_MSG_ID(received_message_p)) { case TIMER_HAS_EXPIRED: { msc_flush_messages(); diff --git a/common/utils/msc/msc.h b/common/utils/msc/msc.h index 49c99abb56..adb0d9e657 100644 --- a/common/utils/msc/msc.h +++ b/common/utils/msc/msc.h @@ -48,12 +48,17 @@ typedef enum { MSC_MAC_ENB, MSC_RLC_ENB, MSC_PDCP_ENB, + MSC_PDCP_GNB, MSC_RRC_ENB, + MSC_RRC_GNB, MSC_IP_ENB, MSC_S1AP_ENB, + MSC_NGAP_GNB, MSC_GTPU_ENB, + MSC_GTPU_GNB, MSC_GTPU_SGW, MSC_S1AP_MME, + MSC_NGAP_AMF, MSC_MMEAPP_MME, MSC_NAS_MME, MSC_NAS_EMM_MME, @@ -112,7 +117,7 @@ void msc_log_message( #define MESSAGE_CHART_GENERATOR msc_interface.msc_loaded -msc_interface_t msc_interface; +extern msc_interface_t msc_interface; #define MSC_INIT(arg1,arg2) if(msc_interface.msc_loaded) msc_interface.msc_init(arg1,arg2) #define MSC_START_USE if(msc_interface.msc_loaded) msc_interface.msc_start_use #define MSC_END if(msc_interface.msc_loaded) msc_interface.msc_end diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 5f07fc00aa..0de24bcf6d 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -32,12 +32,122 @@ #include #include "assertions.h" +#include "nr_common.h" + +const char *duplex_mode[]={"FDD","TDD"}; + +// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) +// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) +// Notes: +// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL +// - Frequencies are expressed in KHz +// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster +nr_bandentry_t nr_bandtable[] = { + {1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, + {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, + {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, + {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, + {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, + {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, + {12, 698000, 716000, 729000, 746000, 20, 145800, 100}, + {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, + {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, + {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, + {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, + {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, + {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, + {29, 000, 000, 717000, 728000, 20, 143400, 100}, + {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, + {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, + {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, + {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, + {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, + {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, + {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, + {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, + {48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, + {48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, + {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, + {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, + {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, + {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, + {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, + {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, + {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, + {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, + {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, + {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, + {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, + {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, + {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, + {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, + {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, + {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, + {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, + {81, 880000, 915000, 000, 000, 20, 176000, 100}, + {82, 832000, 862000, 000, 000, 20, 166400, 100}, + {83, 703000, 748000, 000, 000, 20, 140600, 100}, + {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, + {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, + {89, 824000, 849000, 000, 000, 20, 342000, 100}, + {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, + {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, + {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, + {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, + {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, + {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, + {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, + {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, + {96, 5925000, 7125000, 5925000, 7125000, 1, 795000, 15}, + {257,26500020,29500000,26500020,29500000, 1,2054166, 60}, + {257,26500080,29500000,26500080,29500000, 2,2054167, 120}, + {258,24250080,27500000,24250080,27500000, 1,2016667, 60}, + {258,24250080,27500000,24250080,27500000, 2,2016667, 120}, + {260,37000020,40000000,37000020,40000000, 1,2229166, 60}, + {260,37000080,40000000,37000080,40000000, 2,2229167, 120}, + {261,27500040,28350000,27500040,28350000, 1,2070833, 60}, + {261,27500040,28350000,27500040,28350000, 2,2070833, 120} +}; + +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) +{ + const uint64_t dl_freq_khz = downlink_frequency / 1000; + const int32_t delta_duplex_khz = delta_duplex / 1000; + + uint64_t center_freq_diff_khz = 999999999999999999; // 2^64 + uint16_t current_band = 0; + + for (int ind = 0; ind < nr_bandtable_size; ind++) { + + if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max) + continue; + + int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min; + + if (current_offset_khz != delta_duplex_khz) + continue; + + uint64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; + + if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ + current_band = nr_bandtable[ind].band; + center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); + } + } + + printf("DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n", + downlink_frequency, current_band, downlink_frequency+delta_duplex); + + AssertFatal(current_band != 0, "Can't find EUTRA band for frequency %"PRIu64" and duplex_spacing %u\n", downlink_frequency, delta_duplex); + + return current_band; +} + +const size_t nr_bandtable_size = sizeof(nr_bandtable) / sizeof(nr_bandentry_t); int NRRIV2BW(int locationAndBandwidth,int N_RB) { int tmp = locationAndBandwidth/N_RB; int tmp2 = locationAndBandwidth%N_RB; - - if (tmp <= ((N_RB>>1)+1) && (tmp+tmp2)>1)+1) && (tmp+tmp2)>3); + + for (int i=0; i<45; i++) + if ((bitmap>>(44-i))&1) { + count++; + if (!start_set) { + start = i; + start_set = 1; + } + } + *rb_offset = 6*start; + *n_rb = 6*count; +} + +int get_nb_periods_per_frame(uint8_t tdd_period) { + + int nb_periods_per_frame; + switch(tdd_period) { + case 0: + nb_periods_per_frame = 20; // 10ms/0p5ms + break; + + case 1: + nb_periods_per_frame = 16; // 10ms/0p625ms + break; + + case 2: + nb_periods_per_frame = 10; // 10ms/1ms + break; + + case 3: + nb_periods_per_frame = 8; // 10ms/1p25ms + break; + + case 4: + nb_periods_per_frame = 5; // 10ms/2ms + break; + + case 5: + nb_periods_per_frame = 4; // 10ms/2p5ms + break; + + case 6: + nb_periods_per_frame = 2; // 10ms/5ms + break; + + case 7: + nb_periods_per_frame = 1; // 10ms/10ms + break; + + default: + AssertFatal(1==0,"Undefined tdd period %d\n", tdd_period); + } + return nb_periods_per_frame; +} + + +int get_dmrs_port(int nl, uint16_t dmrs_ports) { + + if (dmrs_ports == 0) return 0; // dci 1_0 + int p = -1; + int found = -1; + for (int i=0; i<12; i++) { // loop over dmrs ports + if((dmrs_ports>>i)&0x01) { // check if current bit is 1 + found++; + if (found == nl) { // found antenna port number corresponding to current layer + p = i; + break; + } + } + } + AssertFatal(p>-1,"No dmrs port corresponding to layer %d found\n",nl); + return p; +} + +lte_frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index) +{ + lte_frame_type_t current_type; + int32_t delta_duplex = get_delta_duplex(current_band, scs_index); + + if (delta_duplex == 0) + current_type = TDD; + else + current_type = FDD; + + LOG_I(NR_MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex); + + return current_type; +} + +// Computes the duplex spacing (either positive or negative) in KHz +int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index) +{ + int nr_table_idx = get_nr_table_idx(nr_bandP, scs_index); + + int32_t delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min); + + LOG_I(NR_MAC, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band); + + return delta_duplex; +} + +uint16_t config_bandwidth(int mu, int nb_rb, int nr_band) +{ + + if (nr_band < 100) { //FR1 + switch(mu) { + case 0 : + if (nb_rb<=25) + return 5; + if (nb_rb<=52) + return 10; + if (nb_rb<=79) + return 15; + if (nb_rb<=106) + return 20; + if (nb_rb<=133) + return 25; + if (nb_rb<=160) + return 30; + if (nb_rb<=216) + return 40; + if (nb_rb<=270) + return 50; + AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); + break; + case 1 : + if (nb_rb<=11) + return 5; + if (nb_rb<=24) + return 10; + if (nb_rb<=38) + return 15; + if (nb_rb<=51) + return 20; + if (nb_rb<=65) + return 25; + if (nb_rb<=78) + return 30; + if (nb_rb<=106) + return 40; + if (nb_rb<=133) + return 50; + if (nb_rb<=162) + return 60; + if (nb_rb<=189) + return 70; + if (nb_rb<=217) + return 80; + if (nb_rb<=245) + return 90; + if (nb_rb<=273) + return 100; + AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); + break; + case 2 : + if (nb_rb<=11) + return 10; + if (nb_rb<=18) + return 15; + if (nb_rb<=24) + return 20; + if (nb_rb<=31) + return 25; + if (nb_rb<=38) + return 30; + if (nb_rb<=51) + return 40; + if (nb_rb<=65) + return 50; + if (nb_rb<=79) + return 60; + if (nb_rb<=93) + return 70; + if (nb_rb<=107) + return 80; + if (nb_rb<=121) + return 90; + if (nb_rb<=135) + return 100; + AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); + break; + default: + AssertFatal(1==0,"Numerology %d undefined for band %d in FR1\n", mu,nr_band); + } + } + else { + switch(mu) { + case 2 : + if (nb_rb<=66) + return 50; + if (nb_rb<=132) + return 100; + if (nb_rb<=264) + return 200; + AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); + break; + case 3 : + if (nb_rb<=32) + return 50; + if (nb_rb<=66) + return 100; + if (nb_rb<=132) + return 200; + if (nb_rb<=264) + return 400; + AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); + break; + default: + AssertFatal(1==0,"Numerology %d undefined for band %d in FR1\n", mu,nr_band); + } + } +} + +// Returns the corresponding row index of the NR table +int get_nr_table_idx(int nr_bandP, uint8_t scs_index) { + int i, j; + int scs_khz = 15 << scs_index; + int supplementary_bands[] = {29,75,76,80,81,82,83,84,86,89,95}; + size_t s = sizeof(supplementary_bands)/sizeof(supplementary_bands[0]); + + for(j = 0; j < s; j++){ + if (nr_bandP == supplementary_bands[j]) + AssertFatal(0 == 1, "Band %d is a supplementary band (%d). This is not supported yet.\n", nr_bandP, supplementary_bands[j]); + } + + AssertFatal(nr_bandP <= nr_bandtable[nr_bandtable_size-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[nr_bandtable_size-1].band); + for (i = 0; i < nr_bandtable_size && nr_bandtable[i].band != nr_bandP; i++); + + // In frequency bands with two deltaFRaster, + // the higher deltaFRaster applies to channels using only the SCS that is equal to or larger than the higher deltaFRaster + // and SSB SCS is equal to the higher deltaFRaster. + while(((i+1) #include "assertions.h" +#include "PHY/defs_common.h" +typedef struct nr_bandentry_s { + int16_t band; + uint64_t ul_min; + uint64_t ul_max; + uint64_t dl_min; + uint64_t dl_max; + uint64_t step_size; + uint64_t N_OFFs_DL; + uint8_t deltaf_raster; +} nr_bandentry_t; + +extern const size_t nr_bandtable_size; +extern nr_bandentry_t nr_bandtable[]; +static inline int get_num_dmrs(uint16_t dmrs_mask ) { + + int num_dmrs=0; + + for (int i=0;i<16;i++) num_dmrs+=((dmrs_mask>>i)&1); + return(num_dmrs); +} + + +int get_SLIV(uint8_t S, uint8_t L); +void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset); +uint16_t config_bandwidth(int mu, int nb_rb, int nr_band); +int get_nr_table_idx(int nr_bandP, uint8_t scs_index); +int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index); +lte_frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index); +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex); int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize); @@ -48,7 +78,8 @@ uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx); uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx); int get_subband_size(int NPRB,int size); void SLIV2SL(int SLIV,int *S,int *L); - +int get_dmrs_port(int nl, uint16_t dmrs_ports); +int get_nb_periods_per_frame(uint8_t tdd_period); #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) diff --git a/common/utils/ocp_itti/all_msg.h b/common/utils/ocp_itti/all_msg.h index a2add514e1..8f7f48ed5a 100644 --- a/common/utils/ocp_itti/all_msg.h +++ b/common/utils/ocp_itti/all_msg.h @@ -16,3 +16,8 @@ #include "openair2/COMMON/gtpv1_u_messages_def.h" #include "openair2/COMMON/flexran_messages_def.h" #include "openair2/COMMON/f1ap_messages_def.h" +#include "openair2/COMMON/ngap_messages_def.h" +#if ITTI_SIM +#include "openair2/COMMON/itti_sim_messages_def.h" +#endif + diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 1680410ebb..4e5323aec9 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -30,30 +30,32 @@ extern "C" { #include #include -typedef struct timer_elm_s { - timer_type_t type; ///< Timer type - long instance; - long duration; - uint64_t timeout; - void *timer_arg; ///< Optional argument that will be passed when timer expires -} timer_elm_t ; + typedef struct timer_elm_s { + timer_type_t type; ///< Timer type + long instance; + long duration; + uint64_t timeout; + void *timer_arg; ///< Optional argument that will be passed when timer expires + } timer_elm_t ; -typedef struct task_list_s { - task_info_t admin; - pthread_t thread; - pthread_mutex_t queue_cond_lock; - std::vector message_queue; - std::map timer_map; - uint64_t next_timer=UINT64_MAX; - struct epoll_event *events =NULL; - int nb_fd_epoll=0; - int nb_events=0; - int epoll_fd=-1; - int sem_fd=-1; -} task_list_t; + typedef struct task_list_s { + task_info_t admin; + pthread_t thread; + pthread_mutex_t queue_cond_lock; + std::vector message_queue; + std::map timer_map; + uint64_t next_timer=UINT64_MAX; + struct epoll_event *events =NULL; + int nb_fd_epoll=0; + int nb_events=0; + int epoll_fd=-1; + int sem_fd=-1; + } task_list_t; -int timer_expired(int fd); -task_list_t tasks[TASK_MAX]; + int timer_expired(int fd); + static task_list_t **tasks=NULL; + static int nb_queues=0; + static pthread_mutex_t lock_nb_queues; void *pool_buffer_init (void) { return 0; @@ -99,7 +101,7 @@ task_list_t tasks[TASK_MAX]; // #define S1AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_register_enb_req // would become // #define S1AP_REGISTER_ENB_REQ(mSGpTR) (s1ap_register_enb_req) mSGpTR)->ittiMsg - MessageDef *itti_alloc_new_message_sized(task_id_t origin_task_id, MessagesIds message_id, MessageHeaderSize size) { + MessageDef *itti_alloc_new_message_sized(task_id_t origin_task_id, instance_t originInstance, MessagesIds message_id, MessageHeaderSize size) { MessageDef *temp = (MessageDef *)itti_malloc (origin_task_id, TASK_UNKNOWN, sizeof(MessageHeader) +32 + size); temp->ittiMsgHeader.messageId = message_id; temp->ittiMsgHeader.originTaskId = origin_task_id; @@ -107,23 +109,24 @@ task_list_t tasks[TASK_MAX]; return temp; } - MessageDef *itti_alloc_new_message(task_id_t origin_task_id, MessagesIds message_id) { + MessageDef *itti_alloc_new_message(task_id_t origin_task_id, instance_t originInstance, MessagesIds message_id) { int size=sizeof(MessageHeader) + 32 + messages_info[message_id].size; MessageDef *temp = (MessageDef *)itti_malloc (origin_task_id, TASK_UNKNOWN, size); temp->ittiMsgHeader.messageId = message_id; temp->ittiMsgHeader.originTaskId = origin_task_id; temp->ittiMsgHeader.ittiMsgSize = size; temp->ittiMsgHeader.destinationTaskId=TASK_UNKNOWN; - temp->ittiMsgHeader.instance=0; - temp->ittiMsgHeader.lte_time={0}; + temp->ittiMsgHeader.originInstance=originInstance; + temp->ittiMsgHeader.destinationInstance=0; + temp->ittiMsgHeader.lte_time= {0}; return temp; //return itti_alloc_new_message_sized(origin_task_id, message_id, messages_info[message_id].size); } - static inline int itti_send_msg_to_task_locked(task_id_t destination_task_id, instance_t instance, MessageDef *message) { - task_list_t *t=tasks+destination_task_id; + static inline int itti_send_msg_to_task_locked(task_id_t destination_task_id, instance_t destinationInstance, MessageDef *message) { + task_list_t *t=tasks[destination_task_id]; message->ittiMsgHeader.destinationTaskId = destination_task_id; - message->ittiMsgHeader.instance = instance; + message->ittiMsgHeader.destinationInstance = destinationInstance; message->ittiMsgHeader.lte_time.frame = 0; message->ittiMsgHeader.lte_time.slot = 0; int message_id = message->ittiMsgHeader.messageId; @@ -133,7 +136,7 @@ task_list_t tasks[TASK_MAX]; LOG_E(TMR,"Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s ); if ( s > 50 ) - LOG_I(TMR,"Queue for %s task size: %ld\n",itti_get_task_name(destination_task_id), s+1); + LOG_I(TMR,"Queue for %s task size: %ld (last message %s)\n",itti_get_task_name(destination_task_id), s+1,ITTI_MSG_NAME(message)); t->message_queue.insert(t->message_queue.begin(), message); eventfd_t sem_counter = 1; @@ -142,25 +145,27 @@ task_list_t tasks[TASK_MAX]; return 0; } - int itti_send_msg_to_task(task_id_t destination_task_id, instance_t instance, MessageDef *message) { - task_list_t *t=&tasks[destination_task_id]; + int itti_send_msg_to_task(task_id_t destination_task_id, instance_t destinationInstance, MessageDef *message) { + task_list_t *t=tasks[destination_task_id]; pthread_mutex_lock (&t->queue_cond_lock); - int ret=itti_send_msg_to_task_locked(destination_task_id, instance, message); + int ret=itti_send_msg_to_task_locked(destination_task_id, destinationInstance, message); while ( t->message_queue.size()>0 && t->admin.func != NULL ) { if (t->message_queue.size()>1) - LOG_W(TMR,"queue in no thread mode is %ld\n", t->message_queue.size()); + LOG_W(TMR,"queue in no thread mode is %ld\n", t->message_queue.size()); + pthread_mutex_unlock (&t->queue_cond_lock); t->admin.func(NULL); pthread_mutex_lock (&t->queue_cond_lock); } + pthread_mutex_unlock (&t->queue_cond_lock); return ret; } void itti_subscribe_event_fd(task_id_t task_id, int fd) { struct epoll_event event; - task_list_t *t=&tasks[task_id]; + task_list_t *t=tasks[task_id]; t->nb_fd_epoll++; t->events = (struct epoll_event *)realloc((void *)t->events, t->nb_fd_epoll * sizeof(struct epoll_event)); @@ -173,7 +178,7 @@ task_list_t tasks[TASK_MAX]; } void itti_unsubscribe_event_fd(task_id_t task_id, int fd) { - task_list_t *t=&tasks[task_id]; + task_list_t *t=tasks[task_id]; AssertFatal (epoll_ctl(t->epoll_fd, EPOLL_CTL_DEL, fd, NULL) == 0, "epoll_ctl (EPOLL_CTL_DEL) failed for task %s, fd %d: %s!\n", itti_get_task_name(task_id), fd, strerror(errno)); @@ -181,7 +186,7 @@ task_list_t tasks[TASK_MAX]; } static inline int itti_get_events_locked(task_id_t task_id, struct epoll_event **events) { - task_list_t *t=&tasks[task_id]; + task_list_t *t=tasks[task_id]; uint64_t current_time=0; do { @@ -194,9 +199,11 @@ task_list_t tasks[TASK_MAX]; t->next_timer=UINT64_MAX; // Proceed expired timer - for ( auto it=t->timer_map.begin() ; it != t->timer_map.end() ; ++it ) { + for ( auto it=t->timer_map.begin(), next_it = it; it != t->timer_map.end() ; it = next_it ) { + ++next_it; + if ( it->second.timeout < current_time ) { - MessageDef *message = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED); + MessageDef *message = itti_alloc_new_message(TASK_TIMER, it->second.instance,TIMER_HAS_EXPIRED); message->ittiMsg.timer_has_expired.timer_id=it->first; message->ittiMsg.timer_has_expired.arg=it->second.timer_arg; @@ -228,8 +235,9 @@ task_list_t tasks[TASK_MAX]; pthread_mutex_unlock(&t->queue_cond_lock); LOG_D(TMR,"enter blocking wait for %s\n", itti_get_task_name(task_id)); t->nb_events = epoll_wait(t->epoll_fd,t->events,t->nb_fd_epoll, epoll_timeout); + if ( t->nb_events < 0 && (errno == EINTR || errno == EAGAIN ) ) - pthread_mutex_lock(&t->queue_cond_lock); + pthread_mutex_lock(&t->queue_cond_lock); } while (t->nb_events < 0 && (errno == EINTR || errno == EAGAIN ) ); AssertFatal (t->nb_events >=0, @@ -258,13 +266,13 @@ task_list_t tasks[TASK_MAX]; } int itti_get_events(task_id_t task_id, struct epoll_event **events) { - pthread_mutex_lock(&tasks[task_id].queue_cond_lock); + pthread_mutex_lock(&tasks[task_id]->queue_cond_lock); return itti_get_events_locked(task_id, events); } void itti_receive_msg(task_id_t task_id, MessageDef **received_msg) { // Reception of one message, blocking caller - task_list_t *t=&tasks[task_id]; + task_list_t *t=tasks[task_id]; pthread_mutex_lock(&t->queue_cond_lock); // Weird condition to deal with crap legacy itti interface @@ -294,10 +302,9 @@ task_list_t tasks[TASK_MAX]; pthread_mutex_unlock (&t->queue_cond_lock); } - void itti_poll_msg(task_id_t task_id, MessageDef **received_msg) - { + void itti_poll_msg(task_id_t task_id, MessageDef **received_msg) { //reception of one message, non-blocking - task_list_t *t=&tasks[task_id]; + task_list_t *t=tasks[task_id]; pthread_mutex_lock(&t->queue_cond_lock); if (!t->message_queue.empty()) { @@ -311,11 +318,10 @@ task_list_t tasks[TASK_MAX]; } int itti_create_task(task_id_t task_id, - void *(*start_routine)(void *), - void *args_p) - { - task_list_t *t=&tasks[task_id]; - threadCreate (&t->thread, start_routine, args_p, (char*)itti_get_task_name(task_id),-1,OAI_PRIORITY_RT); + void *(*start_routine)(void *), + void *args_p) { + task_list_t *t=tasks[task_id]; + threadCreate (&t->thread, start_routine, args_p, (char *)itti_get_task_name(task_id),-1,OAI_PRIORITY_RT); LOG_I(TMR,"Created Posix thread %s\n", itti_get_task_name(task_id) ); return 0; } @@ -324,31 +330,41 @@ task_list_t tasks[TASK_MAX]; pthread_exit (NULL); } - void itti_terminate_tasks(task_id_t task_id) - { + void itti_terminate_tasks(task_id_t task_id) { // Sends Terminate signals to all tasks. itti_send_terminate_message (task_id); usleep(100*1000); // Allow the tasks to receive the message before going returning to main thread } + int itti_create_queue(const task_info_t *taskInfo) { + pthread_mutex_lock (&lock_nb_queues); + int newQueue=nb_queues++; + task_list_t **new_tasks = (task_list_t **)realloc(tasks, nb_queues * sizeof(*tasks)); + AssertFatal(new_tasks != NULL, "could not realloc() tasks list"); + tasks = new_tasks; + tasks[newQueue]= new task_list_t; + pthread_mutex_unlock (&lock_nb_queues); + LOG_I(TMR,"Starting itti queue: %s as task %d\n", taskInfo->name, newQueue); + pthread_mutex_init(&tasks[newQueue]->queue_cond_lock, NULL); + memcpy(&tasks[newQueue]->admin, taskInfo, sizeof(task_info_t)); + AssertFatal( ( tasks[newQueue]->epoll_fd = epoll_create1(0) ) >=0, ""); + AssertFatal( ( tasks[newQueue]->sem_fd = eventfd(0, EFD_SEMAPHORE) ) >=0, ""); + itti_subscribe_event_fd((task_id_t)newQueue, tasks[newQueue]->sem_fd); + + if (tasks[newQueue]->admin.threadFunc != NULL) + itti_create_task((task_id_t)newQueue, tasks[newQueue]->admin.threadFunc, NULL); + + return newQueue; + } + int itti_init(task_id_t task_max, - thread_id_t thread_max, - MessagesIds messages_id_max, - const task_info_t *tasks_info, - const message_info_t *messages_info) - { - AssertFatal(TASK_MAX=0, ""); - AssertFatal( ( tasks[i].sem_fd = eventfd(0, EFD_SEMAPHORE) ) >=0, ""); - itti_subscribe_event_fd((task_id_t)i, tasks[i].sem_fd); - - if (tasks[i].admin.threadFunc != NULL) - itti_create_task((task_id_t)i, tasks[i].admin.threadFunc, NULL); + itti_create_queue(&tasks[i]); } return 0; @@ -358,12 +374,11 @@ task_list_t tasks[TASK_MAX]; uint32_t interval_sec, uint32_t interval_us, task_id_t task_id, - int32_t instance, + instance_t instance, timer_type_t type, void *timer_arg, - long *timer_id) - { - task_list_t *t=&tasks[task_id]; + long *timer_id) { + task_list_t *t=tasks[task_id]; do { // set the taskid in the timer id to keep compatible with the legacy API @@ -396,13 +411,12 @@ task_list_t tasks[TASK_MAX]; return 0; } - int timer_remove(long timer_id) - { + int timer_remove(long timer_id) { task_id_t task_id=(task_id_t)(timer_id&0xffff); int ret; - pthread_mutex_lock (&tasks[task_id].queue_cond_lock); - ret=tasks[task_id].timer_map.erase(timer_id); - pthread_mutex_unlock (&tasks[task_id].queue_cond_lock); + pthread_mutex_lock (&tasks[task_id]->queue_cond_lock); + ret=tasks[task_id]->timer_map.erase(timer_id); + pthread_mutex_unlock (&tasks[task_id]->queue_cond_lock); if (ret==1) return 0; @@ -417,7 +431,7 @@ task_list_t tasks[TASK_MAX]; } const char *itti_get_task_name(task_id_t task_id) { - return tasks[task_id].admin.name; + return tasks[task_id]->admin.name; } // void for compatibility @@ -438,5 +452,7 @@ task_list_t tasks[TASK_MAX]; void itti_wait_ready(int wait_tasks) { // Stupid function, kept for compatibility (the parameter is meaningless!!!) } - int signal_mask(void) { return 0;} + int signal_mask(void) { + return 0; + } } diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 026c8270d7..7c17a6f3b1 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -45,7 +45,7 @@ typedef struct { uint32_t interval_sec; uint32_t interval_us; long task_id; - int32_t instance; + instance_t instance; timer_type_t type; void *timer_arg; long timer_id; @@ -230,6 +230,7 @@ typedef struct IttiMsgText_s { #include #include #include +#include #include #include #include @@ -259,7 +260,11 @@ typedef struct IttiMsgText_s { #include void *rrc_enb_process_itti_msg(void *); #include -#include +#include + +#ifdef ITTI_SIM + #include +#endif /* static const char *const messages_definition_xml = { @@ -295,7 +300,7 @@ typedef struct { //TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) //TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL) //TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL) -void * rrc_enb_process_msg(void*); +void *rrc_enb_process_msg(void *); #define FOREACH_TASK(TASK_DEF) \ TASK_DEF(TASK_UNKNOWN, TASK_PRIORITY_MED, 50, NULL, NULL) \ TASK_DEF(TASK_TIMER, TASK_PRIORITY_MED, 10, NULL, NULL) \ @@ -312,6 +317,7 @@ void * rrc_enb_process_msg(void*); TASK_DEF(TASK_RRC_GNB, TASK_PRIORITY_MED, 200, NULL,NULL)\ TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200, NULL, NULL) \ + TASK_DEF(TASK_NGAP, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_X2AP, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_M2AP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_M2AP_MCE, TASK_PRIORITY_MED, 200, NULL, NULL) \ @@ -329,13 +335,18 @@ void * rrc_enb_process_msg(void*); TASK_DEF(TASK_RLC_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_PDCP_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_RRC_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \ + TASK_DEF(TASK_RRC_NRUE, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_NAS_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_RAL_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_MSC, TASK_PRIORITY_MED, 200, NULL, NULL)\ TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)\ + TASK_DEF(OCP_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)\ TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL)\ TASK_DEF(TASK_CU_F1, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_DU_F1, TASK_PRIORITY_MED, 200, NULL, NULL) \ + TASK_DEF(TASK_RRC_UE_SIM, TASK_PRIORITY_MED, 200, NULL, NULL) \ + TASK_DEF(TASK_RRC_GNB_SIM, TASK_PRIORITY_MED, 200, NULL, NULL) \ + TASK_DEF(TASK_NAS_NRUE, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_MAX, TASK_PRIORITY_MED, 200, NULL, NULL) #define TASK_DEF(TaskID, pRIO, qUEUEsIZE, FuNc, ThreadFunc) { pRIO, qUEUEsIZE, #TaskID, FuNc, ThreadFunc }, @@ -393,7 +404,8 @@ typedef struct MessageHeader_s { MessagesIds messageId; /**< Unique message id as referenced in enum MessagesIds */ task_id_t originTaskId; /**< ID of the sender task */ task_id_t destinationTaskId; /**< ID of the destination task */ - instance_t instance; /**< Task instance for virtualization */ + instance_t originInstance; + instance_t destinationInstance; itti_lte_time_t lte_time; MessageHeaderSize ittiMsgSize; /**< Message size (not including header size) */ } MessageHeader; @@ -423,11 +435,11 @@ typedef struct MessageDef_s { /* Extract the instance from a message */ -#define ITTI_MESSAGE_GET_INSTANCE(mESSAGE) ((mESSAGE)->ittiMsgHeader.instance) #define ITTI_MSG_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.messageId) #define ITTI_MSG_ORIGIN_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.originTaskId) #define ITTI_MSG_DESTINATION_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.destinationTaskId) -#define ITTI_MSG_INSTANCE(mSGpTR) ((mSGpTR)->ittiMsgHeader.instance) +#define ITTI_MSG_ORIGIN_INSTANCE(mSGpTR) ((mSGpTR)->ittiMsgHeader.originInstance) +#define ITTI_MSG_DESTINATION_INSTANCE(mSGpTR) ((mSGpTR)->ittiMsgHeader.destinationInstance) #define ITTI_MSG_NAME(mSGpTR) itti_get_message_name(ITTI_MSG_ID(mSGpTR)) #define ITTI_MSG_ORIGIN_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_ORIGIN_ID(mSGpTR)) #define ITTI_MSG_DESTINATION_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_DESTINATION_ID(mSGpTR)) @@ -461,6 +473,9 @@ void itti_subscribe_event_fd(task_id_t task_id, int fd); void itti_unsubscribe_event_fd(task_id_t task_id, int fd); /** \brief Return the list of events excluding the fd associated with itti + \the fd associated with itti can return, but it is marked events[i].events &= ~EPOLLIN + \as it is not EPOLLIN, the reader should ignore this fd + \or it can manage the list of fd's in his interest, so ignore the other ones \param task_id Task ID of the task \param events events list @returns number of events to handle @@ -490,6 +505,8 @@ int itti_create_task(task_id_t task_id, void *(*start_routine) (void *), void *args_p); +int itti_create_queue(const task_info_t *task_info); + /** \brief Exit the current task. **/ void itti_exit_task(void); @@ -520,6 +537,7 @@ const char *itti_get_task_name(task_id_t task_id); **/ MessageDef *itti_alloc_new_message( task_id_t origin_task_id, + instance_t originInstance, MessagesIds message_id); /** \brief Alloc and memset(0) a new itti message. @@ -530,6 +548,7 @@ MessageDef *itti_alloc_new_message( **/ MessageDef *itti_alloc_new_message_sized( task_id_t origin_task_id, + instance_t originInstance, MessagesIds message_id, MessageHeaderSize size); @@ -537,7 +556,7 @@ MessageDef *itti_alloc_new_message_sized( This function should be called from the main thread after having created all ITTI tasks. **/ void itti_wait_tasks_end(void); -#define THREAD_MAX 0 //for compatibility +#define ADDED_QUEUES_MAX 10 // Fix me: MSC component too hard to understand, we keep room for 10 queues created dynamically void itti_set_task_real_time(task_id_t task_id); /** \brief Send a termination message to all tasks. @@ -551,13 +570,12 @@ void *malloc_or_fail(size_t size); int memory_read(const char *datafile, void *data, size_t size); int itti_free(task_id_t task_id, void *ptr); -int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info, - const message_info_t *messages_info); +int itti_init(task_id_t task_max, const task_info_t *tasks_info); int timer_setup( uint32_t interval_sec, uint32_t interval_us, task_id_t task_id, - int32_t instance, + instance_t instance, timer_type_t type, void *timer_arg, long *timer_id); diff --git a/common/utils/system.c b/common/utils/system.c index 1bd5c7d39b..38d1c1d7ad 100644 --- a/common/utils/system.c +++ b/common/utils/system.c @@ -96,6 +96,54 @@ static void read_pipe(int p, char *b, int size) { } } +static int baseRunTimeCommand(char* cmd, size_t cmdSize) { + FILE *fp; + size_t retSize = 0; + + fp = popen(cmd, "r"); + if(fp) { + memset(cmd, 0, cmdSize); + retSize = fread(cmd, 1, cmdSize, fp); + fclose(fp); + } else { + LOG_D(HW,"%s:%d:%s: Cannot open %s\n", __FILE__, __LINE__, __FUNCTION__, cmd); + } + + if (retSize == 0) { + return 0; + } + return atoi(cmd); +} + +int checkIfFedoraDistribution(void) { + char cmd[200]; + + memset(cmd, 0, 200); + sprintf(cmd, "cat /etc/os-release | grep ID_LIKE | grep -ic fedora || true"); + return baseRunTimeCommand(cmd, 200); +} + +int checkIfGenericKernelOnFedora(void) { + char cmd[200]; + + memset(cmd, 0, 200); + sprintf(cmd, "uname -a | grep -c rt || true"); + return (1 - baseRunTimeCommand(cmd, 200)); +} + +int checkIfInsideContainer(void) { + char cmd[200]; + int res = 0; + + memset(cmd, 0, 200); + sprintf(cmd, "cat /proc/self/cgroup | egrep -c 'libpod|podman|kubepods' || true"); + res = baseRunTimeCommand(cmd, 200); + if (res > 0) + return 1; + else + return 0; +} + /********************************************************************/ /* background process */ /********************************************************************/ @@ -161,6 +209,10 @@ int background_system(char *command) { void start_background_system(void) { int p[2]; pid_t son; + + if (module_initialized == 1) + return; + module_initialized = 1; if (pipe(p) == -1) { @@ -199,15 +251,41 @@ void start_background_system(void) { void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority){ pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); - pthread_attr_setschedpolicy(&attr, SCHED_FIFO); - struct sched_param sparam={0}; - sparam.sched_priority = priority; - pthread_attr_setschedparam(&attr, &sparam); + int ret; + int settingPriority = 1; + ret=pthread_attr_init(&attr); + AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno); + ret=pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno); + ret=pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno); + if (checkIfFedoraDistribution()) + if (checkIfGenericKernelOnFedora()) + if (checkIfInsideContainer()) + settingPriority = 0; - pthread_create(t, &attr, func, param); + if (settingPriority) { + ret=pthread_attr_setschedpolicy(&attr, SCHED_OAI); + AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno); + if(prioritysched_get_priority_max(SCHED_FIFO)) { + LOG_E(TMR,"Prio not possible: %d, min is %d, max: %d, forced in the range\n", + priority, + sched_get_priority_min(SCHED_OAI), + sched_get_priority_max(SCHED_OAI)); + if(prioritysched_get_priority_max(SCHED_OAI)) + priority=sched_get_priority_max(SCHED_OAI); + } + AssertFatal(priority<=sched_get_priority_max(SCHED_OAI),""); + struct sched_param sparam={0}; + sparam.sched_priority = priority; + ret=pthread_attr_setschedparam(&attr, &sparam); + AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno); + } + + ret=pthread_create(t, &attr, func, param); + AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno); pthread_setname_np(*t, name); if (affinity != -1 ) { @@ -216,7 +294,6 @@ void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, CPU_SET(affinity, &cpuset); AssertFatal( pthread_setaffinity_np(*t, sizeof(cpu_set_t), &cpuset) == 0, "Error setting processor affinity"); } - pthread_attr_destroy(&attr); } diff --git a/common/utils/system.h b/common/utils/system.h index a89a6c5b17..c76fef9144 100644 --- a/common/utils/system.h +++ b/common/utils/system.h @@ -46,9 +46,11 @@ void set_latency_target(void); void configure_linux(void); void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority); -#define OAI_PRIORITY_RT_LOW sched_get_priority_min(SCHED_FIFO) -#define OAI_PRIORITY_RT sched_get_priority_max(SCHED_FIFO)-10 -#define OAI_PRIORITY_RT_MAX sched_get_priority_max(SCHED_FIFO) + +#define SCHED_OAI SCHED_RR +#define OAI_PRIORITY_RT_LOW sched_get_priority_min(SCHED_OAI) +#define OAI_PRIORITY_RT ((sched_get_priority_min(SCHED_OAI)+sched_get_priority_max(SCHED_OAI))/2) +#define OAI_PRIORITY_RT_MAX sched_get_priority_max(SCHED_OAI)-2 void thread_top_init(char *thread_name, int affinity, @@ -56,6 +58,14 @@ void thread_top_init(char *thread_name, uint64_t deadline, uint64_t period); +/**************************************************** + * Functions to check system at runtime. + ****************************************************/ + +int checkIfFedoraDistribution(void); +int checkIfGenericKernelOnFedora(void); +int checkIfInsideContainer(void); + #ifdef __cplusplus } #endif diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 03f7af99bc..aab8c84368 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -62,34 +62,27 @@ #include "telnetsrv_proccmd.h" static char *telnet_defstatmod[] = {"softmodem","phy","loader","measur"}; static telnetsrv_params_t telnetparams; -#define TELNETSRV_LISTENADDR 0 -#define TELNETSRV_LISTENPORT 1 -#define TELNETSRV_PRIORITY 2 -#define TELNETSRV_DEBUG 3 -#define TELNETSRV_LOOPC 4 -#define TELNETSRV_LOOPD 5 -#define TELNETSRV_HISFILE 6 -#define TELNETSRV_HISSIZE 7 -#define TELNETSRV_PHYBSIZE 8 -#define TELNETSRV_STATICMOD 9 -#define TELNETSRV_SHRMOD 10 + +#define TELNETSRV_OPTNAME_STATICMOD "staticmod" +#define TELNETSRV_OPTNAME_SHRMOD "shrmod" paramdef_t telnetoptions[] = { - /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ - /* configuration parameters for telnet utility */ - /* optname helpstr paramflags XXXptr defXXXval type numelt */ - /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ - {"listenaddr", "\n", 0, uptr:&telnetparams.listenaddr, defstrval:"0.0.0.0", TYPE_IPV4ADDR, 0 }, - {"listenport", "\n", 0, uptr:&(telnetparams.listenport), defuintval:9090, TYPE_UINT, 0 }, - {"priority", "\n", 0, uptr:NULL, defuintval:0, TYPE_UINT, 0 }, - {"loopcount", "\n", 0, uptr:&(telnetparams.loopcount), defuintval:10, TYPE_UINT, 0 }, - {"loopdelay", "\n", 0, uptr:&(telnetparams.loopdelay), defuintval:5000, TYPE_UINT, 0 }, - {"histfile", "\n", PARAMFLAG_NOFREE, strptr:&(telnetparams.histfile), defstrval:"oaitelnet.history", TYPE_STRING, 0 }, - {"histsize", "\n", 0, iptr:&(telnetparams.histsize), defuintval:50, TYPE_INT, 0 }, - {"phypbsize", "\n",0, uptr:&(telnetparams.phyprntbuff_size),defuintval:65000, TYPE_UINT, 0 }, - {"staticmod", "\n", 0, strlistptr:NULL, defstrlistval:telnet_defstatmod,TYPE_STRINGLIST,(sizeof(telnet_defstatmod)/sizeof(char *))}, - {"shrmod", "\n", 0, strlistptr:NULL, defstrlistval:NULL,TYPE_STRINGLIST,0 } + /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + /* configuration parameters for telnet utility */ + /* optname helpstr paramflags XXXptr defXXXval type numelt */ + /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + {"listenaddr", "\n", 0, uptr:&telnetparams.listenaddr, defstrval:"0.0.0.0", TYPE_IPV4ADDR, 0 }, + {"listenport", "\n", 0, uptr:&(telnetparams.listenport), defuintval:9090, TYPE_UINT, 0 }, + {"listenstdin", "enable input from stdin\n", PARAMFLAG_BOOL, uptr:&(telnetparams.listenstdin), defuintval:0, TYPE_UINT, 0 }, + {"priority", "\n", 0, uptr:NULL, defuintval:0, TYPE_UINT, 0 }, + {"loopcount", "\n", 0, uptr:&(telnetparams.loopcount), defuintval:10, TYPE_UINT, 0 }, + {"loopdelay", "\n", 0, uptr:&(telnetparams.loopdelay), defuintval:5000, TYPE_UINT, 0 }, + {"histfile", "\n", PARAMFLAG_NOFREE, strptr:&(telnetparams.histfile), defstrval:"oaitelnet.history", TYPE_STRING, 0 }, + {"histsize", "\n", 0, iptr:&(telnetparams.histsize), defuintval:50, TYPE_INT, 0 }, + {"phypbsize", "\n",0, uptr:&(telnetparams.phyprntbuff_size),defuintval:65000, TYPE_UINT, 0 }, + {TELNETSRV_OPTNAME_STATICMOD, "\n", 0, strlistptr:NULL, defstrlistval:telnet_defstatmod,TYPE_STRINGLIST,(sizeof(telnet_defstatmod)/sizeof(char *))}, + {TELNETSRV_OPTNAME_SHRMOD, "\n", 0, strlistptr:NULL, defstrlistval:NULL,TYPE_STRINGLIST,0 } }; int get_phybsize(void) { @@ -461,12 +454,12 @@ int process_command(char *buf) { int i,j,k; char modulename[TELNET_CMD_MAXSIZE]; char cmd[TELNET_CMD_MAXSIZE]; - char cmdb[TELNET_MAX_MSGLENGTH]; + char *cmdb=NULL; char *bufbck; int rt; memset(modulename,0,sizeof(modulename)); memset(cmd,0,sizeof(cmd)); - memset(cmdb,0,sizeof(cmdb)); + if (strncasecmp(buf,"ex",2) == 0) return CMDSTATUS_EXIT; @@ -490,12 +483,10 @@ int process_command(char *buf) { return CMDSTATUS_FOUND; } - memset(modulename,0,sizeof(modulename)); - memset(cmd,0,sizeof(cmd)); - memset(cmdb,0,sizeof(cmdb)); + bufbck=strdup(buf); rt=CMDSTATUS_NOTFOUND; - j = sscanf(buf,"%19s %19s %19[^\t\n]",modulename,cmd,cmdb); + j = sscanf(buf,"%19s %19s %m[^\t\n]",modulename,cmd,&cmdb); if (telnetparams.telnetdbg > 0) printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n",j,modulename,cmd,cmdb); @@ -562,7 +553,7 @@ int process_command(char *buf) { rt= CMDSTATUS_FOUND; } /* loop */ } /* for i */ - + free(cmdb); free(bufbck); return rt; } @@ -684,6 +675,77 @@ void run_telnetsrv(void) { return; } +void run_telnetclt(void) { + int sock; + struct sockaddr_in name; + pthread_setname_np(pthread_self(), "telnetclt"); + set_sched(pthread_self(),0,telnetparams.priority); + char prompt[sizeof(TELNET_PROMPT_PREFIX)+10]; + sprintf(prompt,"%s_%s> ",TELNET_PROMPT_PREFIX,get_softmodem_function(NULL)); + name.sin_family = AF_INET; + struct in_addr addr; + inet_aton("127.0.0.1", &addr) ; + name.sin_addr.s_addr = addr.s_addr; + name.sin_port = htons((unsigned short)(telnetparams.listenport)); + while (1) { + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) + fprintf(stderr,"[TELNETSRV] Error %s on socket call\n",strerror(errno)); + + if(connect(sock, (void *) &name, sizeof(name))) + fprintf(stderr,"[TELNETSRV] Error %s on connect call\n",strerror(errno)); + + struct timeval ts; + ts.tv_sec = 1; // 1 second + ts.tv_usec = 0; + while (1) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock, &fds); + FD_SET(STDIN_FILENO , &fds); + // wait for data + int nready = select(sock + 1, &fds, (fd_set *) 0, (fd_set *) 0, &ts); + if (nready < 0) { + perror("select. Error"); + break; + } + else if (nready == 0) { + ts.tv_sec = 1; // 1 second + ts.tv_usec = 0; + } + else if ( FD_ISSET(sock, &fds)) { + int rv; + char inbuf[TELNET_MAX_MSGLENGTH*2]; + memset(inbuf,0,sizeof(inbuf)); + rv = recv(sock , inbuf , sizeof(inbuf)-1 , 0); + if (rv > 0) { + printf("%s",inbuf); + } + else if (rv == 0) { + printf("Connection closed by the remote end\n\r"); + break; + } + else { + perror("recv error"); + break; + } + } + else if (FD_ISSET(STDIN_FILENO , &fds)) { + char *inbuf=NULL; + size_t inlen=0; + inlen = getline( &inbuf,&inlen, stdin); + if ( inlen > 0 ) { + if ( send(sock, inbuf,inlen, 0) < 0) + break; + } + free(inbuf); + } + } + close(sock); + } + return; +} /* run_telnetclt */ + void poll_telnetcmdq(void *qid, void *arg) { notifiedFIFO_elt_t *msg = pollNotifiedFIFO((notifiedFIFO_t *)qid); @@ -702,7 +764,7 @@ void poll_telnetcmdq(void *qid, void *arg) { */ void exec_moduleinit(char *modname) { void (*fptr)(void); - char initfunc[TELNET_CMD_MAXSIZE+9]; + char initfunc[TELNET_CMD_MAXSIZE+10]; if (strlen(modname) > TELNET_CMD_MAXSIZE) { fprintf(stderr,"[TELNETSRV] module %s not loaded, name exceeds the %i size limit\n", @@ -722,10 +784,10 @@ void exec_moduleinit(char *modname) { int add_embeddedmodules(void) { int ret=0; - - for(int i=0; i #define TELNETSRV_MODNAME "telnetsrv" #define TELNET_PORT 9090 @@ -107,6 +108,7 @@ typedef struct cmdparser { /* global variables used by the telnet server */ typedef struct { pthread_t telnet_pthread; // thread id of the telnet server + pthread_t telnetclt_pthread; // thread id of the telnet client (used when listenstdin set to true) int telnetdbg; // debug level of the server int priority; // server running priority char *histfile; // command history @@ -118,6 +120,7 @@ typedef struct { char msgbuff[TELNET_MAX_MSGLENGTH]; // internal buffer of the client_printf function which is used to print to the client terminal */ unsigned int listenport; // ip port the telnet server is listening on unsigned int listenaddr; // ip address the telnet server is listening on + unsigned int listenstdin; // enable command input from stdin unsigned int loopcount; // loop command param: number of loop iteration unsigned int loopdelay; // loop command param: delay in ms between 2 iterations unsigned int phyprntbuff_size; // for phy module, dump_eNB_stats function buffer size diff --git a/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c b/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c new file mode 100644 index 0000000000..a8925a2df9 --- /dev/null +++ b/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c @@ -0,0 +1,178 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file common/utils/telnetsrv/telnetsrv_nrue_measurements.c + * \brief: implementation of telnet commands related to nrUE measurments + * \author Francois TABURET + * \date 2021 + * \version 0.1 + * \company NOKIA BellLabs France + * \email: francois.taburet@nokia-bell-labs.com + * \note + * \warning + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + + + + +#define TELNETSERVERCODE +#include "telnetsrv.h" + +#include "common/utils/LOG/log.h" +#include "common/config/config_userapi.h" +#include "telnetsrv_measurements.h" +#include "telnetsrv_ltemeasur_def.h" +#include "telnetsrv_cpumeasur_def.h" +#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h" +#include "openair1/PHY/phy_extern_nr_ue.h" + +void measurcmd_display_macstats(telnet_printfunc_t prnt); +void measurcmd_display_macstats_ue(telnet_printfunc_t prnt); +void measurcmd_display_rlcstats(telnet_printfunc_t prnt); +void measurcmd_display_phycpu(telnet_printfunc_t prnt); +void measurcmd_display_maccpu(telnet_printfunc_t prnt); +void measurcmd_display_pdcpcpu(telnet_printfunc_t prnt); + + +static telnet_measurgroupdef_t nrUEmeasurgroups[] = { +// {"ue", GROUP_LTESTATS,0, measurcmd_display_macstats, {NULL}}, +// {"rlc", GROUP_LTESTATS,0, measurcmd_display_rlcstats, {NULL}}, + {"phycpu",GROUP_CPUSTATS,0, measurcmd_display_phycpu, {NULL}}, +// {"maccpu",GROUP_CPUSTATS,0, measurcmd_display_maccpu, {NULL}}, +// {"pdcpcpu",GROUP_CPUSTATS,0, measurcmd_display_pdcpcpu, {NULL}}, +}; +#define TELNET_NUM_NRUEMEASURGROUPS (sizeof(nrUEmeasurgroups)/sizeof(telnet_measurgroupdef_t)) + + +static double cpufreq; + + +#define HDR "---------------------------------" + + +int get_measurgroups(telnet_measurgroupdef_t **measurgroups) { + *measurgroups = nrUEmeasurgroups; + return TELNET_NUM_NRUEMEASURGROUPS; +} + + +void measurcmd_display_phycpu(telnet_printfunc_t prnt) { + PHY_VARS_NR_UE *UE = PHY_vars_UE_g[0][0]; + telnet_cpumeasurdef_t cpumeasur[]=CPU_PHYNRUE_MEASURE; + prnt("%s cpu (%1.1g GHz) measurements: PHY (cpustats %s) %s\n",HDR,cpufreq, + PRINT_CPUMEAS_STATE,HDR); + measurcmd_display_cpumeasures(prnt, cpumeasur, sizeof(cpumeasur)/sizeof(telnet_cpumeasurdef_t)); +} +/* +void measurcmd_display_maccpu(telnet_printfunc_t prnt) { + eNB_MAC_INST *macvars = RC.mac[eNB_id]; + telnet_cpumeasurdef_t cpumeasur[]=CPU_MACENB_MEASURE; + prnt("%s cpu (%1.1g GHz) measurements: MAC (cpustats %s) %s\n",HDR,cpufreq, + PRINT_CPUMEAS_STATE,HDR); + measurcmd_display_cpumeasures(prnt, cpumeasur, sizeof(cpumeasur)/sizeof(telnet_cpumeasurdef_t)); +} + +void measurcmd_display_pdcpcpu(telnet_printfunc_t prnt) { + pdcp_stats_t *pdcpvars = &(eNB_pdcp_stats[eNB_id]); + telnet_cpumeasurdef_t cpumeasur[]=CPU_PDCPENB_MEASURE; + prnt("%s cpu (%1.1g GHz) measurements: PDCP (cpustats %s) %s \n",HDR,cpufreq, + PRINT_CPUMEAS_STATE,HDR); + measurcmd_display_cpumeasures(prnt, cpumeasur, sizeof(cpumeasur)/sizeof(telnet_cpumeasurdef_t)); +} +//---------------------------------------------------------------------------------------------------- + + +void measurcmd_display_macstats_ue(telnet_printfunc_t prnt) { + UE_info_t *UE_info = &(RC.mac[eNB_id]->UE_info); + + for (int UE_id=UE_info->list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) { + for (int i=0; inumactiveCCs[UE_id]; i++) { + int CC_id = UE_info->ordered_CCids[i][UE_id]; + prnt("%s UE %i Id %i CCid %i %s\n",HDR,i,UE_id,CC_id,HDR); + eNB_UE_STATS *macuestatptr = &(UE_info->eNB_UE_stats[CC_id][UE_id]); + telnet_ltemeasurdef_t statsptr[]=LTEMAC_UEMEASURE; + measurcmd_display_measures(prnt, statsptr, sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t)); + } + } +} // measurcmd_display_macstats_ue + +void measurcmd_display_macstats(telnet_printfunc_t prnt) { + for (int CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) { + eNB_STATS *macstatptr=&(RC.mac[eNB_id]->eNB_stats[CC_id]); + telnet_ltemeasurdef_t statsptr[]=LTEMAC_MEASURE; + prnt("%s eNB %i mac stats CC %i frame %u %s\n", + HDR, eNB_id, CC_id, RC.mac[eNB_id]->frame,HDR); + measurcmd_display_measures(prnt,statsptr,sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t)); + } +} // measurcmd_display_macstats + + +void measurcmd_display_one_rlcstat(telnet_printfunc_t prnt, int UE_id, telnet_ltemeasurdef_t *statsptr, int num_rlcmeasure, unsigned int *rlcstats, + char *rbid_str, protocol_ctxt_t *ctxt, const srb_flag_t srb_flagP, const rb_id_t rb_idP) + +{ + int rlc_status = rlc_stat_req(ctxt,srb_flagP,rb_idP, + rlcstats, rlcstats+1, rlcstats+2, rlcstats+3, rlcstats+4, rlcstats+5, + rlcstats+6, rlcstats+7, rlcstats+8, rlcstats+9, rlcstats+10, rlcstats+11, + rlcstats+12, rlcstats+13, rlcstats+14, rlcstats+15, rlcstats+16, rlcstats+17, + rlcstats+18, rlcstats+19, rlcstats+20, rlcstats+21, rlcstats+22, rlcstats+23, + rlcstats+24, rlcstats+25, rlcstats+26, rlcstats+27); + + if (rlc_status == RLC_OP_STATUS_OK) { + prnt("%s UE %i RLC %s mode %s %s\n",HDR,UE_id, rbid_str, + (rlcstats[0]==RLC_MODE_AM)? "AM": (rlcstats[0]==RLC_MODE_UM)?"UM":"NONE",HDR); + measurcmd_display_measures(prnt, statsptr, num_rlcmeasure); + } +} // status measurcmd_rlc_stat_req + + +void measurcmd_display_rlcstats(telnet_printfunc_t prnt) { + protocol_ctxt_t ctxt; + UE_info_t *UE_info = &(RC.mac[eNB_id]->UE_info); + telnet_ltemeasurdef_t statsptr[]=LTE_RLCMEASURE; + int num_rlcmeasure = sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t ); + unsigned int *rlcstats = malloc(num_rlcmeasure*sizeof(unsigned int)); + eNB_MAC_INST *eNB = RC.mac[eNB_id]; + + for(int i=0; i list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) { +#define NB_eNB_INST 1 + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,eNB_id, ENB_FLAG_YES,UE_info->eNB_UE_stats[0][UE_id].crnti, + eNB->frame,eNB->subframe,eNB_id); + measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DCCH", &ctxt, SRB_FLAG_YES, DCCH); + measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DTCH", &ctxt, SRB_FLAG_NO, DTCH-2); + } +} // measurcmd_display_macstats_ue + +*/ + + diff --git a/common/utils/telnetsrv/telnetsrv_CMakeLists.txt b/common/utils/telnetsrv/telnetsrv_CMakeLists.txt index 519a1a72ff..2713c71cc0 100644 --- a/common/utils/telnetsrv/telnetsrv_CMakeLists.txt +++ b/common/utils/telnetsrv/telnetsrv_CMakeLists.txt @@ -8,9 +8,9 @@ set(TELNETSRV_SOURCE ) add_library(telnetsrv MODULE ${TELNETSRV_SOURCE} ) -target_link_libraries(telnetsrv PRIVATE history) +target_link_libraries(telnetsrv PRIVATE history ncurses form ) -foreach(TELNETLIB enb gnb 4gUE 5gUE) +foreach(TELNETLIB enb gnb 4Gue 5Gue) set(TELNETLIB_SRCS "") foreach(TELNETLIB_ASRC measurements phycmd) set(TELNETLIB_SRC ${OPENAIR_DIR}/common/utils/telnetsrv/telnetsrv_${TELNETLIB}_${TELNETLIB_ASRC}.c) @@ -32,4 +32,4 @@ install(TARGETS telnetsrv DESTINATION bin) if (EXISTS "${OPENAIR_BUILD_DIR}/ran_build/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/ran_build/build") install(TARGETS telnetsrv DESTINATION ${OPENAIR_BUILD_DIR}/ran_build/build) -endif (EXISTS "${OPENAIR_BUILD_DIR}/ran_build/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/ran_build/build") \ No newline at end of file +endif (EXISTS "${OPENAIR_BUILD_DIR}/ran_build/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/ran_build/build") diff --git a/common/utils/telnetsrv/telnetsrv_cpumeasur_def.h b/common/utils/telnetsrv/telnetsrv_cpumeasur_def.h index 7a45b351f3..a275272e80 100644 --- a/common/utils/telnetsrv/telnetsrv_cpumeasur_def.h +++ b/common/utils/telnetsrv/telnetsrv_cpumeasur_def.h @@ -24,8 +24,8 @@ * \ strucures arrays which are then used by the display functions * \ in telnetsrv_measurements.c. * \author Francois TABURET - * \date 2019 - * \version 0.1 + * \date 2021 + * \version 0.2 * \company NOKIA BellLabs France * \email: francois.taburet@nokia-bell-labs.com * \note @@ -37,67 +37,119 @@ #define CPU_PHYENB_MEASURE \ { \ - {"phy_proc_tx", &(phyvars->phy_proc_tx),0},\ - {"phy_proc_rx", &(phyvars->phy_proc_rx),0},\ - {"rx_prach", &(phyvars->rx_prach),0},\ - {"ofdm_mod", &(phyvars->ofdm_mod_stats),0},\ - {"dlsch_common_and_dci", &(phyvars->dlsch_common_and_dci),0},\ - {"dlsch_ue_specific", &(phyvars->dlsch_ue_specific),0},\ - {"dlsch_encoding", &(phyvars->dlsch_encoding_stats),0},\ - {"dlsch_modulation", &(phyvars->dlsch_modulation_stats),0},\ - {"dlsch_scrambling", &(phyvars->dlsch_scrambling_stats),0},\ - {"dlsch_rate_matching", &(phyvars->dlsch_rate_matching_stats),0},\ - {"dlsch_turbo_encod_prep", &(phyvars->dlsch_turbo_encoding_preperation_stats),0},\ - {"dlsch_turbo_encod_segm", &(phyvars->dlsch_turbo_encoding_segmentation_stats),0},\ - {"dlsch_turbo_encod", &(phyvars->dlsch_turbo_encoding_stats),0},\ - {"dlsch_turbo_encod_waiting", &(phyvars->dlsch_turbo_encoding_waiting_stats),0},\ - {"dlsch_turbo_encod_signal", &(phyvars->dlsch_turbo_encoding_signal_stats),0},\ - {"dlsch_turbo_encod_main", &(phyvars->dlsch_turbo_encoding_main_stats),0},\ - {"dlsch_turbo_encod_wakeup0", &(phyvars->dlsch_turbo_encoding_wakeup_stats0),0},\ - {"dlsch_turbo_encod_wakeup1", &(phyvars->dlsch_turbo_encoding_wakeup_stats1),0},\ - {"dlsch_interleaving", &(phyvars->dlsch_interleaving_stats),0},\ - {"rx_dft", &(phyvars->rx_dft_stats),0},\ - {"ulsch_channel_estimation", &(phyvars->ulsch_channel_estimation_stats),0},\ - {"ulsch_freq_offset_estimation", &(phyvars->ulsch_freq_offset_estimation_stats),0},\ - {"ulsch_decoding", &(phyvars->ulsch_decoding_stats),0},\ - {"ulsch_demodulation", &(phyvars->ulsch_demodulation_stats),0},\ - {"ulsch_rate_unmatching", &(phyvars->ulsch_rate_unmatching_stats),0},\ - {"ulsch_turbo_decoding", &(phyvars->ulsch_turbo_decoding_stats),0},\ - {"ulsch_deinterleaving", &(phyvars->ulsch_deinterleaving_stats),0},\ - {"ulsch_demultiplexing", &(phyvars->ulsch_demultiplexing_stats),0},\ - {"ulsch_llr", &(phyvars->ulsch_llr_stats),0},\ - {"ulsch_tc_init", &(phyvars->ulsch_tc_init_stats),0},\ - {"ulsch_tc_alpha", &(phyvars->ulsch_tc_alpha_stats),0},\ - {"ulsch_tc_beta", &(phyvars->ulsch_tc_beta_stats),0},\ - {"ulsch_tc_gamma", &(phyvars->ulsch_tc_gamma_stats),0},\ - {"ulsch_tc_ext", &(phyvars->ulsch_tc_ext_stats),0},\ - {"ulsch_tc_intl1", &(phyvars->ulsch_tc_intl1_stats),0},\ - {"ulsch_tc_intl2", &(phyvars->ulsch_tc_intl2_stats),0},\ + {"phy_proc_tx", &(phyvars->phy_proc_tx),0,1},\ + {"phy_proc_rx", &(phyvars->phy_proc_rx),0,1},\ + {"rx_prach", &(phyvars->rx_prach),0,1},\ + {"ofdm_mod", &(phyvars->ofdm_mod_stats),0,1},\ + {"dlsch_common_and_dci", &(phyvars->dlsch_common_and_dci),0,1},\ + {"dlsch_ue_specific", &(phyvars->dlsch_ue_specific),0,1},\ + {"dlsch_encoding", &(phyvars->dlsch_encoding_stats),0,1},\ + {"dlsch_modulation", &(phyvars->dlsch_modulation_stats),0,1},\ + {"dlsch_scrambling", &(phyvars->dlsch_scrambling_stats),0,1},\ + {"dlsch_rate_matching", &(phyvars->dlsch_rate_matching_stats),0,1},\ + {"dlsch_turbo_encod_prep", &(phyvars->dlsch_turbo_encoding_preperation_stats),0,1},\ + {"dlsch_turbo_encod_segm", &(phyvars->dlsch_turbo_encoding_segmentation_stats),0,1},\ + {"dlsch_turbo_encod", &(phyvars->dlsch_turbo_encoding_stats),0,1},\ + {"dlsch_turbo_encod_waiting", &(phyvars->dlsch_turbo_encoding_waiting_stats),0,1},\ + {"dlsch_turbo_encod_signal", &(phyvars->dlsch_turbo_encoding_signal_stats),0,1},\ + {"dlsch_turbo_encod_main", &(phyvars->dlsch_turbo_encoding_main_stats),0,1},\ + {"dlsch_turbo_encod_wakeup0", &(phyvars->dlsch_turbo_encoding_wakeup_stats0),0,1},\ + {"dlsch_turbo_encod_wakeup1", &(phyvars->dlsch_turbo_encoding_wakeup_stats1),0,1},\ + {"dlsch_interleaving", &(phyvars->dlsch_interleaving_stats),0,1},\ + {"rx_dft", &(phyvars->rx_dft_stats),0,1},\ + {"ulsch_channel_estimation", &(phyvars->ulsch_channel_estimation_stats),0,1},\ + {"ulsch_freq_offset_estimation", &(phyvars->ulsch_freq_offset_estimation_stats),0,1},\ + {"ulsch_decoding", &(phyvars->ulsch_decoding_stats),0,1},\ + {"ulsch_demodulation", &(phyvars->ulsch_demodulation_stats),0,1},\ + {"ulsch_rate_unmatching", &(phyvars->ulsch_rate_unmatching_stats),0,1},\ + {"ulsch_turbo_decoding", &(phyvars->ulsch_turbo_decoding_stats),0,1},\ + {"ulsch_deinterleaving", &(phyvars->ulsch_deinterleaving_stats),0,1},\ + {"ulsch_demultiplexing", &(phyvars->ulsch_demultiplexing_stats),0,1},\ + {"ulsch_llr", &(phyvars->ulsch_llr_stats),0,1},\ + {"ulsch_tc_init", &(phyvars->ulsch_tc_init_stats),0,1},\ + {"ulsch_tc_alpha", &(phyvars->ulsch_tc_alpha_stats),0,1},\ + {"ulsch_tc_beta", &(phyvars->ulsch_tc_beta_stats),0,1},\ + {"ulsch_tc_gamma", &(phyvars->ulsch_tc_gamma_stats),0,1},\ + {"ulsch_tc_ext", &(phyvars->ulsch_tc_ext_stats),0,1},\ + {"ulsch_tc_intl1", &(phyvars->ulsch_tc_intl1_stats),0,1},\ + {"ulsch_tc_intl2", &(phyvars->ulsch_tc_intl2_stats),0,1},\ } #define CPU_MACENB_MEASURE \ { \ - {"eNB_scheduler", &(macvars->eNB_scheduler),0},\ - {"schedule_si", &(macvars->schedule_si),0},\ - {"schedule_ra", &(macvars->schedule_ra),0},\ - {"schedule_ulsch", &(macvars->schedule_ulsch),0},\ - {"fill_DLSCH_dci", &(macvars->fill_DLSCH_dci),0},\ - {"schedule_dlsch_pre", &(macvars->schedule_dlsch_preprocessor),0},\ - {"schedule_dlsch", &(macvars->schedule_dlsch),0},\ - {"schedule_mch", &(macvars->schedule_mch),0},\ - {"rx_ulsch_sdu", &(macvars->rx_ulsch_sdu),0},\ - {"schedule_pch", &(macvars->schedule_pch),0},\ + {"eNB_scheduler", &(macvars->eNB_scheduler),0,1},\ + {"schedule_si", &(macvars->schedule_si),0,1},\ + {"schedule_ra", &(macvars->schedule_ra),0,1},\ + {"schedule_ulsch", &(macvars->schedule_ulsch),0,1},\ + {"fill_DLSCH_dci", &(macvars->fill_DLSCH_dci),0,1},\ + {"schedule_dlsch_pre", &(macvars->schedule_dlsch_preprocessor),0,1},\ + {"schedule_dlsch", &(macvars->schedule_dlsch),0,1},\ + {"schedule_mch", &(macvars->schedule_mch),0,1},\ + {"rx_ulsch_sdu", &(macvars->rx_ulsch_sdu),0,1},\ + {"schedule_pch", &(macvars->schedule_pch),0,1},\ } #define CPU_PDCPENB_MEASURE \ { \ - {"pdcp_run", &(pdcpvars->pdcp_run),0},\ - {"data_req", &(pdcpvars->data_req),0},\ - {"data_ind", &(pdcpvars->data_ind),0},\ - {"apply_security", &(pdcpvars->apply_security),0},\ - {"validate_security", &(pdcpvars->validate_security),0},\ - {"pdcp_ip", &(pdcpvars->pdcp_ip),0},\ - {"ip_pdcp", &(pdcpvars->ip_pdcp),0},\ + {"pdcp_run", &(pdcpvars->pdcp_run),0,1},\ + {"data_req", &(pdcpvars->data_req),0,1},\ + {"data_ind", &(pdcpvars->data_ind),0,1},\ + {"apply_security", &(pdcpvars->apply_security),0,1},\ + {"validate_security", &(pdcpvars->validate_security),0,1},\ + {"pdcp_ip", &(pdcpvars->pdcp_ip),0,1},\ + {"ip_pdcp", &(pdcpvars->ip_pdcp),0,1},\ } +/* from openair1/PHY/defs_nr_UE.h */ +#define CPU_PHYNRUE_MEASURE \ +{ \ + {"phy_proc", &(UE->phy_proc[0]),0,RX_NB_TH},\ + {"phy_proc_rx", &(UE-> phy_proc_rx[0]),0,RX_NB_TH},\ + {"phy_proc_tx", &(UE->phy_proc_tx),0,1},\ + {"ofdm_mod_stats", &(UE->ofdm_mod_stats),0,1},\ + {"ulsch_encoding_stats", &(UE->ulsch_encoding_stats),0,1},\ + {"ulsch_modulation_stats", &(UE->ulsch_modulation_stats),0,1},\ + {"ulsch_segmentation_stats", &(UE->ulsch_segmentation_stats),0,1},\ + {"ulsch_rate_matching_stats", &(UE->ulsch_rate_matching_stats),0,1},\ + {"ulsch_turbo_encoding_stats", &(UE->ulsch_turbo_encoding_stats),0,1},\ + {"ulsch_interleaving_stats", &(UE->ulsch_interleaving_stats),0,1},\ + {"ulsch_multiplexing_stats", &(UE->ulsch_multiplexing_stats),0,1},\ + {"generic_stat", &(UE->generic_stat),0,1},\ + {"generic_stat_bis", &(UE->generic_stat_bis[0][0]),0,RX_NB_TH,LTE_SLOTS_PER_SUBFRAME},\ + {"ofdm_demod_stats", &(UE->ofdm_demod_stats),0,1},\ + {"dlsch_rx_pdcch_stats", &(UE->dlsch_rx_pdcch_stats),0,1},\ + {"rx_dft_stats", &(UE->rx_dft_stats),0,1},\ + {"dlsch_c...timation_stats", &(UE->dlsch_channel_estimation_stats),0,1},\ + {"dlsch_f...timation_stats", &(UE->dlsch_freq_offset_estimation_stats),0,1},\ + {"dlsch_demodulation_stats", &(UE->dlsch_demodulation_stats),0,1},\ + {"dlsch_rate_unmatching_stats", &(UE->dlsch_rate_unmatching_stats),0,1},\ + {"dlsch_turbo_decoding_stats", &(UE->dlsch_turbo_decoding_stats),0,1},\ + {"dlsch_deinterleaving_stats", &(UE->dlsch_deinterleaving_stats),0,1},\ + {"dlsch_llr_stats", &(UE->dlsch_llr_stats),0,1},\ + {"dlsch_unscrambling_stats", &(UE->dlsch_unscrambling_stats),0,1},\ + {"dlsch_rate_matching_stats", &(UE->dlsch_rate_matching_stats),0,1},\ + {"dlsch_turbo_encoding_stats", &(UE->dlsch_turbo_encoding_stats),0,1},\ + {"dlsch_interleaving_stats", &(UE->dlsch_interleaving_stats),0,1},\ + {"dlsch_tc_init_stats", &(UE->dlsch_tc_init_stats),0,1},\ + {"dlsch_tc_alpha_stats", &(UE->dlsch_tc_alpha_stats),0,1},\ + {"dlsch_tc_beta_stats", &(UE->dlsch_tc_beta_stats),0,1},\ + {"dlsch_tc_gamma_stats", &(UE->dlsch_tc_gamma_stats),0,1},\ + {"dlsch_tc_ext_stats", &(UE->dlsch_tc_ext_stats),0,1},\ + {"dlsch_tc_intl1_stats", &(UE->dlsch_tc_intl1_stats),0,1},\ + {"dlsch_tc_intl2_stats", &(UE->dlsch_tc_intl2_stats),0,1},\ + {"tx_prach", &(UE->tx_prach),0,1},\ + {"dlsch_encoding_SIC_stats", &(UE->dlsch_encoding_SIC_stats),0,1},\ + {"dlsch_scrambling_SIC_stats", &(UE->dlsch_scrambling_SIC_stats),0,1},\ + {"dlsch_modulation_SIC_stats", &(UE->dlsch_modulation_SIC_stats),0,1},\ + {"dlsch...ping_unit_SIC_stats", &(UE->dlsch_llr_stripping_unit_SIC_stats),0,1},\ + {"dlsch_unscrambling_SIC_stats", &(UE->dlsch_unscrambling_SIC_stats),0,1},\ + {"ue_front_end_stat", &(UE->ue_front_end_stat[0]),0,RX_NB_TH},\ + {"ue_front_end_per_slot_stat", &(UE->ue_front_end_per_slot_stat[0][0]),0,RX_NB_TH,LTE_SLOTS_PER_SUBFRAME},\ + {"pdcch_procedures_stat", &(UE->pdcch_procedures_stat[0]),0,RX_NB_TH},\ + {"pdsch_procedures_stat", &(UE->pdsch_procedures_stat[0]),0,RX_NB_TH},\ + {"pdsch_procedures_per_slot_stat", &(UE->pdsch_procedures_per_slot_stat[0][0]),0,RX_NB_TH,LTE_SLOTS_PER_SUBFRAME},\ + {"dlsch_procedures_stat", &(UE->dlsch_procedures_stat[0]),0,RX_NB_TH},\ + {"dlsch_decoding_stats", &(UE->dlsch_decoding_stats[0]),0,RX_NB_TH},\ + {"dlsch_llr_stats_para", &(UE->dlsch_llr_stats_parallelization[0][0]),0,RX_NB_TH,LTE_SLOTS_PER_SUBFRAME},\ +} #endif diff --git a/common/utils/telnetsrv/telnetsrv_measurements.c b/common/utils/telnetsrv/telnetsrv_measurements.c index 4a11e7c2dd..786cbd094c 100644 --- a/common/utils/telnetsrv/telnetsrv_measurements.c +++ b/common/utils/telnetsrv/telnetsrv_measurements.c @@ -64,13 +64,30 @@ void measurcmd_display_groups(telnet_printfunc_t prnt,telnet_measurgroupdef_t *m } /* measurcmd_display_groups */ /*----------------------------------------------------------------------------------------------------*/ /* cpu measurements functions */ -void measurcmd_display_cpumeasures(telnet_printfunc_t prnt, telnet_cpumeasurdef_t *cpumeasure, int cpumeasure_size) { - for (int i=0; istatname, - ((cpumeasure+i)->astatptr->trials!=0)?(((cpumeasure+i)->astatptr->diff)/((cpumeasure+i)->astatptr->trials))/cpufreq/1000:0, - (cpumeasure+i)->astatptr->trials, ((i%2)==1)?"|\n":" | " ); - } + +static char *stridx(int max,int i, char *buff) { + if (max>1) + sprintf(buff,"[%d]",i); + else + sprintf(buff," "); + return buff; + +} +void measurcmd_display_cpumeasures(telnet_printfunc_t prnt, telnet_cpumeasurdef_t *cpumeasure, int cpumeasure_size) { + int p=0; + char stridx1[16]; + char stridx2[16]; + for (int i=0; istatname, + stridx(cpumeasure[i].num_occur1,o1,stridx1),stridx(cpumeasure[i].num_occur2,o2,stridx2), + ((cpumeasure+i+o1+o2)->astatptr->trials!=0)?(((cpumeasure+i+o1+o2)->astatptr->diff)/((cpumeasure+i+o1+o2)->astatptr->trials))/cpufreq/1000:0, + (cpumeasure+i+o1+o2)->astatptr->trials, ((p%2)==1)?"|\n":" | " ); + p++; + } prnt("\n\n"); } /* measurcmd_display_measures */ @@ -137,11 +154,17 @@ int measurcmd_show(char *buf, int debug, telnet_printfunc_t prnt) { } telnet_measurgroupdef_t *measurgroups; int num_measurgroups = fptr( &measurgroups); - + int s = sscanf(buf,"%ms %i-%i\n",&subcmd, &idx1,&idx2); if (s>0) { - if ( strcmp(subcmd,"groups") == 0) { + if ( strcmp(subcmd,"inq") == 0) { + notifiedFIFO_elt_t *msg =newNotifiedFIFO_elt(sizeof(time_stats_msg_t),0,NULL,NULL); + time_stats_msg_t *msgdata=NotifiedFifoData(msg); + msgdata->msgid = TIMESTAT_MSGID_DISPLAY; + msgdata->displayFunc = prnt; + pushNotifiedFIFO(&measur_fifo, msg); + } else if ( strcmp(subcmd,"groups") == 0){ measurcmd_display_groups(prnt,measurgroups,num_measurgroups); badcmd=0; } else { @@ -182,13 +205,13 @@ int measurcmd_cpustats(char *buf, int debug, telnet_printfunc_t prnt) { int badcmd=1; if (debug > 0) - prnt(" measurcmd_show received %s\n",buf); + prnt(" measurcmd_cpustats received %s\n",buf); int s = sscanf(buf,"%ms %i-%i\n",&subcmd, &idx1,&idx2); if (s>0) { if ( strcmp(subcmd,"enable") == 0) { - cpumeas(CPUMEAS_ENABLE); + badcmd=0; } else if ( strcmp(subcmd,"disable") == 0) { cpumeas(CPUMEAS_DISABLE); @@ -203,6 +226,64 @@ int measurcmd_cpustats(char *buf, int debug, telnet_printfunc_t prnt) { free(subcmd); return CMDSTATUS_FOUND; } + +void measurcmd_async_help(telnet_printfunc_t prnt) { +} + +int measurcmd_async(char *buf, int debug, telnet_printfunc_t prnt) { + char *subcmd=NULL; + int idx1, idx2; + int okcmd=0; + + if (buf == NULL) { + measurcmd_async_help(prnt); + return CMDSTATUS_FOUND; + } + if (debug > 0) + prnt(" measurcmd_async received %s\n",buf); + + + int s = sscanf(buf,"%ms %i-%i\n",&subcmd, &idx1,&idx2); + + if (s==1) { + if ( strcmp(subcmd,"enable") == 0) { + init_meas(); + okcmd=1; + } else if ( strcmp(subcmd,"disable") == 0) { + end_meas(); + okcmd=1; + } + } else if ( s == 3 ) { + int msgid; + if ( strcmp(subcmd,"enable") == 0) { + msgid = TIMESTAT_MSGID_ENABLE; + okcmd=1; + } else if ( strcmp(subcmd,"disable") == 0) { + msgid = TIMESTAT_MSGID_DISABLE; + okcmd=1; + } else if ( strcmp(subcmd,"display") == 0) { + msgid = TIMESTAT_MSGID_DISPLAY; + okcmd=1; + } + if (okcmd) { + notifiedFIFO_elt_t *nfe = newNotifiedFIFO_elt(sizeof(time_stats_msg_t),0,NULL,NULL); + time_stats_msg_t *msg = (time_stats_msg_t *)NotifiedFifoData(nfe); + msg->msgid = msgid ; + msg->displayFunc = prnt; + for(int i=idx1; itimestat_id =i; + pushNotifiedFIFO(&measur_fifo, nfe); + } + } + } + + if (!(okcmd)) { + prnt("Unknown command: %s\n",buf); + } + + free(subcmd); + return CMDSTATUS_FOUND; +} /*-------------------------------------------------------------------------------------*/ /* function called at telnet server init to add the measur command */ diff --git a/common/utils/telnetsrv/telnetsrv_measurements.h b/common/utils/telnetsrv/telnetsrv_measurements.h index 08136df0fd..99ae695f41 100644 --- a/common/utils/telnetsrv/telnetsrv_measurements.h +++ b/common/utils/telnetsrv/telnetsrv_measurements.h @@ -49,6 +49,9 @@ typedef struct cpumeasurdef { char statname[TELNET_MAXMEASURNAME_LEN]; time_stats_t *astatptr; unsigned int statemask; + uint8_t num_occur1; + uint8_t num_occur2; + uint8_t num_occur3; } telnet_cpumeasurdef_t; typedef struct ltemeasurdef { @@ -60,6 +63,7 @@ typedef struct ltemeasurdef { #define GROUP_LTESTATS 0 #define GROUP_CPUSTATS 1 + typedef void(*measur_dislayfunc_t)(telnet_printfunc_t prnt); typedef struct mesurgroupdef { char groupname[TELNET_MAXMEASURNAME_LEN]; @@ -79,9 +83,11 @@ typedef struct mesurgroupdef { #ifdef TELNETSRV_MEASURMENTS_MAIN int measurcmd_show(char *buf, int debug, telnet_printfunc_t prnt); int measurcmd_cpustats(char *buf, int debug, telnet_printfunc_t prnt); +int measurcmd_async(char *buf, int debug, telnet_printfunc_t prnt); telnetshell_cmddef_t measur_cmdarray[] = { - {"show", "groups | " , measurcmd_show}, + {"show", "groups | | inq" , measurcmd_show}, {"cpustats","[enable | disable]",measurcmd_cpustats}, + {"async","[enable | disable]",measurcmd_async}, {"","",NULL} }; diff --git a/common/utils/telnetsrv/telnetsrv_proccmd.c b/common/utils/telnetsrv/telnetsrv_proccmd.c index 9dd512091d..6a0da678e2 100644 --- a/common/utils/telnetsrv/telnetsrv_proccmd.c +++ b/common/utils/telnetsrv/telnetsrv_proccmd.c @@ -121,9 +121,11 @@ char toksep[2]; case SCHED_RR: lptr+=sprintf(lptr,"%s ","rt: rr"); break; +#ifdef SCHED_DEADLINE case SCHED_DEADLINE: lptr+=sprintf(lptr,"%s ","rt: deadline"); break; +#endif default: lptr+=sprintf(lptr,"%s ","????"); break; diff --git a/common/utils/threadPool/Makefile b/common/utils/threadPool/Makefile index 6b28eb2ba8..729f9dd0e2 100644 --- a/common/utils/threadPool/Makefile +++ b/common/utils/threadPool/Makefile @@ -1,13 +1,3 @@ -all: -measurement_display thread-pool-test - -measurement_display: -measurement_display.c thread-pool.h -gcc measurement_display.c -I $ {OPENAIR_DIR}/ -I $ {OPENAIR_DIR}/common/utils/ -I. $ {OPENAIR_DIR}/common/utils/backtrace.c -lpthread -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o -measurement_display - -thread-pool-test: -thread-pool.c thread-pool.h -gcc -g thread-pool.c -I $ {OPENAIR_DIR}/ -I $ {OPENAIR_DIR}/common/utils/ -I. $ {OPENAIR_DIR}/common/utils/backtrace.c -I $ {OPENAIR_DIR}/openair2/COMMON $ {OPENAIR_DIR}/common/utils/LOG/log.c $ {OPENAIR_DIR}/common/config/config_userapi.c -$ {OPENAIR_DIR}/common/config/config_load_configmodule.c $ {OPENAIR_DIR}/common/config/config_cmdline.c -lpthread -ldl -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o thread-pool-test +thread-pool-test: thread-pool.c thread-pool.h + gcc -g -O3 thread-pool.c -I ${OPENAIR_DIR}/nfapi/open-nFAPI/nfapi/public_inc -I ${OPENAIR_DIR}/ -I ${OPENAIR_DIR}/common/utils/ -I. ${OPENAIR_DIR}/common/utils/backtrace.c -I ${OPENAIR_DIR}/openair2/COMMON ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/LOG/log.c ${OPENAIR_DIR}/common/config/config_userapi.c ${OPENAIR_DIR}/common/config/config_load_configmodule.c ${OPENAIR_DIR}/common/config/config_cmdline.c -lpthread -ldl -D TEST_THREAD_POOL -DMAX_NUM_CCs=1 -I../LOG -I../../utils/T -o thread-pool-test diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index e1446f15d7..fff09528a8 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -92,7 +92,7 @@ void *one_thread(void *arg) { } while (true); } -void initTpool(char *params,tpool_t *pool, bool performanceMeas) { +void initNamedTpool(char *params,tpool_t *pool, bool performanceMeas, char *name) { memset(pool,0,sizeof(*pool)); char *measr=getenv("threadPoolMeasurements"); pool->measurePerf=performanceMeas; @@ -116,6 +116,7 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { pool->restrictRNTI=false; curptr=strtok_r(parms_cpy,",",&saveptr); struct one_thread * ptr; + char *tname = (name == NULL ? "Tpool" : name); while ( curptr!=NULL ) { int c=toupper(curptr[0]); @@ -129,7 +130,7 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { break; default: - ptr=pool->allthreads; + ptr=pool->allthreads; pool->allthreads=(struct one_thread *)malloc(sizeof(struct one_thread)); pool->allthreads->next=ptr; printf("create a thread for core %d\n", atoi(curptr)); @@ -138,7 +139,7 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { pool->allthreads->pool=pool; //Configure the thread scheduler policy for Linux // set the thread name for debugging - sprintf(pool->allthreads->name,"Tpool_%d",pool->allthreads->coreID); + sprintf(pool->allthreads->name,"%s%d_%d",tname,pool->nbThreads,pool->allthreads->coreID); threadCreate(&pool->allthreads->threadID, one_thread, (void *)pool->allthreads, pool->allthreads->name, pool->allthreads->coreID, OAI_PRIORITY_RT); pool->nbThreads++; @@ -154,21 +155,24 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { } #ifdef TEST_THREAD_POOL +volatile int oai_exit=0; void exit_function(const char *file, const char *function, const int line, const char *s) { } struct testData { int id; + int sleepTime; char txt[30]; }; void processing(void *arg) { struct testData *in=(struct testData *)arg; - printf("doing: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); + //printf("doing: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); sprintf(in->txt,"Done by %ld, job %d", pthread_self(), in->id); - usleep(rand()%100); - printf("done: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); + in->sleepTime=rand()%1000; + usleep(in->sleepTime); + //printf("done: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); } int main() { @@ -207,11 +211,43 @@ int main() { } while(tmp); tpool_t pool; - char params[]="1,2,3,u"; + char params[]="1,2,3,4,5"; initTpool(params,&pool, true); notifiedFIFO_t worker_back; initNotifiedFIFO(&worker_back); + sleep(1); + int cumulProcessTime=0, cumulTime=0; + struct timespec st,end; + clock_gettime(CLOCK_MONOTONIC, &st); + int nb_jobs=4; + for (int i=0; i <1000 ; i++) { + int parall=nb_jobs; + for (int j=0; j id=i; + pushTpool(&pool, work); + } + int sleepmax=0; + while (parall) { + tmp=pullTpool(&worker_back,&pool); + if (tmp) { + parall--; + struct testData *dd=NotifiedFifoData(tmp); + if (dd->sleepTime > sleepmax) + sleepmax=dd->sleepTime; + delNotifiedFIFO_elt(tmp); + } + } + cumulProcessTime+=sleepmax; + } + clock_gettime(CLOCK_MONOTONIC, &end); + long long dur=(end.tv_sec-st.tv_sec)*1000*1000+(end.tv_nsec-st.tv_nsec)/1000; + printf("In µs, Total time per group of %d job:%lld, work time per job %d, overhead per job %lld\n", + nb_jobs, dur/1000, cumulProcessTime/1000, (dur-cumulProcessTime)/(1000*nb_jobs)); + + /* for (int i=0; i <1000 ; i++) { notifiedFIFO_elt_t *work=newNotifiedFIFO_elt(sizeof(struct testData), i, &worker_back, processing); struct testData *x=(struct testData *)NotifiedFifoData(work); @@ -231,7 +267,7 @@ int main() { abortTpool(&pool,510); } while(tmp); - + */ return 0; } #endif diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 0ed8715811..1839b42f39 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -31,21 +31,29 @@ #include #include #include +//#include #ifdef DEBUG #define THREADINIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP #else #define THREADINIT PTHREAD_MUTEX_INITIALIZER #endif -#define mutexinit(mutex) AssertFatal(pthread_mutex_init(&mutex,NULL)==0,""); -#define condinit(signal) AssertFatal(pthread_cond_init(&signal,NULL)==0,""); -#define mutexlock(mutex) AssertFatal(pthread_mutex_lock(&mutex)==0,""); +#define mutexinit(mutex) {int ret=pthread_mutex_init(&mutex,NULL); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define condinit(signal) {int ret=pthread_cond_init(&signal,NULL); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define mutexlock(mutex) {int ret=pthread_mutex_lock(&mutex); \ + AssertFatal(ret==0,"ret=%d\n",ret);} #define mutextrylock(mutex) pthread_mutex_trylock(&mutex) -#define mutexunlock(mutex) AssertFatal(pthread_mutex_unlock(&mutex)==0,""); -#define condwait(condition, mutex) AssertFatal(pthread_cond_wait(&condition, &mutex)==0,""); -#define condbroadcast(signal) AssertFatal(pthread_cond_broadcast(&signal)==0,""); -#define condsignal(signal) AssertFatal(pthread_cond_broadcast(&signal)==0,""); - +#define mutexunlock(mutex) {int ret=pthread_mutex_unlock(&mutex); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define condwait(condition, mutex) {int ret=pthread_cond_wait(&condition, &mutex); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define condbroadcast(signal) {int ret=pthread_cond_broadcast(&signal); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define condsignal(signal) {int ret=pthread_cond_signal(&signal); \ + AssertFatal(ret==0,"ret=%d\n",ret);} +#define tpool_nbthreads(tpool) (tpool.nbThreads) typedef struct notifiedFIFO_elt_s { struct notifiedFIFO_elt_s *next; uint64_t key; //To filter out elements @@ -78,7 +86,7 @@ static inline notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size, ret->reponseFifo=reponseFifo; ret->processingFunc=processingFunc; // We set user data piece aligend 32 bytes to be able to process it with SIMD - ret->msgData=(void *)ret+(sizeof(notifiedFIFO_elt_t)/32+1)*32; + ret->msgData=(void *)((uint8_t*)ret+(sizeof(notifiedFIFO_elt_t)/32+1)*32); ret->malloced=true; return ret; } @@ -123,7 +131,7 @@ static inline void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIF static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) { mutexlock(nf->lockF); pushNotifiedFIFO_nothreadSafe(nf,msg); - condbroadcast(nf->notifF); + condsignal(nf->notifF); mutexunlock(nf->lockF); } @@ -294,6 +302,6 @@ static inline int abortTpool(tpool_t *t, uint64_t key) { mutexunlock(nf->lockF); return nbRemoved; } -void initTpool(char *params,tpool_t *pool, bool performanceMeas); - +void initNamedTpool(char *params,tpool_t *pool, bool performanceMeas, char *name); +#define initTpool(PARAMPTR,TPOOLPTR, MEASURFLAG) initNamedTpool(PARAMPTR,TPOOLPTR, MEASURFLAG, NULL) #endif diff --git a/common/utils/threadPool/thread-pool.md b/common/utils/threadPool/thread-pool.md index bc1b1db54a..f2422d9822 100644 --- a/common/utils/threadPool/thread-pool.md +++ b/common/utils/threadPool/thread-pool.md @@ -6,10 +6,9 @@ Each worker loop on pick from the same input queue jobs to do. When a job is done, the worker sends a return if a return is defined. - A selective abort allows to cancel parallel jobs (usage: a client pushed jobs, but from a response of one job, the other linked jobs becomes useless). +A selective abort allows to cancel parallel jobs (usage: a client pushed jobs, but from a response of one job, the other linked jobs becomes useless). - All the thread pool functions are thread safe, nevertheless the working functions are implemented by the thread pool client, - so the client has to tackle the parallel execution of his functions called "processingFunc" hereafter. +All the thread pool functions are thread safe, nevertheless the working functions are implemented by the thread pool client, so the client has to tackle the parallel execution of his functions called "processingFunc" hereafter. ## license Author: @@ -18,65 +17,191 @@ When a job is done, the worker sends a return if a return is defined. # jobs - A job is a message (notifiedFIFO_elt_t): - next: - internal FIFO chain, do not set it - key: - a long int that the client can use to identify a message or a group of messages - responseFifo: - if the client defines a response FIFO, the message will be posted back after processing - processingFunc: - any funtion (type void processingFunc(void *)) that the worker will launch - msgData: - the data passed to processingFunc. It can be added automatically, or you can set it to a buffer you are managing - malloced: - a boolean that enable internal free in these cases: - no return Fifo or Abort feature +A job is a message (notifiedFIFO_elt_t): - The job messages can be created with newNotifiedFIFO_elt() and delNotifiedFIFO_elt() or managed by the client. +* next: + internal FIFO chain, do not set it +* key: + a long int that the client can use to identify a message or a group of messages +* ResponseFifo: + if the client defines a response FIFO, the message will be posted back after processing +* processingFunc: + any funtion (type void processingFunc(void *)) that the worker will launch +* msgData: + the data passed to processingFunc. It can be added automatically, or you can set it to a buffer you are managing +* malloced: + a boolean that enable internal free in these cases: + no return Fifo or Abort feature + +The job messages can be created with newNotifiedFIFO_elt() and delNotifiedFIFO_elt() or managed by the client. # Queues of jobs - Queues are type of: - notifiedFIFO_t that must be initialized by init_notifiedFIFO() - No delete function is required, the creator has only to free the data of type notifiedFIFO_t +Queues are type of: - push_notifiedFIFO() add a job in the queue - pull_notifiedFIFO() is blocking, poll_notifiedFIFO() is non blocking +* notifiedFIFO_t that must be initialized by init_notifiedFIFO() +* No delete function is required, the creator has only to free the data of type notifiedFIFO_t +* push_notifiedFIFO() add a job in the queue +* pull_notifiedFIFO() is blocking, poll_notifiedFIFO() is non blocking +* abort_notifiedFIFO() allows the customer to delete all waiting jobs that match with the key (see key in jobs definition) - abort_notifiedFIFO() allows the customer to delete all waiting jobs that match with the key (see key in jobs definition) +These queues details hereafter + +## Common + +newNotifiedFIFO_elt() + +creates a message, that will later be used in queues/FIFO + +delNotifiedFIFO_elt() + +deletes it + +NotifiedFifoData() + +gives a pointer to the beginning of free usage memory in a message (you can put any data there, up to 'size' parameter you passed to newNotifiedFIFO_elt() + +These 3 calls are not mandatory, you can also use your own memory to save the malloc()/free() that are behind these calls +iFirst level: non thread safe FIFO (or queues) + +# low level: fast and simple + +initNotifiedFIFO_nothreadSafe() + +to create a queue + +pushNotifiedFIFO_nothreadSafe() + +Add a element in a queue + +pullNotifiedFIFO_nothreadSafe() + +pull a element from a queue + +As these queues are not thread safe, there is NO blocking mechanism, neither pull() versus poll() calls + +There is no delete for a message queue: you only have to abandon the memory you allocated to call iinitNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) + +So if you malloced the memory under 'nf' parameter you have to free it, if it is automatic variable (local variable) or global variable, nothing is to be done. + + +## thread safe queues + +These queues are built on not thread safe queues when we need thread to thread protection + +initNotifiedFIFO() + +to create a queue + +pushNotifiedFIFO() + +Add a element in a queue + +pullNotifiedFIFO() + +pull a element from a queue, this call is blocking until a message arrived + +pollNotifiedFIFO() + +pull a element from a queue, this call is not blocking, so it returns always very shortly + +in 99.9% cases, pull() is better than poll() + +No delete() call, same principle as not thread safe queues # Thread pools ## initialization - The clients can create one or more thread pools with init_tpool() - the params string structure: - describes a list of cores, separated by "," that run a worker thread +The clients can create one or more thread pools with `initTpool(char *params,tpool_t *pool, bool performanceMeas )` or `initNamedTpool(char *params,tpool_t *pool, bool performanceMeas , char *name)` - If the core exists on the CPU, the thread pool initialization sets the affinity between this thread and - the related code (use negative values is allowed, so the thread will never be mapped on a specific core). +the params string structure: describes a list of cores, separated by "," that run a worker thread - The threads are all Linux real time scheduler, their name is set automatically is "Tpool_" +If the core exists on the CPU, the thread pool initialization sets the affinity between this thread and the related code (use negative values is allowed, so the thread will never be mapped on a specific core). + +The threads are all Linux real time scheduler, their name is set automatically to `Tpool_` if initTpool is used or to `_` when initNamedTpool is used. ## adding jobs - The client create their jobs messages as a notifiedFIFO_elt_t, then they push it with pushTpool() (that internally calls push_notifiedFIFO()) +The client create their jobs messages as a notifiedFIFO_elt_t, then they push it with pushTpool() (that internally calls push_notifiedFIFO()) - If they need a return, they have to create response queues with init_notifiedFIFO() and set this FIFO pointer in the notifiedFIFO_elt_t before pushing the job. +If they need a return, they have to create response queues with init_notifiedFIFO() and set this FIFO pointer in the notifiedFIFO_elt_t before pushing the job. ## abort - A abort service abortTpool() allows to abort all jobs that match a key (see jobs "key"). When the abort returns, it garanties no job (matching the key) response will be posted on response queues. +A abort service abortTpool() allows to abort all jobs that match a key (see jobs "key"). When the abort returns, it garanties no job (matching the key) response will be posted on response queues. - Nevertheless, jobs already performed before the return of abortTpool() are pushed in the response Fifo queue. +Nevertheless, jobs already performed before the return of abortTpool() are pushed in the response Fifo queue. + +## API details +Each thread pool (there can be several in the same process) should be initialized once using one of the two API's: + +### initNamedTpool(char *params,tpool_t *pool, bool performanceMeas,char *name) + +### initTpool(char *params,tpool_t *pool, bool performanceMeas) + +`params`: the configuration parameter is a string, elements separator is a comma ",". An element can be: + +* N: if a N is in the parameter list, no threads are created + The purpose is to keep the same API in any case +* a CPU with a little number of cores, + or in debugging sessions to simplify the human work +* a number that represent a valid CPU core on the target CPU + A thread is created and stick on the core (with set affinity) +* a number that is not a valid CPU core + a floating thread is created (Linux is responsible of the real time core allocation) + +example: "-1,-1,-1" +as there is no core number -1, the thread pool is made of 3 floating threads +be careful with fix allocation: it is hard to be more clever than Linux kernel + +`pool` is the memory you allocated before to store the thread pool internal state (same concept as above queues) + +`performanceMeas` is a flag to enable measurements (well described in documentation) + +`name` is used to build the thread names. + +### pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) + +adds a job to do in the thread pool + +The msg data you can set are: + +* key: + a value for you that you will find back in the response + it is also the key for abortTpool() +* reponseFifo + if you set it, the message will be sent back on this queue when the job is done + if you don't set it, no return is performed, the thread pool frees the message 'msg' when the job is done +* processingFunc + the function the job will run. the function prototype is void (void *memory) + the data part (the pointer returned by NotifiedFifoData(msg)) is passed to the function + it is used to send data to the processing function and also to write back results + of course, writing back results will lead you to use also a return queue (the parameter reponseFifo) + +### pullTpool() collects job result in a return queue + +you collect results in one result queue: the message you gave to pushTpool(), nevertheless it has been updated by processingFunc() + +An example of multiple return queues, in eNB: I created one single thread pool (because it depends mainly on CPU hardware), but i use two return queues: one for turbo encode, one for turbo decode. + +### tryPullTpool() + +is the same, but not blocking (pollTpool() would have been a better name) + +### abortTpool() + +Is a facility to cancel work you pushed to a thread pool + +I used it once: when eNB performs turbo decode, I push all segments in the thread pool. + +But when I get back the decoding results, if one segment can't be decoded, I don't need the results of the other segments of the same UE. ## Performance measurements - A performance measurement is integrated: - the pool will automacillay fill timestamps: - - * creationTime: - time the request is push to the pool; +A performance measurement is integrated: +the pool will automacillay fill timestamps: +* creationTime: +time the request is push to the pool; * startProcessingTime: time a worker start to run on the job * endProcessingTime: @@ -85,8 +210,8 @@ time the worker finished the job time the client reads the result if you set the environement variable: -thread-pool-measurements to a valid file name +threadPoolMeasurements to a valid file name These measurements will be wrote to this Linux pipe. -A tool to read the linux fifo and display it in ascii is provided: -see the local directory Makefile for this tool and to compile the thread pool unitary tests. +A tool to read the linux fifo and display it in ascii is provided; compute the binay: +in cmake building directory: make/ninja measurement_display diff --git a/common/utils/utils.c b/common/utils/utils.c index a807a27096..7f7aafc94a 100644 --- a/common/utils/utils.c +++ b/common/utils/utils.c @@ -105,3 +105,9 @@ char *itoa(int i) { return strdup(buffer); } +void *memcpy1(void *dst,const void *src,size_t n) { + + void *ret=dst; + asm volatile("rep movsb" : "+D" (dst) : "c"(n), "S"(src) : "cc","memory"); + return(ret); +} diff --git a/common/utils/utils.h b/common/utils/utils.h index 11db07056e..16631586c4 100644 --- a/common/utils/utils.h +++ b/common/utils/utils.h @@ -7,6 +7,7 @@ extern "C" { #endif +#define sizeofArray(a) (sizeof(a)/sizeof(*(a))) void *calloc_or_fail(size_t size); void *malloc_or_fail(size_t size); @@ -15,6 +16,9 @@ int hex_char_to_hex_value (char c); // Converts an hexadecimal ASCII coded string into its value.** int hex_string_to_hex_value (uint8_t *hex_value, const char *hex_string, int size); +void *memcpy1(void *dst,const void *src,size_t n); + + char *itoa(int i); #define findInList(keY, result, list, element_type) {\ diff --git a/configuration/bladeRF/enb-band7-5mhz.conf b/configuration/bladeRF/enb-band7-5mhz.conf index df9b1cbc85..9d19207522 100644 --- a/configuration/bladeRF/enb-band7-5mhz.conf +++ b/configuration/bladeRF/enb-band7-5mhz.conf @@ -187,6 +187,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -236,7 +238,7 @@ MACRLCs = ( THREAD_STRUCT = ( { parallel_config = "PARALLEL_RU_L1_TRX_SPLITaaaaaa"; - worker_config = "ENABLE"; + worker_config = "WORKER_ENABLE"; } ); diff --git a/doc/5Gnas.md b/doc/5Gnas.md new file mode 100644 index 0000000000..3d33af426c --- /dev/null +++ b/doc/5Gnas.md @@ -0,0 +1,107 @@ + + + +This tuto for 5G gNB NAS design +{: .text-center} + +# source files + +executables/ocp-gnb.c: a main loop to create a debuggable gNB, see document SW_archi.md +openair2/RRC/NR/nr_ngap_gNB.c: skeleton for interface with NGAP +openair3/NAS/COMMON/milenage.h: a simple milenage implementation, depend only on crypto library +openair3/NAS/COMMON/NR_NAS_defs.h: messages defined for NAS implemented in C: C struct, C enums and automatic conversion to labels for debug messages +openair3/NAS/COMMON/nr_common.c: 5G NAS common code between gNB and UE +openair3/UICC/usim_interface.c: UICC simulation for USIM messages + +openair3/NAS/NR_UE/ue_process_nas.c: NAS code for UE + +openair3/NAS/gNB/network_process_nas.c: NAS code for gNB running without 5GC + +openair3/TEST/test5Gnas.c: unitary testing of NAS messages: encodes+decode a standard network entry, mixing code from UE and 5GC (or gNB in noCore) + +# USIM simulation +A new USIM simulation, that parameters are in regular OAI config files + +## To open the USIM +init_uicc() takes a parameter: the name of the block in the config file +In case we run several UEs in one process, the variable section name allows to make several UEs configurations in one config file. + +The NAS implementation uses this possibility. + +# UE side +UEprocessNAS() is the entry for all messages. +It decodes the message type and call the specific function for each messgae + +## Identityrequest + IdentityResponse +When the UE receives the request, it stores the 5GC request parameters in the UE context ( UE->uicc pointer) +It calls "scheduleNAS", that would trigger a answer (seeing general archtecture, it will probly be a itti message to future RRC or NGAP thread). + +When the scheduler wants to encode the answer, it calls identityResponse() +The UE search for a section in the config file called "uicc" +it encodes the NAS answer with the IMSI, as a 4G compatible authentication. +A future release would encode 5G SUPI as native 5G UICC. + +## Authenticationrequest + authenticationResponse +When the UE receives the request, it stores the 5GC request parameters in the UE context ( UE->uicc pointer) +It calls "scheduleNAS", that would trigger a answer (seeing general archtecture, it will probly be a itti message to future RRC or NGAP thread). + +When the scheduler wants to encode the answer, it calls authenticationResponse() +The UE search for a section in the config file called "uicc" +It uses the Milenage parameters of this section to encode a milenage response +A future release would encode 5G new authentication cyphering functions. + +## SecurityModeCommand + securityModeComplete +When the UE receives the request it will: +Selected NAS security algorithms: store it for future encoding +Replayed UE security capabilities: check if it is equal to UE capabilities it sent to the 5GC +IMEISV request: to implement +ngKSI: Key set Indicator, similator to 4G to select a ciphering keys set + +When the scheduler wants to encode the answer, it calls registrationComplete() + +## registrationComplete +To be defined in UE, this NAS message is done after RRC sequence completes + +# gNB side +gNB NGAP thread receives the NAS message from PHY layers +In normal mode, it send it to the core network with no decoding. + +Here after, the gNB mode "noCore" processing in gNB: NGAP calls the entry function: processNAS() instead of forwarding the packet to the 5GC + +## RRCModeComplete + Identityrequest +When the gNB completes RRC attach, it sends a first message to NGAP thread. +Normal processing sends NGAP initial UE message, in noCore mode, it should call: identityRequest() that encode the NAS identity request inside the gNB. +The gNB NGAP thread then should call the piece of code that forward the message to the UE as when it receives a NAS message from 5GC. + +## All NAS coming from UE +When NGAP thread receives a NAS message from lower layers, it encapsulates it to forward it to the 5GC. In "noCore" mode it calls processNAS(). + +This function stores in the gNB the NAS data, then it should encode the next message (identity, authentication, security mode) or do nothing (registration complete). + + +
+**Note** +{: .panel-heading} +
+ + +
+
+ diff --git a/doc/BASIC_SIM.md b/doc/BASIC_SIM.md index ab4c3489d9..1bfc6e76d2 100644 --- a/doc/BASIC_SIM.md +++ b/doc/BASIC_SIM.md @@ -27,7 +27,7 @@ $ cd cmake_targets $ ./build_oai --eNB --UE ``` -Both eNB (lte-softmodem) and UE (lte-uesoftmodem) are present on `cmake_targets/lte_build_oai/build` folder. +Both eNB (lte-softmodem) and UE (lte-uesoftmodem) are present on `cmake_targets/ran_build/build` folder. More details are available on the [build page](BUILD.md). @@ -50,7 +50,7 @@ Example 1: running in FDD mode with EPC. ```bash $ source oaienv -$ cd cmake_targets/lte_build_oai/build +$ cd cmake_targets/ran_build/build $ ENODEB=1 sudo -E ./lte-softmodem -O $OPENAIR_HOME/ci-scripts/conf_files/lte-fdd-basic-sim.conf --basicsim ``` @@ -64,7 +64,7 @@ Example 2: running in TDD mode without any EPC. ```bash $ source oaienv -$ cd cmake_targets/lte_build_oai/build +$ cd cmake_targets/ran_build/build $ ENODEB=1 sudo -E ./lte-softmodem -O $OPENAIR_HOME/ci-scripts/conf_files/lte-tdd-basic-sim.conf --basicsim --noS1 ``` @@ -79,7 +79,7 @@ You need to set the correct OPC, USIM_API_K, MSIN (this is the end par of the IM ```bash $ source oaienv # Edit openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -$ cd cmake_targets/lte_build_oai/build +$ cd cmake_targets/ran_build/build $ ../../nas_sim_tools/build/conf2uedata -c $OPENAIR_HOME/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o . $ sudo -E ./lte-uesoftmodem -C 2625000000 -r 25 --ue-rxgain 140 --basicsim [--noS1] ``` diff --git a/doc/BUILD.md b/doc/BUILD.md index 97f9047596..40b63ac697 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -16,6 +16,7 @@ This page is valid on tags starting from **`2019.w09`**. # Soft Modem Build Script +The OAI EPC is developed in a distinct project with it's own [documentation](https://github.com/OPENAIRINTERFACE/openair-epc-fed/wiki) , it is not described here. OAI softmodem sources, which aim to implement 3GPP compliant UEs, eNodeB and gNodeB can be downloaded from the Eurecom [gitlab repository](./GET_SOURCES.md). @@ -33,7 +34,7 @@ The main oai binaries, which are tested by the Continuous Integration process ar Running the [build_oai](../cmake_targets/build_oai) script also generates some utilities required to build and/or run the oai softmodem binaries: -- `con2uedata`: a binary used to build the UE data from a configuration file. The created file emulates the sim card of a 3GPP compliant phone. +- `conf2uedata`: a binary used to build the UE data from a configuration file. The created file emulates the sim card of a 3GPP compliant phone. - `nvram`: a binary used to build UE (IMEI...) and EMM (IMSI, registered PLMN) non volatile data. - `rb_tool`: radio bearer utility - `genids` T Tracer utility, used at build time to generate T_IDs.h include file. This binary is located in the [T Tracer source file directory](../common/utils/T) . @@ -50,6 +51,19 @@ Calling the `build_oai` script with the -h option gives the list of all availabl # Building PHY Simulators +The PHY layer simulators (LTE and NR) can be built as follows: + +``` +cd /openairinterface5g/ +source oaienv +cd cmake_targets/ +./build_oai -I --phy_simulators +``` + +After completing the build, the binaries are available in the cmake_targets/phy_simulators/build directory. +A copy is also available in the target/bin directory, with all binaries suffixed by the 3GPP release number, today **.Rel15**. + + Detailed information about these simulators can be found [in this dedicated page](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/OpenAirLTEPhySimul) # Building UEs, eNodeB and gNodeB Executables @@ -63,7 +77,7 @@ cd cmake_targets/ ./build_oai -I -w USRP --eNB --UE --nrUE --gNB ``` -- The `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. +- The `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. Note: for Ubuntu 20 use cmake_targets/install_external_packages.ubuntu20 instead! - The `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one,`liboai_usrpdevif.so` . USRP is the only hardware tested today in the Continuous Integration process. The RF simulator[RF simulator](../targets/ARCH/rfsimulator/README.md) is implemented as a specific device replacing RF hardware, it can be specifically built using `-w SIMU` option, but is also built during any softmodem build. - `--eNB` is to build the `lte-softmodem` executable and all required shared libraries - `--gNB` is to build the `nr-softmodem` executable and all required shared libraries @@ -74,6 +88,21 @@ You can build any oai softmodem executable separately, you may not need all of t After completing the build, the binaries are available in the `cmake_targets/ran_build/build` directory. A copy is also available in the `target/bin` directory, with all binaries suffixed by the 3GPP release number, today .Rel15. +When installing the pre-requisites, especially the `UHD` driver, you can now specify if you want to install from source or not. + +- For `fedora`-based OS, it was already the case all the time. But now you can specify which version to install. +- For `ubuntu` OS, the Ettus PPA currently installs the following versions: + * `Ubuntu16.04`: --> version `3.15.0.0` + * `Ubuntu18.04`: --> version `4.1.0.0` + +```bash +export BUILD_UHD_FROM_SOURCE=True +export UHD_VERSION=3.15.0.0 +./build_oai -I -w USRP +``` + +The `UHD_VERSION` env variable `SHALL` be a valid tag (minus `v`) from the `https://github.com/EttusResearch/uhd.git` repository. + ## Issue when building `nasmeh` module ## A lot of users and contributors have faced the issue: `nasmesh` module does not build. diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 23d32effbb..2fc7115193 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -104,7 +104,7 @@ The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support - RLC interface (AM, UM) - UL power control - Link adaptation -- Connected DRX (CDRX) support for FDD LTE UE. Compatible with R13 from 3GPP. Support for Cat-M1 UE comming soon. +- Connected DRX (CDRX) support for FDD LTE UE. Compatible with R13 from 3GPP. Support for Cat-M1 UE comming soon. ## eNB RLC Layer ## @@ -206,7 +206,7 @@ The Physical layer implements **3GPP 36.211**, **36.212**, **36.213** and provid - PRACH preamble format 0 - All downlink (DL) channels are supported: PSS, SSS, PBCH, PCFICH, PHICH, PDCCH, PDSCH, PMCH - All uplink (UL) channels are supported: PRACH, PUSCH, PUCCH (format 1/1a/1b), SRS, DRS -- LTE MBMS-dedicated cell (feMBMS) procedures subset for LTE release 14 (experimental) +- LTE MBMS-dedicated cell (feMBMS) procedures subset for LTE release 14 (experimental) - LTE non-MBSFN subframe (feMBMS) Carrier Adquistion Subframe-CAS procedures (PSS/SSS/PBCH/PDSH) (experimental) - LTE MBSFN MBSFN subframe channel (feMBMS): PMCH (CS@1.25KHz) (channel estimation for 25MHz bandwidth) (experimental) @@ -254,14 +254,17 @@ The NAS layer is based on **3GPP 24.301** and implements the following functions The following features are valid for the gNB and the 5G-NR UE. * Static TDD, +* FDD * Normal CP * 30 kHz subcarrier spacing -* Bandwidths up to 80MHz (217 Physical Resource Blocks) +* Bandwidths: 10, 20, 40, 80, 100MHz (273 Physical Resource Blocks) +* Intermediate downlink and uplink frequencies to interface with IF equipment * Single antenna port (single beam) * Slot format: 14 OFDM symbols in UL or DL * Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 supported) * Highly efficient 3GPP compliant polar encoder and decoder * Encoder and decoder for short blocks +* Support for UL transform precoding (SC-FDMA) ## gNB PHY Layer ## @@ -269,18 +272,28 @@ The following features are valid for the gNB and the 5G-NR UE. * 30KHz SCS for FR1 and 120 KHz SCS for FR2 * Generation of NR-PSS/NR-SSS * NR-PBCH supports multiple SSBs and flexible periodicity -* Generation of NR-PDCCH for SIB1 (including generation of DCI, polar encoding, scrambling, modulation, RB mapping, etc) - - common search space configured by MIB - - user-specific search space configured by RRC - - DCI formats: 00, 10 (01 and 11 **under integration**) +* Generation of NR-PDCCH (including generation of DCI, polar encoding, scrambling, modulation, RB mapping, etc) + - common search space + - user-specific search space + - DCI formats: 00, 10, 01 and 11 * Generation of NR-PDSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). - - Single symbol DMRS, DMRS-TypeA-Position Pos2, DMRS configuration type 1 - - PDSCH mapping type A -* NR-CSI Generation of sequence at PHY (**under integration**) + - PDSCH mapping type A and B + - DMRS configuration type 1 and 2 + - Single and multiple DMRS symbols + - PTRS support + - Support for 1, 2 and 4 TX antennas + - Support for up to 2 layers (currently limited to DMRS configuration type 2) +* NR-CSIRS Generation of sequence at PHY * NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). + - PUSCH mapping type A and B + - DMRS configuration type 1 and 2 + - Single and multiple DMRS symbols + - PTRS support + - Support for 1 RX antenna + - Support for 1 layer * NR-PUCCH - - Format 0 (2 bits, mainly for ACK/NACK) - - Format 2 (up to 64 bits, mainly for CSI feedback) + - Format 0 (2 bits, for ACK/NACK and SR) + - Format 2 (up to 11 bits, mainly for CSI feedback) * NR-PRACH - Formats 0,1,2,3, A1-A3, B1-B3 * Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported) @@ -289,75 +302,214 @@ The following features are valid for the gNB and the 5G-NR UE. ## gNB Higher Layers ## -**gNB RRC** -- NR RRC (38.331) Rel 15 messages using new asn1c -- LTE RRC (36.331) also updated to Rel 15 -- Generation of CellGroupConfig (for eNB) and MIB -- Application to read configuration file and program gNB RRC -- RRC can configure PDCP, RLC, MAC - -**gNB X2AP** -- X2 setup with eNB -- Handling of SgNB Addition Request / Addition Request Acknowledge / Reconfiguration Complete - **gNB MAC** - MAC -> PHY configuration using NR FAPI P5 interface - MAC <-> PHY data interface using FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU -- Scheduler for RA procedreat gNB -- MAC downlink scheduler (fixed allocations) +- Scheduler procedures for SIB1 +- Scheduler procedures for RA + - Contention Free RA procedure + - Contention Based RA procedure + - Msg3 can transfer uplink CCCH, DTCH or DCCH messages + - CBRA can be performed using MAC CE or C-RNTI +- Scheduler procedures for CSI-RS +- MAC downlink scheduler + - phy-test scheduler (fixed allocation and usable also without UE) + - regular scheduler with dynamic allocation + - MCS adaptation from HARQ BLER - MAC header generation (including timing advance) - ACK / NACK handling and HARQ procedures for downlink -- **As of May 2020** only DL was validated with COTS phone ; UL in progress, validated with OAI UE in noS1 mode +- MAC uplink scheduler + - phy-test scheduler (fixed allocation) + - regular scheduler with dynamic allocation + - HARQ procedures for uplink +- MAC procedures to handle CSI measurement report + - evalution of RSRP report + - evaluation of CQI report +- MAC scheduling of SR reception + +**gNB RLC** +- Send/Receive operations according to 38.322 Rel.16 + - Segmentation and reassembly procedures + - RLC Acknowledged mode supporting PDU retransmissions + - RLC Unacknowledged mode + - DRBs and SRBs establishment/handling and association with RLC entities + - Timers implementation + - Interfaces with PDCP, MAC + - Interfaces with gtp-u (data Tx/Rx over F1-U at the DU) + +**gNB PDCP** +- Send/Receive operations according to 38.323 Rel.16 + - Integrity protection and ciphering procedures + - Sequence number management, SDU dicard and in-order delivery + - Radio bearer establishment/handling and association with PDCP entities + - Interfaces with RRC, RLC + - Interfaces with gtp-u (data Tx/Rx over N3 and F1-U interfaces) + +**gNB RRC** +- NR RRC (38.331) Rel 16 messages using new asn1c +- LTE RRC (36.331) also updated to Rel 15 +- Generation of CellGroupConfig (for eNB) and MIB +- Generation of system information block 1 (SIB1) +- Generation of system information block 2 (SIB2) +- Application to read configuration file and program gNB RRC +- RRC can configure PDCP, RLC, MAC +- Interface with gtp-u (tunnel creation/handling for S1-U (NSA), N3 (SA) interfaces) +- Integration of RRC messages and procedures supporting UE 5G SA connection + - RRCSetupRequest/RRCSetup/RRCSetupComplete + - RRC Uplink/Downlink Information transfer carrying NAS messages transparently + - RRC Reconfiguration/Reconfiguration complete + - Support for master cell group configuration + - Interface with NGAP for the interactions with the AMF + - Interface with F1AP for CU/DU split deployment option + +**gNB X2AP** +- Integration of X2AP messages and procedures for the exchanges with the eNB over X2 interface supporting the NSA setup according to 36.423 Rel. 15 + - X2 setup with eNB + - Handling of SgNB Addition Request / Addition Request Acknowledge / Reconfiguration Complete + +**gNB NGAP** + +- Integration of NGAP messages and procedures for the exchanges with the AMF over N2 interface according to 38.413 Rel. 15 + - NGAP Setup request/response + - NGAP Initial UE message + - NGAP Initial context setup request/response + - NGAP Downlink/Uplink NAS transfer + - NGAP UE context release request/complete + - NGAP UE radio capability info indication + - NGAP PDU session resource setup request/response +- Interface with RRC + +**gNB F1AP** + +- Integration of F1AP messages and procedures for the control plane exchanges between the CU and DU entities according to 38.473 Rel. 16 + - F1 Setup request/response + - F1 DL/UL RRC message transfer + - F1 Initial UL RRC message transfer + - F1 UE Context setup request/response + - F1 gNB CU configuration update +- Interface with RRC +- Interface with gtp-u (tunnel creation/handling for F1-U interface) + +**gNB GTP-U** +- New gtp-u implementation supporting both N3 and F1-U interfaces according to 29.281 Rel.15 + - Interfaces with RRC, F1AP for tunnel creation + - Interfaces with PDCP and RLC for data send/receive at the CU and DU respectively (F1-U interface) # OpenAirInterface 5G-NR UE Feature Set # -**as of May 2020** only supporting "noS1" mode (DL): -- Creates TUN interface to PDCP to inject and receive user-place traffic -- Will only work with OAI gNB configured in the same mode +* Supporting "noS1" mode (DL and UL): + - Creates TUN interface to PDCP to inject and receive user-place traffic + - No connection to the core network +* Supporting Standalone (SA) mode: + - UE can register with the 5G Core Network, establish a PDU Session and exchange user-plane traffic -## UE PHY Layer ## +## NR UE PHY Layer ## * Initial synchronization * Time tracking based on PBCH DMRS -* Time tracking based on PBCH DMRS * Frequency offset estimation -* PBCH RX -* PDCCH RX -* PDSCH RX, including a first version of dual stream receiver for PDSCH * 30KHz SCS for FR1 and 120 KHz SCS for FR2 -* Generation of NR-PSS/NR-SSS +* Reception of NR-PSS/NR-SSS * NR-PBCH supports multiple SSBs and flexible periodicity -* Generation of NR-PDCCH for SIB1 (including generation of DCI, polar encoding, scrambling, modulation, RB mapping, etc) +* Reception of NR-PDCCH (including reception of DCI, polar decoding, de-scrambling, de-modulation, RB de-mapping, etc) - common search space configured by MIB - user-specific search space configured by RRC - - DCI formats: 00, 10 (01 and 11 **under integration**) -* Generation of NR-PDSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). - - Single symbol DMRS, DMRS-TypeA-Position Pos2, DMRS configuration type 1 - - PDSCH mapping type A -* NR-CSI Generation of sequence at PHY (**under integration**) + - DCI formats: 00, 10, 01 and 11 +* Reception of NR-PDSCH (including Segmentation, LDPC decoding, rate de-matching, de-scrambling, de-modulation, RB de-mapping, etc). + - PDSCH mapping type A and B + - DMRS configuration type 1 and 2 + - Single and multiple DMRS symbols + - PTRS support + - Support for 1, 2 and 4 RX antennas + - Support for up to 2 layers (currently limited to DMRS configuration type 2) * NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). + - PUSCH mapping type A and B + - DMRS configuration type 1 and 2 + - Single and multiple DMRS symbols + - PTRS support + - Support for 1 TX antenna + - Support for 1 layer * NR-PUCCH - - Format 0 (2 bits, mainly for ACK/NACK) + - Format 0 (2 bits for ACK/NACK and SR) - Format 2 (up to 64 bits, mainly for CSI feedback) + - Format 1, 3 and 4 present but old code never dested (need restructuring before verification) * NR-PRACH - Formats 0,1,2,3, A1-A3, B1-B3 +* NR-SRS + - Old code never dested (need restructuring before verification) +* SS-RSRP + - RSRP measured on synchronization SSB (ok only for single SSB) * Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported) * Highly efficient 3GPP compliant polar encoder and decoder * Encoder and decoder for short block +## NR UE FAPI ## -## UE Higher Layers ## +* MAC -> PHY configuration via UE FAPI P5 interface +* Basic MAC to control PHY via UE FAPI P7 interface +* PHY -> MAC indication (needs some improvement) -**gNB MAC** -- Initial sync and MIB detection -- MAC -> PHY configuration of PHY via UE FAPI P5 interface -- Basic MAC to control PHY via UE FAPI P7 interface -- Random access procedure +## NR UE Higher Layers ## + +**UE MAC** +* Minimum system information (MSI) + - MIB processing + - Scheduling of system information block 1 (SIB1) reception +* Random access procedure (needs improvement, there is still not a clear separation between MAC and PHY) + - Mapping SSBs to multiple ROs + - Scheduling of PRACH + - Processing of RAR + - Transmission and re-transmission of Msg3 + - Msg4 and contention resolution +* DCI processing + - format 10 (RA-RNTI, C-RNTI, SI-RNTI, TC-RNTI) + - format 00 (C-RNTI, TC-RNTI) + - format 11 (C-RNTI) + - format 01 (C-RNTI) +* UCI processing + - ACK/NACK processing + - Triggering periodic SR + - CSI measurement reporting (SSB RSRP only) +* DLSH scheduler + - Configuration of fapi PDU according to DCI + - HARQ procedures +* ULSCH scheduler + - Configuration of fapi PDU according to DCI -**RLC** +**UE RLC** +* Tx/Rx operations according to 38.322 Rel.16 + - Segmentation and reassembly procedures + - RLC Acknowledged mode supporting PDU retransmissions + - RLC Unacknowledged mode + - DRBs and SRBs establishment and handling + - Timers implementation + - Interfaces with PDCP, MAC -**PDCP** +**UE PDCP** +* Tx/Rx operations according to 38.323 Rel.16 + - Integrity protection and ciphering procedures + - Sequence number management, SDU dicard and in-order delivery + - Radio bearer establishment/handling and association with PDCP entities + - Interfaces with RRC, RLC + +**UE RRC** +* Integration of RRC messages and procedures supporting UE 5G SA connection according to 38.331 Rel.16 + - RRCSetupRequest/RRCSetup/RRCSetupComplete + - RRC Uplink/Downlink Information transfer carrying NAS messages transparently + - RRC Reconfiguration/Reconfiguration complete + - Support for master cell group configuration +* Interface with PDCP: configuration, DCCH and CCCH message handling +* Interface with RLC and MAC for configuration + +**UE NAS** +* Transfer of NAS messages between the AMF and the UE supporting the UE registration with the core network and the PDU session establishment according to 24.501 Rel.16 + - Identity Request/Response + - Authentication Request/Response + - Security Mode Command/Complete + - Registration Request/Accept/Complete + - PDU Session Establishment Request/Accept + - NAS configuration and basic interfacing with RRC diff --git a/doc/GET_SOURCES.md b/doc/GET_SOURCES.md index e27e9dbb74..854ff3b504 100644 --- a/doc/GET_SOURCES.md +++ b/doc/GET_SOURCES.md @@ -33,12 +33,8 @@ holds the source code for (eNB RAN + UE RAN). For legal issues (licenses), the core network (EPC) source code is now moved away from the above openairinterface5g git repository. -* A very old version of the EPC is located under the same GitLab Eurecom server (splitted into 2 Git repos): - * [openair-cn](https://gitlab.eurecom.fr/oai/openair-cn.git) with apache license - * [xtables-addons-oai](https://gitlab.eurecom.fr/oai/xtables-addons-oai.git) with GPL license - * **These repositories are no more maintained.** * A more recent version is available under our GitHub domain: - * [OAI GitHub openair-cn](https://github.com/OPENAIRINTERFACE/openair-cn) + * [OAI GitHub openair-cn domain](https://github.com/OPENAIRINTERFACE) * Check its wiki pages for more details Configure git with your name/email address (only important if you are developer and want to contribute/push code to Git Repository): @@ -80,8 +76,6 @@ you do not have account on gitlab.eurecom.fr, please register yourself to gitlab * `git clone git@gitlab.eurecom.fr:oai/openairinterface5g.git` * Clone with user name/password prompt: * `git clone https://YOUR_USERNAME@gitlab.eurecom.fr/oai/openairinterface5g.git` - * `git clone https://YOUR_USERNAME@gitlab.eurecom.fr/oai/openair-cn.git` - * `git clone https://YOUR_USERNAME@gitlab.eurecom.fr/oai/xtables-addons-oai.git` (optional, openair-cn build script can do it for you) # Which branch to checkout? diff --git a/doc/ITTISIM.md b/doc/ITTISIM.md new file mode 100755 index 0000000000..13fdd90846 --- /dev/null +++ b/doc/ITTISIM.md @@ -0,0 +1,48 @@ + + + + + +
+ + + + + + Running L3 ITTI simulator +
+ +This page is valid on the following branches: + +- `develop` starting from tag `2020.w48` + +# 1. Building the ITTI simulator. + +The ITTI simulator is available directly from the standard build. + +```bash +$ source oaienv +$ cd cmake_targets +$ sudo ./build_oai -x -w None -c -ittiSIM +``` + +# 2. Running the ITTI simulator. + +The ITTI simulator establishes ITTI-threaded communication between the gNB RRC task and the UE RRC task. + +This allows to test the sequence of NGAP/RRC/NAS messages. + +The main limitations are: + +- NAS is a simple stub that just sends and receives messages +- only initial Attach sequence + +## 2.1. Starting the ITTI simulator + +The ITTI simulator is able to run with a connected 5GC or without any. +The develop branch tag `2020.w48` only works RRC without 5GC connection. + +```bash +$ sudo -E ./ran_build/build/nr-ittisim -O gnb.conf +``` + diff --git a/doc/NR_NFAPI_archi.md b/doc/NR_NFAPI_archi.md new file mode 100644 index 0000000000..59c511fb52 --- /dev/null +++ b/doc/NR_NFAPI_archi.md @@ -0,0 +1,141 @@ +# global + +xnf is pnf or vnf + +The xnf starting functions are configure_nfapi_xnf() + +The OAI code that read the configuration parameters call these functions that will create autonomous thread for xnf control part + +These control threads create a SCTP socket by Linux API call (no use of OpenAir internal architecture with SCTP itti thread). + +The main() function of softmodem has to create and start the other threads+loop on event for appropriate work: RF Rx in pnf, NGAP, GTP-U, X2, RLC, PDCP for vnf + +NFAPI has it's own code directly on Linux+Posix, it doesn't reuse any piece of the OpenAir framework: SCTP thread, thread creation and management, ... + +## signaling (P5) xnf main loop + +nfapi_vnf_start() create the SCTP socket, then do event waiting in a infinite loop while(vnf->terminate == 0). It accepts the pnf connections, then process the messages on reception + +nfapi_pnf_start() initiate connection to vnf until it has a link. Then it enter a similar infinite loop in pnf_message_pump() + +After some checks, when a message is obtained, it calls pnf_handle_p5_message() or vnf_handle_p4_p5_message() that have a switch on each p5 message types: the enum nfapi_message_id_e + +Each message type has it's own processing function in the switch, like +``` +case NFAPI_START_RESPONSE: + vnf_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; +``` + +These loops are autonomous in their thread waiting incoming message. + +## P7 xnf main loop + +When the p5 interface receives appropriate message, it starts the p7 interface by launching a thread (see the calls to pthread_create() in nfapi/oai_integration/nfapi_xnf.c) + +The p7 main loops starting is a bit simpler, thanks to UDP non connected protocol. The xnf_dispatch_p7_message() do p7 fragments re-assembly, then +calls xnf_dispatch_p7_message() that have the big switch on message type (as in p5 above description) + +So, we have the logic for UL reception in vnf, and DL reception in pnf + +## P7 UL transmission by PNF + +RF samples are received, and decoding is done by the PNF using control data transmitted by the VNF to the PNF through downlink p7 messages (UL_TTI_req and UL_DCI_req). + +After decoding, results are accumulated into the xNB->UL_INFO structure at the PNF. + +The data in the UL_INFO struct is transmitted through a socket in the form of 'uplink indication functions' from the PNF to the VNF. Each uplink indication message is transmitted from their respective handle functions in NR_UL_indication(). For example, + +``` + +void handle_nr_rach(NR_UL_IND_t *UL_info) { + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->rach_ind.number_of_pdus>0) { + oai_nfapi_nr_rach_indication(&UL_info->rach_ind); //This function calls the routines required for packing + transmission through socket + UL_info->rach_ind.number_of_pdus = 0; + } + } + +``` + +## P7 UL reception at VNF + +Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vnf_p7_start(), the VNF receives and unpacks the uplink indication message received on its socket. Based on the unpacked messages, UL_INFO struct on the VNF side gets populated. + +``` + +// have a p7 message + if(FD_ISSET(vnf_p7->socket, &rfds)) + { + vnf_nr_p7_read_dispatch_message(vnf_p7); + } + +``` + +vnf_nr_dispatch_p7_message() is the function that contains the switch on various message headers so that the appropriate unpack function is called. + +## P7 DL Transmission by VNF + +DL messages are scheduled at the VNF, through NR_UL_indication(). NR_UL_indication() is called when the SFN/slot in the UL_info structure changes (this acts as a trigger for next slot processing, instead of running a separate clock at the VNF). The SFN/slot at the VNF in UL_info is updated using the slot_indication uplink p7 message, which is sent at the beginning of every slot by the PNF. The slot_indication message contains SFN/slot of the TX_thread, so that the scheduler operates slot_ahead slots ahead of the RX thread. This ensures that UL_tti_req is received before RX slot processing at the PNF. + +The function NR_schedule_response calls oai_nfapi_[DL P7 msg]_req(), which contains the routines for packing + transmission of scheduled messages through the socket to the PNF. For example, to send the 'TX_data_req' p7 message + +``` + +if (Sched_INFO->TX_req->Number_of_PDUs > 0) +{ + oai_nfapi_tx_data_req(Sched_INFO->TX_req); +} + +``` + +```mermaid + +graph TD + pselect[VNF socket pselect] -- timed out : end of slot --> call_sched[Call Scheduler NR_UL_indication] -- oai_nfapi_***_req sends the DL p7 msg--> slot_inc[Increment sfn/slot]; + pselect[VNF socket pselect] -- UL p7 xyz msg recvd --> msg_recvd[Read message vnf_nr_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Handle Message vnf_handle_nr_xyz] --> fill_ul_info[Fill UL info struct with fn pointer vnf_p7->_public.nr_rx_xyz]; + fill_ul_info -- update pselect_timeout: next_slot_start - time_xyz_msg_recvd-->pselect; + slot_inc -- next slot --> pselect + +``` +Note that since DL P7 message reception and TX/RX processing are done on separate threads, there is the issue of the L1 processing threads trying to do their job before the required P7 message is received. In the case of RX processing, since the scheduler operates slot_ahead slots ahead of the RX thread, the required messages conveniently arrive earlier than they are required. However, in the case of TX processing, this cannot be ensured if the scheduler is exactly in sync with the TX thread. + +Therefore, we operate the VNF vnf_slot_ahead (which is currently 2) slots ahead of the PNF. This is to ensure that the DL fapi structures for a particular TX slot are all received before TX processing for that slot. + +## P7 DL Reception at PNF + +Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message structures are filled in the PNF, and these are used further down the pipeline for processing. + +While receiving the DL P7 message, we check whether the message was received within a timing window from which it was sent. The duration of the window can be set by the user (set as a parameter for xnf in the p5 messages). Note that the DL information must be received by the PNF within a timing window at least lesser than the duration of slot_ahead variable (timing_window <= slot_ahead * slot_duration). + +```mermaid + +graph TB + pselect[PNF socket pselect] -- timed out : end of slot --> slot_inc[Increment sfn/slot]; + pselect[PNF socket pselect] -- DL p7 xyz msg recvd --> msg_recvd[Read message pnf_nr_nfapi_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Unpack Message pnf_handle_nr_xyz] --> fill_pnf_p7[Fill pnf_p7 global structure pnf_handle_nr_xyz] --Data from pnf_p7 struct copied to fapi structures using pnf_phy_***_req. Called every slot from handle_nr_slot_ind-->pselect; + + slot_inc -- next slot --> pselect +``` +Once the messages are received, they are filled into slot buffers, and are stored until the processing of the slot that they were meant for. + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index 37eadd92f3..d063afd5d9 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -100,14 +100,110 @@ Some other useful paramters of the UE are - --clock-source: sets the clock-source (internal or external). - --time-source: sets the time-source (internal or external). - ## noS1 setup with OAI UE Instead of randomly generated payload, in the phy-test mode we can also inject/receive user-plane traffic over a TUN interface. This is the so-called noS1 mode. This setup is described in the [rfsimulator page](../targets/ARCH/rfsimulator/README.md#5g-case). In theory this should also work with the real hardware target although this has yet to be tested. +## do-ra setup with OAI +The do-ra flag is used to ran the NR Random Access procedures in contention-free mode. Currently OAI implements the RACH process from Msg1 to Msg3. + +In order to run the RA, the following flag is needed for both the gNB and the UE: + +`--do-ra` + +### Run OAI in do-ra mode + +From the `cmake_targets/ran_build/build` folder: + +gNB on machine 1: + +`sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra` + +UE on machine 2: + +`sudo ./nr-uesoftmodem --do-ra` + +With the RF simulator (on the same machine): + +`sudo RFSIMULATOR=gnb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD` + +`sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD` + +## SA setup with OAI + +The sa flag is used to run gNB in standalone mode. + +In order to run gNB and UE in standalone mode, the following flag is needed: + +`--sa` + +At the gNB the --sa flag does the following: +- The RRC encodes SIB1 according to the configuration file and transmits it through NR-BCCH-DL-SCH. + +At the UE the --sa flag will: +- Decode SIB1 and starts the 5G NR Initial Access Procedure for SA: + 1) 5G-NR RRC Connection Setup + 2) NAS Authentication and Security + 3) 5G-NR AS Security Procedure + 4) 5G-NR RRC Reconfiguration + 5) Start Downlink and Uplink Data Transfer + +### Run OAI in SA mode + +From the `cmake_targets/ran_build/build` folder: + +gNB on machine 1: + +`sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --sa` + +UE on machine 2: + +`sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --sa` + +With the RF simulator (on the same machine): + +`sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --rfsim --sa` + +`sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa` + +## IF setup with OAI + +The -C and --CO flags can be used together at UE side to set custom downlink and uplink FR1 arbitrary frequencies for the IF equipment. + +In order to run this setup, the following flags are needed at the UE side: + +`-C` + +`--CO` + +and the following parameters must be configured in the RUs section of the gNB configuration file: + +`if_freq` + +`if_offset` + +The values must be given in Hz. + +### Run OAI with custom DL/UL arbitrary frequencies + +The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 (FDD) at gNB side. + +From the `cmake_targets/ran_build/build` folder: + +gNB on machine 1: + +`sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf` + +UE on machine 2: + +`sudo ./nr-uesoftmodem -C 2169080000 --CO -400000000` + + + +[Selecting an alternative ldpc implementation at run time](../openair1/PHY/CODING/DOC/LDPCImplementation.md) [oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) diff --git a/doc/RUN_NR_NFAPI.md b/doc/RUN_NR_NFAPI.md new file mode 100644 index 0000000000..ea7c2590c7 --- /dev/null +++ b/doc/RUN_NR_NFAPI.md @@ -0,0 +1,54 @@ +# Procedure to run nFAPI in 5G NR + +## Contributed by 5G Testbed IISc + +### Developers: Gokul S, Mahesh A, Aniq U R + +## Procedure to Build gNB and UE + +The regular commands to build gNB and UE can be used +``` +sudo ./build_oai --gNB --nrUE + +``` +## Procedure to run NR nFAPI using RF-Simulator + +### Bring up another loopback interface + +If running for the first time on your computer, or you have restarted your computer, bring up another loopback interface with this command: + +sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up + +### VNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test + +``` +### PNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi 1 --rfsim --phy-test --rfsimulator.serveraddr server + +``` +### UE command +``` +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d + +``` +## Procedure to run NR nFAPI using Hardware (tested with USRP x310) + +### VNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test + +``` +### PNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi 1 --phy-test + +``` +### UE command +``` +sudo ./nr-uesoftmodem --usrp-args "addr=*USRP_ADDRESS*,clock_source=external,time_source=external" --phy-test --rrc_config_path ../../../ci-scripts/rrc-files + +``` + diff --git a/doc/SW_archi.md b/doc/SW_archi.md new file mode 100644 index 0000000000..e5856d63bc --- /dev/null +++ b/doc/SW_archi.md @@ -0,0 +1,340 @@ + + + +This tuto for 5G gNB design, with Open Cells main +{: .text-center} + +# Top file: executables/ocp-gnb.c + +the function main() initializes the data from configuration file + +# The main thread is in ru_thread() +The infinite loop: +## rx_rf() + Collect radio signal samples from RF board + all SDR processing is triggered by I/Q sample reception and it's date (timestamp) + TX I/Q samples will have a date in the future, compared to RX timestamp + called for each 5G NR slot + it blocks until data is available + the internal time comes from the RF board sampling numbers + (each sample has a incremental number representing a very accurate timing) +raw incoming data is in buffer called "rxdata" + We derivate frame number, slot number, ... from the RX timestamp +{: .func2} +## nr_fep_full() +"front end processing" of uplink signal +performs DFT on the signal +same function (duplicates): phy_procedures_gNB_common_RX() +it computes the buffer rxdataF (for frequency) from rxdata (samples over time) +rxdataF is the rxdata in frequency domain, phase aligned +{: .func3} +## gNB_top() +only compute frame numbre, slot number, ... +{: .func3} +## ocp_rxtx() +main processing for both UL and DL +start by calling oai_subframe_ind() that trigger processing in pnf_p7_subframe_ind() purpose ??? +all the context is in the passed structure UL_INFO +the context is not very clear: there is a mutex on it, +but not actual coherency (see below handle_nr_rach() assumes data is up-to-date) +The first part (in NR_UL_indication, uses the data computed by the lower part (phy_procedures_gNB_uespec_RX), but for the **previous** slot +Then, phy_procedures_gNB_uespec_RX will hereafter replace the data for the next run +This is very tricky and not thread safe at all. +{: .func3} + +### NR_UL_indication() +This block processes data already decoded and stored in structures behind UL_INFO +{: .func4} + +* handle_nr_rach() +process data from RACH primary detection +if the input is a UE RACH detection +{: .func4} + * nr_schedule_msg2() +{: .func4} +* handle_nr_uci() +handles uplink control information, i.e., for the moment HARQ feedback. +{: .func4} +* handle_nr_ulsch() +handles ulsch data prepared by nr_fill_indication() +{: .func4} +* gNB_dlsch_ulsch_scheduler () +the **scheduler** is called here, see dedicated chapter +{: .func4} +* NR_Schedule_response() +process as per the scheduler decided +{: .func4} + +### L1_nr_prach_procedures() +???? +{: .func4} +### phy_procedures_gNB_uespec_RX() +* nr_decode_pucch0() +actual CCH channel decoding form rxdataF (rx data in frequency domain) +populates UL_INFO.uci_ind, actual uci data is in gNB->pucch +{: .func4} +* nr_rx_pusch() +{: .func4} + * extracts data from rxdataF (frequency transformed received data) +{: .func4} + * nr_pusch_channel_estimation() +{: .func4} + * nr_ulsch_extract_rbs_single() +{: .func4} + * nr_ulsch_scale_channel() +{: .func4} + * nr_ulsch_channel_level() +{: .func4} + * nr_ulsch_channel_compensation() +{: .func4} + * nr_ulsch_compute_llr() +this function creates the "likelyhood ratios" +{: .func4} +* nr_ulsch_procedures() +{: .func4} + * actual ULsch decoding +{: .func4} + * nr_ulsch_unscrambling() + {: .func4} + * nr_ulsch_decoding() + {: .func4} + * nr_fill_indication() +populate the data for the next call to "NR_UL_indication()" +it would be better to call **NR_UL_indication()** now instead of before (on previous slot) +{: .func4} + +### phy_procedures_gNB_TX() +* nr_common_signal_procedures() +generate common signals +{: .func4} +* nr_generate_dci_top() +generate DCI: the scheduling informtion for each UE in both DL and UL +{: .func4} +* nr_generate_pdsch() +generate DL shared channel (user data) +{: .func4} + +### nr_feptx_prec() +tx precoding +{: .func3} +### nr_feptx0 +do the inverse DFT +{: .func3} +### tx_rf() +send radio signal samples to the RF board +the samples numbers are the future time for these samples emission on-air +{: .func3} + +# Scheduler + +The main scheduler function is called by the chain: nr_ul_indication()=>gNB_dlsch_ulsch_scheduler() +It calls sub functions to process each physical channel (rach, ...) +The scheduler uses and internal map of used RB: vrb_map and vrb_map_UL, so each specific channel scheduler can see the already filled RB in each subframe (the function gNB_dlsch_ulsch_scheduler() clears these two arrays when it starts) + +The scheduler also calls "run_pdcp()", as this is not a autonomous thread, it needs to be called here to update traffic requests (DL) and to propagate waiting UL to upper layers +After calling run_pdcp, it updates "rlc" time data but it doesn't actually process rlc +it sends a iiti message to activate the thread for RRC, the answer will be asynchronous in ???? + +Calls schedule_nr_mib() that calls mac_rrc_nr_data_req() to fill MIB, + +Calls schedule_nr_prach() which schedules the (fixed) PRACH region one frame in +advance. + +Calls nr_csi_meas_reporting() to check when to schedule CSI in PUCCH. + +Calls nr_schedule_RA(): checks RA process 0's state. Schedules Msg.2 via +nr_generate_Msg2() if an RA process is ongoing, and pre-allocates the Msg. 3 +for PUSCH as well. + +Calls nr_schedule_ulsch(): It is divided into the "preprocessor" and the +"postprocessor": the first makes the scheduling decisions, the second fills +nFAPI structures to indicate to the PHY what it is supposed to do. To signal +which users have how many resources, the preprocessor populates the +NR_sched_pusch_t (for values changing every TTI, e.g., frequency domain +allocation) and NR_sched_pusch_save_t (for values changing less frequently, at +least in FR1 [to my understanding], e.g., DMRS fields when the time domain +allocation stays between TTIs) structures. Furthermore, the preprocessor is an +exchangeable module that schedules differently based on a particular +use-case/deployment type, e.g., one user for phytest [in +nr_ul_preprocessor_phytest()], multiple users in FR1 +[nr_fr1_ulsch_preprocessor()], or maybe FR2 [does not exist yet]: +* calls preprocessor via pre_processor_ul(): the preprocessor is responsible + for allocating CCEs (using allocate_nr_CCEs()) and deciding on resource + allocation for the UEs including TB size. Note that we do not yet have + scheduling requests. What it typically does: + 1) check whether the current frame/slot plus K2 is an UL slot, and return if + not. + 2) Find first free start RB in vrb_map_UL, and as many free consecutive RBs + as possible. + 3) Either set up resource allocation directly (e.g., for a single UE, + phytest), or call into a function to perform actual resource allocation. + Currently, this is done using pf_ul() which implements a basic + proportional fair scheduler: + * for every UE, check for retransmission and allocate as necessary + * Calculate DMRS stuff (nr_set_pusch_semi_static()) + * Calculate the PF coefficient and put eligible UEs into a list + * Allocate resources to the UE(s) with the highest coefficient + 4) Mark used resources in vrb_map_UL. +* loop through all users: get a HARQ process as indicated through the + preprocessor, update statistics, fill nFAPI structures directly for PUSCH, + and call config_uldci() and fill_dci_pdu_rel15() for DCI filling and PDCCH + messages. + +Calls nr_schedule_ue_spec(). It is divided into the "preprocessor" and the +"postprocessor": the first makes the scheduling decisions, the second fills +nFAPI structures to indicate to the PHY what it is supposed to do. To signal +which users have how many resources, the preprocessor populates the +NR_UE_sched_ctrl_t structure of affected users. In particular, the field rbSize +decides whether a user is to be allocated. Furthermore, the preprocessor is an +exchangeable module that schedules differently based on a particular +use-case/deployment type, e.g., one user for phytest [in +nr_preprocessor_phytest()], multiple users in FR1 +[nr_fr1_dlsch_preprocessor()], or maybe FR2 [does not exist yet]. +* calls preprocessor via pre_processor_dl(): the preprocessor is responsible + for allocating CCEs and PUCCH (using allocate_nr_CCEs() and + nr_acknack_scheduling()) and deciding on the frequency/time domain + allocation including the TB size. What it typically does: + 1) Check available resources in the vrb_map + 2) Checks the quantity of waiting data in RLC + 3) Either set up resource allocation directly (e.g., for a single UE, + phytest), or call into a function to perform actual resource allocation. + Currently, this is done using pf_dl() which implements a basic + proportional fair scheduler: + * for every UE, check for retransmission and allocate as necessary + * Calculate the PF coefficient and put eligible UEs into a list + * Allocate resources to the UE(s) with the highest coefficient + 4) Mark taken resources in the vrb_map +* loop through all users: check if a new TA is necessary. Then, if a user has + allocated resources, update statistics (round, sent bytes), update HARQ + process information, and fill nFAPI structures (allocate a DCI and PDCCH + messages, TX_req, ...) + +# RRC +RRC is a regular thread with itti loop on queue: TASK_RRC_GNB +it receives it's configuration in message NRRRC_CONFIGURATION_REQ, then real time mesages for all events: S1/NGAP events, X2AP messages and RRC_SUBFRAME_PROCESS + +RRC_SUBFRAME_PROCESS message is send each subframe + +how does it communicate to scheduler ? + + +# RLC +RLC code is new implementation, not using OAI mechanisms: it is implemented directly on pthreads, ignoring OAI common functions. +It is a library, running in thread RRC but also in PHY layer threads and some bits in pdcp running thread or F1 interface threads. + +RLC data is isolated and encapsulated. +It is stored under a global var: nr_rlc_ue_manager +The init function rlc_module_init() populates this global variable. +A small effort could lead us to return the pointer to the caller of rlc_module_init() (internal type: nr_rlc_ue_manager_internal_t) +but it returns void. +It could return the initialized pointer (as FILE* fopen() for example), then the RLC layer could have multiple instances in one process. +Even, a future evolution could remove this global rlc layer: rlc can be only a library that we create a instance for each UE because it doesn't shareany data between UEs. + +For DL (respectively from UL in UE), the scheduler need to know the quantity of data waitin to be sent: it calls mac_rlc_status_ind() +That "peek" the size of the waiting data for a UE. +The scheduler then push orders to lower layers. The transport layer will actually pull data from RLC with: mac_rlc_data_req() +the low layer push data into rlc by: mac_rlc_data_ind() +Still on DL (gNB side), PDCP push incoming data into RLC by calling: rlc_data_req() + +For UL, the low layer push data into rlc by: mac_rlc_data_ind() +Then, rlc push it to pdcp by calling pdcp_data_ind() from a complex rlc internal call back (deliver_sdu()) + +When adding a UE, external code have to call nr_rrc_rlc_config_asn1_req(), to remove it: rrc_rlc_remove_ue() +Inside UE, channels called drd or srb can be created: ??? and deleted: rrc_rlc_config_req() + +nr_rlc_tick() must be called periodically to manage the internal timers + +successful_delivery() and max_retx_reached(): in ??? trigger, the RLC sends a itti message to RRC: RLC_SDU_INDICATION (neutralized by #if 0 right now) + +#PDCP + +The PDCP implementation is also protected through a general mutex. +The design is very similar to rlc layer. The pdcp data is isolated and encapsulated. + +pdcp_layer_init(): same as rlc init +we have to call a second init function: pdcp_module_init() + +At Tx side (DL in gNB), pdcp_data_req() is the entry function that the upper layer calls. +The upper layer can be GTP or a PDCP internal thread enb_tun_read_thread() that read directly from Linux socket in case we skip 3GPP core implementation. +PDCP internals for pdcp_data_req() is thread safe: inside pdcp_data_req_drb(), the pdcp manager protects with the mutex the access to the SDU receiving function of PDCP (recv_sdu() callback, corresponding to nr_pdcp_entity_drb_am_recv_sdu() for DRBs). When it needs, the pdcp layer push this data to rlc by calling : rlc_data_req() + +Also, incoming downlink sdu can comme from internal RRC: in this case, pdcp_run() reads a itti queue, for message RRC_DCCH_DATA_REQ, to0 only call 'pdcp_data_req()' + +At Rx side, pdcp_data_ind() is the entry point that receives the data from RLC. +- Inside pdcp_data_ind(), the pdcp manager mutex protects the access to the PDU receiving function of PDCP (recv_pdu() callback corresponding to nr_pdcp_entity_drb_am_recv_pdu() for DRBs) +- Then deliver_sdu_drb() function sends the received data to GTP thread through an ITTI message (GTPV1U_ENB_TUNNEL_DATA_REQ). + +pdcp_config_set_security(): not yet developped + +nr_DRB_preconfiguration(): the mac layer calls this for ??? + +nr_rrc_pdcp_config_asn1_req() adds a UE in pdcp, pdcp_remove_UE() removes it + +# GTP +Gtp + UDP are two twin threads performing the data plane interface to the core network +The design is hybrid: thread and inside other threads calls. It should at least be protected by a mutex. +## GTP thread +Gtp thread has a itti interface: queue TASK_GTPV1_U +The interface is about full definition: control messages (create/delet GTP tunnels) and data messages (user plane UL and DL). +PDCP layer push to the GTP queue (outside UDP thread that do almost nothing and work only with GTP thread) is to push a UL packet. + + +## GTP thread running code from other layers +gtp thread calls directly pdcp_data_req(), so it runs inside it's context internal pdcp structures updates + +## inside other threads +gtpv1u_create_s1u_tunnel(), delete tunnel, ... functions are called inside the other threads, without mutex. + +# New GTP +## initialization +Coexistance until full merge with legacy GTP +cmake new option: NEW_GTPU to use the new implementation (it changes for the entire executable) +It is possible to use both old and new GTP in same executable because the itti task and all functions names are different +Current status of new implementation: not tested, X2 not developped, 5G new GTP option not developped, remain issues on data coming from void: muid, enb_flag, ... + +ocp_gtpv1uTask(): this creates only the thread, doesn't configure anything +gtpv1Init(): creates a listening socket to Linux for a given reception and select a local IP address + +newGtpuCreateTunnel() this function will replace the xxx_create_tunnel_xxx() for various cases +This creates a outgoing context for a teid (in input), it computes and return the incoming teid that will be used for incoming packets +These teids and in a "instance", so in a Linux socket: same teid can co-exist for different sockets + Remain here a lack to fill: the information given in the legacy funtions is not enough to fullfil the data needed by the callback +stuff like enb_flag, but also mui and more important data are not given explicitly by any legacy function (gtpv1u_create_s1u_tunnel), but the legacy and the new interface to lower layer (like pdcp) require this data. +The datamodel is still not fully understood, so this data source remain unknown +A new parameter is the callback function: will be pdpcp_data_req() and gtpv_data_req() (x2 case) for existing implementation and later other call backs like the F1-U implementation. + +incoming packets +the gtp layer retrieves the data, the teid, find out the related data: rnti, bearer and quite a lot of other parameters (not clear why, because it looks like all is statefull, so the lower layer should have the context) +if lower layers can be stateless, it is a good idea to keep the context in the gtp layer and pass it to the callback, but the design remain obfuscated. + +# NGAP +NGAP would be a itti thread as is S1AP (+twin thread SCTP that is almost void processing)? +About all messages are exchanged with RRC thread + + +
+**Note** +{: .panel-heading} +
+ + +
+
+ diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md new file mode 100644 index 0000000000..7365bc0f4c --- /dev/null +++ b/doc/TESTBenches.md @@ -0,0 +1,45 @@ +## Table of Contents ## + +1. [Legacy 1 Bench](#legacy-1-bench) +2. [Legacy 2 Bench](#legacy-2-bench) +3. [Next Bench for DEV](#next-bench-for-dev) +4. [Next Bench for CI](#next-bench-for-ci) +5. [Indoor Live Network Bench](#indoor-live-network-bench) +6. [Outdoor Live Network Bench](#outdoor-live-network-bench) + + +## Legacy 1 Bench + +**Purpose** : FDD Band 7 and Band 13, LTE-M +**Note** : Legacy1 and Legacy2 are duplicated so that they can run in parallel, thus avoiding a CI bottleneck +**Note** : Faraday Cages 1 and 2 are physically the same cage + +![image info](./testbenches_doc_resources/legacy1.jpg) + +## Legacy 2 Bench + +**Purpose** : TDD Band 40, TM2 2xTX 2xRX +**Note** : CN can run in a container, could also run on Massive + +![image info](./testbenches_doc_resources/legacy2.jpg) + +## Next Bench for DEV + +**Note** : Benetel CI can also run on this bench at night + +![image info](./testbenches_doc_resources/next_dev.jpg) + + +## Next Bench for CI + +**Note** : The current test running on Caracal could run on this bench with a N300/N300 setup + +![image info](./testbenches_doc_resources/next_ci.jpg) + +## Indoor Live Network Bench + +![image info](./testbenches_doc_resources/indoor_live.jpg) + +## Outdoor Live Network Bench + +![image info](./testbenches_doc_resources/outdoor_live.jpg) diff --git a/doc/TESTING_5GSA_setup.md b/doc/TESTING_5GSA_setup.md new file mode 100644 index 0000000000..475123c990 --- /dev/null +++ b/doc/TESTING_5GSA_setup.md @@ -0,0 +1,280 @@ + + + + + +
+ + + + + + OAI 5G SA tutorial +
+ +**TABLE OF CONTENTS** + +1. [SA setup with COTS UE](#1--sa-setup-with-cots-ue) + 1. [gNB build and configuration](#11--gnb-build-and-configuration) + 2. [OAI 5G Core Network installation and configuration](#12--oai-5g-core-network-installation-and-configuration) + 3. [Execution of SA scenario](#13--execution-of-sa-scenario) +2. [SA Setup with OAI NR UE Softmodem](#2-sa-setup-with-oai-nr-ue-softmodem) + 1. [Build and configuration](#21-build-and-configuration) + 2. [OAI 5G Core Network installation and configuration](#22--oai-5g-core-network-installation-and-configuration) + 3. [Execution of SA scenario](#23-execution-of-sa-scenario) + +In the following tutorial we describe how to deploy configure and test the two SA OAI setups: + + - SA setup with OAI gNB and COTS UE + - SA setup with OAI gNB and OAI UE + +The operating system and hardware requirements to support OAI 5G NR are described [here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/5g-nr-development-and-setup). + +# 1. SA setup with COTS UE +At the moment of writing this document interoperability with the following COTS UE devices is being tested: + + - [Quectel RM500Q-GL](https://www.quectel.com/product/5g-rm500q-gl/) + - [Simcom SIMCOM8200EA](https://www.simcom.com/product/SIM8200EA_M2.html) + - Huawei Mate 30 Pro + + End-to-end control plane signaling to achieve a 5G SA connection, UE registration and PDU session establishment with the CN, as well as some basic user-plane traffic tests have been validated so far using SIMCOM/Quectel modules and Huawei Mate 30 pro. In terms of interoperability with different 5G Core Networks, so far this setup has been tested with: + + + - [OAI CN](https://openairinterface.org/oai-5g-core-network-project/) + - Nokia SA Box + - [Free CN](https://www.free5gc.org/) + + +## 1.1 gNB build and configuration +To get the code and build the gNB executable: + +### Ubuntu 18.04 +```bash + git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git + git checkout develop + cd openairinterface5g/ + source oaienv + cd cmake_targets/ + ./build_oai -I -w USRP #For OAI first time installation only to install software dependencies + ./build_oai --gNB -w USRP +``` + +### Ubuntu 20.04 +```bash + # Build UHD from source + # https://files.ettus.com/manual/page_build_guide.html + sudo apt-get install libboost-all-dev libusb-1.0-0-dev doxygen python3-docutils python3-mako python3-numpy python3-requests python3-ruamel.yaml python3-setuptools cmake build-essential + + git clone https://github.com/EttusResearch/uhd.git + cd uhd/host + mkdir build + cd build + cmake ../ + make -j 4 + make test # This step is optional + sudo make install + sudo ldconfig + sudo uhd_images_downloader + + + git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git + git checkout develop + + # Install dependencies in Ubuntu 20.04 + cd + cd openairinterface5g/ + source oaienv + cd cmake_targets/ + ./install_external_packages.ubuntu20 + + # Build OAI gNB + cd + cd openairinterface5g/ + source oaienv + cd cmake_targets/ + ./build_oai --gNB -w USRP +``` + +A reference configuration file for the gNB is provided [here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf). + + +In the following, we highlight the fields of the file that have to be configured according to the configuration and interfaces of the Core Network. First, the PLMN section has to be filled with the proper values that match the configuration of the AMF and the UE USIM. +```bash + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x1; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + }); +``` +Then, the source and destination IP interfaces for the communication with +the Core Network also need to be set as shown below. + +```bash + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.70.132"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; +``` +In the first part (*amf_ip_address*) we specify the IP of the AMF and in the second part (*NETWORK_INTERFACES*) we specify the gNB local interface with AMF (N2 interface) and the UPF (N3 interface). + +**CAUTION:** the `192.168.70.132` AMF IF address is the OAI-CN5G `AMF` Container IP address. You certainly will need to do some networking manipulations for the `gNB` server to be able to see this AMF container. + +Please read [CN5G tutorial for more details](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md). + +### **gNB configuration in CU/DU split mode** +For the configuration of the gNB in CU and DU blocks, the following sample configuration files are provided for the [CU](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf) and the [DU](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf) entities respectively. These configuration files have to be updated with the IP addresses of the CU and the DU over the F1 interface. For example, in the following section from the DU configuration file, *local_n_address* corresponds to the DU address and *remote_n_address* corresponds to the CU address: + +```bash +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "f1"; + local_n_if_name = "lo"; + local_n_address = "127.0.0.3"; + remote_n_address = "127.0.0.4"; + local_n_portc = 601; + local_n_portd = 2152; + remote_n_portc = 600; + remote_n_portd = 2152; + + } +); +``` + + +At the point of writing this document the control-plane exchanges between the CU and the DU over *F1-C* interface, as well as some IP traffic tests over *F1-U* have been validated using the OAI gNB/nrUE in RFSIMULATOR mode. + +*These extensions are not yet fully integrated into develop branch, as they are under merge request. Until they get fully integrated, the CU/DU functionalities can be tested in [NR_F1C_F1U_extensions](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/NR_F1C_F1U_extensions) branch.* + +## 1.2 OAI 5G Core Network installation and configuration +The instructions for the installation of OAI CN components (AMF, SMF, NRF, UPF) using `docker-compose` can be found [here](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md). + +## 1.3 Execution of SA scenario + +After having configured the gNB, we can start the individual components in the following sequence: + + - Launch 5G Core Network + - Launch gNB + - Launch COTS UE (disable airplane mode) + +The execution command to start the gNB (in monolithic mode) is the following: +```bash +cd cmake_targets/ran_build/build +sudo ./nr-softmodem -E --sa -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +``` + +# 2. SA Setup with OAI NR UE Softmodem +The SA setup with OAI UE has been validated with **RFSIMULATOR**. Both control plane and user plane for the successful UE registration and PDU Session establishment has been verified with OAI and Nokia SA Box CNs. + +In the following, we provide the instructions on how to build, configure and execute this SA setup. + +### NAS configuration for the OAI UE +The NAS configuration parameters of the OAI UE can be set as input parameters, configuration file or can be hardcoded. More specifically: +- SUCI (*Subscription Concealed Identifier*) +- USIM_API_K and OPc keys +- NSSAI (*Network Slice Assistance Information*) +- DNN (*Data Network Name*) + +Below is a sample configuration file that can be parsed through the execution command ([section 2.3](#23-execution-of-sa-scenario)). + +```bash +uicc0 = { +imsi = "208990000007487"; +key = "fec86ba6eb707ed08905757b1bb44b8f"; +opc= "C42449363BBAD02B66D16BC975D77CC1"; +dnn= "oai"; +nssai_sst=1; +nssai_sd=1; +} +``` + +Alternatively, the values can be hardcoded/edited in source file ***openair3/UICC/usim_interface.c*** through the following lines: +```bash +#define UICC_PARAMS_DESC {\ + {"imsi", "USIM IMSI\n", 0, strptr:&(uicc->imsiStr), defstrval:"2089900007487", TYPE_STRING, 0 },\ + {"nmc_size" "number of digits in NMC", 0, iptr:&(uicc->nmc_size), defintval:2, TYPE_INT, 0 },\ + {"key", "USIM Ki\n", 0, strptr:&(uicc->keyStr), defstrval:"fec86ba6eb707ed08905757b1bb44b8f", TYPE_STRING, 0 },\ + {"opc", "USIM OPc\n", 0, strptr:&(uicc->opcStr), defstrval:"c42449363bbad02b66d16bc975d77cc1", TYPE_STRING, 0 },\ + {"amf", "USIM amf\n", 0, strptr:&(uicc->amfStr), defstrval:"8000", TYPE_STRING, 0 },\ + {"sqn", "USIM sqn\n", 0, strptr:&(uicc->sqnStr), defstrval:"000000", TYPE_STRING, 0 },\ + {"dnn", "UE dnn (apn)\n", 0, strptr:&(uicc->dnnStr), defstrval:"oai", TYPE_STRING, 0 },\ + {"nssai_sst", "UE nssai\n", 0, iptr:&(uicc->nssai_sst), defintval:1, TYPE_INT, 0 }, \ + {"nssai_sd", "UE nssai\n", 0, iptr:&(uicc->nssai_sd), defintval:1, TYPE_INT, 0 }, \ + }; +``` + +For interoperability with OAI or other CNs, it should be ensured that the configuration of the aforementioned parameters match the configuration of the corresponding subscribed user at the core network. + + +## 2.1 Build and configuration +To build the gNB and OAI UE executables: + +```bash + cd cmake_targets + # Note: For OAI first time installation please install software dependencies as described in 1.1. + ./build_oai --gNB --nrUE -w SIMU +``` +The gNB configuration can be performed according to what is described in [section 1.1](#11--gnb-build-and-configuration), using the same reference configuration file as with the RF scenario. + +## 2.2 OAI 5G Core Network installation and configuration +The instructions for the installation of OAI CN components (AMF, SMF, NRF, UPF) using `docker-compose` can be found [here](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md). + +In addition, if you do not want to build anything, please have a look at [this tutorial](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/ci-scripts/yaml_files/5g_rfsimulator/README.md). + +## 2.3 Execution of SA scenario + +The order of starting the different components should be the same as the one described in [section 1.3](#13--execution-of-sa-scenario). + +the gNB can be launched in 2 modes: + +- To launch the gNB in `monolithic` mode: + ```bash + sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \ + -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf + ``` +- To launch the gNB in `CU/DU split` mode: + + 1. Launch the CU component: + ```bash + sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \ + -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf + ``` + 2. Launch the DU component: + ```bash + sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \ + -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf + ``` + +- To launch the OAI UE (valid in `monolithic` gNB and `CU/DU split` gNB): + ```bash +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 \ + --rfsim --sa --nokrnmod -O +``` + +The IP address at the execution command of the OAI UE corresponds to the target IP of the gNB host that the RFSIMULATOR at the UE will connect to. In the above example, we assume that the gNB and UE are running on the same host so the specified address (127.0.0.1) is the one of the loopback interface. diff --git a/doc/TESTING_GNB_W_COTS_UE.md b/doc/TESTING_GNB_W_COTS_UE.md index a16b4dbe13..84f43bfc27 100644 --- a/doc/TESTING_GNB_W_COTS_UE.md +++ b/doc/TESTING_GNB_W_COTS_UE.md @@ -1,23 +1,35 @@ -STATUS 2020/07/30 : under continuous improvement ; updated the configuration files links with CI approved reference files +STATUS 2020/10/15 : added External Resources section and links ## Table of Contents ## -1. [Configuration Overview](#configuration-overview) -2. [SW Repository / Branch](#repository) -3. [Architecture Setup](#architecture-setup) -4. [Build / Install](#build-and-install) -5. [Run / Test](#run-and-test) -6. [Test case](#test-case) -7. [Log file monitoring](#log-file-monitoring) -6. [Required tools for debug](#required-tools-for-debug) -7. [Status of interoperability](#status-of-interoperability) +1. [External Resources](#external-resources) +2. [Configuration Overview](#configuration-overview) +3. [SW Repository / Branch](#repository) +4. [Architecture Setup](#architecture-setup) +5. [Build / Install](#build-and-install) +6. [Run / Test](#run-and-test) +7. [Test case](#test-case) +8. [Log file monitoring](#log-file-monitoring) +9. [Required tools for debug](#required-tools-for-debug) +10. [Status of interoperability](#status-of-interoperability) +11. [CI integration](#ci-integration) + + +## External Resources + +Additional Resources to this page can be found here (special mention to Walter Maguire ) : +https://docs.google.com/document/d/1pL8Szm0ocGxdl5ESVp12Ff71a4PbhCb9SpvbLZzwYbo/edit?usp=sharing +At time of writing, the openairinterface5G Commit Tag is 2020.w39 + + +Faraday Cages can be found here : +http://www.saelig.com/MFR00066/ste2300.htm + ## Configuration Overview * Non Standalone (NSA) configuration : initial Control Plane established between UE and RAN eNB, then User Plane established between UE and gNB, Core network is 4G based supporting rel 15 - -* Commercial UE: Oppo Reno 5G * OAI Software Defined gNB and eNB * eNB RF front end: USRP (ETTUS) B200 Mini or B210 * gNB RF front end: USRP (ETTUS) B200 Mini or B210 (N310 will be needed for MIMO and wider BW's) @@ -26,6 +38,19 @@ STATUS 2020/07/30 : under continuous improvement ; updated the configuration fil * BW: 40MHz * Antenna scheme: SISO +## COTS UEs + +Our code might not work with all 5G phones yet, but we are constantly improving it. Here is a list of COTS UEs that we know that work with OAI. + +* Oppo Reno 5G +* Samsung A90 5G +* Samsung A42 5G +* Google Pixel 5G (note1) +* Simcom SIMCOM8200EA +* Quectel RM500Q-GL + +Note1: In the version we have at Eurecom, you need to set the PLMN to 50501, and you also need to change the firmware to "11.0.0 (RD1A.201105.003.B1, Nov 2020, EU carriers)" (see https://developers.google.com/android/images) + ## Repository https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop @@ -70,7 +95,7 @@ cd cmake_targets/ - **EPC** for reference: -https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master-documentation/docs/DEPLOY_HOME.md +https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME.md @@ -194,7 +219,7 @@ The order to run the different components is important: 1- first, CN 2- then, eNB 3- then, gNB -4- finally, switch UE from airplane mode OFF to ON +4- finally, switch UE from airplane mode ON to OFF (ie Radio from OFF to ON) It is recommended to redirect the run commands to the same log file (fur further analysis and debug), using ```| tee **YOUR_LOG_FILE**``` especially for eNB and gNB. It is not very useful for the CN. @@ -204,7 +229,7 @@ The test takes typically a few seconds, max 10-15 seconds. If it takes more than - **EPC** (on EPC host): for reference: -https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master-documentation/docs/DEPLOY_HOME.md +https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME.md @@ -220,17 +245,16 @@ Execute: - **gNB** (on the gNB host) +**ATTENTION** : for the gNB execution, +The **-E** option is required to enable the tri-quarter sampling rate when using a B2xx serie USRP +The **-E** option is **NOT supported** when using a a N300 USRP + Execute: ``` ~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O **YOUR_GNB_CONF_FILE** -E | tee **YOUR_LOG_FILE** ``` -**ATTENTION** : for the gNB execution, -The -E option is required to enable the tri-quarter sampling rate when using a B2xx serie USRP -The -E opton is not needed when using a a N300 USRP - - ## Test Case @@ -377,13 +401,24 @@ The following parts have been validated with FR1 COTS UE: PDCCH DCI format 1_1 and correponding PDSCH are decoded correctlyby the phone ACK/NACK (PUCCH format 0) are successfully received at gNB -- On going: - validation of HARQ procedures - Integration with higher layers to replace dummy data with real traffic +- **End-to end UL / DL traffic with HARQ procedures validated (ping, iperf)** -- Known limitations as of May 2020: - only dummy DL traffic - no UL traffic - no end-to-end traffic possible +- Known limitations as of September 2020: + DL traffic : 3Mbps + UL traffic : 1Mbps + some packet losses might still occur even in ideal channel conditions +## CI integration +The automation scripts are available on ILIADE. +The end-to-end test is integrated in the CI flow in a semi-automated manner, comprising 3 steps: +- update a YAML file comprising the IT resources definition, branch and commit number the test has to run on +- run the python script that generates the test from the YAML file +``` +python3 obj_build_from_yaml.py py_params_template.yaml fr1.sh +``` +- run the test (fr1.sh) + +At the date of writing, the test comprises the deployment of the components (epc, eNB, gNB, cots ue) and the execution of 2 pings procedures (20 pings in 20sec, then 5 pings in 1sec) + +This automation is run for every integration branch to be merged into develop. diff --git a/doc/testbenches_doc_resources/benches.vsdx b/doc/testbenches_doc_resources/benches.vsdx new file mode 100755 index 0000000000..6ad3a5b576 Binary files /dev/null and b/doc/testbenches_doc_resources/benches.vsdx differ diff --git a/doc/testbenches_doc_resources/indoor_live.jpg b/doc/testbenches_doc_resources/indoor_live.jpg new file mode 100755 index 0000000000..ce8b9cda48 Binary files /dev/null and b/doc/testbenches_doc_resources/indoor_live.jpg differ diff --git a/doc/testbenches_doc_resources/legacy1.jpg b/doc/testbenches_doc_resources/legacy1.jpg new file mode 100755 index 0000000000..c3579df3e4 Binary files /dev/null and b/doc/testbenches_doc_resources/legacy1.jpg differ diff --git a/doc/testbenches_doc_resources/legacy2.jpg b/doc/testbenches_doc_resources/legacy2.jpg new file mode 100755 index 0000000000..f40d167a2d Binary files /dev/null and b/doc/testbenches_doc_resources/legacy2.jpg differ diff --git a/doc/testbenches_doc_resources/next_ci.jpg b/doc/testbenches_doc_resources/next_ci.jpg new file mode 100755 index 0000000000..2d4111510c Binary files /dev/null and b/doc/testbenches_doc_resources/next_ci.jpg differ diff --git a/doc/testbenches_doc_resources/next_dev.jpg b/doc/testbenches_doc_resources/next_dev.jpg new file mode 100755 index 0000000000..72e9f63bf9 Binary files /dev/null and b/doc/testbenches_doc_resources/next_dev.jpg differ diff --git a/doc/testbenches_doc_resources/outdoor_live.jpg b/doc/testbenches_doc_resources/outdoor_live.jpg new file mode 100755 index 0000000000..eba44a3c00 Binary files /dev/null and b/doc/testbenches_doc_resources/outdoor_live.jpg differ diff --git a/doc/testing_gnb_w_cots_ue_resources/enb.conf b/doc/testing_gnb_w_cots_ue_resources/enb.conf index 58e4e86873..a6bbd98bda 100755 --- a/doc/testing_gnb_w_cots_ue_resources/enb.conf +++ b/doc/testing_gnb_w_cots_ue_resources/enb.conf @@ -187,6 +187,8 @@ eNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -236,7 +238,7 @@ MACRLCs = ( THREAD_STRUCT = ( { parallel_config = "PARALLEL_RU_L1_TRX_SPLITaaaaaa"; - worker_config = "ENABLE"; + worker_config = "WORKER_ENABLE"; } ); diff --git a/doc/testing_gnb_w_cots_ue_resources/gnb.conf b/doc/testing_gnb_w_cots_ue_resources/gnb.conf index db8aef33ba..aae22a92ba 100755 --- a/doc/testing_gnb_w_cots_ue_resources/gnb.conf +++ b/doc/testing_gnb_w_cots_ue_resources/gnb.conf @@ -53,29 +53,7 @@ gNBs = #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 0; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) - initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -129,21 +107,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - - initialULBWPk2_2 = 7; - initialULBWPmappingType_2 = 1; - # this is SS=10 L=4 - initialULBWPstartSymbolAndLength_2 = 52; msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -212,6 +175,8 @@ gNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ target_enb_x2_ip_address = ( { ipv4 = "192.168.18.199"; ipv6 = "192:168:30::17"; @@ -273,6 +238,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/docker/Dockerfile.base.rhel8.2 b/docker/Dockerfile.base.rhel8.2 new file mode 100644 index 0000000000..3050f09849 --- /dev/null +++ b/docker/Dockerfile.base.rhel8.2 @@ -0,0 +1,70 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 +# +#--------------------------------------------------------------------- + + +FROM registry.access.redhat.com/ubi8/ubi:latest AS ran-base +ARG NEEDED_GIT_PROXY +ENV TZ=Europe/Paris +ENV BUILD_UHD_FROM_SOURCE=True +ENV UHD_VERSION=3.15.0.0 + +COPY tmp/ca/redhat-uep.pem /etc/rhsm/ca +COPY tmp/entitlement/*.pem /etc/pki/entitlement + +#install developers pkg/repo +RUN rm -f /etc/rhsm-host && \ + yum repolist --disablerepo=* && \ + subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms && \ + yum update -y && \ + yum install -y \ + #gcc needed for build_oai + gcc gcc-c++ \ + diffutils \ + file \ + psmisc \ + git \ + # python3-pip and pyyaml are used for conf template generation + python3-pip \ + #unzip is needed for protobuf + unzip && \ + pip3 install --ignore-installed pyyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +# In some network environments, GIT proxy is required +RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi" + +#create the WORKDIR +WORKDIR /oai-ran +COPY . . + +#run build_oai -I to get the builder image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai -I -w USRP && \ + rm /etc/pki/entitlement/*pem diff --git a/docker/Dockerfile.base.ubuntu18 b/docker/Dockerfile.base.ubuntu18 new file mode 100644 index 0000000000..ca23688430 --- /dev/null +++ b/docker/Dockerfile.base.ubuntu18 @@ -0,0 +1,62 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu 18.04 +# +#--------------------------------------------------------------------- + + +FROM ubuntu:bionic AS ran-base +ARG NEEDED_GIT_PROXY +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/Paris +ENV BUILD_UHD_FROM_SOURCE=True +ENV UHD_VERSION=3.15.0.0 + +#install developers pkg/repo +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + #gcc needed for build_oai + build-essential \ + psmisc \ + git \ + xxd \ + #unzip is needed for protobuf + unzip \ + # python3-pip for conf template generation + python3-pip && \ + pip3 install --ignore-installed pyyaml + +# In some network environments, GIT proxy is required +RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi" + +#create the WORKDIR +WORKDIR /oai-ran +COPY . . + +#run build_oai -I to get the builder image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai -I -w USRP diff --git a/docker/Dockerfile.build.rhel8.2 b/docker/Dockerfile.build.rhel8.2 new file mode 100644 index 0000000000..7ddfcdc034 --- /dev/null +++ b/docker/Dockerfile.build.rhel8.2 @@ -0,0 +1,38 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu 18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest as ran-build + +RUN rm -Rf /oai-ran +WORKDIR /oai-ran +COPY . . + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai --eNB --gNB --RU --UE --nrUE --ninja -w USRP --verbose-ci diff --git a/docker/Dockerfile.build.ubuntu18 b/docker/Dockerfile.build.ubuntu18 new file mode 100644 index 0000000000..b479ee90d9 --- /dev/null +++ b/docker/Dockerfile.build.ubuntu18 @@ -0,0 +1,38 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu 18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest as ran-build + +RUN rm -Rf /oai-ran +WORKDIR /oai-ran +COPY . . + +# build all targets so final targets can be created afterwards +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai --eNB --gNB --RU --UE --nrUE --ninja -w USRP --verbose-ci diff --git a/docker/Dockerfile.eNB.rhel7.oc4-4 b/docker/Dockerfile.eNB.rhel7.oc4-4 new file mode 100644 index 0000000000..85c2a17ead --- /dev/null +++ b/docker/Dockerfile.eNB.rhel7.oc4-4 @@ -0,0 +1,83 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL7 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + +FROM image-registry.openshift-image-registry.svc:5000/oai/oai-ran:latest AS enb-build + + +WORKDIR /oai-enb +COPY . . + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai --eNB + + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi7/ubi:latest as oai-enb + +# Entitlements and RHSM configurations are Open-Shift Secret and ConfigMaps +# It is pre-requisite +RUN rm -Rf /etc/rhsm/ca /etc/pki/entitlement +# Copy the entitlements +COPY ./etc-pki-entitlement /etc/pki/entitlement +# Copy the subscription manager configurations +COPY ./rhsm-conf /etc/rhsm +COPY ./rhsm-ca /etc/rhsm/ca + + +#install developers pkg/repo +RUN rm /etc/rhsm-host && \ + # Initialize /etc/yum.repos.d/redhat.repo + # See https://access.redhat.com/solutions/1443553 + yum repolist --disablerepo=* && \ + yum-config-manager --enable rhel-7-server-optional-rpms rhel-server-rhscl-7-rpms && \ + yum update -y && \ + yum install -y \ + lksctp-tools \ + protobuf-c \ + nettle \ + libyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf + + +WORKDIR /opt/oai-enb/bin +COPY --from=enb-build /oai-enb/targets/bin/lte-softmodem.Rel15 . + +RUN ldd lte-softmodem.Rel15 + +#EXPOSE 2152/udp # S1U, GTP/UDP +#EXPOSE 22100/tcp # ? +#EXPOSE 36412/udp # S1C, SCTP/UDP +#EXPOSE 36422/udp # X2C, SCTP/UDP +#EXPOSE 50000/udp # IF5 / ORI (control) +#EXPOSE 50001/udp # IF5 / ECPRI (data) + +#CMD ["/opt/oai-enb/bin/lte-softmodem", "-O", "/opt/oai-enb/etc/enb.conf"] +#ENTRYPOINT ["/opt/oai-enb/bin/entrypoint.sh"] + diff --git a/docker/Dockerfile.eNB.rhel8.2 b/docker/Dockerfile.eNB.rhel8.2 new file mode 100644 index 0000000000..bb0a9cb064 --- /dev/null +++ b/docker/Dockerfile.eNB.rhel8.2 @@ -0,0 +1,120 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest AS enb-base + +FROM ran-build:latest AS enb-build + +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/enb_parameters.yaml && \ + cp /oai-ran/docker/scripts/enb_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-enb +ENV TZ=Europe/Paris + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + lksctp-tools \ + nettle \ + tzdata \ + procps-ng \ + atlas \ + python3 \ + python3-pip \ + net-tools \ + iputils \ + iproute \ + libyaml && \ + pip3 install six && \ + pip3 install requests && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-enb/bin +COPY --from=enb-build \ + /oai-ran/targets/bin/lte-softmodem.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +COPY --from=enb-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libcoding.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_iqplayer.so \ + /usr/local/lib/ + +COPY --from=enb-base \ + /lib64/libconfig.so.9 \ + /lib64/libblas.so.3 \ + /lib64/liblapack.so.3 \ + /lib64/liblapacke.so.3 \ + /lib64/libboost_chrono.so.1.66.0 \ + /lib64/libboost_date_time.so.1.66.0 \ + /lib64/libboost_filesystem.so.1.66.0 \ + /lib64/libboost_program_options.so.1.66.0 \ + /lib64/libboost_serialization.so.1.66.0 \ + /lib64/libboost_thread.so.1.66.0 \ + /lib64/libboost_system.so.1.66.0 \ + /lib64/libboost_unit_test_framework.so.1.66.0 \ + /lib64/libboost_atomic.so.1.66.0 \ + /lib64/libboost_timer.so.1.66.0 \ + /lib64/libboost_regex.so.1.66.0 \ + /lib64/libicudata.so.60 \ + /lib64/libicui18n.so.60 \ + /lib64/libicuuc.so.60 \ + /lib64/ + + +# Now we are copying from builder-image the UHD files. +COPY --from=enb-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=enb-base /usr/local/lib/libprotobuf-c.so.1 /usr/local/lib +COPY --from=enb-base /usr/local/lib64/libuhd.so.3.15.0 /usr/local/lib64 +COPY --from=enb-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-enb/bin + +WORKDIR /usr/local/share/uhd/rfnoc +COPY --from=enb-base /usr/local/share/uhd/rfnoc/ . + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for eNB +WORKDIR /opt/oai-enb/etc +COPY --from=enb-build /oai-ran/docker/etc . + +WORKDIR /opt/oai-enb + +# 2152 --> S1U, GTP/UDP +# 36412 --> S1C, SCTP/UDP +# 36422 --> X2C, SCTP/UDP +EXPOSE 2152/udp 36412/udp 36422/udp + +ENTRYPOINT ["/opt/oai-enb/bin/entrypoint.sh"] +CMD ["/opt/oai-enb/bin/lte-softmodem.Rel15", "-O", "/opt/oai-enb/etc/enb.conf"] diff --git a/docker/Dockerfile.eNB.rhel8.2.oc4-4 b/docker/Dockerfile.eNB.rhel8.2.oc4-4 new file mode 100644 index 0000000000..5b784c08a2 --- /dev/null +++ b/docker/Dockerfile.eNB.rhel8.2.oc4-4 @@ -0,0 +1,126 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + +FROM image-registry.openshift-image-registry.svc:5000/oai/oai-ran:rhel8-latest AS enb-build + + +WORKDIR /oai-ran + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + rm -Rf log && \ + mkdir -p log && \ + ./build_oai --eNB --ninja -w USRP + +# debug +#RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-softmodem.Rel15 +#RUN ls -ls /oai-ran/targets/bin +#RUN ls -ls /oai-ran/cmake_targets/ran_build/build/*.so + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-enb + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + lksctp-tools \ + nettle \ + atlas \ + net-tools \ + iproute \ + iputils \ + libyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-enb/bin +COPY --from=enb-build /oai-ran/targets/bin/lte-softmodem.Rel15 . + +WORKDIR /usr/local/lib/ +COPY --from=enb-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . +COPY --from=enb-build /oai-ran/targets/bin/libtcp_bridge_oai.so.Rel15 . +COPY --from=enb-build /oai-ran/targets/bin/librfsimulator.so.Rel15 . +COPY --from=enb-build /oai-ran/targets/bin/liboai_usrpdevif.so.Rel15 . +COPY --from=enb-build /oai-ran/targets/bin/libcoding.so . +COPY --from=enb-build /oai-ran/targets/bin/libparams_libconfig.so . +COPY --from=enb-build /oai-ran/cmake_targets/ran_build/build/libdfts.so . +COPY --from=enb-build /oai-ran/cmake_targets/ran_build/build/liboai_iqplayer.so . +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_eth_transpro.so.Rel15 /usr/local/lib/liboai_transpro.so" +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so.Rel15 /usr/local/lib/liboai_device.so" +RUN /bin/bash -c "ln -s /usr/local/lib/librfsimulator.so.Rel15 /usr/local/lib/librfsimulator.so" + +COPY --from=enb-build /usr/local/lib/libprotobuf-c.so.1 . + +COPY --from=enb-build /lib64/libconfig.so.9 /lib64 +COPY --from=enb-build /lib64/libblas.so.3 /lib64 +COPY --from=enb-build /lib64/liblapack.so.3 /lib64 +COPY --from=enb-build /lib64/liblapacke.so.3 /lib64 +COPY --from=enb-build /lib64/libboost_chrono.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_date_time.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_filesystem.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_program_options.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_serialization.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_thread.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_system.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_unit_test_framework.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_atomic.so.1.66.0 /lib64 +COPY --from=enb-build /lib64/libboost_timer.so.1.66.0 /lib64 +COPY --from=enb-build /usr/local/lib64/libuhd.so.4.0.0 /usr/local/lib64 + +RUN ldconfig + +#debug +RUN ldd /usr/local/lib/liboai_eth_transpro.so.Rel15 +RUN ldd /usr/local/lib/libtcp_bridge_oai.so.Rel15 +RUN ldd /usr/local/lib/librfsimulator.so.Rel15 +RUN ldd /usr/local/lib/liboai_usrpdevif.so.Rel15 +RUN ldd /usr/local/lib/libcoding.so +RUN ldd /usr/local/lib/libparams_libconfig.so +RUN ldd /usr/local/lib/libdfts.so +RUN ldd /usr/local/lib/liboai_iqplayer.so +RUN ldd /opt/oai-enb/bin/lte-softmodem.Rel15 + +# Copy the relevant configuration files for eNB +WORKDIR /opt/oai-enb/etc +COPY --from=enb-build /oai-ran/ci-scripts/conf_files/enb.* . +COPY --from=enb-build /oai-ran/ci-scripts/conf_files/rcc.* . +COPY --from=enb-build /oai-ran/ci-scripts/conf_files/cu.* . +COPY --from=enb-build /oai-ran/ci-scripts/conf_files/du.* . +COPY --from=enb-build /oai-ran/ci-scripts/conf_files/rru.* . + +WORKDIR /opt/oai-enb + +#EXPOSE 2152/udp # S1U, GTP/UDP +#EXPOSE 22100/tcp # ? +#EXPOSE 36412/udp # S1C, SCTP/UDP +#EXPOSE 36422/udp # X2C, SCTP/UDP +#EXPOSE 50000/udp # IF5 / ORI (control) +#EXPOSE 50001/udp # IF5 / ECPRI (data) + +#CMD ["/opt/oai-enb/bin/lte-softmodem", "-O", "/opt/oai-enb/etc/enb.conf"] +#ENTRYPOINT ["/opt/oai-enb/bin/entrypoint.sh"] +CMD ["sleep", "infinity"] diff --git a/docker/Dockerfile.eNB.ubuntu18 b/docker/Dockerfile.eNB.ubuntu18 new file mode 100644 index 0000000000..23cea729ca --- /dev/null +++ b/docker/Dockerfile.eNB.ubuntu18 @@ -0,0 +1,116 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu 18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest as enb-base + +FROM ran-build:latest AS enb-build + +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/enb_parameters.yaml && \ + cp /oai-ran/docker/scripts/enb_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM ubuntu:bionic as oai-enb +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/Paris + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + software-properties-common \ + tzdata \ + procps \ + libsctp1 \ + libnettle6 \ + libblas3 \ + libatlas3-base \ + libconfig9 \ + openssl \ + net-tools \ + iputils-ping \ + iproute2 \ + iperf \ + python \ + python3 \ + python3-six \ + python3-requests \ + libusb-1.0-0 \ + libyaml-0-2 && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /opt/oai-enb/bin +COPY --from=enb-build \ + /oai-ran/targets/bin/lte-softmodem.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +COPY --from=enb-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libcoding.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_iqplayer.so \ + /usr/local/lib/ + +# Now we are copying from builder-image the UHD files. +COPY --from=enb-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=enb-base \ + /usr/local/lib/libuhd.so.3.15.0 \ + /usr/local/lib/libprotobuf-c.so.1 \ + /usr/local/lib/ +COPY --from=enb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-enb/bin +COPY --from=enb-base \ + /usr/lib/x86_64-linux-gnu/libboost_date_time.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/ + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for eNB +WORKDIR /opt/oai-enb/etc +COPY --from=enb-build /oai-ran/docker/etc . + +WORKDIR /opt/oai-enb + +# 2152 --> S1U, GTP/UDP +# 36412 --> S1C, SCTP/UDP +# 36422 --> X2C, SCTP/UDP +EXPOSE 2152/udp 36412/udp 36422/udp +#EXPOSE 22100/tcp # ? +#EXPOSE 50000/udp # IF5 / ORI (control) +#EXPOSE 50001/udp # IF5 / ECPRI (data) + +ENTRYPOINT ["/opt/oai-enb/bin/entrypoint.sh"] +CMD ["/opt/oai-enb/bin/lte-softmodem.Rel15", "-O", "/opt/oai-enb/etc/enb.conf"] diff --git a/docker/Dockerfile.gNB.rhel7.oc4-4 b/docker/Dockerfile.gNB.rhel7.oc4-4 new file mode 100644 index 0000000000..5165dd9715 --- /dev/null +++ b/docker/Dockerfile.gNB.rhel7.oc4-4 @@ -0,0 +1,89 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL7 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + +FROM image-registry.openshift-image-registry.svc:5000/oai/oai-ran:latest AS gnb-build + + +WORKDIR /oai-gnb +COPY . . + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai --gNB + + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi7/ubi:latest as oai-gnb + +# Entitlements and RHSM configurations are Open-Shift Secret and ConfigMaps +# It is pre-requisite +RUN rm -Rf /etc/rhsm/ca /etc/pki/entitlement +# Copy the entitlements +COPY ./etc-pki-entitlement /etc/pki/entitlement +# Copy the subscription manager configurations +COPY ./rhsm-conf /etc/rhsm +COPY ./rhsm-ca /etc/rhsm/ca + + +#install developers pkg/repo +RUN rm /etc/rhsm-host && \ + # Initialize /etc/yum.repos.d/redhat.repo + # See https://access.redhat.com/solutions/1443553 + yum repolist --disablerepo=* && \ + yum-config-manager --enable rhel-7-server-optional-rpms rhel-server-rhscl-7-rpms && \ + yum update -y && \ + yum install -y \ + libXpm \ + libX11 \ + atlas \ + blas \ + lapack \ + lksctp-tools \ + protobuf-c \ + nettle \ + libyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-gnb/bin +COPY --from=gnb-build /oai-gnb/targets/bin/nr-softmodem.Rel15 . +WORKDIR /lib64 +COPY --from=gnb-build /lib64/libforms.so.2 . + +RUN ldd /opt/oai-gnb/bin/nr-softmodem.Rel15 + +#EXPOSE 2152/udp # S1U, GTP/UDP +#EXPOSE 22100/tcp # ? +#EXPOSE 36412/udp # S1C, SCTP/UDP +#EXPOSE 36422/udp # X2C, SCTP/UDP +#EXPOSE 50000/udp # IF5 / ORI (control) +#EXPOSE 50001/udp # IF5 / ECPRI (data) + +#CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +#ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] + diff --git a/docker/Dockerfile.gNB.rhel8.2 b/docker/Dockerfile.gNB.rhel8.2 new file mode 100644 index 0000000000..832fa17153 --- /dev/null +++ b/docker/Dockerfile.gNB.rhel8.2 @@ -0,0 +1,126 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest AS gnb-base + +FROM ran-build:latest AS gnb-build + +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/gnb_parameters.yaml && \ + cp /oai-ran/docker/scripts/gnb_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-gnb +ENV TZ=Europe/Paris + +RUN yum repolist --disablerepo=* && \ + yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + procps-ng \ + libXpm \ + libX11 \ + atlas \ + lksctp-tools \ + nettle \ + tzdata \ + python3 \ + python3-pip \ + net-tools \ + iputils \ + libyaml && \ + pip3 install six && \ + pip3 install requests && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-gnb/bin +COPY --from=gnb-build \ + /oai-ran/targets/bin/nr-softmodem.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +COPY --from=gnb-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libcoding.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_optim.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_optim8seg.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_orig.so \ + /usr/local/lib/ + +COPY --from=gnb-base \ + /lib64/libconfig.so.9 \ + /lib64/libforms.so.2 \ + /lib64/libblas.so.3 \ + /lib64/liblapack.so.3 \ + /lib64/liblapacke.so.3 \ + /lib64/libboost_chrono.so.1.66.0 \ + /lib64/libboost_date_time.so.1.66.0 \ + /lib64/libboost_filesystem.so.1.66.0 \ + /lib64/libboost_program_options.so.1.66.0 \ + /lib64/libboost_serialization.so.1.66.0 \ + /lib64/libboost_thread.so.1.66.0 \ + /lib64/libboost_system.so.1.66.0 \ + /lib64/libboost_unit_test_framework.so.1.66.0 \ + /lib64/libboost_atomic.so.1.66.0 \ + /lib64/libboost_timer.so.1.66.0 \ + /lib64/libboost_regex.so.1.66.0 \ + /lib64/libicudata.so.60 \ + /lib64/libicui18n.so.60 \ + /lib64/libicuuc.so.60 \ + /lib64/ + +# Now we are copying from builder-image the UHD files. +COPY --from=gnb-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=gnb-base /usr/local/lib/libprotobuf-c.so.1 /usr/local/lib +COPY --from=gnb-base /usr/local/lib64/libuhd.so.3.15.0 /usr/local/lib64 +COPY --from=gnb-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-gnb/bin + +WORKDIR /usr/local/share/uhd/rfnoc +COPY --from=gnb-base /usr/local/share/uhd/rfnoc/ . + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for gNB +WORKDIR /opt/oai-gnb/etc +COPY --from=gnb-build /oai-ran/docker/etc . + +WORKDIR /opt/oai-gnb +#EXPOSE 2152/udp # S1U, GTP/UDP +#EXPOSE 22100/tcp # ? +#EXPOSE 36412/udp # S1C, SCTP/UDP +#EXPOSE 36422/udp # X2C, SCTP/UDP +#EXPOSE 50000/udp # IF5 / ORI (control) +#EXPOSE 50001/udp # IF5 / ECPRI (data) + +ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] +CMD ["/opt/oai-gnb/bin/nr-softmodem.Rel15", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.gNB.rhel8.2.oc4-4 b/docker/Dockerfile.gNB.rhel8.2.oc4-4 new file mode 100644 index 0000000000..1e1eba016e --- /dev/null +++ b/docker/Dockerfile.gNB.rhel8.2.oc4-4 @@ -0,0 +1,130 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + +FROM image-registry.openshift-image-registry.svc:5000/oai/oai-ran:rhel8-latest AS gnb-build + + +WORKDIR /oai-ran + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + rm -Rf log && \ + mkdir -p log && \ + ./build_oai --gNB --ninja -w USRP + +#debug +#RUN ldconfig -v +#RUN ldd /oai-ran/targets/bin/nr-softmodem.Rel15 +#RUN ls -lst /oai-ran/targets/bin +#RUN ls -lst /oai-ran/cmake_targets/ran_build/build/*.so + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-gnb + +RUN yum repolist --disablerepo=* && \ + yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + libXpm \ + libX11 \ + atlas \ + lksctp-tools \ + nettle \ + net-tools \ + iputils \ + libyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-gnb/bin +COPY --from=gnb-build /oai-ran/targets/bin/nr-softmodem.Rel15 . + +WORKDIR /usr/local/lib/ +COPY --from=gnb-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . +COPY --from=gnb-build /oai-ran/targets/bin/libtcp_bridge_oai.so.Rel15 . +COPY --from=gnb-build /oai-ran/targets/bin/librfsimulator.so.Rel15 . +COPY --from=gnb-build /oai-ran/targets/bin/liboai_usrpdevif.so.Rel15 . +COPY --from=gnb-build /oai-ran/targets/bin/libcoding.so . +COPY --from=gnb-build /oai-ran/targets/bin/libparams_libconfig.so . +COPY --from=gnb-build /oai-ran/cmake_targets/ran_build/build/libdfts.so . +COPY --from=gnb-build /oai-ran/cmake_targets/ran_build/build/libldpc.so . +COPY --from=gnb-build /oai-ran/cmake_targets/ran_build/build/libldpc_optim.so . +COPY --from=gnb-build /oai-ran/cmake_targets/ran_build/build/libldpc_optim8seg.so . +COPY --from=gnb-build /oai-ran/cmake_targets/ran_build/build/libldpc_orig.so . + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_eth_transpro.so.Rel15 /usr/local/lib/liboai_transpro.so" +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so.Rel15 /usr/local/lib/liboai_device.so" +RUN /bin/bash -c "ln -s /usr/local/lib/librfsimulator.so.Rel15 /usr/local/lib/librfsimulator.so" +COPY --from=gnb-build /usr/local/lib/libprotobuf-c.so.1 . + +COPY --from=gnb-build /lib64/libconfig.so.9 /lib64 +COPY --from=gnb-build /lib64/libforms.so.2 /lib64 +COPY --from=gnb-build /lib64/libblas.so.3 /lib64 +COPY --from=gnb-build /lib64/liblapack.so.3 /lib64 +COPY --from=gnb-build /lib64/liblapacke.so.3 /lib64 +COPY --from=gnb-build /lib64/libboost_chrono.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_date_time.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_filesystem.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_program_options.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_serialization.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_thread.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_system.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_unit_test_framework.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_atomic.so.1.66.0 /lib64 +COPY --from=gnb-build /lib64/libboost_timer.so.1.66.0 /lib64 +COPY --from=gnb-build /usr/local/lib64/libuhd.so.4.0.0 /usr/local/lib64 + +RUN ldconfig +#debug +RUN ldd /opt/oai-gnb/bin/nr-softmodem.Rel15 +RUN ldd /usr/local/lib/liboai_eth_transpro.so.Rel15 +RUN ldd /usr/local/lib/libtcp_bridge_oai.so.Rel15 +RUN ldd /usr/local/lib/librfsimulator.so.Rel15 +RUN ldd /usr/local/lib/liboai_usrpdevif.so.Rel15 +RUN ldd /usr/local/lib/libcoding.so +RUN ldd /usr/local/lib/libparams_libconfig.so +RUN ldd /usr/local/lib/libdfts.so +RUN ldd /usr/local/lib/libldpc.so +RUN ldd /usr/local/lib/libldpc_optim.so +RUN ldd /usr/local/lib/libldpc_optim8seg.so +RUN ldd /usr/local/lib/libldpc_orig.so + +# Copy the relevant configuration files for gNB +WORKDIR /opt/oai-gnb/etc +COPY --from=gnb-build /oai-ran/ci-scripts/conf_files/gnb.* . + +WORKDIR /opt/oai-gnb +#EXPOSE 2152/udp # S1U, GTP/UDP +#EXPOSE 22100/tcp # ? +#EXPOSE 36412/udp # S1C, SCTP/UDP +#EXPOSE 36422/udp # X2C, SCTP/UDP +#EXPOSE 50000/udp # IF5 / ORI (control) +#EXPOSE 50001/udp # IF5 / ECPRI (data) + +#CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +#ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] +CMD ["sleep", "infinity"] diff --git a/docker/Dockerfile.gNB.ubuntu18 b/docker/Dockerfile.gNB.ubuntu18 new file mode 100644 index 0000000000..66c5d7703f --- /dev/null +++ b/docker/Dockerfile.gNB.ubuntu18 @@ -0,0 +1,116 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest as gnb-base + +FROM ran-build:latest AS gnb-build + +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/gnb_parameters.yaml && \ + cp /oai-ran/docker/scripts/gnb_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM ubuntu:bionic as oai-gnb +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + software-properties-common \ + procps \ + libsctp1 \ + tzdata \ + libnettle6 \ + libblas3 \ + libatlas3-base \ + libconfig9 \ + openssl \ + net-tools \ + iproute2 \ + iputils-ping \ + python \ + python3 \ + python3-six \ + python3-requests \ + libusb-1.0-0 \ + libyaml-0-2 && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /opt/oai-gnb/bin +COPY --from=gnb-build \ + /oai-ran/targets/bin/nr-softmodem.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +COPY --from=gnb-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libcoding.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_optim.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_optim8seg.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_orig.so \ + /usr/local/lib/ + +# Now we are copying from builder-image the UHD files. +COPY --from=gnb-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=gnb-base \ + /usr/local/lib/libuhd.so.3.15.0 \ + /usr/local/lib/libprotobuf-c.so.1 \ + /usr/local/lib/ +COPY --from=gnb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-gnb/bin +COPY --from=gnb-base \ + /usr/lib/x86_64-linux-gnu/libboost_date_time.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/ + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for gNB +WORKDIR /opt/oai-gnb/etc +COPY --from=gnb-build /oai-ran/docker/etc . + +WORKDIR /opt/oai-gnb +#EXPOSE 2152/udp # S1U, GTP/UDP +#EXPOSE 22100/tcp # ? +#EXPOSE 36412/udp # S1C, SCTP/UDP +#EXPOSE 36422/udp # X2C, SCTP/UDP +#EXPOSE 50000/udp # IF5 / ORI (control) +#EXPOSE 50001/udp # IF5 / ECPRI (data) + +ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] +CMD ["/opt/oai-gnb/bin/nr-softmodem.Rel15", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/docker/Dockerfile.lteRU.rhel8.2 b/docker/Dockerfile.lteRU.rhel8.2 new file mode 100644 index 0000000000..5addbca655 --- /dev/null +++ b/docker/Dockerfile.lteRU.rhel8.2 @@ -0,0 +1,105 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest AS ru-base + +FROM ran-build:latest AS ru-build + +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/enb_parameters.yaml && \ + cp /oai-ran/docker/scripts/lte_ru_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-lte-ru +ENV TZ=Europe/Paris + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + tzdata \ + procps-ng \ + atlas \ + python3 \ + python3-pip \ + net-tools \ + iputils \ + iproute && \ + pip3 install six && \ + pip3 install requests && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-lte-ru/bin +COPY --from=ru-build \ + /oai-ran/targets/bin/oairu.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + . + +COPY --from=ru-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /usr/local/lib/ + +COPY --from=ru-base \ + /lib64/libconfig.so.9 \ + /lib64/libblas.so.3 \ + /lib64/liblapack.so.3 \ + /lib64/liblapacke.so.3 \ + /lib64/libboost_chrono.so.1.66.0 \ + /lib64/libboost_date_time.so.1.66.0 \ + /lib64/libboost_filesystem.so.1.66.0 \ + /lib64/libboost_program_options.so.1.66.0 \ + /lib64/libboost_serialization.so.1.66.0 \ + /lib64/libboost_thread.so.1.66.0 \ + /lib64/libboost_system.so.1.66.0 \ + /lib64/libboost_unit_test_framework.so.1.66.0 \ + /lib64/libboost_atomic.so.1.66.0 \ + /lib64/libboost_timer.so.1.66.0 \ + /lib64/libboost_regex.so.1.66.0 \ + /lib64/ + +# Copying from the ran-build image the USRP needed packages +COPY --from=ru-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=ru-base /usr/local/lib64/libuhd.so.3.15.0 /usr/local/lib64 +COPY --from=ru-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ru/bin + +WORKDIR /usr/local/share/uhd/rfnoc +COPY --from=ru-base /usr/local/share/uhd/rfnoc/ . + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for RRU +WORKDIR /opt/oai-lte-ru/etc +COPY --from=ru-build /oai-ran/docker/etc/rru* ./ + +WORKDIR /opt/oai-lte-ru + +ENTRYPOINT ["/opt/oai-lte-ru/bin/entrypoint.sh"] +CMD ["/opt/oai-lte-ru/bin/oairu.Rel15", "-O", "/opt/oai-lte-ru/etc/rru.conf"] diff --git a/docker/Dockerfile.lteRU.ubuntu18 b/docker/Dockerfile.lteRU.ubuntu18 new file mode 100644 index 0000000000..1f1c903a15 --- /dev/null +++ b/docker/Dockerfile.lteRU.ubuntu18 @@ -0,0 +1,98 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu 18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest as ru-base + +FROM ran-build:latest AS ru-build + +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/enb_parameters.yaml && \ + cp /oai-ran/docker/scripts/lte_ru_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM ubuntu:bionic as oai-lte-ru +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/Paris + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + tzdata \ + procps \ + software-properties-common \ + libblas3 \ + libatlas3-base \ + libconfig9 \ + net-tools \ + python \ + python3 \ + python3-six \ + python3-requests \ + libusb-1.0-0 \ + iputils-ping \ + iproute2 && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /opt/oai-lte-ru/bin +COPY --from=ru-build \ + /oai-ran/targets/bin/oairu.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +COPY --from=ru-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /usr/local/lib/ + +# Now we are copying from builder-image the UHD files. +COPY --from=ru-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=ru-base /usr/local/lib/libuhd.so.3.15.0 /usr/local/lib +COPY --from=ru-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ru/bin + +COPY --from=ru-base \ + /usr/lib/x86_64-linux-gnu/libboost_date_time.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/ + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for RRU +WORKDIR /opt/oai-lte-ru/etc +COPY --from=ru-build /oai-ran/docker/etc/rru* ./ + +WORKDIR /opt/oai-lte-ru + +ENTRYPOINT ["/opt/oai-lte-ru/bin/entrypoint.sh"] +CMD ["/opt/oai-lte-ru/bin/oairu.Rel15", "-O", "/opt/oai-lte-ru/etc/rru.conf"] diff --git a/docker/Dockerfile.lteUE.rhel8.2 b/docker/Dockerfile.lteUE.rhel8.2 new file mode 100644 index 0000000000..2580b95278 --- /dev/null +++ b/docker/Dockerfile.lteUE.rhel8.2 @@ -0,0 +1,117 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest AS lte-ue-base + +FROM ran-build:latest AS lte-ue-build + +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_parameters.yaml && \ + python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_sim_parameters.yaml && \ + cp /oai-ran/docker/scripts/lte_ue_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-lte-ue +ENV TZ=Europe/Paris + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + lksctp-tools \ + procps-ng \ + nettle \ + tzdata \ + atlas \ + python3 \ + python3-pip \ + iproute \ + net-tools \ + iputils \ + libyaml && \ + pip3 install six && \ + pip3 install requests && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-lte-ue/bin +COPY --from=lte-ue-build \ + /oai-ran/targets/bin/lte-uesoftmodem.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + /oai-ran/targets/bin/conf2uedata \ + /oai-ran/targets/bin/nvram \ + /oai-ran/targets/bin/usim \ + ./ + +COPY --from=lte-ue-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libcoding.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libSIMU.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /usr/local/lib/ + +COPY --from=lte-ue-base \ + /lib64/libconfig.so.9 \ + /lib64/libblas.so.3 \ + /lib64/liblapack.so.3 \ + /lib64/liblapacke.so.3 \ + /lib64/libboost_chrono.so.1.66.0 \ + /lib64/libboost_date_time.so.1.66.0 \ + /lib64/libboost_filesystem.so.1.66.0 \ + /lib64/libboost_program_options.so.1.66.0 \ + /lib64/libboost_serialization.so.1.66.0 \ + /lib64/libboost_thread.so.1.66.0 \ + /lib64/libboost_system.so.1.66.0 \ + /lib64/libboost_unit_test_framework.so.1.66.0 \ + /lib64/libboost_atomic.so.1.66.0 \ + /lib64/libboost_timer.so.1.66.0 \ + /lib64/libboost_regex.so.1.66.0 \ + /lib64/libicudata.so.60 \ + /lib64/libicui18n.so.60 \ + /lib64/libicuuc.so.60 \ + /lib64/ + +# Now we are copying from builder-image the UHD files. +COPY --from=lte-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=lte-ue-base /usr/local/lib/libprotobuf-c.so.1 /usr/local/lib +COPY --from=lte-ue-base /usr/local/lib64/libuhd.so.3.15.0 /usr/local/lib64 +COPY --from=lte-ue-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ue/bin + +WORKDIR /usr/local/share/uhd/rfnoc +COPY --from=lte-ue-base /usr/local/share/uhd/rfnoc/ . + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for UE +WORKDIR /opt/oai-lte-ue/etc +COPY --from=lte-ue-build /oai-ran/docker/etc . + +WORKDIR /opt/oai-lte-ue +CMD ["/opt/oai-lte-ue/bin/lte-uesoftmodem.Rel15"] +ENTRYPOINT ["/opt/oai-lte-ue/bin/entrypoint.sh"] diff --git a/docker/Dockerfile.lteUE.rhel8.2.oc4-4 b/docker/Dockerfile.lteUE.rhel8.2.oc4-4 new file mode 100644 index 0000000000..1339d18de6 --- /dev/null +++ b/docker/Dockerfile.lteUE.rhel8.2.oc4-4 @@ -0,0 +1,124 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + +FROM image-registry.openshift-image-registry.svc:5000/oai/oai-ran:rhel8-latest AS lte-ue-build + + +WORKDIR /oai-ran + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + rm -Rf log && \ + mkdir -p log && \ + ./build_oai --UE --ninja -w USRP + +# debug +#RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-uesoftmodem.Rel15 +#RUN ls -lst /oai-ran/targets/bin +#RUN ls -lst /oai-ran/cmake_targets/ran_build/build/*.so + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-lte-ue + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + lksctp-tools \ + nettle \ + atlas \ + iproute \ + net-tools \ + iputils \ + libyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-lte-ue/bin +COPY --from=lte-ue-build /oai-ran/targets/bin/lte-uesoftmodem.Rel15 . +COPY --from=lte-ue-build /oai-ran/targets/bin/conf2uedata . +COPY --from=lte-ue-build /oai-ran/targets/bin/nvram . +COPY --from=lte-ue-build /oai-ran/targets/bin/usim . +COPY --from=lte-ue-build /oai-ran/targets/bin/.ue_emm.nvram0 . +COPY --from=lte-ue-build /oai-ran/targets/bin/.ue.nvram0 . +COPY --from=lte-ue-build /oai-ran/targets/bin/.usim.nvram0 . + +WORKDIR /usr/local/lib/ +COPY --from=lte-ue-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . +COPY --from=lte-ue-build /oai-ran/targets/bin/libtcp_bridge_oai.so.Rel15 . +COPY --from=lte-ue-build /oai-ran/targets/bin/librfsimulator.so.Rel15 . +COPY --from=lte-ue-build /oai-ran/targets/bin/liboai_usrpdevif.so.Rel15 . +COPY --from=lte-ue-build /oai-ran/targets/bin/libcoding.so . +COPY --from=lte-ue-build /oai-ran/targets/bin/libparams_libconfig.so . +COPY --from=lte-ue-build /oai-ran/cmake_targets/ran_build/build/libSIMU.so . +COPY --from=lte-ue-build /oai-ran/cmake_targets/ran_build/build/libdfts.so . +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_eth_transpro.so.Rel15 /usr/local/lib/liboai_transpro.so" +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so.Rel15 /usr/local/lib/liboai_device.so" +RUN /bin/bash -c "ln -s /usr/local/lib/librfsimulator.so.Rel15 /usr/local/lib/librfsimulator.so" + +COPY --from=lte-ue-build /usr/local/lib/libprotobuf-c.so.1 . + +COPY --from=lte-ue-build /lib64/libconfig.so.9 /lib64 +COPY --from=lte-ue-build /lib64/libblas.so.3 /lib64 +COPY --from=lte-ue-build /lib64/liblapack.so.3 /lib64 +COPY --from=lte-ue-build /lib64/liblapacke.so.3 /lib64 +COPY --from=lte-ue-build /lib64/libboost_chrono.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_date_time.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_filesystem.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_program_options.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_serialization.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_thread.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_system.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_unit_test_framework.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_atomic.so.1.66.0 /lib64 +COPY --from=lte-ue-build /lib64/libboost_timer.so.1.66.0 /lib64 +COPY --from=lte-ue-build /usr/local/lib64/libuhd.so.4.0.0 /usr/local/lib64 + +RUN ldconfig + +#debug +RUN ldd /opt/oai-lte-ue/bin/lte-uesoftmodem.Rel15 +RUN ldd /opt/oai-lte-ue/bin/conf2uedata +RUN ldd /opt/oai-lte-ue/bin/nvram +RUN ldd /opt/oai-lte-ue/bin/usim +RUN ldd /usr/local/lib/liboai_eth_transpro.so.Rel15 +RUN ldd /usr/local/lib/libtcp_bridge_oai.so.Rel15 +RUN ldd /usr/local/lib/librfsimulator.so.Rel15 +RUN ldd /usr/local/lib/liboai_usrpdevif.so.Rel15 +RUN ldd /usr/local/lib/libcoding.so +RUN ldd /usr/local/lib/libparams_libconfig.so +RUN ldd /usr/local/lib/libSIMU.so +RUN ldd /usr/local/lib/libdfts.so + +# Copy the relevant configuration files for eNB +WORKDIR /opt/oai-lte-ue/etc +COPY --from=lte-ue-build /oai-ran/ci-scripts/conf_files/ue.* . +COPY --from=lte-ue-build /oai-ran/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf ./ue_usim.conf + +WORKDIR /opt/oai-lte-ue +#CMD ["/opt/oai-lte-ue/bin/lte-uesoftmodem", "-O", "/opt/oai-lte-ue/etc/enb.conf"] +#ENTRYPOINT ["/opt/oai-lte-ue/bin/entrypoint.sh"] +CMD ["sleep", "infinity"] diff --git a/docker/Dockerfile.lteUE.ubuntu18 b/docker/Dockerfile.lteUE.ubuntu18 new file mode 100644 index 0000000000..70394d8a4b --- /dev/null +++ b/docker/Dockerfile.lteUE.ubuntu18 @@ -0,0 +1,112 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest AS lte-ue-base + +FROM ran-build:latest AS lte-ue-build + +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_parameters.yaml && \ + python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_sim_parameters.yaml && \ + cp /oai-ran/docker/scripts/lte_ue_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM ubuntu:bionic as oai-lte-ue +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/Paris + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + software-properties-common \ + tzdata \ + procps \ + libsctp1 \ + libnettle6 \ + liblapacke \ + libatlas3-base \ + libconfig9 \ + openssl \ + net-tools \ + python \ + python3 \ + python3-six \ + python3-requests \ + libusb-1.0-0 \ + iputils-ping \ + iproute2 \ + iperf \ + libyaml-0-2 && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /opt/oai-lte-ue/bin +COPY --from=lte-ue-build \ + /oai-ran/targets/bin/lte-uesoftmodem.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + /oai-ran/targets/bin/conf2uedata \ + /oai-ran/targets/bin/nvram \ + /oai-ran/targets/bin/usim \ + ./ + +COPY --from=lte-ue-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libcoding.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libSIMU.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /usr/local/lib/ + +# Now we are copying from builder-image the UHD files. +COPY --from=lte-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=lte-ue-base \ + /usr/local/lib/libuhd.so.3.15.0 \ + /usr/local/lib/libprotobuf-c.so.1 \ + /usr/local/lib/ +COPY --from=lte-ue-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-lte-ue/bin + +COPY --from=lte-ue-base \ + /usr/lib/x86_64-linux-gnu/libboost_date_time.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/ + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for UE +WORKDIR /opt/oai-lte-ue/etc +COPY --from=lte-ue-build /oai-ran/docker/etc . + +WORKDIR /opt/oai-lte-ue +CMD ["/opt/oai-lte-ue/bin/lte-uesoftmodem.Rel15"] +ENTRYPOINT ["/opt/oai-lte-ue/bin/entrypoint.sh"] diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2 new file mode 100644 index 0000000000..f774638f47 --- /dev/null +++ b/docker/Dockerfile.nrUE.rhel8.2 @@ -0,0 +1,121 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest AS nr-ue-base + +FROM ran-build:latest AS nr-ue-build + +RUN cp /oai-ran/docker/scripts/nr_ue_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-nr-ue +ENV TZ=Europe/Paris + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + lksctp-tools \ + procps-ng \ + tzdata \ + nettle \ + net-tools \ + iputils \ + iproute \ + atlas \ + python3 \ + python3-pip \ + libXpm \ + libX11 \ + libyaml && \ + pip3 install six && \ + pip3 install requests && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-nr-ue/bin +COPY --from=nr-ue-build \ + /oai-ran/targets/bin/nr-uesoftmodem.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +WORKDIR /opt/oai-nr-ue/etc +COPY --from=nr-ue-build /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf . + +COPY --from=nr-ue-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libcoding.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_optim.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_optim8seg.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_orig.so \ + /usr/local/lib/ + +COPY --from=nr-ue-base \ + /lib64/libconfig.so.9 \ + /lib64/libblas.so.3 \ + /lib64/liblapack.so.3 \ + /lib64/liblapacke.so.3 \ + /lib64/libforms.so.2 \ + /lib64/libboost_chrono.so.1.66.0 \ + /lib64/libboost_date_time.so.1.66.0 \ + /lib64/libboost_filesystem.so.1.66.0 \ + /lib64/libboost_program_options.so.1.66.0 \ + /lib64/libboost_serialization.so.1.66.0 \ + /lib64/libboost_thread.so.1.66.0 \ + /lib64/libboost_system.so.1.66.0 \ + /lib64/libboost_unit_test_framework.so.1.66.0 \ + /lib64/libboost_atomic.so.1.66.0 \ + /lib64/libboost_timer.so.1.66.0 \ + /lib64/libboost_regex.so.1.66.0 \ + /lib64/libicudata.so.60 \ + /lib64/libicui18n.so.60 \ + /lib64/libicuuc.so.60 \ + /lib64/ + +# Now we are copying from builder-image the UHD files. +COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=nr-ue-base /usr/local/lib/libprotobuf-c.so.1 /usr/local/lib +COPY --from=nr-ue-base /usr/local/lib64/libuhd.so.3.15.0 /usr/local/lib64 +COPY --from=nr-ue-base /usr/local/lib64/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin + +WORKDIR /usr/local/share/uhd/rfnoc +COPY --from=nr-ue-base /usr/local/share/uhd/rfnoc/ . + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +# Copy the relevant configuration files for eNB +WORKDIR /opt/oai-nr-ue/etc +COPY --from=nr-ue-build /oai-ran/ci-scripts/conf_files/ue.* . + +WORKDIR /opt/oai-nr-ue +CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem.Rel15", "-O", "/opt/oai-nr-ue/etc/nr-ue-sim.conf"] +ENTRYPOINT ["/opt/oai-nr-ue/bin/entrypoint.sh"] diff --git a/docker/Dockerfile.nrUE.rhel8.2.oc4-4 b/docker/Dockerfile.nrUE.rhel8.2.oc4-4 new file mode 100644 index 0000000000..d900fff998 --- /dev/null +++ b/docker/Dockerfile.nrUE.rhel8.2.oc4-4 @@ -0,0 +1,121 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + +FROM image-registry.openshift-image-registry.svc:5000/oai/oai-ran:rhel8-latest AS nr-ue-build + + +WORKDIR /oai-ran + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + rm -Rf log && \ + mkdir -p log && \ + ./build_oai --nrUE --ninja -w USRP + +# debug +#RUN ldconfig -v +#RUN ldd /oai-ran/targets/bin/nr-uesoftmodem.Rel15 +#RUN ls -lst /oai-ran/targets/bin +#RUN ls -lst /oai-ran/cmake_targets/ran_build/build/*.so + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-nr-ue + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + lksctp-tools \ + nettle \ + net-tools \ + iputils \ + atlas \ + libXpm \ + libX11 \ + libyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-nr-ue/bin +COPY --from=nr-ue-build /oai-ran/targets/bin/nr-uesoftmodem.Rel15 . + +WORKDIR /usr/local/lib/ +COPY --from=nr-ue-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . +COPY --from=nr-ue-build /oai-ran/targets/bin/libtcp_bridge_oai.so.Rel15 . +COPY --from=nr-ue-build /oai-ran/targets/bin/librfsimulator.so.Rel15 . +COPY --from=nr-ue-build /oai-ran/targets/bin/liboai_usrpdevif.so.Rel15 . +COPY --from=nr-ue-build /oai-ran/targets/bin/libcoding.so . +COPY --from=nr-ue-build /oai-ran/targets/bin/libparams_libconfig.so . +COPY --from=nr-ue-build /oai-ran/cmake_targets/ran_build/build/libdfts.so . +COPY --from=nr-ue-build /oai-ran/cmake_targets/ran_build/build/libldpc.so . +COPY --from=nr-ue-build /oai-ran/cmake_targets/ran_build/build/libldpc_optim.so . +COPY --from=nr-ue-build /oai-ran/cmake_targets/ran_build/build/libldpc_optim8seg.so . +COPY --from=nr-ue-build /oai-ran/cmake_targets/ran_build/build/libldpc_orig.so . +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_eth_transpro.so.Rel15 /usr/local/lib/liboai_transpro.so" +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so.Rel15 /usr/local/lib/liboai_device.so" +RUN /bin/bash -c "ln -s /usr/local/lib/librfsimulator.so.Rel15 /usr/local/lib/librfsimulator.so" + +COPY --from=nr-ue-build /usr/local/lib/libprotobuf-c.so.1 . + +COPY --from=nr-ue-build /lib64/libconfig.so.9 /lib64 +COPY --from=nr-ue-build /lib64/libblas.so.3 /lib64 +COPY --from=nr-ue-build /lib64/liblapack.so.3 /lib64 +COPY --from=nr-ue-build /lib64/liblapacke.so.3 /lib64 +COPY --from=nr-ue-build /lib64/libforms.so.2 /lib64 +COPY --from=nr-ue-build /lib64/libboost_chrono.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_date_time.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_filesystem.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_program_options.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_serialization.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_thread.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_system.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_unit_test_framework.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_atomic.so.1.66.0 /lib64 +COPY --from=nr-ue-build /lib64/libboost_timer.so.1.66.0 /lib64 +COPY --from=nr-ue-build /usr/local/lib64/libuhd.so.4.0.0 /usr/local/lib64 + +RUN ldconfig +RUN ldd /opt/oai-nr-ue/bin/nr-uesoftmodem.Rel15 +RUN ldd /usr/local/lib/liboai_eth_transpro.so.Rel15 +RUN ldd /usr/local/lib/libtcp_bridge_oai.so.Rel15 +RUN ldd /usr/local/lib/librfsimulator.so.Rel15 +RUN ldd /usr/local/lib/liboai_usrpdevif.so.Rel15 +RUN ldd /usr/local/lib/libcoding.so +RUN ldd /usr/local/lib/libparams_libconfig.so +RUN ldd /usr/local/lib/libdfts.so +RUN ldd /usr/local/lib/libldpc.so +RUN ldd /usr/local/lib/libldpc_optim.so +RUN ldd /usr/local/lib/libldpc_optim8seg.so +RUN ldd /usr/local/lib/libldpc_orig.so + +# Copy the relevant configuration files for eNB +WORKDIR /opt/oai-nr-ue/etc +COPY --from=nr-ue-build /oai-ran/ci-scripts/conf_files/ue.* . + +WORKDIR /opt/oai-nr-ue +#CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem", "-O", "/opt/oai-nr-ue/etc/enb.conf"] +#ENTRYPOINT ["/opt/oai-nr-ue/bin/entrypoint.sh"] +CMD ["sleep", "infinity"] diff --git a/docker/Dockerfile.nrUE.ubuntu18 b/docker/Dockerfile.nrUE.ubuntu18 new file mode 100644 index 0000000000..021e8d39cf --- /dev/null +++ b/docker/Dockerfile.nrUE.ubuntu18 @@ -0,0 +1,109 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu 18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest AS nr-ue-base + +FROM ran-build:latest AS nr-ue-build + +RUN cp /oai-ran/docker/scripts/nr_ue_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +#start from scratch for target executable +FROM ubuntu:bionic as oai-nr-ue +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/Paris + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + software-properties-common \ + libsctp1 \ + procps \ + tzdata \ + libnettle6 \ + liblapacke \ + libatlas3-base \ + libconfig9 \ + openssl \ + net-tools \ + python \ + python3 \ + python3-six \ + python3-requests \ + libusb-1.0-0 \ + iputils-ping \ + iproute2 \ + iperf \ + libyaml-0-2 && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /opt/oai-nr-ue/bin +COPY --from=nr-ue-build \ + /oai-ran/targets/bin/nr-uesoftmodem.Rel15 \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +WORKDIR /opt/oai-nr-ue/etc +COPY --from=nr-ue-build /oai-ran/ci-scripts/conf_files/nr-ue-sim.conf . + +COPY --from=nr-ue-build \ + /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ + /oai-ran/cmake_targets/ran_build/build/libtcp_bridge_oai.so \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/libcoding.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libdfts.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_optim.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_optim8seg.so \ + /oai-ran/cmake_targets/ran_build/build/libldpc_orig.so \ + /usr/local/lib/ + +# Now we are copying from builder-image the UHD files. +COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin +COPY --from=nr-ue-base \ + /usr/local/lib/libuhd.so.3.15.0 \ + /usr/local/lib/libprotobuf-c.so.1 \ + /usr/local/lib/ +COPY --from=nr-ue-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin + +COPY --from=nr-ue-base \ + /usr/lib/x86_64-linux-gnu/libboost_date_time.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_serialization.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.65.1 \ + /usr/lib/x86_64-linux-gnu/ + +RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ + ldconfig + +WORKDIR /opt/oai-nr-ue +CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem.Rel15", "-O", "/opt/oai-nr-ue/etc/nr-ue-sim.conf"] +ENTRYPOINT ["/opt/oai-nr-ue/bin/entrypoint.sh"] diff --git a/docker/Dockerfile.phySim.rhel8.2 b/docker/Dockerfile.phySim.rhel8.2 new file mode 100644 index 0000000000..0e76a12805 --- /dev/null +++ b/docker/Dockerfile.phySim.rhel8.2 @@ -0,0 +1,114 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest AS phy-sim-build + +#run build_oai to build the target image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai --phy_simulators --ninja --verbose-ci + +#start from scratch for target executable +FROM registry.access.redhat.com/ubi8/ubi:latest as oai-physim + +RUN yum update -y && \ + yum install -y --enablerepo="ubi-8-codeready-builder" \ + lksctp-tools \ + nettle \ + tzdata \ + atlas \ + hostname \ + sudo \ + procps-ng \ + net-tools \ + iputils \ + bc \ + iproute \ + libyaml && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +WORKDIR /opt/oai-physim/targets/bin +COPY --from=phy-sim-build \ + /oai-ran/targets/bin/dlsim.Rel15 \ + /oai-ran/targets/bin/nr_dlsim.Rel15 \ + /oai-ran/targets/bin/nr_prachsim.Rel15 \ + /oai-ran/targets/bin/nr_ulschsim.Rel15 \ + /oai-ran/targets/bin/polartest.Rel15 \ + /oai-ran/targets/bin/ulsim.Rel15 \ + /oai-ran/targets/bin/ldpctest.Rel15 \ + /oai-ran/targets/bin/nr_dlschsim.Rel15 \ + /oai-ran/targets/bin/nr_pbchsim.Rel15 \ + /oai-ran/targets/bin/nr_pucchsim.Rel15 \ + /oai-ran/targets/bin/nr_ulsim.Rel15 \ + /oai-ran/targets/bin/smallblocktest.Rel15 \ + ./ + +COPY --from=phy-sim-build \ + /oai-ran/targets/bin/libcoding.so \ + /lib64/liblapacke.so.3 \ + /lib64/libX11.so.6 \ + /lib64/libXpm.so.4 \ + /lib64/libxcb.so.1 \ + /lib64/libXau.so.6 \ + /lib64/libforms.so.2 \ + /lib64/libblas.so.3 \ + /lib64/liblapack.so.3 \ + /lib64/libexslt.so.0 \ + /lib64/libxslt.so.1 \ + /oai-ran/cmake_targets/phy_simulators/build/libdfts.so \ + /oai-ran/cmake_targets/phy_simulators/build/libSIMU.so \ + /oai-ran/cmake_targets/phy_simulators/build/libldpc.so \ + /oai-ran/cmake_targets/phy_simulators/build/libldpc_orig.so \ + /usr/local/lib/ + +RUN ldconfig + +# Copy some executables +WORKDIR /usr/bin/ + +COPY --from=phy-sim-build \ + /usr/bin/killall \ + /usr/bin/xmlstarlet \ + /usr/bin/svn \ + ./ + +# Copy the relevant configuration files for phySim +WORKDIR /opt/oai-physim/ + +COPY --from=phy-sim-build \ + /oai-ran/cmake_targets/autotests/run_exec_autotests.bash \ + /oai-ran/cmake_targets/autotests/test_case_list.xml \ + /opt/oai-physim/cmake_targets/autotests/ +COPY --from=phy-sim-build \ + /oai-ran/cmake_targets/autotests/tools/free_mem.bash \ + /oai-ran/cmake_targets/tools/build_helper \ + /oai-ran/cmake_targets/tools/test_helper \ + /opt/oai-physim/cmake_targets/tools/ + +#CMD ["sleep", "infinity"] diff --git a/docker/Dockerfile.ran.rhel7.oc4-4 b/docker/Dockerfile.ran.rhel7.oc4-4 new file mode 100644 index 0000000000..2f0423801a --- /dev/null +++ b/docker/Dockerfile.ran.rhel7.oc4-4 @@ -0,0 +1,74 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL7 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + + +FROM registry.access.redhat.com/ubi7/ubi:latest AS ran-base + +# Entitlements and RHSM configurations are Open-Shift Secret and ConfigMaps +# It is pre-requisite +RUN rm -Rf /etc/rhsm/ca /etc/pki/entitlement +# Copy the entitlements +COPY ./etc-pki-entitlement /etc/pki/entitlement +# Copy the subscription manager configurations +COPY ./rhsm-conf /etc/rhsm +COPY ./rhsm-ca /etc/rhsm/ca + + +#install developers pkg/repo +RUN rm /etc/rhsm-host && \ + # Initialize /etc/yum.repos.d/redhat.repo + # See https://access.redhat.com/solutions/1443553 + yum repolist --disablerepo=* && \ + yum-config-manager --enable rhel-7-server-optional-rpms rhel-server-rhscl-7-rpms && \ + yum update -y && \ + yum install -y \ + #gcc needed for build_oai + gcc gcc-c++ \ + diffutils \ + file \ + psmisc \ + git \ + #unzip is needed for protobuf + unzip && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf + +# In some network environments, GIT proxy is required +RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi" + +#create the WORKDIR +WORKDIR /oai-ran +COPY . . + +#run build_oai -I to get the builder image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai -I + +#as the image is public, we need to remove the subscription manager configurations +#RUN rm -Rf /etc/rhsm /etc/pki/entitlement + diff --git a/docker/Dockerfile.ran.rhel8.2.oc4-4 b/docker/Dockerfile.ran.rhel8.2.oc4-4 new file mode 100644 index 0000000000..93af2b0e37 --- /dev/null +++ b/docker/Dockerfile.ran.rhel8.2.oc4-4 @@ -0,0 +1,74 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for RHEL8 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + + +FROM registry.access.redhat.com/ubi8/ubi:latest AS ran-base + +# Entitlements and RHSM configurations are Open-Shift Secret and ConfigMaps +# It is pre-requisite +RUN rm -Rf /etc/rhsm/ca /etc/pki/entitlement +# Copy the entitlements +COPY ./etc-pki-entitlement /etc/pki/entitlement +# Copy the subscription manager configurations +COPY ./rhsm-conf /etc/rhsm +COPY ./rhsm-ca /etc/rhsm/ca + +#install developers pkg/repo +RUN rm /etc/rhsm-host && \ + # Initialize /etc/yum.repos.d/redhat.repo + # See https://access.redhat.com/solutions/1443553 + yum repolist --disablerepo=* && \ + subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms && \ + yum update -y && \ + yum install -y \ + #gcc needed for build_oai + gcc gcc-c++ \ + diffutils \ + file \ + psmisc \ + git \ + #unzip is needed for protobuf + unzip && \ + echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ + echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf + +# In some network environments, GIT proxy is required +RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi" + +#create the WORKDIR +WORKDIR /oai-ran +COPY . . + +#run build_oai -I to get the builder image +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai -I -w USRP + +#as the image is public, we need to remove the subscription certificates +RUN rm -Rf /etc/pki/entitlement/*.pem + diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000000..85f553c721 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,167 @@ + + + + + +
+ + + + + + OAI Docker/Podman Build and Usage Procedures +
+ +--- + +**Table of Contents** + +1. [Build Strategy](#1-build-strategy) +2. [File organization](#2-file-organization) +3. [Building using docker under Ubuntu 18.04](#3-building-using-docker-under-ubuntu-1804) +4. [Building using podman under Red Hat Entreprise Linux 8.2](#4-building-using-podman-under-red-hat-entreprise-linux-82) +5. [Running modems using docker under Ubuntu 18.04](#5-running-modems-using-docker-under-ubuntu-1804) +6. [Running modems using podman under Red Hat Entreprise Linux 8.2](#6-running-modems-using-podman-under-red-hat-entreprise-linux-82) + +--- + +# 1. Build Strategy # + +For all platforms, the strategy for building docker/podman images is the same: + +* First we create a common shared image `ran-base` that contains: + - the latest source files (by using the `COPY` function) + - all the means to build an OAI RAN executable + * all packages, compilers, ... + * especially UHD is installed +* Then, from the `ran-base` shared image, we create a shared image `ran-build` + in which all targets are compiled: + - eNB + - gNB + - lte-UE + - nr-UE +* Then from the `ran-build` shared image we can build target images for: + - eNB + - gNB + - lte-UE + - nr-UE +* These target images will only contain: + - the generated executable (for example `lte-softmodem.Rel15`) + - the generated shared libraries (for example `liboai_usrpdevif.so.Rel15`) + - the needed libraries and packages to run these generated binaries + - Some configuration file templates + - Some tools (such as `ping`, `ifconfig`) + +TO DO: + +- Proper entrypoints +- Proper port exposure +- ... + +# 2. File organization # + +Dockerfiles are named with the following naming convention: `Dockerfile.${target}.${OS-version}.${cluster-version}` + +Targets can be: + +- `base` for an image named `ran-base` (shared image) +- `ran` for an image named `ran-build` (shared image) +- `eNB` for an image named `oai-enb` +- `gNB` for an image named `oai-gnb` +- `lteUE` for an image named `oai-lte-ue` +- `nrUE` for an image named `oai-nr-ue` + +The currently-supported OS are: + +- `rhel8.2` for Red Hat Entreprise Linux +- `ubuntu18` for Ubuntu 18.04 LTS + +The currently-supported cluster version is: + +- `rhel8.2.oc4-4` + +We have also `rhel7.oc4-4` support but it will be discontinued soon. + +For more details in build within a Openshift Cluster, see [OpenShift README](../openshift/README.md) for more details. + +# 3. Building using `docker` under Ubuntu 18.04 # + +## 3.1. Pre-requisites ## + +* `git` installed +* `docker-ce` installed +* Pulling `ubuntu:bionic` from DockerHub + +## 3.2. Building the shared images ## + +Note: This can be done starting `2020.XX` tag on the `develop` branch, or any branch that includes that tag. + +There are two shared images: one that has all dependencies, and a second that compiles all targets (eNB, gNB, [nr]UE). + +```bash +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git +cd openairinterface5g +git checkout develop +``` + +In our Eurecom/OSA environment we need to pass a GIT proxy. + +```bash +docker build --target ran-base --tag ran-base:latest --file docker/Dockerfile.base.ubuntu18 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . +docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu18 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . +``` + +if you don't need it, do NOT pass any value: + +```bash +docker build --target ran-base --tag ran-base:latest --file docker/Dockerfile.base.ubuntu18 . +docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu18 . +``` + +After building both: + +```bash +docker image ls +REPOSITORY TAG IMAGE ID CREATED SIZE +ran-build latest f2633a7f5102 1 minute ago 6.81GB +ran-base latest 5c9c02a5b4a8 1 minute ago 2.4GB + +... +``` + +## 3.3. Building any target image ## + +For example, the eNB: + +```bash +docker build --target oai-enb --tag oai-enb:latest --file docker/Dockerfile.eNB.ubuntu18 . +``` + +After a while: + +``` +docker image ls +REPOSITORY TAG IMAGE ID CREATED SIZE +oai-enb latest 25ddbd8b7187 1 minute ago 516MB + 875ea3b05b60 8 minutes ago 8.18GB +ran-build latest f2633a7f5102 1 hour ago 6.81GB +ran-base latest 5c9c02a5b4a8 1 hour ago 2.4GB +``` + +Do not forget to remove the temporary image: + +``` +docker image prune --force +``` + +# 4. Building using `podman` under Red Hat Entreprise Linux 8.2 # + +TODO. + +# 5. Running modems using `docker` under Ubuntu 18.04 # + +TODO. + +# 6. Running modems using `podman` under Red Hat Entreprise Linux 8.2 # + +TODO. diff --git a/docker/scripts/enb_entrypoint.sh b/docker/scripts/enb_entrypoint.sh new file mode 100755 index 0000000000..06e94b1e7a --- /dev/null +++ b/docker/scripts/enb_entrypoint.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +set -euo pipefail + +PREFIX=/opt/oai-enb +RRC_INACTIVITY_THRESHOLD=${RRC_INACTIVITY_THRESHOLD:-0} +ENABLE_MEASUREMENT_REPORTS=${ENABLE_MEASUREMENT_REPORTS:-no} +ENABLE_X2=${ENABLE_X2:-no} +THREAD_PARALLEL_CONFIG=${THREAD_PARALLEL_CONFIG:-PARALLEL_SINGLE_THREAD} + +# Based another env var, pick one template to use +if [[ -v USE_FDD_CU ]]; then cp $PREFIX/etc/cu.fdd.conf $PREFIX/etc/enb.conf; fi +if [[ -v USE_FDD_DU ]]; then cp $PREFIX/etc/du.fdd.conf $PREFIX/etc/enb.conf; fi +if [[ -v USE_FDD_MONO ]]; then cp $PREFIX/etc/enb.fdd.conf $PREFIX/etc/enb.conf; fi +if [[ -v USE_TDD_MONO ]]; then cp $PREFIX/etc/enb.tdd.conf $PREFIX/etc/enb.conf; fi +if [[ -v USE_FDD_FAPI_RCC ]]; then cp $PREFIX/etc/rcc.nfapi.fdd.conf $PREFIX/etc/enb.conf; fi +if [[ -v USE_FDD_IF4P5_RCC ]]; then cp $PREFIX/etc/rcc.if4p5.fdd.conf $PREFIX/etc/enb.conf; fi +if [[ -v USE_TDD_IF4P5_RCC ]]; then cp $PREFIX/etc/rcc.if4p5.tdd.conf $PREFIX/etc/enb.conf; fi +if [[ -v USE_FDD_RRU ]]; then cp $PREFIX/etc/rru.fdd.conf $PREFIX/etc/enb.conf; fi +if [[ -v USE_TDD_RRU ]]; then cp $PREFIX/etc/rru.tdd.conf $PREFIX/etc/enb.conf; fi +# Sometimes, the templates are not enough. We mount a conf file on $PREFIX/etc. It can be a template itself. +if [[ -v USE_VOLUMED_CONF ]]; then cp $PREFIX/etc/mounted.conf $PREFIX/etc/enb.conf; fi + +# Only this template will be manipulated +CONFIG_FILES=`ls $PREFIX/etc/enb.conf || true` + +for c in ${CONFIG_FILES}; do + # Sometimes templates have no pattern to be replaced. + if ! grep -oP '@[a-zA-Z0-9_]+@' ${c}; then + echo "Configuration is already set" + break + fi + + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + NEW_VAR=`echo $v | sed -e "s#@##g"` + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +# Load the USRP binaries +if [[ -v USE_B2XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t b2xx +elif [[ -v USE_X3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t x3xx +elif [[ -v USE_N3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t n3xx +fi + +echo "==================================" +echo "== Starting eNB soft modem" +if [[ -v USE_ADDITIONAL_OPTIONS ]]; then + echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" + new_args=() + while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift + done + for word in ${USE_ADDITIONAL_OPTIONS}; do + new_args+=("$word") + done + echo "${new_args[@]}" + exec "${new_args[@]}" +else + echo "$@" + exec "$@" +fi diff --git a/docker/scripts/enb_parameters.yaml b/docker/scripts/enb_parameters.yaml new file mode 100644 index 0000000000..07bba4479b --- /dev/null +++ b/docker/scripts/enb_parameters.yaml @@ -0,0 +1,356 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +--- +- paths: + source_dir: "ci-scripts/conf_files/" + dest_dir: docker/etc + +- configurations: + - filePrefix: cu.band7.tm1.25PRB + outputfilename: "cu.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: local_s_if_name + env: "@F1_IF_NAME@" + - key: remote_s_address + env: "@F1_DU_IP_ADDRESS@" + - key: local_s_address + env: "@F1_CU_IP_ADDRESS@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@S1C_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@S1U_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@F1_CU_IP_ADDRESS@" + + - filePrefix: du.band7.tm1.25PRB + outputfilename: "du.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: local_n_if_name + env: "@F1_IF_NAME@" + - key: remote_n_address + env: "@F1_DU_IP_ADDRESS@" + - key: local_n_address + env: "@F1_CU_IP_ADDRESS@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + + - filePrefix: rru.fdd + outputfilename: "rru.fdd.conf" + config: + - key: local_if_name + env: "@RRU_IF4P5_IF_NAME@" + - key: remote_address + env: "@RCC_REMOTE_IP_ADDRESS@" + - key: local_address + env: "@RRU_LOCAL_IP_ADDRESS@" + - key: bands + env: "@UTRA_BAND_ID@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + + - filePrefix: rru.tdd + outputfilename: "rru.tdd.conf" + config: + - key: local_if_name + env: "@RRU_IF4P5_IF_NAME@" + - key: remote_address + env: "@RCC_REMOTE_IP_ADDRESS@" + - key: local_address + env: "@RRU_LOCAL_IP_ADDRESS@" + - key: bands + env: "@UTRA_BAND_ID@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + + - filePrefix: enb.band7.tm1.fr1.25PRB.usrpb210.conf + outputfilename: "enb.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: enable_measurement_reports + env: "@ENABLE_MEASUREMENT_REPORTS@" + - key: enable_x2 + env: "@ENABLE_X2@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@ENB_S1C_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@ENB_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@ENB_S1U_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@ENB_S1U_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@ENB_X2_IP_ADDRESS@" + - key: rrc_inactivity_threshold + env: "@RRC_INACTIVITY_THRESHOLD@" + - key: FLEXRAN_ENABLED + env: "@FLEXRAN_ENABLED@" + - key: FLEXRAN_INTERFACE_NAME + env: "@FLEXRAN_INTERFACE_NAME@" + - key: FLEXRAN_IPV4_ADDRESS + env: "@FLEXRAN_IPV4_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + + - filePrefix: enb.band40.tm1.25PRB.FairScheduler.usrpb210 + outputfilename: "enb.tdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@S1C_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@S1U_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@F1_CU_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + + - filePrefix: "rcc.band7.tm1.nfapi" + outputfilename: "rcc.nfapi.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: local_s_if_name + env: "@F1_IF_NAME@" + - key: remote_s_address + env: "@F1_DU_IP_ADDRESS@" + - key: local_s_address + env: "@F1_CU_IP_ADDRESS@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@S1C_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@S1U_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@F1_CU_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + + - filePrefix: "rcc.band7.tm1.if4p5.lo.25PRB" + outputfilename: "rcc.if4p5.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@RCC_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@RCC_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@RCC_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@RCC_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@RCC_IP_ADDRESS@" + - key: local_if_name + env: "@IF4P5_IF_NAME@" + - key: remote_address + env: "@IF4P5_RRU_IP_ADDRESS@" + - key: local_address + env: "@IF4P5_RCC_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + + - filePrefix: "rcc.band40.tm1.25PRB" + outputfilename: "rcc.if4p5.tdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@RCC_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@RCC_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@RCC_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@RCC_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@RCC_IP_ADDRESS@" + - key: local_if_name + env: "@IF4P5_IF_NAME@" + - key: remote_address + env: "@IF4P5_RRU_IP_ADDRESS@" + - key: local_address + env: "@IF4P5_RCC_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + diff --git a/docker/scripts/generateTemplate.py b/docker/scripts/generateTemplate.py new file mode 100644 index 0000000000..cc4b72a703 --- /dev/null +++ b/docker/scripts/generateTemplate.py @@ -0,0 +1,111 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import re +import yaml +import os +import sys + + +def main(): + #read yaml input parameters + f = open(f'{sys.argv[1]}',) + data = yaml.full_load(f) + dir = os.listdir(f'{data[0]["paths"]["source_dir"]}') + + #identify configs, read and replace corresponding values + for config in data[1]["configurations"]: + filePrefix = config["filePrefix"] + outputfilename = config["outputfilename"] + print('================================================') + print('filePrefix = ' + filePrefix) + print('outputfilename = ' + outputfilename) + for inputfile in dir: + if inputfile.find(filePrefix) >=0: + prefix_outputfile = {"cu.band7.tm1.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "du.band7.tm1.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "rru.fdd": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "rru.tdd": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "enb.band7.tm1.fr1.25PRB.usrpb210.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "enb.band40.tm1.25PRB.FairScheduler.usrpb210": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "rcc.band7.tm1.nfapi": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "rcc.band7.tm1.if4p5.lo.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "rcc.band40.tm1.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "gnb.band78.tm1.fr1.106PRB.usrpb210.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "gnb.band78.sa.fr1.106PRB.usrpn310.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "ue.nfapi": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "ue_sim_ci": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}' + } + print('inputfile = ' + inputfile) + if filePrefix in prefix_outputfile: + outputfile1 = prefix_outputfile[filePrefix] + + directory = f'{data[0]["paths"]["dest_dir"]}' + if not os.path.exists(directory): + os.makedirs(directory, exist_ok=True) + + with open(f'{data[0]["paths"]["source_dir"]}{inputfile}', mode='r') as inputfile, \ + open(outputfile1, mode='w') as outputfile: + for line in inputfile: + count = 0 + if re.search(r'EHPLMN_LIST', line): + outputfile.write(line) + continue + if re.search(r'sd = 0x1;', line): + templine = re.sub(r'sd = 0x1;', 'sd = 0x@NSSAI_SD0@;', line) + outputfile.write(templine) + continue + if re.search(r'sd = 0x112233;', line): + templine = re.sub(r'sd = 0x112233;', 'sd = 0x@NSSAI_SD1@;', line) + outputfile.write(templine) + continue + for key in config["config"]: + if line.find(key["key"]) >= 0: + count += 1 + if re.search(r'preference', line): + templine = line + elif re.search(r'mnc_length', line) and key["key"] == "mnc": + continue + elif re.search(r'plmn_list', line): + templine = re.sub(r'[0-9]+', '""', line) + templine = re.sub(r'\"\"', key["env"]["mcc"], templine, 1) + templine = re.sub(r'\"\"', key["env"]["mnc"], templine, 1) + templine = re.sub(r'\"\"', key["env"]["mnc_length"], templine, 1) + elif re.search('downlink_frequency', line): + templine = re.sub(r'[0-9]+', key["env"], line) + elif re.search('uplink_frequency_offset', line): + templine = re.sub(r'[0-9]+', key["env"], line) + + elif re.search(r'"(.*?)"', line): + templine = re.sub(r'(?<=")[^"]*(?=")', key["env"], line) + elif re.search(r'[0-9]', line): + templine = re.sub(r'\d+', key["env"], line) + outputfile.write(templine) + + if count == 0: + outputfile.write(line) + +if __name__ == "__main__": + main() diff --git a/docker/scripts/gnb_entrypoint.sh b/docker/scripts/gnb_entrypoint.sh new file mode 100755 index 0000000000..2fe743920e --- /dev/null +++ b/docker/scripts/gnb_entrypoint.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +set -euo pipefail + +PREFIX=/opt/oai-gnb +ENABLE_X2=${ENABLE_X2:-yes} +THREAD_PARALLEL_CONFIG=${THREAD_PARALLEL_CONFIG:-PARALLEL_SINGLE_THREAD} + +# Based another env var, pick one template to use +if [[ -v USE_NSA_TDD_MONO ]]; then cp $PREFIX/etc/gnb.nsa.tdd.conf $PREFIX/etc/gnb.conf; fi +if [[ -v USE_SA_TDD_MONO ]]; then cp $PREFIX/etc/gnb.sa.tdd.conf $PREFIX/etc/gnb.conf; fi +# Sometimes, the templates are not enough. We mount a conf file on $PREFIX/etc. It can be a template itself. +if [[ -v USE_VOLUMED_CONF ]]; then cp $PREFIX/etc/mounted.conf $PREFIX/etc/gnb.conf; fi + +# Only this template will be manipulated +CONFIG_FILES=`ls $PREFIX/etc/gnb.conf || true` + +for c in ${CONFIG_FILES}; do + # Sometimes templates have no pattern to be replaced. + if ! grep -oP '@[a-zA-Z0-9_]+@' ${c}; then + echo "Configuration is already set" + break + fi + + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + NEW_VAR=`echo $v | sed -e "s#@##g"` + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +# Load the USRP binaries +if [[ -v USE_B2XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t b2xx +elif [[ -v USE_X3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t x3xx +elif [[ -v USE_N3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t n3xx +fi + +echo "==================================" +echo "== Starting gNB soft modem" +if [[ -v USE_ADDITIONAL_OPTIONS ]]; then + echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" + new_args=() + while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift + done + for word in ${USE_ADDITIONAL_OPTIONS}; do + new_args+=("$word") + done + echo "${new_args[@]}" + exec "${new_args[@]}" +else + echo "$@" + exec "$@" +fi diff --git a/docker/scripts/gnb_parameters.yaml b/docker/scripts/gnb_parameters.yaml new file mode 100644 index 0000000000..ac5a6cb971 --- /dev/null +++ b/docker/scripts/gnb_parameters.yaml @@ -0,0 +1,96 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +--- +- paths: + source_dir: "ci-scripts/conf_files/" + dest_dir: docker/etc + +- configurations: + - filePrefix: gnb.band78.tm1.fr1.106PRB.usrpb210.conf + outputfilename: "gnb.nsa.tdd.conf" + config: + - key: Active_gNBs + env: "@GNB_NAME@" + - key: gNB_name + env: "@GNB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: enable_x2 + env: "@ENABLE_X2@" + - key: ipv4 + env: "@ENB_X2_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_S1_MME + env: "@GNB_S1C_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_S1_MME + env: "@GNB_S1C_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_S1U + env: "@GNB_S1U_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_S1U + env: "@GNB_S1U_IP_ADDRESS@" + - key: GNB_IPV4_ADDRESS_FOR_X2C + env: "@GNB_X2_IP_ADDRESS@" + - key: rrc_inactivity_threshold + env: "@RRC_INACTIVITY_THRESHOLD@" + - key: FLEXRAN_ENABLED + env: "@FLEXRAN_ENABLED@" + - key: FLEXRAN_INTERFACE_NAME + env: "@FLEXRAN_INTERFACE_NAME@" + - key: FLEXRAN_IPV4_ADDRESS + env: "@FLEXRAN_IPV4_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + + - filePrefix: gnb.band78.sa.fr1.106PRB.usrpn310.conf + outputfilename: "gnb.sa.tdd.conf" + config: + - key: Active_gNBs + env: "@GNB_NAME@" + - key: gNB_name + env: "@GNB_NAME@" + - key: mcc + env: "@MCC@" + - key: mnc + env: "@MNC@" + - key: mnc_length + env: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: sst + env: "@NSSAI_SST@" + - key: ipv4 + env: "@AMF_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_NG_AMF + env: "@GNB_NGA_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_NG_AMF + env: "@GNB_NGA_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_NGU + env: "@GNB_NGU_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_NGU + env: "@GNB_NGU_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + diff --git a/docker/scripts/lte_ru_entrypoint.sh b/docker/scripts/lte_ru_entrypoint.sh new file mode 100755 index 0000000000..297e437ac0 --- /dev/null +++ b/docker/scripts/lte_ru_entrypoint.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +set -euo pipefail + +PREFIX=/opt/oai-lte-ru + +# Based another env var, pick one template to use +if [[ -v USE_FDD_RRU ]]; then cp $PREFIX/etc/rru.fdd.conf $PREFIX/etc/rru.conf; fi +if [[ -v USE_TDD_RRU ]]; then cp $PREFIX/etc/rru.tdd.conf $PREFIX/etc/rru.conf; fi + +# Only this template will be manipulated +CONFIG_FILES=`ls $PREFIX/etc/rru.conf || true` + +for c in ${CONFIG_FILES}; do + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + NEW_VAR=`echo $v | sed -e "s#@##g"` + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +# Load the USRP binaries +if [[ -v USE_B2XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t b2xx +elif [[ -v USE_X3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t x3xx +elif [[ -v USE_N3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t n3xx +fi + +echo "==================================" +echo "== Starting eNB soft modem" +if [[ -v USE_ADDITIONAL_OPTIONS ]]; then + echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" + new_args=() + while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift + done + for word in ${USE_ADDITIONAL_OPTIONS}; do + new_args+=("$word") + done + echo "${new_args[@]}" + exec "${new_args[@]}" +else + echo "$@" + exec "$@" +fi diff --git a/docker/scripts/lte_ue_entrypoint.sh b/docker/scripts/lte_ue_entrypoint.sh new file mode 100755 index 0000000000..82e96dd07f --- /dev/null +++ b/docker/scripts/lte_ue_entrypoint.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +set -euo pipefail + +PREFIX=/opt/oai-lte-ue + +# Based another env var, pick one template to use +if [[ -v USE_NFAPI ]]; then cp $PREFIX/etc/ue.nfapi.conf $PREFIX/etc/ue.conf; fi + +# Only this template will be manipulated and the USIM one! +CONFIG_FILES=`ls $PREFIX/etc/ue.conf $PREFIX/etc/ue_usim.conf || true` + +for c in ${CONFIG_FILES}; do + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + NEW_VAR=`echo $v | sed -e "s#@##g"` + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +#now generate USIM files +# At this point all operations will be run from $PREFIX! +cd $PREFIX +$PREFIX/bin/conf2uedata -c $PREFIX/etc/ue_usim.conf -o $PREFIX + +# Load the USRP binaries +if [[ -v USE_B2XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t b2xx +elif [[ -v USE_X3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t x3xx +elif [[ -v USE_N3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t n3xx +fi + +# in case we have conf file, append +new_args=() +while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift +done +if [[ -v USE_NFAPI ]]; then + new_args+=("-O") + new_args+=("$PREFIX/etc/ue.conf") +fi + +echo "==================================" +echo "== Starting LTE UE soft modem" +if [[ -v USE_ADDITIONAL_OPTIONS ]]; then + echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" + for word in ${USE_ADDITIONAL_OPTIONS}; do + new_args+=("$word") + done + echo "${new_args[@]}" + exec "${new_args[@]}" +else + echo "${new_args[@]}" + exec "${new_args[@]}" +fi diff --git a/docker/scripts/lte_ue_parameters.yaml b/docker/scripts/lte_ue_parameters.yaml new file mode 100644 index 0000000000..977659bb54 --- /dev/null +++ b/docker/scripts/lte_ue_parameters.yaml @@ -0,0 +1,37 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +--- +- paths: + source_dir: "ci-scripts/conf_files/" + dest_dir: docker/etc + +- configurations: + - filePrefix: ue.nfapi + outputfilename: "ue.nfapi.conf" + config: + - key: remote_n_address + env: "@ENB_IP_ADDRESS@" + - key: local_n_address + env: "@LTE_UE_IP_ADDRESS@" + - key: local_n_if_name + env: "@UE_NFAPI_IF_NAME@" + diff --git a/docker/scripts/lte_ue_sim_parameters.yaml b/docker/scripts/lte_ue_sim_parameters.yaml new file mode 100644 index 0000000000..a339ed7504 --- /dev/null +++ b/docker/scripts/lte_ue_sim_parameters.yaml @@ -0,0 +1,47 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +--- +- paths: + source_dir: "openair3/NAS/TOOLS/" + dest_dir: docker/etc + +- configurations: + - filePrefix: ue_sim_ci + outputfilename: "ue_usim.conf" + config: + - key: MNC + env: "@MNC@" + - key: MCC + env: "@MCC@" + - key: MSIN + env: "@SHORT_IMSI@" + - key: USIM_API_K + env: "@LTE_KEY@" + - key: OPC + env: "@OPC@" + - key: MSISDN + env: "@MSISDN@" + - key: HPLMN + env: "@HPLMN@" + - key: OPLMN_LIST + env: "@HPLMN@" + diff --git a/docker/scripts/nr_ue_entrypoint.sh b/docker/scripts/nr_ue_entrypoint.sh new file mode 100755 index 0000000000..af2b8a8333 --- /dev/null +++ b/docker/scripts/nr_ue_entrypoint.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +set -euo pipefail + +PREFIX=/opt/oai-nr-ue + +# Based another env var, pick one template to use +#if [[ -v USE_NFAPI ]]; then cp $PREFIX/etc/ue.nfapi.conf $PREFIX/etc/ue.conf; fi + +# Only this template will be manipulated and the USIM one! +CONFIG_FILES=`ls $PREFIX/etc/ue.conf $PREFIX/etc/nr-ue-sim.conf || true` + +for c in ${CONFIG_FILES}; do + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + NEW_VAR=`echo $v | sed -e "s#@##g"` + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +# Load the USRP binaries +if [[ -v USE_B2XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t b2xx +elif [[ -v USE_X3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t x3xx +elif [[ -v USE_N3XX ]]; then + $PREFIX/bin/uhd_images_downloader.py -t n3xx +fi + +# in case we have conf file, append +new_args=() +while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift +done + +echo "==================================" +echo "== Starting NR UE soft modem" +if [[ -v USE_ADDITIONAL_OPTIONS ]]; then + echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" + for word in ${USE_ADDITIONAL_OPTIONS}; do + new_args+=("$word") + done + echo "${new_args[@]}" + exec "${new_args[@]}" +else + echo "${new_args[@]}" + exec "${new_args[@]}" +fi diff --git a/executables/main-fs6.c b/executables/main-fs6.c index c4a0d85b34..438edb4044 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -179,7 +179,7 @@ void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_r ru=eNB->RU_list[i]; for (ru_aa=0,aa=0; ru_aanb_rx; ru_aa++,aa++) { - eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[0][ru_aa]; int ce_level; for (ce_level=0; ce_level<4; ce_level++) @@ -435,7 +435,7 @@ void pusch_procedures_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN if ((ulsch) && (ulsch->rnti>0) && (ulsch_harq->status == ACTIVE) && - ((ulsch_harq->frame == frame) || (ulsch_harq->repetition_number >1) ) && + ((ulsch_harq->frame == frame) || (ulsch_harq->repetition_number >1) ) && ((ulsch_harq->subframe == subframe) || (ulsch_harq->repetition_number >1) ) && (ulsch_harq->handled == 0)) { // UE has ULSCH scheduling @@ -750,7 +750,7 @@ void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PH recvFs6Ul(bufferZone, nbBlocks, eNB, ul_propa); // dirty memory allocation in OAI... - for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) + for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) if ( eNB->uci_vars[i].frame == proc->frame_rx && eNB->uci_vars[i].subframe == proc->subframe_rx ) eNB->uci_vars[i].active=0; @@ -1145,7 +1145,7 @@ void appendFs6DLUEcch(uint8_t *bufferZone, PHY_VARS_eNB *eNB, int frame, int sub commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; bool first_UE=true; - for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) { + for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) { LTE_eNB_UCI *uci = &(eNB->uci_vars[i]); if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) { @@ -1520,7 +1520,7 @@ void *cu_fs6(void *arg) { remoteIP[i]=0; break; } - + AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, port_def, &sockFS6), ""); L1_rxtx_proc_t L1proc= {0}; // We pick the global thread pool from the legacy code global vars diff --git a/executables/main-ocp.c b/executables/main-ocp.c index cd221b155a..0355582b2b 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -73,14 +73,26 @@ int sync_var=-1; //!< protected by mutex \ref sync_mutex. int config_sync_var=-1; volatile int oai_exit = 0; double cpuf; +THREAD_STRUCT thread_struct; + uint16_t sf_ahead=4; +//uint16_t slot_ahead=6; int otg_enabled; uint64_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; int split73; char * split73_config; int split73; -int usrp_tx_thread = 0; +AGENT_RRC_xface *agent_rrc_xface[NUM_MAX_ENB]= {0}; +AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB]= {0}; +uint8_t proto_agent_flag = 0; +void flexran_agent_slice_update(mid_t module_idP) { +} +int proto_agent_start(mod_id_t mod_id, const cudu_params_t *p){ + return 0; +} +void proto_agent_stop(mod_id_t mod_id){ +} static void *ru_thread( void *param ); void kill_RU_proc(RU_t *ru) { @@ -101,21 +113,6 @@ void exit_function(const char *file, const char *function, const int line, const close_log_mem(); oai_exit = 1; - if (RC.ru == NULL) - exit(-1); // likely init not completed, prevent crash or hang, exit now... - - for (int ru_id=0; ru_idrfdevice.trx_end_func) { - RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); - RC.ru[ru_id]->rfdevice.trx_end_func = NULL; - } - - if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) { - RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); - RC.ru[ru_id]->ifdevice.trx_end_func = NULL; - } - } - sleep(1); //allow lte-softmodem threads to exit first exit(1); } @@ -207,7 +204,6 @@ void init_eNB_afterRU(void) { for (int inst=0; instframe_parms.nb_antennas_rx = 0; eNB->frame_parms.nb_antennas_tx = 0; eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *)); @@ -228,17 +224,31 @@ void init_eNB_afterRU(void) { for (int i=0; iRU_list[ru_id]->nb_rx; aa++,i++) { LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa); - eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[i]; + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[0][i]; for (int ce_level=0; ce_level<4; ce_level++) eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i]; - eNB->common_vars.rxdataF[aa] = eNB->RU_list[ru_id]->common.rxdataF[i]; } } - AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); - AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); + + AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 5, ""); + AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 5, ""); + + phy_init_lte_eNB(eNB,0,0); + + // need to copy rxdataF after L1 variables are allocated + for (int inst=0; instnum_RU; ru_id++) { + for (int i=0; iRU_list[ru_id]->nb_rx; aa++,i++) + eNB->common_vars.rxdataF[aa] = eNB->RU_list[ru_id]->common.rxdataF[i]; + } + } + } + LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); init_transport(eNB); //init_precoding_weights(RC.eNB[inst][CC_id]); @@ -399,6 +409,7 @@ int setup_RU_buffers(RU_t *ru) { return(0); } +#if 0 void init_precoding_weights(PHY_VARS_eNB *eNB) { int layer,ru_id,aa,re,ue,tb; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -431,6 +442,7 @@ void init_precoding_weights(PHY_VARS_eNB *eNB) { } } } +#endif void ocp_rx_prach(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, @@ -483,7 +495,7 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int br_flag) ru=eNB->RU_list[i]; for (ru_aa=0,aa=0; ru_aanb_rx; ru_aa++,aa++) { - eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[0][ru_aa]; int ce_level; if (br_flag==1) @@ -803,9 +815,8 @@ int init_rf(RU_t *ru) { pthread_setname_np(pthread_self(),name); return ret; } - -void init_RU(char *rf_config_file, int send_dmrssync) { - RU_t *ru; + +void ocp_init_RU(RU_t *ru, char *rf_config_file, int send_dmrssync) { PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL; int i; int CC_id; @@ -821,11 +832,8 @@ void init_RU(char *rf_config_file, int send_dmrssync) { LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); - for (int ru_id=0; ru_idrf_config_file = rf_config_file; - ru->idx = ru_id; + ru->idx = 0; ru->ts_offset = 0; if (ru->is_slave == 1) { @@ -849,8 +857,6 @@ void init_RU(char *rf_config_file, int send_dmrssync) { ru->wakeup_L1_sleep_cnt_max = 3; if (ru->num_eNB > 0) { - LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", - __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file); AssertFatal(ru->eNB_list[0], "ru->eNB_list is not initialized\n"); } else { LOG_E(PHY,"Wrong data model, assigning eNB 0, carrier 0 to RU 0\n"); @@ -867,20 +873,19 @@ void init_RU(char *rf_config_file, int send_dmrssync) { int ruIndex=eNB0->num_RU++; eNB0->RU_list[ruIndex] = ru; } - } // for ru_id } void stop_RU(int nb_ru) { for (int inst = 0; inst < nb_ru; inst++) { LOG_I(PHY, "Stopping RU %d processing threads\n", inst); - kill_RU_proc(RC.ru[inst]); + //kill_RU_proc(RC.ru[inst]); } } /* --------------------------------------------------------*/ /* from here function to use configuration module */ static int DEFBFW[] = {0x00007fff}; -void RCconfig_RU(void) { +void ocpRCconfig_RU(RU_t* ru) { paramdef_t RUParams[] = RUPARAMS_DESC; paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL); @@ -891,87 +896,74 @@ void RCconfig_RU(void) { return; } // setting != NULL - if ( RC.ru != NULL ) { - LOG_W(PHY, "Calling RCconfig_RU twice (nb ru=%d), ignoring the second call data structure is %p\n", - RUParamList.numelt,RC.ru); - return; + ru->idx = 0; + ru->if_timing = synch_to_ext_device; + paramdef_t *vals=RUParamList.paramarray[0]; + + if (RC.nb_L1_inst >0) + ru->num_eNB = vals[RU_ENB_LIST_IDX].numelt; + else + ru->num_eNB = 0; + + for (int i=0; inum_eNB; i++) + ru->eNB_list[i] = RC.eNB[vals[RU_ENB_LIST_IDX].iptr[i]][0]; + + if (config_isparamset(vals, RU_SDR_ADDRS)) { + ru->openair0_cfg.sdr_addrs = strdup(*(vals[RU_SDR_ADDRS].strptr)); } - RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); - - for (int j = 0; j < RC.nb_RU; j++) { - RC.ru[j] = (RU_t *)calloc(sizeof(RU_t), 1); - RC.ru[j]->idx = j; - LOG_I(PHY,"Creating RC.ru[%d]:%p\n", j, RC.ru[j]); - RC.ru[j]->if_timing = synch_to_ext_device; - paramdef_t *vals=RUParamList.paramarray[j]; - - if (RC.nb_L1_inst >0) - RC.ru[j]->num_eNB = vals[RU_ENB_LIST_IDX].numelt; - else - RC.ru[j]->num_eNB = 0; - - for (int i=0; inum_eNB; i++) - RC.ru[j]->eNB_list[i] = RC.eNB[vals[RU_ENB_LIST_IDX].iptr[i]][0]; - - if (config_isparamset(vals, RU_SDR_ADDRS)) { - RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(vals[RU_SDR_ADDRS].strptr)); - } - - if (config_isparamset(vals, RU_SDR_CLK_SRC)) { - char *paramVal=*(vals[RU_SDR_CLK_SRC].strptr); - LOG_D(PHY, "RU clock source set as %s\n", paramVal); - - if (strcmp(paramVal, "internal") == 0) { - RC.ru[j]->openair0_cfg.clock_source = internal; - } else if (strcmp(paramVal, "external") == 0) { - RC.ru[j]->openair0_cfg.clock_source = external; - } else if (strcmp(paramVal, "gpsdo") == 0) { - RC.ru[j]->openair0_cfg.clock_source = gpsdo; - } else { - LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", paramVal); - } - } - - if (strcmp(*(vals[RU_LOCAL_RF_IDX].strptr), "yes") == 0) { - if ( !(config_isparamset(vals,RU_LOCAL_IF_NAME_IDX)) ) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = eNodeB_3GPP; - LOG_I(PHY, "Setting function for RU %d to eNodeB_3GPP\n",j); - } else { - RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); - } - - RC.ru[j]->max_pdschReferenceSignalPower = *(vals[RU_MAX_RS_EPRE_IDX].uptr);; - RC.ru[j]->max_rxgain = *(vals[RU_MAX_RXGAIN_IDX].uptr); - RC.ru[j]->num_bands = vals[RU_BAND_LIST_IDX].numelt; - /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ - RC.ru[j]->sf_extension = *(vals[RU_SF_EXTENSION_IDX].uptr); - RC.ru[j]->end_of_burst_delay = *(vals[RU_END_OF_BURST_DELAY_IDX].uptr); - - for (int i=0; inum_bands; i++) RC.ru[j]->band[i] = vals[RU_BAND_LIST_IDX].iptr[i]; + if (config_isparamset(vals, RU_SDR_CLK_SRC)) { + char *paramVal=*(vals[RU_SDR_CLK_SRC].strptr); + LOG_D(PHY, "RU clock source set as %s\n", paramVal); + + if (strcmp(paramVal, "internal") == 0) { + ru->openair0_cfg.clock_source = internal; + } else if (strcmp(paramVal, "external") == 0) { + ru->openair0_cfg.clock_source = external; + } else if (strcmp(paramVal, "gpsdo") == 0) { + ru->openair0_cfg.clock_source = gpsdo; } else { - LOG_I(PHY,"RU %d: Transport %s\n",j,*(vals[RU_TRANSPORT_PREFERENCE_IDX].strptr)); - RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", paramVal); + } + } + + if (strcmp(*(vals[RU_LOCAL_RF_IDX].strptr), "yes") == 0) { + if ( !(config_isparamset(vals,RU_LOCAL_IF_NAME_IDX)) ) { + ru->if_south = LOCAL_RF; + ru->function = eNodeB_3GPP; + } else { + ru->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); + ru->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); + ru->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); + ru->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); + ru->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); + ru->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); + ru->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); + } + + ru->max_pdschReferenceSignalPower = *(vals[RU_MAX_RS_EPRE_IDX].uptr);; + ru->max_rxgain = *(vals[RU_MAX_RXGAIN_IDX].uptr); + ru->num_bands = vals[RU_BAND_LIST_IDX].numelt; + /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ + ru->sf_extension = *(vals[RU_SF_EXTENSION_IDX].uptr); + ru->end_of_burst_delay = *(vals[RU_END_OF_BURST_DELAY_IDX].uptr); + + for (int i=0; inum_bands; i++) + ru->band[i] = vals[RU_BAND_LIST_IDX].iptr[i]; + } else { + ru->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); + ru->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); + ru->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); + ru->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); + ru->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); + ru->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); + ru->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); } /* strcmp(local_rf, "yes") != 0 */ - RC.ru[j]->nb_tx = *(vals[RU_NB_TX_IDX].uptr); - RC.ru[j]->nb_rx = *(vals[RU_NB_RX_IDX].uptr); - RC.ru[j]->att_tx = *(vals[RU_ATT_TX_IDX].uptr); - RC.ru[j]->att_rx = *(vals[RU_ATT_RX_IDX].uptr); - }// j=0..num_rus + ru->nb_tx = *(vals[RU_NB_TX_IDX].uptr); + ru->nb_rx = *(vals[RU_NB_RX_IDX].uptr); + ru->att_tx = *(vals[RU_ATT_TX_IDX].uptr); + ru->att_rx = *(vals[RU_ATT_RX_IDX].uptr); return; } @@ -1055,13 +1047,13 @@ void init_pdcp(void) { pdcp_module_init(pdcp_initmask); if (NODE_IS_CU(RC.rrc[0]->node_type)) { - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + //pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); } else { pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); } } else { - pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); + //pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); } } @@ -1080,23 +1072,18 @@ void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) { LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n", itti_get_task_name(from), from, itti_get_task_name(to), to); MessageDef *msg; - msg = itti_alloc_new_message (from, TERMINATE_MESSAGE); + msg = itti_alloc_new_message (from, 0, TERMINATE_MESSAGE); itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); } int stop_L1L2(module_id_t enb_id) { LOG_W(ENB_APP, "stopping lte-softmodem\n"); - if (!RC.ru) { - LOG_UI(ENB_APP, "no RU configured\n"); - return -1; - } - /* these tasks need to pick up new configuration */ terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB); oai_exit = 1; LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id); - kill_RU_proc(RC.ru[enb_id]); + //kill_RU_proc(RC.ru[enb_id]); LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id); kill_eNB_proc(enb_id); oai_exit = 0; @@ -1106,7 +1093,7 @@ int stop_L1L2(module_id_t enb_id) { phy_free_lte_eNB(RC.eNB[enb_id][cc_id]); } - phy_free_RU(RC.ru[enb_id]); + //phy_free_RU(RC.ru[enb_id]); free_lte_top(); return 0; } @@ -1115,14 +1102,18 @@ int stop_L1L2(module_id_t enb_id) { * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2() */ int restart_L1L2(module_id_t enb_id) { - RU_t *ru = RC.ru[enb_id]; + RU_t *ru = NULL; //RC.ru[enb_id]; MessageDef *msg_p = NULL; LOG_W(ENB_APP, "restarting lte-softmodem\n"); /* block threads */ pthread_mutex_lock(&sync_mutex); sync_var = -1; pthread_mutex_unlock(&sync_mutex); - RC.ru_mask |= (1 << ru->idx); + + /* copy the changed frame parameters to the RU */ + /* TODO this should be done for all RUs associated to this eNB */ + memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS)); + /* reset the list of connected UEs in the MAC, since in this process with * loose all UEs (have to reconnect) */ init_UE_info(&RC.mac[enb_id]->UE_info); @@ -1132,14 +1123,9 @@ int restart_L1L2(module_id_t enb_id) { itti_mark_task_ready(TASK_RRC_ENB); /* pass a reconfiguration request which will configure everything down to * RC.eNB[i][j]->frame_parms, too */ - msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ); + msg_p = itti_alloc_new_message(TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ); RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); - /* TODO XForms might need to be restarted, but it is currently (09/02/18) - * broken, so we cannot test it */ - init_RU_proc(ru); - ru->rf_map.card = 0; - ru->rf_map.chain = 0; /* CC_id + chain_offset;*/ init_eNB_afterRU(); printf("Sending sync to all threads\n"); pthread_mutex_lock(&sync_mutex); @@ -1171,7 +1157,7 @@ int main ( int argc, char **argv ) { if (opp_enabled ==1) reset_opp_meas(); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + itti_init(TASK_MAX, tasks_info); init_opt(); #ifndef PACKAGE_VERSION # define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" @@ -1187,10 +1173,16 @@ int main ( int argc, char **argv ) { RCconfig_L1(); } + // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator. + // but RU thread deals with pre_scd and this is necessary in VNF and simulator. + // some initialization is necessary and init_ru_vnf do this. + RU_t ru; + + /* We need to read RU configuration before FlexRAN starts so it knows what * splits to report. Actual RU start comes later. */ - if (RC.nb_RU > 0 && NFAPI_MODE != NFAPI_MODE_VNF) { - RCconfig_RU(); + if ( NFAPI_MODE != NFAPI_MODE_VNF) { + ocpRCconfig_RU(&ru); LOG_I(PHY, "number of L1 instances %d, number of RU %d, number of CPU cores %d\n", RC.nb_L1_inst, RC.nb_RU, get_nprocs()); @@ -1211,7 +1203,7 @@ int main ( int argc, char **argv ) { if (RC.nb_inst > 0) { /* Start the agent. If it is turned off in the configuration, it won't start */ for (i = 0; i < RC.nb_inst; i++) { - flexran_agent_start(i); + //flexran_agent_start(i); } /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks @@ -1220,7 +1212,7 @@ int main ( int argc, char **argv ) { AssertFatal(create_tasks(1)==0,"cannot create ITTI tasks\n"); for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) { - MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ); + MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ); RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); } @@ -1292,20 +1284,16 @@ int main ( int argc, char **argv ) { printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); - // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator. - // but RU thread deals with pre_scd and this is necessary in VNF and simulator. - // some initialization is necessary and init_ru_vnf do this. + if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) { printf("Initializing RU threads\n"); - init_RU(get_softmodem_params()->rf_config_file, + ocp_init_RU(&ru, + get_softmodem_params()->rf_config_file, get_softmodem_params()->send_dmrs_sync); - for (int ru_id=0; ru_idrf_map.card=0; - RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); - LOG_I(PHY,"Starting ru_thread %d\n",ru_id); - init_RU_proc(RC.ru[ru_id]); - } + ru.rf_map.card=0; + ru.rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); + init_RU_proc(&ru); config_sync_var=0; @@ -1316,6 +1304,7 @@ int main ( int argc, char **argv ) { LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU); // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) printf("ALL RUs ready - init eNBs\n"); + sleep(1); if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) { LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n"); @@ -1344,7 +1333,7 @@ int main ( int argc, char **argv ) { // end of CI modifications //getchar(); - if(IS_SOFTMODEM_DOFORMS) + if(IS_SOFTMODEM_DOSCOPE) load_softscope("enb", NULL); itti_wait_tasks_end(); @@ -1353,7 +1342,7 @@ int main ( int argc, char **argv ) { // stop threads if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) { - if(IS_SOFTMODEM_DOFORMS) + if(IS_SOFTMODEM_DOSCOPE) end_forms(); LOG_I(ENB_APP,"stopping MODEM threads\n"); @@ -1369,10 +1358,6 @@ int main ( int argc, char **argv ) { } } - for (int inst = 0; inst < RC.nb_RU; inst++) { - phy_free_RU(RC.ru[inst]); - } - free_lte_top(); end_configmodule(); pthread_cond_destroy(&sync_cond); @@ -1381,17 +1366,6 @@ int main ( int argc, char **argv ) { pthread_mutex_destroy(&nfapi_sync_mutex); pthread_mutex_destroy(&ue_pf_po_mutex); - for(int ru_id=0; ru_idrfdevice.trx_end_func) { - RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); - RC.ru[ru_id]->rfdevice.trx_end_func = NULL; - } - - if (RC.ru[ru_id]->ifdevice.trx_end_func) { - RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); - RC.ru[ru_id]->ifdevice.trx_end_func = NULL; - } - } } terminate_opt(); diff --git a/executables/main_ru.c b/executables/main_ru.c new file mode 100644 index 0000000000..93a580560e --- /dev/null +++ b/executables/main_ru.c @@ -0,0 +1,382 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file oairu.c + * \brief Top-level threads for radio-unit + * \author R. Knopp + * \date 2020 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr + * \note + * \warning + */ + + +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include + + + + +#include "assertions.h" +#include "PHY/types.h" + +#include "PHY/defs_RU.h" +#include "common/config/config_userapi.h" +#include "common/utils/load_module_shlib.h" + + +#include "../../ARCH/COMMON/common_lib.h" +#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" + + +#include "PHY/phy_vars.h" +#include "SCHED/sched_common_vars.h" +#include "PHY/TOOLS/phy_scope_interface.h" +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" +#include "PHY/INIT/phy_init.h" +#include "openair2/ENB_APP/enb_paramdef.h" +#include "system.h" + +#include +#include +#include + +static int DEFBANDS[] = {7}; +static int DEFENBS[] = {0}; +static int DEFBFW[] = {0x00007fff}; + +THREAD_STRUCT thread_struct; + +pthread_cond_t sync_cond; +pthread_mutex_t sync_mutex; +int sync_var=-1; //!< protected by mutex \ref sync_mutex. +int config_sync_var=-1; + +volatile int oai_exit = 0; +uint16_t sf_ahead = 4; +RU_t ru_m; + + +extern void init_RU0(RU_t *ru,int ru_id,char *rf_config_file, int send_dmrssync); +extern void init_RU_proc(RU_t *ru); +extern void kill_RU_proc(RU_t *ru); +extern void set_function_spec_param(RU_t *ru); + +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + + +void nfapi_setmode(nfapi_mode_t nfapi_mode) { return; } +void exit_function(const char *file, const char *function, const int line, const char *s) { + + if (s != NULL) { + printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); + } + close_log_mem(); + oai_exit = 1; + + if (ru_m.rfdevice.trx_end_func) { + ru_m.rfdevice.trx_end_func(&ru_m.rfdevice); + ru_m.rfdevice.trx_end_func = NULL; + } + + if (ru_m.ifdevice.trx_end_func) { + ru_m.ifdevice.trx_end_func(&ru_m.ifdevice); + ru_m.ifdevice.trx_end_func = NULL; + } + + pthread_mutex_destroy(ru_m.ru_mutex); + pthread_cond_destroy(ru_m.ru_cond); + sleep(1); //allow lte-softmodem threads to exit first + exit(1); +} + + +static void get_options(void) { + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + get_common_options(SOFTMODEM_ENB_BIT ); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); + + //RCConfig(); + +} + + + + + +extern void phy_free_RU(RU_t *); + +nfapi_mode_t nfapi_getmode(void) { + return(NFAPI_MODE_PNF); +} + +void oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) { + + AssertFatal(1==0,"This is bad ... please check why we get here\n"); +} + +void wait_eNBs(void){ return; } + +uint64_t downlink_frequency[MAX_NUM_CCs][4]; + + +int main ( int argc, char **argv ) +{ + + if ( load_configmodule(argc,argv,0) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + + logInit(); + printf("Reading in command-line options\n"); + get_options (); + + if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) { + fprintf(stderr,"Getting configuration failed\n"); + exit(-1); + } + +#if T_TRACER + T_Config_Init(); +#endif + printf("configuring for RRU\n"); + +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + + /* Read configuration */ + + printf("About to Init RU threads\n"); + + + RU_t *ru=&ru_m; + + paramdef_t RUParams[] = RUPARAMS_DESC; + paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; + config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL); + + int j=0; + uint64_t ru_mask=1; + pthread_mutex_t ru_mutex; pthread_mutex_init(&ru_mutex,NULL); + pthread_cond_t ru_cond; pthread_cond_init(&ru_cond,NULL); + + ru->ru_mask= &ru_mask; + ru->ru_mutex = &ru_mutex; + ru->ru_cond = &ru_cond; + + ru->if_timing = synch_to_ext_device; + ru->num_eNB = 0; + ru->has_ctrl_prt = 1; + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { + ru->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); + } + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { + ru->openair0_cfg.clock_source = internal; + LOG_D(PHY, "RU clock source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { + ru->openair0_cfg.clock_source = external; + LOG_D(PHY, "RU clock source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { + ru->openair0_cfg.clock_source = gpsdo; + LOG_D(PHY, "RU clock source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } + else { + ru->openair0_cfg.clock_source = unset; + } + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { + ru->openair0_cfg.time_source = internal; + LOG_D(PHY, "RU time source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { + ru->openair0_cfg.time_source = external; + LOG_D(PHY, "RU time source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { + ru->openair0_cfg.time_source = gpsdo; + LOG_D(PHY, "RU time source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } + else { + ru->openair0_cfg.time_source = unset; + } + + if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { + if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { + AssertFatal(1==0,"IF_NAME is required\n"); + } else { + ru->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); + ru->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); + ru->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); + ru->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); + ru->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); + + // Check if control port set + if (!(config_isparamset(RUParamList.paramarray[j],RU_REMOTE_PORTC_IDX)) ) { + printf("Removing control port for RU %d\n",j); + ru->has_ctrl_prt = 0; + } else { + ru->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); + ru->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); + printf(" Control port %u \n",ru->eth_params.my_portc); + } + + if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { + ru->if_south = LOCAL_RF; + ru->function = NGFI_RRU_IF5; + ru->eth_params.transp_preference = ETH_UDP_MODE; + printf("Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j); + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { + ru->if_south = LOCAL_RF; + ru->function = NGFI_RRU_IF5; + ru->eth_params.transp_preference = ETH_RAW_MODE; + printf("Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j); + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { + ru->if_south = LOCAL_RF; + ru->function = NGFI_RRU_IF4p5; + ru->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + printf("Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j); + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { + ru->if_south = LOCAL_RF; + ru->function = NGFI_RRU_IF4p5; + ru->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j); + } + + printf("RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr)); + + if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) ru->is_slave=1; + else ru->is_slave=0; + + printf("RU %d ota_sync_enabled=%s\n",j,*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr)); + + if (strcmp(*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr), "yes") == 0) ru->ota_sync_enable=1; + else ru->ota_sync_enable=0; + } + + ru->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; + ru->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); + ru->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; + /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ + ru->sf_extension = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr); + + for (int i=0; inum_bands; i++) ru->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; + } //strcmp(local_rf, "yes") == 0 + else { + printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); + ru->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); + ru->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); + ru->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); + ru->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); + ru->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); + ru->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); + ru->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); + + if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { + ru->if_south = REMOTE_IF5; + ru->function = NGFI_RAU_IF5; + ru->eth_params.transp_preference = ETH_UDP_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { + ru->if_south = REMOTE_IF5; + ru->function = NGFI_RAU_IF5; + ru->eth_params.transp_preference = ETH_RAW_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { + ru->if_south = REMOTE_IF4p5; + ru->function = NGFI_RAU_IF4p5; + ru->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { + ru->if_south = REMOTE_IF4p5; + ru->function = NGFI_RAU_IF4p5; + ru->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + } + + if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) ru->is_slave=1; + else ru->is_slave=0; + } /* strcmp(local_rf, "yes") != 0 */ + + ru->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); + ru->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); + ru->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); + ru->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); + + + set_worker_conf("WORKER_ENABLE"); + + mlockall(MCL_CURRENT | MCL_FUTURE); + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + + init_RU0(ru,0,get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync); + ru->rf_map.card=0; + ru->rf_map.chain=(get_softmodem_params()->chain_offset); + + LOG_I(PHY, "Initializing RRU descriptor : (%s,%s,%d)\n", ru_if_types[ru->if_south], NB_timing[ru->if_timing], ru->function); + set_function_spec_param(ru); + LOG_I(PHY, "Starting ru_thread , is_slave %d, send_dmrs %d\n", ru->is_slave, ru->generate_dmrs_sync); + init_RU_proc(ru); + + pthread_mutex_lock(&ru_mutex); + while (ru_mask>0) + pthread_cond_wait(&ru_cond,&ru_mutex); + pthread_mutex_unlock(&ru_mutex); + LOG_I(PHY,"RU configured, unlocking threads\n"); + config_sync_var=0; + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + + while (oai_exit==0) sleep(1); + // stop threads + + kill_RU_proc(ru); + phy_free_RU(ru); + + free_lte_top(); + end_configmodule(); + + if (ru->rfdevice.trx_end_func) { + ru->rfdevice.trx_end_func(&ru->rfdevice); + ru->rfdevice.trx_end_func = NULL; + } + + if (ru->ifdevice.trx_end_func) { + ru->ifdevice.trx_end_func(&ru->ifdevice); + ru->ifdevice.trx_end_func = NULL; + } + + + + logClean(); + printf("Bye.\n"); + return 0; +} diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 27b0ed08dd..dc8960846f 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -48,6 +48,8 @@ #include "SCHED_NR/sched_nr.h" #include "SCHED_NR/fapi_nr_l1.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" +#include "PHY/MODULATION/nr_modulation.h" +#include "PHY/NR_TRANSPORT/nr_dlsch.h" #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all @@ -71,18 +73,20 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "UTIL/OPT/opt.h" #include "enb_config.h" +#include "gnb_paramdef.h" -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_extern.h" -#endif - #include "s1ap_eNB.h" #include "SIMULATION/ETH_TRANSPORT/proto.h" - +#include #include "T.h" - +#include "nfapi/oai_integration/vendor_ext.h" +#include "executables/softmodem-common.h" +#include +#include +#include +#include //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 @@ -90,16 +94,6 @@ // extern openair0_device openair0; -extern volatile int start_gNB; -extern volatile int start_UE; -extern volatile int oai_exit; - -extern openair0_config_t openair0_cfg[MAX_CARDS]; - -extern int transmission_mode; - -extern uint16_t sf_ahead; -extern uint16_t sl_ahead; //pthread_t main_gNB_thread; time_stats_t softmodem_stats_mt; // main thread @@ -108,54 +102,73 @@ time_stats_t softmodem_stats_rxtx_sf; // total tx time time_stats_t nfapi_meas; // total tx time time_stats_t softmodem_stats_rx_sf; // total rx time -/* mutex, cond and variable to serialize phy proc TX calls - * (this mechanism may be relaxed in the future for better - * performances) - */ -static struct { - pthread_mutex_t mutex_phy_proc_tx; - pthread_cond_t cond_phy_proc_tx; - volatile uint8_t phy_proc_CC_id; -} sync_phy_proc; -extern double cpuf; - -void init_gNB(int,int); -void stop_gNB(int nb_inst); - -int wakeup_txfh(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int frame_tx, int slot_tx, uint64_t timestamp_tx); -int wakeup_tx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, uint64_t timestamp_tx); #include "executables/thread-common.h" -//extern PARALLEL_CONF_t get_thread_parallel_conf(void); -//extern WORKER_CONF_t get_thread_worker_conf(void); -void wakeup_prach_gNB(PHY_VARS_gNB *gNB, RU_t *ru, int frame, int subframe); - -extern uint8_t nfapi_mode; -extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); -extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset); - //#define TICK_TO_US(ts) (ts.diff) #define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials) +#define L1STATSSTRLEN 16384 -static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) { +void tx_func(void *param) { + processingData_L1tx_t *info = (processingData_L1tx_t *) param; + PHY_VARS_gNB *gNB = info->gNB; + int frame_tx = info->frame; + int slot_tx = info->slot; + + phy_procedures_gNB_TX(info, + frame_tx, + slot_tx, + 1); + info->slot = -1; + //if ((frame_tx&127) == 0) dump_pdsch_stats(fd,gNB); + + // If the later of the 2 L1 tx thread finishes first, + // we wait for the earlier one to finish and start the RU thread + // to avoid realtime issues with USRP + + // Start RU TX processing. + notifiedFIFO_elt_t *res; + res = pullTpool(gNB->resp_RU_tx, gNB->threadPool); + processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res); + LOG_D(PHY,"waiting for previous tx to finish, next slot %d,%d\n",syncMsg->next_slot,slot_tx); + while (syncMsg->next_slot != slot_tx) { + pushNotifiedFIFO(gNB->resp_RU_tx, res); + res = pullTpool(gNB->resp_RU_tx, gNB->threadPool); + syncMsg = (processingData_RU_t *)NotifiedFifoData(res); + } + LOG_D(PHY,"previous tx finished, next slot %d,%d\n",syncMsg->next_slot,slot_tx); + syncMsg->frame_tx = frame_tx; + syncMsg->slot_tx = slot_tx; + syncMsg->next_slot = get_next_downlink_slot(gNB, &gNB->gNB_config, frame_tx, slot_tx); + syncMsg->timestamp_tx = info->timestamp_tx; + syncMsg->ru = gNB->RU_list[0]; + res->key = slot_tx; + pushTpool(gNB->threadPool, res); +} + +void rx_func(void *param) { + + processingData_L1_t *info = (processingData_L1_t *) param; + PHY_VARS_gNB *gNB = info->gNB; + int frame_rx = info->frame_rx; + int slot_rx = info->slot_rx; + int frame_tx = info->frame_tx; + int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* - // NFAPI not yet supported for NR - this code has to be revised - if (nfapi_mode == 1) { + + if (NFAPI_MODE == NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick - //add_subframe(&frame, &subframe, 4); - //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); - //LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe); + //LOG_D(PHY, "oai_nfapi_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); start_meas(&nfapi_meas); - oai_subframe_ind(frame_rx, slot_rx); + handle_nr_slot_ind(frame_rx, slot_rx); stop_meas(&nfapi_meas); /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| @@ -178,22 +191,52 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx)); - /* - // if this is IF5 or 3GPP_gNB - if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) { - wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx); + /* hack to remove UEs */ + extern int rnti_to_remove[10]; + extern volatile int rnti_to_remove_count; + extern pthread_mutex_t rnti_to_remove_mutex; + if (pthread_mutex_lock(&rnti_to_remove_mutex)) exit(1); + int up_removed = 0; + int down_removed = 0; + int pucch_removed = 0; + for (int i = 0; i < rnti_to_remove_count; i++) { + LOG_W(NR_PHY, "to remove rnti 0x%04x\n", rnti_to_remove[i]); + void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch); + void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch); + int j; + for (j = 0; j < NUMBER_OF_NR_ULSCH_MAX; j++) + if (gNB->ulsch[j][0]->rnti == rnti_to_remove[i]) { + gNB->ulsch[j][0]->rnti = 0; + gNB->ulsch[j][0]->harq_mask = 0; + //clean_gNB_ulsch(gNB->ulsch[j][0]); + int h; + for (h = 0; h < NR_MAX_ULSCH_HARQ_PROCESSES; h++) { + gNB->ulsch[j][0]->harq_processes[h]->status = SCH_IDLE; + gNB->ulsch[j][0]->harq_processes[h]->round = 0; + gNB->ulsch[j][0]->harq_processes[h]->handled = 0; + } + up_removed++; + } + for (j = 0; j < NUMBER_OF_NR_PUCCH_MAX; j++) + if (gNB->pucch[j]->active > 0 && + gNB->pucch[j]->pucch_pdu.rnti == rnti_to_remove[i]) { + gNB->pucch[j]->active = 0; + gNB->pucch[j]->pucch_pdu.rnti = 0; + pucch_removed++; + } +#if 0 + for (j = 0; j < NUMBER_OF_NR_PDCCH_MAX; j++) + gNB->pdcch_pdu[j].frame = -1; + for (j = 0; j < NUMBER_OF_NR_PDCCH_MAX; j++) + gNB->ul_pdcch_pdu[j].frame = -1; + for (j = 0; j < NUMBER_OF_NR_PRACH_MAX; j++) + gNB->prach_vars.list[j].frame = -1; +#endif } - */ - // Call the scheduler + if (rnti_to_remove_count) LOG_W(NR_PHY, "to remove rnti_to_remove_count=%d, up_removed=%d down_removed=%d pucch_removed=%d\n", rnti_to_remove_count, up_removed, down_removed, pucch_removed); + rnti_to_remove_count = 0; + if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = frame_rx; - gNB->UL_INFO.slot = slot_rx; - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); - // RX processing int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); int rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); @@ -203,31 +246,50 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT // Do PRACH RU processing - int prach_id=find_nr_prach(gNB,frame_rx,slot_rx,0,SEARCH_EXIST); - if (prach_id>=0) { - L1_nr_prach_procedures(gNB,frame_rx,slot_rx,&gNB->prach_vars.list[prach_id].pdu); - gNB->prach_vars.list[prach_id].frame=-1; + L1_nr_prach_procedures(gNB,frame_rx,slot_rx); + + //apply the rx signal rotation here + for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { + apply_nr_rotation_ul(&gNB->frame_parms, + gNB->common_vars.rxdataF[aa], + slot_rx, + 0, + gNB->frame_parms.Ncp==EXTENDED?12:14, + gNB->frame_parms.ofdm_symbol_size); } phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx); } - if (oai_exit) return(-1); - - // ***************************************** - // TX processing for subframe n+sf_ahead - // run PHY TX procedures the one after the other for all CCs to avoid race conditions - // (may be relaxed in the future for performance reasons) - // ***************************************** - - if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { - - if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) { - phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); - } - } - stop_meas( &softmodem_stats_rxtx_sf ); LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx); + + // Call the scheduler + start_meas(&gNB->ul_indication_stats); + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = frame_rx; + gNB->UL_INFO.slot = slot_rx; + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + stop_meas(&gNB->ul_indication_stats); + + if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { + notifiedFIFO_elt_t *res; + res = pullTpool(gNB->resp_L1_tx, gNB->threadPool); + processingData_L1tx_t *syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res); + while (syncMsg->slot != slot_tx) { + pushNotifiedFIFO(gNB->resp_L1_tx, res); + res = pullTpool(gNB->resp_L1_tx, gNB->threadPool); + syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res); + } + syncMsg->gNB = gNB; + AssertFatal(syncMsg->slot == slot_tx, "Thread message slot and logical slot number do not match\n"); + syncMsg->timestamp_tx = info->timestamp_tx; + res->key = slot_tx; + pushTpool(gNB->threadPool, res); + } + #if 0 LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ", softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now, @@ -267,595 +329,146 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t TICK_TO_US(gNB->ulsch_tc_intl2_stats) ); #endif - return(0); } +static void dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output) { + int stroff = 0; + stroff += print_meas_log(gNB->phy_proc_tx_0, "L1 Tx processing thread 0", NULL, NULL, output); + stroff += print_meas_log(gNB->phy_proc_tx_1, "L1 Tx processing thread 1", NULL, NULL, output+stroff); + stroff += print_meas_log(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL, output+stroff); + stroff += print_meas_log(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL, output+stroff); + stroff += print_meas_log(&gNB->ul_indication_stats, "UL Indication", NULL, NULL, output+stroff); + stroff += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output+stroff); + stroff += print_meas_log(&gNB->ulsch_decoding_stats, "PUSCH decoding", NULL, NULL, output+stroff); + if (ru->feprx) stroff += print_meas_log(&ru->ofdm_demod_stats,"feprx",NULL,NULL, output+stroff); -static void *gNB_L1_thread_tx(void *param) { - PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; - gNB_L1_proc_t *gNB_proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB_proc->L1_proc_tx; - //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; - char thread_name[100]; - - sprintf(thread_name,"gNB_L1_thread_tx\n"); - - while (!oai_exit) { - if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 ); - - if (oai_exit) break; - - // ***************************************** - // TX processing for subframe n+4 - // run PHY TX procedures the one after the other for all CCs to avoid race conditions - // (may be relaxed in the future for performance reasons) - // ***************************************** - int frame_tx = L1_proc_tx->frame_tx; - int slot_tx = L1_proc_tx->slot_tx; - uint64_t timestamp_tx = L1_proc_tx->timestamp_tx; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx); - phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 1 ); - pthread_mutex_lock( &L1_proc_tx->mutex ); - L1_proc_tx->instance_cnt = -1; - - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc_tx->cond) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - } - pthread_mutex_unlock(&L1_proc_tx->mutex); - - wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 ); + if (ru->feptx_ofdm) { + stroff += print_meas_log(&ru->precoding_stats,"feptx_prec",NULL,NULL, output+stroff); + stroff += print_meas_log(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL, output+stroff); + stroff += print_meas_log(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL, output+stroff); + stroff += print_meas_log(&ru->ofdm_total_stats,"feptx_total",NULL,NULL, output+stroff); } - return 0; -} + if (ru->fh_north_asynch_in) stroff += print_meas_log(&ru->rx_fhaul,"rx_fhaul",NULL,NULL, output+stroff); -/*! - * \brief The RX UE-specific and TX thread of gNB. - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ + stroff += print_meas_log(&ru->tx_fhaul,"tx_fhaul",NULL,NULL, output+stroff); -static void *gNB_L1_thread( void *param ) { - static int gNB_thread_rxtx_status; - PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; - gNB_L1_proc_t *gNB_proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc; - //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; - char thread_name[100]; - // set default return value - // set default return value - gNB_thread_rxtx_status = 0; - - sprintf(thread_name,"gNB_L1_thread"); - - - while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); - if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); - - int frame_rx = L1_proc->frame_rx; - int slot_rx = L1_proc->slot_rx; - int frame_tx = L1_proc->frame_tx; - int slot_tx = L1_proc->slot_tx; - uint64_t timestamp_tx = L1_proc->timestamp_tx; - - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,frame_rx); - - if (oai_exit) break; - - if (gNB->CC_id==0) { - if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break; - } - - if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break; - - if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx); - else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx); - } // while !oai_exit - - LOG_D(PHY, " *** Exiting gNB thread RXn_TXnp4\n"); - gNB_thread_rxtx_status = 0; - return &gNB_thread_rxtx_status; -} - - -#if 0 -// Wait for gNB application initialization to be complete (gNB registration to MME) -static void wait_system_ready (char *message, volatile int *start_flag) { - static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", - " ....", " ...", " ..", " .", " " - }; - int i = 0; - - while ((!oai_exit) && (*start_flag == 0)) { - LOG_N(EMU, message, indicator[i]); - fflush(stdout); - i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); - usleep(200000); - } - - LOG_D(EMU,"\n"); -} -#endif - - - - - -void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru) { - gNB_L1_proc_t *proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *ru_proc=&ru->proc; - proc->frame_rx = frame_rx; - proc->slot_rx = slot_rx; - sl_ahead = sf_ahead*fp->slots_per_subframe; - - if (!oai_exit) { - T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->slot_rx)); - L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); - L1_proc->frame_rx = ru_proc->frame_rx; - L1_proc->slot_rx = ru_proc->tti_rx; - L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - - if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id); - - ru_proc->timestamp_tx = L1_proc->timestamp_tx; - ru_proc->tti_tx = L1_proc->slot_tx; - ru_proc->frame_tx = L1_proc->frame_tx; + if (ru->fh_north_out) { + stroff += print_meas_log(&ru->compression,"compression",NULL,NULL, output+stroff); + stroff += print_meas_log(&ru->transport,"transport",NULL,NULL, output+stroff); } } -int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) { - - RU_t *ru; - RU_proc_t *ru_proc; - - int waitret = 0, ret = 0, time_ns = 1000*1000; - struct timespec now, abstime; - // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time - // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1); - time_ns = time_ns/gNB->frame_parms.slots_per_subframe; - AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - while (proc->instance_cnt_RUs < 0) { - clock_gettime(CLOCK_REALTIME, &now); - abstime.tv_sec = now.tv_sec; - abstime.tv_nsec = now.tv_nsec + time_ns; - - if (abstime.tv_nsec >= 1000*1000*1000) { - abstime.tv_nsec -= 1000*1000*1000; - abstime.tv_sec += 1; - } - if((waitret = pthread_cond_timedwait(&proc->cond_RUs,&proc->mutex_RUs_tx,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again - } - proc->instance_cnt_RUs = -1; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0); - - if (waitret == ETIMEDOUT) { - LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); - - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); - - return(-1); - } - - for(int i=0; inum_RU; i++) - { - ru = gNB->RU_list[i]; - ru_proc = &ru->proc; - - - if (ru_proc->instance_cnt_gNBs == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1); - LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->tti_tx, proc->frame_rx, proc->slot_rx); - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0); - return(-1); - } - AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret); - - ru_proc->instance_cnt_gNBs = 0; - ru_proc->timestamp_tx = timestamp_tx; - ru_proc->tti_tx = slot_tx; - ru_proc->frame_tx = frame_tx; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs); - - LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0, - "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); - AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret); - - } - return(0); -} - -int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) { - - - gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx; - - int ret; - - - AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); - - - while(L1_proc_tx->instance_cnt == 0) { - pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex); - } - - L1_proc_tx->instance_cnt = 0; - - - L1_proc_tx->slot_rx = slot_rx; - L1_proc_tx->frame_rx = frame_rx; - L1_proc_tx->slot_tx = slot_tx; - L1_proc_tx->frame_tx = frame_tx; - L1_proc_tx->timestamp_tx = timestamp_tx; - - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0); - // the thread can now be woken up - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n"); - - AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); - - return(0); -} - -int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { - gNB_L1_proc_t *proc=&gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc=&proc->L1_proc; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - RU_proc_t *ru_proc=&ru->proc; - int ret; - int i; - struct timespec abstime; - int time_ns = 50000; - - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); - for (i=0; inum_RU; i++) { - if (ru == gNB->RU_list[i]) { - if ((proc->RU_mask&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); - proc->RU_mask |= (1<RU_mask != (1<num_RU)-1) { // not all RUs have provided their information so return - LOG_E(PHY,"Not all RUs have provided their info\n"); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret); - return(0); - } - else { // all RUs have provided their information so continue on and wakeup gNB processing - proc->RU_mask = 0; - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret); - } - - clock_gettime(CLOCK_REALTIME, &abstime); - abstime.tv_nsec = abstime.tv_nsec + time_ns; - - if (abstime.tv_nsec >= 1000*1000*1000) { - abstime.tv_nsec -= 1000*1000*1000; - abstime.tv_sec += 1; - } - - // wake up TX for subframe n+sf_ahead - // lock the TX mutex and make sure the thread is ready - AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret); - - if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); - LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); - return(-1); - } - - ++L1_proc->instance_cnt; - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired - // transmitted timestamp of the next TX slot (first). - - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, - // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti, - // and proc->slot_tx = proc->slot_rx+sf_ahead - L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); - L1_proc->frame_rx = ru_proc->frame_rx; - L1_proc->slot_rx = ru_proc->tti_rx; - L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - - LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sf_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sf_ahead); - - pthread_mutex_unlock( &L1_proc->mutex ); - - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc->cond) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - - return(0); -} -/* -void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) { - - gNB_L1_proc_t *proc = &gNB->proc; - LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms; - int i; - - if (ru!=NULL) { - pthread_mutex_lock(&proc->mutex_RU_PRACH); - for (i=0;inum_RU;i++) { - if (ru == gNB->RU_list[i]) { - LOG_D(PHY,"frame %d, subframe %d: RU %d for gNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,gNB->Mod_id,proc->RU_mask_prach,gNB->num_RU); - if ((proc->RU_mask_prach&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n", - gNB->Mod_id,frame,subframe,ru->idx,gNB->num_RU,proc->RU_mask_prach); - proc->RU_mask_prach |= (1<RU_mask_prach != (1<num_RU)-1) { // not all RUs have provided their information so return - pthread_mutex_unlock(&proc->mutex_RU_PRACH); - return; - } - else { // all RUs have provided their information so continue on and wakeup gNB processing - proc->RU_mask_prach = 0; - pthread_mutex_unlock(&proc->mutex_RU_PRACH); - } - } - - // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe); - if (proc->instance_cnt_prach == 0) { - LOG_W(PHY,"[gNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe); - return; - } - - // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach); - exit_fun( "error locking mutex_prach" ); - return; - } - - ++proc->instance_cnt_prach; - // set timing for prach thread - proc->frame_prach = frame; - proc->subframe_prach = subframe; - - // the thread can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - - pthread_mutex_unlock( &proc->mutex_prach ); - } - -}*/ - -/*! - * \brief The prach receive thread of gNB. - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -/* -static void* gNB_thread_prach( void* param ) { - static int gNB_thread_prach_status; - - - PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param; - gNB_L1_proc_t *proc = &gNB->proc; - - // set default return value - gNB_thread_prach_status = 0; - - - - while (!oai_exit) { - - if (oai_exit) break; - - - if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break; - - LOG_D(PHY,"Running gNB prach procedures\n"); - prach_procedures(gNB ,0); - - if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break; - } - - LOG_I(PHY, "Exiting gNB thread PRACH\n"); - - gNB_thread_prach_status = 0; - return &gNB_thread_prach_status; -} -*/ - -extern void init_td_thread(PHY_VARS_gNB *); -extern void init_te_thread(PHY_VARS_gNB *); - -static void *process_stats_thread(void *param) { - - PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; +void *nrL1_stats_thread(void *param) { + PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; + RU_t *ru = RC.ru[0]; + char output[L1STATSSTRLEN]; + memset(output,0,L1STATSSTRLEN); + wait_sync("L1_stats_thread"); + FILE *fd; + fd=fopen("nrL1_stats.log","w"); + AssertFatal(fd!=NULL,"Cannot open nrL1_stats.log\n"); + reset_meas(gNB->phy_proc_tx_0); + reset_meas(gNB->phy_proc_tx_1); reset_meas(&gNB->dlsch_encoding_stats); - reset_meas(&gNB->dlsch_scrambling_stats); - reset_meas(&gNB->dlsch_modulation_stats); + reset_meas(&gNB->phy_proc_rx); + reset_meas(&gNB->ul_indication_stats); + reset_meas(&gNB->rx_pusch_stats); + reset_meas(&gNB->ulsch_decoding_stats); - wait_sync("process_stats_thread"); - - while(!oai_exit) - { + while (!oai_exit) { sleep(1); - print_meas(&gNB->dlsch_encoding_stats, "pdsch_encoding", NULL, NULL); - print_meas(&gNB->dlsch_scrambling_stats, "pdsch_scrambling", NULL, NULL); - print_meas(&gNB->dlsch_modulation_stats, "pdsch_modulation", NULL, NULL); + dump_nr_I0_stats(fd,gNB); + dump_pdsch_stats(fd,gNB); + dump_pusch_stats(fd,gNB); + dump_L1_meas_stats(gNB, ru, output); + fprintf(fd,"%s\n",output); + fflush(fd); + fseek(fd,0,SEEK_SET); } + fclose(fd); return(NULL); } - -void init_gNB_proc(int inst) { - int i=0; - int CC_id = 0; +void init_gNB_Tpool(int inst) { PHY_VARS_gNB *gNB; - gNB_L1_proc_t *proc; - gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx; -// LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]); gNB = RC.gNB[inst]; - LOG_I(PHY,"Initializing gNB processes instance:%d CC_id %d \n",inst,CC_id); - - proc = &gNB->proc; - L1_proc = &proc->L1_proc; - L1_proc_tx = &proc->L1_proc_tx; - L1_proc->instance_cnt = -1; - L1_proc_tx->instance_cnt = -1; - L1_proc->instance_cnt_RUs = 0; - L1_proc_tx->instance_cnt_RUs = 0; - proc->instance_cnt_prach = -1; - proc->instance_cnt_asynch_rxtx = -1; - proc->CC_id = CC_id; - proc->first_rx =1; - proc->first_tx =1; - proc->RU_mask =0; - proc->RU_mask_tx = (1<num_RU)-1; - proc->RU_mask_prach =0; - pthread_mutex_init( &gNB->UL_INFO_mutex, NULL); - pthread_mutex_init( &L1_proc->mutex, NULL); - pthread_mutex_init( &L1_proc_tx->mutex, NULL); - pthread_cond_init( &L1_proc->cond, NULL); - pthread_cond_init( &L1_proc_tx->cond, NULL); - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); - pthread_mutex_init( &proc->mutex_RU,NULL); - pthread_mutex_init( &proc->mutex_RU_tx,NULL); - pthread_mutex_init( &proc->mutex_RU_PRACH,NULL); - pthread_cond_init( &proc->cond_prach, NULL); - pthread_cond_init( &proc->cond_asynch_rxtx, NULL); - LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag); - - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT ); - threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT); + gNB_L1_proc_t *proc = &gNB->proc; + + // ULSCH decoding threadpool + gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); + int numCPU = sysconf(_SC_NPROCESSORS_ONLN); + LOG_I(PHY,"Number of threads requested in config file: %d, Number of threads available on this machine: %d\n",gNB->pusch_proc_threads,numCPU); + int threadCnt = min(numCPU, gNB->pusch_proc_threads); + if (threadCnt < 2) LOG_E(PHY,"Number of threads for gNB should be more than 1. Allocated only %d\n",threadCnt); + char pool[80]; + sprintf(pool,"-1"); + int s_offset = 0; + for (int icpu=1; icpuL1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW); - //pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB ); - char name[16]; - - if (gNB->single_thread_flag==0) { - snprintf( name, sizeof(name), "L1 %d", i ); - pthread_setname_np( L1_proc->pthread, name ); - snprintf( name, sizeof(name), "L1TX %d", i ); - pthread_setname_np( L1_proc_tx->pthread, name ); - } - - AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach); + if (getenv("noThreads")) strcpy(pool, "n"); + initTpool(pool, gNB->threadPool, false); + // ULSCH decoder result FIFO + gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->respDecode); + + // L1 RX result FIFO + gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_L1); + notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func); + pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning + + // L1 TX result FIFO + gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_L1_tx); + // we create 2 threads for L1 tx processing + notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func); + processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); + init_DLSCH_struct(gNB, msgDataTx); + msgDataTx->slot = -1; + memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t)); + reset_meas(&msgDataTx->phy_proc_tx); + gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx; + pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning + + msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func); + msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); + init_DLSCH_struct(gNB, msgDataTx); + msgDataTx->slot = -1; + memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t)); + reset_meas(&msgDataTx->phy_proc_tx); + gNB->phy_proc_tx_1 = &msgDataTx->phy_proc_tx; + pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning + + // RU TX result FIFO + gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_RU_tx); + notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_RU_t),0,gNB->resp_RU_tx,ru_tx_func); + processingData_RU_t *msgData = (processingData_RU_t*)msgRUTx->msgData; + int first_tx_slot = sf_ahead*gNB->frame_parms.slots_per_subframe; + msgData->next_slot = get_next_downlink_slot(gNB, &gNB->gNB_config, 0, first_tx_slot-1); + pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning + + threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW); - /* setup PHY proc TX sync mechanism */ - pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL); - pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL); - sync_phy_proc.phy_proc_CC_id = 0; } - /*! * \brief Terminate gNB TX and RX threads. */ void kill_gNB_proc(int inst) { - int *status; PHY_VARS_gNB *gNB; - gNB_L1_proc_t *proc; - gNB_L1_rxtx_proc_t *L1_proc, *L1_proc_tx; gNB=RC.gNB[inst]; - proc = &gNB->proc; - L1_proc = &proc->L1_proc; - L1_proc_tx = &proc->L1_proc_tx; - LOG_I(PHY, "Killing TX inst %d\n",inst ); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - pthread_mutex_lock(&L1_proc->mutex); - L1_proc->instance_cnt = 0; - pthread_cond_signal(&L1_proc->cond); - pthread_mutex_unlock(&L1_proc->mutex); - pthread_mutex_lock(&L1_proc_tx->mutex); - L1_proc_tx->instance_cnt = 0; - pthread_cond_signal(&L1_proc_tx->cond); - pthread_mutex_unlock(&L1_proc_tx->mutex); - } - - proc->instance_cnt_prach = 0; - pthread_cond_signal( &proc->cond_prach ); - pthread_cond_signal( &proc->cond_asynch_rxtx ); - pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); - // LOG_D(PHY, "joining pthread_prach\n"); - // pthread_join( proc->pthread_prach, (void**)&status ); - LOG_I(PHY, "Destroying prach mutex/cond\n"); - pthread_mutex_destroy( &proc->mutex_prach ); - pthread_cond_destroy( &proc->cond_prach ); LOG_I(PHY, "Destroying UL_INFO mutex\n"); pthread_mutex_destroy(&gNB->UL_INFO_mutex); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - LOG_I(PHY, "Joining L1_proc mutex/cond\n"); - pthread_join( L1_proc->pthread, (void **)&status ); - LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n"); - pthread_join( L1_proc_tx->pthread, (void **)&status ); - } - - LOG_I(PHY, "Destroying L1_proc mutex/cond\n"); - pthread_mutex_destroy( &L1_proc->mutex ); - pthread_cond_destroy( &L1_proc->cond ); - LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n"); - pthread_mutex_destroy( &L1_proc_tx->mutex ); - pthread_cond_destroy( &L1_proc_tx->cond ); - pthread_mutex_destroy( &proc->mutex_RU ); - pthread_mutex_destroy( &proc->mutex_RU_tx ); - } - - - void reset_opp_meas(void) { int sfn; reset_meas(&softmodem_stats_mt); @@ -886,6 +499,8 @@ void init_eNB_afterRU(void) { PHY_VARS_gNB *gNB; LOG_I(PHY,"%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst); + if(NFAPI_MODE == NFAPI_MODE_PNF) + RC.nb_nr_inst = 1; for (inst=0; instRU_list[ru_id]->nb_rx; aa++,i++) { LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa); - gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[i]; + gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[0][i]; +#if 0 +printf("before %p\n", gNB->common_vars.rxdataF[aa]); +#endif gNB->common_vars.rxdataF[aa] = gNB->RU_list[ru_id]->common.rxdataF[i]; +#if 0 +printf("after %p\n", gNB->common_vars.rxdataF[aa]); +#endif } } @@ -917,15 +538,9 @@ void init_eNB_afterRU(void) { * (not tested in other modes). */ //init_precoding_weights(RC.gNB[inst]); - init_gNB_proc(inst); + init_gNB_Tpool(inst); } - for (ru_id=0; ru_idnr_wakeup_rxtx = wakeup_rxtx; - // RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_gNB; - RC.ru[ru_id]->gNB_top = gNB_top; - } } void init_gNB(int single_thread_flag,int wait_for_sync) { @@ -934,18 +549,16 @@ void init_gNB(int single_thread_flag,int wait_for_sync) { PHY_VARS_gNB *gNB; if (RC.gNB == NULL) { - RC.gNB = (PHY_VARS_gNB **) malloc((1+RC.nb_nr_L1_inst)*sizeof(PHY_VARS_gNB *)); - for (inst=0; instabstraction_flag = 0; gNB->single_thread_flag = single_thread_flag; @@ -972,10 +585,11 @@ void init_gNB(int single_thread_flag,int wait_for_sync) { gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/ gNB->prach_energy_counter = 0; + gNB->prb_interpolation = get_softmodem_params()->prb_interpolation; } - LOG_I(PHY,"[nr-softmodem.c] gNB structure allocated\n"); + LOG_I(PHY,"[nr-gnb.c] gNB structure allocated\n"); } diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 969ad21b8e..3a2589632b 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -24,14 +24,8 @@ #include #include #include -#include -#include -#include #include #include -#include -#include -#include #include #include @@ -39,7 +33,7 @@ #include "common/utils/assertions.h" #include "common/utils/system.h" -#include "msc.h" +#include "common/ran_context.h" #include "../../ARCH/COMMON/common_lib.h" #include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" @@ -50,20 +44,13 @@ #include "PHY/types.h" #include "PHY/defs_nr_common.h" #include "PHY/phy_extern.h" -#include "PHY/LTE_TRANSPORT/transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/INIT/phy_init.h" -#include "SCHED/sched_eNB.h" #include "SCHED_NR/sched_nr.h" -#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -#include "RRC/LTE/rrc_extern.h" -#include "PHY_INTERFACE/phy_interface.h" - #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include "enb_config.h" #include #ifdef SMBV @@ -83,13 +70,9 @@ static int DEFBFW[] = {0x00007fff}; #include "GNB_APP/gnb_paramdef.h" #include "common/config/config_userapi.h" -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_extern.h" -#endif - #include "s1ap_eNB.h" #include "SIMULATION/ETH_TRANSPORT/proto.h" - +#include #include "T.h" @@ -112,21 +95,21 @@ void configure_ru(int idx, void *arg); void configure_rru(int idx, void *arg); int attach_rru(RU_t *ru); int connect_rau(RU_t *ru); +static void NRRCconfig_RU(void); uint16_t sf_ahead; +uint16_t slot_ahead; uint16_t sl_ahead; extern int emulate_rf; extern int numerology; -extern int usrp_tx_thread; /*************************************************************/ /* Functions to attach and configure RRU */ extern void wait_gNBs(void); -int attach_rru(RU_t *ru) -{ +int attach_rru(RU_t *ru) { ssize_t msg_len,len; RRU_CONFIG_msg_t rru_config_msg; int received_capabilities=0; @@ -180,11 +163,21 @@ int attach_rru(RU_t *ru) ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), "RU %d failed send configuration to remote radio\n",ru->idx); + + if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, + &rru_config_msg, + msg_len))<0) { + LOG_I(PHY,"Waiting for RRU %d\n",ru->idx); + } else if (rru_config_msg.type == RRU_config_ok) { + LOG_I(PHY, "RRU_config_ok received\n"); + } else { + LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); + } + return 0; } -int connect_rau(RU_t *ru) -{ +int connect_rau(RU_t *ru) { RRU_CONFIG_msg_t rru_config_msg; ssize_t msg_len; int tick_received = 0; @@ -281,22 +274,20 @@ int connect_rau(RU_t *ru) /* Southbound Fronthaul functions, RCC/RAU */ // southbound IF5 fronthaul for 16-bit OAI format -void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) -{ +void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL); } // southbound IF4p5 fronthaul -void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) -{ +void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { nfapi_nr_config_request_scf_t *cfg = &ru->config; + if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx); - if ((nr_slot_select(cfg,ru->proc.frame_tx,ru->proc.tti_tx)&NR_DOWNLINK_SLOT) > 0) send_IF4p5(ru,frame, slot, IF4p5_PDLFFT); } @@ -305,16 +296,20 @@ void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) /* Input Fronthaul from south RCC/RAU */ // Synchronous if5 from south + +uint64_t ts_rx[20]; void fh_if5_south_in(RU_t *ru, int *frame, - int *tti) -{ + int *tti) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; RU_proc_t *proc = &ru->proc; recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL); - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; - uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe; - proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); + if (proc->first_rx == 1) ru->ts_offset = proc->timestamp_rx; + proc->frame_rx = ((proc->timestamp_rx-ru->ts_offset) / (fp->samples_per_subframe*10))&1023; + proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx-ru->ts_offset,fp); +//(idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); + ts_rx[*tti] = proc->timestamp_rx; + LOG_D(PHY,"IF5 %d.%d => RX %d.%d first_rx %d\n",*frame,*tti,proc->frame_rx,proc->tti_rx,proc->first_rx); if (proc->first_rx == 0) { if (proc->tti_rx != *tti) { @@ -323,7 +318,7 @@ void fh_if5_south_in(RU_t *ru, } if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d proc->tti_rx %d tti %d)\n",proc->frame_rx,*frame,proc->tti_rx,*tti); exit_fun("Exiting"); } } else { @@ -338,8 +333,7 @@ void fh_if5_south_in(RU_t *ru, // Synchronous if4p5 from south void fh_if4p5_south_in(RU_t *ru, int *frame, - int *slot) -{ + int *slot) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; RU_proc_t *proc = &ru->proc; int f,sl; @@ -612,9 +606,11 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { unsigned int rxs; int i; uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp); + uint32_t samples_per_slot_prev ; openair0_timestamp ts,old_ts; AssertFatal(*slotslots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame); + start_meas(&ru->rx_fhaul); for (i=0; inb_rx; i++) rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)]; @@ -635,7 +631,6 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { ru->nb_rx); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); proc->timestamp_rx = ts-ru->ts_offset; @@ -647,22 +642,23 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { ru->ts_offset = proc->timestamp_rx; proc->timestamp_rx = 0; } else { - if (proc->timestamp_rx - old_ts != fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp)) { - LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot,ru->ts_offset); - ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot); + samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp); + + if (proc->timestamp_rx - old_ts != samples_per_slot_prev) { + LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot_prev,ru->ts_offset); + ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot_prev); proc->timestamp_rx = ts-ru->ts_offset; } } proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; - uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe; - proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); + proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx,fp); // synchronize first reception to frame 0 subframe 0 - LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n", + LOG_D(PHY,"RU %d/%d TS %llu , frame %d, slot %d.%d / %d\n", ru->idx, 0, - (unsigned long long int)proc->timestamp_rx, - (int)ru->ts_offset,proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame); + (unsigned long long int)(proc->timestamp_rx+ru->ts_offset), + proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame); // dump VCD output for first RU in list if (ru == RC.ru[0]) { @@ -677,7 +673,8 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame); + LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx, + *frame,proc->tti_rx,*slot); exit_fun("Exiting"); } } else { @@ -687,12 +684,14 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, (proc->timestamp_rx+ru->ts_offset)&0xffffffff ); if (rxs != samples_per_slot) { //exit_fun( "problem receiving samples" ); LOG_E(PHY, "problem receiving samples\n"); } + + stop_meas(&ru->rx_fhaul); } @@ -702,336 +701,92 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { nfapi_nr_config_request_scf_t *cfg = &ru->config; void *txp[ru->nb_tx]; unsigned int txs; - int i,txsymb; + int i,txsymb=fp->symbols_per_slot; T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot), T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4)); - int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame); int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame); - int sf_extension = 0; //sf_extension = ru->sf_extension; + int sf_extension = 0; int siglen=fp->get_samples_per_slot(slot,fp); int flags=1; //nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame); if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) { + if (cfg->cell_config.frame_duplex_type.value == TDD) { + if(slot_type == NR_MIXED_SLOT) { + txsymb = 0; - if(slot_type == NR_MIXED_SLOT) { - txsymb = 0; - for(int symbol_count =0;symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==0) - txsymb++; + for(int symbol_count = 0; symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) + txsymb++; + } + + AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb); + + if(slot%(fp->slots_per_subframe/2)) + siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + else + siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + + //+ ru->end_of_burst_delay; + flags = 3; // end of burst } - AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb); - if(slot%(fp->slots_per_subframe/2)) - siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples); - else - siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); - //+ ru->end_of_burst_delay; - flags=3; // end of burst - } - if (cfg->cell_config.frame_duplex_type.value == TDD && - slot_type == NR_DOWNLINK_SLOT && - prevslot_type == NR_UPLINK_SLOT) { - flags = 2; // start of burst - } - - if (cfg->cell_config.frame_duplex_type.value == TDD && - slot_type == NR_DOWNLINK_SLOT && - nextslot_type == NR_UPLINK_SLOT) { - flags = 3; // end of burst + if (slot_type == NR_DOWNLINK_SLOT && prevslot_type == NR_UPLINK_SLOT) { + flags = 2; // start of burst + sf_extension = ru->sf_extension; + } + if (slot_type == NR_DOWNLINK_SLOT && nextslot_type == NR_UPLINK_SLOT) + flags = 3; // end of burst } if (fp->freq_range==nr_FR2) { // the beam index is written in bits 8-10 of the flags // bit 11 enables the gpio programming + // currently we switch beams every 10 slots (should = 1 TDD period in FR2) and we take the beam index of the first symbol of the first slot of this period int beam=0; - if (slot==0) beam = 11; //3 for boresight & 8 to enable + + if (slot%10==0) { + if ( ru->common.beam_id && (ru->common.beam_id[0][slot*fp->symbols_per_slot] < 8)) { + beam = ru->common.beam_id[0][slot*fp->symbols_per_slot] | 8; + } + } + /* - if (slot==0 || slot==40) beam=0&8; - if (slot==10 || slot==50) beam=1&8; - if (slot==20 || slot==60) beam=2&8; - if (slot==30 || slot==70) beam=3&8; + if (slot==0 || slot==40) beam=0|8; + if (slot==10 || slot==50) beam=1|8; + if (slot==20 || slot==60) beam=2|8; + if (slot==30 || slot==70) beam=3|8; */ flags |= beam<<8; + LOG_D(HW,"slot %d, beam %d\n",slot,ru->common.beam_id[0][slot*fp->symbols_per_slot]); } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags ); + if (proc->first_tx == 1) proc->first_tx = 0; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot ); + for (i=0; inb_tx; i++) - txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension]; + txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)]-sf_extension*sizeof(int32_t); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers - txs = ru->rfdevice.trx_write_func(&ru->rfdevice, - timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, - txp, - siglen+sf_extension, - ru->nb_tx, - flags); - LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %di, returned %d\n",ru->idx, - (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot, txs); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + txs = ru->rfdevice.trx_write_func(&ru->rfdevice, + timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d aa %d tx_rf, writing to TS %llu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, returned %d, E %f\n",ru->idx,i, + (long long unsigned int)(timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension),frame,slot,proc->frame_tx_unwrap,slot, flags, siglen+sf_extension, txs,10*log10((double)signal_energy(txp[0],siglen+sf_extension))); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); //AssertFatal(txs == 0,"trx write function error %d\n", txs); } } - - -/*! - * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU. - * This handles the RX FH for an asynchronous RRU/UE - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_asynch_rxtx( void *param ) { - static int ru_thread_asynch_rxtx_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - int slot=0, frame=0; - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - wait_sync("ru_thread_asynch_rxtx"); - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for devices (ru_thread_asynch_rx)\n"); - wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); - printf( "devices ok (ru_thread_asynch_rx)\n"); - - while (!oai_exit) { - - if (slot==ru->nr_frame_parms->slots_per_frame) { - slot=0; - frame++; - frame&=1023; - } else { - slot++; - } - - LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); - - // asynchronous receive from north (RRU IF4/IF5) - if (ru->fh_north_asynch_in) { - if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0) - ru->fh_north_asynch_in(ru,&frame,&slot); - } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n"); - } - - ru_thread_asynch_rxtx_status=0; - return(&ru_thread_asynch_rxtx_status); -} - - - - -/*! - * \brief The prach receive thread of RU. - * \param param is a \ref RU_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_prach( void *param ) { - static int ru_thread_prach_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = (RU_proc_t *)&ru->proc; - // set default return value - ru_thread_prach_status = 0; - - while (RC.ru_mask>0) { - usleep(1e6); - LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__); - } - - LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__); - - while (!oai_exit) { - - - if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); - - /*if (ru->gNB_list[0]){ - prach_procedures( - ru->gNB_list[0],0 - ); - } - else { - rx_prach(NULL, - ru, - NULL, - NULL, - NULL, - proc->frame_prach, - 0,0 - ); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ - if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - } - - LOG_I(PHY, "Exiting RU thread PRACH\n"); - ru_thread_prach_status = 0; - return &ru_thread_prach_status; -} - - -int wakeup_synch(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - // wake up synch thread - // lock the synch mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch ); - exit_fun( "error locking mutex_synch" ); - return(-1); - } - - ++ru->proc.instance_cnt_synch; - - // the thread can now be woken up - if (pthread_cond_signal(&ru->proc.cond_synch) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - - pthread_mutex_unlock( &ru->proc.mutex_synch ); - return(0); -} - -void do_ru_synch(RU_t *ru) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int i; - void *rxp[2],*rxp2[2]; - int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32))); - int rxs; - int ic; - - // initialize the synchronization buffer to the common_vars.rxdata - for (int i=0; inb_rx; i++) - rxp[i] = &ru->common.rxdata[i][0]; - - double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0]; - double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0]; - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i]; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); - - while ((ru->in_synch ==0)&&(!oai_exit)) { - // read in frame - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - fp->samples_per_subframe*10, - ru->nb_rx); - - if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs); - - // wakeup synchronization processing thread - wakeup_synch(ru); - ic=0; - - while ((ic>=0)&&(!oai_exit)) { - // continuously read in frames, 1ms at a time, - // until we are done with the synchronization procedure - for (i=0; inb_rx; i++) - rxp2[i] = (void *)&dummy_rx[i][0]; - - for (i=0; i<10; i++) - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp2, - fp->samples_per_subframe, - ru->nb_rx); - - pthread_mutex_lock(&ru->proc.mutex_synch); - ic = ru->proc.instance_cnt_synch; - pthread_mutex_unlock(&ru->proc.mutex_synch); - } // ic>=0 - } // in_synch==0 - - // read in rx_offset samples - LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset); - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - ru->rx_offset, - ru->nb_rx); - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); -} - - - -void wakeup_gNB_L1s(RU_t *ru) { - int i; - PHY_VARS_gNB **gNB_list = ru->gNB_list; - LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top); - - if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { - // call gNB function directly - char string[20]; - sprintf(string,"Incoming RU %u",ru->idx); - LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx); - ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru); - } else { - LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB); - - for (i=0; inum_gNB; i++) { - LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx); - - if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) { - LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx); - } - } - } -} - -int wakeup_prach_ru(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } - - if (ru->proc.instance_cnt_prach==-1) { - ++ru->proc.instance_cnt_prach; - ru->proc.frame_prach = ru->proc.frame_rx; - ru->proc.subframe_prach = ru->proc.tti_rx; - - // DJP - think prach_procedures() is looking at gNB frame_prach - if (ru->gNB_list[0]) { - ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx; - ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx; - } - - LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx); - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); - } else LOG_W(PHY,"RU prach thread busy, skipping\n"); - - pthread_mutex_unlock( &ru->proc.mutex_prach ); - return(0); -} - // this is for RU with local RF unit void fill_rf_config(RU_t *ru, char *rf_config_file) { int i; @@ -1041,58 +796,21 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { int mu = config->ssb_config.scs_common.value; int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - if (mu == NR_MU_0) { //or if LTE - if(N_RB == 100) { - if (fp->threequarter_fs) { - cfg->sample_rate=23.04e6; - cfg->samples_per_frame = 230400; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } else { - cfg->sample_rate=30.72e6; - cfg->samples_per_frame = 307200; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - } else if(N_RB == 50) { - cfg->sample_rate=15.36e6; - cfg->samples_per_frame = 153600; - cfg->tx_bw = 5e6; - cfg->rx_bw = 5e6; - } else if (N_RB == 25) { - cfg->sample_rate=7.68e6; - cfg->samples_per_frame = 76800; - cfg->tx_bw = 2.5e6; - cfg->rx_bw = 2.5e6; - } else if (N_RB == 6) { - cfg->sample_rate=1.92e6; - cfg->samples_per_frame = 19200; - cfg->tx_bw = 1.5e6; - cfg->rx_bw = 1.5e6; - } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB); - } else if (mu == NR_MU_1) { - if(N_RB == 273) { - if (fp->threequarter_fs) { - AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } - } else if(N_RB == 217) { + if (mu == NR_MU_0) { + switch(N_RB) { + case 270: if (fp->threequarter_fs) { cfg->sample_rate=92.16e6; cfg->samples_per_frame = 921600; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; } - } else if(N_RB == 106) { + case 216: if (fp->threequarter_fs) { cfg->sample_rate=46.08e6; cfg->samples_per_frame = 460800; @@ -1105,20 +823,195 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { cfg->tx_bw = 40e6; cfg->rx_bw = 40e6; } - } else { + break; + case 160: //30 MHz + case 133: //25 MHz + if (fp->threequarter_fs) { + AssertFatal(1==0,"N_RB %d cannot use 3/4 sampling\n",N_RB); + } + else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + case 106: + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + break; + case 52: + if (fp->threequarter_fs) { + cfg->sample_rate=11.52e6; + cfg->samples_per_frame = 115200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + else { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + case 25: + if (fp->threequarter_fs) { + cfg->sample_rate=5.76e6; + cfg->samples_per_frame = 57600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } + else { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } + break; + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + } + } else if (mu == NR_MU_1) { + switch(N_RB) { + + case 273: + if (fp->threequarter_fs) { + cfg->sample_rate=184.32e6; + cfg->samples_per_frame = 1843200; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + break; + case 217: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } + break; + case 162 : + if (fp->threequarter_fs) { + AssertFatal(1==0,"N_RB %d cannot use 3/4 sampling\n",N_RB); + } + else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 60e6; + cfg->rx_bw = 60e6; + } + + break; + + case 133 : + if (fp->threequarter_fs) { + AssertFatal(1==0,"N_RB %d cannot use 3/4 sampling\n",N_RB); + } + else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + + break; + case 106: + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + break; + case 51: + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + break; + case 24: + if (fp->threequarter_fs) { + cfg->sample_rate=11.52e6; + cfg->samples_per_frame = 115200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + else { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + break; + default: AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else if (mu == NR_MU_3) { - if (N_RB == 66) { - cfg->sample_rate = 122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } else if(N_RB == 32) { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; + switch(N_RB) { + case 66: + if (fp->threequarter_fs) { + cfg->sample_rate=184.32e6; + cfg->samples_per_frame = 1843200; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else { + cfg->sample_rate = 122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + + break; + + case 32: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + + break; + + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else { AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); @@ -1138,19 +1031,23 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { if (ru->if_frequency == 0) { cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; - } - else { + } else if (ru->if_freq_offset) { + cfg->tx_freq[i] = (double)(ru->if_frequency); + cfg->rx_freq[i] = (double)(ru->if_frequency + ru->if_freq_offset); + LOG_I(PHY, "Setting IF TX frequency to %lu Hz with IF RX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset); + } else { cfg->tx_freq[i] = (double)ru->if_frequency; cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq); } + cfg->tx_gain[i] = ru->att_tx; cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; cfg->configFilename = rf_config_file; - printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", - i, cfg->tx_gain[i], - cfg->rx_gain[i], - cfg->tx_freq[i], - cfg->rx_freq[i]); + LOG_I(PHY, "Channel %d: setting tx_gain offset %f, rx_gain offset %f, tx_freq %lu Hz, rx_freq %lu Hz\n", + i, cfg->tx_gain[i], + cfg->rx_gain[i], + (unsigned long)cfg->tx_freq[i], + (unsigned long)cfg->rx_freq[i]); } } @@ -1162,64 +1059,58 @@ int setup_RU_buffers(RU_t *ru) { int i,j; int card,ant; //uint16_t N_TA_offset = 0; - NR_DL_FRAME_PARMS *frame_parms; + NR_DL_FRAME_PARMS *fp; nfapi_nr_config_request_scf_t *config = &ru->config; if (ru) { - frame_parms = ru->nr_frame_parms; - printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + fp = ru->nr_frame_parms; + printf("setup_RU_buffers: frame_parms = %p\n",fp); } else { printf("ru pointer is NULL\n"); return(-1); } + int mu = config->ssb_config.scs_common.value; int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - if (config->cell_config.frame_duplex_type.value == TDD) { int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 - double factor=1; switch (mu) { - case 0: //15 kHz scs - AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n"); - if (N_RB <= 25) factor = .25; // 7.68 Ms/s - else if (N_RB <=50) factor = .5; // 15.36 Ms/s - else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s - else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s - else AssertFatal(1==0,"Too many PRBS for mu=0\n"); - break; - case 1: //30 kHz sc - AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n"); - if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s - else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s - break; - case 2: //60 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - break; - case 3: //120 kHz scs - AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n"); - break; - case 4: //240 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s - else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s - else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); - break; + case 0: //15 kHz scs + AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); + factor = fp->samples_per_subframe / 30720.0; + break; - if (N_RB == 100) ru->N_TA_offset = 624; - else if (N_RB == 50) ru->N_TA_offset = 624/2; - else if (N_RB == 25) ru->N_TA_offset = 624/4; + case 1: //30 kHz sc + AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); + factor = fp->samples_per_subframe / 30720.0; + break; + + case 2: //60 kHz scs + AssertFatal(1==0, "scs_common should not be 60 kHz\n"); + break; + + case 3: //120 kHz scs + AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; + break; + + case 4: //240 kHz scs + AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; + break; + + default: + AssertFatal(1==0, "Invalid scs_common!\n"); } - if (frame_parms->threequarter_fs == 1) factor = factor*.75; - ru->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor, - config->carrier_config.uplink_frequency.value, N_RB); - } - else ru->N_TA_offset = 0; - + ru->N_TA_offset = (int)(N_TA_offset * factor); + LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d, mu %d)\n",ru->idx,ru->N_TA_offset,factor, + config->carrier_config.uplink_frequency.value, N_RB, mu); + } else ru->N_TA_offset = 0; + if (ru->openair0_cfg.mmapped_dma == 1) { // replace RX signal buffers with mmaped HW versions for (i=0; inb_rx; i++) { @@ -1264,7 +1155,6 @@ void *ru_stats_thread(void *param) { sleep(1); if (opp_enabled == 1) { - if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); if (ru->feptx_ofdm) { @@ -1274,9 +1164,9 @@ void *ru_stats_thread(void *param) { print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL); } - if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); - + print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); + if (ru->fh_north_out) { print_meas(&ru->compression,"compression",NULL,NULL); print_meas(&ru->transport,"transport",NULL,NULL); @@ -1287,136 +1177,57 @@ void *ru_stats_thread(void *param) { return(NULL); } -void *ru_thread_tx( void *param ) { - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - PHY_VARS_gNB *gNB; - gNB_L1_proc_t *gNB_proc; - gNB_L1_rxtx_proc_t *L1_proc; - char filename[40]; - int print_frame = 8; - int i = 0; - int ret; - +void ru_tx_func(void *param) { + processingData_RU_t *info = (processingData_RU_t *) param; + RU_t *ru = info->ru; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + int frame_tx = info->frame_tx; + int slot_tx = info->slot_tx; + int print_frame = 8; + char filename[40]; - wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - printf( "ru_thread_tx ready\n"); + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,slot_tx); - while (!oai_exit) { + // do OFDM with/without TX front-end processing if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,slot_tx); - LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n"); - // wait until eNBs are finished subframe RX n and TX n+4 + if(!emulate_rf) { + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,slot_tx,info->timestamp_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 ); - wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 ); - - ret = pthread_mutex_lock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock return %d\n",ret); - int frame_tx=proc->frame_tx; - int tti_tx =proc->tti_tx; - uint64_t timestamp_tx = proc->timestamp_tx; - - ret = pthread_mutex_unlock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - - if (oai_exit) break; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx ); - - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx); - - if(!emulate_rf) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - - if(proc->tti_tx == 0) { - sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - - sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); - } - - if(proc->tti_tx == 9) { - sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); - LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); - sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); - FILE *output_fd = fopen(filename,"w"); - - if (output_fd) { - fwrite(&ru->common.txdata[i][0], - sizeof(int32_t), - fp->samples_per_frame, - output_fd); - fclose(output_fd); - } else { - LOG_E(PHY,"Cannot write to file %s\n",filename); - } - }//if(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs); - - for(i = 0; inum_gNB; i++) { - gNB = ru->gNB_list[i]; - gNB_proc = &gNB->proc; - L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc; - ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - - for (int j=0; jnum_RU; j++) { - if (ru == gNB->RU_list[j]) { - if ((gNB_proc->RU_mask_tx&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx); - - gNB_proc->RU_mask_tx |= (1<fh_north_out) ru->fh_north_out(ru); + } else { + if(frame_tx == print_frame) { + for (int i=0; inb_tx; i++) { + if(slot_tx == 0) { + sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, slot_tx); + LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); + sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, slot_tx); + LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); + sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, slot_tx); + LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); } - } - if (gNB_proc->RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } else { // all RUs TX are finished so send the ready signal to gNB processing - gNB_proc->RU_mask_tx = 0; - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + if(slot_tx == 9) { + sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); + LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); + sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); + FILE *output_fd = fopen(filename,"w"); - ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - // the thread can now be woken up - if (L1_proc->instance_cnt_RUs == -1) { - L1_proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); - AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, - "ERROR pthread_cond_signal for gNB_L1_thread\n"); - } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); - ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } - } - } - - release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - return 0; + if (output_fd) { + fwrite(&ru->common.txdata[i][0], + sizeof(int32_t), + fp->samples_per_frame, + output_fd); + fclose(output_fd); + } else { + LOG_E(PHY,"Cannot write to file %s\n",filename); + } + }//if(slot_tx == 9) + }//for (i=0; inb_tx; i++) + }//if(frame_tx == print_frame) + }//else emulate_rf } void *ru_thread( void *param ) { @@ -1424,23 +1235,21 @@ void *ru_thread( void *param ) { RU_t *ru = (RU_t *)param; RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + PHY_VARS_gNB *gNB = RC.gNB[0]; int ret; int slot = fp->slots_per_frame-1; int frame = 1023; - char filename[40], threadname[40]; - int print_frame = 8; - int i = 0; - int aa; + char threadname[40]; + int initial_wait=0; + int opp_enabled0 = opp_enabled; nfapi_nr_config_request_scf_t *cfg = &ru->config; - // set default return value ru_thread_status = 0; // set default return value sprintf(threadname,"ru_thread %u",ru->idx); - - LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); + memcpy((void *)&ru->config,(void *)&RC.gNB[0]->gNB_config,sizeof(ru->config)); if(emulate_rf) { fill_rf_config(ru,ru->rf_config_file); @@ -1453,24 +1262,25 @@ void *ru_thread( void *param ) { exit(-1); } } else { + nr_init_frame_parms(&ru->config, fp); + nr_dump_frame_parms(fp); + fill_rf_config(ru,ru->rf_config_file); + nr_phy_init_RU(ru); + // Start IF device if any if (ru->nr_start_if) { LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx); AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n"); - if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); - else ret = attach_rru(ru); + if (ru->has_ctrl_prt > 0) { + if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); + else ret = attach_rru(ru); + + AssertFatal(ret==0,"Cannot connect to remote radio\n"); + } - AssertFatal(ret==0,"Cannot connect to remote radio\n"); } - - memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); - - if (ru->if_south == LOCAL_RF) { // configure RF parameters only - nr_init_frame_parms(&ru->config, fp); - nr_dump_frame_parms(fp); - fill_rf_config(ru,ru->rf_config_file); - nr_phy_init_RU(ru); + else if (ru->if_south == LOCAL_RF) { // configure RF parameters only ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); AssertFatal(ret==0,"Cannot connect to local radio\n"); } @@ -1482,13 +1292,16 @@ void *ru_thread( void *param ) { } sf_ahead = (uint16_t) ceil((float)6/(0x01<numerology_index)); - LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); + LOG_I(PHY, "Signaling main thread that RU %d is ready, sf_ahead %d\n",ru->idx,sf_ahead); pthread_mutex_lock(&RC.ru_mutex); RC.ru_mask &= ~(1<idx); pthread_cond_signal(&RC.ru_cond); pthread_mutex_unlock(&RC.ru_mutex); wait_sync("ru_thread"); + processingData_L1_t *syncMsg; + notifiedFIFO_elt_t *res; + if(!emulate_rf) { // Start RF device if any if (ru->start_rf) { @@ -1497,37 +1310,18 @@ void *ru_thread( void *param ) { else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); - // if an asnych_rxtx thread exists - // wakeup the thread because the devices are ready at this point - - if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) { - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx=0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); - } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); - - // if this is a slave RRU, try to synchronize on the DL frequency - if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); - // start trx write thread - if(usrp_tx_thread == 1){ - if (ru->start_write_thread){ - if(ru->start_write_thread(ru) != 0){ + if(usrp_tx_thread == 1) { + if (ru->start_write_thread) { + if(ru->start_write_thread(ru) != 0) { LOG_E(HW,"Could not start tx write thread\n"); - } - else{ + } else { LOG_I(PHY,"tx write thread ready\n"); } } } } - pthread_mutex_lock(&proc->mutex_FH1); - proc->instance_cnt_FH1 = 0; - pthread_mutex_unlock(&proc->mutex_FH1); - pthread_cond_signal(&proc->cond_FH1); - // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. @@ -1542,102 +1336,103 @@ void *ru_thread( void *param ) { // synchronization on input FH interface, acquire signals/data and block LOG_D(PHY,"[RU_thread] read data: frame_rx = %d, tti_rx = %d\n", frame, slot); + if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot); else AssertFatal(1==0, "No fronthaul interface at south port"); + if (initial_wait == 1 && proc->frame_rx < 300 && ru->fh_south_in == rx_rf) { + if (proc->frame_rx>0 && ((proc->frame_rx % 100) == 0) && proc->tti_rx==0) { + LOG_I(PHY,"delay processing to let RX stream settle, frame %d (trials %d)\n",proc->frame_rx,ru->rx_fhaul.trials); + print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); + reset_meas(&ru->rx_fhaul); + } + continue; + } + if (proc->frame_rx>=300) { + initial_wait=0; + opp_enabled = opp_enabled0; + } + if (initial_wait == 0 && ru->rx_fhaul.trials > 1000) reset_meas(&ru->rx_fhaul); + proc->timestamp_tx = proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); + proc->frame_tx = (proc->tti_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (proc->frame_rx+1)&1023 : proc->frame_rx; + proc->tti_tx = (proc->tti_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", frame,slot, proc->frame_rx,proc->tti_rx, proc->frame_tx,proc->tti_tx, RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); - /* - LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", - ru->do_prach, - is_prach_subframe(fp, proc->frame_rx, proc->tti_rx), - proc->frame_rx,proc->tti_rx); + RC.gNB[0]->proc.frame_tx); - if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) { - wakeup_prach_ru(ru); - }*/ - - // adjust for timing offset between RU - //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx); if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; // do RX front-end processing (frequency-shift, dft) if needed - int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { - //if (proc->tti_rx==8) { + if (ru->feprx) { + ru->feprx(ru,proc->tti_rx); + //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); + LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); +/* + LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); - if (ru->feprx) ru->feprx(ru,proc->tti_rx); - //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); + for (int aa=0; aanb_rx; aa++) + memcpy((void *)RC.gNB[0]->common_vars.rxdataF[aa], + (void *)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); +*/ + if (IS_SOFTMODEM_DOSCOPE && RC.gNB[0]->scopeData) + ((scopeData_t *)RC.gNB[0]->scopeData)->slotFunc(ru->common.rxdataF[0],proc->tti_rx, RC.gNB[0]->scopeData); - LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); - LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); - - for (aa=0;aanb_rx;aa++) - memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa], - (void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); + // Do PRACH RU processing + int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); + uint8_t prachStartSymbol,N_dur; - // Do PRACH RU processing - int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); - if (prach_id>=0) { - rx_nr_prach_ru(ru, - ru->prach_list[prach_id].fmt, - ru->prach_list[prach_id].numRA, - ru->prach_list[prach_id].prachStartSymbol, - proc->frame_rx,proc->tti_rx); - free_nr_ru_prach_entry(ru,prach_id); + if (prach_id>=0) { + T(T_GNB_PHY_PRACH_INPUT_SIGNAL, T_INT(proc->frame_rx), T_INT(proc->tti_rx), T_INT(0), + T_BUFFER(&ru->common.rxdata[0][fp->get_samples_slot_timestamp(proc->tti_rx-1,fp,0)]/*-ru->N_TA_offset*/, fp->get_samples_per_slot(proc->tti_rx,fp)*4*2)); + N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt); + + /* + get_nr_prach_info_from_index(ru->config.prach_config.prach_ConfigurationIndex.value, + proc->frame_rx,proc->tti_rx, + ru->config.carrier_config.dl_frequency.value, + fp->numerology_index, + fp->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period); + */ + for (int prach_oc = 0; prach_ocprach_list[prach_id].num_prach_ocas; prach_oc++) { + prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol+prach_oc*N_dur; + //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + rx_nr_prach_ru(ru, + ru->prach_list[prach_id].fmt, //could also use format + ru->prach_list[prach_id].numRA, + prachStartSymbol, + prach_oc, + proc->frame_rx,proc->tti_rx); + } + + free_nr_ru_prach_entry(ru,prach_id); + } } } // At this point, all information for subframe has been received on FH interface - - // wakeup all gNB processes waiting for this RU - if (ru->num_gNB>0) wakeup_gNB_L1s(ru); - - if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) { - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx); - - if(!emulate_rf) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1); - - if(proc->tti_tx == 9) { - sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); - LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); - sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); - FILE *output_fd = fopen(filename,"w"); - - if (output_fd) { - fwrite(&ru->common.txdata[i][0], - sizeof(int32_t), - fp->samples_per_frame, - output_fd); - fclose(output_fd); - } else { - LOG_E(PHY,"Cannot write to file %s\n",filename); - } - }//if(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - proc->emulate_rf_busy = 0; - }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) + res = pullTpool(gNB->resp_L1, gNB->threadPool); + syncMsg = (processingData_L1_t *)NotifiedFifoData(res); + syncMsg->gNB = gNB; + syncMsg->frame_rx = proc->frame_rx; + syncMsg->slot_rx = proc->tti_rx; + syncMsg->frame_tx = proc->frame_tx; + syncMsg->slot_tx = proc->tti_tx; + syncMsg->timestamp_tx = proc->timestamp_tx; + res->key = proc->tti_rx; + pushTpool(gNB->threadPool, res); } printf( "Exiting ru_thread \n"); @@ -1648,85 +1443,23 @@ void *ru_thread( void *param ) { else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); } + res = pullNotifiedFIFO(gNB->resp_L1); + delNotifiedFIFO_elt(res); + res = pullNotifiedFIFO(gNB->resp_L1_tx); + delNotifiedFIFO_elt(res); + res = pullNotifiedFIFO(gNB->resp_L1_tx); + delNotifiedFIFO_elt(res); + res = pullNotifiedFIFO(gNB->resp_RU_tx); + delNotifiedFIFO_elt(res); + ru_thread_status = 0; return &ru_thread_status; } -/* -// This thread run the initial synchronization like a UE -void *ru_thread_synch(void *arg) { - - RU_t *ru = (RU_t*)arg; - NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; - int32_t sync_pos,sync_pos2; - uint32_t peak_val; - uint32_t sync_corr[307200] __attribute__((aligned(32))); - static int ru_thread_synch_status; - - - - wait_sync("ru_thread_synch"); - - // initialize variables for PSS detection - lte_sync_time_init(ru->nr_frame_parms); - - while (!oai_exit) { - - // wait to be woken up - if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break; - - // if we're not in synch, then run initial synch - if (ru->in_synch == 0) { - // run intial synch like UE - LOG_I(PHY,"Running initial synchronization\n"); - - sync_pos = lte_sync_time_gNB(ru->common.rxdata, - fp, - fp->samples_per_subframe*5, - &peak_val, - sync_corr); - LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val); - - if (sync_pos >= 0) { - if (sync_pos >= fp->nb_prefix_samples) - sync_pos2 = sync_pos - fp->nb_prefix_samples; - else - sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples; - - if (fp->frame_type == FDD) { - - // PSS is hypothesized in last symbol of first slot in Frame - int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples; - - if (sync_pos2 >= sync_pos_slot) - ru->rx_offset = sync_pos2 - sync_pos_slot; - else - ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot; - } - else { - - } - - LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset); - - if ((peak_val > 300000) && (sync_pos > 0)) { - // if (sync_pos++ > 3) { - write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2); - write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1); - exit(-1); - } - - ru->in_synch=1; - } - } - - if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break; - } // oai_exit - - ru_thread_synch_status = 0; - return &ru_thread_synch_status; +int start_streaming(RU_t *ru) { + LOG_I(PHY,"Starting streaming on third-party RRU\n"); + return(ru->ifdevice.thirdparty_startstreaming(&ru->ifdevice)); } -*/ int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) { return(ru->ifdevice.trx_start_func(&ru->ifdevice)); @@ -1748,17 +1481,10 @@ int start_write_thread(RU_t *ru) { void init_RU_proc(RU_t *ru) { int i=0; RU_proc_t *proc; - char name[100]; LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); proc = &ru->proc; memset((void *)proc,0,sizeof(RU_proc_t)); proc->ru = ru; - proc->instance_cnt_prach = -1; - proc->instance_cnt_synch = -1; - proc->instance_cnt_FH = -1; - proc->instance_cnt_FH1 = -1; - proc->instance_cnt_gNBs = -1; - proc->instance_cnt_asynch_rxtx = -1; proc->instance_cnt_emulateRF = -1; proc->first_rx = 1; proc->first_tx = 1; @@ -1769,96 +1495,27 @@ void init_RU_proc(RU_t *ru) { for (i=0; i<10; i++) proc->symbol_mask[i]=0; - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); - pthread_mutex_init( &proc->mutex_synch,NULL); - pthread_mutex_init( &proc->mutex_FH,NULL); - pthread_mutex_init( &proc->mutex_FH1,NULL); pthread_mutex_init( &proc->mutex_emulateRF,NULL); - pthread_mutex_init( &proc->mutex_gNBs, NULL); - pthread_cond_init( &proc->cond_prach, NULL); - pthread_cond_init( &proc->cond_FH, NULL); - pthread_cond_init( &proc->cond_FH1, NULL); pthread_cond_init( &proc->cond_emulateRF, NULL); - pthread_cond_init( &proc->cond_asynch_rxtx, NULL); - pthread_cond_init( &proc->cond_synch,NULL); - pthread_cond_init( &proc->cond_gNBs, NULL); threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX ); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) - threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT ); - if(emulate_rf) threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); - if (ru->function == NGFI_RRU_IF4p5) { - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT ); - ///tmp deactivation of synch thread - // if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT ); - - snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); - pthread_setname_np( proc->pthread_FH, name ); - } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF - LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT ); - } - if (get_thread_worker_conf() == WORKER_ENABLE) { if (ru->feprx) nr_init_feprx_thread(ru); if (ru->feptx_ofdm) nr_init_feptx_thread(ru); } - if (opp_enabled == 1) threadCreate(&ru->ru_stats_thread,ru_stats_thread,(void *)ru, "emulateRF", -1, OAI_PRIORITY_RT_LOW); } void kill_NR_RU_proc(int inst) { RU_t *ru = RC.ru[inst]; RU_proc_t *proc = &ru->proc; - pthread_mutex_lock(&proc->mutex_FH); - proc->instance_cnt_FH = 0; - pthread_mutex_unlock(&proc->mutex_FH); - pthread_cond_signal(&proc->cond_FH); - pthread_mutex_lock(&proc->mutex_prach); - proc->instance_cnt_prach = 0; - pthread_mutex_unlock(&proc->mutex_prach); - pthread_cond_signal(&proc->cond_prach); - pthread_mutex_lock(&proc->mutex_synch); - proc->instance_cnt_synch = 0; - pthread_mutex_unlock(&proc->mutex_synch); - pthread_cond_signal(&proc->cond_synch); - pthread_mutex_lock(&proc->mutex_gNBs); - proc->instance_cnt_gNBs = 0; - pthread_mutex_unlock(&proc->mutex_gNBs); - pthread_cond_signal(&proc->cond_gNBs); - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx = 0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); LOG_D(PHY, "Joining pthread_FH\n"); pthread_join(proc->pthread_FH, NULL); - if (ru->function == NGFI_RRU_IF4p5) { - LOG_D(PHY, "Joining pthread_prach\n"); - pthread_join(proc->pthread_prach, NULL); - - if (ru->is_slave) { - LOG_D(PHY, "Joining pthread_\n"); - pthread_join(proc->pthread_synch, NULL); - } - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) { - LOG_D(PHY, "Joining pthread_asynch_rxtx\n"); - pthread_join(proc->pthread_asynch_rxtx, NULL); - } - } - if (get_nprocs() >= 2) { if (ru->feprx) { pthread_mutex_lock(&proc->mutex_fep); @@ -1887,21 +1544,9 @@ void kill_NR_RU_proc(int inst) { LOG_D(PHY, "Joining ru_stats_thread\n"); pthread_join(ru->ru_stats_thread, NULL); } - - pthread_mutex_destroy(&proc->mutex_prach); - pthread_mutex_destroy(&proc->mutex_asynch_rxtx); - pthread_mutex_destroy(&proc->mutex_synch); - pthread_mutex_destroy(&proc->mutex_FH); - pthread_mutex_destroy(&proc->mutex_gNBs); - pthread_cond_destroy(&proc->cond_prach); - pthread_cond_destroy(&proc->cond_FH); - pthread_cond_destroy(&proc->cond_asynch_rxtx); - pthread_cond_destroy(&proc->cond_synch); - pthread_cond_destroy(&proc->cond_gNBs); } -int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) -{ +int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) { FH_fmt_options_t fmt = cap->FH_fmt; int i; int found_band=0; @@ -1957,8 +1602,7 @@ char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"}; char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"}; void configure_ru(int idx, - void *arg) -{ + void *arg) { RU_t *ru = RC.ru[idx]; RRU_config_t *config = (RRU_config_t *)arg; RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg; @@ -2072,6 +1716,7 @@ void set_function_spec_param(RU_t *ru) { switch (ru->if_south) { case LOCAL_RF: // this is an RU with integrated RF (RRU, gNB) + reset_meas(&ru->rx_fhaul); if (ru->function == NGFI_RRU_IF5) { // IF5 RRU ru->do_prach = 0; // no prach processing in RU ru->fh_north_in = NULL; // no shynchronous incoming fronthaul from north @@ -2109,7 +1754,6 @@ void set_function_spec_param(RU_t *ru) { ru->ifdevice.host_type = RRU_HOST; ru->rfdevice.host_type = RRU_HOST; ru->ifdevice.eth_params = &ru->eth_params; - reset_meas(&ru->rx_fhaul); reset_meas(&ru->tx_fhaul); reset_meas(&ru->compression); reset_meas(&ru->transport); @@ -2131,26 +1775,26 @@ void set_function_spec_param(RU_t *ru) { ru->fh_north_out = NULL; // no outgoing fronthaul to north ru->nr_start_if = NULL; // no if interface ru->rfdevice.host_type = RAU_HOST; + ru->fh_south_in = rx_rf; // local synchronous RF RX + ru->fh_south_out = tx_rf; // local synchronous RF TX + ru->start_rf = start_rf; // need to start the local RF interface + ru->stop_rf = stop_rf; + ru->start_write_thread = start_write_thread; // starting RF TX in different thread + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); } - ru->fh_south_in = rx_rf; // local synchronous RF RX - ru->fh_south_out = tx_rf; // local synchronous RF TX - ru->start_rf = start_rf; // need to start the local RF interface - ru->stop_rf = stop_rf; - ru->start_write_thread = start_write_thread; // starting RF TX in different thread - printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); /* - if (ru->function == gNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise - fill_rf_config(ru,rf_config_file); - init_frame_parms(&ru->frame_parms,1); - nr_phy_init_RU(ru); - } + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); + fill_rf_config(ru,rf_config_file); + init_frame_parms(&ru->frame_parms,1); + nr_phy_init_RU(ru); - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - }*/ + ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + */ break; case REMOTE_IF5: // the remote unit is IF5 RRU @@ -2161,7 +1805,7 @@ void set_function_spec_param(RU_t *ru) { ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission ru->fh_south_asynch_in = NULL; // no asynchronous UL - ru->start_rf = NULL; // no local RF + ru->start_rf = ru->eth_params.transp_preference == ETH_UDP_IF5_ECPRI_MODE ? start_streaming : NULL; ru->stop_rf = NULL; ru->start_write_thread = NULL; ru->nr_start_if = nr_start_if; // need to start if interface for IF5 @@ -2181,7 +1825,7 @@ void set_function_spec_param(RU_t *ru) { case REMOTE_IF4p5: ru->do_prach = 0; ru->feprx = NULL; // DFTs - ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // Precoding operation + ru->feptx_prec = nr_feptx_prec; // Precoding operation ru->feptx_ofdm = NULL; // no OFDM mod ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission @@ -2203,6 +1847,18 @@ void set_function_spec_param(RU_t *ru) { exit(-1); } + if (ru->ifdevice.get_internal_parameter != NULL) { + void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in"); + + if (t != NULL) + ru->fh_south_in = t; + + t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out"); + + if (t != NULL) + ru->fh_south_out = t; + } + malloc_IF4p5_buffer(ru); break; @@ -2212,8 +1868,7 @@ void set_function_spec_param(RU_t *ru) { } // switch on interface type } -void init_NR_RU(char *rf_config_file) -{ +void init_NR_RU(char *rf_config_file) { int ru_id; RU_t *ru; PHY_VARS_gNB *gNB_RC; @@ -2226,9 +1881,8 @@ void init_NR_RU(char *rf_config_file) pthread_cond_init(&RC.ru_cond,NULL); // read in configuration file) printf("configuring RU from file\n"); - RCconfig_RU(); + NRRCconfig_RU(); LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs()); - LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); for (ru_id=0; ru_idopenair0_cfg.clock_source = internal; - LOG_D(PHY, "RU clock source set as internal\n"); + LOG_I(PHY, "RU clock source set as internal\n"); } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { RC.ru[j]->openair0_cfg.clock_source = external; - LOG_D(PHY, "RU clock source set as external\n"); + LOG_I(PHY, "RU clock source set as external\n"); } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { RC.ru[j]->openair0_cfg.clock_source = gpsdo; - LOG_D(PHY, "RU clock source set as gpsdo\n"); + LOG_I(PHY, "RU clock source set as gpsdo\n"); } else { LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); } - } - else { - RC.ru[j]->openair0_cfg.clock_source = unset; + } else { + LOG_I(PHY,"Setting clock source to internal\n"); + RC.ru[j]->openair0_cfg.clock_source = internal; } if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { RC.ru[j]->openair0_cfg.time_source = internal; - LOG_D(PHY, "RU time source set as internal\n"); + LOG_I(PHY, "RU time source set as internal\n"); } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { RC.ru[j]->openair0_cfg.time_source = external; - LOG_D(PHY, "RU time source set as external\n"); + LOG_I(PHY, "RU time source set as external\n"); } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { RC.ru[j]->openair0_cfg.time_source = gpsdo; - LOG_D(PHY, "RU time source set as gpsdo\n"); + LOG_I(PHY, "RU time source set as gpsdo\n"); } else { LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); } + } else { + LOG_I(PHY,"Setting time source to internal\n"); + RC.ru[j]->openair0_cfg.time_source = internal; } - else { - RC.ru[j]->openair0_cfg.time_source = unset; - } - + if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { RC.ru[j]->if_south = LOCAL_RF; @@ -2409,7 +2061,7 @@ void RCconfig_RU(void) RC.ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; RC.ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; - + RC.ru[j]->sf_extension = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr); for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; } //strcmp(local_rf, "yes") == 0 else { @@ -2426,6 +2078,12 @@ void RCconfig_RU(void) RC.ru[j]->if_south = REMOTE_IF5; RC.ru[j]->function = NGFI_RAU_IF5; RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_ecpri_if5") == 0) { + RC.ru[j]->if_south = REMOTE_IF5; + RC.ru[j]->function = NGFI_RAU_IF5; + RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF5_ECPRI_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_ecpri_if5") == 0) { + RC.ru[j]->if_south = REMOTE_IF5; } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { RC.ru[j]->if_south = REMOTE_IF5; RC.ru[j]->function = NGFI_RAU_IF5; @@ -2438,7 +2096,7 @@ void RCconfig_RU(void) RC.ru[j]->if_south = REMOTE_IF4p5; RC.ru[j]->function = NGFI_RAU_IF4p5; RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - } + } } /* strcmp(local_rf, "yes") != 0 */ RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); @@ -2446,11 +2104,15 @@ void RCconfig_RU(void) RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); RC.ru[j]->if_frequency = *(RUParamList.paramarray[j][RU_IF_FREQUENCY].u64ptr); + RC.ru[j]->if_freq_offset = *(RUParamList.paramarray[j][RU_IF_FREQ_OFFSET].iptr); + RC.ru[j]->do_precoding = *(RUParamList.paramarray[j][RU_DO_PRECODING].iptr); if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) { RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt; + for (i=0; inum_gNB; i++) { RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t)); + for (int b=0; bnb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b]; } } diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index c968fee7b6..c02155326b 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -30,12 +30,8 @@ #include "PHY/types.h" #include -#if defined(ENABLE_USE_MME) #include "s1ap_eNB.h" -#ifdef PDCP_USE_NETLINK #include "SIMULATION/ETH_TRANSPORT/proto.h" -#endif -#endif /* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ #define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" @@ -64,19 +60,27 @@ #define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" #define CONFIG_HLP_TADV "Set timing_advance\n" #define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" +#define CONFIG_HLP_ULOFF "Set the uplink frequnecy offset for all component carriers\n" #define CONFIG_HLP_CHOFF "Channel id offset\n" #define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n" #define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n" #define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" -#define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" +#define CONFIG_HLP_DLMCS_PHYTEST "Set the downlink MCS for PHYTEST mode\n" +#define CONFIG_HLP_DLNL_PHYTEST "Set the downlink nrOfLayers for PHYTEST mode\n" #define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" -#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" -#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" +#define CONFIG_HLP_ULMCS_PHYTEST "Set the uplink MCS for PHYTEST mode\n" +#define CONFIG_HLP_DLBW_PHYTEST "Set the number of PRBs used for DLSCH in PHYTEST mode\n" +#define CONFIG_HLP_ULBW_PHYTEST "Set the number of PRBs used for ULSCH in PHYTEST mode\n" +#define CONFIG_HLP_PRB_SA "Set the number of PRBs for SA\n" +#define CONFIG_HLP_DLBM_PHYTEST "Bitmap for DLSCH slots (slot 0 starts at LSB)\n" +#define CONFIG_HLP_ULBM_PHYTEST "Bitmap for ULSCH slots (slot 0 starts at LSB)\n" +#define CONFIG_HLP_SSC "Set the start subcarrier \n" #define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" #define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" #define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n" #define CONFIG_HLP_L2MONP "Enable L2 pcap messages on localhost \n" +#define CONFIG_HLP_MAC "Disable the MAC procedures at UE side (default is enabled)\n" #define CONFIG_HLP_VCD "Enable VCD (generated file will is named openair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n" #define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n" #define CONFIG_HLP_TPORT "tracer port\n" @@ -113,7 +117,7 @@ {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ {"G" , CONFIG_HLP_LOGV, 0, uptr:&glog_verbosity, defintval:0, TYPE_UINT16, 0}, \ {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ - {"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \ + {"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \ } #define CMDLINE_ONLINELOG_IDX 0 @@ -149,7 +153,4 @@ extern int emulate_rf; extern int numerology; extern int usrp_tx_thread; -extern volatile int start_eNB; -extern volatile int start_UE; - #endif diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index a3d0b325d6..a2b5c18b6c 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -53,6 +53,7 @@ #include "PHY_INTERFACE/phy_interface_vars.h" #include "gnb_config.h" #include "SIMULATION/TOOLS/sim.h" +#include #ifdef SMBV #include "PHY/TOOLS/smbv.h" @@ -65,10 +66,6 @@ unsigned short config_frames[4] = {2,9,11,13}; //#include "PHY/TOOLS/time_meas.h" -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_vars.h" -#endif - #include "intertask_interface.h" #include "PHY/INIT/phy_init.h" @@ -83,13 +80,17 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "executables/thread-common.h" #include "NB_IoT_interface.h" #include "x2ap_eNB.h" +#include "ngap_gNB.h" +#include "gnb_paramdef.h" +#include +#include "nfapi/oai_integration/vendor_ext.h" pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex -uint8_t nfapi_mode = 0; // Default to monolithic mode - +extern uint8_t nfapi_mode; // Default to monolithic mode +THREAD_STRUCT thread_struct; pthread_cond_t sync_cond; pthread_mutex_t sync_mutex; int sync_var=-1; //!< protected by mutex \ref sync_mutex. @@ -111,7 +112,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; //Temp fix for inexistent NR upper layer unsigned char NB_gNB_INST = 1; -static char *itti_dump_file = NULL; int UE_scan = 1; int UE_scan_carrier = 0; @@ -133,9 +133,6 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; double rx_gain_off = 0.0; -double sample_rate=30.72e6; -double bw = 10.0e6; - static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/; @@ -160,26 +157,30 @@ int otg_enabled; //static NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; //static nfapi_nr_config_request_t *config[MAX_NUM_CCs]; -uint32_t target_dl_mcs = 28; //maximum allowed mcs -uint32_t target_ul_mcs = 20; uint32_t timing_advance = 0; uint64_t num_missed_slots=0; // counter for the number of missed slots +#include +#include + int split73=0; void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { AssertFatal(false, "Must not be called in this context\n"); } +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, + uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} + extern void reset_opp_meas(void); extern void print_opp_meas(void); -extern void init_eNB_afterRU(void); extern void *udp_eNB_task(void *args_p); int transmission_mode=1; int emulate_rf = 0; int numerology = 0; -int usrp_tx_thread = 0; static char *parallel_config = NULL; @@ -298,147 +299,96 @@ void exit_function(const char *file, const char *function, const int line, const } -void *l2l1_task(void *arg) { - MessageDef *message_p = NULL; - int result; - itti_set_task_real_time(TASK_L2L1); - itti_mark_task_ready(TASK_L2L1); - /* Wait for the initialize message */ - printf("Wait for the ITTI initialize message\n"); - - do { - if (message_p != NULL) { - result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - } - - itti_receive_msg (TASK_L2L1, &message_p); - - switch (ITTI_MSG_ID(message_p)) { - case INITIALIZE_MESSAGE: - /* Start gNB thread */ - LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p)); - start_gNB = 1; - break; - - case TERMINATE_MESSAGE: - printf("received terminate message\n"); - oai_exit=1; - start_gNB = 0; - itti_exit_task (); - break; - - default: - LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); - break; - } - } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE); - - result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - /* ???? no else but seems to be UE only ??? - do { - // Wait for a message - itti_receive_msg (TASK_L2L1, &message_p); - - switch (ITTI_MSG_ID(message_p)) { - case TERMINATE_MESSAGE: - oai_exit=1; - itti_exit_task (); - break; - - case ACTIVATE_MESSAGE: - start_UE = 1; - break; - - case DEACTIVATE_MESSAGE: - start_UE = 0; - break; - - case MESSAGE_TEST: - LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); - break; - - default: - LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); - break; - } - - result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - } while(!oai_exit); - */ - return NULL; -} int create_gNB_tasks(uint32_t gnb_nb) { LOG_D(GNB_APP, "%s(gnb_nb:%d)\n", __FUNCTION__, gnb_nb); itti_wait_ready(1); - if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) { - LOG_E(PDCP, "Create task for L2L1 failed\n"); - return -1; - } - if (gnb_nb > 0) { /* Last task to create, others task must be ready before its start */ /*if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { LOG_E(GNB_APP, "Create task for gNB APP failed\n"); return -1; }*/ - if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0){ - LOG_E(SCTP, "Create task for SCTP failed\n"); - return -1; + if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) { + LOG_E(SCTP, "Create task for SCTP failed\n"); + return -1; } + if (is_x2ap_enabled()) { - if(itti_create_task(TASK_X2AP, x2ap_task, NULL) < 0){ - LOG_E(X2AP, "Create task for X2AP failed\n"); - } - } - else { - LOG_I(X2AP, "X2AP is disabled.\n"); + if(itti_create_task(TASK_X2AP, x2ap_task, NULL) < 0) { + LOG_E(X2AP, "Create task for X2AP failed\n"); + } + } else { + LOG_I(X2AP, "X2AP is disabled.\n"); } } - if (EPC_MODE_ENABLED && (get_softmodem_params()->phy_test==0 && get_softmodem_params()->do_ra==0)) { + paramdef_t NETParams[] = GNBNETPARAMS_DESC; + char aprefix[MAX_OPTNAME_SIZE*2 + 8]; + sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); + config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix); + + for(int i = GNB_INTERFACE_NAME_FOR_NG_AMF_IDX; i <= GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX; i++) { + if( NETParams[i].strptr == NULL) { + LOG_E(NGAP, "No configuration in the file.\n"); + NGAP_CONF_MODE = 0; + } else { + LOG_D(NGAP, "Configuration in the file: %s.\n",*NETParams[i].strptr); + } + } + + if (AMF_MODE_ENABLED) { if (gnb_nb > 0) { - /*if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) { + /* + if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) { LOG_E(SCTP, "Create task for SCTP failed\n"); return -1; } + */ + if(NGAP_CONF_MODE) { + if (itti_create_task (TASK_NGAP, ngap_gNB_task, NULL) < 0) { + LOG_E(NGAP, "Create task for NGAP failed\n"); + return -1; + } + } else { + LOG_E(NGAP, "Ngap task not created\n"); + } - if (itti_create_task (TASK_S1AP, s1ap_eNB_task, NULL) < 0) { - LOG_E(S1AP, "Create task for S1AP failed\n"); - return -1; - }*/ - - - if(!emulate_rf){ + if(!emulate_rf) { if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) { LOG_E(UDP_, "Create task for UDP failed\n"); return -1; } } - if (itti_create_task (TASK_GTPV1_U, >pv1u_gNB_task, NULL) < 0) { + /*if (itti_create_task (TASK_GTPV1_U, &nr_gtpv1u_gNB_task, NULL) < 0) { LOG_E(GTPU, "Create task for GTPV1U failed\n"); return -1; - } + }*/ } } - if (gnb_nb > 0) { if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { - LOG_E(GNB_APP, "Create task for gNB APP failed\n"); - return -1; - } + LOG_E(GNB_APP, "Create task for gNB APP failed\n"); + return -1; + } + LOG_I(NR_RRC,"Creating NR RRC gNB Task\n"); if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) { LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n"); return -1; } + + //Use check on x2ap to consider the NSA scenario and check on AMF_MODE_ENABLED for the SA scenario + if(is_x2ap_enabled() || AMF_MODE_ENABLED) { + if (itti_create_task (TASK_GTPV1_U, &nr_gtpv1u_gNB_task, NULL) < 0) { + LOG_E(GTPU, "Create task for GTPV1U failed\n"); + return -1; + } + } } return 0; @@ -446,18 +396,12 @@ int create_gNB_tasks(uint32_t gnb_nb) { static void get_options(void) { - - paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ; - CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); get_common_options(SOFTMODEM_GNB_BIT ); config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); - - - if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) { memset((void *)&RC,0,sizeof(RC)); /* Read RC configuration file */ @@ -470,13 +414,11 @@ static void get_options(void) { if(parallel_config != NULL) set_parallel_conf(parallel_config); if(worker_config != NULL) set_worker_conf(worker_config); - } void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], - NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) -{ + NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { for (int CC_id=0; CC_idrf_config.dl_carrier_bandwidth.value == 100) { - if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=23.04e6; - openair0_cfg[card].samples_per_frame = 230400; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } else { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } - } else if(config[0]->rf_config.dl_carrier_bandwidth.value == 50) { - openair0_cfg[card].sample_rate=15.36e6; - openair0_cfg[card].samples_per_frame = 153600; - openair0_cfg[card].tx_bw = 5e6; - openair0_cfg[card].rx_bw = 5e6; - } else if (config[0]->rf_config.dl_carrier_bandwidth.value == 25) { - openair0_cfg[card].sample_rate=7.68e6; - openair0_cfg[card].samples_per_frame = 76800; - openair0_cfg[card].tx_bw = 2.5e6; - openair0_cfg[card].rx_bw = 2.5e6; - } else if (config[0]->rf_config.dl_carrier_bandwidth.value == 6) { - openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_frame = 19200; - openair0_cfg[card].tx_bw = 1.5e6; - openair0_cfg[card].rx_bw = 1.5e6; - } - - - if (config[0]->subframe_config.duplex_mode.value==TDD) - openair0_cfg[card].duplex_mode = duplex_mode_TDD; - else //FDD - openair0_cfg[card].duplex_mode = duplex_mode_FDD; - - printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, - RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value, - RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - openair0_cfg[card].Mod_id = 0; - - openair0_cfg[card].num_rb_dl=config[0]->rf_config.dl_carrier_bandwidth.value; - - openair0_cfg[card].clock_source = clock_source; - - - openair0_cfg[card].tx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - openair0_cfg[card].rx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - - for (i=0; i<4; i++) { - - if (irx_total_gain_dB; - - - openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; - printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n", - card,i, openair0_cfg[card].tx_gain[i], - openair0_cfg[card].rx_gain[i], - openair0_cfg[card].tx_freq[i], - openair0_cfg[card].rx_freq[i]); - } - } // for loop on cards -} -*/ - void wait_RUs(void) { LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask); // wait for all RUs to be configured over fronthaul @@ -638,10 +493,9 @@ void wait_gNBs(void) { waiting=0; for (i=0; iconfigured==0) { - waiting=1; - break; + waiting=1; + break; } } } @@ -655,7 +509,7 @@ void wait_gNBs(void) { void terminate_task(task_id_t task_id, module_id_t mod_id) { LOG_I(GNB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id); MessageDef *msg; - msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE); + msg = itti_alloc_new_message (ENB_APP, 0, TERMINATE_MESSAGE); itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); } @@ -693,17 +547,13 @@ int stop_L1L2(module_id_t gnb_id) { /* these tasks need to pick up new configuration */ terminate_task(TASK_RRC_ENB, gnb_id); - terminate_task(TASK_L2L1, gnb_id); LOG_I(GNB_APP, "calling kill_gNB_proc() for instance %d\n", gnb_id); kill_gNB_proc(gnb_id); LOG_I(GNB_APP, "calling kill_NR_RU_proc() for instance %d\n", gnb_id); kill_NR_RU_proc(gnb_id); oai_exit = 0; - - //free_transport(RC.gNB[gnb_id]); + //free_transport(RC.gNB[gnb_id]); phy_free_nr_gNB(RC.gNB[gnb_id]); - - nr_phy_free_RU(RC.ru[gnb_id]); free_lte_top(); return 0; @@ -718,27 +568,16 @@ int restart_L1L2(module_id_t gnb_id) { LOG_W(GNB_APP, "restarting nr-softmodem\n"); /* block threads */ sync_var = -1; - RC.gNB[gnb_id]->configured = 0; - - RC.ru_mask |= (1 << ru->idx); set_function_spec_param(RC.ru[gnb_id]); LOG_I(GNB_APP, "attempting to create ITTI tasks\n"); // No more rrc thread, as many race conditions are hidden behind rrc_enb_init(); itti_mark_task_ready(TASK_RRC_ENB); - - if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) { - LOG_E(PDCP, "Create task for L2L1 failed\n"); - return -1; - } else { - LOG_I(PDCP, "Re-created task for L2L1 successfully\n"); - } - /* pass a reconfiguration request which will configure everything down to * RC.eNB[i][j]->frame_parms, too */ - msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ); + msg_p = itti_alloc_new_message(TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ); RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[gnb_id]->configuration; itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p); /* TODO XForms might need to be restarted, but it is currently (09/02/18) @@ -769,32 +608,34 @@ static void wait_nfapi_init(char *thread_name) { } void init_pdcp(void) { - //if (!NODE_IS_DU(RC.rrc[0]->node_type)) { - pdcp_layer_init(); - uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? - (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) { + // pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; - if (IS_SOFTMODEM_NOS1) { - printf("IS_SOFTMODEM_NOS1 option enabled \n"); - pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; - } + if (IS_SOFTMODEM_NOS1) { + printf("IS_SOFTMODEM_NOS1 option enabled \n"); + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT; + } - pdcp_module_init(pdcp_initmask); + pdcp_module_init(pdcp_initmask); - /*if (NODE_IS_CU(RC.rrc[0]->node_type)) { - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); - } else {*/ - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); - pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); - //} - /*} else { + if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + LOG_I(PDCP, "node is CU, pdcp send rlc_data_req by proto_agent \n"); + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + } else { + LOG_I(PDCP, "node is gNB \n"); + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); + } + } else { + LOG_I(PDCP, "node is DU, rlc send pdcp_data_ind by proto_agent \n"); pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); - }*/ + } } -int main( int argc, char **argv ) -{ +int main( int argc, char **argv ) { int ru_id, CC_id = 0; start_background_system(); @@ -802,6 +643,7 @@ int main( int argc, char **argv ) if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) { exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); } + set_softmodem_sighandler(); #ifdef DEBUG_CONSOLE setvbuf(stdout, NULL, _IONBF, 0); @@ -821,11 +663,15 @@ int main( int argc, char **argv ) } openair0_cfg[0].threequarter_fs = threequarter_fs; - EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; //!get_softmodem_params()->phy_test; + AMF_MODE_ENABLED = get_softmodem_params()->sa; + NGAP_CONF_MODE = get_softmodem_params()->sa; if (get_softmodem_params()->do_ra) AssertFatal(get_softmodem_params()->phy_test == 0,"RA and phy_test are mutually exclusive\n"); + if (get_softmodem_params()->sa) + AssertFatal(get_softmodem_params()->phy_test == 0,"Standalone mode and phy_test are mutually exclusive\n"); + #if T_TRACER T_Config_Init(); #endif @@ -838,38 +684,24 @@ int main( int argc, char **argv ) } cpuf=get_cpu_freq_GHz(); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + itti_init(TASK_MAX, tasks_info); // initialize mscgen log after ITTI - MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); - - + MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX); init_opt(); - - -#ifdef PDCP_USE_NETLINK -if(!IS_SOFTMODEM_NOS1) - netlink_init(); -#if defined(PDCP_USE_NETLINK_QUEUES) - pdcp_netlink_init(); -#endif -#endif - + if(PDCP_USE_NETLINK) + if(!IS_SOFTMODEM_NOS1) + netlink_init(); + #ifndef PACKAGE_VERSION # define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" #endif LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); - if(IS_SOFTMODEM_NOS1) - init_pdcp(); - - if (RC.nb_nr_inst > 0) { - // don't create if node doesn't connect to RRC/S1/GTP - AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n"); - } else { - printf("No ITTI, Initializing L1\n"); - RCconfig_L1(); - } + if (RC.nb_nr_L1_inst > 0) + RCconfig_NR_L1(); + // don't create if node doesn't connect to RRC/S1/GTP + AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n"); /* Start the agent. If it is turned off in the configuration, it won't start */ /* RCconfig_nr_flexran(); @@ -877,18 +709,16 @@ if(!IS_SOFTMODEM_NOS1) for (i = 0; i < RC.nb_nr_L1_inst; i++) { flexran_agent_start(i); } -*/ - + */ // init UE_PF_PO and mutex lock pthread_mutex_init(&ue_pf_po_mutex, NULL); memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs); mlockall(MCL_CURRENT | MCL_FUTURE); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); - usleep(1000); - if (nfapi_mode) { + if (NFAPI_MODE) { printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n"); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); @@ -896,7 +726,7 @@ if(!IS_SOFTMODEM_NOS1) const char *nfapi_mode_str = ""; - switch(nfapi_mode) { + switch(NFAPI_MODE) { case 0: nfapi_mode_str = "MONOLITHIC"; break; @@ -916,7 +746,7 @@ if(!IS_SOFTMODEM_NOS1) printf("NFAPI MODE:%s\n", nfapi_mode_str); - if (nfapi_mode==2) // VNF + if (NFAPI_MODE==NFAPI_MODE_VNF) wait_nfapi_init("main?"); printf("START MAIN THREADS\n"); @@ -945,42 +775,47 @@ if(!IS_SOFTMODEM_NOS1) config_sync_var=0; - if (nfapi_mode==1) { // PNF + if (NFAPI_MODE==NFAPI_MODE_PNF) { wait_nfapi_init("main?"); } - printf("wait RUs\n"); - wait_RUs(); - printf("ALL RUs READY!\n"); - printf("RC.nb_RU:%d\n", RC.nb_RU); - // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration) - printf("ALL RUs ready - init gNBs\n"); - if(IS_SOFTMODEM_DOFORMS) { - - scopeParms_t p; - p.argc=&argc; - p.argv=argv; - p.gNB=RC.gNB[0]; - p.ru=RC.ru[0]; - load_softscope("nr",&p); + if (RC.nb_nr_L1_inst > 0) { + printf("wait RUs\n"); + wait_RUs(); + printf("ALL RUs READY!\n"); + printf("RC.nb_RU:%d\n", RC.nb_RU); + // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration) + printf("ALL RUs ready - init gNBs\n"); + + if(IS_SOFTMODEM_DOSCOPE) { + sleep(1); + scopeParms_t p; + p.argc=&argc; + p.argv=argv; + p.gNB=RC.gNB[0]; + p.ru=RC.ru[0]; + load_softscope("nr",&p); + } + + if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) { + printf("Not NFAPI mode - call init_eNB_afterRU()\n"); + init_eNB_afterRU(); + } else { + printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n"); + } + + printf("ALL RUs ready - ALL gNBs ready\n"); + // connect the TX/RX buffers + printf("Sending sync to all threads\n"); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); } - if (nfapi_mode != 1 && nfapi_mode != 2) { - printf("Not NFAPI mode - call init_eNB_afterRU()\n"); - init_eNB_afterRU(); - } else { - printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n"); - } - - printf("ALL RUs ready - ALL gNBs ready\n"); - // connect the TX/RX buffers - printf("Sending sync to all threads\n"); - pthread_mutex_lock(&sync_mutex); - sync_var=0; - pthread_cond_broadcast(&sync_cond); - pthread_mutex_unlock(&sync_mutex); printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); - end_configmodule(); + // We have to set PARAMFLAG_NOFREE on right paramters before re-enabling end_configmodule() + //end_configmodule(); printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); // wait for end of program printf("TYPE TO TERMINATE\n"); @@ -990,7 +825,6 @@ if(!IS_SOFTMODEM_NOS1) printf("Returned from ITTI signal handler\n"); oai_exit=1; printf("oai_exit=%d\n",oai_exit); - // stop threads /*#ifdef XFORMS @@ -1016,13 +850,16 @@ if(!IS_SOFTMODEM_NOS1) printf("stopping MODEM threads\n"); // cleanup stop_gNB(NB_gNB_INST); - stop_RU(NB_RU); + + if (RC.nb_nr_L1_inst > 0) { + stop_RU(NB_RU); + } /* release memory used by the RU/gNB threads (incomplete), after all * threads have been stopped (they partially use the same memory) */ for (int inst = 0; inst < NB_gNB_INST; inst++) { - //free_transport(RC.gNB[inst]); - phy_free_nr_gNB(RC.gNB[inst]); + //free_transport(RC.gNB[inst]); + phy_free_nr_gNB(RC.gNB[inst]); } for (int inst = 0; inst < NB_RU; inst++) { @@ -1046,7 +883,6 @@ if(!IS_SOFTMODEM_NOS1) RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); } - logClean(); printf("Bye.\n"); return 0; diff --git a/executables/nr-softmodem.h b/executables/nr-softmodem.h index d6cfe6b906..896c363cbf 100644 --- a/executables/nr-softmodem.h +++ b/executables/nr-softmodem.h @@ -18,19 +18,29 @@ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_PARAMS_DESC_GNB { \ - {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \ - {"K" , CONFIG_HLP_ITTIL, PARAMFLAG_NOFREE, strptr:&itti_dump_file, defstrval:"/tmp/itti.dump", TYPE_STRING, 0}, \ - {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ - {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ + {"m" , CONFIG_HLP_DLMCS_PHYTEST,0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ + {"l" , CONFIG_HLP_DLNL_PHYTEST,0, uptr:&target_dl_Nl, defintval:0, TYPE_UINT, 0}, \ + {"t" , CONFIG_HLP_ULMCS_PHYTEST,0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ + {"M" , CONFIG_HLP_DLBW_PHYTEST,0, uptr:&target_dl_bw, defintval:0, TYPE_UINT, 0}, \ + {"T" , CONFIG_HLP_ULBW_PHYTEST,0, uptr:&target_ul_bw, defintval:0, TYPE_UINT, 0}, \ + {"D" , CONFIG_HLP_DLBM_PHYTEST,0, u64ptr:&dlsch_slot_bitmap, defintval:0, TYPE_UINT64, 0}, \ + {"U" , CONFIG_HLP_ULBM_PHYTEST,0, u64ptr:&ulsch_slot_bitmap, defintval:0, TYPE_UINT64, 0}, \ {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \ {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ } #include "threads_t.h" extern threads_t threads; +extern uint32_t target_dl_mcs; +extern uint32_t target_dl_Nl; +extern uint32_t target_ul_mcs; +extern uint32_t target_dl_bw; +extern uint32_t target_ul_bw; +extern uint64_t dlsch_slot_bitmap; +extern uint64_t ulsch_slot_bitmap; // In nr-gnb.c extern void init_gNB(int single_thread_flag,int wait_for_sync); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 4b7ff20461..362ad80e9d 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -18,48 +18,18 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -#include "executables/thread-common.h" + +#include #include "executables/nr-uesoftmodem.h" - -#include "NR_MAC_UE/mac.h" -//#include "RRC/LTE/rrc_extern.h" -#include "PHY_INTERFACE/phy_interface_extern.h" - -#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all -//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all - -#include "fapi_nr_ue_l1.h" #include "PHY/phy_extern_nr_ue.h" #include "PHY/INIT/phy_init.h" -#include "PHY/MODULATION/modulation_UE.h" #include "NR_MAC_UE/mac_proto.h" #include "RRC/NR_UE/rrc_proto.h" - #include "SCHED_NR_UE/phy_frame_config_nr.h" #include "SCHED_NR_UE/defs.h" - #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" - -#include "common/utils/LOG/log.h" -#include "common/utils/system.h" -#include "common/utils/LOG/vcd_signal_dumper.h" -#include "executables/nr-softmodem.h" - -#include "T.h" - -#ifdef XFORMS - #include "PHY/TOOLS/nr_phy_scope.h" - - extern char do_forms; -#endif - -// Missing stuff? -int next_ra_frame = 0; -module_id_t next_Mod_id = 0; - -extern double cpuf; -//static nfapi_nr_config_request_t config_t; -//static nfapi_nr_config_request_t* config =&config_t; +#include "executables/softmodem-common.h" +#include "SCHED_NR_UE/pucch_uci_ue_nr.h" /* * NR SLOT PROCESSING SEQUENCE @@ -118,34 +88,27 @@ extern double cpuf; * */ -#ifndef NO_RAT_NR - #define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */ -#else - #define DURATION_RX_TO_TX (6) /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */ -#endif -#define FRAME_PERIOD 100000000ULL -#define DAQ_PERIOD 66667ULL +#define RX_JOB_ID 0x1010 +#define TX_JOB_ID 100 typedef enum { - pss=0, - pbch=1, - si=2 + pss = 0, + pbch = 1, + si = 2 } sync_mode_t; - void init_nr_ue_vars(PHY_VARS_NR_UE *ue, - NR_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag) { int nb_connected_gNB = 1, gNB_id; - memcpy(&(ue->frame_parms), frame_parms, sizeof(NR_DL_FRAME_PARMS)); - ue->Mod_id = UE_id; ue->mac_enabled = 1; + ue->if_inst = nr_ue_if_module_init(0); + ue->dci_thres = 0; // Setting UE mode to NOT_SYNCHED by default for (gNB_id = 0; gNB_id < nb_connected_gNB; gNB_id++){ @@ -158,6 +121,9 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, // intialize transport init_nr_ue_transport(ue, abstraction_flag); + + // init N_TA offset + init_N_TA_offset(ue); } /*! @@ -165,34 +131,29 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure. */ -typedef struct syncData_s { - UE_nr_rxtx_proc_t proc; - PHY_VARS_NR_UE *UE; -} syncData_t; +typedef nr_rxtx_thread_data_t syncData_t; static void UE_synch(void *arg) { syncData_t *syncD=(syncData_t *) arg; int i, hw_slot_offset; PHY_VARS_NR_UE *UE = syncD->UE; sync_mode_t sync_mode = pbch; - int CC_id = UE->CC_id; - int freq_offset=0; + //int CC_id = UE->CC_id; + static int freq_offset=0; UE->is_synchronized = 0; if (UE->UE_scan == 0) { - LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu64", UL %"PRIu64" (oai_exit %d, rx_num_channels %d)\n", - UE->frame_parms.dl_CarrierFreq, UE->frame_parms.ul_CarrierFreq, - oai_exit, openair0_cfg[0].rx_num_channels); for (i=0; irf_map.card].rx_num_channels; i++) { - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq; - openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; - if (UE->frame_parms.frame_type == FDD) - openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD; - else - openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD; + LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %f, UL %f (RF card %d, oai_exit %d, channel %d, rx_num_channels %d)\n", + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i], + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i], + UE->rf_map.card, + oai_exit, + i, + openair0_cfg[0].rx_num_channels); + } sync_mode = pbch; @@ -247,75 +208,30 @@ static void UE_synch(void *arg) { case pbch: LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); - if (nr_initial_sync( &syncD->proc, UE, UE->mode,2) == 0) { + uint64_t dl_carrier, ul_carrier; + nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier); + + if (nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa, get_nrUE_params()->nr_dlsch_parallel) == 0) { freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) + round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0); - LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %lu, UL %lu), UE_scan_carrier %d\n", - hw_slot_offset, - freq_offset, - UE->rx_total_gain_dB, - UE->frame_parms.dl_CarrierFreq+freq_offset, - UE->frame_parms.ul_CarrierFreq+freq_offset, - UE->UE_scan_carrier ); // rerun with new cell parameters and frequency-offset - for (i=0; irf_map.card].rx_num_channels; i++) { - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + // todo: the freq_offset computed on DL shall be scaled before being applied to UL + nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_carrier, dl_carrier, freq_offset); - if (freq_offset >= 0) - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset); - else - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset); - - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+(UE->frame_parms.ul_CarrierFreq-UE->frame_parms.dl_CarrierFreq); - UE->frame_parms.dl_CarrierFreq = openair0_cfg[CC_id].rx_freq[i]; - } - - // reconfigure for potentially different bandwidth - switch(UE->frame_parms.N_RB_DL) { - case 6: - openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; - openair0_cfg[UE->rf_map.card].rx_bw =.96e6; - openair0_cfg[UE->rf_map.card].tx_bw =.96e6; - // openair0_cfg[0].rx_gain[0] -= 12; - break; - - case 25: - openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; - openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; - openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; - // openair0_cfg[0].rx_gain[0] -= 6; - break; - - case 50: - openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; - openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; - openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; - // openair0_cfg[0].rx_gain[0] -= 3; - break; - - case 100: - openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; - openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; - openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; - // openair0_cfg[0].rx_gain[0] -= 0; - break; - - case 66: - openair0_cfg[UE->rf_map.card].sample_rate=122.88e6; - openair0_cfg[UE->rf_map.card].rx_bw=100.e6; - openair0_cfg[UE->rf_map.card].tx_bw=100.e6; - break; - } + LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %f (DL %f Hz, UL %f Hz)\n", + hw_slot_offset, + freq_offset, + openair0_cfg[UE->rf_map.card].rx_gain[0], + openair0_cfg[UE->rf_map.card].rx_freq[0], + openair0_cfg[UE->rf_map.card].tx_freq[0]); if (UE->mode != loop_through_memory) { UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); //UE->rfdevice.trx_stop_func(&UE->rfdevice); // sleep(1); - //nr_init_frame_parms_ue(&UE->frame_parms); /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { LOG_E(HW,"Could not start the device\n"); oai_exit=1; @@ -328,31 +244,21 @@ static void UE_synch(void *arg) { UE->is_synchronized = 1; } } else { - // initial sync failed - // calculate new offset and try again + if (UE->UE_scan_carrier == 1) { + if (freq_offset >= 0) freq_offset += 100; freq_offset *= -1; - LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %lu, UL %lu)\n", - freq_offset, - UE->rx_total_gain_dB, - UE->frame_parms.dl_CarrierFreq+freq_offset, - UE->frame_parms.ul_CarrierFreq+freq_offset ); - for (i=0; irf_map.card].rx_num_channels; i++) { - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq+freq_offset; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq+freq_offset; - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_carrier, dl_carrier, freq_offset); - if (UE->UE_scan_carrier==1) - openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; - } + LOG_I(PHY, "Initial sync failed: trying carrier off %d Hz\n", freq_offset); if (UE->mode != loop_through_memory) UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); - }// initial_sync=0 + } break; @@ -363,13 +269,16 @@ static void UE_synch(void *arg) { } } -void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { - +void processSlotTX(void *arg) { + nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg; + UE_nr_rxtx_proc_t *proc = &rxtxD->proc; + PHY_VARS_NR_UE *UE = rxtxD->UE; fapi_nr_config_request_t *cfg = &UE->nrUE_config; - int tx_slot_type = nr_ue_slot_select(cfg, proc->frame_tx, proc->nr_tti_tx); + int tx_slot_type = nr_ue_slot_select(cfg, proc->frame_tx, proc->nr_slot_tx); uint8_t gNB_id = 0; + LOG_D(PHY,"%d.%d => slot type %d\n",proc->frame_tx,proc->nr_slot_tx,tx_slot_type); if (tx_slot_type == NR_UPLINK_SLOT || tx_slot_type == NR_MIXED_SLOT){ // trigger L2 to run ue_scheduler thru IF module @@ -382,124 +291,97 @@ void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { ul_indication.gNB_index = gNB_id; ul_indication.cc_id = UE->CC_id; ul_indication.frame_rx = proc->frame_rx; - ul_indication.slot_rx = proc->nr_tti_rx; + ul_indication.slot_rx = proc->nr_slot_rx; ul_indication.frame_tx = proc->frame_tx; - ul_indication.slot_tx = proc->nr_tti_tx; + ul_indication.slot_tx = proc->nr_slot_tx; + ul_indication.thread_id = proc->thread_id; + ul_indication.ue_sched_mode = rxtxD->ue_sched_mode; UE->if_inst->ul_indication(&ul_indication); } - if (UE->mode != loop_through_memory) { - uint8_t thread_id = PHY_vars_UE_g[UE->Mod_id][0]->current_thread_id[proc->nr_tti_rx]; - phy_procedures_nrUE_TX(UE,proc,0,thread_id); + if ((UE->mode != loop_through_memory) && (rxtxD->ue_sched_mode != NOT_PUSCH)) { + phy_procedures_nrUE_TX(UE,proc,0); } } } -void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { +void processSlotRX(void *arg) { + nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg; + UE_nr_rxtx_proc_t *proc = &rxtxD->proc; + PHY_VARS_NR_UE *UE = rxtxD->UE; fapi_nr_config_request_t *cfg = &UE->nrUE_config; - int rx_slot_type = nr_ue_slot_select(cfg, proc->frame_rx, proc->nr_tti_rx); + int rx_slot_type = nr_ue_slot_select(cfg, proc->frame_rx, proc->nr_slot_rx); + int tx_slot_type = nr_ue_slot_select(cfg, proc->frame_tx, proc->nr_slot_tx); uint8_t gNB_id = 0; if (rx_slot_type == NR_DOWNLINK_SLOT || rx_slot_type == NR_MIXED_SLOT){ if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) { nr_downlink_indication_t dl_indication; - memset((void*)&dl_indication, 0, sizeof(dl_indication)); - - dl_indication.module_id = UE->Mod_id; - dl_indication.gNB_index = gNB_id; - dl_indication.cc_id = UE->CC_id; - dl_indication.frame = proc->frame_rx; - dl_indication.slot = proc->nr_tti_rx; - + nr_fill_dl_indication(&dl_indication, NULL, NULL, proc, UE, gNB_id); UE->if_inst->dl_indication(&dl_indication, NULL); } // Process Rx data for one sub-frame #ifdef UE_SLOT_PARALLELISATION - phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL ); + phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, no_relay, NULL ); #else uint64_t a=rdtsc(); - phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode); - LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500); - //printf(">>> nr_ue_pdcch_procedures ended\n"); + phy_procedures_nrUE_RX(UE, proc, gNB_id, get_nrUE_params()->nr_dlsch_parallel, &rxtxD->txFifo); + LOG_D(PHY, "In %s: slot %d, time %lu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc()-a)/3500); #endif - if(IS_SOFTMODEM_NOS1){ //&& proc->nr_tti_rx==1 - //Hardcoded rnti value + if(IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa){ + NR_UE_MAC_INST_t *mac = get_mac_inst(0); protocol_ctxt_t ctxt; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, - 0x1234, proc->frame_rx, - proc->nr_tti_rx, 0); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, mac->crnti, proc->frame_rx, proc->nr_slot_rx, 0); pdcp_run(&ctxt); + + /* send tick to RLC and PDCP every ms */ + if (proc->nr_slot_rx % UE->frame_parms.slots_per_subframe == 0) { + void nr_rlc_tick(int frame, int subframe); + void nr_pdcp_tick(int frame, int subframe); + nr_rlc_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe); + nr_pdcp_tick(proc->frame_rx, proc->nr_slot_rx / UE->frame_parms.slots_per_subframe); + } } + // calling UL_indication to schedule things other than PUSCH (eg, PUCCH) + rxtxD->ue_sched_mode = NOT_PUSCH; + processSlotTX(rxtxD); + + // Wait for PUSCH processing to finish + notifiedFIFO_elt_t *res; + res = pullTpool(&rxtxD->txFifo,&(get_nrUE_params()->Tpool)); + delNotifiedFIFO_elt(res); + + } else { + rxtxD->ue_sched_mode = SCHED_ALL; + processSlotTX(rxtxD); } - // no UL for now - /* - if (UE->mac_enabled==1) { - // trigger L2 to run ue_scheduler thru IF module - // [TODO] mapping right after NR initial sync - if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) { - UE->ul_indication.module_id = 0; - UE->ul_indication.gNB_index = 0; - UE->ul_indication.cc_id = 0; - UE->ul_indication.frame = proc->frame_rx; - UE->ul_indication.slot = proc->nr_tti_rx; - UE->if_inst->ul_indication(&UE->ul_indication); + if (tx_slot_type == NR_UPLINK_SLOT || tx_slot_type == NR_MIXED_SLOT){ + if (UE->UE_mode[gNB_id] <= PUSCH) { + if (get_softmodem_params()->usim_test==0) { + pucch_procedures_ue_nr(UE, + gNB_id, + proc); + } + + LOG_D(PHY, "Sending Uplink data \n"); + nr_ue_pusch_common_procedures(UE, + proc->nr_slot_tx, + &UE->frame_parms,1); } - } - */ -} - -/*! - * \brief This is the UE thread for RX subframe n and TX subframe n+4. - * This thread performs the phy_procedures_UE_RX() on every received slot. - * then, if TX is enabled it performs TX for n+4. - * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ - -typedef struct processingData_s { - UE_nr_rxtx_proc_t proc; - PHY_VARS_NR_UE *UE; -} processingData_t; - -void UE_processing(void *arg) { - processingData_t *rxtxD = (processingData_t *) arg; - UE_nr_rxtx_proc_t *proc = &rxtxD->proc; - PHY_VARS_NR_UE *UE = rxtxD->UE; - - uint8_t gNB_id = 0; - - // params for UL time alignment procedure - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &UE->ul_time_alignment[gNB_id]; - uint8_t numerology = UE->frame_parms.numerology_index; - uint16_t bwp_ul_NB_RB = UE->frame_parms.N_RB_UL; - int slot_tx = proc->nr_tti_tx; - int frame_tx = proc->frame_tx; - - /* UL time alignment - // If the current tx frame and slot match the TA configuration in ul_time_alignment - // then timing advance is processed and set to be applied in the next UL transmission */ - if (UE->mac_enabled == 1) { - - if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) { - LOG_D(PHY,"Applying timing advance -- frame %d -- slot %d\n", frame_tx, slot_tx); - - //if (nfapi_mode!=3){ - nr_process_timing_advance(UE->Mod_id, UE->CC_id, ul_time_alignment->ta_command, numerology, bwp_ul_NB_RB); - ul_time_alignment->ta_frame = -1; - ul_time_alignment->ta_slot = -1; - //} + if (UE->UE_mode[gNB_id] > NOT_SYNCHED && UE->UE_mode[gNB_id] < PUSCH) { + nr_ue_prach_procedures(UE, proc, gNB_id); } + LOG_D(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", proc->frame_tx, proc->nr_slot_tx); } - processSlotRX(UE, proc); - processSlotTX(UE, proc); + ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx); } void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) { @@ -578,13 +460,18 @@ int computeSamplesShift(PHY_VARS_NR_UE *UE) { // compute TO compensation that should be applied for this frame if ( UE->rx_offset < UE->frame_parms.samples_per_frame/2 && UE->rx_offset > 0 ) { - //LOG_I(PHY,"!!!adjusting -1 samples!!!\n"); + LOG_I(PHY,"!!!adjusting -1 samples!!! rx_offset == %d\n", UE->rx_offset); + UE->rx_offset = 0; // reset so that it is not applied falsely in case of SSB being only in every second frame + UE->max_pos_fil = 0; // reset IIR filter when sample shift is applied return -1 ; } if ( UE->rx_offset > UE->frame_parms.samples_per_frame/2 && UE->rx_offset < UE->frame_parms.samples_per_frame ) { - //LOG_I(PHY,"!!!adjusting +1 samples!!!\n"); + int rx_offset = UE->rx_offset - UE->frame_parms.samples_per_frame; + LOG_I(PHY,"!!!adjusting +1 samples!!! rx_offset == %d\n", rx_offset); + UE->rx_offset = 0; // reset so that it is not applied falsely in case of SSB being only in every second frame + UE->max_pos_fil = 0; // reset IIR filter when sample shift is applied return 1; } @@ -611,31 +498,51 @@ void *UE_thread(void *arg) { //this thread should be over the processing thread to keep in real time PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; // int tx_enabled = 0; - openair0_timestamp timestamp; + openair0_timestamp timestamp, writeTimestamp; void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX]; int start_rx_stream = 0; AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), ""); UE->rfdevice.host_type = RAU_HOST; + UE->lost_sync = 0; + UE->is_synchronized = 0; AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); + notifiedFIFO_t nf; initNotifiedFIFO(&nf); - int nbSlotProcessing=0; - int thread_idx=0; + notifiedFIFO_t freeBlocks; initNotifiedFIFO_nothreadSafe(&freeBlocks); - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - for (int i=0; itiming_advance; bool syncRunning=false; const int nb_slot_frame = UE->frame_parms.slots_per_frame; int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0; + for (int i=0; itxFifo); + pushNotifiedFIFO_nothreadSafe(&freeBlocks, newElt); + } + while (!oai_exit) { + if (UE->lost_sync) { + int nb = abortTpool(&(get_nrUE_params()->Tpool),RX_JOB_ID); + nb += abortNotifiedFIFO(&nf, RX_JOB_ID); + LOG_I(PHY,"Number of aborted slots %d\n",nb); + for (int i=0; iis_synchronized = 0; + UE->lost_sync = 0; + } + if (syncRunning) { - notifiedFIFO_elt_t *res=tryPullTpool(&nf, Tpool); + notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool)); if (res) { syncRunning=false; @@ -643,9 +550,10 @@ void *UE_thread(void *arg) { if (UE->is_synchronized) { decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx); // shift the frame index with all the frames we trashed meanwhile we perform the synch search - decoded_frame_rx=(decoded_frame_rx + (!UE->init_sync_frame) + trashed_frames) % MAX_FRAME_NUMBER; + decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER; } delNotifiedFIFO_elt(res); + start_rx_stream=0; } else { readFrame(UE, ×tamp, true); trashed_frames+=2; @@ -661,7 +569,7 @@ void *UE_thread(void *arg) { syncData_t *syncMsg=(syncData_t *)NotifiedFifoData(Msg); syncMsg->UE=UE; memset(&syncMsg->proc, 0, sizeof(syncMsg->proc)); - pushTpool(Tpool, Msg); + pushTpool(&(get_nrUE_params()->Tpool), Msg); trashed_frames=0; syncRunning=true; continue; @@ -692,23 +600,21 @@ void *UE_thread(void *arg) { // whatever means thread_idx // Fix me: will be wrong when slot 1 is slow, as slot 2 finishes - // Slot 3 will overlap if RX_NB_TH is 2 + // Slot 3 will overlap if NR_RX_NB_TH is 2 // this is general failure in UE !!! - thread_idx = absolute_slot % RX_NB_TH; + thread_idx = absolute_slot % NR_RX_NB_TH; int slot_nr = absolute_slot % nb_slot_frame; notifiedFIFO_elt_t *msgToPush; AssertFatal((msgToPush=pullNotifiedFIFO_nothreadSafe(&freeBlocks)) != NULL,"chained list failure"); - processingData_t *curMsg=(processingData_t *)NotifiedFifoData(msgToPush); + nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(msgToPush); curMsg->UE=UE; // update thread index for received subframe - curMsg->UE->current_thread_id[slot_nr] = thread_idx; - curMsg->proc.CC_id = UE->CC_id; - curMsg->proc.nr_tti_rx= slot_nr; - curMsg->proc.subframe_rx=slot_nr/(nb_slot_frame/10); - curMsg->proc.nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame; - curMsg->proc.subframe_tx=curMsg->proc.nr_tti_rx; - curMsg->proc.frame_rx = (absolute_slot/nb_slot_frame) % MAX_FRAME_NUMBER; - curMsg->proc.frame_tx = ((absolute_slot+DURATION_RX_TO_TX)/nb_slot_frame) % MAX_FRAME_NUMBER; + curMsg->proc.thread_id = thread_idx; + curMsg->proc.CC_id = UE->CC_id; + curMsg->proc.nr_slot_rx = slot_nr; + curMsg->proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame; + curMsg->proc.frame_rx = (absolute_slot/nb_slot_frame) % MAX_FRAME_NUMBER; + curMsg->proc.frame_tx = ((absolute_slot+DURATION_RX_TO_TX)/nb_slot_frame) % MAX_FRAME_NUMBER; curMsg->proc.decoded_frame_rx=-1; //LOG_I(PHY,"Process slot %d thread Idx %d total gain %d\n", slot_nr, thread_idx, UE->rx_total_gain_dB); @@ -728,19 +634,18 @@ void *UE_thread(void *arg) { for (int i=0; iframe_parms.nb_antennas_tx; i++) txp[i] = (void *)&UE->common_vars.txdata[i][UE->frame_parms.get_samples_slot_timestamp( - ((curMsg->proc.nr_tti_rx + DURATION_RX_TO_TX -2)%nb_slot_frame),&UE->frame_parms,0)]; + ((slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH)%nb_slot_frame),&UE->frame_parms,0)]; int readBlockSize, writeBlockSize; if (slot_nr<(nb_slot_frame - 1)) { readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms); - writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms); + writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH) % nb_slot_frame, &UE->frame_parms); } else { UE->rx_offset_diff = computeSamplesShift(UE); readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) - UE->rx_offset_diff; - writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms) - - UE->rx_offset_diff; + writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff; } AssertFatal(readBlockSize == @@ -750,78 +655,102 @@ void *UE_thread(void *arg) { readBlockSize, UE->frame_parms.nb_antennas_rx),""); - AssertFatal( writeBlockSize == - UE->rfdevice.trx_write_func(&UE->rfdevice, - timestamp+ - UE->frame_parms.get_samples_slot_timestamp(slot_nr, - &UE->frame_parms,DURATION_RX_TO_TX -2) - firstSymSamp - - openair0_cfg[0].tx_sample_advance, - txp, - writeBlockSize, - UE->frame_parms.nb_antennas_tx, - 1),""); - if( slot_nr==(nb_slot_frame-1)) { // read in first symbol of next frame and adjust for timing drift int first_symbols=UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0; // first symbol of every frames - if ( first_symbols > 0 ) + if ( first_symbols > 0 ) { + openair0_timestamp ignore_timestamp; AssertFatal(first_symbols == UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, + &ignore_timestamp, (void **)UE->common_vars.rxdata, first_symbols, UE->frame_parms.nb_antennas_rx),""); - else + } else LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols); } curMsg->proc.timestamp_tx = timestamp+ - UE->frame_parms.get_samples_slot_timestamp(slot_nr, - &UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp; + UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,DURATION_RX_TO_TX) + - firstSymSamp; notifiedFIFO_elt_t *res; - while (nbSlotProcessing >= RX_NB_TH) { - if ( (res=tryPullTpool(&nf, Tpool)) != NULL ) { - nbSlotProcessing--; - processingData_t *tmp=(processingData_t *)res->msgData; - - if (tmp->proc.decoded_frame_rx != -1) - decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx); - //decoded_frame_rx=tmp->proc.decoded_frame_rx; - - pushNotifiedFIFO_nothreadSafe(&freeBlocks,res); - } - - usleep(200); - } - - if ( (decoded_frame_rx != curMsg->proc.frame_rx) && - (((decoded_frame_rx+1) % MAX_FRAME_NUMBER) != curMsg->proc.frame_rx) && - (((decoded_frame_rx+2) % MAX_FRAME_NUMBER) != curMsg->proc.frame_rx)) - LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n", - decoded_frame_rx, curMsg->proc.frame_rx ); - - nbSlotProcessing++; - msgToPush->key=slot_nr; - pushTpool(Tpool, msgToPush); - - if (IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) { //getenv("RFSIMULATOR") - // FixMe: Wait previous thread is done, because race conditions seems too bad - // in case of actual RF board, the overlap between threads mitigate the issue - // We must receive one message, that proves the slot processing is done - res=pullTpool(&nf, Tpool); + while (nbSlotProcessing >= NR_RX_NB_TH) { + res=pullTpool(&nf, &(get_nrUE_params()->Tpool)); nbSlotProcessing--; - processingData_t *tmp=(processingData_t *)res->msgData; + nr_rxtx_thread_data_t *tmp=(nr_rxtx_thread_data_t *)res->msgData; if (tmp->proc.decoded_frame_rx != -1) decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx); - //decoded_frame_rx=tmp->proc.decoded_frame_rx; + else + decoded_frame_rx=-1; pushNotifiedFIFO_nothreadSafe(&freeBlocks,res); } + if (decoded_frame_rx>0 && decoded_frame_rx != curMsg->proc.frame_rx) + LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n", + decoded_frame_rx, curMsg->proc.frame_rx); + + // use previous timing_advance value to compute writeTimestamp + writeTimestamp = timestamp+ + UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,DURATION_RX_TO_TX + - NR_RX_NB_TH) - firstSymSamp - openair0_cfg[0].tx_sample_advance - + UE->N_TA_offset - timing_advance; + + // but use current UE->timing_advance value to compute writeBlockSize + if (UE->timing_advance != timing_advance) { + writeBlockSize -= UE->timing_advance - timing_advance; + timing_advance = UE->timing_advance; + } + + int flags = 0; + int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH; + + if (openair0_cfg[0].duplex_mode == duplex_mode_TDD) { + + uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots; + int nrofUplinkSlots, nrofUplinkSymbols; + if (mac->scc) { + nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + nrofUplinkSymbols = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; + } + else { + nrofUplinkSlots = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + nrofUplinkSymbols = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; + } + uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSymbols != 0); + + uint8_t first_tx_slot = tdd_period - num_UL_slots; + + if (slot_tx_usrp % tdd_period == first_tx_slot) + flags = 2; + else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1) + flags = 3; + else if (slot_tx_usrp % tdd_period > first_tx_slot) + flags = 1; + } else { + flags = 1; + } + + if (flags || IS_SOFTMODEM_RFSIM) + AssertFatal(writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + writeTimestamp, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + flags),""); + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + memset(txp[i], 0, writeBlockSize); + + nbSlotProcessing++; + LOG_D(PHY,"Number of slots being processed at the moment: %d\n",nbSlotProcessing); + pushTpool(&(get_nrUE_params()->Tpool), msgToPush); + } // while !oai_exit return NULL; @@ -849,19 +778,13 @@ void init_NR_UE_threads(int nb_inst) { LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]); threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX); - -#ifdef UE_DLSCH_PARALLELISATION - pthread_t dlsch0_threads; - threadCreate(&dlsch0_threads, dlsch_thread, (void *)UE, "DLthread", -1, OAI_PRIORITY_RT_MAX-1); -#endif - } } /* HACK: this function is needed to compile the UE * fix it somehow */ -int8_t find_dlsch(uint16_t rnti, +int find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB, find_type_t type) { diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 2fbea2bbfb..5431fc1331 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -33,16 +33,18 @@ //#include "common/utils/threadPool/thread-pool.h" #include "common/utils/load_module_shlib.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all +#include "common/utils/nr/nr_common.h" #include "../../ARCH/COMMON/common_lib.h" #include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all - +#include "openair1/PHY/MODULATION/nr_modulation.h" #include "PHY/phy_vars_nr_ue.h" -#include "PHY/LTE_TRANSPORT/transport_vars.h" +#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "SCHED/sched_common_vars.h" #include "PHY/MODULATION/modulation_vars.h" +#include "PHY/NR_TRANSPORT/nr_dlsch.h" //#include "../../SIMU/USER/init_lte.h" #include "LAYER2/MAC/mac_vars.h" @@ -61,10 +63,6 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "enb_config.h" //#include "PHY/TOOLS/time_meas.h" -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_vars.h" -#endif - #include "intertask_interface.h" #include "PHY/INIT/phy_init.h" @@ -85,7 +83,13 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "executables/softmodem-common.h" #include "executables/thread-common.h" -// Raphael : missing +#include "nr_nas_msg_sim.h" + +extern const char *duplex_mode[]; +THREAD_STRUCT thread_struct; +nrUE_params_t nrUE_params; + +// Thread variables pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex @@ -95,29 +99,27 @@ pthread_mutex_t sync_mutex; int sync_var=-1; //!< protected by mutex \ref sync_mutex. int config_sync_var=-1; + + RAN_CONTEXT_t RC; -volatile int start_eNB = 0; -volatile int start_UE = 0; volatile int oai_exit = 0; -int single_thread_flag=1; -static double snr_dB=20; -int threequarter_fs=0; +extern int16_t nr_dlsch_demod_shift; +static int tx_max_power[MAX_NUM_CCs] = {0}; -uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; -//int32_t uplink_counter = 0; +int single_thread_flag = 1; +int tddflag = 0; +int vcdflag = 0; +double rx_gain_off = 0.0; +char *usrp_args = NULL; +char *rrc_config_path = NULL; +int dumpframe = 0; -extern int16_t nr_dlsch_demod_shift; - -int UE_scan = 0; -int UE_scan_carrier = 0; -int UE_fo_compensation = 0; -int UE_no_timing_correction = 0; -runmode_t mode = normal_txrx; -openair0_config_t openair0_cfg[MAX_CARDS]; +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int rx_input_level_dBm; #if MAX_NUM_CCs == 1 rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}}; @@ -129,73 +131,24 @@ double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}}; double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; #endif -double rx_gain_off = 0.0; +// UE and OAI config variables -double sample_rate=30.72e6; -double bw = 10.0e6; - -static int tx_max_power[MAX_NUM_CCs] = {0}; +openair0_config_t openair0_cfg[MAX_CARDS]; +int16_t node_synch_ref[MAX_NUM_CCs]; +int otg_enabled; +double cpuf; -int chain_offset=0; - - -uint8_t dci_Format = 0; -uint8_t agregation_Level =0xFF; - -uint8_t nb_antenna_tx = 1; -uint8_t nb_antenna_rx = 1; - -char ref[128] = "internal"; -char channels[128] = "0"; - - -int rx_input_level_dBm; - -//static int online_log_messages=0; - - -int otg_enabled; -//int number_of_cards = 1; - -static NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; -int16_t node_synch_ref[MAX_NUM_CCs]; - -uint32_t target_dl_mcs = 28; //maximum allowed mcs -uint32_t target_ul_mcs = 20; -uint32_t timing_advance = 0; -uint64_t num_missed_slots=0; // counter for the number of missed slots - - -int transmission_mode=1; -int numerology = 0; -int usrp_tx_thread = 0; - -/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */ -//uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD; -/* struct for ethernet specific parameters given in eNB conf file */ -//eth_params_t *eth_params; - -double cpuf; - -char uecap_xer[1024],uecap_xer_in=0; - -int oaisim_flag=0; -int emulate_rf = 0; - -tpool_t *Tpool; -#ifdef UE_DLSCH_PARALLELISATION - tpool_t *Tpool_dl; -#endif - - -char *usrp_args=NULL; - -char *rrc_config_path=NULL; - -/* forward declarations */ -void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); - +int chain_offset = 0; +int card_offset = 0; +uint64_t num_missed_slots = 0; // counter for the number of missed slots +int transmission_mode = 1; +int numerology = 0; +int oaisim_flag = 0; +int emulate_rf = 0; +uint32_t N_RB_DL = 106; +char uecap_xer_in = 0; +char uecap_xer[1024]; /* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed * this is very hackish - find a proper solution @@ -225,6 +178,26 @@ void print_difftimes(void) { LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); } +int create_tasks_nrue(uint32_t ue_nb) { + LOG_D(NR_RRC, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb); + itti_wait_ready(1); + + if (ue_nb > 0) { + LOG_I(NR_RRC,"create TASK_RRC_NRUE \n"); + if (itti_create_task (TASK_RRC_NRUE, rrc_nrue_task, NULL) < 0) { + LOG_E(NR_RRC, "Create task for RRC UE failed\n"); + return -1; + } + if (itti_create_task (TASK_NAS_NRUE, nas_nrue_task, NULL) < 0) { + LOG_E(NR_RRC, "Create task for NAS UE failed\n"); + return -1; + } + } + + itti_wait_ready(0); + return 0; +} + void exit_function(const char *file, const char *function, const int line, const char *s) { int CC_id; @@ -245,160 +218,42 @@ void exit_function(const char *file, const char *function, const int line, const exit(1); } - -void reset_stats(long arg) { - //int i,j,k; - /*PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0]; - - for (i=0; idlsch[i][0]->Mlimit; j++) { - phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0; - phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0; - phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0; - } - - phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0; - phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0; - phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0; - - for (j=0; julsch[i]->Mlimit; j++) { - phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0; - phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; - phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0; - phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0; - } - } - - phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0; - phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0; - phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0; - }*/ +uint64_t get_nrUE_optmask(void) { + return nrUE_params.optmask; } -void *l2l1_task(void *arg) { - MessageDef *message_p = NULL; - int result; - itti_set_task_real_time(TASK_L2L1); - itti_mark_task_ready(TASK_L2L1); - - do { - // Wait for a message - itti_receive_msg (TASK_L2L1, &message_p); - - switch (ITTI_MSG_ID(message_p)) { - case TERMINATE_MESSAGE: - oai_exit=1; - itti_exit_task (); - break; - - case ACTIVATE_MESSAGE: - start_UE = 1; - break; - - case DEACTIVATE_MESSAGE: - start_UE = 0; - break; - - case MESSAGE_TEST: - LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); - break; - - default: - LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); - break; - } - - result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); - AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - } while(!oai_exit); - - return NULL; +uint64_t set_nrUE_optmask(uint64_t bitmask) { + nrUE_params.optmask = nrUE_params.optmask | bitmask; + return nrUE_params.optmask; } - -int16_t dlsch_demod_shift; +nrUE_params_t *get_nrUE_params(void) { + return &nrUE_params; +} +/* initialie thread pools used for NRUE processing paralleliation */ +void init_tpools(uint8_t nun_dlsch_threads) { + char *params = NULL; + params = calloc(1,(NR_RX_NB_TH*NR_NB_TH_SLOT*3)+1); + for (int i=0; i 0) mode = debug_prach; - - if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) - if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0) mode = no_L2_connect; - - if (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) - if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx; - - if (dumpframe > 0) mode = rx_dump_frame; - - for (CC_id=0; CC_iddl_CarrierFreq = downlink_frequency[0][0]; - } - - UE_scan=0; - - if (tddflag > 0) { - for (CC_id=0; CC_idframe_type = TDD; - } if (vcdflag > 0) ouput_vcd = 1; - /*if (frame_parms[0]->N_RB_DL !=0) { - if ( frame_parms[0]->N_RB_DL < 6 ) { - frame_parms[0]->N_RB_DL = 6; - printf ( "%i: Invalid number of resource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL); - } - if ( frame_parms[0]->N_RB_DL > 100 ) { - frame_parms[0]->N_RB_DL = 100; - printf ( "%i: Invalid number of resource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL); - } - if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) { - frame_parms[0]->N_RB_DL = 50; - printf ( "%i: Invalid number of resource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL); - } - if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) { - frame_parms[0]->N_RB_DL = 25; - printf ( "%i: Invalid number of resource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL); - } - UE_scan = 0; - frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL; - for (CC_id=1; CC_idN_RB_DL=frame_parms[0]->N_RB_DL; - frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL; - } - }*/ - - for (CC_id=1; CC_idframe_parms; + paramdef_t cmdline_params[] = CMDLINE_NRUE_PHYPARAMS_DESC ; + int numparams = sizeof(cmdline_params)/sizeof(paramdef_t); -void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { - int CC_id; + UE->mode = normal_txrx; - for (CC_id=0; CC_idnr_band = 78; - frame_parms[CC_id]->frame_type = FDD; - frame_parms[CC_id]->tdd_config = 3; - //frame_parms[CC_id]->tdd_config_S = 0; - frame_parms[CC_id]->N_RB_DL = 106; - frame_parms[CC_id]->N_RB_UL = 106; - frame_parms[CC_id]->Ncp = NORMAL; - //frame_parms[CC_id]->Ncp_UL = NORMAL; - frame_parms[CC_id]->Nid_cell = 0; - //frame_parms[CC_id]->num_MBSFN_config = 0; - frame_parms[CC_id]->nb_antenna_ports_gNB = 1; - frame_parms[CC_id]->nb_antennas_tx = 1; - frame_parms[CC_id]->nb_antennas_rx = 1; - //frame_parms[CC_id]->nushift = 0; - // NR: Init to legacy LTE 20Mhz params - frame_parms[CC_id]->numerology_index = 0; - frame_parms[CC_id]->ttis_per_subframe = 1; - frame_parms[CC_id]->slots_per_tti = 2; + config_get(cmdline_params,numparams,NULL); + + int pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRX_OPT); + if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue; + + pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRXMED_OPT); + if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue_med; + + pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRXBYP_OPT); + if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue_byp; + + pindex = config_paramidx_fromname(cmdline_params,numparams, DBGPRACH_OPT); + if (cmdline_params[pindex].uptr) + if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = debug_prach; + + pindex = config_paramidx_fromname(cmdline_params,numparams,NOL2CONNECT_OPT ); + if (cmdline_params[pindex].uptr) + if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = no_L2_connect; + + pindex = config_paramidx_fromname(cmdline_params,numparams,CALIBPRACH_OPT ); + if (cmdline_params[pindex].uptr) + if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = calib_prach_tx; + + pindex = config_paramidx_fromname(cmdline_params,numparams,DUMPFRAME_OPT ); + if ((cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) + UE->mode = rx_dump_frame; + + // Init power variables + tx_max_power[CC_id] = tx_max_power[0]; + rx_gain[0][CC_id] = rx_gain[0][0]; + tx_gain[0][CC_id] = tx_gain[0][0]; + + // Set UE variables + UE->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; + UE->tx_total_gain_dB = (int)tx_gain[CC_id][0]; + UE->tx_power_max_dBm = tx_max_power[CC_id]; + UE->rf_map.card = card_offset; + UE->rf_map.chain = CC_id + chain_offset; + + LOG_I(PHY,"Set UE mode %d, UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, do_prb_interpolation %d\n", + UE->mode, UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->prb_interpolation); + + // Set FP variables + + if (tddflag){ + fp->frame_type = TDD; + LOG_I(PHY, "Set UE frame_type %d\n", fp->frame_type); } + + LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ssb_start_subcarrier %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ssb_start_subcarrier); + + fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor; + } void init_openair0(void) { int card; - int i; + int freq_off = 0; + NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms; for (card=0; cardthreequarter_fs; - numerology = frame_parms[0]->numerology_index; + uint64_t dl_carrier, ul_carrier; + openair0_cfg[card].configFilename = NULL; + openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs; + openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3; + openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame; - if(frame_parms[0]->N_RB_DL == 66) { - if (numerology==3) { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } else { - LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n"); - exit(-1); - } - }else if(frame_parms[0]->N_RB_DL == 32) { - if (numerology==3) { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } else { - LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n"); - exit(-1); - } - }else if(frame_parms[0]->N_RB_DL == 217) { - if (numerology==1) { - if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=92.16e6; - openair0_cfg[card].samples_per_frame = 921600; - } - else { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms[0]->N_RB_DL == 273) { - if (numerology==1) { - if (frame_parms[0]->threequarter_fs) { - AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); - } - else { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms[0]->N_RB_DL == 106) { - if (numerology==0) { - if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=23.04e6; - openair0_cfg[card].samples_per_frame = 230400; - } else { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - } - } else if (numerology==1) { - if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=46.08e6; - openair0_cfg[card].samples_per_frame = 460800; - } - else { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } - } else if (numerology==2) { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms[0]->N_RB_DL == 50) { - openair0_cfg[card].sample_rate=15.36e6; - openair0_cfg[card].samples_per_frame = 153600; - } else if (frame_parms[0]->N_RB_DL == 25) { - openair0_cfg[card].sample_rate=7.68e6; - openair0_cfg[card].samples_per_frame = 76800; - } else if (frame_parms[0]->N_RB_DL == 6) { - openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_frame = 19200; - } - else { - LOG_E(PHY,"Unknown NB_RB %d!\n",frame_parms[0]->N_RB_DL); - exit(-1); - } - - if (frame_parms[0]->frame_type==TDD) + if (frame_parms->frame_type==TDD) openair0_cfg[card].duplex_mode = duplex_mode_TDD; - else //FDD + else openair0_cfg[card].duplex_mode = duplex_mode_FDD; - printf("HW: Configuring card %d, nb_antennas_tx/rx %hhu/%hhu\n",card, - PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx, - PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); openair0_cfg[card].Mod_id = 0; - openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; + openair0_cfg[card].num_rb_dl = frame_parms->N_RB_DL; openair0_cfg[card].clock_source = get_softmodem_params()->clock_source; openair0_cfg[card].time_source = get_softmodem_params()->timing_source; - openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx); - openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); + openair0_cfg[card].tx_num_channels = min(4, frame_parms->nb_antennas_tx); + openair0_cfg[card].rx_num_channels = min(4, frame_parms->nb_antennas_rx); - for (i=0; i<4; i++) { - if (iul_CarrierFreq; - else - openair0_cfg[card].tx_freq[i]=0.0; + LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n", + card, + openair0_cfg[card].sample_rate, + openair0_cfg[card].tx_num_channels, + openair0_cfg[card].rx_num_channels, + duplex_mode[openair0_cfg[card].duplex_mode]); - if (idl_CarrierFreq; - else - openair0_cfg[card].rx_freq[i]=0.0; + nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier); - openair0_cfg[card].autocal[i] = 1; - openair0_cfg[card].tx_gain[i] = tx_gain[0][i]; - openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off; - openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; - printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n", - card,i, openair0_cfg[card].tx_gain[i], - openair0_cfg[card].rx_gain[i], - openair0_cfg[card].tx_freq[i], - openair0_cfg[card].rx_freq[i]); - } + nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off); + nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off); + + openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args; @@ -584,11 +383,11 @@ void init_pdcp(void) { LOG_I(RLC, "Problem at RLC initiation \n"); } pdcp_layer_init(); - nr_ip_over_LTE_DRB_preconfiguration();*/ + nr_DRB_preconfiguration();*/ + pdcp_layer_init(); pdcp_module_init(pdcp_initmask); pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); - LOG_I(PDCP, "Before getting out from init_pdcp() \n"); } // Stupid function addition because UE itti messages queues definition is common with eNB @@ -607,35 +406,28 @@ int main( int argc, char **argv ) { } set_softmodem_sighandler(); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); - set_default_frame_parms(frame_parms); - mode = normal_txrx; memset(openair0_cfg,0,sizeof(openair0_config_t)*MAX_CARDS); memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); // initialize logging logInit(); // get options and fill parameters from configuration file - get_options (); //Command-line options, enb_properties - get_common_options(SOFTMODEM_5GUE_BIT ); + + get_options (); //Command-line options specific for NRUE + + get_common_options(SOFTMODEM_5GUE_BIT); + init_tpools(nrUE_params.nr_dlsch_parallel); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); #if T_TRACER T_Config_Init(); #endif //randominit (0); set_taus_seed (0); - tpool_t pool; - Tpool = &pool; - char params[]="-1,-1"; - initTpool(params, Tpool, false); -#ifdef UE_DLSCH_PARALLELISATION - tpool_t pool_dl; - Tpool_dl = &pool_dl; - char params_dl[]="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"; - initTpool(params_dl, Tpool_dl, false); -#endif + cpuf=get_cpu_freq_GHz(); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + itti_init(TASK_MAX, tasks_info); init_opt() ; - load_nrLDPClib(); + load_nrLDPClib(NULL); if (ouput_vcd) { vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd"); @@ -647,16 +439,8 @@ int main( int argc, char **argv ) { LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); init_NR_UE(1,rrc_config_path); - if(IS_SOFTMODEM_NOS1) + if(IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa) init_pdcp(); -/* -#ifdef PDCP_USE_NETLINK - netlink_init(); -#if defined(PDCP_USE_NETLINK_QUEUES) - pdcp_netlink_init(); -#endif -#endif -*/ NB_UE_INST=1; NB_INST=1; @@ -666,91 +450,42 @@ int main( int argc, char **argv ) { if (get_softmodem_params()->do_ra) AssertFatal(get_softmodem_params()->phy_test == 0,"RA and phy_test are mutually exclusive\n"); + if (get_softmodem_params()->sa) + AssertFatal(get_softmodem_params()->phy_test == 0,"Standalone mode and phy_test are mutually exclusive\n"); + for (int CC_id=0; CC_idofdm_symbol_size); - frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx; - frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx; - frame_parms[CC_id]->nb_antenna_ports_gNB = 1; //initial value overwritten by initial sync later - frame_parms[CC_id]->threequarter_fs = threequarter_fs; - LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx); PHY_vars_UE_g[0][CC_id] = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE)); - UE[CC_id] = PHY_vars_UE_g[0][CC_id]; memset(UE[CC_id],0,sizeof(PHY_VARS_NR_UE)); + set_options(CC_id, UE[CC_id]); NR_UE_MAC_INST_t *mac = get_mac_inst(0); - if(mac->if_module != NULL && mac->if_module->phy_config_request != NULL) - mac->if_module->phy_config_request(&mac->phy_config); - fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; - nr_init_frame_parms_ue(frame_parms[CC_id],nrUE_config,NORMAL); - - // Overwrite DL frequency (for FR2 testing) - if (downlink_frequency[0][0]!=0) - frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0]; - - init_nr_ue_vars(UE[CC_id],frame_parms[CC_id],0,abstraction_flag); - - UE[CC_id]->mac_enabled = 1; - UE[CC_id]->if_inst = nr_ue_if_module_init(0); - UE[CC_id]->UE_scan = UE_scan; - UE[CC_id]->UE_scan_carrier = UE_scan_carrier; - UE[CC_id]->UE_fo_compensation = UE_fo_compensation; - UE[CC_id]->mode = mode; - UE[CC_id]->no_timing_correction = UE_no_timing_correction; - printf("UE[%d]->mode = %d\n",CC_id,mode); - - UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; - UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; - - if (UE[CC_id]->frame_parms.frame_type == FDD) { - UE[CC_id]->N_TA_offset = 0; - } else { - int N_RB = UE[CC_id]->frame_parms.N_RB_DL; - int N_TA_offset = UE[CC_id]->frame_parms.ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 - double factor=1; - switch (UE[CC_id]->frame_parms.numerology_index) { - case 0: //15 kHz scs - AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); - if (N_RB <= 25) factor = .25; // 7.68 Ms/s - else if (N_RB <=50) factor = .5; // 15.36 Ms/s - else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s - else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s - else AssertFatal(1==0,"Too many PRBS for mu=0\n"); - break; - case 1: //30 kHz sc - AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); - if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s - else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s - break; - case 2: //60 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - break; - case 3: //120 kHz scs - AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); - break; - case 4: //240 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s - else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s - else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); - break; - - if (N_RB == 100) - UE[CC_id]->N_TA_offset = 624; - else if (N_RB == 50) - UE[CC_id]->N_TA_offset = 624/2; - else if (N_RB == 25) - UE[CC_id]->N_TA_offset = 624/4; - } - if (UE[CC_id]->frame_parms.threequarter_fs == 1) factor = factor*.75; - UE[CC_id]->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d)\n", UE[CC_id]->Mod_id, UE[CC_id]->N_TA_offset, factor, UE[CC_id]->frame_parms.ul_CarrierFreq, N_RB); + if (get_softmodem_params()->sa) { + uint16_t nr_band = get_band(downlink_frequency[CC_id][0],uplink_frequency_offset[CC_id][0]); + mac->nr_band = nr_band; + nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms, + downlink_frequency[CC_id][0], + uplink_frequency_offset[CC_id][0], + get_softmodem_params()->numerology, + nr_band); } + else{ + if(mac->if_module != NULL && mac->if_module->phy_config_request != NULL) + mac->if_module->phy_config_request(&mac->phy_config); + + fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; + + nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); + } + + init_symbol_rotation(&UE[CC_id]->frame_parms); + init_timeshift_rotation(&UE[CC_id]->frame_parms); + init_nr_ue_vars(UE[CC_id], 0, abstraction_flag); + } - // printf("tx_max_power = %d -> amp %d\n",tx_max_power[0],get_tx_amp(tx_max_poHwer,tx_max_power)); init_openair0(); // init UE_PF_PO and mutex lock pthread_mutex_init(&ue_pf_po_mutex, NULL); @@ -758,29 +493,27 @@ int main( int argc, char **argv ) { configure_linux(); mlockall(MCL_CURRENT | MCL_FUTURE); - if(IS_SOFTMODEM_DOFORMS) { + if(IS_SOFTMODEM_DOSCOPE) { load_softscope("nr",PHY_vars_UE_g[0][0]); } - number_of_cards = 1; - - for(int CC_id=0; CC_idrf_map.card=0; - PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; -#if defined(OAI_USRP) || defined(OAI_ADRV9371_ZC706) - PHY_vars_UE_g[0][CC_id]->hw_timing_advance = timing_advance; - PHY_vars_UE_g[0][CC_id]->timing_advance = timing_advance; -#else - PHY_vars_UE_g[0][CC_id]->hw_timing_advance = 160; -#endif - - } + init_NR_UE_threads(1); printf("UE threads created by %ld\n", gettid()); // wait for end of program printf("TYPE TO TERMINATE\n"); + if (create_tasks_nrue(1) < 0) { + printf("cannot create ITTI tasks\n"); + exit(-1); // need a softer mode + } + + // Sleep a while before checking all parameters have been used + // Some are used directly in external threads, asynchronously + sleep(20); + config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); + while(true) sleep(3600); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 418ed54fc6..7f47ed5eb3 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -5,77 +5,80 @@ #include "PHY/defs_nr_UE.h" #include "SIMULATION/ETH_TRANSPORT/proto.h" + + +#define CONFIG_HLP_IF_FREQ "IF frequency for RF, if needed" +#define CONFIG_HLP_IF_FREQ_OFF "UL IF frequency offset for RF, if needed" +#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n" +#define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument when calling config_get or config_getlist functions */ +#define CALIBRX_OPT "calib-ue-rx" +#define CALIBRXMED_OPT "calib-ue-rx-med" +#define CALIBRXBYP_OPT "calib-ue-rx-byp" +#define DBGPRACH_OPT "debug-ue-prach" +#define NOL2CONNECT_OPT "no-L2-connect" +#define CALIBPRACH_OPT "calib-prach-tx" +#define DUMPFRAME_OPT "ue-dump-frame" + +/*------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters defining UE running mode */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_NRUEPARAMS_DESC { \ + {"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:(char **)&usrp_args, defstrval:"type=b200", TYPE_STRING, 0}, \ + {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ + {"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, iptr:(int32_t *)&nrUE_params.nr_dlsch_parallel, defintval:0, TYPE_UINT8, 0}, \ + {"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, uptr:(uint32_t *)&nrUE_params.ofdm_offset_divisor, defuintval:UINT_MAX, TYPE_UINT32, 0}, \ + {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ + {"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, iptr:&vcdflag, defintval:0, TYPE_INT, 0}, \ + {"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH,0, strptr:(char **)&rrc_config_path, defstrval:"./", TYPE_STRING, 0} \ +} + /*------------------------------------------------------------------------------------------------------------------------------------------*/ /* command line parameters defining UE running mode */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CMDLINE_UEMODEPARAMS_DESC { \ - {"calib-ue-rx", CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"calib-ue-rx-med", CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"calib-ue-rx-byp", CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"debug-ue-prach", CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"no-L2-connect", CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"calib-prach-tx", CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"loop-memory", CONFIG_HLP_UELOOP, 0, strptr:&loopfile, defstrval:"iqs.in", TYPE_STRING,0}, \ - {"ue-dump-frame", CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \ - } -#define CMDLINE_CALIBUERX_IDX 0 -#define CMDLINE_CALIBUERXMED_IDX 1 -#define CMDLINE_CALIBUERXBYP_IDX 2 -#define CMDLINE_DEBUGUEPRACH_IDX 3 -#define CMDLINE_NOL2CONNECT_IDX 4 -#define CMDLINE_CALIBPRACHTX_IDX 5 -#define CMDLINE_MEMLOOP_IDX 6 -#define CMDLINE_DUMPMEMORY_IDX 7 -/*------------------------------------------------------------------------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* command line parameters specific to UE */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CMDLINE_NRUEPARAMS_DESC { \ - {"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ - {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \ - {"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ - {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&nb_antenna_rx, defuintval:1, TYPE_UINT8, 0}, \ - {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&nb_antenna_tx, defuintval:1, TYPE_UINT8, 0}, \ - {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&UE_scan_carrier, defintval:0, TYPE_INT, 0}, \ - {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&UE_fo_compensation, defintval:0, TYPE_INT, 0}, \ - {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ - {"r" , CONFIG_HLP_PRB, 0, iptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT, 0}, \ - {"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ - {"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:(char **)&usrp_args, defstrval:"type=b200", TYPE_STRING, 0} \ - } - -/*----------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* command line parameters common to eNodeB and UE */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*----------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CMDLINE_PARAMS_DESC_UE { \ - {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ - {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ - {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ - {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0}, \ - {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ - {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ - {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ - {"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, iptr:&vcdflag, defintval:0, TYPE_INT, 0}, \ - {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ - {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0}, \ - {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&UE_no_timing_correction, defintval:0, TYPE_INT, 0}, \ - {"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH,0, strptr:(char **)&rrc_config_path, defstrval:"./", TYPE_STRING, 0} \ +#define CMDLINE_NRUE_PHYPARAMS_DESC { \ + { CALIBRX_OPT, CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + { CALIBRXMED_OPT, CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + { CALIBRXBYP_OPT, CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + { DBGPRACH_OPT, CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + { NOL2CONNECT_OPT, CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + { CALIBPRACH_OPT, CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + { DUMPFRAME_OPT, CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \ + {"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:110, TYPE_DOUBLE,0}, \ + {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE,0}, \ + {"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE,0}, \ + {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&(fp->nb_antennas_rx), defuintval:1, TYPE_UINT8, 0}, \ + {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&(fp->nb_antennas_tx), defuintval:1, TYPE_UINT8, 0}, \ + {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&(UE->UE_scan_carrier), defintval:0, TYPE_INT, 0}, \ + {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&(UE->UE_fo_compensation), defintval:0, TYPE_INT, 0}, \ + {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ + {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ + {"r" , CONFIG_HLP_PRB_SA, 0, iptr:&(fp->N_RB_DL), defintval:106, TYPE_UINT, 0}, \ + {"s" , CONFIG_HLP_SSC, 0, u16ptr:&(fp->ssb_start_subcarrier), defintval:516, TYPE_UINT16,0}, \ + {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ + {"if_freq" , CONFIG_HLP_IF_FREQ, 0, u64ptr:&(UE->if_freq), defuintval:0, TYPE_UINT64,0}, \ + {"if_freq_off" , CONFIG_HLP_IF_FREQ_OFF, 0, iptr:&(UE->if_freq_off), defuintval:0, TYPE_INT, 0}, \ + {"do-prb-interpolation", CONFIG_HLP_PRBINTER, PARAMFLAG_BOOL, iptr:&(UE->prb_interpolation), defintval:0, TYPE_INT, 0}, \ + {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ } -extern int T_port; -extern int T_nowait; -extern int T_dont_fork; +typedef struct { + uint64_t optmask; //mask to store boolean config options + uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol + uint8_t nr_dlsch_parallel; // number of threads for dlsch decoding, 0 means no parallelization + tpool_t Tpool; // thread pool +} nrUE_params_t; +extern uint64_t get_nrUE_optmask(void); +extern uint64_t set_nrUE_optmask(uint64_t bitmask); +extern nrUE_params_t *get_nrUE_params(void); // In nr-ue.c @@ -86,7 +89,6 @@ extern void init_NR_UE_threads(int); extern void reset_opp_meas(void); extern void print_opp_meas(void); void *UE_thread(void *arg); -void init_nr_ue_vars(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag); -extern tpool_t *Tpool; -extern tpool_t *Tpool_dl; +void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id, uint8_t abstraction_flag); + #endif diff --git a/executables/ocp-gnb.c b/executables/ocp-gnb.c new file mode 100644 index 0000000000..326f7d277f --- /dev/null +++ b/executables/ocp-gnb.c @@ -0,0 +1,1007 @@ +/* + * Author: Laurent Thomas, Open Cells Project + * all rights reserved + */ + +#define _GNU_SOURCE +#include +#include "assertions.h" +#include +#include + +#include "PHY/types.h" + +#include "PHY/INIT/phy_init.h" + +#include "PHY/defs_gNB.h" +#include "SCHED/sched_eNB.h" +#include "SCHED_NR/sched_nr.h" +#include "SCHED_NR/fapi_nr_l1.h" +#include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "../../ARCH/COMMON/common_lib.h" + +#include "PHY/phy_extern.h" +#include "LAYER2/MAC/mac.h" +#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" +#include "LAYER2/MAC/mac_proto.h" +#include "RRC/LTE/rrc_extern.h" +#include "PHY_INTERFACE/phy_interface.h" +#include "common/utils/LOG/log_extern.h" +#include "UTIL/OTG/otg_tx.h" +#include "UTIL/OTG/otg_externs.h" +#include "UTIL/MATH/oml.h" +#include "common/utils/LOG/vcd_signal_dumper.h" +#include "UTIL/OPT/opt.h" +#include "enb_config.h" +#include "s1ap_eNB.h" +#include "SIMULATION/ETH_TRANSPORT/proto.h" +#include +#include +#include +#include +#include +#include +#include +#include + +// should be in a shared lib +#include +#include +#include +#include + +// Global vars +#include +#include +#include +#include +volatile int oai_exit; +int single_thread_flag=1; +uint32_t do_forms=0; +unsigned int mmapped_dma=0; +int8_t threequarter_fs=0; + +int chain_offset=0; +uint16_t sl_ahead=6; +uint16_t sf_ahead=6; +uint32_t timing_advance = 0; +int transmission_mode=1; +int emulate_rf = 0; +int numerology = 0; + + +int config_sync_var=-1; +pthread_mutex_t nfapi_sync_mutex; +pthread_cond_t nfapi_sync_cond; +int nfapi_sync_var=-1; +double cpuf; + +THREAD_STRUCT thread_struct; + +pthread_cond_t sync_cond; +pthread_mutex_t sync_mutex; +int sync_var=-1; //!< protected by mutex \ref sync_mutex. + + +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +time_stats_t softmodem_stats_mt; // main thread +time_stats_t softmodem_stats_hw; // hw acquisition +time_stats_t softmodem_stats_rxtx_sf; // total tx time +time_stats_t nfapi_meas; // total tx time +time_stats_t softmodem_stats_rx_sf; // total rx time +// not used but needed for link +openair0_config_t openair0_cfg[MAX_CARDS]; +uint16_t slot_ahead=6; +msc_interface_t msc_interface; +AGENT_RRC_xface *agent_rrc_xface[NUM_MAX_ENB]; +AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB]; +int flexran_agent_start(mid_t mod_id) { + memset (agent_rrc_xface, 0, sizeof(agent_rrc_xface)); + memset (agent_mac_xface, 0, sizeof(agent_mac_xface)); + return 0; +} +void flexran_agent_slice_update(mid_t module_idP) { +} +int proto_agent_start(mod_id_t mod_id, const cudu_params_t *p) { + return 0; +} +void proto_agent_stop(mod_id_t mod_id) { +} +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +int stop_L1L2(module_id_t gnb_id) { + AssertFatal(false, "Must not be called in this context\n"); +} +int restart_L1L2(module_id_t gnb_id) { + AssertFatal(false, "Must not be called in this context\n"); +} + +static int wait_for_sync = 0; +static double snr_dB=20; +static int DEFBANDS[] = {7}; +static int DEFENBS[] = {0}; +static int DEFBFW[] = {0x00007fff}; + +extern double cpuf; + +short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT] = {0,0,16384,16384,-16384,-16384,16384,16384,16384,-16384,-16384,16384,-16384,-16384,7327,7327,7327,21981,21981,7327,21981,21981,7327,-7327,7327,-21981,21981,-7327,21981,-21981,-7327,7327,-7327,21981,-21981,7327,-21981,21981,-7327,-7327,-7327,-21981,-21981,-7327,-21981,-21981,10726,10726,10726,3576,3576,10726,3576,3576,10726,17876,10726,25027,3576,17876,3576,25027,17876,10726,17876,3576,25027,10726,25027,3576,17876,17876,17876,25027,25027,17876,25027,25027,10726,-10726,10726,-3576,3576,-10726,3576,-3576,10726,-17876,10726,-25027,3576,-17876,3576,-25027,17876,-10726,17876,-3576,25027,-10726,25027,-3576,17876,-17876,17876,-25027,25027,-17876,25027,-25027,-10726,10726,-10726,3576,-3576,10726,-3576,3576,-10726,17876,-10726,25027,-3576,17876,-3576,25027,-17876,10726,-17876,3576,-25027,10726,-25027,3576,-17876,17876,-17876,25027,-25027,17876,-25027,25027,-10726,-10726,-10726,-3576,-3576,-10726,-3576,-3576,-10726,-17876,-10726,-25027,-3576,-17876,-3576,-25027,-17876,-10726,-17876,-3576,-25027,-10726,-25027,-3576,-17876,-17876,-17876,-25027,-25027,-17876,-25027,-25027,8886,8886,8886,12439,12439,8886,12439,12439,8886,5332,8886,1778,12439,5332,12439,1778,5332,8886,5332,12439,1778,8886,1778,12439,5332,5332,5332,1778,1778,5332,1778,1778,8886,19547,8886,15993,12439,19547,12439,15993,8886,23101,8886,26655,12439,23101,12439,26655,5332,19547,5332,15993,1778,19547,1778,15993,5332,23101,5332,26655,1778,23101,1778,26655,19547,8886,19547,12439,15993,8886,15993,12439,19547,5332,19547,1778,15993,5332,15993,1778,23101,8886,23101,12439,26655,8886,26655,12439,23101,5332,23101,1778,26655,5332,26655,1778,19547,19547,19547,15993,15993,19547,15993,15993,19547,23101,19547,26655,15993,23101,15993,26655,23101,19547,23101,15993,26655,19547,26655,15993,23101,23101,23101,26655,26655,23101,26655,26655,8886,-8886,8886,-12439,12439,-8886,12439,-12439,8886,-5332,8886,-1778,12439,-5332,12439,-1778,5332,-8886,5332,-12439,1778,-8886,1778,-12439,5332,-5332,5332,-1778,1778,-5332,1778,-1778,8886,-19547,8886,-15993,12439,-19547,12439,-15993,8886,-23101,8886,-26655,12439,-23101,12439,-26655,5332,-19547,5332,-15993,1778,-19547,1778,-15993,5332,-23101,5332,-26655,1778,-23101,1778,-26655,19547,-8886,19547,-12439,15993,-8886,15993,-12439,19547,-5332,19547,-1778,15993,-5332,15993,-1778,23101,-8886,23101,-12439,26655,-8886,26655,-12439,23101,-5332,23101,-1778,26655,-5332,26655,-1778,19547,-19547,19547,-15993,15993,-19547,15993,-15993,19547,-23101,19547,-26655,15993,-23101,15993,-26655,23101,-19547,23101,-15993,26655,-19547,26655,-15993,23101,-23101,23101,-26655,26655,-23101,26655,-26655,-8886,8886,-8886,12439,-12439,8886,-12439,12439,-8886,5332,-8886,1778,-12439,5332,-12439,1778,-5332,8886,-5332,12439,-1778,8886,-1778,12439,-5332,5332,-5332,1778,-1778,5332,-1778,1778,-8886,19547,-8886,15993,-12439,19547,-12439,15993,-8886,23101,-8886,26655,-12439,23101,-12439,26655,-5332,19547,-5332,15993,-1778,19547,-1778,15993,-5332,23101,-5332,26655,-1778,23101,-1778,26655,-19547,8886,-19547,12439,-15993,8886,-15993,12439,-19547,5332,-19547,1778,-15993,5332,-15993,1778,-23101,8886,-23101,12439,-26655,8886,-26655,12439,-23101,5332,-23101,1778,-26655,5332,-26655,1778,-19547,19547,-19547,15993,-15993,19547,-15993,15993,-19547,23101,-19547,26655,-15993,23101,-15993,26655,-23101,19547,-23101,15993,-26655,19547,-26655,15993,-23101,23101,-23101,26655,-26655,23101,-26655,26655,-8886,-8886,-8886,-12439,-12439,-8886,-12439,-12439,-8886,-5332,-8886,-1778,-12439,-5332,-12439,-1778,-5332,-8886,-5332,-12439,-1778,-8886,-1778,-12439,-5332,-5332,-5332,-1778,-1778,-5332,-1778,-1778,-8886,-19547,-8886,-15993,-12439,-19547,-12439,-15993,-8886,-23101,-8886,-26655,-12439,-23101,-12439,-26655,-5332,-19547,-5332,-15993,-1778,-19547,-1778,-15993,-5332,-23101,-5332,-26655,-1778,-23101,-1778,-26655,-19547,-8886,-19547,-12439,-15993,-8886,-15993,-12439,-19547,-5332,-19547,-1778,-15993,-5332,-15993,-1778,-23101,-8886,-23101,-12439,-26655,-8886,-26655,-12439,-23101,-5332,-23101,-1778,-26655,-5332,-26655,-1778,-19547,-19547,-19547,-15993,-15993,-19547,-15993,-15993,-19547,-23101,-19547,-26655,-15993,-23101,-15993,-26655,-23101,-19547,-23101,-15993,-26655,-19547,-26655,-15993,-23101,-23101,-23101,-26655,-26655,-23101,-26655,-26655}; + +static inline int ocp_rxtx(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc) { + nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; + start_meas(&softmodem_stats_rxtx_sf); + + // ******************************************************************* + + if (nfapi_mode == NFAPI_MODE_PNF) { + // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick + //add_subframe(&frame, &subframe, 4); + //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); + //LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe); + start_meas(&nfapi_meas); + oai_subframe_ind(proc->frame_rx, proc->slot_rx); + stop_meas(&nfapi_meas); + /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| + gNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs || + gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs || + gNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles || + gNB->UL_INFO.cqi_ind.number_of_cqis + ) { + LOG_D(PHY, "UL_info[rx_ind:%05d:%d harqs:%05d:%d crcs:%05d:%d preambles:%05d:%d cqis:%d] RX:%04d%d TX:%04d%d \n", + NFAPI_SFNSF2DEC(gNB->UL_INFO.rx_ind.sfn_sf), gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus, + NFAPI_SFNSF2DEC(gNB->UL_INFO.harq_ind.sfn_sf), gNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs, + NFAPI_SFNSF2DEC(gNB->UL_INFO.crc_ind.sfn_sf), gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs, + NFAPI_SFNSF2DEC(gNB->UL_INFO.rach_ind.sfn_sf), gNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles, + gNB->UL_INFO.cqi_ind.number_of_cqis, + frame_rx, slot_rx, + frame_tx, slot_tx); + }*/ + } + + /// NR disabling + // **************************************** + // Common RX procedures subframe n + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = proc->frame_rx; + gNB->UL_INFO.slot = proc->slot_rx; + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + // RX processing + int tx_slot_type = nr_slot_select(cfg,proc->frame_tx,proc->slot_tx); + int rx_slot_type = nr_slot_select(cfg,proc->frame_rx,proc->slot_rx); + + if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { + // Do PRACH RU processing + L1_nr_prach_procedures(gNB,proc->frame_rx,proc->slot_rx); + phy_procedures_gNB_uespec_RX(gNB, proc->frame_rx, proc->slot_rx); + } + + if (oai_exit) return(-1); + + // ***************************************** + // TX processing for subframe n+sf_ahead + // run PHY TX procedures the one after the other for all CCs to avoid race conditions + // (may be relaxed in the future for performance reasons) + // ***************************************** + + if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { + phy_procedures_gNB_TX(gNB, proc->frame_tx,proc->slot_tx, 1); + } + + stop_meas( &softmodem_stats_rxtx_sf ); + LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, proc->frame_rx, proc->slot_rx, proc->frame_tx, proc->slot_tx); + return(0); +} + + +static void *process_stats_thread(void *param) { + PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; + reset_meas(&gNB->dlsch_encoding_stats); + reset_meas(&gNB->dlsch_scrambling_stats); + reset_meas(&gNB->dlsch_modulation_stats); + + while(!oai_exit) { + sleep(1); + print_meas(&gNB->dlsch_encoding_stats, "pdsch_encoding", NULL, NULL); + print_meas(&gNB->dlsch_scrambling_stats, "pdsch_scrambling", NULL, NULL); + print_meas(&gNB->dlsch_modulation_stats, "pdsch_modulation", NULL, NULL); + } + + return(NULL); +} + +void init_gNB_proc(int inst) { + PHY_VARS_gNB *gNB = RC.gNB[inst]; + gNB_L1_proc_t *proc = &gNB->proc; + gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc; + gNB_L1_rxtx_proc_t *L1_proc_tx = &proc->L1_proc_tx; + L1_proc->instance_cnt = -1; + L1_proc_tx->instance_cnt = -1; + L1_proc->instance_cnt_RUs = 0; + L1_proc_tx->instance_cnt_RUs = 0; + proc->instance_cnt_prach = -1; + proc->instance_cnt_asynch_rxtx = -1; + proc->CC_id = 0; + proc->first_rx =1; + proc->first_tx =1; + proc->RU_mask =0; + proc->RU_mask_tx = (1<num_RU)-1; + proc->RU_mask_prach =0; + pthread_mutex_init( &gNB->UL_INFO_mutex, NULL); + gNB->threadPool = (tpool_t *)malloc(sizeof(tpool_t)); + gNB->respDecode = (notifiedFIFO_t *) malloc(sizeof(notifiedFIFO_t)); + char ul_pool[] = "-1,-1"; + initTpool(ul_pool, gNB->threadPool, false); + initNotifiedFIFO(gNB->respDecode); +} + +/// eNB kept in function name for nffapi calls, TO FIX +void init_gNB_phase2(RU_t *ru) { + int inst; + LOG_I(PHY,"%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst); + + for (inst=0; instnum_RU:%d\n", gNB->num_RU); + phy_init_nr_gNB(gNB,0,0); + RC.gNB[inst]->num_RU=1; + RC.gNB[inst]->RU_list[0]=ru; + //init_precoding_weights(RC.gNB[inst][CC_id]); + } +} + +void init_gNB(int single_thread_flag,int wait_for_sync) { + for (int inst=0; instRCconfig_NR_L1\n"); + PHY_VARS_gNB *gNB= RC.gNB[inst]; + gNB->abstraction_flag = false; + gNB->single_thread_flag = true; + /*nr_polar_init(&gNB->nrPolar_params, + NR_POLAR_PBCH_MESSAGE_TYPE, + NR_POLAR_PBCH_PAYLOAD_BITS, + NR_POLAR_PBCH_AGGREGATION_LEVEL);*/ + LOG_I(PHY,"Registering with MAC interface module\n"); + AssertFatal((gNB->if_inst = NR_IF_Module_init(inst))!=NULL,"Cannot register interface"); + gNB->if_inst->NR_Schedule_response = nr_schedule_response; + gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; + memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO)); + memset((void *)&gNB->UL_tti_req,0,sizeof(nfapi_nr_ul_tti_request_t)); + //memset((void *)&gNB->Sched_INFO,0,sizeof(gNB->Sched_INFO)); + LOG_I(PHY,"Setting indication lists\n"); + gNB->UL_INFO.rx_ind.pdu_list = gNB->rx_pdu_list; + gNB->UL_INFO.crc_ind.crc_list = gNB->crc_pdu_list; + /*gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list; + gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list; + gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list; + gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/ + gNB->prach_energy_counter = 0; + } + + LOG_I(PHY,"[nr-softmodem.c] gNB structure allocated\n"); +} + + +void stop_gNB(int nb_inst) { +} + +static void get_options(void) { + paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ; + config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); + + if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) { + memset((void *)&RC,0,sizeof(RC)); + /* Read RC configuration file */ + NRRCConfig(); + printf("Configuration: nb_rrc_inst %d, nb_nr_L1_inst %d, nb_ru %hhd\n", RC.nb_nr_inst,RC.nb_nr_L1_inst,RC.nb_RU); + } + + AssertFatal(RC.nb_nr_L1_inst == 1 && RC.nb_RU == 1, "Only one gNB, one RU and one carrier is supported\n"); +} + +void set_default_frame_parms(nfapi_nr_config_request_t *config[MAX_NUM_CCs], + NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { + for (int CC_id=0; CC_idsubframe_config.numerology_index_mu.value =1; + config[CC_id]->subframe_config.duplex_mode.value = 1; //FDD + config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL + config[CC_id]->rf_config.dl_carrier_bandwidth.value = 106; + config[CC_id]->rf_config.ul_carrier_bandwidth.value = 106; + config[CC_id]->sch_config.physical_cell_id.value = 0; + } +} + +static void init_pdcp(void) { + //if (!NODE_IS_DU(RC.rrc[0]->node_type)) { + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + + if (IS_SOFTMODEM_NOS1) { + printf("IS_SOFTMODEM_NOS1 option enabled \n"); + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; + } + + pdcp_module_init(pdcp_initmask); + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); +} + +void init_main_gNB(void) { + RCconfig_NR_L1(); + RCconfig_nr_macrlc(); + + if (RC.nb_nr_L1_inst>0) + AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n"); + + LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst); + RC.nrrrc = (gNB_RRC_INST **)calloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *),1); + LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc); + int gnb_id=0; // only 1 gnb per process, index 0 for now + RC.nrrrc[gnb_id] = (gNB_RRC_INST *)calloc(sizeof(gNB_RRC_INST),1); + MessageDef *msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, NRRRC_CONFIGURATION_REQ); + RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]); + openair_rrc_gNB_configuration(GNB_INSTANCE_TO_MODULE_ID(ITTI_MSG_DESTINATION_INSTANCE(msg_p)), &NRRRC_CONFIGURATION_REQ(msg_p)); + //AssertFatal(itti_create_task(TASK_GNB_APP, gNB_app_task, NULL) >= 0, ""); + AssertFatal(itti_create_task(TASK_RRC_GNB, rrc_gnb_task, NULL) >= 0, ""); + //AssertFatal(itti_create_task(TASK_X2AP, x2ap_task, NULL) >= 0, ""); +} + +static void wait_nfapi_init(char *thread_name) { + printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name); + pthread_mutex_lock( &nfapi_sync_mutex ); + + while (nfapi_sync_var<0) + pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex ); + + pthread_mutex_unlock(&nfapi_sync_mutex); + printf( "NFAPI: got sync (%s)\n", thread_name); +} + +void exit_function(const char *file, const char *function, const int line, const char *s) { + if (s != NULL) { + printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); + } + + oai_exit = 1; + sleep(1); //allow lte-softmodem threads to exit first + exit(1); +} + +void stop_RU(int nb_ru) { + return; +} + +void OCPconfig_RU(RU_t *ru) { + int i = 0, j = 0; // Ru and gNB cardinality + paramdef_t RUParams[] = RUPARAMS_DESC; + paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; + config_getlist( &RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL); + AssertFatal( RUParamList.numelt == 1 && RC.nb_nr_L1_inst ==1,"" ); + ru->idx=0; + ru->nr_frame_parms = (NR_DL_FRAME_PARMS *)calloc(sizeof(NR_DL_FRAME_PARMS),1); + ru->frame_parms = (LTE_DL_FRAME_PARMS *)calloc(sizeof(LTE_DL_FRAME_PARMS),1); + ru->if_timing = synch_to_ext_device; + ru->num_gNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt; + ru->gNB_list[i] = &RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0]; + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { + ru->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); + } + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { + ru->openair0_cfg.clock_source = internal; + LOG_D(PHY, "RU clock source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { + ru->openair0_cfg.clock_source = external; + LOG_D(PHY, "RU clock source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { + ru->openair0_cfg.clock_source = gpsdo; + LOG_D(PHY, "RU clock source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } else { + ru->openair0_cfg.clock_source = unset; + } + + if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { + if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { + ru->if_south = REMOTE_IF5; //TBD: max value to avoid to call "ru" functions + ru->function = gNodeB_3GPP; + printf("Setting function for RU %d to gNodeB_3GPP\n",j); + } else { + } + + ru->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; + ru->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); + ru->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; + + for (i=0; inum_bands; i++) ru->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; + } //strcmp(local_rf, "yes") == 0 + else { + } + + ru->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); + ru->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); + ru->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); + ru->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); + + if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) { + ru->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt; + + for (i=0; inum_gNB; i++) { + ru->bw_list[i] = (int32_t *)malloc16_clear((ru->nb_bfw)*sizeof(int32_t)); + + for (int b=0; bnb_bfw; b++) ru->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b]; + } + } + + return; +} + +// this is for RU with local RF unit +void fill_rf_config(RU_t *ru, char *rf_config_file) { + int i; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + nfapi_nr_config_request_scf_t *gNB_config = &ru->gNB_list[0]->gNB_config; //tmp index + openair0_config_t *cfg = &ru->openair0_cfg; + int mu = gNB_config->ssb_config.scs_common.value; + int N_RB = gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value; + fp->threequarter_fs=threequarter_fs; + + if (mu == NR_MU_0) { //or if LTE + if(N_RB == 100) { + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + } else if(N_RB == 50) { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } else if (N_RB == 25) { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 2.5e6; + cfg->rx_bw = 2.5e6; + } else if (N_RB == 6) { + cfg->sample_rate=1.92e6; + cfg->samples_per_frame = 19200; + cfg->tx_bw = 1.5e6; + cfg->rx_bw = 1.5e6; + } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB); + } else if (mu == NR_MU_1) { + if(N_RB == 273) { + if (fp->threequarter_fs) { + AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + } else if(N_RB == 217) { + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } + } else if(N_RB == 106) { + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + } else { + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + } + } else if (mu == NR_MU_3) { + if (N_RB == 66) { + cfg->sample_rate = 122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else if(N_RB == 32) { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + } else { + AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); + } + + if (gNB_config->cell_config.frame_duplex_type.value==TDD) + cfg->duplex_mode = duplex_mode_TDD; + else //FDD + cfg->duplex_mode = duplex_mode_FDD; + + cfg->Mod_id = 0; + cfg->num_rb_dl=N_RB; + cfg->tx_num_channels=ru->nb_tx; + cfg->rx_num_channels=ru->nb_rx; + + for (i=0; inb_tx; i++) { + if (ru->if_frequency == 0) { + cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; + cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; + } else { + cfg->tx_freq[i] = (double)ru->if_frequency; + cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq); + } + + cfg->tx_gain[i] = ru->att_tx; + cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; + cfg->configFilename = rf_config_file; + printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", + i, cfg->tx_gain[i], + cfg->rx_gain[i], + cfg->tx_freq[i], + cfg->rx_freq[i]); + } +} + +/* this function maps the RU tx and rx buffers to the available rf chains. + Each rf chain is is addressed by the card number and the chain on the card. The + rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple + antennas are mapped to successive RF chains on the same card. */ +int setup_RU_buffers(RU_t *ru) { + int i,j; + int card,ant; + //uint16_t N_TA_offset = 0; + NR_DL_FRAME_PARMS *frame_parms; + nfapi_nr_config_request_scf_t *config = &ru->config; + + if (ru) { + frame_parms = ru->nr_frame_parms; + printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + } else { + printf("ru pointer is NULL\n"); + return(-1); + } + + int mu = config->ssb_config.scs_common.value; + int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; + + if (config->cell_config.frame_duplex_type.value == TDD) { + int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 + double factor=1; + + switch (mu) { + case 0: //15 kHz scs + AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n"); + + if (N_RB <= 25) factor = .25; // 7.68 Ms/s + else if (N_RB <=50) factor = .5; // 15.36 Ms/s + else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s + else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s + else AssertFatal(1==0,"Too many PRBS for mu=0\n"); + + break; + + case 1: //30 kHz sc + AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n"); + + if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s + else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s + + break; + + case 2: //60 kHz scs + AssertFatal(1==0,"scs_common should not be 60 kHz\n"); + break; + + case 3: //120 kHz scs + AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n"); + break; + + case 4: //240 kHz scs + AssertFatal(1==0,"scs_common should not be 60 kHz\n"); + + if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s + else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s + else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); + + break; + + if (N_RB == 100) ru->N_TA_offset = 624; + else if (N_RB == 50) ru->N_TA_offset = 624/2; + else if (N_RB == 25) ru->N_TA_offset = 624/4; + } + + if (frame_parms->threequarter_fs == 1) factor = factor*.75; + + ru->N_TA_offset = (int)(N_TA_offset * factor); + LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor, + config->carrier_config.uplink_frequency.value, N_RB); + } else ru->N_TA_offset = 0; + + if (ru->openair0_cfg.mmapped_dma == 1) { + // replace RX signal buffers with mmaped HW versions + for (i=0; inb_rx; i++) { + card = i/4; + ant = i%4; + printf("Mapping RU id %u, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + free(ru->common.rxdata[i]); + ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain+ant]; + printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); + + for (j=0; j<16; j++) { + printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); + ru->common.rxdata[i][j] = 16-j; + } + } + + for (i=0; inb_tx; i++) { + card = i/4; + ant = i%4; + printf("Mapping RU id %u, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + free(ru->common.txdata[i]); + ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant]; + printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); + + for (j=0; j<16; j++) { + printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); + ru->common.txdata[i][j] = 16-j; + } + } + } else { // not memory-mapped DMA + //nothing to do, everything already allocated in lte_init + } + + return(0); +} +int rx_rf(int rxBufOffet, int nbSamples, int nb_rx, int32_t **rxdata, openair0_device *rfdevice, openair0_timestamp *HWtimeStamp) { + void *rxp[nb_rx]; + + for (int i=0; itrx_read_func(rfdevice, + HWtimeStamp, + rxp, + nbSamples, + nb_rx); + + if (rxs != nbSamples ) + LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",nbSamples,rxs); + + return rxs; +} + +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config; + int i,txsymb; + int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); + int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame); + int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame); + int sf_extension = 0; //sf_extension = ru->sf_extension; + int siglen=fp->get_samples_per_slot(slot,fp); + int flags=1; + + //nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame); + if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) { + if(slot_type == NR_MIXED_SLOT) { + txsymb = 0; + + for(int symbol_count =0; symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==0) + txsymb++; + } + + AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb); + + if(slot%(fp->slots_per_subframe/2)) + siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + else + siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + + //+ ru->end_of_burst_delay; + flags=3; // end of burst + } + + if (cfg->cell_config.frame_duplex_type.value == TDD && + slot_type == NR_DOWNLINK_SLOT && + prevslot_type == NR_UPLINK_SLOT) { + flags = 2; // start of burst + } + + if (cfg->cell_config.frame_duplex_type.value == TDD && + slot_type == NR_DOWNLINK_SLOT && + nextslot_type == NR_UPLINK_SLOT) { + flags = 3; // end of burst + } + + if (fp->freq_range==nr_FR2) { + // the beam index is written in bits 8-10 of the flags + // bit 11 enables the gpio programming + int beam=0; + + if (slot==0) beam = 11; //3 for boresight & 8 to enable + + /* + if (slot==0 || slot==40) beam=0&8; + if (slot==10 || slot==50) beam=1&8; + if (slot==20 || slot==60) beam=2&8; + if (slot==30 || slot==70) beam=3&8; + */ + flags |= beam<<8; + } + + void *txp[ru->nb_tx]; + + for (i=0; inb_tx; i++) + txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension]; + + // prepare tx buffer pointers + unsigned int txs = ru->rfdevice.trx_write_func(&ru->rfdevice, + timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %d\n",ru->idx, + (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot); + AssertFatal(txs == siglen+sf_extension,"TX : Timeout (sent %u/%d)\n", txs, siglen); + } +} + +static void *ru_thread( void *param ) { + RU_t *ru = (RU_t *)param; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); + nr_dump_frame_parms(fp); + AssertFatal(openair0_device_load(&ru->rfdevice,&ru->openair0_cfg)==0,"Cannot connect to local radio\n"); + AssertFatal(ru->rfdevice.trx_start_func(&ru->rfdevice) == 0,"Could not start the RF device\n"); + int64_t slot=-1; + int64_t nextHWTSshouldBe=0, nextRxTSlogical=0; + // weird globals, used in NR_IF_Module.c + sf_ahead = (uint16_t) ceil((float)6/(0x01<numerology_index)); + sl_ahead = sf_ahead*fp->slots_per_subframe; + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + + while (!oai_exit) { + int nextSlot=(slot+1)%fp->slots_per_frame; + uint32_t samples_per_slot = fp->get_samples_per_slot(nextSlot,fp); + int rxBuffOffset=fp->get_samples_slot_timestamp(nextSlot,fp,0); + AssertFatal(rxBuffOffset + samples_per_slot <= fp->samples_per_frame, "Will read outside allocated buffer\n"); + int samples=fp->get_samples_per_slot(nextSlot,fp); + openair0_timestamp HWtimeStamp=0; //for multi RU + int rxs=rx_rf(rxBuffOffset, + samples, + ru->nb_rx, + ru->common.rxdata, + &ru->rfdevice, + &HWtimeStamp); + LOG_D(PHY,"Reading %d samples for slot %d\n",samples_per_slot,nextSlot); + + if ( HWtimeStamp != nextHWTSshouldBe) + LOG_E(HW,"reading a stream must be continuous, %ld, %ld\n", HWtimeStamp, nextHWTSshouldBe); + + nextHWTSshouldBe=HWtimeStamp+rxs; + ru->proc.timestamp_rx=nextRxTSlogical; + nextRxTSlogical+=samples_per_slot; + int64_t HW_to_logical_RxTSoffset=(int64_t)HWtimeStamp-(int64_t)ru->proc.timestamp_rx; + ru->proc.frame_rx = (ru->proc.timestamp_rx / (fp->samples_per_subframe*10))&1023; + uint32_t idx_sf = ru->proc.timestamp_rx / fp->samples_per_subframe; + float offsetInSubframe=ru->proc.timestamp_rx % fp->samples_per_subframe; + ru->proc.tti_rx = (idx_sf * fp->slots_per_subframe + + lroundf(offsetInSubframe / fp->samples_per_slot0))% + fp->slots_per_frame; + LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n", + ru->idx, 0, + (unsigned long long int)ru->proc.timestamp_rx, + (int)ru->ts_offset,ru->proc.frame_rx,ru->proc.tti_rx,ru->proc.tti_tx,fp->slots_per_frame); + int slot_type = nr_slot_select(&ru->gNB_list[0]->gNB_config,ru->proc.frame_rx,ru->proc.tti_rx); + + if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { + nr_fep_full(ru,ru->proc.tti_rx); + + for (int aa=0; aanb_rx; aa++) + memcpy((void *)RC.gNB[0]->common_vars.rxdataF[aa], + (void *)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); + + LOG_D(PHY, "rxdataF energy: %d\n", signal_energy(ru->common.rxdataF[0], fp->symbols_per_slot*fp->ofdm_symbol_size)); + } + + gNB_L1_proc_t *gNBproc=&RC.gNB[0][0].proc; + gNB_L1_rxtx_proc_t *L1_proc = &gNBproc->L1_proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + gNBproc->timestamp_rx = ru->proc.timestamp_rx; + L1_proc->frame_rx = gNBproc->frame_rx = gNBproc->frame_prach = ru->proc.frame_rx = + (ru->proc.timestamp_rx / (fp->samples_per_subframe*10))&1023; + L1_proc->slot_rx = gNBproc->slot_rx = gNBproc->slot_prach = + ru->proc.tti_rx; // computed before in caller function + L1_proc->timestamp_tx = gNBproc->timestamp_tx = ru->proc.timestamp_tx = + ru->proc.timestamp_rx + + sf_ahead*fp->samples_per_subframe; + L1_proc->frame_tx = gNBproc->frame_tx = ru->proc.frame_tx = + (gNBproc->timestamp_tx / (fp->samples_per_subframe*10))&1023; + L1_proc->slot_tx = ru->proc.tti_tx = + (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame; + + if (ocp_rxtx(&RC.gNB[0][0],L1_proc) < 0) + LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",RC.gNB[0][0].Mod_id,RC.gNB[0][0].CC_id); + + // do TX front-end processing if needed (precoding and/or IDFTs) + //ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); + nr_feptx_prec(ru,ru->proc.frame_tx,ru->proc.tti_tx); + // do OFDM with/without TX front-end processing if needed + //ru->feptx_ofdm + nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config; + + if (nr_slot_select(cfg,ru->proc.frame_tx, ru->proc.tti_tx ) != NR_UPLINK_SLOT) { + int aa=0; // antenna 0 hardcoded + NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; + nr_feptx0(ru,ru->proc.tti_tx,0,fp->symbols_per_slot,aa); + int *txdata = &ru->common.txdata[aa][fp->get_samples_slot_timestamp(ru->proc.tti_tx,fp,0)]; + int slot_sizeF = (fp->ofdm_symbol_size)* + ((NFAPI_CP_NORMAL == 1) ? 12 : 14); + LOG_D(PHY,"feptx_ofdm (TXPATH): frame %d, slot %d: txp (time %ld) %d dB, txp (freq) %d dB\n", + ru->proc.frame_tx,ru->proc.tti_tx,ru->proc.timestamp_tx, + dB_fixed(signal_energy((int32_t *)txdata,fp->get_samples_per_slot(ru->proc.tti_tx,fp))), + dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF))); + } + + // do outgoing fronthaul (south) if needed + tx_rf(ru,ru->proc.frame_tx,ru->proc.tti_tx,ru->proc.timestamp_tx+HW_to_logical_RxTSoffset); + slot++; + } + + printf( "Exiting ru_thread \n"); + ru->rfdevice.trx_end_func(&ru->rfdevice); + static int ru_thread_status = 0; + return &ru_thread_status; +} + +void launch_NR_RU(RU_t *ru, char *rf_config_file) { + LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n", + RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs()); + LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); + + for (int ru_id=0; ru_idrf_config_file = rf_config_file; + ru->idx = ru_id; + ru->ts_offset = 0; + // use gNB_list[0] as a reference for RU frame parameters + // NOTE: multiple CC_id are not handled here yet! + LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p rf_config_file:%s\n", + __FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], ru->rf_config_file); + LOG_E(PHY,"ru->gNB_list ru->num_gNB hardcoded: one RU connected to carrier 0 of gNB 0\n"); + ru->gNB_list[0] = &RC.gNB[0][0]; + ru->num_gNB=1; + LOG_I(PHY,"Copying frame parms from gNB in RC to ru %d and frame_parms in ru\n",ru->idx); + RU_proc_t *proc = &ru->proc; + threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "MainLoop", -1, OAI_PRIORITY_RT_MAX ); + } +} + +void init_eNB_afterRU(void) { + AssertFatal(false,""); +} + +int main( int argc, char **argv ) { + AssertFatal(load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY), + "[SOFTMODEM] Error, configuration module init failed\n"); + logInit(); +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN" +#endif + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + configure_linux(); + get_options (); + get_common_options(SOFTMODEM_GNB_BIT ); + AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n"); + cpuf=get_cpu_freq_GHz(); + itti_init(TASK_MAX, tasks_info); + set_taus_seed (0); + init_opt(); + init_pdcp(); + init_main_gNB(); + init_gNB(true, wait_for_sync); + /* Start the agent. If it is turned off in the configuration, it won't start */ + RCconfig_nr_flexran(); + + for (int i = 0; i < RC.nb_nr_L1_inst; i++) { + flexran_agent_start(i); + } + + /* + *nfapi stuff very buggy in 4G, not yet implemented in 5G + */ + // init UE_PF_PO and mutex lock (paging from S1AP) + pthread_mutex_init(&ue_pf_po_mutex, NULL); + printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n"); + pthread_cond_init(&nfapi_sync_cond,NULL); + pthread_mutex_init(&nfapi_sync_mutex, NULL); + const char *nfapi_mode_str[] = { + "MONOLITHIC", "PNF", "VNF", + }; + AssertFatal(nfapi_mode < 3,""); + printf("NFAPI MODE:%s\n", nfapi_mode_str[nfapi_mode]); + + if (nfapi_mode==NFAPI_MODE_VNF) // VNF + wait_nfapi_init("main?"); + + for (int i=0; iconfigured, "Remain threads to manage\n"); + + printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); + config_sync_var=0; + + if (nfapi_mode==NFAPI_MODE_PNF) { // PNF + wait_nfapi_init("main?"); + } + + printf("wait RUs\n"); + printf("ALL RUs READY!\n"); + printf("RC.nb_RU:%d\n", RC.nb_RU); + // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration) + printf("ALL RUs ready - init gNBs\n"); + LOG_E(PHY,"configuring RU from file, hardcoded one gNB for one RU, one carrier\n"); + RU_t ru= {0}; + OCPconfig_RU(&ru); + ru.nr_frame_parms->threequarter_fs=threequarter_fs; + fill_rf_config(&ru,ru.rf_config_file); + init_gNB_phase2(&ru); + memcpy((void *)ru.nr_frame_parms,&RC.gNB[0][0].frame_parms,sizeof(NR_DL_FRAME_PARMS)); + memcpy((void *)&ru.config,(void *)&RC.gNB[0]->gNB_config,sizeof(ru.config)); + AssertFatal(setup_RU_buffers(&ru)==0,"Inconsistent configuration"); + nr_phy_init_RU(&ru); + init_gNB_proc(0); // only instance 0 (one gNB per process) + + if (RC.nb_RU >0) { + printf("Initializing RU threads\n"); + launch_NR_RU(&ru, get_softmodem_params()->rf_config_file); + } + + if (opp_enabled ==1) { + pthread_t t; + threadCreate(&t, process_stats_thread, + (void *)NULL, "time_meas", -1, OAI_PRIORITY_RT_LOW); + } + + if(IS_SOFTMODEM_DOSCOPE) { + scopeParms_t tmp= {&argc, argv, &ru, RC.gNB[0]}; + load_softscope("nr",&tmp); + } + + while(!oai_exit) + sleep(1); + + logClean(); + printf("Bye.\n"); + return 0; +} diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index 04a58413b5..e10515ea1a 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -39,11 +39,16 @@ #include "executables/thread-common.h" #include "common/utils/LOG/log.h" #include "softmodem-common.h" +#include "nfapi/oai_integration/vendor_ext.h" + static softmodem_params_t softmodem_params; char *parallel_config=NULL; char *worker_config=NULL; +msc_interface_t msc_interface; +int usrp_tx_thread = 0; +uint8_t nfapi_mode=0; static mapping softmodem_funcs[] = MAPPING_SOFTMODEM_FUNCTIONS; static struct timespec start; @@ -83,8 +88,8 @@ char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr) { void get_common_options(uint32_t execmask) { uint32_t online_log_messages=0; uint32_t glog_level=0 ; - uint32_t start_telnetsrv = 0; - uint32_t noS1 = 0, nokrnmod = 0, nonbiot = 0; + uint32_t start_telnetsrv = 0, start_telnetclt = 0; + uint32_t noS1 = 0, nokrnmod = 1, nonbiot = 0; uint32_t rfsim = 0, basicsim = 0, do_forms = 0; char *logmem_filename = NULL; paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ; @@ -92,21 +97,26 @@ void get_common_options(uint32_t execmask) { checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC; check_execmask(execmask); config_get( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); - config_set_checkfunctions(cmdline_logparams, cmdline_log_CheckParams, - sizeof(cmdline_logparams)/sizeof(paramdef_t)); - config_get( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL); - - if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) { + + int numparams=sizeof(cmdline_logparams)/sizeof(paramdef_t); + config_set_checkfunctions(cmdline_logparams, cmdline_log_CheckParams,numparams); + config_get( cmdline_logparams,numparams,NULL); + + if(config_isparamset(cmdline_logparams,config_paramidx_fromname(cmdline_logparams,numparams, CONFIG_FLOG_OPT))) { set_glog_onlinelog(online_log_messages); } - if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) { + if(config_isparamset(cmdline_logparams,config_paramidx_fromname(cmdline_logparams,numparams, CONFIG_LOGL_OPT))) { set_glog(glog_level); } if (start_telnetsrv) { load_module_shlib("telnetsrv",NULL,0,NULL); } + + if (start_telnetclt) { + set_softmodem_optmask(SOFTMODEM_TELNETCLT_BIT); + } if (logmem_filename != NULL && strlen(logmem_filename) > 0) { log_mem_filename = &logmem_filename[0]; @@ -137,12 +147,13 @@ void get_common_options(uint32_t execmask) { } if (do_forms) { - set_softmodem_optmask(SOFTMODEM_DOFORMS_BIT); + set_softmodem_optmask(SOFTMODEM_DOSCOPE_BIT); } if(parallel_config != NULL) set_parallel_conf(parallel_config); if(worker_config != NULL) set_worker_conf(worker_config); + nfapi_setmode(nfapi_mode); } void softmodem_printresources(int sig, telnet_printfunc_t pf) { struct rusage usage; diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 449d2e0957..3a7022a502 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -56,6 +56,7 @@ extern "C" #define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n" #define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n" #define CONFIG_HLP_DORA "test gNB and UE with RA procedures\n" +#define CONFIG_HLP_SA "run gNB in standalone mode\n" #define CONFIG_HLP_EXTS "tells hardware to use an external timing reference\n" #define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0" #define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n" @@ -63,14 +64,17 @@ extern "C" #define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n" #define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" #define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" +#define CONFIG_HLP_ULF "Set the uplink frequency offset for all component carriers\n" #define CONFIG_HLP_CHOFF "Channel id offset\n" #define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n" #define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n" #define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" #define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" #define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" +#define CONFIG_HLP_256QAM "Use the 256 QAM mcs table for PDSCH\n" +#define CONFIG_HLP_PRBINTER "Do PRB based averaging of channel estimates. Frequency domain linear interpolation by default\n" - +#define CONFIG_HLP_NONSTOP "Go back to frame sync mode after 100 consecutive PBCH failures\n" //#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" #define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" @@ -82,13 +86,18 @@ extern "C" #define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n" #define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n" +#define CONFIG_HLP_BAND "band index\n" #define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n" #define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n" #define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n" +#define CONFIG_HLP_USRP_THREAD "having extra thead for usrp tx\n" + #define CONFIG_HLP_NOS1 "Disable s1 interface\n" #define CONFIG_HLP_RFSIM "Run in rf simulator mode (also known as basic simulator)\n" #define CONFIG_HLP_NOKRNMOD "(noS1 only): Use tun instead of namesh module \n" #define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" +#define CONFIG_HLP_USRP_THREAD "having extra thead for usrp tx\n" +#define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR\n" /*-----------------------------------------------------------------------------------------------------------------------------------------------------*/ /* command line parameters common to eNodeB and UE */ @@ -99,34 +108,44 @@ extern "C" #define TP_CONFIG softmodem_params.threadPoolConfig #define PHY_TEST softmodem_params.phy_test #define DO_RA softmodem_params.do_ra +#define SA softmodem_params.sa #define WAIT_FOR_SYNC softmodem_params.wait_for_sync #define SINGLE_THREAD_FLAG softmodem_params.single_thread_flag #define CHAIN_OFFSET softmodem_params.chain_offset #define NUMEROLOGY softmodem_params.numerology +#define BAND softmodem_params.band #define EMULATE_RF softmodem_params.emulate_rf #define CLOCK_SOURCE softmodem_params.clock_source #define TIMING_SOURCE softmodem_params.timing_source #define SEND_DMRSSYNC softmodem_params.send_dmrs_sync #define USIM_TEST softmodem_params.usim_test +#define USE_256QAM_TABLE softmodem_params.use_256qam_table +#define PRB_INTERPOLATION softmodem_params.prb_interpolation +#define NFAPI softmodem_params.nfapi +#define NON_STOP softmodem_params.non_stop #define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat"; +extern int usrp_tx_thread; #define CMDLINE_PARAMS_DESC { \ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\ - {"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)},\ - {"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \ + {"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)}, \ + {"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \ {"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, iptr:&DO_RA, defintval:0, TYPE_INT, 0}, \ + {"sa", CONFIG_HLP_SA, PARAMFLAG_BOOL, iptr:&SA, defintval:0, TYPE_INT, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \ - {"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ - {"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \ + {"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ + {"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \ {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \ {"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \ + {"CO" , CONFIG_HLP_ULF, 0, iptr:&(uplink_frequency_offset[0][0]), defintval:0, TYPE_INT, 0}, \ {"a" , CONFIG_HLP_CHOFF, 0, iptr:&CHAIN_OFFSET, defintval:0, TYPE_INT, 0}, \ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ - {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \ + {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:1, TYPE_INT, 0}, \ + {"band" , CONFIG_HLP_BAND, PARAMFLAG_BOOL, iptr:&BAND, defintval:78, TYPE_INT, 0}, \ {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&EMULATE_RF, defintval:0, TYPE_INT, 0}, \ {"parallel-config", CONFIG_HLP_PARALLEL_CMD, 0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ @@ -135,6 +154,11 @@ extern "C" {"basicsim", CONFIG_HLP_RFSIM, PARAMFLAG_BOOL, uptr:&basicsim, defintval:0, TYPE_INT, 0}, \ {"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \ + {"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \ + {"do-prb-interpolation", CONFIG_HLP_PRBINTER, PARAMFLAG_BOOL, iptr:&PRB_INTERPOLATION, defintval:0, TYPE_INT, 0}, \ + {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \ + {"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \ + {"non-stop", CONFIG_HLP_NONSTOP, PARAMFLAG_BOOL, iptr:&NON_STOP, defintval:0, TYPE_INT, 0}, \ } @@ -143,23 +167,22 @@ extern "C" #define CONFIG_HLP_LOGV "Set the global log verbosity \n" #define CONFIG_HLP_TELN "Start embedded telnet server \n" #define CONFIG_HLP_MSC "Enable the MSC tracing utility \n" -/*----------------------------------------------------------------------------------------------------------------------------*/ -/* command line parameters for LOG utility */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*----------------------------------------------------------------------------------------------------------------------------*/ +#define CONFIG_FLOG_OPT "R" +#define CONFIG_LOGL_OPT "g" +/*-------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters for LOG utility */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*-------------------------------------------------------------------------------------------------------------------------------------------------*/ #define START_MSC softmodem_params.start_msc #define CMDLINE_LOGPARAMS_DESC { \ - {"R" , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \ - {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ - {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ - {"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \ - {"log-mem", NULL, 0, strptr:(char **)&logmem_filename, defstrval:NULL, TYPE_STRING, 0}, \ + {CONFIG_FLOG_OPT , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \ + {CONFIG_LOGL_OPT , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ + {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ + {"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \ + {"log-mem", NULL, 0, strptr:(char **)&logmem_filename, defstrval:NULL, TYPE_STRING, 0}, \ + {"telnetclt", NULL, 0, uptr:&start_telnetclt, defstrval:NULL, TYPE_UINT, 0}, \ } -#define CMDLINE_ONLINELOG_IDX 0 -#define CMDLINE_GLOGLEVEL_IDX 1 -#define CMDLINE_GLOGVERBO_IDX 2 -#define CMDLINE_STARTTELN_IDX 3 /* check function for global log level */ #define CMDLINE_LOGPARAMS_CHECK_DESC { \ @@ -168,6 +191,7 @@ extern "C" { .s5= {NULL} } , \ { .s5= {NULL} } , \ { .s5= {NULL} } , \ + { .s5= {NULL} } , \ } /***************************************************************************************************************************************/ @@ -178,8 +202,9 @@ extern "C" #define SOFTMODEM_RFSIM_BIT (1<<10) #define SOFTMODEM_BASICSIM_BIT (1<<11) #define SOFTMODEM_SIML1_BIT (1<<12) -#define SOFTMODEM_DOFORMS_BIT (1<<15) +#define SOFTMODEM_DOSCOPE_BIT (1<<15) #define SOFTMODEM_RECPLAY_BIT (1<<16) +#define SOFTMODEM_TELNETCLT_BIT (1<<17) #define SOFTMODEM_ENB_BIT (1<<20) #define SOFTMODEM_GNB_BIT (1<<21) #define SOFTMODEM_4GUE_BIT (1<<22) @@ -194,8 +219,9 @@ extern "C" #define IS_SOFTMODEM_RFSIM ( get_softmodem_optmask() & SOFTMODEM_RFSIM_BIT) #define IS_SOFTMODEM_BASICSIM ( get_softmodem_optmask() & SOFTMODEM_BASICSIM_BIT) #define IS_SOFTMODEM_SIML1 ( get_softmodem_optmask() & SOFTMODEM_SIML1_BIT) -#define IS_SOFTMODEM_DOFORMS ( get_softmodem_optmask() & SOFTMODEM_DOFORMS_BIT) +#define IS_SOFTMODEM_DOSCOPE ( get_softmodem_optmask() & SOFTMODEM_DOSCOPE_BIT) #define IS_SOFTMODEM_IQPLAYER ( get_softmodem_optmask() & SOFTMODEM_RECPLAY_BIT) +#define IS_SOFTMODEM_TELNETCLT_BIT ( get_softmodem_optmask() & SOFTMODEM_TELNETCLT_BIT) #define IS_SOFTMODEM_ENB_BIT ( get_softmodem_optmask() & SOFTMODEM_ENB_BIT) #define IS_SOFTMODEM_GNB_BIT ( get_softmodem_optmask() & SOFTMODEM_GNB_BIT) #define IS_SOFTMODEM_4GUE_BIT ( get_softmodem_optmask() & SOFTMODEM_4GUE_BIT) @@ -209,17 +235,23 @@ typedef struct { char threadPoolConfig[1024]; int phy_test; int do_ra; + int sa; uint8_t usim_test; int emulate_rf; int wait_for_sync; //eNodeB only int single_thread_flag; //eNodeB only int chain_offset; int numerology; + int band; unsigned int start_msc; uint32_t clock_source; uint32_t timing_source; int hw_timing_advance; uint32_t send_dmrs_sync; + int use_256qam_table; + int prb_interpolation; + uint8_t nfapi; + int non_stop; } softmodem_params_t; extern uint64_t get_softmodem_optmask(void); @@ -230,6 +262,16 @@ extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr); #define SOFTMODEM_RTSIGNAL (SIGRTMIN+1) extern void set_softmodem_sighandler(void); extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; +extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +extern int usrp_tx_thread; +extern uint16_t sl_ahead; +extern uint16_t sf_ahead; +extern volatile int oai_exit; + +void tx_func(void *param); +void rx_func(void *param); +void ru_tx_func(void *param); +extern uint8_t nfapi_mode; #ifdef __cplusplus } #endif diff --git a/executables/stats.h b/executables/stats.h index 6c847a2860..9bd4c6f080 100644 --- a/executables/stats.h +++ b/executables/stats.h @@ -21,8 +21,8 @@ /* Header file generated by fdesign on Thu Aug 28 12:13:51 2014 */ -#ifndef FD_stats_form_h_ -#define FD_stats_form_h_ +#ifndef _EXECUTABLES_STATS_H_ +#define _EXECUTABLES_STATS_H_ #include @@ -43,4 +43,4 @@ typedef struct { extern FD_stats_form *create_form_stats_form( void ); -#endif /* FD_stats_form_h_ */ +#endif /* _EXECUTABLES_STATS_H_ */ diff --git a/executables/thread-common.h b/executables/thread-common.h index 6f3af3cfc0..0aaeb3c30e 100644 --- a/executables/thread-common.h +++ b/executables/thread-common.h @@ -3,7 +3,7 @@ #include "PHY/defs_common.h" -THREAD_STRUCT thread_struct; +extern THREAD_STRUCT thread_struct; static inline void set_parallel_conf(char *parallel_conf) { mapping config[]= { diff --git a/executables/threads_t.h b/executables/threads_t.h index 0671f40988..c4b233ccc9 100644 --- a/executables/threads_t.h +++ b/executables/threads_t.h @@ -1,5 +1,5 @@ -#ifndef _THREADS_T_H_ -#define _THREADS_T_H_ +#ifndef _EXECUTABLES_THREADS_T_H_ +#define _EXECUTABLES_THREADS_T_H_ typedef struct threads_s { int main; @@ -18,4 +18,4 @@ typedef struct threads_s { //int dlsch_td1_three; } threads_t; -#endif /* _THREADS_T_H_ */ +#endif /* _EXECUTABLES_THREADS_T_H_ */ diff --git a/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8448_maxit_5.txt b/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8448_maxit_5.txt new file mode 100644 index 0000000000..2983268dac --- /dev/null +++ b/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8448_maxit_5.txt @@ -0,0 +1,64 @@ +SNR BLER BER UNCODED_BER ENCODER_MEAN ENCODER_STD ENCODER_MAX DECODER_TIME_MEAN DECODER_TIME_STD DECODER_TIME_MAX DECODER_ITER_MEAN DECODER_ITER_STD DECODER_ITER_MAX +-2.000000 1.000000 0.346185 0.258473 44.551218 31.688925 357.883903 217.655668 12.810778 326.852166 5.000000 0.000000 5 +-1.900000 1.000000 0.345395 0.256275 40.787109 4.190954 65.926488 215.687102 4.300128 230.585721 5.000000 0.000000 5 +-1.800000 1.000000 0.343100 0.253634 40.748628 3.912915 56.669470 215.314020 4.139156 227.806468 5.000000 0.000000 5 +-1.700000 1.000000 0.341806 0.250634 40.550845 3.347808 56.032851 216.839001 5.959734 244.483352 5.000000 0.000000 5 +-1.600000 1.000000 0.339245 0.248129 40.457158 3.735092 56.853508 215.747244 4.995522 242.867659 5.000000 0.000000 5 +-1.500000 1.000000 0.337230 0.245763 41.178595 4.297429 56.265874 215.785600 4.151781 227.795995 5.000000 0.000000 5 +-1.400000 1.000000 0.335131 0.243311 39.915221 2.739586 55.454917 216.866764 6.547848 251.528327 5.000000 0.000000 5 +-1.300000 1.000000 0.333085 0.240664 40.119215 3.044973 55.978253 216.208443 4.459816 228.810686 5.000000 0.000000 5 +-1.200000 1.000000 0.330664 0.238769 40.507713 2.998241 55.701876 215.868796 3.778455 226.049304 5.000000 0.000000 5 +-1.100000 1.000000 0.329130 0.235812 41.038895 4.522472 56.760814 215.654663 4.746822 236.021980 5.000000 0.000000 5 +-1.000000 1.000000 0.325980 0.233534 41.067622 4.626711 57.444142 215.260535 3.481966 225.512853 5.000000 0.000000 5 +-0.900000 1.000000 0.323823 0.230863 40.683316 3.689159 56.208182 215.560917 5.180017 243.603452 5.000000 0.000000 5 +-0.800000 1.000000 0.321004 0.228222 41.643513 4.717568 58.502452 215.630891 4.283475 238.574145 5.000000 0.000000 5 +-0.700000 1.000000 0.317983 0.225520 41.214547 3.941824 56.054211 215.910346 4.375081 227.444626 5.000000 0.000000 5 +-0.600000 1.000000 0.316243 0.222903 40.834442 4.370416 56.765508 215.153296 3.617927 226.280086 5.000000 0.000000 5 +-0.500000 1.000000 0.312886 0.220473 40.178174 4.185502 64.657291 219.647151 4.454154 236.473446 5.000000 0.000000 5 +-0.400000 1.000000 0.309757 0.217536 40.240385 3.172484 55.751563 217.761119 3.900779 228.757195 5.000000 0.000000 5 +-0.300000 1.000000 0.305464 0.215229 40.852271 3.761739 56.158869 217.830497 4.087453 230.237764 5.000000 0.000000 5 +-0.200000 1.000000 0.302919 0.212364 40.531166 3.688281 56.426841 217.657657 5.498697 253.516146 5.000000 0.000000 5 +-0.100000 1.000000 0.298246 0.209310 41.058364 4.140510 59.959571 217.519279 4.087389 228.768313 5.000000 0.000000 5 +0.000000 1.000000 0.294110 0.207107 40.436486 3.604369 55.788895 217.853044 4.012624 236.118036 5.000000 0.000000 5 +0.100000 1.000000 0.288139 0.204033 40.603738 4.045866 57.560760 217.046816 4.583841 244.429411 5.000000 0.000000 5 +0.200000 1.000000 0.285604 0.201954 40.494607 3.886199 59.431970 217.322824 4.080988 233.317513 5.000000 0.000000 5 +0.300000 1.000000 0.278478 0.198929 40.311327 3.452837 56.124657 217.319394 4.434358 232.534720 5.000000 0.000000 5 +0.400000 1.000000 0.270992 0.196299 40.649243 3.415612 56.204178 218.079445 4.990947 245.055337 5.000000 0.000000 5 +0.500000 1.000000 0.263944 0.193661 40.464299 3.622703 56.602842 218.555364 3.936432 229.481159 5.000000 0.000000 5 +0.600000 1.000000 0.256340 0.191194 40.200314 2.474984 53.432412 216.547260 3.695211 227.198078 5.000000 0.000000 5 +0.700000 1.000000 0.251578 0.188606 40.111945 3.029821 54.900896 216.581752 4.247622 237.358365 5.000000 0.000000 5 +0.800000 1.000000 0.234558 0.184742 39.533282 1.182169 42.753097 215.462335 2.960246 226.716604 5.000000 0.000000 5 +0.900000 1.000000 0.225915 0.182691 39.851294 1.108193 42.180342 216.404194 4.450720 228.482353 5.000000 0.000000 5 +1.000000 1.000000 0.216180 0.179994 40.721936 3.302539 56.032206 217.082196 4.599188 227.979232 5.000000 0.000000 5 +1.100000 1.000000 0.203481 0.177332 41.006217 3.798207 56.014901 216.204345 4.292145 227.297386 5.000000 0.000000 5 +1.200000 1.000000 0.188297 0.174121 40.739289 3.269948 56.653507 216.585873 6.250858 251.207034 5.000000 0.000000 5 +1.300000 1.000000 0.172624 0.171622 41.215540 4.783342 55.692883 215.885639 3.629370 226.473280 5.000000 0.000000 5 +1.400000 1.000000 0.156483 0.169110 40.289903 3.749338 56.290861 215.663761 4.176366 225.824735 5.000000 0.000000 5 +1.500000 1.000000 0.136293 0.165692 42.208932 6.070189 69.182665 216.390504 4.816283 235.417446 5.000000 0.000000 5 +1.600000 1.000000 0.125127 0.163325 40.890581 3.941185 56.491504 215.752348 4.426511 226.425984 5.000000 0.000000 5 +1.700000 1.000000 0.104593 0.159971 41.263557 4.128935 57.062514 217.284932 5.311288 249.647163 5.000000 0.000000 5 +1.800000 1.000000 0.091397 0.157460 40.273078 3.062810 55.546913 217.252505 6.331426 251.175692 5.000000 0.000000 5 +1.900000 1.000000 0.078256 0.154628 40.407489 3.419342 56.316166 216.967648 4.712664 245.093313 5.000000 0.000000 5 +2.000000 1.000000 0.065221 0.152571 40.660365 4.317854 57.537407 216.198346 4.991856 245.173269 5.000000 0.000000 5 +2.100000 1.000000 0.053694 0.148885 40.355654 4.062614 60.051963 215.797667 4.447252 236.221454 5.000000 0.000000 5 +2.200000 1.000000 0.042182 0.146229 40.613562 4.124655 56.201536 216.117304 4.060825 227.115987 5.000000 0.000000 5 +2.300000 1.000000 0.034334 0.143612 40.465884 3.541452 55.067611 215.575953 4.891719 244.546802 5.000000 0.000000 5 +2.400000 1.000000 0.026641 0.140869 41.074690 4.697458 61.619188 216.069185 4.700827 233.830937 5.000000 0.000000 5 +2.500000 1.000000 0.019976 0.138112 40.766971 4.274128 58.871741 215.761570 5.633731 249.753931 5.000000 0.000000 5 +2.600000 1.000000 0.012826 0.135122 40.559343 2.952804 54.017706 215.835161 4.039993 226.822103 5.000000 0.000000 5 +2.700000 1.000000 0.010550 0.132915 40.985193 3.330639 55.013950 215.975836 4.240744 227.040703 5.000000 0.000000 5 +2.800000 1.000000 0.007327 0.130133 39.778804 3.002485 56.610555 216.462786 7.082268 265.051418 5.000000 0.000000 5 +2.900000 1.000000 0.004038 0.126763 40.327795 3.934211 55.515352 215.982666 4.626198 230.696124 5.000000 0.000000 5 +3.000000 1.000000 0.003087 0.124336 40.337807 3.537021 55.101627 215.468662 4.177203 230.789145 5.000000 0.000000 5 +3.100000 1.000000 0.001576 0.121689 39.812195 3.116738 55.422687 215.797778 4.091192 225.897780 5.000000 0.000000 5 +3.200000 0.980000 0.001000 0.118928 39.853764 2.871322 56.405555 215.562722 4.187466 232.598421 5.000000 0.000000 5 +3.300000 0.960000 0.000623 0.116065 40.440328 3.580650 56.738889 216.165848 4.735158 240.329999 5.000000 0.000000 5 +3.400000 0.850000 0.000303 0.113505 40.974107 4.291544 56.280236 215.889562 4.448049 237.556780 5.000000 0.000000 5 +3.500000 0.690000 0.000152 0.111010 41.508631 4.251791 56.198873 216.740295 4.889693 242.922934 5.000000 0.000000 5 +3.600000 0.530000 0.000102 0.108493 40.065231 3.643794 57.120823 216.887338 5.242621 250.003843 5.000000 0.000000 5 +3.700000 0.320000 0.000043 0.105612 40.462159 4.162383 56.782173 216.465615 3.846314 227.022697 5.000000 0.000000 5 +3.800000 0.210000 0.000032 0.103084 42.192455 6.207380 64.648964 217.030913 4.482820 228.095918 5.000000 0.000000 5 +3.900000 0.110000 0.000013 0.100391 40.640286 3.715782 55.922914 217.726055 4.553212 236.362804 5.000000 0.000000 5 +4.000000 0.050000 0.000006 0.097518 40.437760 2.838308 54.764308 218.230040 4.309275 237.932625 5.000000 0.000000 5 +4.100000 0.020000 0.000002 0.095436 41.347934 4.608500 64.182062 217.408836 4.385757 228.219627 5.000000 0.000000 5 +4.200000 0.000000 0.000000 0.092396 40.782371 3.621708 55.984245 217.579878 4.102149 228.145363 5.000000 0.000000 5 diff --git a/nfapi/CHANGES.md b/nfapi/CHANGES.md new file mode 100644 index 0000000000..4dc68c6ff8 --- /dev/null +++ b/nfapi/CHANGES.md @@ -0,0 +1,2 @@ +# Changelog + diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 59857659c1..4edbeee342 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -30,12 +30,13 @@ #include "debug.h" #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi_pnf_interface.h" +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" + #include "nfapi.h" #include "nfapi_pnf.h" #include "common/ran_context.h" #include "openair2/PHY_INTERFACE/phy_stub_UE.h" -//#include "openair1/PHY/vars.h" -extern RAN_CONTEXT_t RC; #include #include @@ -47,11 +48,19 @@ extern RAN_CONTEXT_t RC; #include #include "fapi_stub.h" -//#include "fapi_l1.h" + #include "common/utils/LOG/log.h" #include "PHY/INIT/phy_init.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" +#include "openair1/SCHED_NR/fapi_nr_l1.h" +#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" +#include "openair1/PHY/defs_gNB.h" +#include +#include +#include +#include "nfapi/open-nFAPI/pnf/inc/pnf_p7.h" #define NUM_P5_PHY 2 @@ -59,33 +68,23 @@ extern RAN_CONTEXT_t RC; extern void phy_init_RU(RU_t *); extern int config_sync_var; +extern RAN_CONTEXT_t RC; extern pthread_cond_t nfapi_sync_cond; extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; extern int sync_var; -char uecap_xer_in; - -extern void init_eNB_afterRU(void); -extern void init_UE_stub(int nb_inst,int,int); -extern void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB, int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu); -extern void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame,uint8_t subframe,uint8_t srs_present); -extern void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t codeword_index, uint8_t *sdu); -extern void handle_nfapi_hi_dci0_dci_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu); -extern void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu); -extern void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t *sdu); - - nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus] - +uint8_t nr_tx_pdus[32][16][4096]; +nfapi_nr_pdu_t *tx_data_request[1023][20][10]; //[frame][slot][max_num_pdus] uint8_t tx_pdus[32][8][4096]; nfapi_ue_release_request_body_t release_rntis; uint16_t phy_antenna_capability_values[] = { 1, 2, 4, 8, 16 }; -nfapi_pnf_param_response_t g_pnf_param_resp; +nfapi_nr_pnf_param_response_t g_pnf_param_resp; nfapi_pnf_p7_config_t *p7_config_g = NULL; @@ -248,6 +247,63 @@ void *pnf_p7_thread_start(void *ptr) { return 0; } +void *pnf_nr_p7_thread_start(void *ptr) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P7 THREAD %s\n", __FUNCTION__); + pnf_set_thread_priority(79); + nfapi_pnf_p7_config_t *config = (nfapi_pnf_p7_config_t *)ptr; + nfapi_nr_pnf_p7_start(config); + return 0; +} + +int pnf_nr_param_request(nfapi_pnf_config_t *config, nfapi_nr_pnf_param_request_t *req) { + printf("[PNF] pnf param request\n"); + nfapi_nr_pnf_param_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE; + resp.error_code = NFAPI_MSG_OK; + pnf_info *pnf = (pnf_info *)(config->user_data); + resp.pnf_param_general.tl.tag = NFAPI_PNF_PARAM_GENERAL_TAG; + resp.pnf_param_general.nfapi_sync_mode = pnf->sync_mode; + resp.pnf_param_general.location_mode = pnf->location_mode; + resp.pnf_param_general.dl_config_timing = pnf->dl_config_timing; + resp.pnf_param_general.tx_timing = pnf->tx_timing; + resp.pnf_param_general.ul_config_timing = pnf->ul_config_timing; + resp.pnf_param_general.hi_dci0_timing = pnf->hi_dci0_timing; + resp.pnf_param_general.maximum_number_phys = pnf->max_phys; + resp.pnf_param_general.maximum_total_bandwidth = pnf->max_total_bw; + resp.pnf_param_general.maximum_total_number_dl_layers = pnf->max_total_dl_layers; + resp.pnf_param_general.maximum_total_number_ul_layers = pnf->max_total_ul_layers; + resp.pnf_param_general.shared_bands = pnf->shared_bands; + resp.pnf_param_general.shared_pa = pnf->shared_pa; + resp.pnf_param_general.maximum_total_power = pnf->max_total_power; + resp.pnf_phy.tl.tag = NFAPI_PNF_PHY_TAG; + resp.pnf_phy.number_of_phys = 1; + + for(int i = 0; i < 1; ++i) { + resp.pnf_phy.phy[i].phy_config_index = pnf->phys[i].index; + resp.pnf_phy.phy[i].downlink_channel_bandwidth_supported = pnf->phys[i].dl_channel_bw_support; + resp.pnf_phy.phy[i].uplink_channel_bandwidth_supported = pnf->phys[i].ul_channel_bw_support; + resp.pnf_phy.phy[i].number_of_dl_layers_supported = pnf->phys[i].num_dl_layers_supported; + resp.pnf_phy.phy[i].number_of_ul_layers_supported = pnf->phys[i].num_ul_layers_supported; + resp.pnf_phy.phy[i].maximum_3gpp_release_supported = pnf->phys[i].release_supported; + resp.pnf_phy.phy[i].nmm_modes_supported = pnf->phys[i].nmm_modes_supported; + resp.pnf_phy.phy[i].number_of_rfs = 2; + + for(int j = 0; j < 1; ++j) { + resp.pnf_phy.phy[i].rf_config[j].rf_config_index = pnf->phys[i].rfs[j]; + } + + resp.pnf_phy.phy[i].number_of_rf_exclusions = 0; + + for(int j = 0; j < 0; ++j) { + resp.pnf_phy.phy[i].excluded_rf_config[j].rf_config_index = pnf->phys[i].excluded_rfs[j]; + } + } + nfapi_nr_pnf_pnf_param_resp(config, &resp); + return 0; +} + + int pnf_param_request(nfapi_pnf_config_t *config, nfapi_pnf_param_request_t *req) { printf("[PNF] pnf param request\n"); nfapi_pnf_param_response_t resp; @@ -413,6 +469,21 @@ int pnf_config_request(nfapi_pnf_config_t *config, nfapi_pnf_config_request_t *r return 0; } +int pnf_nr_config_request(nfapi_pnf_config_t *config, nfapi_nr_pnf_config_request_t *req) { + printf("[PNF] pnf config request\n"); + pnf_info *pnf = (pnf_info *)(config->user_data); + phy_info *phy = pnf->phys; + phy->id = req->pnf_phy_rf_config.phy_rf_config[0].phy_id; + printf("[PNF] pnf config request assigned phy_id %d to phy_config_index %d\n", phy->id, req->pnf_phy_rf_config.phy_rf_config[0].phy_config_index); + nfapi_nr_pnf_config_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE; + resp.error_code = NFAPI_MSG_OK; + nfapi_nr_pnf_pnf_config_resp(config, &resp); + printf("[PNF] Sent pnf_config_resp\n"); + return 0; +} + void nfapi_send_pnf_start_resp(nfapi_pnf_config_t *config, uint16_t phy_id) { printf("Sending NFAPI_START_RESPONSE config:%p phy_id:%d\n", config, phy_id); nfapi_start_response_t start_resp; @@ -423,6 +494,16 @@ void nfapi_send_pnf_start_resp(nfapi_pnf_config_t *config, uint16_t phy_id) { nfapi_pnf_start_resp(config, &start_resp); } +void nfapi_nr_send_pnf_start_resp(nfapi_pnf_config_t *config, uint16_t phy_id) { + printf("Sending NFAPI_START_RESPONSE config:%p phy_id:%d\n", config, phy_id); + nfapi_nr_start_response_scf_t start_resp; + memset(&start_resp, 0, sizeof(start_resp)); + start_resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE; + start_resp.header.phy_id = phy_id; + start_resp.error_code = NFAPI_MSG_OK; + nfapi_nr_pnf_start_resp(config, &start_resp); +} + int pnf_start_request(nfapi_pnf_config_t *config, nfapi_pnf_start_request_t *req) { printf("Received NFAPI_PNF_START_REQUEST\n"); pnf_info *pnf = (pnf_info *)(config->user_data); @@ -441,6 +522,24 @@ int pnf_start_request(nfapi_pnf_config_t *config, nfapi_pnf_start_request_t *req return 0; } +int pnf_nr_start_request(nfapi_pnf_config_t *config, nfapi_nr_pnf_start_request_t *req) { + printf("Received NFAPI_PNF_START_REQUEST\n"); + pnf_info *pnf = (pnf_info *)(config->user_data); + // start all phys that have been configured + phy_info *phy = pnf->phys; + + if(phy->id != 0) { + nfapi_nr_pnf_start_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE; + resp.error_code = NFAPI_MSG_OK; + nfapi_nr_pnf_pnf_start_resp(config, &resp); + printf("[PNF] Sent NFAPI_PNF_START_RESP\n"); + } + + return 0; +} + int pnf_stop_request(nfapi_pnf_config_t *config, nfapi_pnf_stop_request_t *req) { printf("[PNF] Received NFAPI_PNF_STOP_REQ\n"); nfapi_pnf_stop_response_t resp; @@ -476,7 +575,228 @@ int param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi return 0; } -int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_config_request_t *req) { +int nr_param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_param_request_scf_t *req) { + printf("[PNF] Received NFAPI_PARAM_REQUEST phy_id:%d\n", req->header.phy_id); + //pnf_info* pnf = (pnf_info*)(config->user_data); + nfapi_nr_param_response_scf_t nfapi_resp; + pnf_info *pnf = (pnf_info *)(config->user_data); + memset(&nfapi_resp, 0, sizeof(nfapi_resp)); + nfapi_resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE; + nfapi_resp.header.phy_id = req->header.phy_id; + nfapi_resp.error_code = 0; // DJP - what value??? + struct sockaddr_in pnf_p7_sockaddr; + + // ASSIGN TAGS + { + nfapi_resp.cell_param.release_capability.tl.tag = NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.cell_param.phy_state.tl.tag = NFAPI_NR_PARAM_TLV_PHY_STATE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.cell_param.skip_blank_dl_config.tl.tag = NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.cell_param.skip_blank_ul_config.tl.tag = NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.cell_param.num_config_tlvs_to_report .tl.tag = NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.cyclic_prefix.tl.tag = NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.supported_subcarrier_spacings_dl.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.supported_bandwidth_dl.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.supported_subcarrier_spacings_ul.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.supported_bandwidth_ul.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.cce_mapping_type.tl.tag = NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot.tl.tag = NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.coreset_precoder_granularity_coreset.tl.tag = NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.pdcch_mu_mimo.tl.tag = NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.pdcch_precoder_cycling.tl.tag = NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.max_pdcch_per_slot.tl.tag = NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pucch_param.pucch_formats.tl.tag = NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pucch_param.max_pucchs_per_slot.tl.tag = NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_mapping_type.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_dmrs_additional_pos.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_allocation_types.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_vrb_to_prb_mapping.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_cbg.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_dmrs_config_types.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.max_number_mimo_layers_pdsch.tl.tag = NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.max_mu_mimo_users_dl.tl.tag = NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_data_in_dmrs_symbols.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.premption_support.tl.tag = NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_non_slot_support.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.uci_mux_ulsch_in_pusch.tl.tag = NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.uci_only_pusch.tl.tag = NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_frequency_hopping.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_dmrs_config_types.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_dmrs_max_len.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_dmrs_additional_pos.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_cbg.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_mapping_type.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_allocation_types.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_vrb_to_prb_mapping.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_max_ptrs_ports.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.max_pduschs_tbs_per_slot.tl.tag = NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.max_number_mimo_layers_non_cb_pusch.tl.tag = NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.supported_modulation_order_ul.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.max_mu_mimo_users_ul.tl.tag = NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.dfts_ofdm_support.tl.tag = NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_aggregation_factor.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.prach_param.prach_long_formats.tl.tag = NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.prach_param.prach_short_formats.tl.tag = NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.prach_param.prach_restricted_sets.tl.tag = NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.prach_param.max_prach_fd_occasions_in_a_slot.tl.tag = NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.measurement_param.rssi_measurement_support.tl.tag = NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_vnf_address_ipv6.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_pnf_address_ipv6.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_pnf_port.tl.tag = NFAPI_NR_NFAPI_P7_PNF_PORT_TAG; + nfapi_resp.num_tlv++; +/* + nfapi_resp.nfapi_config.dl_ue_per_sf.tl.tag = NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.ul_ue_per_sf.tl.tag = NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.rf_bands.tl.tag = NFAPI_NR_NFAPI_RF_BANDS_TAG; + nfapi_resp.num_tlv++; + nfapi_resp.nfapi_config.max_transmit_power.tl.tag = NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG; + nfapi_resp.num_tlv++; +*/ + nfapi_resp.nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.timing_info_mode.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; + nfapi_resp.num_tlv++; + } + + nfapi_resp.nfapi_config.p7_pnf_port.value = 32123; //pnf->phys[0].local_port; DJP - hard code alert!!!! FIXME TODO + nfapi_resp.num_tlv++; + pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(pnf->phys[0].local_addr); + + memcpy(nfapi_resp.nfapi_config.p7_pnf_address_ipv4.address, &pnf_p7_sockaddr.sin_addr.s_addr, 4); + nfapi_resp.num_tlv++; + // P7 PNF Port + printf("TAG value :%d",nfapi_resp.cell_param.phy_state.tl.tag); + nfapi_nr_pnf_param_resp(config, &nfapi_resp); + + printf("[PNF] Sent NFAPI_PNF_PARAM_RESPONSE phy_id:%d number_of_tlvs:%u\n", req->header.phy_id, nfapi_resp.num_tlv); + printf("[PNF] param request .. exit\n"); + return 0; +} + +int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_config_request_t *req) +{ printf("[PNF] Received NFAPI_CONFIG_REQ phy_id:%d\n", req->header.phy_id); pnf_info *pnf = (pnf_info *)(config->user_data); uint8_t num_tlv = 0; @@ -657,8 +977,7 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap phy_config_request(&phy_config); dump_frame_parms(fp); } - - phy_info->remote_port = req->nfapi_config.p7_vnf_port.value; + phy_info->remote_port = req->nfapi_config.p7_vnf_port.value; struct sockaddr_in vnf_p7_sockaddr; memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(req->nfapi_config.p7_vnf_address_ipv4.address[0]), 4); phy_info->remote_addr = inet_ntoa(vnf_p7_sockaddr.sin_addr); @@ -678,6 +997,100 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap return 0; } +int nr_config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_config_request_scf_t *req) +{ + printf("[PNF] Received NFAPI_CONFIG_REQ phy_id:%d\n", req->header.phy_id); + pnf_info *pnf = (pnf_info *)(config->user_data); + uint8_t num_tlv = 0; + //struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; + // In the case of nfapi_mode = 3 (UE = PNF) we should not have dependency on any eNB var. So we aim + // to keep only the necessary just to keep the nfapi FSM rolling by sending a dummy response. + NR_DL_FRAME_PARMS *fp; + + if (NFAPI_MODE!=NFAPI_UE_STUB_PNF) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + fp = &gNB->frame_parms; + } else { + fp = (NR_DL_FRAME_PARMS *) malloc(sizeof(NR_DL_FRAME_PARMS)); + } + + phy_info *phy_info = pnf->phys; + + printf("\nTiming window tag: %d\n",NFAPI_NR_NFAPI_TIMING_WINDOW_TAG); + if(req->nfapi_config.timing_window.tl.tag == NFAPI_NR_NFAPI_TIMING_WINDOW_TAG) { + phy_info->timing_window = req->nfapi_config.timing_window.value; + printf("Phy_info:Timing window:%u NFAPI_CONFIG:timing_window:%u\n", phy_info->timing_window, req->nfapi_config.timing_window.value); + num_tlv++; + } + + if(req->nfapi_config.timing_info_mode.tl.tag == NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG) { + printf("timing info mode:%d\n", req->nfapi_config.timing_info_mode.value); + phy_info->timing_info_mode = req->nfapi_config.timing_info_mode.value; + num_tlv++; + } else { + phy_info->timing_info_mode = 0; + printf("NO timing info mode provided\n"); + } + //TODO: Read the P7 message offset values + if(req->nfapi_config.timing_info_period.tl.tag == NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG) { + printf("timing info period provided value:%d\n", req->nfapi_config.timing_info_period.value); + phy_info->timing_info_period = req->nfapi_config.timing_info_period.value; + num_tlv++; + } else { + phy_info->timing_info_period = 0; + } + + if(req->carrier_config.dl_bandwidth.tl.tag == NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG) { + phy_info->dl_channel_bw_support = req->carrier_config.dl_bandwidth.value; //rf_config.dl_channel_bandwidth.value; + fp->N_RB_DL = req->carrier_config.dl_bandwidth.value; //rf_config.dl_channel_bandwidth.value; + num_tlv++; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG N_RB_DL:%u\n", __FUNCTION__, fp->N_RB_DL); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() Missing NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG\n", __FUNCTION__); + } + + if(req->carrier_config.uplink_bandwidth.tl.tag == NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG) { + phy_info->ul_channel_bw_support = req->carrier_config.uplink_bandwidth.value; //req->rf_config.ul_channel_bandwidth.value; + fp->N_RB_UL = req->carrier_config.uplink_bandwidth.value; //req->rf_config.ul_channel_bandwidth.value; + num_tlv++; + } + + if (req->cell_config.phy_cell_id.tl.tag == NFAPI_NR_CONFIG_PHY_CELL_ID_TAG) { + fp->Nid_cell = req->cell_config.phy_cell_id.value; //sch_config.physical_cell_id.value; + fp->nushift = fp->Nid_cell%6; + num_tlv++; + } + + if(NFAPI_MODE!=NFAPI_UE_STUB_PNF) { + printf("[PNF] CONFIG_REQUEST[num_tlv:%d] TLVs processed:%d\n", req->num_tlv, num_tlv); + printf("[PNF] Simulating PHY CONFIG - DJP\n"); + NR_PHY_Config_t nr_phy_config; + nr_phy_config.Mod_id = 0; + nr_phy_config.CC_id=0; + nr_phy_config.cfg = req; + nr_phy_config_request(&nr_phy_config); + nr_dump_frame_parms(fp); + } + phy_info->remote_port = req->nfapi_config.p7_vnf_port.value; + struct sockaddr_in vnf_p7_sockaddr; + memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(req->nfapi_config.p7_vnf_address_ipv4.address[0]), 4); + phy_info->remote_addr = inet_ntoa(vnf_p7_sockaddr.sin_addr); + printf("[PNF] %d vnf p7 %s:%d timing %d %d %d\n", phy_info->id, phy_info->remote_addr, phy_info->remote_port, + phy_info->timing_window, phy_info->timing_info_mode, phy_info->timing_info_period); + nfapi_nr_config_response_scf_t nfapi_resp; + memset(&nfapi_resp, 0, sizeof(nfapi_resp)); + nfapi_resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE; + nfapi_resp.header.phy_id = phy_info->id; + nfapi_resp.error_code = 0; // DJP - some value resp->error_code; + nfapi_nr_pnf_config_resp(config, &nfapi_resp); + printf("[PNF] Sent NFAPI_PNF_CONFIG_RESPONSE phy_id:%d\n", phy_info->id); + + if(NFAPI_MODE==NFAPI_UE_STUB_PNF) + free(fp); + + return 0; +} + nfapi_p7_message_header_t *pnf_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) { if(message_id == P7_VENDOR_EXT_REQ) { (*msg_size) = sizeof(vendor_ext_p7_req); @@ -691,6 +1104,74 @@ void pnf_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) { free(header); } +notifiedFIFO_elt_t *l1tx_message_extract(PHY_VARS_gNB *gNB, int frame, int slot) { + notifiedFIFO_elt_t *res; + notifiedFIFO_elt_t *freeRes = NULL; + + // check first message + res = pullTpool(gNB->resp_L1_tx, gNB->threadPool); + processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res); + if (msgTx->slot == slot) { + return res; + } + if (msgTx->slot == -1) { + freeRes = res; + } + + // check second message + pushNotifiedFIFO(gNB->resp_L1_tx,res); + res = pullTpool(gNB->resp_L1_tx, gNB->threadPool); + msgTx = (processingData_L1tx_t *)NotifiedFifoData(res); + if (msgTx->slot == slot) { + return res; + } + if (msgTx->slot == -1) { + freeRes = res; + } + + if (freeRes) { + msgTx = (processingData_L1tx_t *)NotifiedFifoData(res); + msgTx->num_pdsch_slot=0; + msgTx->pdcch_pdu.pdcch_pdu_rel15.numDlDci = 0; + msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci = 0; + msgTx->slot = slot; + msgTx->frame = frame; + return freeRes; + } + pushNotifiedFIFO(gNB->resp_L1_tx,res); + AssertFatal(1==0, "It means both L1 Tx messages are still waiting to be processed. This happens when L1 Tx processing is too slow. Message slot %d, scheduled slot %d\n", + msgTx->slot, slot); +} + +int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_dci_request_t *req) { + + // LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); + + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + + // extract the next available thread message (priority to message with current slot, then free message) + notifiedFIFO_elt_t *res; + res = l1tx_message_extract(gNB, req->SFN, req->Slot); + processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res); + + if (proc ==NULL) + proc = &gNB->proc.L1_proc; + + if (req->numPdus > 0) { + if (req->ul_dci_pdu_list[req->numPdus-1].PDUType == 0) { // copy only the last PDU (PHY can have only one UL PDCCH pdu) + msgTx->ul_pdcch_pdu = req->ul_dci_pdu_list[req->numPdus-1]; // copy the last pdu + } + else { + LOG_E(PHY,"[PNF] UL_DCI_REQ sfn_slot:%d PDU[%d] - unknown pdu type:%d\n", NFAPI_SFNSLOT2DEC(req->SFN, req->Slot), req->numPdus-1, req->ul_dci_pdu_list[req->numPdus-1].PDUType); + } + } + + pushNotifiedFIFO(gNB->resp_L1_tx,res); + + return 0; +} + + int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { if (req->hi_dci0_request_body.number_of_dci == 0 && req->hi_dci0_request_body.number_of_hi == 0) LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); @@ -719,11 +1200,92 @@ int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfa return 0; } -int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { + +int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_dl_tti_request_t *req) { if (RC.ru == 0) { return -1; } + if (RC.gNB == 0) { + return -2; + } + + if (RC.gNB[0] == 0) { + return -3; + } + + if (sync_var != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() Main system not up - is this a dummy subframe?\n", __FUNCTION__); + return -4; + } + + int sfn = req->SFN; + int slot = req->Slot; + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + if (proc==NULL) + proc = &gNB->proc.L1_proc; + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu_list = req->dl_tti_request_body.dl_tti_pdu_list; + + //if (req->dl_tti_request_body.nPDUs) + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d; sfn:%d, slot:%d, nGroup:%u, nPDUs: %u, nUE: %u, PduIdx: %u,\n", + // __FUNCTION__, proc->frame_tx, proc->slot_tx, proc->frame_rx, proc->slot_rx, // TODO: change subframes to slot + // req->SFN, + // req->Slot, + // req->dl_tti_request_body.nGroup, + // req->dl_tti_request_body.nPDUs, + // req->dl_tti_request_body.nUe, + // req->dl_tti_request_body.PduIdx); + + for (int i=0; idl_tti_request_body.nPDUs; i++) { + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sfn/sf:%d PDU[%d] size:%d pdcch_vars->num_dci:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size,pdcch_vars->num_dci); + notifiedFIFO_elt_t *res; + res = l1tx_message_extract(gNB, sfn, slot); + processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res); + + if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE) { + // we trust the scheduler sends only one PDCCH PDU per slot + msgTx->pdcch_pdu = dl_tti_pdu_list[i].pdcch_pdu; // fills the last received PDCCH PDU + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PDU:%d BCH: pdu_index:%u pdu_length:%d sdu_length:%d BCH_SDU:%x,%x,%x\n", __FUNCTION__, i, pdu_index, bch_pdu->bch_pdu_rel8.length, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length, sdu[0], sdu[1], sdu[2]); + handle_nr_nfapi_ssb_pdu(msgTx, sfn, slot, &dl_tti_pdu_list[i]); + gNB->pbch_configured=1; + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) { + nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu = &dl_tti_pdu_list[i].pdsch_pdu; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15_pdu = &pdsch_pdu->pdsch_pdu_rel15; + nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; + + if (tx_data != NULL) { + uint8_t *dlsch_sdu = (uint8_t *)tx_data->TLVs[0].value.direct; + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols); + AssertFatal(msgTx->num_pdsch_slot < gNB->number_of_nr_dlsch_max,"Number of PDSCH PDUs %d exceeded the limit %d\n", + msgTx->num_pdsch_slot,gNB->number_of_nr_dlsch_max); + handle_nr_nfapi_pdsch_pdu(msgTx, pdsch_pdu, dlsch_sdu); + } + else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(sfn,slot), rel15_pdu->pduIndex); + } + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE) { + nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu = &dl_tti_pdu_list[i].csi_rs_pdu; + handle_nfapi_nr_csirs_pdu(msgTx, sfn, slot, csi_rs_pdu); + } + else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() UNKNOWN:%d\n", __FUNCTION__, dl_tti_pdu_list[i].PDUType); + } + pushNotifiedFIFO(gNB->resp_L1_tx,res); + } + + if(req->vendor_extension) + free(req->vendor_extension); + + return 0; +} + + +int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { + if (RC.eNB == 0) { return -2; } @@ -813,6 +1375,35 @@ int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, n return 0; } + + +int pnf_phy_tx_data_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_tx_data_request_t *req) { + uint16_t sfn = req->SFN; + uint16_t slot = req->Slot; + + if (req->Number_of_PDUs == 0) + LOG_D(PHY,"%s() SFN/SLOT:%d%d PDUs:%d\n", __FUNCTION__, sfn, slot, req->Number_of_PDUs); + + //if (req->pdu_list[0].TLVs->tag == NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST) { + for (int i=0; iNumber_of_PDUs; i++) { + // LOG_D(PHY,"%s() SFN/SF:%d%d number_of_pdus:%d [PDU:%d] pdu_length:%d pdu_index:%d num_segments:%d\n", + // __FUNCTION__, + // sfn, sf, + // req->tx_request_body.number_of_pdus, + // i, + // req->tx_request_body.tx_pdu_list[i].pdu_length, + // req->tx_request_body.tx_pdu_list[i].pdu_index, + // req->tx_request_body.tx_pdu_list[i].num_segments + // ); + // tx_request_pdu[sfn][sf][i] = &req->tx_request_body.tx_pdu_list[i]; + tx_data_request[sfn][slot][i] = &req->pdu_list[i]; + } + //} + + return 0; +} + + int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { uint16_t sfn = NFAPI_SFNSF2SFN(req->sfn_sf); uint16_t sf = NFAPI_SFNSF2SF(req->sfn_sf); @@ -838,6 +1429,79 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { return 0; } + + +int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_tti_request_t *req) { + LOG_D(PHY,"[PNF] UL_TTI_REQ recvd, writing into structs, SFN/slot:%d.%d pdu:%d \n", + req->SFN,req->Slot, + req->n_pdus + ); + + if (RC.ru == 0) { + return -1; + } + + if (RC.gNB == 0) { + return -2; + } + + if (RC.gNB[0] == 0) { + return -3; + } + + if (sync_var != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() Main system not up - is this a dummy slot?\n", __FUNCTION__); + return -4; + } + uint16_t curr_sfn = req->SFN; + uint16_t curr_slot = req->Slot; + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + + if (proc==NULL) + proc = &gNB->proc.L1_proc; + + nfapi_nr_ul_tti_request_number_of_pdus_t *ul_tti_pdu_list = req->pdus_list; + + for (int i=0; i< req->n_pdus; i++) { + switch (ul_tti_pdu_list[i].pdu_type) { + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_ulsch(gNB,curr_sfn, curr_slot, &ul_tti_pdu_list[i].pusch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_pucch(gNB,curr_sfn, curr_slot, &ul_tti_pdu_list[i].pucch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_prach(gNB, curr_sfn, curr_slot, &ul_tti_pdu_list[i].prach_pdu); + if (gNB->RU_list[0]->if_south == LOCAL_RF) nr_fill_prach_ru(gNB->RU_list[0], curr_sfn, curr_slot, &ul_tti_pdu_list[i].prach_pdu); + break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() PDU:%i UNKNOWN type :%d\n", __FUNCTION__, i, ul_tti_pdu_list[i].pdu_type); + break; + + } + // //LOG_D(PHY, "%s() sfn/sf:%d PDU[%d] size:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, ul_config_pdu_list[i].pdu_size); + // if ( + // ul_tti_pdu_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE || + // ul_tti_pdu_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE || + // ul_tti_pdu_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE || + // ul_tti_pdu_list[i].pdu_type == NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE + // ) { + // //LOG_D(PHY, "%s() handle_nfapi_ul_pdu() for PDU:%d\n", __FUNCTION__, i); + // // handle_nfapi_ul_pdu(eNB,proc,&ul_config_pdu_list[i],curr_sfn,curr_sf,req->ul_config_request_body.srs_present); + + // // TODO: dont have an NR function for this, also srs_present flag not there + + // } else { + // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() PDU:%i UNKNOWN type :%d\n", __FUNCTION__, i, ul_tti_pdu_list[i].pdu_type); + // } + } + + return 0; +} + int pnf_phy_ul_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", __FUNCTION__, @@ -847,9 +1511,6 @@ int pnf_phy_ul_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, n req->ul_config_request_body.srs_present ); - if (RC.ru == 0) { - return -1; - } if (RC.eNB == 0) { return -2; @@ -989,6 +1650,7 @@ int pnf_sim_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, uint //printf("%s\n", __FUNCTION__); (void)ve; (void)ppWritePackedMsg; + return -1; } @@ -1006,7 +1668,7 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi p7_config->phy_id = phy->phy_id; p7_config->remote_p7_port = phy_info->remote_port; p7_config->remote_p7_addr = phy_info->remote_addr; - p7_config->local_p7_port = 32123; // DJP - good grief cannot seem to get the right answer phy_info->local_port; + p7_config->local_p7_port = 32123;//phy_info->local_port;//50010; // DJP - good grief cannot seem to get the right answer phy_info->local_port; //DJP p7_config->local_p7_addr = (char*)phy_info->local_addr.c_str(); p7_config->local_p7_addr = phy_info->local_addr; printf("[PNF] P7 remote:%s:%d local:%s:%d\n", p7_config->remote_p7_addr, p7_config->remote_p7_port, p7_config->local_p7_addr, p7_config->local_p7_port); @@ -1117,6 +1779,142 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi return 0; } +int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_start_request_scf_t *req) { + printf("[PNF] Received NFAPI_START_REQ phy_id:%d\n", req->header.phy_id); + nfapi_set_trace_level(NFAPI_TRACE_INFO); + pnf_info *pnf = (pnf_info *)(config->user_data); + phy_info *phy_info = pnf->phys; + nfapi_pnf_p7_config_t *p7_config = nfapi_pnf_p7_config_create(); + p7_config->phy_id = phy->phy_id; + p7_config->remote_p7_port = phy_info->remote_port; + p7_config->remote_p7_addr = phy_info->remote_addr; + // TODO: remove this hardcoded port + p7_config->local_p7_port = 32123; // DJP - good grief cannot seem to get the right answer phy_info->local_port; + //DJP p7_config->local_p7_addr = (char*)phy_info->local_addr.c_str(); + p7_config->local_p7_addr = phy_info->local_addr; + printf("[PNF] P7 remote:%s:%d local:%s:%d\n", p7_config->remote_p7_addr, p7_config->remote_p7_port, p7_config->local_p7_addr, p7_config->local_p7_port); + p7_config->user_data = phy_info; + p7_config->malloc = &pnf_allocate; + p7_config->free = &pnf_deallocate; + p7_config->codec_config.allocate = &pnf_allocate; + p7_config->codec_config.deallocate = &pnf_deallocate; + p7_config->trace = &pnf_nfapi_trace; + phy->user_data = p7_config; + p7_config->subframe_buffer_size = phy_info->timing_window; + p7_config->slot_buffer_size = phy_info->timing_window; // TODO: check if correct for NR + printf("subframe_buffer_size configured using phy_info->timing_window:%d\n", phy_info->timing_window); + + if(phy_info->timing_info_mode & 0x1) { + p7_config->timing_info_mode_periodic = 1; + p7_config->timing_info_period = phy_info->timing_info_period; + } + + if(phy_info->timing_info_mode & 0x2) { + p7_config->timing_info_mode_aperiodic = 1; + } + + // NR + p7_config->dl_tti_req_fn = &pnf_phy_dl_tti_req; + p7_config->ul_tti_req_fn = &pnf_phy_ul_tti_req; + p7_config->ul_dci_req_fn = &pnf_phy_ul_dci_req; + p7_config->tx_data_req_fn = &pnf_phy_tx_data_req; + + // LTE + p7_config->dl_config_req = &pnf_phy_dl_config_req; + p7_config->ul_config_req = &pnf_phy_ul_config_req; + p7_config->hi_dci0_req = &pnf_phy_hi_dci0_req; + p7_config->tx_req = &pnf_phy_tx_req; + p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req; + p7_config->ue_release_req = &pnf_phy_ue_release_req; + if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { + p7_config->dl_config_req = &memcpy_dl_config_req; + p7_config->ul_config_req = &memcpy_ul_config_req; + p7_config->hi_dci0_req = &memcpy_hi_dci0_req; + p7_config->tx_req = &memcpy_tx_req; + } else { + p7_config->dl_config_req = &pnf_phy_dl_config_req; + p7_config->ul_config_req = &pnf_phy_ul_config_req; + p7_config->hi_dci0_req = &pnf_phy_hi_dci0_req; + p7_config->tx_req = &pnf_phy_tx_req; + } + + p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req; + memset(&dummy_dl_config_req, 0, sizeof(dummy_dl_config_req)); + dummy_dl_config_req.dl_config_request_body.tl.tag=NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + dummy_dl_config_req.dl_config_request_body.number_pdcch_ofdm_symbols=1; + dummy_dl_config_req.dl_config_request_body.number_dci=0; + dummy_dl_config_req.dl_config_request_body.number_pdu=0; + dummy_dl_config_req.dl_config_request_body.number_pdsch_rnti=0; + dummy_dl_config_req.dl_config_request_body.transmission_power_pcfich=6000; + dummy_dl_config_req.dl_config_request_body.dl_config_pdu_list=0; + memset(&dummy_tx_req, 0, sizeof(dummy_tx_req)); + dummy_tx_req.tx_request_body.number_of_pdus=0; + dummy_tx_req.tx_request_body.tl.tag=NFAPI_TX_REQUEST_BODY_TAG; + dummy_subframe.dl_config_req = &dummy_dl_config_req; + dummy_subframe.tx_req = 0;//&dummy_tx_req; + dummy_subframe.ul_config_req=0; + dummy_subframe.hi_dci0_req=0; + dummy_subframe.lbt_dl_config_req=0; + p7_config->dummy_subframe = dummy_subframe; + p7_config->vendor_ext = &pnf_phy_vendor_ext; + p7_config->allocate_p7_vendor_ext = &pnf_phy_allocate_p7_vendor_ext; + p7_config->deallocate_p7_vendor_ext = &pnf_phy_deallocate_p7_vendor_ext; + p7_config->codec_config.unpack_p7_vendor_extension = &pnf_phy_unpack_p7_vendor_extension; + p7_config->codec_config.pack_p7_vendor_extension = &pnf_phy_pack_p7_vendor_extension; + p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_phy_unpack_vendor_extension_tlv; + p7_config->codec_config.pack_vendor_extension_tlv = &pnf_phy_pack_vendor_extention_tlv; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__); + pthread_t p7_thread; + pthread_create(&p7_thread, NULL, &pnf_nr_p7_thread_start, p7_config); + //((pnf_phy_user_data_t*)(phy_info->fapi->user_data))->p7_config = p7_config; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__); + l1_north_init_gNB(); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] DJP - HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__); + p7_config_g = p7_config; + + // Need to wait for main thread to create RU structures + while(config_sync_var<0) { + usleep(5000000); + printf("[PNF] waiting for OAI to be configured (eNB/RU)\n"); + } + + printf("[PNF] OAI eNB/RU configured\n"); + //printf("[PNF] About to call phy_init_RU() for RC.ru[0]:%p\n", RC.ru[0]); + //phy_init_RU(RC.ru[0]); + printf("[PNF] About to call init_eNB_afterRU()\n"); + + if (NFAPI_MODE!=NFAPI_UE_STUB_PNF) { + init_eNB_afterRU(); + } + + // Signal to main thread that it can carry on - otherwise RU will startup too quickly and it is not initialised + { + pthread_mutex_lock(&nfapi_sync_mutex); + nfapi_sync_var=0; + pthread_cond_broadcast(&nfapi_sync_cond); + pthread_mutex_unlock(&nfapi_sync_mutex); + } + + while(sync_var<0) { + usleep(5000000); + printf("[PNF] waiting for OAI to be started\n"); + } + + printf("[PNF] Sending PNF_START_RESP\n"); + nfapi_nr_send_pnf_start_resp(config, p7_config->phy_id); + printf("[PNF] Sending first P7 slot indication\n"); +#if 1 + nfapi_pnf_p7_slot_ind(p7_config, p7_config->phy_id, 0, 0); + printf("[PNF] Sent first P7 slot ind\n"); +#else + nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // DJP - SFN_SF set to zero - correct??? + printf("[PNF] Sent first P7 subframe ind\n"); +#endif + + + return 0; +} + int measurement_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_measurement_request_t *req) { nfapi_measurement_response_t resp; memset(&resp, 0, sizeof(resp)); @@ -1362,7 +2160,6 @@ int pnf_sim_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, } /*------------------------------------------------------------------------------*/ - void *pnf_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; @@ -1373,18 +2170,76 @@ void *pnf_start_thread(void *ptr) { return (void *)0; } +void *pnf_nr_start_thread(void *ptr) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); + nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; + struct sched_param sp; + sp.sched_priority = 20; + pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp); + nfapi_nr_pnf_start(config); + return (void *)0; +} + +void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { + printf("%s() PNF\n\n\n\n\n\n", __FUNCTION__); + nfapi_setmode(NFAPI_MODE_PNF); // PNF! + + nfapi_pnf_config_t *config = nfapi_pnf_config_create(); + config->vnf_ip_addr = vnf_ip_addr; + config->vnf_p5_port = vnf_p5_port; + pnf.phys[0].udp.enabled = 1; + pnf.phys[0].udp.rx_port = 32123;//pnf_p7_port; + pnf.phys[0].udp.tx_port = vnf_p7_port; + strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr); + strcpy(pnf.phys[0].local_addr, pnf_ip_addr); + printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%d rx:%d]\n", + __FUNCTION__,config->vnf_ip_addr, config->vnf_p5_port, + pnf.phys[0].local_addr, + pnf.phys[0].udp.tx_addr, pnf.phys[0].udp.tx_port, + pnf.phys[0].udp.rx_port); + config->cell_search_req = &cell_search_request; + + + //config->pnf_nr_param_req = &pnf_nr_param_request; + config->pnf_nr_param_req = &pnf_nr_param_request; + config->pnf_nr_config_req = &pnf_nr_config_request; + config->pnf_nr_start_req = &pnf_nr_start_request; + config->pnf_stop_req = &pnf_stop_request; + config->nr_param_req = &nr_param_request; + config->nr_config_req = &nr_config_request; + config->nr_start_req = &nr_start_request; + config->measurement_req = &measurement_request; + config->rssi_req = &rssi_request; + config->broadcast_detect_req = &broadcast_detect_request; + config->system_information_schedule_req = &system_information_schedule_request; + config->system_information_req = &system_information_request; + config->nmm_stop_req = &nmm_stop_request; + config->vendor_ext = &vendor_ext; + config->trace = &pnf_nfapi_trace; + config->user_data = &pnf; + // To allow custom vendor extentions to be added to nfapi + config->codec_config.unpack_vendor_extension_tlv = &pnf_sim_unpack_vendor_extension_tlv; + config->codec_config.pack_vendor_extension_tlv = &pnf_sim_pack_vendor_extention_tlv; + config->allocate_p4_p5_vendor_ext = &pnf_sim_allocate_p4_p5_vendor_ext; + config->deallocate_p4_p5_vendor_ext = &pnf_sim_deallocate_p4_p5_vendor_ext; + config->codec_config.unpack_p4_p5_vendor_extension = &pnf_sim_unpack_p4_p5_vendor_extension; + config->codec_config.pack_p4_p5_vendor_extension = &pnf_sim_pack_p4_p5_vendor_extension; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); + pthread_create(&pnf_start_pthread, NULL, &pnf_nr_start_thread, config); + pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); +} + void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { printf("%s() PNF\n\n\n\n\n\n", __FUNCTION__); if(NFAPI_MODE!=NFAPI_UE_STUB_PNF) { nfapi_setmode(NFAPI_MODE_PNF); // PNF! } - nfapi_pnf_config_t *config = nfapi_pnf_config_create(); config->vnf_ip_addr = vnf_ip_addr; config->vnf_p5_port = vnf_p5_port; pnf.phys[0].udp.enabled = 1; - pnf.phys[0].udp.rx_port = pnf_p7_port; + pnf.phys[0].udp.rx_port = 32123;//pnf_p7_port; pnf.phys[0].udp.tx_port = vnf_p7_port; strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr); strcpy(pnf.phys[0].local_addr, pnf_ip_addr); @@ -1428,7 +2283,7 @@ void oai_subframe_ind(uint16_t sfn, uint16_t sf) { //TODO FIXME - HACK - DJP - using a global to bodge it in if (p7_config_g != NULL && sync_var==0) { - uint16_t sfn_sf_tx = sfn<<4 | sf; + uint16_t sfn_sf_tx = sfn<<4 | sf; if ((sfn % 100 == 0) && sf==0) { struct timespec ts; @@ -1447,6 +2302,26 @@ void oai_subframe_ind(uint16_t sfn, uint16_t sf) { } } +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) { + + //send VNF slot indication, which is aligned with TX thread, so that it can call the scheduler + nfapi_nr_slot_indication_scf_t *ind; + ind = (nfapi_nr_slot_indication_scf_t *) malloc(sizeof(nfapi_nr_slot_indication_scf_t)); + uint8_t slot_ahead = 6; + uint32_t sfn_slot_tx = sfnslot_add_slot(sfn, slot, slot_ahead); + uint16_t sfn_tx = NFAPI_SFNSLOT2SFN(sfn_slot_tx); + uint8_t slot_tx = NFAPI_SFNSLOT2SLOT(sfn_slot_tx); + + ind->sfn = sfn_tx; + ind->slot = slot_tx; + oai_nfapi_nr_slot_indication(ind); + + //copy data from appropriate p7 slot buffers into channel structures for PHY processing + nfapi_pnf_p7_slot_ind(p7_config_g, p7_config_g->phy_id, sfn, slot); + + return; +} + int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) { rach_ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! LOG_D(PHY, "%s() sfn_sf:%d preambles:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(rach_ind->sfn_sf), rach_ind->rach_indication_body.number_of_preambles); @@ -1495,3 +2370,42 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //free(ind.rx_indication_body.rx_pdu_list); return retval; } + +//NR UPLINK INDICATION + +int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { + ind->header.phy_id = 1; + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION; + return nfapi_pnf_p7_nr_slot_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; + return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; + return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION; + return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; + return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION; + return nfapi_pnf_p7_nr_rach_ind(p7_config_g, ind); +} + diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 2c8201737c..b7ebdb36ea 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -19,9 +19,20 @@ * contact@openairinterface.org */ -#if !defined(NFAPI_PNF_H__) -#define NFAPI_PNF_H__ + +extern nfapi_ue_release_request_body_t release_rntis; int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); +void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); + void oai_subframe_ind(uint16_t sfn, uint16_t sf); -#endif +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); +uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset); + +int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); + diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 7ab8be5746..d96829e127 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -33,14 +33,19 @@ #include "nfapi_nr_interface_scf.h" #include "nfapi_vnf_interface.h" +#include "nfapi_vnf.h" #include "nfapi.h" #include "vendor_ext.h" -#include "nfapi_vnf.h" #include "PHY/defs_eNB.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" +#include #include "common/ran_context.h" + +#define TEST + extern RAN_CONTEXT_t RC; extern UL_RCC_IND_t UL_RCC_INFO; @@ -189,11 +194,11 @@ int vnf_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t int vnf_unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMessage, uint8_t *end, void **ve, nfapi_p4_p5_codec_config_t *codec) { return -1; } - +void install_nr_schedule_handlers(NR_IF_Module_t *if_inst); void install_schedule_handlers(IF_Module_t *if_inst); extern int single_thread_flag; -extern void init_eNB_afterRU(void); extern uint16_t sf_ahead; +extern uint16_t slot_ahead; void oai_create_enb(void) { int bodge_counter=0; @@ -231,6 +236,51 @@ void oai_enb_init(void) { init_eNB_afterRU(); } + +void oai_create_gnb(void) { + int bodge_counter=0; + + if (RC.gNB == NULL) { + RC.gNB = (PHY_VARS_gNB **) calloc(1, sizeof(PHY_VARS_gNB *)); + LOG_I(PHY,"gNB L1 structure RC.gNB allocated @ %p\n",RC.gNB); + } + + + if (RC.gNB[0] == NULL) { + RC.gNB[0] = (PHY_VARS_gNB *) calloc(1, sizeof(PHY_VARS_gNB)); + LOG_I(PHY,"[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n",0,RC.gNB[0]); + } + + PHY_VARS_gNB *gNB = RC.gNB[0]; + RC.nb_nr_CC = (int *)malloc(sizeof(int)); // TODO: find a better function to place this in + + gNB->Mod_id = bodge_counter; + gNB->CC_id = bodge_counter; + gNB->abstraction_flag = 0; + gNB->single_thread_flag = 0;//single_thread_flag; + RC.nb_nr_CC[bodge_counter] = 1; + + if (gNB->if_inst==0) { + gNB->if_inst = NR_IF_Module_init(bodge_counter); + } + + + // This will cause phy_config_request to be installed. That will result in RRC configuring the PHY + // that will result in gNB->configured being set to TRUE. + // See we need to wait for that to happen otherwise the NFAPI message exchanges won't contain the right parameter values + if (RC.gNB[0]->if_inst==0 || RC.gNB[0]->if_inst->NR_PHY_config_req==0 || RC.gNB[0]->if_inst->NR_Schedule_response==0) { + printf("RC.gNB[0][0]->if_inst->NR_PHY_config_req is not installed - install it\n"); + install_nr_schedule_handlers(RC.gNB[0]->if_inst); + } + + do { + printf("%s() Waiting for gNB to become configured (by RRC/PHY) - need to wait otherwise NFAPI messages won't contain correct values\n", __FUNCTION__); + usleep(50000); + } while(gNB->configured != 1); + + printf("%s() gNB is now configured\n", __FUNCTION__); +} + int pnf_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { printf("[VNF] pnf connection indication idx:%d\n", p5_idx); oai_create_enb(); @@ -241,6 +291,16 @@ int pnf_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { return 0; } +int pnf_nr_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { + printf("[VNF] pnf connection indication idx:%d\n", p5_idx); + oai_create_gnb(); + nfapi_nr_pnf_param_request_t req; + memset(&req, 0, sizeof(req)); + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST; + nfapi_nr_vnf_pnf_param_req(config, p5_idx, &req); + return 0; +} + int pnf_disconnection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { printf("[VNF] pnf disconnection indication idx:%d\n", p5_idx); vnf_info *vnf = (vnf_info *)(config->user_data); @@ -251,6 +311,42 @@ int pnf_disconnection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { return 0; } +int pnf_nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_param_response_t *resp) { + printf("[VNF] pnf param response idx:%d error:%d\n", p5_idx, resp->error_code); + vnf_info *vnf = (vnf_info *)(config->user_data); + pnf_info *pnf = vnf->pnfs; + + for(int i = 0; i < resp->pnf_phy.number_of_phys; ++i) { + phy_info phy; + memset(&phy,0,sizeof(phy)); + phy.index = resp->pnf_phy.phy[i].phy_config_index; + printf("[VNF] (PHY:%d) phy_config_idx:%d\n", i, resp->pnf_phy.phy[i].phy_config_index); + nfapi_vnf_allocate_phy(config, p5_idx, &(phy.id)); + + for(int j = 0; j < resp->pnf_phy.phy[i].number_of_rfs; ++j) { + printf("[VNF] (PHY:%d) (RF%d) %d\n", i, j, resp->pnf_phy.phy[i].rf_config[j].rf_config_index); + phy.rfs[0] = resp->pnf_phy.phy[i].rf_config[j].rf_config_index; + } + + pnf->phys[0] = phy; + } + nfapi_nr_pnf_config_request_t req; + memset(&req, 0, sizeof(req)); + req.header.message_id = NFAPI_PNF_CONFIG_REQUEST; + req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG; + req.pnf_phy_rf_config.number_phy_rf_config_info = 2; // DJP pnf.phys.size(); + printf("DJP:Hard coded num phy rf to 2\n"); + + for(unsigned i = 0; i < 2; ++i) { + req.pnf_phy_rf_config.phy_rf_config[i].phy_id = pnf->phys[i].id; + req.pnf_phy_rf_config.phy_rf_config[i].phy_config_index = pnf->phys[i].index; + req.pnf_phy_rf_config.phy_rf_config[i].rf_config_index = pnf->phys[i].rfs[0]; + } + + nfapi_nr_vnf_pnf_config_req(config, p5_idx, &req); + return 0; +} + int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_response_t *resp) { printf("[VNF] pnf param response idx:%d error:%d\n", p5_idx, resp->error_code); vnf_info *vnf = (vnf_info *)(config->user_data); @@ -270,7 +366,6 @@ int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_re pnf->phys[0] = phy; } - for(int i = 0; i < resp->pnf_rf.number_of_rfs; ++i) { rf_info rf; memset(&rf,0,sizeof(rf)); @@ -278,7 +373,6 @@ int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_re printf("[VNF] (RF:%d) rf_config_idx:%d\n", i, resp->pnf_rf.rf[i].rf_config_index); pnf->rfs[0] = rf; } - nfapi_pnf_config_request_t req; memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_PNF_CONFIG_REQUEST; @@ -296,6 +390,31 @@ int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_re return 0; } +int pnf_nr_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_config_response_t *resp) { + printf("[VNF] pnf config response idx:%d resp[header[phy_id:%u message_id:%02x message_length:%u]]\n", p5_idx, resp->header.phy_id, resp->header.message_id, resp->header.message_length); + + if(1) { + nfapi_nr_pnf_start_request_t req; + memset(&req, 0, sizeof(req)); + req.header.phy_id = resp->header.phy_id; + req.header.message_id = NFAPI_PNF_START_REQUEST; + nfapi_nr_vnf_pnf_start_req(config, p5_idx, &req); + } else { + // Rather than send the pnf_start_request we will demonstrate + // sending a vendor extention message. The start request will be + // send when the vendor extension response is received + //vnf_info* vnf = (vnf_info*)(config->user_data); + vendor_ext_p5_req req; + memset(&req, 0, sizeof(req)); + req.header.message_id = P5_VENDOR_EXT_REQ; + req.dummy1 = 45; + req.dummy2 = 1977; + nfapi_vnf_vendor_extension(config, p5_idx, &req.header); + } + + return 0; +} + int pnf_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_response_t *resp) { printf("[VNF] pnf config response idx:%d resp[header[phy_id:%u message_id:%02x message_length:%u]]\n", p5_idx, resp->header.phy_id, resp->header.message_id, resp->header.message_length); @@ -321,6 +440,70 @@ int pnf_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_ return 0; } +int wake_gNB_rxtx(PHY_VARS_gNB *gNB, uint16_t sfn, uint16_t slot) { + struct timespec curr_t; + clock_gettime(CLOCK_MONOTONIC,&curr_t); + //printf("\n wake_gNB_rxtx before assignment sfn:%d slot:%d TIME %d.%d",sfn,slot,curr_t.tv_sec,curr_t.tv_nsec); + gNB_L1_proc_t *proc=&gNB->proc; + gNB_L1_rxtx_proc_t *L1_proc= (slot&1)? &proc->L1_proc : &proc->L1_proc_tx; + + NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + //printf("%s(eNB:%p, sfn:%d, sf:%d)\n", __FUNCTION__, eNB, sfn, sf); + //int i; + struct timespec wait; + clock_gettime(CLOCK_REALTIME, &wait); + wait.tv_sec = 0; + wait.tv_nsec +=5000L; + //wait.tv_nsec = 0; + // wake up TX for subframe n+sf_ahead + // lock the TX mutex and make sure the thread is ready + if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { + LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt ); + exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + + { + static uint16_t old_slot = 0; + static uint16_t old_sfn = 0; + proc->slot_rx = old_slot; + proc->frame_rx = old_sfn; + // Try to be 1 frame back + old_slot = slot; + old_sfn = sfn; + //printf("\n wake_gNB_rxtx after assignment sfn:%d slot:%d",proc->frame_rx,proc->slot_rx); + if (old_slot == 0 && old_sfn % 100 == 0) LOG_W( PHY,"[gNB] sfn/slot:%d%d old_sfn/slot:%d%d proc[rx:%d%d]\n", sfn, slot, old_sfn, old_slot, proc->frame_rx, proc->slot_rx); + } + + ++L1_proc->instance_cnt; + //LOG_D( PHY,"[VNF-subframe_ind] sfn/sf:%d:%d proc[frame_rx:%d subframe_rx:%d] L1_proc->instance_cnt_rxtx:%d \n", sfn, sf, proc->frame_rx, proc->subframe_rx, L1_proc->instance_cnt_rxtx); + // We have just received and processed the common part of a subframe, say n. + // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired + // transmitted timestamp of the next TX slot (first). + // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, + // we want to generate subframe (n+N), so TS_tx = TX_rx+N*samples_per_tti, + // and proc->subframe_tx = proc->subframe_rx+sf_ahead + L1_proc->timestamp_tx = proc->timestamp_rx + (slot_ahead *fp->samples_per_subframe); + L1_proc->frame_rx = proc->frame_rx; + L1_proc->slot_rx = proc->slot_rx; + L1_proc->frame_tx = (L1_proc->slot_rx > (19-slot_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; + L1_proc->slot_tx = (L1_proc->slot_rx + slot_ahead)%20; + + //LOG_I(PHY, "sfn/sf:%d%d proc[rx:%d%d] rx:%d%d] About to wake rxtx thread\n\n", sfn, slot, proc->frame_rx, proc->slot_rx, L1_proc->frame_rx, L1_proc->slot_rx); + //printf("\nEntering wake_gNB_rxtx sfn %d slot %d\n",L1_proc->frame_rx,L1_proc->slot_rx); + // the thread can now be woken up + if (pthread_cond_signal(&L1_proc->cond) != 0) { + LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n"); + exit_fun( "ERROR pthread_clond_signal" ); + return(-1); + } + + //LOG_D(PHY,"%s() About to attempt pthread_mutex_unlock\n", __FUNCTION__); + pthread_mutex_unlock( &L1_proc->mutex ); + //LOG_D(PHY,"%s() UNLOCKED pthread_mutex_unlock\n", __FUNCTION__); + return(0); +} + int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) { L1_proc_t *proc=&eNB->proc; L1_rxtx_proc_t *L1_proc= (sf&1)? &proc->L1_proc : &proc->L1_proc_tx; @@ -333,11 +516,11 @@ int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) { // wake up TX for subframe n+sf_ahead // lock the TX mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt ); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } + //if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { + // LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt ); + // exit_fun( "error locking mutex_rxtx" ); + // return(-1); + //} { static uint16_t old_sf = 0; @@ -348,10 +531,41 @@ int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) { old_sf = sf; old_sfn = sfn; - if (old_sf == 0 && old_sfn % 100==0) LOG_W( PHY,"[eNB] sfn/sf:%d%d old_sfn/sf:%d%d proc[rx:%d%d]\n", sfn, sf, old_sfn, old_sf, proc->frame_rx, proc->subframe_rx); + if (old_sf == 0 && old_sfn % 100==0) + LOG_D(PHY, + "[eNB] sfn/sf:%d%d old_sfn/sf:%d%d proc[rx:%d%d]\n", + sfn, + sf, + old_sfn, + old_sf, + proc->frame_rx, + proc->subframe_rx); + } + // wake up TX for subframe n+sf_ahead + // lock the TX mutex and make sure the thread is ready + if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt ); + //exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + static int busy_log_cnt=0; + if(L1_proc->instance_cnt < 0){ + ++L1_proc->instance_cnt; + if(busy_log_cnt!=0){ + LOG_E(MAC,"RCC singal to rxtx frame %d subframe %d busy end %d (frame %d subframe %d)\n",L1_proc->frame_rx,L1_proc->subframe_rx,busy_log_cnt,proc->frame_rx,proc->subframe_rx); + } + busy_log_cnt=0; + }else{ + if(busy_log_cnt==0){ + LOG_E(MAC,"RCC singal to rxtx frame %d subframe %d busy %d (frame %d subframe %d)\n",L1_proc->frame_rx,L1_proc->subframe_rx,L1_proc->instance_cnt,proc->frame_rx,proc->subframe_rx); + } + pthread_mutex_unlock( &L1_proc->mutex ); + busy_log_cnt++; + return(0); } - ++L1_proc->instance_cnt; + pthread_mutex_unlock( &L1_proc->mutex ); + //LOG_D( PHY,"[VNF-subframe_ind] sfn/sf:%d:%d proc[frame_rx:%d subframe_rx:%d] L1_proc->instance_cnt_rxtx:%d \n", sfn, sf, proc->frame_rx, proc->subframe_rx, L1_proc->instance_cnt_rxtx); // We have just received and processed the common part of a subframe, say n. // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired @@ -374,9 +588,6 @@ int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) { return(-1); } - //LOG_D(PHY,"%s() About to attempt pthread_mutex_unlock\n", __FUNCTION__); - pthread_mutex_unlock( &L1_proc->mutex ); - //LOG_D(PHY,"%s() UNLOCKED pthread_mutex_unlock\n", __FUNCTION__); return(0); } @@ -385,9 +596,10 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { - printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); + //printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); if (sync==1 && nfapi_sync_var!=0) { + printf("[VNF] Signal to OAI main code that it can go\n"); pthread_mutex_lock(&nfapi_sync_mutex); nfapi_sync_var=0; @@ -398,6 +610,29 @@ int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { return(0); } + +int phy_slot_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn, uint16_t slot) { + static uint8_t first_time = 1; + + if (first_time) { + printf("[VNF] slot indication %d\n", NFAPI_SFNSLOT2DEC(sfn, slot)); + first_time = 0; + } + + if (RC.gNB && RC.gNB[0]->configured) { + // uint16_t sfn = NFAPI_SFNSF2SFN(sfn_sf); + // uint16_t sf = NFAPI_SFNSF2SF(sfn_sf); + LOG_D(PHY,"[VNF] slot indication sfn:%d sf:%d\n", sfn, slot); + wake_gNB_rxtx(RC.gNB[0], sfn, slot); // DONE: find NR equivalent + } else { + printf("[VNF] %s() RC.gNB:%p\n", __FUNCTION__, RC.gNB); + + if (RC.gNB) printf("RC.gNB[0]->configured:%d\n", RC.gNB[0]->configured); + } + + return 0; +} + int phy_subframe_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) { static uint8_t first_time = 1; @@ -435,6 +670,7 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio } if(index == -1){ LOG_E(MAC,"phy_rach_indication : num of rach reach max \n"); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); return 0; } UL_RCC_INFO.rach_ind[index] = *ind; @@ -499,6 +735,7 @@ int phy_harq_indication(struct nfapi_vnf_p7_config *config, nfapi_harq_indicatio } if(index == -1){ LOG_E(MAC,"phy_harq_indication : num of harq reach max \n"); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); return 0; } UL_RCC_INFO.harq_ind[index] = *ind; @@ -538,6 +775,7 @@ int phy_crc_indication(struct nfapi_vnf_p7_config *config, nfapi_crc_indication_ } if(index == -1){ LOG_E(MAC,"phy_crc_indication : num of crc reach max \n"); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); return 0; } UL_RCC_INFO.crc_ind[index] = *ind; @@ -603,6 +841,7 @@ int phy_rx_indication(struct nfapi_vnf_p7_config *config, nfapi_rx_indication_t } if(index == -1){ LOG_E(MAC,"phy_rx_indication : num of rx reach max \n"); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); return 0; } UL_RCC_INFO.rx_ind[index] = *ind; @@ -686,6 +925,7 @@ int phy_sr_indication(struct nfapi_vnf_p7_config *config, nfapi_sr_indication_t } if(index == -1){ LOG_E(MAC,"phy_sr_indication : num of sr reach max \n"); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); return 0; } UL_RCC_INFO.sr_ind[index] = *ind; @@ -737,6 +977,7 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ } if(index == -1){ LOG_E(MAC,"phy_cqi_indication : num of cqi reach max \n"); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); return 0; } UL_RCC_INFO.cqi_ind[index] = *ind; @@ -773,6 +1014,124 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ return 1; } +//NR phy indication + +int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { + + uint8_t vnf_slot_ahead = 2; + uint32_t vnf_sfn_slot = sfnslot_add_slot(ind->sfn, ind->slot, vnf_slot_ahead); + uint16_t vnf_sfn = NFAPI_SFNSLOT2SFN(vnf_sfn_slot); + uint8_t vnf_slot = NFAPI_SFNSLOT2SLOT(vnf_sfn_slot); //offsetting the vnf from pnf by vnf_slot_head slots + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_sfn; + gNB->UL_INFO.slot = vnf_slot; + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + LOG_D(MAC, "VNF SFN/Slot %d.%d \n", gNB->UL_INFO.frame, gNB->UL_INFO.slot); + + return 1; +} + +int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + gNB->UL_INFO.crc_ind = *ind; + + if (ind->number_crcs > 0) + gNB->UL_INFO.crc_ind.crc_list = malloc(sizeof(nfapi_nr_crc_t)*ind->number_crcs); + + for (int i=0; inumber_crcs; i++) + memcpy(&gNB->UL_INFO.crc_ind.crc_list[i], &ind->crc_list[i], sizeof(ind->crc_list[0])); + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + gNB->UL_INFO.rx_ind = *ind; + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.rx_ind.pdu_list = malloc(sizeof(nfapi_nr_rx_data_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) + memcpy(&gNB->UL_INFO.rx_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + gNB->UL_INFO.uci_ind = *ind; + + if (ind->num_ucis > 0) + gNB->UL_INFO.uci_ind.uci_list = malloc(sizeof(nfapi_nr_uci_t)*ind->num_ucis); + + for (int i=0; inum_ucis; i++) + memcpy(&gNB->UL_INFO.uci_ind.uci_list[i], &ind->uci_list[i], sizeof(ind->uci_list[0])); + //printf("UCI ind written to UL_info: num_ucis: %d, PDU_type : %d. \n", ind->num_ucis, ind->uci_list[0].pdu_type); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + gNB->UL_INFO.srs_ind = *ind; + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.srs_ind.pdu_list = malloc(sizeof(nfapi_nr_srs_indication_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) { + memcpy(&gNB->UL_INFO.srs_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + LOG_D(MAC, "%s() NFAPI SFN/Slot:%d.%d SRS_IND:number_of_pdus:%d UL_INFO:pdus:%d\n", + __FUNCTION__, + ind->sfn,ind->slot, ind->number_of_pdus, gNB->UL_INFO.srs_ind.number_of_pdus + ); + } + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + gNB->UL_INFO.rach_ind = *ind; + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.rach_ind.pdu_list = malloc(sizeof(nfapi_nr_prach_indication_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) { + memcpy(&gNB->UL_INFO.rach_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + LOG_D(MAC, "%s() NFAPI SFN/Slot:%d.%d RACH_IND:number_of_pdus:%d UL_INFO:pdus:%d\n", + __FUNCTION__, + ind->sfn,ind->slot, ind->number_of_pdus, gNB->UL_INFO.rach_ind.number_of_pdus + ); + } + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +//end NR phy indication + int phy_lbt_dl_indication(struct nfapi_vnf_p7_config *config, nfapi_lbt_dl_indication_t *ind) { // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data); //mac_lbt_dl_ind(p7_vnf->mac, ind); @@ -903,6 +1262,14 @@ int vnf_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, uint8_ static pthread_t vnf_start_pthread; static pthread_t vnf_p7_start_pthread; +void *vnf_nr_p7_start_thread(void *ptr) { + printf("%s()\n", __FUNCTION__); + pthread_setname_np(pthread_self(), "VNF_P7"); + nfapi_vnf_p7_config_t *config = (nfapi_vnf_p7_config_t *)ptr; + nfapi_nr_vnf_p7_start(config); + return config; +} + void *vnf_p7_start_thread(void *ptr) { printf("%s()\n", __FUNCTION__); pthread_setname_np(pthread_self(), "VNF_P7"); @@ -913,12 +1280,56 @@ void *vnf_p7_start_thread(void *ptr) { void set_thread_priority(int priority); +void *vnf_nr_p7_thread_start(void *ptr) { + set_thread_priority(79); + vnf_p7_info *p7_vnf = (vnf_p7_info *)ptr; + p7_vnf->config->port = p7_vnf->local_port; + p7_vnf->config->sync_indication = &phy_sync_indication; + p7_vnf->config->slot_indication = &phy_slot_indication; + + p7_vnf->config->harq_indication = &phy_harq_indication; + p7_vnf->config->crc_indication = &phy_crc_indication; + p7_vnf->config->rx_indication = &phy_rx_indication; + p7_vnf->config->rach_indication = &phy_rach_indication; + p7_vnf->config->srs_indication = &phy_srs_indication; + p7_vnf->config->sr_indication = &phy_sr_indication; + p7_vnf->config->cqi_indication = &phy_cqi_indication; + p7_vnf->config->lbt_dl_indication = &phy_lbt_dl_indication; + p7_vnf->config->nb_harq_indication = &phy_nb_harq_indication; + p7_vnf->config->nrach_indication = &phy_nrach_indication; + p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication; + p7_vnf->config->nr_slot_indication = &phy_nr_slot_indication; + p7_vnf->config->nr_rx_data_indication = &phy_nr_rx_data_indication; + p7_vnf->config->nr_uci_indication = &phy_nr_uci_indication; + p7_vnf->config->nr_rach_indication = &phy_nr_rach_indication; + p7_vnf->config->nr_srs_indication = &phy_nr_srs_indication; + p7_vnf->config->malloc = &vnf_allocate; + p7_vnf->config->free = &vnf_deallocate; + p7_vnf->config->trace = &vnf_trace; + p7_vnf->config->vendor_ext = &phy_vendor_ext; + p7_vnf->config->user_data = p7_vnf; + p7_vnf->mac->user_data = p7_vnf; + p7_vnf->config->codec_config.unpack_p7_vendor_extension = &phy_unpack_p7_vendor_extension; + p7_vnf->config->codec_config.pack_p7_vendor_extension = &phy_pack_p7_vendor_extension; + p7_vnf->config->codec_config.unpack_vendor_extension_tlv = &phy_unpack_vendor_extension_tlv; + p7_vnf->config->codec_config.pack_vendor_extension_tlv = &phy_pack_vendor_extension_tlv; + p7_vnf->config->codec_config.allocate = &vnf_allocate; + p7_vnf->config->codec_config.deallocate = &vnf_deallocate; + p7_vnf->config->allocate_p7_vendor_ext = &phy_allocate_p7_vendor_ext; + p7_vnf->config->deallocate_p7_vendor_ext = &phy_deallocate_p7_vendor_ext; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); + pthread_create(&vnf_p7_start_pthread, NULL, &vnf_nr_p7_start_thread, p7_vnf->config); + return 0; +} + void *vnf_p7_thread_start(void *ptr) { set_thread_priority(79); vnf_p7_info *p7_vnf = (vnf_p7_info *)ptr; p7_vnf->config->port = p7_vnf->local_port; p7_vnf->config->sync_indication = &phy_sync_indication; p7_vnf->config->subframe_indication = &phy_subframe_indication; + p7_vnf->config->slot_indication = &phy_slot_indication; + p7_vnf->config->harq_indication = &phy_harq_indication; p7_vnf->config->crc_indication = &phy_crc_indication; p7_vnf->config->rx_indication = &phy_rx_indication; @@ -943,11 +1354,35 @@ void *vnf_p7_thread_start(void *ptr) { p7_vnf->config->codec_config.deallocate = &vnf_deallocate; p7_vnf->config->allocate_p7_vendor_ext = &phy_allocate_p7_vendor_ext; p7_vnf->config->deallocate_p7_vendor_ext = &phy_deallocate_p7_vendor_ext; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); pthread_create(&vnf_p7_start_pthread, NULL, &vnf_p7_start_thread, p7_vnf->config); return 0; } +int pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_start_response_t *resp) { + vnf_info *vnf = (vnf_info *)(config->user_data); + vnf_p7_info *p7_vnf = vnf->p7_vnfs; + pnf_info *pnf = vnf->pnfs; + nfapi_nr_param_request_scf_t req; + printf("[VNF] pnf start response idx:%d config:%p user_data:%p p7_vnf[config:%p thread_started:%d]\n", p5_idx, config, config->user_data, vnf->p7_vnfs[0].config, vnf->p7_vnfs[0].thread_started); + + if(p7_vnf->thread_started == 0) { + pthread_t vnf_p7_thread; + pthread_create(&vnf_p7_thread, NULL, &vnf_nr_p7_thread_start, p7_vnf); + p7_vnf->thread_started = 1; + } else { + // P7 thread already running. + } + + // start all the phys in the pnf. + printf("[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); + memset(&req, 0, sizeof(req)); + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST; + req.header.phy_id = pnf->phys[0].id; + nfapi_nr_vnf_param_req(config, p5_idx, &req); + return 0; +} + int pnf_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_start_response_t *resp) { vnf_info *vnf = (vnf_info *)(config->user_data); vnf_p7_info *p7_vnf = vnf->p7_vnfs; @@ -964,7 +1399,7 @@ int pnf_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_start_re } // start all the phys in the pnf. - printf("[VNF] Sending NFAPI_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); + printf("[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_PARAM_REQUEST; req.header.phy_id = pnf->phys[0].id; @@ -974,6 +1409,69 @@ int pnf_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_start_re extern uint32_t to_earfcn(int eutra_bandP,uint32_t dl_CarrierFreq,uint32_t bw); +int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_response_scf_t *resp) { + + printf("[VNF] Received NFAPI_PARAM_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + vnf_info *vnf = (vnf_info *)(config->user_data); + vnf_p7_info *p7_vnf = vnf->p7_vnfs; + pnf_info *pnf = vnf->pnfs; + phy_info *phy = pnf->phys; + struct sockaddr_in pnf_p7_sockaddr; + nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; // check + phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value; + memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4); + phy->remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr); + // for now just 1 + printf("[VNF] %d.%d pnf p7 %s:%d timing %u %u %u %u\n", p5_idx, phy->id, phy->remote_addr, phy->remote_port, p7_vnf->timing_window, p7_vnf->periodic_timing_period, p7_vnf->aperiodic_timing_enabled, + p7_vnf->periodic_timing_period); + req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST; + req->header.phy_id = phy->id; + printf("[VNF] Send NFAPI_CONFIG_REQUEST\n"); + //printf("\n NR bandP =%d\n",req->nfapi_config.rf_bands.rf_band[0]); + + req->nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG; + req->nfapi_config.p7_vnf_port.value = p7_vnf->local_port; + req->num_tlv++; + printf("[VNF] DJP local_port:%d\n", p7_vnf->local_port); + req->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; + struct sockaddr_in vnf_p7_sockaddr; + vnf_p7_sockaddr.sin_addr.s_addr = inet_addr(p7_vnf->local_addr); + memcpy(&(req->nfapi_config.p7_vnf_address_ipv4.address[0]), &vnf_p7_sockaddr.sin_addr.s_addr, 4); + req->num_tlv++; + printf("[VNF] DJP local_addr:%s\n", p7_vnf->local_addr); + req->nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG; + req->nfapi_config.timing_window.value = p7_vnf->timing_window; + printf("\n[VNF]Timing window tag : %d Timing window:%u\n",NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, p7_vnf->timing_window); + req->num_tlv++; + + if(p7_vnf->periodic_timing_enabled || p7_vnf->aperiodic_timing_enabled) { + req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG; + req->nfapi_config.timing_info_mode.value = (p7_vnf->aperiodic_timing_enabled << 1) | (p7_vnf->periodic_timing_enabled); + req->num_tlv++; + + if(p7_vnf->periodic_timing_enabled) { + req->nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; + req->nfapi_config.timing_info_period.value = p7_vnf->periodic_timing_period; + req->num_tlv++; + } + } +//TODO: Assign tag and value for P7 message offsets +req->nfapi_config.dl_tti_timing_offset.tl.tag = NFAPI_NR_NFAPI_DL_TTI_TIMING_OFFSET; +req->nfapi_config.ul_tti_timing_offset.tl.tag = NFAPI_NR_NFAPI_UL_TTI_TIMING_OFFSET; +req->nfapi_config.ul_dci_timing_offset.tl.tag = NFAPI_NR_NFAPI_UL_DCI_TIMING_OFFSET; +req->nfapi_config.tx_data_timing_offset.tl.tag = NFAPI_NR_NFAPI_TX_DATA_TIMING_OFFSET; + + vendor_ext_tlv_2 ve2; + memset(&ve2, 0, sizeof(ve2)); + ve2.tl.tag = VENDOR_EXT_TLV_2_TAG; + ve2.dummy = 2016; + req->vendor_extension = &ve2.tl; + nfapi_nr_vnf_config_req(config, p5_idx, req); + printf("[VNF] Sent NFAPI_VNF_CONFIG_REQ num_tlv:%u\n",req->num_tlv); + return 0; +} + + int param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_response_t *resp) { printf("[VNF] Received NFAPI_PARAM_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); vnf_info *vnf = (vnf_info *)(config->user_data); @@ -982,7 +1480,7 @@ int param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_response_t phy_info *phy = pnf->phys; struct sockaddr_in pnf_p7_sockaddr; nfapi_config_request_t *req = &RC.mac[0]->config[0]; - phy->remote_port = resp->nfapi_config.p7_pnf_port.value; + phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value; memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4); phy->remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr); // for now just 1 @@ -1028,6 +1526,19 @@ int param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_response_t return 0; } +int nr_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_config_response_scf_t *resp) { + nfapi_nr_start_request_scf_t req; + printf("[VNF] Received NFAPI_CONFIG_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + printf("[VNF] Calling oai_enb_init()\n"); + oai_enb_init(); // TODO: change to gnb + memset(&req, 0, sizeof(req)); + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_REQUEST; + req.header.phy_id = resp->header.phy_id; + nfapi_nr_vnf_start_req(config, p5_idx, &req); + printf("[VNF] Send NFAPI_VNF_START_REQUEST idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + return 0; +} + int config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_config_response_t *resp) { nfapi_start_request_t req; printf("[VNF] Received NFAPI_CONFIG_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); @@ -1051,6 +1562,17 @@ int start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_start_response_t return 0; } +int nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_start_response_scf_t *resp) { + printf("[VNF] Received NFAPI_START_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + vnf_info *vnf = (vnf_info *)(config->user_data); + pnf_info *pnf = vnf->pnfs; + phy_info *phy = pnf->phys; + vnf_p7_info *p7_vnf = vnf->p7_vnfs; + + nfapi_vnf_p7_add_pnf((p7_vnf->config), phy->remote_addr, phy->remote_port, phy->id); + return 0; +} + int vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_p4_p5_message_header_t *msg) { printf("[VNF] %s\n", __FUNCTION__); @@ -1095,6 +1617,13 @@ void vnf_deallocate_p4_p5_vendor_ext(nfapi_p4_p5_message_header_t *header) { nfapi_vnf_config_t *config = 0; +void vnf_nr_start_thread(void *ptr) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); + pthread_setname_np(pthread_self(), "VNF"); + config = (nfapi_vnf_config_t *)ptr; + nfapi_nr_vnf_start(config); +} + void vnf_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); pthread_setname_np(pthread_self(), "VNF"); @@ -1104,7 +1633,57 @@ void vnf_start_thread(void *ptr) { static vnf_info vnf; -/*------------------------------------------------------------------------------*/ +void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { + nfapi_setmode(NFAPI_MODE_VNF); + memset(&vnf, 0, sizeof(vnf)); + memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); + vnf.p7_vnfs[0].timing_window = 30; + vnf.p7_vnfs[0].periodic_timing_enabled = 0; + vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; + vnf.p7_vnfs[0].periodic_timing_period = 10; + vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port); + strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); + //vnf.p7_vnfs[0].local_port = vnf.p7_vnfs[0].local_port; // 50001; // TODO: remove hardcode + vnf.p7_vnfs[0].local_port = 50011; + vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); + nfapi_vnf_config_t *config = nfapi_vnf_config_create(); + config->malloc = malloc; + config->free = free; + config->trace = &vnf_trace; + config->vnf_p5_port = vnf_p5_port; + config->vnf_ipv4 = 1; + config->vnf_ipv6 = 0; + config->pnf_list = 0; + config->phy_list = 0; + + config->pnf_nr_connection_indication = &pnf_nr_connection_indication_cb; + config->pnf_disconnect_indication = &pnf_disconnection_indication_cb; + + config->pnf_nr_param_resp = &pnf_nr_param_resp_cb; + config->pnf_nr_config_resp = &pnf_nr_config_resp_cb; + config->pnf_nr_start_resp = &pnf_nr_start_resp_cb; + config->nr_param_resp = &nr_param_resp_cb; + config->nr_config_resp = &nr_config_resp_cb; + config->nr_start_resp = &nr_start_resp_cb; + config->vendor_ext = &vendor_ext_cb; + config->user_data = &vnf; + // To allow custom vendor extentions to be added to nfapi + config->codec_config.unpack_vendor_extension_tlv = &vnf_unpack_vendor_extension_tlv; + config->codec_config.pack_vendor_extension_tlv = &vnf_pack_vendor_extension_tlv; + config->codec_config.unpack_p4_p5_vendor_extension = &vnf_unpack_p4_p5_vendor_extension; + config->codec_config.pack_p4_p5_vendor_extension = &vnf_pack_p4_p5_vendor_extension; + config->allocate_p4_p5_vendor_ext = &vnf_allocate_p4_p5_vendor_ext; + config->deallocate_p4_p5_vendor_ext = &vnf_deallocate_p4_p5_vendor_ext; + config->codec_config.allocate = &vnf_allocate; + config->codec_config.deallocate = &vnf_deallocate; + memset(&UL_RCC_INFO,0,sizeof(UL_RCC_IND_t)); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); + pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_nr_start_thread, config); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); +} + + void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { nfapi_setmode(NFAPI_MODE_VNF); memset(&vnf, 0, sizeof(vnf)); @@ -1116,7 +1695,8 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port); strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); - vnf.p7_vnfs[0].local_port = 50001; + //vnf.p7_vnfs[0].local_port = vnf.p7_vnfs[0].local_port; // 50001; // TODO: remove hardcode + vnf.p7_vnfs[0].local_port = 50011; vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); nfapi_vnf_config_t *config = nfapi_vnf_config_create(); config->malloc = malloc; @@ -1127,8 +1707,10 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { config->vnf_ipv6 = 0; config->pnf_list = 0; config->phy_list = 0; + config->pnf_connection_indication = &pnf_connection_indication_cb; config->pnf_disconnect_indication = &pnf_disconnection_indication_cb; + config->pnf_param_resp = &pnf_param_resp_cb; config->pnf_config_resp = &pnf_config_resp_cb; config->pnf_start_resp = &pnf_start_resp_cb; @@ -1169,15 +1751,17 @@ int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return retval; } -int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_tti_request_t *dl_config_req) +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { + //LOG_I(PHY, "sfn:%d,slot:%d\n",dl_config_req->SFN,dl_config_req->Slot); + //printf("\nEntering oai_nfapi_nr_dl_config_req sfn:%d,slot:%d\n",dl_config_req->SFN,dl_config_req->Slot); nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; - + dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! int retval = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req); - dl_config_req->dl_tti_request_body.nPDUs = 0; + dl_config_req->dl_tti_request_body.nPDUs = 0; dl_config_req->dl_tti_request_body.nGroup = 0; @@ -1187,6 +1771,23 @@ int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_tti_request_t *dl_config_req) return retval; } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) +{ + nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; + //LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus); + int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); + + if (retval!=0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + tx_data_req->Number_of_PDUs = 0; + } + + return retval; +} + int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; @@ -1204,6 +1805,22 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) return retval; } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { + nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; + //LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi); + int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); + + if (retval!=0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + ul_dci_req->numPdus = 0; + } + + return retval; +} + int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; hi_dci0_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! @@ -1221,6 +1838,26 @@ int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { return retval; } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { + nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + + ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; + + int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); + + if (retval!=0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + // Reset number of PDUs so that it is not resent + ul_tti_req->n_pdus = 0; + ul_tti_req->n_group = 0; + ul_tti_req->n_ulcch = 0; + ul_tti_req->n_ulsch = 0; + } + return retval; +} + int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; ul_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index 4ea26eda12..478956f75c 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -19,9 +19,9 @@ * contact@openairinterface.org */ -#if !defined(NFAPI_VNF_H__) -#define NFAPI_VNF_H__ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port); +void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port); + +uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset); -#endif diff --git a/nfapi/open-nFAPI/common/src/debug.c b/nfapi/open-nFAPI/common/src/debug.c index a45d41d7d7..5d4ad8a194 100644 --- a/nfapi/open-nFAPI/common/src/debug.c +++ b/nfapi/open-nFAPI/common/src/debug.c @@ -1,76 +1,75 @@ -/* - * Copyright 2017 Cisco Systems, Inc. - * - * 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. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MAX_MSG_LENGTH 2096 -#define TRACE_HEADER_LENGTH 44 - -void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...); - -// initialize the trace function to 0 -void (*nfapi_trace_g)(nfapi_trace_level_t level, const char* format, ...) = &nfapi_trace_dbg; - -nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_INFO; -//nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_WARN; - -void nfapi_set_trace_level(nfapi_trace_level_t new_level) -{ - nfapi_trace_level_g = new_level; -} - -void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...) -{ - char trace_buff[MAX_MSG_LENGTH + TRACE_HEADER_LENGTH]; - uint32_t num_chars; - va_list p_args; - struct timeval tv; - pthread_t tid = pthread_self(); - - (void)gettimeofday(&tv, NULL); - - num_chars = (uint32_t)snprintf(trace_buff, TRACE_HEADER_LENGTH, "%04u.%06u: 0x%02x: %10u: ", ((uint32_t)tv.tv_sec) & 0x1FFF, (uint32_t)tv.tv_usec, (uint32_t)level, (uint32_t)tid); - - if (num_chars > TRACE_HEADER_LENGTH) - { - printf("trace_dbg: Error, num_chars is too large: %d", num_chars); - return; - } - - va_start(p_args, format); - if ((num_chars = (uint32_t)vsnprintf(&trace_buff[num_chars], MAX_MSG_LENGTH, format, p_args))) - { - if (level <= NFAPI_TRACE_WARN) - { - printf("%s", trace_buff); - } - printf("%s", trace_buff); - } - va_end(p_args); -} +/* + * Copyright 2017 Cisco Systems, Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_MSG_LENGTH 2096 +#define TRACE_HEADER_LENGTH 44 + +void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...); + +// initialize the trace function to 0 +void (*nfapi_trace_g)(nfapi_trace_level_t level, const char* format, ...) = &nfapi_trace_dbg; + +nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_INFO; +//nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_WARN; + +void nfapi_set_trace_level(nfapi_trace_level_t new_level) +{ + nfapi_trace_level_g = new_level; +} + +void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...) +{ + char trace_buff[MAX_MSG_LENGTH + TRACE_HEADER_LENGTH]; + uint32_t num_chars; + va_list p_args; + struct timeval tv; + pthread_t tid = pthread_self(); + + (void)gettimeofday(&tv, NULL); + + num_chars = (uint32_t)snprintf(trace_buff, TRACE_HEADER_LENGTH, "%04u.%06u: 0x%02x: %10u: ", ((uint32_t)tv.tv_sec) & 0x1FFF, (uint32_t)tv.tv_usec, (uint32_t)level, (uint32_t)tid); + + if (num_chars > TRACE_HEADER_LENGTH) + { + printf("trace_dbg: Error, num_chars is too large: %d", num_chars); + return; + } + + va_start(p_args, format); + if ((num_chars = (uint32_t)vsnprintf(&trace_buff[num_chars], MAX_MSG_LENGTH, format, p_args))) + { + if (level <= NFAPI_TRACE_WARN) + { + printf("%s", trace_buff); + } + printf("%s", trace_buff); + } + va_end(p_args); +} diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h index e1d06335f5..f107b5b973 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h @@ -10,11 +10,11 @@ #define FAPI_NR_MAX_RA_OCCASION_PER_CSIRS 64 // Constants Defined in 38.213 #define FAPI_NR_MAX_CORESET_PER_BWP 3 -#define FAPI_NR_MAX_SS_PER_CORESET 10 +#define FAPI_NR_MAX_SS 10 /// RX_IND -#define FAPI_NR_RX_PDU_TYPE_MIB 0x01 +#define FAPI_NR_RX_PDU_TYPE_SSB 0x01 #define FAPI_NR_RX_PDU_TYPE_SIB 0x02 #define FAPI_NR_RX_PDU_TYPE_DLSCH 0x03 #define FAPI_NR_DCI_IND 0x04 @@ -44,7 +44,9 @@ #define FAPI_NR_DL_CONFIG_TYPE_DCI 0x01 #define FAPI_NR_DL_CONFIG_TYPE_DLSCH 0x02 #define FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH 0x03 - +#define FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH 0x04 +#define FAPI_NR_DL_CONFIG_TYPE_P_DLSCH 0x05 +#define FAPI_NR_DL_CONFIG_TYPES 0x05 #define FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED 0x01 #define FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED 0x02 @@ -55,10 +57,11 @@ /// UL_CONFIG_REQ #define FAPI_NR_UL_CONFIG_LIST_NUM 10 +#define FAPI_NR_UL_CONFIG_TYPE_DONE 0x00 #define FAPI_NR_UL_CONFIG_TYPE_PRACH 0x01 #define FAPI_NR_UL_CONFIG_TYPE_PUCCH 0x02 #define FAPI_NR_UL_CONFIG_TYPE_PUSCH 0x03 #define FAPI_NR_UL_CONFIG_TYPE_SRS 0x04 - +#define FAPI_NR_UL_CONFIG_TYPES 0x04 #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 246ab13e86..0e923931ad 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -16,6 +16,7 @@ #ifndef _FAPI_NR_UE_INTERFACE_H_ #define _FAPI_NR_UE_INTERFACE_H_ +#include #include "stddef.h" #include "platform_types.h" @@ -23,6 +24,7 @@ #include "PHY/impl_defs_nr.h" #define NFAPI_UE_MAX_NUM_CB 8 +#define NFAPI_MAX_NUM_UL_PDU 8 /* typedef unsigned int uint32_t; @@ -100,6 +102,8 @@ typedef struct { typedef struct { + uint8_t harq_pid; + uint8_t ack_nack; uint32_t pdu_length; uint8_t* pdu; } fapi_nr_pdsch_pdu_t; @@ -110,21 +114,15 @@ typedef struct { uint8_t ssb_index; uint8_t ssb_length; uint16_t cell_id; - -} fapi_nr_mib_pdu_t; - -typedef struct { - uint32_t pdu_length; - uint8_t* pdu; - uint32_t sibs_mask; -} fapi_nr_sib_pdu_t; + uint16_t ssb_start_subcarrier; + short rsrp_dBm; +} fapi_nr_ssb_pdu_t; typedef struct { uint8_t pdu_type; union { fapi_nr_pdsch_pdu_t pdsch_pdu; - fapi_nr_mib_pdu_t mib_pdu; - fapi_nr_sib_pdu_t sib_pdu; + fapi_nr_ssb_pdu_t ssb_pdu; }; } fapi_nr_rx_indication_body_t; @@ -155,7 +153,7 @@ typedef struct { uint16_t slot; fapi_nr_tx_config_t tx_config; uint16_t number_of_pdus; - fapi_nr_tx_request_body_t *tx_request_body; + fapi_nr_tx_request_body_t tx_request_body[NFAPI_MAX_NUM_UL_PDU]; } fapi_nr_tx_request_t; /// This struct replaces: @@ -170,6 +168,7 @@ typedef struct { uint8_t prach_format; /// Num RA uint8_t num_ra; + uint8_t prach_slot; uint8_t prach_start_symbol; /// 38.211 (NCS 38.211 6.3.3.1). uint16_t num_cs; @@ -179,91 +178,39 @@ typedef struct { uint8_t restricted_set; /// see TS 38.211 (6.3.3.2). uint16_t freq_msg1; + // When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble + uint8_t ssb_nb_in_ro; // nfapi_nr_ul_beamforming_t beamforming; } fapi_nr_ul_config_prach_pdu; typedef struct { - - pucch_format_nr_t format; /* format 0 1 2 3 4 */ - uint8_t initialCyclicShift; /* x x */ - uint8_t nrofSymbols; /* x x x x x */ - uint8_t startingSymbolIndex; /* x x x x x */ - uint8_t timeDomainOCC; /* x */ - uint8_t nrofPRBs; /* x x */ - uint16_t startingPRB; /* maxNrofPhysicalResourceBlocks = 275 */ - uint8_t occ_length; /* x */ - uint8_t occ_Index; /* x */ - - feature_status_t intraSlotFrequencyHopping; - uint16_t secondHopPRB; - - /* - -- Enabling inter-slot frequency hopping when PUCCH Format 1, 3 or 4 is repeated over multiple slots. - -- The field is not applicable for format 2. - */ - feature_status_t interslotFrequencyHopping; - /* - -- Enabling 2 DMRS symbols per hop of a PUCCH Format 3 or 4 if both hops are more than X symbols when FH is enabled (X=4). - -- Enabling 4 DMRS sybmols for a PUCCH Format 3 or 4 with more than 2X+1 symbols when FH is disabled (X=4). - -- Corresponds to L1 parameter 'PUCCH-F3-F4-additional-DMRS' (see 38.213, section 9.2.1) - -- The field is not applicable for format 1 and 2. - */ - enable_feature_t additionalDMRS; - /* - -- Max coding rate to determine how to feedback UCI on PUCCH for format 2, 3 or 4 - -- Corresponds to L1 parameter 'PUCCH-F2-maximum-coderate', 'PUCCH-F3-maximum-coderate' and 'PUCCH-F4-maximum-coderate' - -- (see 38.213, section 9.2.5) - -- The field is not applicable for format 1. - */ - PUCCH_MaxCodeRate_t maxCodeRate; - /* - -- Number of slots with the same PUCCH F1, F3 or F4. When the field is absent the UE applies the value n1. - -- Corresponds to L1 parameter 'PUCCH-F1-number-of-slots', 'PUCCH-F3-number-of-slots' and 'PUCCH-F4-number-of-slots' - -- (see 38.213, section 9.2.6) - -- The field is not applicable for format 2. - */ - uint8_t nrofSlots; - /* - -- Enabling pi/2 BPSK for UCI symbols instead of QPSK for PUCCH. - -- Corresponds to L1 parameter 'PUCCH-PF3-PF4-pi/2PBSK' (see 38.213, section 9.2.5) - -- The field is not applicable for format 1 and 2. - */ - feature_status_t pi2PBSK; - /* - -- Enabling simultaneous transmission of CSI and HARQ-ACK feedback with or without SR with PUCCH Format 2, 3 or 4 - -- Corresponds to L1 parameter 'PUCCH-F2-Simultaneous-HARQ-ACK-CSI', 'PUCCH-F3-Simultaneous-HARQ-ACK-CSI' and - -- 'PUCCH-F4-Simultaneous-HARQ-ACK-CSI' (see 38.213, section 9.2.5) - -- When the field is absent the UE applies the value OFF - -- The field is not applicable for format 1. - */ - enable_feature_t simultaneousHARQ_ACK_CSI; - /* - -- Configuration of group- and sequence hopping for all the PUCCH formats 0, 1, 3 and 4. "neither" implies neither group - -- or sequence hopping is enabled. "enable" enables group hopping and disables sequence hopping. "disable"â€� disables group - -- hopping and enables sequence hopping. Corresponds to L1 parameter 'PUCCH-GroupHopping' (see 38.211, section 6.4.1.3) - pucch-GroupHopping ENUMERATED { neither, enable, disable }, - */ - pucch_GroupHopping_t pucch_GroupHopping; - /* - -- Cell-Specific scrambling ID for group hoppping and sequence hopping if enabled. - -- Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) - hoppingId BIT STRING (SIZE (10)) OPTIONAL, -- Need R - */ - uint16_t hoppingId; - /* - -- Power control parameter P0 for PUCCH transmissions. Value in dBm. Only even values (step size 2) allowed. - -- Corresponds to L1 parameter 'p0-nominal-pucch' (see 38.213, section 7.2) - p0-nominal INTEGER (-202..24) OPTIONAL, -- Need R - */ - int8_t p0_nominal; - - int8_t deltaF_PUCCH_f[NUMBER_PUCCH_FORMAT_NR]; - uint8_t p0_PUCCH_Id; /* INTEGER (1..8) */ - int8_t p0_PUCCH_Value; - // pathlossReferenceRSs SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSs)) OF PUCCH-PathlossReferenceRS OPTIONAL, -- Need M - int8_t twoPUCCH_PC_AdjustmentStates; - - } fapi_nr_ul_config_pucch_pdu; + uint16_t rnti; + uint16_t bwp_size; + uint16_t bwp_start; + uint8_t format_type; + uint8_t start_symbol_index; + uint8_t nr_of_symbols; + uint16_t prb_start; + uint16_t prb_size; + uint32_t hopping_id; + uint8_t freq_hop_flag; + uint8_t group_hop_flag; + uint8_t sequence_hop_flag; + uint16_t second_hop_prb; + uint16_t initial_cyclic_shift; + uint8_t time_domain_occ_idx; + uint8_t add_dmrs_flag; + uint16_t dmrs_scrambling_id; + uint16_t data_scrambling_id; + uint8_t dmrs_cyclic_shift; + uint8_t pi_2bpsk; + uint8_t mcs; + uint8_t pre_dft_occ_idx; + uint8_t pre_dft_occ_len; + int16_t pucch_tx_power; + uint32_t n_bit; + uint64_t payload; +} fapi_nr_ul_config_pucch_pdu; typedef struct { @@ -403,6 +350,7 @@ typedef struct { uint16_t slot; uint8_t number_pdus; fapi_nr_ul_config_request_pdu_t ul_config_list[FAPI_NR_UL_CONFIG_LIST_NUM]; + pthread_mutex_t mutex_ul_config; } fapi_nr_ul_config_request_t; @@ -415,8 +363,14 @@ typedef struct { uint8_t number_of_candidates; uint16_t CCE[64]; uint8_t L[64]; - uint8_t dci_length; - uint8_t dci_format; + // 3GPP TS 38.212 Sec. 7.3.1.0, 3GPP TS 138.131 sec. 6.3.2 (SearchSpace) + // The maximum number of DCI lengths allowed by the spec are 4, with max 3 for C-RNTI. + // But a given search space may only support a maximum of 2 DCI formats at a time + // depending on its search space type configured by RRC. Hence for blind decoding, UE + // needs to monitor only upto 2 DCI lengths for a given search space. + uint8_t num_dci_options; // Num DCIs the UE actually needs to decode (1 or 2) + uint8_t dci_length_options[2]; + uint8_t dci_format_options[2]; } fapi_nr_dl_config_dci_dl_pdu_rel15_t; typedef struct { @@ -449,11 +403,8 @@ typedef struct { uint8_t tb2_rv; uint8_t harq_process_nbr; vrb_to_prb_mapping_t vrb_to_prb_mapping; - uint8_t dai; double scaling_factor_S; int8_t accumulated_delta_PUCCH; - uint8_t pucch_resource_id; - uint8_t pdsch_to_harq_feedback_time_ind; uint8_t n_dmrs_cdm_groups; uint8_t dmrs_ports[10]; uint8_t n_front_load_symb; @@ -462,6 +413,21 @@ typedef struct { uint8_t cbgti; uint8_t codeBlockGroupFlushIndicator; // to be check the fields needed to L1 with NR_DL_UE_HARQ_t and NR_UE_DLSCH_t + // PTRS [TS38.214, sec 5.1.6.3] + /// PT-RS antenna ports [TS38.214, sec 5.1.6.3] [TS38.211, table 7.4.1.2.2-1] Bitmap occupying the 6 LSBs with: bit 0: antenna port 1000 bit 5: antenna port 1005 and for each bit 0: PTRS port not used 1: PTRS port used + uint8_t PTRSPortIndex ; + /// PT-RS time density [TS38.214, table 5.1.6.3-1] 0: 1 1: 2 2: 4 + uint8_t PTRSTimeDensity; + /// PT-RS frequency density [TS38.214, table 5.1.6.3-2] 0: 2 1: 4 + uint8_t PTRSFreqDensity; + /// PT-RS resource element offset [TS38.211, table 7.4.1.2.2-1] Value: 0->3 + uint8_t PTRSReOffset; + /// PT-RS-to-PDSCH EPRE ratio [TS38.214, table 4.1-2] Value :0->3 + uint8_t nEpreRatioOfPDSCHToPTRS; + /// MCS table for this DLSCH + uint8_t mcs_table; + + uint16_t pduBitmap; } fapi_nr_dl_config_dlsch_pdu_rel15_t; typedef struct { @@ -485,437 +451,6 @@ typedef struct { } fapi_nr_dl_config_request_t; -// -// P5 -// - - - -typedef struct { - fapi_nr_coreset_t coreset; - - uint8_t monitoring_slot_peridicity; - uint8_t monitoring_slot_offset; - uint16_t duration; - uint16_t monitoring_symbols_within_slot; - uint8_t number_of_candidates[5]; // aggregation level 1, 2, 4, 8, 16 - - uint8_t dci_2_0_number_of_candidates[5]; // aggregation level 1, 2, 4, 8, 16 - uint8_t dci_2_3_monitorying_periodicity; - uint8_t dci_2_3_number_of_candidates; - -} fapi_nr_search_space_t; - -typedef struct { - fapi_nr_search_space_t search_space_sib1; - fapi_nr_search_space_t search_space_others_sib; - fapi_nr_search_space_t search_space_paging; - //fapi_nr_coreset_t coreset_ra; // common coreset - fapi_nr_search_space_t search_space_ra; -} fapi_nr_pdcch_config_common_t; - -typedef struct { - uint8_t k0; - uint8_t mapping_type; - uint8_t symbol_starting; - uint8_t symbol_length; -} fapi_nr_pdsch_time_domain_resource_allocation_t; - -typedef struct { - fapi_nr_pdsch_time_domain_resource_allocation_t allocation_list[FAPI_NR_MAX_NUM_DL_ALLOCATIONS]; -} fapi_nr_pdsch_config_common_t; - -typedef struct { - uint8_t prach_configuration_index; - uint8_t msg1_fdm; - uint8_t msg1_frequency_start; - uint8_t zero_correlation_zone_config; - uint8_t preamble_received_target_power; - uint8_t preamble_transmission_max; - uint8_t power_ramping_step; - uint8_t ra_window_size; - - uint8_t total_number_of_preamble; - uint8_t ssb_occasion_per_rach; - uint8_t cb_preamble_per_ssb; - - uint8_t group_a_msg3_size; - uint8_t group_a_number_of_preamble; - uint8_t group_b_power_offset; - uint8_t contention_resolution_timer; - uint8_t rsrp_threshold_ssb; - uint8_t rsrp_threshold_ssb_sul; - uint8_t prach_length; // l839, l139 - uint8_t prach_root_sequence_index; // 0 - 837 for l839, 0 - 137 for l139 - uint8_t msg1_subcarrier_spacing; - uint8_t restrictedset_config; - uint8_t msg3_transform_precoding; -} fapi_nr_rach_config_common_t; - -typedef struct { - uint8_t k2; - uint8_t mapping_type; - uint8_t symbol_starting; - uint8_t symbol_length; -} fapi_nr_pusch_time_domain_resource_allocation_t; - -typedef struct { - uint8_t group_hopping_enabled_transform_precoding; - fapi_nr_pusch_time_domain_resource_allocation_t allocation_list[FAPI_NR_MAX_NUM_UL_ALLOCATIONS]; - uint8_t msg3_delta_preamble; - uint8_t p0_nominal_with_grant; -} fapi_nr_pusch_config_common_t; - -typedef struct { - uint8_t pucch_resource_common; - uint8_t pucch_group_hopping; - uint8_t hopping_id; - uint8_t p0_nominal; -} fapi_nr_pucch_config_common_t; - -typedef struct { - - fapi_nr_pdcch_config_common_t pdcch_config_common; - fapi_nr_pdsch_config_common_t pdsch_config_common; - -} fapi_nr_dl_bwp_common_config_t; - - - -typedef struct { - uint16_t int_rnti; - uint8_t time_frequency_set; - uint8_t dci_payload_size; - uint8_t serving_cell_id[FAPI_NR_MAX_NUM_SERVING_CELLS]; // interrupt configuration per serving cell - uint8_t position_in_dci[FAPI_NR_MAX_NUM_SERVING_CELLS]; // interrupt configuration per serving cell -} fapi_nr_downlink_preemption_t; - -typedef struct { - uint8_t tpc_index; - uint8_t tpc_index_sul; - uint8_t target_cell; -} fapi_nr_pusch_tpc_command_config_t; - -typedef struct { - uint8_t tpc_index_pcell; - uint8_t tpc_index_pucch_scell; -} fapi_nr_pucch_tpc_command_config_t; - -typedef struct { - uint8_t starting_bit_of_format_2_3; - uint8_t feild_type_format_2_3; -} fapi_nr_srs_tpc_command_config_t; - -typedef struct { - fapi_nr_downlink_preemption_t downlink_preemption; - fapi_nr_pusch_tpc_command_config_t tpc_pusch; - fapi_nr_pucch_tpc_command_config_t tpc_pucch; - fapi_nr_srs_tpc_command_config_t tpc_srs; -} fapi_nr_pdcch_config_dedicated_t; - -typedef struct { - uint8_t dmrs_type; - uint8_t dmrs_addition_position; - uint8_t max_length; - uint16_t scrambling_id0; - uint16_t scrambling_id1; - uint8_t ptrs_frequency_density[2]; // phase tracking rs - uint8_t ptrs_time_density[3]; // phase tracking rs - uint8_t ptrs_epre_ratio; // phase tracking rs - uint8_t ptrs_resource_element_offset; // phase tracking rs -} fapi_nr_dmrs_downlink_config_t; - -typedef struct { - uint8_t bwp_or_cell_level; - uint8_t pattern_type; - uint32_t resource_blocks[9]; // bitmaps type 275 bits - uint8_t slot_type; // bitmaps type one/two slot(s) - uint32_t symbols_in_resouece_block; // bitmaps type 14/28 bits - uint8_t periodic; // bitmaps type - uint32_t pattern[2]; // bitmaps type 2/4/5/8/10/20/40 bits - - fapi_nr_coreset_t coreset; // coreset - - uint8_t subcarrier_spacing; - uint8_t mode; -} fapi_nr_rate_matching_pattern_group_t; - -typedef struct { - // resource mapping - uint8_t row; // row1/row2/row4/other - uint16_t frequency_domain_allocation; // 4/12/3/6 bits - uint8_t number_of_ports; - uint8_t first_ofdm_symbol_in_time_domain; - uint8_t first_ofdm_symbol_in_time_domain2; - uint8_t cdm_type; - uint8_t density; // .5/1/3 - uint8_t density_dot5_type; // even/odd PRBs - - uint8_t frequency_band_starting_rb; // freqBand - uint8_t frequency_band_number_of_rb; // freqBand - - // periodicityAndOffset - uint8_t periodicity; // slot4/5/8/10/16/20/32/40/64/80/160/320/640 - uint32_t offset; // 0..639 bits -} fapi_nr_zp_csi_rs_resource_t; - -typedef struct { - uint16_t data_scrambling_id_pdsch; - fapi_nr_dmrs_downlink_config_t dmrs_dl_for_pdsch_mapping_type_a; - fapi_nr_dmrs_downlink_config_t dmrs_dl_for_pdsch_mapping_type_b; - uint8_t vrb_to_prb_interleaver; - uint8_t resource_allocation; - fapi_nr_pdsch_time_domain_resource_allocation_t allocation_list[FAPI_NR_MAX_NUM_DL_ALLOCATIONS]; - uint8_t pdsch_aggregation_factor; - fapi_nr_rate_matching_pattern_group_t rate_matching_pattern_group1; - fapi_nr_rate_matching_pattern_group_t rate_matching_pattern_group2; - uint8_t rbg_size; - uint8_t mcs_table; - uint8_t max_num_of_code_word_scheduled_by_dci; - uint8_t bundle_size; // prb_bundling static - uint8_t bundle_size_set1; // prb_bundling dynamic - uint8_t bundle_size_set2; // prb_bundling dynamic - fapi_nr_zp_csi_rs_resource_t periodically_zp_csi_rs_resource_set[FAPI_NR_MAX_NUM_ZP_CSI_RS_RESOURCE_PER_SET]; -} fapi_nr_pdsch_config_dedicated_t; - -typedef struct { - uint16_t starting_prb; - uint8_t intra_slot_frequency_hopping; - uint16_t second_hop_prb; - uint8_t format; // pucch format 0..4 - uint8_t initial_cyclic_shift; - uint8_t number_of_symbols; - uint8_t starting_symbol_index; - uint8_t time_domain_occ; - uint8_t number_of_prbs; - uint8_t occ_length; - uint8_t occ_index; -} fapi_nr_pucch_resource_t; - -typedef struct { - uint8_t periodicity; - uint8_t number_of_harq_process; - fapi_nr_pucch_resource_t n1_pucch_an; -} fapi_nr_sps_config_t; - -typedef struct { - uint8_t beam_failure_instance_max_count; - uint8_t beam_failure_detection_timer; -} fapi_nr_radio_link_monitoring_config_t; - -typedef struct { - fapi_nr_pdcch_config_dedicated_t pdcch_config_dedicated; - fapi_nr_pdsch_config_dedicated_t pdsch_config_dedicated; - fapi_nr_sps_config_t sps_config; - fapi_nr_radio_link_monitoring_config_t radio_link_monitoring_config; - -} fapi_nr_dl_bwp_dedicated_config_t; - -typedef struct { - fapi_nr_rach_config_common_t rach_config_common; - fapi_nr_pusch_config_common_t pusch_config_common; - fapi_nr_pucch_config_common_t pucch_config_common; - -} fapi_nr_ul_bwp_common_config_t; - -typedef struct { - uint8_t inter_slot_frequency_hopping; - uint8_t additional_dmrs; - uint8_t max_code_rate; - uint8_t number_of_slots; - uint8_t pi2bpsk; - uint8_t simultaneous_harq_ack_csi; -} fapi_nr_pucch_format_config_t; - -typedef struct { - fapi_nr_pucch_format_config_t format1; - fapi_nr_pucch_format_config_t format2; - fapi_nr_pucch_format_config_t format3; - fapi_nr_pucch_format_config_t format4; - fapi_nr_pucch_resource_t multi_csi_pucch_resources[2]; - uint8_t dl_data_to_ul_ack[8]; - // pucch power control - uint8_t deltaF_pucch_f0; - uint8_t deltaF_pucch_f1; - uint8_t deltaF_pucch_f2; - uint8_t deltaF_pucch_f3; - uint8_t deltaF_pucch_f4; - uint8_t two_pucch_pc_adjusment_states; -} fapi_nr_pucch_config_dedicated_t; - -typedef struct { - uint8_t dmrs_type; - uint8_t dmrs_addition_position; - uint8_t ptrs_uplink_config; // to indicate if PTRS Uplink is configured of not - uint8_t ptrs_type; //cp-OFDM, dft-S-OFDM - uint16_t ptrs_frequency_density[2]; - uint8_t ptrs_time_density[3]; - uint8_t ptrs_max_number_of_ports; - uint8_t ptrs_resource_element_offset; - uint8_t ptrs_power; - uint16_t ptrs_sample_density[5]; - uint8_t ptrs_time_density_transform_precoding; - - uint8_t max_length; - uint16_t scrambling_id0; - uint16_t scrambling_id1; - uint8_t npusch_identity; - uint8_t disable_sequence_group_hopping; - uint8_t sequence_hopping_enable; -} fapi_nr_dmrs_uplink_config_t; - -typedef struct { - uint8_t tpc_accmulation; - uint8_t msg3_alpha; - uint8_t p0_nominal_with_grant; - uint8_t two_pusch_pc_adjustments_states; - uint8_t delta_mcs; -} fapi_nr_pusch_power_control_t; - -typedef enum {tx_config_codebook = 1, tx_config_nonCodebook = 2} tx_config_t; -typedef enum {transform_precoder_disabled = 0, transform_precoder_enabled = 1} transform_precoder_t; -typedef enum { - codebook_subset_fullyAndPartialAndNonCoherent = 1, - codebook_subset_partialAndNonCoherent = 2, - codebook_subset_nonCoherent = 3} codebook_subset_t; -typedef struct { - uint16_t data_scrambling_identity; - tx_config_t tx_config; - fapi_nr_dmrs_uplink_config_t dmrs_ul_for_pusch_mapping_type_a; - fapi_nr_dmrs_uplink_config_t dmrs_ul_for_pusch_mapping_type_b; - fapi_nr_pusch_power_control_t pusch_power_control; - uint8_t frequency_hopping; - uint16_t frequency_hopping_offset_lists[4]; - uint8_t resource_allocation; - fapi_nr_pusch_time_domain_resource_allocation_t allocation_list[FAPI_NR_MAX_NUM_UL_ALLOCATIONS]; - uint8_t pusch_aggregation_factor; - uint8_t mcs_table; - uint8_t mcs_table_transform_precoder; - transform_precoder_t transform_precoder; - codebook_subset_t codebook_subset; - uint8_t max_rank; - uint8_t rbg_size; - - //uci-OnPUSCH - uint8_t uci_on_pusch_type; //dynamic, semi-static - uint8_t beta_offset_ack_index1[4]; - uint8_t beta_offset_ack_index2[4]; - uint8_t beta_offset_ack_index3[4]; - uint8_t beta_offset_csi_part1_index1[4]; - uint8_t beta_offset_csi_part1_index2[4]; - uint8_t beta_offset_csi_part2_index1[4]; - uint8_t beta_offset_csi_part2_index2[4]; - - uint8_t tp_pi2BPSK; -} fapi_nr_pusch_config_dedicated_t; - -typedef struct { - uint8_t frequency_hopping; - fapi_nr_dmrs_uplink_config_t cg_dmrs_configuration; - uint8_t mcs_table; - uint8_t mcs_table_transform_precoder; - - //uci-OnPUSCH - uint8_t uci_on_pusch_type; //dynamic, semi-static - uint8_t beta_offset_ack_index1[4]; - uint8_t beta_offset_ack_index2[4]; - uint8_t beta_offset_ack_index3[4]; - uint8_t beta_offset_csi_part1_index1[4]; - uint8_t beta_offset_csi_part1_index2[4]; - uint8_t beta_offset_csi_part2_index1[4]; - uint8_t beta_offset_csi_part2_index2[4]; - - uint8_t resource_allocation; - // rgb-Size structure missing in spec. - uint8_t power_control_loop_to_use; - // p0-PUSCH-Alpha - uint8_t p0; - uint8_t alpha; - - uint8_t transform_precoder; - uint8_t number_of_harq_process; - uint8_t rep_k; - uint8_t rep_k_rv; - uint8_t periodicity; - uint8_t configured_grant_timer; - // rrc-ConfiguredUplinkGrant - uint16_t time_domain_offset; - uint8_t time_domain_allocation; - uint32_t frequency_domain_allocation; - uint8_t antenna_ports; - uint8_t dmrs_seq_initialization; - uint8_t precoding_and_number_of_layers; - uint8_t srs_resource_indicator; - uint8_t mcs_and_tbs; - uint8_t frequency_hopping_offset; - uint8_t path_loss_reference_index; - -} fapi_nr_configured_grant_config_t; - -typedef struct { - uint8_t qcl_type1_serving_cell_index; - uint8_t qcl_type1_bwp_id; - uint8_t qcl_type1_rs_type; // csi-rs or ssb - uint8_t qcl_type1_nzp_csi_rs_resource_id; - uint8_t qcl_type1_ssb_index; - uint8_t qcl_type1_type; - - uint8_t qcl_type2_serving_cell_index; - uint8_t qcl_type2_bwp_id; - uint8_t qcl_type2_rs_type; // csi-rs or ssb - uint8_t qcl_type2_nzp_csi_rs_resource_id; - uint8_t qcl_type2_ssb_index; - uint8_t qcl_type2_type; - -} fapi_nr_tci_state_t; - -typedef struct { - uint8_t root_sequence_index; - // rach genertic - uint8_t prach_configuration_index; - uint8_t msg1_fdm; - uint8_t msg1_frequency_start; - uint8_t zero_correlation_zone_config; - uint8_t preamble_received_target_power; - uint8_t preamble_transmission_max; - uint8_t power_ramping_step; - uint8_t ra_window_size; - - uint8_t rsrp_threshold_ssb; - // PRACH-ResourceDedicatedBFR - uint8_t bfr_ssb_index[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_ssb_ra_preamble_index[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - // NZP-CSI-RS-Resource - uint8_t bfr_csi_rs_nzp_resource_mapping[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_csi_rs_power_control_offset[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_csi_rs_power_control_offset_ss[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint16_t bfr_csi_rs_scrambling_id[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_csi_rs_resource_periodicity[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint16_t bfr_csi_rs_resource_offset[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - fapi_nr_tci_state_t qcl_infomation_periodic_csi_rs[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - - uint8_t bfr_csirs_ra_occasions[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS]; - uint8_t bfr_csirs_ra_preamble_index[FAPI_NR_MAX_NUM_CANDIDATE_BEAMS][FAPI_NR_MAX_RA_OCCASION_PER_CSIRS]; - - uint8_t ssb_per_rach_occasion; - uint8_t ra_ssb_occasion_mask_index; - fapi_nr_search_space_t recovery_search_space; - // RA-Prioritization - uint8_t power_ramping_step_high_priority; - uint8_t scaling_factor_bi; - uint8_t beam_failure_recovery_timer; -} fapi_nr_beam_failure_recovery_config_t; - -typedef struct { - fapi_nr_pucch_config_dedicated_t pucch_config_dedicated; - fapi_nr_pusch_config_dedicated_t pusch_config_dedicated; - fapi_nr_configured_grant_config_t configured_grant_config; - // SRS-Config - uint8_t srs_tpc_accumulation; - fapi_nr_beam_failure_recovery_config_t beam_failure_recovery_config; - -} fapi_nr_ul_bwp_dedicated_config_t; - #define FAPI_NR_CONFIG_REQUEST_MASK_PBCH 0x01 #define FAPI_NR_CONFIG_REQUEST_MASK_DL_BWP_COMMON 0x02 #define FAPI_NR_CONFIG_REQUEST_MASK_UL_BWP_COMMON 0x04 @@ -947,7 +482,7 @@ typedef struct typedef struct { - uint32_t ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) + int ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) uint8_t bch_payload;//Defines option selected for generation of BCH payload, see Table 3-13 (v0.0.011 Value: 0: MAC generates the full PBCH payload 1: PHY generates the timing PBCH bits 2: PHY generates the full PBCH payload uint8_t scs_common;//subcarrierSpacing for common, used for initial access and broadcast message. [38.211 sec 4.2] Value:0->3 @@ -994,6 +529,7 @@ typedef struct typedef struct { uint8_t tdd_period;//DL UL Transmission Periodicity. Value:0: ms0p5 1: ms0p625 2: ms1 3: ms1p25 4: ms2 5: ms2p5 6: ms5 7: ms10 8: ms3 9: ms4 + uint8_t tdd_period_in_slots; fapi_nr_max_tdd_periodicity_t* max_tdd_periodicity_list; } fapi_nr_tdd_table_t; @@ -1032,12 +568,6 @@ typedef struct { fapi_nr_tdd_table_t tdd_table; fapi_nr_prach_config_t prach_config; - fapi_nr_dl_bwp_common_config_t dl_bwp_common; - fapi_nr_dl_bwp_dedicated_config_t dl_bwp_dedicated; - - fapi_nr_ul_bwp_common_config_t ul_bwp_common; - fapi_nr_ul_bwp_dedicated_config_t ul_bwp_dedicated; - } fapi_nr_config_request_t; #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h index 32a31a99f6..ea459138e1 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h @@ -120,6 +120,17 @@ typedef struct { } nfapi_tl_t; #define NFAPI_TAG_LENGTH_PACKED_LEN 4 +// Convenience methods to convert between SFN/SLOT formats +#define NFAPI_SFNSLOT2DEC(_sfn,_slot) ( _sfn*20 + _slot ) // total count of slots +#define NFAPI_SFNSLOTDEC2SFNSLOT(_sfnslot_dec) ((((_sfnslot_dec) / 20) << 4) | (((_sfnslot_dec) - (((_sfnslot_dec) / 20) * 10)) & 0x3F)) + +#define NFAPI_SFNSLOT2SFN(_sfnslot) ((_sfnslot) >> 6) +#define NFAPI_SFNSLOT2SLOT(_sfnslot) ((_sfnslot) & 0x3F) +#define NFAPI_SFNSLOTDEC2SFN(_sfnslot_dec) ((_sfnslot_dec) / 20) +#define NFAPI_SFNSLOTDEC2SLOT(_sfnslot_dec) ((_sfnslot_dec) % 20) + +#define NFAPI_MAX_SFNSLOTDEC 1024*20 // 20 is for numerology 1 + // Convenience methods to convert between SFN/SFN formats #define NFAPI_SFNSF2DEC(_sfnsf) ((((_sfnsf) >> 4) * 10) + ((_sfnsf) & 0xF)) #define NFAPI_SFNSFDEC2SFNSF(_sfnsf_dec) ((((_sfnsf_dec) / 10) << 4) | (((_sfnsf_dec) - (((_sfnsf_dec) / 10) * 10)) & 0xF)) @@ -176,7 +187,6 @@ typedef enum { NFAPI_DL_NODE_SYNC, NFAPI_TIMING_INFO, - NFAPI_RSSI_REQUEST = 0x0200, NFAPI_RSSI_RESPONSE, NFAPI_RSSI_INDICATION, @@ -587,6 +597,26 @@ typedef struct { #define NFAPI_PNF_PHY_RF_TAG 0x1003 // Generic strucutre for single tlv value. +typedef struct { + nfapi_tl_t tl; + int32_t value; +} nfapi_int32_tlv_t; + +typedef struct { + nfapi_tl_t tl; + uint32_t value; +} nfapi_uint32_tlv_t; + +typedef struct { + nfapi_tl_t tl; + int64_t value; +} nfapi_int64_tlv_t; + +typedef struct { + nfapi_tl_t tl; + uint64_t value; +} nfapi_uint64_tlv_t; + typedef struct { nfapi_tl_t tl; uint16_t value; @@ -1106,6 +1136,7 @@ typedef struct { typedef struct { nfapi_p4_p5_message_header_t header; + uint8_t num_tlvs; nfapi_pnf_phy_rf_config_t pnf_phy_rf_config; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_pnf_config_request_t; @@ -2466,7 +2497,7 @@ typedef struct { typedef struct { nfapi_p7_message_header_t header; uint32_t t1; - int32_t delta_sfn_sf; + int32_t delta_sfn_sf; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_dl_node_sync_t; @@ -2481,22 +2512,50 @@ typedef struct { typedef struct { nfapi_p7_message_header_t header; uint32_t last_sfn_sf; + uint32_t time_since_last_timing_info; uint32_t dl_config_jitter; uint32_t tx_request_jitter; uint32_t ul_config_jitter; uint32_t hi_dci0_jitter; + int32_t dl_config_latest_delay; int32_t tx_request_latest_delay; int32_t ul_config_latest_delay; int32_t hi_dci0_latest_delay; + int32_t dl_config_earliest_arrival; int32_t tx_request_earliest_arrival; int32_t ul_config_earliest_arrival; int32_t hi_dci0_earliest_arrival; + nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_timing_info_t; +typedef struct { + nfapi_p7_message_header_t header; + + uint32_t last_sfn; + uint32_t last_slot; + uint32_t time_since_last_timing_info; + + uint32_t dl_tti_jitter; + uint32_t tx_data_request_jitter; + uint32_t ul_tti_jitter; + uint32_t ul_dci_jitter; + + int32_t dl_tti_latest_delay; + int32_t tx_data_request_latest_delay; + int32_t ul_tti_latest_delay; + int32_t ul_dci_latest_delay; + + int32_t dl_tti_earliest_arrival; + int32_t tx_data_request_earliest_arrival; + int32_t ul_tti_earliest_arrival; + int32_t ul_dci_earliest_arrival; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_timing_info_t; + typedef struct { nfapi_tl_t tl; uint32_t handle; @@ -2668,7 +2727,7 @@ typedef struct { } nfapi_cqi_indication_rel8_t; #define NFAPI_CQI_INDICATION_REL8_TAG 0x202f -#define NFAPI_CC_MAX 4 +#define NFAPI_CC_MAX MAX_NUM_CCs typedef struct { nfapi_tl_t tl; uint16_t length; @@ -3653,6 +3712,50 @@ typedef struct { nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nmm_stop_response_t; +typedef struct +{ + // TODO: see if this needs to be uncommented + + // These TLVs are used to setup the transport connection between VNF and PNF + nfapi_ipv4_address_t p7_vnf_address_ipv4; + nfapi_ipv6_address_t p7_vnf_address_ipv6; + nfapi_uint16_tlv_t p7_vnf_port; + + nfapi_ipv4_address_t p7_pnf_address_ipv4; + nfapi_ipv6_address_t p7_pnf_address_ipv6; + nfapi_uint16_tlv_t p7_pnf_port; + + nfapi_uint8_tlv_t timing_window; //Value: 0 → 30,000 microseconds + nfapi_uint8_tlv_t timing_info_mode; + nfapi_uint8_tlv_t timing_info_period; + + nfapi_uint32_tlv_t dl_tti_timing_offset; + nfapi_uint32_tlv_t ul_tti_timing_offset; + nfapi_uint32_tlv_t ul_dci_timing_offset; + nfapi_uint32_tlv_t tx_data_timing_offset; + + // These TLVs are used to setup the transport connection between VNF and PNF + /* + nfapi_uint8_tlv_t dl_ue_per_sf; + nfapi_uint8_tlv_t ul_ue_per_sf; + + // These TLVs are used by PNF to report its RF capabilities to the VNF software + nfapi_rf_bands_t rf_bands; +*/ + // These TLVs are used by the VNF to configure the synchronization with the PNF. + + + // These TLVs are used by the VNF to configure the RF in the PNF + //nfapi_uint16_tlv_t max_transmit_power; + //nfapi_uint32_tlv_t nrarfcn; + + // nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands; + // nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands; + // nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands; + // nfapi_uint8_tlv_t nmm_uplink_rssi_supported; + +} nfapi_nr_nfapi_t; + // // Configuration options for the encode decode functions // @@ -3864,6 +3967,7 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn * */ int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config); +int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config); /*! \brief Decodes an NFAPI P5 message header * \param pMessageBuf A pointer to an encoded P5 message header @@ -3887,6 +3991,7 @@ int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo * * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf */ +int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); /*! \brief Encodes an NFAPI P7 message to a buffer @@ -3900,6 +4005,7 @@ int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn * */ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); /*! \brief Decodes an NFAPI P7 message header * \param pMessageBuf A pointer to an encoded P7 message header @@ -3925,6 +4031,7 @@ int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf */ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); +int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); /*! \brief Calculates the checksum of a message * diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index 650bda4f78..fbe7a0e170 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -10,7 +10,7 @@ #define _NFAPI_NR_INTERFACE_H_ #include "nfapi_interface.h" -#include +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 #define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 @@ -22,62 +22,32 @@ // nFAPI enums - //These TLVs are used exclusively by nFAPI -typedef struct -{ - // These TLVs are used to setup the transport connection between VNF and PNF - // nfapi_ipv4_address_t p7_vnf_address_ipv4; - // nfapi_ipv6_address_t p7_vnf_address_ipv6; - // nfapi_uint16_tlv_t p7_vnf_port; - - // nfapi_ipv4_address_t p7_pnf_address_ipv4; - // nfapi_ipv6_address_t p7_pnf_address_ipv6; - // nfapi_uint16_tlv_t p7_pnf_port; - - // // These TLVs are used to setup the transport connection between VNF and PNF - // nfapi_uint8_tlv_t dl_ue_per_sf; - // nfapi_uint8_tlv_t ul_ue_per_sf; - - // These TLVs are used by PNF to report its RF capabilities to the VNF software - nfapi_rf_bands_t rf_bands; - - // These TLVs are used by the VNF to configure the synchronization with the PNF. - // nfapi_uint8_tlv_t timing_window; - // nfapi_uint8_tlv_t timing_info_mode; - // nfapi_uint8_tlv_t timing_info_period; - - // These TLVs are used by the VNF to configure the RF in the PNF - // nfapi_uint16_tlv_t max_transmit_power; - nfapi_uint32_tlv_t nrarfcn; - - // nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands; - // nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands; - // nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands; - // nfapi_uint8_tlv_t nmm_uplink_rssi_supported; - -} nfapi_nr_nfapi_t; - -#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x5100 -#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x5101 -#define NFAPI_NR_NFAPI_P7_VNF_PORT_TAG 0x5102 -#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x5103 -#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x5104 -#define NFAPI_NR_NFAPI_P7_PNF_PORT_TAG 0x5105 +#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x0100 +#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x0101 +#define NFAPI_NR_NFAPI_P7_VNF_PORT_TAG 0x0102 +#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x0103 +#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x0104 +#define NFAPI_NR_NFAPI_P7_PNF_PORT_TAG 0x0105 +#define NFAPI_NR_NFAPI_DL_TTI_TIMING_OFFSET 0x0106 +#define NFAPI_NR_NFAPI_UL_TTI_TIMING_OFFSET 0x0107 +#define NFAPI_NR_NFAPI_UL_DCI_TIMING_OFFSET 0x0108 +#define NFAPI_NR_NFAPI_TX_DATA_TIMING_OFFSET 0x0109 +#define NFAPI_NR_NFAPI_TIMING_WINDOW_TAG 0x011E +#define NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG 0x011F +#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120 +/* #define NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG 0x510A #define NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG 0x510B #define NFAPI_NR_NFAPI_RF_BANDS_TAG 0x5114 -#define NFAPI_NR_NFAPI_TIMING_WINDOW_TAG 0x511E -#define NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG 0x511F -#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x5120 #define NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG 0x5128 #define NFAPI_NR_NFAPI_NRARFCN_TAG 0x5129 #define NFAPI_NR_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG 0x5130 #define NFAPI_NR_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG 0x5131 #define NFAPI_NR_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG 0x5132 #define NFAPI_NR_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG 0x5133 - +*/ // P5 Message Structures typedef struct { @@ -323,7 +293,7 @@ typedef enum { typedef enum { NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED=0, - NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED + NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED=1 } nfapi_nr_cce_reg_mapping_type_e; typedef enum { diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index f84917f12e..9d245446c8 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -11,6 +11,7 @@ #include "stddef.h" #include "nfapi_interface.h" +#include "nfapi_nr_interface.h" #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 #define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 @@ -24,25 +25,7 @@ #define NFAPI_MAX_NUM_CB 8 // Extension to the generic structures for single tlv values -typedef struct { - nfapi_tl_t tl; - int32_t value; -} nfapi_int32_tlv_t; -typedef struct { - nfapi_tl_t tl; - uint32_t value; -} nfapi_uint32_tlv_t; - -typedef struct { - nfapi_tl_t tl; - int64_t value; -} nfapi_int64_tlv_t; - -typedef struct { - nfapi_tl_t tl; - uint64_t value; -} nfapi_uint64_tlv_t; typedef enum { NFAPI_NR_DMRS_TYPE1=0, @@ -76,35 +59,42 @@ typedef enum { NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST= 0X05, NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION=0X06, NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION=0X07, + NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE=0X010D, + NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE=0X010F, //RESERVED 0X08 ~ 0X7F NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST= 0X80, NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST= 0X81, NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION=0X82, NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST= 0X83, - NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST=0X54, + NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST=0X84, // CHANGED TO 0X84 NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION=0X85, NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION= 0X86, NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION= 0X87, NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION= 0X88, - NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION= 0X89 + NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION= 0X89, //RESERVED 0X8a ~ 0xff + NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST = 0x0100, + NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE = 0x0101, + NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST= 0x0102, + NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE= 0x0103, + NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST= 0x0104, + NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE= 0x0105, + NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST= 0x0106, + NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE= 0x0107, + + NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC = 0x0180, + NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, + NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO } nfapi_nr_phy_msg_type_e; // SCF222_5G-FAPI_PHY_SPI_Specificayion.pdf Section 3.3 //3.3.1 PARAM + + //same with nfapi_param_request_t -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nr_param_request_t; -typedef enum { - NFAPI_NR_PARAM_MSG_OK = 0, - NFAPI_NR_PARAM_MSG_INVALID_STATE - -} nfapi_nr_param_errors_e; /*typedef struct { nfapi_nr_param_errors_e error_code; @@ -278,12 +268,6 @@ typedef struct //-------------------------------------------// //3.3.2 CONFIG - -typedef enum { - NFAPI_NR_CONFIG_MSG_OK = 0, - NFAPI_NR_CONFIG_MSG_INVALID_CONFIG //The configuration provided has missing mandatory TLVs, or TLVs that are invalid or unsupported in this state. -} nfapi_nr_config_errors_e; - /*typedef struct { nfapi_nr_config_errors_e error_code; uint8_t number_of_invalid_tlvs_that_can_only_be_configured_in_idle; @@ -321,6 +305,7 @@ typedef enum { #define NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG 0x1012 #define NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG 0x1013 #define NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG 0x1014 +#define NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG 0x1029 #define NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG 0x1015 #define NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG 0x1016 #define NFAPI_NR_CONFIG_K1_TAG 0x1017 @@ -372,7 +357,7 @@ typedef struct //table 3-23 typedef struct { - nfapi_uint32_tlv_t ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) + nfapi_int32_tlv_t ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) nfapi_uint8_tlv_t bch_payload;//Defines option selected for generation of BCH payload, see Table 3-13 (v0.0.011 Value: 0: MAC generates the full PBCH payload 1: PHY generates the timing PBCH bits 2: PHY generates the full PBCH payload nfapi_uint8_tlv_t scs_common;//subcarrierSpacing for common, used for initial access and broadcast message. [38.211 sec 4.2] Value:0->3 @@ -385,7 +370,6 @@ typedef struct typedef struct { - uint8_t num_prach_fd_occasions; nfapi_uint16_tlv_t prach_root_sequence_index;//Starting logical root sequence index, ð�‘–, equivalent to higher layer parameter prach-RootSequenceIndex [38.211, sec 6.3.3.1] Value: 0 -> 837 nfapi_uint8_tlv_t num_root_sequences;//Number of root sequences for a particular FD occasion that are required to generate the necessary number of preambles nfapi_uint16_tlv_t k1;//Frequency offset (from UL bandwidth part) for each FD. [38.211, sec 6.3.3.2] Value: from 0 to 272 @@ -401,7 +385,9 @@ typedef struct nfapi_uint8_tlv_t prach_sub_c_spacing;//Subcarrier spacing of PRACH. [38.211 sec 4.2] Value:0->4 nfapi_uint8_tlv_t restricted_set_config;//PRACH restricted set config Value: 0: unrestricted 1: restricted set type A 2: restricted set type B nfapi_uint8_tlv_t num_prach_fd_occasions;//Corresponds to the parameter ð�‘€ in [38.211, sec 6.3.3.2] which equals the higher layer parameter msg1FDM Value: 1,2,4,8 + nfapi_uint8_tlv_t prach_ConfigurationIndex;//PRACH configuration index. Value:0->255 nfapi_nr_num_prach_fd_occasions_t* num_prach_fd_occasions_list; + nfapi_uint8_tlv_t ssb_per_rach;//SSB-per-RACH-occasion Value: 0: 1/8 1:1/4, 2:1/2 3:1 4:2 5:4, 6:8 7:16 nfapi_uint8_tlv_t prach_multiple_carriers_in_a_band;//0 = disabled 1 = enabled @@ -412,13 +398,13 @@ typedef struct { nfapi_uint32_tlv_t ssb_mask;//Bitmap for actually transmitted SSB. MSB->LSB of first 32 bit number corresponds to SSB 0 to SSB 31 MSB->LSB of second 32 bit number corresponds to SSB 32 to SSB 63 Value for each bit: 0: not transmitted 1: transmitted -} nfapi_nr_ssb_mask_size_2_t; +} nfapi_nr_ssb_mask_list_t; typedef struct { - nfapi_uint8_tlv_t beam_id[64];//BeamID for each SSB in SsbMask. For example, if SSB mask bit 26 is set to 1, then BeamId[26] will be used to indicate beam ID of SSB 26. Value: from 0 to 63 + nfapi_uint8_tlv_t beam_id;//BeamID for each SSB in SsbMask. For example, if SSB mask bit 26 is set to 1, then BeamId[26] will be used to indicate beam ID of SSB 26. Value: from 0 to 63 -} nfapi_nr_ssb_mask_size_64_t; +} nfapi_nr_ssb_beam_id_list_t; typedef struct { @@ -427,8 +413,8 @@ typedef struct nfapi_uint8_tlv_t ssb_period;//SSB periodicity in msec Value: 0: ms5 1: ms10 2: ms20 3: ms40 4: ms80 5: ms160 nfapi_uint8_tlv_t ssb_subcarrier_offset;//ssbSubcarrierOffset or ð�‘˜ð�‘†ð�‘†ð��µ (38.211, section 7.4.3.1) Value: 0->31 nfapi_uint32_tlv_t MIB;//MIB payload, where the 24 MSB are used and represent the MIB in [38.331 MIB IE] and represent 0 1 2 3 1 , , , ,..., A− a a a a a [38.212, sec 7.1.1] - nfapi_nr_ssb_mask_size_2_t ssb_mask_list[2]; - nfapi_nr_ssb_mask_size_64_t* ssb_beam_id_list;//64 + nfapi_nr_ssb_mask_list_t ssb_mask_list[2]; + nfapi_nr_ssb_beam_id_list_t ssb_beam_id_list[64]; nfapi_uint8_tlv_t ss_pbch_multiple_carriers_in_a_band;//0 = disabled 1 = enabled nfapi_uint8_tlv_t multiple_cells_ss_pbch_in_a_carrier;//Indicates that multiple cells will be supported in a single carrier 0 = disabled 1 = enabled @@ -463,9 +449,108 @@ typedef struct } nfapi_nr_measurement_config_t; +// ERROR enums +typedef enum { // Table 2-22 + NFAPI_NR_PARAM_MSG_OK = 0, + NFAPI_NR_PARAM_MSG_INVALID_STATE +} nfapi_nr_param_errors_e; + +typedef enum { // Table 2-25 + NFAPI_NR_CONFIG_MSG_OK = 0, + NFAPI_NR_CONFIG_MSG_INVALID_STATE, //The CONFIG.request was received when the PHY was not in the IDLE state or the CONFIGURED state. + NFAPI_NR_CONFIG_MSG_INVALID_CONFIG //The configuration provided has missing mandatory TLVs, or TLVs that are invalid or unsupported in this state. +} nfapi_nr_config_errors_e; + +typedef enum { // Table 2-27 + NFAPI_NR_START_MSG_OK = 0, + NFAPI_NR_START_MSG_INVALID_STATE +} nfapi_nr_start_errors_e; + +//PNF P5 NR +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_param_request_t; typedef struct { - uint8_t num_tlv; + nfapi_p4_p5_message_header_t header; + uint32_t error_code; + nfapi_pnf_param_general_t pnf_param_general; + nfapi_pnf_phy_t pnf_phy; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_param_response_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + uint8_t num_tlvs; + nfapi_pnf_phy_rf_config_t pnf_phy_rf_config; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_config_request_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + uint32_t error_code; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_config_response_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_start_request_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + uint32_t error_code; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_start_response_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_stop_request_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + uint32_t error_code; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_stop_response_t; + + +/* PARAM.REQUEST */ +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_param_request_scf_t; + +/* PARAM.RESPONSE */ +typedef struct { + nfapi_p4_p5_message_header_t header; + uint8_t error_code; + + uint8_t num_tlv; + nfapi_vendor_extension_tlv_t vendor_extension; + + nfapi_nr_cell_param_t cell_param; + nfapi_nr_carrier_param_t carrier_param; + nfapi_nr_pdcch_param_t pdcch_param; + nfapi_nr_pucch_param_t pucch_param; + nfapi_nr_pdsch_param_t pdsch_param; + nfapi_nr_pusch_param_t pusch_param; + nfapi_nr_prach_param_t prach_param; + nfapi_nr_measurement_param_t measurement_param; + nfapi_nr_nfapi_t nfapi_config; +} nfapi_nr_param_response_scf_t; + +//------------------------------// +//3.3.2 CONFIG + +/* CONFIG.REQUEST */ +typedef struct { + nfapi_p4_p5_message_header_t header; + + uint8_t num_tlv; + nfapi_vendor_extension_tlv_t vendor_extension; + nfapi_nr_carrier_config_t carrier_config; nfapi_nr_cell_config_t cell_config; nfapi_nr_ssb_config_t ssb_config; @@ -473,20 +558,32 @@ typedef struct { nfapi_nr_ssb_table_t ssb_table; nfapi_nr_tdd_table_t tdd_table; nfapi_nr_measurement_config_t measurement_config; + nfapi_nr_nfapi_t nfapi_config; } nfapi_nr_config_request_scf_t; +/* CONFIG.RESPONSE */ +typedef struct { + nfapi_p4_p5_message_header_t header; + uint8_t error_code; + //uint8_t num_invalid_tlvs; + // TODO: add list of invalid/unsupported TLVs (see Table 3.18) + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_config_response_scf_t; + //------------------------------// //3.3.3 START typedef struct { nfapi_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nr_start_request_t; +} nfapi_nr_start_request_scf_t; -typedef enum { - NFAPI_NR_START_MSG_INVALID_STATE -} nfapi_nr_start_errors_e; +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_nr_start_errors_e error_code; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_start_response_scf_t; //3.3.4 STOP @@ -495,6 +592,7 @@ typedef struct { nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_stop_request_t; + typedef struct { nfapi_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; @@ -575,12 +673,13 @@ typedef struct { #define NFAPI_NR_SLOT_INDICATION_PERIOD_NUMEROLOGY_3 125 //us typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; //0->1023 uint16_t slot;//0->319 -} nfapi_nr_slot_indication_t; +} nfapi_nr_slot_indication_scf_t; -// 3.4.2 +// 3.4.2 //for pdcch_pdu: @@ -593,11 +692,10 @@ typedef struct typedef struct { uint16_t pm_idx;//Index to precoding matrix (PM) pre-stored at cell configuration. Note: If precoding is not used this parameter should be set to 0. Value: 0->65535. - nfapi_nr_dig_bf_interface_t* dig_bf_interface_list; + nfapi_nr_dig_bf_interface_t dig_bf_interface_list[1];//max dig_bf_interfaces }nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t; -/* //table 3-43 typedef struct { @@ -605,21 +703,10 @@ typedef struct uint16_t prg_size;//Size in RBs of a precoding resource block group (PRG) – to which same precoding and digital beamforming gets applied. Value: 1->275 //watchout: dig_bf_interfaces here, in table 3-53 it's dig_bf_interface uint8_t dig_bf_interfaces;//Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255 - nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t* prgs_list;// + nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t prgs_list[1];//max prg_size }nfapi_nr_tx_precoding_and_beamforming_t; -*/ -typedef struct { - /// Number of PRGs spanning this allocation. Value : 1->275 - uint16_t numPRGs; - /// Size in RBs of a precoding resource block group (PRG) – to which same precoding and digital beamforming gets applied. Value: 1->275 - uint16_t prgSize; - /// Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255 - uint8_t digBFInterfaces; - uint16_t PMIdx[275]; - uint16_t *beamIdx[275]; -} nfapi_nr_tx_precoding_and_beamforming_t; //table 3-37 @@ -628,43 +715,33 @@ typedef struct { typedef struct { // The RNTI used for identifying the UE when receiving the PDU Value: 1 -> 65535. - uint16_t RNTI[MAX_DCI_CORESET]; + uint16_t RNTI; // For a UE-specific search space it equals the higher-layer parameter PDCCH-DMRSScrambling-ID if configured, // otherwise it should be set to the phy cell ID. [TS38.211, sec 7.3.2.3] Value: 0->65535 - uint16_t ScramblingId[MAX_DCI_CORESET]; + uint16_t ScramblingId; // For a UE-specific search space where PDCCH-DMRSScrambling- ID is configured This param equals the CRNTI. // Otherwise, it should be set to 0. [TS38.211, sec 7.3.2.3] Value: 0 -> 65535 - uint16_t ScramblingRNTI[MAX_DCI_CORESET]; + uint16_t ScramblingRNTI; // CCE start Index used to send the DCI Value: 0->135 - uint8_t CceIndex[MAX_DCI_CORESET]; + uint8_t CceIndex; // Aggregation level used [TS38.211, sec 7.3.2.1] Value: 1,2,4,8,16 - uint8_t AggregationLevel[MAX_DCI_CORESET]; + uint8_t AggregationLevel; // Precoding and Beamforming structure See Table 3-43 - nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming[MAX_DCI_CORESET]; + nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming; // PDCCH power value used for PDCCH Format 1_0 with CRC scrambled by SI-RNTI, PI-RNTI or RA-RNTI. // This is ratio of SSB/PBCH EPRE to PDCCH and PDCCH DMRS EPRE [TS38.213, sec 4.1] // Value :0->17 Report title: 5G FAPI: PHY API Specification Issue date: 29 June 2019 Version: 222.10.17 68 Field Type Description representing -8 to 8 dB in 1dB steps - uint8_t beta_PDCCH_1_0[MAX_DCI_CORESET]; + uint8_t beta_PDCCH_1_0; // PDCCH power value used for all other PDCCH Formats. // This is ratio of SSB/PBCH block EPRE to PDCCH and PDCCH DMRS EPRE [TS38.214, sec 4.1] Values: 0: -3dB,1: 0dB,2: 3dB,3: 6dB - uint8_t powerControlOffsetSS[MAX_DCI_CORESET]; + uint8_t powerControlOffsetSS; // The total DCI length (in bits) including padding bits [TS38.212 sec 7.3.1] Range 0->DCI_PAYLOAD_BYTE_LEN*8 - uint16_t PayloadSizeBits[MAX_DCI_CORESET]; + uint16_t PayloadSizeBits; // DCI payload, where the actual size is defined by PayloadSizeBits. The bit order is as following bit0-bit7 are mapped to first byte of MSB - LSB - uint8_t Payload[MAX_DCI_CORESET][DCI_PAYLOAD_BYTE_LEN]; + uint8_t Payload[DCI_PAYLOAD_BYTE_LEN]; } nfapi_nr_dl_dci_pdu_t; -typedef struct { - /// Number of PRGs spanning this allocation. Value : 1->275 - uint16_t numPRGs; - /// Size in RBs of a precoding resource block group (PRG) – to which same precoding and digital beamforming gets applied. Value: 1->275 - uint16_t prgSize; - /// Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255 - uint8_t digBFInterfaces; - uint16_t PMIdx[275]; - uint16_t *beamIdx[275]; -} nr_beamforming_t; typedef struct { ///Bandwidth part size [TS38.213 sec12]. Number of contiguous PRBs allocated to the BWP,Value: 1->275 @@ -696,7 +773,7 @@ typedef struct { ///Number of DCIs in this CORESET.Value: 0->MaxDciPerSlot uint16_t numDlDci; ///DL DCI PDU - nfapi_nr_dl_dci_pdu_t dci_pdu; + nfapi_nr_dl_dci_pdu_t dci_pdu[MAX_DCI_CORESET]; } nfapi_nr_dl_tti_pdcch_pdu_rel15_t; typedef struct { @@ -928,7 +1005,7 @@ typedef struct { typedef struct { uint16_t PDUType; - uint16_t PDUSize; + uint32_t PDUSize; union { nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu; @@ -939,6 +1016,7 @@ typedef struct { } nfapi_nr_dl_tti_request_pdu_t; #define NFAPI_NR_MAX_DL_TTI_PDUS 32 + typedef struct { /// Number of PDUs that are included in this message. All PDUs in the message are numbered in order. Value 0 -> 255 uint8_t nPDUs; @@ -952,11 +1030,28 @@ typedef struct { uint8_t PduIdx[256][12]; } nfapi_nr_dl_tti_request_body_t; + +typedef struct { + nfapi_p7_message_header_t header; + uint32_t t1; + int32_t delta_sfn_slot; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_dl_node_sync_t; + +typedef struct { + nfapi_p7_message_header_t header; + uint32_t t1; + uint32_t t2; + uint32_t t3; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_ul_node_sync_t; + + typedef struct { nfapi_p7_message_header_t header; /// System Frame Number (0-1023) uint16_t SFN; - /// Slot number (0-319) + /// Slot number (0-19) uint16_t Slot; nfapi_nr_dl_tti_request_body_t dl_tti_request_body; nfapi_vendor_extension_tlv_t vendor_extension; @@ -971,7 +1066,7 @@ typedef struct nfapi_nr_dl_tti_ssb_pdu_t* ssb_pdu; } nfapi_nr_dl_pdu_configuration_t; */ - /* + /* typedef struct { uint16_t pdu_type;//0: PDCCH PDU 1: PDSCH PDU 2: CSI-RS PDU 3: SSB PDU, @@ -1258,7 +1353,7 @@ typedef struct typedef struct { - uint8_t pdu_idx;//This value is an index for number of PDU identified by nPDU in this message Value: 0 -> 65535 + uint8_t pdu_idx;//This value is an index for number of PDU identified by nPDU in this message Value: 0 -> 255 } nfapi_nr_ul_tti_request_number_of_ue_t; @@ -1270,6 +1365,7 @@ typedef struct } nfapi_nr_ul_tti_request_number_of_groups_t; typedef struct { + nfapi_p7_message_header_t header; uint16_t SFN; //0->1023 uint16_t Slot;//0->319 uint8_t n_pdus;//Number of PDUs that are included in this message. All PDUs in the message are numbered in order. Value 0 -> 255 @@ -1316,6 +1412,7 @@ typedef struct { } nfapi_nr_ul_dci_request_pdus_t; typedef struct { + nfapi_p7_message_header_t header; uint16_t SFN; uint16_t Slot; uint8_t numPdus; @@ -1361,6 +1458,7 @@ typedef struct #define NFAPI_NR_MAX_TX_REQUEST_PDUS 16 typedef struct { + nfapi_p7_message_header_t header; uint16_t SFN; uint16_t Slot; uint16_t Number_of_PDUs; @@ -1395,10 +1493,11 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_of_pdus; - nfapi_nr_rx_data_pdu_t* pdu_list; + nfapi_nr_rx_data_pdu_t *pdu_list; } nfapi_nr_rx_data_indication_t; @@ -1421,6 +1520,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_crcs; @@ -1474,8 +1574,7 @@ typedef struct { uint8_t csi_part1_crc; uint16_t csi_part1_bit_len; - //! fixme - uint8_t* csi_part1_payload;//uint8_t[ceil(csiPart1BitLen/8)] + uint8_t* csi_part1_payload; } nfapi_nr_csi_part1_pdu_t; @@ -1484,8 +1583,7 @@ typedef struct { uint8_t csi_part2_crc; uint16_t csi_part2_bit_len; - //! fixme - uint8_t* csi_part2_payload;//uint8_t[ceil(csiPart2BitLen/8)] + uint8_t* csi_part2_payload; } nfapi_nr_csi_part2_pdu_t; //table 3-63 @@ -1539,7 +1637,7 @@ typedef struct }nfapi_nr_uci_pucch_pdu_format_2_3_4_t; typedef enum { - NFAPI_NR_UCI_PDCCH_PDU_TYPE = 0, + NFAPI_NR_UCI_PUSCH_PDU_TYPE = 0, NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE = 1, NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE = 2, } nfapi_nr_uci_pdu_type_e; @@ -1558,6 +1656,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t num_ucis; @@ -1594,6 +1693,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; @@ -1626,6 +1726,7 @@ typedef struct{ typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index 61c6875bc6..63dd8a16ae 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -1,969 +1,783 @@ -/* - * Copyright (c) 2001-2016, Cisco Systems, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * Neither the name of the Cisco Systems, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -// Fundamental routines - -uint8_t push8(uint8_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 1) - { - pOut[0] = in; - - (*out)+=1; - - return 1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } - -} - -uint8_t pushs8(int8_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 1) - { - pOut[0] = in; - - (*out)+=1; - - return 1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t push16(uint16_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 2) - { - pOut[0] = (in & 0xFF00) >> 8; - pOut[1] = (in & 0xFF); - - (*out)+=2; - - return 2; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pushs16(int16_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 2) - { - pOut[0] = (in & 0xFF00) >> 8; - pOut[1] = (in & 0xFF); - - (*out)+=2; - - return 2; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t push32(uint32_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - if((end - pOut) >= 4) - { - pOut[0] = (in & 0xFF000000) >> 24; - pOut[1] = (in & 0xFF0000) >> 16; - pOut[2] = (in & 0xFF00) >> 8; - pOut[3] = (in & 0xFF); - - (*out)+=4; - - return 4; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pushs32(int32_t in, uint8_t **out, uint8_t *end) -{ - uint8_t *pOut = *out; - - if((end - pOut) >= 4) - { - pOut[0] = (in & 0xFF000000) >> 24; - pOut[1] = (in & 0xFF0000) >> 16; - pOut[2] = (in & 0xFF00) >> 8; - pOut[3] = (in & 0xFF); - - (*out)+=4; - - return 4; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >= 1 ) - { - *out = *pIn; - - (*in)+=1; - - return 1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pulls8(uint8_t **in, int8_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >= 1 ) - { - *out = *pIn; - - (*in)+=1; - - return 1; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >=2 ) - { - *out = ((pIn[0]) << 8) | pIn[1]; - (*in)+=2; - - return 2; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >=2 ) - { - *out = ((pIn[0]) << 8) | pIn[1]; - - (*in)+=2; - - return 2; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >=4 ) - { - *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; - - (*in)+=4; - - return 4; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end) -{ - uint8_t *pIn = *in; - - if((end - pIn) >=4 ) - { - *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; - - (*in)+=4; - - return 4; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -/* -inline void pusharray16(uint8_t **, uint16_t, uint32_t len) -{ -} -*/ - -uint32_t pullarray16(uint8_t **in, uint16_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint16_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!pull16(in, &out[idx], end)) - return 0; - } - - return sizeof(uint16_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint32_t pullarrays16(uint8_t **in, int16_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint16_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!pulls16(in, &out[idx], end)) - return 0; - } - - return sizeof(uint16_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pusharray16(uint16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint16_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!push16(in[idx], out, end)) - return 0; - } - return sizeof(uint16_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pusharrays16(int16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint16_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - pushs16(in[idx], out, end); - } - return sizeof(uint16_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pullarray32(uint8_t **in, uint32_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint32_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!pull32(in, &out[idx], end)) - return 0; - } - - return sizeof(uint32_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint32_t pullarrays32(uint8_t **in, int32_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint32_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!pulls32(in, &out[idx], end)) - return 0; - } - - return sizeof(uint32_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pusharray32(uint32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint32_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - if(!push32(in[idx], out, end)) - return 0; - } - return sizeof(uint32_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pusharrays32(int32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint32_t) * len) - { - uint32_t idx; - for(idx = 0; idx < len; ++idx) - { - pushs32(in[idx], out, end); - } - return sizeof(uint32_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} -uint32_t pullarray8(uint8_t **in, uint8_t out[], uint32_t max_len, uint32_t len, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*in)) >= sizeof(uint8_t) * len) - { - memcpy(out, (*in), len); - (*in)+=len; - - return sizeof(uint8_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint32_t pusharray8(uint8_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) -{ - if(len == 0) - return 1; - - if(len > max_len) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); - return 0; - } - - if((end - (*out)) >= sizeof(uint8_t) * len) - { - memcpy((*out), in, len); - (*out)+=len; - - return sizeof(uint8_t) * len; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); - return 0; - } -} - -uint8_t packarray(void* array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t **ppwritepackedmsg, uint8_t *end, pack_array_elem_fn fn) -{ - if(count > max_count) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count); - return 0; - } - - uint16_t i = 0; - for(i = 0; i < count; ++i) - { - if((fn)(array, ppwritepackedmsg, end) == 0) - return 0; - - array += array_element_size; - } - - return 1; -} - -uint8_t unpackarray(uint8_t **ppReadPackedMsg, void* array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t *end, unpack_array_elem_fn fn) -{ - if(count > max_count) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count); - return 0; - } - - uint16_t i = 0; - for(i = 0; i < count; ++i) - { - if((fn)(array, ppReadPackedMsg, end) == 0) - return 0; - - array += array_element_size; - } - - return 1; -} - - -uint32_t pack_vendor_extension_tlv(nfapi_tl_t* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - if(ve != 0 && config != 0) - { - if(config->pack_vendor_extension_tlv) - { - - uint8_t* pStartOfTlv = *ppWritePackedMsg; - if(pack_tl(ve, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t* pStartOfValue = *ppWritePackedMsg; - if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0) - return 0; - - ve->length = (*ppWritePackedMsg) - pStartOfValue; - - pack_tl(ve, &pStartOfTlv, end); - - return 1; - - } - } - return 1; -} - -uint32_t unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config, nfapi_tl_t** ve_tlv) -{ - if(ve_tlv != 0 && config != 0) - { - if(config->unpack_vendor_extension_tlv) - { - return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void**)ve_tlv, config); - } - } - return 1; -} - -uint32_t pack_p7_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end ,nfapi_p7_codec_config_t* config) -{ - if(ve != 0 && config != 0) - { - if(config->pack_vendor_extension_tlv) - { - uint8_t* pStartOfTlv = *ppWritePackedMsg; - if(pack_tl(ve, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t* pStartOfValue = *ppWritePackedMsg; - if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0) - return 0; - - ve->length = (*ppWritePackedMsg) - pStartOfValue; - - pack_tl(ve, &pStartOfTlv, end); - - return 1; - - } - } - return 1; -} - -int unpack_p7_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config, nfapi_tl_t** ve_tlv) -{ - if(ve_tlv != 0 && config != 0) - { - if(config->unpack_vendor_extension_tlv) - { - return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void**)ve_tlv, config); - } - } - return 1; -} - - -uint8_t pack_tl(nfapi_tl_t *tl, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return (push16(tl->tag, ppWritePackedMsg, end) && - push16(tl->length, ppWritePackedMsg, end)); -} - -uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end) -{ - return (pull16(ppReadPackedMsg, &tl->tag, end) && - pull16(ppReadPackedMsg, &tl->length, end)); -} - -int unpack_tlv_list(unpack_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config, nfapi_tl_t** ve) -{ - nfapi_tl_t generic_tl; - uint8_t numBadTags = 0; - uint16_t idx = 0; - - while ((uint8_t*)(*ppReadPackedMsg) < end) - { - // unpack the tl and process the values accordingly - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - uint8_t tagMatch = 0; - - uint8_t* pStartOfValue = *ppReadPackedMsg; - - for(idx = 0; idx < size; ++idx) - { - if(unpack_fns[idx].tag == generic_tl.tag) - { - tagMatch = 1; - nfapi_tl_t* tl = (nfapi_tl_t*)(unpack_fns[idx].tlv); - tl->tag = generic_tl.tag; - tl->length = generic_tl.length; - - int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end); - - if(result == 0) - { - return 0; - } - - // check if the length was right; - if(tl->length != (*ppReadPackedMsg - pStartOfValue)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue)); - } - } - } - - if(tagMatch == 0) - { - - if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && - generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) - { - int result = unpack_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve); - if(result == 0) - { - // got tot the end. - return 0; - } - else if(result < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown VE TAG value: 0x%04x\n", generic_tl.tag); - - if (++numBadTags > MAX_BAD_TAG) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); - return 0; - } - - if((end - *ppReadPackedMsg) >= generic_tl.length) - { - // Advance past the unknown TLV - (*ppReadPackedMsg) += generic_tl.length; - } - else - { - // go to the end - return 0; - } - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); - - if (++numBadTags > MAX_BAD_TAG) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); - return 0; - } - - if((end - *ppReadPackedMsg) >= generic_tl.length) - { - // Advance past the unknown TLV - (*ppReadPackedMsg) += generic_tl.length; - } - else - { - // go to the end - return 0; - } - } - - } - } - - return 1; -} -int unpack_p7_tlv_list(unpack_p7_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t* end, nfapi_p7_codec_config_t* config, nfapi_tl_t** ve) -{ - nfapi_tl_t generic_tl; - uint8_t numBadTags = 0; - uint16_t idx = 0; - - while ((uint8_t*)(*ppReadPackedMsg) < end) - { - // unpack the tl and process the values accordingly - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - uint8_t tagMatch = 0; - - uint8_t* pStartOfValue = *ppReadPackedMsg; - - for(idx = 0; idx < size; ++idx) - { - if(unpack_fns[idx].tag == generic_tl.tag) - { - tagMatch = 1; - nfapi_tl_t* tl = (nfapi_tl_t*)(unpack_fns[idx].tlv); - tl->tag = generic_tl.tag; - tl->length = generic_tl.length; - - int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end , config); - - if(result == 0) - { - return 0; - } - - // check if the length was right; - if(tl->length != (*ppReadPackedMsg - pStartOfValue)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue)); - } - } - } - - if(tagMatch == 0) - { - - if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && - generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) - { - int result = unpack_p7_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve); - if(result == 0) - { - // got to end - return 0; - } - else if(result < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); - - if (++numBadTags > MAX_BAD_TAG) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); - return -1; - } - - if((end - *ppReadPackedMsg) >= generic_tl.length) - { - // Advance past the unknown TLV - (*ppReadPackedMsg) += generic_tl.length; - } - else - { - // got ot the dn - return 0; - } - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); - - if (++numBadTags > MAX_BAD_TAG) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); - return -1; - } - - if((end - *ppReadPackedMsg) >= generic_tl.length) - { - // Advance past the unknown TLV - (*ppReadPackedMsg) += generic_tl.length; - } - else - { - // got ot the dn - return 0; - } - - } - - } - } - - return 1; -} - -// This intermediate function deals with calculating the length of the value -// and writing into the tlv header. -uint8_t pack_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn) -{ - nfapi_tl_t* tl = (nfapi_tl_t*)tlv; - - // If the tag is defined - if(tl->tag == tag) - { - uint8_t* pStartOfTlv = *ppWritePackedMsg; - - // write a dumy tlv header - if(pack_tl(tl, ppWritePackedMsg, end) == 0) - return 0; - - // Record the start of the value - uint8_t* pStartOfValue = *ppWritePackedMsg; - - // pack the tlv value - if(fn(tlv, ppWritePackedMsg, end) == 0) - return 0; - - // calculate the length of the value and rewrite the tl header - tl->length = (*ppWritePackedMsg) - pStartOfValue; - - // rewrite the header with the correct length - pack_tl(tl, &pStartOfTlv, end); - } - else - { - if(tl->tag != 0) - { - NFAPI_TRACE(NFAPI_TRACE_WARN, "Warning pack_tlv tag 0x%x does not match expected 0x%x\n", tl->tag, tag); - } - else - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning pack_tlv tag 0x%x ZERO does not match expected 0x%x\n", tl->tag, tag); - } - } - - return 1; -} - -const char* nfapi_error_code_to_str(nfapi_error_code_e value) -{ - switch(value) - { - case NFAPI_MSG_OK: - return "NFAPI_MSG_OK"; - case NFAPI_MSG_INVALID_STATE: - return "NFAPI_MSG_INVALID_STATE"; - case NFAPI_MSG_INVALID_CONFIG: - return "NFAPI_MSG_INVALID_CONFIG"; - case NFAPI_SFN_OUT_OF_SYNC: - return "NFAPI_SFN_OUT_OF_SYNC"; - case NFAPI_MSG_SUBFRAME_ERR: - return "NFAPI_MSG_SUBFRAME_ERR"; - case NFAPI_MSG_BCH_MISSING: - return "NFAPI_MSG_BCH_MISSING"; - case NFAPI_MSG_INVALID_SFN: - return "NFAPI_MSG_INVALID_SFN"; - case NFAPI_MSG_HI_ERR: - return "NFAPI_MSG_HI_ERR"; - case NFAPI_MSG_TX_ERR: - return "NFAPI_MSG_TX_ERR"; - default: - return "UNKNOWN"; - } -} +/* + * Copyright (c) 2001-2016, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +// Fundamental routines + +uint8_t push8(uint8_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 1) { + pOut[0] = in; + (*out)+=1; + return 1; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pushs8(int8_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 1) { + pOut[0] = in; + (*out)+=1; + return 1; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t push16(uint16_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 2) { + pOut[0] = (in & 0xFF00) >> 8; + pOut[1] = (in & 0xFF); + (*out)+=2; + return 2; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pushs16(int16_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 2) { + pOut[0] = (in & 0xFF00) >> 8; + pOut[1] = (in & 0xFF); + (*out)+=2; + return 2; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t push32(uint32_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 4) { + pOut[0] = (in & 0xFF000000) >> 24; + pOut[1] = (in & 0xFF0000) >> 16; + pOut[2] = (in & 0xFF00) >> 8; + pOut[3] = (in & 0xFF); + (*out)+=4; + return 4; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pushs32(int32_t in, uint8_t **out, uint8_t *end) { + uint8_t *pOut = *out; + + if((end - pOut) >= 4) { + pOut[0] = (in & 0xFF000000) >> 24; + pOut[1] = (in & 0xFF0000) >> 16; + pOut[2] = (in & 0xFF00) >> 8; + pOut[3] = (in & 0xFF); + (*out)+=4; + return 4; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >= 1 ) { + *out = *pIn; + (*in)+=1; + return 1; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pulls8(uint8_t **in, int8_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >= 1 ) { + *out = *pIn; + (*in)+=1; + return 1; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pull16(uint8_t **in, uint16_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >=2 ) { + *out = ((pIn[0]) << 8) | pIn[1]; + (*in)+=2; + return 2; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pulls16(uint8_t **in, int16_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >=2 ) { + *out = ((pIn[0]) << 8) | pIn[1]; + (*in)+=2; + return 2; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pull32(uint8_t **in, uint32_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >=4 ) { + *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; + (*in)+=4; + return 4; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t pulls32(uint8_t **in, int32_t *out, uint8_t *end) { + uint8_t *pIn = *in; + + if((end - pIn) >=4 ) { + *out = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3]; + (*in)+=4; + return 4; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +/* +inline void pusharray16(uint8_t **, uint16_t, uint32_t len) +{ +} +*/ + +uint32_t pullarray16(uint8_t **in, uint16_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint16_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!pull16(in, &out[idx], end)) + return 0; + } + + return sizeof(uint16_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint32_t pullarrays16(uint8_t **in, int16_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint16_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!pulls16(in, &out[idx], end)) + return 0; + } + + return sizeof(uint16_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pusharray16(uint16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint16_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!push16(in[idx], out, end)) + return 0; + } + + return sizeof(uint16_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pusharrays16(int16_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint16_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + pushs16(in[idx], out, end); + } + + return sizeof(uint16_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pullarray32(uint8_t **in, uint32_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint32_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!pull32(in, &out[idx], end)) + return 0; + } + + return sizeof(uint32_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint32_t pullarrays32(uint8_t **in, int32_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint32_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!pulls32(in, &out[idx], end)) + return 0; + } + + return sizeof(uint32_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pusharray32(uint32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint32_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + if(!push32(in[idx], out, end)) + return 0; + } + + return sizeof(uint32_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pusharrays32(int32_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint32_t) * len) { + uint32_t idx; + + for(idx = 0; idx < len; ++idx) { + pushs32(in[idx], out, end); + } + + return sizeof(uint32_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} +uint32_t pullarray8(uint8_t **in, uint8_t out[], uint32_t max_len, uint32_t len, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*in)) >= sizeof(uint8_t) * len) { + memcpy(out, (*in), len); + (*in)+=len; + return sizeof(uint8_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint32_t pusharray8(uint8_t in[], uint32_t max_len, uint32_t len, uint8_t **out, uint8_t *end) { + if(len == 0) + return 1; + + if(len > max_len) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, len, max_len); + return 0; + } + + if((end - (*out)) >= sizeof(uint8_t) * len) { + memcpy((*out), in, len); + (*out)+=len; + return sizeof(uint8_t) * len; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); + return 0; + } +} + +uint8_t packarray(void *array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t **ppwritepackedmsg, uint8_t *end, pack_array_elem_fn fn) { + if(count > max_count) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count); + return 0; + } + + uint16_t i = 0; + + for(i = 0; i < count; ++i) { + if((fn)(array, ppwritepackedmsg, end) == 0) + return 0; + + array += array_element_size; + } + + return 1; +} + +uint8_t unpackarray(uint8_t **ppReadPackedMsg, void *array, uint16_t array_element_size, uint16_t max_count, uint16_t count, uint8_t *end, unpack_array_elem_fn fn) { + if(count > max_count) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s exceed array size (%d > %d)\n", __FUNCTION__, count, max_count); + return 0; + } + + uint16_t i = 0; + + for(i = 0; i < count; ++i) { + if((fn)(array, ppReadPackedMsg, end) == 0) + return 0; + + array += array_element_size; + } + + return 1; +} + + +uint32_t pack_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + if(ve != 0 && config != 0) { + if(config->pack_vendor_extension_tlv) { + uint8_t *pStartOfTlv = *ppWritePackedMsg; + + if(pack_tl(ve, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t *pStartOfValue = *ppWritePackedMsg; + + if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0) + return 0; + + ve->length = (*ppWritePackedMsg) - pStartOfValue; + pack_tl(ve, &pStartOfTlv, end); + return 1; + } + } + + return 1; +} + +uint32_t unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config, nfapi_tl_t **ve_tlv) { + if(ve_tlv != 0 && config != 0) { + if(config->unpack_vendor_extension_tlv) { + return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void **)ve_tlv, config); + } + } + + return 1; +} + +uint32_t pack_p7_vendor_extension_tlv(nfapi_tl_t *ve, uint8_t **ppWritePackedMsg, uint8_t *end,nfapi_p7_codec_config_t *config) { + if(ve != 0 && config != 0) { + if(config->pack_vendor_extension_tlv) { + uint8_t *pStartOfTlv = *ppWritePackedMsg; + + if(pack_tl(ve, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t *pStartOfValue = *ppWritePackedMsg; + + if((config->pack_vendor_extension_tlv)(ve, ppWritePackedMsg, end, config) == 0) + return 0; + + ve->length = (*ppWritePackedMsg) - pStartOfValue; + pack_tl(ve, &pStartOfTlv, end); + return 1; + } + } + + return 1; +} + +int unpack_p7_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config, nfapi_tl_t **ve_tlv) { + if(ve_tlv != 0 && config != 0) { + if(config->unpack_vendor_extension_tlv) { + return (config->unpack_vendor_extension_tlv)(tl, ppReadPackedMsg, end, (void **)ve_tlv, config); + } + } + + return 1; +} + + +uint8_t pack_tl(nfapi_tl_t *tl, uint8_t **ppWritePackedMsg, uint8_t *end) { + return (push16(tl->tag, ppWritePackedMsg, end) && + push16(tl->length, ppWritePackedMsg, end)); +} + +uint8_t unpack_tl(uint8_t **ppReadPackedMsg, nfapi_tl_t *tl, uint8_t *end) { + return (pull16(ppReadPackedMsg, &tl->tag, end) && + pull16(ppReadPackedMsg, &tl->length, end)); +} + +int unpack_tlv_list(unpack_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config, nfapi_tl_t **ve) { + nfapi_tl_t generic_tl; + uint8_t numBadTags = 0; + uint16_t idx = 0; + + while ((uint8_t *)(*ppReadPackedMsg) < end) { + // unpack the tl and process the values accordingly + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + uint8_t tagMatch = 0; + uint8_t *pStartOfValue = *ppReadPackedMsg; + + for(idx = 0; idx < size; ++idx) { + if(unpack_fns[idx].tag == generic_tl.tag) { // match the extracted tag value with all the tags in unpack_fn list + tagMatch = 1; + nfapi_tl_t *tl = (nfapi_tl_t *)(unpack_fns[idx].tlv); + tl->tag = generic_tl.tag; + tl->length = generic_tl.length; + int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end); + + if(result == 0) { + return 0; + } + + // check if the length was right; + if(tl->length != (*ppReadPackedMsg - pStartOfValue)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue)); + } + } + } + + if(tagMatch == 0) { + if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && + generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) { + int result = unpack_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve); + + if(result == 0) { + // got tot the end. + return 0; + } else if(result < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown VE TAG value: 0x%04x\n", generic_tl.tag); + + if (++numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + return 0; + } + + if((end - *ppReadPackedMsg) >= generic_tl.length) { + // Advance past the unknown TLV + (*ppReadPackedMsg) += generic_tl.length; + } else { + // go to the end + return 0; + } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); + + if (++numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + return 0; + } + + if((end - *ppReadPackedMsg) >= generic_tl.length) { + // Advance past the unknown TLV + (*ppReadPackedMsg) += generic_tl.length; + } else { + // go to the end + return 0; + } + } + } + } + + return 1; +} +int unpack_p7_tlv_list(unpack_p7_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config, nfapi_tl_t **ve) { + nfapi_tl_t generic_tl; + uint8_t numBadTags = 0; + uint16_t idx = 0; + + while ((uint8_t *)(*ppReadPackedMsg) < end) { + // unpack the tl and process the values accordingly + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + uint8_t tagMatch = 0; + uint8_t *pStartOfValue = *ppReadPackedMsg; + + for(idx = 0; idx < size; ++idx) { + if(unpack_fns[idx].tag == generic_tl.tag) { + tagMatch = 1; + nfapi_tl_t *tl = (nfapi_tl_t *)(unpack_fns[idx].tlv); + tl->tag = generic_tl.tag; + tl->length = generic_tl.length; + int result = (*unpack_fns[idx].unpack_func)(tl, ppReadPackedMsg, end, config); + + if(result == 0) { + return 0; + } + + // check if the length was right; + if(tl->length != (*ppReadPackedMsg - pStartOfValue)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning tlv tag 0x%x length %d not equal to unpack %d\n", tl->tag, tl->length, (*ppReadPackedMsg - pStartOfValue)); + } + } + } + + if(tagMatch == 0) { + if(generic_tl.tag >= NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE && + generic_tl.tag <= NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE) { + int result = unpack_p7_vendor_extension_tlv(&generic_tl, ppReadPackedMsg, end, config, ve); + + if(result == 0) { + // got to end + return 0; + } else if(result < 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); + + if (++numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + return -1; + } + + if((end - *ppReadPackedMsg) >= generic_tl.length) { + // Advance past the unknown TLV + (*ppReadPackedMsg) += generic_tl.length; + } else { + // got ot the dn + return 0; + } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown TAG value: 0x%04x\n", generic_tl.tag); + + if (++numBadTags > MAX_BAD_TAG) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Supplied message has had too many bad tags\n"); + return -1; + } + + if((end - *ppReadPackedMsg) >= generic_tl.length) { + // Advance past the unknown TLV + (*ppReadPackedMsg) += generic_tl.length; + } else { + // got ot the dn + return 0; + } + } + } + } + + return 1; +} + +// This intermediate function deals with calculating the length of the value +// and writing into the tlv header. +uint8_t pack_tlv(uint16_t tag, void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, pack_tlv_fn fn) { + nfapi_tl_t *tl = (nfapi_tl_t *)tlv; + + // If the tag is defined + if(tl->tag == tag) { + uint8_t *pStartOfTlv = *ppWritePackedMsg; + + // write a dumy tlv header + if(pack_tl(tl, ppWritePackedMsg, end) == 0) + return 0; + + // Record the start of the value + uint8_t *pStartOfValue = *ppWritePackedMsg; + + // pack the tlv value + if(fn(tlv, ppWritePackedMsg, end) == 0) + return 0; + + // calculate the length of the value and rewrite the tl header + tl->length = (*ppWritePackedMsg) - pStartOfValue; + // rewrite the header with the correct length + pack_tl(tl, &pStartOfTlv, end); + } else { + if(tl->tag != 0) { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Warning pack_tlv tag 0x%x does not match expected 0x%x\n", tl->tag, tag); + } else { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "Warning pack_tlv tag 0x%x ZERO does not match expected 0x%x\n", tl->tag, tag); + } + } + + return 1; +} + +const char *nfapi_error_code_to_str(nfapi_error_code_e value) { + switch(value) { + case NFAPI_MSG_OK: + return "NFAPI_MSG_OK"; + + case NFAPI_MSG_INVALID_STATE: + return "NFAPI_MSG_INVALID_STATE"; + + case NFAPI_MSG_INVALID_CONFIG: + return "NFAPI_MSG_INVALID_CONFIG"; + + case NFAPI_SFN_OUT_OF_SYNC: + return "NFAPI_SFN_OUT_OF_SYNC"; + + case NFAPI_MSG_SUBFRAME_ERR: + return "NFAPI_MSG_SUBFRAME_ERR"; + + case NFAPI_MSG_BCH_MISSING: + return "NFAPI_MSG_BCH_MISSING"; + + case NFAPI_MSG_INVALID_SFN: + return "NFAPI_MSG_INVALID_SFN"; + + case NFAPI_MSG_HI_ERR: + return "NFAPI_MSG_HI_ERR"; + + case NFAPI_MSG_TX_ERR: + return "NFAPI_MSG_TX_ERR"; + + default: + return "UNKNOWN"; + } +} diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c index b429e0a6ce..dbaa4347d3 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p4.c @@ -1,12 +1,12 @@ /* * Copyright 2017 Cisco Systems, Inc. - * + * * 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. @@ -27,2059 +27,1804 @@ #include #include -static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) -{ - if (msgEnd < msgHead) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd); - return 0; - } - - return (msgEnd - msgHead); +static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) { + if (msgEnd < msgHead) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd); + return 0; + } + + return (msgEnd - msgHead); +} + +static uint8_t pack_opaque_data_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_opaqaue_data_t *value = (nfapi_opaqaue_data_t *)tlv; + return pusharray8(value->value, NFAPI_MAX_OPAQUE_DATA, value->length, ppWritePackedMsg, end); +} + +static uint8_t unpack_opaque_data_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_opaqaue_data_t *value = (nfapi_opaqaue_data_t *)tlv; + value->length = value->tl.length; + + if(value->length <= NFAPI_MAX_OPAQUE_DATA) { + if(!pullarray8(ppReadPackedMsg, value->value, NFAPI_MAX_OPAQUE_DATA, value->length, end)) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Opaque date to long %d \n", value->length); + return 0; + } + + return 1; +} + +static uint8_t pack_lte_rssi_request_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_rssi_request_t *value = (nfapi_lte_rssi_request_t *)tlv; + return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) && + push16(value->measurement_period, ppWritePackedMsg, end) && + push8(value->bandwidth, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_earfcns, ppWritePackedMsg, end) && + pusharray16(value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, ppWritePackedMsg, end)); +} + +static uint8_t pack_utran_rssi_request_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_rssi_request_t *value = (nfapi_utran_rssi_request_t *)tlv; + return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) && + push16(value->measurement_period, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_uarfcns, ppWritePackedMsg, end) && + pusharray16(value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, ppWritePackedMsg, end)); } -static uint8_t pack_opaque_data_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_opaqaue_data_t* value = (nfapi_opaqaue_data_t*)tlv; - return pusharray8(value->value, NFAPI_MAX_OPAQUE_DATA, value->length, ppWritePackedMsg, end); -} +static uint8_t pack_geran_rssi_request_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_rssi_request_t *value = (nfapi_geran_rssi_request_t *)tlv; + uint16_t idx = 0; -static uint8_t unpack_opaque_data_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_opaqaue_data_t* value = (nfapi_opaqaue_data_t*)tlv; - value->length = value->tl.length; - if(value->length <= NFAPI_MAX_OPAQUE_DATA) - { - if(!pullarray8(ppReadPackedMsg, value->value, NFAPI_MAX_OPAQUE_DATA, value->length, end)) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Opaque date to long %d \n", value->length); - return 0; - } - - return 1; - -} - -static uint8_t pack_lte_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_rssi_request_t* value = (nfapi_lte_rssi_request_t*)tlv; - - return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) && - push16(value->measurement_period, ppWritePackedMsg, end) && - push8(value->bandwidth, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_earfcns, ppWritePackedMsg, end) && - pusharray16(value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, ppWritePackedMsg, end)); -} - -static uint8_t pack_utran_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_rssi_request_t* value = (nfapi_utran_rssi_request_t*)tlv; - - return (push8(value->frequency_band_indicator, ppWritePackedMsg, end) && - push16(value->measurement_period, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_uarfcns, ppWritePackedMsg, end) && - pusharray16(value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, ppWritePackedMsg, end)); -} - -static uint8_t pack_geran_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_rssi_request_t* value = (nfapi_geran_rssi_request_t*)tlv; - uint16_t idx = 0; - - if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) && - push16(value->measurement_period, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_arfcns, ppWritePackedMsg, end))) - return 0; + if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) && + push16(value->measurement_period, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_arfcns, ppWritePackedMsg, end))) + return 0; - for(;idx < value->number_of_arfcns; ++idx) - { - if(!(push16(value->arfcn[idx].arfcn, ppWritePackedMsg, end) && - push8(value->arfcn[idx].direction, ppWritePackedMsg, end))) - return 0; - } - - return 1; + for(; idx < value->number_of_arfcns; ++idx) { + if(!(push16(value->arfcn[idx].arfcn, ppWritePackedMsg, end) && + push8(value->arfcn[idx].direction, ppWritePackedMsg, end))) + return 0; + } + + return 1; } -static uint8_t pack_nb_iot_rssi_request_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_rssi_request_t* value = (nfapi_nb_iot_rssi_request_t*)tlv; - uint16_t idx = 0; +static uint8_t pack_nb_iot_rssi_request_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_rssi_request_t *value = (nfapi_nb_iot_rssi_request_t *)tlv; + uint16_t idx = 0; - if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) && - push16(value->measurement_period, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_earfcns, ppWritePackedMsg, end))) - return 0; + if(!(push8(value->frequency_band_indicator, ppWritePackedMsg, end) && + push16(value->measurement_period, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_earfcns, ppWritePackedMsg, end))) + return 0; - for(;idx < value->number_of_earfcns; ++idx) - { - if(!(push16(value->earfcn[idx].earfcn, ppWritePackedMsg, end) && - push8(value->earfcn[idx].number_of_ro_dl, ppWritePackedMsg, end))) - return 0; - - uint8_t ro_dl_idx = 0; - for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx) - { - if(!push8(value->earfcn[idx].ro_dl[ro_dl_idx], ppWritePackedMsg, end)) - return 0; - } - } + for(; idx < value->number_of_earfcns; ++idx) { + if(!(push16(value->earfcn[idx].earfcn, ppWritePackedMsg, end) && + push8(value->earfcn[idx].number_of_ro_dl, ppWritePackedMsg, end))) + return 0; - return 1; + uint8_t ro_dl_idx = 0; + + for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx) { + if(!push8(value->earfcn[idx].ro_dl[ro_dl_idx], ppWritePackedMsg, end)) + return 0; + } + } + + return 1; } -static uint8_t pack_rssi_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t*)msg; +static uint8_t pack_rssi_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: + if(pack_tlv(NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, ppWritePackedMsg, end, &pack_lte_rssi_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_UTRAN: + if(pack_tlv(NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, ppWritePackedMsg, end, &pack_utran_rssi_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_GERAN: + if(pack_tlv(NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, ppWritePackedMsg, end, &pack_geran_rssi_request_value) == 0) + return 0; - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; + break; - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - if(pack_tlv(NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, ppWritePackedMsg, end, &pack_lte_rssi_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_UTRAN: - if(pack_tlv(NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, ppWritePackedMsg, end, &pack_utran_rssi_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_GERAN: - if(pack_tlv(NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, ppWritePackedMsg, end, &pack_geran_rssi_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_NB_IOT: - if(pack_tlv(NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, ppWritePackedMsg, end, &pack_nb_iot_rssi_request_value) == 0) - return 0; - break; - } - - return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_rssi_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_rssi_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rssi_indication_body_t* value = (nfapi_rssi_indication_body_t*)tlv; - - return (push16(value->number_of_rssi, ppWritePackedMsg, end) && - pusharrays16(value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, ppWritePackedMsg, end)); -} - -static uint8_t pack_rssi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, ppWritePackedMsg, end, &pack_rssi_indication_body_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -static uint8_t pack_lte_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_cell_search_request_t* value = (nfapi_lte_cell_search_request_t*)msg; - - return (push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->measurement_bandwidth, ppWritePackedMsg, end) && - push8(value->exhaustive_search, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_pci, ppWritePackedMsg, end) && - pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end)); -} - -static uint8_t pack_utran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_cell_search_request_t* value = (nfapi_utran_cell_search_request_t*)msg; - - return (push16(value->uarfcn, ppWritePackedMsg, end) && - push8(value->exhaustive_search, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_psc, ppWritePackedMsg, end) && - pusharray16(value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, ppWritePackedMsg, end)); -} - -static uint8_t pack_geran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_cell_search_request_t* value = (nfapi_geran_cell_search_request_t*)msg; - - return (push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_arfcn, ppWritePackedMsg, end) && - pusharray16(value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, ppWritePackedMsg, end)); -} - -static uint8_t pack_nb_iot_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_cell_search_request_t* value = (nfapi_nb_iot_cell_search_request_t*)msg; - - return (push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->ro_dl, ppWritePackedMsg, end) && - push8(value->exhaustive_search, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end) && - push8(value->number_of_pci, ppWritePackedMsg, end) && - pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end)); -} - - -static uint8_t pack_cell_search_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t*)msg; - - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; - - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - { - if(pack_tlv(NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, ppWritePackedMsg, end, &pack_lte_cell_search_request_value) == 0) - return 0; - } - break; - case NFAPI_RAT_TYPE_UTRAN: - { - if(pack_tlv(NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, ppWritePackedMsg, end, &pack_utran_cell_search_request_value) == 0) - return 0; - } - break; - case NFAPI_RAT_TYPE_GERAN: - { - if(pack_tlv(NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, ppWritePackedMsg, end, &pack_geran_cell_search_request_value) == 0) - return 0; - } - break; - case NFAPI_RAT_TYPE_NB_IOT: - { - if(pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, ppWritePackedMsg, end, &pack_nb_iot_cell_search_request_value) == 0) - return 0; - } - break; - }; - - return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_cell_search_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_lte_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_cell_search_indication_t* value = (nfapi_lte_cell_search_indication_t*)msg; - uint16_t idx = 0; - - if(push16(value->number_of_lte_cells_found, ppWritePackedMsg, end) == 0) - return 0; - - for(idx = 0; idx < value->number_of_lte_cells_found; ++idx) - { - if(!(push16(value->lte_found_cells[idx].pci, ppWritePackedMsg, end) && - push8(value->lte_found_cells[idx].rsrp, ppWritePackedMsg, end) && - push8(value->lte_found_cells[idx].rsrq, ppWritePackedMsg, end) && - pushs16(value->lte_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) - return 0; - } - return 1; -} - -static uint8_t pack_utran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_cell_search_indication_t* value = (nfapi_utran_cell_search_indication_t*)msg; - uint16_t idx = 0; - - if(push16(value->number_of_utran_cells_found, ppWritePackedMsg, end) == 0) - return 0; - - for(idx = 0; idx < value->number_of_utran_cells_found; ++idx) - { - if(!(push16(value->utran_found_cells[idx].psc, ppWritePackedMsg, end) && - push8(value->utran_found_cells[idx].rscp, ppWritePackedMsg, end) && - push8(value->utran_found_cells[idx].ecno, ppWritePackedMsg, end) && - pushs16(value->utran_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -static uint8_t pack_geran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_cell_search_indication_t* value = (nfapi_geran_cell_search_indication_t*)msg; - uint16_t idx = 0; - - if(push16(value->number_of_gsm_cells_found, ppWritePackedMsg, end) == 0) - return 0; - - for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx) - { - if(!(push16(value->gsm_found_cells[idx].arfcn, ppWritePackedMsg, end) && - push8(value->gsm_found_cells[idx].bsic, ppWritePackedMsg, end) && - push8(value->gsm_found_cells[idx].rxlev, ppWritePackedMsg, end) && - push8(value->gsm_found_cells[idx].rxqual, ppWritePackedMsg, end) && - pushs16(value->gsm_found_cells[idx].frequency_offset, ppWritePackedMsg, end) && - push32(value->gsm_found_cells[idx].sfn_offset, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -static uint8_t pack_nb_iot_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_cell_search_indication_t* value = (nfapi_nb_iot_cell_search_indication_t*)msg; - uint16_t idx = 0; - - if(push16(value->number_of_nb_iot_cells_found, ppWritePackedMsg, end) == 0) - return 0; - - for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx) - { - if(!(push16(value->nb_iot_found_cells[idx].pci, ppWritePackedMsg, end) && - push8(value->nb_iot_found_cells[idx].rsrp, ppWritePackedMsg, end) && - push8(value->nb_iot_found_cells[idx].rsrq, ppWritePackedMsg, end) && - pushs16(value->nb_iot_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} -static uint8_t pack_cell_search_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, ppWritePackedMsg, end, &pack_lte_cell_search_indication_value) && - pack_tlv(NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, ppWritePackedMsg, end, &pack_utran_cell_search_indication_value) && - pack_tlv(NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, ppWritePackedMsg, end, &pack_geran_cell_search_indication_value) && - pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, ppWritePackedMsg, end, &pack_nb_iot_cell_search_indication_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_lte_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_broadcast_detect_request_t* value = (nfapi_lte_broadcast_detect_request_t*)msg; - - return (push16(value->earfcn, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} - -static uint8_t pack_utran_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_broadcast_detect_request_t* value = (nfapi_utran_broadcast_detect_request_t*)msg; - - return (push16(value->uarfcn, ppWritePackedMsg, end) && - push16(value->psc, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} - -static uint8_t pack_nb_iot_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_broadcast_detect_request_t* value = (nfapi_nb_iot_broadcast_detect_request_t*)msg; + case NFAPI_RAT_TYPE_NB_IOT: + if(pack_tlv(NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, ppWritePackedMsg, end, &pack_nb_iot_rssi_request_value) == 0) + return 0; - return (push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->ro_dl, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} - -static uint8_t pack_broadcast_detect_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t * end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t*)msg; + break; + } - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_rssi_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - if(pack_tlv(NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, ppWritePackedMsg, end ,&pack_lte_broadcast_detect_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_UTRAN: - if(pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, ppWritePackedMsg, end, &pack_utran_broadcast_detect_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_NB_IOT: - if(pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_request_value) == 0) - return 0; - break; - - } - - return (pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_rssi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rssi_indication_body_t *value = (nfapi_rssi_indication_body_t *)tlv; + return (push16(value->number_of_rssi, ppWritePackedMsg, end) && + pusharrays16(value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, ppWritePackedMsg, end)); } -static uint8_t pack_broadcast_detect_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_rssi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, ppWritePackedMsg, end, &pack_rssi_indication_body_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_lte_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_broadcast_detect_indication_t* value = (nfapi_lte_broadcast_detect_indication_t*)msg; - return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && - push16(value->mib_length, ppWritePackedMsg, end) && - pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && - push32(value->sfn_offset, ppWritePackedMsg, end)); +static uint8_t pack_lte_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_cell_search_request_t *value = (nfapi_lte_cell_search_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->measurement_bandwidth, ppWritePackedMsg, end) && + push8(value->exhaustive_search, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_pci, ppWritePackedMsg, end) && + pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end)); } -static uint8_t pack_utran_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_broadcast_detect_indication_t* value = (nfapi_utran_broadcast_detect_indication_t*)msg; +static uint8_t pack_utran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_cell_search_request_t *value = (nfapi_utran_cell_search_request_t *)msg; + return (push16(value->uarfcn, ppWritePackedMsg, end) && + push8(value->exhaustive_search, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_psc, ppWritePackedMsg, end) && + pusharray16(value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, ppWritePackedMsg, end)); +} + +static uint8_t pack_geran_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_cell_search_request_t *value = (nfapi_geran_cell_search_request_t *)msg; + return (push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_arfcn, ppWritePackedMsg, end) && + pusharray16(value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, ppWritePackedMsg, end)); +} - return (push16(value->mib_length, ppWritePackedMsg, end) && - pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && - push32(value->sfn_offset, ppWritePackedMsg, end)); +static uint8_t pack_nb_iot_cell_search_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_cell_search_request_t *value = (nfapi_nb_iot_cell_search_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->ro_dl, ppWritePackedMsg, end) && + push8(value->exhaustive_search, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end) && + push8(value->number_of_pci, ppWritePackedMsg, end) && + pusharray16(value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, ppWritePackedMsg, end)); } -static uint8_t pack_nb_iot_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_broadcast_detect_indication_t* value = (nfapi_nb_iot_broadcast_detect_indication_t*)msg; - return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && - push16(value->mib_length, ppWritePackedMsg, end) && - pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && - push32(value->sfn_offset, ppWritePackedMsg, end)); +static uint8_t pack_cell_search_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: { + if(pack_tlv(NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, ppWritePackedMsg, end, &pack_lte_cell_search_request_value) == 0) + return 0; + } + break; + + case NFAPI_RAT_TYPE_UTRAN: { + if(pack_tlv(NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, ppWritePackedMsg, end, &pack_utran_cell_search_request_value) == 0) + return 0; + } + break; + + case NFAPI_RAT_TYPE_GERAN: { + if(pack_tlv(NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, ppWritePackedMsg, end, &pack_geran_cell_search_request_value) == 0) + return 0; + } + break; + + case NFAPI_RAT_TYPE_NB_IOT: { + if(pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, ppWritePackedMsg, end, &pack_nb_iot_cell_search_request_value) == 0) + return 0; + } + break; + }; + + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_cell_search_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_broadcast_detect_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t*)msg; +static uint8_t pack_lte_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_cell_search_indication_t *value = (nfapi_lte_cell_search_indication_t *)msg; + uint16_t idx = 0; - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, ppWritePackedMsg, end, &pack_lte_broadcast_detect_indication_value) && - pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, ppWritePackedMsg, end, &pack_utran_broadcast_detect_indication_value) && - pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_indication_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + if(push16(value->number_of_lte_cells_found, ppWritePackedMsg, end) == 0) + return 0; + + for(idx = 0; idx < value->number_of_lte_cells_found; ++idx) { + if(!(push16(value->lte_found_cells[idx].pci, ppWritePackedMsg, end) && + push8(value->lte_found_cells[idx].rsrp, ppWritePackedMsg, end) && + push8(value->lte_found_cells[idx].rsrq, ppWritePackedMsg, end) && + pushs16(value->lte_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) + return 0; + } + + return 1; } -static uint8_t pack_lte_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_schedule_request_t* value = (nfapi_lte_system_information_schedule_request_t*)msg; +static uint8_t pack_utran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_cell_search_indication_t *value = (nfapi_utran_cell_search_indication_t *)msg; + uint16_t idx = 0; + + if(push16(value->number_of_utran_cells_found, ppWritePackedMsg, end) == 0) + return 0; - return (push16(value->earfcn, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) && - push8(value->phich_configuration, ppWritePackedMsg, end) && - push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && - push8(value->retry_count, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); + for(idx = 0; idx < value->number_of_utran_cells_found; ++idx) { + if(!(push16(value->utran_found_cells[idx].psc, ppWritePackedMsg, end) && + push8(value->utran_found_cells[idx].rscp, ppWritePackedMsg, end) && + push8(value->utran_found_cells[idx].ecno, ppWritePackedMsg, end) && + pushs16(value->utran_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) + return 0; + } + + return 1; } -static uint8_t pack_nb_iot_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_schedule_request_t* value = (nfapi_nb_iot_system_information_schedule_request_t*)msg; +static uint8_t pack_geran_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_cell_search_indication_t *value = (nfapi_geran_cell_search_indication_t *)msg; + uint16_t idx = 0; + + if(push16(value->number_of_gsm_cells_found, ppWritePackedMsg, end) == 0) + return 0; + + for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx) { + if(!(push16(value->gsm_found_cells[idx].arfcn, ppWritePackedMsg, end) && + push8(value->gsm_found_cells[idx].bsic, ppWritePackedMsg, end) && + push8(value->gsm_found_cells[idx].rxlev, ppWritePackedMsg, end) && + push8(value->gsm_found_cells[idx].rxqual, ppWritePackedMsg, end) && + pushs16(value->gsm_found_cells[idx].frequency_offset, ppWritePackedMsg, end) && + push32(value->gsm_found_cells[idx].sfn_offset, ppWritePackedMsg, end))) + return 0; + } - return (push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->ro_dl, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push8(value->scheduling_info_sib1_nb, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); + return 1; } +static uint8_t pack_nb_iot_cell_search_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_cell_search_indication_t *value = (nfapi_nb_iot_cell_search_indication_t *)msg; + uint16_t idx = 0; -static uint8_t pack_system_information_schedule_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t*)msg; + if(push16(value->number_of_nb_iot_cells_found, ppWritePackedMsg, end) == 0) + return 0; - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; + for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx) { + if(!(push16(value->nb_iot_found_cells[idx].pci, ppWritePackedMsg, end) && + push8(value->nb_iot_found_cells[idx].rsrp, ppWritePackedMsg, end) && + push8(value->nb_iot_found_cells[idx].rsrq, ppWritePackedMsg, end) && + pushs16(value->nb_iot_found_cells[idx].frequency_offset, ppWritePackedMsg, end))) + return 0; + } - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, ppWritePackedMsg, end, &pack_lte_system_information_schedule_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_NB_IOT: - if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, ppWritePackedMsg, end, &pack_nb_iot_system_information_schedule_request_value) == 0) - return 0; - break; - } + return 1; +} +static uint8_t pack_cell_search_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, ppWritePackedMsg, end, &pack_lte_cell_search_indication_value) && + pack_tlv(NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, ppWritePackedMsg, end, &pack_utran_cell_search_indication_value) && + pack_tlv(NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, ppWritePackedMsg, end, &pack_geran_cell_search_indication_value) && + pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_tlv(NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, ppWritePackedMsg, end, &pack_nb_iot_cell_search_indication_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_lte_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_broadcast_detect_request_t *value = (nfapi_lte_broadcast_detect_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); +} +static uint8_t pack_utran_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_broadcast_detect_request_t *value = (nfapi_utran_broadcast_detect_request_t *)msg; + return (push16(value->uarfcn, ppWritePackedMsg, end) && + push16(value->psc, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } -static uint8_t pack_system_information_schedule_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +static uint8_t pack_nb_iot_broadcast_detect_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_broadcast_detect_request_t *value = (nfapi_nb_iot_broadcast_detect_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->ro_dl, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } -static uint8_t pack_lte_system_information_indication_value(void* msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_indication_t* value = (nfapi_lte_system_information_indication_t*)msg; +static uint8_t pack_broadcast_detect_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: + if(pack_tlv(NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, ppWritePackedMsg, end,&pack_lte_broadcast_detect_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_UTRAN: + if(pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, ppWritePackedMsg, end, &pack_utran_broadcast_detect_request_value) == 0) + return 0; + + break; - return (push8(value->sib_type, ppWritePackedMsg, end) && - push16(value->sib_length, ppWritePackedMsg, end) && - pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); + case NFAPI_RAT_TYPE_NB_IOT: + if(pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_request_value) == 0) + return 0; + + break; + } + + return (pack_tlv(NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t pack_nb_iot_system_information_indication_value(void* msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_indication_t* value = (nfapi_nb_iot_system_information_indication_t*)msg; - - return (push8(value->sib_type, ppWritePackedMsg, end) && - push16(value->sib_length, ppWritePackedMsg, end) && - pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); -} - -static uint8_t pack_system_information_schedule_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) && - pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_lte_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_request_t* value = (nfapi_lte_system_information_request_t*)msg; - uint16_t idx = 0; - - if(!(push16(value->earfcn, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) && - push8(value->phich_configuration, ppWritePackedMsg, end) && - push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && - push8(value->number_of_si_periodicity, ppWritePackedMsg, end))) - return 0; - - for(idx = 0; idx < value->number_of_si_periodicity; ++idx) - { - if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) && - push8(value->si_periodicity[idx].si_index, ppWritePackedMsg, end))) - return 0; - } - - return (push8(value->si_window_length, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} -static uint8_t pack_utran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_system_information_request_t* value = (nfapi_utran_system_information_request_t*)msg; - - return (push16(value->uarfcn, ppWritePackedMsg, end) && - push16(value->psc, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} -static uint8_t pack_geran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_system_information_request_t* value = (nfapi_geran_system_information_request_t*)msg; - - return (push16(value->arfcn, ppWritePackedMsg, end) && - push8(value->bsic, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} -static uint8_t pack_nb_iot_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_request_t* value = (nfapi_nb_iot_system_information_request_t*)msg; - uint16_t idx = 0; - - if(!(push16(value->earfcn, ppWritePackedMsg, end) && - push8(value->ro_dl, ppWritePackedMsg, end) && - push16(value->pci, ppWritePackedMsg, end) && - push8(value->number_of_si_periodicity, ppWritePackedMsg, end))) - return 0; - - for(idx = 0; idx < value->number_of_si_periodicity; ++idx) - { - if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) && - push8(value->si_periodicity[idx].si_repetition_pattern, ppWritePackedMsg, end) && - push8(value->si_periodicity[idx].si_tb_size, ppWritePackedMsg, end) && - push8(value->si_periodicity[idx].number_of_si_index, ppWritePackedMsg, end))) - return 0; - - uint8_t si_idx; - for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx) - { - if(!(push8(value->si_periodicity[idx].si_index[si_idx], ppWritePackedMsg, end))) - return 0; - } - } - - return (push8(value->si_window_length, ppWritePackedMsg, end) && - push32(value->timeout, ppWritePackedMsg, end)); -} - - -static uint8_t pack_system_information_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t*)msg; - - if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) - return 0; - - switch(pNfapiMsg->rat_type) - { - case NFAPI_RAT_TYPE_LTE: - if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, ppWritePackedMsg, end, &pack_lte_system_information_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_UTRAN: - if(pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, ppWritePackedMsg, end, &pack_utran_system_information_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_GERAN: - if(pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, ppWritePackedMsg, end, &pack_geran_system_information_request_value) == 0) - return 0; - break; - case NFAPI_RAT_TYPE_NB_IOT: - if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, ppWritePackedMsg, end, &pack_nb_iot_system_information_request_value) == 0) - return 0; - break; - } - - return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_system_information_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_utran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_utran_system_information_indication_t* value = (nfapi_utran_system_information_indication_t*)msg; - - return (push16(value->sib_length, ppWritePackedMsg, end) && - pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); -} - -static uint8_t pack_geran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_geran_system_information_indication_t* value = (nfapi_geran_system_information_indication_t*)msg; - - return (push16(value->si_length, ppWritePackedMsg, end) && - pusharray8(value->si, NFAPI_MAX_SIB_LENGTH, value->si_length, ppWritePackedMsg, end)); -} - -static uint8_t pack_system_information_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) && - pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, ppWritePackedMsg, end, &pack_utran_system_information_indication_value) && - pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, ppWritePackedMsg, end, &pack_geran_system_information_indication_value) && - pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nmm_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t*)msg; - - return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nmm_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t unpack_lte_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - //int result = 0; - nfapi_lte_rssi_request_t* value = (nfapi_lte_rssi_request_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && - pull16(ppReadPackedMsg, &value->measurement_period, end) && - pull8(ppReadPackedMsg, &value->bandwidth, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_earfcns, end))) - return 0; - - if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST) - { - if(pullarray16(ppReadPackedMsg, value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns); - return 0; - } - - return 1; - -} - -static uint8_t unpack_utran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_rssi_request_t* value = (nfapi_utran_rssi_request_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && - pull16(ppReadPackedMsg, &value->measurement_period, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_uarfcns, end))) - return 0; - - if(value->number_of_uarfcns <= NFAPI_MAX_CARRIER_LIST) - { - if(pullarray16(ppReadPackedMsg, value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More UARFCN's than we can decode %d \n", value->number_of_uarfcns); - return 0; - } - - return 1; -} - -static uint8_t unpack_geran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_rssi_request_t* value = (nfapi_geran_rssi_request_t*)tlv; - uint16_t idx = 0; - - if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && - pull16(ppReadPackedMsg, &value->measurement_period, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_arfcns, end))) - return 0; - - if(value->number_of_arfcns <= NFAPI_MAX_CARRIER_LIST) - { - for(idx = 0; idx < value->number_of_arfcns; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->arfcn[idx].arfcn, end) && - pull8(ppReadPackedMsg, &value->arfcn[idx].direction, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcns); - return 0; - } - - return 1; -} - -static uint8_t unpack_nb_iot_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_rssi_request_t* value = (nfapi_nb_iot_rssi_request_t*)tlv; - uint16_t idx = 0; - - if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && - pull16(ppReadPackedMsg, &value->measurement_period, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_earfcns, end))) - return 0; - - if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST) - { - for(idx = 0; idx < value->number_of_earfcns; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->earfcn[idx].earfcn, end) && - pull8(ppReadPackedMsg, &value->earfcn[idx].number_of_ro_dl, end))) - return 0; - - if(value->earfcn[idx].number_of_ro_dl <= NFAPI_MAX_RO_DL) - { - uint8_t ro_dl_idx = 0; - for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx) - { - if(!pull8(ppReadPackedMsg, &value->earfcn[idx].ro_dl[ro_dl_idx], end)) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ROdl's than we can decode %d \n", value->earfcn[idx].number_of_ro_dl); - return 0; - } - - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns); - return 0; - } - - return 1; -} - -static uint8_t unpack_rssi_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, &unpack_lte_rssi_request_value}, - { NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, &unpack_utran_rssi_request_value}, - { NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, &unpack_geran_rssi_request_value}, - { NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, &unpack_nb_iot_rssi_request_value}, - }; - - int result = 0; - - result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - - - // Verify that the rat type and the tlv match - if(result == 1 && - !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_rssi_request.tl.tag == NFAPI_LTE_RSSI_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_rssi_request.tl.tag == NFAPI_UTRAN_RSSI_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_rssi_request.tl.tag == NFAPI_GERAN_RSSI_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_rssi_request.tl.tag == NFAPI_NB_IOT_RSSI_REQUEST_TAG))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_rssi_request.tl.tag); - result = 0; - } - - return result; -} - -static uint8_t unpack_rssi_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); -} - -static uint8_t unpack_rssi_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rssi_indication_body_t* value = (nfapi_rssi_indication_body_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->number_of_rssi, end) == 0) - return 0; - - if(value->number_of_rssi <= NFAPI_MAX_RSSI) - { - if(pullarrays16(ppReadPackedMsg, value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More RSSI's than we can decode %d \n", value->number_of_rssi); - return 0; - } - - return 1; -} - -static uint8_t unpack_rssi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, &unpack_rssi_indication_value}, - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lte_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_cell_search_request_t* value = (nfapi_lte_cell_search_request_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->measurement_bandwidth, end) && - pull8(ppReadPackedMsg, &value->exhaustive_search, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_pci, end))) - return 0; - - if(value->number_of_pci <= NFAPI_MAX_PCI_LIST) - { - if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci); - return 0; - } - return 1; -} - -static uint8_t unpack_utran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_cell_search_request_t* value = (nfapi_utran_cell_search_request_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->uarfcn, end) && - pull8(ppReadPackedMsg, &value->exhaustive_search, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_psc, end))) - return 0; - - if(value->number_of_psc <= NFAPI_MAX_PSC_LIST) - { - if(pullarray16(ppReadPackedMsg, value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PSC's than we can decode %d \n", value->number_of_psc); - return 0; - } - return 1; -} - -static uint8_t unpack_geran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_cell_search_request_t* value = (nfapi_geran_cell_search_request_t*)tlv; - - if(!(pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_arfcn, end))) - return 0; - - if(value->number_of_arfcn <= NFAPI_MAX_ARFCN_LIST) - { - if(pullarray16(ppReadPackedMsg, value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcn); - return 0; - } - return 1; -} - -static uint8_t unpack_nb_iot_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_cell_search_request_t* value = (nfapi_nb_iot_cell_search_request_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->ro_dl, end) && - pull8(ppReadPackedMsg, &value->exhaustive_search, end) && - pull32(ppReadPackedMsg, &value->timeout, end) && - pull8(ppReadPackedMsg, &value->number_of_pci, end))) - return 0; - - if(value->number_of_pci <= NFAPI_MAX_PCI_LIST) - { - if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0) - return 0; - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci); - return 0; - } - return 1; -} - -static uint8_t unpack_cell_search_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, &unpack_lte_cell_search_request_value}, - { NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, &unpack_utran_cell_search_request_value}, - { NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, &unpack_geran_cell_search_request_value}, - { NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, &unpack_nb_iot_cell_search_request_value}, - }; - - int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - - // Verify that the rat type and the tlv match - if(result == 1 && - !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_cell_search_request.tl.tag == NFAPI_LTE_CELL_SEARCH_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_cell_search_request.tl.tag == NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_cell_search_request.tl.tag == NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_cell_search_request.tl.tag == NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_cell_search_request.tl.tag); - result = 0; - } - - return result; -} - -static uint8_t unpack_cell_search_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lte_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_cell_search_indication_t* value = (nfapi_lte_cell_search_indication_t*)tlv; - - uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->number_of_lte_cells_found, end) == 0) - return 0; - - if(value->number_of_lte_cells_found <= NFAPI_MAX_LTE_CELLS_FOUND) - { - for(idx = 0; idx < value->number_of_lte_cells_found; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->lte_found_cells[idx].pci, end) && - pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrp, end) && - pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrq, end) && - pulls16(ppReadPackedMsg, &value->lte_found_cells[idx].frequency_offset, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found LTE cells than we can decode %d \n", value->number_of_lte_cells_found); - return 0; - } - return 1; -} - -static uint8_t unpack_utran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_cell_search_indication_t* value = (nfapi_utran_cell_search_indication_t*)tlv; - - uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->number_of_utran_cells_found, end) == 0) - return 0; - - if(value->number_of_utran_cells_found <= NFAPI_MAX_UTRAN_CELLS_FOUND) - { - for(idx = 0; idx < value->number_of_utran_cells_found; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->utran_found_cells[idx].psc, end) && - pull8(ppReadPackedMsg, &value->utran_found_cells[idx].rscp, end) && - pull8(ppReadPackedMsg, &value->utran_found_cells[idx].ecno, end) && - pulls16(ppReadPackedMsg, &value->utran_found_cells[idx].frequency_offset, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found UTRAN cells than we can decode %d \n", value->number_of_utran_cells_found); - return 0; - } - return 1; -} - -static uint8_t unpack_geran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_cell_search_indication_t* value = (nfapi_geran_cell_search_indication_t*)tlv; - - uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->number_of_gsm_cells_found, end) == 0) - return 0; - - if(value->number_of_gsm_cells_found <= NFAPI_MAX_GSM_CELLS_FOUND) - { - for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->gsm_found_cells[idx].arfcn, end) && - pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].bsic, end) && - pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxlev, end) && - pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxqual, end) && - pulls16(ppReadPackedMsg, &value->gsm_found_cells[idx].frequency_offset, end) && - pull32(ppReadPackedMsg, &value->gsm_found_cells[idx].sfn_offset, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found GSM cells than we can decode %d \n", value->number_of_gsm_cells_found); - return 0; - } - return 1; -} - -static uint8_t unpack_nb_iot_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_cell_search_indication_t* value = (nfapi_nb_iot_cell_search_indication_t*)tlv; - - uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->number_of_nb_iot_cells_found, end) == 0) - return 0; - - if(value->number_of_nb_iot_cells_found <= NFAPI_MAX_NB_IOT_CELLS_FOUND) - { - for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx) - { - if(!(pull16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].pci, end) && - pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrp, end) && - pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrq, end) && - pulls16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].frequency_offset, end))) - return 0; - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found NB_IOT cells than we can decode %d \n", value->number_of_nb_iot_cells_found); - return 0; - } - return 1; -} - -static uint8_t unpack_cell_search_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, &unpack_lte_cell_search_indication_value}, - { NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, &unpack_utran_cell_search_indication_value}, - { NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, &unpack_geran_cell_search_indication_value}, - { NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value}, - { NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, &unpack_nb_iot_cell_search_indication_value}, - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_lte_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_broadcast_detect_request_t* value = (nfapi_lte_broadcast_detect_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->earfcn, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_utran_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_broadcast_detect_request_t* value = (nfapi_utran_broadcast_detect_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->uarfcn, end) && - pull16(ppReadPackedMsg, &value->psc, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_nb_iot_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_broadcast_detect_request_t* value = (nfapi_nb_iot_broadcast_detect_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->ro_dl, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_broadcast_detect_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, &unpack_lte_broadcast_detect_request_value}, - { NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, &unpack_utran_broadcast_detect_request_value}, - { NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value}, - { NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, &unpack_nb_iot_broadcast_detect_request_value} - }; - - return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_broadcast_detect_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t*)msg; +static uint8_t pack_broadcast_detect_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_lte_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_broadcast_detect_indication_t *value = (nfapi_lte_broadcast_detect_indication_t *)msg; + return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && + push16(value->mib_length, ppWritePackedMsg, end) && + pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && + push32(value->sfn_offset, ppWritePackedMsg, end)); +} - unpack_tlv_t unpack_fns[] = - { - }; +static uint8_t pack_utran_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_broadcast_detect_indication_t *value = (nfapi_utran_broadcast_detect_indication_t *)msg; + return (push16(value->mib_length, ppWritePackedMsg, end) && + pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && + push32(value->sfn_offset, ppWritePackedMsg, end)); +} - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t pack_nb_iot_broadcast_detect_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_broadcast_detect_indication_t *value = (nfapi_nb_iot_broadcast_detect_indication_t *)msg; + return (push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && + push16(value->mib_length, ppWritePackedMsg, end) && + pusharray8(value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, ppWritePackedMsg, end) && + push32(value->sfn_offset, ppWritePackedMsg, end)); } -static uint8_t unpack_lte_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_broadcast_detect_indication_t* value = (nfapi_lte_broadcast_detect_indication_t*)tlv; +static uint8_t pack_broadcast_detect_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, ppWritePackedMsg, end, &pack_lte_broadcast_detect_indication_value) && + pack_tlv(NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, ppWritePackedMsg, end, &pack_utran_broadcast_detect_indication_value) && + pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_tlv(NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, ppWritePackedMsg, end, &pack_nb_iot_broadcast_detect_indication_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && - pull16(ppReadPackedMsg, &value->mib_length, end))) - return 0; +static uint8_t pack_lte_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_system_information_schedule_request_t *value = (nfapi_lte_system_information_schedule_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) && + push8(value->phich_configuration, ppWritePackedMsg, end) && + push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && + push8(value->retry_count, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); +} - if(value->mib_length > NFAPI_MAX_MIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); - return 0; - } - - return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && - pull32(ppReadPackedMsg, &value->sfn_offset, end)); +static uint8_t pack_nb_iot_system_information_schedule_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_schedule_request_t *value = (nfapi_nb_iot_system_information_schedule_request_t *)msg; + return (push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->ro_dl, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push8(value->scheduling_info_sib1_nb, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } -static uint8_t unpack_utran_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_broadcast_detect_indication_t* value = (nfapi_utran_broadcast_detect_indication_t*)tlv; - if(pull16(ppReadPackedMsg, &value->mib_length, end) == 0) - return 0; +static uint8_t pack_system_information_schedule_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: + if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, ppWritePackedMsg, end, &pack_lte_system_information_schedule_request_value) == 0) + return 0; + + break; - if(value->mib_length > NFAPI_MAX_MIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); - return 0; - } + case NFAPI_RAT_TYPE_NB_IOT: + if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, ppWritePackedMsg, end, + &pack_nb_iot_system_information_schedule_request_value) == 0) + return 0; - return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && - pull32(ppReadPackedMsg, &value->sfn_offset, end)); + break; + } + + return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t unpack_nb_iot_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_broadcast_detect_indication_t* value = (nfapi_nb_iot_broadcast_detect_indication_t*)tlv; +static uint8_t pack_system_information_schedule_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && - pull16(ppReadPackedMsg, &value->mib_length, end))) - return 0; +static uint8_t pack_lte_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_system_information_indication_t *value = (nfapi_lte_system_information_indication_t *)msg; + return (push8(value->sib_type, ppWritePackedMsg, end) && + push16(value->sib_length, ppWritePackedMsg, end) && + pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); +} - if(value->mib_length > NFAPI_MAX_MIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); - return 0; - } +static uint8_t pack_nb_iot_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_indication_t *value = (nfapi_nb_iot_system_information_indication_t *)msg; + return (push8(value->sib_type, ppWritePackedMsg, end) && + push16(value->sib_length, ppWritePackedMsg, end) && + pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); +} - return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && - pull32(ppReadPackedMsg, &value->sfn_offset, end)); +static uint8_t pack_system_information_schedule_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) && + pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t unpack_broadcast_detect_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t*)msg; +static uint8_t pack_lte_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lte_system_information_request_t *value = (nfapi_lte_system_information_request_t *)msg; + uint16_t idx = 0; + + if(!(push16(value->earfcn, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push16(value->downlink_channel_bandwidth, ppWritePackedMsg, end) && + push8(value->phich_configuration, ppWritePackedMsg, end) && + push8(value->number_of_tx_antenna, ppWritePackedMsg, end) && + push8(value->number_of_si_periodicity, ppWritePackedMsg, end))) + return 0; - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, &unpack_lte_broadcast_detect_indication_value}, - { NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, &unpack_utran_broadcast_detect_indication_value}, - { NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, &unpack_nb_iot_broadcast_detect_indication_value}, - { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} - }; + for(idx = 0; idx < value->number_of_si_periodicity; ++idx) { + if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) && + push8(value->si_periodicity[idx].si_index, ppWritePackedMsg, end))) + return 0; + } - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + return (push8(value->si_window_length, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } +static uint8_t pack_utran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_system_information_request_t *value = (nfapi_utran_system_information_request_t *)msg; + return (push16(value->uarfcn, ppWritePackedMsg, end) && + push16(value->psc, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); +} +static uint8_t pack_geran_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_system_information_request_t *value = (nfapi_geran_system_information_request_t *)msg; + return (push16(value->arfcn, ppWritePackedMsg, end) && + push8(value->bsic, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); +} +static uint8_t pack_nb_iot_system_information_request_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_request_t *value = (nfapi_nb_iot_system_information_request_t *)msg; + uint16_t idx = 0; + + if(!(push16(value->earfcn, ppWritePackedMsg, end) && + push8(value->ro_dl, ppWritePackedMsg, end) && + push16(value->pci, ppWritePackedMsg, end) && + push8(value->number_of_si_periodicity, ppWritePackedMsg, end))) + return 0; -static uint8_t unpack_lte_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_schedule_request_t* value = (nfapi_lte_system_information_schedule_request_t*)tlv; + for(idx = 0; idx < value->number_of_si_periodicity; ++idx) { + if(!(push8(value->si_periodicity[idx].si_periodicity, ppWritePackedMsg, end) && + push8(value->si_periodicity[idx].si_repetition_pattern, ppWritePackedMsg, end) && + push8(value->si_periodicity[idx].si_tb_size, ppWritePackedMsg, end) && + push8(value->si_periodicity[idx].number_of_si_index, ppWritePackedMsg, end))) + return 0; - return (pull16(ppReadPackedMsg, &value->earfcn, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) && - pull8(ppReadPackedMsg, &value->phich_configuration, end) && - pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && - pull8(ppReadPackedMsg, &value->retry_count, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); + uint8_t si_idx; + + for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx) { + if(!(push8(value->si_periodicity[idx].si_index[si_idx], ppWritePackedMsg, end))) + return 0; + } + } + + return (push8(value->si_window_length, ppWritePackedMsg, end) && + push32(value->timeout, ppWritePackedMsg, end)); } -static uint8_t unpack_nb_iot_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_schedule_request_t* value = (nfapi_nb_iot_system_information_schedule_request_t*)tlv; - return (pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->ro_dl, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull8(ppReadPackedMsg, &value->scheduling_info_sib1_nb, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); +static uint8_t pack_system_information_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t *)msg; + + if(push8(pNfapiMsg->rat_type, ppWritePackedMsg, end) == 0) + return 0; + + switch(pNfapiMsg->rat_type) { + case NFAPI_RAT_TYPE_LTE: + if(pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, ppWritePackedMsg, end, &pack_lte_system_information_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_UTRAN: + if(pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, ppWritePackedMsg, end, &pack_utran_system_information_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_GERAN: + if(pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, ppWritePackedMsg, end, &pack_geran_system_information_request_value) == 0) + return 0; + + break; + + case NFAPI_RAT_TYPE_NB_IOT: + if(pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, ppWritePackedMsg, end, &pack_nb_iot_system_information_request_value) == 0) + return 0; + + break; + } + + return (pack_tlv(NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, ppWritePackedMsg, end, &pack_opaque_data_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t unpack_system_information_schedule_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t*)msg; +static uint8_t pack_system_information_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, &unpack_lte_system_information_schedule_request_value}, - { NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, &unpack_nb_iot_system_information_schedule_request_value}, - { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} - }; +static uint8_t pack_utran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_utran_system_information_indication_t *value = (nfapi_utran_system_information_indication_t *)msg; + return (push16(value->sib_length, ppWritePackedMsg, end) && + pusharray8(value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, ppWritePackedMsg, end)); +} - return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t pack_geran_system_information_indication_value(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_geran_system_information_indication_t *value = (nfapi_geran_system_information_indication_t *)msg; + return (push16(value->si_length, ppWritePackedMsg, end) && + pusharray8(value->si, NFAPI_MAX_SIB_LENGTH, value->si_length, ppWritePackedMsg, end)); } -static uint8_t unpack_system_information_schedule_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t*)msg; +static uint8_t pack_system_information_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, ppWritePackedMsg, end, &pack_lte_system_information_indication_value) && + pack_tlv(NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, ppWritePackedMsg, end, &pack_utran_system_information_indication_value) && + pack_tlv(NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, ppWritePackedMsg, end, &pack_geran_system_information_indication_value) && + pack_tlv(NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, ppWritePackedMsg, end, &pack_nb_iot_system_information_indication_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - unpack_tlv_t unpack_fns[] = - { - }; +static uint8_t pack_nmm_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t *)msg; + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +static uint8_t pack_nmm_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } -static uint8_t unpack_lte_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_indication_t* value = (nfapi_lte_system_information_indication_t*)tlv; +static uint8_t unpack_lte_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + //int result = 0; + nfapi_lte_rssi_request_t *value = (nfapi_lte_rssi_request_t *)tlv; - if(!(pull8(ppReadPackedMsg, &value->sib_type, end) && - pull16(ppReadPackedMsg, &value->sib_length, end))) - return 0; + if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && + pull16(ppReadPackedMsg, &value->measurement_period, end) && + pull8(ppReadPackedMsg, &value->bandwidth, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_earfcns, end))) + return 0; - if(value->sib_length > NFAPI_MAX_SIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); - return 0; - } - - if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) - return 0; + if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST) { + if(pullarray16(ppReadPackedMsg, value->earfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_earfcns, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns); + return 0; + } - return 1; + return 1; } -static uint8_t unpack_nb_iot_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_indication_t* value = (nfapi_nb_iot_system_information_indication_t*)tlv; +static uint8_t unpack_utran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_rssi_request_t *value = (nfapi_utran_rssi_request_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && + pull16(ppReadPackedMsg, &value->measurement_period, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_uarfcns, end))) + return 0; + + if(value->number_of_uarfcns <= NFAPI_MAX_CARRIER_LIST) { + if(pullarray16(ppReadPackedMsg, value->uarfcn, NFAPI_MAX_CARRIER_LIST, value->number_of_uarfcns, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More UARFCN's than we can decode %d \n", value->number_of_uarfcns); + return 0; + } - if(!(pull8(ppReadPackedMsg, &value->sib_type, end) && - pull16(ppReadPackedMsg, &value->sib_length, end))) - return 0; + return 1; +} - if(value->sib_length > NFAPI_MAX_SIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); - return 0; - } - - if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) - return 0; - - return 1; -} - -static uint8_t unpack_system_information_schedule_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value}, - { NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value}, - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lte_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lte_system_information_request_t* value = (nfapi_lte_system_information_request_t*)tlv; - uint16_t idx = 0; - - if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) && - pull8(ppReadPackedMsg, &value->phich_configuration, end) && - pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && - pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end))) - return 0; - - if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity); - return 0; - } - - for(idx = 0; idx < value->number_of_si_periodicity; ++idx) - { - if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) && - pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index, end))) - return 0; - } - - if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) && - pull32(ppReadPackedMsg, &value->timeout, end))) - return 0; - - return 1; -} - -static uint8_t unpack_utran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_system_information_request_t* value = (nfapi_utran_system_information_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->uarfcn, end) && - pull16(ppReadPackedMsg, &value->psc, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_geran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_system_information_request_t* value = (nfapi_geran_system_information_request_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->arfcn, end) && - pull8(ppReadPackedMsg, &value->bsic, end) && - pull32(ppReadPackedMsg, &value->timeout, end)); -} - -static uint8_t unpack_nb_iot_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_iot_system_information_request_t* value = (nfapi_nb_iot_system_information_request_t*)tlv; - uint16_t idx = 0; - - if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && - pull8(ppReadPackedMsg, &value->ro_dl, end) && - pull16(ppReadPackedMsg, &value->pci, end) && - pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end))) - return 0; - - if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity); - return 0; - } - - for(idx = 0; idx < value->number_of_si_periodicity; ++idx) - { - if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) && - pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_repetition_pattern, end) && - pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_tb_size, end) && - pull8(ppReadPackedMsg, &value->si_periodicity[idx].number_of_si_index, end))) - return 0; - - uint8_t si_idx; - for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx) - { - if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index[si_idx], end))) - return 0; - - } - } - - if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) && - pull32(ppReadPackedMsg, &value->timeout, end))) - return 0; +static uint8_t unpack_geran_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_rssi_request_t *value = (nfapi_geran_rssi_request_t *)tlv; + uint16_t idx = 0; + + if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && + pull16(ppReadPackedMsg, &value->measurement_period, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_arfcns, end))) + return 0; + + if(value->number_of_arfcns <= NFAPI_MAX_CARRIER_LIST) { + for(idx = 0; idx < value->number_of_arfcns; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->arfcn[idx].arfcn, end) && + pull8(ppReadPackedMsg, &value->arfcn[idx].direction, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcns); + return 0; + } + + return 1; +} + +static uint8_t unpack_nb_iot_rssi_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_rssi_request_t *value = (nfapi_nb_iot_rssi_request_t *)tlv; + uint16_t idx = 0; + + if(!(pull8(ppReadPackedMsg, &value->frequency_band_indicator, end) && + pull16(ppReadPackedMsg, &value->measurement_period, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_earfcns, end))) + return 0; + + if(value->number_of_earfcns <= NFAPI_MAX_CARRIER_LIST) { + for(idx = 0; idx < value->number_of_earfcns; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->earfcn[idx].earfcn, end) && + pull8(ppReadPackedMsg, &value->earfcn[idx].number_of_ro_dl, end))) + return 0; + + if(value->earfcn[idx].number_of_ro_dl <= NFAPI_MAX_RO_DL) { + uint8_t ro_dl_idx = 0; + + for(ro_dl_idx = 0; ro_dl_idx < value->earfcn[idx].number_of_ro_dl; ++ro_dl_idx) { + if(!pull8(ppReadPackedMsg, &value->earfcn[idx].ro_dl[ro_dl_idx], end)) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ROdl's than we can decode %d \n", value->earfcn[idx].number_of_ro_dl); + return 0; + } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More EARFCN's than we can decode %d \n", value->number_of_earfcns); + return 0; + } + + return 1; +} + +static uint8_t unpack_rssi_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_request_t *pNfapiMsg = (nfapi_rssi_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_RSSI_REQUEST_TAG, &pNfapiMsg->lte_rssi_request, &unpack_lte_rssi_request_value}, + { NFAPI_UTRAN_RSSI_REQUEST_TAG, &pNfapiMsg->utran_rssi_request, &unpack_utran_rssi_request_value}, + { NFAPI_GERAN_RSSI_REQUEST_TAG, &pNfapiMsg->geran_rssi_request, &unpack_geran_rssi_request_value}, + { NFAPI_NB_IOT_RSSI_REQUEST_TAG, &pNfapiMsg->nb_iot_rssi_request, &unpack_nb_iot_rssi_request_value}, + }; + int result = 0; + result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); + + // Verify that the rat type and the tlv match + if(result == 1 && + !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_rssi_request.tl.tag == NFAPI_LTE_RSSI_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_rssi_request.tl.tag == NFAPI_UTRAN_RSSI_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_rssi_request.tl.tag == NFAPI_GERAN_RSSI_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_rssi_request.tl.tag == NFAPI_NB_IOT_RSSI_REQUEST_TAG))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_rssi_request.tl.tag); + result = 0; + } + + return result; +} + +static uint8_t unpack_rssi_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_response_t *pNfapiMsg = (nfapi_rssi_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_rssi_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rssi_indication_body_t *value = (nfapi_rssi_indication_body_t *)tlv; + + if(pull16(ppReadPackedMsg, &value->number_of_rssi, end) == 0) + return 0; + + if(value->number_of_rssi <= NFAPI_MAX_RSSI) { + if(pullarrays16(ppReadPackedMsg, value->rssi, NFAPI_MAX_RSSI, value->number_of_rssi, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More RSSI's than we can decode %d \n", value->number_of_rssi); + return 0; + } + + return 1; +} + +static uint8_t unpack_rssi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_rssi_indication_t *pNfapiMsg = (nfapi_rssi_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RSSI_INDICATION_TAG, &pNfapiMsg->rssi_indication_body, &unpack_rssi_indication_value}, + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_cell_search_request_t *value = (nfapi_lte_cell_search_request_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->measurement_bandwidth, end) && + pull8(ppReadPackedMsg, &value->exhaustive_search, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_pci, end))) + return 0; + + if(value->number_of_pci <= NFAPI_MAX_PCI_LIST) { + if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci); + return 0; + } + + return 1; +} + +static uint8_t unpack_utran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_cell_search_request_t *value = (nfapi_utran_cell_search_request_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &value->uarfcn, end) && + pull8(ppReadPackedMsg, &value->exhaustive_search, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_psc, end))) + return 0; + + if(value->number_of_psc <= NFAPI_MAX_PSC_LIST) { + if(pullarray16(ppReadPackedMsg, value->psc, NFAPI_MAX_PSC_LIST, value->number_of_psc, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PSC's than we can decode %d \n", value->number_of_psc); + return 0; + } + + return 1; +} + +static uint8_t unpack_geran_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_cell_search_request_t *value = (nfapi_geran_cell_search_request_t *)tlv; + + if(!(pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_arfcn, end))) + return 0; + + if(value->number_of_arfcn <= NFAPI_MAX_ARFCN_LIST) { + if(pullarray16(ppReadPackedMsg, value->arfcn, NFAPI_MAX_ARFCN_LIST, value->number_of_arfcn, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More ARFCN's than we can decode %d \n", value->number_of_arfcn); + return 0; + } + + return 1; +} + +static uint8_t unpack_nb_iot_cell_search_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_cell_search_request_t *value = (nfapi_nb_iot_cell_search_request_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->ro_dl, end) && + pull8(ppReadPackedMsg, &value->exhaustive_search, end) && + pull32(ppReadPackedMsg, &value->timeout, end) && + pull8(ppReadPackedMsg, &value->number_of_pci, end))) + return 0; + + if(value->number_of_pci <= NFAPI_MAX_PCI_LIST) { + if(pullarray16(ppReadPackedMsg, value->pci, NFAPI_MAX_PCI_LIST, value->number_of_pci, end) == 0) + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More PCI's than we can decode %d \n", value->number_of_pci); + return 0; + } + + return 1; +} + +static uint8_t unpack_cell_search_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_request_t *pNfapiMsg = (nfapi_cell_search_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->lte_cell_search_request, &unpack_lte_cell_search_request_value}, + { NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->utran_cell_search_request, &unpack_utran_cell_search_request_value}, + { NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->geran_cell_search_request, &unpack_geran_cell_search_request_value}, + { NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG, &pNfapiMsg->nb_iot_cell_search_request, &unpack_nb_iot_cell_search_request_value}, + }; + int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + + // Verify that the rat type and the tlv match + if(result == 1 && + !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_cell_search_request.tl.tag == NFAPI_LTE_CELL_SEARCH_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_cell_search_request.tl.tag == NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_cell_search_request.tl.tag == NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_NB_IOT && pNfapiMsg->nb_iot_cell_search_request.tl.tag == NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_cell_search_request.tl.tag); + result = 0; + } + + return result; +} + +static uint8_t unpack_cell_search_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_response_t *pNfapiMsg = (nfapi_cell_search_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_cell_search_indication_t *value = (nfapi_lte_cell_search_indication_t *)tlv; + uint16_t idx = 0; + + if(pull16(ppReadPackedMsg, &value->number_of_lte_cells_found, end) == 0) + return 0; + + if(value->number_of_lte_cells_found <= NFAPI_MAX_LTE_CELLS_FOUND) { + for(idx = 0; idx < value->number_of_lte_cells_found; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->lte_found_cells[idx].pci, end) && + pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrp, end) && + pull8(ppReadPackedMsg, &value->lte_found_cells[idx].rsrq, end) && + pulls16(ppReadPackedMsg, &value->lte_found_cells[idx].frequency_offset, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found LTE cells than we can decode %d \n", value->number_of_lte_cells_found); + return 0; + } + + return 1; +} + +static uint8_t unpack_utran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_cell_search_indication_t *value = (nfapi_utran_cell_search_indication_t *)tlv; + uint16_t idx = 0; + + if(pull16(ppReadPackedMsg, &value->number_of_utran_cells_found, end) == 0) + return 0; + + if(value->number_of_utran_cells_found <= NFAPI_MAX_UTRAN_CELLS_FOUND) { + for(idx = 0; idx < value->number_of_utran_cells_found; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->utran_found_cells[idx].psc, end) && + pull8(ppReadPackedMsg, &value->utran_found_cells[idx].rscp, end) && + pull8(ppReadPackedMsg, &value->utran_found_cells[idx].ecno, end) && + pulls16(ppReadPackedMsg, &value->utran_found_cells[idx].frequency_offset, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found UTRAN cells than we can decode %d \n", value->number_of_utran_cells_found); + return 0; + } + + return 1; +} + +static uint8_t unpack_geran_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_cell_search_indication_t *value = (nfapi_geran_cell_search_indication_t *)tlv; + uint16_t idx = 0; + + if(pull16(ppReadPackedMsg, &value->number_of_gsm_cells_found, end) == 0) + return 0; + + if(value->number_of_gsm_cells_found <= NFAPI_MAX_GSM_CELLS_FOUND) { + for(idx = 0; idx < value->number_of_gsm_cells_found; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->gsm_found_cells[idx].arfcn, end) && + pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].bsic, end) && + pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxlev, end) && + pull8(ppReadPackedMsg, &value->gsm_found_cells[idx].rxqual, end) && + pulls16(ppReadPackedMsg, &value->gsm_found_cells[idx].frequency_offset, end) && + pull32(ppReadPackedMsg, &value->gsm_found_cells[idx].sfn_offset, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found GSM cells than we can decode %d \n", value->number_of_gsm_cells_found); + return 0; + } + + return 1; +} + +static uint8_t unpack_nb_iot_cell_search_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_cell_search_indication_t *value = (nfapi_nb_iot_cell_search_indication_t *)tlv; + uint16_t idx = 0; + + if(pull16(ppReadPackedMsg, &value->number_of_nb_iot_cells_found, end) == 0) + return 0; + + if(value->number_of_nb_iot_cells_found <= NFAPI_MAX_NB_IOT_CELLS_FOUND) { + for(idx = 0; idx < value->number_of_nb_iot_cells_found; ++idx) { + if(!(pull16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].pci, end) && + pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrp, end) && + pull8(ppReadPackedMsg, &value->nb_iot_found_cells[idx].rsrq, end) && + pulls16(ppReadPackedMsg, &value->nb_iot_found_cells[idx].frequency_offset, end))) + return 0; + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found NB_IOT cells than we can decode %d \n", value->number_of_nb_iot_cells_found); + return 0; + } - return 1; -} - -static uint8_t unpack_system_information_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t*)msg; + return 1; +} - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, &unpack_lte_system_information_request_value}, - { NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, &unpack_utran_system_information_request_value}, - { NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, &unpack_geran_system_information_request_value}, - { NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, &unpack_nb_iot_system_information_request_value}, - { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} - }; +static uint8_t unpack_cell_search_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_cell_search_indication_t *pNfapiMsg = (nfapi_cell_search_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->lte_cell_search_indication, &unpack_lte_cell_search_indication_value}, + { NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->utran_cell_search_indication, &unpack_utran_cell_search_indication_value}, + { NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->geran_cell_search_indication, &unpack_geran_cell_search_indication_value}, + { NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value}, + { NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG, &pNfapiMsg->nb_iot_cell_search_indication, &unpack_nb_iot_cell_search_indication_value}, + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_broadcast_detect_request_t *value = (nfapi_lte_broadcast_detect_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->earfcn, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_utran_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_broadcast_detect_request_t *value = (nfapi_utran_broadcast_detect_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->uarfcn, end) && + pull16(ppReadPackedMsg, &value->psc, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_nb_iot_broadcast_detect_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_broadcast_detect_request_t *value = (nfapi_nb_iot_broadcast_detect_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->ro_dl, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_broadcast_detect_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_request_t *pNfapiMsg = (nfapi_broadcast_detect_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->lte_broadcast_detect_request, &unpack_lte_broadcast_detect_request_value}, + { NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->utran_broadcast_detect_request, &unpack_utran_broadcast_detect_request_value}, + { NFAPI_PNF_CELL_SEARCH_STATE_TAG, &pNfapiMsg->pnf_cell_search_state, &unpack_opaque_data_value}, + { NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG, &pNfapiMsg->nb_iot_broadcast_detect_request, &unpack_nb_iot_broadcast_detect_request_value} + }; + return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_broadcast_detect_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_response_t *pNfapiMsg = (nfapi_broadcast_detect_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_broadcast_detect_indication_t *value = (nfapi_lte_broadcast_detect_indication_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && + pull16(ppReadPackedMsg, &value->mib_length, end))) + return 0; + + if(value->mib_length > NFAPI_MAX_MIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); + return 0; + } + + return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && + pull32(ppReadPackedMsg, &value->sfn_offset, end)); +} +static uint8_t unpack_utran_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_broadcast_detect_indication_t *value = (nfapi_utran_broadcast_detect_indication_t *)tlv; - int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + if(pull16(ppReadPackedMsg, &value->mib_length, end) == 0) + return 0; - // Verify that the rat type and the tlv match - if(result == 1 && - !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_system_information_request.tl.tag == NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_system_information_request.tl.tag == NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG) || - (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_system_information_request.tl.tag == NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_system_information_request.tl.tag); - result = 0; - } - - return result; + if(value->mib_length > NFAPI_MAX_MIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); + return 0; + } + + return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && + pull32(ppReadPackedMsg, &value->sfn_offset, end)); +} + +static uint8_t unpack_nb_iot_broadcast_detect_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_broadcast_detect_indication_t *value = (nfapi_nb_iot_broadcast_detect_indication_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && + pull16(ppReadPackedMsg, &value->mib_length, end))) + return 0; + + if(value->mib_length > NFAPI_MAX_MIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "MIB too long %d \n", value->mib_length); + return 0; + } + + return (pullarray8(ppReadPackedMsg, value->mib, NFAPI_MAX_MIB_LENGTH, value->mib_length, end) && + pull32(ppReadPackedMsg, &value->sfn_offset, end)); +} + +static uint8_t unpack_broadcast_detect_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_broadcast_detect_indication_t *pNfapiMsg = (nfapi_broadcast_detect_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->lte_broadcast_detect_indication, &unpack_lte_broadcast_detect_indication_value}, + { NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->utran_broadcast_detect_indication, &unpack_utran_broadcast_detect_indication_value}, + { NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG, &pNfapiMsg->nb_iot_broadcast_detect_indication, &unpack_nb_iot_broadcast_detect_indication_value}, + { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_system_information_schedule_request_t *value = (nfapi_lte_system_information_schedule_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->earfcn, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) && + pull8(ppReadPackedMsg, &value->phich_configuration, end) && + pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && + pull8(ppReadPackedMsg, &value->retry_count, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_nb_iot_system_information_schedule_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_schedule_request_t *value = (nfapi_nb_iot_system_information_schedule_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->ro_dl, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull8(ppReadPackedMsg, &value->scheduling_info_sib1_nb, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_system_information_schedule_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_request_t *pNfapiMsg = (nfapi_system_information_schedule_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->lte_system_information_schedule_request, &unpack_lte_system_information_schedule_request_value}, + { NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_schedule_request, &unpack_nb_iot_system_information_schedule_request_value}, + { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} + }; + return (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_system_information_schedule_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_response_t *pNfapiMsg = (nfapi_system_information_schedule_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_system_information_indication_t *value = (nfapi_lte_system_information_indication_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->sib_type, end) && + pull16(ppReadPackedMsg, &value->sib_length, end))) + return 0; + + if(value->sib_length > NFAPI_MAX_SIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); + return 0; + } + + if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) + return 0; + + return 1; } -static uint8_t unpack_system_information_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t*)msg; +static uint8_t unpack_nb_iot_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_indication_t *value = (nfapi_nb_iot_system_information_indication_t *)tlv; - unpack_tlv_t unpack_fns[] = - { - }; + if(!(pull8(ppReadPackedMsg, &value->sib_type, end) && + pull16(ppReadPackedMsg, &value->sib_length, end))) + return 0; - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + if(value->sib_length > NFAPI_MAX_SIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); + return 0; + } + + if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) + return 0; + + return 1; +} + +static uint8_t unpack_system_information_schedule_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_schedule_indication_t *pNfapiMsg = (nfapi_system_information_schedule_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value}, + { NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value}, + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lte_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lte_system_information_request_t *value = (nfapi_lte_system_information_request_t *)tlv; + uint16_t idx = 0; + + if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull16(ppReadPackedMsg, &value->downlink_channel_bandwidth, end) && + pull8(ppReadPackedMsg, &value->phich_configuration, end) && + pull8(ppReadPackedMsg, &value->number_of_tx_antenna, end) && + pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end))) + return 0; + + if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity); + return 0; + } + + for(idx = 0; idx < value->number_of_si_periodicity; ++idx) { + if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) && + pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index, end))) + return 0; + } + + if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) && + pull32(ppReadPackedMsg, &value->timeout, end))) + return 0; + + return 1; +} + +static uint8_t unpack_utran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_system_information_request_t *value = (nfapi_utran_system_information_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->uarfcn, end) && + pull16(ppReadPackedMsg, &value->psc, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); +} + +static uint8_t unpack_geran_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_system_information_request_t *value = (nfapi_geran_system_information_request_t *)tlv; + return (pull16(ppReadPackedMsg, &value->arfcn, end) && + pull8(ppReadPackedMsg, &value->bsic, end) && + pull32(ppReadPackedMsg, &value->timeout, end)); } -static uint8_t unpack_utran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_utran_system_information_indication_t* value = (nfapi_utran_system_information_indication_t*)tlv; +static uint8_t unpack_nb_iot_system_information_request_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_iot_system_information_request_t *value = (nfapi_nb_iot_system_information_request_t *)tlv; + uint16_t idx = 0; - if(pull16(ppReadPackedMsg, &value->sib_length, end) == 0) - return 0; + if(!(pull16(ppReadPackedMsg, &value->earfcn, end) && + pull8(ppReadPackedMsg, &value->ro_dl, end) && + pull16(ppReadPackedMsg, &value->pci, end) && + pull8(ppReadPackedMsg, &value->number_of_si_periodicity, end))) + return 0; - if(value->sib_length > NFAPI_MAX_SIB_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); - return 0; - } - - if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) - return 0; + if(value->number_of_si_periodicity > NFAPI_MAX_SI_PERIODICITY) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "More found SI periodicity than we can decode %d \n", value->number_of_si_periodicity); + return 0; + } - return 1; -} - -static uint8_t unpack_geran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_geran_system_information_indication_t* value = (nfapi_geran_system_information_indication_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->si_length, end) == 0) - return 0; + for(idx = 0; idx < value->number_of_si_periodicity; ++idx) { + if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_periodicity, end) && + pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_repetition_pattern, end) && + pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_tb_size, end) && + pull8(ppReadPackedMsg, &value->si_periodicity[idx].number_of_si_index, end))) + return 0; - if(value->si_length > NFAPI_MAX_SI_LENGTH) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->si_length); - return 0; - } + uint8_t si_idx; - if(pullarray8(ppReadPackedMsg, value->si, NFAPI_MAX_SI_LENGTH, value->si_length, end) == 0) - return 0; + for(si_idx = 0; si_idx < value->si_periodicity[idx].number_of_si_index; ++si_idx) { + if(!(pull8(ppReadPackedMsg, &value->si_periodicity[idx].si_index[si_idx], end))) + return 0; + } + } - return 1; + if(!(pull8(ppReadPackedMsg, &value->si_window_length, end) && + pull32(ppReadPackedMsg, &value->timeout, end))) + return 0; + + return 1; } -static uint8_t unpack_system_information_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t*)msg; +static uint8_t unpack_system_information_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_request_t *pNfapiMsg = (nfapi_system_information_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->lte_system_information_request, &unpack_lte_system_information_request_value}, + { NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->utran_system_information_request, &unpack_utran_system_information_request_value}, + { NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->geran_system_information_request, &unpack_geran_system_information_request_value}, + { NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG, &pNfapiMsg->nb_iot_system_information_request, &unpack_nb_iot_system_information_request_value}, + { NFAPI_PNF_CELL_BROADCAST_STATE_TAG, &pNfapiMsg->pnf_cell_broadcast_state, &unpack_opaque_data_value} + }; + int result = (pull8(ppReadPackedMsg, &pNfapiMsg->rat_type, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value}, - { NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, &unpack_utran_system_information_indication_value}, - { NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, &unpack_geran_system_information_indication_value}, - { NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value}, - }; + // Verify that the rat type and the tlv match + if(result == 1 && + !((pNfapiMsg->rat_type == NFAPI_RAT_TYPE_LTE && pNfapiMsg->lte_system_information_request.tl.tag == NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_UTRAN && pNfapiMsg->utran_system_information_request.tl.tag == NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG) || + (pNfapiMsg->rat_type == NFAPI_RAT_TYPE_GERAN && pNfapiMsg->geran_system_information_request.tl.tag == NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Mismatch RAT Type: %d and TAG value: 0x%04x \n", pNfapiMsg->rat_type, pNfapiMsg->lte_system_information_request.tl.tag); + result = 0; + } - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + return result; +} +static uint8_t unpack_system_information_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_response_t *pNfapiMsg = (nfapi_system_information_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } -static uint8_t unpack_nmm_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t*)msg; +static uint8_t unpack_utran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_utran_system_information_indication_t *value = (nfapi_utran_system_information_indication_t *)tlv; + + if(pull16(ppReadPackedMsg, &value->sib_length, end) == 0) + return 0; - unpack_tlv_t unpack_fns[] = - { - }; + if(value->sib_length > NFAPI_MAX_SIB_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->sib_length); + return 0; + } - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); + if(pullarray8(ppReadPackedMsg, value->sib, NFAPI_MAX_SIB_LENGTH, value->sib_length, end) == 0) + return 0; + + return 1; } -static uint8_t unpack_nmm_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t*)msg; +static uint8_t unpack_geran_system_information_indication_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_geran_system_information_indication_t *value = (nfapi_geran_system_information_indication_t *)tlv; + + if(pull16(ppReadPackedMsg, &value->si_length, end) == 0) + return 0; + + if(value->si_length > NFAPI_MAX_SI_LENGTH) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "SIB too long %d \n", value->si_length); + return 0; + } - unpack_tlv_t unpack_fns[] = - { - }; + if(pullarray8(ppReadPackedMsg, value->si, NFAPI_MAX_SI_LENGTH, value->si_length, end) == 0) + return 0; - return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + return 1; } +static uint8_t unpack_system_information_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_system_information_indication_t *pNfapiMsg = (nfapi_system_information_indication_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->lte_system_information_indication, &unpack_lte_system_information_indication_value}, + { NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->utran_system_information_indication, &unpack_utran_system_information_indication_value}, + { NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->geran_system_information_indication, &unpack_geran_system_information_indication_value}, + { NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG, &pNfapiMsg->nb_iot_system_information_indication, &unpack_nb_iot_system_information_indication_value}, + }; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nmm_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nmm_stop_request_t *pNfapiMsg = (nfapi_nmm_stop_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); +} + +static uint8_t unpack_nmm_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nmm_stop_response_t *pNfapiMsg = (nfapi_nmm_stop_response_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; + + switch (msgId) { + case NFAPI_RSSI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_rssi_request_t)) + retLen = sizeof(nfapi_rssi_request_t); + + break; + + case NFAPI_RSSI_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_rssi_response_t)) + retLen = sizeof(nfapi_rssi_response_t); + + break; + + case NFAPI_RSSI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rssi_indication_t)) + retLen = sizeof(nfapi_rssi_indication_t); + + break; + + case NFAPI_CELL_SEARCH_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_cell_search_request_t)) + retLen = sizeof(nfapi_cell_search_request_t); + + break; + + case NFAPI_CELL_SEARCH_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_cell_search_response_t)) + retLen = sizeof(nfapi_cell_search_response_t); + + break; + + case NFAPI_CELL_SEARCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cell_search_indication_t)) + retLen = sizeof(nfapi_cell_search_indication_t); + + break; + + case NFAPI_BROADCAST_DETECT_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_request_t)) + retLen = sizeof(nfapi_broadcast_detect_request_t); + + break; + + case NFAPI_BROADCAST_DETECT_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_response_t)) + retLen = sizeof(nfapi_broadcast_detect_response_t); + + break; + + case NFAPI_BROADCAST_DETECT_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_indication_t)) + retLen = sizeof(nfapi_broadcast_detect_indication_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_request_t)) + retLen = sizeof(nfapi_system_information_schedule_request_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_response_t)) + retLen = sizeof(nfapi_system_information_schedule_response_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_indication_t)) + retLen = sizeof(nfapi_system_information_schedule_indication_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_system_information_request_t)) + retLen = sizeof(nfapi_system_information_request_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_system_information_response_t)) + retLen = sizeof(nfapi_system_information_response_t); + + break; + + case NFAPI_SYSTEM_INFORMATION_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_system_information_indication_t)) + retLen = sizeof(nfapi_system_information_indication_t); + + break; + + case NFAPI_NMM_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nmm_stop_request_t)) + retLen = sizeof(nfapi_nmm_stop_request_t); + + break; + + case NFAPI_NMM_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nmm_stop_response_t)) + retLen = sizeof(nfapi_nmm_stop_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; +} + +int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *end = pPackedBuf + packedBufLen; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint32_t packedMsgLen; + uint16_t packedMsgLen16; + + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 Pack supplied pointers are null\n"); + return -1; + } + + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->spare, &pWritePackedMessage, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header\n"); + return -1; + } + + // look for the specific message + uint8_t result = 0; -static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; + switch (pMessageHeader->message_id) { + case NFAPI_RSSI_REQUEST: + result = pack_rssi_request(pMessageHeader, &pWritePackedMessage, end, config); + break; - switch (msgId) - { - case NFAPI_RSSI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_rssi_request_t)) - retLen = sizeof(nfapi_rssi_request_t); - break; + case NFAPI_RSSI_RESPONSE: + result = pack_rssi_response(pMessageHeader, &pWritePackedMessage, end,config); + break; - case NFAPI_RSSI_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_rssi_response_t)) - retLen = sizeof(nfapi_rssi_response_t); - break; + case NFAPI_RSSI_INDICATION: + result = pack_rssi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - case NFAPI_RSSI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rssi_indication_t)) - retLen = sizeof(nfapi_rssi_indication_t); - break; - - case NFAPI_CELL_SEARCH_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_cell_search_request_t)) - retLen = sizeof(nfapi_cell_search_request_t); - break; - - case NFAPI_CELL_SEARCH_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_cell_search_response_t)) - retLen = sizeof(nfapi_cell_search_response_t); - break; - - case NFAPI_CELL_SEARCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cell_search_indication_t)) - retLen = sizeof(nfapi_cell_search_indication_t); - break; - - case NFAPI_BROADCAST_DETECT_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_request_t)) - retLen = sizeof(nfapi_broadcast_detect_request_t); - break; - - case NFAPI_BROADCAST_DETECT_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_response_t)) - retLen = sizeof(nfapi_broadcast_detect_response_t); - break; - - case NFAPI_BROADCAST_DETECT_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_broadcast_detect_indication_t)) - retLen = sizeof(nfapi_broadcast_detect_indication_t); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_request_t)) - retLen = sizeof(nfapi_system_information_schedule_request_t); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_response_t)) - retLen = sizeof(nfapi_system_information_schedule_response_t); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_system_information_schedule_indication_t)) - retLen = sizeof(nfapi_system_information_schedule_indication_t); - break; - - case NFAPI_SYSTEM_INFORMATION_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_system_information_request_t)) - retLen = sizeof(nfapi_system_information_request_t); - break; - - case NFAPI_SYSTEM_INFORMATION_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_system_information_response_t)) - retLen = sizeof(nfapi_system_information_response_t); - break; - - case NFAPI_SYSTEM_INFORMATION_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_system_information_indication_t)) - retLen = sizeof(nfapi_system_information_indication_t); - break; - - case NFAPI_NMM_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nmm_stop_request_t)) - retLen = sizeof(nfapi_nmm_stop_request_t); - break; - - case NFAPI_NMM_STOP_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_nmm_stop_response_t)) - retLen = sizeof(nfapi_nmm_stop_response_t); - break; - - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } - - return retLen; -} - -int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *end = pPackedBuf + packedBufLen; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint32_t packedMsgLen; - uint16_t packedMsgLen16; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 Pack supplied pointers are null\n"); - return -1; - } - - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->spare, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header\n"); - return -1; - } - - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_RSSI_REQUEST: - result = pack_rssi_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RSSI_RESPONSE: - result = pack_rssi_response(pMessageHeader, &pWritePackedMessage, end,config); - break; - - case NFAPI_RSSI_INDICATION: - result = pack_rssi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CELL_SEARCH_REQUEST: - result = pack_cell_search_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CELL_SEARCH_RESPONSE: - result = pack_cell_search_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CELL_SEARCH_INDICATION: - result = pack_cell_search_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_BROADCAST_DETECT_REQUEST: - result = pack_broadcast_detect_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_BROADCAST_DETECT_RESPONSE: - result = pack_broadcast_detect_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_BROADCAST_DETECT_INDICATION: - result = pack_broadcast_detect_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: - result = pack_system_information_schedule_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: - result = pack_system_information_schedule_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: - result = pack_system_information_schedule_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_REQUEST: - result = pack_system_information_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_RESPONSE: - result = pack_system_information_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SYSTEM_INFORMATION_INDICATION: - result = pack_system_information_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NMM_STOP_REQUEST: - result = pack_nmm_stop_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NMM_STOP_RESPONSE: - result = pack_nmm_stop_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MIN) - { - if(config && config->pack_p4_p5_vendor_extension) - { - result =(config->pack_p4_p5_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve encoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - // return the packed length - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Result is 0\n"); - return -1; - } - - - // check for a valid message length - packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - if(push16(packedMsgLen16, &pPackedLengthField, end) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header lengt\n"); - return -1; - } - - return (packedMsgLen); + case NFAPI_CELL_SEARCH_REQUEST: + result = pack_cell_search_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_CELL_SEARCH_RESPONSE: + result = pack_cell_search_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_CELL_SEARCH_INDICATION: + result = pack_cell_search_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_BROADCAST_DETECT_REQUEST: + result = pack_broadcast_detect_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_BROADCAST_DETECT_RESPONSE: + result = pack_broadcast_detect_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_BROADCAST_DETECT_INDICATION: + result = pack_broadcast_detect_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + result = pack_system_information_schedule_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: + result = pack_system_information_schedule_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: + result = pack_system_information_schedule_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_REQUEST: + result = pack_system_information_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_RESPONSE: + result = pack_system_information_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SYSTEM_INFORMATION_INDICATION: + result = pack_system_information_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NMM_STOP_REQUEST: + result = pack_nmm_stop_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NMM_STOP_RESPONSE: + result = pack_nmm_stop_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MIN) { + if(config && config->pack_p4_p5_vendor_extension) { + result =(config->pack_p4_p5_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve encoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + // return the packed length + if(result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Result is 0\n"); + return -1; + } + + // check for a valid message length + packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); + + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + if(push16(packedMsgLen16, &pPackedLengthField, end) == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to pack p4 message header lengt\n"); + return -1; + } + + return (packedMsgLen); } // Main unpack functions - public -int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; +int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 header unpack supplied pointers are null\n"); - return -1; - } + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 header unpack supplied pointers are null\n"); + return -1; + } - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } - // process the headei - if (pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end)) - return -1; + // process the headei + if (pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end)) + return -1; - return 0; + return 0; } -int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - int result = 0; - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; +int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + int result = 0; + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied pointers are null\n"); - return -1; - } + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied pointers are null\n"); + return -1; + } - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P4 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) - return -1; + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) + return -1; - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_RSSI_REQUEST: - if (check_unpack_length(NFAPI_RSSI_REQUEST, unpackedBufLen)) - result = unpack_rssi_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_RSSI_REQUEST: + if (check_unpack_length(NFAPI_RSSI_REQUEST, unpackedBufLen)) + result = unpack_rssi_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_RSSI_RESPONSE: - if (check_unpack_length(NFAPI_RSSI_RESPONSE, unpackedBufLen)) - result = unpack_rssi_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_RSSI_INDICATION: - if (check_unpack_length(NFAPI_RSSI_INDICATION, unpackedBufLen)) - result = unpack_rssi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_RSSI_RESPONSE: + if (check_unpack_length(NFAPI_RSSI_RESPONSE, unpackedBufLen)) + result = unpack_rssi_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_CELL_SEARCH_REQUEST: - if (check_unpack_length(NFAPI_CELL_SEARCH_REQUEST, unpackedBufLen)) - result = unpack_cell_search_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_CELL_SEARCH_RESPONSE: - if (check_unpack_length(NFAPI_CELL_SEARCH_RESPONSE, unpackedBufLen)) - result = unpack_cell_search_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_RSSI_INDICATION: + if (check_unpack_length(NFAPI_RSSI_INDICATION, unpackedBufLen)) + result = unpack_rssi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_CELL_SEARCH_INDICATION: - if (check_unpack_length(NFAPI_CELL_SEARCH_INDICATION, unpackedBufLen)) - result = unpack_cell_search_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_BROADCAST_DETECT_REQUEST: - if (check_unpack_length(NFAPI_BROADCAST_DETECT_REQUEST, unpackedBufLen)) - result = unpack_broadcast_detect_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_CELL_SEARCH_REQUEST: + if (check_unpack_length(NFAPI_CELL_SEARCH_REQUEST, unpackedBufLen)) + result = unpack_cell_search_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_BROADCAST_DETECT_RESPONSE: - if (check_unpack_length(NFAPI_BROADCAST_DETECT_RESPONSE, unpackedBufLen)) - result = unpack_broadcast_detect_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_BROADCAST_DETECT_INDICATION: - if (check_unpack_length(NFAPI_BROADCAST_DETECT_INDICATION, unpackedBufLen)) - result = unpack_broadcast_detect_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_CELL_SEARCH_RESPONSE: + if (check_unpack_length(NFAPI_CELL_SEARCH_RESPONSE, unpackedBufLen)) + result = unpack_cell_search_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST, unpackedBufLen)) - result = unpack_system_information_schedule_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; - - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE, unpackedBufLen)) - result = unpack_system_information_schedule_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION, unpackedBufLen)) - result = unpack_system_information_schedule_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_CELL_SEARCH_INDICATION: + if (check_unpack_length(NFAPI_CELL_SEARCH_INDICATION, unpackedBufLen)) + result = unpack_cell_search_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_SYSTEM_INFORMATION_REQUEST: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_REQUEST, unpackedBufLen)) - result = unpack_system_information_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_SYSTEM_INFORMATION_RESPONSE: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_RESPONSE, unpackedBufLen)) - result = unpack_system_information_response(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_BROADCAST_DETECT_REQUEST: + if (check_unpack_length(NFAPI_BROADCAST_DETECT_REQUEST, unpackedBufLen)) + result = unpack_broadcast_detect_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_SYSTEM_INFORMATION_INDICATION: - if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_INDICATION, unpackedBufLen)) - result = unpack_system_information_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + break; - case NFAPI_NMM_STOP_REQUEST: - if (check_unpack_length(NFAPI_NMM_STOP_REQUEST, unpackedBufLen)) - result = unpack_nmm_stop_request(&pReadPackedMessage, end, pMessageHeader, config); - else - result = -1; - break; + case NFAPI_BROADCAST_DETECT_RESPONSE: + if (check_unpack_length(NFAPI_BROADCAST_DETECT_RESPONSE, unpackedBufLen)) + result = unpack_broadcast_detect_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - case NFAPI_NMM_STOP_RESPONSE: - if (check_unpack_length(NFAPI_NMM_STOP_RESPONSE, unpackedBufLen)) - result = unpack_nmm_stop_response(&pReadPackedMessage, end , pMessageHeader, config); - else - result = -1; - break; + break; - default: - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p4_p5_vendor_extension) - { - result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P4 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } + case NFAPI_BROADCAST_DETECT_INDICATION: + if (check_unpack_length(NFAPI_BROADCAST_DETECT_INDICATION, unpackedBufLen)) + result = unpack_broadcast_detect_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; - if(result == 0) - return -1; + break; - return result; + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST, unpackedBufLen)) + result = unpack_system_information_schedule_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE, unpackedBufLen)) + result = unpack_system_information_schedule_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION, unpackedBufLen)) + result = unpack_system_information_schedule_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_REQUEST: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_REQUEST, unpackedBufLen)) + result = unpack_system_information_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_RESPONSE: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_RESPONSE, unpackedBufLen)) + result = unpack_system_information_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_SYSTEM_INFORMATION_INDICATION: + if (check_unpack_length(NFAPI_SYSTEM_INFORMATION_INDICATION, unpackedBufLen)) + result = unpack_system_information_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_NMM_STOP_REQUEST: + if (check_unpack_length(NFAPI_NMM_STOP_REQUEST, unpackedBufLen)) + result = unpack_nmm_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + case NFAPI_NMM_STOP_RESPONSE: + if (check_unpack_length(NFAPI_NMM_STOP_RESPONSE, unpackedBufLen)) + result = unpack_nmm_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + else + result = -1; + + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p4_p5_vendor_extension) { + result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P4 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + if(result == 0) + return -1; + + return result; } diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index a8ac0f0a65..3a6d807bdd 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -1,1830 +1,2388 @@ -/* - * Copyright 2017 Cisco Systems, Inc. - * - * 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. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -// Pack routines - -static uint8_t pack_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_param_request_t* request = (nfapi_pnf_param_request_t*)msg; - return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_pnf_param_general_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_param_general_t* value = (nfapi_pnf_param_general_t*)tlv; - - return ( push8(value->nfapi_sync_mode, ppWritePackedMsg, end) && - push8(value->location_mode, ppWritePackedMsg, end) && - push16(value->location_coordinates_length, ppWritePackedMsg, end) && - pusharray8(value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, ppWritePackedMsg, end) && - push32(value->dl_config_timing, ppWritePackedMsg, end) && - push32(value->tx_timing, ppWritePackedMsg, end) && - push32(value->ul_config_timing, ppWritePackedMsg, end) && - push32(value->hi_dci0_timing, ppWritePackedMsg, end) && - push16(value->maximum_number_phys, ppWritePackedMsg, end) && - push16(value->maximum_total_bandwidth, ppWritePackedMsg, end) && - push8(value->maximum_total_number_dl_layers, ppWritePackedMsg, end) && - push8(value->maximum_total_number_ul_layers, ppWritePackedMsg, end) && - push8(value->shared_bands, ppWritePackedMsg, end) && - push8(value->shared_pa, ppWritePackedMsg, end) && - pushs16(value->maximum_total_power, ppWritePackedMsg, end) && - pusharray8(value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, ppWritePackedMsg, end)); -} - -static uint8_t pack_rf_config_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rf_config_info_t* rf = (nfapi_rf_config_info_t*)elem; - - return (push16(rf->rf_config_index, ppWritePackedMsg, end)); -} - - -static uint8_t pack_pnf_phy_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t* end) -{ - nfapi_pnf_phy_info_t* phy = (nfapi_pnf_phy_info_t*)elem; - - return ( push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->number_of_rfs, ppWritePackedMsg, end) && - packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) && - push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) && - packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) && - push16(phy->downlink_channel_bandwidth_supported, ppWritePackedMsg, end) && - push16(phy->uplink_channel_bandwidth_supported, ppWritePackedMsg, end) && - push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) && - push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) && - push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) && - push8(phy->nmm_modes_supported, ppWritePackedMsg, end)); - - -} - -static uint8_t pack_pnf_phy_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_t* value = (nfapi_pnf_phy_t*)tlv; - - return ( push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_info)); -} - -static uint8_t pack_pnf_rf_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_rf_t* value = (nfapi_pnf_rf_t*)tlv; - uint16_t rf_index = 0; - - if(push16(value->number_of_rfs, ppWritePackedMsg, end) == 0) - return 0; - - for(; rf_index < value->number_of_rfs; ++rf_index) - { - if( !(push16(value->rf[rf_index].rf_config_index, ppWritePackedMsg, end) && - push16(value->rf[rf_index].band, ppWritePackedMsg, end) && - pushs16(value->rf[rf_index].maximum_transmit_power, ppWritePackedMsg, end) && - pushs16(value->rf[rf_index].minimum_transmit_power, ppWritePackedMsg, end) && - push8(value->rf[rf_index].number_of_antennas_suppported, ppWritePackedMsg, end) && - push32(value->rf[rf_index].minimum_downlink_frequency, ppWritePackedMsg, end) && - push32(value->rf[rf_index].maximum_downlink_frequency, ppWritePackedMsg, end) && - push32(value->rf[rf_index].minimum_uplink_frequency, ppWritePackedMsg, end) && - push32(value->rf[rf_index].maximum_uplink_frequency, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} -static uint8_t pack_pnf_phy_rel10_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel10_info_t* phy = (nfapi_pnf_phy_rel10_info_t*)elem; - - return(push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->transmission_mode_7_supported, ppWritePackedMsg, end) && - push16(phy->transmission_mode_8_supported, ppWritePackedMsg, end) && - push16(phy->two_antenna_ports_for_pucch, ppWritePackedMsg, end) && - push16(phy->transmission_mode_9_supported, ppWritePackedMsg, end) && - push16(phy->simultaneous_pucch_pusch, ppWritePackedMsg, end) && - push16(phy->four_layer_tx_with_tm3_and_tm4, ppWritePackedMsg, end)); -} - -static uint8_t pack_pnf_phy_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel10_t* value = (nfapi_pnf_phy_rel10_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel10_info)); - -} - -static uint8_t pack_pnf_phy_rel11_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel11_info_t* phy = (nfapi_pnf_phy_rel11_info_t*)elem; - - return (push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->edpcch_supported, ppWritePackedMsg, end) && - push16(phy->multi_ack_csi_reporting, ppWritePackedMsg, end) && - push16(phy->pucch_tx_diversity, ppWritePackedMsg, end) && - push16(phy->ul_comp_supported, ppWritePackedMsg, end) && - push16(phy->transmission_mode_5_supported, ppWritePackedMsg, end )); -} -static uint8_t pack_pnf_phy_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel11_t* value = (nfapi_pnf_phy_rel11_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel11_info)); -} -static uint8_t pack_pnf_phy_rel12_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel12_info_t* phy = (nfapi_pnf_phy_rel12_info_t*)elem; - - return( push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->csi_subframe_set, ppWritePackedMsg, end) && - push16(phy->enhanced_4tx_codebook, ppWritePackedMsg, end) && - push16(phy->drs_supported, ppWritePackedMsg, end) && - push16(phy->ul_64qam_supported, ppWritePackedMsg, end) && - push16(phy->transmission_mode_10_supported, ppWritePackedMsg, end) && - push16(phy->alternative_bts_indices, ppWritePackedMsg, end)); -} -static uint8_t pack_pnf_phy_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel12_t* value = (nfapi_pnf_phy_rel12_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel12_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel12_info)); - -} - -static uint8_t pack_pnf_phy_rel13_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_info_t* phy = (nfapi_pnf_phy_rel13_info_t*)elem; - - return( push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->pucch_format4_supported, ppWritePackedMsg, end) && - push16(phy->pucch_format5_supported, ppWritePackedMsg, end) && - push16(phy->more_than_5_ca_support, ppWritePackedMsg, end) && - push16(phy->laa_supported, ppWritePackedMsg, end) && - push16(phy->laa_ending_in_dwpts_supported, ppWritePackedMsg, end) && - push16(phy->laa_starting_in_second_slot_supported, ppWritePackedMsg, end) && - push16(phy->beamforming_supported, ppWritePackedMsg, end) && - push16(phy->csi_rs_enhancement_supported, ppWritePackedMsg, end) && - push16(phy->drms_enhancement_supported, ppWritePackedMsg, end) && - push16(phy->srs_enhancement_supported, ppWritePackedMsg, end) ); -} - -static uint8_t pack_pnf_phy_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_t* value = (nfapi_pnf_phy_rel13_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_info)); -} - -static uint8_t pack_pnf_phy_rel13_nb_iot_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_nb_iot_info_t* phy = (nfapi_pnf_phy_rel13_nb_iot_info_t*)elem; - - return( push16(phy->phy_config_index, ppWritePackedMsg, end) && - push16(phy->number_of_rfs, ppWritePackedMsg, end) && - packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) && - push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) && - packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) && - push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) && - push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) && - push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) && - push8(phy->nmm_modes_supported, ppWritePackedMsg, end)); -} - -static uint8_t pack_pnf_phy_rel13_nb_iot_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_nb_iot_t* value = (nfapi_pnf_phy_rel13_nb_iot_t*)tlv; - - return (push16(value->number_of_phys, ppWritePackedMsg, end) && - packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_info)); -} - - -static uint8_t pack_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t*)msg; - - return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && - pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && - pack_tlv(NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, ppWritePackedMsg, end, &pack_pnf_rf_value) && - pack_tlv(NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, ppWritePackedMsg, end, &pack_pnf_phy_rel10_value) && - pack_tlv(NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, ppWritePackedMsg, end, &pack_pnf_phy_rel11_value) && - pack_tlv(NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, ppWritePackedMsg, end, &pack_pnf_phy_rel12_value) && - pack_tlv(NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, ppWritePackedMsg, end, &pack_pnf_phy_rel13_value) && - pack_tlv(NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_phy_rf_config_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_phy_rf_config_info_t* rf = (nfapi_phy_rf_config_info_t*)elem; - - return (push16(rf->phy_id, ppWritePackedMsg, end) && - push16(rf->phy_config_index, ppWritePackedMsg, end) && - push16(rf->rf_config_index, ppWritePackedMsg, end)); -} - - -static uint8_t pack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rf_config_t *value = (nfapi_pnf_phy_rf_config_t*)tlv; - - return(push16(value->number_phy_rf_config_info, ppWritePackedMsg, end) && - packarray(value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, ppWritePackedMsg, end, &pack_phy_rf_config_info)); - -} - -static uint8_t pack_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t*)msg; - return ( pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end , config)); -} - - -static uint8_t pack_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t*)msg; - return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t*)msg; - - return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t*)msg; - return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t*)msg; - return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_uint16_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_uint16_tlv_t* value = (nfapi_uint16_tlv_t*)tlv; - return push16(value->value, ppWritePackedMsg, end); -} - -static uint8_t unpack_uint16_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_uint16_tlv_t* value = (nfapi_uint16_tlv_t*)tlv; - return pull16(ppReadPackedMsg, &value->value, end); -} -static uint8_t pack_int16_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_int16_tlv_t* value = (nfapi_int16_tlv_t*)tlv; - return pushs16(value->value, ppWritePackedMsg, end); -} - -static uint8_t unpack_int16_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_int16_tlv_t* value = (nfapi_int16_tlv_t*)tlv; - return pulls16(ppReadPackedMsg, &value->value, end); -} - -static uint8_t pack_uint8_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_uint8_tlv_t* value = (nfapi_uint8_tlv_t*)tlv; - return push8(value->value, ppWritePackedMsg, end); -} -static uint8_t unpack_uint8_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_uint8_tlv_t* value = (nfapi_uint8_tlv_t*)tlv; - return pull8(ppReadPackedMsg, &value->value, end); -} - -static uint8_t pack_ipv4_address_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv; - return pusharray8(value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, ppWritePackedMsg, end); -} -static uint8_t unpack_ipv4_address_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv; - return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, end); -} -static uint8_t pack_ipv6_address_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ipv6_address_t* value = (nfapi_ipv6_address_t*)tlv; - return pusharray8(value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, ppWritePackedMsg, end); -} -static uint8_t unpack_ipv6_address_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ipv4_address_t* value = (nfapi_ipv4_address_t*)tlv; - return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, end); -} - -static uint8_t pack_rf_bands_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rf_bands_t* value = (nfapi_rf_bands_t*)tlv; - - return ( push16(value->number_rf_bands, ppWritePackedMsg, end) && - pusharray16(value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, ppWritePackedMsg, end)); -} -static uint8_t unpack_rf_bands_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end) -{ - nfapi_rf_bands_t* value = (nfapi_rf_bands_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_rf_bands, end) && - pullarray16(ppReadPackedMsg, value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, end)); -} - -static uint8_t pack_nmm_frequency_bands_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nmm_frequency_bands_t* value = (nfapi_nmm_frequency_bands_t*)tlv; - - return( push16(value->number_of_rf_bands, ppWritePackedMsg, end) && - pusharray16(value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, ppWritePackedMsg, end)); -} -static uint8_t unpack_nmm_frequency_bands_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nmm_frequency_bands_t* value = (nfapi_nmm_frequency_bands_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_rf_bands, end) && - pullarray16(ppReadPackedMsg, value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, end)); -} -static uint8_t pack_embms_mbsfn_config_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv; - - return ( push16(value->num_mbsfn_config, ppWritePackedMsg, end) && - pusharray16(value->radioframe_allocation_period, 8,value->num_mbsfn_config ,ppWritePackedMsg, end) && - pusharray16(value->radioframe_allocation_offset, 8,value->num_mbsfn_config ,ppWritePackedMsg, end) && - pusharray8(value->fourframes_flag, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && - pusharrays32(value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, ppWritePackedMsg, end)); -} -//static uint8_t unpack_embms_mbsfn_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end) -//{ -// nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv; -// -// return ( pull16(ppReadPackedMsg, &value->num_mbsfn_config, end) && -// pull16(ppReadPackedMsg, &value->radioframe_allocation_period, end) && -// pull16(ppReadPackedMsg, &value->radioframe_allocation_offset, end) && -// pull8(ppReadPackedMsg, &value->fourframes_flag, end) && -// pullarrays32(ppReadPackedMsg, value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, end)); -//} -static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg; - - return( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && - push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && - pack_tlv(NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - // Do we check the phy state and then just fill those sepecified, however - // we do not know the duplex mode, so just attempt to pack all and assumme - // that the callee has set the right tlvs - - pack_tlv(NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.phy_antenna_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.mbsfn_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - // laa capability - - pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value)&& - pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end ,&pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDX_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_idx), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDR9_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_id_r9), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_TAG, &(pNfapiMsg->embms_mbsfn_config), ppWritePackedMsg, end, &pack_embms_mbsfn_config_value) && - - pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_PERIOD_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_OFFSET_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_FLAG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_config_flag), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_SUBFRAMECONFIG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_subframeconfig), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - - pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - - pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - - pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && - - pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - - pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); - -} - -static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t*)msg; - - return ( push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && - - // Do we check the phy state and then just fill those sepecified, however - // we do not know the duplex mode, so just attempt to pack all and assumme - // that the callee has set the right tlvs - - pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_pdsch), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &(pNfapiMsg->laa_config.pd_threshold), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &(pNfapiMsg->laa_config.multi_carrier_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &(pNfapiMsg->laa_config.multi_carrier_tx), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &(pNfapiMsg->laa_config.multi_carrier_freeze), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_antenna_ports_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_power_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &(pNfapiMsg->emtc_config.pbch_repetitions_enable_r13), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_catm_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &(pNfapiMsg->emtc_config.prach_catm_high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - - pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && - pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && - pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_PHY_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && - - pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - - - pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && - pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t*)msg; - return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t*)msg; - return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); -} - -static uint8_t pack_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t*)msg; - - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); -} - -static uint8_t pack_measurement_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t*)msg; - - return( pack_tlv(NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &(pNfapiMsg->dl_rs_tx_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &(pNfapiMsg->received_interference_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &(pNfapiMsg->thermal_noise_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_recevied_interference_power_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_received_interference_power_measurement_t* value = (nfapi_received_interference_power_measurement_t*)tlv; - - return ( push16(value->number_of_resource_blocks, ppWritePackedMsg, end) && - pusharrays16(value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, ppWritePackedMsg, end)); -} - -static uint8_t pack_measurement_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t*)msg; - - return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && - pack_tlv(NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &(pNfapiMsg->dl_rs_tx_power_measurement), ppWritePackedMsg, end, &pack_int16_tlv_value) && - pack_tlv(NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &(pNfapiMsg->received_interference_power_measurement), ppWritePackedMsg, end, &pack_recevied_interference_power_measurement_value) && - pack_tlv(NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &(pNfapiMsg->thermal_noise_power_measurement), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ - uint8_t result = 0; - // look for the specific message - switch (header->message_id) - { - case NFAPI_PNF_PARAM_REQUEST: - result = pack_pnf_param_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_PARAM_RESPONSE: - result = pack_pnf_param_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_CONFIG_REQUEST: - result = pack_pnf_config_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_CONFIG_RESPONSE: - result = pack_pnf_config_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_START_REQUEST: - result = pack_pnf_start_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_START_RESPONSE: - result = pack_pnf_start_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_STOP_REQUEST: - result = pack_pnf_stop_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PNF_STOP_RESPONSE: - result = pack_pnf_stop_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PARAM_REQUEST: - result = pack_param_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_PARAM_RESPONSE: - result = pack_param_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_CONFIG_REQUEST: - result = pack_config_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_CONFIG_RESPONSE: - result = pack_config_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_START_REQUEST: - result = pack_start_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_START_RESPONSE: - result = pack_start_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_STOP_REQUEST: - result = pack_stop_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_STOP_RESPONSE: - result = pack_stop_response(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_MEASUREMENT_REQUEST: - result = pack_measurement_request(header, ppWritePackedMsg, end, config); - break; - - case NFAPI_MEASUREMENT_RESPONSE: - result = pack_measurement_response(header, ppWritePackedMsg, end, config); - break; - - default: - { - if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p4_p5_vendor_extension) - { - result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); - } - } - break; - } - - return result; -} - - -// helper function for message length calculation - -// takes the pointers to the start of message to end of message - -static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) -{ - if (msgEnd < msgHead) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd); - return 0; - } - - return (msgEnd - msgHead); -} - -// Main pack function - public - -int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint32_t packedMsgLen; - uint16_t packedMsgLen16; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); - return -1; - } - - // pack the message - if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && - push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, pPackMessageEnd) && - push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && - pack_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config)) - { - // check for a valid message length - packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) - return -1; - - // return the packed length - return (packedMsgLen); - } - else - { - // Failed to pack the meassage - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n"); - return -1; - } - -} - - - -// Unpack routines -static uint8_t unpack_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_param_request_t *pNfapiMsg = (nfapi_pnf_param_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_pnf_param_general_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_param_general_t* value = (nfapi_pnf_param_general_t*)tlv; - - return( pull8(ppReadPackedMsg, &value->nfapi_sync_mode, end) && - pull8(ppReadPackedMsg, &value->location_mode, end) && - pull16(ppReadPackedMsg, &value->location_coordinates_length, end) && - pullarray8(ppReadPackedMsg, value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, end) && - pull32(ppReadPackedMsg, &value->dl_config_timing, end) && - pull32(ppReadPackedMsg, &value->tx_timing, end) && - pull32(ppReadPackedMsg, &value->ul_config_timing, end) && - pull32(ppReadPackedMsg, &value->hi_dci0_timing, end) && - pull16(ppReadPackedMsg, &value->maximum_number_phys, end) && - pull16(ppReadPackedMsg, &value->maximum_total_bandwidth, end) && - pull8(ppReadPackedMsg, &value->maximum_total_number_dl_layers, end) && - pull8(ppReadPackedMsg, &value->maximum_total_number_ul_layers, end) && - pull8(ppReadPackedMsg, &value->shared_bands, end) && - pull8(ppReadPackedMsg, &value->shared_pa, end) && - pulls16(ppReadPackedMsg, &value->maximum_total_power, end) && - pullarray8(ppReadPackedMsg, value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, end)); -} - -static uint8_t unpack_rf_config_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rf_config_info_t* info = (nfapi_rf_config_info_t*)elem; - return pull16(ppReadPackedMsg, &info->rf_config_index, end); -} - -static uint8_t unpack_pnf_phy_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_info_t* phy = (nfapi_pnf_phy_info_t*)elem; - - return ( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->number_of_rfs, end) && - unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) && - pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) && - unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) && - pull16(ppReadPackedMsg, &phy->downlink_channel_bandwidth_supported, end) && - pull16(ppReadPackedMsg, &phy->uplink_channel_bandwidth_supported, end) && - pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) && - pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) && - pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) && - pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end)); -} - - -static uint8_t unpack_pnf_phy_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_t* value = (nfapi_pnf_phy_t*)tlv; - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_info)); -} - -static uint8_t unpack_pnf_rf_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_rf_info_t* rf = (nfapi_pnf_rf_info_t*)elem; - - return( pull16(ppReadPackedMsg, &rf->rf_config_index, end) && - pull16(ppReadPackedMsg, &rf->band, end) && - pulls16(ppReadPackedMsg, &rf->maximum_transmit_power, end) && - pulls16(ppReadPackedMsg, &rf->minimum_transmit_power, end) && - pull8(ppReadPackedMsg, &rf->number_of_antennas_suppported, end) && - pull32(ppReadPackedMsg, &rf->minimum_downlink_frequency, end) && - pull32(ppReadPackedMsg, &rf->maximum_downlink_frequency, end) && - pull32(ppReadPackedMsg, &rf->minimum_uplink_frequency, end) && - pull32(ppReadPackedMsg, &rf->maximum_uplink_frequency, end)); - -} -static uint8_t unpack_pnf_rf_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_rf_t* value = (nfapi_pnf_rf_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_rfs, end) && - unpackarray(ppReadPackedMsg, value->rf, sizeof(nfapi_pnf_rf_info_t), NFAPI_MAX_PNF_RF, value->number_of_rfs, end, &unpack_pnf_rf_info)); -} - -static uint8_t unpack_pnf_phy_rel10_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel10_info_t* phy = (nfapi_pnf_phy_rel10_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_7_supported, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_8_supported, end) && - pull16(ppReadPackedMsg, &phy->two_antenna_ports_for_pucch, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_9_supported, end) && - pull16(ppReadPackedMsg, &phy->simultaneous_pucch_pusch, end) && - pull16(ppReadPackedMsg, &phy->four_layer_tx_with_tm3_and_tm4, end)); - - -} -static uint8_t unpack_pnf_phy_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel10_t* value = (nfapi_pnf_phy_rel10_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel10_info)); - -} - - -static uint8_t unpack_pnf_phy_rel11_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel11_info_t* phy = (nfapi_pnf_phy_rel11_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->edpcch_supported, end) && - pull16(ppReadPackedMsg, &phy->multi_ack_csi_reporting, end ) && - pull16(ppReadPackedMsg, &phy->pucch_tx_diversity, end) && - pull16(ppReadPackedMsg, &phy->ul_comp_supported, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_5_supported, end)); -} - -static uint8_t unpack_pnf_phy_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel11_t* value = (nfapi_pnf_phy_rel11_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel11_info)); - -} - -static uint8_t unpack_phy_phy_rel12_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel12_info_t* phy = (nfapi_pnf_phy_rel12_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->csi_subframe_set, end) && - pull16(ppReadPackedMsg, &phy->enhanced_4tx_codebook, end) && - pull16(ppReadPackedMsg, &phy->drs_supported, end) && - pull16(ppReadPackedMsg, &phy->ul_64qam_supported, end) && - pull16(ppReadPackedMsg, &phy->transmission_mode_10_supported, end) && - pull16(ppReadPackedMsg, &phy->alternative_bts_indices, end)); -} - -static uint8_t unpack_pnf_phy_rel12_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel12_t* value = (nfapi_pnf_phy_rel12_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel12_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_phy_phy_rel12_info)); - -} - -static uint8_t unpack_pnf_phy_rel13_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_info_t* phy = (nfapi_pnf_phy_rel13_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->pucch_format4_supported, end) && - pull16(ppReadPackedMsg, &phy->pucch_format5_supported, end) && - pull16(ppReadPackedMsg, &phy->more_than_5_ca_support, end) && - pull16(ppReadPackedMsg, &phy->laa_supported, end) && - pull16(ppReadPackedMsg, &phy->laa_ending_in_dwpts_supported, end) && - pull16(ppReadPackedMsg, &phy->laa_starting_in_second_slot_supported, end) && - pull16(ppReadPackedMsg, &phy->beamforming_supported, end) && - pull16(ppReadPackedMsg, &phy->csi_rs_enhancement_supported, end) && - pull16(ppReadPackedMsg, &phy->drms_enhancement_supported, end) && - pull16(ppReadPackedMsg, &phy->srs_enhancement_supported, end)); -} - -static uint8_t unpack_pnf_phy_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_t* value = (nfapi_pnf_phy_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_info)); -} - -static uint8_t unpack_pnf_phy_rel13_nb_info_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_nb_iot_info_t* phy = (nfapi_pnf_phy_rel13_nb_iot_info_t*)elem; - - return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && - pull16(ppReadPackedMsg, &phy->number_of_rfs, end) && - unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) && - pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) && - unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) && - pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) && - pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) && - pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) && - pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end)); -} - -static uint8_t unpack_pnf_phy_rel13_nb_iot_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rel13_nb_iot_t* value = (nfapi_pnf_phy_rel13_nb_iot_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && - unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_nb_info_info)); -} - - - -static uint8_t unpack_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value}, - { NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value}, - { NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, &unpack_pnf_rf_value}, - { NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, &unpack_pnf_phy_rel10_value}, - { NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, &unpack_pnf_phy_rel11_value}, - { NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, &unpack_pnf_phy_rel12_value}, - { NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, &unpack_pnf_phy_rel13_value}, - { NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, &unpack_pnf_phy_rel13_nb_iot_value}, - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_phy_rf_config_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_phy_rf_config_info_t* rf = (nfapi_phy_rf_config_info_t*)elem; - - return( pull16(ppReadPackedMsg, &rf->phy_id, end) && - pull16(ppReadPackedMsg, &rf->phy_config_index, end) && - pull16(ppReadPackedMsg, &rf->rf_config_index, end)); - -} - -static uint8_t unpack_pnf_phy_rf_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_pnf_phy_rf_config_t* value = (nfapi_pnf_phy_rf_config_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_phy_rf_config_info, end) && - unpackarray(ppReadPackedMsg, value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, end, &unpack_phy_rf_config_info)); -} - -static uint8_t unpack_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value}, - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); -} - -static uint8_t unpack_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} - -static uint8_t unpack_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); -} - -static uint8_t unpack_pnf_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_pnf_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} - -static uint8_t unpack_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, &unpack_uint16_tlv_value}, - - { NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_bandwidth_support, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_bandwidth_support, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_modulation_support, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_modulation_support, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.phy_antenna_capability, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.release_capability, &unpack_uint16_tlv_value}, - { NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.mbsfn_capability, &unpack_uint16_tlv_value}, - - { NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG, &pNfapiMsg->laa_capability.laa_support, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.pd_sensing_lbt_support, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.multi_carrier_lbt_support, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG, &pNfapiMsg->laa_capability.partial_sf_support, &unpack_uint16_tlv_value}, - - { NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value}, - - { NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value}, - - { NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value}, - { NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value}, - { NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value}, - - { NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, - { NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, - { NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value}, - - { NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value}, - - { NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value}, - { NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value}, - - { NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value}, - - { NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value}, - - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value}, - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value}, - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value}, - - { NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value}, - { NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value}, - - { NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value}, - { NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value}, - - { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, - { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, - { NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, - { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, - { NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value}, - { NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value}, - - }; - - return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value}, - { NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value}, - - { NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value}, - { NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value}, - - { NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value}, - { NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value}, - { NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value}, - - { NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, - { NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, - { NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value}, - - { NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value}, - { NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value}, - - { NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value}, - { NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value}, - - { NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value}, - { NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value}, - - { NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value}, - { NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value}, - - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value}, - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value}, - { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value}, - - - { NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_pdsch, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_drs, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &pNfapiMsg->laa_config.pd_threshold, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &pNfapiMsg->laa_config.multi_carrier_type, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &pNfapiMsg->laa_config.multi_carrier_tx, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &pNfapiMsg->laa_config.multi_carrier_freeze, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_antenna_ports_drs, &unpack_uint16_tlv_value}, - { NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_power_drs, &unpack_uint16_tlv_value}, - - { NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &pNfapiMsg->emtc_config.pbch_repetitions_enable_r13, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->emtc_config.prach_catm_root_sequence_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &pNfapiMsg->emtc_config.prach_catm_high_speed_flag, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea, &unpack_uint16_tlv_value}, - { NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb, &unpack_uint16_tlv_value}, - - { NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value}, - { NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value}, - - { NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value}, - { NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value}, - - { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, - { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, - { NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, - { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, - { NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value}, - { NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, - { NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value}, - { NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value}, - { NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value}, - - }; - - return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); -} - -static uint8_t unpack_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} - -static uint8_t unpack_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); - -} -static uint8_t unpack_measurement_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &pNfapiMsg->dl_rs_tx_power, &unpack_uint16_tlv_value}, - { NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &pNfapiMsg->received_interference_power, &unpack_uint16_tlv_value}, - { NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &pNfapiMsg->thermal_noise_power, &unpack_uint16_tlv_value}, - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_received_interference_power_measurement_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_received_interference_power_measurement_t* value = (nfapi_received_interference_power_measurement_t*)tlv; - - return ( pull16(ppReadPackedMsg, &value->number_of_resource_blocks, end) && - pullarrays16(ppReadPackedMsg, value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, end)); -} - - -static uint8_t unpack_measurement_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t*)msg; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &pNfapiMsg->dl_rs_tx_power_measurement, &unpack_int16_tlv_value}, - { NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &pNfapiMsg->received_interference_power_measurement, &unpack_received_interference_power_measurement_value}, - { NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &pNfapiMsg->thermal_noise_power_measurement, &unpack_int16_tlv_value}, - }; - - return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -// unpack length check - -static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_PNF_PARAM_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t)) - retLen = sizeof(nfapi_pnf_param_request_t); - break; - - case NFAPI_PNF_PARAM_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_pnf_param_response_t)) - retLen = sizeof(nfapi_pnf_param_response_t); - break; - - case NFAPI_PNF_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_config_request_t)) - retLen = sizeof(nfapi_pnf_config_request_t); - break; - - case NFAPI_PNF_CONFIG_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_pnf_config_response_t)) - retLen = sizeof(nfapi_pnf_config_response_t); - break; - - case NFAPI_PNF_START_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_start_request_t)) - retLen = sizeof(nfapi_pnf_start_request_t); - break; - - case NFAPI_PNF_START_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_pnf_start_response_t)) - retLen = sizeof(nfapi_pnf_start_response_t); - break; - - case NFAPI_PNF_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_pnf_stop_request_t)) - retLen = sizeof(nfapi_pnf_stop_request_t); - break; - - case NFAPI_PNF_STOP_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_pnf_stop_response_t)) - retLen = sizeof(nfapi_pnf_stop_response_t); - break; - - case NFAPI_PARAM_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_param_request_t)) - retLen = sizeof(nfapi_param_request_t); - break; - - case NFAPI_PARAM_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_param_response_t)) - retLen = sizeof(nfapi_param_response_t); - break; - - case NFAPI_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_config_request_t)) - retLen = sizeof(nfapi_config_request_t); - break; - - case NFAPI_CONFIG_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_config_response_t)) - retLen = sizeof(nfapi_config_response_t); - break; - - case NFAPI_START_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_start_request_t)) - retLen = sizeof(nfapi_start_request_t); - break; - - case NFAPI_START_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_start_response_t)) - retLen = sizeof(nfapi_start_response_t); - break; - - case NFAPI_STOP_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_stop_request_t)) - retLen = sizeof(nfapi_stop_request_t); - break; - - case NFAPI_STOP_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_stop_response_t)) - retLen = sizeof(nfapi_stop_response_t); - break; - - case NFAPI_MEASUREMENT_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_measurement_request_t)) - retLen = sizeof(nfapi_measurement_request_t); - break; - - case NFAPI_MEASUREMENT_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_measurement_response_t)) - retLen = sizeof(nfapi_measurement_response_t); - break; - - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); - break; - } - - return retLen; -} - - -// Main unpack functions - public - -int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - - // process the header - return ( pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end) ); - -} - -int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) -{ - nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); - - // process the header - if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) - { - // failed to read the header - return -1; - } - - int result = -1; - - - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - // the unpack buffer is not big enough for the struct - return -1; - } - - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_PNF_PARAM_REQUEST: - result = unpack_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_PARAM_RESPONSE: - result = unpack_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_CONFIG_REQUEST: - result = unpack_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_CONFIG_RESPONSE: - result = unpack_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_START_REQUEST: - result = unpack_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_START_RESPONSE: - result = unpack_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_STOP_REQUEST: - result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PNF_STOP_RESPONSE: - result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PARAM_REQUEST: - result = unpack_param_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_PARAM_RESPONSE: - result = unpack_param_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_CONFIG_REQUEST: - result = unpack_config_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_CONFIG_RESPONSE: - result = unpack_config_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_START_REQUEST: - result = unpack_start_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_START_RESPONSE: - result = unpack_start_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_STOP_REQUEST: - result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_STOP_RESPONSE: - result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_MEASUREMENT_REQUEST: - result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config); - break; - - case NFAPI_MEASUREMENT_RESPONSE: - result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config); - break; - - default: - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p4_p5_vendor_extension) - { - result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } - - return result; -} - +/* + * Copyright 2017 Cisco Systems, Inc. + * + * 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. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" +#include + + +// Pack routines +//TODO: Add pacl/unpack fns for uint32 and uint64 +static uint8_t pack_nr_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_param_request_t *request = (nfapi_nr_pnf_param_request_t *)msg; + return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_param_request_t *request = (nfapi_pnf_param_request_t *)msg; + return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_pnf_param_general_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_param_general_t *value = (nfapi_pnf_param_general_t *)tlv; + return ( push8(value->nfapi_sync_mode, ppWritePackedMsg, end) && + push8(value->location_mode, ppWritePackedMsg, end) && + push16(value->location_coordinates_length, ppWritePackedMsg, end) && + pusharray8(value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, ppWritePackedMsg, end) && + push32(value->dl_config_timing, ppWritePackedMsg, end) && + push32(value->tx_timing, ppWritePackedMsg, end) && + push32(value->ul_config_timing, ppWritePackedMsg, end) && + push32(value->hi_dci0_timing, ppWritePackedMsg, end) && + push16(value->maximum_number_phys, ppWritePackedMsg, end) && + push16(value->maximum_total_bandwidth, ppWritePackedMsg, end) && + push8(value->maximum_total_number_dl_layers, ppWritePackedMsg, end) && + push8(value->maximum_total_number_ul_layers, ppWritePackedMsg, end) && + push8(value->shared_bands, ppWritePackedMsg, end) && + push8(value->shared_pa, ppWritePackedMsg, end) && + pushs16(value->maximum_total_power, ppWritePackedMsg, end) && + pusharray8(value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, ppWritePackedMsg, end)); +} + +static uint8_t pack_rf_config_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rf_config_info_t *rf = (nfapi_rf_config_info_t *)elem; + return (push16(rf->rf_config_index, ppWritePackedMsg, end)); +} + + +static uint8_t pack_pnf_phy_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_info_t *phy = (nfapi_pnf_phy_info_t *)elem; + return ( push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->number_of_rfs, ppWritePackedMsg, end) && + packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) && + push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) && + packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) && + push16(phy->downlink_channel_bandwidth_supported, ppWritePackedMsg, end) && + push16(phy->uplink_channel_bandwidth_supported, ppWritePackedMsg, end) && + push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) && + push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) && + push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) && + push8(phy->nmm_modes_supported, ppWritePackedMsg, end)); +} + +static uint8_t pack_pnf_phy_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_t *value = (nfapi_pnf_phy_t *)tlv; + return ( push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_info)); +} + +static uint8_t pack_pnf_rf_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_rf_t *value = (nfapi_pnf_rf_t *)tlv; + uint16_t rf_index = 0; + + if(push16(value->number_of_rfs, ppWritePackedMsg, end) == 0) + return 0; + + for(; rf_index < value->number_of_rfs; ++rf_index) { + if( !(push16(value->rf[rf_index].rf_config_index, ppWritePackedMsg, end) && + push16(value->rf[rf_index].band, ppWritePackedMsg, end) && + pushs16(value->rf[rf_index].maximum_transmit_power, ppWritePackedMsg, end) && + pushs16(value->rf[rf_index].minimum_transmit_power, ppWritePackedMsg, end) && + push8(value->rf[rf_index].number_of_antennas_suppported, ppWritePackedMsg, end) && + push32(value->rf[rf_index].minimum_downlink_frequency, ppWritePackedMsg, end) && + push32(value->rf[rf_index].maximum_downlink_frequency, ppWritePackedMsg, end) && + push32(value->rf[rf_index].minimum_uplink_frequency, ppWritePackedMsg, end) && + push32(value->rf[rf_index].maximum_uplink_frequency, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} +static uint8_t pack_pnf_phy_rel10_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel10_info_t *phy = (nfapi_pnf_phy_rel10_info_t *)elem; + return(push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->transmission_mode_7_supported, ppWritePackedMsg, end) && + push16(phy->transmission_mode_8_supported, ppWritePackedMsg, end) && + push16(phy->two_antenna_ports_for_pucch, ppWritePackedMsg, end) && + push16(phy->transmission_mode_9_supported, ppWritePackedMsg, end) && + push16(phy->simultaneous_pucch_pusch, ppWritePackedMsg, end) && + push16(phy->four_layer_tx_with_tm3_and_tm4, ppWritePackedMsg, end)); +} + +static uint8_t pack_pnf_phy_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel10_t *value = (nfapi_pnf_phy_rel10_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel10_info)); +} + +static uint8_t pack_pnf_phy_rel11_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel11_info_t *phy = (nfapi_pnf_phy_rel11_info_t *)elem; + return (push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->edpcch_supported, ppWritePackedMsg, end) && + push16(phy->multi_ack_csi_reporting, ppWritePackedMsg, end) && + push16(phy->pucch_tx_diversity, ppWritePackedMsg, end) && + push16(phy->ul_comp_supported, ppWritePackedMsg, end) && + push16(phy->transmission_mode_5_supported, ppWritePackedMsg, end )); +} +static uint8_t pack_pnf_phy_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel11_t *value = (nfapi_pnf_phy_rel11_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel11_info)); +} +static uint8_t pack_pnf_phy_rel12_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel12_info_t *phy = (nfapi_pnf_phy_rel12_info_t *)elem; + return( push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->csi_subframe_set, ppWritePackedMsg, end) && + push16(phy->enhanced_4tx_codebook, ppWritePackedMsg, end) && + push16(phy->drs_supported, ppWritePackedMsg, end) && + push16(phy->ul_64qam_supported, ppWritePackedMsg, end) && + push16(phy->transmission_mode_10_supported, ppWritePackedMsg, end) && + push16(phy->alternative_bts_indices, ppWritePackedMsg, end)); +} +static uint8_t pack_pnf_phy_rel12_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel12_t *value = (nfapi_pnf_phy_rel12_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel12_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel12_info)); +} + +static uint8_t pack_pnf_phy_rel13_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_info_t *phy = (nfapi_pnf_phy_rel13_info_t *)elem; + return( push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->pucch_format4_supported, ppWritePackedMsg, end) && + push16(phy->pucch_format5_supported, ppWritePackedMsg, end) && + push16(phy->more_than_5_ca_support, ppWritePackedMsg, end) && + push16(phy->laa_supported, ppWritePackedMsg, end) && + push16(phy->laa_ending_in_dwpts_supported, ppWritePackedMsg, end) && + push16(phy->laa_starting_in_second_slot_supported, ppWritePackedMsg, end) && + push16(phy->beamforming_supported, ppWritePackedMsg, end) && + push16(phy->csi_rs_enhancement_supported, ppWritePackedMsg, end) && + push16(phy->drms_enhancement_supported, ppWritePackedMsg, end) && + push16(phy->srs_enhancement_supported, ppWritePackedMsg, end) ); +} + +static uint8_t pack_pnf_phy_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_t *value = (nfapi_pnf_phy_rel13_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_info)); +} + +static uint8_t pack_pnf_phy_rel13_nb_iot_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_nb_iot_info_t *phy = (nfapi_pnf_phy_rel13_nb_iot_info_t *)elem; + return( push16(phy->phy_config_index, ppWritePackedMsg, end) && + push16(phy->number_of_rfs, ppWritePackedMsg, end) && + packarray(phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, ppWritePackedMsg, end, &pack_rf_config_info) && + push16(phy->number_of_rf_exclusions, ppWritePackedMsg, end) && + packarray(phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, ppWritePackedMsg, end, &pack_rf_config_info) && + push8(phy->number_of_dl_layers_supported, ppWritePackedMsg, end) && + push8(phy->number_of_ul_layers_supported, ppWritePackedMsg, end) && + push16(phy->maximum_3gpp_release_supported, ppWritePackedMsg, end) && + push8(phy->nmm_modes_supported, ppWritePackedMsg, end)); +} + +static uint8_t pack_pnf_phy_rel13_nb_iot_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_nb_iot_t *value = (nfapi_pnf_phy_rel13_nb_iot_t *)tlv; + return (push16(value->number_of_phys, ppWritePackedMsg, end) && + packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_info)); +} +/* +static uint8_t pack_nr_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t*)msg; + + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && + pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} +*/ +static uint8_t pack_nr_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && + pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t *)msg; + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && + pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && + pack_tlv(NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, ppWritePackedMsg, end, &pack_pnf_rf_value) && + pack_tlv(NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, ppWritePackedMsg, end, &pack_pnf_phy_rel10_value) && + pack_tlv(NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, ppWritePackedMsg, end, &pack_pnf_phy_rel11_value) && + pack_tlv(NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, ppWritePackedMsg, end, &pack_pnf_phy_rel12_value) && + pack_tlv(NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, ppWritePackedMsg, end, &pack_pnf_phy_rel13_value) && + pack_tlv(NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_phy_rf_config_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_phy_rf_config_info_t *rf = (nfapi_phy_rf_config_info_t *)elem; + return (push16(rf->phy_id, ppWritePackedMsg, end) && + push16(rf->phy_config_index, ppWritePackedMsg, end) && + push16(rf->rf_config_index, ppWritePackedMsg, end)); +} + + +static uint8_t pack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_pnf_phy_rf_config_t *value = (nfapi_pnf_phy_rf_config_t *)tlv; + return(push16(value->number_phy_rf_config_info, ppWritePackedMsg, end) && + packarray(value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, ppWritePackedMsg, end, &pack_phy_rf_config_info)); +} + +static uint8_t pack_nr_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t *)msg; + return (pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && + //push8(pNfapiMsg->num_tlvs,ppWritePackedMsg,end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t *)msg; + return (pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && + push8(pNfapiMsg->num_tlvs,ppWritePackedMsg,end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_nr_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_config_response_t *pNfapiMsg = (nfapi_nr_pnf_config_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_start_request_t *pNfapiMsg = (nfapi_nr_pnf_start_request_t *)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t *)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_nr_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_start_response_t *pNfapiMsg = (nfapi_nr_pnf_start_response_t *)msg; + return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t *)msg; + return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_nr_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_stop_request_t *pNfapiMsg = (nfapi_nr_pnf_stop_request_t *)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + + +static uint8_t pack_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t *)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + +static uint8_t pack_nr_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_stop_response_t *pNfapiMsg = (nfapi_nr_pnf_stop_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +static uint8_t pack_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg; + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t *)msg; + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_uint32_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_uint32_tlv_t *value = (nfapi_uint32_tlv_t *)tlv; + return push32(value->value, ppWritePackedMsg, end); +} + +static uint8_t unpack_uint32_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_uint32_tlv_t *value = (nfapi_uint32_tlv_t *)tlv; + return pull32(ppReadPackedMsg, &value->value, end); +} + + +static uint8_t pack_uint16_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_uint16_tlv_t *value = (nfapi_uint16_tlv_t *)tlv; + return push16(value->value, ppWritePackedMsg, end); +} + +static uint8_t unpack_uint16_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_uint16_tlv_t *value = (nfapi_uint16_tlv_t *)tlv; + return pull16(ppReadPackedMsg, &value->value, end); +} + +static uint8_t pack_int16_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_int16_tlv_t *value = (nfapi_int16_tlv_t *)tlv; + return pushs16(value->value, ppWritePackedMsg, end); +} + +static uint8_t unpack_int16_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_int16_tlv_t *value = (nfapi_int16_tlv_t *)tlv; + return pulls16(ppReadPackedMsg, &value->value, end); +} + +static uint8_t pack_uint8_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_uint8_tlv_t *value = (nfapi_uint8_tlv_t *)tlv; + return push8(value->value, ppWritePackedMsg, end); +} +static uint8_t unpack_uint8_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_uint8_tlv_t *value = (nfapi_uint8_tlv_t *)tlv; + return pull8(ppReadPackedMsg, &value->value, end); +} + +static uint8_t pack_ipv4_address_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ipv4_address_t *value = (nfapi_ipv4_address_t *)tlv; + return pusharray8(value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, ppWritePackedMsg, end); +} +static uint8_t unpack_ipv4_address_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ipv4_address_t *value = (nfapi_ipv4_address_t *)tlv; + return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV4_ADDRESS_LENGTH, NFAPI_IPV4_ADDRESS_LENGTH, end); +} +static uint8_t pack_ipv6_address_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ipv6_address_t *value = (nfapi_ipv6_address_t *)tlv; + return pusharray8(value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, ppWritePackedMsg, end); +} +static uint8_t unpack_ipv6_address_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ipv4_address_t *value = (nfapi_ipv4_address_t *)tlv; + return pullarray8(ppReadPackedMsg, value->address, NFAPI_IPV6_ADDRESS_LENGTH, NFAPI_IPV6_ADDRESS_LENGTH, end); +} + +static uint8_t pack_rf_bands_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rf_bands_t *value = (nfapi_rf_bands_t *)tlv; + return ( push16(value->number_rf_bands, ppWritePackedMsg, end) && + pusharray16(value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, ppWritePackedMsg, end)); +} +static uint8_t unpack_rf_bands_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rf_bands_t *value = (nfapi_rf_bands_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_rf_bands, end) && + pullarray16(ppReadPackedMsg, value->rf_band, NFAPI_MAX_NUM_RF_BANDS, value->number_rf_bands, end)); +} + +static uint8_t pack_nmm_frequency_bands_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nmm_frequency_bands_t *value = (nfapi_nmm_frequency_bands_t *)tlv; + return( push16(value->number_of_rf_bands, ppWritePackedMsg, end) && + pusharray16(value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, ppWritePackedMsg, end)); +} +static uint8_t unpack_nmm_frequency_bands_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nmm_frequency_bands_t *value = (nfapi_nmm_frequency_bands_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_rf_bands, end) && + pullarray16(ppReadPackedMsg, value->bands, NFAPI_MAX_NMM_FREQUENCY_BANDS, value->number_of_rf_bands, end)); +} +static uint8_t pack_embms_mbsfn_config_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_embms_mbsfn_config_t *value = (nfapi_embms_mbsfn_config_t *)tlv; + return ( push16(value->num_mbsfn_config, ppWritePackedMsg, end) && + pusharray16(value->radioframe_allocation_period, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && + pusharray16(value->radioframe_allocation_offset, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && + pusharray8(value->fourframes_flag, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && + pusharrays32(value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, ppWritePackedMsg, end)); +} +// static uint8_t unpack_embms_mbsfn_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end) +// { +// nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv; + +// return ( pull16(ppReadPackedMsg, &value->num_mbsfn_config, end) && +// pull16(ppReadPackedMsg, &value->radioframe_allocation_period, end) && +// pull16(ppReadPackedMsg, &value->radioframe_allocation_offset, end) && +// pull8(ppReadPackedMsg, &value->fourframes_flag, end) && +// pullarrays32(ppReadPackedMsg, value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, end)); +// } + +static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t *)msg; + return( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + pack_tlv(NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, ppWritePackedMsg, end, &pack_uint16_tlv_value) && + // Do we check the phy state and then just fill those sepecified, however + // we do not know the duplex mode, so just attempt to pack all and assumme + // that the callee has set the right tlvs + pack_tlv(NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_bandwidth_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.dl_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &(pNfapiMsg->phy_capabilities.ul_modulation_support), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.phy_antenna_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &(pNfapiMsg->phy_capabilities.mbsfn_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + // laa capability + pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value)&& + pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end,&pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDX_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_idx), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_AREA_IDR9_TAG, &(pNfapiMsg->embms_sib13_config.mbsfn_area_id_r9), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMBMS_MBSFN_CONFIG_TAG, &(pNfapiMsg->embms_mbsfn_config), ppWritePackedMsg, end, &pack_embms_mbsfn_config_value) && + pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_PERIOD_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_FEMBMS_CONFIG_RADIOFRAME_ALLOCATION_OFFSET_TAG, &(pNfapiMsg->fembms_config.radioframe_allocation_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_FLAG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_config_flag), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_FEMBMS_CONFIG_NON_MBSFN_SUBFRAMECONFIG_TAG, &(pNfapiMsg->fembms_config.non_mbsfn_subframeconfig), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && + pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + printf("\nRUNNING pack_param_response\n"); + nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg; + return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param.num_config_tlvs_to_report ), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG, &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG, &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG, &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, &(pNfapiMsg->pusch_param.supported_modulation_order_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, &(pNfapiMsg->pusch_param.pusch_aggregation_factor), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG, &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, &(pNfapiMsg->measurement_param.rssi_measurement_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + // config: + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t *)msg; + return ( push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + // Do we check the phy state and then just fill those sepecified, however + // we do not know the duplex mode, so just attempt to pack all and assumme + // that the callee has set the right tlvs + pack_tlv(NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &(pNfapiMsg->subframe_config.duplex_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &(pNfapiMsg->subframe_config.pcfich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_PB_TAG, &(pNfapiMsg->subframe_config.pb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.dl_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &(pNfapiMsg->subframe_config.ul_cyclic_prefix_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.dl_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &(pNfapiMsg->rf_config.ul_channel_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &(pNfapiMsg->rf_config.reference_signal_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.tx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &(pNfapiMsg->rf_config.rx_antenna_ports), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &(pNfapiMsg->phich_config.phich_resource), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &(pNfapiMsg->phich_config.phich_duration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &(pNfapiMsg->phich_config.phich_power_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &(pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &(pNfapiMsg->sch_config.physical_cell_id), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->prach_config.configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->prach_config.zero_correlation_zone_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &(pNfapiMsg->prach_config.high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->prach_config.frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &(pNfapiMsg->pusch_config.hopping_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &(pNfapiMsg->pusch_config.hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &(pNfapiMsg->pusch_config.number_of_subbands), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &(pNfapiMsg->pucch_config.delta_pucch_shift), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &(pNfapiMsg->pucch_config.n_cqi_rb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &(pNfapiMsg->pucch_config.n_an_cs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &(pNfapiMsg->pucch_config.n1_pucch_an), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.bandwidth_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &(pNfapiMsg->srs_config.max_up_pts), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &(pNfapiMsg->srs_config.srs_subframe_configuration), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &(pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &(pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &(pNfapiMsg->uplink_reference_signal_config.group_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &(pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_pdsch), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &(pNfapiMsg->laa_config.ed_threshold_lbt_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &(pNfapiMsg->laa_config.pd_threshold), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &(pNfapiMsg->laa_config.multi_carrier_type), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &(pNfapiMsg->laa_config.multi_carrier_tx), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &(pNfapiMsg->laa_config.multi_carrier_freeze), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_antenna_ports_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &(pNfapiMsg->laa_config.tx_power_drs), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &(pNfapiMsg->emtc_config.pbch_repetitions_enable_r13), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_catm_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &(pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &(pNfapiMsg->emtc_config.prach_catm_high_speed_flag), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity), ppWritePackedMsg, end, + &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &(pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &(pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &(pNfapiMsg->tdd_frame_structure_config.subframe_assignment), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &(pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &(pNfapiMsg->l23_config.data_report_mode), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_L23_CONFIG_SFNSF_TAG, &(pNfapiMsg->l23_config.sfnsf), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_PHY_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && + pack_tlv(NFAPI_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_EARFCN_TAG, &(pNfapiMsg->nfapi_config.earfcn), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_umts_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &(pNfapiMsg->nfapi_config.nmm_lte_frequency_bands), ppWritePackedMsg, end, &pack_nmm_frequency_bands_value) && + pack_tlv(NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &(pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + +static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + + nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; + + for(int i = 0; i<40; i++){ //packing tdd slot config + for(int symbol = 0; symbol<14;symbol++){ + push8(pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[symbol].slot_config.value, ppWritePackedMsg,end); + } + } + + return (push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + + pack_tlv(NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg; + return ( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t *)msg; + return ( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_nr_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t *)msg; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t *)msg; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_nr_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + +static uint8_t pack_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t *)msg; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + +static uint8_t pack_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t *)msg; + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_measurement_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t *)msg; + return( pack_tlv(NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &(pNfapiMsg->dl_rs_tx_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &(pNfapiMsg->received_interference_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &(pNfapiMsg->thermal_noise_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_recevied_interference_power_measurement_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_received_interference_power_measurement_t *value = (nfapi_received_interference_power_measurement_t *)tlv; + return ( push16(value->number_of_resource_blocks, ppWritePackedMsg, end) && + pusharrays16(value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, ppWritePackedMsg, end)); +} + +static uint8_t pack_measurement_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t *)msg; + return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &(pNfapiMsg->dl_rs_tx_power_measurement), ppWritePackedMsg, end, &pack_int16_tlv_value) && + pack_tlv(NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &(pNfapiMsg->received_interference_power_measurement), ppWritePackedMsg, end, + &pack_recevied_interference_power_measurement_value) && + pack_tlv(NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &(pNfapiMsg->thermal_noise_power_measurement), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + uint8_t result = 0; + + // look for the specific message + switch (header->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + result = pack_nr_pnf_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_PARAM_RESPONSE: + result = pack_nr_pnf_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + result = pack_nr_pnf_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + result = pack_nr_pnf_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + result = pack_nr_pnf_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + result = pack_nr_pnf_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + result = pack_nr_pnf_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_STOP_RESPONSE: + result = pack_nr_pnf_stop_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + result = pack_nr_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + result = pack_nr_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + result = pack_nr_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + result = pack_nr_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + result = pack_nr_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + result = pack_nr_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + result = pack_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + result = pack_stop_response(header, ppWritePackedMsg, end, config); + break; + + default: { + if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->pack_p4_p5_vendor_extension) { + result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); + } + } + break; + } + + return result; +} + + +static uint8_t pack_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { + uint8_t result = 0; + + // look for the specific message + switch (header->message_id) { + case NFAPI_PNF_PARAM_REQUEST: + result = pack_pnf_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_PARAM_RESPONSE: + result = pack_pnf_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_CONFIG_REQUEST: + result = pack_pnf_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_CONFIG_RESPONSE: + result = pack_pnf_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_START_REQUEST: + result = pack_pnf_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_START_RESPONSE: + result = pack_pnf_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_STOP_REQUEST: + result = pack_pnf_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_STOP_RESPONSE: + result = pack_pnf_stop_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PARAM_REQUEST: + result = pack_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PARAM_RESPONSE: + result = pack_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_CONFIG_REQUEST: + result = pack_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_CONFIG_RESPONSE: + result = pack_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_START_REQUEST: + result = pack_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_START_RESPONSE: + result = pack_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_STOP_REQUEST: + result = pack_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_STOP_RESPONSE: + result = pack_stop_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_MEASUREMENT_REQUEST: + result = pack_measurement_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_MEASUREMENT_RESPONSE: + result = pack_measurement_response(header, ppWritePackedMsg, end, config); + break; + + default: { + if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->pack_p4_p5_vendor_extension) { + result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); + } + } + break; + } + + return result; +} + + +// helper function for message length calculation - +// takes the pointers to the start of message to end of message + +static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) { + if (msgEnd < msgHead) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "get_packed_msg_len: Error in pointers supplied %d, %d\n", msgHead, msgEnd); + return 0; + } + + return (msgEnd - msgHead); +} + +// Main pack function - public +int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint32_t packedMsgLen; + uint16_t packedMsgLen16; + + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); + return -1; + } + + // pack the message + if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) && + push16(0, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && + pack_nr_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config)) { + // check for a valid message length + packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); + + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) + return -1; + + // return the packed length + return (packedMsgLen); + } else { + // Failed to pack the meassage + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n"); + return -1; + } +} + +int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint32_t packedMsgLen; + uint16_t packedMsgLen16; + + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); + return -1; + } + + // pack the message + if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && + pack_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config)) { + // check for a valid message length + packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); + + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) + return -1; + + // return the packed length + return (packedMsgLen); + } else { + // Failed to pack the meassage + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n"); + return -1; + } +} + + + +// Unpack routines + + +static uint8_t unpack_nr_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_param_request_t *pNfapiMsg = (nfapi_nr_pnf_param_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_param_request_t *pNfapiMsg = (nfapi_pnf_param_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_pnf_param_general_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_param_general_t *value = (nfapi_pnf_param_general_t *)tlv; + return( pull8(ppReadPackedMsg, &value->nfapi_sync_mode, end) && + pull8(ppReadPackedMsg, &value->location_mode, end) && + pull16(ppReadPackedMsg, &value->location_coordinates_length, end) && + pullarray8(ppReadPackedMsg, value->location_coordinates, NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH, value->location_coordinates_length, end) && + pull32(ppReadPackedMsg, &value->dl_config_timing, end) && + pull32(ppReadPackedMsg, &value->tx_timing, end) && + pull32(ppReadPackedMsg, &value->ul_config_timing, end) && + pull32(ppReadPackedMsg, &value->hi_dci0_timing, end) && + pull16(ppReadPackedMsg, &value->maximum_number_phys, end) && + pull16(ppReadPackedMsg, &value->maximum_total_bandwidth, end) && + pull8(ppReadPackedMsg, &value->maximum_total_number_dl_layers, end) && + pull8(ppReadPackedMsg, &value->maximum_total_number_ul_layers, end) && + pull8(ppReadPackedMsg, &value->shared_bands, end) && + pull8(ppReadPackedMsg, &value->shared_pa, end) && + pulls16(ppReadPackedMsg, &value->maximum_total_power, end) && + pullarray8(ppReadPackedMsg, value->oui, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH, end)); +} + +static uint8_t unpack_rf_config_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rf_config_info_t *info = (nfapi_rf_config_info_t *)elem; + return pull16(ppReadPackedMsg, &info->rf_config_index, end); +} + +static uint8_t unpack_pnf_phy_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_info_t *phy = (nfapi_pnf_phy_info_t *)elem; + return ( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->number_of_rfs, end) && + unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) && + pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) && + unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) && + pull16(ppReadPackedMsg, &phy->downlink_channel_bandwidth_supported, end) && + pull16(ppReadPackedMsg, &phy->uplink_channel_bandwidth_supported, end) && + pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) && + pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) && + pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) && + pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end)); +} + + +static uint8_t unpack_pnf_phy_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_t *value = (nfapi_pnf_phy_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_info)); +} + +static uint8_t unpack_pnf_rf_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_rf_info_t *rf = (nfapi_pnf_rf_info_t *)elem; + return( pull16(ppReadPackedMsg, &rf->rf_config_index, end) && + pull16(ppReadPackedMsg, &rf->band, end) && + pulls16(ppReadPackedMsg, &rf->maximum_transmit_power, end) && + pulls16(ppReadPackedMsg, &rf->minimum_transmit_power, end) && + pull8(ppReadPackedMsg, &rf->number_of_antennas_suppported, end) && + pull32(ppReadPackedMsg, &rf->minimum_downlink_frequency, end) && + pull32(ppReadPackedMsg, &rf->maximum_downlink_frequency, end) && + pull32(ppReadPackedMsg, &rf->minimum_uplink_frequency, end) && + pull32(ppReadPackedMsg, &rf->maximum_uplink_frequency, end)); +} +static uint8_t unpack_pnf_rf_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_rf_t *value = (nfapi_pnf_rf_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_rfs, end) && + unpackarray(ppReadPackedMsg, value->rf, sizeof(nfapi_pnf_rf_info_t), NFAPI_MAX_PNF_RF, value->number_of_rfs, end, &unpack_pnf_rf_info)); +} + +static uint8_t unpack_pnf_phy_rel10_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel10_info_t *phy = (nfapi_pnf_phy_rel10_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_7_supported, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_8_supported, end) && + pull16(ppReadPackedMsg, &phy->two_antenna_ports_for_pucch, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_9_supported, end) && + pull16(ppReadPackedMsg, &phy->simultaneous_pucch_pusch, end) && + pull16(ppReadPackedMsg, &phy->four_layer_tx_with_tm3_and_tm4, end)); +} +static uint8_t unpack_pnf_phy_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel10_t *value = (nfapi_pnf_phy_rel10_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel10_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel10_info)); +} + + +static uint8_t unpack_pnf_phy_rel11_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel11_info_t *phy = (nfapi_pnf_phy_rel11_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->edpcch_supported, end) && + pull16(ppReadPackedMsg, &phy->multi_ack_csi_reporting, end ) && + pull16(ppReadPackedMsg, &phy->pucch_tx_diversity, end) && + pull16(ppReadPackedMsg, &phy->ul_comp_supported, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_5_supported, end)); +} + +static uint8_t unpack_pnf_phy_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel11_t *value = (nfapi_pnf_phy_rel11_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel11_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel11_info)); +} + +static uint8_t unpack_phy_phy_rel12_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel12_info_t *phy = (nfapi_pnf_phy_rel12_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->csi_subframe_set, end) && + pull16(ppReadPackedMsg, &phy->enhanced_4tx_codebook, end) && + pull16(ppReadPackedMsg, &phy->drs_supported, end) && + pull16(ppReadPackedMsg, &phy->ul_64qam_supported, end) && + pull16(ppReadPackedMsg, &phy->transmission_mode_10_supported, end) && + pull16(ppReadPackedMsg, &phy->alternative_bts_indices, end)); +} + +static uint8_t unpack_pnf_phy_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel12_t *value = (nfapi_pnf_phy_rel12_t *)tlv; + return (pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel12_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_phy_phy_rel12_info)); +} + +static uint8_t unpack_pnf_phy_rel13_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_info_t *phy = (nfapi_pnf_phy_rel13_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->pucch_format4_supported, end) && + pull16(ppReadPackedMsg, &phy->pucch_format5_supported, end) && + pull16(ppReadPackedMsg, &phy->more_than_5_ca_support, end) && + pull16(ppReadPackedMsg, &phy->laa_supported, end) && + pull16(ppReadPackedMsg, &phy->laa_ending_in_dwpts_supported, end) && + pull16(ppReadPackedMsg, &phy->laa_starting_in_second_slot_supported, end) && + pull16(ppReadPackedMsg, &phy->beamforming_supported, end) && + pull16(ppReadPackedMsg, &phy->csi_rs_enhancement_supported, end) && + pull16(ppReadPackedMsg, &phy->drms_enhancement_supported, end) && + pull16(ppReadPackedMsg, &phy->srs_enhancement_supported, end)); +} + +static uint8_t unpack_pnf_phy_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_t *value = (nfapi_pnf_phy_rel13_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_info)); +} + +static uint8_t unpack_pnf_phy_rel13_nb_info_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_nb_iot_info_t *phy = (nfapi_pnf_phy_rel13_nb_iot_info_t *)elem; + return( pull16(ppReadPackedMsg, &phy->phy_config_index, end) && + pull16(ppReadPackedMsg, &phy->number_of_rfs, end) && + unpackarray(ppReadPackedMsg, phy->rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rfs, end, &unpack_rf_config_info) && + pull16(ppReadPackedMsg, &phy->number_of_rf_exclusions, end) && + unpackarray(ppReadPackedMsg, phy->excluded_rf_config, sizeof(nfapi_rf_config_info_t), NFAPI_MAX_PNF_PHY_RF_CONFIG, phy->number_of_rf_exclusions, end, &unpack_rf_config_info) && + pull8(ppReadPackedMsg, &phy->number_of_dl_layers_supported, end) && + pull8(ppReadPackedMsg, &phy->number_of_ul_layers_supported, end) && + pull16(ppReadPackedMsg, &phy->maximum_3gpp_release_supported, end) && + pull8(ppReadPackedMsg, &phy->nmm_modes_supported, end)); +} + +static uint8_t unpack_pnf_phy_rel13_nb_iot_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rel13_nb_iot_t *value = (nfapi_pnf_phy_rel13_nb_iot_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_phys, end) && + unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_nb_info_info)); +} + +static uint8_t unpack_nr_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value}, + { NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value}, + }; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + + +static uint8_t unpack_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_param_response_t *pNfapiMsg = (nfapi_pnf_param_response_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value}, + { NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value}, + { NFAPI_PNF_RF_TAG, &pNfapiMsg->pnf_rf, &unpack_pnf_rf_value}, + { NFAPI_PNF_PHY_REL10_TAG, &pNfapiMsg->pnf_phy_rel10, &unpack_pnf_phy_rel10_value}, + { NFAPI_PNF_PHY_REL11_TAG, &pNfapiMsg->pnf_phy_rel11, &unpack_pnf_phy_rel11_value}, + { NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, &unpack_pnf_phy_rel12_value}, + { NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, &unpack_pnf_phy_rel13_value}, + { NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, &unpack_pnf_phy_rel13_nb_iot_value}, + + }; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_phy_rf_config_info(void *elem, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_phy_rf_config_info_t *rf = (nfapi_phy_rf_config_info_t *)elem; + return( pull16(ppReadPackedMsg, &rf->phy_id, end) && + pull16(ppReadPackedMsg, &rf->phy_config_index, end) && + pull16(ppReadPackedMsg, &rf->rf_config_index, end)); +} + +static uint8_t unpack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_pnf_phy_rf_config_t *value = (nfapi_pnf_phy_rf_config_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_phy_rf_config_info, end) && + unpackarray(ppReadPackedMsg, value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, end, &unpack_phy_rf_config_info)); +} + +static uint8_t unpack_nr_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value}, + }; + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); +} + + + +static uint8_t unpack_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value}, + }; + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); +} + + +static uint8_t unpack_nr_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_config_response_t *pNfapiMsg = (nfapi_nr_pnf_config_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_start_request_t *pNfapiMsg = (nfapi_nr_pnf_start_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_pnf_start_response_t *pNfapiMsg = (nfapi_nr_pnf_start_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + + +static uint8_t unpack_pnf_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_pnf_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_L1_STATUS_PHY_STATE_TAG, &pNfapiMsg->l1_status.phy_state, &unpack_uint16_tlv_value}, + + { NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_bandwidth_support, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_bandwidth_support, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.dl_modulation_support, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG, &pNfapiMsg->phy_capabilities.ul_modulation_support, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.phy_antenna_capability, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.release_capability, &unpack_uint16_tlv_value}, + { NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG, &pNfapiMsg->phy_capabilities.mbsfn_capability, &unpack_uint16_tlv_value}, + + { NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG, &pNfapiMsg->laa_capability.laa_support, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.pd_sensing_lbt_support, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG, &pNfapiMsg->laa_capability.multi_carrier_lbt_support, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG, &pNfapiMsg->laa_capability.partial_sf_support, &unpack_uint16_tlv_value}, + + { NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value}, + + { NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value}, + + { NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value}, + { NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value}, + { NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value}, + + { NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, + { NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, + { NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value}, + + { NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value}, + + { NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value}, + { NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value}, + + { NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value}, + + { NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value}, + + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value}, + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value}, + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value}, + + { NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value}, + { NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value}, + + { NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value}, + { NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value}, + + { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value}, + { NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value}, + + }; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state),&unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param.num_config_tlvs_to_report ), &unpack_uint16_tlv_value}, + + { NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), &unpack_uint16_tlv_value}, + + + { NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG, &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG, &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG, &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, &(pNfapiMsg->pusch_param.supported_modulation_order_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, &(pNfapiMsg->pusch_param.pusch_aggregation_factor), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG, &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, &(pNfapiMsg->measurement_param.rssi_measurement_support), &unpack_uint8_tlv_value}, + //config + { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, + }; + // print ppReadPackedMsg + uint8_t *ptr = *ppReadPackedMsg; + printf("\n Read message unpack_param_response: "); + + while(ptr < end) { + printf(" %d ", *ptr); + ptr++; + } + + printf("\n"); + return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG, &pNfapiMsg->subframe_config.duplex_mode, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG, &pNfapiMsg->subframe_config.pcfich_power_offset, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_PB_TAG, &pNfapiMsg->subframe_config.pb, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.dl_cyclic_prefix_type, &unpack_uint16_tlv_value}, + { NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG, &pNfapiMsg->subframe_config.ul_cyclic_prefix_type, &unpack_uint16_tlv_value}, + + { NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.dl_channel_bandwidth, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG, &pNfapiMsg->rf_config.ul_channel_bandwidth, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG, &pNfapiMsg->rf_config.reference_signal_power, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.tx_antenna_ports, &unpack_uint16_tlv_value}, + { NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG, &pNfapiMsg->rf_config.rx_antenna_ports, &unpack_uint16_tlv_value}, + + { NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG, &pNfapiMsg->phich_config.phich_resource, &unpack_uint16_tlv_value}, + { NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG, &pNfapiMsg->phich_config.phich_duration, &unpack_uint16_tlv_value}, + { NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG, &pNfapiMsg->phich_config.phich_power_offset, &unpack_uint16_tlv_value}, + + { NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.primary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, + { NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG, &pNfapiMsg->sch_config.secondary_synchronization_signal_epre_eprers, &unpack_uint16_tlv_value}, + { NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG, &pNfapiMsg->sch_config.physical_cell_id, &unpack_uint16_tlv_value}, + + { NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG, &pNfapiMsg->prach_config.configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->prach_config.root_sequence_index, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->prach_config.zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG, &pNfapiMsg->prach_config.high_speed_flag, &unpack_uint16_tlv_value}, + { NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG, &pNfapiMsg->prach_config.frequency_offset, &unpack_uint16_tlv_value}, + + { NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG, &pNfapiMsg->pusch_config.hopping_mode, &unpack_uint16_tlv_value}, + { NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG, &pNfapiMsg->pusch_config.hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG, &pNfapiMsg->pusch_config.number_of_subbands, &unpack_uint16_tlv_value}, + + { NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG, &pNfapiMsg->pucch_config.delta_pucch_shift, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG, &pNfapiMsg->pucch_config.n_cqi_rb, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N_AN_CS_TAG, &pNfapiMsg->pucch_config.n_an_cs, &unpack_uint16_tlv_value}, + { NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG, &pNfapiMsg->pucch_config.n1_pucch_an, &unpack_uint16_tlv_value}, + + { NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG, &pNfapiMsg->srs_config.bandwidth_configuration, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG, &pNfapiMsg->srs_config.max_up_pts, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG, &pNfapiMsg->srs_config.srs_subframe_configuration, &unpack_uint16_tlv_value}, + { NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG, &pNfapiMsg->srs_config.srs_acknack_srs_simultaneous_transmission, &unpack_uint16_tlv_value}, + + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG, &pNfapiMsg->uplink_reference_signal_config.uplink_rs_hopping, &unpack_uint16_tlv_value}, + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG, &pNfapiMsg->uplink_reference_signal_config.group_assignment, &unpack_uint16_tlv_value}, + { NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG, &pNfapiMsg->uplink_reference_signal_config.cyclic_shift_1_for_drms, &unpack_uint16_tlv_value}, + + + { NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_pdsch, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG, &pNfapiMsg->laa_config.ed_threshold_lbt_drs, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG, &pNfapiMsg->laa_config.pd_threshold, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG, &pNfapiMsg->laa_config.multi_carrier_type, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG, &pNfapiMsg->laa_config.multi_carrier_tx, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG, &pNfapiMsg->laa_config.multi_carrier_freeze, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_antenna_ports_drs, &unpack_uint16_tlv_value}, + { NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG, &pNfapiMsg->laa_config.tx_power_drs, &unpack_uint16_tlv_value}, + + { NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG, &pNfapiMsg->emtc_config.pbch_repetitions_enable_r13, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG, &pNfapiMsg->emtc_config.prach_catm_root_sequence_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG, &pNfapiMsg->emtc_config.prach_catm_zero_correlation_zone_configuration, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG, &pNfapiMsg->emtc_config.prach_catm_high_speed_flag, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_frequency_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_starting_subframe_periodicity, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_0_hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_frequency_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_starting_subframe_periodicity, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_1_hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_frequency_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_starting_subframe_periodicity, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_2_hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_configuration_index, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_frequency_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_starting_subframe_periodicity, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_enable, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG, &pNfapiMsg->emtc_config.prach_ce_level_3_hopping_offset, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodea, &unpack_uint16_tlv_value}, + { NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG, &pNfapiMsg->emtc_config.pucch_interval_ulhoppingconfigcommonmodeb, &unpack_uint16_tlv_value}, + + { NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG, &pNfapiMsg->tdd_frame_structure_config.subframe_assignment, &unpack_uint16_tlv_value}, + { NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG, &pNfapiMsg->tdd_frame_structure_config.special_subframe_patterns, &unpack_uint16_tlv_value}, + + { NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG, &pNfapiMsg->l23_config.data_report_mode, &unpack_uint16_tlv_value}, + { NFAPI_L23_CONFIG_SFNSF_TAG, &pNfapiMsg->l23_config.sfnsf, &unpack_uint16_tlv_value}, + + { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.dl_ue_per_sf, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &pNfapiMsg->nfapi_config.ul_ue_per_sf, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_RF_BANDS_TAG, &pNfapiMsg->nfapi_config.rf_bands, &unpack_rf_bands_value}, + { NFAPI_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, + { NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &pNfapiMsg->nfapi_config.max_transmit_power, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_EARFCN_TAG, &pNfapiMsg->nfapi_config.earfcn, &unpack_uint16_tlv_value}, + { NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_gsm_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_umts_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG, &pNfapiMsg->nfapi_config.nmm_lte_frequency_bands, &unpack_nmm_frequency_bands_value}, + { NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG, &pNfapiMsg->nfapi_config.nmm_uplink_rssi_supported, &unpack_uint8_tlv_value}, + + }; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; + + pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t*) malloc(40*sizeof(nfapi_nr_max_tdd_periodicity_t)); + + for(int i=0;i<40;i++) + pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t*) malloc(14*sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); + + pNfapiMsg->prach_config.num_prach_fd_occasions_list=(nfapi_nr_num_prach_fd_occasions_t *) malloc(sizeof(nfapi_nr_num_prach_fd_occasions_t)); + + for(int i = 0; i < 40; i++){ //unpacking tdd slot config + for(int symbol = 0; symbol<14;symbol++){ + pull8(ppReadPackedMsg,&pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[symbol].slot_config.value, end); + } + } + unpack_tlv_t unpack_fns[] = + { + { NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), &unpack_uint8_tlv_value}, + + { NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask), &unpack_uint32_tlv_value}, + + { NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), &unpack_ipv6_address_value}, + { NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), &unpack_uint16_tlv_value}, + { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value}, + { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value}, + { NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), &unpack_uint16_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), &unpack_uint8_tlv_value}, + }; + + return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + +} + +static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t *)msg; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_start_request_scf_t *pNfapiMsg = ( nfapi_nr_start_request_scf_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_start_request_t *pNfapiMsg = ( nfapi_start_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t *)msg; + return unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_stop_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_stop_response_t *pNfapiMsg = (nfapi_stop_response_t *)msg; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} +static uint8_t unpack_measurement_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_measurement_request_t *pNfapiMsg = (nfapi_measurement_request_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG, &pNfapiMsg->dl_rs_tx_power, &unpack_uint16_tlv_value}, + { NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG, &pNfapiMsg->received_interference_power, &unpack_uint16_tlv_value}, + { NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG, &pNfapiMsg->thermal_noise_power, &unpack_uint16_tlv_value}, + }; + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_received_interference_power_measurement_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_received_interference_power_measurement_t *value = (nfapi_received_interference_power_measurement_t *)tlv; + return ( pull16(ppReadPackedMsg, &value->number_of_resource_blocks, end) && + pullarrays16(ppReadPackedMsg, value->received_interference_power, NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS, value->number_of_resource_blocks, end)); +} + + +static uint8_t unpack_measurement_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { + nfapi_measurement_response_t *pNfapiMsg = (nfapi_measurement_response_t *)msg; + unpack_tlv_t unpack_fns[] = { + { NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG, &pNfapiMsg->dl_rs_tx_power_measurement, &unpack_int16_tlv_value}, + { NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG, &pNfapiMsg->received_interference_power_measurement, &unpack_received_interference_power_measurement_value}, + { NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG, &pNfapiMsg->thermal_noise_power_measurement, &unpack_int16_tlv_value}, + }; + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +// unpack length check + +static int check_nr_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; + + switch (msgId) { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t)) + retLen = sizeof(nfapi_pnf_param_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_param_response_t)) + retLen = sizeof(nfapi_nr_pnf_param_response_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_config_request_t)) + retLen = sizeof(nfapi_nr_pnf_config_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_config_response_t)) + retLen = sizeof(nfapi_nr_pnf_config_response_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_start_request_t)) + retLen = sizeof(nfapi_nr_pnf_start_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_start_response_t)) + retLen = sizeof(nfapi_nr_pnf_start_response_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_stop_request_t)) + retLen = sizeof(nfapi_nr_pnf_stop_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_stop_response_t)) + retLen = sizeof(nfapi_nr_pnf_stop_response_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_param_request_scf_t)) + retLen = sizeof(nfapi_nr_param_request_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_param_response_scf_t)) + retLen = sizeof(nfapi_nr_param_response_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_config_request_scf_t)) + retLen = sizeof(nfapi_nr_config_request_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_config_response_scf_t)) + retLen = sizeof(nfapi_nr_config_response_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + if (unpackedBufLen >= sizeof( nfapi_nr_start_request_scf_t)) + retLen = sizeof( nfapi_nr_start_request_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_start_response_scf_t)) + retLen = sizeof(nfapi_nr_start_response_scf_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_stop_request_t)) + retLen = sizeof(nfapi_stop_request_t); + + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_stop_response_t)) + retLen = sizeof(nfapi_stop_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); + break; + } + + return retLen; +} + + +static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; + + switch (msgId) { + case NFAPI_PNF_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t)) + retLen = sizeof(nfapi_pnf_param_request_t); + + break; + + case NFAPI_PNF_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_pnf_param_response_t)) + retLen = sizeof(nfapi_pnf_param_response_t); + + break; + + case NFAPI_PNF_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_config_request_t)) + retLen = sizeof(nfapi_pnf_config_request_t); + + break; + + case NFAPI_PNF_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_pnf_config_response_t)) + retLen = sizeof(nfapi_pnf_config_response_t); + + break; + + case NFAPI_PNF_START_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_start_request_t)) + retLen = sizeof(nfapi_pnf_start_request_t); + + break; + + case NFAPI_PNF_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_pnf_start_response_t)) + retLen = sizeof(nfapi_pnf_start_response_t); + + break; + + case NFAPI_PNF_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_stop_request_t)) + retLen = sizeof(nfapi_pnf_stop_request_t); + + break; + + case NFAPI_PNF_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_pnf_stop_response_t)) + retLen = sizeof(nfapi_pnf_stop_response_t); + + break; + + case NFAPI_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_param_request_t)) + retLen = sizeof(nfapi_param_request_t); + + break; + + case NFAPI_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_param_response_t)) + retLen = sizeof(nfapi_param_response_t); + + break; + + case NFAPI_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_config_request_t)) + retLen = sizeof(nfapi_config_request_t); + + break; + + case NFAPI_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_config_response_t)) + retLen = sizeof(nfapi_config_response_t); + + break; + + case NFAPI_START_REQUEST: + if (unpackedBufLen >= sizeof( nfapi_start_request_t)) + retLen = sizeof( nfapi_start_request_t); + + break; + + case NFAPI_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_start_response_t)) + retLen = sizeof(nfapi_start_response_t); + + break; + + case NFAPI_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_stop_request_t)) + retLen = sizeof(nfapi_stop_request_t); + + break; + + case NFAPI_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_stop_response_t)) + retLen = sizeof(nfapi_stop_response_t); + + break; + + case NFAPI_MEASUREMENT_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_measurement_request_t)) + retLen = sizeof(nfapi_measurement_request_t); + + break; + + case NFAPI_MEASUREMENT_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_measurement_response_t)) + retLen = sizeof(nfapi_measurement_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); + break; + } + + return retLen; +} + + +// Main unpack functions - public + +int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + // process the header + return ( pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end) ); +} + +int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + uint8_t *ptr = pReadPackedMessage; + printf("\n Read message unpack: "); + + while(ptr < end) { + printf(" %d ", *ptr); + ptr++; + } + + printf("\n"); + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) { + // failed to read the header + return -1; + } + + int result = -1; + + if(check_nr_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { + // the unpack buffer is not big enough for the struct + return -1; + } + + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + result = unpack_nr_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: + result = unpack_nr_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + result = unpack_nr_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + result = unpack_nr_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + result = unpack_nr_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + result = unpack_nr_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE: + result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + result = unpack_nr_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + result = unpack_nr_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + result = unpack_nr_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + result = unpack_nr_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + result = unpack_nr_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + result = unpack_nr_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_REQUEST: + result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_RESPONSE: + result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p4_p5_vendor_extension) { + result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + return result; +} + +int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t *config) { + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + uint8_t *ptr = pReadPackedMessage; + printf("\n Read message unpack: "); + + while(ptr < end) { + printf(" %d ", *ptr); + ptr++; + } + + printf("\n"); + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) { + // failed to read the header + return -1; + } + + int result = -1; + + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) { + // the unpack buffer is not big enough for the struct + return -1; + } + + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_PNF_PARAM_REQUEST: + result = unpack_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_PARAM_RESPONSE: + result = unpack_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_CONFIG_REQUEST: + result = unpack_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_CONFIG_RESPONSE: + result = unpack_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_START_REQUEST: + result = unpack_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_START_RESPONSE: + result = unpack_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_STOP_REQUEST: + result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PNF_STOP_RESPONSE: + result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PARAM_REQUEST: + result = unpack_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_PARAM_RESPONSE: + result = unpack_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_CONFIG_REQUEST: + result = unpack_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_CONFIG_RESPONSE: + result = unpack_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_START_REQUEST: + result = unpack_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_START_RESPONSE: + result = unpack_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_STOP_REQUEST: + result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_STOP_RESPONSE: + result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_REQUEST: + result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_RESPONSE: + result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p4_p5_vendor_extension) { + result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + return result; +} diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c old mode 100755 new mode 100644 index be9205d035..7cb74f8562 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -1,2712 +1,3354 @@ -/* - * Copyright 2017 Cisco Systems, Inc. - * - * 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. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, void* user_data); -extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedMsg, void* user_data); - -uint32_t nfapi_calculate_checksum(uint8_t* buffer, uint16_t len) -{ - uint32_t chksum = 0; - // calcaulte upto the checksum - chksum = crc32(chksum, buffer, 8); - - // skip the checksum - uint8_t zeros[4] = {0, 0, 0, 0}; - chksum = crc32(chksum, zeros, 4); - - // continu with the rest of the mesage - chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH); - - // return the inverse - return ~(chksum); -} - -int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len) -{ - uint32_t checksum = nfapi_calculate_checksum(buffer, len); - - uint8_t* p_write = &buffer[8]; - return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); -} - -int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp) -{ - uint8_t* p_write = &buffer[12]; - return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); -} - -uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len) -{ - return nfapi_calculate_checksum(buffer, len); -} - -void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config) -{ - if(size == 0) - return 0; - - void* buffer_p = NULL; - if(config && config->allocate) - { - buffer_p = (config->allocate)(size); - if(buffer_p != NULL){ - memset(buffer_p,0,size); - } - return buffer_p; - } - else - { - buffer_p = calloc(1, size); - return buffer_p; - } -} - -void nfapi_p7_deallocate(void* ptr, nfapi_p7_codec_config_t* config) -{ - if(ptr == NULL) - return; - - if(config && config->deallocate) - { - return (config->deallocate)(ptr); - } - else - { - return free(ptr); - } -} -// Pack routines - - -static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel8_t* value = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format); - - return ( push8(value->dci_format, ppWritePackedMsg, end) && - push8(value->cce_idx, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs_1, ppWritePackedMsg, end) && - push8(value->redundancy_version_1, ppWritePackedMsg, end) && - push8(value->new_data_indicator_1, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->mcs_2, ppWritePackedMsg, end) && - push8(value->redundancy_version_2, ppWritePackedMsg, end) && - push8(value->new_data_indicator_2, ppWritePackedMsg, end) && - push8(value->harq_process, ppWritePackedMsg, end) && - push8(value->tpmi, ppWritePackedMsg, end) && - push8(value->pmi, ppWritePackedMsg, end) && - push8(value->precoding_information, ppWritePackedMsg, end) && - push8(value->tpc, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end) && - push8(value->transport_block_size_index, ppWritePackedMsg, end) && - push8(value->downlink_power_offset, ppWritePackedMsg, end) && - push8(value->allocate_prach_flag, ppWritePackedMsg, end) && - push8(value->preamble_index, ppWritePackedMsg, end) && - push8(value->prach_mask_index, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel9_t* value = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; - - return( push8(value->mcch_flag, ppWritePackedMsg, end) && - push8(value->mcch_change_notification, ppWritePackedMsg, end) && - push8(value->scrambling_identity, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel10_t* value = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; - - return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && - push8(value->carrier_indicator, ppWritePackedMsg, end) && - push8(value->srs_flag, ppWritePackedMsg, end) && - push8(value->srs_request, ppWritePackedMsg, end) && - push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(value->n_dl_rb, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel11_t* value = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; - - return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel12_t* value = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; - - return ( push8(value->primary_cell_type, ppWritePackedMsg, end) && - push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) && - push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) && - pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end)); -} - -static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->num_antennas, ppWritePackedMsg, end))) - return 0; - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); - - if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) && - push8(subband_info->scheduled_ues, ppWritePackedMsg, end))) - return 0; - - - uint8_t antenna_idx = 0; - uint8_t scheduled_ue_idx = 0; - - for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) - { - for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) - { - if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end)) - return 0; - } - } - - } - - - return 1; - -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel13_t* value = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; - - return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && - push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end) && - push8(value->codebook_size_determination, ppWritePackedMsg, end) && - push8(value->drms_table_flag, ppWritePackedMsg, end) && - push8(value->tpm_struct_flag, ppWritePackedMsg, end) && - (value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1)); -} - -static uint8_t pack_dl_config_bch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_bch_pdu_rel8_t* value = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__); - - return( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_mch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_mch_pdu_rel8_t* value = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->mbsfn_area_id, ppWritePackedMsg, end)); -} - -static uint8_t pack_bf_vector_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_bf_vector_t* bf = (nfapi_bf_vector_t*)elem; - - return ( push8(bf->subband_index, ppWritePackedMsg, end) && - push8(bf->num_antennas, ppWritePackedMsg, end) && - pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end)); - - -} -static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel8_t* value = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->transport_blocks, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->transmission_scheme, ppWritePackedMsg, end) && - push8(value->number_of_layers, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->ue_category_capacity, ppWritePackedMsg, end) && - push8(value->pa, ppWritePackedMsg, end) && - push8(value->delta_power_offset_index, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end) && - push8(value->nprb, ppWritePackedMsg, end) && - push8(value->transmission_mode, ppWritePackedMsg, end) && - push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) && - push8(value->num_bf_vector, ppWritePackedMsg, end) && - packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info)); - -} -static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel9_t* value = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; - return ( push8(value->nscid, ppWritePackedMsg, end) ); -} -static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel10_t* value = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; - - return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) && - push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && - push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && - pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && - push8(value->pdsch_start, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel11_t* value = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; - - return( push8(value->drms_config_flag, ppWritePackedMsg, end) && - push16(value->drms_scrambling, ppWritePackedMsg, end) && - push8(value->csi_config_flag, ppWritePackedMsg, end) && - push16(value->csi_scrambling, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel12_t* value = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; - - return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) && - push8(value->maxlayers, ppWritePackedMsg, end) && - push8(value->n_dl_harq, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel13_t* value = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; - - return( push8(value->dwpts_symbols, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end) && - push8(value->ue_type, ppWritePackedMsg, end) && - push8(value->pdsch_payload_type, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && - push8(value->drms_table_flag, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_pch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel8_t* value = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; - - return( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->p_rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->number_of_transport_blocks, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->transmission_scheme, ppWritePackedMsg, end) && - push8(value->number_of_layers, ppWritePackedMsg, end) && - push8(value->codebook_index, ppWritePackedMsg, end) && - push8(value->ue_category_capacity, ppWritePackedMsg, end) && - push8(value->pa, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->nprb, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_pch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel13_t* value = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; - - return ( push8(value->ue_mode, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_prs_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_prs_pdu_rel9_t* value = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; - - return( push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->prs_bandwidth, ppWritePackedMsg, end) && - push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) && - push8(value->prs_muting, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel10_t* value = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; - - return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) && - pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel13_t* value = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; - - if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - push8(value->num_bf_vector, ppWritePackedMsg, end))) - { - return 0; - } - - uint16_t i; - for(i = 0; i < value->num_bf_vector; ++i) - { - if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) && - pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} -static uint8_t pack_bf_vector(nfapi_bf_vector_t* vector, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(vector->subband_index, ppWritePackedMsg, end) && - push8(vector->num_antennas, ppWritePackedMsg, end) && - pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel11_t* value = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; - - return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) && - push16(value->epdcch_id, ppWritePackedMsg, end) && - push8(value->epdcch_start_symbol, ppWritePackedMsg, end) && - push8(value->epdcch_num_prb, ppWritePackedMsg, end) && - pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) && - pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel13_t* value = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; - - return (push8(value->dwpts_symbols, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_mpdcch_pdu_rel13_t* value = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; - - return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) && - push8(value->number_of_prb_pairs, ppWritePackedMsg, end) && - push8(value->resource_block_assignment, ppWritePackedMsg, end) && - push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->ecce_index, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->ce_mode, ppWritePackedMsg, end) && - push16(value->drms_scrambling_init, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->dci_format, ppWritePackedMsg, end) && - push16(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->new_data_indicator, ppWritePackedMsg, end) && - push8(value->harq_process, ppWritePackedMsg, end) && - push8(value->tpmi_length, ppWritePackedMsg, end) && - push8(value->tpmi, ppWritePackedMsg, end) && - push8(value->pmi_flag, ppWritePackedMsg, end) && - push8(value->pmi, ppWritePackedMsg, end) && - push8(value->harq_resource_offset, ppWritePackedMsg, end) && - push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push8(value->tpc, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index, ppWritePackedMsg, end) && - push8(value->allocate_prach_flag, ppWritePackedMsg, end) && - push8(value->preamble_index, ppWritePackedMsg, end) && - push8(value->prach_mask_index, ppWritePackedMsg, end) && - push8(value->starting_ce_level, ppWritePackedMsg, end) && - push8(value->srs_request, ppWritePackedMsg, end) && - push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) && - push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) && - push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) && - push8(value->direct_indication, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) && - pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end)); -} - - -static uint8_t pack_dl_config_nbch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_nbch_pdu_rel13_t* value = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end)); -} - - -static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_npdcch_pdu_rel13_t* value = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push8(value->ncce_index, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && - push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && - push8(value->dci_format, ppWritePackedMsg, end) && - push8(value->scheduling_delay, ppWritePackedMsg, end) && - push8(value->resource_assignment, ppWritePackedMsg, end) && - push8(value->repetition_number, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->new_data_indicator, ppWritePackedMsg, end) && - push8(value->harq_ack_resource, ppWritePackedMsg, end) && - push8(value->npdcch_order_indication, ppWritePackedMsg, end) && - push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) && - push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) && - push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) && - push8(value->direct_indication, ppWritePackedMsg, end) && - push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_ndlsch_pdu_rel13_t* value = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->resource_assignment, ppWritePackedMsg, end) && - push16(value->repetition_number, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) && - push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && - push16(value->sf_idx, ppWritePackedMsg, end) && - push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich); - - if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) && - push8(value->number_dci, ppWritePackedMsg, end) && - push16(value->number_pdu, ppWritePackedMsg, end) && - push8(value->number_pdsch_rnti, ppWritePackedMsg, end) && - push16(value->transmission_power_pcfich, ppWritePackedMsg, end))) - { - return 0; - } - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_pdu; - for(; i < total_number_of_pdus; ++i) - { - nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__); - - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value))) - { - return 0; - } - } - break; - case NFAPI_DL_CONFIG_BCH_PDU_TYPE: - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__); - - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_MCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_PCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_PRS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) & - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - -static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; - - //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) && - //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - { - uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value); - uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - - if (!x || !y || !z) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z); - } - - return x && y && z; - } -} - -static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t * end) -{ - nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; - - return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; - - return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && - push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; - - return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; - - return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu* ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value)); -} - -static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; - - return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; - - if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end))) - { - return 0; - } - - switch(cqi_ri_info_rel9->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end))) - { - return 0; - } - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t i; - for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t j; - for(j = 0; j < 8; ++j) - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0) - return 0; - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); - } - break; - }; - - return 1; -} - -static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; - - switch(cqi_ri_info_rel13->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0) - return 0; - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - // No parameters - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type ); - } - break; - }; - - return 1; -} - -static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information* cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value)); - -} - -static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; - - return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) && - push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters* init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, &pack_ul_config_request_init_tx_params_rel8_value); -} - -static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; - - return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) && - push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; - - return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && - push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value)); -} - -static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; - - return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) && - push16(ue_info_rel8->rnti, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; - - return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && - push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; - - return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) && - push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) && - push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && - push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information* ue_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value)); -} - -static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; - - return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) && - push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; - - return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) && - push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; - - return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) && - push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; - - return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; - - return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && - push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) && - push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) && - push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) && - push8(harq_info_rel13->n_srs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value)); - -} - -static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; - - return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) && - push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; - - return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) && - push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; - - return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) && - push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) && - push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) && - push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) && - push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) && - push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information* cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value)); - -} - -static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; - return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end); -} -static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; - - return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information* sr_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value)); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; - - return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->size, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; - return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; - - return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; - - return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; - - return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) && - push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && - pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, &pack_ul_config_request_nb_harq_rel13_value)); -} -static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; - - return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) && - push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) && - push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); - -} - -static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; - - if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) && - push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) && - push8(value->srs_present, ppWritePackedMsg, end))) - return 0; - - uint16_t i = 0; - for(i = 0; i < value->number_of_pdus; ++i) - { - nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - { - if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && - pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_SRS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - - } - return 1; -} - -static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ; -} - -static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; - - return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) && - push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; - - return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) && - push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; - - return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) && - push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) && - push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) && - push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; - - return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && - push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; - - return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) && - push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; - - return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) && - pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end)); - -} - -static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; - - return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && - push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end)); -} - - -static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; - - if(!(push16(value->sfnsf, ppWritePackedMsg, end) && - push8(value->number_of_dci, ppWritePackedMsg, end) && - push8(value->number_of_hi, ppWritePackedMsg, end))) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_HI_DCI0_HI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - - } - - return 1; -} - -static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_tx_request_body_t* value = (nfapi_tx_request_body_t*)tlv; - - if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_tx_request_pdu_t* pdu = &(value->tx_pdu_list[i]); - - if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) && - push16(pdu->pdu_index, ppWritePackedMsg, end))) - return 0; - - uint8_t j; - for(j = 0; j < pdu->num_segments; ++j) - { - // Use -1 as it is unbounded - // DJP - does not handle -1 - // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) - int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); - - if (pdu->segments[j].segment_length == 3) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, - pdu->segments[j].segment_data[0], - pdu->segments[j].segment_data[1], - pdu->segments[j].segment_data[2] - ); - } - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret); - - if (push_ret == 0) - { - return 0; - } - } - } - - return 1; -} - -static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; - - int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z); - - return x && y && z; -} +/* + * Copyright 2017 Cisco Systems, Inc. + * + * 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. + */ -static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "nfapi_nr_interface_scf.h" + +extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppReadPackedMsg, void *user_data); +extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t *header, uint8_t **ppWritePackedMsg, void *user_data); + +uint32_t nfapi_calculate_checksum(uint8_t *buffer, uint16_t len) { + uint32_t chksum = 0; + // calcaulte upto the checksum + chksum = crc32(chksum, buffer, 8); + // skip the checksum + uint8_t zeros[4] = {0, 0, 0, 0}; + chksum = crc32(chksum, zeros, 4); + // continu with the rest of the mesage + chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH); + // return the inverse + return ~(chksum); +} + +int nfapi_p7_update_checksum(uint8_t *buffer, uint32_t len) { + uint32_t checksum = nfapi_calculate_checksum(buffer, len); + uint8_t *p_write = &buffer[8]; + return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); +} + +int nfapi_p7_update_transmit_timestamp(uint8_t *buffer, uint32_t timestamp) { + uint8_t *p_write = &buffer[12]; + return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); +} + +uint32_t nfapi_p7_calculate_checksum(uint8_t *buffer, uint32_t len) { + return nfapi_calculate_checksum(buffer, len); +} + +void *nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t *config) { + if(size == 0) + return 0; + + void *buffer_p = NULL; + + if(config && config->allocate) { + buffer_p = (config->allocate)(size); + + if(buffer_p != NULL) { + memset(buffer_p,0,size); + } + + return buffer_p; + } else { + buffer_p = calloc(1, size); + return buffer_p; + } +} + +void nfapi_p7_deallocate(void *ptr, nfapi_p7_codec_config_t *config) { + if(ptr == NULL) + return; + + if(config && config->deallocate) { + return (config->deallocate)(ptr); + } else { + return free(ptr); + } +} +// Pack routines + + +static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel8_t *value = (nfapi_dl_config_dci_dl_pdu_rel8_t *)tlv; + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format); + return ( push8(value->dci_format, ppWritePackedMsg, end) && + push8(value->cce_idx, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs_1, ppWritePackedMsg, end) && + push8(value->redundancy_version_1, ppWritePackedMsg, end) && + push8(value->new_data_indicator_1, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->mcs_2, ppWritePackedMsg, end) && + push8(value->redundancy_version_2, ppWritePackedMsg, end) && + push8(value->new_data_indicator_2, ppWritePackedMsg, end) && + push8(value->harq_process, ppWritePackedMsg, end) && + push8(value->tpmi, ppWritePackedMsg, end) && + push8(value->pmi, ppWritePackedMsg, end) && + push8(value->precoding_information, ppWritePackedMsg, end) && + push8(value->tpc, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end) && + push8(value->transport_block_size_index, ppWritePackedMsg, end) && + push8(value->downlink_power_offset, ppWritePackedMsg, end) && + push8(value->allocate_prach_flag, ppWritePackedMsg, end) && + push8(value->preamble_index, ppWritePackedMsg, end) && + push8(value->prach_mask_index, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel9_t *value = (nfapi_dl_config_dci_dl_pdu_rel9_t *)tlv; + return( push8(value->mcch_flag, ppWritePackedMsg, end) && + push8(value->mcch_change_notification, ppWritePackedMsg, end) && + push8(value->scrambling_identity, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel10_t *value = (nfapi_dl_config_dci_dl_pdu_rel10_t *)tlv; + return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && + push8(value->carrier_indicator, ppWritePackedMsg, end) && + push8(value->srs_flag, ppWritePackedMsg, end) && + push8(value->srs_request, ppWritePackedMsg, end) && + push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(value->n_dl_rb, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel11_t *value = (nfapi_dl_config_dci_dl_pdu_rel11_t *)tlv; + return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel12_t *value = (nfapi_dl_config_dci_dl_pdu_rel12_t *)tlv; + return ( push8(value->primary_cell_type, ppWritePackedMsg, end) && + push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) && + push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) && + pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end)); +} + +static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t *value, uint8_t **ppWritePackedMsg, uint8_t *end) { + if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->num_antennas, ppWritePackedMsg, end))) + return 0; + + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_subbands; ++idx) { + nfapi_dl_config_dci_dl_tpm_subband_info_t *subband_info = &(value->subband_info[idx]); + + if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) && + push8(subband_info->scheduled_ues, ppWritePackedMsg, end))) + return 0; + + uint8_t antenna_idx = 0; + uint8_t scheduled_ue_idx = 0; + + for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) { + for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) { + if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end)) + return 0; + } + } + } + + return 1; +} + + +static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; + return( + push16(value->bwp_size, ppWritePackedMsg, end) && + push16(value->bwp_start, ppWritePackedMsg, end) && + push8(value->subcarrier_spacing, ppWritePackedMsg, end) && + push8(value->cyclic_prefix, ppWritePackedMsg, end) && + push16(value->start_rb, ppWritePackedMsg, end) && + push16(value->nr_of_rbs, ppWritePackedMsg, end) && + push8(value->csi_type, ppWritePackedMsg, end) && + push8(value->row, ppWritePackedMsg, end) && + push16(value->freq_domain, ppWritePackedMsg, end) && + push8(value->symb_l0, ppWritePackedMsg, end) && + push8(value->symb_l1, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + push8(value->freq_density, ppWritePackedMsg, end) && + push16(value->scramb_id, ppWritePackedMsg, end) && + push8(value->power_control_offset, ppWritePackedMsg, end) && + push8(value->power_control_offset_ss, ppWritePackedMsg, end) + ); +} + + +static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + + nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) + return 0; + + } + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->BWPSize, ppWritePackedMsg, end) && + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->CceRegMappingType, ppWritePackedMsg, end) && + push8(value->RegBundleSize, ppWritePackedMsg, end) && + push8(value->InterleaverSize, ppWritePackedMsg, end) && + push8(value->CoreSetType, ppWritePackedMsg, end) && + push16(value->ShiftIndex, ppWritePackedMsg, end) && + push8(value->precoderGranularity, ppWritePackedMsg, end) && + push16(value->numDlDci, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->pduBitmap, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->pduIndex, ppWritePackedMsg, end) && + push16(value->BWPSize, ppWritePackedMsg, end) && + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + push8(value->NrOfCodewords, ppWritePackedMsg, end) && + pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && + pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && + push16(value->dataScramblingId, ppWritePackedMsg, end) && + push8(value->nrOfLayers, ppWritePackedMsg, end) && + push8(value->transmissionScheme, ppWritePackedMsg, end) && + push8(value->refPoint, ppWritePackedMsg, end) && + push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && + push8(value->dmrsConfigType, ppWritePackedMsg, end) && + push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && + push8(value->SCID, ppWritePackedMsg, end) && + push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && + push16(value->dmrsPorts, ppWritePackedMsg, end) && + push8(value->resourceAlloc, ppWritePackedMsg, end) && + push16(value->rbStart, ppWritePackedMsg, end) && + push16(value->rbSize, ppWritePackedMsg, end) && + push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->NrOfSymbols, ppWritePackedMsg, end) && + push8(value->PTRSPortIndex, ppWritePackedMsg, end) && + push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && + push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && + push8(value->PTRSReOffset, ppWritePackedMsg, end) + ); +} + + +static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; + return( + push16(value->PhysCellId, ppWritePackedMsg, end) && + push8(value->BetaPss, ppWritePackedMsg, end) && + push8(value->SsbBlockIndex, ppWritePackedMsg, end) && + push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && + push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && + push8(value->bchPayloadFlag, ppWritePackedMsg, end) && + push32(value->bchPayload, ppWritePackedMsg, end) + // TODO: pack precoding_and_beamforming too + ); +} + + +static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel13_t *value = (nfapi_dl_config_dci_dl_pdu_rel13_t *)tlv; + return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && + push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end) && + push8(value->codebook_size_determination, ppWritePackedMsg, end) && + push8(value->drms_table_flag, ppWritePackedMsg, end) && + push8(value->tpm_struct_flag, ppWritePackedMsg, end) && + (value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1)); +} + +static uint8_t pack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_bch_pdu_rel8_t *value = (nfapi_dl_config_bch_pdu_rel8_t *)tlv; + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__); + return( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_mch_pdu_rel8_t *value = (nfapi_dl_config_mch_pdu_rel8_t *)tlv; + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->mbsfn_area_id, ppWritePackedMsg, end)); +} + +static uint8_t pack_bf_vector_info(void *elem, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_bf_vector_t *bf = (nfapi_bf_vector_t *)elem; + return ( push8(bf->subband_index, ppWritePackedMsg, end) && + push8(bf->num_antennas, ppWritePackedMsg, end) && + pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel8_t *value = (nfapi_dl_config_dlsch_pdu_rel8_t *)tlv; + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->transport_blocks, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->transmission_scheme, ppWritePackedMsg, end) && + push8(value->number_of_layers, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->ue_category_capacity, ppWritePackedMsg, end) && + push8(value->pa, ppWritePackedMsg, end) && + push8(value->delta_power_offset_index, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end) && + push8(value->nprb, ppWritePackedMsg, end) && + push8(value->transmission_mode, ppWritePackedMsg, end) && + push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) && + push8(value->num_bf_vector, ppWritePackedMsg, end) && + packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel9_t *value = (nfapi_dl_config_dlsch_pdu_rel9_t *)tlv; + return ( push8(value->nscid, ppWritePackedMsg, end) ); +} +static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel10_t *value = (nfapi_dl_config_dlsch_pdu_rel10_t *)tlv; + return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) && + push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && + push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && + pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && + push8(value->pdsch_start, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel11_t *value = (nfapi_dl_config_dlsch_pdu_rel11_t *)tlv; + return( push8(value->drms_config_flag, ppWritePackedMsg, end) && + push16(value->drms_scrambling, ppWritePackedMsg, end) && + push8(value->csi_config_flag, ppWritePackedMsg, end) && + push16(value->csi_scrambling, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel12_t *value = (nfapi_dl_config_dlsch_pdu_rel12_t *)tlv; + return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) && + push8(value->maxlayers, ppWritePackedMsg, end) && + push8(value->n_dl_harq, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel13_t *value = (nfapi_dl_config_dlsch_pdu_rel13_t *)tlv; + return( push8(value->dwpts_symbols, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end) && + push8(value->ue_type, ppWritePackedMsg, end) && + push8(value->pdsch_payload_type, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && + push8(value->drms_table_flag, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_pch_pdu_rel8_t *value = (nfapi_dl_config_pch_pdu_rel8_t *)tlv; + return( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->p_rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->number_of_transport_blocks, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->transmission_scheme, ppWritePackedMsg, end) && + push8(value->number_of_layers, ppWritePackedMsg, end) && + push8(value->codebook_index, ppWritePackedMsg, end) && + push8(value->ue_category_capacity, ppWritePackedMsg, end) && + push8(value->pa, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->nprb, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_pch_pdu_rel13_t *value = (nfapi_dl_config_pch_pdu_rel13_t *)tlv; + return ( push8(value->ue_mode, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_prs_pdu_rel9_t *value = (nfapi_dl_config_prs_pdu_rel9_t *)tlv; + return( push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->prs_bandwidth, ppWritePackedMsg, end) && + push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) && + push8(value->prs_muting, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_csi_rs_pdu_rel10_t *value = (nfapi_dl_config_csi_rs_pdu_rel10_t *)tlv; + return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) && + pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_csi_rs_pdu_rel13_t *value = (nfapi_dl_config_csi_rs_pdu_rel13_t *)tlv; + + if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + push8(value->num_bf_vector, ppWritePackedMsg, end))) { + return 0; + } + + uint16_t i; + + for(i = 0; i < value->num_bf_vector; ++i) { + if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) && + pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} +static uint8_t pack_bf_vector(nfapi_bf_vector_t *vector, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(vector->subband_index, ppWritePackedMsg, end) && + push8(vector->num_antennas, ppWritePackedMsg, end) && + pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_epdcch_parameters_rel11_t *value = (nfapi_dl_config_epdcch_parameters_rel11_t *)tlv; + return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) && + push16(value->epdcch_id, ppWritePackedMsg, end) && + push8(value->epdcch_start_symbol, ppWritePackedMsg, end) && + push8(value->epdcch_num_prb, ppWritePackedMsg, end) && + pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) && + pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_epdcch_parameters_rel13_t *value = (nfapi_dl_config_epdcch_parameters_rel13_t *)tlv; + return (push8(value->dwpts_symbols, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_mpdcch_pdu_rel13_t *value = (nfapi_dl_config_mpdcch_pdu_rel13_t *)tlv; + return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) && + push8(value->number_of_prb_pairs, ppWritePackedMsg, end) && + push8(value->resource_block_assignment, ppWritePackedMsg, end) && + push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->ecce_index, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->ce_mode, ppWritePackedMsg, end) && + push16(value->drms_scrambling_init, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->dci_format, ppWritePackedMsg, end) && + push16(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->new_data_indicator, ppWritePackedMsg, end) && + push8(value->harq_process, ppWritePackedMsg, end) && + push8(value->tpmi_length, ppWritePackedMsg, end) && + push8(value->tpmi, ppWritePackedMsg, end) && + push8(value->pmi_flag, ppWritePackedMsg, end) && + push8(value->pmi, ppWritePackedMsg, end) && + push8(value->harq_resource_offset, ppWritePackedMsg, end) && + push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push8(value->tpc, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index, ppWritePackedMsg, end) && + push8(value->allocate_prach_flag, ppWritePackedMsg, end) && + push8(value->preamble_index, ppWritePackedMsg, end) && + push8(value->prach_mask_index, ppWritePackedMsg, end) && + push8(value->starting_ce_level, ppWritePackedMsg, end) && + push8(value->srs_request, ppWritePackedMsg, end) && + push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) && + push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) && + push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) && + push8(value->direct_indication, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) && + pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_nbch_pdu_rel13_t *value = (nfapi_dl_config_nbch_pdu_rel13_t *)tlv; + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_npdcch_pdu_rel13_t *value = (nfapi_dl_config_npdcch_pdu_rel13_t *)tlv; + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push8(value->ncce_index, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && + push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && + push8(value->dci_format, ppWritePackedMsg, end) && + push8(value->scheduling_delay, ppWritePackedMsg, end) && + push8(value->resource_assignment, ppWritePackedMsg, end) && + push8(value->repetition_number, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->new_data_indicator, ppWritePackedMsg, end) && + push8(value->harq_ack_resource, ppWritePackedMsg, end) && + push8(value->npdcch_order_indication, ppWritePackedMsg, end) && + push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) && + push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) && + push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) && + push8(value->direct_indication, ppWritePackedMsg, end) && + push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_ndlsch_pdu_rel13_t *value = (nfapi_dl_config_ndlsch_pdu_rel13_t *)tlv; + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->resource_assignment, ppWritePackedMsg, end) && + push16(value->repetition_number, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) && + push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && + push16(value->sf_idx, ppWritePackedMsg, end) && + push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_tti_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)tlv; + + if(!(push32(value->PDUSize, ppWritePackedMsg, end) && + push16(value->PDUType, ppWritePackedMsg, end) )) + return 0; + + // first match the pdu type, then call the respective function + switch(value->PDUType) { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { + if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { + if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { + if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { + if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; +} + +static uint8_t pack_dl_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_dl_config_request_body_t *value = (nfapi_dl_config_request_body_t *)tlv; + + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich); + + if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) && + push8(value->number_dci, ppWritePackedMsg, end) && + push16(value->number_pdu, ppWritePackedMsg, end) && + push8(value->number_pdsch_rnti, ppWritePackedMsg, end) && + push16(value->transmission_power_pcfich, ppWritePackedMsg, end))) { + return 0; + } + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_pdu; + + for(; i < total_number_of_pdus; ++i) { + nfapi_dl_config_request_pdu_t *pdu = &(value->dl_config_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__); + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value))) { + return 0; + } + } + break; + + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__); + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) & + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + + +static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nPDUs, ppWritePackedMsg, end) && + pusharray8(pNfapiMsg->dl_tti_request_body.nUe,256,pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + + for(int i=0; idl_tti_request_body.nGroup; i++) { + for(int j=0; jdl_tti_request_body.nUe[i]; j++) { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + + if(!(pusharrays32(arr,12,pNfapiMsg->dl_tti_request_body.nUe[i],ppWritePackedMsg, end))) + return 0; + } + + for(int i=0; idl_tti_request_body.nPDUs; i++) { + if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) + return 0; + } + + return 1; +} + + +static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; + //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) && + //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + { + uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value); + uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + + if (!x || !y || !z) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z); + } + + return x && y && z; + } +} + + + + +static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel8_t *ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t *)tlv; + return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel10_t *ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t *)tlv; + return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && + push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel11_t *ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t *)tlv; + return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel13_t *ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t *)tlv; + return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); +} + +//Pack fns for ul_tti PDUS + + +static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t *prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + return( + push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && + push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && + push8(prach_pdu->prach_format, ppWritePackedMsg, end) && + push8(prach_pdu->num_ra, ppWritePackedMsg, end) && + push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && + push16(prach_pdu->num_cs, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); +} + +static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t *pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + return( + push16(pucch_pdu->rnti, ppWritePackedMsg, end) && + push32(pucch_pdu->handle, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(pucch_pdu->format_type, ppWritePackedMsg, end) && + push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && + push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && + push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && + push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && + push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && + push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && + push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && + push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + if (!( + push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && + push16(pusch_pdu->rnti, ppWritePackedMsg, end) && + push32(pusch_pdu->handle, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && + push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && + push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && + push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && + push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->scid, ppWritePackedMsg, end) && + push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && + push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && + push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && + push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && + push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && + push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map) { + case PUSCH_PDU_BITMAP_PUSCH_DATA: { + // pack optional TLVs + return( + push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && + push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && + pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: { + return( + push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: { + return( + push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: { + return( + push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && + push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) + ); + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + +static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t *srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + return( + push16(srs_pdu->rnti, ppWritePackedMsg, end) && + push32(srs_pdu->handle, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && + push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && + push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && + push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && + push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && + push8(srs_pdu->config_index, ppWritePackedMsg, end) && + push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && + push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && + push8(srs_pdu->comb_size, ppWritePackedMsg, end) && + push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->resource_type, ppWritePackedMsg, end) && + push16(srs_pdu->t_srs, ppWritePackedMsg, end) && + push16(srs_pdu->t_offset, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); +} + +static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu *ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value)); +} + +static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel8_t *cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t *)tlv; + return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel9_t *cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t *)tlv; + + if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end))) { + return 0; + } + + switch(cqi_ri_info_rel9->report_type) { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: { + if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end))) { + return 0; + } + } + break; + + case NFAPI_CSI_REPORT_TYPE_APERIODIC: { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t i; + + for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t j; + + for(j = 0; j < 8; ++j) { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0) + return 0; + } + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); + } + break; + }; + + return 1; +} + +static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel13_t *cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t *)tlv; + + switch(cqi_ri_info_rel13->report_type) { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: { + if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0) + return 0; + } + break; + + case NFAPI_CSI_REPORT_TYPE_APERIODIC: { + // No parameters + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type ); + } + break; + }; + + return 1; +} + +static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information *cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value)); +} + +static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_initial_transmission_parameters_rel8_t *init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t *)tlv; + return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) && + push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters *init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end) { + return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, + &pack_ul_config_request_init_tx_params_rel8_value); +} + +static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_harq_information_rel10_t *harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t *)tlv; + return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) && + push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_harq_information_rel13_t *harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t *)tlv; + return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && + push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information *harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value)); +} + +static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel8_t *ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t *)tlv; + return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) && + push16(ue_info_rel8->rnti, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel11_t *ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t *)tlv; + return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && + push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel13_t *ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t *)tlv; + return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) && + push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) && + push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && + push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information *ue_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value)); +} + +static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel10_tdd_t *harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t *)tlv; + return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) && + push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel8_fdd_t *harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t *)tlv; + return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) && + push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel9_fdd_t *harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t *)tlv; + return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) && + push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel11_t *harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t *)tlv; + return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel13_t *harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t *)tlv; + return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && + push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) && + push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) && + push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) && + push8(harq_info_rel13->n_srs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information *harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value)); +} + +static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel8_t *cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t *)tlv; + return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) && + push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel10_t *cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t *)tlv; + return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) && + push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel13_t *cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t *)tlv; + return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) && + push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) && + push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) && + push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) && + push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) && + push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information *cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value)); +} + +static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_sr_information_rel8_t *sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t *)tlv; + return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end); +} +static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_sr_information_rel10_t *sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t *)tlv; + return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information *sr_info, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value)); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel8_t *srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t *)tlv; + return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->size, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel10_t *srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t *)tlv; + return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel13_t *srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t *)tlv; + return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_nb_harq_information_rel13_fdd_t *nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t *)tlv; + return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_nulsch_pdu_rel13_t *nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t *)tlv; + return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) && + push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && + pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, + &pack_ul_config_request_nb_harq_rel13_value)); +} +static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_nrach_pdu_rel13_t *nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t *)tlv; + return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) && + push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) && + push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); +} + + + +static uint8_t pack_ul_tti_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_ul_tti_request_number_of_pdus_t *value = (nfapi_nr_ul_tti_request_number_of_pdus_t *)tlv; + + if(!(push16(value->pdu_size, ppWritePackedMsg, end) && + push16(value->pdu_type, ppWritePackedMsg, end) )) + return 0; + + // first match the pdu type, then call the respective function + switch(value->pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { + if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { + if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); + } + break; + } + + return 1; +} + +static uint8_t pack_ul_tti_groups_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_ul_tti_request_number_of_groups_t *value = (nfapi_nr_ul_tti_request_number_of_groups_t *)tlv; + + if(!push8(value->n_ue, ppWritePackedMsg, end)) + return 0; + + for(int i=0; in_ue; i++) { + if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t pack_ul_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_config_request_body_t *value = (nfapi_ul_config_request_body_t *)tlv; + + if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) && + push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) && + push8(value->srs_present, ppWritePackedMsg, end))) + return 0; + + uint16_t i = 0; + + for(i = 0; i < value->number_of_pdus; ++i) { + nfapi_ul_config_request_pdu_t *pdu = &(value->ul_config_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: { + if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end)) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && + pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: { + if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value))) + return 0; + } + break; + + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + + +static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_pdus, ppWritePackedMsg, end) && + push8(pNfapiMsg->rach_present, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_group, ppWritePackedMsg, end) )) + return 0; + + for(int i=0; in_pdus; i++) { + if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) + return 0; + } + + for(int i=0; in_group; i++) { + if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + + +static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ; +} + +static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_hi_pdu_rel8_t *hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t *)tlv; + return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) && + push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_hi_pdu_rel10_t *hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t *)tlv; + return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) && + push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel8_t *dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t *)tlv; + return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) && + push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) && + push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) && + push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel10_t *dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t *)tlv; + return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && + push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel12_t *dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t *)tlv; + return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) && + push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *)tlv; + return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) && + pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_npdcch_dci_pdu_rel13_t *npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t *)tlv; + return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && + push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end)); +} + + +static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_hi_dci0_request_body_t *value = (nfapi_hi_dci0_request_body_t *)tlv; + + if(!(push16(value->sfnsf, ppWritePackedMsg, end) && + push8(value->number_of_dci, ppWritePackedMsg, end) && + push8(value->number_of_hi, ppWritePackedMsg, end))) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi; + + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_hi_dci0_request_pdu_t *pdu = &(value->hi_dci0_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_HI_DCI0_HI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value))) + return 0; + } + break; + + case NFAPI_HI_DCI0_DCI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value))) + return 0; + } + break; + + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value))) + return 0; + } + break; + + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value))) + return 0; + } + break; + + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + +static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv; - if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){ + nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) + + return 0; + } + + return (push16(value->PDUType, ppWritePackedMsg, end) && + push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); + +} + +static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->numPdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumPdus; i++) { + if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + + + +static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +//pack_tx_data_pdu_list_value +static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)tlv; + + if(!(push32(value->num_TLV, ppWritePackedMsg, end) && + push16(value->PDU_index, ppWritePackedMsg, end) && + push16(value->PDU_length, ppWritePackedMsg, end) + )) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_tlvs = value->num_TLV; + + for(; i < total_number_of_tlvs; ++i) { + if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && + push16(value->TLVs[i].tag, ppWritePackedMsg, end))) + return 0; + + switch(value->TLVs[i].tag) { + case 0: { + if(!pusharray32(value->TLVs[i].value.direct, 16384, value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + + break; + } + + case 1: { + if(!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length, value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + + break; + } + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); + break; + } + } + } + + return 1; +} + +static uint8_t pack_tx_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_tx_request_body_t *value = (nfapi_tx_request_body_t *)tlv; + + if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + + for(; i < total_number_of_pdus; ++i) { + nfapi_tx_request_pdu_t *pdu = &(value->tx_pdu_list[i]); + + if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) && + push16(pdu->pdu_index, ppWritePackedMsg, end))) + return 0; + + uint8_t j; + + for(j = 0; j < pdu->num_segments; ++j) { + // Use -1 as it is unbounded + // DJP - does not handle -1 + // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) + int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); + + if (pdu->segments[j].segment_length == 3) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, + pdu->segments[j].segment_data[0], + pdu->segments[j].segment_data[1], + pdu->segments[j].segment_data[2] + ); + } + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret); + + if (push_ret == 0) { + return 0; + } + } + } + + return 1; +} + +static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; + + if (!( + push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iNumber_of_PDUs; i++) { + if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t *)msg; + int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z); + return x && y && z; +} + +static uint8_t pack_release_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ue_release_request_body_t *value = (nfapi_ue_release_request_body_t *)tlv; + + if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0) { return 0; } uint8_t j; uint16_t num = value->number_of_TLVs; - for(j = 0; j < num; ++j){ - if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){ + + for(j = 0; j < num; ++j) { + if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0) { return 0; } } + return 1; } -static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; +static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t *)msg; int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value); int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); return x && y && z; } -static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - - int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return x && z; +static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t *)msg; + int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return x && z; } -static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) ); -} - -static uint8_t unpack_rx_ue_information_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; - - return ( pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) && - push8(data->value_1, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) && - push8(data->value_1, ppWritePackedMsg, end) && - push8(data->value_2, ppWritePackedMsg, end) && - push8(data->value_3, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) ); -} - -static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) ); -} - -static uint8_t pack_harq_indication_tdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel8_t* harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t*)tlv; - - if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) && - push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t result = 0; - switch(harq_indication_tdd_rel8->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = 1; - break; - default: - // err.... - break; - } - - return result; - -} - -static uint8_t pack_harq_indication_tdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel9_t* harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t*)tlv; - - if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) && - push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t idx; - for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - - switch(harq_indication_tdd_rel9->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end); - break; - default: - // err.... - break; - } - - if(result == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_harq_indication_tdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel13_t* harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t*)tlv; - - if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) && - push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t idx; - for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(harq_indication_tdd_rel13->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end); - break; - default: - // err.... - break; - } - - if(result == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_harq_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel8_t* harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t*)tlv; - - return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) && - push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel9_t* harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t*)tlv; - - return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) && - push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) && - pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel13_t* harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t*)tlv; - - return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) && - push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) && - pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_cqi_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; - - return ( push8(value->ul_cqi, ppWritePackedMsg, end) && - push8(value->channel, ppWritePackedMsg, end)); - -} - -static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; - - if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_harqs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_crc_indication_rel8_t* crc_indication_rel8 = (nfapi_crc_indication_rel8_t*)tlv; - - return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) ); -} - -static uint8_t pack_crc_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; - - if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_crcs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - return 1; -} - -static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} -static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->offset, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end)); -} -static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; - - return ( push16(value->timing_advance_r9, ppWritePackedMsg, end)); -} - -static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; - - //printf("RX ULSCH BODY\n"); - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - // need to calculate the data offset's. - uint16_t i = 0; - uint16_t offset = 2; // taking into account the number_of_pdus - uint16_t total_number_of_pdus = value->number_of_pdus; - //printf("ULSCH:pdus:%d\n", total_number_of_pdus); - - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) - { - //printf("NFAPI_RX_UE_INFORMATION_TAG\n"); - offset += 4 + 6; - } - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - //printf("NFAPI_RX_INDICATION_REL8_TAG\n"); - offset += 4 + 7; - } - - if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG) - { - //printf("NFAPI_RX_INDICATION_REL9_TAG\n"); - offset += 4 + 2; - } - } - - // Now update the structure to include the offset - for(i =0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - if(pdu->rx_indication_rel8.offset == 1) - { - pdu->rx_indication_rel8.offset = offset; - offset += pdu->rx_indication_rel8.length; - } - } - } - - // Write out the pdu - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) && - pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value))) - return 0; - } - - // Write out the pdu data - for(i = 0; i < total_number_of_pdus; ++i) - { - uint16_t length = 0; - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - length = pdu->rx_indication_rel8.length; - } - - if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0) - return 0; - } - return 1; -} - - -static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_preamble_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel8_t* preamble_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; - - return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) && - push8(preamble_rel8->preamble, ppWritePackedMsg, end) && - push16(preamble_rel8->timing_advance, ppWritePackedMsg, end)); -} -static uint8_t pack_preamble_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel9_t* preamble_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; - - return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) ); -} -static uint8_t pack_preamble_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel13_t* preamble_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; - - return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) ); -} - -static uint8_t pack_rach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; - - if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_preambles; - for(; i < total_number_of_pdus; ++i) - { - nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) && - pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) && - pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel8_t* srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; - - return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) && - pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end)); -} - -static uint8_t pack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel9_t* srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; - - return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) ); -} - -static uint8_t pack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_ttd_rel10_t* srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; - - return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) ); - -} - -static uint8_t pack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel11_t* srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; - - return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ; -} - -static uint8_t pack_tdd_channel_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; - - if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->num_atennas, ppWritePackedMsg, end))) - return 0; - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) && - pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t*)tlv; - - if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_ues; - for(; i < total_number_of_pdus; ++i) - { - nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) && - pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) && - pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; - - if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_srs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - return 1; -} - -static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; - - return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) && - push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) && - push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) && - push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) && - push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end)); -} - -static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; - - return ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) && - push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) && - push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && - pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end)); -} - -static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; - - if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0) - return 0; - - // need to calculate the data offset's. This very bittle due the hardcoding - // of the sizes. can not use the sizeof as we have an array for the Rel9 - // info - uint16_t i = 0; - uint16_t offset = 2; // taking into account the number_of_cqis - uint16_t total_number_of_pdus = value->number_of_cqis; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - offset += 2; // for the instance length - - if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) - { - offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t) - } - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - offset += 4 + 8; - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported; - } - - if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG) - { - offset += 4 + 2; - } - } - - // Now update the structure to include the offset - for(i =0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - if(pdu->cqi_indication_rel8.data_offset == 1) - { - pdu->cqi_indication_rel8.data_offset = offset; - offset += pdu->cqi_indication_rel8.length; - } - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - if(pdu->cqi_indication_rel9.data_offset == 1) - { - pdu->cqi_indication_rel9.data_offset = offset; - offset += pdu->cqi_indication_rel9.length; - } - } - - } - - // Write out the cqi information - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end ,pack_rx_ue_information_value) && - pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) && - pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - - } - - // Write out the cqi raw data - for(i = 0; i < total_number_of_pdus; ++i) - { - uint16_t length = 0; - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - length = pdu->cqi_indication_rel8.length; - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - length = pdu->cqi_indication_rel9.length; - } - - if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->mp_cca, ppWritePackedMsg, end) && - push32(value->n_cca, ppWritePackedMsg, end) && - push32(value->offset, ppWritePackedMsg, end) && - push32(value->lte_txop_sf, ppWritePackedMsg, end) && - push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) && - push32(value->lbt_mode, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->offset, ppWritePackedMsg, end) && - push16(value->sfn_sf_end, ppWritePackedMsg, end) && - push32(value->lbt_mode, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); - - if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0) - return 0; - } - break; - case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: - { - if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - -static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->result, ppWritePackedMsg, end) && - push32(value->lte_txop_symbols, ppWritePackedMsg, end) && - push32(value->initial_partial_sf, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->result, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_lbt_dl_config_indication_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); - - if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0) - return 0; - } - break; - case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - -static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nb_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_fdd_rel13_t* nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; - - return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) ); -} - -static uint8_t pack_nb_harq_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; - - if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_harqs = value->number_of_harqs; - for(; i < total_number_of_harqs; ++i) - { - nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - - -static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nrach_indication_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_pdu_rel13_t* nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t*)tlv; - - return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) && - push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) && - push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) && - push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end)); -} - - -static uint8_t pack_nrach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; - - if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected; - for(; i < total_number_of_initial_scs_detected; ++i) - { - nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); - - //uint8_t* instance_length_p = *ppWritePackedMsg; - //if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - // return 0; - - if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - //uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - //push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; - - return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; - - return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - push32(pNfapiMsg->t2, ppWritePackedMsg, end) && - push32(pNfapiMsg->t3, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - - return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && - push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && - push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - -// Main pack function - public - -int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *end = pPackedBuf + packedBufLen; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && - push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && - push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } - - if (pMessageHeader->message_id != NFAPI_TIMING_INFO) - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); - } - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_DL_CONFIG_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); - result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UL_CONFIG_REQUEST: - result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_HI_DCI0_REQUEST: - result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TX_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); - result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); - break; +static uint8_t pack_rx_ue_information_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rx_ue_information *value = (nfapi_rx_ue_information *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) ); +} + +static uint8_t unpack_rx_ue_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rx_ue_information *value = (nfapi_rx_ue_information *)tlv; + return ( pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t *data, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(data->value_0, ppWritePackedMsg, end) && + push8(data->value_1, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t *data, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(data->value_0, ppWritePackedMsg, end) && + push8(data->value_1, ppWritePackedMsg, end) && + push8(data->value_2, ppWritePackedMsg, end) && + push8(data->value_3, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t *data, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(data->value_0, ppWritePackedMsg, end) ); +} + +static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t *data, uint8_t **ppWritePackedMsg, uint8_t *end) { + return ( push8(data->value_0, ppWritePackedMsg, end) ); +} + +static uint8_t pack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel8_t *harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t *)tlv; + + if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) && + push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t result = 0; + + switch(harq_indication_tdd_rel8->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = 1; + break; + + default: + // err.... + break; + } + + return result; +} + +static uint8_t pack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel9_t *harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t *)tlv; + + if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) && + push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t idx; + + for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx) { + uint8_t result = 0; + + switch(harq_indication_tdd_rel9->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end); + break; + + default: + // err.... + break; + } + + if(result == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t *)tlv; + + if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) && + push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t idx; + + for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx) { + uint8_t result = 0; + + switch(harq_indication_tdd_rel13->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end); + break; + + default: + // err.... + break; + } + + if(result == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel8_t *harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t *)tlv; + return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) && + push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel9_t *harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t *)tlv; + return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) && + push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) && + pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t *)tlv; + return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) && + push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) && + pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_cqi_information_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_ul_cqi_information_t *value = (nfapi_ul_cqi_information_t *)tlv; + return ( push8(value->ul_cqi, ppWritePackedMsg, end) && + push8(value->channel, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_harq_indication_body_t *value = (nfapi_harq_indication_body_t *)tlv; + + if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_harqs; + + for(; i < total_number_of_pdus; ++i) { + nfapi_harq_indication_pdu_t *pdu = &(value->harq_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_crc_indication_rel8_t *crc_indication_rel8 = (nfapi_crc_indication_rel8_t *)tlv; + return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) ); +} + +static uint8_t pack_crc_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_crc_indication_body_t *value = (nfapi_crc_indication_body_t *)tlv; + + if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_crcs; + + for(; i < total_number_of_pdus; ++i) { + nfapi_crc_indication_pdu_t *pdu = &(value->crc_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} +static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rx_indication_rel8_t *value = (nfapi_rx_indication_rel8_t *)tlv; + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->offset, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end)); +} +static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rx_indication_rel9_t *value = (nfapi_rx_indication_rel9_t *)tlv; + return ( push16(value->timing_advance_r9, ppWritePackedMsg, end)); +} + +static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rx_indication_body_t *value = (nfapi_rx_indication_body_t *)tlv; + + //printf("RX ULSCH BODY\n"); + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + // need to calculate the data offset's. + uint16_t i = 0; + uint16_t offset = 2; // taking into account the number_of_pdus + uint16_t total_number_of_pdus = value->number_of_pdus; + //printf("ULSCH:pdus:%d\n", total_number_of_pdus); + + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_rx_indication_pdu_t *pdu = &(value->rx_pdu_list[i]); + + if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) { + //printf("NFAPI_RX_UE_INFORMATION_TAG\n"); + offset += 4 + 6; + } + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) { + //printf("NFAPI_RX_INDICATION_REL8_TAG\n"); + offset += 4 + 7; + } + + if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG) { + //printf("NFAPI_RX_INDICATION_REL9_TAG\n"); + offset += 4 + 2; + } + } + + // Now update the structure to include the offset + for(i =0; i < total_number_of_pdus; ++i) { + nfapi_rx_indication_pdu_t *pdu = &(value->rx_pdu_list[i]); + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) { + if(pdu->rx_indication_rel8.offset == 1) { + pdu->rx_indication_rel8.offset = offset; + offset += pdu->rx_indication_rel8.length; + } + } + } + + // Write out the pdu + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_rx_indication_pdu_t *pdu = &(value->rx_pdu_list[i]); + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) && + pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value))) + return 0; + } + + // Write out the pdu data + for(i = 0; i < total_number_of_pdus; ++i) { + uint16_t length = 0; + nfapi_rx_indication_pdu_t *pdu = &(value->rx_pdu_list[i]); + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) { + length = pdu->rx_indication_rel8.length; + } + + if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0) + return 0; + } + + return 1; +} + + +static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel8_t *preamble_rel8 = (nfapi_preamble_pdu_rel8_t *)tlv; + return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) && + push8(preamble_rel8->preamble, ppWritePackedMsg, end) && + push16(preamble_rel8->timing_advance, ppWritePackedMsg, end)); +} +static uint8_t pack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel9_t *preamble_rel9 = (nfapi_preamble_pdu_rel9_t *)tlv; + return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) ); +} +static uint8_t pack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel13_t *preamble_rel13 = (nfapi_preamble_pdu_rel13_t *)tlv; + return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) ); +} + +static uint8_t pack_rach_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_rach_indication_body_t *value = (nfapi_rach_indication_body_t *)tlv; + + if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_preambles; + + for(; i < total_number_of_pdus; ++i) { + nfapi_preamble_pdu_t *pdu = &(value->preamble_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) && + pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) && + pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_srs_indication_fdd_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel8_t *srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t *)tlv; + return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) && + pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end)); +} + +static uint8_t pack_srs_indication_fdd_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel9_t *srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t *)tlv; + return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) ); +} + +static uint8_t pack_srs_indication_tdd_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_ttd_rel10_t *srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t *)tlv; + return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) ); +} + +static uint8_t pack_srs_indication_fdd_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel11_t *srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t *)tlv; + return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ; +} + +static uint8_t pack_tdd_channel_measurement_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_tdd_channel_measurement_t *value = (nfapi_tdd_channel_measurement_t *)tlv; + + if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->num_atennas, ppWritePackedMsg, end))) + return 0; + + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_subbands; ++idx) { + if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) && + pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} + +static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t *)tlv; + + if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_ues; + + for(; i < total_number_of_pdus; ++i) { + nfapi_srs_indication_pdu_t *pdu = &(value->srs_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) && + pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) && + pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_sr_indication_body_t *value = (nfapi_sr_indication_body_t *)tlv; + + if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_srs; + + for(; i < total_number_of_pdus; ++i) { + nfapi_sr_indication_pdu_t *pdu = &(value->sr_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_cqi_indication_rel8_t *cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t *)tlv; + return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) && + push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) && + push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) && + push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) && + push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end)); +} + +static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_cqi_indication_rel9_t *cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t *)tlv; + return ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) && + push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) && + push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && + pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end)); +} + +static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_cqi_indication_body_t *value = (nfapi_cqi_indication_body_t *)tlv; + + if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0) + return 0; + + // need to calculate the data offset's. This very bittle due the hardcoding + // of the sizes. can not use the sizeof as we have an array for the Rel9 + // info + uint16_t i = 0; + uint16_t offset = 2; // taking into account the number_of_cqis + uint16_t total_number_of_pdus = value->number_of_cqis; + + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + offset += 2; // for the instance length + + if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) { + offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t) + } + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) { + offset += 4 + 8; + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) { + offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported; + } + + if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG) { + offset += 4 + 2; + } + } + + // Now update the structure to include the offset + for(i =0; i < total_number_of_pdus; ++i) { + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) { + if(pdu->cqi_indication_rel8.data_offset == 1) { + pdu->cqi_indication_rel8.data_offset = offset; + offset += pdu->cqi_indication_rel8.length; + } + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) { + if(pdu->cqi_indication_rel9.data_offset == 1) { + pdu->cqi_indication_rel9.data_offset = offset; + offset += pdu->cqi_indication_rel9.length; + } + } + } + + // Write out the cqi information + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end,pack_rx_ue_information_value) && + pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) && + pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + // Write out the cqi raw data + for(i = 0; i < total_number_of_pdus; ++i) { + uint16_t length = 0; + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) { + length = pdu->cqi_indication_rel8.length; + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) { + length = pdu->cqi_indication_rel9.length; + } + + if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t *)msg; + //Fixme: allocate some mem to fix pure bug, need to find out proper size + pNfapiMsg->vendor_extension=NULL;//(nfapi_vendor_extension_tlv_t)malloc( sizeof(* pNfapiMsg->vendor_extension)); + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_pdsch_req_pdu_rel13_t *value = (nfapi_lbt_pdsch_req_pdu_rel13_t *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->mp_cca, ppWritePackedMsg, end) && + push32(value->n_cca, ppWritePackedMsg, end) && + push32(value->offset, ppWritePackedMsg, end) && + push32(value->lte_txop_sf, ppWritePackedMsg, end) && + push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) && + push32(value->lbt_mode, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_drs_req_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_drs_req_pdu_rel13_t *value = (nfapi_lbt_drs_req_pdu_rel13_t *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->offset, ppWritePackedMsg, end) && + push16(value->sfn_sf_end, ppWritePackedMsg, end) && + push32(value->lbt_mode, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_dl_config_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_dl_config_request_body_t *value = (nfapi_lbt_dl_config_request_body_t *)tlv; + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + + for(; i < total_number_of_pdus; ++i) { + nfapi_lbt_dl_config_request_pdu_t *pdu = &(value->lbt_dl_config_req_pdu_list[i]); + + if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: { + if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0) + return 0; + } + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: { + if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + +static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_pdsch_rsp_pdu_rel13_t *value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->result, ppWritePackedMsg, end) && + push32(value->lte_txop_symbols, ppWritePackedMsg, end) && + push32(value->initial_partial_sf, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_drs_rsp_pdu_rel13_t *value = (nfapi_lbt_drs_rsp_pdu_rel13_t *)tlv; + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->result, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_lbt_dl_config_indication_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_lbt_dl_indication_body_t *value = (nfapi_lbt_dl_indication_body_t *)tlv; + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + + for(; i < total_number_of_pdus; ++i) { + nfapi_lbt_dl_indication_pdu_t *pdu = &(value->lbt_indication_pdu_list[i]); + + if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t *pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: { + if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0) + return 0; + } + break; + + case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: { + if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + +static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_harq_indication_fdd_rel13_t *nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t *)tlv; + return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) ); +} + +static uint8_t pack_nb_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nb_harq_indication_body_t *value = (nfapi_nb_harq_indication_body_t *)tlv; + + if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_harqs = value->number_of_harqs; + + for(; i < total_number_of_harqs; ++i) { + nfapi_nb_harq_indication_pdu_t *pdu = &(value->nb_harq_pdu_list[i]); + uint8_t *instance_length_p = *ppWritePackedMsg; + + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + + +static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nrach_indication_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nrach_indication_pdu_rel13_t *nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t *)tlv; + return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) && + push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) && + push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) && + push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end)); +} + + +static uint8_t pack_nrach_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nrach_indication_body_t *value = (nfapi_nrach_indication_body_t *)tlv; + + if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected; + + for(; i < total_number_of_initial_scs_detected; ++i) { + nfapi_nrach_indication_pdu_t *pdu = &(value->nrach_pdu_list[i]); + + //uint8_t* instance_length_p = *ppWritePackedMsg; + //if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + // return 0; + + if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + //uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + //push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t *)msg; + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t *)msg; + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t *)msg; + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t *)msg; + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t *)msg; + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t *)msg; + return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t *)msg; + return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && + push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +//NR UPLINK indication function packing + +//SLOT INDICATION + +static uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg; + + if (!(push16((uint16_t)pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16((uint16_t)pNfapiMsg->slot , ppWritePackedMsg, end) + )) + return 0; + +return 1; +} + +//RX DATA INDICATION + +static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push16(value->pdu_length, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + + +static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rx_data_indication_body(pNfapiMsg->pdu_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t pack_nr_crc_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push8(value->tb_crc_status, ppWritePackedMsg, end) && + push16(value->num_cb, ppWritePackedMsg, end) && + //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + +static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!pack_nr_crc_indication_body(pNfapiMsg->crc_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t pack_nr_srs_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push8(value->num_symbols, ppWritePackedMsg, end) && + push8(value->wide_band_snr, ppWritePackedMsg, end) && + push8(value->num_reported_symbols, ppWritePackedMsg, end) && + push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(push8(value->reported_symbol_list->rb_list->rb_snr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//RACH INDICATION + +static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) && + push8(value->symbol_index, ppWritePackedMsg, end) && + push8(value->slot_index, ppWritePackedMsg, end) && + push8(value->freq_index, ppWritePackedMsg, end) && + push8(value->avg_rssi, ppWritePackedMsg, end) && + push8(value->avg_snr, ppWritePackedMsg, end) && + push8(value->num_preamble, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(push8(value->preamble_list->preamble_index, ppWritePackedMsg, end) && + push16(value->preamble_list->timing_advance, ppWritePackedMsg, end) && + push32(value->preamble_list->preamble_pwr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + +//UCI INDICATION + +static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr->sr_indication, ppWritePackedMsg, end) && + push8(value->sr->sr_confidence_level, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq->num_harq, ppWritePackedMsg, end) && + push8(value->harq->harq_confidence_level, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iharq->num_harq;i++) + { + if(!(push8(value->harq->harq_list[i].harq_value, ppWritePackedMsg, end) + )) + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr.sr_bit_len, ppWritePackedMsg, end) && + pusharray8(value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq.harq_crc, ppWritePackedMsg, end) && + push8(value->harq.harq_bit_len, ppWritePackedMsg, end) && + pusharray8(value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end) && + push8(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end) && + push8(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(push16(value->pdu_type, ppWritePackedMsg, end) && + push16(value->pdu_size, ppWritePackedMsg, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end); + break; + + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end); + break; + } + + return 1; +} + +static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!pack_nr_uci_indication_body(pNfapiMsg->uci_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + +// Main pack function - public + +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) +{ + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; + + if (pMessageBuf == NULL || pPackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_UE_RELEASE_REQUEST: result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); @@ -2716,3339 +3358,4102 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_DL_NODE_SYNC: - result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UL_NODE_SYNC: - result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p7_vendor_extension) - { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPackedBuf; - uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - if(!push16(packedMsgLen16, &pPackedLengthField, end)) - return -1; - - if(1) - { - //quick test - if(pMessageHeader->message_length != packedMsgLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); - } - } - - return (packedMsgLen); -} - - - -// Unpack routines - -static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel8_t* dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) && - pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) && - pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end)); - -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel9_t* dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel10_t* dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel11_t* dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel12_t* dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) && - pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end)); -} - -static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end) -{ - if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && - pull8(ppReadPackedMsg, &value->number_of_subbands, end) && - pull8(ppReadPackedMsg, &value->num_antennas, end))) - return 0; - - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); - - if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) && - pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end))) - return 0; - - uint8_t antenna_idx = 0; - uint8_t scheduled_ue_idx = 0; - - for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) - { - for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) - { - if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end)) - return 0; - } - } - - } - - - return 1; - -} - - -static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel13_t* dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; - - // If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been - // added - uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5; - dci_dl_pdu_rel13->tpm_struct_flag = 0; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && - ( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) && - ( (tpm_struct_flag_present == 1 && dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1)); - -} - -static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_bch_pdu_rel8_t* bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&bch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_mch_pdu_rel8_t* mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&mch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end)); -} - -static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel8_t* dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; - - if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&dlsch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) && - pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end))) - return 0; - - uint16_t j = 0; - for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j) - { - if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) && - pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end))) - return 0; - } - return 1; -} -static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel9_t* dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) ); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel10_t* dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && - pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ; -} -static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel11_t* dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end)); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel12_t* dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end)); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel13_t* dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end)); -} - -static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel8_t* pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&pch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end)); -} -static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel13_t* pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end)); -} - -static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_prs_pdu_rel9_t* prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; - - return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end)); -} - -static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel10_t* csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; - - return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) && - pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) && - pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) && - pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end)); -} - -static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel13_t* csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; - - if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end))) - return 0; - - - uint16_t idx =0; - for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx) - { - if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end))) - return 0; - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n"); - //pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??); - } - return 1; -} - -static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel11_t* epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) && - pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) && - pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) && - pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end)); -} - -static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel13_t* epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end)); -} - -static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_mpdcch_pdu_rel13_t* mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; - - - return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) && - pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end)); -} - - -static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_nbch_pdu_rel13_t* nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&nbch_params_rel13->pdu_index, end) && - pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) && - pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end)); -} - -static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_npdcch_pdu_rel13_t* npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&npdcch_params_rel13->pdu_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end)); -} - -static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_ndlsch_pdu_rel13_t* ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&ndlsch_params_rel13->pdu_index, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); -} - - -static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) && - pull8(ppReadPackedMsg, &value->number_dci, end) && - pull16(ppReadPackedMsg, &value->number_pdu, end) && - pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) && - pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end))) - return 0; - - if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU); - return 0; - } - - if(value->number_pdu) - { - value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config); - if(value->dl_config_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu); - return 0; - } - } - else - { - value->dl_config_pdu_list = 0; - } - - uint16_t i; - uint16_t total_number_of_pdus = value->number_pdu; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end of beyond buffer end - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_BCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_MCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_PCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_PRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - - } - break; - case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - - } - break; - default: - // Need to log an error - break; - } - } - - return 1; -} - -static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value}, - }; - - return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) & - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end)); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; - - return ( pull8(ppReadPackedMsg, &ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel11->dmrs_config_flag, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end)); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &ulsch_pdu_rel13->ue_type, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end)); -} -static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end)); -} - -static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end))) - return 0; - - switch(cqi_ri_info_rel9->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end))) - return 0; - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0) - return 0; - - uint8_t i; - for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0) - return 0; - - uint8_t j; - for(j = 0; j < 8; ++j) - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0) - return 0; - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); - return 0; - } - break; - }; - return 1; -} - -// NOTE : This function is a little unconventional as we uese the side to -// determine the report type -static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; - if(cqi_ri_info_rel13->tl.length == 0) - { - cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC; - } - else - { - cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC; - if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0) - return 0; - } - return 1; -} -static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) && - pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end)); -} -static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) && - pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end)); -} - -static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end)); -} - -static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) && - pull16(ppReadPackedMsg, (uint16_t *)&ue_info_rel8->rnti, end)); -} -static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) && - pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end)); -} -static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) && - pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) && - pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) && - pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end)); -} - -static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) && - pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end)); -} -static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) && - pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end)); -} -static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) && - pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end)); -} - -static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end)); -} - -static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) && - pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end)); -} - - -static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end)); -} - -static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; - return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end); -} - -static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end)); -} - -static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end)); -} - -static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && - pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end))) - return 0; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, - { NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value}, - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0); -} - -static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) && - pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) && - pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end)); -} - - -static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - #define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, - - #define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value}, - - #define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value}, - - #define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value}, - - #define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, - - #define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value}, - - #define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value}, - - #define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value}, - - #define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value}, - - #define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value}, - - #define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value}, - - - nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) && - pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) && - pull8(ppReadPackedMsg, &value->srs_present, end))) - return 0; - - if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config); - - if(value->ul_config_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->ul_config_pdu_list = 0; - } - - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end is past buffer end - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu) - UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu) - UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu) - UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information) - UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_SRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - } - } - return 1; -} - - -static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; - - return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) && - pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) && - pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) && - pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) && - pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end)); -} - -static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) && - pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) && - pull8(ppReadPackedMsg, &value->resource_block_assignment, end) && - pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) && - pull8(ppReadPackedMsg, &value->start_symbol, end) && - pull8(ppReadPackedMsg, &value->ecce_index, end) && - pull8(ppReadPackedMsg, &value->aggreagation_level, end) && - pull8(ppReadPackedMsg, &value->rnti_type, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->ce_mode, end) && - pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) && - pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) && - pull16(ppReadPackedMsg, &value->transmission_power, end) && - pull8(ppReadPackedMsg, &value->dci_format, end) && - pull8(ppReadPackedMsg, &value->resource_block_start, end) && - pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &value->mcs, end) && - pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) && - pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) && - pull8(ppReadPackedMsg, &value->new_data_indication, end) && - pull8(ppReadPackedMsg, &value->harq_process, end) && - pull8(ppReadPackedMsg, &value->redudency_version, end) && - pull8(ppReadPackedMsg, &value->tpc, end) && - pull8(ppReadPackedMsg, &value->csi_request, end) && - pull8(ppReadPackedMsg, &value->ul_inex, end) && - pull8(ppReadPackedMsg, &value->dai_presence_flag, end) && - pull8(ppReadPackedMsg, &value->dl_assignment_index, end) && - pull8(ppReadPackedMsg, &value->srs_request, end) && - pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) && - pull32(ppReadPackedMsg, &value->tcp_bitmap, end) && - pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) && - pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) && - pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end)); -} - -static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->ncce_index, end) && - pull8(ppReadPackedMsg, &value->aggregation_level, end) && - pull8(ppReadPackedMsg, &value->start_symbol, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) && - pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) && - pull8(ppReadPackedMsg, &value->subcarrier_indication, end) && - pull8(ppReadPackedMsg, &value->resource_assignment, end) && - pull8(ppReadPackedMsg, &value->scheduling_delay, end) && - pull8(ppReadPackedMsg, &value->mcs, end) && - pull8(ppReadPackedMsg, &value->redudancy_version, end) && - pull8(ppReadPackedMsg, &value->repetition_number, end) && - pull8(ppReadPackedMsg, &value->new_data_indicator, end) && - pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end)); -} - -static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) && - pull8(ppReadPackedMsg, &value->number_of_dci, end) && - pull8(ppReadPackedMsg, &value->number_of_hi, end))) - return 0; - - uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci; - - if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU); - return 0; - } - - if(totalNumPdus > 0) - { - value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config); - if(value->hi_dci0_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus); - return 0; - } - } - else - { - value->hi_dci0_pdu_list = 0; - } - - uint8_t i; - for(i = 0; i < totalNumPdus; ++i) - { - nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end if past buffer end - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end); - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_HI_DCI0_HI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, - { NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - } - - return 1; -} - -static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} - -static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; - - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; - - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_TX_REQUEST_BODY_TAG: - { - pNfapiMsg->tx_request_body.tl = generic_tl; - - if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0) - return 0; - - if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU); - return 0; - } - - if(pNfapiMsg->tx_request_body.number_of_pdus > 0) - { - pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config); - if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus); - return 0; - } - } - else - { - pNfapiMsg->tx_request_body.tx_pdu_list = 0; - } - - - uint16_t i; - uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus; - for(i = 0; i < totalNumPdus; ++i) - { - nfapi_tx_request_pdu_t* pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); - if (pdu) { - uint16_t length = 0; - uint16_t index = 0; - - if(!(pull16(ppReadPackedMsg, &length, end) && - pull16(ppReadPackedMsg, &index, end))) - return 0; - - pdu->pdu_length = length; - pdu->pdu_index = index; - - - // TODO : May need to rethink this bit - pdu->num_segments = 1; - pdu->segments[0].segment_length = pdu->pdu_length; - pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); - - if(pdu->segments[0].segment_data) - { - if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) - return 0; - if (pdu->segments[0].segment_length == 3) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, - pdu->segments[0].segment_data[0], - pdu->segments[0].segment_data[1], - pdu->segments[0].segment_data[2] - ); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); - } - break; - }; - } - - return 1; -} + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); -static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - switch(generic_tl.tag) - { - case NFAPI_UE_RELEASE_BODY_TAG: - { - pNfapiMsg->ue_release_request_body.tl = generic_tl; - if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) - return 0; + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); - return 0; - } else { - uint8_t j; - uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; - for(j = 0; j < num; ++j){ - if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){ - return 0; - } - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); - } - break; - }; - } + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; - return 1; + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: + { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->pack_p7_vendor_extension) + { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + if(result == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } + else + { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; + + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; + + if(1) + { + //quick test + if(pMessageHeader->message_length != packedMsgLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } + + return (packedMsgLen); } -static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->value_0, end) && - pull8(ppReadPackedMsg, &value->value_1, end)); -} - -static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_multiplexing_t* value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->value_0, end) && - pull8(ppReadPackedMsg, &value->value_1, end) && - pull8(ppReadPackedMsg, &value->value_2, end) && - pull8(ppReadPackedMsg, &value->value_3, end)); -} -static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_special_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t*)tlv; - return ( pull8(ppReadPackedMsg, &value->value_0, end)); -} -static uint8_t unpack_harq_indication_tdd_harq_data(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_t* value = (nfapi_harq_indication_tdd_harq_data_t*)tlv; - return (pull8(ppReadPackedMsg, &value->value_0, end)); -} - -static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel8_t* value = (nfapi_harq_indication_tdd_rel8_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = 1; - break; - default: - // TODO add error message - return 0; - break; - } - return result; -} - -static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel9_t* value = (nfapi_harq_indication_tdd_rel9_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) - { - // TODO : add error message - return 0; - } - - uint16_t idx = 0; - for(idx = 0; idx < value->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); - break; - default: - // TODO add error message - return 0; - break; - } - - if(result == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel13_t* value = (nfapi_harq_indication_tdd_rel13_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull16(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) - { - // TODO : add error message - return 0; - } - - uint16_t idx = 0; - for(idx = 0; idx < value->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end); - break; - default: - // TODO add error message - return 0; - break; - } - - if(result == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel8_t* value = (nfapi_harq_indication_fdd_rel8_t*)tlv; - return (pull8(ppReadPackedMsg, &value->harq_tb1, end) && - pull8(ppReadPackedMsg, &value->harq_tb2, end)); -} - -static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel9_t* value = (nfapi_harq_indication_fdd_rel9_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) && - pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end)); -} - -static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel13_t* value = (nfapi_harq_indication_fdd_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mode, end) && - pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) && - pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end)); -} - -static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull8(ppReadPackedMsg, &value->channel, end)); -} - - - -static uint8_t unpack_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; - uint8_t* harqBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(harqBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) - return 0; - - if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); - return 0; - } - - value->harq_pdu_list = (nfapi_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config); - if(value->harq_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_harqs; ++i) - { - nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value}, - { NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value}, - { NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value}, - { NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value}, - { NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value}, - { NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value}, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_crc_indication_rel8_t* crc_pdu_rel8 = (nfapi_crc_indication_rel8_t*)tlv; - return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) ); -} - -static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; - uint8_t* crcBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(crcBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0) - return 0; - - if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU); - return 0; - } - - if(value->number_of_crcs > 0) - { - value->crc_pdu_list = (nfapi_crc_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config); - if(value->crc_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs); - return 0; - } - } - else - { - value->crc_pdu_list = 0; - } - - - uint8_t i = 0; - for(i = 0; i < value->number_of_crcs; ++i) - { - nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0) - return 0; - } - - return 1; -} - -static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->length, end) && - pull16(ppReadPackedMsg, &value->offset, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end)); -} -static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; - return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end)); -} - -static uint8_t unpack_rx_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; - - // the rxBodyEnd points to the end of the cqi PDU's - uint8_t* rxBodyEnd = *ppReadPackedMsg + value->tl.length; - uint8_t* rxPduEnd = rxBodyEnd; - - uint8_t* numberOfPdusAddress = *ppReadPackedMsg; - - if(rxBodyEnd > end) - { - // pdu end is past buffer end - return 0; - } - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->rx_pdu_list = (nfapi_rx_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config); - if(value->rx_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->rx_pdu_list = 0; - } - - uint8_t i = 0; - nfapi_rx_indication_pdu_t* pdu = 0; - while((uint8_t*)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t*)(*ppReadPackedMsg) < rxPduEnd) - { - nfapi_tl_t generic_tl; - if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_RX_UE_INFORMATION_TAG: - { - pdu = &(value->rx_pdu_list[i++]); - pdu->rx_ue_information.tl = generic_tl; - if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) - return 0; - } - break; - case NFAPI_RX_INDICATION_REL8_TAG: - { - if(pdu != 0) - { - pdu->rx_indication_rel8.tl = generic_tl; - if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0) - return 0; - - if(pdu->rx_indication_rel8.offset > 0) - { - // Need to check that the data is within the tlv - if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd) - { - // If this the first pdu set the rxPduEnd - if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd) - { - rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset; - - if(rxPduEnd > end) - { - // pdu end is past buffer end - return 0; - } - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n"); - } - } - } - } - break; - case NFAPI_RX_INDICATION_REL9_TAG: - { - if(pdu != 0) - { - pdu->rx_indication_rel9.tl = generic_tl; - if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0) - return 0; - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag ); - } - break; - } - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_pdus; ++idx) - { - if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length; - value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config); - if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0) - { - return 0; - } - } - } - - return 1; -} - -static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel8_t* preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) && - pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end)); -} - -static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel9_t* preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; - return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end); -} - -static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel13_t* preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; - return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end); -} - -static uint8_t unpack_rach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; - uint8_t* rachBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(rachBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0) - return 0; - - if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU); - return 0; - } - - if(value->number_of_preambles > 0) - { - value->preamble_list = (nfapi_preamble_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config); - if(value->preamble_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles); - return 0; - } - } - else - { - value->preamble_list = 0; - } - - - uint8_t i = 0; - for(i = 0; i < value->number_of_preambles; ++i) - { - nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value }, - { NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value }, - { NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel8_t* srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) && - pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) && - pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) && - pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end))) - return 0; - return 1; -} - -static uint8_t unpack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel9_t* srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; - return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end)); -} - -static uint8_t unpack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_ttd_rel10_t* srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; - return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end)); -} - -static uint8_t unpack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel11_t* srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; - return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end)); -} - -static uint8_t unpack_tdd_channel_measurement_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && - pull8(ppReadPackedMsg, &value->number_of_subbands, end) && - pull8(ppReadPackedMsg, &value->num_atennas, end))) - return 0; - - if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS) - { - // todo : add error - return 0; - } - - if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS) - { - // todo : add error - return 0; - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) && - pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end))) - return 0; - } - - return 1; -} - - -static uint8_t unpack_srs_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_body_t* value = (nfapi_srs_indication_body_t*)tlv; - uint8_t* srsBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(srsBodyEnd > end) - return 0; - - if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0) - return 0; - - if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU); - return 0; - } - - if(value->number_of_ues > 0) - { - value->srs_pdu_list = (nfapi_srs_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config); - if(value->srs_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues); - return 0; - } - } - else - { - value->srs_pdu_list = 0; - } - - - - uint8_t i = 0; - for(i = 0; i < value->number_of_ues; ++i) - { - nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); - - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value}, - { NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value}, - { NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value}, - { NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value}, - { NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value}, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; - uint8_t* srBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(srBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0) - return 0; - - if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU); - return 0; - } - - if(value->number_of_srs > 0) - { - value->sr_pdu_list = (nfapi_sr_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config); - if(value->sr_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs); - return 0; - } - } - else - { - value->sr_pdu_list = 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_srs; ++i) - { - nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0) - return 0; - } - - return 1; - -} - -static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} -static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end)); - -} - -static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end))) - return 0; - - if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n"); - return 0; - } - - if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end))) - return 0; - - return 1; -} - -static uint8_t unpack_cqi_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; - - // the cqiBodyEnd points to the end of the cqi PDU's - uint8_t* cqiBodyEnd = *ppReadPackedMsg + value->tl.length; - - //uint8_t* cqiPduEnd = cqiBodyEnd; - //uint8_t* numberOfPdusAddress = *ppReadPackedMsg; - - if(cqiBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0) - return 0; - - if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU); - return -1; - } - - if(value->number_of_cqis > 0) - { - value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config); - if(value->cqi_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); - return 0; - } - } - else - { - value->cqi_pdu_list = 0; - } - - if(value->number_of_cqis > 0) - { - value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config); - if(value->cqi_raw_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); - return 0; - } - } - else - { - value->cqi_raw_pdu_list = 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_cqis; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t)); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - while((uint8_t*)(*ppReadPackedMsg) < cqiPduInstanceEnd) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_RX_UE_INFORMATION_TAG: - pdu->rx_ue_information.tl = generic_tl; - if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) - return 0; - break; - case NFAPI_CQI_INDICATION_REL8_TAG: - pdu->cqi_indication_rel8.tl = generic_tl; - if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0) - return 0; - - break; - case NFAPI_CQI_INDICATION_REL9_TAG: - pdu->cqi_indication_rel9.tl = generic_tl; - if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0) - return 0; - - break; - case NFAPI_UL_CQI_INFORMATION_TAG: - pdu->ul_cqi_information.tl = generic_tl; - if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0) - return 0; - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag ); - } - break; - - }; - } - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_cqis; ++idx) - { - if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0) - return 0; - } - else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0) - return 0; - } - } - - - return 1; - -} - -static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} -static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->mp_cca, end) && - pull32(ppReadPackedMsg, &value->n_cca, end) && - pull32(ppReadPackedMsg, &value->offset, end) && - pull32(ppReadPackedMsg, &value->lte_txop_sf, end) && - pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) && - pull32(ppReadPackedMsg, &value->lbt_mode, end)); -} - -static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->offset, end) && - pull16(ppReadPackedMsg, &value->sfn_sf_end, end) && - pull32(ppReadPackedMsg, &value->lbt_mode, end)); -} - - -static uint8_t unpack_lbt_config_request_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU); - return 0; - } - - if(value->number_of_pdus) - { - value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config); - if(value->lbt_dl_config_req_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->lbt_dl_config_req_pdu_list = 0; - } - - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type); - return 0; - } - } - - return 1; -} -static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->result, end) && - pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) && - pull32(ppReadPackedMsg, &value->initial_partial_sf, end)); - -} -static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->result, end)); -} - -static uint8_t unpack_lbt_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config); - if(value->lbt_indication_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->lbt_indication_pdu_list = 0; - } - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type); - return 0; - } - } - - return 1; -} -static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_fdd_rel13_t* value = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; - return (pull8(ppReadPackedMsg, &value->harq_tb1, end)); -} - - -static uint8_t unpack_nb_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; - uint8_t* nbharqBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(nbharqBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) - return 0; - - if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); - return 0; - } - - value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config); - if(value->nb_harq_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_harqs; ++i) - { - nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value}, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_pdu_rel13_t* value = (nfapi_nrach_indication_pdu_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->initial_sc, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); -} - -static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){ +int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config) { + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; + + if (pMessageBuf == NULL || pPackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } + + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + + // look for the specific message + uint8_t result = 0; + + switch (pMessageHeader->message_id) { + case NFAPI_DL_CONFIG_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); + result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UL_CONFIG_REQUEST: + result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TX_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); + result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_HI_DCI0_REQUEST: + result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_HARQ_INDICATION: + result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_CRC_INDICATION: + result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_ULSCH_INDICATION: + //printf("RX ULSCH\n"); + result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RACH_INDICATION: + result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SRS_INDICATION: + result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_SR_INDICATION: + result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_CQI_INDICATION: + result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_INDICATION: + result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NB_HARQ_INDICATION: + result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NRACH_INDICATION: + result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_DL_NODE_SYNC: + result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UL_NODE_SYNC: + result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->pack_p7_vendor_extension) { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + if(result == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } else { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; + + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; + + if(1) { + //quick test + if(pMessageHeader->message_length != packedMsgLen) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } + + return (packedMsgLen); +} + +// Unpack routines +// NR: +static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *)tlv; + return( + pull16(ppReadPackedMsg, &value->bwp_size, end) && + pull16(ppReadPackedMsg, &value->bwp_start, end) && + pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && + pull16(ppReadPackedMsg, &value->start_rb, end) && + pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && + pull8(ppReadPackedMsg, &value->csi_type, end) && + pull8(ppReadPackedMsg, &value->row, end) && + pull16(ppReadPackedMsg, &value->freq_domain, end) && + pull8(ppReadPackedMsg, &value->symb_l0, end) && + pull8(ppReadPackedMsg, &value->symb_l1, end) && + pull8(ppReadPackedMsg, &value->cdm_type, end) && + pull8(ppReadPackedMsg, &value->freq_density, end) && + pull16(ppReadPackedMsg, &value->scramb_id, end) && + pull8(ppReadPackedMsg, &value->power_control_offset, end) && + pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) + ); +} + + +static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + + nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && + + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) + return 0; } - else{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->BWPSize, end) && + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && + pull8(ppReadPackedMsg, &value->RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->CoreSetType, end) && + pull16(ppReadPackedMsg, &value->ShiftIndex, end) && + pull8(ppReadPackedMsg, &value->precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->numDlDci, end)); +} + + + +static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t *)tlv; + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->pduBitmap, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->pduIndex, end) && + pull16(ppReadPackedMsg, &value->BWPSize, end) && + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && + pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && + pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && + pull16(ppReadPackedMsg, &value->dataScramblingId, end) && + pull8(ppReadPackedMsg, &value->nrOfLayers, end) && + pull8(ppReadPackedMsg, &value->transmissionScheme, end) && + pull8(ppReadPackedMsg, &value->refPoint, end) && + pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && + pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && + pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && + pull8(ppReadPackedMsg, &value->SCID, end) && + pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && + pull16(ppReadPackedMsg, &value->dmrsPorts, end) && + pull8(ppReadPackedMsg, &value->resourceAlloc, end) && + pull16(ppReadPackedMsg, &value->rbStart, end) && + pull16(ppReadPackedMsg, &value->rbSize, end) && + pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && + pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && + pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSReOffset, end) + ); +} + + +static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_dl_tti_ssb_pdu_rel15_t *value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t *)tlv; + return( + pull16(ppReadPackedMsg, &value->PhysCellId, end) && + pull8(ppReadPackedMsg, &value->BetaPss, end) && + pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && + pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && + pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && + pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && + pull32(ppReadPackedMsg, &value->bchPayload, end) + // TODO: pack precoding_and_beamforming too + ); +} + + +// LTE: +static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel8_t *dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) && + pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) && + pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel9_t *dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t *)tlv; + return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel10_t *dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel11_t *dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel12_t *dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) && + pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end)); +} + +static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end) { + if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && + pull8(ppReadPackedMsg, &value->number_of_subbands, end) && + pull8(ppReadPackedMsg, &value->num_antennas, end))) + return 0; + + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_subbands; ++idx) { + nfapi_dl_config_dci_dl_tpm_subband_info_t *subband_info = &(value->subband_info[idx]); + + if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) && + pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end))) + return 0; + + uint8_t antenna_idx = 0; + uint8_t scheduled_ue_idx = 0; + + for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) { + for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) { + if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end)) + return 0; + } + } + } + + return 1; +} + + +static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dci_dl_pdu_rel13_t *dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t *)tlv; + // If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been + // added + uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5; + dci_dl_pdu_rel13->tpm_struct_flag = 0; + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && + ( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) && + ( (tpm_struct_flag_present == 1 && dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1)); +} + +static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_bch_pdu_rel8_t *bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t *)tlv; + return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&bch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_mch_pdu_rel8_t *mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t *)tlv; + return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&mch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end)); +} + +static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel8_t *dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t *)tlv; + + if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&dlsch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) && + pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end))) + return 0; + + uint16_t j = 0; + + for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j) { + if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) && + pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end))) + return 0; + } + + return 1; +} +static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel9_t *dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) ); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel10_t *dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && + pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ; +} +static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel11_t *dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end)); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel12_t *dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end)); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_dlsch_pdu_rel13_t *dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t *)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end)); +} + +static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_pch_pdu_rel8_t *pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t *)tlv; + return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&pch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end)); +} +static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_pch_pdu_rel13_t *pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t *)tlv; + return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end)); +} + +static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_prs_pdu_rel9_t *prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t *)tlv; + return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end)); +} + +static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_csi_rs_pdu_rel10_t *csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t *)tlv; + return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) && + pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) && + pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) && + pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end)); +} + +static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_csi_rs_pdu_rel13_t *csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t *)tlv; + + if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end))) + return 0; + + uint16_t idx =0; + + for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx) { + if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end))) + return 0; + + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n"); + //pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??); + } + + return 1; +} + +static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_epdcch_parameters_rel11_t *epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t *)tlv; + return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) && + pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) && + pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) && + pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end)); +} + +static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_epdcch_parameters_rel13_t *epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t *)tlv; + return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end)); +} + +static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_mpdcch_pdu_rel13_t *mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t *)tlv; + return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) && + pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end)); +} + + +static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_nbch_pdu_rel13_t *nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t *)tlv; + return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&nbch_params_rel13->pdu_index, end) && + pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) && + pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end)); +} + +static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_npdcch_pdu_rel13_t *npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t *)tlv; + return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&npdcch_params_rel13->pdu_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end)); +} + +static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_dl_config_ndlsch_pdu_rel13_t *ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t *)tlv; + return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&ndlsch_params_rel13->pdu_index, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); +} + + +static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_dl_tti_request_pdu_t *value = (nfapi_nr_dl_tti_request_pdu_t *)msg; + + if(!(pull32(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->PDUType, end) )) + return 0; + + // first match the pdu type, then call the respective function + switch(value->PDUType) { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: { + if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: { + if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { + if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: { + if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; +} + + + + +static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_dl_config_request_body_t *value = (nfapi_dl_config_request_body_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) && + pull8(ppReadPackedMsg, &value->number_dci, end) && + pull16(ppReadPackedMsg, &value->number_pdu, end) && + pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) && + pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end))) + return 0; + + if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU); + return 0; + } + + if(value->number_pdu) { + value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config); + + if(value->dl_config_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu); + return 0; + } + } else { + value->dl_config_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_pdu; + + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_dl_config_request_pdu_t *pdu = &(value->dl_config_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) { + // pdu end of beyond buffer end + return 0; + } + + switch(pdu->pdu_type) { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + default: + // Need to log an error + break; + } + } + + return 1; +} + + +static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t *)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && + pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe,256,pNfapiMsg->dl_tti_request_body.nGroup, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + + for(int i=0; idl_tti_request_body.nGroup; i++) { + for(int j=0; jdl_tti_request_body.nUe[i]; j++) { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + + if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) + return 0; + } + + for(int i=0; idl_tti_request_body.nPDUs; i++) { + if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + return 0; + } + + return 1; +} + + +static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_prach_pdu_t *prach_pdu = (nfapi_nr_prach_pdu_t *)tlv; + return( + pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && + pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_pucch_pdu_t *pucch_pdu = (nfapi_nr_pucch_pdu_t *)tlv; + return( + pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && + pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && + pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && + pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && + pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && + pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && + pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && + pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_pusch_pdu_t *pusch_pdu = (nfapi_nr_pusch_pdu_t *)tlv; + + if (!( + pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && + pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && + pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && + pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && + pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && + pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && + pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && + pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && + pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && + pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && + pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map) { + case PUSCH_PDU_BITMAP_PUSCH_DATA: { + // pack optional TLVs + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && + pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && + pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: { + return( + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: { + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && + + pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && + + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: { + return( + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) + ); + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + + +static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_srs_pdu_t *srs_pdu = (nfapi_nr_srs_pdu_t *)tlv; + return( + pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && + pull32(ppReadPackedMsg, &srs_pdu->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && + pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && + pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && + pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_ul_tti_request_number_of_pdus_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t *)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) + return 0; + + // first natch the pdu type, then call the respective function + switch(pNfapiMsg->pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { + if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: { + if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: { + if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: { + if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); + } + break; + } + + return 1; +} + + +static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_ul_tti_request_number_of_groups_t *pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t *)msg; + + if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) + return 0; + + for (int i = 0; i < pNfapiMsg->n_ue; i++) { + if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx,end) ) + return 0; + } + + return 1; +} + + +static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t *)msg; + + if (!( + pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end) )) + return 0; + + for(int i=0; i< pNfapiMsg->n_pdus; i++) { + if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) + return 0; + } + + for(int i=0; i< pNfapiMsg->n_group; i++) { + if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) + return 0; + } + + return 1; +} + + + +static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value}, + }; + return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel8_t *ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t *)tlv; + return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); +} + +static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel10_t *ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) & + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end)); +} +static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel11_t *ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t *)tlv; + return ( pull8(ppReadPackedMsg, &ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel11->dmrs_config_flag, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end)); +} +static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_pdu_rel13_t *ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &ulsch_pdu_rel13->ue_type, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end)); +} +static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel8_t *cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end)); +} + +static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel9_t *cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end))) + return 0; + + switch(cqi_ri_info_rel9->report_type) { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: { + if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end))) + return 0; + } + break; + + case NFAPI_CSI_REPORT_TYPE_APERIODIC: { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0) + return 0; + + uint8_t i; + + for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0) + return 0; + + uint8_t j; + + for(j = 0; j < 8; ++j) { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0) + return 0; + } + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); + return 0; + } + break; + }; + + return 1; +} + +// NOTE : This function is a little unconventional as we uese the side to +// determine the report type +static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_ri_information_rel13_t *cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t *)tlv; + + if(cqi_ri_info_rel13->tl.length == 0) { + cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC; + } else { + cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC; + + if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0) + return 0; + } + + return 1; +} +static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_initial_transmission_parameters_rel8_t *init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) && + pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end)); +} +static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_harq_information_rel10_t *harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) && + pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end)); +} + +static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ulsch_harq_information_rel13_t *harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t *)tlv; + return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end)); +} + +static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel8_t *ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t *)tlv; + return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) && + pull16(ppReadPackedMsg, (uint16_t *)&ue_info_rel8->rnti, end)); +} +static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel11_t *ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t *)tlv; + return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) && + pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end)); +} +static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_ue_information_rel13_t *ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) && + pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) && + pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) && + pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end)); +} + +static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel8_t *cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t *)tlv; + return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) && + pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end)); +} +static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel10_t *cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) && + pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end)); +} +static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_cqi_information_rel13_t *cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) && + pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end)); +} + +static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_sr_information_rel8_t *sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t *)tlv; + return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end)); +} + +static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_sr_information_rel10_t *sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel10_tdd_t *harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t *)tlv; + return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) && + pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel8_fdd_t *harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t *)tlv; + return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel9_fdd_t *harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t *)tlv; + return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel11_t *harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t *)tlv; + return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_harq_information_rel13_t *harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t *)tlv; + return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end)); +} + + +static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel8_t *srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t *)tlv; + return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end)); +} + +static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel10_t *srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t *)tlv; + return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end); +} + +static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_srs_pdu_rel13_t *srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end)); +} + +static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_nb_harq_information_rel13_fdd_t *nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t *)tlv; + return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end)); +} + +static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_nulsch_pdu_rel13_t *nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && + pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end))) + return 0; + + unpack_tlv_t unpack_fns[] = { + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, + { NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value}, + }; + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0); +} + +static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_config_nrach_pdu_rel13_t *nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) && + pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) && + pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end)); +} + + +static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { +#define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, +#define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value}, +#define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value}, +#define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value}, +#define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, +#define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value}, +#define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value}, +#define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value}, +#define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value}, +#define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value}, +#define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value}, + nfapi_ul_config_request_body_t *value = (nfapi_ul_config_request_body_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) && + pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) && + pull8(ppReadPackedMsg, &value->srs_present, end))) + return 0; + + if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) { + value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config); + + if(value->ul_config_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } else { + value->ul_config_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_ul_config_request_pdu_t *pdu = &(value->ul_config_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) { + // pdu end is past buffer end + return 0; + } + + switch(pdu->pdu_type) { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu) + UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu) + UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu) + UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information) + UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu) + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + } + } + + return 1; +} + + +static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_hi_pdu_rel8_t *hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t *)tlv; + return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) && + pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_hi_pdu_rel10_t *hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel8_t *dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) && + pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) && + pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) && + pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel10_t *dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_dci_pdu_rel12_t *dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t *)tlv; + return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end)); +} + +static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) && + pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) && + pull8(ppReadPackedMsg, &value->resource_block_assignment, end) && + pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) && + pull8(ppReadPackedMsg, &value->start_symbol, end) && + pull8(ppReadPackedMsg, &value->ecce_index, end) && + pull8(ppReadPackedMsg, &value->aggreagation_level, end) && + pull8(ppReadPackedMsg, &value->rnti_type, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->ce_mode, end) && + pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) && + pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) && + pull16(ppReadPackedMsg, &value->transmission_power, end) && + pull8(ppReadPackedMsg, &value->dci_format, end) && + pull8(ppReadPackedMsg, &value->resource_block_start, end) && + pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &value->mcs, end) && + pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) && + pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) && + pull8(ppReadPackedMsg, &value->new_data_indication, end) && + pull8(ppReadPackedMsg, &value->harq_process, end) && + pull8(ppReadPackedMsg, &value->redudency_version, end) && + pull8(ppReadPackedMsg, &value->tpc, end) && + pull8(ppReadPackedMsg, &value->csi_request, end) && + pull8(ppReadPackedMsg, &value->ul_inex, end) && + pull8(ppReadPackedMsg, &value->dai_presence_flag, end) && + pull8(ppReadPackedMsg, &value->dl_assignment_index, end) && + pull8(ppReadPackedMsg, &value->srs_request, end) && + pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) && + pull32(ppReadPackedMsg, &value->tcp_bitmap, end) && + pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) && + pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) && + pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end)); +} + +static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_hi_dci0_npdcch_dci_pdu_rel13_t *value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &value->ncce_index, end) && + pull8(ppReadPackedMsg, &value->aggregation_level, end) && + pull8(ppReadPackedMsg, &value->start_symbol, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) && + pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) && + pull8(ppReadPackedMsg, &value->subcarrier_indication, end) && + pull8(ppReadPackedMsg, &value->resource_assignment, end) && + pull8(ppReadPackedMsg, &value->scheduling_delay, end) && + pull8(ppReadPackedMsg, &value->mcs, end) && + pull8(ppReadPackedMsg, &value->redudancy_version, end) && + pull8(ppReadPackedMsg, &value->repetition_number, end) && + pull8(ppReadPackedMsg, &value->new_data_indicator, end) && + pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end)); +} + +static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_hi_dci0_request_body_t *value = (nfapi_hi_dci0_request_body_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) && + pull8(ppReadPackedMsg, &value->number_of_dci, end) && + pull8(ppReadPackedMsg, &value->number_of_hi, end))) + return 0; + + uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci; + + if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU); + return 0; + } + + if(totalNumPdus > 0) { + value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config); + + if(value->hi_dci0_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus); + return 0; + } + } else { + value->hi_dci0_pdu_list = 0; + } + + uint8_t i; + + for(i = 0; i < totalNumPdus; ++i) { + nfapi_hi_dci0_request_pdu_t *pdu = &(value->hi_dci0_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) { + // pdu end if past buffer end + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end); + return 0; + } + + switch(pdu->pdu_type) { + case NFAPI_HI_DCI0_HI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_HI_DCI0_DCI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, + { NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + } + + return 1; +} +//unpack_ul_dci_pdu_list_value + +static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && + + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && + + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) + + return 0; + } + + return (pull16(ppReadPackedMsg, &value->PDUType, end) && + pull16(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); + +} + +static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t *)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) + )) + return 0; + + for(int i=0; i< pNfapiMsg->numPdus; i++) { + if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) + return 0; + } + + return 1; +} + +static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { + nfapi_nr_pdu_t *pNfapiMsg = (nfapi_nr_pdu_t *)msg; + + if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) + )) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; + + for(; i < total_number_of_tlvs; ++i) { + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) + return 0; + + switch(pNfapiMsg->TLVs[i].tag) { + case 0: { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, 16384, pNfapiMsg->TLVs[i].length, end)) + return 0; + + break; + } + + case 1: { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, pNfapiMsg->TLVs[i].length, pNfapiMsg->TLVs[i].length, end)) + return 0; + + break; + } + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); + break; + } + } + } + + return 1; +} + +static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) + return 0; + + for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) { + if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) + return 0; + } + + return 1; +} + +static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + uint8_t proceed = 1; + nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t *)msg; + + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; + + while (((uint8_t *)(*ppReadPackedMsg) < end) && proceed) { + nfapi_tl_t generic_tl; + + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) { + case NFAPI_TX_REQUEST_BODY_TAG: { + pNfapiMsg->tx_request_body.tl = generic_tl; + + if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0) + return 0; + + if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU); + return 0; + } + + if(pNfapiMsg->tx_request_body.number_of_pdus > 0) { + pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config); + + if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus); + return 0; + } + } else { + pNfapiMsg->tx_request_body.tx_pdu_list = 0; + } + + uint16_t i; + uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus; + + for(i = 0; i < totalNumPdus; ++i) { + nfapi_tx_request_pdu_t *pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); + + if (pdu) { + uint16_t length = 0; + uint16_t index = 0; + + if(!(pull16(ppReadPackedMsg, &length, end) && + pull16(ppReadPackedMsg, &index, end))) + return 0; + + pdu->pdu_length = length; + pdu->pdu_index = index; + // TODO : May need to rethink this bit + pdu->num_segments = 1; + pdu->segments[0].segment_length = pdu->pdu_length; + pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); + + if(pdu->segments[0].segment_data) { + if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) + return 0; + + if (pdu->segments[0].segment_length == 3) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, + pdu->segments[0].segment_data[0], + pdu->segments[0].segment_data[1], + pdu->segments[0].segment_data[2] + ); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); + } + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + +//UNPACK NR UPLINK INDICATION FUNCTIONS + +//SLOT INDICATION + +static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_slot_indication_scf_t *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) + )) + return 0; + +return 1; +} + +//RX DATA INDICATION + +static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull16(ppReadPackedMsg, &value->pdu_length, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + return 1; +} + + +static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_rx_data_indication_body(pNfapiMsg->pdu_list, ppReadPackedMsg, end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t* value, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull8(ppReadPackedMsg, &value->tb_crc_status, end) && + pull16(ppReadPackedMsg, &value->num_cb, end) && + //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + + //memcpy((nfapi_nr_crc_t *)tlv,value,sizeof(nfapi_nr_crc_t)); + + return 1; +} + +static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_crc_indication_t *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *) msg; + // pNfapiMsg = (nfapi_nr_crc_indication_t *) malloc(sizeof(nfapi_nr_crc_indication_t)); + // pNfapiMsg->crc_list = (nfapi_nr_crc_t *) malloc(sizeof(nfapi_nr_crc_t)); + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!unpack_nr_crc_indication_body(pNfapiMsg->crc_list,ppReadPackedMsg,end)) + //if(!unpack_nr_crc_indication_body(value,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t unpack_nr_srs_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->num_symbols, end) && + pull8(ppReadPackedMsg, &value->wide_band_snr, end) && + pull8(ppReadPackedMsg, &value->num_reported_symbols, end) && + pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list->rb_snr, end) + )) + return 0; } return 1; } -static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; - uint8_t* nrachBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(nrachBodyEnd > end) - return 0; - - if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0) - return 0; - - if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU); - return 0; - } - - value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config); - if(value->nrach_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_initial_scs_detected; ++i) - { - nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); - - uint8_t* nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value}, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -// unpack length check - -static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t)) - retLen = sizeof(nfapi_dl_config_request_t); - break; - - case NFAPI_UL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t)) - retLen = sizeof(nfapi_ul_config_request_t); - break; - - case NFAPI_SUBFRAME_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) - retLen = sizeof(nfapi_subframe_indication_t); - break; - - case NFAPI_HI_DCI0_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t)) - retLen = sizeof(nfapi_hi_dci0_request_t); - break; - - case NFAPI_TX_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_tx_request_t)) - retLen = sizeof(nfapi_tx_request_t); - break; - - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); - break; - - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); - break; - - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); - break; - - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; - - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; - - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; - - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - - case NFAPI_DL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t)) - retLen = sizeof(nfapi_dl_node_sync_t); - break; - - case NFAPI_UL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t)) - retLen = sizeof(nfapi_ul_node_sync_t); - break; - - case NFAPI_TIMING_INFO: - if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) - retLen = sizeof(nfapi_timing_info_t); - break; +static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR RACH + +static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && + pull8(ppReadPackedMsg, &value->symbol_index, end) && + pull8(ppReadPackedMsg, &value->slot_index, end) && + pull8(ppReadPackedMsg, &value->freq_index, end) && + pull8(ppReadPackedMsg, &value->avg_rssi, end) && + pull8(ppReadPackedMsg, &value->avg_snr, end) && + pull8(ppReadPackedMsg, &value->num_preamble, end) + )) + return 0; + value->preamble_list = (nfapi_nr_prach_indication_preamble_t*) malloc(sizeof(nfapi_nr_prach_indication_preamble_t) * value->num_preamble); + for(int i = 0; i < value->num_preamble; i++) + { + if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && + pull16(ppReadPackedMsg, &value->preamble_list->timing_advance, end) && + pull32(ppReadPackedMsg, &value->preamble_list->preamble_pwr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rach_indication_t* msg, nfapi_p7_codec_config_t* config) { + + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + pNfapiMsg->pdu_list = (nfapi_nr_prach_indication_pdu_t*) malloc(sizeof(nfapi_nr_prach_indication_pdu_t) * pNfapiMsg->number_of_pdus); + for(int i=0; i< pNfapiMsg->number_of_pdus;i++) + { + if(!unpack_nr_rach_indication_body(pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR UCI + +static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + // uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message uci_0_1 indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + value->sr = (nfapi_nr_sr_pdu_0_1_t*) malloc(sizeof(nfapi_nr_sr_pdu_0_1_t)); + if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && + pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + value->harq = (nfapi_nr_harq_pdu_0_1_t*) malloc(sizeof(nfapi_nr_harq_pdu_0_1_t)); + if(!(pull8(ppReadPackedMsg, &value->harq->num_harq, end) && + pull8(ppReadPackedMsg, &value->harq->harq_confidence_level, end) + )) + return 0; + value->harq->harq_list = (nfapi_nr_harq_t*) malloc(sizeof(nfapi_nr_harq_t*) * value->harq->num_harq); + for(int i=0; iharq->num_harq;i++) + { + if(!(pull8(ppReadPackedMsg, &value->harq->harq_list->harq_value, end) + )) + return 0; + } + } + + return 1; +} + + +static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end))) + return 0; + + value->sr.sr_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->sr.sr_bit_len/8))); + + if(!(pullarray8(ppReadPackedMsg, &value->sr.sr_payload[0], (int)(value->sr.sr_bit_len / 8), (int)(value->sr.sr_bit_len / 8), end))) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) && + (pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end))) + return 0; + + value->harq.harq_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->harq.harq_bit_len/8 ))); + + if(!(pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8), (int)(value->harq.harq_bit_len / 8), end))) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) && + (pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end))) + return 0; + + value->csi_part1.csi_part1_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->csi_part1.csi_part1_bit_len/8))); + +// if(!(pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8), (int)(value->csi_part1.csi_part1_bit_len / 8), end))) +// return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) && + (pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end))) + return 0; + + value->csi_part2.csi_part2_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->csi_part2.csi_part2_bit_len/8 ))); + + if(!(pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) , (int)(value->csi_part2.csi_part2_bit_len / 8) , end))) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication_body(nfapi_nr_uci_t* value, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && + pull16(ppReadPackedMsg, &value->pdu_size, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; + unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!unpack_nr_uci_indication_body(pNfapiMsg->uci_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + uint8_t proceed = 1; + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t *)msg; + + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; + + while (((uint8_t *)(*ppReadPackedMsg) < end) && proceed) { + nfapi_tl_t generic_tl; + + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) { + case NFAPI_UE_RELEASE_BODY_TAG: { + pNfapiMsg->ue_release_request_body.tl = generic_tl; + + if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) + return 0; + + if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); + return 0; + } else { + uint8_t j; + uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; + + for(j = 0; j < num; ++j) { + if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0) { + return 0; + } + } + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + +static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_harq_data_bundling_t *value = (nfapi_harq_indication_tdd_harq_data_bundling_t *)tlv; + return (pull8(ppReadPackedMsg, &value->value_0, end) && + pull8(ppReadPackedMsg, &value->value_1, end)); +} + +static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_harq_data_multiplexing_t *value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t *)tlv; + return (pull8(ppReadPackedMsg, &value->value_0, end) && + pull8(ppReadPackedMsg, &value->value_1, end) && + pull8(ppReadPackedMsg, &value->value_2, end) && + pull8(ppReadPackedMsg, &value->value_3, end)); +} +static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_harq_data_special_bundling_t *value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t *)tlv; + return ( pull8(ppReadPackedMsg, &value->value_0, end)); +} +static uint8_t unpack_harq_indication_tdd_harq_data(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_harq_data_t *value = (nfapi_harq_indication_tdd_harq_data_t *)tlv; + return (pull8(ppReadPackedMsg, &value->value_0, end)); +} + +static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel8_t *value = (nfapi_harq_indication_tdd_rel8_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + uint8_t result = 0; + + switch(value->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = 1; + break; + + default: + // TODO add error message + return 0; + break; + } + + return result; +} + +static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel9_t *value = (nfapi_harq_indication_tdd_rel9_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) { + // TODO : add error message + return 0; + } + + uint16_t idx = 0; + + for(idx = 0; idx < value->number_of_ack_nack; ++idx) { + uint8_t result = 0; + + switch(value->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); + break; + + default: + // TODO add error message + return 0; + break; + } + + if(result == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_tdd_rel13_t *value = (nfapi_harq_indication_tdd_rel13_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull16(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) { + // TODO : add error message + return 0; + } + + uint16_t idx = 0; + + for(idx = 0; idx < value->number_of_ack_nack; ++idx) { + uint8_t result = 0; + + switch(value->mode) { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end); + break; + + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end); + break; + + default: + // TODO add error message + return 0; + break; + } + + if(result == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel8_t *value = (nfapi_harq_indication_fdd_rel8_t *)tlv; + return (pull8(ppReadPackedMsg, &value->harq_tb1, end) && + pull8(ppReadPackedMsg, &value->harq_tb2, end)); +} + +static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel9_t *value = (nfapi_harq_indication_fdd_rel9_t *)tlv; + return (pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) && + pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end)); +} + +static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_harq_indication_fdd_rel13_t *value = (nfapi_harq_indication_fdd_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &value->mode, end) && + pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) && + pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end)); +} + +static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_ul_cqi_information_t *value = (nfapi_ul_cqi_information_t *)tlv; + return (pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull8(ppReadPackedMsg, &value->channel, end)); +} + + + +static uint8_t unpack_harq_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_harq_indication_body_t *value = (nfapi_harq_indication_body_t *)tlv; + uint8_t *harqBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(harqBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) + return 0; + + if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); + return 0; + } + + value->harq_pdu_list = (nfapi_harq_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config); + + if(value->harq_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); + return 0; + } + + uint8_t i = 0; + + for(i = 0; i < value->number_of_harqs; ++i) { + nfapi_harq_indication_pdu_t *pdu = &(value->harq_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value}, + { NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value}, + { NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value}, + { NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value}, + { NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value}, + { NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value}, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_crc_indication_rel8_t *crc_pdu_rel8 = (nfapi_crc_indication_rel8_t *)tlv; + return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) ); +} + +static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_crc_indication_body_t *value = (nfapi_crc_indication_body_t *)tlv; + uint8_t *crcBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(crcBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0) + return 0; + + if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU); + return 0; + } + + if(value->number_of_crcs > 0) { + value->crc_pdu_list = (nfapi_crc_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config); + + if(value->crc_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs); + return 0; + } + } else { + value->crc_pdu_list = 0; + } + + uint8_t i = 0; + + for(i = 0; i < value->number_of_crcs; ++i) { + nfapi_crc_indication_pdu_t *pdu = &(value->crc_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rx_indication_rel8_t *value = (nfapi_rx_indication_rel8_t *)tlv; + return (pull16(ppReadPackedMsg, &value->length, end) && + pull16(ppReadPackedMsg, &value->offset, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end)); +} +static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_rx_indication_rel9_t *value = (nfapi_rx_indication_rel9_t *)tlv; + return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end)); +} + +static uint8_t unpack_rx_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_rx_indication_body_t *value = (nfapi_rx_indication_body_t *)tlv; + // the rxBodyEnd points to the end of the cqi PDU's + uint8_t *rxBodyEnd = *ppReadPackedMsg + value->tl.length; + uint8_t *rxPduEnd = rxBodyEnd; + uint8_t *numberOfPdusAddress = *ppReadPackedMsg; + + if(rxBodyEnd > end) { + // pdu end is past buffer end + return 0; + } + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) { + value->rx_pdu_list = (nfapi_rx_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config); + + if(value->rx_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } else { + value->rx_pdu_list = 0; + } + + uint8_t i = 0; + nfapi_rx_indication_pdu_t *pdu = 0; + + while((uint8_t *)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t *)(*ppReadPackedMsg) < rxPduEnd) { + nfapi_tl_t generic_tl; + + if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) { + case NFAPI_RX_UE_INFORMATION_TAG: { + pdu = &(value->rx_pdu_list[i++]); + pdu->rx_ue_information.tl = generic_tl; + + if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) + return 0; + } + break; + + case NFAPI_RX_INDICATION_REL8_TAG: { + if(pdu != 0) { + pdu->rx_indication_rel8.tl = generic_tl; + + if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0) + return 0; + + if(pdu->rx_indication_rel8.offset > 0) { + // Need to check that the data is within the tlv + if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd) { + // If this the first pdu set the rxPduEnd + if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd) { + rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset; + + if(rxPduEnd > end) { + // pdu end is past buffer end + return 0; + } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n"); + } + } + } + } + break; + + case NFAPI_RX_INDICATION_REL9_TAG: { + if(pdu != 0) { + pdu->rx_indication_rel9.tl = generic_tl; + + if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0) + return 0; + } + } + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag ); + } + break; + } + } + + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_pdus; ++idx) { + if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) { + uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length; + value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config); + + if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0) { + return 0; + } + } + } + + return 1; +} + +static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel8_t *preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t *)tlv; + return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) && + pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end)); +} + +static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel9_t *preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t *)tlv; + return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end); +} + +static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_preamble_pdu_rel13_t *preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t *)tlv; + return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end); +} + +static uint8_t unpack_rach_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_rach_indication_body_t *value = (nfapi_rach_indication_body_t *)tlv; + uint8_t *rachBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(rachBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0) + return 0; + + if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU); + return 0; + } + + if(value->number_of_preambles > 0) { + value->preamble_list = (nfapi_preamble_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config); + + if(value->preamble_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles); + return 0; + } + } else { + value->preamble_list = 0; + } + + uint8_t i = 0; + + for(i = 0; i < value->number_of_preambles; ++i) { + nfapi_preamble_pdu_t *pdu = &(value->preamble_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value }, + { NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value }, + { NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_srs_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel8_t *srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) && + pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) && + pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) && + pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end))) + return 0; + + return 1; +} + +static uint8_t unpack_srs_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel9_t *srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t *)tlv; + return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end)); +} + +static uint8_t unpack_srs_indication_tdd_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_srs_indication_ttd_rel10_t *srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t *)tlv; + return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end)); +} + +static uint8_t unpack_srs_indication_fdd_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_srs_indication_fdd_rel11_t *srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t *)tlv; + return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end)); +} + +static uint8_t unpack_tdd_channel_measurement_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_tdd_channel_measurement_t *value = (nfapi_tdd_channel_measurement_t *)tlv; + + if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && + pull8(ppReadPackedMsg, &value->number_of_subbands, end) && + pull8(ppReadPackedMsg, &value->num_atennas, end))) + return 0; + + if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS) { + // todo : add error + return 0; + } + + if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS) { + // todo : add error + return 0; + } + + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_subbands; ++idx) { + if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) && + pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end))) + return 0; + } + + return 1; +} + + +static uint8_t unpack_srs_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t *)tlv; + uint8_t *srsBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(srsBodyEnd > end) + return 0; + + if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0) + return 0; + + if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU); + return 0; + } + + if(value->number_of_ues > 0) { + value->srs_pdu_list = (nfapi_srs_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config); + + if(value->srs_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues); + return 0; + } + } else { + value->srs_pdu_list = 0; + } + + uint8_t i = 0; + + for(i = 0; i < value->number_of_ues; ++i) { + nfapi_srs_indication_pdu_t *pdu = &(value->srs_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value}, + { NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value}, + { NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value}, + { NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value}, + { NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value}, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_sr_indication_body_t *value = (nfapi_sr_indication_body_t *)tlv; + uint8_t *srBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(srBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0) + return 0; + + if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU); + return 0; + } + + if(value->number_of_srs > 0) { + value->sr_pdu_list = (nfapi_sr_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config); + + if(value->sr_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs); + return 0; + } + } else { + value->sr_pdu_list = 0; + } + + uint8_t i = 0; + + for(i = 0; i < value->number_of_srs; ++i) { + nfapi_sr_indication_pdu_t *pdu = &(value->sr_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_cqi_indication_rel8_t *cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t *)tlv; + return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end)); +} + +static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_cqi_indication_rel9_t *cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t *)tlv; + + if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end))) + return 0; + + if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n"); + return 0; + } + + if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end))) + return 0; + + return 1; +} + +static uint8_t unpack_cqi_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_cqi_indication_body_t *value = (nfapi_cqi_indication_body_t *)tlv; + // the cqiBodyEnd points to the end of the cqi PDU's + uint8_t *cqiBodyEnd = *ppReadPackedMsg + value->tl.length; + + //uint8_t* cqiPduEnd = cqiBodyEnd; + //uint8_t* numberOfPdusAddress = *ppReadPackedMsg; + + if(cqiBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0) + return 0; + + if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU); + return -1; + } + + if(value->number_of_cqis > 0) { + value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config); + + if(value->cqi_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); + return 0; + } + } else { + value->cqi_pdu_list = 0; + } + + if(value->number_of_cqis > 0) { + value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config); + + if(value->cqi_raw_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); + return 0; + } + } else { + value->cqi_raw_pdu_list = 0; + } + + uint8_t i = 0; + + for(i = 0; i < value->number_of_cqis; ++i) { + nfapi_cqi_indication_pdu_t *pdu = &(value->cqi_pdu_list[i]); + memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t)); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + while((uint8_t *)(*ppReadPackedMsg) < cqiPduInstanceEnd) { + nfapi_tl_t generic_tl; + + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) { + case NFAPI_RX_UE_INFORMATION_TAG: + pdu->rx_ue_information.tl = generic_tl; + + if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) + return 0; + + break; + + case NFAPI_CQI_INDICATION_REL8_TAG: + pdu->cqi_indication_rel8.tl = generic_tl; + + if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0) + return 0; + + break; + + case NFAPI_CQI_INDICATION_REL9_TAG: + pdu->cqi_indication_rel9.tl = generic_tl; + + if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0) + return 0; + + break; + + case NFAPI_UL_CQI_INFORMATION_TAG: + pdu->ul_cqi_information.tl = generic_tl; + + if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0) + return 0; + + break; + + default: { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag ); + } + break; + }; + } + } + + uint8_t idx = 0; + + for(idx = 0; idx < value->number_of_cqis; ++idx) { + if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) { + if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0) + return 0; + } else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) { + if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0) + return 0; + } + } + + return 1; +} + +static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lbt_pdsch_req_pdu_rel13_t *value = (nfapi_lbt_pdsch_req_pdu_rel13_t *)tlv; + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->mp_cca, end) && + pull32(ppReadPackedMsg, &value->n_cca, end) && + pull32(ppReadPackedMsg, &value->offset, end) && + pull32(ppReadPackedMsg, &value->lte_txop_sf, end) && + pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) && + pull32(ppReadPackedMsg, &value->lbt_mode, end)); +} + +static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lbt_drs_req_pdu_rel13_t *value = (nfapi_lbt_drs_req_pdu_rel13_t *)tlv; + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->offset, end) && + pull16(ppReadPackedMsg, &value->sfn_sf_end, end) && + pull32(ppReadPackedMsg, &value->lbt_mode, end)); +} + + +static uint8_t unpack_lbt_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_config_request_body_t *value = (nfapi_lbt_dl_config_request_body_t *)tlv; + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU); + return 0; + } + + if(value->number_of_pdus) { + value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config); + + if(value->lbt_dl_config_req_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } else { + value->lbt_dl_config_req_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_lbt_dl_config_request_pdu_t *pdu = &(value->lbt_dl_config_req_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type); + return 0; + } + } + + return 1; +} +static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lbt_pdsch_rsp_pdu_rel13_t *value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t *)tlv; + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->result, end) && + pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) && + pull32(ppReadPackedMsg, &value->initial_partial_sf, end)); +} +static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_lbt_drs_rsp_pdu_rel13_t *value = (nfapi_lbt_drs_rsp_pdu_rel13_t *)tlv; + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->result, end)); +} + +static uint8_t unpack_lbt_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_indication_body_t *value = (nfapi_lbt_dl_indication_body_t *)tlv; + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) { + value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config); + + if(value->lbt_indication_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } else { + value->lbt_indication_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + + for(i = 0; i < total_number_of_pdus; ++i) { + nfapi_lbt_dl_indication_pdu_t *pdu = &(value->lbt_indication_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + return 0; + + switch(pdu->pdu_type) { + case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: { + unpack_tlv_t unpack_fns[] = { + { NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value}, + }; + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type); + return 0; + } + } + + return 1; +} +static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nb_harq_indication_fdd_rel13_t *value = (nfapi_nb_harq_indication_fdd_rel13_t *)tlv; + return (pull8(ppReadPackedMsg, &value->harq_tb1, end)); +} + + +static uint8_t unpack_nb_harq_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nb_harq_indication_body_t *value = (nfapi_nb_harq_indication_body_t *)tlv; + uint8_t *nbharqBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(nbharqBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) + return 0; + + if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); + return 0; + } + + value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config); + + if(value->nb_harq_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); + return 0; + } + + uint8_t i = 0; + + for(i = 0; i < value->number_of_harqs; ++i) { + nfapi_nb_harq_indication_pdu_t *pdu = &(value->nb_harq_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t *harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + unpack_tlv_t unpack_fns[] = { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value}, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nrach_indication_pdu_rel13_t *value = (nfapi_nrach_indication_pdu_rel13_t *)tlv; + return (pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->initial_sc, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); +} + +static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t *)msg; + + if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0) { + return 0; + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); + } + + return 1; +} + +static uint8_t unpack_nrach_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t *config) { + nfapi_nrach_indication_body_t *value = (nfapi_nrach_indication_body_t *)tlv; + uint8_t *nrachBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(nrachBodyEnd > end) + return 0; + + if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0) + return 0; + + if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU); + return 0; + } + + value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t *)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config); + + if(value->nrach_pdu_list == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected); + return 0; + } + + uint8_t i = 0; + + for(i = 0; i < value->number_of_initial_scs_detected; ++i) { + nfapi_nrach_indication_pdu_t *pdu = &(value->nrach_pdu_list[i]); + uint8_t *nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6; + unpack_tlv_t unpack_fns[] = { + { NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value}, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t *)msg; + unpack_p7_tlv_t unpack_fns[] = { + { NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value}, + }; + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nr_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_slot, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_nr_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_nr_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t *config) { + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t *)msg; + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->last_slot, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_dci_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_earliest_arrival, end) && + unpack_p7_tlv_list(NULL, 0, ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + + +// unpack length check + +static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) { + int retLen = 0; + + switch (msgId) { + case NFAPI_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t)) + retLen = sizeof(nfapi_dl_config_request_t); + + break; + + case NFAPI_UL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t)) + retLen = sizeof(nfapi_ul_config_request_t); + + break; + + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); + + break; + + case NFAPI_HI_DCI0_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t)) + retLen = sizeof(nfapi_hi_dci0_request_t); + + break; + + case NFAPI_TX_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_tx_request_t)) + retLen = sizeof(nfapi_tx_request_t); + + break; + + case NFAPI_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) + retLen = sizeof(nfapi_harq_indication_t); + + break; + + case NFAPI_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) + retLen = sizeof(nfapi_crc_indication_t); + + break; + + case NFAPI_RX_ULSCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) + retLen = sizeof(nfapi_rx_indication_t); + + break; + + case NFAPI_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) + retLen = sizeof(nfapi_rach_indication_t); + + break; + + case NFAPI_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) + retLen = sizeof(nfapi_srs_indication_t); + + break; + + case NFAPI_RX_SR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) + retLen = sizeof(nfapi_sr_indication_t); + + break; + + case NFAPI_RX_CQI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) + retLen = sizeof(nfapi_cqi_indication_t); + + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) + retLen = sizeof(nfapi_lbt_dl_config_request_t); + + break; + + case NFAPI_LBT_DL_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) + retLen = sizeof(nfapi_lbt_dl_indication_t); + + break; + + case NFAPI_NB_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) + retLen = sizeof(nfapi_nb_harq_indication_t); + + break; + + case NFAPI_NRACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) + retLen = sizeof(nfapi_nrach_indication_t); + + break; + + case NFAPI_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t)) + retLen = sizeof(nfapi_dl_node_sync_t); + + break; + + case NFAPI_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t)) + retLen = sizeof(nfapi_ul_node_sync_t); + + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; +} + +static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) +{ + int retLen = 0; + + switch (msgId) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) + retLen = sizeof(nfapi_nr_dl_tti_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) + retLen = sizeof(nfapi_nr_ul_tti_request_t); + break; + + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) + retLen = sizeof(nfapi_nr_ul_dci_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) + retLen = sizeof(nfapi_nr_tx_data_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) + retLen = sizeof(nfapi_nr_rx_data_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) + retLen = sizeof(nfapi_nr_crc_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) + retLen = sizeof(nfapi_nr_rach_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) + retLen = sizeof(nfapi_nr_uci_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) + retLen = sizeof(nfapi_nr_srs_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) + retLen = sizeof(nfapi_nr_dl_node_sync_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) + retLen = sizeof(nfapi_nr_ul_node_sync_t); + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + break; case NFAPI_UE_RELEASE_REQUEST: if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) @@ -6060,262 +7465,482 @@ static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen retLen = sizeof(nfapi_ue_release_response_t); break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } - - return retLen; -} - - -// Main unpack functions - public - -int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - return -1; - - return 0; -} - -int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - int result = 0; - nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); - - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; - } - - if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); - return -1; - } - - /* - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); - return -1; - } - */ - - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_DL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_HI_DCI0_REQUEST: - if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) - result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_TX_REQUEST: - if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) - result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } - case NFAPI_UE_RELEASE_REQUEST: - if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + return retLen; +} + + + +// Main unpack functions - public + +int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { + nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + return -1; + + return 0; +} + +int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t *config) { + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t *)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + /* + uint8_t *ptr = pMessageBuf; + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + */ + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } + + if((uint8_t *)(pMessageBuf + pMessageHeader->message_length) > end) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); + return -1; + } + + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ + + // look for the specific message + switch (pMessageHeader->message_id) { + case NFAPI_DL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_UL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_TX_REQUEST: + if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) + result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_HI_DCI0_REQUEST: + if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) + result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_HARQ_INDICATION: + if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_CRC_INDICATION: + if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) + result = unpack_crc_indication(&pReadPackedMessage,end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_RX_ULSCH_INDICATION: + if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_RACH_INDICATION: + if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_SRS_INDICATION: + if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_RX_SR_INDICATION: + if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_RX_CQI_INDICATION: + if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_LBT_DL_INDICATION: + if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_NB_HARQ_INDICATION: + if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_NRACH_INDICATION: + if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_DL_NODE_SYNC: + if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_UL_NODE_SYNC: + if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_ul_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_TIMING_INFO: + if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { + if(config && config->unpack_p7_vendor_extension) { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + + break; + } + + if(result == 0) + return -1; + else + return 0; +} + +int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +{ + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + // uint8_t *ptr = pMessageBuf; + // printf("\n Read P7 message unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } + + if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); + return -1; + } + + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ + + // look for the specific message + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) + result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_HARQ_INDICATION: - if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_CRC_INDICATION: - if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RACH_INDICATION: - if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_SRS_INDICATION: - if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_SR_INDICATION: - if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_CQI_INDICATION: - if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_INDICATION: - if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_DL_NODE_SYNC: - if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UL_NODE_SYNC: - if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen)) - result = unpack_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_TIMING_INFO: - if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) - result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) + result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) + result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) + result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION, unpackedBufLen)){ + nfapi_nr_slot_indication_scf_t* msg = (nfapi_nr_slot_indication_scf_t*) pMessageHeader; + result = unpack_nr_slot_indication(&pReadPackedMessage, end, msg, config); + } + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)){ + nfapi_nr_rx_data_indication_t* msg = (nfapi_nr_rx_data_indication_t*) pMessageHeader; + msg->pdu_list = (nfapi_nr_rx_data_pdu_t*) malloc(sizeof(nfapi_nr_rx_data_pdu_t)); + msg->pdu_list->pdu = (uint8_t *) malloc(sizeof(uint8_t)); + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, msg, config); + } + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)){ + + nfapi_nr_crc_indication_t* msg = (nfapi_nr_crc_indication_t*) pMessageHeader; + msg->crc_list = (nfapi_nr_crc_t*) malloc(sizeof(nfapi_nr_crc_t)); + result = unpack_nr_crc_indication(&pReadPackedMessage,end , msg, config); + } + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)){ + nfapi_nr_uci_indication_t* msg = (nfapi_nr_uci_indication_t*) pMessageHeader; + msg->uci_list = (nfapi_nr_uci_t*) malloc(sizeof(nfapi_nr_uci_t)); + result = unpack_nr_uci_indication(&pReadPackedMessage, end, msg, config); + } + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)){ + nfapi_nr_srs_indication_t* msg = (nfapi_nr_srs_indication_t*) pMessageHeader; + msg->pdu_list = (nfapi_nr_srs_indication_pdu_t*) malloc(sizeof(nfapi_nr_srs_indication_pdu_t)); + result = unpack_nr_srs_indication(&pReadPackedMessage, end, msg, config); + } + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)){ + nfapi_nr_rach_indication_t* msg = (nfapi_nr_rach_indication_t*) pMessageHeader; + result = unpack_nr_rach_indication(&pReadPackedMessage, end, msg, config); + } + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_TIMING_INFO: + if (check_nr_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; case NFAPI_UE_RELEASE_RESPONSE: - if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + if (check_nr_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - default: - - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p7_vendor_extension) - { - result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } - - if(result == 0) - return -1; - else - return 0; -} - + default: + + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->unpack_p7_vendor_extension) + { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } + + if(result == 0) + return -1; + else + return 0; +} diff --git a/nfapi/open-nFAPI/pnf/inc/pnf.h b/nfapi/open-nFAPI/pnf/inc/pnf.h index ab38c66e09..8c4e5cf9ab 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf.h @@ -38,7 +38,9 @@ typedef struct { int pnf_connect(pnf_t *pnf); int pnf_message_pump(pnf_t *pnf); +int pnf_nr_message_pump(pnf_t *pnf); +int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_send_message(pnf_t* pnf, uint8_t* msg, uint32_t msg_len, uint16_t stream_id); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 3f08d85e6b..763b5c9abe 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -29,15 +29,37 @@ typedef struct { uint16_t dl_conf_ontime; + uint16_t dl_tti_ontime; uint16_t dl_conf_late; + uint16_t dl_tti_late; uint16_t ul_conf_ontime; + uint16_t ul_tti_ontime; uint16_t ul_conf_late; + uint16_t ul_tti_late; uint16_t hi_dci0_ontime; uint16_t hi_dci0_late; + uint16_t ul_dci_ontime; + uint16_t ul_dci_late; uint16_t tx_ontime; uint16_t tx_late; + uint16_t tx_data_ontime; + uint16_t tx_data_late; } pnf_p7_stats_t; + +typedef struct { // TODO: replace with the stats + uint16_t dl_tti_ontime; + uint16_t dl_tti_late; + uint16_t ul_tti_ontime; + uint16_t ul_tti_late; + uint16_t ul_dci_ontime; + uint16_t ul_dci_late; + uint16_t tx_data_ontime; + uint16_t tx_data_late; +} pnf_p7_nr_stats_t; + + + typedef struct { uint8_t* buffer; uint16_t length; @@ -82,7 +104,7 @@ typedef struct { pthread_mutex_t pack_mutex; // should we allow the client to specifiy nfapi_pnf_p7_subframe_buffer_t subframe_buffer[30/*NFAPI_MAX_TIMING_WINDOW_SIZE*/]; - + nfapi_pnf_p7_slot_buffer_t slot_buffer[30/*NFAPI_MAX_TIMING_WINDOW_SIZE*/]; uint32_t sequence_number; uint16_t max_num_segments; @@ -94,6 +116,12 @@ typedef struct { uint16_t sfn_sf; uint32_t sf_start_time_hr; int32_t sfn_sf_shift; + + uint16_t sfn; + uint16_t slot; + uint16_t sfn_slot; + uint32_t slot_start_time_hr; + int32_t slot_shift; uint8_t timing_info_period_counter; uint8_t timing_info_aperiodic_send; // 0:false 1:true @@ -104,23 +132,38 @@ typedef struct { uint32_t ul_config_jitter; uint32_t hi_dci0_jitter; uint32_t tx_jitter; + + //P7 NR + uint32_t dl_tti_jitter; + uint32_t ul_tti_jitter; + uint32_t ul_dci_jitter; + uint32_t tx_data_jitter; uint32_t tick; pnf_p7_stats_t stats; + pnf_p7_nr_stats_t nr_stats; } pnf_p7_t; int pnf_p7_message_pump(pnf_p7_t* pnf_p7); - +int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len); int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len); +int pnf_p7_slot_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); int pnf_p7_subframe_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn_sf); - +int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind); +int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind); +int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind); +int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind); +int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind); +int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind); pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len); void pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, pnf_p7_rx_message_t* msg); void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint32_t delta); +int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* header, uint32_t msg_len); + #endif /* _PNF_P7_H_ */ diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index d169177d6b..fc9cd66077 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -25,8 +25,14 @@ extern "C" { #include "nfapi_interface.h" #include "debug.h" #include +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" #include +#include "openair1/PHY/defs_gNB.h" + + + /*! This enum is used to describe the states of the pnf */ @@ -121,6 +127,7 @@ typedef struct nfapi_pnf_config * The client is expected to send the PNF_PARAM.response after receiving the * PNF_PARAM.request. This can be done in the call back. */ + int (*pnf_nr_param_req)(nfapi_pnf_config_t* config, nfapi_nr_pnf_param_request_t* req); int (*pnf_param_req)(nfapi_pnf_config_t* config, nfapi_pnf_param_request_t* req); /*! A callback for the PNF_CONFIG.request @@ -133,7 +140,8 @@ typedef struct nfapi_pnf_config * PNF_CONFIG.request. This can be done in the call back. */ int (*pnf_config_req)(nfapi_pnf_config_t* config, nfapi_pnf_config_request_t* req); - + int (*pnf_nr_config_req)(nfapi_pnf_config_t* config, nfapi_nr_pnf_config_request_t* req); + /*! A callback for the PNF_START.request * \param config A pointer to the pnf configuration * \param req A data structure for the decoded PNF_CONFIG.request. This will have @@ -144,7 +152,8 @@ typedef struct nfapi_pnf_config * PNF_START.request. This can be done in the call back. */ int (*pnf_start_req)(nfapi_pnf_config_t* config, nfapi_pnf_start_request_t* req); - + int (*pnf_nr_start_req)(nfapi_pnf_config_t* config, nfapi_nr_pnf_start_request_t* req); + /*! A callback for the PNF_STOP.request * \param config A pointer to the pnf configuration * \param req A data structure for the decoded PNF_STOP.request. This will have @@ -167,7 +176,8 @@ typedef struct nfapi_pnf_config * PARAM.request. This can be done in the call back. */ int (*param_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_param_request_t* req); - + int (*nr_param_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_param_request_scf_t* req); + /*! A callback for the CONFIG.request * \param config A pointer to the pnf configuration * \param phy A pointer to the pnf phy configuration @@ -179,6 +189,7 @@ typedef struct nfapi_pnf_config * CONFIG.request. This can be done in the call back. */ int (*config_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_config_request_t* req); + int (*nr_config_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_config_request_scf_t* req); /*! A callback for the START.request * \param config A pointer to the pnf configuration @@ -190,8 +201,8 @@ typedef struct nfapi_pnf_config * The client is expected to send the START.response after the client has received the * first subframe indication from FAPI. */ - int (*start_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req); - + int (*start_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req); + int (*nr_start_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_start_request_scf_t* req); /*! A callback for the STOP.request * \param config A pointer to the pnf configuration * \param phy A pointer to the pnf phy configuration @@ -203,7 +214,8 @@ typedef struct nfapi_pnf_config * STOP.request. This can be done in the call back. */ int (*stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_stop_request_t* req); - + int (*nr_stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_stop_request_t* req); + /*! A callback for the MEASUREMENT.request * \param config A pointer to the pnf configuration * \param phy A pointer to the pnf phy configuration @@ -355,6 +367,7 @@ int nfapi_pnf_config_destroy(nfapi_pnf_config_t* config); * \endcode */ int nfapi_pnf_start(nfapi_pnf_config_t* config); +int nfapi_nr_pnf_start(nfapi_pnf_config_t* config); /*! Stop the PNF library. * \param config A pointer to the pnf configuration @@ -371,6 +384,8 @@ int nfapi_pnf_stop(nfapi_pnf_config_t* config); * */ int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp); +int nfapi_nr_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_param_response_t* resp); + /*! Send the PNF_CONFIG.response * \param config A pointer to a pnf configuraiton @@ -379,6 +394,7 @@ int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_respons * */ int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_response_t* resp); +int nfapi_nr_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_config_response_t* resp); /*! Send the PNF_START.response * \param config A pointer to a pnf configuraiton @@ -387,7 +403,7 @@ int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_respo * */ int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_response_t* resp); - +int nfapi_nr_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_start_response_t* resp); /*! Send the PNF_STOP.response * \param config A pointer to a pnf configuraiton * \param resp A pointer to the message structure @@ -403,6 +419,7 @@ int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_ * */ int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* resp); +int nfapi_nr_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_param_response_scf_t* resp); /*! Send the CONFIG.response * \param config A pointer to a pnf configuraiton @@ -411,7 +428,7 @@ int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* res * */ int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp); - +int nfapi_nr_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_config_response_scf_t* resp); /*! Send the START.response * \param config A pointer to a pnf configuraiton * \param resp A pointer to the message structure @@ -419,6 +436,7 @@ int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* r * */ int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* resp); +int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_scf_t* resp); /*! Send the STOP.response * \param config A pointer to a pnf configuraiton @@ -550,6 +568,22 @@ typedef struct nfapi_ue_release_request_t* ue_release_req; } nfapi_pnf_p7_subframe_buffer_t; +typedef struct +{ + //uint16_t sfn_slot + int16_t sfn; + int16_t slot; + //TODO: Change P7 structs to NR + nfapi_nr_dl_tti_request_t* dl_tti_req;//nfapi_dl_config_request_t* dl_config_req; + nfapi_nr_ul_tti_request_t* ul_tti_req;//nfapi_ul_config_request_t* ul_config_req; + nfapi_nr_ul_dci_request_t* ul_dci_req;//nfapi_hi_dci0_request_t* hi_dci0_req; + nfapi_nr_tx_data_request_t* tx_data_req;//nfapi_tx_request_t* tx_req; + + //TODO: check these two later + //nfapi_lbt_dl_config_request_t* lbt_dl_config_req; + //nfapi_ue_release_request_t* ue_release_req; +} nfapi_pnf_p7_slot_buffer_t; + typedef struct nfapi_pnf_p7_config nfapi_pnf_p7_config_t; /*! The nfapi PNF PHY P7 configuration information created using the nfapi_pnf_p7_create function @@ -602,6 +636,8 @@ typedef struct nfapi_pnf_p7_config /*! The dummy subframe buffer structure that should be used in case there * are no 'valid' subframe messages */ nfapi_pnf_p7_subframe_buffer_t dummy_subframe; + + nfapi_pnf_p7_slot_buffer_t dummy_slot; // defining a slot equivalent for now /*! Configuration options for the p7 pack unpack functions*/ nfapi_p7_codec_config_t codec_config; @@ -611,6 +647,7 @@ typedef struct nfapi_pnf_p7_config // tdb : if these should be public uint16_t subframe_buffer_size; + uint16_t slot_buffer_size; uint8_t timing_info_mode_periodic; // 0:false 1:true uint8_t timing_info_mode_aperiodic; // 0:false 1:true uint8_t timing_info_period; // 1..225 in subframes @@ -620,6 +657,7 @@ typedef struct nfapi_pnf_p7_config * \param req A pointer to the dl config request message structure * \return not currently used */ + int (*dl_tti_req_fn)(gNB_L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req); int (*dl_config_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req); /*! A callback for the UL_CONFIG.request @@ -627,6 +665,7 @@ typedef struct nfapi_pnf_p7_config * \param req A pointer to the ul config request message structure * \return not currently used */ + int (*ul_tti_req_fn)(gNB_L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req); int (*ul_config_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req); /*! A callback for the HI_DCI0.request @@ -634,8 +673,9 @@ typedef struct nfapi_pnf_p7_config * \param req A pointer to the hi dci0 request message structure * \return not currently used */ + int (*ul_dci_req_fn)(gNB_L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req); int (*hi_dci0_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); - + /*! A callback for the TX_REQ.request * \param config A poiner to the PNF P7 config * \param req A pointer to the tx request message structure @@ -645,6 +685,7 @@ typedef struct nfapi_pnf_p7_config * will 'keep' the pointers until they are transmitted the callee should set the pointers in the req to 0 * and then use the p7 codec config free function to release the pdu's when appropriate. */ + int (*tx_data_req_fn)(nfapi_pnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req); int (*tx_req)(nfapi_pnf_p7_config_t* config, nfapi_tx_request_t* req); /*! A callback for the LBT_DL_CONFIG.request @@ -708,6 +749,7 @@ int nfapi_pnf_p7_config_destroy(nfapi_pnf_p7_config_t* config); * This function will not return until nfapi_pnf_p7_stop is called. */ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); +int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config); /*! Stop the PNF P7 library. * \param config A pointer to a PNF P7 config @@ -717,6 +759,21 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); */ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config); +/*! NR Slot indication + * message copied from nfapi_pnf_p7_subframe_ind + * \param config A pointer to a PNF P7 config + * \param phy_id The phy_id for the phy instance + * \param sfn_sf The SFN and SF in the format of FAPI + * \return 0 means success, -1 means failure + * + * The client should call the subframe indication every 1ms. The PNF will + * respond by invoking the pnf p7 subframe callbacks with the messages from the subframe buffer + * + * If messages are not in the subframe buffer, they dummy subframe messages will be sent + */ +int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); + + /*! Subframe indication * \param config A pointer to a PNF P7 config * \param phy_id The phy_id for the phy instance diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index eec9ff80c3..fdafd93279 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -26,9 +26,29 @@ #include #include #include - +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" #include "pnf.h" +# if 1 // for hard-code (remove later) +#include "COMMON/platform_types.h" +#include "COMMON/platform_constants.h" +#include "common/ran_context.h" + +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#include "NR_BCCH-BCH-Message.h" +#include "NR_ServingCellConfigCommon.h" + +#include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include "SCHED_NR/phy_frame_config_nr.h" + +#include "NR_MIB.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" + +#endif + #define MAX_SCTP_STREAMS 16 void nfapi_pnf_phy_config_delete_all(nfapi_pnf_config_t* config) @@ -63,6 +83,50 @@ nfapi_pnf_phy_config_t* nfapi_pnf_phy_config_find(nfapi_pnf_config_t* config, ui return 0; } +void pnf_nr_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_pnf_param_request_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_PARAM.request received\n"); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_nr_pnf_param_request_t), &pnf->_public.codec_config) >= 0) + { + if(pnf->_public.state == NFAPI_PNF_IDLE) + { + if(pnf->_public.pnf_nr_param_req) + { + (pnf->_public.pnf_nr_param_req)(&pnf->_public, &req); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in IDLE state\n", __FUNCTION__); + + nfapi_nr_pnf_param_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_pnf_param_resp(&pnf->_public, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + } +} + void pnf_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -173,6 +237,72 @@ void pnf_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + + + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_pnf_config_request_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_CONFIG.request received\n"); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0) + { + // ensure correct state + if(pnf->_public.state != NFAPI_PNF_RUNNING) + { + // delete the phy records + nfapi_pnf_phy_config_delete_all(&pnf->_public); + + // create the phy records + if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG) + { + int i = 0; + for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i) + { + nfapi_pnf_phy_config_t* phy = (nfapi_pnf_phy_config_t*)malloc(sizeof(nfapi_pnf_phy_config_t)); + memset(phy, 0, sizeof(nfapi_pnf_phy_config_t)); + + phy->state = NFAPI_PNF_PHY_IDLE; + phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id; + + nfapi_pnf_phy_config_add(&(pnf->_public), phy); + } + } + + if(pnf->_public.pnf_nr_config_req) + { + (pnf->_public.pnf_nr_config_req)(&(pnf->_public), &req); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in correct state: %d\n", __FUNCTION__, pnf->_public.state); + + nfapi_nr_pnf_config_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_pnf_config_resp(&(pnf->_public), &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + } +} + void pnf_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -215,6 +345,48 @@ void pnf_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_pnf_start_request_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_START.request Received\n"); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0) + { + if(pnf->_public.state == NFAPI_PNF_CONFIGURED) + { + if(pnf->_public.pnf_nr_start_req) + { + (pnf->_public.pnf_nr_start_req)(&(pnf->_public), &req); + } + } + else + { + nfapi_nr_pnf_start_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_PNF_START_RESPONSE; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_pnf_start_resp(&(pnf->_public), &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + } +} + void pnf_handle_pnf_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -330,6 +502,78 @@ void pnf_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_param_request_scf_t req; + + nfapi_pnf_config_t* config = &(pnf->_public); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PARAM.request received\n"); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + { + if(config->state == NFAPI_PNF_RUNNING) + { + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); + if(phy) + { + if(phy->state == NFAPI_PNF_PHY_IDLE) + { + if(config->nr_param_req) + { + (config->nr_param_req)(config, phy, &req); + } + } + else + { + nfapi_nr_param_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_param_resp(config, &resp); + } + } + else + { + nfapi_nr_param_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_CONFIG; + nfapi_nr_pnf_param_resp(config, &resp); + } + + } + else + { + nfapi_nr_param_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_param_resp(config, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + + } +} + void pnf_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { @@ -401,6 +645,85 @@ void pnf_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } + +void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_config_request_scf_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "CONFIG.request received\n"); + + nfapi_pnf_config_t* config = &(pnf->_public); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + { + if(config->state == NFAPI_PNF_RUNNING) + { + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); + +#if 0 // emulate set_config TLV reception (hard-code) + int tdd_return = set_tdd_config_nr(&req, 1, 7, 6, 2, 4); +#endif + + if(phy) + { + if(phy->state != NFAPI_PNF_PHY_RUNNING) + { + if(config->nr_config_req) + { + (config->nr_config_req)(config, phy, &req); + + + } + } + else + { + nfapi_nr_config_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_CONFIG_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_config_resp(config, &resp); + } + } + else + { + nfapi_nr_config_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_CONFIG_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_CONFIG; + nfapi_nr_pnf_config_resp(config, &resp); + } + } + else + { + nfapi_nr_config_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_CONFIG_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_config_resp(config, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + } +} + void pnf_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -472,6 +795,77 @@ void pnf_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_start_request_scf_t req; + + nfapi_pnf_config_t* config = &(pnf->_public); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() START.request received state:%d\n", __FUNCTION__, config->state); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + { + if(config->state == NFAPI_PNF_RUNNING) + { + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); + if(phy) + { + if(phy->state != NFAPI_PNF_PHY_RUNNING) + { + if(config->nr_start_req) + { + (config->nr_start_req)(config, phy, &req); + } + } + else + { + nfapi_nr_start_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_start_resp(config, &resp); + } + } + else + { + nfapi_nr_start_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_CONFIG; + nfapi_nr_pnf_start_resp(config, &resp); + } + } + else + { + nfapi_nr_start_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_start_resp(config, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + + } +} + void pnf_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -543,6 +937,77 @@ void pnf_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_stop_request_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "STOP.request received\n"); + + nfapi_pnf_config_t* config = &(pnf->_public); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + { + if(config->state == NFAPI_PNF_RUNNING) + { + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); + if(phy) + { + if(phy->state != NFAPI_PNF_PHY_RUNNING) + { + if(config->nr_stop_req) + { + (config->nr_stop_req)(config, phy, &req); + } + } + else + { + nfapi_stop_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_pnf_stop_resp(config, &resp); + } + } + else + { + nfapi_stop_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_CONFIG; + nfapi_pnf_stop_resp(config, &resp); + } + } + else + { + nfapi_stop_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_pnf_stop_resp(config, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + + } +} + void pnf_handle_measurement_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -1071,7 +1536,101 @@ void pnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, pnf_t* pnf, uin } } +void pnf_nr_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + nfapi_p4_p5_message_header_t messageHeader; + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return; + } + + // unpack the message header + if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &pnf->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + switch (messageHeader.message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + pnf_nr_handle_pnf_param_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + pnf_nr_handle_pnf_config_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + pnf_nr_handle_pnf_start_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_PNF_STOP_REQUEST: + pnf_handle_pnf_stop_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + pnf_nr_handle_param_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + pnf_nr_handle_config_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + pnf_nr_handle_start_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + pnf_nr_handle_stop_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_MEASUREMENT_REQUEST: + pnf_handle_measurement_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_RSSI_REQUEST: + pnf_handle_rssi_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_CELL_SEARCH_REQUEST: + pnf_handle_cell_search_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_BROADCAST_DETECT_REQUEST: + pnf_handle_broadcast_detect_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + pnf_handle_system_information_schedule_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_SYSTEM_INFORMATION_REQUEST: + pnf_handle_system_information_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NMM_STOP_REQUEST: + pnf_handle_nmm_stop_request(pnf, pRecvMsg, recvMsgLen); + break; + + default: + { + if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + pnf_handle_vendor_extension(pRecvMsg, recvMsgLen, pnf, messageHeader.message_id); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id); + } + } + break; + } +} void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { @@ -1169,6 +1728,24 @@ void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } + +int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len) +{ + int packed_len = nfapi_nr_p5_message_pack(msg, msg_len, + pnf->tx_message_buffer, + sizeof(pnf->tx_message_buffer), + &pnf->_public.codec_config); + + if (packed_len < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len); + return -1; + } + + return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/); +} + + int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len) { int packed_len = nfapi_p5_message_pack(msg, msg_len, @@ -1393,8 +1970,15 @@ int pnf_connect(pnf_t* pnf) int pnf_send_message(pnf_t* pnf, uint8_t *msg, uint32_t len, uint16_t stream) { + if (pnf->sctp) { + printf("\nPNF SENDS: \n"); + for(int i=0; ip5_sock, msg, len, NULL, 0, 42/*config->sctp_stream_number*/, 0, stream/*P5_STREAM_ID*/, 0, 0) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp_sendmsg failed errno: %d\n", errno); @@ -1412,7 +1996,6 @@ int pnf_send_message(pnf_t* pnf, uint8_t *msg, uint32_t len, uint16_t stream) return 0; } - int pnf_read_dispatch_message(pnf_t* pnf) { int socket_connected = 1; @@ -1486,6 +2069,13 @@ int pnf_read_dispatch_message(pnf_t* pnf) } else { + // print the received message + printf("\n MESSAGE RECEIVED: \n"); + for(int i=0; ip5_sock, header_buffer, header_buffer_size, /*(struct sockaddr*)&addr, &addr_len*/ 0, 0, &sndrcvinfo, &flags); + + if(message_size == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno); + return 0; + } + + nfapi_p4_p5_message_header_t header; + int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if(unpack_result < 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n"); + return 0; + } + message_size = header.message_length; + + // now have the size of the mesage + } + + if(message_size > stack_buffer_size) + { + dynamic_buffer = (uint8_t*)malloc(message_size); + + if(dynamic_buffer == NULL) + { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } + + read_buffer = dynamic_buffer; + } + + { + int flags = 0; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + int recvmsg_result = sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + if(recvmsg_result == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); + } + else + { + // print the received message + printf("\n MESSAGE RECEIVED: \n"); + for(int i=0; ip5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + */ + + // handle now if complete message in one or more segments + if ((flags & 0x80) == 0x80) + { + pnf_nr_handle_p5_message(pnf, read_buffer, message_size); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); + + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } + + + } + } + } + + if(dynamic_buffer) + { + free(dynamic_buffer); + } + + return socket_connected; + + } @@ -1597,3 +2316,64 @@ int pnf_message_pump(pnf_t* pnf) } +int pnf_nr_message_pump(pnf_t* pnf) +{ + uint8_t socketConnected = 1; + + while(socketConnected && pnf->terminate == 0) + { + fd_set rfds; + int selectRetval = 0; + + // select on a timeout and then get the message + FD_ZERO(&rfds); + FD_SET(pnf->p5_sock, &rfds); + + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + selectRetval = select(pnf->p5_sock+1, &rfds, NULL, NULL, &timeout); + + if(selectRetval == 0) + { + // timeout + continue; + } + else if (selectRetval == -1 && (errno == EINTR)) + { + // interrupted by signal + NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 Signal Interrupt %d\n", errno); + continue; + } + else if (selectRetval == -1) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 select() failed\n"); + sleep(1); + continue; + } + + if(FD_ISSET(pnf->p5_sock, &rfds)) + { + socketConnected = pnf_nr_read_dispatch_message(pnf); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Why are we here\n"); + } + } + + // Drop back to idle if we have lost connection + pnf->_public.state = NFAPI_PNF_PHY_IDLE; + + + // close the connection and socket + if (close(pnf->p5_sock) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "close(sctpSock) failed errno: %d\n", errno); + } + + return 0; + +} + diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index dda0d0fdc6..8c9722c13e 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -19,6 +19,8 @@ #include #include #include +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" nfapi_pnf_config_t* nfapi_pnf_config_create() { @@ -81,6 +83,40 @@ int nfapi_pnf_start(nfapi_pnf_config_t* config) return 0; } +int nfapi_nr_pnf_start(nfapi_pnf_config_t* config) +{ + // Verify that config is not null + if(config == 0) + return -1; + + // Make sure to set the defined trace function before using NFAPI_TRACE + if(config->trace) + nfapi_trace_g = config->trace; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + pnf_t* _this = (pnf_t*)(config); + + while (_this->terminate == 0) + { + int connect_result = pnf_connect(_this); + + if(connect_result > 0) + { + pnf_nr_message_pump(_this); + } + else if(connect_result < 0) + { + return connect_result; + } + + sleep(1); + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__); + + return 0; +} + int nfapi_pnf_stop(nfapi_pnf_config_t* config) { // Verify that config is not null @@ -96,6 +132,21 @@ int nfapi_pnf_stop(nfapi_pnf_config_t* config) return 0; } + +int nfapi_nr_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_param_response_t* resp) +{ + // ensure it's valid + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_param_response_t)); +} + int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp) { // ensure it's valid @@ -129,6 +180,27 @@ int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_respo return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_config_response_t)); } + +int nfapi_nr_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_config_response_t* resp) +{ + // ensure it's valid + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + if(resp->error_code == NFAPI_MSG_OK) + { + config->state = NFAPI_PNF_CONFIGURED; + } + + pnf_t* _this = (pnf_t*)(config); + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_config_response_t)); +} + + int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_response_t* resp) { // ensure it's valid @@ -148,6 +220,26 @@ int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_respons return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_start_response_t)); } +int nfapi_nr_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_start_response_t* resp) +{ + // ensure it's valid + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + if(resp->error_code == NFAPI_MSG_OK) + { + config->state = NFAPI_PNF_RUNNING; + } + + pnf_t* _this = (pnf_t*)(config); + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_start_response_t)); +} + + int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_t* resp) { // ensure it's valid @@ -166,7 +258,6 @@ int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_ return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_stop_response_t)); } - int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* resp) { if (config == NULL || resp == NULL) @@ -180,6 +271,20 @@ int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* res return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_param_response_t)); } + +int nfapi_nr_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_param_response_scf_t* resp) +{ + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_param_response_scf_t)); +} + int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp) { if (config == NULL || resp == NULL) @@ -208,6 +313,35 @@ int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* r return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_config_response_t)); } +int nfapi_nr_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_config_response_scf_t* resp) +{ + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id); + + if(phy) + { + if(resp->error_code == NFAPI_NR_CONFIG_MSG_OK) + { + phy->state = NFAPI_PNF_PHY_CONFIGURED; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id); + return -1; + } + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_config_response_scf_t)); +} + + int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* resp) { if (config == NULL || resp == NULL) @@ -235,6 +369,34 @@ int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* res return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_start_response_t)); } +int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_scf_t* resp) +{ + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id); + if(phy) + { + if(resp->error_code == NFAPI_NR_START_MSG_OK) + { + phy->state = NFAPI_PNF_PHY_RUNNING; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknown phy id %d\n", __FUNCTION__, resp->header.phy_id); + return -1; + } + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_start_response_scf_t)); +} + + int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp) { if (config == NULL || resp == NULL) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 5ba912e059..092b967189 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -32,8 +32,19 @@ #define FAPI2_IP_DSCP 0 extern uint16_t sf_ahead; +extern uint16_t slot_ahead; + //uint16_t sf_ahead=4; +void add_slot(uint16_t *frameP, uint16_t *slotP, int offset) +{ + uint16_t num_slots = 20; // set based on numerlogy (fixing for 1) + + *frameP = (*frameP + ((*slotP + offset) / num_slots))%1024; + + *slotP = ((*slotP + offset) % num_slots); +} + void add_sf(uint16_t *frameP, uint16_t *subframeP, int offset) { *frameP = (*frameP + ((*subframeP + offset) / 10))%1024; @@ -50,6 +61,22 @@ void subtract_sf(uint16_t *frameP, uint16_t *subframeP, int offset) *subframeP = (*subframeP+10-offset)%10; } +uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset) +{ + uint32_t new_sfnslot; +// uint16_t sfn = NFAPI_SFNSLOT2SFN(sfnslot); +// uint16_t slot = NFAPI_SFNSLOT2SLOT(sfnslot); + + //printf("%s() sfn:%u sf:%u\n", __FUNCTION__, sfn, sf); + add_slot(&sfn, &slot, offset); + + new_sfnslot = sfn<<6|slot; + + //printf("%s() sfn:%u sf:%u offset:%d sfnsf:%d(DEC:%d) new:%d(DEC:%d)\n", __FUNCTION__, sfn, sf, offset, sfnsf, NFAPI_SFNSF2DEC(sfnsf), new_sfnsf, NFAPI_SFNSF2DEC(new_sfnsf)); + + return new_sfnslot; +} + uint16_t sfnsf_add_sf(uint16_t sfnsf, int offset) { uint16_t new_sfnsf; @@ -114,12 +141,33 @@ void pnf_p7_free(pnf_p7_t* pnf_p7, void* ptr) } // todo : for now these just malloc/free need to move to a memory cache +nfapi_nr_dl_tti_request_t* allocate_nfapi_dl_tti_request(pnf_p7_t* pnf_p7) +{ + void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_nr_dl_tti_request_t)); + //printf("%s() ptr:%p\n", __FUNCTION__, ptr); + return ptr; +} nfapi_dl_config_request_t* allocate_nfapi_dl_config_request(pnf_p7_t* pnf_p7) { void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_dl_config_request_t)); //printf("%s() ptr:%p\n", __FUNCTION__, ptr); return ptr; } +void deallocate_nfapi_dl_tti_request(nfapi_nr_dl_tti_request_t* req, pnf_p7_t* pnf_p7) +{ + //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->dl_config_request_body.dl_config_pdu_list); + + // if(pnf_p7->_public.codec_config.deallocate) + // { + // (pnf_p7->_public.codec_config.deallocate)(req); + // } + // else + // { + // free(req); + // } + + pnf_p7_free(pnf_p7, req); +} void deallocate_nfapi_dl_config_request(nfapi_dl_config_request_t* req, pnf_p7_t* pnf_p7) { @@ -137,6 +185,13 @@ void deallocate_nfapi_dl_config_request(nfapi_dl_config_request_t* req, pnf_p7_t pnf_p7_free(pnf_p7, req); } +nfapi_nr_ul_tti_request_t* allocate_nfapi_ul_tti_request(pnf_p7_t* pnf_p7) +{ + void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_nr_ul_tti_request_t)); + //printf("%s() ptr:%p\n", __FUNCTION__, ptr); + return ptr; +} + nfapi_ul_config_request_t* allocate_nfapi_ul_config_request(pnf_p7_t* pnf_p7) { void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_ul_config_request_t)); @@ -144,6 +199,23 @@ nfapi_ul_config_request_t* allocate_nfapi_ul_config_request(pnf_p7_t* pnf_p7) return ptr; } +void deallocate_nfapi_ul_tti_request(nfapi_nr_ul_tti_request_t* req, pnf_p7_t* pnf_p7) +{ + //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->ul_config_request_body.ul_config_pdu_list); + /*if(pnf_p7->_public.codec_config.deallocate) + { + (pnf_p7->_public.codec_config.deallocate)(req->pdus_list); + (pnf_p7->_public.codec_config.deallocate)(req->groups_list); + } + else + { + free(req->pdus_list); + free(req->groups_list); + } + */ + pnf_p7_free(pnf_p7, req); +} + void deallocate_nfapi_ul_config_request(nfapi_ul_config_request_t* req, pnf_p7_t* pnf_p7) { //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->ul_config_request_body.ul_config_pdu_list); @@ -160,11 +232,31 @@ void deallocate_nfapi_ul_config_request(nfapi_ul_config_request_t* req, pnf_p7_t pnf_p7_free(pnf_p7, req); } +nfapi_nr_ul_dci_request_t* allocate_nfapi_ul_dci_request(pnf_p7_t* pnf_p7) +{ + return pnf_p7_malloc(pnf_p7, sizeof(nfapi_nr_ul_dci_request_t)); +} + nfapi_hi_dci0_request_t* allocate_nfapi_hi_dci0_request(pnf_p7_t* pnf_p7) { return pnf_p7_malloc(pnf_p7, sizeof(nfapi_hi_dci0_request_t)); } +void deallocate_nfapi_ul_dci_request(nfapi_nr_ul_dci_request_t* req, pnf_p7_t* pnf_p7) +{ + //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->hi_dci0_request_body.hi_dci0_pdu_list); + // if(pnf_p7->_public.codec_config.deallocate) + // { + // (pnf_p7->_public.codec_config.deallocate)(req->ul_dci_pdu_list); + // } + // else + // { + // free(req->ul_dci_pdu_list); + // } + + pnf_p7_free(pnf_p7, req); +} + void deallocate_nfapi_hi_dci0_request(nfapi_hi_dci0_request_t* req, pnf_p7_t* pnf_p7) { //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->hi_dci0_request_body.hi_dci0_pdu_list); @@ -181,11 +273,32 @@ void deallocate_nfapi_hi_dci0_request(nfapi_hi_dci0_request_t* req, pnf_p7_t* pn pnf_p7_free(pnf_p7, req); } +nfapi_nr_tx_data_request_t* allocate_nfapi_tx_data_request(pnf_p7_t* pnf_p7) +{ + return pnf_p7_malloc(pnf_p7, sizeof(nfapi_nr_tx_data_request_t)); +} + nfapi_tx_request_t* allocate_nfapi_tx_request(pnf_p7_t* pnf_p7) { return pnf_p7_malloc(pnf_p7, sizeof(nfapi_tx_request_t)); } +//TODO: Check if deallocate_nfapi_tx_data_request defn is proper +void deallocate_nfapi_tx_data_request(nfapi_nr_tx_data_request_t* req, pnf_p7_t* pnf_p7) +{ +/* + if(pnf_p7->_public.codec_config.deallocate) + { + (pnf_p7->_public.codec_config.deallocate)(req->pdu_list); + } + else + { + free(req->pdu_list); + } +*/ + pnf_p7_free(pnf_p7, req); +} + void deallocate_nfapi_tx_request(nfapi_tx_request_t* req, pnf_p7_t* pnf_p7) { int i = 0; @@ -385,11 +498,33 @@ void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reas } +static uint32_t get_slot_time(uint32_t now_hr, uint32_t slot_start_hr) +{ + if(now_hr < slot_start_hr) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe now_hr:%u sf_start_hr:%u\n", now_hr, sf_start_hr); + return 0; + } + else + { + uint32_t now_us = TIMEHR_USEC(now_hr); + uint32_t slot_start_us = TIMEHR_USEC(slot_start_hr); + + // if the us have wrapped adjust for it + if(now_hr < slot_start_us) + { + now_us += 500000; + } + + return now_us - slot_start_us; + } +} + static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr) { if(now_hr < sf_start_hr) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe now_hr:%u sf_start_hr:%u\n", now_hr, sf_start_hr); + NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe\n"); return 0; } else @@ -407,6 +542,8 @@ static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr) } } + + int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len) { // todo : consider how to do this only once @@ -414,7 +551,8 @@ int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len) memset((char*)&remote_addr, 0, sizeof(struct sockaddr_in)); remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(pnf_p7->_public.remote_p7_port); - //remote_addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.remote_p7_addr); + + if(inet_aton(pnf_p7->_public.remote_p7_addr, &remote_addr.sin_addr) == -1) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "inet_aton failed %d\n", errno); @@ -424,7 +562,9 @@ int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len) socklen_t remote_addr_len = sizeof(struct sockaddr_in); int sendto_result; + if ((sendto_result = sendto((int)pnf_p7->p7_sock, (const char*)msg, len, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) +//if ((sendto_result = sendto((int)pnf_p7->p7_sock,"hello", 6, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s %s:%d sendto(%d, %p, %d) %d failed errno: %d\n", __FUNCTION__, pnf_p7->_public.remote_p7_addr, pnf_p7->_public.remote_p7_port, (int)pnf_p7->p7_sock, (const char*)msg, len, remote_addr_len, errno); return -1; @@ -527,6 +667,97 @@ int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* return 0; } + +int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* header, uint32_t msg_len) +{ + header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, pnf_p7->sequence_number); + + // Need to guard against different threads calling the encode function at the same time + if(pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return -1; + } + + int len = nfapi_nr_p7_message_pack(header, pnf_p7->tx_message_buffer, sizeof(pnf_p7->tx_message_buffer), &pnf_p7->_public.codec_config); + + if (len < 0) + { + if(pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len ); + return -1; + } + + if(len > pnf_p7->_public.segment_size) + { + int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ; + int seg_body_len = pnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + + int segment = 0; + int offset = NFAPI_P7_HEADER_LENGTH; + uint8_t buffer[pnf_p7->_public.segment_size]; + for(segment = 0; segment < segment_count; ++segment) + { + uint8_t last = 0; + uint16_t size = pnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH; + if(segment + 1 == segment_count) + { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } + + uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH; + + // Update the header with the m and segement + memcpy(&buffer[0], pnf_p7->tx_message_buffer, NFAPI_P7_HEADER_LENGTH); + + // set the segment length + buffer[4] = (segment_size & 0xFF00) >> 8; + buffer[5] = (segment_size & 0xFF); + + // set the m & segment number + buffer[6] = ((!last) << 7) + segment; + + memcpy(&buffer[NFAPI_P7_HEADER_LENGTH], pnf_p7->tx_message_buffer + offset, size); + offset += size; + + if(pnf_p7->_public.checksum_enabled) + { + nfapi_p7_update_checksum(buffer, segment_size); + } + + + pnf_p7_send_message(pnf_p7, &buffer[0], segment_size); + } + } + else + { + if(pnf_p7->_public.checksum_enabled) + { + nfapi_p7_update_checksum(pnf_p7->tx_message_buffer, len); + } + + // simple case that the message fits in a single segment + pnf_p7_send_message(pnf_p7, pnf_p7->tx_message_buffer, len); + } + + pnf_p7->sequence_number++; + + if(pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } + + return 0; +} + void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7) { nfapi_timing_info_t timing_info; @@ -558,6 +789,88 @@ void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7) pnf_p7->timing_info_ms_counter = 0; } + +void pnf_nr_pack_and_send_timing_info(pnf_p7_t* pnf_p7) +{ + nfapi_nr_timing_info_t timing_info; + memset(&timing_info, 0, sizeof(timing_info)); + timing_info.header.message_id = NFAPI_TIMING_INFO; + timing_info.header.phy_id = pnf_p7->_public.phy_id; + + timing_info.last_sfn = pnf_p7->sfn; + timing_info.last_slot = pnf_p7->slot; + timing_info.time_since_last_timing_info = pnf_p7->timing_info_ms_counter; + + timing_info.dl_tti_jitter = pnf_p7->dl_tti_jitter; + timing_info.tx_data_request_jitter = pnf_p7->tx_data_jitter; + timing_info.ul_tti_jitter = pnf_p7->ul_tti_jitter; + timing_info.ul_dci_jitter = pnf_p7->ul_dci_jitter; + + timing_info.dl_tti_latest_delay = 0; + timing_info.tx_data_request_latest_delay = 0; + timing_info.ul_tti_latest_delay = 0; + timing_info.ul_dci_latest_delay = 0; + + timing_info.dl_tti_earliest_arrival = 0; + timing_info.tx_data_request_earliest_arrival = 0; + timing_info.ul_tti_earliest_arrival = 0; + timing_info.ul_dci_earliest_arrival = 0; + + + pnf_nr_p7_pack_and_send_p7_message(pnf_p7, &(timing_info.header), sizeof(timing_info)); + + pnf_p7->timing_info_ms_counter = 0; +} + + +void send_dummy_slot(pnf_p7_t* pnf_p7, uint16_t sfn, uint16_t slot) +{ + struct timespec t; + clock_gettime( CLOCK_MONOTONIC, &t); + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(sfn_sf:%d) t:%ld.%09ld\n", __FUNCTION__, NFAPI_SFNSF2DEC(sfn_sf), t.tv_sec, t.tv_nsec); + + if(pnf_p7->_public.tx_data_req_fn && pnf_p7->_public.dummy_slot.tx_data_req) + { + pnf_p7->_public.dummy_slot.tx_data_req->SFN = sfn; + pnf_p7->_public.dummy_slot.tx_data_req->Slot = slot; + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy tx_req - enter\n"); + (pnf_p7->_public.tx_data_req_fn)(&pnf_p7->_public, pnf_p7->_public.dummy_slot.tx_data_req); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy tx_req - exit\n"); + } + if(pnf_p7->_public.dl_tti_req_fn && pnf_p7->_public.dummy_slot.dl_tti_req) + { + pnf_p7->_public.dummy_slot.dl_tti_req->SFN = sfn; + pnf_p7->_public.dummy_slot.dl_tti_req->Slot = slot; + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - enter\n"); + (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.dl_tti_req); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - exit\n"); + } + if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) + { + pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; + pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy ul_config_req - enter\n"); + (pnf_p7->_public.ul_tti_req_fn)(NULL, &pnf_p7->_public, pnf_p7->_public.dummy_slot.ul_tti_req); + } + if(pnf_p7->_public.ul_dci_req_fn && pnf_p7->_public.dummy_slot.ul_dci_req) + { + pnf_p7->_public.dummy_slot.ul_dci_req->SFN = sfn; + pnf_p7->_public.dummy_slot.ul_dci_req->Slot = slot; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy hi_dci0 - enter\n"); + (pnf_p7->_public.ul_dci_req_fn)(NULL, &pnf_p7->_public, pnf_p7->_public.dummy_slot.ul_dci_req); + } + #if 0 + if(pnf_p7->_public.lbt_dl_config_req && pnf_p7->_public.dummy_subframe.lbt_dl_config_req) // TODO: Change later + { + pnf_p7->_public.dummy_slot.lbt_dl_config_req->sfn_sf = sfn; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy lbt - enter\n"); + (pnf_p7->_public.lbt_dl_config_req)(&pnf_p7->_public, pnf_p7->_public.dummy_slot.lbt_dl_config_req); + } + #endif +} + + void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) { struct timespec t; @@ -599,6 +912,251 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) } } + +int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t slot) +{ + //This function is aligned with rx sfn/slot + + // We could either send an event to the p7 thread have have it run the + // subframe or we could handle it here and lock access to the subframe + // buffers. If we do it on the p7 thread then we run the risk of blocking + // on the udp send. + + // todo : consider a more efficent lock mechasium + //uint16_t NUM_SLOTS = 20;//10* 2^mu + + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return -1; + } + + // save the curren time, sfn and slot + pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); + slot_ahead = 6; + uint32_t sfn_slot_tx = sfnslot_add_slot(sfn, slot, slot_ahead); + uint16_t sfn_tx = NFAPI_SFNSLOT2SFN(sfn_slot_tx); + uint8_t slot_tx = NFAPI_SFNSLOT2SLOT(sfn_slot_tx); + + //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. + + pnf_p7->sfn = sfn_tx; + pnf_p7->slot = slot_tx; + + uint32_t rx_slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); + uint8_t buffer_index_rx = rx_slot_dec % 20; + + uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(sfn_tx,slot_tx); + uint8_t buffer_index_tx = tx_slot_dec % 20; + + // If the subframe_buffer has been configured + if(pnf_p7->_public.slot_buffer_size!= 0) // for now value is same as sf_buffer_size + { + + // apply the shift to the incoming sfn_sf + if(pnf_p7->slot_shift != 0) // see in vnf_build_send_dl_node_sync + { + uint16_t shifted_slot = slot + pnf_p7->slot_shift; + + // adjust for wrap-around + if(shifted_slot < 0) + shifted_slot += NFAPI_MAX_SFNSLOTDEC; + else if(shifted_slot > NFAPI_MAX_SFNSLOTDEC) + shifted_slot -= NFAPI_MAX_SFNSLOTDEC; + + // NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/slot (%d -> %d)\n", pnf_p7->sfn_slot_shift, NFAPI_SFNSF2DEC(sfn_slot), shifted_sfn_slot); + slot = shifted_slot; + + // + // DJP - why does the shift not apply to pnf_p7->sfn_sf??? + // + + pnf_p7->slot_shift = 0; + } + + nfapi_pnf_p7_slot_buffer_t* rx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_rx]); + + nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); + + // if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d slot_buffer->sfn_sf:%d tx_slot_buffer->sfn_slot:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] " + // "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", + // __FUNCTION__, + // pnf_p7->slot_shift, + // NFAPI_SFNSLOT2DEC(rx_slot_buffer->sfn, rx_slot_buffer->slot), + // NFAPI_SFNSLOT2DEC(tx_slot_buffer->sfn, tx_slot_buffer->slot), + // slot_dec, buffer_index_rx, rx_slot_buffer->dl_tti_req, rx_slot_buffer->tx_data_req, + // tx_slot_dec, buffer_index_tx, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); + //TODO: Change later if required + + // todo : how to handle the messages we don't have, send dummies for + // now + + //printf("tx_subframe_buffer->sfn_sf:%d sfn_sf_tx:%d\n", tx_subframe_buffer->sfn_sf, sfn_sf_tx); + //printf("subframe_buffer->sfn_sf:%d sfn_sf:%d\n", subframe_buffer->sfn_sf, sfn_sf); + //printf("tx_slot_buff_sfn - %d, tx_slot_buf_slot - %d, sfn_tx = %d, sllot_tx - %d \n",tx_slot_buffer->sfn,tx_slot_buffer->slot,sfn_tx,slot_tx); + // if(tx_slot_buffer->slot == slot_tx && tx_slot_buffer->sfn == sfn_tx) + // { + + //checking in the tx slot buffers to see if a p7 msg is present. todo: what if it's a mixed slot? + + if(tx_slot_buffer->tx_data_req != 0 && tx_slot_buffer->tx_data_req->SFN == sfn_tx && tx_slot_buffer->tx_data_req->Slot == slot_tx) + { + + if(pnf_p7->_public.tx_data_req_fn) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling tx_data_req_fn in SFN/slot %d.%d \n",sfn,slot); + LOG_D(PHY, "Process tx_data SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); + (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); + } + } + else + { + // send dummy + if(pnf_p7->_public.tx_data_req_fn && pnf_p7->_public.dummy_slot.tx_data_req) + { + pnf_p7->_public.dummy_slot.tx_data_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.tx_data_req->Slot = slot_tx; + + (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), pnf_p7->_public.dummy_slot.tx_data_req); + } + } + + if(tx_slot_buffer->dl_tti_req != 0 && tx_slot_buffer->dl_tti_req->SFN == sfn_tx && tx_slot_buffer->dl_tti_req->Slot == slot_tx) + { + if(pnf_p7->_public.dl_tti_req_fn) + { + LOG_D(PHY, "Process dl_tti SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); + (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->dl_tti_req); + } + } + else + { + // send dummy + if(pnf_p7->_public.dl_tti_req_fn && pnf_p7->_public.dummy_slot.dl_tti_req) + { + pnf_p7->_public.dummy_slot.dl_tti_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.dl_tti_req->Slot = slot_tx; + (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.dl_tti_req); + } + } + + + if(tx_slot_buffer->ul_dci_req!= 0 && tx_slot_buffer->ul_dci_req->SFN == sfn_tx && tx_slot_buffer->ul_dci_req->Slot == slot_tx) + { + if(pnf_p7->_public.ul_dci_req_fn) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling UL_dci_req_fn in SFN/slot %d.%d \n",sfn,slot); + LOG_D(PHY, "Process ul_dci SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); + (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_dci_req); + } + } + else + { + //send dummy + if(pnf_p7->_public.ul_dci_req_fn && pnf_p7->_public.dummy_slot.ul_dci_req) + { + pnf_p7->_public.dummy_slot.ul_dci_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.ul_dci_req->Slot = slot_tx; + (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_dci_req); + } + } + + //deallocate slot buffers after passing down the PDUs to PHY processing + + if(tx_slot_buffer->dl_tti_req != 0) + { + deallocate_nfapi_dl_tti_request(tx_slot_buffer->dl_tti_req, pnf_p7); + tx_slot_buffer->dl_tti_req = 0; + LOG_D(PHY,"SFN/slot %d.%d Buffer index : %d freed \n",sfn_tx,slot_tx,buffer_index_tx); + } + + if(tx_slot_buffer->tx_data_req != 0) + { + deallocate_nfapi_tx_data_request(tx_slot_buffer->tx_data_req, pnf_p7); + tx_slot_buffer->tx_data_req = 0; + } + + if(tx_slot_buffer->ul_dci_req != 0) + { + deallocate_nfapi_ul_dci_request(tx_slot_buffer->ul_dci_req, pnf_p7); + tx_slot_buffer->ul_dci_req = 0; + } + + + //checking in the rx slot buffers to see if a p7 msg is present. + + if(rx_slot_buffer->ul_tti_req != 0 && rx_slot_buffer->ul_tti_req->SFN == sfn && rx_slot_buffer->ul_tti_req->Slot == slot) + { + if(pnf_p7->_public.ul_tti_req_fn) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling UL_tti_req_fn in SFN/slot %d.%d \n",sfn,slot); + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), rx_slot_buffer->ul_tti_req); + } + } + else + { + // send dummy + if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) + { + pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; + pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; + LOG_D(PHY, "Process ul_tti SFN/slot %d.%d buffer index: %d \n",sfn,slot,buffer_index_rx); + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); + } + } + if(rx_slot_buffer->ul_tti_req != 0) + { + deallocate_nfapi_ul_tti_request(rx_slot_buffer->ul_tti_req, pnf_p7); + rx_slot_buffer->ul_tti_req = 0; + + } + + //reset slot buffer + + if ( rx_slot_buffer->dl_tti_req == 0 && + rx_slot_buffer->tx_data_req == 0 && + rx_slot_buffer->ul_tti_req == 0) + { + memset(&(pnf_p7->slot_buffer[buffer_index_rx]), 0, sizeof(nfapi_pnf_p7_slot_buffer_t)); + pnf_p7->slot_buffer[buffer_index_rx].sfn = -1; + pnf_p7->slot_buffer[buffer_index_rx].slot = -1; + } + + //printf("pnf_p7->_public.timing_info_mode_periodic:%d pnf_p7->timing_info_period_counter:%d pnf_p7->_public.timing_info_period:%d\n", pnf_p7->_public.timing_info_mode_periodic, pnf_p7->timing_info_period_counter, pnf_p7->_public.timing_info_period); + //printf("pnf_p7->_public.timing_info_mode_aperiodic:%d pnf_p7->timing_info_aperiodic_send:%d\n", pnf_p7->_public.timing_info_mode_aperiodic, pnf_p7->timing_info_aperiodic_send); + //printf("pnf_p7->timing_info_ms_counter:%d\n", pnf_p7->timing_info_ms_counter); + + //send the periodic timing info if configured + if(pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) + { + pnf_nr_pack_and_send_timing_info(pnf_p7); + + pnf_p7->timing_info_period_counter = 0; + } + else if(pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send) + { + pnf_nr_pack_and_send_timing_info(pnf_p7); + + pnf_p7->timing_info_aperiodic_send = 0; + } + else + { + pnf_p7->timing_info_ms_counter++; + } + + } + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } + + return 0; +} + + + int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) { // We could either send an event to the p7 thread have have it run the @@ -621,8 +1179,8 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) pnf_p7->sf_start_time_hr = pnf_get_current_time_hr(); pnf_p7->sfn_sf = sfn_sf; - uint32_t sfn_sf_tx = sfnsf_add_sf(sfn_sf, sf_ahead); - uint32_t tx_sfn_sf_dec = NFAPI_SFNSF2DEC(sfn_sf_tx); + uint32_t sfn_sf_tx = sfnsf_add_sf(sfn_sf, sf_ahead); + uint32_t tx_sfn_sf_dec = NFAPI_SFNSF2DEC(sfn_sf_tx); // If the subframe_buffer has been configured if(pnf_p7->_public.subframe_buffer_size != 0) @@ -890,6 +1448,82 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) // return 1 if in window // return 0 if out of window + +uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, pnf_p7_t* phy) +{ + uint32_t recv_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); + uint32_t current_sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + //printf("p7_msg_sfn: %d, p7_msg_slot: %d, phy_sfn:%d , phy_slot:%d \n",sfn,slot,phy->sfn,phy->slot); + uint8_t in_window = 0; + uint8_t timing_window = phy->_public.slot_buffer_size; + + // if(recv_sfn_slot_dec <= current_sfn_slot_dec) + // { + // // Need to check for wrap in window + // if(((recv_sfn_slot_dec + timing_window) % NFAPI_MAX_SFNSLOTDEC) < recv_sfn_slot_dec) + // { + // if(current_sfn_slot_dec > ((recv_sfn_slot_dec + timing_window) % NFAPI_MAX_SFNSLOTDEC)) + // { + // // out of window + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is late %d (with wrap)\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + // } + // else + // { + // // ok + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d (with wrap)\n", current_sfn_sf_dec, name, recv_sfn_sf_dec); + // in_window = 1; + // } + // } + // else + // { + // if((current_sfn_slot_dec - recv_sfn_slot_dec) <= timing_window) + // { + // // in window + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + // in_window = 1; + // } + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in late %d (delta:%d)\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec)); + // } + + // } + // else + // { + // // Need to check it is in window + // if((recv_sfn_slot_dec - current_sfn_slot_dec) <= timing_window) + // { + // // in window + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_sf_dec, name, recv_sfn_sf_dec); + // in_window = 1; + // } + // else + // { + // // too far in the future + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (recv_sfn_slot_dec - current_sfn_slot_dec), timing_window); + // } + + // } + if(current_sfn_slot_dec <= recv_sfn_slot_dec + timing_window){ + in_window = 1; + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + } + else if(current_sfn_slot_dec + NFAPI_MAX_SFNSLOTDEC <= recv_sfn_slot_dec + timing_window){ //checking for wrap + in_window = 1; + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + } + + else + { + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); + + }//Need to add more cases + + + return in_window; +} + + + uint8_t is_p7_request_in_window(uint16_t sfnsf, const char* name, pnf_p7_t* phy) { uint32_t recv_sfn_sf_dec = NFAPI_SFNSF2DEC(sfnsf); @@ -943,8 +1577,80 @@ uint8_t is_p7_request_in_window(uint16_t sfnsf, const char* name, pnf_p7_t* phy) } -// P7 messages -// +// P7 messages +void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) +{ + //NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req Received\n"); + nfapi_nr_dl_tti_request_t* req = allocate_nfapi_dl_tti_request(pnf_p7); + + if(req == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_dl_tti_request structure\n"); + return; + } + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_dl_tti_request_t), &(pnf_p7->_public.codec_config)); + + if(unpack_result == 0) + { + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + if(is_nr_p7_request_in_window(req->SFN,req->Slot, "dl_tti_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % 20; + + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE DL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); + + // if there is already an dl_tti_req make sure we free it. + if(pnf_p7->slot_buffer[buffer_index].dl_tti_req != 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "%s() is_nr_p7_request_in_window()=TRUE buffer_index occupied - free it first sfn_slot:%d buffer_index:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(req->SFN,req->Slot), buffer_index); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing dl_config_req at index %d (%d/%d)", + // pMyPhyInfo->sfnSf, bufferIdx, + // SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf)); + deallocate_nfapi_dl_tti_request(pnf_p7->slot_buffer[buffer_index].dl_tti_req, pnf_p7); + } + + // filling dl_tti_request in slot buffer + pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; + pnf_p7->slot_buffer[buffer_index].slot = req->Slot; + pnf_p7->slot_buffer[buffer_index].dl_tti_req = req; + + pnf_p7->stats.dl_tti_ontime++; + } + else + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "NOT storing dl_config_req SFN/SF %d\n", req->sfn_sf); + deallocate_nfapi_dl_tti_request(req, pnf_p7); + + if(pnf_p7->_public.timing_info_mode_aperiodic) + { + pnf_p7->timing_info_aperiodic_send = 1; + } + + pnf_p7->stats.dl_tti_late++; + } + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack dl_tti_req"); + deallocate_nfapi_dl_tti_request(req, pnf_p7); + } +} + + void pnf_handle_dl_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req Received\n"); @@ -1035,6 +1741,82 @@ void pnf_handle_dl_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_ } } + +void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) +{ + //NFAPI_TRACE(NFAPI_TRACE_INFO, "UL_CONFIG.req Received\n"); + + nfapi_nr_ul_tti_request_t* req = allocate_nfapi_ul_tti_request(pnf_p7); + + if(req == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_ul_tti_request structure\n"); + return; + } + + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_ul_tti_request_t), &(pnf_p7->_public.codec_config)); + + if(unpack_result == 0) + { + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + if(is_nr_p7_request_in_window(req->SFN,req->Slot, "ul_tti_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = (sfn_slot_dec % 20); + + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); + + if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing ul_config_req at index %d (%d/%d)", + // pMyPhyInfo->sfnSf, bufferIdx, + // SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf)); + + deallocate_nfapi_ul_tti_request(pnf_p7->slot_buffer[buffer_index].ul_tti_req, pnf_p7); + } + + //filling slot buffer + + pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; + pnf_p7->slot_buffer[buffer_index].slot = req->Slot; + pnf_p7->slot_buffer[buffer_index].ul_tti_req = req; + + pnf_p7->stats.ul_tti_ontime++; + } + else + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] NOT storing ul_tti_req OUTSIDE OF TRANSMIT BUFFER WINDOW SFN/SLOT %d\n", NFAPI_SFNSLOT2DEC(pnf_p7->sfn,pnf_p7->slot), NFAPI_SFNSLOT2DEC(req->SFN,req->Slot)); + deallocate_nfapi_ul_tti_request(req, pnf_p7); + + if(pnf_p7->_public.timing_info_mode_aperiodic) + { + pnf_p7->timing_info_aperiodic_send = 1; + } + + pnf_p7->stats.ul_tti_late++; + } + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_tti_req\n"); + deallocate_nfapi_ul_tti_request(req, pnf_p7); + } +} + void pnf_handle_ul_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "UL_CONFIG.req Received\n"); @@ -1107,7 +1889,79 @@ void pnf_handle_ul_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_ } } + +void pnf_handle_ul_dci_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) +{ + //NFAPI_TRACE(NFAPI_TRACE_INFO, "HI_DCI0.req Received\n"); + + nfapi_nr_ul_dci_request_t* req = allocate_nfapi_ul_dci_request(pnf_p7); + + if(req == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate nfapi_ul_dci_request structure\n"); + return; + } + + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_ul_dci_request_t), &pnf_p7->_public.codec_config); + + if(unpack_result == 0) + { + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + if(is_nr_p7_request_in_window(req->SFN,req->Slot,"ul_dci_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % 20; + + if(pnf_p7->slot_buffer[buffer_index].ul_dci_req!= 0) + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing hi_dci0_req at index %d (%d/%d)", + // pMyPhyInfo->sfnSf, bufferIdx, + // SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf)); + + deallocate_nfapi_ul_dci_request(pnf_p7->slot_buffer[buffer_index].ul_dci_req, pnf_p7); + } + + pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; + pnf_p7->slot_buffer[buffer_index].ul_dci_req = req; + + pnf_p7->stats.ul_dci_ontime++; + + } + else + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] NOT storing hi_dci0_req SFN/SF %d/%d\n", pMyPhyInfo->sfnSf, SFNSF2SFN(req->sfn_sf), SFNSF2SF(req->sfn_sf)); + deallocate_nfapi_ul_dci_request(req, pnf_p7); + + if(pnf_p7->_public.timing_info_mode_aperiodic) + { + pnf_p7->timing_info_aperiodic_send = 1; + } + + pnf_p7->stats.ul_dci_late++; + } + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack UL DCI req\n"); + deallocate_nfapi_ul_dci_request(req, pnf_p7); + } +} + + + void pnf_handle_hi_dci0_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) + { //NFAPI_TRACE(NFAPI_TRACE_INFO, "HI_DCI0.req Received\n"); @@ -1175,6 +2029,87 @@ void pnf_handle_hi_dci0_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 } } + +void pnf_handle_tx_data_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) +{ + //NFAPI_TRACE(NFAPI_TRACE_INFO, "TX.req Received\n"); + + nfapi_nr_tx_data_request_t* req = allocate_nfapi_tx_data_request(pnf_p7); + + if(req == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_tx_request structure\n"); + return; + } + + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_tx_data_request_t), &pnf_p7->_public.codec_config); + if(unpack_result == 0) + { + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + if(is_nr_p7_request_in_window(req->SFN, req->Slot,"tx_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % 20; + + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + + //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE TX_DATA_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); +#if 0 + if (0 && NFAPI_SFNSF2DEC(req->sfn_sf)%100==0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX_REQ.req sfn_sf:%d pdus:%d - TX_REQ is within window\n", + __FUNCTION__, + NFAPI_SFNSF2DEC(req->sfn_sf), + req->tx_request_body.number_of_pdus); +#endif + + if(pnf_p7->slot_buffer[buffer_index].tx_data_req != 0) + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing tx_req at index %d (%d/%d)", + // pMyPhyInfo->sfnSf, bufferIdx, + // SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf)); + + deallocate_nfapi_tx_data_request(pnf_p7->slot_buffer[buffer_index].tx_data_req, pnf_p7); + } + + pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; + pnf_p7->slot_buffer[buffer_index].slot = req->Slot; + pnf_p7->slot_buffer[buffer_index].tx_data_req = req; + + pnf_p7->stats.tx_data_ontime++; + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() TX_DATA_REQUEST Request is outside of window REQ:SFN_SLOT:%d CURR:SFN_SLOT:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(req->SFN,req->Slot), NFAPI_SFNSLOT2DEC(pnf_p7->sfn,pnf_p7->slot)); + + deallocate_nfapi_tx_data_request(req, pnf_p7); + + if(pnf_p7->_public.timing_info_mode_aperiodic) + { + pnf_p7->timing_info_aperiodic_send = 1; + } + + pnf_p7->stats.tx_data_late++; + } + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + } + else + { + deallocate_nfapi_tx_data_request(req, pnf_p7); + } +} + + + void pnf_handle_tx_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "TX.req Received\n"); @@ -1437,6 +2372,29 @@ uint32_t calculate_t2(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_t return t2; } +uint32_t calculate_nr_t2(uint32_t now_time_hr, uint16_t sfn,uint16_t slot, uint32_t slot_start_time_hr) +{ + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); + uint32_t t2 = (NFAPI_SFNSLOT2DEC(sfn, slot) * 500) + slot_time_us; + + if (0) + { + static uint32_t prev_t2 = 0; + + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s(now_time_hr:%u sfn:%d slot:%d slot_start_time_Hr:%u) slot_time_us:%u t2:%u prev_t2:%u diff:%u\n", + __FUNCTION__, + now_time_hr, NFAPI_SFNSLOT2DEC(sfn, slot), slot_start_time_hr, + slot_time_us, + t2, + prev_t2, + t2-prev_t2); + + prev_t2 = t2; + } + + return t2; +} + uint32_t calculate_t3(uint16_t sfn_sf, uint32_t sf_start_time_hr) { uint32_t now_time_hr = pnf_get_current_time_hr(); @@ -1448,6 +2406,17 @@ uint32_t calculate_t3(uint16_t sfn_sf, uint32_t sf_start_time_hr) return t3; } +uint32_t calculate_nr_t3(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr) +{ + uint32_t now_time_hr = pnf_get_current_time_hr(); + + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); + + uint32_t t3 = (NFAPI_SFNSLOT2DEC(sfn, slot) * 500) + slot_time_us; + + return t3; +} + void pnf_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { nfapi_dl_node_sync_t dl_node_sync; @@ -1498,6 +2467,60 @@ void pnf_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, u pnf_p7_pack_and_send_p7_message(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync)); } + +void pnf_nr_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +{ + //printf("Received DL node sync"); + + nfapi_nr_dl_node_sync_t dl_node_sync; + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_NODE_SYNC Received\n"); + + if (pRecvMsg == NULL || pnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return; + } + + // unpack the message + if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &dl_node_sync, sizeof(dl_node_sync), &pnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + return; + } + + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + + if (dl_node_sync.delta_sfn_slot != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Will shift Slot timing by %d on next slot\n", dl_node_sync.delta_sfn_slot); + + pnf_p7->slot_shift = dl_node_sync.delta_sfn_slot; + } + + nfapi_nr_ul_node_sync_t ul_node_sync; + memset(&ul_node_sync, 0, sizeof(ul_node_sync)); + ul_node_sync.header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC; + ul_node_sync.header.phy_id = dl_node_sync.header.phy_id; + ul_node_sync.t1 = dl_node_sync.t1; + ul_node_sync.t2 = calculate_nr_t2(rx_hr_time, pnf_p7->sfn,pnf_p7->slot, pnf_p7->slot_start_time_hr); + ul_node_sync.t3 = calculate_nr_t3(pnf_p7->sfn,pnf_p7->slot, pnf_p7->slot_start_time_hr); + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + + pnf_nr_p7_pack_and_send_p7_message(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync)); + //printf("\nSSent UL Node Sync sfn:%d,slot:%d\n",pnf_p7->sfn,pnf_p7->slot); +} + void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { nfapi_p7_message_header_t header; @@ -1528,7 +2551,6 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, case NFAPI_DL_NODE_SYNC: pnf_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); break; - case NFAPI_DL_CONFIG_REQUEST: pnf_handle_dl_config_request(pRecvMsg, recvMsgLen, pnf_p7); break; @@ -1544,7 +2566,7 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, case NFAPI_TX_REQUEST: pnf_handle_tx_request(pRecvMsg, recvMsgLen, pnf_p7); break; - + case NFAPI_LBT_DL_CONFIG_REQUEST: pnf_handle_lbt_dl_config_request(pRecvMsg, recvMsgLen, pnf_p7); break; @@ -1569,6 +2591,64 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, } } +void pnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +{ + nfapi_p7_message_header_t header; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return; + } + + // unpack the message header + if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + switch (header.message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + pnf_nr_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + pnf_handle_dl_tti_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + pnf_handle_ul_tti_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + pnf_handle_ul_dci_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + pnf_handle_tx_data_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + default: + { + if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + pnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, pnf_p7, header.message_id); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P7 Unknown message ID %d\n", __FUNCTION__, header.message_id); + } + } + break; + } +} + void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { nfapi_p7_message_header_t messageHeader; @@ -1674,6 +2754,114 @@ void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, ui pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 1000); } + +void pnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +{ + nfapi_p7_message_header_t messageHeader; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%d %d %d)\n", pRecvMsg, recvMsgLen, pnf_p7); + return; + } + + // unpack the message header + if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &pnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + + if(pnf_p7->_public.checksum_enabled) + { + uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if(checksum != messageHeader.checksum) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum); + return; + } + } + + if(m == 0 && segment_num == 0) + { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + pnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); + } + else + { + pnf_p7_rx_message_t* rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, sequence_num, segment_num, m, pRecvMsg, recvMsgLen); + + if(rx_msg->num_segments_received == rx_msg->num_segments_expected) + { + // send the buffer on + uint16_t i = 0; + uint16_t length = 0; + for(i = 0; i < rx_msg->num_segments_expected; ++i) + { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0); + } + + if(pnf_p7->reassemby_buffer_size < length) + { + pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer); + pnf_p7->reassemby_buffer = 0; + } + + if(pnf_p7->reassemby_buffer == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length); + pnf_p7->reassemby_buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, length); + + if(pnf_p7->reassemby_buffer == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(pnf_p7->reassemby_buffer, 0, length); + pnf_p7->reassemby_buffer_size = length; + } + + uint16_t offset = 0; + for(i = 0; i < rx_msg->num_segments_expected; ++i) + { + if(i == 0) + { + memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } + else + { + memcpy(pnf_p7->reassemby_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH; + } + } + + + pnf_nr_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); + + + // delete the structure + pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg); + } + } + + pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 1000); + +} + + void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) { int recvfrom_result = 0; @@ -1708,6 +2896,7 @@ void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) if(recvfrom_result > 0) { pnf_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); + //printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); } } else if(recvfrom_result == 0) @@ -1735,6 +2924,68 @@ void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) while(recvfrom_result > 0); } +void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) +{ + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + remote_addr.sin_family = 2; //hardcoded + do + { + // peek the header + uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); + if(recvfrom_result > 0) + { + // get the segment size + nfapi_p7_message_header_t header; + nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, 34, 0); + + // resize the buffer if we have a large segment + if(header.message_length > pnf_p7->rx_message_buffer_size) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length); + pnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(pnf_p7->p7_sock, pnf_p7->rx_message_buffer, header.message_length, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); + + now_hr_time = pnf_get_current_time_hr(); //DJP - moved to here - get closer timestamp??? + + if(recvfrom_result > 0) + { + pnf_nr_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); + //printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); + } + } + else if(recvfrom_result == 0) + { + // recv zero length message + recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); + } + + if(recvfrom_result == -1) + { + if(errno == EAGAIN || errno == EWOULDBLOCK) + { + // return to the select + //NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } + + // need to update the time as we would only use the value from the + // select + } + while(recvfrom_result > 0); +} + + int pnf_p7_message_pump(pnf_p7_t* pnf_p7) { @@ -1786,7 +3037,7 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(pnf_p7->_public.local_p7_port); + addr.sin_port = pnf_p7->_public.local_p7_port; if(pnf_p7->_public.local_p7_addr == 0) { @@ -1827,6 +3078,9 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) uint32_t now_hr_time = pnf_get_current_time_hr(); + + + if(selectRetval == 0) { // timeout @@ -1845,7 +3099,8 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) continue; } - if(FD_ISSET(pnf_p7->p7_sock, &rfds)) + if(FD_ISSET(pnf_p7->p7_sock, &rfds)) + { pnf_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); } @@ -1870,3 +3125,143 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) return 0; } + +int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) +{ + + // initialize the mutex lock + if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); + return -1; + } + + if(pthread_mutex_init(&(pnf_p7->pack_mutex), NULL) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); + return -1; + } + + // create the pnf p7 socket + if ((pnf_p7->p7_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); + return -1; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 socket created (%d)...\n", pnf_p7->p7_sock); + + // configure the UDP socket options + int reuseaddr_enable = 1; + if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_enable, sizeof(int)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEADDR) failed errno: %d\n", errno); + return -1; + } + +/* + int reuseport_enable = 1; + if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEPORT, &reuseport_enable, sizeof(int)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEPORT) failed errno: %d\n", errno); + return -1; + } +*/ + + int iptos_value = FAPI2_IP_DSCP << 2; + if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno); + return -1; + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = pnf_p7->_public.local_p7_port; + + if(pnf_p7->_public.local_p7_addr == 0) + { + addr.sin_addr.s_addr = INADDR_ANY; + } + else + { + //addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.local_p7_addr); + if(inet_aton(pnf_p7->_public.local_p7_addr, &addr.sin_addr) == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "inet_aton failed\n"); + } + } + + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 binding %d too %s:%d\n", pnf_p7->p7_sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + if (bind(pnf_p7->p7_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 bind error fd:%d errno: %d\n", pnf_p7->p7_sock, errno); + return -1; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n"); + + while(pnf_p7->terminate == 0) + { + fd_set rfds; + int selectRetval = 0; + + // select on a timeout and then get the message + FD_ZERO(&rfds); + FD_SET(pnf_p7->p7_sock, &rfds); + + struct timeval timeout; + timeout.tv_sec = 100; + timeout.tv_usec = 0; + + selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout); + + uint32_t now_hr_time = pnf_get_current_time_hr(); + + + + + if(selectRetval == 0) + { + // timeout + continue; + } + else if (selectRetval == -1 && (errno == EINTR)) + { + // interrupted by signal + NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 Signal Interrupt %d\n", errno); + continue; + } + else if (selectRetval == -1) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 select() failed\n"); + sleep(1); + continue; + } + + if(FD_ISSET(pnf_p7->p7_sock, &rfds)) + + { + pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); + } + } + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); + + // close the connection and socket + if (close(pnf_p7->p7_sock) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "close failed errno: %d\n", errno); + } + + if(pthread_mutex_destroy(&(pnf_p7->pack_mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); + } + + if(pthread_mutex_destroy(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); + } + + return 0; +} diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 24e73ae9b3..0db1feb398 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -31,7 +31,7 @@ nfapi_pnf_p7_config_t* nfapi_pnf_p7_config_create() _this->_public.segment_size = 1400; _this->max_num_segments = 8; - _this->_public.subframe_buffer_size = 8; + _this->_public.subframe_buffer_size = 8;// TODO: Initialize the slot_buffer size _this->_public.timing_info_mode_periodic = 1; _this->_public.timing_info_period = 32; _this->_public.timing_info_mode_aperiodic = 1; @@ -76,6 +76,26 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config) return 0; } +int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config) +{ + // Verify that config is not null + if(config == 0) + return -1; + + // Make sure to set the defined trace function before using NFAPI_TRACE + if(config->trace) + nfapi_trace_g = config->trace; + + pnf_p7_t* _this = (pnf_p7_t*)(config); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + pnf_nr_p7_message_pump(_this); + + return 0; +} + + int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config) { // Verify that config is not null @@ -88,6 +108,16 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config) return 0; } +int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot) +{ + // Verify that config is not null + if(config == 0) + return -1; + + pnf_p7_t* _this = (pnf_p7_t*)(config); + + return pnf_p7_slot_ind(_this, phy_id, sfn, slot); +} int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf) { @@ -235,3 +265,77 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } + +//NR UPLINK INDICATION + +int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); +} + +int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); +} + +int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); +} + +int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); +} + +int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); +} + +int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); +} diff --git a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c index d2ab031ad4..bd6bedbea5 100644 --- a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c +++ b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c @@ -48,6 +48,9 @@ typedef struct phy_info uint8_t enabled; uint16_t phy_id; uint16_t sfn_sf; + uint16_t sfn; + uint16_t slot; + pthread_t thread; @@ -1207,6 +1210,12 @@ void send_dl_subframe_msgs_interleaved(int p7Sock, int phy_id, struct sockaddr_i //free(req.tx_request_body.tx_pdu_list); } +void send_slot_indication(phy_info_t* phy_info) +{ + // DONE: add sfn and slot as members in the phy_info + nfapi_pnf_p7_slot_ind(phy_info->config, phy_info->phy_id, phy_info->sfn, phy_info->slot); +} + void send_subframe_indication(phy_info_t* phy_info) { nfapi_pnf_p7_subframe_ind(phy_info->config, phy_info->phy_id, phy_info->sfn_sf); diff --git a/nfapi/open-nFAPI/vnf/inc/vnf.h b/nfapi/open-nFAPI/vnf/inc/vnf.h index 4fd8d2b91d..b16b842606 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf.h @@ -35,9 +35,13 @@ typedef struct int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); +int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); + int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf); +int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf); + void nfapi_vnf_phy_info_list_add(nfapi_vnf_config_t* config, nfapi_vnf_phy_info_t* info); nfapi_vnf_phy_info_t* nfapi_vnf_phy_info_list_find(nfapi_vnf_config_t* config, uint16_t phy_id); diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index fc2ab4e6b5..4fcc99f79b 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -25,7 +25,6 @@ #define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF)) - typedef struct { uint8_t* buffer; uint16_t length; @@ -77,6 +76,9 @@ typedef struct nfapi_vnf_p7_connection_info { int32_t sf_offset_filtered; int32_t sf_offset_trend; int32_t sf_offset; + int32_t slot_offset; + int32_t slot_offset_trend; + int32_t slot_offset_filtered; uint16_t zero_count; int32_t adjustment; int32_t insync_minor_adjustment; @@ -85,8 +87,10 @@ typedef struct nfapi_vnf_p7_connection_info { uint32_t previous_t1; uint32_t previous_t2; int32_t previous_sf_offset_filtered; - + int32_t previous_slot_offset_filtered; int sfn_sf; + int sfn; + int slot; int socket; struct sockaddr_in local_addr; @@ -111,6 +115,7 @@ typedef struct { nfapi_vnf_p7_connection_info_t* p7_connections; int socket; uint32_t sf_start_time_hr; + uint32_t slot_start_time_hr; uint8_t* rx_message_buffer; // would this be better put in the p7 conenction info? uint16_t rx_message_buffer_size; @@ -120,14 +125,19 @@ uint32_t vnf_get_current_time_hr(void); uint16_t increment_sfn_sf(uint16_t sfn_sf); int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info); +int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info); + int send_mac_subframe_indications(vnf_p7_t* config); +int send_mac_slot_indications(vnf_p7_t* config); int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7 ); +int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7 ); void vnf_p7_connection_info_list_add(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* node); nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p7, uint16_t phy_id); nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_delete(vnf_p7_t* vnf_p7, uint16_t phy_id); int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); +int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu); diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index 5abf6b75c3..31328393c9 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -19,6 +19,7 @@ #include "nfapi_interface.h" #include "nfapi_nr_interface_scf.h" +#include "nfapi_nr_interface.h" #include "debug.h" @@ -120,6 +121,7 @@ typedef struct nfapi_vnf_config * * \todo Do we need to send the address information of the PNF? */ + int (*pnf_nr_connection_indication)(nfapi_vnf_config_t* config, int p5_idx); int (*pnf_connection_indication)(nfapi_vnf_config_t* config, int p5_idx); /*! \brief Callback indicating that a pnf has lost connection @@ -160,6 +162,7 @@ typedef struct nfapi_vnf_config * then the substructure pointers should be set to 0 and then the client should * use the codec_config.deallocate function to release it at a future point */ + int (*pnf_nr_param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_param_response_t* resp); int (*pnf_param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_response_t* resp); /*! A callback for the PNF_CONFIG.resp @@ -182,7 +185,8 @@ typedef struct nfapi_vnf_config * use the codec_config.deallocate function to release it at a future point */ int (*pnf_config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_response_t* resp); - + int (*pnf_nr_config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_config_response_t* resp); + /*! A callback for the PNF_START.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -203,7 +207,8 @@ typedef struct nfapi_vnf_config * use the codec_config.deallocate function to release it at a future point */ int (*pnf_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* resp); - + int (*pnf_nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_start_response_t* resp); + /*! A callback for the PNF_STOP.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -249,6 +254,7 @@ typedef struct nfapi_vnf_config * use the codec_config.deallocate function to release it at a future point */ int (*param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_response_t* resp); + int (*nr_param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_param_response_scf_t* resp); /*! A callback for the CONFIG.response * \param config A pointer to the vnf configuration @@ -266,8 +272,9 @@ typedef struct nfapi_vnf_config * then the substructure pointers should be set to 0 and then the client should * use the codec_config.deallocate function to release it at a future point */ + int (*nr_config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_config_response_scf_t* resp); int (*config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_response_t* resp); - + /*! A callback for the START.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -285,6 +292,7 @@ typedef struct nfapi_vnf_config * use the codec_config.deallocate function to release it at a future point */ int (*start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* resp); + int (*nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_response_scf_t* resp); /*! A callback for the STOP.resp * \param config A pointer to the vnf configuration @@ -469,6 +477,8 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config); * * This function will not return untill nfapi_vnf_stop is called */ +int nfapi_nr_vnf_start(nfapi_vnf_config_t* config); + int nfapi_vnf_start(nfapi_vnf_config_t* config); /*! Stop the VNF library. @@ -500,6 +510,7 @@ int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy * \return 0 means success, -1 failure */ int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req); +int nfapi_nr_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_param_request_t* req); /*! Send the PNF_CONFIG.request * \param config A pointer to a vnf config @@ -508,6 +519,7 @@ int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_pa * \return 0 means success, -1 failure */ int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_config_request_t* req); +int nfapi_nr_vnf_pnf_config_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_nr_pnf_config_request_t* req); /*! Send the PNF_START.request * \param config A pointer to a vnf config @@ -516,6 +528,7 @@ int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_co * \return 0 means success, -1 failure */ int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_start_request_t* req); +int nfapi_nr_vnf_pnf_start_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_nr_pnf_start_request_t* req); /*! Send the PNF_STOP.request * \param config A pointer to a vnf config @@ -532,6 +545,7 @@ int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_stop * \return 0 means success, -1 failure */ int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req); +int nfapi_nr_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_param_request_scf_t* req); /*! Send the CONFIG.request * \param config A pointer to a vnf config @@ -539,6 +553,7 @@ int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_requ * \param req A pointer to a CONFIG.request message structure * \return 0 means success, -1 failure */ +int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_config_request_scf_t* req); int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req); /*! Send the START.request @@ -548,6 +563,7 @@ int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_re * \return 0 means success, -1 failure */ int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req); +int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_request_scf_t* req); /*! Send the STOP.request * \param config A pointer to a vnf config @@ -692,6 +708,7 @@ typedef struct nfapi_vnf_p7_config */ int (*subframe_indication)(struct nfapi_vnf_p7_config* config, uint16_t phy_id, uint16_t sfn_sf); + int (*slot_indication)(struct nfapi_vnf_p7_config* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); /*! A callback for the HARQ.indication * \param config A pointer to the vnf p7 configuration @@ -835,7 +852,15 @@ typedef struct nfapi_vnf_p7_config * use the codec_config.deallocate function to release it at a future point */ int (*nrach_indication)(struct nfapi_vnf_p7_config* config, nfapi_nrach_indication_t* ind); - + + //The NR indication functions below copy uplink information received at the VNF into the UL info struct + int (*nr_slot_indication)(nfapi_nr_slot_indication_scf_t* ind); + int (*nr_crc_indication)(nfapi_nr_crc_indication_t* ind); + int (*nr_rx_data_indication)(nfapi_nr_rx_data_indication_t* ind); + int (*nr_uci_indication)(nfapi_nr_uci_indication_t* ind); + int (*nr_rach_indication)(nfapi_nr_rach_indication_t* ind); + int (*nr_srs_indication)(nfapi_nr_srs_indication_t* ind); + /*! A callback for any vendor extension messages * \param config A pointer to the vnf p7 configuration * \param msg A data structure for the decoded vendor extention message allocated @@ -885,6 +910,8 @@ void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config); */ int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config); +int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config); + /*! Stop the VNF P7 library. * \param config A pointer to an vnf p7 configuration structure @@ -950,7 +977,7 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req); - +int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req); /*! Send the HI_DCI0.request * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded HI_DCI0.request. @@ -960,7 +987,7 @@ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_re * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); - +int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req); /*! Send the TX.req * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded HI_DCI0.request. @@ -970,7 +997,7 @@ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_reques * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req); - +int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req); /*! Send the LBT_DL_CONFIG.requst * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded LBT_DL_CONFIG.request. diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 6800ee21d2..7fee47d6d5 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -21,9 +21,12 @@ #include #include #include +#include #include #include "vnf.h" +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" void* vnf_malloc(nfapi_vnf_config_t* config, size_t size) @@ -101,6 +104,39 @@ nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5 return 0; } +void vnf_nr_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_PARAM.reponse\n"); + + nfapi_nr_pnf_param_response_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { + // Invoke the call back + if(config->pnf_nr_param_resp) + { + (config->pnf_nr_param_resp)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { // ensure it's valid @@ -134,6 +170,40 @@ void vnf_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_con } } + +void vnf_nr_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_CONFIG_RESPONSE\n"); + + nfapi_nr_pnf_config_response_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { + // Invoke the call back + if(config->pnf_nr_config_resp) + { + (config->pnf_nr_config_resp)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { // ensure it's valid @@ -167,6 +237,38 @@ void vnf_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_co } } +void vnf_nr_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_START_RESPONSE\n"); + + nfapi_nr_pnf_start_response_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { + if(config->pnf_nr_start_resp) + { + (config->pnf_nr_start_resp)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { // ensure it's valid @@ -298,8 +400,113 @@ void vnf_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_ } } +void vnf_nr_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PARAM_RESPONSE\n"); + + nfapi_nr_param_response_scf_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { + + if (msg.error_code == NFAPI_NR_PARAM_MSG_OK) + { + nfapi_vnf_phy_info_t* phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id); + + if(msg.nfapi_config.p7_pnf_address_ipv4.tl.tag) + { + struct sockaddr_in sockAddr; + + (void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH); + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr)); + + // store address + phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr; + } + + if(msg.nfapi_config.p7_pnf_address_ipv6.tl.tag) + { + struct sockaddr_in6 sockAddr6; + char addr6[64]; + (void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH); + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv6 address: %s\n", inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6))); + } + + if (msg.nfapi_config.p7_pnf_port.tl.tag) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value); + + // store port + phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value); + } + } + + if(config->nr_param_resp) + { + (config->nr_param_resp)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + + +void vnf_nr_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CONFIG_RESPONSE\n"); + + nfapi_nr_config_response_scf_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 ) + { + // check the error code: + + if (msg.error_code == NFAPI_NR_CONFIG_MSG_OK){ + if(config->nr_config_resp) + { + (config->nr_config_resp)(config, p5_idx, &msg); + } + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { + // ensure it's valid if (pRecvMsg == NULL || config == NULL) { @@ -314,9 +521,13 @@ void vnf_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config // unpack the message if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 ) { - if(config->config_resp) - { - (config->config_resp)(config, p5_idx, &msg); + // check the error code: + + if (msg.error_code == NFAPI_MSG_OK){ + if(config->config_resp) + { + (config->config_resp)(config, p5_idx, &msg); + } } } else @@ -362,6 +573,40 @@ void vnf_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_ } } +void vnf_nr_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received START_RESPONSE\n"); + + nfapi_nr_start_response_scf_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { // check the error code + if (msg.error_code == NFAPI_NR_START_MSG_OK){ + if(config->nr_start_resp) + { + (config->nr_start_resp)(config, p5_idx, &msg); + } + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { @@ -811,6 +1056,74 @@ void vnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, nfapi_vnf_confi } } +void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config) +{ + nfapi_p4_p5_message_header_t messageHeader; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p4_p5_message: invalid input params\n"); + return; + } + + // unpack the message header + if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &config->codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + switch (messageHeader.message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: + vnf_nr_handle_pnf_param_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + vnf_nr_handle_pnf_config_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + vnf_nr_handle_pnf_start_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_PNF_STOP_RESPONSE: + vnf_handle_pnf_stop_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + vnf_nr_handle_param_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + vnf_nr_handle_config_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + vnf_nr_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + vnf_handle_stop_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + default: + { + if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + vnf_handle_vendor_extension(pRecvMsg, recvMsgLen, config, p5_idx, messageHeader.message_id); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id); + } + } + break; + } +} + void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config) { nfapi_p4_p5_message_header_t messageHeader; @@ -926,6 +1239,137 @@ void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_ break; } } + + +int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf) +{ + if(1) + { + int socket_connected = 1; + + // 1. Peek the message header + // 2. If the message is larger than the stack buffer then create a dynamic buffer + // 3. Read the buffer + // 4. Handle the p5 message + + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + + uint32_t stack_buffer_size = 32; //should it be the size of then sctp_notificatoin structure + uint8_t stack_buffer[stack_buffer_size]; + + uint8_t* dynamic_buffer = 0; + + uint8_t* read_buffer = &stack_buffer[0]; + uint32_t message_size = 0; + + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + + struct sctp_sndrcvinfo sndrcvinfo; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + { + int flags = MSG_PEEK; + message_size = sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + + if(message_size == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno); + return 0; + } + + nfapi_p4_p5_message_header_t header; + int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if(unpack_result < 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header %d\n", unpack_result); + return 0; + } + message_size = header.message_length; + + // now have the size of the mesage + } + + if(message_size > stack_buffer_size) + { + dynamic_buffer = (uint8_t*)malloc(message_size); + + if(dynamic_buffer == NULL) + { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } + + read_buffer = dynamic_buffer; + } + + { + int flags = 0; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + int recvmsg_result = sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + if(recvmsg_result == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); + } + else + { + if (flags & MSG_NOTIFICATION) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + // todo - handle the events + } + else + { + /* + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n", + pnf->p5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + */ + + // handle now if complete message in one or more segments + if ((flags & 0x80) == 0x80) + { + // printf("\nVNF RECEIVES:\n"); + // for(int i=0; ip5_idx, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); + + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } + + + } + } + } + + if(dynamic_buffer) + { + free(dynamic_buffer); + } + + return socket_connected; + } +} + int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf) { if(1) @@ -1024,6 +1468,12 @@ int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* // handle now if complete message in one or more segments if ((flags & 0x80) == 0x80) { + // printf("\nVNF RECEIVES:\n"); + // for(int i=0; ip5_idx, config); } else @@ -1051,6 +1501,12 @@ int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, uint8_t stream) { + // printf("\n MESSAGE SENT: \n"); + // for(int i=0; ip5_sock, msg, len, (struct sockaddr*)&pnf->p5_pnf_sockaddr, sizeof(pnf->p5_pnf_sockaddr),1, 0, stream, 0, 4); @@ -1071,6 +1527,29 @@ static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, return 0; } +int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len) +{ + nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); + + if(pnf) + { + // pack the message for transmission + int packedMessageLength = nfapi_nr_p5_message_pack(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config); + + if (packedMessageLength < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed with return %d\n", packedMessageLength); + return -1; + } + return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); + return -1; + } +} + int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len) { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 59d7f3eb4f..084c4fa485 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -63,6 +63,418 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config) free(config); } +int nfapi_nr_vnf_start(nfapi_vnf_config_t* config) +{ + // Verify that config is not null + if(config == 0) + return -1; + + // Make sure to set the defined trace function before using NFAPI_TRACE + if(config->trace) + nfapi_trace_g = (nfapi_trace_fn_t)config->trace; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + + int p5ListenSock, p5Sock; + + struct sockaddr_in addr; + socklen_t addrSize; + + struct sockaddr_in6 addr6; + + struct sctp_event_subscribe events; + struct sctp_initmsg initMsg; + int noDelay; + + (void)memset(&addr, 0, sizeof(struct sockaddr_in)); + (void)memset(&addr6, 0, sizeof(struct sockaddr_in6)); + (void)memset(&events, 0, sizeof(struct sctp_event_subscribe)); + (void)memset(&initMsg, 0, sizeof(struct sctp_initmsg)); + + vnf_t* vnf = (vnf_t*)(config); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); + + /* + char * host = 0; + char * port = "4242"; + struct addrinfo hints; + bzero(&hints, sizeof(struct addrinfo)); + //hints.ai_flags=AI_PASSIVE; + //hints.ai_flags=AI_DEFAULT; + hints.ai_family=AF_UNSPEC; + //hints.ai_family=AF_INET6; + hints.ai_socktype=SOCK_STREAM; + //hints.ai_protocol=IPPROTO_SCTP + + struct addrinfo *aiHead = 0; + + + + int result = getaddrinfo(host, port, &hints, &aiHead); + NFAPI_TRACE(NFAPI_TRACE_INFO, "getaddrinfo return %d %d\n", result, errno); + + while(aiHead->ai_next != NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "addr info %d (IP %d UDP %d SCTP %d)\n %d (%d)\n", + aiHead->ai_protocol, IPPROTO_IP, IPPROTO_UDP, IPPROTO_SCTP, + aiHead->ai_flags, AI_PASSIVE); + + char hostBfr[ NI_MAXHOST ]; + char servBfr[ NI_MAXSERV ]; + + getnameinfo(aiHead->ai_addr, + aiHead->ai_addrlen, + hostBfr, + sizeof( hostBfr ), + servBfr, + sizeof( servBfr ), + NI_NUMERICHOST | NI_NUMERICSERV ); + + switch(aiHead->ai_family) + { + case PF_INET: + { + struct sockaddr_in *pSadrIn = (struct sockaddr_in*) aiHead->ai_addr; + printf( + " ai_addr = sin_family: %d (AF_INET = %d, " + "AF_INET6 = %d)\n" + " sin_addr: %s\n" + " sin_port: %s\n", + pSadrIn->sin_family, + AF_INET, + AF_INET6, + hostBfr, + servBfr ); + } + break; + case PF_INET6: + { + struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6*) aiHead->ai_addr; + fprintf( stderr, + " ai_addr = sin6_family: %d (AF_INET = %d, " + "AF_INET6 = %d) \n" + " sin6_addr: %s\n" + " sin6_port: %s\n" + " sin6_flowinfo: %d\n" + " sin6_scope_id: %d\n", + pSadrIn6->sin6_family, + AF_INET, + AF_INET6, + hostBfr, + servBfr, + pSadrIn6->sin6_flowinfo, + pSadrIn6->sin6_scope_id); + } + break; + default: + NFAPI_TRACE(NFAPI_TRACE_INFO, "Not ment to be here\n"); + break; + } + + aiHead = aiHead->ai_next; + } + */ + + { + int protocol; + int domain; + + if (vnf->sctp) + protocol = IPPROTO_SCTP; + else + protocol = IPPROTO_IP; + + if(config->vnf_ipv6) + { + domain = PF_INET6; + } + else + { + domain = AF_INET; + } + + // open the SCTP socket + if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock); + } + + if (vnf->sctp) + { + // configure for MSG_NOTIFICATION + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n"); + // configure the SCTP socket options + initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater + initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno) + close(p5ListenSock); + return 0; + } + noDelay = 1; + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + struct sctp_event_subscribe events; + memset( (void *)&events, 0, sizeof(events) ); + events.sctp_data_io_event = 1; + + if(setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + close(p5ListenSock); + return -1; + } + + } + + + if(config->vnf_ipv6) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(config->vnf_p5_port); + addr6.sin6_addr = in6addr_any; + + // bind to the configured address and port + if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + } + else if(config->vnf_ipv4) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port); + addr.sin_family = AF_INET; + addr.sin_port = htons(config->vnf_p5_port); + addr.sin_addr.s_addr = INADDR_ANY; + + // bind to the configured address and port + if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) + //if (sctp_bindx(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), SCTP_BINDX_ADD_ADDR) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock); + + // put the socket into listen mode + if (listen(p5ListenSock, 2) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n"); + + struct timeval tv; + fd_set read_fd_set; + + + int p5_idx = 0; + while(vnf->terminate == 0) + { + FD_ZERO(&read_fd_set); + + FD_SET(p5ListenSock, &read_fd_set); + int max_fd = p5ListenSock; + + tv.tv_sec = 5; + tv.tv_usec = 0; + + nfapi_vnf_pnf_info_t* pnf = config->pnf_list; + while(pnf != 0) + { + if(pnf->connected) + { + FD_SET(pnf->p5_sock, &read_fd_set); + if (pnf->p5_sock > max_fd) + { + max_fd = pnf->p5_sock; + } + } + + pnf = pnf->next; + } + + int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv); + + if(select_result == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno); + close(p5ListenSock); + return 0; + } + else if(select_result) + { + if(FD_ISSET(p5ListenSock, &read_fd_set)) + { + addrSize = sizeof(struct sockaddr_in); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n"); + + p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize); + + if (p5Sock < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF connection (fd:%d) accepted from %s:%d \n", p5Sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + nfapi_vnf_pnf_info_t* pnf = (nfapi_vnf_pnf_info_t*)malloc(sizeof(nfapi_vnf_pnf_info_t)); + NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); + memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); + pnf->p5_sock = p5Sock; + pnf->p5_idx = p5_idx++; + pnf->p5_pnf_sockaddr = addr; + pnf->connected = 1; + + nfapi_vnf_pnf_list_add(config, pnf); + + // Inform mac that a pnf connection has been established + // todo : allow mac to 'accept' the connection. i.e. to + // reject it. + if(config->pnf_nr_connection_indication != 0) + { + (config->pnf_nr_connection_indication)(config, pnf->p5_idx); + } + + + // check the connection status + { + struct sctp_status status; + (void)memset(&status, 0, sizeof(struct sctp_status)); + socklen_t optLen = (socklen_t) sizeof(struct sctp_status); + if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms); + + } + } + } + } + else + { + uint8_t delete_pnfs = 0; + + nfapi_vnf_pnf_info_t* pnf = config->pnf_list; + while(pnf != 0) + { + if(FD_ISSET(pnf->p5_sock, &read_fd_set)) + { + if(vnf_nr_read_dispatch_message(config, pnf) == 0) + { + if(config->pnf_disconnect_indication != 0) + { + (config->pnf_disconnect_indication)(config, pnf->p5_idx); + } + + close(pnf->p5_sock); + + pnf->to_delete = 1; + delete_pnfs = 1; + } + } + + pnf = pnf->next; + } + + if(delete_pnfs) + { + nfapi_vnf_pnf_info_t* pnf = config->pnf_list; + nfapi_vnf_pnf_info_t* prev = 0; + while(pnf != 0) + { + nfapi_vnf_pnf_info_t* curr = pnf; + + if(pnf->to_delete == 1) + { + if(prev == 0) + { + config->pnf_list = pnf->next; + } + else + { + prev->next = pnf->next; + } + + pnf = pnf->next; + + free(curr); + } + else + { + prev = pnf; + pnf = pnf->next; + } + + } + + } + } + + continue; + } + else + { + // timeout + + // Should we test for socket closure here every second? + + continue; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n"); + { + nfapi_vnf_pnf_info_t* curr = config->pnf_list; + while(curr != NULL) + { + if(config->pnf_disconnect_indication) + { + (config->pnf_disconnect_indication)(config, curr->p5_idx); + } + + close(curr->p5_sock); + curr = curr->next; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n"); + close(p5ListenSock); + + return 0; + +} + int nfapi_vnf_start(nfapi_vnf_config_t* config) { // Verify that config is not null @@ -486,6 +898,16 @@ int nfapi_vnf_stop(nfapi_vnf_config_t* config) return 0; } +int nfapi_nr_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_param_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_param_request_t)); +} + int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req) { if(config == 0 || req == 0) @@ -496,6 +918,17 @@ int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_pa return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_param_request_t)); } +int nfapi_nr_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_config_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_config_request_t)); +} + + int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_request_t* req) { if(config == 0 || req == 0) @@ -516,6 +949,16 @@ int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_st return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_start_request_t)); } +int nfapi_nr_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_start_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_start_request_t)); +} + int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_request_t* req) { if(config == 0 || req == 0) @@ -526,6 +969,16 @@ int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_sto return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_stop_request_t)); } +int nfapi_nr_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_param_request_scf_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_param_request_scf_t)); +} + int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req) { if(config == 0 || req == 0) @@ -535,6 +988,38 @@ int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_requ return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_param_request_t)); } + +int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_config_request_scf_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); + + if(phy == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s failed to find phy information phy_id:%d\n", __FUNCTION__, req->header.phy_id); + return -1; + } + + // set the timing parameters + req->nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG; + req->nfapi_config.timing_window.value = phy->timing_window; + req->num_tlv++; + + req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG; + req->nfapi_config.timing_info_mode.value = phy->timing_info_mode; + req->num_tlv++; + + req->nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; + req->nfapi_config.timing_info_period.value = phy->timing_info_period; + req->num_tlv++; + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_config_request_scf_t)); +} + int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req) { if(config == 0 || req == 0) @@ -565,7 +1050,8 @@ int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_re return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_config_request_t)); } -int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req) + +int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t * req) { if(config == 0 || req == 0) return -1; @@ -574,6 +1060,18 @@ int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_requ return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_start_request_t)); } + +int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_request_scf_t * req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_start_request_scf_t)); +} + + int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req) { if(config == 0 || req == 0) @@ -664,7 +1162,7 @@ int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy info->p5_idx = p5_idx; info->phy_id = vnf->next_phy_id++; - info->timing_window = 30; // This seems to override what gets set by the user - why??? + info->timing_window = 30; // This seems to override what gets set by the user - why??? //TODO: Change in NR in terms of microsecends,what should be the value? info->timing_info_mode = 0x03; info->timing_info_period = 128; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 394bfc58ff..e390031554 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -22,7 +22,7 @@ #include #include #include - +#include #include "vnf_p7.h" #define SYNC_CYCLE_COUNT 2 @@ -303,7 +303,7 @@ static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr) { if(now_hr < sf_start_hr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier that start of subframe\n"); + NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe\n"); return 0; } else @@ -321,6 +321,28 @@ static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr) } } +static uint32_t get_slot_time(uint32_t now_hr, uint32_t slot_start_hr) +{ + if(now_hr < slot_start_hr) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of slot\n"); + return 0; + } + else + { + uint32_t now_us = TIMEHR_USEC(now_hr); + uint32_t slot_start_us = TIMEHR_USEC(slot_start_hr); + + // if the us have wrapped adjust for it + if(now_hr < slot_start_us) + { + now_us += 1000000; + } + + return now_us - slot_start_us; + } +} + uint32_t calculate_t1(uint16_t sfn_sf, uint32_t sf_start_time_hr) { uint32_t now_time_hr = vnf_get_current_time_hr(); @@ -332,6 +354,17 @@ uint32_t calculate_t1(uint16_t sfn_sf, uint32_t sf_start_time_hr) return t1; } +uint32_t calculate_nr_t1(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr) +{ + uint32_t now_time_hr = vnf_get_current_time_hr(); + + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); + + uint32_t t1 = (NFAPI_SFNSLOT2DEC(sfn,slot) * 500) + slot_time_us; + + return t1; +} + uint32_t calculate_t4(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_time_hr) { @@ -343,15 +376,25 @@ uint32_t calculate_t4(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_t } +uint32_t calculate_nr_t4(uint32_t now_time_hr, uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr) +{ + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); -uint32_t calculate_transmit_timestamp(uint16_t sfn_sf, uint32_t sf_start_time_hr) + uint32_t t4 = (NFAPI_SFNSLOT2DEC(sfn,slot) * 500) + slot_time_us; + + return t4; + +} + + +uint32_t calculate_transmit_timestamp(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr) { uint32_t now_time_hr = vnf_get_current_time_hr(); - uint32_t sf_time_us = get_sf_time(now_time_hr, sf_start_time_hr); - - uint32_t tt = (NFAPI_SFNSF2DEC(sfn_sf) * 1000) + sf_time_us; + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); + uint32_t tt = (NFAPI_SFNSLOT2DEC(sfn, slot) * 500) + slot_time_us; + return tt; } @@ -367,6 +410,27 @@ uint16_t increment_sfn_sf_by(uint16_t sfn_sf, uint8_t increment) return sfn_sf; } +int send_mac_slot_indications(vnf_p7_t* vnf_p7) +{ + nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; + while(curr != 0) + { + if(curr->in_sync == 1) + { + // ask for subframes in the future + //uint16_t sfn_sf_adv = increment_sfn_sf_by(curr->sfn_sf, 2); + + //vnf_p7->_public.subframe_indication(&(vnf_p7->_public), curr->phy_id, sfn_sf_adv); + // suggestion fix by Haruki NAOI + //printf("\nsfn:%d, slot:%d\n",curr->sfn,curr->slot); + vnf_p7->_public.slot_indication(&(vnf_p7->_public), curr->phy_id, curr->sfn,curr->slot); + } + + curr = curr->next; + } + + return 0; +} int send_mac_subframe_indications(vnf_p7_t* vnf_p7) { @@ -392,7 +456,7 @@ int send_mac_subframe_indications(vnf_p7_t* vnf_p7) int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, uint8_t* msg, const uint32_t len) { int sendto_result = sendto(vnf_p7->socket, msg, len, 0, (struct sockaddr*)&(p7_info->remote_addr), sizeof(p7_info->remote_addr)); - + //printf("P7 msg sent \n"); if(sendto_result != len) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno); @@ -401,6 +465,100 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u return 0; } +int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header) +{ + + nfapi_vnf_p7_connection_info_t* p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id); + if(p7_connection) + { + int send_result = 0; + uint8_t buffer[1024 * 32]; + + header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, p7_connection->sequence_number); + + int len = nfapi_nr_p7_message_pack(header, buffer, sizeof(buffer), &vnf_p7->_public.codec_config); + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); + + if(len < 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id); + return -1; + } + + if(len > vnf_p7->_public.segment_size) + { + // todo : consider replacing with the sendmmsg call + // todo : worry about blocking writes? + + // segmenting the transmit + int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ; + int seg_body_len = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + + int segment = 0; + int offset = NFAPI_P7_HEADER_LENGTH; + uint8_t tx_buffer[vnf_p7->_public.segment_size]; + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); + for(segment = 0; segment < segment_count; ++segment) + { + uint8_t last = 0; + uint16_t size = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH; + if(segment + 1 == segment_count) + { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } + + uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH; + + // Update the header with the m and segement + memcpy(&tx_buffer[0], buffer, NFAPI_P7_HEADER_LENGTH); + + // set the segment length + tx_buffer[4] = (segment_size & 0xFF00) >> 8; + tx_buffer[5] = (segment_size & 0xFF); + + // set the m & segment number + tx_buffer[6] = ((!last) << 7) + segment; + + memcpy(&tx_buffer[NFAPI_P7_HEADER_LENGTH], &buffer[0] + offset, size); + offset += size; + + if(vnf_p7->_public.checksum_enabled) + { + nfapi_p7_update_checksum(tx_buffer, segment_size); + } + + nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); + + send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); + + } + } + else + { + if(vnf_p7->_public.checksum_enabled) + { + nfapi_p7_update_checksum(buffer, len); + } + + nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); + + // simple case that the message fits in a single segement + send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len); + } + + p7_connection->sequence_number++; + return send_result; + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id); + return -1; + } +} + int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header) { @@ -466,7 +624,7 @@ int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* hea nfapi_p7_update_checksum(tx_buffer, segment_size); } - nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn_sf, vnf_p7->sf_start_time_hr)); + nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); } @@ -478,7 +636,7 @@ int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* hea nfapi_p7_update_checksum(buffer, len); } - nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn_sf, vnf_p7->sf_start_time_hr)); + nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); // simple case that the message fits in a single segement send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len); @@ -494,7 +652,6 @@ int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* hea return -1; } } - int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) { nfapi_dl_node_sync_t dl_node_sync; @@ -508,6 +665,51 @@ int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t return vnf_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header); } +int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) +{ + nfapi_nr_dl_node_sync_t dl_node_sync; + memset(&dl_node_sync, 0, sizeof(dl_node_sync)); + + dl_node_sync.header.phy_id = p7_info->phy_id; + dl_node_sync.header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC; + //dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr); + dl_node_sync.t1 = calculate_nr_t1(p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr); + dl_node_sync.delta_sfn_slot = 0; + + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header); +} + +int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) +{ + + if(p7_info->in_sync == 1) + { + uint16_t dl_sync_period_mask = p7_info->dl_in_sync_period-1; + // uint16_t sfn_sf_dec = NFAPI_SFNSF2DEC(p7_info->sfn_sf); + uint16_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(p7_info->sfn,p7_info->slot); + + //if ((((sfn_sf_dec + p7_info->dl_in_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0) + if ((((sfn_slot_dec + p7_info->dl_in_sync_offset) % NFAPI_MAX_SFNSLOTDEC) & dl_sync_period_mask) == 0) + { + vnf_nr_build_send_dl_node_sync(vnf_p7, p7_info); + } + } + else + { + uint16_t dl_sync_period_mask = p7_info->dl_out_sync_period-1; + //uint16_t sfn_sf_dec = NFAPI_SFNSF2DEC(p7_info->sfn_sf); + uint16_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(p7_info->sfn, p7_info->slot); + + //if ((((sfn_sf_dec + p7_info->dl_out_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0) + if ((((sfn_slot_dec + p7_info->dl_out_sync_offset) % NFAPI_MAX_SFNSLOTDEC) & dl_sync_period_mask) == 0) + { + vnf_nr_build_send_dl_node_sync(vnf_p7, p7_info); + } + } + return 0; +} + + int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) { @@ -955,7 +1157,7 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + NFAPI_TRACE(NFAPI_TRACE_INFO, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", NFAPI_SFNSF2SFN(phy->sfn_sf), NFAPI_SFNSF2SF(phy->sfn_sf), ts.tv_sec, ts.tv_nsec, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->sf_offset, phy->sf_offset_filtered, @@ -1016,7 +1218,7 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { phy->adjustment = NFAPI_SFNSF2DEC(new_sfn_sf) - NFAPI_SFNSF2DEC(curr_sfn_sf); - NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_sf_offset_filtered:%d phy->previous_sf_offset_filtered:%d phy->sf_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_sf_offset_filtered, phy->previous_sf_offset_filtered, phy->sf_offset_trend); + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF to VNF phy_id:%d adjustment%d phy->previous_sf_offset_filtered:%d phy->previous_sf_offset_filtered:%d phy->sf_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_sf_offset_filtered, phy->previous_sf_offset_filtered, phy->sf_offset_trend); phy->previous_t1 = 0; phy->previous_t2 = 0; @@ -1087,7 +1289,7 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { if(phy->in_sync == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); if(vnf_p7->_public.sync_indication) (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); @@ -1251,6 +1453,553 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } +//NR HANDLES FOR UPLINK MESSAGES +void vnf_handle_nr_slot_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_slot_indication_scf_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + if(vnf_p7->_public.nr_slot_indication) + { + (vnf_p7->_public.nr_slot_indication)(&ind); + } + } + + } +} +void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_rx_data_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + if(vnf_p7->_public.nr_rx_data_indication) + { + (vnf_p7->_public.nr_rx_data_indication)(&ind); + } + } + + } +} + +void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_crc_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + if(vnf_p7->_public.nr_crc_indication) + { + (vnf_p7->_public.nr_crc_indication)(&ind); + } + } + + } +} + +void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_srs_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + if(vnf_p7->_public.nr_srs_indication) + { + (vnf_p7->_public.nr_srs_indication)(&ind); + } + } + } +} + +void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_uci_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + if(vnf_p7->_public.nr_uci_indication) + { + (vnf_p7->_public.nr_uci_indication)(&ind); + } + } + + } +} + +void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_rach_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + if(vnf_p7->_public.nr_rach_indication) + { + (vnf_p7->_public.nr_rach_indication)(&ind); + } + } + + } +} + +void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + //printf("received UL Node sync"); + + uint32_t now_time_hr = vnf_get_current_time_hr(); + + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_ul_node_sync: NULL parameters\n"); + return; + } + + nfapi_nr_ul_node_sync_t ind; + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_nr_ul_node_sync_t), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_node_sync\n"); + return; + } + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Received UL_NODE_SYNC phy_id:%d t1:%d t2:%d t3:%d\n", ind.header.phy_id, ind.t1, ind.t2, ind.t3); + + nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, ind.header.phy_id); + uint32_t t4 = calculate_nr_t4(now_time_hr, phy->sfn, phy->slot, vnf_p7->slot_start_time_hr); + + uint32_t tx_2_rx = t4>ind.t1 ? t4 - ind.t1 : t4 + NFAPI_MAX_SFNSLOTDEC - ind.t1 ; //time taken to receive ul node sync - time taken to send dl node sync + uint32_t pnf_proc_time = ind.t3 - ind.t2; + + // divide by 2 using shift operator + uint32_t latency = (tx_2_rx - pnf_proc_time) >> 1; + + //phy->in_sync = 1; + + if(!(phy->filtered_adjust)) + { + phy->latency[phy->min_sync_cycle_count] = latency; + + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", + // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency); + } + else + { + phy->latency[phy->min_sync_cycle_count] = latency; + + //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) + { + if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) + { + // Only t2 wrap has occurred!!! + phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; + } + else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) + { + // Only t1 wrap has occurred + phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; + } + else + { + // Either no wrap or both have wrapped + phy->slot_offset = ind.t2 - ind.t1 - latency; + } + + if (phy->slot_offset_filtered == 0) + { + phy->slot_offset_filtered = phy->slot_offset; + } + else + { + int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; + int32_t newOffsetShifted = phy->slot_offset << 5; + + // 1/8 of new and 7/8 of old + phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; + } + } + + if(1) + { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + // ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + // (ind.t1previous_t1), (ind.t2previous_t2)); + } + + } + + if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) + { struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + ind.t1, ind.t2, ind.t3, t4, + tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + (ind.t1previous_t1), (ind.t2previous_t2)); + + phy->filtered_adjust = 0; + phy->zero_count=0; + phy->min_sync_cycle_count = 2; + phy->in_sync = 0; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); + } + + if(phy->min_sync_cycle_count) + phy->min_sync_cycle_count--; + + if(phy->min_sync_cycle_count == 0) + { + uint32_t curr_sfn = phy->sfn; + uint32_t curr_slot = phy->slot; + int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + + if(!phy->filtered_adjust) + { + int i = 0; + //phy->average_latency = 0; + for(i = 0; i < SYNC_CYCLE_COUNT; ++i) + { + phy->average_latency += phy->latency[i]; + + } + phy->average_latency /= SYNC_CYCLE_COUNT; + + phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); + + sfn_slot_dec += (phy->slot_offset / 500); + + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); + + + } + else + { + sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot + + } + + if(sfn_slot_dec < 0) + { + sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; + } + else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) + { + sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; + } + + + uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); + uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); + + { + phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); + + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); + + phy->previous_t1 = 0; + phy->previous_t2 = 0; + + if(phy->previous_slot_offset_filtered > 0) + { + if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) + { + // pnf is getting futher ahead of vnf + //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; + phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; + } + else + { + // pnf is getting back in sync + } + } + else if(phy->previous_slot_offset_filtered < 0) + { + if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) + { + // vnf is getting future ahead of pnf + //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); + phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; + } + else + { + // vnf is getting back in sync + } + } + + + int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; + int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; + + + if(insync_minor_adjustment_1 == 0) + insync_minor_adjustment_1 = 2; + + if(insync_minor_adjustment_2 == 0) + insync_minor_adjustment_2 = 10; + + if(!phy->filtered_adjust) + { + if(phy->adjustment < 10) + { + phy->zero_count++; + + if(phy->zero_count >= 10) + { + phy->filtered_adjust = 1; + phy->zero_count = 0; + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); + } + } + else + { + phy->zero_count = 0; + } + } + else + { + // Fine level of adjustment + if (phy->adjustment == 0) + { + if (phy->zero_count >= 10) + { + if(phy->in_sync == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + + if(vnf_p7->_public.sync_indication) + (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); + } + + phy->in_sync = 1; + } + else + { + phy->zero_count++; + } + + if(phy->in_sync) + { + // in sync + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; + phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; + phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); + } + else + { + phy->insync_minor_adjustment = 0; + } + + if(phy->insync_minor_adjustment != 0) + { + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, + // phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, + // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), + // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), + // phy->adjustment); + } + } + } + else + { + if (phy->in_sync) + { + if(phy->adjustment == 0) + { + } + else if(phy->adjustment > 0) + { + // VNF is slow + //if(phy->adjustment == 1) + { + // + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_2; + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_2); + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); + } + + } + //else + { + // out of sync? + } + + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, + // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), + // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), + // phy->adjustment); + + } + else if(phy->adjustment < 0) + { + // VNF is fast + //if(phy->adjustment == -1) + { + // + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_2; + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_2); + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); + } + } + //else + { + // out of sync? + } + + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); + } + + /* + if (phy->adjustment > 10 || phy->adjustment < -10) + { + phy->zero_count++; // Add one to the getting out of sync counter + } + else + { + phy->zero_count = 0; // Small error - zero the out of sync counter + } + + if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); + //pP7SockInfo->syncAchieved = 0; + } + */ + } + } + } + + + if(phy->in_sync == 0) + { + /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", + ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), + NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, + phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", + phy->zero_count, + phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ + + phy->sfn = new_sfn; + phy->slot = new_slot; + } + } + + // reset for next cycle + phy->previous_slot_offset_filtered = phy->slot_offset_filtered; + phy->min_sync_cycle_count = 2; + phy->slot_offset_filtered = 0; + phy->slot_offset = 0; + } + else + { + phy->previous_t1 = ind.t1; + phy->previous_t2 = ind.t2; + } +} + void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { if (pRecvMsg == NULL || vnf_p7 == NULL) @@ -1283,6 +2032,41 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } + +void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_timing_info: NULL parameters\n"); + return; + } + + nfapi_nr_timing_info_t ind; + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_timing_info_t), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack timing_info\n"); + return; + } + + if (vnf_p7 && vnf_p7->p7_connections) + { + //int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf); + int16_t vnf_pnf_sfnslot_delta = NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot) - NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta); + + // Panos: Careful here!!! Modification of the original nfapi-code + //if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1) + //printf("VNF-PNF delta - %d", vnf_pnf_sfnslot_delta); + if (vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnslot_delta,NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot),NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot)) ; + // Panos: Careful here!!! Modification of the original nfapi-code + // vnf_p7->p7_connections[0].sfn = ind.last_sfn; + // vnf_p7->p7_connections[0].slot = ind.last_slot; + } + } +} + void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { nfapi_p7_message_header_t header; @@ -1378,6 +2162,85 @@ void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } +void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + nfapi_p7_message_header_t header; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return; + } + + // unpack the message header + if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + switch (header.message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + vnf_nr_handle_ul_node_sync(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_TIMING_INFO: + vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + vnf_handle_nr_slot_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + vnf_handle_nr_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + vnf_handle_nr_uci_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7); + break; + + default: + { + if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + vnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, vnf_p7, header.message_id); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Unknown message ID %d\n", header.message_id); + } + } + break; + } +} + void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { nfapi_p7_message_header_t messageHeader; @@ -1496,6 +2359,200 @@ void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } +void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + nfapi_p7_message_header_t messageHeader; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p7_message: invalid input params (%d %d %d)\n", pRecvMsg, recvMsgLen, vnf_p7); + return; + } + + // unpack the message header + if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + if(vnf_p7->_public.checksum_enabled) + { + uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if(checksum != messageHeader.checksum) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d msg:%d len:%d\n", checksum, messageHeader.checksum, messageHeader.message_id, recvMsgLen); + return; + } + } + + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + + + if(m == 0 && segment_num == 0) + { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + //vnf_dispatch_p7_message(&messageHeader, pRecvMsg, recvMsgLen, vnf_p7); + vnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, vnf_p7); + } + else + { + nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, messageHeader.phy_id); + + if(phy) + { + vnf_p7_rx_message_t* rx_msg = vnf_p7_rx_reassembly_queue_add_segment(vnf_p7, &(phy->reassembly_queue), sequence_num, segment_num, m, pRecvMsg, recvMsgLen); + + if(rx_msg->num_segments_received == rx_msg->num_segments_expected) + { + // send the buffer on + uint16_t i = 0; + uint16_t length = 0; + for(i = 0; i < rx_msg->num_segments_expected; ++i) + { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0); + } + + if(phy->reassembly_buffer_size < length) + { + vnf_p7_free(vnf_p7, phy->reassembly_buffer); + phy->reassembly_buffer = 0; + } + + if(phy->reassembly_buffer == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing VNF_P7 Reassembly buffer %d->%d\n", phy->reassembly_buffer_size, length); + phy->reassembly_buffer = (uint8_t*)vnf_p7_malloc(vnf_p7, length); + + if(phy->reassembly_buffer == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(phy->reassembly_buffer, 0, length); + phy->reassembly_buffer_size = length; + } + + uint16_t offset = 0; + for(i = 0; i < rx_msg->num_segments_expected; ++i) + { + if(i == 0) + { + memcpy(phy->reassembly_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } + else + { + memcpy(phy->reassembly_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH; + } + } + + + //pnf_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); + vnf_nr_dispatch_p7_message(phy->reassembly_buffer, length , vnf_p7); + + + // delete the structure + vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7, &(phy->reassembly_queue), rx_msg); + } + + vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7, &(phy->reassembly_queue), 1000); + } + else + { + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Unknown phy id %d\n", messageHeader.phy_id); + } + } +} + +int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7) +{ + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + + do + { + // peek the header + uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(vnf_p7->socket, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); + + if(recvfrom_result > 0) + { + // get the segment size + nfapi_p7_message_header_t header; + if(nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, sizeof(header), 0) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return -1; + } + + // resize the buffer if we have a large segment + if(header.message_length > vnf_p7->rx_message_buffer_size) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + vnf_p7->rx_message_buffer = realloc(vnf_p7->rx_message_buffer, header.message_length); + vnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(vnf_p7->socket, vnf_p7->rx_message_buffer, header.message_length, MSG_WAITALL, (struct sockaddr*)&remote_addr, &remote_addr_size); + + // todo : how to handle incomplete readfroms, need some sort of buffer/select + + if(recvfrom_result == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom returned 0\n"); + } + else if(recvfrom_result != header.message_length) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "did not receive the entire message %d %d\n", recvfrom_result, header.message_length); + + recvfrom_result += recvfrom(vnf_p7->socket, &vnf_p7->rx_message_buffer[recvfrom_result], header.message_length - recvfrom_result, MSG_WAITALL, (struct sockaddr*)&remote_addr, &remote_addr_size); + + } + + + if(recvfrom_result > 0) + { + vnf_nr_handle_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom failed %d %d\n", recvfrom_result, errno); + } + } + + if(recvfrom_result == -1) + { + if(errno == EAGAIN || errno == EWOULDBLOCK) + { + // return to the select + //NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } + } + while(recvfrom_result > 0); + + return 0; +} + int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7) { int recvfrom_result = 0; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index a0efeeb5f4..8cebf2b468 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -25,9 +25,15 @@ #include #include "vnf_p7.h" +#include "nfapi_vnf.h" +#include "common/ran_context.h" + +#include "openair1/PHY/defs_gNB.h" #define FAPI2_IP_DSCP 0 +extern RAN_CONTEXT_t RC; + nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create() { vnf_p7_t* _this = (vnf_p7_t*)calloc(1, sizeof(vnf_p7_t)); @@ -90,6 +96,135 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // monitor the p7 endpoints and the timing loop and // send indications to mac +int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) +{ + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + uint8_t prev_slot = 0; + if(config == 0) + return -1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + + // Create p7 receive udp port + // todo : this needs updating for Ipv6 + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port); + + // open the UDP socket + if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n"); + + // configure the UDP socket options + int iptos_value = FAPI2_IP_DSCP << 2; + if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n"); + + // Create the address structure + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(config->port); + addr.sin_addr.s_addr = INADDR_ANY; + + // bind to the configured port + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) + //if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n"); + + + //struct timespec original_pselect_timeout; + struct timespec pselect_timeout; + pselect_timeout.tv_sec = 100; + pselect_timeout.tv_nsec = 0; + + struct timespec ref_time; + clock_gettime(CLOCK_MONOTONIC, &ref_time); + uint8_t setup_time; + while(vnf_p7->terminate == 0) + { + fd_set rfds; + int maxSock = 0; + FD_ZERO(&rfds); + int selectRetval = 0; + + // Add the p7 socket + FD_SET(vnf_p7->socket, &rfds); + maxSock = vnf_p7->socket; + + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + setup_time = curr_time.tv_sec - ref_time.tv_sec; + + if(setup_time > 10 && prev_slot != gNB->UL_INFO.slot){ //Give the VNF sufficient time to setup before starting scheduling + + //Call the scheduler + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + prev_slot = gNB->UL_INFO.slot; + } + + selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); + + if(selectRetval == 0) + { + // pselect timed out, continue + } + else if(selectRetval > 0) + { + // have a p7 message + if(FD_ISSET(vnf_p7->socket, &rfds)) + { + vnf_nr_p7_read_dispatch_message(vnf_p7); + } + } + else + { + // pselect error + if(selectRetval == -1 && errno == EINTR) + { + // a sigal was received. + } + else + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond); + // should we exit now? + if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration + { + usleep(100000); + } + } + } + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n"); + close(vnf_p7->socket); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__); + + return 0; +} + + int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config) { if(config == 0) @@ -408,6 +543,7 @@ if (selectRetval==-1 && errno == 22) return 0; } + int nfapi_vnf_p7_stop(nfapi_vnf_p7_config_t* config) { if(config == 0) @@ -434,17 +570,18 @@ int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, memset(node, 0, sizeof(nfapi_vnf_p7_connection_info_t)); node->phy_id = phy_id; node->in_sync = 0; - node->dl_out_sync_offset = 30; + node->dl_out_sync_offset = 30;//TODO: Values need to be changed for NR,How to set the values node->dl_out_sync_period = 10; node->dl_in_sync_offset = 30; node->dl_in_sync_period = 512; - node->sfn_sf = 0; - + //node->sfn_sf = 0; + node->sfn = 0; + node->slot = 0; node->min_sync_cycle_count = 8; // save the remote endpoint information node->remote_addr.sin_family = AF_INET; - node->remote_addr.sin_port = htons(pnf_p7_port); + node->remote_addr.sin_port = pnf_p7_port;//htons(pnf_p7_port); node->remote_addr.sin_addr.s_addr = inet_addr(pnf_p7_addr); vnf_p7_connection_info_list_add(vnf_p7, node); @@ -490,7 +627,15 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); +} + +int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req) @@ -501,6 +646,14 @@ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_re vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } +int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); +} int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req) { if(config == 0 || req == 0) @@ -509,6 +662,14 @@ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_reques vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } +int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); +} int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req) { if(config == 0 || req == 0) diff --git a/openair1/PHY/CODING/3gpplte_sse.c b/openair1/PHY/CODING/3gpplte_sse.c index 2a7b789650..393b0f4a5d 100644 --- a/openair1/PHY/CODING/3gpplte_sse.c +++ b/openair1/PHY/CODING/3gpplte_sse.c @@ -44,8 +44,6 @@ //#define DEBUG_TURBO_ENCODER 1 //#define CALLGRIND 1 -unsigned short threegpplte_interleaver_output; -unsigned long long threegpplte_interleaver_tmp; #if defined(__x86_64__) || defined(__i386__) struct treillis { @@ -375,10 +373,10 @@ char interleave_compact_byte(short *base_interleaver,unsigned char *input, unsig short *ptr_intl=base_interleaver; #if defined(__x86_64) || defined(__i386__) #ifndef __AVX2__ - __m128i tmp; + __m128i tmp={0}; uint16_t *systematic2_ptr=(uint16_t *) output; #else - __m256i tmp; + __m256i tmp={0}; uint32_t *systematic2_ptr=(uint32_t *) output; #endif #elif defined(__arm__) diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c index 8c2513b702..619a8f07b9 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c @@ -933,7 +933,7 @@ unsigned char phy_threegpplte_turbo_decoder16avx2(int16_t *y, uint32_t db; - __m256i tmp, zeros=_mm256_setzero_si256(); + __m256i tmp={0}, zeros=_mm256_setzero_si256(); int offset8_flag=0; diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c index 50fae438b7..c9d2579314 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c @@ -1105,7 +1105,7 @@ uint8_t phy_threegpplte_turbo_decoder16(int16_t *y, uint8_t temp; #if defined(__x86_64__) || defined(__i386__) __m128i *yp128; - __m128i tmp, zeros=_mm_setzero_si128(); + __m128i tmp={0}, zeros=_mm_setzero_si128(); __m128i tmpe; #elif defined(__arm__) int16x8_t *yp128; diff --git a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c index e1ca906b55..264b25deca 100644 --- a/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c +++ b/openair1/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c @@ -798,11 +798,11 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, n is the size in bits of the coded block, with the tail */ int n2; llr_t y8[3*(n+16)] __attribute__((aligned(16))); - llr_t systematic0[n+16] __attribute__ ((aligned(16))); - llr_t systematic1[n+16] __attribute__ ((aligned(16))); - llr_t systematic2[n+16] __attribute__ ((aligned(16))); - llr_t yparity1[n+16] __attribute__ ((aligned(16))); - llr_t yparity2[n+16] __attribute__ ((aligned(16))); + llr_t systematic0[n+32] __attribute__ ((aligned(16))); + llr_t systematic1[n+32] __attribute__ ((aligned(16))); + llr_t systematic2[n+32] __attribute__ ((aligned(16))); + llr_t yparity1[n+32] __attribute__ ((aligned(16))); + llr_t yparity2[n+32] __attribute__ ((aligned(16))); llr_t ext[n+128] __attribute__((aligned(16))); llr_t ext2[n+128] __attribute__((aligned(16))); llr_t alpha[(n+16)*8] __attribute__ ((aligned(16))); @@ -811,7 +811,7 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, llr_t m10[n+16] __attribute__ ((aligned(16))); // int *pi2_p,*pi4_p,*pi5_p,*pi6_p; int *pi4_p,*pi5_p,*pi6_p; - llr_t *s,*s1,*s2,*yp1,*yp2,*yp; + llr_t *s1,*s2,*yp1,*yp2,*yp; unsigned int i,j,iind;//,pi; unsigned char iteration_cnt=0; unsigned int crc,oldcrc,crc_len; @@ -819,7 +819,7 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, #if defined(__x86_64__) || defined(__i386__) __m128i *yp128; __m128i tmp128[(n+8)>>3]; - __m128i tmp, zeros=_mm_setzero_si128(); + __m128i tmp={0}, zeros=_mm_setzero_si128(); #elif defined(__arm__) int8x16_t *yp128; int8x16_t tmp128[(n+8)>>3]; @@ -927,7 +927,6 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, yp128 = (int8x16_t *)y8; #endif - s = systematic0; s1 = systematic1; s2 = systematic2; yp1 = yparity1; @@ -938,7 +937,7 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, for (i=0; i<16 ; i++ ) for (j=0; jn) { /* - s[n]=0;s[n+1]=0;s[n+2]=0;s[n+3]=0; - s[n+4]=0;s[n+5]=0;s[n+6]=0;s[n+7]=0; + systematic0[n]=0;systematic0[n+1]=0;systematic0[n+2]=0;systematic0[n+3]=0; + systematic0[n+4]=0;s[n+5]=0;s[n+6]=0;s[n+7]=0; s1[n]=0;s1[n+1]=0;s1[n+2]=0;s1[n+3]=0; s1[n+4]=0;s1[n+5]=0;s1[n+6]=0;s1[n+7]=0; s2[n]=0;s2[n+1]=0;s2[n+2]=0;s2[n+3]=0; @@ -961,26 +960,26 @@ uint8_t phy_threegpplte_turbo_decoder8(int16_t *y, // Termination for (i=n2; iloading `libldpc_optim8seg.so` instead of `libldpc.so` +#### Examples of ldpc shared lib selection when running nr softmodem's: + +loading `libldpc_optim8seg.so` instead of `libldpc.so`: ``` ./nr-softmodem -O libconfig:gnb.band78.tm1.106PRB.usrpx300.conf:dbgl5 --loader.ldpc.shlibversion _optim8seg @@ -18,9 +20,160 @@ By default the function `int load_nrLDPClib(void)` looks for `libldpc.so`, this ........................ ``` -Today, this mechanism is not available in the `ldpctest` phy simulator which doesn't initialize the [configuration module](file://../../../../common/config/DOC/config.md). loads `libldpc.so` and `libldpc_orig.so` to compare the performance of the two implementations. +loading `libldpc_cl.so` instead of `libldpc.so`: -###LDPC libraries -Libraries implementing the LDPC algorithms must be named `libldpc<_version>.so`, they must implement two functions: `nrLDPC_decod` and `nrLDPC_encod`. The prototypes for these functions is defined in [nrLDPC_defs.h](file://nrLDPC_defs.h). +`make ldpc_cl` + +`cp ../../../openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.cl` + +`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --sa --log_config.gtpu_log_level info --loader.ldpc.shlibversion _cl` + +``` [LOADER] library libldpc_cl.so successfully loaded +------------------------------------------------ +[HW] Platform 0, OpenCL profile FULL_PROFILE +[HW] Platform 0, OpenCL version OpenCL 2.1 LINUX +[HW] Device 0 is available +[HW] Device 0, type 2 = 0x00000002: cpu +[HW] Device 0, number of Compute Units: 8 +[HW] Device 0, max Work Items dimension: 3 +[HW] Device 0, max Work Items size for dimension: 0 8192 +[HW] Device 0, max Work Items size for dimension: 1 8192 +[HW] Device 0, max Work Items size for dimension: 2 8192 +[New Thread 0x7fffcc258700 (LWP 3945123)] +[New Thread 0x7fffc3e57700 (LWP 3945124)] +[New Thread 0x7fffcbe57700 (LWP 3945125)] +[New Thread 0x7fffcba56700 (LWP 3945126)] +[New Thread 0x7fffcb254700 (LWP 3945128)] +[New Thread 0x7fffcb655700 (LWP 3945127)] +[New Thread 0x7fffcae53700 (LWP 3945129)] +[HW] Platform 1, OpenCL profile FULL_PROFILE +[HW] Platform 1, OpenCL version OpenCL 2.0 beignet 1.3 +[New Thread 0x7fffc965a700 (LWP 3945130)] +[Thread 0x7fffc965a700 (LWP 3945130) exited] +[HW] Device 0 is available +[HW] Device 0, type 4 = 0x00000004: gpu +[HW] Device 0, number of Compute Units: 20 +[HW] Device 0, max Work Items dimension: 3 +[HW] Device 0, max Work Items size for dimension: 0 512 +[HW] Device 0, max Work Items size for dimension: 1 512 +[HW] Device 0, max Work Items size for dimension: 2 512 +----------------------------------------------------------------- +``` + +`./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa -O libconfig:/usr/local/oai/conf/nrue_sim.conf:dbgl5 --nokrnmod --loader.ldpc.shlibversion _cl --log_config.hw_log_level info` + +```[CONFIG] shlibversion set to _cl from command line +............................................................ +[CONFIG] loader.ldpc 1 options set from command line +[LOADER] library libldpc_cl.so successfully loaded +[HW] Platform 0, OpenCL profile FULL_PROFILE +[HW] Platform 0, OpenCL version OpenCL 2.1 LINUX +[HW] Device 0 is available +[HW] Device 0, type 2 = 0x00000002: cpu +[HW] Device 0, number of Compute Units: 8 +[HW] Device 0, max Work Items dimension: 3 +[HW] Device 0, max Work Items size for dimension: 0 8192 +[HW] Device 0, max Work Items size for dimension: 1 8192 +[HW] Device 0, max Work Items size for dimension: 2 8192 +[New Thread 0x7fffecccc700 (LWP 3945413)] +[New Thread 0x7fffec8cb700 (LWP 3945415)] +[New Thread 0x7fffec4ca700 (LWP 3945414)] +[New Thread 0x7fffdf7fd700 (LWP 3945417)] +[New Thread 0x7fffdfbfe700 (LWP 3945418)] +[New Thread 0x7fffdffff700 (LWP 3945416)] +[New Thread 0x7fffd73fc700 (LWP 3945419)] +[HW] Platform 1, OpenCL profile FULL_PROFILE +[HW] Platform 1, OpenCL version OpenCL 2.0 beignet 1.3 +[New Thread 0x7fffde105700 (LWP 3945420)] +[Thread 0x7fffde105700 (LWP 3945420) exited] +[HW] Device 0 is available +[HW] Device 0, type 4 = 0x00000004: gpu +[HW] Device 0, number of Compute Units: 20 +[HW] Device 0, max Work Items dimension: 3 +[HW] Device 0, max Work Items size for dimension: 0 512 +[HW] Device 0, max Work Items size for dimension: 1 512 +[HW] Device 0, max Work Items size for dimension: 2 512 +------------------------------------------------------------ +​``` +``` + +A mechanism to select ldpc implementation is also available in the `ldpctest` phy simulator via the `-v`option, which can be used to specify the version of the ldpc shared library to be used. + +#### Examples of ldpc shared lib selection when running ldpctest: + +Loading libldpc_cuda.so, the cuda implementation of the ldpc decoder: + +```$ ./ldpctest -v _cuda +Initializing random number generator, seed 0 +block length 8448: +n_trials 1: +SNR0 -2.000000: +[CONFIG] get parameters from cmdline , debug flags: 0x00400000 +[CONFIG] log_config: 2/3 parameters successfully set +[CONFIG] log_config: 53/53 parameters successfully set +[CONFIG] log_config: 53/53 parameters successfully set +[CONFIG] log_config: 16/16 parameters successfully set +[CONFIG] log_config: 16/16 parameters successfully set +log init done +[CONFIG] loader: 2/2 parameters successfully set +[CONFIG] loader.ldpc: 1/2 parameters successfully set +[LOADER] library libldpc_cuda.so successfully loaded +................................... +​``` +``` + +Loading libldpc_cl.so, the opencl implementation of the ldpc decoder: + +`make ldpc_cl` + +`cp ../../../openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.cl` + +`./ldpctest -v _cl` + +```$ ./ldpctest -v _cl +Initializing random number generator, seed 0 +block length 8448: +n_trials 1: +SNR0 -2.000000: +[CONFIG] get parameters from cmdline , debug flags: 0x00400000 +[CONFIG] log_config: 2/3 parameters successfully set +[CONFIG] log_config: 53/53 parameters successfully set +[CONFIG] log_config: 53/53 parameters successfully set +[CONFIG] log_config: 16/16 parameters successfully set +[CONFIG] log_config: 16/16 parameters successfully set +log init done +[CONFIG] loader: 2/2 parameters successfully set +[CONFIG] loader.ldpc: 1/2 parameters successfully set +[LOADER] library libldpc_cl.so successfully loaded +[HW] Platform 0, OpenCL profile FULL_PROFILE +[HW] Platform 0, OpenCL version OpenCL 2.1 LINUX +[HW] Device 0 is available +[HW] Device 0, type 2 = 0x00000002: cpu +[HW] Device 0, number of Compute Units: 8 +[HW] Device 0, max Work Items dimension: 3 +[HW] Device 0, max Work Items size for dimension: 0 8192 +[HW] Device 0, max Work Items size for dimension: 1 8192 +[HW] Device 0, max Work Items size for dimension: 2 8192 +[HW] Platform 1, OpenCL profile FULL_PROFILE +[HW] Platform 1, OpenCL version OpenCL 2.0 beignet 1.3 +[HW] Device 0 is available +[HW] Device 0, type 4 = 0x00000004: gpu +[HW] Device 0, number of Compute Units: 20 +[HW] Device 0, max Work Items dimension: 3 +[HW] Device 0, max Work Items size for dimension: 0 512 +[HW] Device 0, max Work Items size for dimension: 1 512 +[HW] Device 0, max Work Items size for dimension: 2 512 +................................ +​``` +``` + + + +### LDPC libraries +Libraries implementing the LDPC algorithms must be named `libldpc<_version>.so`, they must implement three functions: `nrLDPC_initcall` `nrLDPC_decod` and `nrLDPC_encod`. The prototypes for these functions is defined in [nrLDPC_defs.h](file://nrLDPC_defs.h). + +`libldpc_cuda.so`has been tested with the `ldpctest` executable, usage from the softmodem's has to be tested. + +`libldpc_cl`is under development. [oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) diff --git a/openair1/PHY/CODING/TESTBENCH/coding_unitary_defs.h b/openair1/PHY/CODING/TESTBENCH/coding_unitary_defs.h new file mode 100644 index 0000000000..f77ffff2eb --- /dev/null +++ b/openair1/PHY/CODING/TESTBENCH/coding_unitary_defs.h @@ -0,0 +1,53 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + * ------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef __CODING_UNITARY_DEFS__h__ +#define __CODING_UNITARY_DEFS__h__ +int oai_exit=0; +unsigned int NB_UE_INST = 1; +#include "openair1/PHY/defs_UE.h" +PHY_VARS_UE ***PHY_vars_UE_g; +#include "common/ran_context.h" +RAN_CONTEXT_t RC; + +void exit_function(const char* file, const char* function, const int line, const char *s) { + const char * msg= s==NULL ? "no comment": s; + printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg); + exit(-1); +} + +signed char quantize(double D, double x, unsigned char B) { + double qxd; + short maxlev; + qxd = floor(x / D); + maxlev = 1 << (B - 1); //(char)(pow(2,B-1)); + + if (qxd <= -maxlev) + qxd = -maxlev; + else if (qxd >= maxlev) + qxd = maxlev - 1; + + return ((char) qxd); +} + + +#endif + diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index b42ac6e4c8..aff707a1d5 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -26,9 +26,11 @@ #include "assertions.h" #include "SIMULATION/TOOLS/sim.h" #include "PHY/CODING/nrLDPC_extern.h" -#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" +//#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" #include "openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.h" -#define MAX_NUM_DLSCH_SEGMENTS 16 +#include "openair1/PHY/defs_nr_common.h" +#include "coding_unitary_defs.h" + #define MAX_BLOCK_LENGTH 8448 #ifndef malloc16 @@ -81,9 +83,6 @@ typedef struct { int n_iter_max; } n_iter_stats_t; -RAN_CONTEXT_t RC; -PHY_VARS_UE ***PHY_vars_UE_g; -uint16_t NB_UE_INST = 1; nrLDPC_encoderfunc_t encoder_orig; short lift_size[51]= {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384}; @@ -102,8 +101,8 @@ int test_ldpc(short No_iteration, unsigned int *crc_misses, time_stats_t *time_optim, time_stats_t *time_decoder, - n_iter_stats_t *dec_iter, - short run_cuda) + n_iter_stats_t *dec_iter + ) { //clock initiate //time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder; @@ -116,9 +115,8 @@ int test_ldpc(short No_iteration, double sigma; sigma = 1.0/sqrt(2*SNR); opp_enabled=1; - cpu_freq_GHz = get_cpu_freq_GHz(); //short test_input[block_length]; - unsigned char *test_input[MAX_NUM_DLSCH_SEGMENTS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};; + unsigned char *test_input[MAX_NUM_NR_DLSCH_SEGMENTS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};; //short *c; //padded codeword unsigned char *estimated_output[MAX_NUM_DLSCH_SEGMENTS]; unsigned char *estimated_output_bit[MAX_NUM_DLSCH_SEGMENTS]; @@ -144,7 +142,7 @@ int test_ldpc(short No_iteration, t_nrLDPC_procBuf nrLDPC_procBuf; t_nrLDPC_procBuf* p_nrLDPC_procBuf = &nrLDPC_procBuf; - t_nrLDPC_time_stats decoder_profiler; + t_nrLDPC_time_stats decoder_profiler = {0}; t_nrLDPC_time_stats* p_decoder_profiler =&decoder_profiler ; int32_t n_iter = 0; @@ -395,28 +393,13 @@ int test_ldpc(short No_iteration, decParams.R=code_rate_vec[R_ind];//13; decParams.numMaxIter=No_iteration; decParams.outMode = nrLDPC_outMode_BIT; + decParams.block_length=block_length; //decParams.outMode =nrLDPC_outMode_LLRINT8; -#ifdef CUDA_FLAG - set_compact_BG(Zc,BG); - init_LLR_DMA_for_CUDA(&decParams, (int8_t*)channel_output_fixed[j], (int8_t*)estimated_output[j], block_length); -#endif + nrLDPC_initcall(&decParams, (int8_t*)channel_output_fixed[j], (int8_t*)estimated_output[j]); for(j=0;j 1280, 2401 -> 2560 - + char *ldpc_version=NULL; /* version of the ldpc decoder library to use (XXX suffix to use when loading libldpc_XXX.so */ short No_iteration=5; int n_segments=1; //double rate=0.333; - short run_cuda = 0; int nom_rate=1; int denom_rate=3; @@ -546,7 +526,7 @@ int main(int argc, char *argv[]) short BG=0,Zc,Kb=0; - while ((c = getopt (argc, argv, "q:r:s:S:l:G:n:d:i:t:u:h")) != -1) + while ((c = getopt (argc, argv, "q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1) switch (c) { case 'q': @@ -566,7 +546,7 @@ int main(int argc, char *argv[]) break; case 'G': - run_cuda = atoi(optarg); + ldpc_version="_cuda"; break; case 'n': @@ -592,9 +572,11 @@ int main(int argc, char *argv[]) case 'u': test_uncoded = atoi(optarg); break; - + case 'v': + ldpc_version=strdup(optarg); + break; case 'h': - default: + default: printf("CURRENTLY SUPPORTED CODE RATES: \n"); printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \n"); printf("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n"); @@ -611,10 +593,10 @@ int main(int argc, char *argv[]) printf("-t SNR simulation step, Default: 0.1\n"); printf("-i Max decoder iterations, Default: 5\n"); printf("-u Set SNR per coded bit, Default: 0\n"); + printf("-v XXX Set ldpc shared library version. libldpc_XXX.so will be used \n"); exit(1); break; } - cpu_freq_GHz = get_cpu_freq_GHz(); //printf("the decoder supports BG2, Kb=10, Z=128 & 256\n"); //printf(" range of blocklength: 1201 -> 1280, 2401 -> 2560\n"); printf("block length %d: \n", block_length); @@ -622,7 +604,10 @@ int main(int argc, char *argv[]) printf("SNR0 %f: \n", SNR0); - load_nrLDPClib(); + if (ldpc_version != NULL) + load_nrLDPClib(ldpc_version); + else + load_nrLDPClib(NULL); load_nrLDPClib_ref("_orig", &encoder_orig); //for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8) @@ -694,8 +679,7 @@ int main(int argc, char *argv[]) &crc_misses, time_optim, time_decoder, - dec_iter, - run_cuda); + dec_iter); printf("SNR %f, BLER %f (%u/%d)\n", SNR, (float)decoded_errors[i]/(float)n_trials, decoded_errors[i], n_trials); printf("SNR %f, BER %f (%u/%d)\n", SNR, (float)errors_bit/(float)n_trials/(float)block_length/(double)n_segments, decoded_errors[i], n_trials); @@ -704,25 +688,25 @@ int main(int argc, char *argv[]) printf("SNR %f, Std iterations: %f\n",SNR, dec_iter->n_iter_std); printf("SNR %f, Max iterations: %d\n",SNR, dec_iter->n_iter_max); printf("\n"); - printf("Encoding time mean: %15.3f us\n",(double)time_optim->diff/time_optim->trials/1000.0/cpu_freq_GHz); - printf("Encoding time std: %15.3f us\n",sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(cpu_freq_GHz,2)-pow((double)time_optim->diff/time_optim->trials/1000.0/cpu_freq_GHz,2))); - printf("Encoding time max: %15.3f us\n",(double)time_optim->max/1000.0/cpu_freq_GHz); + printf("Encoding time mean: %15.3f us\n",(double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz()); + printf("Encoding time std: %15.3f us\n",sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(),2))); + printf("Encoding time max: %15.3f us\n",(double)time_optim->max/1000.0/get_cpu_freq_GHz()); printf("\n"); - printf("Decoding time mean: %15.3f us\n",(double)time_decoder->diff/time_decoder->trials/1000.0/cpu_freq_GHz); - printf("Decoding time std: %15.3f us\n",sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(cpu_freq_GHz,2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/cpu_freq_GHz,2))); - printf("Decoding time max: %15.3f us\n",(double)time_decoder->max/1000.0/cpu_freq_GHz); + printf("Decoding time mean: %15.3f us\n",(double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz()); + printf("Decoding time std: %15.3f us\n",sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(),2))); + printf("Decoding time max: %15.3f us\n",(double)time_decoder->max/1000.0/get_cpu_freq_GHz()); fprintf(fd,"%f %f %f %f %f %f %f %f %f %f %f %f %d \n", SNR, (double)decoded_errors[i]/(double)n_trials , (double)errors_bit/(double)n_trials/(double)block_length/(double)n_segments , errors_bit_uncoded/(double)n_trials/(double)n_segments , - (double)time_optim->diff/time_optim->trials/1000.0/cpu_freq_GHz, - sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(cpu_freq_GHz,2)-pow((double)time_optim->diff/time_optim->trials/1000.0/cpu_freq_GHz,2)), - (double)time_optim->max/1000.0/cpu_freq_GHz, - (double)time_decoder->diff/time_decoder->trials/1000.0/cpu_freq_GHz, - sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(cpu_freq_GHz,2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/cpu_freq_GHz,2)), - (double)time_decoder->max/1000.0/cpu_freq_GHz, + (double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(), + sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(),2)), + (double)time_optim->max/1000.0/get_cpu_freq_GHz(), + (double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(), + sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(),2)), + (double)time_decoder->max/1000.0/get_cpu_freq_GHz(), dec_iter->n_iter_mean, dec_iter->n_iter_std, dec_iter->n_iter_max diff --git a/openair1/PHY/CODING/TESTBENCH/polartest.c b/openair1/PHY/CODING/TESTBENCH/polartest.c index d9adf3e24f..8e7e377542 100644 --- a/openair1/PHY/CODING/TESTBENCH/polartest.c +++ b/openair1/PHY/CODING/TESTBENCH/polartest.c @@ -11,16 +11,12 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_uci_defs.h" #include "PHY/CODING/coding_defs.h" #include "SIMULATION/TOOLS/sim.h" -#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" //#include "common/utils/LOG/log.h" - +#include "coding_unitary_defs.h" //#define DEBUG_DCI_POLAR_PARAMS //#define DEBUG_POLAR_TIMING //#define DEBUG_POLARTEST -RAN_CONTEXT_t RC; -PHY_VARS_UE ***PHY_vars_UE_g; -uint16_t NB_UE_INST = 1; int main(int argc, char *argv[]) { @@ -113,7 +109,6 @@ int main(int argc, char *argv[]) //Initiate timing. (Results depend on CPU Frequency. Therefore, might change due to performance variances during simulation.) time_stats_t timeEncoder,timeDecoder; opp_enabled=1; - cpu_freq_GHz = get_cpu_freq_GHz(); reset_meas(&timeEncoder); reset_meas(&timeDecoder); randominit(0); @@ -324,9 +319,9 @@ if (logFlag){ #endif //Iteration times are in microseconds. - timeEncoderCumulative+=(timeEncoder.diff/(cpu_freq_GHz*1000.0)); - timeDecoderCumulative+=(timeDecoder.diff/(cpu_freq_GHz*1000.0)); - if (logFlag) fprintf(logFile,",%f,%d,%u,%f,%f\n", SNR, nBitError, blockErrorState, (timeEncoder.diff/(cpu_freq_GHz*1000.0)), (timeDecoder.diff/(cpu_freq_GHz*1000.0))); + timeEncoderCumulative+=(timeEncoder.diff/(get_cpu_freq_GHz()*1000.0)); + timeDecoderCumulative+=(timeDecoder.diff/(get_cpu_freq_GHz()*1000.0)); + if (logFlag) fprintf(logFile,",%f,%d,%u,%f,%f\n", SNR, nBitError, blockErrorState, (timeEncoder.diff/(get_cpu_freq_GHz()*1000.0)), (timeDecoder.diff/(get_cpu_freq_GHz()*1000.0))); if (nBitError<0) { blockErrorCumulative++; @@ -348,7 +343,7 @@ if (logFlag){ printf("[ListSize=%d] SNR=%+8.3f, BLER=%9.6f, BER=%12.9f, t_Encoder=%9.3fus, t_Decoder=%9.3fus\n", decoderListSize, SNR, ((double)blockErrorCumulative/iterations), ((double)bitErrorCumulative / (iterations*testLength)), - (double)timeEncoder.diff/timeEncoder.trials/(cpu_freq_GHz*1000.0),(double)timeDecoder.diff/timeDecoder.trials/(cpu_freq_GHz*1000.0)); + (double)timeEncoder.diff/timeEncoder.trials/(get_cpu_freq_GHz()*1000.0),(double)timeDecoder.diff/timeDecoder.trials/(get_cpu_freq_GHz()*1000.0)); //(timeEncoderCumulative/iterations),timeDecoderCumulative/iterations); if (blockErrorCumulative==0 && bitErrorCumulative==0) break; diff --git a/openair1/PHY/CODING/TESTBENCH/smallblocktest.c b/openair1/PHY/CODING/TESTBENCH/smallblocktest.c index 02d5dc64e0..c9ed678a8f 100644 --- a/openair1/PHY/CODING/TESTBENCH/smallblocktest.c +++ b/openair1/PHY/CODING/TESTBENCH/smallblocktest.c @@ -1,19 +1,15 @@ #include #include "SIMULATION/TOOLS/sim.h" #include "PHY/CODING/nrSmallBlock/nr_small_block_defs.h" -#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" +#include "coding_unitary_defs.h" //#define DEBUG_SMALLBLOCKTEST -RAN_CONTEXT_t RC; -PHY_VARS_UE ***PHY_vars_UE_g; -uint16_t NB_UE_INST = 1; int main(int argc, char *argv[]) { time_stats_t timeEncoder,timeDecoder; opp_enabled=1; - cpu_freq_GHz = get_cpu_freq_GHz(); reset_meas(&timeEncoder); reset_meas(&timeDecoder); randominit(0); @@ -141,8 +137,8 @@ int main(int argc, char *argv[]) SNR, ((double)bitErrorCumulative / (iterations*messageLength)), ((double)blockErrorCumulative/iterations), - ((double)timeEncoder.diff/timeEncoder.trials)/(cpu_freq_GHz), - ((double)timeDecoder.diff/timeDecoder.trials)/(cpu_freq_GHz*1000.0)); + ((double)timeEncoder.diff/timeEncoder.trials)/(get_cpu_freq_GHz()), + ((double)timeDecoder.diff/timeDecoder.trials)/(get_cpu_freq_GHz()*1000.0)); blockErrorCumulative=0; bitErrorCumulative=0; diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 7f466c7097..8fe31f208e 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -469,6 +469,9 @@ int32_t nr_segmentation(unsigned char *input_buffer, unsigned int *F, uint8_t BG); +/*!\fn uint32_t nr_compute_tbs +\brief This function returns the TBS in bits as per 6.1.4.2 of TS 38.214 +*/ uint32_t nr_compute_tbs(uint16_t Qm, uint16_t R, uint16_t nb_rb, @@ -480,8 +483,7 @@ uint32_t nr_compute_tbs(uint16_t Qm, uint32_t nr_compute_tbslbrm(uint16_t table, uint16_t nb_rb, - uint8_t Nl, - uint8_t C); + uint8_t Nl); void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f); diff --git a/openair1/PHY/CODING/crc.h b/openair1/PHY/CODING/crc.h new file mode 100644 index 0000000000..d6474eae9b --- /dev/null +++ b/openair1/PHY/CODING/crc.h @@ -0,0 +1,543 @@ +/******************************************************************************* + Copyright (c) 2009-2018, Intel Corporation + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/** + * Header file for module with CRC computation methods + * + * PCLMULQDQ implementation is based on work by: + * Erdinc Ozturk + * Vinodh Gopal + * James Guilford + * + * "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction" + * URL: http://download.intel.com/design/intarch/papers/323102.pdf + */ + +#ifndef __CRC_H__ +#define __CRC_H__ + +#include + +#include "crcext.h" +#include "types.h" +#include +#include + +/** + * PCLMULQDQ CRC computation context structure + */ +struct crc_pclmulqdq_ctx { + /** + * K1 = reminder X^128 / P(X) : 0-63 + * K2 = reminder X^192 / P(X) : 64-127 + */ + uint64_t k1; + uint64_t k2; + + /** + * K3 = reminder X^64 / P(X) : 0-63 + * q = quotient X^64 / P(X) : 64-127 + */ + uint64_t k3; + uint64_t q; + + /** + * p = polynomial / P(X) : 0-63 + * res = reserved : 64-127 + */ + uint64_t p; + uint64_t res; +}; + +/** + * Functions and prototypes + */ + +/** + * @brief Initializes look-up-table (LUT) for given 8 bit polynomial + * + * @param poly CRC polynomial + * @param lut pointer to look-up-table to be initialized + */ +void crc8_init_lut(const uint8_t poly, uint8_t *lut); + +/** + * @brief Calculates 8 bit CRC using LUT method. + * + * @param crc CRC initial value + * @param data pointer to data block to calculate CRC for + * @param data_len size of data block + * @param lut 256x8bits look-up-table pointer + * + * @return New CRC value + */ +__forceinline +uint8_t crc8_calc_lut(const uint8_t *data, + uint32_t data_len, + uint8_t crc, + const uint8_t *lut) +{ + if (unlikely(data == NULL || lut == NULL)) + return crc; + + while (data_len--) + crc = lut[*data++ ^ crc]; + + return crc; +} + +/** + * @brief Initializes look-up-table (LUT) for given 16 bit polynomial + * + * @param poly CRC polynomial + * @param lut pointer to 256x16bits look-up-table to be initialized + */ +void crc16_init_lut(const uint16_t poly, uint16_t *lut); + +/** + * @brief Calculates 16 bit CRC using LUT method. + * + * @param crc CRC initial value + * @param data pointer to data block to calculate CRC for + * @param data_len size of data block + * @param lut 256x16bits look-up-table pointer + * + * @return New CRC value + */ +__forceinline +uint16_t crc16_calc_lut(const uint8_t *data, + uint32_t data_len, + uint16_t crc, + const uint16_t *lut) +{ + if (unlikely(data == NULL || lut == NULL)) + return crc; + + while (data_len--) + crc = lut[(crc >> 8) ^ *data++] ^ (crc << 8); + + return crc; +} + +/** + * @brief Initializes look-up-table (LUT) for given 32 bit polynomial + * + * @param poly CRC polynomial + * @param lut pointer to 256x32bits look-up-table to be initialized + */ +void crc32_init_lut(const uint32_t poly, uint32_t *lut); + +/** + * @brief Calculates 32 bit CRC using LUT method. + * + * @param crc CRC initial value + * @param data pointer to data block to calculate CRC for + * @param data_len size of data block + * @param lut 256x32bits look-up-table pointer + * + * @return New CRC value + */ +__forceinline +uint32_t crc32_calc_lut(const uint8_t *data, + uint32_t data_len, + uint32_t crc, + const uint32_t *lut) +{ + if (unlikely(data == NULL || lut == NULL)) + return crc; + + while (data_len--) + crc = lut[(crc >> 24) ^ *data++] ^ (crc << 8); + + return crc; +} + +/** + * @brief Initializes look up tables for slice-By-2 method. + * + * @param poly CRC polynomial + * @param slice1 slice-by-2 look-up-table 1 + * @param slice2 slice-by-2 look-up-table 2 + * + * @return New CRC value + */ +void crc16_init_slice2(const uint16_t poly, + uint16_t *slice1, + uint16_t *slice2); + +/** + * @brief Calculates 16 bit CRC using Slice-By-2 method. + * + * @param crc CRC initial value + * @param data pointer to data block to calculate CRC for + * @param data_len size of data block + * @param slice1 256x16bits slice look-up-table 1 + * @param slice2 256x16bits slice look-up-table 2 + * + * @return New CRC value + */ +__forceinline +uint16_t crc16_calc_slice2(const uint8_t *data, + uint32_t data_len, + uint16_t crc, + const uint16_t *slice1, + const uint16_t *slice2) +{ + uint_fast32_t i; + + if (unlikely(data == NULL)) + return crc; + + if (unlikely(slice1 == NULL || slice2 == NULL)) + return crc; + + crc = bswap2(crc); + for (i = (data_len & (~1)), data += (data_len & (~1)); i != 0; + i -= sizeof(uint16_t)) { + crc ^= (*((const uint16_t *)(data - i))); + crc = slice2[(uint8_t)crc] ^ slice1[(uint8_t)(crc >> 8)]; + } + crc = bswap2(crc); + if (data_len & 1) + crc = (crc << 8) ^ bswap2(slice1[(crc >> 8) ^ *data]); + + return crc; +} + +/** + * @brief Initializes look up tables for slice-By-4 method. + * + * @param poly CRC polynomial + * @param slice1 256x32bits slice look-up-table 1 + * @param slice2 256x32bits slice look-up-table 2 + * @param slice3 256x32bits slice look-up-table 3 + * @param slice4 256x32bits slice look-up-table 4 + * + * @return New CRC value + */ +void crc32_init_slice4(const uint32_t poly, + uint32_t *slice1, uint32_t *slice2, + uint32_t *slice3, uint32_t *slice4); + +/** + * @brief Calculates 32 bit CRC using Slice-By-4 method. + * + * @param data pointer to data block to calculate CRC for + * @param data_len size of data block + * @param crc CRC initial value + * @param slice1 256x32bits slice look-up-table 1 + * @param slice2 256x32bits slice look-up-table 2 + * @param slice3 256x32bits slice look-up-table 3 + * @param slice4 256x32bits slice look-up-table 4 + * + * @return New CRC value + */ +__forceinline +uint32_t crc32_calc_slice4(const uint8_t *data, + uint32_t data_len, uint32_t crc, + const uint32_t *slice1, const uint32_t *slice2, + const uint32_t *slice3, const uint32_t *slice4) +{ + uint_fast32_t i; + + if (unlikely(data == NULL)) + return crc; + + if (unlikely(slice1 == NULL || slice2 == NULL || + slice3 == NULL || slice4 == NULL)) + return crc; + + crc = bswap4(crc); + for (i = data_len & (~3), data += (data_len & (~3)); i != 0; + i -= sizeof(uint32_t)) { + crc ^= (*((const uint32_t *)(data - i))); + crc = slice4[(uint8_t)(crc)] ^ + slice3[(uint8_t)(crc >> 8)] ^ + slice2[(uint8_t)(crc >> 16)] ^ + slice1[(uint8_t)(crc >> 24)]; + } + crc = bswap4(crc); + for (i = data_len & 3, data += (data_len & 3); i != 0; i--) + crc = (crc << 8) ^ + bswap4(slice1[(crc >> 24) ^ *(data - i)]); + + return crc; +} + +/** + * @brief Performs one folding round + * + * Logically function operates as follows: + * DATA = READ_NEXT_16BYTES(); + * F1 = LSB8(FOLD) + * F2 = MSB8(FOLD) + * T1 = CLMUL( F1, K1 ) + * T2 = CLMUL( F2, K2 ) + * FOLD = XOR( T1, T2, DATA ) + * + * @param data_block 16 byte data block + * @param k1_k2 k1 and k2 constanst enclosed in XMM register + * @param fold running 16 byte folded data + * + * @return New 16 byte folded data + */ +__forceinline +__m128i crc32_folding_round(const __m128i data_block, + const __m128i k1_k2, + const __m128i fold) +{ + __m128i tmp = _mm_clmulepi64_si128(fold, k1_k2, 0x11); + + return _mm_xor_si128(_mm_clmulepi64_si128(fold, k1_k2, 0x00), + _mm_xor_si128(data_block, tmp)); +} + +/** + * @brief Performs Barret's reduction from 128 bits to 64 bits + * + * @param data128 128 bits data to be reduced + * @param k3_q k3 and Q constants enclosed in XMM register + * + * @return data reduced to 64 bits + */ +__forceinline +__m128i crc32_reduce_128_to_64(__m128i data128, const __m128i k3_q) +{ + __m128i tmp; + + tmp = _mm_xor_si128(_mm_clmulepi64_si128(data128, k3_q, 0x01 /* k3 */), + data128); + + data128 = _mm_xor_si128(_mm_clmulepi64_si128(tmp, k3_q, 0x01 /* k3 */), + data128); + + return _mm_srli_si128(_mm_slli_si128(data128, 8), 8); +} + +/** + * @brief Performs Barret's reduction from 64 bits to 32 bits + * + * @param data64 64 bits data to be reduced + * @param k3_q k3 and Q constants enclosed in XMM register + * @param p_res P constant enclosed in XMM register + * + * @return data reduced to 32 bits + */ +__forceinline +uint32_t +crc32_reduce_64_to_32(__m128i fold, const __m128i k3_q, const __m128i p_res) +{ + __m128i temp; + + temp = _mm_clmulepi64_si128(_mm_srli_si128(fold, 4), + k3_q, 0x10 /* Q */); + temp = _mm_srli_si128(_mm_xor_si128(temp, fold), 4); + temp = _mm_clmulepi64_si128(temp, p_res, 0 /* P */); + return _mm_extract_epi32(_mm_xor_si128(temp, fold), 0); +} + +/** + * @brief Calculates 32 bit CRC for given \a data block by applying folding and + * reduction methods. + * + * Algorithm operates on 32 bit CRCs so polynomials and initial values may + * need to be promoted to 32 bits where required. + * + * @param crc initial CRC value (32 bit value) + * @param data pointer to data block + * @param data_len length of \a data block in bytes + * @param params pointer to PCLMULQDQ CRC calculation context + * + * @return CRC for given \a data block (32 bits wide). + */ +__forceinline +uint32_t +crc32_calc_pclmulqdq(const uint8_t *data, + uint32_t data_len, uint32_t crc, + const struct crc_pclmulqdq_ctx *params) +{ + __m128i temp, fold, k, swap; + uint32_t n; + + if (unlikely(data == NULL || data_len == 0 || params == NULL)) + return crc; + +#ifdef __KERNEL__ + /** + * Preserve FPU context + */ + kernel_fpu_begin(); +#endif + + /** + * Add 4 bytes to data block size + * This is to secure the following: + * CRC32 = M(X)^32 mod P(X) + * M(X) - message to compute CRC on + * P(X) - CRC polynomial + */ + data_len += 4; + + /** + * Load first 16 data bytes in \a fold and + * set \a swap BE<->LE 16 byte conversion variable + */ + fold = _mm_loadu_si128((__m128i *)data); + swap = crc_xmm_be_le_swap128; + + /** + * ------------------------------------------------- + * Folding all data into single 16 byte data block + * Assumes: \a fold holds first 16 bytes of data + */ + + if (unlikely(data_len <= 16)) { + /** + * Data block fits into 16 byte block + * - adjust data block + * - 4 least significant bytes need to be zero + */ + fold = _mm_shuffle_epi8(fold, swap); + fold = _mm_slli_si128(xmm_shift_right(fold, 20 - data_len), 4); + + /** + * Apply CRC init value + */ + temp = _mm_insert_epi32(_mm_setzero_si128(), bswap4(crc), 0); + temp = xmm_shift_left(temp, data_len - 4); + fold = _mm_xor_si128(fold, temp); + } else { + /** + * There are 2x16 data blocks or more + */ + __m128i next_data; + + /** + * n = number of bytes required to align \a data_len + * to multiple of 16 + */ + n = ((~data_len) + 1) & 15; + + /** + * Apply CRC initial value and + * get \a fold to BE format + */ + fold = _mm_xor_si128(fold, + _mm_insert_epi32(_mm_setzero_si128(), + crc, 0)); + fold = _mm_shuffle_epi8(fold, swap); + + /** + * Load next 16 bytes of data and + * adjust \a fold & \a next_data as follows: + * + * CONCAT(fold,next_data) >> (n*8) + */ + next_data = _mm_loadu_si128((__m128i *)&data[16]); + next_data = _mm_shuffle_epi8(next_data, swap); + next_data = _mm_or_si128(xmm_shift_right(next_data, n), + xmm_shift_left(fold, 16 - n)); + fold = xmm_shift_right(fold, n); + + if (unlikely(data_len <= 32)) + /** + * In such unlikely case clear 4 least significant bytes + */ + next_data = + _mm_slli_si128(_mm_srli_si128(next_data, 4), 4); + + /** + * Do the initial folding round on 2 first 16 byte chunks + */ + k = _mm_load_si128((__m128i *)(¶ms->k1)); + fold = crc32_folding_round(next_data, k, fold); + + if (likely(data_len > 32)) { + /** + * \a data_block needs to be at least 48 bytes long + * in order to get here + */ + __m128i new_data; + + /** + * Main folding loop + * - n is adjusted to point to next 16 data block + * to read + * (16+16) = 2x16; represents 2 first data blocks + * processed above + * (- n) is the number of zero bytes padded to + * the message in order to align it to 16 bytes + * - the last 16 bytes is processed separately + */ + for (n = 16 + 16 - n; n < (data_len - 16); n += 16) { + new_data = _mm_loadu_si128((__m128i *)&data[n]); + new_data = _mm_shuffle_epi8(new_data, swap); + fold = crc32_folding_round(new_data, k, fold); + } + + /** + * The last folding round works always on 12 bytes + * (12 bytes of data and 4 zero bytes) + * Read from offset -4 is to avoid one + * shift right operation. + */ + new_data = _mm_loadu_si128((__m128i *)&data[n - 4]); + new_data = _mm_shuffle_epi8(new_data, swap); + new_data = _mm_slli_si128(new_data, 4); + fold = crc32_folding_round(new_data, k, fold); + } /* if (data_len > 32) */ + } + + /** + * ------------------------------------------------- + * Reduction 128 -> 32 + * Assumes: \a fold holds 128bit folded data + */ + + /** + * REDUCTION 128 -> 64 + */ + k = _mm_load_si128((__m128i *)(¶ms->k3)); + fold = crc32_reduce_128_to_64(fold, k); + + /** + * REDUCTION 64 -> 32 + */ + n = crc32_reduce_64_to_32(fold, k, + _mm_load_si128((__m128i *)(¶ms->p))); + +#ifdef __KERNEL__ + /** + * - restore FPU context + */ + kernel_fpu_end(); +#endif + + return n; +} + +#endif /* __CRC_H__ */ diff --git a/openair1/PHY/CODING/crc_byte.c b/openair1/PHY/CODING/crc_byte.c index 555f314429..d1c3917c2c 100644 --- a/openair1/PHY/CODING/crc_byte.c +++ b/openair1/PHY/CODING/crc_byte.c @@ -30,10 +30,17 @@ Modified in June, 2001, to include the length non multiple of 8 */ +#ifndef __SSE4_1__ +#define USE_INTEL_CRC 0 +#else +#define USE_INTEL_CRC __SSE4_1__ +#endif #include "coding_defs.h" #include "assertions.h" - +#if USE_INTEL_CRC +#include "crc.h" +#endif /*ref 36-212 v8.6.0 , pp 8-9 */ /* the highest degree is set by default */ @@ -94,6 +101,28 @@ static unsigned short crc11Table[256]; static unsigned char crc8Table[256]; static unsigned char crc6Table[256]; +#if USE_INTEL_CRC +static DECLARE_ALIGNED(struct crc_pclmulqdq_ctx lte_crc24a_pclmulqdq, 16) = { + 0x64e4d700, /**< k1 */ + 0x2c8c9d00, /**< k2 */ + 0xd9fe8c00, /**< k3 */ + 0xf845fe24, /**< q */ + 0x864cfb00, /**< p */ + 0ULL /**< res */ +}; +__m128i crc_xmm_be_le_swap128; + +DECLARE_ALIGNED(const uint8_t crc_xmm_shift_tab[48], 16) = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +#endif + void crcTableInit (void) { unsigned char c = 0; @@ -108,23 +137,29 @@ void crcTableInit (void) crc8Table[c] = (unsigned char) (crcbit (&c, 1, poly8) >> 24); crc6Table[c] = (unsigned char) (crcbit (&c, 1, poly6) >> 24); } while (++c); +#if USE_INTEL_CRC + crc_xmm_be_le_swap128 = _mm_setr_epi32(0x0c0d0e0f, 0x08090a0b, + 0x04050607, 0x00010203); + +#endif } /********************************************************* -Byte by byte implementations, +Byte by byte LUT implementations, assuming initial byte is 0 padded (in MSB) if necessary - +can use SIMD optimized Intel CRC for LTE/NR 24a/24b variants *********************************************************/ + unsigned int crc24a (unsigned char * inptr, int bitlen) { + int octetlen = bitlen / 8; /* Change in octets */ - int octetlen, resbit; - unsigned int crc = 0; - octetlen = bitlen / 8; /* Change in octets */ - resbit = (bitlen % 8); - + if ( bitlen % 8 || !USE_INTEL_CRC ) { + unsigned int crc = 0; + int resbit= (bitlen % 8); + while (octetlen-- > 0) { // printf("crc24a: in %x => crc %x\n",crc,*inptr); crc = (crc << 8) ^ crc24aTable[(*inptr++) ^ (crc >> 24)]; @@ -132,17 +167,35 @@ unsigned int crc24a (unsigned char * inptr, if (resbit > 0) crc = (crc << resbit) ^ crc24aTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))]; - return crc; + } + #if USE_INTEL_CRC + else { + return crc32_calc_pclmulqdq(inptr, octetlen, 0, + <e_crc24a_pclmulqdq); + } + #endif + } +#if USE_INTEL_CRC +static DECLARE_ALIGNED(struct crc_pclmulqdq_ctx lte_crc24b_pclmulqdq, 16) = { + 0x80140500, /**< k1 */ + 0x42000100, /**< k2 */ + 0x90042100, /**< k3 */ + 0xffff83ff, /**< q */ + 0x80006300, /**< p */ + 0ULL /**< res */ +}; +#endif unsigned int crc24b (unsigned char * inptr, - int bitlen) + int bitlen) { - int octetlen, resbit; + int octetlen = bitlen / 8; /* Change in octets */ + + if ( bitlen % 8 || !USE_INTEL_CRC ) { unsigned int crc = 0; - octetlen = bitlen / 8; /* Change in octets */ - resbit = (bitlen % 8); + int resbit = (bitlen % 8); while (octetlen-- > 0) { // printf("crc24b: in %x => crc %x (%x)\n",crc,*inptr,crc24bTable[(*inptr) ^ (crc >> 24)]); @@ -153,6 +206,13 @@ unsigned int crc24b (unsigned char * inptr, crc = (crc << resbit) ^ crc24bTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))]; return crc; + } +#if USE_INTEL_CRC + else { + return crc32_calc_pclmulqdq(inptr, octetlen, 0, + <e_crc24b_pclmulqdq); + } +#endif } unsigned int crc24c (unsigned char * inptr, @@ -260,7 +320,7 @@ crc6 (unsigned char * inptr, int bitlen) } if (resbit > 0) - crc = (crc << resbit) ^ (crc8Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 24); + crc = (crc << resbit) ^ (crc6Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 24); return crc; } diff --git a/openair1/PHY/CODING/crcext.h b/openair1/PHY/CODING/crcext.h new file mode 100644 index 0000000000..f441f25e50 --- /dev/null +++ b/openair1/PHY/CODING/crcext.h @@ -0,0 +1,89 @@ +/******************************************************************************* + Copyright (c) 2009-2018, Intel Corporation + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/** + * Header file with CRC external definitions + * + */ + +#ifndef __CRCEXT_H__ +#define __CRCEXT_H__ + +#include +#include "types.h" +/** + * Flag indicating availability of PCLMULQDQ instruction + * Only valid after running CRCInit() function. + */ +extern int pclmulqdq_available; + +/** + * Flag indicating availability of PCLMULQDQ instruction + * Only valid after running CRCInit() function. + */ +extern __m128i crc_xmm_be_le_swap128; +extern const uint8_t crc_xmm_shift_tab[48]; + +/** + * @brief Shifts right 128 bit register by specified number of bytes + * + * @param reg 128 bit value + * @param num number of bytes to shift right \a reg by (0-16) + * + * @return \a reg >> (\a num * 8) + */ +__forceinline +__m128i xmm_shift_right(__m128i reg, const unsigned int num) +{ + const __m128i *p = (const __m128i *)(crc_xmm_shift_tab + 16 + num); + + return _mm_shuffle_epi8(reg, _mm_loadu_si128(p)); +} + +/** + * @brief Shifts left 128 bit register by specified number of bytes + * + * @param reg 128 bit value + * @param num number of bytes to shift left \a reg by (0-16) + * + * @return \a reg << (\a num * 8) + */ +__forceinline +__m128i xmm_shift_left(__m128i reg, const unsigned int num) +{ + const __m128i *p = (const __m128i *)(crc_xmm_shift_tab + 16 - num); + + return _mm_shuffle_epi8(reg, _mm_loadu_si128(p)); +} + +/** + * @brief Initializes CRC module. + * @note It is mandatory to run it before using any of CRC API's. + */ +extern void CRCInit(void); + +#endif /* __CRCEXT_H__ */ diff --git a/openair1/PHY/CODING/defs_NB_IoT.h b/openair1/PHY/CODING/defs_NB_IoT.h index 2a6bee7924..d33ae1c440 100644 --- a/openair1/PHY/CODING/defs_NB_IoT.h +++ b/openair1/PHY/CODING/defs_NB_IoT.h @@ -30,14 +30,6 @@ #include // for uint8/16/32_t -/* check if this ifndef is required for NB-IoT ?! -//#ifndef NO_OPENAIR1 -//#include "PHY/defs_NB_IoT.h" -//#else -//#include "PHY/TOOLS/time_meas.h" -//#endif -*/ - #define CRC24_A_NB_IoT 0 #define CRC24_B_NB_IoT 1 #define CRC16_NB_IoT 2 diff --git a/openair1/PHY/CODING/nrLDPC_cnProc.h b/openair1/PHY/CODING/nrLDPC_cnProc.h new file mode 100644 index 0000000000..02a9f8554c --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_cnProc.h @@ -0,0 +1,2444 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*!\file nrLDPC_cnProc.h + * \brief Defines the functions for check node processing + * \author Sebastian Wagner (TCL Communications) Email: + * \date 30-09-2019 + * \version 1.0 + * \note + * \warning + */ + +#ifndef __NR_LDPC_CNPROC__H__ +#define __NR_LDPC_CNPROC__H__ + +/** + \brief Performs CN processing for BG2 on the CN processing buffer and stores the results in the CN processing results buffer. + \param p_lut Pointer to decoder LUTs + \param p_procBuf Pointer to processing buffers + \param Z Lifting size +*/ +static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_procBuf, uint16_t Z) +{ + const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; + + __m256i* p_cnProcBuf; + __m256i* p_cnProcBufRes; + + // Number of CNs in Groups + uint32_t M; + uint32_t i; + uint32_t j; + uint32_t k; + // Offset to each bit within a group in terms of 32 Byte + uint32_t bitOffsetInGroup; + + __m256i ymm0, min, sgn; + __m256i* p_cnProcBufResBit; + + const __m256i* p_ones = (__m256i*) ones256_epi8; + const __m256i* p_maxLLR = (__m256i*) maxLLR256_epi8; + + // LUT with offsets for bits that need to be processed + // 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc. + // Offsets are in units of bitOffsetInGroup + const uint8_t lut_idxCnProcG3[3][2] = {{72,144}, {0,144}, {0,72}}; + + // ===================================================================== + // Process group with 3 BNs + + if (lut_numCnInCnGroups[0] > 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[0]*Z + 31)>>5; + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[0]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 3 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[0]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[0]]; + + // Loop over every BN + for (j=0; j<3; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + __m256i *pj0 = &p_cnProcBuf[lut_idxCnProcG3[j][0]]; + __m256i *pj1 = &p_cnProcBuf[lut_idxCnProcG3[j][1]]; + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[1]*Z + 31)>>5; + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[1]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 4 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + for (j=0; j<4; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[2]*Z + 31)>>5; + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[2]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 5 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[2]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[2]]; + + // Loop over every BN + for (j=0; j<5; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[3]*Z + 31)>>5; + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[3]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 6 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[3]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[3]]; + + // Loop over every BN + for (j=0; j<6; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[4]*Z + 31)>>5; + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[4]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 8 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[4]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[4]]; + + // Loop over every BN + for (j=0; j<8; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[5]*Z + 31)>>5; + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[5]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 10 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[5]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[5]]; + + // Loop over every BN + for (j=0; j<10; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; inumCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; + + __m512i* p_cnProcBuf; + __m512i* p_cnProcBufRes; + + // Number of CNs in Groups + uint32_t M; + uint32_t i; + uint32_t j; + uint32_t k; + // Offset to each bit within a group in terms of 32 Byte + uint32_t bitOffsetInGroup; + + __m512i zmm0, min, sgn, zeros,maxLLR; + + zeros = _mm512_setzero_si512(); + maxLLR = _mm512_set1_epi8((char)127); + __m512i* p_cnProcBufResBit; + + + const __m512i* p_ones = (__m512i*) ones512_epi8; + const __m512i* p_maxLLR = (__m512i*) maxLLR512_epi8; + + + + + // LUT with offsets for bits that need to be processed + // 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc. + // Offsets are in units of bitOffsetInGroup (1*384/32) + const uint8_t lut_idxCnProcG3[3][2] = {{12,24}, {0,24}, {0,12}}; + + // ===================================================================== + // Process group with 3 BNs + + if (lut_numCnInCnGroups[0] > 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[0]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 3 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[0]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[0]]; + + // Loop over every BN + for (j=0; j<3; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[1]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 4 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + for (j=0; j<4; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[2]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[2]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 5 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[2]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[2]]; + + // Loop over every BN + for (j=0; j<5; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[3]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[3]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 6 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[3]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[3]]; + + // Loop over every BN + for (j=0; j<6; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[4]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[4]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 7 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[4]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[4]]; + + // Loop over every BN + for (j=0; j<7; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[5]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[5]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 8 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[5]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[5]]; + + // Loop over every BN + for (j=0; j<8; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[6]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[6]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 9 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[6]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[6]]; + + // Loop over every BN + for (j=0; j<9; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[7]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[7]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 10 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[7]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[7]]; + + // Loop over every BN + for (j=0; j<10; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[8]*Z + 63)>>6; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[8]*NR_LDPC_ZMAX)>>6; + + // Set pointers to start of group 19 + p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[8]]; + p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[8]]; + + // Loop over every BN + for (j=0; j<19; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; inumCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; + + __m256i* p_cnProcBuf; + __m256i* p_cnProcBufRes; + + // Number of CNs in Groups + uint32_t M; + uint32_t i; + uint32_t j; + uint32_t k; + // Offset to each bit within a group in terms of 32 Byte + uint32_t bitOffsetInGroup; + + __m256i ymm0, min, sgn; + __m256i* p_cnProcBufResBit; + + const __m256i* p_ones = (__m256i*) ones256_epi8; + const __m256i* p_maxLLR = (__m256i*) maxLLR256_epi8; + + // LUT with offsets for bits that need to be processed + // 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc. + // Offsets are in units of bitOffsetInGroup (1*384/32) + const uint8_t lut_idxCnProcG3[3][2] = {{12,24}, {0,24}, {0,12}}; + + // ===================================================================== + // Process group with 3 BNs + + if (lut_numCnInCnGroups[0] > 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[0]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 3 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[0]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[0]]; + + // Loop over every BN + for (j=0; j<3; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[1]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 4 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + for (j=0; j<4; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[2]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[2]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 5 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[2]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[2]]; + + // Loop over every BN + for (j=0; j<5; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[3]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[3]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 6 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[3]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[3]]; + + // Loop over every BN + for (j=0; j<6; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[4]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[4]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 7 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[4]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[4]]; + + // Loop over every BN + for (j=0; j<7; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[5]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[5]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 8 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[5]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[5]]; + + // Loop over every BN + for (j=0; j<8; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[6]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[6]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 9 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[6]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[6]]; + + // Loop over every BN + for (j=0; j<9; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[7]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[7]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 10 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[7]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[7]]; + + // Loop over every BN + for (j=0; j<10; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; i 0) + { + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M = (lut_numCnInCnGroups[8]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[8]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 19 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[8]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[8]]; + + // Loop over every BN + for (j=0; j<19; j++) + { + // Set of results pointer to correct BN address + p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + for (i=0; inumCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; + + __m256i* p_cnProcBuf; + __m256i* p_cnProcBufRes; + + // Number of CNs in Groups + uint32_t M; + uint32_t i; + uint32_t j; + uint32_t pcRes = 0; + uint32_t pcResSum = 0; + uint32_t Mrem; + uint32_t M32; + + __m256i ymm0, ymm1; + + // ===================================================================== + // Process group with 3 BNs + + if (lut_numCnInCnGroups[0] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[0]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 3 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[0]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[0]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<3; j++) + { + // BN offset is units of (1*384/32) = 12 + ymm0 = p_cnProcBuf [j*12 + i]; + ymm1 = p_cnProcBufRes[j*12 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<3; j++) + { + // BN offset is units of (1*384/32) = 12 + ymm0 = p_cnProcBuf [j*12 + i]; + ymm1 = p_cnProcBufRes[j*12 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 4 BNs + + if (lut_numCnInCnGroups[1] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[1]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 4 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<4; j++) + { + // BN offset is units of 5*384/32 = 60 + ymm0 = p_cnProcBuf [j*60 + i]; + ymm1 = p_cnProcBufRes[j*60 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<4; j++) + { + // BN offset is units of 5*384/32 = 60 + ymm0 = p_cnProcBuf [j*60 + i]; + ymm1 = p_cnProcBufRes[j*60 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 5 BNs + + if (lut_numCnInCnGroups[2] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[2]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 5 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[2]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[2]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<5; j++) + { + // BN offset is units of 18*384/32 = 216 + ymm0 = p_cnProcBuf [j*216 + i]; + ymm1 = p_cnProcBufRes[j*216 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<5; j++) + { + // BN offset is units of 18*384/32 = 216 + ymm0 = p_cnProcBuf [j*216 + i]; + ymm1 = p_cnProcBufRes[j*216 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 6 BNs + + if (lut_numCnInCnGroups[3] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[3]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 6 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[3]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[3]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<6; j++) + { + // BN offset is units of 8*384/32 = 96 + ymm0 = p_cnProcBuf [j*96 + i]; + ymm1 = p_cnProcBufRes[j*96 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<6; j++) + { + // BN offset is units of 8*384/32 = 96 + ymm0 = p_cnProcBuf [j*96 + i]; + ymm1 = p_cnProcBufRes[j*96 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 7 BNs + + if (lut_numCnInCnGroups[4] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[4]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 7 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[4]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[4]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<7; j++) + { + // BN offset is units of 5*384/32 = 60 + ymm0 = p_cnProcBuf [j*60 + i]; + ymm1 = p_cnProcBufRes[j*60 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<7; j++) + { + // BN offset is units of 5*384/32 = 60 + ymm0 = p_cnProcBuf [j*60 + i]; + ymm1 = p_cnProcBufRes[j*60 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 8 BNs + + if (lut_numCnInCnGroups[5] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[5]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 8 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[5]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[5]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<8; j++) + { + // BN offset is units of 2*384/32 = 24 + ymm0 = p_cnProcBuf [j*24 + i]; + ymm1 = p_cnProcBufRes[j*24 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<8; j++) + { + // BN offset is units of 2*384/32 = 24 + ymm0 = p_cnProcBuf [j*24 + i]; + ymm1 = p_cnProcBufRes[j*24 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 9 BNs + + if (lut_numCnInCnGroups[6] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[6]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 9 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[6]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[6]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<9; j++) + { + // BN offset is units of 2*384/32 = 24 + ymm0 = p_cnProcBuf [j*24 + i]; + ymm1 = p_cnProcBufRes[j*24 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<9; j++) + { + // BN offset is units of 2*384/32 = 24 + ymm0 = p_cnProcBuf [j*24 + i]; + ymm1 = p_cnProcBufRes[j*24 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 10 BNs + + if (lut_numCnInCnGroups[7] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[7]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 10 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[7]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[7]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<10; j++) + { + // BN offset is units of 1*384/32 = 12 + ymm0 = p_cnProcBuf [j*12 + i]; + ymm1 = p_cnProcBufRes[j*12 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<10; j++) + { + // BN offset is units of 1*384/32 = 12 + ymm0 = p_cnProcBuf [j*12 + i]; + ymm1 = p_cnProcBufRes[j*12 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 19 BNs + + if (lut_numCnInCnGroups[8] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[8]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 19 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[8]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[8]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN (Last BN is connected to multiple CNs) + // Compute PC for 32 CNs at once + for (j=0; j<19; j++) + { + // BN offset is units of 4*384/32 = 48 + ymm0 = p_cnProcBuf [j*48 + i]; + ymm1 = p_cnProcBufRes[j*48 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN (Last BN is connected to multiple CNs) + // Compute PC for 32 CNs at once + for (j=0; j<19; j++) + { + // BN offset is units of 4*384/32 = 48 + ymm0 = p_cnProcBuf [j*48 + i]; + ymm1 = p_cnProcBufRes[j*48 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + return pcResSum; +} + +/** + \brief Performs parity check for BG2 on the CN processing buffer. Stops as soon as error is detected. + \param p_lut Pointer to decoder LUTs + \param Z Lifting size + \return 32-bit parity check indicator +*/ +static inline uint32_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_procBuf, uint16_t Z) +{ + const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; + + __m256i* p_cnProcBuf; + __m256i* p_cnProcBufRes; + + // Number of CNs in Groups + uint32_t M; + uint32_t i; + uint32_t j; + uint32_t pcRes = 0; + uint32_t pcResSum = 0; + uint32_t Mrem; + uint32_t M32; + + __m256i ymm0, ymm1; + + // ===================================================================== + // Process group with 3 BNs + + if (lut_numCnInCnGroups[0] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[0]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 3 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[0]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[0]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<3; j++) + { + // BN offset is units of (6*384/32) = 72 + ymm0 = p_cnProcBuf [j*72 + i]; + ymm1 = p_cnProcBufRes[j*72 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<3; j++) + { + // BN offset is units of (6*384/32) = 72 + ymm0 = p_cnProcBuf [j*72 + i]; + ymm1 = p_cnProcBufRes[j*72 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 4 BNs + + if (lut_numCnInCnGroups[1] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[1]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 4 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<4; j++) + { + // BN offset is units of 20*384/32 = 240 + ymm0 = p_cnProcBuf [j*240 + i]; + ymm1 = p_cnProcBufRes[j*240 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<4; j++) + { + // BN offset is units of 20*384/32 = 240 + ymm0 = p_cnProcBuf [j*240 + i]; + ymm1 = p_cnProcBufRes[j*240 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 5 BNs + + if (lut_numCnInCnGroups[2] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[2]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 5 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[2]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[2]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<5; j++) + { + // BN offset is units of 9*384/32 = 108 + ymm0 = p_cnProcBuf [j*108 + i]; + ymm1 = p_cnProcBufRes[j*108 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<5; j++) + { + // BN offset is units of 9*384/32 = 108 + ymm0 = p_cnProcBuf [j*108 + i]; + ymm1 = p_cnProcBufRes[j*108 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 6 BNs + + if (lut_numCnInCnGroups[3] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[3]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 6 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[3]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[3]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<6; j++) + { + // BN offset is units of 3*384/32 = 36 + ymm0 = p_cnProcBuf [j*36 + i]; + ymm1 = p_cnProcBufRes[j*36 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<6; j++) + { + // BN offset is units of 3*384/32 = 36 + ymm0 = p_cnProcBuf [j*36 + i]; + ymm1 = p_cnProcBufRes[j*36 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 8 BNs + + if (lut_numCnInCnGroups[4] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[4]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 8 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[4]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[4]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<8; j++) + { + // BN offset is units of 2*384/32 = 24 + ymm0 = p_cnProcBuf [j*24 + i]; + ymm1 = p_cnProcBufRes[j*24 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<8; j++) + { + // BN offset is units of 2*384/32 = 24 + ymm0 = p_cnProcBuf [j*24 + i]; + ymm1 = p_cnProcBufRes[j*24 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + // ===================================================================== + // Process group with 10 BNs + + if (lut_numCnInCnGroups[5] > 0) + { + // Reset results + pcResSum = 0; + + // Number of CNs in group + M = lut_numCnInCnGroups[5]*Z; + // Remainder modulo 32 + Mrem = M&31; + // Number of groups of 32 CNs for parallel processing + // Ceil for values not divisible by 32 + M32 = (M + 31)>>5; + + // Set pointers to start of group 10 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[5]]; + p_cnProcBufRes = (__m256i*) &cnProcBufRes[lut_startAddrCnGroups[5]]; + + // Loop over CNs + for (i=0; i<(M32-1); i++) + { + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<10; j++) + { + // BN offset is units of 2*384/32 = 24 + ymm0 = p_cnProcBuf [j*24 + i]; + ymm1 = p_cnProcBufRes[j*24 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + pcResSum |= pcRes; + } + + // Last 32 CNs might not be full valid 32 depending on Z + pcRes = 0; + // Loop over every BN + // Compute PC for 32 CNs at once + for (j=0; j<10; j++) + { + // BN offset is units of 2*384/32 = 24 + ymm0 = p_cnProcBuf [j*24 + i]; + ymm1 = p_cnProcBufRes[j*24 + i]; + + // Add BN and input LLR, extract the sign bit + // and add in GF(2) (xor) + pcRes ^= _mm256_movemask_epi8(_mm256_adds_epi8(ymm0,ymm1)); + } + + // If no error pcRes should be 0 + // Only use valid CNs + pcResSum |= (pcRes&(0xFFFFFFFF>>(32-Mrem))); + + // If PC failed we can stop here + if (pcResSum > 0) + { + return pcResSum; + } + } + + return pcResSum; +} + +#endif + diff --git a/openair1/PHY/CODING/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder.c new file mode 100644 index 0000000000..b1a91769c6 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder.c @@ -0,0 +1,505 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*!\file nrLDPC_decoder.c + * \brief Defines the LDPC decoder + * \author Sebastian Wagner (TCL Communications) Email: + * \date 30-09-2019 + * \version 2.0 + * \note + * \warning + */ + + +#include +#include +#include "nrLDPCdecoder_defs.h" +#include "nrLDPC_types.h" +#include "nrLDPC_init.h" +#include "nrLDPC_mPass.h" +#include "nrLDPC_cnProc.h" +#include "nrLDPC_bnProc.h" + +#define NR_LDPC_ENABLE_PARITY_CHECK +#define NR_LDPC_PROFILER_DETAIL + +#ifdef NR_LDPC_DEBUG_MODE +#include "nrLDPC_tools/nrLDPC_debug.h" +#endif + +static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDPC_procBuf* p_procBuf, uint32_t numLLR, t_nrLDPC_lut* p_lut, t_nrLDPC_dec_params* p_decParams, t_nrLDPC_time_stats* p_profiler); + +int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, t_nrLDPC_procBuf* p_procBuf, t_nrLDPC_time_stats* p_profiler) +{ + uint32_t numLLR; + uint32_t numIter = 0; + t_nrLDPC_lut lut; + t_nrLDPC_lut* p_lut = &lut; + + //printf("p_procBuf->cnProcBuf = %p\n", p_procBuf->cnProcBuf); + + // Initialize decoder core(s) with correct LUTs + numLLR = nrLDPC_init(p_decParams, p_lut); + + // Launch LDPC decoder core for one segment + numIter = nrLDPC_decoder_core(p_llr, p_out, p_procBuf, numLLR, p_lut, p_decParams, p_profiler); + + return numIter; +} + +/** + \brief Performs LDPC decoding of one code block + \param p_llr Input LLRs + \param p_out Output vector + \param numLLR Number of LLRs + \param p_lut Pointer to decoder LUTs + \param p_decParams LDPC decoder parameters + \param p_profiler LDPC profiler statistics +*/ +static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDPC_procBuf* p_procBuf, uint32_t numLLR, t_nrLDPC_lut* p_lut, t_nrLDPC_dec_params* p_decParams, t_nrLDPC_time_stats* p_profiler) +{ + uint16_t Z = p_decParams->Z; + uint8_t BG = p_decParams->BG; + uint8_t numMaxIter = p_decParams->numMaxIter; + e_nrLDPC_outMode outMode = p_decParams->outMode; + + // Minimum number of iterations is 1 + // 0 iterations means hard-decision on input LLRs + uint32_t i = 1; + // Initialize with parity check fail != 0 + int32_t pcRes = 1; + int8_t* p_llrOut; + + if (outMode == nrLDPC_outMode_LLRINT8) + { + p_llrOut = p_out; + } + else + { + // Use LLR processing buffer as temporary output buffer + p_llrOut = p_procBuf->llrProcBuf; + // Clear llrProcBuf + memset(p_llrOut,0, NR_LDPC_MAX_NUM_LLR*sizeof(int8_t)); + } + + + // Initialization +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->llr2llrProcBuf); +#endif + nrLDPC_llr2llrProcBuf(p_lut, p_llr, p_procBuf, Z, BG); +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->llr2llrProcBuf); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_initBuffer2File(nrLDPC_buffers_LLR_PROC); + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_PROC, p_procBuf); +#endif + +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->llr2CnProcBuf); +#endif + if (BG == 1) + { + nrLDPC_llr2CnProcBuf_BG1(p_lut, p_llr, p_procBuf, Z); + } + else + { + nrLDPC_llr2CnProcBuf_BG2(p_lut, p_llr, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->llr2CnProcBuf); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_initBuffer2File(nrLDPC_buffers_CN_PROC); + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf); +#endif + + // First iteration + + // CN processing +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->cnProc); +#endif + if (BG == 1) + { + #ifdef __AVX512BW__ + nrLDPC_cnProc_BG1_AVX512(p_lut, p_procBuf, Z); + #else + nrLDPC_cnProc_BG1(p_lut, p_procBuf, Z); + #endif + } + else + { + nrLDPC_cnProc_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->cnProc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_initBuffer2File(nrLDPC_buffers_CN_PROC_RES); + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC_RES, p_procBuf); +#endif + +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->cn2bnProcBuf); +#endif + if (BG == 1) + { + nrLDPC_cn2bnProcBuf_BG1(p_lut, p_procBuf, Z); + } + else + { + nrLDPC_cn2bnProcBuf_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->cn2bnProcBuf); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_initBuffer2File(nrLDPC_buffers_BN_PROC); + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC, p_procBuf); +#endif + + // BN processing +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bnProcPc); +#endif + nrLDPC_bnProcPc(p_lut, p_procBuf, Z); +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bnProcPc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_initBuffer2File(nrLDPC_buffers_LLR_RES); + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_RES, p_procBuf); +#endif + +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bnProc); +#endif + nrLDPC_bnProc(p_lut, p_procBuf, Z); +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bnProc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_initBuffer2File(nrLDPC_buffers_BN_PROC_RES); + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC_RES, p_procBuf); +#endif + + // BN results to CN processing buffer +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bn2cnProcBuf); +#endif + if (BG == 1) + { + nrLDPC_bn2cnProcBuf_BG1(p_lut, p_procBuf, Z); + } + else + { + nrLDPC_bn2cnProcBuf_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bn2cnProcBuf); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf); +#endif + + // Parity Check not necessary here since it will fail + // because first 2 cols/BNs in BG are punctured and cannot be + // estimated after only one iteration + + // First iteration finished + + while ( (i < (numMaxIter-1)) && (pcRes != 0) ) + { + // Increase iteration counter + i++; + + // CN processing +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->cnProc); +#endif + if (BG == 1) + { + #ifdef __AVX512BW__ + nrLDPC_cnProc_BG1_AVX512(p_lut, p_procBuf, Z); + #else + nrLDPC_cnProc_BG1(p_lut, p_procBuf, Z); + #endif + } + else + { + nrLDPC_cnProc_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->cnProc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC_RES, p_procBuf); +#endif + + // Send CN results back to BNs +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->cn2bnProcBuf); +#endif + if (BG == 1) + { + nrLDPC_cn2bnProcBuf_BG1(p_lut, p_procBuf, Z); + } + else + { + nrLDPC_cn2bnProcBuf_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->cn2bnProcBuf); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC, p_procBuf); +#endif + + // BN Processing +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bnProcPc); +#endif + nrLDPC_bnProcPc(p_lut, p_procBuf, Z); +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bnProcPc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_RES, p_procBuf); +#endif + +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bnProc); +#endif + nrLDPC_bnProc(p_lut, p_procBuf, Z); +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bnProc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC_RES, p_procBuf); +#endif + + // BN results to CN processing buffer +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bn2cnProcBuf); +#endif + if (BG == 1) + { + nrLDPC_bn2cnProcBuf_BG1(p_lut, p_procBuf, Z); + } + else + { + nrLDPC_bn2cnProcBuf_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bn2cnProcBuf); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf); +#endif + + // Parity Check +#ifdef NR_LDPC_ENABLE_PARITY_CHECK +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->cnProcPc); +#endif + if (BG == 1) + { + pcRes = nrLDPC_cnProcPc_BG1(p_lut, p_procBuf, Z); + } + else + { + pcRes = nrLDPC_cnProcPc_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->cnProcPc); +#endif +#endif + } + + // Last iteration + if ( (i < numMaxIter) && (pcRes != 0) ) + { + // Increase iteration counter + i++; + + // CN processing +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->cnProc); +#endif + if (BG == 1) + { + #ifdef __AVX512BW__ + nrLDPC_cnProc_BG1_AVX512(p_lut, p_procBuf, Z); + #else + nrLDPC_cnProc_BG1(p_lut, p_procBuf, Z); + #endif + } + else + { + nrLDPC_cnProc_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->cnProc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC_RES, p_procBuf); +#endif + + // Send CN results back to BNs +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->cn2bnProcBuf); +#endif + if (BG == 1) + { + nrLDPC_cn2bnProcBuf_BG1(p_lut, p_procBuf, Z); + } + else + { + nrLDPC_cn2bnProcBuf_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->cn2bnProcBuf); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC, p_procBuf); +#endif + + // BN Processing +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bnProcPc); +#endif + nrLDPC_bnProcPc(p_lut, p_procBuf, Z); +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bnProcPc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_RES, p_procBuf); +#endif + + // If parity check not enabled, no need to send the BN proc results + // back to CNs +#ifdef NR_LDPC_ENABLE_PARITY_CHECK +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bnProc); +#endif + nrLDPC_bnProc(p_lut, p_procBuf, Z); +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bnProc); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC_RES, p_procBuf); +#endif + + // BN results to CN processing buffer +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->bn2cnProcBuf); +#endif + if (BG == 1) + { + nrLDPC_bn2cnProcBuf_BG1(p_lut, p_procBuf, Z); + } + else + { + nrLDPC_bn2cnProcBuf_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->bn2cnProcBuf); +#endif + +#ifdef NR_LDPC_DEBUG_MODE + nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf); +#endif + + // Parity Check +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->cnProcPc); +#endif + if (BG == 1) + { + pcRes = nrLDPC_cnProcPc_BG1(p_lut, p_procBuf, Z); + } + else + { + pcRes = nrLDPC_cnProcPc_BG2(p_lut, p_procBuf, Z); + } +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->cnProcPc); +#endif +#endif + } + + // If maximum number of iterations reached an PC still fails increase number of iterations + // Thus, i > numMaxIter indicates that PC has failed + +#ifdef NR_LDPC_ENABLE_PARITY_CHECK + if (pcRes != 0) + { + i++; + } +#endif + + // Assign results from processing buffer to output +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->llrRes2llrOut); +#endif + nrLDPC_llrRes2llrOut(p_lut, p_llrOut, p_procBuf, Z, BG); +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->llrRes2llrOut); +#endif + + // Hard-decision +#ifdef NR_LDPC_PROFILER_DETAIL + start_meas(&p_profiler->llr2bit); +#endif + if (outMode == nrLDPC_outMode_BIT) + { + nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR); + } + else if (outMode == nrLDPC_outMode_BITINT8) + { + nrLDPC_llr2bit(p_out, p_llrOut, numLLR); + } + +#ifdef NR_LDPC_PROFILER_DETAIL + stop_meas(&p_profiler->llr2bit); +#endif + + return i; +} + diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c index c32413aa86..b22a94afb5 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c @@ -110,14 +110,15 @@ #define NR_LDPC_ENABLE_PARITY_CHECK -#define NR_LDPC_PROFILER_DETAIL +//#define NR_LDPC_PROFILER_DETAIL #ifdef NR_LDPC_DEBUG_MODE #include "nrLDPC_tools/nrLDPC_debug.h" #endif static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDPC_procBuf* p_procBuf, uint32_t numLLR, t_nrLDPC_lut* p_lut, t_nrLDPC_dec_params* p_decParams, t_nrLDPC_time_stats* p_profiler); - +void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) { +} int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, t_nrLDPC_procBuf* p_procBuf, t_nrLDPC_time_stats* p_profiler) { uint32_t numLLR; @@ -126,7 +127,6 @@ int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_ t_nrLDPC_lut* p_lut = &lut; //printf("p_procBuf->cnProcBuf = %p\n", p_procBuf->cnProcBuf); - // Initialize decoder core(s) with correct LUTs numLLR = nrLDPC_init(p_decParams, p_lut); @@ -494,7 +494,11 @@ if (BG==1) // First iteration finished +<<<<<<< HEAD while ( (i < (numMaxIter-1)) && (pcRes != 0) ) +======= + while ( (i < numMaxIter) && (pcRes != 0) ) +>>>>>>> 74ce2cf4be34a6c62ea74116c4b1c45d3cbf1536 { // Increase iteration counter i++; diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c new file mode 100644 index 0000000000..58e6b507af --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c @@ -0,0 +1,436 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file nrLDPC_decoder_CL.c +* \brief ldpc decoder, openCL implementaion +* \author Francois TABURET +* \date 2021 +* \version 1.0 +* \note initial implem - translation of cuda version +*/ +/* uses HW component id for log messages ( --log_config.hw_log_level ) */ +#include +#include +#include +#include +#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" +#include "PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h" +#include "assertions.h" +#include "common/utils/LOG/log.h" + +#define MAX_ITERATION 2 +#define MC 1 + +#define MAX_OCLDEV 10 +#define MAX_OCLRUNTIME 5 + + +#define CLSETKERNELARG(A,B,C,D) \ +rt=clSetKernelArg(A,B,C,D) ;\ +AssertFatal(rt == CL_SUCCESS, "Error %d setting kernel argument index %d\n" , (int)rt, B); + +typedef struct{ + char x; + char y; + short value; +} h_element; +#include "../nrLDPC_decoder_LYC/bgs/BG1_compact_in_C.h" + +typedef struct{ + cl_uint max_CU; + cl_uint max_WID; + size_t *max_WIS; +} ocldev_t; + +typedef struct { + cl_kernel cnp_kernel_1st; + cl_kernel cnp_kernel; + cl_kernel vnp_kernel_normal; + cl_kernel pack_decoded_bit; +} oclkernels_t; + +typedef struct{ + cl_uint num_devices; + cl_device_id devices[MAX_OCLDEV]; + ocldev_t ocldev[MAX_OCLDEV]; + cl_context context; + cl_program program; + cl_mem dev_h_compact1; + cl_mem dev_h_compact2; + cl_mem dev_const_llr; + cl_mem dev_llr; + cl_mem dev_dt; + cl_mem dev_tmp; + oclkernels_t kernels[MAX_OCLDEV]; + cl_command_queue queue[MAX_OCLDEV]; +} oclruntime_t; + +typedef struct{ + oclruntime_t runtime[MAX_OCLRUNTIME]; +} ocl_t; + + + +ocl_t ocl; + + +void set_compact_BG(int Zc,short BG){ + cl_uint rt; + int row,col; + if(BG == 1){ + row = 46; + col = 68; + } + else{ + row = 42; + col = 52; + } + int compact_row = 30; + int compact_col = 19; + if(BG==2){compact_row = 10, compact_col = 23;} + int memorySize_h_compact1 = row * compact_col * sizeof(h_element); + int memorySize_h_compact2 = compact_row * col * sizeof(h_element); + int lift_index = 0; + short lift_set[][9] = { + {2,4,8,16,32,64,128,256}, + {3,6,12,24,48,96,192,384}, + {5,10,20,40,80,160,320}, + {7,14,28,56,112,224}, + {9,18,36,72,144,288}, + {11,22,44,88,176,352}, + {13,26,52,104,208}, + {15,30,60,120,240}, + {0} + }; + + for(int i = 0; lift_set[i][0] != 0; i++){ + for(int j = 0; lift_set[i][j] != 0; j++){ + if(Zc == lift_set[i][j]){ + lift_index = i; + break; + } + } + } + printf("\nZc = %d BG = %d\n",Zc,BG); + ocl.runtime[0].dev_h_compact1 = clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY|CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact1, NULL, (cl_int *)&rt); + AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact1 for platform %i \n" , (int)rt, 0); + ocl.runtime[0].dev_h_compact2 = clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY|CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact2, NULL, (cl_int *)&rt); + AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact2 for platform %i \n" , (int)rt, 0); + h_element *h1; + h_element *h2; + switch(lift_index){ + case 0: + h1 = host_h_compact1_I0; + h2 = host_h_compact2_I0; + break; + case 1: + h1 = host_h_compact1_I1; + h2 = host_h_compact2_I1; + break; + case 2: + h1 = host_h_compact1_I2; + h2 = host_h_compact2_I2; + break; + case 3: + h1 = host_h_compact1_I3; + h2 = host_h_compact2_I3; + break; + case 4: + h1 = host_h_compact1_I4; + h2 = host_h_compact2_I4; + break; + case 5: + h1 = host_h_compact1_I5; + h2 = host_h_compact2_I5; + break; + case 6: + h1 = host_h_compact1_I6; + h2 = host_h_compact2_I6; + break; + case 7: + h1 = host_h_compact1_I7; + h2 = host_h_compact2_I7; + break; + default: + AssertFatal(0, "Invalid lift_index value %i\n" , lift_index); + break; + } + rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_h_compact1, CL_TRUE, 0,memorySize_h_compact1, h1, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving h_compact1 memory to pltf %i dev %i\n" , (int)rt, 0,0); + rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_h_compact2, CL_TRUE, 0,memorySize_h_compact2, h2, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving h_compact2 memory to pltf %i dev %i\n" , (int)rt, 0,0); + // return 0; +} +void cl_error_callback(const char* errinfo, const void* private_info, size_t cb, void* user_data) { + oclruntime_t *runtime = (oclruntime_t *)user_data; + LOG_E(HW,"OpenCL accelerator error %s\n", errinfo ); +} + +char *clutil_getstrdev(int intdev) { + static char retstring[255]=""; + char *retptr=retstring; + retptr+=sprintf(retptr,"0x%08x: ",(uint32_t)intdev); + if (intdev & CL_DEVICE_TYPE_CPU) + retptr+=sprintf(retptr,"%s","cpu "); + if (intdev & CL_DEVICE_TYPE_GPU) + retptr+=sprintf(retptr,"%s","gpu "); + if (intdev & CL_DEVICE_TYPE_ACCELERATOR) + retptr+=sprintf(retptr,"%s","acc "); + return retstring; +} + +void get_CompilErr(cl_program program, int pltf) { + + // Determine the size of the log + size_t log_size; + for(int i=0; i0 , "clGetPlatformIDs: no cl compatible platform found\n"); + for (int i=0 ; i<(int)num_platforms_found ; i++) { + char stringval[255]; + rt = clGetPlatformInfo(platforms[i],CL_PLATFORM_PROFILE, sizeof(stringval),stringval,NULL); + AssertFatal(rt == CL_SUCCESS, "clGetPlatformInfo PROFILE error %d\n" , (int)rt); + LOG_I(HW,"Platform %i, OpenCL profile %s\n", i,stringval ); + rt = clGetPlatformInfo(platforms[i],CL_PLATFORM_VERSION, sizeof(stringval),stringval,NULL); + AssertFatal(rt == CL_SUCCESS, "clGetPlatformInfo VERSION error %d\n" , (int)rt); + LOG_I(HW,"Platform %i, OpenCL version %s\n", i,stringval ); + rt = clGetDeviceIDs(platforms[i],CL_DEVICE_TYPE_ALL, sizeof(ocl.runtime[i].devices)/sizeof(cl_device_id),ocl.runtime[i].devices,&(ocl.runtime[i].num_devices)); + AssertFatal(rt == CL_SUCCESS, "clGetDeviceIDs error %d\n" , (int)rt); + int devok=0; + for (int j=0; j0) { + ocl.runtime[i].context = clCreateContext(NULL, ocl.runtime[i].num_devices, ocl.runtime[i].devices, cl_error_callback, &(ocl.runtime[i]), (cl_int *)&rt); + AssertFatal(rt == CL_SUCCESS, "Error %d creating context for platform %i\n" , (int)rt, i); + for(int dev=0; dev0, "No openCL device available to accelerate ldpc\n"); + return 0; +} + + +void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) { + set_compact_BG(p_decParams->Z,p_decParams->BG); +// init_LLR_DMA(p_decParams, p_llr, p_out); +} + + +int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out,t_nrLDPC_procBuf* p_procBuf, t_nrLDPC_time_stats *time_decoder) +{ + uint16_t Zc = p_decParams->Z; + uint8_t BG = p_decParams->BG; +// uint8_t numMaxIter = p_decParams->numMaxIter; + int block_length = p_decParams->block_length; +// e_nrLDPC_outMode outMode = p_decParams->outMode; + uint8_t row,col; + if(BG == 1){ + row = 46; + col = 68; + } + else{ + row = 42; + col = 52; + } + +// alloc memory +// unsigned char *hard_decision = (unsigned char*)p_out; +// gpu + int memorySize_llr = col * Zc * sizeof(char) * MC; +// cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); +// cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); + int rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_const_llr, CL_TRUE, 0, + memorySize_llr, p_llr, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read only memory in pltf %i dev %i\n" , (int)rt, 0,0); + rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_llr, CL_TRUE, 0, + memorySize_llr, p_llr, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read-write memory in pltf %i dev %i\n" , (int)rt, 0,0); +// Define CUDA kernel dimension +// int blockSizeX = Zc; +// dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks +// dim3 dimBlockKernel1(blockSizeX, 1, 1); + +// dim3 dimGridKernel2(col, MC, 1); +// dim3 dimBlockKernel2(blockSizeX, 1, 1); +// cudaDeviceSynchronize(); + +// lauch kernel + size_t global_item_sizek0[2] = {row*Zc,MC}; // Process the entire lists + size_t global_item_sizek1[2] = {col*Zc,MC}; // Process the entire lists + size_t local_item_sizek[2] = {128,1}; // Divide work items into groups of 128 + + for(int ii = 0; ii < MAX_ITERATION; ii++){ + // first kernel + if(ii == 0){ +// ldpc_cnp_kernel_1st_iter +// <<>> +// ( BG, row, col, Zc); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact1)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 3, sizeof(int), (void *)&(BG)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 4, sizeof(int), (void *)&(row)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 5, sizeof(int), (void *)&(col)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel_1st, 6, sizeof(int), (void *)&(Zc)); + rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], ocl.runtime[0].kernels[0].cnp_kernel_1st, 2, NULL, + global_item_sizek0, local_item_sizek, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d enqueing cnp_kernel_1st \n" , (int)rt); + }else{ +// ldpc_cnp_kernel +// <<>> +// ( BG, row, col, Zc); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact1)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 3, sizeof(int), (void *)&(BG)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 4, sizeof(int), (void *)&(row)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 5, sizeof(int), (void *)&(col)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].cnp_kernel, 6, sizeof(int), (void *)&(Zc)); + rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], ocl.runtime[0].kernels[0].cnp_kernel, 2, NULL, + global_item_sizek0, local_item_sizek, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d enqueing cnp_kernel\n" , (int)rt); + } + // second kernel +// ldpc_vnp_kernel_normal +// <<>> +// // (dev_llr, dev_const_llr,BG, row, col, Zc); +// (BG, row, col, Zc); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_dt)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 2, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_const_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 3, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_h_compact2)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 4, sizeof(int), (void *)&(BG)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 5, sizeof(int), (void *)&(row)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 6, sizeof(int), (void *)&(col)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].vnp_kernel_normal, 7, sizeof(int), (void *)&(Zc)); + rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], ocl.runtime[0].kernels[0].vnp_kernel_normal, 2, NULL, + global_item_sizek1, local_item_sizek, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d enqueing vnp_kernel_normal \n" , (int)rt); + } + +// int pack = (block_length/128)+1; +// dim3 pack_block(pack, MC, 1); +// pack_decoded_bit<<>>( col, Zc); + CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 0, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_llr)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 1, sizeof(cl_mem), (void *)&(ocl.runtime[0].dev_tmp)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 2, sizeof(int), (void *)&(col)); + CLSETKERNELARG(ocl.runtime[0].kernels[0].pack_decoded_bit, 3, sizeof(int), (void *)&(Zc)); + + // Execute the OpenCL kernel on the list + size_t global_item_size[2] = {block_length,MC}; // Process the entire lists + size_t local_item_size[2] = {128,1}; // Divide work items into groups of 128 + rt = clEnqueueNDRangeKernel(ocl.runtime[0].queue[0], ocl.runtime[0].kernels[0].pack_decoded_bit, 2, NULL, + global_item_size, local_item_size, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d enqueing pack_decoded_bit \n" , (int)rt); +// cudaCheck( cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length/8)*sizeof(unsigned char)) ); +// cudaDeviceSynchronize(); + + rt = clEnqueueReadBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_tmp, CL_TRUE, 0, + (block_length/8)*sizeof(unsigned char) , p_llr, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to pltf %i dev %i\n" , (int)rt, 0,0); + return MAX_ITERATION; + +} diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.cl b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.cl new file mode 100644 index 0000000000..d5e2fa5695 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_kernels_CL.cl @@ -0,0 +1,302 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/CODING/nrLDPC_decoder_kernels_CL.cl +* \brief kernel functions for ldpc decoder accelerated via openCL +* \author Francois TABURET +* \date 2021 +* \version 1.0 +* \company Nokia BellLabs France +* \email: francois.taburet@nokia-bell-labs.com +* \note initial implem - translation of cuda version +* \warning +*/ +#define define MAX_ITERATION 2 +#define MC 1 + +#define INT32_MAX 2147483647 + +typedef struct{ + char x; + char y; + short value; +} h_element; + +//__global char dev_dt [46*68*384]; +//__local char *dev_t; +//__global char dev_llr[68*384]; +//__global unsigned char dev_tmp[68*384]; + + + + +//__constant h_element dev_h_compact1[46*19] = {}; // used in kernel 1 +//__constant h_element dev_h_compact2[68*30] = {}; // used in kernel 2 + +// __device__ __constantant__ h_element dev_h_compact1[46*19]; // used in kernel 1 +// __device__ __constantant__ h_element dev_h_compact2[68*30]; // used in kernel 2 + +// row and col element count +__constant char h_ele_row_bg1_count[46] = { + 19, 19, 19, 19, 3, 8, 9, 7, 10, 9, + 7, 8, 7, 6, 7, 7, 6, 6, 6, 6, + 6, 6, 5, 5, 6, 5, 5, 4, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, + 4, 5, 4, 5, 5, 4}; +__constant char h_ele_col_bg1_count[68] = { + 30, 28, 7, 11, 9, 4, 8, 12, 8, 7, + 12, 10, 12, 11, 10, 7, 10, 10, 13, 7, + 8, 11, 12, 5, 6, 6, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1}; +__constant char h_ele_row_bg2_count[42] = { + 8, 10, 8, 10, 4, 6, 6, 6, 4, 5, + 5, 5, 4, 5, 5, 4, 5, 5, 4, 4, + 4, 4, 3, 4, 4, 3, 5, 3, 4, 3, + 5, 3, 4, 4, 4, 4, 4, 3, 4, 4, + 4, 4}; +__constant char h_ele_col_bg2_count[52] = { + 22, 23, 10, 5, 5, 14, 7, 13, 6, 8, + 9, 16, 9, 12, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1}; + + + +// Kernel 1 +__kernel void ldpc_cnp_kernel_1st_iter( __global char * dev_llr, __global char * dev_dt, __local h_element *dev_h_compact1, int BG, int row, int col, int Zc) +{ +// int iMCW = blockIdx.y; // codeword id +// int iBlkRow = blockIdx.x; // block row in h_base +// int iSubRow = threadIdx.x; // row index in sub_block of h_base +// if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp %d\n", threadIdx.x); + int iMCW = get_group_id(1); // codeword id + int iBlkRow = get_group_id(0); // block row in h_base + int iBlkCol; // block col in h_base + int iSubRow = get_local_id(0);; // row index in sub_block of h_base + int iCol; // overall col index in h_base + int offsetR; + int shift_t; + +// For 2-min algorithm. + int Q_sign = 0; + int sq; + int Q, Q_abs; + int R_temp; + + int sign = 1; + int rmin1 = INT32_MAX; + int rmin2 = INT32_MAX; + char idx_min = 0; + + h_element h_element_t; + int s = (BG==1)? h_ele_row_bg1_count[iBlkRow]:h_ele_row_bg2_count[iBlkRow]; + offsetR = (iMCW * row*col*Zc) + iBlkRow * Zc + iSubRow; // row*col*Zc = size of dev_dt +// if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR); +// The 1st recursion + for(int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row + { + h_element_t = dev_h_compact1[i*row+iBlkRow]; // compact_col == row + + iBlkCol = h_element_t.y; + shift_t = h_element_t.value; + + shift_t = (iSubRow + shift_t) % Zc; + iCol = (iMCW * col*Zc) + iBlkCol * Zc + shift_t; // col*Zc = size of llr + Q = dev_llr[iCol]; + Q_abs = (Q>0)? Q : -Q; + sq = Q < 0; +// if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); + // quick version + sign = sign * (1 - sq * 2); + Q_sign |= sq << i; + + if (Q_abs < rmin1){ + rmin2 = rmin1; + rmin1 = Q_abs; + idx_min = i; + } else if (Q_abs < rmin2){ + rmin2 = Q_abs; + } + } + +// if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); + +// The 2nd recursion + for(int i = 0; i < s; i++){ + // v0: Best performance so far. 0.75f is the value of alpha. + sq = 1 - 2 * ((Q_sign >> i) & 0x01); + R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); + // write results to global memory + h_element_t = dev_h_compact1[i*row+iBlkRow]; + int addr_temp = offsetR + h_element_t.y * row * Zc; + dev_dt[addr_temp] = R_temp; +// if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); + } +} + +// Kernel_1 +__kernel void ldpc_cnp_kernel( __global char * dev_llr, __global char * dev_dt, __local h_element *dev_h_compact1, int BG, int row, int col, int Zc) +{ +// if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp\n"); +// int iMCW = blockIdx.y; +// int iBlkRow = blockIdx.x; // block row in h_base // block col in h_base +// int iSubRow = threadIdx.x; // row index in sub_block of h_base + int iMCW = get_group_id(1); + int iBlkRow = get_group_id(0); // block row in h_base + int iBlkCol; // block col in h_base + int iSubRow = get_local_id(0);; // row index in sub_block of h_base + int iCol; // overall col index in h_base + int offsetR; + int shift_t; + +// For 2-min algorithm. + int Q_sign = 0; + int sq; + int Q, Q_abs; + int R_temp; + + int sign = 1; + int rmin1 = INT32_MAX; + int rmin2 = INT32_MAX; + char idx_min = 0; + + h_element h_element_t; + int s = (BG==1)? h_ele_row_bg1_count[iBlkRow]: h_ele_row_bg2_count[iBlkRow]; + offsetR = (iMCW *row*col*Zc) + iBlkRow * Zc + iSubRow; // row * col * Zc = size of dev_dt +// if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR); +// The 1st recursion + for(int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row + { + h_element_t = dev_h_compact1[i*row+iBlkRow]; + + iBlkCol = h_element_t.y; + shift_t = h_element_t.value; + shift_t = (iSubRow + shift_t) % Zc; + iCol = iBlkCol * Zc + shift_t; + + R_temp = dev_dt[offsetR + iBlkCol * row * Zc]; + + Q = dev_llr[iMCW * (col*Zc) + iCol] - R_temp; + Q_abs = (Q>0)? Q : -Q; +// if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); + sq = Q < 0; + sign = sign * (1 - sq * 2); + Q_sign |= sq << i; + + if (Q_abs < rmin1){ + rmin2 = rmin1; + rmin1 = Q_abs; + idx_min = i; + } else if (Q_abs < rmin2){ + rmin2 = Q_abs; + } + + } + +// if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); + +// The 2nd recursion + for(int i = 0; i < s; i ++){ + sq = 1 - 2 * ((Q_sign >> i) & 0x01); + R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); + + + // write results to global memory + h_element_t = dev_h_compact1[i*row+iBlkRow]; + int addr_temp = h_element_t.y * row * Zc + offsetR; + dev_dt[addr_temp] = R_temp; +// if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); + } +} + +// Kernel 2: VNP processing +__kernel void +ldpc_vnp_kernel_normal(__global char * dev_llr, __global char * dev_dt, __global char * dev_const_llr, __local h_element *dev_h_compact2, int BG, int row, int col, int Zc) +{ +// int iMCW = blockIdx.y; +// int iBlkCol = blockIdx.x; +// int iSubCol = threadIdx.x; + int iMCW = get_group_id(1); + int iBlkCol = get_group_id(0); + int iBlkRow; + int iSubCol = get_local_id(0); + int iRow; + int iCol; + + int shift_t, sf; + int APP; + + h_element h_element_t; + + // update all the llr values + iCol = iBlkCol * Zc + iSubCol; + APP = dev_const_llr[iMCW *col*Zc + iCol]; + int offsetDt = iMCW *row*col*Zc + iBlkCol * row * Zc; + int s = (BG==1)? h_ele_col_bg1_count[iBlkCol]:h_ele_col_bg2_count[iBlkCol]; + + for(int i = 0; i < s; i++) + { + h_element_t = dev_h_compact2[i*col+iBlkCol]; + + shift_t = h_element_t.value%Zc; + iBlkRow = h_element_t.x; + + sf = iSubCol - shift_t; + sf = (sf + Zc) % Zc; + + iRow = iBlkRow * Zc + sf; + APP = APP + dev_dt[offsetDt + iRow]; + } + if(APP > SCHAR_MAX) APP = SCHAR_MAX; + if(APP < SCHAR_MIN) APP = SCHAR_MIN; + // write back to device global memory + dev_llr[iMCW *col*Zc + iCol] = APP; +} + + +__kernel void pack_decoded_bit(__global unsigned char * dev_llr, __global unsigned char * dev_tmp, int col, int Zc) +{ +// int iMCW = blockIdx.y; +// int btid = threadIdx.x; + unsigned char tmp[128]; + int iMCW = get_group_id(1); + int btid = get_local_id(0); + int tid = iMCW * col*Zc + get_group_id(0)*128 + btid; + tmp[btid] = 0; + + if(dev_llr[tid] < 0){ + tmp[btid] = 1 << (7-(btid&7)); + } +// __syncthreads(); + + if(btid < 16){ + dev_tmp[iMCW * col*Zc + get_group_id(0)*16+btid] = 0; + for(int i = 0; i < 8; i++){ + dev_tmp[iMCW * col*Zc + get_group_id(0)*16+btid] += tmp[btid*8+i]; + } + } +} + diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h index acd40d5d2d..5678a7b3b7 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h @@ -34,7 +34,6 @@ #include #include "nrLDPC_types.h" -#ifndef malloc32_clear /** \brief Allocates 32 byte aligned memory and initializes to zero \param size Input size in bytes @@ -46,7 +45,6 @@ static inline void* malloc32_clear(size_t size) memset(ptr, 0, size); return ptr; } -#endif /** \brief Allocates and initializes the internal decoder processing buffers diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h_native_memcpy b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h_native_memcpy new file mode 100644 index 0000000000..131274dbc5 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h_native_memcpy @@ -0,0 +1,1205 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*!\file nrLDPC_mPass.h + * \brief Defines the functions for message passing + * \author Sebastian Wagner (TCL Communications) Email: + * \date 30-09-2019 + * \version 2.0 + * \note + * \warning + */ + +#ifndef __NR_LDPC_MPASS__H__ +#define __NR_LDPC_MPASS__H__ + +#include +#include "nrLDPCdecoder_defs.h" +//#include +/** + \brief Circular memcpy + |<- rem->|<- circular shift ->| + (src) str2 = |--------xxxxxxxxxxxxxxxxxxxxx| + \_______________ + \ + (dst) str1 = |xxxxxxxxxxxxxxxxxxxxx---------| + \param str1 Pointer to the start of the destination buffer + \param str2 Pointer to the source buffer + \param Z Lifting size + \param cshift Circular shift +*/ +static inline void *nrLDPC_inv_circ_memcpy(int8_t *str1, const int8_t *str2, uint16_t Z, uint16_t cshift) +{ + uint16_t rem = Z - cshift; + memcpy(str1+cshift, str2 , rem); + memcpy(str1 , str2+rem, cshift); + + return(str1); +} + +/** + \brief Inverse circular memcpy + |<- circular shift ->|<- rem->| + (src) str2 = |xxxxxxxxxxxxxxxxxxxx\--------| + \ + (dst) str1 = |--------xxxxxxxxxxxxxxxxxxxxx| + \param str1 Pointer to the start of the destination buffer + \param str2 Pointer to the source buffer + \param Z Lifting size + \param cshift Circular shift +*/ +static inline void *nrLDPC_circ_memcpy(int8_t *str1, const int8_t *str2, uint16_t Z, uint16_t cshift) +{ + uint16_t rem = Z - cshift; + memcpy(str1 , str2+cshift, rem); + memcpy(str1+rem , str2 , cshift); + + return(str1); +} + +/** + \brief Copies the input LLRs to their corresponding place in the LLR processing buffer. + Example: BG2 + | 0| 0| LLRs --> | + BN Groups |22|23|10| 5| 5|14| 7|13| 6| 8| 9|16| 9|12|1|1|...|1| + ^---------------------------------------/---- / + _________________________/ | / + / ____________________________|___/ + / / \ + LLR Proc Buffer (BNG) | 1| 5| 6| 7| 8| 9|10|12|13|14|16|22|23| + Number BN in BNG(R15) |38| 2| 1| 1| 1| 2| 1| 1| 1| 1| 1| 1| 1| + Idx: 0 ^ ^ ^ + 38*384=14592 _____| ... | | + 50*384=19200 ----------------------------------- | + 51*384=19584 -------------------------------------- + + \param p_lut Pointer to decoder LUTs + \param llr Pointer to input LLRs + \param p_procBuf Pointer the processing buffers + \param Z Lifting size + \param BG Base graph +*/ +static inline void nrLDPC_llr2llrProcBuf(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrLDPC_procBuf* p_procBuf, uint16_t Z, uint8_t BG) +{ + uint32_t i; + const uint8_t numBn2CnG1 = p_lut->numBnInBnGroups[0]; + uint32_t startColParity = (BG ==1 ) ? (NR_LDPC_START_COL_PARITY_BG1) : (NR_LDPC_START_COL_PARITY_BG2); + + uint32_t colG1 = startColParity*Z; + + const uint16_t* lut_llr2llrProcBufAddr = p_lut->llr2llrProcBufAddr; + const uint8_t* lut_llr2llrProcBufBnPos = p_lut->llr2llrProcBufBnPos; + + uint32_t idxBn; + int8_t* llrProcBuf = p_procBuf->llrProcBuf; + + // Copy LLRs connected to 1 CN + if (numBn2CnG1 > 0) + { + memcpy(&llrProcBuf[0], &llr[colG1], numBn2CnG1*Z); + } + + // First 2 columns might be set to zero directly if it's true they always belong to the groups with highest number of connected CNs... + for (i=0; icircShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + + const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->posBnInCnProcBuf[0]; + const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->posBnInCnProcBuf[1]; + const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->posBnInCnProcBuf[2]; + const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->posBnInCnProcBuf[3]; + const uint8_t (*lut_posBnInCnProcBuf_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->posBnInCnProcBuf[4]; + const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->posBnInCnProcBuf[5]; + const uint8_t (*lut_posBnInCnProcBuf_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->posBnInCnProcBuf[6]; + const uint8_t (*lut_posBnInCnProcBuf_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->posBnInCnProcBuf[7]; + const uint8_t (*lut_posBnInCnProcBuf_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->posBnInCnProcBuf[8]; + + const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + uint32_t i; + uint32_t j; + + uint32_t idxBn = 0; + int8_t* p_cnProcBuf; + uint32_t bitOffsetInGroup; + + // ===================================================================== + // CN group with 3 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX; + +// #pragma omp simd +// #pragma omp parallel for schedule(dynamic) + + for (j=0; j<3; j++) + { + p_cnProcBuf = &cnProcBuf[lut_startAddrCnGroups[0] + j*bitOffsetInGroup]; + + idxBn = lut_posBnInCnProcBuf_CNG3[j][0]*Z; + + nrLDPC_circ_memcpy(p_cnProcBuf, &llr[idxBn], Z, lut_circShift_CNG3[j][0]); + } + + // ===================================================================== + // CN group with 4 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX; + + for (j=0; j<4; j++) + { + p_cnProcBuf = &cnProcBuf[lut_startAddrCnGroups[1] + j*bitOffsetInGroup]; + + for (i=0; i | + BN Groups |22|23|10| 5| 5|14| 7|13| 6| 8| 9|16| 9|12|1|1|...|1| + + + CN Processing Buffer (CNGs) | 3| 4| 5| 6| 8|10| + Number of CN per CNG (R15) | 6|20| 9| 3| 2| 2| + 0 ^ ^\ \ + 3*6*384=6912 _________| || \_____________ + (3*6+4*20+5*9)*384=54912____|| \ + Bit | 1| 2| 3| 4| 5| 6| + 3*Z CNs>| |< + ^ + 54912 + 3*384______| + + \param p_lut Pointer to decoder LUTs + \param llr Pointer to input LLRs + \param p_procBuf Pointer to the processing buffers + \param Z Lifting size +*/ +static inline void nrLDPC_llr2CnProcBuf_BG2(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrLDPC_procBuf* p_procBuf, uint16_t Z) +{ + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + + const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->posBnInCnProcBuf[0]; + const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->posBnInCnProcBuf[1]; + const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->posBnInCnProcBuf[2]; + const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->posBnInCnProcBuf[3]; + const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->posBnInCnProcBuf[4]; + const uint8_t (*lut_posBnInCnProcBuf_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->posBnInCnProcBuf[5]; + + const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + uint32_t i; + uint32_t j; + + uint32_t idxBn = 0; + int8_t* p_cnProcBuf; + uint32_t bitOffsetInGroup; + + // ===================================================================== + // CN group with 3 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG2_R15[0]*NR_LDPC_ZMAX; + + for (j=0; j<3; j++) + { + p_cnProcBuf = &cnProcBuf[lut_startAddrCnGroups[0] + j*bitOffsetInGroup]; + + for (i=0; inumCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + + const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + + int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; + int8_t* bnProcBuf = p_procBuf->bnProcBuf; + + int8_t* p_cnProcBufRes; + uint32_t bitOffsetInGroup; + uint32_t i; + uint32_t j; + uint32_t idxBn = 0; + + // ===================================================================== + // CN group with 3 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG2_R15[0]*NR_LDPC_ZMAX; + + for (j=0; j<3; j++) + { + p_cnProcBufRes = &cnProcBufRes[lut_startAddrCnGroups[0] + j*bitOffsetInGroup]; + for (i=0; inumCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; + const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; + + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; + const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; + + int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; + int8_t* bnProcBuf = p_procBuf->bnProcBuf; + + int8_t* p_cnProcBufRes; + uint32_t bitOffsetInGroup; + uint32_t i; + uint32_t j; + uint32_t idxBn = 0; + + // ===================================================================== + // CN group with 3 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX; + + for (j=0; j<3; j++) + { + p_cnProcBufRes = &cnProcBufRes[lut_startAddrCnGroups[0] + j*bitOffsetInGroup]; + nrLDPC_inv_circ_memcpy(&bnProcBuf[lut_startAddrBnProcBuf_CNG3[j][0]],p_cnProcBufRes,Z,lut_circShift_CNG3[j][0]); + } + + // ===================================================================== + // CN group with 4 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX; + + for (j=0; j<4; j++) + { + p_cnProcBufRes = &cnProcBufRes[lut_startAddrCnGroups[1] + j*bitOffsetInGroup]; + + for (i=0; inumCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + + const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + int8_t* bnProcBufRes = p_procBuf->bnProcBufRes; + + int8_t* p_cnProcBuf; + uint32_t bitOffsetInGroup; + uint32_t i; + uint32_t j; + uint32_t idxBn = 0; + + // For CN groups 3 to 6 no need to send the last BN back since it's single edge + // and BN processing does not change the value already in the CN proc buf + + // ===================================================================== + // CN group with 3 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG2_R15[0]*NR_LDPC_ZMAX; + + for (j=0; j<2; j++) + { + p_cnProcBuf = &cnProcBuf[lut_startAddrCnGroups[0] + j*bitOffsetInGroup]; + for (i=0; inumCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; + + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; + const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; + + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; + const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; + + int8_t* cnProcBuf = p_procBuf->cnProcBuf; + int8_t* bnProcBufRes = p_procBuf->bnProcBufRes; + + int8_t* p_cnProcBuf; + uint32_t bitOffsetInGroup; + uint32_t i; + uint32_t j; + uint32_t idxBn = 0; + + // For CN groups 3 to 19 no need to send the last BN back since it's single edge + // and BN processing does not change the value already in the CN proc buf + + // ===================================================================== + // CN group with 3 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX; + // #pragma omp simd + for (j=0;j<2; j++) + { + p_cnProcBuf = &cnProcBuf[lut_startAddrCnGroups[0] + j*bitOffsetInGroup]; + nrLDPC_circ_memcpy(p_cnProcBuf, &bnProcBufRes[lut_startAddrBnProcBuf_CNG3[j][0]], Z, lut_circShift_CNG3[j][0]); + } + + // ===================================================================== + // CN group with 4 BNs + + bitOffsetInGroup = lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX; + // #pragma omp simd + for (j=0; j<3; j++) + { + p_cnProcBuf = &cnProcBuf[lut_startAddrCnGroups[1] + j*bitOffsetInGroup]; + // #pragma omp simd + for (i=0; inumBnInBnGroups[0]; + uint32_t startColParity = (BG ==1 ) ? (NR_LDPC_START_COL_PARITY_BG1) : (NR_LDPC_START_COL_PARITY_BG2); + + uint32_t colG1 = startColParity*Z; + + const uint16_t* lut_llr2llrProcBufAddr = p_lut->llr2llrProcBufAddr; + const uint8_t* lut_llr2llrProcBufBnPos = p_lut->llr2llrProcBufBnPos; + + int8_t* llrRes = p_procBuf->llrRes; + int8_t* p_llrOut = &llrOut[0]; + uint32_t idxBn; + + // Copy LLRs connected to 1 CN + if (numBn2CnG1 > 0) + { + memcpy(&llrOut[colG1], llrRes, numBn2CnG1*Z); + } + + for (i=0; i -#include -static inline void nrLDPC_cnProc_BG1_R23_AVX2(int8_t* cnProcBuf, int8_t* cnProcBufRes, uint16_t Z) { -//Process group with 3 BNs - __m256i ymm0, min, sgn,ones,maxLLR; - ones = _mm256_set1_epi8((char)1); - maxLLR = _mm256_set1_epi8((char)127); - uint32_t M; - M = (1*Z + 31)>>5; - for (int i=0;i>5; - for (int i=0;i>5; - for (int i=0;i>5; - for (int i=0;i>5; - for (int i=0;i>5; - for (int i=0;i #include #include #include #include #include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" #include "PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h" - +#include "assertions.h" #include "bgs/BG1_I0" #include "bgs/BG1_I1" #include "bgs/BG1_I2" @@ -462,10 +462,11 @@ void read_BG(int BG, int *h, int row, int col) } extern "C" -void init_LLR_DMA_for_CUDA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, int block_length){ +void init_LLR_DMA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out){ uint16_t Zc = p_decParams->Z; uint8_t BG = p_decParams->BG; + int block_length = p_decParams->block_length; uint8_t row,col; if(BG == 1){ row = 46; @@ -483,14 +484,60 @@ void init_LLR_DMA_for_CUDA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8 } +using namespace std ; + +/* from here: entry points in decoder shared lib */ extern "C" -int32_t nrLDPC_decoder_LYC(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, int block_length, time_stats_t *time_decoder) +int ldpc_autoinit(void) { // called by the library loader +/*int devices = 0; + + cudaError_t err = cudaGetDeviceCount(&devices); + AssertFatal(devices>0,"\nNo cuda GPU found\n\n"); + + const int kb = 1024; + const int mb = kb * kb; + wcout << "NBody.GPU" << endl << "=========" << endl << endl; + + wcout << "CUDA version: v" << CUDART_VERSION << endl; + + + wcout << "CUDA Devices: " << endl << endl; + + for(int i = 0; i < devices; ++i) + { + cudaDeviceProp props; + cudaGetDeviceProperties(&props, i); + wcout << i << ": " << props.name << ": " << props.major << "." << props.minor << endl; + wcout << " Global memory: " << props.totalGlobalMem / mb << "mb" << endl; + wcout << " Shared memory: " << props.sharedMemPerBlock / kb << "kb" << endl; + wcout << " Constant memory: " << props.totalConstMem / kb << "kb" << endl; + wcout << " Block registers: " << props.regsPerBlock << endl << endl; + + wcout << " Warp size: " << props.warpSize << endl; + wcout << " Threads per block: " << props.maxThreadsPerBlock << endl; + wcout << " Max block dimensions: [ " << props.maxThreadsDim[0] << ", " << props.maxThreadsDim[1] << ", " << props.maxThreadsDim[2] << " ]" << endl; + wcout << " Max grid dimensions: [ " << props.maxGridSize[0] << ", " << props.maxGridSize[1] << ", " << props.maxGridSize[2] << " ]" << endl; + wcout << endl; + } +*/ + warmup_for_GPU(); + return 0; +} + +extern "C" +void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) { + set_compact_BG(p_decParams->Z,p_decParams->BG); + init_LLR_DMA(p_decParams, p_llr, p_out); +} + + +extern "C" +int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out,t_nrLDPC_procBuf* p_procBuf, t_nrLDPC_time_stats *time_decoder) { - - uint16_t Zc = p_decParams->Z; uint8_t BG = p_decParams->BG; uint8_t numMaxIter = p_decParams->numMaxIter; + int block_length = p_decParams->block_length; e_nrLDPC_outMode outMode = p_decParams->outMode; cudaError_t cudaStatus; uint8_t row,col; diff --git a/openair1/PHY/CODING/nrLDPC_defs.h b/openair1/PHY/CODING/nrLDPC_defs.h index b96067f4b6..0d7ff9ef9f 100644 --- a/openair1/PHY/CODING/nrLDPC_defs.h +++ b/openair1/PHY/CODING/nrLDPC_defs.h @@ -22,6 +22,7 @@ // encoder interface #ifndef __NRLDPC_DEFS__H__ #define __NRLDPC_DEFS__H__ +#include #include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" /** \brief LDPC encoder @@ -36,16 +37,31 @@ \param 9-12 time_stats_t *tinput,*tprep, *tparity,*toutput */ typedef struct { - int n_segments; // optim8seg - unsigned int macro_num; // optim8segmulti - unsigned char gen_code; //orig - time_stats_t *tinput; - time_stats_t *tprep; - time_stats_t *tparity; - time_stats_t *toutput; -}encoder_implemparams_t; + unsigned int n_segments; // optim8seg + unsigned int macro_num; // optim8segmulti + unsigned char gen_code; //orig + time_stats_t *tinput; + time_stats_t *tprep; + time_stats_t *tparity; + time_stats_t *toutput; + int Kr; + uint32_t Kb; + uint32_t *Zc; + void *harq; + /// Encoder BG + uint8_t BG; + /// Interleaver outputs + unsigned char *output; + /// Number of bits in "small" code segments + uint32_t K; + /// Number of "Filler" bits + uint32_t F; + /// LDPC-code outputs + uint8_t *d[MAX_NUM_NR_DLSCH_SEGMENTS]; +} encoder_implemparams_t; #define INIT0_LDPCIMPLEMPARAMS {0,0,0,NULL,NULL,NULL,NULL} -typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,short, short, encoder_implemparams_t*); +typedef void(*nrLDPC_initcallfunc_t)(t_nrLDPC_dec_params *p_decParams, int8_t *p_llr, int8_t *p_out); +typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,short, short, encoder_implemparams_t *); //============================================================================================================================ // decoder interface /** @@ -55,5 +71,5 @@ typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,sho \param p_llrOut Output vector \param p_profiler LDPC profiler statistics */ -typedef int32_t(*nrLDPC_decoderfunc_t)(t_nrLDPC_dec_params* , int8_t*, int8_t* , t_nrLDPC_procBuf* , t_nrLDPC_time_stats* ); -#endif \ No newline at end of file +typedef int32_t(*nrLDPC_decoderfunc_t)(t_nrLDPC_dec_params *, int8_t *, int8_t *, t_nrLDPC_procBuf *, t_nrLDPC_time_stats * ); +#endif diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encode_parity_check.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encode_parity_check.c index 738fd49b7d..69d2ac4972 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encode_parity_check.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encode_parity_check.c @@ -38,8 +38,6 @@ #include "common/utils/LOG/log.h" -//#define DEBUG_LDPC - #include "ldpc384_byte.c" #include "ldpc352_byte.c" #include "ldpc320_byte.c" @@ -73,9 +71,18 @@ -static inline void encode_parity_check_part_optim(uint8_t *c,uint8_t *d, short BG,short Zc,short Kb) +static void encode_parity_check_part_optim(uint8_t *cc,uint8_t *d, short BG,short Zc,short Kb, int simd_size, int ncols) { - + unsigned char c[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c + + for (int i1=0; i1 < ncols; i1++) { + memcpy(&c[2*i1*Zc], &cc[i1*Zc], Zc*sizeof(unsigned char)); + memcpy(&c[(2*i1+1)*Zc], &cc[i1*Zc], Zc*sizeof(unsigned char)); + } + for (int i1=1;i1tinput != NULL) start_meas(impp->tinput); - for (i=0; i>(i&7)))>>(7-(i&7)); //printf("c(%d,%d)=%d\n",j,i,temp); } @@ -108,24 +103,10 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) { // extend matrix if(impp->tprep != NULL) start_meas(impp->tprep); - for (i1=0; i1 < ncols; i1++) - { - memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - } - for (i1=1;i1tprep != NULL) stop_meas(impp->tprep); //parity check part if(impp->tparity != NULL) start_meas(impp->tparity); - encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb); + encode_parity_check_part_optim(c, d, BG, Zc, Kb,simd_size, ncols); if(impp->tparity != NULL) stop_meas(impp->tparity); } else { diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8seg.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8seg.c index a974e86e27..6fa9c5ff53 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8seg.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8seg.c @@ -38,7 +38,6 @@ #include "common/utils/LOG/log.h" #include "PHY/TOOLS/time_meas.h" #include "openair1/PHY/CODING/nrLDPC_defs.h" -//#define DEBUG_LDPC #include "ldpc_encode_parity_check.c" #include "ldpc_generate_coefficient.c" @@ -102,7 +101,6 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size - unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c // calculate number of punctured bits no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; @@ -151,24 +149,10 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) { // extend matrix if(impp->tprep != NULL) start_meas(impp->tprep); - for (i1=0; i1 < ncols; i1++) - { - memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - } - for (i1=1;i1tprep != NULL) stop_meas(impp->tprep); //parity check part if(impp->tparity != NULL) start_meas(impp->tparity); - encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb); + encode_parity_check_part_optim(c, d, BG, Zc, Kb, simd_size, ncols); if(impp->tparity != NULL) stop_meas(impp->tparity); } else { diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c index b21f875b32..15d4481eb6 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c @@ -39,17 +39,17 @@ #include "PHY/TOOLS/time_meas.h" #include "openair1/PHY/CODING/nrLDPC_defs.h" -//#define DEBUG_LDPC - #include "ldpc_encode_parity_check.c" #include "ldpc_generate_coefficient.c" -int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp) +int nrLDPC_encod(unsigned char **input,unsigned char **output,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp) { + //set_log(PHY, 4); + - short nrows=0,ncols=0; - int i,i1,j,rate=3; + int nrows=0,ncols=0; + int rate=3; int no_punctured_columns,removed_bit; //Table of possible lifting sizes char temp; @@ -95,8 +95,8 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc } #ifdef DEBUG_LDPC - LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,n_segments); - LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",test_input[0][0],test_input[0][1],test_input[0][2],test_input[0][3]); + LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,impp->n_segments); + LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",input[0][0],input[0][1],input[0][2],input[0][3]); #endif AssertFatal(Zc>0,"no valid Zc found for block length %d\n",block_length); @@ -104,10 +104,8 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc if ((Zc&31) > 0) simd_size = 16; else simd_size = 32; - unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size - unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size - - unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c + unsigned char cc[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size + unsigned char dd[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size // calculate number of punctured bits no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; @@ -115,8 +113,8 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc //printf("%d\n",no_punctured_columns); //printf("%d\n",removed_bit); // unpack input - memset(c,0,sizeof(unsigned char) * ncols * Zc); - memset(d,0,sizeof(unsigned char) * nrows * Zc); + memset(cc,0,sizeof(unsigned char) * ncols * Zc); + memset(dd,0,sizeof(unsigned char) * nrows * Zc); if(impp->tinput != NULL) start_meas(impp->tinput); #if 0 @@ -124,29 +122,29 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc //for (j=0; j>(i&7); + temp = (input[j][i/8]&(1<<(i&7)))>>(i&7); //printf("c(%d,%d)=%d\n",j,i,temp); c[i] |= (temp << (j-macro_segment)); } } #else #ifdef __AVX2__ - for (i=0; i>5; i++) { - c256 = _mm256_and_si256(_mm256_cmpeq_epi8(_mm256_andnot_si256(_mm256_shuffle_epi8(_mm256_set1_epi32(((uint32_t*)test_input[macro_segment])[i]), shufmask),andmask),zero256),masks[0]); + for (int i=0; i>5; i++) { + c256 = _mm256_and_si256(_mm256_cmpeq_epi8(_mm256_andnot_si256(_mm256_shuffle_epi8(_mm256_set1_epi32(((uint32_t*)input[macro_segment])[i]), shufmask),andmask),zero256),masks[0]); //for (j=1; j>5)<<5;i>5)<<5;i>(i&7)))>>(7-(i&7)); + temp = (input[j][i/8]&(128>>(i&7)))>>(7-(i&7)); //printf("c(%d,%d)=%d\n",j,i,temp); - c[i] |= (temp << (j-macro_segment)); + cc[i] |= (temp << (j-macro_segment)); } } #else @@ -159,28 +157,14 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) { // extend matrix if(impp->tprep != NULL) start_meas(impp->tprep); - for (i1=0; i1 < ncols; i1++) - { - memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - } - for (i1=1;i1tprep != NULL) stop_meas(impp->tprep); //parity check part if(impp->tparity != NULL) start_meas(impp->tparity); - encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb); + encode_parity_check_part_optim(cc, dd, BG, Zc, Kb, simd_size, ncols); if(impp->tparity != NULL) stop_meas(impp->tparity); } else { - if (encode_parity_check_part_orig(c, d, BG, Zc, Kb, block_length)!=0) { + if (encode_parity_check_part_orig(cc, dd, BG, Zc, Kb, block_length)!=0) { printf("Problem with encoder\n"); return(-1); } @@ -188,8 +172,8 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc if(impp->toutput != NULL) start_meas(impp->toutput); // information part and puncture columns /* - memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char)); - memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char)); + memcpy(&output[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char)); + memcpy(&output[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char)); */ #ifdef __AVX2__ if ((((2*Zc)&31) == 0) && (((block_length-(2*Zc))&31) == 0)) { @@ -197,34 +181,34 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc //AssertFatal(((block_length-(2*Zc))&31) == 0,"block_length-(2*Zc) needs to be a multiple of 32 for now\n"); uint32_t l1 = (block_length-(2*Zc))>>5; uint32_t l2 = ((nrows-no_punctured_columns) * Zc-removed_bit)>>5; - __m256i *c256p = (__m256i *)&c[2*Zc]; - __m256i *d256p = (__m256i *)&d[0]; + __m256i *c256p = (__m256i *)&cc[2*Zc]; + __m256i *d256p = (__m256i *)&dd[0]; // if (((block_length-(2*Zc))&31)>0) l1++; - for (i=0;i0) l2++; - for (i1=0;i1>(j-macro_segment))&1; - for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++) + for (int j=macro_segment; j < macro_segment_end; j++) + output[j][i] = (cc[2*Zc+i]>>(j-macro_segment))&1; + for (int i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++) //for (j=0; j>(j-macro_segment))&1; + for (int j=macro_segment; j < macro_segment_end; j++) + output[j][block_length-2*Zc+i] = (dd[i]>>(j-macro_segment))&1; } #else diff --git a/openair1/PHY/CODING/nrLDPC_extern.h b/openair1/PHY/CODING/nrLDPC_extern.h index c0bfa0fdd8..b75b38fc76 100644 --- a/openair1/PHY/CODING/nrLDPC_extern.h +++ b/openair1/PHY/CODING/nrLDPC_extern.h @@ -23,13 +23,16 @@ #ifdef LDPC_LOADER nrLDPC_decoderfunc_t nrLDPC_decoder; nrLDPC_encoderfunc_t nrLDPC_encoder; +nrLDPC_initcallfunc_t nrLDPC_initcall; #else /* functions to load the LDPC shared lib, implemented in openair1/PHY/CODING/nrLDPC_load.c */ -extern int load_nrLDPClib(void) ; +extern int load_nrLDPClib(char *version) ; extern int load_nrLDPClib_ref(char *libversion, nrLDPC_encoderfunc_t * nrLDPC_encoder_ptr); // for ldpctest /* ldpc coder/decoder functions, as loaded by load_nrLDPClib(). */ +extern nrLDPC_initcallfunc_t nrLDPC_initcall; + extern nrLDPC_decoderfunc_t nrLDPC_decoder; extern nrLDPC_encoderfunc_t nrLDPC_encoder; // inline functions: #include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_init_mem.h" -#endif \ No newline at end of file +#endif diff --git a/openair1/PHY/CODING/nrLDPC_load.c b/openair1/PHY/CODING/nrLDPC_load.c index a74bdf7bd1..23e5032bad 100644 --- a/openair1/PHY/CODING/nrLDPC_load.c +++ b/openair1/PHY/CODING/nrLDPC_load.c @@ -42,22 +42,32 @@ /* function description array, to be used when loading the encoding/decoding shared lib */ -static loader_shlibfunc_t shlib_fdesc[2]; +static loader_shlibfunc_t shlib_fdesc[3]; -char *arg[64]={"ldpctest","-O","cmdlineonly::dbgl0"}; +/* arguments used when called from phy simulators exec's which do not use the config module */ +/* arg is used to initialize the config module so that the loader works as expected */ +char *arg[64]={"ldpctest","-O","cmdlineonly::dbgl0",NULL,NULL}; -int load_nrLDPClib(void) { +int load_nrLDPClib(char *version) { char *ptr = (char*)config_get_if(); + char libname[64]="ldpc"; + if ( ptr==NULL ) {// phy simulators, config module possibly not loaded - load_configmodule(3,(char **)arg,CONFIG_ENABLECMDLINEONLY) ; + load_configmodule(0,(char **)NULL,CONFIG_ENABLECMDLINEONLY) ; logInit(); } shlib_fdesc[0].fname = "nrLDPC_decod"; shlib_fdesc[1].fname = "nrLDPC_encod"; - int ret=load_module_shlib("ldpc",shlib_fdesc,sizeof(shlib_fdesc)/sizeof(loader_shlibfunc_t),NULL); + shlib_fdesc[2].fname = "nrLDPC_initcall"; + int ret; + if (version) + ret=load_module_version_shlib(libname,version,shlib_fdesc,sizeof(shlib_fdesc)/sizeof(loader_shlibfunc_t),NULL); + else + ret=load_module_shlib(libname,shlib_fdesc,sizeof(shlib_fdesc)/sizeof(loader_shlibfunc_t),NULL); AssertFatal( (ret >= 0),"Error loading ldpc decoder"); nrLDPC_decoder = (nrLDPC_decoderfunc_t)shlib_fdesc[0].fptr; nrLDPC_encoder = (nrLDPC_encoderfunc_t)shlib_fdesc[1].fptr; + nrLDPC_initcall = (nrLDPC_initcallfunc_t)shlib_fdesc[2].fptr; return 0; } @@ -65,10 +75,8 @@ int load_nrLDPClib_ref(char *libversion, nrLDPC_encoderfunc_t * nrLDPC_encoder_p loader_shlibfunc_t shlib_encoder_fdesc; shlib_encoder_fdesc.fname = "nrLDPC_encod"; - char libpath[64]; - sprintf(libpath,"ldpc%s",libversion); - int ret=load_module_shlib(libpath,&shlib_encoder_fdesc,1,NULL); - AssertFatal( (ret >= 0),"Error loading ldpc encoder %s\n",libpath); + int ret=load_module_version_shlib("ldpc",libversion,&shlib_encoder_fdesc,1,NULL); + AssertFatal( (ret >= 0),"Error loading ldpc encoder %s\n",(libversion==NULL)?"":libversion); *nrLDPC_encoder_ptr = (nrLDPC_encoderfunc_t)shlib_encoder_fdesc.fptr; return 0; } diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c index 18db8a01fb..8fe115b23a 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c @@ -40,9 +40,9 @@ #include "assertions.h" int8_t polar_decoder(double *input, - uint32_t *out, - t_nrPolar_params *polarParams, - uint8_t listSize) + uint32_t *out, + const t_nrPolar_params *polarParams, + uint8_t listSize) { //Assumes no a priori knowledge. uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); @@ -299,7 +299,7 @@ int8_t polar_decoder(double *input, int8_t polar_decoder_dci(double *input, uint32_t *out, - t_nrPolar_params *polarParams, + const t_nrPolar_params *polarParams, uint8_t listSize, uint16_t n_RNTI) { uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h index a44a08a701..c2e9fd9381 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h @@ -138,22 +138,22 @@ typedef struct nrPolar_params t_nrPolar_params; void polar_encoder(uint32_t *input, uint32_t *output, - t_nrPolar_params *polarParams); + const t_nrPolar_params *polarParams); void polar_encoder_dci(uint32_t *in, uint32_t *out, - t_nrPolar_params *polarParams, + const t_nrPolar_params *polarParams, uint16_t n_RNTI); void polar_encoder_fast(uint64_t *A, void *out, int32_t crcmask, uint8_t ones_flag, - t_nrPolar_params *polarParams); + const t_nrPolar_params *polarParams); int8_t polar_decoder(double *input, - uint32_t *output, - t_nrPolar_params *polarParams, + uint32_t *output, + const t_nrPolar_params *polarParams, uint8_t listSize); uint32_t polar_decoder_int16(int16_t *input, @@ -163,21 +163,21 @@ uint32_t polar_decoder_int16(int16_t *input, int8_t polar_decoder_dci(double *input, uint32_t *out, - t_nrPolar_params *polarParams, + const t_nrPolar_params *polarParams, uint8_t listSize, uint16_t n_RNTI); void generic_polar_decoder(const t_nrPolar_params *pp, - decoder_node_t *node); + decoder_node_t *node); void applyFtoleft(const t_nrPolar_params *pp, - decoder_node_t *node); + decoder_node_t *node); void applyGtoright(const t_nrPolar_params *pp, - decoder_node_t *node); + decoder_node_t *node); void computeBeta(const t_nrPolar_params *pp, - decoder_node_t *node); + decoder_node_t *node); void build_decoder_tree(t_nrPolar_params *pp); void build_polar_tables(t_nrPolar_params *polarParams); diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c index 27c062c217..1dfaed8b94 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c @@ -43,7 +43,7 @@ void polar_encoder(uint32_t *in, uint32_t *out, - t_nrPolar_params *polarParams) { + const t_nrPolar_params *polarParams) { if (1) {//polarParams->idx == 0 || polarParams->idx == 1) { //PBCH or PDCCH /* uint64_t B = (((uint64_t)*in)&((((uint64_t)1)<<32)-1)) | (((uint64_t)crc24c((uint8_t*)in,polarParams->payloadBits)>>8)<payloadBits); @@ -154,7 +154,7 @@ void polar_encoder(uint32_t *in, void polar_encoder_dci(uint32_t *in, uint32_t *out, - t_nrPolar_params *polarParams, + const t_nrPolar_params *polarParams, uint16_t n_RNTI) { #ifdef DEBUG_POLAR_ENCODER_DCI printf("[polar_encoder_dci] in: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", in[0], in[1], in[2], in[3]); @@ -251,17 +251,18 @@ void polar_encoder_dci(uint32_t *in, #endif } -static inline void polar_rate_matching(t_nrPolar_params *polarParams,void *in,void *out) __attribute__((always_inline)); +static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void *in,void *out) __attribute__((always_inline)); -static inline void polar_rate_matching(t_nrPolar_params *polarParams,void *in,void *out) { +static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void *in,void *out) { // handle rate matching with a single 128 bit word using bit shuffling // can be done with SIMD intrisics if needed if (polarParams->groupsize < 8) { - AssertFatal(polarParams->encoderLength<=128,"Need to handle groupsize<8 and N>128\n"); + AssertFatal(polarParams->encoderLength<=512,"Need to handle groupsize(%d)<8 and N(%d)>512\n",polarParams->groupsize,polarParams->encoderLength); uint128_t *out128=(uint128_t*)out; uint128_t *in128=(uint128_t*)in; - *out128=0; + for (int i=0;iencoderLength>>7;i++) + out128[i]=0; uint128_t tmp0; #ifdef DEBUG_POLAR_ENCODER uint128_t tmp1; @@ -270,15 +271,21 @@ static inline void polar_rate_matching(t_nrPolar_params *polarParams,void *in,vo #ifdef DEBUG_POLAR_ENCODER printf("%d<-%u : %llx.%llx =>",i,polarParams->rate_matching_pattern[i],((uint64_t *)out)[1],((uint64_t *)out)[0]); #endif - tmp0 = (*in128&(((uint128_t)1)<rate_matching_pattern[i])); + uint8_t pi=polarParams->rate_matching_pattern[i]; + uint8_t pi7=pi>>7; + uint8_t pimod128=pi&127; + uint8_t imod128=i&127; + uint8_t i7=i>>7; + + tmp0 = (in128[pi7]&(((uint128_t)1)<<(pimod128))); + if (tmp0!=0) { - *out128 = *out128 | ((uint128_t)1)<%llx.%llx => %llx.%llx\n", - ((uint64_t *)&tmp0)[1],((uint64_t *)&tmp0)[0], - ((uint64_t *)&tmp1)[1],((uint64_t *)&tmp1)[0], - ((uint64_t *)out)[1],((uint64_t *)out)[0]); + printf("%llx.%llx<->%llx.%llx => %llx.%llx\n", + ((uint64_t *)&tmp0)[1],((uint64_t *)&tmp0)[0], + ((uint64_t *)&tmp1)[1],((uint64_t *)&tmp1)[0], + ((uint64_t *)out)[1],((uint64_t *)out)[0]); #endif } } @@ -411,7 +418,7 @@ void polar_encoder_fast(uint64_t *A, void *out, int32_t crcmask, uint8_t ones_flag, - t_nrPolar_params *polarParams) { + const t_nrPolar_params *polarParams) { // AssertFatal(polarParams->K > 32, "K = %d < 33, is not supported yet\n",polarParams->K); AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n",polarParams->K); AssertFatal(polarParams->payloadBits < 65, "payload bits = %d > 64, is not supported yet\n",polarParams->payloadBits); diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c index 5294e79b9f..ae49f9a4a7 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nr_rate_matching.c @@ -236,13 +236,12 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) } */ - int j2=0; fp=f; switch (Qm) { case 2: e0=e; e1=e0+EQm; - for (int j = 0; j< EQm; j++,j2+=2){ + for (int j = 0, j2 = 0; j< EQm; j++,j2+=2){ fp=&f[j2]; fp[0] = e0[j]; fp[1] = e1[j]; @@ -253,7 +252,7 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) e1=e0+EQm; e2=e1+EQm; e3=e2+EQm; - for (int j = 0; j< EQm; j++,j2+=4){ + for (int j = 0, j2 = 0; j< EQm; j++,j2+=4){ fp=&f[j2]; fp[0] = e0[j]; fp[1] = e1[j]; @@ -287,7 +286,7 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) e5=e4+EQm; e6=e5+EQm; e7=e6+EQm; - for (int j = 0; j< EQm; j++,j2+=8){ + for (int j = 0, j2 = 0; j< EQm; j++,j2+=8){ fp=&f[j2]; fp[0] = e0[j]; fp[1] = e1[j]; @@ -310,15 +309,67 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f) { - uint32_t EQm; - - EQm = E/Qm; - - for (int j = 0; j< EQm; j++){ - for (int i = 0; i< Qm; i++){ - e[(i*EQm + j)] = f[(i+j*Qm)]; - } + int16_t *e1,*e2,*e3,*e4,*e5,*e6,*e7; + switch(Qm) { + case 2: + e1=e+(E/2); + for (int j = 0,j2=0; j< E/2; j+=2,j2+=4){ + e[j] = f[j2]; + e1[j] = f[j2+1]; + e[j+1] = f[j2+2]; + e1[j+1] = f[j2+3]; + } + break; + case 4: + e1=e+(E/4); + e2=e1+(E/4); + e3=e2+(E/4); + for (int j = 0,j2=0; j< E/4; j++,j2+=4){ + e[j] = f[j2]; + e1[j] = f[j2+1]; + e2[j] = f[j2+2]; + e3[j] = f[j2+3]; + } + break; + case 6: + e1=e+(E/6); + e2=e1+(E/6); + e3=e2+(E/6); + e4=e3+(E/6); + e5=e4+(E/6); + for (int j = 0,j2=0; j< E/6; j++,j2+=6){ + e[j] = f[j2]; + e1[j] = f[j2+1]; + e2[j] = f[j2+2]; + e3[j] = f[j2+3]; + e4[j] = f[j2+4]; + e5[j] = f[j2+5]; + } + break; + case 8: + e1=e+(E/8); + e2=e1+(E/8); + e3=e2+(E/8); + e4=e3+(E/8); + e5=e4+(E/8); + e6=e5+(E/8); + e7=e6+(E/8); + for (int j = 0,j2=0; j< E/8; j++,j2+=8){ + e[j] = f[j2]; + e1[j] = f[j2+1]; + e2[j] = f[j2+2]; + e3[j] = f[j2+3]; + e4[j] = f[j2+4]; + e5[j] = f[j2+5]; + e6[j] = f[j2+6]; + e7[j] = f[j2+7]; + } + break; + default: + AssertFatal(1==0,"Should not get here : Qm %d\n",Qm); + break; } + } @@ -337,7 +388,7 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm, uint32_t Ncb,ind,k=0,Nref,N; if (C==0) { - printf("nr_rate_matching: invalid parameters (C %d\n",C); + LOG_E(PHY,"nr_rate_matching: invalid parameters (C %d\n",C); return -1; } @@ -356,8 +407,15 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm, #ifdef RM_DEBUG printf("nr_rate_matching_ldpc: E %d, F %d, Foffset %d, k0 %d, Ncb %d, rvidx %d\n", E, F, Foffset,ind, Ncb, rvidx); #endif - AssertFatal(Foffset <= E,"Foffset %d > E %d\n",Foffset,E); - AssertFatal(Foffset <= Ncb,"Foffset %d > Ncb %d\n",Foffset,Ncb); + + if (Foffset > E) { + LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > E %d)\n",Foffset,E); + return -1; + } + if (Foffset > Ncb) { + LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > Ncb %d)\n",Foffset,Ncb); + return -1; + } if (ind >= Foffset && ind < (F+Foffset)) ind = F+Foffset; @@ -374,7 +432,7 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm, } } else { - if (E + F <= Ncb-ind) { //E+F doesn't contain all coded bits + if (E <= Ncb-ind) { //E+F doesn't contain all coded bits memcpy((void*)(e),(void*)(w+ind),E); k=E; } @@ -419,7 +477,7 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, #endif if (C==0) { - printf("nr_rate_matching: invalid parameters (C %d\n",C); + LOG_E(PHY,"nr_rate_matching: invalid parameters (C %d\n",C); return -1; } @@ -434,8 +492,14 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, } ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z; - AssertFatal(Foffset <= E,"Foffset %d > E %d\n",Foffset,E); - AssertFatal(Foffset <= Ncb,"Foffset %d > Ncb %d\n",Foffset,Ncb); + if (Foffset > E) { + LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > E %d)\n",Foffset,E); + return -1; + } + if (Foffset > Ncb) { + LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > Ncb %d)\n",Foffset,Ncb); + return -1; + } #ifdef RM_DEBUG printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d\n", clear, E, ind, Ncb, rvidx); diff --git a/openair1/PHY/CODING/nr_segmentation.c b/openair1/PHY/CODING/nr_segmentation.c index 1d80a83131..0eede23766 100644 --- a/openair1/PHY/CODING/nr_segmentation.c +++ b/openair1/PHY/CODING/nr_segmentation.c @@ -92,9 +92,7 @@ if ((Kprime%Kb) > 0) else Z = (Kprime/Kb); -#ifdef DEBUG_SEGMENTATION - printf("nr segmetation B %u Bprime %u Kprime %u z %u \n", B, Bprime, Kprime, Z); -#endif + LOG_D(PHY,"nr segmetation B %u Bprime %u Kprime %u z %u \n", B, Bprime, Kprime, Z); if (Z <= 2) { *K = 2; @@ -148,10 +146,8 @@ else *F = ((*K) - Kprime); -#ifdef DEBUG_SEGMENTATION - printf("final nr seg output Z %u K %u F %u \n", *Zout, *K, *F); - printf("C %u, K %u, Bprime_bytes %u, Bprime %u, F %u\n",*C,*K,Bprime>>3,Bprime,*F); -#endif + LOG_D(PHY,"final nr seg output Z %u K %u F %u \n", *Zout, *K, *F); + LOG_D(PHY,"C %u, K %u, Bprime_bytes %u, Bprime %u, F %u\n",*C,*K,Bprime>>3,Bprime,*F); if ((input_buffer) && (output_buffers)) { diff --git a/openair1/PHY/CODING/types.h b/openair1/PHY/CODING/types.h new file mode 100644 index 0000000000..2bc7739e36 --- /dev/null +++ b/openair1/PHY/CODING/types.h @@ -0,0 +1,98 @@ +/******************************************************************************* + Copyright (c) 2009-2018, Intel Corporation + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/* Common data types, macros and functions used across the CRC library */ + +#ifndef CRC_TYPES_H_ +#define CRC_TYPES_H_ + +#ifdef __KERNEL__ +#include +#include +typedef uint32_t uint_fast32_t; +typedef uint16_t uint_fast16_t; +typedef uint8_t uint_fast8_t; +#else +#include +#include +#endif + +/* Declare variable at address aligned to a boundary */ +#define DECLARE_ALIGNED(_declaration, _boundary) \ + _declaration __attribute__((aligned(_boundary))) + +/* Macro to make function to be always inlined */ +#ifndef DEBUG +#define __forceinline \ + static inline __attribute__((always_inline)) +#else +#define __forceinline \ + static +#endif + +/* Likely & unliekly hints for the compiler */ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +/* Macro to get dimension of an array */ +#ifndef DIM +#define DIM(x) (sizeof(x)/sizeof(x[0])) +#endif + +/** + * Common functions + */ + +/** + * @brief Swaps bytes in 16 bit word + * + * @param val 16 bit data value + * + * @return byte swapped value + */ +__forceinline uint16_t bswap2(const uint16_t val) +{ + return (uint16_t) ((val >> 8) | (val << 8)); +} + +/** + * @brief Swaps bytes in 32 bit word + * ABCD -> DCBA + * + * @param val 32 bit data value + * + * @return byte swapped value + */ +__forceinline uint32_t bswap4(const uint32_t val) +{ + return ((val >> 24) | /**< A*/ + ((val & 0xff0000) >> 8) | /**< B*/ + ((val & 0xff00) << 8) | /**< C*/ + (val << 24)); /**< D*/ +} + +#endif /* CRC_TYPES_H_ */ diff --git a/openair1/PHY/INIT/init_top.c b/openair1/PHY/INIT/init_top.c index 0990a58266..81fb28cc98 100644 --- a/openair1/PHY/INIT/init_top.c +++ b/openair1/PHY/INIT/init_top.c @@ -73,7 +73,6 @@ void init_lte_top(LTE_DL_FRAME_PARMS *frame_parms) { init_unscrambling_lut(); init_scrambling_lut(); //set_taus_seed(1328); - init_sss(); } void free_lte_top(void) { diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 2c7e3e88eb..1daeb72187 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -35,7 +35,7 @@ #include "assertions.h" #include #include "nfapi/oai_integration/vendor_ext.h" - +#include extern uint32_t from_earfcn(int eutra_bandP,uint32_t dl_earfcn); extern int32_t get_uldl_offset(int eutra_bandP); @@ -46,6 +46,17 @@ uint8_t dmrs1_tab[8] = { 0, 2, 3, 4, 6, 8, 9, 10 }; int N_RB_DL_array[6] = { 6, 15, 25, 50, 75, 100 }; +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + +void pdsch_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int harq_pid, + LTE_eNB_DLSCH_t *dlsch, + LTE_eNB_DLSCH_t *dlsch1); + +void init_sss(void); + int l1_north_init_eNB () { int i,j; @@ -347,6 +358,33 @@ void phy_config_sib13_eNB(module_id_t Mod_id,int CC_id,int mbsfn_Area_idx, lte_gold_mbsfn_khz_1dot25 (fp, RC.eNB[Mod_id][CC_id]->lte_gold_mbsfn_khz_1dot25_table, fp->Nid_cell_mbsfn); } +void fill_subframe_mask(PHY_VARS_eNB *eNB) { + + AssertFatal(eNB->subframe_mask!=NULL,"Subframe mask is null\n"); + int32_t **dummy_tx=eNB->common_vars.txdataF; + eNB->common_vars.txdataF = eNB->subframe_mask; + + for (int sf=0;sf<10;sf++) { + if (subframe_select(&eNB->frame_parms,sf)==SF_DL) { + LTE_DL_eNB_HARQ_t *dlsch_harq=eNB->dlsch[0][0]->harq_processes[0]; + L1_rxtx_proc_t proc; + proc.frame_tx=0; + proc.subframe_tx=sf; + eNB->dlsch[0][0]->harq_ids[0][sf]=0; + eNB->dlsch[0][0]->rnti=0x1234; + dlsch_harq->nb_rb=48; + dlsch_harq->rb_alloc[0]=(uint32_t)0xffffffff; + dlsch_harq->Qm=2; + dlsch_harq->Nl=1; + dlsch_harq->pdsch_start=1; + dlsch_harq->mimo_mode=(eNB->frame_parms.nb_antenna_ports_eNB>1) ? ALAMOUTI : SISO; + dlsch_harq->dl_power_off = 1; + computeRhoB_eNB(4,eNB->frame_parms.pdsch_config_common.p_b,eNB->frame_parms.nb_antenna_ports_eNB,eNB->dlsch[0][0],dlsch_harq->dl_power_off); + pdsch_procedures(eNB,&proc,0,eNB->dlsch[0][0],NULL); + } + } + eNB->common_vars.txdataF = dummy_tx; +} int phy_init_lte_eNB(PHY_VARS_eNB *eNB, unsigned char is_secondary_eNB, @@ -385,7 +423,9 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, lte_gold (fp, eNB->lte_gold_table, fp->Nid_cell); generate_pcfich_reg_mapping (fp); generate_phich_reg_mapping (fp); + init_sss(); + init_fde(); for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { eNB->first_run_timing_advance[UE_id] = 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. @@ -397,9 +437,13 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, eNB->first_run_I0_measurements = 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. + eNB->use_DTX=1; if (NFAPI_MODE!=NFAPI_MODE_VNF) { common_vars->rxdata = (int32_t **)NULL; common_vars->txdataF = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t *)); + if (eNB->use_DTX==0) { + eNB->subframe_mask = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t *)); + } common_vars->rxdataF = (int32_t **)malloc16(64*sizeof(int32_t *)); LOG_I(PHY,"[INIT] NB_ANTENNA_PORTS_ENB:%d fp->nb_antenna_ports_eNB:%d\n", NB_ANTENNA_PORTS_ENB, fp->nb_antenna_ports_eNB); @@ -409,17 +453,19 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, LOG_I(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n", i,common_vars->txdataF[i], fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t)); + if (eNB->use_DTX==0 && inb_antenna_ports_eNB) eNB->subframe_mask[i] = malloc16_clear(fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) ); } } + LOG_I(PHY,"[INIT]SRS allocation\n"); // Channel estimates for SRS - for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - srs_vars[UE_id].srs_ch_estimates = (int32_t **) malloc16 (64 * sizeof (int32_t *)); - srs_vars[UE_id].srs_ch_estimates_time = (int32_t **) malloc16 (64 * sizeof (int32_t *)); + for (int srs_id = 0; srs_id < NUMBER_OF_SRS_MAX; srs_id++) { + srs_vars[srs_id].srs_ch_estimates = (int32_t **) malloc16 (64 * sizeof (int32_t *)); + srs_vars[srs_id].srs_ch_estimates_time = (int32_t **) malloc16 (64 * sizeof (int32_t *)); for (i = 0; i < 64; i++) { - srs_vars[UE_id].srs_ch_estimates[i] = (int32_t *) malloc16_clear (sizeof (int32_t) * fp->ofdm_symbol_size); - srs_vars[UE_id].srs_ch_estimates_time[i] = (int32_t *) malloc16_clear (sizeof (int32_t) * fp->ofdm_symbol_size * 2); + srs_vars[srs_id].srs_ch_estimates[i] = (int32_t *) malloc16_clear (sizeof (int32_t) * fp->ofdm_symbol_size); + srs_vars[srs_id].srs_ch_estimates_time[i] = (int32_t *) malloc16_clear (sizeof (int32_t) * fp->ofdm_symbol_size * 2); } } //UE_id @@ -427,10 +473,11 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, init_ulsch_power_LUT (); // SRS - for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - srs_vars[UE_id].srs = (int32_t *) malloc16_clear (2 * fp->ofdm_symbol_size * sizeof (int32_t)); + for (int srs_id = 0; srs_id < NUMBER_OF_SRS_MAX; srs_id++) { + srs_vars[srs_id].srs = (int32_t *) malloc16_clear (2 * fp->ofdm_symbol_size * sizeof (int32_t)); } + LOG_I(PHY,"PRACH allocation\n"); // PRACH prach_vars->prachF = (int16_t *) malloc16_clear (1024 * 2 * sizeof (int16_t)); // assume maximum of 64 RX antennas for PRACH receiver @@ -461,34 +508,33 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,prach_vars->rxsigF[i]); }*/ - for (UE_id=0; UE_idrxdataF_ext = (int32_t **) malloc16 (2 * sizeof (int32_t *)); - pusch_vars[UE_id]->rxdataF_ext2 = (int32_t **) malloc16 (2 * sizeof (int32_t *)); - pusch_vars[UE_id]->drs_ch_estimates = (int32_t **) malloc16 (2 * sizeof (int32_t *)); - pusch_vars[UE_id]->drs_ch_estimates_time = (int32_t **) malloc16 (2 * sizeof (int32_t *)); - pusch_vars[UE_id]->rxdataF_comp = (int32_t **) malloc16 (2 * sizeof (int32_t *)); - pusch_vars[UE_id]->ul_ch_mag = (int32_t **) malloc16 (2 * sizeof (int32_t *)); - pusch_vars[UE_id]->ul_ch_magb = (int32_t **) malloc16 (2 * sizeof (int32_t *)); + pusch_vars[ULSCH_id] = (LTE_eNB_PUSCH *) malloc16_clear (NUMBER_OF_ULSCH_MAX * sizeof (LTE_eNB_PUSCH)); + pusch_vars[ULSCH_id]->rxdataF_ext = (int32_t **) malloc16 (4 * sizeof (int32_t *)); + pusch_vars[ULSCH_id]->rxdataF_ext2 = (int32_t **) malloc16 (4 * sizeof (int32_t *)); + pusch_vars[ULSCH_id]->drs_ch_estimates = (int32_t **) malloc16 (4 * sizeof (int32_t *)); + pusch_vars[ULSCH_id]->drs_ch_estimates_time = (int32_t **) malloc16 (4 * sizeof (int32_t *)); + pusch_vars[ULSCH_id]->rxdataF_comp = (int32_t **) malloc16 (4 * sizeof (int32_t *)); + pusch_vars[ULSCH_id]->ul_ch_mag = (int32_t **) malloc16 (4 * sizeof (int32_t *)); + pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **) malloc16 (4 * sizeof (int32_t *)); AssertFatal (fp->ofdm_symbol_size > 127, "fp->ofdm_symbol_size %d<128\n", fp->ofdm_symbol_size); AssertFatal (fp->symbols_per_tti > 11, "fp->symbols_per_tti %d < 12\n", fp->symbols_per_tti); AssertFatal (fp->N_RB_UL > 5, "fp->N_RB_UL %d < 6\n", fp->N_RB_UL); - - for (i = 0; i < 2; i++) { - // RK 2 times because of output format of FFT! + AssertFatal (fp->nb_antennas_rx > 0,"fp->nb_antennas_rx = %d\n",fp->nb_antennas_rx); + for (i = 0; i < fp->nb_antennas_rx; i++) { // FIXME We should get rid of this - pusch_vars[UE_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->drs_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->drs_ch_estimates_time[i] = (int32_t *)malloc16_clear( 2*sizeof(int32_t)*fp->ofdm_symbol_size ); - pusch_vars[UE_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - pusch_vars[UE_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[ULSCH_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[ULSCH_id]->drs_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[ULSCH_id]->drs_ch_estimates_time[i] = (int32_t *)malloc16_clear( 4*sizeof(int32_t)*fp->ofdm_symbol_size ); + pusch_vars[ULSCH_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[ULSCH_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[ULSCH_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); } - pusch_vars[UE_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); - } //UE_id + pusch_vars[ULSCH_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + } //ULSCH_id for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) eNB->UE_stats_ptr[UE_id] = &eNB->UE_stats[UE_id]; @@ -518,19 +564,19 @@ void phy_free_lte_eNB(PHY_VARS_eNB *eNB) { free_and_zero(common_vars->rxdataF); // Channel estimates for SRS - for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + for (int srs_id = 0; srs_id < NUMBER_OF_SRS_MAX; srs_id++) { for (i=0; i<64; i++) { - free_and_zero(srs_vars[UE_id].srs_ch_estimates[i]); - free_and_zero(srs_vars[UE_id].srs_ch_estimates_time[i]); + free_and_zero(srs_vars[srs_id].srs_ch_estimates[i]); + free_and_zero(srs_vars[srs_id].srs_ch_estimates_time[i]); } - free_and_zero(srs_vars[UE_id].srs_ch_estimates); - free_and_zero(srs_vars[UE_id].srs_ch_estimates_time); + free_and_zero(srs_vars[srs_id].srs_ch_estimates); + free_and_zero(srs_vars[srs_id].srs_ch_estimates_time); } //UE_id free_ul_ref_sigs(); - for (UE_id=0; UE_idprachF); @@ -548,26 +594,26 @@ void phy_free_lte_eNB(PHY_VARS_eNB *eNB) { free_and_zero(prach_vars_br->prachF); free_and_zero(prach_vars->rxsigF[0]); - for (UE_id=0; UE_idrxdataF_ext[i]); - free_and_zero(pusch_vars[UE_id]->rxdataF_ext2[i]); - free_and_zero(pusch_vars[UE_id]->drs_ch_estimates[i]); - free_and_zero(pusch_vars[UE_id]->drs_ch_estimates_time[i]); - free_and_zero(pusch_vars[UE_id]->rxdataF_comp[i]); - free_and_zero(pusch_vars[UE_id]->ul_ch_mag[i]); - free_and_zero(pusch_vars[UE_id]->ul_ch_magb[i]); + for (int ULSCH_id=0; ULSCH_idnb_antennas_rx; i++) { + free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext[i]); + free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext2[i]); + free_and_zero(pusch_vars[ULSCH_id]->drs_ch_estimates[i]); + free_and_zero(pusch_vars[ULSCH_id]->drs_ch_estimates_time[i]); + free_and_zero(pusch_vars[ULSCH_id]->rxdataF_comp[i]); + free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag[i]); + free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb[i]); } - free_and_zero(pusch_vars[UE_id]->rxdataF_ext); - free_and_zero(pusch_vars[UE_id]->rxdataF_ext2); - free_and_zero(pusch_vars[UE_id]->drs_ch_estimates); - free_and_zero(pusch_vars[UE_id]->drs_ch_estimates_time); - free_and_zero(pusch_vars[UE_id]->rxdataF_comp); - free_and_zero(pusch_vars[UE_id]->ul_ch_mag); - free_and_zero(pusch_vars[UE_id]->ul_ch_magb); - free_and_zero(pusch_vars[UE_id]->llr); - free_and_zero(pusch_vars[UE_id]); + free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext); + free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext2); + free_and_zero(pusch_vars[ULSCH_id]->drs_ch_estimates); + free_and_zero(pusch_vars[ULSCH_id]->drs_ch_estimates_time); + free_and_zero(pusch_vars[ULSCH_id]->rxdataF_comp); + free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag); + free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb); + free_and_zero(pusch_vars[ULSCH_id]->llr); + free_and_zero(pusch_vars[ULSCH_id]); } //UE_id for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) eNB->UE_stats_ptr[UE_id] = NULL; diff --git a/openair1/PHY/INIT/lte_init_ru.c b/openair1/PHY/INIT/lte_init_ru.c index baea52083f..a856c33999 100644 --- a/openair1/PHY/INIT/lte_init_ru.c +++ b/openair1/PHY/INIT/lte_init_ru.c @@ -21,9 +21,8 @@ #include "phy_init.h" #include "SCHED/sched_eNB.h" -#include "PHY/phy_extern.h" #include "PHY/LTE_REFSIG/lte_refsig.h" -#include "SIMULATION/TOOLS/sim.h" +//#include "SIMULATION/TOOLS/sim.h" #include "LTE_RadioResourceConfigCommonSIB.h" #include "LTE_RadioResourceConfigDedicated.h" #include "LTE_TDD-Config.h" @@ -34,6 +33,8 @@ void init_7_5KHz(void); +extern const char ru_if_types[MAX_RU_IF_TYPES][20]; + int phy_init_RU(RU_t *ru) { LTE_DL_FRAME_PARMS *fp = ru->frame_parms; RU_CALIBRATION *calibration = &ru->calibration; @@ -44,6 +45,7 @@ int phy_init_RU(RU_t *ru) { if (ru->is_slave == 1) { generate_ul_ref_sigs_rx(); } + else generate_ul_ref_sigs(); if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so allocate memory for time-domain signals // Time-domain signals @@ -121,13 +123,13 @@ int phy_init_RU(RU_t *ru) { /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */ //AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]), //"nb_antennas_rx too large"); - ru->prach_rxsigF = (int16_t **)malloc(ru->nb_rx * sizeof(int16_t *)); + ru->prach_rxsigF[0] = (int16_t **)malloc(ru->nb_rx * sizeof(int16_t *)); for (j=0; j<4; j++) ru->prach_rxsigF_br[j] = (int16_t **)malloc(ru->nb_rx * sizeof(int16_t *)); for (i=0; inb_rx; i++) { - ru->prach_rxsigF[i] = (int16_t *)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) ); - LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[i]); + ru->prach_rxsigF[0][i] = (int16_t *)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) ); + LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[0][i]); for (j=0; j<4; j++) { ru->prach_rxsigF_br[j][i] = (int16_t *)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) ); @@ -135,14 +137,14 @@ int phy_init_RU(RU_t *ru) { } } - AssertFatal(RC.nb_L1_inst <= NUMBER_OF_eNB_MAX,"eNB instances %d > %d\n", - RC.nb_L1_inst,NUMBER_OF_eNB_MAX); - LOG_D(PHY,"[INIT] %s() RC.nb_L1_inst:%d \n", __FUNCTION__, RC.nb_L1_inst); + AssertFatal(ru->num_eNB <= NUMBER_OF_eNB_MAX,"eNB instances %d > %d\n", + ru->num_eNB,NUMBER_OF_eNB_MAX); + LOG_D(PHY,"[INIT] %s() ru->num_eNB:%d \n", __FUNCTION__, ru->num_eNB); int starting_antenna_index=0; for (i=0; iidx; i++) starting_antenna_index+=ru->nb_tx; - for (i=0; inum_eNB; i++) { for (p=0; p<15; p++) { LOG_D(PHY,"[INIT] %s() nb_antenna_ports_eNB:%d \n", __FUNCTION__, ru->eNB_list[i]->frame_parms.nb_antenna_ports_eNB); @@ -230,17 +232,17 @@ void phy_free_RU(RU_t *ru) { } for (i = 0; i < ru->nb_rx; i++) { - free_and_zero(ru->prach_rxsigF[i]); + free_and_zero(ru->prach_rxsigF[0][i]); for (j = 0; j < 4; j++) free_and_zero(ru->prach_rxsigF_br[j][i]); } for (j = 0; j < 4; j++) free_and_zero(ru->prach_rxsigF_br[j]); - free_and_zero(ru->prach_rxsigF); + free_and_zero(ru->prach_rxsigF[0]); /* ru->prach_rxsigF_br is not allocated -> don't free */ - for (i = 0; i < RC.nb_L1_inst; i++) { + for (i = 0; i < ru->num_eNB; i++) { for (p = 0; p < 15; p++) { if (p < ru->eNB_list[i]->frame_parms.nb_antenna_ports_eNB || p == 5) { for (j=0; jnb_tx; j++) free_and_zero(ru->beam_weights[i][p][j]); diff --git a/openair1/PHY/INIT/lte_init_ue.c b/openair1/PHY/INIT/lte_init_ue.c index 64a5992a64..b756735816 100644 --- a/openair1/PHY/INIT/lte_init_ue.c +++ b/openair1/PHY/INIT/lte_init_ue.c @@ -39,6 +39,7 @@ void init_7_5KHz(void); uint8_t dmrs1_tab_ue[8] = {0,2,3,4,6,8,9,10}; +void init_sss(void); void phy_config_sib1_ue(module_id_t Mod_id,int CC_id, uint8_t eNB_id, @@ -629,6 +630,7 @@ int init_lte_ue_signal(PHY_VARS_UE *ue, init_frame_parms(&ue->frame_parms,1); lte_sync_time_init(&ue->frame_parms); init_lte_top(&ue->frame_parms); + init_sss(); init_7_5KHz(); init_ul_hopping(&ue->frame_parms); // many memory allocation sizes are hard coded diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c index 1505ee018e..504c8fa80a 100644 --- a/openair1/PHY/INIT/lte_param_init.c +++ b/openair1/PHY/INIT/lte_param_init.c @@ -25,7 +25,6 @@ #include #include -#include "SIMULATION/TOOLS/sim.h" #include "PHY/types.h" #include "PHY/defs_eNB.h" #include "PHY/defs_UE.h" @@ -33,7 +32,9 @@ #include "phy_init.h" #include "PHY/LTE_REFSIG/lte_refsig.h" #include "PHY/LTE_TRANSPORT/transport_common_proto.h" -#include "targets/RT/USER/lte-softmodem.h" +#include "executables/softmodem-common.h" +#include "SIMULATION/TOOLS/sim.h" + extern PHY_VARS_eNB *eNB; extern PHY_VARS_UE *UE; extern RU_t *ru; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 136092f2d4..cd4848ea8c 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -20,6 +20,8 @@ */ #include "executables/nr-softmodem-common.h" +#include "common/utils/nr/nr_common.h" +#include "common/ran_context.h" #include "PHY/defs_gNB.h" #include "PHY/phy_extern.h" #include "PHY/NR_REFSIG/nr_refsig.h" @@ -27,13 +29,13 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "openair1/PHY/MODULATION/nr_modulation.h" /*#include "RadioResourceConfigCommonSIB.h" #include "RadioResourceConfigDedicated.h" #include "TDD-Config.h" #include "MBSFN-SubframeConfigList.h"*/ #include "openair1/PHY/defs_RU.h" #include "openair1/PHY/CODING/nrLDPC_extern.h" -#include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "assertions.h" #include @@ -42,12 +44,8 @@ #include "SCHED_NR/fapi_nr_l1.h" #include "nfapi_nr_interface.h" -/* -extern uint32_t from_nrarfcn(int nr_bandP,uint32_t dl_nrarfcn); +#include "PHY/NR_REFSIG/ul_ref_seq_nr.h" -extern int32_t get_nr_uldl_offset(int nr_bandP); -extern openair0_config_t openair0_cfg[MAX_CARDS]; -*/ int l1_north_init_gNB() { @@ -76,19 +74,18 @@ int l1_north_init_gNB() { int phy_init_nr_gNB(PHY_VARS_gNB *gNB, unsigned char is_secondary_gNB, - unsigned char abstraction_flag) { + unsigned char lowmem_flag) { // shortcuts NR_DL_FRAME_PARMS *const fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; NR_gNB_COMMON *const common_vars = &gNB->common_vars; NR_gNB_PRACH *const prach_vars = &gNB->prach_vars; NR_gNB_PUSCH **const pusch_vars = gNB->pusch_vars; - /*LTE_eNB_SRS *const srs_vars = gNB->srs_vars; - LTE_eNB_PRACH *const prach_vars = &gNB->prach_vars;*/ int i; int Ptx=cfg->carrier_config.num_tx_ant.value; int Prx=cfg->carrier_config.num_rx_ant.value; + int max_ul_mimo_layers = 4; AssertFatal(Ptx>0 && Ptx<9,"Ptx %d is not supported\n",Ptx); AssertFatal(Prx>0 && Prx<9,"Prx %d is not supported\n",Prx); @@ -96,25 +93,22 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, while(gNB->configured == 0) usleep(10000); + if (lowmem_flag == 1) { + gNB->number_of_nr_dlsch_max = 2; + gNB->number_of_nr_ulsch_max = 2; + } + else { + gNB->number_of_nr_dlsch_max = NUMBER_OF_NR_DLSCH_MAX; + gNB->number_of_nr_ulsch_max = NUMBER_OF_NR_ULSCH_MAX; + } + load_dftslib(); - /* - LOG_I(PHY,"[gNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d nb_antennas_tx:%u nb_antennas_rx:%u PRACH[rootSequenceIndex:%u prach_Config_enabled:%u configIndex:%u highSpeed:%u zeroCorrelationZoneConfig:%u freqOffset:%u]\n", - gNB->Mod_id, - fp->N_RB_DL,fp->phich_config_common.phich_resource, - fp->phich_config_common.phich_duration, - fp->nb_antennas_tx, fp->nb_antennas_rx, - fp->prach_config_common.rootSequenceIndex, - fp->prach_config_common.prach_Config_enabled, - fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - fp->prach_config_common.prach_ConfigInfo.highSpeedFlag, - fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset - );*/ + LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_gNB][MOD %02"PRIu8"][]\n", gNB->Mod_id); crcTableInit(); init_scrambling_luts(); init_pucch2_luts(); - load_nrLDPClib(); + load_nrLDPClib(NULL); // PBCH DMRS gold sequences generation nr_init_pbch_dmrs(gNB); //PDCCH DMRS init @@ -122,12 +116,15 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs; AssertFatal(pdcch_dmrs!=NULL, "NR init: pdcch_dmrs malloc failed\n"); + gNB->bad_pucch = 0; + for (int slot=0; slotslots_per_frame; slot++) { pdcch_dmrs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *)); AssertFatal(pdcch_dmrs[slot]!=NULL, "NR init: pdcch_dmrs for slot %d - malloc failed\n", slot); for (int symb=0; symbsymbols_per_slot; symb++) { pdcch_dmrs[slot][symb] = (uint32_t *)malloc16(NR_MAX_PDCCH_DMRS_INIT_LENGTH_DWORD*sizeof(uint32_t)); + LOG_D(PHY,"pdcch_dmrs[%d][%d] %p\n",slot,symb,pdcch_dmrs[slot][symb]); AssertFatal(pdcch_dmrs[slot][symb]!=NULL, "NR init: pdcch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb); } } @@ -135,6 +132,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, nr_generate_modulation_table(); nr_init_pdcch_dmrs(gNB, cfg->cell_config.phy_cell_id.value); nr_init_pbch_interleaver(gNB->nr_pbch_interleaver); + //PDSCH DMRS init gNB->nr_gold_pdsch_dmrs = (uint32_t ****)malloc16(fp->slots_per_frame*sizeof(uint32_t ***)); uint32_t ****pdsch_dmrs = gNB->nr_gold_pdsch_dmrs; @@ -180,6 +178,26 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, LOG_D(PHY,"Initializing PUSCH DMRS Gold sequence with (%x,%x)\n",Nid_pusch[0],Nid_pusch[1]); nr_gold_pusch(gNB, &Nid_pusch[0]); + //CSI RS init + gNB->nr_gold_csi_rs = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **)); + uint32_t ***csi_rs = gNB->nr_gold_csi_rs; + AssertFatal(csi_rs!=NULL, "NR init: csi reference signal malloc failed\n"); + + for (int slot=0; slotslots_per_frame; slot++) { + csi_rs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *)); + AssertFatal(csi_rs[slot]!=NULL, "NR init: csi reference signal for slot %d - malloc failed\n", slot); + + for (int symb=0; symbsymbols_per_slot; symb++) { + csi_rs[slot][symb] = (uint32_t *)malloc16(NR_MAX_CSI_RS_INIT_LENGTH_DWORD*sizeof(uint32_t)); + AssertFatal(csi_rs[slot][symb]!=NULL, "NR init: csi reference signal for slot %d symbol %d - malloc failed\n", slot, symb); + } + } + + nr_init_csi_rs(gNB, cfg->cell_config.phy_cell_id.value); + + /* Generate low PAPR type 1 sequences for PUSCH DMRS, these are used if transform precoding is enabled. */ + generate_lowpapr_typ1_refsig_sequences(SHRT_MAX); + /// Transport init necessary for NR synchro init_nr_transport(gNB); @@ -188,18 +206,22 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, common_vars->rxdata = (int32_t **)malloc16(Prx*sizeof(int32_t*)); common_vars->txdataF = (int32_t **)malloc16(Ptx*sizeof(int32_t*)); common_vars->rxdataF = (int32_t **)malloc16(Prx*sizeof(int32_t*)); + common_vars->beam_id = (uint8_t **)malloc16(Ptx*sizeof(uint8_t*)); for (i=0;itxdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); // [hna] samples_per_frame without CP LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n", i,common_vars->txdataF[i], fp->samples_per_frame_wCP*sizeof(int32_t)); - + common_vars->beam_id[i] = (uint8_t*)malloc16_clear(fp->symbols_per_slot*fp->slots_per_frame*sizeof(uint8_t)); + memset(common_vars->beam_id[i],255,fp->symbols_per_slot*fp->slots_per_frame); } for (i=0;irxdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); common_vars->rxdata[i] = (int32_t*)malloc16_clear(fp->samples_per_frame*sizeof(int32_t)); } + common_vars->debugBuff = (int32_t*)malloc16_clear(fp->samples_per_frame*sizeof(int32_t)*100); + common_vars->debugBuff_sample_offset = 0; // Channel estimates for SRS @@ -237,56 +259,56 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, init_prach_list(gNB); int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value; + int n_buf = Prx*max_ul_mimo_layers; - printf("Before ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]); - for (int ULSCH_id=0; ULSCH_iddlsch[0][0]->harq_processes[0]); + for (int ULSCH_id=0; ULSCH_idnumber_of_nr_ulsch_max; ULSCH_id++) { pusch_vars[ULSCH_id] = (NR_gNB_PUSCH *)malloc16_clear( sizeof(NR_gNB_PUSCH) ); pusch_vars[ULSCH_id]->rxdataF_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->rxdataF_ext2 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_estimates = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_estimates_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_estimates_time = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->rxdataF_comp = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_mag0 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_magb0 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_mag = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->rho = (int32_t **)malloc16_clear(Prx*sizeof(int32_t*) ); + pusch_vars[ULSCH_id]->ul_ch_estimates = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_estimates_ext = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_estimates_time = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->rxdataF_comp = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_mag0 = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_magb0 = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_mag = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->rho = (int32_t **)malloc16_clear(n_buf*sizeof(int32_t*) ); - printf("ULSCH_id %d (before rx antenna alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); for (i=0; irxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); pusch_vars[ULSCH_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); + } + for (i=0; iul_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2*fp->symbols_per_slot ); pusch_vars[ULSCH_id]->ul_ch_estimates_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); pusch_vars[ULSCH_id]->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear( 2*sizeof(int32_t)*fp->ofdm_symbol_size ); pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2*fp->symbols_per_slot ); // max intensity in freq is 1 sc every 2 RBs - pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2*fp->symbols_per_slot ); + pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); + pusch_vars[ULSCH_id]->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->symbols_per_slot); // symbols per slot pusch_vars[ULSCH_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_mag0[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); - pusch_vars[ULSCH_id]->ul_ch_magb0[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); + pusch_vars[ULSCH_id]->ul_ch_mag0[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); + pusch_vars[ULSCH_id]->ul_ch_magb0[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); pusch_vars[ULSCH_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); pusch_vars[ULSCH_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); pusch_vars[ULSCH_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(fp->N_RB_UL*12*7*2) ); } - printf("ULSCH_id %d (before llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); pusch_vars[ULSCH_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear - printf("ULSCH_id %d (after llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); + pusch_vars[ULSCH_id]->ul_valid_re_per_slot = (int16_t *)malloc16_clear( sizeof(int16_t)*fp->symbols_per_slot); } //ulsch_id /* for (ulsch_id=0; ulsch_idUE_stats_ptr[ulsch_id] = &gNB->UE_stats[ulsch_id]; */ - printf("After ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]); return (0); } void phy_free_nr_gNB(PHY_VARS_gNB *gNB) { - //NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms; + NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms; NR_gNB_COMMON *const common_vars = &gNB->common_vars; NR_gNB_PUSCH **const pusch_vars = gNB->pusch_vars; /*LTE_eNB_SRS *const srs_vars = gNB->srs_vars; @@ -326,15 +348,18 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(prach_vars->prach_ifft[0]); free_and_zero(prach_vars->rxsigF[0]); */ - for (int ULSCH_id=0; ULSCH_idnumber_of_nr_ulsch_max; ULSCH_id++) { + for (int i = 0; i < fp->nb_antennas_rx; i++) { free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext[i]); free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext2[i]); + } + for (int i = 0; i < 4*fp->nb_antennas_rx; i++) { free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_ext[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_time[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext[i]); + free_and_zero(pusch_vars[ULSCH_id]->ptrs_phase_per_slot[i]); free_and_zero(pusch_vars[ULSCH_id]->rxdataF_comp[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag0[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb0[i]); @@ -342,7 +367,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb[i]); free_and_zero(pusch_vars[ULSCH_id]->rho[i]); } - free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext); free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext2); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates); @@ -350,6 +374,8 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_time); + free_and_zero(pusch_vars[ULSCH_id]->ptrs_phase_per_slot); + free_and_zero(pusch_vars[ULSCH_id]->ul_valid_re_per_slot); free_and_zero(pusch_vars[ULSCH_id]->rxdataF_comp); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag0); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb0); @@ -363,6 +389,18 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) /* for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) gNB->UE_stats_ptr[UE_id] = NULL; */ + + + free_gnb_lowpapr_sequences(); + + +} + +//Adding nr_schedule_handler +void install_nr_schedule_handlers(NR_IF_Module_t *if_inst) +{ + if_inst->NR_PHY_config_req = nr_phy_config_request; + if_inst->NR_Schedule_response = nr_schedule_response; } /* void install_schedule_handlers(IF_Module_t *if_inst) @@ -406,14 +444,23 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, //gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED; gNB->mac_enabled = 1; - fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); - fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); - fp->nr_band = 78; -// fp->threequarter_fs= 0; + if (mu==1) { + fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->nr_band = 78; + // fp->threequarter_fs= 0; + } else if (mu==3) { + fp->dl_CarrierFreq = 27524520000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 27524520000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->nr_band = 261; + // fp->threequarter_fs= 0; + } + fp->threequarter_fs = 0; gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band); nr_init_frame_parms(gNB_config, fp); + fp->ofdm_offset_divisor = UINT_MAX; gNB->configured = 1; LOG_I(PHY,"gNB configured\n"); } @@ -425,51 +472,20 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id]->frame_parms; nfapi_nr_config_request_scf_t *gNB_config = &RC.gNB[Mod_id]->gNB_config; - /* - gNB_config->cell_config.phy_cell_id.value = phy_config->cfg->cell_config.phy_cell_id.value; - gNB_config->carrier_config.dl_frequency.value = phy_config->cfg->carrier_config.dl_frequency.value; - gNB_config->carrier_config.uplink_frequency.value = phy_config->cfg->carrier_config.uplink_frequency.value; - gNB_config->ssb_config.scs_common.value = phy_config->cfg->ssb_config.scs_common.value; - gNB_config->carrier_config.dl_bandwidth.value = phy_config->cfg->carrier_config.dl_bandwidth.value; - gNB_config->carrier_config.uplink_bandwidth.value = phy_config->cfg->carrier_config.uplink_bandwidth.value; - gNB_config->ssb_table.ssb_subcarrier_offset.value = phy_config->cfg->ssb_table.ssb_subcarrier_offset.value; - gNB_config->ssb_table.ssb_offset_point_a.value = phy_config->cfg->ssb_table.ssb_offset_point_a.value; - gNB_config->ssb_table.ssb_mask_list[0].ssb_mask.value = phy_config->cfg->ssb_table.ssb_mask_list[0].ssb_mask.value; - gNB_config->ssb_table.ssb_mask_list[1].ssb_mask.value = phy_config->cfg->ssb_table.ssb_mask_list[1].ssb_mask.value; - gNB_config->ssb_table.ssb_period.value = phy_config->cfg->ssb_table.ssb_period.value; - for (int i=0; i<5; i++) { - gNB_config->carrier_config.dl_grid_size[i].value = phy_config->cfg->carrier_config.dl_grid_size[i].value; - gNB_config->carrier_config.ul_grid_size[i].value = phy_config->cfg->carrier_config.ul_grid_size[i].value; - gNB_config->carrier_config.dl_k0[i].value = phy_config->cfg->carrier_config.dl_k0[i].value; - gNB_config->carrier_config.ul_k0[i].value = phy_config->cfg->carrier_config.ul_k0[i].value; - } - - - if (phy_config->cfg->cell_config.frame_duplex_type.value == 0) { - gNB_config->cell_config.frame_duplex_type.value = FDD; - } else { - gNB_config->cell_config.frame_duplex_type.value = TDD; - } - - memcpy((void*)&gNB_config->prach_config,(void*)&phy_config->cfg->prach_config,sizeof(phy_config->cfg->prach_config)); - memcpy((void*)&gNB_config->tdd_table,(void*)&phy_config->cfg->tdd_table,sizeof(phy_config->cfg->tdd_table)); - */ memcpy((void*)gNB_config,phy_config->cfg,sizeof(*phy_config->cfg)); RC.gNB[Mod_id]->mac_enabled = 1; uint64_t dl_bw_khz = (12*gNB_config->carrier_config.dl_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<ssb_config.scs_common.value); fp->dl_CarrierFreq = ((dl_bw_khz>>1) + gNB_config->carrier_config.dl_frequency.value)*1000 ; - - int32_t dlul_offset = 0; - lte_frame_type_t frame_type = 0; - get_band(fp->dl_CarrierFreq,&fp->nr_band,&dlul_offset,&frame_type); - uint64_t ul_bw_khz = (12*gNB_config->carrier_config.ul_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<ssb_config.scs_common.value); fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ; - AssertFatal(fp->ul_CarrierFreq==(fp->dl_CarrierFreq+dlul_offset), "Disagreement in uplink frequency for band %d\n", fp->nr_band); - + int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; + fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset); + + LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset); + fp->threequarter_fs = openair0_cfg[0].threequarter_fs; LOG_I(PHY,"Configuring MIB for instance %d, : (Nid_cell %d,DL freq %llu, UL freq %llu)\n", Mod_id, @@ -488,44 +504,53 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { fd_occasion = 0; nfapi_nr_prach_config_t *prach_config = &gNB_config->prach_config; short_sequence = prach_config->prach_sequence_length.value; +// for(fd_occasion = 0; fd_occasion <= prach_config->num_prach_fd_occasions.value ; fd_occasion) { // TODO Need to handle for msg1-fdm > 1 num_sequences = prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value; rootSequenceIndex = prach_config->num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index.value; compute_nr_prach_seq(short_sequence, num_sequences, rootSequenceIndex, RC.gNB[Mod_id]->X_u); - +// } RC.gNB[Mod_id]->configured = 1; + + fp->ofdm_offset_divisor = RC.gNB[Mod_id]->ofdm_offset_divisor; + init_symbol_rotation(fp); + init_timeshift_rotation(fp); + LOG_I(PHY,"gNB %d configured\n",Mod_id); } -void init_nr_transport(PHY_VARS_gNB *gNB) { - int i; - int j; +void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) { NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - LOG_I(PHY, "Initialise nr transport\n"); uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value; + msg->num_pdsch_slot = 0; - for (i=0; inumber_of_nr_dlsch_max; i++) { + LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n",i,gNB->number_of_nr_dlsch_max); + for (int j=0; j<2; j++) { + msg->dlsch[i][j] = new_gNB_dlsch(fp,1,16,NSOFT,0,grid_size); + AssertFatal(msg->dlsch[i][j]!=NULL,"Can't initialize dlsch %d \n", i); + } + } +} + +void init_nr_transport(PHY_VARS_gNB *gNB) { + NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + LOG_I(PHY, "Initialise nr transport\n"); + + memset(gNB->num_pdsch_rnti, 0, sizeof(uint16_t)*80); + + for (int i=0; ipucch[i] = new_gNB_pucch(); AssertFatal(gNB->pucch[i]!=NULL,"Can't initialize pucch %d \n", i); } - for (i=0; inumber_of_nr_ulsch_max; i++) { - LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n",i,NUMBER_OF_NR_DLSCH_MAX); + LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH %d/%d\n",i,gNB->number_of_nr_ulsch_max); - for (j=0; j<2; j++) { - gNB->dlsch[i][j] = new_gNB_dlsch(fp,1,16,NSOFT,0,grid_size); - AssertFatal(gNB->dlsch[i][j]!=NULL,"Can't initialize dlsch %d \n", i); - } - } - - for (i=0; iulsch[i][j] = new_gNB_ulsch(MAX_LDPC_ITERATIONS, fp->N_RB_UL, 0); @@ -534,27 +559,6 @@ void init_nr_transport(PHY_VARS_gNB *gNB) { exit(-1); } - /* - LOG_I(PHY,"Initializing nFAPI for ULSCH, UE %d\n",i); - // [hna] added here for RT implementation - uint8_t harq_pid = 0; - nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &gNB->ulsch[i+1][j]->harq_processes[harq_pid]->ulsch_pdu; - - // --------- setting rel15_ul parameters ---------- - rel15_ul->rnti = 0x1234; - rel15_ul->ulsch_pdu_rel15.start_rb = 0; - rel15_ul->ulsch_pdu_rel15.number_rbs = 50; - rel15_ul->ulsch_pdu_rel15.start_symbol = 2; - rel15_ul->ulsch_pdu_rel15.number_symbols = 12; - rel15_ul->ulsch_pdu_rel15.length_dmrs = gNB->dmrs_UplinkConfig.pusch_maxLength; - rel15_ul->ulsch_pdu_rel15.Qm = 2; - rel15_ul->ulsch_pdu_rel15.R = 679; - rel15_ul->ulsch_pdu_rel15.mcs = 9; - rel15_ul->ulsch_pdu_rel15.rv = 0; - rel15_ul->ulsch_pdu_rel15.n_layers = 1; - /////////////////////////////////////////////////// - */ - } } diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 28b13112ce..4024ed1617 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -21,9 +21,6 @@ #include "phy_init.h" #include "SCHED/sched_common.h" -#include "PHY/phy_extern.h" -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" -#include "SIMULATION/TOOLS/sim.h" /*#include "RadioResourceConfigCommonSIB.h" #include "RadioResourceConfigDedicated.h" #include "TDD-Config.h" @@ -33,6 +30,10 @@ #include #include "openair1/PHY/defs_RU.h" +void init_prach_ru_list(RU_t *ru); + +extern const char ru_if_types[MAX_RU_IF_TYPES][20]; + int nr_phy_init_RU(RU_t *ru) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; @@ -44,7 +45,7 @@ int nr_phy_init_RU(RU_t *ru) { nfapi_nr_config_request_scf_t *cfg; ru->nb_log_antennas=0; - for (int n=0;nnum_gNB;n++) { cfg = &ru->config; if (cfg->carrier_config.num_tx_ant.value > ru->nb_log_antennas) ru->nb_log_antennas = cfg->carrier_config.num_tx_ant.value; } @@ -59,10 +60,12 @@ int nr_phy_init_RU(RU_t *ru) { for (i=0; inb_tx; i++) { // Allocate 10 subframes of I/Q TX signal data (time) if not - ru->common.txdata[i] = (int32_t*)malloc16_clear( fp->samples_per_frame*sizeof(int32_t) ); + ru->common.txdata[i] = (int32_t*)malloc16_clear( ru->sf_extension + (fp->samples_per_frame*sizeof(int32_t) )); + LOG_I(PHY,"[INIT] common.txdata[%d] = %p (%lu bytes,sf_extension %d)\n",i,ru->common.txdata[i], + (ru->sf_extension + fp->samples_per_frame)*sizeof(int32_t),ru->sf_extension); + ru->common.txdata[i] = &ru->common.txdata[i][ru->sf_extension]; - LOG_I(PHY,"[INIT] common.txdata[%d] = %p (%lu bytes)\n",i,ru->common.txdata[i], - fp->samples_per_frame*sizeof(int32_t)); + LOG_I(PHY,"[INIT] common.txdata[%d] = %p \n",i,ru->common.txdata[i]); } for (i=0;inb_rx;i++) { @@ -99,50 +102,61 @@ int nr_phy_init_RU(RU_t *ru) { // allocate FFT output buffers (RX) ru->common.rxdataF = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) ); for (i=0; inb_rx; i++) { - // allocate 2 subframes of I/Q signal data (frequency) - ru->common.rxdataF[i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(2*fp->samples_per_subframe_wCP) ); + // allocate 4 slots of I/Q signal data (frequency) + ru->common.rxdataF[i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(4*fp->symbols_per_slot*fp->ofdm_symbol_size) ); LOG_I(PHY,"rxdataF[%d] %p for RU %d\n",i,ru->common.rxdataF[i],ru->idx); } /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */ // AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]), // "nb_antennas_rx too large"); - ru->prach_rxsigF = (int16_t**)malloc(ru->nb_rx * sizeof(int16_t*)); - - for (i=0; inb_rx; i++) { - // largest size for PRACH FFT is 4x98304 (16*24576) - ru->prach_rxsigF[i] = (int16_t*)malloc16_clear( 4*98304*2*sizeof(int16_t) ); - LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[i]); + for (j=0;jprach_rxsigF[j] = (int16_t**)malloc(ru->nb_rx * sizeof(int16_t*)); + + for (i=0; inb_rx; i++) { + // largest size for PRACH FFT is 4x98304 (16*24576) + ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear( 4*98304*2*sizeof(int16_t) ); + LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[j][i]); + } } - AssertFatal(RC.nb_nr_L1_inst <= NUMBER_OF_eNB_MAX,"gNB instances %d > %d\n", - RC.nb_nr_L1_inst,NUMBER_OF_gNB_MAX); + AssertFatal(ru->num_gNB <= NUMBER_OF_gNB_MAX,"gNB instances %d > %d\n", + ru->num_gNB,NUMBER_OF_gNB_MAX); - LOG_E(PHY,"[INIT] %s() RC.nb_nr_L1_inst:%d \n", __FUNCTION__, RC.nb_nr_L1_inst); - - int beam_count = 0; - if (ru->nb_tx>1) {//Enable beamforming when nb_tx > 1 - for (p=0;pnb_log_antennas;p++) { - if ((fp->L_ssb >> (63-p)) & 0x01)//64 bit-map with the MSB @2â�¶Â³ corresponds to SSB ssb_index 0 - beam_count++; - } - AssertFatal(ru->nb_bfw==(beam_count*ru->nb_tx),"Number of beam weights from config file is %d while the expected number is %d",ru->nb_bfw,(beam_count*ru->nb_tx)); - - int l_ind = 0; - for (i=0; inum_gNB:%d \n", __FUNCTION__, ru->num_gNB); + + if (ru->do_precoding == 1) { + int beam_count = 0; + if (ru->nb_tx>1) {//Enable beamforming when nb_tx > 1 for (p=0;pnb_log_antennas;p++) { - if ((fp->L_ssb >> (63-p)) & 0x01) { - ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*)); - for (j=0; jnb_tx; j++) { - ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t)); - for (re=0; reofdm_symbol_size; re++) - ru->beam_weights[i][p][j][re] = ru->bw_list[i][l_ind]; - //printf("Beam Weight %08x for beam %d and tx %d\n",ru->bw_list[i][l_ind],p,j); - l_ind++; - } // for j - } // for p + //if ((fp->L_ssb >> (63-p)) & 0x01)//64 bit-map with the MSB @2â�¶Â³ corresponds to SSB ssb_index 0 + beam_count++; } + AssertFatal(ru->nb_bfw==(beam_count*ru->nb_tx),"Number of beam weights from config file is %d while the expected number is %d",ru->nb_bfw,(beam_count*ru->nb_tx)); + + for (i=0; inum_gNB; i++) { + int l_ind = 0; + for (p=0;pnb_log_antennas;p++) { + //if ((fp->L_ssb >> (63-p)) & 0x01) { + ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*)); + for (j=0; jnb_tx; j++) { + ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t)); + AssertFatal(ru->bw_list[i],"ru->bw_list[%d] is null\n",i); + for (re=0; reofdm_symbol_size; re++) + ru->beam_weights[i][p][j][re] = ru->bw_list[i][l_ind]; + //printf("Beam Weight %08x for beam %d and tx %d\n",ru->bw_list[i][l_ind],p,j); + l_ind++; + } // for j + //} + } // for p } //for i + } + + ru->common.beam_id = (uint8_t**)malloc16_clear(ru->nb_tx*sizeof(uint8_t*)); + for(i=0; i< ru->nb_tx; ++i) { + ru->common.beam_id[i] = (uint8_t*)malloc16_clear(fp->symbols_per_slot*fp->slots_per_frame*sizeof(uint8_t)); + memset(ru->common.beam_id[i],255,fp->symbols_per_slot*fp->slots_per_frame); + } } } // !=IF5 @@ -164,7 +178,11 @@ void nr_phy_free_RU(RU_t *ru) free_and_zero(ru->frame_parms); if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals - for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdata[i]); + int32_t *ptr; + for (i = 0; i < ru->nb_tx; i++) { + ptr=&ru->common.txdata[i][-ru->sf_extension]; + free_and_zero(ptr); + } for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdata[i]); free_and_zero(ru->common.txdata); free_and_zero(ru->common.rxdata); @@ -186,11 +204,12 @@ void nr_phy_free_RU(RU_t *ru) for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdataF[i]); free_and_zero(ru->common.rxdataF); - for (i = 0; i < ru->nb_rx; i++) { - free_and_zero(ru->prach_rxsigF[i]); + for (j=0;jnb_rx; i++) { + free_and_zero(ru->prach_rxsigF[j][i]); + } } - - for (i = 0; i < RC.nb_nr_L1_inst; i++) { + for (i = 0; i < ru->num_gNB; i++) { for (p = 0; p < 15; p++) { for (j=0; jnb_tx; j++) free_and_zero(ru->beam_weights[i][p][j]); free_and_zero(ru->beam_weights[i][p]); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index fed58dea12..f664a03ba0 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -28,6 +28,7 @@ #include "TDD-Config.h" #include "MBSFN-SubframeConfigList.h"*/ #include "openair1/PHY/defs_RU.h" +#include "openair1/PHY/impl_defs_nr.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "assertions.h" #include @@ -41,543 +42,22 @@ #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/NR_REFSIG/nr_refsig.h" -//uint8_t dmrs1_tab_ue[8] = {0,2,3,4,6,8,9,10}; - -/*void phy_config_sib1_ue(uint8_t Mod_id,int CC_id, - uint8_t eNB_id, - TDD_Config_t *tdd_Config, - uint8_t SIwindowsize, - uint16_t SIperiod) -{ - - NR_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; - - if (tdd_Config) { - fp->tdd_config = tdd_Config->subframeAssignment; - fp->tdd_config_S = tdd_Config->specialSubframePatterns; - } - - fp->SIwindowsize = SIwindowsize; - fp->SIPeriod = SIperiod; -} - -void phy_config_sib2_ue(uint8_t Mod_id,int CC_id, - uint8_t eNB_id, - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, - ARFCN_ValueEUTRA_t *ul_CarrierFreq, - long *ul_Bandwidth, - AdditionalSpectrumEmission_t *additionalSpectrumEmission, - struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList) -{ - - PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - int i; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_IN); - - LOG_I(PHY,"[UE%d] Applying radioResourceConfigCommon from eNB%d\n",Mod_id,eNB_id); - - ue->prach_vars[eNB_id]->prach_pdu.root_seq_id =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - - ue->prach_vars[eNB_id]->prach_Config_enabled=1; - //ue->prach_vars[eNB_id]->prach_pdu.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; - ue->prach_vars[eNB_id]->prach_pdu.restricted_set =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; - ue->prach_vars[eNB_id]->prach_pdu.num_cs =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; - //ue->prach_vars[eNB_id]->prach_pdu.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; - - //compute_prach_seq(fp->prach_config_common.rootSequenceIndex, - // fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - // fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - // fp->prach_config_common.prach_ConfigInfo.highSpeedFlag, - // fp->frame_type,ue->X_u); - - - - fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; - fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; - fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; - fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; - - - - fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; - fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; - - - fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab_ue[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; - - - init_ul_hopping(fp); - fp->soundingrs_ul_config_common.enabled_flag = 0; - - if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) { - fp->soundingrs_ul_config_common.enabled_flag = 1; - fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; - fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; - fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; - - if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) - fp->soundingrs_ul_config_common.srs_MaxUpPts = 1; - else - fp->soundingrs_ul_config_common.srs_MaxUpPts = 0; - } - - - - fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; - fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; - fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; - fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; - fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; - fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; - - fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; - - // Now configure some of the Physical Channels - - // PUCCH - init_ncs_cell(fp,ue->ncs_cell); - - init_ul_hopping(fp); - - // PCH - init_ue_paging_info(ue,radioResourceConfigCommon->pcch_Config.defaultPagingCycle,radioResourceConfigCommon->pcch_Config.nB); - - // MBSFN - - if (mbsfn_SubframeConfigList != NULL) { - fp->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; - - for (i=0; ilist.count; i++) { - fp->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; - fp->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; - - if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { - fp->MBSFN_config[i].fourFrames_flag = 0; - fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration - LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i, - fp->MBSFN_config[i].mbsfn_SubframeConfig); - } else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration - fp->MBSFN_config[i].fourFrames_flag = 1; - fp->MBSFN_config[i].mbsfn_SubframeConfig = - mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]| - (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)| - (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]<<16); - - LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i, - fp->MBSFN_config[i].mbsfn_SubframeConfig); - } - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_OUT); - -} - -void phy_config_sib13_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,int mbsfn_Area_idx, - long mbsfn_AreaId_r9) -{ - - NR_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; - - - LOG_I(PHY,"[UE%d] Applying MBSFN_Area_id %ld for index %d\n",Mod_id,mbsfn_AreaId_r9,mbsfn_Area_idx); - - if (mbsfn_Area_idx == 0) { - fp->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; - LOG_N(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n"); - } - - lte_gold_mbsfn(fp,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_mbsfn_table,fp->Nid_cell_mbsfn); - -}*/ - - -/* - * Configures UE MAC and PHY with radioResourceCommon received in mobilityControlInfo IE during Handover - */ -/*void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, MobilityControlInfo_t *mobilityControlInfo, uint8_t ho_failed) -{ - - if(mobilityControlInfo!=NULL) { - RadioResourceConfigCommon_t *radioResourceConfigCommon = &mobilityControlInfo->radioResourceConfigCommon; - LOG_I(PHY,"radioResourceConfigCommon %p\n", radioResourceConfigCommon); - memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms_before_ho, - (void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms, - sizeof(NR_DL_FRAME_PARMS)); - PHY_vars_UE_g[Mod_id][CC_id]->ho_triggered = 1; - //PHY_vars_UE_g[UE_id]->UE_mode[0] = PRACH; - - NR_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; - // int N_ZC; - // uint8_t prach_fmt; - // int u; - - LOG_I(PHY,"[UE%d] Handover triggered: Applying radioResourceConfigCommon from eNB %d\n", - Mod_id,eNB_id); - - ue->prach_vars[eNB_id]->prach_pdu.root_seq_id =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - ue->prach_vars[eNB_id]->prach_Config_enabled=1; - //ue->prach_vars[eNB_id]->prach_pdu.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex; - ue->prach_vars[eNB_id]->prach_pdu.restricted_set =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->highSpeedFlag; - ue->prach_vars[eNB_id]->prach_pdu.num_cs =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->zeroCorrelationZoneConfig; - //ue->prach_vars[eNB_id]->prach_pdu.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_FreqOffset; - - // prach_fmt = get_prach_fmt(radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex,fp->frame_type); - // N_ZC = (prach_fmt <4)?839:139; - // u = (prach_fmt < 4) ? prach_root_sequence_map0_3[fp->prach_config_common.rootSequenceIndex] : - // prach_root_sequence_map4[fp->prach_config_common.rootSequenceIndex]; - - //compute_prach_seq(u,N_ZC, PHY_vars_UE_g[Mod_id]->X_u); - //compute_prach_seq(PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex, - // PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - // PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - // PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag, - // fp->frame_type, - // PHY_vars_UE_g[Mod_id][CC_id]->X_u); - - - fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon->deltaPUCCH_Shift; - fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon->nRB_CQI; - fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon->nCS_AN; - fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon->n1PUCCH_AN; - fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon->referenceSignalPower; - fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon->p_b; - - - fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift; - - init_ul_hopping(fp); - fp->soundingrs_ul_config_common.enabled_flag = 0; - - if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->present==SoundingRS_UL_ConfigCommon_PR_setup) { - fp->soundingrs_ul_config_common.enabled_flag = 1; - fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_BandwidthConfig; - fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig; - fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.ackNackSRS_SimultaneousTransmission; - - if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_MaxUpPts) - fp->soundingrs_ul_config_common.srs_MaxUpPts = 1; - else - fp->soundingrs_ul_config_common.srs_MaxUpPts = 0; - } - - fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUSCH; - fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon->alpha; - fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUCCH; - fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaPreambleMsg3; - fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1; - fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1b; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2a; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2b; - - fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon->maxHARQ_Msg3Tx; - - // Now configure some of the Physical Channels - if (radioResourceConfigCommon->antennaInfoCommon) - fp->nb_antennas_tx = (1<antennaInfoCommon->antennaPortsCount); - else - fp->nb_antennas_tx = 1; - - //PHICH - if (radioResourceConfigCommon->antennaInfoCommon) { - fp->phich_config_common.phich_resource = radioResourceConfigCommon->phich_Config->phich_Resource; - fp->phich_config_common.phich_duration = radioResourceConfigCommon->phich_Config->phich_Duration; - } - - //Target CellId - fp->Nid_cell = mobilityControlInfo->targetPhysCellId; - fp->nushift = fp->Nid_cell%6; - - // PUCCH - init_ncs_cell(fp,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); - - init_ul_hopping(fp); - - // RNTI - - - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); - - LOG_I(PHY,"SET C-RNTI %x %x\n",PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_id]->crnti, - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_id]->crnti); - } - - if(ho_failed) { - LOG_D(PHY,"[UE%d] Handover failed, triggering RACH procedure\n",Mod_id); - memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms,(void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms_before_ho, sizeof(NR_DL_FRAME_PARMS)); - PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_id] = PRACH; - } -} - - -void phy_config_meas_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,uint8_t n_adj_cells,unsigned int *adj_cell_id) -{ - - PHY_NR_MEASUREMENTS *phy_meas = &PHY_vars_UE_g[Mod_id][CC_id]->measurements; - int i; - - LOG_I(PHY,"Configuring inter-cell measurements for %d cells, ids: \n",n_adj_cells); - - for (i=0; iframe_parms,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_table[i+1],adj_cell_id[i]); - } - - phy_meas->n_adj_cells = n_adj_cells; - memcpy((void*)phy_meas->adj_cell_id,(void *)adj_cell_id,n_adj_cells*sizeof(unsigned int)); - -} -*/ - -#if defined(Rel10) || defined(Rel14) -void phy_config_dedicated_scell_ue(uint8_t Mod_id, - uint8_t eNB_index, - SCellToAddMod_r10_t *sCellToAddMod_r10, - int CC_id) { -} -#endif - #if 0 void phy_config_harq_ue(module_id_t Mod_id, int CC_id, - uint8_t eNB_id, + uint8_t gNB_id, uint16_t max_harq_tx) { int num_of_threads,num_of_code_words; PHY_VARS_NR_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; for (num_of_threads=0; num_of_threadsulsch[num_of_threads][eNB_id][num_of_code_words]->Mlimit = max_harq_tx; + phy_vars_ue->ulsch[num_of_threads][gNB_id][num_of_code_words]->Mlimit = max_harq_tx; } #endif extern uint16_t beta_cqi[16]; -/* -void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id, - struct PhysicalConfigDedicated *physicalConfigDedicated ) -{ - - static uint8_t first_dedicated_configuration = 0; - PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; - - phy_vars_ue->total_TBS[eNB_id]=0; - phy_vars_ue->total_TBS_last[eNB_id]=0; - phy_vars_ue->bitrate[eNB_id]=0; - phy_vars_ue->total_received_bits[eNB_id]=0; - phy_vars_ue->dlsch_errors[eNB_id]=0; - phy_vars_ue->dlsch_errors_last[eNB_id]=0; - phy_vars_ue->dlsch_received[eNB_id]=0; - phy_vars_ue->dlsch_received_last[eNB_id]=0; - phy_vars_ue->dlsch_fer[eNB_id]=0; - - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1; - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1; - - if (physicalConfigDedicated) { - LOG_D(PHY,"[UE %d] Received physicalConfigDedicated from eNB %d\n",Mod_id, eNB_id); - LOG_D(PHY,"------------------------------------------------------------------------\n"); - - if (physicalConfigDedicated->pdsch_ConfigDedicated) { - phy_vars_ue->pdsch_config_dedicated[eNB_id].p_a=physicalConfigDedicated->pdsch_ConfigDedicated->p_a; - LOG_D(PHY,"pdsch_config_dedicated.p_a %d\n",phy_vars_ue->pdsch_config_dedicated[eNB_id].p_a); - LOG_D(PHY,"\n"); - } - - if (physicalConfigDedicated->pucch_ConfigDedicated) { - if (physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.present==PUCCH_ConfigDedicated__ackNackRepetition_PR_release) - phy_vars_ue->pucch_config_dedicated[eNB_id].ackNackRepetition=0; - else { - phy_vars_ue->pucch_config_dedicated[eNB_id].ackNackRepetition=1; - } - - if (physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode) - phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode = *physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode; - else - phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode = bundling; - - if ( phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode == multiplexing) - LOG_D(PHY,"pucch_config_dedicated.tdd_AckNackFeedbackMode = multiplexing\n"); - else - LOG_D(PHY,"pucch_config_dedicated.tdd_AckNackFeedbackMode = bundling\n"); - } - - if (physicalConfigDedicated->pusch_ConfigDedicated) { - phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index; - phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_RI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index; - phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index; - - - LOG_D(PHY,"pusch_config_dedicated.betaOffset_ACK_Index %d\n",phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index); - LOG_D(PHY,"pusch_config_dedicated.betaOffset_RI_Index %d\n",phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_RI_Index); - LOG_D(PHY,"pusch_config_dedicated.betaOffset_CQI_Index %d => %d)\n",phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index,beta_cqi[phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index]); - LOG_D(PHY,"\n"); - - - } - - if (physicalConfigDedicated->uplinkPowerControlDedicated) { - - phy_vars_ue->ul_power_control_dedicated[eNB_id].p0_UE_PUSCH = physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUSCH; - phy_vars_ue->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled= physicalConfigDedicated->uplinkPowerControlDedicated->deltaMCS_Enabled; - phy_vars_ue->ul_power_control_dedicated[eNB_id].accumulationEnabled= physicalConfigDedicated->uplinkPowerControlDedicated->accumulationEnabled; - phy_vars_ue->ul_power_control_dedicated[eNB_id].p0_UE_PUCCH= physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUCCH; - phy_vars_ue->ul_power_control_dedicated[eNB_id].pSRS_Offset= physicalConfigDedicated->uplinkPowerControlDedicated->pSRS_Offset; - phy_vars_ue->ul_power_control_dedicated[eNB_id].filterCoefficient= *physicalConfigDedicated->uplinkPowerControlDedicated->filterCoefficient; - LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUSCH %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].p0_UE_PUSCH); - LOG_D(PHY,"ul_power_control_dedicated.deltaMCS_Enabled %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled); - LOG_D(PHY,"ul_power_control_dedicated.accumulationEnabled %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].accumulationEnabled); - LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUCCH %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].p0_UE_PUCCH); - LOG_D(PHY,"ul_power_control_dedicated.pSRS_Offset %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].pSRS_Offset); - LOG_D(PHY,"ul_power_control_dedicated.filterCoefficient %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].filterCoefficient); - LOG_D(PHY,"\n"); - } - - if (physicalConfigDedicated->antennaInfo) { - phy_vars_ue->transmission_mode[eNB_id] = 1+(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode); - LOG_I(PHY,"Transmission Mode %d\n",phy_vars_ue->transmission_mode[eNB_id]); - switch(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode) { - case AntennaInfoDedicated__transmissionMode_tm1: - phy_vars_ue->transmission_mode[eNB_id] = 1; - break; - case AntennaInfoDedicated__transmissionMode_tm2: - phy_vars_ue->transmission_mode[eNB_id] = 2; - break; - case AntennaInfoDedicated__transmissionMode_tm3: - phy_vars_ue->transmission_mode[eNB_id] = 3; - break; - case AntennaInfoDedicated__transmissionMode_tm4: - phy_vars_ue->transmission_mode[eNB_id] = 4; - break; - case AntennaInfoDedicated__transmissionMode_tm5: - phy_vars_ue->transmission_mode[eNB_id] = 5; - break; - case AntennaInfoDedicated__transmissionMode_tm6: - phy_vars_ue->transmission_mode[eNB_id] = 6; - break; - case AntennaInfoDedicated__transmissionMode_tm7: - lte_gold_ue_spec_port5(phy_vars_ue->lte_gold_uespec_port5_table, phy_vars_ue->frame_parms.Nid_cell, phy_vars_ue->pdcch_vars[0][eNB_id]->crnti); - phy_vars_ue->transmission_mode[eNB_id] = 7; - break; - default: - LOG_E(PHY,"Unknown transmission mode!\n"); - break; - } - } else { - LOG_D(PHY,"[UE %d] Received NULL physicalConfigDedicated->antennaInfo from eNB %d\n",Mod_id, eNB_id); - } - - if (physicalConfigDedicated->schedulingRequestConfig) { - if (physicalConfigDedicated->schedulingRequestConfig->present == SchedulingRequestConfig_PR_setup) { - phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex = physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex; - phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex=physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_ConfigIndex; - phy_vars_ue->scheduling_request_config[eNB_id].dsr_TransMax=physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax; - - LOG_D(PHY,"scheduling_request_config.sr_PUCCH_ResourceIndex %d\n",phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - LOG_D(PHY,"scheduling_request_config.sr_ConfigIndex %d\n",phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex); - LOG_D(PHY,"scheduling_request_config.dsr_TransMax %d\n",phy_vars_ue->scheduling_request_config[eNB_id].dsr_TransMax); - } - - LOG_D(PHY,"------------------------------------------------------------\n"); - - } - - if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated) { - - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = 0; - if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) { - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = 1; - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].duration = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.duration; - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].cyclicShift = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift; - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].freqDomainPosition = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition; - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_Bandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth; - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex; - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_HoppingBandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth; - phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].transmissionComb = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb; - - - LOG_D(PHY,"soundingrs_ul_config_dedicated.srs_ConfigIndex %d\n",phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex); - } - - LOG_D(PHY,"------------------------------------------------------------\n"); - - } - - - if (physicalConfigDedicated->cqi_ReportConfig) { - if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic) { - // configure PUSCH CQI reporting - phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic; - if ((phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm12) && - (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm30) && - (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm31)) - LOG_E(PHY,"Unsupported Aperiodic CQI Feedback Mode : %d\n",phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic); - } - if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) { - if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_setup) { - // configure PUCCH CQI reporting - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex; - if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex) - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex; - } - else if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_release) { - // handle release - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1; - phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1; - } - } - } - - } else { - LOG_D(PHY,"[PHY][UE %d] Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id,eNB_id); - return; - } - - // fill cqi parameters for periodic CQI reporting - get_cqipmiri_params(phy_vars_ue,eNB_id); - - // disable MIB SIB decoding once we are on connected mode - first_dedicated_configuration ++; - if(first_dedicated_configuration > 1) - { - LOG_I(PHY,"Disable SIB MIB decoding \n"); - phy_vars_ue->decode_SIB = 0; - phy_vars_ue->decode_MIB = 0; - } - //phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti; - if(phy_vars_ue->pdcch_vars[0][eNB_id]->crnti == 0x1234) - phy_vars_ue->pdcch_vars[0][eNB_id]->crnti = phy_vars_ue->pdcch_vars[1][eNB_id]->crnti; - else - phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti; - - LOG_I(PHY,"C-RNTI %x %x \n", phy_vars_ue->pdcch_vars[0][eNB_id]->crnti, - phy_vars_ue->pdcch_vars[1][eNB_id]->crnti); - - -}*/ - /*! \brief Helper function to allocate memory for DLSCH data structures. * \param[out] pdsch Pointer to the LTE_UE_PDSCH structure to initialize. * \param[in] frame_parms LTE_DL_FRAME_PARMS structure. @@ -592,29 +72,39 @@ void phy_init_nr_ue__PDSCH(NR_UE_PDSCH *const pdsch, pdsch->llr128 = (int16_t **)malloc16_clear( sizeof(int16_t *) ); // FIXME! no further allocation for (int16_t*)pdsch->llr128 !!! expect SIGSEGV // FK, 11-3-2015: this is only as a temporary pointer, no memory is stored there - pdsch->rxdataF_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pdsch->rxdataF_uespec_pilots = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pdsch->rxdataF_comp0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pdsch->rho = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) ); - pdsch->dl_ch_estimates = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pdsch->dl_ch_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pdsch->dl_bf_ch_estimates = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pdsch->dl_bf_ch_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + pdsch->rxdataF_ext = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->rxdataF_uespec_pilots = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->rxdataF_comp0 = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->rho = (int32_t ***)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t **) ); + pdsch->dl_ch_estimates = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->dl_ch_estimates_ext = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->dl_bf_ch_estimates = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->dl_bf_ch_estimates_ext = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) ); //pdsch->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); //pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); - pdsch->dl_ch_mag0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pdsch->dl_ch_magb0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + pdsch->dl_ch_mag0 = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->dl_ch_magb0 = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->dl_ch_magr0 = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->ptrs_phase_per_slot = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->ptrs_re_per_slot = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) ); + pdsch->dl_ch_ptrs_estimates_ext = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) ); // the allocated memory size is fixed: - AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" ); + AssertFatal( fp->nb_antennas_rx <= 4, "nb_antennas_rx > 4" );//Extend the max number of UE Rx antennas to 4 + const size_t num = 7*2*fp->N_RB_DL*12; for (int i=0; inb_antennas_rx; i++) { - pdsch->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*7*2) ); + pdsch->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + pdsch->rxdataF_uespec_pilots[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * fp->N_RB_DL*12); + pdsch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * 14 ); + pdsch->ptrs_re_per_slot[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * 14); + pdsch->dl_ch_ptrs_estimates_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t) * num); + pdsch->rho[i] = (int32_t **)malloc16_clear( NR_MAX_NB_LAYERS*NR_MAX_NB_LAYERS*sizeof(int32_t *) ); - for (int j=0; j<4; j++) { //fp->nb_antennas_tx; j++) - const int idx = (j<<1)+i; - const size_t num = 7*2*fp->N_RB_DL*12; - pdsch->rxdataF_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); - pdsch->rxdataF_uespec_pilots[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * fp->N_RB_DL*12); + for (int j=0; jnb_antennas_rx)+i; + for (int k=0; krho[i][j*NR_MAX_NB_LAYERS+k] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + } pdsch->rxdataF_comp0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * fp->ofdm_symbol_size*7*2); pdsch->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); @@ -624,6 +114,7 @@ void phy_init_nr_ue__PDSCH(NR_UE_PDSCH *const pdsch, //pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_ch_mag0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_ch_magb0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + pdsch->dl_ch_magr0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); } } } @@ -633,39 +124,31 @@ void phy_init_nr_ue_PUSCH(NR_UE_PUSCH *const pusch, AssertFatal( pusch, "pusch==0" ); for (int i=0; itxdataF_layers[i] = (int32_t *)malloc16_clear((NR_MAX_PUSCH_ENCODED_LENGTH)*sizeof(int32_t *)); + pusch->txdataF_layers[i] = (int32_t *)malloc16_clear(NR_MAX_PUSCH_ENCODED_LENGTH*sizeof(int32_t)); } } int init_nr_ue_signal(PHY_VARS_NR_UE *ue, - int nb_connected_eNB, + int nb_connected_gNB, uint8_t abstraction_flag) { // create shortcuts NR_DL_FRAME_PARMS *const fp = &ue->frame_parms; NR_UE_COMMON *const common_vars = &ue->common_vars; - NR_UE_PDSCH **const pdsch_vars_SI = ue->pdsch_vars_SI; - NR_UE_PDSCH **const pdsch_vars_ra = ue->pdsch_vars_ra; - NR_UE_PDSCH **const pdsch_vars_p = ue->pdsch_vars_p; - NR_UE_PDSCH **const pdsch_vars_mch = ue->pdsch_vars_MCH; NR_UE_PBCH **const pbch_vars = ue->pbch_vars; NR_UE_PRACH **const prach_vars = ue->prach_vars; int i,j,k,l,slot,symb,q; - int eNB_id; + int gNB_id; int th_id; uint32_t ****pusch_dmrs; uint16_t N_n_scid[2] = {0,1}; // [HOTFIX] This is a temporary implementation of scramblingID0 and scramblingID1 which are given by DMRS-UplinkConfig int n_scid; abstraction_flag = 0; - fp->nb_antennas_tx = 1; - fp->nb_antennas_rx=1; - // dmrs_UplinkConfig_t *dmrs_Uplink_Config = &ue->pusch_config.dmrs_UplinkConfig; - // ptrs_UplinkConfig_t *ptrs_Uplink_Config = &ue->pusch_config.dmrs_UplinkConfig.ptrs_UplinkConfig; - printf("Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,fp->nb_antennas_tx,fp->nb_antennas_rx); - //LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_UE][MOD %02u][]\n", ue->Mod_id+NB_eNB_INST); + LOG_I(PHY, "Initializing UE vars (abstraction %u) for gNB TXant %u, UE RXant %u\n", abstraction_flag, fp->nb_antennas_tx, fp->nb_antennas_rx); + //LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_UE][MOD %02u][]\n", ue->Mod_id+NB_gNB_INST); phy_init_nr_top(ue); // many memory allocation sizes are hard coded - AssertFatal( fp->nb_antennas_rx <= 2, "hard coded allocation for ue_common_vars->dl_ch_estimates[eNB_id]" ); - AssertFatal( nb_connected_eNB <= NUMBER_OF_CONNECTED_eNB_MAX, "n_connected_eNB is too large" ); + AssertFatal( fp->nb_antennas_rx <= 4, "hard coded allocation for ue_common_vars->dl_ch_estimates[gNB_id]" ); + AssertFatal( nb_connected_gNB <= NUMBER_OF_CONNECTED_gNB_MAX, "n_connected_gNB is too large" ); // init phy_vars_ue for (i=0; i<4; i++) { @@ -674,13 +157,17 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, ue->rx_gain_byp[i] = 120; } - ue->n_connected_eNB = nb_connected_eNB; + ue->n_connected_gNB = nb_connected_gNB; - for(eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) { - ue->total_TBS[eNB_id] = 0; - ue->total_TBS_last[eNB_id] = 0; - ue->bitrate[eNB_id] = 0; - ue->total_received_bits[eNB_id] = 0; + for(gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { + ue->total_TBS[gNB_id] = 0; + ue->total_TBS_last[gNB_id] = 0; + ue->bitrate[gNB_id] = 0; + ue->total_received_bits[gNB_id] = 0; + + ue->ul_time_alignment[gNB_id].apply_ta = 0; + ue->ul_time_alignment[gNB_id].ta_frame = -1; + ue->ul_time_alignment[gNB_id].ta_slot = -1; } // init NR modulation lookup tables nr_generate_modulation_table(); @@ -688,9 +175,19 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, /////////////////////////PUSCH init///////////////////////// /////////// for (th_id = 0; th_id < RX_NB_TH_MAX; th_id++) { - for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) { - ue->pusch_vars[th_id][eNB_id] = (NR_UE_PUSCH *)malloc16(sizeof(NR_UE_PUSCH)); - phy_init_nr_ue_PUSCH( ue->pusch_vars[th_id][eNB_id], fp ); + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { + ue->pusch_vars[th_id][gNB_id] = (NR_UE_PUSCH *)malloc16(sizeof(NR_UE_PUSCH)); + phy_init_nr_ue_PUSCH( ue->pusch_vars[th_id][gNB_id], fp ); + } + } + + /////////////////////////PUCCH init///////////////////////// + /////////// + for (th_id = 0; th_id < RX_NB_TH_MAX; th_id++) { + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { + ue->pucch_vars[th_id][gNB_id] = (NR_UE_PUCCH *)malloc16(sizeof(NR_UE_PUCCH)); + for (i=0; i<2; i++) + ue->pucch_vars[th_id][gNB_id]->active[i] = false; } } @@ -699,29 +196,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, /////////////////////////PUSCH DMRS init///////////////////////// /////////// - - // default values until overwritten by RRCConnectionReconfiguration - - for (i=0; ipusch_config.pusch_TimeDomainResourceAllocation[i] = (PUSCH_TimeDomainResourceAllocation_t *)malloc16(sizeof(PUSCH_TimeDomainResourceAllocation_t)); - ue->pusch_config.pusch_TimeDomainResourceAllocation[i]->mappingType = typeB; - } - - for (i=0;iPDSCH_Config.pdsch_TimeDomainResourceAllocation[i] = (NR_PDSCH_TimeDomainResourceAllocation_t *)malloc16(sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); - ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[i]->mappingType = typeA; - } - - //------------- config DMRS parameters--------------// - // dmrs_Uplink_Config->pusch_dmrs_type = pusch_dmrs_type1; - // dmrs_Uplink_Config->pusch_dmrs_AdditionalPosition = pusch_dmrs_pos0; - // dmrs_Uplink_Config->pusch_maxLength = pusch_len1; - //-------------------------------------------------// - ue->dmrs_DownlinkConfig.pdsch_dmrs_type = pdsch_dmrs_type1; - ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition = pdsch_dmrs_pos0; - ue->dmrs_DownlinkConfig.pdsch_maxLength = pdsch_len1; - //-------------------------------------------------// - ue->nr_gold_pusch_dmrs = (uint32_t ****)malloc16(fp->slots_per_frame*sizeof(uint32_t ***)); pusch_dmrs = ue->nr_gold_pusch_dmrs; n_scid = 0; // This quantity is indicated by higher layer parameter dmrs-SeqInitialization @@ -789,54 +263,87 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, } } + //PDCCH DMRS init (gNB offset = 0) + ue->nr_gold_pdcch[0] = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **)); + uint32_t ***pdcch_dmrs = ue->nr_gold_pdcch[0]; + AssertFatal(pdcch_dmrs!=NULL, "NR init: pdcch_dmrs malloc failed\n"); + + for (int slot=0; slotslots_per_frame; slot++) { + pdcch_dmrs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *)); + AssertFatal(pdcch_dmrs[slot]!=NULL, "NR init: pdcch_dmrs for slot %d - malloc failed\n", slot); + + for (int symb=0; symbsymbols_per_slot; symb++) { + pdcch_dmrs[slot][symb] = (uint32_t *)malloc16(NR_MAX_PDCCH_DMRS_INIT_LENGTH_DWORD*sizeof(uint32_t)); + AssertFatal(pdcch_dmrs[slot][symb]!=NULL, "NR init: pdcch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb); + } + } + + ue->scramblingID_pdcch = fp->Nid_cell; + nr_gold_pdcch(ue,fp->Nid_cell); + + //PDSCH DMRS init (eNB offset = 0) + ue->nr_gold_pdsch[0] = (uint32_t ****)malloc16(fp->slots_per_frame*sizeof(uint32_t ***)); + uint32_t ****pdsch_dmrs = ue->nr_gold_pdsch[0]; + + for (int slot=0; slotslots_per_frame; slot++) { + pdsch_dmrs[slot] = (uint32_t ***)malloc16(fp->symbols_per_slot*sizeof(uint32_t **)); + AssertFatal(pdsch_dmrs[slot]!=NULL, "NR init: pdsch_dmrs for slot %d - malloc failed\n", slot); + + for (int symb=0; symbsymbols_per_slot; symb++) { + pdsch_dmrs[slot][symb] = (uint32_t **)malloc16(NR_MAX_NB_CODEWORDS*sizeof(uint32_t *)); + AssertFatal(pdsch_dmrs[slot][symb]!=NULL, "NR init: pdsch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb); + + for (int q=0; qscramblingID[i]=fp->Nid_cell; + + nr_gold_pdsch(ue,ue->scramblingID); + // DLSCH - for (eNB_id=0; eNB_idn_connected_eNB; eNB_id++) { + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { for (th_id=0; th_idpdsch_vars[th_id][eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); + ue->pdsch_vars[th_id][gNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); } for (th_id=0; th_idpdcch_vars[th_id][eNB_id] = (NR_UE_PDCCH *)malloc16_clear(sizeof(NR_UE_PDCCH)); + ue->pdcch_vars[th_id][gNB_id] = (NR_UE_PDCCH *)malloc16_clear(sizeof(NR_UE_PDCCH)); } - pdsch_vars_SI[eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); - pdsch_vars_ra[eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); - pdsch_vars_p[eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); - pdsch_vars_mch[eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); - prach_vars[eNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH)); - pbch_vars[eNB_id] = (NR_UE_PBCH *)malloc16_clear(sizeof(NR_UE_PBCH)); + prach_vars[gNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH)); + pbch_vars[gNB_id] = (NR_UE_PBCH *)malloc16_clear(sizeof(NR_UE_PBCH)); if (abstraction_flag == 0) { for (th_id=0; th_idpdsch_vars[th_id][eNB_id], fp ); + phy_init_nr_ue__PDSCH( ue->pdsch_vars[th_id][gNB_id], fp ); } for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->llr_shifts = (uint8_t *)malloc16_clear(7*2*fp->N_RB_DL*12); - ue->pdsch_vars[th_id][eNB_id]->llr_shifts_p = ue->pdsch_vars[0][eNB_id]->llr_shifts; - ue->pdsch_vars[th_id][eNB_id]->llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); - ue->pdsch_vars[th_id][eNB_id]->layer_llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); - ue->pdsch_vars[th_id][eNB_id]->llr128_2ndstream = (int16_t **)malloc16_clear( sizeof(int16_t *) ); - ue->pdsch_vars[th_id][eNB_id]->rho = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->llr_shifts = (uint8_t *)malloc16_clear(7*2*fp->N_RB_DL*12); + ue->pdsch_vars[th_id][gNB_id]->llr_shifts_p = ue->pdsch_vars[0][gNB_id]->llr_shifts; + ue->pdsch_vars[th_id][gNB_id]->llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); + ue->pdsch_vars[th_id][gNB_id]->layer_llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); + ue->pdsch_vars[th_id][gNB_id]->llr128_2ndstream = (int16_t **)malloc16_clear( sizeof(int16_t *) ); } - for (int i=0; inb_antennas_rx; i++) { - for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->rho[i] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - } - } for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->dl_ch_rho2_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_rho2_ext = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); } for (i=0; inb_antennas_rx; i++) for (j=0; j<4; j++) { - const int idx = (j<<1)+i; + const int idx = (j*fp->nb_antennas_rx)+i; const size_t num = 7*2*fp->N_RB_DL*12+4; for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->dl_ch_rho2_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_rho2_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); } } @@ -844,103 +351,94 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, for (k=0; k<8; k++) { //harq_pid for (l=0; l<8; l++) { //round for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->rxdataF_comp1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_rho_ext[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_mag1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_magb1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->rxdataF_comp1[k][l] = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_rho_ext[k][l] = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_mag1[k][l] = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_magb1[k][l] = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); } for (int i=0; inb_antennas_rx; i++) for (int j=0; j<4; j++) { //frame_parms->nb_antennas_tx; j++) - const int idx = (j<<1)+i; + const int idx = (j*fp->nb_antennas_rx)+i; for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - ue->pdsch_vars[th_id][eNB_id]->rxdataF_comp1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_mag1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_magb1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); + ue->pdsch_vars[th_id][gNB_id]->rxdataF_comp1[k][l][idx] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_mag1[k][l][idx] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_magb1[k][l][idx] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); } } } } - phy_init_nr_ue__PDSCH( pdsch_vars_SI[eNB_id], fp ); - phy_init_nr_ue__PDSCH( pdsch_vars_ra[eNB_id], fp ); - phy_init_nr_ue__PDSCH( pdsch_vars_p[eNB_id], fp ); - phy_init_nr_ue__PDSCH( pdsch_vars_mch[eNB_id], fp ); - // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE for (th_id=0; th_idpdcch_vars[th_id][eNB_id]->llr = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue->pdcch_vars[th_id][eNB_id]->llr16 = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue->pdcch_vars[th_id][eNB_id]->wbar = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue->pdcch_vars[th_id][eNB_id]->e_rx = (int16_t *)malloc16_clear( 4*2*100*12 ); - ue->pdcch_vars[th_id][eNB_id]->rxdataF_comp = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_rho_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdcch_vars[th_id][eNB_id]->rho = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - ue->pdcch_vars[th_id][eNB_id]->rxdataF_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + ue->pdcch_vars[th_id][gNB_id]->llr = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + ue->pdcch_vars[th_id][gNB_id]->llr16 = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + ue->pdcch_vars[th_id][gNB_id]->wbar = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); + ue->pdcch_vars[th_id][gNB_id]->e_rx = (int16_t *)malloc16_clear( 4*2*100*12 ); + ue->pdcch_vars[th_id][gNB_id]->rxdataF_comp = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_rho_ext = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdcch_vars[th_id][gNB_id]->rho = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdcch_vars[th_id][gNB_id]->rxdataF_ext = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); // Channel estimates - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear(4*fp->nb_antennas_rx*sizeof(int32_t *)); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear(4*fp->nb_antennas_rx*sizeof(int32_t *)); for (i=0; inb_antennas_rx; i++) { - ue->pdcch_vars[th_id][eNB_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(100*12*4) ); + ue->pdcch_vars[th_id][gNB_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(100*12*4)); for (j=0; j<4; j++) { - int idx = (j<<1) + i; - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates_time[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); + int idx = (j*fp->nb_antennas_rx)+i; + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) ); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates_time[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); // size_t num = 7*2*fp->N_RB_DL*12; size_t num = 4*273*12; // 4 symbols, 100 PRBs, 12 REs per PRB - ue->pdcch_vars[th_id][eNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_rho_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); - ue->pdcch_vars[th_id][eNB_id]->rxdataF_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + ue->pdcch_vars[th_id][gNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_rho_ext[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); + ue->pdcch_vars[th_id][gNB_id]->rxdataF_ext[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); } } } // PBCH - pbch_vars[eNB_id]->rxdataF_ext = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - pbch_vars[eNB_id]->rxdataF_comp = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pbch_vars[eNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pbch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pbch_vars[eNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pbch_vars[eNB_id]->llr = (int16_t *)malloc16_clear( 1920 ); // - prach_vars[eNB_id]->prachF = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); - prach_vars[eNB_id]->prach = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); + pbch_vars[gNB_id]->rxdataF_ext = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); + pbch_vars[gNB_id]->rxdataF_comp = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + pbch_vars[gNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + pbch_vars[gNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + pbch_vars[gNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear( 4*fp->nb_antennas_rx*sizeof(int32_t *) ); + pbch_vars[gNB_id]->llr = (int16_t *)malloc16_clear( 1920 ); // + prach_vars[gNB_id]->prachF = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); + prach_vars[gNB_id]->prach = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); for (i=0; inb_antennas_rx; i++) { - pbch_vars[eNB_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); + pbch_vars[gNB_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); for (j=0; j<4; j++) {//fp->nb_antennas_tx;j++) { - int idx = (j<<1)+i; - pbch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); - pbch_vars[eNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size) ); - pbch_vars[eNB_id]->dl_ch_estimates_time[idx]= (int32_t *)malloc16_clear( sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size) ); - pbch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); + int idx = (j*fp->nb_antennas_rx)+i; + pbch_vars[gNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); + pbch_vars[gNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size) ); + pbch_vars[gNB_id]->dl_ch_estimates_time[idx]= (int32_t *)malloc16_clear( sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size) ); + pbch_vars[gNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); } } } - pbch_vars[eNB_id]->decoded_output = (uint8_t *)malloc16_clear( 64 ); + pbch_vars[gNB_id]->decoded_output = (uint8_t *)malloc16_clear(64); } // initialization for the last instance of pdsch_vars (used for MU-MIMO) for (th_id=0; th_idpdsch_vars[th_id][eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); + ue->pdsch_vars[th_id][gNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); } - pdsch_vars_SI[eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); - pdsch_vars_ra[eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); - pdsch_vars_p[eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); - if (abstraction_flag == 0) { for (th_id=0; th_idpdsch_vars[th_id][eNB_id], fp ); - ue->pdsch_vars[th_id][eNB_id]->llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); - ue->pdsch_vars[th_id][eNB_id]->layer_llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); + //phy_init_lte_ue__PDSCH( ue->pdsch_vars[th_id][gNB_id], fp ); + ue->pdsch_vars[th_id][gNB_id]->llr[1] = (int16_t *)malloc16_clear((8*(3*8*8448))*sizeof(int16_t)); + ue->pdsch_vars[th_id][gNB_id]->layer_llr[1] = (int16_t *)malloc16_clear((8*(3*8*8448))*sizeof(int16_t)); } } else { //abstraction == 1 ue->sinr_dB = (double *) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); @@ -955,21 +453,18 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, else ue->pdsch_config_dedicated->p_a = dB0; - // set channel estimation to do linear interpolation in time - ue->high_speed_flag = 1; - ue->ch_est_alpha = 24576; // enable MIB/SIB decoding by default ue->decode_MIB = 1; ue->decode_SIB = 1; init_nr_prach_tables(839); - + init_symbol_rotation(fp); return 0; } void init_nr_ue_transport(PHY_VARS_NR_UE *ue, int abstraction_flag) { - for (int i=0; idlsch[k][i][j] = new_nr_ue_dlsch(1,NR_MAX_DLSCH_HARQ_PROCESSES,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag))!=NULL,"Can't get ue dlsch structures\n"); @@ -986,6 +481,50 @@ void init_nr_ue_transport(PHY_VARS_NR_UE *ue, //ue->frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; ue->dlsch_MCH[0] = new_nr_ue_dlsch(1,NR_MAX_DLSCH_HARQ_PROCESSES,NSOFT,MAX_LDPC_ITERATIONS_MBSFN,ue->frame_parms.N_RB_DL,0); + + for(int i=0; i<5; i++) + ue->dl_stats[i] = 0; +} + + +void init_N_TA_offset(PHY_VARS_NR_UE *ue){ + + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; + + if (fp->frame_type == FDD) { + ue->N_TA_offset = 0; + } else { + int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 + + double factor = 1.0; + switch (fp->numerology_index) { + case 0: //15 kHz scs + AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); + factor = fp->samples_per_subframe / 30720.0; + break; + case 1: //30 kHz sc + AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); + factor = fp->samples_per_subframe / 30720.0; + break; + case 2: //60 kHz scs + AssertFatal(1==0, "scs_common should not be 60 kHz\n"); + break; + case 3: //120 kHz scs + AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; + break; + case 4: //240 kHz scs + AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; + break; + default: + AssertFatal(1==0, "Invalid scs_common!\n"); + } + + ue->N_TA_offset = (int)(N_TA_offset * factor); + + LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d, mu %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index); + } } void phy_init_nr_top(PHY_VARS_NR_UE *ue) { @@ -1005,57 +544,3 @@ void phy_init_nr_top(PHY_VARS_NR_UE *ue) { //init_scrambling_lut(); //set_taus_seed(1328); } - -void set_default_frame_parms_single(nfapi_nr_config_request_t *config, - NR_DL_FRAME_PARMS *frame_parms) { - /* Set some default values that may be overwritten while reading options */ - frame_parms = (NR_DL_FRAME_PARMS*) malloc(sizeof(NR_DL_FRAME_PARMS)); - config = (nfapi_nr_config_request_t*) malloc(sizeof(nfapi_nr_config_request_t)); - config->subframe_config.numerology_index_mu.value =1; - config->subframe_config.duplex_mode.value = 1; //FDD - config->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL - config->rf_config.dl_carrier_bandwidth.value = 100; - config->rf_config.ul_carrier_bandwidth.value = 100; - config->sch_config.physical_cell_id.value = 0; - - frame_parms->frame_type = FDD; - //frame_parms[CC_id]->tdd_config_S = 0; - frame_parms->N_RB_DL = 106; - frame_parms->N_RB_UL = 106; - frame_parms->Ncp = NORMAL; - //frame_parms[CC_id]->Ncp_UL = NORMAL; - frame_parms->Nid_cell = 0; - //frame_parms[CC_id]->num_MBSFN_config = 0; - frame_parms->nb_antenna_ports_gNB = 1; - frame_parms->nb_antennas_tx = 1; - frame_parms->nb_antennas_rx = 1; - - //frame_parms[CC_id]->nushift = 0; - - ///frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; - //frame_parms[CC_id]->phich_config_common.phich_duration = normal; - - // UL RS Config - /*frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 1;//n_DMRS1 set to 0 - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1; - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; - frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; - - frame_parms[CC_id]->pusch_config_common.n_SB = 1; - frame_parms[CC_id]->pusch_config_common.hoppingMode = 0; - frame_parms[CC_id]->pusch_config_common.pusch_HoppingOffset = 0; - frame_parms[CC_id]->pusch_config_common.enable64QAM = 0; - - frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; - frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;*/ - - // NR: Init to legacy LTE 20Mhz params - frame_parms->numerology_index = 0; - frame_parms->ttis_per_subframe = 1; - frame_parms->slots_per_tti = 2; - - -} diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 6045930b17..347155ed3b 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -20,21 +20,82 @@ */ #include "phy_init.h" +#include "common/utils/nr/nr_common.h" #include "common/utils/LOG/log.h" -#include "LAYER2/NR_MAC_gNB/mac_proto.h" /// Subcarrier spacings in Hz indexed by numerology index uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, 120e3, 240e3}; uint16_t nr_slots_per_subframe[MAX_NUM_SUBCARRIER_SPACING] = {1, 2, 4, 8, 16}; +// Table 5.4.3.3-1 38-101 +int nr_ssb_table[48][3] = { + {1, 15, nr_ssb_type_A}, + {2, 15, nr_ssb_type_A}, + {3, 15, nr_ssb_type_A}, + {5, 15, nr_ssb_type_A}, + {5, 30, nr_ssb_type_B}, + {7, 15, nr_ssb_type_A}, + {8, 15, nr_ssb_type_A}, + {12, 15, nr_ssb_type_A}, + {14, 15, nr_ssb_type_A}, + {18, 15, nr_ssb_type_A}, + {20, 15, nr_ssb_type_A}, + {25, 15, nr_ssb_type_A}, + {26, 15, nr_ssb_type_A}, + {28, 15, nr_ssb_type_A}, + {29, 15, nr_ssb_type_A}, + {30, 15, nr_ssb_type_A}, + {34, 15, nr_ssb_type_A}, + {34, 30, nr_ssb_type_C}, + {38, 15, nr_ssb_type_A}, + {38, 30, nr_ssb_type_C}, + {39, 15, nr_ssb_type_A}, + {39, 30, nr_ssb_type_C}, + {40, 30, nr_ssb_type_C}, + {41, 15, nr_ssb_type_A}, + {41, 30, nr_ssb_type_C}, + {46, 30, nr_ssb_type_C}, + {48, 30, nr_ssb_type_C}, + {50, 30, nr_ssb_type_C}, + {51, 15, nr_ssb_type_A}, + {53, 15, nr_ssb_type_A}, + {65, 15, nr_ssb_type_A}, + {66, 15, nr_ssb_type_A}, + {66, 30, nr_ssb_type_B}, + {70, 15, nr_ssb_type_A}, + {71, 15, nr_ssb_type_A}, + {74, 15, nr_ssb_type_A}, + {75, 15, nr_ssb_type_A}, + {76, 15, nr_ssb_type_A}, + {77, 30, nr_ssb_type_C}, + {78, 30, nr_ssb_type_C}, + {79, 30, nr_ssb_type_C}, + {90, 15, nr_ssb_type_A}, + {90, 30, nr_ssb_type_C}, + {91, 15, nr_ssb_type_A}, + {92, 15, nr_ssb_type_A}, + {93, 15, nr_ssb_type_A}, + {94, 15, nr_ssb_type_A}, + {96, 30, nr_ssb_type_C} +}; -int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp) -{ +void set_Lmax(NR_DL_FRAME_PARMS *fp) { + // definition of Lmax according to ts 38.213 section 4.1 + if (fp->dl_CarrierFreq < 6e9) { + if(fp->frame_type && (fp->ssb_type==2)) + fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8; + else + fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8; + } else { + fp->Lmax = 64; + } +} + + +int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb) { int mu = fp->numerology_index; - uint8_t half_frame_index = fp->half_frame_bit; - uint8_t i_ssb = fp->ssb_index; int symbol = 0; uint8_t n, n_temp; nr_ssb_type_e type = fp->ssb_type; @@ -43,171 +104,72 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp) int case_E[8] = {8, 12, 16, 20, 32, 36, 40, 44}; switch(mu) { - - case NR_MU_0: // case A - n = i_ssb >> 1; - symbol = case_AC[i_ssb % 2] + 14*n; - break; - - case NR_MU_1: - if (type == 1){ // case B - n = i_ssb >> 2; - symbol = case_BD[i_ssb % 4] + 28*n; - } - if (type == 2){ // case C - n = i_ssb >> 1; - symbol = case_AC[i_ssb % 2] + 14*n; - } - break; - - case NR_MU_3: // case D - n_temp = i_ssb >> 2; - n = n_temp + (n_temp >> 2); - symbol = case_BD[i_ssb % 4] + 28*n; - break; - - case NR_MU_4: // case E - n_temp = i_ssb >> 3; - n = n_temp + (n_temp >> 2); - symbol = case_E[i_ssb % 8] + 56*n; - break; - - - default: - AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu); + case NR_MU_0: // case A + n = i_ssb >> 1; + symbol = case_AC[i_ssb % 2] + 14*n; + break; + case NR_MU_1: + if (type == 1){ // case B + n = i_ssb >> 2; + symbol = case_BD[i_ssb % 4] + 28*n; + } + if (type == 2){ // case C + n = i_ssb >> 1; + symbol = case_AC[i_ssb % 2] + 14*n; + } + break; + case NR_MU_3: // case D + n_temp = i_ssb >> 2; + n = n_temp + (n_temp >> 2); + symbol = case_BD[i_ssb % 4] + 28*n; + break; + case NR_MU_4: // case E + n_temp = i_ssb >> 3; + n = n_temp + (n_temp >> 2); + symbol = case_E[i_ssb % 8] + 56*n; + break; + default: + AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu); } - if (half_frame_index) - symbol += (5 * fp->symbols_per_slot * fp->slots_per_subframe); - return symbol; } -void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw) +void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL) { + int idx = 0; switch(mu) { - case NR_MU_0: //15kHz scs fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_0]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_0]; fp->ssb_type = nr_ssb_type_A; + while(nr_ssb_table[idx][0]!=fp->nr_band) + idx++; + AssertFatal(nr_ssb_table[idx][1]==15,"SCS %d not applicable to band %d\n", + fp->subcarrier_spacing,fp->nr_band); break; case NR_MU_1: //30kHz scs fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_1]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_1]; - - // selection of SS block pattern according to TS 38101-1 Table 5.4.3.3-1 for SCS 30kHz - if (fp->nr_band == 5 || fp->nr_band == 66) - fp->ssb_type = nr_ssb_type_B; - else{ - if (fp->nr_band == 41 || ( fp->nr_band > 76 && fp->nr_band < 80) ) - fp->ssb_type = nr_ssb_type_C; - else - AssertFatal(1==0,"NR Operating Band n%d not available for SS block SCS with mu=%d\n", fp->nr_band, mu); - } - - switch(bw){ - case 5: - case 15: - case 20: - case 25: - case 30: - case 40: //40 MHz - if (fp->threequarter_fs) { - fp->ofdm_symbol_size = 1536; - fp->first_carrier_offset = 900; //1536 - ( (106*12) / 2 ) - fp->nb_prefix_samples0 = 132; - fp->nb_prefix_samples = 108; - } - else { - fp->ofdm_symbol_size = 2048; - fp->first_carrier_offset = 1412; //2048 - ( (106*12) / 2 ) - fp->nb_prefix_samples0 = 176; - fp->nb_prefix_samples = 144; - } - break; - - case 50: - case 60: - case 70: - - case 80: //80 MHz - if (fp->threequarter_fs) { - fp->ofdm_symbol_size = 3072; - fp->first_carrier_offset = 1770; //3072 - ( (217*12) / 2 ) - fp->nb_prefix_samples0 = 264; - fp->nb_prefix_samples = 216; - } - else { - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2794; //4096 - ( (217*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - } - break; - - case 90: - AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for %d MHz band and MU %d\n",bw,mu); - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2626; //4096 - ( (245*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - break; - case 100: - AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for %d MHz band and MU %d\n",bw,mu); - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2458; //4096 - ( (273*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - break; - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); + while(nr_ssb_table[idx][0]!=fp->nr_band || + nr_ssb_table[idx][1]!=30) { + AssertFatal(nr_ssb_table[idx][0]<=fp->nr_band,"SCS %d not applicable to band %d\n", + fp->subcarrier_spacing,fp->nr_band); + idx++; } + fp->ssb_type = nr_ssb_table[idx][2]; break; case NR_MU_2: //60kHz scs fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_2]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_2]; - - switch(bw){ //FR1 bands only - case 10: - case 15: - case 20: - case 25: - case 30: - case 40: - case 50: - case 60: - case 70: - case 80: - case 90: - case 100: - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); - } break; case NR_MU_3: fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_3]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_3]; fp->ssb_type = nr_ssb_type_D; - switch(bw){ - case 100: - fp->ofdm_symbol_size = 1024; - fp->first_carrier_offset = 628; //1024 - ( (66*12) / 2 ) - fp->nb_prefix_samples0 = 136; - fp->nb_prefix_samples = 72; - break; - case 50: - fp->ofdm_symbol_size = 512; - fp->first_carrier_offset = 320; //1024 - ( (66*12) / 2 ) - fp->nb_prefix_samples0 = 68; - fp->nb_prefix_samples = 36; - break; - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); - } break; case NR_MU_4: @@ -216,9 +178,23 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw) fp->ssb_type = nr_ssb_type_E; break; - default: - AssertFatal(1==0,"Invalid numerology index %d", mu); + default: + AssertFatal(1==0,"Invalid numerology index %d", mu); } + + if(fp->threequarter_fs) + fp->ofdm_symbol_size = 3 * 128; + else + fp->ofdm_symbol_size = 4 * 128; + + while(fp->ofdm_symbol_size < N_RB_DL * 12) + fp->ofdm_symbol_size <<= 1; + + fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2); + fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9; + fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu)); + LOG_I(PHY,"Init: N_RB_DL %d, first_carrier_offset %d, nb_prefix_samples %d,nb_prefix_samples0 %d\n", + N_RB_DL,fp->first_carrier_offset,fp->nb_prefix_samples,fp->nb_prefix_samples0); } uint32_t get_samples_per_slot(int slot, NR_DL_FRAME_PARMS* fp) @@ -233,6 +209,19 @@ uint32_t get_samples_per_slot(int slot, NR_DL_FRAME_PARMS* fp) return samp_count; } +uint32_t get_slot_from_timestamp(openair0_timestamp timestamp_rx, NR_DL_FRAME_PARMS* fp) +{ + uint32_t slot_idx = 0; + int samples_till_the_slot = 0; + timestamp_rx = timestamp_rx%fp->samples_per_frame; + + while (timestamp_rx > samples_till_the_slot) { + samples_till_the_slot += fp->get_samples_per_slot(slot_idx,fp); + slot_idx++; + } + return slot_idx; +} + uint32_t get_samples_slot_timestamp(int slot, NR_DL_FRAME_PARMS* fp, uint8_t sl_ahead) { uint32_t samp_count = 0; @@ -251,13 +240,15 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, NR_DL_FRAME_PARMS *fp) { + AssertFatal (cfg != NULL, "%s %s:%i Null pointer to cfg %p!\n", __FUNCTION__, __FILE__, __LINE__, cfg); + fp->frame_type = cfg->cell_config.frame_duplex_type.value; fp->L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ; fp->N_RB_DL = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value; fp->N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value; int Ncp = NFAPI_CP_NORMAL; - int mu = cfg!= NULL ? cfg->ssb_config.scs_common.value : 0; + int mu = cfg->ssb_config.scs_common.value; #if DISABLE_LOG_X printf("Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",mu, fp->N_RB_DL, Ncp); @@ -271,13 +262,12 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, fp->half_frame_bit = 0; // half frame bit initialized to 0 here fp->numerology_index = mu; - set_scs_parameters(fp, mu, cfg->carrier_config.dl_bandwidth.value); + set_scs_parameters(fp, mu, fp->N_RB_DL); fp->slots_per_frame = 10* fp->slots_per_subframe; - fp->nb_antenna_ports_gNB = 1; // default value until overwritten by RRCConnectionReconfiguration - fp->nb_antennas_rx = 1; // default value until overwritten by RRCConnectionReconfiguration - fp->nb_antennas_tx = 1; // default value until overwritten by RRCConnectionReconfiguration + fp->nb_antennas_rx = cfg->carrier_config.num_rx_ant.value; // It denotes the number of rx antennas at gNB + fp->nb_antennas_tx = cfg->carrier_config.num_tx_ant.value; // It corresponds to pdsch_AntennaPorts (logical antenna ports) fp->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe; @@ -289,23 +279,16 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, (fp->nb_prefix_samples + fp->ofdm_symbol_size) * (fp->symbols_per_slot * fp->slots_per_subframe - 2); fp->get_samples_per_slot = &get_samples_per_slot; fp->get_samples_slot_timestamp = &get_samples_slot_timestamp; + fp->get_slot_from_timestamp = &get_slot_from_timestamp; fp->samples_per_frame = 10 * fp->samples_per_subframe; fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; fp->Ncp = Ncp; - // definition of Lmax according to ts 38.213 section 4.1 - if (fp->dl_CarrierFreq < 6e9) { - if(fp->frame_type && (fp->ssb_type==2)) - fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8; - else - fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8; - } else { - fp->Lmax = 64; - } + set_Lmax(fp); fp->N_ssb = 0; - int num_tx_ant = (cfg == NULL) ? fp->Lmax : cfg->carrier_config.num_tx_ant.value; + int num_tx_ant = cfg->carrier_config.num_tx_ant.value; for (int p=0; pN_ssb += ((fp->L_ssb >> (63-p)) & 0x01); @@ -315,13 +298,34 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, } int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, - fapi_nr_config_request_t* config, - int Ncp) + fapi_nr_config_request_t* config, + uint16_t nr_band) { + uint8_t nb_ant_ports_gNB = 1; + uint8_t tdd_cfg = 3; + uint8_t Nid_cell = 0; + int Ncp = NORMAL; + + if(fp->nb_antennas_rx == 0) + fp->nb_antennas_rx = 1; + if(fp->nb_antennas_tx == 0) + fp->nb_antennas_tx = 1; + + // default values until overwritten by RRCConnectionReconfiguration + fp->nb_antenna_ports_gNB = nb_ant_ports_gNB; + fp->tdd_config = tdd_cfg; + fp->Nid_cell = Nid_cell; + fp->nr_band = nr_band; + + LOG_I(PHY, "Initializing frame parms: set nb_antenna_ports_gNB %d, tdd_config, %d, Nid_cell %d\n", fp->nb_antenna_ports_gNB, fp->tdd_config, fp->Nid_cell); + uint64_t dl_bw_khz = (12*config->carrier_config.dl_grid_size[config->ssb_config.scs_common])*(15<ssb_config.scs_common); fp->dl_CarrierFreq = ((dl_bw_khz>>1) + config->carrier_config.dl_frequency)*1000 ; + LOG_D(PHY,"dl_bw_kHz %lu\n",dl_bw_khz); + LOG_D(PHY,"dl_CarrierFreq %lu\n",fp->dl_CarrierFreq); + uint64_t ul_bw_khz = (12*config->carrier_config.ul_grid_size[config->ssb_config.scs_common])*(15<ssb_config.scs_common); fp->ul_CarrierFreq = ((ul_bw_khz>>1) + config->carrier_config.uplink_frequency)*1000 ; @@ -329,12 +333,15 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->N_RB_UL = config->carrier_config.ul_grid_size[fp->numerology_index]; fp->N_RB_DL = config->carrier_config.dl_grid_size[fp->numerology_index]; - int32_t uplink_frequency_offset = 0; + fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); + int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); + uplink_frequency_offset *= 1000; - get_band(fp->dl_CarrierFreq, &fp->nr_band, &uplink_frequency_offset, &fp->frame_type); + LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); - AssertFatal(fp->frame_type==config->cell_config.frame_duplex_type, "Invalid duplex type in config request file for band %d\n", fp->nr_band); - AssertFatal(fp->ul_CarrierFreq==(fp->dl_CarrierFreq+uplink_frequency_offset), "Disagreement in uplink frequency for band %d\n", fp->nr_band); + AssertFatal(fp->frame_type==config->cell_config.frame_duplex_type, "Invalid duplex type (frame_type %d,cell_config.frame_duplex_type %d) in config request file for band %d\n", fp->frame_type,config->cell_config.frame_duplex_type,fp->nr_band); + + AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset), "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + uplink_frequency_offset); #if DISABLE_LOG_X printf("Initializing UE frame parms for mu %d, N_RB %d, Ncp %d\n",fp->numerology_index, fp->N_RB_DL, Ncp); @@ -347,14 +354,9 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->Ncp = Ncp; - set_scs_parameters(fp,fp->numerology_index,config->carrier_config.dl_bandwidth); + set_scs_parameters(fp, fp->numerology_index, fp->N_RB_DL); fp->slots_per_frame = 10* fp->slots_per_subframe; - - fp->nb_antenna_ports_gNB = 1; // default value until overwritten by RRCConnectionReconfiguration - fp->nb_antennas_rx = 1; // default value until overwritten by RRCConnectionReconfiguration - fp->nb_antennas_tx = 1; // default value until overwritten by RRCConnectionReconfiguration - fp->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe; fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP; @@ -374,18 +376,9 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, sco = config->ssb_table.ssb_subcarrier_offset; fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco); + set_Lmax(fp); - // definition of Lmax according to ts 38.213 section 4.1 - if (fp->dl_CarrierFreq < 6e9) { - if(fp->frame_type && (fp->ssb_type==2)) - fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8; - else - fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8; - } else { - fp->Lmax = 64; - } - - fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[1].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask; + fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask; fp->N_ssb = 0; for (int p=0; pLmax; p++) @@ -394,6 +387,43 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, return 0; } +void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t delta_duplex, uint8_t mu, uint16_t nr_band) { + + LOG_I(PHY,"SA init parameters. DL freq %lu UL offset %d SSB numerology %d N_RB_DL %d\n", + downlink_frequency, + delta_duplex, + mu, + frame_parms->N_RB_DL); + + frame_parms->numerology_index = mu; + frame_parms->dl_CarrierFreq = downlink_frequency; + frame_parms->ul_CarrierFreq = downlink_frequency + delta_duplex; + frame_parms->freq_range = (frame_parms->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; + frame_parms->N_RB_UL = frame_parms->N_RB_DL; + + frame_parms->nr_band = nr_band; + frame_parms->frame_type = get_frame_type(frame_parms->nr_band, frame_parms->numerology_index); + + frame_parms->Ncp = NORMAL; + set_scs_parameters(frame_parms, frame_parms->numerology_index, frame_parms->N_RB_DL); + set_Lmax(frame_parms); + + frame_parms->slots_per_frame = 10* frame_parms->slots_per_subframe; + frame_parms->symbols_per_slot = ((frame_parms->Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats + frame_parms->samples_per_subframe_wCP = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot * frame_parms->slots_per_subframe; + frame_parms->samples_per_frame_wCP = 10 * frame_parms->samples_per_subframe_wCP; + frame_parms->samples_per_slot_wCP = frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + frame_parms->samples_per_slotN0 = (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * frame_parms->symbols_per_slot; + frame_parms->samples_per_slot0 = frame_parms->nb_prefix_samples0 + ((frame_parms->symbols_per_slot-1)*frame_parms->nb_prefix_samples) + (frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size); + frame_parms->samples_per_subframe = (frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size) * 2 + + (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * (frame_parms->symbols_per_slot * frame_parms->slots_per_subframe - 2); + frame_parms->get_samples_per_slot = &get_samples_per_slot; + frame_parms->get_samples_slot_timestamp = &get_samples_slot_timestamp; + frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe; + +} + + void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp) { LOG_I(PHY,"fp->scs=%d\n",fp->subcarrier_spacing); diff --git a/openair1/PHY/INIT/phy_init.h b/openair1/PHY/INIT/phy_init.h index 1862d5f8e0..dd9232de83 100644 --- a/openair1/PHY/INIT/phy_init.h +++ b/openair1/PHY/INIT/phy_init.h @@ -389,16 +389,17 @@ void phy_config_request(PHY_Config_t *phy_config); void phy_config_update_sib2_request(PHY_Config_t *phy_config); void phy_config_update_sib13_request(PHY_Config_t *phy_config); - int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf); void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms); -int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp); +int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb); int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms); -int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms,fapi_nr_config_request_t *config,int Ncp); +int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band); +void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band); int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB,uint8_t abstraction_flag); void init_nr_ue_transport(PHY_VARS_NR_UE *ue,int abstraction_flag); +void init_N_TA_offset(PHY_VARS_NR_UE *ue); void nr_dump_frame_parms(NR_DL_FRAME_PARMS *frame_parms); -int phy_init_nr_gNB(PHY_VARS_gNB *gNB, unsigned char is_secondary_gNB, unsigned char abstraction_flag); +int phy_init_nr_gNB(PHY_VARS_gNB *gNB, unsigned char is_secondary_gNB, unsigned char lowmem_flag); void nr_phy_config_request(NR_PHY_Config_t *gNB); void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,int N_RB_DL,int N_RB_UL,int mu,int Nid_cell,uint64_t position_in_burst); void phy_free_nr_gNB(PHY_VARS_gNB *gNB); @@ -407,6 +408,8 @@ void init_nr_transport(PHY_VARS_gNB *gNB); void init_dfts(void); +void fill_subframe_mask(PHY_VARS_eNB *eNB); +void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg); /** @} */ #endif diff --git a/openair1/PHY/LTE_ESTIMATION/freq_equalization.c b/openair1/PHY/LTE_ESTIMATION/freq_equalization.c index 3fd58a4989..6d382bdd63 100644 --- a/openair1/PHY/LTE_ESTIMATION/freq_equalization.c +++ b/openair1/PHY/LTE_ESTIMATION/freq_equalization.c @@ -20,11 +20,11 @@ */ #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" #include "PHY/sse_intrin.h" +#include "PHY/LTE_ESTIMATION/lte_estimation.h" -// This is 512/(1:256) in __m128i format -int16_t inv_ch[256*8] = {512,512,512,512,512,512,512,512, +// This is 4096/(1:4096) in __m128i format +__m128i inv_ch[4096];/* = {512,512,512,512,512,512,512,512, 256,256,256,256,256,256,256,256, 170,170,170,170,170,170,170,170, 128,128,128,128,128,128,128,128, @@ -280,7 +280,11 @@ int16_t inv_ch[256*8] = {512,512,512,512,512,512,512,512, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, - }; + };*/ + +void init_fde() { + for (int i=1;i<4096;i++) inv_ch[i] = _mm_set1_epi16(4096/i); +} void freq_equalization(LTE_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, @@ -313,12 +317,12 @@ void freq_equalization(LTE_DL_FRAME_PARMS *frame_parms, amp=(*((int16_t*)&ul_ch_mag128[re])); - if (amp>255) - amp=255; + if (amp>4095) + amp=4095; - // printf("freq_eq: symbol %d re %d => %d,%d,%d, (%d) (%d,%d) => ",symbol,re,*((int16_t*)(&ul_ch_mag128[re])),amp,inv_ch[8*amp],*((int16_t*)(&ul_ch_mag128[re]))*inv_ch[8*amp],*(int16_t*)&(rxdataF_comp128[re]),*(1+(int16_t*)&(rxdataF_comp128[re]))); + //printf("freq_eq: symbol %d re %d => mag %d,amp %d,inv %d, prod %d (%d,%d)\n",symbol,re,*((int16_t*)(&ul_ch_mag128[re])),amp,_mm_extract_epi16(inv_ch[amp],0),(*((int16_t*)(&ul_ch_mag128[re]))*_mm_extract_epi16(inv_ch[amp],0))>>3,*(int16_t*)&(rxdataF_comp128[re]),*(1+(int16_t*)&(rxdataF_comp128[re]))); #if defined(__x86_64__) || defined(__i386__) - rxdataF_comp128[re] = _mm_mullo_epi16(rxdataF_comp128[re],*((__m128i *)&inv_ch[8*amp])); + rxdataF_comp128[re] = _mm_srai_epi16(_mm_mullo_epi16(rxdataF_comp128[re],inv_ch[amp]),3); if (Qm==4) ul_ch_mag128[re] = _mm_set1_epi16(324); // this is 512*2/sqrt(10) @@ -327,7 +331,7 @@ void freq_equalization(LTE_DL_FRAME_PARMS *frame_parms, ul_ch_magb128[re] = _mm_set1_epi16(158); // this is 512*2/sqrt(42) } #elif defined(__arm__) - rxdataF_comp128[re] = vmulq_s16(rxdataF_comp128[re],*((int16x8_t *)&inv_ch[8*amp])); + rxdataF_comp128[re] = vmulq_s16(rxdataF_comp128[re],inv_ch[amp]); if (Qm==4) ul_ch_mag128[re] = vdupq_n_s16(324); // this is 512*2/sqrt(10) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c index f85162e095..aac8e71828 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c @@ -21,7 +21,6 @@ #include "PHY/types.h" #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -118,12 +117,12 @@ int lte_est_timing_advance_pusch(LTE_DL_FRAME_PARMS *frame_parms, int temp, i, aa, max_pos=0, max_val=0; short Re,Im; - uint8_t cyclic_shift = 0; - int sync_pos = (frame_parms->ofdm_symbol_size-cyclic_shift*frame_parms->ofdm_symbol_size/12)%(frame_parms->ofdm_symbol_size); + // uint8_t cyclic_shift = 0; + int sync_pos = 0;//(frame_parms->ofdm_symbol_size-cyclic_shift*frame_parms->ofdm_symbol_size/12)%(frame_parms->ofdm_symbol_size); AssertFatal(frame_parms->ofdm_symbol_size > 127,"frame_parms->ofdm_symbol_size %d<128\n",frame_parms->ofdm_symbol_size); - AssertFatal(frame_parms->nb_antennas_rx >0 && frame_parms->nb_antennas_rx<3,"frame_parms->nb_antennas_rx %d not in [0,1]\n", - frame_parms->nb_antennas_rx); + AssertFatal(frame_parms->nb_antennas_rx >0 && frame_parms->nb_antennas_rx<=4,"frame_parms->nb_antennas_rx %d not in [1...%d]\n", + frame_parms->nb_antennas_rx,4); for (i = 0; i < frame_parms->ofdm_symbol_size; i++) { temp = 0; @@ -142,9 +141,5 @@ int lte_est_timing_advance_pusch(LTE_DL_FRAME_PARMS *frame_parms, if (max_pos>frame_parms->ofdm_symbol_size/2) max_pos = max_pos-frame_parms->ofdm_symbol_size; - //#ifdef DEBUG_PHY - LOG_D(PHY,"max_pos = %d, sync_pos=%d\n",max_pos,sync_pos); - //#endif //DEBUG_PHY - return max_pos - sync_pos; } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c index a881773910..7eeeb998ba 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c @@ -32,6 +32,30 @@ int32_t rx_power_avg_eNB[3]; +void dump_I0_stats(FILE *fd,PHY_VARS_eNB *eNB) { + + + int min_I0=1000,max_I0=0; + int amin=0,amax=0; + for (int i=0; iframe_parms.N_RB_UL; i++) { + if (i==(eNB->frame_parms.N_RB_UL>>1) - 1) i+=2; + + if (eNB->measurements.n0_subband_power_tot_dB[i]measurements.n0_subband_power_tot_dB[i]; amin=i;} + + if (eNB->measurements.n0_subband_power_tot_dB[i]>max_I0) {max_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; amax=i;} + } + + for (int i=0; iframe_parms.N_RB_UL; i++) { + fprintf(fd,"%2d.",eNB->measurements.n0_subband_power_tot_dB[i]-eNB->measurements.n0_subband_power_avg_dB); + if (i%25 == 24) fprintf(fd,"\n"); + } + + fprintf(fd,"\nmax_I0 %d (rb %d), min_I0 %d (rb %d), avg I0 %d\n", max_I0, amax, min_I0, amin, eNB->measurements.n0_subband_power_avg_dB); + + fprintf(fd,"prach_I0 = %d.%d dB\n",eNB->measurements.prach_I0/10,eNB->measurements.prach_I0%10); + + +} void lte_eNB_I0_measurements(PHY_VARS_eNB *eNB, int subframe, module_id_t eNB_id, @@ -47,6 +71,7 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *eNB, uint32_t rb; int32_t *ul_ch; int32_t n0_power_tot; + int64_t n0_power_tot2; int len; int offset; // noise measurements @@ -75,53 +100,56 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *eNB, } + n0_power_tot2=0; + int nb_rb=0; for (rb=0; rbN_RB_UL; rb++) { - n0_power_tot=0; + n0_power_tot=0; + int offset0= (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; + if ((rb_mask[rb>>5]&(1<<(rb&31))) == 0) { // check that rb was not used in this subframe + nb_rb++; for (aarx=0; aarxnb_antennas_rx; aarx++) { - - // select the 7th symbol in an uplink subframe - offset = (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; - offset += (7*frame_parms->ofdm_symbol_size); - ul_ch = &common_vars->rxdataF[aarx][offset]; - len = 12; + measurements->n0_subband_power[aarx][rb] = 0; + for (int s=0;s<(14-(frame_parms->Ncp<<1));s++) { + offset = offset0 + (s*frame_parms->ofdm_symbol_size); + ul_ch = &common_vars->rxdataF[aarx][offset]; + len = 12; // just do first half of middle PRB for odd number of PRBs - if (((frame_parms->N_RB_UL&1) == 1) && - (rb==(frame_parms->N_RB_UL>>1))) { - len=6; - } - if (clear == 1) - measurements->n0_subband_power[aarx][rb]=0; + if (((frame_parms->N_RB_UL&1) == 1) && + (rb==(frame_parms->N_RB_UL>>1))) { + len=6; + } - AssertFatal(ul_ch, "RX signal buffer (freq) problem"); + AssertFatal(ul_ch, "RX signal buffer (freq) problem"); - measurements->n0_subband_power[aarx][rb] = signal_energy_nodc(ul_ch,len); - //((k1*(signal_energy_nodc(ul_ch,len))) - // + (k2*measurements->n0_subband_power[aarx][rb])); + measurements->n0_subband_power[aarx][rb] += signal_energy_nodc(ul_ch,len); - measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(measurements->n0_subband_power[aarx][rb]); - // printf("subframe %d (%d): eNB %d, aarx %d, rb %d len %d: energy %d (%d dB)\n",subframe,offset,eNB_id,aarx,rb,len,signal_energy_nodc(ul_ch,len), - // measurements->n0_subband_power_dB[aarx][rb]); - n0_power_tot += measurements->n0_subband_power[aarx][rb]; - } - + } // symbol + measurements->n0_subband_power[aarx][rb]/=(14-(frame_parms->Ncp<<1)); + measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(measurements->n0_subband_power[aarx][rb]); + n0_power_tot += measurements->n0_subband_power[aarx][rb]; + + } //antenna + n0_power_tot/=frame_parms->nb_antennas_rx; + n0_power_tot2 += n0_power_tot; measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot); measurements->n0_subband_power_tot_dBm[rb] = measurements->n0_subband_power_tot_dB[rb] - eNB->rx_total_gain_dB - dB_fixed(frame_parms->N_RB_UL); - } - } + } //rb not used in subframe + } //rb + if (nb_rb>0) measurements->n0_subband_power_avg_dB = dB_fixed(n0_power_tot2/nb_rb); } void lte_eNB_srs_measurements(PHY_VARS_eNB *eNB, module_id_t eNB_id, - module_id_t UE_id, + module_id_t srs_id, unsigned char init_averaging) { LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; PHY_MEASUREMENTS_eNB *measurements = &eNB->measurements; - LTE_eNB_SRS *srs_vars = &eNB->srs_vars[UE_id]; + LTE_eNB_SRS *srs_vars = &eNB->srs_vars[srs_id]; int32_t aarx,rx_power_correction; int32_t rx_power; @@ -131,7 +159,7 @@ void lte_eNB_srs_measurements(PHY_VARS_eNB *eNB, //printf("Running eNB_srs_measurements for eNB_id %d\n",eNB_id); if (init_averaging == 1) - rx_power_avg_eNB[UE_id] = 0; + rx_power_avg_eNB[srs_id] = 0; rx_power = 0; @@ -147,24 +175,24 @@ void lte_eNB_srs_measurements(PHY_VARS_eNB *eNB, for (aarx=0; aarxnb_antennas_rx; aarx++) { - measurements->rx_spatial_power[UE_id][0][aarx] = + measurements->rx_spatial_power[srs_id][0][aarx] = ((signal_energy_nodc(&srs_vars->srs_ch_estimates[aarx][frame_parms->first_carrier_offset], (frame_parms->N_RB_DL*6)) + signal_energy_nodc(&srs_vars->srs_ch_estimates[aarx][1], (frame_parms->N_RB_DL*6)))*rx_power_correction) - measurements->n0_power[aarx]; - measurements->rx_spatial_power[UE_id][0][aarx]<<=1; // because of noise only in odd samples + measurements->rx_spatial_power[srs_id][0][aarx]<<=1; // because of noise only in odd samples - measurements->rx_spatial_power_dB[UE_id][0][aarx] = (unsigned short) dB_fixed(measurements->rx_spatial_power[UE_id][0][aarx]); + measurements->rx_spatial_power_dB[srs_id][0][aarx] = (unsigned short) dB_fixed(measurements->rx_spatial_power[srs_id][0][aarx]); - measurements->wideband_cqi[UE_id][aarx] = measurements->rx_spatial_power[UE_id][0][aarx]; + measurements->wideband_cqi[srs_id][aarx] = measurements->rx_spatial_power[srs_id][0][aarx]; // measurements->rx_power[UE_id][aarx]/=frame_parms->nb_antennas_tx; - measurements->wideband_cqi_dB[UE_id][aarx] = (unsigned short) dB_fixed(measurements->wideband_cqi[UE_id][aarx]); - rx_power += measurements->wideband_cqi[UE_id][aarx]; + measurements->wideband_cqi_dB[srs_id][aarx] = (unsigned short) dB_fixed(measurements->wideband_cqi[srs_id][aarx]); + rx_power += measurements->wideband_cqi[srs_id][aarx]; // measurements->rx_avg_power_dB[UE_id] += measurements->rx_power_dB[UE_id][aarx]; } @@ -172,14 +200,14 @@ void lte_eNB_srs_measurements(PHY_VARS_eNB *eNB, // measurements->rx_avg_power_dB[UE_id]/=frame_parms->nb_antennas_rx; if (init_averaging == 0) - rx_power_avg_eNB[UE_id] = ((k1*rx_power_avg_eNB[UE_id]) + (k2*rx_power))>>10; + rx_power_avg_eNB[srs_id] = ((k1*rx_power_avg_eNB[srs_id]) + (k2*rx_power))>>10; else - rx_power_avg_eNB[UE_id] = rx_power; + rx_power_avg_eNB[srs_id] = rx_power; - measurements->wideband_cqi_tot[UE_id] = dB_fixed2(rx_power,2*measurements->n0_power_tot); + measurements->wideband_cqi_tot[srs_id] = dB_fixed2(rx_power,2*measurements->n0_power_tot); // times 2 since we have noise only in the odd carriers of the srs comb - measurements->rx_rssi_dBm[UE_id] = (int32_t)dB_fixed(rx_power_avg_eNB[UE_id])-eNB->rx_total_gain_dB; + measurements->rx_rssi_dBm[srs_id] = (int32_t)dB_fixed(rx_power_avg_eNB[srs_id])-eNB->rx_total_gain_dB; @@ -195,21 +223,21 @@ void lte_eNB_srs_measurements(PHY_VARS_eNB *eNB, else if (rb>12) ul_ch = &srs_vars->srs_ch_estimates[aarx][6 + (rb-13)*12]; else { - measurements->subband_cqi_dB[UE_id][aarx][rb] = 0; + measurements->subband_cqi_dB[srs_id][aarx][rb] = 0; continue; } // cqi if (aarx==0) - measurements->subband_cqi_tot[UE_id][rb]=0; + measurements->subband_cqi_tot[srs_id][rb]=0; - measurements->subband_cqi[UE_id][aarx][rb] = (signal_energy_nodc(ul_ch,12))*rx_power_correction - measurements->n0_power[aarx]; + measurements->subband_cqi[srs_id][aarx][rb] = (signal_energy_nodc(ul_ch,12))*rx_power_correction - measurements->n0_power[aarx]; - if (measurements->subband_cqi[UE_id][aarx][rb] < 0) - measurements->subband_cqi[UE_id][aarx][rb]=0; + if (measurements->subband_cqi[srs_id][aarx][rb] < 0) + measurements->subband_cqi[srs_id][aarx][rb]=0; - measurements->subband_cqi_tot[UE_id][rb] += measurements->subband_cqi[UE_id][aarx][rb]; - measurements->subband_cqi_dB[UE_id][aarx][rb] = dB_fixed2(measurements->subband_cqi[UE_id][aarx][rb], + measurements->subband_cqi_tot[srs_id][rb] += measurements->subband_cqi[srs_id][aarx][rb]; + measurements->subband_cqi_dB[srs_id][aarx][rb] = dB_fixed2(measurements->subband_cqi[srs_id][aarx][rb], 2*measurements->n0_power[aarx]); // 2*n0_power since we have noise from the odd carriers in the comb of the srs @@ -220,7 +248,7 @@ void lte_eNB_srs_measurements(PHY_VARS_eNB *eNB, for (rb=0; rbN_RB_DL; rb++) { - measurements->subband_cqi_tot_dB[UE_id][rb] = dB_fixed2(measurements->subband_cqi_tot[UE_id][rb], + measurements->subband_cqi_tot_dB[srs_id][rb] = dB_fixed2(measurements->subband_cqi_tot[srs_id][rb], measurements->n0_power_tot); /* if (measurements->subband_cqi_tot_dB[UE_id][rb] == 65) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_estimation.h b/openair1/PHY/LTE_ESTIMATION/lte_estimation.h index fc40280853..6ba901e29f 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_estimation.h +++ b/openair1/PHY/LTE_ESTIMATION/lte_estimation.h @@ -288,6 +288,8 @@ void freq_equalization(LTE_DL_FRAME_PARMS *frame_parms, unsigned short Msc_RS, unsigned char Qm); +void init_fde(void); +void dump_I0_stats(FILE *fd,PHY_VARS_eNB *eNB); /** @} */ #endif diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c index 0d765a18b3..1fbc8b7ef2 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c @@ -27,276 +27,89 @@ //#include #include -#include "LAYER2/MAC/mac.h" #include "PHY/defs_UE.h" #include "PHY/phy_extern_ue.h" -#include "PHY_INTERFACE/phy_interface.h" #include "PHY/LTE_REFSIG/lte_refsig.h" -#include "RRC/LTE/rrc_extern.h" // Note: this is for prototype of generate_drs_pusch (OTA synchronization of RRUs) #include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h" -int* sync_corr_ue0 = NULL; -int* sync_corr_ue1 = NULL; -int* sync_corr_ue2 = NULL; -int sync_tmp[2048*4] __attribute__((aligned(32))); -short syncF_tmp[2048*2] __attribute__((aligned(32))); +static struct complex16 *primary_synch0_time __attribute__((aligned(32))); +static struct complex16 *primary_synch1_time __attribute__((aligned(32))); +static struct complex16 *primary_synch2_time __attribute__((aligned(32))); +static void doIdft(int size, short *in, short *out) { + switch (size) { + case 6: + idft(IDFT_128,in,out,1); + break; -int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *common_vars -{ - int i,k; + case 25: + idft(IDFT_512,in,out,1); + break; - sync_corr_ue0 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_tti); - sync_corr_ue1 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_tti); - sync_corr_ue2 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_tti); + case 50: + idft(IDFT_1024,in,out,1); + break; + + case 75: + idft(IDFT_1536,in,out,1); + break; - if (sync_corr_ue0) { -#ifdef DEBUG_PHY - LOG_D(PHY,"[openair][LTE_PHY][SYNC] sync_corr_ue allocated at %p\n", sync_corr_ue0); -#endif - //common_vars->sync_corr = sync_corr; - } else { - LOG_E(PHY,"[openair][LTE_PHY][SYNC] sync_corr_ue0 not allocated\n"); - return(-1); + case 100: + idft(IDFT_2048,in,out,1); + break; + + default: + LOG_E(PHY,"Unsupported N_RB_DL %d\n",size); + abort(); + break; + } } - if (sync_corr_ue1) { -#ifdef DEBUG_PHY - LOG_D(PHY,"[openair][LTE_PHY][SYNC] sync_corr_ue allocated at %p\n", sync_corr_ue1); -#endif - //common_vars->sync_corr = sync_corr; - } else { - LOG_E(PHY,"[openair][LTE_PHY][SYNC] sync_corr_ue1 not allocated\n"); - return(-1); +static void copyPrimary( struct complex16 *out, struct complex16 *in, int ofdmSize) { + int k=ofdmSize-36; + + for (int i=0; i<72; i++) { + out[k].r = in[i].r>>1; //we need to shift input to avoid overflow in fft + out[k].i = in[i].i>>1; + k++; + + if (k >= ofdmSize) { + k++; // skip DC carrier + k-=ofdmSize; + } + } } - if (sync_corr_ue2) { -#ifdef DEBUG_PHY - LOG_D(PHY,"[openair][LTE_PHY][SYNC] sync_corr_ue allocated at %p\n", sync_corr_ue2); -#endif - //common_vars->sync_corr = sync_corr; - } else { - LOG_E(PHY,"[openair][LTE_PHY][SYNC] sync_corr_ue2 not allocated\n"); - return(-1); - } - - // primary_synch0_time = (int *)malloc16((frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*sizeof(int)); - primary_synch0_time = (int16_t *)malloc16((frame_parms->ofdm_symbol_size)*sizeof(int16_t)*2); - - if (primary_synch0_time) { - // bzero(primary_synch0_time,(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*sizeof(int)); - bzero(primary_synch0_time,(frame_parms->ofdm_symbol_size)*sizeof(int16_t)*2); -#ifdef DEBUG_PHY - LOG_D(PHY,"[openair][LTE_PHY][SYNC] primary_synch0_time allocated at %p\n", primary_synch0_time); -#endif - } else { - LOG_E(PHY,"[openair][LTE_PHY][SYNC] primary_synch0_time not allocated\n"); - return(-1); - } - - // primary_synch1_time = (int *)malloc16((frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*sizeof(int)); - primary_synch1_time = (int16_t *)malloc16((frame_parms->ofdm_symbol_size)*sizeof(int16_t)*2); - - if (primary_synch1_time) { - // bzero(primary_synch1_time,(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*sizeof(int)); - bzero(primary_synch1_time,(frame_parms->ofdm_symbol_size)*sizeof(int16_t)*2); -#ifdef DEBUG_PHY - LOG_D(PHY,"[openair][LTE_PHY][SYNC] primary_synch1_time allocated at %p\n", primary_synch1_time); -#endif - } else { - LOG_E(PHY,"[openair][LTE_PHY][SYNC] primary_synch1_time not allocated\n"); - return(-1); - } - - // primary_synch2_time = (int *)malloc16((frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*sizeof(int)); - primary_synch2_time = (int16_t *)malloc16((frame_parms->ofdm_symbol_size)*sizeof(int16_t)*2); - - if (primary_synch2_time) { - // bzero(primary_synch2_time,(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*sizeof(int)); - bzero(primary_synch2_time,(frame_parms->ofdm_symbol_size)*sizeof(int16_t)*2); -#ifdef DEBUG_PHY - LOG_D(PHY,"[openair][LTE_PHY][SYNC] primary_synch2_time allocated at %p\n", primary_synch2_time); -#endif - } else { - LOG_E(PHY,"[openair][LTE_PHY][SYNC] primary_synch2_time not allocated\n"); - return(-1); - } - - +int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) { // LTE_UE_COMMON *common_vars + struct complex16 syncF_tmp[2048]__attribute__((aligned(32)))= {{0}}; + int sz=frame_parms->ofdm_symbol_size*sizeof(*primary_synch0_time); + AssertFatal( NULL != (primary_synch0_time = (struct complex16 *)malloc16(sz)),""); + bzero(primary_synch0_time,sz); + AssertFatal( NULL != (primary_synch1_time = (struct complex16 *)malloc16(sz)),""); + bzero(primary_synch1_time,sz); + AssertFatal( NULL != (primary_synch2_time = (struct complex16 *)malloc16(sz)),""); + bzero(primary_synch2_time,sz); // generate oversampled sync_time sequences - k=frame_parms->ofdm_symbol_size-36; - - for (i=0; i<72; i++) { - syncF_tmp[2*k] = primary_synch0[2*i]>>2; //we need to shift input to avoid overflow in fft - syncF_tmp[2*k+1] = primary_synch0[2*i+1]>>2; - k++; - - if (k >= frame_parms->ofdm_symbol_size) { - k++; // skip DC carrier - k-=frame_parms->ofdm_symbol_size; - } - } - - switch (frame_parms->N_RB_DL) { - case 6: - idft(IDFT_128,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - case 25: - idft(IDFT_512,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - case 50: - idft(IDFT_1024,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - - case 75: - idft(IDFT_1536,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, - 1); /// complex output - break; - case 100: - idft(IDFT_2048,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - default: - LOG_E(PHY,"Unsupported N_RB_DL %d\n",frame_parms->N_RB_DL); - break; - } - - for (i=0; iofdm_symbol_size; i++) - ((int32_t*)primary_synch0_time)[i] = sync_tmp[i]; - - k=frame_parms->ofdm_symbol_size-36; - - for (i=0; i<72; i++) { - syncF_tmp[2*k] = primary_synch1[2*i]>>2; //we need to shift input to avoid overflow in fft - syncF_tmp[2*k+1] = primary_synch1[2*i+1]>>2; - k++; - - if (k >= frame_parms->ofdm_symbol_size) { - k++; // skip DC carrier - k-=frame_parms->ofdm_symbol_size; - } - } - - switch (frame_parms->N_RB_DL) { - case 6: - idft(IDFT_128,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - case 25: - idft(IDFT_512,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - case 50: - idft(IDFT_1024,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - - case 75: - idft(IDFT_1536,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - case 100: - idft(IDFT_2048,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - default: - LOG_E(PHY,"Unsupported N_RB_DL %d\n",frame_parms->N_RB_DL); - break; - } - - for (i=0; iofdm_symbol_size; i++) - ((int32_t*)primary_synch1_time)[i] = sync_tmp[i]; - - k=frame_parms->ofdm_symbol_size-36; - - for (i=0; i<72; i++) { - syncF_tmp[2*k] = primary_synch2[2*i]>>2; //we need to shift input to avoid overflow in fft - syncF_tmp[2*k+1] = primary_synch2[2*i+1]>>2; - k++; - - if (k >= frame_parms->ofdm_symbol_size) { - k++; // skip DC carrier - k-=frame_parms->ofdm_symbol_size; - } - } - - switch (frame_parms->N_RB_DL) { - case 6: - idft(IDFT_128,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - case 25: - idft(IDFT_512,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - case 50: - idft(IDFT_1024,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - - case 75: - idft(IDFT_1536,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - case 100: - idft(IDFT_2048,(short*)syncF_tmp, /// complex input - (short*)sync_tmp, /// complex output - 1); - break; - default: - LOG_E(PHY,"Unsupported N_RB_DL %d\n",frame_parms->N_RB_DL); - break; - } - - for (i=0; iofdm_symbol_size; i++) - ((int32_t*)primary_synch2_time)[i] = sync_tmp[i]; - + copyPrimary( syncF_tmp, (struct complex16 *) primary_synch0, frame_parms->ofdm_symbol_size); + doIdft(frame_parms->N_RB_DL, (short *)syncF_tmp,(short *)primary_synch0_time); + copyPrimary( syncF_tmp, (struct complex16 *) primary_synch1, frame_parms->ofdm_symbol_size); + doIdft(frame_parms->N_RB_DL, (short *)syncF_tmp,(short *)primary_synch1_time); + copyPrimary( syncF_tmp, (struct complex16 *) primary_synch2, frame_parms->ofdm_symbol_size); + doIdft(frame_parms->N_RB_DL, (short *)syncF_tmp,(short *)primary_synch2_time); if ( LOG_DUMPFLAG(DEBUG_LTEESTIM)){ LOG_M("primary_sync0.m","psync0",primary_synch0_time,frame_parms->ofdm_symbol_size,1,1); LOG_M("primary_sync1.m","psync1",primary_synch1_time,frame_parms->ofdm_symbol_size,1,1); LOG_M("primary_sync2.m","psync2",primary_synch2_time,frame_parms->ofdm_symbol_size,1,1); } + return (1); } -void lte_sync_time_free(void) -{ - if (sync_corr_ue0) { - LOG_D(PHY,"Freeing sync_corr_ue (%p)...\n",sync_corr_ue0); - free(sync_corr_ue0); - } - - if (sync_corr_ue1) { - LOG_D(PHY,"Freeing sync_corr_ue (%p)...\n",sync_corr_ue1); - free(sync_corr_ue1); - } - - if (sync_corr_ue2) { - LOG_D(PHY,"Freeing sync_corr_ue (%p)...\n",sync_corr_ue2); - free(sync_corr_ue2); - } - +void lte_sync_time_free(void) { if (primary_synch0_time) { LOG_D(PHY,"Freeing primary_sync0_time ...\n"); free(primary_synch0_time); @@ -312,126 +125,81 @@ void lte_sync_time_free(void) free(primary_synch2_time); } - sync_corr_ue0 = NULL; - sync_corr_ue1 = NULL; - sync_corr_ue2 = NULL; primary_synch0_time = NULL; primary_synch1_time = NULL; primary_synch2_time = NULL; } -static inline int abs32(int x) -{ +static inline int abs32(int x) { return (((int)((short*)&x)[0])*((int)((short*)&x)[0]) + ((int)((short*)&x)[1])*((int)((short*)&x)[1])); } +static inline double absF(struct complexd x) { + return x.r*x.r+x.i*x.i; +} + +#define complexNull(c) bzero((void*) &(c), sizeof(c)) #define SHIFT 17 int lte_sync_time(int **rxdata, ///rx data in time domain LTE_DL_FRAME_PARMS *frame_parms, - int *eNB_id) -{ + int *eNB_id) { // perform a time domain correlation using the oversampled sync sequence - unsigned int n, ar, s, peak_pos, peak_val, sync_source; int result,result2; - int sync_out[3] = {0,0,0},sync_out2[3] = {0,0,0}; - int tmp[3] = {0,0,0}; + struct complexd sync_out[3]= {{0}}, sync_out2[3]= {{0}}; int length = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti>>1; - - //LOG_D(PHY,"[SYNC TIME] Calling sync_time.\n"); - AssertFatal(sync_corr_ue0 != NULL, - "sync_corr_ue0 not yet allocated! Exiting.\n"); - AssertFatal(sync_corr_ue1 != NULL, - "sync_corr_ue0 not yet allocated! Exiting.\n"); - AssertFatal(sync_corr_ue2 != NULL, - "sync_corr_ue0 not yet allocated! Exiting.\n"); - peak_val = 0; peak_pos = 0; sync_source = 0; - for (n=0; nofdm_symbol_size-frame_parms->nb_prefix_samples)) { if (n<(length-frame_parms->ofdm_symbol_size)) { - //calculate dot product of primary_synch0_time and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n]; for (ar=0; arnb_antennas_rx; ar++) { - - result = dot_product((short*)primary_synch0_time, (short*) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT); - result2 = dot_product((short*)primary_synch0_time, (short*) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT); - - ((short*)sync_corr_ue0)[2*n] += ((short*) &result)[0]; - ((short*)sync_corr_ue0)[2*n+1] += ((short*) &result)[1]; - ((short*)sync_corr_ue0)[2*(length+n)] += ((short*) &result2)[0]; - ((short*)sync_corr_ue0)[(2*(length+n))+1] += ((short*) &result2)[1]; - ((short*)sync_out)[0] += ((short*) &result)[0]; - ((short*)sync_out)[1] += ((short*) &result)[1]; - ((short*)sync_out2)[0] += ((short*) &result2)[0]; - ((short*)sync_out2)[1] += ((short*) &result2)[1]; + result = dot_product((short *)primary_synch0_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT); + result2 = dot_product((short *)primary_synch0_time, (short *) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT); + sync_out[0].r += ((short *) &result)[0]; + sync_out[0].i += ((short *) &result)[1]; + sync_out2[0].r += ((short *) &result2)[0]; + sync_out2[0].i += ((short *) &result2)[1]; } for (ar=0; arnb_antennas_rx; ar++) { - result = dot_product((short*)primary_synch1_time, (short*) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT); - result2 = dot_product((short*)primary_synch1_time, (short*) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT); - ((short*)sync_corr_ue1)[2*n] += ((short*) &result)[0]; - ((short*)sync_corr_ue1)[2*n+1] += ((short*) &result)[1]; - ((short*)sync_corr_ue1)[2*(length+n)] += ((short*) &result2)[0]; - ((short*)sync_corr_ue1)[(2*(length+n))+1] += ((short*) &result2)[1]; - - ((short*)sync_out)[2] += ((short*) &result)[0]; - ((short*)sync_out)[3] += ((short*) &result)[1]; - ((short*)sync_out2)[2] += ((short*) &result2)[0]; - ((short*)sync_out2)[3] += ((short*) &result2)[1]; + result = dot_product((short *)primary_synch1_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT); + result2 = dot_product((short *)primary_synch1_time, (short *) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT); + sync_out[1].r += ((short *) &result)[0]; + sync_out[1].i += ((short *) &result)[1]; + sync_out2[1].r += ((short *) &result2)[0]; + sync_out2[1].i += ((short *) &result2)[1]; } for (ar=0; arnb_antennas_rx; ar++) { - - result = dot_product((short*)primary_synch2_time, (short*) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT); - result2 = dot_product((short*)primary_synch2_time, (short*) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT); - ((short*)sync_corr_ue2)[2*n] += ((short*) &result)[0]; - ((short*)sync_corr_ue2)[2*n+1] += ((short*) &result)[1]; - ((short*)sync_corr_ue2)[2*(length+n)] += ((short*) &result2)[0]; - ((short*)sync_corr_ue2)[(2*(length+n))+1] += ((short*) &result2)[1]; - ((short*)sync_out)[4] += ((short*) &result)[0]; - ((short*)sync_out)[5] += ((short*) &result)[1]; - ((short*)sync_out2)[4] += ((short*) &result2)[0]; - ((short*)sync_out2)[5] += ((short*) &result2)[1]; + result = dot_product((short *)primary_synch2_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT); + result2 = dot_product((short *)primary_synch2_time, (short *) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT); + sync_out[2].r += ((short *) &result)[0]; + sync_out[2].i += ((short *) &result)[1]; + sync_out2[2].r += ((short *) &result2)[0]; + sync_out2[2].i += ((short *) &result2)[1]; } - } // calculate the absolute value of sync_corr[n] - sync_corr_ue0[n] = abs32(sync_corr_ue0[n]); - sync_corr_ue0[n+length] = abs32(sync_corr_ue0[n+length]); - sync_corr_ue1[n] = abs32(sync_corr_ue1[n]); - sync_corr_ue1[n+length] = abs32(sync_corr_ue1[n+length]); - sync_corr_ue2[n] = abs32(sync_corr_ue2[n]); - sync_corr_ue2[n+length] = abs32(sync_corr_ue2[n+length]); - for (s=0; s<3; s++) { - tmp[s] = (abs32(sync_out[s])>>1) + (abs32(sync_out2[s])>>1); + double tmp = absF(sync_out[s]) + absF(sync_out2[s]); - if (tmp[s]>peak_val) { - peak_val = tmp[s]; + if (tmp>peak_val) { + peak_val = tmp; peak_pos = n; sync_source = s; /* @@ -443,42 +211,22 @@ int lte_sync_time(int **rxdata, ///rx data in time domain } *eNB_id = sync_source; - - LOG_I(PHY,"[UE] lte_sync_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n",sync_source,peak_pos,peak_val,dB_fixed(peak_val)/2); - - - if ( LOG_DUMPFLAG(DEBUG_LTEESTIM)){ - static int debug_cnt; - if (debug_cnt == 0) { - LOG_M("sync_corr0_ue.m","synccorr0",sync_corr_ue0,2*length,1,2); - LOG_M("sync_corr1_ue.m","synccorr1",sync_corr_ue1,2*length,1,2); - LOG_M("sync_corr2_ue.m","synccorr2",sync_corr_ue2,2*length,1,2); - LOG_M("rxdata0.m","rxd0",rxdata[0],length<<1,1,1); - // exit(-1); - } else { - debug_cnt++; - } -} + LOG_I(PHY,"[UE] lte_sync_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n",sync_source,peak_pos,peak_val/2,dB_fixed(peak_val/2)/2); return(peak_pos); } -int ru_sync_time_init(RU_t *ru) // LTE_UE_COMMON *common_vars -{ +int ru_sync_time_init(RU_t *ru) { // LTE_UE_COMMON *common_vars /* int16_t dmrs[2048]; int16_t *dmrsp[2] = {dmrs,NULL}; */ - int32_t dmrs[ru->frame_parms->ofdm_symbol_size*14] __attribute__((aligned(32))); //int32_t *dmrsp[2] = {&dmrs[(3-ru->frame_parms->Ncp)*ru->frame_parms->ofdm_symbol_size],NULL}; int32_t *dmrsp[2] = {&dmrs[0],NULL}; - generate_ul_ref_sigs(); - - ru->dmrssync = (int16_t*)malloc16_clear(ru->frame_parms->ofdm_symbol_size*2*sizeof(int16_t)); - ru->dmrs_corr = (uint64_t*)malloc16_clear(ru->frame_parms->samples_per_tti*10*sizeof(uint64_t)); - + ru->dmrssync = (int16_t *)malloc16_clear(ru->frame_parms->ofdm_symbol_size*2*sizeof(int16_t)); + ru->dmrs_corr = (uint64_t *)malloc16_clear(ru->frame_parms->samples_per_tti*10*sizeof(uint64_t)); generate_drs_pusch(NULL, NULL, ru->frame_parms, @@ -491,35 +239,39 @@ int ru_sync_time_init(RU_t *ru) // LTE_UE_COMMON *common_vars 0); switch (ru->frame_parms->N_RB_DL) { - case 6: - idft(IDFT_128,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), - ru->dmrssync, /// complex output - 1); - break; - case 25: - idft(IDFT_512,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), - ru->dmrssync, /// complex output - 1); - break; - case 50: - idft(IDFT_1024,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), - ru->dmrssync, /// complex output - 1); - break; - - case 75: - idft(IDFT_1536,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), - ru->dmrssync, - 1); /// complex output - break; - case 100: - idft(IDFT_2048,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), - ru->dmrssync, /// complex output - 1); - break; - default: - AssertFatal(1==0,"Unsupported N_RB_DL %d\n",ru->frame_parms->N_RB_DL); - break; + case 6: + idft(IDFT_128,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + ru->dmrssync, /// complex output + 1); + break; + + case 25: + idft(IDFT_512,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + ru->dmrssync, /// complex output + 1); + break; + + case 50: + idft(IDFT_1024,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + ru->dmrssync, /// complex output + 1); + break; + + case 75: + idft(IDFT_1536,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + ru->dmrssync, + 1); /// complex output + break; + + case 100: + idft(IDFT_2048,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + ru->dmrssync, /// complex output + 1); + break; + + default: + AssertFatal(1==0,"Unsupported N_RB_DL %d\n",ru->frame_parms->N_RB_DL); + break; } return(0); @@ -527,10 +279,11 @@ int ru_sync_time_init(RU_t *ru) // LTE_UE_COMMON *common_vars void ru_sync_time_free(RU_t *ru) { - AssertFatal(ru->dmrssync!=NULL,"ru->dmrssync is NULL\n"); free(ru->dmrssync); - if (ru->dmrs_corr) free(ru->dmrs_corr); + + if (ru->dmrs_corr) + free(ru->dmrs_corr); } //#define DEBUG_PHY @@ -539,10 +292,8 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain LTE_DL_FRAME_PARMS *frame_parms, uint32_t length, uint32_t *peak_val_out, - uint32_t *sync_corr_eNB) -{ + uint32_t *sync_corr_eNB) { // perform a time domain correlation using the oversampled sync sequence - unsigned int n, ar, peak_val, peak_pos; uint64_t mean_val; int result; @@ -556,21 +307,21 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain } switch (eNB_id) { - case 0: - primary_synch_time = (short*)primary_synch0_time; - break; + case 0: + primary_synch_time = (short *)primary_synch0_time; + break; - case 1: - primary_synch_time = (short*)primary_synch1_time; - break; + case 1: + primary_synch_time = (short *)primary_synch1_time; + break; - case 2: - primary_synch_time = (short*)primary_synch2_time; - break; + case 2: + primary_synch_time = (short *)primary_synch2_time; + break; - default: - LOG_E(PHY,"[SYNC TIME] Illegal eNB_id!\n"); - return (-1); + default: + LOG_E(PHY,"[SYNC TIME] Illegal eNB_id!\n"); + return (-1); } peak_val = 0; @@ -578,21 +329,16 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain mean_val = 0; for (n=0; nofdm_symbol_size-frame_parms->nb_prefix_samples)) { - //calculate dot product of primary_synch0_time and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n]; for (ar=0; arnb_antennas_rx; ar++) { - - result = dot_product((short*)primary_synch_time, (short*) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT); + result = dot_product((short *)primary_synch_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT); //((short*)sync_corr)[2*n] += ((short*) &result)[0]; //((short*)sync_corr)[2*n+1] += ((short*) &result)[1]; sync_corr_eNB[n] += abs32(result); - } - } /* @@ -610,7 +356,6 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain } mean_val/=length; - *peak_val_out = peak_val; if (peak_val <= (40*(uint32_t)mean_val)) { @@ -620,88 +365,91 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain LOG_I(PHY,"[SYNC TIME] Peak found at pos %u, val = %u, mean_val = %"PRIu64"\n",peak_pos,peak_val,mean_val); return(peak_pos); } - } -static inline int64_t abs64(int64_t x) -{ - return (((int64_t)((int32_t*)&x)[0])*((int64_t)((int32_t*)&x)[0]) + ((int64_t) -((int32_t*)&x)[1])*((int64_t)((int32_t*)&x)[1])); +static inline int64_t abs64(int64_t x) { + return (((int64_t)((int32_t *)&x)[0])*((int64_t)((int32_t *)&x)[0]) + ((int64_t) + ((int32_t *)&x)[1])*((int64_t)((int32_t *)&x)[1])); } int ru_sync_time(RU_t *ru, int64_t *lev, - int64_t *avg) -{ + int64_t *avg) { LTE_DL_FRAME_PARMS *frame_parms = ru->frame_parms; RU_CALIBRATION *calibration = &ru->calibration; - // perform a time domain correlation using the oversampled sync sequence - int length = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti; - // circular copy of beginning to end of rxdata buffer. Note: buffer should be big enough upon calling this function - for (int ar=0;arnb_rx;ar++) memcpy((void*)&ru->common.rxdata[ar][2*length], - (void*)&ru->common.rxdata[ar][0], - frame_parms->ofdm_symbol_size); - + for (int ar=0; arnb_rx; ar++) + memcpy((void *)&ru->common.rxdata[ar][2*length], + (void *)&ru->common.rxdata[ar][0], + frame_parms->ofdm_symbol_size); + int32_t maxlev0=0; int maxpos0=0; int64_t avg0=0; int64_t result; int64_t dmrs_corr; - int maxval=0; - for (int i=0;i<2*(frame_parms->ofdm_symbol_size);i++) { + + for (int i=0; i<2*(frame_parms->ofdm_symbol_size); i++) { maxval = max(maxval,ru->dmrssync[i]); maxval = max(maxval,-ru->dmrssync[i]); } if (ru->state == RU_CHECK_SYNC) { - for (int i=0;i<2*(frame_parms->ofdm_symbol_size);i++) { - maxval = max(maxval,calibration->drs_ch_estimates_time[0][i]); - maxval = max(maxval,-calibration->drs_ch_estimates_time[0][i]); - } + for (int i=0; i<2*(frame_parms->ofdm_symbol_size); i++) { + maxval = max(maxval,calibration->drs_ch_estimates_time[0][i]); + maxval = max(maxval,-calibration->drs_ch_estimates_time[0][i]); + } } int shift = log2_approx(maxval); for (int n=0; nnb_rx; ar++) { - result = dot_product64(ru->dmrssync, - (int16_t*) &ru->common.rxdata[ar][n], - frame_parms->ofdm_symbol_size, - shift); - - if (ru->state == RU_CHECK_SYNC) { - result = dot_product64((int16_t*) &calibration->drs_ch_estimates_time[ar], - (int16_t*) &ru->common.rxdata[ar][n], + (int16_t *) &ru->common.rxdata[ar][n], frame_parms->ofdm_symbol_size, shift); + + if (ru->state == RU_CHECK_SYNC) { + result = dot_product64((int16_t *) &calibration->drs_ch_estimates_time[ar], + (int16_t *) &ru->common.rxdata[ar][n], + frame_parms->ofdm_symbol_size, + shift); } + dmrs_corr += abs64(result); } - if (ru->dmrs_corr != NULL) ru->dmrs_corr[n] = dmrs_corr; + + if (ru->dmrs_corr != NULL) + ru->dmrs_corr[n] = dmrs_corr; // tmpi holds ++...+ + if (dmrs_corr>maxlev0) { + maxlev0 = dmrs_corr; + maxpos0 = n; + } - if (dmrs_corr>maxlev0) { maxlev0 = dmrs_corr; maxpos0 = n; } avg0 += dmrs_corr; } - avg0/=(length/4); + avg0/=(length/4); int dmrsoffset = frame_parms->samples_per_tti + (3*frame_parms->ofdm_symbol_size)+(3*frame_parms->nb_prefix_samples) + frame_parms->nb_prefix_samples0; - - if ((int64_t)maxlev0 > (10*avg0)) {*lev = maxlev0; *avg=avg0; return((length+maxpos0-dmrsoffset)%length);} + + if ((int64_t)maxlev0 > (10*avg0)) { + *lev = maxlev0; + *avg=avg0; + return((length+maxpos0-dmrsoffset)%length); + } return(-1); } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 755111feb8..c867292942 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -20,7 +20,7 @@ */ #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" +//#include "PHY/phy_extern.h" #include "PHY/sse_intrin.h" //#define DEBUG_CH #include "common/utils/LOG/log.h" @@ -34,12 +34,17 @@ static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32 #define SCALE 0x3FFF +static const short conjugate[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1}; + +extern unsigned short dftsizes[34]; +extern int16_t *ul_ref_sigs_rx[30][2][34]; + int32_t lte_ul_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, L1_rxtx_proc_t *proc, - LTE_eNB_ULSCH_t * ulsch, - int32_t **ul_ch_estimates, - int32_t **ul_ch_estimates_time, - int32_t **rxdataF_ext, + LTE_eNB_ULSCH_t * ulsch, + int32_t **ul_ch_estimates, + int32_t **ul_ch_estimates_time, + int32_t **rxdataF_ext, module_id_t UE_id, unsigned char l, unsigned char Ns) { @@ -786,33 +791,38 @@ int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms, Ravg[0]=0; Ravg[1]=0; int16_t iv, rv, phase_idx = 0; - __m128i avg128U1, avg128U2, R[3], mmtmpD0, mmtmpD1, mmtmpD2, mmtmpD3; + __m128i R[3], mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3; + __m128 avg128U1, avg128U2; // round(tan((pi/4)*[1:1:N]/N)*pow2(15)) int16_t alpha[128] = {201, 402, 603, 804, 1006, 1207, 1408, 1610, 1811, 2013, 2215, 2417, 2619, 2822, 3024, 3227, 3431, 3634, 3838, 4042, 4246, 4450, 4655, 4861, 5066, 5272, 5479, 5686, 5893, 6101, 6309, 6518, 6727, 6937, 7147, 7358, 7570, 7782, 7995, 8208, 8422, 8637, 8852, 9068, 9285, 9503, 9721, 9940, 10160, 10381, 10603, 10825, 11049, 11273, 11498, 11725, 11952, 12180, 12410, 12640, 12872, 13104, 13338, 13573, 13809, 14046, 14285, 14525, 14766, 15009, 15253, 15498, 15745, 15993, 16243, 16494, 16747, 17001, 17257, 17515, 17774, 18035, 18298, 18563, 18829, 19098, 19368, 19640, 19915, 20191, 20470, 20750, 21033, 21318, 21605, 21895, 22187, 22481, 22778, 23078, 23380, 23685, 23992, 24302, 24615, 24931, 25250, 25572, 25897, 26226, 26557, 26892, 27230, 27572, 27917, 28266, 28618, 28975, 29335, 29699, 30067, 30440, 30817, 31198, 31583, 31973, 32368, 32767}; // compute log2_maxh (output_shift) - avg128U1 = _mm_setzero_si128(); - avg128U2 = _mm_setzero_si128(); + avg128U1 = _mm_setzero_ps(); + avg128U2 = _mm_setzero_ps(); for (rb=0; rbNcp==0)?4:3)*l) + (7*(1+ns))))<<10); //cinit //x2 = frame_parms->Ncp + (Nid_cell<<1) + (1+(Nid_cell<<1))*(1 + (3*l) + (7*(1+ns))); //cinit //n = 0 - x1 = 1+ (1<<31); + x1 = 1+ (1U<<31); x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); // skip first 50 double words (1600 bits) @@ -103,7 +103,7 @@ void lte_gold_ue_spec(uint32_t lte_gold_uespec_table[2][20][2][21],uint16_t Nid_ //x2 = frame_parms->Ncp + (Nid_cell<<1) + (1+(Nid_cell<<1))*(1 + (3*l) + (7*(1+ns))); //cinit //n = 0 // printf("cinit (ns %d, l %d) => %d\n",ns,l,x2); - x1 = 1+ (1<<31); + x1 = 1+ (1U<<31); x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); // skip first 50 double words (1600 bits) @@ -143,7 +143,7 @@ void lte_gold_ue_spec_port5(uint32_t lte_gold_uespec_port5_table[20][38],uint16_ //x2 = frame_parms->Ncp + (Nid_cell<<1) + (1+(Nid_cell<<1))*(1 + (3*l) + (7*(1+ns))); //cinit //n = 0 //printf("cinit (ns %d, l %d) => %d\n",ns,l,x2); - x1 = 1+ (1<<31); + x1 = 1+ (1U<<31); x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); //skip first 50 double words (1600 bits) diff --git a/openair1/PHY/LTE_REFSIG/lte_gold_mbsfn.c b/openair1/PHY/LTE_REFSIG/lte_gold_mbsfn.c index b057f6a403..78f0fd93fe 100644 --- a/openair1/PHY/LTE_REFSIG/lte_gold_mbsfn.c +++ b/openair1/PHY/LTE_REFSIG/lte_gold_mbsfn.c @@ -59,7 +59,7 @@ void lte_gold_mbsfn(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_mbsfn_tabl //n = 0 // printf("cinit (sfn %d, l %d) => %d\n",sfn,l,x2); // Initializing the Sequence - x1 = 1+ (1<<31); + x1 = 1+ (1U<<31); x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); // skip first 50 double words (1600 bits) // printf("n=0 : x1 %x, x2 %x\n",x1,x2); @@ -90,7 +90,7 @@ void lte_gold_mbsfn_khz_1dot25(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold for (sfn=0; sfn<10; sfn++) { x2 = (Nid_mbsfn) + (((1+(Nid_mbsfn<<1))*(1 + (7*(1+sfn))))<<9); //cinit - x1 = 1+ (1<<31); + x1 = 1+ (1U<<31); x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); for (n=1; n<50; n++) { diff --git a/openair1/PHY/LTE_REFSIG/lte_refsig.h b/openair1/PHY/LTE_REFSIG/lte_refsig.h index 84a2676082..9d3bae503b 100644 --- a/openair1/PHY/LTE_REFSIG/lte_refsig.h +++ b/openair1/PHY/LTE_REFSIG/lte_refsig.h @@ -36,8 +36,7 @@ \param reset resets the generator \return 32 bits of the gold sequence */ -uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset); - +#include /*!\brief This function generates the LTE Gold sequence (36-211, Sec 7.2), specifically for DL reference signals. @param frame_parms LTE DL Frame parameters diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c index 1913afab2d..99f37c1323 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -50,8 +50,6 @@ //#define DEBUG_DCI_DECODING 1 //#define DEBUG_PHY -//#undef ALL_AGGREGATION - //extern uint16_t phich_reg[MAX_NUM_PHICH_GROUPS][3]; //extern uint16_t pcfich_reg[4]; diff --git a/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h index 60720e13b7..512316f565 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h +++ b/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h @@ -32,11 +32,8 @@ #ifndef __DCI_NB_IOT_H__ #define __DCI_NB_IOT_H__ -//#ifndef USER_MODE -//#include "PHY/types.h" -//#else #include -//#endif + typedef enum { diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 8de011acef..1bbe9eb39a 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -53,22 +53,25 @@ //#undef LOG_D //#define LOG_D(A,B...) printf(B) -int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type) { - uint16_t i; - int16_t first_free_index=-1; +int find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type) { + int first_free_index=-1; AssertFatal(eNB!=NULL,"eNB is null\n"); - for (i=0; idlsch[i]!=NULL,"eNB->dlsch[%d] is null\n",i); - AssertFatal(eNB->dlsch[i]!=NULL,"eNB->dlsch[%d][0] is null\n",i); + for (int i=0; idlsch[i][0] == NULL) continue; LOG_D(PHY,"searching for rnti %x : UE index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,eNB->dlsch[i][0]->harq_mask,eNB->dlsch[i][0]->rnti,first_free_index); - if ((eNB->dlsch[i][0]->harq_mask >0) && - (eNB->dlsch[i][0]->rnti==rnti)) return i; - else if ((eNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; + if (type == SEARCH_EXIST_RA) { + if (eNB->dlsch[i][0]->rnti==rnti) return i; + } else { + if ((eNB->dlsch[i][0]->harq_mask >0) && + (eNB->dlsch[i][0]->rnti==rnti)) return i; + else if ((eNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; + } + } - if (type == SEARCH_EXIST) + if (type == SEARCH_EXIST_RA || type == SEARCH_EXIST) return -1; if (first_free_index != -1) @@ -78,20 +81,23 @@ int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type) { } -int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type) { - uint16_t i; - int16_t first_free_index=-1; +int find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type) { + int first_free_index=-1; AssertFatal(eNB!=NULL,"eNB is null\n"); - for (i=0; iulsch[i]!=NULL,"eNB->ulsch[%d] is null\n",i); + for (int i=0; iulsch[i]==NULL) continue; - if ((eNB->ulsch[i]->harq_mask >0) && - (eNB->ulsch[i]->rnti==rnti)) return i; - else if ((eNB->ulsch[i]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; + if (type == SEARCH_EXIST_RA) { + if (eNB->ulsch[i]->rnti == rnti) return i; + } else { + if ((eNB->ulsch[i]->harq_mask >0) && + (eNB->ulsch[i]->rnti==rnti)) return i; + else if ((eNB->ulsch[i]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; + } } - if (type == SEARCH_EXIST) + if (type == SEARCH_EXIST_RA || type == SEARCH_EXIST) return -1; if (first_free_index != -1) @@ -301,7 +307,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB, UE_id = find_dlsch(rel8->rnti,eNB,SEARCH_EXIST_OR_FREE); - if( (UE_id<0) || (UE_id>=NUMBER_OF_UE_MAX) ) { + if( (UE_id<0) || (UE_id>=NUMBER_OF_DLSCH_MAX) ) { LOG_E(PHY,"illegal UE_id found!!! rnti %04x UE_id %d\n",rel8->rnti,UE_id); return; } @@ -476,7 +482,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB, ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->harq_pid = rel8->harq_process; ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->dai = rel8->downlink_assignment_index; ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->padding = 0; - // printf("TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); + //LOG_D(PHY,"TDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",rel8->mcs_1,rel8->resource_block_coding,rel8->redundancy_version_1,NPRB); } else { dci_alloc->dci_length = sizeof_DCI1A_20MHz_FDD_t; ((DCI1A_20MHz_FDD_t *)dci_pdu)->type = 1; @@ -535,7 +541,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB, dlsch0->harq_mask |= (1 << rel8->harq_process); - if (rel8->rnti_type == 1) LOG_D(PHY,"DCI 1A: round %d, mcs %d, TBS %d, rballoc %x, rv %d, rnti %x, harq process %d\n",dlsch0_harq->round,rel8->mcs_1,dlsch0_harq->TBS,rel8->resource_block_coding, + if (rel8->rnti != SI_RNTI) LOG_D(PHY,"DCI 1A: round %d, mcs %d, TBS %d, rballoc %x, rv %d, rnti %x, harq process %d\n",dlsch0_harq->round,rel8->mcs_1,dlsch0_harq->TBS,rel8->resource_block_coding, rel8->redundancy_version_1,rel8->rnti,rel8->harq_process); break; @@ -1521,7 +1527,9 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB, if (dlsch0->active) T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(0), T_INT(frame), T_INT(subframe), T_INT(rel8->rnti), T_INT(rel8->dci_format), T_INT(rel8->harq_process), - T_INT(rel8->mcs_1), T_INT(dlsch0_harq->TBS)); + T_INT(rel8->mcs_1), T_INT(dlsch0_harq->TBS), T_INT(rel8->new_data_indicator_1), + T_INT(rel8->redundancy_version_1), T_INT(rel8->resource_block_coding), + T_INT(dlsch0_harq->nb_rb), T_INT(dlsch0_harq->rb_alloc[0])); #endif } @@ -1550,7 +1558,7 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dci_alloc->i0 = rel13->initial_transmission_sf_io; UE_id = find_dlsch (rel13->rnti, eNB, SEARCH_EXIST_OR_FREE); AssertFatal (UE_id != -1, "no free or exiting dlsch_context\n"); - AssertFatal (UE_id < NUMBER_OF_UE_MAX, "returned UE_id %d >= %d(NUMBER_OF_UE_MAX)\n", UE_id, NUMBER_OF_UE_MAX); + AssertFatal (UE_id < NUMBER_OF_DLSCH_MAX, "returned UE_id %d >= %d(NUMBER_OF_DLSCH_MAX)\n", UE_id, NUMBER_OF_DLSCH_MAX); dlsch0 = eNB->dlsch[UE_id][0]; dlsch0_harq = dlsch0->harq_processes[rel13->harq_process]; dci_alloc->ra_flag = 0; @@ -1955,7 +1963,7 @@ void fill_dci0(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc, if(frame_parms->frame_type == TDD) { UE_id = find_ulsch(pdu->dci_pdu_rel8.rnti, eNB,SEARCH_EXIST_OR_FREE); - if(UE_id != -1) { + if(UE_id >=0 -1 || UE_id < NUMBER_OF_ULSCH_MAX) { eNB->ulsch[UE_id]->harq_processes[pdu->dci_pdu_rel8.harq_pid]->V_UL_DAI = dai +1; } } @@ -2071,6 +2079,8 @@ void fill_ulsch(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_ulsch_pdu *ulsch_pdu ulsch->harq_processes[harq_pid]->round++; ulsch->harq_processes[harq_pid]->TBS = ulsch_pdu->ulsch_pdu_rel8.size<<3; ulsch->harq_processes[harq_pid]->Msc_initial = 12*ulsch_pdu->ulsch_pdu_rel8.number_of_resource_blocks; + ulsch->harq_processes[harq_pid]->Or1 = 0; + ulsch->harq_processes[harq_pid]->Or2 = 0; } ulsch->rnti = ulsch_pdu->ulsch_pdu_rel8.rnti; diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools_common.c b/openair1/PHY/LTE_TRANSPORT/dci_tools_common.c index 583d12eedb..64e74ebfbf 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools_common.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools_common.c @@ -32,7 +32,6 @@ #include "PHY/defs_eNB.h" #include "PHY/phy_extern.h" -#include "SCHED/sched_eNB.h" #ifdef DEBUG_DCI_TOOLS #include "PHY/phy_vars.h" #endif @@ -43,7 +42,6 @@ //#define DEBUG_HARQ -#include "LAYER2/MAC/mac.h" //#define DEBUG_DCI @@ -100,7 +98,6 @@ uint16_t RIV2nb_rb_LUT100[6000]; uint16_t RIV2first_rb_LUT100[6000]; uint16_t RIV_max100=0; -extern RAN_CONTEXT_t RC; extern uint32_t current_dlsch_cqi; @@ -273,15 +270,6 @@ uint16_t get_nCCE(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uint -uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int subframe) -{ - - // check for eNB only ! - return(get_nCCE(num_pdcch_symbols, - &RC.eNB[Mod_id][CC_id]->frame_parms, - get_mi(&RC.eNB[Mod_id][CC_id]->frame_parms,subframe))); -} - void conv_eMTC_rballoc (uint16_t resource_block_coding, uint32_t N_RB_DL, uint32_t * rb_alloc) { diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 3eb44d98fa..b5bcb0848d 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -96,6 +96,7 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) { } + LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, unsigned char Mdlharq, uint32_t Nsoft, @@ -110,7 +111,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, switch (N_RB_DL) { case 6: - bw_scaling =16; + bw_scaling = 4; break; case 25: @@ -160,7 +161,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, for (i=0; iharq_processes[i] = (LTE_DL_eNB_HARQ_t *)malloc16(sizeof(LTE_DL_eNB_HARQ_t)); - LOG_T(PHY, "Required mem size %d (bw scaling %d), dlsch->harq_processes[%d] %p\n", + LOG_I(PHY, "Required DLSCH mem size %d (bw scaling %d), dlsch->harq_processes[%d] %p\n", MAX_DLSCH_PAYLOAD_BYTES/bw_scaling,bw_scaling, i,dlsch->harq_processes[i]); if (dlsch->harq_processes[i]) { @@ -169,9 +170,9 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, dlsch->harq_processes[i]->b = (unsigned char *)malloc16(MAX_DLSCH_PAYLOAD_BYTES/bw_scaling); if (dlsch->harq_processes[i]->b) { - bzero(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES/bw_scaling); + memset(dlsch->harq_processes[i]->b,0,MAX_DLSCH_PAYLOAD_BYTES/bw_scaling); } else { - printf("Can't get b\n"); + AssertFatal(1==0,"Can't get b\n"); exit_flag=1; } @@ -181,15 +182,15 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, dlsch->harq_processes[i]->c[r] = (uint8_t *)malloc16(((r==0)?8:0) + 3+ 768); if (dlsch->harq_processes[i]->c[r]) { - bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768); + memset(dlsch->harq_processes[i]->c[r],0,((r==0)?8:0) + 3+ 768); } else { - printf("Can't get c\n"); + AssertFatal(1==0,"Can't get c\n"); exit_flag=2; } } } } else { - printf("Can't get harq_p %d\n",i); + AssertFatal(1==0,"Can't get harq_p %d\n",i); exit_flag=3; } } @@ -203,7 +204,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, } } - LOG_D(PHY,"new_eNB_dlsch exit flag %d, size of %ld\n", + LOG_I(PHY,"new_eNB_dlsch exit flag %d, size of %ld\n", exit_flag, sizeof(LTE_eNB_DLSCH_t)); free_eNB_dlsch(dlsch); return(NULL); @@ -360,6 +361,7 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, proc->nbEncode=0; + // if (hadlsch->Ndi == 1) { // this is a new packet if (hadlsch->round == 0) { // this is a new packet // Add 24-bit crc (polynomial A) to payload diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 8c07421b7e..aba4a464f2 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -2242,16 +2242,12 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, MIMO_mode_t mimo_mode = -1; uint8_t mprime=0,Ns; int8_t lprime=-1; - int aa=0; #ifdef DEBUG_DLSCH_MODULATION uint8_t Nl0; //= dlsch0_harq->Nl; uint8_t Nl1; #endif - int ru_id; - RU_t *ru; - int eNB_id; if ((dlsch0 != NULL) && (dlsch1 != NULL)){ @@ -2379,16 +2375,14 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, for (l=num_pdcch_symbols; lmimo_mode, pmi2hex_2Ar2(dlsch0_harq->pmi_alloc), mod_order0, mod_order1, rb_alloc[0] ); -#endif } if (frame_parms->Ncp==0) { // normal prefix @@ -2432,11 +2426,13 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, } // mapping ue specific beamforming weights from UE specified DLSCH structure to RU beam weights for the eNB - for (ru_id=0;ru_idnum_eNB;eNB_id++){ + for (int eNB_id=0;eNB_idnum_eNB;eNB_id++){ if (phy_vars_eNB == ru->eNB_list[eNB_id]) { - for (aa=0;aanb_tx;aa++){ + for (int aa=0;aanb_tx;aa++){ LOG_I(PHY,"ru_id:%d eNB_id:%d aa:%d memcpy(ru->beam_weights, dlsch0->ue_spec_bf_weights[ru_id][0],)\n", ru_id, eNB_id, aa); memcpy(ru->beam_weights[eNB_id][5][aa], dlsch0->ue_spec_bf_weights[ru_id][0], @@ -2445,6 +2441,7 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB, } } } + */ } @@ -2981,7 +2978,7 @@ int allocate_REs_in_RB_MCH_khz_1dot25(int32_t **txdataF, case 2: //QPSK - LOG_D(PHY,"%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + LOG_D(PHY,"%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); ((int16_t*)&txdataF[0][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i *jj = *jj + 1; @@ -3083,7 +3080,7 @@ int mch_modulation_khz_1dot25(int32_t **txdataF, uint8_t skip_dc=0; uint8_t mod_order = dlsch->harq_processes[0]->Qm; int16_t qam16_table_a[4],qam64_table_a[8];//,qam16_table_b[4],qam64_table_b[8]; - int16_t *qam_table_s; + int16_t *qam_table_s=qam16_table_a; nsymb_pmch = 1; nsymb = (frame_parms->Ncp == NORMAL) ? 14 : 12; @@ -3126,12 +3123,8 @@ int mch_modulation_khz_1dot25(int32_t **txdataF, } - if (mod_order == 4) - qam_table_s = qam16_table_a; - else if (mod_order == 6) + if (mod_order == 6) qam_table_s = qam64_table_a; - else - qam_table_s = NULL; //LOG_I(PHY,"Allocated rb %d, subframe_offset %d,amp %d\n",rb,subframe_offset,amp); allocate_REs_in_RB_MCH_khz_1dot25(txdataF, diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c index d48164e07d..015a95a862 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c @@ -113,15 +113,12 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell_mbsfn; //this is c_init in 36.211 Sec 6.3.1 for PMCH } -#ifdef DEBUG_SCRAMBLING - printf("scrambling: i0 %d rnti %x, q %d, Ns %d, Nid_cell %d, G %d x2 %x\n",dlsch->i0,dlsch->rnti,q,Ns,frame_parms->Nid_cell, G, x2); -#endif s = lte_gold_generic(&x1, &x2, 1); for (n=0; n<(1+(G>>5)); n++) { #ifdef DEBUG_SCRAMBLING - for (int k=0; k<32; k++) printf("scrambling %d : %d xor %d = %d\n",k+(n<<5),e[k],(s>>k)&1,e[k]^((s>>k)&1)); + for (int k=0; k<32; k++) printf("scrambling %d : %x xor %x = %d\n",k+(n<<5),e[k],(s>>k)&1,e[k]^((s>>k)&1)); #endif e[0] = (e[0]) ^ (s&1); diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index a843fc1fd7..09c0b4ba0f 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -30,10 +30,13 @@ * \warning */ -#include "PHY/defs_eNB.h" +#include +//#include "PHY/defs_eNB.h" +#include "PHY/defs_RU.h" #include "PHY/TOOLS/alaw_lut.h" -#include "PHY/phy_extern.h" -#include "SCHED/sched_eNB.h" +//#include "PHY/phy_extern.h" +//#include "SCHED/sched_eNB.h" +lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); //#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" @@ -49,7 +52,7 @@ void send_IF4p5(RU_t *ru, LTE_DL_FRAME_PARMS *fp = ru->frame_parms; int32_t **txdataF = ru->common.txdataF_BF; int32_t **rxdataF = ru->common.rxdataF; - int16_t **prach_rxsigF = ru->prach_rxsigF; + int16_t **prach_rxsigF = ru->prach_rxsigF[0]; int16_t ***prach_rxsigF_br = ru->prach_rxsigF_br; void *tx_buffer = ru->ifbuffer.tx[subframe&1]; void *tx_buffer_prach = ru->ifbuffer.tx_prach; @@ -276,7 +279,7 @@ void recv_IF4p5(RU_t *ru, LTE_DL_FRAME_PARMS *fp = ru->frame_parms; int32_t **txdataF = ru->common.txdataF_BF; int32_t **rxdataF = ru->common.rxdataF; - int16_t **prach_rxsigF = ru->prach_rxsigF; + int16_t **prach_rxsigF = ru->prach_rxsigF[0]; int16_t ***prach_rxsigF_br = ru->prach_rxsigF_br; void *rx_buffer = ru->ifbuffer.rx; uint16_t element_id; diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 1e0dd9db1b..86723d0fed 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -32,14 +32,13 @@ #include #include "PHY/defs_eNB.h" +#include "PHY/defs_gNB.h" +#include +#include "PHY/defs_RU.h" #include "PHY/TOOLS/alaw_lut.h" //#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" -#include #include "common/utils/LOG/vcd_signal_dumper.h" -//#define DEBUG_DL_MOBIPASS -//#define DEBUG_UL_MOBIPASS -#define SUBFRAME_SKIP_NUM_MOBIPASS 8 const uint8_t lin2alaw_if5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, @@ -1050,18 +1049,12 @@ static inline int64_t clock_difftime_ns(struct timespec start, struct timespec e return temp_ns; } -void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t *seqno, uint16_t packet_type) { +void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int tti, uint8_t *seqno, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp=ru->frame_parms; int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; int32_t *tx_buffer=NULL; -#ifdef DEBUG_DL_MOBIPASS - int8_t dummy_buffer[fp->samples_per_tti*2]; -#endif - void *alaw_buffer = ru->ifbuffer.tx[subframe&1]; - uint16_t *data_block = NULL; - uint16_t *j = NULL; - uint16_t packet_id=0, i=0, element_id=0; + uint16_t packet_id=0, i=0; uint32_t spp_eth = (uint32_t) ru->ifdevice.openair0_cfg->samples_per_packet; uint32_t spsf = (uint32_t) ru->ifdevice.openair0_cfg->samples_per_frame/10; @@ -1070,6 +1063,14 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); if (packet_type == IF5_RRH_GW_DL) { if (eth->compression == ALAW_COMPRESS) { + AssertFatal(1==0,"IF5 compression needs reworking\n"); +/* + void *alaw_buffer = ru->ifbuffer.tx[subframe&1]; + int element_id=0; + + uint16_t *data_block = NULL; + uint16_t *j = NULL; + if (eth->flags == ETH_RAW_MODE) { data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); } else { @@ -1100,39 +1101,55 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 0 ); } +*/ } else if (eth->compression == NO_COMPRESS) { - for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] = (void*)&ru->common.txdata[i][subframe*fp->samples_per_tti]; - - for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); - clock_gettime( CLOCK_MONOTONIC, &start_comp); - ru->ifdevice.trx_write_func(&ru->ifdevice, - (proc_timestamp + packet_id*spp_eth), - (void**)txp, - spp_eth, - fp->nb_antennas_tx, - 0); - clock_gettime( CLOCK_MONOTONIC, &end_comp); - LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 0 ); - for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] += spp_eth; + NR_DL_FRAME_PARMS *nrfp = ru->nr_frame_parms; + int offset,siglen; + if (nrfp) { + offset = nrfp->get_samples_slot_timestamp(tti,nrfp,0); + siglen = nrfp->get_samples_per_slot(tti,nrfp); } + else { + offset = tti*fp->samples_per_subframe; + siglen = spsf; + } + + for (i=0; i < ru->nb_tx; i++) + txp[i] = (int32_t*)&ru->common.txdata[i][offset]; + + for (packet_id=0; packet_id < siglen / spp_eth; packet_id++) { + for (int aid=0; aidnb_tx;aid++) { + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_comp); + ru->ifdevice.trx_write_func2(&ru->ifdevice, + (proc_timestamp + packet_id*spp_eth-500)*(30720/spsf), + (void*)txp[aid], + spp_eth, + aid, + 0); + LOG_D(HW,"TTI %d : packet %d, TS %llu\n",tti,packet_id,(unsigned long long)(proc_timestamp-ru->ts_offset+packet_id*spp_eth)); + clock_gettime( CLOCK_MONOTONIC, &end_comp); + LOG_D(HW,"[TTI %d] IF_Write_Time: %"PRId64"\n",tti,clock_difftime_ns(start_comp, end_comp)); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 0 ); + txp[aid] += spp_eth; + + } + } } } else if (packet_type == IF5_RRH_GW_UL) { if (eth->compression == ALAW_COMPRESS) { - if (eth->flags == ETH_RAW_MODE) { + AssertFatal(1==0,"ALAW IF5 requires work\n"); + /* if (eth->flags == ETH_RAW_MODE) { data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); } else { data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES); } for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); clock_gettime( CLOCK_MONOTONIC, &start_comp); for (i=0; i < fp->nb_antennas_rx; i++) { for (element_id=0; element_id< spp_eth; element_id++){ @@ -1142,8 +1159,8 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t } clock_gettime( CLOCK_MONOTONIC, &end_comp); LOG_D(HW,"[SF %d] Compress_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); clock_gettime( CLOCK_MONOTONIC, &start_comp); ru->ifdevice.trx_write_func(&ru->ifdevice, (proc_timestamp + packet_id*spp_eth), @@ -1155,9 +1172,10 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 0 ); } +*/ } else if (eth->compression == NO_COMPRESS) { for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] = (void*)&ru->common.rxdata[i][subframe*fp->samples_per_tti]; + rxp[i] = (void*)&ru->common.rxdata[i][tti*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); @@ -1170,162 +1188,38 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t fp->nb_antennas_rx, 0); clock_gettime( CLOCK_MONOTONIC, &end_comp); - LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); + LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",tti,clock_difftime_ns(start_comp, end_comp)); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 0 ); for (i=0; i < fp->nb_antennas_rx; i++) rxp[i] += spp_eth; } } - } else if (packet_type == IF5_MOBIPASS) { - /* the only difference between mobipass standalone and the other one - * is the timestamp in trx_write_func, but let's duplicate anyway - * (plus we don't call malloc for the standalone case) - */ - if (ru->if_timing == synch_to_mobipass_standalone) { - uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES; - - __m128i *data_block=NULL, *data_block_head=NULL; - __m128i *txp128; - __m128i t0, t1; - - unsigned char _tx_buffer[MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)]; - tx_buffer=(int32_t *)_tx_buffer; - - IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block_head = (__m128i *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t); - - header->flags = 0; - header->fifo_status = 0; - header->seqno = *seqno; - header->ack = 0; - header->word0 = 0; - - txp[0] = (void*)&ru->common.txdata[0][subframe*ru->frame_parms->samples_per_tti]; - txp128 = (__m128i *) txp[0]; - - for (packet_id=0; packet_idsamples_per_tti/db_fulllength; packet_id++) { - header->time_stamp = htonl((uint32_t)(proc_timestamp + packet_id*db_fulllength)); - data_block = data_block_head; - - for (i=0; i>2; i+=2) { - t0 = _mm_srai_epi16(*txp128++, 4); - t1 = _mm_srai_epi16(*txp128++, 4); - _mm_storeu_si128(data_block++, _mm_packs_epi16(t0, t1)); - } - - // Write the packet to the fronthaul - if ((ru->ifdevice.trx_write_func(&ru->ifdevice, - proc_timestamp + packet_id*db_fulllength, - (void**)&tx_buffer, - db_fulllength, - 1, - IF5_MOBIPASS)) < 0) { - perror("ETHERNET write for IF5_MOBIPASS\n"); - } - header->seqno += 1; - } - *seqno = header->seqno; - tx_buffer = NULL; - } else { - uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES; - - __m128i *data_block=NULL, *data_block_head=NULL; - - __m128i *txp128; - __m128i t0, t1; - - // tx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); - tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); - IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES); - data_block_head = (__m128i *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t); - - header->flags = 0; - header->fifo_status = 0; - header->seqno = *seqno; - header->ack = 0; - header->word0 = 0; - - txp[0] = (void*)&ru->common.txdata[0][subframe*ru->frame_parms->samples_per_tti]; - txp128 = (__m128i *) txp[0]; - - for (packet_id=0; packet_idsamples_per_tti/db_fulllength; packet_id++) { - header->time_stamp = htonl((uint32_t)(proc_timestamp + packet_id*db_fulllength)); - data_block = data_block_head; - - for (i=0; i>2; i+=2) { - t0 = _mm_srai_epi16(*txp128++, 4); - t1 = _mm_srai_epi16(*txp128++, 4); -// *data_block++ = _mm_packs_epi16(t0, t1); - _mm_storeu_si128(data_block++, _mm_packs_epi16(t0, t1)); - } - - // Write the packet to the fronthaul - if ((ru->ifdevice.trx_write_func(&ru->ifdevice, - packet_id, - (void**)&tx_buffer, - db_fulllength, - 1, - IF5_MOBIPASS)) < 0) { - perror("ETHERNET write for IF5_MOBIPASS\n"); - } - -#ifdef DEBUG_DL_MOBIPASS - if ((subframe==0)&&(dummy_cnt == 100)) { - memcpy((void*)&dummy_buffer[packet_id*db_fulllength*2],(void*)data_block_head,db_fulllength*2); - } -#endif - header->seqno += 1; - } - *seqno = header->seqno; - -#ifdef DEBUG_DL_MOBIPASS - uint8_t txe; - txe = dB_fixed(signal_energy(txp[0],fp->samples_per_tti)); - if (txe > 0){ - LOG_D(PHY,"[Mobipass] frame:%d, subframe:%d, energy %d\n", (proc_timestamp/(10*fp->samples_per_tti))&1023,subframe, txe); - } -#endif - } } else { AssertFatal(1==0, "send_IF5 - Unknown packet_type %x", packet_type); } free(tx_buffer); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); -#ifdef DEBUG_DL_MOBIPASS - if(subframe==0) { - if (dummy_cnt==100) { - LOG_M("txsigmb.m","txs",(void*)dummy_buffer, fp->samples_per_tti,1, 5); - exit(-1); - } else { - dummy_cnt++; - } - } -#endif return; } - -void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type) { +void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int tti, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp=ru->frame_parms; - int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; + int32_t *txp[ru->nb_tx], *rxp[ru->nb_rx]; - uint16_t packet_id=0, i=0, element_id=0; -#ifdef DEBUG_UL_MOBIPASS - //int8_t dummy_buffer_rx[fp->samples_per_tti*2]; - uint8_t rxe; -#endif + uint16_t packet_id=0, i=0; int32_t spp_eth = (int32_t) ru->ifdevice.openair0_cfg->samples_per_packet; int32_t spsf = (int32_t) ru->ifdevice.openair0_cfg->samples_per_frame/10; - void *alaw_buffer = ru->ifbuffer.rx; - uint16_t *data_block = NULL; - uint16_t *j = NULL; - openair0_timestamp timestamp[spsf / spp_eth]; + openair0_timestamp timestamp[ru->nb_rx*spsf / spp_eth]; + long timein[ru->nb_rx*spsf/spp_eth]; + long timeout[ru->nb_rx*spsf/spp_eth]; + struct timespec if_time; + memset(timestamp, 0, sizeof(timestamp)); eth_state_t *eth = (eth_state_t*) (ru->ifdevice.priv); @@ -1333,6 +1227,9 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 if (packet_type == IF5_RRH_GW_DL) { if (eth->compression == ALAW_COMPRESS) { + AssertFatal(1==0,"IF5 compression needs reworking\n"); + +/* if (eth->flags == ETH_RAW_MODE) { data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); } else { @@ -1364,13 +1261,15 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 LOG_D(HW,"[SF %d] Decomperss_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); } +*/ } else if (eth->compression == NO_COMPRESS) { + int subframe = tti; for (i=0; i < fp->nb_antennas_tx; i++) txp[i] = (void*)&ru->common.txdata[i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF5_PKT_ID, packet_id ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 1 ); + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF5_PKT_ID, packet_id ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 1 ); clock_gettime( CLOCK_MONOTONIC, &start_decomp); ru->ifdevice.trx_read_func(&ru->ifdevice, ×tamp[packet_id], @@ -1379,7 +1278,7 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 fp->nb_antennas_tx); clock_gettime( CLOCK_MONOTONIC, &end_decomp); LOG_D(HW,"[SF %d] IF_Read_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 0 ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 0 ); for (i=0; i < fp->nb_antennas_tx; i++) txp[i] += spp_eth; @@ -1389,6 +1288,8 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 } else if (packet_type == IF5_RRH_GW_UL) { if (eth->compression == ALAW_COMPRESS) { + AssertFatal(1==0,"IF5 compression needs reworking\n"); +/* if (eth->flags == ETH_RAW_MODE) { data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); } else { @@ -1419,197 +1320,67 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 LOG_D(HW,"[SF %d] Decomperss_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); } +*/ } else if (eth->compression == NO_COMPRESS) { - for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] = (void*)&ru->common.rxdata[i][subframe*fp->samples_per_tti]; - - for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 1 ); - clock_gettime( CLOCK_MONOTONIC, &start_decomp); - ru->ifdevice.trx_read_func(&ru->ifdevice, + int16_t temp_rx[spp_eth*2] __attribute__((aligned(32))); + NR_DL_FRAME_PARMS *nrfp = ru->nr_frame_parms; + + int offset,siglen; + if (nrfp) { + offset = nrfp->get_samples_slot_timestamp(tti,nrfp,0); + siglen = nrfp->get_samples_per_slot(tti,nrfp); + } + else { + offset = tti*fp->samples_per_subframe; + siglen = spsf; + } + for (i=0; i < ru->nb_rx; i++) + rxp[i] = &ru->common.rxdata[i][offset]; + int aid; + int firstTS=1; + openair0_timestamp oldTS=0; + + for (packet_id=0; packet_id < ru->nb_rx*siglen / spp_eth; packet_id++) { + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 1 ); + clock_gettime( CLOCK_MONOTONIC, &if_time); + timein[packet_id] = if_time.tv_nsec; + ru->ifdevice.trx_read_func2(&ru->ifdevice, ×tamp[packet_id], - (void**)rxp, + (void*)temp_rx, spp_eth, - fp->nb_antennas_rx); + &aid); + clock_gettime( CLOCK_MONOTONIC, &if_time); + timeout[packet_id] = if_time.tv_nsec; + timestamp[packet_id] /= (30720/spsf); + LOG_D(PHY,"TTI %d: Received packet %d: aid %d, TS %llu, oldTS %llu, diff %lld, \n",tti,packet_id,aid,(unsigned long long)timestamp[packet_id],(unsigned long long)oldTS,(unsigned long long)(timestamp[packet_id]-timestamp[0])); + + if (aid==0) { + if (firstTS==1) firstTS=0; + else if (oldTS + 256 != timestamp[packet_id]) { + LOG_I(PHY,"oldTS %llu, newTS %llu, diff %llu, timein %lu, timeout %lu\n",(long long unsigned int)oldTS,(long long unsigned int)timestamp[packet_id],(long long unsigned int)timestamp[packet_id]-oldTS,timein[packet_id],timeout[packet_id]); + for (int i=0;i<=packet_id;i++) LOG_I(PHY,"packet %d TS %llu, timein %lu, timeout %lu\n",i,(long long unsigned int)timestamp[i],timein[i],timeout[i]); + AssertFatal(1==0,"fronthaul problem\n"); + } + + oldTS = timestamp[packet_id]; + } + + + // HYPOTHESIS: first packet per subframe has lowest timestamp of subframe + // should detect out of order and act accordingly .... + AssertFatal(aid==0 || aid==1,"aid %d != 0 or 1\n",aid); + LOG_D(PHY,"rxp[%d] %p, dest %p, offset %d (%llu,%llu)\n",aid,rxp[aid],rxp[aid]+(timestamp[packet_id]-timestamp[0]),(int)(timestamp[packet_id]-timestamp[0]),(long long unsigned int)timestamp[packet_id],(long long unsigned int)timestamp[0]); + memcpy((void*)(rxp[aid]+(timestamp[packet_id]-timestamp[0])), + (void*)temp_rx, + spp_eth<<2); clock_gettime( CLOCK_MONOTONIC, &end_decomp); - LOG_D(HW,"[SF %d] IF_Read_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 0 ); - for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] += spp_eth; + LOG_D(HW,"[TTI %d] IF_Read_Time: %"PRId64"\n",tti,clock_difftime_ns(start_decomp, end_decomp)); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 0 ); } } *proc_timestamp = timestamp[0]; - - } else if (packet_type == IF5_MOBIPASS) { - if (ru->if_timing == synch_to_mobipass_standalone) { - uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES; - openair0_timestamp timestamp_mobipass[fp->samples_per_tti/db_fulllength]; - int32_t *rx_buffer=NULL; - __m128i *data_block=NULL, *data_block_head=NULL; - __m128i *rxp128; - __m128i r0; - - unsigned char _rx_buffer[MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)]; - rx_buffer = (int32_t *)_rx_buffer; - data_block_head = (__m128i *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t); - - rxp[0] = (void*)&ru->common.rxdata[0][subframe*ru->frame_parms->samples_per_tti]; - rxp128 = (__m128i *) (rxp[0]); - - packet_id=0; - while(packet_idsamples_per_tti/db_fulllength) { - data_block = data_block_head; - - ru->ifdevice.trx_read_func(&ru->ifdevice, - ×tamp_mobipass[packet_id], - (void**)&rx_buffer, - db_fulllength, - 1 - ); - - //store rxdata and increase packet_id - rxp[0] = (void*)&ru->common.rxdata[0][(subframe*ru->frame_parms->samples_per_tti)+packet_id*db_fulllength]; - rxp128 = (__m128i *) (rxp[0]); - for (i=0; i>2; i+=2) { - r0 = _mm_loadu_si128(data_block++); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4); - } - packet_id++; - }//end while - - *proc_timestamp = ntohl(timestamp_mobipass[0]); - } else { - - uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES; - openair0_timestamp timestamp_mobipass[fp->samples_per_tti/db_fulllength]; -#ifdef DEBUG_UL_MOBIPASS - int lower_offset = 0; - int upper_offset = 70000; -#endif - int subframe_skip = 0; - int reset_flag = 0; - int32_t *rx_buffer=NULL; - __m128i *data_block=NULL, *data_block_head=NULL; - __m128i *rxp128; - __m128i r0; - - //rx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); - rx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); - IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES); - data_block_head = (__m128i *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t); - - rxp[0] = (void*)&ru->common.rxdata[0][subframe*ru->frame_parms->samples_per_tti]; - rxp128 = (__m128i *) (rxp[0]); - - RU_proc_t *proc = &ru->proc; -/* - // while(packet_idsamples_per_tti/db_fulllength) { - data_block = data_block_head; - - eNB->ifdevice.trx_read_func(&eNB->ifdevice, - &ts0, - (void**)&rx_buffer, - db_fulllength, - 1 - ); - - if ((header->seqno == 1)&&(first_packet==1)) { - first_packet = 0; //ignore the packets before synchnorization - packet_id = 0; - ts_offset = ntohl(ts0); - } - if (first_packet==0) { - packet_cnt++; - ts = ntohl(ts0); - packet_id = (ts-ts_offset)/db_fulllength; - packet_id = packet_id % (fp->samples_per_tti/db_fulllength); - - printf("[IF5_tools]packet_id:%d\n", packet_id); - // if (ts_stored == 0) { - // ts_stored = 1; - *proc_timestamp = ntohl(ts - (packet_id*db_fulllength)); - // } - rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][(subframe*eNB->frame_parms.samples_per_tti)+packet_id*db_fulllength]; - rxp128 = (__m128i *) (rxp[0]); - - for (i=0; i>2; i+=2) { - r0 = _mm_loadu_si128(data_block++); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4); - } - } - // }//end while -*/ - - - packet_id=0; - while(packet_idsamples_per_tti/db_fulllength) { - data_block = data_block_head; - - - ru->ifdevice.trx_read_func(&ru->ifdevice, - ×tamp_mobipass[packet_id], - (void**)&rx_buffer, - db_fulllength, - 1 - ); -#ifdef DEBUG_UL_MOBIPASS - if (((proc->timestamp_tx + lower_offset) > ntohl(timestamp_mobipass[packet_id])) || ((proc->timestamp_tx + upper_offset) < ntohl(timestamp_mobipass[packet_id]))) { - //ignore the packet - subframe_skip_extra = (subframe_skip_extra + 1)%67; - LOG_D("[Mobipass] ignored packet, id:[%d,%d], proc->timestamp_tx:%llu, proc->timestamp_rx:%llu, seqno:%d\n", packet_id,subframe_skip_extra, proc->timestamp_tx, ntohl(timestamp_mobipass[packet_id]), header->seqno); - } -#endif - //skip SUBFRAME_SKIP_NUM_MOBIPASS additional UL packets - if ((start_flag == 1) && (subframe_skip < SUBFRAME_SKIP_NUM_MOBIPASS)){ - subframe_skip++; - offset_cnt = header->seqno; - } else { - if ((offset_cnt != header->seqno) && (start_flag == 0) && (proc->first_rx > 3)){ -#ifdef DEBUG_UL_MOBIPASS - LOG_D(PHY,"[Mobipass] Reset sequence number, offset_cnt:%d, header->seqno:%d, packet_id:%d\n", offset_cnt, header->seqno, packet_id); -#endif - reset_flag=1; - } - if ((reset_flag == 1) && (proc->first_rx > 3 ) && (start_flag == 0) && (packet_id == 0)) { - packet_id = 1; - reset_flag = 0; - } - start_flag = 0; - - //store rxdata and increase packet_id - rxp[0] = (void*)&ru->common.rxdata[0][(subframe*ru->frame_parms->samples_per_tti)+packet_id*db_fulllength]; - rxp128 = (__m128i *) (rxp[0]); - for (i=0; i>2; i+=2) { - r0 = _mm_loadu_si128(data_block++); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4); - } - packet_id++; - offset_cnt = (header->seqno+1)&255; - } - }//end while - - *proc_timestamp = ntohl(timestamp_mobipass[0]); -#ifdef DEBUG_UL_MOBIPASS - LOG_I(PHY,"[Mobipass][Recv_MOBIPASS] timestamp: %llu\n ", *proc_timestamp); - if (eNB->CC_id>0) { - rxe = dB_fixed(signal_energy(rxp[0],fp->samples_per_tti)); - if (rxe > 0){ - LOG_I(PHY,"[Mobipass] frame:%d, subframe:%d, energy %d\n", (*proc_timestamp/(10*fp->samples_per_tti))&1023,subframe, rxe); - - // LOG_M("rxsigmb.m","rxs",(void*)dummy_buffer_rx, fp->samples_per_tti,1, 5); - // exit(-1); - } - } -#endif - free(rx_buffer); - - - } } else { AssertFatal(1==0, "recv_IF5 - Unknown packet_type %x", packet_type); } diff --git a/openair1/PHY/LTE_TRANSPORT/lte_gold_generic.c b/openair1/PHY/LTE_TRANSPORT/lte_gold_generic.c deleted file mode 100644 index b249052cbf..0000000000 --- a/openair1/PHY/LTE_TRANSPORT/lte_gold_generic.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "PHY/types.h" - -/** - \brief Gold Sequence Generation defined in 3x.211 - \param x1 x1 shift register - \param x2 x2 shift register / cinit if reset is set - \param reset Reset flag / reinitialize the generator - \return c 32 bits of gold output -*/ -extern inline uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset) -{ - int32_t n; - - // 3GPP 3x.211 - // Nc = 1600 - // c(n) = [x1(n+Nc) + x2(n+Nc)]mod2 - // x1(n+31) = [x1(n+3) + x1(n)]mod2 - // x2(n+31) = [x2(n+3) + x2(n+2) + x2(n+1) + x2(n)]mod2 - if (reset) - { - // Init value for x1: x1(0) = 1, x1(n) = 0, n=1,2,...,30 - // x1(31) = [x1(3) + x1(0)]mod2 = 1 - *x1 = 1 + (1<<31); - // Init value for x2: cinit = sum_{i=0}^30 x2*2^i - // x2(31) = [x2(3) + x2(2) + x2(1) + x2(0)]mod2 - // = (*x2>>3) ^ (*x2>>2) + (*x2>>1) + *x2 - *x2 = *x2 ^ ((*x2 ^ (*x2>>1) ^ (*x2>>2) ^ (*x2>>3))<<31); - - // x1 and x2 contain bits n = 0,1,...,31 - - // Nc = 1600 bits are skipped at the beginning - // i.e., 1600 / 32 = 50 32bit words - - for (n = 1; n < 50; n++) - { - // Compute x1(0),...,x1(27) - *x1 = (*x1>>1) ^ (*x1>>4); - // Compute x1(28),..,x1(31) and xor - *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28); - // Compute x2(0),...,x2(27) - *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4); - // Compute x2(28),..,x2(31) and xor - *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28); - } - } - - *x1 = (*x1>>1) ^ (*x1>>4); - *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28); - *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4); - *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28); - - // c(n) = [x1(n+Nc) + x2(n+Nc)]mod2 - return(*x1^*x2); -} diff --git a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c index 6144b978bf..38914506ee 100644 --- a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c +++ b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c @@ -147,10 +147,10 @@ uint32_t get_TBS_UL(uint8_t mcs, uint16_t nb_rb) { } } -int adjust_G2(LTE_DL_FRAME_PARMS *frame_parms, uint32_t *rb_alloc, uint8_t mod_order, uint8_t subframe, uint8_t symbol) { +int adjust_G2(int Ncp, int frame_type, int N_RB_DL, uint32_t *rb_alloc, uint8_t mod_order, uint8_t subframe, uint8_t symbol) { int rb,re_pbch_sss=0; int rb_alloc_ind,nsymb; - nsymb = (frame_parms->Ncp==NORMAL) ? 14 : 12; + nsymb = (Ncp==NORMAL) ? 14 : 12; // printf("adjust_G2 : symbol %d, subframe %d\n",symbol,subframe); if ((subframe!=0) && (subframe!=5) && (subframe!=6)) // if not PBCH/SSS or SSS @@ -158,12 +158,12 @@ int adjust_G2(LTE_DL_FRAME_PARMS *frame_parms, uint32_t *rb_alloc, uint8_t mod_o //first half of slot and TDD (no adjustments in first slot except for subframe 6 - PSS) if ((symbol<(nsymb>>1))&& - (frame_parms->frame_type == TDD)&& + (frame_type == TDD)&& (subframe!=6)) return(0); // after PBCH - if (frame_parms->frame_type==TDD) { //TDD + if (frame_type==TDD) { //TDD if ((symbol>((nsymb>>1)+3)) && (symbol!=(nsymb-1))) ///SSS return(0); @@ -185,9 +185,9 @@ int adjust_G2(LTE_DL_FRAME_PARMS *frame_parms, uint32_t *rb_alloc, uint8_t mod_o return(0); } - if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL - for (rb=((frame_parms->N_RB_DL>>1)-3); - rb<=((frame_parms->N_RB_DL>>1)+3); + if ((N_RB_DL&1) == 1) { // ODD N_RB_DL + for (rb=((N_RB_DL>>1)-3); + rb<=((N_RB_DL>>1)+3); rb++) { if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; @@ -201,16 +201,16 @@ int adjust_G2(LTE_DL_FRAME_PARMS *frame_parms, uint32_t *rb_alloc, uint8_t mod_o rb_alloc_ind = 0; if (rb_alloc_ind==1) { - if ((rb==(frame_parms->N_RB_DL>>1)-3) || - (rb==((frame_parms->N_RB_DL>>1)+3))) { + if ((rb==(N_RB_DL>>1)-3) || + (rb==((N_RB_DL>>1)+3))) { re_pbch_sss += 6; } else re_pbch_sss += 12; } } } else { - for (rb=((frame_parms->N_RB_DL>>1)-3); - rb<((frame_parms->N_RB_DL>>1)+3); + for (rb=((N_RB_DL>>1)-3); + rb<((N_RB_DL>>1)+3); rb++) { if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; diff --git a/openair1/PHY/LTE_TRANSPORT/pbch.c b/openair1/PHY/LTE_TRANSPORT/pbch.c index dfa990269e..8e9a968827 100644 --- a/openair1/PHY/LTE_TRANSPORT/pbch.c +++ b/openair1/PHY/LTE_TRANSPORT/pbch.c @@ -72,6 +72,7 @@ int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, first_re=0; last_re=12; + for (re=first_re; resubframe_tx; phich_config_t *phich; @@ -748,16 +749,20 @@ void generate_phich_top(PHY_VARS_eNB *eNB, nseq_PHICH = ((phich->first_rb/Ngroup_PHICH) + phich->n_DMRS)%(2*NSF_PHICH); + harq_pid = subframe2harq_pid(frame_parms,phich_frame2_pusch_frame(frame_parms,proc->frame_tx,subframe),pusch_subframe); + if (harq_pid == 255) { + LOG_E(PHY,"FATAL ERROR: illegal harq_pid, returning\n"); + return; + } LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Generating PHICH, AMP %d ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d)\n", - eNB->Mod_id,subframe2harq_pid(frame_parms, - phich_frame2_pusch_frame(frame_parms,proc->frame_tx,subframe),pusch_subframe),proc->frame_tx, + eNB->Mod_id,harq_pid,proc->frame_tx, subframe,amp,ngroup_PHICH,Ngroup_PHICH,nseq_PHICH, phich->hi, phich->first_rb); T(T_ENB_PHY_PHICH, T_INT(eNB->Mod_id), T_INT(proc->frame_tx), T_INT(subframe), T_INT(-1 /* TODO: rnti */), - T_INT(subframe2harq_pid(frame_parms,phich_frame2_pusch_frame(frame_parms,proc->frame_tx,subframe),pusch_subframe)), + T_INT(harq_pid), T_INT(Ngroup_PHICH), T_INT(NSF_PHICH), T_INT(ngroup_PHICH), T_INT(nseq_PHICH), T_INT(phich->hi), diff --git a/openair1/PHY/LTE_TRANSPORT/phich_common.c b/openair1/PHY/LTE_TRANSPORT/phich_common.c index 89c826be66..302229b88d 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich_common.c +++ b/openair1/PHY/LTE_TRANSPORT/phich_common.c @@ -102,6 +102,34 @@ unsigned char subframe2_ul_harq(LTE_DL_FRAME_PARMS *frame_parms,unsigned char su return(subframe&7); switch (frame_parms->tdd_config) { + case 1: + if (subframe == 6) { + return(0); + } else if (subframe==9){ + return(1); + } else if (subframe==1){ + return(2); + } else if (subframe==4){ + return(3); + } else { + LOG_E(PHY,"phich.c: subframe2_ul_harq, illegal subframe %d for tdd_config %d\n", + subframe,frame_parms->tdd_config); + return(0); + } + + break; + case 2: + if (subframe == 3) { + return(1); + } else if (subframe==8){ + return(0); + } else { + LOG_E(PHY,"phich.c: subframe2_ul_harq, illegal subframe %d for tdd_config %d\n", + subframe,frame_parms->tdd_config); + return(0); + } + + break; case 3: if ( (subframe == 8) || (subframe == 9) ) { return(subframe-8); diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 7b508239a9..37fe0d17ae 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -24,22 +24,6 @@ #include "transport_eNB.h" #include "transport_proto.h" #include "transport_common_proto.h" -// Mask for identifying subframe for MBMS -#define MBSFN_TDD_SF3 0x80// for TDD -#define MBSFN_TDD_SF4 0x40 -#define MBSFN_TDD_SF7 0x20 -#define MBSFN_TDD_SF8 0x10 -#define MBSFN_TDD_SF9 0x08 - - - -#define MBSFN_FDD_SF1 0x80// for FDD -#define MBSFN_FDD_SF2 0x40 -#define MBSFN_FDD_SF3 0x20 -#define MBSFN_FDD_SF6 0x10 -#define MBSFN_FDD_SF7 0x08 -#define MBSFN_FDD_SF8 0x04 - diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 24faf584d3..eb46a8d663 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -31,7 +31,7 @@ */ #include "PHY/sse_intrin.h" #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" +//#include "PHY/phy_extern.h" //#include "prach.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" @@ -40,6 +40,7 @@ #include "prach_extern.h" #include #include +#include "common/utils/lte/prach_utils.h" void rx_prach0(PHY_VARS_eNB *eNB, RU_t *ru, @@ -84,12 +85,12 @@ void rx_prach0(PHY_VARS_eNB *eNB, uint8_t aa; int32_t lev; int16_t levdB; - int fft_size,log2_ifft_size; + int fft_size=0,log2_ifft_size; int16_t prach_ifft_tmp[2048*2] __attribute__((aligned(32))); int32_t *prach_ifft=(int32_t *)NULL; int32_t **prach_ifftp=(int32_t **)NULL; int prach_ifft_cnt=0; - + int exit_flag=0; LTE_DL_FRAME_PARMS *fp; int nb_rx; if(eNB) { @@ -112,7 +113,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, prach_ConfigIndex = fp->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[ce_level]; Ncs_config = fp->prach_emtc_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; restricted_set = fp->prach_emtc_config_common.prach_ConfigInfo.highSpeedFlag; - n_ra_prb = get_prach_prb_offset(fp,prach_ConfigIndex, + n_ra_prb = get_prach_prb_offset(fp->frame_type,fp->tdd_config,fp->N_RB_UL,fp->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[ce_level], fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level], tdd_mapindex,Nf); // update pointers to results for ce_level @@ -124,7 +125,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, prach_ConfigIndex = fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; Ncs_config = fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; restricted_set = fp->prach_config_common.prach_ConfigInfo.highSpeedFlag; - n_ra_prb = get_prach_prb_offset(fp,prach_ConfigIndex, + n_ra_prb = get_prach_prb_offset(fp->frame_type,fp->tdd_config,fp->N_RB_UL,fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset, tdd_mapindex,Nf); } @@ -140,7 +141,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, rxsigF = eNB->prach_vars_br.rxsigF[ce_level]; if (LOG_DEBUGFLAG(PRACH)) { - if (((frame_prach)&1023) < 20) LOG_I(PHY, + if (((frame_prach)&1023) < 20) LOG_D(PHY, "PRACH (eNB) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d, rootSequenceIndex %d, repetition number %d,numRepetitionsPrePreambleAttempt %d\n", br_flag,ce_level,frame_prach,subframe, fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level], @@ -153,56 +154,57 @@ void rx_prach0(PHY_VARS_eNB *eNB, prachF = eNB->prach_vars.prachF; rxsigF = eNB->prach_vars.rxsigF[0]; - if (LOG_DEBUGFLAG(PRACH)) { - if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe, + //if (LOG_DEBUGFLAG(PRACH)) { + if (((frame_prach)&1023) < 20) LOG_D(PHY,"PRACH (eNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe, fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex,rootSequenceIndex); - } + //} } } else { if (br_flag == 1) { rxsigF = ru->prach_rxsigF_br[ce_level]; if (LOG_DEBUGFLAG(PRACH)) { - if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + if (((frame_prach)&1023) < 20) LOG_D(PHY,"PRACH (RU) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", br_flag,ce_level,frame_prach,subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex); } } else { - rxsigF = ru->prach_rxsigF; + rxsigF = ru->prach_rxsigF[0]; if (LOG_DEBUGFLAG(PRACH)) { - if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + if (((frame_prach)&1023) < 20) LOG_D(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex); } } } AssertFatal(ru!=NULL,"ru is null\n"); - + int8_t dBEn0=0; for (aa=0; aaif_south == LOCAL_RF) { // set the time-domain signal if we have to use it in this node + if (ru->if_south == LOCAL_RF || ru->function == NGFI_RAU_IF5) { // set the time-domain signal if we have to use it in this node // DJP - indexing below in subframe zero takes us off the beginning of the array??? prach[aa] = (int16_t *)&ru->common.rxdata[aa][(subframe*fp->samples_per_tti)-ru->N_TA_offset]; if (LOG_DUMPFLAG(PRACH)) { int32_t en0=signal_energy((int32_t *)prach[aa],fp->samples_per_tti); - int8_t dbEn0 = dB_fixed(en0); - int8_t rach_dBm = dbEn0 - ru->rx_total_gain_dB; + dBEn0 = dB_fixed(en0); + int8_t rach_dBm = dBEn0 - ru->rx_total_gain_dB; char buffer[80]; - if (dbEn0>32 && prach[0]!= NULL) { + if (dBEn0>30 && prach[0]!= NULL) { static int counter=0; - sprintf(buffer, "%s%d", "/tmp/prach_rx",counter); - LOG_M(buffer,"prach_rx",prach[0],fp->samples_per_tti,1,13); + sprintf(buffer, "%s%d", "/tmp/prach_rx.m",counter); + LOG_M(buffer,"prach_rx",prach[0],fp->samples_per_tti,1,1); + exit_flag=1; } - if (dB_fixed(en0)>32) { + if (dBEn0>30) { sprintf(buffer, "rach_dBm:%d",rach_dBm); - if (prach[0]!= NULL) LOG_M("prach_rx","prach_rx",prach[0],fp->samples_per_tti,1,1); + if (prach[0]!= NULL) LOG_M("prach_rx.m","prach_rx",prach[0],fp->samples_per_tti,1,1); LOG_I(PHY,"RU %d, br_flag %d ce_level %d frame %d subframe %d per_tti:%d prach:%p (energy %d) TA:%d %s rxdata:%p index:%d\n", ru->idx,br_flag,ce_level,frame_prach,subframe,fp->samples_per_tti, - prach[aa],dbEn0,ru->N_TA_offset,buffer,ru->common.rxdata[aa], + prach[aa],dBEn0,ru->N_TA_offset,buffer,ru->common.rxdata[aa], (subframe*fp->samples_per_tti)-ru->N_TA_offset); } } @@ -298,11 +300,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 6: if (prach_fmt == 4) { dft(DFT_256,prach2,rxsigF[aa],1); + fft_size=256; } else { dft(DFT_1536,prach2,rxsigF[aa],1); if (prach_fmt>1) dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); + fft_size=1536; } break; @@ -310,13 +314,14 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 15: if (prach_fmt == 4) { dft(DFT_256,prach2,rxsigF[aa],1); + fft_size=256; } else { dft(DFT_3072,prach2,rxsigF[aa],1); if (prach_fmt>1) dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); } - + fft_size=3072; break; case 25: @@ -338,11 +343,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 50: if (prach_fmt == 4) { dft(DFT_2048,prach2,rxsigF[aa],1); + fft_size=2048; } else { dft(DFT_12288,prach2,rxsigF[aa],1); if (prach_fmt>1) dft(DFT_12288,prach2+24576,rxsigF[aa]+24576,1); + fft_size=12288; } break; @@ -350,11 +357,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 75: if (prach_fmt == 4) { dft(DFT_3072,prach2,rxsigF[aa],1); + fft_size=3072; } else { dft(DFT_18432,prach2,rxsigF[aa],1); if (prach_fmt>1) dft(DFT_18432,prach2+36864,rxsigF[aa]+36864,1); + fft_size=18432; } break; @@ -363,20 +372,24 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (fp->threequarter_fs==0) { if (prach_fmt == 4) { dft(DFT_4096,prach2,rxsigF[aa],1); + fft_size=2048; } else { dft(DFT_24576,prach2,rxsigF[aa],1); if (prach_fmt>1) dft(DFT_24576,prach2+49152,rxsigF[aa]+49152,1); + fft_size=24576; } } else { if (prach_fmt == 4) { dft(DFT_3072,prach2,rxsigF[aa],1); + fft_size=3072; } else { dft(DFT_18432,prach2,rxsigF[aa],1); if (prach_fmt>1) dft(DFT_18432,prach2+36864,rxsigF[aa]+36864,1); + fft_size=18432; } } @@ -415,7 +428,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if ( LOG_DEBUGFLAG(PRACH)) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if ((en > 60)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,frame_prach,subframe,en); + if ((en > 10)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,frame_prach,subframe,en); } } @@ -454,9 +467,9 @@ void rx_prach0(PHY_VARS_eNB *eNB, for (preamble_index=0 ; preamble_index<64 ; preamble_index++) { if (LOG_DEBUGFLAG(PRACH)) { - int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); + // int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",frame_prach,subframe,preamble_index,br_flag); + if (dBEn0>30) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",frame_prach,subframe,preamble_index,br_flag); } if (restricted_set == 0) { @@ -539,14 +552,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, // Compute DFT of RX signal (conjugate input, results in conjugate output) for each new rootSequenceIndex if (LOG_DEBUGFLAG(PRACH)) { - int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); + //en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d : preamble index %d: offset %d, preamble shift %d (br_flag %d, en %d)\n", - frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en); + if (dBEn0>30) LOG_I(PHY,"frame %d, subframe %d : preamble index %d: offset %d, preamble shift %d (br_flag %d, en %d)\n", + frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,dBEn0); } log2_ifft_size = 10; - fft_size = 6144; if (new_dft == 1) { new_dft = 0; @@ -564,13 +576,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, memset(prachF, 0, sizeof(int16_t)*2*1024 ); - if (LOG_DUMPFLAG(PRACH)) { + if (LOG_DUMPFLAG(PRACH)) { if (prach[0]!= NULL) LOG_M("prach_rx0.m","prach_rx0",prach[0],6144+792,1,1); LOG_M("prach_rx1.m","prach_rx1",prach[1],6144+792,1,1); LOG_M("prach_rxF0.m","prach_rxF0",rxsigF[0],12288,1,1); LOG_M("prach_rxF1.m","prach_rxF1",rxsigF[1],12288,1,1); - } + } for (aa=0; aa*max_preamble_energy) { *max_preamble_energy = levdB; @@ -633,9 +645,9 @@ void rx_prach0(PHY_VARS_eNB *eNB, *max_preamble = preamble_index; if (LOG_DEBUGFLAG(PRACH)) { - int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); + // int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if ((en>60) && (br_flag==1)) + if (dBEn0>30) LOG_D(PHY,"frame %d, subframe %d : max_preamble_energy %d, max_preamble_delay %d, max_preamble %d (br_flag %d,ce_level %d, levdB %d, lev %d)\n", frame_prach,subframe, *max_preamble_energy,*max_preamble_delay, @@ -648,10 +660,10 @@ void rx_prach0(PHY_VARS_eNB *eNB, *avg_preamble_energy=dB_fixed(avg_en/64); - if (LOG_DUMPFLAG(PRACH)) { + if (exit_flag==1) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) { + if (en>30) { k = (12*n_ra_prb) - 6*fp->N_RB_UL; if (k<0) k+=fp->ofdm_symbol_size; @@ -665,19 +677,20 @@ void rx_prach0(PHY_VARS_eNB *eNB, LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); LOG_M("Xu.m","xu",Xu,N_ZC,1,1); LOG_M("prach_ifft0.m","prach_t0",prach_ifft,1024,1,1); - exit(-1); + LOG_M("SF2_3.m","sf2_3",&ru->common.rxdata[0][2*fp->samples_per_tti],2*fp->samples_per_tti,1,1); } else { LOG_E(PHY,"Dumping prach (br_flag %d), k = %d (n_ra_prb %d)\n",br_flag,k,n_ra_prb); LOG_M("rxsigF_br.m","prach_rxF_br",&rxsigF[0][0],12288,1,1); LOG_M("prach_rxF_comp0_br.m","prach_rxF_comp0_br",prachF,1024,1,1); LOG_M("Xu_br.m","xu_br",Xu,N_ZC,1,1); LOG_M("prach_ifft0_br.m","prach_t0_br",prach_ifft,1024,1,1); - exit(-1); } } } /* LOG_DUMPFLAG(PRACH) */ if (eNB) stop_meas(&eNB->rx_prach); + AssertFatal(exit_flag==0,"exiting\n"); + } diff --git a/openair1/PHY/LTE_TRANSPORT/prach_common.c b/openair1/PHY/LTE_TRANSPORT/prach_common.c index 393d4ca3f8..e366e8edbc 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach_common.c +++ b/openair1/PHY/LTE_TRANSPORT/prach_common.c @@ -34,7 +34,7 @@ #include "PHY/phy_extern.h" #include "PHY/phy_extern_ue.h" #include "common/utils/LOG/vcd_signal_dumper.h" - +#include "common/utils/lte/prach_utils.h" uint16_t NCS_unrestricted[16] = {0,13,15,18,22,26,32,38,46,59,76,93,119,167,279,419}; uint16_t NCS_restricted[15] = {15,18,22,26,32,38,46,55,68,82,100,128,158,202,237}; // high-speed case @@ -44,6 +44,9 @@ int16_t ru[2*839]; // quantized roots of unity uint32_t ZC_inv[839]; // multiplicative inverse for roots u uint16_t du[838]; +extern PRACH_TDD_PREAMBLE_MAP tdd_preamble_map[64][7]; + +/* // This is table 5.7.1-4 from 36.211 PRACH_TDD_PREAMBLE_MAP tdd_preamble_map[64][7] = { // TDD Configuration Index 0 @@ -254,7 +257,7 @@ PRACH_TDD_PREAMBLE_MAP tdd_preamble_map[64][7] = { } }; - +*/ uint16_t prach_root_sequence_map0_3[838] = { 129, 710, 140, 699, 120, 719, 210, 629, 168, 671, 84, 755, 105, 734, 93, 746, 70, 769, 60, 779, 2, 837, 1, 838, @@ -378,192 +381,13 @@ uint8_t get_fid_prach_tdd(module_id_t Mod_id,uint8_t tdd_map_index) { return(tdd_preamble_map[fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex][fp->tdd_config].map[tdd_map_index].f_ra); } -uint8_t get_prach_fmt(uint8_t prach_ConfigIndex,lte_frame_type_t frame_type) { - if (frame_type == FDD) // FDD - return(prach_ConfigIndex>>4); - else { - if (prach_ConfigIndex < 20) - return (0); - - if (prach_ConfigIndex < 30) - return (1); - - if (prach_ConfigIndex < 40) - return (2); - - if (prach_ConfigIndex < 48) - return (3); - else - return (4); - } -} - -uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, - uint8_t prach_ConfigIndex, - uint8_t n_ra_prboffset, - uint8_t tdd_mapindex, uint16_t Nf) { - lte_frame_type_t frame_type = frame_parms->frame_type; - uint8_t tdd_config = frame_parms->tdd_config; - uint8_t n_ra_prb; - uint8_t f_ra,t1_ra; - uint8_t prach_fmt = get_prach_fmt(prach_ConfigIndex,frame_type); - uint8_t Nsp=2; - - if (frame_type == TDD) { // TDD - if (tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach==0) { - LOG_E(PHY, "Illegal prach_ConfigIndex %"PRIu8"", prach_ConfigIndex); - return(-1); - } - - // adjust n_ra_prboffset for frequency multiplexing (p.36 36.211) - f_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[tdd_mapindex].f_ra; - - if (prach_fmt < 4) { - if ((f_ra&1) == 0) { - n_ra_prb = n_ra_prboffset + 6*(f_ra>>1); - } else { - n_ra_prb = frame_parms->N_RB_UL - 6 - n_ra_prboffset + 6*(f_ra>>1); - } - } else { - if ((tdd_config >2) && (tdd_config<6)) - Nsp = 2; - - t1_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t1_ra; - - if ((((Nf&1)*(2-Nsp)+t1_ra)&1) == 0) { - n_ra_prb = 6*f_ra; - } else { - n_ra_prb = frame_parms->N_RB_UL - 6*(f_ra+1); - } - } - } else { //FDD - n_ra_prb = n_ra_prboffset; - } - - return(n_ra_prb); -} - -int is_prach_subframe0(LTE_DL_FRAME_PARMS *frame_parms,uint8_t prach_ConfigIndex,uint32_t frame, uint8_t subframe) { - // uint8_t prach_ConfigIndex = frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; - uint8_t tdd_config = frame_parms->tdd_config; - uint8_t t0_ra; - uint8_t t1_ra; - uint8_t t2_ra; - int prach_mask = 0; - - if (frame_parms->frame_type == FDD) { //FDD - //implement Table 5.7.1-2 from 36.211 (Rel-10, p.41) - if ((((frame&1) == 1) && (subframe < 9)) || - (((frame&1) == 0) && (subframe == 9))) // This is an odd frame, ignore even-only PRACH frames - if (((prach_ConfigIndex&0xf)<3) || // 0,1,2,16,17,18,32,33,34,48,49,50 - ((prach_ConfigIndex&0x1f)==18) || // 18,50 - ((prach_ConfigIndex&0xf)==15)) // 15,47 - return(0); - - switch (prach_ConfigIndex&0x1f) { - case 0: - case 3: - if (subframe==1) prach_mask = 1; - - break; - - case 1: - case 4: - if (subframe==4) prach_mask = 1; - - break; - - case 2: - case 5: - if (subframe==7) prach_mask = 1; - - break; - - case 6: - if ((subframe==1) || (subframe==6)) prach_mask=1; - - break; - - case 7: - if ((subframe==2) || (subframe==7)) prach_mask=1; - - break; - - case 8: - if ((subframe==3) || (subframe==8)) prach_mask=1; - - break; - - case 9: - if ((subframe==1) || (subframe==4) || (subframe==7)) prach_mask=1; - - break; - - case 10: - if ((subframe==2) || (subframe==5) || (subframe==8)) prach_mask=1; - - break; - - case 11: - if ((subframe==3) || (subframe==6) || (subframe==9)) prach_mask=1; - - break; - - case 12: - if ((subframe&1)==0) prach_mask=1; - - break; - - case 13: - if ((subframe&1)==1) prach_mask=1; - - break; - - case 14: - prach_mask=1; - break; - - case 15: - if (subframe==9) prach_mask=1; - - break; - } - } else { // TDD - AssertFatal(prach_ConfigIndex<64, - "Illegal prach_ConfigIndex %d for ",prach_ConfigIndex); - AssertFatal(tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach>0, - "Illegal prach_ConfigIndex %d for ",prach_ConfigIndex); - t0_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t0_ra; - t1_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t1_ra; - t2_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t2_ra; -#ifdef PRACH_DEBUG - LOG_I(PHY,"[PRACH] Checking for PRACH format (ConfigIndex %d) in TDD subframe %d (%d,%d,%d)\n", - prach_ConfigIndex, - subframe, - t0_ra,t1_ra,t2_ra); -#endif - - if ((((t0_ra == 1) && ((frame &1)==0))|| // frame is even and PRACH is in even frames - ((t0_ra == 2) && ((frame &1)==1))|| // frame is odd and PRACH is in odd frames - (t0_ra == 0)) && // PRACH is in all frames - (((subframe<5)&&(t1_ra==0)) || // PRACH is in 1st half-frame - (((subframe>4)&&(t1_ra==1))))) { // PRACH is in 2nd half-frame - if ((prach_ConfigIndex<48) && // PRACH only in normal UL subframe - (((subframe%5)-2)==t2_ra)) prach_mask=1; - else if ((prach_ConfigIndex>47) && (((subframe%5)-1)==t2_ra)) prach_mask=1; // PRACH can be in UpPTS - } - } - - return(prach_mask); -} - int is_prach_subframe(LTE_DL_FRAME_PARMS *frame_parms, uint32_t frame, uint8_t subframe) { uint8_t prach_ConfigIndex = frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; - int prach_mask = is_prach_subframe0(frame_parms, prach_ConfigIndex, frame, subframe); + int prach_mask = is_prach_subframe0(frame_parms->tdd_config,frame_parms->frame_type, prach_ConfigIndex, frame, subframe); for (int i=0; i<4; i++) { if (frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i] == 1) - prach_mask |= (is_prach_subframe0(frame_parms, frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i], + prach_mask |= (is_prach_subframe0(frame_parms->tdd_config,frame_parms->frame_type, frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i], frame, subframe) << (i+1)); } diff --git a/openair1/PHY/LTE_TRANSPORT/prach_extern.h b/openair1/PHY/LTE_TRANSPORT/prach_extern.h index 47fbd93ad7..3404646923 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach_extern.h +++ b/openair1/PHY/LTE_TRANSPORT/prach_extern.h @@ -35,7 +35,7 @@ #include "PHY/sse_intrin.h" #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" +//#include "PHY/phy_extern.h" //#define PRACH_DEBUG 1 //#define PRACH_WRITE_OUTPUT_DEBUG 1 @@ -74,17 +74,6 @@ uint8_t get_num_prach_tdd(module_id_t Mod_id); uint8_t get_fid_prach_tdd(module_id_t Mod_id,uint8_t tdd_map_index); -uint8_t get_prach_fmt(uint8_t prach_ConfigIndex,lte_frame_type_t frame_type); - - -uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, - uint8_t prach_ConfigIndex, - uint8_t n_ra_prboffset, - uint8_t tdd_mapindex, uint16_t Nf); - - -int is_prach_subframe0(LTE_DL_FRAME_PARMS *frame_parms,uint8_t prach_ConfigIndex,uint32_t frame, uint8_t subframe); - int is_prach_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t subframe); diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index 031c97e50d..44f57f4304 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -36,10 +36,8 @@ #include "PHY/extern.h" #include "SCHED/extern.h" -#ifdef OPENAIR2 #include "openair2/LAYER2/MAC/proto.h" #include "openair2/RRC/L2_INTERFACE/openair_rrc_L2_interface.h" -#endif extern int mac_get_rrc_status(uint8_t Mod_id,uint8_t eNB_flag,uint8_t index); @@ -434,10 +432,8 @@ int dump_ue_stats(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,char *buffer, int length break; } -#ifdef OPENAIR2 RRC_status = mac_UE_get_rrc_status(ue->Mod_id, 0); len += sprintf(&buffer[len],"[UE PROC] RRC status = %d\n",RRC_status); -#endif len += sprintf(&buffer[len], "[UE PROC] Transmission Mode %d \n",ue->transmission_mode[eNB]); len += sprintf(&buffer[len], "[UE PROC] PBCH err conseq %d, PBCH error total %d, PBCH FER %d\n", ue->pbch_vars[eNB]->pdu_errors_conseq, diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 8637e80137..998edf235f 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -65,10 +65,41 @@ int16_t cfo_pucch_ep[24*6] = {24278,-22005,29621,-14010,32412,-4808,32412,4807,2 +void dump_uci_stats(FILE *fd,PHY_VARS_eNB *eNB,int frame) { + + int strpos=0; + char output[16384]; + + for (int i=0;iuci_stats[i].rnti>0) { + eNB_UCI_STATS_t *uci_stats = &eNB->uci_stats[i]; + strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch1_trials %d, pucch1_n0 %d dB, pucch1_thres %d dB, current pucch1_stat_pos %d dB, current pucch1_stat_neg %d dB, positive SR count %d\n", + i,uci_stats->rnti,uci_stats->pucch1_trials,eNB->measurements.n0_pucch_dB/*max(eNB->measurements.n0_subband_power_tot_dB[0], eNB->measurements.n0_subband_power_tot_dB[eNB->frame_parms.N_RB_UL-1])*/,uci_stats->pucch1_thres,dB_fixed(uci_stats->current_pucch1_stat_pos),dB_fixed(uci_stats->current_pucch1_stat_neg),uci_stats->pucch1_positive_SR); + strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch1_low (%d,%d)dB pucch1_high (%d,%d)dB\n", + i,uci_stats->rnti, + dB_fixed(uci_stats->pucch1_low_stat[0]), + dB_fixed(uci_stats->pucch1_low_stat[1]), + dB_fixed(uci_stats->pucch1_high_stat[0]), + dB_fixed(uci_stats->pucch1_high_stat[1])); + + strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch1a_trials %d, pucch1a_stat (%d,%d), pucch1b_trials %d, pucch1b_stat (%d,%d) pucch1ab_DTX %d\n", + i,uci_stats->rnti, + uci_stats->pucch1a_trials, + uci_stats->current_pucch1a_stat_re, + uci_stats->current_pucch1a_stat_im, + uci_stats->pucch1b_trials, + uci_stats->current_pucch1b_stat_re, + uci_stats->current_pucch1b_stat_im, + uci_stats->pucch1ab_DTX); + } + } + if (fd) fprintf(fd,"%s",output); + else printf("%s",output); +} /* PUCCH format3 >> */ /* SubCarrier Demap */ uint16_t pucchfmt3_subCarrierDeMapping( PHY_VARS_eNB *eNB, - int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2], + int16_t SubCarrierDeMapData[4][14][12][2], uint16_t n3_pucch ) { LTE_eNB_COMMON *eNB_common_vars = &eNB->common_vars; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; @@ -118,8 +149,8 @@ uint16_t pucchfmt3_subCarrierDeMapping( PHY_VARS_eNB *eNB, } /* cyclic shift hopping remove */ -uint16_t pucchfmt3_Baseseq_csh_remove( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2], - int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2], +uint16_t pucchfmt3_Baseseq_csh_remove( int16_t SubCarrierDeMapData[4][14][12][2], + int16_t CshData_fmt3[4][14][12][2], LTE_DL_FRAME_PARMS *frame_parms, uint8_t subframe, uint8_t ncs_cell[20][7] ) { @@ -169,9 +200,9 @@ const int16_t TBL_3_SF5_GEN_N_DASH_NS[MAXROW_TBL_SF5_OS_IDX] = {0,3,6,8,10}; const int16_t TBL_3_SF4_GEN_N_DASH_NS[MAXROW_TBL_SF4_OS_IDX] = {0,3,6,9}; /* Channel estimation */ -uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2], - double delta_theta[NB_ANTENNAS_RX][12], - int16_t ChestValue[NB_ANTENNAS_RX][2][12][2], +uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[4][14][12][2], + double delta_theta[4][12], + int16_t ChestValue[4][2][12][2], int16_t *Interpw, uint8_t subframe, uint8_t shortened_format, @@ -183,12 +214,12 @@ uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX int16_t np, np_n, ip_ind=-1; //int16_t npucch_sf; int16_t calctmp[2]; - int16_t BsCshData[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2]; - //int16_t delta_theta_calctmp[NB_ANTENNAS_RX][4][D_NSC1RB][2], delta_theta_comp[NB_ANTENNAS_RX][D_NSC1RB][2]; - int16_t delta_theta_comp[NB_ANTENNAS_RX][D_NSC1RB][2]; - int16_t CsData_allavg[NB_ANTENNAS_RX][14][2]; - int16_t CsData_temp[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2]; - int32_t IP_CsData_allsfavg[NB_ANTENNAS_RX][14][4][2]; + int16_t BsCshData[4][D_NSYM1SF][D_NSC1RB][2]; + //int16_t delta_theta_calctmp[4][4][D_NSC1RB][2], delta_theta_comp[4][D_NSC1RB][2]; + int16_t delta_theta_comp[4][D_NSC1RB][2]; + int16_t CsData_allavg[4][14][2]; + int16_t CsData_temp[4][D_NSYM1SF][D_NSC1RB][2]; + int32_t IP_CsData_allsfavg[4][14][4][2]; int32_t IP_allavg[D_NPUCCH_SF5]; //int16_t temp_ch[2]; int16_t m[NUMBER_OF_UE_MAX], m_self=0, same_m_number; @@ -432,9 +463,9 @@ uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX } /* Channel Equalization */ -uint16_t pucchfmt3_Equalization( int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2], - int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2], - int16_t ChestValue[NB_ANTENNAS_RX][2][12][2], +uint16_t pucchfmt3_Equalization( int16_t CshData_fmt3[4][14][12][2], + int16_t ChdetAfterValue_fmt3[4][14][12][2], + int16_t ChestValue[4][2][12][2], LTE_DL_FRAME_PARMS *frame_parms) { int16_t aa, sltNo, symNo, k; @@ -457,9 +488,9 @@ uint16_t pucchfmt3_Equalization( int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2] } /* Frequency deviation remove AFC */ -uint16_t pucchfmt3_FrqDevRemove( int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2], - double delta_theta[NB_ANTENNAS_RX][12], - int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2], +uint16_t pucchfmt3_FrqDevRemove( int16_t ChdetAfterValue_fmt3[4][14][12][2], + double delta_theta[4][12], + int16_t RemoveFrqDev_fmt3[4][2][5][12][2], LTE_DL_FRAME_PARMS *frame_parms ) { int16_t aa, sltNo, symNo1slt, k, n; double calctmp[2]; @@ -509,8 +540,8 @@ const int16_t TBL_3_SF4[MAXROW_TBL_SF4_fmt3][MAXCLM_TBL_SF4][2] = { }; /* orthogonal sequence remove */ -uint16_t pucchfmt3_OrthSeqRemove( int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2], - int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2], +uint16_t pucchfmt3_OrthSeqRemove( int16_t RemoveFrqDev_fmt3[4][2][5][12][2], + int16_t Fmt3xDataRmvOrth[4][2][5][12][2], uint8_t shortened_format, uint16_t n3_pucch, LTE_DL_FRAME_PARMS *frame_parms ) { @@ -556,7 +587,7 @@ uint16_t pucchfmt3_OrthSeqRemove( int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5 } /* averaging antenna */ -uint16_t pucchfmt3_AvgAnt( int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2], +uint16_t pucchfmt3_AvgAnt( int16_t Fmt3xDataRmvOrth[4][2][5][12][2], int16_t Fmt3xDataAvgAnt[2][5][12][2], uint8_t shortened_format, LTE_DL_FRAME_PARMS *frame_parms ) { @@ -721,11 +752,142 @@ int16_t pucchfmt3_Decode( int16_t b[48], } } + +uint32_t calc_pucch_1x_interference(PHY_VARS_eNB *eNB, + int frame, + uint8_t subframe, + uint8_t shortened_format +) +//----------------------------------------------------------------------------- +{ + LTE_eNB_COMMON *common_vars = &eNB->common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + + uint32_t u,v,n,aa; + uint32_t z[12*14]; + int16_t *zptr; + int16_t rxcomp[NB_ANTENNAS_RX][2*12*14]; + uint8_t ns,N_UL_symb,nsymb,n_cs_base; + uint16_t i,j,re_offset; + uint8_t m,l; + uint8_t n_cs,alpha_ind; + int16_t tmp_re,tmp_im,W_re=0,W_im=0; + int16_t W4_nouse[4]={32767,32767,-32768,-32768}; + int32_t n0_IQ[2]; + double interference_power; + int16_t *rxptr; + uint32_t symbol_offset; + + uint32_t u0 = (frame_parms->pucch_config_common.grouphop[subframe<<1]) % 30; + uint32_t u1 = (frame_parms->pucch_config_common.grouphop[1+(subframe<<1)]) % 30; + uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; + uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; + int calc_cnt; + + zptr = (int16_t *)z; + N_UL_symb = (frame_parms->Ncp==NORMAL) ? 7 : 6; + + interference_power=0.0; + calc_cnt=0; + // loop over 2 slots + for (n_cs_base=0; n_cs_base<12; n_cs_base++) { + zptr = (int16_t *)z; + for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) { + + //loop over symbols in slot + for (l=0; lncs_cell[ns][l]+n_cs_base; + if(((l>1)&&(l=N_UL_symb-2)) { // data + W_re=W4_nouse[l-N_UL_symb+4]; + W_im=0; + } + + alpha_ind=0; + // compute output sequence + + for (n=0; n<12; n++) { + + // this is r_uv^alpha(n) + tmp_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15); + tmp_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15); + + // this is S(ns)*w_noc(m)*r_uv^alpha(n) + zptr[n<<1] = (tmp_re*W_re - tmp_im*W_im)>>15; + zptr[1+(n<<1)] = -(tmp_re*W_im + tmp_im*W_re)>>15; + + alpha_ind = (alpha_ind + n_cs)%12; + } // n + + zptr+=24; + } // l + } // ns + + m = 1; + + nsymb = N_UL_symb<<1; + + zptr = (int16_t*)z; + + // Do detection + for (aa=0; aanb_antennas_rx; aa++) { + n0_IQ[0]=0; + n0_IQ[1]=0; + for (j=0,l=0; l1)&&((l%N_UL_symb)=N_UL_symb) && (shortened_format==1)) ){ + j+=24; + continue; + } + if ((l<(nsymb>>1)) && ((m&1) == 0)) + re_offset = (m*6) + frame_parms->first_carrier_offset; + else if ((l<(nsymb>>1)) && ((m&1) == 1)) + re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12; + else if ((m&1) == 0) + re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12; + else + re_offset = ((m-1)*6) + frame_parms->first_carrier_offset; + + if (re_offset > frame_parms->ofdm_symbol_size) + re_offset -= (frame_parms->ofdm_symbol_size); + + symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*l; + rxptr = (int16_t *)&common_vars->rxdataF[aa][symbol_offset]; + + for (i=0; i<12; i++,j+=2,re_offset++) { + if (re_offset==frame_parms->ofdm_symbol_size) + re_offset = 0; + + rxcomp[aa][j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[j])>>15) - ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[1+j])>>15); + rxcomp[aa][1+j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[1+j])>>15) + ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[j])>>15); + n0_IQ[0]+=rxcomp[aa][j]; + n0_IQ[1]+=rxcomp[aa][1+j]; + } //re + calc_cnt++; + } // symbol + n0_IQ[0]/=12; + n0_IQ[1]/=12; + interference_power+= (double)(n0_IQ[0]*n0_IQ[0]+n0_IQ[1]*n0_IQ[1]); + } // antenna + } + interference_power /= calc_cnt; + eNB->measurements.n0_pucch_dB = dB_fixed_x10((int)interference_power)/10; + LOG_D(PHY,"estimate pucch noise %lf %d %d\n",interference_power,calc_cnt,eNB->measurements.n0_pucch_dB); + return 0; +} + + /* PUCCH format3 << */ uint32_t rx_pucch(PHY_VARS_eNB *eNB, PUCCH_FMT_t fmt, - uint8_t UE_id, + uint8_t UCI_id, uint16_t n1_pucch, uint16_t n2_pucch, uint8_t shortened_format, @@ -733,21 +895,22 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, int frame, uint8_t subframe, uint8_t pucch1_thres, - uint8_t br_flag + int br_flag ) //----------------------------------------------------------------------------- { static int first_call = 1; LTE_eNB_COMMON *common_vars = &eNB->common_vars; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; - int8_t sigma2_dB = max(eNB->measurements.n0_subband_power_tot_dB[0], eNB->measurements.n0_subband_power_tot_dB[eNB->frame_parms.N_RB_UL-1]); + int8_t sigma2_dB = /*max(eNB->measurements.n0_subband_power_tot_dB[0], eNB->measurements.n0_subband_power_tot_dB[eNB->frame_parms.N_RB_UL-1]); */eNB->measurements.n0_pucch_dB; + uint32_t u,v,n,aa; uint32_t z[12*14]; int16_t *zptr; - int16_t rxcomp[NB_ANTENNAS_RX][2*12*14]; + int16_t rxcomp[4][2*12*14]; uint8_t ns,N_UL_symb,nsymb,n_oc,n_oc0,n_oc1; uint8_t c = (frame_parms->Ncp==0) ? 3 : 2; - uint16_t nprime,nprime0,nprime1; + int16_t nprime,nprime0,nprime1; uint16_t i,j,re_offset,thres,h,off; uint8_t Nprime_div_deltaPUCCH_Shift,Nprime,d; uint8_t m,l,refs,phase,re,l2,phase_max=0; @@ -755,30 +918,31 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, int16_t tmp_re,tmp_im,W_re=0,W_im=0; int16_t *rxptr; uint32_t symbol_offset; - int16_t stat_ref_re,stat_ref_im,*cfo; - int16_t chest0_re[NB_ANTENNAS_RX][12],chest0_im[NB_ANTENNAS_RX][12]; - int16_t chest1_re[NB_ANTENNAS_RX][12],chest1_im[NB_ANTENNAS_RX][12]; + int16_t stat0_ref_re[4],stat0_ref_im[4],stat1_ref_re[4],stat1_ref_im[4],*cfo; + int16_t chest0_re[4][12],chest0_im[4][12]; + int16_t chest1_re[4][12],chest1_im[4][12]; int32_t chest_mag; - int32_t stat_re=0,stat_im=0; - uint32_t stat,stat_max=0; + int32_t stat0_re[4],stat1_re[4],stat0_im[4],stat1_im[4]; + uint32_t stat0[4],stat1[4],stat_max=0,stat0_max[4],stat1_max[4]; uint8_t log2_maxh; uint8_t deltaPUCCH_Shift = frame_parms->pucch_config_common.deltaPUCCH_Shift; uint8_t NRB2 = frame_parms->pucch_config_common.nRB_CQI; uint8_t Ncs1_div_deltaPUCCH_Shift = frame_parms->pucch_config_common.nCS_AN; - uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30; - uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30; + + uint32_t u0 = (frame_parms->pucch_config_common.grouphop[subframe<<1]) % 30; + uint32_t u1 = (frame_parms->pucch_config_common.grouphop[1+(subframe<<1)]) % 30; uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; int chL; /* PUCCH format3 >> */ uint16_t Ret = 0; - int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] - int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] - double delta_theta[NB_ANTENNAS_RX][12]; //[Antenna][Subcarrier][Complex] - int16_t ChestValue[NB_ANTENNAS_RX][2][12][2]; //[Antenna][Slot][Subcarrier][Complex] - int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] - int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2]; //[Antenna][Slot][PUCCH_Symbol][Subcarrier][Complex] - int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2]; //[Antenna][Slot][PUCCH_Symbol][Subcarrier][Complex] + int16_t SubCarrierDeMapData[4][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] + int16_t CshData_fmt3[4][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] + double delta_theta[4][12]; //[Antenna][Subcarrier][Complex] + int16_t ChestValue[4][2][12][2]; //[Antenna][Slot][Subcarrier][Complex] + int16_t ChdetAfterValue_fmt3[4][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex] + int16_t RemoveFrqDev_fmt3[4][2][5][12][2]; //[Antenna][Slot][PUCCH_Symbol][Subcarrier][Complex] + int16_t Fmt3xDataRmvOrth[4][2][5][12][2]; //[Antenna][Slot][PUCCH_Symbol][Subcarrier][Complex] int16_t Fmt3xDataAvgAnt[2][5][12][2]; //[Slot][PUCCH_Symbol][Subcarrier][Complex] int16_t Fmt3xDataAvgSym[2][12][2]; //[Slot][Subcarrier][Complex] int16_t IFFTOutData_Fmt3[2][12][2]; //[Slot][Subcarrier][Complex] @@ -808,9 +972,27 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, first_call=0; } - + eNB_UCI_STATS_t *uci_stats = NULL; if(fmt!=pucch_format3) { /* PUCCH format3 */ + + eNB_UCI_STATS_t *first_uci_stats=NULL; + for (int i=0;iuci_stats[i].rnti == eNB->uci_vars[UCI_id].rnti) { + uci_stats = &eNB->uci_stats[i]; + break; + } else if (first_uci_stats == NULL && eNB->uci_stats[i].rnti == 0) first_uci_stats = &eNB->uci_stats[i]; + if (uci_stats == NULL) { + if (first_uci_stats == NULL) { + LOG_E(PHY,"first_uci_stats is NULL\n"); + return -1; + } + uci_stats=first_uci_stats; + uci_stats->rnti = eNB->uci_vars[UCI_id].rnti; + } + + AssertFatal(uci_stats!=NULL,"No stat index found\n"); + uci_stats->frame = frame; // TODO // "SR+ACK/NACK" length is only 7 bits. // This restriction will be lifted in the future. @@ -1016,57 +1198,63 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, // Do cfo correction and MRC across symbols if (fmt == pucch_format1) { + uci_stats->pucch1_trials++; #ifdef DEBUG_PUCCH_RX printf("Doing PUCCH detection for format 1\n"); #endif stat_max = 0; for (phase=0; phase<7; phase++) { - stat=0; - + int stat=0; for (aa=0; aanb_antennas_rx; aa++) { + stat0[aa]=0;stat1[aa]=0; for (re=0; re<12; re++) { - stat_re=0; - stat_im=0; + stat0_re[aa]=0; + stat0_im[aa]=0; + stat1_re[aa]=0; + stat1_im[aa]=0; off=re<<1; cfo = (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase] : &cfo_pucch_ep[12*phase]; for (l=0; l<(nsymb>>1); l++) { - stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/nsymb; - stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/nsymb; + stat0_re[aa] += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/nsymb; + stat0_im[aa] += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/nsymb; off+=2; #ifdef DEBUG_PUCCH_RX printf("[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) , stat %d\n",subframe,phase,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], - stat_re,stat_im,stat); + stat0_re[aa],stat0_im[aa],stat); #endif } for (l2=0,l=(nsymb>>1); l < nsymb; l++,l2++) { - stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15))/nsymb; - stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15))/nsymb; + stat1_re[aa] += (((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15))/nsymb; + stat1_im[aa] += (((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15))/nsymb; off+=2; #ifdef DEBUG_PUCCH_RX printf("[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d), stat %d\n",subframe,phase,l2,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l2<<1],cfo[1+(l2<<1)], - stat_re,stat_im,stat); + stat1_re[aa],stat1_im[aa],stat); #endif } - - stat += ((stat_re*stat_re) + (stat_im*stat_im)); + + stat0[aa] += ((stat0_re[aa]*stat0_re[aa]) + (stat0_im[aa]*stat0_im[aa])); + stat1[aa] += ((stat1_re[aa]*stat1_re[aa]) + (stat1_im[aa]*stat1_im[aa])); } //re + stat+=(stat0[aa]+stat1[aa]); } // aa - if (stat>stat_max) { stat_max = stat; phase_max = phase; + for (aa=0;aanb_antennas_rx;aa++) { + stat0_max[aa] = stat0[aa]; + stat1_max[aa] = stat1[aa]; + } } } //phase - // stat_max *= nsymb; // normalize to energy per symbol - // stat_max /= (frame_parms->N_RB_UL*12); // stat_max /= 12; #ifdef DEBUG_PUCCH_RX printf("[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max); @@ -1074,12 +1262,14 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, #ifdef DEBUG_PUCCH_RX LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements.n0_subband_power_tot_dBm[6],pucch1_thres,phase_max); #endif - eNB->pucch1_stats[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = stat_max; - eNB->pucch1_stats_thres[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres; - eNB->pucch1_stats_cnt[UE_id][subframe] = (eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023; - T(T_ENB_PHY_PUCCH_1_ENERGY, T_INT(eNB->Mod_id), T_INT(eNB->uci_vars[UE_id].rnti), T_INT(frame), T_INT(subframe), + eNB->pucch1_stats[UCI_id][(subframe<<10)+eNB->pucch1_stats_cnt[UCI_id][subframe]] = stat_max; + eNB->pucch1_stats_thres[UCI_id][(subframe<<10)+eNB->pucch1_stats_cnt[UCI_id][subframe]] = sigma2_dB+pucch1_thres; + eNB->pucch1_stats_cnt[UCI_id][subframe] = (eNB->pucch1_stats_cnt[UCI_id][subframe]+1)&1023; + uci_stats->pucch1_thres = sigma2_dB+pucch1_thres; + T(T_ENB_PHY_PUCCH_1_ENERGY, T_INT(eNB->Mod_id), T_INT(eNB->uci_vars[UCI_id].rnti), T_INT(frame), T_INT(subframe), T_INT(stat_max), T_INT(sigma2_dB+pucch1_thres)); + /* if (eNB->pucch1_stats_cnt[UE_id][subframe] == 0) { LOG_M("pucch_debug.m","pucch_energy", @@ -1093,11 +1283,18 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, // This is a moving average of the PUCCH1 statistics conditioned on being above or below the threshold if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) { *payload = 1; + uci_stats->current_pucch1_stat_pos = stat_max; + for (int aa=0;aanb_antennas_rx;aa++) { + uci_stats->pucch1_low_stat[aa]=stat0_max[aa]; + uci_stats->pucch1_high_stat[aa]=stat1_max[aa]; + uci_stats->pucch1_positive_SR++; + } } else { + uci_stats->current_pucch1_stat_neg = stat_max; *payload = 0; } - if (UE_id==0) { + if (UCI_id==0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_ENERGY,dB_fixed(stat_max)); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_THRES,sigma2_dB+pucch1_thres); } @@ -1106,29 +1303,30 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"Doing PUCCH detection for format 1a/1b\n"); #endif - + int stat_re=0,stat_im=0; for (phase=0; phase<7; phase++) { - stat=0; - + int stat=0; for (aa=0; aanb_antennas_rx; aa++) { + stat0[aa]=0; + stat1[aa]=0; for (re=0; re<12; re++) { // compute received energy first slot, seperately for data and reference // by coherent combining across symbols but not resource elements // Note: assumption is that channel is stationary over symbols in slot after CFO - stat_re=0; - stat_im=0; - stat_ref_re=0; - stat_ref_im=0; + stat0_re[aa]=0; + stat0_im[aa]=0; + stat0_ref_re[aa]=0; + stat0_ref_im[aa]=0; off=re<<1; cfo = (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase] : &cfo_pucch_ep[12*phase]; for (l=0; l<(nsymb>>1); l++) { if ((l<2)||(l>(nsymb>>1) - 3)) { //data symbols - stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); - stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); + stat0_re[aa] += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); + stat0_im[aa] += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); } else { //reference symbols - stat_ref_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); - stat_ref_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); + stat0_ref_re[aa] += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); + stat0_ref_im[aa] += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); } off+=2; @@ -1141,21 +1339,21 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, } // this is total energy received, summed over data and reference - stat += ((((stat_re*stat_re)) + ((stat_im*stat_im)) + - ((stat_ref_re*stat_ref_re)) + ((stat_ref_im*stat_ref_im)))/nsymb); + stat0[aa] += ((((stat0_re[aa]*stat0_re[aa])) + ((stat0_im[aa]*stat0_im[aa])) + + ((stat0_ref_re[aa]*stat0_ref_re[aa])) + ((stat0_ref_im[aa]*stat0_ref_im[aa])))/nsymb); // now second slot - stat_re=0; - stat_im=0; - stat_ref_re=0; - stat_ref_im=0; + stat1_re[aa]=0; + stat1_im[aa]=0; + stat1_ref_re[aa]=0; + stat1_ref_im[aa]=0; for (l2=0,l=(nsymb>>1); l< nsymb; l++,l2++) { if ((l2<2) || ((l2>(nsymb>>1) - 3)) ) { // data symbols - stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15); - stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15); + stat1_re[aa] += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15); + stat1_im[aa] += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15); } else { //reference_symbols - stat_ref_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15); - stat_ref_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15); + stat1_ref_re[aa] += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15); + stat1_ref_im[aa] += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15); } off+=2; @@ -1170,15 +1368,16 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, #ifdef DEBUG_PUCCH_RX printf("aa%d re %d : phase %d : stat %d\n",aa,re,phase,stat); #endif - stat += ((((stat_re*stat_re)) + ((stat_im*stat_im)) + - ((stat_ref_re*stat_ref_re)) + ((stat_ref_im*stat_ref_im)))/nsymb); + stat1[aa] += ((((stat1_re[aa]*stat1_re[aa])) + ((stat1_im[aa]*stat1_im[aa])) + + ((stat1_ref_re[aa]*stat1_ref_re[aa])) + ((stat1_ref_im[aa]*stat1_ref_im[aa])))/nsymb); } //re + stat+=(stat0[aa]+stat1[aa]); } // aa #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"Format 1A: phase %d : stat %d\n",phase,stat); #endif - + if (stat>stat_max) { stat_max = stat; phase_max = phase; @@ -1189,8 +1388,6 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, #ifdef DEBUG_PUCCH_RX LOG_I(PHY,"[eNB] PUCCH fmt1a/b: stat_max : %d (%d : sigma2 %d), phase_max : %d\n",stat_max,dB_fixed(stat_max),sigma2_dB,phase_max); #endif - stat_re=0; - stat_im=0; // Do detection now @@ -1198,13 +1395,12 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, // For instance i assume to skip pucch1_thres from the test below. // Not 100% sure - if (sigma2_dB<(dB_fixed(stat_max) - (IS_SOFTMODEM_IQPLAYER?0:pucch1_thres)) ) {// + if (sigma2_dB<(dB_fixed(stat_max) - (IS_SOFTMODEM_IQPLAYER?0:pucch1_thres)) ) {// chL = (nsymb>>1)-4; chest_mag=0; cfo = (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase_max] : &cfo_pucch_ep[12*phase_max]; for (aa=0; aanb_antennas_rx; aa++) { - // channel estimates first for (re=0; re<12; re++) { // channel estimate for first slot chest0_re[aa][re]=0; @@ -1238,6 +1434,11 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, // now do channel matched filter for (aa=0; aanb_antennas_rx; aa++) { + stat0_re[aa]=0; + stat0_im[aa]=0; + stat1_re[aa]=0; + stat1_im[aa]=0; + for (re=0; re<12; re++) { #ifdef DEBUG_PUCCH_RX printf("[eNB] PUCCH subframe %d chest0[%d][%d] => (%d,%d)\n",subframe,aa,re, @@ -1249,8 +1450,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, off=(re<<1) + (24*l); tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += (((tmp_re*chest0_re[aa][re])>>log2_maxh) + ((tmp_im*chest0_im[aa][re])>>log2_maxh)); - stat_im += (((tmp_re*chest0_im[aa][re])>>log2_maxh) - ((tmp_im*chest0_re[aa][re])>>log2_maxh)); + stat0_re[aa] += (((tmp_re*chest0_re[aa][re])>>log2_maxh) + ((tmp_im*chest0_im[aa][re])>>log2_maxh)); + stat0_im[aa] += (((tmp_re*chest0_im[aa][re])>>log2_maxh) - ((tmp_im*chest0_re[aa][re])>>log2_maxh)); off+=2; #ifdef DEBUG_PUCCH_RX printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) => (%d,%d)\n",subframe,l,re, @@ -1266,8 +1467,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, off=(re<<1) + (24*l); tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += (((tmp_re*chest0_re[aa][re])>>log2_maxh) + ((tmp_im*chest0_im[aa][re])>>log2_maxh)); - stat_im += (((tmp_re*chest0_im[aa][re])>>log2_maxh) - ((tmp_im*chest0_re[aa][re])>>log2_maxh)); + stat0_re[aa] += (((tmp_re*chest0_re[aa][re])>>log2_maxh) + ((tmp_im*chest0_im[aa][re])>>log2_maxh)); + stat0_im[aa] += (((tmp_re*chest0_im[aa][re])>>log2_maxh) - ((tmp_im*chest0_re[aa][re])>>log2_maxh)); off+=2; #ifdef DEBUG_PUCCH_RX printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) => (%d,%d)\n",subframe,l,re, @@ -1288,8 +1489,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, off=(re<<1) + (24*l) + (nsymb>>1)*24; tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += (((tmp_re*chest1_re[aa][re])>>log2_maxh) + ((tmp_im*chest1_im[aa][re])>>log2_maxh)); - stat_im += (((tmp_re*chest1_im[aa][re])>>log2_maxh) - ((tmp_im*chest1_re[aa][re])>>log2_maxh)); + stat1_re[aa] += (((tmp_re*chest1_re[aa][re])>>log2_maxh) + ((tmp_im*chest1_im[aa][re])>>log2_maxh)); + stat1_im[aa] += (((tmp_re*chest1_im[aa][re])>>log2_maxh) - ((tmp_im*chest1_re[aa][re])>>log2_maxh)); off+=2; #ifdef DEBUG_PUCCH_RX printf("[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) => (%d,%d)\n",subframe,l,re, @@ -1305,8 +1506,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, off=(re<<1) + (24*l) + (nsymb>>1)*24; tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += (((tmp_re*chest1_re[aa][re])>>log2_maxh) + ((tmp_im*chest1_im[aa][re])>>log2_maxh)); - stat_im += (((tmp_re*chest1_im[aa][re])>>log2_maxh) - ((tmp_im*chest1_re[aa][re])>>log2_maxh)); + stat1_re[aa] += (((tmp_re*chest1_re[aa][re])>>log2_maxh) + ((tmp_im*chest1_im[aa][re])>>log2_maxh)); + stat1_im[aa] += (((tmp_re*chest1_im[aa][re])>>log2_maxh) - ((tmp_im*chest1_re[aa][re])>>log2_maxh)); off+=2; #ifdef DEBUG_PUCCH_RX printf("[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) => (%d,%d)\n",subframe,l,re, @@ -1321,29 +1522,42 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB, printf("aa%d re %d : stat %d,%d\n",aa,re,stat_re,stat_im); #endif } //re + stat_re+=stat0_re[aa]+stat1_re[aa]; + stat_im+=stat0_im[aa]+stat1_im[aa]; } // aa LOG_D(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im, - (subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])); + (subframe<<10) + (eNB->pucch1ab_stats_cnt[UCI_id][subframe])); LOG_D(PHY,"In pucch.c PUCCH 1a/b: ACK subframe %d : sigma2_dB %d, stat_max %d, pucch1_thres %d\n",subframe,sigma2_dB,dB_fixed(stat_max),pucch1_thres); - eNB->pucch1ab_stats[UE_id][(subframe<<11) + 2*(eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_re); - eNB->pucch1ab_stats[UE_id][(subframe<<11) + 1+2*(eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_im); - eNB->pucch1ab_stats_cnt[UE_id][subframe] = (eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + eNB->pucch1ab_stats[UCI_id][(subframe<<11) + 2*(eNB->pucch1ab_stats_cnt[UCI_id][subframe])] = (stat_re); + eNB->pucch1ab_stats[UCI_id][(subframe<<11) + 1+2*(eNB->pucch1ab_stats_cnt[UCI_id][subframe])] = (stat_im); + eNB->pucch1ab_stats_cnt[UCI_id][subframe] = (eNB->pucch1ab_stats_cnt[UCI_id][subframe]+1)&1023; /* frame not available here - set to -1 for the moment */ - T(T_ENB_PHY_PUCCH_1AB_IQ, T_INT(eNB->Mod_id), T_INT(eNB->uci_vars[UE_id].rnti), T_INT(-1), T_INT(subframe), T_INT(stat_re), T_INT(stat_im)); + T(T_ENB_PHY_PUCCH_1AB_IQ, T_INT(eNB->Mod_id), T_INT(eNB->uci_vars[UCI_id].rnti), T_INT(-1), T_INT(subframe), T_INT(stat_re), T_INT(stat_im)); *payload = (stat_re<0) ? 1 : 2; // 1 == ACK, 2 == NAK - if (fmt==pucch_format1b) + if (fmt==pucch_format1b) { + uci_stats->pucch1b_trials++; *(1+payload) = (stat_im<0) ? 1 : 2; + uci_stats->current_pucch1b_stat_re = stat_re; + uci_stats->current_pucch1b_stat_im = stat_im; + } + else { + uci_stats->pucch1a_trials++; + uci_stats->current_pucch1a_stat_re = stat_re; + uci_stats->current_pucch1a_stat_im = stat_im; + } + } else { // insufficient energy on PUCCH so NAK LOG_D(PHY,"In pucch.c PUCCH 1a/b: NAK subframe %d : sigma2_dB %d, stat_max %d, pucch1_thres %d\n",subframe,sigma2_dB,dB_fixed(stat_max),pucch1_thres); *payload = 4; // DTX - ((int16_t *)&eNB->pucch1ab_stats[UE_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); - ((int16_t *)&eNB->pucch1ab_stats[UE_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); - eNB->pucch1ab_stats_cnt[UE_id][subframe] = (eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + ((int16_t *)&eNB->pucch1ab_stats[UCI_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UCI_id][subframe])])[0] = (int16_t)(stat_re); + ((int16_t *)&eNB->pucch1ab_stats[UCI_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UCI_id][subframe])])[1] = (int16_t)(stat_im); + eNB->pucch1ab_stats_cnt[UCI_id][subframe] = (eNB->pucch1ab_stats_cnt[UCI_id][subframe]+1)&1023; if (fmt==pucch_format1b) *(1+payload) = 4; + uci_stats->pucch1ab_DTX++; } } else { LOG_E(PHY,"[eNB] PUCCH fmt2/2a/2b not supported\n"); diff --git a/openair1/PHY/LTE_TRANSPORT/pucch_common.c b/openair1/PHY/LTE_TRANSPORT/pucch_common.c index 5b939b08d2..d7a500d5f7 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch_common.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch_common.c @@ -31,7 +31,6 @@ */ #include "PHY/defs_eNB.h" #include "PHY/phy_extern.h" -#include "LAYER2/MAC/mac.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/LOG/log.h" diff --git a/openair1/PHY/LTE_TRANSPORT/transport_common.h b/openair1/PHY/LTE_TRANSPORT/transport_common.h index ab2921c2b9..135f3cdf4b 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_common.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_common.h @@ -35,9 +35,9 @@ #include "dci.h" #include "mdci.h" //#include "uci.h" -#ifndef STANDALONE_COMPILE - #include "UTIL/LISTS/list.h" -#endif +//#ifndef STANDALONE_COMPILE +// #include "UTIL/LISTS/list.h" +//#endif #define MOD_TABLE_QPSK_OFFSET 1 #define MOD_TABLE_16QAM_OFFSET 5 @@ -57,7 +57,7 @@ // maximum of 3 segments before each coding block if data length exceeds 6144 bits. -#define MAX_NUM_DLSCH_SEGMENTS 16 +#define MAX_NUM_DLSCH_SEGMENTS 13 #define MAX_NUM_ULSCH_SEGMENTS MAX_NUM_DLSCH_SEGMENTS #define MAX_DLSCH_PAYLOAD_BYTES (MAX_NUM_DLSCH_SEGMENTS*768) #define MAX_ULSCH_PAYLOAD_BYTES (MAX_NUM_ULSCH_SEGMENTS*768) @@ -65,22 +65,6 @@ #define MAX_NUM_CHANNEL_BITS (14*1200*6) // 14 symbols, 1200 REs, 12 bits/RE #define MAX_NUM_RE (14*1200) -#if !defined(SI_RNTI) - #define SI_RNTI (rnti_t)0xffff - #define SI_RNTI_MBMS (rnti_t)0xfff9 -#endif -#if !defined(M_RNTI) - #define M_RNTI (rnti_t)0xfffd -#endif -#if !defined(P_RNTI) - #define P_RNTI (rnti_t)0xfffe -#endif -#if !defined(CBA_RNTI) - #define CBA_RNTI (rnti_t)0xfff4 -#endif -#if !defined(C_RNTI) - #define C_RNTI (rnti_t)0x1234 -#endif // These are the codebook indexes according to Table 6.3.4.2.3-1 of 36.211 //1 layer #define PMI_2A_11 0 @@ -93,7 +77,8 @@ #define PMI_2A_R1_1j 2 typedef enum { SEARCH_EXIST=0, - SEARCH_EXIST_OR_FREE + SEARCH_EXIST_OR_FREE, + SEARCH_EXIST_RA } find_type_t; typedef enum { diff --git a/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h index 1944f06fab..af8e63c3ed 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h @@ -101,7 +101,7 @@ int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint int get_G_khz_1dot25(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe, uint8_t beamforming_mode); int adjust_G(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe); -int adjust_G2(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol); +int adjust_G2(int Ncp, int frame_type, int N_RB_DL, uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol); #ifndef modOrder @@ -223,7 +223,9 @@ uint8_t get_num_prach_tdd(module_id_t Mod_id); @param frame_type 0-FDD, 1-TDD @returns 0-1 accordingly */ +/* uint8_t get_prach_fmt(uint8_t prach_ConfigIndex,lte_frame_type_t frame_type); +*/ /*! \brief Helper for MAC, returns frequency index of PRACH resource in TDD for a particular configuration index @@ -306,12 +308,12 @@ void init_scrambling_lut(void); void init_unscrambling_lut(void); - +/* uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, uint8_t prach_ConfigIndex, uint8_t n_ra_prboffset, uint8_t tdd_mapindex, uint16_t Nf); - +*/ uint8_t subframe2harq_pid(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame,uint8_t subframe); uint8_t ul_subframe2pdcch_alloc_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n); @@ -319,6 +321,6 @@ uint32_t conv_1C_RIV(int32_t rballoc,uint32_t N_RB_DL); void conv_rballoc(uint8_t ra_header,uint32_t rb_alloc,uint32_t N_RB_DL,uint32_t *rb_alloc2); -int16_t estimate_ue_tx_power(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs); +int16_t estimate_ue_tx_power(int norm,uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs); #endif diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 5e446db5fd..b3985e973a 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -36,9 +36,9 @@ #include "dci.h" #include "mdci.h" #include "uci_common.h" -#ifndef STANDALONE_COMPILE - #include "UTIL/LISTS/list.h" -#endif +//#ifndef STANDALONE_COMPILE +// #include "UTIL/LISTS/list.h" +//#endif // structures below implement 36-211 and 36-212 diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index 4ce113f78e..1fbd1266d7 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -520,6 +520,9 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB, void dump_ulsch(PHY_VARS_eNB *phy_vars_eNB,int frame, int subframe, uint8_t UE_id,int round); +void dump_ulsch_stats(FILE *fd,PHY_VARS_eNB *eNB,int frame); +void dump_uci_stats(FILE *fd,PHY_VARS_eNB *eNB,int frame); + @@ -621,7 +624,11 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, uint16_t frame, uint8_t Ns); - +uint32_t calc_pucch_1x_interference(PHY_VARS_eNB *eNB, + int frame, + uint8_t subframe, + uint8_t shortened_format +); uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, PUCCH_FMT_t fmt, @@ -687,15 +694,57 @@ void conv_eMTC_rballoc(uint16_t resource_block_coding, uint32_t N_RB_DL, uint32_t *rb_alloc); -int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +int find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); -int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +int find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); -int16_t find_uci(uint16_t rnti, int frame, int subframe, PHY_VARS_eNB *eNB,find_type_t type); +int find_uci(uint16_t rnti, int frame, int subframe, PHY_VARS_eNB *eNB,find_type_t type); -uint8_t get_prach_fmt(uint8_t prach_ConfigIndex,lte_frame_type_t frame_type); +static inline uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset) +{ + int32_t n; -uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset); + // 3GPP 3x.211 + // Nc = 1600 + // c(n) = [x1(n+Nc) + x2(n+Nc)]mod2 + // x1(n+31) = [x1(n+3) + x1(n)]mod2 + // x2(n+31) = [x2(n+3) + x2(n+2) + x2(n+1) + x2(n)]mod2 + if (reset) + { + // Init value for x1: x1(0) = 1, x1(n) = 0, n=1,2,...,30 + // x1(31) = [x1(3) + x1(0)]mod2 = 1 + *x1 = 1 + (1U<<31); + // Init value for x2: cinit = sum_{i=0}^30 x2*2^i + // x2(31) = [x2(3) + x2(2) + x2(1) + x2(0)]mod2 + // = (*x2>>3) ^ (*x2>>2) + (*x2>>1) + *x2 + *x2 = *x2 ^ ((*x2 ^ (*x2>>1) ^ (*x2>>2) ^ (*x2>>3))<<31); + + // x1 and x2 contain bits n = 0,1,...,31 + + // Nc = 1600 bits are skipped at the beginning + // i.e., 1600 / 32 = 50 32bit words + + for (n = 1; n < 50; n++) + { + // Compute x1(0),...,x1(27) + *x1 = (*x1>>1) ^ (*x1>>4); + // Compute x1(28),..,x1(31) and xor + *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28); + // Compute x2(0),...,x2(27) + *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4); + // Compute x2(28),..,x2(31) and xor + *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28); + } + } + + *x1 = (*x1>>1) ^ (*x1>>4); + *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28); + *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4); + *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28); + + // c(n) = [x1(n+Nc) + x2(n+Nc)]mod2 + return(*x1^*x2); +} /**@}*/ diff --git a/openair1/PHY/LTE_TRANSPORT/uci_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/uci_NB_IoT.h index 6f2dd0f989..c16be6a308 100644 --- a/openair1/PHY/LTE_TRANSPORT/uci_NB_IoT.h +++ b/openair1/PHY/LTE_TRANSPORT/uci_NB_IoT.h @@ -321,4 +321,4 @@ HLC_subband_cqi_mcs_CBA_20MHz_NB_IoT; #define MAX_ACK_PAYLOAD_NB_IoT 18 #define MAX_RI_PAYLOAD_NB_IoT 6 -#endif \ No newline at end of file +#endif diff --git a/openair1/PHY/LTE_TRANSPORT/uci_tools.c b/openair1/PHY/LTE_TRANSPORT/uci_tools.c index f8ade9afc8..ae039bec2a 100644 --- a/openair1/PHY/LTE_TRANSPORT/uci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/uci_tools.c @@ -37,12 +37,11 @@ //#define DEBUG_UCI 1 -int16_t find_uci(uint16_t rnti, int frame, int subframe, PHY_VARS_eNB *eNB,find_type_t type) { - uint16_t i; - int16_t first_free_index=-1; +int find_uci(uint16_t rnti, int frame, int subframe, PHY_VARS_eNB *eNB,find_type_t type) { + int first_free_index=-1; AssertFatal(eNB!=NULL,"eNB is null\n"); - for (i=0; iuci_vars[i].active >0) && (eNB->uci_vars[i].rnti==rnti) && (eNB->uci_vars[i].frame==frame) && diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 92fe777201..ae8c666d18 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -374,7 +374,7 @@ static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, int n; if (reset) { - *x1 = 1+ (1<<31); + *x1 = 1+ (1U<<31); *x2=*x2 ^ ((*x2 ^ (*x2>>1) ^ (*x2>>2) ^ (*x2>>3))<<31); // skip first 50 double words (1600 bits) @@ -468,6 +468,35 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, ulsch_harq->Nsymb_pusch, nb_rb); //#endif + + eNB_SCH_STATS_t *stats=NULL; + int first_free=-1; + for (int i=0;iulsch_stats[i].rnti == 0 && first_free == -1) { + first_free = i; + stats=&eNB->ulsch_stats[i]; + } + if (eNB->ulsch_stats[i].rnti == ulsch->rnti) { + stats=&eNB->ulsch_stats[i]; + break; + } + } + if (stats) { + stats->rnti = ulsch->rnti; + stats->round_trials[ulsch_harq->round]++; + stats->frame=proc->frame_rx; + } + if (ulsch_harq->round == 0) { + if (stats) { + stats->current_Qm = Q_m; + stats->current_RI = 1; + stats->total_bytes_tx += ulsch_harq->TBS; + stats->current_TBS = ulsch_harq->TBS; + stats->current_G = ulsch_harq->G; + } + } + + //if (ulsch_harq->round == 0) { // delete for RB shortage pattern // This is a new packet, so compute quantities regarding segmentation ulsch_harq->B = A+24; @@ -1086,3 +1115,44 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, ret = ulsch_decoding_data_all(eNB,proc, UE_id,harq_pid,llr8_flag); return(ret); } + +#define STATSTRLEN 16384 +void dump_ulsch_stats(FILE *fd,PHY_VARS_eNB *eNB,int frame) { + + char output[16384]; + int stroff=0; + for (int i=0;iulsch_stats[i].rnti>0 && eNB->ulsch_stats[i].round_trials[0]>100) { + for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) + stroff+=sprintf(output+stroff,"ULSCH RNTI %x: ulsch_power[%d] %d, ulsch_noise_power[%d] %d\n", + eNB->ulsch_stats[i].rnti, aa,eNB->ulsch_stats[i].ulsch_power[aa],aa,eNB->ulsch_stats[i].ulsch_noise_power[aa]); + AssertFatal(stroff<(STATSTRLEN-1000),"Increase STATSTRLEN\n"); + stroff+=sprintf(output+stroff,"ULSCH RNTI %x: round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d\n", + eNB->ulsch_stats[i].rnti, + eNB->ulsch_stats[i].round_trials[0], + (double)eNB->ulsch_stats[i].round_trials[1]/eNB->ulsch_stats[i].round_trials[0], + eNB->ulsch_stats[i].round_trials[1], + (double)eNB->ulsch_stats[i].round_trials[2]/eNB->ulsch_stats[i].round_trials[0], + eNB->ulsch_stats[i].round_trials[2], + (double)eNB->ulsch_stats[i].round_trials[3]/eNB->ulsch_stats[i].round_trials[0], + eNB->ulsch_stats[i].round_trials[3]); + stroff+=sprintf(output+stroff,"ULSCH RNTI %x: current_Qm %d, current_G %d, current_TBS %d, current_rate %f,current_RI %d, timing_offset %d, total_bytes RX/SCHED %d/%d\n", + eNB->ulsch_stats[i].rnti, + eNB->ulsch_stats[i].current_Qm, + eNB->ulsch_stats[i].current_G, + eNB->ulsch_stats[i].current_TBS, + (double)eNB->ulsch_stats[i].current_G/eNB->ulsch_stats[i].current_TBS, + eNB->ulsch_stats[i].current_RI, + eNB->ulsch_stats[i].timing_offset, + eNB->ulsch_stats[i].total_bytes_rx, + eNB->ulsch_stats[i].total_bytes_tx); + } + fprintf(fd,"%s",output); +} + +void clear_ulsch_stats(PHY_VARS_eNB *eNB) { + + for (int i=0;iulsch_stats[i],0,sizeof(eNB->ulsch_stats[i])); +} + diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 1b23fc99bf..3529df8e44 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -31,12 +31,12 @@ */ #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" +//#include "PHY/phy_extern.h" #include "transport_eNB.h" #include "PHY/sse_intrin.h" #include "transport_common_proto.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" -#include "PHY/MODULATION/modulation_eNB.h" +//#include "PHY/MODULATION/modulation_eNB.h" #include "T.h" @@ -45,8 +45,11 @@ //extern int **ulchmag_eren; //eren -static short jitter[8] __attribute__ ((aligned(16))) = {1,0,0,1,0,1,1,0}; -static short jitterc[8] __attribute__ ((aligned(16))) = {0,1,1,0,1,0,0,1}; +static const short jitter[8] __attribute__ ((aligned(16))) = {1,0,0,1,0,1,1,0}; +static const short jitterc[8] __attribute__ ((aligned(16))) = {0,1,1,0,1,0,0,1}; +static const short conjugate[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1}; +static const short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; + void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) { #if defined(__x86_64__) || defined(__i386__) @@ -511,7 +514,6 @@ void ulsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms, for (i=0; i<(nb_rb*3); i++) { #if defined(__x86_64__) || defined(__i386__) mmtmpU0 = _mm_abs_epi16(rxF[i]); - // print_shorts("tmp0",&tmp0); mmtmpU0 = _mm_subs_epi16(ch_mag[i],mmtmpU0); (*llrp128)[0] = _mm_unpacklo_epi32(rxF[i],mmtmpU0); (*llrp128)[1] = _mm_unpackhi_epi32(rxF[i],mmtmpU0); @@ -627,11 +629,15 @@ void ulsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, uint8_t symbol, uint16_t nb_rb) { #if defined(__x86_64__) || defined(__i386__) - __m128i *rxdataF_comp128_0,*ul_ch_mag128_0,*ul_ch_mag128_0b; - __m128i *rxdataF_comp128_1,*ul_ch_mag128_1,*ul_ch_mag128_1b; + __m128i *rxdataF_comp128_0=NULL,*ul_ch_mag128_0=NULL,*ul_ch_mag128_0b=NULL; + __m128i *rxdataF_comp128_1=NULL,*ul_ch_mag128_1=NULL,*ul_ch_mag128_1b=NULL; + __m128i *rxdataF_comp128_2=NULL,*ul_ch_mag128_2=NULL,*ul_ch_mag128_2b=NULL; + __m128i *rxdataF_comp128_3=NULL,*ul_ch_mag128_3=NULL,*ul_ch_mag128_3b=NULL; #elif defined(__arm__) int16x8_t *rxdataF_comp128_0,*ul_ch_mag128_0,*ul_ch_mag128_0b; int16x8_t *rxdataF_comp128_1,*ul_ch_mag128_1,*ul_ch_mag128_1b; + int16x8_t *rxdataF_comp128_2,*ul_ch_mag128_2,*ul_ch_mag128_2b; + int16x8_t *rxdataF_comp128_3,*ul_ch_mag128_3,*ul_ch_mag128_3b; #endif int32_t i; @@ -643,15 +649,39 @@ void ulsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, ul_ch_mag128_1 = (__m128i *)&ul_ch_mag[1][symbol*frame_parms->N_RB_DL*12]; ul_ch_mag128_0b = (__m128i *)&ul_ch_magb[0][symbol*frame_parms->N_RB_DL*12]; ul_ch_mag128_1b = (__m128i *)&ul_ch_magb[1][symbol*frame_parms->N_RB_DL*12]; - - // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) - for (i=0; inb_antennas_rx>2) { + rxdataF_comp128_2 = (__m128i *)&rxdataF_comp[2][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_2 = (__m128i *)&ul_ch_mag[2][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_2b = (__m128i *)&ul_ch_magb[2][symbol*frame_parms->N_RB_DL*12]; + } + if (frame_parms->nb_antennas_rx>3) { + rxdataF_comp128_3 = (__m128i *)&rxdataF_comp[3][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_3 = (__m128i *)&ul_ch_mag[3][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_3b = (__m128i *)&ul_ch_magb[3][symbol*frame_parms->N_RB_DL*12]; } + // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) + if (frame_parms->nb_antennas_rx==2) + for (i=0; inb_antennas_rx==3) + for (i=0; inb_antennas_rx==4) + for (i=0; iN_RB_DL*12]; rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12]; @@ -755,6 +785,7 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, __m128i *ul_ch128,*ul_ch_mag128,*ul_ch_mag128b,*rxdataF128,*rxdataF_comp128; uint8_t aarx;//,symbol_mod; __m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3; + #elif defined(__arm__) int16x4_t *ul_ch128,*rxdataF128; int16x8_t *ul_ch_mag128,*ul_ch_mag128b,*rxdataF_comp128; @@ -762,6 +793,7 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, int32x4_t mmtmpU0,mmtmpU1,mmtmpU0b,mmtmpU1b; int16_t conj[4]__attribute__((aligned(16))) = {1,-1,1,-1}; int32x4_t output_shift128 = vmovq_n_s32(-(int32_t)output_shift); + #endif for (aarx=0; aarxnb_antennas_rx; aarx++) { @@ -793,7 +825,7 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift); mmtmpU1 = _mm_packs_epi32(mmtmpU0,mmtmpU0); ul_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpU1,mmtmpU1); - LOG_D(PHY,"comp: symbol %d rb %d => %d,%d,%d (output_shift %d)\n",symbol,rb,*((int16_t *)&ul_ch_mag128[0]),*((int16_t *)&ul_ch_mag128[1]),*((int16_t *)&ul_ch_mag128[2]),output_shift); + //LOG_I(PHY,"comp: ant %d symbol %d rb %d => %d,%d,%d (output_shift %d)\n",aarx,symbol,rb,*((int16_t *)&ul_ch_mag128[0]),*((int16_t *)&ul_ch_mag128[1]),*((int16_t *)&ul_ch_mag128[2]),output_shift); #elif defined(__arm__) mmtmpU0 = vmull_s16(ul_ch128[0], ul_ch128[0]); mmtmpU0 = vqshlq_s32(vqaddq_s32(mmtmpU0,vrev64q_s32(mmtmpU0)),-output_shift128); @@ -832,6 +864,7 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, // print_ints("c1",&mmtmpU3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3); /* + LOG_I(PHY,"Antenna %d:",aarx); print_shorts("rx:",&rxdataF128[0]); print_shorts("ch:",&ul_ch128[0]); print_shorts("pack:",&rxdataF_comp128[0]); @@ -849,9 +882,12 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1); mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3); - // print_shorts("rx:",rxdataF128[1]); - // print_shorts("ch:",ul_ch128[1]); - // print_shorts("pack:",rxdataF_comp128[1]); + /* + LOG_I(PHY,"Antenna %d:",aarx); + print_shorts("rx:",&rxdataF128[1]); + print_shorts("ch:",&ul_ch128[1]); + print_shorts("pack:",&rxdataF_comp128[1]); + */ // multiply by conjugated channel mmtmpU0 = _mm_madd_epi16(ul_ch128[2],rxdataF128[2]); // mmtmpU0 contains real part of 4 consecutive outputs (32-bit) @@ -865,13 +901,17 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1); mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1); rxdataF_comp128[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3); - // print_shorts("rx:",rxdataF128[2]); - // print_shorts("ch:",ul_ch128[2]); - // print_shorts("pack:",rxdataF_comp128[2]); + /* + LOG_I(PHY,"Antenna %d:",aarx); + print_shorts("rx:",&rxdataF128[2]); + print_shorts("ch:",&ul_ch128[2]); + print_shorts("pack:",&rxdataF_comp128[2]); + */ // Add a jitter to compensate for the saturation in "packs" resulting in a bias on the DC after IDFT rxdataF_comp128[0] = _mm_add_epi16(rxdataF_comp128[0],(*(__m128i *)&jitter[0])); rxdataF_comp128[1] = _mm_add_epi16(rxdataF_comp128[1],(*(__m128i *)&jitter[0])); rxdataF_comp128[2] = _mm_add_epi16(rxdataF_comp128[2],(*(__m128i *)&jitter[0])); + ul_ch128+=3; ul_ch_mag128+=3; ul_ch_mag128b+=3; @@ -918,9 +958,10 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, mmtmpU1 = vqshlq_s32(mmtmpU1,-output_shift128); rxdataF_comp128[2] = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1)); // Add a jitter to compensate for the saturation in "packs" resulting in a bias on the DC after IDFT - rxdataF_comp128[0] = vqaddq_s16(rxdataF_comp128[0],(*(int16x8_t *)&jitter[0])); - rxdataF_comp128[1] = vqaddq_s16(rxdataF_comp128[1],(*(int16x8_t *)&jitter[0])); - rxdataF_comp128[2] = vqaddq_s16(rxdataF_comp128[2],(*(int16x8_t *)&jitter[0])); + rxdataF_comp128[0] = vqaddq_s16(rxdataF_comp128[0],(*(int16x8_t*)&jitter[0])); + rxdataF_comp128[1] = vqaddq_s16(rxdataF_comp128[1],(*(int16x8_t*)&jitter[0])); + rxdataF_comp128[2] = vqaddq_s16(rxdataF_comp128[2],(*(int16x8_t*)&jitter[0])); + ul_ch128+=6; ul_ch_mag128+=3; ul_ch_mag128b+=3; @@ -1031,6 +1072,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, AssertFatal(ulsch[UE_id]->harq_processes[harq_pid]->nb_rb > 0, "PUSCH (%d/%x) nb_rb=0!\n", harq_pid,ulsch[UE_id]->rnti); + for (l=0; l<(frame_parms->symbols_per_tti-ulsch[UE_id]->harq_processes[harq_pid]->srs_active); l++) { if(LOG_DEBUGFLAG(DEBUG_ULSCH)) { LOG_I(PHY,"rx_ulsch : symbol %d (first_rb %d,nb_rb %d), rxdataF %p, rxdataF_ext %p\n",l, @@ -1064,18 +1106,47 @@ void rx_ulsch(PHY_VARS_eNB *eNB, if (deltaMCS==1) { // Note we're using TBS instead of sumKr, since didn't run segmentation yet! MPR_times_100Ks = 500*ulsch[UE_id]->harq_processes[harq_pid]->TBS/(ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12*4*ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch); - AssertFatal(MPR_times_100Ks < 750 && MPR_times_100Ks >= 0,"Impossible value for MPR_times_100Ks %d (TBS %d,Nre %d)\n", - MPR_times_100Ks,ulsch[UE_id]->harq_processes[harq_pid]->TBS, - (ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12*4*ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch)); - if (MPR_times_100Ks > 0) correction_factor = ulsch_power_LUT[MPR_times_100Ks]; + if ((MPR_times_100Ks > 0)&&(MPR_times_100Ks < 750)){ + correction_factor = ulsch_power_LUT[MPR_times_100Ks]; + }else{ + correction_factor = 1; + } } for (i=0; inb_antennas_rx; i++) { pusch_vars->ulsch_power[i] = signal_energy_nodc(pusch_vars->drs_ch_estimates[i], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12)/correction_factor; LOG_D(PHY,"%4.4d.%d power harq_pid %d rb %2.2d TBS %2.2d (MPR_times_Ks %d correction %d) power %d dBtimes10\n", proc->frame_rx, proc->subframe_rx, harq_pid, - ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, ulsch[UE_id]->harq_processes[harq_pid]->TBS,MPR_times_100Ks,correction_factor,dB_fixed_times10(pusch_vars->ulsch_power[i])); + ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, ulsch[UE_id]->harq_processes[harq_pid]->TBS,MPR_times_100Ks,correction_factor,dB_fixed_x10(pusch_vars->ulsch_power[i])); + pusch_vars->ulsch_noise_power[i]=0; + for (int rb=0;rbharq_processes[harq_pid]->nb_rb;rb++) + pusch_vars->ulsch_noise_power[i]+=eNB->measurements.n0_subband_power[i][rb]/ulsch[UE_id]->harq_processes[harq_pid]->nb_rb; + LOG_D(PHY,"noise power[%d] %d\n",i,dB_fixed_x10(pusch_vars->ulsch_noise_power[i])); +/* Check this modification w.r.t to new PUSCH modifications + //symbol 3 + int symbol_offset = frame_parms->N_RB_UL*12*(3 - frame_parms->Ncp); + pusch_vars->ulsch_interference_power[i] = interference_power(&pusch_vars->drs_ch_estimates[i][symbol_offset],ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); + pusch_vars->ulsch_power[i] = signal_power(&pusch_vars->drs_ch_estimates[i][symbol_offset],ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); + //symbol 3+7 + symbol_offset = frame_parms->N_RB_UL*12*((3 - frame_parms->Ncp)+(7-frame_parms->Ncp)); + pusch_vars->ulsch_interference_power[i] += interference_power(&pusch_vars->drs_ch_estimates[i][symbol_offset],ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); + pusch_vars->ulsch_power[i] += signal_power(&pusch_vars->drs_ch_estimates[i][symbol_offset],ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); + + pusch_vars->ulsch_interference_power[i] = pusch_vars->ulsch_interference_power[i]/correction_factor; + pusch_vars->ulsch_power[i] = pusch_vars->ulsch_power[i]/correction_factor; + + if(pusch_vars->ulsch_power[i]>0x20000000){ + pusch_vars->ulsch_power[i] = 0x20000000; + pusch_vars->ulsch_interference_power[i] = 1; + }else{ + pusch_vars->ulsch_power[i] -= pusch_vars->ulsch_interference_power[i]; + if(pusch_vars->ulsch_power[i]<1) pusch_vars->ulsch_power[i] = 1; + if(pusch_vars->ulsch_interference_power[i]<1)pusch_vars->ulsch_interference_power[i] = 1; + } + + LOG_D(PHY,"%4.4d.%d power harq_pid %d rb %2.2d TBS %2.2d (MPR_times_Ks %d correction %d) power %d dBtimes10\n", proc->frame_rx, proc->subframe_rx, harq_pid, ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, ulsch[UE_id]->harq_processes[harq_pid]->TBS,MPR_times_100Ks,correction_factor,dB_fixed_x10(pusch_vars->ulsch_power[i])); + */ } ulsch_channel_level(pusch_vars->drs_ch_estimates, @@ -1088,8 +1159,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, for (aarx=0; aarxnb_antennas_rx; aarx++) avgs = cmax(avgs,avgU[aarx]); - // log2_maxh = 4+(log2_approx(avgs)/2); - log2_maxh = (log2_approx(avgs)/2)+ log2_approx(frame_parms->nb_antennas_rx-1)+4; + log2_maxh = 4+(log2_approx(avgs)/2); LOG_D(PHY,"[ULSCH] log2_maxh = %d (%d,%d)\n",log2_maxh,avgU[0],avgs); for (l=0; l<(frame_parms->symbols_per_tti-ulsch[UE_id]->harq_processes[harq_pid]->srs_active); l++) { @@ -1196,67 +1266,56 @@ void dump_ulsch(PHY_VARS_eNB *eNB,int frame,int subframe,uint8_t UE_id,int round uint8_t harq_pid; char fname[100],vname[100]; harq_pid = subframe2harq_pid(&eNB->frame_parms,frame,subframe); - LOG_UI(PHY,"Dumping ULSCH in subframe %d with harq_pid %d, round %d for NB_rb %d, TBS %d, Qm %d, N_symb %d\n", + LOG_UI(PHY,"Dumping ULSCH in subframe %d with harq_pid %d, round %d for NB_rb %d, first_rb %d, TBS %d, Qm %d, N_symb %d\n", subframe,harq_pid,round,eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, + eNB->ulsch[UE_id]->harq_processes[harq_pid]->first_rb, eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS,eNB->ulsch[UE_id]->harq_processes[harq_pid]->Qm, eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch); + for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) + LOG_UI(PHY,"ulsch_power[%d] %d, ulsch_noise_power[%d] %d\n",aa,dB_fixed_x10(eNB->pusch_vars[UE_id]->ulsch_power[aa]),aa,dB_fixed_x10(eNB->pusch_vars[UE_id]->ulsch_noise_power[aa])); sprintf(fname,"/tmp/ulsch_r%d_d",round); sprintf(vname,"/tmp/ulsch_r%d_dseq",round); LOG_UM(fname,vname,&eNB->ulsch[UE_id]->harq_processes[harq_pid]->d[0][96], eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus*3,1,0); if (eNB->common_vars.rxdata) { - sprintf(fname,"/tmp/rxsig0_r%d.m",round); - sprintf(vname,"rxs0_r%d",round); - LOG_UM(fname,vname, &eNB->common_vars.rxdata[0][0],eNB->frame_parms.samples_per_tti*10,1,1); + for (int aarx=0;aarxframe_parms.nb_antennas_rx;aarx++) { + sprintf(fname,"/tmp/rxsig%d_r%d.m",aarx,round); + sprintf(vname,"rxs%d_r%d",aarx,round); + LOG_UM(fname,vname, &eNB->common_vars.rxdata[aarx][0],eNB->frame_parms.samples_per_tti*10,1,1); - if (eNB->frame_parms.nb_antennas_rx>1) - if (eNB->common_vars.rxdata) { - sprintf(fname,"/tmp/rxsig1_r%d.m",round); - sprintf(vname,"rxs1_r%d",round); - LOG_UM(fname,vname, &eNB->common_vars.rxdata[1][0],eNB->frame_parms.samples_per_tti*10,1,1); - } + } } - - sprintf(fname,"/tmp/rxsigF0_r%d.m",round); - sprintf(vname,"rxsF0_r%d",round); - LOG_UM(fname,vname, (void *)&eNB->common_vars.rxdataF[0][0],eNB->frame_parms.ofdm_symbol_size*nsymb,1,1); - - if (eNB->frame_parms.nb_antennas_rx>1) { - sprintf(fname,"/tmp/rxsigF1_r%d.m",round); - sprintf(vname,"rxsF1_r%d",round); - LOG_UM(vname,fname, &eNB->common_vars.rxdataF[1][0],eNB->frame_parms.ofdm_symbol_size*nsymb,1,1); + if (eNB->common_vars.rxdataF) { + for (int aarx=0;aarxframe_parms.nb_antennas_rx;aarx++) { + sprintf(fname,"/tmp/rxsigF%d_r%d.m",aarx,round); + sprintf(vname,"rxsF%d_r%d",aarx,round); + LOG_UM(fname,vname, (void *)&eNB->common_vars.rxdataF[aarx][0],eNB->frame_parms.ofdm_symbol_size*nsymb,1,1); + } } - - sprintf(fname,"/tmp/rxsigF0_ext_r%d.m",round); - sprintf(vname,"rxsF0_ext_r%d",round); - LOG_UM(fname,vname, &eNB->pusch_vars[UE_id]->rxdataF_ext[0][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); - - if (eNB->frame_parms.nb_antennas_rx>1) { - sprintf(fname,"/tmp/rxsigF1_ext_r%d.m",round); - sprintf(vname,"rxsF1_ext_r%d",round); - LOG_UM(fname,vname,&eNB->pusch_vars[UE_id]->rxdataF_ext[1][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); + if (eNB->pusch_vars[UE_id]->rxdataF_ext) { + for (int aarx=0;aarxframe_parms.nb_antennas_rx;aarx++) { + sprintf(fname,"/tmp/rxsigF%d_ext_r%d.m",aarx,round); + sprintf(vname,"rxsF%d_ext_r%d",aarx,round); + LOG_UM(fname,vname, &eNB->pusch_vars[UE_id]->rxdataF_ext[aarx][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); + } } - /* if (eNB->srs_vars[UE_id].srs_ch_estimates) LOG_UM("/tmp/srs_est0.m","srsest0",eNB->srs_vars[UE_id].srs_ch_estimates[0],eNB->frame_parms.ofdm_symbol_size,1,1); if (eNB->frame_parms.nb_antennas_rx>1) if (eNB->srs_vars[UE_id].srs_ch_estimates) LOG_UM("/tmp/srs_est1.m","srsest1",eNB->srs_vars[UE_id].srs_ch_estimates[1],eNB->frame_parms.ofdm_symbol_size,1,1); */ - sprintf(fname,"/tmp/drs_est0_r%d.m",round); - sprintf(vname,"drsest0_r%d",round); - LOG_UM(fname,vname,eNB->pusch_vars[UE_id]->drs_ch_estimates[0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); + for (int aarx=0;aarxframe_parms.nb_antennas_rx;aarx++) { + sprintf(fname,"/tmp/drs_est%d_r%d.m",aarx,round); + sprintf(vname,"drsest%d_r%d",aarx,round); + LOG_UM(fname,vname,eNB->pusch_vars[UE_id]->drs_ch_estimates[aarx],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); - if (eNB->frame_parms.nb_antennas_rx>1) { - sprintf(fname,"/tmp/drs_est1_r%d.m",round); - sprintf(vname,"drsest1_r%d",round); - LOG_UM(fname,vname,eNB->pusch_vars[UE_id]->drs_ch_estimates[1],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); + sprintf(fname,"/tmp/ulsch%d_rxF_comp0_r%d.m",aarx,round); + sprintf(vname,"ulsch_rxF%d_comp0_r%d",aarx,round); + LOG_UM(fname,vname,&eNB->pusch_vars[UE_id]->rxdataF_comp[aarx][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); } - sprintf(fname,"/tmp/ulsch0_rxF_comp0_r%d.m",round); - sprintf(vname,"ulsch0_rxF_comp0_r%d",round); - LOG_UM(fname,vname,&eNB->pusch_vars[UE_id]->rxdataF_comp[0][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); // LOG_M("ulsch_rxF_comp1.m","ulsch0_rxF_comp1",&eNB->pusch_vars[UE_id]->rxdataF_comp[0][1][0],eNB->frame_parms.N_RB_UL*12*nsymb,1,1); sprintf(fname,"/tmp/ulsch_rxF_llr_r%d.m",round); sprintf(vname,"ulsch_llr_r%d",round); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c index 4f65edd6d5..efde277203 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c @@ -1293,7 +1293,7 @@ void compute_llr_offset(LTE_DL_FRAME_PARMS *frame_parms, } granted_re = nb_rb_alloc * (12-crs_re); - pbch_pss_sss_re = adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,dlsch0_harq->Qm,subframe,symbol); + pbch_pss_sss_re = adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,dlsch0_harq->Qm,subframe,symbol); pbch_pss_sss_re = (double)pbch_pss_sss_re * ((double)(12-crs_re)/12); data_re = granted_re - pbch_pss_sss_re; llr_offset = data_re * dlsch0_harq->Qm * 2; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c index 3c7e3f986b..0d8c3c9960 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c @@ -50,9 +50,6 @@ //#define DEBUG_DCI_DECODING 1 //#define DEBUG_PHY -//#undef ALL_AGGREGATION - - uint16_t extract_crc(uint8_t *dci,uint8_t dci_len) { @@ -2802,7 +2799,6 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, if (dci_cnt>old_dci_cnt) return(dci_cnt); - //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 1 search spaces at aggregation 8 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode,subframe, @@ -2836,7 +2832,6 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, if (dci_cnt>old_dci_cnt) return(dci_cnt); - //#endif //ALL_AGGREGATION } else if (tmode == 3) { @@ -2946,7 +2941,6 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, if (dci_cnt>old_dci_cnt) return(dci_cnt); - //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 2_2A search spaces at aggregation 8 LOG_D(PHY," Now check UE_SPEC format 2_2A search spaces at aggregation 8 dci length: %d[bits] %d[bytes]\n",format2A_size_bits,format2A_size_bytes); old_dci_cnt=dci_cnt; @@ -3082,7 +3076,6 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, if (dci_cnt>old_dci_cnt) return(dci_cnt); - //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 2_2A search spaces at aggregation 8 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, @@ -3214,7 +3207,6 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, if (dci_cnt>old_dci_cnt) return(dci_cnt); - //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 1E_2A_M10PRB search spaces at aggregation 8 old_dci_cnt=dci_cnt; @@ -3249,7 +3241,6 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue, if (dci_cnt>old_dci_cnt) return(dci_cnt); - //#endif //ALL_AGGREGATION } diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c index 7442a0ae7e..39900113b7 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c @@ -78,7 +78,7 @@ LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_ switch (N_RB_DL) { case 6: - bw_scaling =16; + bw_scaling =4; break; case 25: @@ -276,7 +276,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue, switch (frame_parms->N_RB_DL) { case 6: - bw_scaling =16; + bw_scaling =4; break; case 25: diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c index 556a9f2d23..6afd028099 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c @@ -51,7 +51,6 @@ #include #include "linear_preprocessing_rec.h" -#define NOCYGWIN_STATIC //#define DEBUG_MMSE @@ -838,7 +837,7 @@ int rx_pdsch(PHY_VARS_UE *ue, symbol, first_symbol_flag, nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,2,subframe,symbol), beamforming_mode); } else if (codeword_TB0 == -1) { dlsch_qpsk_llr(frame_parms, @@ -847,7 +846,7 @@ int rx_pdsch(PHY_VARS_UE *ue, symbol, first_symbol_flag, nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,2,subframe,symbol), beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { if (dlsch1_harq->Qm == 2) { @@ -857,7 +856,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { @@ -867,7 +866,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { @@ -878,7 +877,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { @@ -889,7 +888,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else { @@ -900,7 +899,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { @@ -911,7 +910,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } @@ -926,7 +925,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->llr[0], pdsch_vars[eNB_id]->dl_ch_mag0, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128, beamforming_mode); } else if (codeword_TB0 == -1) { @@ -935,7 +934,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->llr[1], pdsch_vars[eNB_id]->dl_ch_mag0, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream, beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { @@ -947,7 +946,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { @@ -958,7 +957,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { @@ -970,7 +969,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { @@ -982,7 +981,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else { @@ -994,7 +993,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { @@ -1006,7 +1005,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } @@ -1022,7 +1021,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol], beamforming_mode); } else if (codeword_TB0 == -1) { @@ -1032,7 +1031,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol], beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { @@ -1044,7 +1043,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { @@ -1055,7 +1054,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { @@ -1067,7 +1066,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { @@ -1079,7 +1078,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else { @@ -1091,7 +1090,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho2_ext, (int16_t *)pllr_symbol_cw0, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol]); if (rx_type==rx_IC_dual_stream) { @@ -1103,7 +1102,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], (int16_t *)pllr_symbol_cw1, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch1_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol]); } } @@ -1125,7 +1124,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->rxdataF_comp0, (int16_t *)pllr_symbol_cw0, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,2,subframe,symbol), beamforming_mode); } @@ -1138,7 +1137,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->llr[0], pdsch_vars[eNB_id]->dl_ch_mag0, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128, beamforming_mode); } @@ -1153,7 +1152,7 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), + adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol], beamforming_mode); } @@ -1234,7 +1233,7 @@ void dlsch_channel_compensation(int **rxdataF_ext, unsigned short rb; unsigned char aatx,aarx,symbol_mod,pilots=0; __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0}; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { @@ -1657,11 +1656,11 @@ void dlsch_channel_compensation_core(int **rxdataF_ext, int length_mod8 = 0; int length2; __m128i *dl_ch128,*dl_ch_mag128,*dl_ch_mag128b, *dl_ch128_2, *rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0}; int aatx = 0, aarx = 0; for (aatx=0; aatx=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) @@ -2411,7 +2410,7 @@ void dlsch_channel_compensation_TM34(LTE_DL_FRAME_PARMS *frame_parms, int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[harq_pid][round]; unsigned char *pmi_ext = pdsch_vars->pmi_ext; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp0_128,QAM_amp1_128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp0_128={0},QAM_amp1_128={0}; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c index 4c74377ef6..43f3b5451f 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c @@ -746,7 +746,7 @@ int32_t dlsch_qpsk_llr_SIC(LTE_DL_FRAME_PARMS *frame_parms, amp_tmp=amp_tmp<<1; // to compensate for >> 1 shift in modulation - pbch_pss_sss_adjust=adjust_G2(frame_parms,&rb_alloc,2,subframe,symbol); + pbch_pss_sss_adjust=adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL ,&rb_alloc,2,subframe,symbol); if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { if (frame_parms->nb_antenna_ports_eNB!=1) @@ -981,7 +981,7 @@ void dlsch_16qam_llr_SIC (LTE_DL_FRAME_PARMS *frame_parms, symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; - pbch_pss_sss_adjust=adjust_G2(frame_parms,&rb_alloc,4,subframe,symbol); + pbch_pss_sss_adjust=adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,&rb_alloc,4,subframe,symbol); if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { amp_tmp=0x1fff;//dlsch0->sqrt_rho_b; already taken into account @@ -1281,7 +1281,7 @@ void dlsch_64qam_llr_SIC(LTE_DL_FRAME_PARMS *frame_parms, symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; - pbch_pss_sss_adjust=adjust_G2(frame_parms,&rb_alloc,6,subframe,symbol); + pbch_pss_sss_adjust=adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,&rb_alloc,6,subframe,symbol); if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { amp_tmp = 0x1fff;//dlsch0->sqrt_rho_b; already taken into account diff --git a/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c index 69aa1c06a3..3c22c64a9e 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c @@ -328,7 +328,7 @@ void mch_channel_compensation(int **rxdataF_ext, int aarx,nre,i; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0}; #elif defined(__arm__) #endif @@ -455,7 +455,7 @@ void mch_channel_compensation_khz_1dot25(int **rxdataF_ext, int aarx,nre,i; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0}; #elif defined(__arm__) #endif /*if ((symbol == 2) || (symbol == 6) || (symbol == 10)) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c index ab7c2b9091..929f63e9fc 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c @@ -41,6 +41,7 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "../LTE_TRANSPORT/prach_extern.h" +#include "common/utils/lte/prach_utils.h" //#define PRACH_DEBUG 1 @@ -115,7 +116,9 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 NCS = NCS_restricted[Ncs_config]; } - n_ra_prb = get_prach_prb_offset(&(ue->frame_parms), + n_ra_prb = get_prach_prb_offset(ue->frame_parms.frame_type, + ue->frame_parms.tdd_config, + ue->frame_parms.N_RB_UL, ue->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, ue->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset, tdd_mapindex, Nf); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c index 1f9fb86f80..9427ec3a5b 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/pucch_ue.c @@ -336,8 +336,8 @@ void generate_pucch1x(int32_t **txdataF, -inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) __attribute__((always_inline)); -inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) { +static inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) __attribute__((always_inline)); +static inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) { uint32_t x1, x2, s=0; int i; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/srs_modulation.c b/openair1/PHY/LTE_UE_TRANSPORT/srs_modulation.c index e6960273c7..9c0edb467c 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/srs_modulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/srs_modulation.c @@ -170,6 +170,7 @@ int32_t generate_srs(LTE_DL_FRAME_PARMS *frame_parms, Msc_RS = msrsb * 6; k0 = ( ( (int16_t)(frame_parms->N_RB_UL>>1) - (int16_t)(msrs0>>1) ) * 12 ) + kTC; + AssertFatal(msrsb,"divide by 0"); nb = (4*n_RRC/msrsb)%Nb; for (b=0; b<=Bsrs; b++) { diff --git a/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h b/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h index 3299401443..c5d096ceb7 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h +++ b/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h @@ -1303,7 +1303,7 @@ uint32_t conv_nprb(uint8_t ra_header,uint32_t rb_alloc,int N_RB_DL); int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe, uint8_t beamforming_mode); int adjust_G(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe); -int adjust_G2(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol); + #ifndef modOrder @@ -1740,10 +1740,5 @@ double computeRhoB_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, LTE_UE_DLSCH_t *dlsch_ue); */ -uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, - uint8_t prach_ConfigIndex, - uint8_t n_ra_prboffset, - uint8_t tdd_mapindex, uint16_t Nf); - /**@}*/ #endif diff --git a/openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h b/openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h index 4c433a5683..6b84a5f969 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h +++ b/openair1/PHY/LTE_UE_TRANSPORT/transport_ue.h @@ -36,9 +36,11 @@ #include "../LTE_TRANSPORT/mdci.h" #include "../LTE_TRANSPORT/uci_common.h" #include "../LTE_TRANSPORT/transport_common.h" +/* #ifndef STANDALONE_COMPILE #include "UTIL/LISTS/list.h" #endif +*/ #include "../LTE_TRANSPORT/transport_common.h" diff --git a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c index de1c3891da..ae3ebbce9d 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c @@ -52,8 +52,7 @@ -void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) -{ +void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) { int i; int r; @@ -68,6 +67,7 @@ void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); ulsch->harq_processes[i]->b = NULL; } + for (r=0; rharq_processes[i]->c[r]) { free16(ulsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); @@ -79,51 +79,47 @@ void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch) ulsch->harq_processes[i] = NULL; } } + free16(ulsch,sizeof(LTE_UE_ULSCH_t)); } - } -LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) -{ - +LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) { LTE_UE_ULSCH_t *ulsch; unsigned char exit_flag = 0,i,j,r; unsigned char bw_scaling =1; switch (N_RB_UL) { - case 6: - bw_scaling =16; - break; + case 6: + bw_scaling =16; + break; - case 25: - bw_scaling =4; - break; + case 25: + bw_scaling =4; + break; - case 50: - bw_scaling =2; - break; - - default: - bw_scaling =1; - break; + case 50: + bw_scaling =2; + break; + + default: + bw_scaling =1; + break; } ulsch = (LTE_UE_ULSCH_t *)malloc16(sizeof(LTE_UE_ULSCH_t)); if (ulsch) { memset(ulsch,0,sizeof(LTE_UE_ULSCH_t)); - ulsch->Mlimit = 4; for (i=0; i<8; i++) { - ulsch->harq_processes[i] = (LTE_UL_UE_HARQ_t *)malloc16(sizeof(LTE_UL_UE_HARQ_t)); // printf("ulsch->harq_processes[%d] %p\n",i,ulsch->harq_processes[i]); if (ulsch->harq_processes[i]) { memset(ulsch->harq_processes[i], 0, sizeof(LTE_UL_UE_HARQ_t)); - ulsch->harq_processes[i]->b = (unsigned char*)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + ulsch->harq_processes[i]->b = (unsigned char *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); if (ulsch->harq_processes[i]->b) memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); @@ -134,7 +130,7 @@ LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) if (abstraction_flag==0) { for (r=0; rharq_processes[i]->c[r] = (unsigned char*)malloc16(((r==0)?8:0) + 3+768); // account for filler in first segment and CRCs for multiple segment case + ulsch->harq_processes[i]->c[r] = (unsigned char *)malloc16(((r==0)?8:0) + 3+768); // account for filler in first segment and CRCs for multiple segment case if (ulsch->harq_processes[i]->c[r]) memset(ulsch->harq_processes[i]->c[r],0,((r==0)?8:0) + 3+768); @@ -167,8 +163,6 @@ LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag) LOG_E(PHY,"new_ue_ulsch exit flag, size of %d , %zu\n",exit_flag, sizeof(LTE_UE_ULSCH_t)); free_ue_ulsch(ulsch); return(NULL); - - } @@ -179,15 +173,12 @@ uint32_t ulsch_encoding(uint8_t *a, uint8_t subframe_rx, uint8_t tmode, uint8_t control_only_flag, - uint8_t Nbundled) -{ - + uint8_t Nbundled) { time_stats_t *seg_stats=&ue->ulsch_segmentation_stats; time_stats_t *rm_stats=&ue->ulsch_rate_matching_stats; time_stats_t *te_stats=&ue->ulsch_turbo_encoding_stats; time_stats_t *i_stats=&ue->ulsch_interleaving_stats; time_stats_t *m_stats=&ue->ulsch_multiplexing_stats; - // uint16_t offset; uint32_t crc=1; uint32_t A; @@ -237,7 +228,6 @@ uint32_t ulsch_encoding(uint8_t *a, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI, VCD_FUNCTION_IN); rnti = ue->pdcch_vars[ue->current_thread_id[subframe_rx]][eNB_id]->crnti; fill_CQI(ulsch,meas,0,harq_pid,ue->frame_parms.N_RB_DL,rnti, tmode,ue->sinr_eff); - LOG_D(PHY,"ULSCH Encoding rnti %x \n", rnti); print_CQI(ulsch->o,ulsch->uci_format,0,ue->frame_parms.N_RB_DL); @@ -246,6 +236,7 @@ uint32_t ulsch_encoding(uint8_t *a, //LOG_I(PHY,"XXX saving pmi for DL %x\n",pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi)); dlsch[0]->pmi_alloc = ((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi; } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI, VCD_FUNCTION_OUT); } @@ -268,17 +259,15 @@ uint32_t ulsch_encoding(uint8_t *a, if (control_only_flag == 0) { A=ulsch->harq_processes[harq_pid]->TBS; Q_m = get_Qm_ul(ulsch->harq_processes[harq_pid]->mcs); - ulsch->harq_processes[harq_pid]->control_only = 0; - #ifdef DEBUG_ULSCH_CODING printf("[PHY][UE] ULSCH coding : A %d, Qm %d, mcs %d, harq_pid %d, round %d, RV %d\n", - ulsch->harq_processes[harq_pid]->TBS, - Q_m, - ulsch->harq_processes[harq_pid]->mcs, - harq_pid, - ulsch->harq_processes[harq_pid]->round, - ulsch->harq_processes[harq_pid]->rvidx); + ulsch->harq_processes[harq_pid]->TBS, + Q_m, + ulsch->harq_processes[harq_pid]->mcs, + harq_pid, + ulsch->harq_processes[harq_pid]->round, + ulsch->harq_processes[harq_pid]->rvidx); for (i=0; iharq_processes[harq_pid]->O_ACK; i++) printf("ulsch_coding: o_ACK[%d] %d\n",i,ulsch->o_ACK[i]); @@ -301,16 +290,13 @@ uint32_t ulsch_encoding(uint8_t *a, #endif if (ulsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - start_meas(seg_stats); // Add 24-bit crc (polynomial A) to payload crc = crc24a(a, A)>>8; - - a[A>>3] = ((uint8_t*)&crc)[2]; - a[1+(A>>3)] = ((uint8_t*)&crc)[1]; - a[2+(A>>3)] = ((uint8_t*)&crc)[0]; - + a[A>>3] = ((uint8_t *)&crc)[2]; + a[1+(A>>3)] = ((uint8_t *)&crc)[1]; + a[2+(A>>3)] = ((uint8_t *)&crc)[0]; ulsch->harq_processes[harq_pid]->B = A+24; ulsch->harq_processes[harq_pid]->b = a; lte_segmentation(ulsch->harq_processes[harq_pid]->b, @@ -322,7 +308,6 @@ uint32_t ulsch_encoding(uint8_t *a, &ulsch->harq_processes[harq_pid]->Kplus, &ulsch->harq_processes[harq_pid]->Kminus, &ulsch->harq_processes[harq_pid]->F); - stop_meas(seg_stats); for (r=0; rharq_processes[harq_pid]->C; r++) { @@ -332,25 +317,20 @@ uint32_t ulsch_encoding(uint8_t *a, Kr = ulsch->harq_processes[harq_pid]->Kplus; Kr_bytes = Kr>>3; - #ifdef DEBUG_ULSCH_CODING printf("Generating Code Segment %d (%d bits)\n",r,Kr); // generate codewords - printf("bits_per_codeword (Kr)= %d\n",Kr); printf("N_RB = %d\n",ulsch->harq_processes[harq_pid]->nb_rb); printf("Ncp %d\n",frame_parms->Ncp); printf("Qm %d\n",Q_m); #endif - // offset=0; - - start_meas(te_stats); encoder(ulsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &ulsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? ulsch->harq_processes[harq_pid]->F : 0 + Kr>>3, + &ulsch->harq_processes[harq_pid]->d[r][96], + (r==0) ? ulsch->harq_processes[harq_pid]->F : 0 ); stop_meas(te_stats); #ifdef DEBUG_ULSCH_CODING @@ -366,7 +346,6 @@ uint32_t ulsch_encoding(uint8_t *a, ulsch->harq_processes[harq_pid]->w[r]); stop_meas(i_stats); } - } if (ulsch->harq_processes[harq_pid]->C == 0) { @@ -392,7 +371,6 @@ uint32_t ulsch_encoding(uint8_t *a, ulsch->harq_processes[harq_pid]->sumKr = sumKr; // Compute Q_ri (p. 23 36-212) - Qprime = ulsch->O_RI*ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_ri_times8; if (Qprime > 0) { @@ -407,7 +385,6 @@ uint32_t ulsch_encoding(uint8_t *a, Q_RI = Q_m*Qprime; Qprime_RI = Qprime; - // Compute Q_ack (p. 23 36-212) Qprime = ulsch->harq_processes[harq_pid]->O_ACK*ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_harqack_times8; @@ -423,20 +400,18 @@ uint32_t ulsch_encoding(uint8_t *a, Q_ACK = Qprime * Q_m; Qprime_ACK = Qprime; - LOG_D(PHY,"UE (%x/%d) O_ACK %d, Mcs_initial %d, Nsymb_initial %d, beta_offset_harqack*8 %d, sum Kr %d, Qprime_ACK %d, Q_ACK %d\n", - rnti, harq_pid, - ulsch->harq_processes[harq_pid]->O_ACK, - ulsch->harq_processes[harq_pid]->Msc_initial, - ulsch->harq_processes[harq_pid]->Nsymb_initial, - ulsch->beta_offset_harqack_times8, - sumKr, - Qprime_ACK, - Q_ACK); + rnti, harq_pid, + ulsch->harq_processes[harq_pid]->O_ACK, + ulsch->harq_processes[harq_pid]->Msc_initial, + ulsch->harq_processes[harq_pid]->Nsymb_initial, + ulsch->beta_offset_harqack_times8, + sumKr, + Qprime_ACK, + Q_ACK); // Compute Q_cqi, assume O>11, p. 26 36-212 if (control_only_flag == 0) { - if (ulsch->O < 12) L=0; else @@ -446,13 +421,13 @@ uint32_t ulsch_encoding(uint8_t *a, Qprime = (ulsch->O + L) * ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_cqi_times8; else Qprime = 0; - LOG_D(PHY,"Qprime %d, O_RI %d + %d, Msc %d, Nym %d beta %d\n", - Qprime, - ulsch->O, L, - ulsch->harq_processes[harq_pid]->Msc_initial, - ulsch->harq_processes[harq_pid]->Nsymb_initial, - ulsch->beta_offset_cqi_times8); + LOG_D(PHY,"Qprime %d, O_RI %d + %d, Msc %d, Nym %d beta %d\n", + Qprime, + ulsch->O, L, + ulsch->harq_processes[harq_pid]->Msc_initial, + ulsch->harq_processes[harq_pid]->Nsymb_initial, + ulsch->beta_offset_cqi_times8); if (Qprime > 0) { if ((Qprime % (8*sumKr)) > 0) @@ -463,31 +438,29 @@ uint32_t ulsch_encoding(uint8_t *a, G = ulsch->harq_processes[harq_pid]->nb_rb * (12 * Q_m) * (ulsch->Nsymb_pusch); LOG_D(PHY,"G: rb %d * ( 12 * Qm %d ) * nsymb %d, Qprime %d, O_RI %d\n", ulsch->harq_processes[harq_pid]->nb_rb, Q_m, ulsch->Nsymb_pusch, Qprime, ulsch->O_RI); + if (Qprime > (G - ulsch->O_RI)) Qprime = G - ulsch->O_RI; Q_CQI = Q_m * Qprime; Qprime_CQI = Qprime; - - - G = G - Q_RI - Q_CQI; - LOG_D(PHY,"new G: %d, Q_RI %d Q_CQI %d\n", G , Q_RI , Q_CQI); + LOG_D(PHY,"new G: %d, Q_RI %d Q_CQI %d\n", G, Q_RI, Q_CQI); ulsch->harq_processes[harq_pid]->G = G; -/* - LOG_I(PHY,"ULSCH Encoding G %d, Q_RI %d (O_RI%d, Msc_initial %d, Nsymb_initial%d, beta_offset_ri_times8 %d), Q_CQI %d, Q_ACK %d \n",G,Q_RI,ulsch->O_RI,ulsch->harq_processes[harq_pid]->Msc_initial,ulsch->harq_processes[harq_pid]->Nsymb_initial,ulsch->beta_offset_ri_times8,Q_CQI,Q_ACK); + /* + LOG_I(PHY,"ULSCH Encoding G %d, Q_RI %d (O_RI%d, Msc_initial %d, Nsymb_initial%d, beta_offset_ri_times8 %d), Q_CQI %d, Q_ACK %d \n",G,Q_RI,ulsch->O_RI,ulsch->harq_processes[harq_pid]->Msc_initial,ulsch->harq_processes[harq_pid]->Nsymb_initial,ulsch->beta_offset_ri_times8,Q_CQI,Q_ACK); - LOG_I(PHY,"ULSCH Encoding (Nid_cell %d, rnti %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d\n", - frame_parms->Nid_cell,ulsch->rnti, - harq_pid, - ulsch->harq_processes[harq_pid]->round, - ulsch->harq_processes[harq_pid]->rvidx, - ulsch->harq_processes[harq_pid]->mcs, - ulsch->O_RI, - ulsch->harq_processes[harq_pid]->O_ACK, - G); -*/ + LOG_I(PHY,"ULSCH Encoding (Nid_cell %d, rnti %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d\n", + frame_parms->Nid_cell,ulsch->rnti, + harq_pid, + ulsch->harq_processes[harq_pid]->round, + ulsch->harq_processes[harq_pid]->rvidx, + ulsch->harq_processes[harq_pid]->mcs, + ulsch->O_RI, + ulsch->harq_processes[harq_pid]->O_ACK, + G); + */ if ((int)G < 0) { LOG_E(PHY,"FATAL: ulsch_coding.c G < 0 (%d) : Q_RI %d, Q_CQI %d, O %d, betaCQI_times8 %d)\n",G,Q_RI,Q_CQI,ulsch->O,ulsch->beta_offset_cqi_times8); @@ -495,26 +468,21 @@ uint32_t ulsch_encoding(uint8_t *a, return(-1); } - // Data and control multiplexing (5.2.2.7 36-212) - H = G + Q_CQI; Hprime = H/Q_m; - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the // outputs for each code segment, see Section 5.1.5 p.20 for (r=0; rharq_processes[harq_pid]->C; r++) { #ifdef DEBUG_ULSCH_CODING printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - Q_m,ulsch->harq_processes[harq_pid]->nb_rb); + r, + G, + Kr*3, + Q_m,ulsch->harq_processes[harq_pid]->nb_rb); #endif - start_meas(rm_stats); r_offset += lte_rate_matching_turbo(ulsch->harq_processes[harq_pid]->RTC[r], G, @@ -529,7 +497,7 @@ uint32_t ulsch_encoding(uint8_t *a, 1, r, ulsch->harq_processes[harq_pid]->nb_rb); - //ulsch->harq_processes[harq_pid]->mcs); // r + //ulsch->harq_processes[harq_pid]->mcs); // r stop_meas(rm_stats); #ifdef DEBUG_ULSCH_CODING @@ -544,7 +512,6 @@ uint32_t ulsch_encoding(uint8_t *a, Hprime = H/Q_m; } - // Do CQI coding if ((ulsch->O>1) && (ulsch->O < 12)) { LOG_E(PHY,"short CQI sizes not supported yet\n"); @@ -558,23 +525,18 @@ uint32_t ulsch_encoding(uint8_t *a, printf("crc(cqi) tx : %x\n",crc); #endif memset((void *)&ulsch->o_d[0],LTE_NULL,96); - ccodelte_encode(ulsch->O, 1, o_flip, &ulsch->o_d[96], 0); - - o_RCC = sub_block_interleaving_cc(8+ulsch->O, &ulsch->o_d[96], ulsch->o_w); - lte_rate_matching_cc(o_RCC, Q_CQI, ulsch->o_w, ulsch->q); - } i=0; @@ -582,29 +544,29 @@ uint32_t ulsch_encoding(uint8_t *a, // Do RI coding if (ulsch->O_RI == 1) { switch (Q_m) { - case 2: - ulsch->q_RI[0] = ulsch->o_RI[0]; - ulsch->q_RI[1] = PUSCH_y;//ulsch->o_RI[0]; - len_RI=2; - break; + case 2: + ulsch->q_RI[0] = ulsch->o_RI[0]; + ulsch->q_RI[1] = PUSCH_y;//ulsch->o_RI[0]; + len_RI=2; + break; - case 4: - ulsch->q_RI[0] = ulsch->o_RI[0]; - ulsch->q_RI[1] = PUSCH_y;//1; - ulsch->q_RI[2] = PUSCH_x;//ulsch->o_RI[0]; - ulsch->q_RI[3] = PUSCH_x;//1; - len_RI=4; - break; + case 4: + ulsch->q_RI[0] = ulsch->o_RI[0]; + ulsch->q_RI[1] = PUSCH_y;//1; + ulsch->q_RI[2] = PUSCH_x;//ulsch->o_RI[0]; + ulsch->q_RI[3] = PUSCH_x;//1; + len_RI=4; + break; - case 6: - ulsch->q_RI[0] = ulsch->o_RI[0]; - ulsch->q_RI[1] = PUSCH_y;//1; - ulsch->q_RI[2] = PUSCH_x;//1; - ulsch->q_RI[3] = PUSCH_x;//ulsch->o_RI[0]; - ulsch->q_RI[4] = PUSCH_x;//1; - ulsch->q_RI[5] = PUSCH_x;//1; - len_RI=6; - break; + case 6: + ulsch->q_RI[0] = ulsch->o_RI[0]; + ulsch->q_RI[1] = PUSCH_y;//1; + ulsch->q_RI[2] = PUSCH_x;//1; + ulsch->q_RI[3] = PUSCH_x;//ulsch->o_RI[0]; + ulsch->q_RI[4] = PUSCH_x;//1; + ulsch->q_RI[5] = PUSCH_x;//1; + len_RI=6; + break; } } else if (ulsch->O_RI>1) { LOG_E(PHY,"RI cannot be more than 1 bit yet\n"); @@ -616,35 +578,35 @@ uint32_t ulsch_encoding(uint8_t *a, wACK_idx = (ulsch->bundling==0) ? 4 : ((Nbundled-1)&3); #ifdef DEBUG_ULSCH_CODING printf("ulsch_coding.c: Bundling %d, Nbundled %d, wACK_idx %d\n", - ulsch->bundling,Nbundled,wACK_idx); + ulsch->bundling,Nbundled,wACK_idx); #endif // 1-bit ACK/NAK if (ulsch->harq_processes[harq_pid]->O_ACK == 1) { switch (Q_m) { - case 2: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1);//ulsch->o_ACK[0]; - len_ACK = 2; - break; + case 2: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1);//ulsch->o_ACK[0]; + len_ACK = 2; + break; - case 4: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1); - ulsch->q_ACK[2] = PUSCH_x; - ulsch->q_ACK[3] = PUSCH_x; - len_ACK = 4; - break; + case 4: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1); + ulsch->q_ACK[2] = PUSCH_x; + ulsch->q_ACK[3] = PUSCH_x; + len_ACK = 4; + break; - case 6: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1); - ulsch->q_ACK[2] = PUSCH_x; - ulsch->q_ACK[3] = PUSCH_x; - ulsch->q_ACK[4] = PUSCH_x; - ulsch->q_ACK[6] = PUSCH_x; - len_ACK = 6; - break; + case 6: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : ((ulsch->o_ACK[0]+wACK[wACK_idx][1])&1); + ulsch->q_ACK[2] = PUSCH_x; + ulsch->q_ACK[3] = PUSCH_x; + ulsch->q_ACK[4] = PUSCH_x; + ulsch->q_ACK[6] = PUSCH_x; + len_ACK = 6; + break; } } @@ -653,56 +615,53 @@ uint32_t ulsch_encoding(uint8_t *a, ack_parity = (ulsch->o_ACK[0]+ulsch->o_ACK[1])&1; switch (Q_m) { - case 2: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[2] = (ack_parity+wACK[wACK_idx][0])&1; - ulsch->q_ACK[3] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[4] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[5] = (ack_parity+wACK[wACK_idx][1])&1; - len_ACK = 6; - break; + case 2: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[2] = (ack_parity+wACK[wACK_idx][0])&1; + ulsch->q_ACK[3] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[4] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[5] = (ack_parity+wACK[wACK_idx][1])&1; + len_ACK = 6; + break; - case 4: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[2] = PUSCH_x; - ulsch->q_ACK[3] = PUSCH_x;//1; - ulsch->q_ACK[4] = (ack_parity+wACK[wACK_idx][0])&1; - ulsch->q_ACK[5] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[6] = PUSCH_x; - ulsch->q_ACK[7] = PUSCH_x;//1; - ulsch->q_ACK[8] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[9] = (ack_parity+wACK[wACK_idx][1])&1; - ulsch->q_ACK[10] = PUSCH_x; - ulsch->q_ACK[11] = PUSCH_x;//1; - len_ACK = 12; - break; + case 4: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[2] = PUSCH_x; + ulsch->q_ACK[3] = PUSCH_x;//1; + ulsch->q_ACK[4] = (ack_parity+wACK[wACK_idx][0])&1; + ulsch->q_ACK[5] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[6] = PUSCH_x; + ulsch->q_ACK[7] = PUSCH_x;//1; + ulsch->q_ACK[8] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[9] = (ack_parity+wACK[wACK_idx][1])&1; + ulsch->q_ACK[10] = PUSCH_x; + ulsch->q_ACK[11] = PUSCH_x;//1; + len_ACK = 12; + break; - case 6: - ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; - ulsch->q_ACK[2] = PUSCH_x; - ulsch->q_ACK[3] = PUSCH_x; - ulsch->q_ACK[4] = PUSCH_x; - ulsch->q_ACK[5] = PUSCH_x; - - ulsch->q_ACK[6] = (ack_parity+wACK[wACK_idx][0])&1; - ulsch->q_ACK[7] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[8] = PUSCH_x; - ulsch->q_ACK[9] = PUSCH_x; - ulsch->q_ACK[10] = PUSCH_x; - ulsch->q_ACK[11] = PUSCH_x; - - ulsch->q_ACK[12] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; - ulsch->q_ACK[13] = (ack_parity+wACK[wACK_idx][1])&1; - ulsch->q_ACK[14] = PUSCH_x; - ulsch->q_ACK[15] = PUSCH_x; - ulsch->q_ACK[16] = PUSCH_x; - ulsch->q_ACK[17] = PUSCH_x; - len_ACK = 18; - - break; + case 6: + ulsch->q_ACK[0] = (ulsch->o_ACK[0]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[1] = (ulsch->o_ACK[1]+wACK[wACK_idx][0])&1; + ulsch->q_ACK[2] = PUSCH_x; + ulsch->q_ACK[3] = PUSCH_x; + ulsch->q_ACK[4] = PUSCH_x; + ulsch->q_ACK[5] = PUSCH_x; + ulsch->q_ACK[6] = (ack_parity+wACK[wACK_idx][0])&1; + ulsch->q_ACK[7] = (ulsch->o_ACK[0]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[8] = PUSCH_x; + ulsch->q_ACK[9] = PUSCH_x; + ulsch->q_ACK[10] = PUSCH_x; + ulsch->q_ACK[11] = PUSCH_x; + ulsch->q_ACK[12] = (ulsch->o_ACK[1]+wACK[wACK_idx][1])&1; + ulsch->q_ACK[13] = (ack_parity+wACK[wACK_idx][1])&1; + ulsch->q_ACK[14] = PUSCH_x; + ulsch->q_ACK[15] = PUSCH_x; + ulsch->q_ACK[16] = PUSCH_x; + ulsch->q_ACK[17] = PUSCH_x; + len_ACK = 18; + break; } } @@ -712,23 +671,17 @@ uint32_t ulsch_encoding(uint8_t *a, return(-1); } - // channel multiplexing/interleaving - start_meas(m_stats); Hpp = Hprime + Q_RI; - Cmux = ulsch->Nsymb_pusch; Rmux = Hpp*Q_m/Cmux; Rmux_prime = Rmux/Q_m; - Qprime_RI = Q_RI / Q_m; Qprime_ACK = Q_ACK / Q_m; Qprime_CQI = Q_CQI / Q_m; - // printf("Qprime_CQI = %d\n",Qprime_CQI); // RI BITS - memset(y,LTE_NULL,Q_m*Hpp); if (frame_parms->Ncp == 0) @@ -747,10 +700,8 @@ uint32_t ulsch_encoding(uint8_t *a, } j=(j+3)&3; - } - // CQI and Data bits j=0; /* @@ -775,7 +726,6 @@ uint32_t ulsch_encoding(uint8_t *a, */ for (i=0; ie[iprime]; + y[1+j2] = ulsch->e[1+iprime]; + j2+=2; + } - for (iprime=0; iprime<(Hprime-Qprime_CQI)<<1; iprime+=2) { - while (y[j2] != LTE_NULL) j2+=2; + break; - y[j2] = ulsch->e[iprime]; - y[1+j2] = ulsch->e[1+iprime]; - j2+=2; - } + case 4: + for (iprime=0; iprime<(Hprime-Qprime_CQI)<<2; iprime+=4) { + while (y[j2] != LTE_NULL) j2+=4; - break; + y[j2] = ulsch->e[iprime]; + y[1+j2] = ulsch->e[1+iprime]; + y[2+j2] = ulsch->e[2+iprime]; + y[3+j2] = ulsch->e[3+iprime]; + j2+=4; + } - case 4: - for (iprime=0; iprime<(Hprime-Qprime_CQI)<<2; iprime+=4) { - while (y[j2] != LTE_NULL) j2+=4; + break; - y[j2] = ulsch->e[iprime]; - y[1+j2] = ulsch->e[1+iprime]; - y[2+j2] = ulsch->e[2+iprime]; - y[3+j2] = ulsch->e[3+iprime]; - j2+=4; - } + case 6: + for (iprime=0; iprime<(Hprime-Qprime_CQI)*6; iprime+=6) { + while (y[j2] != LTE_NULL) j2+=6; - break; - - case 6: - for (iprime=0; iprime<(Hprime-Qprime_CQI)*6; iprime+=6) { - while (y[j2] != LTE_NULL) j2+=6; - - y[j2] = ulsch->e[iprime]; - y[1+j2] = ulsch->e[1+iprime]; - y[2+j2] = ulsch->e[2+iprime]; - y[3+j2] = ulsch->e[3+iprime]; - y[4+j2] = ulsch->e[4+iprime]; - y[5+j2] = ulsch->e[5+iprime]; - j2+=6; - } - - break; + y[j2] = ulsch->e[iprime]; + y[1+j2] = ulsch->e[1+iprime]; + y[2+j2] = ulsch->e[2+iprime]; + y[3+j2] = ulsch->e[3+iprime]; + y[4+j2] = ulsch->e[4+iprime]; + y[5+j2] = ulsch->e[5+iprime]; + j2+=6; + } + break; } // HARQ-ACK Bits (Note these overwrite some bits) @@ -848,57 +795,56 @@ uint32_t ulsch_encoding(uint8_t *a, y[q+(Q_m*((r*Cmux) + columnset[j]))] = ulsch->q_ACK[(q+(Q_m*i))%len_ACK]; #ifdef DEBUG_ULSCH_CODING printf("ulsch_coding.c: ACK %d => y[%d]=%d (i %d, r*Cmux %d, columnset %d)\n",q+(Q_m*i), - q+(Q_m*((r*Cmux) + columnset[j])),ulsch->q_ACK[(q+(Q_m*i))%len_ACK], - i,r*Cmux,columnset[j]); + q+(Q_m*((r*Cmux) + columnset[j])),ulsch->q_ACK[(q+(Q_m*i))%len_ACK], + i,r*Cmux,columnset[j]); #endif } j=(j+3)&3; - } // write out buffer j=0; switch (Q_m) { - case 2: - for (i=0; ih[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - } + case 2: + for (i=0; ih[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + } - break; + break; - case 4: - for (i=0; ih[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - } + case 4: + for (i=0; ih[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + } - break; + break; - case 6: - for (i=0; ih[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - ulsch->h[j++] = *yptr++; - } + case 6: + for (i=0; ih[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + ulsch->h[j++] = *yptr++; + } - break; + break; - default: - break; + default: + break; } stop_meas(m_stats); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_modulation.c b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_modulation.c index b08fe30248..7ec3e7bfb6 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_modulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_modulation.c @@ -42,7 +42,6 @@ //#define DEBUG_ULSCH_MODULATION -#ifndef OFDMA_ULSCH void dft_lte(int32_t *z,int32_t *d, int32_t Msc_PUSCH, uint8_t Nsymb) { @@ -371,7 +370,6 @@ void dft_lte(int32_t *z,int32_t *d, int32_t Msc_PUSCH, uint8_t Nsymb) // printf("\n"); } -#endif void ulsch_modulation(int32_t **txdataF, short amp, uint32_t frame, @@ -690,57 +688,10 @@ void ulsch_modulation(int32_t **txdataF, // Transform Precoding -#ifdef OFDMA_ULSCH - - for (i=0; iz[i] = ulsch->d[i]; - } - -#else dft_lte(ulsch->z,ulsch->d,Msc_PUSCH,ulsch->Nsymb_pusch); -#endif DevAssert(txdataF); -#ifdef OFDMA_ULSCH - re_offset0 = frame_parms->first_carrier_offset + (ulsch->harq_processes[harq_pid]->first_rb*12); - - if (re_offset0>frame_parms->ofdm_symbol_size) { - re_offset0 -= frame_parms->ofdm_symbol_size; - // re_offset0++; - } - - // printf("re_offset0 %d\n",re_offset0); - - - for (j=0,l=0; l<(nsymb-ulsch->srs_active); l++) { - re_offset = re_offset0; - symbol_offset = (int)frame_parms->ofdm_symbol_size*(l+(subframe*nsymb)); -#ifdef DEBUG_ULSCH_MODULATION - printf("symbol %d (subframe %d): symbol_offset %d\n",l,subframe,symbol_offset); -#endif - txptr = &txdataF[0][symbol_offset]; - - if (((frame_parms->Ncp == 0) && ((l==3) || (l==10)))|| - ((frame_parms->Ncp == 1) && ((l==2) || (l==8)))) { - } - // Skip reference symbols - else { - - // printf("copying %d REs\n",Msc_PUSCH); - for (i=0; iz[j],((int16_t*)&ulsch->z[j])[0],((int16_t*)&ulsch->z[j])[1]); -#endif - txptr[re_offset++] = ulsch->z[j]; - - if (re_offset==frame_parms->ofdm_symbol_size) - re_offset = 0; - } - } - } - -# else // OFDMA_ULSCH = 0 re_offset0 = frame_parms->first_carrier_offset + (ulsch->harq_processes[harq_pid]->first_rb*12); if (re_offset0>frame_parms->ofdm_symbol_size) { @@ -777,8 +728,5 @@ void ulsch_modulation(int32_t **txdataF, } } -#endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_MODULATION, VCD_FUNCTION_OUT); - } diff --git a/openair1/PHY/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c index b1f419b172..d592aa466e 100644 --- a/openair1/PHY/MODULATION/beamforming.c +++ b/openair1/PHY/MODULATION/beamforming.c @@ -44,7 +44,6 @@ #include "PHY/defs_common.h" #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" #include "PHY/CODING/coding_defs.h" #include "PHY/CODING/coding_extern.h" #include "PHY/CODING/lte_interleaver_inline.h" @@ -145,7 +144,8 @@ int nr_beam_precoding(int32_t **txdataF, int slot, int symbol, int aa, - int nb_antenna_ports) + int nb_antenna_ports, + int offset) { @@ -155,14 +155,14 @@ int nr_beam_precoding(int32_t **txdataF, memset(&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size],0,sizeof(int32_t)*(frame_parms->ofdm_symbol_size)); for (p=0; pL_ssb >> (63-p)) & 0x01) { - multadd_cpx_vector((int16_t*)&txdataF[p][symbol*frame_parms->ofdm_symbol_size], + //if ((frame_parms->L_ssb >> (63-p)) & 0x01) { + multadd_cpx_vector((int16_t*)&txdataF[p][(symbol*frame_parms->ofdm_symbol_size)+offset], (int16_t*)beam_weights[p][aa], (int16_t*)&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size], 0, frame_parms->ofdm_symbol_size, 15); - } + //} } return 0; } diff --git a/openair1/PHY/MODULATION/modulation_UE.h b/openair1/PHY/MODULATION/modulation_UE.h index 228299095f..20fdaa7ad8 100644 --- a/openair1/PHY/MODULATION/modulation_UE.h +++ b/openair1/PHY/MODULATION/modulation_UE.h @@ -49,16 +49,15 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, int reset_freq_est); int nr_slot_fep(PHY_VARS_NR_UE *phy_vars_ue, - unsigned char l, - unsigned char Ns, - int sample_offset, - int no_prefix); + UE_nr_rxtx_proc_t *proc, + unsigned char l, + unsigned char Ns); int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix); + int sample_offset); int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, unsigned char l, diff --git a/openair1/PHY/MODULATION/modulation_common.h b/openair1/PHY/MODULATION/modulation_common.h index f550eeca5f..1a19bec78c 100644 --- a/openair1/PHY/MODULATION/modulation_common.h +++ b/openair1/PHY/MODULATION/modulation_common.h @@ -49,7 +49,7 @@ void PHY_ofdm_mod(int *input, void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRAME_PARMS *frame_parms); -void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms); +void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms, uint32_t slot); void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms); diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 764b02065f..c81a88ff30 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -22,6 +22,101 @@ #include "nr_modulation.h" #include "PHY/NR_REFSIG/nr_mod_table.h" +//Table 6.3.1.5-1 Precoding Matrix W 1 layer 2 antenna ports 'n' = -1 and 'o' = -j +char nr_W_1l_2p[6][2][1] = { + {{'1'}, {'0'}},//pmi 0 + {{'0'}, {'1'}}, + {{'1'}, {'1'}}, + {{'1'}, {'n'}}, + {{'1'}, {'j'}}, + {{'1'}, {'o'}}//pmi 5 +}; + +//Table 6.3.1.5-3 Precoding Matrix W 1 layer 4 antenna ports 'n' = -1 and 'o' = -j +char nr_W_1l_4p[28][4][1] = { + {{'1'}, {'0'}, {'0'}, {'0'}},//pmi 0 + {{'0'}, {'1'}, {'0'}, {'0'}}, + {{'0'}, {'0'}, {'1'}, {'0'}}, + {{'0'}, {'0'}, {'0'}, {'1'}}, + {{'1'}, {'0'}, {'1'}, {'0'}}, + {{'1'}, {'0'}, {'n'}, {'0'}}, + {{'1'}, {'0'}, {'j'}, {'0'}}, + {{'1'}, {'0'}, {'o'}, {'0'}},//pmi 7 + {{'0'}, {'1'}, {'0'}, {'1'}},//pmi 8 + {{'0'}, {'1'}, {'0'}, {'n'}}, + {{'0'}, {'1'}, {'0'}, {'j'}}, + {{'0'}, {'1'}, {'0'}, {'o'}}, + {{'1'}, {'1'}, {'1'}, {'1'}}, + {{'1'}, {'1'}, {'j'}, {'j'}}, + {{'1'}, {'1'}, {'n'}, {'n'}}, + {{'1'}, {'1'}, {'o'}, {'o'}}, + {{'1'}, {'j'}, {'1'}, {'j'}},//pmi 16 + {{'1'}, {'j'}, {'j'}, {'n'}}, + {{'1'}, {'j'}, {'n'}, {'o'}}, + {{'1'}, {'j'}, {'o'}, {'1'}}, + {{'1'}, {'n'}, {'1'}, {'n'}}, + {{'1'}, {'n'}, {'j'}, {'o'}}, + {{'1'}, {'n'}, {'n'}, {'1'}}, + {{'1'}, {'n'}, {'o'}, {'j'}},//pmi 23 + {{'1'}, {'o'}, {'1'}, {'o'}},//pmi 24 + {{'1'}, {'o'}, {'j'}, {'1'}}, + {{'1'}, {'o'}, {'n'}, {'j'}}, + {{'1'}, {'o'}, {'o'}, {'n'}}//pmi 27 +}; + +//Table 6.3.1.5-4 Precoding Matrix W 2 antenna ports layers 2 'n' = -1 and 'o' = -j +char nr_W_2l_2p[3][2][2] = { + {{'1', '0'}, {'0', '1'}},//pmi 0 + {{'1', '1'}, {'1', 'n'}}, + {{'1', '1'}, {'j', 'o'}} //pmi 2 +}; + +//Table 6.3.1.5-5 Precoding Matrix W 2 layers 4 antenna ports 'n' = -1 and 'o' = -j +char nr_W_2l_4p[22][4][2] = { + {{'1', '0'}, {'0', '1'}, {'0', '0'}, {'0', '0'}},//pmi 0 + {{'1', '0'}, {'0', '0'}, {'0', '1'}, {'0', '0'}}, + {{'1', '0'}, {'0', '0'}, {'0', '0'}, {'0', '1'}}, + {{'0', '0'}, {'1', '0'}, {'0', '1'}, {'0', '0'}},//pmi 3 + {{'0', '0'}, {'1', '0'}, {'0', '0'}, {'0', '1'}},//pmi 4 + {{'0', '0'}, {'0', '0'}, {'1', '0'}, {'0', '1'}}, + {{'1', '0'}, {'0', '1'}, {'1', '0'}, {'0', 'o'}}, + {{'1', '0'}, {'0', '1'}, {'1', '0'}, {'0', 'j'}}, + {{'1', '0'}, {'0', '1'}, {'o', '0'}, {'0', '1'}},//pmi 8 + {{'1', '0'}, {'0', '1'}, {'o', '0'}, {'0', 'n'}}, + {{'1', '0'}, {'0', '1'}, {'n', '0'}, {'0', 'o'}}, + {{'1', '0'}, {'0', '1'}, {'n', '0'}, {'0', 'j'}},//pmi 11 + {{'1', '0'}, {'0', '1'}, {'j', '0'}, {'0', '1'}},//pmi 12 + {{'1', '0'}, {'0', '1'}, {'j', '0'}, {'0', 'n'}}, + {{'1', '1'}, {'1', '1'}, {'1', 'n'}, {'1', 'n'}}, + {{'1', '1'}, {'1', '1'}, {'j', 'o'}, {'j', 'o'}},//pmi 15 + {{'1', '1'}, {'j', 'j'}, {'1', 'n'}, {'j', 'o'}},//pmi 16 + {{'1', '1'}, {'j', 'j'}, {'j', 'o'}, {'n', '1'}}, + {{'1', '1'}, {'n', 'n'}, {'1', 'n'}, {'n', '1'}}, + {{'1', '1'}, {'n', 'n'}, {'j', 'o'}, {'o', 'j'}},//pmi 19 + {{'1', '1'}, {'o', 'o'}, {'1', 'n'}, {'o', 'j'}}, + {{'1', '1'}, {'o', 'o'}, {'j', 'o'}, {'1', 'n'}}//pmi 21 +}; + +//Table 6.3.1.5-6 Precoding Matrix W 3 layers 4 antenna ports 'n' = -1 and 'o' = -j +char nr_W_3l_4p[7][4][3] = { + {{'1', '0', '0'}, {'0', '1', '0'}, {'0', '0', '1'},{'0', '0', '0'}},//pmi 0 + {{'1', '0', '0'}, {'0', '1', '0'}, {'1', '0', '0'},{'0', '0', '1'}}, + {{'1', '0', '0'}, {'0', '1', '0'}, {'n', '0', '0'},{'0', '0', '1'}}, + {{'1', '1', '1'}, {'1', 'n', '1'}, {'1', '1', 'n'},{'1', 'n', 'n'}},//pmi 3 + {{'1', '1', '1'}, {'1', 'n', '1'}, {'j', 'j', 'o'},{'j', 'o', 'o'}},//pmi 4 + {{'1', '1', '1'}, {'n', '1', 'n'}, {'1', '1', 'n'},{'n', '1', '1'}}, + {{'1', '1', '1'}, {'n', '1', 'n'}, {'j', 'j', 'o'},{'o', 'j', 'j'}} +}; + +//Table 6.3.1.5-7 Precoding Matrix W 4 layers 4 antenna ports 'n' = -1 and 'o' = -j +char nr_W_4l_4p[5][4][4] = { + {{'1', '0', '0', '0'}, {'0', '1', '0', '0'}, {'0', '0', '1', '0'}, {'0', '0', '0', '1'}},//pmi 0 + {{'1', '1', '0', '0'}, {'0', '0', '1', '1'}, {'1', 'n', '0', '0'}, {'0', '0', '1', 'n'}}, + {{'1', '1', '0', '0'}, {'0', '0', '1', '1'}, {'j', 'o', '0', '0'}, {'0', '0', 'j', 'o'}}, + {{'1', '1', '1', '1'}, {'1', 'n', '1', 'n'}, {'1', '1', 'n', 'n'}, {'1', 'n', 'n', '1'}},//pmi 3 + {{'1', '1', '1', '1'}, {'1', 'n', '1', 'n'}, {'j', 'j', 'o', 'o'}, {'j', 'o', 'o', 'j'}}//pmi 4 +}; + void nr_modulation(uint32_t *in, uint32_t length, uint16_t mod_order, @@ -37,7 +132,7 @@ void nr_modulation(uint32_t *in, uint32_t i,j; uint32_t bit_cnt; uint64_t x,x1,x2; - + #if defined(__SSE2__) __m128i *nr_mod_table128; __m128i *out128; @@ -56,7 +151,7 @@ void nr_modulation(uint32_t *in, // the bits that are left out i = i*8/2; nr_mod_table32 = (int32_t*) nr_qpsk_mod_table; - while (i>((i*2)&0x7)) & mask); out32[i] = nr_mod_table32[idx]; i++; @@ -78,7 +173,7 @@ void nr_modulation(uint32_t *in, out64[i] = nr_16qam_byte_mod_table[in_bytes[i]]; // the bits that are left out i = i*8/4; - while (i>((i*4)&0x7)) & mask); out32[i] = nr_16qam_mod_table[idx]; i++; @@ -88,7 +183,7 @@ void nr_modulation(uint32_t *in, case 6: j = 0; for (i=0; i>12)&4095; @@ -140,7 +235,7 @@ void nr_modulation(uint32_t *in, bit_cnt += 24; } return; - + case 8: nr_mod_table32 = (int32_t*) nr_256qam_mod_table; for (i=0; i>1; i++) @@ -186,8 +281,8 @@ void nr_layer_mapping(int16_t **mod_symbs, for (int l=2; l<5; l++) { tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1]; tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1]; - } - break; + } + break; case 6: for (int q=0; q<2; q++) @@ -196,7 +291,7 @@ void nr_layer_mapping(int16_t **mod_symbs, tx_layers[l][i<<1] = mod_symbs[q][(3*i+l)<<1]; tx_layers[l][(i<<1)+1] = mod_symbs[q][((3*i+l)<<1)+1]; } - break; + break; case 7: for (int i=0; id_mod; - for (int i=0; i>15; tx_layers[0][(i<<1)+1] = (mod_symbs[(i<<1)+1]*AMP)>>15; } - break; + break; case 2: case 3: case 4: mod_symbs = (int16_t *)ulsch_ue[0]->d_mod; - for (int i=0; i>15; tx_layers[l][(i<<1)+1] = (mod_symbs[((n_layers*i+l)<<1)+1]*AMP)>>15; } } - break; + break; case 5: mod_symbs = (int16_t *)ulsch_ue[0]->d_mod; @@ -271,11 +366,10 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue, tx_layers[l][i<<1] = (mod_symbs[(3*i+l)<<1]*AMP)>>15; tx_layers[l][(i<<1)+1] = (mod_symbs[((3*i+l)<<1)+1]*AMP)>>15; } - break; + break; case 6: - for (int q=0; q<2; q++){ - + for (int q=0; q<2; q++) { mod_symbs = (int16_t *)ulsch_ue[q]->d_mod; for (int i=0; i>15; } } - break; + break; case 7: mod_symbs = (int16_t *)ulsch_ue[1]->d_mod; @@ -302,11 +396,10 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue, tx_layers[l][i<<1] = (mod_symbs[((i<<2)+l)<<1]*AMP)>>15; tx_layers[l][(i<<1)+1] = (mod_symbs[(((i<<2)+l)<<1)+1]*AMP)>>15; } - break; + break; case 8: - for (int q=0; q<2; q++){ - + for (int q=0; q<2; q++) { mod_symbs = (int16_t *)ulsch_ue[q]->d_mod; for (int i=0; i>2; i++) @@ -315,20 +408,20 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue, tx_layers[l][(i<<1)+1] = (mod_symbs[(((i<<2)+l)<<1)+1]*AMP)>>15; } } - break; + break; - default: - AssertFatal(0, "Invalid number of layers %d\n", n_layers); + default: + AssertFatal(0, "Invalid number of layers %d\n", n_layers); } } void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) { -#if defined(__x86_64__) || defined(__i386__) - __m128i dft_in128[1][1200], dft_out128[1][1200]; +#if defined(__x86_64__) || +defined(__i386__) + __m128i dft_in128[1][3240], dft_out128[1][3240]; #elif defined(__arm__) - int16x8_t dft_in128[1][1200], dft_out128[1][1200]; + int16x8_t dft_in128[1][3240], dft_out128[1][3240]; #endif uint32_t *dft_in0 = (uint32_t*)dft_in128[0], *dft_out0 = (uint32_t*)dft_out128[0]; @@ -340,8 +433,10 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) int16x8_t norm128; #endif - for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { - dft_in0[ip] = d[i]; + if ((Msc_PUSCH % 1536) > 0) { + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { + dft_in0[ip] = d[i]; + } } switch (Msc_PUSCH) { @@ -480,7 +575,7 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) break; case 972: - dft(DFT_960,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_972,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 1080: @@ -494,9 +589,215 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) case 1200: dft(DFT_1200,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; + + case 1296: + dft(DFT_1296,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1440: + dft(DFT_1440,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1500: + dft(DFT_1500,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1536: + //dft(DFT_1536,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_1536,(int16_t*)d, (int16_t*)z, 1); + break; + + case 1620: + dft(DFT_1620,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1728: + dft(DFT_1728,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1800: + dft(DFT_1800,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1920: + dft(DFT_1920,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1944: + dft(DFT_1944,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2160: + dft(DFT_2160,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2304: + dft(DFT_2304,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2400: + dft(DFT_2400,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2592: + dft(DFT_2592,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2700: + dft(DFT_2700,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2880: + dft(DFT_2880,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2916: + dft(DFT_2916,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 3000: + dft(DFT_3000,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 3072: + //dft(DFT_3072,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_3072,(int16_t*)d, (int16_t*)z, 1); + break; + + case 3240: + dft(DFT_3240,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + default: + // should not be reached + LOG_E( PHY, "Unsupported Msc_PUSCH value of %"PRIu16"\n", Msc_PUSCH ); + return; + } - for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { - z[i] = dft_out0[ip]; + + if ((Msc_PUSCH % 1536) > 0) { + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) + z[i] = dft_out0[ip]; + } + +} + + +void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) { + + uint64_t dl_CarrierFreq = fp->dl_CarrierFreq; + uint64_t ul_CarrierFreq = fp->ul_CarrierFreq; + double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq}; + + const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10; + const double Tc=(1/480e3/4096); + const double Nu=2048*64*(1/(float)(1<numerology_index)); + const double Ncp0=16*64 + (144*64*(1/(float)(1<numerology_index))); + const double Ncp1=(144*64*(1/(float)(1<numerology_index))); + + for (uint8_t ll = 0; ll < 2; ll++){ + + double f0 = f[ll]; + double Ncpm1 = Ncp0; + int16_t *symbol_rotation = fp->symbol_rotation[ll]; + + double tl = 0; + double poff = 2 * M_PI * ((Ncp0 * Tc)) * f0; + double exp_re = cos(poff); + double exp_im = sin(-poff); + symbol_rotation[0] = (int16_t)floor(exp_re * 32767); + symbol_rotation[1] = (int16_t)floor(exp_im * 32767); + LOG_I(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb); + LOG_I(PHY, "Symbol rotation %d/%d => (%d,%d)\n", + 0, + nsymb, + symbol_rotation[0], + symbol_rotation[1]); + + for (int l = 1; l < nsymb; l++) { + + double Ncp; + if (l == (7 * (1 << fp->numerology_index))) { + Ncp = Ncp0; + } else { + Ncp = Ncp1; + } + + tl += (Nu + Ncpm1) * Tc; + poff = 2 * M_PI * (tl + (Ncp * Tc)) * f0; + exp_re = cos(poff); + exp_im = sin(-poff); + symbol_rotation[l<<1] = (int16_t)floor(exp_re * 32767); + symbol_rotation[1 + (l<<1)] = (int16_t)floor(exp_im * 32767); + + LOG_I(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n", + l, + nsymb, + tl, + symbol_rotation[l<<1], + symbol_rotation[1 + (l<<1)], + (poff / 2 / M_PI) - floor(poff / 2 / M_PI)); + + Ncpm1 = Ncp; + + } } } + +void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp) +{ + for (int i = 0; i < fp->ofdm_symbol_size; i++) { + double poff = -i * 2.0 * M_PI * 144.0 / 2048.0 / fp->ofdm_offset_divisor; + double exp_re = cos(poff); + double exp_im = sin(-poff); + fp->timeshift_symbol_rotation[i*2] = (int16_t)round(exp_re * 32767); + fp->timeshift_symbol_rotation[i*2+1] = (int16_t)round(exp_im * 32767); + + if (i < 10) + LOG_I(PHY,"Timeshift symbol rotation %d => (%d,%d) %f\n",i, + fp->timeshift_symbol_rotation[i*2], + fp->timeshift_symbol_rotation[i*2+1], + poff); + } +} + +int nr_layer_precoder(int16_t **datatx_F_precoding, char *prec_matrix, uint8_t n_layers, int32_t re_offset) +{ + int32_t precodatatx_F = 0; + + for (int al = 0; al>15); + ((int16_t *)precodatatx_F)[1] = (int16_t)((((int16_t *)precodatatx_F)[1]*ONE_OVER_SQRT2_Q15)>>15);*/ +} diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 706b4dc113..75541a1361 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -28,7 +28,13 @@ #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" #define DMRS_MOD_ORDER 2 - +/*Precoding matices: W[pmi][antenna_port][layer]*/ +extern char nr_W_1l_2p[6][2][1]; +extern char nr_W_2l_2p[3][2][2]; +extern char nr_W_1l_4p[28][4][1]; +extern char nr_W_2l_4p[22][4][2]; +extern char nr_W_3l_4p[7][4][3]; +extern char nr_W_4l_4p[5][4][4]; /*! \brief Perform NR modulation. TS 38.211 V15.4.0 subclause 5.1 @param[in] in, Pointer to input bits @param[in] length, size of input bits @@ -74,7 +80,6 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue, \param symbol symbol within slot (0..12/14) \param Ns Slot number (0..19) \param sample_offset offset within rxdata (points to beginning of subframe) -\param no_prefix if 1 prefix is removed by HW */ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, @@ -82,8 +87,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix); + int sample_offset); /*! \brief This function implements the dft transform precoding in PUSCH @@ -100,7 +104,35 @@ int nr_beam_precoding(int32_t **txdataF, int slot, int symbol, int aa, - int nb_antenna_ports + int nb_antenna_ports, + int offset ); +void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, + int16_t* txdata, + int slot, + int first_symbol, + int nsymb, + int length); + +void init_symbol_rotation(NR_DL_FRAME_PARMS *fp); + +void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp); + +void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, + int32_t *rxdataF, + int slot, + int first_symbol, + int nsymb, + int length); + +/*! \brief Perform NR precoding. TS 38.211 V15.4.0 subclause 6.3.1.5 + @param[in] datatx_F_precoding, Pointer to n_layers*re data array + @param[in] prec_matrix, Pointer to precoding matrix + @param[in] n_layers, number of DLSCH layers +*/ +int nr_layer_precoder(int16_t **datatx_F_precoding, + char *prec_matrix, + uint8_t n_layers, + int32_t re_offset); #endif diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index e1d21af9b9..2f075e8218 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -27,6 +27,7 @@ This section deals with basic functions for OFDM Modulation. + */ #include "PHY/defs_eNB.h" @@ -47,6 +48,7 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA PHY_ofdm_mod(txdataF, // input txdata, // output frame_parms->ofdm_symbol_size, + 1, // number of symbols frame_parms->nb_prefix_samples0, // number of prefix samples CYCLIC_PREFIX); @@ -61,20 +63,62 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA } -void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms) +void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms, uint32_t slot) { - PHY_ofdm_mod(txdataF, // input - txdata, // output - frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples0, // number of prefix samples - CYCLIC_PREFIX); - PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size, // input - txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, // output - frame_parms->ofdm_symbol_size, - nsymb - 1, - frame_parms->nb_prefix_samples, // number of prefix samples - CYCLIC_PREFIX); + // This function works only slot wise. For more generic symbol generation refer nr_feptx0() + if (frame_parms->numerology_index != 0) { // case where numerology != 0 + if (!(slot%(frame_parms->slots_per_subframe/2))) { + PHY_ofdm_mod(txdataF, + txdata, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size, + txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, + frame_parms->ofdm_symbol_size, + nsymb - 1, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } + else { + PHY_ofdm_mod(txdataF, + txdata, + frame_parms->ofdm_symbol_size, + nsymb, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } + } + else { // numerology = 0, longer CP for every 7th symbol + PHY_ofdm_mod(txdataF, + txdata, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size, + txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, + frame_parms->ofdm_symbol_size, + 6, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + PHY_ofdm_mod(txdataF + 7*frame_parms->ofdm_symbol_size, + txdata + 6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples) + + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + PHY_ofdm_mod(txdataF + 8*frame_parms->ofdm_symbol_size, + txdata + 6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples) + + 2*(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0), + frame_parms->ofdm_symbol_size, + 6, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } + } void PHY_ofdm_mod(int *input, /// pointer to complex input @@ -88,9 +132,8 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input if(nb_symbols == 0) return; - short temp[2*2*6144*4] __attribute__((aligned(32))); - unsigned short i,j; - short k; + int16_t temp[2*2*6144*4] __attribute__((aligned(32))); + int i,j; volatile int *output_ptr=(int*)0; @@ -188,18 +231,9 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input if (fftsize==128) #endif { - /*for (j=0; j=-nb_prefix_samples; k--) { - output_ptr[k] = output_ptr[--j]; - } - + memcpy((void*)&output_ptr[-nb_prefix_samples],(void*)&output_ptr[fftsize-nb_prefix_samples],nb_prefix_samples<<2); break; case CYCLIC_SUFFIX: @@ -306,60 +340,31 @@ void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t ne } -/* -// OFDM modulation for each symbol -void do_OFDM_mod_symbol(LTE_eNB_COMMON *eNB_common_vars, RU_COMMON *common, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms,int do_precoding) -{ +void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, + int16_t* trxdata, + int slot, + int first_symbol, + int nsymb, + int length) { + int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot; - int aa, l, slot_offset, slot_offsetF; - int32_t **txdataF = eNB_common_vars->txdataF; - int32_t **txdataF_BF = common->txdataF_BF; - int32_t **txdata = common->txdata; + int16_t *symbol_rotation = fp->symbol_rotation[0]; - slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); - slot_offsetF = (next_slot)*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==EXTENDED) ? 6 : 7); - //printf("Thread %d starting ... aa %d (%llu)\n",omp_get_thread_num(),aa,rdtsc()); - for (l=0; lsymbols_per_tti>>1; l++) { - - for (aa=0; aanb_antennas_tx; aa++) { + for (int sidx=0;sidxbeam_weights,next_slot,l,aa); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,0); + LOG_D(PHY,"Rotating symbol %d, slot %d, symbol_subframe_index %d, length %d (%d,%d)\n", + first_symbol + sidx, + slot, + sidx + first_symbol + symb_offset, + length, + symbol_rotation[2 * (sidx + first_symbol + symb_offset)], + symbol_rotation[1 + 2 * (sidx + first_symbol + symb_offset)]); - //PMCH case not implemented... - - if (frame_parms->Ncp == EXTENDED) - PHY_ofdm_mod((do_precoding == 1)?txdataF_BF[aa]:&txdataF[aa][slot_offsetF+l*frame_parms->ofdm_symbol_size], // input - &txdata[aa][slot_offset+l*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES], // output - frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples, // number of prefix samples - CYCLIC_PREFIX); - else { - if (l==0) { - PHY_ofdm_mod((do_precoding==1)?txdataF_BF[aa]:&txdataF[aa][slot_offsetF+l*frame_parms->ofdm_symbol_size], // input - &txdata[aa][slot_offset], // output - frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples0, // number of prefix samples - CYCLIC_PREFIX); - - } else { - PHY_ofdm_mod((do_precoding==1)?txdataF_BF[aa]:&txdataF[aa][slot_offsetF+l*frame_parms->ofdm_symbol_size], // input - &txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES], // output - frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples, // number of prefix samples - CYCLIC_PREFIX); - - //printf("txdata[%d][%d]=%d\n",aa,slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES,txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES]); - - } - } - } + rotate_cpx_vector(trxdata + (sidx * length * 2), + &symbol_rotation[2 * (sidx + first_symbol + symb_offset)], + trxdata + (sidx * length * 2), + length, + 15); } - } -*/ + diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index cf0a50a018..eb26dfc02b 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -29,361 +29,253 @@ //#define DEBUG_FEP -#define SOFFSET 0 - /*#ifdef LOG_I #undef LOG_I #define LOG_I(A,B...) printf(A) #endif*/ -int nr_slot_fep(PHY_VARS_NR_UE *ue, - unsigned char symbol, - unsigned char Ns, - int sample_offset, - int no_prefix) +dft_size_idx_t get_dft_size_idx(uint16_t ofdm_symbol_size) { - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - NR_UE_COMMON *common_vars = &ue->common_vars; - unsigned char aa; - unsigned int nb_prefix_samples; - unsigned int nb_prefix_samples0; - unsigned int abs_symbol; - if (ue->is_synchronized) { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); - } - else { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - } - //unsigned int subframe_offset;//,subframe_offset_F; - unsigned int slot_offset; - //int i; - unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10; - unsigned int rx_offset; - - - dft_size_idx_t dftsize; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs - - switch (frame_parms->ofdm_symbol_size) { + switch (ofdm_symbol_size) { case 128: - dftsize = DFT_128; - break; + return DFT_128; case 256: - dftsize = DFT_256; - break; + return DFT_256; case 512: - dftsize = DFT_512; - break; + return DFT_512; case 1024: - dftsize = DFT_1024; - break; + return DFT_1024; case 1536: - dftsize = DFT_1536; - break; + return DFT_1536; case 2048: - dftsize = DFT_2048; - break; + return DFT_2048; case 3072: - dftsize = DFT_3072; - break; + return DFT_3072; case 4096: - dftsize = DFT_4096; - break; + return DFT_4096; + + case 6144: + return DFT_6144; case 8192: - dftsize = DFT_8192; - break; + return DFT_8192; default: printf("unsupported ofdm symbol size \n"); assert(0); } - if (no_prefix) { - slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns); + return DFT_SIZE_IDXTABLESIZE; +} + +int nr_slot_fep(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + unsigned char symbol, + unsigned char Ns) +{ + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + NR_UE_COMMON *common_vars = &ue->common_vars; + + AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); + AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1); + + unsigned int nb_prefix_samples; + unsigned int nb_prefix_samples0; + if (ue->is_synchronized) { + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples0; } else { - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples; } - /*if (l<0 || l>=7-frame_parms->Ncp) { - printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); - return(-1); - }*/ + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); - if (Ns<0 || Ns>(frame_parms->slots_per_frame-1)) { - printf("slot_fep: Ns must be between 0 and %d\n",frame_parms->slots_per_frame-1); - return(-1); - } + unsigned int rx_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; + for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) + rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rx_offset += frame_parms->ofdm_symbol_size * symbol; - for (aa=0; aanb_antennas_rx; aa++) { - memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); + // use OFDM symbol from within 1/8th of the CP to avoid ISI + rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor); - rx_offset = sample_offset + slot_offset - SOFFSET; - // Align with 256 bit - // rx_offset = rx_offset&0xfffffff8; +//#ifdef DEBUG_FEP + // if (ue->frame <100) + LOG_D(PHY,"slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n", + Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset, dB_fixed(signal_energy(&common_vars->rxdata[0][rx_offset],frame_parms->ofdm_symbol_size))); + //#endif -#ifdef DEBUG_FEP - // if (ue->frame <100) - /*LOG_I(PHY,*/printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", - ue->proc.proc_rxtx[(Ns)&1].frame_rx, Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); -#endif + for (unsigned char aa=0; aanb_antennas_rx; aa++) { + memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t)); - abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; - - for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb < abs_symbol; idx_symb++) - rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; - - rx_offset += frame_parms->ofdm_symbol_size * symbol; - - if (abs_symbol%(0x7<numerology_index)) { - - rx_offset += nb_prefix_samples; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short*) &common_vars->rxdata[aa][frame_length_samples], - (short*) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); - - if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset % frame_length_samples], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif - } - } else { - - rx_offset += nb_prefix_samples0; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((void *) &common_vars->rxdata[aa][frame_length_samples], - (void *) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly - - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif + int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset]; + // if input to dft is not 256-bit aligned + if ((rx_offset & 7) != 0) { + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + frame_parms->ofdm_symbol_size * sizeof(int32_t)); + rxdata_ptr = (int16_t *)tmp_dft_in; } - #ifdef DEBUG_FEP - // if (ue->frame <100) - printf("slot_fep: frame %d: symbol %d rx_offset %u\n", ue->proc.proc_rxtx[(Ns)&1].frame_rx, symbol, rx_offset); - #endif - } + start_meas(&ue->rx_dft_stats); + dft(dftsize, + rxdata_ptr, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + 1); + + stop_meas(&ue->rx_dft_stats); + + int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol+symb_offset]; + ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + +#ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset, + symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); +#endif + + rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + (int16_t*)&rot2, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + frame_parms->ofdm_symbol_size, + 15); + + int16_t *shift_rot = frame_parms->timeshift_symbol_rotation; + + multadd_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + shift_rot, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + 1, + frame_parms->ofdm_symbol_size, + 15); + } #ifdef DEBUG_FEP printf("slot_fep: done\n"); #endif - return(0); + + return 0; } int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix) + int sample_offset) { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; NR_UE_COMMON *common_vars = &ue->common_vars; - unsigned char aa; + + AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); + AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1); + unsigned int nb_prefix_samples; unsigned int nb_prefix_samples0; - unsigned int abs_symbol; if (ue->is_synchronized) { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples0; } else { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples); + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples; } - //unsigned int subframe_offset;//,subframe_offset_F; - unsigned int slot_offset; - //int i; - unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10; - unsigned int rx_offset; + unsigned int frame_length_samples = frame_parms->samples_per_frame; + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); - dft_size_idx_t dftsize; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs - - switch (frame_parms->ofdm_symbol_size) { - case 128: - dftsize = DFT_128; - break; - - case 256: - dftsize = DFT_256; - break; - - case 512: - dftsize = DFT_512; - break; - - case 1024: - dftsize = DFT_1024; - break; - - case 1536: - dftsize = DFT_1536; - break; - - case 2048: - dftsize = DFT_2048; - break; - - case 3072: - dftsize = DFT_3072; - break; - - case 4096: - dftsize = DFT_4096; - break; - - case 8192: - dftsize = DFT_8192; - break; - - default: - printf("unsupported ofdm symbol size \n"); - assert(0); - } - - if (no_prefix) { - slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns); - } else { - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - } - - /*if (l<0 || l>=7-frame_parms->Ncp) { - printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); - return(-1); - }*/ - - if (Ns<0 || Ns>(frame_parms->slots_per_frame-1)) { - printf("slot_fep: Ns must be between 0 and %d\n",frame_parms->slots_per_frame-1); - return(-1); - } - - for (aa=0; aanb_antennas_rx; aa++) { - memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); - - rx_offset = sample_offset + slot_offset - SOFFSET; - // Align with 256 bit - // rx_offset = rx_offset&0xfffffff8; + unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + unsigned int rx_offset = sample_offset + slot_offset; + unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; + for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) + rx_offset += (abs_symbol%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rx_offset += frame_parms->ofdm_symbol_size * symbol; #ifdef DEBUG_FEP - // if (ue->frame <100) - /*LOG_I(PHY,*/printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", - ue->proc.proc_rxtx[(Ns)&1].frame_rx, Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", + Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); #endif - abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; - - for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb < abs_symbol; idx_symb++) - rx_offset += (abs_symbol%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + for (unsigned char aa=0; aanb_antennas_rx; aa++) { + memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t)); - rx_offset += frame_parms->ofdm_symbol_size * symbol; + int16_t *rxdata_ptr; + rx_offset%=frame_length_samples*2; - if (abs_symbol%(0x7<numerology_index)) { + if (rx_offset+frame_parms->ofdm_symbol_size > frame_length_samples*2 ) { + // rxdata is 2 frames len + // we have to wrap on the end - rx_offset += nb_prefix_samples; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short*) &common_vars->rxdata[aa][frame_length_samples], - (short*) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + (frame_length_samples*2 - rx_offset) * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[frame_length_samples*2 - rx_offset], + (void *)&common_vars->rxdata[aa][0], + (frame_parms->ofdm_symbol_size - (frame_length_samples*2 - rx_offset)) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)tmp_dft_in; - if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif + } else if ((rx_offset & 7) != 0) { + // if input to dft is not 256-bit aligned + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + frame_parms->ofdm_symbol_size * sizeof(int32_t)); + rxdata_ptr = (int16_t *)tmp_dft_in; - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][rx_offset], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif - } } else { - rx_offset += nb_prefix_samples0; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((void *) &common_vars->rxdata[aa][frame_length_samples], - (void *) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][rx_offset], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif - + // use dft input from RX buffer directly + rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset]; } - #ifdef DEBUG_FEP - // if (ue->frame <100) - printf("slot_fep: frame %d: symbol %d rx_offset %u\n", ue->proc.proc_rxtx[(Ns)&1].frame_rx, symbol, rx_offset); - #endif - } + start_meas(&ue->rx_dft_stats); + dft(dftsize, + rxdata_ptr, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + 1); + + stop_meas(&ue->rx_dft_stats); + + int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset]; + ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + +#ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset, + symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); +#endif + + rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + (int16_t*)&rot2, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + frame_parms->ofdm_symbol_size, + 15); + } #ifdef DEBUG_FEP printf("slot_fep: done\n"); #endif - return(0); + + return 0; } @@ -392,81 +284,89 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix) + int sample_offset) { - int32_t slot_offset, rxdata_offset; - - unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); + unsigned int nb_prefix_samples = frame_parms->nb_prefix_samples; + unsigned int nb_prefix_samples0 = frame_parms->nb_prefix_samples0; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); - dft_size_idx_t dftsize; + // offset of first OFDM symbol + unsigned int rxdata_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; + for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) + rxdata_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rxdata_offset += frame_parms->ofdm_symbol_size * symbol; - switch (frame_parms->ofdm_symbol_size) { - case 128: - dftsize = DFT_128; - break; + // use OFDM symbol from within 1/8th of the CP to avoid ISI + rxdata_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor); - case 256: - dftsize = DFT_256; - break; + int16_t *rxdata_ptr; - case 512: - dftsize = DFT_512; - break; + if(sample_offset > rxdata_offset) { - case 1024: - dftsize = DFT_1024; - break; + memcpy((void *)&tmp_dft_in[0], + (void *)&rxdata[frame_parms->samples_per_frame - sample_offset + rxdata_offset], + (sample_offset - rxdata_offset) * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[sample_offset - rxdata_offset], + (void *)&rxdata[0], + (frame_parms->ofdm_symbol_size - sample_offset + rxdata_offset) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)tmp_dft_in; - case 1536: - dftsize = DFT_1536; - break; + } else if (((rxdata_offset - sample_offset) & 7) != 0) { - case 2048: - dftsize = DFT_2048; - break; + // if input to dft is not 256-bit aligned + memcpy((void *)&tmp_dft_in[0], + (void *)&rxdata[rxdata_offset - sample_offset], + (frame_parms->ofdm_symbol_size) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)tmp_dft_in; - case 4096: - dftsize = DFT_4096; - break; + } else { - case 8192: - dftsize = DFT_8192; - break; + // use dft input from RX buffer directly + rxdata_ptr = (int16_t *)&rxdata[rxdata_offset - sample_offset]; - default: - dftsize = DFT_512; - break; } - - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - if(symbol == 0) - rxdata_offset = slot_offset + nb_prefix_samples0 - SOFFSET; - else - rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET; + dft(dftsize, + rxdata_ptr, + (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], + 1); - if(sample_offset>rxdata_offset) { - memcpy((void *)tmp_dft_in, - (void *) &rxdata[frame_parms->samples_per_frame-sample_offset+rxdata_offset], - (sample_offset-rxdata_offset)*sizeof(int)); + return 0; +} - memcpy((void *)&tmp_dft_in[sample_offset-rxdata_offset], - (void *) &rxdata[0], - (frame_parms->ofdm_symbol_size-sample_offset+rxdata_offset)*sizeof(int)); +void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, + int32_t *rxdataF, + int slot, + int first_symbol, + int nsymb, + int length) { - dft(dftsize,(int16_t *)&tmp_dft_in, - (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - } - else - dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset], - (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); + + int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + + for (int symbol=first_symbol;symbolsymbol_rotation[1])[symbol + symb_offset]; + ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); + rotate_cpx_vector((int16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], + (int16_t*)&rot2, + (int16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], + length, + 15); - // clear DC carrier from OFDM symbols - rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0; + int16_t *shift_rot = frame_parms->timeshift_symbol_rotation; - return(0); + multadd_cpx_vector((int16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], + shift_rot, + (int16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], + 1, + length, + 15); + } } diff --git a/openair1/PHY/MODULATION/slot_fep_ul.c b/openair1/PHY/MODULATION/slot_fep_ul.c index 746f8dbc0e..ccb7ee5f3e 100644 --- a/openair1/PHY/MODULATION/slot_fep_ul.c +++ b/openair1/PHY/MODULATION/slot_fep_ul.c @@ -20,8 +20,8 @@ */ #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" -#include "modulation_eNB.h" +//#include "PHY/phy_extern.h" +//#include "modulation_eNB.h" //#define DEBUG_FEP diff --git a/openair1/PHY/MODULATION/ul_7_5_kHz.c b/openair1/PHY/MODULATION/ul_7_5_kHz.c index a5b428a813..384b9d621c 100644 --- a/openair1/PHY/MODULATION/ul_7_5_kHz.c +++ b/openair1/PHY/MODULATION/ul_7_5_kHz.c @@ -20,7 +20,6 @@ */ #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" #include #include "PHY/sse_intrin.h" #include "modulation_extern.h" diff --git a/openair1/PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c deleted file mode 100644 index 9c4d1fcc93..0000000000 --- a/openair1/PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c -* \brief TA estimation for TA updates -* \author Ahmed Hussein -* \date 2019 -* \version 0.1 -* \company Fraunhofer IIS -* \email: ahmed.hussein@iis.fraunhofer.de -* \note -* \warning -*/ - -#include "PHY/types.h" -#include "PHY/defs_gNB.h" -#include "PHY/phy_extern.h" -#include "nr_ul_estimation.h" - -int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) -{ - int temp, i, aa, max_pos = 0, max_val = 0; - short Re, Im; - uint8_t cyclic_shift = 0; - - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; - int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; - - int sync_pos = (frame_parms->ofdm_symbol_size - cyclic_shift*frame_parms->ofdm_symbol_size/12) % (frame_parms->ofdm_symbol_size); - - for (i = 0; i < frame_parms->ofdm_symbol_size; i++) { - temp = 0; - - for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; - Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; - temp += (Re*Re/2) + (Im*Im/2); - } - - if (temp > max_val) { - max_pos = i; - max_val = temp; - } - } - - if (max_pos > frame_parms->ofdm_symbol_size/2) - max_pos = max_pos - frame_parms->ofdm_symbol_size; - - - return max_pos - sync_pos; -} - diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c new file mode 100644 index 0000000000..cfb5a2e56e --- /dev/null +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -0,0 +1,228 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/NR_ESTIMATION/nr_measurements_gNB.c +* \brief gNB measurement routines +* \author Ahmed Hussein, G. Casati, K. Saaifan +* \date 2019 +* \version 0.1 +* \company Fraunhofer IIS +* \email: ahmed.hussein@iis.fraunhofer.de, guido.casati@iis.fraunhofer.de, khodr.saaifan@iis.fraunhofer.de +* \note +* \warning +*/ + +#include "PHY/types.h" +#include "PHY/defs_gNB.h" +#include "PHY/phy_extern.h" +#include "nr_ul_estimation.h" + +extern openair0_config_t openair0_cfg[MAX_CARDS]; + +int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) +{ + int max_pos = 0, max_val = 0; + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; + int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; + + const int sync_pos = 0; + + for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { + int temp = 0; + + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + int Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; + int Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; + temp += (Re*Re/2) + (Im*Im/2); + } + if (temp > max_val) { + max_pos = i; + max_val = temp; + } + } + + if (max_pos > frame_parms->ofdm_symbol_size/2) + max_pos = max_pos - frame_parms->ofdm_symbol_size; + + return max_pos - sync_pos; +} + + +void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) { + + + int min_I0=1000,max_I0=0; + int amin=0,amax=0; + fprintf(fd,"Blacklisted PRBs %d/%d\n",gNB->num_ulprbbl,gNB->frame_parms.N_RB_UL); + for (int i=0; iframe_parms.N_RB_UL; i++) { + if (gNB->ulprbbl[i] > 0) continue; + + if (gNB->measurements.n0_subband_power_tot_dB[i]measurements.n0_subband_power_tot_dB[i]; amin=i;} + + if (gNB->measurements.n0_subband_power_tot_dB[i]>max_I0) {max_I0 = gNB->measurements.n0_subband_power_tot_dB[i]; amax=i;} + } + + for (int i=0; iframe_parms.N_RB_UL; i++) { + if (gNB->ulprbbl[i] ==0) fprintf(fd,"%2d.",gNB->measurements.n0_subband_power_tot_dB[i]-gNB->measurements.n0_subband_power_avg_dB); + else fprintf(fd," X."); + if (i%25 == 24) fprintf(fd,"\n"); + } + fprintf(fd,"\n"); + fprintf(fd,"max_IO = %d (%d), min_I0 = %d (%d), avg_I0 = %d dB",max_I0,amax,min_I0,amin,gNB->measurements.n0_subband_power_avg_dB); + if (gNB->frame_parms.nb_antennas_rx>1) { + fprintf(fd,"("); + for (int aarx=0;aarxframe_parms.nb_antennas_rx;aarx++) + fprintf(fd,"%d.",gNB->measurements.n0_subband_power_avg_perANT_dB[aarx]); + fprintf(fd,")"); + } + fprintf(fd,"\nPRACH I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10); + + +} + + + +void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot, int first_symb,int num_symb) { + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + NR_gNB_COMMON *common_vars = &gNB->common_vars; + PHY_MEASUREMENTS_gNB *measurements = &gNB->measurements; + int rb, offset, offset0, nb_symb[275], len; + int32_t *ul_ch; + + LOG_D(PHY,"slot %d Doing I0 for first_symb %d, num_symb %d\n",slot,first_symb,num_symb); + for (int s=first_symb;s<(first_symb+num_symb);s++) { + for (rb=0; rbN_RB_UL; rb++) { + + if (s==first_symb) { + nb_symb[rb]=0; + for (int aarx=0; aarxnb_antennas_rx;aarx++) + measurements->n0_subband_power[aarx][rb]=0; + } + offset0 = (slot&3)*(frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size) + (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; + if ((gNB->rb_mask_ul[s][rb>>5]&(1<<(rb&31))) == 0) { // check that rb was not used in this subframe + nb_symb[rb]++; + for (int aarx=0; aarxnb_antennas_rx; aarx++) { + offset = offset0 + (s*frame_parms->ofdm_symbol_size); + ul_ch = &common_vars->rxdataF[aarx][offset]; + len = 12; + if (((frame_parms->N_RB_UL&1) == 1) && + (rb==(frame_parms->N_RB_UL>>1))) { + len=6; + } + AssertFatal(ul_ch, "RX signal buffer (freq) problem\n"); + measurements->n0_subband_power[aarx][rb] += signal_energy_nodc(ul_ch,len); + } //antenna + } + } //rb + } // symb + int nb_rb=0; + int32_t n0_subband_tot=0; + int32_t n0_subband_tot_perPRB=0; + int32_t n0_subband_tot_perANT[1+frame_parms->nb_antennas_rx]; + + for (int rb = 0 ; rbN_RB_UL;rb++) { + n0_subband_tot_perPRB=0; + if (nb_symb[rb] > 0) { + for (int aarx=0;aarxnb_antennas_rx;aarx++) { + measurements->n0_subband_power[aarx][rb]/=nb_symb[rb]; + measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(measurements->n0_subband_power[aarx][rb]); + n0_subband_tot_perPRB+=measurements->n0_subband_power[aarx][rb]; + if (rb==0) n0_subband_tot_perANT[aarx]=measurements->n0_subband_power[aarx][rb]; + else n0_subband_tot_perANT[aarx]+=measurements->n0_subband_power[aarx][rb]; + } + n0_subband_tot_perPRB/=frame_parms->nb_antennas_rx; + measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_subband_tot_perPRB); + measurements->n0_subband_power_tot_dBm[rb] = measurements->n0_subband_power_tot_dB[rb] - gNB->rx_total_gain_dB - dB_fixed(frame_parms->N_RB_UL); + LOG_D(PHY,"n0_subband_power_tot_dB[%d] => %d, over %d symbols\n",rb,measurements->n0_subband_power_tot_dB[rb],nb_symb[rb]); + n0_subband_tot += n0_subband_tot_perPRB; + nb_rb++; + } + } + if (nb_rb>0) { + measurements->n0_subband_power_avg_dB = dB_fixed(n0_subband_tot/nb_rb); + for (int aarx=0;aarxnb_antennas_rx;aarx++) { + measurements->n0_subband_power_avg_perANT_dB[aarx] = dB_fixed(n0_subband_tot_perANT[aarx]/nb_rb); + } + } +} + + +// Scope: This function computes the UL SNR from the UL channel estimates +// +// Todo: +// - averaging IIR filter for RX power and noise +void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol, uint8_t nrOfLayers){ + + int rx_power_tot[NUMBER_OF_NR_ULSCH_MAX]; + int rx_power[NUMBER_OF_NR_ULSCH_MAX][NB_ANTENNAS_RX]; + unsigned short rx_power_avg_dB[NUMBER_OF_NR_ULSCH_MAX]; + unsigned short rx_power_tot_dB[NUMBER_OF_NR_ULSCH_MAX]; + + double rx_gain = openair0_cfg[0].rx_gain[0]; + double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0]; + PHY_MEASUREMENTS_gNB *meas = &gNB->measurements; + NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + int ch_offset = fp->ofdm_symbol_size * symbol; + int N_RB_UL = gNB->ulsch[ulsch_id][0]->harq_processes[harq_pid]->ulsch_pdu.rb_size; + + rx_power_tot[ulsch_id] = 0; + + for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++){ + + rx_power[ulsch_id][aarx] = 0; + + for (int aatx = 0; aatx < nrOfLayers; aatx++){ + + meas->rx_spatial_power[ulsch_id][aatx][aarx] = (signal_energy_nodc(&gNB->pusch_vars[ulsch_id]->ul_ch_estimates[aatx*fp->nb_antennas_rx+aarx][ch_offset], N_RB_UL * NR_NB_SC_PER_RB)); + + if (meas->rx_spatial_power[ulsch_id][aatx][aarx] < 0) { + meas->rx_spatial_power[ulsch_id][aatx][aarx] = 0; + } + + meas->rx_spatial_power_dB[ulsch_id][aatx][aarx] = (unsigned short) dB_fixed(meas->rx_spatial_power[ulsch_id][aatx][aarx]); + rx_power[ulsch_id][aarx] += meas->rx_spatial_power[ulsch_id][aatx][aarx]; + + } + LOG_D(PHY, "[ULSCH ID %d] RX power in antenna %d = %d\n", ulsch_id, aarx, rx_power[ulsch_id][aarx]); + + rx_power_tot[ulsch_id] += rx_power[ulsch_id][aarx]; + + } + + rx_power_tot_dB[ulsch_id] = (unsigned short) dB_fixed(rx_power_tot[ulsch_id]); + rx_power_avg_dB[ulsch_id] = rx_power_tot_dB[ulsch_id]; + + meas->wideband_cqi_tot[ulsch_id] = dB_fixed2(rx_power_tot[ulsch_id], meas->n0_power_tot); + meas->rx_rssi_dBm[ulsch_id] = rx_power_avg_dB[ulsch_id] + 30 - 10 * log10(pow(2, 30)) - (rx_gain - rx_gain_offset) - dB_fixed(fp->ofdm_symbol_size); + + LOG_D(PHY, "[ULSCH %d] RSSI %d dBm/RE, RSSI (digital) %d dB (N_RB_UL %d), WBand CQI tot %d dB, N0 Power tot %d, RX Power tot %d\n", + ulsch_id, + meas->rx_rssi_dBm[ulsch_id], + rx_power_avg_dB[ulsch_id], + N_RB_UL, + meas->wideband_cqi_tot[ulsch_id], + meas->n0_power_tot, + rx_power_tot[ulsch_id]); + +} diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 3f7c7817f7..1f164748bf 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -25,15 +25,26 @@ #include "nr_ul_estimation.h" #include "PHY/sse_intrin.h" #include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/NR_REFSIG/dmrs_nr.h" +#include "PHY/NR_REFSIG/ptrs_nr.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_ESTIMATION/filt16a_32.h" +#include "PHY/NR_REFSIG/ul_ref_seq_nr.h" +#include "executables/softmodem-common.h" + + //#define DEBUG_CH //#define DEBUG_PUSCH +#define NO_INTERP 1 +#define dBc(x,y) (dB_fixed(((int32_t)(x))*(x) + ((int32_t)(y))*(y))) + int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned char Ns, unsigned short p, unsigned char symbol, + int ul_id, unsigned short bwp_start_subcarrier, nfapi_nr_pusch_pdu_t *pusch_pdu) { @@ -43,8 +54,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned int pilot_cnt,re_cnt; int16_t ch[2],ch_r[2],ch_l[2],*pil,*rxF,*ul_ch; int16_t *fl,*fm,*fr,*fml,*fmr,*fmm,*fdcl,*fdcr,*fdclh,*fdcrh; - int ch_offset,symbol_offset, UE_id = 0; - int32_t **ul_ch_estimates_time = gNB->pusch_vars[UE_id]->ul_ch_estimates_time; + int ch_offset,symbol_offset ; + int32_t **ul_ch_estimates_time = gNB->pusch_vars[ul_id]->ul_ch_estimates_time; __m128i *ul_ch_128; #ifdef DEBUG_CH @@ -55,9 +66,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1]; uint8_t nushift; - int **ul_ch_estimates = gNB->pusch_vars[UE_id]->ul_ch_estimates; + int **ul_ch_estimates = gNB->pusch_vars[ul_id]->ul_ch_estimates; int **rxdataF = gNB->common_vars.rxdataF; - + int soffset = (Ns&3)*gNB->frame_parms.symbols_per_slot*gNB->frame_parms.ofdm_symbol_size; nushift = (p>>1)&1; gNB->frame_parms.nushift = nushift; @@ -66,16 +77,19 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, symbol_offset = gNB->frame_parms.ofdm_symbol_size*symbol; k = bwp_start_subcarrier; - int re_offset = k; + int re_offset; uint16_t nb_rb_pusch = pusch_pdu->rb_size; -/* -#ifdef DEBUG_CH - printf("PUSCH Channel Estimation : ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n", ,ch_offset,symbol_offset,gNB->frame_parms.ofdm_symbol_size, - gNB->frame_parms.Ncp,l,Ns,k, symbol); -#endif -*/ + LOG_D(PHY, "In %s: ch_offset %d, soffset %d, symbol_offset %d OFDM size %d, Ns = %d, k = %d symbol %d\n", + __FUNCTION__, + ch_offset, soffset, + symbol_offset, + gNB->frame_parms.ofdm_symbol_size, + Ns, + k, + symbol); + switch (nushift) { case 0: fl = filt8_l0; @@ -113,52 +127,94 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, break; } - //------------------generate DMRS------------------// - if (pusch_pdu->transform_precoding==1) // if transform precoding is disabled - nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, pusch_pdu->rb_start*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); - else - nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, 0, pusch_pdu->dmrs_config_type); + // transform precoding = 1 means disabled + if (pusch_pdu->transform_precoding == 1) { + nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, + (pusch_pdu->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); + } + else { // if transform precoding or SC-FDMA is enabled in Uplink + // NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible + uint16_t index = get_index_for_dmrs_lowpapr_seq(nb_rb_pusch * (NR_NB_SC_PER_RB/2)); + uint8_t u = pusch_pdu->dfts_ofdm.low_papr_group_number; + uint8_t v = pusch_pdu->dfts_ofdm.low_papr_sequence_number; + int16_t *dmrs_seq = gNB_dmrs_lowpaprtype1_sequence[u][v][index]; + + AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n"); + AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated"); + + LOG_D(PHY,"Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index); + + nr_pusch_lowpaprtype1_dmrs_rx(gNB, Ns, dmrs_seq, &pilot[0], 1000, 0, nb_rb_pusch, 0, pusch_pdu->dmrs_config_type); + + #ifdef DEBUG_PUSCH + printf ("NR_UL_CHANNEL_EST: index %d, u %d,v %d\n", index, u, v); + LOG_M("gNb_DMRS_SEQ.m","gNb_DMRS_SEQ", dmrs_seq,6*nb_rb_pusch,1,1); + #endif + + } //------------------------------------------------// + +#ifdef DEBUG_PUSCH + for (int i = 0; i < (6 * nb_rb_pusch); i++) { + LOG_I(PHY, "In %s: %d + j*(%d)\n", + __FUNCTION__, + ((int16_t*)pilot)[2 * i], + ((int16_t*)pilot)[1 + (2 * i)]); + } +#endif + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { + re_offset = k; /* Initializing the Resource element offset for each Rx antenna */ + pil = (int16_t *)&pilot[0]; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+nushift)]; - ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset]; + rxF = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+k+nushift)]; + ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; + re_offset = k; memset(ul_ch,0,4*(gNB->frame_parms.ofdm_symbol_size)); #ifdef DEBUG_PUSCH - printf("symbol_offset %d, nushift %d\n",symbol_offset,nushift); - printf("ch est pilot addr %p RB_DL %d\n",&pilot[0], gNB->frame_parms.N_RB_UL); - printf("bwp_start_subcarrier %d, k %d, first_carrier %d\n",bwp_start_subcarrier,k,gNB->frame_parms.first_carrier_offset); - printf("rxF addr %p p %d\n", rxF,p); - printf("ul_ch addr %p nushift %d\n",ul_ch,nushift); + LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift); + LOG_I(PHY, "In %s ch est pilot addr %p, N_RB_UL %d\n", __FUNCTION__, &pilot[0], gNB->frame_parms.N_RB_UL); + LOG_I(PHY, "In %s bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k, gNB->frame_parms.first_carrier_offset, nb_rb_pusch); + LOG_I(PHY, "In %s rxF addr %p p %d\n", __FUNCTION__, rxF, p); + LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift); #endif //if ((gNB->frame_parms.N_RB_UL&1)==0) { - if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1){ - + if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && gNB->prb_interpolation == 0){ + LOG_D(PHY,"PUSCH estimation DMRS type 1, Freq-domain interpolation"); // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); - printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); - printf("data 0 : rxF - > (%d,%d)\n",rxF[2],rxF[3]); + LOG_I(PHY, "In %s ch 0 %d\n", __FUNCTION__, ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); + LOG_I(PHY, "In %s pilot 0 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 0 : rxF - > (%d,%d) (%d)\n", __FUNCTION__, rxF[2], rxF[3], dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fl, ch, ul_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)]; //for (int i= 0; i<8; i++) //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i)); @@ -166,25 +222,53 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - printf("data 1 : rxF - > (%d,%d)\n",rxF[2],rxF[3]); + LOG_I(PHY, "In %s pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 1 : rxF - > (%d,%d) (%d)\n", + __FUNCTION__, + rxF[2], + rxF[3], + dBc(rxF[2],rxF[3])); #endif + multadd_real_vector_complex_scalar(fml, ch, ul_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)]; //printf("ul_ch addr %p\n",ul_ch); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - printf("data 2 : rxF - > (%d,%d)\n",rxF[2],rxF[3]); + LOG_I(PHY, "In %s pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 2 : rxF - > (%d,%d) (%d)\n", + __FUNCTION__, + rxF[2], + rxF[3], + dBc(rxF[2],rxF[3])); #endif + multadd_real_vector_complex_scalar(fmm, ch, ul_ch, @@ -193,35 +277,35 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //for (int i= 0; i<16; i++) //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)]; ul_ch+=8; - for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pusch-3); pilot_cnt+=2) { + for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pusch-3); pilot_cnt += 2) { ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt,rxF[2],rxF[3]); + printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fml, ch, ul_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)]; //printf("ul_ch addr %p\n",ul_ch); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt+1,rxF[2],rxF[3]); + printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+1,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fmm, ch, @@ -231,19 +315,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //for (int i= 0; i<16; i++) //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)]; ul_ch+=8; - } // Treat first 2 pilots specially (right edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt,rxF[2],rxF[3]); + printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fm, ch, @@ -253,32 +336,32 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //for (int i= 0; i<8; i++) //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)]; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); - printf("pilot %u: rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt+1,rxF[2],rxF[3]); + printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+1,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fmr, ch, ul_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)]; ul_ch+=8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot %u: rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt+2,rxF[2],rxF[3]); + printf("pilot %u: rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+2,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fr, ch, @@ -288,7 +371,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, // check if PRB crosses DC and improve estimates around DC if ((bwp_start_subcarrier < gNB->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pusch*12 >= gNB->frame_parms.ofdm_symbol_size)) { - ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset]; + ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; uint16_t idxDC = 2*(gNB->frame_parms.ofdm_symbol_size - bwp_start_subcarrier); uint16_t idxPil = idxDC/2; re_offset = k; @@ -297,7 +380,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch += (idxDC-4); ul_ch = memset(ul_ch, 0, sizeof(int16_t)*10); re_offset = (re_offset+idxDC/2-2) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)]; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -328,7 +411,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, pil += 4; re_offset = (re_offset+4) % gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)]; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -338,33 +421,33 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, 8); } } -#ifdef DEBUG_PDSCH - ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset]; +#ifdef DEBUG_PUSCH + ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; for(uint16_t idxP=0; idxPdmrs_config_type == pusch_dmrs_type2 && gNB->prb_interpolation == 0) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| + LOG_D(PHY,"PUSCH estimation DMRS type 2, Freq-domain interpolation"); // Treat first DMRS specially (left edge) - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)]; ul_ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ul_ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - ul_ch+=2; + pil += 2; + ul_ch += 2; re_offset = (re_offset + 1)%gNB->frame_parms.ofdm_symbol_size; ch_offset++; - for (re_cnt = 1; re_cnt < (nb_rb_pusch*NR_NB_SC_PER_RB) - 5; re_cnt+=6){ + for (re_cnt = 1; re_cnt < (nb_rb_pusch*NR_NB_SC_PER_RB) - 5; re_cnt += 6){ - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)]; ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch_l[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -372,8 +455,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch[0] = ch_l[0]; ul_ch[1] = ch_l[1]; - pil+=2; - ul_ch+=2; + pil += 2; + ul_ch += 2; ch_offset++; multadd_real_four_symbols_vector_complex_scalar(filt8_ml2, @@ -382,7 +465,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, re_offset = (re_offset+5)%gNB->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+symbol_offset+nushift+re_offset]; ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch_r[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -392,17 +475,17 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch_r, ul_ch); - //for (int re_idx = 0; re_idx < 8; re_idx+=2) + //for (int re_idx = 0; re_idx < 8; re_idx += 2) //printf("ul_ch = %d + j*%d\n", ul_ch[re_idx], ul_ch[re_idx+1]); - ul_ch+=8; - ch_offset+=4; + ul_ch += 8; + ch_offset += 4; ul_ch[0] = ch_r[0]; ul_ch[1] = ch_r[1]; - pil+=2; - ul_ch+=2; + pil += 2; + ul_ch += 2; ch_offset++; re_offset = (re_offset + 1)%gNB->frame_parms.ofdm_symbol_size; @@ -410,7 +493,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, // Treat last pilot specially (right edge) - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)]; ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch_l[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -418,7 +501,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch[0] = ch_l[0]; ul_ch[1] = ch_l[1]; - ul_ch+=2; + ul_ch += 2; ch_offset++; multadd_real_four_symbols_vector_complex_scalar(filt8_rr1, @@ -429,11 +512,390 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch_r, ul_ch); - ul_ch_128 = (__m128i *)&ul_ch_estimates[aarx][ch_offset]; + ul_ch_128 = (__m128i *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; ul_ch_128[0] = _mm_slli_epi16 (ul_ch_128[0], 2); } + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + LOG_D(PHY,"PUSCH estimation DMRS type 1, no Freq-domain interpolation"); + int32_t ch_0, ch_1; + // First PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + + + +#if NO_INTERP + for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; + ul_ch+=24; +#else + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + ul_ch, + 8); + ul_ch -= 24; +#endif + + for (pilot_cnt=6; pilot_cnt<6*(nb_rb_pusch-1); pilot_cnt += 6) { + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + +#if NO_INTERP + for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; + ul_ch+=24; +#else + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + ul_ch, + 8); + ul_ch -= 16; +#endif + } + // Last PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + +#if NO_INTERP + for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; + ul_ch+=24; +#else + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + ul_ch, + 8); +#endif + } + else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + LOG_D(PHY,"PUSCH estimation DMRS type 2, no Freq-domain interpolation"); + int32_t ch_0, ch_1; + //First PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + ul_ch, + 8); + ul_ch -= 24; + + for (pilot_cnt=4; pilot_cnt<4*(nb_rb_pusch-1); pilot_cnt += 4) { + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + ul_ch, + 8); + ul_ch -= 16; + } + // Last PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + ul_ch, + 8); + } +#ifdef DEBUG_PUSCH + ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; + for(uint16_t idxP=0; idxPstart_symbol_index + rel15_ul->nr_of_symbols; + uint8_t *startSymbIndex = &rel15_ul->start_symbol_index; + uint8_t *nbSymb = &rel15_ul->nr_of_symbols; + uint8_t *L_ptrs = &rel15_ul->pusch_ptrs.ptrs_time_density; + uint8_t *K_ptrs = &rel15_ul->pusch_ptrs.ptrs_freq_density; + uint16_t *dmrsSymbPos = &rel15_ul->ul_dmrs_symb_pos; + uint16_t *ptrsSymbPos = &gNB->pusch_vars[ulsch_id]->ptrs_symbols; + uint8_t *ptrsSymbIdx = &gNB->pusch_vars[ulsch_id]->ptrs_symbol_index; + uint8_t *dmrsConfigType = &rel15_ul->dmrs_config_type; + uint16_t *nb_rb = &rel15_ul->rb_size; + uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset; + /* loop over antennas */ + for (int aarx=0; aarxnb_antennas_rx; aarx++) { + phase_per_symbol = (int16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx]; + ptrs_re_symbol = &gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot; + *ptrs_re_symbol = 0; + phase_per_symbol[(2*symbol)+1] = 0; // Imag + /* set DMRS estimates to 0 angle with magnitude 1 */ + if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { + /* set DMRS real estimation to 32767 */ + phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767 +#ifdef DEBUG_UL_PTRS + printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]); +#endif + } + else {// real ptrs value is set to 0 + phase_per_symbol[2*symbol] = 0; // Real + } + + if(symbol == *startSymbIndex) { + *ptrsSymbPos = 0; + set_ptrs_symb_idx(ptrsSymbPos, + *nbSymb, + *startSymbIndex, + 1<< *L_ptrs, + *dmrsSymbPos); + } + /* if not PTRS symbol set current ptrs symbol index to zero*/ + *ptrsSymbIdx = 0; + /* Check if current symbol contains PTRS */ + if(is_ptrs_symbol(symbol, *ptrsSymbPos)) { + *ptrsSymbIdx = symbol; + /*------------------------------------------------------------------------------------------------------- */ + /* 1) Estimate common phase error per PTRS symbol */ + /*------------------------------------------------------------------------------------------------------- */ + nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb, + rel15_ul->rnti, + (int16_t *)&gNB->pusch_vars[ulsch_id]->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch], + nr_tti_rx, + symbol,frame_parms->ofdm_symbol_size, + (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)], + gNB->nr_gold_pusch_dmrs[rel15_ul->scid][nr_tti_rx][symbol], + &phase_per_symbol[2* symbol], + ptrs_re_symbol); + } + /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ + if(symbol == (symbInSlot -1)) { + /*------------------------------------------------------------------------------------------------------- */ + /* 2) Interpolate PTRS estimated value in TD */ + /*------------------------------------------------------------------------------------------------------- */ + /* If L-PTRS is > 0 then we need interpolation */ + if(*L_ptrs > 0) { + ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb); + if(ret != 0) { + LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); + } + } +#ifdef DEBUG_UL_PTRS + LOG_M("ptrsEstUl.m","est",gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); + LOG_M("rxdataF_bf_ptrs_comp_ul.m","bf_ptrs_cmp", + &gNB->pusch_vars[0]->rxdataF_comp[aarx][rel15_ul->start_symbol_index * NR_NB_SC_PER_RB * rel15_ul->rb_size], + rel15_ul->nr_of_symbols * NR_NB_SC_PER_RB * rel15_ul->rb_size,1,1); +#endif + /*------------------------------------------------------------------------------------------------------- */ + /* 3) Compensated DMRS based estimated signal with PTRS estimation */ + /*--------------------------------------------------------------------------------------------------------*/ + for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) { + /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */ + /* Skip rotation if the slot processing is wrong */ + if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) { +#ifdef DEBUG_UL_PTRS + printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]); +#endif + rotate_cpx_vector((int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + &phase_per_symbol[2* i], + (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + ((*nb_rb) * NR_NB_SC_PER_RB), 15); + }// if not DMRS Symbol + }// symbol loop + }// last symbol check + }//Antenna loop +} diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index a7789c9224..fd3403236e 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -43,9 +43,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned char Ns, unsigned short p, unsigned char symbol, + int ul_id, unsigned short bwp_start_subcarrier, nfapi_nr_pusch_pdu_t *pusch_pdu); +void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); + +void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot,int first_symb,int num_symb); + +void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol, uint8_t nrOfLayers); + int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); +void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, + NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_pusch_pdu_t *rel15_ul, + uint8_t ulsch_id, + uint8_t nr_tti_rx, + unsigned char symbol, + uint32_t nb_re_pusch); #endif diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.c b/openair1/PHY/NR_REFSIG/dmrs_nr.c index 7042c152fd..2e270318f8 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.c +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.c @@ -37,6 +37,7 @@ uint8_t allowed_xlsch_re_in_dmrs_symbol(uint16_t k, uint16_t start_sc, + uint16_t ofdm_symbol_size, uint8_t numDmrsCdmGrpsNoData, uint8_t dmrs_type) { uint8_t delta; @@ -44,7 +45,7 @@ uint8_t allowed_xlsch_re_in_dmrs_symbol(uint16_t k, if (k>start_sc) diff = k-start_sc; else - diff = start_sc-k; + diff = (ofdm_symbol_size-start_sc)+k; for (int i = 0; i>1) ^ (x2>>2) ^ (x2>>3))<<31); @@ -362,4 +363,46 @@ void generate_dmrs_pbch(uint32_t dmrs_pbch_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_H free(dmrs_sequence); #endif } +/* return the position of next dmrs symbol in a slot */ +int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol) +{ + for(uint8_t symbol = counter; symbol < end_symbol; symbol++) { + if((ul_dmrs_symb_pos >> symbol) & 0x01 ) { + return symbol; + } + } + return -1; +} + +/* return the total number of dmrs symbol in a slot */ +uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb) +{ + uint8_t tmp = 0; + for (int i = 0; i < nb_symb; i++) { + tmp += (l_prime_mask >> i) & 0x01; + } + return tmp; +} + +/* return the position of valid dmrs symbol in a slot for channel compensation */ +int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter) +{ + int8_t symbIdx = -1; + /* if current symbol is DMRS then return this index */ + if(is_dmrs_symbol(counter, dmrs_symb_pos ) ==1) { + return counter; + } + /* find previous DMRS symbol */ + for(int8_t symbol = counter;symbol >=0 ; symbol--) { + if((1< 0) { + symbIdx = symbol; + break; + } + } + /* if there is no previous dmrs available then find the next possible*/ + if(symbIdx == -1) { + symbIdx = get_next_dmrs_symbol_in_slot(dmrs_symb_pos,counter,15); + } + return symbIdx; +} diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.h b/openair1/PHY/NR_REFSIG/dmrs_nr.h index c76f58ad18..b9e9ca6f0d 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.h +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.h @@ -58,9 +58,16 @@ uint16_t get_dmrs_freq_idx_ul(uint16_t n, uint8_t k_prime, uint8_t delta, uint8_ uint8_t allowed_xlsch_re_in_dmrs_symbol(uint16_t k, uint16_t start_sc, + uint16_t ofdm_symbol_size, uint8_t numDmrsCdmGrpsNoData, uint8_t dmrs_type); +void nr_gen_ref_conj_symbols(uint32_t *in, uint32_t length, int16_t *output, uint16_t offset, int mod_order); +int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol); +uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb); +int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter); + +static inline uint8_t is_dmrs_symbol(uint8_t l, uint16_t dmrsSymbMask ) { return ((dmrsSymbMask >> l) & 0x1); } #undef EXTERN #endif /* DMRS_NR_H */ diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 4eeb8a6e96..920b78eac2 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -40,9 +40,9 @@ #include "PHY/defs_gNB.h" /*Table 7.4.1.1.2-1/2 from 38.211 */ -int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1}}; +int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}}; int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}}; -int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1},{1,1},{1,-1},{1,1},{1,1}}; +int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}}; int wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}}; // complex conjugate of mod table @@ -111,9 +111,10 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue, int32_t *output, unsigned short p, unsigned char lp, - unsigned short nb_pdsch_rb) + unsigned short nb_pdsch_rb, + uint8_t config_type) { - int8_t w,config_type; + int8_t w; short *mod_table; unsigned char idx=0; @@ -121,18 +122,16 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue, array_of_w *wf; array_of_w *wt; - config_type = 0; //to be updated by higher layer - - wf = (config_type==0) ? wf1 : wf2; - wt = (config_type==0) ? wt1 : wt2; + wf = (config_type==NFAPI_NR_DMRS_TYPE1) ? wf1 : wf2; + wt = (config_type==NFAPI_NR_DMRS_TYPE1) ? wt1 : wt2; if (config_type > 1) LOG_E(PHY,"Bad PDSCH DMRS config type %d\n", config_type); - if ((p>=1000) && (p<((config_type==0) ? 1008 : 1012))) { + if ((p>=1000) && (p<((config_type==NFAPI_NR_DMRS_TYPE1) ? 1008 : 1012))) { if (ue->frame_parms.Ncp == NORMAL) { - for (int i=0; i>b_idx)&1)<<(mod_order-j-1); + } + output[i<<1] = nr_rx_mod_table[(offset+idx)<<1]; + output[(i<<1)+1] = nr_rx_mod_table[((offset+idx)<<1)+1]; + } +} + +int nr_pusch_lowpaprtype1_dmrs_rx(PHY_VARS_gNB *gNB, + unsigned int Ns, + int16_t *dmrs_seq, + int32_t *output, + unsigned short p, + unsigned char lp, + unsigned short nb_pusch_rb, + uint32_t re_offset, + uint8_t dmrs_type) +{ + int8_t w, nb_dmrs; + int k; + + int dmrs_offset = re_offset/((dmrs_type==pusch_dmrs_type1)?2:3); + + if (dmrs_type != pusch_dmrs_type1) + LOG_E(PHY,"PUSCH DMRS config type %d not valid\n", dmrs_type); + + if ((p>=1000) && (p<1008)) { + if (gNB->frame_parms.Ncp == NORMAL) { + nb_dmrs = NR_NB_SC_PER_RB/2; // for DMRS TYPE 1 - 6 DMRS REs present per RB + for (int i=dmrs_offset; isymbols_per_slot; symb++) { reset = 1; - x2 = ((1<<17) * (14*slot+symb+1) * ((Nid<<1)+1)) + (Nid<<1); - + x2 = ((1<<17) * (fp->symbols_per_slot*slot+symb+1) * ((Nid<<1)+1) + (Nid<<1)); + LOG_D(PHY,"PDCCH DMRS slot %d, symb %d, Nid %d, x2 %x\n",slot,symb,Nid,x2); for (uint32_t n=0; nsymbols_per_slot; symb++) { reset = 1; x2 = ((1<<17) * (fp->symbols_per_slot*slot+symb+1) * ((N_n_scid[n_scid]<<1)+1) +((N_n_scid[n_scid]<<1)+n_scid)); - LOG_D(PHY,"DMRS slot %d, symb %d x2 %x\n",slot,symb,x2); + LOG_D(PHY,"PDSCH DMRS slot %d, symb %d x2 %x, N_n_scid %d,n_scid %d\n",slot,symb,x2,N_n_scid[n_scid],n_scid); for (uint32_t n=0; nframe_parms; + uint32_t ***csi_rs = gNB->nr_gold_csi_rs; + uint32_t x1, x2; + uint8_t reset; + + for (uint8_t slot=0; slotslots_per_frame; slot++) { + for (uint8_t symb=0; symbsymbols_per_slot; symb++) { + + reset = 1; + x2 = ((1<<10) * (fp->symbols_per_slot*slot+symb+1) * ((Nid<<1)+1) + (Nid)); + + for (uint32_t n=0; nframe_parms.Nid_cell; Lmax = ue->frame_parms.Lmax; @@ -37,24 +38,12 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue) i_ssb = l & (Lmax-1); i_ssb2 = i_ssb + (n_hf<<2); - x1 = 1 + (1<<31); + reset = 1; x2 = (1<<11) * (i_ssb2 + 1) * ((Nid>>2) + 1) + (1<<6) * (i_ssb2 + 1) + (Nid&3); - x2 = x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); - - // skip first 50 double words (1600 bits) - for (n = 1; n < 50; n++) { - x1 = (x1>>1) ^ (x1>>4); - x1 = x1 ^ (x1<<31) ^ (x1<<28); - x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); - x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); - } for (n=0; n>1) ^ (x1>>4); - x1 = x1 ^ (x1<<31) ^ (x1<<28); - x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); - x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); - ue->nr_gold_pbch[n_hf][l][n] = x1 ^ x2; + ue->nr_gold_pbch[n_hf][l][n] = lte_gold_generic(&x1, &x2, reset); + reset = 0; } } @@ -63,101 +52,56 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue) } void nr_gold_pdcch(PHY_VARS_NR_UE* ue, - unsigned short n_idDMRS, - unsigned short length_dmrs) + unsigned short nid) { unsigned char ns,l; unsigned int n,x1,x2,x2tmp0; - unsigned int nid; + uint8_t reset; - if (n_idDMRS) - nid = n_idDMRS; - else - nid = ue->frame_parms.Nid_cell; + for (ns=0; nsframe_parms.slots_per_frame; ns++) { - for (ns=0; ns<20; ns++) { + for (l=0; lframe_parms.symbols_per_slot; l++) { - for (l=0; l>1) ^ (x2>>2) ^ (x2>>3))<<31); - - // skip first 50 double words (1600 bits) - for (n=1; n<50; n++) { - x1 = (x1>>1) ^ (x1>>4); - x1 = x1 ^ (x1<<31) ^ (x1<<28); - x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); - x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); - //printf("x1 : %x, x2 : %x\n",x1,x2); - } - - for (n=0; n<52; n++) { - x1 = (x1>>1) ^ (x1>>4); - x1 = x1 ^ (x1<<31) ^ (x1<<28); - x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); - x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); - ue->nr_gold_pdcch[0][ns][l][n] = x1^x2; - // if (ns==1 && l==0) printf("n=%d : c %x\n",n,x1^x2); - } - } + reset = 1; + x2tmp0 = ((ue->frame_parms.symbols_per_slot*ns+l+1)*((nid<<1)+1))<<17; + x2 = (x2tmp0+(nid<<1))%(1<<31); //cinit + + for (n=0; nnr_gold_pdcch[0][ns][l][n] = lte_gold_generic(&x1, &x2, reset); + reset = 0; + } } + } } void nr_gold_pdsch(PHY_VARS_NR_UE* ue, - unsigned short lbar, - unsigned short *n_idDMRS, - unsigned short length_dmrs) + unsigned short *n_idDMRS) { - unsigned char ns,l; - unsigned int n,x1,x2,x2tmp0; + unsigned char l; + unsigned int n,x1,x2,x2tmp0,ns; int nscid; unsigned int nid; + uint8_t reset; /// to be updated from higher layer //unsigned short lbar = 0; for (nscid=0; nscid<2; nscid++) { - if (n_idDMRS) + for (ns=0; nsframe_parms.slots_per_frame; ns++) { + nid = n_idDMRS[nscid]; - else - nid = ue->frame_parms.Nid_cell; - - //printf("gold pdsch nid %d lbar %d\n",nid,lbar); - for (ns=0; ns<20; ns++) { + for (l=0; lframe_parms.symbols_per_slot; l++) { - for (l=0; lframe_parms.symbols_per_slot*ns+l+1)*((nid<<1)+1))<<17; x2 = (x2tmp0+(nid<<1)+nscid)%(1<<31); //cinit - LOG_D(PHY,"UE DMRS slot %d, symb %d, lbar %d, x2 %x, nscid %d\n",ns,l,lbar,x2,nscid); - //printf("ns %d gold pdsch x2 %d\n",ns,x2); - - x1 = 1+ (1<<31); - x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31); - - // skip first 50 double words (1600 bits) - for (n=1; n<50; n++) { - x1 = (x1>>1) ^ (x1>>4); - x1 = x1 ^ (x1<<31) ^ (x1<<28); - x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); - x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); - //printf("x1 : %x, x2 : %x\n",x1,x2); - } + LOG_D(PHY,"UE DMRS slot %d, symb %d, x2 %x, nscid %d\n",ns,l,x2,nscid); for (n=0; n>1) ^ (x1>>4); - x1 = x1 ^ (x1<<31) ^ (x1<<28); - x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); - x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); - ue->nr_gold_pdsch[nscid][ns][l][n] = x1^x2; - // if ((ns==2)&&(l==0)) - //printf("n=%d : c %x\n",n,x1^x2); + ue->nr_gold_pdsch[0][ns][l][nscid][n] = lte_gold_generic(&x1, &x2, reset); + reset = 0; } - } } } diff --git a/openair1/PHY/NR_REFSIG/nr_mod_table.h b/openair1/PHY/NR_REFSIG/nr_mod_table.h index aa8b99f584..2c6964fe96 100644 --- a/openair1/PHY/NR_REFSIG/nr_mod_table.h +++ b/openair1/PHY/NR_REFSIG/nr_mod_table.h @@ -29,16 +29,16 @@ #define NR_MOD_TABLE_QAM64_OFFSET 23 #define NR_MOD_TABLE_QAM256_OFFSET 87 -short nr_qpsk_mod_table[8]; +extern short nr_qpsk_mod_table[8]; -int32_t nr_16qam_mod_table[16]; +extern int32_t nr_16qam_mod_table[16]; #if defined(__SSE2__) -__m128i nr_qpsk_byte_mod_table[2048]; +extern __m128i nr_qpsk_byte_mod_table[2048]; #endif -int64_t nr_16qam_byte_mod_table[1024]; +extern int64_t nr_16qam_byte_mod_table[1024]; -int64_t nr_64qam_mod_table[4096]; +extern int64_t nr_64qam_mod_table[4096]; -int32_t nr_256qam_mod_table[512]; +extern int32_t nr_256qam_mod_table[512]; #endif diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index 786fb2af35..aedc535c29 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -38,6 +38,7 @@ void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB); */ void nr_init_pdcch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid); void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid); +void nr_init_csi_rs(PHY_VARS_gNB* gNB, uint32_t Nid); void nr_gold_pusch(PHY_VARS_gNB* gNB, uint32_t *Nid); @@ -52,10 +53,24 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB, uint8_t dmrs_type); void init_scrambling_luts(void); - void nr_generate_modulation_table(void); extern __m64 byte2m64_re[256]; extern __m64 byte2m64_im[256]; +extern __m128i byte2m128i[256]; + + + +int nr_pusch_lowpaprtype1_dmrs_rx(PHY_VARS_gNB *gNB, + unsigned int Ns, + int16_t *dmrs_seq, + int32_t *output, + unsigned short p, + unsigned char lp, + unsigned short nb_pusch_rb, + uint32_t re_offset, + uint8_t dmrs_type); + + #endif diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index 19b9736bcb..b32d48a2e9 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -120,8 +120,7 @@ EXTERN int64_t *pss_corr_ue[NUMBER_PSS_SEQUENCE] ; /* profiling structure */ -EXTERN double cpuf; -time_stats_t generic_time[TIME_LAST]; +EXTERN time_stats_t generic_time[TIME_LAST]; #ifndef DEFINE_HEADER_ONLY diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.c b/openair1/PHY/NR_REFSIG/ptrs_nr.c index 785252126a..b50c9a7bc9 100644 --- a/openair1/PHY/NR_REFSIG/ptrs_nr.c +++ b/openair1/PHY/NR_REFSIG/ptrs_nr.c @@ -34,7 +34,7 @@ #include #include "dmrs_nr.h" #include "PHY/NR_REFSIG/ptrs_nr.h" - +#include "PHY/NR_REFSIG/nr_refsig.h" /***********************************************************************/ @@ -180,93 +180,249 @@ uint8_t is_ptrs_subcarrier(uint16_t k, return 0; } - -/* -int main(int argc, char const *argv[]) +/* return the total number of ptrs symbol in a slot */ +uint8_t get_ptrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t start_symb, uint16_t nb_symb) { - - dmrs_UplinkConfig_t dmrs_Uplink_Config; - ptrs_UplinkConfig_t ptrs_Uplink_Config; - uint8_t resourceElementOffset; - uint8_t dmrs_antenna_port; - uint8_t L_ptrs, K_ptrs; - int16_t k_RE_ref; - uint16_t N_RB, ptrs_symbols, ofdm_symbol_size, k; - uint8_t duration_in_symbols, I_mcs; - uint8_t start_symbol, l; - uint8_t ptrs_symbol_flag; - uint16_t n_rnti; - - dmrs_Uplink_Config.pusch_dmrs_type = pusch_dmrs_type1; - dmrs_Uplink_Config.pusch_dmrs_AdditionalPosition = pusch_dmrs_pos1; - dmrs_Uplink_Config.pusch_maxLength = pusch_len2; - - ptrs_Uplink_Config.timeDensity.ptrs_mcs1 = 0; // setting MCS values to 0 indicate abscence of time_density field in the configuration - ptrs_Uplink_Config.timeDensity.ptrs_mcs2 = 0; - ptrs_Uplink_Config.timeDensity.ptrs_mcs3 = 0; - ptrs_Uplink_Config.frequencyDensity.n_rb0 = 0; // setting N_RB values to 0 indicate abscence of frequency_density field in the configuration - ptrs_Uplink_Config.frequencyDensity.n_rb1 = 0; - ptrs_Uplink_Config.resourceElementOffset = 0; - - n_rnti = 0x1234; - resourceElementOffset = 0; - ptrs_symbols = 0; - dmrs_antenna_port = 0; - N_RB = 50; - duration_in_symbols = 14; - ofdm_symbol_size = 2048; - I_mcs = 9; - start_symbol = 0; - ptrs_symbol_flag = 0; - - k_RE_ref = get_kRE_ref(dmrs_antenna_port, dmrs_Uplink_Config.pusch_dmrs_type, resourceElementOffset); - - K_ptrs = get_K_ptrs(&ptrs_Uplink_Config, N_RB); - - L_ptrs = get_L_ptrs(&ptrs_Uplink_Config, I_mcs); - - set_ptrs_symb_idx(&ptrs_symbols, - &ptrs_Uplink_Config, - &dmrs_Uplink_Config, - 1, - duration_in_symbols, - start_symbol, - L_ptrs, - ofdm_symbol_size); - - printf("PTRS OFDM symbol indicies: "); - - for (l = start_symbol; l < start_symbol + duration_in_symbols; l++){ - - ptrs_symbol_flag = is_ptrs_symbol(l, - 0, - n_rnti, - N_RB, - duration_in_symbols, - dmrs_antenna_port, - K_ptrs, - ptrs_symbols, - dmrs_Uplink_Config.pusch_dmrs_type, - &ptrs_Uplink_Config); - - if (ptrs_symbol_flag == 1) - printf(" %d ", l); - + uint8_t tmp = 0; + for (int i = start_symb; i <= nb_symb; i++) + { + tmp += (l_prime_mask >> i) & 0x01; } + return tmp; +} - printf("\n"); - - printf("PTRS subcarrier indicies: "); - - for (k = 0; k < N_RB*12; k++){ - - if (is_ptrs_subcarrier(k, K_ptrs, n_rnti, N_RB, k_RE_ref) == 1) - printf(" %d ", k); - +/* return the position of next ptrs symbol in a slot */ +int8_t get_next_ptrs_symbol_in_slot(uint16_t ptrs_symb_pos, uint8_t counter, uint8_t nb_symb) +{ + for(int8_t symbol = counter; symbol < nb_symb; symbol++) { + if((ptrs_symb_pos >>symbol)&0x01 ) { + return symbol; } + } + return -1; +} - printf("\n"); +/* get the next nearest estimate from DMRS or PTRS */ +int8_t get_next_estimate_in_slot(uint16_t ptrsSymbPos,uint16_t dmrsSymbPos, uint8_t counter,uint8_t nb_symb) +{ + int8_t nextPtrs = get_next_ptrs_symbol_in_slot(ptrsSymbPos, counter,nb_symb); + int8_t nextDmrs = get_next_dmrs_symbol_in_slot(dmrsSymbPos, counter,nb_symb); + if(nextDmrs == -1) { + return nextPtrs; + } + /* Special case when DMRS is next valid estimation */ + if(nextPtrs == -1) { + return nextDmrs; + } + return (nextPtrs > nextDmrs)?nextDmrs:nextPtrs; +} +/******************************************************************* + * + * NAME : nr_ptrs_cpe_estimation + * + * PARAMETERS : K_ptrs : K value for PTRS + * ptrsReOffset : RE offset for PTRS + * dmrsConfigType: DMRS configuration type + * nb_rb : No. of resource blocks + * rnti : RNTI + * ptrs_ch_p : pointer to ptrs channel structure + * Ns : + * symbol : OFDM symbol + * ofdm_symbol_size: OFDM Symbol Size + * rxF_comp : pointer to channel compensated signal + * gold_seq : Gold sequence pointer + * error_est : Estimated error output vector [Re Im] + * ptrs_sc : Total PTRS RE in a symbol + * RETURN : nothing + * + * DESCRIPTION : + * perform phase estimation from regenerated PTRS SC and channel compensated + * signal + *********************************************************************/ +void nr_ptrs_cpe_estimation(uint8_t K_ptrs, + uint8_t ptrsReOffset, + uint8_t dmrsConfigType, + uint16_t nb_rb, + uint16_t rnti, + int16_t *ptrs_ch_p, + unsigned char Ns, + unsigned char symbol, + uint16_t ofdm_symbol_size, + int16_t *rxF_comp, + uint32_t *gold_seq, + int16_t *error_est, + int32_t *ptrs_sc) +{ +//#define DEBUG_PTRS 1 + uint8_t is_ptrs_re = 0; + uint16_t re_cnt = 0; + uint16_t cnt = 0; + unsigned short nb_re_pdsch = NR_NB_SC_PER_RB * nb_rb; + uint16_t sc_per_symbol = (nb_rb + K_ptrs - 1)/K_ptrs; + int16_t *ptrs_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol)); + int16_t *dmrs_comp_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol)); + double abs = 0.0; + double real = 0.0; + double imag = 0.0; +#ifdef DEBUG_PTRS + double alpha = 0; +#endif + /* generate PTRS RE for the symbol */ + nr_gen_ref_conj_symbols(gold_seq,sc_per_symbol*2,ptrs_p, NR_MOD_TABLE_QPSK_OFFSET,2);// 2 for QPSK + + /* loop over all sub carriers to get compensated RE on ptrs symbols*/ + for (int re = 0; re < nb_re_pdsch; re++) { + is_ptrs_re = is_ptrs_subcarrier(re, + rnti, + 0, + dmrsConfigType, + K_ptrs, + nb_rb, + ptrsReOffset, + 0,// start_re is 0 here + ofdm_symbol_size); + if(is_ptrs_re) { + dmrs_comp_p[re_cnt*2] = rxF_comp[re *2]; + dmrs_comp_p[(re_cnt*2)+1] = rxF_comp[(re *2)+1]; + re_cnt++; + } + else { + /* Skip PTRS symbols and keep data in a continuous vector */ + rxF_comp[cnt *2]= rxF_comp[re *2]; + rxF_comp[(cnt *2)+1]= rxF_comp[(re *2)+1]; + cnt++; + } + }/* RE loop */ + /* update the total ptrs RE in a symbol */ + *ptrs_sc = re_cnt; + + /*Multiple compensated data with conj of PTRS */ + mult_cpx_vector(dmrs_comp_p, ptrs_p, ptrs_ch_p,(1 + sc_per_symbol/4)*4,15); // 2^15 shifted + + /* loop over all ptrs sub carriers in a symbol */ + /* sum the error vector */ + for(int i = 0;i < sc_per_symbol; i++) { + real+= ptrs_ch_p[(2*i)]; + imag+= ptrs_ch_p[(2*i)+1]; + } +#ifdef DEBUG_PTRS + alpha = atan(imag/real); + printf("[PHY][PTRS]: Symbol %d atan(Im,real):= %f \n",symbol, alpha ); +#endif + /* mean */ + real /= sc_per_symbol; + imag /= sc_per_symbol; + /* absolute calculation */ + abs = sqrt(((real * real) + (imag * imag))); + /* normalized error estimation */ + error_est[0]= (real / abs)*(1<<15); + /* compensation in given by conjugate of estimated phase (e^-j*2*pi*fd*t)*/ + error_est[1]= (-1)*(imag / abs)*(1<<15); +#ifdef DEBUG_PTRS + printf("[PHY][PTRS]: Estimated Symbol %d -> %d + j* %d \n",symbol, error_est[0], error_est[1] ); +#endif + /* free vectors */ + free(ptrs_p); + free(dmrs_comp_p); +} + + +/******************************************************************* + * + * NAME : nr_ptrs_process_slot + * + * PARAMETERS : dmrsSymbPos DMRS symbol index mask per slot + * ptrsSymbpos PTRS symbol index mask per slot + * estPerSymb Estimated CPE pointer + * startSymbIdx First symbol index in a slot + * noSymb total number of OFDM symbols in a slot + * RETURN : True if slot is process correctly + * DESCRIPTION : + * Process whole slot and interpolate or extrapolate estimation for the symbols + * where there is neither PTRS nor DMRS configured + * + *********************************************************************/ +int8_t nr_ptrs_process_slot(uint16_t dmrsSymbPos, + uint16_t ptrsSymbPos, + int16_t *estPerSymb, + uint16_t startSymbIdx, + uint16_t noSymb) +{ + double slope[2] = {0,0}; + double *slope_p = &slope[0]; + uint8_t symbInSlot = startSymbIdx + noSymb; + int8_t rightRef = 0; + int8_t leftRef = 0; + int8_t tmp = 0; + for(uint8_t symb = startSymbIdx; symb %4d %4d from Slope (%4f %4f)\n", start+i,error_est[(start+i)*2],error_est[((start +i)*2)+1], + slope_p[0],slope_p[1]); +#endif + } +} diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.h b/openair1/PHY/NR_REFSIG/ptrs_nr.h index e8a4e61232..41acde0d06 100644 --- a/openair1/PHY/NR_REFSIG/ptrs_nr.h +++ b/openair1/PHY/NR_REFSIG/ptrs_nr.h @@ -80,6 +80,31 @@ uint8_t is_ptrs_subcarrier(uint16_t k, static inline uint8_t is_ptrs_symbol(uint8_t l, uint16_t ptrs_symbols) { return ((ptrs_symbols >> l) & 1); } +uint8_t get_ptrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t start_symb, uint16_t nb_symb); +int8_t get_next_ptrs_symbol_in_slot(uint16_t ptrsSymbPos, uint8_t counter, uint8_t nb_symb); +int8_t get_next_estimate_in_slot(uint16_t ptrsSymbPos,uint16_t dmrsSymbPos, uint8_t counter,uint8_t nb_symb); +int8_t nr_ptrs_process_slot(uint16_t dmrsSymbPos, + uint16_t ptrsSymbPos, + int16_t *estPerSymb, + uint16_t startSymbIdx, + uint16_t noSymb + ); +/* general function to estimate common phase error based upon PTRS */ +void nr_ptrs_cpe_estimation(uint8_t K_ptrs, + uint8_t ptrsReOffset, + uint8_t dmrsConfigType, + uint16_t nb_rb, + uint16_t rnti, + int16_t *ptrs_ch_p, + unsigned char Ns, + unsigned char symbol, + uint16_t ofdm_symbol_size, + int16_t *rxF_comp, + uint32_t *gold_seq, + int16_t *error_est, + int32_t *ptrs_sc); +void get_slope_from_estimates(uint8_t start, uint8_t end, int16_t *est_p, double *slope_p); +void ptrs_estimate_from_slope(int16_t *error_est, double *slope_p, uint8_t start, uint8_t end); #endif /* PTRS_NR_H */ diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 93a64051de..1fca2be2a1 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -52,18 +52,16 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue, int32_t *output, unsigned short p, unsigned char lp, - unsigned short nb_pdsch_rb); + unsigned short nb_pdsch_rb, + uint8_t config_type); void nr_gold_pbch(PHY_VARS_NR_UE* ue); void nr_gold_pdcch(PHY_VARS_NR_UE* ue, - unsigned short n_idDMRS, - unsigned short length_dmrs); + unsigned short n_idDMRS); void nr_gold_pdsch(PHY_VARS_NR_UE* ue, - unsigned short lbar, - unsigned short *n_idDMRS, - unsigned short length_dmrs); + unsigned short *n_idDMRS); void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue, uint16_t *N_n_scid, diff --git a/openair1/PHY/NR_REFSIG/scrambling_luts.c b/openair1/PHY/NR_REFSIG/scrambling_luts.c index 790d3f7719..2a37a12539 100644 --- a/openair1/PHY/NR_REFSIG/scrambling_luts.c +++ b/openair1/PHY/NR_REFSIG/scrambling_luts.c @@ -32,6 +32,8 @@ __m64 byte2m64_re[256]; __m64 byte2m64_im[256]; +__m128i byte2m128i[256]; + void init_byte2m64(void) { for (int s=0;s<256;s++) { @@ -49,15 +51,29 @@ void init_byte2m64(void) { ((int16_t*)&byte2m64_re[s])[0],((int16_t*)&byte2m64_im[s])[0], ((int16_t*)&byte2m64_re[s])[1],((int16_t*)&byte2m64_im[s])[1], ((int16_t*)&byte2m64_re[s])[2],((int16_t*)&byte2m64_im[s])[2], - ((int16_t*)&byte2m64_re[s])[3],((int16_t*)&byte2m64_im[s])[3]); + ((int16_t*)&byte2m64_re[s])[3],((int16_t*)&byte2m64_im[s])[3]); } } +void init_byte2m128i(void) { + + for (int s=0;s<256;s++) { + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*(s&1)),0); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>1)&1)),1); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>2)&1)),2); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>3)&1)),3); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>4)&1)),4); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>5)&1)),5); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>6)&1)),6); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>7)&1)),7); + } +} + void init_scrambling_luts(void) { init_byte2m64(); - + init_byte2m128i(); } #endif diff --git a/openair1/PHY/NR_REFSIG/sss_nr.h b/openair1/PHY/NR_REFSIG/sss_nr.h index c260abd071..12d91ed3d1 100644 --- a/openair1/PHY/NR_REFSIG/sss_nr.h +++ b/openair1/PHY/NR_REFSIG/sss_nr.h @@ -92,13 +92,7 @@ int pss_ch_est_nr(PHY_VARS_NR_UE *ue, int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR]); -int _do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, - int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], - int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR], - uint8_t doPss, uint8_t doSss, - uint8_t subframe); - -int rx_sss_nr(PHY_VARS_NR_UE *ue, int32_t *tot_metric, uint8_t *phase_max); +int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max); #undef INIT_VARIABLES_SSS_NR_H #undef EXTERN diff --git a/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.c b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.c index 8521a2618f..4a419ae926 100644 --- a/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.c +++ b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.c @@ -108,6 +108,39 @@ int16_t *base_sequence_less_than_36(unsigned int M_ZC, return rv_overbar; } +/******************************************************************* +* +* NAME : get_index_for_dmrs_lowpapr_seq +* +* PARAMETERS : num_dmrs_res - Total number of DMRS RES possible in allocated RBs +* +* +* RETURN : returns index of array dmrs_ul_allocated_res +* +* DESCRIPTION : finds the index which in turn is used to index into dmrs low papr sequences +* +*********************************************************************/ + +int16_t get_index_for_dmrs_lowpapr_seq(int16_t num_dmrs_res) { + + int16_t index = -1; + + if (num_dmrs_res >= dmrs_ul_allocated_res[(MAX_INDEX_DMRS_UL_ALLOCATED_REs-1)]) + index = MAX_INDEX_DMRS_UL_ALLOCATED_REs-1; + else + index = (num_dmrs_res/6) -1; + + for (;index >= 0; index--) { + if (dmrs_ul_allocated_res[index] == num_dmrs_res) + break; + + } + + LOG_D(PHY, "num_dmrs_res: %d INDEX RETURNED: %d", num_dmrs_res, index); + return index; + +} + /******************************************************************* * * NAME : base_sequence_36_or_larger @@ -126,13 +159,19 @@ int16_t *base_sequence_less_than_36(unsigned int M_ZC, int16_t *base_sequence_36_or_larger(unsigned int Msc_RS, unsigned int u, unsigned int v, - unsigned int scaling) + unsigned int scaling, unsigned int if_dmrs_seq) { int16_t *rv_overbar; - unsigned int N_ZC; + unsigned int N_ZC, M_ZC; double q_overbar, x; unsigned int q,m,n; - unsigned int M_ZC = ul_allocated_re[Msc_RS]; + + + if (if_dmrs_seq) + M_ZC = dmrs_ul_allocated_res[Msc_RS]; + else + M_ZC = ul_allocated_re[Msc_RS]; + rv_overbar = malloc16(IQ_SIZE*M_ZC); if (rv_overbar == NULL) { @@ -140,7 +179,11 @@ int16_t *base_sequence_36_or_larger(unsigned int Msc_RS, assert(0); } - N_ZC = ref_ul_primes[Msc_RS]; /* The length N_ZC is given by the largest prime number such that N_ZC < M_ZC */ + if (if_dmrs_seq) + N_ZC = dmrs_ref_ul_primes[Msc_RS]; + else + N_ZC = ref_ul_primes[Msc_RS]; /* The length N_ZC is given by the largest prime number such that N_ZC < M_ZC */ + q_overbar = N_ZC * (u+1)/(double)31; @@ -159,19 +202,24 @@ int16_t *base_sequence_36_or_larger(unsigned int Msc_RS, return rv_overbar; } -/******************************************************************* -* -* NAME : generate_ul_srs_sequences -* -* PARAMETERS : scaling to apply -* -* RETURN : none -* -* DESCRIPTION : uplink reference signal sequences generation -* which are Low-PAPR base sequences -* see TS 38.211 5.2.2 Low-PAPR sequence generation -* -*********************************************************************/ +void generate_lowpapr_typ1_refsig_sequences(unsigned int scaling) +{ + unsigned int u,Msc_RS; + unsigned int v = 0; // sequence hopping and group hopping are not supported yet + + for (Msc_RS=0; Msc_RS <= INDEX_SB_LESS_32; Msc_RS++) { + for (u=0; u < U_GROUP_NUMBER; u++) { + gNB_dmrs_lowpaprtype1_sequence[u][v][Msc_RS] = base_sequence_less_than_36(ul_allocated_re[Msc_RS], u, scaling); + } + } + + for (Msc_RS=INDEX_SB_LESS_32+1; Msc_RS < MAX_INDEX_DMRS_UL_ALLOCATED_REs; Msc_RS++) { + for (u=0; u < U_GROUP_NUMBER; u++) { + gNB_dmrs_lowpaprtype1_sequence[u][v][Msc_RS] = base_sequence_36_or_larger(Msc_RS, u, v, scaling, 1); + } + } +} + void generate_ul_reference_signal_sequences(unsigned int scaling) { @@ -184,10 +232,13 @@ void generate_ul_reference_signal_sequences(unsigned int scaling) #endif + for (Msc_RS=0; Msc_RS <= INDEX_SB_LESS_32; Msc_RS++) { - v = 0; + v = 0; for (u=0; u < U_GROUP_NUMBER; u++) { rv_ul_ref_sig[u][v][Msc_RS] = base_sequence_less_than_36(ul_allocated_re[Msc_RS], u, scaling); + dmrs_lowpaprtype1_ul_ref_sig[u][v][Msc_RS] = base_sequence_less_than_36(ul_allocated_re[Msc_RS], u, scaling); + #if 0 sprintf(output_file, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]); sprintf(sequence_name, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]); @@ -198,10 +249,19 @@ void generate_ul_reference_signal_sequences(unsigned int scaling) } } + for (Msc_RS=INDEX_SB_LESS_32+1; Msc_RS < MAX_INDEX_DMRS_UL_ALLOCATED_REs; Msc_RS++) { + v = 0; // neither group hopping or sequnce hopping is supported for PUSCH DMRS hence v = 0 + for (u=0; u < U_GROUP_NUMBER; u++) { + dmrs_lowpaprtype1_ul_ref_sig[u][v][Msc_RS] = base_sequence_36_or_larger(Msc_RS, u, v, scaling, 1); + } + + } + for (Msc_RS=INDEX_SB_LESS_32+1; Msc_RS < SRS_SB_CONF; Msc_RS++) { for (u=0; u < U_GROUP_NUMBER; u++) { - for (v=0; v < V_BASE_SEQUENCE_NUMBER; v++) { - rv_ul_ref_sig[u][v][Msc_RS] = base_sequence_36_or_larger(Msc_RS, u, v, scaling); + for (v=0; v < V_BASE_SEQUENCE_NUMBER; v++) { + rv_ul_ref_sig[u][v][Msc_RS] = base_sequence_36_or_larger(Msc_RS, u, v, scaling, 0); + #if 0 sprintf(output_file, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]); sprintf(sequence_name, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]); @@ -212,8 +272,11 @@ void generate_ul_reference_signal_sequences(unsigned int scaling) } } } + + } + /******************************************************************* * * NAME : free_ul_reference_signal_sequences @@ -233,7 +296,33 @@ void free_ul_reference_signal_sequences(void) for (v=0; v < V_BASE_SEQUENCE_NUMBER; v++) { if (rv_ul_ref_sig[u][v][Msc_RS]) free16(rv_ul_ref_sig[u][v][Msc_RS],2*sizeof(int16_t)*ul_allocated_re[Msc_RS]); + if ((v==0) && (Msc_RS < MAX_INDEX_DMRS_UL_ALLOCATED_REs)) + if (dmrs_lowpaprtype1_ul_ref_sig[u][v][Msc_RS]) + free16(dmrs_lowpaprtype1_ul_ref_sig[u][v][Msc_RS],2*sizeof(int16_t)*dmrs_ul_allocated_res[Msc_RS]); } } } } +/******************************************************************* +* +* NAME : free_gnb_lowpapr_sequences +* +* PARAMETERS : none +* +* RETURN : none +* +* DESCRIPTION : free of uplink reference signal sequences +* +*********************************************************************/ +void free_gnb_lowpapr_sequences(void) +{ + unsigned int u,v,Msc_RS; + for (Msc_RS=0; Msc_RS < MAX_INDEX_DMRS_UL_ALLOCATED_REs; Msc_RS++) { + v=0; + for (u=0; u < U_GROUP_NUMBER; u++) { + if (gNB_dmrs_lowpaprtype1_sequence[u][v][Msc_RS]) + free16(gNB_dmrs_lowpaprtype1_sequence[u][v][Msc_RS],2*sizeof(int16_t)*dmrs_ul_allocated_res[Msc_RS]); + } + } +} + diff --git a/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h index dd967e8e5e..43ec0c03dc 100644 --- a/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h +++ b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h @@ -38,6 +38,10 @@ #include "PHY/NR_REFSIG/ss_pbch_nr.h" +#include "PHY/defs_nr_common.h" +#include "PHY/defs_gNB.h" + + #ifdef DEFINE_VARIABLES_LOWPAPR_SEQUENCES_NR_H #define EXTERN #define INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H @@ -54,7 +58,7 @@ #define INDEX_SB_LESS_32 (4) /* index of dftsizes array for which subcarrier number is less than 36 */ -const uint16_t ul_allocated_re[SRS_SB_CONF] /* number of uplink allocated resource elements */ +EXTERN const uint16_t ul_allocated_re[SRS_SB_CONF] /* number of uplink allocated resource elements */ /* this table is derivated from TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration which gives m_SRS_b then all possible values of sequence length is */ /* M_sc_b_SRS = m_SRS_b * N_SC_RB/K_TC with K_TC = 2 or K_TC = 4 as specified in TS 38.211 6.4.1.4.3 */ #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H @@ -78,7 +82,7 @@ m_SRS_b 224 116, 240 256 264 272 144 152 160 168 176 184 ; /* table of largest prime number lower than uplink allocated resource elements "ul_allocated_re" */ -const uint16_t ref_ul_primes[SRS_SB_CONF] +EXTERN const uint16_t ref_ul_primes[SRS_SB_CONF] #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H = { /* 6, 12, 18, 24, 30, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 168, 180, 192, 204, 216, 228, 240, */ @@ -97,10 +101,10 @@ const uint16_t ref_ul_primes[SRS_SB_CONF] ; /* Low-PAPR base sequence; see TS 38.211 clause 5.2.2 */ -int16_t *rv_ul_ref_sig[U_GROUP_NUMBER][V_BASE_SEQUENCE_NUMBER][SRS_SB_CONF]; +EXTERN int16_t *rv_ul_ref_sig[U_GROUP_NUMBER][V_BASE_SEQUENCE_NUMBER][SRS_SB_CONF]; /* 38.211 table Table 5.2.2.2-1: Definition of phi(n) for M_ZC = 6 */ -const char phi_M_ZC_6[6*U_GROUP_NUMBER] +EXTERN const char phi_M_ZC_6[6*U_GROUP_NUMBER] #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H = { /* 0 1 2 3 4 5 */ @@ -138,7 +142,7 @@ const char phi_M_ZC_6[6*U_GROUP_NUMBER] #endif ; /* Table 5.2.2.2-2: Definition of phi ( n ) for M ZC = 12 */ -const char phi_M_ZC_12[12*U_GROUP_NUMBER] +EXTERN const char phi_M_ZC_12[12*U_GROUP_NUMBER] #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H = { /* 0 1 2 3 4 5 6 7 8 9 10 11 */ @@ -177,7 +181,7 @@ const char phi_M_ZC_12[12*U_GROUP_NUMBER] ; /* Table 5.2.2.2-3: Definition of phi (n ) for M_ZC = 18 */ -const char phi_M_ZC_18[18*U_GROUP_NUMBER] +EXTERN const char phi_M_ZC_18[18*U_GROUP_NUMBER] #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H = { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 */ @@ -216,7 +220,7 @@ const char phi_M_ZC_18[18*U_GROUP_NUMBER] ; /* Table 5.2.2.2-4: Definition of phi (n ) for M_ZC = 24 */ -const char phi_M_ZC_24[24*U_GROUP_NUMBER] +EXTERN const char phi_M_ZC_24[24*U_GROUP_NUMBER] #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H = { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 */ @@ -255,8 +259,11 @@ const char phi_M_ZC_24[24*U_GROUP_NUMBER] ; /************** FUNCTION ******************************************/ -int16_t *base_sequence_36_or_larger(unsigned int M_ZC, unsigned int u, unsigned int v, unsigned int scaling); -int16_t *base_sequence_less_than_36(unsigned int M_ZC, unsigned int u, unsigned int scaling); + +EXTERN int16_t *base_sequence_36_or_larger(unsigned int M_ZC, unsigned int u, unsigned int v, unsigned int scaling, unsigned int if_dmrs_seq); + + +EXTERN int16_t *base_sequence_less_than_36(unsigned int M_ZC, unsigned int u, unsigned int scaling); /*! \brief This function generate the sounding reference symbol (SRS) for the uplink. @param tables of srs @@ -265,6 +272,72 @@ int16_t *base_sequence_less_than_36(unsigned int M_ZC, unsigned int u, unsigned void generate_ul_reference_signal_sequences(unsigned int scaling); void free_ul_reference_signal_sequences(void); + + +// Supported for 100Mhz configuration - which has max 273 RBs +#define MAX_INDEX_DMRS_UL_ALLOCATED_REs 53 + + +EXTERN const uint16_t dmrs_ul_allocated_res[MAX_INDEX_DMRS_UL_ALLOCATED_REs] +/* Number of possible DMRS REs based on PRBs allocated for PUSCH. Array has values until 273 RBs (100Mhz BW) + Number of PUSCH RBs allocated should be able to be expressed as 2topowerofn*3topowerofn*5tothepowerofn + According to 3GPP spec 38.211 section 6.3.1.4 + Table used in calculating DMRS low papr type1 sequence for transform precoding */ +#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H += { +/*RBs 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, */ + 6, 12, 18, 24, 30, 36, 48, 54, 60, 72, 90, 96, + +/*RBs 18, 20, 24, 25, 27, 30, 32, 36, 40, 45, 48, 50, */ + 108, 120, 144, 150, 162, 180, 192, 216, 240, 270, 288, 300, + +/*RBs 54, 60, 64, 72 75, 80, 81, 90, 96, 100, (Bw 40Mhz) */ + 324, 360, 384, 432, 450, 480, 486, 540, 576, 600, + +/*RBs 108, 120 125 128 135 144 150 160 162 180 192 200 */ + 648, 720, 750, 768, 810, 864, 900, 960, 972, 1080, 1152, 1200, + +/*RBs 216 225 240 243 250 256 270 supported until 100Mhz */ + 1296, 1350, 1440, 1458, 1500, 1536, 1620 + +} +#endif +; + +/* Table of largest prime number N_ZC < possible DMRS REs M_ZC, this array has values until 100Mhz + According to 3GPP spec 38.211 section 5.2.2.1 + Table used in calculating DMRS low papr type1 sequence for transform precoding */ +EXTERN const uint16_t dmrs_ref_ul_primes[MAX_INDEX_DMRS_UL_ALLOCATED_REs] +#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H += { +/*DMRS REs 6, 12, 18, 24, 30, 36, 48, 54, 60, 72, 90, 96, */ + 5, 11, 17, 23, 29, 31, 47, 53, 59, 71, 89, 89, + +/*DMRS REs 108, 120, 144, 150, 162, 180, 192, 216, 240, 270, 288, 300, */ + 107, 113, 139, 149, 157, 179, 191, 211, 239, 269, 283, 293, + +/*DMRS REs 324, 360, 384, 432, 450, 480, 486, 540, 576, 600, */ + 317, 359, 383, 431, 449, 479, 479, 523, 571, 599, + +/*DMRS REs 648, 720, 750, 768, 810, 864, 900, 960, 972, 1080, 1152, 1200, */ + 647, 719, 743, 761, 809, 863, 887, 953, 971, 1069, 1151, 1193, + +/*DMRS REs 1296, 1350, 1440, 1458, 1500, 1536 1620 supported until 100Mhz */ + 1291, 1327, 1439, 1453, 1499, 1531, 1619 + + +} +#endif +; + +/// PUSCH DMRS for transform precoding +EXTERN int16_t *gNB_dmrs_lowpaprtype1_sequence[U_GROUP_NUMBER][V_BASE_SEQUENCE_NUMBER][MAX_INDEX_DMRS_UL_ALLOCATED_REs]; +EXTERN int16_t *dmrs_lowpaprtype1_ul_ref_sig[U_GROUP_NUMBER][V_BASE_SEQUENCE_NUMBER][MAX_INDEX_DMRS_UL_ALLOCATED_REs]; +int16_t get_index_for_dmrs_lowpapr_seq(int16_t num_dmrs_res); +void generate_lowpapr_typ1_refsig_sequences(unsigned int scaling); +void free_gnb_lowpapr_sequences(void); + + #undef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H #undef EXTERN diff --git a/common/utils/itti_analyzer/NEWS b/openair1/PHY/NR_TRANSPORT/dlsch_pdu_rel15.time_alloc_list_flag similarity index 100% rename from common/utils/itti_analyzer/NEWS rename to openair1/PHY/NR_TRANSPORT/dlsch_pdu_rel15.time_alloc_list_flag diff --git a/openair1/PHY/NR_TRANSPORT/dlsch_pdu_rel15.time_allocation_type b/openair1/PHY/NR_TRANSPORT/dlsch_pdu_rel15.time_allocation_type new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c new file mode 100644 index 0000000000..ac0eac8a79 --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_csi_rs.c @@ -0,0 +1,623 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + + +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" +#include "PHY/MODULATION/nr_modulation.h" +#include "PHY/NR_REFSIG/nr_refsig.h" + +//#define NR_CSIRS_DEBUG + + +void nr_generate_csi_rs(PHY_VARS_gNB *gNB, + int16_t amp, + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t csi_params, + uint16_t cell_id, + int slot){ + + NR_DL_FRAME_PARMS frame_parms=gNB->frame_parms; + int32_t **txdataF = gNB->common_vars.txdataF; + int txdataF_offset = (slot%2)*frame_parms.samples_per_slot_wCP; + uint32_t **gold_csi_rs = gNB->nr_gold_csi_rs[slot]; + int16_t mod_csi[frame_parms.symbols_per_slot][NR_MAX_CSI_RS_LENGTH>>1] __attribute__((aligned(16)));; + uint16_t b = csi_params.freq_domain; + uint16_t n, csi_bw, csi_start, p, k, l, mprime, na, kpn, csi_length; + uint8_t size, ports, kprime, lprime, i, gs; + uint8_t j[16], k_n[6], koverline[16], loverline[16]; + int found = 0; + int wf, wt, lp, kp, symb; + uint8_t fi = 0; + double rho, alpha; + uint32_t beta = amp; + + AssertFatal(b!=0, "Invalid CSI frequency domain mapping: no bit selected in bitmap\n"); + + // pre-computed for scrambling id equel to cell id + // if the scrambling id is not the cell id we need to re-initialize the rs + if (csi_params.scramb_id != cell_id) { + uint8_t reset; + uint32_t x1, x2; + uint32_t Nid = csi_params.scramb_id; + for (uint8_t symb=0; symb> fi) & 0x01) { + k_n[found] = fi; + found++; + } + else + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi; + found++; + } + else + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + else + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<2; + found++; + } + else + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + else + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i>1); + koverline[i] = k_n[i%2]; + } + break; + + case 8: + ports = 8; + kprime = 1; + lprime = 1; + size = 2; + while (found < 2) { + if ((b >> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i>2); + koverline[i] = k_n[i%4]; + } + break; + + case 12: + ports = 16; + kprime = 1; + lprime = 1; + size = 4; + while (found < 4) { + if ((b >> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i>2); + else + loverline[i] = csi_params.symb_l1 + (i/12); + koverline[i] = k_n[i%4]; + } + break; + + case 17: + ports = 32; + kprime = 1; + lprime = 1; + size = 8; + while (found < 4) { + if ((b >> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i> fi) & 0x01) { + k_n[found] = fi<<1; + found++; + } + fi++; + } + for (i=0; i (csi_params.bwp_start+csi_params.bwp_size-csi_start)) + csi_bw = csi_params.bwp_start+csi_params.bwp_size-csi_start; + else + csi_bw = csi_params.nr_of_rbs; + + if (rho < 1) { + if (csi_params.freq_density == 0) + csi_length = (((csi_bw + csi_start)>>1)<>1)<>15; + break; + case 1: + beta = amp; + break; + case 2: + beta = (amp*ONE_OVER_SQRT2_Q15)>>14; + break; + case 3: + beta = amp<<1; + break; + default: + AssertFatal(0==1, "Invalid SS power offset density index for CSI\n"); + } + + for (lp=0; lp<=lprime; lp++){ + symb = csi_params.symb_l0; + nr_modulation(gold_csi_rs[symb+lp], csi_length, DMRS_MOD_ORDER, mod_csi[symb+lp]); + if ((csi_params.row == 5) || (csi_params.row == 7) || (csi_params.row == 11) || (csi_params.row == 13) || (csi_params.row == 16)) + nr_modulation(gold_csi_rs[symb+1], csi_length, DMRS_MOD_ORDER, mod_csi[symb+1]); + if ((csi_params.row == 14) || (csi_params.row == 13) || (csi_params.row == 16) || (csi_params.row == 17)) { + symb = csi_params.symb_l1; + nr_modulation(gold_csi_rs[symb+lp], csi_length, DMRS_MOD_ORDER, mod_csi[symb+lp]); + if ((csi_params.row == 13) || (csi_params.row == 16)) + nr_modulation(gold_csi_rs[symb+1], csi_length, DMRS_MOD_ORDER, mod_csi[symb+1]); + } + } + } + + uint16_t start_sc = frame_parms.first_carrier_offset; + + // resource mapping according to 38.211 7.4.1.5.3 + for (n=csi_start; n<(csi_start+csi_bw); n++) { + if ( (csi_params.freq_density > 1) || (csi_params.freq_density == (n%2))) { // for freq density 0.5 checks if even or odd RB + for (int ji=0; ji> 15; + ((int16_t*)txdataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+1+(2*txdataF_offset)] = (beta*wt*wf*mod_csi[l][(mprime<<1) + 1]) >> 15; + } +#ifdef NR_CSIRS_DEBUG + printf("l,k (%d %d) seq. index %d \t port %d \t (%d,%d)\n",l,k,mprime,p+3000, + ((int16_t*)txdataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+(2*txdataF_offset)], + ((int16_t*)txdataF[p])[((l*frame_parms.ofdm_symbol_size + k)<<1)+1+(2*txdataF_offset)]); +#endif + } + } + } + } + } + } +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 3a44ebc49a..f26464fd70 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -30,104 +30,17 @@ * \warning */ + #include "nr_dci.h" #include "nr_dlsch.h" #include "nr_sch_dmrs.h" #include "PHY/MODULATION/nr_modulation.h" +#include "common/utils/nr/nr_common.h" //#define DEBUG_PDCCH_DMRS //#define DEBUG_DCI //#define DEBUG_CHANNEL_CODING - -uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, - nfapi_nr_rnti_type_e rnti_type, - uint16_t N_RB) { - uint16_t size = 0; - - switch(format) { - /*Only sizes for 0_0 and 1_0 are correct at the moment*/ - case NFAPI_NR_UL_DCI_FORMAT_0_0: - /// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20 - size += 20; - size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment -- hopping scenario to be updated - size += nr_get_dci_size(NFAPI_NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB) - size; // Padding to match 1_0 size - // UL/SUL indicator assumed to be 0 - break; - - case NFAPI_NR_UL_DCI_FORMAT_0_1: - /// fixed: Format identifier 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2, SRS request 2 --17 - size += 17; - // Carrier indicator - // UL/SUL indicator - // BWP Indicator - // Freq domain assignment - // Time domain assignment - // VRB to PRB mapping - // Frequency Hopping flag - // 1st DAI - // 2nd DAI - // SRS resource indicator - // Precoding info and number of layers - // Antenna ports - // CSI request - // CBGTI - // PTRS - DMRS association - // beta offset indicator - // DMRS sequence init - break; - - case NFAPI_NR_DL_DCI_FORMAT_1_0: - /// fixed: Format identifier 1, VRB2PRB 1, MCS 5, NDI 1, RV 2, HARQ PID 4, DAI 2, PUCCH TPC 2, PUCCH RInd 3, PDSCH to HARQ TInd 3 Time Domain assgnmt 4 -- 28 - size += 28; - size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment - break; - - case NFAPI_NR_DL_DCI_FORMAT_1_1: - // Carrier indicator - size += 1; // Format identifier - // BWP Indicator - // Freq domain assignment - // Time domain assignment - // VRB to PRB mapping - // PRB bundling size indicator - // Rate matching indicator - // ZP CSI-RS trigger - /// TB1- MCS 5, NDI 1, RV 2 - size += 8; - // TB2 - size += 4 ; // HARQ PID - // DAI - size += 2; // TPC PUCCH - size += 3; // PUCCH resource indicator - size += 3; // PDSCH to HARQ timing indicator - // Antenna ports - // Tx Config Indication - size += 2; // SRS request - // CBGTI - // CBGFI - size += 1; // DMRS sequence init - break; - - case NFAPI_NR_DL_DCI_FORMAT_2_0: - break; - - case NFAPI_NR_DL_DCI_FORMAT_2_1: - break; - - case NFAPI_NR_DL_DCI_FORMAT_2_2: - break; - - case NFAPI_NR_DL_DCI_FORMAT_2_3: - break; - - default: - AssertFatal(1==0, "Invalid NR DCI format %d\n", format); - } - - return size; -} - void nr_pdcch_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, @@ -153,63 +66,46 @@ void nr_pdcch_scrambling(uint32_t *in, } } - -uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu, - uint32_t **gold_pdcch_dmrs, - int32_t *txdataF, - int16_t amp, - NR_DL_FRAME_PARMS frame_parms) { +void nr_generate_dci(PHY_VARS_gNB *gNB, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + uint32_t **gold_pdcch_dmrs, + int32_t *txdataF, + int16_t amp, + NR_DL_FRAME_PARMS *frame_parms) { int16_t mod_dmrs[NR_MAX_CSET_DURATION][NR_MAX_PDCCH_DMRS_LENGTH>>1] __attribute__((aligned(16))); // 3 for the max coreset duration uint16_t cset_start_sc; uint8_t cset_start_symb, cset_nsymb; int k,l,k_prime,dci_idx, dmrs_idx; - /*First iteration: single DCI*/ - - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15=NULL; - // find coreset descriptor int rb_offset; int n_rb; - - AssertFatal(pdcch_pdu!=NULL || ul_dci_pdu!=NULL,"At least one pointer has to be !NULL\n"); - AssertFatal(pdcch_pdu==NULL || ul_dci_pdu==NULL,"Can't handle both DL and UL DCI in same slot\n"); - - - if (pdcch_pdu) pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15; - else if (ul_dci_pdu) pdcch_pdu_rel15 = &ul_dci_pdu->pdcch_pdu.pdcch_pdu_rel15; - - get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset); - + // compute rb_offset and n_prb based on frequency allocation - - if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_MIB_SIB1) { - cset_start_sc = frame_parms.first_carrier_offset + (frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB + - rb_offset)*NR_NB_SC_PER_RB; - } else - cset_start_sc = frame_parms.first_carrier_offset + rb_offset*NR_NB_SC_PER_RB; + nr_fill_cce_list(gNB,0,pdcch_pdu_rel15); + get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset); + cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; for (int d=0;dnumDlDci;d++) { /*The coreset is initialised * in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0 * or the rb_offset for other coresets * in time: by its first slot and its first symbol*/ + const nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[d]; cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex; cset_nsymb = pdcch_pdu_rel15->DurationSymbols; dci_idx = 0; - LOG_D(PHY, "Coreset rb_offset %d, nb_rb %d\n",rb_offset,n_rb); + LOG_D(PHY, "Coreset rb_offset %d, nb_rb %d BWP Start %d\n",rb_offset,n_rb,pdcch_pdu_rel15->BWPStart); LOG_D(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb); // DMRS length is per OFDM symbol - AssertFatal(pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED, - "Interleaved CCE REG MAPPING not supported\n"); - uint32_t dmrs_length = (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED)? - (n_rb*6) : (pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*36/cset_nsymb); //2(QPSK)*3(per RB)*6(REG per CCE) - uint32_t encoded_length = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*108; //2(QPSK)*9(per RB)*6(REG per CCE) - LOG_D(PHY, "DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d)\n", dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType); + uint32_t dmrs_length = n_rb*6; //2(QPSK)*3(per RB)*6(REG per CCE) + uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE) + LOG_D(PHY, "DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d),Scrambling_Id %d,ScramblingRNTI %x,PayloadSizeBits %d\n", + rb_offset, n_rb,dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType, + dci_pdu->ScramblingId,dci_pdu->ScramblingRNTI,dci_pdu->PayloadSizeBits); dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset /// DMRS QPSK modulation @@ -218,11 +114,11 @@ uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, nr_modulation(gold_pdcch_dmrs[symb], dmrs_length, DMRS_MOD_ORDER, mod_dmrs[symb]); //Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_PDCCH_DMRS - + if(dci_pdu->RNTI!=0xFFFF) { for (int i=0; i>1; i++) - printf("symb %d i %d gold seq 0x%08x mod_dmrs %d %d\n", symb, i, - gold_pdcch_dmrs[symb][i>>5], mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1] ); - + printf("symb %d i %d %p gold seq 0x%08x mod_dmrs %d %d\n", symb, i, + &gold_pdcch_dmrs[symb][i>>5],gold_pdcch_dmrs[symb][i>>5], mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1] ); + } #endif } @@ -230,19 +126,19 @@ uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, // CRC attachment + Scrambling + Channel coding + Rate matching uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD]; - uint16_t n_RNTI = pdcch_pdu_rel15->dci_pdu.RNTI[d]; - uint16_t Nid = pdcch_pdu_rel15->dci_pdu.ScramblingId[d]; - uint16_t scrambling_RNTI = pdcch_pdu_rel15->dci_pdu.ScramblingRNTI[d]; + uint16_t n_RNTI = dci_pdu->RNTI; + uint16_t Nid = dci_pdu->ScramblingId; + uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI; t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE, - pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d], - pdcch_pdu_rel15->dci_pdu.AggregationLevel[d], + dci_pdu->PayloadSizeBits, + dci_pdu->AggregationLevel, 0,NULL); - polar_encoder_fast((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d], (void*)encoder_output, n_RNTI,1,currentPtr); + polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI,1,currentPtr); #ifdef DEBUG_CHANNEL_CODING - printf("polar rnti %x,length %d, L %d\n",n_RNTI, pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d],pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]); + printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu->AggregationLevel); printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n", - ((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d])[0], ((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d])[1]); + ((uint64_t*)dci_pdu->Payload)[0], ((uint64_t*)dci_pdu->Payload)[1]); printf("Encoded Payload (length:%d dwords):\n", encoded_length>>5); for (int i=0; i>5; i++) @@ -268,63 +164,107 @@ uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, printf("i %d mod_dci %d %d\n", i, mod_dci[i<<1], mod_dci[(i<<1)+1] ); #endif - + /// Resource mapping - - if (cset_start_sc >= frame_parms.ofdm_symbol_size) - cset_start_sc -= frame_parms.ofdm_symbol_size; - - /*Reorder REG list for a freq first mapping*/ - uint8_t reg_idx0 = pdcch_pdu_rel15->dci_pdu.CceIndex[d]*NR_NB_REG_PER_CCE; - uint8_t nb_regs = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*NR_NB_REG_PER_CCE; + + if (cset_start_sc >= frame_parms->ofdm_symbol_size) + cset_start_sc -= frame_parms->ofdm_symbol_size; + + // Get cce_list indices by reg_idx in ascending order + int reg_list_index = 0; + int reg_list_order[NR_MAX_PDCCH_AGG_LEVEL] = {}; + for (int p = 0; p < NR_MAX_PDCCH_AGG_LEVEL; p++) { + for(int p2 = 0; p2 < dci_pdu->AggregationLevel; p2++) { + if(gNB->cce_list[d][p2].reg_list[0].reg_idx == p * NR_NB_REG_PER_CCE) { + reg_list_order[reg_list_index] = p2; + reg_list_index++; + break; + } + } + } /*Mapping the encoded DCI along with the DMRS */ - for (int reg_idx=reg_idx0; reg_idx<(nb_regs+reg_idx0); reg_idx++) { - k = cset_start_sc + (12*reg_idx/cset_nsymb); - - if (k >= frame_parms.ofdm_symbol_size) - k -= frame_parms.ofdm_symbol_size; - - l = cset_start_symb + ((reg_idx/cset_nsymb)%cset_nsymb); - - // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 - if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - dmrs_idx = (reg_idx/cset_nsymb)*3; - else - dmrs_idx = ((reg_idx/cset_nsymb)+rb_offset)*3; - - k_prime = 0; - - for (int m=0; mCceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED) { - ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[l][dmrs_idx<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15; + for(int symbol_idx = 0; symbol_idx < pdcch_pdu_rel15->DurationSymbols; symbol_idx++) { + for (int cce_count = 0; cce_count < dci_pdu->AggregationLevel; cce_count+=pdcch_pdu_rel15->DurationSymbols) { + + int8_t cce_idx = reg_list_order[cce_count]; + + for (int reg_in_cce_idx = 0; reg_in_cce_idx < NR_NB_REG_PER_CCE; reg_in_cce_idx++) { + + k = cset_start_sc + gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].start_sc_idx; + + if (k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; + + l = cset_start_symb + symbol_idx; + + // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 + if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) + dmrs_idx = (gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx) * 3; + else + dmrs_idx = (gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx + rb_offset) * 3; + + k_prime = 0; + + for (int m = 0; m < NR_NB_SC_PER_RB; m++) { + if (m == (k_prime << 2) + 1) { // DMRS if not already mapped + ((int16_t *) txdataF)[(l * frame_parms->ofdm_symbol_size + k) << 1] = + (amp * mod_dmrs[l][dmrs_idx << 1]) >> 15; + ((int16_t *) txdataF)[((l * frame_parms->ofdm_symbol_size + k) << 1) + 1] = + (amp * mod_dmrs[l][(dmrs_idx << 1) + 1]) >> 15; + #ifdef DEBUG_PDCCH_DMRS - printf("PDCCH DMRS: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], - ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); + LOG_D(PHY,"PDCCH DMRS %d: l %d position %d => (%d,%d)\n",dmrs_idx,l,k,((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); #endif - dmrs_idx++; - } - - k_prime++; - } else { // DCI payload - ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * mod_dci[dci_idx<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dci[(dci_idx<<1) + 1]) >> 15; + + dmrs_idx++; + k_prime++; + + } else { // DCI payload + ((int16_t *) txdataF)[(l * frame_parms->ofdm_symbol_size + k) << 1] = (amp * mod_dci[dci_idx << 1]) >> 15; + ((int16_t *) txdataF)[((l * frame_parms->ofdm_symbol_size + k) << 1) + 1] = + (amp * mod_dci[(dci_idx << 1) + 1]) >> 15; #ifdef DEBUG_DCI - printf("PDCCH: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], - ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); + LOG_D(PHY,"PDCCH: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); #endif - dci_idx++; - } - - k++; - - if (k >= frame_parms.ofdm_symbol_size) - k -= frame_parms.ofdm_symbol_size; - } // m - } // reg_idx + + dci_idx++; + } + + k++; + + if (k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; + + } // m + } // reg_in_cce_idx + } // cce_count + } // symbol_idx + + LOG_D(PHY, + "DCI: payloadSize = %d | payload = %llx\n", + dci_pdu->PayloadSizeBits, + *(unsigned long long *)dci_pdu->Payload); } // for (int d=0;dnumDlDci;d++) - return 0; +} + +void nr_generate_dci_top(PHY_VARS_gNB *gNB, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, + nfapi_nr_dl_tti_pdcch_pdu *ul_dci_pdu, + uint32_t **gold_pdcch_dmrs, + int32_t *txdataF, + int16_t amp, + NR_DL_FRAME_PARMS *frame_parms) { + + AssertFatal(pdcch_pdu!=NULL || ul_dci_pdu!=NULL,"At least one pointer has to be !NULL\n"); + + if (pdcch_pdu) { + nr_generate_dci(gNB,&pdcch_pdu->pdcch_pdu_rel15,gold_pdcch_dmrs,txdataF,amp,frame_parms); + } + if (ul_dci_pdu) { + nr_generate_dci(gNB,&ul_dci_pdu->pdcch_pdu_rel15,gold_pdcch_dmrs,txdataF,amp,frame_parms); + } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.h b/openair1/PHY/NR_TRANSPORT/nr_dci.h index 047139aa63..07baaf2728 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.h @@ -29,12 +29,13 @@ uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, nfapi_nr_rnti_type_e rnti_type, uint16_t N_RB); -uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu, - uint32_t **gold_pdcch_dmrs, +void nr_generate_dci_top(PHY_VARS_gNB *gNB, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, + nfapi_nr_dl_tti_pdcch_pdu *ul_pdcch_pdu, + uint32_t **gold_pdcch_dmrs, int32_t *txdataF, int16_t amp, - NR_DL_FRAME_PARMS frame_parms); + NR_DL_FRAME_PARMS *frame_parms); void nr_pdcch_scrambling(uint32_t *in, uint32_t size, @@ -42,16 +43,20 @@ void nr_pdcch_scrambling(uint32_t *in, uint32_t n_RNTI, uint32_t *out); +int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type); + void nr_fill_dci(PHY_VARS_gNB *gNB, int frame, - int slot); + int slot, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu); + +int16_t find_nr_ul_dci(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type); void nr_fill_ul_dci(PHY_VARS_gNB *gNB, int frame, - int slot); + int slot, + nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu); -void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m); - -void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset); +void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m,nfapi_nr_dl_tti_pdcch_pdu_rel15_t *); #endif //__PHY_NR_TRANSPORT_DCI__H diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index 02ecfc4404..1675045443 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -31,6 +31,7 @@ */ #include "nr_dci.h" +#include "common/utils/nr/nr_common.h" //#define DEBUG_FILL_DCI @@ -118,11 +119,11 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint16_t n_shift, uint8_t m) { */ -void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { +void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15) { nr_cce_t* cce; nr_reg_t* reg; - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu_rel15 = &gNB->pdcch_pdu->pdcch_pdu_rel15; + int bsize = pdcch_pdu_rel15->RegBundleSize; int R = pdcch_pdu_rel15->InterleaverSize; int n_shift = pdcch_pdu_rel15->ShiftIndex; @@ -136,11 +137,13 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset); - int N_reg = n_rb * pdcch_pdu_rel15->DurationSymbols; + int N_reg = n_rb; int C=-1; + AssertFatal(N_reg > 0,"N_reg cannot be 0\n"); + for (int d=0;dnumDlDci;d++) { - int L = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]; + int L = pdcch_pdu_rel15->dci_pdu[d].AggregationLevel; if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_MIB_SIB1) AssertFatal(L>=4, "Invalid aggregation level for SIB1 configured PDCCH %d\n", L); @@ -151,10 +154,10 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { C = N_reg/(bsize*R); } - LOG_D(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d CceIndex %d\n", m, bsize, R, pdcch_pdu_rel15->dci_pdu.CceIndex[d]); + if (pdcch_pdu_rel15->dci_pdu[d].RNTI != 0xFFFF) LOG_D(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d CceIndex %d\n", m, bsize, R, pdcch_pdu_rel15->dci_pdu[d].CceIndex); for (uint8_t cce_idx=0; cce_idxcce_list[d][cce_idx]; - cce->cce_idx = pdcch_pdu_rel15->dci_pdu.CceIndex[d] + cce_idx; + cce->cce_idx = pdcch_pdu_rel15->dci_pdu[d].CceIndex + cce_idx; LOG_D(PHY, "cce_idx %d\n", cce->cce_idx); if (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { @@ -172,8 +175,8 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { for (uint8_t reg_idx=0; reg_idxreg_list[reg_idx]; reg->reg_idx = bsize*idx + reg_idx; - reg->start_sc_idx = (reg->reg_idx/pdcch_pdu_rel15->DurationSymbols) * NR_NB_SC_PER_RB; - reg->symb_idx = reg->reg_idx % pdcch_pdu_rel15->DurationSymbols; + reg->start_sc_idx = reg->reg_idx * NR_NB_SC_PER_RB; + reg->symb_idx = 0; LOG_D(PHY, "reg %d symbol %d start subcarrier %d\n", reg->reg_idx, reg->symb_idx, reg->start_sc_idx); } } @@ -183,8 +186,8 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { for (uint8_t reg_idx=0; reg_idxreg_list[reg_idx]; reg->reg_idx = cce->cce_idx*NR_NB_REG_PER_CCE + reg_idx; - reg->start_sc_idx = (reg->reg_idx/pdcch_pdu_rel15->DurationSymbols) * NR_NB_SC_PER_RB; - reg->symb_idx = reg->reg_idx % pdcch_pdu_rel15->DurationSymbols; + reg->start_sc_idx = reg->reg_idx * NR_NB_SC_PER_RB; + reg->symb_idx = 0; LOG_D(PHY, "reg %d symbol %d start subcarrier %d\n", reg->reg_idx, reg->symb_idx, reg->start_sc_idx); } @@ -200,63 +203,3 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { ret |= ((field>>i)&1)<<(size-i-1); return ret; }*/ - -void nr_fill_dci(PHY_VARS_gNB *gNB, - int frame, - int slot) { - - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &gNB->pdcch_pdu->pdcch_pdu_rel15; - NR_gNB_DLSCH_t *dlsch; - - for (int i=0;inumDlDci;i++) { - - //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; - - int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu.RNTI[i],gNB,SEARCH_EXIST_OR_FREE); - if( (dlsch_id<0) || (dlsch_id>=NUMBER_OF_NR_DLSCH_MAX) ){ - LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu.RNTI[i],dlsch_id); - return; - } - - dlsch = gNB->dlsch[dlsch_id][0]; - int num_slots_tdd = (gNB->frame_parms.slots_per_frame)>>(7-gNB->gNB_config.tdd_table.tdd_period.value); - int harq_pid = slot % num_slots_tdd; - - dlsch->slot_tx[slot] = 1; - dlsch->harq_ids[frame%2][slot] = harq_pid; - AssertFatal(harq_pid < 8 && harq_pid >= 0, - "illegal harq_pid %d\n",harq_pid); - - dlsch->harq_mask |= (1<rnti = pdcch_pdu_rel15->dci_pdu.RNTI[i]; - - nr_fill_cce_list(gNB,0); - /* - LOG_D(PHY, "DCI PDU: [0]->0x%lx \t [1]->0x%lx \n",dci_pdu[0], dci_pdu[1]); - LOG_D(PHY, "DCI type %d payload (size %d) generated on candidate %d\n", dci_alloc->pdcch_params.dci_format, dci_alloc->size, cand_idx); - */ - - } - -} -void nr_fill_ul_dci(PHY_VARS_gNB *gNB, - int frame, - int slot) { - - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &gNB->ul_dci_pdu->pdcch_pdu.pdcch_pdu_rel15; - - - for (int i=0;inumDlDci;i++) { - - //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; - - // if there's no DL DCI then generate CCE list - if (gNB->pdcch_pdu) nr_fill_cce_list(gNB,0); - /* - LOG_D(PHY, "DCI PDU: [0]->0x%lx \t [1]->0x%lx \n",dci_pdu[0], dci_pdu[1]); - LOG_D(PHY, "DCI type %d payload (size %d) generated on candidate %d\n", dci_alloc->pdcch_params.dci_format, dci_alloc->size, cand_idx); - */ - - } - -} diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 2849986833..9bbc61d4b6 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -35,7 +35,9 @@ #include "nr_sch_dmrs.h" #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_REFSIG/dmrs_nr.h" +#include "PHY/NR_REFSIG/ptrs_nr.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "common/utils/nr/nr_common.h" //#define DEBUG_DLSCH //#define DEBUG_DLSCH_MAPPING @@ -84,7 +86,7 @@ void nr_pdsch_codeword_scrambling_optim(uint8_t *in, for (int i=0; i<((size>>5)+((size&0x1f) > 0 ? 1 : 0)); i++) { in32=_mm256_movemask_epi8(_mm256_slli_epi16(((__m256i*)in)[i],7)); out[i]=(in32^s); - // printf("in[%d] %x => %x\n",i,in32,out[i]); + //printf("in[%d] %x => %x\n",i,in32,out[i]); s=lte_gold_generic(&x1, &x2, 0); } #elif defined(__SSE4__) @@ -109,220 +111,505 @@ void nr_pdsch_codeword_scrambling_optim(uint8_t *in, } -uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, - uint32_t ***pdsch_dmrs, - int32_t** txdataF, - int16_t amp, - int frame, - uint8_t slot, - NR_DL_FRAME_PARMS *frame_parms, - int xOverhead, - time_stats_t *dlsch_encoding_stats, - time_stats_t *dlsch_scrambling_stats, - time_stats_t *dlsch_modulation_stats, - time_stats_t *tinput, - time_stats_t *tprep, - time_stats_t *tparity, - time_stats_t *toutput, - time_stats_t *dlsch_rate_matching_stats, - time_stats_t *dlsch_interleaving_stats, - time_stats_t *dlsch_segmentation_stats) { +void nr_generate_pdsch(processingData_L1tx_t *msgTx, + int frame, + int slot) { - int harq_pid = dlsch->harq_ids[frame%2][slot]; - NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[harq_pid]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; - uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; - int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs; - int16_t **tx_layers = (int16_t**)dlsch->txdataF; - int8_t Wf[2], Wt[2], l0, l_prime[2], delta; - uint8_t dmrs_Type = rel15->dmrsConfigType; - int nb_re_dmrs; - uint16_t n_dmrs; - if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { - nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; - n_dmrs = ((rel15->rbSize+rel15->rbStart)*6)<<1; - } - else { - nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; - n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1; - } - uint16_t nb_re; - nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs-xOverhead)*rel15->rbSize*rel15->NrOfCodewords; - uint8_t Qm = rel15->qamModOrder[0]; - uint32_t encoded_length = nb_re*Qm; - int16_t mod_dmrs[n_dmrs<<1] __attribute__ ((aligned(16))); + PHY_VARS_gNB *gNB = msgTx->gNB; + NR_gNB_DLSCH_t *dlsch; + uint32_t ***pdsch_dmrs = gNB->nr_gold_pdsch_dmrs[slot]; + int32_t** txdataF = gNB->common_vars.txdataF; + int16_t amp = AMP; + int xOverhead = 0; + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + time_stats_t *dlsch_encoding_stats=&gNB->dlsch_encoding_stats; + time_stats_t *dlsch_scrambling_stats=&gNB->dlsch_scrambling_stats; + time_stats_t *dlsch_modulation_stats=&gNB->dlsch_modulation_stats; + time_stats_t *tinput=&gNB->tinput; + time_stats_t *tprep=&gNB->tprep; + time_stats_t *tparity=&gNB->tparity; + time_stats_t *toutput=&gNB->toutput; + time_stats_t *dlsch_rate_matching_stats=&gNB->dlsch_rate_matching_stats; + time_stats_t *dlsch_interleaving_stats=&gNB->dlsch_interleaving_stats; + time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats; - /// CRC, coding, interleaving and rate matching - AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); - start_meas(dlsch_encoding_stats); - nr_dlsch_encoding(harq->pdu, frame, slot, dlsch, frame_parms,tinput,tprep,tparity,toutput, - dlsch_rate_matching_stats, - dlsch_interleaving_stats, - dlsch_segmentation_stats); - stop_meas(dlsch_encoding_stats); + for (int dlsch_id=0; dlsch_idnum_pdsch_slot; dlsch_id++) { + dlsch = msgTx->dlsch[dlsch_id][0]; + + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; + int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs; + int16_t **tx_layers = (int16_t**)dlsch->txdataF; + int16_t **txdataF_precoding = (int16_t**)dlsch->txdataF_precoding; + int8_t Wf[2], Wt[2], l0, l_prime, l_overline, delta; + uint8_t dmrs_Type = rel15->dmrsConfigType; + int nb_re_dmrs; + uint16_t n_dmrs; + if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; + } + else { + nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; + } + n_dmrs = (rel15->BWPStart+rel15->rbStart+rel15->rbSize)*nb_re_dmrs; + + uint16_t dmrs_symbol_map = rel15->dlDmrsSymbPos;//single DMRS: 010000100 Double DMRS 110001100 + uint8_t dmrs_len = get_num_dmrs(rel15->dlDmrsSymbPos); + uint16_t nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs*dmrs_len-xOverhead)*rel15->rbSize*rel15->nrOfLayers; + uint8_t Qm = rel15->qamModOrder[0]; + uint32_t encoded_length = nb_re*Qm; + int16_t mod_dmrs[n_dmrs<<1] __attribute__ ((aligned(16))); + + /* PTRS */ + uint16_t beta_ptrs = 1; + uint8_t ptrs_symbol = 0; + uint16_t dlPtrsSymPos = 0; + uint16_t n_ptrs = 0; + uint16_t ptrs_idx = 0; + uint8_t is_ptrs_re = 0; + if(rel15->pduBitmap & 0x1) { + set_ptrs_symb_idx(&dlPtrsSymPos, + rel15->NrOfSymbols, + rel15->StartSymbolIndex, + 1<PTRSTimeDensity, + rel15->dlDmrsSymbPos); + n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1)/rel15->PTRSFreqDensity; + } + int16_t mod_ptrs[n_ptrs<<1] __attribute__ ((aligned(16))); + + /// CRC, coding, interleaving and rate matching + AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); + unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(32))); + bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + start_meas(dlsch_encoding_stats); + nr_dlsch_encoding(gNB, + harq->pdu, frame, slot, dlsch, frame_parms, output, + tinput,tprep,tparity,toutput, + dlsch_rate_matching_stats, + dlsch_interleaving_stats, + dlsch_segmentation_stats); + stop_meas(dlsch_encoding_stats); #ifdef DEBUG_DLSCH - printf("PDSCH encoding:\nPayload:\n"); - for (int i=0; iB>>7; i++) { - for (int j=0; j<16; j++) - printf("0x%02x\t", harq->pdu[(i<<4)+j]); - printf("\n"); - } - printf("\nEncoded payload:\n"); - for (int i=0; i>3; i++) { - for (int j=0; j<8; j++) - printf("%d", harq->f[(i<<3)+j]); - printf("\t"); - } - printf("\n"); -#endif - - - - /// scrambling - start_meas(dlsch_scrambling_stats); - for (int q=0; qNrOfCodewords; q++) - memset((void*)scrambled_output[q], 0, (encoded_length>>5)*sizeof(uint32_t)); - for (int q=0; qNrOfCodewords; q++) - nr_pdsch_codeword_scrambling_optim(harq->f, - encoded_length, - q, - rel15->dlDmrsScramblingId, - rel15->rnti, - scrambled_output[q]); - - stop_meas(dlsch_scrambling_stats); -#ifdef DEBUG_DLSCH - printf("PDSCH scrambling:\n"); - for (int i=0; i>8; i++) { - for (int j=0; j<8; j++) - printf("0x%08x\t", scrambled_output[0][(i<<3)+j]); - printf("\n"); - } -#endif - - /// Modulation - start_meas(dlsch_modulation_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 1); - for (int q=0; qNrOfCodewords; q++) - nr_modulation(scrambled_output[q], - encoded_length, - Qm, - mod_symbs[q]); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 0); - stop_meas(dlsch_modulation_stats); -#ifdef DEBUG_DLSCH - printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_re); - for (int i=0; i>3; i++) { - for (int j=0; j<8; j++) { - printf("%d %d\t", mod_symbs[0][((i<<3)+j)<<1], mod_symbs[0][(((i<<3)+j)<<1)+1]); + printf("PDSCH encoding:\nPayload:\n"); + for (int i=0; iB>>7; i++) { + for (int j=0; j<16; j++) + printf("0x%02x\t", harq->pdu[(i<<4)+j]); + printf("\n"); + } + printf("\nEncoded payload:\n"); + for (int i=0; i>3; i++) { + for (int j=0; j<8; j++) + printf("%d", output[(i<<3)+j]); + printf("\t"); } printf("\n"); - } #endif - - - /// Layer mapping - nr_layer_mapping(mod_symbs, - rel15->nrOfLayers, - nb_re, - tx_layers); + + + + /// scrambling + start_meas(dlsch_scrambling_stats); + for (int q=0; qNrOfCodewords; q++) + memset((void*)scrambled_output[q], 0, (encoded_length>>5)*sizeof(uint32_t)); + for (int q=0; qNrOfCodewords; q++) + nr_pdsch_codeword_scrambling_optim(output, + encoded_length, + q, + rel15->dataScramblingId, + rel15->rnti, + scrambled_output[q]); + + stop_meas(dlsch_scrambling_stats); #ifdef DEBUG_DLSCH - printf("Layer mapping (%d layers):\n", rel15->nrOfLayers); - for (int l=0; lnrOfLayers; l++) - for (int i=0; i<(nb_re/rel15->nrOfLayers)>>3; i++) { - printf("layer %d, Re %d..%d : ",l,i<<3,(i<<3)+7); + printf("PDSCH scrambling:\n"); + for (int i=0; i>8; i++) { + for (int j=0; j<8; j++) + printf("0x%08x\t", scrambled_output[0][(i<<3)+j]); + printf("\n"); + } +#endif + + /// Modulation + start_meas(dlsch_modulation_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 1); + for (int q=0; qNrOfCodewords; q++) + nr_modulation(scrambled_output[q], + encoded_length, + Qm, + mod_symbs[q]); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 0); + stop_meas(dlsch_modulation_stats); +#ifdef DEBUG_DLSCH + printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_re); + for (int i=0; i>3; i++) { for (int j=0; j<8; j++) { - printf("l%d %d\t", tx_layers[l][((i<<3)+j)<<1], tx_layers[l][(((i<<3)+j)<<1)+1]); + printf("%d %d\t", mod_symbs[0][((i<<3)+j)<<1], mod_symbs[0][(((i<<3)+j)<<1)+1]); } printf("\n"); } #endif - - /// Antenna port mapping - //to be moved to init phase potentially, for now tx_layers 1-8 are mapped on antenna ports 1000-1007 - - /// DMRS QPSK modulation - - - l0 = get_l0(rel15->dlDmrsSymbPos); - nr_modulation(pdsch_dmrs[l0][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated - + + start_meas(&gNB->dlsch_layer_mapping_stats); + /// Layer mapping + nr_layer_mapping(mod_symbs, + rel15->nrOfLayers, + nb_re, + tx_layers); #ifdef DEBUG_DLSCH - printf("DMRS modulation (single symbol %d, %d symbols, type %d):\n", l0, n_dmrs>>1, dmrs_Type); - for (int i=0; i>4; i++) { - for (int j=0; j<8; j++) { - printf("%d %d\t", mod_dmrs[((i<<3)+j)<<1], mod_dmrs[(((i<<3)+j)<<1)+1]); - } - printf("\n"); - } + printf("Layer mapping (%d layers):\n", rel15->nrOfLayers); + for (int l=0; lnrOfLayers; l++) + for (int i=0; i<(nb_re/rel15->nrOfLayers)>>3; i++) { + printf("layer %d, Re %d..%d : ",l,i<<3,(i<<3)+7); + for (int j=0; j<8; j++) { + printf("l%d %d\t", tx_layers[l][((i<<3)+j)<<1], tx_layers[l][(((i<<3)+j)<<1)+1]); + } + printf("\n"); + } #endif - - - /// Resource mapping - - // Non interleaved VRB to PRB mapping - uint16_t start_sc = frame_parms->first_carrier_offset + rel15->rbStart*NR_NB_SC_PER_RB; - if (start_sc >= frame_parms->ofdm_symbol_size) - start_sc -= frame_parms->ofdm_symbol_size; -#ifdef DEBUG_DLSCH_MAPPING - printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", - start_sc, rel15->StartSymbolIndex, rel15->rbSize, nb_re,rel15->nrOfLayers); -#endif - for (int ap=0; apnrOfLayers; ap++) { - - // DMRS params for this ap - get_Wt(Wt, ap, dmrs_Type); - get_Wf(Wf, ap, dmrs_Type); - delta = get_delta(ap, dmrs_Type); - l_prime[0] = 0; // single symbol ap 0 - uint8_t dmrs_symbol = l0+l_prime[0]; -#ifdef DEBUG_DLSCH_MAPPING - printf("DMRS Type %d params for ap %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n", - 1+dmrs_Type,ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol); -#endif - uint8_t k_prime=0; - uint16_t m=0, n=0, dmrs_idx=0, k=0; + stop_meas(&gNB->dlsch_layer_mapping_stats); + /// Resource mapping + + // Non interleaved VRB to PRB mapping + uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart+rel15->BWPStart)*NR_NB_SC_PER_RB; + if (start_sc >= frame_parms->ofdm_symbol_size) + start_sc -= frame_parms->ofdm_symbol_size; int txdataF_offset = (slot%2)*frame_parms->samples_per_slot_wCP; - if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k) - dmrs_idx = rel15->rbStart*6; - else - dmrs_idx = rel15->rbStart*4; - for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { - k = start_sc; - for (int i=0; irbSize*NR_NB_SC_PER_RB; i++) { - if ((l == dmrs_symbol) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) { - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15; - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; #ifdef DEBUG_DLSCH_MAPPING - printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n", - dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)], - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]); + printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", + start_sc, rel15->StartSymbolIndex, rel15->rbSize, nb_re,rel15->nrOfLayers); +#endif + start_meas(&gNB->dlsch_resource_mapping_stats); + for (int ap=0; apnrOfLayers; ap++) { + + // DMRS params for this ap + get_Wt(Wt, ap, dmrs_Type); + get_Wf(Wf, ap, dmrs_Type); + delta = get_delta(ap, dmrs_Type); + l_prime = 0; // single symbol ap 0 + l0 = get_l0(rel15->dlDmrsSymbPos); + l_overline = l0; + +#ifdef DEBUG_DLSCH_MAPPING + uint8_t dmrs_symbol = l0+l_prime; + printf("DMRS Type %d params for ap %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n", + 1+dmrs_Type,ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime, l0, dmrs_symbol); +#endif + + uint16_t m=0, dmrs_idx=0; + + // Loop Over OFDM symbols: + for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { + /// DMRS QPSK modulation + uint8_t k_prime=0; + uint16_t n=0; + + if ((dmrs_symbol_map & (1 << l))){ // DMRS time occasion + // The reference point for is subcarrier 0 of the lowest-numbered resource block in CORESET 0 if the corresponding + // PDCCH is associated with CORESET 0 and Type0-PDCCH common search space and is addressed to SI-RNTI + // 3GPP TS 38.211 V15.8.0 Section 7.4.1.1.2 Mapping to physical resources + if (rel15->rnti==SI_RNTI) { + if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) { + dmrs_idx = rel15->rbStart*6; + } else { + dmrs_idx = rel15->rbStart*4; + } + } else { + if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) { + dmrs_idx = (rel15->rbStart+rel15->BWPStart)*6; + } else { + dmrs_idx = (rel15->rbStart+rel15->BWPStart)*4; + } + } + if (l==(l_overline+1)) //take into account the double DMRS symbols + l_prime = 1; + else if (l>(l_overline+1)) {//new DMRS pair + l_overline = l; + l_prime = 0; + } + /// DMRS QPSK modulation + nr_modulation(pdsch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated + +#ifdef DEBUG_DLSCH + printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs, dmrs_Type); + for (int i=0; i>4; i++) { + for (int j=0; j<8; j++) { + printf("%d %d\t", mod_dmrs[((i<<3)+j)<<1], mod_dmrs[(((i<<3)+j)<<1)+1]); + } + printf("\n"); + } #endif - dmrs_idx++; - k_prime++; - k_prime&=1; - n+=(k_prime)?0:1; } - else { - if( (l != dmrs_symbol) || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) { - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15; - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15; -#ifdef DEBUG_DLSCH_MAPPING - printf("m %d\t l %d \t k %d \t txdataF: %d %d\n", - m, l, k, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)], - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]); -#endif - m++; + /* calculate if current symbol is PTRS symbols */ + ptrs_idx = 0; + + if(rel15->pduBitmap & 0x1) { + ptrs_symbol = is_ptrs_symbol(l,dlPtrsSymPos); + if(ptrs_symbol) { + /* PTRS QPSK Modulation for each OFDM symbol in a slot */ + printf("Doing ptrs modulation for symbol %d, n_ptrs %d\n",l,n_ptrs); + nr_modulation(pdsch_dmrs[l][0], (n_ptrs<<1), DMRS_MOD_ORDER, mod_ptrs); } } - if (++k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; - } + uint16_t k = start_sc; + if (ptrs_symbol || dmrs_symbol_map & (1 << l)) { + + // Loop Over SCs: + for (int i=0; irbSize*NR_NB_SC_PER_RB; i++) { + /* check if cuurent RE is PTRS RE*/ + is_ptrs_re = 0; + if (ptrs_symbol) + is_ptrs_re = is_ptrs_subcarrier(k, + rel15->rnti, + ap, + rel15->dmrsConfigType, + rel15->PTRSFreqDensity, + rel15->rbSize, + rel15->PTRSReOffset, + start_sc, + frame_parms->ofdm_symbol_size); + /* Map DMRS Symbol */ + if ( (dmrs_symbol_map & (1 << l)) && + (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) { + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15; + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; +#ifdef DEBUG_DLSCH_MAPPING + printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n", + dmrs_idx, l, k, k_prime, n, txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)], + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]); +#endif + dmrs_idx++; + k_prime++; + k_prime&=1; + n+=(k_prime)?0:1; + } + else if(is_ptrs_re){ + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[ptrs_idx<<1]) >> 15; + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[(ptrs_idx<<1) + 1])>> 15; +#ifdef DEBUG_DLSCH_MAPPING + printf("ptrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d, mod_ptrs: %d %d\n", + ptrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)], + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)],mod_ptrs[ptrs_idx<<1],mod_ptrs[(ptrs_idx<<1)+1]); +#endif + ptrs_idx++; + } + /* Map DATA Symbol */ + else if( ptrs_symbol || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,frame_parms->ofdm_symbol_size,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) { + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15; + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15; +#ifdef DEBUG_DLSCH_MAPPING + printf("m %d\t l %d \t k %d \t txdataF: %d %d\n", + m, l, k, txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)], + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]); +#endif + m++; + } + /* mute RE */ + else { + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = 0; + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = 0; + } + if (++k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; + } //RE loop + } + else { // no PTRS or DMRS in this symbol + // Loop Over SCs: + int upper_limit=rel15->rbSize*NR_NB_SC_PER_RB; + int remaining_re = 0; + if (start_sc + upper_limit > frame_parms->ofdm_symbol_size) { + remaining_re = upper_limit + start_sc - frame_parms->ofdm_symbol_size; + upper_limit = frame_parms->ofdm_symbol_size - start_sc; + } + // fix the alignment issues later, use 64-bit SIMD below instead of 128. + if (0/*(frame_parms->N_RB_DL&1)==0*/) { + __m128i *txF=(__m128i*)&txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size+start_sc+txdataF_offset)<<1)]; + + __m128i *txl = (__m128i*)&tx_layers[ap][m<<1]; + __m128i amp128=_mm_set1_epi16(amp); + for (int i=0; i<(upper_limit>>2); i++) { + txF[i] = _mm_mulhrs_epi16(amp128,txl[i]); + } //RE loop, first part + m+=upper_limit; + if (remaining_re > 0) { + txF = (__m128i*)&txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size+txdataF_offset)<<1)]; + txl = (__m128i*)&tx_layers[ap][m<<1]; + for (int i=0; i<(remaining_re>>2); i++) { + txF[i] = _mm_mulhrs_epi16(amp128,txl[i]); + } + } + } + else { + __m64 *txF=(__m64*)&txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size+start_sc+txdataF_offset)<<1)]; + + __m64 *txl = (__m64*)&tx_layers[ap][m<<1]; + __m64 amp64=_mm_set1_pi16(amp); + for (int i=0; i<(upper_limit>>1); i++) { + + txF[i] = _mm_mulhrs_pi16(amp64,txl[i]); +#ifdef DEBUG_DLSCH_MAPPING + if ((i&1) > 0) + printf("m %d\t l %d \t k %d \t txdataF: %d %d\n", + m, l, start_sc+(i>>1), txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + start_sc+(i>>1))<<1) + (2*txdataF_offset)], + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + start_sc+(i>>1))<<1) + 1 + (2*txdataF_offset)]); +#endif + /* handle this, mute RE */ + /*else { + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = 0; + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = 0; + }*/ + } //RE loop, first part + m+=upper_limit; + if (remaining_re > 0) { + txF = (__m64*)&txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size+txdataF_offset)<<1)]; + txl = (__m64*)&tx_layers[ap][m<<1]; + for (int i=0; i<(remaining_re>>1); i++) { + txF[i] = _mm_mulhrs_pi16(amp64,txl[i]); +#ifdef DEBUG_DLSCH_MAPPING + if ((i&1) > 0) + printf("m %d\t l %d \t k %d \t txdataF: %d %d\n", + m, l, i>>1, txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + (i>>1))<<1) + (2*txdataF_offset)], + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + (i>>1))<<1) + 1 + (2*txdataF_offset)]); +#endif + /* handle this, mute RE */ + /*else { + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = 0; + txdataF_precoding[ap][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = 0; + }*/ + } //RE loop, second part + } // + m+=remaining_re; + } // N_RB_DL even + } // no DMRS/PTRS in symbol + } // symbol loop + }// layer loop + stop_meas(&gNB->dlsch_resource_mapping_stats); + + ///Layer Precoding and Antenna port mapping + // tx_layers 1-8 are mapped on antenna ports 1000-1007 + // The precoding info is supported by nfapi such as num_prgs, prg_size, prgs_list and pm_idx + // The same precoding matrix is applied on prg_size RBs, Thus + // pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1 + // The Precoding matrix: + // The Codebook Type I and Type II are not supported yet. + // We`adopt the precoding matrices of PUSCH for 4 layers. + start_meas(&gNB->dlsch_precoding_stats); + + for (int ap=0; apnb_antennas_tx; ap++) { + + for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { + uint16_t k = start_sc; + + for (int rb=0; rbrbSize; rb++) { + //get pmi info + uint8_t pmi; + if (rel15->precodingAndBeamforming.prg_size > 0) + pmi = rel15->precodingAndBeamforming.prgs_list[(int)rb/rel15->precodingAndBeamforming.prg_size].pm_idx; + else + pmi = 0;//no precoding + + if (pmi == 0) {//unitary Precoding + if(apnrOfLayers) + memcpy((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset + k], + (void*)&txdataF_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + txdataF_offset+ k)], + NR_NB_SC_PER_RB*sizeof(int32_t)); + else + memset((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset + k], + 0, + NR_NB_SC_PER_RB*sizeof(int32_t)); + k += NR_NB_SC_PER_RB; + if (k >= frame_parms->ofdm_symbol_size) { + k -= frame_parms->ofdm_symbol_size; + } + } + else { + //get the precoding matrix weights: + char *W_prec; + switch (frame_parms->nb_antennas_tx) { + case 1://1 antenna port + W_prec = nr_W_1l_2p[pmi][ap]; + break; + case 2://2 antenna ports + if (rel15->nrOfLayers == 1)//1 layer + W_prec = nr_W_1l_2p[pmi][ap]; + else//2 layers + W_prec = nr_W_2l_2p[pmi][ap]; + break; + case 4://4 antenna ports + if (rel15->nrOfLayers == 1)//1 layer + W_prec = nr_W_1l_4p[pmi][ap]; + else if (rel15->nrOfLayers == 2)//2 layers + W_prec = nr_W_2l_4p[pmi][ap]; + else if (rel15->nrOfLayers == 3)//3 layers + W_prec = nr_W_3l_4p[pmi][ap]; + else//4 layers + W_prec = nr_W_4l_4p[pmi][ap]; + break; + default: + LOG_D(PHY,"Precoding 1,2, or 4 antenna ports are currently supported\n"); + W_prec = nr_W_1l_2p[pmi][ap]; + break; + } + for (int i=0; iofdm_symbol_size + k; + int32_t precodatatx_F = nr_layer_precoder(txdataF_precoding, W_prec, rel15->nrOfLayers, re_offset+txdataF_offset); + ((int16_t*)txdataF[ap])[(re_offset<<1) + (2*txdataF_offset)] = ((int16_t *) &precodatatx_F)[0]; + ((int16_t*)txdataF[ap])[(re_offset<<1) + 1 + (2*txdataF_offset)] = ((int16_t *) &precodatatx_F)[1]; +#ifdef DEBUG_DLSCH_MAPPING + printf("antenna %d\t l %d \t k %d \t txdataF: %d %d\n", + ap, l, k, ((int16_t*)txdataF[ap])[(re_offset<<1) + (2*txdataF_offset)], + ((int16_t*)txdataF[ap])[(re_offset<<1) + 1 + (2*txdataF_offset)]); +#endif + if (++k >= frame_parms->ofdm_symbol_size) { + k -= frame_parms->ofdm_symbol_size; + } + } + } + } //RB loop + } // symbol loop + }// port loop + + stop_meas(&gNB->dlsch_precoding_stats); + dlsch->slot_tx[slot]=0; + + // TODO: handle precoding + // this maps the layers onto antenna ports + + // handle beamforming ID + // each antenna port is assigned a beam_index + // since PHY can only handle BF on slot basis we set the whole slot + + // first check if this slot has not already been allocated to another beam + if (gNB->common_vars.beam_id[0][slot*frame_parms->symbols_per_slot]==255) { + for (int j=0;jsymbols_per_slot;j++) + gNB->common_vars.beam_id[0][slot*frame_parms->symbols_per_slot+j] = rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx; } - } - return 0; + else { + LOG_D(PHY,"beam index for PDSCH allocation already taken\n"); + } + }// dlsch loop +} + +void dump_pdsch_stats(FILE *fd,PHY_VARS_gNB *gNB) { + + for (int i=0;idlsch_stats[i].rnti > 0 && gNB->dlsch_stats[i].frame != gNB->dlsch_stats[i].dump_frame) { + gNB->dlsch_stats[i].dump_frame = gNB->dlsch_stats[i].frame; + fprintf(fd,"DLSCH RNTI %x: current_Qm %d, current_RI %d, total_bytes TX %d\n", + gNB->dlsch_stats[i].rnti, + gNB->dlsch_stats[i].current_Qm, + gNB->dlsch_stats[i].current_RI, + gNB->dlsch_stats[i].total_bytes_tx); + } + +} + +void clear_pdsch_stats(PHY_VARS_gNB *gNB) { + + for (int i=0;inumber_of_nr_dlsch_max;i++) + memset((void*)&gNB->dlsch_stats[i],0,sizeof(gNB->dlsch_stats[i])); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index 3a6851ee8f..77db12672f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -43,8 +43,6 @@ void nr_check_time_alloc(uint8_t S, uint8_t L,nfapi_nr_dl_tti_pdsch_pdu_rel15_t uint16_t get_RIV(uint16_t rb_start, uint16_t L, uint16_t N_RB); -uint16_t get_SLIV(uint8_t S, uint8_t L); - uint8_t nr_get_S(uint8_t row_idx, uint8_t CP, uint8_t time_alloc_type, uint8_t dmrs_typeA_position); void nr_get_rbg_parms(NR_BWP_PARMS* bwp, uint8_t config_type); @@ -63,33 +61,13 @@ void nr_pdsch_codeword_scrambling(uint8_t *in, uint32_t n_RNTI, uint32_t* out); -void nr_fill_dlsch(PHY_VARS_gNB *gNB, - int frame, - int slot, +void nr_fill_dlsch(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, unsigned char *sdu); -uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, - uint32_t ***pdsch_dmrs, - int32_t** txdataF, - int16_t amp, - int frame, - uint8_t slot, - NR_DL_FRAME_PARMS *frame_parms, - int xOverhead, - time_stats_t *dlsch_encoding_stats, - time_stats_t *dlsch_scrambling_stats, - time_stats_t *dlsch_modulation_stats, - time_stats_t *tinput, - time_stats_t *tprep, - time_stats_t *tparity, - time_stats_t *toutput, - time_stats_t *dlsch_rate_matching_stats, - time_stats_t *dlsch_interleaving_stats, - time_stats_t *dlsch_segmentation_stats); - - - +void nr_generate_pdsch(processingData_L1tx_t *msgTx, + int frame, + int slot); void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB); void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch); @@ -98,10 +76,14 @@ void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch); int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); -int nr_dlsch_encoding(unsigned char *a,int frame, +NR_gNB_SCH_STATS_t *find_nr_dlsch_stats(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); + +int nr_dlsch_encoding(PHY_VARS_gNB *gNB, + unsigned char *a,int frame, uint8_t slot, NR_gNB_DLSCH_t *dlsch, NR_DL_FRAME_PARMS* frame_parms, + unsigned char * output, time_stats_t *tinput, time_stats_t *tprep, time_stats_t *tparity, @@ -110,7 +92,11 @@ int nr_dlsch_encoding(unsigned char *a,int frame, time_stats_t *dlsch_interleaving_stats, time_stats_t *dlsch_segmentation_stats); - +void init_dlsch_tpool(uint8_t nun_dlsch_threads); void nr_emulate_dlsch_payload(uint8_t* payload, uint16_t size); +void dump_pdsch_stats(FILE *fd,PHY_VARS_gNB *gNB); + +void clear_pdsch_stats(PHY_VARS_gNB *gNB); + #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 52377ac945..5620018b73 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -39,100 +39,58 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" -#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "SCHED_NR/sched_nr.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/LOG/log.h" +#include "common/utils/nr/nr_common.h" #include +#include //#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_FREE 1 -void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB) -{ - int i; +void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB) { int r; - NR_gNB_DLSCH_t *dlsch = *dlschptr; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated - if (dlsch) { + if (dlsch) { if (N_RB != 273) { a_segments = a_segments*N_RB; - a_segments = a_segments/273; - } - - - + a_segments = a_segments/273 +1; + } + #ifdef DEBUG_DLSCH_FREE LOG_D(PHY,"Freeing dlsch %p\n",dlsch); #endif - - for (i=0; iMdlharq; i++) { + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + + if (harq->b) { + free16(harq->b, a_segments * 1056); + harq->b = NULL; #ifdef DEBUG_DLSCH_FREE - LOG_D(PHY,"Freeing dlsch process %d\n",i); + LOG_D(PHY, "Freeing harq->b (%p)\n", harq->b); #endif - - if (dlsch->harq_processes[i]) { + } + #ifdef DEBUG_DLSCH_FREE - LOG_D(PHY,"Freeing dlsch process %d (%p)\n",i,dlsch->harq_processes[i]); + LOG_D(PHY, "Freeing dlsch process %d c (%p)\n", i, harq->c); #endif - - if (dlsch->harq_processes[i]->b) { - free16(dlsch->harq_processes[i]->b,a_segments*1056); - dlsch->harq_processes[i]->b = NULL; + + for (r = 0; r < a_segments; r++) { #ifdef DEBUG_DLSCH_FREE - LOG_D(PHY,"Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b); + LOG_D(PHY, "Freeing dlsch process %d c[%d] (%p)\n", i, r, harq->c[r]); #endif - } - - if (dlsch->harq_processes[i]->e) { - free16(dlsch->harq_processes[i]->e,14*N_RB*12*8); - dlsch->harq_processes[i]->e = NULL; -#ifdef DEBUG_DLSCH_FREE - printf("Freeing dlsch process %d e (%p)\n",i,dlsch->harq_processes[i]->e); -#endif - } - - if (dlsch->harq_processes[i]->f) { - free16(dlsch->harq_processes[i]->f,14*N_RB*12*8); - dlsch->harq_processes[i]->f = NULL; -#ifdef DEBUG_DLSCH_FREE - printf("Freeing dlsch process %d f (%p)\n",i,dlsch->harq_processes[i]->f); -#endif - } - -#ifdef DEBUG_DLSCH_FREE - LOG_D(PHY,"Freeing dlsch process %d c (%p)\n",i,dlsch->harq_processes[i]->c); -#endif - - for (r=0; rharq_processes[i]->c[r]); -#endif - - if (dlsch->harq_processes[i]->c[r]) { - free16(dlsch->harq_processes[i]->c[r],1056); - dlsch->harq_processes[i]->c[r] = NULL; - } - if (dlsch->harq_processes[i]->d[r]) { - free16(dlsch->harq_processes[i]->d[r],3*8448); - dlsch->harq_processes[i]->d[r] = NULL; - } - - } - free16(dlsch->harq_processes[i],sizeof(NR_DL_gNB_HARQ_t)); - dlsch->harq_processes[i] = NULL; + + if (harq->c[r]) { + free16(harq->c[r], 1056); + harq->c[r] = NULL; } } - - free16(dlsch,sizeof(NR_gNB_DLSCH_t)); + free16(dlsch, sizeof(NR_gNB_DLSCH_t)); *dlschptr = NULL; } - } NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, @@ -140,201 +98,98 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, unsigned char Mdlharq, uint32_t Nsoft, uint8_t abstraction_flag, - uint16_t N_RB) -{ - - NR_gNB_DLSCH_t *dlsch; - unsigned char exit_flag = 0,i,r,aa,layer; + uint16_t N_RB) { + unsigned char i,r,aa,layer; int re; uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated if (N_RB != 273) { a_segments = a_segments*N_RB; - a_segments = (a_segments + 272) / 273; - } + a_segments = a_segments/273 +1; + } uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + NR_gNB_DLSCH_t *dlsch = malloc16(sizeof(NR_gNB_DLSCH_t)); + AssertFatal(dlsch, "cannot allocate dlsch\n"); + bzero(dlsch,sizeof(NR_gNB_DLSCH_t)); + dlsch->Kmimo = Kmimo; + dlsch->Mdlharq = Mdlharq; + dlsch->Mlimit = 4; + dlsch->Nsoft = Nsoft; - - dlsch = (NR_gNB_DLSCH_t *)malloc16(sizeof(NR_gNB_DLSCH_t)); + for (layer=0; layerue_spec_bf_weights[layer] = (int32_t **)malloc16(64*sizeof(int32_t *)); - if (dlsch) { - bzero(dlsch,sizeof(NR_gNB_DLSCH_t)); - dlsch->Kmimo = Kmimo; - dlsch->Mdlharq = Mdlharq; - dlsch->Mlimit = 4; - dlsch->Nsoft = Nsoft; + for (aa=0; aa<64; aa++) { + dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - for (layer=0; layerue_spec_bf_weights[layer] = (int32_t**)malloc16(64*sizeof(int32_t*)); - - for (aa=0; aa<64; aa++) { - dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - for (re=0;reue_spec_bf_weights[layer][aa][re] = 0x00007fff; - } - } - - dlsch->txdataF[layer] = (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH/NR_MAX_NB_LAYERS)*sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH - } - - for (int q=0; qmod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH*sizeof(int32_t)); - - dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(64*sizeof(int32_t*)); - for (aa=0; aa<64; aa++) { - dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - - } - - for (i=0; i<20; i++) { - dlsch->harq_ids[0][i] = 0; - dlsch->harq_ids[1][i] = 0; - } - - for (i=0; iharq_processes[i] = (NR_DL_gNB_HARQ_t *)malloc16(sizeof(NR_DL_gNB_HARQ_t)); - LOG_T(PHY, "Required mem size %d dlsch->harq_processes[%d] %p\n", - dlsch_bytes, i,dlsch->harq_processes[i]); - - if (dlsch->harq_processes[i]) { - bzero(dlsch->harq_processes[i],sizeof(NR_DL_gNB_HARQ_t)); - // dlsch->harq_processes[i]->first_tx=1; - dlsch->harq_processes[i]->b = (unsigned char*)malloc16(dlsch_bytes); - dlsch->harq_processes[i]->pdu = (uint8_t*)malloc16(dlsch_bytes); - if (dlsch->harq_processes[i]->pdu) { - bzero(dlsch->harq_processes[i]->pdu,dlsch_bytes); - nr_emulate_dlsch_payload(dlsch->harq_processes[i]->pdu, (dlsch_bytes)>>3); - } else { - LOG_D(PHY,"Can't allocate PDU\n"); - exit_flag=1; - } - - if (dlsch->harq_processes[i]->b) { - bzero(dlsch->harq_processes[i]->b,dlsch_bytes); - } else { - LOG_D(PHY,"Can't get b\n"); - exit_flag=1; - } - - if (abstraction_flag==0) { - for (r=0; rharq_processes[i]->c[r] = (uint8_t*)malloc16(8448); - dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); //max size for coded output - if (dlsch->harq_processes[i]->c[r]) { - bzero(dlsch->harq_processes[i]->c[r],8448); - } else { - LOG_D(PHY,"Can't get c\n"); - exit_flag=2; - } - if (dlsch->harq_processes[i]->d[r]) { - bzero(dlsch->harq_processes[i]->d[r],(3*8448)); - } else { - LOG_D(PHY,"Can't get d\n"); - exit_flag=2; - } - } - dlsch->harq_processes[i]->e = (uint8_t*)malloc16(14*N_RB*12*8); - if (dlsch->harq_processes[i]->e) { - bzero(dlsch->harq_processes[i]->e,14*N_RB*12*8); - } else { - printf("Can't get e\n"); - exit_flag=1; - } - dlsch->harq_processes[i]->f = (uint8_t*)malloc16(14*N_RB*12*8); - if (dlsch->harq_processes[i]->f) { - bzero(dlsch->harq_processes[i]->f,14*N_RB*12*8); - } else { - printf("Can't get f\n"); - exit_flag=1; - } - } - } else { - LOG_D(PHY,"Can't get harq_p %d\n",i); - exit_flag=3; + for (re=0; reue_spec_bf_weights[layer][aa][re] = 0x00007fff; } } - if (exit_flag==0) { - for (i=0; iharq_processes[i]->round=0; - } - - return(dlsch); - } + dlsch->txdataF[layer] = (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH/NR_MAX_NB_LAYERS)*sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH + dlsch->txdataF_precoding[layer] = (int32_t *)malloc16(2*14*frame_parms->ofdm_symbol_size*sizeof(int32_t)); } - LOG_D(PHY,"new_gNB_dlsch exit flag %d, size of %ld\n", - exit_flag, sizeof(NR_gNB_DLSCH_t)); + for (int q=0; qmod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH*sizeof(int32_t)); - free_gNB_dlsch(&dlsch,N_RB); + dlsch->calib_dl_ch_estimates = (int32_t **)malloc16(64*sizeof(int32_t *)); - return(NULL); + for (aa=0; aa<64; aa++) { + dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); + } + for (i=0; i<20; i++) { + dlsch->harq_ids[0][i] = 0; + dlsch->harq_ids[1][i] = 0; + } + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + bzero(harq, sizeof(NR_DL_gNB_HARQ_t)); + harq->b = malloc16(dlsch_bytes); + AssertFatal(harq->b, "cannot allocate memory for harq->b\n"); + harq->pdu = malloc16(dlsch_bytes); + AssertFatal(harq->pdu, "cannot allocate memory for harq->pdu\n"); + bzero(harq->pdu, dlsch_bytes); + nr_emulate_dlsch_payload(harq->pdu, (dlsch_bytes) >> 3); + bzero(harq->b, dlsch_bytes); + + for (r = 0; r < a_segments; r++) { + // account for filler in first segment and CRCs for multiple segment case + // [hna] 8448 is the maximum CB size in NR + // 68*348 = 68*(maximum size of Zc) + // In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc) + harq->c[r] = malloc16(8448); + AssertFatal(harq->c[r], "cannot allocate harq->c[%d]\n", r); + bzero(harq->c[r], 8448); + } + + return(dlsch); } -void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) -{ - - unsigned char Mdlharq; - unsigned char i,j,r; - - if (dlsch) { - Mdlharq = dlsch->Mdlharq; - dlsch->rnti = 0; - dlsch->active = 0; - - for (i=0; i<10; i++) { - dlsch->harq_ids[0][i] = Mdlharq; - dlsch->harq_ids[1][i] = Mdlharq; - } - for (i=0; iharq_processes[i]) { - // dlsch->harq_processes[i]->Ndi = 0; - //dlsch->harq_processes[i]->status = 0; - dlsch->harq_processes[i]->round = 0; - - for (j=0; j<96; j++) - for (r=0; rharq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = NR_NULL; - - } - } +void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) { + AssertFatal(dlsch!=NULL,"dlsch is null\n"); + unsigned char Mdlharq = dlsch->Mdlharq; + dlsch->rnti = 0; + dlsch->active = 0; + for (int i=0; i<10; i++) { + dlsch->harq_ids[0][i] = Mdlharq; + dlsch->harq_ids[1][i] = Mdlharq; } } -int nr_dlsch_encoding(unsigned char *a, - int frame, - uint8_t slot, - NR_gNB_DLSCH_t *dlsch, - NR_DL_FRAME_PARMS* frame_parms, - time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput, - time_stats_t *dlsch_rate_matching_stats,time_stats_t *dlsch_interleaving_stats, - time_stats_t *dlsch_segmentation_stats) -{ - - unsigned int G; - unsigned int crc=1; - uint8_t harq_pid = dlsch->harq_ids[frame%2][slot]; - AssertFatal(harq_pid<8 && harq_pid>=0,"illegal harq_pid %d\b",harq_pid); - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15; +void ldpc8blocks( void *p) { + encoder_implemparams_t *impp=(encoder_implemparams_t *) p; + NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq; + uint16_t Kr= impp->K; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + uint8_t mod_order = rel15->qamModOrder[0]; uint16_t nb_rb = rel15->rbSize; uint8_t nb_symb_sch = rel15->NrOfSymbols; - uint32_t A, Z, Kb, F=0; - uint32_t *Zc = &Z; - uint8_t mod_order = rel15->qamModOrder[0]; - uint16_t Kr=0,r; - uint32_t r_offset=0; - uint8_t BG=1; - uint32_t E; - uint8_t Ilbrm = 1; - uint32_t Tbslbrm = 950984; //max tbs + uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos); + uint32_t A = rel15->TBSize[0]<<3; uint8_t nb_re_dmrs; if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) @@ -342,204 +197,215 @@ int nr_dlsch_encoding(unsigned char *a, else nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; - uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos); - uint16_t R=rel15->targetCodeRate[0]; - float Coderate = 0.0; - uint8_t Nl = 4; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); - - A = rel15->TBSize[0]<<3; - - G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); - - LOG_D(PHY,"dlsch coding A %d G %d mod_order %d\n", A,G, mod_order); - - // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet -#ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"encoding thinks this is a new packet \n"); -#endif - /* - int i; - LOG_D(PHY,"dlsch (tx): \n"); - for (i=0;i<(A>>3);i++) - LOG_D(PHY,"%02x\n",a[i]); - LOG_D(PHY,"\n"); - */ - - if (A > 3824) { - // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a,A)>>8; - a[A>>3] = ((uint8_t*)&crc)[2]; - a[1+(A>>3)] = ((uint8_t*)&crc)[1]; - a[2+(A>>3)] = ((uint8_t*)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); - - dlsch->harq_processes[harq_pid]->B = A+24; - // dlsch->harq_processes[harq_pid]->b = a; - - AssertFatal((A/8)+4 <= MAX_NR_DLSCH_PAYLOAD_BYTES,"A %d is too big (A/8+4 = %d > %d)\n",A,(A/8)+4,MAX_NR_DLSCH_PAYLOAD_BYTES); - - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); // why is this +4 if the CRC is only 3 bytes? - } - else { - // Add 16-bit crc (polynomial A) to payload - crc = crc16(a,A)>>16; - a[A>>3] = ((uint8_t*)&crc)[1]; - a[1+(A>>3)] = ((uint8_t*)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); - - dlsch->harq_processes[harq_pid]->B = A+16; - // dlsch->harq_processes[harq_pid]->b = a; - - AssertFatal((A/8)+3 <= MAX_NR_DLSCH_PAYLOAD_BYTES,"A %d is too big (A/8+3 = %d > %d)\n",A,(A/8)+3,MAX_NR_DLSCH_PAYLOAD_BYTES); - - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+3); // using 3 bytes to mimic the case of 24 bit crc - } - if (R<1000) - Coderate = (float) R /(float) 1024; - else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools - Coderate = (float) R /(float) 2048; - - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) - BG = 2; - else - BG = 1; - - start_meas(dlsch_segmentation_stats); - Kb = nr_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->K, - Zc, - &dlsch->harq_processes[harq_pid]->F, - BG); - stop_meas(dlsch_segmentation_stats); - F = dlsch->harq_processes[harq_pid]->F; - - Kr = dlsch->harq_processes[harq_pid]->K; -#ifdef DEBUG_DLSCH_CODING - uint16_t Kr_bytes; - Kr_bytes = Kr>>3; -#endif - - //printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,dlsch->harq_processes[harq_pid]->K,Kr,BG,dlsch->harq_processes[harq_pid]->C); - - for (r=0; rharq_processes[harq_pid]->C; r++) { - //d_tmp[r] = &dlsch->harq_processes[harq_pid]->d[r][0]; - //channel_input[r] = &dlsch->harq_processes[harq_pid]->d[r][0]; -#ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"Encoder: B %d F %d \n",dlsch->harq_processes[harq_pid]->B, dlsch->harq_processes[harq_pid]->F); - LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,dlsch->harq_processes[harq_pid]->C); - LOG_D(PHY,"input %d %d %d %d %d \n", dlsch->harq_processes[harq_pid]->c[r][0], dlsch->harq_processes[harq_pid]->c[r][1], dlsch->harq_processes[harq_pid]->c[r][2],dlsch->harq_processes[harq_pid]->c[r][3], dlsch->harq_processes[harq_pid]->c[r][4]); - for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++){ - LOG_D(PHY,"%d ", dlsch->harq_processes[harq_pid]->c[r][cnt]); - } - LOG_D(PHY,"\n"); - -#endif - //ldpc_encoder_orig((unsigned char*)dlsch->harq_processes[harq_pid]->c[r],dlsch->harq_processes[harq_pid]->d[r],*Zc,Kb,Kr,BG,0); - //ldpc_encoder_optim((unsigned char*)dlsch->harq_processes[harq_pid]->c[r],(unsigned char*)&dlsch->harq_processes[harq_pid]->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL); - } - encoder_implemparams_t impp; - impp.n_segments=dlsch->harq_processes[harq_pid]->C; - impp.tprep = tprep; - impp.tinput = tinput; - impp.tparity = tparity; - impp.toutput = toutput; - - for(int j=0;j<(dlsch->harq_processes[harq_pid]->C/8+1);j++) { - impp.macro_num=j; - nrLDPC_encoder(dlsch->harq_processes[harq_pid]->c,dlsch->harq_processes[harq_pid]->d,*Zc,Kb,Kr,BG,&impp); + unsigned int G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); + LOG_D(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", + A,impp->K,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,(int)mod_order); + // nrLDPC_encoder output is in "d" + // let's make this interface happy! + uint8_t tmp[8][68 * 384]__attribute__((aligned(32))); + for (int rr=impp->macro_num*8, i=0; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++,i++ ) + impp->d[rr]=tmp[i]; + nrLDPC_encoder(harq->c,impp->d,*impp->Zc, impp->Kb,Kr,impp->BG,impp); + // Compute where to place in output buffer that is concatenation of all segments + uint32_t r_offset=0; + for (int i=0; i < impp->macro_num*8; i++ ) + r_offset+=nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, i); + for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) { + if (impp->F>0) { + // writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212 + memset(&impp->d[rr][Kr-impp->F-2*(*impp->Zc)], impp->F, NR_NULL); } - #ifdef DEBUG_DLSCH_CODING - write_output("enc_input0.m","enc_in0",&dlsch->harq_processes[harq_pid]->c[0][0],Kr_bytes,1,4); - write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[0][0],(3*8*Kr_bytes)+12,1,4); + LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]); #endif - - } - - F = dlsch->harq_processes[harq_pid]->F; - - Kr = dlsch->harq_processes[harq_pid]->K; - for (r=0; rharq_processes[harq_pid]->C; r++) { - - if (F>0) { - for (int k=(Kr-F-2*(*Zc)); kharq_processes[harq_pid]->d[r][k] = NR_NULL; - //if (k<(Kr-F+8)) - //printf("r %d filler bits [%d] = %d \n", r,k, dlsch->harq_processes[harq_pid]->d[r][k]); - } - } - - - -#ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]); -#endif - - E = nr_get_E(G, dlsch->harq_processes[harq_pid]->C, mod_order, rel15->nrOfLayers, r); - + uint32_t E = nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, rr); //#ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d)...\n", - r, - dlsch->harq_processes[harq_pid]->C, - G, - E, - F, - Kr-F-2*(*Zc), - mod_order,nb_rb); - + LOG_D(NR_PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d)...\n", + rr, + impp->n_segments, + G, + E, + impp->F, + Kr-impp->F-2*(*impp->Zc), + mod_order,nb_rb); // for tbslbrm calculation according to 5.4.2.1 of 38.212 + uint8_t Nl = 4; + if (rel15->nrOfLayers < Nl) Nl = rel15->nrOfLayers; - Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl,dlsch->harq_processes[harq_pid]->C); + uint32_t Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl); + uint8_t Ilbrm = 1; - start_meas(dlsch_rate_matching_stats); + uint8_t e[E]; + bzero (e, E); nr_rate_matching_ldpc(Ilbrm, Tbslbrm, - BG, - *Zc, - dlsch->harq_processes[harq_pid]->d[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, - F, - Kr-F-2*(*Zc), + impp->BG, + *impp->Zc, + impp->d[rr], + e, + impp->n_segments, + impp->F, + Kr-impp->F-2*(*impp->Zc), rel15->rvIndex[0], E); - stop_meas(dlsch_rate_matching_stats); #ifdef DEBUG_DLSCH_CODING - for (int i =0; i<16; i++) - printf("output ratematching e[%d]= %d r_offset %u\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset); -#endif - start_meas(dlsch_interleaving_stats); + for (int i =0; i<16; i++) + printf("output ratematching e[%d]= %d r_offset %u\n", i,harq->e[i+r_offset], r_offset); + +#endif nr_interleaving_ldpc(E, - mod_order, - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->f+r_offset); - stop_meas(dlsch_interleaving_stats); - + mod_order, + e, + impp->output+r_offset); #ifdef DEBUG_DLSCH_CODING + for (int i =0; i<16; i++) - printf("output interleaving f[%d]= %d r_offset %u\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset); + printf("output interleaving f[%d]= %d r_offset %u\n", i,impp->output[i+r_offset], r_offset); + + if (r==impp->n_segments-1) + write_output("enc_output.m","enc",impp->output,G,1,4); - if (r==dlsch->harq_processes[harq_pid]->C-1) - write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,G,1,4); #endif - r_offset += E; } +} +int nr_dlsch_encoding(PHY_VARS_gNB *gNB, + unsigned char *a, + int frame, + uint8_t slot, + NR_gNB_DLSCH_t *dlsch, + NR_DL_FRAME_PARMS *frame_parms, + unsigned char * output, + time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput, + time_stats_t *dlsch_rate_matching_stats,time_stats_t *dlsch_interleaving_stats, + time_stats_t *dlsch_segmentation_stats) { + encoder_implemparams_t impp; + impp.output=output; + unsigned int crc=1; + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + impp.Zc = &dlsch->harq_process.Z; + float Coderate = 0.0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); + uint32_t A = rel15->TBSize[0]<<3; + + if ( dlsch->rnti != SI_RNTI ) + trace_NRpdu(DIRECTION_DOWNLINK, a, rel15->TBSize[0], 0, WS_C_RNTI, dlsch->rnti, frame, slot,0, 0); + + NR_gNB_SCH_STATS_t *stats=NULL; + int first_free=-1; + + for (int i=0; idlsch_stats[i].rnti == 0 && first_free == -1) { + first_free = i; + stats=&gNB->dlsch_stats[i]; + } + + if (gNB->dlsch_stats[i].rnti == dlsch->rnti) { + stats=&gNB->dlsch_stats[i]; + break; + } + } + + if (stats) { + stats->rnti = dlsch->rnti; + stats->total_bytes_tx += rel15->TBSize[0]; + stats->current_RI = rel15->nrOfLayers; + stats->current_Qm = rel15->qamModOrder[0]; + } + + if (A > 3824) { + // Add 24-bit crc (polynomial A) to payload + crc = crc24a(a,A)>>8; + a[A>>3] = ((uint8_t *)&crc)[2]; + a[1+(A>>3)] = ((uint8_t *)&crc)[1]; + a[2+(A>>3)] = ((uint8_t *)&crc)[0]; + //printf("CRC %x (A %d)\n",crc,A); + //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); + harq->B = A+24; + // harq->b = a; + AssertFatal((A / 8) + 4 <= MAX_NR_DLSCH_PAYLOAD_BYTES, + "A %d is too big (A/8+4 = %d > %d)\n", + A, + (A / 8) + 4, + MAX_NR_DLSCH_PAYLOAD_BYTES); + memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? + } else { + // Add 16-bit crc (polynomial A) to payload + crc = crc16(a,A)>>16; + a[A>>3] = ((uint8_t *)&crc)[1]; + a[1+(A>>3)] = ((uint8_t *)&crc)[0]; + //printf("CRC %x (A %d)\n",crc,A); + //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); + harq->B = A+16; + // harq->b = a; + AssertFatal((A / 8) + 3 <= MAX_NR_DLSCH_PAYLOAD_BYTES, + "A %d is too big (A/8+3 = %d > %d)\n", + A, + (A / 8) + 3, + MAX_NR_DLSCH_PAYLOAD_BYTES); + memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc + } + + if (rel15->targetCodeRate[0]<1000) + Coderate = (float)rel15->targetCodeRate[0] /(float) 1024; + else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools + Coderate = (float)rel15->targetCodeRate[0] /(float) 2048; + + if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) + impp.BG = 2; + else + impp.BG = 1; + + start_meas(dlsch_segmentation_stats); + impp.Kb = nr_segmentation(harq->b, harq->c, harq->B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG); + stop_meas(dlsch_segmentation_stats); + + for (int r=0; rd[r][0]; + //channel_input[r] = &harq->d[r][0]; +#ifdef DEBUG_DLSCH_CODING + LOG_D(PHY,"Encoder: B %d F %d \n",harq->B, impp->F); + LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,impp.n_segments); + LOG_D(PHY,"input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2],harq->c[r][3], harq->c[r][4]); + + for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++) { + LOG_D(PHY,"%d ", harq->c[r][cnt]); + } + + LOG_D(PHY,"\n"); +#endif + //ldpc_encoder_orig((unsigned char*)harq->c[r],harq->d[r],*Zc,Kb,Kr,BG,0); + //ldpc_encoder_optim((unsigned char*)harq->c[r],(unsigned char*)&harq->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL); + } + + impp.tprep = tprep; + impp.tinput = tinput; + impp.tparity = tparity; + impp.toutput = toutput; + + impp.harq=harq; + notifiedFIFO_t nf; + initNotifiedFIFO(&nf); + int nbJobs=0; + for(int j=0; j<(impp.n_segments/8+((impp.n_segments&7)==0 ? 0 : 1)); j++) { + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks); + encoder_implemparams_t* perJobImpp=(encoder_implemparams_t*)NotifiedFifoData(req); + *perJobImpp=impp; + perJobImpp->macro_num=j; + pushTpool(gNB->threadPool,req); + nbJobs++; + } + while(nbJobs) { + notifiedFIFO_elt_t *req=pullTpool(&nf, gNB->threadPool); + delNotifiedFIFO_elt(req); + nbJobs--; + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT); - return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 7702d770ee..26b45eb9f7 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -96,11 +96,6 @@ void nr_get_time_domain_allocation_type(nfapi_nr_config_request_t config, } } - -uint16_t get_SLIV(uint8_t S, uint8_t L) { - return ( (uint16_t)(((L-1)<=7)? (14*(L-1)+S) : (14*(15-L)+(13-S))) ); -} - static inline uint8_t get_K0(uint8_t row_idx, uint8_t time_alloc_type) { return ( (time_alloc_type == NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A)|| (time_alloc_type == NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_C)? 0 : @@ -254,47 +249,16 @@ void nr_emulate_dlsch_payload(uint8_t* pdu, uint16_t size) { *(pdu+i) = (uint8_t)rand(); } -int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { - - uint16_t i; - int16_t first_free_index=-1; - - AssertFatal(gNB!=NULL,"gNB is null\n"); - for (i=0; idlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i); - AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i); - LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); - if ((gNB->dlsch[i][0]->harq_mask >0) && - (gNB->dlsch[i][0]->rnti==rnti)) return i; - else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; - } - if (type == SEARCH_EXIST) return -1; - if (first_free_index != -1) - gNB->dlsch[first_free_index][0]->rnti = 0; - return first_free_index; -} - - - -void nr_fill_dlsch(PHY_VARS_gNB *gNB, - int frame, - int slot, +void nr_fill_dlsch(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu) { - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &pdsch_pdu->pdsch_pdu_rel15; - - int dlsch_id = find_nr_dlsch(rel15->rnti,gNB,SEARCH_EXIST); - AssertFatal( (dlsch_id>=0) && (dlsch_idrnti,dlsch_id); - NR_gNB_DLSCH_t *dlsch = gNB->dlsch[dlsch_id][0]; - NR_DL_gNB_HARQ_t **harq = dlsch->harq_processes; + NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[msgTx->num_pdsch_slot][0]; + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; /// DLSCH struct - memcpy((void*)&harq[dlsch->harq_ids[frame%2][slot]]->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu)); - gNB->num_pdsch_rnti++; + memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + msgTx->num_pdsch_slot++; AssertFatal(sdu!=NULL,"sdu is null\n"); - harq[dlsch->harq_ids[frame%2][slot]]->pdu = sdu; - - + harq->pdu = sdu; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index bd1278b2eb..a4cec432de 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -42,7 +42,7 @@ extern short nr_qpsk_mod_table[8]; -uint8_t nr_pbch_payload_interleaving_pattern[32] = {16, 23, 18, 17, 8, 30, 10, 6, 24, 7, 0, 5, 3, 2, 1, 4, +const uint8_t nr_pbch_payload_interleaving_pattern[32] = {16, 23, 18, 17, 8, 30, 10, 6, 24, 7, 0, 5, 3, 2, 1, 4, 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31 }; @@ -141,7 +141,7 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, return 0; } -void nr_pbch_scrambling(NR_gNB_PBCH *pbch, +static void nr_pbch_scrambling(NR_gNB_PBCH *pbch, uint32_t Nid, uint8_t nushift, uint16_t M, @@ -241,7 +241,7 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, ///Payload generation memset((void *)pbch, 0, sizeof(NR_gNB_PBCH)); pbch->pbch_a=0; - uint8_t ssb_index = frame_parms->ssb_index; + uint8_t ssb_index = ssb_pdu->ssb_pdu_rel15.SsbBlockIndex; uint8_t *pbch_pdu = (uint8_t*)&ssb_pdu->ssb_pdu_rel15.bchPayload; uint8_t Lmax = frame_parms->Lmax; for (int i=0; iprach_vars.list[i].frame=-1; + for (int i=0; iprach_vars.list[i].frame = -1; + gNB->prach_vars.list[i].slot = -1; + } } -int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, int numRA, find_type_t type) { +void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id) { - uint16_t i; - int16_t first_free_index=-1; + gNB->prach_vars.list[prach_id].frame = -1; + gNB->prach_vars.list[prach_id].slot = -1; + +} + +int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) { AssertFatal(gNB!=NULL,"gNB is null\n"); - for (i=0; i %d.%d numRA %d\n", frame,slot,numRA,i, - gNB->prach_vars.list[i].frame,gNB->prach_vars.list[i].slot,gNB->prach_vars.list[i].pdu.num_ra); - if ((gNB->prach_vars.list[i].frame == frame) && - (gNB->prach_vars.list[i].slot == slot) && - (gNB->prach_vars.list[i].pdu.num_ra == numRA)) return i; - else if ((gNB->prach_vars.list[i].frame == -1) && (first_free_index==-1)) first_free_index=i; + for (uint16_t i=0; i %d.%d\n", frame,slot,i, + gNB->prach_vars.list[i].frame,gNB->prach_vars.list[i].slot); + if((type == SEARCH_EXIST_OR_FREE) && + (gNB->prach_vars.list[i].frame == -1) && + (gNB->prach_vars.list[i].slot == -1)) { + return i; + } + else if ((type == SEARCH_EXIST) && + (gNB->prach_vars.list[i].frame == frame) && + (gNB->prach_vars.list[i].slot == slot)) { + return i; + } } - if (type == SEARCH_EXIST) return -1; - - return first_free_index; + return -1; } void nr_fill_prach(PHY_VARS_gNB *gNB, @@ -69,9 +80,9 @@ void nr_fill_prach(PHY_VARS_gNB *gNB, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) { - int prach_id = find_nr_prach(gNB,SFN,Slot,prach_pdu->num_ra,SEARCH_EXIST_OR_FREE); - AssertFatal( (prach_id>=0) && (prach_idnum_ra,prach_id); + int prach_id = find_nr_prach(gNB,SFN,Slot,SEARCH_EXIST_OR_FREE); + AssertFatal( ((prach_id>=0) && (prach_idprach_vars.list[prach_id].frame=SFN; gNB->prach_vars.list[prach_id].slot=Slot; @@ -82,31 +93,35 @@ void nr_fill_prach(PHY_VARS_gNB *gNB, void init_prach_ru_list(RU_t *ru) { AssertFatal(ru!=NULL,"ruis null\n"); - for (int i=0; iprach_list[i].frame=-1; + for (int i=0; iprach_list[i].frame = -1; + ru->prach_list[i].slot = -1; + } pthread_mutex_init(&ru->prach_list_mutex,NULL); } int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type) { - uint16_t i; - int16_t first_free_index=-1; - AssertFatal(ru!=NULL,"ru is null\n"); pthread_mutex_lock(&ru->prach_list_mutex); - for (i=0; i %d.%d\n", frame,slot,i, ru->prach_list[i].frame,ru->prach_list[i].slot); - if ((ru->prach_list[i].frame == frame) && - (ru->prach_list[i].slot == slot)) { + if((type == SEARCH_EXIST_OR_FREE) && + (ru->prach_list[i].frame == -1) && + (ru->prach_list[i].slot == -1)) { + pthread_mutex_unlock(&ru->prach_list_mutex); + return i; + } + else if ((type == SEARCH_EXIST) && + (ru->prach_list[i].frame == frame) && + (ru->prach_list[i].slot == slot)) { pthread_mutex_unlock(&ru->prach_list_mutex); return i; } - else if ((ru->prach_list[i].frame == -1) && (first_free_index==-1)) first_free_index=i; } pthread_mutex_unlock(&ru->prach_list_mutex); - if (type == SEARCH_EXIST) return -1; - - return first_free_index; + return -1; } void nr_fill_prach_ru(RU_t *ru, @@ -115,7 +130,7 @@ void nr_fill_prach_ru(RU_t *ru, nfapi_nr_prach_pdu_t *prach_pdu) { int prach_id = find_nr_prach_ru(ru,SFN,Slot,SEARCH_EXIST_OR_FREE); - AssertFatal( (prach_id>=0) && (prach_id=0) && (prach_idprach_list_mutex); @@ -124,6 +139,7 @@ void nr_fill_prach_ru(RU_t *ru, ru->prach_list[prach_id].fmt = prach_pdu->prach_format; ru->prach_list[prach_id].numRA = prach_pdu->num_ra; ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol; + ru->prach_list[prach_id].num_prach_ocas = prach_pdu->num_prach_ocas; pthread_mutex_unlock(&ru->prach_list_mutex); } @@ -132,7 +148,8 @@ void free_nr_ru_prach_entry(RU_t *ru, int prach_id) { pthread_mutex_lock(&ru->prach_list_mutex); - ru->prach_list[prach_id].frame=-1; + ru->prach_list[prach_id].frame = -1; + ru->prach_list[prach_id].slot = -1; pthread_mutex_unlock(&ru->prach_list_mutex); } @@ -142,6 +159,7 @@ void rx_nr_prach_ru(RU_t *ru, int prachFormat, int numRA, int prachStartSymbol, + int prachOccasion, int frame, int slot) { @@ -156,15 +174,25 @@ void rx_nr_prach_ru(RU_t *ru, int msg1_frequencystart = ru->config.prach_config.num_prach_fd_occasions_list[numRA].k1.value; - rxsigF = ru->prach_rxsigF; + int sample_offset_slot; + if (!(slot%(fp->slots_per_subframe/2))) + sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1)); + else + sample_offset_slot = (prachStartSymbol==0?0:prachStartSymbol*(fp->ofdm_symbol_size+fp->nb_prefix_samples)); + //to be checked for mu=0; + + LOG_D(PHY,"frame %d, slot %d: doing rx_nr_prach_ru for format %d, numRA %d, prachStartSymbol %d, prachOccasion %d\n",frame,slot,prachFormat,numRA,prachStartSymbol,prachOccasion); + + rxsigF = ru->prach_rxsigF[prachOccasion]; AssertFatal(ru->if_south == LOCAL_RF,"we shouldn't call this if if_south != LOCAL_RF\n"); for (int aa=0; aanb_rx; aa++){ if (prach_sequence_length == 0) slot2=(slot/fp->slots_per_subframe)*fp->slots_per_subframe; - prach[aa] = (int16_t*)&ru->common.rxdata[aa][(slot2*fp->get_samples_per_slot(slot,fp))-ru->N_TA_offset]; + prach[aa] = (int16_t*)&ru->common.rxdata[aa][fp->get_samples_slot_timestamp(slot2,fp,0)+sample_offset_slot-ru->N_TA_offset]; } + idft_size_idx_t dftsize; int dftlen=0; int mu = fp->numerology_index; int Ncp = 0; @@ -198,22 +226,24 @@ void rx_nr_prach_ru(RU_t *ru, ru->idx,frame,slot,prachfmt[prachFormat],msg1_frequencystart,prachStartSymbol); switch (prachFormat) { - case 0: //A1 + case 4: //A1 Ncp = 288/(1<nb_rx, Ncp); } - AssertFatal(mu==1,"only 30 kHz SCS handled for now\n"); + + // Note: Assumes PUSCH SCS @ 30 kHz, take values for formats 0-2 and adjust for others below int kbar = 1; @@ -265,242 +296,361 @@ void rx_nr_prach_ru(RU_t *ru, if (k<0) k+=(fp->ofdm_symbol_size); k*=K; - k+=kbar; + k+=kbar; + int reps=1; for (int aa=0; aanb_rx; aa++) { AssertFatal(prach[aa]!=NULL,"prach[%d] is null\n",aa); // do DFT - if (fp->N_RB_UL <= 100) - AssertFatal(1==0,"N_RB_UL %d not support for NR PRACH yet\n",fp->N_RB_UL); - else if (fp->N_RB_UL < 137) { - if (fp->threequarter_fs==0) { - //40 MHz @ 61.44 Ms/s - //50 MHz @ 61.44 Ms/s - prach2 = prach[aa] + (Ncp<<2); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 to bring to 61.44 Ms/s - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=49152; - dft(DFT_49152,prach2,rxsigF[aa],1); + if (mu==1) { + switch(fp->samples_per_subframe) { + case 15360: + // 10, 15 MHz @ 15.36 Ms/s + prach2 = prach[aa] + (1*Ncp); // Ncp is for 30.72 Ms/s, so divide by 2 to bring to 15.36 Ms/s and multiply by 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=12288; + dft(DFT_12288,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_12288,prach2+24576,rxsigF[aa]+24576,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_12288,prach2+(24576*2),rxsigF[aa]+(24576*2),1); + dft(DFT_12288,prach2+(24576*3),rxsigF[aa]+(24576*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=3072; + for (int i=0;i<4;i++) dft(DFT_3072,prach2+(i*3072*2),rxsigF[aa]+(i*3072*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=16; // 8 samples @ 15.36 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=512; + dft(DFT_512,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_512,prach2+1024,rxsigF[aa]+1024,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_512,prach2+1024*2,rxsigF[aa]+1024*2,1); + dft(DFT_512,prach2+1024*3,rxsigF[aa]+1024*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_512,prach2+1024*4,rxsigF[aa]+1024*4,1); + dft(DFT_512,prach2+1024*5,rxsigF[aa]+1024*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_512,prach2+(1024*i),rxsigF[aa]+(1024*i),1); + reps+=6; + } } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1); - dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=12288; - for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); - reps=4; - } - }// 839 sequence - else { - if ((mu==0 && - (prachStartSymbol == 0 || prachStartSymbol == 7)) || - (mu==1 && prachStartSymbol == 0)) prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) + break; + + case 30720: + // 20, 25, 30 MHz @ 30.72 Ms/s + prach2 = prach[aa] + (2*Ncp); // Ncp is for 30.72 Ms/s, so just multiply by 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=24576; + dft(DFT_24576,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_24576,prach2+49152,rxsigF[aa]+49152,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_24576,prach2+(49152*2),rxsigF[aa]+(49152*2),1); + dft(DFT_24576,prach2+(49152*3),rxsigF[aa]+(49152*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=6144; + for (int i=0;i<4;i++) dft(DFT_6144,prach2+(i*6144*2),rxsigF[aa]+(i*6144*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=32; // 16 samples @ 30.72 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=1024; + dft(DFT_1024,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_1024,prach2+2048,rxsigF[aa]+2048,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_1024,prach2+2048*2,rxsigF[aa]+2048*2,1); + dft(DFT_1024,prach2+2048*3,rxsigF[aa]+2048*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_1024,prach2+2048*4,rxsigF[aa]+2048*4,1); + dft(DFT_1024,prach2+2048*5,rxsigF[aa]+2048*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_1024,prach2+(2048*i),rxsigF[aa]+(2048*i),1); + reps+=6; + } + } + break; + + case 61440: + // 40, 50, 60 MHz @ 61.44 Ms/s + prach2 = prach[aa] + (4*Ncp); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 to bring to 61.44 Ms/s + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=49152; + dft(DFT_49152,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1); + dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=12288; + for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) - if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==1) { dftlen=2048; dft(DFT_2048,prach2,rxsigF[aa],1); - if (prachFormat != 7) { // !=C0 - dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); - reps++; - } - if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { + if (prachFormat != 9/*C0*/) { + dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1); dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1); - reps+=2; - } - if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) { + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1); dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1); - reps+=2; - } - if (prachFormat == 6) { - for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); - reps+=6; - } - } - else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); - } - } else { // threequarter sampling - // 40 MHz @ 46.08 Ms/s - prach2 = prach[aa] + (3*Ncp); // 46.08 is 1.5 * 30.72, times 2 for I/Q - if (prach_sequence_length == 0) { - AssertFatal(fp->N_RB_UL <= 107,"cannot do 108..136 PRBs with 3/4 sampling\n"); - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=36864; - dft(DFT_36864,prach2,rxsigF[aa],1); - reps++; - } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1); - dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=9216; - for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); - reps=4; - } - } else { - if ((mu==0 && - (prachStartSymbol == 0 || prachStartSymbol == 7)) || - (mu==1 && prachStartSymbol == 0)) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only) - if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==1) { - dftlen=1536; - dft(DFT_1536,prach2,rxsigF[aa],1); - if (prachFormat != 7) { - dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); - reps++; - } - - if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { - dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1); - dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1); - reps+=2; - } - if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) { - dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1); - dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1); - reps+=2; - } - if (prachFormat == 6) { - for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); - reps+=6; - } - }// mu==1 - else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); - } // short format - } // 3/4 sampling - } // <=50 MHz BW - else if (fp->N_RB_UL <= 273) { - if (fp->threequarter_fs==0) { - prach2 = prach[aa] + (Ncp<<3); - //80,90,100 MHz @ 122.88 Ms/s - - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=98304; - dft(DFT_98304,prach2,rxsigF[aa],1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); + reps+=6; + } } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_98304,prach2+(196608*2),rxsigF[aa]+(196608*2),1); - dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=24576; - for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); - reps=4; - } - } - else { - if ((mu==0 && - (prachStartSymbol == 0 || prachStartSymbol == 7)) || - (mu==1 && prachStartSymbol == 0)) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + break; - if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==1) { - dftlen=4096; - dft(DFT_4096,prach2,rxsigF[aa],1); - if (prachFormat != 7) { //!=C0 - dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); - reps++; - } - - if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { + case 46080: + // 40 MHz @ 46.08 Ms/s + prach2 = prach[aa] + (3*Ncp); // 46.08 is 1.5 * 30.72, times 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=36864; + dft(DFT_36864,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1); + dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=9216; + for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=1536; + dft(DFT_1536,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1); + dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1); + dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); + reps+=6; + } + } + break; + + case 122880: + // 70, 80, 90, 100 MHz @ 122.88 Ms/s + prach2 = prach[aa] + (8*Ncp); + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=98304; + dft(DFT_98304,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_98304,prach2+(196608*2),rxsigF[aa]+(196608*2),1); + dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=24576; + for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=4096; + dft(DFT_4096,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1); dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1); - reps+=2; - } - if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) { + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1); dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1); - reps+=2; - } - if (prachFormat == 6) { - for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); - reps+=6; - } - } - else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); - } - } else { - AssertFatal(fp->N_RB_UL <= 217,"cannot do more than 217 PRBs with 3/4 sampling\n"); - prach2 = prach[aa] + (6*Ncp); - // 80 MHz @ 92.16 Ms/s - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=73728; - dft(DFT_73728,prach2,rxsigF[aa],1); - reps++; - } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_73728,prach2+(2*73728),rxsigF[aa]+(2*73728),1); - reps++; - } - if (prachFormat == 3) { - dftlen=18432; - for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); - reps=4; - } - } else { - if ((mu==0 && - (prachStartSymbol == 0 || prachStartSymbol == 7)) || - (mu==1 && prachStartSymbol == 0)) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); + reps+=6; + } + } + break; - if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==1) { - dftlen=3072; - dft(DFT_3072,prach2,rxsigF[aa],1); - if (prachFormat != 7) { //!=C0 - dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); - reps++; - } - - if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { + case 92160: + // 80, 90 MHz @ 92.16 Ms/s + prach2 = prach[aa] + (6*Ncp); + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=73728; + dft(DFT_73728,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_73728,prach2+147456,rxsigF[aa]+147456,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_73728,prach2+(147456*2),rxsigF[aa]+(147456*2),1); + dft(DFT_73728,prach2+(147456*3),rxsigF[aa]+(147456*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=18432; + for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); + reps=4; + } + } else { + if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=3072; + dft(DFT_3072,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1); dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1); - reps+=2; - } - if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) { + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1); dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1); - reps+=2; - } - if (prachFormat == 6) { - for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); - reps+=6; - } - } - else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); - } + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); + reps+=6; + } + } + break; + default: + AssertFatal(1==0,"sample_rate %f MHz not support for NR PRACH yet\n", fp->samples_per_subframe / 1000.0); } } + else if (mu==3) { + if (fp->threequarter_fs) { + AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu); + } + if (prach_sequence_length == 0) { + AssertFatal(1==0,"long prach not supported for numerology %d\n",mu); + } + if (fp->N_RB_UL == 32) { + prach2 = prach[aa] + (Ncp<<2); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 for 61.44Msps + if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe + dftlen=512; + dftsize = DFT_512; + } + else if (fp->N_RB_UL == 66) { + prach2 = prach[aa] + (Ncp<<3); // Ncp is for 30.72 Ms/s, so multiply by 4 for I/Q, and 2 for 122.88Msps + if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe + dftlen=1024; + dftsize = DFT_1024; + } + else { + AssertFatal(1==0,"N_RB_UL %d not support for numerology %d\n",fp->N_RB_UL,mu); + } + + dft(dftsize,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(dftsize,prach2+dftlen*2,rxsigF[aa]+dftlen*2,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(dftsize,prach2+dftlen*4,rxsigF[aa]+dftlen*4,1); + dft(dftsize,prach2+dftlen*6,rxsigF[aa]+dftlen*6,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(dftsize,prach2+dftlen*8,rxsigF[aa]+dftlen*8,1); + dft(dftsize,prach2+dftlen*10,rxsigF[aa]+dftlen*10,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) + dft(dftsize,prach2+(dftlen*2*i),rxsigF[aa]+(dftlen*2*i),1); + reps+=6; + } + } + else { + AssertFatal(1==0,"Numerology not supported\n"); + } + + //LOG_M("ru_rxsigF_tmp.m","rxsFtmp", rxsigF[aa], dftlen*2*reps, 1, 1); //Coherent combining of PRACH repetitions (assumes channel does not change, to be revisted for "long" PRACH) LOG_D(PHY,"Doing PRACH combining of %d reptitions N_ZC %d\n",reps,N_ZC); @@ -515,13 +665,13 @@ void rx_nr_prach_ru(RU_t *ru, for (int i=1;iframe_parms; nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value; - - rootSequenceIndex = cfg->num_prach_fd_occasions_list[0].prach_root_sequence_index.value; - numrootSequenceIndex = cfg->num_prach_fd_occasions_list[0].num_root_sequences.value; + rootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].prach_root_sequence_index.value; + numrootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].num_root_sequences.value; NCS = prach_pdu->num_cs;//cfg->num_prach_fd_occasions_list[0].prach_zero_corr_conf.value; int prach_sequence_length = cfg->prach_sequence_length.value; - - int msg1_frequencystart = cfg->num_prach_fd_occasions_list[0].k1.value; + int msg1_frequencystart = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].k1.value; // int num_unused_root_sequences = cfg->num_prach_fd_occasions_list[0].num_unused_root_sequences.value; // cfg->num_prach_fd_occasions_list[0].unused_root_sequences_list @@ -585,7 +733,7 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, uint8_t prach_fmt = prach_pdu->prach_format; uint16_t N_ZC = (prach_sequence_length==0)?839:139; - LOG_D(PHY,"L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d \n", rootSequenceIndex,numrootSequenceIndex,NCS,N_ZC); + LOG_D(PHY,"L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d, format %d \n",rootSequenceIndex,numrootSequenceIndex,NCS,N_ZC,prach_fmt); prach_ifft = gNB->prach_vars.prach_ifft; prachF = gNB->prach_vars.prachF; @@ -630,13 +778,13 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, else { preamble_shift -= NCS; - + if (preamble_shift < 0) preamble_shift+=N_ZC; } } else { // This is the high-speed case new_dft = 0; - + nr_fill_du(N_ZC,prach_root_sequence_map); // set preamble_offset to initial rootSequenceIndex and look if we need more root sequences for this // preamble index and find the corresponding cyclic shift // Check if all shifts for that root have been processed @@ -644,7 +792,7 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, not_found = 1; new_dft = 1; preamble_index0 -= numshift; - (preamble_offset==0 && numshift==0) ? (preamble_offset) : (preamble_offset++); + //(preamble_offset==0 && numshift==0) ? (preamble_offset) : (preamble_offset++); while (not_found == 1) { // current root depending on rootSequenceIndex @@ -714,38 +862,50 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, memset(prachF, 0, sizeof(int16_t)*2*1024 ); if (LOG_DUMPFLAG(PRACH)) { - LOG_M("prach_rxF0.m","prach_rxF0",rxsigF[0],N_ZC,1,1); - LOG_M("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1); + LOG_M("prach_rxF0.m","prach_rxF0",rxsigF[0],N_ZC,1,1); + LOG_M("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1); } for (aa=0;aa>15); - prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset+1] - (int32_t)Xu[offset+1]*rxsigF[aa][offset])>>15); - } + for (offset=0; offset<(N_ZC<<1); offset+=2) { + prachF[offset] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset] + (int32_t)Xu[offset+1]*rxsigF[aa][offset+1])>>15); + prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset+1] - (int32_t)Xu[offset+1]*rxsigF[aa][offset])>>15); + } - // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) - if (N_ZC == 839) { - log2_ifft_size = 10; - idft(IDFT_1024,prachF,prach_ifft_tmp,1); - // compute energy and accumulate over receive antennas - for (i=0;i<2048;i++) - prach_ifft[i] += ((int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[i<<1] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)])>>10; - } else { - idft(IDFT_256,prachF,prach_ifft_tmp,1); - log2_ifft_size = 8; - // compute energy and accumulate over receive antennas and repetitions for BR - for (i=0;i<256;i++) - prach_ifft[i] += ((int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[(i<<1)] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)])>>10; - } + // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) + if (N_ZC == 839) { + idft(IDFT_1024,prachF,prach_ifft_tmp,1); + // compute energy and accumulate over receive antennas + for (i=0;i<1024;i++) + prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[i<<1] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)]; + } else { + idft(IDFT_256,prachF,prach_ifft_tmp,1); + log2_ifft_size = 8; + // compute energy and accumulate over receive antennas and repetitions for BR + for (i=0;i<256;i++) + prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[(i<<1)] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)]; + } - if (LOG_DUMPFLAG(PRACH)) { - if (aa==0) LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); + if (LOG_DUMPFLAG(PRACH)) { + if (aa==0) LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); if (aa==1) LOG_M("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1); - } + } + }// antennas_rx + + // Normalization of energy over ifft and receive antennas + if (N_ZC == 839) { + log2_ifft_size = 10; + for (i=0;i<1024;i++) + prach_ifft[i] = (prach_ifft[i]>>log2_ifft_size)/nb_rx; + } else { + log2_ifft_size = 8; + for (i=0;i<256;i++) + prach_ifft[i] = (prach_ifft[i]>>log2_ifft_size)/nb_rx; + } + } // new dft // check energy in nth time shift, for @@ -756,10 +916,10 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, lev = (int32_t)prach_ifft[(preamble_shift2+i)]; levdB = dB_fixed_times10(lev); if (levdB>*max_preamble_energy) { - LOG_D(PHY,"preamble_index %d, delay %d en %d dB > %d dB\n",preamble_index,i,levdB,*max_preamble_energy); - *max_preamble_energy = levdB; - *max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate - *max_preamble = preamble_index; + LOG_D(PHY,"preamble_index %d, delay %d en %d dB > %d dB\n",preamble_index,i,levdB,*max_preamble_energy); + *max_preamble_energy = levdB; + *max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate + *max_preamble = preamble_index; } } }// preamble_index diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach_common.c b/openair1/PHY/NR_TRANSPORT/nr_prach_common.c index a95c519d43..84118e8267 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach_common.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach_common.c @@ -37,7 +37,6 @@ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" #include "T.h" diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c index 04045380eb..e6a9b8c5dc 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c @@ -67,12 +67,12 @@ void get_antenna_ports(uint8_t *ap, uint8_t n_symbs, uint8_t config) { void get_Wt(int8_t *Wt, uint8_t ap, uint8_t config) { for (int i=0; i<2; i++) - *(Wt+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][3+i]):(pdsch_dmrs_2[ap][3+i]); + *(Wt+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][5+i]):(pdsch_dmrs_2[ap][5+i]); } void get_Wf(int8_t *Wf, uint8_t ap, uint8_t config) { for (int i=0; i<2; i++) - *(Wf+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][5+i]):(pdsch_dmrs_2[ap][5+i]); + *(Wf+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][3+i]):(pdsch_dmrs_2[ap][3+i]); } uint8_t get_delta(uint8_t ap, uint8_t config) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c index e535286084..aa51f23cb6 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c @@ -46,11 +46,11 @@ uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r) { AssertFatal(Nl>0,"Nl is 0\n"); AssertFatal(Qm>0,"Qm is 0\n"); - LOG_D(PHY,"nr_get_E : (G %d, C %d, Qm %d, Nl %d, r %d)\n",G, C, Qm, Nl, r); if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) E = Nl*Qm*(G/(Nl*Qm*Cprime)); else E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); + LOG_D(PHY,"nr_get_E : (G %d, C %d, Qm %d, Nl %d, r %d), E %d\n",G, C, Qm, Nl, r, E); return E; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h index a30c529459..02e594e76a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h @@ -44,7 +44,7 @@ void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping, uint32_t n_id, uint8_t n_hop, - int nr_tti_tx, + int nr_slot_tx, uint8_t *u, uint8_t *v); @@ -53,7 +53,7 @@ double nr_cyclic_shift_hopping(uint32_t n_id, uint8_t mcs, uint8_t lnormal, uint8_t lprime, - int nr_tti_tx); + int nr_slot_tx); /** \brief Computes available bits G. */ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t length_dmrs, uint8_t Qm, uint8_t Nl); @@ -73,6 +73,8 @@ void compute_nr_prach_seq(uint8_t short_sequence, uint8_t rootSequenceIndex, uint32_t X_u[64][839]); +void nr_fill_du(uint16_t N_ZC,uint16_t *prach_root_sequence_map); + void init_nr_prach_tables(int N_ZC); /**@}*/ diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index e33532fa65..4fed3a468f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -35,7 +35,6 @@ #include "PHY/defs_nr_common.h" #include "PHY/defs_gNB.h" -#include "LAYER2/NR_MAC_gNB/mac_proto.h" #define NR_PBCH_PDU_BITS 24 @@ -78,19 +77,6 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms); -/*! -\fn int nr_pbch_scrambling -\brief PBCH scrambling function -@param - */ -void nr_pbch_scrambling(NR_gNB_PBCH *pbch, - uint32_t Nid, - uint8_t nushift, - uint16_t M, - uint16_t length, - uint8_t encoded, - uint32_t unscrambling_mask); - /*! \fn int nr_generate_pbch \brief Generation of the PBCH @@ -133,15 +119,13 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, @param ue Pointer to PHY variables @param UE_id id of current UE @param frame Frame number - @param nr_tti_rx TTI number - @param symbol Symbol on which to act (within-in nr_TTI_rx) + @param slot Slot number @param harq_pid HARQ process ID */ int nr_rx_pusch(PHY_VARS_gNB *gNB, uint8_t UE_id, uint32_t frame, - uint8_t nr_tti_rx, - unsigned char symbol, + uint8_t slot, unsigned char harq_pid); /** \brief This function performs RB extraction (signal and channel estimates) (currently signal only until channel estimation and compensation are implemented) @@ -155,6 +139,7 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, */ void nr_ulsch_extract_rbs_single(int32_t **rxdataF, NR_gNB_PUSCH *pusch_vars, + int slot, unsigned char symbol, uint8_t is_dmrs_symbol, nfapi_nr_pusch_pdu_t *pusch_pdu, @@ -180,6 +165,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, int32_t *avg, uint8_t symbol, uint32_t len, + uint8_t nrOfLayers, unsigned short nb_rb); /** \brief This function performs channel compensation (matched filtering) on the received RBs for this allocation. In addition, it computes the squared-magnitude of the channel with weightings for 16QAM/64QAM detection as well as dual-stream detection (cross-correlation) @@ -204,6 +190,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, unsigned char symbol, uint8_t is_dmrs_symbol, unsigned char mod_order, + uint8_t nrOfLayers, unsigned short nb_rb, unsigned char output_shift); @@ -212,7 +199,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, \param z Pointer to input in frequnecy domain, and it is also the output in time domain \param Msc_PUSCH number of allocated data subcarriers */ -void nr_idft(uint32_t *z, uint32_t Msc_PUSCH); +void nr_idft(int32_t *z, uint32_t Msc_PUSCH); /** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms. @param rxdataF_comp Compensated channel output @@ -288,6 +275,7 @@ void nr_fill_prach(PHY_VARS_gNB *gNB, void rx_nr_prach(PHY_VARS_gNB *gNB, nfapi_nr_prach_pdu_t *prach_pdu, + int prachOccasion, int frame, int subframe, uint16_t *max_preamble, @@ -298,6 +286,7 @@ void rx_nr_prach_ru(RU_t *ru, int prach_fmt, int numRA, int prachStartSymbol, + int prachOccasion, int frame, int subframe); @@ -306,7 +295,7 @@ void nr_fill_prach_ru(RU_t *ru, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); -int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, int numRA, find_type_t type); +int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, find_type_t type); int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type); NR_gNB_PUCCH_t *new_gNB_pucch(void); @@ -325,7 +314,15 @@ int nr_find_pucch(uint16_t rnti, void init_prach_list(PHY_VARS_gNB *gNB); void init_prach_ru_list(RU_t *ru); void free_nr_ru_prach_entry(RU_t *ru, int prach_id); +uint8_t get_nr_prach_duration(uint8_t prach_format); +void nr_generate_csi_rs(PHY_VARS_gNB *gNB, + int16_t amp, + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t csi_params, + uint16_t cell_id, + int slot); + +void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id); void nr_decode_pucch1(int32_t **rxdataF, pucch_GroupHopping_t pucch_GroupHopping, @@ -342,10 +339,21 @@ void nr_decode_pucch1(int32_t **rxdataF, uint8_t timeDomainOCC, uint8_t nr_bit); +void nr_decode_pucch2(PHY_VARS_gNB *gNB, + int slot, + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, + nfapi_nr_pucch_pdu_t* pucch_pdu); + void nr_decode_pucch0(PHY_VARS_gNB *gNB, + int frame, int slot, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu); +void nr_decode_pucch2(PHY_VARS_gNB *gNB, + int slot, + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, + nfapi_nr_pucch_pdu_t* pucch_pdu); + #endif /*__NR_TRANSPORT__H__*/ diff --git a/openair1/PHY/NR_TRANSPORT/nr_uci_tools_common.c b/openair1/PHY/NR_TRANSPORT/nr_uci_tools_common.c index 2b0cbe72b3..4d286bc937 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_uci_tools_common.c +++ b/openair1/PHY/NR_TRANSPORT/nr_uci_tools_common.c @@ -33,11 +33,11 @@ #include "nr_dci.h" void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping, - uint32_t n_id, - uint8_t n_hop, - int nr_tti_tx, - uint8_t *u, - uint8_t *v) { + uint32_t n_id, + uint8_t n_hop, + int nr_slot_tx, + uint8_t *u, + uint8_t *v) { /* * Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping * The following variables are set by higher layers: @@ -65,7 +65,7 @@ void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping, *v=0; uint32_t c_init = 0; uint32_t x1,s; // TS 38.211 Subclause 5.2.1 - int l = 32, minShift = ((2*nr_tti_tx+n_hop)<<3); + int l = 32, minShift = ((2*nr_slot_tx+n_hop)<<3); int tmpShift =0; #ifdef DEBUG_NR_PUCCH_TX printf("\t\t [nr_group_sequence_hopping] calculating u,v -> "); @@ -92,7 +92,7 @@ void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping, f_gh = f_gh%30; f_ss = n_id%30; /* for (int m=0; m<8; m++){ - f_gh = f_gh + ((1<>(8*(2*nr_tti_tx+n_hop)+m))&1))); // Not sure we have to use nr_tti_tx FIXME!!! + f_gh = f_gh + ((1<>(8*(2*nr_slot_tx+n_hop)+m))&1))); // Not sure we have to use nr_slot_tx FIXME!!! } f_gh = f_gh%30; f_ss = n_id%30;*/ @@ -102,7 +102,7 @@ void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping, c_init = (1<<5)*floor(n_id/30)+(n_id%30); // we initialize c_init to calculate u,v s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1 f_ss = n_id%30; - l = 32, minShift = (2*nr_tti_tx+n_hop); + l = 32, minShift = (2*nr_slot_tx+n_hop); while(minShift >= l) { s = lte_gold_generic(&x1, &c_init, 0); @@ -111,7 +111,7 @@ void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping, tmpShift = (minShift&((1<<5)-1)); //minShift%32; *v = (uint8_t)((s>>tmpShift)&1); - // *v = (uint8_t)((s>>(2*nr_tti_tx+n_hop))&1); // Not sure we have to use nr_tti_tx FIXME!!! + // *v = (uint8_t)((s>>(2*nr_slot_tx+n_hop))&1); // Not sure we have to use nr_slot_tx FIXME!!! } *u = (f_gh+f_ss)%30; @@ -125,7 +125,7 @@ double nr_cyclic_shift_hopping(uint32_t n_id, uint8_t mcs, uint8_t lnormal, uint8_t lprime, - int nr_tti_tx) { + int nr_slot_tx) { /* * Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping * - n_id: higher-layer parameter hoppingId @@ -140,7 +140,7 @@ double nr_cyclic_shift_hopping(uint32_t n_id, uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1 uint8_t n_cs=0; - int l = 32, minShift = (14*8*nr_tti_tx )+ 8*(lnormal+lprime); + int l = 32, minShift = (14*8*nr_slot_tx )+ 8*(lnormal+lprime); int tmpShift =0; #ifdef DEBUG_NR_PUCCH_TX printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%u -> \n",c_init); @@ -155,8 +155,8 @@ double nr_cyclic_shift_hopping(uint32_t n_id, tmpShift = (minShift&((1<<5)-1)); //minShift%32; minShift ++; n_cs = n_cs+((1<>tmpShift)&1))); - // calculating n_cs (Not sure we have to use nr_tti_tx FIXME!!!) - // n_cs = n_cs+((1<>((14*8*nr_tti_tx) + 8*(lnormal+lprime) + m))&1))); + // calculating n_cs (Not sure we have to use nr_slot_tx FIXME!!!) + // n_cs = n_cs+((1<>((14*8*nr_slot_tx) + 8*(lnormal+lprime) + m))&1))); } alpha = (alpha * (double)((m0+mcs+n_cs)%12)); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 3622e61b61..4278338dbc 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -33,7 +33,7 @@ #include #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_ulsch.h" -#include "PHY/LTE_REFSIG/lte_refsig.h" +#include "PHY/NR_REFSIG/nr_refsig.h" int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { @@ -41,7 +41,7 @@ int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { int16_t first_free_index=-1; AssertFatal(gNB!=NULL,"gNB is null\n"); - for (i=0; inumber_of_nr_ulsch_max; i++) { AssertFatal(gNB->ulsch[i]!=NULL,"gNB->ulsch[%d] is null\n",i); AssertFatal(gNB->ulsch[i][0]!=NULL,"gNB->ulsch[%d][0] is null\n",i); LOG_D(PHY,"searching for rnti %x : ulsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,gNB->ulsch[i][0]->harq_mask,gNB->ulsch[i][0]->rnti,first_free_index); @@ -62,7 +62,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int ulsch_id = find_nr_ulsch(ulsch_pdu->rnti,gNB,SEARCH_EXIST_OR_FREE); - AssertFatal( (ulsch_id>=0) && (ulsch_id=0) && (ulsch_idnumber_of_nr_ulsch_max), "illegal or no ulsch_id found!!! rnti %04x ulsch_id %d\n",ulsch_pdu->rnti,ulsch_id); NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ulsch_id][0]; @@ -103,3 +103,93 @@ void nr_ulsch_unscrambling(int16_t* llr, llr[i] = -llr[i]; } } + +void nr_ulsch_unscrambling_optim(int16_t* llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI) { + +#if defined(__x86_64__) || defined(__i386__) + uint32_t x1, x2, s=0; + + x2 = (n_RNTI<<15) + Nid; + + uint8_t *s8=(uint8_t *)&s; + __m128i *llr128 = (__m128i*)llr; + int j=0; + s = lte_gold_generic(&x1, &x2, 1); + + for (int i=0; i<((size>>5)+((size&0x1f) > 0 ? 1 : 0)); i++,j+=4) { + llr128[j] = _mm_mullo_epi16(llr128[j],byte2m128i[s8[0]]); + llr128[j+1] = _mm_mullo_epi16(llr128[j+1],byte2m128i[s8[1]]); + llr128[j+2] = _mm_mullo_epi16(llr128[j+2],byte2m128i[s8[2]]); + llr128[j+3] = _mm_mullo_epi16(llr128[j+3],byte2m128i[s8[3]]); + s = lte_gold_generic(&x1, &x2, 0); + } +#else + + nr_ulsch_unscrambling(llr, + size, + q, + Nid, + n_RNTI); +#endif +} + +void dump_pusch_stats(FILE *fd,PHY_VARS_gNB *gNB) { + + for (int i=0;inumber_of_nr_ulsch_max;i++) { + + if (gNB->ulsch_stats[i].rnti>0 && gNB->ulsch_stats[i].frame != gNB->ulsch_stats[i].dump_frame) { + gNB->ulsch_stats[i].dump_frame = gNB->ulsch_stats[i].frame; + for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) + if (aa==0) fprintf(fd,"ULSCH RNTI %4x, %d.%d: ulsch_power[%d] %d,%d ulsch_noise_power[%d] %d.%d, sync_pos %d\n", + gNB->ulsch_stats[i].rnti,gNB->ulsch_stats[i].frame,gNB->ulsch_stats[i].dump_frame, + aa,gNB->ulsch_stats[i].power[aa]/10,gNB->ulsch_stats[i].power[aa]%10, + aa,gNB->ulsch_stats[i].noise_power[aa]/10,gNB->ulsch_stats[i].noise_power[aa]%10, + gNB->ulsch_stats[i].sync_pos); + else fprintf(fd," ulsch_power[%d] %d.%d, ulsch_noise_power[%d] %d.%d\n", + aa,gNB->ulsch_stats[i].power[aa]/10,gNB->ulsch_stats[i].power[aa]%10, + aa,gNB->ulsch_stats[i].noise_power[aa]/10,gNB->ulsch_stats[i].noise_power[aa]%10); + + + fprintf(fd," round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d, DTX %d, current_Qm %d, current_RI %d, total_bytes RX/SCHED %d/%d\n", + gNB->ulsch_stats[i].round_trials[0], + (double)gNB->ulsch_stats[i].round_trials[1]/gNB->ulsch_stats[i].round_trials[0], + gNB->ulsch_stats[i].round_trials[1], + (double)gNB->ulsch_stats[i].round_trials[2]/gNB->ulsch_stats[i].round_trials[0], + gNB->ulsch_stats[i].round_trials[2], + (double)gNB->ulsch_stats[i].round_trials[3]/gNB->ulsch_stats[i].round_trials[0], + gNB->ulsch_stats[i].round_trials[3], + gNB->ulsch_stats[i].DTX, + gNB->ulsch_stats[i].current_Qm, + gNB->ulsch_stats[i].current_RI, + gNB->ulsch_stats[i].total_bytes_rx, + gNB->ulsch_stats[i].total_bytes_tx); + } + } +} + +void clear_pusch_stats(PHY_VARS_gNB *gNB) { + + for (int i=0;inumber_of_nr_ulsch_max;i++) + memset((void*)&gNB->ulsch_stats[i],0,sizeof(gNB->ulsch_stats[i])); +} + +NR_gNB_SCH_STATS_t *get_ulsch_stats(PHY_VARS_gNB *gNB,NR_gNB_ULSCH_t *ulsch) { + NR_gNB_SCH_STATS_t *stats=NULL; + int first_free=-1; + for (int i=0;inumber_of_nr_ulsch_max;i++) { + if (gNB->ulsch_stats[i].rnti == 0 && first_free == -1) { + first_free = i; + stats=&gNB->ulsch_stats[i]; + } + if (gNB->ulsch_stats[i].rnti == ulsch->rnti) { + stats=&gNB->ulsch_stats[i]; + break; + } + } + return(stats); +} + diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index 7ff52ae692..80c10d74b1 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -31,6 +31,7 @@ */ #include "PHY/defs_gNB.h" +#include "common/utils/threadPool/thread-pool.h" void free_gNB_ulsch(NR_gNB_ULSCH_t **ulsch,uint8_t N_RB_UL); @@ -75,9 +76,22 @@ void nr_ulsch_unscrambling(int16_t* llr, uint32_t n_RNTI); +void nr_ulsch_unscrambling_optim(int16_t* llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI); + void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int UE_id, uint8_t harq_pid); int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); + +void dump_pusch_stats(FILE *fd,PHY_VARS_gNB *gNB); + +void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); +void clear_pusch_stats(PHY_VARS_gNB *gNB); + +NR_gNB_SCH_STATS_t *get_ulsch_stats(PHY_VARS_gNB *gNB,NR_gNB_ULSCH_t *ulsch); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 8ca3071e06..8bbf569814 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -52,9 +52,6 @@ #define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 //#define PRINT_CRC_CHECK -static uint64_t nb_total_decod =0; -static uint64_t nb_error_decod =0; - //extern double cpuf; void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr,uint8_t N_RB_UL) @@ -67,7 +64,7 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr,uint8_t N_RB_UL) if (ulsch) { if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } @@ -119,11 +116,10 @@ NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint16_t N_RB_UL, uint if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } uint16_t ulsch_bytes = a_segments*1056; // allocated bytes per segment - ulsch = (NR_gNB_ULSCH_t *)malloc16(sizeof(NR_gNB_ULSCH_t)); if (ulsch) { @@ -209,8 +205,6 @@ void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch) ulsch->Mlimit = 0; ulsch->max_ldpc_iterations = 0; ulsch->last_iteration_cnt = 0; - ulsch->num_active_cba_groups = 0; - for (i=0;icba_rnti[i] = 0; for (i=0;iharq_process_id[i] = 0; for (i=0; iharq_processes[i]->rar_alloc=0; ulsch->harq_processes[i]->status=NR_SCH_IDLE; ulsch->harq_processes[i]->subframe_scheduling_flag=0; - ulsch->harq_processes[i]->subframe_cba_scheduling_flag=0; - ulsch->harq_processes[i]->phich_active=0; - ulsch->harq_processes[i]->phich_ACK=0; ulsch->harq_processes[i]->previous_first_rb=0; ulsch->harq_processes[i]->handled=0; ulsch->harq_processes[i]->delta_TF=0; @@ -290,8 +281,174 @@ void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch) static uint32_t prnt_crc_cnt = 0; #endif +void nr_processULSegment(void* arg) { + ldpcDecode_t *rdata = (ldpcDecode_t*) arg; + PHY_VARS_gNB *phy_vars_gNB = rdata->gNB; + NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; + int length_dec; + int no_iteration_ldpc; + int Kr; + int Kr_bytes; + int K_bits_F; + uint8_t crc_type; + int i; + int j; + int r = rdata->segment_r; + int A = rdata->A; + int E = rdata->E; + int Qm = rdata->Qm; + int rv_index = rdata->rv_index; + int r_offset = rdata->r_offset; + uint8_t kc = rdata->Kc; + uint32_t Tbslbrm = rdata->Tbslbrm; + short* ulsch_llr = rdata->ulsch_llr; + int max_ldpc_iterations = p_decoderParms->numMaxIter; + int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); + + int16_t z [68*384 + 16] __attribute__ ((aligned(16))); + int8_t l [68*384 + 16] __attribute__ ((aligned(16))); + + __m128i *pv = (__m128i*)&z; + __m128i *pl = (__m128i*)&l; + + uint8_t Ilbrm = 0; + + Kr = ulsch_harq->K; + Kr_bytes = Kr>>3; + K_bits_F = Kr-ulsch_harq->F; + + t_nrLDPC_time_stats procTime = {0}; + t_nrLDPC_time_stats* p_procTime = &procTime ; + + //start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); + + //////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + //////////////////////////// ulsch_llr =====> ulsch_harq->e ////////////////////////////// + + nr_deinterleaving_ldpc(E, + Qm, + ulsch_harq->e[r], + ulsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset); + + stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); + + + /*LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", + harq_pid,r, G, + Kr*3, + ulsch_harq->TBS, + Qm, + nb_rb, + n_layers, + pusch_pdu->pusch_data.rv_index, + ulsch_harq->round);*/ + ////////////////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////// nr_rate_matching_ldpc_rx //////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////// ulsch_harq->e =====> ulsch_harq->d ///////////////////////// + + //start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + + if (nr_rate_matching_ldpc_rx(Ilbrm, + Tbslbrm, + p_decoderParms->BG, + p_decoderParms->Z, + ulsch_harq->d[r], + ulsch_harq->e[r], + ulsch_harq->C, + rv_index, + ulsch_harq->new_rx, + E, + ulsch_harq->F, + Kr-ulsch_harq->F-2*(p_decoderParms->Z))==-1) { + + stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + + LOG_E(PHY,"ulsch_decoding.c: Problem in rate_matching\n"); + rdata->decodeIterations = max_ldpc_iterations + 1; + return; + } else { + stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + } + + memset(ulsch_harq->c[r],0,Kr_bytes); + + if (ulsch_harq->C == 1) { + if (A > 3824) + crc_type = CRC24_A; + else + crc_type = CRC16; + + length_dec = ulsch_harq->B; + } + else { + crc_type = CRC24_B; + length_dec = (ulsch_harq->B+24*ulsch_harq->C)/ulsch_harq->C; + } + + //start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); + + //set first 2*Z_c bits to zeros + memset(&z[0],0,2*ulsch_harq->Z*sizeof(int16_t)); + //set Filler bits + memset((&z[0]+K_bits_F),127,ulsch_harq->F*sizeof(int16_t)); + //Move coded bits before filler bits + memcpy((&z[0]+2*ulsch_harq->Z),ulsch_harq->d[r],(K_bits_F-2*ulsch_harq->Z)*sizeof(int16_t)); + //skip filler bits + memcpy((&z[0]+Kr),ulsch_harq->d[r]+(Kr-2*ulsch_harq->Z),(kc*ulsch_harq->Z-Kr)*sizeof(int16_t)); + //Saturate coded bits before decoding into 8 bits values + for (i=0, j=0; j < ((kc*ulsch_harq->Z)>>4)+1; i+=2, j++) + { + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); + } + ////////////////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////// nrLDPC_decoder ///////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// + + no_iteration_ldpc = nrLDPC_decoder(p_decoderParms, + (int8_t*)&pl[0], + llrProcBuf, + ulsch_harq->p_nrLDPC_procBuf[r], + p_procTime); + + if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) { +#ifdef PRINT_CRC_CHECK + LOG_I(PHY, "Segment %d CRC OK, iterations %d/%d\n",r,no_iteration_ldpc,max_ldpc_iterations); +#endif + rdata->decodeIterations = no_iteration_ldpc; + if (rdata->decodeIterations > p_decoderParms->numMaxIter) rdata->decodeIterations--; + } else { +#ifdef PRINT_CRC_CHECK + LOG_I(PHY, "CRC NOK\n"); +#endif + rdata->decodeIterations = max_ldpc_iterations + 1; + } + + for (int m=0; m < Kr>>3; m ++) { + ulsch_harq->c[r][m]= (uint8_t) llrProcBuf[m]; + } + + //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); +} + uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, - uint8_t UE_id, + uint8_t ULSCH_id, short *ulsch_llr, NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *pusch_pdu, @@ -300,36 +457,37 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint8_t harq_pid, uint32_t G) { - uint32_t A,E; - uint32_t ret, offset; - int32_t no_iteration_ldpc, length_dec; - uint32_t r,r_offset=0,Kr=8424,Kr_bytes,K_bytes_F,err_flag=0; - uint8_t crc_type; - int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); + uint32_t A; + uint32_t r; + uint32_t r_offset; + uint32_t offset; + int kc; + int Tbslbrm; + int E; #ifdef PRINT_CRC_CHECK prnt_crc_cnt++; #endif - NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id][0]; + NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[ULSCH_id][0]; + NR_gNB_PUSCH *pusch = phy_vars_gNB->pusch_vars[ULSCH_id]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; - + + if (!harq_process) { + LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n"); + return 1; + } + t_nrLDPC_dec_params decParams; t_nrLDPC_dec_params* p_decParams = &decParams; - t_nrLDPC_time_stats procTime; - t_nrLDPC_time_stats* p_procTime = &procTime ; - if (!harq_process) { - printf("ulsch_decoding.c: NULL harq_process pointer\n"); - return (ulsch->max_ldpc_iterations + 1); - } - t_nrLDPC_procBuf** p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf; - int16_t z [68*384]; - int8_t l [68*384]; - uint8_t kc = 255; - uint8_t Ilbrm = 0; - uint32_t Tbslbrm = 950984; + int Kr; + int Kr_bytes; + + phy_vars_gNB->nbDecode = 0; + harq_process->processedSegments = 0; + double Coderate = 0.0; // ------------------------------------------------------------------ @@ -340,76 +498,95 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint8_t n_layers = pusch_pdu->nrOfLayers; // ------------------------------------------------------------------ - uint32_t i,j; - - __m128i *pv = (__m128i*)&z; - __m128i *pl = (__m128i*)&l; - - if (!ulsch_llr) { - printf("ulsch_decoding.c: NULL ulsch_llr pointer\n"); - return (ulsch->max_ldpc_iterations + 1); + LOG_E(PHY,"ulsch_decoding.c: NULL ulsch_llr pointer\n"); + return 1; } - if (!frame_parms) { - printf("ulsch_decoding.c: NULL frame_parms pointer\n"); - return (ulsch->max_ldpc_iterations + 1); - } - - // harq_process->trials[nfapi_ulsch_pdu_rel15->round]++; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,1); harq_process->TBS = pusch_pdu->pusch_data.tb_size; + harq_process->round = nr_rv_round_map[pusch_pdu->pusch_data.rv_index]; + + harq_process->new_rx = false; // flag to indicate if this is a new reception for this harq (initialized to false) + if (harq_process->round == 0) { + harq_process->new_rx = true; + harq_process->ndi = pusch_pdu->pusch_data.new_data_indicator; + } + + // this happens if there was a DTX in round 0 + if (harq_process->ndi != pusch_pdu->pusch_data.new_data_indicator) { + harq_process->new_rx = true; + harq_process->ndi = pusch_pdu->pusch_data.new_data_indicator; + LOG_E(PHY,"Missed ULSCH detection. NDI toggled but rv %d does not correspond to first reception\n",pusch_pdu->pusch_data.rv_index); + } A = (harq_process->TBS)<<3; - ret = ulsch->max_ldpc_iterations + 1; - LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, n_layers %d\n",harq_pid,A,G, mcs, n_layers, nb_rb, Qm, n_layers); + LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, n_layers %d, Coderate %d\n",harq_pid,A,G, mcs, n_layers, nb_rb, Qm, n_layers, R); - if (harq_process->round == 0) { - - // This is a new packet, so compute quantities regarding segmentation - if (A > 3824) - harq_process->B = A+24; - else - harq_process->B = A+16; - - if (R<1024) - Coderate = (float) R /(float) 1024; - else - Coderate = (float) R /(float) 2048; - - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ - p_decParams->BG = 2; - if (Coderate < 0.3333) { + if (R<1024) + Coderate = (float) R /(float) 1024; + else + Coderate = (float) R /(float) 2048; + + if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ + p_decParams->BG = 2; + kc = 52; + if (Coderate < 0.3333) { p_decParams->R = 15; - kc = 52; } else if (Coderate <0.6667) { p_decParams->R = 13; - kc = 32; } else { p_decParams->R = 23; - kc = 17; } } else { p_decParams->BG = 1; + kc = 68; if (Coderate < 0.6667) { p_decParams->R = 13; - kc = 68; } else if (Coderate <0.8889) { p_decParams->R = 23; - kc = 35; } else { p_decParams->R = 89; - kc = 27; } } + + NR_gNB_SCH_STATS_t *stats=NULL; + int first_free=-1; + for (int i=0;iulsch_stats[i].rnti == 0 && first_free == -1) { + first_free = i; + stats=&phy_vars_gNB->ulsch_stats[i]; + } + if (phy_vars_gNB->ulsch_stats[i].rnti == ulsch->rnti) { + stats=&phy_vars_gNB->ulsch_stats[i]; + break; + } + } + if (stats) { + stats->frame = frame; + stats->rnti = ulsch->rnti; + stats->round_trials[harq_process->round]++; + for (int aarx=0;aarxnb_antennas_rx;aarx++) { + stats->power[aarx]=dB_fixed_x10(pusch->ulsch_power[aarx]); + stats->noise_power[aarx]=dB_fixed_x10(pusch->ulsch_noise_power[aarx]); + } + if (harq_process->new_rx == 0) { + stats->current_Qm = Qm; + stats->current_RI = n_layers; + stats->total_bytes_tx += harq_process->TBS; + } + } + if (A > 3824) + harq_process->B = A+24; + else + harq_process->B = A+16; - // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F) +// [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F) nr_segmentation(NULL, NULL, harq_process->B, @@ -420,309 +597,71 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, p_decParams->BG); #ifdef DEBUG_ULSCH_DECODING - printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z); - if (!frame%100) - printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z); + printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z); + if (!frame%100) + printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z); #endif - } + Tbslbrm = nr_compute_tbslbrm(0,nb_rb,n_layers); + p_decParams->Z = harq_process->Z; p_decParams->numMaxIter = ulsch->max_ldpc_iterations; p_decParams->outMode= 0; - err_flag = 0; r_offset = 0; uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS; //number of segments to be allocated if (nb_rb != 273) { a_segments = a_segments*nb_rb; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } if (harq_process->C > a_segments) { LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); - return (ulsch->max_ldpc_iterations + 1); + return 1; } #ifdef DEBUG_ULSCH_DECODING printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); #endif - - //opp_enabled=1; - Kr = harq_process->K; Kr_bytes = Kr>>3; - - K_bytes_F = Kr_bytes-(harq_process->F>>3); + offset = 0; + void (*nr_processULSegment_ptr)(void*) = &nr_processULSegment; for (r=0; rC; r++) { + E = nr_get_E(G, harq_process->C, Qm, n_layers, r); + union ldpcReqUnion id = {.s={ulsch->rnti,frame,nr_tti_rx,0,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, phy_vars_gNB->respDecode, nr_processULSegment_ptr); + ldpcDecode_t * rdata=(ldpcDecode_t *) NotifiedFifoData(req); - start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); - - //////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - //////////////////////////// ulsch_llr =====> harq_process->e ////////////////////////////// - - nr_deinterleaving_ldpc(E, - Qm, - harq_process->e[r], - ulsch_llr+r_offset); - - //for (int i =0; i<16; i++) - // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); - - stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); - - -#ifdef DEBUG_ULSCH_DECODING - LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", - harq_pid,r, G, - Kr*3, - harq_process->TBS, - Qm, - nb_rb, - n_layers, - pusch_pdu->pusch_data.rv_index, - harq_process->round); -#endif - ////////////////////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////// nr_rate_matching_ldpc_rx //////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - ///////////////////////// harq_process->e =====> harq_process->d ///////////////////////// - - start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - - Tbslbrm = nr_compute_tbslbrm(0,nb_rb,n_layers,harq_process->C); - - if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - harq_process->d[r], - harq_process->e[r], - harq_process->C, - pusch_pdu->pusch_data.rv_index, - (harq_process->round==0)?1:0, - E, - harq_process->F, - Kr-harq_process->F-2*(p_decParams->Z))==-1) { - - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - - LOG_E(PHY,"ulsch_decoding.c: Problem in rate_matching\n"); - return (ulsch->max_ldpc_iterations + 1); - } else { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - } - + rdata->gNB = phy_vars_gNB; + rdata->ulsch_harq = harq_process; + rdata->decoderParms = decParams; + rdata->ulsch_llr = ulsch_llr; + rdata->Kc = kc; + rdata->harq_pid = harq_pid; + rdata->segment_r = r; + rdata->nbSegments = harq_process->C; + rdata->E = E; + rdata->A = A; + rdata->Qm = Qm; + rdata->r_offset = r_offset; + rdata->Kr_bytes = Kr_bytes; + rdata->rv_index = pusch_pdu->pusch_data.rv_index; + rdata->Tbslbrm = Tbslbrm; + rdata->offset = offset; + rdata->ulsch = ulsch; + rdata->ulsch_id = ULSCH_id; + pushTpool(phy_vars_gNB->threadPool,req); + phy_vars_gNB->nbDecode++; + LOG_D(PHY,"Added a block to decode, in pipe: %d\n",phy_vars_gNB->nbDecode); r_offset += E; - -#ifdef DEBUG_ULSCH_DECODING - if (r==0) { - write_output("decoder_llr.m","decllr",ulsch_llr,G,1,0); - write_output("decoder_in.m","dec",&harq_process->d[0][0],E,1,0); - } - - printf("decoder input(segment %u) :", r); - int i; - for (i=0;i<(3*8*Kr_bytes)+12;i++) - printf("%d : %d\n",i,harq_process->d[r][i]); - printf("\n"); -#endif - - - // printf("Clearing c, %p\n",harq_process->c[r]); - memset(harq_process->c[r],0,Kr_bytes); - - // printf("done\n"); - if (harq_process->C == 1) { - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } - else { - crc_type = CRC24_B; - length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; - } - - if (err_flag == 0) { - - start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); - - //LOG_E(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A); - - - memset(pv,0,2*harq_process->Z*sizeof(int16_t)); - memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); - - for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++) { - pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); - } - - AssertFatal(kc!=255,""); - j+=(harq_process->F>>3); - // for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) { - for (i=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) { - pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); - } - - for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } - - ////////////////////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////// nrLDPC_decoder ///////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// - - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, - p_nrLDPC_procBuf[r], - p_procTime); - - if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - #ifdef PRINT_CRC_CHECK - //if (prnt_crc_cnt % 10 == 0) - LOG_I(PHY, "Segment %d CRC OK\n",r); - #endif - ret = no_iteration_ldpc; - } else { - #ifdef PRINT_CRC_CHECK - //if (prnt_crc_cnt%10 == 0) - LOG_I(PHY, "CRC NOK\n"); - #endif - ret = ulsch->max_ldpc_iterations + 1; - } - nb_total_decod++; - - if (no_iteration_ldpc > ulsch->max_ldpc_iterations){ - nb_error_decod++; - } - - for (int m=0; m < Kr>>3; m ++) { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } - -#ifdef DEBUG_ULSCH_DECODING - //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - for (int k=0;k>3;k++) - printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); - printf("no_iterations_ldpc %d (ret %u)\n",no_iteration_ldpc,ret); - //write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4); -#endif - - stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); - } - - if ((err_flag == 0) && (ret >= (ulsch->max_ldpc_iterations + 1))) { - // a Code segment is in error so break; - LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1); - err_flag = 1; - } + offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); ////////////////////////////////////////////////////////////////////////////////////////// } - - int32_t frame_rx_prev = frame; - int32_t tti_rx_prev = nr_tti_rx - 1; - if (tti_rx_prev < 0) { - frame_rx_prev--; - tti_rx_prev += frame_parms->slots_per_frame; - } - frame_rx_prev = frame_rx_prev%1024; - - if (err_flag == 1) { - -#ifdef gNB_DEBUG_TRACE - LOG_I(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d) Kr %d r %d\n", - phy_vars_gNB->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,Kr,r); -#endif - - // harq_process->harq_ack.ack = 0; - // harq_process->harq_ack.harq_id = harq_pid; - // harq_process->harq_ack.send_harq_status = 1; - // harq_process->errors[harq_process->round]++; - //harq_process->round++; - - if (harq_process->round >= ulsch->Mlimit) { - harq_process->status = SCH_IDLE; - harq_process->round = 0; - harq_process->handled = 0; - ulsch->harq_mask &= ~(1 << harq_pid); - } - - // LOG_D(PHY,"[gNB %d] ULSCH: Setting NACK for nr_tti_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", - // phy_vars_gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->status,harq_process->round,ulsch->Mlimit,harq_process->TBS); - - harq_process->handled = 1; - ret = ulsch->max_ldpc_iterations + 1; - - } else { - -#ifdef gNB_DEBUG_TRACE - LOG_I(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d TBS %d\n", - phy_vars_gNB->Mod_id,nr_tti_rx,harq_process->TBS); -#endif - - harq_process->status = SCH_IDLE; - harq_process->round = 0; - // harq_process->handled = 0; - ulsch->harq_mask &= ~(1 << harq_pid); - // harq_process->harq_ack.ack = 1; - // harq_process->harq_ack.harq_id = harq_pid; - // harq_process->harq_ack.send_harq_status = 1; - - // LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->round,harq_process->TBS); - - - // Reassembly of Transport block here - offset = 0; - Kr = harq_process->K; - Kr_bytes = Kr>>3; - - for (r=0; rC; r++) { - - memcpy(harq_process->b+offset, - harq_process->c[r], - Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0)); - - offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); - -#ifdef DEBUG_ULSCH_DECODING - printf("Segment %u : Kr = %u bytes\n", r, Kr_bytes); - printf("copied %d bytes to b sequence (harq_pid %d)\n", (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)), harq_pid); - printf("b[0] = %x, c[%d] = %x\n", harq_process->b[offset], harq_process->F>>3, harq_process->c[r]); -#endif - - } - } - -#ifdef DEBUG_ULSCH_DECODING - LOG_I(PHY, "Decoder output (payload) at SFN/SF: %d/%d \n", frame, nr_tti_rx); - for (i = 0; i < harq_process->TBS ; i++) { - //harq_process_ul_ue->a[i] = (unsigned char) rand(); - //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - printf("%02x ",harq_process->b[i]); - } -#endif - - ulsch->last_iteration_cnt = ret; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0); - return(ret); + return 1; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index a966db5844..28dd5ab219 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -7,19 +7,22 @@ #include "PHY/NR_REFSIG/ptrs_nr.h" #include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "PHY/defs_nr_common.h" +#include "common/utils/nr/nr_common.h" //#define DEBUG_CH_COMP //#define DEBUG_RB_EXT //#define DEBUG_CH_MAG -void nr_idft(uint32_t *z, uint32_t Msc_PUSCH) +#define INVALID_VALUE 255 + +void nr_idft(int32_t *z, uint32_t Msc_PUSCH) { #if defined(__x86_64__) || defined(__i386__) - __m128i idft_in128[1][1200], idft_out128[1][1200]; + __m128i idft_in128[1][3240], idft_out128[1][3240]; __m128i norm128; #elif defined(__arm__) - int16x8_t idft_in128[1][1200], idft_out128[1][1200]; + int16x8_t idft_in128[1][3240], idft_out128[1][3240]; int16x8_t norm128; #endif int16_t *idft_in0 = (int16_t*)idft_in128[0], *idft_out0 = (int16_t*)idft_out128[0]; @@ -28,20 +31,19 @@ void nr_idft(uint32_t *z, uint32_t Msc_PUSCH) LOG_T(PHY,"Doing lte_idft for Msc_PUSCH %d\n",Msc_PUSCH); - // conjugate input - for (i = 0; i < (Msc_PUSCH>>2); i++) { + if ((Msc_PUSCH % 1536) > 0) { + // conjugate input + for (i = 0; i < (Msc_PUSCH>>2); i++) { #if defined(__x86_64__)||defined(__i386__) - *&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]); + *&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]); #elif defined(__arm__) - *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); + *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); #endif + } + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) + ((uint32_t*)idft_in0)[ip+0] = z[i]; } - for (i=0,ip=0; i 0) { + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) + z[i] = ((uint32_t*)idft_out0)[ip]; - - for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { - z[i] = ((uint32_t*)idft_out0)[ip]; - } - - // conjugate output - for (i = 0; i < (Msc_PUSCH>>2); i++) { + // conjugate output + for (i = 0; i < (Msc_PUSCH>>2); i++) { #if defined(__x86_64__) || defined(__i386__) - ((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]); + ((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]); #elif defined(__arm__) - *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); + *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); #endif + } } #if defined(__x86_64__) || defined(__i386__) @@ -222,8 +301,10 @@ void nr_idft(uint32_t *z, uint32_t Msc_PUSCH) } + void nr_ulsch_extract_rbs_single(int32_t **rxdataF, NR_gNB_PUSCH *pusch_vars, + int slot, unsigned char symbol, uint8_t is_dmrs_symbol, nfapi_nr_pusch_pdu_t *pusch_pdu, @@ -232,104 +313,92 @@ void nr_ulsch_extract_rbs_single(int32_t **rxdataF, unsigned short start_re, re, nb_re_pusch; unsigned char aarx; - uint8_t K_ptrs = 0; uint32_t rxF_ext_index = 0; uint32_t ul_ch0_ext_index = 0; uint32_t ul_ch0_index = 0; - uint32_t ul_ch0_ptrs_ext_index = 0; - uint32_t ul_ch0_ptrs_index = 0; - uint8_t is_ptrs_symbol_flag,k_prime; - uint16_t n=0, num_ptrs_symbols; + uint8_t k_prime; + uint16_t n; int16_t *rxF,*rxF_ext; int *ul_ch0,*ul_ch0_ext; - int *ul_ch0_ptrs,*ul_ch0_ptrs_ext; - uint16_t n_rnti = pusch_pdu->rnti; uint8_t delta = 0; - + int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; #ifdef DEBUG_RB_EXT printf("--------------------symbol = %d-----------------------\n", symbol); printf("--------------------ch_ext_index = %d-----------------------\n", symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size); #endif - + uint8_t is_dmrs_re; - start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start * NR_NB_SC_PER_RB))%frame_parms->ofdm_symbol_size; + start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB)%frame_parms->ofdm_symbol_size; nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size; - is_ptrs_symbol_flag = 0; - num_ptrs_symbols = 0; +#ifdef __AVX2__ + int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); +#else + int nb_re_pusch2 = nb_re_pusch; +#endif for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - - rxF = (int16_t *)&rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size]; - rxF_ext = (int16_t *)&pusch_vars->rxdataF_ext[aarx][symbol * nb_re_pusch]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6 + + rxF = (int16_t *)&rxdataF[aarx][soffset+(symbol * frame_parms->ofdm_symbol_size)]; + rxF_ext = (int16_t *)&pusch_vars->rxdataF_ext[aarx][symbol * nb_re_pusch2]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6 ul_ch0 = &pusch_vars->ul_ch_estimates[aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available - ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aarx][symbol*nb_re_pusch]; - - ul_ch0_ptrs = &pusch_vars->ul_ch_ptrs_estimates[aarx][pusch_vars->ptrs_symbol_index*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available - - ul_ch0_ptrs_ext = &pusch_vars->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch]; + ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aarx][symbol*nb_re_pusch2]; n = 0; k_prime = 0; + rxF_ext_index = 0; + ul_ch0_ext_index = 0; + ul_ch0_index = 0; - for (re = 0; re < nb_re_pusch; re++) { - - if (is_dmrs_symbol) - is_dmrs_re = (re == get_dmrs_freq_idx_ul(n, k_prime, delta, pusch_pdu->dmrs_config_type)); - else - is_dmrs_re = 0; - - if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - K_ptrs = (pusch_pdu->pusch_ptrs.ptrs_freq_density)?4:2; - if(is_ptrs_symbol(symbol, pusch_vars->ptrs_symbols)) - is_ptrs_symbol_flag = is_ptrs_subcarrier((start_re + re) % frame_parms->ofdm_symbol_size, - n_rnti, - aarx, - pusch_pdu->dmrs_config_type, - K_ptrs, - pusch_pdu->rb_size, - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset, - start_re, - frame_parms->ofdm_symbol_size); - - if (is_ptrs_symbol_flag == 1) - num_ptrs_symbols++; - - } - - #ifdef DEBUG_RB_EXT - printf("re = %d, is_ptrs_symbol_flag = %d, symbol = %d\n", re, is_ptrs_symbol_flag, symbol); - #endif - - if ( is_dmrs_re == 0 && is_ptrs_symbol_flag == 0) { - - rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); - rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]); - ul_ch0_ext[ul_ch0_ext_index] = ul_ch0[ul_ch0_index]; - ul_ch0_ptrs_ext[ul_ch0_ptrs_ext_index] = ul_ch0_ptrs[ul_ch0_ptrs_index]; - - #ifdef DEBUG_RB_EXT - printf("rxF_ext[%d] = (%d,%d)\n", rxF_ext_index>>1, rxF_ext[rxF_ext_index],rxF_ext[rxF_ext_index+1]); - #endif - - ul_ch0_ext_index++; - ul_ch0_ptrs_ext_index++; - rxF_ext_index +=2; + if (is_dmrs_symbol == 0) { + // + //rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); + if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) { + memcpy1((void*)rxF_ext, + (void*)&rxF[start_re*2], + nb_re_pusch*sizeof(int32_t)); } else { - k_prime++; - k_prime&=1; - n+=(k_prime)?0:1; + int neg_length = frame_parms->ofdm_symbol_size-start_re; + int pos_length = nb_re_pusch-neg_length; + + memcpy1((void*)rxF_ext,(void*)&rxF[start_re*2],neg_length*sizeof(int32_t)); + memcpy1((void*)&rxF_ext[2*neg_length],(void*)rxF,pos_length*sizeof(int32_t)); + } + memcpy1((void*)ul_ch0_ext,(void*)ul_ch0,nb_re_pusch*sizeof(int32_t)); + } + else { + for (re = 0; re < nb_re_pusch; re++) { + + is_dmrs_re = (re == get_dmrs_freq_idx_ul(n, k_prime, delta, pusch_pdu->dmrs_config_type)); + +#ifdef DEBUG_RB_EXT + printf("re = %d, kprime %d, n %d, is_dmrs_symbol = %d, symbol = %d\n", re, k_prime, n, is_dmrs_symbol, symbol); +#endif + + /* save only data and respective channel estimates */ + if (is_dmrs_re == 0) { + rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); + rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]); + ul_ch0_ext[ul_ch0_ext_index] = ul_ch0[ul_ch0_index]; + +#ifdef DEBUG_RB_EXT + printf("dmrs symb %d: rxF_ext[%d] = (%d,%d), ul_ch0_ext[%d] = (%d,%d)\n", + is_dmrs_symbol,rxF_ext_index>>1, rxF_ext[rxF_ext_index],rxF_ext[rxF_ext_index+1], + ul_ch0_ext_index, ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[0], ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[1]); +#endif + ul_ch0_ext_index++; + rxF_ext_index +=2; + } else { + n += k_prime; + k_prime ^= 1; + } + ul_ch0_index++; } - ul_ch0_index++; - ul_ch0_ptrs_index++; } } - - pusch_vars->ptrs_sc_per_ofdm_symbol = num_ptrs_symbols; - } void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, @@ -344,7 +413,7 @@ void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, #if defined(__x86_64__)||defined(__i386__) short rb, ch_amp; - unsigned char aatx,aarx; + unsigned char aarx; __m128i *ul_ch128, ch_amp128; // Determine scaling amplitude based the symbol @@ -356,10 +425,15 @@ void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, ch_amp128 = _mm_set1_epi16(ch_amp); // Q3.13 - for (aatx=0; aatx < frame_parms->nb_antenna_ports_gNB; aatx++) { - for (aarx=0; aarx < frame_parms->nb_antennas_rx; aarx++) { +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif - ul_ch128 = (__m128i *)&ul_ch_estimates_ext[aarx][symbol*nb_rb*NR_NB_SC_PER_RB]; + for (aarx=0; aarx < frame_parms->nb_antennas_rx; aarx++) { + + ul_ch128 = (__m128i *)&ul_ch_estimates_ext[aarx][symbol*(off+(nb_rb*NR_NB_SC_PER_RB))]; if (is_dmrs_symbol==1){ if (pusch_dmrs_type == pusch_dmrs_type1) @@ -386,7 +460,6 @@ void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, } } } - } #endif } @@ -396,6 +469,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, int32_t *avg, uint8_t symbol, uint32_t len, + uint8_t nrOfLayers, unsigned short nb_rb) { @@ -408,12 +482,18 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, int16_t x = factor2(len); int16_t y = (len)>>x; - for (aatx = 0; aatx < frame_parms->nb_antennas_tx; aatx++) +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + + for (aatx = 0; aatx < nrOfLayers; aatx++) for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { //clear average level avg128U = _mm_setzero_si128(); - ul_ch128=(__m128i *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*nb_rb*12]; + ul_ch128=(__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; for (rb = 0; rb < len/12; rb++) { avg128U = _mm_add_epi32(avg128U, _mm_srai_epi32(_mm_madd_epi16(ul_ch128[0], ul_ch128[0]), x)); @@ -422,10 +502,10 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, ul_ch128+=3; } - avg[(aatx<<1)+aarx] = (((int32_t*)&avg128U)[0] + - ((int32_t*)&avg128U)[1] + - ((int32_t*)&avg128U)[2] + - ((int32_t*)&avg128U)[3] ) / y; + avg[aatx*frame_parms->nb_antennas_rx+aarx] = (((int32_t*)&avg128U)[0] + + ((int32_t*)&avg128U)[1] + + ((int32_t*)&avg128U)[2] + + ((int32_t*)&avg128U)[3]) / y; } @@ -441,13 +521,13 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; - for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { + for (aatx=0; aatxnb_antennas_rx; aarx++) { //clear average level avg128U = vdupq_n_s32(0); // 5 is always a symbol with no pilots for both normal and extended prefix - ul_ch128 = (int16x4_t *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; + ul_ch128 = (int16x4_t *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; for (rb = 0; rb < nb_rb; rb++) { // printf("rb %d : ",rb); @@ -457,7 +537,7 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, avg128U = vqaddq_s32(avg128U, vmull_s16(ul_ch128[2], ul_ch128[2])); avg128U = vqaddq_s32(avg128U, vmull_s16(ul_ch128[3], ul_ch128[3])); - if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_gNB!=1)) { + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(nrOfLayers!=1)) { ul_ch128+=4; } else { avg128U = vqaddq_s32(avg128U, vmull_s16(ul_ch128[4], ul_ch128[4])); @@ -479,10 +559,10 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, else nre=12; - avg[(aatx<<1)+aarx] = (((int32_t*)&avg128U)[0] + - ((int32_t*)&avg128U)[1] + - ((int32_t*)&avg128U)[2] + - ((int32_t*)&avg128U)[3] ) / (nb_rb*nre); + avg[aatx*frame_parms->nb_antennas_rx+aarx] = (((int32_t*)&avg128U)[0] + + ((int32_t*)&avg128U)[1] + + ((int32_t*)&avg128U)[2] + + ((int32_t*)&avg128U)[3]) / (nb_rb*nre); } } #endif @@ -498,25 +578,33 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, unsigned char symbol, uint8_t is_dmrs_symbol, unsigned char mod_order, + uint8_t nrOfLayers, unsigned short nb_rb, unsigned char output_shift) { +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + #ifdef DEBUG_CH_COMP int16_t *rxF, *ul_ch; int prnt_idx; + for (int ant=0; antnb_antennas_rx; ant++) { + rxF = (int16_t *)&rxdataF_ext[ant][symbol*(off+(nb_rb*12))]; + ul_ch = (int16_t *)&ul_ch_estimates_ext[ant][symbol*(off+(nb_rb*12))]; - rxF = (int16_t *)&rxdataF_ext[0][(symbol*nb_rb*12)]; - ul_ch = (int16_t *)&ul_ch_estimates_ext[0][symbol*nb_rb*12]; + printf("--------------------symbol = %d, mod_order = %d, output_shift = %d-----------------------\n", symbol, mod_order, output_shift); + printf("----------------Before compensation------------------\n"); - printf("--------------------symbol = %d, mod_order = %d, output_shift = %d-----------------------\n", symbol, mod_order, output_shift); - printf("----------------Before compensation------------------\n"); + for (prnt_idx=0;prnt_idx<12*5*2;prnt_idx+=2){ - for (prnt_idx=0;prnt_idx<12*nb_rb*2;prnt_idx+=2){ - - printf("rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]); - printf("ul_ch[%d] = (%d,%d)\n", prnt_idx>>1, ul_ch[prnt_idx],ul_ch[prnt_idx+1]); + printf("rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]); + printf("ul_ch[%d] = (%d,%d)\n", prnt_idx>>1, ul_ch[prnt_idx],ul_ch[prnt_idx+1]); + } } #endif @@ -526,28 +614,30 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, int print_idx; - ch_mag = (int16_t *)&ul_ch_mag[0][(symbol*nb_rb*12)]; + for (int ant=0; antnb_antennas_rx; ant++) { + ch_mag = (int16_t *)&ul_ch_mag[ant][symbol*(off+(nb_rb*12))]; - printf("--------------------symbol = %d, mod_order = %d-----------------------\n", symbol, mod_order); - printf("----------------Before computation------------------\n"); + printf("--------------------symbol = %d, mod_order = %d-----------------------\n", symbol, mod_order); + printf("----------------Before computation------------------\n"); - for (print_idx=0;print_idx<50;print_idx++){ + for (print_idx=0;print_idx<5;print_idx++){ - printf("ch_mag[%d] = %d\n", print_idx, ch_mag[print_idx]); + printf("ch_mag[%d] = %d\n", print_idx, ch_mag[print_idx]); + } } #endif -#if defined(__i386) || defined(__x86_64) +#if defined(__i386) || defined(__x86_64__) unsigned short rb; unsigned char aatx,aarx; __m128i *ul_ch128,*ul_ch128_2,*ul_ch_mag128,*ul_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0}; QAM_amp128b = _mm_setzero_si128(); - for (aatx=0; aatxnb_antennas_tx; aatx++) { + for (aatx=0; aatxnb_antennas_rx; aarx++) { - ul_ch128 = (__m128i *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*nb_rb*12]; - ul_ch_mag128 = (__m128i *)&ul_ch_mag[(aatx<<1)+aarx][symbol*nb_rb*12]; - ul_ch_mag128b = (__m128i *)&ul_ch_magb[(aatx<<1)+aarx][symbol*nb_rb*12]; - rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*nb_rb*12]; - rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*nb_rb*12]; + ul_ch128 = (__m128i *)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; + ul_ch_mag128 = (__m128i *)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; + ul_ch_mag128b = (__m128i *)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; + rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*(off+(nb_rb*12))]; + rxdataF_comp128 = (__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx+aarx][symbol*(off+(nb_rb*12))]; for (rb=0; rb=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { - if (frame_parms->nb_antenna_ports_gNB==1) { // 10 out of 12 so don't reduce size + if (nrOfLayers==1) { // 10 out of 12 so don't reduce size nb_rb=1+(5*nb_rb/6); } else { @@ -807,7 +897,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, } } - for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { + for (aatx=0; aatxnb_antennas_rx; aarx++) { - ul_ch128 = (int16x4_t*)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; - ul_ch_mag128 = (int16x8_t*)&ul_ch_mag[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; - ul_ch_mag128b = (int16x8_t*)&ul_ch_magb[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; + ul_ch128 = (int16x4_t*)&ul_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; + ul_ch_mag128 = (int16x8_t*)&ul_ch_mag[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; + ul_ch_mag128b = (int16x8_t*)&ul_ch_magb[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_UL*12]; - rxdataF_comp128 = (int16x4x2_t*)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_UL*12]; + rxdataF_comp128 = (int16x4x2_t*)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx+aarx][symbol*frame_parms->N_RB_UL*12]; for (rb=0; rb2) { @@ -981,14 +1071,16 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, #ifdef DEBUG_CH_COMP - rxF = (int16_t *)&rxdataF_comp[0][(symbol*nb_rb*12)]; + for (int ant=0; antnb_antennas_rx; ant++) { + rxF = (int16_t *)&rxdataF_comp[ant][(symbol*(off+(nb_rb*12)))]; - printf("----------------After compansation------------------\n"); + printf("----------------After compansation------------------\n"); - for (prnt_idx=0;prnt_idx<12*nb_rb*2;prnt_idx+=2){ + for (prnt_idx=0;prnt_idx<12*5*2;prnt_idx+=2){ - printf("rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]); + printf("rxF[%d] = (%d,%d)\n", prnt_idx>>1, rxF[prnt_idx],rxF[prnt_idx+1]); + } } #endif @@ -996,181 +1088,300 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, #ifdef DEBUG_CH_MAG - ch_mag = (int16_t *)&ul_ch_mag[0][(symbol*nb_rb*12)]; + for (int ant=0; antnb_antennas_rx; ant++) { + ch_mag = (int16_t *)&ul_ch_mag[ant][(symbol*(off+(nb_rb*12)))]; - printf("----------------After computation------------------\n"); + printf("----------------After computation------------------\n"); - for (print_idx=0;print_idx<12*nb_rb*2;print_idx+=2){ + for (print_idx=0;print_idx<12*5*2;print_idx+=2){ - printf("ch_mag[%d] = (%d,%d)\n", print_idx>>1, ch_mag[print_idx],ch_mag[print_idx+1]); + printf("ch_mag[%d] = (%d,%d)\n", print_idx>>1, ch_mag[print_idx],ch_mag[print_idx+1]); + } } #endif } +void nr_ulsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int32_t **ul_ch_mag, + int32_t **ul_ch_magb, + uint8_t symbol, + uint16_t nb_rb) { + int n_rx = frame_parms->nb_antennas_rx; +#if defined(__x86_64__) || defined(__i386__) + __m128i *rxdataF_comp128[1+n_rx],*ul_ch_mag128[1+n_rx],*ul_ch_mag128b[1+n_rx]; +#elif defined(__arm__) + int16x8_t *rxdataF_comp128_0,*ul_ch_mag128_0,*ul_ch_mag128_0b; + int16x8_t *rxdataF_comp128_1,*ul_ch_mag128_1,*ul_ch_mag128_1b; +#endif + int32_t i; + +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + + if (frame_parms->nb_antennas_rx>1) { +#if defined(__x86_64__) || defined(__i386__) + int nb_re = nb_rb*12; + for (int aa=0;aanb_antennas_rx;aa++) { + rxdataF_comp128[aa] = (__m128i *)&rxdataF_comp[aa][(symbol*(nb_re + off))]; + ul_ch_mag128[aa] = (__m128i *)&ul_ch_mag[aa][(symbol*(nb_re + off))]; + ul_ch_mag128b[aa] = (__m128i *)&ul_ch_magb[aa][(symbol*(nb_re + off))]; + } + for (int aa=1;aanb_antennas_rx;aa++) { + // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) + for (i=0; iN_RB_DL*12]; + rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_0 = (int16x8_t *)&ul_ch_mag[0][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_1 = (int16x8_t *)&ul_ch_mag[1][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_0b = (int16x8_t *)&ul_ch_magb[0][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_1b = (int16x8_t *)&ul_ch_magb[1][symbol*frame_parms->N_RB_DL*12]; + + // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) + for (i=0; iframe_parms; nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id][0]->harq_processes[harq_pid]->ulsch_pdu; + int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; - dmrs_symbol_flag = 0; - gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol = 0; - - if(symbol == rel15_ul->start_symbol_index){ - gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset = 0; - gNB->pusch_vars[ulsch_id]->dmrs_symbol = 0; - gNB->pusch_vars[ulsch_id]->cl_done = 0; - gNB->pusch_vars[ulsch_id]->ptrs_symbols = 0; - - if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { // if there is ptrs pdu - L_ptrs = 1<<(rel15_ul->pusch_ptrs.ptrs_time_density); - - set_ptrs_symb_idx(&gNB->pusch_vars[ulsch_id]->ptrs_symbols, - rel15_ul->nr_of_symbols, - rel15_ul->start_symbol_index, - L_ptrs, - rel15_ul->ul_dmrs_symb_pos); - } - } - - bwp_start_subcarrier = (rel15_ul->rb_start*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; - - dmrs_symbol_flag = ((rel15_ul->ul_dmrs_symb_pos)>>symbol)&0x01; - - if (dmrs_symbol_flag == 1){ - if (((rel15_ul->ul_dmrs_symb_pos)>>((symbol+1)%frame_parms->symbols_per_slot))&0x01) - AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); - - if (rel15_ul->dmrs_config_type == 0) { - // if no data in dmrs cdm group is 1 only even REs have no data - // if no data in dmrs cdm group is 2 both odd and even REs have no data - nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6)); - } - else { - nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4)); - } - gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; - } else { - nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB; - } - - if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { // if there is ptrs pdu - if(is_ptrs_symbol(symbol, gNB->pusch_vars[ulsch_id]->ptrs_symbols)) - gNB->pusch_vars[ulsch_id]->ptrs_symbol_index = symbol; - } + gNB->pusch_vars[ulsch_id]->dmrs_symbol = INVALID_VALUE; + gNB->pusch_vars[ulsch_id]->cl_done = 0; + bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; + LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset); + LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos); //---------------------------------------------------------- //--------------------- Channel estimation --------------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_channel_estimation_stats); - if (dmrs_symbol_flag == 1) - nr_pusch_channel_estimation(gNB, - nr_tti_rx, - 0, // p - symbol, - bwp_start_subcarrier, - rel15_ul); + for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { + uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag); + if (dmrs_symbol_flag == 1) { + if (gNB->pusch_vars[ulsch_id]->dmrs_symbol == INVALID_VALUE) + gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; + + for (int nl=0; nlnrOfLayers; nl++) + nr_pusch_channel_estimation(gNB, + slot, + get_dmrs_port(nl,rel15_ul->dmrs_ports), + symbol, + ulsch_id, + bwp_start_subcarrier, + rel15_ul); + + nr_gnb_measurements(gNB, ulsch_id, harq_pid, symbol,rel15_ul->nrOfLayers); + + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + if (symbol == rel15_ul->start_symbol_index) { + gNB->pusch_vars[ulsch_id]->ulsch_power[aarx] = 0; + gNB->pusch_vars[ulsch_id]->ulsch_noise_power[aarx] = 0; + } + gNB->pusch_vars[ulsch_id]->ulsch_power[aarx] += signal_energy_nodc( + &gNB->pusch_vars[ulsch_id]->ul_ch_estimates[aarx][symbol * frame_parms->ofdm_symbol_size], + rel15_ul->rb_size * 12); + for (int rb = 0; rb < rel15_ul->rb_size; rb++) { + gNB->pusch_vars[ulsch_id]->ulsch_noise_power[aarx] += + gNB->measurements.n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / + rel15_ul->rb_size; + } + } + } + } stop_meas(&gNB->ulsch_channel_estimation_stats); - //---------------------------------------------------------- - //--------------------- RBs extraction --------------------- - //---------------------------------------------------------- - if (nb_re_pusch > 0) { +#ifdef __AVX2__ + int off = ((rel15_ul->rb_size&1) == 1)? 4:0; +#else + int off = 0; +#endif + uint32_t rxdataF_ext_offset = 0; - start_meas(&gNB->ulsch_rbs_extraction_stats); - nr_ulsch_extract_rbs_single(gNB->common_vars.rxdataF, - gNB->pusch_vars[ulsch_id], - symbol, - dmrs_symbol_flag, - rel15_ul, - frame_parms); - stop_meas(&gNB->ulsch_rbs_extraction_stats); + for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { + uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; + if (dmrs_symbol_flag == 1) { + if ((rel15_ul->ul_dmrs_symb_pos >> ((symbol + 1) % frame_parms->symbols_per_slot)) & 0x01) + AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); - nr_ulsch_scale_channel(gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, - frame_parms, - gNB->ulsch[ulsch_id], - symbol, - dmrs_symbol_flag, - rel15_ul->rb_size, - rel15_ul->dmrs_config_type); + gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; - - if (gNB->pusch_vars[ulsch_id]->cl_done==0) { - - nr_ulsch_channel_level(gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, - frame_parms, - avg, - symbol, - nb_re_pusch, - rel15_ul->rb_size); - - avgs = 0; - - for (aatx=0;aatxnb_antennas_tx;aatx++) - for (aarx=0;aarxnb_antennas_rx;aarx++) - avgs = cmax(avgs,avg[(aatx<<1)+aarx]); - - gNB->pusch_vars[ulsch_id]->log2_maxh = (log2_approx(avgs)/2)+1; - gNB->pusch_vars[ulsch_id]->cl_done = 1; + if (rel15_ul->dmrs_config_type == 0) { + // if no data in dmrs cdm group is 1 only even REs have no data + // if no data in dmrs cdm group is 2 both odd and even REs have no data + nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6)); + } + else { + nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4)); + } + } else { + nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB; } - start_meas(&gNB->ulsch_channel_compensation_stats); - nr_ulsch_channel_compensation(gNB->pusch_vars[ulsch_id]->rxdataF_ext, - gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, - gNB->pusch_vars[ulsch_id]->ul_ch_mag0, - gNB->pusch_vars[ulsch_id]->ul_ch_magb0, - gNB->pusch_vars[ulsch_id]->rxdataF_comp, - (frame_parms->nb_antennas_tx>1) ? gNB->pusch_vars[ulsch_id]->rho : NULL, - frame_parms, + gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] = nb_re_pusch; + LOG_D(PHY,"symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, gNB->pusch_vars[ulsch_id]->dmrs_symbol); + + //---------------------------------------------------------- + //--------------------- RBs extraction --------------------- + //---------------------------------------------------------- + if (nb_re_pusch > 0) { + + start_meas(&gNB->ulsch_rbs_extraction_stats); + nr_ulsch_extract_rbs_single(gNB->common_vars.rxdataF, + gNB->pusch_vars[ulsch_id], + slot, symbol, dmrs_symbol_flag, - rel15_ul->qam_mod_order, - rel15_ul->rb_size, - gNB->pusch_vars[ulsch_id]->log2_maxh); - stop_meas(&gNB->ulsch_channel_compensation_stats); + rel15_ul, + frame_parms); + stop_meas(&gNB->ulsch_rbs_extraction_stats); + //---------------------------------------------------------- + //--------------------- Channel Scaling -------------------- + //---------------------------------------------------------- + nr_ulsch_scale_channel(gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, + frame_parms, + gNB->ulsch[ulsch_id], + symbol, + dmrs_symbol_flag, + rel15_ul->rb_size, + rel15_ul->dmrs_config_type); - int rxsig = signal_energy(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[0][(symbol*rel15_ul->rb_size*12)], - rel15_ul->rb_size*12); + if (gNB->pusch_vars[ulsch_id]->cl_done==0) { + nr_ulsch_channel_level(gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, + frame_parms, + avg, + symbol, + nb_re_pusch, + rel15_ul->nrOfLayers, + rel15_ul->rb_size); - if (rxsig==1) return (rxsig); + avgs = 0; -#ifdef NR_SC_FDMA - nr_idft(&((uint32_t*)gNB->pusch_vars[ulsch_id]->rxdataF_ext[0])[symbol * rel15_ul->rb_size * NR_NB_SC_PER_RB], nb_re_pusch); -#endif + for (aatx=0;aatxnrOfLayers;aatx++) + for (aarx=0;aarxnb_antennas_rx;aarx++) + avgs = cmax(avgs,avg[aatx*frame_parms->nb_antennas_rx+aarx]); - //---------------------------------------------------------- - //-------------------- LLRs computation -------------------- - //---------------------------------------------------------- - start_meas(&gNB->ulsch_llr_stats); - AssertFatal(gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset * rel15_ul->qam_mod_order+nb_re_pusch*rel15_ul->qam_mod_order < (8*((3*8*6144)+12)) , "Mysterious llr buffer size check"); - nr_ulsch_compute_llr(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[0][symbol * rel15_ul->rb_size * NR_NB_SC_PER_RB], - gNB->pusch_vars[ulsch_id]->ul_ch_mag0, - gNB->pusch_vars[ulsch_id]->ul_ch_magb0, - &gNB->pusch_vars[ulsch_id]->llr[gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset * rel15_ul->qam_mod_order], - rel15_ul->rb_size, - nb_re_pusch, - symbol, - rel15_ul->qam_mod_order); - stop_meas(&gNB->ulsch_llr_stats); + gNB->pusch_vars[ulsch_id]->log2_maxh = (log2_approx(avgs)/2)+2; + gNB->pusch_vars[ulsch_id]->cl_done = 1; + } - } + //---------------------------------------------------------- + //--------------------- Channel Compensation --------------- + //---------------------------------------------------------- + start_meas(&gNB->ulsch_channel_compensation_stats); + LOG_D(PHY,"Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n",gNB->pusch_vars[ulsch_id]->log2_maxh,avgs,avg[0],avg[1]); + nr_ulsch_channel_compensation(gNB->pusch_vars[ulsch_id]->rxdataF_ext, + gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, + gNB->pusch_vars[ulsch_id]->ul_ch_mag0, + gNB->pusch_vars[ulsch_id]->ul_ch_magb0, + gNB->pusch_vars[ulsch_id]->rxdataF_comp, + (rel15_ul->nrOfLayers>1) ? gNB->pusch_vars[ulsch_id]->rho : NULL, + frame_parms, + symbol, + dmrs_symbol_flag, + rel15_ul->qam_mod_order, + rel15_ul->nrOfLayers, + rel15_ul->rb_size, + gNB->pusch_vars[ulsch_id]->log2_maxh); + stop_meas(&gNB->ulsch_channel_compensation_stats); - gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset = gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset + nb_re_pusch; - return (0); + start_meas(&gNB->ulsch_mrc_stats); + nr_ulsch_detection_mrc(frame_parms, + gNB->pusch_vars[ulsch_id]->rxdataF_comp, + gNB->pusch_vars[ulsch_id]->ul_ch_mag0, + gNB->pusch_vars[ulsch_id]->ul_ch_magb0, + symbol, + rel15_ul->rb_size); + stop_meas(&gNB->ulsch_mrc_stats); + // transform precoding = 0 means enabled + if (rel15_ul->transform_precoding == 0) { + + #ifdef __AVX2__ + // For odd number of resource blocks need byte alignment to multiple of 8 + int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); + #else + int nb_re_pusch2 = nb_re_pusch; + #endif + + // perform IDFT operation on the compensated rxdata if transform precoding is enabled + nr_idft(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[0][symbol * nb_re_pusch2], nb_re_pusch); + LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d\n", symbol, nb_re_pusch); + } + + //---------------------------------------------------------- + //--------------------- PTRS Processing -------------------- + //---------------------------------------------------------- + /* In case PTRS is enabled then LLR will be calculated after PTRS symbols are processed * + * otherwise LLR are calculated for each symbol based upon DMRS channel estimates only. */ + if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + start_meas(&gNB->ulsch_ptrs_processing_stats); + nr_pusch_ptrs_processing(gNB, + frame_parms, + rel15_ul, + ulsch_id, + slot, + symbol, + nb_re_pusch); + stop_meas(&gNB->ulsch_ptrs_processing_stats); + + /* Subtract total PTRS RE's in the symbol from PUSCH RE's */ + gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] -= gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot; + } + + /*---------------------------------------------------------------------------------------------------- */ + /*-------------------- LLRs computation -------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------------------------*/ + start_meas(&gNB->ulsch_llr_stats); + nr_ulsch_compute_llr(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[0][symbol * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)], + gNB->pusch_vars[ulsch_id]->ul_ch_mag0, + gNB->pusch_vars[ulsch_id]->ul_ch_magb0, + &gNB->pusch_vars[ulsch_id]->llr[rxdataF_ext_offset * rel15_ul->qam_mod_order], + rel15_ul->rb_size, + gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol], + symbol, + rel15_ul->qam_mod_order); + stop_meas(&gNB->ulsch_llr_stats); + rxdataF_ext_offset += gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol]; + } + } // symbol loop + + return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index 233ecd8de7..bf96a76106 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -34,9 +34,6 @@ #include "PHY/sse_intrin.h" #include "PHY/impl_defs_top.h" -__m128i xmm0 __attribute__ ((aligned(32))); -__m128i xmm1 __attribute__ ((aligned(32))); -__m128i xmm2 __attribute__ ((aligned(32))); //---------------------------------------------------------------------------------------------- @@ -47,20 +44,19 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, uint32_t nb_re, uint8_t symbol) { - int i; - uint32_t *rxF = (uint32_t*)rxdataF_comp; uint32_t *llr32 = (uint32_t*)ulsch_llr; if (!llr32) { LOG_E(PHY,"nr_ulsch_qpsk_llr: llr is null, symbol %d, llr32 = %p\n",symbol, llr32); } - + /* for (i = 0; i < nb_re; i++) { *llr32 = *rxF; rxF++; llr32++; - } + }*/ + memcpy1((void*)llr32,(void*)rxF,nb_re<<2); } //---------------------------------------------------------------------------------------------- @@ -76,9 +72,17 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, { #if defined(__x86_64__) || defined(__i386__) +#ifdef __AVX2__ + __m256i *rxF = (__m256i*)rxdataF_comp; + __m256i *ch_mag; + __m256i llr256[2]; + register __m256i xmm0; +#else __m128i *rxF = (__m128i*)rxdataF_comp; __m128i *ch_mag; __m128i llr128[2]; + register __m128i xmm0; +#endif uint32_t *llr32; #elif defined(__arm__) @@ -90,7 +94,12 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, int i; - unsigned char len_mod4 = 0; + +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif #if defined(__x86_64__) || defined(__i386__) @@ -100,22 +109,69 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, #endif #if defined(__x86_64__) || defined(__i386__) - ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*nb_rb*12)]; +#ifdef __AVX2__ + ch_mag = (__m256i*)&ul_ch_mag[0][(symbol*(off+(nb_rb*12)))]; +#else + ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*(off+(nb_rb*12)))]; +#endif #elif defined(__arm__) ch_mag = (int16x8_t*)&ul_ch_mag[0][(symbol*nb_rb*12)]; #endif - len_mod4 = nb_re&3; +#ifdef __AVX2__ + unsigned char len_mod8 = nb_re&7; + nb_re >>= 3; // length in quad words (4 REs) + nb_re += (len_mod8 == 0 ? 0 : 1); +#else + unsigned char len_mod4 = nb_re&3; nb_re >>= 2; // length in quad words (4 REs) nb_re += (len_mod4 == 0 ? 0 : 1); +#endif for (i=0; i |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = _mm256_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + + llr256[0] = _mm256_unpacklo_epi32(rxF[i],xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs + llr256[1] = _mm256_unpackhi_epi32(rxF[i],xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs + + // 1st RE + llr32[0] = _mm256_extract_epi32(llr256[0],0); // llr32[0] low 16 bits-> y_R , high 16 bits-> y_I + llr32[1] = _mm256_extract_epi32(llr256[0],1); // llr32[1] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + // 2nd RE + llr32[2] = _mm256_extract_epi32(llr256[0],2); // llr32[2] low 16 bits-> y_R , high 16 bits-> y_I + llr32[3] = _mm256_extract_epi32(llr256[0],3); // llr32[3] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 3rd RE + llr32[4] = _mm256_extract_epi32(llr256[1],0); // llr32[4] low 16 bits-> y_R , high 16 bits-> y_I + llr32[5] = _mm256_extract_epi32(llr256[1],1); // llr32[5] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 4th RE + llr32[6] = _mm256_extract_epi32(llr256[1],2); // llr32[6] low 16 bits-> y_R , high 16 bits-> y_I + llr32[7] = _mm256_extract_epi32(llr256[1],3); // llr32[7] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 5th RE + llr32[8] = _mm256_extract_epi32(llr256[0],4); // llr32[8] low 16 bits-> y_R , high 16 bits-> y_I + llr32[9] = _mm256_extract_epi32(llr256[0],5); // llr32[9] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 6th RE + llr32[10] = _mm256_extract_epi32(llr256[0],6); // llr32[10] low 16 bits-> y_R , high 16 bits-> y_I + llr32[11] = _mm256_extract_epi32(llr256[0],7); // llr32[11] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 7th RE + llr32[12] = _mm256_extract_epi32(llr256[1],4); // llr32[12] low 16 bits-> y_R , high 16 bits-> y_I + llr32[13] = _mm256_extract_epi32(llr256[1],5); // llr32[13] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 8th RE + llr32[14] = _mm256_extract_epi32(llr256[1],6); // llr32[14] low 16 bits-> y_R , high 16 bits-> y_I + llr32[15] = _mm256_extract_epi32(llr256[1],7); // llr32[15] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + llr32+=16; +#else xmm0 = _mm_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - - xmm0 = _mm_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 llr128[0] = _mm_unpacklo_epi32(rxF[i],xmm0); // llr128[0] contains the llrs of the 1st and 2nd REs @@ -138,6 +194,7 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, llr32[7] = _mm_extract_epi32(llr128[1],3); // llr32[7] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 llr32+=8; +#endif #elif defined(__arm__) xmm0 = vabsq_s16(rxF[i]); xmm0 = vqsubq_s16((*(__m128i*)&ones[0]),xmm0); @@ -182,40 +239,69 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, uint8_t symbol) { +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + #if defined(__x86_64__) || defined(__i386__) +#ifdef __AVX2__ + __m256i *rxF = (__m256i*)rxdataF_comp; + __m256i *ch_mag,*ch_magb; + register __m256i xmm0,xmm1,xmm2; +#else __m128i *rxF = (__m128i*)rxdataF_comp; __m128i *ch_mag,*ch_magb; + register __m128i xmm0,xmm1,xmm2; +#endif #elif defined(__arm__) int16x8_t *rxF = (int16x8_t*)&rxdataF_comp; int16x8_t *ch_mag,*ch_magb; // [hna] This should be uncommented once channel estimation is implemented - int16x8_t xmm1,xmm2; + int16x8_t xmm0,xmm1,xmm2; #endif int i; - unsigned char len_mod4; #if defined(__x86_64__) || defined(__i386__) +#ifdef __AVX2__ + ch_mag = (__m256i*)&ul_ch_mag[0][(symbol*(off+(nb_rb*12)))]; + ch_magb = (__m256i*)&ul_ch_magb[0][(symbol*(off+(nb_rb*12)))]; +#else ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*nb_rb*12)]; ch_magb = (__m128i*)&ul_ch_magb[0][(symbol*nb_rb*12)]; +#endif #elif defined(__arm__) ch_mag = (int16x8_t*)&ul_ch_mag[0][(symbol*nb_rb*12)]; ch_magb = (int16x8_t*)&ul_ch_magb[0][(symbol*nb_rb*12)]; #endif - len_mod4 = nb_re&3; +#ifdef __AVX2__ + int len_mod8 = nb_re&7; + nb_re = nb_re>>3; // length in quad words (4 REs) + nb_re += ((len_mod8 == 0) ? 0 : 1); +#else + int len_mod4 = nb_re&3; nb_re = nb_re>>2; // length in quad words (4 REs) nb_re += ((len_mod4 == 0) ? 0 : 1); - +#endif for (i=0; ipucch[i]!=NULL,"gNB->pucch[%d] is null\n",i); if ((gNB->pucch[i]->active >0) && (gNB->pucch[i]->pucch_pdu.rnti==rnti) && @@ -96,7 +98,6 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, pucch->slot = slot; pucch->active = 1; memcpy((void*)&pucch->pucch_pdu, (void*)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); - } @@ -162,14 +163,14 @@ int16_t idft12_im[12][12] = { void nr_decode_pucch0(PHY_VARS_gNB *gNB, + int frame, int slot, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu) { - int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - + int soffset=(slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; int nr_sequences; const uint8_t *mcs; @@ -179,6 +180,19 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, "Either bit_len_harq (%d) or sr_flag (%d) must be > 0\n", pucch_pdu->bit_len_harq,pucch_pdu->sr_flag); + NR_gNB_UCI_STATS_t *uci_stats=NULL; + NR_gNB_UCI_STATS_t *first_uci_stats=NULL; + for (int i=0;iuci_stats[i].rnti == pucch_pdu->rnti) { + uci_stats = &gNB->uci_stats[i]; + break; + } else if (first_uci_stats == NULL && gNB->uci_stats[i].rnti == 0) first_uci_stats = &gNB->uci_stats[i]; + + if (uci_stats == NULL) { uci_stats=first_uci_stats; uci_stats->rnti = pucch_pdu->rnti;} + + AssertFatal(uci_stats!=NULL,"No stat index found\n"); + uci_stats->frame = frame; + if(pucch_pdu->bit_len_harq==0){ mcs=table1_mcs; nr_sequences=1; @@ -192,6 +206,10 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, nr_sequences=8>>(1-pucch_pdu->sr_flag); } + LOG_D(PHY,"pucch0: nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, O_ACK %d, O_SR %d, mcs %d initial_cyclic_shift %d\n", + pucch_pdu->nr_of_symbols,pucch_pdu->start_symbol_index,pucch_pdu->prb_start,pucch_pdu->second_hop_prb,pucch_pdu->group_hop_flag,pucch_pdu->sequence_hop_flag,pucch_pdu->bit_len_harq, + pucch_pdu->sr_flag,mcs[0],pucch_pdu->initial_cyclic_shift); + int cs_ind = get_pucch0_cs_lut_index(gNB,pucch_pdu); /* * Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation @@ -218,204 +236,223 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, * x(l*12+n) = r_u_v_alpha_delta(n) */ // the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1 - uint8_t u=0,v=0;//,delta=0; - // if frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping - // n_hop = 0 - // if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping - // n_hop = 0 for first hop - // n_hop = 1 for second hop - uint8_t n_hop = 0; // Frequnecy hopping not implemented FIXME!! + uint8_t u[2]={0,0},v[2]={0,0}; // x_n contains the sequence r_u_v_alpha_delta(n) - int n,i,l; - nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,slot,&u,&v); // calculating u and v value + int n,i; + int prb_offset[2] = {pucch_pdu->bwp_start+pucch_pdu->prb_start, pucch_pdu->bwp_start+pucch_pdu->prb_start}; - uint32_t re_offset=0; + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,0,slot,&u[0],&v[0]); // calculating u and v value first hop + LOG_D(PHY,"pucch0: u %d, v %d\n",u[0],v[0]); + + + if (pucch_pdu->freq_hop_flag == 1) { + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,1,slot,&u[1],&v[1]); // calculating u and v value second hop + LOG_D(PHY,"pucch0 second hop: u %d, v %d\n",u[1],v[1]); + prb_offset[1] = pucch_pdu->bwp_start+pucch_pdu->second_hop_prb; + } + + + AssertFatal(pucch_pdu->nr_of_symbols < 3,"nr_of_symbols %d not allowed\n",pucch_pdu->nr_of_symbols); + uint32_t re_offset[2]={0,0}; uint8_t l2; -#ifdef OLD_IMPL - int16_t x_n_re[nr_sequences][24],x_n_im[nr_sequences][24]; + const int16_t *x_re[2],*x_im[2]; + x_re[0] = table_5_2_2_2_2_Re[u[0]]; + x_im[0] = table_5_2_2_2_2_Im[u[0]]; + x_re[1] = table_5_2_2_2_2_Re[u[1]]; + x_im[1] = table_5_2_2_2_2_Im[u[1]]; - for(i=0;inr_of_symbols; l++){ - double alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,pucch_pdu->initial_cyclic_shift,mcs[i],l,pucch_pdu->start_symbol_index,slot); -#ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d/%d,mcs %d)\n",u,v,alpha,l,l+pucch_pdu->start_symbol_index,mcs[i]); - printf("lut output %d\n",gNB->pucch0_lut.lut[cs_ind][slot][l+pucch_pdu->start_symbol_index]); -#endif - alpha=0.0; - for (n=0; n<12; n++){ - x_n_re[i][(12*l)+n] = (int16_t)((int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) - - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)))); // Re part of base sequence shifted by alpha - x_n_im[i][(12*l)+n] =(int16_t)((int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) - + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)))); // Im part of base sequence shifted by alpha -#ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d) %d,%d\n", - u,v,alpha,l,n,x_n_re[i][(12*l)+n],x_n_im[i][(12*l)+n], - (int32_t)(round(32767*cos(alpha*n))), - (int32_t)(round(32767*sin(alpha*n)))); -#endif - } - } - } - /* - * Implementing TS 38.211 Subclause 6.3.2.3.2 Mapping to physical resources - */ - - int16_t r_re[24],r_im[24]; - - for (l=0; lnr_of_symbols; l++) { - - l2 = l+pucch_pdu->start_symbol_index; - re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; - if (re_offset>= frame_parms->ofdm_symbol_size) - re_offset-=frame_parms->ofdm_symbol_size; - - for (n=0; n<12; n++){ - - r_re[(12*l)+n]=((int16_t *)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset])[0]; - r_im[(12*l)+n]=((int16_t *)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset])[1]; -#ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch0] mapping to RE \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", - frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,(l2*frame_parms->ofdm_symbol_size)+re_offset, - l,n,((int16_t *)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset])[0], - ((int16_t *)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset])[1]); -#endif - re_offset++; - if (re_offset>= frame_parms->ofdm_symbol_size) - re_offset-=frame_parms->ofdm_symbol_size; - } - } - double corr[nr_sequences],corr_re[nr_sequences],corr_im[nr_sequences]; - memset(corr,0,nr_sequences*sizeof(double)); - memset(corr_re,0,nr_sequences*sizeof(double)); - memset(corr_im,0,nr_sequences*sizeof(double)); - for(i=0;inr_of_symbols;l++){ - for(n=0;n<12;n++){ - corr_re[i]+= (double)(r_re[12*l+n])/32767*(double)(x_n_re[i][12*l+n])/32767+(double)(r_im[12*l+n])/32767*(double)(x_n_im[i][12*l+n])/32767; - corr_im[i]+= (double)(r_re[12*l+n])/32767*(double)(x_n_im[i][12*l+n])/32767-(double)(r_im[12*l+n])/32767*(double)(x_n_re[i][12*l+n])/32767; - } - } - corr[i]=corr_re[i]*corr_re[i]+corr_im[i]*corr_im[i]; - } - float max_corr=corr[0]; + int16_t xr[1+frame_parms->nb_antennas_rx][1+pucch_pdu->nr_of_symbols][24] __attribute__((aligned(32))); + int64_t xrtmag=0,xrtmag_next=0; + uint8_t maxpos=0; uint8_t index=0; - for(i=1;imax_corr){ - index= i; - max_corr=corr[i]; + for (int l=0; lnr_of_symbols; l++) { + for (int aarx=0;aarxnb_antennas_rx;aarx++) { + memset((void*)xr[aarx][l],0,24*sizeof(int16_t)); } } -#else - - const int16_t *x_re = table_5_2_2_2_2_Re[u],*x_im = table_5_2_2_2_2_Im[u]; - int16_t xr[24] __attribute__((aligned(32))); - //int16_t xrt[24] __attribute__((aligned(32))); - int32_t xrtmag=0; - int maxpos=0; - int n2=0; - uint8_t index=0; - memset((void*)xr,0,24*sizeof(int16_t)); - - for (l=0; lnr_of_symbols; l++) { + int n2; + for (int l=0; lnr_of_symbols; l++) { l2 = l+pucch_pdu->start_symbol_index; - re_offset = (12*pucch_pdu->prb_start) + frame_parms->first_carrier_offset; - if (re_offset>= frame_parms->ofdm_symbol_size) - re_offset-=frame_parms->ofdm_symbol_size; + re_offset[l] = (12*prb_offset[l]) + frame_parms->first_carrier_offset; + if (re_offset[l]>= frame_parms->ofdm_symbol_size) + re_offset[l]-=frame_parms->ofdm_symbol_size; - AssertFatal(re_offset+12 < frame_parms->ofdm_symbol_size,"pucch straddles DC carrier, handle this!\n"); - - int16_t *r=(int16_t*)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size+re_offset)]; - for (n=0;n<12;n++,n2+=2) { - xr[n2] =(int16_t)(((int32_t)x_re[n]*r[n2]+(int32_t)x_im[n]*r[n2+1])>>15); - xr[n2+1]=(int16_t)(((int32_t)x_re[n]*r[n2+1]-(int32_t)x_im[n]*r[n2])>>15); + AssertFatal(re_offset[l]+12 < frame_parms->ofdm_symbol_size,"pucch straddles DC carrier, handle this!\n"); + int16_t *r; + for (int aa=0;aanb_antennas_rx;aa++) { + r=(int16_t*)&rxdataF[aa][soffset+(l2*frame_parms->ofdm_symbol_size)+re_offset[l]]; + n2=0; + for (n=0;n<12;n++,n2+=2) { + xr[aa][l][n2] +=(int16_t)(((int32_t)x_re[l][n]*r[n2]+(int32_t)x_im[l][n]*r[n2+1])>>15); + xr[aa][l][n2+1]+=(int16_t)(((int32_t)x_re[l][n]*r[n2+1]-(int32_t)x_im[l][n]*r[n2])>>15); #ifdef DEBUG_NR_PUCCH_RX - printf("x (%d,%d), r (%d,%d), xr (%d,%d)\n", - x_re[n],x_im[n],r[n2],r[n2+1],xr[n2],xr[n2+1]); + printf("x (%d,%d), r%d.%d (%d,%d), xr (%d,%d)\n", + x_re[l][n],x_im[l][n],l2,re_offset[l],r[n2],r[n2+1],xr[aa][l][n2],xr[aa][l][n2+1]); #endif + } } } - int32_t corr_re,corr_im,temp; + + int32_t corr_re[1+frame_parms->nb_antennas_rx][2]; + int32_t corr_im[1+frame_parms->nb_antennas_rx][2]; + //int32_t no_corr = 0; int seq_index; + int64_t temp; for(i=0;inr_of_symbols;l++) { + for (int l=0;lnr_of_symbols;l++) { seq_index = (pucch_pdu->initial_cyclic_shift+ mcs[i]+ gNB->pucch0_lut.lut[cs_ind][slot][l+pucch_pdu->start_symbol_index])%12; - for (n=0;n<12;n++,n2+=2) { - corr_re+=(xr[n2]*idft12_re[seq_index][n]+xr[n2+1]*idft12_im[seq_index][n])>>15; - corr_im+=(xr[n2]*idft12_im[seq_index][n]-xr[n2+1]*idft12_re[seq_index][n])>>15; +#ifdef DEBUG_NR_PUCCH_RX + printf("PUCCH symbol %d seq %d, seq_index %d, mcs %d\n",l,i,seq_index,mcs[i]); +#endif + for (int aa=0;aanb_antennas_rx;aa++) { + corr_re[aa][l]=0; + corr_im[aa][l]=0; + + n2=0; + for (n=0;n<12;n++,n2+=2) { + corr_re[aa][l]+=(xr[aa][l][n2]*idft12_re[seq_index][n]+xr[aa][l][n2+1]*idft12_im[seq_index][n])>>15; + corr_im[aa][l]+=(xr[aa][l][n2]*idft12_im[seq_index][n]-xr[aa][l][n2+1]*idft12_re[seq_index][n])>>15; + } } } - -#ifdef DEBUG_NR_PUCCH_RX - printf("PUCCH IDFT[%d/%d] = (%d,%d)=>%f\n",mcs[i],seq_index,corr_re,corr_im,10*log10(corr_re*corr_re + corr_im*corr_im)); -#endif - if ((temp=corr_re*corr_re + corr_im*corr_im)>xrtmag) { - xrtmag=temp; - maxpos=i; + LOG_D(PHY,"PUCCH IDFT[%d/%d] = (%d,%d)=>%f\n", + mcs[i],seq_index,corr_re[0][0],corr_im[0][0], + 10*log10((double)corr_re[0][0]*corr_re[0][0] + (double)corr_im[0][0]*corr_im[0][0])); + if (pucch_pdu->nr_of_symbols==2) + LOG_D(PHY,"PUCCH 2nd symbol IDFT[%d/%d] = (%d,%d)=>%f\n", + mcs[i],seq_index,corr_re[0][1],corr_im[0][1], + 10*log10((double)corr_re[0][1]*corr_re[0][1] + (double)corr_im[0][1]*corr_im[0][1])); + if (pucch_pdu->freq_hop_flag == 0) { + if (pucch_pdu->nr_of_symbols==1) {// non-coherent correlation + temp=0; + for (int aa=0;aanb_antennas_rx;aa++) + temp+=(int64_t)corr_re[aa][0]*corr_re[aa][0] + (int64_t)corr_im[aa][0]*corr_im[aa][0]; + } else { + int64_t corr_re2=0; + int64_t corr_im2=0; + temp=0; + for (int aa=0;aanb_antennas_rx;aa++) { + corr_re2 = (int64_t)corr_re[aa][0]+corr_re[aa][1]; + corr_im2 = (int64_t)corr_im[aa][0]+corr_im[aa][1]; + // coherent combining of 2 symbols and then complex modulus for single-frequency case + temp+=corr_re2*corr_re2 + corr_im2*corr_im2; + } + } + } else if (pucch_pdu->freq_hop_flag == 1) { + // full non-coherent combining of 2 symbols for frequency-hopping case + temp=0; + for (int aa=0;aanb_antennas_rx;aa++) + temp += (int64_t)corr_re[aa][0]*corr_re[aa][0] + (int64_t)corr_im[aa][0]*corr_im[aa][0] + (int64_t)corr_re[aa][1]*corr_re[aa][1] + (int64_t)corr_im[aa][1]*corr_im[aa][1]; } + else AssertFatal(1==0,"shouldn't happen\n"); + + if (temp>xrtmag) { + xrtmag_next = xrtmag; + xrtmag=temp; + LOG_D(PHY,"Sequence %d xrtmag %ld xrtmag_next %ld\n", i, xrtmag, xrtmag_next); + maxpos=i; + uci_stats->current_pucch0_stat0 = 0; + int64_t temp2=0,temp3=0;; + for (int aa=0;aanb_antennas_rx;aa++) { + temp2 += ((int64_t)corr_re[aa][0]*corr_re[aa][0] + (int64_t)corr_im[aa][0]*corr_im[aa][0]); + if (pucch_pdu->nr_of_symbols==2) + temp3 += ((int64_t)corr_re[aa][1]*corr_re[aa][1] + (int64_t)corr_im[aa][1]*corr_im[aa][1]); + } + uci_stats->current_pucch0_stat0= dB_fixed64(temp2); + if ( pucch_pdu->nr_of_symbols==2) + uci_stats->current_pucch0_stat1= dB_fixed64(temp3); + } + else if (temp>xrtmag_next) + xrtmag_next = temp; } - uint8_t xrtmag_dB = dB_fixed(xrtmag); - -//#ifdef DEBUG_NR_PUCCH_RX + int xrtmag_dBtimes10 = 10*(int)dB_fixed64(xrtmag/(12*pucch_pdu->nr_of_symbols)); + int xrtmag_next_dBtimes10 = 10*(int)dB_fixed64(xrtmag_next/(12*pucch_pdu->nr_of_symbols)); +#ifdef DEBUG_NR_PUCCH_RX printf("PUCCH 0 : maxpos %d\n",maxpos); -//#endif +#endif index=maxpos; -#endif + uci_stats->pucch0_n00 = gNB->measurements.n0_subband_power_tot_dB[prb_offset[0]]; + uci_stats->pucch0_n01 = gNB->measurements.n0_subband_power_tot_dB[prb_offset[1]]; + LOG_D(PHY,"n00[%d] = %d, n01[%d] = %d\n",prb_offset[0],uci_stats->pucch0_n00,prb_offset[1],uci_stats->pucch0_n01); + // estimate CQI for MAC (from antenna port 0 only) + int max_n0 = uci_stats->pucch0_n00>uci_stats->pucch0_n01 ? uci_stats->pucch0_n00:uci_stats->pucch0_n01; + int SNRtimes10,sigenergy=0; + for (int aa=0;aanb_antennas_rx;aa++) + sigenergy += signal_energy_nodc(&rxdataF[aa][soffset+ + (pucch_pdu->start_symbol_index*frame_parms->ofdm_symbol_size)+ + re_offset[0]],12); + SNRtimes10 = xrtmag_dBtimes10-(10*max_n0); + int cqi; + if (SNRtimes10 < -640) cqi=0; + else if (SNRtimes10 > 635) cqi=255; + else cqi=(640+SNRtimes10)/5; + + uci_stats->pucch0_thres = gNB->pucch0_thres; /* + (10*max_n0);*/ + bool no_conf=false; + if (nr_sequences>1) { + if (xrtmag_dBtimes10 < (50+xrtmag_next_dBtimes10) || SNRtimes10 < uci_stats->pucch0_thres) + no_conf=true; + } + gNB->bad_pucch += no_conf; // first bit of bitmap for sr presence and second bit for acknack presence uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq>0)<<1); uci_pdu->pucch_format = 0; // format 0 - uci_pdu->ul_cqi = 0xff; // currently not valid + uci_pdu->rnti = pucch_pdu->rnti; + uci_pdu->ul_cqi = cqi; uci_pdu->timing_advance = 0xffff; // currently not valid - uci_pdu->rssi = 0xffff; // currently not valid + uci_pdu->rssi = 1280 - (10*dB_fixed(32767*32767))-dB_fixed_times10(sigenergy); if (pucch_pdu->bit_len_harq==0) { uci_pdu->harq = NULL; uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); - if (xrtmag_dB>(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres)) { + uci_pdu->sr->sr_confidence_level = no_conf ? 1 : 0; + uci_stats->pucch0_sr_trials++; + if (xrtmag_dBtimes10>(10*gNB->measurements.n0_power_tot_dB)) { uci_pdu->sr->sr_indication = 1; - uci_pdu->sr->sr_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_stats->pucch0_positive_SR++; } else { uci_pdu->sr->sr_indication = 0; - uci_pdu->sr->sr_confidence_level = (gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres)-xrtmag_dB; } } else if (pucch_pdu->bit_len_harq==1) { uci_pdu->harq = calloc(1,sizeof(*uci_pdu->harq)); uci_pdu->harq->num_harq = 1; - uci_pdu->harq->harq_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_pdu->harq->harq_confidence_level = no_conf ? 1 : 0; uci_pdu->harq->harq_list = (nfapi_nr_harq_t*)malloc(1); - uci_pdu->harq->harq_list[0].harq_value = index&0x01; + uci_pdu->harq->harq_list[0].harq_value = !(index&0x01); + LOG_D(PHY, "[DLSCH/PDSCH/PUCCH] %d.%d HARQ value %d (0 pass, 1 fail) with confidence level %d (0 is good, 1 is bad) xrt_mag %d xrt_mag_next %d n0 %d (%d,%d) pucch0_thres %d, cqi %d, SNRtimes10 %d, energy %f, sync_pos %d\n", + frame,slot,uci_pdu->harq->harq_list[0].harq_value,uci_pdu->harq->harq_confidence_level,xrtmag_dBtimes10,xrtmag_next_dBtimes10,max_n0,uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_thres,cqi,SNRtimes10,10*log10((double)sigenergy),gNB->ulsch_stats[0].sync_pos); if (pucch_pdu->sr_flag == 1) { uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); uci_pdu->sr->sr_indication = (index>1) ? 1 : 0; - uci_pdu->sr->sr_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_pdu->sr->sr_confidence_level = no_conf ? 1 : 0; + uci_stats->pucch0_positive_SR++; } + uci_stats->pucch01_trials++; } else { uci_pdu->harq = calloc(1,sizeof(*uci_pdu->harq)); uci_pdu->harq->num_harq = 2; - uci_pdu->harq->harq_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_pdu->harq->harq_confidence_level = (no_conf) ? 1 : 0; uci_pdu->harq->harq_list = (nfapi_nr_harq_t*)malloc(2); - - uci_pdu->harq->harq_list[1].harq_value = index&0x01; - uci_pdu->harq->harq_list[0].harq_value = (index>>1)&0x01; - + uci_pdu->harq->harq_list[1].harq_value = !(index&0x01); + uci_pdu->harq->harq_list[0].harq_value = !((index>>1)&0x01); + LOG_D(PHY, "[DLSCH/PDSCH/PUCCH] %d.%d HARQ values %d (0 pass, 1 fail) and %d with confidence level %d (0 is good, 1 is bad), xrt_mag %d xrt_mag_next %d n0 %d (%d,%d) pucch0_thres %d, cqi %d, SNRtimes10 %d,sync_pos %d\n", + frame,slot,uci_pdu->harq->harq_list[1].harq_value,uci_pdu->harq->harq_list[0].harq_value,uci_pdu->harq->harq_confidence_level,xrtmag_dBtimes10,xrtmag_next_dBtimes10,max_n0,uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_thres,cqi,SNRtimes10,gNB->ulsch_stats[0].sync_pos); if (pucch_pdu->sr_flag == 1) { uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); uci_pdu->sr->sr_indication = (index>3) ? 1 : 0; - uci_pdu->sr->sr_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_pdu->sr->sr_confidence_level = (no_conf) ? 1 : 0; } } } @@ -446,6 +483,7 @@ void nr_decode_pucch1( int32_t **rxdataF, * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation * */ + int soffset = (nr_tti_tx&3)*frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; // complex-valued symbol d_re, d_im containing complex-valued symbol d(0): int16_t d_re=0, d_im=0,d1_re=0,d1_im=0; #ifdef DEBUG_NR_PUCCH_RX @@ -540,23 +578,23 @@ void nr_decode_pucch1( int32_t **rxdataF, } if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1 - z_re_rx[i+n] = ((int16_t *)&rxdataF[0][re_offset])[0]; - z_im_rx[i+n] = ((int16_t *)&rxdataF[0][re_offset])[1]; + z_re_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[0]; + z_im_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[1]; #ifdef DEBUG_NR_PUCCH_RX printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n", amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, - l,n,((int16_t *)&rxdataF[0][re_offset])[0],((int16_t *)&rxdataF[0][re_offset])[1]); + l,n,((int16_t *)&rxdataF[0][soffset+re_offset])[0],((int16_t *)&rxdataF[0][soffset+re_offset])[1]); #endif } if (l%2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1 - z_dmrs_re_rx[i+n] = ((int16_t *)&rxdataF[0][re_offset])[0]; - z_dmrs_im_rx[i+n] = ((int16_t *)&rxdataF[0][re_offset])[1]; + z_dmrs_re_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[0]; + z_dmrs_im_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[1]; // printf("%d\t%d\t%d\n",l,z_dmrs_re_rx[i+n],z_dmrs_im_rx[i+n]); #ifdef DEBUG_NR_PUCCH_RX printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n", amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, - l,n,((int16_t *)&rxdataF[0][re_offset])[0],((int16_t *)&rxdataF[0][re_offset])[1]); + l,n,((int16_t *)&rxdataF[0][soffset+re_offset])[0],((int16_t *)&rxdataF[0][soffset+re_offset])[1]); #endif // printf("l=%d\ti=%d\tre_offset=%d\treceived dmrs re=%d\tim=%d\n",l,i,re_offset,z_dmrs_re_rx[i+n],z_dmrs_im_rx[i+n]); } @@ -1047,6 +1085,8 @@ void init_pucch2_luts() { bit = (i&0x80) > 0 ? 0 : 1; *lut_num_i = _mm_insert_epi16(*lut_num_i,bit,7); *lut_den_i = _mm_insert_epi16(*lut_den_i,1-bit,7); + +#ifdef DEBUG_NR_PUCCH_RX printf("i %d, lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",i, ((int16_t *)lut_num_i)[0], ((int16_t *)lut_num_i)[1], @@ -1056,6 +1096,7 @@ void init_pucch2_luts() { ((int16_t *)lut_num_i)[5], ((int16_t *)lut_num_i)[6], ((int16_t *)lut_num_i)[7]); +#endif } } @@ -1069,130 +1110,125 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); - - AssertFatal(pucch_pdu->nr_of_symbols==1 || pucch_pdu->nr_of_symbols==2, "Illegal number of symbols for PUCCH 2 %d\n",pucch_pdu->nr_of_symbols); + AssertFatal((pucch_pdu->prb_start-((pucch_pdu->prb_start>>2)<<2))==0, + "Current pucch2 receiver implementation requires a PRB offset multiple of 4. The one selected is %d", + pucch_pdu->prb_start); //extract pucch and dmrs first int l2=pucch_pdu->start_symbol_index; - int re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; - if (re_offset>= frame_parms->ofdm_symbol_size) - re_offset-=frame_parms->ofdm_symbol_size; - + int re_offset[2]; + re_offset[0] = 12*(pucch_pdu->prb_start+pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; + int soffset=(slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + + if (re_offset[0]>= frame_parms->ofdm_symbol_size) + re_offset[0]-=frame_parms->ofdm_symbol_size; + if (pucch_pdu->freq_hop_flag == 0) re_offset[1] = re_offset[0]; + else { + re_offset[1] = 12*(pucch_pdu->second_hop_prb+pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; + if (re_offset[1]>= frame_parms->ofdm_symbol_size) + re_offset[1]-=frame_parms->ofdm_symbol_size; + } AssertFatal(pucch_pdu->prb_size*pucch_pdu->nr_of_symbols > 1,"number of PRB*SYMB (%d,%d)< 2", pucch_pdu->prb_size,pucch_pdu->nr_of_symbols); int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value; int Prx2 = (Prx==1)?2:Prx; // use 2 for Nb antennas in case of single antenna to allow the following allocations - int16_t r_re_ext[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); - int16_t r_im_ext[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); - int16_t r_re_ext2[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); - int16_t r_im_ext2[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); - int16_t rd_re_ext[Prx2][4*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); - int16_t rd_im_ext[Prx2][4*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int prb_size_ext = pucch_pdu->prb_size+(pucch_pdu->prb_size&1); + int16_t r_re_ext[Prx2][2][8*prb_size_ext] __attribute__((aligned(32))); + int16_t r_im_ext[Prx2][2][8*prb_size_ext] __attribute__((aligned(32))); + int16_t r_re_ext2[Prx2][2][8*prb_size_ext] __attribute__((aligned(32))); + int16_t r_im_ext2[Prx2][2][8*prb_size_ext] __attribute__((aligned(32))); + int16_t rd_re_ext[Prx2][2][4*prb_size_ext] __attribute__((aligned(32))); + int16_t rd_im_ext[Prx2][2][4*prb_size_ext] __attribute__((aligned(32))); int16_t *r_re_ext_p,*r_im_ext_p,*rd_re_ext_p,*rd_im_ext_p; - int16_t *rp[Prx2]; + int nb_re_pucch = 12*pucch_pdu->prb_size; + + int16_t rp[Prx2][2][nb_re_pucch*2],*tmp_rp; __m64 dmrs_re,dmrs_im; - for (int aa=0;aaofdm_symbol_size)+re_offset]); + for (int aa=0;aanr_of_symbols;symb++) { + tmp_rp = ((int16_t *)&rxdataF[aa][soffset + (l2+symb)*frame_parms->ofdm_symbol_size]); + if (re_offset[symb] + nb_re_pucch < frame_parms->ofdm_symbol_size) { + memcpy1((void*)rp[aa][symb],(void*)&tmp_rp[re_offset[symb]*2],nb_re_pucch*sizeof(int32_t)); + } + else { + int neg_length = frame_parms->ofdm_symbol_size-re_offset[symb]; + int pos_length = nb_re_pucch-neg_length; + memcpy1((void*)rp[aa][symb],(void*)&tmp_rp[re_offset[symb]*2],neg_length*sizeof(int32_t)); + memcpy1((void*)&rp[aa][symb][neg_length*2],(void*)tmp_rp,pos_length*sizeof(int32_t)); + } + } + } #ifdef DEBUG_NR_PUCCH_RX printf("Decoding pucch2 for %d symbols, %d PRB\n",pucch_pdu->nr_of_symbols,pucch_pdu->prb_size); #endif int nc_group_size=1; // 2 PRB - int ngroup = pucch_pdu->prb_size/nc_group_size/2; - int32_t corr32_re[ngroup][Prx2],corr32_im[ngroup][Prx2]; - for (int aa=0;aanr_of_symbols == 1) { - AssertFatal((pucch_pdu->prb_size&1) == 0,"prb_size %d is not a multiple of 2\n",pucch_pdu->prb_size); - // 24 PRBs contains 48x16-bit, so 6x8x16-bit + // AssertFatal((pucch_pdu->prb_size&1) == 0,"prb_size %d is not a multiple of 2\n",pucch_pdu->prb_size); + if ((pucch_pdu->prb_size&1) > 0) { // if the number of PRBs is odd + for (int symb=0; symbnr_of_symbols;symb++) { + for (int aa=0;aaprb_size],0,8*pucch_pdu->prb_size*sizeof(int16_t)); + memset(&r_im_ext[aa][symb][8*pucch_pdu->prb_size],0,8*pucch_pdu->prb_size*sizeof(int16_t)); + memset(&rd_re_ext[aa][symb][4*pucch_pdu->prb_size],0,8*pucch_pdu->prb_size*sizeof(int16_t)); + memset(&rd_im_ext[aa][symb][4*pucch_pdu->prb_size],0,8*pucch_pdu->prb_size*sizeof(int16_t)); + } + } + } + for (int symb=0; symbnr_of_symbols;symb++) { + // 24 REs contains 48x16-bit, so 6x8x16-bit for (int prb=0;prbprb_size;prb+=2) { for (int aa=0;aa (%d,%d)\n",aa,prb+(i>>2),i,rd_re_ext_p[i],rd_im_ext_p[i]); - for (int i=0;i<16;i++) printf("Ant %d PRB %d data[%d] -> (%d,%d)\n",aa,prb+(i>>3),i,r_re_ext_p[i],r_im_ext_p[i]); + for (int i=0;i<8;i++) printf("Ant %d PRB %d dmrs[%d] -> (%d,%d)\n",aa,prb+(i>>2),i,rd_re_ext_p[i],rd_im_ext_p[i]); + for (int i=0;i<16;i++) printf("Ant %d PRB %d data[%d] -> (%d,%d)\n",aa,prb+(i>>3),i,r_re_ext_p[i],r_im_ext_p[i]); #endif - rp[aa]+=48; } // aa } // prb - // first compute DMRS component + uint32_t x1, x2, s=0; - x2 = (((1<<17)*((14*slot) + (pucch_pdu->start_symbol_index) + 1)*((2*pucch_pdu->dmrs_scrambling_id) + 1)) + (2*pucch_pdu->dmrs_scrambling_id))%(1U<<31); // c_init calculation according to TS38.211 subclause + x2 = (((1<<17)*((14*slot) + (pucch_pdu->start_symbol_index+symb) + 1)*((2*pucch_pdu->dmrs_scrambling_id) + 1)) + (2*pucch_pdu->dmrs_scrambling_id))%(1U<<31); // c_init calculation according to TS38.211 subclause #ifdef DEBUG_NR_PUCCH_RX - printf("slot %d, start_symbol_index %d, dmrs_scrambling_id %d\n", - slot,pucch_pdu->start_symbol_index,pucch_pdu->dmrs_scrambling_id); + printf("slot %d, start_symbol_index %d, symbol %d, dmrs_scrambling_id %d\n", + slot,pucch_pdu->start_symbol_index,symb,pucch_pdu->dmrs_scrambling_id); #endif - s = lte_gold_generic(&x1, &x2, 1); + int reset = 1; + for (int i=0; i<=(pucch_pdu->prb_start>>2); i++) { + s = lte_gold_generic(&x1, &x2, reset); + reset = 0; + } for (int group=0;group>=5; - corr32_im[group][aa]>>=5; + corr32_re[symb][group][aa]+=(rd_re_ext_p[4]*((int16_t*)&dmrs_re)[0] + rd_im_ext_p[4]*((int16_t*)&dmrs_im)[0]); + corr32_im[symb][group][aa]+=(-rd_re_ext_p[4]*((int16_t*)&dmrs_im)[0] + rd_im_ext_p[4]*((int16_t*)&dmrs_re)[0]); + corr32_re[symb][group][aa]+=(rd_re_ext_p[5]*((int16_t*)&dmrs_re)[1] + rd_im_ext_p[5]*((int16_t*)&dmrs_im)[1]); + corr32_im[symb][group][aa]+=(-rd_re_ext_p[5]*((int16_t*)&dmrs_im)[1] + rd_im_ext_p[5]*((int16_t*)&dmrs_re)[1]); + corr32_re[symb][group][aa]+=(rd_re_ext_p[6]*((int16_t*)&dmrs_re)[2] + rd_im_ext_p[6]*((int16_t*)&dmrs_im)[2]); + corr32_im[symb][group][aa]+=(-rd_re_ext_p[6]*((int16_t*)&dmrs_im)[2] + rd_im_ext_p[6]*((int16_t*)&dmrs_re)[2]); + corr32_re[symb][group][aa]+=(rd_re_ext_p[7]*((int16_t*)&dmrs_re)[3] + rd_im_ext_p[7]*((int16_t*)&dmrs_im)[3]); + corr32_im[symb][group][aa]+=(-rd_re_ext_p[7]*((int16_t*)&dmrs_im)[3] + rd_im_ext_p[7]*((int16_t*)&dmrs_re)[3]); + /* corr32_re[group][aa]>>=5; + corr32_im[group][aa]>>=5;*/ #ifdef DEBUG_NR_PUCCH_RX - printf("Group %d: corr32 (%d,%d)\n",group,corr32_re[group][aa],corr32_im[group][aa]); + printf("Group %d: corr32 (%d,%d)\n",group,corr32_re[symb][group][aa],corr32_im[symb][group][aa]); #endif } //aa - + if ((group&1) == 1) s = lte_gold_generic(&x1, &x2, 0); } // group - } - else { // 2 symbol case - AssertFatal(1==0, "Fill in 2 symbol PUCCH2 case\n"); - } + } // symb uint32_t x1, x2, s=0; // unscrambling @@ -1280,112 +1313,114 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, #ifdef DEBUG_NR_PUCCH_RX printf("x2 %x, s %x\n",x2,s); #endif - __m64 c_re0,c_im0,c_re1,c_im1,c_re2,c_im2,c_re3,c_im3; - re_offset=0; - for (int prb=0;prbprb_size;prb+=2,re_offset+=16) { - c_re0 = byte2m64_re[((uint8_t*)&s)[0]]; - c_im0 = byte2m64_im[((uint8_t*)&s)[0]]; - c_re1 = byte2m64_re[((uint8_t*)&s)[1]]; - c_im1 = byte2m64_im[((uint8_t*)&s)[1]]; - c_re2 = byte2m64_re[((uint8_t*)&s)[2]]; - c_im2 = byte2m64_im[((uint8_t*)&s)[2]]; - c_re3 = byte2m64_re[((uint8_t*)&s)[3]]; - c_im3 = byte2m64_im[((uint8_t*)&s)[3]]; + for (int symb=0;symbnr_of_symbols;symb++) { + __m64 c_re0,c_im0,c_re1,c_im1,c_re2,c_im2,c_re3,c_im3; + int re_off=0; + for (int prb=0;prbbit_len_harq+pucch_pdu->sr_flag+pucch_pdu->bit_len_csi_part1+pucch_pdu->bit_len_csi_part2; AssertFatal(nb_bit > 2 && nb_bit< 65,"illegal length (%d : %d,%d,%d,%d)\n",nb_bit,pucch_pdu->bit_len_harq,pucch_pdu->sr_flag,pucch_pdu->bit_len_csi_part1,pucch_pdu->bit_len_csi_part2); @@ -1393,18 +1428,20 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, uint8_t corr_dB; int decoderState=2; if (nb_bit < 12) { // short blocklength case - __m256i *rp_re[Prx2]; - __m256i *rp2_re[Prx2]; - __m256i *rp_im[Prx2]; - __m256i *rp2_im[Prx2]; + __m256i *rp_re[Prx2][2]; + __m256i *rp2_re[Prx2][2]; + __m256i *rp_im[Prx2][2]; + __m256i *rp2_im[Prx2][2]; for (int aa=0;aanr_of_symbols;symb++) { + rp_re[aa][symb] = (__m256i*)r_re_ext[aa][symb]; + rp_im[aa][symb] = (__m256i*)r_im_ext[aa][symb]; + rp2_re[aa][symb] = (__m256i*)r_re_ext2[aa][symb]; + rp2_im[aa][symb] = (__m256i*)r_im_ext2[aa][symb]; + } } __m256i prod_re[Prx2],prod_im[Prx2]; - int64_t corr=0; + uint64_t corr=0; int cw_ML=0; @@ -1418,74 +1455,93 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } printf("\n"); #endif - // do complex correlation - for (int aa=0;aanr_of_symbols;symb++) { + for (int group=0;group (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",aa, - ((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3], - ((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7], - ((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11], - ((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]); - printf("prod_im[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",aa, - ((int16_t*)&prod_im[aa])[0],((int16_t*)&prod_im[aa])[1],((int16_t*)&prod_im[aa])[2],((int16_t*)&prod_im[aa])[3], - ((int16_t*)&prod_im[aa])[4],((int16_t*)&prod_im[aa])[5],((int16_t*)&prod_im[aa])[6],((int16_t*)&prod_im[aa])[7], - ((int16_t*)&prod_im[aa])[8],((int16_t*)&prod_im[aa])[9],((int16_t*)&prod_im[aa])[10],((int16_t*)&prod_im[aa])[11], - ((int16_t*)&prod_im[aa])[12],((int16_t*)&prod_im[aa])[13],((int16_t*)&prod_im[aa])[14],((int16_t*)&prod_im[aa])[15]); + printf("prod_re[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",aa, + ((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3], + ((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7], + ((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11], + ((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]); + printf("prod_im[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",aa, + ((int16_t*)&prod_im[aa])[0],((int16_t*)&prod_im[aa])[1],((int16_t*)&prod_im[aa])[2],((int16_t*)&prod_im[aa])[3], + ((int16_t*)&prod_im[aa])[4],((int16_t*)&prod_im[aa])[5],((int16_t*)&prod_im[aa])[6],((int16_t*)&prod_im[aa])[7], + ((int16_t*)&prod_im[aa])[8],((int16_t*)&prod_im[aa])[9],((int16_t*)&prod_im[aa])[10],((int16_t*)&prod_im[aa])[11], + ((int16_t*)&prod_im[aa])[12],((int16_t*)&prod_im[aa])[13],((int16_t*)&prod_im[aa])[14],((int16_t*)&prod_im[aa])[15]); #endif - prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1 - prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); - prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3 - prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); - prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3+4+5+6+7 - prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); - prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15 - prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); - } - int64_t corr_re=0,corr_im=0; - - int64_t corr_tmp = 0; - for (int aa=0;aa corr) { - corr = corr_tmp; - cw_ML=cw; + corr = corr_tmp; + cw_ML=cw; } - } + } // cw loop corr_dB = dB_fixed64((uint64_t)corr); +#ifdef DEBUG_NR_PUCCH_RX + printf("cw_ML %d, metric %d dB\n",cw_ML,corr_dB); +#endif LOG_D(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); decodedPayload[0]=(uint64_t)cw_ML; } else { // polar coded case t_nrPolar_params *currentPtr = nr_polar_params(2,nb_bit,pucch_pdu->prb_size,1,&gNB->uci_polarParams); - __m64 *rp_re[Prx2]; - __m64 *rp2_re[Prx2]; - __m64 *rp_im[Prx2]; - __m64 *rp2_im[Prx2]; - __m128i llrs[pucch_pdu->prb_size*2]; + __m64 *rp_re[Prx2][2]; + __m64 *rp2_re[Prx2][2]; + __m64 *rp_im[Prx2][2]; + __m64 *rp2_im[Prx2][2]; + __m128i llrs[pucch_pdu->prb_size*2*pucch_pdu->nr_of_symbols]; for (int aa=0;aanr_of_symbols;symb++) { + rp_re[aa][symb] = (__m64*)r_re_ext[aa][symb]; + rp_im[aa][symb] = (__m64*)r_im_ext[aa][symb]; + rp2_re[aa][symb] = (__m64*)r_re_ext2[aa][symb]; + rp2_im[aa][symb] = (__m64*)r_im_ext2[aa][symb]; + } } __m64 prod_re[Prx2],prod_im[Prx2]; @@ -1505,55 +1561,55 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, int32_t corr_re,corr_im,corr_tmp; __m128i corr16,llr_num,llr_den; uint64_t corr = 0; + for (int symb=0;symbnr_of_symbols;symb++) { + for (int half_prb=0;half_prb<(2*pucch_pdu->prb_size);half_prb++) { + llr_num=_mm_set1_epi16(0);llr_den=_mm_set1_epi16(0); + for (int cw=0;cw<256;cw++) { + corr_tmp=0; + for (int aa=0;aa>4],rp_im[aa][symb][half_prb])),5); + prod_im[aa] = _mm_srai_pi16(_mm_subs_pi16(_mm_mullo_pi16(pucch2_polar_4bit[cw&15],rp2_im[aa][symb][half_prb]), + _mm_mullo_pi16(pucch2_polar_4bit[cw>>4],rp2_re[aa][symb][half_prb])),5); + prod_re[aa] = _mm_hadds_pi16(prod_re[aa],prod_re[aa]);// 0+1 + prod_im[aa] = _mm_hadds_pi16(prod_im[aa],prod_im[aa]); + prod_re[aa] = _mm_hadds_pi16(prod_re[aa],prod_re[aa]);// 0+1+2+3 + prod_im[aa] = _mm_hadds_pi16(prod_im[aa],prod_im[aa]); - for (int half_prb=0;half_prb<(2*pucch_pdu->prb_size);half_prb++) { - llr_num=_mm_set1_epi16(0);llr_den=_mm_set1_epi16(0); - for (int cw=0;cw<256;cw++) { - corr_tmp=0; - for (int aa=0;aa>4],rp_im[aa][half_prb])),5); - prod_im[aa] = _mm_srai_pi16(_mm_subs_pi16(_mm_mullo_pi16(pucch2_polar_4bit[cw&15],rp2_im[aa][half_prb]), - _mm_mullo_pi16(pucch2_polar_4bit[cw>>4],rp2_re[aa][half_prb])),5); - prod_re[aa] = _mm_hadds_pi16(prod_re[aa],prod_re[aa]);// 0+1 - prod_im[aa] = _mm_hadds_pi16(prod_im[aa],prod_im[aa]); - prod_re[aa] = _mm_hadds_pi16(prod_re[aa],prod_re[aa]);// 0+1+2+3 - prod_im[aa] = _mm_hadds_pi16(prod_im[aa],prod_im[aa]); + // this is for UL CQI measurement + if (cw==0) corr += ((int64_t)corr32_re[symb][half_prb>>2][aa]*corr32_re[symb][half_prb>>2][aa])+ + ((int64_t)corr32_im[symb][half_prb>>2][aa]*corr32_im[symb][half_prb>>2][aa]); - // this is for UL CQI measurement - if (cw==0) corr += ((int64_t)corr32_re[half_prb>>2][aa]*corr32_re[half_prb>>2][aa])+ - ((int64_t)corr32_im[half_prb>>2][aa]*corr32_im[half_prb>>2][aa]); - - corr_re = ( corr32_re[half_prb>>2][aa]/(2*nc_group_size*4/2)+((int16_t*)(&prod_re[aa]))[0]); - corr_im = ( corr32_im[half_prb>>2][aa]/(2*nc_group_size*4/2)+((int16_t*)(&prod_im[aa]))[0]); - corr_tmp += corr_re*corr_re + corr_im*corr_im; - /* - LOG_D(PHY,"pucch2 half_prb %d cw %d (%d,%d) aa %d: (%d,%d,%d,%d,%d,%d,%d,%d)x(%d,%d,%d,%d,%d,%d,%d,%d) (%d,%d)+(%d,%d) = (%d,%d) => %d\n", - half_prb,cw,cw&15,cw>>4,aa, - ((int16_t*)&pucch2_polar_4bit[cw&15])[0],((int16_t*)&pucch2_polar_4bit[cw>>4])[0], - ((int16_t*)&pucch2_polar_4bit[cw&15])[1],((int16_t*)&pucch2_polar_4bit[cw>>4])[1], - ((int16_t*)&pucch2_polar_4bit[cw&15])[2],((int16_t*)&pucch2_polar_4bit[cw>>4])[2], - ((int16_t*)&pucch2_polar_4bit[cw&15])[3],((int16_t*)&pucch2_polar_4bit[cw>>4])[3], - ((int16_t*)&rp_re[aa][half_prb])[0],((int16_t*)&rp_im[aa][half_prb])[0], - ((int16_t*)&rp_re[aa][half_prb])[1],((int16_t*)&rp_im[aa][half_prb])[1], - ((int16_t*)&rp_re[aa][half_prb])[2],((int16_t*)&rp_im[aa][half_prb])[2], - ((int16_t*)&rp_re[aa][half_prb])[3],((int16_t*)&rp_im[aa][half_prb])[3], - corr32_re[half_prb>>2][aa]/(2*nc_group_size*4/2),corr32_im[half_prb>>2][aa]/(2*nc_group_size*4/2), - ((int16_t*)(&prod_re[aa]))[0], - ((int16_t*)(&prod_im[aa]))[0], - corr_re, - corr_im, - corr_tmp); - */ + corr_re = ( corr32_re[symb][half_prb>>2][aa]/(2*nc_group_size*4/2)+((int16_t*)(&prod_re[aa]))[0]); + corr_im = ( corr32_im[symb][half_prb>>2][aa]/(2*nc_group_size*4/2)+((int16_t*)(&prod_im[aa]))[0]); + corr_tmp += corr_re*corr_re + corr_im*corr_im; + /* + LOG_D(PHY,"pucch2 half_prb %d cw %d (%d,%d) aa %d: (%d,%d,%d,%d,%d,%d,%d,%d)x(%d,%d,%d,%d,%d,%d,%d,%d) (%d,%d)+(%d,%d) = (%d,%d) => %d\n", + half_prb,cw,cw&15,cw>>4,aa, + ((int16_t*)&pucch2_polar_4bit[cw&15])[0],((int16_t*)&pucch2_polar_4bit[cw>>4])[0], + ((int16_t*)&pucch2_polar_4bit[cw&15])[1],((int16_t*)&pucch2_polar_4bit[cw>>4])[1], + ((int16_t*)&pucch2_polar_4bit[cw&15])[2],((int16_t*)&pucch2_polar_4bit[cw>>4])[2], + ((int16_t*)&pucch2_polar_4bit[cw&15])[3],((int16_t*)&pucch2_polar_4bit[cw>>4])[3], + ((int16_t*)&rp_re[aa][half_prb])[0],((int16_t*)&rp_im[aa][half_prb])[0], + ((int16_t*)&rp_re[aa][half_prb])[1],((int16_t*)&rp_im[aa][half_prb])[1], + ((int16_t*)&rp_re[aa][half_prb])[2],((int16_t*)&rp_im[aa][half_prb])[2], + ((int16_t*)&rp_re[aa][half_prb])[3],((int16_t*)&rp_im[aa][half_prb])[3], + corr32_re[half_prb>>2][aa]/(2*nc_group_size*4/2),corr32_im[half_prb>>2][aa]/(2*nc_group_size*4/2), + ((int16_t*)(&prod_re[aa]))[0], + ((int16_t*)(&prod_im[aa]))[0], + corr_re, + corr_im, + corr_tmp); +*/ } corr16 = _mm_set1_epi16((int16_t)(corr_tmp>>8)); - /* + LOG_D(PHY,"half_prb %d cw %d corr16 %d\n",half_prb,cw,corr_tmp>>8); - */ + llr_num = _mm_max_epi16(_mm_mullo_epi16(corr16,pucch2_polar_llr_num_lut[cw]),llr_num); llr_den = _mm_max_epi16(_mm_mullo_epi16(corr16,pucch2_polar_llr_den_lut[cw]),llr_den); - /* + LOG_D(PHY,"lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n", ((int16_t*)&pucch2_polar_llr_num_lut[cw])[0], ((int16_t*)&pucch2_polar_llr_num_lut[cw])[1], @@ -1563,7 +1619,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ((int16_t*)&pucch2_polar_llr_num_lut[cw])[5], ((int16_t*)&pucch2_polar_llr_num_lut[cw])[6], ((int16_t*)&pucch2_polar_llr_num_lut[cw])[7]); - + LOG_D(PHY,"llr_num (%d,%d,%d,%d,%d,%d,%d,%d)\n", ((int16_t*)&llr_num)[0], ((int16_t*)&llr_num)[1], @@ -1582,54 +1638,65 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ((int16_t*)&llr_den)[5], ((int16_t*)&llr_den)[6], ((int16_t*)&llr_den)[7]); - */ + } // compute llrs - llrs[half_prb] = _mm_subs_epi16(llr_num,llr_den); - LOG_D(PHY,"llrs[%d] : (%d,%d,%d,%d,%d,%d,%d,%d)\n", - half_prb, - ((int16_t*)&llrs[half_prb])[0], - ((int16_t*)&llrs[half_prb])[1], - ((int16_t*)&llrs[half_prb])[2], - ((int16_t*)&llrs[half_prb])[3], - ((int16_t*)&llrs[half_prb])[4], - ((int16_t*)&llrs[half_prb])[5], - ((int16_t*)&llrs[half_prb])[6], - ((int16_t*)&llrs[half_prb])[7]); - } // half_prb + llrs[half_prb + (symb*2*pucch_pdu->prb_size)] = _mm_subs_epi16(llr_num,llr_den); + LOG_D(PHY,"llrs[%d] : (%d,%d,%d,%d,%d,%d,%d,%d)\n", + half_prb, + ((int16_t*)&llrs[half_prb])[0], + ((int16_t*)&llrs[half_prb])[1], + ((int16_t*)&llrs[half_prb])[2], + ((int16_t*)&llrs[half_prb])[3], + ((int16_t*)&llrs[half_prb])[4], + ((int16_t*)&llrs[half_prb])[5], + ((int16_t*)&llrs[half_prb])[6], + ((int16_t*)&llrs[half_prb])[7]); + } // half_prb + } // symb // run polar decoder on llrs decoderState = polar_decoder_int16((int16_t*)llrs, decodedPayload, 0, currentPtr); - LOG_D(PHY,"UCI decoderState %d, payload[0] %llux\n",decoderState,(unsigned long long)decodedPayload[0]); + LOG_D(PHY,"UCI decoderState %d, payload[0] %llu\n",decoderState,(unsigned long long)decodedPayload[0]); if (decoderState>0) decoderState=1; corr_dB = dB_fixed64(corr); LOG_D(PHY,"metric %d dB\n",corr_dB); } + + // estimate CQI for MAC (from antenna port 0 only) + int SNRtimes10 = dB_fixed_times10(signal_energy_nodc(&rxdataF[0][soffset+(l2*frame_parms->ofdm_symbol_size)+re_offset[0]], + 12*pucch_pdu->prb_size)) - + (10*gNB->measurements.n0_power_tot_dB); + int cqi,bit_left; + if (SNRtimes10 < -640) cqi=0; + else if (SNRtimes10 > 635) cqi=255; + else cqi=(640+SNRtimes10)/5; + uci_pdu->harq.harq_bit_len = pucch_pdu->bit_len_harq; uci_pdu->pduBitmap=0; uci_pdu->rnti=pucch_pdu->rnti; uci_pdu->handle=pucch_pdu->handle; uci_pdu->pucch_format=0; - uci_pdu->ul_cqi=corr_dB; - // need to fill these field! - uci_pdu->timing_advance=31; - uci_pdu->rssi=0; + uci_pdu->ul_cqi=cqi; + uci_pdu->timing_advance=0xffff; // currently not valid + uci_pdu->rssi=1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(signal_energy_nodc(&rxdataF[0][soffset+(l2*frame_parms->ofdm_symbol_size)+re_offset[0]],12*pucch_pdu->prb_size))); if (pucch_pdu->bit_len_harq>0) { int harq_bytes=pucch_pdu->bit_len_harq>>3; if ((pucch_pdu->bit_len_harq&7) > 0) harq_bytes++; - uci_pdu->pduBitmap|=1; + uci_pdu->pduBitmap|=2; uci_pdu->harq.harq_payload = (uint8_t*)malloc(harq_bytes); - uci_pdu->harq.harq_crc = decoderState > 0 ? 1 : 0; + uci_pdu->harq.harq_crc = decoderState; int i=0; for (;iharq.harq_payload[i] = decodedPayload[0] & 255; decodedPayload[0]>>=8; } - uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<<(pucch_pdu->bit_len_harq&7))-1); + bit_left = pucch_pdu->bit_len_harq-((harq_bytes-1)<<3); + uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<>= pucch_pdu->bit_len_harq; } if (pucch_pdu->sr_flag == 1) { - uci_pdu->pduBitmap|=2; + uci_pdu->pduBitmap|=1; uci_pdu->sr.sr_bit_len = 1; uci_pdu->sr.sr_payload = malloc(1); uci_pdu->sr.sr_payload[0] = decodedPayload[0]&1; @@ -1638,22 +1705,52 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, // csi if (pucch_pdu->bit_len_csi_part1>0) { uci_pdu->pduBitmap|=4; + uci_pdu->csi_part1.csi_part1_bit_len=pucch_pdu->bit_len_csi_part1; int csi_part1_bytes=pucch_pdu->bit_len_csi_part1>>3; if ((pucch_pdu->bit_len_csi_part1&7) > 0) csi_part1_bytes++; uci_pdu->csi_part1.csi_part1_payload = (uint8_t*)malloc(csi_part1_bytes); - uci_pdu->csi_part1.csi_part1_crc = decoderState > 0 ? 1 : 0; + uci_pdu->csi_part1.csi_part1_crc = decoderState; int i=0; for (;icsi_part1.csi_part1_payload[i] = decodedPayload[0] & 255; decodedPayload[0]>>=8; } - uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<<(pucch_pdu->bit_len_csi_part1&7))-1); - decodedPayload[0] >>= pucch_pdu->bit_len_csi_part1; + bit_left = pucch_pdu->bit_len_csi_part1-((csi_part1_bytes-1)<<3); + uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<>= pucch_pdu->bit_len_csi_part1; } if (pucch_pdu->bit_len_csi_part2>0) { uci_pdu->pduBitmap|=8; } - } - + +void nr_dump_uci_stats(FILE *fd,PHY_VARS_gNB *gNB,int frame) { + + int strpos=0; + char output[16384]; + + for (int i=0;iuci_stats[i].rnti>0) { + NR_gNB_UCI_STATS_t *uci_stats = &gNB->uci_stats[i]; + if (uci_stats->pucch0_sr_trials > 0) + strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch0_sr_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_sr_thres %d dB, current pucch1_stat0 %d dB, current pucch1_stat1 %d dB, positive SR count %d\n", + i,uci_stats->rnti,uci_stats->pucch0_sr_trials,uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_sr_thres,dB_fixed(uci_stats->current_pucch0_sr_stat0),dB_fixed(uci_stats->current_pucch0_sr_stat1),uci_stats->pucch0_positive_SR); + if (uci_stats->pucch01_trials > 0) + strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current pucch0_stat0 %d dB, current pucch1_stat1 %d dB, pucch01_DTX %d\n", + i,uci_stats->rnti,uci_stats->pucch01_trials,uci_stats->pucch0_n01,uci_stats->pucch0_n01,uci_stats->pucch0_thres,dB_fixed(uci_stats->current_pucch0_stat0),dB_fixed(uci_stats->current_pucch0_stat1),uci_stats->pucch01_DTX); + + if (uci_stats->pucch02_trials > 0) + strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current pucch0_stat0 %d dB, current pucch0_stat1 %d dB, pucch01_DTX %d\n", + i,uci_stats->rnti,uci_stats->pucch02_trials,uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_thres,dB_fixed(uci_stats->current_pucch0_stat0),dB_fixed(uci_stats->current_pucch0_stat1),uci_stats->pucch02_DTX); + + if (uci_stats->pucch2_trials > 0) + strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch2_trials %d, pucch2_DTX %d\n", + i,uci_stats->rnti, + uci_stats->pucch2_trials, + uci_stats->pucch2_DTX); + } + } + if (fd) fprintf(fd,"%s",output); + else printf("%s",output); +} diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c index dec3d7cc2d..65ae288252 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c +++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c @@ -185,3 +185,78 @@ short filt8_rr1[8] = { short filt8_rr2[8] = { -4096,-8192,-12288,-16384,0,0,0,0}; + +short filt8_l2[8] = { +0,0,13107,9830,6554,3277,0,0}; + +short filt8_r2[8] = { +0,0,3277,6554,9830,13107,0,0}; + +short filt8_m2[8] = { +0,0,0,0,13107,9830,6554,3277}; + +short filt8_mm2[8]= { +0,0,0,0,3277,6554,9830,13107}; + +short filt8_rl2[8] = { +19661,22938,26214,29491,0,0,0,0}; + +short filt8_rm2[8] = { +-3277,-6554,-9830,-13107,0,0,0,0};//-3277,-6554,-9830,-13107 + +short filt8_l3[8] = { +22938,19661,0,0,13107,9830,6554,3277}; + +short filt8_r3[8] = { +-7537,-4260,0,0,3277,6554,9830,13107};//-6554,-3277 + +short filt8_rl3[8] = { +0,0,19661,22938,0,0,0,0}; + +short filt8_rr3[8] = { +0,0,-4260,-7537,0,0,0,0};//-3277,-6554 + +short filt8_dcrl1[8] = { +14895,13405,11916,10426,8937,7447,5958,4468}; + +short filt8_dcrh1[8] = { +2979,1489,0,0,0,0,0,0}; + +short filt8_dcll1[8] = { +13405,14895,0,0,0,0,0,0}; + +short filt8_dclh1[8] = { +1489,2979,4468,5958,7447,8937,10426,11916}; + +short filt8_dcrl2[8] = { +0,0,0,0,14895,13405,11916,10426}; + +short filt8_dcrh2[8] = { +8937,7447,5958,4468,2979,1489,0,0,}; + +short filt8_dcll2[8] = { +7447,8937,10426,11916,13405,14895,0,0}; + +short filt8_dclh2[8] = { +0,0,0,0,1489,2979,4468,5958}; + +short filt8_avlip0[8] = { +16384,16384,16384,16384,16384,16384,16384,15019}; + +short filt8_avlip1[8] = { +13653,12288,10923,9557,8192,6827,5461,4096}; + +short filt8_avlip2[8] = { +2731,1365,0,0,0,0,0,0}; + +short filt8_avlip3[8] = { +2731,4096,5461,6827,8192,9557,10923,12288}; + +short filt8_avlip4[8] = { +13653,15019,16384,15019,13653,12288,10923,9557}; + +short filt8_avlip5[8] = { +8192,6827,5461,4096,2731,1365,0,0}; + +short filt8_avlip6[8] = { +13653,15019,16384,16384,16384,16384,16384,16384}; diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h index e350985b0a..e28736b51d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h +++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h @@ -133,4 +133,53 @@ extern short filt8_rr1[8]; extern short filt8_rr2[8]; -#endif \ No newline at end of file +extern short filt8_rm2[8]; + +extern short filt8_rl2[8]; + +extern short filt8_l2[8]; + +extern short filt8_r2[8]; + +extern short filt8_m2[8]; + +extern short filt8_mm2[8]; + +extern short filt8_l3[8]; + +extern short filt8_r3[8]; + +extern short filt8_rr3[8]; + +extern short filt8_rl3[8]; + +extern short filt8_dcrl1[8]; + +extern short filt8_dcrh1[8]; + +extern short filt8_dcll1[8]; + +extern short filt8_dclh1[8]; + +extern short filt8_dcrl2[8]; + +extern short filt8_dcrh2[8]; + +extern short filt8_dcll2[8]; + +extern short filt8_dclh2[8]; + +extern short filt8_avlip0[8]; + +extern short filt8_avlip1[8]; + +extern short filt8_avlip2[8]; + +extern short filt8_avlip3[8]; + +extern short filt8_avlip4[8]; + +extern short filt8_avlip5[8]; + +extern short filt8_avlip6[8]; +#endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c index 161408254f..4a884b964b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_gain.c @@ -27,7 +27,7 @@ void phy_adjust_gain_nr (PHY_VARS_NR_UE *ue, uint32_t rx_power_fil_dB, uint8_t eNB_id) { - LOG_I(PHY,"Gain control: rssi %d (%d,%d)\n", + LOG_D(PHY,"Gain control: rssi %d (%d,%d)\n", rx_power_fil_dB, ue->measurements.rssi, ue->measurements.rx_power_avg_dB[eNB_id] @@ -61,7 +61,7 @@ phy_adjust_gain_nr (PHY_VARS_NR_UE *ue, uint32_t rx_power_fil_dB, uint8_t eNB_id ue->rx_total_gain_dB = MIN_RF_GAIN; } - LOG_I(PHY,"Gain control: rx_total_gain_dB = %d TARGET_RX_POWER %d (max %d,rxpf %d)\n",ue->rx_total_gain_dB,TARGET_RX_POWER,MAX_RF_GAIN,rx_power_fil_dB); + LOG_D(PHY,"Gain control: rx_total_gain_dB = %d TARGET_RX_POWER %d (max %d,rxpf %d)\n",ue->rx_total_gain_dB,TARGET_RX_POWER,MAX_RF_GAIN,rx_power_fil_dB); #ifdef DEBUG_PHY /* if ((ue->frame%100==0) || (ue->frame < 10)) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index b49443c03c..19d4bf5079 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -24,6 +24,7 @@ #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "PHY/impl_defs_top.h" +#include "executables/softmodem-common.h" #include "common/utils/LOG/vcd_signal_dumper.h" #define DEBUG_PHY @@ -33,35 +34,34 @@ // last channel estimate of the receiver void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, - PHY_VARS_NR_UE *ue, - module_id_t gNB_id, - uint8_t frame, - uint8_t subframe, - unsigned char clear, - short coef) + PHY_VARS_NR_UE *ue, + module_id_t gNB_id, + uint8_t frame, + uint8_t subframe, + unsigned char clear, + short coef) { - static int max_pos_fil = 0; static int count_max_pos_ok = 0; static int first_time = 1; - int temp = 0, i, aa, max_val = 0, max_pos = 0; - int diff; - short Re,Im,ncoef; + int max_val = 0, max_pos = 0; + const int sync_pos = 0; + uint8_t sync_offset = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); - ncoef = 32767 - coef; + short ncoef = 32767 - coef; LOG_D(PHY,"AbsSubframe %d: rx_offset (before) = %d\n",subframe,ue->rx_offset); + // search for maximum position within the cyclic prefix + for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) { + int temp = 0; - // we only use channel estimates from tx antenna 0 here - for (i = 0; i < frame_parms->nb_prefix_samples; i++) { - temp = 0; - - for (aa=0; aanb_antennas_rx; aa++) { - Re = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[(i<<1)]; - Im = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[1+(i<<1)]; + int j = (i < 0) ? (i + frame_parms->ofdm_symbol_size) : i; + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + int Re = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[(j<<1)]; + int Im = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[1+(j<<1)]; temp += (Re*Re/2) + (Im*Im/2); } @@ -73,67 +73,65 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, // filter position to reduce jitter if (clear == 1) - max_pos_fil = max_pos; + ue->max_pos_fil = max_pos; else - max_pos_fil = ((max_pos_fil * coef) + (max_pos * ncoef)) >> 15; + ue->max_pos_fil = ((ue->max_pos_fil * coef) + (max_pos * ncoef)) >> 15; // do not filter to have proactive timing adjustment - //max_pos_fil = max_pos; + //ue->max_pos_fil = max_pos; - if(subframe == 0) + int diff = ue->max_pos_fil - sync_pos; + + if (frame_parms->freq_range==nr_FR2) + sync_offset = 2; + else + sync_offset = 0; + + if ( abs(diff) < (SYNCH_HYST+sync_offset) ) + ue->rx_offset = 0; + else + ue->rx_offset = diff; + + if(abs(diff)<5) + count_max_pos_ok ++; + else + count_max_pos_ok = 0; + + //printf("adjust sync count_max_pos_ok = %d\n",count_max_pos_ok); + + if(count_max_pos_ok > 10 && first_time == 1) { - diff = max_pos_fil - (frame_parms->nb_prefix_samples>>3); - - if ( abs(diff) < SYNCH_HYST ) - ue->rx_offset = 0; - else - ue->rx_offset = diff; - - if(abs(diff)<5) - count_max_pos_ok ++; - else - count_max_pos_ok = 0; - - //printf("adjust sync count_max_pos_ok = %d\n",count_max_pos_ok); - - if(count_max_pos_ok > 10 && first_time == 1) - { - first_time = 0; - ue->time_sync_cell = 1; - if (ue->mac_enabled==1) { - LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); - //mac_resynch(); - //dl_phy_sync_success(ue->Mod_id,ue->proc.proc_rxtx[0].frame_rx,0,1);//ue->common_vars.eNb_id); - ue->UE_mode[0] = PRACH; - ue->prach_resources[gNB_id]->sync_frame = frame; - ue->prach_resources[gNB_id]->init_msg1 = 0; - } - else { - ue->UE_mode[0] = PUSCH; - } - } - - if (ue->rx_offset < 0) - ue->rx_offset += frame_parms->samples_per_frame; - - if (ue->rx_offset >= frame_parms->samples_per_frame) - ue->rx_offset -= frame_parms->samples_per_frame; - - - - #ifdef DEBUG_PHY - LOG_D(PHY,"AbsSubframe %d: ThreadId %d diff =%i rx_offset (final) = %i : clear %d,max_pos = %d,max_pos_fil = %d (peak %d) max_val %d target_pos %d \n", - subframe, - ue->current_thread_id[subframe], - diff, - ue->rx_offset, - clear, - max_pos, - max_pos_fil, - temp,max_val, - (frame_parms->nb_prefix_samples>>3)); - #endif //DEBUG_PHY - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); + first_time = 0; + ue->time_sync_cell = 1; + if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) { + LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); + //mac_resynch(); + //dl_phy_sync_success(ue->Mod_id,frame,0,1);//ue->common_vars.eNb_id); + ue->UE_mode[0] = PRACH; + ue->prach_resources[gNB_id]->sync_frame = frame; + ue->prach_resources[gNB_id]->init_msg1 = 0; + } else { + ue->UE_mode[0] = PUSCH; + } } + + if (ue->rx_offset < 0) + ue->rx_offset += frame_parms->samples_per_frame; + + if (ue->rx_offset >= frame_parms->samples_per_frame) + ue->rx_offset -= frame_parms->samples_per_frame; + +#ifdef DEBUG_PHY + LOG_D(PHY,"AbsSubframe %d: diff = %i, rx_offset (final) = %i : clear = %d, max_pos = %d, max_pos_fil = %d, max_val = %d, sync_pos %d\n", + subframe, + diff, + ue->rx_offset, + clear, + max_pos, + ue->max_pos_fil, + max_val, + sync_pos); +#endif //DEBUG_PHY + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 71a5771f5b..30eae2d30f 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -24,6 +24,10 @@ #include "SCHED_NR_UE/defs.h" #include "nr_estimation.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/NR_REFSIG/dmrs_nr.h" +#include "PHY/NR_REFSIG/ptrs_nr.h" +#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" #include "filt16a_32.h" //#define DEBUG_PDSCH @@ -31,7 +35,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, - uint8_t eNB_offset, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, unsigned char Ns, unsigned char symbol, int dmrss, @@ -48,7 +53,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, uint8_t nushift; uint8_t ssb_index=current_ssb->i_ssb; uint8_t n_hf=current_ssb->n_hf; - int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; nushift = ue->frame_parms.Nid_cell%4; ue->frame_parms.nushift = nushift; @@ -65,16 +70,16 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, k = nushift; #ifdef DEBUG_CH - printf("PBCH DMRS Correlation : ThreadId %d, eNB_offset %d , OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ue->frame_parms.ofdm_symbol_size, + printf("PBCH DMRS Correlation : ThreadId %d, gNB_id %d , OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",proc->thread_id, gNB_id,ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp,Ns,k, symbol); #endif // generate pilot nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]); - int re_offset = ssb_offset; for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { + int re_offset = ssb_offset; pil = (int16_t *)&pilot[0]; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -89,15 +94,15 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -105,29 +110,29 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; - for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt+=3) { + for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt += 3) { // if (pilot_cnt == 30) // rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k)]; @@ -141,14 +146,14 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -156,13 +161,13 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -170,14 +175,14 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -192,7 +197,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_offset, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, unsigned char Ns, unsigned char symbol, int dmrss, @@ -207,21 +213,16 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, int ch_offset,symbol_offset; //int slot_pbch; - //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; - uint8_t nushift; - int **dl_ch_estimates =ue->pbch_vars[eNB_offset]->dl_ch_estimates; - int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF; + int **dl_ch_estimates =ue->pbch_vars[gNB_id]->dl_ch_estimates; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; nushift = ue->frame_parms.Nid_cell%4; ue->frame_parms.nushift = nushift; unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size; - if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage - ch_offset = ue->frame_parms.ofdm_symbol_size ; - else - ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; + ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; AssertFatal(dmrss >= 0 && dmrss < 3, "symbol %d is illegal for PBCH DM-RS \n", @@ -233,7 +234,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, k = nushift; #ifdef DEBUG_CH - printf("PBCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,ue->frame_parms.ofdm_symbol_size, + printf("PBCH Channel Estimation : ThreadId %d, gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",proc->thread_id, gNB_id,ch_offset,ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp,Ns,k, symbol); #endif @@ -271,25 +272,21 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, // generate pilot nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]); - int re_offset = ssb_offset; for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { + int re_offset = ssb_offset; pil = (int16_t *)&pilot[0]; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size)); - if (ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha - multadd_complex_vector_real_scalar(dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), - ue->ch_est_alpha,dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), - 1,ue->frame_parms.ofdm_symbol_size); + #ifdef DEBUG_CH printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL); printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset); printf("rxF addr %p\n", rxF); printf("dl_ch addr %p\n",dl_ch); #endif - //if ((ue->frame_parms.N_RB_DL&1)==0) { // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -303,7 +300,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -321,7 +318,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -336,12 +333,12 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; - dl_ch+=24; + dl_ch += 24; - for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt+=3) { + for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt += 3) { // if (pilot_cnt == 30) // rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k)]; @@ -367,7 +364,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, //for (int i= 0; i<8; i++) // printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -382,7 +379,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -398,10 +395,10 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; - dl_ch+=24; + dl_ch += 24; } @@ -445,29 +442,28 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, assert(0); } - if( symbol == 3) + if( dmrss == 2) // update time statistics for last PBCH symbol { - // do ifft of channel estimate - for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) - for (p=0; pframe_parms.nb_antenna_ports_gNB; p++) { - if (ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx]) - { - LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d ch_offset %d\n", Ns, ue->current_thread_id[Ns], symbol, ch_offset); - idft(idftsizeidx, - (int16_t*) &ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx][ch_offset], - (int16_t*) ue->pbch_vars[eNB_offset]->dl_ch_estimates_time[(p<<1)+aarx],1); - } - } + // do ifft of channel estimate + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) + for (p=0; pframe_parms.nb_antenna_ports_gNB; p++) { + if (ue->pbch_vars[gNB_id]->dl_ch_estimates[(p*ue->frame_parms.nb_antennas_rx)+aarx]) + { + LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d ch_offset %d\n", Ns, proc->thread_id, symbol, ch_offset); + idft(idftsizeidx, + (int16_t*) &ue->pbch_vars[gNB_id]->dl_ch_estimates[(p*ue->frame_parms.nb_antennas_rx)+aarx][ch_offset], + (int16_t*) ue->pbch_vars[gNB_id]->dl_ch_estimates_time[(p*ue->frame_parms.nb_antennas_rx)+aarx],1); + } + } } - //} - } return(0); } int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_offset, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, unsigned char Ns, unsigned char symbol, unsigned short coreset_start_subcarrier, @@ -480,24 +476,17 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, int16_t ch[2],*pil,*rxF,*dl_ch,*fl,*fm,*fr; int ch_offset,symbol_offset; - //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; + int **dl_ch_estimates =ue->pdcch_vars[proc->thread_id][gNB_id]->dl_ch_estimates; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; - int **dl_ch_estimates =ue->pdcch_vars[ue->current_thread_id[Ns]][eNB_offset]->dl_ch_estimates; - int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF; - - - if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage - ch_offset = ue->frame_parms.ofdm_symbol_size ; - else - ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; + ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol; - k = coreset_start_subcarrier; #ifdef DEBUG_PDCCH - printf("PDCCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,ue->frame_parms.ofdm_symbol_size, - ue->frame_parms.Ncp,Ns,k, symbol); + printf("PDCCH Channel Estimation : ThreadId %d, gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, symbol %d\n", + proc->thread_id, gNB_id,ch_offset,ue->frame_parms.ofdm_symbol_size,ue->frame_parms.Ncp,Ns,symbol); #endif fl = filt16a_l1; @@ -505,22 +494,27 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, fr = filt16a_r1; + // checking if re-initialization of scrambling IDs is needed (should be done here but scrambling ID for PDCCH is not taken from RRC) +/* if (( != ue->scramblingID_pdcch){ + ue->scramblingID_pdcch=; + nr_gold_pdsch(ue,ue->scramblingID_pdcch); + }*/ + + // generate pilot int pilot[nb_rb_coreset * 3] __attribute__((aligned(16))); - nr_pdcch_dmrs_rx(ue,eNB_offset,Ns,ue->nr_gold_pdcch[eNB_offset][Ns][symbol], &pilot[0],2000,nb_rb_coreset); + nr_pdcch_dmrs_rx(ue,gNB_id,Ns,ue->nr_gold_pdcch[gNB_id][Ns][symbol], &pilot[0],2000,nb_rb_coreset); for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { + k = coreset_start_subcarrier; pil = (int16_t *)&pilot[0]; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)]; dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size)); - if (ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha - multadd_complex_vector_real_scalar(dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), - ue->ch_est_alpha,dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), - 1,ue->frame_parms.ofdm_symbol_size); + #ifdef DEBUG_PDCCH printf("pdcch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL); printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset); @@ -529,111 +523,111 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, printf("dl_ch addr %p\n",dl_ch); #endif // if ((ue->frame_parms.N_RB_DL&1)==0) { - // Treat first 2 pilots specially (left edge) + // Treat first 2 pilots specially (left edge) + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); +#ifdef DEBUG_PDCCH + printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); + printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); +#endif + multadd_real_vector_complex_scalar(fl, + ch, + dl_ch, + 16); + pil += 2; + rxF += 8; + //for (int i= 0; i<8; i++) + //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); + + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); +#ifdef DEBUG_PDCCH + printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif + multadd_real_vector_complex_scalar(fm, + ch, + dl_ch, + 16); + pil += 2; + rxF += 8; + + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + +#ifdef DEBUG_PDCCH + printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif + + multadd_real_vector_complex_scalar(fr, + ch, + dl_ch, + 16); + +#ifdef DEBUG_PDCCH + for (int m =0; m<12; m++) + printf("data : dl_ch -> (%d,%d)\n",dl_ch[0+2*m],dl_ch[1+2*m]); +#endif + pil += 2; + rxF += 8; + dl_ch += 24; + k += 12; + + + + for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt += 3) { + + if (k >= ue->frame_parms.ofdm_symbol_size){ + k-=ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];} + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDCCH - printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); - printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fl, - ch, - dl_ch, - 16); - pil+=2; - rxF+=8; + ch, + dl_ch, + 16); + //for (int i= 0; i<8; i++) - //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); + // printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); + + pil += 2; + rxF += 8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDCCH - printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fm, - ch, - dl_ch, - 16); - pil+=2; - rxF+=8; + ch, + dl_ch, + 16); + pil += 2; + rxF += 8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDCCH - printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fr, - ch, - dl_ch, - 16); - -#ifdef DEBUG_PDCCH - for (int m =0; m<12; m++) - printf("data : dl_ch -> (%d,%d)\n",dl_ch[0+2*m],dl_ch[1+2*m]); -#endif - pil+=2; - rxF+=8; - dl_ch+=24; - k+=12; - - + ch, + dl_ch, + 16); + pil += 2; + rxF += 8; + dl_ch += 24; + k += 12; - for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt+=3) { - - if (k >= ue->frame_parms.ofdm_symbol_size){ - k-=ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];} - - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); -#ifdef DEBUG_PDCCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); -#endif - multadd_real_vector_complex_scalar(fl, - ch, - dl_ch, - 16); - - //for (int i= 0; i<8; i++) - // printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); - - pil+=2; - rxF+=8; - - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); -#ifdef DEBUG_PDCCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); -#endif - multadd_real_vector_complex_scalar(fm, - ch, - dl_ch, - 16); - pil+=2; - rxF+=8; - - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - -#ifdef DEBUG_PDCCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); -#endif - - multadd_real_vector_complex_scalar(fr, - ch, - dl_ch, - 16); - pil+=2; - rxF+=8; - dl_ch+=24; - k+=12; - - } + } - //} + //} } @@ -641,10 +635,13 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, } int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_offset, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, + bool is_SI, unsigned char Ns, unsigned short p, unsigned char symbol, + unsigned short BWPStart, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch) { @@ -652,23 +649,19 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned char aarx; unsigned short k; unsigned int pilot_cnt; - int16_t ch[2],*pil,*rxF,*dl_ch; - int16_t *fl,*fm,*fr,*fml,*fmr,*fmm,*fdcl,*fdcr,*fdclh,*fdcrh; + int16_t ch_l[2],ch_r[2],ch[2],*pil,*rxF,*dl_ch; + int16_t *fl=NULL,*fm=NULL,*fr=NULL,*fml=NULL,*fmr=NULL,*fmm=NULL,*fdcl=NULL,*fdcr=NULL,*fdclh=NULL,*fdcrh=NULL, *frl=NULL, *frr=NULL; int ch_offset,symbol_offset; - //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; + NR_UE_DLSCH_t **dlsch = ue->dlsch[proc->thread_id][gNB_id]; + const unsigned char harq_pid = dlsch[0]->current_harq_pid; + NR_DL_UE_HARQ_t *dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; uint8_t nushift; - int **dl_ch_estimates =ue->pdsch_vars[ue->current_thread_id[Ns]][eNB_offset]->dl_ch_estimates; - int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF; + int **dl_ch_estimates =ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; - nushift = (p>>1)&1; - ue->frame_parms.nushift = nushift; - - if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage - ch_offset = ue->frame_parms.ofdm_symbol_size ; - else - ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; + ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol; @@ -676,68 +669,123 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, int re_offset = k; #ifdef DEBUG_CH - printf("PDSCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,symbol_offset,ue->frame_parms.ofdm_symbol_size, + printf("PDSCH Channel Estimation : ThreadId %d, gNB_id %d ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",proc->thread_id, gNB_id,ch_offset,symbol_offset,ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp,Ns,k, symbol); #endif - switch (nushift) { - case 0: - fl = filt8_l0; - fm = filt8_m0; - fr = filt8_r0; - fmm = filt8_mm0; - fml = filt8_m0; - fmr = filt8_mr0; - fdcl = filt8_dcl0; - fdcr = filt8_dcr0; - fdclh = filt8_dcl0_h; - fdcrh = filt8_dcr0_h; - break; - - case 1: - fl = filt8_l1; - fm = filt8_m1; - fr = filt8_r1; - fmm = filt8_mm1; - fml = filt8_ml1; - fmr = filt8_m1; - fdcl = filt8_dcl1; - fdcr = filt8_dcr1; - fdclh = filt8_dcl1_h; - fdcrh = filt8_dcr1_h; - break; - - default: - msg("pdsch_channel_estimation: nushift=%d -> ERROR\n",nushift); - return(-1); - break; - } - - - // generate pilot + // generate pilot for gNB port number 1000+p uint16_t rb_offset = (bwp_start_subcarrier - ue->frame_parms.first_carrier_offset) / 12; - int config_type = 0; // needs to be updated from higher layer - nr_pdsch_dmrs_rx(ue,Ns,ue->nr_gold_pdsch[eNB_offset][Ns][0], &pilot[0],1000,0,nb_rb_pdsch+rb_offset); + if (is_SI) { + rb_offset -= BWPStart; + } + uint8_t config_type = dlsch0_harq->dmrsConfigType; + int8_t delta = get_delta(p, config_type); + + // checking if re-initialization of scrambling IDs is needed + /*if ((XXX.scramblingID0 != ue->scramblingID[0]) || (XXX.scramblingID1 != ue->scramblingID[1])){ + ue->scramblingID[0] = XXX.scramblingID0; + ue->scramblingID[1] = XXX.scramblingID1; + nr_gold_pdsch(ue,ue->scramblingID); + }*/ + + nr_pdsch_dmrs_rx(ue, Ns, ue->nr_gold_pdsch[gNB_id][Ns][symbol][0], &pilot[0], 1000+p, 0, nb_rb_pdsch+rb_offset, config_type); + + if (config_type == NFAPI_NR_DMRS_TYPE1){ + nushift = (p>>1)&1; + if (p<4) ue->frame_parms.nushift = nushift; + switch (delta) { + + case 0://port 0,1 + fl = filt8_l0;//left interpolation Filter for DMRS config. 1 + fm = filt8_m0;//left middle interpolation Filter + fr = filt8_r0;//right interpolation Filter + fmm = filt8_mm0;;//middle middle interpolation Filter + fml = filt8_m0;//left middle interpolation Filter + fmr = filt8_mr0;//middle right interpolation Filter + fdcl = filt8_dcl0;//left DC interpolation Filter (even RB) + fdcr = filt8_dcr0;//right DC interpolation Filter (even RB) + fdclh = filt8_dcl0_h;//left DC interpolation Filter (odd RB) + fdcrh = filt8_dcr0_h;//right DC interpolation Filter (odd RB) + frl = NULL; + frr = NULL; + break; + + case 1://port2,3 + fl = filt8_l1; + fm = filt8_m1; + fr = filt8_r1; + fmm = filt8_mm1; + fml = filt8_ml1; + fmr = filt8_m1; + fdcl = filt8_dcl1; + fdcr = filt8_dcr1; + fdclh = filt8_dcl1_h; + fdcrh = filt8_dcr1_h; + frl = NULL; + frr = NULL; + break; + + default: + LOG_E(PHY,"pdsch_channel_estimation: nushift=%d -> ERROR\n",nushift); + return -1; + break; + } + } else {//NFAPI_NR_DMRS_TYPE2 + nushift = delta; + if (p<6) ue->frame_parms.nushift = nushift; + switch (delta) { + case 0://port 0,1 + fl = filt8_l2;//left interpolation Filter should be fml + fr = filt8_r2;//right interpolation Filter should be fmr + fm = filt8_l2; + fmm = filt8_r2; + fml = filt8_ml2; + fmr = filt8_mr2; + frl = filt8_rl2; + frr = filt8_rm2; + fdcl = filt8_dcl1; + fdcr = filt8_dcr1; + fdclh = filt8_dcl1_h; + fdcrh = filt8_dcr1_h; + break; + + case 2://port2,3 + fl = filt8_l3; + fm = filt8_m2; + fr = filt8_r3; + fmm = filt8_mm2; + fml = filt8_l2; + fmr = filt8_r2; + frl = filt8_rl3; + frr = filt8_rr3; + fdcl = NULL; + fdcr = NULL; + fdclh = NULL; + fdcrh = NULL; + break; + + default: + LOG_E(PHY,"pdsch_channel_estimation: nushift=%d -> ERROR\n",nushift); + return -1; + break; + } + } for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { - - pil = (int16_t *)&pilot[rb_offset*((config_type==0) ? 6:4)]; + pil = (int16_t *)&pilot[rb_offset*((config_type == NFAPI_NR_DMRS_TYPE1) ? 6:4)]; k = k % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+nushift)]; - dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; + re_offset = k; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+re_offset+nushift)]; + dl_ch = (int16_t *)&dl_ch_estimates[p*ue->frame_parms.nb_antennas_rx+aarx][ch_offset]; memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size)); - if (ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha - multadd_complex_vector_real_scalar(dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), - ue->ch_est_alpha,dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), - 1,ue->frame_parms.ofdm_symbol_size); #ifdef DEBUG_PDSCH printf("ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL); printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset); printf("rxF addr %p p %d\n", rxF,p); printf("dl_ch addr %p nushift %d\n",dl_ch,nushift); #endif - //if ((ue->frame_parms.N_RB_DL&1)==0) { + if (config_type == NFAPI_NR_DMRS_TYPE1 && ue->prb_interpolation == 0) { // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -751,7 +799,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //for (int i= 0; i<8; i++) @@ -766,7 +814,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //printf("dl_ch addr %p\n",dl_ch); @@ -781,18 +829,12 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - //for (int i= 0; i<16; i++) - //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); - - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - dl_ch+=8; + dl_ch += 8; - for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pdsch-3); pilot_cnt+=2) { - //if ((pilot_cnt%6)==0) - //dl_ch+=4; - //printf("re_offset %d\n",re_offset); + for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pdsch-3); pilot_cnt += 2) { ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -804,7 +846,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -817,10 +859,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - dl_ch+=8; + dl_ch += 8; } @@ -828,7 +870,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDSCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fm, ch, @@ -838,7 +880,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, //for (int i= 0; i<8; i++) //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -853,10 +895,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - dl_ch+=8; + dl_ch += 8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -867,73 +909,792 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 8); - //} - // check if PRB crosses DC and improve estimates around DC - if ((bwp_start_subcarrier < ue->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pdsch*12 >= ue->frame_parms.ofdm_symbol_size)) { - dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; - uint16_t idxDC = 2*(ue->frame_parms.ofdm_symbol_size - bwp_start_subcarrier); - uint16_t idxPil = idxDC/2; - re_offset = k; - pil = (int16_t *)&pilot[rb_offset*((config_type==0) ? 6:4)]; - pil += (idxPil-2); - dl_ch += (idxDC-4); - dl_ch = memset(dl_ch, 0, sizeof(int16_t)*10); - re_offset = (re_offset+idxDC/2-2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - - // for proper allignment of SIMD vectors - if((ue->frame_parms.N_RB_DL&1)==0) { - - multadd_real_vector_complex_scalar(fdcl, - ch, - dl_ch-4, - 8); - - pil += 4; - re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; + // check if PRB crosses DC and improve estimates around DC + if ((bwp_start_subcarrier < ue->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pdsch*12 >= ue->frame_parms.ofdm_symbol_size)) { + dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; + uint16_t idxDC = 2*(ue->frame_parms.ofdm_symbol_size - bwp_start_subcarrier); + uint16_t idxPil = idxDC/2; + re_offset = k; + pil = (int16_t *)&pilot[rb_offset*((config_type == NFAPI_NR_DMRS_TYPE1) ? 6:4)]; + pil += (idxPil-2); + dl_ch += (idxDC-4); + dl_ch = memset(dl_ch, 0, sizeof(int16_t)*10); + re_offset = (re_offset+idxDC/2-2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - - multadd_real_vector_complex_scalar(fdcr, - ch, - dl_ch-4, - 8); - } else { + + // for proper allignment of SIMD vectors + if((ue->frame_parms.N_RB_DL&1) == 0) { + + multadd_real_vector_complex_scalar(fdcl, + ch, + dl_ch-4, + 8); + + pil += 4; + re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + multadd_real_vector_complex_scalar(fdcr, + ch, + dl_ch-4, + 8); + } else { - multadd_real_vector_complex_scalar(fdclh, - ch, - dl_ch, - 8); - - pil += 4; - re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - - multadd_real_vector_complex_scalar(fdcrh, - ch, - dl_ch, - 8); + multadd_real_vector_complex_scalar(fdclh, + ch, + dl_ch, + 8); + + pil += 4; + re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + multadd_real_vector_complex_scalar(fdcrh, + ch, + dl_ch, + 8); + } } + } else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->prb_interpolation == 0){ //pdsch_dmrs_type2 |dmrs_r,dmrs_l,0,0,0,0,dmrs_r,dmrs_l,0,0,0,0| - } + // Treat first 4 pilots specially (left edge) + ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch_l[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDSCH - dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; + printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); + printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch_l[0],ch_l[1],pil[0],pil[1]); +#endif + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch_r[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + ch[0] = (ch_l[0]+ch_r[0])>>1; + ch[1] = (ch_l[1]+ch_r[1])>>1; + + dl_ch[(0+2*nushift)] = ch[0]; + dl_ch[(1+2*nushift)] = ch[1]; + dl_ch[2+2*nushift] = ch[0]; + dl_ch[3+2*nushift] = ch[1]; + + multadd_real_vector_complex_scalar(fl, + ch, + dl_ch, + 8); + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch_l[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch_r[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + ch[0] = (ch_l[0]+ch_r[0])>>1; + ch[1] = (ch_l[1]+ch_r[1])>>1; + + multadd_real_vector_complex_scalar(fr, + ch, + dl_ch, + 8); + + dl_ch += 12; + dl_ch[0+2*nushift] = ch[0]; + dl_ch[1+2*nushift] = ch[1]; + dl_ch[2+2*nushift] = ch[0]; + dl_ch[3+2*nushift] = ch[1]; + dl_ch += 4; + + for (pilot_cnt=4; pilot_cnt<4*nb_rb_pdsch; pilot_cnt += 4) { + + multadd_real_vector_complex_scalar(fml, + ch, + dl_ch, + 8); + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch_l[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + +#ifdef DEBUG_PDSCH + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch_l[0],ch_l[1],pil[0],pil[1]); +#endif + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch_r[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + ch[0] = (ch_l[0]+ch_r[0])>>1; + ch[1] = (ch_l[1]+ch_r[1])>>1; + +#ifdef DEBUG_PDSCH + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch_r[0],ch_r[1],pil[0],pil[1]); +#endif + + multadd_real_vector_complex_scalar(fmr, + ch, + dl_ch, + 8); + + dl_ch += 8; + dl_ch[0+2*nushift] = ch[0]; + dl_ch[1+2*nushift] = ch[1]; + dl_ch[2+2*nushift] = ch[0]; + dl_ch[3+2*nushift] = ch[1]; + + multadd_real_vector_complex_scalar(fm, + ch, + dl_ch, + 8); + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch_l[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch_r[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + +#ifdef DEBUG_PDSCH + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch_r[0],ch_r[1],pil[0],pil[1]); +#endif + + ch[0] = (ch_l[0]+ch_r[0])>>1; + ch[1] = (ch_l[1]+ch_r[1])>>1; + + multadd_real_vector_complex_scalar(fmm, + ch, + dl_ch, + 8); + + dl_ch += 12; + dl_ch[0+2*nushift] = ch[0]; + dl_ch[1+2*nushift] = ch[1]; + dl_ch[2+2*nushift] = ch[0]; + dl_ch[3+2*nushift] = ch[1]; + dl_ch += 4; + } + + // Treat last 2 pilots specially (right edge) + // dl_ch-2+nushift<<1 + multadd_real_vector_complex_scalar(frl, + dl_ch-2+2*nushift, + dl_ch, + 8); + + multadd_real_vector_complex_scalar(frr, + dl_ch-14+2*nushift,/*14*/ + dl_ch, + 8); + + // check if PRB crosses DC and improve estimates around DC + if ((bwp_start_subcarrier < ue->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pdsch*12 >= ue->frame_parms.ofdm_symbol_size) && (p<2)) { + + dl_ch = (int16_t *)&dl_ch_estimates[p*ue->frame_parms.nb_antennas_rx+aarx][ch_offset]; + uint16_t idxDC = 2*(ue->frame_parms.ofdm_symbol_size - bwp_start_subcarrier); + dl_ch += (idxDC-8); + dl_ch = memset(dl_ch, 0, sizeof(int16_t)*20); + + dl_ch -= 2; + + ch_r[0] = dl_ch[0]; + ch_r[1]= dl_ch[1] ; + dl_ch += 22; + ch_l[0] = dl_ch[0]; + ch_l[1]= dl_ch[1] ; + + // for proper allignment of SIMD vectors + if((ue->frame_parms.N_RB_DL&1) == 0) { + dl_ch -= 20; + //Interpolate fdcrl1 with ch_r + multadd_real_vector_complex_scalar(filt8_dcrl1, + ch_r, + dl_ch, + 8); + //Interpolate fdclh1 with ch_l + multadd_real_vector_complex_scalar(filt8_dclh1, + ch_l, + dl_ch, + 8); + dl_ch += 16; + //Interpolate fdcrh1 with ch_r + multadd_real_vector_complex_scalar(filt8_dcrh1, + ch_r, + dl_ch, + 8); + //Interpolate fdcll1 with ch_l + multadd_real_vector_complex_scalar(filt8_dcll1, + ch_l, + dl_ch, + 8); + } else { + dl_ch -= 28; + //Interpolate fdcrl1 with ch_r + multadd_real_vector_complex_scalar(filt8_dcrl2, + ch_r, + dl_ch, + 8); + //Interpolate fdclh1 with ch_l + multadd_real_vector_complex_scalar(filt8_dclh2, + ch_l, + dl_ch, + 8); + dl_ch += 16; + //Interpolate fdcrh1 with ch_r + multadd_real_vector_complex_scalar(filt8_dcrh2, + ch_r, + dl_ch, + 8); + //Interpolate fdcll1 with ch_l + multadd_real_vector_complex_scalar(filt8_dcll2, + ch_l, + dl_ch, + 8); + } + } + } + else if (config_type == NFAPI_NR_DMRS_TYPE1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + dl_ch, + 8); + dl_ch -= 24; + + for (pilot_cnt=6; pilot_cnt<6*(nb_rb_pdsch-1); pilot_cnt += 6) { + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + dl_ch, + 8); + dl_ch -= 16; + } + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + dl_ch, + 8); + } + else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + dl_ch, + 8); + dl_ch -= 24; + + for (pilot_cnt=4; pilot_cnt<4*(nb_rb_pdsch-1); pilot_cnt += 4) { + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + dl_ch, + 8); + dl_ch -= 16; + } + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + dl_ch, + 8); + } +#ifdef DEBUG_PDSCH + dl_ch = (int16_t *)&dl_ch_estimates[p*ue->frame_parms.nb_antennas_rx+aarx][ch_offset]; for(uint16_t idxP=0; idxPstatus == ACTIVE) { + symbInSlot = dlsch0_harq->start_symbol + dlsch0_harq->nb_symbols; + startSymbIndex = &dlsch0_harq->start_symbol; + nbSymb = &dlsch0_harq->nb_symbols; + L_ptrs = &dlsch0_harq->PTRSTimeDensity; + K_ptrs = &dlsch0_harq->PTRSFreqDensity; + dmrsSymbPos = &dlsch0_harq->dlDmrsSymbPos; + ptrsSymbPos = &dlsch0_harq->ptrs_symbols; + ptrsSymbIdx = &dlsch0_harq->ptrs_symbol_index; + ptrsReOffset = &dlsch0_harq->PTRSReOffset; + dmrsConfigType = &dlsch0_harq->dmrsConfigType; + nb_rb = &dlsch0_harq->nb_rb; + } + if(dlsch1_harq) { + symbInSlot = dlsch1_harq->start_symbol + dlsch0_harq->nb_symbols; + startSymbIndex = &dlsch1_harq->start_symbol; + nbSymb = &dlsch1_harq->nb_symbols; + L_ptrs = &dlsch1_harq->PTRSTimeDensity; + K_ptrs = &dlsch1_harq->PTRSFreqDensity; + dmrsSymbPos = &dlsch1_harq->dlDmrsSymbPos; + ptrsSymbPos = &dlsch1_harq->ptrs_symbols; + ptrsSymbIdx = &dlsch1_harq->ptrs_symbol_index; + ptrsReOffset = &dlsch1_harq->PTRSReOffset; + dmrsConfigType = &dlsch1_harq->dmrsConfigType; + nb_rb = &dlsch1_harq->nb_rb; + } + /* loop over antennas */ + for (int aarx=0; aarxnb_antennas_rx; aarx++) { + phase_per_symbol = (int16_t*)pdsch_vars[gNB_id]->ptrs_phase_per_slot[aarx]; + ptrs_re_symbol = (int32_t*)pdsch_vars[gNB_id]->ptrs_re_per_slot[aarx]; + ptrs_re_symbol[symbol] = 0; + phase_per_symbol[(2*symbol)+1] = 0; // Imag + /* set DMRS estimates to 0 angle with magnitude 1 */ + if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { + /* set DMRS real estimation to 32767 */ + phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767 +#ifdef DEBUG_DL_PTRS + printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]); +#endif + } + else { // real ptrs value is set to 0 + phase_per_symbol[2*symbol] = 0; // Real + } + + if(dlsch0_harq->status == ACTIVE) { + if(symbol == *startSymbIndex) { + *ptrsSymbPos = 0; + set_ptrs_symb_idx(ptrsSymbPos, + *nbSymb, + *startSymbIndex, + 1<< *L_ptrs, + *dmrsSymbPos); + } + /* if not PTRS symbol set current ptrs symbol index to zero*/ + *ptrsSymbIdx = 0; + /* Check if current symbol contains PTRS */ + if(is_ptrs_symbol(symbol, *ptrsSymbPos)) { + *ptrsSymbIdx = symbol; + /*------------------------------------------------------------------------------------------------------- */ + /* 1) Estimate common phase error per PTRS symbol */ + /*------------------------------------------------------------------------------------------------------- */ + nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb, + rnti, + (int16_t *)&pdsch_vars[gNB_id]->dl_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pdsch], + nr_slot_rx, + symbol,frame_parms->ofdm_symbol_size, + (int16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(symbol * nb_re_pdsch)], + ue->nr_gold_pdsch[gNB_id][nr_slot_rx][symbol][0], + &phase_per_symbol[2* symbol], + &ptrs_re_symbol[symbol]); + } + }// HARQ 0 + + /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ + if(symbol == (symbInSlot -1)) { + /*------------------------------------------------------------------------------------------------------- */ + /* 2) Interpolate PTRS estimated value in TD */ + /*------------------------------------------------------------------------------------------------------- */ + /* If L-PTRS is > 0 then we need interpolation */ + if(*L_ptrs > 0) { + ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb); + if(ret != 0) { + LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); + } + } +#ifdef DEBUG_DL_PTRS + LOG_M("ptrsEst.m","est",pdsch_vars[gNB_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); + LOG_M("rxdataF_bf_ptrs_comp.m","bf_ptrs_cmp", + &pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(*startSymbIndex) * NR_NB_SC_PER_RB * (*nb_rb) ], + (*nb_rb) * NR_NB_SC_PER_RB * (*nbSymb),1,1); +#endif + /*------------------------------------------------------------------------------------------------------- */ + /* 3) Compensated DMRS based estimated signal with PTRS estimation */ + /*--------------------------------------------------------------------------------------------------------*/ + for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) { + /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */ + /* Skip rotation if the slot processing is wrong */ + if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) { +#ifdef DEBUG_DL_PTRS + printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]); +#endif + rotate_cpx_vector((int16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], + &phase_per_symbol[2* i], + (int16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], + ((*nb_rb) * NR_NB_SC_PER_RB), 15); + }// if not DMRS Symbol + }// symbol loop + }// last symbol check + }//Antenna loop +}//main function diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 1837664391..c5330ce2f2 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -34,30 +34,30 @@ /*! \brief This function performs channel estimation including frequency and temporal interpolation -\param phy_vars_ue Pointer to UE PHY variables -\param eNB_id Index of target eNB -\param eNB_offset Offset for interfering eNB (in terms cell ID mod 3) +\param ue Pointer to UE PHY variables +\param gNB_id Index of target gNB \param Ns slot number (0..19) -\param p antenna port -\param l symbol within slot -\param symbol symbol within frame +\param symbol symbol within slot */ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_offset, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, unsigned char Ns, unsigned char symbol, unsigned short coreset_start_subcarrier, unsigned short nb_rb_coreset); int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, - uint8_t eNB_offset, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, unsigned char Ns, unsigned char symbol, int dmrss, NR_UE_SSB *current_ssb); int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_offset, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, unsigned char Ns, unsigned char symbol, int dmrss, @@ -65,33 +65,56 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, uint8_t n_hf); int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_offset, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, + bool is_SI, unsigned char Ns, unsigned short p, unsigned char symbol, + unsigned short BWPStart, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch); void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, PHY_VARS_NR_UE *ue, - module_id_t eNB_id, + module_id_t gNB_id, uint8_t frame, uint8_t subframe, unsigned char clear, short coef); void nr_ue_measurements(PHY_VARS_NR_UE *ue, - unsigned int subframe_offset, - unsigned char N0_symbol, - unsigned char abstraction_flag, - unsigned char rank_adaptation, - uint8_t subframe); + UE_nr_rxtx_proc_t *proc, + uint8_t slot); + +void nr_ue_rsrp_measurements(PHY_VARS_NR_UE *ue, + uint8_t gNB_index, + UE_nr_rxtx_proc_t *proc, + uint8_t slot, + uint8_t abstraction_flag); + +void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + uint8_t slot); void phy_adjust_gain_nr(PHY_VARS_NR_UE *ue, uint32_t rx_power_fil_dB, - uint8_t eNB_id); + uint8_t gNB_id); int16_t get_nr_PL(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index); +void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, + NR_UE_PDSCH **pdsch_vars, + NR_DL_FRAME_PARMS *frame_parms, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq, + uint8_t gNB_id, + uint8_t nr_slot_rx, + unsigned char symbol, + uint32_t nb_re_pdsch, + uint16_t rnti, + RX_type_t rx_type); + +float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index); #endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 860ca11d8c..7f6f0e8ef9 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -19,6 +19,19 @@ * contact@openairinterface.org */ +/*! \file nr_ue_measurements.c + * \brief UE measurements routines + * \author R. Knopp, G. Casati, K. Saaifan + * \date 2020 + * \version 0.1 + * \company Eurecom, Fraunhofer IIS + * \email: knopp@eurecom.fr, guido.casati@iis.fraunhofer.de, khodr.saaifan@iis.fraunhofer.de + * \note + * \warning + */ + +#include "executables/softmodem-common.h" +#include "executables/nr-softmodem-common.h" #include "PHY/defs_nr_UE.h" #include "PHY/phy_extern_nr_ue.h" #include "common/utils/LOG/log.h" @@ -32,163 +45,301 @@ //#define DEBUG_MEAS_UE //#define DEBUG_RANK_EST -#if 0 -int16_t cond_num_threshold = 0; - -void print_shorts(char *s,short *x) -{ - - - printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s, - x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7] - ); - -} -void print_ints(char *s,int *x) -{ - - - printf("%s : %d,%d,%d,%d\n",s, - x[0],x[1],x[2],x[3] - ); - -} -#endif - +// Returns the pathloss in dB for the active UL BWP on the selected carrier based on the DL RS associated with the PRACH transmission +// computation according to clause 7.4 (Physical random access channel) of 3GPP TS 38.213 version 16.3.0 Release 16 +// Assumptions: +// - PRACH transmission from a UE is not in response to a detection of a PDCCH order by the UE +// Measurement units: +// - referenceSignalPower: dBm/RE (average EPRE of the resources elements that carry secondary synchronization signals in dBm) int16_t get_nr_PL(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index){ PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; + int16_t pathloss; - /* - if (ue->frame_parms.mode1_flag == 1) - RSoffset = 6; - else - RSoffset = 3; - */ + if (get_softmodem_params()->do_ra){ - /* LOG_D(PHY,"get_nr_PL : rsrp %f dBm/RE (%f), eNB power %d dBm/RE\n", - (1.0*dB_fixed_times10(ue->measurements.rsrp[eNB_index])-(10.0*ue->rx_total_gain_dB))/10.0, - 10*log10((double)ue->measurements.rsrp[eNB_index]), - ue->frame_parms.pdsch_config_common.referenceSignalPower);*/ + long referenceSignalPower = ue->nrUE_config.ssb_config.ss_pbch_power; - return((int16_t)(((10*ue->rx_total_gain_dB) - dB_fixed_times10(ue->measurements.rsrp[gNB_index]))/10)); - // dB_fixed_times10(RSoffset*12*ue_g[Mod_id][CC_id]->frame_parms.N_RB_DL) + - //(ue->frame_parms.pdsch_config_common.referenceSignalPower*10))/10)); + pathloss = (int16_t)(referenceSignalPower - ue->measurements.rsrp_dBm[gNB_index]); + + LOG_D(MAC, "In %s: pathloss %d dB, UE RX total gain %d dB, referenceSignalPower %ld dBm/RE (%f mW), RSRP %d dBm (%f mW)\n", + __FUNCTION__, + pathloss, + ue->rx_total_gain_dB, + referenceSignalPower, + pow(10, referenceSignalPower/10), + ue->measurements.rsrp_dBm[gNB_index], + pow(10, ue->measurements.rsrp_dBm[gNB_index]/10)); + + } else { + + pathloss = ((int16_t)(((10*ue->rx_total_gain_dB) - dB_fixed_times10(ue->measurements.rsrp[gNB_index]))/10)); + + } + + return pathloss; + +} + +uint32_t get_nr_rx_total_gain_dB (module_id_t Mod_id,uint8_t CC_id) +{ + + PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; + + if (ue) + return ue->rx_total_gain_dB; + + return 0xFFFFFFFF; +} + + +float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index) +{ + + AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is null\n"); + AssertFatal(PHY_vars_UE_g[Mod_id]!=NULL,"PHY_vars_UE_g[%d] is null\n",Mod_id); + AssertFatal(PHY_vars_UE_g[Mod_id][CC_id]!=NULL,"PHY_vars_UE_g[%d][%d] is null\n",Mod_id,CC_id); + + PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; + + if (ue) + return (10*log10(ue->measurements.rsrp[gNB_index])- + get_nr_rx_total_gain_dB(Mod_id,0) - + 10*log10(20*12)); + return -140.0; } void nr_ue_measurements(PHY_VARS_NR_UE *ue, - unsigned int subframe_offset, - unsigned char N0_symbol, - unsigned char abstraction_flag, - unsigned char rank_adaptation, - uint8_t subframe) + UE_nr_rxtx_proc_t *proc, + uint8_t slot) { - int aarx,aatx,eNB_id=0; //,gain_offset=0; - //int rx_power[NUMBER_OF_CONNECTED_eNB_MAX]; - -/*#if defined(__x86_64__) || defined(__i386__) - __m128i *dl_ch0_128, *dl_ch1_128; -#elif defined(__arm__) - int16x8_t *dl_ch0_128, *dl_ch1_128get_PL; -#endif*/ - + int aarx, aatx, gNB_id = 0; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - //unsigned int limit, subband; - //int nb_subbands, subband_size, last_subband_size, *dl_ch0, *dl_ch1, N_RB_DL = frame_parms->N_RB_DL; - - int ch_offset, rank_tm3_tm4 = 0; + int ch_offset = frame_parms->ofdm_symbol_size*2; + NR_UE_DLSCH_t *dlsch = ue->dlsch[proc->thread_id][gNB_id][0]; + uint8_t harq_pid = dlsch->current_harq_pid; + int N_RB_DL = dlsch->harq_processes[harq_pid]->nb_rb; ue->measurements.nb_antennas_rx = frame_parms->nb_antennas_rx; - - /*int16_t *dl_ch; - dl_ch = (int16_t *)&ue->pdsch_vars[ue->current_thread_id[subframe]][0]->dl_ch_estimates[eNB_id][ch_offset];*/ - ch_offset = ue->frame_parms.ofdm_symbol_size*2; - -//printf("testing measurements\n"); // signal measurements + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++){ - for (eNB_id=0; eNB_idn_connected_eNB; eNB_id++) { - for (aarx=0; aarxnb_antennas_rx; aarx++) { - for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { - ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] = - (signal_energy_nodc(&ue->pdsch_vars[ue->current_thread_id[subframe]][0]->dl_ch_estimates[eNB_id][ch_offset], - (50*12))); - //- ue->measurements.n0_power[aarx]; + ue->measurements.rx_power_tot[gNB_id] = 0; - if (ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]<0) - ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] = 0; //ue->measurements.n0_power[aarx]; + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++){ - ue->measurements.rx_spatial_power_dB[eNB_id][aatx][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]); + ue->measurements.rx_power[gNB_id][aarx] = 0; - if (aatx==0) - ue->measurements.rx_power[eNB_id][aarx] = ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]; - else - ue->measurements.rx_power[eNB_id][aarx] += ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]; - } //aatx + for (aatx = 0; aatx < frame_parms->nb_antenna_ports_gNB; aatx++){ - ue->measurements.rx_power_dB[eNB_id][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_power[eNB_id][aarx]); + ue->measurements.rx_spatial_power[gNB_id][aatx][aarx] = (signal_energy_nodc(&ue->pdsch_vars[proc->thread_id][0]->dl_ch_estimates[gNB_id][ch_offset], N_RB_DL*NR_NB_SC_PER_RB)); - if (aarx==0) - ue->measurements.rx_power_tot[eNB_id] = ue->measurements.rx_power[eNB_id][aarx]; - else - ue->measurements.rx_power_tot[eNB_id] += ue->measurements.rx_power[eNB_id][aarx]; - } //aarx + if (ue->measurements.rx_spatial_power[gNB_id][aatx][aarx]<0) + ue->measurements.rx_spatial_power[gNB_id][aatx][aarx] = 0; - ue->measurements.rx_power_tot_dB[eNB_id] = (unsigned short) dB_fixed(ue->measurements.rx_power_tot[eNB_id]); + ue->measurements.rx_spatial_power_dB[gNB_id][aatx][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_spatial_power[gNB_id][aatx][aarx]); + ue->measurements.rx_power[gNB_id][aarx] += ue->measurements.rx_spatial_power[gNB_id][aatx][aarx]; - } //eNB_id - - //printf("ue measurement addr dlch %p\n", dl_ch); + } - eNB_id=0; + ue->measurements.rx_power_dB[gNB_id][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_power[gNB_id][aarx]); + ue->measurements.rx_power_tot[gNB_id] += ue->measurements.rx_power[gNB_id][aarx]; - if (ue->transmission_mode[eNB_id]!=4 && ue->transmission_mode[eNB_id]!=3) - ue->measurements.rank[eNB_id] = 0; - else - ue->measurements.rank[eNB_id] = rank_tm3_tm4; - // printf ("tx mode %d\n", ue->transmission_mode[eNB_id]); - // printf ("rank %d\n", ue->PHY_measurements.rank[eNB_id]); + } + + ue->measurements.rx_power_tot_dB[gNB_id] = (unsigned short) dB_fixed(ue->measurements.rx_power_tot[gNB_id]); + + } // filter to remove jitter if (ue->init_averaging == 0) { - for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) - ue->measurements.rx_power_avg[eNB_id] = (int) - (((k1*((long long int)(ue->measurements.rx_power_avg[eNB_id]))) + - (k2*((long long int)(ue->measurements.rx_power_tot[eNB_id]))))>>10); - //LOG_I(PHY,"Noise Power Computation: k1 %d k2 %d n0 avg %d n0 tot %d\n", k1, k2, ue->measurements.n0_power_avg, - // ue->measurements.n0_power_tot); - ue->measurements.n0_power_avg = (int) - (((k1*((long long int) (ue->measurements.n0_power_avg))) + - (k2*((long long int) (ue->measurements.n0_power_tot))))>>10); + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) + ue->measurements.rx_power_avg[gNB_id] = (int)(((k1*((long long int)(ue->measurements.rx_power_avg[gNB_id]))) + (k2*((long long int)(ue->measurements.rx_power_tot[gNB_id])))) >> 10); + + ue->measurements.n0_power_avg = (int)(((k1*((long long int) (ue->measurements.n0_power_avg))) + (k2*((long long int) (ue->measurements.n0_power_tot))))>>10); + + LOG_D(PHY, "Noise Power Computation: k1 %lld k2 %lld n0 avg %u n0 tot %u\n", k1, k2, ue->measurements.n0_power_avg, ue->measurements.n0_power_tot); + } else { - for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) - ue->measurements.rx_power_avg[eNB_id] = ue->measurements.rx_power_tot[eNB_id]; + + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) + ue->measurements.rx_power_avg[gNB_id] = ue->measurements.rx_power_tot[gNB_id]; ue->measurements.n0_power_avg = ue->measurements.n0_power_tot; ue->init_averaging = 0; + } - for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) { - ue->measurements.rx_power_avg_dB[eNB_id] = dB_fixed( ue->measurements.rx_power_avg[eNB_id]); - ue->measurements.wideband_cqi_tot[eNB_id] = dB_fixed2(ue->measurements.rx_power_tot[eNB_id],ue->measurements.n0_power_tot); - ue->measurements.wideband_cqi_avg[eNB_id] = dB_fixed2(ue->measurements.rx_power_avg[eNB_id],ue->measurements.n0_power_avg); - ue->measurements.rx_rssi_dBm[eNB_id] = ue->measurements.rx_power_avg_dB[eNB_id] - ue->rx_total_gain_dB; -//#ifdef DEBUG_MEAS_UE - LOG_D(PHY,"[eNB %d] Subframe %d, RSSI %d dBm, RSSI (digital) %d dB, WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d\n", - eNB_id, - subframe, - ue->measurements.rx_rssi_dBm[eNB_id], - ue->measurements.rx_power_avg_dB[eNB_id], - ue->measurements.wideband_cqi_avg[eNB_id], - ue->measurements.rx_power_avg[eNB_id], - ue->measurements.n0_power_tot); -//#endif + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { + + ue->measurements.rx_power_avg_dB[gNB_id] = dB_fixed( ue->measurements.rx_power_avg[gNB_id]); + ue->measurements.wideband_cqi_tot[gNB_id] = dB_fixed2(ue->measurements.rx_power_tot[gNB_id], ue->measurements.n0_power_tot); + ue->measurements.wideband_cqi_avg[gNB_id] = dB_fixed2(ue->measurements.rx_power_avg[gNB_id], ue->measurements.n0_power_avg); + ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - 10*log10(pow(2, 30)) - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + + LOG_D(PHY, "[gNB %d] Slot %d, RSSI %d dB (%d dBm/RE), WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d\n", + gNB_id, + slot, + ue->measurements.rx_power_avg_dB[gNB_id], + ue->measurements.rx_rssi_dBm[gNB_id], + ue->measurements.wideband_cqi_avg[gNB_id], + ue->measurements.rx_power_avg[gNB_id], + ue->measurements.n0_power_tot); } #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); #endif -} \ No newline at end of file +} + +// This function implements: +// - SS reference signal received power (SS-RSRP) as per clause 5.1.1 of 3GPP TS 38.215 version 16.3.0 Release 16 +// - no Layer 3 filtering implemented (no filterCoefficient provided from RRC) +// Todo: +// - Layer 3 filtering according to clause 5.5.3.2 of 3GPP TS 38.331 version 16.2.0 Release 16 +// Measurement units: +// - RSRP: W (dBW) +// - RX Gain dB +void nr_ue_rsrp_measurements(PHY_VARS_NR_UE *ue, + uint8_t gNB_id, + UE_nr_rxtx_proc_t *proc, + uint8_t slot, + uint8_t abstraction_flag) +{ + int aarx; + int nb_re; + int k_start = 55; + int k_end = 183; + unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; + uint8_t l_sss = ue->symbol_offset + 2; + + if (ssb_offset>= ue->frame_parms.ofdm_symbol_size){ + + ssb_offset -= ue->frame_parms.ofdm_symbol_size; + + } + + ue->measurements.rsrp[gNB_id] = 0; + + if (abstraction_flag == 0) { + + LOG_D(PHY, "In %s: [UE %d] slot %d l_sss %d ssb_offset %d\n", __FUNCTION__, ue->Mod_id, slot, l_sss, ssb_offset); + + nb_re = 0; + + for (aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) { + + int16_t *rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aarx][(l_sss*ue->frame_parms.ofdm_symbol_size) + ssb_offset]; + + for(int k = k_start; k < k_end; k++){ + + #ifdef DEBUG_MEAS_UE + LOG_I(PHY, "In %s rxF_sss %d %d\n", __FUNCTION__, rxF_sss[k*2], rxF_sss[k*2 + 1]); + #endif + + ue->measurements.rsrp[gNB_id] += (((int32_t)rxF_sss[k*2]*rxF_sss[k*2]) + ((int32_t)rxF_sss[k*2 + 1]*rxF_sss[k*2 + 1])); + + nb_re++; + + } + } + + ue->measurements.rsrp[gNB_id] /= nb_re; + + } else { + + ue->measurements.rsrp[gNB_id] = -93; + + } + + ue->measurements.rsrp_filtered[gNB_id] = ue->measurements.rsrp[gNB_id]; + + ue->measurements.rsrp_dBm[gNB_id] = 10*log10(ue->measurements.rsrp[gNB_id]) + 30 - 10*log10(pow(2,30)) - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + + LOG_D(PHY, "In %s: [UE %d] slot %d SS-RSRP: %d dBm/RE (%d)\n", + __FUNCTION__, + ue->Mod_id, + slot, + ue->measurements.rsrp_dBm[gNB_id], + ue->measurements.rsrp[gNB_id]); + +} + +// This function computes the received noise power +// Measurement units: +// - psd_awgn (AWGN power spectral density): dBm/Hz +void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + uint8_t slot){ + + uint8_t k; + int aarx, nb_nulls; + int16_t *rxF_sss; + uint8_t k_left = 48; + uint8_t k_right = 183; + uint8_t k_length = 8; + uint8_t l_sss = ue->symbol_offset + 2; + unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; + double rx_gain = openair0_cfg[0].rx_gain[0]; + double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0]; + + ue->measurements.n0_power_tot = 0; + + LOG_D(PHY, "In %s doing measurements for ssb_offset %d l_sss %d \n", __FUNCTION__, ssb_offset, l_sss); + + for (aarx = 0; aarxframe_parms.nb_antennas_rx; aarx++) { + + nb_nulls = 0; + ue->measurements.n0_power[aarx] = 0; + rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aarx][(l_sss*ue->frame_parms.ofdm_symbol_size) + ssb_offset]; + + //-ve spectrum from SSS + for(k = k_left; k < k_left + k_length; k++){ + + #ifdef DEBUG_MEAS_RRC + LOG_I(PHY, "In %s -rxF_sss %d %d\n", __FUNCTION__, rxF_sss[k*2], rxF_sss[k*2 + 1]); + #endif + + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[k*2]*rxF_sss[k*2]) + ((int32_t)rxF_sss[k*2 + 1]*rxF_sss[k*2 + 1])); + nb_nulls++; + + } + + //+ve spectrum from SSS + for(k = k_right; k < k_right + k_length; k++){ + + #ifdef DEBUG_MEAS_RRC + LOG_I(PHY, "In %s +rxF_sss %d %d\n", __FUNCTION__, rxF_sss[k*2], rxF_sss[k*2 + 1]); + #endif + + ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[k*2]*rxF_sss[k*2]) + ((int32_t)rxF_sss[k*2 + 1]*rxF_sss[k*2 + 1])); + nb_nulls++; + + } + + ue->measurements.n0_power[aarx] /= nb_nulls; + ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]); + ue->measurements.n0_power_tot += ue->measurements.n0_power[aarx]; + + } + + ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/aarx); + + #ifdef DEBUG_MEAS_RRC + const int psd_awgn = -174; + const int scs = 15000 * (1 << ue->frame_parms.numerology_index); + const int nf_usrp = ue->measurements.n0_power_tot_dB + 3 + 30 - ((int)rx_gain - (int)rx_gain_offset) - 10 * log10(pow(2, 30)) - (psd_awgn + dB_fixed(scs) + dB_fixed(ue->frame_parms.ofdm_symbol_size)); + LOG_D(PHY, "In [%s][slot:%d] NF USRP %d dB\n", __FUNCTION__, slot, nf_usrp); + #endif + + LOG_D(PHY, "In [%s][slot:%d] Noise Level %d (digital level %d dB, noise power spectral density %f dBm/RE)\n", + __FUNCTION__, + slot, + ue->measurements.n0_power_tot, + ue->measurements.n0_power_tot_dB, + ue->measurements.n0_power_tot_dB + 30 - 10*log10(pow(2, 30)) - dB_fixed(ue->frame_parms.ofdm_symbol_size) - ((int)rx_gain - (int)rx_gain_offset)); + +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 7cde6e31c1..84c9627c8a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -30,28 +30,35 @@ * \warning */ -#ifdef USER_MODE - #include - #include - #include -#endif +#include +#include +#include + #include "executables/softmodem-common.h" - #include "nr_transport_proto_ue.h" #include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h" #include "PHY/phy_extern_nr_ue.h" #include "PHY/CODING/coding_extern.h" #include "PHY/sse_intrin.h" -#include "PHY/NR_TRANSPORT/nr_dci.h" +#include "common/utils/nr/nr_common.h" #include "assertions.h" #include "T.h" +char nr_dci_format_string[8][30] = { + "NR_DL_DCI_FORMAT_1_0", + "NR_DL_DCI_FORMAT_1_1", + "NR_DL_DCI_FORMAT_2_0", + "NR_DL_DCI_FORMAT_2_1", + "NR_DL_DCI_FORMAT_2_2", + "NR_DL_DCI_FORMAT_2_3", + "NR_UL_DCI_FORMAT_0_0", + "NR_UL_DCI_FORMAT_0_1"}; + //#define DEBUG_DCI_DECODING 1 //#define NR_LTE_PDCCH_DCI_SWITCH -#define NR_PDCCH_DCI_RUN // activates new nr functions //#define NR_PDCCH_DCI_DEBUG // activates NR_PDCCH_DCI_DEBUG logs #ifdef NR_PDCCH_DCI_DEBUG #define LOG_DNL(a, ...) printf("\n\t\t<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ ) @@ -71,7 +78,6 @@ #define LOG_I(A,B...) printf(B) #endif -#ifdef NR_PDCCH_DCI_RUN //static const int16_t conjugate[8]__attribute__((aligned(32))) = {-1,1,-1,1,-1,1,-1,1}; @@ -79,12 +85,15 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, uint32_t *z, - NR_DL_FRAME_PARMS *frame_parms, uint8_t coreset_time_dur, + uint8_t start_symbol, uint32_t coreset_nbr_rb, uint8_t reg_bundle_size_L, uint8_t coreset_interleaver_size_R, - uint8_t n_shift) { + uint8_t n_shift, + uint8_t number_of_candidates, + uint16_t *CCE, + uint8_t *L) { /* * This function will do demapping and deinterleaving from llr containing demodulated symbols * Demapping will regroup in REG and bundles @@ -120,52 +129,83 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, | REG 0 (bundle 0) bundle 0 bundle 0 */ - int c=0,r=0; - uint16_t bundle_j=0, f_bundle_j=0,f_reg=0; - uint32_t coreset_C=0; + int c = 0, r = 0; + uint16_t bundle_j = 0, f_bundle_j = 0, f_reg = 0; + uint32_t coreset_C = 0; uint16_t index_z, index_llr; int coreset_interleaved = 0; - if (reg_bundle_size_L!=0) { // interleaving will be done only if reg_bundle_size_L != 0 - coreset_interleaved=1; - coreset_C = (uint32_t)((coreset_nbr_rb * coreset_time_dur)/ (coreset_interleaver_size_R*reg_bundle_size_L)); + if (reg_bundle_size_L != 0) { // interleaving will be done only if reg_bundle_size_L != 0 + coreset_interleaved = 1; + coreset_C = (uint32_t) (coreset_nbr_rb / (coreset_interleaver_size_R * reg_bundle_size_L)); } else { - reg_bundle_size_L=6; + reg_bundle_size_L = 6; } - for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) { - if ((reg%reg_bundle_size_L) == 0) { + + int f_bundle_j_list[(2*NR_MAX_PDCCH_AGG_LEVEL) - 1] = {}; + + for (int reg = 0; reg < coreset_nbr_rb; reg++) { + if ((reg % reg_bundle_size_L) == 0) { if (r == coreset_interleaver_size_R) { - r=0; + r = 0; c++; } - bundle_j = (c*coreset_interleaver_size_R)+r; - f_bundle_j = ((r*coreset_C)+c+n_shift)%((coreset_nbr_rb*coreset_time_dur)/reg_bundle_size_L); + bundle_j = (c * coreset_interleaver_size_R) + r; + f_bundle_j = ((r * coreset_C) + c + n_shift) % (coreset_nbr_rb / reg_bundle_size_L); - if (coreset_interleaved==0) f_bundle_j=bundle_j; + if (coreset_interleaved == 0) f_bundle_j = bundle_j; + + f_bundle_j_list[reg / 6] = f_bundle_j; - LOG_DNL("[r=%d,c=%d] bundle_j(%d) interleaved at f_bundle_j(%d)\n",r,c,bundle_j,f_bundle_j); } + if ((reg % reg_bundle_size_L) == 0) r++; + } - f_reg = (f_bundle_j*reg_bundle_size_L)+(reg%reg_bundle_size_L); - index_z = 9*reg; - index_llr = 9*((uint16_t)floor(f_reg/coreset_time_dur)+((f_reg%coreset_time_dur)*(coreset_nbr_rb))); - - for (int i=0; i<9; i++) { - z[index_z + i] = llr[index_llr + i]; - LOG_D(PHY,"[reg=%d,bundle_j=%d] z[%d]=(%d,%d) <-> \t[f_reg=%d,fbundle_j=%d] llr[%d]=(%d,%d) \n", - reg,bundle_j,(index_z + i),*(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i]), - f_reg,f_bundle_j,(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i])); + // Get cce_list indices by reg_idx in ascending order + int f_bundle_j_list_id = 0; + int f_bundle_j_list_ord[(2*NR_MAX_PDCCH_AGG_LEVEL)-1] = {}; + for (int c_id = 0; c_id < number_of_candidates; c_id++ ) { + f_bundle_j_list_id = CCE[c_id]; + for (int p = 0; p < NR_MAX_PDCCH_AGG_LEVEL; p++) { + for (int p2 = CCE[c_id]; p2 < CCE[c_id] + L[c_id]; p2++) { + AssertFatal(p2<2*NR_MAX_PDCCH_AGG_LEVEL,"number_of_candidates %d : p2 %d, CCE[%d] %d, L[%d] %d\n",number_of_candidates,p2,c_id,CCE[c_id],c_id,L[c_id]); + if (f_bundle_j_list[p2] == p) { + AssertFatal(f_bundle_j_list_id < 2*NR_MAX_PDCCH_AGG_LEVEL,"f_bundle_j_list_id %d\n",f_bundle_j_list_id); + f_bundle_j_list_ord[f_bundle_j_list_id] = p; + f_bundle_j_list_id++; + break; + } + } } + } - if ((reg%reg_bundle_size_L) == 0) r++; + int rb = 0; + for (int c_id = 0; c_id < number_of_candidates; c_id++ ) { + for (int symbol_idx = start_symbol; symbol_idx < start_symbol+coreset_time_dur; symbol_idx++) { + for (int cce_count = CCE[c_id/coreset_time_dur]+c_id%coreset_time_dur; cce_count < CCE[c_id/coreset_time_dur]+c_id%coreset_time_dur+L[c_id]; cce_count += coreset_time_dur) { + for (int reg_in_cce_idx = 0; reg_in_cce_idx < NR_NB_REG_PER_CCE; reg_in_cce_idx++) { + + f_reg = (f_bundle_j_list_ord[cce_count] * reg_bundle_size_L) + reg_in_cce_idx; + index_z = 9 * rb; + index_llr = (uint16_t) (f_reg + symbol_idx * coreset_nbr_rb) * 9; + + for (int i = 0; i < 9; i++) { + z[index_z + i] = llr[index_llr + i]; +#ifdef NR_PDCCH_DCI_DEBUG + LOG_I(PHY,"[cce_count=%d,reg_in_cce_idx=%d,bundle_j=%d,symbol_idx=%d,candidate=%d] z[%d]=(%d,%d) <-> \t[f_reg=%d,fbundle_j=%d] llr[%d]=(%d,%d) \n", + cce_count,reg_in_cce_idx,bundle_j,symbol_idx,c_id,(index_z + i),*(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i]), + f_reg,f_bundle_j,(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i])); +#endif + } + rb++; + } + } + } } } -#endif - -#ifdef NR_PDCCH_DCI_RUN int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int16_t *pdcch_llr, uint8_t symbol,uint32_t coreset_nbr_rb) { int16_t *rxF = (int16_t *) &rxdataF_comp[0][(symbol * coreset_nbr_rb * 12)]; @@ -196,7 +236,6 @@ int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, return (0); } -#endif #if 0 @@ -237,9 +276,10 @@ int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, //compute average channel_level on each (TX,RX) antenna pair void nr_pdcch_channel_level(int32_t **dl_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - uint8_t nb_rb) { + NR_DL_FRAME_PARMS *frame_parms, + int32_t *avg, + int symbol, + uint8_t nb_rb) { int16_t rb; uint8_t aarx; #if defined(__x86_64__) || defined(__i386__) @@ -254,9 +294,9 @@ void nr_pdcch_channel_level(int32_t **dl_ch_estimates_ext, //clear average level #if defined(__x86_64__) || defined(__i386__) avg128P = _mm_setzero_si128(); - dl_ch128=(__m128i *)&dl_ch_estimates_ext[aarx][0]; + dl_ch128=(__m128i *)&dl_ch_estimates_ext[aarx][symbol*nb_rb*12]; #elif defined(__arm__) - dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[aarx][0]; + dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[aarx][symbol*nb_rb*12]; #endif for (rb=0; rb<(nb_rb*3)>>2; rb++) { @@ -282,7 +322,7 @@ void nr_pdcch_channel_level(int32_t **dl_ch_estimates_ext, ((int32_t *)&avg128P)[1] + ((int32_t *)&avg128P)[2] + ((int32_t *)&avg128P)[3])/(nb_rb*9); - // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); + LOG_DDD("Channel level : %d\n",avg[aarx]); } #if defined(__x86_64__) || defined(__i386__) @@ -300,7 +340,6 @@ void nr_pdcch_channel_level(int32_t **dl_ch_estimates_ext, -#ifdef NR_PDCCH_DCI_RUN // This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources) void nr_pdcch_extract_rbs_single(int32_t **rxdataF, int32_t **dl_ch_estimates, @@ -339,7 +378,7 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, #endif for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - dl_ch0 = &dl_ch_estimates[aarx][0]; + dl_ch0 = &dl_ch_estimates[aarx][frame_parms->ofdm_symbol_size*symbol]; LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n",aarx); dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)]; @@ -367,29 +406,31 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, * we have to point the pointer at (1+c_rb-N_RB_DL/2) in rxdataF */ - LOG_DDD("n_BWP_start=%d, coreset_nbr_rb=%d\n",n_BWP_start,coreset_nbr_rb); int c_rb_by6; - c_rb = n_BWP_start; + c_rb = 0; for (int rb=0;rb>3] & (1<<(c_rb_by6&7))) == 0) c_rb+=6; - LOG_DDD("c_rb=%d\n",c_rb); + // skip zeros in frequency domain bitmap + while ((coreset_freq_dom[c_rb_by6>>3] & (1<<(7-(c_rb_by6&7)))) == 0) { + c_rb+=6; + c_rb_by6 = c_rb/6; + } + rxF=NULL; // first we set initial conditions for pointer to rxdataF depending on the situation of the first RB within the CORESET (c_rb = n_BWP_start) - if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { + if (((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): even case - rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; LOG_DDD("in even case c_rb (%d) is lower than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); } - if ((c_rb >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { + if (((c_rb + n_BWP_start) >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF - rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol + rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; // we point at the 1st part of the rxdataF in symbol LOG_DDD("in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))); //rxF = &rxdataF[aarx][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol @@ -399,29 +440,29 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, //#endif } - if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { + if (((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): odd case - rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; #ifdef NR_PDCCH_DCI_DEBUG LOG_D(PHY,"in odd case c_rb (%d) is lower or equal than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); #endif } - if ((c_rb > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { + if (((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF just after the first IQ symbols of the RB containing DC - rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol + rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; // we point at the 1st part of the rxdataF in symbol #ifdef NR_PDCCH_DCI_DEBUG LOG_D(PHY,"in odd case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - frame_parms->N_RB_DL) - 5 + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))); #endif } - if ((c_rb == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // treatment of RB containing the DC + if (((c_rb + n_BWP_start) == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // treatment of RB containing the DC // if odd number RBs in system bandwidth and first RB to be treated is higher than middle system bandwidth (around DC) // we have to treat the RB in two parts: first part from i=0 to 5, the data is at the end of rxdataF (pointing at the end of the table) - rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; + rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; #ifdef NR_PDCCH_DCI_DEBUG LOG_D(PHY,"in odd case c_rb (%d) is half N_RB_DL + 1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); @@ -494,9 +535,7 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, } } -#endif - - +#define print_shorts(s,x) printf("%s %d,%d,%d,%d,%d,%d,%d,%d\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7]) void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, @@ -531,16 +570,15 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, #endif for (rb=0; rb<(coreset_nbr_rb*3)>>2; rb++) { - //printf("rb %d\n",rb); #if defined(__x86_64__) || defined(__i386__) // multiply by conjugated channel mmtmpP0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]); - // print_ints("re",&mmtmpP0); + //print_ints("re",&mmtmpP0); // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i *)&conjugate[0]); - // print_ints("im",&mmtmpP1); + //print_ints("im",&mmtmpP1); mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[0]); // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit) mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift); @@ -549,12 +587,12 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, // print_ints("im(shift)",&mmtmpP1); mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1); mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1); - // print_ints("c0",&mmtmpP2); - // print_ints("c1",&mmtmpP3); + //print_ints("c0",&mmtmpP2); + //print_ints("c1",&mmtmpP3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpP2,mmtmpP3); - //print_shorts("rx:",rxdataF128); - //print_shorts("ch:",dl_ch128); - //print_shorts("pack:",rxdataF_comp128); +// print_shorts("rx:",(int16_t*)rxdataF128); +// print_shorts("ch:",(int16_t*)dl_ch128); +// print_shorts("pack:",(int16_t*)rxdataF_comp128); // multiply by conjugated channel mmtmpP0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) @@ -591,9 +629,9 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, for (int i=0; i<12 ; i++) LOG_DDD("rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n", - (rb*12)+i, ((short *)rxdataF128)[i<<1],((short *)rxdataF128)[1+(i<<1)], - (rb*12)+i, ((short *)dl_ch128)[i<<1],((short *)dl_ch128)[1+(i<<1)], - (rb*12)+i, ((short *)rxdataF_comp128)[i<<1],((short *)rxdataF_comp128)[1+(i<<1)]); + (rb*12)+i, ((short *)rxdataF128)[i<<1],((short *)rxdataF128)[1+(i<<1)], + (rb*12)+i, ((short *)dl_ch128)[i<<1],((short *)dl_ch128)[1+(i<<1)], + (rb*12)+i, ((short *)rxdataF_comp128)[i<<1],((short *)rxdataF_comp128)[1+(i<<1)]); dl_ch128+=3; rxdataF128+=3; @@ -646,118 +684,105 @@ void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, #endif } -#if 0 -void pdcch_siso(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, - uint8_t l) { - uint8_t rb,re,jj,ii; - jj=0; - ii=0; - - for (rb=0; rbN_RB_DL; rb++) { - for (re=0; re<12; re++) { - rxdataF_comp[0][jj++] = rxdataF_comp[0][ii]; - ii++; - } - } -} -#endif - -#ifdef NR_PDCCH_DCI_RUN int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, - uint32_t frame, - uint32_t slot) { + UE_nr_rxtx_proc_t *proc, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) { + uint32_t frame = proc->frame_rx; + uint32_t slot = proc->nr_slot_rx; NR_UE_COMMON *common_vars = &ue->common_vars; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[slot]][0]; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; uint8_t log2_maxh, aarx; int32_t avgs; int32_t avgP[4]; - for (int i=0;inb_search_space;i++) { + int n_rb,rb_offset; + get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); + LOG_D(PHY,"pdcch coreset: freq %x, n_rb %d, rb_offset %d\n", + rel15->coreset.frequency_domain_resource[0],n_rb,rb_offset); + for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { + LOG_D(PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); - rel15 = &pdcch_vars->pdcch_config[i]; - int n_rb,rb_offset; - get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); - for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { - LOG_D(PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); + nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, + pdcch_vars->dl_ch_estimates, + pdcch_vars->rxdataF_ext, + pdcch_vars->dl_ch_estimates_ext, + s, + frame_parms, + rel15->coreset.frequency_domain_resource, + n_rb, + rel15->BWPStart); - nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[slot]].rxdataF, - pdcch_vars->dl_ch_estimates, - pdcch_vars->rxdataF_ext, - pdcch_vars->dl_ch_estimates_ext, - s, - frame_parms, - rel15->coreset.frequency_domain_resource, - n_rb, - rel15->BWPStart); + LOG_D(PHY,"we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",*avgP); + LOG_D(PHY,"in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); + // compute channel level based on ofdm symbol 0 + nr_pdcch_channel_level(pdcch_vars->dl_ch_estimates_ext, + frame_parms, + avgP, + s, + n_rb); + avgs = 0; - LOG_D(PHY,"we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",*avgP); - LOG_D(PHY,"in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); - // compute channel level based on ofdm symbol 0 - nr_pdcch_channel_level(pdcch_vars->dl_ch_estimates_ext, - frame_parms, - avgP, - n_rb); - avgs = 0; + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + avgs = cmax(avgs, avgP[aarx]); - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) - avgs = cmax(avgs, avgP[aarx]); + log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; - log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; #ifdef UE_DEBUG_TRACE - LOG_D(PHY,"slot %d: pdcch log2_maxh = %d (%d,%d)\n",slot,log2_maxh,avgP[0],avgs); + LOG_D(PHY,"slot %d: pdcch log2_maxh = %d (%d,%d)\n",slot,log2_maxh,avgP[0],avgs); #endif #if T_TRACER - T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(frame%1024), T_INT(slot), - T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); + T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(frame%1024), T_INT(slot), + T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); #endif - LOG_D(PHY,"we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh); - LOG_D(PHY,"in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); - // compute LLRs for ofdm symbol 0 only - nr_pdcch_channel_compensation(pdcch_vars->rxdataF_ext, - pdcch_vars->dl_ch_estimates_ext, - pdcch_vars->rxdataF_comp, - NULL, - frame_parms, - s, - log2_maxh, - n_rb); // log2_maxh+I0_shift - if (frame_parms->nb_antennas_rx > 1) { - LOG_D(PHY,"we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); - nr_pdcch_detection_mrc(frame_parms, pdcch_vars->rxdataF_comp,s); - } + LOG_D(PHY,"we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh); + LOG_D(PHY,"in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); + // compute LLRs for ofdm symbol 0 only + nr_pdcch_channel_compensation(pdcch_vars->rxdataF_ext, + pdcch_vars->dl_ch_estimates_ext, + pdcch_vars->rxdataF_comp, + NULL, + frame_parms, + s, + log2_maxh, + n_rb); // log2_maxh+I0_shift + if (frame_parms->nb_antennas_rx > 1) { + LOG_D(PHY,"we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); + nr_pdcch_detection_mrc(frame_parms, pdcch_vars->rxdataF_comp,s); + } - LOG_D(PHY,"we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s); - LOG_D(PHY,"in nr_pdcch_llr(rxdataF_comp -> llr)\n"); - nr_pdcch_llr(frame_parms, - pdcch_vars->rxdataF_comp, - pdcch_vars->llr, - s, - n_rb); + LOG_D(PHY,"we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s); + LOG_D(PHY,"in nr_pdcch_llr(rxdataF_comp -> llr)\n"); + nr_pdcch_llr(frame_parms, + pdcch_vars->rxdataF_comp, + pdcch_vars->llr, + s, + n_rb); #if T_TRACER - // T(T_UE_PHY_PDCCH_IQ, T_INT(frame_parms->N_RB_DL), T_INT(frame_parms->N_RB_DL), - // T_INT(n_pdcch_symbols), - // T_BUFFER(pdcch_vars[eNB_id]->rxdataF_comp, frame_parms->N_RB_DL*12*n_pdcch_symbols* 4)); + // T(T_UE_PHY_PDCCH_IQ, T_INT(frame_parms->N_RB_DL), T_INT(frame_parms->N_RB_DL), + // T_INT(n_pdcch_symbols), + // T_BUFFER(pdcch_vars[eNB_id]->rxdataF_comp, frame_parms->N_RB_DL*12*n_pdcch_symbols* 4)); #endif #ifdef DEBUG_DCI_DECODING - printf("demapping: slot %d, mi %d\n",slot,get_mi(frame_parms,slot)); + printf("demapping: slot %d, mi %d\n",slot,get_mi(frame_parms,slot)); #endif - } + } - LOG_D(PHY,"we enter nr_pdcch_demapping_deinterleaving()\n"); - nr_pdcch_demapping_deinterleaving((uint32_t *) pdcch_vars->llr, - (uint32_t *) pdcch_vars->e_rx, - frame_parms, - rel15->coreset.duration, - n_rb, - rel15->coreset.RegBundleSize, - rel15->coreset.InterleaverSize, - rel15->coreset.ShiftIndex); + LOG_D(PHY,"we enter nr_pdcch_demapping_deinterleaving(), number of candidates %d\n",rel15->number_of_candidates); + nr_pdcch_demapping_deinterleaving((uint32_t *) pdcch_vars->llr, + (uint32_t *) pdcch_vars->e_rx, + rel15->coreset.duration, + rel15->coreset.StartSymbolIndex, + n_rb, + rel15->coreset.RegBundleSize, + rel15->coreset.InterleaverSize, + rel15->coreset.ShiftIndex, + rel15->number_of_candidates, + rel15->CCE, + rel15->L); /* nr_pdcch_unscrambling(rel15->rnti, frame_parms, @@ -767,41 +792,13 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, // get_nCCE(n_pdcch_symbols, frame_parms, mi) * 72, rel15->coreset.pdcch_dmrs_scrambling_id); */ - LOG_D(PHY,"we end nr_pdcch_unscrambling()\n"); - LOG_D(PHY,"Ending nr_rx_pdcch() function\n"); + LOG_D(PHY,"we end nr_pdcch_unscrambling()\n"); + LOG_D(PHY,"Ending nr_rx_pdcch() function\n"); - } return (0); } -#endif -void pdcch_scrambling(NR_DL_FRAME_PARMS *frame_parms, - uint8_t nr_tti_rx, - uint8_t *e, - uint32_t length) { - int i; - uint8_t reset; - uint32_t x1, x2, s=0; - reset = 1; - // x1 is set in lte_gold_generic - x2 = (nr_tti_rx<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 - - for (i=0; i>(i&0x1f))&1)); - if (e[i] != 2) // element is 2 - e[i] = (e[i]&1) ^ ((s>>(i&0x1f))&1); - } -} - - -#ifdef NR_PDCCH_DCI_RUN void nr_pdcch_unscrambling(int16_t *z, uint16_t scrambling_RNTI, @@ -831,43 +828,79 @@ void nr_pdcch_unscrambling(int16_t *z, } } -#endif +/* This function compares the received DCI bits with + * re-encoded DCI bits and returns the number of mismatched bits + */ +uint16_t nr_dci_false_detection(uint64_t *dci, + int16_t *soft_in, + const t_nrPolar_params *polar_param, + int encoded_length, + int rnti) { + + uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD]; + polar_encoder_fast(dci, (void*)encoder_output, rnti, 1, (t_nrPolar_params *)polar_param); + uint8_t *enout_p = (uint8_t*)encoder_output; + uint16_t x = 0; + + for (int i=0; i> 15 ) & 1); + x += ( ( enout_p[i] >> 1 ) & 1 ) ^ ( ( soft_in[i*8+1] >> 15 ) & 1 ); + x += ( ( enout_p[i] >> 2 ) & 1 ) ^ ( ( soft_in[i*8+2] >> 15 ) & 1 ); + x += ( ( enout_p[i] >> 3 ) & 1 ) ^ ( ( soft_in[i*8+3] >> 15 ) & 1 ); + x += ( ( enout_p[i] >> 4 ) & 1 ) ^ ( ( soft_in[i*8+4] >> 15 ) & 1 ); + x += ( ( enout_p[i] >> 5 ) & 1 ) ^ ( ( soft_in[i*8+5] >> 15 ) & 1 ); + x += ( ( enout_p[i] >> 6 ) & 1 ) ^ ( ( soft_in[i*8+6] >> 15 ) & 1 ); + x += ( ( enout_p[i] >> 7 ) & 1 ) ^ ( ( soft_in[i*8+7] >> 15 ) & 1 ); + } + return x; +} -#ifdef NR_PDCCH_DCI_RUN uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, - int frame, - int slot, - fapi_nr_dci_indication_t *dci_ind) { + UE_nr_rxtx_proc_t *proc, + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) { - NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[slot]][0]; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; - for (int i=0;inb_search_space;i++) { + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; - rel15 = &pdcch_vars->pdcch_config[i]; - int dci_length = rel15->dci_length; - //int gNB_id = 0; - int16_t tmp_e[16*108]; - rnti_t n_rnti; + //int gNB_id = 0; + int16_t tmp_e[16*108]; + rnti_t n_rnti; - for (int j=0;jnumber_of_candidates;j++) { - int CCEind = rel15->CCE[j]; - int L = rel15->L[j]; + for (int j=0;jnumber_of_candidates;j++) { + int CCEind = rel15->CCE[j]; + int L = rel15->L[j]; + + // Loop over possible DCI lengths + for (int k = 0; k < rel15->num_dci_options; k++) { + // skip this candidate if we've already found one with the + // same rnti and format at a different aggregation level + int dci_found=0; + for (int ind=0;ind < dci_ind->number_of_dcis ; ind++) { + if (rel15->rnti== dci_ind->dci_list[ind].rnti && + rel15->dci_format_options[k]==dci_ind->dci_list[ind].dci_format) { + dci_found=1; + break; + } + } + if (dci_found==1) continue; + int dci_length = rel15->dci_length_options[k]; uint64_t dci_estimation[2]= {0}; const t_nrPolar_params *currentPtrDCI = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L, 1, &ue->polarList); - LOG_D(PHY, "Trying DCI candidate %d of %d number of candidates, CCE %d (%d), L %d\n", j, rel15->number_of_candidates, CCEind, CCEind*9*6*2, L); + LOG_D(PHY, "Trying DCI candidate %d of %d number of candidates, CCE %d (%d), L %d, length %d, format %s\n", + j, rel15->number_of_candidates, CCEind, CCEind*9*6*2, L, dci_length,nr_dci_format_string[rel15->dci_format_options[k]]); nr_pdcch_unscrambling(&pdcch_vars->e_rx[CCEind*108], rel15->coreset.scrambling_rnti, L*108, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e); - #ifdef DEBUG_DCI_DECODING - uint32_t * z = (uint32_t *) &pdcch_vars->e_rx[CCEind*108]; - for (int index_z = 0; index_z < 96; index_z++){ - for (int i=0; i<9; i++) { - LOG_D(PHY,"z[%d]=(%d,%d) \n", (9*index_z + i), *(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i])); - } +#ifdef DEBUG_DCI_DECODING + uint32_t * z = (uint32_t *) &pdcch_vars->e_rx[CCEind*108]; + for (int index_z = 0; index_z < 96; index_z++){ + for (int i=0; i<9; i++) { + LOG_D(PHY,"z[%d]=(%d,%d) \n", (9*index_z + i), *(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i])); } - #endif + } +#endif uint16_t crc = polar_decoder_int16(tmp_e, dci_estimation, @@ -875,865 +908,36 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, currentPtrDCI); n_rnti = rel15->rnti; - + LOG_D(PHY, "(%i.%i) dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d)\n", + proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length); if (crc == n_rnti) { - LOG_D(PHY,"Decoded crc %x matches rnti %x for DCI format %d\n", crc, n_rnti, rel15->dci_format); - dci_ind->SFN = frame; - dci_ind->slot = slot; - dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti; - dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind; - dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format; - dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length; - memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8); - dci_ind->number_of_dcis++; + LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx)\n", + proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length,*(unsigned long long*)dci_estimation); + uint16_t mb = nr_dci_false_detection(dci_estimation,tmp_e,currentPtrDCI,L*108,n_rnti); + ue->dci_thres = (ue->dci_thres + mb) / 2; + if (mb > (ue->dci_thres+20)) { + LOG_W(PHY,"DCI false positive. Dropping DCI index %d. Mismatched bits: %d/%d. Current DCI threshold: %d\n",j,mb,L*108,ue->dci_thres); + continue; + } + else { + dci_ind->SFN = proc->frame_rx; + dci_ind->slot = proc->nr_slot_rx; + dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti; + dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind; + dci_ind->dci_list[dci_ind->number_of_dcis].N_CCE = L; + dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k]; + dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length; + memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8); + dci_ind->number_of_dcis++; + break; // If DCI is found, no need to check for remaining DCI lengths + } } else { - LOG_D(PHY,"Decoded crc %x does not match rnti %x for DCI format %d\n", crc, n_rnti, rel15->dci_format); + LOG_D(PHY,"(%i.%i) Decoded crc %x does not match rnti %x for DCI format %d\n", proc->frame_rx, proc->nr_slot_rx, crc, n_rnti, rel15->dci_format_options[k]); } } } + pdcch_vars->nb_search_space = 0; return(dci_ind->number_of_dcis); } -/* -void nr_dci_decoding_procedure0(int s, - int p, - int coreset_time_dur, - uint16_t coreset_nbr_rb, - NR_UE_PDCCH **pdcch_vars, - int do_common, - uint8_t nr_tti_rx, - NR_DCI_ALLOC_t *dci_alloc, - int16_t eNB_id, - uint8_t current_thread_id, - NR_DL_FRAME_PARMS *frame_parms, - //uint8_t mi, - uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES], - uint8_t L, - NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t format_css, - NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t format_uss, - uint8_t sizeof_bits, - uint8_t sizeof_bytes, - uint8_t *dci_cnt, - crc_scrambled_t *crc_scrambled, - format_found_t *format_found, - uint16_t pdcch_DMRS_scrambling_id, - uint32_t *CCEmap0, - uint32_t *CCEmap1, - uint32_t *CCEmap2) { - uint32_t crc, CCEind, nCCE[3]; - uint32_t *CCEmap = NULL, CCEmap_mask = 0; - uint8_t L2 = (1 << L); - unsigned int Yk, nb_candidates = 0, i, m; - unsigned int CCEmap_cand; - uint32_t decoderState=0; - // A[p], p is the current active CORESET - uint16_t A[3]= {39827,39829,39839}; - //Table 10.1-2: Maximum number of PDCCH candidates per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3} - uint8_t m_max_slot_pdcch_Table10_1_2 [4] = {44,36,22,20}; - //Table 10.1-3: Maximum number of non-overlapped CCEs per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3} - //uint8_t cce_max_slot_pdcch_Table10_1_3 [4] = {56,56,48,32}; - int coreset_nbr_cce_per_symbol=0; - LOG_DDD("format_found is %d \n", *format_found); - //if (mode == NO_DCI) { - // #ifdef NR_PDCCH_DCI_DEBUG - // LOG_DDD("skip DCI decoding: expect no DCIs at nr_tti_rx %d in current searchSpace\n", nr_tti_rx); - // #endif - // return; - //} - LOG_DDD("frequencyDomainResources=%lx, duration=%d\n", - pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources, pdcch_vars[eNB_id]->coreset[p].duration); - // nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols, frame_parms, mi); - for (int i = 0; i < 45; i++) { - // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' - if (((pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_cce_per_symbol++; - } - - nCCE[p] = pdcch_vars[eNB_id]->coreset[p].duration*coreset_nbr_cce_per_symbol; // 1 CCE = 6 RB - // p is the current CORESET we are currently monitoring (among the 3 possible CORESETs in a BWP) - // the number of CCE in the current CORESET is: - // the number of symbols in the CORESET (pdcch_vars[eNB_id]->coreset[p].duration) - // multiplied by the number of bits set to '1' in the frequencyDomainResources bitmap - // (1 bit set to '1' corresponds to 6 RB and 1 CCE = 6 RB) - LOG_DDD("nCCE[%d]=%d\n",p,nCCE[p]); - - // if (nCCE > get_nCCE(3, frame_parms, 1)) { - //LOG_D(PHY, - //"skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", - //nCCE, get_nCCE(3, frame_parms, 1)); - //return; - // } - -// if (nCCE < L2) { -// LOG_D(PHY, "skip DCI decoding: nCCE=%d < L2=%d\n", nCCE, L2); -// return; -// } - -// if (mode == NO_DCI) { -// LOG_D(PHY, "skip DCI decoding: expect no DCIs at nr_tti_rx %d\n", -// nr_tti_rx); -// return; -// } - - if (do_common == 1) { - Yk = 0; - - if (pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.common_dci_formats == cformat2_0) { - // for dci_format_2_0, the nb_candidates is obtained from a different variable - switch (L2) { - case 1: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel1; - break; - - case 2: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel2; - break; - - case 4: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel4; - break; - - case 8: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel8; - break; - - case 16: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel16; - break; - - default: - break; - } - } else if (pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.common_dci_formats == cformat2_3) { - // for dci_format_2_3, the nb_candidates is obtained from a different variable - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.srs_nrofCandidates; - } else { - nb_candidates = (L2 == 4) ? 4 : ((L2 == 8)? 2 : 1); // according to Table 10.1-1 (38.213 section 10.1) - LOG_DDD("we are in common searchSpace and nb_candidates=%u for L2=%d\n", nb_candidates, L2); - } - } else { - switch (L2) { - case 1: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel1; - break; - - case 2: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel2; - break; - - case 4: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel4; - break; - - case 8: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel8; - break; - - case 16: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel16; - break; - - default: - break; - } - - // Find first available in ue specific search space - // according to procedure in Section 10.1 of 38.213 - // compute Yk - Yk = (unsigned int) pdcch_vars[eNB_id]->crnti; - - for (i = 0; i <= nr_tti_rx; i++) - Yk = (Yk * A[p%3]) % 65537; - } - - LOG_DDD("L2(%d) | nCCE[%d](%d) | Yk(%u) | nb_candidates(%u)\n", L2, p, nCCE[p], Yk, nb_candidates); - // for (CCEind=0; - // CCEind nCCE[p]) - // nb_candidates = nCCE[p] / L2; - // In the next code line there is maybe a bug. The spec is not comparing Table 10.1-2 with nb_candidates, but with total number of candidates for all s and all p - int m_p_s_L_max = (m_max_slot_pdcch_Table10_1_2[1]<=nb_candidates ? m_max_slot_pdcch_Table10_1_2[1] : nb_candidates); - - if (L==4) m_p_s_L_max=1; // Table 10.1-2 is not defined for L=4 - - if(0 <= L && L < 4) LOG_DDD("m_max_slot_pdcch_Table10_1_2(%d)=%d\n",L,m_max_slot_pdcch_Table10_1_2[L]); - - for (m = 0; m < nb_candidates; m++) { - int n_ci = 0; - - if (nCCE[p] < L2) return; - - LOG_DDD("debug1(%d)=nCCE[p]/L2 | nCCE[%d](%d) | L2(%d)\n",nCCE[p] / L2,p,nCCE[p],L2); - LOG_DDD("debug2(%d)=L2*m_p_s_L_max | L2(%d) | m_p_s_L_max(%d)\n",L2*m_p_s_L_max,L2,m_p_s_L_max); - CCEind = (((Yk + (uint16_t)(floor((m*nCCE[p])/(L2*m_p_s_L_max))) + n_ci) % (uint16_t)(floor(nCCE[p] / L2))) * L2); - LOG_DDD("CCEind(%u) = (((Yk(%u) + ((m(%u)*nCCE[p](%u))/(L2(%d)*m_p_s_L_max(%d)))) %% (nCCE[p] / L2)) * L2)\n", - CCEind,Yk,m,nCCE[p],L2,m_p_s_L_max); - LOG_DDD("n_candidate(m)=%u | CCEind=%u |",m,CCEind); - - if (CCEind < 32) - CCEmap = CCEmap0; - else if (CCEind < 64) - CCEmap = CCEmap1; - else if (CCEind < 96) - CCEmap = CCEmap2; - else AssertFatal(1==0,"Illegal CCEind %u (Yk %u, m %u, nCCE %u, L2 %u\n", CCEind, Yk, m, nCCE[p], L2); - - switch (L2) { - case 1: - CCEmap_mask = (1 << (CCEind & 0x1f)); - break; - - case 2: - CCEmap_mask = (3 << (CCEind & 0x1f)); - break; - - case 4: - CCEmap_mask = (0xf << (CCEind & 0x1f)); - break; - - case 8: - CCEmap_mask = (0xff << (CCEind & 0x1f)); - break; - - case 16: - CCEmap_mask = (0xfff << (CCEind & 0x1f)); - break; - - default: - LOG_E(PHY, "Illegal L2 value %d\n", L2); - //mac_xface->macphy_exit("Illegal L2\n"); - return; // not reached - } - - CCEmap_cand = (*CCEmap) & CCEmap_mask; - // CCE is not allocated yet - LOG_DDD("CCEmap_cand=%u \n",CCEmap_cand); - - if (CCEmap_cand == 0) { -#ifdef DEBUG_DCI_DECODING - - if (do_common == 1) - LOG_I(PHY,"[DCI search nPdcch %d - common] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n", - pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); - else - LOG_I(PHY,"[DCI search nPdcch %d - ue spec] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x) format %d\n", - pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_uss); - -#endif - LOG_DDD("... we enter function dci_decoding(sizeof_bits=%d L=%d) -----\n",sizeof_bits,L); - LOG_DDD("... we have to replace this part of the code by polar decoding\n"); - // for (int m=0; m < (nCCE[p]*6*9*2); m++) - LOG_DDD("(polar decoding)-> polar intput (with coreset_time_dur=%d, coreset_nbr_rb=%d, p=%d, CCEind=%u): \n", - coreset_time_dur,coreset_nbr_rb,p,CCEind); - - //int reg_p=0,reg_e=0; - //for (int m=0; m < (L2*6); m++){ - //reg_p = (((int)floor(m/coreset_time_dur))+((m%coreset_time_dur)*(L2*6/coreset_time_dur)))*9*2; - //reg_e = m*9*2; - //for (int i=0; i<9*2; i++){ - //polar_input[reg_p+i] = (pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]>0) ? (1.0):(-1.0); - //polar_input[reg_e+i] = (pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]>0) ? (1/sqrt(2)):((-1)/sqrt(2)); - //printf("\t m=%d \tpolar_input[%d]=%lf <-> e_rx[%d]=%d\n",m,reg_e+i,polar_input[reg_e+i], - // ((CCEind*9*6*2) + reg_e + i),pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]); - //printf("\t m=%d \tpolar_input[%d]=%lf <-> e_rx[%d]=%d\n",m,reg_p+i,polar_input[reg_p+i], - // ((CCEind*9*6*2) + reg_e + i),pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]); - //} - //} - - //#ifdef NR_PDCCH_DCI_DEBUG - //printf("\n"); - //int j=0; - //uint32_t polar_hex[27] = {0}; - //for (int i=0; ie_rx[CCEind*9*6*2], - dci_estimation, - 1, - currentPtrDCI); - crc = decoderState; - //crc = (crc16(&dci_decoded_output[current_thread_id][0], sizeof_bits) >> 16) ^ extract_crc(&dci_decoded_output[current_thread_id][0], sizeof_bits); - LOG_DDD("... we end function dci_decoding() with crc=%x\n",crc); - LOG_DDD("... we have to replace this part of the code by polar decoding\n"); -#ifdef DEBUG_DCI_DECODING - LOG_DDD("(nr_dci_decoding_procedure0: crc =>%d\n",crc); -#endif //uint16_t tc_rnti, uint16_t int_rnti, uint16_t sfi_rnti, uint16_t tpc_pusch_rnti, uint16_t tpc_pucch_rnti, uint16_t tpc_srs__rnti - LOG_DDD("format_found=%d\n",*format_found); - LOG_DDD("crc_scrambled=%d\n",*crc_scrambled); - - if (crc == crc_scrambled_values[_C_RNTI_]) { - *crc_scrambled =_c_rnti; - *format_found=1; - } - - if (crc == crc_scrambled_values[_CS_RNTI_]) { - *crc_scrambled =_cs_rnti; - *format_found=1; - } - - if (crc == crc_scrambled_values[_NEW_RNTI_]) { - *crc_scrambled =_new_rnti; - *format_found=1; - } - - if (crc == crc_scrambled_values[_TC_RNTI_]) { - *crc_scrambled =_tc_rnti; - *format_found=_format_1_0_found; - } - - if (crc == crc_scrambled_values[_P_RNTI_]) { - *crc_scrambled =_p_rnti; - *format_found=_format_1_0_found; - } - - if (crc == crc_scrambled_values[_SI_RNTI_]) { - *crc_scrambled =_si_rnti; - *format_found=_format_1_0_found; - } - - if (crc == crc_scrambled_values[_RA_RNTI_]) { - *crc_scrambled =_ra_rnti; - *format_found=_format_1_0_found; - } - - if (crc == crc_scrambled_values[_SP_CSI_RNTI_]) { - *crc_scrambled =_sp_csi_rnti; - *format_found=_format_0_1_found; - } - - if (crc == crc_scrambled_values[_SFI_RNTI_]) { - *crc_scrambled =_sfi_rnti; - *format_found=_format_2_0_found; - } - - if (crc == crc_scrambled_values[_INT_RNTI_]) { - *crc_scrambled =_int_rnti; - *format_found=_format_2_1_found; - } - - if (crc == crc_scrambled_values[_TPC_PUSCH_RNTI_]) { - *crc_scrambled =_tpc_pusch_rnti; - *format_found=_format_2_2_found; - } - - if (crc == crc_scrambled_values[_TPC_PUCCH_RNTI_]) { - *crc_scrambled =_tpc_pucch_rnti; - *format_found=_format_2_2_found; - } - - if (crc == crc_scrambled_values[_TPC_SRS_RNTI_]) { - *crc_scrambled =_tpc_srs_rnti; - *format_found=_format_2_3_found; - } - - - LOG_DDD("format_found=%d\n",*format_found); - LOG_DDD("crc_scrambled=%d\n",*crc_scrambled); - - if (*format_found!=255) { - dci_alloc[*dci_cnt].dci_length = sizeof_bits; - dci_alloc[*dci_cnt].rnti = crc; - dci_alloc[*dci_cnt].L = L; - dci_alloc[*dci_cnt].firstCCE = CCEind; - memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_estimation,8); - - LOG_DDD("rnti matches -> DCI FOUND !!! crc =>0x%x, sizeof_bits %d, sizeof_bytes %d \n", - dci_alloc[*dci_cnt].rnti, dci_alloc[*dci_cnt].dci_length, sizeof_bytes); - LOG_DDD("dci_cnt %d (format_css %d crc_scrambled %d) L %d, firstCCE %d pdu[0] 0x%lx pdu[1] 0x%lx \n", - *dci_cnt, format_css,*crc_scrambled,dci_alloc[*dci_cnt].L, dci_alloc[*dci_cnt].firstCCE,dci_alloc[*dci_cnt].dci_pdu[0],dci_alloc[*dci_cnt].dci_pdu[1]); - if ((format_css == cformat0_0_and_1_0) || (format_uss == uformat0_0_and_1_0)) { - if ((*crc_scrambled == _p_rnti) || (*crc_scrambled == _si_rnti) || (*crc_scrambled == _ra_rnti)) { - dci_alloc[*dci_cnt].format = format1_0; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_1_0_found; - // LOG_DDD("a format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); - } else { - if ((dci_estimation[0]&1) == 0) { - dci_alloc[*dci_cnt].format = format0_0; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_0_0_found; - // LOG_DDD("b format0_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); - } - - if ((dci_estimation[0]&1) == 1) { - dci_alloc[*dci_cnt].format = format1_0; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_1_0_found; - // LOG_DDD("c format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); - } - } - } - - if (format_css == cformat2_0) { - dci_alloc[*dci_cnt].format = format2_0; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_2_0_found; - } - - if (format_css == cformat2_1) { - dci_alloc[*dci_cnt].format = format2_1; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_2_1_found; - } - - if (format_css == cformat2_2) { - dci_alloc[*dci_cnt].format = format2_2; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_2_2_found; - } - - if (format_css == cformat2_3) { - dci_alloc[*dci_cnt].format = format2_3; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_2_3_found; - } - - if (format_uss == uformat0_1_and_1_1) { - if ((dci_estimation[0]&1) == 0) { - dci_alloc[*dci_cnt].format = format0_1; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_0_1_found; - } - - if ((dci_estimation[0]&1) == 1) { - dci_alloc[*dci_cnt].format = format1_1; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_1_1_found; - } - } - - // store first nCCE of group for PUCCH transmission of ACK/NAK - pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - - // if (crc == si_rnti) { - // dci_alloc[*dci_cnt].format = format_si; - // *dci_cnt = *dci_cnt + 1; - // } else if (crc == p_rnti) { - // dci_alloc[*dci_cnt].format = format_p; - // *dci_cnt = *dci_cnt + 1; - // } else if (crc == ra_rnti) { - // dci_alloc[*dci_cnt].format = format_ra; - // // store first nCCE of group for PUCCH transmission of ACK/NAK - // pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - // *dci_cnt = *dci_cnt + 1; - // } else if (crc == pdcch_vars[eNB_id]->crnti) { - - // if ((mode & UL_DCI) && (format_c == format0) - // && ((dci_decoded_output[current_thread_id][0] & 0x80) - // == 0)) { // check if pdu is format 0 or 1A - // if (*format0_found == 0) { - // dci_alloc[*dci_cnt].format = format0; - // *format0_found = 1; - // *dci_cnt = *dci_cnt + 1; - // pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - // } - // } else if (format_c == format0) { // this is a format 1A DCI - // dci_alloc[*dci_cnt].format = format1A; - // *dci_cnt = *dci_cnt + 1; - // pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - // } else { - // // store first nCCE of group for PUCCH transmission of ACK/NAK - // if (*format_c_found == 0) { - // dci_alloc[*dci_cnt].format = format_c; - // *dci_cnt = *dci_cnt + 1; - // *format_c_found = 1; - // pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - // } - // } - // } - //LOG_I(PHY,"DCI decoding CRNTI [format: %d, nCCE[nr_tti_rx: %d]: %d ], AggregationLevel %d \n",format_c, nr_tti_rx, pdcch_vars[eNB_id]->nCCE[nr_tti_rx],L2); - // memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes); - switch (1 << L) { - case 1: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - - case 2: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - - case 4: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - - case 8: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - - case 16: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - } - -#ifdef DEBUG_DCI_DECODING - LOG_I(PHY,"[DCI search] Found DCI %d rnti %x Aggregation %d length %d format %d in CCE %d (CCEmap %x) candidate %d / %d \n", - *dci_cnt,crc,1<pdcch_vars[ue->current_thread_id[nr_tti_rx]]; - NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; - uint16_t pdcch_DMRS_scrambling_id = pdcch_vars2->coreset[p].pdcchDMRSScramblingID; - uint64_t coreset_freq_dom = pdcch_vars2->coreset[p].frequencyDomainResources; - int coreset_time_dur = pdcch_vars2->coreset[p].duration; - uint16_t coreset_nbr_rb=0; - - for (int i = 0; i < 45; i++) { - // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' - if (((coreset_freq_dom & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_rb++; - } - - coreset_nbr_rb = 6 * coreset_nbr_rb; - // coreset_time_dur,coreset_nbr_rb, - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - //uint8_t mi;// = get_mi(&ue->frame_parms, nr_tti_rx); - //uint8_t tmode = ue->transmission_mode[eNB_id]; - //uint8_t frame_type = frame_parms->frame_type; - uint8_t format_0_0_1_0_size_bits = 0, format_0_0_1_0_size_bytes = 0; //FIXME - uint8_t format_0_1_1_1_size_bits = 0, format_0_1_1_1_size_bytes = 0; //FIXME - uint8_t format_2_0_size_bits = 0, format_2_0_size_bytes = 0; //FIXME - uint8_t format_2_1_size_bits = 0, format_2_1_size_bytes = 0; //FIXME - uint8_t format_2_2_size_bits = 0, format_2_2_size_bytes = 0; //FIXME - uint8_t format_2_3_size_bits = 0, format_2_3_size_bytes = 0; //FIXME - /* - * - * The implementation of this function will depend on the information given by the searchSpace IE - * - * In LTE the UE has no knowledge about: - * - the type of search (common or ue-specific) - * - the DCI format it is going to be decoded when performing the PDCCH monitoring - * So the blind decoding has to be done for common and ue-specific searchSpaces for each aggregation level and for each dci format - * - * In NR the UE has a knowledge about the search Space type and the DCI format it is going to be decoded, - * so in the blind decoding we can call the function nr_dci_decoding_procedure0 with the searchSpace type and the dci format parameter - * We will call this function as many times as aggregation levels indicated in searchSpace - * Implementation according to 38.213 v15.1.0 Section 10. - * - */ - NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t css_dci_format = pdcch_vars2->searchSpace[s].searchSpaceType.common_dci_formats; //FIXME!!! - NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t uss_dci_format = pdcch_vars2->searchSpace[s].searchSpaceType.ue_specific_dci_formats; //FIXME!!! - // The following initialization is only for test purposes. To be removed - // NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t - css_dci_format = cformat0_0_and_1_0; - //NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t - uss_dci_format = uformat0_0_and_1_0; - /* - * Possible overlap between RE for SS/PBCH blocks (described in section 10, 38.213) has not been implemented yet - * This can be implemented by setting variable 'mode = NO_DCI' when overlap occurs - */ - //dci_detect_mode_t mode = 3; //dci_detect_mode_select(&ue->frame_parms, nr_tti_rx); - LOG_DD("searSpaceType=%d\n",do_common); - LOG_DD("%s_dci_format=%d\n",do_common?"uss":"css",css_dci_format); - - - // A set of PDCCH candidates for a UE to monitor is defined in terms of PDCCH search spaces - if (do_common==0) { // COMMON SearchSpaceType assigned to current SearchSpace/CORESET - // Type0-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI - // number of consecutive resource blocks and a number of consecutive symbols for - // the control resource set of the Type0-PDCCH common search space from - // the four most significant bits of RMSI-PDCCH-Config as described in Tables 13-1 through 13-10 - // and determines PDCCH monitoring occasions - // from the four least significant bits of RMSI-PDCCH-Config, - // included in MasterInformationBlock, as described in Tables 13-11 through 13-15 - // Type0A-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI - // Type1-PDCCH common search space for a DCI format with CRC scrambled by a RA-RNTI, or a TC-RNTI, or a C-RNTI - // Type2-PDCCH common search space for a DCI format with CRC scrambled by a P-RNTI - if (css_dci_format == cformat0_0_and_1_0) { - // 38.213 v15.1.0 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE - // aggregation level for Type0/Type0A/Type2-PDCCH common search space - // CCE Aggregation Level Number of Candidates - // 4 4 - // 8 2 - // 16 1 - // FIXME - // We shall consider Table 10.1-1 to calculate the blind decoding only for Type0/Type0A/Type2-PDCCH - // Shall we consider the nrofCandidates in SearSpace IE that considers Aggregation Levels 1,2,4,8,16? Our implementation considers Table 10.1-1 - // blind decoding (Type0-PDCCH,Type0A-PDCCH,Type1-PDCCH,Type2-PDCCH) - // for format0_0 => we are NOT implementing format0_0 for common search spaces. FIXME! - // for format0_0 and format1_0, first we calculate dci pdu size - format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_c_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,0); - format_0_0_1_0_size_bytes = (format_0_0_1_0_size_bits%8 == 0) ? (uint8_t)floor(format_0_0_1_0_size_bits/8) : (uint8_t)(floor(format_0_0_1_0_size_bits/8) + 1); - LOG_DD("calculating dci format size for common searchSpaces with format css_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n", - css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes); - - for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8 - //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { - // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 - LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat0_0_and_1_0, uformat0_0_and_1_0, - format_0_0_1_0_size_bits, format_0_0_1_0_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_, pdcch_DMRS_scrambling_id,&CCEmap0, &CCEmap1, &CCEmap2); - - if (dci_cnt != old_dci_cnt) { - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,crc_scrambled_,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes, - 0); // after decoding dci successfully we recalculate dci pdu size with correct crc scrambled to get the right field sizes - old_dci_cnt = dci_cnt; - - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevelSFI, - cformat2_0, uformat0_0_and_1_0, - format_2_0_size_bits, format_2_0_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - - if (dci_cnt != old_dci_cnt) { - // we will exit the loop as we have found the DCI - aggregationLevelSFI = 5; - old_dci_cnt = dci_cnt; - - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat2_1, uformat0_0_and_1_0, - format_2_1_size_bits, format_2_1_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - - if (dci_cnt != old_dci_cnt) { - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat2_2, uformat0_0_and_1_0, - format_2_2_size_bits, format_2_2_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - - if (dci_cnt != old_dci_cnt) { - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat2_3, uformat0_0_and_1_0, - format_2_3_size_bits, format_2_3_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - - if (dci_cnt != old_dci_cnt) { - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - - for (int i=0; i nbr of CCE=8 - //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { - // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 - LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat0_0_and_1_0, uformat0_0_and_1_0, - format_0_0_1_0_size_bits, format_0_0_1_0_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - - if (dci_cnt != old_dci_cnt) { - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - - for (int i=0; i nbr of CCE=8 - //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { - // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 - LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat0_0_and_1_0, uformat0_1_and_1_1, - format_0_1_1_1_size_bits, format_0_1_1_1_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - - if (dci_cnt != old_dci_cnt) { - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - - for (int i=0; i -#endif - - #define MAX_DCI_SIZE_BITS 45 diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c index 347c9c2ab9..8a4cafc6d7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c @@ -45,11 +45,6 @@ //#define DEBUG_HARQ -//#include "LAYER2/MAC/extern.h" -//#include "LAYER2/MAC/defs.h" -//#include "../openair2/LAYER2/MAC/extern.h" -//#include "../openair2/LAYER2/MAC/defs.h" - //#define DEBUG_DCI #define NR_PDCCH_DCI_TOOLS //#define NR_PDCCH_DCI_TOOLS_DEBUG @@ -59,7 +54,7 @@ -uint8_t nr_subframe2harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t nr_tti_rx) { +uint8_t nr_subframe2harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t slot) { /* #ifdef DEBUG_DCI if (frame_parms->frame_type == TDD) @@ -69,11 +64,11 @@ uint8_t nr_subframe2harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8 #endif */ uint8_t ret = 255; - uint8_t subframe = nr_tti_rx>>((int)(log2 (frame_parms->ttis_per_subframe))); + uint8_t subframe = slot / frame_parms->slots_per_subframe; AssertFatal(1==0,"Not ready for this ...\n"); if (frame_parms->frame_type == FDD) { - ret = (((frame<<1)+nr_tti_rx)&7); + ret = (((frame<<1)+slot)&7); } else { } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 3a2cb3f436..b8cd59eead 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -43,10 +43,11 @@ #include "SIMULATION/TOOLS/sim.h" #include "executables/nr-uesoftmodem.h" #include "PHY/CODING/nrLDPC_extern.h" -#include "LAYER2/NR_MAC_gNB/mac_proto.h" -//#define DEBUG_DLSCH_DECODING +#include "common/utils/nr/nr_common.h" + //#define ENABLE_PHY_PAYLOAD_DEBUG 1 +#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 //#define OAI_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX static uint64_t nb_total_decod =0; @@ -56,11 +57,29 @@ notifiedFIFO_t freeBlocks_dl; notifiedFIFO_elt_t *msgToPush_dl; int nbDlProcessing =0; + +static tpool_t pool_dl; //extern double cpuf; -void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) -{ +void init_dlsch_tpool(uint8_t num_dlsch_threads) { + char *params = NULL; + if( num_dlsch_threads==0) { + params = calloc(1,2); + memcpy(params,"N",1); + } + else { + params = calloc(1,(num_dlsch_threads*3)+1); + for (int i=0; iMdlharq; i++) { if (dlsch->harq_processes[i]) { @@ -89,7 +107,7 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) free16(dlsch->harq_processes[i]->d[r],(5*8448)*sizeof(short)); dlsch->harq_processes[i]->d[r] = NULL; } - + for (r=0; rharq_processes[i]->w[r]) { free16(dlsch->harq_processes[i]->w[r],(5*8448)*sizeof(short)); @@ -97,7 +115,7 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) } for (r=0; rharq_processes[i]->p_nrLDPC_procBuf[r]){ + if (dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]) { nrLDPC_free_mem(dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]); dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = NULL; } @@ -107,27 +125,23 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) dlsch->harq_processes[i] = NULL; } } - + free16(dlsch,sizeof(NR_UE_DLSCH_t)); dlsch = NULL; } } -NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_ldpc_iterations,uint16_t N_RB_DL, uint8_t abstraction_flag) -{ - +NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_ldpc_iterations,uint16_t N_RB_DL, uint8_t abstraction_flag) { NR_UE_DLSCH_t *dlsch; uint8_t exit_flag = 0,i,r; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated if (N_RB_DL != 273) { a_segments = a_segments*N_RB_DL; a_segments = (a_segments/273)+1; - } + } uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment - dlsch = (NR_UE_DLSCH_t *)malloc16(sizeof(NR_UE_DLSCH_t)); if (dlsch) { @@ -138,16 +152,15 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint dlsch->Nsoft = Nsoft; dlsch->Mlimit = 4; dlsch->max_ldpc_iterations = max_ldpc_iterations; - + for (i=0; iharq_processes[i] = (NR_DL_UE_HARQ_t *)malloc16(sizeof(NR_DL_UE_HARQ_t)); if (dlsch->harq_processes[i]) { memset(dlsch->harq_processes[i],0,sizeof(NR_DL_UE_HARQ_t)); init_downlink_harq_status(dlsch->harq_processes[i]); - dlsch->harq_processes[i]->first_tx=1; - dlsch->harq_processes[i]->b = (uint8_t*)malloc16(dlsch_bytes); + dlsch->harq_processes[i]->first_rx=1; + dlsch->harq_processes[i]->b = (uint8_t *)malloc16(dlsch_bytes); if (dlsch->harq_processes[i]->b) memset(dlsch->harq_processes[i]->b,0,dlsch_bytes); @@ -155,23 +168,23 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint exit_flag=3; if (abstraction_flag == 0) { - for (r=0; rharq_processes[i]->p_nrLDPC_procBuf[r] = nrLDPC_init_mem(); - dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(1056); + dlsch->harq_processes[i]->c[r] = (uint8_t *)malloc16(1056); if (dlsch->harq_processes[i]->c[r]) memset(dlsch->harq_processes[i]->c[r],0,1056); else exit_flag=2; - dlsch->harq_processes[i]->d[r] = (short*)malloc16((5*8448)*sizeof(short)); + dlsch->harq_processes[i]->d[r] = (short *)malloc16((5*8448)*sizeof(short)); if (dlsch->harq_processes[i]->d[r]) memset(dlsch->harq_processes[i]->d[r],0,(5*8448)*sizeof(short)); else exit_flag=2; - dlsch->harq_processes[i]->w[r] = (short*)malloc16((5*8448)*sizeof(short)); + dlsch->harq_processes[i]->w[r] = (short *)malloc16((5*8448)*sizeof(short)); if (dlsch->harq_processes[i]->w[r]) memset(dlsch->harq_processes[i]->w[r],0,(5*8448)*sizeof(short)); @@ -188,21 +201,18 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint return(dlsch); } - printf("new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag); + LOG_D(PHY,"new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag); free_nr_ue_dlsch(&dlsch,N_RB_DL); - return(NULL); } -void nr_dlsch_unscrambling(int16_t* llr, - uint32_t size, - uint8_t q, - uint32_t Nid, - uint32_t n_RNTI) { - +void nr_dlsch_unscrambling(int16_t *llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI) { uint8_t reset; uint32_t x1, x2, s=0; - reset = 1; x2 = (n_RNTI<<15) + (q<<14) + Nid; @@ -211,177 +221,387 @@ void nr_dlsch_unscrambling(int16_t* llr, s = lte_gold_generic(&x1, &x2, reset); reset = 0; } + if (((s>>(i&0x1f))&1)==1) llr[i] = -llr[i]; } - } -uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, - short *dlsch_llr, - NR_DL_FRAME_PARMS *frame_parms, - NR_UE_DLSCH_t *dlsch, - NR_DL_UE_HARQ_t *harq_process, - uint32_t frame, - uint16_t nb_symb_sch, - uint8_t nr_tti_rx, - uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag) -{ +bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool last, notifiedFIFO_t *nf_p) { + ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) NotifiedFifoData(req); + NR_DL_UE_HARQ_t *harq_process = rdata->harq_process; + NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch; + int r = rdata->segment_r; -#if UE_TIMING_TRACE + bool decodeSuccess = (rdata->decodeIterations < (1+dlsch->max_ldpc_iterations)); + + if (decodeSuccess) { + memcpy(harq_process->b+rdata->offset, + harq_process->c[r], + rdata->Kr_bytes - (harq_process->F>>3) -((harq_process->C>1)?3:0)); + + } else { + if ( !last ) { + int nb=abortTpool(&(pool_dl), req->key); + nb+=abortNotifiedFIFO(nf_p, req->key); + LOG_D(PHY,"downlink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); + LOG_D(PHY, "DLSCH %d in error\n",rdata->dlsch_id); + last = true; + } + } + + // if all segments are done + if (last) { + if (decodeSuccess) { + //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n", + // phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round); + harq_process->status = SCH_IDLE; + harq_process->round = 0; + harq_process->ack = 1; + + //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d)\n", + // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); + + //if(is_crnti) { + // LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->round,harq_process->TBS); + //} + dlsch->last_iteration_cnt = rdata->decodeIterations; + LOG_D(PHY, "DLSCH received ok \n"); + } else { + //LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", + // phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); + harq_process->ack = 0; + harq_process->round++; + if (harq_process->round >= dlsch->Mlimit) { + harq_process->status = SCH_IDLE; + harq_process->round = 0; + phy_vars_ue->dl_stats[4]++; + } + + //if(is_crnti) { + // LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", + // phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mdlharq,harq_process->TBS); + //} + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; + LOG_D(PHY, "DLSCH received nok \n"); + } + return true; //stop + } + else + { + return false; //not last one + } +} + +void nr_processDLSegment(void* arg) { + ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) arg; + NR_UE_DLSCH_t *dlsch = rdata->dlsch; +#if UE_TIMING_TRACE //TBD + PHY_VARS_NR_UE *phy_vars_ue = rdata->phy_vars_ue; time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats; time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats; time_stats_t *dlsch_deinterleaving_stats=&phy_vars_ue->dlsch_deinterleaving_stats; #endif - uint32_t A,E; - uint32_t G; - uint32_t ret,offset; - int32_t no_iteration_ldpc, length_dec; - uint32_t r,r_offset=0,Kr=8424,Kr_bytes,K_bytes_F,err_flag=0; + NR_DL_UE_HARQ_t *harq_process= rdata->harq_process; + t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; + int length_dec; + int no_iteration_ldpc; + int Kr; + int Kr_bytes; + int K_bits_F; uint8_t crc_type; - int8_t llrProcBuf[NR_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); - t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params* p_decParams = &decParams; - t_nrLDPC_time_stats procTime; - t_nrLDPC_time_stats* p_procTime =&procTime ; - - if (!harq_process) { - printf("dlsch_decoding.c: NULL harq_process pointer\n"); - return(dlsch->max_ldpc_iterations + 1); - } - t_nrLDPC_procBuf** p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf; + int i; + int j; + int r = rdata->segment_r; + int A = rdata->A; + int E = rdata->E; + int Qm = rdata->Qm; + //int rv_index = rdata->rv_index; + int r_offset = rdata->r_offset; + uint8_t kc = rdata->Kc; + uint32_t Tbslbrm = rdata->Tbslbrm; + short* dlsch_llr = rdata->dlsch_llr; + rdata->decodeIterations = dlsch->max_ldpc_iterations + 1; + int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); - - int16_t z [68*384]; - int8_t l [68*384]; - //__m128i l; - //int16_t inv_d [68*384]; - uint8_t kc; - uint8_t Ilbrm = 0; - - uint32_t Tbslbrm;// = 950984; - uint16_t nb_rb;// = 30; - double Coderate;// = 0.0; - - uint8_t dmrs_Type = harq_process->dmrsConfigType; - AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); - uint8_t nb_re_dmrs; - if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) { - nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; - } - else { - nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; - } - uint16_t dmrs_length = get_num_dmrs(harq_process->dlDmrsSymbPos); - AssertFatal(dmrs_length == 1 || dmrs_length == 2,"Illegal dmrs_length %d\n",dmrs_length); - - uint32_t i,j; + int16_t z [68*384 + 16] __attribute__ ((aligned(16))); + int8_t l [68*384 + 16] __attribute__ ((aligned(16))); __m128i *pv = (__m128i*)&z; __m128i *pl = (__m128i*)&l; - - vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); + + uint8_t Ilbrm = 0; + + Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb" + Kr_bytes = Kr>>3; + K_bits_F = Kr-harq_process->F; + + t_nrLDPC_time_stats procTime = {0}; + t_nrLDPC_time_stats* p_procTime = &procTime ; + + t_nrLDPC_procBuf **p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf; + +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_IN); + nr_deinterleaving_ldpc(E, + Qm, + harq_process->w[r], // [hna] w is e + dlsch_llr+r_offset); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif +#if UE_TIMING_TRACE + start_meas(dlsch_rate_unmatching_stats); +#endif + /* LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,E %d, F %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", + harq_pid,r, G,E,harq_process->F, + Kr*3, + harq_process->TBS, + Qm, + harq_process->nb_rb, + harq_process->Nl, + harq_process->rvidx, + harq_process->round); */ + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_IN); + + if (nr_rate_matching_ldpc_rx(Ilbrm, + Tbslbrm, + p_decoderParms->BG, + p_decoderParms->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->first_rx==1)?1:0, + E, + harq_process->F, + Kr-harq_process->F-2*(p_decoderParms->Z))==-1) { + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_OUT); +#if UE_TIMING_TRACE + stop_meas(dlsch_rate_unmatching_stats); +#endif + LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); + rdata->decodeIterations = dlsch->max_ldpc_iterations + 1; + return; + } else { +#if UE_TIMING_TRACE + stop_meas(dlsch_rate_unmatching_stats); +#endif + } + + r_offset += E; + + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) { + LOG_I(PHY,"decoder input(segment %u) :",r); + + for (int i=0; id[r][i]); + + LOG_D(PHY,"\n"); + } + + memset(harq_process->c[r],0,Kr_bytes); + + if (harq_process->C == 1) { + if (A > NR_MAX_PDSCH_TBS) + crc_type = CRC24_A; + else + crc_type = CRC16; + + length_dec = harq_process->B; + } else { + crc_type = CRC24_B; + length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; + } + + { +#if UE_TIMING_TRACE + start_meas(dlsch_turbo_decoding_stats); +#endif + //set first 2*Z_c bits to zeros + memset(&z[0],0,2*harq_process->Z*sizeof(int16_t)); + //set Filler bits + memset((&z[0]+K_bits_F),127,harq_process->F*sizeof(int16_t)); + //Move coded bits before filler bits + memcpy((&z[0]+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t)); + //skip filler bits + memcpy((&z[0]+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t)); + + //Saturate coded bits before decoding into 8 bits values + for (i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) { + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); + } + + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN); + p_decoderParms->block_length=length_dec; + nrLDPC_initcall(p_decoderParms, (int8_t*)&pl[0], llrProcBuf); + no_iteration_ldpc = nrLDPC_decoder(p_decoderParms, + (int8_t *)&pl[0], + llrProcBuf, + p_nrLDPC_procBuf[r], + p_procTime); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT); + + // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int + if (check_crc((uint8_t *)llrProcBuf,length_dec,harq_process->F,crc_type)) { + LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); + + if (r==0) { + for (int i=0; i<10; i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t *)llrProcBuf)[i]); + } + + //Temporary hack + no_iteration_ldpc = dlsch->max_ldpc_iterations; + rdata->decodeIterations = no_iteration_ldpc; + } else { + LOG_D(PHY,"CRC NOT OK\n\033[0m"); + } + + nb_total_decod++; + + if (no_iteration_ldpc > dlsch->max_ldpc_iterations) { + nb_error_decod++; + } + + for (int m=0; m < Kr>>3; m ++) { + harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; + } + +#if UE_TIMING_TRACE + stop_meas(dlsch_turbo_decoding_stats); +#endif + } +} + +uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, + UE_nr_rxtx_proc_t *proc, + int eNB_id, + short *dlsch_llr, + NR_DL_FRAME_PARMS *frame_parms, + NR_UE_DLSCH_t *dlsch, + NR_DL_UE_HARQ_t *harq_process, + uint32_t frame, + uint16_t nb_symb_sch, + uint8_t nr_slot_rx, + uint8_t harq_pid, + uint8_t is_crnti, + uint8_t llr8_flag) { + uint32_t A,E; + uint32_t G; + uint32_t ret,offset; + uint32_t r,r_offset=0,Kr=8424,Kr_bytes; + t_nrLDPC_dec_params decParams; + t_nrLDPC_dec_params *p_decParams = &decParams; + + if (!harq_process) { + LOG_E(PHY,"dlsch_decoding.c: NULL harq_process pointer\n"); + return(dlsch->max_ldpc_iterations + 1); + } + + // HARQ stats + phy_vars_ue->dl_stats[harq_process->round]++; + uint8_t kc; + uint32_t Tbslbrm;// = 950984; + uint16_t nb_rb;// = 30; + double Coderate;// = 0.0; + uint8_t dmrs_Type = harq_process->dmrsConfigType; + AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); + uint8_t nb_re_dmrs; + + if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; + } else { + nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; + } + + uint16_t dmrs_length = get_num_dmrs(harq_process->dlDmrsSymbPos); + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); //NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[0]; - + + int nbDecode = 0; + if (!dlsch_llr) { - printf("dlsch_decoding.c: NULL dlsch_llr pointer\n"); + LOG_E(PHY,"dlsch_decoding.c: NULL dlsch_llr pointer\n"); return(dlsch->max_ldpc_iterations + 1); } if (!frame_parms) { - printf("dlsch_decoding.c: NULL frame_parms pointer\n"); + LOG_E(PHY,"dlsch_decoding.c: NULL frame_parms pointer\n"); return(dlsch->max_ldpc_iterations + 1); } - /*if (nr_tti_rx> (10*frame_parms->ttis_per_subframe-1)) { - printf("dlsch_decoding.c: Illegal subframe index %d\n",nr_tti_rx); + /*if (nr_slot_rx> (frame_parms->slots_per_frame-1)) { + printf("dlsch_decoding.c: Illegal slot index %d\n",nr_slot_rx); return(dlsch->max_ldpc_iterations + 1); }*/ - /*if (harq_process->harq_ack.ack != 2) { LOG_D(PHY, "[UE %d] DLSCH @ SF%d : ACK bit is %d instead of DTX even before PDSCH is decoded!\n", - phy_vars_ue->Mod_id, nr_tti_rx, harq_process->harq_ack.ack); + phy_vars_ue->Mod_id, nr_slot_rx, harq_process->harq_ack.ack); }*/ - // nb_rb = dlsch->nb_rb; - /* if (nb_rb > frame_parms->N_RB_DL) { printf("dlsch_decoding.c: Illegal nb_rb %d\n",nb_rb); return(max_ldpc_iterations + 1); }*/ - - /*harq_pid = dlsch->current_harq_pid[phy_vars_ue->current_thread_id[subframe]]; + /*harq_pid = dlsch->current_harq_pid[proc->thread_id]; if (harq_pid >= 8) { printf("dlsch_decoding.c: Illegal harq_pid %d\n",harq_pid); return(max_ldpc_iterations + 1); } */ - nb_rb = harq_process->nb_rb; - harq_process->trials[harq_process->round]++; - uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs - harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*dmrs_length, nb_rb_oh, 0, harq_process->Nl); - A = harq_process->TBS; ret = dlsch->max_ldpc_iterations + 1; dlsch->last_iteration_cnt = ret; - harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, dmrs_length, harq_process->Qm,harq_process->Nl); G = harq_process->G; - LOG_D(PHY,"DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,A/8,G, nb_re_dmrs,harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); + LOG_D(PHY,"%d.%d DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n", + frame,nr_slot_rx,harq_pid,A,A/8,G, nb_re_dmrs, dmrs_length, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); if ((harq_process->R)<1024) Coderate = (float) (harq_process->R) /(float) 1024; else Coderate = (float) (harq_process->R) /(float) 2048; - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) - { + if ((A <=292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { p_decParams->BG = 2; - if (Coderate < 0.3333){ + kc = 52; + + if (Coderate < 0.3333) { p_decParams->R = 15; - kc = 52; - } - else if (Coderate <0.6667){ + } else if (Coderate <0.6667) { p_decParams->R = 13; - kc = 32; - } - else { + } else { p_decParams->R = 23; - kc = 17; } - } - else{ + } else { p_decParams->BG = 1; - if (Coderate < 0.6667){ + kc = 68; + + if (Coderate < 0.6667) { p_decParams->R = 13; - kc = 68; - } - else if (Coderate <0.8889){ + } else if (Coderate <0.8889) { p_decParams->R = 23; - kc = 35; - } - else { + } else { p_decParams->R = 89; - kc = 27; } } - - if (harq_process->round == 0) { + if (harq_process->first_rx == 1) { // This is a new packet, so compute quantities regarding segmentation - if (A > 3824) - harq_process->B = A+24; - else - harq_process->B = A+16; + if (A > NR_MAX_PDSCH_TBS) + harq_process->B = A+24; + else + harq_process->B = A+16; nr_segmentation(NULL, NULL, @@ -392,1423 +612,87 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, &harq_process->F, p_decParams->BG); -#ifdef DEBUG_DLSCH_DECODING - if (!frame%100) - printf("K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl); -#endif + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!frame%100)) + LOG_I(PHY,"K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl); } + if ((harq_process->Nl)<4) + Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl); + else + Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); - p_decParams->Z = harq_process->Z; //printf("dlsch decoding nr segmentation Z %d\n", p_decParams->Z); - //printf("coderate %f kc %d \n", Coderate, kc); - p_decParams->numMaxIter = dlsch->max_ldpc_iterations; p_decParams->outMode= 0; - - err_flag = 0; r_offset = 0; - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated if (nb_rb != 273) { a_segments = a_segments*nb_rb; - a_segments = (a_segments + 272) / 273; - } + a_segments = a_segments/273 +1; + } if (harq_process->C > a_segments) { LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); return((1+dlsch->max_ldpc_iterations)); } -#ifdef DEBUG_DLSCH_DECODING - printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); -#endif + if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) + LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); opp_enabled=1; - Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb" Kr_bytes = Kr>>3; - - K_bytes_F = Kr_bytes-(harq_process->F>>3); - + offset = 0; + void (*nr_processDLSegment_ptr)(void*) = &nr_processDLSegment; + notifiedFIFO_t nf; + initNotifiedFIFO(&nf); for (r=0; rC; r++) { - //printf("start rx segment %d\n",r); E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + union ldpcReqUnion id = {.s={dlsch->rnti,frame,nr_slot_rx,0,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(ldpcDecode_ue_t), id.p, &nf, nr_processDLSegment_ptr); + ldpcDecode_ue_t * rdata=(ldpcDecode_ue_t *) NotifiedFifoData(req); -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_IN); - - - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->w[r], // [hna] w is e - dlsch_llr+r_offset); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_OUT); - - //for (int i =0; i<16; i++) - // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); - -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif - -#if UE_TIMING_TRACE - start_meas(dlsch_rate_unmatching_stats); -#endif - - LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,E %d, F %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", - harq_pid,r, G,E,harq_process->F, - Kr*3, - harq_process->TBS, - harq_process->Qm, - harq_process->nb_rb, - harq_process->Nl, - harq_process->rvidx, - harq_process->round); - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_IN); - - if ((harq_process->Nl)<4) - Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl,harq_process->C); - else - Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4,harq_process->C); - - - if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - harq_process->d[r], - harq_process->w[r], - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - E, - harq_process->F, - Kr-harq_process->F-2*(p_decParams->Z))==-1) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); -#endif - LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); - return(dlsch->max_ldpc_iterations + 1); - } else { - -#if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); -#endif - } - - - //for (int i =0; i<16; i++) - // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); - + rdata->phy_vars_ue = phy_vars_ue; + rdata->harq_process = harq_process; + rdata->decoderParms = decParams; + rdata->dlsch_llr = dlsch_llr; + rdata->Kc = kc; + rdata->harq_pid = harq_pid; + rdata->segment_r = r; + rdata->nbSegments = harq_process->C; + rdata->E = E; + rdata->A = A; + rdata->Qm = harq_process->Qm; + rdata->r_offset = r_offset; + rdata->Kr_bytes = Kr_bytes; + rdata->rv_index = harq_process->rvidx; + rdata->Tbslbrm = Tbslbrm; + rdata->offset = offset; + rdata->dlsch = dlsch; + rdata->dlsch_id = 0; + pushTpool(&(pool_dl),req); + nbDecode++; + LOG_D(PHY,"Added a block to decode, in pipe: %d\n",nbDecode); r_offset += E; - -#ifdef DEBUG_DLSCH_DECODING - if (r==0) { - write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); - write_output("decoder_in.m","dec",&harq_process->d[0][0],E,1,0); - } - - printf("decoder input(segment %u) :",r); - int i; - for (i=0;id[r][i]); - printf("\n"); -#endif - - // printf("Clearing c, %p\n",harq_process->c[r]); - memset(harq_process->c[r],0,Kr_bytes); - - // printf("done\n"); - if (harq_process->C == 1){ - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - - } - else{ - crc_type = CRC24_B; - length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; - } - - if (err_flag == 0) { - -#if UE_TIMING_TRACE - start_meas(dlsch_turbo_decoding_stats); -#endif - - //LOG_E(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A); - - //printf("harq process dr iteration %d\n", p_decParams->numMaxIter); - - memset(pv,0,2*harq_process->Z*sizeof(int16_t)); - //memset(pl,0,2*p_decParams->Z*sizeof(int8_t)); - memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); - - - for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); - } - // Kbytes_F = Kr_bytes - F>>3 - j+=(harq_process->F>>3); - // for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) - for (i=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++,j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); - } - - for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) - { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN); - - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, - p_nrLDPC_procBuf[r], - p_procTime); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT); - - // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int - if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); - //Temporary hack - no_iteration_ldpc = dlsch->max_ldpc_iterations; - ret = no_iteration_ldpc; - } - else { - LOG_D(PHY,"CRC NOK\n\033[0m"); - ret = 1 + dlsch->max_ldpc_iterations; - } - - - nb_total_decod++; - if (no_iteration_ldpc > dlsch->max_ldpc_iterations){ - nb_error_decod++; - } - - //if (!nb_total_decod%10000){ - //printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout); - //} - //else - //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); - - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } - -#ifdef DEBUG_DLSCH_DECODING - //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - for (int k=0;k>3;k++) - printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); - printf("no_iterations_ldpc %d (ret %u)\n",no_iteration_ldpc,ret); - //write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4); -#endif - - -#if UE_TIMING_TRACE - stop_meas(dlsch_turbo_decoding_stats); -#endif - } - - - - /*printf("Segmentation: C %d r %d, dlsch_rate_unmatching_stats %5.3f dlsch_deinterleaving_stats %5.3f dlsch_turbo_decoding_stats %5.3f \n", - harq_process->C, - r, - dlsch_rate_unmatching_stats->p_time/(cpuf*1000.0), - dlsch_deinterleaving_stats->p_time/(cpuf*1000.0), - dlsch_turbo_decoding_stats->p_time/(cpuf*1000.0));*/ - - - if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; - LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1); - err_flag = 1; - } - } - - int32_t frame_rx_prev = frame; - int32_t tti_rx_prev = nr_tti_rx - 1; - if (tti_rx_prev < 0) { - frame_rx_prev--; - tti_rx_prev += 10*frame_parms->ttis_per_subframe; - } - frame_rx_prev = frame_rx_prev%1024; - - if (err_flag == 1) { -//#if UE_DEBUG_TRACE - LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", - phy_vars_ue->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); -//#endif - harq_process->harq_ack.ack = 0; - harq_process->harq_ack.harq_id = harq_pid; - harq_process->harq_ack.send_harq_status = 1; - harq_process->errors[harq_process->round]++; - // harq_process->round++; // [hna] uncomment this line when HARQ is implemented - - // printf("Rate: [UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); - if (harq_process->round >= dlsch->Mlimit) { - harq_process->status = SCH_IDLE; - harq_process->round = 0; - } - - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_tti_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", - phy_vars_ue->Mod_id,nr_tti_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mdlharq,harq_process->TBS); - } - - return((1 + dlsch->max_ldpc_iterations)); - } else { -//#if UE_DEBUG_TRACE - LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_tti_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n", - phy_vars_ue->Mod_id,nr_tti_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round); -//#endif - - harq_process->status = SCH_IDLE; - harq_process->round = 0; - harq_process->harq_ack.ack = 1; - harq_process->harq_ack.harq_id = harq_pid; - harq_process->harq_ack.send_harq_status = 1; - - //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d)\n", - // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); - - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_tti_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,nr_tti_rx,harq_pid,harq_process->round,harq_process->TBS); - } - //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); - - } - - // Reassembly of Transport block here - offset = 0; - Kr = harq_process->K; - Kr_bytes = Kr>>3; - - /* - printf("harq_pid %d\n",harq_pid); - printf("F %d, Fbytes %d\n",harq_process->F,harq_process->F>>3); - printf("C %d\n",harq_process->C); - */ - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_COMBINE_SEG, VCD_FUNCTION_IN); - - for (r=0; rC; r++) { - - memcpy(harq_process->b+offset, - harq_process->c[r], - Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0)); offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); - -#ifdef DEBUG_DLSCH_DECODING - printf("Segment %u : Kr= %u bytes\n",r,Kr_bytes); - printf("copied %d bytes to b sequence (harq_pid %d)\n", - (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); - printf("b[0] = %x,c[%d] = %x\n", - harq_process->b[offset], - harq_process->F>>3, - harq_process->c[r]); - - /*printf ("Printing payload bytes:"); - for (int i = 0; i < Kr_bytes; i++){ - printf("%d : %d \n", i, harq_process->b[i]); - }*/ -#endif - -#if defined(ENABLE_PHY_PAYLOAD_DEBUG) - if (frame%100 == 0){ - LOG_I (PHY, "Printing 10 first payload bytes at frame: %d ", frame); - for (int i = 0; i <10 ; i++){ //Kr_bytes - LOG_I(PHY, "[%d] : %x ", i, harq_process->b[i]); - } - } -#endif - + ////////////////////////////////////////////////////////////////////////////////////////// + } + for (r=0; rlast_iteration_cnt = ret; - + ret = dlsch->last_iteration_cnt; return(ret); } - -#ifdef UE_DLSCH_PARALLELISATION -uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, - UE_nr_rxtx_proc_t *proc, - int eNB_id, - short *dlsch_llr, - NR_DL_FRAME_PARMS *frame_parms, - NR_UE_DLSCH_t *dlsch, - NR_DL_UE_HARQ_t *harq_process, - uint32_t frame, - uint16_t nb_symb_sch, - uint8_t nr_tti_rx, - uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag) -{ - -#if UE_TIMING_TRACE - time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats; - time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats; - time_stats_t *dlsch_deinterleaving_stats=&phy_vars_ue->dlsch_deinterleaving_stats; -#endif - uint32_t A,E; - uint32_t G; - uint32_t ret,offset; - uint32_t r,r_offset=0,Kr=8424,Kr_bytes,err_flag=0,K_bytes_F; - uint8_t crc_type; - //UE_rxtx_proc_t *proc = &phy_vars_ue->proc; - int32_t no_iteration_ldpc,length_dec; - /*uint8_t C; - uint8_t Qm; - uint8_t r_thread; - uint32_t Er, Gp,GpmodC;*/ - t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params* p_decParams = &decParams; - t_nrLDPC_time_stats procTime; - t_nrLDPC_time_stats* p_procTime =&procTime ; - int8_t llrProcBuf[NR_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); - if (!harq_process) { - printf("dlsch_decoding.c: NULL harq_process pointer\n"); - return(dlsch->max_ldpc_iterations); - } - t_nrLDPC_procBuf* p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[0]; - uint8_t Nl=4; - int16_t z [68*384]; - int8_t l [68*384]; - //__m128i l; - //int16_t inv_d [68*384]; - //int16_t *p_invd =&inv_d; - uint8_t kb, kc; - uint8_t Ilbrm = 1; - uint32_t Tbslbrm = 950984; - uint16_t nb_rb = 30; - double Coderate = 0.0; - uint8_t dmrs_type = harq_process->dmrsConfigType; - //nfapi_nr_config_request_t *cfg = &phy_vars_ue->nrUE_config; - //uint8_t dmrs_type = cfg->pdsch_config.dmrs_type.value; - - uint8_t nb_re_dmrs; - if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) - nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; - else - nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; - - uint16_t length_dmrs = get_num_dmrs(dl_config_pdu->dlDmrsSymbPos); - - uint32_t i,j; -// int nbDlProcessing =0; - - __m128i *pv = (__m128i*)&z; - __m128i *pl = (__m128i*)&l; - notifiedFIFO_t nf; - initNotifiedFIFO(&nf); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); - - if (!dlsch_llr) { - printf("dlsch_decoding.c: NULL dlsch_llr pointer\n"); - return(dlsch->max_ldpc_iterations); - } - - - - if (!frame_parms) { - printf("dlsch_decoding.c: NULL frame_parms pointer\n"); - return(dlsch->max_ldpc_iterations); - } - - /* if (nr_tti_rx> (10*frame_parms->ttis_per_subframe-1)) { - printf("dlsch_decoding.c: Illegal subframe index %d\n",nr_tti_rx); - return(dlsch->max_ldpc_iterations); - } - - if (dlsch->harq_ack[nr_tti_rx].ack != 2) { - LOG_D(PHY, "[UE %d] DLSCH @ SF%d : ACK bit is %d instead of DTX even before PDSCH is decoded!\n", - phy_vars_ue->Mod_id, nr_tti_rx, dlsch->harq_ack[nr_tti_rx].ack); - }*/ - - /* - if (nb_rb > frame_parms->N_RB_DL) { - printf("dlsch_decoding.c: Illegal nb_rb %d\n",nb_rb); - return(max_ldpc_iterations); - }*/ - - /*harq_pid = dlsch->current_harq_pid[phy_vars_ue->current_thread_id[subframe]]; - if (harq_pid >= 8) { - printf("dlsch_decoding.c: Illegal harq_pid %d\n",harq_pid); - return(max_ldpc_iterations); - } - */ - - nb_rb = harq_process->nb_rb; - harq_process->trials[harq_process->round]++; - - uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs - - harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*length_dmrs, nb_rb_oh, 0, harq_process->Nl); - - A = harq_process->TBS; - - ret = dlsch->max_ldpc_iterations + 1; - dlsch->last_iteration_cnt = ret; - - harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq_process->Qm,harq_process->Nl); - - G = harq_process->G; - - LOG_D(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); - - proc->decoder_main_available = 1; - proc->decoder_thread_available = 0; - proc->decoder_thread_available1 = 0; - //get_G(frame_parms,nb_rb,dlsch->rb_alloc,mod_order,num_pdcch_symbols,phy_vars_ue->frame,subframe); - - // printf("DLSCH Decoding, harq_pid %d Ndi %d\n",harq_pid,harq_process->Ndi); - - if ((harq_process->R)<1024) - Coderate = (float) (harq_process->R) /(float) 1024; - else - Coderate = (float) (harq_process->R) /(float) 2048; - - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) - { - p_decParams->BG = 2; - if (Coderate < 0.3333){ - p_decParams->R = 15; - kc = 52; - } - else if (Coderate <0.6667){ - p_decParams->R = 13; - kc = 32; - } - else { - p_decParams->R = 23; - kc = 17; - } - } - else{ - p_decParams->BG = 1; - if (Coderate < 0.6667){ - p_decParams->R = 13; - kc = 68; - } - else if (Coderate <0.8889){ - p_decParams->R = 23; - kc = 35; - } - else { - p_decParams->R = 89; - kc = 27; - } - } - - if (harq_process->round == 0) { - // This is a new packet, so compute quantities regarding segmentation - if (A > 3824) - harq_process->B = A+24; - else - harq_process->B = A+16; - - nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - p_decParams->BG); - - - } - - p_decParams->Z = harq_process->Z; - - //printf("coderate %f kc %d \n", Coderate, kc); - p_decParams->numMaxIter = dlsch->max_ldpc_iterations; - p_decParams->outMode= 0; - - err_flag = 0; - r_offset = 0; - - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated - - if (nb_rb != 273) { - a_segments = a_segments*nb_rb; - a_segments = a_segments/273; - } - - if (harq_process->C > a_segments) { - LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); - return((1+dlsch->max_ldpc_iterations)); - } -#ifdef DEBUG_DLSCH_DECODING - printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); -#endif - - notifiedFIFO_elt_t *res_dl; - opp_enabled=1; - if (harq_process->C>1) { - for (int nb_seg =1 ; nb_segC; nb_seg++){ - if ( (res_dl=tryPullTpool(&nf, Tpool_dl)) != NULL ) { - pushNotifiedFIFO_nothreadSafe(&freeBlocks_dl,res_dl); - } - - AssertFatal((msgToPush_dl=pullNotifiedFIFO_nothreadSafe(&freeBlocks_dl)) != NULL,"chained list failure"); - nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(msgToPush_dl); - curMsg->UE=phy_vars_ue; - - nbDlProcessing++; - - - memset(&curMsg->proc, 0, sizeof(curMsg->proc)); - curMsg->proc.frame_rx = proc->frame_rx; - curMsg->proc.nr_tti_rx = proc->nr_tti_rx; - curMsg->proc.num_seg = nb_seg; - - curMsg->proc.eNB_id= eNB_id; - curMsg->proc.harq_pid=harq_pid; - curMsg->proc.llr8_flag = llr8_flag; - - msgToPush_dl->key= (nr_tti_rx%2) ? (nb_seg+30): nb_seg; - pushTpool(Tpool_dl, msgToPush_dl); - - /*Qm= harq_process->Qm; - Nl=harq_process->Nl; - r_thread = harq_process->C/2-1; - C= harq_process->C; - - Gp = G/Nl/Qm; - GpmodC = Gp%C; - - - if (r_thread < (C-(GpmodC))) - Er = Nl*Qm * (Gp/C); - else - Er = Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - printf("mthread Er %d\n", Er); - - printf("mthread instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td);*/ - } - //proc->decoder_main_available = 1; - } - - r = 0; - if (r==0) r_offset =0; - - Kr = harq_process->K; - Kr_bytes = Kr>>3; - K_bytes_F = Kr_bytes-(harq_process->F>>3); - - E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); - - /* - printf("Subblock deinterleaving, dlsch_llr %p, w %p\n", - dlsch_llr+r_offset, - &harq_process->w[r]); - */ -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->w[r], - dlsch_llr+r_offset); - -#ifdef DEBUG_DLSCH_DECODING - for (int i =0; i<16; i++) - printf("rx output deinterleaving w[%d]= %d r_offset %u\n", i,harq_process->w[r][i], r_offset); -#endif - -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif - -#if UE_TIMING_TRACE - start_meas(dlsch_rate_unmatching_stats); -#endif - -#ifdef DEBUG_DLSCH_DECODING - LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", - harq_pid,r, G, - Kr*3, - harq_process->TBS, - harq_process->Qm, - harq_process->nb_rb, - harq_process->Nl, - harq_process->rvidx, - harq_process->round); -#endif - - // for tbslbrm calculation according to 5.4.2.1 of 38.212 - if (harq_process->Nl < Nl) - Nl = harq_process->Nl; - - Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl,harq_process->C); - - if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - harq_process->d[r], - harq_process->w[r], - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - E, - harq_process->F, - Kr-harq_process->F-2*(p_decParams->Z))==-1) { -#if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); -#endif - LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); - return(dlsch->max_ldpc_iterations); - } else - { -#if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); -#endif - } - - //for (int i =0; i<16; i++) - // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); - - //r_offset += E; - //printf("main thread r_offset %d\n",r_offset); - -#ifdef DEBUG_DLSCH_DECODING - for (int i =0; i<16; i++) - printf("rx output ratematching d[%d]= %d r_offset %u\n", i,harq_process->d[r][i], r_offset); -#endif - -#ifdef DEBUG_DLSCH_DECODING - - if (r==0) { - write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); - write_output("decoder_in.m","dec",&harq_process->d[0][96],(3*8*Kr_bytes)+12,1,0); - } - - printf("decoder input(segment %u) :",r); - for (int i=0;i<(3*8*Kr_bytes);i++) - printf("%d : %d\n",i,harq_process->d[r][i]); - printf("\n"); -#endif - - - // printf("Clearing c, %p\n",harq_process->c[r]); - memset(harq_process->c[r],0,Kr_bytes); - - // printf("done\n"); - if (harq_process->C == 1){ - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } - else{ - crc_type = CRC24_B; - length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; - } - - //#ifndef __AVX2__ - - if (err_flag == 0) { -/* - LOG_D(PHY, "LDPC algo Kr=%d cb_cnt=%d C=%d nbRB=%d crc_type %d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d maxIter %d\n", - Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, - harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); -*/ - -#if UE_TIMING_TRACE - start_meas(dlsch_turbo_decoding_stats); -#endif - LOG_D(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1); - - /*for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ - inv_d[cnt] = (1)*harq_process->d[r][cnt]; - }*/ - - memset(pv,0,2*p_decParams->Z*sizeof(int16_t)); - //memset(pl,0,2*p_decParams->Z*sizeof(int8_t)); - memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); - - - for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); - } - - j+=(harq_process->F>>3); - // for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) - for (i=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++,j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); - } - - for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) - { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } - - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, - p_nrLDPC_procBuf, - p_procTime); - - nb_total_decod++; - if (no_iteration_ldpc > 10){ - nb_error_decod++; - ret = 1+dlsch->max_ldpc_iterations; - } - else { - ret=2; - } - - if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - printf("Segment %u CRC OK\n",r); - ret = 2; - } - else { - printf("CRC NOK\n"); - ret = 1+dlsch->max_ldpc_iterations; - } - - if (!nb_total_decod%10000){ - printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout); - } - - //else - //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); - - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } - - /*for (int u=0; u < Kr>>3; u ++) - { - ullrProcBuf[u]= (uint8_t) llrProcBuf[u]; - } - - - printf("output unsigned ullrProcBuf \n"); - - for (int j=0; j < Kr>>3; j ++) - { - printf(" %d \n", ullrProcBuf[j]); - } - printf(" \n");*/ - //printf("output channel decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - - //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); -#ifdef DEBUG_DLSCH_DECODING - for (int k=0;k<32;k++) - printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); -#endif - -#if UE_TIMING_TRACE - stop_meas(dlsch_turbo_decoding_stats); -#endif - } - - - if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; - LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1); - err_flag = 1; - } - //} //loop r - - int32_t frame_rx_prev = frame; - int32_t tti_rx_prev = nr_tti_rx - 1; - if (tti_rx_prev < 0) { - frame_rx_prev--; - tti_rx_prev += 10*frame_parms->ttis_per_subframe; - } - frame_rx_prev = frame_rx_prev%1024; - - if (err_flag == 1) { -#if UE_DEBUG_TRACE - LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", - phy_vars_ue->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); -#endif - harq_process->harq_ack.ack = 0; - harq_process->harq_ack.harq_id = harq_pid; - harq_process->harq_ack.send_harq_status = 1; - harq_process->errors[harq_process->round]++; - harq_process->round++; - - - // printf("Rate: [UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); - if (harq_process->round >= dlsch->Mlimit) { - harq_process->status = SCH_IDLE; - harq_process->round = 0; - } - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_tti_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", - phy_vars_ue->Mod_id,nr_tti_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mlimit,harq_process->TBS); - } - - return((1+dlsch->max_ldpc_iterations)); - } else { -#if UE_DEBUG_TRACE - LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_tti_rx %d TBS %d mcs %d nb_rb %d\n", - phy_vars_ue->Mod_id,nr_tti_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb); -#endif - - harq_process->status = SCH_IDLE; - harq_process->round = 0; - harq_process->harq_ack.ack = 1; - harq_process->harq_ack.harq_id = harq_pid; - harq_process->harq_ack.send_harq_status = 1; - //LOG_I(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d)\n", - // phy_vars_ue->Mod_id, frame, subframe, harq_pid, harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs); - - if(is_crnti) - { - LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_tti_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,nr_tti_rx,harq_pid,harq_process->round,harq_process->TBS); - } - //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); - - } - - // Reassembly of Transport block here - offset = 0; - - /* - printf("harq_pid %d\n",harq_pid); - printf("F %d, Fbytes %d\n",harq_process->F,harq_process->F>>3); - printf("C %d\n",harq_process->C); - */ - //uint32_t wait = 0; - - /* while((proc->decoder_thread_available == 0) ) - { - usleep(1); - } - proc->decoder_thread_available == 0;*/ - - /*notifiedFIFO_elt_t *res1=tryPullTpool(&nf, Tpool); - if (!res1) { - printf("mthread trypull null\n"); - usleep(1); - wait++; - }*/ - - //usleep(50); - - proc->decoder_main_available = 0; - Kr = harq_process->K; //to check if same K in all segments - Kr_bytes = Kr>>3; - - for (r=0; rC; r++) { - - memcpy(harq_process->b+offset, - harq_process->c[r], - Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0)); - offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); - -#ifdef DEBUG_DLSCH_DECODING - printf("Segment %u : Kr= %u bytes\n",r,Kr_bytes); - printf("copied %d bytes to b sequence (harq_pid %d)\n", - (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); - printf("b[0] = %x,c[%d] = %x\n", - harq_process->b[offset], - harq_process->F>>3, - harq_process->c[r]); -#endif - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); - - dlsch->last_iteration_cnt = ret; - //proc->decoder_thread_available = 0; - //proc->decoder_main_available = 0; - - return(ret); -} -#endif - -#ifdef UE_DLSCH_PARALLELISATION -void nr_dlsch_decoding_process(void *arg) -{ - nr_rxtx_thread_data_t *rxtxD= (nr_rxtx_thread_data_t *)arg; - UE_nr_rxtx_proc_t *proc = &rxtxD->proc; - PHY_VARS_NR_UE *phy_vars_ue = rxtxD->UE; - NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; - int llr8_flag1; - int32_t no_iteration_ldpc,length_dec; - t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params* p_decParams = &decParams; - t_nrLDPC_time_stats procTime; - t_nrLDPC_time_stats* p_procTime =&procTime ; - int8_t llrProcBuf[NR_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); - t_nrLDPC_procBuf* p_nrLDPC_procBuf; - int16_t z [68*384]; - int8_t l [68*384]; - //__m128i l; - //int16_t inv_d [68*384]; - //int16_t *p_invd =&inv_d; - uint8_t kb, kc; - uint8_t Ilbrm = 1; - uint32_t Tbslbrm = 950984; - uint16_t nb_rb = 30; //to update - double Coderate = 0.0; - uint16_t nb_symb_sch = 12; - uint8_t nb_re_dmrs = 6; - uint16_t length_dmrs = 1; - - uint32_t i,j; - uint32_t k; - - __m128i *pv = (__m128i*)&z; - __m128i *pl = (__m128i*)&l; - - proc->instance_cnt_dlsch_td=-1; - //proc->nr_tti_rx=proc->sub_frame_start; - - proc->decoder_thread_available = 1; - - -#if UE_TIMING_TRACE - time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats; - time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats; - time_stats_t *dlsch_deinterleaving_stats=&phy_vars_ue->dlsch_deinterleaving_stats; -#endif - uint32_t A,E; - uint32_t G; - uint32_t ret,offset; - uint32_t r,r_offset=0,Kr,Kr_bytes,err_flag=0,K_bytes_F; - uint8_t crc_type; - uint8_t C,Cprime; - uint8_t Qm; - uint8_t Nl; - //uint32_t Er; - - int eNB_id = proc->eNB_id; - int harq_pid = proc->harq_pid; - llr8_flag1 = proc->llr8_flag; - int frame = proc->frame_rx; - int slot = proc->nr_tti_rx; - r = proc->num_seg; - - NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[slot]][eNB_id][0]; - NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid]; - short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[slot]][eNB_id]->llr[0]; - //printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag); - p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[r]; - nb_symb_sch = harq_process->nb_symbols; - printf("dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_tti_rx, proc->num_seg, r, harq_process->nb_symbols); - - - /* - if (nb_rb > frame_parms->N_RB_DL) { - printf("dlsch_decoding.c: Illegal nb_rb %d\n",nb_rb); - return(max_ldpc_iterations); - }*/ - - /*harq_pid = dlsch->current_harq_pid[phy_vars_ue->current_thread_id[subframe]]; - if (harq_pid >= 8) { - printf("dlsch_decoding.c: Illegal harq_pid %d\n",harq_pid); - return(max_ldpc_iterations); - } - */ - - nb_rb = harq_process->nb_rb; - - harq_process->trials[harq_process->round]++; - - uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs - - harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*length_dmrs, nb_rb_oh, 0, harq_process->Nl); - - A = harq_process->TBS; //2072 for QPSK 1/3 - - - ret = dlsch->max_ldpc_iterations; - - harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq_process->Qm,harq_process->Nl); - G = harq_process->G; - - LOG_D(PHY,"DLSCH Decoding process, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); - - if ((harq_process->R)<1024) - Coderate = (float) (harq_process->R) /(float) 1024; - else - Coderate = (float) (harq_process->R) /(float) 2048; - - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) - { - p_decParams->BG = 2; - if (Coderate < 0.3333){ - p_decParams->R = 15; - kc = 52; - } - else if (Coderate <0.6667){ - p_decParams->R = 13; - kc = 32; - } - else { - p_decParams->R = 23; - kc = 17; - } - } - else{ - p_decParams->BG = 1; - if (Coderate < 0.6667){ - p_decParams->R = 13; - kc = 68; - } - else if (Coderate <0.8889){ - p_decParams->R = 23; - kc = 35; - } - else { - p_decParams->R = 89; - kc = 27; - } - } - - harq_process->round =0; - // if (harq_process->round == 0) { - // This is a new packet, so compute quantities regarding segmentation - if (A > 3824) - harq_process->B = A+24; - else - harq_process->B = A+16; - - nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - p_decParams->BG); - - p_decParams->Z = harq_process->Z; - - // } - - //printf("round %d Z %d K %d BG %d\n", harq_process->round, p_decParams->Z, harq_process->K, p_decParams->BG); - - - p_decParams->numMaxIter = dlsch->max_ldpc_iterations; - p_decParams->outMode= 0; - - /* - else { - printf("dlsch_decoding.c: Ndi>0 not checked yet!!\n"); - return(max_ldpc_iterations); - } - */ - err_flag = 0; - //r_offset = 0; - - /* - uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated - - if (nb_rb != 273) { - a_segments = a_segments*nb_rb; - a_segments = a_segments/273; - } - - if (harq_process->C > a_segments) { - LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); - return((1+dlsch->max_ldpc_iterations)); - }*/ -#ifdef DEBUG_DLSCH_DECODING - printf("Segmentation: C %d, Cminus %d, Kminus %d, Kplus %d\n",harq_process->C,harq_process->Cminus,harq_process->Kminus,harq_process->Kplus); -#endif - - opp_enabled=1; - - Qm= harq_process->Qm; - Nl=harq_process->Nl; - //r_thread = harq_process->C/2-1; - C= harq_process->C; - - Cprime = C; //assume CBGTI not present - - if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - r_offset = Nl*Qm*(G/(Nl*Qm*Cprime)); - else - r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - - // printf("thread0 r_offset %d\n",r_offset); - - //for (r=(harq_process->C/2); rC; r++) { - // r=1; //(harq_process->C/2); - - r_offset = r*r_offset; - - Kr = harq_process->K; - Kr_bytes = Kr>>3; - K_bytes_F = Kr_bytes-(harq_process->F>>3); - - E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); - -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->w[r], - dlsch_llr+r_offset); - -#ifdef DEBUG_DLSCH_DECODING - for (int i =0; i<16; i++) - printf("rx output thread 0 deinterleaving w[%d]= %d r_offset %u\n", i,harq_process->w[r][i], r_offset); -#endif - -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif - -#if UE_TIMING_TRACE - start_meas(dlsch_rate_unmatching_stats); -#endif - -#ifdef DEBUG_DLSCH_DECODING - LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", - harq_pid,r, G, - Kr*3, - harq_process->TBS, - harq_process->Qm, - harq_process->nb_rb, - harq_process->Nl, - harq_process->rvidx, - harq_process->round); -#endif - - if (Nl<4) - Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,Nl,harq_process->C); - else - Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4,harq_process->C); - - if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - harq_process->d[r], - harq_process->w[r], - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - E, - harq_process->F, - Kr-harq_process->F-2*(p_decParams->Z))==-1) { -#if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); -#endif - LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); - //return(dlsch->max_ldpc_iterations); - } else - { -#if UE_TIMING_TRACE - stop_meas(dlsch_rate_unmatching_stats); -#endif - } - - //for (int i =0; i<16; i++) - // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); - - //r_offset += E; - -#ifdef DEBUG_DLSCH_DECODING - if (r==0) { - write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); - write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); - } - - printf("decoder input(segment %u) :",r); - int i; for (i=0;i<(3*8*Kr_bytes)+12;i++) - printf("%d : %d\n",i,harq_process->d[r][i]); - printf("\n"); -#endif - - - // printf("Clearing c, %p\n",harq_process->c[r]); - memset(harq_process->c[r],0,Kr_bytes); - - if (harq_process->C == 1){ - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = harq_process->B; - } - else{ - crc_type = CRC24_B; - length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; - } - - if (err_flag == 0) { -/* - LOG_D(PHY, "turbo algo Kr=%d cb_cnt=%d C=%d nbRB=%d crc_type %d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d maxIter %d\n", - Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, - harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); -*/ - if (llr8_flag1) { - AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", - Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); - } -#if UE_TIMING_TRACE - start_meas(dlsch_turbo_decoding_stats); -#endif -// LOG_D(PHY,"AbsSubframe %d.%d Start turbo segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); -/* - for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ - inv_d[cnt] = (1)*harq_process->d[r][cnt]; - } -*/ - - memset(pv,0,2*p_decParams->Z*sizeof(int16_t)); - //memset(pl,0,2*p_decParams->Z*sizeof(int8_t)); - memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); - - for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); - } - - j+=(harq_process->F>>3); - // for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) - for (i=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++,j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); - } - - for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) - { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } - - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, - p_nrLDPC_procBuf, - p_procTime); - - // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int - if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_D(PHY,"Segment %u CRC OK\n",r); - ret = 2; - } - else { - LOG_D(PHY,"Segment %u CRC NOK\n",r); - ret = 1+dlsch->max_ldpc_iterations; - } - - if (no_iteration_ldpc > 10) - LOG_D(PHY,"Error number of iteration LPDC %d\n", no_iteration_ldpc); - //else - //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); - - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } - - /*for (int u=0; u < Kr>>3; u ++) - { - ullrProcBuf[u]= (uint8_t) llrProcBuf[u]; - } - - - printf("output unsigned ullrProcBuf \n"); - - for (int j=0; j < Kr>>3; j ++) - { - - printf(" %d \n", ullrProcBuf[j]); - - } - printf(" \n");*/ -#ifdef DEBUG_DLSCH_DECODING - for (int k=0;k<2;k++) - printf("segment 1 output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); -#endif - -#if UE_TIMING_TRACE - stop_meas(dlsch_turbo_decoding_stats); -#endif - } - - if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; -// LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); - err_flag = 1; - } - //} - - proc->decoder_thread_available = 1; - //proc->decoder_main_available = 0; -} - -void *dlsch_thread(void *arg) { - //this thread should be over the processing thread to keep in real time - PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; - notifiedFIFO_t nf; - initNotifiedFIFO(&nf); - notifiedFIFO_elt_t *res_dl; - initNotifiedFIFO_nothreadSafe(&freeBlocks_dl); - - for (int i=0; i= RX_NB_TH_DL) { - if ( (res=tryPullTpool(&nf, Tpool_dl)) != NULL ) { - nr_rxtx_thread_data_t *tmp=(nr_rxtx_thread_data_t *)res->msgData; - //nbDlProcessing--; - pushNotifiedFIFO_nothreadSafe(&freeBlocks_dl,res); - } - - usleep(200); - } - - res_dl=pullTpool(&nf, Tpool_dl); - nbDlProcessing--; - pushNotifiedFIFO_nothreadSafe(&freeBlocks_dl,res_dl); - - - //msgToPush->key=0; - //pushTpool(Tpool, msgToPush); - - } // while !oai_exit - - return NULL; -} - -#endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index ab3cf4ae90..0894ae9166 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -37,27 +37,23 @@ //#include "extern.h" #include "PHY/sse_intrin.h" #include "T.h" +#include "openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" - -#ifndef USER_MODE -#define NOCYGWIN_STATIC static -#else -#define NOCYGWIN_STATIC -#endif +#include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/NR_REFSIG/dmrs_nr.h" +#include "common/utils/nr/nr_common.h" /* dynamic shift for LLR computation for TM3/4 * set as command line argument, see lte-softmodem.c * default value: 0 */ -int16_t nr_dlsch_demod_shift = 0; +int32_t nr_dlsch_demod_shift = 0; //int16_t interf_unaw_shift = 13; //#define DEBUG_HARQ - -//#define DEBUG_PHY 1 -//#define DEBUG_DLSCH_DEMOD 1 - - +//#define DEBUG_PHY +//#define DEBUG_DLSCH_DEMOD +//#define DEBUG_PDSCH_RX // [MCS][i_mod (0,1,2) = (2,4,6)] //unsigned char offset_mumimo_llr_drange_fix=0; @@ -83,8 +79,8 @@ unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{ */ //unsigned char offset_mumimo_llr_drange[29][3]= {{0, 6, 5},{0, 4, 5},{0, 4, 5},{0, 5, 4},{0, 5, 6},{0, 5, 3},{0, 4, 4},{0, 4, 4},{0, 3, 3},{0, 1, 2},{1, 1, 0},{1, 3, 2},{3, 4, 1},{2, 0, 0},{2, 2, 2},{1, 1, 1},{2, 1, 0},{2, 1, 1},{1, 0, 1},{1, 0, 1},{0, 0, 0},{1, 0, 0},{0, 0, 0},{0, 1, 0},{1, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}}; - -extern void print_shorts(char *s,int16_t *x); +#define print_ints(s,x) printf("%s = %d %d %d %d\n",s,(x)[0],(x)[1],(x)[2],(x)[3]) +#define print_shorts(s,x) printf("%s = [%d+j*%d, %d+j*%d, %d+j*%d, %d+j*%d]\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7]) static void nr_dlsch_dual_stream_correlation_core(int **dl_ch_estimates_ext, int **dl_ch_estimates_ext_i, @@ -95,23 +91,61 @@ static void nr_dlsch_dual_stream_correlation_core(int **dl_ch_estimates_ext, int length, int start_point); +uint8_t nr_zero_forcing_rx_2layers(int **rxdataF_comp, + int **dl_ch_mag, + int **dl_ch_magb, + int **dl_ch_magr, + int **dl_ch_estimates_ext, + unsigned short nb_rb, + unsigned char n_rx, + unsigned char mod_order, + int shift, + unsigned char symbol, + int length); + static void nr_dlsch_layer_demapping(int16_t **llr_cw, uint8_t Nl, uint8_t mod_order, - uint16_t length, + uint32_t length, + int32_t codeword_TB0, + int32_t codeword_TB1, int16_t **llr_layers); + +/* compute LLR */ +static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, + NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp_ptr, + int32_t **dl_ch_mag_ptr, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq, + RX_type_t rx_type, + unsigned char harq_pid, + unsigned char gNB_id, + unsigned char gNB_id_i, + unsigned char first_symbol_flag, + unsigned char symbol, + unsigned short nb_rb, + unsigned short round, + int32_t codeword_TB0, + int32_t codeword_TB1, + uint32_t len, + uint8_t nr_slot_rx, + uint8_t beamforming_mode); + +/* Main Function */ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, - PDSCH_t type, - unsigned char eNB_id, - unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference - uint32_t frame, - uint8_t nr_tti_rx, - unsigned char symbol, - unsigned char first_symbol_flag, - RX_type_t rx_type, - unsigned char i_mod, - unsigned char harq_pid) + UE_nr_rxtx_proc_t *proc, + PDSCH_t type, + unsigned char gNB_id, + unsigned char gNB_id_i, + uint32_t frame, + uint8_t nr_slot_rx, + unsigned char symbol, + unsigned char first_symbol_flag, + RX_type_t rx_type, + unsigned char i_mod, + unsigned char harq_pid) { NR_UE_COMMON *common_vars = &ue->common_vars; @@ -120,13 +154,11 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, PHY_NR_MEASUREMENTS *measurements = &ue->measurements; NR_UE_DLSCH_t **dlsch; - int avg[4]; + int avg[16]; // int avg_0[2]; // int avg_1[2]; -#if UE_TIMING_TRACE uint8_t slot = 0; -#endif unsigned char aatx=0,aarx=0; @@ -144,55 +176,48 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //to be updated higher layer unsigned short start_rb = 0; unsigned short nb_rb_pdsch = 50; - int16_t *pllr_symbol_cw0; - int16_t *pllr_symbol_cw1; - int16_t *pllr_symbol_layer0; - int16_t *pllr_symbol_layer1; //int16_t *pllr_symbol_cw0_deint; //int16_t *pllr_symbol_cw1_deint; - uint32_t llr_offset_symbol; //uint16_t bundle_L = 2; - uint8_t pilots=0; uint16_t n_tx=1, n_rx=1; int32_t median[16]; uint32_t len; + uint16_t startSymbIdx=0; + uint16_t nbSymb=0; + uint16_t pduBitmap=0x0; switch (type) { case SI_PDSCH: - pdsch_vars = ue->pdsch_vars_SI; - dlsch = &ue->dlsch_SI[eNB_id]; + pdsch_vars = ue->pdsch_vars[proc->thread_id]; + dlsch = &ue->dlsch_SI[gNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; break; case RA_PDSCH: - pdsch_vars = ue->pdsch_vars_ra; - dlsch = &ue->dlsch_ra[eNB_id]; + pdsch_vars = ue->pdsch_vars[proc->thread_id]; + dlsch = &ue->dlsch_ra[gNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - // WIP TBR Hotfix - memcpy((void*)&pdsch_vars[eNB_id]->dl_ch_estimates[0][ue->frame_parms.ofdm_symbol_size*2], (void*)&ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_estimates[0][ue->frame_parms.ofdm_symbol_size*2], ue->frame_parms.ofdm_symbol_size*sizeof(int32_t)); - break; case PDSCH: - pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]]; - dlsch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id]; + pdsch_vars = ue->pdsch_vars[proc->thread_id]; + dlsch = ue->dlsch[proc->thread_id][gNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; dlsch1_harq = dlsch[1]->harq_processes[harq_pid]; - beamforming_mode = ue->transmission_mode[eNB_id] < 7 ? 0 :ue->transmission_mode[eNB_id]; + beamforming_mode = ue->transmission_mode[gNB_id] < 7 ? 0 :ue->transmission_mode[gNB_id]; break; default: - LOG_E(PHY, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); + LOG_E(PHY, "[UE][FATAL] nr_slot_rx %d: Unknown PDSCH format %d\n", nr_slot_rx, type); return -1; break; } - if (dlsch1_harq){ + if (dlsch0_harq && dlsch1_harq){ - //printf("status TB0 = %d, status TB1 = %d \n", dlsch[0]->harq_processes[harq_pid]->status, dlsch[1]->harq_processes[harq_pid]->status); - LOG_D(PHY,"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", frame, nr_tti_rx, symbol, harq_pid, dlsch0_harq->status, dlsch1_harq->status); + LOG_D(PHY,"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", frame, nr_slot_rx, symbol, harq_pid, dlsch0_harq->status, dlsch1_harq->status); if ((dlsch0_harq->status == ACTIVE) && (dlsch1_harq->status == ACTIVE)){ codeword_TB0 = dlsch0_harq->codeword; @@ -226,29 +251,32 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, return -1; } else { - LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx); + LOG_E(PHY,"[UE][FATAL] nr_slot_rx %d: no active DLSCH\n", nr_slot_rx); return(-1); } } else if (dlsch0_harq) { - if (dlsch0_harq->status == ACTIVE) + if (dlsch0_harq->status == ACTIVE) { codeword_TB0 = dlsch0_harq->codeword; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; #ifdef DEBUG_HARQ printf("[DEMOD] I am assuming only TB0 is active\n"); #endif + } else { + LOG_E(PHY,"[UE][FATAL] nr_slot_rx %d: no active DLSCH\n", nr_slot_rx); + return (-1); + } } else { - LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx); - return (-1); - } - - if (dlsch0_harq == NULL) { LOG_E(PHY, "Done\n"); return -1; } dlsch0_harq->Qm = nr_get_Qm_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table); dlsch0_harq->R = nr_get_code_rate_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table); + if (dlsch0_harq->Qm == 0 || dlsch0_harq->R == 0) { + LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n"); + return -1; + } #ifdef DEBUG_HARQ printf("[DEMOD] MIMO mode = %d\n", dlsch0_harq->mimo_mode); @@ -262,8 +290,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, round = dlsch0_harq->round; //printf("round = %d\n", round); - if (eNB_id > 2) { - LOG_W(PHY,"dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id); + if (gNB_id > 2) { + LOG_W(PHY, "In %s: Illegal gNB_id %d\n", __FUNCTION__, gNB_id); return(-1); } @@ -296,812 +324,387 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, DevAssert(dlsch1_harq); } -#if UE_TIMING_TRACE if(symbol > ue->frame_parms.symbols_per_slot>>1) { slot = 1; } -#endif #ifdef DEBUG_HARQ printf("Demod dlsch0_harq->pmi_alloc %d\n", dlsch0_harq->pmi_alloc); #endif - pilots = ((1<dlDmrsSymbPos)>0 ? 1 : 0; + uint8_t pilots = (dlsch0_harq->dlDmrsSymbPos >> symbol) & 1; + uint8_t config_type = dlsch0_harq->dmrsConfigType; - if (frame_parms->nb_antenna_ports_gNB>1 && beamforming_mode==0) { -#ifdef DEBUG_DLSCH_MOD - LOG_I(PHY,"dlsch: using pmi %x (%p)\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch[0]); -#endif - -#if UE_TIMING_TRACE - start_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); -#endif - nb_rb = nr_dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, - pdsch_vars[eNB_id]->dl_ch_estimates, - pdsch_vars[eNB_id]->rxdataF_ext, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - dlsch0_harq->pmi_alloc, - pdsch_vars[eNB_id]->pmi_ext, - symbol, - pilots, - start_rb, - nb_rb_pdsch, - nr_tti_rx, - ue->high_speed_flag, - frame_parms, - dlsch0_harq->mimo_mode); -#ifdef DEBUG_DLSCH_MOD - printf("dlsch: using pmi %lx, pmi_ext ",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc)); - for (rb=0;rbpmi_ext[rb]); - printf("\n"); -#endif - - if (rx_type >= rx_IC_single_stream) { - if (eNB_id_in_connected_eNB) // we are in TM5 - nb_rb = nr_dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, - pdsch_vars[eNB_id]->dl_ch_estimates, - pdsch_vars[eNB_id_i]->rxdataF_ext, - pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - dlsch0_harq->pmi_alloc, - pdsch_vars[eNB_id_i]->pmi_ext, - symbol, - pilots, - start_rb, - nb_rb_pdsch, - nr_tti_rx, - ue->high_speed_flag, - frame_parms, - dlsch0_harq->mimo_mode); - else - nb_rb = nr_dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, - pdsch_vars[eNB_id]->dl_ch_estimates, - pdsch_vars[eNB_id_i]->rxdataF_ext, - pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - dlsch0_harq->pmi_alloc, - pdsch_vars[eNB_id_i]->pmi_ext, - symbol, - pilots, - start_rb, - nb_rb_pdsch, - nr_tti_rx, - ue->high_speed_flag, - frame_parms, - dlsch0_harq->mimo_mode); - } - } else if (beamforming_mode==0) { //else if nb_antennas_ports_gNB==1 && beamforming_mode == 0 - //printf("start nr dlsch extract nr_tti_rx %d thread id %d \n", nr_tti_rx, ue->current_thread_id[nr_tti_rx]); - nb_rb = nr_dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, - pdsch_vars[eNB_id]->dl_ch_estimates, - pdsch_vars[eNB_id]->rxdataF_ext, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - dlsch0_harq->pmi_alloc, - pdsch_vars[eNB_id]->pmi_ext, - symbol, - pilots, - start_rb, - nb_rb_pdsch, - nr_tti_rx, - ue->high_speed_flag, - frame_parms); - - } /*else if(beamforming_mode>7) { + if (beamforming_mode==0) {//No beamforming + start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); + if (dlsch0_harq->Nl > 1)//More than or equal 2 layers + nb_rb = nr_dlsch_extract_rbs_multiple(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, + pdsch_vars[gNB_id]->dl_ch_estimates, + pdsch_vars[gNB_id]->rxdataF_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, + symbol, + pilots, + config_type, + start_rb + dlsch0_harq->BWPStart, + nb_rb_pdsch, + dlsch0_harq->n_dmrs_cdm_groups, + dlsch0_harq->Nl, + frame_parms, + dlsch0_harq->dlDmrsSymbPos); + else// one layer + nb_rb = nr_dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, + pdsch_vars[gNB_id]->dl_ch_estimates, + pdsch_vars[gNB_id]->rxdataF_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, + symbol, + pilots, + config_type, + start_rb + dlsch0_harq->BWPStart, + nb_rb_pdsch, + dlsch0_harq->n_dmrs_cdm_groups, + frame_parms, + dlsch0_harq->dlDmrsSymbPos); + } + else if(beamforming_mode>7) { LOG_W(PHY,"dlsch_demodulation: beamforming mode not supported yet.\n"); - }*/ - - //printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id); + } + + //printf("nb_rb = %d, gNB_id %d\n",nb_rb,gNB_id); if (nb_rb==0) { LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n"); return(-1); } - len = (pilots==1)? (nb_rb*6):(nb_rb*12); - -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); + len = (pilots==1)? ((config_type==NFAPI_NR_DMRS_TYPE1)?nb_rb*(12-6*dlsch0_harq->n_dmrs_cdm_groups): nb_rb*(12-4*dlsch0_harq->n_dmrs_cdm_groups)):(nb_rb*12); + + stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #if DISABLE_LOG_X - printf("[AbsSFN %u.%d] Slot%d Symbol %d Flag %d type %d: Pilot/Data extraction %5.2f \n", - frame,nr_tti_rx,slot,symbol,ue->high_speed_flag,type,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); + printf("[AbsSFN %u.%d] Slot%d Symbol %d type %d: Pilot/Data extraction %5.2f \n", + frame,nr_slot_rx,slot,symbol,type,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #else - LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d Flag %d type %d: Pilot/Data extraction %5.2f \n", - frame,nr_tti_rx,slot,symbol,ue->high_speed_flag,type,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); -#endif + LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d type %d: Pilot/Data extraction %5.2f \n", + frame,nr_slot_rx,slot,symbol,type,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #endif -#if UE_TIMING_TRACE - start_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); -#endif - n_tx = frame_parms->nb_antenna_ports_gNB; + start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); + n_tx = dlsch0_harq->Nl; n_rx = frame_parms->nb_antennas_rx; - nr_dlsch_scale_channel(pdsch_vars[eNB_id]->dl_ch_estimates_ext, - frame_parms, - dlsch, - symbol, - pilots, - nb_rb); + nr_dlsch_scale_channel(pdsch_vars[gNB_id]->dl_ch_estimates_ext, + frame_parms, + n_tx, + n_rx, + dlsch, + symbol, + pilots, + len, + nb_rb_pdsch); -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); + stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #if DISABLE_LOG_X - printf("[AbsSFN %u.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,nr_tti_rx,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); + printf("[AbsSFN %u.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #else - LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,nr_tti_rx,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); -#endif -#endif - -#if UE_TIMING_TRACE - start_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); + LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #endif + start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); if (first_symbol_flag==1) { if (beamforming_mode==0){ - if (dlsch0_harq->mimo_modedl_ch_estimates_ext, - frame_parms, - avg, - symbol, - len, - nb_rb); - avgs = 0; - for (aatx=0;aatxnb_antenna_ports_gNB;aatx++) - for (aarx=0;aarxnb_antennas_rx;aarx++) - avgs = cmax(avgs,avg[(aatx<<1)+aarx]); + nr_dlsch_channel_level(pdsch_vars[gNB_id]->dl_ch_estimates_ext, + frame_parms, + n_tx, + avg, + symbol, + len, + nb_rb_pdsch); + avgs = 0; + for (aatx=0;aatxnb_antennas_rx+aarx]); + avgs = cmax(avgs,avg[(aatx*frame_parms->nb_antennas_rx)+aarx]); + //LOG_I(PHY, "avgs Power per SC is %d\n", avgs); + median[(aatx*frame_parms->nb_antennas_rx)+aarx] = avg[(aatx*frame_parms->nb_antennas_rx)+aarx]; + } - pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+3; - } - else if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) - { - nr_dlsch_channel_level_median(pdsch_vars[eNB_id]->dl_ch_estimates_ext, - median, - n_tx, - n_rx, - 2*len,// subcarriers Re Im - 0); + if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { + nr_dlsch_channel_level_median(pdsch_vars[gNB_id]->dl_ch_estimates_ext, + median, + n_tx, + n_rx, + len, + symbol*nb_rb*12); - for (aatx = 0; aatx < n_tx; ++aatx) - { - for (aarx = 0; aarx < n_rx; ++aarx) - { - avgs = cmax(avgs, median[aatx*n_rx + aarx]); - } - } + for (aatx = 0; aatx < n_tx; aatx++) { + for (aarx = 0; aarx < n_rx; aarx++) { + avgs = cmax(avgs, median[aatx*n_rx + aarx]); + } + } + } - pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; // this might need to be tuned - - } + pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; + //LOG_I(PHY, "avgs Power per SC is %d lg2_maxh %d\n", avgs, pdsch_vars[gNB_id]->log2_maxh); } - //#ifdef UE_DEBUG_TRACE LOG_D(PHY,"[DLSCH] AbsSubframe %d.%d log2_maxh = %d [log2_maxh0 %d log2_maxh1 %d] (%d,%d)\n", - frame%1024,nr_tti_rx, pdsch_vars[eNB_id]->log2_maxh, - pdsch_vars[eNB_id]->log2_maxh0, - pdsch_vars[eNB_id]->log2_maxh1, - avg[0],avgs); - //LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode); - //#endif - - //wait until pdcch is decoded - //proc->channel_level = 1; + frame%1024, + nr_slot_rx, + pdsch_vars[gNB_id]->log2_maxh, + pdsch_vars[gNB_id]->log2_maxh0, + pdsch_vars[gNB_id]->log2_maxh1, + avg[0], + avgs); } - /* - uint32_t wait = 0; - while(proc->channel_level == 0) - { - usleep(1); - wait++; - } - */ - #if T_TRACER if (type == PDSCH) { - T(T_UE_PHY_PDSCH_ENERGY, T_INT(eNB_id), T_INT(0), T_INT(frame%1024), T_INT(nr_tti_rx), + T(T_UE_PHY_PDSCH_ENERGY, T_INT(gNB_id), T_INT(0), T_INT(frame%1024), T_INT(nr_slot_rx), T_INT(avg[0]), T_INT(avg[1]), T_INT(avg[2]), T_INT(avg[3])); } #endif -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); + stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #if DISABLE_LOG_X - printf("[AbsSFN %u.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,nr_tti_rx,slot,symbol,first_symbol_flag,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); + printf("[AbsSFN %u.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,nr_slot_rx,slot,symbol,first_symbol_flag,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #else - LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,nr_tti_rx,slot,symbol,first_symbol_flag,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); -#endif + LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,nr_slot_rx,slot,symbol,first_symbol_flag,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #endif - -#if UE_TIMING_TRACE - start_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); -#endif + start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); // Now channel compensation if (dlsch0_harq->mimo_moderxdataF_ext, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->rxdataF_comp0, - (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, - frame_parms, - symbol, - pilots, - first_symbol_flag, - dlsch0_harq->Qm, - nb_rb, - pdsch_vars[eNB_id]->log2_maxh, - measurements); // log2_maxh+I0_shift - /*if (symbol == 5) { - write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); - } */ + nr_dlsch_channel_compensation(pdsch_vars[gNB_id]->rxdataF_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_magr0, + pdsch_vars[gNB_id]->rxdataF_comp0, + (n_tx>1) ? pdsch_vars[gNB_id]->rho : NULL, + frame_parms, + n_tx, + symbol, + len, + first_symbol_flag, + dlsch0_harq->Qm, + nb_rb_pdsch, + pdsch_vars[gNB_id]->log2_maxh, + measurements); // log2_maxh+I0_shift + } - /*if ((rx_type==rx_IC_single_stream) && - (eNB_id_in_connected_eNB)) { - nr_dlsch_channel_compensation(pdsch_vars[eNB_id_i]->rxdataF_ext, - pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - pdsch_vars[eNB_id_i]->dl_ch_mag0, - pdsch_vars[eNB_id_i]->dl_ch_magb0, - pdsch_vars[eNB_id_i]->rxdataF_comp0, - (aatx>1) ? pdsch_vars[eNB_id_i]->rho : NULL, - frame_parms, - symbol, - first_symbol_flag, - i_mod, - nb_rb, - pdsch_vars[eNB_id]->log2_maxh, - measurements); // log2_maxh+I0_shift -#ifdef DEBUG_PHY - if (symbol == 5) { - write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); - write_output("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); - } -#endif - - dlsch_dual_stream_correlation(frame_parms, - symbol, - nb_rb, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->log2_maxh); - }*/ + else if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { + nr_dlsch_channel_compensation_core(pdsch_vars[gNB_id]->rxdataF_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->rxdataF_comp0, //rxdataF_comp + NULL, + n_tx, + n_rx, + dlsch0_harq->Qm, + pdsch_vars[gNB_id]->log2_maxh, + 2*len, // subcarriers Re Im + 0); // we start from the beginning of the vector + // compute correlation between signal and interference channels (rho12 and rho21) + nr_dlsch_dual_stream_correlation_core(pdsch_vars[gNB_id]->dl_ch_estimates_ext, + &(pdsch_vars[gNB_id]->dl_ch_estimates_ext[2]), + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + n_tx, + n_rx, + pdsch_vars[gNB_id]->log2_maxh, + 2*len, + 0); } - else if (dlsch0_harq->mimo_mode == NR_DUALSTREAM){ - nr_dlsch_channel_compensation_core(pdsch_vars[eNB_id]->rxdataF_ext, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->rxdataF_comp0, //rxdataF_comp - NULL, - n_tx, - n_rx, - dlsch0_harq->Qm, - pdsch_vars[eNB_id]->log2_maxh, - 2*len, // subcarriers Re Im - 0); // we start from the beginning of the vector - /* if (symbol == 5) { - write_output("rxF_comp_d00.m","rxF_c_d00",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM - write_output("rxF_comp_d01.m","rxF_c_d01",&pdsch_vars[eNB_id]->rxdataF_comp0[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - write_output("rxF_comp_d10.m","rxF_c_d10",&pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - write_output("rxF_comp_d11.m","rxF_c_d11",&pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM - } */ - // compute correlation between signal and interference channels (rho12 and rho21) - nr_dlsch_dual_stream_correlation_core(pdsch_vars[eNB_id]->dl_ch_estimates_ext, - &(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - n_tx, - n_rx, - pdsch_vars[eNB_id]->log2_maxh, - 2*len, - 0); - //printf("rho stream1 =%d\n", &pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round] ); - nr_dlsch_dual_stream_correlation_core(&(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - n_tx, - n_rx, - pdsch_vars[eNB_id]->log2_maxh, - 2*len, - 0); - // printf("rho stream2 =%d\n",&pdsch_vars[eNB_id]->dl_ch_rho2_ext ); - //printf("TM3 log2_maxh : %d\n",pdsch_vars[eNB_id]->log2_maxh); - /* if (symbol == 5) { - write_output("rho0_0.m","rho0_0",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM - write_output("rho2_0.m","rho2_0",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - write_output("rho0_1.m.m","rho0_1",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - write_output("rho2_1.m","rho2_1",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM - } */ - - } - -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); + stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #if DISABLE_LOG_X - printf("[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n",frame,nr_tti_rx,slot,symbol,pdsch_vars[eNB_id]->log2_maxh,proc->channel_level,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); + printf("[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, pdsch_vars[gNB_id]->log2_maxh, proc->channel_level, ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #else - LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n",frame,nr_tti_rx,slot,symbol,pdsch_vars[eNB_id]->log2_maxh,proc->channel_level,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); -#endif -#endif -// MRC -#if UE_TIMING_TRACE - start_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); + LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, pdsch_vars[gNB_id]->log2_maxh, proc->channel_level, ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #endif + start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); - if (frame_parms->nb_antennas_rx > 1) { - if (dlsch0_harq->mimo_mode == NR_DUALSTREAM){ - nr_dlsch_detection_mrc_core(pdsch_vars[eNB_id]->rxdataF_comp0, - NULL, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - NULL, - NULL, - n_tx, + if (frame_parms->nb_antennas_rx > 1) { + if (dlsch0_harq->mimo_moderxdataF_comp0, + (n_tx>1)? pdsch_vars[gNB_id]->rho : NULL, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_magr0, + n_tx, + n_rx, + symbol, + nb_rb_pdsch, + len); + if (n_tx == 2)//Apply zero forcing for 2 Tx layers + nr_zero_forcing_rx_2layers(pdsch_vars[gNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_magr0, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, + nb_rb_pdsch, n_rx, - 2*len, - 0); - /* if (symbol == 5) { - write_output("rho0_mrc.m","rho0_0",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM - write_output("rho2_mrc.m","rho2_0",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - } */ + dlsch0_harq->Qm, + pdsch_vars[gNB_id]->log2_maxh, + symbol, + len); } + else if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { + nr_dlsch_detection_mrc_core(pdsch_vars[gNB_id]->rxdataF_comp0, + NULL, + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + NULL, + NULL, + n_tx, + n_rx, + 2*len, + 0); } - - //printf("start compute LLR\n"); + } + //printf("start compute LLR\n"); if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { - rxdataF_comp_ptr = pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round]; - dl_ch_mag_ptr = pdsch_vars[eNB_id]->dl_ch_mag1[harq_pid][round]; + rxdataF_comp_ptr = pdsch_vars[gNB_id]->rxdataF_comp1[harq_pid][round]; + dl_ch_mag_ptr = pdsch_vars[gNB_id]->dl_ch_mag1[harq_pid][round]; } else { - rxdataF_comp_ptr = pdsch_vars[eNB_id_i]->rxdataF_comp0; - dl_ch_mag_ptr = pdsch_vars[eNB_id_i]->dl_ch_mag0; + rxdataF_comp_ptr = pdsch_vars[gNB_id_i]->rxdataF_comp0; + dl_ch_mag_ptr = pdsch_vars[gNB_id_i]->dl_ch_mag0; //i_mod should have been passed as a parameter } -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); + stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #if DISABLE_LOG_X - printf("[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,nr_tti_rx,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); + printf("[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #else - LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,nr_tti_rx,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); -#endif + LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #endif + start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); + /* Store the valid DL RE's */ + pdsch_vars[gNB_id]->dl_valid_re[symbol-1] = len; -#if UE_TIMING_TRACE - - start_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); -#endif - //printf("LLR dlsch0_harq->Qm %d rx_type %d cw0 %d cw1 %d symbol %d \n",dlsch0_harq->Qm,rx_type,codeword_TB0,codeword_TB1,symbol); - // compute LLRs - // -> // compute @pointer where llrs should filled for this ofdm-symbol - - if (first_symbol_flag==1) pdsch_vars[eNB_id]->llr_offset[symbol-1] = 0; - llr_offset_symbol = pdsch_vars[eNB_id]->llr_offset[symbol-1]; - //pllr_symbol_cw0_deint = (int8_t*)pdsch_vars[eNB_id]->llr[0]; - //pllr_symbol_cw1_deint = (int8_t*)pdsch_vars[eNB_id]->llr[1]; - pllr_symbol_layer0 = pdsch_vars[eNB_id]->layer_llr[0]; - pllr_symbol_layer1 = pdsch_vars[eNB_id]->layer_llr[1]; - pllr_symbol_layer0 += llr_offset_symbol; - pllr_symbol_layer1 += llr_offset_symbol; - pllr_symbol_cw0 = pdsch_vars[eNB_id]->llr[0]; - pllr_symbol_cw1 = pdsch_vars[eNB_id]->llr[1]; - pllr_symbol_cw0 += llr_offset_symbol; - pllr_symbol_cw1 += llr_offset_symbol; - - pdsch_vars[eNB_id]->llr_offset[symbol] = len*dlsch0_harq->Qm + llr_offset_symbol; - - /*LOG_I(PHY,"compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %x @LLR Buff(symb) %x\n", - symbol, - nb_rb,dlsch0_harq->Qm, - pdsch_vars[eNB_id]->llr_length[symbol], - pdsch_vars[eNB_id]->llr_offset[symbol], - (int16_t*)pdsch_vars[eNB_id]->llr[0], - pllr_symbol_cw0);*/ - - /*printf("compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n", - symbol, - nb_rb,dlsch0_harq->Qm, - pdsch_vars[eNB_id]->llr_length[symbol], - pdsch_vars[eNB_id]->llr_offset[symbol], - pdsch_vars[eNB_id]->llr[0], - pllr_symbol_cw0);*/ - - switch (dlsch0_harq->Qm) { - case 2 : - if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { - nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw0, - symbol, - len, - first_symbol_flag, - nb_rb, - beamforming_mode); - - } else if (codeword_TB0 == -1){ - - nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw1, - symbol, - len, - first_symbol_flag, - nb_rb, - beamforming_mode); + if(dlsch0_harq->status == ACTIVE) { + startSymbIdx = dlsch0_harq->start_symbol; + nbSymb = dlsch0_harq->nb_symbols; + pduBitmap = dlsch0_harq->pduBitmap; } - else if (rx_type >= rx_IC_single_stream) { - if (dlsch1_harq->Qm == 2) { - nr_dlsch_qpsk_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_qpsk_qpsk_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else if (dlsch1_harq->Qm == 4) { - nr_dlsch_qpsk_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_16qam_qpsk_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } + if(dlsch1_harq) { + startSymbIdx = dlsch1_harq->start_symbol; + nbSymb = dlsch1_harq->nb_symbols; + pduBitmap = dlsch1_harq->pduBitmap; + } + + /* Check for PTRS bitmap and process it respectively */ + if((pduBitmap & 0x1) && (type == PDSCH)) { + nr_pdsch_ptrs_processing(ue, + pdsch_vars, + frame_parms, + dlsch0_harq, + dlsch1_harq, + gNB_id, + nr_slot_rx, + symbol, + (nb_rb*12), + dlsch[0]->rnti,rx_type); + pdsch_vars[gNB_id]->dl_valid_re[symbol-1] -= pdsch_vars[gNB_id]->ptrs_re_per_slot[0][symbol]; + } + + /* at last symbol in a slot calculate LLR's for whole slot */ + if(symbol == (startSymbIdx + nbSymb -1)) { + for(uint8_t i =startSymbIdx; i < (startSymbIdx+nbSymb);i++) { + /* re evaluating the first symbol flag as LLR's are done in symbol loop */ + if(i == startSymbIdx && i < 3) { + first_symbol_flag =1; } else { - nr_dlsch_qpsk_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_64qam_qpsk_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } + first_symbol_flag=0; } + /* Calculate LLR's for each symbol */ + nr_dlsch_llr(pdsch_vars, frame_parms, + rxdataF_comp_ptr, dl_ch_mag_ptr, + dlsch0_harq, dlsch1_harq, + rx_type, harq_pid, + gNB_id, gNB_id_i, + first_symbol_flag, + i, nb_rb, round, + codeword_TB0, codeword_TB1, + pdsch_vars[gNB_id]->dl_valid_re[i-1], + nr_slot_rx, beamforming_mode); } - break; - case 4 : - if ((rx_type==rx_standard ) || (codeword_TB1 == -1)) { - nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], - pdsch_vars[eNB_id]->dl_ch_mag0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128, - beamforming_mode); - } else if (codeword_TB0 == -1){ - nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[1], - pdsch_vars[eNB_id]->dl_ch_mag0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128_2ndstream, - beamforming_mode); - } - else if (rx_type >= rx_IC_single_stream) { - if (dlsch1_harq->Qm == 2) { - nr_dlsch_16qam_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_qpsk_16qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else if (dlsch1_harq->Qm == 4) { - nr_dlsch_16qam_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_16qam_16qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else { - nr_dlsch_16qam_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_64qam_16qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0, - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - } - break; - case 6 : - if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { - nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - (int16_t*)pllr_symbol_cw0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], - beamforming_mode); - } else if (codeword_TB0 == -1){ - nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw1, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], - beamforming_mode); - } - else if (rx_type >= rx_IC_single_stream) { - if (dlsch1_harq->Qm == 2) { - nr_dlsch_64qam_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_qpsk_64qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else if (dlsch1_harq->Qm == 4) { - nr_dlsch_64qam_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_16qam_64qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else { - nr_dlsch_64qam_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - (int16_t*)pllr_symbol_layer0, - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr_offset[symbol]); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_64qam_64qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pllr_symbol_layer1, - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_tti_rx,symbol), - pdsch_vars[eNB_id]->llr_offset[symbol]); - } - } - } - break; - default: - LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); - return(-1); - break; - } - if (dlsch1_harq) { - switch (nr_get_Qm_dl(dlsch1_harq->mcs,dlsch1_harq->mcs_table)) { - case 2 : - if (rx_type==rx_standard) { - nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw0, - symbol,len,first_symbol_flag,nb_rb, - beamforming_mode); - } - break; - case 4: - if (rx_type==rx_standard) { - nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], - pdsch_vars[eNB_id]->dl_ch_mag0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128, - beamforming_mode); - } - break; - case 6 : - if (rx_type==rx_standard) { - nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], - beamforming_mode); - } - break; - default: - LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); - return(-1); - break; + int dmrs_type = dlsch[0]->harq_processes[harq_pid]->dmrsConfigType; + uint8_t nb_re_dmrs; + uint16_t dmrs_len = get_num_dmrs(dlsch[0]->harq_processes[harq_pid]->dlDmrsSymbPos); + if (dmrs_type==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*dlsch[0]->harq_processes[harq_pid]->n_dmrs_cdm_groups; + } else { + nb_re_dmrs = 4*dlsch[0]->harq_processes[harq_pid]->n_dmrs_cdm_groups; + } + dlsch[0]->harq_processes[harq_pid]->G = nr_get_G(dlsch[0]->harq_processes[harq_pid]->nb_rb, + dlsch[0]->harq_processes[harq_pid]->nb_symbols, + nb_re_dmrs, + dmrs_len, + dlsch[0]->harq_processes[harq_pid]->Qm, + dlsch[0]->harq_processes[harq_pid]->Nl); + nr_dlsch_layer_demapping(pdsch_vars[gNB_id]->llr, + dlsch[0]->harq_processes[harq_pid]->Nl, + dlsch[0]->harq_processes[harq_pid]->Qm, + dlsch[0]->harq_processes[harq_pid]->G, + codeword_TB0, + codeword_TB1, + pdsch_vars[gNB_id]->layer_llr); + } - } - //nr_dlsch_deinterleaving(symbol,bundle_L,(int16_t*)pllr_symbol_cw0,(int16_t*)pllr_symbol_cw0_deint, nb_rb_pdsch); - - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr, - dlsch[0]->harq_processes[harq_pid]->Nl, - dlsch[0]->harq_processes[harq_pid]->Qm, - dlsch[0]->harq_processes[harq_pid]->G, - pdsch_vars[eNB_id]->layer_llr); - } - -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot]); + stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #if DISABLE_LOG_X - printf("[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,nr_tti_rx,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); + printf("[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #else - LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,nr_tti_rx,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); -#endif + LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,nr_slot_rx,slot,symbol,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #endif + // Please keep it: useful for debugging -#if 0 - if( (symbol == 13) && (nr_tti_rx==0) && (dlsch0_harq->Qm == 6) /*&& (nb_rb==25)*/) - { - LOG_E(PHY,"Dump Phy Chan Est \n"); - if(1) - { -#if 1 - write_output("rxdataF0.m" , "rxdataF0", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0][0],14*frame_parms->ofdm_symbol_size,1,1); - //write_output("rxdataF1.m" , "rxdataF1", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0][0],14*frame_parms->ofdm_symbol_size,1,1); - write_output("dl_ch_estimates00.m", "dl_ch_estimates00", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id][0][0],14*frame_parms->ofdm_symbol_size,1,1); - //write_output("dl_ch_estimates01.m", "dl_ch_estimates01", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id][1][0],14*frame_parms->ofdm_symbol_size,1,1); - //write_output("dl_ch_estimates10.m", "dl_ch_estimates10", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id][2][0],14*frame_parms->ofdm_symbol_size,1,1); - //write_output("dl_ch_estimates11.m", "dl_ch_estimates11", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id][3][0],14*frame_parms->ofdm_symbol_size,1,1); +#ifdef DEBUG_PDSCH_RX + char filename[40]; + uint8_t aa = 0; + snprintf(filename, 40, "rxdataF0_symb_%d_nr_slot_rx_%d.m", symbol, nr_slot_rx); + write_output(filename, "rxdataF0", &common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1); - //write_output("rxdataF_ext00.m" , "rxdataF_ext00", &pdsch_vars[eNB_id]->rxdataF_ext[0][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("rxdataF_ext01.m" , "rxdataF_ext01", &pdsch_vars[eNB_id]->rxdataF_ext[1][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("rxdataF_ext10.m" , "rxdataF_ext10", &pdsch_vars[eNB_id]->rxdataF_ext[2][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("rxdataF_ext11.m" , "rxdataF_ext11", &pdsch_vars[eNB_id]->rxdataF_ext[3][0],14*frame_parms->N_RB_DL*12,1,1); - write_output("dl_ch_estimates_ext00.m", "dl_ch_estimates_ext00", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[0][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("dl_ch_estimates_ext01.m", "dl_ch_estimates_ext01", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[1][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("dl_ch_estimates_ext10.m", "dl_ch_estimates_ext10", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[2][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("dl_ch_estimates_ext11.m", "dl_ch_estimates_ext11", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[3][0],14*frame_parms->N_RB_DL*12,1,1); - write_output("rxdataF_comp00.m","rxdataF_comp00", &pdsch_vars[eNB_id]->rxdataF_comp0[0][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("rxdataF_comp01.m","rxdataF_comp01", &pdsch_vars[eNB_id]->rxdataF_comp0[1][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("rxdataF_comp10.m","rxdataF_comp10", &pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][0][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("rxdataF_comp11.m","rxdataF_comp11", &pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][1][0],14*frame_parms->N_RB_DL*12,1,1); -#endif - write_output("llr0.m","llr0", &pdsch_vars[eNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); - //write_output("llr1.m","llr1", &pdsch_vars[eNB_id]->llr[1][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); + snprintf(filename, 40, "dl_ch_estimates0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx); + write_output(filename, "dl_ch_estimates", &pdsch_vars[gNB_id]->dl_ch_estimates[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1); + snprintf(filename, 40, "rxdataF_ext0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx); + write_output(filename, "rxdataF_ext", &pdsch_vars[gNB_id]->rxdataF_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); - AssertFatal(0," "); - } + snprintf(filename, 40, "dl_ch_estimates_ext0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx); + write_output(filename, "dl_ch_estimates_ext00", &pdsch_vars[gNB_id]->dl_ch_estimates_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); + snprintf(filename, 40, "rxdataF_comp0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx); + write_output(filename, "rxdataF_comp00", &pdsch_vars[gNB_id]->rxdataF_comp0[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); + + for (int i=0; i < 2; i++){ + snprintf(filename, 40, "llr%d_symb_%d_nr_slot_rx_%d.m", i, symbol, nr_slot_rx); + write_output(filename,"llr", &pdsch_vars[gNB_id]->llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm), 1, 0); } #endif #if T_TRACER - T(T_UE_PHY_PDSCH_IQ, T_INT(eNB_id), T_INT(ue->Mod_id), T_INT(frame%1024), - T_INT(nr_tti_rx), T_INT(nb_rb), + T(T_UE_PHY_PDSCH_IQ, T_INT(gNB_id), T_INT(ue->Mod_id), T_INT(frame%1024), + T_INT(nr_slot_rx), T_INT(nb_rb), T_INT(frame_parms->N_RB_UL), T_INT(frame_parms->symbols_per_slot), - T_BUFFER(&pdsch_vars[eNB_id]->rxdataF_comp0[eNB_id][0], - 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_slot*2)); + T_BUFFER(&pdsch_vars[gNB_id]->rxdataF_comp0[gNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_slot*2)); #endif return(0); } void nr_dlsch_deinterleaving(uint8_t symbol, - uint8_t start_symbol, - uint16_t L, - uint16_t *llr, - uint16_t *llr_deint, - uint16_t nb_rb_pdsch) + uint8_t start_symbol, + uint16_t L, + uint16_t *llr, + uint16_t *llr_deint, + uint16_t nb_rb_pdsch) { uint32_t bundle_idx, N_bundle, R, C, r,c; @@ -1151,11 +754,13 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, int **dl_ch_estimates_ext, int **dl_ch_mag, int **dl_ch_magb, + int **dl_ch_magr, int **rxdataF_comp, - int **rho, + int ***rho, NR_DL_FRAME_PARMS *frame_parms, + uint8_t nb_aatx, unsigned char symbol, - uint8_t pilots, + int length, uint8_t first_symbol_flag, unsigned char mod_order, unsigned short nb_rb, @@ -1166,32 +771,38 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, #if defined(__i386) || defined(__x86_64) unsigned short rb; - unsigned char aatx,aarx; - __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; - QAM_amp128b = _mm_setzero_si128(); + unsigned char aatx,aarx,atx; + __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*dl_ch_mag128r,*rxdataF128,*rxdataF_comp128,*rho128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128={0},QAM_amp128b={0},QAM_amp128r={0}; - for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { + uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); + for (aatx=0; aatxnb_antennas_rx; aarx++) { - dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*nb_rb*12]; - dl_ch_mag128 = (__m128i *)&dl_ch_mag[(aatx<<1)+aarx][symbol*nb_rb*12]; - dl_ch_mag128b = (__m128i *)&dl_ch_magb[(aatx<<1)+aarx][symbol*nb_rb*12]; + dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx*frame_parms->nb_antennas_rx)+aarx][symbol*nb_rb*12]; + dl_ch_mag128 = (__m128i *)&dl_ch_mag[(aatx*frame_parms->nb_antennas_rx)+aarx][symbol*nb_rb*12]; + dl_ch_mag128b = (__m128i *)&dl_ch_magb[(aatx*frame_parms->nb_antennas_rx)+aarx][symbol*nb_rb*12]; + dl_ch_mag128r = (__m128i *)&dl_ch_magr[(aatx*frame_parms->nb_antennas_rx)+aarx][symbol*nb_rb*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*nb_rb*12]; - rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*nb_rb*12]; + rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx*frame_parms->nb_antennas_rx)+aarx][symbol*nb_rb*12]; - - for (rb=0; rb2) { // get channel amplitude if not QPSK @@ -1201,45 +812,53 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, mmtmpD1 = _mm_madd_epi16(dl_ch128[1],dl_ch128[1]); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); + mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); //|H[0]|^2 |H[1]|^2 |H[2]|^2 |H[3]|^2 |H[4]|^2 |H[5]|^2 |H[6]|^2 |H[7]|^2 // store channel magnitude here in a new field of dlsch dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[0] = dl_ch_mag128[0]; + dl_ch_mag128r[0] = dl_ch_mag128[0]; dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); + + dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b); + dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1); + + dl_ch_mag128r[0] = _mm_mulhi_epi16(dl_ch_mag128r[0],QAM_amp128r); + dl_ch_mag128r[0] = _mm_slli_epi16(dl_ch_mag128r[0],1); + //print_ints("Re(ch):",(int16_t*)&mmtmpD0); //print_shorts("QAM_amp:",(int16_t*)&QAM_amp128); //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; + dl_ch_mag128r[1] = dl_ch_mag128[1]; dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1); - if (pilots==0) { - mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128[2]); - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); - - dl_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1); - dl_ch_mag128b[2] = dl_ch_mag128[2]; - - dl_ch_mag128[2] = _mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128); - dl_ch_mag128[2] = _mm_slli_epi16(dl_ch_mag128[2],1); - } - - dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b); - dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1); - - dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b); dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1); - if (pilots==0) { - dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); - dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1); - } + dl_ch_mag128r[1] = _mm_mulhi_epi16(dl_ch_mag128r[1],QAM_amp128r); + dl_ch_mag128r[1] = _mm_slli_epi16(dl_ch_mag128r[1],1); + + mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128[2]);//[H_I(0)^2+H_Q(0)^2 H_I(1)^2+H_Q(1)^2 H_I(2)^2+H_Q(2)^2 H_I(3)^2+H_Q(3)^2] + mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); + mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0);//[|H(0)|^2 |H(1)|^2 |H(2)|^2 |H(3)|^2 |H(0)|^2 |H(1)|^2 |H(2)|^2 |H(3)|^2] + + dl_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1);//[|H(0)|^2 |H(0)|^2 |H(1)|^2 |H(1)|^2 |H(2)|^2 |H(2)|^2 |H(3)|^2 |H(3)|^2] + dl_ch_mag128b[2] = dl_ch_mag128[2]; + dl_ch_mag128r[2] = dl_ch_mag128[2]; + + dl_ch_mag128[2] = _mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128); + dl_ch_mag128[2] = _mm_slli_epi16(dl_ch_mag128[2],1); + + dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); + dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1); + + dl_ch_mag128r[2] = _mm_mulhi_epi16(dl_ch_mag128r[2],QAM_amp128r); + dl_ch_mag128r[2] = _mm_slli_epi16(dl_ch_mag128r[2],1); } // multiply by conjugated channel @@ -1262,9 +881,16 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128); - // print_shorts("ch:",dl_ch128); - // print_shorts("pack:",rxdataF_comp128); + +#ifdef DEBUG_DLSCH_DEMOD + printf("%%arx%d atx%d rb_index %d symbol %d shift %d\n",aarx,aatx,rb,symbol,output_shift); + printf("rx_%d(%d,:)",aarx+1,rb+1); + print_shorts(" ",(int16_t *)&rxdataF128[0]); + printf("ch_%d%d(%d,:)",aarx+1,aatx+1,rb+1); + print_shorts(" ",(int16_t *)&dl_ch128[0]); + printf("rx_comp_%d%d(%d,:)",aarx+1,aatx+1,rb+1); + print_shorts(" ",(int16_t *)&rxdataF_comp128[0]); +#endif // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); @@ -1280,136 +906,166 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128+1); - // print_shorts("ch:",dl_ch128+1); - // print_shorts("pack:",rxdataF_comp128+1); - - if (pilots==0) { - // multiply by conjugated channel - mmtmpD0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); - // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) - mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); - mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); - mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); - // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) - mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); - mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); - mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); - mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); - - rxdataF_comp128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); - // print_shorts("rx:",rxdataF128+2); - // print_shorts("ch:",dl_ch128+2); - // print_shorts("pack:",rxdataF_comp128+2); - - dl_ch128+=3; - dl_ch_mag128+=3; - dl_ch_mag128b+=3; - rxdataF128+=3; - rxdataF_comp128+=3; - } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less - dl_ch128+=2; - dl_ch_mag128+=2; - dl_ch_mag128b+=2; - rxdataF128+=2; - rxdataF_comp128+=2; - } - - } - } - } - - if (rho) { - - - for (aarx=0; aarxnb_antennas_rx; aarx++) { - rho128 = (__m128i *)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; - dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; - dl_ch128_2 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; - - for (rb=0; rbrx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*nb_rb*12],rb*12); + dl_ch_mag128+=3; + dl_ch_mag128b+=3; + dl_ch_mag128r+=3; + rxdataF128+=3; + rxdataF_comp128+=3; } } } + if (rho) { + //we compute the Tx correlation matrix for each Rx antenna + //As an example the 2x2 MIMO case requires + //rho[aarx][nb_aatx*nb_aatx] = [cov(H_aarx_0,H_aarx_0) cov(H_aarx_0,H_aarx_1) + // cov(H_aarx_1,H_aarx_0) cov(H_aarx_1,H_aarx_1)], aarx=0,...,nb_antennas_rx-1 + int avg_rho_re[frame_parms->nb_antennas_rx][nb_aatx*nb_aatx]; + int avg_rho_im[frame_parms->nb_antennas_rx][nb_aatx*nb_aatx]; + + for (aarx=0; aarxnb_antennas_rx; aarx++) { + + for (aatx=0; aatxnb_antennas_rx+aarx][symbol*nb_rb*12]; + + for (atx=0; atxnb_antennas_rx+aarx][symbol*nb_rb*12]; + + for (rb=0; rbrx_correlation[0][0][aarx] = signal_energy(&rho[aarx][aatx*nb_aatx+atx][symbol*nb_rb*12],rb*12); + avg_rho_re[aarx][aatx*nb_aatx+atx] = 16*avg_rho_re[aarx][aatx*nb_aatx+atx]/(nb_rb*12); + avg_rho_im[aarx][aatx*nb_aatx+atx] = 16*avg_rho_im[aarx][aatx*nb_aatx+atx]/(nb_rb*12); + //printf("rho[rx]%d tx%d tx%d = Re: %d Im: %d\n",aarx, aatx,atx, avg_rho_re[aarx][aatx*nb_aatx+atx], avg_rho_im[aarx][aatx*nb_aatx+atx]); + } + } + } + } + } _mm_empty(); _m_empty(); #elif defined(__arm__) - unsigned short rb; - unsigned char aatx,aarx,symbol_mod,pilots=0; + unsigned char aatx,aarx,symbol_mod; int16x4_t *dl_ch128,*dl_ch128_2,*rxdataF128; int32x4_t mmtmpD0,mmtmpD1,mmtmpD0b,mmtmpD1b; @@ -1422,14 +1078,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; - if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { - if (frame_parms->nb_antenna_ports_gNB==1) { // 10 out of 12 so don't reduce size - nb_rb=1+(5*nb_rb/6); - } - else { - pilots=1; - } - } + uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { if (mod_order == 4) { @@ -1448,7 +1097,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (int16x4x2_t*)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; - for (rb=0; rb2) { // get channel amplitude if not QPSK mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128[0]); @@ -1464,23 +1113,20 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, mmtmpD1 = vmull_s16(dl_ch128[3], dl_ch128[3]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch128[4], dl_ch128[4]); - mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); - mmtmpD1 = vmull_s16(dl_ch128[5], dl_ch128[5]); - mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); - mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - } + + mmtmpD0 = vmull_s16(dl_ch128[4], dl_ch128[4]); + mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); + mmtmpD1 = vmull_s16(dl_ch128[5], dl_ch128[5]); + mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); + mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); dl_ch_mag128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128b); dl_ch_mag128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128b); dl_ch_mag128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128); dl_ch_mag128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128); - if (pilots==0) { - dl_ch_mag128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128b); - dl_ch_mag128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128); - } + dl_ch_mag128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128b); + dl_ch_mag128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128); } mmtmpD0 = vmull_s16(dl_ch128[0], rxdataF128[0]); @@ -1514,36 +1160,29 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[1] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - if (pilots==0) { - mmtmpD0 = vmull_s16(dl_ch128[4], rxdataF128[4]); - mmtmpD1 = vmull_s16(dl_ch128[5], rxdataF128[5]); - mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), - vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); - mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[4],*(int16x4_t*)conj)), rxdataF128[4]); - mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[5],*(int16x4_t*)conj)), rxdataF128[5]); - mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), - vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); + mmtmpD0 = vmull_s16(dl_ch128[4], rxdataF128[4]); + mmtmpD1 = vmull_s16(dl_ch128[5], rxdataF128[5]); + mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), + vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); + + mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[4],*(int16x4_t*)conj)), rxdataF128[4]); + mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[5],*(int16x4_t*)conj)), rxdataF128[5]); + mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), + vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); - mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); - mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); - rxdataF_comp128[2] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); + mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); + mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); + rxdataF_comp128[2] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); - dl_ch128+=6; - dl_ch_mag128+=3; - dl_ch_mag128b+=3; - rxdataF128+=6; - rxdataF_comp128+=3; + dl_ch128+=6; + dl_ch_mag128+=3; + dl_ch_mag128b+=3; + rxdataF128+=6; + rxdataF_comp128+=3; - } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less - dl_ch128+=4; - dl_ch_mag128+=2; - dl_ch_mag128b+=2; - rxdataF128+=4; - rxdataF_comp128+=2; - } } } } @@ -1553,7 +1192,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, rho128 = (int16x4x2_t*)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128 = (int16x4_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_2 = (int16x4_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; - for (rb=0; rb>1; - } + uint32_t nb_rb_0 = len/12 + ((len%12)?1:0); // Determine scaling amplitude based the symbol ch_amp = 1024*8; //((pilots) ? (dlsch_ue[0]->sqrt_rho_b) : (dlsch_ue[0]->sqrt_rho_a)); - LOG_D(PHY,"Scaling PDSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n",symbol,ch_amp,pilots,nb_rb,frame_parms->Ncp,symbol); - // printf("Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); + LOG_D(PHY,"Scaling PDSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n",symbol,ch_amp,pilots,nb_rb,frame_parms->Ncp,symbol); + // printf("Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); ch_amp128 = _mm_set1_epi16(ch_amp); // Q3.13 - for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { - for (aarx=0; aarxnb_antennas_rx; aarx++) { + for (aatx=0; aatx4) ? 4 : x; int16_t y = (len)>>x; //printf("len = %d = %d * 2^(%d)\n",len,y,x); + uint32_t nb_rb_0 = len/12 + ((len%12)?1:0); - for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) + AssertFatal(y!=0,"Cannot divide by zero: in function %s of file %s\n", __func__, __FILE__); + + for (aatx=0; aatxnb_antennas_rx; aarx++) { //clear average level avg128D = _mm_setzero_si128(); - // 5 is always a symbol with no pilots for both normal and extended prefix - dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*nb_rb*12]; + dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx*frame_parms->nb_antennas_rx)+aarx][symbol*nb_rb*12]; - for (rb=0;rbnb_antennas_rx)+aarx] =(((int32_t*)&avg128D)[0] + ((int32_t*)&avg128D)[1] + ((int32_t*)&avg128D)[2] + ((int32_t*)&avg128D)[3])/y; @@ -1924,7 +1562,7 @@ void nr_dlsch_channel_level(int **dl_ch_estimates_ext, int16x4_t *dl_ch128; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; - + uint32_t nb_rb_0 = len/12 + ((len%12)?1:0); for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) for (aarx=0; aarxnb_antennas_rx; aarx++) { //clear average level @@ -1933,7 +1571,7 @@ void nr_dlsch_channel_level(int **dl_ch_estimates_ext, dl_ch128=(int16x4_t *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; - for (rb=0; rb>2; + length2 = length>>2;//length = number of REs, hence length2=nb_REs*(32/128) in SIMD loop for (ii=0;ii max) - max = norm_pack; + max = norm_pack;//store values more than max if (norm_pack < min) - min = norm_pack; - + min = norm_pack;//store values less than min dl_ch128+=1; } - median[aatx*n_rx + aarx] = (max+min)>>1; - - // printf("Channel level median [%d]: %d\n",aatx*n_rx + aarx, median[aatx*n_rx + aarx]); + median[aatx*n_rx + aarx] = (max+min)>>1; + //printf("Channel level median [%d]: %d max = %d min = %d\n",aatx*n_rx + aarx, median[aatx*n_rx + aarx],max,min); } - } + } _mm_empty(); _m_empty(); @@ -2363,40 +1999,45 @@ void nr_dlsch_detection_mrc_core(int **rxdataF_comp, //============================================================================================== unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, - int **dl_ch_estimates, - int **rxdataF_ext, - int **dl_ch_estimates_ext, - unsigned short pmi, - unsigned char *pmi_ext, - unsigned char symbol, - uint8_t pilots, - unsigned short start_rb, - unsigned short nb_rb_pdsch, - unsigned char nr_tti_rx, - uint32_t high_speed_flag, - NR_DL_FRAME_PARMS *frame_parms) { - - + int **dl_ch_estimates, + int **rxdataF_ext, + int **dl_ch_estimates_ext, + unsigned char symbol, + uint8_t pilots, + uint8_t config_type, + unsigned short start_rb, + unsigned short nb_rb_pdsch, + uint8_t n_dmrs_cdm_groups, + NR_DL_FRAME_PARMS *frame_parms, + uint16_t dlDmrsSymbPos) +{ unsigned short k,rb; - unsigned char i,aarx; //,nsymb,sss_symb,pss_symb=0,l; + unsigned char nushift,i,aarx; int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; - + int8_t validDmrsEst = 0; //store last DMRS Symbol index unsigned char j=0; - AssertFatal(frame_parms->nushift ==0 || frame_parms->nushift == 1, - "nushift %d is illegal\n",frame_parms->nushift); + if (config_type==NFAPI_NR_DMRS_TYPE1) { + AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2, + "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); + nushift = n_dmrs_cdm_groups -1;//delta in Table 7.4.1.1.2-1 + + } else { + AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2 || n_dmrs_cdm_groups == 3, + "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); + nushift = (n_dmrs_cdm_groups -1)<<1;//delta in Table 7.4.1.1.2-2 + } for (aarx=0; aarxnb_antennas_rx; aarx++) { k = frame_parms->first_carrier_offset + NR_NB_SC_PER_RB*start_rb; - if (high_speed_flag == 1) - dl_ch0 = &dl_ch_estimates[aarx][(2*(frame_parms->ofdm_symbol_size))]; - else - dl_ch0 = &dl_ch_estimates[aarx][0]; + validDmrsEst = get_valid_dmrs_idx_for_channel_est(dlDmrsSymbPos,symbol); + + dl_ch0 = &dl_ch_estimates[aarx][(validDmrsEst*(frame_parms->ofdm_symbol_size))]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(nb_rb_pdsch*12)]; @@ -2404,149 +2045,927 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, rxF = &rxdataF[aarx][(k+(symbol*(frame_parms->ofdm_symbol_size)))]; for (rb = 0; rb < nb_rb_pdsch; rb++) { - if (k>frame_parms->ofdm_symbol_size) { + if (k>=frame_parms->ofdm_symbol_size) { k = k-frame_parms->ofdm_symbol_size; rxF = &rxdataF[aarx][(k+(symbol*(frame_parms->ofdm_symbol_size)))]; - } - if (pilots==0) { - memcpy((void*)rxF_ext,(void*)rxF,12*sizeof(*rxF_ext)); - memcpy((void*)dl_ch0_ext,(void*)dl_ch0,12*sizeof(*dl_ch0_ext)); - dl_ch0_ext+=12; - rxF_ext+=12; - } else { - j=0; - - for (i = (1-frame_parms->nushift); - i<12; - i+=2) { - rxF_ext[j]=rxF[i]; - dl_ch0_ext[j]=dl_ch0[i]; - j++; - } - - - dl_ch0_ext+=6; - rxF_ext+=6; } - + if (pilots==0) { + memcpy((void*)rxF_ext,(void*)rxF,12*sizeof(*rxF_ext)); + memcpy((void*)dl_ch0_ext,(void*)dl_ch0,12*sizeof(*dl_ch0_ext)); + dl_ch0_ext+=12; + rxF_ext+=12; + } else {//the symbol contains DMRS + j=0; + if (config_type==NFAPI_NR_DMRS_TYPE1){ + if (nushift == 0) {//data is multiplexed + for (i = (1-nushift); i<12; i+=2) { + rxF_ext[j]=rxF[i]; + dl_ch0_ext[j]=dl_ch0[i]; + j++; + } + dl_ch0_ext+=6; + rxF_ext+=6; + } + } else {//NFAPI_NR_DMRS_TYPE2 + for (i = (2+nushift); i<6; i++) { + rxF_ext[j]=rxF[i]; + dl_ch0_ext[j]=dl_ch0[i]; + j++; + } + for (i = (8+nushift); i<12; i++) { + rxF_ext[j]=rxF[i]; + dl_ch0_ext[j]=dl_ch0[i]; + j++; + } + dl_ch0_ext+= j; + rxF_ext+= j; + } + } + dl_ch0+=12; rxF+=12; k+=12; if (k>=frame_parms->ofdm_symbol_size) { - k=k-(frame_parms->ofdm_symbol_size); - rxF = &rxdataF[aarx][k+(symbol*(frame_parms->ofdm_symbol_size))]; + k = k-(frame_parms->ofdm_symbol_size); + rxF = &rxdataF[aarx][k+(symbol*(frame_parms->ofdm_symbol_size))]; } } } - - - return(nb_rb_pdsch/frame_parms->nb_antennas_rx); + return(nb_rb_pdsch); } -unsigned short nr_dlsch_extract_rbs_dual(int **rxdataF, - int **dl_ch_estimates, - int **rxdataF_ext, - int **dl_ch_estimates_ext, - unsigned short pmi, - unsigned char *pmi_ext, - unsigned char symbol, - uint8_t pilots, - unsigned short start_rb, - unsigned short nb_rb_pdsch, - unsigned char nr_tti_rx, - uint32_t high_speed_flag, - NR_DL_FRAME_PARMS *frame_parms, - MIMO_mode_t mimo_mode) { +unsigned short nr_dlsch_extract_rbs_multiple(int **rxdataF, + int **dl_ch_estimates, + int **rxdataF_ext, + int **dl_ch_estimates_ext, + unsigned char symbol, + uint8_t pilots, + uint8_t config_type, + unsigned short start_rb, + unsigned short nb_rb_pdsch, + uint8_t n_dmrs_cdm_groups, + uint8_t Nl, + NR_DL_FRAME_PARMS *frame_parms, + uint16_t dlDmrsSymbPos) +{ - int prb,nb_rb=0; - unsigned short k; - int i,j,aarx; - int32_t *dl_ch0=NULL,*dl_ch0_ext=NULL,*dl_ch1=NULL,*dl_ch1_ext=NULL,*rxF=NULL,*rxF_ext=NULL; + unsigned short k,rb; + unsigned char nushift,j,i,aarx,aatx; + int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; + int8_t validDmrsEst = 0; //store last DMRS Symbol index - k = frame_parms->first_carrier_offset + 516; //0 + if (config_type==NFAPI_NR_DMRS_TYPE1) { + AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2, + "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); + nushift = n_dmrs_cdm_groups -1;//delta in Table 7.4.1.1.2-1 + } else { + AssertFatal(n_dmrs_cdm_groups == 1 || n_dmrs_cdm_groups == 2 || n_dmrs_cdm_groups == 3, + "n_dmrs_cdm_groups %d is illegal\n",n_dmrs_cdm_groups); + nushift = (n_dmrs_cdm_groups -1)<<1;//delta in Table 7.4.1.1.2-2 + } + + validDmrsEst = get_valid_dmrs_idx_for_channel_est(dlDmrsSymbPos,symbol); for (aarx=0; aarxnb_antennas_rx; aarx++) { - if (high_speed_flag==1) { - dl_ch0 = &dl_ch_estimates[aarx][symbol*(frame_parms->ofdm_symbol_size)]; - dl_ch1 = &dl_ch_estimates[2+aarx][symbol*(frame_parms->ofdm_symbol_size)]; - } else { - dl_ch0 = &dl_ch_estimates[aarx][0]; - dl_ch1 = &dl_ch_estimates[2+aarx][0]; - } + k = frame_parms->first_carrier_offset + NR_NB_SC_PER_RB*start_rb; + if (k>=frame_parms->ofdm_symbol_size) + k = k-frame_parms->ofdm_symbol_size; - //pmi_loc = pmi_ext; + rxF_ext = &rxdataF_ext[aarx][symbol*(nb_rb_pdsch*12)]; + rxF = &rxdataF[aarx][(k+(symbol*(frame_parms->ofdm_symbol_size)))]; - // pointers to extracted RX signals and channel estimates - rxF_ext = &rxdataF_ext[aarx][symbol*(nb_rb_pdsch*12)]; - dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(nb_rb_pdsch*12)]; - dl_ch1_ext = &dl_ch_estimates_ext[2+aarx][symbol*(nb_rb_pdsch*12)]; + for (aatx=0; aatxN_RB_DL; prb++) { - //skip_half=0; + dl_ch0 = &dl_ch_estimates[(aatx*frame_parms->nb_antennas_rx)+aarx][(validDmrsEst*(frame_parms->ofdm_symbol_size))]; + dl_ch0_ext = &dl_ch_estimates_ext[(aatx*frame_parms->nb_antennas_rx)+aarx][symbol*(nb_rb_pdsch*NR_NB_SC_PER_RB)]; - if ((frame_parms->N_RB_DL&1) == 0) { // even number of RBs - - // For second half of RBs skip DC carrier - if (k>=frame_parms->ofdm_symbol_size) { - rxF = &rxdataF[aarx][(symbol*(frame_parms->ofdm_symbol_size))]; - k=k-(frame_parms->ofdm_symbol_size); + for (rb = 0; rb < nb_rb_pdsch; rb++) + { + if (pilots==0) {//data symbol only + if (aatx==0) {//Extract Rx signal only + memcpy((void*)rxF_ext,(void*)rxF,12*sizeof(*rxF_ext)); + rxF_ext+=12; + } + memcpy((void*)dl_ch0_ext,(void*)dl_ch0,12*sizeof(*dl_ch0_ext));//Extract Channel Estimate + dl_ch0_ext+=12; + } + else {//the symbol contains DMRS + j=0; + if (config_type==NFAPI_NR_DMRS_TYPE1) { + if (nushift == 0) {//data is multiplexed + for (i = (1-nushift); i<12; i+=2) { + if (aatx==0) rxF_ext[j]=rxF[i]; + dl_ch0_ext[j]=dl_ch0[i]; + j++; + } + dl_ch0_ext+=6; + if (aatx==0) rxF_ext+=6; + } + } + else {//NFAPI_NR_DMRS_TYPE2 + for (i = (2+nushift); i<6; i++) { + if (aatx==0) rxF_ext[j]=rxF[i]; + dl_ch0_ext[j]=dl_ch0[i]; + j++; + } + for (i = (8+nushift); i<12; i++) { + if (aatx==0) rxF_ext[j]=rxF[i]; + dl_ch0_ext[j]=dl_ch0[i]; + j++; + } + dl_ch0_ext+= j; + if (aatx==0) rxF_ext+= j; + } } - /* - if (mimo_mode <= PUSCH_PRECODING1) - *pmi_loc = (pmi>>((prb>>2)<<1))&3; - else - *pmi_loc=(pmi>>prb)&1;*/ - - // *pmi_loc = get_pmi(frame_parms->N_RB_DL,mimo_mode,pmi,prb); - // pmi_loc++; - - - if (pilots == 0) { - - memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); - memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int)); - memcpy(rxF_ext,rxF,12*sizeof(int)); - dl_ch0_ext +=12; - dl_ch1_ext +=12; - rxF_ext +=12; - } else { // pilots==1 - j=0; - for (i=0; i<12; i++) { - if ((i&1)!=frame_parms->nushift) { - rxF_ext[j]=rxF[i]; - // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); - dl_ch0_ext[j]=dl_ch0[i]; - dl_ch1_ext[j++]=dl_ch1[i]; - } - } - dl_ch0_ext+=6; - dl_ch1_ext+=6; - rxF_ext+=6; - } // pilots==1 - - dl_ch0+=12; - dl_ch1+=12; + dl_ch0+=12; + if (aatx==0) { rxF+=12; k+=12; - } - } // for prb - } // for aarx - return(nb_rb/frame_parms->nb_antennas_rx); + if (k>=frame_parms->ofdm_symbol_size) { + k=k-(frame_parms->ofdm_symbol_size); + rxF = &rxdataF[aarx][k+(symbol*(frame_parms->ofdm_symbol_size))]; + } + } + }//rb + }//aatx + }//aarx + return(nb_rb_pdsch); } +void nr_dlsch_detection_mrc(int **rxdataF_comp, + int ***rho, + int **dl_ch_mag, + int **dl_ch_magb, + int **dl_ch_magr, + short n_tx, + short n_rx, + unsigned char symbol, + unsigned short nb_rb, + int length) { +#if defined(__x86_64__)||defined(__i386__) + unsigned char aatx, aarx; + int i; + __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*dl_ch_mag128_0r,*dl_ch_mag128_1r; + + uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); + + if (n_rx>1) { + for (aatx=0; aatxN_RB_DL*12]; + rho128_1 = (__m128i *) &rho[1][symbol*frame_parms->N_RB_DL*12]; + for (i=0; i>2); + //printf("det_%d = %d log2 =%d \n",k,(((int *)&det[0])[k]),log2_approx(((int *)&det[0])[k])); + } + + xy_re_128 = _mm_slli_epi32(xy_re_128,5); + xy_re_128 = _mm_srai_epi32(xy_re_128,log2_approx(sum_det)); + xy_re_128 = _mm_slli_epi32(xy_re_128,5); + + xy_im_128 = _mm_slli_epi32(xy_im_128,5); + xy_im_128 = _mm_srai_epi32(xy_im_128,log2_approx(sum_det)); + xy_im_128 = _mm_slli_epi32(xy_im_128,5); + + tmp_z0 = _mm_unpacklo_epi32(xy_re_128,xy_im_128); + //print_ints("unpack lo:",&tmp_z0[0]); + tmp_z1 = _mm_unpackhi_epi32(xy_re_128,xy_im_128); + //print_ints("unpack hi:",&tmp_z1[0]); + output = _mm_packs_epi32(tmp_z0,tmp_z1); + + _mm_empty(); + _m_empty(); + return(output); +} +/* Zero Forcing Rx function: nr_construct_HhH_elements() + * + * + * */ +void nr_construct_HhH_elements(int *conjch00_ch00, + int *conjch01_ch01, + int *conjch11_ch11, + int *conjch10_ch10,// + int *conjch20_ch20, + int *conjch21_ch21, + int *conjch30_ch30, + int *conjch31_ch31, + int *conjch00_ch01,//00_01 + int *conjch01_ch00,//01_00 + int *conjch10_ch11,//10_11 + int *conjch11_ch10,//11_10 + int *conjch20_ch21, + int *conjch21_ch20, + int *conjch30_ch31, + int *conjch31_ch30, + int32_t *after_mf_00, + int32_t *after_mf_01, + int32_t *after_mf_10, + int32_t *after_mf_11, + unsigned short nb_rb, + unsigned char symbol) +{ + //This function is used to construct the (H_hermitian * H matrix) matrix elements + unsigned short rb; + __m128i *conjch00_ch00_128, *conjch01_ch01_128, *conjch11_ch11_128, *conjch10_ch10_128; + __m128i *conjch20_ch20_128, *conjch21_ch21_128, *conjch30_ch30_128, *conjch31_ch31_128; + __m128i *conjch00_ch01_128, *conjch01_ch00_128, *conjch10_ch11_128, *conjch11_ch10_128; + __m128i *conjch20_ch21_128, *conjch21_ch20_128, *conjch30_ch31_128, *conjch31_ch30_128; + __m128i *after_mf_00_128, *after_mf_01_128, *after_mf_10_128, *after_mf_11_128; + + conjch00_ch00_128 = (__m128i *)conjch00_ch00; + conjch01_ch01_128 = (__m128i *)conjch01_ch01; + conjch11_ch11_128 = (__m128i *)conjch11_ch11; + conjch10_ch10_128 = (__m128i *)conjch10_ch10; + + conjch20_ch20_128 = (__m128i *)conjch20_ch20; + conjch21_ch21_128 = (__m128i *)conjch21_ch21; + conjch30_ch30_128 = (__m128i *)conjch30_ch30; + conjch31_ch31_128 = (__m128i *)conjch31_ch31; + + conjch00_ch01_128 = (__m128i *)conjch00_ch01; + conjch01_ch00_128 = (__m128i *)conjch01_ch00; + conjch10_ch11_128 = (__m128i *)conjch10_ch11; + conjch11_ch10_128 = (__m128i *)conjch11_ch10; + + conjch20_ch21_128 = (__m128i *)conjch20_ch21; + conjch21_ch20_128 = (__m128i *)conjch21_ch20; + conjch30_ch31_128 = (__m128i *)conjch30_ch31; + conjch31_ch30_128 = (__m128i *)conjch31_ch30; + + after_mf_00_128 = (__m128i *)after_mf_00; + after_mf_01_128 = (__m128i *)after_mf_01; + after_mf_10_128 = (__m128i *)after_mf_10; + after_mf_11_128 = (__m128i *)after_mf_11; + + for (rb=0; rb<3*nb_rb; rb++) { + + after_mf_00_128[0] =_mm_adds_epi16(conjch00_ch00_128[0],conjch10_ch10_128[0]);//00_00 + 10_10 + if (conjch20_ch20 != NULL) after_mf_00_128[0] =_mm_adds_epi16(after_mf_00_128[0],conjch20_ch20_128[0]); + if (conjch30_ch30 != NULL) after_mf_00_128[0] =_mm_adds_epi16(after_mf_00_128[0],conjch30_ch30_128[0]); + + after_mf_11_128[0] =_mm_adds_epi16(conjch01_ch01_128[0], conjch11_ch11_128[0]); //01_01 + 11_11 + if (conjch21_ch21 != NULL) after_mf_11_128[0] =_mm_adds_epi16(after_mf_11_128[0],conjch21_ch21_128[0]); + if (conjch31_ch31 != NULL) after_mf_11_128[0] =_mm_adds_epi16(after_mf_11_128[0],conjch31_ch31_128[0]); + + after_mf_01_128[0] =_mm_adds_epi16(conjch00_ch01_128[0], conjch10_ch11_128[0]);//00_01 + 10_11 + if (conjch20_ch21 != NULL) after_mf_01_128[0] =_mm_adds_epi16(after_mf_01_128[0],conjch20_ch21_128[0]); + if (conjch30_ch31 != NULL) after_mf_01_128[0] =_mm_adds_epi16(after_mf_01_128[0],conjch30_ch31_128[0]); + + after_mf_10_128[0] =_mm_adds_epi16(conjch01_ch00_128[0], conjch11_ch10_128[0]);//01_00 + 11_10 + if (conjch21_ch20 != NULL) after_mf_10_128[0] =_mm_adds_epi16(after_mf_10_128[0],conjch21_ch20_128[0]); + if (conjch31_ch30 != NULL) after_mf_10_128[0] =_mm_adds_epi16(after_mf_10_128[0],conjch31_ch30_128[0]); + +#ifdef DEBUG_DLSCH_DEMOD + if ((rb<=30)) + { + printf(" \n construct_HhH_elements \n"); + print_shorts("after_mf_00_128:",(int16_t*)&after_mf_00_128[0]); + print_shorts("after_mf_01_128:",(int16_t*)&after_mf_01_128[0]); + print_shorts("after_mf_10_128:",(int16_t*)&after_mf_10_128[0]); + print_shorts("after_mf_11_128:",(int16_t*)&after_mf_11_128[0]); + } +#endif + conjch00_ch00_128+=1; + conjch10_ch10_128+=1; + conjch01_ch01_128+=1; + conjch11_ch11_128+=1; + + if (conjch20_ch20 != NULL) conjch20_ch20_128+=1; + if (conjch21_ch21 != NULL) conjch21_ch21_128+=1; + if (conjch30_ch30 != NULL) conjch30_ch30_128+=1; + if (conjch31_ch31 != NULL) conjch31_ch31_128+=1; + + conjch00_ch01_128+=1; + conjch01_ch00_128+=1; + conjch10_ch11_128+=1; + conjch11_ch10_128+=1; + + if (conjch20_ch21 != NULL) conjch20_ch21_128+=1; + if (conjch21_ch20 != NULL) conjch21_ch20_128+=1; + if (conjch30_ch31 != NULL) conjch30_ch31_128+=1; + if (conjch31_ch30 != NULL) conjch31_ch30_128+=1; + + after_mf_00_128 += 1; + after_mf_01_128 += 1; + after_mf_10_128 += 1; + after_mf_11_128 += 1; + } + _mm_empty(); + _m_empty(); +} + +/* Zero Forcing Rx function: nr_zero_forcing_rx_2layers() + * + * + * */ +uint8_t nr_zero_forcing_rx_2layers(int **rxdataF_comp, + int **dl_ch_mag, + int **dl_ch_magb, + int **dl_ch_magr, + int **dl_ch_estimates_ext, + unsigned short nb_rb, + unsigned char n_rx, + unsigned char mod_order, + int shift, + unsigned char symbol, + int length) +{ + int *ch00, *ch01, *ch10, *ch11; + int *ch20, *ch30, *ch21, *ch31; + uint32_t nb_rb_0 = length/12 + ((length%12)?1:0); + /* we need at least alignment to 16 bytes, let's put 32 to be sure + * (maybe not necessary but doesn't hurt) + */ + int32_t conjch00_ch01[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch01_ch00[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch10_ch11[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch11_ch10[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch00_ch00[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch01_ch01[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch10_ch10[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch11_ch11[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch20_ch20[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch21_ch21[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch30_ch30[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch31_ch31[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch20_ch21[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch30_ch31[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch21_ch20[12*nb_rb] __attribute__((aligned(32))); + int32_t conjch31_ch30[12*nb_rb] __attribute__((aligned(32))); + + int32_t af_mf_00[12*nb_rb] __attribute__((aligned(32))); + int32_t af_mf_01[12*nb_rb] __attribute__((aligned(32))); + int32_t af_mf_10[12*nb_rb] __attribute__((aligned(32))); + int32_t af_mf_11[12*nb_rb] __attribute__((aligned(32))); + int32_t determ_fin[12*nb_rb] __attribute__((aligned(32))); + + switch (n_rx) { + case 2:// + ch00 = (int *)&dl_ch_estimates_ext[0][symbol*nb_rb*12]; + ch01 = (int *)&dl_ch_estimates_ext[2][symbol*nb_rb*12]; + ch10 = (int *)&dl_ch_estimates_ext[1][symbol*nb_rb*12]; + ch11 = (int *)&dl_ch_estimates_ext[3][symbol*nb_rb*12]; + ch20 = NULL; + ch21 = NULL; + ch30 = NULL; + ch31 = NULL; + break; + + case 4:// + ch00 = (int *)&dl_ch_estimates_ext[0][symbol*nb_rb*12]; + ch01 = (int *)&dl_ch_estimates_ext[4][symbol*nb_rb*12]; + ch10 = (int *)&dl_ch_estimates_ext[1][symbol*nb_rb*12]; + ch11 = (int *)&dl_ch_estimates_ext[5][symbol*nb_rb*12]; + ch20 = (int *)&dl_ch_estimates_ext[2][symbol*nb_rb*12]; + ch21 = (int *)&dl_ch_estimates_ext[6][symbol*nb_rb*12]; + ch30 = (int *)&dl_ch_estimates_ext[3][symbol*nb_rb*12]; + ch31 = (int *)&dl_ch_estimates_ext[7][symbol*nb_rb*12]; + break; + + default: + return -1; + break; + } + + /* 1- Compute the rx channel matrix after compensation: (1/2^log2_max)x(H_herm x H) + * for n_rx = 2 + * |conj_H_00 conj_H_10| | H_00 H_01| |(conj_H_00xH_00+conj_H_10xH_10) (conj_H_00xH_01+conj_H_10xH_11)| + * | | x | | = | | + * |conj_H_01 conj_H_11| | H_10 H_11| |(conj_H_01xH_00+conj_H_11xH_10) (conj_H_01xH_01+conj_H_11xH_11)| + * + */ + + if (n_rx>=2){ + // (1/2^log2_maxh)*conj_H_00xH_00: (1/(64*2))conjH_00*H_00*2^15 + nr_conjch0_mult_ch1(ch00, + ch00, + conjch00_ch00, + nb_rb_0, + shift); + // (1/2^log2_maxh)*conj_H_10xH_10: (1/(64*2))conjH_10*H_10*2^15 + nr_conjch0_mult_ch1(ch10, + ch10, + conjch10_ch10, + nb_rb_0, + shift); + // conj_H_00xH_01 + nr_conjch0_mult_ch1(ch00, + ch01, + conjch00_ch01, + nb_rb_0, + shift); // this shift is equal to the channel level log2_maxh + // conj_H_10xH_11 + nr_conjch0_mult_ch1(ch10, + ch11, + conjch10_ch11, + nb_rb_0, + shift); + // conj_H_01xH_01 + nr_conjch0_mult_ch1(ch01, + ch01, + conjch01_ch01, + nb_rb_0, + shift); + // conj_H_11xH_11 + nr_conjch0_mult_ch1(ch11, + ch11, + conjch11_ch11, + nb_rb_0, + shift); + // conj_H_01xH_00 + nr_conjch0_mult_ch1(ch01, + ch00, + conjch01_ch00, + nb_rb_0, + shift); + // conj_H_11xH_10 + nr_conjch0_mult_ch1(ch11, + ch10, + conjch11_ch10, + nb_rb_0, + shift); + } + if (n_rx==4){ + // (1/2^log2_maxh)*conj_H_20xH_20: (1/(64*2*16))conjH_20*H_20*2^15 + nr_conjch0_mult_ch1(ch20, + ch20, + conjch20_ch20, + nb_rb_0, + shift); + + // (1/2^log2_maxh)*conj_H_30xH_30: (1/(64*2*4))conjH_30*H_30*2^15 + nr_conjch0_mult_ch1(ch30, + ch30, + conjch30_ch30, + nb_rb_0, + shift); + + // (1/2^log2_maxh)*conj_H_20xH_20: (1/(64*2))conjH_20*H_20*2^15 + nr_conjch0_mult_ch1(ch20, + ch21, + conjch20_ch21, + nb_rb_0, + shift); + + nr_conjch0_mult_ch1(ch30, + ch31, + conjch30_ch31, + nb_rb_0, + shift); + + nr_conjch0_mult_ch1(ch21, + ch21, + conjch21_ch21, + nb_rb_0, + shift); + + nr_conjch0_mult_ch1(ch31, + ch31, + conjch31_ch31, + nb_rb_0, + shift); + + // (1/2^log2_maxh)*conj_H_20xH_20: (1/(64*2))conjH_20*H_20*2^15 + nr_conjch0_mult_ch1(ch21, + ch20, + conjch21_ch20, + nb_rb_0, + shift); + + nr_conjch0_mult_ch1(ch31, + ch30, + conjch31_ch30, + nb_rb_0, + shift); + + nr_construct_HhH_elements(conjch00_ch00, + conjch01_ch01, + conjch11_ch11, + conjch10_ch10,// + conjch20_ch20, + conjch21_ch21, + conjch30_ch30, + conjch31_ch31, + conjch00_ch01, + conjch01_ch00, + conjch10_ch11, + conjch11_ch10,// + conjch20_ch21, + conjch21_ch20, + conjch30_ch31, + conjch31_ch30, + af_mf_00, + af_mf_01, + af_mf_10, + af_mf_11, + nb_rb_0, + symbol); + } + if (n_rx==2){ + nr_construct_HhH_elements(conjch00_ch00, + conjch01_ch01, + conjch11_ch11, + conjch10_ch10,// + NULL, + NULL, + NULL, + NULL, + conjch00_ch01, + conjch01_ch00, + conjch10_ch11, + conjch11_ch10,// + NULL, + NULL, + NULL, + NULL, + af_mf_00, + af_mf_01, + af_mf_10, + af_mf_11, + nb_rb_0, + symbol); + } + //det_HhH = ad -bc + nr_det_HhH(af_mf_00,//a + af_mf_01,//b + af_mf_10,//c + af_mf_11,//d + determ_fin, + nb_rb_0, + symbol, + shift); + /* 2- Compute the channel matrix inversion ********************************** + * + * |(conj_H_00xH_00+conj_H_10xH_10) (conj_H_00xH_01+conj_H_10xH_11)| + * A= | | + * |(conj_H_01xH_00+conj_H_11xH_10) (conj_H_01xH_01+conj_H_11xH_11)| + * + * + * + *inv(A) =(1/det)*[d -b + * -c a] + * + * + **************************************************************************/ + __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0=NULL,*dl_ch_mag128b_0=NULL,*dl_ch_mag128r_0=NULL,*determ_fin_128;//*dl_ch_mag128_1,*dl_ch_mag128b_1,*dl_ch_mag128r_1 + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3; + __m128i *after_mf_a_128,*after_mf_b_128, *after_mf_c_128, *after_mf_d_128; + __m128i QAM_amp128={0},QAM_amp128b={0},QAM_amp128r={0}; + + determ_fin_128 = (__m128i *)&determ_fin[0]; + + rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[0][symbol*nb_rb*12];//aatx=0 @ aarx =0 + rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[n_rx][symbol*nb_rb*12];//aatx=1 @ aarx =0 + + after_mf_a_128 = (__m128i *)af_mf_00; + after_mf_b_128 = (__m128i *)af_mf_01; + after_mf_c_128 = (__m128i *)af_mf_10; + after_mf_d_128 = (__m128i *)af_mf_11; + + if (mod_order>2) { + if (mod_order == 4) { + QAM_amp128 = _mm_set1_epi16(QAM16_n1); //2/sqrt(10) + QAM_amp128b = _mm_setzero_si128(); + QAM_amp128r = _mm_setzero_si128(); + } else if (mod_order == 6) { + QAM_amp128 = _mm_set1_epi16(QAM64_n1); //4/sqrt{42} + QAM_amp128b = _mm_set1_epi16(QAM64_n2); //2/sqrt{42} + QAM_amp128r = _mm_setzero_si128(); + } else if (mod_order == 8) { + QAM_amp128 = _mm_set1_epi16(QAM256_n1); //8/sqrt{170} + QAM_amp128b = _mm_set1_epi16(QAM256_n2);//4/sqrt{170} + QAM_amp128r = _mm_set1_epi16(QAM256_n3);//2/sqrt{170} + } + dl_ch_mag128_0 = (__m128i *)&dl_ch_mag[0][symbol*nb_rb*12]; + dl_ch_mag128b_0 = (__m128i *)&dl_ch_magb[0][symbol*nb_rb*12]; + dl_ch_mag128r_0 = (__m128i *)&dl_ch_magr[0][symbol*nb_rb*12]; + } + + for (int rb=0; rb<3*nb_rb_0; rb++) { + if (mod_order>2) { + int sum_det =0; + for (int k=0; k<4;k++) { + sum_det += ((((int *)&determ_fin_128[0])[k])>>2); + //printf("det_%d = %d\n",k,sum_det); + } + + mmtmpD2 = _mm_slli_epi32(determ_fin_128[0],5); + mmtmpD2 = _mm_srai_epi32(mmtmpD2,log2_approx(sum_det)); + mmtmpD2 = _mm_slli_epi32(mmtmpD2,5); + + mmtmpD3 = _mm_unpacklo_epi32(mmtmpD2,mmtmpD2); + + mmtmpD2 = _mm_unpackhi_epi32(mmtmpD2,mmtmpD2); + + mmtmpD2 = _mm_packs_epi32(mmtmpD3,mmtmpD2); + + dl_ch_mag128_0[0] = mmtmpD2; + dl_ch_mag128b_0[0] = mmtmpD2; + dl_ch_mag128r_0[0] = mmtmpD2; + + dl_ch_mag128_0[0] = _mm_mulhi_epi16(dl_ch_mag128_0[0],QAM_amp128); + dl_ch_mag128_0[0] = _mm_slli_epi16(dl_ch_mag128_0[0],1); + + dl_ch_mag128b_0[0] = _mm_mulhi_epi16(dl_ch_mag128b_0[0],QAM_amp128b); + dl_ch_mag128b_0[0] = _mm_slli_epi16(dl_ch_mag128b_0[0],1); + + dl_ch_mag128r_0[0] = _mm_mulhi_epi16(dl_ch_mag128r_0[0],QAM_amp128r); + dl_ch_mag128r_0[0] = _mm_slli_epi16(dl_ch_mag128r_0[0],1); + + //print_shorts("mag layer 1:",(int16_t*)&dl_ch_mag128_0[0]); + //print_shorts("mag layer 2:",(int16_t*)&dl_ch_mag128_1[0]); + //print_shorts("magb layer 1:",(int16_t*)&dl_ch_mag128b_0[0]); + //print_shorts("magb layer 2:",(int16_t*)&dl_ch_mag128b_1[0]); + //print_shorts("magr layer 1:",(int16_t*)&dl_ch_mag128r_0[0]); + //print_shorts("magr layer 2:",(int16_t*)&dl_ch_mag128r_1[0]); + } + // multiply by channel Inv + //rxdataF_zf128_0 = rxdataF_comp128_0*d - b*rxdataF_comp128_1 + //rxdataF_zf128_1 = rxdataF_comp128_1*a - c*rxdataF_comp128_0 + //printf("layer_1 \n"); + mmtmpD0 = nr_comp_muli_sum(rxdataF_comp128_0[0], + after_mf_d_128[0], + rxdataF_comp128_1[0], + after_mf_b_128[0], + determ_fin_128[0]); + + //printf("layer_2 \n"); + mmtmpD1 = nr_comp_muli_sum(rxdataF_comp128_1[0], + after_mf_a_128[0], + rxdataF_comp128_0[0], + after_mf_c_128[0], + determ_fin_128[0]); + + rxdataF_comp128_0[0] = mmtmpD0; + rxdataF_comp128_1[0] = mmtmpD1; +#ifdef DEBUG_DLSCH_DEMOD + printf("\n Rx signal after ZF l%d rb%d\n",symbol,rb); + print_shorts(" Rx layer 1:",(int16_t*)&rxdataF_comp128_0[0]); + print_shorts(" Rx layer 2:",(int16_t*)&rxdataF_comp128_1[0]); +#endif + determ_fin_128 += 1; + dl_ch_mag128_0 += 1; + dl_ch_mag128b_0 += 1; + dl_ch_mag128r_0 += 1; + rxdataF_comp128_0 += 1; + rxdataF_comp128_1 += 1; + after_mf_a_128 += 1; + after_mf_b_128 += 1; + after_mf_c_128 += 1; + after_mf_d_128 += 1; + } + _mm_empty(); + _m_empty(); + return(0); +} static void nr_dlsch_layer_demapping(int16_t **llr_cw, uint8_t Nl, uint8_t mod_order, - uint16_t length, + uint32_t length, + int32_t codeword_TB0, + int32_t codeword_TB1, int16_t **llr_layers) { switch (Nl) { - case 1: - memcpy((void*)llr_layers[0], (void*)llr_cw[0], (length)*sizeof(int16_t)); + if (codeword_TB1 == -1) + memcpy((void*)llr_cw[0], (void*)llr_layers[0], (length)*sizeof(int16_t)); + else if (codeword_TB0 == -1) + memcpy((void*)llr_cw[1], (void*)llr_layers[0], (length)*sizeof(int16_t)); + break; case 2: @@ -2554,112 +2973,260 @@ static void nr_dlsch_layer_demapping(int16_t **llr_cw, case 4: for (int i=0; i<(length/Nl/mod_order); i++){ for (int l=0; l0 1 2 3 + else if (codeword_TB0 == -1) + llr_cw[1][Nl*mod_order*i+l*mod_order+m] = llr_layers[l][i*mod_order+m];//i:0 -->0 1 2 3 + //if (i<4) printf("length%d: llr_layers[l%d][m%d]=%d: \n",length,l,m,llr_layers[l][i*mod_order+m]); + } + } } - } break; default: AssertFatal(0, "Not supported number of layers %d\n", Nl); } } -//============================================================================================== -#ifdef USER_MODE - - -void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t nr_tti_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid) +static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, + NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp_ptr, + int32_t **dl_ch_mag_ptr, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq, + RX_type_t rx_type, + unsigned char harq_pid, + unsigned char gNB_id, + unsigned char gNB_id_i, + unsigned char first_symbol_flag, + unsigned char symbol, + unsigned short nb_rb, + unsigned short round, + int32_t codeword_TB0, + int32_t codeword_TB1, + uint32_t len, + uint8_t nr_slot_rx, + uint8_t beamforming_mode) { - unsigned int nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; - char fname[32],vname[32]; - int N_RB_DL=ue->frame_parms.N_RB_DL; - sprintf(fname,"dlsch%d_rxF_r%d_ext0.m",eNB_id,round); - sprintf(vname,"dl%d_rxF_r%d_ext0",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1); + int16_t *pllr_symbol_cw0; + int16_t *pllr_symbol_cw1; + int16_t *pllr_symbol_layer0; + int16_t *pllr_symbol_layer1; + uint32_t llr_offset_symbol; + + if (first_symbol_flag==1) pdsch_vars[gNB_id]->llr_offset[symbol-1] = 0; + llr_offset_symbol = pdsch_vars[gNB_id]->llr_offset[symbol-1]; + //pllr_symbol_cw0_deint = (int8_t*)pdsch_vars[gNB_id]->llr[0]; + //pllr_symbol_cw1_deint = (int8_t*)pdsch_vars[gNB_id]->llr[1]; + pllr_symbol_layer0 = pdsch_vars[gNB_id]->layer_llr[0]; + pllr_symbol_layer1 = pdsch_vars[gNB_id]->layer_llr[1]; + pllr_symbol_layer0 += llr_offset_symbol; + pllr_symbol_layer1 += llr_offset_symbol; + pllr_symbol_cw0 = pdsch_vars[gNB_id]->llr[0]; + pllr_symbol_cw1 = pdsch_vars[gNB_id]->llr[1]; + pllr_symbol_cw0 += llr_offset_symbol; + pllr_symbol_cw1 += llr_offset_symbol; + + pdsch_vars[gNB_id]->llr_offset[symbol] = len*dlsch0_harq->Qm + llr_offset_symbol; + + /*LOG_I(PHY,"compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %x @LLR Buff(symb) %x\n", + symbol, + nb_rb,dlsch0_harq->Qm, + pdsch_vars[gNB_id]->llr_length[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], + (int16_t*)pdsch_vars[gNB_id]->llr[0], + pllr_symbol_cw0);*/ + + /*printf("compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n", + symbol, + nb_rb,dlsch0_harq->Qm, + pdsch_vars[gNB_id]->llr_length[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], + pdsch_vars[gNB_id]->llr[0], + pllr_symbol_cw0);*/ - if (ue->frame_parms.nb_antennas_rx >1) { - sprintf(fname,"dlsch%d_rxF_r%d_ext1.m",eNB_id,round); - sprintf(vname,"dl%d_rxF_r%d_ext1",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->rxdataF_ext[1],12*N_RB_DL*nsymb,1,1); + switch (dlsch0_harq->Qm) { + case 2 : + switch (rx_type) { + case rx_standard : + for(int l =0; lNl; l++) + nr_dlsch_qpsk_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0[l*frame_parms->nb_antennas_rx], + pdsch_vars[gNB_id]->layer_llr[l]+llr_offset_symbol, + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + break; + case rx_IC_single_stream ://not implemented yet + /*nr_dlsch_qpsk_qpsk_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0, + rxdataF_comp_ptr, + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], + symbol,len,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), + pdsch_vars[gNB_id]->llr128);*/ + break; + case rx_IC_dual_stream ://not implemented yet + /*nr_dlsch_qpsk_qpsk_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[gNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], + symbol,len,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), + pdsch_vars[gNB_id]->llr128_2ndstream);*/ + break; + case rx_SIC_dual_stream ://not implemented yet + break; + } + break; + case 4 : + switch (rx_type) { + case rx_standard : + for(int l =0; lNl; l++) + nr_dlsch_16qam_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0[l*frame_parms->nb_antennas_rx], + pdsch_vars[gNB_id]->layer_llr[l]+llr_offset_symbol, + pdsch_vars[gNB_id]->dl_ch_mag0[0], + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + break; + case rx_IC_single_stream ://not implemented yet + break; + case rx_IC_dual_stream ://not implemented yet + break; + case rx_SIC_dual_stream ://not implemented yet + break; + } + break; + case 6 : + switch (rx_type) { + case rx_standard : + for(int l =0; lNl; l++) + nr_dlsch_64qam_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0[l*frame_parms->nb_antennas_rx], + pdsch_vars[gNB_id]->layer_llr[l]+llr_offset_symbol, + pdsch_vars[gNB_id]->dl_ch_mag0[0], + pdsch_vars[gNB_id]->dl_ch_magb0[0], + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + break; + case rx_IC_single_stream ://not implemented yet + break; + case rx_IC_dual_stream ://not implemented yet + break; + case rx_SIC_dual_stream ://not implemented yet + break; + } + + break; + case 8: + switch (rx_type) { + case rx_standard : + for(int l =0; lNl; l++) + nr_dlsch_256qam_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0[l*frame_parms->nb_antennas_rx], + pdsch_vars[gNB_id]->layer_llr[l]+llr_offset_symbol, + pdsch_vars[gNB_id]->dl_ch_mag0[0], + pdsch_vars[gNB_id]->dl_ch_magb0[0], + pdsch_vars[gNB_id]->dl_ch_magr0[0], + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + break; + case rx_IC_single_stream ://not implemented yet + break; + case rx_IC_dual_stream ://not implemented yet + break; + case rx_SIC_dual_stream ://not implemented yet + break; + } + break; + default: + LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); + return(-1); + break; } - sprintf(fname,"dlsch%d_ch_r%d_ext00.m",eNB_id,round); - sprintf(vname,"dl%d_ch_r%d_ext00",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); - - if (ue->transmission_mode[eNB_id]==7){ - sprintf(fname,"dlsch%d_bf_ch_r%d.m",eNB_id,round); - sprintf(vname,"dl%d_bf_ch_r%d",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_bf_ch_estimates[0],512*nsymb,1,1); - //write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates[0],512,1,1); - - sprintf(fname,"dlsch%d_bf_ch_r%d_ext00.m",eNB_id,round); - sprintf(vname,"dl%d_bf_ch_r%d_ext00",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_bf_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); - } - - if (ue->frame_parms.nb_antennas_rx == 2) { - sprintf(fname,"dlsch%d_ch_r%d_ext01.m",eNB_id,round); - sprintf(vname,"dl%d_ch_r%d_ext01",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); - } - - if (ue->frame_parms.nb_antenna_ports_gNB == 2) { - sprintf(fname,"dlsch%d_ch_r%d_ext10.m",eNB_id,round); - sprintf(vname,"dl%d_ch_r%d_ext10",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); - - if (ue->frame_parms.nb_antennas_rx == 2) { - sprintf(fname,"dlsch%d_ch_r%d_ext11.m",eNB_id,round); - sprintf(vname,"dl%d_ch_r%d_ext11",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); + if (dlsch1_harq) { + switch (nr_get_Qm_dl(dlsch1_harq->mcs,dlsch1_harq->mcs_table)) { + case 2 : + if (rx_type==rx_standard) { + nr_dlsch_qpsk_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0[0], + pdsch_vars[gNB_id]->layer_llr[0]+llr_offset_symbol, + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + } + break; + case 4: + if (rx_type==rx_standard) { + nr_dlsch_16qam_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0[0], + pdsch_vars[gNB_id]->layer_llr[0]+llr_offset_symbol, + pdsch_vars[gNB_id]->dl_ch_mag0[0], + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + } + break; + case 6 : + if (rx_type==rx_standard) { + nr_dlsch_64qam_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0[0], + pdsch_vars[gNB_id]->layer_llr[0]+llr_offset_symbol, + pdsch_vars[gNB_id]->dl_ch_mag0[0], + pdsch_vars[gNB_id]->dl_ch_magb0[0], + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + } + break; + case 8 : + if (rx_type==rx_standard) { + nr_dlsch_256qam_llr(frame_parms, + pdsch_vars[gNB_id]->rxdataF_comp0[0], + pdsch_vars[gNB_id]->layer_llr[0]+llr_offset_symbol, + pdsch_vars[gNB_id]->dl_ch_mag0[0], + pdsch_vars[gNB_id]->dl_ch_magb0[0], + pdsch_vars[gNB_id]->dl_ch_magr0[0], + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + } + break; + default: + LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); + return(-1); + break; } } - - sprintf(fname,"dlsch%d_rxF_r%d_uespec0.m",eNB_id,round); - sprintf(vname,"dl%d_rxF_r%d_uespec0",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->rxdataF_uespec_pilots[0],12*N_RB_DL,1,1); - - /* - write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); - write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); - write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); - */ - sprintf(fname,"dlsch%d_r%d_rho.m",eNB_id,round); - sprintf(vname,"dl_rho_r%d_%d",eNB_id,round); - - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_rho_ext[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); - - sprintf(fname,"dlsch%d_r%d_rho2.m",eNB_id,round); - sprintf(vname,"dl_rho2_r%d_%d",eNB_id,round); - - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_rho2_ext[0],12*N_RB_DL*nsymb,1,1); - - sprintf(fname,"dlsch%d_rxF_r%d_comp0.m",eNB_id,round); - sprintf(vname,"dl%d_rxF_r%d_comp0",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb,1,1); - if (ue->frame_parms.nb_antenna_ports_gNB == 2) { - sprintf(fname,"dlsch%d_rxF_r%d_comp1.m",eNB_id,round); - sprintf(vname,"dl%d_rxF_r%d_comp1",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->rxdataF_comp1[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); - } - - sprintf(fname,"dlsch%d_rxF_r%d_llr.m",eNB_id,round); - sprintf(vname,"dl%d_r%d_llr",eNB_id,round); - write_output(fname,vname, ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->llr[0],coded_bits_per_codeword[0],1,0); - sprintf(fname,"dlsch%d_r%d_mag1.m",eNB_id,round); - sprintf(vname,"dl%d_r%d_mag1",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb,1,1); - sprintf(fname,"dlsch%d_r%d_mag2.m",eNB_id,round); - sprintf(vname,"dl%d_r%d_mag2",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_magb0[0],12*N_RB_DL*nsymb,1,1); - - // printf("log2_maxh = %d\n",ue->pdsch_vars[eNB_id]->log2_maxh); + return 0; } -#endif +//============================================================================================== + #ifdef DEBUG_DLSCH_DEMOD /* diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c index ce1c0df156..7c75884fa6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c @@ -629,16 +629,16 @@ __m128i tmp_result4 __attribute__ ((aligned(16))); //---------------------------------------------------------------------------------------------- int nr_dlsch_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, + int32_t *rxdataF_comp, int16_t *dlsch_llr, uint8_t symbol, - uint32_t len, - uint8_t first_symbol_flag, + uint32_t len, + uint8_t first_symbol_flag, uint16_t nb_rb, uint8_t beamforming_mode) { - uint32_t *rxF = (uint32_t*)&rxdataF_comp[0][((int32_t)symbol*nb_rb*12)]; + uint32_t *rxF = (uint32_t *)&rxdataF_comp[((int32_t)symbol*nb_rb*12)]; uint32_t *llr32; int i; @@ -670,24 +670,23 @@ int nr_dlsch_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms, //---------------------------------------------------------------------------------------------- void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, + int32_t *rxdataF_comp, int16_t *dlsch_llr, - int32_t **dl_ch_mag, + int32_t *dl_ch_mag, uint8_t symbol, - uint32_t len, + uint32_t len, uint8_t first_symbol_flag, uint16_t nb_rb, - int16_t **llr32p, uint8_t beamforming_mode) { #if defined(__x86_64__) || defined(__i386__) - __m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*nb_rb*12)]; + __m128i *rxF = (__m128i*)&rxdataF_comp[(symbol*nb_rb*12)]; __m128i *ch_mag; __m128i llr128[2]; uint32_t *llr32; #elif defined(__arm__) - int16x8_t *rxF = (int16x8_t*)&rxdataF_comp[0][(symbol*nb_rb*12)]; + int16x8_t *rxF = (int16x8_t*)&rxdataF_comp[(symbol*nb_rb*12)]; int16x8_t *ch_mag; int16x8_t xmm0; int16_t *llr16; @@ -699,30 +698,17 @@ void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, #if defined(__x86_64__) || defined(__i386__) - if (first_symbol_flag==1) { llr32 = (uint32_t*)dlsch_llr; - } else { - llr32 = (uint32_t*)*llr32p; - } #elif defined(__arm__) - if (first_symbol_flag==1) { llr16 = (int16_t*)dlsch_llr; - } else { - llr16 = (int16_t*)*llr32p; - } #endif #if defined(__x86_64__) || defined(__i386__) - ch_mag = (__m128i*)&dl_ch_mag[0][(symbol*nb_rb*12)]; + ch_mag = (__m128i*)&dl_ch_mag[(symbol*nb_rb*12)]; #elif defined(__arm__) - ch_mag = (int16x8_t*)&dl_ch_mag[0][(symbol*nb_rb*12)]; + ch_mag = (int16x8_t*)&dl_ch_mag[(symbol*nb_rb*12)]; #endif - // update output pointer according to number of REs in this symbol (<<2 because 4 bits per RE) - if (first_symbol_flag == 1) - *llr32p = dlsch_llr + (len<<2); - else - *llr32p += (len<<2); // printf("len=%d\n", len); len_mod4 = len&3; @@ -786,47 +772,35 @@ void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, //---------------------------------------------------------------------------------------------- void nr_dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, - int16_t *dlsch_llr, - int32_t **dl_ch_mag, - int32_t **dl_ch_magb, - uint8_t symbol, - uint32_t len, - uint8_t first_symbol_flag, - uint16_t nb_rb, - uint32_t llr_offset, - uint8_t beamforming_mode) + int32_t *rxdataF_comp, + int16_t *dlsch_llr, + int32_t *dl_ch_mag, + int32_t *dl_ch_magb, + uint8_t symbol, + uint32_t len, + uint8_t first_symbol_flag, + uint16_t nb_rb, + uint8_t beamforming_mode) { #if defined(__x86_64__) || defined(__i386__) - __m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*nb_rb*12)]; + __m128i *rxF = (__m128i*)&rxdataF_comp[(symbol*nb_rb*12)]; __m128i *ch_mag,*ch_magb; #elif defined(__arm__) - int16x8_t *rxF = (int16x8_t*)&rxdataF_comp[0][(symbol*nb_rb*12)]; + int16x8_t *rxF = (int16x8_t*)&rxdataF_comp[(symbol*nb_rb*12)]; int16x8_t *ch_mag,*ch_magb,xmm1,xmm2; #endif int i,len2; unsigned char len_mod4; - short *llr; int16_t *llr2; - int8_t *pllr_symbol; - /* - if (first_symbol_flag==1) - llr = dlsch_llr; - else - llr = *llr_save; - */ - llr = dlsch_llr; - - pllr_symbol = (int8_t*)dlsch_llr; - pllr_symbol += llr_offset; + llr2 = dlsch_llr; #if defined(__x86_64__) || defined(__i386__) - ch_mag = (__m128i*)&dl_ch_mag[0][(symbol*nb_rb*12)]; - ch_magb = (__m128i*)&dl_ch_magb[0][(symbol*nb_rb*12)]; + ch_mag = (__m128i*)&dl_ch_mag[(symbol*nb_rb*12)]; + ch_magb = (__m128i*)&dl_ch_magb[(symbol*nb_rb*12)]; #elif defined(__arm__) - ch_mag = (int16x8_t*)&dl_ch_mag[0][(symbol*nb_rb*12)]; - ch_magb = (int16x8_t*)&dl_ch_magb[0][(symbol*nb_rb*12)]; + ch_mag = (int16x8_t*)&dl_ch_mag[(symbol*nb_rb*12)]; + ch_magb = (int16x8_t*)&dl_ch_magb[(symbol*nb_rb*12)]; #endif // printf("nr_dlsch_64qam_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); @@ -838,9 +812,6 @@ void nr_dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms, dlsch_llr, pllr_symbol);*/ - llr2 = llr; - llr += (len*6); - len_mod4 =len&3; len2=len>>2; // length in quad words (4 REs) len2+=((len_mod4==0)?0:1); @@ -976,7 +947,7 @@ void nr_dlsch_64qam_llr_SIC(NR_DL_FRAME_PARMS *frame_parms, symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; - pbch_pss_sss_adjust=adjust_G2(frame_parms,&rb_alloc,6,subframe,symbol); + pbch_pss_sss_adjust=adjust_G2(frame_parms->Ncp,frame_parms->frame_type, frame_parms->N_RB_DL,&rb_alloc,6,subframe,symbol); if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { amp_tmp = 0x1fff;//dlsch0->sqrt_rho_b; already taken into account @@ -1089,6 +1060,94 @@ void nr_dlsch_64qam_llr_SIC(NR_DL_FRAME_PARMS *frame_parms, } } //#endif + +//---------------------------------------------------------------------------------------------- +// 256-QAM +//---------------------------------------------------------------------------------------------- + +void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms, + int32_t *rxdataF_comp, + int16_t *dlsch_llr, + int32_t *dl_ch_mag, + int32_t *dl_ch_magb, + int32_t *dl_ch_magr, + uint8_t symbol, + uint32_t len, + uint8_t first_symbol_flag, + uint16_t nb_rb, + uint8_t beamforming_mode) +{ + __m128i *rxF = (__m128i*)&rxdataF_comp[(symbol*nb_rb*12)]; + __m128i *ch_mag,*ch_magb,*ch_magr; + + int i,len2; + unsigned char len_mod4; + int16_t *llr2; + + llr2 = dlsch_llr; + + ch_mag = (__m128i*)&dl_ch_mag[(symbol*nb_rb*12)]; + ch_magb = (__m128i*)&dl_ch_magb[(symbol*nb_rb*12)]; + ch_magr = (__m128i*)&dl_ch_magr[(symbol*nb_rb*12)]; + + len_mod4 =len&3; + len2=len>>2; // length in quad words (4 REs) + len2+=((len_mod4==0)?0:1); + + for (i=0; i @@ -46,6 +46,7 @@ #include "PHY/NR_REFSIG/pss_nr.h" #include "PHY/NR_REFSIG/sss_nr.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_TRANSPORT/nr_dci.h" extern openair0_config_t openair0_cfg[]; //static nfapi_nr_config_request_t config_t; @@ -103,7 +104,7 @@ void free_list(NR_UE_SSB *node) { } -int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_initial_symbol, runmode_t mode) +int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_initial_symbol) { NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int ret =-1; @@ -126,15 +127,11 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini // initialization of structure current_ssb = create_ssb_node(l,hf); -#if UE_TIMING_TRACE start_meas(&ue->dlsch_channel_estimation_stats); -#endif // computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf for(int i=pbch_initial_symbol; idlsch_channel_estimation_stats); -#endif current_ssb->metric = current_ssb->c_re*current_ssb->c_re + current_ssb->c_im*current_ssb->c_im; @@ -150,24 +147,19 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini NR_UE_SSB *temp_ptr=best_ssb; while (ret!=0 && temp_ptr != NULL) { -#if UE_TIMING_TRACE start_meas(&ue->dlsch_channel_estimation_stats); -#endif // computing channel estimation for selected best ssb for(int i=pbch_initial_symbol; ii_ssb,temp_ptr->n_hf); -#if UE_TIMING_TRACE + nr_pbch_channel_estimation(ue,proc,0,0,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf); stop_meas(&ue->dlsch_channel_estimation_stats); -#endif ret = nr_rx_pbch(ue, - proc, - ue->pbch_vars[0], - frame_parms, - 0, - temp_ptr->i_ssb, - SISO, - ue->high_speed_flag); + proc, + ue->pbch_vars[0], + frame_parms, + 0, + temp_ptr->i_ssb, + SISO); temp_ptr=temp_ptr->next_ssb; } @@ -202,7 +194,10 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini char duplex_string[2][4] = {"FDD","TDD"}; char prefix_string[2][9] = {"NORMAL","EXTENDED"}; -int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode, int n_frames) +int nr_initial_sync(UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + int n_frames, int sa, + int dlsch_parallel) { int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2, @@ -286,43 +281,45 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode, for(int i=0; i<4;i++) nr_slot_fep_init_sync(ue, - i, - 0, - is*fp->samples_per_frame+ue->ssb_offset, - 0); + proc, + i, + 0, + is*fp->samples_per_frame+ue->ssb_offset); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"Calling sss detection (normal CP)\n"); #endif - rx_sss_nr(ue,&metric_tdd_ncp,&phase_tdd_ncp); - - //FK: why do we need to do this again here? - //nr_init_frame_parms_ue(fp,NR_MU_1,NORMAL,n_ssb_crb,0); + rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp); nr_gold_pbch(ue); - ret = nr_pbch_detection(proc, ue,1,mode); // start pbch detection at first symbol after pss + ret = nr_pbch_detection(proc, ue, 1); // start pbch detection at first symbol after pss if (ret == 0) { // sync at symbol ue->symbol_offset // computing the offset wrt the beginning of the frame - sync_pos_frame = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)+((ue->symbol_offset)-1)*(fp->ofdm_symbol_size + fp->nb_prefix_samples); - - if (ue->ssb_offset < sync_pos_frame) + int mu = fp->numerology_index; + // number of symbols with different prefix length + // every 7*(1<symbol_offset/(7*(1<ofdm_symbol_size + fp->nb_prefix_samples0)+(ue->symbol_offset-n_symb_prefix0)*(fp->ofdm_symbol_size + fp->nb_prefix_samples); + // for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of the n_frames we got sync + ue->init_sync_frame = n_frames - 1 - is; + // we also need to take into account the shift by samples_per_frame in case the if is true + if (ue->ssb_offset < sync_pos_frame){ ue->rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset; + ue->init_sync_frame += 1; + } else ue->rx_offset = ue->ssb_offset - sync_pos_frame; - - ue->init_sync_frame = is; } - nr_gold_pdcch(ue,0, 2); /* int nb_prefix_samples0 = fp->nb_prefix_samples0; fp->nb_prefix_samples0 = fp->nb_prefix_samples; - nr_slot_fep(ue,0, 0, ue->ssb_offset, 0, NR_PDCCH_EST); - nr_slot_fep(ue,1, 0, ue->ssb_offset, 0, NR_PDCCH_EST); + nr_slot_fep(ue, proc, 0, 0, ue->ssb_offset, 0, NR_PDCCH_EST); + nr_slot_fep(ue, proc, 1, 0, ue->ssb_offset, 0, NR_PDCCH_EST); fp->nb_prefix_samples0 = nb_prefix_samples0; LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n", @@ -348,7 +345,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode, } } else { - ret = -1; + ret = -1; } /* Consider this is a false detection if the offset is > 1000 Hz @@ -373,8 +370,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode, #endif //#endif - ue->is_synchronized_on_frame = is; // to notify on which of the two frames sync was successful - if (ue->UE_scan_carrier == 0) { #if UE_AUTOTEST_TRACE @@ -480,6 +475,76 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode, } + // if stand alone and sync on ssb do sib1 detection as part of initial sync + if (sa==1 && ret==0) { + bool dec = false; + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; + int gnb_id = 0; //FIXME + int coreset_nb_rb=0; + int coreset_start_rb=0; + + for(int n_ss = 0; n_ssnb_search_space; n_ss++) { + uint8_t nb_symb_pdcch = pdcch_vars->pdcch_config[n_ss].coreset.duration; + int start_symb = pdcch_vars->pdcch_config[n_ss].coreset.StartSymbolIndex; + get_coreset_rballoc(pdcch_vars->pdcch_config[n_ss].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); + for (uint16_t l=start_symb; lslot, + is*fp->samples_per_frame+pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); + + if (coreset_nb_rb > 0) + nr_pdcch_channel_estimation(ue, + proc, + 0, + pdcch_vars->slot, + l, + fp->first_carrier_offset+(pdcch_vars->pdcch_config[n_ss].BWPStart + coreset_start_rb)*12, + coreset_nb_rb); + + } + int dci_cnt = nr_ue_pdcch_procedures(gnb_id, ue, proc, n_ss); + if (dci_cnt>0){ + NR_UE_DLSCH_t *dlsch = ue->dlsch_SI[gnb_id]; + if (dlsch && (dlsch->active == 1)) { + uint8_t harq_pid = dlsch->current_harq_pid; + NR_DL_UE_HARQ_t *dlsch0_harq = dlsch->harq_processes[harq_pid]; + uint16_t nb_symb_sch = dlsch0_harq->nb_symbols; + uint16_t start_symb_sch = dlsch0_harq->start_symbol; + + for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ + nr_slot_fep_init_sync(ue, + proc, + m, + pdcch_vars->slot, // same slot and offset as pdcch + is*fp->samples_per_frame+pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); + } + + int ret = nr_ue_pdsch_procedures(ue, + proc, + gnb_id, + SI_PDSCH, + ue->dlsch_SI[gnb_id], + NULL); + if (ret >= 0) + dec = nr_ue_dlsch_procedures(ue, + proc, + gnb_id, + SI_PDSCH, + ue->dlsch_SI[gnb_id], + NULL, + &ue->dlsch_SI_errors[gnb_id], + dlsch_parallel); + + // deactivate dlsch once dlsch proc is done + ue->dlsch_SI[gnb_id]->active = 0; + } + } + } + if (dec == false) // sib1 not decoded + ret = -1; + } // exit_fun("debug exit"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT); return ret; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 612dc6283d..86c9974f68 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -35,13 +35,12 @@ #include "PHY/sse_intrin.h" #include "PHY/LTE_REFSIG/lte_refsig.h" #include "PHY/INIT/phy_init.h" +#include "openair1/SCHED_NR_UE/defs.h" -//#define DEBUG_PBCH 1 +//#define DEBUG_PBCH //#define DEBUG_PBCH_ENCODING -#ifdef OPENAIR2 //#include "PHY_INTERFACE/defs.h" -#endif #define PBCH_A 24 @@ -53,21 +52,20 @@ uint16_t nr_pbch_extract(int **rxdataF, int **dl_ch_estimates_ext, uint32_t symbol, uint32_t s_offset, - uint32_t high_speed_flag, NR_DL_FRAME_PARMS *frame_parms) { uint16_t rb; uint8_t i,j,aarx; int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; int nushiftmod4 = frame_parms->nushift; - unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; //and - - if (rx_offset>= frame_parms->ofdm_symbol_size) rx_offset-=frame_parms->ofdm_symbol_size; AssertFatal(symbol>=1 && symbol<5, "symbol %d illegal for PBCH extraction\n", symbol); for (aarx=0; aarxnb_antennas_rx; aarx++) { + unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + rx_offset = (rx_offset)%(frame_parms->ofdm_symbol_size); + rxF = &rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size]; rxF_ext = &rxdataF_ext[aarx][symbol*20*12]; #ifdef DEBUG_PBCH @@ -103,8 +101,8 @@ uint16_t nr_pbch_extract(int **rxdataF, j++; } - //rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); - rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1); + rx_offset=(rx_offset+1)%(frame_parms->ofdm_symbol_size); + //rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1); } rxF_ext+=9; @@ -126,19 +124,18 @@ uint16_t nr_pbch_extract(int **rxdataF, j++; } - //rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); - rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1); + rx_offset=(rx_offset+1)%(frame_parms->ofdm_symbol_size); + //rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1); } rxF_ext+=9; - } else rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 12) : (rx_offset+12);//rx_offset = (rx_offset+12)&(frame_parms->ofdm_symbol_size-1); + } else{ //rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 12) : (rx_offset+12); + rx_offset = (rx_offset+12)%(frame_parms->ofdm_symbol_size); + } } } - if (high_speed_flag == 1) - dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))]; - else - dl_ch0 = &dl_ch_estimates[aarx][0]; + dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))]; //printf("dl_ch0 addr %p\n",dl_ch0); dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*20*12]; @@ -329,7 +326,7 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, #endif } -void nr_pbch_unscrambling(NR_UE_PBCH *pbch, +static void nr_pbch_unscrambling(NR_UE_PBCH *pbch, uint16_t Nid, uint8_t nushift, uint16_t M, @@ -415,12 +412,10 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, NR_UE_PBCH *nr_ue_pbch_vars, NR_DL_FRAME_PARMS *frame_parms, - uint8_t eNB_id, + uint8_t gNB_id, uint8_t i_ssb, - MIMO_mode_t mimo_mode, - uint32_t high_speed_flag) { + MIMO_mode_t mimo_mode) { - int Ns = proc->nr_tti_rx; NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars; int max_h=0; int symbol; @@ -454,21 +449,20 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, #ifdef DEBUG_PBCH - //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF); + //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF); write_output("rxdataF0_pbch.m","rxF0pbch", - &nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1); + &nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1); #endif // symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot for (symbol=1; symbol<4; symbol++) { - nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF, + nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, nr_ue_pbch_vars->dl_ch_estimates, nr_ue_pbch_vars->rxdataF_ext, nr_ue_pbch_vars->dl_ch_estimates_ext, symbol, symbol_offset, - high_speed_flag, frame_parms); #ifdef DEBUG_PBCH LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size ); @@ -536,6 +530,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, M = NR_POLAR_PBCH_E; nushift = (Lmax==4)? i_ssb&3 : i_ssb&7; uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041; + nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_E,0,0); //polar decoding de-rate matching const t_nrPolar_params *currentPtr = nr_polar_params( NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL,1,&ue->polarList); @@ -552,7 +547,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, nr_ue_pbch_vars->pbch_a_prime = a_reversed; //payload un-scrambling - memset(&nr_ue_pbch_vars->pbch_a_interleaved, 0, sizeof(uint32_t) ); + nr_ue_pbch_vars->pbch_a_interleaved=0; M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = ((nr_ue_pbch_vars->pbch_a_prime>>24)&1) ^ (((nr_ue_pbch_vars->pbch_a_prime>>6)&1)<<1); nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_PAYLOAD_BITS,1,unscrambling_mask); @@ -586,7 +581,9 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, frame_parms->ssb_index += (((nr_ue_pbch_vars->xtra_byte>>(7-i))&0x01)<<(3+i)); } - ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms); + ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms,frame_parms->ssb_index); + if (frame_parms->half_frame_bit) + ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot; uint8_t frame_number_4lsb = 0; for (int i=0; i<4; i++) @@ -605,20 +602,10 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; - - dl_indication.rx_ind = &rx_ind; // hang on rx_ind instance - dl_indication.dci_ind = NULL; - dl_indication.proc=proc; - dl_indication.module_id=0; - dl_indication.cc_id=proc->CC_id; + uint16_t number_pdus = 1; - rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_MIB; - rx_ind.rx_indication_body[0].mib_pdu.pdu = &decoded_output[0]; //not good as it is pointing to a memory that can change - rx_ind.rx_indication_body[0].mib_pdu.additional_bits = nr_ue_pbch_vars->xtra_byte; - rx_ind.rx_indication_body[0].mib_pdu.ssb_index = i_ssb; // confirm with TCL - rx_ind.rx_indication_body[0].mib_pdu.ssb_length = Lmax; // confirm with TCL - rx_ind.rx_indication_body[0].mib_pdu.cell_id = frame_parms->Nid_cell; // confirm with TCL - rx_ind.number_pdus = 1; //rx_ind.number_pdus++; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, gNB_id, ue, NULL, NULL, number_pdus); if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication, NULL); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index e4cab0b9a6..24299fd788 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -48,8 +48,7 @@ extern uint16_t prach_root_sequence_map_0_3[838]; extern uint16_t prach_root_sequence_map_abc[138]; extern uint16_t nr_du[838]; extern int16_t nr_ru[2*839]; -extern const char *prachfmt[9]; -extern const char *prachfmt03[4]; +extern const char *prachfmt[]; // Note: // - prach_fmt_id is an ID used to map to the corresponding PRACH format value in prachfmt @@ -67,14 +66,18 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ uint8_t Mod_id, fd_occasion, preamble_index, restricted_set, not_found; uint16_t rootSequenceIndex, prach_fmt_id, NCS, *prach_root_sequence_map, preamble_offset = 0; - uint16_t preamble_shift = 0, preamble_index0, n_shift_ra, n_shift_ra_bar, d_start, numshift, N_ZC, u, offset, offset2, first_nonzero_root_idx; + uint16_t preamble_shift = 0, preamble_index0, n_shift_ra, n_shift_ra_bar, d_start=INT16_MAX, numshift, N_ZC, u, offset, offset2, first_nonzero_root_idx; int16_t prach_tmp[98304*2*4] __attribute__((aligned(32))); int16_t Ncp = 0, amp, *prach, *prach2, *prachF, *Xu; - int32_t Xu_re, Xu_im, samp_count; - int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k; + int32_t Xu_re, Xu_im; + int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k, prachStartSymbol, sample_offset_slot; //int restricted_Type; + fd_occasion = 0; + prach_len = 0; + dftlen = 0; + first_nonzero_root_idx = 0; prach = prach_tmp; prachF = ue->prach_vars[gNB_id]->prachF; amp = ue->prach_vars[gNB_id]->amp; @@ -84,18 +87,14 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ mu = nrUE_config->prach_config.prach_sub_c_spacing; restricted_set = prach_pdu->restricted_set; rootSequenceIndex = prach_pdu->root_seq_id; - n_ra_prb = prach_pdu->freq_msg1; + n_ra_prb = nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].k1,//prach_pdu->freq_msg1; NCS = prach_pdu->num_cs; prach_fmt_id = prach_pdu->prach_format; preamble_index = prach_resources->ra_PreambleIndex; - fd_occasion = 0; - prach_len = 0; - dftlen = 0; - first_nonzero_root_idx = 0; kbar = 1; K = 24; k = 12*n_ra_prb - 6*fp->N_RB_UL; - //prachStartSymbol = prach_config_pdu->prach_start_symbol + prachStartSymbol = prach_pdu->prach_start_symbol; //restricted_Type = 0; compute_nr_prach_seq(nrUE_config->prach_config.prach_sequence_length, @@ -103,22 +102,14 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index, ue->X_u); - if (mu == 0) - samp_count = fp->samples_per_subframe; + if (slot % (fp->slots_per_subframe / 2) == 0) + sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1)); else - samp_count = (slot%(fp->slots_per_subframe/2)) ? fp->samples_per_slotN0 : fp->samples_per_slot0; + sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * prachStartSymbol; - #ifdef OAI_USRP - prach_start = (ue->rx_offset + slot*samp_count - ue->hw_timing_advance - ue->N_TA_offset); - #else //normal case (simulation) - prach_start = slot*samp_count - ue->N_TA_offset; - #endif + prach_start = fp->get_samples_slot_timestamp(slot, fp, 0) + sample_offset_slot; - if (prach_start<0) - prach_start += (fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME); - - if (prach_start >= (fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME)) - prach_start -= (fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME); + //printf("prachstartsymbold %d, sample_offset_slot %d, prach_start %d\n",prachStartSymbol, sample_offset_slot, prach_start); // First compute physical root sequence /************************************************************************ @@ -143,6 +134,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ #endif not_found = 1; + nr_fill_du(N_ZC,prach_root_sequence_map); preamble_index0 = preamble_index; // set preamble_offset to initial rootSequenceIndex and look if we need more root sequences for this // preamble index and find the corresponding cyclic shift @@ -196,14 +188,14 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } // now generate PRACH signal - #ifdef NR_PRACH_DEBUG +#ifdef NR_PRACH_DEBUG if (NCS>0) LOG_I(PHY, "PRACH [UE %d] generate PRACH in slot %d for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d msg1 frequency start %d\n", Mod_id, slot, rootSequenceIndex, preamble_index, - prach_sequence_length == 0 ? prachfmt03[prach_fmt_id] : prachfmt[prach_fmt_id], + prachfmt[prach_fmt_id], NCS, N_ZC, preamble_offset, @@ -229,12 +221,13 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ k += kbar; k *= 2; - LOG_I(PHY, "PRACH [UE %d] in slot %d, placing PRACH in position %d, msg1 frequency start %d, preamble_offset %d, first_nonzero_root_idx %d\n", Mod_id, - slot, - k, - n_ra_prb, - preamble_offset, - first_nonzero_root_idx); + LOG_I(PHY, "PRACH [UE %d] in slot %d, placing PRACH in position %d, msg1 frequency start %d (k1 %d), preamble_offset %d, first_nonzero_root_idx %d\n", Mod_id, + slot, + k, + n_ra_prb, + nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].k1, + preamble_offset, + first_nonzero_root_idx); Xu = (int16_t*)ue->X_u[preamble_offset-first_nonzero_root_idx]; @@ -256,86 +249,99 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ * *********************************************************/ - if (fp->N_RB_UL <= 100) - AssertFatal(1 == 0, "N_RB_UL %d not support for NR PRACH yet\n", fp->N_RB_UL); - else if (fp->N_RB_UL < 137) { - if (fp->threequarter_fs == 0) { - //40 MHz @ 61.44 Ms/s - //50 MHz @ 61.44 Ms/s + if (mu==1) { + switch(fp->samples_per_subframe) { + case 15360: + // 10, 15 MHz @ 15.36 Ms/s if (prach_sequence_length == 0) { if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) - dftlen = 49152; + dftlen = 12288; if (prach_fmt_id == 3) - dftlen = 12288; - } // 839 sequence - else { - switch (mu){ - case 1: - dftlen = 2048; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } + dftlen = 3072; + } else { // 839 sequence + dftlen = 512; } - } else { // threequarter sampling - // 40 MHz @ 46.08 Ms/s + break; + + case 30720: + // 20, 25, 30 MHz @ 30.72 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 24576; + if (prach_fmt_id == 3) + dftlen = 6144; + } else { // 839 sequence + dftlen = 1024; + } + break; + + case 46080: + // 40 MHz @ 46.08 Ms/s if (prach_sequence_length == 0) { - AssertFatal(fp->N_RB_UL <= 107, "cannot do 108..136 PRBs with 3/4 sampling\n"); if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) dftlen = 36864; if (prach_fmt_id == 3) dftlen = 9216; - } else { - switch (mu){ - case 1: - dftlen = 1536; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } - } // short format - } // 3/4 sampling - } // <=50 MHz BW - else if (fp->N_RB_UL <= 273) { - if (fp->threequarter_fs == 0) { - //80,90,100 MHz @ 122.88 Ms/s + } else { // 839 sequence + dftlen = 1536; + } + break; + + case 61440: + // 40, 50, 60 MHz @ 61.44 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 49152; + if (prach_fmt_id == 3) + dftlen = 12288; + } else { // 839 sequence + dftlen = 2048; + } + break; + + case 92160: + // 50, 60, 70, 80, 90 MHz @ 92.16 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 73728; + if (prach_fmt_id == 3) + dftlen = 18432; + } else { // 839 sequence + dftlen = 3072; + } + break; + + case 122880: + // 70, 80, 90, 100 MHz @ 122.88 Ms/s if (prach_sequence_length == 0) { if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) dftlen = 98304; if (prach_fmt_id == 3) dftlen = 24576; + } else { // 839 sequence + dftlen = 4096; } - } else { // threequarter sampling - switch (mu){ - case 1: - dftlen = 4096; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } - } - } else { - AssertFatal(fp->N_RB_UL <= 217, "cannot do more than 217 PRBs with 3/4 sampling\n"); - // 80 MHz @ 92.16 Ms/s - if (prach_sequence_length == 0) { - if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) - dftlen = 73728; - if (prach_fmt_id == 3) - dftlen = 18432; - } else { - switch (mu){ - case 1: - dftlen = 3072; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } } + else if (mu==3) { + if (fp->threequarter_fs) + AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu); + + if (prach_sequence_length == 0) + AssertFatal(1==0,"long prach not supported for numerology %d\n",mu); + + if (fp->N_RB_UL == 32) + dftlen=512; + else if (fp->N_RB_UL == 66) + dftlen=1024; + else + AssertFatal(1==0,"N_RB_UL %d not support for numerology %d\n",fp->N_RB_UL,mu); + } + for (offset=0,offset2=0; offsetN_RB_UL <= 100) - AssertFatal(1==0,"N_RB_UL %d not supported for NR PRACH yet\n",fp->N_RB_UL); - else if (fp->N_RB_UL < 137) { // 46.08 or 61.44 Ms/s - if (fp->threequarter_fs == 0) { // full sampling @ 61.44 Ms/s - Ncp<<=1; - // This is after cyclic prefix (Ncp<<1 samples for 30.72 Ms/s, Ncp<<2 samples for 61.44 Ms/s - prach2 = prach+(Ncp<<1); + //actually what we should be checking here is how often the current prach crosses a 0.5ms boundary. I am not quite sure for which paramter set this would be the case, so I will ignore it for now and just check if the prach starts on a 0.5ms boundary + uint8_t use_extended_prach_prefix = 0; + if(fp->numerology_index == 0) { + if (prachStartSymbol == 0 || prachStartSymbol == 7) + use_extended_prach_prefix = 1; + } + else { + if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + use_extended_prach_prefix = 1; + } + + if (mu == 3) { + switch (fp->samples_per_subframe) { + case 61440: // 32 PRB case, 61.44 Msps + Ncp<<=1; //to account for 61.44Mbps + // This is after cyclic prefix + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_sequence_length == 0) + AssertFatal(1==0,"no long PRACH for this PRACH size %d\n",fp->N_RB_UL); + else { + if (use_extended_prach_prefix) + Ncp+=32; // 16*kappa, kappa=2 for 61.44Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { + idft(IDFT_512,prachF,prach2,1); + // here we have |empty | Prach512 | + if (prach_fmt_id != 9) { + memmove(prach2+(512<<1),prach2,(512<<2)); + prach_len = (512*2)+Ncp; + } + else prach_len = (512*1)+Ncp; + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have |Prefix | Prach512 | Prach512 (if ! 0xc0) | + } else if (prach_fmt_id == 5) { // 6x512 + idft(IDFT_512,prachF,prach2,1); + // here we have |empty | Prach512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have |empty | Prach512 | Prach512| empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have |Prefix | Prach512 | + prach_len = (512*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x512 + idft(IDFT_512,prachF,prach2,1); + // here we have |empty | Prach512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have |empty | Prach512 | Prach512| empty512 | empty512 | empty512 | empty512 + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | empty512 | empty512 + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have |Prefix | Prach512 | + prach_len = (512*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x512 + idft(IDFT_512,prachF,prach2,1); + // here we have |empty | Prach512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have |empty | Prach512 | Prach512| empty512 | empty512 | empty512 | empty512 + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | empty512 | empty512 + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 + memmove(prach2+(512<<1)*6,prach2,(512<<2)*6); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512| + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have |Prefix | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512| + prach_len = (512*12)+Ncp; + } + } + break; + + case 122880: // 66 PRB case, 122.88 Msps + Ncp<<=2; //to account for 122.88Mbps + // This is after cyclic prefix + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_sequence_length == 0) + AssertFatal(1==0,"no long PRACH for this PRACH size %d\n",fp->N_RB_UL); + else { + if (use_extended_prach_prefix) + Ncp+=64; // 16*kappa, kappa=4 for 122.88Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { + idft(IDFT_1024,prachF,prach2,1); + // here we have |empty | Prach1024 | + if (prach_fmt_id != 9) { + memmove(prach2+(1024<<1),prach2,(1024<<2)); + prach_len = (1024*2)+Ncp; + } + else prach_len = (1024*1)+Ncp; + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have |Prefix | Prach1024 | Prach1024 (if ! 0xc0) | + } else if (prach_fmt_id == 5) { // 6x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have |empty | Prach1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have |Prefix | Prach1024 | + prach_len = (1024*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have |empty | Prach1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 | empty1024 | empty1024 + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | empty1024 | empty1024 + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have |Prefix | Prach1024 | + prach_len = (1024*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have |empty | Prach1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 | empty1024 | empty1024 + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | empty1024 | empty1024 + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 + memmove(prach2+(1024<<1)*6,prach2,(1024<<2)*6); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024| + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have |Prefix | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024| + prach_len = (1024*12)+Ncp; + } + } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); + } + } else if (mu == 1) { + switch (fp->samples_per_subframe) { + case 15360: // full sampling @ 15.36 Ms/s + Ncp = Ncp/2; // to account for 15.36 Ms/s + // This is after cyclic prefix + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_sequence_length == 0){ + if (prach_fmt_id == 0) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | + memmove(prach,prach+(12288<<1),(Ncp<<2)); + // here we have | Prefix | Prach12288 | + prach_len = 12288+Ncp; + } else if (prach_fmt_id == 1) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | empty12288 | + memmove(prach2+(12288<<1),prach2,(12288<<2)); + // here we have | empty | Prach12288 | Prach12288 | + memmove(prach,prach+(12288<<2),(Ncp<<2)); + // here we have | Prefix | Prach12288 | Prach12288 | + prach_len = (12288*2)+Ncp; + } else if (prach_fmt_id == 2) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | empty12288 | empty12288 | empty12288 | + memmove(prach2+(12288<<1),prach2,(12288<<2)); + // here we have | empty | Prach12288 | Prach12288 | empty12288 | empty12288 | + memmove(prach2+(12288<<2),prach2,(12288<<3)); + // here we have | empty | Prach12288 | Prach12288 | Prach12288 | Prach12288 | + memmove(prach,prach+(12288<<3),(Ncp<<2)); + // here we have | Prefix | Prach12288 | Prach12288 | Prach12288 | Prach12288 | + prach_len = (12288*4)+Ncp; + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s, 3072 samples @ 15.36 Ms/s + idft(IDFT_3072,prachF,prach2,1); + // here we have | empty | Prach3072 | empty3072 | empty3072 | empty3072 | + memmove(prach2+(3072<<1),prach2,(3072<<2)); + // here we have | empty | Prach3072 | Prach3072 | empty3072 | empty3072 | + memmove(prach2+(3072<<2),prach2,(3072<<3)); + // here we have | empty | Prach3072 | Prach3072 | Prach3072 | Prach3072 | + memmove(prach,prach+(3072<<3),(Ncp<<2)); + // here we have | Prefix | Prach3072 | Prach3072 | Prach3072 | Prach3072 | + prach_len = (3072*4)+Ncp; + } + } else { // short PRACH sequence + if (use_extended_prach_prefix) + Ncp += 8; // 16*kappa, kappa=0.5 for 15.36 Ms/s + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_fmt_id == 9) { + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | + prach_len = (512*1)+Ncp; + } else if (prach_fmt_id == 4 || prach_fmt_id == 7) { + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | + prach_len = (512*2)+Ncp; + } else if (prach_fmt_id == 5) { // 4x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1)*6,prach2,(512<<2)*6); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*12)+Ncp; + } + } + break; + + case 30720: // full sampling @ 30.72 Ms/s + Ncp = Ncp*1; // to account for 30.72 Ms/s + // This is after cyclic prefix + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_sequence_length == 0){ + if (prach_fmt_id == 0) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | + memmove(prach,prach+(24576<<1),(Ncp<<2)); + // here we have | Prefix | Prach24576 | + prach_len = 24576+Ncp; + } else if (prach_fmt_id == 1) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | empty24576 | + memmove(prach2+(24576<<1),prach2,(24576<<2)); + // here we have | empty | Prach24576 | Prach24576 | + memmove(prach,prach+(24576<<2),(Ncp<<2)); + // here we have | Prefix | Prach24576 | Prach24576 | + prach_len = (24576*2)+Ncp; + } else if (prach_fmt_id == 2) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | empty24576 | empty24576 | empty24576 | + memmove(prach2+(24576<<1),prach2,(24576<<2)); + // here we have | empty | Prach24576 | Prach24576 | empty24576 | empty24576 | + memmove(prach2+(24576<<2),prach2,(24576<<3)); + // here we have | empty | Prach24576 | Prach24576 | Prach24576 | Prach24576 | + memmove(prach,prach+(24576<<3),(Ncp<<2)); + // here we have | Prefix | Prach24576 | Prach24576 | Prach24576 | Prach24576 | + prach_len = (24576*4)+Ncp; + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s + idft(IDFT_6144,prachF,prach2,1); + // here we have | empty | Prach6144 | empty6144 | empty6144 | empty6144 | + memmove(prach2+(6144<<1),prach2,(6144<<2)); + // here we have | empty | Prach6144 | Prach6144 | empty6144 | empty6144 | + memmove(prach2+(6144<<2),prach2,(6144<<3)); + // here we have | empty | Prach6144 | Prach6144 | Prach6144 | Prach6144 | + memmove(prach,prach+(6144<<3),(Ncp<<2)); + // here we have | Prefix | Prach6144 | Prach6144 | Prach6144 | Prach6144 | + prach_len = (6144*4)+Ncp; + } + } else { // short PRACH sequence + if (use_extended_prach_prefix) + Ncp += 16; // 16*kappa, kappa=1 for 30.72Msps + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_fmt_id == 9) { + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | + prach_len = (1024*1)+Ncp; + } else if (prach_fmt_id == 4 || prach_fmt_id == 7) { + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | + prach_len = (1024*2)+Ncp; + } else if (prach_fmt_id == 5) { // 4x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1)*6,prach2,(1024<<2)*6); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*12)+Ncp; + } + } + break; + + case 61440: // full sampling @ 61.44 Ms/s + Ncp = Ncp*2; // to account for 61.44 Ms/s + // This is after cyclic prefix + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { //24576 samples @ 30.72 Ms/s, 49152 samples @ 61.44 Ms/s idft(IDFT_49152,prachF,prach2,1); @@ -444,7 +784,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(49152<<3),(Ncp<<2)); // here we have |Prefix | Prach49152 | Prach49152| Prach49152 | Prach49152 prach_len = (49152*4)+Ncp; - } else if (prach_fmt_id == 3) { // //6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s idft(IDFT_12288,prachF,prach2,1); memmove(prach2+(12288<<1),prach2,(12288<<2)); // here we have |empty | Prach12288 | Prach12288| empty12288 | empty12288 @@ -455,21 +795,20 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (12288*4)+Ncp; } } else { // short PRACH sequence - if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) { - Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + if (use_extended_prach_prefix) + Ncp+=32; // 16*kappa, kappa=2 for 61.44Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | - if (prach_fmt_id != 7) { + if (prach_fmt_id != 9) { memmove(prach2+(2048<<1),prach2,(2048<<2)); prach_len = (2048*2)+Ncp; } else prach_len = (2048*1)+Ncp; memmove(prach,prach+(2048<<1),(Ncp<<2)); // here we have |Prefix | Prach2048 | Prach2048 (if ! 0xc0) | - } else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 6x2048 - Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 5) { // 6x2048 idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); @@ -479,9 +818,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(2048<<1),(Ncp<<2)); // here we have |Prefix | Prach2048 | prach_len = (2048*4)+Ncp; - } else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x2048 - Ncp+=32; - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 6) { // 6x2048 idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); @@ -493,9 +830,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(2048<<1),(Ncp<<2)); // here we have |Prefix | Prach2048 | prach_len = (2048*6)+Ncp; - } else if (prach_fmt_id == 6) { // 12x2048 - Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 8) { // 12x2048 idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); @@ -511,7 +846,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (2048*12)+Ncp; } } - } else { // threequarter sampling @ 46.08 Ms/s + break; + + case 46080: // threequarter sampling @ 46.08 Ms/s Ncp = (Ncp*3)/2; prach2 = prach+(Ncp<<1); if (prach_sequence_length == 0){ @@ -548,12 +885,13 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (9216*4)+Ncp; } } else { // short sequence - if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) { - Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + if (use_extended_prach_prefix) + Ncp+=24; // 16*kappa, kappa=1.5 for 46.08Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | - if (prach_fmt_id != 7) { + if (prach_fmt_id != 9) { memmove(prach2+(1536<<1),prach2,(1536<<2)); prach_len = (1536*2)+Ncp; } else prach_len = (1536*1)+Ncp; @@ -561,10 +899,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(1536<<1),(Ncp<<2)); // here we have |Prefix | Prach1536 | Prach1536 (if ! 0xc0) | - } else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 6x1536 - - Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 5) { // 6x1536 idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); @@ -574,9 +909,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(1536<<1),(Ncp<<2)); // here we have |Prefix | Prach1536 | prach_len = (1536*4)+Ncp; - } else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x1536 - Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 6) { // 6x1536 idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); @@ -588,9 +921,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(1536<<1),(Ncp<<2)); // here we have |Prefix | Prach1536 | prach_len = (1536*6)+Ncp; - } else if (prach_fmt_id == 6) { // 12x1536 - Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 8) { // 12x1536 idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); @@ -606,11 +937,12 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (1536*12)+Ncp; } } - } - } else if (fp->N_RB_UL <= 273) {// 92.16 or 122.88 Ms/s - if (fp->threequarter_fs == 0) { // full sampling @ 122.88 Ms/s - Ncp<<=2; - prach2 = prach+(Ncp<<1); + break; + + case 122880: // full sampling @ 122.88 Ms/s + Ncp<<=2; //to account for 122.88Mbps + // This is after cyclic prefix + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { //24576 samples @ 30.72 Ms/s, 98304 samples @ 122.88 Ms/s idft(IDFT_98304,prachF,prach2,1); @@ -645,20 +977,19 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (24576*4)+Ncp; } } else { // short sequence - if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) { - Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + if (use_extended_prach_prefix) + Ncp+=64; // 16*kappa, kappa=4 for 122.88Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | - if (prach_fmt_id != 7) { + if (prach_fmt_id != 9) { memmove(prach2+(4096<<1),prach2,(4096<<2)); prach_len = (4096*2)+Ncp; } else prach_len = (4096*1)+Ncp; memmove(prach,prach+(4096<<1),(Ncp<<2)); // here we have |Prefix | Prach4096 | Prach4096 (if ! 0xc0) | - } else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 4x4096 - Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 5) { // 4x4096 idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); @@ -668,9 +999,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(4096<<1),(Ncp<<2)); // here we have |Prefix | Prach4096 | prach_len = (4096*4)+Ncp; - } else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x4096 - Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 6) { // 6x4096 idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); @@ -682,9 +1011,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(4096<<1),(Ncp<<2)); // here we have |Prefix | Prach4096 | prach_len = (4096*6)+Ncp; - } else if (prach_fmt_id == 6) { // 12x4096 - Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 8) { // 12x4096 idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); @@ -700,9 +1027,11 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (4096*12)+Ncp; } } - } else { // three quarter sampling @ 92.16 Ms/s - Ncp = (Ncp*3); - prach2 = prach+(Ncp<<1); + break; + + case 92160: // three quarter sampling @ 92.16 Ms/s + Ncp = (Ncp*3); //to account for 92.16 Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { idft(IDFT_73728,prachF,prach2,1); @@ -737,20 +1066,19 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (18432*4)+Ncp; } } else { // short sequence - if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) { - Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + if (use_extended_prach_prefix) + Ncp+=48; // 16*kappa, kappa=3 for 92.16Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | - if (prach_fmt_id != 7) { + if (prach_fmt_id != 9) { memmove(prach2+(3072<<1),prach2,(3072<<2)); prach_len = (3072*2)+Ncp; } else prach_len = (3072*1)+Ncp; - memmove(prach,prach+(3072<<1),(Ncp<<2)); - // here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) | - } else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x3072 - Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + memmove(prach,prach+(3072<<1),(Ncp<<2)); + // here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) | + } else if (prach_fmt_id == 6) { // 6x3072 idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); @@ -762,9 +1090,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(3072<<1),(Ncp<<2)); // here we have |Prefix | Prach3072 | prach_len = (3072*6)+Ncp; - } else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 4x3072 - Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + } else if (prach_fmt_id == 5) { // 4x3072 idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); @@ -775,8 +1101,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach3072 | prach_len = (3072*4)+Ncp; } else if (prach_fmt_id == 6) { // 12x3072 - Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); @@ -792,44 +1116,24 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (3072*12)+Ncp; } } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } } #ifdef NR_PRACH_DEBUG - LOG_I(PHY, "PRACH [UE %d] N_RB_UL %d prach_start %d, prach_len %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", Mod_id, + LOG_I(PHY, "PRACH [UE %d] N_RB_UL %d prach_start %d, prach_len %d\n", Mod_id, fp->N_RB_UL, prach_start, - prach_len, - ue->rx_offset, - ue->hw_timing_advance, - ue->N_TA_offset); + prach_len); #endif - #if defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - int j, overflow = prach_start + prach_len - NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe; - - #ifdef NR_PRACH_DEBUG - LOG_I( PHY, "PRACH [UE %d] overflow = %d\n", Mod_id, overflow); - #endif - - // prach_start=414.730, overflow=-39470 prach_len=6600 fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME 460.800 prach_start+prach_len 421.330 fp->samples_per_subframe 46080 - - // from prach_start=414.730 to prach_start+prach_len 421.330 - for (i = prach_start, j = 0; i < min(fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME, prach_start + prach_len); i++, j++) { - ((int16_t*)ue->common_vars.txdata[0])[2*i] = prach[2*j]; - ((int16_t*)ue->common_vars.txdata[0])[2*i+1] = prach[2*j+1]; - } - - for (i = 0; i < overflow; i++,j++) { - ((int16_t*)ue->common_vars.txdata[0])[2*i] = prach[2*j]; - ((int16_t*)ue->common_vars.txdata[0])[2*i+1] = prach[2*j+1]; - } - #else // simulators - for (i=0; icommon_vars.txdata[0][prach_start]))[2*i] = prach[2*i]; - ((int16_t*)(&ue->common_vars.txdata[0][prach_start]))[2*i+1] = prach[2*i+1]; - } - #endif + for (i=0; icommon_vars.txdata[0][prach_start]))[2*i] = prach[2*i]; + ((int16_t*)(&ue->common_vars.txdata[0][prach_start]))[2*i+1] = prach[2*i+1]; + } //printf("----------------------\n"); //for(int ii = prach_start; ii<2*(prach_start + prach_len); ii++){ diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index ee957965cd..3cb002f9e1 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -471,7 +471,7 @@ int nr_dlsch_64qam_64qam_llr(NR_DL_FRAME_PARMS *frame_parms, @param beamforming_mode beamforming mode */ int32_t nr_dlsch_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, + int32_t *rxdataF_comp, int16_t *dlsch_llr, uint8_t symbol, uint32_t len, @@ -505,14 +505,13 @@ int32_t nr_dlsch_qpsk_llr_SIC(NR_DL_FRAME_PARMS *frame_parms, uint32_t rb_alloc); void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, + int32_t *rxdataF_comp, int16_t *dlsch_llr, - int32_t **dl_ch_mag, + int32_t *dl_ch_mag, uint8_t symbol, - uint32_t len, + uint32_t len, uint8_t first_symbol_flag, uint16_t nb_rb, - int16_t **llr32p, uint8_t beamforming_mode); /** \brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms @@ -553,17 +552,27 @@ void dlsch_64qam_llr_SIC(NR_DL_FRAME_PARMS *frame_parms, uint32_t rb_alloc); void nr_dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, + int32_t *rxdataF_comp, int16_t *dlsch_llr, - int32_t **dl_ch_mag, - int32_t **dl_ch_magb, + int32_t *dl_ch_mag, + int32_t *dl_ch_magb, uint8_t symbol, - uint32_t len, + uint32_t len, uint8_t first_symbol_flag, uint16_t nb_rb, - uint32_t llr_offset, uint8_t beamforming_mode); +void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms, + int32_t *rxdataF_comp, + int16_t *dlsch_llr, + int32_t *dl_ch_mag, + int32_t *dl_ch_magb, + int32_t *dl_ch_magr, + uint8_t symbol, + uint32_t len, + uint8_t first_symbol_flag, + uint16_t nb_rb, + uint8_t beamforming_mode); /** \fn dlsch_siso(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, @@ -674,11 +683,8 @@ void dlsch_detection_mrc_TM34(NR_DL_FRAME_PARMS *frame_parms, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, - uint16_t pmi, - uint8_t *pmi_ext, uint32_t *rb_alloc, uint8_t symbol, - uint8_t subframe, NR_DL_FRAME_PARMS *frame_parms) \brief This function extracts the received resource blocks, both channel estimates and data symbols, for the current allocation and for single antenna eNB transmission. @@ -686,78 +692,61 @@ void dlsch_detection_mrc_TM34(NR_DL_FRAME_PARMS *frame_parms, @param dl_ch_estimates Channel estimates of current slot @param rxdataF_ext FFT output for RBs in this allocation @param dl_ch_estimates_ext Channel estimates for RBs in this allocation - @param pmi subband Precoding matrix indicator - @param pmi_ext Extracted PMI for chosen RBs @param rb_alloc RB allocation vector @param symbol Symbol to extract - @param subframe Subframe number - @param vrb_type Flag to indicate distributed VRB type - @param high_speed_flag + @param n_dmrs_cdm_groups @param frame_parms Pointer to frame descriptor */ -/*uint16_t nr_dlsch_extract_rbs_single(int32_t **rxdataF, - int32_t **dl_ch_estimates, - int32_t **rxdataF_ext, - int32_t **dl_ch_estimates_ext, - uint16_t pmi, - uint8_t *pmi_ext, - uint32_t *rb_alloc, - uint8_t symbol, - uint8_t subframe, - uint32_t high_speed_flag, - NR_DL_FRAME_PARMS *frame_parms);*/ - unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, int **dl_ch_estimates, int **rxdataF_ext, int **dl_ch_estimates_ext, - unsigned short pmi, - unsigned char *pmi_ext, unsigned char symbol, - uint8_t pilots, - unsigned short start_rb, - unsigned short nb_pdsch_rb, - unsigned char nr_tti_rx, - uint32_t high_speed_flag, - NR_DL_FRAME_PARMS *frame_parms); + uint8_t pilots, + uint8_t config_type, + unsigned short start_rb, + unsigned short nb_rb_pdsch, + uint8_t n_dmrs_cdm_groups, + NR_DL_FRAME_PARMS *frame_parms, + uint16_t dlDmrsSymbPos); -/** \fn dlsch_extract_rbs_dual(int32_t **rxdataF, +/** \fn dlsch_extract_rbs_multiple(int32_t **rxdataF, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, - uint16_t pmi, - uint8_t *pmi_ext, - uint32_t *rb_alloc, - uint8_t symbol, - NR_DL_FRAME_PARMS *frame_parms) + unsigned char symbol + uint8_t pilots, + uint8_t config_type, + unsigned short start_rb, + unsigned short nb_rb_pdsch, + uint8_t n_dmrs_cdm_groups, + uint8_t Nl, + NR_DL_FRAME_PARMS *frame_parms, + uint16_t dlDmrsSymbPos) \brief This function extracts the received resource blocks, both channel estimates and data symbols, - for the current allocation and for dual antenna eNB transmission. + for the current allocation and for multiple layer antenna gNB transmission. @param rxdataF Raw FFT output of received signal @param dl_ch_estimates Channel estimates of current slot @param rxdataF_ext FFT output for RBs in this allocation @param dl_ch_estimates_ext Channel estimates for RBs in this allocation - @param pmi subband Precoding matrix indicator - @param pmi_ext Extracted PMI for chosen RBs - @param rb_alloc RB allocation vector + @param Nl nb of antenna layers @param symbol Symbol to extract - @param subframe Subframe index - @param high_speed_flag + @param n_dmrs_cdm_groups @param frame_parms Pointer to frame descriptor */ -unsigned short nr_dlsch_extract_rbs_dual(int **rxdataF, - int **dl_ch_estimates, - int **rxdataF_ext, - int **dl_ch_estimates_ext, - unsigned short pmi, - unsigned char *pmi_ext, - unsigned char symbol, - uint8_t pilots, - unsigned short start_rb, - unsigned short nb_rb_pdsch, - unsigned char nr_tti_rx, - uint32_t high_speed_flag, - NR_DL_FRAME_PARMS *frame_parms, - MIMO_mode_t mimo_mode); +unsigned short nr_dlsch_extract_rbs_multiple(int **rxdataF, + int **dl_ch_estimates, + int **rxdataF_ext, + int **dl_ch_estimates_ext, + unsigned char symbol, + uint8_t pilots, + uint8_t config_type, + unsigned short start_rb, + unsigned short nb_rb_pdsch, + uint8_t n_dmrs_cdm_groups, + uint8_t Nl, + NR_DL_FRAME_PARMS *frame_parms, + uint16_t dlDmrsSymbPos); /** \fn dlsch_extract_rbs_TM7(int32_t **rxdataF, int32_t **dl_bf_ch_estimates, @@ -809,11 +798,13 @@ void nr_dlsch_channel_compensation(int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, int32_t **dl_ch_mag, int32_t **dl_ch_magb, + int32_t **dl_ch_magr, int32_t **rxdataF_comp, - int32_t **rho, + int32_t ***rho, NR_DL_FRAME_PARMS *frame_parms, + uint8_t nb_aatx, uint8_t symbol, - uint8_t start_symbol, + int length, uint8_t first_symbol_flag, uint8_t mod_order, uint16_t nb_rb, @@ -825,7 +816,7 @@ void nr_dlsch_channel_compensation_core(int **rxdataF_ext, int **dl_ch_mag, int **dl_ch_magb, int **rxdataF_comp, - int **rho, + int ***rho, unsigned char n_tx, unsigned char n_rx, unsigned char mod_order, @@ -896,6 +887,17 @@ void nr_dlsch_channel_level_median(int **dl_ch_estimates_ext, int length, int start_point); +void nr_dlsch_detection_mrc(int **rxdataF_comp, + int ***rho, + int **dl_ch_mag, + int **dl_ch_magb, + int **dl_ch_magr, + short n_tx, + short n_rx, + unsigned char symbol, + unsigned short nb_rb, + int length); + void nr_dlsch_detection_mrc_core(int **rxdataF_comp, int **rxdataF_comp_i, int **rho, @@ -969,6 +971,7 @@ void dlsch_channel_compensation_TM34(NR_DL_FRAME_PARMS *frame_parms, */ void nr_dlsch_channel_level(int **dl_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, + uint8_t n_tx, int32_t *avg, uint8_t symbol, uint32_t len, @@ -1000,9 +1003,12 @@ void dlsch_channel_level_TM7(int32_t **dl_bf_ch_estimates_ext, void nr_dlsch_scale_channel(int32_t **dl_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, + uint8_t n_tx, + uint8_t n_rx, NR_UE_DLSCH_t **dlsch_ue, uint8_t symbol, - uint8_t start_symbol, + uint8_t start_symbol, + uint32_t len, uint16_t nb_rb); /** \brief This is the top-level entry point for DLSCH decoding in UE. It should be replicated on several @@ -1017,7 +1023,7 @@ void nr_dlsch_scale_channel(int32_t **dl_ch_estimates_ext, @param lte_frame_parms Pointer to frame descriptor @param dlsch Pointer to DLSCH descriptor @param frame Frame number - @param subframe Subframe number + @param nr_slot_rx Slot number @param num_pdcch_symbols Number of PDCCH symbols @param is_crnti indicates if PDSCH belongs to a CRNTI (necessary for parallelizing decoding threads) @param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used @@ -1025,18 +1031,21 @@ void nr_dlsch_scale_channel(int32_t **dl_ch_estimates_ext, */ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, + UE_nr_rxtx_proc_t *proc, + int eNB_id, short *dlsch_llr, NR_DL_FRAME_PARMS *frame_parms, NR_UE_DLSCH_t *dlsch, NR_DL_UE_HARQ_t *harq_process, uint32_t frame, - uint16_t nb_symb_sch, - uint8_t nr_tti_rx, + uint16_t nb_symb_sch, + uint8_t nr_slot_rx, uint8_t harq_pid, uint8_t is_crnti, uint8_t llr8_flag); -int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, +int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, + NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS* frame_parms, uint8_t harq_pid, unsigned int G); @@ -1074,27 +1083,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, */ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, - uint8_t harq_pid, uint8_t slot, - uint8_t thread_id, - uint8_t gNB_id, - NR_DL_FRAME_PARMS *frame_parms); - - - -uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, - UE_nr_rxtx_proc_t *proc, - int eNB_id, - short *dlsch_llr, - NR_DL_FRAME_PARMS *frame_parms, - NR_UE_DLSCH_t *dlsch, - NR_DL_UE_HARQ_t *harq_process, - uint32_t frame, - uint16_t nb_symb_sch, - uint8_t nr_tti_rx, - uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag); + NR_DL_FRAME_PARMS *frame_parms, + uint8_t Nl); void *nr_dlsch_decoding_2thread0(void *arg); @@ -1113,8 +1104,8 @@ uint32_t dlsch_decoding_emul(PHY_VARS_NR_UE *phy_vars_ue, uint8_t eNB_id); int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, - uint32_t frame, - uint32_t slot); + UE_nr_rxtx_proc_t *proc, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); /*! \brief Extract PSS and SSS resource elements @@ -1160,18 +1151,16 @@ int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uin \returns number of tx antennas or -1 if error */ int nr_rx_pbch( PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - NR_UE_PBCH *nr_ue_pbch_vars, - NR_DL_FRAME_PARMS *frame_parms, - uint8_t eNB_id, - uint8_t i_ssb, - MIMO_mode_t mimo_mode, - uint32_t high_speed_flag); + UE_nr_rxtx_proc_t *proc, + NR_UE_PBCH *nr_ue_pbch_vars, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t eNB_id, + uint8_t i_ssb, + MIMO_mode_t mimo_mode); int nr_pbch_detection(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, - int pbch_initial_symbol, - runmode_t mode); + int pbch_initial_symbol); uint16_t rx_pbch_emul(PHY_VARS_NR_UE *phy_vars_ue, uint8_t eNB_id, @@ -1297,8 +1286,8 @@ uint8_t get_transmission_mode(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti); */ uint32_t conv_nprb(uint8_t ra_header,uint32_t rb_alloc,int N_RB_DL); -int adjust_G(NR_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe); -int adjust_G2(NR_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol); +//int adjust_G(NR_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe); +//int adjust_G2(NR_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol); #ifndef modOrder @@ -1324,16 +1313,6 @@ uint8_t I_TBS2I_MCS(uint8_t I_TBS); uint8_t SE2I_TBS(float SE, uint8_t N_PRB, uint8_t symbPerRB); -/** \brief This function generates the sounding reference symbol (SRS) for the uplink according to 36.211 v8.6.0. If IFFT_FPGA is defined, the SRS is quantized to a QPSK sequence. - @param frame_parms LTE DL Frame Parameters - @param soundingrs_ul_config_dedicated Dynamic configuration from RRC during Connection Establishment - @param txdataF pointer to the frequency domain TX signal - @returns 0 on success*/ -int generate_srs(NR_DL_FRAME_PARMS *frame_parms, - SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated, - int *txdataF, - int16_t amp, - uint32_t subframe); /*! @@ -1363,12 +1342,6 @@ int32_t generate_drs_pusch(PHY_VARS_NR_UE *phy_vars_ue, uint32_t nb_rb, uint8_t ant); -/*! - \brief This function initializes the Group Hopping, Sequence Hopping and nPRS sequences for PUCCH/PUSCH according to 36.211 v8.6.0. It should be called after configuration of UE (reception of SIB2/3) and initial configuration of eNB (or after reconfiguration of cell-specific parameters). - @param frame_parms Pointer to a NR_DL_FRAME_PARMS structure (eNB or UE)*/ -void init_ul_hopping(NR_DL_FRAME_PARMS *frame_parms); - - /*! \brief This function implements the initialization of paging parameters for UE (See Section 7, 36.304).It must be called after setting IMSImod1024 during UE startup and after receiving SIB2 @param ue Pointer to UE context @@ -1433,8 +1406,6 @@ double sinr_eff_cqi_calc(PHY_VARS_NR_UE *phy_vars_ue, uint8_t sinr2cqi(double sinr,uint8_t trans_mode); -int dump_dci(NR_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci); - int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, char* buffer, int length, runmode_t mode, int input_level_dBm); void init_transport_channels(uint8_t); @@ -1451,28 +1422,37 @@ void generate_RIV_tables(void); */ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, - runmode_t mode, - int n_frames); - + int n_frames, + int sa, + int dlsch_parallel); /*! - \brief Encoding of PUSCH/ACK/RI/ACK from 36-212. - @param a Pointer to ulsch SDU - @param frame_parms Pointer to Frame parameters - @param ulsch Pointer to ulsch descriptor - @param harq_pid HARQ process ID - @param tmode Transmission mode (1-7) - @param control_only_flag Generate PUSCH with control information only - @param Nbundled Parameter for ACK/NAK bundling (36.213 Section 7.3) + \brief This function gets the carrier frequencies either from FP or command-line-set global variables, depending on the availability of the latter + @param fp Pointer to frame params + @param dl_Carrier Pointer to DL carrier to be set + @param ul_Carrier Pointer to UL carrier to be set */ -uint32_t ulsch_encoding(uint8_t *a, - PHY_VARS_NR_UE *phy_vars_ue, - uint8_t harq_pid, - uint8_t eNB_id, - uint8_t subframe_rx, - uint8_t tmode, - uint8_t control_only_flag, - uint8_t Nbundled); +void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue, + uint64_t *dl_Carrier, + uint64_t *ul_Carrier); + +/*! + \brief This function sets the OAI RF card rx/tx params + @param openair0_cfg Pointer OAI config for a specific card + @param tx_gain_off Tx gain offset + @param rx_gain_off Rx gain offset + @param ul_Carrier UL carrier to be set + @param dl_Carrier DL carrier to be set + @param freq_offset Freq offset to be set +*/ +void nr_rf_card_config_gain(openair0_config_t *openair0_cfg, + double rx_gain_off); + +void nr_rf_card_config_freq(openair0_config_t *openair0_cfg, + uint64_t ul_Carrier, + uint64_t dl_Carrier, + int freq_offset); + void print_CQI(void *o,UCI_format_t uci_format,uint8_t eNB_id,int N_RB_DL); @@ -1515,18 +1495,11 @@ int get_nCCE_offset_l1(int *CCE_table, const unsigned short rnti, const unsigned char subframe); -uint16_t get_nCCE(uint8_t num_pdcch_symbols,NR_DL_FRAME_PARMS *frame_parms,uint8_t mi); -uint16_t get_nquad(uint8_t num_pdcch_symbols,NR_DL_FRAME_PARMS *frame_parms,uint8_t mi); - -uint8_t get_mi(NR_DL_FRAME_PARMS *frame,uint8_t subframe); +//uint8_t get_mi(NR_DL_FRAME_PARMS *frame,uint8_t subframe); uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int subframe); -uint8_t get_num_pdcch_symbols(uint8_t num_dci,DCI_ALLOC_t *dci_alloc,NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe); - -void pdcch_interleaving(NR_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **wbar,uint8_t n_symbols_pdcch,uint8_t mi); - void nr_pdcch_unscrambling(int16_t *z, uint16_t scrambling_RNTI, uint32_t length, @@ -1541,7 +1514,6 @@ void dlsch_unscrambling(NR_DL_FRAME_PARMS *frame_parms, uint8_t q, uint8_t Ns); -void init_ncs_cell(NR_DL_FRAME_PARMS *frame_parms,uint8_t ncs_cell[20][7]); void generate_pucch1x(int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, @@ -1589,7 +1561,7 @@ void init_ulsch_power_LUT(void); @param subframe subframe index to check @returns 0 on success */ -int is_prach_subframe(NR_DL_FRAME_PARMS *frame_parms,frame_t frame, uint8_t subframe); +//int is_prach_subframe(NR_DL_FRAME_PARMS *frame_parms,frame_t frame, uint8_t subframe); /*! \brief Generate PRACH waveform @@ -1655,8 +1627,6 @@ void init_scrambling_lut(void); @param frame_parms Pointer to frame parameters @returns 1 if subframe is for MBSFN */ -int is_pmch_subframe(frame_t frame, int subframe, NR_DL_FRAME_PARMS *frame_parms); - uint8_t is_not_pilot(uint8_t pilots, uint8_t re, uint8_t nushift, uint8_t use2ndpilots); uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode); @@ -1693,13 +1663,12 @@ uint8_t get_prach_prb_offset(NR_DL_FRAME_PARMS *frame_parms, uint8_t n_ra_prboffset, uint8_t tdd_mapindex, uint16_t Nf); - -uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset); +#include uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, - int frame, - int slot, - fapi_nr_dci_indication_t *dci_ind); + UE_nr_rxtx_proc_t *proc, + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); /** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation. It performs @@ -1714,39 +1683,28 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, @param eNB_id eNb index (Nid1) 0,1,2 @param eNB_id_i Interfering eNB index (Nid1) 0,1,2, or 3 in case of MU-MIMO IC receiver @param frame Frame number - @param nr_tti_rx Subframe number + @param nr_slot_rx Slot number @param symbol Symbol on which to act (within sub-frame) @param first_symbol_flag set to 1 on first DLSCH symbol @param rx_type. rx_type=RX_IC_single_stream will enable interference cancellation of a second stream when decoding the first stream. In case of TM1, 2, 5, and this can cancel interference from a neighbouring cell given by eNB_id_i. In case of TM5, eNB_id_i should be set to n_connected_eNB to perform multi-user interference cancellation. In case of TM3, eNB_id_i should be set to eNB_id to perform co-channel interference cancellation; this option should be used together with an interference cancellation step [...]. In case of TM3, if rx_type=RX_IC_dual_stream, both streams will be decoded by applying the IC single stream receiver twice. @param i_mod Modulation order of the interfering stream */ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, PDSCH_t type, unsigned char eNB_id, unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference uint32_t frame, - uint8_t nr_tti_rx, + uint8_t nr_slot_rx, unsigned char symbol, unsigned char first_symbol_flag, RX_type_t rx_type, unsigned char i_mod, unsigned char harq_pid); -uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, - short *dlsch_llr, - NR_DL_FRAME_PARMS *frame_parms, - NR_UE_DLSCH_t *dlsch, - NR_DL_UE_HARQ_t *harq_process, - uint32_t frame, - uint16_t nb_symb_sch, - uint8_t nr_tti_rx, - uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag); - int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe); -void *dlsch_thread(void *arg); +void dump_nrdlsch(PHY_VARS_NR_UE *ue,uint8_t gNB_id,uint8_t nr_slot_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid); /**@}*/ #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index d1dd0f785b..b4ee4f5b41 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -38,10 +38,10 @@ //#include "PHY/defs_nr_UE.h" #include "../NR_TRANSPORT/nr_transport_common_proto.h" -#ifndef STANDALONE_COMPILE +/*#ifndef STANDALONE_COMPILE #include "UTIL/LISTS/list.h" #endif - +*/ #include "openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h" @@ -56,34 +56,6 @@ typedef enum { RETRANSMISSION_HARQ } harq_result_t; -//#if defined(UPGRADE_RAT_NR) -#if 1 -typedef struct { - /// HARQ process id - uint8_t harq_id; - /// HARQ rx status - harq_result_t rx_status; - /// ACK bits (after decoding) 0:NACK / 1:ACK / 2:DTX - uint8_t ack; - /// send status (for PUCCH) - uint8_t send_harq_status; - /// nCCE (for PUCCH) - uint8_t nCCE; - /// DAI value detected from DCI1/1a/1b/1d/2/2a/2b/2c. 0xff indicates not touched - uint8_t vDAI_DL; - /// DAI value detected from DCI0/4. 0xff indicates not touched - uint8_t vDAI_UL; - /// allow to define pucch parameters TS 38.213 9.2.3 UE procedure for reporting HARQ-ACK - uint8_t pucch_resource_indicator; - /// slot on which feedback ack should be send to network - uint16_t slot_for_feedback_ack; - /// index of a first CCE for the PDCCH reception - uint8_t n_CCE; - /// number of CCEs in a control resource set of a PDCCH reception conveying DCI format 1_0 - uint8_t N_CCE; -} NR_UE_HARQ_STATUS_t; -#endif - typedef struct { /// NDAPI struct for UE nfapi_nr_ue_pusch_pdu_t pusch_pdu; @@ -105,6 +77,8 @@ typedef struct { uint8_t O_ACK; /// Index of current HARQ round for this ULSCH uint8_t round; + /// Last Ndi for this harq process + uint8_t ndi; /// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8) unsigned char *a; /// Pointer to the payload + CRC @@ -139,6 +113,10 @@ typedef struct { uint32_t num_of_mod_symbols; // decode phich uint8_t decode_phich; + // Encoder BG + uint8_t BG; + // LDPC lifting size + uint32_t Z; } NR_UL_UE_HARQ_t; typedef struct { @@ -177,9 +155,9 @@ typedef struct { /// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14) uint8_t b_tilde[MAX_NUM_NR_CHANNEL_BITS]; /// Modulated "d"-sequences (for definition see 36-211 V8.6 2009-03, p.14) - uint32_t d_mod[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); + int32_t d_mod[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); /// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4) - uint32_t y[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); + int32_t y[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); /* /// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27) uint8_t q[MAX_CQI_PAYLOAD]; @@ -228,8 +206,8 @@ typedef struct { } NR_UE_ULSCH_t; typedef struct { - /// Indicator of first transmission - uint8_t first_tx; + /// Indicator of first reception + uint8_t first_rx; /// Last Ndi received for this process on DCI (used for C-RNTI only) uint8_t DCINdi; /// DLSCH status flag indicating @@ -313,7 +291,20 @@ typedef struct { /// codeword this transport block is mapped to uint8_t codeword; /// HARQ-ACKs - NR_UE_HARQ_STATUS_t harq_ack; + uint8_t ack; + /// PTRS Frequency Density + uint8_t PTRSFreqDensity; + /// PTRS Time Density + uint8_t PTRSTimeDensity; + uint8_t PTRSPortIndex ; + uint8_t nEpreRatioOfPDSCHToPTRS; + uint8_t PTRSReOffset; + /// bit mask of PT-RS ofdm symbol indicies + uint16_t ptrs_symbols; + // PTRS symbol index, to be updated every PTRS symbol within a slot. + uint8_t ptrs_symbol_index; + /// PDU BITMAP + uint16_t pduBitmap; } NR_DL_UE_HARQ_t; typedef struct { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c new file mode 100644 index 0000000000..6530dd9512 --- /dev/null +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c @@ -0,0 +1,113 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/NR_UE_TRANSPORT/nr_ue_rf_config.c +* \brief Functional helpers to configure the RF boards at UE side +* \author Guido Casati +* \date 2020 +* \version 0.1 +* \company Fraunhofer IIS +* \email: guido.casati@iis.fraunhofer.de +*/ + +#include "PHY/defs_nr_UE.h" +#include "PHY/phy_extern_nr_ue.h" +#include "nr_transport_proto_ue.h" +#include "executables/softmodem-common.h" + +void nr_get_carrier_frequencies(PHY_VARS_NR_UE *ue, uint64_t *dl_carrier, uint64_t *ul_carrier){ + + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; + if (ue->if_freq!=0) { + *dl_carrier = ue->if_freq; + *ul_carrier = *dl_carrier + ue->if_freq_off; + } + else{ + *dl_carrier = fp->dl_CarrierFreq; + *ul_carrier = fp->ul_CarrierFreq; + } +} + + +void nr_rf_card_config_gain(openair0_config_t *openair0_cfg, + double rx_gain_off){ + + uint8_t mod_id = 0; + uint8_t cc_id = 0; + PHY_VARS_NR_UE *ue = PHY_vars_UE_g[mod_id][cc_id]; + int rf_chain = ue->rf_map.chain; + double rx_gain = ue->rx_total_gain_dB; + double tx_gain = ue->tx_total_gain_dB; + + for (int i = rf_chain; i < rf_chain + 4; i++) { + + if (tx_gain) + openair0_cfg->tx_gain[i] = tx_gain; + if (rx_gain) + openair0_cfg->rx_gain[i] = rx_gain - rx_gain_off; + + openair0_cfg->autocal[i] = 1; + + if (i < openair0_cfg->rx_num_channels) { + LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f\n", + i, + rf_chain, + openair0_cfg->tx_gain[i], + openair0_cfg->rx_gain[i]); + } + + } +} + +void nr_rf_card_config_freq(openair0_config_t *openair0_cfg, + uint64_t ul_carrier, + uint64_t dl_carrier, + int freq_offset){ + + uint8_t mod_id = 0; + uint8_t cc_id = 0; + PHY_VARS_NR_UE *ue = PHY_vars_UE_g[mod_id][cc_id]; + int rf_chain = ue->rf_map.chain; + + for (int i = rf_chain; i < rf_chain + 4; i++) { + + if (i < openair0_cfg->rx_num_channels) + openair0_cfg->rx_freq[i + rf_chain] = dl_carrier + freq_offset; + else + openair0_cfg->rx_freq[i] = 0.0; + + if (itx_num_channels) + openair0_cfg->tx_freq[i] = ul_carrier + freq_offset; + else + openair0_cfg->tx_freq[i] = 0.0; + + openair0_cfg->autocal[i] = 1; + + if (i < openair0_cfg->rx_num_channels) { + LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_freq %f Hz, rx_freq %f Hz\n", + i, + rf_chain, + openair0_cfg->tx_freq[i], + openair0_cfg->rx_freq[i]); + } + + } +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 4b36f91e69..945dc51673 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -39,8 +39,9 @@ #include "PHY/CODING/nrLDPC_extern.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include +//#define DEBUG_ULSCH_CODING void free_nr_ue_ulsch(NR_UE_ULSCH_t **ulschptr,unsigned char N_RB_UL) @@ -57,7 +58,7 @@ void free_nr_ue_ulsch(NR_UE_ULSCH_t **ulschptr,unsigned char N_RB_UL) if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } @@ -114,7 +115,7 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL, if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } uint16_t ulsch_bytes = a_segments*1056; // allocated bytes per segment @@ -201,7 +202,6 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL, for (i=0; iharq_processes[i]->round=0; } - return(ulsch); } } @@ -214,23 +214,24 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL, } -int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, +int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, + NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS* frame_parms, uint8_t harq_pid, unsigned int G) { + start_meas(&ue->ulsch_encoding_stats); /////////////////////////parameters and variables declaration///////////////////////// /////////// unsigned int crc; NR_UL_UE_HARQ_t *harq_process; uint16_t nb_rb ; - uint32_t A, Z, F; + uint32_t A, F; uint32_t *pz; uint8_t mod_order; uint16_t Kr,r; uint32_t r_offset; - uint8_t BG; uint32_t E,Kb; uint8_t Ilbrm; uint32_t Tbslbrm; @@ -247,18 +248,17 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, crc = 1; harq_process = ulsch->harq_processes[harq_pid]; nb_rb = harq_process->pusch_pdu.rb_size; - A = harq_process->pusch_pdu.pusch_data.tb_size; - pz = &Z; + A = harq_process->pusch_pdu.pusch_data.tb_size*8; + pz = &harq_process->Z; mod_order = nr_get_Qm_ul(harq_process->pusch_pdu.mcs_index, harq_process->pusch_pdu.mcs_table); R = nr_get_code_rate_ul(harq_process->pusch_pdu.mcs_index, harq_process->pusch_pdu.mcs_table); Kr=0; r_offset=0; - BG = 1; F=0; Ilbrm = 0; Tbslbrm = 950984; //max tbs Coderate = 0.0; - + trace_NRpdu(DIRECTION_UPLINK, harq_process->a, harq_process->pusch_pdu.pusch_data.tb_size, 0, WS_C_RNTI, 0, 0, 0,0, 0); /////////// ///////////////////////////////////////////////////////////////////////////////////////// @@ -266,22 +266,24 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, LOG_D(PHY,"ulsch coding nb_rb %d, Nl = %d\n", nb_rb, harq_process->pusch_pdu.nrOfLayers); LOG_D(PHY,"ulsch coding A %d G %d mod_order %d\n", A,G, mod_order); + LOG_D(PHY,"harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n", + harq_pid,harq_process->ndi,harq_process->pusch_pdu.pusch_data.new_data_indicator); - // if (harq_process->Ndi == 1) { // this is a new packet - if (harq_process->round == 0) { // this is a new packet -#ifdef DEBUG_DLSCH_CODING + if (harq_process->first_tx == 1 || + harq_process->ndi != harq_process->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet +#ifdef DEBUG_ULSCH_CODING printf("encoding thinks this is a new packet \n"); #endif - + harq_process->first_tx = 0; ///////////////////////// a---->| add CRC |---->b ///////////////////////// /////////// - /* + /* int i; printf("ulsch (tx): \n"); for (i=0;i<(A>>3);i++) - printf("%02x.",a[i]); + printf("%02x.",harq_process->a[i]); printf("\n"); - */ + */ if (A > 3824) { // Add 24-bit crc (polynomial A) to payload @@ -324,13 +326,14 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, Coderate = (float) R /(float) 2048; if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ - BG = 2; + harq_process->BG = 2; } else{ - BG = 1; + harq_process->BG = 1; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN); + start_meas(&ue->ulsch_segmentation_stats); Kb=nr_segmentation(harq_process->b, harq_process->c, harq_process->B, @@ -338,12 +341,13 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, &harq_process->K, pz, &harq_process->F, - BG); + harq_process->BG); + stop_meas(&ue->ulsch_segmentation_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT); F = harq_process->F; Kr = harq_process->K; -#ifdef DEBUG_DLSCH_CODING +#ifdef DEBUG_ULSCH_CODING uint16_t Kr_bytes; Kr_bytes = Kr>>3; #endif @@ -356,7 +360,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, //start_meas(te_stats); for (r=0; rC; r++) { //channel_input[r] = &harq_process->d[r][0]; -#ifdef DEBUG_DLSCH_CODING +#ifdef DEBUG_ULSCH_CODING printf("Encoder: B %d F %d \n",harq_process->B, harq_process->F); printf("start ldpc encoder segment %d/%d\n",r,harq_process->C); printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); @@ -373,42 +377,45 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, //for (int i=0;i<68*384;i++) // printf("channel_input[%d]=%d\n",i,channel_input[i]); - int temp_opp = 0; - - if (opp_enabled) { - opp_enabled = 0; - temp_opp = 1; - } - - /*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3], harq_process->d[0][4]); for (int cnt =0 ; cnt < 66*(*pz); cnt ++){ printf("%d \n", harq_process->d[0][cnt]); } printf("\n");*/ - encoder_implemparams_t impp; - impp.n_segments=harq_process->C; - impp.macro_num=0; + encoder_implemparams_t impp = { + .n_segments=harq_process->C, + .macro_num=0, + .tinput = NULL, + .tprep = NULL, + .tparity = NULL, + .toutput = NULL}; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN); - - nrLDPC_encoder(harq_process->c,harq_process->d,*pz,Kb,Kr,BG,&impp); - + + start_meas(&ue->ulsch_ldpc_encoding_stats); + for(int j = 0; j < (harq_process->C/8 + 1); j++) + { + impp.macro_num = j; + nrLDPC_encoder(harq_process->c,harq_process->d,*pz,Kb,Kr,harq_process->BG,&impp); + } + stop_meas(&ue->ulsch_ldpc_encoding_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); //stop_meas(te_stats); //printf("end ldpc encoder -- output\n"); -#ifdef DEBUG_DLSCH_CODING +#ifdef DEBUG_ULSCH_CODING write_output("ulsch_enc_input0.m","enc_in0",&harq_process->c[0][0],Kr_bytes,1,4); write_output("ulsch_enc_output0.m","enc0",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,4); #endif - if (temp_opp) opp_enabled = 1; - /////////// /////////////////////////////////////////////////////////////////////////////// - + LOG_D(PHY,"setting ndi to %d from pusch_data\n", harq_process->pusch_pdu.pusch_data.new_data_indicator); + harq_process->ndi = harq_process->pusch_pdu.pusch_data.new_data_indicator; } + F = harq_process->F; + Kr = harq_process->K; for (r=0; rC; r++) { // looping over C segments @@ -420,43 +427,43 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, } } -#ifdef DEBUG_DLSCH_CODING - printf("Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb); -#endif + + LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n", + r, + G, + Kr*3, + mod_order,nb_rb, + harq_process->pusch_pdu.pusch_data.rv_index); //start_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - printf("rvidx in encoding = %d\n", harq_process->pusch_pdu.pusch_data.rv_index); -#endif - ///////////////////////// d---->| Rate matching bit selection |---->e ///////////////////////// /////////// E = nr_get_E(G, harq_process->C, mod_order, harq_process->pusch_pdu.nrOfLayers, r); - Tbslbrm = nr_compute_tbslbrm(0,nb_rb,harq_process->pusch_pdu.nrOfLayers,harq_process->C); + Tbslbrm = nr_compute_tbslbrm(0,nb_rb,harq_process->pusch_pdu.nrOfLayers); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN); - nr_rate_matching_ldpc(Ilbrm, - Tbslbrm, - BG, - *pz, - harq_process->d[r], - harq_process->e+r_offset, - harq_process->C, - F, - Kr-F-2*(*pz), - harq_process->pusch_pdu.pusch_data.rv_index, - E); + start_meas(&ue->ulsch_rate_matching_stats); + if (nr_rate_matching_ldpc(Ilbrm, + Tbslbrm, + harq_process->BG, + *pz, + harq_process->d[r], + harq_process->e+r_offset, + harq_process->C, + F, + Kr-F-2*(*pz), + harq_process->pusch_pdu.pusch_data.rv_index, + E) == -1) + return -1; + + stop_meas(&ue->ulsch_rate_matching_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_OUT); -#ifdef DEBUG_DLSCH_CODING +#ifdef DEBUG_ULSCH_CODING for (int i =0; i<16; i++) printf("output ratematching e[%d]= %d r_offset %d\n", i,harq_process->e[i+r_offset], r_offset); #endif @@ -473,16 +480,18 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, //start_meas(i_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_IN); + start_meas(&ue->ulsch_interleaving_stats); nr_interleaving_ldpc(E, mod_order, harq_process->e+r_offset, harq_process->f+r_offset); + stop_meas(&ue->ulsch_interleaving_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_OUT); //stop_meas(i_stats); -#ifdef DEBUG_DLSCH_CODING +#ifdef DEBUG_ULSCH_CODING for (int i =0; i<16; i++) printf("output interleaving f[%d]= %d r_offset %d\n", i,harq_process->f[i+r_offset], r_offset); @@ -501,5 +510,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_OUT); + stop_meas(&ue->ulsch_encoding_stats); return(0); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 34cd6e92af..914523bc70 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -44,11 +44,11 @@ #include "PHY/TOOLS/tools_defs.h" #include "executables/nr-softmodem.h" #include "executables/softmodem-common.h" -#include "LAYER2/NR_MAC_UE/mac_proto.h" +#include "PHY/NR_REFSIG/ul_ref_seq_nr.h" -//#define DEBUG_SCFDMA //#define DEBUG_PUSCH_MAPPING //#define DEBUG_MAC_PDU +//#define DEBUG_DFT_IDFT //extern int32_t uplink_counter; @@ -101,80 +101,70 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot); uint32_t available_bits; - uint8_t mod_order, cwd_index, num_of_codewords, l; + uint8_t cwd_index, l; uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; - uint32_t ***pusch_dmrs; int16_t **tx_layers; int32_t **txdataF; - uint16_t start_sc, start_rb; - int8_t Wf[2], Wt[2], l_prime[2], delta; - uint16_t rnti, n_dmrs, code_rate, number_dmrs_symbols, nb_rb, k; - uint8_t dmrs_type, nb_dmrs_re_per_rb, number_of_symbols, mcs, Nl; - int ap, start_symbol, Nid_cell, i; - int sample_offsetF, N_RE_prime, N_PRB_oh; - uint16_t ul_dmrs_symb_pos; - uint8_t L_ptrs, K_ptrs; // PTRS parameters - uint16_t beta_ptrs; // PTRS parameter related to power control + int8_t Wf[2], Wt[2]; + int l_prime[2], delta; + uint8_t nb_dmrs_re_per_rb; + int ap, i; + int sample_offsetF, N_RE_prime; - NR_UE_ULSCH_t *ulsch_ue; - NR_UL_UE_HARQ_t *harq_process_ul_ue=NULL; NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; NR_UE_PUSCH *pusch_ue = UE->pusch_vars[thread_id][gNB_id]; - // ptrs_UplinkConfig_t *ptrs_Uplink_Config = &UE->pusch_config.dmrs_UplinkConfig.ptrs_UplinkConfig; - num_of_codewords = 1; // tmp assumption - Nid_cell = 0; - N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig - number_dmrs_symbols = 0; + uint8_t num_of_codewords = 1; // tmp assumption + int Nid_cell = 0; + int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig + uint16_t number_dmrs_symbols = 0; for (cwd_index = 0;cwd_index < num_of_codewords; cwd_index++) { - ulsch_ue = UE->ulsch[thread_id][gNB_id][cwd_index]; - harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid]; + NR_UE_ULSCH_t *ulsch_ue = UE->ulsch[thread_id][gNB_id][cwd_index]; + NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid]; + nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &harq_process_ul_ue->pusch_pdu; - start_symbol = harq_process_ul_ue->pusch_pdu.start_symbol_index; - ul_dmrs_symb_pos = harq_process_ul_ue->pusch_pdu.ul_dmrs_symb_pos; - number_of_symbols = harq_process_ul_ue->pusch_pdu.nr_of_symbols; - dmrs_type = harq_process_ul_ue->pusch_pdu.dmrs_config_type; + int start_symbol = pusch_pdu->start_symbol_index; + uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos; + uint8_t number_of_symbols = pusch_pdu->nr_of_symbols; + uint8_t dmrs_type = pusch_pdu->dmrs_config_type; + uint16_t start_rb = pusch_pdu->rb_start; + uint16_t nb_rb = pusch_pdu->rb_size; + uint8_t Nl = pusch_pdu->nrOfLayers; + uint8_t mod_order = pusch_pdu->qam_mod_order; + uint16_t rnti = pusch_pdu->rnti; + uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data; + uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb+pusch_pdu->bwp_start)*NR_NB_SC_PER_RB; - for (i = start_symbol; i < start_symbol + number_of_symbols; i++) { + if (start_sc >= frame_parms->ofdm_symbol_size) + start_sc -= frame_parms->ofdm_symbol_size; - if((ul_dmrs_symb_pos >> i) & 0x01) - number_dmrs_symbols += 1; - - } - - rnti = harq_process_ul_ue->pusch_pdu.rnti; ulsch_ue->Nid_cell = Nid_cell; - nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*harq_process_ul_ue->pusch_pdu.num_dmrs_cdm_grps_no_data; + for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) { + if((ul_dmrs_symb_pos >> i) & 0x01) + number_dmrs_symbols += 1; + } + nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*cdm_grps_no_data; + + LOG_D(PHY,"ulsch %x : start_rb %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n", + rnti,start_rb,pusch_pdu->bwp_start,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb); + + // TbD num_of_mod_symbols is set but never used N_RE_prime = NR_NB_SC_PER_RB*number_of_symbols - nb_dmrs_re_per_rb*number_dmrs_symbols - N_PRB_oh; - - nb_rb = harq_process_ul_ue->pusch_pdu.rb_size; - harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb*num_of_codewords; - mcs = harq_process_ul_ue->pusch_pdu.mcs_index; - Nl = harq_process_ul_ue->pusch_pdu.nrOfLayers; - mod_order = nr_get_Qm_ul(mcs, 0); - code_rate = nr_get_code_rate_ul(mcs, 0); - - harq_process_ul_ue->pusch_pdu.pusch_data.tb_size = nr_compute_tbs(mod_order, - code_rate, - nb_rb, - number_of_symbols, - nb_dmrs_re_per_rb*number_dmrs_symbols, - 0, - 0, - harq_process_ul_ue->pusch_pdu.nrOfLayers); - /////////////////////////ULSCH coding///////////////////////// /////////// unsigned int G = nr_get_G(nb_rb, number_of_symbols, nb_dmrs_re_per_rb, number_dmrs_symbols, mod_order, Nl); - nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid, G); + + + if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, G) == -1) + return; /////////// //////////////////////////////////////////////////////////////////// @@ -205,19 +195,14 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, (int16_t *)ulsch_ue->d_mod); - // pusch_transform_precoding(ulsch_ue, frame_parms, harq_pid); - + /////////// //////////////////////////////////////////////////////////////////////// - - //} - } - /////////////////////////DMRS Modulation///////////////////////// /////////// - pusch_dmrs = UE->nr_gold_pusch_dmrs[slot]; - n_dmrs = (nb_rb*((dmrs_type == pusch_dmrs_type1) ? 6:4)*number_dmrs_symbols); + uint32_t ***pusch_dmrs = UE->nr_gold_pusch_dmrs[slot]; + uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4); int16_t mod_dmrs[n_dmrs<<1] __attribute((aligned(16))); /////////// //////////////////////////////////////////////////////////////////////// @@ -226,12 +211,13 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////PTRS parameters' initialization///////////////////////// /////////// - int16_t mod_ptrs[(nb_rb/2)*(NR_SYMBOLS_PER_SLOT-1)*2]; // assume maximum number of PTRS per pusch allocation - K_ptrs = 0; // just to avoid a warning + int16_t mod_ptrs[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation + uint8_t L_ptrs, K_ptrs = 0; + uint16_t beta_ptrs = 1; // temp value until power control is implemented - if (harq_process_ul_ue->pusch_pdu.pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - K_ptrs = (harq_process_ul_ue->pusch_pdu.pusch_ptrs.ptrs_freq_density)?4:2; + K_ptrs = harq_process_ul_ue->pusch_pdu.pusch_ptrs.ptrs_freq_density; L_ptrs = 1<pusch_pdu.pusch_ptrs.ptrs_time_density; beta_ptrs = 1; // temp value until power control is implemented @@ -267,31 +253,73 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, l_prime[0] = 0; // single symbol ap 0 -#ifdef NR_SC_FDMA - uint32_t nb_re_pusch, nb_re_dmrs_per_rb; - uint32_t y_offset = 0; + uint16_t index; + uint8_t u = 0, v = 0; + int16_t *dmrs_seq = NULL; - for (l = start_symbol; l < start_symbol + number_of_symbols; l++) { + // if transform precoding is enbaled (value 0) + if (pusch_pdu->transform_precoding == 0) { - if((ul_dmrs_symb_pos >> l) & 0x01) - is_dmrs = 1; - else - is_dmrs = 0; - - if (is_dmrs == 1) - nb_re_dmrs_per_rb = nb_dmrs_re_per_rb; - else - nb_re_dmrs_per_rb = 0; + uint32_t nb_re_pusch=nb_rb * NR_NB_SC_PER_RB; + uint32_t y_offset = 0; + uint16_t num_dmrs_res_per_symbol = nb_rb*(NR_NB_SC_PER_RB/2); - nb_re_pusch = nb_rb * (NR_NB_SC_PER_RB - nb_re_dmrs_per_rb); + // Calculate index to dmrs seq array based on number of DMRS Subcarriers on this symbol + index = get_index_for_dmrs_lowpapr_seq(num_dmrs_res_per_symbol); + u = pusch_pdu->dfts_ofdm.low_papr_group_number; + v = pusch_pdu->dfts_ofdm.low_papr_sequence_number; + dmrs_seq = dmrs_lowpaprtype1_ul_ref_sig[u][v][index]; - nr_dft(&ulsch_ue->y[y_offset], &((int32_t*)tx_layers[0])[y_offset], nb_re_pusch); + AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n"); + AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated"); + + LOG_D(PHY,"Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index); + + for (l = start_symbol; l < start_symbol + number_of_symbols; l++) { + + if((ul_dmrs_symb_pos >> l) & 0x01) + /* In the symbol with DMRS no data would be transmitted CDM groups is 2*/ + continue; + + nr_dft(&ulsch_ue->y[y_offset], &((int32_t*)tx_layers[0])[y_offset], nb_re_pusch); + + y_offset = y_offset + nb_re_pusch; + + LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d, y_offset: %d\n", l, nb_re_pusch, y_offset); + + #ifdef DEBUG_PUSCH_MAPPING + printf("NR_ULSCH_UE: y_offset %d\t nb_re_pusch %d \t Symbol %d \t nb_rb %d \n", + y_offset, nb_re_pusch, l, nb_rb); + #endif + } + + #ifdef DEBUG_DFT_IDFT + int32_t debug_symbols[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); + int offset = 0; + printf("NR_ULSCH_UE: available_bits: %d, mod_order: %d", available_bits,mod_order); + + for (int ll = 0; ll < (available_bits/mod_order); ll++) { + debug_symbols[ll] = ulsch_ue->y[ll]; + } + + printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols,number_dmrs_symbols); + for (int ll = 0; ll < (number_of_symbols-number_dmrs_symbols); ll++) { + + nr_idft(&debug_symbols[offset], nb_re_pusch); + + offset = offset + nb_re_pusch; + + } + LOG_M("preDFT_all_symbols.m","UE_preDFT", tx_layers[0],number_of_symbols*nb_re_pusch,1,1); + LOG_M("postDFT_all_symbols.m","UE_postDFT", ulsch_ue->y,number_of_symbols*nb_re_pusch,1,1); + LOG_M("DEBUG_IDFT_SYMBOLS.m","UE_Debug_IDFT", debug_symbols,number_of_symbols*nb_re_pusch,1,1); + LOG_M("UE_DMRS_SEQ.m","UE_DMRS_SEQ", dmrs_seq,nb_re_pusch,1,1); + #endif - y_offset = y_offset + nb_re_pusch; } -#else - memcpy(ulsch_ue->y, tx_layers[0], (available_bits/mod_order)*sizeof(int32_t)); -#endif + else + memcpy(ulsch_ue->y, tx_layers[0], (available_bits/mod_order)*sizeof(int32_t)); + /////////// //////////////////////////////////////////////////////////////////////// @@ -303,66 +331,97 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, txdataF = UE->common_vars.txdataF; - start_rb = harq_process_ul_ue->pusch_pdu.rb_start; - start_sc = frame_parms->first_carrier_offset + start_rb*NR_NB_SC_PER_RB; - - if (start_sc >= frame_parms->ofdm_symbol_size) - start_sc -= frame_parms->ofdm_symbol_size; - for (ap=0; ap< Nl; ap++) { + uint8_t k_prime = 0; + uint16_t m = 0; + + + #ifdef DEBUG_PUSCH_MAPPING + printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u); + #endif + + + // DMRS params for this ap get_Wt(Wt, ap, dmrs_type); get_Wf(Wf, ap, dmrs_type); delta = get_delta(ap, dmrs_type); - - - uint8_t k_prime=0; - uint8_t is_dmrs, is_ptrs, is_dmrs_symbol; - uint16_t m=0, n=0, dmrs_idx=0, ptrs_idx = 0; for (l=start_symbol; l> l) & 0x01) { + is_dmrs_sym = 1; + + // transform precoding disabled (value 1) + if (pusch_pdu->transform_precoding == 1){ + + if (dmrs_type == pusch_dmrs_type1) + dmrs_idx = (pusch_pdu->bwp_start + start_rb)*6; + else + dmrs_idx = (pusch_pdu->bwp_start + start_rb)*4; + + // TODO: performance improvement, we can skip the modulation of DMRS symbols outside the bandwidth part + // Perform this on gold sequence, not required when SC FDMA operation is done, + LOG_D(PHY,"DMRS in symbol %d\n",l); + nr_modulation(pusch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated + + } else { + dmrs_idx = 0; + } + + + } else if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + + AssertFatal(pusch_pdu->transform_precoding == 1, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n"); + + if(is_ptrs_symbol(l, ulsch_ue->ptrs_symbols)) { + is_ptrs_sym = 1; + nr_modulation(pusch_dmrs[l][0], nb_rb, DMRS_MOD_ORDER, mod_ptrs); + } + } for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) { + uint8_t is_dmrs = 0; + uint8_t is_ptrs = 0; + sample_offsetF = l*frame_parms->ofdm_symbol_size + k; - is_dmrs = 0; - is_ptrs = 0; - is_dmrs_symbol = 0; - - if((ul_dmrs_symb_pos >> l) & 0x01) { - is_dmrs_symbol = 1; + if (is_dmrs_sym) { if (k == ((start_sc+get_dmrs_freq_idx_ul(n, k_prime, delta, dmrs_type))%frame_parms->ofdm_symbol_size)) is_dmrs = 1; - } - - if (harq_process_ul_ue->pusch_pdu.pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS){ - - if(is_ptrs_symbol(l, ulsch_ue->ptrs_symbols)) + } else if (is_ptrs_sym) { is_ptrs = is_ptrs_subcarrier(k, rnti, ap, dmrs_type, K_ptrs, nb_rb, - harq_process_ul_ue->pusch_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset, + pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset, start_sc, frame_parms->ofdm_symbol_size); } if (is_dmrs == 1) { + // if transform precoding is enabled + if (pusch_pdu->transform_precoding == 0) { - if (k == start_sc){ - nr_modulation(pusch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated - } + ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[2*dmrs_idx]) >> 15; + ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*dmrs_seq[(2*dmrs_idx) + 1]) >> 15; + + } else { - ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[dmrs_idx<<1]) >> 15; - ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; + ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[dmrs_idx<<1]) >> 15; + ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; + + } #ifdef DEBUG_PUSCH_MAPPING printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n", @@ -378,16 +437,12 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, } else if (is_ptrs == 1) { - if (k == start_sc){ - nr_modulation(pusch_dmrs[l][0], nb_rb, DMRS_MOD_ORDER, mod_ptrs); - } - ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (beta_ptrs*AMP*mod_ptrs[ptrs_idx<<1]) >> 15; ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (beta_ptrs*AMP*mod_ptrs[(ptrs_idx<<1) + 1]) >> 15; ptrs_idx++; - } else if (!is_dmrs_symbol || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,harq_process_ul_ue->pusch_pdu.num_dmrs_cdm_grps_no_data,dmrs_type)) { + } else if (!is_dmrs_sym || allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) { ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = ((int16_t *) ulsch_ue->y)[m<<1]; ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = ((int16_t *) ulsch_ue->y)[(m<<1) + 1]; @@ -412,8 +467,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, } } } + } - //} NR_UL_UE_HARQ_t *harq_process_ulsch=NULL; harq_process_ulsch = UE->ulsch[thread_id][gNB_id][0]->harq_processes[harq_pid]; harq_process_ulsch->status = SCH_IDLE; @@ -425,31 +480,18 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, - uint8_t harq_pid, uint8_t slot, - uint8_t thread_id, - uint8_t gNB_id, - NR_DL_FRAME_PARMS *frame_parms) { + NR_DL_FRAME_PARMS *frame_parms, + uint8_t Nl) { int tx_offset, ap; int32_t **txdata; int32_t **txdataF; - int timing_advance; - uint8_t Nl = UE->ulsch[thread_id][gNB_id][0]->harq_processes[harq_pid]->pusch_pdu.nrOfLayers; // cw 0 /////////////////////////IFFT/////////////////////// /////////// -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - timing_advance = UE->timing_advance; -#else - timing_advance = 0; -#endif - - tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0) - timing_advance; - - if (tx_offset < 0) - tx_offset += frame_parms->samples_per_frame; + tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); // clear the transmit data array for the current subframe /*for (int aa=0; aaframe_parms.nb_antennas_tx; aa++) { @@ -461,49 +503,39 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, txdata = UE->common_vars.txdata; txdataF = UE->common_vars.txdataF; - if(UE->N_TA_offset > tx_offset) { - int32_t *tmp_idft_out = (int32_t*)malloc16(frame_parms->get_samples_per_slot(slot, frame_parms) * sizeof(int32_t)); + int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + for(ap = 0; ap < Nl; ap++) { + for (int s=0;sNcp == 1) { // extended cyclic prefix - PHY_ofdm_mod(txdataF[ap], - tmp_idft_out, - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - } else { // normal cyclic prefix - nr_normal_prefix_mod(txdataF[ap], - tmp_idft_out, - 14, - frame_parms); - } + LOG_D(PHY,"In %s: rotating txdataF symbol %d (%d) => (%d.%d)\n", + __FUNCTION__, + s, + s + symb_offset, + frame_parms->symbol_rotation[1][2 * (s + symb_offset)], + frame_parms->symbol_rotation[1][1 + (2 * (s + symb_offset))]); - memcpy((void *) &txdata[ap][frame_parms->samples_per_frame - UE->N_TA_offset + tx_offset], - (void *) tmp_idft_out, - (UE->N_TA_offset - tx_offset) * sizeof(int32_t)); - - memcpy((void *) &txdata[ap][0], - (void *) &tmp_idft_out[UE->N_TA_offset - tx_offset], - (frame_parms->get_samples_per_slot(slot, frame_parms) - UE->N_TA_offset + tx_offset) * sizeof(int32_t)); + rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], + &frame_parms->symbol_rotation[1][2 * (s + symb_offset)], + (int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], + frame_parms->ofdm_symbol_size, + 15); } + } - free(tmp_idft_out); - } else { // UE->N_TA_offset <= tx_offset - for (ap = 0; ap < Nl; ap++) { - if (frame_parms->Ncp == 1) { // extended cyclic prefix - PHY_ofdm_mod(txdataF[ap], - &txdata[ap][tx_offset-UE->N_TA_offset], - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - } else { // normal cyclic prefix - nr_normal_prefix_mod(txdataF[ap], - &txdata[ap][tx_offset-UE->N_TA_offset], - 14, - frame_parms); - } + for (ap = 0; ap < Nl; ap++) { + if (frame_parms->Ncp == 1) { // extended cyclic prefix + PHY_ofdm_mod(txdataF[ap], + &txdata[ap][tx_offset], + frame_parms->ofdm_symbol_size, + 12, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } else { // normal cyclic prefix + nr_normal_prefix_mod(txdataF[ap], + &txdata[ap][tx_offset], + 14, + frame_parms, + slot); } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index c977118df3..28b6677b2c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -213,7 +213,7 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) } for (int n=0; n < LENGTH_PSS_NR; n++) { - int m = (n + 43*N_ID_2)%(LENGTH_PSS_NR); + int m = (n + 43*N_ID_2)%(LENGTH_PSS_NR); d_pss[n] = 1 - 2*x[m]; } @@ -270,7 +270,6 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size; - for (int i=0; i < LENGTH_PSS_NR; i++) { synchroF_tmp[2*k] = primary_synchro[2*i]; synchroF_tmp[2*k+1] = primary_synchro[2*i+1]; @@ -561,7 +560,6 @@ void set_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change { /* set new value according to rate_change */ frame_parms_ue->ofdm_symbol_size = (frame_parms_ue->ofdm_symbol_size / rate_change); - frame_parms_ue->samples_per_tti = (frame_parms_ue->samples_per_tti / rate_change); frame_parms_ue->samples_per_subframe = (frame_parms_ue->samples_per_subframe / rate_change); free_context_pss_nr(); @@ -589,7 +587,6 @@ void set_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change void restore_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change) { frame_parms_ue->ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size * rate_change; - frame_parms_ue->samples_per_tti = frame_parms_ue->samples_per_tti * rate_change; frame_parms_ue->samples_per_subframe = frame_parms_ue->samples_per_subframe * rate_change; free_context_pss_nr(); @@ -621,8 +618,6 @@ void decimation_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change, int **r NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int samples_for_frame = 2*frame_parms->samples_per_frame; - AssertFatal(frame_parms->samples_per_tti > 3839,"Illegal samples_per_tti %d\n",frame_parms->samples_per_tti); - #if TEST_SYNCHRO_TIMING_PSS opp_enabled = 1; diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index 65bb2edaca..ddec605253 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -34,7 +34,6 @@ #include "PHY/defs_nr_common.h" #include "PHY/defs_nr_UE.h" //#include "PHY/extern.h" -//#include "LAYER2/MAC/extern.h" #include "PHY/NR_UE_TRANSPORT/pucch_nr.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" @@ -54,17 +53,12 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - long pucch_GroupHopping, - long hoppingId, int16_t amp, - int nr_tti_tx, - uint8_t m0, - uint8_t mcs, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB) { + int nr_slot_tx, + fapi_nr_ul_config_pucch_pdu *pucch_pdu) { + #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] start function at slot(nr_tti_tx)=%d\n",nr_tti_tx); + printf("\t [nr_generate_pucch0] start function at slot(nr_slot_tx)=%d\n",nr_slot_tx); #endif /* * Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation @@ -94,38 +88,45 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, * x(l*12+n) = r_u_v_alpha_delta(n) */ // the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1 - uint8_t u=0,v=0;//,delta=0; - // if frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping - // n_hop = 0 - // if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping - // n_hop = 0 for first hop - // n_hop = 1 for second hop - uint8_t n_hop = 0; - //uint8_t PUCCH_Frequency_Hopping; // from higher layers FIXME!! + uint8_t u[2]={0,0},v[2]={0,0}; + + LOG_D(PHY,"pucch0: slot %d nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, mcs %d\n", + nr_slot_tx,pucch_pdu->nr_of_symbols,pucch_pdu->start_symbol_index,pucch_pdu->prb_start,pucch_pdu->second_hop_prb,pucch_pdu->group_hop_flag,pucch_pdu->sequence_hop_flag,pucch_pdu->mcs); + #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n"); #endif // x_n contains the sequence r_u_v_alpha_delta(n) - int16_t x_n_re[24],x_n_im[24]; + int16_t x_n_re[2][24],x_n_im[2][24]; + + uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); // we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2 - for (int l=0; lpucch_config_common_nr->hoppingId,m0,mcs,l,startingSymbolIndex,nr_tti_tx); + int prb_offset[2]={startingPRB,startingPRB}; + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,0,nr_slot_tx,&u[0],&v[0]); // calculating u and v value + if (pucch_pdu->freq_hop_flag == 1) { + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,1,nr_slot_tx,&u[1],&v[1]); // calculating u and v value + prb_offset[1] = pucch_pdu->second_hop_prb; + } + for (int l=0; lnr_of_symbols; l++) { + alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id, + pucch_pdu->initial_cyclic_shift, + pucch_pdu->mcs,l, + pucch_pdu->start_symbol_index, + nr_slot_tx); #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u,v,alpha,l); + printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u[l],v[l],alpha,l); #endif for (int n=0; n<12; n++) { - x_n_re[(12*l)+n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) - - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha - x_n_im[(12*l)+n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) - + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha + x_n_re[l][n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u[l]][n])>>15) + - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u[l]][n])>>15))); // Re part of base sequence shifted by alpha + x_n_im[l][n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u[l]][n])>>15) + + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u[l]][n])>>15))); // Im part of base sequence shifted by alpha #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n", - u,v,alpha,l,n,x_n_re[(12*l)+n],x_n_im[(12*l)+n]); + u[l],v[l],alpha,l,n,x_n_re[l][n],x_n_im[l][n]); #endif } } @@ -137,17 +138,20 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, uint32_t re_offset=0; uint8_t l2; - for (int l=0; lfirst_carrier_offset; + for (int l=0; lnr_of_symbols; l++) { + l2=l+pucch_pdu->start_symbol_index; + re_offset = (12*prb_offset[l]) + frame_parms->first_carrier_offset; if (re_offset>= frame_parms->ofdm_symbol_size) re_offset-=frame_parms->ofdm_symbol_size; //txptr = &txdataF[0][re_offset]; +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch0] symbol %d PRB %d (%d)\n",l,prb_offset[l],re_offset); +#endif for (int n=0; n<12; n++) { - ((int16_t *)&txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset])[0] = (int16_t)(((int32_t)(amp) * x_n_re[(12*l)+n])>>15); - ((int16_t *)&txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset])[1] = (int16_t)(((int32_t)(amp) * x_n_im[(12*l)+n])>>15); + ((int16_t *)&txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset])[0] = (int16_t)(((int32_t)(amp) * x_n_re[l][n])>>15); + ((int16_t *)&txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset])[1] = (int16_t)(((int32_t)(amp) * x_n_im[l][n])>>15); //((int16_t *)txptr[0][re_offset])[0] = (int16_t)((int32_t)amp * x_n_re[(12*l)+n])>>15; //((int16_t *)txptr[0][re_offset])[1] = (int16_t)((int32_t)amp * x_n_im[(12*l)+n])>>15; //txptr[re_offset] = (x_n_re[(12*l)+n]<<16) + x_n_im[(12*l)+n]; @@ -167,20 +171,20 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, void nr_generate_pucch1(PHY_VARS_NR_UE *ue, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, - int nr_tti_tx, - uint8_t m0, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t timeDomainOCC, - uint8_t nr_bit) { + int nr_slot_tx, + fapi_nr_ul_config_pucch_pdu *pucch_pdu) { + + uint16_t m0 = pucch_pdu->initial_cyclic_shift; + uint64_t payload = pucch_pdu->payload; + uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index; + uint8_t nrofSymbols = pucch_pdu->nr_of_symbols; + uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; + uint8_t timeDomainOCC = pucch_pdu->time_domain_occ_idx; + #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%lu m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n", - nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + printf("\t [nr_generate_pucch1] start function at slot(nr_slot_tx)=%d payload=%lu m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d second_hop_prb=%d timeDomainOCC=%d nr_bit=%d\n", + nr_slot_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,pucch_pdu->second_hop_prb,timeDomainOCC,pucch_pdu->n_bit); #endif /* * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation @@ -189,12 +193,12 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, // complex-valued symbol d_re, d_im containing complex-valued symbol d(0): int16_t d_re=0, d_im=0; - if (nr_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2 + if (pucch_pdu->n_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2 d_re = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - if (nr_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 + if (pucch_pdu->n_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 if (((payload&1)==0) && (((payload>>1)&1)==0)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); @@ -255,7 +259,7 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers uint8_t intraSlotFrequencyHopping = 0; - if (startingPRB != startingPRB_intraSlotHopping) { + if (pucch_pdu->freq_hop_flag) { intraSlotFrequencyHopping=1; } @@ -283,11 +287,12 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", - n_hop,nr_tti_tx); + printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_slot_tx=%d\n", + n_hop,nr_slot_tx); #endif - nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_tti_tx,&u,&v); // calculating u and v value - alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,l,lprime,nr_tti_tx); + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,nr_slot_tx,&u,&v); // calculating u and v value + alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,m0,mcs,l,lprime,nr_slot_tx); for (int n=0; n<12; n++) { r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) @@ -440,7 +445,7 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, } if ((intraSlotFrequencyHopping == 1) && (lsecond_hop_prb; } if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band @@ -505,7 +510,7 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, uint64_t payload, int16_t amp, - int nr_tti_tx, + int nr_slot_tx, uint8_t m0, uint8_t nrofSymbols, uint8_t startingSymbolIndex, @@ -514,8 +519,8 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, uint8_t timeDomainOCC, uint8_t nr_bit) { #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%d m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n", - nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + printf("\t [nr_generate_pucch1] start function at slot(nr_slot_tx)=%d payload=%d m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n", + nr_slot_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); #endif /* * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation @@ -603,11 +608,11 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, // y_n contains the complex value d multiplied by the sequence r_u_v int16_t y_n_re[12],y_n_im[12]; #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", - n_hop,nr_tti_tx); + printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_slot_tx=%d\n", + n_hop,nr_slot_tx); #endif - nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_tti_tx,&u,&v); // calculating u and v value - alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,lnormal,lprime,nr_tti_tx); + nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_slot_tx,&u,&v); // calculating u and v value + alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,lnormal,lprime,nr_slot_tx); for (int n=0; n<12; n++) { r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) @@ -800,13 +805,13 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, } #endif //0 -inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint64_t *B64,uint8_t *btilde) __attribute__((always_inline)); -inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint64_t *B64,uint8_t *btilde) { +static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint64_t *B64,uint8_t *btilde) __attribute__((always_inline)); +static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint64_t *B64,uint8_t *btilde) { uint32_t x1, x2, s=0; int i; uint8_t c; // c_init=nRNTI*2^15+n_id according to TS 38.211 Subclause 6.3.2.6.1 - //x2 = (rnti) + ((uint32_t)(1+nr_tti_tx)<<16)*(1+(fp->Nid_cell<<1)); + //x2 = (rnti) + ((uint32_t)(1+nr_slot_tx)<<16)*(1+(fp->Nid_cell<<1)); x2 = ((rnti)<<15)+n_id; #ifdef DEBUG_NR_PUCCH_TX printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%x, M_bit %d\n",s,M_bit); @@ -833,7 +838,7 @@ inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id, c = (uint8_t)((s>>i)&1); btildep[i] = (((B>>i)&1) ^ c); #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t\t btilde[%d]=%lx from unscrambled bit %d and scrambling %d (%x)\n",i+(iprime<<5),btilde[i],((B>>i)&1),c,s>>i); + printf("\t\t\t btilde[%d]=%x from unscrambled bit %d and scrambling %d (%x)\n",i+(iprime<<5),btilde[i],((B>>i)&1),c,s>>i); #endif } M_bit3-=32; @@ -847,7 +852,7 @@ inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id, } void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, - pucch_format_nr_t fmt, + int fmt, uint8_t is_pi_over_2_bpsk_enabled, uint8_t nrofSymbols, uint8_t nrofPRB, @@ -867,9 +872,9 @@ void nr_uci_encoding(uint64_t payload, // E is the rate matching output sequence length as given in TS 38.212 subclause 6.3.1.4.1 uint16_t E=0,E_init; - if (fmt == pucch_format2_nr) E = 16*nrofSymbols*nrofPRB; + if (fmt == 2) E = 16*nrofSymbols*nrofPRB; - if (fmt == pucch_format3_nr) { + if (fmt == 3) { E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; if (nrofSymbols == 4) { @@ -894,7 +899,7 @@ void nr_uci_encoding(uint64_t payload, } } - if (fmt == pucch_format4_nr) { + if (fmt == 4) { E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; if (nrofSymbols == 4) { @@ -928,7 +933,17 @@ void nr_uci_encoding(uint64_t payload, if (A<=11) { // procedure in subclause 6.3.1.2.2 (UCI encoded by channel coding of small block lengths -> subclause 6.3.1.3.2) // CRC bits are not attached, and coding small block lengths (subclause 5.3.3) - b[0] = encodeSmallBlock((uint16_t*)&payload,A); + uint64_t b0= encodeSmallBlock((uint16_t*)&payload,A); + // repetition for rate-matching up to 16 PRB + b[0] = b0 | (b0<<32); + b[1] = b[0]; + b[2] = b[0]; + b[3] = b[0]; + b[4] = b[0]; + b[5] = b[0]; + b[6] = b[0]; + b[7] = b[0]; + AssertFatal(nrofPRB<=16,"Number of PRB >16\n"); } else if (A>=12) { AssertFatal(A<65,"Polar encoding not supported yet for UCI with more than 64 bits\n"); t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, @@ -942,28 +957,24 @@ void nr_uci_encoding(uint64_t payload, } //#if 0 void nr_generate_pucch2(PHY_VARS_NR_UE *ue, - uint16_t crnti, - uint32_t dmrs_scrambling_id, - uint32_t data_scrambling_id, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, - int nr_tti_tx, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint8_t nrofPRB, - uint16_t startingPRB, - uint8_t nr_bit) { + int nr_slot_tx, + fapi_nr_ul_config_pucch_pdu *pucch_pdu) { #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] start function at slot(nr_tti_tx)=%d with payload=%lu and nr_bit=%d\n",nr_tti_tx, payload, nr_bit); + printf("\t [nr_generate_pucch2] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n",nr_slot_tx, pucch_pdu->payload, pucch_pdu->n_bit); #endif // b is the block of bits transmitted on the physical channel after payload coding uint64_t b[16]; // limit to 1024-bit encoded length // M_bit is the number of bits of block b (payload after encoding) uint16_t M_bit; - nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,&b[0],&M_bit); + nr_uci_encoding(pucch_pdu->payload, + pucch_pdu->n_bit, + 2,0, + pucch_pdu->nr_of_symbols, + pucch_pdu->prb_size, + 1,0,0,&b[0],&M_bit); /* * Implementing TS 38.211 * Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2) @@ -978,14 +989,14 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, */ uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI - uint16_t rnti=crnti; + uint16_t rnti=pucch_pdu->rnti; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch2] rnti = %d ,\n",rnti); #endif /* * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2 */ - nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,&b[0],btilde); + nr_pucch2_3_4_scrambling(M_bit,rnti,pucch_pdu->data_scrambling_id,&b[0],btilde); /* * Implementing TS 38.211 Subclause 6.3.2.5.2 modulation format 2 * btilde shall be modulated as described in subclause 5.1 using QPSK @@ -1031,13 +1042,20 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint32_t x1, x2, s=0; int i=0; int m=0; + uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index; + uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; - for (int l=0; lnr_of_symbols; l++) { + // c_init calculation according to TS38.211 subclause + x2 = (((1<<17)*((14*nr_slot_tx) + (l+startingSymbolIndex) + 1)*((2*pucch_pdu->dmrs_scrambling_id) + 1)) + (2*pucch_pdu->dmrs_scrambling_id))%(1U<<31); - s = lte_gold_generic(&x1, &x2, 1); + int reset = 1; + for (int ii=0; ii<=(startingPRB>>2); ii++) { + s = lte_gold_generic(&x1, &x2, reset); + reset = 0; + } m = 0; - for (int rb=0; rbprb_size; rb++) { //startingPRB = startingPRB + rb; if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; @@ -1109,52 +1127,53 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, } //#if 0 void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, - uint16_t crnti, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - pucch_format_nr_t fmt, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, - int nr_tti_tx, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint8_t nrofPRB, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t nr_bit, - uint8_t occ_length_format4, - uint8_t occ_index_format4) { + int nr_slot_tx, + fapi_nr_ul_config_pucch_pdu *pucch_pdu) { #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] start function at slot(nr_tti_tx)=%d with payload=%lu and nr_bit=%d\n", nr_tti_tx, payload, nr_bit); + printf("\t [nr_generate_pucch3_4] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n", nr_slot_tx, pucch_pdu->payload, pucch_pdu->n_bit); #endif // b is the block of bits transmitted on the physical channel after payload coding uint64_t b[16]; // M_bit is the number of bits of block b (payload after encoding) uint16_t M_bit; // parameter PUCCH-F4-preDFT-OCC-length set of {2,4} -> to use table -1 or -2 - uint8_t n_SF_PUCCH_s = 2; // in format 4, n_SF_PUCCH_s = {2,4}, provided by higher layer parameter PUCCH-F4-preDFT-OCC-length (in format 3 n_SF_PUCCH_s=1), FIXME!!! - uint8_t is_pi_over_2_bpsk_enabled = 0; // this value has to be provided by higher layers parameter + // in format 4, n_SF_PUCCH_s = {2,4}, provided by higher layer parameter PUCCH-F4-preDFT-OCC-length (in format 3 n_SF_PUCCH_s=1) + uint8_t n_SF_PUCCH_s; + if (pucch_pdu->format_type == 3) + n_SF_PUCCH_s = 1; + else + n_SF_PUCCH_s = pucch_pdu->pre_dft_occ_len; + uint8_t is_pi_over_2_bpsk_enabled = pucch_pdu->pi_2bpsk; // Intra-slot frequency hopping shall be assumed when the higher-layer parameter intraSlotFrequencyHopping is provided, // regardless of whether the frequency-hop distance is zero or not, // otherwise no intra-slot frequency hopping shall be assumed //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers uint8_t intraSlotFrequencyHopping = 0; - if (startingPRB != startingPRB_intraSlotHopping) { + if (pucch_pdu->freq_hop_flag) { intraSlotFrequencyHopping=1; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); #endif } - // add_dmrs indicates if we are using or not Additional DM-RS for formats 3 and 4. From higher layers. FIXME!!! - uint8_t add_dmrs = 0; + uint8_t nrofSymbols = pucch_pdu->nr_of_symbols; + uint16_t nrofPRB = pucch_pdu->prb_size; + uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; + uint8_t add_dmrs = pucch_pdu->add_dmrs_flag; - //nrofPRB = 2; // only for test purposes - if (fmt == pucch_format4_nr) nrofPRB = 1; - - nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,&b[0],&M_bit); + nr_uci_encoding(pucch_pdu->payload, + pucch_pdu->n_bit, + pucch_pdu->format_type, + is_pi_over_2_bpsk_enabled, + nrofSymbols,nrofPRB, + n_SF_PUCCH_s, + intraSlotFrequencyHopping, + add_dmrs, + &b[0],&M_bit); /* * Implementing TS 38.211 * Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4) @@ -1169,7 +1188,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, */ uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI - uint16_t rnti=crnti, n_id=0; + uint16_t rnti=pucch_pdu->rnti, n_id=0; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] rnti = %d ,\n",rnti); #endif @@ -1285,12 +1304,11 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1} }; - //uint8_t occ_Length = occ_length_format4; // higher layer parameter occ-Length - uint8_t occ_Index = occ_index_format4; // higher layer parameter occ-Index + + uint8_t occ_Index = pucch_pdu->pre_dft_occ_idx; // higher layer parameter occ-Index //occ_Index = 1; //only for testing purposes; to be removed FIXME!!! - if (fmt == pucch_format3_nr) { // no block-wise spreading for format 3 - n_SF_PUCCH_s = 1; + if (pucch_pdu->format_type == 3) { // no block-wise spreading for format 3 for (int l=0; l < floor(m_symbol/(12*nrofPRB)); l++) { for (int k=0; k < (12*nrofPRB); k++) { @@ -1304,7 +1322,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, } } - if (fmt == pucch_format4_nr) { + if (pucch_pdu->format_type == 4) { nrofPRB = 1; for (int l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) { @@ -1399,9 +1417,9 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, uint8_t m0; uint8_t mcs=0; - if (fmt == pucch_format3_nr) m0 = 0; + if (pucch_pdu->format_type == 3) m0 = 0; - if (fmt == pucch_format4_nr) { + if (pucch_pdu->format_type == 4) { if (n_SF_PUCCH_s == 2) { m0 = (occ_Index == 0) ? 0 : 6; } @@ -1441,7 +1459,8 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, for (int l=0; l= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop - nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_tti_tx,&u,&v); // calculating u and v value + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,nr_slot_tx,&u,&v); // calculating u and v value // Next we proceed to calculate base sequence for DM-RS signal, according to TS 38.211 subclause 6.4.1.33 if (nrofPRB >= 3) { // TS 38.211 subclause 5.2.2.1 (Base sequences of length 36 or larger) applies @@ -1486,12 +1505,13 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, } } + uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index; uint16_t j=0; - alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,l,startingSymbolIndex,nr_tti_tx); + alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,m0,mcs,l,startingSymbolIndex,nr_slot_tx); for (int rb=0; rbsecond_hop_prb; } //startingPRB = startingPRB + rb; diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index 0e81045d66..078a95605f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -37,7 +37,6 @@ #include "PHY/defs_nr_common.h" #include "PHY/defs_nr_UE.h" //#include "PHY/extern.h" -//#include "LAYER2/MAC/extern.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -49,61 +48,30 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - long pucch_GroupHopping, - long hoppingId, int16_t amp, - int nr_tti_tx, - uint8_t m0, - uint8_t mcs, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB); + int nr_slot_tx, + fapi_nr_ul_config_pucch_pdu *pucch_pdu); + void nr_generate_pucch1(PHY_VARS_NR_UE *ue, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, - int nr_tti_tx, - uint8_t m0, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t timeDomainOCC, - uint8_t nr_bit); + int nr_slot_tx, + fapi_nr_ul_config_pucch_pdu *pucch_pdu); + void nr_generate_pucch2(PHY_VARS_NR_UE *ue, - uint16_t crnti, - uint32_t dmrs_scrambling_id, - uint32_t data_scrambling_id, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, - int nr_tti_tx, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint8_t nrofPRB, - uint16_t startingPRB, - uint8_t nr_bit); + int nr_slot_tx, + fapi_nr_ul_config_pucch_pdu *pucch_pdu); + void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, - uint16_t crnti, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, - pucch_format_nr_t fmt, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, int16_t amp, - int nr_tti_tx, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint8_t nrofPRB, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t nr_bit, - uint8_t occ_length_format4, - uint8_t occ_index_format4); + int nr_slot_tx, + fapi_nr_ul_config_pucch_pdu *pucch_pdu); // tables for mcs values for different payloads static const uint8_t table1_mcs[]={0,6,3,9}; diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c index aba3c12636..4109950df6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c @@ -84,7 +84,7 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set, uint32_t f_gh = 0; SRS_Resource_t *p_SRS_Resource; int frame_number = proc->frame_tx; - int slot_number = proc->nr_tti_tx; + int slot_number = proc->nr_slot_tx; uint16_t n_SRS, n_SRS_cs_i; double alpha_i; uint8_t K_TC_p; @@ -278,7 +278,7 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set, n_SRS = l/R; } else { - int8_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * frame_parms->ttis_per_subframe; + int8_t N_slot_frame = frame_parms->slots_per_frame; n_SRS = ((N_slot_frame*frame_number + slot_number - T_offset)/T_SRS)*(N_symb_SRS/R)+(l/R); } @@ -399,7 +399,7 @@ int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource, NR_DL_FRAME_PARMS *frame_pa return (-1); } - int16_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * frame_parms->ttis_per_subframe; + int16_t N_slot_frame = frame_parms->slots_per_frame; if ((N_slot_frame*frame_tx + slot_tx - T_offset)%T_SRS == 0) { return (0); } @@ -445,7 +445,7 @@ int ue_srs_procedure_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB /* SRS resource configurated ? */ if (p_srs_resource != NULL) { if (p_srs_resource_set->resourceType == periodic) { - if (is_srs_period_nr(p_srs_resource, frame_parms, proc->frame_tx, proc->nr_tti_tx) == 0) { + if (is_srs_period_nr(p_srs_resource, frame_parms, proc->frame_tx, proc->nr_slot_tx) == 0) { generate_srs = 1; } } @@ -459,7 +459,7 @@ int ue_srs_procedure_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB if (generate_srs == 1) { int16_t txptr = AMP; uint16_t nsymb = (ue->frame_parms.Ncp==0) ? 14:12; - uint16_t symbol_offset = (int)ue->frame_parms.ofdm_symbol_size*((proc->nr_tti_tx*nsymb)+(nsymb-1)); + uint16_t symbol_offset = (int)ue->frame_parms.ofdm_symbol_size*((proc->nr_slot_tx*nsymb)+(nsymb-1)); if (generate_srs_nr(p_srs_resource_set, frame_parms, &ue->common_vars.txdataF[eNB_id][symbol_offset], txptr, proc) == 0) { return 0; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index e3f1f13a8d..9339f3974d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -314,10 +314,11 @@ int pss_ch_est_nr(PHY_VARS_NR_UE *ue, *********************************************************************/ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR], uint8_t doPss, uint8_t doSss, - uint8_t subframe) // add flag to indicate extracting only PSS, only SSS, or both + uint8_t subframe) // add flag to indicate extracting only PSS, only SSS, or both { uint8_t aarx; int32_t *pss_rxF,*pss_rxF_ext; @@ -328,10 +329,10 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, for (aarx=0; aarxnb_antennas_rx; aarx++) { - pss_symbol = 0; - sss_symbol = SSS_SYMBOL_NB-PSS_SYMBOL_NB; + pss_symbol = 0; + sss_symbol = SSS_SYMBOL_NB-PSS_SYMBOL_NB; - rxdataF = ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF; + rxdataF = ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size; @@ -342,6 +343,7 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, sss_rxF_ext = &sss_ext[aarx][0]; unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; + if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; for (int i=0; i < LENGTH_PSS_NR; i++) { @@ -386,7 +388,7 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, /******************************************************************* * -* NAME : rx_sss_nr +* NAME : pss_sss_extract_nr * * PARAMETERS : none * @@ -397,11 +399,12 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, *********************************************************************/ int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue, + UE_nr_rxtx_proc_t *proc, int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR], - uint8_t subframe) + uint8_t subframe) { - return do_pss_sss_extract_nr(phy_vars_ue, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe); + return do_pss_sss_extract_nr(phy_vars_ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe); } /******************************************************************* @@ -417,7 +420,7 @@ int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue, * *********************************************************************/ -int rx_sss_nr(PHY_VARS_NR_UE *ue, int32_t *tot_metric,uint8_t *phase_max) +int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, uint8_t *phase_max) { uint8_t i; int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR]; @@ -433,6 +436,7 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, int32_t *tot_metric,uint8_t *phase_max) // pss sss extraction pss_sss_extract_nr(ue, + proc, pss_ext, sss_ext, 0); /* subframe */ @@ -440,8 +444,8 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, int32_t *tot_metric,uint8_t *phase_max) #ifdef DEBUG_PLOT_SSS write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1); - write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[0]].rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1); - write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[0]].rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); + write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1); + write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1); #endif diff --git a/openair1/PHY/TOOLS/calibration_scope.c b/openair1/PHY/TOOLS/calibration_scope.c new file mode 100644 index 0000000000..da1acb5175 --- /dev/null +++ b/openair1/PHY/TOOLS/calibration_scope.c @@ -0,0 +1,387 @@ +#include +#include +#include "executables/softmodem-common.h" +#include "executables/nr-softmodem-common.h" +#include +#include + +#define TPUT_WINDOW_LENGTH 100 +#define ScaleZone 4 + +const FL_COLOR rx_antenna_colors[4] = {FL_RED,FL_BLUE,FL_GREEN,FL_YELLOW}; +const FL_COLOR water_colors[4] = {FL_BLUE,FL_GREEN,FL_YELLOW,FL_RED}; + +typedef struct { + int16_t r; + int16_t i; +} scopeSample_t; +#define SquaredNorm(VaR) ((VaR).r*(VaR).r+(VaR).i*(VaR).i) +typedef struct { + void ** samplesRx; + openair0_device *rfdevice; +} calibData_t; + +typedef struct OAIgraph { + FL_OBJECT *graph; + FL_OBJECT *text; + float maxX; + float maxY; + float minX; + float minY; + int x; + int y; + int w; + int h; + int waterFallh; + double *waterFallAvg; + boolean_t initDone; + int iteration; + void (*funct) (struct OAIgraph *graph, calibData_t *); +} OAIgraph_t; + + +/* Forms and Objects */ +typedef struct { + calibData_t * context; + FL_FORM *phy_scope; + OAIgraph_t graph[20]; + FL_OBJECT *button_0; +} OAI_phy_scope_t; + +typedef struct { + FL_FORM *stats_form; + void *vdata; + char *cdata; + long ldata; + FL_OBJECT *stats_text; + FL_OBJECT *stats_button; +} FD_stats_form; + +static void drawsymbol(FL_OBJECT *obj, int id, + FL_POINT *p, int n, int w, int h) { + fl_points( p, n, FL_YELLOW); +} + +#define WATERFALL 10000 + +static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { + if (type==WATERFALL) { + graph->waterFallh=h-15; + graph->waterFallAvg=malloc(sizeof(*graph->waterFallAvg) * graph->waterFallh); + + for (int i=0; i< graph->waterFallh; i++) + graph->waterFallAvg[i]=0; + + graph->graph=fl_add_canvas(FL_NORMAL_CANVAS, x, y, w, graph->waterFallh, label); + graph->text=fl_add_text(FL_NORMAL_TEXT, x, y+graph->waterFallh, w, 15, label); + fl_set_object_lcolor(graph->text,FL_WHITE); + fl_set_object_color(graph->text, FL_BLACK, FL_BLACK); + fl_set_object_lalign(graph->text, FL_ALIGN_CENTER ); + } else { + graph->graph=fl_add_xyplot(type, x, y, w, h, label); + fl_set_object_lcolor(graph->graph, FL_WHITE ); // Label color + fl_set_object_color(graph->graph, FL_BLACK, pointColor); + + for (int i=0; i< FL_MAX_XYPLOTOVERLAY; i++) + fl_set_xyplot_symbol(graph->graph, i, drawsymbol); + } + + graph->x=x; + graph->y=y; + graph->w=w; + graph->h=h; + graph->maxX=0; + graph->maxY=0; + graph->minX=0; + graph->minY=0; + graph->initDone=false; + graph->iteration=0; +} + +static OAIgraph_t calibrationCommonGraph( void (*funct) (OAIgraph_t *graph, calibData_t *context), + int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { + OAIgraph_t graph; + commonGraph(&graph, type, x, y, w, h, label, pointColor); + graph.funct=funct; + return graph; +} + + +static void setRange(OAIgraph_t *graph, float minX, float maxX, float minY, float maxY) { + if ( maxX > graph->maxX || minX < graph->minX || + abs(maxX-graph->maxX)>abs(graph->maxX)/2 || + abs(maxX-graph->maxX)>abs(graph->maxX)/2 ) { + graph->maxX/=2; + graph->minX/=2; + graph->maxX=max(graph->maxX,maxX); + graph->minX=min(graph->minX,minX); + fl_set_xyplot_xbounds(graph->graph, graph->minX*1.2, graph->maxX*1.2); + } + + if ( maxY > graph->maxY || minY < graph->minY || + abs(maxY-graph->maxY)>abs(graph->maxY)/2 || + abs(maxY-graph->maxY)>abs(graph->maxY)/2 ) { + graph->maxY/=2; + graph->minY/=2; + graph->maxY=max(graph->maxY,maxY); + graph->minY=min(graph->minY,minY); + fl_set_xyplot_ybounds(graph->graph, graph->minY*1.2, graph->maxY*1.2); + } +} + +static void oai_xygraph_getbuff(OAIgraph_t *graph, float **x, float **y, int len, int layer) { + float *old_x; + float *old_y; + int old_len=-1; + + if (graph->iteration >1) + fl_get_xyplot_data_pointer(graph->graph, layer, &old_x, &old_y, &old_len); + + if (old_len != len) { + LOG_W(HW,"allocating graph of %d scope\n", len); + float values[len]; + float time[len]; + + // make time in case we will use it + for (int i=0; igraph,time,values,len,"","",""); + else + fl_add_xyplot_overlay(graph->graph,layer,time,values,len,rx_antenna_colors[layer]); + + fl_get_xyplot_data_pointer(graph->graph, layer, &old_x, &old_y, &old_len); + AssertFatal(old_len==len,""); + } + + *x=old_x; + *y=old_y; +} + +static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, boolean_t NoAutoScale) { + fl_redraw_object(graph->graph); + + if ( NoAutoScale && graph->iteration%NoAutoScale == 0) { + float maxX=0, maxY=0, minX=0, minY=0; + + for (int k=0; kiteration++; +} + +static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize, const int divisions, const char *label) { + if ( values == NULL ) + return; + fl_winset(FL_ObjWin(graph->graph)); + const int samplesPerPixel=datasize/graph->w; + int displayPart=graph->waterFallh-ScaleZone; + int row=graph->iteration%displayPart; + double avg=0; + + for (int i=0; i < displayPart; i++) + avg+=graph->waterFallAvg[i]; + + avg/=displayPart; + graph->waterFallAvg[row]=0; + + for (int pix=0; pixw; pix++) { + scopeSample_t *end=values+(pix+1)*samplesPerPixel; + end-=2; + AssertFatal(end <= values+datasize,"diff : %ld", end-values+datasize); + double val=0; + + for (scopeSample_t *s=values+(pix)*samplesPerPixel; + s waterFallAvg[row]+=val/graph->w; + int col=0; + + if (val > avg*2 ) + col=1; + + if (val > avg*10 ) + col=2; + + if (val > avg*100 ) + col=3; + + fl_point(pix, graph->iteration%displayPart, water_colors[col]); + } + + if (graph->initDone==false) { + for ( int i=0; i < graph->waterFallh; i++ ) + for ( int j = 0 ; j < graph->w ; j++ ) + fl_point(j, i, FL_BLACK); + + for ( int i=1; iwaterFallh; j++) + fl_point(i*(graph->w/divisions),j, FL_WHITE); + + graph->initDone=true; + } + + fl_set_object_label_f(graph->text, "%s, avg I/Q pow: %4.1f", label, sqrt(avg)); + graph->iteration++; +} + +static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) { + float *values, *time; + oai_xygraph_getbuff(graph, &time, &values, len, 0); + + for (int ant=0; antsamplesRx[0], + 0, 0, + "X axis:one frame in time"); +} +static void gNBfreqWaterFall (OAIgraph_t *graph, calibData_t *context) { + //use 1st antenna + genericWaterFall(graph, (scopeSample_t *)context->samplesRx[0], + 0, 0, + "X axis:one frame in time"); +} +static void timeResponse (OAIgraph_t *graph, calibData_t *context) { + #if 0 + const int len=2*phy_vars_gnb->frame_parms.ofdm_symbol_size; + float *values, *time; + oai_xygraph_getbuff(graph, &time, &values, len, 0); + const int ant=0; // display antenna 0 for each UE + + for (int ue=0; uepusch_vars[ue]->ul_ch_estimates_time[ant]; + + if (data != NULL) { + for (int i=0; iframe_parms; + int sz=frame_parms->N_RB_UL*12*frame_parms->symbols_per_slot; + + for (int ue=0; uepusch_vars[ue]->rxdataF_comp[0]; + float *I, *Q; + oai_xygraph_getbuff(graph, &I, &Q, sz, ue); + + if (pusch_comp) { + for (int k=0; kcontext=context; + // Define form + fdui->phy_scope = fl_bgn_form( FL_NO_BOX, 800, 800 ); + // This the whole UI box + obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 800, "" ); + fl_set_object_color( obj, FL_BLACK, FL_WHITE ); + int curY=0,x,y,w,h; + // Received signal + fdui->graph[0] = calibrationCommonGraph( gNBWaterFall, WATERFALL, 0, curY, 400, 100, + "Received Signal (Time-Domain, one frame)", FL_RED ); + + // Time-domain channel response + //fdui->graph[1] = calibrationCommonGraph( timeResponse, FL_NORMAL_XYPLOT, 410, curY, 400, 100, "SRS Frequency Response (samples, abs)", FL_RED ); + fl_get_object_bbox(fdui->graph[0].graph,&x, &y,&w, &h); + curY+=h; + // Frequency-domain channel response + fdui->graph[1] = calibrationCommonGraph( gNBfreqWaterFall, WATERFALL, 0, curY, 800, 100, + "Channel Frequency domain (RE, one frame)", FL_RED ); + fl_get_object_bbox(fdui->graph[1].graph,&x, &y,&w, &h); + curY+=h+20; + // LLR of PUSCH + //fdui->graph[3] = calibrationCommonGraph( puschLLR, FL_POINTS_XYPLOT, 0, curY, 500, 200, "PUSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW ); + // I/Q PUSCH comp + fdui->graph[2] = calibrationCommonGraph( puschIQ, FL_POINTS_XYPLOT, 500, curY, 300, 200, + "PUSCH I/Q of MF Output", FL_YELLOW ); + fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h); + curY+=h; + //fl_get_object_bbox(fdui->graph[6].graph,&x, &y,&w, &h); + curY+=h; + fdui->graph[3].graph=NULL; + fl_end_form( ); + fdui->phy_scope->fdui = fdui; + fl_show_form (fdui->phy_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, "LTE UL SCOPE gNB"); + return fdui; +} + +void calibrationScope(OAI_phy_scope_t *form) { + int i=0; + + while (form->graph[i].graph) { + form->graph[i].funct(form->graph+i, form->context); + i++; + } + + //fl_check_forms(); +} + +static void *scopeThread(void *arg) { + calibData_t * context = (calibData_t *)arg; + size_t stksize=0; + pthread_attr_t atr; + pthread_attr_init(&atr); + pthread_attr_getstacksize(&atr, &stksize); + pthread_attr_setstacksize(&atr,32*1024*1024 ); + sleep(3); // no clean interthread barriers + int fl_argc=1; + char *name="Calibration-scope"; + fl_initialize (&fl_argc, &name, NULL, 0, 0); + OAI_phy_scope_t *form = createScopeCalibration(context); + + while (!oai_exit) { + calibrationScope(form); + usleep(99*1000); + } + + return NULL; +} + +void CalibrationInitScope(void ** samplesRx,openair0_device *rfdevice) { + pthread_t forms_thread; + calibData_t * tmp=(calibData_t *) malloc(sizeof(*tmp)); + tmp->samplesRx=samplesRx; + tmp->rfdevice=rfdevice; + threadCreate(&forms_thread, scopeThread, (void*) tmp, "scope", -1, OAI_PRIORITY_RT_LOW); +} diff --git a/openair1/PHY/TOOLS/calibration_scope.h b/openair1/PHY/TOOLS/calibration_scope.h new file mode 100644 index 0000000000..052a1a6b6e --- /dev/null +++ b/openair1/PHY/TOOLS/calibration_scope.h @@ -0,0 +1,5 @@ +#ifndef CALIB_SCOPE_H +#define CALIB_SCOPE_H + +void CalibrationInitScope(void ** samplesRx,openair0_device *rfdevice); +#endif diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c new file mode 100644 index 0000000000..53baf83d41 --- /dev/null +++ b/openair1/PHY/TOOLS/calibration_test.c @@ -0,0 +1,340 @@ +#include +#include +#include +#include +#include + + +volatile int oai_exit=false; +unsigned int mmapped_dma=0; +int single_thread_flag; +uint32_t timing_advance; +int8_t threequarter_fs; +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int opp_enabled; +static double snr_dB=20; +THREAD_STRUCT thread_struct; +uint32_t target_ul_mcs = 9; +uint32_t target_dl_mcs = 9; +uint64_t dlsch_slot_bitmap = (1<<1); +uint64_t ulsch_slot_bitmap = (1<<8); +uint32_t target_ul_bw = 50; +uint32_t target_dl_bw = 50; +#include + +int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state) {return 0;} +void nfapi_setmode(nfapi_mode_t nfapi_mode) {} +void set_taus_seed(unsigned int seed_init){}; + +int main(int argc, char **argv) { + ///static configuration for NR at the moment + if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + set_softmodem_sighandler(); + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); + logInit(); + paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ; + + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + get_common_options(SOFTMODEM_GNB_BIT ); + config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); + configure_linux(); + + + int N_RB=50; + int subCarrierFreq=30e3; + int sampling_rate=30.72e6; + int DFT=2048; + int TxAdvanceInDFTSize=12; + int antennas=1; + uint64_t freq=3619.200e6; + int rxGain=90; + int txGain=90; + int filterBand=40e6; + char * usrp_addrs="type=b200"; + + openair0_config_t openair0_cfg= { + //! Module ID for this configuration + .Mod_id=0, + //! device log level + .log_level=0, + //! duplexing mode + .duplex_mode=0, + //! number of downlink resource blocks + .num_rb_dl=N_RB, + //! number of samples per frame + .samples_per_frame=0, + //! the sample rate for both transmit and receive. + .sample_rate=sampling_rate, + //device is doing mmapped DMA transfers + .mmapped_dma=0, + //! offset in samples between TX and RX paths + .tx_sample_advance=0, + //! samples per packet on the fronthaul interface + .samples_per_packet=1024, + //! number of RX channels (=RX antennas) + .rx_num_channels=antennas, + //! number of TX channels (=TX antennas) + .tx_num_channels=antennas, + //! \brief Center frequency in Hz for RX. + //! index: [0..rx_num_channels[ + .rx_freq={freq,freq,freq,freq}, + //! \brief Center frequency in Hz for TX. + //! index: [0..rx_num_channels[ !!! see lte-ue.c:427 FIXME iterates over rx_num_channels + .tx_freq={freq,freq,freq,freq}, + //! \brief memory + //! \brief Pointer to Calibration table for RX gains + .rx_gain_calib_table=NULL, + //! mode for rxgain (ExpressMIMO2) + .rxg_mode={0}, + //! \brief Gain for RX in dB. + //! index: [0..rx_num_channels] + .rx_gain={rxGain,rxGain,rxGain,rxGain}, + //! \brief Gain offset (for calibration) in dB + //! index: [0..rx_num_channels] + .rx_gain_offset={0}, + //! gain for TX in dB + .tx_gain={txGain,txGain,txGain,txGain}, + //! RX bandwidth in Hz + .rx_bw=filterBand, + //! TX bandwidth in Hz + .tx_bw=filterBand, + //! clock source + .clock_source=external,//internal gpsdo external + //! timing_source + .time_source=internal, //internal gpsdo external + //! Manual SDR IP address + //#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) + .sdr_addrs=usrp_addrs, + //! Auto calibration flag + .autocal={0}, + //! rf devices work with x bits iqs when oai have its own iq format + //! the two following parameters are used to convert iqs + .iq_txshift=0, + .iq_rxrescale=0, + //! Configuration file for LMS7002M + .configFilename="", + //! remote IP/MAC addr for Ethernet interface + .remote_addr="", + //! remote port number for Ethernet interface + .remote_port=0, + //! local IP/MAC addr for Ethernet interface (eNB/BBU, UE) + .my_addr=0, + //! local port number for Ethernet interface (eNB/BBU, UE) + .my_port=0, + //! record player configuration, definition in record_player.h + .recplay_mode=0, + .recplay_conf=NULL, + //! number of samples per tti + .samples_per_tti=0, + //! check for threequarter sampling rate + .threequarter_fs=0, + }; + //----------------------- + openair0_device rfdevice= { + /*!tx write thread*/ + //.write_thread={0}, + /*!brief Module ID of this device */ + .Mod_id=0, + /*!brief Component Carrier ID of this device */ + .CC_id=0, + /*!brief Type of this device */ + .type=NONE_DEV, + /*!brief Transport protocol type that the device supports (in case I/Q samples need to be transported) */ + .transp_type=NONE_TP, + /*!brief Type of the device's host (RAU/RRU) */ + .host_type=MIN_HOST_TYPE, + /* !brief RF frontend parameters set by application */ + .openair0_cfg=NULL, //set by device_init + /* !brief ETH params set by application */ + .eth_params=NULL, + //! record player data, definition in record_player.h + .recplay_state=NULL, + /* !brief Indicates if device already initialized */ + .is_init=0, + /*!brief Can be used by driver to hold internal structure*/ + .priv=NULL, + /* Functions API, which are called by the application*/ + /*! \brief Called to start the transceiver. Return 0 if OK, < 0 if error + @param device pointer to the device structure specific to the RF hardware target + */ + .trx_start_func=NULL, + + /*! \brief Called to configure the device + @param device pointer to the device structure specific to the RF hardware target + */ + .trx_config_func=NULL, + + /*! \brief Called to send a request message between RAU-RRU on control port + @param device pointer to the device structure specific to the RF hardware target + @param msg pointer to the message structure passed between RAU-RRU + @param msg_len length of the message + */ + .trx_ctlsend_func=NULL, + + /*! \brief Called to receive a reply message between RAU-RRU on control port + @param device pointer to the device structure specific to the RF hardware target + @param msg pointer to the message structure passed between RAU-RRU + @param msg_len length of the message + */ + .trx_ctlrecv_func=NULL, + + /*! \brief Called to send samples to the RF target + @param device pointer to the device structure specific to the RF hardware target + @param timestamp The timestamp at whicch the first sample MUST be sent + @param buff Buffer which holds the samples (2 dimensional) + @param nsamps number of samples to be sent + @param number of antennas + @param flags flags must be set to TRUE if timestamp parameter needs to be applied + */ + .trx_write_func=NULL, + + /*! \brief Called to send samples to the RF target + @param device pointer to the device structure specific to the RF hardware target + @param timestamp The timestamp at whicch the first sample MUST be sent + @param buff Buffer which holds the samples (1 dimensional) + @param nsamps number of samples to be sent + @param antenna_id index of the antenna if the device has multiple anteannas + @param flags flags must be set to TRUE if timestamp parameter needs to be applied + */ + .trx_write_func2=NULL, + + /*! \brief Receive samples from hardware. + * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for + * the first channel. *ptimestamp is the time at which the first sample + * was received. + * \param device the hardware to use + * \param[out] ptimestamp the time at which the first sample was received. + * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps. + * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. + * \param num_antennas number of antennas from which to receive samples + * \returns the number of sample read + */ + + .trx_read_func=NULL, + + /*! \brief Receive samples from hardware, this version provides a single antenna at a time and returns. + * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for + * the first channel. *ptimestamp is the time at which the first sample + * was received. + * \param device the hardware to use + * \param[out] ptimestamp the time at which the first sample was received. + * \param[out] buff A pointers to a buffer for received samples. The buffer must be large enough to hold the number of samples \ref nsamps. + * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. + * \param antenna_id Index of antenna from which samples were received + * \returns the number of sample read + */ + .trx_read_func2=NULL, + + /*! \brief print the device statistics + * \param device the hardware to use + * \returns 0 on success + */ + /*! \brief print the device statistics + * \param device the hardware to use + * \returns 0 on success + */ + .trx_get_stats_func=NULL, + + /*! \brief Reset device statistics + * \param device the hardware to use + * \returns 0 in success + */ + .trx_reset_stats_func=NULL, + + /*! \brief Terminate operation of the transceiver -- free all associated resources + * \param device the hardware to use + */ + .trx_end_func=NULL, + + /*! \brief Stop operation of the transceiver + */ + .trx_stop_func=NULL, + + /* Functions API related to UE*/ + + /*! \brief Set RX feaquencies + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + * \param exmimo_dump_config dump EXMIMO configuration + * \returns 0 in success + */ + .trx_set_freq_func=NULL, + + /*! \brief Set gains + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + * \returns 0 in success + */ + .trx_set_gains_func=NULL, + + /*! \brief RRU Configuration callback + * \param idx RU index + * \param arg pointer to capabilities or configuration + */ + .configure_rru=NULL, + /*! \brief Pointer to generic RRU private information + */ + .thirdparty_priv=NULL, + .thirdparty_init=NULL, + /*! \brief Callback for Third-party RRU Cleanup routine + \param device the hardware configuration to use + */ + .thirdparty_cleanup=NULL, + + /*! \brief Callback for Third-party start streaming routine + \param device the hardware configuration to use + */ + .thirdparty_startstreaming=NULL, + + /*! \brief RRU Configuration callback + * \param idx RU index + * \param arg pointer to capabilities or configuration + */ + .trx_write_init=NULL, + /* \brief Get internal parameter + * \param id parameter to get + * \return a pointer to the parameter + */ + .get_internal_parameter=NULL, + }; + + openair0_device_load(&rfdevice,&openair0_cfg); + + void ** samplesRx = (void **)malloc16(antennas* sizeof(struct complex16 *) ); + void ** samplesTx = (void **)malloc16(antennas* sizeof(struct complex16 *) ); + + int fd=open(getenv("rftestInputFile"),O_RDONLY); + AssertFatal(fd>=0,"%s",strerror(errno)); + + for (int i=0; i> shift_right) & tbl_addr_mask; + dB_power = dB_fix_x10_tbl[Mantissa] + Exponent * 30u; + } + return dB_power; +} + int16_t dB_fixed_times10(uint32_t x) { int16_t dB_power=0; diff --git a/openair1/PHY/TOOLS/dB_routines.h b/openair1/PHY/TOOLS/dB_routines.h index c28184259f..185913cf5b 100644 --- a/openair1/PHY/TOOLS/dB_routines.h +++ b/openair1/PHY/TOOLS/dB_routines.h @@ -30,5 +30,6 @@ #define DB_ROUTINES_H_ int16_t dB_fixed_times10(uint32_t x); +int16_t dB_fixed_x10(uint32_t x); #endif /* DB_ROUTINES_H_ */ diff --git a/openair1/PHY/TOOLS/lte_enb_scope.c b/openair1/PHY/TOOLS/lte_enb_scope.c index b2c6bd909f..bed507feee 100644 --- a/openair1/PHY/TOOLS/lte_enb_scope.c +++ b/openair1/PHY/TOOLS/lte_enb_scope.c @@ -44,7 +44,6 @@ FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; char title[255]; unsigned char scope_enb_num_ue = 2; static pthread_t forms_thread; //xforms -int otg_enabled=0; void reset_stats(FL_OBJECT *button, long arg) { int i,j,k; @@ -70,18 +69,12 @@ void reset_stats(FL_OBJECT *button, long arg) { static void *scope_thread_eNB(void *arg) { -# ifdef ENABLE_XFORMS_WRITE_STATS - FILE *eNB_stats; -# endif struct sched_param sched_param; int UE_id, CC_id; int ue_cnt=0; sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; sched_setscheduler(0, SCHED_FIFO,&sched_param); printf("Scope thread has priority %d\n",sched_param.sched_priority); -# ifdef ENABLE_XFORMS_WRITE_STATS - eNB_stats = fopen("eNB_stats.txt", "w"); -#endif while (!oai_exit) { ue_cnt=0; @@ -97,19 +90,9 @@ static void *scope_thread_eNB(void *arg) { } } - sleep(1); + usleep(100*1000); } - // printf("%s",stats_buffer); -# ifdef ENABLE_XFORMS_WRITE_STATS - - if (eNB_stats) { - rewind (eNB_stats); - fwrite (stats_buffer, 1, len, eNB_stats); - fclose (eNB_stats); - } - -# endif pthread_exit((void *)arg); } @@ -131,7 +114,7 @@ int enbscope_autoinit(void) { sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id); fl_show_form (form_enb[CC_id][UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); - if (otg_enabled) { + if (0) { fl_set_button(form_enb[CC_id][UE_id]->button_0,1); fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic ON"); } else { diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 8621898d9d..d28bb1b8ba 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -27,7 +27,6 @@ #include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h" #define TPUT_WINDOW_LENGTH 100 -int otg_enabled; FL_COLOR rx_antenna_colors[4] = {FL_RED,FL_BLUE,FL_GREEN,FL_YELLOW}; @@ -37,9 +36,12 @@ float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_ue_max[NUMBER_OF_UE_MAX] = {0}; -static void ia_receiver_on_off( FL_OBJECT *button, long arg) -{ +void drawsymbol(FL_OBJECT *obj, int id, + FL_POINT *p, int n, int w, int h) { + fl_points( p, n, FL_YELLOW); +} +static void ia_receiver_on_off( FL_OBJECT *button, long arg) { if (fl_get_button(button)) { fl_set_object_label(button, "IA Receiver ON"); // PHY_vars_UE_g[0][0]->use_ia_receiver = 1; @@ -51,60 +53,48 @@ static void ia_receiver_on_off( FL_OBJECT *button, long arg) } } -static void dl_traffic_on_off( FL_OBJECT *button, long arg) -{ - +static void dl_traffic_on_off( FL_OBJECT *button, long arg) { if (fl_get_button(button)) { fl_set_object_label(button, "DL Traffic ON"); - otg_enabled = 1; fl_set_object_color(button, FL_GREEN, FL_GREEN); } else { fl_set_object_label(button, "DL Traffic OFF"); - otg_enabled = 0; fl_set_object_color(button, FL_RED, FL_RED); } } -FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) -{ - +FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) { FL_OBJECT *obj; FD_lte_phy_scope_enb *fdui = fl_malloc( sizeof *fdui ); - // Define form fdui->lte_phy_scope_enb = fl_bgn_form( FL_NO_BOX, 800, 800 ); - // This the whole UI box obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 800, "" ); fl_set_object_color( obj, FL_BLACK, FL_BLACK ); - // Received signal fdui->rxsig_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 20, 370, 100, "Received Signal (Time-Domain, dB)" ); fl_set_object_boxtype( fdui->rxsig_t, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->rxsig_t, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->rxsig_t, FL_WHITE ); // Label color fl_set_xyplot_ybounds(fdui->rxsig_t,10,70); - // Time-domain channel response fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "SRS Frequency Response (samples, abs)" ); fl_set_object_boxtype( fdui->chest_t, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->chest_t, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->chest_t, FL_WHITE ); // Label color - // Frequency-domain channel response fdui->chest_f = fl_add_xyplot( FL_IMPULSE_XYPLOT, 20, 140, 760, 100, "Channel Frequency Response (RE, dB)" ); fl_set_object_boxtype( fdui->chest_f, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->chest_f, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->chest_f, FL_WHITE ); // Label color fl_set_xyplot_ybounds( fdui->chest_f,30,70); - // LLR of PUSCH fdui->pusch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 260, 500, 200, "PUSCH Log-Likelihood Ratios (LLR, mag)" ); fl_set_object_boxtype( fdui->pusch_llr, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->pusch_llr, FL_BLACK, FL_YELLOW ); fl_set_object_lcolor( fdui->pusch_llr, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pusch_llr,2); - + fl_set_xyplot_symbol(fdui->pusch_llr, 0, drawsymbol); // I/Q PUSCH comp fdui->pusch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 260, 240, 200, "PUSCH I/Q of MF Output" ); fl_set_object_boxtype( fdui->pusch_comp, FL_EMBOSSED_BOX ); @@ -112,7 +102,7 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) fl_set_object_lcolor( fdui->pusch_comp, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pusch_comp,2); fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); - + fl_set_xyplot_symbol(fdui->pusch_comp, 0, drawsymbol); // I/Q PUCCH comp (format 1) fdui->pucch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 480, 240, 100, "PUCCH1 Energy (SR)" ); fl_set_object_boxtype( fdui->pucch_comp1, FL_EMBOSSED_BOX ); @@ -120,7 +110,7 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) fl_set_object_lcolor( fdui->pucch_comp1, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pucch_comp1,2); // fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); - + fl_set_xyplot_symbol(fdui->pucch_comp1, 0, drawsymbol); // I/Q PUCCH comp (fromat 1a/b) fdui->pucch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 600, 240, 100, "PUCCH I/Q of MF Output" ); fl_set_object_boxtype( fdui->pucch_comp, FL_EMBOSSED_BOX ); @@ -128,33 +118,28 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) fl_set_object_lcolor( fdui->pucch_comp, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pucch_comp,2); // fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); - + fl_set_xyplot_symbol(fdui->pucch_comp, 0, drawsymbol); // Throughput on PUSCH fdui->pusch_tput = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 480, 500, 100, "PUSCH Throughput [frame]/[kbit/s]" ); fl_set_object_boxtype( fdui->pusch_tput, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->pusch_tput, FL_BLACK, FL_WHITE ); fl_set_object_lcolor( fdui->pusch_tput, FL_WHITE ); // Label color - // Generic eNB Button fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 20, 600, 240, 40, "" ); fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER ); fl_set_button(fdui->button_0,0); - otg_enabled = 0; fl_set_object_label(fdui->button_0, "DL Traffic OFF"); fl_set_object_color(fdui->button_0, FL_RED, FL_RED); fl_set_object_callback(fdui->button_0, dl_traffic_on_off, 0 ); - fl_end_form( ); fdui->lte_phy_scope_enb->fdui = fdui; - return fdui; } void phy_scope_eNB(FD_lte_phy_scope_enb *form, PHY_VARS_eNB *phy_vars_enb, - int UE_id) -{ - + int UE_id) { + LOG_D(HW,"scope for UE%d\n", UE_id); int i,i2,arx,atx,ind,k; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_enb->frame_parms; int nsymb_ce = 12*frame_parms->N_RB_UL*frame_parms->symbols_per_tti; @@ -164,7 +149,6 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, int16_t **chest_t; int16_t **chest_f; int16_t *pusch_llr; - int32_t *pusch_comp; int32_t *pucch1_comp; int32_t *pucch1_thres; int32_t *pucch1ab_comp; @@ -192,20 +176,17 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, } coded_bits_per_codeword = frame_parms->N_RB_UL*12*Qm*frame_parms->symbols_per_tti; - - chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); - llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero + chest_f_abs = (float *) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); + llr = (float *) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero bit = malloc(coded_bits_per_codeword*sizeof(float)); - - rxsig_t = (int16_t**) phy_vars_enb->RU_list[0]->common.rxdata; - //chest_t = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id]; - chest_t = (int16_t**) phy_vars_enb->srs_vars[UE_id].srs_ch_estimates; - chest_f = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates; - pusch_llr = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->llr; - pusch_comp = (int32_t*) phy_vars_enb->pusch_vars[UE_id]->rxdataF_comp[0]; - pucch1_comp = (int32_t*) phy_vars_enb->pucch1_stats[UE_id]; - pucch1_thres = (int32_t*) phy_vars_enb->pucch1_stats_thres[UE_id]; - pucch1ab_comp = (int32_t*) phy_vars_enb->pucch1ab_stats[UE_id]; + rxsig_t = (int16_t **) phy_vars_enb->RU_list[0]->common.rxdata; + chest_t = (int16_t **) phy_vars_enb->srs_vars[UE_id].srs_ch_estimates; + chest_f = (int16_t **) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates; + pusch_llr = (int16_t *) phy_vars_enb->pusch_vars[UE_id]->llr; + int16_t *pusch_comp= (int16_t *) phy_vars_enb->pusch_vars[UE_id]->rxdataF_comp[0]; + pucch1_comp = (int32_t *) phy_vars_enb->pucch1_stats[UE_id]; + pucch1_thres = (int32_t *) phy_vars_enb->pucch1_stats_thres[UE_id]; + pucch1ab_comp = (int32_t *) phy_vars_enb->pucch1ab_stats[UE_id]; // Received signal in time domain of receive antenna 0 if (rxsig_t != NULL) { @@ -236,7 +217,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, if (chest_t[0] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size); i++) { //i2 = (i+(frame_parms->ofdm_symbol_size>>1))%frame_parms->ofdm_symbol_size; - i2=i; + i2=i; //time2[i] = (float)(i-(frame_parms->ofdm_symbol_size>>1)); time2[i] = (float)i; chest_t_abs[0][i] = 10*log10((float) (1+chest_t[0][2*i2]*chest_t[0][2*i2]+chest_t[0][2*i2+1]*chest_t[0][2*i2+1])); @@ -278,7 +259,6 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, freq[ind] = (float)ind; Re = (float)(chest_f[(atx<<1)+arx][(2*k)]); Im = (float)(chest_f[(atx<<1)+arx][(2*k)+1]); - chest_f_abs[ind] = (short)10*log10(1.0+((double)Re*Re + (double)Im*Im)); ind++; } @@ -333,9 +313,9 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i] < range && pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1] > -range && pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1] < range ) { - I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; - Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; - ind++; + I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; + Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; + ind++; } } } @@ -346,75 +326,62 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, // PUSCH I/Q of MF Output if (pucch1ab_comp!=NULL) { for (ind=0; ind<10240; ind++) { - I_pucch[ind] = (float)pucch1ab_comp[2*(ind)]; Q_pucch[ind] = (float)pucch1ab_comp[2*(ind)+1]; A_pucch[ind] = 10*log10(pucch1_comp[ind]); B_pucch[ind] = ind; C_pucch[ind] = (float)pucch1_thres[ind]; } + fl_set_xyplot_data(form->pucch_comp,I_pucch,Q_pucch,10240,"","",""); fl_set_xyplot_data(form->pucch_comp1,B_pucch,A_pucch,1024,"","",""); fl_add_xyplot_overlay(form->pucch_comp1,1,B_pucch,C_pucch,1024,FL_RED); fl_set_xyplot_ybounds(form->pucch_comp,-5000,5000); fl_set_xyplot_xbounds(form->pucch_comp,-5000,5000); - fl_set_xyplot_ybounds(form->pucch_comp1,0,80); } - // PUSCH Throughput memmove( tput_time_enb[UE_id], &tput_time_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); memmove( tput_enb[UE_id], &tput_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); - tput_time_enb[UE_id][TPUT_WINDOW_LENGTH-1] = (float) frame; tput_enb[UE_id][TPUT_WINDOW_LENGTH-1] = ((float) total_dlsch_bitrate)/1000.0; - fl_set_xyplot_data(form->pusch_tput,tput_time_enb[UE_id],tput_enb[UE_id],TPUT_WINDOW_LENGTH,"","",""); - // fl_get_xyplot_ybounds(form->pusch_tput,&ymin,&ymax); // fl_set_xyplot_ybounds(form->pusch_tput,0,ymax); - fl_check_forms(); - free(llr); free(bit); free(chest_f_abs); } -FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) -{ - +FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) { FL_OBJECT *obj; FD_lte_phy_scope_ue *fdui = fl_malloc( sizeof *fdui ); - // Define form fdui->lte_phy_scope_ue = fl_bgn_form( FL_NO_BOX, 800, 900 ); - // This the whole UI box obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 900, "" ); fl_set_object_color( obj, FL_BLACK, FL_BLACK ); - // Received signal fdui->rxsig_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 20, 370, 100, "Received Signal (Time-Domain, dB)" ); fl_set_object_boxtype( fdui->rxsig_t, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->rxsig_t, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->rxsig_t, FL_WHITE ); // Label color fl_set_xyplot_ybounds(fdui->rxsig_t,10,70); - + fl_set_xyplot_symbol(fdui->rxsig_t, 0, drawsymbol); // Time-domain channel response fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)" ); fl_set_object_boxtype( fdui->chest_t, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->chest_t, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->chest_t, FL_WHITE ); // Label color - + fl_set_xyplot_symbol(fdui->chest_t, 0, drawsymbol); // Frequency-domain channel response fdui->chest_f = fl_add_xyplot( FL_IMPULSE_XYPLOT, 20, 140, 760, 100, "Channel Frequency Response (RE, dB)" ); fl_set_object_boxtype( fdui->chest_f, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->chest_f, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->chest_f, FL_WHITE ); // Label color fl_set_xyplot_ybounds( fdui->chest_f,30,70); - // LLR of PBCH fdui->pbch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 260, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)" ); fl_set_object_boxtype( fdui->pbch_llr, FL_EMBOSSED_BOX ); @@ -423,23 +390,23 @@ FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) fl_set_xyplot_symbolsize( fdui->pbch_llr,2); fl_set_xyplot_xgrid( fdui->pbch_llr,FL_GRID_MAJOR); fl_set_xyplot_xbounds( fdui->pbch_llr,0,1920); - + fl_set_xyplot_symbol(fdui->pbch_llr, 0, drawsymbol); // I/Q PBCH comp fdui->pbch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 260, 240, 100, "PBCH I/Q of MF Output" ); fl_set_object_boxtype( fdui->pbch_comp, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->pbch_comp, FL_BLACK, FL_GREEN ); fl_set_object_lcolor( fdui->pbch_comp, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pbch_comp,2); + fl_set_xyplot_symbol(fdui->pbch_comp, 0, drawsymbol); // fl_set_xyplot_xbounds( fdui->pbch_comp,-100,100); // fl_set_xyplot_ybounds( fdui->pbch_comp,-100,100); - // LLR of PDCCH fdui->pdcch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 380, 500, 100, "PDCCH Log-Likelihood Ratios (LLR, mag)" ); fl_set_object_boxtype( fdui->pdcch_llr, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->pdcch_llr, FL_BLACK, FL_CYAN ); fl_set_object_lcolor( fdui->pdcch_llr, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pdcch_llr,2); - + fl_set_xyplot_symbol(fdui->pdcch_llr, 0, drawsymbol); // I/Q PDCCH comp fdui->pdcch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 380, 240, 100, "PDCCH I/Q of MF Output" ); fl_set_object_boxtype( fdui->pdcch_comp, FL_EMBOSSED_BOX ); @@ -447,7 +414,7 @@ FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) fl_set_object_lcolor( fdui->pdcch_comp, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pdcch_comp,2); fl_set_xyplot_xgrid( fdui->pdcch_llr,FL_GRID_MAJOR); - + fl_set_xyplot_symbol(fdui->pdcch_comp, 0, drawsymbol); // LLR of PDSCH fdui->pdsch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 500, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)" ); fl_set_object_boxtype( fdui->pdsch_llr, FL_EMBOSSED_BOX ); @@ -455,20 +422,19 @@ FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) fl_set_object_lcolor( fdui->pdsch_llr, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pdsch_llr,2); fl_set_xyplot_xgrid( fdui->pdsch_llr,FL_GRID_MAJOR); - + fl_set_xyplot_symbol(fdui->pdsch_llr, 0, drawsymbol); // I/Q PDSCH comp fdui->pdsch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 500, 240, 200, "PDSCH I/Q of MF Output" ); fl_set_object_boxtype( fdui->pdsch_comp, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->pdsch_comp, FL_BLACK, FL_YELLOW ); fl_set_object_lcolor( fdui->pdsch_comp, FL_WHITE ); // Label color fl_set_xyplot_symbolsize( fdui->pdsch_comp,2); - + fl_set_xyplot_symbol(fdui->pdsch_comp, 0, drawsymbol); // Throughput on PDSCH fdui->pdsch_tput = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 720, 500, 100, "PDSCH Throughput [frame]/[kbit/s]" ); fl_set_object_boxtype( fdui->pdsch_tput, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->pdsch_tput, FL_BLACK, FL_WHITE ); fl_set_object_lcolor( fdui->pdsch_tput, FL_WHITE ); // Label color - // Generic UE Button fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 540, 720, 240, 40, "" ); fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER ); @@ -478,10 +444,8 @@ FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) fl_set_object_color(fdui->button_0, FL_RED, FL_RED); fl_set_object_callback(fdui->button_0, ia_receiver_on_off, 0 ); fl_hide_object(fdui->button_0); - fl_end_form( ); fdui->lte_phy_scope_ue->fdui = fdui; - return fdui; } @@ -489,8 +453,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, PHY_VARS_UE *phy_vars_ue, int eNB_id, int UE_id, - uint8_t subframe) -{ + uint8_t subframe) { int i,arx,atx,ind,k; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; int nsymb_ce = frame_parms->ofdm_symbol_size;//*frame_parms->symbols_per_tti; @@ -521,7 +484,6 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, unsigned char harq_pid = 0; int beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0; - if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]!=NULL) { harq_pid = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->current_harq_pid; @@ -556,34 +518,32 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, coded_bits_per_codeword = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); } - I = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*2,sizeof(float)); - Q = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*2,sizeof(float)); - chest_t_abs = (float**) malloc(nb_antennas_rx*sizeof(float*)); + I = (float *) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*2,sizeof(float)); + Q = (float *) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*2,sizeof(float)); + chest_t_abs = (float **) malloc(nb_antennas_rx*sizeof(float *)); for (arx=0; arxofdm_symbol_size,sizeof(float)); + chest_t_abs[arx] = (float *) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); } - chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); + chest_f_abs = (float *) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); //llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // Cppcheck returns "invalidFunctionArg" error. - llr = (float*) malloc(coded_bits_per_codeword*sizeof(float)); + llr = (float *) malloc(coded_bits_per_codeword*sizeof(float)); memset((void *)llr, 0,coded_bits_per_codeword*sizeof(float)); // init to zero - bit = malloc(coded_bits_per_codeword*sizeof(float)); - llr_pdcch = (float*) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); // init to zero - bit_pdcch = (float*) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); - - rxsig_t = (int16_t**) phy_vars_ue->common_vars.rxdata; - chest_t = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id]; - chest_f = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id]; - pbch_llr = (int8_t*) phy_vars_ue->pbch_vars[eNB_id]->llr; - pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; - pdcch_llr = (int8_t*) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr; - pdcch_comp = (int16_t*) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp[0]; - pdsch_llr = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; // stream 0 + llr_pdcch = (float *) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); // init to zero + bit_pdcch = (float *) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); + rxsig_t = (int16_t **) phy_vars_ue->common_vars.rxdata; + chest_t = (int16_t **) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id]; + chest_f = (int16_t **) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id]; + pbch_llr = (int8_t *) phy_vars_ue->pbch_vars[eNB_id]->llr; + pbch_comp = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; + pdcch_llr = (int8_t *) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr; + pdcch_comp = (int16_t *) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp[0]; + pdsch_llr = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; // stream 0 //pdsch_llr = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]->llr[0]; // stream 0 - pdsch_comp = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp0[0]; - pdsch_mag = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag0[0]; + pdsch_comp = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp0[0]; + pdsch_mag = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag0[0]; // Received signal in time domain of receive antenna 0 if (rxsig_t != NULL) { @@ -652,7 +612,6 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, freq[ind] = (float)ind; Re = (float)(chest_f[(atx<<1)+arx][(2*k)]); Im = (float)(chest_f[(atx<<1)+arx][(2*k)+1]); - chest_f_abs[ind] = (short)10*log10(1.0+((double)Re*Re + (double)Im*Im)); ind++; } @@ -715,13 +674,11 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } fl_set_xyplot_xbounds(form->pdcch_llr,0,12*frame_parms->N_RB_DL*2*3); - if (frame_parms->N_RB_DL != 100) - { - fl_set_xyplot_data(form->pdcch_llr,bit_pdcch,llr_pdcch,12*frame_parms->N_RB_DL*2*num_pdcch_symbols,"","",""); - } - else - { - LOG_D(PHY,"UE PDCCH LLR plot is bugged in 20 MHz BW, to be fixed !!!\n"); + + if (frame_parms->N_RB_DL != 100) { + fl_set_xyplot_data(form->pdcch_llr,bit_pdcch,llr_pdcch,12*frame_parms->N_RB_DL*2*num_pdcch_symbols,"","",""); + } else { + LOG_D(PHY,"UE PDCCH LLR plot is bugged in 20 MHz BW, to be fixed !!!\n"); } } @@ -731,13 +688,11 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, I[i] = pdcch_comp[2*i]; Q[i] = pdcch_comp[2*i+1]; } - if (frame_parms->N_RB_DL != 100) - { - fl_set_xyplot_data(form->pdcch_comp,I,Q,12*frame_parms->N_RB_DL*num_pdcch_symbols,"","",""); - } - else - { - LOG_D(PHY,"UE PDCCH COMP plot is bugged in 20 MHz BW, to be fixed !!!\n"); + + if (frame_parms->N_RB_DL != 100) { + fl_set_xyplot_data(form->pdcch_comp,I,Q,12*frame_parms->N_RB_DL*num_pdcch_symbols,"","",""); + } else { + LOG_D(PHY,"UE PDCCH COMP plot is bugged in 20 MHz BW, to be fixed !!!\n"); } } @@ -749,13 +704,11 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } fl_set_xyplot_xbounds(form->pdsch_llr,0,coded_bits_per_codeword); - if (frame_parms->N_RB_DL != 100) - { - fl_set_xyplot_data(form->pdsch_llr,bit,llr,coded_bits_per_codeword,"","",""); - } - else - { - LOG_D(PHY,"UE PDSCH LLR plot is bugged in 20 MHz BW, to be fixed !!!\n"); + + if (frame_parms->N_RB_DL != 100) { + fl_set_xyplot_data(form->pdsch_llr,bit,llr,coded_bits_per_codeword,"","",""); + } else { + LOG_D(PHY,"UE PDSCH LLR plot is bugged in 20 MHz BW, to be fixed !!!\n"); } } @@ -765,7 +718,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, for (k=0; ksymbols_per_tti; k++) { for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { - int j = (2*frame_parms->N_RB_DL*12*k)+4*i; + int j = (2*frame_parms->N_RB_DL*12*k)+4*i; I[ind] = (pdsch_mag[j ]!=0? 1.0/pdsch_mag[j ]: 0.0) * pdsch_comp[j ]*1.0; Q[ind] = (pdsch_mag[j+1]!=0? 1.0/pdsch_mag[j+1]: 0.0) * pdsch_comp[j+1]*1.0; ind++; @@ -778,7 +731,6 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, // PDSCH Throughput memmove( tput_time_ue[UE_id], &tput_time_ue[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); memmove( tput_ue[UE_id], &tput_ue[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); - tput_time_ue[UE_id][TPUT_WINDOW_LENGTH-1] = (float) frame; tput_ue[UE_id][TPUT_WINDOW_LENGTH-1] = ((float) total_dlsch_bitrate)/1000.0; @@ -787,11 +739,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } fl_set_xyplot_data(form->pdsch_tput,tput_time_ue[UE_id],tput_ue[UE_id],TPUT_WINDOW_LENGTH,"","",""); - fl_set_xyplot_ybounds(form->pdsch_tput,0,tput_ue_max[UE_id]); - fl_check_forms(); - free(I); free(Q); free(chest_f_abs); diff --git a/openair1/PHY/TOOLS/lte_phy_scope.h b/openair1/PHY/TOOLS/lte_phy_scope.h index af9858ebad..1873fabea0 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.h +++ b/openair1/PHY/TOOLS/lte_phy_scope.h @@ -28,6 +28,7 @@ #include "PHY/defs_eNB.h" #include "PHY/defs_UE.h" #include "PHY/impl_defs_top.h" +#include /* Forms and Objects */ diff --git a/openair1/PHY/TOOLS/lte_phy_scope_tm4.c b/openair1/PHY/TOOLS/lte_phy_scope_tm4.c index d44f8e325b..a9caf8713b 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope_tm4.c +++ b/openair1/PHY/TOOLS/lte_phy_scope_tm4.c @@ -32,8 +32,7 @@ float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_ue_max[NUMBER_OF_UE_MAX] = {0}; -static void ia_receiver_on_off( FL_OBJECT *button, long arg) -{ +static void ia_receiver_on_off( FL_OBJECT *button, long arg) { if (fl_get_button(button)) { fl_set_object_label(button, "IA Receiver ON"); // PHY_vars_UE_g[0][0]->use_ia_receiver = 1; @@ -45,8 +44,7 @@ static void ia_receiver_on_off( FL_OBJECT *button, long arg) } } -static void dl_traffic_on_off( FL_OBJECT *button, long arg) -{ +static void dl_traffic_on_off( FL_OBJECT *button, long arg) { if (fl_get_button(button)) { fl_set_object_label(button, "DL Traffic ON"); otg_enabled = 1; @@ -58,9 +56,7 @@ static void dl_traffic_on_off( FL_OBJECT *button, long arg) } } -static void sic_receiver_on_off( FL_OBJECT *button, long arg) -{ - +static void sic_receiver_on_off( FL_OBJECT *button, long arg) { if (fl_get_button(button)) { fl_set_object_label(button, "SIC Receiver ON"); use_sic_receiver = 1; @@ -72,8 +68,7 @@ static void sic_receiver_on_off( FL_OBJECT *button, long arg) } } -FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) -{ +FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) { FL_OBJECT *obj; FD_lte_phy_scope_enb *fdui = fl_malloc( sizeof *fdui ); // Define form @@ -145,8 +140,7 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) void phy_scope_eNB(FD_lte_phy_scope_enb *form, PHY_VARS_eNB *phy_vars_enb, - int UE_id) -{ + int UE_id) { int eNB_id = 0; int i,i2,arx,atx,ind,k; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_enb->frame_parms; @@ -176,24 +170,27 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, int coded_bits_per_codeword = 0; uint8_t harq_pid; // in TDD config 3 it is sf-2, i.e., can be 0,1,2 int mcs = 0; + // choose max MCS to compute coded_bits_per_codeword if (phy_vars_enb->ulsch[UE_id]!=NULL) { for (harq_pid=0; harq_pid<3; harq_pid++) { mcs = cmax(phy_vars_enb->ulsch[UE_id]->harq_processes[harq_pid]->mcs,mcs); } } + coded_bits_per_codeword = frame_parms->N_RB_UL*12*get_Qm(mcs)*frame_parms->symbols_per_tti; - chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); - llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero + chest_f_abs = (float *) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); + llr = (float *) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero bit = malloc(coded_bits_per_codeword*sizeof(float)); - rxsig_t = (int16_t**) phy_vars_enb->common_vars.rxdata[eNB_id]; - chest_t = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id]; - chest_f = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates[eNB_id]; - pusch_llr = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->llr; - pusch_comp = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; - pucch1_comp = (int32_t*) phy_vars_enb->pucch1_stats[UE_id]; - pucch1_thres = (int32_t*) phy_vars_enb->pucch1_stats_thres[UE_id]; - pucch1ab_comp = (int32_t*) phy_vars_enb->pucch1ab_stats[UE_id]; + rxsig_t = (int16_t **) phy_vars_enb->common_vars.rxdata[eNB_id]; + chest_t = (int16_t **) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id]; + chest_f = (int16_t **) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates[eNB_id]; + pusch_llr = (int16_t *) phy_vars_enb->pusch_vars[UE_id]->llr; + pusch_comp = (int16_t *) phy_vars_enb->pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; + pucch1_comp = (int32_t *) phy_vars_enb->pucch1_stats[UE_id]; + pucch1_thres = (int32_t *) phy_vars_enb->pucch1_stats_thres[UE_id]; + pucch1ab_comp = (int32_t *) phy_vars_enb->pucch1ab_stats[UE_id]; + // Received signal in time domain of receive antenna 0 if (rxsig_t != NULL) { if (rxsig_t[0] != NULL) { @@ -201,48 +198,61 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, rxsig_t_dB[0][i] = 10*log10(1.0+(float) ((rxsig_t[0][2*i])*(rxsig_t[0][2*i])+(rxsig_t[0][2*i+1])*(rxsig_t[0][2*i+1]))); time[i] = (float) i; } + fl_set_xyplot_data(form->rxsig_t,time,rxsig_t_dB[0],FRAME_LENGTH_COMPLEX_SAMPLES,"","",""); } + for (arx=1; arxrxsig_t,arx,time,rxsig_t_dB[arx],FRAME_LENGTH_COMPLEX_SAMPLES,rx_antenna_colors[arx]); } } } + // Channel Impulse Response if (chest_t != NULL) { ymax = 0; + if (chest_t[0] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size); i++) { - i2 = (i+(frame_parms->ofdm_symbol_size>>1))%frame_parms->ofdm_symbol_size; - time2[i] = (float)(i-(frame_parms->ofdm_symbol_size>>1)); + i2 = (i+(frame_parms->ofdm_symbol_size>>1))%frame_parms->ofdm_symbol_size; + time2[i] = (float)(i-(frame_parms->ofdm_symbol_size>>1)); chest_t_abs[0][i] = 10*log10((float) (1+chest_t[0][2*i2]*chest_t[0][2*i2]+chest_t[0][2*i2+1]*chest_t[0][2*i2+1])); + if (chest_t_abs[0][i] > ymax) ymax = chest_t_abs[0][i]; } + fl_set_xyplot_data(form->chest_t,time2,chest_t_abs[0],(frame_parms->ofdm_symbol_size),"","",""); } + for (arx=1; arxofdm_symbol_size>>3); i++) { chest_t_abs[arx][i] = 10*log10((float) (1+chest_t[arx][2*i]*chest_t[arx][2*i]+chest_t[arx][2*i+1]*chest_t[arx][2*i+1])); + if (chest_t_abs[arx][i] > ymax) ymax = chest_t_abs[arx][i]; } + fl_add_xyplot_overlay(form->chest_t,arx,time,chest_t_abs[arx],(frame_parms->ofdm_symbol_size>>3),rx_antenna_colors[arx]); fl_set_xyplot_overlay_type(form->chest_t,arx,FL_DASHED_XYPLOT); } } + // Avoid flickering effect // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); fl_set_xyplot_ybounds(form->chest_t,0,ymax); } + // Channel Frequency Response if (chest_f != NULL) { ind = 0; + for (atx=0; atxchest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,3); fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); + for (arx=1; arxchest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); } + // other tx antennas if (nb_antennas_tx > 1) { if (nb_antennas_rx > 1) { @@ -279,17 +292,21 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, } } } + // PUSCH LLRs if (pusch_llr != NULL) { for (i=0; ipusch_llr,bit,llr,coded_bits_per_codeword,"","",""); } + // PUSCH I/Q of MF Output if (pusch_comp!=NULL) { ind=0; + for (k=0; ksymbols_per_tti; k++) { for (i=0; i<12*frame_parms->N_RB_UL; i++) { I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; @@ -297,8 +314,10 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, ind++; } } + fl_set_xyplot_data(form->pusch_comp,I,Q,ind,"","",""); } + // PUSCH I/Q of MF Output if (pucch1ab_comp!=NULL) { for (ind=0; ind<10240; ind++) { @@ -308,6 +327,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, B_pucch[ind] = ind; C_pucch[ind] = (float)pucch1_thres[ind]; } + fl_set_xyplot_data(form->pucch_comp,I_pucch,Q_pucch,10240,"","",""); fl_set_xyplot_data(form->pucch_comp1,B_pucch,A_pucch,1024,"","",""); fl_add_xyplot_overlay(form->pucch_comp1,1,B_pucch,C_pucch,1024,FL_RED); @@ -315,6 +335,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, fl_set_xyplot_xbounds(form->pucch_comp,-5000,5000); fl_set_xyplot_ybounds(form->pucch_comp1,0,80); } + // PUSCH Throughput memmove( tput_time_enb[UE_id], &tput_time_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); memmove( tput_enb[UE_id], &tput_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); @@ -329,509 +350,564 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, free(chest_f_abs); } -FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) -{ - FL_OBJECT *obj; - FD_lte_phy_scope_ue *fdui = fl_malloc( sizeof *fdui ); - // Define form - fdui->lte_phy_scope_ue = fl_bgn_form( FL_NO_BOX, 800, 1000 ); - // This the whole UI box - obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 1000, "" ); - fl_set_object_color( obj, FL_BLACK, FL_BLACK ); - // Received signal - fdui->rxsig_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 20, 370, 100, "Received Signal (Time-Domain, dB)" ); - fl_set_object_boxtype( fdui->rxsig_t, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->rxsig_t, FL_BLACK, FL_RED ); - fl_set_object_lcolor( fdui->rxsig_t, FL_WHITE ); // Label color - fl_set_xyplot_ybounds(fdui->rxsig_t,30,70); - // Time-domain channel response - fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)" ); - fl_set_object_boxtype( fdui->chest_t, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->chest_t, FL_BLACK, FL_RED ); - fl_set_object_lcolor( fdui->chest_t, FL_WHITE ); // Label color - // Frequency-domain channel response - fdui->chest_f = fl_add_xyplot( FL_IMPULSE_XYPLOT, 20, 140, 760, 100, "Channel Frequency Response (RE, dB)" ); - fl_set_object_boxtype( fdui->chest_f, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->chest_f, FL_BLACK, FL_RED ); - fl_set_object_lcolor( fdui->chest_f, FL_WHITE ); // Label color - fl_set_xyplot_ybounds( fdui->chest_f,30,70); - /* - // LLR of PBCH - fdui->pbch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 260, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)" ); - fl_set_object_boxtype( fdui->pbch_llr, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pbch_llr, FL_BLACK, FL_GREEN ); - fl_set_object_lcolor( fdui->pbch_llr, FL_WHITE ); // Label color - fl_set_xyplot_symbolsize( fdui->pbch_llr,2); - fl_set_xyplot_xgrid( fdui->pbch_llr,FL_GRID_MAJOR); - fl_set_xyplot_xbounds( fdui->pbch_llr,0,1920); - // I/Q PBCH comp - fdui->pbch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 260, 240, 100, "PBCH I/Q of MF Output" ); - fl_set_object_boxtype( fdui->pbch_comp, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pbch_comp, FL_BLACK, FL_GREEN ); - fl_set_object_lcolor( fdui->pbch_comp, FL_WHITE ); // Label color - fl_set_xyplot_symbolsize( fdui->pbch_comp,2); - fl_set_xyplot_xbounds( fdui->pbch_comp,-100,100); - fl_set_xyplot_ybounds( fdui->pbch_comp,-100,100); - // LLR of PDCCH - fdui->pdcch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 380, 500, 100, "PDCCH Log-Likelihood Ratios (LLR, mag)" ); - fl_set_object_boxtype( fdui->pdcch_llr, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pdcch_llr, FL_BLACK, FL_CYAN ); - fl_set_object_lcolor( fdui->pdcch_llr, FL_WHITE ); // Label color - fl_set_xyplot_symbolsize( fdui->pdcch_llr,2); - // I/Q PDCCH comp - fdui->pdcch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 380, 240, 100, "PDCCH I/Q of MF Output" ); - fl_set_object_boxtype( fdui->pdcch_comp, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pdcch_comp, FL_BLACK, FL_CYAN ); - fl_set_object_lcolor( fdui->pdcch_comp, FL_WHITE ); // Label color - fl_set_xyplot_symbolsize( fdui->pdcch_comp,2); - fl_set_xyplot_xgrid( fdui->pdcch_llr,FL_GRID_MAJOR); - */ - int offset=240; - // LLR of PDSCH - fdui->pdsch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 500-offset, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)" ); - fl_set_object_boxtype( fdui->pdsch_llr, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pdsch_llr, FL_BLACK, FL_YELLOW ); - fl_set_object_lcolor( fdui->pdsch_llr, FL_WHITE ); // Label color - fl_set_xyplot_symbolsize( fdui->pdsch_llr,2); - fl_set_xyplot_xgrid( fdui->pdsch_llr,FL_GRID_MAJOR); - // I/Q PDSCH comp - fdui->pdsch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 500-offset, 240, 200, "PDSCH I/Q of MF Output" ); - fl_set_object_boxtype( fdui->pdsch_comp, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pdsch_comp, FL_BLACK, FL_YELLOW ); - fl_set_object_lcolor( fdui->pdsch_comp, FL_WHITE ); // Label color - fl_set_xyplot_symbolsize( fdui->pdsch_comp,2); - // LLR of PDSCH - fdui->pdsch_llr1 = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 720-offset, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)" ); - fl_set_object_boxtype( fdui->pdsch_llr1, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pdsch_llr1, FL_BLACK, FL_YELLOW ); - fl_set_object_lcolor( fdui->pdsch_llr1, FL_WHITE ); // Label color - fl_set_xyplot_symbolsize( fdui->pdsch_llr1,2); - fl_set_xyplot_xgrid( fdui->pdsch_llr1,FL_GRID_MAJOR); - // I/Q PDSCH comp - fdui->pdsch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 720-offset, 240, 200, "PDSCH I/Q of MF Output" ); - fl_set_object_boxtype( fdui->pdsch_comp1, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pdsch_comp1, FL_BLACK, FL_YELLOW ); - fl_set_object_lcolor( fdui->pdsch_comp1, FL_WHITE ); // Label color - fl_set_xyplot_symbolsize( fdui->pdsch_comp1,2); - /* - // Throughput on PDSCH - fdui->pdsch_tput = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 720, 500, 100, "PDSCH Throughput [frame]/[kbit/s]" ); - fl_set_object_boxtype( fdui->pdsch_tput, FL_EMBOSSED_BOX ); - fl_set_object_color( fdui->pdsch_tput, FL_BLACK, FL_WHITE ); - fl_set_object_lcolor( fdui->pdsch_tput, FL_WHITE ); // Label color - */ - // Generic UE Button - fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 540, 720, 240, 40, "" ); - fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER ); - //use_sic_receiver = 0; - fl_set_button(fdui->button_0,0); - fl_set_object_label(fdui->button_0, "SIC Receiver OFF"); - fl_set_object_color(fdui->button_0, FL_RED, FL_RED); - fl_set_object_callback(fdui->button_0, sic_receiver_on_off, 0 ); - fl_hide_object(fdui->button_0); - - fl_end_form( ); - fdui->lte_phy_scope_ue->fdui = fdui; - return fdui; +FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) { + FL_OBJECT *obj; + FD_lte_phy_scope_ue *fdui = fl_malloc( sizeof *fdui ); + // Define form + fdui->lte_phy_scope_ue = fl_bgn_form( FL_NO_BOX, 800, 1000 ); + // This the whole UI box + obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 1000, "" ); + fl_set_object_color( obj, FL_BLACK, FL_BLACK ); + // Received signal + fdui->rxsig_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 20, 370, 100, "Received Signal (Time-Domain, dB)" ); + fl_set_object_boxtype( fdui->rxsig_t, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->rxsig_t, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->rxsig_t, FL_WHITE ); // Label color + fl_set_xyplot_ybounds(fdui->rxsig_t,30,70); + // Time-domain channel response + fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)" ); + fl_set_object_boxtype( fdui->chest_t, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->chest_t, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->chest_t, FL_WHITE ); // Label color + // Frequency-domain channel response + fdui->chest_f = fl_add_xyplot( FL_IMPULSE_XYPLOT, 20, 140, 760, 100, "Channel Frequency Response (RE, dB)" ); + fl_set_object_boxtype( fdui->chest_f, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->chest_f, FL_BLACK, FL_RED ); + fl_set_object_lcolor( fdui->chest_f, FL_WHITE ); // Label color + fl_set_xyplot_ybounds( fdui->chest_f,30,70); + /* + // LLR of PBCH + fdui->pbch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 260, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pbch_llr, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pbch_llr, FL_BLACK, FL_GREEN ); + fl_set_object_lcolor( fdui->pbch_llr, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pbch_llr,2); + fl_set_xyplot_xgrid( fdui->pbch_llr,FL_GRID_MAJOR); + fl_set_xyplot_xbounds( fdui->pbch_llr,0,1920); + // I/Q PBCH comp + fdui->pbch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 260, 240, 100, "PBCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pbch_comp, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pbch_comp, FL_BLACK, FL_GREEN ); + fl_set_object_lcolor( fdui->pbch_comp, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pbch_comp,2); + fl_set_xyplot_xbounds( fdui->pbch_comp,-100,100); + fl_set_xyplot_ybounds( fdui->pbch_comp,-100,100); + // LLR of PDCCH + fdui->pdcch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 380, 500, 100, "PDCCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pdcch_llr, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdcch_llr, FL_BLACK, FL_CYAN ); + fl_set_object_lcolor( fdui->pdcch_llr, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdcch_llr,2); + // I/Q PDCCH comp + fdui->pdcch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 380, 240, 100, "PDCCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pdcch_comp, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdcch_comp, FL_BLACK, FL_CYAN ); + fl_set_object_lcolor( fdui->pdcch_comp, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdcch_comp,2); + fl_set_xyplot_xgrid( fdui->pdcch_llr,FL_GRID_MAJOR); + */ + int offset=240; + // LLR of PDSCH + fdui->pdsch_llr = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 500-offset, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pdsch_llr, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_llr, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pdsch_llr, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdsch_llr,2); + fl_set_xyplot_xgrid( fdui->pdsch_llr,FL_GRID_MAJOR); + // I/Q PDSCH comp + fdui->pdsch_comp = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 500-offset, 240, 200, "PDSCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pdsch_comp, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_comp, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pdsch_comp, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdsch_comp,2); + // LLR of PDSCH + fdui->pdsch_llr1 = fl_add_xyplot( FL_POINTS_XYPLOT, 20, 720-offset, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)" ); + fl_set_object_boxtype( fdui->pdsch_llr1, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_llr1, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pdsch_llr1, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdsch_llr1,2); + fl_set_xyplot_xgrid( fdui->pdsch_llr1,FL_GRID_MAJOR); + // I/Q PDSCH comp + fdui->pdsch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 720-offset, 240, 200, "PDSCH I/Q of MF Output" ); + fl_set_object_boxtype( fdui->pdsch_comp1, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_comp1, FL_BLACK, FL_YELLOW ); + fl_set_object_lcolor( fdui->pdsch_comp1, FL_WHITE ); // Label color + fl_set_xyplot_symbolsize( fdui->pdsch_comp1,2); + /* + // Throughput on PDSCH + fdui->pdsch_tput = fl_add_xyplot( FL_NORMAL_XYPLOT, 20, 720, 500, 100, "PDSCH Throughput [frame]/[kbit/s]" ); + fl_set_object_boxtype( fdui->pdsch_tput, FL_EMBOSSED_BOX ); + fl_set_object_color( fdui->pdsch_tput, FL_BLACK, FL_WHITE ); + fl_set_object_lcolor( fdui->pdsch_tput, FL_WHITE ); // Label color + */ + // Generic UE Button + fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 540, 720, 240, 40, "" ); + fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER ); + //use_sic_receiver = 0; + fl_set_button(fdui->button_0,0); + fl_set_object_label(fdui->button_0, "SIC Receiver OFF"); + fl_set_object_color(fdui->button_0, FL_RED, FL_RED); + fl_set_object_callback(fdui->button_0, sic_receiver_on_off, 0 ); + fl_hide_object(fdui->button_0); + fl_end_form( ); + fdui->lte_phy_scope_ue->fdui = fdui; + return fdui; } void phy_scope_UE(FD_lte_phy_scope_ue *form, PHY_VARS_UE *phy_vars_ue, int eNB_id, int UE_id, - uint8_t subframe) -{ - int i,arx,atx,ind,k; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; - int nsymb_ce = frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti; - uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; - uint8_t nb_antennas_tx = frame_parms->nb_antenna_ports_eNB; - int16_t **rxsig_t; - int16_t **chest_t; - int16_t **chest_f; - int16_t *pdsch_llr,*pdsch_llr1; - int16_t *pdsch_comp,*pdsch_comp1; - int16_t *pdsch_mag0,*pdsch_mag1,*pdsch_magb0,*pdsch_magb1; - int8_t *pdcch_llr; - int16_t *pdcch_comp; - int8_t *pbch_llr; - int16_t *pbch_comp; - float Re,Im,ymax=1; - int num_pdcch_symbols=3; - float *llr0, *bit0, *llr1, *bit1, *chest_f_abs, llr_pbch[1920], bit_pbch[1920], *llr_pdcch, *bit_pdcch; - float *I, *Q; - float rxsig_t_dB[nb_antennas_rx][FRAME_LENGTH_COMPLEX_SAMPLES]; - float **chest_t_abs; - float time[FRAME_LENGTH_COMPLEX_SAMPLES]; - float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; - int frame = phy_vars_ue->proc.proc_rxtx[0].frame_rx; - uint32_t total_dlsch_bitrate = phy_vars_ue->bitrate[eNB_id]; - int coded_bits_per_codeword0=0,coded_bits_per_codeword1=1; - int mod0,mod1; - int mcs0 = 0; - int mcs1=0; - unsigned char harq_pid = 0; - int beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0; - if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]!=NULL) { - harq_pid = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->current_harq_pid; - if (harq_pid>=8) - return; - mcs0 = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->mcs; - // Button 0 - /* - if(!phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off) { - // we are in TM5 - fl_show_object(form->button_0); - } - */ - } - fl_show_object(form->button_0); - if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]!=NULL) { - harq_pid = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->current_harq_pid; - if (harq_pid>=8) - return; - mcs1 = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->harq_processes[harq_pid]->mcs; - } - if (phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]!=NULL) { - num_pdcch_symbols = phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->num_pdcch_symbols; - } - // coded_bits_per_codeword = frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); - if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]!=NULL) { - mod0 = get_Qm(mcs0); - coded_bits_per_codeword0 = get_G(frame_parms, - phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->nb_rb, - phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, - get_Qm(mcs0), - phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->Nl, - num_pdcch_symbols, - frame, - subframe, - beamforming_mode); - } else { - coded_bits_per_codeword0 = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); - mod0=0; - } - if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]!=NULL) { - mod1 = get_Qm(mcs1); - coded_bits_per_codeword1 = get_G(frame_parms, - phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->harq_processes[harq_pid]->nb_rb, - phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->harq_processes[harq_pid]->rb_alloc_even, - get_Qm(mcs1), - phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->harq_processes[harq_pid]->Nl, - num_pdcch_symbols, - frame, - subframe, - beamforming_mode); - } else { - coded_bits_per_codeword1 = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); - mod1=0; - } - I = (float*) calloc(nsymb_ce*2,sizeof(float)); - Q = (float*) calloc(nsymb_ce*2,sizeof(float)); - chest_t_abs = (float**) malloc(nb_antennas_rx*sizeof(float*)); - for (arx=0;arxofdm_symbol_size,sizeof(float)); - } - chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); - //llr0 = (float*) calloc(coded_bits_per_codeword0,sizeof(float)); // Cppcheck returns "invalidFunctionArg" error. - llr0 = (float*) malloc(coded_bits_per_codeword0*sizeof(float)); - memset((void *)llr0, 0,coded_bits_per_codeword0*sizeof(float)); // init to zero - bit0 = malloc(coded_bits_per_codeword0*sizeof(float)); + uint8_t subframe) { + int i,arx,atx,ind,k; + LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; + int nsymb_ce = frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti; + uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; + uint8_t nb_antennas_tx = frame_parms->nb_antenna_ports_eNB; + int16_t **rxsig_t; + int16_t **chest_t; + int16_t **chest_f; + int16_t *pdsch_llr,*pdsch_llr1; + int16_t *pdsch_comp,*pdsch_comp1; + int16_t *pdsch_mag0,*pdsch_mag1,*pdsch_magb0,*pdsch_magb1; + int8_t *pdcch_llr; + int16_t *pdcch_comp; + int8_t *pbch_llr; + int16_t *pbch_comp; + float Re,Im,ymax=1; + int num_pdcch_symbols=3; + float *llr0, *bit0, *llr1, *bit1, *chest_f_abs, llr_pbch[1920], bit_pbch[1920], *llr_pdcch, *bit_pdcch; + float *I, *Q; + float rxsig_t_dB[nb_antennas_rx][FRAME_LENGTH_COMPLEX_SAMPLES]; + float **chest_t_abs; + float time[FRAME_LENGTH_COMPLEX_SAMPLES]; + float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; + int frame = phy_vars_ue->proc.proc_rxtx[0].frame_rx; + uint32_t total_dlsch_bitrate = phy_vars_ue->bitrate[eNB_id]; + int coded_bits_per_codeword0=0,coded_bits_per_codeword1=1; + int mod0,mod1; + int mcs0 = 0; + int mcs1=0; + unsigned char harq_pid = 0; + int beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0; - //llr1 = (float*) calloc(coded_bits_per_codeword1,sizeof(float)); // Cppcheck returns "invalidFunctionArg" error. - llr1 = (float*) malloc(coded_bits_per_codeword1*sizeof(float)); - memset((void *)llr1, 0,coded_bits_per_codeword1*sizeof(float)); // init to zero - bit1 = malloc(coded_bits_per_codeword1*sizeof(float)); - llr_pdcch = (float*) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); // init to zero - bit_pdcch = (float*) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); - rxsig_t = (int16_t**) phy_vars_ue->common_vars.rxdata; - chest_t = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id]; - chest_f = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id]; - pbch_llr = (int8_t*) phy_vars_ue->pbch_vars[eNB_id]->llr; - pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; - pdcch_llr = (int8_t*) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr; - pdcch_comp = (int16_t*) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp[0]; - pdsch_llr = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; // stream 0 - pdsch_llr1 = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[1]; // stream 1 - pdsch_comp = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp0[0]; - //pdsch_comp = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_ext[0]; - //pdsch_comp1 = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_ext[1]; - pdsch_comp1 = (int16_t*) (phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp1[0][0])[0]; - //pdsch_comp1 = (int16_t*) (phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext[0][0])[0]; - pdsch_mag0 = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag0[0]; - pdsch_mag1 = (int16_t*) (phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag1[0][0])[0]; - pdsch_magb0 = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_magb0[0]; - pdsch_magb1 = (int16_t*) (phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_magb1[0][0])[0]; - fl_freeze_form(form->lte_phy_scope_ue); - // Received signal in time domain of receive antenna 0 - if (rxsig_t != NULL) { - if (rxsig_t[0] != NULL) { - for (i=0; irxsig_t,time,rxsig_t_dB[0],FRAME_LENGTH_COMPLEX_SAMPLES,"","",""); - } - for (arx=1;arxrxsig_t,arx,time,rxsig_t_dB[arx],FRAME_LENGTH_COMPLEX_SAMPLES,rx_antenna_colors[arx]); - } - } + if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]!=NULL) { + harq_pid = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->current_harq_pid; + + if (harq_pid>=8) + return; + + mcs0 = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->mcs; + // Button 0 + /* + if(!phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off) { + // we are in TM5 + fl_show_object(form->button_0); + } + */ + } + + fl_show_object(form->button_0); + + if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]!=NULL) { + harq_pid = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->current_harq_pid; + + if (harq_pid>=8) + return; + + mcs1 = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->harq_processes[harq_pid]->mcs; + } + + if (phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]!=NULL) { + num_pdcch_symbols = phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->num_pdcch_symbols; + } + + // coded_bits_per_codeword = frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); + if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]!=NULL) { + mod0 = get_Qm(mcs0); + coded_bits_per_codeword0 = get_G(frame_parms, + phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->nb_rb, + phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, + get_Qm(mcs0), + phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->Nl, + num_pdcch_symbols, + frame, + subframe, + beamforming_mode); + } else { + coded_bits_per_codeword0 = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); + mod0=0; + } + + if (phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]!=NULL) { + mod1 = get_Qm(mcs1); + coded_bits_per_codeword1 = get_G(frame_parms, + phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->harq_processes[harq_pid]->nb_rb, + phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->harq_processes[harq_pid]->rb_alloc_even, + get_Qm(mcs1), + phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][1]->harq_processes[harq_pid]->Nl, + num_pdcch_symbols, + frame, + subframe, + beamforming_mode); + } else { + coded_bits_per_codeword1 = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti); + mod1=0; + } + + I = (float *) calloc(nsymb_ce*2,sizeof(float)); + Q = (float *) calloc(nsymb_ce*2,sizeof(float)); + chest_t_abs = (float **) malloc(nb_antennas_rx*sizeof(float *)); + + for (arx=0; arxofdm_symbol_size,sizeof(float)); + } + + chest_f_abs = (float *) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); + //llr0 = (float*) calloc(coded_bits_per_codeword0,sizeof(float)); // Cppcheck returns "invalidFunctionArg" error. + llr0 = (float *) malloc(coded_bits_per_codeword0*sizeof(float)); + memset((void *)llr0, 0,coded_bits_per_codeword0*sizeof(float)); // init to zero + bit0 = malloc(coded_bits_per_codeword0*sizeof(float)); + //llr1 = (float*) calloc(coded_bits_per_codeword1,sizeof(float)); // Cppcheck returns "invalidFunctionArg" error. + llr1 = (float *) malloc(coded_bits_per_codeword1*sizeof(float)); + memset((void *)llr1, 0,coded_bits_per_codeword1*sizeof(float)); // init to zero + bit1 = malloc(coded_bits_per_codeword1*sizeof(float)); + llr_pdcch = (float *) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); // init to zero + bit_pdcch = (float *) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); + rxsig_t = (int16_t **) phy_vars_ue->common_vars.rxdata; + chest_t = (int16_t **) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id]; + chest_f = (int16_t **) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id]; + pbch_llr = (int8_t *) phy_vars_ue->pbch_vars[eNB_id]->llr; + pbch_comp = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; + pdcch_llr = (int8_t *) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr; + pdcch_comp = (int16_t *) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp[0]; + pdsch_llr = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; // stream 0 + pdsch_llr1 = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[1]; // stream 1 + pdsch_comp = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp0[0]; + //pdsch_comp = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_ext[0]; + //pdsch_comp1 = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_ext[1]; + pdsch_comp1 = (int16_t *) (phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp1[0][0])[0]; + //pdsch_comp1 = (int16_t*) (phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext[0][0])[0]; + pdsch_mag0 = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag0[0]; + pdsch_mag1 = (int16_t *) (phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag1[0][0])[0]; + pdsch_magb0 = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_magb0[0]; + pdsch_magb1 = (int16_t *) (phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_magb1[0][0])[0]; + fl_freeze_form(form->lte_phy_scope_ue); + + // Received signal in time domain of receive antenna 0 + if (rxsig_t != NULL) { + if (rxsig_t[0] != NULL) { + for (i=0; irxsig_t,time,rxsig_t_dB[0],FRAME_LENGTH_COMPLEX_SAMPLES,"","",""); } + + for (arx=1; arxrxsig_t,arx,time,rxsig_t_dB[arx],FRAME_LENGTH_COMPLEX_SAMPLES,rx_antenna_colors[arx]); + } + } + } + // Channel Impulse Response (still repeated format) if (chest_t != NULL) { ymax = 0; + if (chest_t[0] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { chest_t_abs[0][i] = (float) (chest_t[0][4*i]*chest_t[0][4*i]+chest_t[0][4*i+1]*chest_t[0][4*i+1]); + if (chest_t_abs[0][i] > ymax) ymax = chest_t_abs[0][i]; } + fl_set_xyplot_data(form->chest_t,time,chest_t_abs[0],(frame_parms->ofdm_symbol_size>>3),"","",""); } + for (arx=1; arxofdm_symbol_size>>3); i++) { chest_t_abs[arx][i] = (float) (chest_t[arx][4*i]*chest_t[arx][4*i]+chest_t[arx][4*i+1]*chest_t[arx][4*i+1]); + if (chest_t_abs[arx][i] > ymax) ymax = chest_t_abs[arx][i]; } + fl_add_xyplot_overlay(form->chest_t,arx,time,chest_t_abs[arx],(frame_parms->ofdm_symbol_size>>3),rx_antenna_colors[arx]); fl_set_xyplot_overlay_type(form->chest_t,arx,FL_DASHED_XYPLOT); } } - // Avoid flickering effect - // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); - fl_set_xyplot_ybounds(form->chest_t,0,ymax); + + // Avoid flickering effect + // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); + fl_set_xyplot_ybounds(form->chest_t,0,ymax); + } + + // Channel Frequency Response (includes 5 complex sample for filter) + if (chest_f != NULL) { + ind = 0; + + for (atx=0; atxchest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); - //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); - // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); - fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); - fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); - for (arx=1;arxchest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); - } - // other tx antennas - if (nb_antennas_tx > 1) { - if (nb_antennas_rx > 1) { - for (atx=1;atxchest_f,(atx<<1)+arx,&freq[((atx<<1)+arx)*nsymb_ce],&chest_f_abs[((atx<<1)+arx)*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); - } - } - } else { // 1 rx antenna - atx=1; arx=0; - fl_add_xyplot_overlay(form->chest_f,atx,&freq[atx*nsymb_ce],&chest_f_abs[atx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); - } - } + + // tx antenna 0 + fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); + //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); + // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); + fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); + fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); + + for (arx=1; arxchest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); } - /* - // PBCH LLRs - if (pbch_llr != NULL) { - for (i=0; i<1920;i++) { - llr_pbch[i] = (float) pbch_llr[i]; - bit_pbch[i] = (float) i; + + // other tx antennas + if (nb_antennas_tx > 1) { + if (nb_antennas_rx > 1) { + for (atx=1; atxchest_f,(atx<<1)+arx,&freq[((atx<<1)+arx)*nsymb_ce],&chest_f_abs[((atx<<1)+arx)*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); + } } - fl_set_xyplot_data(form->pbch_llr,bit_pbch,llr_pbch,1920,"","",""); + } else { // 1 rx antenna + atx=1; + arx=0; + fl_add_xyplot_overlay(form->chest_f,atx,&freq[atx*nsymb_ce],&chest_f_abs[atx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); + } } - // PBCH I/Q of MF Output - if (pbch_comp!=NULL) { - for (i=0; i<72*2; i++) { - I[i] = pbch_comp[2*i]; - Q[i] = pbch_comp[2*i+1]; - } - fl_set_xyplot_data(form->pbch_comp,I,Q,72*2,"","",""); - } - // PDCCH LLRs - if (pdcch_llr != NULL) { - for (i=0; i<12*frame_parms->N_RB_DL*2*num_pdcch_symbols;i++) { - llr_pdcch[i] = (float) pdcch_llr[i]; - bit_pdcch[i] = (float) i; - } - fl_set_xyplot_xbounds(form->pdcch_llr,0,12*frame_parms->N_RB_DL*2*3); - fl_set_xyplot_data(form->pdcch_llr,bit_pdcch,llr_pdcch,12*frame_parms->N_RB_DL*2*num_pdcch_symbols,"","",""); - } - // PDCCH I/Q of MF Output - if (pdcch_comp!=NULL) { - for (i=0; i<12*frame_parms->N_RB_DL*num_pdcch_symbols; i++) { - I[i] = pdcch_comp[2*i]; - Q[i] = pdcch_comp[2*i+1]; - } - fl_set_xyplot_data(form->pdcch_comp,I,Q,12*frame_parms->N_RB_DL*num_pdcch_symbols,"","",""); - } - */ - // PDSCH LLRs CW0 - if (pdsch_llr != NULL) { - for (i=0; ipdsch_llr,0,coded_bits_per_codeword0); - fl_set_xyplot_data(form->pdsch_llr,bit0,llr0,coded_bits_per_codeword0,"","",""); + } + + /* + // PBCH LLRs + if (pbch_llr != NULL) { + for (i=0; i<1920;i++) { + llr_pbch[i] = (float) pbch_llr[i]; + bit_pbch[i] = (float) i; + } + fl_set_xyplot_data(form->pbch_llr,bit_pbch,llr_pbch,1920,"","",""); + } + // PBCH I/Q of MF Output + if (pbch_comp!=NULL) { + for (i=0; i<72*2; i++) { + I[i] = pbch_comp[2*i]; + Q[i] = pbch_comp[2*i+1]; + } + fl_set_xyplot_data(form->pbch_comp,I,Q,72*2,"","",""); + } + // PDCCH LLRs + if (pdcch_llr != NULL) { + for (i=0; i<12*frame_parms->N_RB_DL*2*num_pdcch_symbols;i++) { + llr_pdcch[i] = (float) pdcch_llr[i]; + bit_pdcch[i] = (float) i; + } + fl_set_xyplot_xbounds(form->pdcch_llr,0,12*frame_parms->N_RB_DL*2*3); + fl_set_xyplot_data(form->pdcch_llr,bit_pdcch,llr_pdcch,12*frame_parms->N_RB_DL*2*num_pdcch_symbols,"","",""); + } + // PDCCH I/Q of MF Output + if (pdcch_comp!=NULL) { + for (i=0; i<12*frame_parms->N_RB_DL*num_pdcch_symbols; i++) { + I[i] = pdcch_comp[2*i]; + Q[i] = pdcch_comp[2*i+1]; + } + fl_set_xyplot_data(form->pdcch_comp,I,Q,12*frame_parms->N_RB_DL*num_pdcch_symbols,"","",""); + } + */ + // PDSCH LLRs CW0 + if (pdsch_llr != NULL) { + for (i=0; ipdsch_llr,0,coded_bits_per_codeword0); + fl_set_xyplot_data(form->pdsch_llr,bit0,llr0,coded_bits_per_codeword0,"","",""); + } + // PDSCH I/Q of MF Output - if (pdsch_comp!=NULL) { - ind=0; - for (k=0; ksymbols_per_tti; k++) { - for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { - I[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i]; - Q[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i+1]; - ind++; - } - } - fl_set_xyplot_data(form->pdsch_comp,I,Q,ind,"","",""); + if (pdsch_comp!=NULL) { + ind=0; + + for (k=0; ksymbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i]; + Q[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i+1]; + ind++; + } } - if (pdsch_mag0 != NULL) { - ind=0; - for (k=0; ksymbols_per_tti; k++) { - for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + + fl_set_xyplot_data(form->pdsch_comp,I,Q,ind,"","",""); + } + + if (pdsch_mag0 != NULL) { + ind=0; + + for (k=0; ksymbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { I[ind] = pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i]*cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); Q[ind] = pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i+1]*sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); ind++; - } - } - fl_add_xyplot_overlay(form->pdsch_comp,1,I,Q,ind,FL_GREEN); + } } - if (pdsch_magb0 != NULL) { - ind=0; - for (k=0; ksymbols_per_tti; k++) { - for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + + fl_add_xyplot_overlay(form->pdsch_comp,1,I,Q,ind,FL_GREEN); + } + + if (pdsch_magb0 != NULL) { + ind=0; + + for (k=0; ksymbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { I[ind] = pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i]*cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); Q[ind] = pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i+1]*sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); ind++; - } - } - fl_add_xyplot_overlay(form->pdsch_comp,2,I,Q,ind,FL_RED); + } } - if ((pdsch_mag0 != NULL) && (pdsch_magb0 != NULL)) { - ind=0; - for (k=0; ksymbols_per_tti; k++) { - for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + + fl_add_xyplot_overlay(form->pdsch_comp,2,I,Q,ind,FL_RED); + } + + if ((pdsch_mag0 != NULL) && (pdsch_magb0 != NULL)) { + ind=0; + + for (k=0; ksymbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { I[ind] = - (pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i]+ - pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i])* - cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + (pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i]+ + pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i])* + cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); Q[ind] = - (pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i+1]+ - pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i+1])* - sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + (pdsch_mag0[(2*frame_parms->N_RB_DL*12*k)+4*i+1]+ + pdsch_magb0[(2*frame_parms->N_RB_DL*12*k)+4*i+1])* + sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); ind++; - } - } - fl_add_xyplot_overlay(form->pdsch_comp,3,I,Q,ind,FL_BLUE); + } } - // PDSCH LLRs CW1 - if (pdsch_llr1 != NULL) { - for (i=0; ipdsch_llr1,0,coded_bits_per_codeword1); - fl_set_xyplot_data(form->pdsch_llr1,bit1,llr1,coded_bits_per_codeword1,"","",""); + + fl_add_xyplot_overlay(form->pdsch_comp,3,I,Q,ind,FL_BLUE); + } + + // PDSCH LLRs CW1 + if (pdsch_llr1 != NULL) { + for (i=0; isymbols_per_tti; k++) { - for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { - I[ind] = pdsch_comp1[(2*frame_parms->N_RB_DL*12*k)+4*i]; - Q[ind] = pdsch_comp1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]; - ind++; - } - } - fl_set_xyplot_data(form->pdsch_comp1,I,Q,ind,"","",""); + + fl_set_xyplot_xbounds(form->pdsch_llr1,0,coded_bits_per_codeword1); + fl_set_xyplot_data(form->pdsch_llr1,bit1,llr1,coded_bits_per_codeword1,"","",""); + } + + // PDSCH I/Q of MF Output + if (pdsch_comp1!=NULL) { + ind=0; + + for (k=0; ksymbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + I[ind] = pdsch_comp1[(2*frame_parms->N_RB_DL*12*k)+4*i]; + Q[ind] = pdsch_comp1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]; + ind++; + } } - if (pdsch_mag1 != NULL) { - ind=0; - for (k=0; ksymbols_per_tti; k++) { - for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + + fl_set_xyplot_data(form->pdsch_comp1,I,Q,ind,"","",""); + } + + if (pdsch_mag1 != NULL) { + ind=0; + + for (k=0; ksymbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { I[ind] = pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i]*cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); Q[ind] = pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]*sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); ind++; - } - } - fl_add_xyplot_overlay(form->pdsch_comp1,1,I,Q,ind,FL_GREEN); + } } - if (pdsch_magb1 != NULL) { - ind=0; - for (k=0; ksymbols_per_tti; k++) { - for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + + fl_add_xyplot_overlay(form->pdsch_comp1,1,I,Q,ind,FL_GREEN); + } + + if (pdsch_magb1 != NULL) { + ind=0; + + for (k=0; ksymbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { I[ind] = pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i]*cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); Q[ind] = pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]*sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); ind++; - } - } - fl_add_xyplot_overlay(form->pdsch_comp1,2,I,Q,ind,FL_RED); + } } - if ((pdsch_mag1 != NULL) && (pdsch_magb1 != NULL)) { - ind=0; - for (k=0; ksymbols_per_tti; k++) { - for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { + + fl_add_xyplot_overlay(form->pdsch_comp1,2,I,Q,ind,FL_RED); + } + + if ((pdsch_mag1 != NULL) && (pdsch_magb1 != NULL)) { + ind=0; + + for (k=0; ksymbols_per_tti; k++) { + for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { I[ind] = - (pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i]+ - pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i])* - cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + (pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i]+ + pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i])* + cos(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); Q[ind] = - (pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]+ - pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i+1])* - sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); + (pdsch_mag1[(2*frame_parms->N_RB_DL*12*k)+4*i+1]+ + pdsch_magb1[(2*frame_parms->N_RB_DL*12*k)+4*i+1])* + sin(i*2*M_PI/(12*frame_parms->N_RB_DL/2)); ind++; - } - } - fl_add_xyplot_overlay(form->pdsch_comp1,3,I,Q,ind,FL_BLUE); + } } - /* - // PDSCH Throughput - memcpy((void*)tput_time_ue[UE_id],(void*)&tput_time_ue[UE_id][1],(TPUT_WINDOW_LENGTH-1)*sizeof(float)); - memcpy((void*)tput_ue[UE_id],(void*)&tput_ue[UE_id][1],(TPUT_WINDOW_LENGTH-1)*sizeof(float)); - tput_time_ue[UE_id][TPUT_WINDOW_LENGTH-1] = (float) frame; - tput_ue[UE_id][TPUT_WINDOW_LENGTH-1] = ((float) total_dlsch_bitrate)/1000.0; - if (tput_ue[UE_id][TPUT_WINDOW_LENGTH-1] > tput_ue_max[UE_id]) { - tput_ue_max[UE_id] = tput_ue[UE_id][TPUT_WINDOW_LENGTH-1]; - } - fl_set_xyplot_data(form->pdsch_tput,tput_time_ue[UE_id],tput_ue[UE_id],TPUT_WINDOW_LENGTH,"","",""); - fl_set_xyplot_ybounds(form->pdsch_tput,0,tput_ue_max[UE_id]); - */ - fl_unfreeze_form(form->lte_phy_scope_ue); - fl_check_forms(); - free(I); - free(Q); - free(chest_f_abs); - free(llr0); - free(bit0); - free(llr1); - free(bit1); - free(bit_pdcch); - free(llr_pdcch); - //This is done to avoid plotting old data when TB0 is disabled, and TB1 is mapped onto CW0 - /*if (phy_vars_ue->transmission_mode[eNB_id]==3 && phy_vars_ue->transmission_mode[eNB_id]==4){ - for (int i = 0; i<8; ++i) - for (int j = 0; j < 7*2*frame_parms->N_RB_DL*12+4; ++j ) - phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp1[0][0][i][j]=0; + fl_add_xyplot_overlay(form->pdsch_comp1,3,I,Q,ind,FL_BLUE); + } - for (int m=0; mpdsch_vars[subframe&0x1][eNB_id]->llr[0][m]=0; - }*/ + /* + // PDSCH Throughput + memcpy((void*)tput_time_ue[UE_id],(void*)&tput_time_ue[UE_id][1],(TPUT_WINDOW_LENGTH-1)*sizeof(float)); + memcpy((void*)tput_ue[UE_id],(void*)&tput_ue[UE_id][1],(TPUT_WINDOW_LENGTH-1)*sizeof(float)); + tput_time_ue[UE_id][TPUT_WINDOW_LENGTH-1] = (float) frame; + tput_ue[UE_id][TPUT_WINDOW_LENGTH-1] = ((float) total_dlsch_bitrate)/1000.0; + if (tput_ue[UE_id][TPUT_WINDOW_LENGTH-1] > tput_ue_max[UE_id]) { + tput_ue_max[UE_id] = tput_ue[UE_id][TPUT_WINDOW_LENGTH-1]; + } + fl_set_xyplot_data(form->pdsch_tput,tput_time_ue[UE_id],tput_ue[UE_id],TPUT_WINDOW_LENGTH,"","",""); + fl_set_xyplot_ybounds(form->pdsch_tput,0,tput_ue_max[UE_id]); + */ + fl_unfreeze_form(form->lte_phy_scope_ue); + fl_check_forms(); + free(I); + free(Q); + free(chest_f_abs); + free(llr0); + free(bit0); + free(llr1); + free(bit1); + free(bit_pdcch); + free(llr_pdcch); + //This is done to avoid plotting old data when TB0 is disabled, and TB1 is mapped onto CW0 + /*if (phy_vars_ue->transmission_mode[eNB_id]==3 && phy_vars_ue->transmission_mode[eNB_id]==4){ + for (int i = 0; i<8; ++i) + for (int j = 0; j < 7*2*frame_parms->N_RB_DL*12+4; ++j ) + phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp1[0][0][i][j]=0; + + for (int m=0; mpdsch_vars[subframe&0x1][eNB_id]->llr[0][m]=0; + }*/ } diff --git a/openair1/PHY/TOOLS/lte_ue_scope.c b/openair1/PHY/TOOLS/lte_ue_scope.c index 20d88ebdab..00560f2d74 100644 --- a/openair1/PHY/TOOLS/lte_ue_scope.c +++ b/openair1/PHY/TOOLS/lte_ue_scope.c @@ -72,16 +72,10 @@ void reset_stats(FL_OBJECT *button, long arg) { static void *scope_thread_UE(void *arg) { char stats_buffer[16384]; -# ifdef ENABLE_XFORMS_WRITE_STATS - FILE *UE_stats, *eNB_stats; -# endif struct sched_param sched_param; sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; sched_setscheduler(0, SCHED_FIFO,&sched_param); printf("Scope thread has priority %d\n",sched_param.sched_priority); -# ifdef ENABLE_XFORMS_WRITE_STATS - UE_stats = fopen("UE_stats.txt", "w"); -#endif while (!oai_exit) { // dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm); @@ -94,16 +88,6 @@ static void *scope_thread_UE(void *arg) { 0,7); // printf("%s",stats_buffer); } - -# ifdef ENABLE_XFORMS_WRITE_STATS - - if (UE_stats) { - rewind (UE_stats); - fwrite (stats_buffer, 1, len, UE_stats); - fclose (UE_stats); - } - -# endif pthread_exit((void *)arg); } diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 44d7b93ae2..303ec5121d 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -25,36 +25,38 @@ #include #include "nr_phy_scope.h" -#include "executables/nr-softmodem-common.h" #include "executables/softmodem-common.h" +#include "executables/nr-softmodem-common.h" #include #define TPUT_WINDOW_LENGTH 100 +#define ScaleZone 4 #define localBuff(NaMe,SiZe) float NaMe[SiZe]; memset(NaMe,0,sizeof(NaMe)); + int otg_enabled; -FL_COLOR rx_antenna_colors[4] = {FL_RED,FL_BLUE,FL_GREEN,FL_YELLOW}; +const FL_COLOR rx_antenna_colors[4] = {FL_RED,FL_BLUE,FL_GREEN,FL_YELLOW}; +const FL_COLOR water_colors[4] = {FL_BLUE,FL_GREEN,FL_YELLOW,FL_RED}; -float tput_time_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; -float tput_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; -float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; -float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; -float tput_ue_max[NUMBER_OF_UE_MAX] = {0}; - -typedef struct { - int16_t r; - int16_t i; -} scopeSample_t; +typedef struct complex16 scopeSample_t; #define SquaredNorm(VaR) ((VaR).r*(VaR).r+(VaR).i*(VaR).i) typedef struct OAIgraph { FL_OBJECT *graph; + FL_OBJECT *text; float maxX; float maxY; float minX; float minY; + int x; + int y; + int w; + int h; + int waterFallh; + double *waterFallAvg; + boolean_t initDone; int iteration; - void (*gNBfunct) (struct OAIgraph *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id); + void (*gNBfunct) (struct OAIgraph *graph, scopeData_t *p, int UE_id); void (*nrUEfunct)(struct OAIgraph *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id); } OAIgraph_t; @@ -94,57 +96,114 @@ static void dl_traffic_on_off( FL_OBJECT *button, long arg) { } #endif -static FL_OBJECT *commonGraph( int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { - FL_OBJECT *graph; - graph=fl_add_xyplot(type, x, y, w, h, label); - fl_set_object_lcolor(graph, FL_WHITE ); // Label color - fl_set_object_color(graph, FL_BLACK, pointColor); - fl_set_xyplot_symbol(graph, -1, drawsymbol); - return graph; +#define WATERFALL 10000 + +static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { + if (type==WATERFALL) { + graph->waterFallh=h-15; + graph->waterFallAvg=malloc(sizeof(*graph->waterFallAvg) * graph->waterFallh); + + for (int i=0; i< graph->waterFallh; i++) + graph->waterFallAvg[i]=0; + + graph->graph=fl_add_canvas(FL_NORMAL_CANVAS, x, y, w, graph->waterFallh, label); + graph->text=fl_add_text(FL_NORMAL_TEXT, x, y+graph->waterFallh, w, 15, label); + fl_set_object_lcolor(graph->text,FL_WHITE); + fl_set_object_color(graph->text, FL_BLACK, FL_BLACK); + fl_set_object_lalign(graph->text, FL_ALIGN_CENTER ); + } else { + graph->graph=fl_add_xyplot(type, x, y, w, h, label); + fl_set_object_lcolor(graph->graph, FL_WHITE ); // Label color + fl_set_object_color(graph->graph, FL_BLACK, pointColor); + + for (int i=0; i< FL_MAX_XYPLOTOVERLAY; i++) + fl_set_xyplot_symbol(graph->graph, i, drawsymbol); + } + + graph->x=x; + graph->y=y; + graph->w=w; + graph->h=h; + graph->maxX=0; + graph->maxY=0; + graph->minX=0; + graph->minY=0; + graph->initDone=false; + graph->iteration=0; } -static OAIgraph_t gNBcommonGraph( void (*funct) (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id), +static OAIgraph_t gNBcommonGraph( void (*funct) (OAIgraph_t *graph, scopeData_t *p, int UE_id), int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { OAIgraph_t graph; - graph.graph=commonGraph(type, x, y, w, h, label, pointColor); + commonGraph(&graph, type, x, y, w, h, label, pointColor); graph.gNBfunct=funct; graph.nrUEfunct=NULL; - graph.maxX=0; - graph.maxY=0; - graph.minX=0; - graph.minY=0; return graph; } static OAIgraph_t nrUEcommonGraph( void (*funct) (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id), int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { OAIgraph_t graph; - graph.graph=commonGraph(type, x, y, w, h, label, pointColor); + commonGraph(&graph, type, x, y, w, h, label, pointColor); graph.gNBfunct=NULL; graph.nrUEfunct=funct; - graph.maxX=0; - graph.maxY=0; - graph.minX=0; - graph.minY=0; return graph; } static void setRange(OAIgraph_t *graph, float minX, float maxX, float minY, float maxY) { - if ( maxX > graph->maxX || maxY > graph->maxY || minX < graph->minX || minY < graph->minY ) { + if ( maxX > graph->maxX || minX < graph->minX || + abs(maxX-graph->maxX)>abs(graph->maxX)/2 || + abs(maxX-graph->maxX)>abs(graph->maxX)/2 ) { + graph->maxX/=2; + graph->minX/=2; graph->maxX=max(graph->maxX,maxX); graph->minX=min(graph->minX,minX); + fl_set_xyplot_xbounds(graph->graph, graph->minX*1.2, graph->maxX*1.2); + } + + if ( maxY > graph->maxY || minY < graph->minY || + abs(maxY-graph->maxY)>abs(graph->maxY)/2 || + abs(maxY-graph->maxY)>abs(graph->maxY)/2 ) { + graph->maxY/=2; + graph->minY/=2; graph->maxY=max(graph->maxY,maxY); graph->minY=min(graph->minY,minY); - fl_set_xyplot_ybounds(graph->graph, graph->minY, graph->maxY); - fl_set_xyplot_xbounds(graph->graph, graph->minX, graph->maxX); + fl_set_xyplot_ybounds(graph->graph, graph->minY*1.2, graph->maxY*1.2); } } -static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, int NoAutoScale) { - if (layer==0) - fl_set_xyplot_data(graph->graph,x,y,len,"","",""); - else - fl_add_xyplot_overlay(graph->graph,layer,x,y,len,rx_antenna_colors[layer]); +static void oai_xygraph_getbuff(OAIgraph_t *graph, float **x, float **y, int len, int layer) { + float *old_x; + float *old_y; + int old_len=-1; + + if (graph->iteration >1) + fl_get_xyplot_data_pointer(graph->graph, layer, &old_x, &old_y, &old_len); + + if (old_len != len) { + LOG_W(HW,"allocating graph of %d scope\n", len); + float values[len]; + float time[len]; + + // make time in case we will use it + for (int i=0; igraph,time,values,len,"","",""); + else + fl_add_xyplot_overlay(graph->graph,layer,time,values,len,rx_antenna_colors[layer]); + + fl_get_xyplot_data_pointer(graph->graph, layer, &old_x, &old_y, &old_len); + AssertFatal(old_len==len,""); + } + + *x=old_x; + *y=old_y; +} + +static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, boolean_t NoAutoScale) { + fl_redraw_object(graph->graph); if ( NoAutoScale && graph->iteration%NoAutoScale == 0) { float maxX=0, maxY=0, minX=0, minY=0; @@ -156,46 +215,79 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye minY=min(minY,y[k]); } - setRange(graph,minX,maxX, minY, maxY); + setRange(graph, minX-5, maxX+5, minY-5, maxY+5); } graph->iteration++; } -static void genericLogPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) { - float *values=malloc(len*sizeof(*values)); - float *time=malloc(len*sizeof(*time)); +static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize, const int divisions, const char *label) { + if ( values == NULL ) + return; - for (int ant=0; antgraph)); + const int samplesPerPixel=datasize/graph->w; + int displayPart=graph->waterFallh-ScaleZone; + int row=graph->iteration%displayPart; + double avg=0; - for (int k=0; k<8; k++ ) { - vals[k] = 10*log10(1.0+SquaredNorm(in[k])); - tim[k] = i+k; - } - } + for (int i=0; i < displayPart; i++) + avg+=graph->waterFallAvg[i]; - oai_xygraph(graph,time,values, len, ant, 10); - } + avg/=displayPart; + graph->waterFallAvg[row]=0; + + for (int pix=0; pixw; pix++) { + scopeSample_t *end=values+(pix+1)*samplesPerPixel; + end-=2; + AssertFatal(end <= values+datasize,"diff : %ld", end-values+datasize); + double val=0; + + for (scopeSample_t *s=values+(pix)*samplesPerPixel; + s waterFallAvg[row]+=val/graph->w; + int col=0; + + if (val > avg*2 ) + col=1; + + if (val > avg*10 ) + col=2; + + if (val > avg*100 ) + col=3; + + fl_point(pix, graph->iteration%displayPart, water_colors[col]); } - free(values); - free(time); + if (graph->initDone==false) { + for ( int i=0; i < graph->waterFallh; i++ ) + for ( int j = 0 ; j < graph->w ; j++ ) + fl_point(j, i, FL_BLACK); + + for ( int i=1; iwaterFallh; j++) + fl_point(i*(graph->w/divisions),j, FL_WHITE); + + graph->initDone=true; + } + + fl_set_object_label_f(graph->text, "%s, avg I/Q pow: %4.1f", label, 0/*sqrt(avg)*/); + graph->iteration++; } static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) { - float values[len]; - float time[len]; + float *values, *time; + oai_xygraph_getbuff(graph, &time, &values, len, 0); for (int ant=0; antgNB->frame_parms; + //use 1st antenna + genericWaterFall(graph, (scopeSample_t *)p->ru->common.rxdata[0], + frame_parms->samples_per_frame, frame_parms->slots_per_frame, + "X axis:one frame in time"); +} + +/* replaced by waterfall static void timeSignal (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, const int nb_UEs) { // Received signal in time domain of receive antenna 0 if (!phy_vars_ru->common.rxdata) @@ -213,47 +314,62 @@ static void timeSignal (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy (const scopeSample_t **)phy_vars_ru->common.rxdata, frame_parms->samples_per_frame); } +*/ -static void timeResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { - const int len=2*phy_vars_gnb->frame_parms.ofdm_symbol_size; - float values[len]; - float time[len]; +static void timeResponse (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) { + const int len=2*p->gNB->frame_parms.ofdm_symbol_size; + float *values, *time; + oai_xygraph_getbuff(graph, &time, &values, len, 0); const int ant=0; // display antenna 0 for each UE for (int ue=0; uepusch_vars[ue]->ul_ch_estimates_time[ant]; + if ( p->gNB->pusch_vars && p->gNB->pusch_vars[ue] && + p->gNB->pusch_vars[ue]->ul_ch_estimates_time && + p->gNB->pusch_vars[ue]->ul_ch_estimates_time[ant] ) { + scopeSample_t *data= (scopeSample_t *)p->gNB->pusch_vars[ue]->ul_ch_estimates_time[ant]; - if (data != NULL) { - for (int i=0; igNB->frame_parms; + //use 1st antenna + genericWaterFall(graph, (scopeSample_t *)p->rxdataF, frame_parms->samples_per_frame_wCP, + frame_parms->slots_per_frame, + "X axis: Frequency domain, one subframe"); +} + +/* static void frequencyResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; genericLogPowerPerAntena(graph, frame_parms->nb_antennas_rx, (const scopeSample_t **)phy_vars_ru->common.rxdataF, frame_parms->samples_per_slot_wCP); } +*/ -static void puschLLR (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { +static void puschLLR (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) { //int Qm = 2; int coded_bits_per_codeword =3*8*6144+12; // (8*((3*8*6144)+12)); // frame_parms->N_RB_UL*12*Qm*frame_parms->symbols_per_tti; - float llr[coded_bits_per_codeword]; - float bit[coded_bits_per_codeword]; for (int ue=0; uepusch_vars[ue]->llr; + if ( p->gNB->pusch_vars && + p->gNB->pusch_vars[ue] && + p->gNB->pusch_vars[ue]->llr ) { + int16_t *pusch_llr = (int16_t *)p->gNB->pusch_vars[ue]->llr; + float *llr, *bit; + oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword, ue); - if (pusch_llr) { for (int i=0; iframe_parms; +static void puschIQ (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) { + NR_DL_FRAME_PARMS *frame_parms=&p->gNB->frame_parms; int sz=frame_parms->N_RB_UL*12*frame_parms->symbols_per_slot; - float I[sz], Q[sz]; for (int ue=0; uepusch_vars[ue]->rxdataF_comp[0]; + if ( p->gNB->pusch_vars && + p->gNB->pusch_vars[ue] && + p->gNB->pusch_vars[ue]->rxdataF_comp && + p->gNB->pusch_vars[ue]->rxdataF_comp[0] ) { + scopeSample_t *pusch_comp = (scopeSample_t *) p->gNB->pusch_vars[ue]->rxdataF_comp[0]; + float *I, *Q; + oai_xygraph_getbuff(graph, &I, &Q, sz, ue); - if (pusch_comp) { for (int k=0; kpucch1ab_stats[UE_id]; @@ -306,12 +426,15 @@ static void pucchEnergy (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *ph */ } -static void pucchIQ (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { +static void pucchIQ (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) { } -static void puschThroughtput (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { +static void puschThroughtput (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) { // PUSCH Throughput /* + float tput_time_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; + float tput_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; + memmove( tput_time_enb[UE_id], &tput_time_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); memmove( tput_enb[UE_id], &tput_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); tput_time_enb[UE_id][TPUT_WINDOW_LENGTH-1] = (float) 0; @@ -321,29 +444,29 @@ static void puschThroughtput (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_ // fl_set_xyplot_ybounds(form->pusch_tput,0,ymax); */ } - static OAI_phy_scope_t *create_phy_scope_gnb(void) { FL_OBJECT *obj; OAI_phy_scope_t *fdui = calloc(( sizeof *fdui ),1); // Define form fdui->phy_scope = fl_bgn_form( FL_NO_BOX, 800, 800 ); + fl_set_form_dblbuffer(fdui->phy_scope, 1); // This the whole UI box obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 800, "" ); fl_set_object_color( obj, FL_BLACK, FL_WHITE ); int curY=0,x,y,w,h; // Received signal - fdui->graph[0] = gNBcommonGraph( timeSignal, FL_NORMAL_XYPLOT, 0, curY, 400, 100, - "Received Signal (Time-Domain, dB)", FL_RED ); + fdui->graph[0] = gNBcommonGraph( gNBWaterFall, WATERFALL, 0, curY, 400, 100, + "Received Signal (Time-Domain, one frame)", FL_RED ); // Time-domain channel response fdui->graph[1] = gNBcommonGraph( timeResponse, FL_NORMAL_XYPLOT, 410, curY, 400, 100, "SRS Frequency Response (samples, abs)", FL_RED ); - fl_get_object_bbox(fdui->graph[0].graph,&x, &y,&w, &h); + fl_get_object_bbox(fdui->graph[1].graph,&x, &y,&w, &h); curY+=h; // Frequency-domain channel response - fdui->graph[2] = gNBcommonGraph( frequencyResponse, FL_NORMAL_XYPLOT, 0, curY, 800, 100, - "Channel Frequency Response (RE, dB)", FL_RED ); + fdui->graph[2] = gNBcommonGraph( gNBfreqWaterFall, WATERFALL, 0, curY, 800, 100, + "Channel Frequency domain (RE, one frame)", FL_RED ); fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h); - curY+=h; + curY+=h+20; // LLR of PUSCH fdui->graph[3] = gNBcommonGraph( puschLLR, FL_POINTS_XYPLOT, 0, curY, 500, 200, "PUSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW ); @@ -370,75 +493,104 @@ static OAI_phy_scope_t *create_phy_scope_gnb(void) { fl_show_form (fdui->phy_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, "LTE UL SCOPE gNB"); return fdui; } - static const int scope_enb_num_ue = 1; void phy_scope_gNB(OAI_phy_scope_t *form, - PHY_VARS_gNB *phy_vars_gnb, - RU_t *phy_vars_ru, + scopeData_t *p, int UE_id) { - static OAI_phy_scope_t *remeberForm=NULL; + static OAI_phy_scope_t *rememberForm=NULL; if (form==NULL) - form=remeberForm; + form=rememberForm; else - remeberForm=form; + rememberForm=form; - if (form==NULL) return; + if (form==NULL) + return; int i=0; while (form->graph[i].graph) { - form->graph[i].gNBfunct(form->graph+i, phy_vars_gnb, phy_vars_ru, UE_id); + form->graph[i].gNBfunct(form->graph+i, p, UE_id); i++; } - fl_check_forms(); + //fl_check_forms(); } - static void *scope_thread_gNB(void *arg) { - scopeParms_t *p=(scopeParms_t *) arg; - //# ifdef ENABLE_XFORMS_WRITE_STATS - // FILE *gNB_stats = fopen("gNB_stats.txt", "w"); - //#endif + scopeData_t *p=(scopeData_t *) arg; size_t stksize=0; pthread_attr_t atr; pthread_attr_init(&atr); pthread_attr_getstacksize(&atr, &stksize); pthread_attr_setstacksize(&atr,32*1024*1024 ); sleep(3); // no clean interthread barriers - fl_initialize (p->argc, p->argv, NULL, 0, 0); + int fl_argc=1; + char *name="5G-gNB-scope"; + fl_initialize (&fl_argc, &name, NULL, 0, 0); int nb_ue=min(NUMBER_OF_UE_MAX, scope_enb_num_ue); OAI_phy_scope_t *form_gnb = create_phy_scope_gnb(); while (!oai_exit) { - phy_scope_gNB(form_gnb, p->gNB, p->ru, nb_ue); + fl_freeze_form(form_gnb->phy_scope); + phy_scope_gNB(form_gnb, p, nb_ue); + fl_unfreeze_form(form_gnb->phy_scope); + fl_redraw_form(form_gnb->phy_scope); usleep(99*1000); } return NULL; } - -void gNBinitScope(scopeParms_t *p) { - static scopeParms_t parms; - memcpy(&parms,p,sizeof(parms)); - pthread_t forms_thread; - threadCreate(&forms_thread, scope_thread_gNB, &parms, "scope", -1, OAI_PRIORITY_RT_LOW); +static void copyRxdataF(int32_t *data, int slot, void *scopeData) { + scopeData_t *scope=(scopeData_t *)scopeData; + memcpy(scope->rxdataF + slot*scope->gNB->frame_parms.samples_per_slot_wCP, + data, + scope->gNB->frame_parms.samples_per_slot_wCP); } +void gNBinitScope(scopeParms_t *p) { + AssertFatal(p->gNB->scopeData=malloc(sizeof(scopeData_t)),""); + scopeData_t *scope=(scopeData_t *) p->gNB->scopeData; + scope->argc=p->argc; + scope->argv=p->argv; + scope->ru=p->ru; + scope->gNB=p->gNB; + scope->slotFunc=copyRxdataF; + AssertFatal(scope->rxdataF=(int32_t *) calloc(p->gNB->frame_parms.samples_per_frame_wCP*sizeof(int32_t),1),""); + pthread_t forms_thread; + threadCreate(&forms_thread, scope_thread_gNB, p->gNB->scopeData, "scope", -1, OAI_PRIORITY_RT_LOW); +} +static void ueWaterFall (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { + // Received signal in time domain of receive antenna 0 + genericWaterFall(graph, + (scopeSample_t *) phy_vars_ue->common_vars.rxdata[0], + phy_vars_ue->frame_parms.samples_per_frame, + phy_vars_ue->frame_parms.slots_per_frame, + "X axis: one frame time"); +} +/* replaced by waterfall static void ueTimeResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // Received signal in time domain of receive antenna 0 genericLogPowerPerAntena(graph, phy_vars_ue->frame_parms.nb_antennas_rx, (const scopeSample_t **) phy_vars_ue->common_vars.rxdata, phy_vars_ue->frame_parms.samples_per_frame); } - +*/ static void ueChannelResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // Channel Impulse Response genericPowerPerAntena(graph, phy_vars_ue->frame_parms.nb_antennas_rx, (const scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates_time, phy_vars_ue->frame_parms.ofdm_symbol_size>>3); } - +static void ueFreqWaterFall (OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id ) { + NR_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->frame_parms; + //use 1st antenna + genericWaterFall(graph, + (scopeSample_t *)phy_vars_ue->common_vars.common_vars_rx_data_per_thread[0].rxdataF[0], + frame_parms->samples_per_slot_wCP, + phy_vars_ue->frame_parms.slots_per_frame, + "X axis: one frame frequency" ); +} +/* static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // Channel Frequency Response (includes 5 complex sample for filter) if (!phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates) @@ -449,12 +601,13 @@ static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue uint8_t nb_antennas_tx = frame_parms->nb_antenna_ports_gNB; scopeSample_t **chest_f = (scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates; int ind = 0; - float chest_f_abs[frame_parms->ofdm_symbol_size]; - float freq[frame_parms->ofdm_symbol_size]; + float *freq, *chest_f_abs; + oai_xygraph_getbuff(graph, &freq, &chest_f_abs, frame_parms->ofdm_symbol_size, 0); for (int atx=0; atxofdm_symbol_size; k++) { freq[ind] = (float)ind; chest_f_abs[ind] = (short)10*log10(1.0+SquaredNorm(chest_f[(atx<<1)+arx][6144+k])); @@ -471,31 +624,32 @@ static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue //fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); oai_xygraph(graph,freq,chest_f_abs,frame_parms->ofdm_symbol_size,0,10); } - +*/ static void uePbchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PBCH LLRs if ( !phy_vars_ue->pbch_vars[eNB_id]->llr) return; int16_t *pbch_llr = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->llr; - float llr_pbch[864], bit_pbch[864]; + float *llr_pbch, *bit_pbch; + oai_xygraph_getbuff(graph, &bit_pbch, &llr_pbch, 864, 0); for (int i=0; i<864; i++) { llr_pbch[i] = (float) pbch_llr[i]; - bit_pbch[i] = (float) i; } oai_xygraph(graph,bit_pbch,llr_pbch,864,0,10); } - static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PBCH I/Q of MF Output if (!phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]) return; scopeSample_t *pbch_comp = (scopeSample_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; - localBuff(I,180*3); - localBuff(Q,180*3); + float *I, *Q; + oai_xygraph_getbuff(graph, &I, &Q, 180*3, 0); + memset(I,0,180*3*sizeof(*I)); + memset(Q,0,180*3*sizeof(*Q)); int first_symbol=1; int base=0; @@ -517,50 +671,42 @@ static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i base+=nb_re; } - oai_xygraph(graph,I,Q,base,0,10); + AssertFatal(base <= 180*3,""); + oai_xygraph(graph,I,Q,base,0, 10); } - static void uePcchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PDCCH LLRs if (!phy_vars_ue->pdcch_vars[0][eNB_id]->llr) return; - NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; - uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; - uint8_t nb_antennas_tx = frame_parms->nb_antennas_tx; - scopeSample_t **chest_f = (scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates; - int ind = 0; - float chest_f_abs[frame_parms->ofdm_symbol_size]; - float freq[frame_parms->ofdm_symbol_size]; + //int num_re = 4*273*12; // 12*frame_parms->N_RB_DL*num_pdcch_symbols + //int Qm = 2; + int coded_bits_per_codeword = 2*4*100*12; //num_re*Qm; + float *llr, *bit; + oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword*RX_NB_TH_MAX, 0); + int base=0; - for (int atx=0; atxofdm_symbol_size; k++) { - freq[ind] = (float)ind; - chest_f_abs[ind] = (short)10*log10(1.0+SquaredNorm(chest_f[(atx<<1)+arx][6144+k])); - ind++; - } - } + for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { + int16_t *pdcch_llr = (int16_t *) phy_vars_ue->pdcch_vars[thr][eNB_id]->llr; + + for (int i=0; ichest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); - //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); - // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); - //fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); - oai_xygraph(graph,freq,chest_f_abs,frame_parms->ofdm_symbol_size,0,10); + AssertFatal(base <= coded_bits_per_codeword*RX_NB_TH_MAX, ""); + oai_xygraph(graph,bit,llr,base,0,10); } - static void uePcchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PDCCH I/Q of MF Output if (!phy_vars_ue->pdcch_vars[0][eNB_id]->rxdataF_comp[0]) return; int nb=4*273*12; // 12*frame_parms->N_RB_DL*num_pdcch_symbols - localBuff(I,nb*RX_NB_TH_MAX); - localBuff(Q,nb*RX_NB_TH_MAX); + float *I, *Q; + oai_xygraph_getbuff(graph, &I, &Q, nb*RX_NB_TH_MAX, 0); int base=0; for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { @@ -574,9 +720,9 @@ static void uePcchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i base+=nb; } + AssertFatal(base <= nb*RX_NB_TH_MAX, ""); oai_xygraph(graph,I,Q,base,0,10); } - static void uePdschLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PDSCH LLRs if (!phy_vars_ue->pdsch_vars[0][eNB_id]->llr[0]) @@ -585,8 +731,8 @@ static void uePdschLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB int num_re = 4500; int Qm = 2; int coded_bits_per_codeword = num_re*Qm; - localBuff(llr,coded_bits_per_codeword*RX_NB_TH_MAX); - localBuff(bit,coded_bits_per_codeword*RX_NB_TH_MAX); + float *llr, *bit; + oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword*RX_NB_TH_MAX, 0); int base=0; for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { @@ -600,10 +746,10 @@ static void uePdschLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB base+=coded_bits_per_codeword; } + AssertFatal(base <= coded_bits_per_codeword*RX_NB_TH_MAX, ""); //fl_set_xyplot_xbounds(form->pdsch_llr,0,coded_bits_per_codeword); oai_xygraph(graph,bit,llr,base,0,10); } - static void uePdschIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { // PDSCH I/Q of MF Output if (!phy_vars_ue->pdsch_vars[0][eNB_id]->rxdataF_comp0[0]) @@ -611,9 +757,11 @@ static void uePdschIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_ NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; int sz=7*2*frame_parms->N_RB_DL*12; // size of the malloced buffer - localBuff(I,sz*RX_NB_TH_MAX); - localBuff(Q,sz*RX_NB_TH_MAX); + float *I, *Q; + oai_xygraph_getbuff(graph, &I, &Q, sz*RX_NB_TH_MAX, 0); int base=0; + memset(I+base, 0, sz*RX_NB_TH_MAX * sizeof(*I)); + memset(Q+base, 0, sz*RX_NB_TH_MAX * sizeof(*Q)); for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { scopeSample_t *pdsch_comp = (scopeSample_t *) phy_vars_ue->pdsch_vars[thr][eNB_id]->rxdataF_comp0[0]; @@ -626,11 +774,15 @@ static void uePdschIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_ base+=sz; } - oai_xygraph(graph,I,Q,base,0,10); + AssertFatal(base <= sz*RX_NB_TH_MAX, ""); + oai_xygraph(graph,I,Q,sz*RX_NB_TH_MAX,0,10); } - static void uePdschThroughput (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { /* + float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; + float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; + float tput_ue_max[NUMBER_OF_UE_MAX] = {0}; + // PDSCH Throughput memmove( tput_time_ue[UE_id], &tput_time_ue[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) ); @@ -648,29 +800,29 @@ static void uePdschThroughput (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, fl_set_xyplot_ybounds(form->pdsch_tput,0,tput_ue_max[UE_id]); */ } - static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) { FL_OBJECT *obj; OAI_phy_scope_t *fdui = calloc(( sizeof *fdui ),1); // Define form fdui->phy_scope = fl_bgn_form( FL_NO_BOX, 800, 900 ); + fl_set_form_dblbuffer(fdui->phy_scope, 1); // This the whole UI box obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 900, "" ); fl_set_object_color( obj, FL_BLACK, FL_BLACK ); int curY=0,x,y,w,h; // Received signal - fdui->graph[0] = nrUEcommonGraph(ueTimeResponse, - FL_NORMAL_XYPLOT, 0, curY, 400, 100, "Received Signal (Time-Domain, dB)", FL_RED ); + fdui->graph[0] = nrUEcommonGraph(ueWaterFall, + WATERFALL, 0, curY, 400, 100, "Received Signal (Time-Domain, one frame)", FL_RED ); // Time-domain channel response fdui->graph[1] = nrUEcommonGraph(ueChannelResponse, FL_NORMAL_XYPLOT, 400, curY, 400, 100, "Channel Impulse Response (samples, abs)", FL_RED ); - fl_get_object_bbox(fdui->graph[0].graph,&x, &y,&w, &h); + fl_get_object_bbox(fdui->graph[1].graph,&x, &y,&w, &h); curY+=h; // Frequency-domain channel response - fdui->graph[2] = nrUEcommonGraph(uePbchFrequencyResp, - FL_IMPULSE_XYPLOT, 0, curY, 800, 100, "Channel Frequency data (RE, dB)", FL_RED ); + fdui->graph[2] = nrUEcommonGraph(ueFreqWaterFall, + WATERFALL, 0, curY, 800, 100, "Channel Frequency (RE, one slot)", FL_RED ); fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h); - curY+=h; + curY+=h+20; // LLR of PBCH fdui->graph[3] = nrUEcommonGraph(uePbchLLR, FL_POINTS_XYPLOT, 0, curY, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)", FL_GREEN ); @@ -718,7 +870,6 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) { fl_show_form (fdui->phy_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, buf); return fdui; } - void phy_scope_nrUE(OAI_phy_scope_t *form, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, @@ -740,14 +891,12 @@ void phy_scope_nrUE(OAI_phy_scope_t *form, i++; } - fl_check_forms(); + //fl_check_forms(); } - - static void *nrUEscopeThread(void *arg) { PHY_VARS_NR_UE *ue=(PHY_VARS_NR_UE *)arg; size_t stksize; - pthread_attr_t atr; + pthread_attr_t atr={0}; pthread_attr_getstacksize(&atr, &stksize); pthread_attr_setstacksize(&atr,32*1024*1024 ); int fl_argc=1; @@ -756,28 +905,28 @@ static void *nrUEscopeThread(void *arg) { OAI_phy_scope_t *form_nrue=create_phy_scope_nrue(0); while (!oai_exit) { + fl_freeze_form(form_nrue->phy_scope); phy_scope_nrUE(form_nrue, ue, 0,0); + fl_unfreeze_form(form_nrue->phy_scope); + fl_redraw_form(form_nrue->phy_scope); usleep(99*1000); } pthread_exit((void *)arg); } - void nrUEinitScope(PHY_VARS_NR_UE *ue) { pthread_t forms_thread; threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW); } - - void nrscope_autoinit(void *dataptr) { AssertFatal( (IS_SOFTMODEM_GNB_BIT||IS_SOFTMODEM_5GUE_BIT),"Scope cannot find NRUE or GNB context"); - + if (IS_SOFTMODEM_GNB_BIT) - gNBinitScope(dataptr); + gNBinitScope(dataptr); else - nrUEinitScope(dataptr); + nrUEinitScope(dataptr); } // Kept to put back the functionality soon #if 0 @@ -805,9 +954,6 @@ static void reset_stats_gNB(FL_OBJECT *button, } } } - - - static FD_stats_form *create_form_stats_form(int ID) { FL_OBJECT *obj; FD_stats_form *fdui = calloc(( sizeof *fdui ),1); @@ -827,7 +973,3 @@ static FD_stats_form *create_form_stats_form(int ID) { return fdui; } #endif - - - - diff --git a/openair1/PHY/TOOLS/nr_phy_scope.h b/openair1/PHY/TOOLS/nr_phy_scope.h index 84b9e66908..e34ddf2c20 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.h +++ b/openair1/PHY/TOOLS/nr_phy_scope.h @@ -33,13 +33,7 @@ //#include "PHY/impl_defs_top.h" #include "PHY/defs_nr_UE.h" -typedef struct { - int *argc; - char **argv; - RU_t *ru; - PHY_VARS_gNB *gNB; -} scopeParms_t; - +#include extern RAN_CONTEXT_t RC; #endif diff --git a/openair1/PHY/TOOLS/oai_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c index 25244eeff5..83207426fd 100644 --- a/openair1/PHY/TOOLS/oai_dfts.c +++ b/openair1/PHY/TOOLS/oai_dfts.c @@ -18,7 +18,7 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ - + #include #include #include @@ -32,17 +32,17 @@ #define M_PI 3.14159265358979323846 #endif #define OAIDFTS_MAIN -#ifndef MR_MAIN -#include "PHY/defs_common.h" -#include "PHY/impl_defs_top.h" -#else +//#ifndef MR_MAIN +//#include "PHY/defs_common.h" +//#include "PHY/impl_defs_top.h" +//#else #include "time_meas.h" #include "LOG/log.h" #define debug_msg #define ONE_OVER_SQRT2_Q15 23170 -int oai_exit=0; -#endif +//int oai_exit=0; +//#endif #define ONE_OVER_SQRT3_Q15 18919 @@ -50,6 +50,8 @@ int oai_exit=0; #include "assertions.h" +#include "tools_defs.h" + #define print_shorts(s,x) printf("%s %d,%d,%d,%d,%d,%d,%d,%d\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7]) #define print_shorts256(s,x) printf("%s %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7],(x)[8],(x)[9],(x)[10],(x)[11],(x)[12],(x)[13],(x)[14],(x)[15]) @@ -112,7 +114,7 @@ static inline void cmac_256(__m256i a,__m256i b, __m256i *re32, __m256i *im32) { __m256i cmac_tmp,cmac_tmp_re32,cmac_tmp_im32; - __m256i imshuffle = _mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,19,18,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + __m256i imshuffle = _mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); cmac_tmp = _mm256_sign_epi16(b,*(__m256i*)reflip); cmac_tmp_re32 = _mm256_madd_epi16(a,cmac_tmp); @@ -129,7 +131,7 @@ static inline void cmacc_256(__m256i a,__m256i b, __m256i *re32, __m256i *im32) { __m256i cmac_tmp,cmac_tmp_re32,cmac_tmp_im32; - __m256i imshuffle = _mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,19,18,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); + __m256i imshuffle = _mm256_set_epi8(29,28,31,30,25,24,27,26,21,20,23,22,17,16,19,18,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2); cmac_tmp_re32 = _mm256_madd_epi16(a,b); @@ -3103,10 +3105,12 @@ void dft128(int16_t *x,int16_t *y,unsigned char scale) dft64((int16_t*)(xtmp),(int16_t*)ytmp,1); dft64((int16_t*)(xtmp+32),(int16_t*)(ytmp+16),1); +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft128a.m","dfta",ytmp,64,1,1); LOG_M("dft128b.m","dftb",ytmp+16,64,1,1); } +#endif for (i=0; i<16; i++) { bfly2_16(ytmpp,ytmpp+16, y128p,y128p+16, @@ -3155,10 +3159,12 @@ void dft128(int16_t *x,int16_t *y,unsigned char scale) } +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft128out.m","dft128",y,128,1,1); exit(-1); } +#endif _mm_empty(); _m_empty(); @@ -3183,18 +3189,20 @@ void dft128(int16_t *x,int16_t *y,unsigned char scale) transpose4_ooff_simd256(x256+10,xtmp+5,8); transpose4_ooff_simd256(x256+12,xtmp+6,8); transpose4_ooff_simd256(x256+14,xtmp+7,8); +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft128ina_256.m","dftina",xtmp,64,1,1); LOG_M("dft128inb_256.m","dftinb",xtmp+8,64,1,1); } - +#endif dft64((int16_t*)(xtmp),(int16_t*)ytmp,1); dft64((int16_t*)(xtmp+8),(int16_t*)(ytmp+8),1); +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft128outa_256.m","dftouta",ytmp,64,1,1); LOG_M("dft128outb_256.m","dftoutb",ytmp+8,64,1,1); } - +#endif for (i=0; i<8; i++) { bfly2_16_256(ytmpp,ytmpp+8, y256p,y256p+8, @@ -3226,10 +3234,12 @@ void dft128(int16_t *x,int16_t *y,unsigned char scale) y256[15] = mulhi_int16_simd256(y256[15],ONE_OVER_SQRT2_Q15_256); } +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft128.m","dft",y256,128,1,1); exit(-1); } +#endif } #endif @@ -5952,8 +5962,6 @@ void idft32768(int16_t *x,int16_t *y,unsigned char scale) #endif - - int16_t twa1536[1024],twb1536[1024]; // 512 x 3 @@ -6033,11 +6041,13 @@ void dft1536(int16_t *input, int16_t *output, unsigned char scale) tmpo[1][i] = tmpo[1][i<<1]; tmpo[2][i] = tmpo[2][i<<1]; }*/ +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft1536out0.m","o0",tmpo[0],2048,1,1); LOG_M("dft1536out1.m","o1",tmpo[1],2048,1,1); LOG_M("dft1536out2.m","o2",tmpo[2],2048,1,1); } +#endif for (i=0,i2=0; i<1024; i+=8,i2+=4) { bfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),(simd_q15_t*)(&tmpo[2][i2]), (simd_q15_t*)(output+i),(simd_q15_t*)(output+1024+i),(simd_q15_t*)(output+2048+i), @@ -6195,14 +6205,14 @@ void idft6144(int16_t *input, int16_t *output,unsigned char scale) idft2048((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1); idft2048((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1); idft2048((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1); - +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("idft6144in.m","in",input,6144,1,1); LOG_M("idft6144out0.m","o0",tmpo[0],2048,1,1); LOG_M("idft6144out1.m","o1",tmpo[1],2048,1,1); LOG_M("idft6144out2.m","o2",tmpo[2],2048,1,1); } - +#endif for (i=0,i2=0; i<4096; i+=8,i2+=4) { ibfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]), (simd_q15_t*)(output+i),(simd_q15_t*)(output+4096+i),(simd_q15_t*)(output+8192+i), @@ -6262,11 +6272,13 @@ void dft6144(int16_t *input, int16_t *output,unsigned char scale) tmpo[1][i] = tmpo[1][i<<1]; tmpo[2][i] = tmpo[2][i<<1]; }*/ +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("ft6144out0.m","o0",tmpo[0],2048,1,1); LOG_M("ft6144out1.m","o1",tmpo[1],2048,1,1); LOG_M("ft6144out2.m","o2",tmpo[2],2048,1,1); } +#endif for (i=0,i2=0; i<4096; i+=8,i2+=4) { bfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),(simd_q15_t*)(&tmpo[2][i2]), (simd_q15_t*)(output+i),(simd_q15_t*)(output+4096+i),(simd_q15_t*)(output+8192+i), @@ -6338,11 +6350,13 @@ void dft12288(int16_t *input, int16_t *output,unsigned char scale) tmpo[1][i] = tmpo[1][i<<1]; tmpo[2][i] = tmpo[2][i<<1]; }*/ +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft12288out0.m","o0",tmpo[0],4096,1,1); LOG_M("dft12288out1.m","o1",tmpo[1],4096,1,1); LOG_M("dft12288out2.m","o2",tmpo[2],4096,1,1); } +#endif for (i=0,i2=0; i<8192; i+=8,i2+=4) { bfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),(simd_q15_t*)(&tmpo[2][i2]), (simd_q15_t*)(output+i),(simd_q15_t*)(output+8192+i),(simd_q15_t*)(output+16384+i), @@ -6394,14 +6408,14 @@ void idft12288(int16_t *input, int16_t *output,unsigned char scale) idft4096((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),scale); idft4096((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),scale); idft4096((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),scale); - +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("idft12288in.m","in",input,12288,1,1); LOG_M("idft12288out0.m","o0",tmpo[0],4096,1,1); LOG_M("idft12288out1.m","o1",tmpo[1],4096,1,1); LOG_M("idft12288out2.m","o2",tmpo[2],4096,1,1); } - +#endif for (i=0,i2=0; i<8192; i+=8,i2+=4) { ibfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]), (simd_q15_t*)(output+i),(simd_q15_t*)(output+8192+i),(simd_q15_t*)(output+16384+i), @@ -6431,9 +6445,11 @@ void idft12288(int16_t *input, int16_t *output,unsigned char scale) } _mm_empty(); _m_empty(); +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("idft12288out.m","out",output,6144,1,1); } +#endif } int16_t twa18432[12288] __attribute__((aligned(32))); @@ -6562,11 +6578,13 @@ void dft24576(int16_t *input, int16_t *output,unsigned char scale) tmpo[1][i] = tmpo[1][i<<1]; tmpo[2][i] = tmpo[2][i<<1]; }*/ +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft24576out0.m","o0",tmpo[0],8192,1,1); LOG_M("dft24576out1.m","o1",tmpo[1],8192,1,1); LOG_M("dft24576out2.m","o2",tmpo[2],8192,1,1); } +#endif for (i=0,i2=0; i<16384; i+=8,i2+=4) { bfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),(simd_q15_t*)(&tmpo[2][i2]), (simd_q15_t*)(output+i),(simd_q15_t*)(output+16384+i),(simd_q15_t*)(output+32768+i), @@ -6597,9 +6615,11 @@ void dft24576(int16_t *input, int16_t *output,unsigned char scale) } _mm_empty(); _m_empty(); +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("out.m","out",output,24576,1,1); } +#endif } void idft24576(int16_t *input, int16_t *output,unsigned char scale) @@ -6619,14 +6639,14 @@ void idft24576(int16_t *input, int16_t *output,unsigned char scale) idft8192((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1); idft8192((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1); idft8192((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1); - + #ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("idft24576in.m","in",input,24576,1,1); LOG_M("idft24576out0.m","o0",tmpo[0],8192,1,1); LOG_M("idft24576out1.m","o1",tmpo[1],8192,1,1); LOG_M("idft24576out2.m","o2",tmpo[2],8192,1,1); } - +#endif for (i=0,i2=0; i<16384; i+=8,i2+=4) { ibfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]), (simd_q15_t*)(output+i),(simd_q15_t*)(output+16384+i),(simd_q15_t*)(output+32768+i), @@ -6655,10 +6675,11 @@ void idft24576(int16_t *input, int16_t *output,unsigned char scale) } _mm_empty(); _m_empty(); - +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("idft24576out.m","out",output,24576,1,1); } +#endif } int16_t twa36864[24576] __attribute__((aligned(32))); @@ -6682,13 +6703,13 @@ void dft36864(int16_t *input, int16_t *output,uint8_t scale) { dft12288((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1); dft12288((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1); dft12288((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1); - +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("dft36864out0.m","o0",tmpo[0],12288,1,1); LOG_M("dft36864out1.m","o1",tmpo[1],12288,1,1); LOG_M("dft36864out2.m","o2",tmpo[2],12288,1,1); } - +#endif for (i=0,i2=0; i<24576; i+=8,i2+=4) { bfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),(simd_q15_t*)(&tmpo[2][i2]), (simd_q15_t*)(output+i),(simd_q15_t*)(output+24576+i),(simd_q15_t*)(output+49152+i), @@ -6718,9 +6739,11 @@ void dft36864(int16_t *input, int16_t *output,uint8_t scale) { } _mm_empty(); _m_empty(); +#ifndef MR_MAIN if (LOG_DUMPFLAG(DEBUG_DFT)) { LOG_M("out.m","out",output,36864,1,1); } +#endif } void idft36864(int16_t *input, int16_t *output,uint8_t scale) { @@ -9471,6 +9494,919 @@ void dft1200(int16_t *x,int16_t *y,unsigned char scale_flag) } + +static int16_t twa1296[431*2*4]; +static int16_t twb1296[431*2*4]; + +void dft1296(int16_t *x,int16_t *y,unsigned char scale_flag) //432 * 3 +{ + + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1296[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1296[0]; + simd_q15_t x2128[1296];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1296];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<432; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+432] = x128[j+1]; + x2128[i+864] = x128[j+2]; + } + + dft432((int16_t *)x2128,(int16_t *)ytmp128,1); + dft432((int16_t *)(x2128+432),(int16_t *)(ytmp128+432),1); + dft432((int16_t *)(x2128+864),(int16_t *)(ytmp128+864),1); + + bfly3_tw1(ytmp128,ytmp128+432,ytmp128+864,y128,y128+432,y128+864); + + for (i=1,j=0; i<432; i++,j++) { + bfly3(ytmp128+i, + ytmp128+432+i, + ytmp128+864+i, + y128+i, + y128+432+i, + y128+864+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1296; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + + +static int16_t twa1440[479*2*4]; +static int16_t twb1440[479*2*4]; + +void dft1440(int16_t *x,int16_t *y,unsigned char scale_flag) // 480 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1440[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1440[0]; + simd_q15_t x2128[1440];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1440];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<480; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+480] = x128[j+1]; + x2128[i+960] = x128[j+2]; + } + + dft480((int16_t *)x2128,(int16_t *)ytmp128,1); + dft480((int16_t *)(x2128+480),(int16_t *)(ytmp128+480),1); + dft480((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1); + + bfly3_tw1(ytmp128,ytmp128+480,ytmp128+960,y128,y128+480,y128+960); + + for (i=1,j=0; i<480; i++,j++) { + bfly3(ytmp128+i, + ytmp128+480+i, + ytmp128+960+i, + y128+i, + y128+480+i, + y128+960+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1440; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1500[2392]__attribute__((aligned(32))); +static int16_t twb1500[2392]__attribute__((aligned(32))); +static int16_t twc1500[2392]__attribute__((aligned(32))); +static int16_t twd1500[2392]__attribute__((aligned(32))); + +void dft1500(int16_t *x,int16_t *y,unsigned char scale_flag) +{ + + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1500[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1500[0]; + simd_q15_t *twc128=(simd_q15_t *)&twc1500[0]; + simd_q15_t *twd128=(simd_q15_t *)&twd1500[0]; + simd_q15_t x2128[1500];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1500];//=&ytmp128array2[0]; + + + + for (i=0,j=0; i<300; i++,j+=5) { + x2128[i] = x128[j]; + x2128[i+300] = x128[j+1]; + x2128[i+600] = x128[j+2]; + x2128[i+900] = x128[j+3]; + x2128[i+1200] = x128[j+4]; + } + + dft300((int16_t *)x2128,(int16_t *)ytmp128,1); + dft300((int16_t *)(x2128+300),(int16_t *)(ytmp128+300),1); + dft300((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1); + dft300((int16_t *)(x2128+900),(int16_t *)(ytmp128+900),1); + dft300((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1); + + bfly5_tw1(ytmp128,ytmp128+300,ytmp128+600,ytmp128+900,ytmp128+1200,y128,y128+300,y128+600,y128+900,y128+1200); + + for (i=1,j=0; i<300; i++,j++) { + bfly5(ytmp128+i, + ytmp128+300+i, + ytmp128+600+i, + ytmp128+900+i, + ytmp128+1200+i, + y128+i, + y128+300+i, + y128+600+i, + y128+900+i, + y128+1200+i, + twa128+j, + twb128+j, + twc128+j, + twd128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[15]); + + for (i=0; i<1500; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +} + +static int16_t twa1620[539*2*4]; +static int16_t twb1620[539*2*4]; + +void dft1620(int16_t *x,int16_t *y,unsigned char scale_flag) // 540 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1620[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1620[0]; + simd_q15_t x2128[1620];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1620];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<540; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+540] = x128[j+1]; + x2128[i+1080] = x128[j+2]; + } + + dft540((int16_t *)x2128,(int16_t *)ytmp128,1); + dft540((int16_t *)(x2128+540),(int16_t *)(ytmp128+540),1); + dft540((int16_t *)(x2128+1080),(int16_t *)(ytmp128+1080),1); + + bfly3_tw1(ytmp128,ytmp128+540,ytmp128+1080,y128,y128+540,y128+1080); + + for (i=1,j=0; i<540; i++,j++) { + bfly3(ytmp128+i, + ytmp128+540+i, + ytmp128+1080+i, + y128+i, + y128+540+i, + y128+1080+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1620; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1728[575*2*4]; +static int16_t twb1728[575*2*4]; + +void dft1728(int16_t *x,int16_t *y,unsigned char scale_flag) // 576 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1728[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1728[0]; + simd_q15_t x2128[1728];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1728];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<576; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+576] = x128[j+1]; + x2128[i+1152] = x128[j+2]; + } + + dft576((int16_t *)x2128,(int16_t *)ytmp128,1); + dft576((int16_t *)(x2128+576),(int16_t *)(ytmp128+576),1); + dft576((int16_t *)(x2128+1152),(int16_t *)(ytmp128+1152),1); + + bfly3_tw1(ytmp128,ytmp128+576,ytmp128+1152,y128,y128+576,y128+1152); + + for (i=1,j=0; i<576; i++,j++) { + bfly3(ytmp128+i, + ytmp128+576+i, + ytmp128+1152+i, + y128+i, + y128+576+i, + y128+1152+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1728; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1800[599*2*4]; +static int16_t twb1800[599*2*4]; + +void dft1800(int16_t *x,int16_t *y,unsigned char scale_flag) // 600 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1800[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1800[0]; + simd_q15_t x2128[1800];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1800];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<600; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+600] = x128[j+1]; + x2128[i+1200] = x128[j+2]; + } + + dft600((int16_t *)x2128,(int16_t *)ytmp128,1); + dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1); + dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1); + + bfly3_tw1(ytmp128,ytmp128+600,ytmp128+1200,y128,y128+600,y128+1200); + + for (i=1,j=0; i<600; i++,j++) { + bfly3(ytmp128+i, + ytmp128+600+i, + ytmp128+1200+i, + y128+i, + y128+600+i, + y128+1200+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1800; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1920[479*2*4]; +static int16_t twb1920[479*2*4]; +static int16_t twc1920[479*2*4]; + +void dft1920(int16_t *x,int16_t *y,unsigned char scale_flag) // 480 x 4 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1920[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1920[0]; + simd_q15_t *twc128=(simd_q15_t *)&twc1920[0]; + simd_q15_t x2128[1920];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1920];//=&ytmp128array2[0]; + + + + for (i=0,j=0; i<480; i++,j+=4) { + x2128[i] = x128[j]; + x2128[i+480] = x128[j+1]; + x2128[i+960] = x128[j+2]; + x2128[i+1440] = x128[j+3]; + } + + dft480((int16_t *)x2128,(int16_t *)ytmp128,1); + dft480((int16_t *)(x2128+480),(int16_t *)(ytmp128+480),1); + dft480((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1); + dft480((int16_t *)(x2128+1440),(int16_t *)(ytmp128+1440),1); + + bfly4_tw1(ytmp128,ytmp128+480,ytmp128+960,ytmp128+1440,y128,y128+480,y128+960,y128+1440); + + for (i=1,j=0; i<480; i++,j++) { + bfly4(ytmp128+i, + ytmp128+480+i, + ytmp128+960+i, + ytmp128+1440+i, + y128+i, + y128+480+i, + y128+960+i, + y128+1440+i, + twa128+j, + twb128+j, + twc128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[13]); + for (i=0; i<1920; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1944[647*2*4]; +static int16_t twb1944[647*2*4]; + +void dft1944(int16_t *x,int16_t *y,unsigned char scale_flag) // 648 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1944[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1944[0]; + simd_q15_t x2128[1944];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1944];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<648; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+648] = x128[j+1]; + x2128[i+1296] = x128[j+2]; + } + + dft648((int16_t *)x2128,(int16_t *)ytmp128,1); + dft648((int16_t *)(x2128+648),(int16_t *)(ytmp128+648),1); + dft648((int16_t *)(x2128+1296),(int16_t *)(ytmp128+1296),1); + + bfly3_tw1(ytmp128,ytmp128+648,ytmp128+1296,y128,y128+648,y128+1296); + + for (i=1,j=0; i<648; i++,j++) { + bfly3(ytmp128+i, + ytmp128+648+i, + ytmp128+1296+i, + y128+i, + y128+648+i, + y128+1296+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1944; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2160[719*2*4]; +static int16_t twb2160[719*2*4]; + +void dft2160(int16_t *x,int16_t *y,unsigned char scale_flag) // 720 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2160[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2160[0]; + simd_q15_t x2128[2160];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2160];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<720; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+720] = x128[j+1]; + x2128[i+1440] = x128[j+2]; + } + + dft720((int16_t *)x2128,(int16_t *)ytmp128,1); + dft720((int16_t *)(x2128+720),(int16_t *)(ytmp128+720),1); + dft720((int16_t *)(x2128+1440),(int16_t *)(ytmp128+1440),1); + + bfly3_tw1(ytmp128,ytmp128+720,ytmp128+1440,y128,y128+720,y128+1440); + + for (i=1,j=0; i<720; i++,j++) { + bfly3(ytmp128+i, + ytmp128+720+i, + ytmp128+1440+i, + y128+i, + y128+720+i, + y128+1440+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2160; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2304[767*2*4]; +static int16_t twb2304[767*2*4]; + +void dft2304(int16_t *x,int16_t *y,unsigned char scale_flag) // 768 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2304[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2304[0]; + simd_q15_t x2128[2304];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2304];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<768; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+768] = x128[j+1]; + x2128[i+1536] = x128[j+2]; + } + + dft768((int16_t *)x2128,(int16_t *)ytmp128,1); + dft768((int16_t *)(x2128+768),(int16_t *)(ytmp128+768),1); + dft768((int16_t *)(x2128+1536),(int16_t *)(ytmp128+1536),1); + + bfly3_tw1(ytmp128,ytmp128+768,ytmp128+1536,y128,y128+768,y128+1536); + + for (i=1,j=0; i<768; i++,j++) { + bfly3(ytmp128+i, + ytmp128+768+i, + ytmp128+1536+i, + y128+i, + y128+768+i, + y128+1536+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2304; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2400[599*2*4]; +static int16_t twb2400[599*2*4]; +static int16_t twc2400[599*2*4]; + +void dft2400(int16_t *x,int16_t *y,unsigned char scale_flag) // 600 x 4 +{ + + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2400[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2400[0]; + simd_q15_t *twc128=(simd_q15_t *)&twc2400[0]; + simd_q15_t x2128[2400];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2400];//=&ytmp128array2[0]; + + + + for (i=0,j=0; i<600; i++,j+=4) { + x2128[i] = x128[j]; + x2128[i+600] = x128[j+1]; + x2128[i+1200] = x128[j+2]; + x2128[i+1800] = x128[j+3]; + } + + dft600((int16_t *)x2128,(int16_t *)ytmp128,1); + dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1); + dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1); + dft600((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1); + + bfly4_tw1(ytmp128,ytmp128+600,ytmp128+1200,ytmp128+1800,y128,y128+600,y128+1200,y128+1800); + + for (i=1,j=0; i<600; i++,j++) { + bfly4(ytmp128+i, + ytmp128+600+i, + ytmp128+1200+i, + ytmp128+1800+i, + y128+i, + y128+600+i, + y128+1200+i, + y128+1800+i, + twa128+j, + twb128+j, + twc128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[13]); + for (i=0; i<2400; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2592[863*2*4]; +static int16_t twb2592[863*2*4]; + +void dft2592(int16_t *x,int16_t *y,unsigned char scale_flag) // 864 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2592[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2592[0]; + simd_q15_t x2128[2592];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2592];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<864; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+864] = x128[j+1]; + x2128[i+1728] = x128[j+2]; + } + + dft864((int16_t *)x2128,(int16_t *)ytmp128,1); + dft864((int16_t *)(x2128+864),(int16_t *)(ytmp128+864),1); + dft864((int16_t *)(x2128+1728),(int16_t *)(ytmp128+1728),1); + + bfly3_tw1(ytmp128,ytmp128+864,ytmp128+1728,y128,y128+864,y128+1728); + + for (i=1,j=0; i<864; i++,j++) { + bfly3(ytmp128+i, + ytmp128+864+i, + ytmp128+1728+i, + y128+i, + y128+864+i, + y128+1728+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2592; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2700[899*2*4]; +static int16_t twb2700[899*2*4]; + +void dft2700(int16_t *x,int16_t *y,unsigned char scale_flag) // 900 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2700[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2700[0]; + simd_q15_t x2128[2700];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2700];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<900; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+900] = x128[j+1]; + x2128[i+1800] = x128[j+2]; + } + + dft900((int16_t *)x2128,(int16_t *)ytmp128,1); + dft900((int16_t *)(x2128+900),(int16_t *)(ytmp128+900),1); + dft900((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1); + + bfly3_tw1(ytmp128,ytmp128+900,ytmp128+1800,y128,y128+900,y128+1800); + + for (i=1,j=0; i<900; i++,j++) { + bfly3(ytmp128+i, + ytmp128+900+i, + ytmp128+1800+i, + y128+i, + y128+900+i, + y128+1800+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2700; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2880[959*2*4]; +static int16_t twb2880[959*2*4]; + +void dft2880(int16_t *x,int16_t *y,unsigned char scale_flag) // 960 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2880[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2880[0]; + simd_q15_t x2128[2880];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2880];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<960; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+960] = x128[j+1]; + x2128[i+1920] = x128[j+2]; + } + + dft960((int16_t *)x2128,(int16_t *)ytmp128,1); + dft960((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1); + dft960((int16_t *)(x2128+1920),(int16_t *)(ytmp128+1920),1); + + bfly3_tw1(ytmp128,ytmp128+960,ytmp128+1920,y128,y128+960,y128+1920); + + for (i=1,j=0; i<960; i++,j++) { + bfly3(ytmp128+i, + ytmp128+960+i, + ytmp128+1920+i, + y128+i, + y128+960+i, + y128+1920+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2880; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2916[971*2*4]; +static int16_t twb2916[971*2*4]; + +void dft2916(int16_t *x,int16_t *y,unsigned char scale_flag) // 972 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2916[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2916[0]; + simd_q15_t x2128[2916];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2916];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<972; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+972] = x128[j+1]; + x2128[i+1944] = x128[j+2]; + } + + dft972((int16_t *)x2128,(int16_t *)ytmp128,1); + dft972((int16_t *)(x2128+972),(int16_t *)(ytmp128+972),1); + dft972((int16_t *)(x2128+1944),(int16_t *)(ytmp128+1944),1); + + bfly3_tw1(ytmp128,ytmp128+972,ytmp128+1944,y128,y128+972,y128+1944); + + for (i=1,j=0; i<972; i++,j++) { + bfly3(ytmp128+i, + ytmp128+972+i, + ytmp128+1944+i, + y128+i, + y128+972+i, + y128+1944+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2916; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa3000[599*8]__attribute__((aligned(32))); +static int16_t twb3000[599*8]__attribute__((aligned(32))); +static int16_t twc3000[599*8]__attribute__((aligned(32))); +static int16_t twd3000[599*8]__attribute__((aligned(32))); + +void dft3000(int16_t *x,int16_t *y,unsigned char scale_flag) // 600 * 5 +{ + + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa3000[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb3000[0]; + simd_q15_t *twc128=(simd_q15_t *)&twc3000[0]; + simd_q15_t *twd128=(simd_q15_t *)&twd3000[0]; + simd_q15_t x2128[3000];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[3000];//=&ytmp128array2[0]; + + + + for (i=0,j=0; i<600; i++,j+=5) { + x2128[i] = x128[j]; + x2128[i+600] = x128[j+1]; + x2128[i+1200] = x128[j+2]; + x2128[i+1800] = x128[j+3]; + x2128[i+2400] = x128[j+4]; + } + + dft600((int16_t *)x2128,(int16_t *)ytmp128,1); + dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1); + dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1); + dft600((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1); + dft600((int16_t *)(x2128+2400),(int16_t *)(ytmp128+2400),1); + + bfly5_tw1(ytmp128,ytmp128+600,ytmp128+1200,ytmp128+1800,ytmp128+2400,y128,y128+600,y128+1200,y128+1800,y128+2400); + + for (i=1,j=0; i<600; i++,j++) { + bfly5(ytmp128+i, + ytmp128+600+i, + ytmp128+1200+i, + ytmp128+1800+i, + ytmp128+2400+i, + y128+i, + y128+600+i, + y128+1200+i, + y128+1800+i, + y128+2400+i, + twa128+j, + twb128+j, + twc128+j, + twd128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[15]); + + for (i=0; i<3000; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +} + +static int16_t twa3240[1079*2*4]; +static int16_t twb3240[1079*2*4]; + +void dft3240(int16_t *x,int16_t *y,unsigned char scale_flag) // 1080 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa3240[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb3240[0]; + simd_q15_t x2128[3240];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[3240];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<1080; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+1080] = x128[j+1]; + x2128[i+2160] = x128[j+2]; + } + + dft1080((int16_t *)x2128,(int16_t *)ytmp128,1); + dft1080((int16_t *)(x2128+1080),(int16_t *)(ytmp128+1080),1); + dft1080((int16_t *)(x2128+2160),(int16_t *)(ytmp128+2160),1); + + bfly3_tw1(ytmp128,ytmp128+1080,ytmp128+2160,y128,y128+1080,y128+2160); + + for (i=1,j=0; i<1080; i++,j++) { + bfly3(ytmp128+i, + ytmp128+1080+i, + ytmp128+2160+i, + y128+i, + y128+1080+i, + y128+2160+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<3240; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + void init_rad4(int N,int16_t *tw) { int16_t *twa = tw; @@ -9492,7 +10428,7 @@ void init_rad4_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc) { int i,j; for (i=1;i<(N/4);i++) { - twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); + twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); @@ -9525,7 +10461,7 @@ void init_rad2_rep(int N,int16_t *twa) { int i,j; for (i=1;i<(N/2);i++) { - twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); + twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); for (j=1;j<4;j++) { ((int32_t*)twa)[j]=((int32_t*)twa)[0]; @@ -9551,7 +10487,7 @@ void init_rad3_rep(int N,int16_t *twa,int16_t *twb) { int i,j; for (i=1;i<(N/3);i++) { - twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); + twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); @@ -9569,7 +10505,7 @@ void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) { int i,j; for (i=1;i<(N/5);i++) { - twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); + twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); @@ -9586,7 +10522,7 @@ void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) { twa+=8; twb+=8; twc+=8; - twd+=8; + twd+=8; } } /*----------------------------------------------------------------*/ @@ -9600,7 +10536,7 @@ int dfts_autoinit(void) init_rad2(8192,tw8192); init_rad4(16384,tw16384); init_rad2(32768,tw32768); - + init_rad3(1536,twa1536,twb1536); init_rad3(3072,twa3072,twb3072); init_rad3(6144,twa6144,twb6144); @@ -9645,6 +10581,24 @@ int dfts_autoinit(void) init_rad3_rep(1080,twa1080,twb1080); init_rad4_rep(1152,twa1152,twb1152,twc1152); init_rad4_rep(1200,twa1200,twb1200,twc1200); + init_rad3_rep(1296,twa1296,twb1296); + init_rad3_rep(1440,twa1440,twb1440); + init_rad5_rep(1500,twa1500,twb1500,twc1500,twd1500); + init_rad3_rep(1620,twa1620,twb1620); + init_rad3_rep(1728,twa1728,twb1728); + init_rad3_rep(1800,twa1800,twb1800); + init_rad4_rep(1920,twa1920,twb1920, twc1920); + init_rad3_rep(1944,twa1944,twb1944); + init_rad3_rep(2160,twa2160,twb2160); + init_rad3_rep(2304,twa2304,twb2304); + init_rad4_rep(2400,twa2400,twb2400,twc2400); + init_rad3_rep(2592,twa2592,twb2592); + init_rad3_rep(2700,twa2700,twb2700); + init_rad3_rep(2880,twa2880,twb2880); + init_rad3_rep(2916,twa2916,twb2916); + init_rad5_rep(3000,twa3000,twb3000,twc3000,twd3000); + init_rad3_rep(3240,twa3240,twb3240); + return 0; } diff --git a/openair1/PHY/TOOLS/phy_scope_interface.c b/openair1/PHY/TOOLS/phy_scope_interface.c index af237b2325..7cd68c53d2 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.c +++ b/openair1/PHY/TOOLS/phy_scope_interface.c @@ -35,6 +35,7 @@ #include "phy_scope_interface.h" #define SOFTSCOPE_ENDFUNC_IDX 0 + static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}}; int load_softscope(char *exectype, void *initarg) { diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index adf04d5ea4..8b747d575d 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -29,7 +29,26 @@ * \note * \warning */ +#ifndef __PHY_SCOPE_INTERFACE_H__ +#define __PHY_SCOPE_INTERFACE_H__ +#include +typedef struct { + int *argc; + char **argv; + RU_t *ru; + PHY_VARS_gNB *gNB; +} scopeParms_t; +typedef struct scopeData_s { + int *argc; + char **argv; + RU_t *ru; + PHY_VARS_gNB *gNB; + int32_t * rxdataF; + void (*slotFunc)(int32_t* data, int slot, void * scopeData); +} scopeData_t; + int load_softscope(char *exectype, void *initarg); int end_forms(void) ; +#endif diff --git a/openair1/PHY/TOOLS/signal_energy.c b/openair1/PHY/TOOLS/signal_energy.c index 83bcb7b764..96ee211285 100644 --- a/openair1/PHY/TOOLS/signal_energy.c +++ b/openair1/PHY/TOOLS/signal_energy.c @@ -29,6 +29,7 @@ #define shift 4 //#define shift_DC 0 +#define SHRT_MIN -32768 #if defined(__x86_64__) || defined(__i386__) #ifdef LOCALIZATION @@ -67,52 +68,39 @@ int32_t subcarrier_energy(int32_t *input,uint32_t length, int32_t *subcarrier_en } #endif +//----------------------------------------------------------------- +// Average Power calculation with DC removing +//----------------------------------------------------------------- int32_t signal_energy(int32_t *input,uint32_t length) { + uint32_t i; + int32_t temp; + __m128i in, in_clp, i16_min, coe1; + __m128 num0, num1, num2, num3, recp1; - int32_t i; - int32_t temp,temp2; - register __m64 mm0,mm1,mm2,mm3; - __m64 *in = (__m64 *)input; + //init + num0 = _mm_setzero_ps(); + num1 = _mm_setzero_ps(); + i16_min = _mm_set1_epi16(SHRT_MIN); + coe1 = _mm_set1_epi16(1); + recp1 = _mm_rcp_ps(_mm_cvtepi32_ps(_mm_set1_epi32(length))); - - mm0 = _mm_setzero_si64();//pxor(mm0,mm0); - mm3 = _mm_setzero_si64();//pxor(mm3,mm3); - - for (i=0; i>1; i++) { - - mm1 = in[i]; - mm2 = mm1; - mm1 = _m_pmaddwd(mm1,mm1); - mm1 = _m_psradi(mm1,shift);// shift any 32 bits blocs of the word by the value shift - mm0 = _m_paddd(mm0,mm1);// add the two 64 bits words 4 bytes by 4 bytes - // mm2 = _m_psrawi(mm2,shift_DC); - mm3 = _m_paddw(mm3,mm2);// add the two 64 bits words 2 bytes by 2 bytes + //Acc + for (i = 0; i < (length >> 2); i++) { + in = _mm_loadu_si128((__m128i *)input); + in_clp = _mm_subs_epi16(in, _mm_cmpeq_epi16(in, i16_min));//if in=SHRT_MIN in+1, else in + num0 = _mm_add_ps(num0, _mm_cvtepi32_ps(_mm_madd_epi16(in_clp, in_clp))); + num1 = _mm_add_ps(num1, _mm_cvtepi32_ps(_mm_madd_epi16(in, coe1)));//DC + input += 4; } + //Ave + num2 = _mm_dp_ps(num0, recp1, 0xFF);//AC power + num3 = _mm_dp_ps(num1, recp1, 0xFF);//DC + num3 = _mm_mul_ps(num3, num3); //DC power + //remove DC + temp = _mm_cvtsi128_si32(_mm_cvttps_epi32(_mm_sub_ps(num2, num3))); - mm1 = mm0; - mm0 = _m_psrlqi(mm0,32); - mm0 = _m_paddd(mm0,mm1); - temp = _m_to_int(mm0); - temp/=length; - temp<<=shift; // this is the average of x^2 - - - // now remove the DC component - - - mm2 = _m_psrlqi(mm3,32); - mm2 = _m_paddw(mm2,mm3); - mm2 = _m_pmaddwd(mm2,mm2); - temp2 = _m_to_int(mm2); - temp2/=(length*length); - // temp2<<=(2*shift_DC); - temp -= temp2; - - _mm_empty(); - _m_empty(); - - return((temp>0)?temp:1); + return temp; } int32_t signal_energy_amp_shift(int32_t *input,uint32_t length) @@ -163,61 +151,27 @@ int32_t signal_energy_amp_shift(int32_t *input,uint32_t length) int32_t signal_energy_nodc(int32_t *input,uint32_t length) { - int32_t i; int32_t temp; - register __m64 mm0,mm1;//,mm2,mm3; - __m64 *in = (__m64 *)input; - -#ifdef MAIN - int16_t *printb; -#endif - - mm0 = _mm_setzero_si64();//_pxor(mm0,mm0); - // mm3 = _mm_setzero_si64();//pxor(mm3,mm3); - - for (i=0; i>1; i++) { - - mm1 = in[i]; - mm1 = _m_pmaddwd(mm1,mm1);// SIMD complex multiplication - mm1 = _m_psradi(mm1,shift); - mm0 = _m_paddd(mm0,mm1); - // temp2 = mm0; - // printf("%d %d\n",((int *)&in[i])[0],((int *)&in[i])[1]); - - - // printb = (int16_t *)&mm2; - // printf("mm2 %d : %d %d %d %d\n",i,printb[0],printb[1],printb[2],printb[3]); + __m128i in; + __m128 mm0; +//init + mm0 = _mm_setzero_ps(); +//Acc + for (i=0; i<(length>>2); i++) { + in = _mm_loadu_si128((__m128i *)input); + mm0 = _mm_add_ps(mm0,_mm_cvtepi32_ps(_mm_madd_epi16(in,in))); + input += 4; } + //Ave + temp = (int)((((float*)&mm0)[0] + + ((float*)&mm0)[1] + + ((float*)&mm0)[2] + + ((float*)&mm0)[3])/(float)length); - /* - #ifdef MAIN - printb = (int16_t *)&mm3; - printf("%d %d %d %d\n",printb[0],printb[1],printb[2],printb[3]); - #endif - */ - mm1 = mm0; - - mm0 = _m_psrlqi(mm0,32); - - mm0 = _m_paddd(mm0,mm1); - - temp = _m_to_int(mm0); - - temp/=length; - temp<<=shift; // this is the average of x^2 - -#ifdef MAIN - printf("E x^2 = %d\n",temp); -#endif - _mm_empty(); - _m_empty(); - - - - return((temp>0)?temp:1); + return temp; } #elif defined(__arm__) @@ -310,7 +264,7 @@ double signal_energy_fp(double *s_re[2],double *s_im[2],uint32_t nb_antennas,uin return(V/length/nb_antennas); } -double signal_energy_fp2(struct complex *s,uint32_t length) +double signal_energy_fp2(struct complexd *s,uint32_t length) { int32_t i; @@ -319,7 +273,7 @@ double signal_energy_fp2(struct complex *s,uint32_t length) for (i=0; i %f\n",s[i].x,s[i].y,V); // V= V + (s[i].y*s[i].x) + (s[i].y*s[i].x); - V= V + (s[i].x*s[i].x) + (s[i].y*s[i].y); + V= V + (s[i].r*s[i].r) + (s[i].i*s[i].i); } return(V/length); @@ -364,3 +318,66 @@ main(int argc,char **argv) } #endif +#define SHRT_MIN -32768 +int32_t signal_power(int32_t *input, uint32_t length) +{ + + uint32_t i; + int32_t temp; + + __m128i in, in_clp, i16_min; + __m128 num0, num1; + __m128 recp1; + + //init + num0 = _mm_setzero_ps(); + i16_min = _mm_set1_epi16(SHRT_MIN); + recp1 = _mm_rcp_ps(_mm_cvtepi32_ps(_mm_set1_epi32(length))); + //Acc + for (i = 0; i < (length >> 2); i++) { + in = _mm_loadu_si128((__m128i *)input); + in_clp = _mm_subs_epi16(in, _mm_cmpeq_epi16(in, i16_min));//if in=SHRT_MIN in+1, else in + num0 = _mm_add_ps(num0, _mm_cvtepi32_ps(_mm_madd_epi16(in_clp, in_clp))); + input += 4; + } + //Ave + num1 = _mm_dp_ps(num0, recp1, 0xFF); + temp = _mm_cvtsi128_si32(_mm_cvttps_epi32(num1)); + + return temp; +} + +int32_t interference_power(int32_t *input, uint32_t length) +{ + + uint32_t i; + int32_t temp; + + __m128i in, in_clp, i16_min; + __m128i num0, num1, num2, num3; + __m128 num4, num5, num6; + __m128 recp1; + + //init + i16_min = _mm_set1_epi16(SHRT_MIN); + num5 = _mm_setzero_ps(); + recp1 = _mm_rcp_ps(_mm_cvtepi32_ps(_mm_set1_epi32(length>>2)));// 1/n, n= length/4 + //Acc + for (i = 0; i < (length >> 2); i++) { + in = _mm_loadu_si128((__m128i *)input); + in_clp = _mm_subs_epi16(in, _mm_cmpeq_epi16(in, i16_min)); //if in=SHRT_MIN, in+1, else in + num0 = _mm_cvtepi16_epi32(in_clp); //lower 2 complex [0], [1] + num1 = _mm_cvtepi16_epi32(_mm_shuffle_epi32(in_clp, 0x4E)); //upper 2 complex [2], [3] + num2 = _mm_srai_epi32(_mm_add_epi32(num0, num1), 0x01); //average A=complex( [0] + [2] ) / 2, B=complex( [1] + [3] ) / 2 + num3 = _mm_sub_epi32(num2, _mm_shuffle_epi32(num2, 0x4E)); //complexA-complexB, B-A + num4 = _mm_dp_ps(_mm_cvtepi32_ps(num3), _mm_cvtepi32_ps(num3), 0x3F);//C = num3 lower complex power, C, C, C + num5 = _mm_add_ps(num5, num4); //Acc Cn, Cn, Cn, Cn, + input += 4; + } + //Interference ve + num6 = _mm_mul_ps(num5, recp1); //Cn / n + temp = _mm_cvtsi128_si32(_mm_cvttps_epi32(num6)); + + return temp; +} + diff --git a/openair1/PHY/TOOLS/time_meas.c b/openair1/PHY/TOOLS/time_meas.c index cfa3b93007..1b62687f7e 100644 --- a/openair1/PHY/TOOLS/time_meas.c +++ b/openair1/PHY/TOOLS/time_meas.c @@ -18,17 +18,27 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ - +#define _GNU_SOURCE #include #include "time_meas.h" #include #include - +#include +#include "assertions.h" +#include +#include "common/config/config_userapi.h" +#include // global var for openair performance profiler int opp_enabled = 0; +double cpu_freq_GHz __attribute__ ((aligned(32))); +double cpu_freq_GHz __attribute__ ((aligned(32)))=0.0; +static uint32_t max_cpumeasur; +static time_stats_t **measur_table; +notifiedFIFO_t measur_fifo; double get_cpu_freq_GHz(void) { + if (cpu_freq_GHz <1 ) { time_stats_t ts = {0}; reset_meas(&ts); ts.trials++; @@ -37,6 +47,7 @@ double get_cpu_freq_GHz(void) ts.diff = (rdtsc_oai()-ts.in); cpu_freq_GHz = (double)ts.diff/1000000000; printf("CPU Freq is %f \n", cpu_freq_GHz); + } return cpu_freq_GHz; } @@ -60,8 +71,8 @@ int cpumeas(int action) } void print_meas_now(time_stats_t *ts, - const char *name, - FILE *file_name) + const char *name, + FILE *file_name) { if (opp_enabled) { //static double cpu_freq_GHz = 3.2; @@ -76,9 +87,9 @@ void print_meas_now(time_stats_t *ts, } void print_meas(time_stats_t *ts, - const char *name, - time_stats_t *total_exec_time, - time_stats_t *sf_exec_time) + const char *name, + time_stats_t *total_exec_time, + time_stats_t *sf_exec_time) { if (opp_enabled) { static int first_time = 0; @@ -99,10 +110,11 @@ void print_meas(time_stats_t *ts, if (ts->trials>0) { //printf("%20s: total: %10.3f ms, average: %10.3f us (%10d trials)\n", name, ts->diff/cpu_freq_GHz/1000000.0, ts->diff/ts->trials/cpu_freq_GHz/1000.0, ts->trials); if ((total_exec_time == NULL) || (sf_exec_time== NULL)) { - fprintf(stderr, "%25s: %15.3f us; %15d;\n", + fprintf(stderr, "%25s: %15.3f us; %15d; %15.3f us;\n", name, (ts->diff/ts->trials/cpu_freq_GHz/1000.0), - ts->trials); + ts->trials, + ts->max/cpu_freq_GHz/1000.0); } else { fprintf(stderr, "%25s: %15.3f ms (%5.2f%%); %15.3f us (%5.2f%%); %15d;\n", name, @@ -116,6 +128,49 @@ void print_meas(time_stats_t *ts, } } +int print_meas_log(time_stats_t *ts, + const char *name, + time_stats_t *total_exec_time, + time_stats_t *sf_exec_time, + char *output) +{ + int stroff = 0; + static int first_time = 0; + static double cpu_freq_GHz = 0.0; + + if (cpu_freq_GHz == 0.0) + cpu_freq_GHz = get_cpu_freq_GHz(); + + if (first_time == 0) { + first_time=1; + + if ((total_exec_time == NULL) || (sf_exec_time== NULL)) + stroff += sprintf(output, "%25s %25s %25s %25s %25s %6f\n","Name","Total","Per Trials", "Num Trials","CPU_F_GHz", cpu_freq_GHz); + else + stroff += sprintf(output+stroff, "%25s %25s %25s %20s %15s %6f\n","Name","Total","Average/Frame","Trials", "CPU_F_GHz", cpu_freq_GHz); + } + + if (ts->trials>0) { + //printf("%20s: total: %10.3f ms, average: %10.3f us (%10d trials)\n", name, ts->diff/cpu_freq_GHz/1000000.0, ts->diff/ts->trials/cpu_freq_GHz/1000.0, ts->trials); + if ((total_exec_time == NULL) || (sf_exec_time== NULL)) { + stroff += sprintf(output+stroff, "%25s: %15.3f us; %15d; %15.3f us;\n", + name, + (ts->diff/ts->trials/cpu_freq_GHz/1000.0), + ts->trials, + ts->max/cpu_freq_GHz/1000.0); + } else { + stroff += sprintf(output+stroff, "%25s: %15.3f ms (%5.2f%%); %15.3f us (%5.2f%%); %15d;\n", + name, + (ts->diff/cpu_freq_GHz/1000000.0), + ((ts->diff/cpu_freq_GHz/1000000.0)/(total_exec_time->diff/cpu_freq_GHz/1000000.0))*100, // percentage + (ts->diff/ts->trials/cpu_freq_GHz/1000.0), + ((ts->diff/ts->trials/cpu_freq_GHz/1000.0)/(sf_exec_time->diff/sf_exec_time->trials/cpu_freq_GHz/1000.0))*100, // percentage + ts->trials); + } + } + return stroff; +} + double get_time_meas_us(time_stats_t *ts) { static double cpu_freq_GHz = 0.0; @@ -128,3 +183,110 @@ double get_time_meas_us(time_stats_t *ts) return 0; } + +/* function for the asynchronous measurment module: cpu stat are sent to a dedicated thread + * which is in charge of computing the cpu time spent in a given function/algorithm... + */ + +time_stats_t *register_meas(char *name) +{ + for (int i=0; imeas_name = strdup(name); + measur_table[i]->meas_index = i; + measur_table[i]->tpoolmsg =newNotifiedFIFO_elt(sizeof(time_stats_msg_t),0,NULL,NULL); + measur_table[i]->tstatptr = (time_stats_msg_t *)NotifiedFifoData(measur_table[i]->tpoolmsg); + return measur_table[i]; + } + } + return NULL; +} + +void free_measurtbl(void) { + for (int i=0; imeas_name); + delNotifiedFIFO_elt(measur_table[i]->tpoolmsg); + free(measur_table[i]); + } + } + //free the fifo... +} + +void run_cpumeasur(void) { + struct sched_param schedp; + pthread_setname_np(pthread_self(), "measur"); + schedp.sched_priority=0; + int rt=pthread_setschedparam(pthread_self(), SCHED_IDLE, &schedp); + AssertFatal(rt==0, "couldn't set measur thread priority: %s\n",strerror(errno)); + initNotifiedFIFO(&measur_fifo); + while(1) { + notifiedFIFO_elt_t *msg = pullNotifiedFIFO(&measur_fifo); + time_stats_msg_t *tsm = (time_stats_msg_t *)NotifiedFifoData(msg); + switch(tsm->msgid) { + case TIMESTAT_MSGID_START: + measur_table[tsm->timestat_id]->in=tsm->ts; + (measur_table[tsm->timestat_id]->trials)++; + break; + case TIMESTAT_MSGID_STOP: + /// process duration is the difference between two clock points + measur_table[tsm->timestat_id]->p_time = (tsm->ts - measur_table[tsm->timestat_id]->in); + measur_table[tsm->timestat_id]->diff += measur_table[tsm->timestat_id]->p_time; + if ( measur_table[tsm->timestat_id]->p_time > measur_table[tsm->timestat_id]->max ) + measur_table[tsm->timestat_id]->max = measur_table[tsm->timestat_id]->p_time; + break; + case TIMESTAT_MSGID_DISPLAY: + { + char aline[256]; + int start, stop; + if (tsm->displayFunc != NULL) { + if(tsm->timestat_id >= 0) { + start=tsm->timestat_id ; + stop=start+1; + } + else { + start=0; + stop=max_cpumeasur ; + } + for (int i=start ; imeas_name, measur_table[i]->trials==0?0:( (measur_table[i]->trials/measur_table[i]->diff )/ cpu_freq_GHz /1000 )); + tsm->displayFunc(aline); + } + } + } + } + break; + case TIMESTAT_MSGID_END: + free_measurtbl(); + delNotifiedFIFO_elt(msg); + pthread_exit(NULL); + break; + default: + break; + } + delNotifiedFIFO_elt(msg); + } +} + + +void init_meas(void) { + pthread_t thid; + paramdef_t cpumeasur_params[] = CPUMEASUR_PARAMS_DESC; + int numparams=sizeof(cpumeasur_params)/sizeof(paramdef_t); + int rt = config_get( cpumeasur_params,numparams,CPUMEASUR_SECTION); + AssertFatal(rt >= 0, "cpumeasur configuration couldn't be performed"); + measur_table=calloc(max_cpumeasur,sizeof( time_stats_t *)); + AssertFatal(measur_table!=NULL, "couldn't allocate %u cpu measurements entries\n",max_cpumeasur); + rt=pthread_create(&thid,NULL, (void *(*)(void *))run_cpumeasur, NULL); + AssertFatal(rt==0, "couldn't create cpu measurment thread: %s\n",strerror(errno)); +} + +void end_meas(void) { + notifiedFIFO_elt_t *nfe = newNotifiedFIFO_elt(sizeof(time_stats_msg_t),0,NULL,NULL); + time_stats_msg_t *msg = (time_stats_msg_t *)NotifiedFifoData(nfe); + msg->msgid = TIMESTAT_MSGID_END ; + pushNotifiedFIFO(&measur_fifo, nfe); +} diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h index 5b8ea6e75a..bb2bb3d276 100644 --- a/openair1/PHY/TOOLS/time_meas.h +++ b/openair1/PHY/TOOLS/time_meas.h @@ -29,39 +29,62 @@ #include #include #include -//#include -//#include +#include +#include +#include "common/utils/threadPool/thread-pool.h" // global var to enable openair performance profiler extern int opp_enabled; -double cpu_freq_GHz __attribute__ ((aligned(32)));; - +extern double cpu_freq_GHz __attribute__ ((aligned(32)));; +// structure to store data to compute cpu measurment #if defined(__x86_64__) || defined(__i386__) -typedef struct { - long long in; - long long diff; - long long p_time; /*!< \brief absolute process duration */ - long long diff_square; /*!< \brief process duration square */ - long long max; - int trials; - int meas_flag; -} time_stats_t; + #define OAI_CPUTIME_TYPE long long #elif defined(__arm__) -typedef struct { - uint32_t in; - uint32_t diff; - uint32_t p_time; /*!< \brief absolute process duration */ - uint32_t diff_square; /*!< \brief process duration square */ - uint32_t max; - int trials; -} time_stats_t; + #define OAI_CPUTIME_TYPE uint32_t +#else + #error "building on unsupported CPU architecture" #endif +#define TIMESTAT_MSGID_START 0 /*!< \brief send time at measure starting point */ +#define TIMESTAT_MSGID_STOP 1 /*!< \brief send time at measure end point */ +#define TIMESTAT_MSGID_ENABLE 2 /*!< \brief enable measure point */ +#define TIMESTAT_MSGID_DISABLE 3 /*!< \brief disable measure point */ +#define TIMESTAT_MSGID_DISPLAY 10 /*!< \brief display measure */ +#define TIMESTAT_MSGID_END 11 /*!< \brief stops the measure threads and free assocated resources */ +typedef void(*meas_printfunc_t)(const char* format, ...); +typedef struct { + int msgid; /*!< \brief message id, as defined by TIMESTAT_MSGID_X macros */ + int timestat_id; /*!< \brief points to the time_stats_t entry in cpumeas table */ + OAI_CPUTIME_TYPE ts; /*!< \brief time stamp */ + meas_printfunc_t displayFunc; /*!< \brief function to call when DISPLAY message is received*/ +} time_stats_msg_t; + + +typedef struct { + OAI_CPUTIME_TYPE in; /*!< \brief time at measure starting point */ + OAI_CPUTIME_TYPE diff; /*!< \brief average difference between time at starting point and time at endpoint*/ + OAI_CPUTIME_TYPE p_time; /*!< \brief absolute process duration */ + OAI_CPUTIME_TYPE diff_square; /*!< \brief process duration square */ + OAI_CPUTIME_TYPE max; /*!< \brief maximum difference between time at starting point and time at endpoint*/ + int trials; /*!< \brief number of start point - end point iterations */ + int meas_flag; /*!< \brief 1: stop_meas not called (consecutive calls of start_meas) */ + char *meas_name; /*!< \brief name to use when printing the measure (not used for PHY simulators)*/ + int meas_index; /*!< \brief index of this measure in the measure array (not used for PHY simulators)*/ + int meas_enabled; /*!< \brief per measure enablement flag. send_meas tests this flag, unused today in start_meas and stop_meas*/ + notifiedFIFO_elt_t *tpoolmsg; /*!< \brief message pushed to the cpu measurment queue to report a measure START or STOP */ + time_stats_msg_t *tstatptr; /*!< \brief pointer to the time_stats_msg_t data in the tpoolmsg, stored here for perf considerations*/ +} time_stats_t; +#define MEASURE_ENABLED(X) (X->meas_enabled) + + + + static inline void start_meas(time_stats_t *ts) __attribute__((always_inline)); static inline void stop_meas(time_stats_t *ts) __attribute__((always_inline)); void print_meas_now(time_stats_t *ts, const char *name, FILE *file_name); void print_meas(time_stats_t *ts, const char *name, time_stats_t *total_exec_time, time_stats_t *sf_exec_time); +int print_meas_log(time_stats_t *ts, const char *name, time_stats_t *total_exec_time, time_stats_t *sf_exec_time, char *output); double get_time_meas_us(time_stats_t *ts); double get_cpu_freq_GHz(void); @@ -137,4 +160,26 @@ static inline void copy_meas(time_stats_t *dst_ts,time_stats_t *src_ts) { dst_ts->max=src_ts->max; } } + +extern notifiedFIFO_t measur_fifo; +#define CPUMEASUR_SECTION "cpumeasur" + +#define CPUMEASUR_PARAMS_DESC { \ + {"max_cpumeasur", "Max number of cpu measur entries", 0, uptr:&max_cpumeasur, defintval:100, TYPE_UINT, 0},\ + } + + void init_meas(void); + time_stats_t *register_meas(char *name); + #define START_MEAS(X) send_meas(X, TIMESTAT_MSGID_START) + #define STOP_MEAS(X) send_meas(X, TIMESTAT_MSGID_STOP) + static inline void send_meas(time_stats_t *ts, int msgid) { + if (MEASURE_ENABLED(ts) ) { + ts->tstatptr->timestat_id=ts->meas_index; + ts->tstatptr->msgid = msgid ; + ts->tstatptr->ts = rdtsc_oai(); + pushNotifiedFIFO(&measur_fifo, ts->tpoolmsg); + } + } + void end_meas(void); + #endif diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 9c9b8aa821..966e93440e 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -39,9 +39,9 @@ extern "C" { #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) -struct complex { - double x; - double y; +struct complexd { + double r; + double i; }; struct complexf { @@ -226,9 +226,26 @@ void dft1024(int16_t *x,int16_t *y,uint8_t scale_flag); void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag); void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag); void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1296(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1440(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1500(int16_t *x,int16_t *y,uint8_t scale_flag); void dft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft1620(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1728(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1800(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1920(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1944(int16_t *x,int16_t *y,uint8_t scale_flag); void dft2048(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2160(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2304(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2400(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2592(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2700(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2880(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2916(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft3000(int16_t *x,int16_t *y,uint8_t scale_flag); void dft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft3240(int16_t *x,int16_t *y,uint8_t scale_flag); void dft4096(int16_t *x,int16_t *y,uint8_t scale_flag); void dft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag); void dft8192(int16_t *x,int16_t *y,uint8_t scale_flag); @@ -283,21 +300,25 @@ typedef enum DFT_size_idx { DFT_108, DFT_120, DFT_128, DFT_144, DFT_180, DFT_192, DFT_216, DFT_240, DFT_256, DFT_288, DFT_300, DFT_324, DFT_360, DFT_384, DFT_432, DFT_480, DFT_512, DFT_540, DFT_576, DFT_600, DFT_648, DFT_720, DFT_768, DFT_864, - DFT_900, DFT_960, DFT_972, DFT_1024, DFT_1080, DFT_1152, DFT_1200, DFT_1536, - DFT_2048, DFT_3072, DFT_4096, DFT_6144, DFT_8192, DFT_9216, DFT_12288, DFT_18432, - DFT_24576, DFT_36864, DFT_49152, DFT_73728, DFT_98304, + DFT_900, DFT_960, DFT_972, DFT_1024, DFT_1080, DFT_1152, DFT_1200, DFT_1296, + DFT_1440, DFT_1500, DFT_1536, DFT_1620, DFT_1728, DFT_1800, DFT_1920, DFT_1944, + DFT_2048, DFT_2160, DFT_2304, DFT_2400, DFT_2592, DFT_2700, DFT_2880, DFT_2916, + DFT_3000, DFT_3072, DFT_3240, DFT_4096, DFT_6144, DFT_8192, DFT_9216, DFT_12288, + DFT_18432, DFT_24576, DFT_36864, DFT_49152, DFT_73728, DFT_98304, DFT_SIZE_IDXTABLESIZE } dft_size_idx_t; #ifdef OAIDFTS_MAIN adftfunc_t dft_ftab[]={ dft12, dft24, dft36, dft48, dft60, dft72, dft96, - dft108, dft120, dft128, dft144, dft180, dft192, dft216, dft240, + dft108, dft120, dft128, dft144, dft180, dft192, dft216, dft240, dft256, dft288, dft300, dft324, dft360, dft384, dft432, dft480, dft512, dft540, dft576, dft600, dft648, dft720, dft768, dft864, - dft900, dft960, dft972, dft1024, dft1080, dft1152, dft1200, dft1536, - dft2048, dft3072, dft4096, dft6144, dft8192, dft9216, dft12288, dft18432, - dft24576, dft36864, dft49152, dft73728, dft98304 + dft900, dft960, dft972, dft1024, dft1080, dft1152, dft1200, dft1296, + dft1440, dft1500, dft1536, dft1620, dft1728, dft1800, dft1920, dft1944, + dft2048, dft2160, dft2304, dft2400, dft2592, dft2700, dft2880, dft2916, + dft3000, dft3072, dft3240, dft4096, dft6144, dft8192, dft9216, dft12288, + dft18432, dft24576, dft36864, dft49152, dft73728, dft98304 }; #endif @@ -309,9 +330,9 @@ typedef enum idft_size_idx { } idft_size_idx_t; #ifdef OAIDFTS_MAIN aidftfunc_t idft_ftab[]={ - idft128, idft256, idft512, idft1024, idft1536, idft2048, idft3072, idft4096, - idft6144, idft8192, idft9216, idft12288, idft18432, idft24576, idft36864, idft49152, - idft73728, idft98304 + idft128, idft256, idft512, idft1024, idft1536, idft2048, idft3072, idft4096, + idft6144, idft8192, idft9216, idft12288, idft18432, idft24576, idft36864, idft49152, + idft73728, idft98304 }; #endif @@ -431,6 +452,9 @@ int32_t subcarrier_energy(int32_t *,uint32_t, int32_t* subcarrier_energy, uint16 */ int32_t signal_energy_nodc(int32_t *,uint32_t); +int32_t signal_power(int32_t *,uint32_t); +int32_t interference_power(int32_t *,uint32_t); + /*!\fn double signal_energy_fp(double *s_re[2], double *s_im[2],uint32_t, uint32_t,uint32_t); \brief Computes the signal energy per subcarrier */ @@ -439,7 +463,7 @@ double signal_energy_fp(double *s_re[2], double *s_im[2], uint32_t nb_antennas, /*!\fn double signal_energy_fp2(struct complex *, uint32_t); \brief Computes the signal energy per subcarrier */ -double signal_energy_fp2(struct complex *s, uint32_t length); +double signal_energy_fp2(struct complexd *s, uint32_t length); int32_t iSqrt(int32_t value); @@ -469,6 +493,7 @@ uint8_t dB_fixed64(uint64_t x); int8_t dB_fixed2(uint32_t x,uint32_t y); int16_t dB_fixed_times10(uint32_t x); +int16_t dB_fixed_x10(uint32_t x); int32_t phy_phase_compensation_top(uint32_t pilot_type, uint32_t initial_pilot, diff --git a/openair1/PHY/defs_L1_NB_IoT.h b/openair1/PHY/defs_L1_NB_IoT.h index 1f8c0b8eee..a4552c8c27 100644 --- a/openair1/PHY/defs_L1_NB_IoT.h +++ b/openair1/PHY/defs_L1_NB_IoT.h @@ -32,7 +32,9 @@ #ifndef __PHY_DEFS_NB_IOT__H__ #define __PHY_DEFS_NB_IOT__H__ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include #include @@ -46,7 +48,6 @@ #ifdef MEX #define msg mexPrintf #else - #ifdef OPENAIR2 #if ENABLE_RAL #include "collection/hashtable/hashtable.h" #include "COMMON/ral_messages_types.h" @@ -54,9 +55,6 @@ #endif #include "common/utils/LOG/log.h" #define msg(aRGS...) LOG_D(PHY, ##aRGS) - #else - #define msg printf - #endif #endif //use msg in the real-time thread context #define msg_nrt printf @@ -194,19 +192,6 @@ typedef struct { NB_IoT_UE_DLSCH_t *dlsch_rn_MCH[10]; } PHY_VARS_RN_NB_IoT; -/* -#ifdef OCP_FRAMEWORK -#include -#else -//typedef enum {normal_txrx=0,rx_calib_ue=1,rx_calib_ue_med=2,rx_calib_ue_byp=3,debug_prach=4,no_L2_connect=5,calib_prach_tx=6,rx_dump_frame=7,loop_through_memory=8} runmode_t; -*/ -// enum transmission_access_mode { -// NO_ACCESS=0, -// POSTPONED_ACCESS, -// CANCELED_ACCESS, -// UNKNOWN_ACCESS, -// SCHEDULED_ACCESS, -// CBA_ACCESS}; typedef enum { eNodeB_3GPP_NB_IoT=0, // classical eNodeB function diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index b8083b5ecf..76dd92ef5d 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -92,17 +92,17 @@ typedef enum { typedef struct { - /// \brief Holds the transmit data in the frequency domain. + /// \brief Holds the transmit data in the frequency domain (1 frame). /// - first index: rx antenna [0..nb_antennas_rx[ - /// - second index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[ + /// - second index: ? [0..samples_per_frame[ int32_t **txdata; - /// \brief holds the transmit data after beamforming in the frequency domain. + /// \brief holds the transmit data after beamforming in the frequency domain (1 slot). /// - first index: tx antenna [0..nb_antennas_tx[ - /// - second index: sample [0..] + /// - second index: sample [0..samples_per_slot_woCP] int32_t **txdataF_BF; - /// \brief holds the transmit data before beamforming in the frequency domain. - /// - first index: tx antenna [0..nb_antennas_tx[ - /// - second index: sample [0..] + /// \brief holds the transmit data before beamforming in the frequency domain (1 frame). + /// - first index: tx antenna [0..nb_antenna_ports[ + /// - second index: sample [0..samples_per_frame_woCP] int32_t **txdataF; /// \brief holds the transmit data before beamforming for epdcch/mpdcch /// - first index : tx antenna [0..nb_epdcch_antenna_ports[ @@ -128,6 +128,10 @@ typedef struct { /// - second index: tx antenna [0..nb_antennas_tx[ /// - third index: frequency [0..] int32_t **tdd_calib_coeffs; + /// \brief Anaglogue beam ID for each OFDM symbol (used when beamforming not done in RU) + /// - first index: antenna port + /// - second index: beam_id [0.. symbols_per_frame[ + uint8_t **beam_id; } RU_COMMON; @@ -191,9 +195,11 @@ typedef struct { int fmt; int numRA; int prachStartSymbol; + int num_prach_ocas; } RU_PRACH_list_t; #define NUMBER_OF_NR_RU_PRACH_MAX 8 +#define NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX 12 typedef struct RU_proc_t_s { /// Pointer to associated RU descriptor @@ -430,6 +436,14 @@ typedef enum { typedef struct RU_t_s { /// index of this ru uint32_t idx; + /// pointer to first RU + struct RU_t_s *ru0; + /// pointer to ru_mask + uint64_t *ru_mask; + /// pointer to ru_mutex + pthread_mutex_t *ru_mutex; + /// pointer to ru_cond + pthread_cond_t *ru_cond; /// Pointer to configuration file char *rf_config_file; /// southbound interface @@ -440,6 +454,12 @@ typedef struct RU_t_s { node_function_t function; /// Ethernet parameters for fronthaul interface eth_params_t eth_params; + /// flag to indicate RF emulation mode + int emulate_rf; + /// numerology index + int numerology; + /// flag to indicate basicsim operation + int basicsim; /// flag to indicate the RU is in sync with a master reference int in_synch; /// timing offset @@ -594,8 +614,8 @@ typedef struct RU_t_s { RU_PRACH_list_t prach_list[NUMBER_OF_NR_RU_PRACH_MAX]; /// mutex for prach_list access pthread_mutex_t prach_list_mutex; - /// received frequency-domain signal for PRACH (IF4p5 RRU) - int16_t **prach_rxsigF; + /// received frequency-domain signal for PRACH (IF4p5 RRU) + int16_t **prach_rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX]; /// received frequency-domain signal for PRACH BR (IF4p5 RRU) int16_t **prach_rxsigF_br[4]; /// sequence number for IF5 @@ -622,6 +642,8 @@ typedef struct RU_t_s { int wakeup_L1_sleep_cnt_max; /// DL IF frequency in Hz uint64_t if_frequency; + /// UL IF frequency offset to DL IF frequency in Hz + int if_freq_offset; } RU_t; @@ -737,4 +759,11 @@ typedef struct RRU_config_s { MBSFN_config_t MBSFN_config[8]; } RRU_config_t; +typedef struct processingData_RU { + int frame_tx; + int slot_tx; + int next_slot; + openair0_timestamp timestamp_tx; + RU_t *ru; +} processingData_RU_t; #endif //__PHY_DEFS_RU__H__ diff --git a/openair1/PHY/defs_UE.h b/openair1/PHY/defs_UE.h index 9163fc13b6..2d2697a4b7 100644 --- a/openair1/PHY/defs_UE.h +++ b/openair1/PHY/defs_UE.h @@ -87,7 +87,6 @@ #define LOG_W(x, ...) mexPrintf(__VA_ARGS__) #define LOG_M(x, ...) mexPrintf(__VA_ARGS__) #else - #ifdef OPENAIR2 #if ENABLE_RAL #include "collection/hashtable/hashtable.h" #include "COMMON/ral_messages_types.h" @@ -95,9 +94,6 @@ #endif #include "common/utils/LOG/log.h" #define msg(aRGS...) LOG_D(PHY, ##aRGS) - #else - #define msg printf - #endif #endif @@ -452,55 +448,6 @@ typedef struct { uint32_t llr_length[14]; } LTE_UE_PDSCH; -typedef struct { - /// \brief Received frequency-domain signal after extraction. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - int32_t **rxdataF_ext; - /// \brief Received frequency-domain signal after extraction and channel compensation. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **rxdataF_comp; - /// \brief Downlink channel estimates extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - int32_t **dl_ch_estimates_ext; - /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_rho_ext; - /// \brief Downlink PMIs extracted in PRBS and grouped in subbands. - /// - first index: ressource block [0..N_RB_DL[ - uint8_t *pmi_ext; - /// \brief Magnitude of Downlink Channel (16QAM level/First 64QAM level). - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_mag; - /// \brief Magnitude of Downlink Channel (2nd 64QAM level). - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_magb; - /// \brief Cross-correlation of two eNB signals. - /// - first index: rx antenna [0..nb_antennas_rx[ - /// - second index: ? [0..] - double **rho; - /// never used... always send dl_ch_rho_ext instead... - double **rho_i; - /// \brief Pointers to llr vectors (2 TBs). - /// - first index: ? [0..1] (hard coded) - /// - second index: ? [0..1179743] (hard coded) - int16_t *llr[2]; - /// \f$\log_2(\max|H_i|^2)\f$ - uint8_t log2_maxh; - /// \brief Pointers to llr vectors (128-bit alignment). - /// - first index: ? [0..0] (hard coded) - /// - second index: ? [0..] - int16_t **llr128; - //uint32_t *rb_alloc; - //uint8_t Qm[2]; - //MIMO_mode_t mimo_mode; -} LTE_UE_PDSCH_FLP; - typedef struct { /// \brief Pointers to extracted PDCCH symbols in frequency-domain. /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx @@ -667,7 +614,6 @@ typedef struct { uint8_t current_thread_id[10]; LTE_UE_PDSCH *pdsch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX+1]; // two RxTx Threads - LTE_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1]; diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h index 75b2d54dc6..a371b2334b 100644 --- a/openair1/PHY/defs_common.h +++ b/openair1/PHY/defs_common.h @@ -867,8 +867,10 @@ typedef enum { NOT_SYNCHED=0, PRACH=1, RA_RESPONSE=2, - PUSCH=3, - RESYNCH=4 + RA_WAIT_CR=3, + PUSCH=4, + RESYNCH=5, + NUM_UE_MODE=6 } UE_MODE_t; #define FOREACH_PARALLEL(GEN) \ @@ -943,6 +945,23 @@ extern int sync_var; #define DECODE_NUM_FPTR 13 +// Mask for identifying subframe for MBMS +#define MBSFN_TDD_SF3 0x80// for TDD +#define MBSFN_TDD_SF4 0x40 +#define MBSFN_TDD_SF7 0x20 +#define MBSFN_TDD_SF8 0x10 +#define MBSFN_TDD_SF9 0x08 + + + +#define MBSFN_FDD_SF1 0x80// for FDD +#define MBSFN_FDD_SF2 0x40 +#define MBSFN_FDD_SF3 0x20 +#define MBSFN_FDD_SF6 0x10 +#define MBSFN_FDD_SF7 0x08 +#define MBSFN_FDD_SF8 0x04 + + typedef uint8_t(decoder_if_t)(int16_t *y, int16_t *y2, uint8_t *decoded_bytes, @@ -1094,5 +1113,4 @@ static inline int release_thread(pthread_mutex_t *mutex, return(0); } - #endif // __PHY_DEFS_COMMON_H__ diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 557b8bfc30..030d50bc04 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -164,8 +164,10 @@ typedef struct { /// - first index: rx antenna id [0..nb_antennas_rx[ /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **ul_ch_magb; - /// measured RX power based on DRS - int ulsch_power[2]; + /// measured RX power based on DMRS + int ulsch_power[4]; + /// measured RX power of noise + int ulsch_noise_power[4]; /// \brief llr values. /// - first index: ? [0..1179743] (hard coded) int16_t *llr; @@ -215,6 +217,58 @@ typedef struct { int ret; } td_params; +/// Context data structure for RX/TX portion of subframe processing +typedef struct { + /// Component Carrier index + uint8_t CC_id; + /// timestamp transmitted to HW + openair0_timestamp timestamp_tx; + openair0_timestamp timestamp_rx; + /// subframe to act upon for transmission + int subframe_tx; + /// subframe to act upon for reception + int subframe_rx; + /// frame to act upon for transmission + int frame_tx; + /// frame to act upon for reception + int frame_rx; + int frame_prach; + int subframe_prach; + int frame_prach_br; + int subframe_prach_br; + /// \brief Instance count for RXn-TXnp4 processing thread. + /// \internal This variable is protected by \ref mutex_rxtx. + int instance_cnt; + /// pthread structure for RXn-TXnp4 processing thread + pthread_t pthread; + /// pthread attributes for RXn-TXnp4 processing thread + pthread_attr_t attr; + /// condition variable for tx processing thread + pthread_cond_t cond; + /// mutex for RXn-TXnp4 processing thread + pthread_mutex_t mutex; + /// scheduling parameters for RXn-TXnp4 thread + struct sched_param sched_param_rxtx; + + /// \internal This variable is protected by \ref mutex_RUs. + int instance_cnt_RUs; + /// condition variable for tx processing thread + pthread_cond_t cond_RUs; + /// mutex for RXn-TXnp4 processing thread + pthread_mutex_t mutex_RUs; + tpool_t *threadPool; + int nbEncode; + int nbDecode; + notifiedFIFO_t *respEncode; + notifiedFIFO_t *respDecode; + pthread_mutex_t mutex_emulateRF; + int instance_cnt_emulateRF; + pthread_t pthread_emulateRF; + pthread_attr_t attr_emulateRF; + pthread_cond_t cond_emulateRF; + int first_rx; +} L1_rxtx_proc_t; + typedef struct { struct PHY_VARS_eNB_s *eNB; LTE_eNB_DLSCH_t *dlsch; @@ -360,8 +414,11 @@ typedef struct L1_proc_t_s { L1_rxtx_proc_t L1_proc,L1_proc_tx; /// stats thread pthread descriptor pthread_t process_stats_thread; + /// L1 stats pthread descriptor + pthread_t L1_stats_thread; /// for waking up tx procedure RU_proc_t *ru_proc; + struct PHY_VARS_eNB_s *eNB; } L1_proc_t; @@ -389,36 +446,77 @@ typedef struct { short n0_subband_power_tot_dB[100]; //! estimated avg noise power per RB (dBm) short n0_subband_power_tot_dBm[100]; + //! etimated avg noise power over all RB (dB) + short n0_subband_power_avg_dB; // eNB measurements (per user) //! estimated received spatial signal power (linear) - unsigned int rx_spatial_power[NUMBER_OF_UE_MAX][2][2]; + unsigned int rx_spatial_power[NUMBER_OF_SRS_MAX][2][2]; //! estimated received spatial signal power (dB) - unsigned short rx_spatial_power_dB[NUMBER_OF_UE_MAX][2][2]; + unsigned short rx_spatial_power_dB[NUMBER_OF_SRS_MAX][2][2]; //! estimated rssi (dBm) - short rx_rssi_dBm[NUMBER_OF_UE_MAX]; + short rx_rssi_dBm[NUMBER_OF_SRS_MAX]; //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation) - int rx_correlation[NUMBER_OF_UE_MAX][2]; + int rx_correlation[NUMBER_OF_SRS_MAX][2]; //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation) - int rx_correlation_dB[NUMBER_OF_UE_MAX][2]; + int rx_correlation_dB[NUMBER_OF_SRS_MAX][2]; /// Wideband CQI (= SINR) - int wideband_cqi[NUMBER_OF_UE_MAX][MAX_NUM_RU_PER_eNB]; + int wideband_cqi[NUMBER_OF_SRS_MAX][MAX_NUM_RU_PER_eNB]; /// Wideband CQI in dB (= SINR dB) - int wideband_cqi_dB[NUMBER_OF_UE_MAX][MAX_NUM_RU_PER_eNB]; + int wideband_cqi_dB[NUMBER_OF_SRS_MAX][MAX_NUM_RU_PER_eNB]; /// Wideband CQI (sum of all RX antennas, in dB) - char wideband_cqi_tot[NUMBER_OF_UE_MAX]; + char wideband_cqi_tot[NUMBER_OF_SRS_MAX]; /// Subband CQI per RX antenna and RB (= SINR) - int subband_cqi[NUMBER_OF_UE_MAX][MAX_NUM_RU_PER_eNB][100]; + int subband_cqi[NUMBER_OF_SRS_MAX][MAX_NUM_RU_PER_eNB][100]; /// Total Subband CQI and RB (= SINR) int subband_cqi_tot[NUMBER_OF_UE_MAX][100]; /// Subband CQI in dB and RB (= SINR dB) - int subband_cqi_dB[NUMBER_OF_UE_MAX][MAX_NUM_RU_PER_eNB][100]; + int subband_cqi_dB[NUMBER_OF_SRS_MAX][MAX_NUM_RU_PER_eNB][100]; /// Total Subband CQI and RB - int subband_cqi_tot_dB[NUMBER_OF_UE_MAX][100]; + int subband_cqi_tot_dB[NUMBER_OF_SRS_MAX][100]; /// PRACH background noise level int prach_I0; + /// PUCCH background noise level + int n0_pucch_dB; } PHY_MEASUREMENTS_eNB; +typedef struct { + uint16_t rnti; + int frame; + int round_trials[8]; + int total_bytes_tx; + int total_bytes_rx; + int current_G; + int current_TBS; + int current_Qm; + int current_mcs; + int current_RI; + int timing_offset; + int ulsch_power[4]; + int ulsch_noise_power[4]; +} eNB_SCH_STATS_t; + +typedef struct { + uint16_t rnti; + int frame; + int pucch1_trials; + int pucch1_thres; + int current_pucch1_stat_pos; + int current_pucch1_stat_neg; + int pucch1_positive_SR; + int pucch1_low_stat[4]; + int pucch1_high_stat[4]; + int pucch1_phase; + int pucch1a_trials; + int current_pucch1a_stat_re; + int current_pucch1a_stat_im; + int pucch1ab_DTX; + int pucch1b_trials; + int current_pucch1b_stat_re; + int current_pucch1b_stat_im; + int pucch3_trials; + int current_pucch3_stat; +} eNB_UCI_STATS_t; /// Top-level PHY Data Structure for eNB typedef struct PHY_VARS_eNB_s { @@ -466,13 +564,13 @@ typedef struct PHY_VARS_eNB_s { LTE_eNB_MPDCCH mpdcch_vars[2]; LTE_eNB_PRACH prach_vars_br; LTE_eNB_COMMON common_vars; - LTE_eNB_UCI uci_vars[NUMBER_OF_UCI_VARS_MAX]; - LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX]; + LTE_eNB_UCI uci_vars[NUMBER_OF_UCI_MAX]; + LTE_eNB_SRS srs_vars[NUMBER_OF_SRS_MAX]; LTE_eNB_PBCH pbch; - LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX]; + LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_ULSCH_MAX]; LTE_eNB_PRACH prach_vars; - LTE_eNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams - LTE_eNB_ULSCH_t *ulsch[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA + LTE_eNB_DLSCH_t *dlsch[NUMBER_OF_DLSCH_MAX][2]; // Num active DLSCH contexts times two spatial streams + LTE_eNB_ULSCH_t *ulsch[NUMBER_OF_ULSCH_MAX]; // Num active ULSCH contexts LTE_eNB_DLSCH_t *dlsch_SI,*dlsch_ra,*dlsch_p; LTE_eNB_DLSCH_t *dlsch_MCH; LTE_eNB_DLSCH_t *dlsch_PCH; @@ -483,7 +581,7 @@ typedef struct PHY_VARS_eNB_s { uint32_t lte_gold_table[20][2][14]; /// UE-specific reference symbols (p=5), TM 7 - uint32_t lte_gold_uespec_port5_table[NUMBER_OF_UE_MAX][20][38]; + uint32_t lte_gold_uespec_port5_table[NUMBER_OF_DLSCH_MAX][20][38]; /// UE-specific reference symbols (p=7...14), TM 8/9/10 uint32_t lte_gold_uespec_table[2][20][2][21]; @@ -515,6 +613,9 @@ typedef struct PHY_VARS_eNB_s { uint8_t pbch_pdu[4]; //PBCH_PDU_SIZE char eNB_generate_rar; + /// indicator that eNB signal generation uses DTX (i.e. signal is cleared in each subframe + int use_DTX; + int32_t **subframe_mask; /// Indicator set to 0 after first SR uint8_t first_sr[NUMBER_OF_UE_MAX]; @@ -586,7 +687,12 @@ typedef struct PHY_VARS_eNB_s { /// Information regarding TM5 MU_MIMO_mode mu_mimo_mode[NUMBER_OF_UE_MAX]; - + /// statistics for DLSCH measurement collection + eNB_SCH_STATS_t dlsch_stats[NUMBER_OF_SCH_STATS_MAX]; + /// statistics for ULSCH measurement collection + eNB_SCH_STATS_t ulsch_stats[NUMBER_OF_SCH_STATS_MAX]; + /// statis for UCI (PUCCH) measurement collection + eNB_UCI_STATS_t uci_stats[NUMBER_OF_SCH_STATS_MAX]; /// target_ue_dl_mcs : only for debug purposes uint32_t target_ue_dl_mcs; /// target_ue_ul_mcs : only for debug purposes @@ -665,6 +771,7 @@ typedef struct PHY_VARS_eNB_s { int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_BO[NUMBER_OF_UE_MAX][10240]; uint8_t *FS6bufferZone; + int32_t pusch_signal_threshold; } PHY_VARS_eNB; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index e2cdebff3a..fb4f9a0092 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -94,30 +94,72 @@ typedef struct { uint32_t frame; /// Subframe where current HARQ round was sent uint32_t subframe; - /// Index of current HARQ round for this DLSCH - uint8_t round; /// MIMO mode for this DLSCH MIMO_mode_t mimo_mode; - /// Concatenated sequences - uint8_t *e; - /// LDPC-code outputs - uint8_t *d[MAX_NUM_NR_DLSCH_SEGMENTS]; - /// Interleaver outputs - uint8_t *f; - /// Number of code segments - uint32_t C; - /// Number of bits in "small" code segments - uint32_t K; - /// Number of "Filler" bits - uint32_t F; + /// LDPC lifting size + uint32_t Z; } NR_DL_gNB_HARQ_t; +typedef struct { + int frame; + int slot; + nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu; +} NR_gNB_PDCCH_t; typedef struct { - /// Pointers to 16 HARQ processes for the DLSCH - NR_DL_gNB_HARQ_t *harq_processes[NR_MAX_NB_HARQ_PROCESSES]; - /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding) + uint8_t active; + nfapi_nr_dl_tti_csi_rs_pdu csirs_pdu; +} NR_gNB_CSIRS_t; + +typedef struct { + int frame; + int slot; + nfapi_nr_ul_dci_request_pdus_t pdcch_pdu; +} NR_gNB_UL_PDCCH_t; + +typedef struct { + int frame; + int dump_frame; + uint16_t rnti; + int round_trials[8]; + int total_bytes_tx; + int total_bytes_rx; + int current_Qm; + int current_RI; + int power[NB_ANTENNAS_RX]; + int noise_power[NB_ANTENNAS_RX]; + int DTX; + int sync_pos; +} NR_gNB_SCH_STATS_t; + +typedef struct { + int frame; + uint16_t rnti; + int pucch0_sr_trials; + int pucch0_sr_thres; + int current_pucch0_sr_stat0; + int current_pucch0_sr_stat1; + int pucch0_positive_SR; + int pucch01_trials; + int pucch0_n00; + int pucch0_n01; + int pucch0_thres; + int current_pucch0_stat0; + int current_pucch0_stat1; + int pucch01_DTX; + int pucch02_trials; + int pucch02_DTX; + int pucch2_trials; + int pucch2_DTX; +} NR_gNB_UCI_STATS_t; + +typedef struct { + /// Pointers to variables related to DLSCH harq process + NR_DL_gNB_HARQ_t harq_process; + /// TX buffers for UE-spec transmission (antenna layers 1,...,4 after to precoding) int32_t *txdataF[NR_MAX_NB_LAYERS]; + /// TX buffers for UE-spec transmission (antenna ports 1000 or 1001,...,1007, before precoding) + int32_t *txdataF_precoding[NR_MAX_NB_LAYERS]; /// Modulated symbols buffer int32_t *mod_symbs[NR_MAX_NB_CODEWORDS]; /// beamforming weights for UE-spec transmission (antenna ports 5 or 7..14), for each codeword, maximum 4 layers? @@ -158,6 +200,11 @@ typedef struct { int16_t sqrt_rho_b; } NR_gNB_DLSCH_t; +typedef struct { + bool active; + nfapi_nr_dl_tti_ssb_pdu ssb_pdu; +} NR_gNB_SSB_t; + typedef struct { int frame; int slot; @@ -188,6 +235,8 @@ typedef struct { uint32_t slot; /// Index of current HARQ round for this DLSCH uint8_t round; + uint8_t ndi; + bool new_rx; /// Last TPC command uint8_t TPC; /// MIMO mode for this DLSCH @@ -241,6 +290,8 @@ typedef struct { int16_t e[MAX_NUM_NR_DLSCH_SEGMENTS][3*8448]; /// Number of bits in each code block after rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1) uint32_t E; + /// Number of segments processed so far + uint32_t processedSegments; ////////////////////////////////////////////////////////////// @@ -334,10 +385,6 @@ typedef struct { uint8_t max_ldpc_iterations; /// number of iterations used in last LDPC decoding uint8_t last_iteration_cnt; - /// num active cba group - uint8_t num_active_cba_groups; - /// num active cba group - uint16_t cba_rnti[NUM_MAX_CBA_GROUP]; } NR_gNB_ULSCH_t; typedef struct { @@ -363,8 +410,14 @@ typedef struct { /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. //? /// - first index: eNB id [0..2] (hard coded) /// - second index: tx antenna [0..14[ where 14 is the total supported antenna ports. - /// - third index: sample [0..] + /// - third index: sample [0..samples_per_frame_woCP] int32_t **txdataF; + /// \brief Anaglogue beam ID for each OFDM symbol (used when beamforming not done in RU) + /// - first index: antenna port + /// - second index: beam_id [0.. symbols_per_frame[ + uint8_t **beam_id; + int32_t *debugBuff; + int32_t debugBuff_sample_offset; } NR_gNB_COMMON; @@ -377,8 +430,6 @@ typedef struct { /// - first index: rx antenna id [0..nb_antennas_rx[ /// - second index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **rxdataF_ext2; - /// \brief Offset for calculating the index of rxdataF_ext for the current symbol - uint32_t rxdataF_ext_offset; /// \brief Hold the channel estimates in time domain based on DRS. /// - first index: rx antenna id [0..nb_antennas_rx[ /// - second index: ? [0..4*ofdm_symbol_size[ @@ -434,7 +485,13 @@ typedef struct { /// - second index: ? [0..168*N_RB_UL[ int32_t **ul_ch_magb1[8][8]; /// measured RX power based on DRS - int ulsch_power[2]; + int ulsch_power[8]; + /// total signal over antennas + int ulsch_power_tot; + /// measured RX noise power + int ulsch_noise_power[8]; + /// total noise over antennas + int ulsch_noise_power_tot; /// \brief llr values. /// - first index: ? [0..1179743] (hard coded) int16_t *llr; @@ -445,12 +502,20 @@ typedef struct { /// bit mask of PT-RS ofdm symbol indicies uint16_t ptrs_symbols; // PTRS subcarriers per OFDM symbol - uint16_t ptrs_sc_per_ofdm_symbol; + int32_t ptrs_re_per_slot; + /// \brief Estimated phase error based upon PTRS on each symbol . + /// - first index: ? [0..7] Number of Antenna + /// - second index: ? [0...14] smybol per slot + int32_t **ptrs_phase_per_slot; + /// \brief Total RE count after DMRS/PTRS RE's are extracted from respective symbol. + /// - first index: ? [0...14] smybol per slot + int16_t *ul_valid_re_per_slot; /// flag to verify if channel level computation is done uint8_t cl_done; + /// flag to indicate DTX on reception + int DTX; } NR_gNB_PUSCH; - /// Context data structure for RX/TX portion of slot processing typedef struct { /// Component Carrier index @@ -525,8 +590,10 @@ typedef struct gNB_L1_proc_t_s { pthread_t pthread_single; /// pthread structure for asychronous RX/TX processing thread pthread_t pthread_asynch_rxtx; - /// pthread structure for printing time meas + /// pthread structure for dumping L1 stats pthread_t L1_stats_thread; + /// pthread structure for printing time meas + pthread_t process_stats_thread; /// flag to indicate first RX acquisition int first_rx; /// flag to indicate first TX transmission @@ -581,51 +648,57 @@ typedef struct { //! estimated noise power (linear) unsigned int n0_power[MAX_NUM_RU_PER_gNB]; //! estimated noise power (dB) - unsigned short n0_power_dB[MAX_NUM_RU_PER_gNB]; + unsigned int n0_power_dB[MAX_NUM_RU_PER_gNB]; //! total estimated noise power (linear) unsigned int n0_power_tot; //! estimated avg noise power (dB) - unsigned short n0_power_tot_dB; + unsigned int n0_power_tot_dB; //! estimated avg noise power (dB) - short n0_power_tot_dBm; + int n0_power_tot_dBm; //! estimated avg noise power per RB per RX ant (lin) - unsigned short n0_subband_power[MAX_NUM_RU_PER_gNB][275]; + unsigned int n0_subband_power[MAX_NUM_RU_PER_gNB][275]; //! estimated avg noise power per RB per RX ant (dB) - unsigned short n0_subband_power_dB[MAX_NUM_RU_PER_gNB][275]; + unsigned int n0_subband_power_dB[MAX_NUM_RU_PER_gNB][275]; + //! estimated avg subband noise power (dB) + unsigned int n0_subband_power_avg_dB; + //! estimated avg subband noise power per antenna (dB) + unsigned int n0_subband_power_avg_perANT_dB[NB_ANTENNAS_RX]; //! estimated avg noise power per RB (dB) - short n0_subband_power_tot_dB[275]; + int n0_subband_power_tot_dB[275]; //! estimated avg noise power per RB (dBm) - short n0_subband_power_tot_dBm[275]; + int n0_subband_power_tot_dBm[275]; + // gNB measurements (per user) //! estimated received spatial signal power (linear) - unsigned int rx_spatial_power[NUMBER_OF_NR_DLSCH_MAX][2][2]; + unsigned int rx_spatial_power[NUMBER_OF_NR_ULSCH_MAX][NB_ANTENNAS_TX][NB_ANTENNAS_RX]; //! estimated received spatial signal power (dB) - unsigned short rx_spatial_power_dB[NUMBER_OF_NR_DLSCH_MAX][2][2]; + unsigned int rx_spatial_power_dB[NUMBER_OF_NR_ULSCH_MAX][NB_ANTENNAS_TX][NB_ANTENNAS_RX]; //! estimated rssi (dBm) - short rx_rssi_dBm[NUMBER_OF_NR_DLSCH_MAX]; + int rx_rssi_dBm[NUMBER_OF_NR_ULSCH_MAX]; //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation) - int rx_correlation[NUMBER_OF_NR_DLSCH_MAX][2]; + int rx_correlation[NUMBER_OF_NR_ULSCH_MAX][2]; //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation) - int rx_correlation_dB[NUMBER_OF_NR_DLSCH_MAX][2]; + int rx_correlation_dB[NUMBER_OF_NR_ULSCH_MAX][2]; /// Wideband CQI (= SINR) - int wideband_cqi[NUMBER_OF_NR_DLSCH_MAX][MAX_NUM_RU_PER_gNB]; + int wideband_cqi[NUMBER_OF_NR_ULSCH_MAX][MAX_NUM_RU_PER_gNB]; /// Wideband CQI in dB (= SINR dB) - int wideband_cqi_dB[NUMBER_OF_NR_DLSCH_MAX][MAX_NUM_RU_PER_gNB]; + int wideband_cqi_dB[NUMBER_OF_NR_ULSCH_MAX][MAX_NUM_RU_PER_gNB]; /// Wideband CQI (sum of all RX antennas, in dB) - char wideband_cqi_tot[NUMBER_OF_NR_DLSCH_MAX]; + char wideband_cqi_tot[NUMBER_OF_NR_ULSCH_MAX]; /// Subband CQI per RX antenna and RB (= SINR) - int subband_cqi[NUMBER_OF_NR_DLSCH_MAX][MAX_NUM_RU_PER_gNB][275]; + int subband_cqi[NUMBER_OF_NR_ULSCH_MAX][MAX_NUM_RU_PER_gNB][275]; /// Total Subband CQI and RB (= SINR) - int subband_cqi_tot[NUMBER_OF_NR_DLSCH_MAX][275]; + int subband_cqi_tot[NUMBER_OF_NR_ULSCH_MAX][275]; /// Subband CQI in dB and RB (= SINR dB) - int subband_cqi_dB[NUMBER_OF_NR_DLSCH_MAX][MAX_NUM_RU_PER_gNB][275]; + int subband_cqi_dB[NUMBER_OF_NR_ULSCH_MAX][MAX_NUM_RU_PER_gNB][275]; /// Total Subband CQI and RB - int subband_cqi_tot_dB[NUMBER_OF_NR_DLSCH_MAX][275]; + int subband_cqi_tot_dB[NUMBER_OF_NR_ULSCH_MAX][275]; /// PRACH background noise level int prach_I0; } PHY_MEASUREMENTS_gNB; +#define MAX_NUM_NR_PRACH_PREAMBLES 64 #define MAX_NUM_NR_RX_RACH_PDUS 4 #define MAX_NUM_NR_RX_PRACH_PREAMBLES 4 #define MAX_UL_PDUS_PER_SLOT 8 @@ -674,21 +747,26 @@ typedef struct PHY_VARS_gNB_s { nfapi_nr_ul_tti_request_t UL_tti_req; nfapi_nr_uci_indication_t uci_indication; - nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu; - nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu; - nfapi_nr_dl_tti_ssb_pdu ssb_pdu; - - int num_pdsch_rnti; - NR_gNB_PBCH pbch; + // nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu; + // nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu; + uint16_t num_pdsch_rnti[80]; + NR_gNB_PBCH pbch; nr_cce_t cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL]; NR_gNB_COMMON common_vars; NR_gNB_PRACH prach_vars; NR_gNB_PUSCH *pusch_vars[NUMBER_OF_NR_ULSCH_MAX]; NR_gNB_PUCCH_t *pucch[NUMBER_OF_NR_PUCCH_MAX]; + NR_gNB_PDCCH_t pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX]; + NR_gNB_UL_PDCCH_t ul_pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX]; NR_gNB_DLSCH_t *dlsch[NUMBER_OF_NR_DLSCH_MAX][2]; // Nusers times two spatial streams NR_gNB_ULSCH_t *ulsch[NUMBER_OF_NR_ULSCH_MAX][2]; // [Nusers times][2 codewords] NR_gNB_DLSCH_t *dlsch_SI,*dlsch_ra,*dlsch_p; NR_gNB_DLSCH_t *dlsch_PCH; + /// statistics for DLSCH measurement collection + NR_gNB_SCH_STATS_t dlsch_stats[NUMBER_OF_NR_SCH_STATS_MAX]; + /// statistics for ULSCH measurement collection + NR_gNB_SCH_STATS_t ulsch_stats[NUMBER_OF_NR_SCH_STATS_MAX]; + NR_gNB_UCI_STATS_t uci_stats[NUMBER_OF_NR_UCI_STATS_MAX]; t_nrPolar_params *uci_polarParams; uint8_t pbch_configured; @@ -715,6 +793,12 @@ typedef struct PHY_VARS_gNB_s { /// PUSCH DMRS uint32_t ****nr_gold_pusch_dmrs; + // Mask of occupied RBs, per symbol and PRB + uint32_t rb_mask_ul[14][9]; + + /// CSI RS sequence + uint32_t ***nr_gold_csi_rs; + /// Indicator set to 0 after first SR uint8_t first_sr[NUMBER_OF_NR_SR_MAX]; @@ -723,6 +807,8 @@ typedef struct PHY_VARS_gNB_s { uint32_t max_peak_val; + /// OFDM symbol offset divisor for UL + uint32_t ofdm_offset_divisor; /// \brief sinr for all subcarriers of the current link (used only for abstraction). /// first index: ? [0..N_RB_DL*12[ double *sinr_dB; @@ -742,16 +828,24 @@ typedef struct PHY_VARS_gNB_s { int **dl_precoder_SgNB[3]; char log2_maxp; /// holds the maximum channel/precoder coefficient + int prb_interpolation; + /// if ==0 enables phy only test mode int mac_enabled; /// counter to average prach energh over first 100 prach opportunities int prach_energy_counter; int pucch0_thres; + int pusch_thres; + int prach_thres; + uint64_t bad_pucch; + int num_ulprbbl; + int ulprbbl[275]; /* time_stats_t phy_proc; */ - time_stats_t phy_proc_tx; + time_stats_t *phy_proc_tx_0; + time_stats_t *phy_proc_tx_1; time_stats_t phy_proc_rx; time_stats_t rx_prach; /* @@ -760,6 +854,9 @@ typedef struct PHY_VARS_gNB_s { time_stats_t dlsch_encoding_stats; time_stats_t dlsch_modulation_stats; time_stats_t dlsch_scrambling_stats; + time_stats_t dlsch_resource_mapping_stats; + time_stats_t dlsch_layer_mapping_stats; + time_stats_t dlsch_precoding_stats; time_stats_t tinput; time_stats_t tprep; time_stats_t tparity; @@ -769,20 +866,98 @@ typedef struct PHY_VARS_gNB_s { time_stats_t dlsch_interleaving_stats; time_stats_t dlsch_segmentation_stats; + time_stats_t rx_pusch_stats; + time_stats_t ul_indication_stats; time_stats_t ulsch_decoding_stats; time_stats_t ulsch_rate_unmatching_stats; time_stats_t ulsch_ldpc_decoding_stats; time_stats_t ulsch_deinterleaving_stats; time_stats_t ulsch_unscrambling_stats; time_stats_t ulsch_channel_estimation_stats; + time_stats_t ulsch_ptrs_processing_stats; time_stats_t ulsch_channel_compensation_stats; time_stats_t ulsch_rbs_extraction_stats; + time_stats_t ulsch_mrc_stats; time_stats_t ulsch_llr_stats; + /* time_stats_t rx_dft_stats; time_stats_t ulsch_freq_offset_estimation_stats; */ - + notifiedFIFO_t *respDecode; + notifiedFIFO_t *resp_L1; + notifiedFIFO_t *resp_L1_tx; + notifiedFIFO_t *resp_RU_tx; + tpool_t *threadPool; + int nbDecode; + uint8_t pusch_proc_threads; + int number_of_nr_dlsch_max; + int number_of_nr_ulsch_max; + void * scopeData; } PHY_VARS_gNB; +typedef struct LDPCDecode_s { + PHY_VARS_gNB *gNB; + NR_UL_gNB_HARQ_t *ulsch_harq; + t_nrLDPC_dec_params decoderParms; + NR_gNB_ULSCH_t *ulsch; + short* ulsch_llr; + int ulsch_id; + int harq_pid; + int rv_index; + int A; + int E; + int Kc; + int Qm; + int Kr_bytes; + int nbSegments; + int segment_r; + int r_offset; + int offset; + int Tbslbrm; + int decodeIterations; +} ldpcDecode_t; + +struct ldpcReqId { + uint16_t rnti; + uint16_t frame; + uint8_t subframe; + uint8_t codeblock; + uint16_t spare; +} __attribute__((packed)); + +union ldpcReqUnion { + struct ldpcReqId s; + uint64_t p; +}; + +typedef struct processingData_L1 { + int frame_rx; + int frame_tx; + int slot_rx; + int slot_tx; + openair0_timestamp timestamp_tx; + PHY_VARS_gNB *gNB; +} processingData_L1_t; + +typedef enum { + FILLED, + FILLING, + NOT_FILLED +} msgStatus_t; + +typedef struct processingData_L1tx { + int frame; + int slot; + openair0_timestamp timestamp_tx; + PHY_VARS_gNB *gNB; + nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu; + nfapi_nr_ul_dci_request_pdus_t ul_pdcch_pdu; + NR_gNB_CSIRS_t csirs_pdu[NUMBER_OF_NR_CSIRS_MAX]; + NR_gNB_DLSCH_t *dlsch[NUMBER_OF_NR_DLSCH_MAX][2]; + NR_gNB_SSB_t ssb[64]; + uint16_t num_pdsch_slot; + time_stats_t phy_proc_tx; +} processingData_L1tx_t; + #endif diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 9bdf892ceb..69978f5548 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -20,7 +20,7 @@ */ /*! \file PHY/defs_nr_UE.h - \brief Top-level defines and structure definitions for nr ue + \brief Top-level constants and data structures definitions for NR UE \author Guy De Souza, H. WANG, A. Mico Pereperez \date 2018 \version 0.1 @@ -46,22 +46,17 @@ #include "common_lib.h" #include "msc.h" #include "fapi_nr_ue_interface.h" - -//#include #include "assertions.h" + #ifdef MEX #define msg mexPrintf #else - #ifdef OPENAIR2 #if ENABLE_RAL #include "common/utils/hashtable/hashtable.h" #include "COMMON/ral_messages_types.h" #include "UTIL/queue.h" #endif #define msg(aRGS...) LOG_D(PHY, ##aRGS) - #else - #define msg printf - #endif #endif //use msg in the real-time thread context #define msg_nrt printf @@ -79,9 +74,6 @@ #define openair_free(y,x) free((y)) #define PAGE_SIZE 4096 -//#define RX_NB_TH_MAX 3 -//#define RX_NB_TH 3 - #ifdef NR_UNIT_TEST #define FILE_NAME " " #define LINE_FILE (0) @@ -92,53 +84,19 @@ #define NR_TST_PHY_PRINTF(...) #endif -//#ifdef SHRLIBDEV -//extern int rxrescale; -//#define RX_IQRESCALELEN rxrescale -//#else -//#define RX_IQRESCALELEN 15 -//#endif - -//! \brief Allocate \c size bytes of memory on the heap with alignment 16 and zero it afterwards. -//! If no more memory is available, this function will terminate the program with an assertion error. -/*static inline void* malloc16_clear( size_t size ) -{ -#ifdef __AVX2__ - void* ptr = memalign(32, size); -#else - void* ptr = memalign(16, size); -#endif - DevAssert(ptr); - memset( ptr, 0, size ); - return ptr; -}*/ - - - #define PAGE_MASK 0xfffff000 #define virt_to_phys(x) (x) - #define openair_sched_exit() exit(-1) - -//#define max(a,b) ((a)>(b) ? (a) : (b)) -//#define min(a,b) ((a)<(b) ? (a) : (b)) - - #define bzero(s,n) (memset((s),0,(n))) - #define cmax(a,b) ((a>b) ? (a) : (b)) #define cmin(a,b) ((ac) ? (cmax(a,b)) : (c)) - /// suppress compiler warning for unused arguments #define UNUSED(x) (void)x; - #include "impl_defs_top.h" #include "impl_defs_nr.h" - #include "PHY/TOOLS/time_meas.h" #include "PHY/CODING/coding_defs.h" #include "PHY/TOOLS/tools_defs.h" @@ -146,20 +104,14 @@ #include "NR_UE_TRANSPORT/nr_transport_ue.h" #if defined(UPGRADE_RAT_NR) - #include "PHY/NR_REFSIG/ss_pbch_nr.h" - #endif #include "PHY/NR_UE_TRANSPORT/dci_nr.h" -//#include "PHY/LTE_TRANSPORT/defs.h" -//#include "PHY/NR_UE_TRANSPORT/defs_nr.h" #include - #include "targets/ARCH/COMMON/common_lib.h" - -/// Context data structure for eNB subframe processing +/// Context data structure for gNB subframe processing typedef struct { /// Component Carrier index uint8_t CC_id; @@ -177,9 +129,6 @@ typedef enum { #define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg typedef struct { - //unsigned int rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; //! estimated received signal power (linear) - //unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; //! estimated received signal power (dB) - //unsigned short rx_avg_power_dB[NUMBER_OF_CONNECTED_eNB_MAX]; //! estimated avg received signal power (dB) // RRC measurements uint32_t rssi; @@ -189,6 +138,7 @@ typedef struct { uint32_t rsrp[7]; float rsrp_filtered[7]; // after layer 3 filtering float rsrq_filtered[7]; + short rsrp_dBm[7]; // common measurements //! estimated noise power (linear) unsigned int n0_power[NB_ANTENNAS_RX]; @@ -207,61 +157,59 @@ typedef struct { // UE measurements //! estimated received spatial signal power (linear) - int rx_spatial_power[NUMBER_OF_CONNECTED_eNB_MAX][2][2]; + int rx_spatial_power[NUMBER_OF_CONNECTED_gNB_MAX][2][2]; //! estimated received spatial signal power (dB) - unsigned short rx_spatial_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][2][2]; + unsigned short rx_spatial_power_dB[NUMBER_OF_CONNECTED_gNB_MAX][2][2]; /// estimated received signal power (sum over all TX antennas) - //int wideband_cqi[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; - int rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; + int rx_power[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX]; /// estimated received signal power (sum over all TX antennas) - //int wideband_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; - unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; + unsigned short rx_power_dB[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX]; /// estimated received signal power (sum over all TX/RX antennas) - int rx_power_tot[NUMBER_OF_CONNECTED_eNB_MAX]; //NEW + int rx_power_tot[NUMBER_OF_CONNECTED_gNB_MAX]; //NEW /// estimated received signal power (sum over all TX/RX antennas) - unsigned short rx_power_tot_dB[NUMBER_OF_CONNECTED_eNB_MAX]; //NEW + unsigned short rx_power_tot_dB[NUMBER_OF_CONNECTED_gNB_MAX]; //NEW //! estimated received signal power (sum of all TX/RX antennas, time average) - int rx_power_avg[NUMBER_OF_CONNECTED_eNB_MAX]; + int rx_power_avg[NUMBER_OF_CONNECTED_gNB_MAX]; //! estimated received signal power (sum of all TX/RX antennas, time average, in dB) - unsigned short rx_power_avg_dB[NUMBER_OF_CONNECTED_eNB_MAX]; + unsigned short rx_power_avg_dB[NUMBER_OF_CONNECTED_gNB_MAX]; /// SINR (sum of all TX/RX antennas, in dB) - int wideband_cqi_tot[NUMBER_OF_CONNECTED_eNB_MAX]; + int wideband_cqi_tot[NUMBER_OF_CONNECTED_gNB_MAX]; /// SINR (sum of all TX/RX antennas, time average, in dB) - int wideband_cqi_avg[NUMBER_OF_CONNECTED_eNB_MAX]; + int wideband_cqi_avg[NUMBER_OF_CONNECTED_gNB_MAX]; //! estimated rssi (dBm) - short rx_rssi_dBm[NUMBER_OF_CONNECTED_eNB_MAX]; + short rx_rssi_dBm[NUMBER_OF_CONNECTED_gNB_MAX]; //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation) - int rx_correlation[NUMBER_OF_CONNECTED_eNB_MAX][2]; + int rx_correlation[NUMBER_OF_CONNECTED_gNB_MAX][4][4]; //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation) - int rx_correlation_dB[NUMBER_OF_CONNECTED_eNB_MAX][2]; + int rx_correlation_dB[NUMBER_OF_CONNECTED_gNB_MAX][2]; /// Wideband CQI (sum of all RX antennas, in dB, for precoded transmission modes (3,4,5,6), up to 4 spatial streams) - int precoded_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX+1][4]; + int precoded_cqi_dB[NUMBER_OF_CONNECTED_gNB_MAX+1][4]; /// Subband CQI per RX antenna (= SINR) - int subband_cqi[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX]; + int subband_cqi[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX]; /// Total Subband CQI (= SINR) - int subband_cqi_tot[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX]; + int subband_cqi_tot[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX]; /// Subband CQI in dB (= SINR dB) - int subband_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX]; + int subband_cqi_dB[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX]; /// Total Subband CQI - int subband_cqi_tot_dB[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX]; + int subband_cqi_tot_dB[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX]; /// Wideband PMI for each RX antenna - int wideband_pmi_re[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; + int wideband_pmi_re[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX]; /// Wideband PMI for each RX antenna - int wideband_pmi_im[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; + int wideband_pmi_im[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX]; ///Subband PMI for each RX antenna - int subband_pmi_re[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX]; + int subband_pmi_re[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX]; ///Subband PMI for each RX antenna - int subband_pmi_im[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX]; + int subband_pmi_im[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX]; /// chosen RX antennas (1=Rx antenna 1, 2=Rx antenna 2, 3=both Rx antennas) - unsigned char selected_rx_antennas[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX]; + unsigned char selected_rx_antennas[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX]; /// Wideband Rank indication - unsigned char rank[NUMBER_OF_CONNECTED_eNB_MAX]; + unsigned char rank[NUMBER_OF_CONNECTED_gNB_MAX]; /// Number of RX Antennas unsigned char nb_antennas_rx; /// DLSCH error counter @@ -283,6 +231,11 @@ typedef struct { int32_t *txdataF_layers[NR_MAX_NB_LAYERS]; } NR_UE_PUSCH; +typedef struct { + bool active[2]; + fapi_nr_ul_config_pucch_pdu pucch_pdu[2]; + } NR_UE_PUCCH; + typedef struct { /// \brief Holds the transmit data in time domain. /// For IFFT_FPGA this points to the same memory as PHY_vars->tx_vars[a].TX_DMA_BUFFER. @@ -338,6 +291,10 @@ typedef struct { /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_estimates_ext; + /// \brief Downlink channel estimates extracted in PRBS. + /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx + /// - second index: ? [0..168*N_RB_DL[ + int32_t **dl_ch_ptrs_estimates_ext; /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. For the SIC receiver we need to store the history of this for each harq process and round /// - first index: ? [0..7] (hard coded) accessed via \c harq_pid /// - second index: ? [0..7] (hard coded) accessed via \c round @@ -375,12 +332,12 @@ typedef struct { /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_magb1[8][8]; - /// \brief Cross-correlation of two eNB signals. - /// - first index: rx antenna [0..nb_antennas_rx[ + /// \brief Magnitude of Downlink Channel, first layer (256QAM level). + int32_t **dl_ch_magr0; + /// \brief Cross-correlation Matrix of the gNB Tx channel signals. + /// - first index: aatx*n_rx+aarx for all aatx=[0..n_tx[ and aarx=[0..nb_rx[ /// - second index: symbol [0..] - int32_t **rho; - /// never used... always send dl_ch_rho_ext instead... - int32_t **rho_i; + int32_t ***rho; /// \brief Pointers to llr vectors (2 TBs). /// - first index: ? [0..1] (hard coded) /// - second index: ? [0..1179743] (hard coded) @@ -414,57 +371,18 @@ typedef struct { uint32_t llr_offset[14]; // llr length per ofdm symbol uint32_t llr_length[14]; + // llr offset per ofdm symbol + uint32_t dl_valid_re[14]; + /// \brief Estimated phase error based upon PTRS on each symbol . + /// - first index: ? [0..7] Number of Antenna + /// - second index: ? [0...14] smybol per slot + int32_t **ptrs_phase_per_slot; + /// \brief Estimated phase error based upon PTRS on each symbol . + /// - first index: ? [0..7] Number of Antenna + /// - second index: ? [0...14] smybol per slot + int32_t **ptrs_re_per_slot; } NR_UE_PDSCH; -typedef struct { - /// \brief Received frequency-domain signal after extraction. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - int32_t **rxdataF_ext; - /// \brief Received frequency-domain signal after extraction and channel compensation. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **rxdataF_comp; - /// \brief Downlink channel estimates extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - int32_t **dl_ch_estimates_ext; - /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_rho_ext; - /// \brief Downlink PMIs extracted in PRBS and grouped in subbands. - /// - first index: ressource block [0..N_RB_DL[ - uint8_t *pmi_ext; - /// \brief Magnitude of Downlink Channel (16QAM level/First 64QAM level). - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_mag; - /// \brief Magnitude of Downlink Channel (2nd 64QAM level). - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_magb; - /// \brief Cross-correlation of two eNB signals. - /// - first index: rx antenna [0..nb_antennas_rx[ - /// - second index: ? [0..] - double **rho; - /// never used... always send dl_ch_rho_ext instead... - double **rho_i; - /// \brief Pointers to llr vectors (2 TBs). - /// - first index: ? [0..1] (hard coded) - /// - second index: ? [0..1179743] (hard coded) - int16_t *llr[2]; - /// \f$\log_2(\max|H_i|^2)\f$ - uint8_t log2_maxh; - /// \brief Pointers to llr vectors (128-bit alignment). - /// - first index: ? [0..0] (hard coded) - /// - second index: ? [0..] - int16_t **llr128; - //uint32_t *rb_alloc; - //uint8_t Qm[2]; - //MIMO_mode_t mimo_mode; -} NR_UE_PDSCH_FLP; - #define NR_PDCCH_DEFS_NR_UE #define NR_NBR_CORESET_ACT_BWP 3 // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0) #define NR_NBR_SEARCHSPACE_ACT_BWP 10 // The number of SearchSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0) @@ -682,11 +600,11 @@ typedef struct { /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_estimates_ext; - /// \brief Pointers to channel cross-correlation vectors for multi-eNB detection. + /// \brief Pointers to channel cross-correlation vectors for multi-gNB detection. /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_rho_ext; - /// \brief Pointers to channel cross-correlation vectors for multi-eNB detection. + /// \brief Pointers to channel cross-correlation vectors for multi-gNB detection. /// - first index: rx antenna [0..nb_antennas_rx[ /// - second index: ? [0..] int32_t **rho; @@ -716,7 +634,10 @@ typedef struct { uint8_t dciFormat; uint8_t agregationLevel; int nb_search_space; - fapi_nr_dl_config_dci_dl_pdu_rel15_t pdcch_config[FAPI_NR_MAX_SS_PER_CORESET]; + fapi_nr_dl_config_dci_dl_pdu_rel15_t pdcch_config[FAPI_NR_MAX_SS]; + // frame and slot for sib1 in initial sync + uint16_t sfn; + uint16_t slot; /* #ifdef NR_PDCCH_DEFS_NR_UE int nb_searchSpaces; @@ -783,7 +704,6 @@ typedef struct { int16_t *prachF; int16_t *prach; fapi_nr_ul_config_prach_pdu prach_pdu; - uint8_t prach_Config_enabled; } NR_UE_PRACH; // structure used for multiple SSB detection @@ -820,7 +740,7 @@ typedef struct NR_UL_TIME_ALIGNMENT { int16_t ta_frame; char ta_slot; /// TA command and TAGID received from the gNB - uint8_t ta_command; + uint16_t ta_command; uint8_t tag_id; } NR_UL_TIME_ALIGNMENT_t; @@ -843,10 +763,14 @@ typedef struct { int UE_scan_carrier; /// \brief Indicator that UE should enable estimation and compensation of frequency offset int UE_fo_compensation; + /// IF frequency for RF + uint64_t if_freq; + /// UL IF frequency offset for RF + int if_freq_off; /// \brief Indicator that UE is synchronized to a gNB int is_synchronized; - /// \brief Indicates on which frame is synchronized in a two frame synchronization - int is_synchronized_on_frame; + /// \brief Indicator that UE lost frame synchronization + int lost_sync; /// Data structure for UE process scheduling UE_nr_proc_t proc; /// Flag to indicate the UE shouldn't do timing correction at all @@ -867,12 +791,14 @@ typedef struct { int tx_total_RE[NR_MAX_SLOTS_PER_FRAME]; /// \brief Maximum transmit power int8_t tx_power_max_dBm; - /// \brief Number of eNB seen by UE - uint8_t n_connected_eNB; + /// \brief Number of gNB seen by UE + uint8_t n_connected_gNB; /// \brief indicator that Handover procedure has been initiated uint8_t ho_initiated; /// \brief indicator that Handover procedure has been triggered uint8_t ho_triggered; + /// threshold for false dci detection + int dci_thres; /// \brief Measurement variables. PHY_NR_MEASUREMENTS measurements; NR_DL_FRAME_PARMS frame_parms; @@ -884,41 +810,19 @@ typedef struct { fapi_nr_config_request_t nrUE_config; - // the following structures are not part of PHY_vars_UE anymore as it is not thread safe. They are now on the stack of the functions that actually need them - - //nr_downlink_indication_t dl_indication; - //nr_uplink_indication_t ul_indication; - /// UE FAPI DCI request - //nr_dcireq_t dcireq; - - // pointers to the next 2 strcutres are also included in dl_indictation - /// UE FAPI indication for DLSCH reception - //fapi_nr_rx_indication_t rx_ind; - /// UE FAPI indication for DCI reception - //fapi_nr_dci_indication_t dci_ind; - - // point to the current rxTx thread index - uint8_t current_thread_id[NR_MAX_SLOTS_PER_FRAME]; - t_nrPolar_params *polarList; - NR_UE_PDSCH *pdsch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX+1]; // two RxTx Threads - NR_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1]; - NR_UE_PDSCH *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1]; - NR_UE_PDSCH *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1]; - NR_UE_PDSCH *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1]; - NR_UE_PDSCH *pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_PDCCH *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_PUSCH *pusch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][NR_MAX_NB_CODEWORDS]; // two RxTx Threads - NR_UE_ULSCH_t *ulsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][NR_MAX_NB_CODEWORDS]; // two code words - NR_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_DLSCH_t *dlsch_p[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_DLSCH_t *dlsch_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; - // This is for SIC in the UE, to store the reencoded data - LTE_eNB_DLSCH_t *dlsch_eNB[NUMBER_OF_CONNECTED_eNB_MAX]; + NR_UE_PDSCH *pdsch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX+1]; // two RxTx Threads + NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_PDCCH *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_PUSCH *pusch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_PUCCH *pucch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX][NR_MAX_NB_CODEWORDS]; // two RxTx Threads + NR_UE_ULSCH_t *ulsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX][NR_MAX_NB_CODEWORDS]; // two code words + NR_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_DLSCH_t *dlsch_p[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_DLSCH_t *dlsch_MCH[NUMBER_OF_CONNECTED_gNB_MAX]; //Paging parameters uint32_t IMSImod1024; @@ -932,7 +836,7 @@ typedef struct { UE_MODE_t UE_mode[NUMBER_OF_CONNECTED_gNB_MAX]; /// cell-specific reference symbols - uint32_t lte_gold_table[7][20][2][14]; + //uint32_t lte_gold_table[7][20][2][14]; #if defined(UPGRADE_RAT_NR) @@ -946,91 +850,90 @@ typedef struct { uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD]; /// PDSCH DMRS - uint32_t nr_gold_pdsch[2][20][2][NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD]; + uint32_t ****nr_gold_pdsch[NUMBER_OF_CONNECTED_eNB_MAX]; + + // Scrambling IDs used in PDSCH DMRS + uint16_t scramblingID[2]; /// PDCCH DMRS - uint32_t nr_gold_pdcch[7][20][3][52]; + uint32_t ***nr_gold_pdcch[NUMBER_OF_CONNECTED_eNB_MAX]; + + // Scrambling IDs used in PDCCH DMRS + uint16_t scramblingID_pdcch; /// PUSCH DMRS sequence uint32_t ****nr_gold_pusch_dmrs; uint32_t X_u[64][839]; - uint32_t high_speed_flag; + uint32_t perfect_ce; - int16_t ch_est_alpha; - int generate_ul_signal[NUMBER_OF_CONNECTED_eNB_MAX]; + // flag to activate PRB based averaging of channel estimates + // when off, defaults to frequency domain interpolation + int prb_interpolation; + int generate_ul_signal[NUMBER_OF_CONNECTED_gNB_MAX]; UE_NR_SCAN_INFO_t scan_info[NB_BANDS_MAX]; - char ulsch_no_allocation_counter[NUMBER_OF_CONNECTED_eNB_MAX]; - - unsigned char ulsch_Msg3_active[NUMBER_OF_CONNECTED_gNB_MAX]; - uint32_t ulsch_Msg3_frame[NUMBER_OF_CONNECTED_gNB_MAX]; - unsigned char ulsch_Msg3_subframe[NUMBER_OF_CONNECTED_gNB_MAX]; - uint8_t Msg3_startSymbol[NUMBER_OF_CONNECTED_gNB_MAX]; - uint8_t Msg3_Length[NUMBER_OF_CONNECTED_gNB_MAX]; + char ulsch_no_allocation_counter[NUMBER_OF_CONNECTED_gNB_MAX]; NR_PRACH_RESOURCES_t *prach_resources[NUMBER_OF_CONNECTED_gNB_MAX]; int turbo_iterations, turbo_cntl_iterations; /// \brief ?. - /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded) - uint32_t total_TBS[NUMBER_OF_CONNECTED_eNB_MAX]; + /// - first index: gNB [0..NUMBER_OF_CONNECTED_gNB_MAX[ (hard coded) + uint32_t total_TBS[NUMBER_OF_CONNECTED_gNB_MAX]; /// \brief ?. - /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded) - uint32_t total_TBS_last[NUMBER_OF_CONNECTED_eNB_MAX]; + /// - first index: gNB [0..NUMBER_OF_CONNECTED_gNB_MAX[ (hard coded) + uint32_t total_TBS_last[NUMBER_OF_CONNECTED_gNB_MAX]; /// \brief ?. - /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded) - uint32_t bitrate[NUMBER_OF_CONNECTED_eNB_MAX]; + /// - first index: gNB [0..NUMBER_OF_CONNECTED_gNB_MAX[ (hard coded) + uint32_t bitrate[NUMBER_OF_CONNECTED_gNB_MAX]; /// \brief ?. - /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded) - uint32_t total_received_bits[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_errors[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_errors_last[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_received_last[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_fer[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_SI_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_SI_errors[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_ra_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_ra_errors[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_p_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_p_errors[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mch_received_sf[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mch_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mcch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mtch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mcch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mtch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mcch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mtch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int current_dlsch_cqi[NUMBER_OF_CONNECTED_eNB_MAX]; - unsigned char first_run_timing_advance[NUMBER_OF_CONNECTED_eNB_MAX]; - uint8_t prach_cnt; - uint8_t prach_PreambleIndex; - // uint8_t prach_timer; + /// - first index: gNB [0..NUMBER_OF_CONNECTED_gNB_MAX[ (hard coded) + uint32_t total_received_bits[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_errors[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_errors_last[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_received_last[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_fer[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_SI_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_SI_errors[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_ra_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_ra_errors[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_p_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_p_errors[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mch_received_sf[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mch_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mcch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mtch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mcch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mtch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mcch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mtch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int current_dlsch_cqi[NUMBER_OF_CONNECTED_gNB_MAX]; + unsigned char first_run_timing_advance[NUMBER_OF_CONNECTED_gNB_MAX]; uint8_t decode_SIB; uint8_t decode_MIB; uint8_t init_sync_frame; /// temporary offset during cell search prior to MIB decoding int ssb_offset; - uint16_t symbol_offset; // offset in terms of symbols for detected ssb in sync - int rx_offset; /// Timing offset + uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync + int rx_offset; /// Timing offset int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP + int max_pos_fil; /// Timing offset IIR filter int time_sync_cell; /// Timing Advance updates variables /// Timing advance update computed from the TA command signalled from gNB int timing_advance; - int hw_timing_advance; int N_TA_offset; ///timing offset used in TDD NR_UL_TIME_ALIGNMENT_t ul_time_alignment[NUMBER_OF_CONNECTED_gNB_MAX]; /// Flag to tell if UE is secondary user (cognitive mode) unsigned char is_secondary_ue; - /// Flag to tell if secondary eNB has channel estimates to create NULL-beams from. + /// Flag to tell if secondary gNB has channel estimates to create NULL-beams from. unsigned char has_valid_precoder; - /// hold the precoder for NULL beam to the primary eNB + /// hold the precoder for NULL beam to the primary gNB int **ul_precoder_S_UE; /// holds the maximum channel/precoder coefficient char log2_maxp; @@ -1056,67 +959,46 @@ typedef struct { double N0; /// PDSCH Varaibles - PDSCH_CONFIG_DEDICATED pdsch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + PDSCH_CONFIG_DEDICATED pdsch_config_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; /// PUSCH Varaibles - PUSCH_CONFIG_DEDICATED pusch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + PUSCH_CONFIG_DEDICATED pusch_config_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; /// PUSCH contention-based access vars PUSCH_CA_CONFIG_DEDICATED pusch_ca_config_dedicated[NUMBER_OF_eNB_MAX]; // lola - /// PUCCH variables - - PUCCH_CONFIG_DEDICATED pucch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; //#if defined(UPGRADE_RAT_NR) #if 1 - SystemInformationBlockType1_nr_t systemInformationBlockType1_nr; - - CellGroupConfig_t cell_group_config; - PDSCH_ServingCellConfig_t PDSCH_ServingCellConfig; - PDSCH_Config_t PDSCH_Config; - - PUCCH_ConfigCommon_nr_t pucch_config_common_nr[NUMBER_OF_CONNECTED_eNB_MAX]; - PUCCH_Config_t pucch_config_dedicated_nr[NUMBER_OF_CONNECTED_eNB_MAX]; - - PUSCH_Config_t pusch_config; - SRS_NR srs; - - crossCarrierSchedulingConfig_t crossCarrierSchedulingConfig; - supplementaryUplink_t supplementaryUplink; - dmrs_DownlinkConfig_t dmrs_DownlinkConfig; - csi_MeasConfig_t csi_MeasConfig; - PUSCH_ServingCellConfig_t PUSCH_ServingCellConfig; - #endif uint8_t ncs_cell[20][7]; /// UL-POWER-Control - UL_POWER_CONTROL_DEDICATED ul_power_control_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + UL_POWER_CONTROL_DEDICATED ul_power_control_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; /// TPC - TPC_PDCCH_CONFIG tpc_pdcch_config_pucch[NUMBER_OF_CONNECTED_eNB_MAX]; - TPC_PDCCH_CONFIG tpc_pdcch_config_pusch[NUMBER_OF_CONNECTED_eNB_MAX]; + TPC_PDCCH_CONFIG tpc_pdcch_config_pucch[NUMBER_OF_CONNECTED_gNB_MAX]; + TPC_PDCCH_CONFIG tpc_pdcch_config_pusch[NUMBER_OF_CONNECTED_gNB_MAX]; /// CQI reporting - CQI_REPORT_CONFIG cqi_report_config[NUMBER_OF_CONNECTED_eNB_MAX]; + CQI_REPORT_CONFIG cqi_report_config[NUMBER_OF_CONNECTED_gNB_MAX]; /// SRS Variables - SOUNDINGRS_UL_CONFIG_DEDICATED soundingrs_ul_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + SOUNDINGRS_UL_CONFIG_DEDICATED soundingrs_ul_config_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; /// Scheduling Request Config - SCHEDULING_REQUEST_CONFIG scheduling_request_config[NUMBER_OF_CONNECTED_eNB_MAX]; + SCHEDULING_REQUEST_CONFIG scheduling_request_config[NUMBER_OF_CONNECTED_gNB_MAX]; //#if defined(UPGRADE_RAT_NR) #if 1 - scheduling_request_config_t scheduling_request_config_nr[NUMBER_OF_CONNECTED_eNB_MAX]; + scheduling_request_config_t scheduling_request_config_nr[NUMBER_OF_CONNECTED_gNB_MAX]; #endif - /// Transmission mode per eNB - uint8_t transmission_mode[NUMBER_OF_CONNECTED_eNB_MAX]; + /// Transmission mode per gNB + uint8_t transmission_mode[NUMBER_OF_CONNECTED_gNB_MAX]; time_stats_t phy_proc[RX_NB_TH]; time_stats_t phy_proc_tx; @@ -1126,6 +1008,7 @@ typedef struct { time_stats_t ofdm_mod_stats; time_stats_t ulsch_encoding_stats; + time_stats_t ulsch_ldpc_encoding_stats; time_stats_t ulsch_modulation_stats; time_stats_t ulsch_segmentation_stats; time_stats_t ulsch_rate_matching_stats; @@ -1180,88 +1063,42 @@ typedef struct { SLIST_HEAD(ral_thresholds_gen_poll_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX]; SLIST_HEAD(ral_thresholds_lte_poll_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX]; #endif + + int dl_stats[5]; } PHY_VARS_NR_UE; - /* this structure is used to pass both UE phy vars and * proc to the function UE_thread_rxn_txnp4 */ typedef struct nr_rxtx_thread_data_s { UE_nr_rxtx_proc_t proc; PHY_VARS_NR_UE *UE; + NR_UE_SCHED_MODE_t ue_sched_mode; + notifiedFIFO_t txFifo; } nr_rxtx_thread_data_t; -/*static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { +typedef struct LDPCDecode_ue_s { + PHY_VARS_NR_UE *phy_vars_ue; + NR_DL_UE_HARQ_t *harq_process; + t_nrLDPC_dec_params decoderParms; + NR_UE_DLSCH_t *dlsch; + short* dlsch_llr; + int dlsch_id; + int harq_pid; + int rv_index; + int A; + int E; + int Kc; + int Qm; + int Kr_bytes; + int nbSegments; + int segment_r; + int r_offset; + int offset; + int Tbslbrm; + int decodeIterations; +} ldpcDecode_ue_t; - if (pthread_mutex_lock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - - while (*instance_cnt < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_rxtx is -1 - pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again - } - - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - return(0); -} - -static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { - - if (pthread_mutex_lock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - - while (*instance_cnt == 0) { - // most of the time the thread will skip this - // waits only if proc->instance_cnt_rxtx is 0 - pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again - } - - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - return(0); -} - -static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { - - if (pthread_mutex_lock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - - *instance_cnt=*instance_cnt-1; - - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - return(0); -} -*/ - - -/* -#include "PHY/INIT/defs.h" -#include "PHY/LTE_REFSIG/defs.h" -#include "PHY/MODULATION/defs.h" -#include "PHY/LTE_TRANSPORT/proto.h" -#include "PHY/LTE_ESTIMATION/defs.h" -*/ #include "SIMULATION/ETH_TRANSPORT/defs.h" #endif diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 584962c55c..c385d323e3 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -42,11 +42,6 @@ #define nr_subframe_t lte_subframe_t #define nr_slot_t lte_subframe_t -// [hna] This enables SC-FDMA transmission in Uplink. If disabled, then OFDMA is used in UPLINK. -#ifndef NR_SC_FDMA -// #define NR_SC_FDMA -#endif - #define MAX_NUM_SUBCARRIER_SPACING 5 #define NR_MAX_NB_RB 275 @@ -82,6 +77,9 @@ #define NR_MAX_PDSCH_DMRS_LENGTH 3300 //275*6(k)*2(QPSK real+imag) #define NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD 104 // ceil(NR_MAX_PDSCH_DMRS_LENGTH/32) +#define NR_MAX_CSI_RS_LENGTH 4400 //275*8(max allocation per RB)*2(QPSK) +#define NR_MAX_CSI_RS_INIT_LENGTH_DWORD 138 // ceil(NR_MAX_CSI_RS_LENGTH/32) + #define NR_MAX_PUSCH_DMRS_LENGTH NR_MAX_PDSCH_DMRS_LENGTH #define NR_MAX_PUSCH_DMRS_INIT_LENGTH_DWORD NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD @@ -91,25 +89,31 @@ #define NR_MAX_NUM_BWP 4 -#define NR_MAX_PDCCH_AGG_LEVEL 16 +#define NR_MAX_PDCCH_AGG_LEVEL 16 // 3GPP TS 38.211 V15.8 Section 7.3.2 Table 7.3.2.1-1: Supported PDCCH aggregation levels #define NR_MAX_CSET_DURATION 3 #define NR_MAX_NB_RBG 18 -#define NR_MAX_NB_LAYERS 8 // SU-MIMO (3GPP TS 38.211 V15.4.0 section 7.3.1.3) +#define NR_MAX_NB_LAYERS 2 // 8 // SU-MIMO (3GPP TS 38.211 V15.4.0 section 7.3.1.3) #define NR_MAX_NB_CODEWORDS 2 #define NR_MAX_NB_HARQ_PROCESSES 16 -#define NR_MAX_PDSCH_ENCODED_LENGTH NR_MAX_NB_RB*NR_SYMBOLS_PER_SLOT*NR_NB_SC_PER_RB*8*NR_MAX_NB_LAYERS // 8 is the maximum modulation order (it was 950984 before !!) +#define NR_MAX_PDSCH_ENCODED_LENGTH (NR_MAX_NB_RB*NR_SYMBOLS_PER_SLOT*NR_NB_SC_PER_RB*8*NR_MAX_NB_LAYERS) // 8 is the maximum modulation order (it was 950984 before !!) #define NR_MAX_PUSCH_ENCODED_LENGTH NR_MAX_PDSCH_ENCODED_LENGTH #define NR_MAX_PDSCH_TBS 3824 +#define NR_MAX_SIB_LENGTH 2976 // 3GPP TS 38.331 section 5.2.1 - The physical layer imposes a limit to the maximum size a SIB can take. The maximum SIB1 or SI message size is 2976 bits. -#define MAX_NUM_NR_DLSCH_SEGMENTS 34 +#define MAX_NUM_NR_DLSCH_SEGMENTS (NR_MAX_NB_LAYERS*34) #define MAX_NR_DLSCH_PAYLOAD_BYTES (MAX_NUM_NR_DLSCH_SEGMENTS*1056) -#define MAX_NUM_NR_ULSCH_SEGMENTS MAX_NUM_NR_DLSCH_SEGMENTS +#define MAX_NUM_NR_ULSCH_SEGMENTS 34 #define MAX_NR_ULSCH_PAYLOAD_BYTES (MAX_NUM_NR_ULSCH_SEGMENTS*1056) #define MAX_NUM_NR_CHANNEL_BITS (14*273*12*8) // 14 symbols, 273 RB #define MAX_NUM_NR_RE (14*273*12) +#define NR_RX_NB_TH 1 +#define NR_NB_TH_SLOT 2 + +extern const uint8_t nr_rv_round_map[4]; +extern const uint8_t nr_rv_round_map_ue[4]; typedef enum { NR_MU_0=0, @@ -148,6 +152,11 @@ typedef enum { MOD_QAM256 }nr_mod_t; +typedef enum { + RA_2STEP = 0, + RA_4STEP +} nr_ra_type_e; + typedef struct { /// Size of first RBG uint8_t start_size; @@ -203,8 +212,12 @@ typedef struct { uint16_t prach_format; /// Preamble index for PRACH (0-63) uint8_t ra_PreambleIndex; - /// RACH MaskIndex - uint8_t ra_RACH_MaskIndex; + /// Preamble Tx Counter + uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; + /// Preamble Power Ramping Counter + uint8_t RA_PREAMBLE_POWER_RAMPING_COUNTER; + /// 2-step RA power offset + int POWER_OFFSET_2STEP_RA; /// Target received power at gNB. Baseline is range -202..-60 dBm. Depends on delta preamble, power ramping counter and step. int ra_PREAMBLE_RECEIVED_TARGET_POWER; /// PRACH index for TDD (0 ... 6) depending on TDD configuration and prachConfigIndex @@ -215,14 +228,14 @@ typedef struct { uint8_t RA_PREAMBLE_BACKOFF; /// uint8_t RA_SCALING_FACTOR_BI; - /// - uint8_t RA_PCMAX; + /// Indicating whether it is 2-step or 4-step RA + nr_ra_type_e RA_TYPE; + /// UE configured maximum output power + int RA_PCMAX; /// Corresponding RA-RNTI for UL-grant uint16_t ra_RNTI; - /// Pointer to Msg3 payload for UL-grant - uint8_t *Msg3; /// Frame of last completed synch - uint8_t sync_frame; + uint16_t sync_frame; /// Flag to indicate that prach is ready to start: it is enabled with an initial delay after the sync uint8_t init_msg1; } NR_PRACH_RESOURCES_t; @@ -230,6 +243,7 @@ typedef struct { typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS; typedef uint32_t (*get_samples_per_slot_t)(int slot, NR_DL_FRAME_PARMS* fp); +typedef uint32_t (*get_slot_from_timestamp_t)(openair0_timestamp timestamp_rx, NR_DL_FRAME_PARMS* fp); typedef uint32_t (*get_samples_slot_timestamp_t)(int slot, NR_DL_FRAME_PARMS* fp, uint8_t sl_ahead); @@ -286,14 +300,14 @@ struct NR_DL_FRAME_PARMS { uint32_t samples_per_subframe; /// Number of samples in current slot get_samples_per_slot_t get_samples_per_slot; + /// slot calculation from timestamp + get_slot_from_timestamp_t get_slot_from_timestamp; /// Number of samples before slot get_samples_slot_timestamp_t get_samples_slot_timestamp; /// Number of samples in 0th and center slot of a subframe uint32_t samples_per_slot0; /// Number of samples in other slots of the subframe uint32_t samples_per_slotN0; - /// Number of OFDM/SC-FDMA symbols in one subframe (to be modified to account for potential different in UL/DL) - uint16_t symbols_per_tti; /// Number of samples in a radio frame uint32_t samples_per_frame; /// Number of samples in a subframe without CP @@ -302,15 +316,8 @@ struct NR_DL_FRAME_PARMS { uint32_t samples_per_slot_wCP; /// Number of samples in a radio frame without CP uint32_t samples_per_frame_wCP; - /// Number of samples in a tti (same as subrame in LTE, slot in NR) - uint32_t samples_per_tti; /// NR numerology index [0..5] as specified in 38.211 Section 4 (mu). 0=15khZ SCS, 1=30khZ, 2=60kHz, etc uint8_t numerology_index; - /// NR number of ttis per subframe deduced from numerology (cf 38.211): 1, 2, 4, 8(not supported),16(not supported),32(not supported) - uint8_t ttis_per_subframe; - /// NR number of slots per tti . Assumption only 2 Slot per TTI is supported (Slot Config 1 in 38.211) - uint8_t slots_per_tti; -//#endif /// Number of Physical transmit antennas in node uint8_t nb_antennas_tx; /// Number of Receive antennas in node @@ -319,6 +326,12 @@ struct NR_DL_FRAME_PARMS { uint8_t nb_antenna_ports_gNB; /// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP) lte_prefix_type_t Ncp; + /// sequence which is computed based on carrier frequency and numerology to rotate/derotate each OFDM symbol according to Section 5.3 in 38.211 + /// First dimension is for the direction of the link (0 DL, 1 UL) + int16_t symbol_rotation[2][224*2]; + /// sequence used to compensate the phase rotation due to timeshifted OFDM symbols + /// First dimenstion is for different CP lengths + int16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16))); /// shift of pilot position in one RB uint8_t nushift; /// SRS configuration from TS 38.331 RRC @@ -352,6 +365,8 @@ struct NR_DL_FRAME_PARMS { uint8_t ssb_index; /// PBCH polar encoder params t_nrPolar_params pbch_polar_params; + /// OFDM symbol offset divisor for UL + uint32_t ofdm_offset_divisor; }; @@ -359,20 +374,4 @@ struct NR_DL_FRAME_PARMS { #define KHz (1000UL) #define MHz (1000*KHz) -typedef struct nr_bandentry_s { - int16_t band; - uint64_t ul_min; - uint64_t ul_max; - uint64_t dl_min; - uint64_t dl_max; - uint64_t step_size; - uint64_t N_OFFs_DL; - uint8_t deltaf_raster; -} nr_bandentry_t; - -typedef struct nr_band_info_s { - int nbands; - nr_bandentry_t band_info[100]; -} nr_band_info_t; - #endif diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h index 3e09f3f593..59d8216679 100644 --- a/openair1/PHY/impl_defs_nr.h +++ b/openair1/PHY/impl_defs_nr.h @@ -36,7 +36,6 @@ #include #include "types.h" -#include "NR_PDSCH-TimeDomainResourceAllocation.h" #ifdef DEFINE_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H #define EXTERN @@ -214,10 +213,8 @@ typedef enum { #define NB_SRS_PERIOD (17) -const uint16_t srs_period[NB_SRS_PERIOD] -#ifdef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H +static const uint16_t srs_period[NB_SRS_PERIOD] = { 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560} -#endif ; /// SRS_Resource of SRS_Config information element from 38.331 RRC specifications @@ -342,116 +339,22 @@ typedef struct { * ************************************************************************/ -/* FFS TODO_NR partial structure that should be complete */ - -typedef enum { - semiStatic = 0, - dynamic = 1 -} pdsch_HARQ_ACK_Codebook_t; - - -////////////////////////////////////////////////////////////////////////////////################################ #define MAX_NR_RATE_MATCH_PATTERNS 4 #define MAX_NR_ZP_CSI_RS_RESOURCES 32 #define MAX_NR_OF_DL_ALLOCATIONS 16 #define MAX_NR_OF_UL_ALLOCATIONS (16) -typedef enum{ - dl_resourceAllocationType0 = 1, - dl_resourceAllocationType1 = 2, - dl_dynamicSwitch = 3 -} dl_resourceAllocation_t; -typedef enum{ - dl_rgb_config1 = 1, - dl_rgb_config2 = 2 -} dl_rgb_Size_t; typedef enum { - st_n4 = 1, - st_wideband = 2 -} static_bundleSize_t; -typedef enum { - dy_1_n4 = 1, - dy_1_wideband = 2, - dy_1_n2_wideband = 3, - dy_1_n4_wideband = 4 -} bundleSizeSet1_t; -typedef enum { - dy_2_n4 = 1, - dy_2_wideband = 2, -} bundleSizeSet2_t; -typedef struct{ - bundleSizeSet1_t bundleSizeSet1; - bundleSizeSet2_t bundleSizeSet2; -} dynamic_bundleSize_t; -typedef struct { - static_bundleSize_t staticBundling; - dynamic_bundleSize_t dynamicBundlig; -} prb_bundleType_t; -typedef enum { - nb_code_n1 = 1, - nb_code_n2 = 2 -} maxNrofCodeWordsScheduledByDCI_t; -typedef struct{ -// to be defined FIXME!!! -}rateMatchPattern_t; -typedef struct{ -// to be defined FIXME!!! -}zp_CSI_RS_Resource_t; -typedef struct { -/* - * resourceAllocation - */ - dl_resourceAllocation_t dl_resourceAllocation; -/* - * corresponds to I, where I the number of entries in the higher layer parameter pdsch-AllocationList - */ - uint8_t n_pdsh_alloc_list; -/* - * rateMatchPatternToAddModList - */ - rateMatchPattern_t rateMatchPatternToAddModList[MAX_NR_RATE_MATCH_PATTERNS]; -/* - * rateMatchPatternToReleaseList - */ - uint8_t rateMatchPatternToReleaseList[MAX_NR_RATE_MATCH_PATTERNS]; - /* - * n_rateMatchPatterns indicates the number of rateMatchPatterns defined currently - */ - uint8_t n_rateMatchPatterns; - /* - * zp-CSI-RS-ResourceToAddModList - */ - zp_CSI_RS_Resource_t zp_CSI_RS_Resource[MAX_NR_ZP_CSI_RS_RESOURCES]; - /* - * zp-CSI-RS-ResourceToReleaseList - */ - uint8_t zp_CSI_RS_ResourceId[MAX_NR_ZP_CSI_RS_RESOURCES]; - /* - * n_zp-CSI-RS-Resource - */ - uint8_t n_zp_CSI_RS_ResourceId; -/* - * rgb_Size - */ - dl_rgb_Size_t dl_rgbSize; -/* - * prb-BundlingType - */ - prb_bundleType_t prbBundleType; -/* - * pdsch-HARQ-ACK-Codebook: this is part of the IE PhysicalCellGroupConfig which is used to configure cell-group specific L1 parameters (TS 38.331) - */ - pdsch_HARQ_ACK_Codebook_t pdsch_HARQ_ACK_Codebook; - ////////////////////////////////////////////////////////////////////////////////################################ + typeA = 0, + typeB = 1 +} mappingType_t; -/* - Maximum number of code words that a single DCI may schedule. This changes the number of MCS/RV/NDI bits in the DCI message from 1 to 2. -*/ - maxNrofCodeWordsScheduledByDCI_t maxNrofCodeWordsScheduledByDCI; - - NR_PDSCH_TimeDomainResourceAllocation_t *pdsch_TimeDomainResourceAllocation[MAX_NR_OF_DL_ALLOCATIONS]; - -} PDSCH_Config_t; +typedef enum { + pdsch_dmrs_pos0 = 0, + pdsch_dmrs_pos1 = 1, + pdsch_dmrs_pos2 = 2, + pdsch_dmrs_pos3 = 3, +} pdsch_dmrs_AdditionalPosition_t; /*********************************************************************** * @@ -461,128 +364,20 @@ typedef struct { * ************************************************************************/ - -typedef enum { - enable_tpc_accumulation = 0, /* by default it is enable */ - disable_tpc_accumulation = 1 -} tpc_Accumulation_t; - -typedef enum { - typeA = 0, - typeB = 1 -} mappingType_t; - -typedef struct { - tpc_Accumulation_t tpc_Accumulation; -} PUSCH_PowerControl_t; - -typedef struct { - - uint8_t k2; - mappingType_t mappingType; - uint8_t startSymbolAndLength; -} PUSCH_TimeDomainResourceAllocation_t; -////////////////////////////////////////////////////////////////////////////////################################ -typedef enum{ - maxCodeBlockGroupsPerTransportBlock_n2 = 2, - maxCodeBlockGroupsPerTransportBlock_n4 = 4, - maxCodeBlockGroupsPerTransportBlock_n6 = 6, - maxCodeBlockGroupsPerTransportBlock_n8 = 8 -} maxCodeBlockGroupsPerTransportBlock_t; -typedef struct{ // The IE PUSCH-ServingCellConfig is used to configure UE specific PUSCH parameters that are common across the UE's BWPs of one serving cell - maxCodeBlockGroupsPerTransportBlock_t maxCodeBlockGroupsPerTransportBlock; -} PUSCH_ServingCellConfig_t; -typedef struct{ // CSI-MeasConfig IE is used to configure CSI-RS (reference signals) - uint8_t reportTriggerSize; -} csi_MeasConfig_t; -typedef enum { - pdsch_dmrs_type1 = 1, - pdsch_dmrs_type2 = 2 -} pdsch_dmrs_type_t; typedef enum { pusch_dmrs_type1 = 0, pusch_dmrs_type2 = 1 } pusch_dmrs_type_t; -typedef enum { - pdsch_dmrs_pos0 = 0, - pdsch_dmrs_pos1 = 1, - pdsch_dmrs_pos3 = 3, -} pdsch_dmrs_AdditionalPosition_t; typedef enum { pusch_dmrs_pos0 = 0, pusch_dmrs_pos1 = 1, pusch_dmrs_pos2 = 2, pusch_dmrs_pos3 = 3, } pusch_dmrs_AdditionalPosition_t; -typedef enum { - offset00 = 0, - offset01 = 1, - offset10 = 2, - offset11 = 3, -} ptrs_resource_elementoffset_t; -typedef enum { - pdsch_len1 = 1, - pdsch_len2 = 2 -} pdsch_maxLength_t; typedef enum { pusch_len1 = 1, pusch_len2 = 2 } pusch_maxLength_t; -typedef struct { - uint8_t ptrs_mcs1; - uint8_t ptrs_mcs2; - uint8_t ptrs_mcs3; -} ptrs_time_density_t; -typedef struct { - uint16_t n_rb0; - uint16_t n_rb1; -} ptrs_frequency_density_t; -typedef struct { // The IE PTRS-UplinkConfig is used to configure uplink Phase-Tracking-Reference-Signals (PTRS) - uint8_t num_ptrs_ports; - ptrs_resource_elementoffset_t resourceElementOffset; - ptrs_time_density_t timeDensity; - ptrs_frequency_density_t frequencyDensity; - uint32_t ul_ptrs_power; -} ptrs_UplinkConfig_t; -typedef struct { // The IE DMRS-DownlinkConfig is used to configure downlink demodulation reference signals for PDSCH - pdsch_dmrs_type_t pdsch_dmrs_type; - pdsch_dmrs_AdditionalPosition_t pdsch_dmrs_AdditionalPosition; - pdsch_maxLength_t pdsch_maxLength; - uint16_t scramblingID0; - uint16_t scramblingID1; -} dmrs_DownlinkConfig_t; -typedef struct { // The IE DMRS-UplinkConfig is used to configure uplink demodulation reference signals for PUSCH - pusch_dmrs_type_t pusch_dmrs_type; - pusch_dmrs_AdditionalPosition_t pusch_dmrs_AdditionalPosition; - pusch_maxLength_t pusch_maxLength; - ptrs_UplinkConfig_t ptrs_UplinkConfig; - uint16_t scramblingID0; - uint16_t scramblingID1; -} dmrs_UplinkConfig_t; -typedef struct { -/* - * Serving cell ID of a PSCell. The PCell of the Master Cell Group uses ID = 0 - */ - uint8_t servCellIndex; -}servCellIndex_t; -typedef struct{ - uint8_t cif_presence; -}own_t; -typedef struct{ - servCellIndex_t scheduling_cell_id; - uint8_t cif_InSchedulingCell; -}other_t; -typedef struct{ - own_t own; - other_t other; -}schedulingCellInfo_t; -typedef struct{ - schedulingCellInfo_t schedulingCellInfo; -} crossCarrierSchedulingConfig_t; -typedef struct{ - // this variable will be filled with '1' if SUL is supported and '0' if SUL is not supported - uint8_t supplementaryUplink; -}supplementaryUplink_t; typedef enum { txConfig_codebook = 1, @@ -601,9 +396,11 @@ typedef enum{ ul_rgb_config1 = 1, ul_rgb_config2 = 2 } ul_rgb_Size_t; -typedef enum { - transformPrecoder_enabled = 1, - transformPrecoder_disabled = 2 +/* Aligned values of this enum to other tranform precoder enums + * eg: as defined in fapi_nr_ue_interface.h for transform_precoder_t*/ +typedef enum { + transformPrecoder_enabled = 0, + transformPrecoder_disabled = 1 } transformPrecoder_t; typedef enum { codebookSubset_fullyAndPartialAndNonCoherent = 1, @@ -621,57 +418,6 @@ typedef struct { betaOffset_type_t betaOffset_type; betaOffset_t betaOffset; } uci_onPusch_t; -typedef struct { -/* - * txConfig - */ - txConfig_t txConfig; -/* - * frequencyHopping - */ - frequencyHopping_t frequencyHopping; -/* - * frequencyHoppingOffsetLists - */ - uint16_t frequencyHoppingOffsetLists[4]; - // n_frequencyHoppingOffsetLists contains the number of offsets listed. We can list up to 4 offsets - uint8_t n_frequencyHoppingOffsetLists; -/* - * resourceAllocation - */ - ul_resourceAllocation_t ul_resourceAllocation; -/* - * DMRS-Uplinkconfig - */ - dmrs_UplinkConfig_t dmrs_UplinkConfig; -/* - * rgb_Size - */ - ul_rgb_Size_t ul_rgbSize; -/* - * corresponds to I, where I the number of entries in the higher layer parameter pusch-AllocationList - */ - uint8_t n_push_alloc_list; -/* - * transformPrecoder - */ -transformPrecoder_t transformPrecoder; -/* - * codebookSubset - */ -codebookSubset_t codebookSubset; -/* - * maxRank - */ -uint8_t maxRank; -/* - * uci_onPusch - */ -uci_onPusch_t uci_onPusch; -////////////////////////////////////////////////////////////////////////////////################################ - PUSCH_PowerControl_t pusch_PowerControl; - PUSCH_TimeDomainResourceAllocation_t *pusch_TimeDomainResourceAllocation[MAX_NR_OF_UL_ALLOCATIONS]; -} PUSCH_Config_t; /*********************************************************************** * @@ -681,23 +427,10 @@ uci_onPusch_t uci_onPusch; * ************************************************************************/ -#define MAX_NR_OF_PUCCH_P0_PER_SET (8) #define NUMBER_PUCCH_FORMAT_NR (5) typedef int8_t power_level_t; /* INTEGER (-16..15) */ -typedef struct { - uint8_t p0_PUCCH_Id; /* INTEGER (1..8) */ - power_level_t p0_PUCCH_Value; -} P0_PUCCH_t; - -typedef struct { - power_level_t deltaF_PUCCH_f[NUMBER_PUCCH_FORMAT_NR]; - P0_PUCCH_t *p0_Set[MAX_NR_OF_PUCCH_P0_PER_SET]; - // pathlossReferenceRSs SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSs)) OF PUCCH-PathlossReferenceRS OPTIONAL, -- Need M - int8_t twoPUCCH_PC_AdjustmentStates; - -} PUCCH_PowerControl_t; /*********************************************************************** * @@ -794,7 +527,6 @@ typedef struct { uint8_t initial_CS_indexes[MAX_NB_CYCLIC_SHIFT]; } initial_pucch_resource_t; -const initial_pucch_resource_t initial_pucch_resource[NB_INITIAL_PUCCH_RESOURCE]; /* TS 36.213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */ /* structure with all possible fields for pucch format from 0 to 4 */ typedef struct { @@ -888,152 +620,9 @@ typedef struct { PUCCH_FormatConfig_t *formatConfig[NUMBER_PUCCH_FORMAT_NR-1]; /* format 0 is not there */ uint8_t dl_DataToUL_ACK[NB_DL_DATA_TO_UL_ACK]; /* table TS 38.213 Table 9.2.3-1: Mapping of PSDCH-to-HARQ_feedback timing indicator field values to numbers of slots */ void *spatial_Relation_Info[MAX_NR_OF_SPATIAL_RELATION_INFOS]; - PUCCH_PowerControl_t pucch_PowerControl; } PUCCH_Config_t; -/*********************************************************************** -* -* FUNCTIONALITY : PhysicalCellGroupConfig -* -* DESCRIPTION : Physical cell group configuration -* -************************************************************************/ -typedef uint16_t RNTI_value_t; - -typedef struct { -/* - -- Enables spatial bundling of HARQ ACKs. It is configured per cell group (i.e. for all the cells within the cell group) for PUCCH - -- reporting of HARQ-ACK. It is only applicable when more than 4 layers are possible to schedule. - -- Corresponds to L1 parameter 'HARQ-ACK-spatial-bundling' (see 38.213, section FFS_Section) - -- Absence indicates that spatial bundling is disabled. -*/ - bool harq_ACK_SpatialBundlingPUCCH; -/* - -- Enables spatial bundling of HARQ ACKs. It is configured per cell group (i.e. for all the cells within the cell group) for PUSCH - -- reporting of HARQ-ACK. It is only applicable when more than 4 layers are possible to schedule. - -- Corresponds to L1 parameter 'HARQ-ACK-spatial-bundling' (see 38.213, section FFS_Section) - -- Absence indicates that spatial bundling is disabled. -*/ - bool harq_ACK_SpatialBundlingPUSCH; -/* - -- The maximum transmit power to be used by the UE in this NR cell group. -*/ - uint8_t p_NR; -/* - -- The PDSCH HARQ-ACK codebook is either semi-static of dynamic. This is applicable to both CA and none CA operation. - -- Corresponds to L1 parameter 'HARQ-ACK-codebook' (see 38.213, section FFS_Section) -*/ - pdsch_HARQ_ACK_Codebook_t pdsch_HARQ_ACK_Codebook; -/* - -- RNTI used for SRS TPC commands on DCI. Corresponds to L1 parameter 'TPC-SRS-RNTI' (see 38.213, section 10) -*/ - RNTI_value_t tpc_SRS_RNTI; -/* - -- RNTI used for PUCCH TPC commands on DCI. Corresponds to L1 parameter 'TPC-PUCCH-RNTI' (see 38.213, section 10). -*/ - RNTI_value_t tpc_PUCCH_RNTI; -/* - -- RNTI used for PUSCH TPC commands on DCI. Corresponds to L1 parameter 'TPC-PUSCH-RNTI' (see 38.213, section 10) -*/ - RNTI_value_t tpc_PUSCH_RNTI; -} PhysicalCellGroupConfig_t; - -/*********************************************************************** -* -* FUNCTIONALITY : CellGroupConfig -* -* DESCRIPTION : Cell Group configuration -* -************************************************************************/ - -/* FFS TODO_NR partial structure that should be complete */ - -typedef struct { -/* - cellGroupId CellGroupId, - - -- Logical Channel configuration and association with radio bearers: - rlc-BearerToAddModList SEQUENCE (SIZE(1..maxLC-ID)) OF RLC-Bearer-Config OPTIONAL, -- Need N - rlc-BearerToReleaseList SEQUENCE (SIZE(1..maxLC-ID)) OF LogicalChannelIdentity OPTIONAL, -- Need N - - -- Parameters applicable for the entire cell group: - mac-CellGroupConfig MAC-CellGroupConfig OPTIONAL, -- Need M -*/ - PhysicalCellGroupConfig_t physicalCellGroupConfig; -/* - -- Serving Cell specific parameters (SpCell and SCells) - spCellConfig SpCellConfig OPTIONAL, -- Need M - sCellToAddModList SEQUENCE (SIZE (1..maxNrofSCells)) OF SCellConfig OPTIONAL, -- Need N - -- List of seconary serving cells to be released (not applicable for SpCells) - sCellToReleaseList SEQUENCE (SIZE (1..maxNrofSCells)) OF SCellIndex OPTIONAL, -- Need N - ... - */ -} CellGroupConfig_t; - -/*********************************************************************** -* -* FUNCTIONALITY : PDSCH_ServingCellConfig -* -* DESCRIPTION : pdsch serving cell configuration -* -************************************************************************/ - -/* FFS TODO_NR partial structure that should be complete */ - -typedef int PDSCH_CodeBlockGroupTransmission_t; /* dummy struct which should be change by correct structure */ - -typedef enum { - xOh6 = 0, - xOh12 = 1, - xOh18 = 2 -} xOverhead_t; - -typedef enum { - n2_dl_harq = 2, - n4_dl_harq = 4, - n6_dl_harq = 6, - n10_dl_harq = 10, - n12_dl_harq = 12, - n16_dl_harq = 16 -} nrofHARQ_ProcessesForPDSCH_t; -typedef enum{ - maxCodeBlockGroupsPerTransportBlock_dl_n2 = 2, - maxCodeBlockGroupsPerTransportBlock_dl_n4 = 4, - maxCodeBlockGroupsPerTransportBlock_dl_n6 = 6, - maxCodeBlockGroupsPerTransportBlock_dl_n8 = 8 -} maxCodeBlockGroupsPerTransportBlock_dl_t; - -typedef struct { -/* - -- Enables and configures code-block-group (CBG) based transmission (see 38.213, section 9.1.1) -*/ - PDSCH_CodeBlockGroupTransmission_t *codeBlockGroupTransmission; -/* - -- Accounts for overhead from CSI-RS, CORESET, etc. If the field is absent, the UE applies value xOh0. - -- Corresponds to L1 parameter 'Xoh-PDSCH' (see 38.214, section 5.1.3.2) -*/ - xOverhead_t xOverhead; -/* - -- The number of HARQ processes to be used on the PDSCH of a serving cell. n2 corresponds to 2 HARQ processes, n4 to 4 HARQ processes - -- and so on. If the field is absent, the UE uses 8 HARQ processes. - -- Corresponds to L1 parameter 'number-HARQ-process-PDSCH' (see 38.214, section REF) -*/ - nrofHARQ_ProcessesForPDSCH_t nrofHARQ_ProcessesForPDSCH; -/* - -- The ID of the serving cell (of the same cell group) to use for PUCCH. - -- If the field is absent, the UE sends the HARQ feedback on the PUCCH of the SpCell of this cell group. -*/ - uint8_t pucch_Cell; -/* - * maxCodeBlockGroupsPerTransportBlock_dl_t - */ - maxCodeBlockGroupsPerTransportBlock_dl_t maxCodeBlockGroupsPerTransportBlock_dl; -/* - * codeBlockGroupFlushIndicator (boolean) - */ - uint8_t codeBlockGroupFlushIndicator; -} PDSCH_ServingCellConfig_t; /*********************************************************************** * @@ -1049,11 +638,6 @@ typedef struct { #define NB_SR_PERIOD (15) -const uint16_t scheduling_request_periodicity[NB_SR_PERIOD] -#ifdef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H -= { 0, 0, 1, 2, 4, 5, 8, 10, 16, 20, 40, 80, 160, 320, 640 } -#endif -; typedef enum { sr_sym2 = 0, diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index 6c3d97838d..31b9899605 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -219,6 +219,13 @@ ///Third Amplitude for QAM64 (\f$ 2^{15} \times 1/\sqrt{42}\f$) #define QAM64_n3 5056 +///First Amplitude for QAM256 (\f$ 2^{15} \times 8/\sqrt{170}\f$) +#define QAM256_n1 20106 +///Second Amplitude for QAM256 (\f$ 2^{15} \times 4/\sqrt{170}\f$) +#define QAM256_n2 10053 +///Third Amplitude for QAM256 (\f$ 2^{15} \times 2/\sqrt{170}\f$) +#define QAM256_n3 5026 + /// First Amplitude for QAM16 for TM5 (\f$ 2^{15} \times 2/sqrt(20)\f$) #define QAM16_TM5_n1 14654 /// Second Amplitude for QAM16 for TM5 Receiver (\f$ 2^{15} \times 1/\sqrt{20}\f$) @@ -265,9 +272,20 @@ #define NB_NUMEROLOGIES_NR (5) #define TDD_CONFIG_NB_FRAMES (2) #define NR_MAX_SLOTS_PER_FRAME (160) /* number of slots per frame */ -#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (6) /* FFS_NR_TODO it defines ue capability which is the number of slots */ - /* - between reception of pdsch and tarnsmission of its acknowlegment */ - /* - between reception of un uplink grant and its related transmission */ + +/* FFS_NR_TODO it defines ue capability which is the number of slots */ +/* - between reception of pdsch and tarnsmission of its acknowlegment */ +/* - between reception of un uplink grant and its related transmission */ +/* - FIXME temprarily set to 5 to avoid timing issues at OAI UE in rfsimulator */ +/* - issues caused by no rendez-vous point between TX and RX in the OAI UE */ +#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (5) + +#ifndef NO_RAT_NR + #define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */ +#else + #define DURATION_RX_TO_TX (6) /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */ +#endif + #define NR_MAX_HARQ_PROCESSES (16) #define NR_MAX_ULSCH_HARQ_PROCESSES (NR_MAX_HARQ_PROCESSES) /* cf 38.214 6.1 UE procedure for receiving the physical uplink shared channel */ diff --git a/openair1/PHY/phy_extern.h b/openair1/PHY/phy_extern.h index 165ed961b3..1ce042d086 100644 --- a/openair1/PHY/phy_extern.h +++ b/openair1/PHY/phy_extern.h @@ -23,7 +23,6 @@ #define __PHY_EXTERN_H__ #include "PHY/defs_common.h" -#include "common/ran_context.h" extern char* namepointer_chMag ; extern char* namepointer_log2; @@ -33,14 +32,13 @@ extern unsigned int RX_DMA_BUFFER[4][NB_ANTENNAS_RX]; extern unsigned int TX_DMA_BUFFER[4][NB_ANTENNAS_TX]; #include "PHY/LTE_TRANSPORT/transport_extern.h" -//#include "SIMULATION/ETH_TRANSPORT/extern.h" +#include "PHY/defs_RU.h" extern unsigned int DAQ_MBOX; extern int number_of_cards; extern const short conjugate[8],conjugate2[8]; -extern RAN_CONTEXT_t RC; extern short primary_synch0[144]; extern short primary_synch1[144]; @@ -48,12 +46,6 @@ extern short primary_synch2[144]; extern unsigned char primary_synch0_tab[72]; extern unsigned char primary_synch1_tab[72]; extern unsigned char primary_synch2_tab[72]; -extern int16_t *primary_synch0_time; //!< index: [0..ofdm_symbol_size*2[ -extern int16_t *primary_synch1_time; //!< index: [0..ofdm_symbol_size*2[ -extern int16_t *primary_synch2_time; //!< index: [0..ofdm_symbol_size*2[ -extern int *sync_corr_ue0; //!< index [0..10*samples_per_tti[ -extern int *sync_corr_ue1; //!< index [0..10*samples_per_tti[ -extern int *sync_corr_ue2; //!< index [0..10*samples_per_tti[ extern int flagMag; //extern short **txdataF_rep_tmp; @@ -63,12 +55,6 @@ extern char mode_string[4][20]; extern unsigned char NB_RU; -#ifndef OPENAIR2 -extern unsigned char NB_eNB_INST; -extern uint16_t NB_UE_INST; -extern unsigned char NB_RN_INST; -#endif - extern int flag_LA; extern double sinr_bler_map[MCS_COUNT][2][MCS_TABLE_LENGTH_MAX]; extern double sinr_bler_map_up[MCS_COUNT][2][16]; diff --git a/openair1/PHY/phy_extern_nr_ue.h b/openair1/PHY/phy_extern_nr_ue.h index 2f2a0427f4..66d554f245 100644 --- a/openair1/PHY/phy_extern_nr_ue.h +++ b/openair1/PHY/phy_extern_nr_ue.h @@ -25,6 +25,11 @@ #include "PHY/defs_nr_UE.h" //#include "common/ran_context.h" +#ifdef XFORMS + #include "PHY/TOOLS/nr_phy_scope.h" + extern char do_forms; +#endif + extern char* namepointer_chMag ; extern char* namepointer_log2; extern char fmageren_name2[512]; @@ -32,7 +37,8 @@ extern char fmageren_name2[512]; extern unsigned int RX_DMA_BUFFER[4][NB_ANTENNAS_RX]; extern unsigned int TX_DMA_BUFFER[4][NB_ANTENNAS_TX]; -//#include "PHY/LTE_TRANSPORT/transport_extern.h" +extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; +extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern const short conjugate[8],conjugate2[8]; extern int number_of_cards; @@ -49,9 +55,6 @@ extern unsigned char primary_synch2_tab[72]; extern int16_t *primary_synch0_time; //!< index: [0..ofdm_symbol_size*2[ extern int16_t *primary_synch1_time; //!< index: [0..ofdm_symbol_size*2[ extern int16_t *primary_synch2_time; //!< index: [0..ofdm_symbol_size*2[ -extern int *sync_corr_ue0; //!< index [0..10*samples_per_tti[ -extern int *sync_corr_ue1; //!< index [0..10*samples_per_tti[ -extern int *sync_corr_ue2; //!< index [0..10*samples_per_tti[ extern int flagMag; //extern short **txdataF_rep_tmp; @@ -60,12 +63,6 @@ extern char mode_string[4][20]; extern unsigned char NB_RU; -#ifndef OPENAIR2 -extern unsigned char NB_eNB_INST; -extern uint16_t NB_UE_INST; -extern unsigned char NB_RN_INST; -#endif - extern int flag_LA; extern double sinr_bler_map[MCS_COUNT][2][MCS_TABLE_LENGTH_MAX]; extern double sinr_bler_map_up[MCS_COUNT][2][16]; @@ -108,5 +105,8 @@ extern unsigned short Nb_81_110[8][4]; extern uint16_t hundred_times_log10_NPRB[100]; extern uint8_t alpha_lut[8]; extern uint8_t max_turbo_iterations; + +extern double cpuf; + #endif /*__PHY_EXTERN_H__ */ diff --git a/openair1/PHY/phy_extern_ue.h b/openair1/PHY/phy_extern_ue.h index 622551c2fe..cff03e375d 100644 --- a/openair1/PHY/phy_extern_ue.h +++ b/openair1/PHY/phy_extern_ue.h @@ -23,7 +23,6 @@ #define __PHY_EXTERN_UE__H__ #include "PHY/defs_UE.h" -#include "common/ran_context.h" extern char* namepointer_chMag ; extern char* namepointer_log2; @@ -47,12 +46,6 @@ extern short primary_synch2[144]; extern unsigned char primary_synch0_tab[72]; extern unsigned char primary_synch1_tab[72]; extern unsigned char primary_synch2_tab[72]; -extern int16_t *primary_synch0_time; //!< index: [0..ofdm_symbol_size*2[ -extern int16_t *primary_synch1_time; //!< index: [0..ofdm_symbol_size*2[ -extern int16_t *primary_synch2_time; //!< index: [0..ofdm_symbol_size*2[ -extern int *sync_corr_ue0; //!< index [0..10*samples_per_tti[ -extern int *sync_corr_ue1; //!< index [0..10*samples_per_tti[ -extern int *sync_corr_ue2; //!< index [0..10*samples_per_tti[ extern int flagMag; //extern short **txdataF_rep_tmp; @@ -60,12 +53,6 @@ extern int flagMag; extern char mode_string[4][20]; -#ifndef OPENAIR2 -extern unsigned char NB_eNB_INST; -extern uint16_t NB_UE_INST; -extern unsigned char NB_RN_INST; -#endif - extern int flag_LA; extern double sinr_bler_map[MCS_COUNT][2][MCS_TABLE_LENGTH_MAX]; extern double sinr_bler_map_up[MCS_COUNT][2][16]; diff --git a/openair1/PHY/phy_vars.h b/openair1/PHY/phy_vars.h index 5e2be8bd8f..5879784827 100644 --- a/openair1/PHY/phy_vars.h +++ b/openair1/PHY/phy_vars.h @@ -25,7 +25,6 @@ #include "PHY/types.h" #include "PHY/defs_eNB.h" #include "PHY/defs_UE.h" -#include "common/ran_context.h" char* namepointer_chMag ; char fmageren_name2[512]; @@ -33,17 +32,15 @@ char* namepointer_log2; #include "PHY/LTE_REFSIG/primary_synch.h" -int16_t *primary_synch0_time; -int16_t *primary_synch1_time; -int16_t *primary_synch2_time; #include "PHY/LTE_TRANSPORT/transport_vars.h" #include "PHY/MODULATION/modulation_vars.h" +#include "nfapi/oai_integration/vendor_ext.h" + PHY_VARS_UE ***PHY_vars_UE_g; -RAN_CONTEXT_t RC; UL_RCC_IND_t UL_RCC_INFO; unsigned short rev[2048],rev_times4[8192],rev_half[1024]; @@ -58,13 +55,6 @@ const short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; unsigned char NB_RU=0; -#ifndef OPENAIR2 -//unsigned char NB_eNB_INST=0; -//uint16_t NB_UE_INST=0; -//unsigned char NB_RN_INST=0; -//unsigned char NB_INST=0; -#endif - int number_of_cards; diff --git a/openair1/PHY/phy_vars_nr_ue.h b/openair1/PHY/phy_vars_nr_ue.h index baa64561f0..cfdfbeb49d 100644 --- a/openair1/PHY/phy_vars_nr_ue.h +++ b/openair1/PHY/phy_vars_nr_ue.h @@ -57,13 +57,6 @@ const short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; unsigned char NB_RU=0; -#ifndef OPENAIR2 -unsigned char NB_eNB_INST=0; -uint16_t NB_UE_INST=0; -unsigned char NB_RN_INST=0; -unsigned char NB_INST=0; -#endif - int number_of_cards; diff --git a/openair1/PHY/phy_vars_ue.h b/openair1/PHY/phy_vars_ue.h index e90c2641aa..ca35ab6629 100644 --- a/openair1/PHY/phy_vars_ue.h +++ b/openair1/PHY/phy_vars_ue.h @@ -33,9 +33,6 @@ char *namepointer_log2; #include "PHY/LTE_REFSIG/primary_synch.h" -int16_t *primary_synch0_time; -int16_t *primary_synch1_time; -int16_t *primary_synch2_time; PHY_VARS_UE ***PHY_vars_UE_g; @@ -50,14 +47,6 @@ const short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; #include "SIMULATION/ETH_TRANSPORT/vars.h" -#ifndef OPENAIR2 - unsigned char NB_eNB_INST=0; - uint16_t NB_UE_INST=0; - unsigned char NB_RN_INST=0; - unsigned char NB_INST=0; -#endif - - int number_of_cards; diff --git a/openair1/PHY/thread_NR_UE.h b/openair1/PHY/thread_NR_UE.h index 94271ed55d..901d8faec9 100644 --- a/openair1/PHY/thread_NR_UE.h +++ b/openair1/PHY/thread_NR_UE.h @@ -4,26 +4,18 @@ #include /// Context data structure for RX/TX portion of subframe processing typedef struct { - /// index of the current UE RX/TX proc - int proc_id; + /// index of the current UE RX/TX thread + int thread_id; /// Component Carrier index uint8_t CC_id; /// timestamp transmitted to HW openair0_timestamp timestamp_tx; //#ifdef UE_NR_PHY_DEMO - /// NR TTI index within subframe_tx [0 .. ttis_per_subframe - 1] to act upon for transmission - int nr_tti_tx; - /// NR TTI index within subframe_rx [0 .. ttis_per_subframe - 1] to act upon for reception - int nr_tti_rx; /// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission int nr_slot_tx; /// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission int nr_slot_rx; //#endif - /// subframe to act upon for transmission - int subframe_tx; - /// subframe to act upon for reception - int subframe_rx; /// frame to act upon for transmission int frame_tx; /// frame to act upon for reception diff --git a/openair1/PHY/types.h b/openair1/PHY/types.h index c0a9af388c..8d8d9db2de 100644 --- a/openair1/PHY/types.h +++ b/openair1/PHY/types.h @@ -23,6 +23,6 @@ #define __openair_TYPES_H__ #include - +#define MAKE_VERSION(a,b,c) ((a)*256+(b)*16+c) #endif /*__openair_TYPES_H__ */ diff --git a/openair1/PHY/types_NB_IoT.h b/openair1/PHY/types_NB_IoT.h index 6735092583..e41129169c 100644 --- a/openair1/PHY/types_NB_IoT.h +++ b/openair1/PHY/types_NB_IoT.h @@ -22,11 +22,6 @@ #ifndef __openair_TYPES_NB_IOT_H__ #define __openair_TYPES_NB_IOT_H__ -#ifdef USER_MODE #include -#else -#include -#endif - #endif /*__openair_TYPES_NB_IOT_H__ */ diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index 96a073fbb8..ecfec02193 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -32,11 +32,15 @@ #include "PHY/defs_eNB.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "PHY/LTE_TRANSPORT/transport_extern.h" #include "SCHED/sched_eNB.h" #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi_pnf_interface.h" #include "fapi_l1.h" +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req); int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req); int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req); @@ -209,13 +213,13 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro UE_id = find_dlsch(rel8->rnti,eNB,SEARCH_EXIST_OR_FREE); - if( (UE_id<0) || (UE_id>=NUMBER_OF_UE_MAX) ) { + if( (UE_id<0) || (UE_id>=NUMBER_OF_DLSCH_MAX) ) { LOG_E(PHY,"illegal UE_id found!!! rnti %04x UE_id %d\n",rel8->rnti,UE_id); return; } //AssertFatal(UE_id!=-1,"no free or exiting dlsch_context\n"); - //AssertFatal(UE_id= %d(NUMBER_OF_UE_MAX)\n",UE_id,NUMBER_OF_UE_MAX); + //AssertFatal(UE_id= %d(NUMBER_OF_DLSCHMAX)\n",UE_id,NUMBER_OF_DLSCH_MAX); dlsch0 = eNB->dlsch[UE_id][0]; dlsch1 = eNB->dlsch[UE_id][1]; @@ -291,7 +295,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro if ((rel13->pdsch_payload_type <2) && (rel13->ue_type>0)) { // this is a BR/CE UE and SIB1-BR/SI-BR UE_id = find_dlsch(rel8->rnti,eNB,SEARCH_EXIST_OR_FREE); AssertFatal(UE_id!=-1,"no free or exiting dlsch_context\n"); - AssertFatal(UE_id= %d(NUMBER_OF_UE_MAX)\n",UE_id,NUMBER_OF_UE_MAX); + AssertFatal(UE_id= %d(NUMBER_OF_DLSCH_MAX)\n",UE_id,NUMBER_OF_DLSCH_MAX); dlsch0 = eNB->dlsch[UE_id][0]; dlsch0->harq_mask = 1; dlsch0_harq = dlsch0->harq_processes[0]; @@ -366,7 +370,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro } else { UE_id = find_dlsch(rel8->rnti,eNB,SEARCH_EXIST_OR_FREE); AssertFatal(UE_id!=-1,"no free or exiting dlsch_context\n"); - AssertFatal(UE_id= %d(NUMBER_OF_UE_MAX)\n",UE_id,NUMBER_OF_UE_MAX); + AssertFatal(UE_id= %d(NUMBER_OF_DLSCH_MAX)\n",UE_id,NUMBER_OF_DLSCH_MAX); dlsch0 = eNB->dlsch[UE_id][0]; dlsch1 = eNB->dlsch[UE_id][1]; dlsch0->sib1_br_flag=0; @@ -596,7 +600,7 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB, uci->frame = frame; uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti; - uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); uci->type = SR; uci->pucch_fmt = pucch_format1; uci->num_antenna_ports = 1; @@ -622,7 +626,7 @@ void handle_uci_sr_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_ uci->frame = frame; uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti; - uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); uci->type = HARQ_SR; uci->num_antenna_ports = 1; uci->num_pucch_resources = 1; @@ -660,7 +664,7 @@ void handle_srs_pdu(PHY_VARS_eNB *eNB,nfapi_ul_config_request_pdu_t *ul_config_p if (NFAPI_MODE==NFAPI_MODE_VNF) return; - for (i=0; isoundingrs_ul_config_dedicated[i].active==1) continue; eNB->soundingrs_ul_config_dedicated[i].active = 1; @@ -676,7 +680,7 @@ void handle_srs_pdu(PHY_VARS_eNB *eNB,nfapi_ul_config_request_pdu_t *ul_config_p break; } - AssertFatal(imodule_id; @@ -780,7 +785,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc) { nfapi_dl_config_request_pdu_t *dl_config_pdu; nfapi_hi_dci0_request_pdu_t *hi_dci0_req_pdu; nfapi_ul_config_request_pdu_t *ul_config_pdu; - int i; + eNB->pdcch_vars[subframe&1].num_pdcch_symbols = number_pdcch_ofdm_symbols; eNB->pdcch_vars[subframe&1].num_dci = 0; eNB->phich_vars[subframe&1].num_hi = 0; @@ -811,8 +816,8 @@ void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc) { // clear DCI allocation maps for new subframe if (NFAPI_MODE!=NFAPI_MODE_VNF) - for (i=0; iulsch[i]) { + for (int i=0; iulsch[i]!=NULL) { ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; ulsch_harq->dci_alloc=0; ulsch_harq->rar_alloc=0; @@ -820,7 +825,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc) { } } - for (i=0; idl_config_request_body.dl_config_pdu_list[i]; //LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_config_pdu->pdu_type); @@ -969,7 +974,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc) { } if (NFAPI_MODE!=NFAPI_MODE_VNF) - for (i=0; ihi_dci0_request_body.hi_dci0_pdu_list[i]; LOG_D(PHY,"NFAPI: hi_dci0_pdu %d : type %d\n",i,hi_dci0_req_pdu->pdu_type); @@ -992,14 +997,35 @@ void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc) { if (NFAPI_MODE!=NFAPI_MONOLITHIC) { if (number_ul_pdu>0) { - //LOG_D(PHY, "UL_CONFIG to send to PNF\n"); - UL_req->sfn_sf = frame << 4 | subframe; - oai_nfapi_ul_config_req(UL_req); - UL_req->ul_config_request_body.number_of_pdus=0; - number_ul_pdu=0; + uint8_t ulsch_pdu_num = 0; + for (int i=0; iul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE) || + (UL_req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) || + (UL_req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) || + (UL_req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE)){ + ulsch_pdu_num++; + } + } + if (RC.mac[Mod_id]->scheduler_mode == SCHED_MODE_DEFAULT) { + //LOG_D(PHY, "UL_CONFIG to send to PNF\n"); + UL_req->sfn_sf = frame << 4 | subframe; + oai_nfapi_ul_config_req(UL_req); + UL_req->ul_config_request_body.number_of_pdus=0; + number_ul_pdu=0; + }else if (RC.mac[Mod_id]->scheduler_mode == SCHED_MODE_FAIR_RR) { + if(ulsch_pdu_num <= RC.rrc[Mod_id]->configuration.radioresourceconfig[CC_id].ue_multiple_max){ + UL_req->sfn_sf = frame << 4 | subframe; + oai_nfapi_ul_config_req(UL_req); + UL_req->ul_config_request_body.number_of_pdus=0; + number_ul_pdu=0; + }else{ + LOG_E(MAC,"NFAPI: frame %d subframe %d ul_req num %d ul pdu %d\n", + frame,subframe,number_ul_pdu,ulsch_pdu_num); + } + } } } else { - for (i=0; iul_config_request_body.ul_config_pdu_list[i]; LOG_D(PHY,"NFAPI: ul_pdu %d : type %d\n",i,ul_config_pdu->pdu_type); AssertFatal(ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE || diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h index 4da1fa63ec..60ef5e764a 100644 --- a/openair1/SCHED/fapi_l1.h +++ b/openair1/SCHED/fapi_l1.h @@ -31,7 +31,6 @@ */ #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" #include "SCHED/sched_eNB.h" #include "SCHED/sched_common.h" @@ -62,6 +61,8 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame,uint8_t subframe,uint8_t srs_present); +void handle_nfapi_hi_dci0_dci_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc, + nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu); void handle_ulsch_harq_pdu( PHY_VARS_eNB *eNB, int UE_id, @@ -69,7 +70,9 @@ void handle_ulsch_harq_pdu( nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t frame, uint8_t subframe); - +void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, + nfapi_dl_config_request_pdu_t *dl_config_pdu, + uint8_t *sdu) ; void handle_ulsch_cqi_ri_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu_t *ul_config_pdu,uint16_t frame,uint8_t subframe); void handle_uci_harq_information(PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci,nfapi_ul_config_harq_information *harq_information); @@ -81,4 +84,4 @@ void handle_uci_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu void handle_srs_pdu(PHY_VARS_eNB *eNB,nfapi_ul_config_request_pdu_t *ul_config_pdu,uint16_t frame,uint8_t subframe); -void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); +void schedule_response(Sched_Rsp_t *Sched_INFO, void *proc); diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c new file mode 100644 index 0000000000..4e82c3ecb3 --- /dev/null +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -0,0 +1,55 @@ +//Dummy NR defs to avoid linking errors + +#include "PHY/defs_gNB.h" +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" +#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" +#include "openair1/PHY/LTE_TRANSPORT/transport_common.h" + +void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){} + +void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){} + +int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type){return 0;} +void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, + nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, + uint8_t *sdu){ +} +void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ + } +int l1_north_init_gNB(void){return 0;} + +uint8_t slot_ahead=6; +//uint8_t nfapi_mode=0; +NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} + +void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){} +void nr_fill_ulsch(PHY_VARS_gNB *gNB, + int frame, + int slot, + nfapi_nr_pusch_pdu_t *ulsch_pdu){} +void nr_fill_pucch(PHY_VARS_gNB *gNB, + int frame, + int slot, + nfapi_nr_pucch_pdu_t *pucch_pdu){} +void nr_fill_prach(PHY_VARS_gNB *gNB, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu){} +void nr_fill_prach_ru(RU_t *ru, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu){} + +void nr_phy_config_request(NR_PHY_Config_t *gNB){} + +void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} + +void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} + diff --git a/openair1/SCHED/nfapi_nr_dummy.c b/openair1/SCHED/nfapi_nr_dummy.c new file mode 100644 index 0000000000..511911723f --- /dev/null +++ b/openair1/SCHED/nfapi_nr_dummy.c @@ -0,0 +1,55 @@ +//Dummy NR defs to avoid linking errors + +#include "PHY/defs_gNB.h" +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" +#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" +#include "openair1/PHY/LTE_TRANSPORT/transport_common.h" + +void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){} + +void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){} + +int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type){return 0;} +void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, + nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, + uint8_t *sdu){ +} +void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ + } +int l1_north_init_gNB(void){return 0;} + +uint8_t slot_ahead=6; +//uint8_t nfapi_mode=0; +NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} + +void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){} +void nr_fill_ulsch(PHY_VARS_gNB *gNB, + int frame, + int slot, + nfapi_nr_pusch_pdu_t *ulsch_pdu){} +void nr_fill_pucch(PHY_VARS_gNB *gNB, + int frame, + int slot, + nfapi_nr_pucch_pdu_t *pucch_pdu){} +void nr_fill_prach(PHY_VARS_gNB *gNB, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu){} +void nr_fill_prach_ru(RU_t *ru, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu){} + +void nr_phy_config_request(NR_PHY_Config_t *gNB){} + +void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} + +//void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} + diff --git a/openair1/SCHED/phy_procedures_lte_common.c b/openair1/SCHED/phy_procedures_lte_common.c index d162a413c1..7033c52701 100644 --- a/openair1/SCHED/phy_procedures_lte_common.c +++ b/openair1/SCHED/phy_procedures_lte_common.c @@ -1085,73 +1085,3 @@ void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeri } } - -// uint8_t eNB_id,uint8_t harq_pid, uint8_t UE_id, -int16_t estimate_ue_tx_power(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs) -{ - - /// The payload + CRC size in bits, "B" - uint32_t B; - /// Number of code segments - uint32_t C; - /// Number of "small" code segments - uint32_t Cminus; - /// Number of "large" code segments - uint32_t Cplus; - /// Number of bits in "small" code segments (<6144) - uint32_t Kminus; - /// Number of bits in "large" code segments (<6144) - uint32_t Kplus; - /// Total number of bits across all segments - uint32_t sumKr; - /// Number of "Filler" bits - uint32_t F; - // num resource elements - uint32_t num_re=0.0; - // num symbols - uint32_t num_symb=0.0; - /// effective spectral efficiency of the PUSCH - uint32_t MPR_x100=0; - /// beta_offset - uint16_t beta_offset_pusch_x8=8; - /// delta mcs - float delta_mcs=0.0; - /// bandwidth factor - float bw_factor=0.0; - - B= tbs+24; - lte_segmentation(NULL, - NULL, - B, - &C, - &Cplus, - &Cminus, - &Kplus, - &Kminus, - &F); - - - sumKr = Cminus*Kminus + Cplus*Kplus; - num_symb = 12-(ncp<<1)-(use_srs==0?0:1); - num_re = num_symb * nb_rb * 12; - - if (num_re == 0) - return(0); - - MPR_x100 = 100*sumKr/num_re; - - if (control_only == 1 ) - beta_offset_pusch_x8=8; // fixme - - //(beta_offset_pusch_x8=ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? ue->ulsch[eNB_id]->beta_offset_cqi_times8:8; - - // if deltamcs_enabledm - delta_mcs = ((hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch_x8)>>3))/100.0); - bw_factor = (hundred_times_log10_NPRB[nb_rb-1]/100.0); -#ifdef DEBUG_SEGMENTATION - printf("estimated ue tx power %d (num_re %d, sumKr %d, mpr_x100 %d, delta_mcs %f, bw_factor %f)\n", - (int16_t)ceil(delta_mcs + bw_factor), num_re, sumKr, MPR_x100, delta_mcs, bw_factor); -#endif - return (int16_t)ceil(delta_mcs + bw_factor); - -} diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index b3e3ab8c4e..973c921d23 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -40,6 +40,7 @@ #include "common/utils/LOG/log.h" #include #include "common/utils/LOG/vcd_signal_dumper.h" +#include #include "assertions.h" #include "msc.h" @@ -51,22 +52,24 @@ #define MBMS_NFAPI_SCHEDULER -nfapi_ue_release_request_body_t release_rntis; +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; -int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t UE_id,uint8_t harq_pid, uint8_t bw_factor) { + +int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t ULSCH_id,uint8_t harq_pid, uint8_t bw_factor) { uint32_t Nre,sumKr,MPR_x100,Kr,r; uint16_t beta_offset_pusch; - DevAssert( UE_id < NUMBER_OF_UE_MAX+1 ); + DevAssert( ULSCH_id < NUMBER_OF_ULSCH_MAX+1 ); DevAssert( harq_pid < 8 ); - Nre = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_initial * - eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12; + Nre = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->Nsymb_initial * + eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->nb_rb*12; sumKr = 0; - for (r=0; rulsch[UE_id]->harq_processes[harq_pid]->C; r++) { - if (rulsch[UE_id]->harq_processes[harq_pid]->Cminus) - Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kminus; + for (r=0; rulsch[ULSCH_id]->harq_processes[harq_pid]->C; r++) { + if (rulsch[ULSCH_id]->harq_processes[harq_pid]->Cminus) + Kr = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->Kminus; else - Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus; + Kr = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->Kplus; sumKr += Kr; } @@ -79,17 +82,17 @@ int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t UE_id,uint8_t // FK 20140908 sumKr is only set after the ulsch_encoding beta_offset_pusch = 8; //(eNB->ulsch[UE_id]->harq_processes[harq_pid]->control_only == 1) ? eNB->ulsch[UE_id]->beta_offset_cqi_times8:8; - DevAssert( UE_id < NUMBER_OF_UE_MAX ); + DevAssert( ULSCH_id < NUMBER_OF_ULSCH_MAX ); //#warning "This condition happens sometimes. Need more investigation" // navid //DevAssert( MPR_x100/6 < 100 ); if (1==1) { //eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled == 1) { // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch) if (bw_factor == 1) { - uint8_t nb_rb = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb; - return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)) + hundred_times_log10_NPRB[nb_rb-1]; + uint8_t nb_rb = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->nb_rb; + return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_x10((beta_offset_pusch)>>3)) + hundred_times_log10_NPRB[nb_rb-1]; } else - return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)); + return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_x10((beta_offset_pusch)>>3)); } else { return(0); } @@ -97,21 +100,21 @@ int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t UE_id,uint8_t int16_t get_hundred_times_delta_IF_mac(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t harq_pid) { - int8_t UE_id; + int8_t ULSCH_id; if ((RC.eNB == NULL) || (module_idP > RC.nb_inst) || (CC_id > RC.nb_CC[module_idP])) { LOG_E(PHY,"get_UE_stats: No eNB found (or not allocated) for Mod_id %d,CC_id %d\n",module_idP,CC_id); return -1; } - UE_id = find_ulsch( rnti, RC.eNB[module_idP][CC_id],SEARCH_EXIST); + ULSCH_id = find_ulsch( rnti, RC.eNB[module_idP][CC_id],SEARCH_EXIST); - if (UE_id == -1) { + if (ULSCH_id == -1) { // not found return 0; } - return get_hundred_times_delta_IF_eNB( RC.eNB[module_idP][CC_id], UE_id, harq_pid, 0 ); + return get_hundred_times_delta_IF_eNB( RC.eNB[module_idP][CC_id], ULSCH_id, harq_pid, 0 ); } int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); @@ -244,8 +247,15 @@ void common_signal_procedures_fembms (PHY_VARS_eNB *eNB,int frame, int subframe) eNB->pbch_configured=0; } - T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), - T_BUFFER(pbch_pdu, 3)); + if (T_ACTIVE(T_ENB_PHY_MIB)) { + /* MIB is stored in reverse in pbch_pdu, reverse it for properly logging */ + uint8_t mib[3]; + mib[0] = pbch_pdu[2]; + mib[1] = pbch_pdu[1]; + mib[2] = pbch_pdu[0]; + T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), + T_BUFFER(mib, 3)); + } generate_pbch_fembms (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, (frame & 15)/4); } //else if ((subframe == 1) && (fp->frame_type == TDD)) { //generate_pss (txdataF, AMP, fp, 2, 2); @@ -313,8 +323,15 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) { eNB->pbch_configured=0; } - T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), - T_BUFFER(pbch_pdu, 3)); + if (T_ACTIVE(T_ENB_PHY_MIB)) { + /* MIB is stored in reverse in pbch_pdu, reverse it for properly logging */ + uint8_t mib[3]; + mib[0] = pbch_pdu[2]; + mib[1] = pbch_pdu[1]; + mib[2] = pbch_pdu[0]; + T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), + T_BUFFER(mib, 3)); + } generate_pbch (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, frame & 3); } else if ((subframe == 1) && (fp->frame_type == TDD)) { generate_pss (txdataF, AMP, fp, 2, 2); @@ -485,9 +502,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, int do_meas) { int frame=proc->frame_tx; int subframe=proc->subframe_tx; - uint32_t i,aa; uint8_t harq_pid; - int16_t UE_id=0; uint8_t num_pdcch_symbols=0; uint8_t num_dci=0; uint8_t num_mdci = 0; @@ -502,12 +517,15 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(eNB->CC_id),1); if (do_meas==1) start_meas(&eNB->phy_proc_tx); - if (do_meas==1) start_meas(&eNB->dlsch_common_and_dci); // clear the transmit data array for the current subframe - for (aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { - memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti)], 0, fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); + for (int aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { + if (eNB->use_DTX==0) + memcpy(&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti)], + &eNB->subframe_mask[aa][subframe*fp->ofdm_symbol_size*fp->symbols_per_tti], + fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); + else memset(&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti)], 0, fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); } if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { @@ -542,7 +560,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); // clear previous allocation information for all UEs - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + for (volatile int i = 0; i < NUMBER_OF_DLSCH_MAX; i++) { if (eNB->dlsch[i][0]) eNB->dlsch[i][0]->subframe_tx[subframe] = 0; } @@ -551,7 +569,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, //if ((ul_subframe < 10)&& // (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here - for (i=0; iulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; else @@ -637,9 +655,9 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, // Now scan UE specific DLSCH LTE_eNB_DLSCH_t *dlsch0,*dlsch1; - for (UE_id=0; UE_iddlsch[(uint8_t)UE_id][0]; - dlsch1 = eNB->dlsch[(uint8_t)UE_id][1]; + for (int DLSCH_id=0; DLSCH_iddlsch[(uint8_t)DLSCH_id][0]; + dlsch1 = eNB->dlsch[(uint8_t)DLSCH_id][1]; if ((dlsch0)&&(dlsch0->rnti>0)&& #ifdef PHY_TX_THREAD @@ -649,12 +667,13 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #endif ) { // get harq_pid - harq_pid = dlsch0->harq_ids[frame%2][subframe]; + harq_pid = dlsch0->harq_ids[frame%2][subframe]; //AssertFatal(harq_pid>=0,"harq_pid is negative\n"); if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) { + if (dlsch0->ue_type==0) - LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x [ %1d.%1d.%1d.%1d.%1d.%1d.%1d.%1d\n", harq_pid,UE_id,frame,subframe,dlsch0->rnti, + LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 DLSCH_id:%d frame:%d subframe:%d rnti:%x [ %1d.%1d.%1d.%1d.%1d.%1d.%1d.%1d\n", harq_pid,DLSCH_id,frame,subframe,dlsch0->rnti, dlsch0->harq_ids[frame%2][0], dlsch0->harq_ids[frame%2][1], dlsch0->harq_ids[frame%2][2], @@ -668,7 +687,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, proc, harq_pid, dlsch0, - &eNB->UE_stats[(uint32_t)UE_id])) { + &eNB->UE_stats[(uint32_t)DLSCH_id])) { // if we generate dlsch, we must generate pdsch pdsch_procedures(eNB, proc, @@ -703,6 +722,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if (do_meas==1) stop_meas(&eNB->phy_proc_tx); } +/* This has to be updated with FAPI structures*/ void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; @@ -714,7 +734,7 @@ void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { // Do SRS processing // check if there is SRS and we have to use shortened format // TODO: check for exceptions in transmission of SRS together with ACK/NACK - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + for (i = 0; i < NUMBER_OF_SRS_MAX; i++) { if (eNB->soundingrs_ul_config_dedicated[i].active == 1) { if (lte_srs_channel_estimation (fp, &eNB->common_vars, &eNB->srs_vars[i], &eNB->soundingrs_ul_config_dedicated[i], subframe, 0 /*eNB_id */ )) { LOG_E (PHY, "problem processing SRS\n"); @@ -743,8 +763,8 @@ void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int // pdu->rx_ue_information.handle = handle; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; - int SNRtimes10 = dB_fixed_times10(stat) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; - LOG_D(PHY,"stat %d subbandpower %d, SNRtimes10 %d\n", stat, eNB->measurements.n0_subband_power_dB[0][0], SNRtimes10); + int SNRtimes10 = dB_fixed_x10(stat) - 10 * eNB->measurements.n0_pucch_dB; + LOG_D(PHY,"stat %d n0 %d, SNRtimes10 %d\n", stat, eNB->measurements.n0_subband_power_dB[0][0], SNRtimes10); pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; if (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0; @@ -777,7 +797,9 @@ uci_procedures(PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci = NULL; LTE_DL_FRAME_PARMS *fp = &(eNB->frame_parms); - for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) { + calc_pucch_1x_interference(eNB, frame, subframe, 0); + + for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) { uci = &(eNB->uci_vars[i]); if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) { @@ -834,7 +856,7 @@ uci_procedures(PHY_VARS_eNB *eNB, int pucch1_thres = (uci->ue_type == 0) ? eNB->pucch1_DTX_threshold : eNB->pucch1_DTX_threshold_emtc[0]; metric_SR = rx_pucch(eNB, uci->pucch_fmt, - uci->ue_id, + i,//uci->ue_id, uci->n_pucch_1_0_sr[0], 0, // n2_pucch uci->srs_active, // shortened format @@ -1259,7 +1281,7 @@ uci_procedures(PHY_VARS_eNB *eNB, #ifdef DEBUG_PHY_PROC LOG_D (PHY, "[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, (%d,%d)\n", eNB->Mod_id, - eNB->dlsch[UE_id][0]->rnti, frame, subframe, metric0, metric1, pucch_b0b1[0], pucch_b0b1[1]); + eNB->dlsch[DLSCH_id][0]->rnti, frame, subframe, metric0, metric1, pucch_b0b1[0], pucch_b0b1[1]); #endif } @@ -1282,7 +1304,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } } } // end if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) { - } // end loop for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + } // end loop for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) { } void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { @@ -1309,7 +1331,7 @@ void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { int nb=abortTpool(proc->threadPool, req->key); nb+=abortNotifiedFIFO(proc->respDecode, req->key); proc->nbDecode-=nb; - LOG_I(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); + LOG_D(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", ulsch_harq->processedSegments, nb, rdata->nbSegments); ulsch_harq->processedSegments=rdata->nbSegments; @@ -1365,6 +1387,15 @@ void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { fill_rx_indication(eNB,i,rdata->frame,rdata->subframe); // indicate SDU to MAC ulsch_harq->status = SCH_IDLE; ulsch->harq_mask &= ~(1 << rdata->harq_pid); + for (int j=0;julsch_stats[j].rnti == ulsch->rnti) { + eNB->ulsch_stats[j].total_bytes_rx+=ulsch_harq->TBS; + for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) { + eNB->ulsch_stats[j].ulsch_power[aa] = dB_fixed_x10(eNB->pusch_vars[rdata->UEid]->ulsch_power[aa]); + eNB->ulsch_stats[j].ulsch_noise_power[aa] = dB_fixed_x10(eNB->pusch_vars[rdata->UEid]->ulsch_noise_power[aa]); + } + break; + } T (T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(rdata->frame), T_INT(rdata->subframe), T_INT(ulsch->rnti), T_INT(rdata->harq_pid)); } // ulsch not in error @@ -1385,8 +1416,9 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { const int frame = proc->frame_rx; uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + for (i = 0; i < NUMBER_OF_ULSCH_MAX; i++) { ulsch = eNB->ulsch[i]; + if (!ulsch) continue; if (ulsch->ue_type > 0) harq_pid = 0; else harq_pid=harq_pid0; @@ -1395,10 +1427,9 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { if (ulsch->rnti>0) LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", i, harq_pid, frame,subframe,i,ulsch->rnti, - ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); - if ((ulsch) && - (ulsch->rnti>0) && + if ((ulsch->rnti>0) && (ulsch_harq->status == ACTIVE) && ((ulsch_harq->frame == frame) || (ulsch_harq->repetition_number >1) ) && ((ulsch_harq->subframe == subframe) || (ulsch_harq->repetition_number >1) ) && @@ -1443,6 +1474,17 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { ulsch_harq->V_UL_DAI, ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); +/* + int ulsch_id=-1; + for (ulsch_id=0;ulsch_idrnti == eNB->ulsch_stats[ulsch_id].rnti) break; + AssertFatal(ulsch_id>=0,"no ulsch_id found\n"); + + if (eNB->ulsch_stats[ulsch_id].round_trials[0]>100) { + dump_ulsch(eNB,frame,subframe,i,ulsch_harq->round); + AssertFatal(1==0,"exiting\n"); + } +*/ } else if ((ulsch) && (ulsch->rnti>0) && @@ -1456,7 +1498,7 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { ulsch->harq_mask &= ~(1 << harq_pid); LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); } - } // for (i=0; inbDecode > 0) { notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool); @@ -1521,7 +1563,7 @@ void kill_te_thread(PHY_VARS_eNB *eNB) { } void fill_rx_indication(PHY_VARS_eNB *eNB, - int UE_id, + int ULSCH_id, int frame, int subframe) { nfapi_rx_indication_pdu_t *pdu; @@ -1529,7 +1571,7 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, int sync_pos; uint32_t harq_pid; - if (eNB->ulsch[UE_id]->ue_type > 0) harq_pid = 0; + if (eNB->ulsch[ULSCH_id]->ue_type > 0) harq_pid = 0; else { harq_pid = subframe2harq_pid (&eNB->frame_parms, frame, subframe); @@ -1539,19 +1581,22 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, eNB->UL_INFO.rx_ind.sfn_sf = frame<<4| subframe; eNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG; pdu = &eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus]; - // pdu->rx_ue_information.handle = eNB->ulsch[UE_id]->handle; + // pdu->rx_ue_information.handle = eNB->ulsch[ULSCH_id]->handle; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; - pdu->rx_ue_information.rnti = eNB->ulsch[UE_id]->rnti; + pdu->rx_ue_information.rnti = eNB->ulsch[ULSCH_id]->rnti; pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; - pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; + pdu->rx_indication_rel8.length = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->TBS>>3; pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation - pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->decodedBytes; + pdu->data = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->decodedBytes; // estimate timing advance for MAC - sync_pos = lte_est_timing_advance_pusch(&eNB->frame_parms, eNB->pusch_vars[UE_id]->drs_ch_estimates_time); - timing_advance_update = sync_pos; // - eNB->frame_parms.nb_prefix_samples/4; //to check + sync_pos = lte_est_timing_advance_pusch(&eNB->frame_parms, eNB->pusch_vars[ULSCH_id]->drs_ch_estimates_time); + timing_advance_update = sync_pos; - // if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} - // if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} + for (int i=0;iulsch_stats[i].rnti == eNB->ulsch[ULSCH_id]->rnti) + eNB->ulsch_stats[i].timing_offset = sync_pos; + // if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,ULSCH_id); exit(-1);} + // if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,ULSCH_id); exit(-1);} switch (eNB->frame_parms.N_RB_DL) { case 6: /* nothing to do */ break; @@ -1590,8 +1635,14 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, timing_advance_update = 63; pdu->rx_indication_rel8.timing_advance = timing_advance_update; - // estimate UL_CQI for MAC (from antenna port 0 only) - int SNRtimes10 = dB_fixed_times10(eNB->pusch_vars[UE_id]->ulsch_power[0]) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; + // estimate UL_CQI for MAC + int total_power=0, avg_noise_power=0; + for (int i=0;iframe_parms.nb_antennas_rx;i++) { + total_power+=(eNB->pusch_vars[ULSCH_id]->ulsch_power[i]); + avg_noise_power+=(eNB->pusch_vars[ULSCH_id]->ulsch_noise_power[i])/eNB->frame_parms.nb_antennas_rx; + } + int SNRtimes10 = dB_fixed_x10(total_power) - + dB_fixed_x10(avg_noise_power); if (SNRtimes10 < -640) pdu->rx_indication_rel8.ul_cqi = 0; @@ -1600,9 +1651,11 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, else pdu->rx_indication_rel8.ul_cqi = (640 + SNRtimes10) / 5; - LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d), timing_advance %d (update %d)\n", - harq_pid,frame,subframe,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,pdu->rx_indication_rel8.timing_advance, - timing_advance_update); + LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d,%d,%d), timing_advance %d (update %d,sync_pos %d)\n", + harq_pid,frame,subframe,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,dB_fixed_x10(total_power),dB_fixed_x10(avg_noise_power),pdu->rx_indication_rel8.timing_advance,timing_advance_update,sync_pos); + for (int i=0;iframe_parms.nb_antennas_rx;i++) + LOG_D(PHY,"antenna %d: ulsch_power %d, noise_power %d\n",i,dB_fixed_x10(eNB->pusch_vars[ULSCH_id]->ulsch_power[i]),dB_fixed_x10(eNB->pusch_vars[ULSCH_id]->ulsch_noise_power[i])); + eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++; eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe; pthread_mutex_unlock(&eNB->UL_INFO_mutex); @@ -1613,7 +1666,7 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, * Release the harq process if its round is >= 'after_rounds' */ static void do_release_harq(PHY_VARS_eNB *eNB, - int UE_id, + int DLSCH_id, int tb, uint16_t frame, uint8_t subframe, @@ -1628,10 +1681,10 @@ static void do_release_harq(PHY_VARS_eNB *eNB, int harq_pid; int subframe_tx; int frame_tx; - AssertFatal(UE_id != -1, "No existing dlsch context\n"); - AssertFatal(UE_id < NUMBER_OF_UE_MAX, "Returned UE_id %d >= %d (NUMBER_OF_UE_MAX)\n", UE_id, NUMBER_OF_UE_MAX); - dlsch0 = eNB->dlsch[UE_id][0]; - dlsch1 = eNB->dlsch[UE_id][1]; + AssertFatal(DLSCH_id != -1, "No existing dlsch context\n"); + AssertFatal(DLSCH_id < NUMBER_OF_DLSCH_MAX, "Returned DLSCH_id %d >= %d (NUMBER_OF_DLSCH_MAX)\n", DLSCH_id, NUMBER_OF_DLSCH_MAX); + dlsch0 = eNB->dlsch[DLSCH_id][0]; + dlsch1 = eNB->dlsch[DLSCH_id][1]; if (eNB->frame_parms.frame_type == FDD) { subframe_tx = (subframe + 6) % 10; @@ -1730,13 +1783,13 @@ static void do_release_harq(PHY_VARS_eNB *eNB, } // end if TDD } -static void release_harq(PHY_VARS_eNB *eNB,int UE_id,int tb,uint16_t frame,uint8_t subframe,uint16_t mask, int is_ack) { +static void release_harq(PHY_VARS_eNB *eNB,int DLSCH_id,int tb,uint16_t frame,uint8_t subframe,uint16_t mask, int is_ack) { /* * Maximum number of DL transmissions = 4. * TODO: get the value from configuration. * If is_ack is true then we release immediately. The value -1 can be used for that. */ - do_release_harq(eNB, UE_id, tb, frame, subframe, mask, is_ack ? -1 : 4); + do_release_harq(eNB, DLSCH_id, tb, frame, subframe, mask, is_ack ? -1 : 4); } int getM(PHY_VARS_eNB *eNB,int frame,int subframe) { @@ -1816,14 +1869,14 @@ void fill_ulsch_cqi_indication (PHY_VARS_eNB *eNB, uint16_t frame, uint8_t subfr } void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_harq, uint16_t rnti, int frame, int subframe, int bundling) { - int UE_id = find_dlsch(rnti,eNB,SEARCH_EXIST); + int DLSCH_id = find_dlsch(rnti,eNB,SEARCH_EXIST); - if( (UE_id<0) || (UE_id>=NUMBER_OF_UE_MAX) ) { - LOG_E(PHY,"illegal UE_id found!!! rnti %04x UE_id %d\n",rnti,UE_id); + if( (DLSCH_id<0) || (DLSCH_id>=NUMBER_OF_DLSCH_MAX) ) { + LOG_E(PHY,"illegal DLSCH_id found!!! rnti %04x DLSCH_id %d\n",rnti,DLSCH_id); return; } - //AssertFatal(UE_id>=0,"UE_id doesn't exist\n"); + //AssertFatal(DLSCH_id>=0,"DLSCH_id doesn't exist\n"); pthread_mutex_lock(&eNB->UL_INFO_mutex); nfapi_harq_indication_pdu_t *pdu = &eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list[eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs]; int M; @@ -1845,7 +1898,7 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har AssertFatal (ulsch_harq->o_ACK[i] == 0 || ulsch_harq->o_ACK[i] == 1, "harq_ack[%d] is %d, should be 1,2 or 4\n", i, ulsch_harq->o_ACK[i]); pdu->harq_indication_fdd_rel13.harq_tb_n[i] = 2 - ulsch_harq->o_ACK[i]; // release DLSCH if needed - release_harq(eNB,UE_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1); + release_harq(eNB,DLSCH_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1); } } else { // TDD M = ul_ACK_subframe2_M (&eNB->frame_parms, subframe); @@ -1861,14 +1914,14 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har * We have to release the proper HARQ in case of ACK or NACK if max retransmission reached. * Basically, call release_harq with 1 as last argument when ACK and 0 when NACK. */ - release_harq(eNB,UE_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1); + release_harq(eNB,DLSCH_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1); - if (M==1 && ulsch_harq->O_ACK==1 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,UE_id,0,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1); - else if (M==1 && ulsch_harq->O_ACK==2 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,UE_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1); + if (M==1 && ulsch_harq->O_ACK==1 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1); + else if (M==1 && ulsch_harq->O_ACK==2 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,DLSCH_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1); else if (M>1 && ulsch_harq->o_ACK[i] == 1) { // spatial bundling - release_harq(eNB,UE_id,0,frame,subframe,1<o_ACK[i] == 1); - release_harq(eNB,UE_id,1,frame,subframe,1<o_ACK[i] == 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,1<o_ACK[i] == 1); + release_harq(eNB,DLSCH_id,1,frame,subframe,1<o_ACK[i] == 1); } } } @@ -1884,10 +1937,10 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in return; } - int UE_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST); + int DLSCH_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST); - //AssertFatal(UE_id>=0,"UE_id doesn't exist rnti:%x\n", uci->rnti); - if (UE_id < 0) { + //AssertFatal(DLSCH_id>=0,"DLSCH_id doesn't exist rnti:%x\n", uci->rnti); + if (DLSCH_id < 0) { LOG_E(PHY,"SFN/SF:%04d%d Unable to find rnti:%x do not send HARQ\n", frame, subframe, uci->rnti); return; } @@ -1905,7 +1958,7 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in pdu->rx_ue_information.rnti = uci->rnti; // estimate UL_CQI for MAC (from antenna port 0 only) pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; - int SNRtimes10 = dB_fixed_times10(uci->stat) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; + int SNRtimes10 = dB_fixed_x10(uci->stat) - 10 * eNB->measurements.n0_pucch_dB; if (SNRtimes10 < -100) LOG_I (PHY, "uci->stat %d \n", uci->stat); @@ -1927,7 +1980,7 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in AssertFatal (harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n", harq_ack[0]); pdu->harq_indication_fdd_rel13.harq_tb_n[0] = harq_ack[0]; // release DLSCH if needed - release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1); } else if (uci->pucch_fmt == pucch_format1b) { pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG; pdu->harq_indication_fdd_rel13.mode = 0; @@ -1937,8 +1990,8 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in pdu->harq_indication_fdd_rel13.harq_tb_n[0] = harq_ack[0]; pdu->harq_indication_fdd_rel13.harq_tb_n[1] = harq_ack[1]; // release DLSCH if needed - release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1); - release_harq(eNB,UE_id,1,frame,subframe,0xffff, harq_ack[1] == 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1); + release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, harq_ack[1] == 1); } else AssertFatal(1==0,"only format 1a/b for now, received %d\n",uci->pucch_fmt); } else { // TDD AssertFatal (tdd_mapping_mode == 0 || tdd_mapping_mode == 1 || tdd_mapping_mode == 2, "Illegal tdd_mapping_mode %d\n", tdd_mapping_mode); @@ -1956,7 +2009,7 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n",harq_ack[0]); pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = harq_ack[0]; // release all bundled DLSCH if needed - release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1); } else if (uci->pucch_fmt == pucch_format1b) { pdu->harq_indication_tdd_rel13.number_of_ack_nack = 2; AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n",harq_ack[0]); @@ -1965,8 +2018,8 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = harq_ack[0]; pdu->harq_indication_tdd_rel13.harq_data[1].bundling.value_0 = harq_ack[1]; // release all DLSCH if needed - release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1); - release_harq(eNB,UE_id,1,frame,subframe,0xffff, harq_ack[1] == 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1); + release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, harq_ack[1] == 1); } break; @@ -1980,7 +2033,7 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n",harq_ack[0]); pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0]; // release all DLSCH if needed - release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1); } else if (uci->num_pucch_resources == 1 && uci->pucch_fmt == pucch_format1b) { pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG; pdu->harq_indication_tdd_rel13.number_of_ack_nack = 2; @@ -1989,8 +2042,8 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0]; pdu->harq_indication_tdd_rel13.harq_data[1].multiplex.value_0 = harq_ack[1]; // release all DLSCH if needed - release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1); - release_harq(eNB,UE_id,1,frame,subframe,0xffff, harq_ack[1] == 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1); + release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, harq_ack[1] == 1); } else { // num_pucch_resources (M) > 1 pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG; pdu->harq_indication_tdd_rel13.number_of_ack_nack = uci->num_pucch_resources; @@ -2002,8 +2055,8 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in if (uci->num_pucch_resources == 4) pdu->harq_indication_tdd_rel13.harq_data[3].multiplex.value_0 = harq_ack[3]; // spatial-bundling in this case so release both HARQ if necessary - release_harq(eNB,UE_id,0,frame,subframe,tdd_multiplexing_mask, 1 /* force release? previous code was unconditional */); - release_harq(eNB,UE_id,1,frame,subframe,tdd_multiplexing_mask, 1 /* force release? previous code was unconditional */); + release_harq(eNB,DLSCH_id,0,frame,subframe,tdd_multiplexing_mask, 1 /* force release? previous code was unconditional */); + release_harq(eNB,DLSCH_id,1,frame,subframe,tdd_multiplexing_mask, 1 /* force release? previous code was unconditional */); } break; @@ -2027,8 +2080,8 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in if (uci->num_pucch_resources == 1 || uci->num_pucch_resources == 4 || tdd_config5_sf2scheds == 1 || tdd_config5_sf2scheds == 4 || tdd_config5_sf2scheds == 7) { pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1; - release_harq(eNB,UE_id,0,frame,subframe,0xffff, 1); - release_harq(eNB,UE_id,1,frame,subframe,0xffff, 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, 1); + release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, 1); } else { pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0; } @@ -2039,8 +2092,8 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in if (uci->num_pucch_resources == 2 || tdd_config5_sf2scheds == 2 || tdd_config5_sf2scheds == 5 || tdd_config5_sf2scheds == 8) { pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1; - release_harq(eNB,UE_id,0,frame,subframe,0xffff, 1); - release_harq(eNB,UE_id,1,frame,subframe,0xffff, 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, 1); + release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, 1); } else { pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0; } @@ -2051,8 +2104,8 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in if (uci->num_pucch_resources == 3 || tdd_config5_sf2scheds == 3 || tdd_config5_sf2scheds == 6 || tdd_config5_sf2scheds == 9) { pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1; - release_harq(eNB,UE_id,0,frame,subframe,0xffff, 1); - release_harq(eNB,UE_id,1,frame,subframe,0xffff, 1); + release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, 1); + release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, 1); } else { pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0; } @@ -2069,7 +2122,7 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in pthread_mutex_unlock(&eNB->UL_INFO_mutex); } -void fill_crc_indication (PHY_VARS_eNB *eNB, int UE_id, int frame, int subframe, uint8_t crc_flag) { +void fill_crc_indication (PHY_VARS_eNB *eNB, int ULSCH_id, int frame, int subframe, uint8_t crc_flag) { pthread_mutex_lock(&eNB->UL_INFO_mutex); nfapi_crc_indication_pdu_t *pdu = &eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list[eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs]; eNB->UL_INFO.crc_ind.sfn_sf = frame<<4 | subframe; @@ -2078,7 +2131,7 @@ void fill_crc_indication (PHY_VARS_eNB *eNB, int UE_id, int frame, int subframe, pdu->instance_length = 0; // don't know what to do with this // pdu->rx_ue_information.handle = handle; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; - pdu->rx_ue_information.rnti = eNB->ulsch[UE_id]->rnti; + pdu->rx_ue_information.rnti = eNB->ulsch[ULSCH_id]->rnti; pdu->crc_indication_rel8.tl.tag = NFAPI_CRC_INDICATION_REL8_TAG; pdu->crc_indication_rel8.crc_flag = crc_flag; eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs++; @@ -2117,20 +2170,24 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements); - int min_I0=1000,max_I0=0; - if ((frame==0) && (subframe==4)) { - for (int i=0; iframe_parms.N_RB_UL; i++) { - if (i==(eNB->frame_parms.N_RB_UL>>1) - 1) i+=2; - - if (eNB->measurements.n0_subband_power_tot_dB[i]measurements.n0_subband_power_tot_dB[i]; - - if (eNB->measurements.n0_subband_power_tot_dB[i]>max_I0) max_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; - } - - LOG_I (PHY, "max_I0 %d, min_I0 %d\n", max_I0, min_I0); + // clear unused statistics after 2 seconds + for (int i=0;iulsch_stats[i].frame <= frame) { + if ((eNB->ulsch_stats[i].frame + 200) < frame) memset(&eNB->ulsch_stats[i],0,sizeof(eNB->ulsch_stats[i])); + } + else { + if (eNB->ulsch_stats[i].frame + 200 < (frame+1024)) memset(&eNB->ulsch_stats[i],0,sizeof(eNB->ulsch_stats[i])); + } + if (eNB->uci_stats[i].frame <= frame) { + if ((eNB->uci_stats[i].frame + 200) < frame) memset(&eNB->uci_stats[i],0,sizeof(eNB->uci_stats[i])); + } + else { + if (eNB->uci_stats[i].frame + 200 < (frame+1024)) memset(&eNB->uci_stats[i],0,sizeof(eNB->uci_stats[i])); + } } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); } @@ -2147,13 +2204,7 @@ void release_rnti_of_phy(module_id_t mod_id) { eNB_PHY = RC.eNB[mod_id][CC_id]; rnti = release_rntis.ue_release_request_TLVs_list[i].rnti; - for (j=0; julsch[j]; - - if((ulsch != NULL) && (ulsch->rnti == rnti)) { - LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti); - clean_eNb_ulsch(ulsch); - } + for (j=0; jdlsch[j][0]; @@ -2163,14 +2214,18 @@ void release_rnti_of_phy(module_id_t mod_id) { } } - ulsch = eNB_PHY->ulsch[j]; + for (j=0;julsch[j]; - if((ulsch != NULL) && (ulsch->rnti == rnti)) { - LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti); - clean_eNb_ulsch(ulsch); + if((ulsch != NULL) && (ulsch->rnti == rnti)) { + LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti); + clean_eNb_ulsch(ulsch); + for (j=0;julsch_stats[j].rnti == rnti) {eNB_PHY->ulsch_stats[j].rnti=0; break;} + } } - for(j=0; juci_vars[j].rnti == rnti) { LOG_I(PHY, "clean eNb uci_vars[%d] UE %x \n",j, rnti); memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI)); diff --git a/openair1/SCHED/prach_procedures.c b/openair1/SCHED/prach_procedures.c index eb9a2922c5..4d0fe428e8 100644 --- a/openair1/SCHED/prach_procedures.c +++ b/openair1/SCHED/prach_procedures.c @@ -31,8 +31,6 @@ */ #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" -#include "SCHED/sched_eNB.h" #include "nfapi_interface.h" #include "fapi_l1.h" #include "nfapi_pnf.h" @@ -46,7 +44,6 @@ #include -#include "intertask_interface.h" extern int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); @@ -80,7 +77,7 @@ void prach_procedures(PHY_VARS_eNB *eNB, ru=eNB->RU_list[i]; for (ru_aa=0,aa=0; ru_aanb_rx; ru_aa++,aa++) { - eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[0][ru_aa]; int ce_level; if (br_flag==1) @@ -188,7 +185,7 @@ void prach_procedures(PHY_VARS_eNB *eNB, else { eNB->measurements.prach_I0 = ((eNB->measurements.prach_I0*900)>>10) + ((avg_preamble_energy[0]*124)>>10); - if (frame==0) LOG_I(PHY,"prach_I0 = %d.%d dB\n",eNB->measurements.prach_I0/10,eNB->measurements.prach_I0%10); + if (frame==0) LOG_D(PHY,"prach_I0 = %d.%d dB\n",eNB->measurements.prach_I0/10,eNB->measurements.prach_I0%10); if (eNB->prach_energy_counter < 100) eNB->prach_energy_counter++; } diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c index e472d64db4..15eba7b5bc 100644 --- a/openair1/SCHED/ru_procedures.c +++ b/openair1/SCHED/ru_procedures.c @@ -54,7 +54,6 @@ #include "PHY/defs_eNB.h" -#include "PHY/phy_extern.h" #include "SCHED/sched_eNB.h" #include "PHY/MODULATION/modulation_eNB.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" @@ -140,27 +139,26 @@ void feptx0(RU_t *ru, int num_symb = 7; if (subframe_select(fp,subframe) == SF_S) - num_symb = fp->dl_symbols_in_S_subframe+1; + num_symb = fp->dl_symbols_in_S_subframe+1; - if (ru->generate_dmrs_sync == 1 && slot == 0 && subframe == 1 && aa==0) { + if (ru->generate_dmrs_sync == 1 && slot == 2 && aa==0) { //int32_t dmrs[ru->frame_parms.ofdm_symbol_size*14] __attribute__((aligned(32))); //int32_t *dmrsp[2] ={dmrs,NULL}; //{&dmrs[(3-ru->frame_parms.Ncp)*ru->frame_parms.ofdm_symbol_size],NULL}; - - generate_drs_pusch((PHY_VARS_UE *)NULL, - (UE_rxtx_proc_t*)NULL, - fp, - ru->common.txdataF_BF, - 0, - AMP, - 0, - 0, - fp->N_RB_DL, - aa); + generate_drs_pusch((PHY_VARS_UE *)NULL, + (UE_rxtx_proc_t*)NULL, + fp, + ru->common.txdataF_BF, + 0, + AMP, + 0, + 0, + fp->N_RB_DL, + aa); } - normal_prefix_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF], - (int*)&ru->common.txdata[aa][slot_offset], - num_symb, - fp); + normal_prefix_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF], + (int*)&ru->common.txdata[aa][slot_offset], + num_symb, + fp); } } @@ -474,15 +472,16 @@ void feptx_prec(RU_t *ru, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+ru->idx , 1); for (aa=0;aanb_tx;aa++) { - memset(ru->common.txdataF_BF[aa],0,sizeof(int32_t)*fp->ofdm_symbol_size*fp->symbols_per_tti); - for (int p=0;pdo_precoding == 0) { - if (p==0) - memcpy((void*)ru->common.txdataF_BF[aa], - (void*)&eNB->common_vars.txdataF[aa][subframe*fp->symbols_per_tti*fp->ofdm_symbol_size], - sizeof(int32_t)*fp->ofdm_symbol_size*fp->symbols_per_tti); - } else { - if (pnb_antenna_ports_eNB) { + if (ru->do_precoding == 0) { + memcpy((void*)ru->common.txdataF_BF[aa], + (void*)&eNB->common_vars.txdataF[aa%fp->nb_antenna_ports_eNB][subframe*fp->symbols_per_tti*fp->ofdm_symbol_size], + sizeof(int32_t)*fp->ofdm_symbol_size*fp->symbols_per_tti); + + } + else { + memset(ru->common.txdataF_BF[aa],0,sizeof(int32_t)*fp->ofdm_symbol_size*fp->symbols_per_tti); + for (int p=0;pnb_antenna_ports_eNB) { // For the moment this does nothing different than below, except ignore antenna ports 5,7,8. for (l=0;lnum_pdcch_symbols;l++) beam_precoding(eNB->common_vars.txdataF, @@ -494,10 +493,10 @@ void feptx_prec(RU_t *ru, aa, p, eNB->Mod_id); - } //if (pnb_antenna_ports_eNB) + } //if (pnb_antenna_ports_eNB) // PDSCH region - if (pnb_antenna_ports_eNB || p==5 || p==7 || p==8) { + if (pnb_antenna_ports_eNB || p==5 || p==7 || p==8) { for (l=pdcch_vars->num_pdcch_symbols;lsymbols_per_tti;l++) { beam_precoding(eNB->common_vars.txdataF, ru->common.txdataF_BF, @@ -510,8 +509,8 @@ void feptx_prec(RU_t *ru, eNB->Mod_id); } // for (l=pdcch_vars ....) } // if (pnb_antenna_ports_eNB) ... - } // ru->do_precoding!=0 - } // for (p=0...) + } // for (p=0...) + } // if do_precoding } // for (aa=0 ...) if(ru->idx<2) @@ -658,7 +657,7 @@ void ru_fep_full_2thread(RU_t *ru, struct timespec wait; - if ((fp->frame_type == TDD) && (subframe_select(fp,subframe) != SF_UL)) return; + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe) == SF_DL)) return; if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 ); @@ -705,7 +704,7 @@ void ru_fep_full_2thread(RU_t *ru, if (proc->tti_rx/*proc->subframe_rx*/==1 && ru->is_slave==1/* && ru->state == RU_CHECK_SYNC*/) { - //LOG_I(PHY,"Running check synchronization procedure for frame %d\n", proc->frame_rx); + LOG_I(PHY,"Running check synchronization procedure for frame %d\n", proc->frame_rx); ulsch_extract_rbs_single(ru->common.rxdataF, calibration->rxdataF_ext, 0, @@ -731,9 +730,10 @@ void ru_fep_full_2thread(RU_t *ru, check_sync_pos = lte_est_timing_advance_pusch(ru->frame_parms, ru->calibration.drs_ch_estimates_time); if (ru->state == RU_CHECK_SYNC) { if ((check_sync_pos >= 0 && check_sync_pos<8) || (check_sync_pos < 0 && check_sync_pos>-8)) { - LOG_I(PHY,"~~~~~~~~~~~ check_sync_pos %d, frame %d, cnt %d\n",check_sync_pos,proc->frame_rx,ru->wait_check); +// LOG_I(PHY,"~~~~~~~~~~~ check_sync_pos %d, frame %d, cnt %d\n",check_sync_pos,proc->frame_rx,ru->wait_check); ru->wait_check++; } + LOG_I(PHY,"~~~~~~~~~~~ check_sync_pos %d, frame %d, cnt %d\n",check_sync_pos,proc->frame_rx,ru->wait_check); if (ru->wait_check==20) { ru->state = RU_RUN; @@ -743,10 +743,11 @@ void ru_fep_full_2thread(RU_t *ru, rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len LOG_I(PHY,"Sending RRU_sync_ok to RAU\n"); AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),"Failed to send msg to RAU %d\n",ru->idx); +/* //LOG_I(PHY,"~~~~~~~~~ RU_RUN\n"); - /*LOG_M("dmrs_time.m","dmrstime",calibration->drs_ch_estimates_time[0], (fp->ofdm_symbol_size),1,1); + LOG_M("dmrs_time.m","dmrstime",calibration->drs_ch_estimates_time[0], (fp->ofdm_symbol_size),1,1); LOG_M("rxdataF_ext.m","rxdataFext",&calibration->rxdataF_ext[0][36*fp->N_RB_DL], 12*(fp->N_RB_DL),1,1); - LOG_M("drs_seq0.m","drsseq0",ul_ref_sigs_rx[0][0][23],600,1,1); + //LOG_M("drs_seq0.m","drsseq0",ul_ref_sigs_rx[0][0][23],600,1,1); LOG_M("rxdata.m","rxdata",&ru->common.rxdata[0][0], fp->samples_per_tti*2,1,1); exit(-1);*/ } @@ -775,7 +776,6 @@ void fep_full(RU_t *ru, if ((fp->frame_type == TDD) && (subframe_select(fp,subframe) != SF_UL)) return; - start_meas(&ru->ofdm_demod_stats); if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+ru->idx, 1 ); diff --git a/openair1/SCHED/sched_common.h b/openair1/SCHED/sched_common.h index f3e43d516e..c9fc338686 100644 --- a/openair1/SCHED/sched_common.h +++ b/openair1/SCHED/sched_common.h @@ -311,7 +311,7 @@ void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id); int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id, uint8_t eNB_index); -void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); +void schedule_response(Sched_Rsp_t *Sched_INFO, void *proc); LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); diff --git a/openair1/SCHED/sched_eNB.h b/openair1/SCHED/sched_eNB.h index f04bec2e5c..de987b0ac7 100644 --- a/openair1/SCHED/sched_eNB.h +++ b/openair1/SCHED/sched_eNB.h @@ -193,7 +193,7 @@ int8_t find_ue_ulsch(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); -void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); +void schedule_response(Sched_Rsp_t *Sched_INFO, void *proc); LTE_eNB_UE_stats *get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 2870f1d42e..8f315ba214 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -30,22 +30,36 @@ * \warning */ #include "fapi_nr_l1.h" +#include "common/ran_context.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_dci.h" +#include "nfapi/oai_integration/vendor_ext.h" + +extern int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); +extern int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); +extern int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req); +extern int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); extern uint8_t nfapi_mode; -void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, +void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot, nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu) { AssertFatal(dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag== 1, "bchPayloadFlat %d != 1\n", dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag); - LOG_D(PHY,"%d.%d : pbch_pdu: %x\n",frame,slot,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload); - memcpy((void*)&gNB->ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_pdu)); + uint8_t i_ssb = dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex; + + LOG_D(PHY,"%d.%d : ssb index %d pbch_pdu: %x\n",frame,slot,i_ssb,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload); + if (msgTx->ssb[i_ssb].active) + AssertFatal(1==0,"SSB PDU with index %d already active\n",i_ssb); + else { + msgTx->ssb[i_ssb].active = true; + memcpy((void*)&msgTx->ssb[i_ssb].ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_pdu)); + } } /*void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int subframe,gNB_L1_rxtx_proc_t *proc, @@ -87,46 +101,39 @@ void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, }*/ -void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu) { - - LOG_D(PHY,"Frame %d, Slot %d: DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); - - // copy dci configuration into gNB structure - gNB->pdcch_pdu = pdcch_pdu; - - nr_fill_dci(gNB,frame,slot); - +void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, + int frame,int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu) { + int found = 0; + for (int id=0; idcsirs_pdu[id]; + if (csirs->active == 0) { + LOG_D(PHY,"Frame %d Slot %d CSI_RS with ID %d is now active\n",frame,slot,id); + csirs->active = 1; + memcpy((void*)&csirs->csirs_pdu, (void*)csirs_pdu, sizeof(nfapi_nr_dl_tti_csi_rs_pdu)); + found = 1; + break; + } + } + if (found == 0) + LOG_E(MAC,"CSI-RS list is full\n"); } -void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu) { - LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); - - // copy dci configuration into gNB structure - gNB->ul_dci_pdu = ul_dci_request_pdu; - - nr_fill_ul_dci(gNB,frame,slot); - -} - -void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, +void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu) { - nr_fill_dlsch(gNB,frame,slot,pdsch_pdu,sdu); + nr_fill_dlsch(msgTx,pdsch_pdu,sdu); } void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ - + PHY_VARS_gNB *gNB; // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; @@ -140,87 +147,106 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n"); AssertFatal(RC.gNB[Mod_id]!=NULL,"RC.gNB[%d] is null\n",Mod_id); - gNB = RC.gNB[Mod_id]; + gNB = RC.gNB[Mod_id]; + + notifiedFIFO_elt_t *res; + res = pullTpool(gNB->resp_L1_tx, gNB->threadPool); + processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res); uint8_t number_dl_pdu = (DL_req==NULL) ? 0 : DL_req->dl_tti_request_body.nPDUs; uint8_t number_ul_dci_pdu = (UL_dci_req==NULL) ? 0 : UL_dci_req->numPdus; uint8_t number_ul_tti_pdu = (UL_tti_req==NULL) ? 0 : UL_tti_req->n_pdus; + uint8_t number_tx_data_pdu = (TX_req == NULL) ? 0 : TX_req->Number_of_PDUs; - if (DL_req != NULL && TX_req!=NULL) - LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SLOT:%04d/%d DL_req:SFN/SLO:%04d/%d:dl_pdu:%d tx_req:SFN/SLOT:%04d/%d:pdus:%d;ul_dci %d ul_tti %d\n", - frame,slot, - DL_req->SFN,DL_req->Slot,number_dl_pdu, - TX_req->SFN,TX_req->Slot,TX_req->Number_of_PDUs, - number_ul_dci_pdu,number_ul_tti_pdu); + if (NFAPI_MODE == NFAPI_MONOLITHIC){ + if (DL_req != NULL && TX_req!=NULL && (number_dl_pdu > 0 || number_ul_dci_pdu > 0 || number_ul_tti_pdu > 0)) + LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SLOT:%04d/%d DL_req:SFN/SLO:%04d/%d:dl_pdu:%d tx_req:SFN/SLOT:%04d/%d:pdus:%d;ul_dci %d ul_tti %d\n", + frame,slot, + DL_req->SFN,DL_req->Slot,number_dl_pdu, + TX_req->SFN,TX_req->Slot,TX_req->Number_of_PDUs, + number_ul_dci_pdu,number_ul_tti_pdu); - int pdcch_received=0; - gNB->num_pdsch_rnti=0; - for (int i=0; idlsch[i][0]->rnti=0; - gNB->dlsch[i][0]->harq_mask=0; - } - gNB->pdcch_pdu = NULL; - gNB->ul_dci_pdu = NULL; - gNB->pbch_configured=0; + int pdcch_received=0; + msgTx->num_pdsch_slot=0; + msgTx->pdcch_pdu.pdcch_pdu_rel15.numDlDci = 0; + msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci = 0; + msgTx->slot = slot; + msgTx->frame = frame; - for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; - LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType); - switch (dl_tti_pdu->PDUType) { - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - gNB->pbch_configured=1; + for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; + LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType); + switch (dl_tti_pdu->PDUType) { + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + handle_nr_nfapi_ssb_pdu(msgTx,frame,slot, + dl_tti_pdu); + break; - handle_nr_nfapi_ssb_pdu(gNB,frame,slot, - dl_tti_pdu); + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); + msgTx->pdcch_pdu = dl_tti_pdu->pdcch_pdu; - break; + pdcch_received = 1; + break; - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); - handle_nfapi_nr_pdcch_pdu(gNB, - frame, slot, - &dl_tti_pdu->pdcch_pdu); - - pdcch_received = 1; + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + handle_nfapi_nr_csirs_pdu(msgTx,frame,slot, + &dl_tti_pdu->csi_rs_pdu); + break; - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; + uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; + AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", + pduIndex,TX_req->pdu_list[pduIndex].num_TLV); + uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; + AssertFatal(msgTx->num_pdsch_slot < gNB->number_of_nr_dlsch_max,"Number of PDSCH PDUs %d exceeded the limit %d\n", + msgTx->num_pdsch_slot,gNB->number_of_nr_dlsch_max); + handle_nr_nfapi_pdsch_pdu(msgTx,&dl_tti_pdu->pdsch_pdu, sdu); + } + } - { - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; - uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; - AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", - pduIndex,TX_req->pdu_list[pduIndex].num_TLV); - uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); + if (number_ul_dci_pdu > 0) + msgTx->ul_pdcch_pdu = UL_dci_req->ul_dci_pdu_list[number_ul_dci_pdu-1]; // copy the last pdu + + pushNotifiedFIFO(gNB->resp_L1_tx,res); + + for (int i = 0; i < number_ul_tti_pdu; i++) { + switch (UL_tti_req->pdus_list[i].pdu_type) { + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_ulsch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_pucch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; + nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); + if (gNB->RU_list[0]->if_south == LOCAL_RF) nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); + break; } } } - // if (UL_tti_req!=NULL) memcpy(&gNB->UL_tti_req,UL_tti_req,sizeof(nfapi_nr_ul_tti_request_t)); - - for (int i=0;iul_dci_pdu_list[i]); + if (NFAPI_MODE == NFAPI_MODE_VNF) { //If VNF, oai_nfapi functions send respective p7 msgs to PNF for which nPDUs is greater than 0 + + if(number_ul_tti_pdu>0) + oai_nfapi_ul_tti_req(UL_tti_req); + + if (number_ul_dci_pdu>0) + oai_nfapi_ul_dci_req(UL_dci_req); + + if (number_dl_pdu>0) + oai_nfapi_dl_tti_req(DL_req); + + if (number_tx_data_pdu>0) + oai_nfapi_tx_data_req(TX_req); + } - for (int i = 0; i < number_ul_tti_pdu; i++) { - switch (UL_tti_req->pdus_list[i].pdu_type) { - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); - nr_fill_ulsch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); - break; - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); - nr_fill_pucch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); - break; - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); - nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; - nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - break; - } - } } diff --git a/openair1/SCHED_NR/fapi_nr_l1.h b/openair1/SCHED_NR/fapi_nr_l1.h index d66d6e7b24..f598b263c3 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.h +++ b/openair1/SCHED_NR/fapi_nr_l1.h @@ -36,15 +36,29 @@ #include "nfapi_nr_interface.h" #include "nfapi_nr_interface_scf.h" +// added +void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx, + int frame,int slot, + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu); + void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO); +void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu); + void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, int frame, int subframe, nfapi_nr_dl_tti_pdcch_pdu *dcl_dl_pdu); -void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, +void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu); -void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int UE_id, uint8_t harq_pid, uint8_t crc_flag); +void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int UE_id, uint8_t harq_pid, uint8_t crc_flag,int dtx_flag); +//added + +void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu); diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index a5d459a7c6..1ea8dbdf3c 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -49,90 +49,168 @@ extern uint8_t nfapi_mode; -extern int oai_nfapi_nr_rach_ind(nfapi_rach_indication_t *rach_ind); +uint8_t get_nr_prach_duration(uint8_t prach_format){ + switch(prach_format){ -void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot, - nfapi_nr_prach_pdu_t *prach_pdu) { + case 0: // format 0 + return 0; + + case 1: // format 1 + return 0; + + case 2: // format 2 + return 0; + + case 3: // format 3 + return 0; + + case 4: // format A1 + return 2; + + case 5: // format A2 + return 4; + + case 6: // format A3 + return 6; + + case 7: // format B1 + return 2; + + case 8: // format B4 + return 12; + + case 9: // format C0 + return 2; + + case 10: // format C2 + return 6; + + case 11: // format A1/B1 + return 2; + + case 12: // format A2/B2 + return 4; + + case 13: // format A3/B3 + return 6; + + default : + AssertFatal(1==0,"Invalid Prach format\n"); + break; + + } +} + +void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot) { uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={0}; - uint16_t i; - gNB->UL_INFO.rach_ind.number_of_pdus=0; - + uint8_t pdu_index = 0; RU_t *ru; int aa=0; int ru_aa; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); + gNB->UL_INFO.rach_ind.sfn = frame; + gNB->UL_INFO.rach_ind.slot = slot; + gNB->UL_INFO.rach_ind.pdu_list = gNB->prach_pdu_indication_list; + gNB->UL_INFO.rach_ind.number_of_pdus = 0; + ru=gNB->RU_list[0]; + int prach_id=find_nr_prach(gNB,frame,slot,SEARCH_EXIST); + + if (prach_id>=0) { + nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list[prach_id].pdu; + uint8_t prachStartSymbol; + uint8_t N_dur = get_nr_prach_duration(prach_pdu->prach_format); + + /* + uint16_t format,RA_sfn_index; + uint8_t start_symbol,N_t_slot,N_dur,N_RA_slot,config_period; - for (i=0;inum_RU;i++) { - ru=gNB->RU_list[i]; - for (ru_aa=0,aa=0;ru_aanb_rx;ru_aa++,aa++) { - gNB->prach_vars.rxsigF[aa] = gNB->RU_list[i]->prach_rxsigF[ru_aa]; - } - } + get_nr_prach_info_from_index(gNB->gNB_config.prach_config.prach_ConfigurationIndex.value, + frame,slot, + gNB->gNB_config.carrier_config.dl_frequency.value, + gNB->frame_parms.numerology_index, + gNB->frame_parms.frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period); + */ + + for(int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) { + for (ru_aa=0,aa=0;ru_aanb_rx;ru_aa++,aa++) { + gNB->prach_vars.rxsigF[aa] = ru->prach_rxsigF[prach_oc][ru_aa]; + } - rx_nr_prach(gNB, - prach_pdu, + prachStartSymbol = prach_pdu->prach_start_symbol+prach_oc*N_dur; + //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + + rx_nr_prach(gNB, + prach_pdu, + prach_oc, + frame, + slot, + &max_preamble[0], + &max_preamble_energy[0], + &max_preamble_delay[0] + ); + free_nr_prach_entry(gNB,prach_id); + LOG_D(PHY,"[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d.%d dB delay %d (prach_energy counter %d)\n", + frame,slot,prach_oc,prachStartSymbol, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + max_preamble_delay[0], + gNB->prach_energy_counter); + + if ((gNB->prach_energy_counter == 100) && (max_preamble_energy[0] > gNB->measurements.prach_I0+gNB->prach_thres)) { + + LOG_I(NR_PHY,"[gNB %d][RAPROC] Frame %d, slot %d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol %u freq index %u\n", + gNB->Mod_id, frame, slot, - &max_preamble[0], - &max_preamble_energy[0], - &max_preamble_delay[0] - ); - - LOG_D(PHY,"[RAPROC] Frame %d, slot %d : Most likely preamble %d, energy %d dB delay %d (prach_energy counter %d)\n", - frame,slot, - max_preamble[0], - max_preamble_energy[0]/10, - max_preamble_delay[0], - gNB->prach_energy_counter); - - if ((gNB->prach_energy_counter == 100) && - (max_preamble_energy[0] > gNB->measurements.prach_I0+100)) { - - LOG_I(PHY,"[gNB %d][RAPROC] Frame %d, slot %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", - gNB->Mod_id, - frame, - slot, - max_preamble[0], - max_preamble_energy[0]/10, - max_preamble_energy[0]%10, - max_preamble_delay[0]); - - T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(gNB->Mod_id), T_INT(frame), T_INT(slot), - T_INT(max_preamble[0]), T_INT(max_preamble_energy[0]), T_INT(max_preamble_delay[0])); - - - gNB->UL_INFO.rach_ind.number_of_pdus = 1; - gNB->UL_INFO.rach_ind.pdu_list = &gNB->prach_pdu_indication_list[0]; - gNB->UL_INFO.rach_ind.sfn = frame; - gNB->UL_INFO.rach_ind.slot = slot; - - gNB->prach_pdu_indication_list[0].phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value; - gNB->prach_pdu_indication_list[0].symbol_index = prach_pdu->prach_start_symbol; // FIXME to be changed for multi-ssb (this is only the start symbol of first occasion) - gNB->prach_pdu_indication_list[0].slot_index = slot; - gNB->prach_pdu_indication_list[0].freq_index = prach_pdu->num_ra; - gNB->prach_pdu_indication_list[0].avg_rssi = (max_preamble_energy[0]<631) ? (128+(max_preamble_energy[0]/5)) : 254; - gNB->prach_pdu_indication_list[0].avg_snr = 0xff; // invalid for now - - - gNB->prach_pdu_indication_list[0].num_preamble = 1; - gNB->prach_pdu_indication_list[0].preamble_list = gNB->preamble_list; - gNB->prach_pdu_indication_list[0].preamble_list[0].preamble_index = max_preamble[0]; - gNB->prach_pdu_indication_list[0].preamble_list[0].timing_advance = max_preamble_delay[0]; - gNB->prach_pdu_indication_list[0].preamble_list[0].preamble_pwr = 0xffffffff; - } - gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0*900)>>10) + ((max_preamble_energy[0]*124)>>10); - if (frame==0) LOG_I(PHY,"prach_I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10); - if (gNB->prach_energy_counter < 100) gNB->prach_energy_counter++; - - + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + gNB->measurements.prach_I0,gNB->prach_thres, + max_preamble_delay[0], + prachStartSymbol, + prach_pdu->num_ra); + + T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(gNB->Mod_id), T_INT(frame), T_INT(slot), + T_INT(max_preamble[0]), T_INT(max_preamble_energy[0]), T_INT(max_preamble_delay[0])); + + + gNB->UL_INFO.rach_ind.number_of_pdus += 1; + + gNB->prach_pdu_indication_list[pdu_index].phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value; + gNB->prach_pdu_indication_list[pdu_index].symbol_index = prachStartSymbol; + gNB->prach_pdu_indication_list[pdu_index].slot_index = slot; + gNB->prach_pdu_indication_list[pdu_index].freq_index = prach_pdu->num_ra; + gNB->prach_pdu_indication_list[pdu_index].avg_rssi = (max_preamble_energy[0]<631) ? (128+(max_preamble_energy[0]/5)) : 254; + gNB->prach_pdu_indication_list[pdu_index].avg_snr = 0xff; // invalid for now + + gNB->prach_pdu_indication_list[pdu_index].num_preamble = 1; + gNB->prach_pdu_indication_list[pdu_index].preamble_list = gNB->preamble_list; + gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].preamble_index = max_preamble[0]; + gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].timing_advance = max_preamble_delay[0]; + gNB->prach_pdu_indication_list[pdu_index].preamble_list[0].preamble_pwr = 0xffffffff; + pdu_index++; + } + gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0*900)>>10) + ((max_preamble_energy[0]*124)>>10); + if (frame==0) LOG_I(PHY,"prach_I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10); + if (gNB->prach_energy_counter < 100) gNB->prach_energy_counter++; + } //if prach_id>0 + } //for NUMBER_OF_NR_PRACH_OCCASION_MAX VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 560f47059a..d8fa11d157 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -31,15 +31,12 @@ */ #include "PHY/defs_gNB.h" -#include "PHY/phy_extern.h" #include "sched_nr.h" #include "PHY/MODULATION/modulation_common.h" #include "PHY/MODULATION/nr_modulation.h" #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/LTE_TRANSPORT/if5_tools.h" -#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac.h" #include "common/utils/LOG/log.h" #include "common/utils/system.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -87,14 +84,15 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { CYCLIC_PREFIX); else { if (fp->numerology_index != 0) { - - if (!(slot%(fp->slots_per_subframe/2))&&(first_symbol==0)) { + + if (!(slot%(fp->slots_per_subframe/2))&&(first_symbol==0)) { // case where first symbol in slot has longer prefix PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], (int*)&ru->common.txdata[aa][slot_offset], fp->ofdm_symbol_size, 1, fp->nb_prefix_samples0, CYCLIC_PREFIX); + PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size], (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size], fp->ofdm_symbol_size, @@ -102,7 +100,7 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { fp->nb_prefix_samples, CYCLIC_PREFIX); } - else { + else { // all symbols in slot have shorter prefix PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], (int*)&ru->common.txdata[aa][slot_offset], fp->ofdm_symbol_size, @@ -110,9 +108,8 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { fp->nb_prefix_samples, CYCLIC_PREFIX); } - } - - else { + } // numerology_index!=0 + else { //numerology_index == 0 for (uint16_t idx_sym=abs_first_symbol; idx_symcommon.txdataF_BF[aa][slot_offsetF], @@ -122,6 +119,7 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { fp->nb_prefix_samples, CYCLIC_PREFIX); slot_offset += fp->nb_prefix_samples+fp->ofdm_symbol_size; + slot_offsetF += fp->ofdm_symbol_size; } else { PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], @@ -131,6 +129,7 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { fp->nb_prefix_samples0, CYCLIC_PREFIX); slot_offset += fp->nb_prefix_samples0+fp->ofdm_symbol_size; + slot_offsetF += fp->ofdm_symbol_size; } } } @@ -200,17 +199,17 @@ void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+j , 1); start_meas(&ru->txdataF_copy_stats); - if (ru->num_gNB == 1){ - gNB = ru->gNB_list[0]; - cfg = &gNB->gNB_config; + AssertFatal(ru->num_gNB==1,"num_gNB>1, help\n"); + gNB = ru->gNB_list[0]; + cfg = &gNB->gNB_config; - for(i=0; inb_tx; ++i){ - memcpy((void*)&ru->common.txdataF[i][j*fp->ofdm_symbol_size], - (void*)&gNB->common_vars.txdataF[i][j*fp->ofdm_symbol_size + txdataF_offset], - fp->ofdm_symbol_size*sizeof(int32_t)); - } + for(i=0; inb_tx; ++i){ + memcpy((void*)&ru->common.txdataF[i][j*fp->ofdm_symbol_size], + (void*)&gNB->common_vars.txdataF[i][j*fp->ofdm_symbol_size + txdataF_offset], + fp->ofdm_symbol_size*sizeof(int32_t)); + + } - }//num_gNB == 1 stop_meas(&ru->txdataF_copy_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+j , 0); @@ -279,13 +278,12 @@ static void *nr_feptx_thread(void *param) { RU_feptx_t *feptx = (RU_feptx_t *)param; RU_t *ru; - int aa, slot, start, l, nb_antenna_ports, ret; + int aa, slot, start, l, ret; int i; int32_t ***bw; NR_DL_FRAME_PARMS *fp; int ofdm_mask_full; int txdataF_offset; - int32_t *txdataF; while (!oai_exit) { ret = 0; if (wait_on_condition(&feptx->mutex_feptx,&feptx->cond_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break; @@ -299,40 +297,55 @@ static void *nr_feptx_thread(void *param) { l = feptx->symbol; fp = ru->nr_frame_parms; start = feptx->symbol; - nb_antenna_ports = feptx->nb_antenna_ports; ofdm_mask_full = (1<<(ru->nb_tx*2))-1; if(ru->num_gNB != 0){ txdataF_offset = ((slot%2)*fp->samples_per_slot_wCP); ////////////precoding//////////// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 1); - start_meas(&ru->precoding_stats); + + if (aa==0 && l==0) start_meas(&ru->precoding_stats); + + if (ru->do_precoding == 1) { + for(i=0; inb_log_antennas; ++i) { + memcpy((void*) &ru->common.beam_id[i][slot*fp->symbols_per_slot+l], + (void*) &ru->gNB_list[0]->common_vars.beam_id[i][slot*fp->symbols_per_slot+l], + (fp->symbols_per_slot>>1)*sizeof(uint8_t)); + } + } + if (ru->nb_tx == 1 && ru->nb_log_antennas == 1) { - memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size], - (void*)&ru->gNB_list[0]->common_vars.txdataF[0][txdataF_offset + l*fp->ofdm_symbol_size], - (fp->samples_per_slot_wCP>>1)*sizeof(int32_t)); + memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size], + (void*)&ru->gNB_list[0]->common_vars.txdataF[0][txdataF_offset + l*fp->ofdm_symbol_size], + (fp->samples_per_slot_wCP>>1)*sizeof(int32_t)); + } + else if (ru->do_precoding == 0) { + int gNB_tx = ru->gNB_list[0]->frame_parms.nb_antennas_tx; + memcpy((void*)&ru->common.txdataF_BF[aa][l*fp->ofdm_symbol_size], + (void*)&ru->gNB_list[0]->common_vars.txdataF[aa%gNB_tx][txdataF_offset + l*fp->ofdm_symbol_size], + (fp->samples_per_slot_wCP>>1)*sizeof(int32_t)); } else { bw = ru->beam_weights[0]; - txdataF = &ru->gNB_list[0]->common_vars.txdataF[0][txdataF_offset]; for(i=0; isymbols_per_slot>>1; ++i){ - nr_beam_precoding(&txdataF, + nr_beam_precoding(ru->gNB_list[0]->common_vars.txdataF, ru->common.txdataF_BF, fp, bw, slot, l+i, aa, - nb_antenna_ports); + ru->nb_log_antennas, + txdataF_offset);//here } } - stop_meas(&ru->precoding_stats); + if (aa==0 && l==0) stop_meas(&ru->precoding_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 0); ////////////FEPTX//////////// - start_meas(&ru->ofdm_mod_stats); + if (aa==0 && l==0) start_meas(&ru->ofdm_mod_stats); nr_feptx0(ru,slot,start,fp->symbols_per_slot>>1,aa); - stop_meas(&ru->ofdm_mod_stats); + if (aa==0 && l==0) stop_meas(&ru->ofdm_mod_stats); if (release_thread(&feptx->mutex_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break; @@ -362,7 +375,8 @@ static void *nr_feptx_thread(void *param) { slot, l, aa, - nb_antenna_ports); + ru->nb_log_antennas, + 0); } stop_meas(&ru->precoding_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 0); @@ -459,10 +473,14 @@ void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx) { if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT) return; - for(i=0; inb_log_antennas; ++i) + for(i=0; inb_log_antennas; ++i) { memcpy((void*)ru->common.txdataF[i], (void*)&gNB->common_vars.txdataF[i][txdataF_offset], fp->samples_per_slot_wCP*sizeof(int32_t)); + memcpy((void*)&ru->common.beam_id[i][slot_tx*fp->symbols_per_slot], + (void*)&gNB->common_vars.beam_id[i][slot_tx*fp->symbols_per_slot], + fp->symbols_per_slot*sizeof(uint8_t)); + } if (ru->nb_tx == 1 && ru->nb_log_antennas == 1) { @@ -485,7 +503,8 @@ void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx) { tti_tx, l, aa, - ru->nb_log_antennas); + ru->nb_log_antennas, + 0); }// for (aa=0;aanb_tx;aa++) }// for (l=0;lsymbols_per_slot;l++) }// if (ru->nb_tx == 1) @@ -512,16 +531,15 @@ void nr_fep0(RU_t *ru, int first_half) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+proc->tti_rx, 1); - // remove_7_5_kHz(ru,(slot&1)+(proc->tti_rx<<1)); + int offset = (proc->tti_rx&3) * fp->symbols_per_slot * fp->ofdm_symbol_size; for (l = start_symbol; l < end_symbol; l++) { for (aa = 0; aa < fp->nb_antennas_rx; aa++) { nr_slot_fep_ul(fp, ru->common.rxdata[aa], - ru->common.rxdataF[aa], + &ru->common.rxdataF[aa][offset], l, proc->tti_rx, - ru->N_TA_offset, - 0); + ru->N_TA_offset); } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+proc->tti_rx, 0); @@ -647,18 +665,18 @@ void nr_fep_full(RU_t *ru, int slot) { start_meas(&ru->ofdm_demod_stats); if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 ); + // remove_7_5_kHz(ru,proc->tti_rx<<1); // remove_7_5_kHz(ru,1+(proc->tti_rx<<1)); - + int offset = (proc->tti_rx&3)*(fp->symbols_per_slot * fp->ofdm_symbol_size); for (l = 0; l < fp->symbols_per_slot; l++) { for (aa = 0; aa < fp->nb_antennas_rx; aa++) { nr_slot_fep_ul(fp, ru->common.rxdata[aa], - ru->common.rxdataF[aa], + &ru->common.rxdataF[aa][offset], l, proc->tti_rx, - ru->N_TA_offset, - 0); + ru->N_TA_offset); } } diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 9d34f496b3..25c39846fe 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -30,6 +30,7 @@ ************************************************************************/ #include "PHY/defs_nr_common.h" +#include "PHY/defs_gNB.h" #include "PHY/defs_nr_UE.h" #include "SCHED_NR/phy_frame_config_nr.h" @@ -41,7 +42,7 @@ * * OUTPUT: table of uplink symbol for each slot for 2 frames * -* RETURN : 0 if tdd has been properly configurated +* RETURN : nb_periods_per_frame if tdd has been properly configurated * -1 tdd configuration can not be done * * DESCRIPTION : generate bit map for uplink symbol for each slot for several frames @@ -179,7 +180,7 @@ int set_tdd_config_nr( nfapi_nr_config_request_scf_t *cfg, LOG_E(PHY,"set_tdd_configuration_nr: additionnal tdd configuration 2 is not supported for tdd configuration \n"); return (-1); }*/ - return (0); + return (nb_periods_per_frame); } /******************************************************************* @@ -252,7 +253,7 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms) { while(p_current_TDD_UL_DL_SlotConfig != NULL) { int slot_index = p_current_TDD_UL_DL_SlotConfig->slotIndex; - if (slot_index < TDD_CONFIG_NB_FRAMES*(frame_parms->ttis_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME)) { + if (slot_index < TDD_CONFIG_NB_FRAMES * frame_parms->slots_per_frame) { if (p_current_TDD_UL_DL_SlotConfig->nrofDownlinkSymbols != 0) { if (p_current_TDD_UL_DL_SlotConfig->nrofDownlinkSymbols == NR_TDD_SET_ALL_SYMBOLS) { if (p_current_TDD_UL_DL_SlotConfig->nrofUplinkSymbols == 0) { @@ -308,7 +309,22 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms) { * *********************************************************************/ -int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti) { +int get_next_downlink_slot(PHY_VARS_gNB *gNB, nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) { + + int slot = nr_slot; + int frame = nr_frame; + int slots_per_frame = gNB->frame_parms.slots_per_frame; + while (true) { + slot++; + if (slot/slots_per_frame) frame++; + slot %= slots_per_frame; + int slot_type = nr_slot_select(cfg, frame, slot); + if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) return slot; + AssertFatal(frame < (nr_frame+2), "Something went worng. This shouldn't happen\n"); + } +} + +int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) { /* for FFD all slot can be considered as an uplink */ int mu = cfg->ssb_config.scs_common.value,check_slot=0; @@ -318,7 +334,7 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti) if (nr_frame%2 == 0) { for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { + if (cfg->tdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { check_slot++; } } @@ -330,7 +346,7 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti) check_slot = 0; for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==0) { + if (cfg->tdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==0) { check_slot++; } } @@ -342,7 +358,7 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti) } } else { for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1<ssb_start_subcarrier,cfg->ssb_table.ssb_offset_point_a.value,sco); } -void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) { +void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_dl_tti_ssb_pdu ssb_pdu) { NR_DL_FRAME_PARMS *fp=&gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; int **txdataF = gNB->common_vars.txdataF; uint8_t ssb_index, n_hf; - uint16_t ssb_start_symbol, rel_slot; + uint16_t ssb_start_symbol; int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP; uint16_t slots_per_hf = (fp->slots_per_frame)>>1; - n_hf = fp->half_frame_bit; + if (slotssb_table.ssb_period.value == 0) { - if (slotsymbols_per_slot; // start symbol wrt slot + + nr_set_ssb_first_subcarrier(cfg, fp); // setting the first subcarrier + + LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol); + nr_generate_pss(gNB->d_pss, &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); + nr_generate_sss(gNB->d_sss, &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); + + if (cfg->carrier_config.num_tx_ant.value <= 4) + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); + else + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); + + if (T_ACTIVE(T_GNB_PHY_MIB)) { + unsigned char bch[3]; + bch[0] = ssb_pdu.ssb_pdu_rel15.bchPayload & 0xff; + bch[1] = (ssb_pdu.ssb_pdu_rel15.bchPayload >> 8) & 0xff; + bch[2] = (ssb_pdu.ssb_pdu_rel15.bchPayload >> 16) & 0xff; + T(T_GNB_PHY_MIB, T_INT(0) /* module ID */, T_INT(frame), T_INT(slot), T_BUFFER(bch, 3)); } - // to set a effective slot number in the half frame where the SSB is supposed to be - rel_slot = (n_hf)? (slot-slots_per_hf) : slot; - - LOG_D(PHY,"common_signal_procedures: frame %d, slot %d\n",frame,slot); - - if(rel_slot<38 && rel_slot>=0) { // there is no SSB beyond slot 37 - - for (int i=0; i<2; i++) { // max two SSB per frame - - ssb_index = i + SSB_Table[rel_slot]; // computing the ssb_index - - if ((ssb_index<64) && ((fp->L_ssb >> (63-ssb_index)) & 0x01)) { // generating the ssb only if the bit of L_ssb at current ssb index is 1 - fp->ssb_index = ssb_index; - int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp); // computing the starting symbol for current ssb - ssb_start_symbol = ssb_start_symbol_abs % fp->symbols_per_slot; // start symbol wrt slot - - nr_set_ssb_first_subcarrier(cfg, fp); // setting the first subcarrier - - LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol); - nr_generate_pss(gNB->d_pss, &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); - nr_generate_sss(gNB->d_sss, &txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); - - if (cfg->carrier_config.num_tx_ant.value <= 4) - nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); - else - nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); - - nr_generate_pbch(&gNB->pbch, - &gNB->ssb_pdu, - gNB->nr_pbch_interleaver, - &txdataF[0][txdataF_offset], - AMP, - ssb_start_symbol, - n_hf, frame, cfg, fp); - - } - } + // Beam_id is currently used only for FR2 + if (fp->freq_range==nr_FR2){ + LOG_D(PHY,"slot %d, ssb_index %d, beam %d\n",slot,ssb_index,cfg->ssb_table.ssb_beam_id_list[ssb_index].beam_id.value); + for (int j=0;jsymbols_per_slot;j++) + gNB->common_vars.beam_id[0][slot*fp->symbols_per_slot+j] = cfg->ssb_table.ssb_beam_id_list[ssb_index].beam_id.value; } + + nr_generate_pbch(&gNB->pbch, + &ssb_pdu, + gNB->nr_pbch_interleaver, + &txdataF[0][txdataF_offset], + AMP, + ssb_start_symbol, + n_hf, frame, cfg, fp); } -void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, - int frame,int slot, + +void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, + int frame, + int slot, int do_meas) { int aa; + PHY_VARS_gNB *gNB = msgTx->gNB; NR_DL_FRAME_PARMS *fp=&gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; int offset = gNB->CC_id; - uint8_t ssb_frame_periodicity = 1; // every how many frames SSB are generated int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP; - - - if (cfg->ssb_table.ssb_period.value > 1) - ssb_frame_periodicity = 1 <<(cfg->ssb_table.ssb_period.value -1) ; - if ((cfg->cell_config.frame_duplex_type.value == TDD) && (nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT)) return; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,1); - if (do_meas==1) start_meas(&gNB->phy_proc_tx); + if (do_meas==1) start_meas(&msgTx->phy_proc_tx); - // clear the transmit data array for the current subframe + // clear the transmit data array and beam index for the current slot for (aa=0; aacarrier_config.num_tx_ant.value; aa++) { memset(&gNB->common_vars.txdataF[aa][txdataF_offset],0,fp->samples_per_slot_wCP*sizeof(int32_t)); + memset(&gNB->common_vars.beam_id[aa][slot*fp->symbols_per_slot],255,fp->symbols_per_slot*sizeof(uint8_t)); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1); - if (nfapi_mode == 0 || nfapi_mode == 1) { - if ((!(frame%ssb_frame_periodicity))) // generate SSB only for given frames according to SSB periodicity - nr_common_signal_procedures(gNB,frame, slot); + for (int i=0; iLmax; i++) { + if (msgTx->ssb[i].active) { + nr_common_signal_procedures(gNB,frame,slot,msgTx->ssb[i].ssb_pdu); + msgTx->ssb[i].active = false; + } } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0); + int num_dl_dci = msgTx->pdcch_pdu.pdcch_pdu_rel15.numDlDci; + int num_ul_dci = msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci; - if (gNB->pdcch_pdu || gNB->ul_dci_pdu) { + if (num_dl_dci > 0 || num_ul_dci > 0) { LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", - gNB->Mod_id, frame, slot, - gNB->ul_dci_pdu==NULL?0:gNB->ul_dci_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci, - gNB->pdcch_pdu==NULL?0:gNB->pdcch_pdu->pdcch_pdu_rel15.numDlDci); + gNB->Mod_id, frame, slot, num_ul_dci, num_dl_dci); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1); - nr_generate_dci_top(gNB->pdcch_pdu, - gNB->ul_dci_pdu, + nr_generate_dci_top(gNB, + num_dl_dci > 0 ? &msgTx->pdcch_pdu : NULL, + num_ul_dci > 0 ? &msgTx->ul_pdcch_pdu.pdcch_pdu : NULL, gNB->nr_gold_pdcch_dmrs[slot], &gNB->common_vars.txdataF[0][txdataF_offset], - AMP, *fp); - + AMP, fp); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0); } - for (int i=0; inum_pdsch_rnti; i++) { + if (msgTx->num_pdsch_slot > 0) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); - LOG_D(PHY, "PDSCH generation started (%d)\n", gNB->num_pdsch_rnti); - nr_generate_pdsch(gNB->dlsch[i][0], - gNB->nr_gold_pdsch_dmrs[slot], - gNB->common_vars.txdataF, - AMP, frame, slot, fp, 0, - &gNB->dlsch_encoding_stats, - &gNB->dlsch_scrambling_stats, - &gNB->dlsch_modulation_stats, - &gNB->tinput, - &gNB->tprep, - &gNB->tparity, - &gNB->toutput, - &gNB->dlsch_rate_matching_stats, - &gNB->dlsch_interleaving_stats, - &gNB->dlsch_segmentation_stats); + LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", msgTx->num_pdsch_slot,frame,slot); + nr_generate_pdsch(msgTx, frame, slot); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0); } + for (int i=0;icsirs_pdu[i]; + if ((csirs->active == 1)) { + LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot); + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t csi_params = csirs->csirs_pdu.csi_rs_pdu_rel15; + nr_generate_csi_rs(gNB, AMP, csi_params, gNB->gNB_config.cell_config.phy_cell_id.value, slot); + csirs->active = 0; + } + } + + if (do_meas==1) stop_meas(&msgTx->phy_proc_tx); + +// if ((frame&127) == 0) dump_pdsch_stats(gNB); + + //apply the OFDM symbol rotation here + for (aa=0; aacarrier_config.num_tx_ant.value; aa++) { + apply_nr_rotation(fp,(int16_t*) &gNB->common_vars.txdataF[aa][txdataF_offset],slot,0,fp->Ncp==EXTENDED?12:14,fp->ofdm_symbol_size); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0); } @@ -212,12 +217,118 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, */ +void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { + ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); + NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + NR_gNB_ULSCH_t *ulsch = rdata->ulsch; + int r = rdata->segment_r; + nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[rdata->ulsch_id][0]->harq_processes[rdata->harq_pid]->ulsch_pdu; + + bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter); + ulsch_harq->processedSegments++; + LOG_D(PHY, "processing result of segment: %d, processed %d/%d\n", + rdata->segment_r, ulsch_harq->processedSegments, rdata->nbSegments); + gNB->nbDecode--; + LOG_D(PHY,"remain to decoded in subframe: %d\n", gNB->nbDecode); + + if (decodeSuccess) { + memcpy(ulsch_harq->b+rdata->offset, + ulsch_harq->c[r], + rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0)); + + } else { + if ( rdata->nbSegments != ulsch_harq->processedSegments ) { + int nb=abortTpool(gNB->threadPool, req->key); + nb+=abortNotifiedFIFO(gNB->respDecode, req->key); + gNB->nbDecode-=nb; + LOG_D(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); + LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id); + AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", + ulsch_harq->processedSegments, nb, rdata->nbSegments); + ulsch_harq->processedSegments=rdata->nbSegments; + } + } + + //int dumpsig=0; + // if all segments are done + if (rdata->nbSegments == ulsch_harq->processedSegments) { + if (decodeSuccess) { + LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation (all seg) %d)\n", + gNB->Mod_id,ulsch_harq->frame,ulsch_harq->slot,rdata->harq_pid,pusch_pdu->pusch_data.new_data_indicator,ulsch_harq->status,ulsch_harq->round,ulsch_harq->TBS,rdata->decodeIterations); + ulsch_harq->status = SCH_IDLE; + ulsch_harq->round = 0; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + + LOG_D(PHY, "ULSCH received ok \n"); + nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 0,0); + //dumpsig=1; + } else { + LOG_D(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, TBS %d) r %d\n", + gNB->Mod_id, ulsch_harq->frame, ulsch_harq->slot, + rdata->harq_pid, pusch_pdu->pusch_data.new_data_indicator, ulsch_harq->status, + ulsch_harq->round, + ulsch_harq->ulsch_pdu.pusch_data.rv_index, + ulsch_harq->ulsch_pdu.rb_start, + ulsch_harq->ulsch_pdu.rb_size, + ulsch_harq->TBS, + r); + ulsch_harq->round++; + if (ulsch_harq->round >= ulsch->Mlimit) { + ulsch_harq->status = SCH_IDLE; + ulsch_harq->round = 0; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + } + ulsch_harq->handled = 1; + + LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id); + nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 1,0); + } +/* + if (ulsch_harq->ulsch_pdu.mcs_index == 9 && dumpsig==1) { +#ifdef __AVX2__ + int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0; +#else + int off = 0; +#endif + + LOG_M("rxsigF0_ext.m","rxsF0_ext", + &gNB->pusch_vars[0]->rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); + LOG_M("chestF0.m","chF0", + &gNB->pusch_vars[0]->ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); + LOG_M("chestF0_ext.m","chF0_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size))], + (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); + LOG_M("rxsigF0_comp.m","rxsF0_comp", + &gNB->pusch_vars[0]->rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); + LOG_M("rxsigF0_llr.m","rxsF0_llr", + &gNB->pusch_vars[0]->llr[0],(ulsch_harq->ulsch_pdu.nr_of_symbols-1)*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size * ulsch_harq->ulsch_pdu.qam_mod_order,1,0); + if (gNB->frame_parms.nb_antennas_rx > 1) { + + LOG_M("rxsigF1_ext.m","rxsF0_ext", + &gNB->pusch_vars[0]->rxdataF_ext[1][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); + LOG_M("chestF1.m","chF1", + &gNB->pusch_vars[0]->ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); + LOG_M("chestF1_ext.m","chF1_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[1][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size))], + (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); + LOG_M("rxsigF1_comp.m","rxsF1_comp", + &gNB->pusch_vars[0]->rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); + } + exit(-1); + + } */ + ulsch->last_iteration_cnt = rdata->decodeIterations; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0); + } +} + + void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid) { NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->ulsch_pdu; - uint8_t ret; uint8_t l, number_dmrs_symbols = 0; uint32_t G; uint16_t start_symbol, number_symbols, nb_re_dmrs; @@ -239,70 +350,81 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs pusch_pdu->qam_mod_order, pusch_pdu->nrOfLayers); - + + AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n", + pusch_pdu->rb_size, + number_symbols, + nb_re_dmrs, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + pusch_pdu->qam_mod_order, + pusch_pdu->nrOfLayers); + LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n", + pusch_pdu->rb_size, + number_symbols, + nb_re_dmrs, + pusch_pdu->ul_dmrs_symb_pos, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + pusch_pdu->qam_mod_order, + pusch_pdu->nrOfLayers); //---------------------------------------------------------- //------------------- ULSCH unscrambling ------------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_unscrambling_stats); - nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id]->llr, - G, - 0, - pusch_pdu->data_scrambling_id, - pusch_pdu->rnti); + nr_ulsch_unscrambling_optim(gNB->pusch_vars[ULSCH_id]->llr, + G, + 0, + pusch_pdu->data_scrambling_id, + pusch_pdu->rnti); stop_meas(&gNB->ulsch_unscrambling_stats); //---------------------------------------------------------- //--------------------- ULSCH decoding --------------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_decoding_stats); - ret = nr_ulsch_decoding(gNB, - ULSCH_id, - gNB->pusch_vars[ULSCH_id]->llr, - frame_parms, - pusch_pdu, - frame_rx, - slot_rx, - harq_pid, - G); + nr_ulsch_decoding(gNB, + ULSCH_id, + gNB->pusch_vars[ULSCH_id]->llr, + frame_parms, + pusch_pdu, + frame_rx, + slot_rx, + harq_pid, + G); + + while (gNB->nbDecode > 0) { + notifiedFIFO_elt_t *req=pullTpool(gNB->respDecode, gNB->threadPool); + nr_postDecode(gNB, req); + delNotifiedFIFO_elt(req); + } stop_meas(&gNB->ulsch_decoding_stats); - - - if (ret > gNB->ulsch[ULSCH_id][0]->max_ldpc_iterations){ - LOG_I(PHY, "ULSCH %d in error\n",ULSCH_id); - nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1); - } - else if(gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->b!=NULL){ - LOG_I(PHY, "ULSCH received ok \n"); - nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 0); - } } -void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag) { +void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag) { pthread_mutex_lock(&gNB->UL_INFO_mutex); - int timing_advance_update, cqi; - int sync_pos; - uint16_t mu = gNB->frame_parms.numerology_index; NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; + NR_gNB_SCH_STATS_t *stats=get_ulsch_stats(gNB,ulsch); nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu; // pdu->data = gNB->ulsch[ULSCH_id+1][0]->harq_processes[harq_pid]->b; - sync_pos = nr_est_timing_advance_pusch(gNB, ULSCH_id); // estimate timing advance for MAC - timing_advance_update = sync_pos * (1 << mu); // scale by the used scs numerology + int sync_pos = nr_est_timing_advance_pusch(gNB, ULSCH_id); // estimate timing advance for MAC // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size - switch (gNB->frame_parms.N_RB_DL) { - case 106: timing_advance_update /= 16; break; - case 217: timing_advance_update /= 32; break; - case 245: timing_advance_update /= 32; break; - case 273: timing_advance_update /= 32; break; - case 66: timing_advance_update /= 12; break; - default: abort(); - } + uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; + + // do some integer rounding to improve TA accuracy + int sync_pos_rounded; + if (sync_pos > 0) + sync_pos_rounded = sync_pos + (bw_scaling / 2) - 1; + else + sync_pos_rounded = sync_pos - (bw_scaling / 2) + 1; + if (stats) stats->sync_pos = sync_pos; + + int timing_advance_update = sync_pos_rounded / bw_scaling; // put timing advance command in 0..63 range timing_advance_update += 31; @@ -310,15 +432,63 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, if (timing_advance_update < 0) timing_advance_update = 0; if (timing_advance_update > 63) timing_advance_update = 63; - LOG_D(PHY, "Estimated timing advance PUSCH is = %d, timing_advance_update is %d \n", sync_pos,timing_advance_update); + if (crc_flag == 0) LOG_D(PHY, "%d.%d : Received PUSCH : Estimated timing advance PUSCH is = %d, timing_advance_update is %d \n", frame,slot_rx,sync_pos,timing_advance_update); + else if (harq_process->round>0 || dtx_flag == 0) { // increment round if crc_flag == 1 and not(dtx_flag ==1 and round==0) + harq_process->round++; + if (harq_process->round >= ulsch->Mlimit) { + harq_process->status = SCH_IDLE; + harq_process->round = 0; + harq_process->handled = 0; + ulsch->harq_mask &= ~(1 << harq_pid); + } + } + // estimate UL_CQI for MAC - // estimate UL_CQI for MAC (from antenna port 0 only) - int SNRtimes10 = dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0]) - 300;//(10*gNB->measurements.n0_power_dB[0]); + int SNRtimes10 = dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot) - + dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot); + LOG_D(PHY, "Estimated SNR for PUSCH is = %f dB (ulsch_power %f, noise %f)\n", SNRtimes10/10.0,dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot)/10.0,dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot)/10.0); + + int cqi; if (SNRtimes10 < -640) cqi=0; else if (SNRtimes10 > 635) cqi=255; else cqi=(640+SNRtimes10)/5; + + if (0/*pusch_pdu->mcs_index == 9*/) { +#ifdef __AVX2__ + int off = ((pusch_pdu->rb_size&1) == 1)? 4:0; +#else + int off = 0; +#endif + LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(slot_rx&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1); + LOG_M("rxsigF0_ext.m","rxsF0_ext", + &gNB->pusch_vars[0]->rxdataF_ext[0][pusch_pdu->start_symbol_index*NR_NB_SC_PER_RB * pusch_pdu->rb_size],pusch_pdu->nr_of_symbols*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("chestF0.m","chF0", + &gNB->pusch_vars[0]->ul_ch_estimates[0][pusch_pdu->start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); + LOG_M("chestF0_ext.m","chF0_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(pusch_pdu->start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (pusch_pdu->nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("rxsigF0_comp.m","rxsF0_comp", + &gNB->pusch_vars[0]->rxdataF_comp[0][pusch_pdu->start_symbol_index*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],pusch_pdu->nr_of_symbols*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("rxsigF0_llr.m","rxsF0_llr", + &gNB->pusch_vars[0]->llr[0],(pusch_pdu->nr_of_symbols-1)*NR_NB_SC_PER_RB *pusch_pdu->rb_size * pusch_pdu->qam_mod_order,1,0); + if (gNB->frame_parms.nb_antennas_rx > 1) { + LOG_M("rxsigF1.m","rxsF1",&gNB->common_vars.rxdataF[1][(slot_rx&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1); + LOG_M("rxsigF1_ext.m","rxsF1_ext", + &gNB->pusch_vars[0]->rxdataF_ext[1][pusch_pdu->start_symbol_index*NR_NB_SC_PER_RB * pusch_pdu->rb_size],pusch_pdu->nr_of_symbols*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("chestF1.m","chF1", + &gNB->pusch_vars[0]->ul_ch_estimates[1][pusch_pdu->start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); + LOG_M("chestF1_ext.m","chF1_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[1][(pusch_pdu->start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (pusch_pdu->nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("rxsigF1_comp.m","rxsF1_comp", + &gNB->pusch_vars[0]->rxdataF_comp[1][pusch_pdu->start_symbol_index*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],pusch_pdu->nr_of_symbols*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + } + exit(-1); + + } + // crc indication uint16_t num_crc = gNB->UL_INFO.crc_ind.number_crcs; gNB->UL_INFO.crc_ind.crc_list = &gNB->crc_pdu_list[0]; @@ -332,7 +502,8 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, gNB->crc_pdu_list[num_crc].num_cb = pusch_pdu->pusch_data.num_cb; gNB->crc_pdu_list[num_crc].ul_cqi = cqi; gNB->crc_pdu_list[num_crc].timing_advance = timing_advance_update; - gNB->crc_pdu_list[num_crc].rssi = 0xffff; // invalid value as this is not yet computed + // in terms of dBFS range -128 to 0 with 0.1 step + gNB->crc_pdu_list[num_crc].rssi = (dtx_flag==0) ? 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0])) : 0; gNB->UL_INFO.crc_ind.number_crcs++; @@ -346,7 +517,7 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, gNB->rx_pdu_list[num_rx].harq_id = harq_pid; gNB->rx_pdu_list[num_rx].ul_cqi = cqi; gNB->rx_pdu_list[num_rx].timing_advance = timing_advance_update; - gNB->rx_pdu_list[num_rx].rssi = 0xffff; // invalid value as this is not yet computed + gNB->rx_pdu_list[num_rx].rssi = gNB->crc_pdu_list[num_crc].rssi; if (crc_flag) gNB->rx_pdu_list[num_rx].pdu_length = 0; else { @@ -359,45 +530,146 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, pthread_mutex_unlock(&gNB->UL_INFO_mutex); } +// Function to fill UL RB mask to be used for N0 measurements +void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { + + int rb = 0; + int rb2 = 0; + int prbpos = 0; + + for (int symbol=0;symbol<14;symbol++) { + for (int m=0;m<9;m++) { + gNB->rb_mask_ul[symbol][m] = 0; + for (int i=0;i<32;i++) { + prbpos = (m*32)+i; + if (prbpos>gNB->frame_parms.N_RB_UL) break; + gNB->rb_mask_ul[symbol][m] |= (gNB->ulprbbl[prbpos]>0 ? 1 : 0)<pucch[i]; + if (pucch) { + if ((pucch->active == 1) && + (pucch->frame == frame_rx) && + (pucch->slot == slot_rx) ) { + nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; + LOG_D(PHY,"%d.%d pucch %d : start_symbol %d, nb_symbols %d, prb_size %d\n",frame_rx,slot_rx,i,pucch_pdu->start_symbol_index,pucch_pdu->nr_of_symbols,pucch_pdu->prb_size); + for (int symbol=pucch_pdu->start_symbol_index ; symbol<(pucch_pdu->start_symbol_index+pucch_pdu->nr_of_symbols);symbol++) { + if(gNB->frame_parms.frame_type == FDD || + (gNB->frame_parms.frame_type == TDD && gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol].slot_config.value==1)) { + for (rb=0; rbprb_size; rb++) { + rb2 = rb + pucch_pdu->bwp_start + + ((symbol < pucch_pdu->start_symbol_index+(pucch_pdu->nr_of_symbols>>1)) || (pucch_pdu->freq_hop_flag == 0) ? + pucch_pdu->prb_start : pucch_pdu->second_hop_prb); + gNB->rb_mask_ul[symbol][rb2>>5] |= (1<<(rb2&31)); + } + } + } + } + } + } + + for (int ULSCH_id=0;ULSCH_idnumber_of_nr_ulsch_max;ULSCH_id++) { + NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0]; + int harq_pid; + NR_UL_gNB_HARQ_t *ulsch_harq; + if ((ulsch) && + (ulsch->rnti > 0)) { + for (harq_pid=0;harq_pidharq_processes[harq_pid]; + AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); + if ((ulsch_harq->status == NR_ACTIVE) && + (ulsch_harq->frame == frame_rx) && + (ulsch_harq->slot == slot_rx) && + (ulsch_harq->handled == 0)){ + uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; + uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; + for (int symbol=symbol_start ; symbolframe_parms.frame_type == FDD || + (gNB->frame_parms.frame_type == TDD && gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol].slot_config.value==1)) { + LOG_D(PHY,"symbol %d Filling rb_mask_ul rb_size %d\n",symbol,ulsch_harq->ulsch_pdu.rb_size); + for (rb=0; rbulsch_pdu.rb_size; rb++) { + rb2 = rb+ulsch_harq->ulsch_pdu.rb_start+ulsch_harq->ulsch_pdu.bwp_start; + gNB->rb_mask_ul[symbol][rb2>>5] |= (1<<(rb2&31)); + } + } + } + } + } + } + } + +} + void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { uint8_t symbol; unsigned char aa; - for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) { - // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0); - + for(symbol = 0; symbol < (gNB->frame_parms.Ncp==EXTENDED?12:14); symbol++) { for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { nr_slot_fep_ul(&gNB->frame_parms, gNB->common_vars.rxdata[aa], gNB->common_vars.rxdataF[aa], symbol, slot_rx, - 0, 0); } } + for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { + apply_nr_rotation_ul(&gNB->frame_parms, + gNB->common_vars.rxdataF[aa], + slot_rx, + 0, + gNB->frame_parms.Ncp==EXTENDED?12:14, + gNB->frame_parms.ofdm_symbol_size); + } + } -void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { +int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { + /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ + int pucch_decode_done = 0; + int pusch_decode_done = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); + fill_ul_rb_mask(gNB, frame_rx, slot_rx); + + int first_symb=0,num_symb=0; + if (gNB->frame_parms.frame_type == TDD) + for(int symbol_count=0; symbol_countgNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { + if (num_symb==0) first_symb=symbol_count; + num_symb++; + } + } + else num_symb=NR_NUMBER_OF_SYMBOLS_PER_SLOT; + gNB_I0_measurements(gNB,slot_rx,first_symb,num_symb); + + int offset = 10*gNB->frame_parms.ofdm_symbol_size + gNB->frame_parms.first_carrier_offset; + int power_rxF = signal_energy_nodc(&gNB->common_vars.rxdataF[0][offset+(47*12)],12*18); + LOG_D(PHY,"frame %d, slot %d: UL signal energy %d\n",frame_rx,slot_rx,power_rxF); + + start_meas(&gNB->phy_proc_rx); + for (int i=0;ipucch[i]; if (pucch) { if ((pucch->active == 1) && - (pucch->frame == frame_rx) && - (pucch->slot == slot_rx) ) { + (pucch->frame == frame_rx) && + (pucch->slot == slot_rx) ) { - nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch[i].pucch_pdu; + pucch_decode_done = 1; + + nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; uint16_t num_ucis; - switch (pucch_pdu->format_type) { case 0: - num_ucis = gNB->UL_INFO.uci_ind.num_ucis; gNB->UL_INFO.uci_ind.uci_list = &gNB->uci_pdu_list[0]; gNB->UL_INFO.uci_ind.sfn = frame_rx; @@ -406,67 +678,144 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) gNB->uci_pdu_list[num_ucis].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t); nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &gNB->uci_pdu_list[num_ucis].pucch_pdu_format_0_1; + offset = pucch_pdu->start_symbol_index*gNB->frame_parms.ofdm_symbol_size + (gNB->frame_parms.first_carrier_offset+pucch_pdu->prb_start*12); + power_rxF = signal_energy_nodc(&gNB->common_vars.rxdataF[0][offset],12); + LOG_D(PHY,"frame %d, slot %d: PUCCH signal energy %d\n",frame_rx,slot_rx,power_rxF); + nr_decode_pucch0(gNB, - slot_rx, + frame_rx, + slot_rx, uci_pdu_format0, pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; pucch->active = 0; - break; + break; + case 2: + num_ucis = gNB->UL_INFO.uci_ind.num_ucis; + gNB->UL_INFO.uci_ind.uci_list = &gNB->uci_pdu_list[0]; + gNB->UL_INFO.uci_ind.sfn = frame_rx; + gNB->UL_INFO.uci_ind.slot = slot_rx; + gNB->uci_pdu_list[num_ucis].pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE; + gNB->uci_pdu_list[num_ucis].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &gNB->uci_pdu_list[num_ucis].pucch_pdu_format_2_3_4; + + nr_decode_pucch2(gNB, + slot_rx, + uci_pdu_format2, + pucch_pdu); + + gNB->UL_INFO.uci_ind.num_ucis += 1; + pucch->active = 0; + break; default: - AssertFatal(1==0,"Only PUCCH format 0 is currently supported\n"); + AssertFatal(1==0,"Only PUCCH formats 0 and 2 are currently supported\n"); } } } } - for (int ULSCH_id=0;ULSCH_idnumber_of_nr_ulsch_max;ULSCH_id++) { NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0]; int harq_pid; - //int no_sig; + int no_sig; NR_UL_gNB_HARQ_t *ulsch_harq; if ((ulsch) && (ulsch->rnti > 0)) { // for for an active HARQ process for (harq_pid=0;harq_pidharq_processes[harq_pid]; - AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); - if ((ulsch_harq->status == NR_ACTIVE) && - (ulsch_harq->frame == frame_rx) && - (ulsch_harq->slot == slot_rx) && - (ulsch_harq->handled == 0)){ + ulsch_harq = ulsch->harq_processes[harq_pid]; + AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); + if ((ulsch_harq->status == NR_ACTIVE) && + (ulsch_harq->frame == frame_rx) && + (ulsch_harq->slot == slot_rx) && + (ulsch_harq->handled == 0)){ + + LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n", + frame_rx,slot_rx); + int num_dmrs=0; + for (int s=0;sulsch_pdu.ul_dmrs_symb_pos>>s)&1; #ifdef DEBUG_RXDATA NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; RU_t *ru = gNB->RU_list[0]; int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx,frame_parms,0); slot_offset -= ru->N_TA_offset; - char name[128]; - FILE *f; - sprintf(name, "rxdata.%d.%d.raw", frame_rx,slot_rx); - f = fopen(name, "w"); if (f == NULL) exit(1); - fwrite(&ru->common.rxdata[0][slot_offset],2,frame_parms->get_samples_per_slot(slot_rx,frame_parms)*2, f); - fclose(f); + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[0]=(int16_t)ulsch->rnti; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[1]=(int16_t)ulsch_harq->ulsch_pdu.rb_size; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[2]=(int16_t)ulsch_harq->ulsch_pdu.rb_start; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[3]=(int16_t)ulsch_harq->ulsch_pdu.nr_of_symbols; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[4]=(int16_t)ulsch_harq->ulsch_pdu.start_symbol_index; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[5]=(int16_t)ulsch_harq->ulsch_pdu.mcs_index; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[6]=(int16_t)ulsch_harq->ulsch_pdu.pusch_data.rv_index; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[7]=(int16_t)harq_pid; + memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset+4],&ru->common.rxdata[0][slot_offset],frame_parms->get_samples_per_slot(slot_rx,frame_parms)*sizeof(int32_t)); + gNB->common_vars.debugBuff_sample_offset+=(frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+4); + if(gNB->common_vars.debugBuff_sample_offset>((frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+2)*20)) { + FILE *f; + f = fopen("rxdata_buff.raw", "w"); if (f == NULL) exit(1); + fwrite((int16_t*)gNB->common_vars.debugBuff,2,(frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+4)*20*2, f); + fclose(f); + exit(-1); + } #endif - uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; - uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; + pusch_decode_done = 1; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,1); - for(uint8_t symbol = symbol_start; symbol < symbol_end; symbol++) { - nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, symbol, harq_pid); + start_meas(&gNB->rx_pusch_stats); + no_sig = nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, harq_pid); + if (no_sig) { + LOG_D(PHY, "PUSCH not detected in frame %d, slot %d\n", frame_rx, slot_rx); + nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1); + return 1; } + gNB->pusch_vars[ULSCH_id]->ulsch_power_tot=0; + gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot=0; + for (int aarx=0;aarxframe_parms.nb_antennas_rx;aarx++) { + gNB->pusch_vars[ULSCH_id]->ulsch_power[aarx]/=num_dmrs; + gNB->pusch_vars[ULSCH_id]->ulsch_power_tot += gNB->pusch_vars[ULSCH_id]->ulsch_power[aarx]; + gNB->pusch_vars[ULSCH_id]->ulsch_noise_power[aarx]/=num_dmrs; + gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot += gNB->pusch_vars[ULSCH_id]->ulsch_noise_power[aarx]; + } + if (dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot) < + dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot) + gNB->pusch_thres) { + NR_gNB_SCH_STATS_t *stats=get_ulsch_stats(gNB,ulsch); + + LOG_D(PHY, "PUSCH not detected in %d.%d (%d,%d,%d)\n",frame_rx,slot_rx, + dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot), + dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot),gNB->pusch_thres); + gNB->pusch_vars[ULSCH_id]->ulsch_power_tot = gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot; + nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1); + gNB->pusch_vars[ULSCH_id]->DTX=1; + if (stats) stats->DTX++; + return 1; + } else gNB->pusch_vars[ULSCH_id]->DTX=0; + + stop_meas(&gNB->rx_pusch_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,0); //LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); //LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,1); - nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid); + nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,0); break; } } } } + stop_meas(&gNB->phy_proc_rx); + // figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS + if ((frame_rx&127) == 0 && slot_rx==19) { + LOG_I(NR_PHY, "Number of bad PUCCH received: %lu\n", gNB->bad_pucch); + } + + if (pucch_decode_done || pusch_decode_done) { + T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); + return 0; } diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index b393e9566e..d7e0332b85 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -34,13 +34,13 @@ #include "PHY/NR_TRANSPORT/nr_dci.h" #include "phy_frame_config_nr.h" - +void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx); void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp); -void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx, int slot_tx, int do_meas); +void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, int frame_tx, int slot_tx, int do_meas); void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx); -void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx); -void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_prach_pdu_t *prach_pdu); -void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot); +int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx); +void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot); +void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_dl_tti_ssb_pdu ssb_pdu); void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa); diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index c6aea2ec08..c98574ec42 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -20,6 +20,7 @@ */ /* + \brief NR UE PHY functions prototypes \author R. Knopp, F. Kaltenberger \company EURECOM \email knopp@eurecom.fr @@ -103,27 +104,28 @@ void phy_procedures_UE_lte(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN int phy_procedures_RN_UE_RX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type); /*! \brief Scheduling for UE TX procedures in normal subframes. - @param phy_vars_ue Pointer to UE variables on which to act + @param ue Pointer to UE variables on which to act @param proc Pointer to RXn-TXnp4 proc information @param eNB_id Local id of eNB on which to act - @param abstraction_flag Indicator of PHY abstraction - @param mode calib/normal mode - @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id, uint8_t thread_id); -/*! \brief Scheduling for UE RX procedures in normal subframes. - @param last_slot Index of last slot (0-19) - @param phy_vars_ue Pointer to UE variables on which to act - @param proc Pointer to RXn_TXnp4 proc information - @param eNB_id Local id of eNB on which to act - @param abstraction_flag Indicator of PHY abstraction - @param mode calibration/debug mode - @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying - @param phy_vars_rn pointer to RN variables -*/ -int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t do_pdcch_flag,runmode_t mode); -int phy_procedures_slot_parallelization_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,relaying_type_t r_type); +void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id); +/*! \brief Scheduling for UE RX procedures in normal subframes. + @param ue Pointer to UE variables on which to act + @param proc Pointer to proc information + @param gNB_id Local id of eNB on which to act + @param dlsch_parallel use multithreaded dlsch processing + @param txFifo Result fifo if PDSCH is run in parallel +*/ +int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, + uint8_t dlsch_parallel, + notifiedFIFO_t *txFifo); + +int phy_procedures_slot_parallelization_nrUE_RX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id, uint8_t abstraction_flag, uint8_t do_pdcch_flag, relaying_type_t r_type); + +void processSlotTX(void *arg); #ifdef UE_SLOT_PARALLELISATION void *UE_thread_slot1_dl_processing(void *arg); @@ -223,7 +225,7 @@ void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); @param @param */ -void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, runmode_t mode); +void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id); int is_nr_prach_subframe(NR_DL_FRAME_PARMS *frame_parms, uint32_t frame, uint8_t subframe); @@ -298,14 +300,12 @@ uint16_t nr_get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1); int8_t nr_find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); -/*! \brief Compute the timing adjustment at UE side from the old TA offset and the new received TA command - @param Mod_id Local UE index on which to act - @param CC_id Component Carrier Index - @param ta_command TA command received from the network - @param mu numerology index (0,1,2..) +/*! \brief UL time alignment procedures for TA application + @param PHY_VARS_NR_UE ue + @param int slot_tx + @param int frame_tx */ -void nr_process_timing_advance(module_id_t Mod_id,uint8_t CC_id,uint8_t ta_command, uint8_t mu, uint16_t bwp_ul_NB_RB); -void nr_process_timing_advance_rar(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint16_t timing_advance); +void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx); unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb); @@ -387,9 +387,56 @@ void set_tx_harq_id(NR_UE_ULSCH_t *ulsch, int harq_pid, int slot_tx); int get_tx_harq_id(NR_UE_ULSCH_t *ulsch, int slot_tx); int is_pbch_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp); +int is_ssb_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp); + +/*! \brief This function prepares the dl indication to pass to the MAC + @param + @param + @param + @param + */ +void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_rx_indication_t *rx_ind, + UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + uint8_t gNB_id); /*@}*/ +/*! \brief This function prepares the dl rx indication + @param + @param + @param + @param + */ +void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, + uint8_t pdu_type, + uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + uint16_t n_pdus); + +bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int gNB_id, + PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + int *dlsch_errors, + uint8_t dlsch_parallel); + +int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int eNB_id, PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1); + +int nr_ue_pdcch_procedures(uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int n_ss); + #endif diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index ea73f2fecc..6848101a27 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -42,8 +42,12 @@ extern PHY_VARS_NR_UE ***PHY_vars_UE_g; +const char *dl_pdu_type[]={"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH"}; +const char *ul_pdu_type[]={"PRACH", "PUCCH", "PUSCH", "SRS"}; + int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ + bool found = false; if(scheduled_response != NULL){ module_id_t module_id = scheduled_response->module_id; @@ -52,50 +56,58 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ int slot = scheduled_response->slot; // Note: we have to handle the thread IDs for this. To be revisited completely. - thread_id = PHY_vars_UE_g[module_id][cc_id]->current_thread_id[slot]; + thread_id = scheduled_response->thread_id; NR_UE_DLSCH_t *dlsch0 = NULL; NR_UE_PDCCH *pdcch_vars = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[thread_id][0]; NR_UE_ULSCH_t *ulsch0 = PHY_vars_UE_g[module_id][cc_id]->ulsch[thread_id][0][0]; - NR_DL_FRAME_PARMS frame_parms = PHY_vars_UE_g[module_id][cc_id]->frame_parms; - //PRACH_RESOURCES_t *prach_resources = PHY_vars_UE_g[module_id][cc_id]->prach_resources[0]; - - // PUCCH_ConfigCommon_nr_t *pucch_config_common = PHY_vars_UE_g[module_id][cc_id]->pucch_config_common_nr[0]; - // PUCCH_Config_t *pucch_config_dedicated = PHY_vars_UE_g[module_id][cc_id]->pucch_config_dedicated_nr[0]; + NR_UE_PUCCH *pucch_vars = PHY_vars_UE_g[module_id][cc_id]->pucch_vars[thread_id][0]; if(scheduled_response->dl_config != NULL){ fapi_nr_dl_config_request_t *dl_config = scheduled_response->dl_config; - LOG_D(PHY,"Received %d DL pdus\n",dl_config->number_pdus); pdcch_vars->nb_search_space = 0; for (i = 0; i < dl_config->number_pdus; ++i){ + AssertFatal(dl_config->number_pdus < FAPI_NR_DL_CONFIG_LIST_NUM,"dl_config->number_pdus %d out of bounds\n",dl_config->number_pdus); + AssertFatal(dl_config->dl_config_list[i].pdu_type<=FAPI_NR_DL_CONFIG_TYPES,"pdu_type %d > 2\n",dl_config->dl_config_list[i].pdu_type); + LOG_D(PHY, "In %s: frame %d slot %d received 1 DL %s PDU of %d total DL PDUs:\n", + __FUNCTION__, scheduled_response->frame, slot, dl_pdu_type[dl_config->dl_config_list[i].pdu_type - 1], dl_config->number_pdus); if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_DCI) { fapi_nr_dl_config_dci_dl_pdu_rel15_t *pdcch_config = &dl_config->dl_config_list[i].dci_config_pdu.dci_config_rel15; memcpy((void*)&pdcch_vars->pdcch_config[pdcch_vars->nb_search_space],(void*)pdcch_config,sizeof(*pdcch_config)); pdcch_vars->nb_search_space = pdcch_vars->nb_search_space + 1; + pdcch_vars->sfn = scheduled_response->frame; + pdcch_vars->slot = slot; LOG_D(PHY,"Number of DCI SearchSpaces %d\n",pdcch_vars->nb_search_space); } else { + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &dl_config->dl_config_list[i].dlsch_config_pdu.dlsch_config_rel15; + uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr; + if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_DLSCH){ dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[thread_id][0][0]; } else if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH){ dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch_ra[0]; + dlsch0->rnti_type = _RA_RNTI_; + dlsch0->harq_processes[current_harq_pid]->status = ACTIVE; + } + else if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH){ + dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch_SI[0]; + dlsch0->rnti_type = _SI_RNTI_; + dlsch0->harq_processes[current_harq_pid]->status = ACTIVE; } - - fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &dl_config->dl_config_list[i].dlsch_config_pdu.dlsch_config_rel15; - uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr; - NR_DL_UE_HARQ_t *dlsch0_harq; dlsch0->current_harq_pid = current_harq_pid; dlsch0->active = 1; dlsch0->rnti = dl_config->dl_config_list[i].dlsch_config_pdu.rnti; - //dlsch0->harq_processes[0]->mcs = &dlsch_config_pdu->mcs; - dlsch0_harq = dlsch0->harq_processes[current_harq_pid]; + LOG_D(PHY,"slot %d current_harq_pid = %d\n",slot, current_harq_pid); + + NR_DL_UE_HARQ_t *dlsch0_harq = dlsch0->harq_processes[current_harq_pid]; if (dlsch0_harq){ dlsch0_harq->BWPStart = dlsch_config_pdu->BWPStart; @@ -110,27 +122,47 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->mcs = dlsch_config_pdu->mcs; dlsch0_harq->rvidx = dlsch_config_pdu->rv; dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; - dlsch0_harq->harq_ack.pucch_resource_indicator = dlsch_config_pdu->pucch_resource_id; - dlsch0_harq->harq_ack.slot_for_feedback_ack = (slot+dlsch_config_pdu->pdsch_to_harq_feedback_time_ind)%frame_parms.slots_per_frame; - dlsch0_harq->Nl=1; - dlsch0_harq->mcs_table=0; - dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); - dlsch0_harq->harq_ack.vDAI_DL = dlsch_config_pdu->dai; + //get nrOfLayers from DCI info + uint8_t Nl = 0; + for (i = 0; i < 4; i++) { + if (dlsch_config_pdu->dmrs_ports[i] >= i) Nl += 1; + } + dlsch0_harq->Nl = Nl; + dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; + downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch_config_pdu->rv, dlsch0->rnti_type); + if (dlsch0_harq->status != ACTIVE) { + // dlsch0_harq->status not ACTIVE due to false retransmission + // Reset the following flag to skip PDSCH procedures in that case and retrasmit harq status + dlsch0->active = 0; + update_harq_status(module_id,dlsch0->current_harq_pid,dlsch0_harq->ack); + } + /* PTRS */ + dlsch0_harq->PTRSFreqDensity = dlsch_config_pdu->PTRSFreqDensity; + dlsch0_harq->PTRSTimeDensity = dlsch_config_pdu->PTRSTimeDensity; + dlsch0_harq->PTRSPortIndex = dlsch_config_pdu->PTRSPortIndex; + dlsch0_harq->nEpreRatioOfPDSCHToPTRS = dlsch_config_pdu->nEpreRatioOfPDSCHToPTRS; + dlsch0_harq->PTRSReOffset = dlsch_config_pdu->PTRSReOffset; + dlsch0_harq->pduBitmap = dlsch_config_pdu->pduBitmap; LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs); } } } - } else { - pdcch_vars->nb_search_space = 0; + dl_config->number_pdus = 0; } if (scheduled_response->ul_config != NULL){ fapi_nr_ul_config_request_t *ul_config = scheduled_response->ul_config; + int pdu_done = 0; + pthread_mutex_lock(&ul_config->mutex_ul_config); + LOG_D(PHY, "%d.%d ul S ul_config %p pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_done, ul_config->number_pdus); for (i = 0; i < ul_config->number_pdus; ++i){ - uint8_t pdu_type = ul_config->ul_config_list[i].pdu_type, pucch_resource_id, current_harq_pid, format, gNB_id = 0; + AssertFatal(ul_config->ul_config_list[i].pdu_type <= FAPI_NR_UL_CONFIG_TYPES,"pdu_type %d out of bounds\n",ul_config->ul_config_list[i].pdu_type); + LOG_D(PHY, "In %s: processing %s PDU of %d total UL PDUs (ul_config %p) \n", __FUNCTION__, ul_pdu_type[ul_config->ul_config_list[i].pdu_type - 1], ul_config->number_pdus, ul_config); + + uint8_t pdu_type = ul_config->ul_config_list[i].pdu_type, current_harq_pid, gNB_id = 0; /* PRACH */ //NR_PRACH_RESOURCES_t *prach_resources; fapi_nr_ul_config_prach_pdu *prach_config_pdu; @@ -138,9 +170,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu; /* PUCCH */ fapi_nr_ul_config_pucch_pdu *pucch_config_pdu; - PUCCH_ConfigCommon_nr_t *pucch_config_common_nr; - PUCCH_Config_t *pucch_config_dedicated_nr; - PUCCH_format_t *format_params; + LOG_D(PHY, "%d.%d ul B ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus); switch (pdu_type){ @@ -149,6 +179,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ pusch_config_pdu = &ul_config->ul_config_list[i].pusch_config_pdu; current_harq_pid = pusch_config_pdu->pusch_data.harq_process_id; NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch0->harq_processes[current_harq_pid]; + harq_process_ul_ue->status = 0; if (harq_process_ul_ue){ @@ -158,13 +189,19 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ ulsch0->f_pusch = pusch_config_pdu->absolute_delta_PUSCH; - if (scheduled_response->tx_request){ - fapi_nr_tx_request_body_t *tx_req_body = scheduled_response->tx_request->tx_request_body; - - //harq_process_ul_ue->a = (unsigned char*)calloc(TBS/8, sizeof(unsigned char)); - memcpy(harq_process_ul_ue->a, tx_req_body->pdu, tx_req_body->pdu_length); - - harq_process_ul_ue->status = ACTIVE; + if (scheduled_response->tx_request) { + for (int j=0; jtx_request->number_of_pdus; j++) { + fapi_nr_tx_request_body_t *tx_req_body = &scheduled_response->tx_request->tx_request_body[j]; + if ((tx_req_body->pdu_index == i) && (tx_req_body->pdu_length > 0)) { + LOG_D(PHY,"%d.%d Copying %d bytes to harq_process_ul_ue->a (harq_pid %d)\n",scheduled_response->frame,slot,tx_req_body->pdu_length,current_harq_pid); + memcpy(harq_process_ul_ue->a, tx_req_body->pdu, tx_req_body->pdu_length); + harq_process_ul_ue->status = ACTIVE; + ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more + pdu_done++; + LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus); + break; + } + } } } else { @@ -177,66 +214,59 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ break; case (FAPI_NR_UL_CONFIG_TYPE_PUCCH): - // pucch config pdu + found = false; pucch_config_pdu = &ul_config->ul_config_list[i].pucch_config_pdu; - pucch_resource_id = 0; //FIXME!!! - format = 1; // FIXME!!! - pucch_config_common_nr = &PHY_vars_UE_g[module_id][cc_id]->pucch_config_common_nr[0]; - pucch_config_dedicated_nr = &PHY_vars_UE_g[module_id][cc_id]->pucch_config_dedicated_nr[0]; - format_params = &pucch_config_dedicated_nr->PUCCH_Resource[pucch_resource_id]->format_parameters; - - format_params->initialCyclicShift = pucch_config_pdu->initialCyclicShift; - format_params->nrofSymbols = pucch_config_pdu->nrofSymbols; - format_params->startingSymbolIndex = pucch_config_pdu->startingSymbolIndex; - format_params->nrofPRBs = pucch_config_pdu->nrofPRBs; - format_params->timeDomainOCC = pucch_config_pdu->timeDomainOCC; - format_params->occ_length = pucch_config_pdu->occ_length; - format_params->occ_Index = pucch_config_pdu->occ_Index; - - pucch_config_dedicated_nr->PUCCH_Resource[pucch_resource_id]->startingPRB = pucch_config_pdu->startingPRB; - pucch_config_dedicated_nr->PUCCH_Resource[pucch_resource_id]->intraSlotFrequencyHopping = pucch_config_pdu->intraSlotFrequencyHopping; - pucch_config_dedicated_nr->PUCCH_Resource[pucch_resource_id]->secondHopPRB = pucch_config_pdu->secondHopPRB; // Not sure this parameter is used - pucch_config_dedicated_nr->formatConfig[format - 1]->additionalDMRS = pucch_config_pdu->additionalDMRS; // At this point we need to know which format is going to be used - pucch_config_dedicated_nr->formatConfig[format - 1]->pi2PBSK = pucch_config_pdu->pi2PBSK; - - pucch_config_common_nr->pucch_GroupHopping = pucch_config_pdu->pucch_GroupHopping; - pucch_config_common_nr->hoppingId = pucch_config_pdu->hoppingId; - pucch_config_common_nr->p0_nominal = pucch_config_pdu->p0_nominal; - - /* pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.initialCyclicShift = pucch_config_pdu->initialCyclicShift; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.nrofSymbols = pucch_config_pdu->nrofSymbols; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.startingSymbolIndex = pucch_config_pdu->startingSymbolIndex; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.nrofPRBs = pucch_config_pdu->nrofPRBs; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->startingPRB = pucch_config_pdu->startingPRB; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.timeDomainOCC = pucch_config_pdu->timeDomainOCC; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.occ_length = pucch_config_pdu->occ_length; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->format_parameters.occ_Index = pucch_config_pdu->occ_Index; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->intraSlotFrequencyHopping = pucch_config_pdu->intraSlotFrequencyHopping; - pucch_config_dedicated->PUCCH_Resource[pucch_resource_id]->secondHopPRB = pucch_config_pdu->secondHopPRB; // Not sure this parameter is used - pucch_config_dedicated->formatConfig[format-1]->additionalDMRS = pucch_config_pdu->additionalDMRS; // At this point we need to know which format is going to be used - pucch_config_dedicated->formatConfig[format-1]->pi2PBSK = pucch_config_pdu->pi2PBSK; - pucch_config_common->pucch_GroupHopping = pucch_config_pdu->pucch_GroupHopping; - pucch_config_common->hoppingId = pucch_config_pdu->hoppingId; - pucch_config_common->p0_nominal = pucch_config_pdu->p0_nominal;*/ + for(int j=0; j<2; j++) { + if(pucch_vars->active[j] == false) { + LOG_D(PHY,"%d.%d Copying pucch pdu to UE PHY\n",scheduled_response->frame,slot); + memcpy((void*)&(pucch_vars->pucch_pdu[j]), (void*)pucch_config_pdu, sizeof(fapi_nr_ul_config_pucch_pdu)); + pucch_vars->active[j] = true; + found = true; + ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more + pdu_done++; + LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus); + break; + } + } + if (!found) + LOG_E(PHY, "Couldn't find allocation for PUCCH PDU in PUCCH VARS\n"); break; case (FAPI_NR_UL_CONFIG_TYPE_PRACH): // prach config pdu - //prach_resources = PHY_vars_UE_g[module_id][cc_id]->prach_resources[gNB_id]; prach_config_pdu = &ul_config->ul_config_list[i].prach_config_pdu; memcpy((void*)&(PHY_vars_UE_g[module_id][cc_id]->prach_vars[gNB_id]->prach_pdu), (void*)prach_config_pdu, sizeof(fapi_nr_ul_config_prach_pdu)); - PHY_vars_UE_g[module_id][cc_id]->prach_vars[gNB_id]->prach_Config_enabled = 1; + ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more + pdu_done++; + LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus); + break; + + case (FAPI_NR_UL_CONFIG_TYPE_DONE): + pdu_done++; // count the no of pdu processed + LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus); break; default: + ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more + pdu_done++; // count the no of pdu processed + LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus); break; } } - } else { + + //Clear the fields when all the config pdu are done + if (pdu_done == ul_config->number_pdus) { + if (scheduled_response->tx_request) + scheduled_response->tx_request->number_of_pdus = 0; + ul_config->sfn = 0; + ul_config->slot = 0; + ul_config->number_pdus = 0; + LOG_D(PHY, "%d.%d clear ul_config %p\n", scheduled_response->frame, slot, ul_config); + memset(ul_config->ul_config_list, 0, sizeof(ul_config->ul_config_list)); + } + pthread_mutex_unlock(&ul_config->mutex_ul_config); } - } - return 0; } @@ -247,9 +277,11 @@ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){ fapi_nr_config_request_t *nrUE_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config; - if(phy_config != NULL) + if(phy_config != NULL) { memcpy(nrUE_config,&phy_config->config_req,sizeof(fapi_nr_config_request_t)); - + if (PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->UE_mode[0] == NOT_SYNCHED) + PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->UE_mode[0] = PRACH; + } return 0; } diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h index 9b7b87a18c..0cd882a9b5 100755 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h @@ -43,5 +43,6 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response); \param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config); +void update_harq_status(module_id_t module_id, uint8_t harq_pid, uint8_t ack_nack); -#endif \ No newline at end of file +#endif diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 3c3017d658..5b65131934 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -98,43 +98,6 @@ #define DL_DCI (1) #define UL_DCI (0) -/******************************************************************* -* -* NAME : get_dci_info_for_harq -* -* PARAMETERS : pointer to ue context -* id of current gNB -* number of uplink processes -* maximum number of uplink retransmissions -* RETURN : none -* -* DESCRIPTION : update HARQ entity with information from DCI -* TS 38.212 7.3.1.2 DCI formats for scheduling PDSCH -* -*********************************************************************/ - -void get_dci_info_for_harq(PHY_VARS_NR_UE *ue, NR_DCI_INFO_EXTRACTED_t *nr_dci_info_extracted, - NR_UE_DLSCH_t **dlsch, NR_UE_ULSCH_t *ulsch, uint8_t nr_tti_rx, uint8_t tx_offset) -{ - if (nr_dci_info_extracted->identifier_dci_formats == DL_DCI) { - - dlsch[0]->current_harq_pid = nr_dci_info_extracted->harq_process_number; - - NR_DL_UE_HARQ_t *dl_harq = dlsch[0]->harq_processes[dlsch[0]->current_harq_pid]; - - dl_harq->harq_ack.vDAI_DL = nr_dci_info_extracted->dai+1; - dl_harq->harq_ack.pucch_resource_indicator = nr_dci_info_extracted->pucch_resource_ind; - dl_harq->harq_ack.slot_for_feedback_ack = (nr_tti_rx + nr_dci_info_extracted->pdsch_to_harq_feedback_time_ind)%ue->frame_parms.ttis_per_subframe; - dl_harq->harq_ack.harq_id = nr_dci_info_extracted->harq_process_number; - dl_harq->harq_ack.rx_status = downlink_harq_process(dl_harq, dlsch[0]->current_harq_pid, nr_dci_info_extracted->ndi, dlsch[0]->rnti_type); - } - else if (nr_dci_info_extracted->identifier_dci_formats == UL_DCI) { - - /* store harq id for which pusch should be transmitted at rx_slot + tx_offset */ - set_tx_harq_id(ulsch, nr_dci_info_extracted->harq_process_number, (nr_tti_rx + tx_offset)%ue->frame_parms.ttis_per_subframe); - ulsch->harq_processes[nr_dci_info_extracted->harq_process_number]->tx_status = uplink_harq_process(ulsch, nr_dci_info_extracted->harq_process_number, nr_dci_info_extracted->ndi, ulsch->rnti_type); - } -} /******************************************************************* * @@ -295,14 +258,14 @@ harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, int ndi, u /* 38.321 5.4.2.1 2> if the uplink grant was received on PDCCH for the C-RNTI and the HARQ buffer of the identified process is empty */ if ((ulsch->harq_processes[harq_pid]->first_tx == 1) && (rnti_type == _C_RNTI_)) { /* no transmission yet on this process so consider its harq buffer as empty */ - ulsch->harq_processes[harq_pid]->first_tx = 0; + ulsch->harq_processes[harq_pid]->first_tx = 0; ulsch->harq_processes[harq_pid]->pusch_pdu.pusch_data.new_data_indicator = ndi; /* store first value of ndi */ ulsch->harq_processes[harq_pid]->round = 0; ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1; result_harq = NEW_TRANSMISSION_HARQ; - NR_TST_PHY_PRINTF("[HARQ-UL-PUSCH harqId : %d] first new transmission \n", harq_pid); + LOG_D(PHY, "[HARQ-UL-PUSCH harqId : %d] first new transmission \n", harq_pid); } /* 38.321 5.4.2.1 2> if the received grant was not addressed to a Temporary C-RNTI on PDCCH, and the NDI provided in the associated HARQ */ /* information has been toggled compared to the value in the previous transmission of this TB of this HARQ process */ @@ -313,7 +276,7 @@ harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, int ndi, u result_harq = NEW_TRANSMISSION_HARQ; - NR_TST_PHY_PRINTF("[HARQ-UL-PUSCH harqId : %d] new transmission due to toogle of ndi \n", harq_pid); + LOG_D(PHY, "[HARQ-UL-PUSCH harqId : %d] new transmission due to toogle of ndi \n", harq_pid); } /* 38.321 5.4.2.1 2> else (i.e. retransmission): */ else { @@ -322,7 +285,7 @@ harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, int ndi, u result_harq = RETRANSMISSION_HARQ; - NR_TST_PHY_PRINTF("[HARQ-UL-PUSCH harqId : %d] retransmission \n", harq_pid); + LOG_D(PHY, "[HARQ-UL-PUSCH harqId : %d] retransmission \n", harq_pid); } return (result_harq); @@ -343,98 +306,10 @@ harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, int ndi, u void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) { dl_harq->status = SCH_IDLE; - dl_harq->first_tx = 1; + dl_harq->first_rx = 1; dl_harq->round = 0; - dl_harq->harq_ack.ack = DL_ACKNACK_NO_SET; - dl_harq->harq_ack.send_harq_status = 0; - dl_harq->harq_ack.vDAI_UL = UL_DAI_NO_SET; - dl_harq->harq_ack.vDAI_DL = DL_DAI_NO_SET; - dl_harq->harq_ack.slot_for_feedback_ack = NR_MAX_SLOTS_PER_FRAME; - dl_harq->harq_ack.pucch_resource_indicator = MAX_PUCCH_RESOURCE_INDICATOR; - dl_harq->harq_ack.n_CCE = 0; - dl_harq->harq_ack.N_CCE = 0;; -} - -/******************************************************************* -* -* NAME : config_downlink_harq_process -* -* PARAMETERS : pointer to ue context -* id of current gNB -* number of downlink processes -* -* RETURN : none -* -* DESCRIPTION : configuration of downlink HARQ entity -* -*********************************************************************/ - -void config_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, int execution_thread_number, uint8_t number_harq_processes_for_pdsch) -{ - NR_UE_DLSCH_t *dlsch; - - dlsch = (NR_UE_DLSCH_t *)malloc16(sizeof(NR_UE_DLSCH_t)); - - if (dlsch != NULL) { - - memset(dlsch,0,sizeof(NR_UE_DLSCH_t)); - - ue->dlsch[execution_thread_number][gNB_id][TB_id] = dlsch; - } - else { - LOG_E(PHY, "Fatal memory allocation problem at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); - assert(0); - } - - dlsch->Mdlharq = number_harq_processes_for_pdsch; /* an additional HARQ is reserved for PBCCH */ - dlsch->number_harq_processes_for_pdsch = number_harq_processes_for_pdsch; - - /* allocation of HARQ process context */ - for (int harq_pid = 0; harq_pid < number_harq_processes_for_pdsch; harq_pid++) { - - //dlsch->harq_processes[harq_pid] = (NR_DL_UE_HARQ_t *)malloc16(sizeof(NR_DL_UE_HARQ_t)); - - /*if (dlsch->harq_processes[harq_pid] == NULL) { - LOG_E(PHY, "Fatal memory allocation problem at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); - assert(0); - }*/ - - memset(&dlsch->harq_processes[harq_pid],0,sizeof(NR_DL_UE_HARQ_t)); - - NR_DL_UE_HARQ_t *dl_harq = dlsch->harq_processes[harq_pid]; - - init_downlink_harq_status(dl_harq); - } -} - -/******************************************************************* -* -* NAME : release_downlink_harq_process -* -* PARAMETERS : pointer to ue context -* id of current gNB -* TB_id transport block identity 0 or 1 -* execution_thread_number thread number for current downlink processing -* RETURN : none -* -* DESCRIPTION : release of HARQ downlink entity -* -*********************************************************************/ - -void release_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, int execution_thread_number) -{ - NR_UE_DLSCH_t *dlsch = ue->dlsch[execution_thread_number][gNB_id][TB_id]; - - /*for (int process_id = 0; process_id < dlsch->Mdlharq; process_id++) { - - free16(dlsch->harq_processes[process_id],sizeof(NR_DL_UE_HARQ_t)); - - dlsch->harq_processes[process_id] = NULL; - }*/ - - free16(dlsch,sizeof(NR_UE_DLSCH_t)); - - ue->dlsch[execution_thread_number][gNB_id][TB_id] = NULL; + dl_harq->DCINdi = 1; + dl_harq->ack = DL_ACKNACK_NO_SET; } /******************************************************************* @@ -454,47 +329,65 @@ void release_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, in * *********************************************************************/ -harq_result_t downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, uint8_t rnti_type) -{ - harq_result_t result_harq = RETRANSMISSION_HARQ; +void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, int rv, uint8_t rnti_type) { - if (rnti_type == _CS_RNTI_) - { - LOG_E(PHY, "Fatal error in HARQ entity due to not supported CS_RNTI at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); - return(NEW_TRANSMISSION_HARQ); - } - else if ((rnti_type != _C_RNTI_) && (rnti_type != _TC_RNTI_)) { - /* harq mechanism is not relevant for other rnti */ - return(NEW_TRANSMISSION_HARQ); - } - - if (dl_harq->first_tx == 1) { + if (rnti_type == _SI_RNTI_ || + rnti_type == _P_RNTI_ || + rnti_type == _RA_RNTI_) { dl_harq->round = 0; dl_harq->status = ACTIVE; - dl_harq->DCINdi = ndi; - dl_harq->first_tx = 0; - - result_harq = NEW_TRANSMISSION_HARQ; - - NR_TST_PHY_PRINTF("[HARQ-DL-PDSCH harqId : %d] first new reception \n", harq_pid); + dl_harq->first_rx = 1; } - else if (dl_harq->DCINdi != ndi) { - dl_harq->round = 0; - dl_harq->status = ACTIVE; - dl_harq->DCINdi = ndi; - - result_harq = NEW_TRANSMISSION_HARQ; - - NR_TST_PHY_PRINTF("[HARQ-DL-PDSCH harqId : %d] new reception due to toogle of ndi \n", harq_pid); - } - else { - - dl_harq->round++; - - result_harq = RETRANSMISSION_HARQ; - - NR_TST_PHY_PRINTF("[HARQ-DL-PDSCH harqId : %d] reception of a retransmission \n", harq_pid); + else{ + switch(rv){ + case 0: + dl_harq->round = 0; + dl_harq->status = ACTIVE; + dl_harq->first_rx = 1; + if (dl_harq->DCINdi == ndi) + LOG_E(PHY,"Warning! rv %d indicates new transmission but new ndi %d is the same as old ndi %d\n",rv,ndi,dl_harq->DCINdi); + dl_harq->DCINdi = ndi; + break; + case 1: + dl_harq->round = 2; + dl_harq->status = ACTIVE; + dl_harq->first_rx = 0; + if (dl_harq->DCINdi != ndi) { + LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); + dl_harq->first_rx = 1; + dl_harq->DCINdi = ndi; + } + else if (dl_harq->ack == 1) + dl_harq->status = SCH_IDLE; + break; + case 2: + dl_harq->round = 1; + dl_harq->status = ACTIVE; + dl_harq->first_rx = 0; + if (dl_harq->DCINdi != ndi) { + LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); + dl_harq->first_rx = 1; + dl_harq->DCINdi = ndi; + } + else if (dl_harq->ack == 1) + dl_harq->status = SCH_IDLE; + break; + case 3: + dl_harq->round = 3; + dl_harq->status = ACTIVE; + dl_harq->first_rx = 0; + if (dl_harq->DCINdi != ndi) { + LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); + dl_harq->first_rx = 1; + dl_harq->DCINdi = ndi; + } + else if (dl_harq->ack == 1) + dl_harq->status = SCH_IDLE; + break; + default: + AssertFatal(1==0,"Invalid value for rv %d\n",rv); + } } - return (result_harq); } + diff --git a/openair1/SCHED_NR_UE/harq_nr.h b/openair1/SCHED_NR_UE/harq_nr.h index ee6e8625b0..5586518d7c 100644 --- a/openair1/SCHED_NR_UE/harq_nr.h +++ b/openair1/SCHED_NR_UE/harq_nr.h @@ -46,8 +46,6 @@ #define NR_DEFAULT_DLSCH_HARQ_PROCESSES (8) /* TS 38.214 5.1 */ -#define NR_DL_MAX_DAI (4) /* TS 38.213 table 9.1.3-1 Value of counter DAI for DCI format 1_0 and 1_1 */ -#define NR_DL_MAX_NB_CW (2) /* number of downlink code word */ #define DL_ACKNACK_NO_SET (2) #define DL_NACK (0) #define DL_ACK (1) @@ -68,18 +66,6 @@ /*************** FUNCTIONS ****************************************/ -/** \brief This function updates HARQ context according to dci - @param PHY_VARS_NR_UE ue context - @param nr_dci_info_extracted extracted information from dci - @param dlsch downlink context - @param ulsch uplink context - @param nr_tti_rx rx slot - @param tx_offset slot offset for tx - @returns none */ - -void get_dci_info_for_harq(PHY_VARS_NR_UE *ue, NR_DCI_INFO_EXTRACTED_t *nr_dci_info_extracted, - NR_UE_DLSCH_t **dlsch, NR_UE_ULSCH_t *ulsch, uint8_t nr_tti_rx, uint8_t tx_offset); - /** \brief This function configures uplink HARQ context @param PHY_VARS_NR_UE ue context @param gNB_id gNodeB identifier @@ -127,24 +113,6 @@ harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, int ndi, u void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq); -/** \brief This function configures downlink HARQ context - @param PHY_VARS_NR_UE ue context - @param gNB_id gNodeB identifier - @param TB_id transport block identifier - @param execution_thread_number thread_number - @param number_harq_processes maximum number of downlink HARQ processes - @returns none */ - -void config_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, int execution_thread_number, uint8_t number_harq_processes); - -/** \brief This function releases downlink HARQ context - @param PHY_VARS_NR_UE ue context - @param gNB_id gNodeB identifier - @param TB_id transport block identifier - @param execution_thread_number thread_number - @returns none */ - -void release_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, int execution_thread_number); /** \brief This function update downlink harq context and return reception type (new transmission or retransmission) @param dlsch downlink harq context @@ -152,7 +120,7 @@ void release_downlink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int TB_id, in @param rnti_type type of rnti @returns retransmission or new transmission */ -harq_result_t downlink_harq_process(NR_DL_UE_HARQ_t *dlsch, int harq_pid, int ndi, uint8_t rnti_type); +void downlink_harq_process(NR_DL_UE_HARQ_t *dlsch, int harq_pid, int ndi, int rv, uint8_t rnti_type); #undef EXTERN #undef INIT_VARIABLES_HARQ_NR_H diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr.h b/openair1/SCHED_NR_UE/phy_frame_config_nr.h index 3669239578..fcc2fa5838 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr.h +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr.h @@ -61,18 +61,18 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms); /** \brief This function checks nr slot direction : downlink or uplink * @param frame_parms NR DL Frame parameters * @param nr_frame : frame number - * @param nr_tti : slot number + * @param nr_slot : slot number @returns int : downlink or uplink */ -int slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_tti); +int slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_slot); /** \brief This function checks nr UE slot direction : downlink or uplink * @param cfg : FAPI Config Request * @param nr_frame : frame number - * @param nr_tti : slot number + * @param nr_slot : slot number @returns int : downlink, uplink or mixed slot type */ -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti); +int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_slot); /** \brief This function frees tdd configuration for nr * @param frame_parms NR DL Frame parameters diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c index 640ffb4ac3..696828a970 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c @@ -39,17 +39,19 @@ * *********************************************************************/ -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti) { +int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_slot) { /* for FFD all slot can be considered as an uplink */ int mu = cfg->ssb_config.scs_common, check_slot = 0; if (cfg->cell_config.frame_duplex_type == FDD) { return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT); } + if (cfg->tdd_table.max_tdd_periodicity_list == NULL) // this happens before receiving TDD configuration + return (NR_DOWNLINK_SLOT); if (nr_frame%2 == 0) { for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { + if (cfg->tdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { check_slot++; } } @@ -61,7 +63,7 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti) { check_slot = 0; for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) { + if (cfg->tdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) { check_slot++; } } @@ -73,7 +75,7 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti) { } } else { for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1< -//#include "targets/RT/USER/nr-softmodem.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "PHY/NR_TRANSPORT/nr_dci.h" #ifdef EMOS #include "SCHED/phy_procedures_emos.h" #endif #include "executables/softmodem-common.h" -//#define DEBUG_PHY_PROC +#include "executables/nr-uesoftmodem.h" +#include "LAYER2/NR_MAC_UE/mac_proto.h" +#include "LAYER2/NR_MAC_UE/nr_l1_helpers.h" +//#define DEBUG_PHY_PROC #define NR_PDCCH_SCHED //#define NR_PDCCH_SCHED_DEBUG //#define NR_PUCCH_SCHED @@ -66,8 +65,6 @@ #define PUCCH #endif -#include "LAYER2/NR_MAC_UE/mac_defs.h" -#include "LAYER2/NR_MAC_UE/mac_proto.h" #include "common/utils/LOG/log.h" #ifdef EMOS @@ -79,123 +76,102 @@ fifo_dump_emos_UE emos_dump_UE; #include "intertask_interface.h" #include "T.h" -#define DLSCH_RB_ALLOC 0x1fbf // skip DC RB (total 23/25 RBs) -#define DLSCH_RB_ALLOC_12 0x0aaa // skip DC RB (total 23/25 RBs) +char nr_mode_string[NUM_UE_MODE][20] = {"NOT SYNCHED","PRACH","RAR","RA_WAIT_CR", "PUSCH", "RESYNCH"}; -#define NS_PER_SLOT 500000 - -char nr_mode_string[4][20] = {"NOT SYNCHED","PRACH","RAR","PUSCH"}; - -extern double cpuf; - -/* -int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue, - uint8_t eNB_id, - int frame, - uint8_t nr_tti_rx, - uint64_t dci_pdu[2], - uint16_t rnti, - uint8_t dci_length, - NR_DCI_format_t dci_format, - NR_UE_PDCCH *pdcch_vars, - NR_UE_PDSCH *pdsch_vars, - NR_UE_DLSCH_t **dlsch, - NR_UE_ULSCH_t *ulsch, - NR_DL_FRAME_PARMS *frame_parms, - PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, - uint8_t beamforming_mode, - uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS], - uint16_t n_RB_ULBWP, - uint16_t n_RB_DLBWP, - uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES], - NR_DCI_INFO_EXTRACTED_t *nr_dci_info_extracted); -*/ +const uint8_t nr_rv_round_map_ue[4] = {0, 2, 1, 3}; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; #endif - -#if 0 -void nr_dump_dlsch(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t nr_tti_rx,uint8_t harq_pid) -{ - unsigned int coded_bits_per_codeword; - uint8_t nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; - - coded_bits_per_codeword = get_G(&ue->frame_parms, - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[harq_pid]->nb_rb, - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even, - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[harq_pid]->Qm, - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[harq_pid]->Nl, - ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, - proc->frame_rx, - nr_tti_rx, - ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]); - - write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,2,1); - write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1); - write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_estimates_ext[0],300*nsymb,1,1); - /* - write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); - write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); - write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); - write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); - */ - write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->rxdataF_comp0[0],300*12,1,1); - write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->llr[0],coded_bits_per_codeword,1,0); - - write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_mag0,300*12,1,1); - write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_magb0,300*12,1,1); -} - -void nr_dump_dlsch_SI(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t nr_tti_rx) -{ - unsigned int coded_bits_per_codeword; - uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12); - - coded_bits_per_codeword = get_G(&ue->frame_parms, - ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, - ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even, - 2, - 1, - ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, - proc->frame_rx, - nr_tti_rx, - 0); - LOG_D(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", - ue->Mod_id, - ue->frame_parms.ofdm_symbol_size, - nsymb, - ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, - ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs, - ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb, - ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, - coded_bits_per_codeword); - - write_output("rxsig0.m","rxs0", &ue->common_vars.rxdata[0][nr_tti_rx*ue->frame_parms.samples_per_tti],ue->frame_parms.samples_per_tti,1,1); - - write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0],nsymb*ue->frame_parms.ofdm_symbol_size,1,1); - write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_SI[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1); - write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_SI[0]->dl_ch_estimates_ext[0],ue->frame_parms.N_RB_DL*12*nsymb,1,1); - /* - write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); - write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); - write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); - write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); - */ - write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_SI[0]->rxdataF_comp0[0],ue->frame_parms.N_RB_DL*12*nsymb,1,1); - write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_SI[0]->llr[0],coded_bits_per_codeword,1,0); - - write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_SI[0]->dl_ch_mag0,300*nsymb,1,1); - write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_SI[0]->dl_ch_magb0,300*nsymb,1,1); - sleep(1); - exit(-1); -} - -#endif - unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162}; +void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_rx_indication_t *rx_ind, + UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + uint8_t gNB_id){ + + memset((void*)dl_ind, 0, sizeof(nr_downlink_indication_t)); + + dl_ind->gNB_index = gNB_id; + dl_ind->module_id = ue->Mod_id; + dl_ind->cc_id = ue->CC_id; + dl_ind->frame = proc->frame_rx; + dl_ind->slot = proc->nr_slot_rx; + dl_ind->thread_id = proc->thread_id; + + if (dci_ind) { + + dl_ind->rx_ind = NULL; //no data, only dci for now + dl_ind->dci_ind = dci_ind; + + } else if (rx_ind) { + + dl_ind->rx_ind = rx_ind; // hang on rx_ind instance + dl_ind->dci_ind = NULL; + + } +} + +void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, + uint8_t pdu_type, + uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + uint16_t n_pdus){ + + + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + + if (n_pdus > 1){ + LOG_E(PHY, "In %s: multiple number of DL PDUs not supported yet...\n", __FUNCTION__); + } + + switch (pdu_type){ + case FAPI_NR_RX_PDU_TYPE_SIB: + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8; + break; + case FAPI_NR_RX_PDU_TYPE_DLSCH: + if(dlsch0) { + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8; + } + if(dlsch1) { + AssertFatal(1==0,"Second codeword currently not supported\n"); + } + break; + case FAPI_NR_RX_PDU_TYPE_RAR: + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8; + break; + case FAPI_NR_RX_PDU_TYPE_SSB: + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.additional_bits = ue->pbch_vars[gNB_id]->xtra_byte; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_index = (frame_parms->ssb_index)&0x7; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_length = frame_parms->Lmax; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.cell_id = frame_parms->Nid_cell; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.rsrp_dBm = ue->measurements.rsrp_dBm[gNB_id]; + break; + default: + break; + } + + rx_ind->rx_indication_body[n_pdus -1].pdu_type = pdu_type; + rx_ind->number_pdus = n_pdus; + +} + int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){ int gain_dB = power_dBm - power_max_dBm, amp_x_100 = -1; @@ -234,2109 +210,113 @@ int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){ return (amp_x_100); } -#if 0 - -void nr_dump_dlsch_ra(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t nr_tti_rx) -{ - unsigned int coded_bits_per_codeword; - uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12); - - coded_bits_per_codeword = get_G(&ue->frame_parms, - ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, - ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even, - 2, - 1, - ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, - proc->frame_rx, - nr_tti_rx, - 0); - LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", - ue->Mod_id, - ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, - ue->dlsch_ra[eNB_id]->harq_processes[0]->mcs, - ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb, - ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols, - coded_bits_per_codeword); - - write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0],2*12*ue->frame_parms.ofdm_symbol_size,2,1); - write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_ra[0]->rxdataF_ext[0],2*12*ue->frame_parms.ofdm_symbol_size,1,1); - write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_ra[0]->dl_ch_estimates_ext[0],300*nsymb,1,1); - /* - write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1); - write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1); - write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1); - write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1); - */ - write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_ra[0]->rxdataF_comp0[0],300*nsymb,1,1); - write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_ra[0]->llr[0],coded_bits_per_codeword,1,0); - - write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_ra[0]->dl_ch_mag0,300*nsymb,1,1); - write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_ra[0]->dl_ch_magb0,300*nsymb,1,1); -} - -uint8_t nr_is_SR_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id) -{ - - int nr_tti_tx=proc->nr_tti_tx; - - LOG_D(PHY,"[UE %d][SR %x] Frame %d nr_tti_tx %d Checking for SR TXOp (sr_ConfigIndex %d)\n", - ue->Mod_id,ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->crnti,proc->frame_tx,nr_tti_tx, - ue->scheduling_request_config[eNB_id].sr_ConfigIndex); - - if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 4) { // 5 ms SR period - if ((nr_tti_tx%5) == ue->scheduling_request_config[eNB_id].sr_ConfigIndex) - return(1); - } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 14) { // 10 ms SR period - if (nr_tti_tx==(ue->scheduling_request_config[eNB_id].sr_ConfigIndex-5)) - return(1); - } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 34) { // 20 ms SR period - if ((10*(proc->frame_tx&1)+nr_tti_tx) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15)) - return(1); - } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 74) { // 40 ms SR period - if ((10*(proc->frame_tx&3)+nr_tti_tx) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35)) - return(1); - } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 154) { // 80 ms SR period - if ((10*(proc->frame_tx&7)+nr_tti_tx) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75)) - return(1); - } - - return(0); -} - -uint8_t is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id) -{ - int nr_tti_tx = proc->nr_tti_tx; - int frame = proc->frame_tx; - CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic; - - //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for CQI TXOp (cqi_ConfigIndex %d) isCQIOp %d\n", - // ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,nr_tti_rx, - // cqirep->cqi_PMI_ConfigIndex, - // (((10*frame + nr_tti_tx) % cqirep->Npd) == cqirep->N_OFFSET_CQI)); - - if (cqirep->cqi_PMI_ConfigIndex==-1) - return(0); - else if (((10*frame + nr_tti_tx) % cqirep->Npd) == cqirep->N_OFFSET_CQI) - return(1); - else - return(0); -} -uint8_t is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id) -{ - - - int nr_tti_tx = proc->nr_tti_tx; - int frame = proc->frame_tx; - CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic; - int log2Mri = cqirep->ri_ConfigIndex/161; - int N_OFFSET_RI = cqirep->ri_ConfigIndex % 161; - - //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for RI TXOp (ri_ConfigIndex %d) isRIOp %d\n", - // ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,nr_tti_tx, - // cqirep->ri_ConfigIndex, - // (((10*frame + nr_tti_tx + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<ri_ConfigIndex==-1) - return(0); - else if (((10*frame + nr_tti_tx + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<measurements; - //uint8_t transmission_mode = ue->transmission_mode[eNB_id]; - - - //LOG_I(PHY,"compute_cqi_ri_resources O_RI %d O %d uci format %d \n",ulsch->O_RI,ulsch->O,ulsch->uci_format); - if (cqi_status == 1 || ri_status == 1) - { - ulsch->O = 4; - } -} - -void ue_compute_srs_occasion(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t isSubframeSRS) -{ - - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - int frame_tx = proc->frame_tx; - int nr_tti_tx = proc->nr_tti_tx; - SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; - uint16_t srsPeriodicity; - uint16_t srsOffset; - uint8_t is_pucch2_subframe = 0; - uint8_t is_sr_an_subframe = 0; - - // check for SRS opportunity - pSoundingrs_ul_config_dedicated->srsUeSubframe = 0; - pSoundingrs_ul_config_dedicated->srsCellSubframe = isSubframeSRS; - - if (isSubframeSRS) { - LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup); - if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup) - { - nr_compute_srs_pos(frame_parms->frame_type, pSoundingrs_ul_config_dedicated->srs_ConfigIndex, &srsPeriodicity, &srsOffset); - - LOG_D(PHY," srsPeriodicity: %d srsOffset: %d isSubframeSRS %d \n",srsPeriodicity,srsOffset,isSubframeSRS); - - // transmit SRS if the four following constraints are respected: - // - UE is configured to transmit SRS - // - SRS are configured in current nr_tti_rx - // - UE is configured to send SRS in this nr_tti_tx - - // 36.213 8.2 - // 1- A UE shall not transmit SRS whenever SRS and PUCCH format 2/2a/2b transmissions happen to coincide in the same nr_tti_rx - // 2- A UE shall not transmit SRS whenever SRS transmit - // on and PUCCH transmission carrying ACK/NACK and/or - // positive SR happen to coincide in the same nr_tti_rx if the parameter - // Simultaneous-AN-and-SRS is FALSE - - // check PUCCH format 2/2a/2b transmissions - is_pucch2_subframe = nr_is_cqi_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0); - is_pucch2_subframe = (nr_is_ri_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0)) || is_pucch2_subframe; - - // check ACK/SR transmission - if(frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission == FALSE) - { - if(nr_is_SR_TXOp(ue,proc,eNB_id)) - { - uint32_t SR_payload = 0; - if (ue->mac_enabled==1) - { - int Mod_id = ue->Mod_id; - int CC_id = ue->CC_id; - SR_payload = mac_xface->ue_get_SR(Mod_id, - CC_id, - frame_tx, - eNB_id, - ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->crnti, - nr_tti_tx); // nr_tti_tx used for meas gap - - if (SR_payload > 0) - is_sr_an_subframe = 1; - } - } - - uint8_t pucch_ack_payload[2]; - if (nr_get_ack(&ue->frame_parms, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, - nr_tti_tx,proc->nr_tti_rx,pucch_ack_payload,0) > 0) - { - is_sr_an_subframe = 1; - } - } - - // check SRS UE opportunity - if( isSubframeSRS && - (((10*frame_tx+nr_tti_tx) % srsPeriodicity) == srsOffset) - ) - { - if ((is_pucch2_subframe == 0) && (is_sr_an_subframe == 0)) - { - pSoundingrs_ul_config_dedicated->srsUeSubframe = 1; - ue->ulsch[eNB_id]->srs_active = 1; - ue->ulsch[eNB_id]->Nsymb_pusch = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active; - } - else - { - LOG_I(PHY,"DROP UE-SRS-TX for this nr_tti_tx %d.%d: collision with PUCCH2 or SR/AN: PUCCH2-occasion: %d, SR-AN-occasion[simSRS-SR-AN %d]: %d \n", frame_tx, nr_tti_tx, is_pucch2_subframe, frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, is_sr_an_subframe); - } - } - } - LOG_D(PHY," srsCellSubframe: %d, srsUeSubframe: %d, Nsymb-pusch: %d \n", pSoundingrs_ul_config_dedicated->srsCellSubframe, pSoundingrs_ul_config_dedicated->srsUeSubframe, ue->ulsch[eNB_id]->Nsymb_pusch); - } -} - - -void nr_get_cqipmiri_params(PHY_VARS_NR_UE *ue,uint8_t eNB_id) -{ - - CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic; - int cqi_PMI_ConfigIndex = cqirep->cqi_PMI_ConfigIndex; - - if (ue->frame_parms.frame_type == FDD) { - if (cqi_PMI_ConfigIndex <= 1) { // 2 ms CQI_PMI period - cqirep->Npd = 2; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex; - } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period - cqirep->Npd = 5; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-2; - } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period - cqirep->Npd = 10; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-7; - } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period - cqirep->Npd = 20; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-17; - } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period - cqirep->Npd = 40; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-37; - } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period - cqirep->Npd = 80; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-77; - } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period - cqirep->Npd = 160; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-157; - } - else if (cqi_PMI_ConfigIndex > 317) { - - if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period - cqirep->Npd = 32; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-318; - } - else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period - cqirep->Npd = 64; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-350; - } - else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period - cqirep->Npd = 128; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-414; - } - } - } - else { // TDD - if (cqi_PMI_ConfigIndex == 0) { // all UL subframes - cqirep->Npd = 1; - cqirep->N_OFFSET_CQI = 0; - } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period - cqirep->Npd = 5; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-1; - } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period - cqirep->Npd = 10; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-6; - } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period - cqirep->Npd = 20; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-16; - } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period - cqirep->Npd = 40; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-36; - } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period - cqirep->Npd = 80; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-76; - } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period - cqirep->Npd = 160; - cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-156; - } - } -} - -PUCCH_FMT_t get_pucch_format(lte_frame_type_t frame_type, - lte_prefix_type_t cyclic_prefix_type, - uint8_t SR_payload, - uint8_t nb_cw, - uint8_t cqi_status, - uint8_t ri_status, - uint8_t bundling_flag) -{ - if((cqi_status == 0) && (ri_status==0)) - { - // PUCCH Format 1 1a 1b - // 1- SR only ==> PUCCH format 1 - // 2- 1bit Ack/Nack with/without SR ==> PUCCH format 1a - // 3- 2bits Ack/Nack with/without SR ==> PUCCH format 1b - if((nb_cw == 1)&&(bundling_flag==bundling)) - { - return pucch_format1a; - } - if((nb_cw == 1)&&(bundling_flag==multiplexing)) - { - return pucch_format1b; - } - if(nb_cw == 2) - { - return pucch_format1b; - } - if(SR_payload == 1) - { - return pucch_format1; - /* - if (frame_type == FDD) { - return pucch_format1; - } else if (frame_type == TDD) { - return pucch_format1b; - } else { - AssertFatal(1==0,"Unknown frame_type"); - }*/ - } - } - else - { - // PUCCH Format 2 2a 2b - // 1- CQI only or RI only ==> PUCCH format 2 - // 2- CQI or RI + 1bit Ack/Nack for normal CP ==> PUCCH format 2a - // 3- CQI or RI + 2bits Ack/Nack for normal CP ==> PUCCH format 2b - // 4- CQI or RI + Ack/Nack for extended CP ==> PUCCH format 2 - if(nb_cw == 0) - { - return pucch_format2; - } - if(cyclic_prefix_type == NORMAL) - { - if(nb_cw == 1) - { - return pucch_format2a; - } - if(nb_cw == 2) - { - return pucch_format2b; - } - } - else - { - return pucch_format2; - } - } - return pucch_format1a; -} - -uint16_t nr_get_n1_pucch(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - nr_harq_status_t *harq_ack, - uint8_t eNB_id, - uint8_t *b, - uint8_t SR) -{ - - NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - uint8_t nCCE0,nCCE1,nCCE2,nCCE3,harq_ack1,harq_ack0,harq_ack3,harq_ack2; - ANFBmode_t bundling_flag; - uint16_t n1_pucch0=0,n1_pucch1=0,n1_pucch2=0,n1_pucch3=0,n1_pucch_inter; - static uint8_t candidate_dl[9]; // which downlink(s) the current ACK/NACK is associating to - uint8_t last_dl=0xff; // the last downlink with valid DL-DCI. for calculating the PUCCH resource index - int sf; - int M; - uint8_t ack_counter=0; - // clear this, important for case where n1_pucch selection is not used - int nr_tti_tx=proc->nr_tti_tx; - - ue->pucch_sel[nr_tti_tx] = 0; - - if (frame_parms->frame_type == FDD ) { // FDD - sf = (nr_tti_tx<4)? nr_tti_tx+6 : nr_tti_tx-4; - LOG_D(PHY,"n1_pucch_UE: nr_tti_tx %d, nCCE %d\n",sf,ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[sf]); - - if (SR == 0) - return(frame_parms->pucch_config_common.n1PUCCH_AN + ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[sf]); - else - return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - } else { - - bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; -#ifdef DEBUG_PHY_PROC - - if (bundling_flag==bundling) { - LOG_D(PHY,"[UE%d] Frame %d nr_tti_tx %d : nr_get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,proc->frame_tx,nr_tti_tx,SR, - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - } else { - LOG_D(PHY,"[UE%d] Frame %d nr_tti_tx %d : nr_get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,proc->frame_tx,nr_tti_tx,SR, - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - } - -#endif - - switch (frame_parms->tdd_config) { - case 1: // DL:S:UL:UL:DL:DL:S:UL:UL:DL - - harq_ack0 = 2; // DTX - M=1; - - // This is the offset for a particular nr_tti_tx (2,3,4) => (0,2,4) - if (nr_tti_tx == 2) { // ACK nr_tti_txs 5,6 - candidate_dl[0] = 6; - candidate_dl[1] = 5; - M=2; - } else if (nr_tti_tx == 3) { // ACK nr_tti_tx 9 - candidate_dl[0] = 9; - } else if (nr_tti_tx == 7) { // ACK nr_tti_txs 0,1 - candidate_dl[0] = 1; - candidate_dl[1] = 0; - M=2; - } else if (nr_tti_tx == 8) { // ACK nr_tti_txs 4 - candidate_dl[0] = 4; - } else { - LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal tx-nr_tti_tx %d for tdd_config %d\n", - ue->Mod_id,proc->frame_tx,nr_tti_tx,frame_parms->tdd_config); - return(0); - } - - // checking which downlink candidate is the last downlink with valid DL-DCI - int k; - for (k=0;k0) { - last_dl = candidate_dl[k]; - break; - } - } - if (last_dl >= 10) { - LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal rx-nr_tti_tx %d (tx-nr_tti_tx %d) for tdd_config %d\n", - ue->Mod_id,proc->frame_tx,last_dl,nr_tti_tx,frame_parms->tdd_config); - return (0); - } - - LOG_D(PHY,"SFN/SF %d/%d calculating n1_pucch0 from last_dl=%d\n", - proc->frame_tx%1024, - proc->nr_tti_tx, - last_dl); - - // i=0 - nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[last_dl]; - n1_pucch0 = nr_get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; - - harq_ack0 = b[0]; - - if (harq_ack0!=2) { // DTX - if (frame_parms->frame_type == FDD ) { - if (SR == 0) { // last paragraph pg 68 from 36.213 (v8.6), m=0 - b[0]=(M==2) ? 1-harq_ack0 : harq_ack0; - b[1]=harq_ack0; // in case we use pucch format 1b (subframes 2,7) - ue->pucch_sel[nr_tti_tx] = 0; - return(n1_pucch0); - } else { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213) - b[0]=harq_ack0; - return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - } - } else { - if (SR == 0) { - b[0] = harq_ack0; - b[1] = harq_ack0; - ue->pucch_sel[nr_tti_tx] = 0; - return(n1_pucch0); - } else { - b[0] = harq_ack0; - b[1] = harq_ack0; - return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - } - } - } - - - break; - - case 3: // DL:S:UL:UL:UL:DL:DL:DL:DL:DL - // in this configuration we have M=2 from pg 68 of 36.213 (v8.6) - // Note: this doesn't allow using nr_tti_tx 1 for PDSCH transmission!!! (i.e. SF 1 cannot be acked in SF 2) - // set ACK/NAKs to DTX - harq_ack1 = 2; // DTX - harq_ack0 = 2; // DTX - // This is the offset for a particular nr_tti_rx (2,3,4) => (0,2,4) - last_dl = (nr_tti_tx-2)<<1; - // i=0 - nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[5+last_dl]; - n1_pucch0 = nr_get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; - // i=1 - nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(6+last_dl)%10]; - n1_pucch1 = nr_get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; - - // set ACK/NAK to values if not DTX - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(6+last_dl)%10].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed - harq_ack1 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(6+last_dl)%10].ack; - - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[5+last_dl].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed - harq_ack0 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[5+last_dl].ack; - - LOG_D(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d cce1=%d n1_pucch1=%d\n", - proc->frame_tx%1024, - proc->nr_tti_tx, - nCCE0,n1_pucch0, - nCCE1,n1_pucch1); - - if (harq_ack1!=2) { // n-6 // nr_tti_tx 6,8,0 and maybe 5,7,9 is to be ACK/NAKed - - if ((bundling_flag==bundling)&&(SR == 0)) { // This is for bundling without SR, - // n1_pucch index takes value of smallest element in set {0,1} - // i.e. 0 if harq_ack0 is not DTX, otherwise 1 - b[0] = harq_ack1; - - if (harq_ack0!=2) - b[0]=b[0]&harq_ack0; - - ue->pucch_sel[nr_tti_tx] = 1; - return(n1_pucch1); - - } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 - if (harq_ack0 == 2) - harq_ack0 = 0; - - b[1] = harq_ack0; - b[0] = (harq_ack0!=harq_ack1)?0:1; - - if ((harq_ack0 == 1) && (harq_ack1 == 0)) { - ue->pucch_sel[nr_tti_tx] = 0; - return(n1_pucch0); - } else { - ue->pucch_sel[nr_tti_tx] = 1; - return(n1_pucch1); - } - } else if (SR==1) { // SR and 0,1,or 2 ACKS, (first 3 entries in Table 7.3-1 of 36.213) - // this should be number of ACKs (including - if (harq_ack0 == 2) - harq_ack0 = 0; - - b[0]= harq_ack1 | harq_ack0; - b[1]= harq_ack1 ^ harq_ack0; - return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - } - } else if (harq_ack0!=2) { // n-7 // nr_tti_tx 5,7,9 only is to be ACK/NAKed - if ((bundling_flag==bundling)&&(SR == 0)) { // last paragraph pg 68 from 36.213 (v8.6), m=0 - b[0]=harq_ack0; - ue->pucch_sel[nr_tti_tx] = 0; - return(n1_pucch0); - } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 with i=1 set to DTX - b[0] = harq_ack0; - b[1] = 1-b[0]; - ue->pucch_sel[nr_tti_tx] = 0; - return(n1_pucch0); - } else if (SR==1) { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213) - b[0]=harq_ack0; - b[1]=b[0]; - return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - } - } - - break; - - case 4: // DL:S:UL:UL:DL:DL:DL:DL:DL:DL - // in this configuration we have M=4 from pg 68 of 36.213 (v8.6) - // Note: this doesn't allow using nr_tti_tx 1 for PDSCH transmission!!! (i.e. SF 1 cannot be acked in SF 2) - // set ACK/NAKs to DTX - harq_ack3 = 2; // DTX - harq_ack2 = 2; // DTX - harq_ack1 = 2; // DTX - harq_ack0 = 2; // DTX - // This is the offset for a particular nr_tti_tx (2,3,4) => (0,2,4) - //last_dl = (nr_tti_tx-2)<<1; - if (nr_tti_tx == 2) { - // i=0 - //nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[2+nr_tti_tx]; - nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(8+nr_tti_tx)%10]; - n1_pucch0 = 2*nr_get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; - // i=1 - nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[2+nr_tti_tx]; - n1_pucch1 = nr_get_Np(frame_parms->N_RB_DL,nCCE1,0) + nr_get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; - // i=2 - nCCE2 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(8+nr_tti_tx)%10]; - - n1_pucch2 = 2*nr_get_Np(frame_parms->N_RB_DL,nCCE2,1) + nCCE2+ frame_parms->pucch_config_common.n1PUCCH_AN; - // i=3 - //nCCE3 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(9+nr_tti_tx)%10]; - //n1_pucch3 = nr_get_Np(frame_parms->N_RB_DL,nCCE3,1) + nCCE3 + frame_parms->pucch_config_common.n1PUCCH_AN; - - // set ACK/NAK to values if not DTX - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(8+nr_tti_tx)%10].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed - harq_ack0 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(8+nr_tti_tx)%10].ack; - - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[2+nr_tti_tx].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed - harq_ack1 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[2+nr_tti_tx].ack; - - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[3+nr_tti_tx].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed - harq_ack2 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[3+nr_tti_tx].ack; - - //if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(9+nr_tti_tx)%10].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed - //harq_ack3 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(9+nr_tti_tx)%10].ack; - //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d cce1=%d n1_pucch1=%d cce2=%d n1_pucch2=%d\n", - // proc->frame_tx%1024, - // proc->nr_tti_tx_tx, - // nCCE0,n1_pucch0, - // nCCE1,n1_pucch1, nCCE2, n1_pucch2); - }else if (nr_tti_tx == 3) { - // i=0 - - nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[4+nr_tti_tx]; - n1_pucch0 = 3*nr_get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN; - // i=1 - nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[5+nr_tti_tx]; - n1_pucch1 = 2*nr_get_Np(frame_parms->N_RB_DL,nCCE1,0) + nr_get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN; - // i=2 - nCCE2 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(6+nr_tti_tx)]; - n1_pucch2 = nr_get_Np(frame_parms->N_RB_DL,nCCE2,0) + 2*nr_get_Np(frame_parms->N_RB_DL,nCCE2,1) + nCCE2+ frame_parms->pucch_config_common.n1PUCCH_AN; - // i=3 - nCCE3 = ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->nCCE[(3+nr_tti_tx)]; - n1_pucch3 = 3*nr_get_Np(frame_parms->N_RB_DL,nCCE3,1) + nCCE3 + frame_parms->pucch_config_common.n1PUCCH_AN; - - // set ACK/NAK to values if not DTX - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[4+nr_tti_tx].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed - harq_ack0 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[4+nr_tti_tx].ack; - - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[5+nr_tti_tx].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed - harq_ack1 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[5+nr_tti_tx].ack; - - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(6+nr_tti_tx)].send_harq_status>0) // n-6 // nr_tti_tx 6 is to be ACK/NAKed - harq_ack2 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(6+nr_tti_tx)].ack; - - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(3+nr_tti_tx)].send_harq_status>0) // n-6 // nr_tti_tx 5 is to be ACK/NAKed - harq_ack3 = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack[(3+nr_tti_tx)].ack; - } - - //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d harq_ack0=%d cce1=%d n1_pucch1=%d harq_ack1=%d cce2=%d n1_pucch2=%d harq_ack2=%d cce3=%d n1_pucch3=%d harq_ack3=%d bundling_flag=%d\n", - // proc->frame_tx%1024, - // proc->nr_tti_tx, - // nCCE0,n1_pucch0,harq_ack0, - // nCCE1,n1_pucch1,harq_ack1, nCCE2, n1_pucch2, harq_ack2, - // nCCE3, n1_pucch3, harq_ack3, bundling_flag); - - if ((bundling_flag==bundling)&&(SR == 0)) { // This is for bundling without SR, - b[0] = 1; - ack_counter = 0; - - if ((harq_ack3!=2) ) { - b[0] = b[0]&harq_ack3; - n1_pucch_inter = n1_pucch3; - ack_counter ++; - } - if ((harq_ack0!=2) ) { - b[0] = b[0]&harq_ack0; - n1_pucch_inter = n1_pucch0; - ack_counter ++; - } - if ((harq_ack1!=2) ) { - b[0] = b[0]&harq_ack1; - n1_pucch_inter = n1_pucch1; - ack_counter ++; - } - if ((harq_ack2!=2) ) { - b[0] = b[0]&harq_ack2; - n1_pucch_inter = n1_pucch2; - ack_counter ++; - } - - if (ack_counter == 0) - b[0] = 0; - - /*if (nr_tti_tx == 3) { - n1_pucch_inter = n1_pucch2; - } else if (nr_tti_tx == 2) { - n1_pucch_inter = n1_pucch1; - }*/ - - //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch n1_pucch_inter=%d b[0]=%d b[1]=%d \n", - // proc->frame_tx%1024, - // proc->nr_tti_tx,n1_pucch_inter, - // b[0],b[1]); - - return(n1_pucch_inter); - - } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 - - if (nr_tti_tx == 3) { - LOG_I(PHY, "sbuframe=%d \n",nr_tti_tx); - if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) { - b[0] = 1; - b[1] = 1; - return(n1_pucch1); - } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { - b[0] = 1; - b[1] = 0; - return(n1_pucch1); - } else if (((harq_ack0 == 0) || (harq_ack0 == 2)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 0) && (harq_ack3 == 2)) { - b[0] = 1; - b[1] = 1; - return(n1_pucch2); - } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) { - b[0] = 1; - b[1] = 0; - return(n1_pucch1); - } else if ((harq_ack0 == 0) && (harq_ack1 == 2) && (harq_ack2 == 2) && (harq_ack3 == 2)) { - b[0] = 1; - b[1] = 0; - return(n1_pucch0); - } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { - b[0] = 1; - b[1] = 0; - return(n1_pucch1); - } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && (harq_ack3 == 1)) { - b[0] = 0; - b[1] = 1; - return(n1_pucch3); - } else if (((harq_ack0 == 0) || (harq_ack0 == 2)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 0)) { - b[0] = 1; - b[1] = 1; - return(n1_pucch3); - } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { - b[0] = 0; - b[1] = 1; - return(n1_pucch2); - } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) { - b[0] = 0; - b[1] = 1; - return(n1_pucch0); - } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { - b[0] = 0; - b[1] = 1; - return(n1_pucch0); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) { - b[0] = 0; - b[1] = 1; - return(n1_pucch3); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 0) && (harq_ack2 == 2) && (harq_ack3 == 2)) { - b[0] = 0; - b[1] = 0; - return(n1_pucch1); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { - b[0] = 1; - b[1] = 0; - return(n1_pucch2); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) { - b[0] = 1; - b[1] = 0; - return(n1_pucch3); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { - b[0] = 0; - b[1] = 1; - return(n1_pucch1); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && (harq_ack3 == 1)) { - b[0] = 0; - b[1] = 1; - return(n1_pucch3); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) { - b[0] = 0; - b[1] = 0; - return(n1_pucch2); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack3 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { - b[0] = 0; - b[1] = 0; - return(n1_pucch3); - } - } else if (nr_tti_tx == 2) { - if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1)) { - b[0] = 1; - b[1] = 1; - return(n1_pucch2); - } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { - b[0] = 1; - b[1] = 1; - return(n1_pucch1); - } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1)) { - b[0] = 1; - b[1] = 1; - return(n1_pucch0); - } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { - b[0] = 0; - b[1] = 1; - return(n1_pucch0); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1)) { - b[0] = 1; - b[1] = 0; - return(n1_pucch2); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { - b[1] = 0; - b[0] = 0; - return(n1_pucch1); - } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1)) { - b[0] = 0; - b[1] = 0; - return(n1_pucch2); - } else if ((harq_ack0 == 2) && (harq_ack1 == 2) && (harq_ack2 == 0)) { - b[0] = 0; - b[1] = 1; - return(n1_pucch2); - } else if ((harq_ack0 == 2) && (harq_ack1 == 0) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { - b[0] = 1; - b[1] = 0; - return(n1_pucch1); - } else if ((harq_ack0 == 0) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0))) { - b[0] = 1; - b[1] = 0; - return(n1_pucch0); - } - - } - } else if (SR==1) { // SR and 0,1,or 2 ACKS, (first 3 entries in Table 7.3-1 of 36.213) - // this should be number of ACKs (including - ack_counter = 0; - if (harq_ack0==1) - ack_counter ++; - if (harq_ack1==1) - ack_counter ++; - if (harq_ack2==1) - ack_counter ++; - if (harq_ack3==1) - ack_counter ++; - - switch (ack_counter) { - case 0: - b[0] = 0; - b[1] = 0; - break; - - case 1: - b[0] = 1; - b[1] = 1; - break; - - case 2: - b[0] = 1; - b[1] = 0; - break; - - case 3: - b[0] = 0; - b[1] = 1; - break; - - case 4: - b[0] = 1; - b[1] = 1; - break; - } - - ack_counter = 0; - return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex); - } - - break; - - } // switch tdd_config - } - - LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, exit without proper return\n", ue->Mod_id, proc->frame_tx); - return(-1); -} - - - -void ulsch_common_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t empty_subframe) { - - int aa; - NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - - int nsymb; - int nr_tti_tx = proc->nr_tti_tx; - int frame_tx = proc->frame_tx; - int ulsch_start; - int overflow=0; -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - int k,l; - int dummy_tx_buffer[frame_parms->samples_per_subframe] __attribute__((aligned(16))); -#endif - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN); -#if UE_TIMING_TRACE - start_meas(&ue->ofdm_mod_stats); -#endif - nsymb = (frame_parms->Ncp == 0) ? 14 : 12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)//this is the EXPRESS MIMO case - ulsch_start = (ue->rx_offset+nr_tti_tx*frame_parms->samples_per_subframe- - ue->hw_timing_advance- - ue->timing_advance- - ue->N_TA_offset+5); - //LOG_E(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d]\n",nr_tti_tx, ulsch_start); - - if(ulsch_start < 0) - ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); - - if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe)) - ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); - - //LOG_E(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d]\n",nr_tti_tx, ulsch_start); -#else //this is the normal case - ulsch_start = (frame_parms->samples_per_subframe*nr_tti_tx)-ue->N_TA_offset; //-ue->timing_advance; -#endif //else EXMIMO - - //#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - if (empty_subframe) - { - //#if 1 - overflow = ulsch_start - 9*frame_parms->samples_per_subframe; - for (aa=0; aanb_antennas_tx; aa++) { - - if (overflow > 0) - { - memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*(frame_parms->samples_per_subframe-overflow)); - memset(&ue->common_vars.txdata[aa][0],0,4*overflow); - } - else - { - memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*frame_parms->samples_per_subframe); - } - } - /*#else - overflow = ulsch_start - 9*frame_parms->samples_per_subframe; - for (aa=0; aanb_antennas_tx; aa++) { - for (k=ulsch_start; ksamples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_subframe); k++) { - ((short*)ue->common_vars.txdata[aa])[2*k] = 0; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = 0; - } - - for (k=0; kcommon_vars.txdata[aa])[2*k] = 0; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = 0; - } - } - endif*/ - return; - } - - - if ((frame_tx%100) == 0) - LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: ulsch_start = %d (rxoff %d, HW TA %d, timing advance %d, TA_offset %d\n", - ue->Mod_id,frame_tx,nr_tti_tx, - ulsch_start, - ue->rx_offset, - ue->hw_timing_advance, - ue->timing_advance, - ue->N_TA_offset); - - - for (aa=0; aanb_antennas_tx; aa++) { - if (frame_parms->Ncp == 1) - PHY_ofdm_mod(&ue->common_vars.txdataF[aa][nr_tti_tx*nsymb*frame_parms->ofdm_symbol_size], -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - dummy_tx_buffer, -#else - &ue->common_vars.txdata[aa][ulsch_start], -#endif - frame_parms->ofdm_symbol_size, - nsymb, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - else - normal_prefix_mod(&ue->common_vars.txdataF[aa][nr_tti_tx*nsymb*frame_parms->ofdm_symbol_size], -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - dummy_tx_buffer, -#else - &ue->common_vars.txdata[aa][ulsch_start], -#endif - nsymb, - &ue->frame_parms); - - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - apply_7_5_kHz(ue,dummy_tx_buffer,0); - apply_7_5_kHz(ue,dummy_tx_buffer,1); -#else - apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],0); - apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],1); -#endif - - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - overflow = ulsch_start - 9*frame_parms->samples_per_subframe; - - - for (k=ulsch_start,l=0; ksamples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_subframe); k++,l++) { - ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; - } - - for (k=0; kcommon_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; - } -#if defined(EXMIMO) - // handle switch before 1st TX nr_tti_rx, guarantee that the slot prior to transmission is switch on - for (k=ulsch_start - (frame_parms->samples_per_subframe>>1) ; kcommon_vars.txdata[aa][k+frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; - else if (k>(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) - ue->common_vars.txdata[aa][k-frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; - else - ue->common_vars.txdata[aa][k] &= 0xFFFEFFFE; - } -#endif -#endif - /* - only for debug - LOG_I(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d, TA: %d, rxOffset: %d, timing_advance: %d, hw_timing_advance: %d]\n",nr_tti_tx, ulsch_start, ue->N_TA_offset, ue->rx_offset, ue->timing_advance, ue->hw_timing_advance); - if( (crash == 1) && (nr_tti_tx == 0) ) - { - LOG_E(PHY,"***** DUMP TX Signal [ulsch_start %d] *****\n",ulsch_start); - write_output("txBuff.m","txSignal",&ue->common_vars.txdata[aa][ulsch_start],frame_parms->samples_per_subframe,1,1); - } - */ - - } //nb_antennas_tx - -#if UE_TIMING_TRACE - stop_meas(&ue->ofdm_mod_stats); -#endif - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_OUT); - -} - -#endif - UE_MODE_t get_nrUE_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t gNB_id){ return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[gNB_id]); } -uint16_t get_bw_scaling(uint16_t bwp_ul_NB_RB){ - uint16_t bw_scaling; - // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size - switch (bwp_ul_NB_RB) { - case 32: bw_scaling = 4; break; - case 66: bw_scaling = 8; break; - case 106: bw_scaling = 16; break; - case 217: bw_scaling = 32; break; - case 245: bw_scaling = 32; break; - case 273: bw_scaling = 32; break; - default: abort(); - } - return bw_scaling; +// convert time factor "16 * 64 * T_c / (2^mu)" in N_TA calculation in TS38.213 section 4.2 to samples by multiplying with samples per second +// 16 * 64 * T_c / (2^mu) * samples_per_second +// = 16 * T_s / (2^mu) * samples_per_second +// = 16 * 1 / (15 kHz * 2048) / (2^mu) * (15 kHz * 2^mu * ofdm_symbol_size) +// = 16 * 1 / 2048 * ofdm_symbol_size +// = 16 * ofdm_symbol_size / 2048 +static inline +uint16_t get_bw_scaling(uint16_t ofdm_symbol_size){ + return 16 * ofdm_symbol_size / 2048; } -void nr_process_timing_advance(module_id_t Mod_id, uint8_t CC_id, uint8_t ta_command, uint8_t mu, uint16_t bwp_ul_NB_RB){ +// UL time alignment procedures: +// - If the current tx frame and slot match the TA configuration in ul_time_alignment +// then timing advance is processed and set to be applied in the next UL transmission +// - Application of timing adjustment according to TS 38.213 p4.2 +// todo: +// - handle RAR TA application as per ch 4.2 TS 38.213 +void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){ - // 3GPP TS 38.213 p4.2 - // scale by the scs numerology - int factor_mu = 1 << mu; - uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB); - - PHY_vars_UE_g[Mod_id][CC_id]->timing_advance += (ta_command - 31) * bw_scaling / factor_mu; - - LOG_D(PHY, "[UE %d] Got timing advance command %u from MAC, new value is %d\n", Mod_id, ta_command, PHY_vars_UE_g[Mod_id][CC_id]->timing_advance); -} - -// WIP -// - todo: handle TA application as per ch 4.2 TS 38.213 -void nr_process_timing_advance_rar(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint16_t ta_command) { - - int factor_mu = 1 << ue->frame_parms.numerology_index; - uint16_t bwp_ul_NB_RB = ue->frame_parms.N_RB_UL; - uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB); - - // Transmission timing adjustment (TS 38.213 p4.2) - ue->timing_advance = bw_scaling / factor_mu; - - LOG_D(PHY, "[UE %d] Frame %d Slot %d, Received (RAR) timing advance command %d new value is %u \n", ue->Mod_id, proc->frame_rx, proc->nr_tti_rx, ta_command, ue->timing_advance); -} - -#if 0 - -void ue_ulsch_uespec_procedures(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - uint8_t eNB_id, - uint8_t abstraction_flag) -{ - int nr_tti_tx=proc->nr_tti_tx; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_IN); - - /* reset harq for tx of current rx slot because it is sure that transmission has already been achieved for this slot */ - set_tx_harq_id(ue->ulsch[ue->current_thread_id[nr_tti_tx]][eNB_id][0], NR_MAX_HARQ_PROCESSES, proc->nr_tti_rx); - -#if 0 - int frame_tx=proc->frame_tx; - int harq_pid; - /* get harq pid related to this next tx slot */ - harq_pid = get_tx_harq_id(ue->ulsch[ue->current_thread_id[nr_tti_tx]][eNB_id][0], nr_tti_tx); - - int tx_amp; - unsigned int input_buffer_length; - int Mod_id = ue->Mod_id; - int CC_id = ue->CC_id; - uint8_t Msg3_flag=0; - uint16_t first_rb, nb_rb; - uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32))); - uint8_t access_mode; - uint8_t Nbundled=0; - uint8_t NbundledCw1=0; - uint8_t ack_status_cw0=0; - uint8_t ack_status_cw1=0; - uint8_t cqi_status = 0; - uint8_t ri_status = 0; if (ue->mac_enabled == 1) { - if ((ue->ulsch_Msg3_active[eNB_id] == 1) && - (ue->ulsch_Msg3_frame[eNB_id] == frame_tx) && - (ue->ulsch_Msg3_subframe[eNB_id] == nr_tti_tx)) { // Initial Transmission of Msg3 - ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1; + uint8_t gNB_id = 0; + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id]; - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) - generate_ue_ulsch_params_from_rar(ue, - proc, - eNB_id); + if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) { - ue->ulsch[eNB_id]->power_offset = 14; - LOG_D(PHY,"[UE %d][RAPROC] Frame %d: Setting Msg3_flag in nr_tti_rx %d, for harq_pid %d\n", - Mod_id, - frame_tx, - nr_tti_tx, - harq_pid); - Msg3_flag = 1; - } else { + uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; + uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size); - /* no pusch has been scheduled on this transmit slot */ - if (harq_pid == NR_MAX_HARQ_PROCESSES) { - LOG_E(PHY,"[UE%d] Frame %d nr_tti_rx %d ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n", - Mod_id,frame_tx, nr_tti_tx); - //mac_xface->macphy_exit("Error in ulsch_decoding"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(&ue->phy_proc_tx); -#endif - return; - } + ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling; + + LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n", + __FUNCTION__, + ue->Mod_id, + frame_tx, + slot_tx, + ul_time_alignment->ta_command, + ue->timing_advance); + + ul_time_alignment->ta_frame = -1; + ul_time_alignment->ta_slot = -1; - Msg3_flag=0; } } - - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { - - uint8_t isBad = 0; - if (ue->frame_parms.N_RB_UL <= ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb) { - LOG_D(PHY,"Invalid PUSCH first_RB=%d for N_RB_UL=%d\n", - ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, - ue->frame_parms.N_RB_UL); - isBad = 1; - } - if (ue->frame_parms.N_RB_UL < ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb) { - LOG_D(PHY,"Invalid PUSCH num_RB=%d for N_RB_UL=%d\n", - ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, - ue->frame_parms.N_RB_UL); - isBad = 1; - } - if (0 > ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb) { - LOG_D(PHY,"Invalid PUSCH first_RB=%d\n", - ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb); - isBad = 1; - } - if (0 >= ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb) { - LOG_D(PHY,"Invalid PUSCH num_RB=%d\n", - ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb); - isBad = 1; - } - if (ue->frame_parms.N_RB_UL < (ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb)) { - LOG_D(PHY,"Invalid PUSCH num_RB=%d + first_RB=%d for N_RB_UL=%d\n", - ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, - ue->frame_parms.N_RB_UL); - isBad = 1; - } - if ((0 > ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx) || - (3 < ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx)) { - LOG_D(PHY,"Invalid PUSCH RV index=%d\n", ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx); - isBad = 1; - } - - if (20 < ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs) { - LOG_D(PHY,"Not supported MCS in OAI mcs=%d\n", ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs); - isBad = 1; - } - - if (isBad) { - LOG_I(PHY,"Skip PUSCH generation!\n"); - ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; - } - } - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) { - - ue->generate_ul_signal[eNB_id] = 1; - - // deactivate service request - // ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; - LOG_D(PHY,"Generating PUSCH (Abssubframe: %d.%d): harq-Id: %d, round: %d, MaxReTrans: %d \n",frame_tx,nr_tti_tx,harq_pid,ue->ulsch[eNB_id]->harq_processes[harq_pid]->round,ue->ulsch[eNB_id]->Mlimit); - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round >= (ue->ulsch[eNB_id]->Mlimit - 1)) - { - LOG_D(PHY,"PUSCH MAX Retransmission achieved ==> send last pusch\n"); - ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; - ue->ulsch[eNB_id]->harq_processes[harq_pid]->round = 0; - } - - ack_status_cw0 = nr_reset_ack(&ue->frame_parms, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, - nr_tti_tx, - proc->nr_tti_rx, - ue->ulsch[eNB_id]->o_ACK, - &Nbundled, - 0); - ack_status_cw1 = nr_reset_ack(&ue->frame_parms, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][1]->harq_ack, - nr_tti_tx, - proc->nr_tti_rx, - ue->ulsch[eNB_id]->o_ACK, - &NbundledCw1, - 1); - - //Nbundled = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack; - //ue->ulsch[eNB_id]->bundling = Nbundled; - - first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; - nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; - - - // check Periodic CQI/RI reporting - cqi_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0)&& - (nr_is_cqi_TXOp(ue,proc,eNB_id)==1)); - - ri_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) && - (nr_is_ri_TXOp(ue,proc,eNB_id)==1)); - - // compute CQI/RI resources - compute_cqi_ri_resources(ue, ue->ulsch[eNB_id], eNB_id, ue->ulsch[eNB_id]->rnti, P_RNTI, CBA_RNTI, cqi_status, ri_status); - - if (ack_status_cw0 > 0) { - - // check if we received a PDSCH at nr_tti_tx - 4 - // ==> send ACK/NACK on PUSCH - if (ue->frame_parms.frame_type == FDD) - { - ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK = ack_status_cw0 + ack_status_cw1; - } - - -#if T_TRACER - if(ue->ulsch[eNB_id]->o_ACK[0]) - { - LOG_I(PHY,"PUSCH ACK\n"); - T(T_UE_PHY_DLSCH_UE_ACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx), T_INT(Mod_id), T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti), - T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->current_harq_pid)); - } - else - { - LOG_I(PHY,"PUSCH NACK\n"); - T(T_UE_PHY_DLSCH_UE_NACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx), T_INT(Mod_id), T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti), - T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->current_harq_pid)); - } -#endif -#ifdef UE_DEBUG_TRACE - LOG_I(PHY,"[UE %d][PDSCH %x] AbsSubFrame %d.%d Generating ACK (%d,%d) for %d bits on PUSCH\n", - Mod_id, - ue->ulsch[eNB_id]->rnti, - frame_tx%1024,nr_tti_tx, - ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], - ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK); -#endif - } - - //#ifdef UE_DEBUG_TRACE - LOG_I(PHY, - "[UE %d][PUSCH %d] AbsSubframe %d.%d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, tbs %d, rv %d, " - "cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d, ack_status_cw0 %d ack_status_cw1 %d bundling %d, Nbundled %d, CQI %d, RI %d\n", - Mod_id,harq_pid,frame_tx%1024,nr_tti_tx, - first_rb,nb_rb, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, - (ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift+ - ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2+ - ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[nr_tti_tx<<1])%12, - ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2, - ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[nr_tti_tx<<1], - ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1], - ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK, - ack_status_cw0, - ack_status_cw1, - ue->ulsch[eNB_id]->bundling, Nbundled, - cqi_status, - ri_status); - //#endif - - - - - - if (Msg3_flag == 1) { - LOG_I(PHY,"[UE %d][RAPROC] Frame %d, nr_tti_rx %d Generating (RRCConnectionRequest) Msg3 (nb_rb %d, first_rb %d, round %d, rvidx %d) Msg3: %x.%x.%x|%x.%x.%x.%x.%x.%x\n",Mod_id,frame_tx, - nr_tti_tx, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->round, - ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx, - ue->prach_resources[eNB_id]->Msg3[0], - ue->prach_resources[eNB_id]->Msg3[1], - ue->prach_resources[eNB_id]->Msg3[2], - ue->prach_resources[eNB_id]->Msg3[3], - ue->prach_resources[eNB_id]->Msg3[4], - ue->prach_resources[eNB_id]->Msg3[5], - ue->prach_resources[eNB_id]->Msg3[6], - ue->prach_resources[eNB_id]->Msg3[7], - ue->prach_resources[eNB_id]->Msg3[8]); -#if UE_TIMING_TRACE - start_meas(&ue->ulsch_encoding_stats); -#endif - - if (abstraction_flag==0) { - if (ulsch_encoding(ue->prach_resources[eNB_id]->Msg3, - ue, - harq_pid, - eNB_id, - proc->nr_tti_rx, - ue->transmission_mode[eNB_id],0,0)!=0) { - LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); - //mac_xface->macphy_exit("Error in ulsch_coding"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(&ue->phy_proc_tx); - printf("------FULL TX PROC : %5.2f ------\n",ue->phy_proc_tx.p_time/(cpuf*1000.0)); -#endif - return; - } - } - -#ifdef PHY_ABSTRACTION - else { - ulsch_encoding_emul(ue->prach_resources[eNB_id]->Msg3,ue,eNB_id,proc->nr_tti_rx,harq_pid,0); - } - -#endif - -#if UE_TIMING_TRACE - stop_meas(&ue->ulsch_encoding_stats); -#endif - if (ue->mac_enabled == 1) { - // signal MAC that Msg3 was sent - //mac_xface->Msg3_transmitted(Mod_id, - CC_id, - frame_tx, - eNB_id); - } - } // Msg3_flag==1 - else { - input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; - - if (ue->mac_enabled==1) { - // LOG_D(PHY,"[UE %d] ULSCH : Searching for MAC SDUs\n",Mod_id); - if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) { - //if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { - access_mode=SCHEDULED_ACCESS; - //mac_xface->ue_get_sdu(Mod_id, - CC_id, - frame_tx, - proc->subframe_tx, - nr_tti_tx%(ue->frame_parms.ttis_per_subframe), - eNB_id, - ulsch_input_buffer, - input_buffer_length, - &access_mode); - } - -#ifdef DEBUG_PHY_PROC -#ifdef DEBUG_ULSCH - LOG_D(PHY,"[UE] Frame %d, nr_tti_rx %d : ULSCH SDU (TX harq_pid %d) (%d bytes) : \n",frame_tx,nr_tti_tx,harq_pid, ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3); - - for (int i=0; iulsch[eNB_id]->harq_processes[harq_pid]->TBS>>3; i++) - LOG_T(PHY,"%x.",ulsch_input_buffer[i]); - - LOG_T(PHY,"\n"); -#endif -#endif - } - else { - unsigned int taus(void); - - for (int i=0; iulsch_encoding_stats); -#endif - if (abstraction_flag==0) { - - if (ulsch_encoding(ulsch_input_buffer, - ue, - harq_pid, - eNB_id, - proc->nr_tti_rx, - ue->transmission_mode[eNB_id],0, - Nbundled)!=0) { - LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(&ue->phy_proc_tx); -#endif - return; - } - } - -#ifdef PHY_ABSTRACTION - else { - ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,proc->nr_tti_rx,harq_pid,0); - } - -#endif -#if UE_TIMING_TRACE - stop_meas(&ue->ulsch_encoding_stats); -#endif -} - -if (abstraction_flag == 0) { - if (ue->mac_enabled==1) { - nr_pusch_power_cntl(ue,proc,eNB_id,1, abstraction_flag); - ue->tx_power_dBm[nr_tti_tx] = ue->ulsch[eNB_id]->Po_PUSCH; - } - else { - ue->tx_power_dBm[nr_tti_tx] = ue->tx_power_max_dBm; - } - ue->tx_total_RE[nr_tti_tx] = nb_rb*12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - tx_amp = nr_get_tx_amp(ue->tx_power_dBm[nr_tti_tx], - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - nb_rb); -#else - tx_amp = AMP; -#endif -#if T_TRACER - T(T_UE_PHY_PUSCH_TX_POWER, T_INT(eNB_id),T_INT(Mod_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx),T_INT(ue->tx_power_dBm[nr_tti_tx]), - T_INT(tx_amp),T_INT(ue->ulsch[eNB_id]->f_pusch),T_INT(get_nr_PL(Mod_id,0,eNB_id)),T_INT(nb_rb)); -#endif - -#ifdef UE_DEBUG_TRACE - LOG_I(PHY,"[UE %d][PUSCH %d] AbsSubFrame %d.%d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", - Mod_id,harq_pid,frame_tx%1024,nr_tti_tx,ue->tx_power_dBm[nr_tti_tx],ue->tx_power_max_dBm, tx_amp); -#endif - - if (tx_amp>100) - tx_amp =100; - - //LOG_I(PHY,"[UE %d][PUSCH %d] after AbsSubFrame %d.%d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n", - // Mod_id,harq_pid,frame_tx%1024,nr_tti_tx,ue->tx_power_dBm[nr_tti_tx],ue->tx_power_max_dBm, tx_amp); - - -#if UE_TIMING_TRACE - - start_meas(&ue->ulsch_modulation_stats); -#endif - ulsch_modulation(ue->common_vars.txdataF, - tx_amp, - frame_tx, - nr_tti_tx, - &ue->frame_parms, - ue->ulsch[eNB_id]); - for (int aa=0; aa<1/*frame_parms->nb_antennas_tx*/; aa++) - generate_drs_pusch(ue, - proc, - eNB_id, - tx_amp, - nr_tti_tx, - first_rb, - nb_rb, - aa); -#if UE_TIMING_TRACE - stop_meas(&ue->ulsch_modulation_stats); -#endif - } - -if (abstraction_flag==1) { - // clear SR - ue->sr[nr_tti_tx]=0; - } -} // subframe_scheduling_flag==1 - -VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_OUT); - -#endif - -} -#endif - -#if 0 - -void ue_srs_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) -{ - - //NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - //int8_t frame_tx = proc->frame_tx; - int8_t nr_tti_tx = proc->nr_tti_tx; - int16_t tx_amp; - int16_t Po_SRS; - uint8_t nb_rb_srs; - - SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; - uint8_t isSrsTxOccasion = pSoundingrs_ul_config_dedicated->srsUeSubframe; - - if(isSrsTxOccasion) - { - ue->generate_ul_signal[eNB_id] = 1; - if (ue->mac_enabled==1) - { - srs_power_cntl(ue,proc,eNB_id, (uint8_t*)(&nb_rb_srs), abstraction_flag); - Po_SRS = ue->ulsch[eNB_id]->Po_SRS; - } - else - { - Po_SRS = ue->tx_power_max_dBm; - } - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - if (ue->mac_enabled==1) - { - tx_amp = nr_get_tx_amp(Po_SRS, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - nb_rb_srs); - } - else - { - tx_amp = AMP; - } -#else - tx_amp = AMP; -#endif - LOG_D(PHY,"SRS PROC; TX_MAX_POWER %d, Po_SRS %d, NB_RB_UL %d, NB_RB_SRS %d TX_AMPL %d\n",ue->tx_power_max_dBm, - Po_SRS, - ue->frame_parms.N_RB_UL, - nb_rb_srs, - tx_amp); - - uint16_t nsymb = (ue->frame_parms.Ncp==0) ? 14:12; - uint16_t symbol_offset = (int)ue->frame_parms.ofdm_symbol_size*((nr_tti_tx*nsymb)+(nsymb-1)); - generate_srs(&ue->frame_parms, - &ue->soundingrs_ul_config_dedicated[eNB_id], - &ue->common_vars.txdataF[eNB_id][symbol_offset], - tx_amp, - nr_tti_tx); - } -} - -int16_t get_pucch2_cqi(PHY_VARS_NR_UE *ue,int eNB_id,int *len) { - - if ((ue->transmission_mode[eNB_id]<4)|| - (ue->transmission_mode[eNB_id]==7)) { // Mode 1-0 feedback - // 4-bit CQI message - /*LOG_I(PHY,"compute CQI value, TM %d, length 4, Cqi Avg %d, value %d \n", ue->transmission_mode[eNB_id], - ue->measurements.wideband_cqi_avg[eNB_id], - sinr2cqi((double)ue->measurements.wideband_cqi_avg[eNB_id], - ue->transmission_mode[eNB_id]));*/ - *len=4; - return(sinr2cqi((double)ue->measurements.wideband_cqi_avg[eNB_id], - ue->transmission_mode[eNB_id])); - } - else { // Mode 1-1 feedback, later - //LOG_I(PHY,"compute CQI value, TM %d, length 0, Cqi Avg 0 \n", ue->transmission_mode[eNB_id]); - *len=0; - // 2-antenna ports RI=1, 6 bits (2 PMI, 4 CQI) - - // 2-antenna ports RI=2, 8 bits (1 PMI, 7 CQI/DIFF CQI) - return(0); - } } - -int16_t get_pucch2_ri(PHY_VARS_NR_UE *ue,int eNB_id) { - - return(1); -} - - -void get_pucch_param(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - uint8_t *ack_payload, - PUCCH_FMT_t format, - uint8_t eNB_id, - uint8_t SR, - uint8_t cqi_report, - uint16_t *pucch_resource, - uint8_t *pucch_payload, - uint16_t *plength) -{ - - switch (format) { - case pucch_format1: - { - pucch_resource[0] = ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex; - pucch_payload[0] = 0; // payload is ignored in case of format1 - pucch_payload[1] = 0; // payload is ignored in case of format1 - } - break; - - case pucch_format1a: - case pucch_format1b: - { - pucch_resource[0] = nr_get_n1_pucch(ue, - proc, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, - eNB_id, - ack_payload, - SR); - pucch_payload[0] = ack_payload[0]; - pucch_payload[1] = ack_payload[1]; - //pucch_payload[1] = 1; - } - break; - - case pucch_format2: - { - pucch_resource[0] = ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex; - if(cqi_report) - { - pucch_payload[0] = get_pucch2_cqi(ue,eNB_id,(int*)plength); - } - else - { - *plength = 1; - pucch_payload[0] = get_pucch2_ri(ue,eNB_id); - } - } - break; - - case pucch_format2a: - case pucch_format2b: - LOG_E(PHY,"NO Resource available for PUCCH 2a/2b \n"); - break; - - case pucch_format3: - fprintf(stderr, "PUCCH format 3 not handled\n"); - abort(); - } -} - -#ifdef NR_PUCCH_SCHED -void ue_nr_pucch_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) { -} -#endif - -void ue_pucch_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) { - - - uint8_t pucch_ack_payload[2]; - uint16_t pucch_resource; - ANFBmode_t bundling_flag; - PUCCH_FMT_t format; - - uint8_t SR_payload; - uint8_t pucch_payload[2]; - uint16_t len; - - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - int frame_tx=proc->frame_tx; - int nr_tti_tx=proc->nr_tti_tx; - int Mod_id = ue->Mod_id; - int CC_id = ue->CC_id; - int tx_amp; - int16_t Po_PUCCH; - uint8_t ack_status_cw0=0; - uint8_t ack_status_cw1=0; - uint8_t nb_cw=0; - uint8_t cqi_status=0; - uint8_t ri_status=0; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_IN); - - SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id]; - - // 36.213 8.2 - /*if ackNackSRS_SimultaneousTransmission == TRUE and in the cell specific SRS subframes UE shall transmit - ACK/NACK and SR using the shortened PUCCH format. This shortened PUCCH format shall be used in a cell - specific SRS nr_tti_rx even if the UE does not transmit SRS in that nr_tti_rx - */ - - int harq_pid = nr_subframe2harq_pid(&ue->frame_parms, - frame_tx, - nr_tti_tx); - - if(ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag) - { - LOG_D(PHY,"PUSCH is programmed on this nr_tti_rx [pid %d] AbsSuframe %d.%d ==> Skip PUCCH transmission \n",harq_pid,frame_tx,nr_tti_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_OUT); - return; - } - - uint8_t isShortenPucch = (pSoundingrs_ul_config_dedicated->srsCellSubframe && frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission); - - bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode; - - if ((frame_parms->frame_type==FDD) || - (bundling_flag==bundling) || - ((frame_parms->frame_type==TDD)&&(frame_parms->tdd_config==1)&&((nr_tti_tx!=2)||(nr_tti_tx!=7)))) { - format = pucch_format1a; - LOG_D(PHY,"[UE] PUCCH 1a\n"); - } else { - format = pucch_format1b; - LOG_D(PHY,"[UE] PUCCH 1b\n"); - } - - // Part - I - // Collect feedback that should be transmitted at this nr_tti_rx - // - SR - // - ACK/NACK - // - CQI - // - RI - - SR_payload = 0; - if (nr_is_SR_TXOp(ue,proc,eNB_id)==1) - { - if (ue->mac_enabled==1) { - SR_payload = mac_xface->ue_get_SR(Mod_id, - CC_id, - frame_tx, - eNB_id, - ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->crnti, - nr_tti_tx); // nr_tti_rx used for meas gap - } - else { - SR_payload = 1; - } - } - - ack_status_cw0 = nr_get_ack(&ue->frame_parms, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, - nr_tti_tx, - proc->nr_tti_rx, - pucch_ack_payload, - 0); - - ack_status_cw1 = nr_get_ack(&ue->frame_parms, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][1]->harq_ack, - nr_tti_tx, - proc->nr_tti_rx, - pucch_ack_payload, - 1); - - nb_cw = ( (ack_status_cw0 != 0) ? 1:0) + ( (ack_status_cw1 != 0) ? 1:0); - - cqi_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0)&& - (nr_is_cqi_TXOp(ue,proc,eNB_id)==1)); - - ri_status = ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) && - (nr_is_ri_TXOp(ue,proc,eNB_id)==1)); - - // Part - II - // if nothing to report ==> exit function - if( (nb_cw==0) && (SR_payload==0) && (cqi_status==0) && (ri_status==0) ) - { - LOG_D(PHY,"PUCCH No feedback AbsSubframe %d.%d SR_payload %d nb_cw %d pucch_ack_payload[0] %d pucch_ack_payload[1] %d cqi_status %d Return \n", - frame_tx%1024, nr_tti_tx, SR_payload, nb_cw, pucch_ack_payload[0], pucch_ack_payload[1], cqi_status); - return; - } - - // Part - III - // Decide which PUCCH format should be used if needed - format = get_pucch_format(frame_parms->frame_type, - frame_parms->Ncp, - SR_payload, - nb_cw, - cqi_status, - ri_status, - bundling_flag); - // Determine PUCCH resources and payload: mandatory for pucch encoding - get_pucch_param(ue, - proc, - pucch_ack_payload, - format, - eNB_id, - SR_payload, - cqi_status, - &pucch_resource, - (uint8_t *)&pucch_payload, - &len); - - - LOG_D(PHY,"PUCCH feedback AbsSubframe %d.%d SR %d NbCW %d (%d %d) AckNack %d.%d CQI %d RI %d format %d pucch_resource %d pucch_payload %d %d \n", - frame_tx%1024, nr_tti_tx, SR_payload, nb_cw, ack_status_cw0, ack_status_cw1, pucch_ack_payload[0], pucch_ack_payload[1], cqi_status, ri_status, format, pucch_resource,pucch_payload[0],pucch_payload[1]); - - // Part - IV - // Generate PUCCH signal - ue->generate_ul_signal[eNB_id] = 1; - - switch (format) { - case pucch_format1: - case pucch_format1a: - case pucch_format1b: - { - if (ue->mac_enabled == 1) { - Po_PUCCH = nr_pucch_power_cntl(ue,proc,nr_tti_tx,eNB_id,format); - } - else { - Po_PUCCH = ue->tx_power_max_dBm; - } - ue->tx_power_dBm[nr_tti_tx] = Po_PUCCH; - ue->tx_total_RE[nr_tti_tx] = 12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - tx_amp = nr_get_tx_amp(Po_PUCCH, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - 1); -#else - tx_amp = AMP; -#endif -#if T_TRACER - T(T_UE_PHY_PUCCH_TX_POWER, T_INT(eNB_id),T_INT(Mod_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx),T_INT(ue->tx_power_dBm[nr_tti_tx]), - T_INT(tx_amp),T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->g_pucch),T_INT(get_nr_PL(ue->Mod_id,ue->CC_id,eNB_id))); -#endif - -#ifdef UE_DEBUG_TRACE - if(format == pucch_format1) - { - LOG_I(PHY,"[UE %d][SR %x] AbsSubframe %d.%d Generating PUCCH 1 (SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH %d\n", - Mod_id, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, - frame_tx%1024, nr_tti_tx, - frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, - isShortenPucch, - ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex, - Po_PUCCH); - } - else - { - if (SR_payload>0) { - LOG_I(PHY,"[UE %d][SR %x] AbsSubFrame %d.%d Generating PUCCH %s payload %d,%d (with SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH %d, amp %d\n", - Mod_id, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, - frame_tx % 1024, nr_tti_tx, - (format == pucch_format1a? "1a": ( - format == pucch_format1b? "1b" : "??")), - pucch_ack_payload[0],pucch_ack_payload[1], - frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, - isShortenPucch, - pucch_resource, - Po_PUCCH, - tx_amp); - } else { - LOG_I(PHY,"[UE %d][PDSCH %x] AbsSubFrame %d.%d rx_offset_diff: %d, Generating PUCCH %s, an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n", - Mod_id, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, - frame_tx%1024, nr_tti_tx,ue->rx_offset_diff, - (format == pucch_format1a? "1a": ( - format == pucch_format1b? "1b" : "??")), - frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, - isShortenPucch, - pucch_resource,pucch_payload[0],pucch_payload[1],SR_payload, - Po_PUCCH, - tx_amp); - } - } -#endif - -#if T_TRACER - if(pucch_payload[0]) - { - T(T_UE_PHY_DLSCH_UE_ACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx), T_INT(Mod_id), T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti), - T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->current_harq_pid)); - } - else - { - T(T_UE_PHY_DLSCH_UE_NACK, T_INT(eNB_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx), T_INT(Mod_id), T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti), - T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->current_harq_pid)); - } -#endif - - if (abstraction_flag == 0) { - - generate_pucch1x(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - format, - &ue->pucch_config_dedicated[eNB_id], - pucch_resource, - isShortenPucch, // shortened format - pucch_payload, - tx_amp, - nr_tti_tx); - - } else { -#ifdef PHY_ABSTRACTION - LOG_D(PHY,"Calling generate_pucch_emul ... (ACK %d %d, SR %d)\n",pucch_ack_payload[0],pucch_ack_payload[1],SR_payload); - generate_pucch_emul(ue, - proc, - format, - ue->frame_parms.pucch_config_common.nCS_AN, - pucch_payload, - SR_payload); -#endif - } - } - break; - - - case pucch_format2: - { - if (ue->mac_enabled == 1) { - Po_PUCCH = nr_pucch_power_cntl(ue,proc,nr_tti_tx,eNB_id,format); - } - else { - Po_PUCCH = ue->tx_power_max_dBm; - } - ue->tx_power_dBm[nr_tti_tx] = Po_PUCCH; - ue->tx_total_RE[nr_tti_tx] = 12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - tx_amp = nr_get_tx_amp(Po_PUCCH, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - 1); -#else - tx_amp = AMP; -#endif -#if T_TRACER - T(T_UE_PHY_PUCCH_TX_POWER, T_INT(eNB_id),T_INT(Mod_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx),T_INT(ue->tx_power_dBm[nr_tti_tx]), - T_INT(tx_amp),T_INT(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->g_pucch),T_INT(get_nr_PL(ue->Mod_id,ue->CC_id,eNB_id))); -#endif -#ifdef UE_DEBUG_TRACE - LOG_I(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (RI or CQI), Po_PUCCH %d, isShortenPucch %d, amp %d\n", - Mod_id, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, - frame_tx%1024, nr_tti_tx, - Po_PUCCH, - isShortenPucch, - tx_amp); -#endif - generate_pucch2x(ue->common_vars.txdataF, - &ue->frame_parms, - ue->ncs_cell, - format, - &ue->pucch_config_dedicated[eNB_id], - pucch_resource, - pucch_payload, - len, // A - 0, // B2 not needed - tx_amp, - nr_tti_tx, - ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][eNB_id]->crnti); - } - break; - - case pucch_format2a: - LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2a (RI or CQI) Ack/Nack 1bit \n", - Mod_id, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, - frame_tx%1024, nr_tti_tx); - break; - case pucch_format2b: - LOG_D(PHY,"[UE %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2b (RI or CQI) Ack/Nack 2bits\n", - Mod_id, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->rnti, - frame_tx%1024, nr_tti_tx); - break; - default: - break; - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_OUT); - -} - -#endif - - void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, - uint8_t gNB_id, - uint8_t thread_id){ - //int32_t ulsch_start=0; - int slot_tx = proc->nr_tti_tx; + uint8_t gNB_id) { + + int slot_tx = proc->nr_slot_tx; int frame_tx = proc->frame_tx; - uint8_t harq_pid = 0; - runmode_t mode = normal_txrx; + + AssertFatal(ue->CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN); memset(ue->common_vars.txdataF[0], 0, sizeof(int)*14*ue->frame_parms.ofdm_symbol_size); - LOG_I(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); + LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); + -#if UE_TIMING_TRACE start_meas(&ue->phy_proc_tx); -#endif - if (ue->UE_mode[gNB_id] == PUSCH || get_softmodem_params()->phy_test == 1){ - if (ue->ulsch[thread_id][gNB_id][0]->harq_processes[harq_pid]->status == ACTIVE) - nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, thread_id, gNB_id); + if (ue->UE_mode[gNB_id] <= PUSCH){ - -/* - if (ue->UE_mode[eNB_id] == PUSCH) { - // check if we need to use PUCCH 1a/1b - ue_pucch_procedures(ue,proc,eNB_id,abstraction_flag); - // check if we need to use SRS - ue_srs_procedures(ue,proc,eNB_id,abstraction_flag); - } // UE_mode==PUSCH -*/ - - if (get_softmodem_params()->usim_test==0) { - LOG_D(PHY, "Sending PUCCH\n"); - pucch_procedures_ue_nr(ue, - gNB_id, - proc, - TRUE); - } - - LOG_D(PHY, "Sending data \n"); - nr_ue_pusch_common_procedures(ue, - harq_pid, - slot_tx, - thread_id, - gNB_id, - &ue->frame_parms); - } - //LOG_M("txdata.m","txs",ue->common_vars.txdata[0],1228800,1,1); - - /* RACH */ - if (get_softmodem_params()->do_ra==1) { - if ((ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { - nr_ue_prach_procedures(ue, proc, gNB_id, mode); + for (uint8_t harq_pid = 0; harq_pid < ue->ulsch[proc->thread_id][gNB_id][0]->number_harq_processes_for_pusch; harq_pid++) { + if (ue->ulsch[proc->thread_id][gNB_id][0]->harq_processes[harq_pid]->status == ACTIVE) + nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, proc->thread_id, gNB_id); } + } - LOG_I(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE stop_meas(&ue->phy_proc_tx); -#endif + } -/* -void phy_procedures_UE_S_TX(PHY_VARS_NR_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,relaying_type_t r_type) -{ - int aa;//i,aa; - NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - - if (abstraction_flag==0) { - - for (aa=0; aanb_antennas_tx; aa++) { -#if defined(EXMIMO) //this is the EXPRESS MIMO case - int i; - // set the whole tx buffer to RX - for (i=0; isamples_per_subframe; i++) - ue->common_vars.txdata[aa][i] = 0x00010001; - -#else //this is the normal case - memset(&ue->common_vars.txdata[aa][0],0, - (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe)*sizeof(int32_t)); -#endif //else EXMIMO - - } - } -} - -*/ - -void nr_ue_measurement_procedures(uint16_t l, // symbol index of each slot [0..6] - PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - uint8_t eNB_id, - uint16_t slot, // slot index of each radio frame [0..19] - runmode_t mode) -{ - LOG_D(PHY,"ue_measurement_procedures l %u Ncp %d\n",l,ue->frame_parms.Ncp); +void nr_ue_measurement_procedures(uint16_t l, + PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + uint8_t gNB_id, + uint16_t slot){ NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; - int nr_tti_rx = proc->nr_tti_rx; + int frame_rx = proc->frame_rx; + int nr_slot_rx = proc->nr_slot_rx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN); if (l==2) { - // UE measurements on symbol 0 - LOG_D(PHY,"Calling measurements nr_tti_rx %d, rxdata %p\n",nr_tti_rx,ue->common_vars.rxdata); -/* - nr_ue_measurements(ue, - 0, - 0, - 0, - 0, - nr_tti_rx); -*/ - //(nr_tti_rx*frame_parms->samples_per_tti+ue->rx_offset)%(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME) + + LOG_D(PHY,"Doing UE measurement procedures in symbol l %u Ncp %d nr_slot_rx %d, rxdata %p\n", + l, + ue->frame_parms.Ncp, + nr_slot_rx, + ue->common_vars.rxdata); + + nr_ue_measurements(ue, proc, nr_slot_rx); #if T_TRACER if(slot == 0) - T(T_UE_PHY_MEAS, T_INT(eNB_id), T_INT(ue->Mod_id), T_INT(proc->frame_rx%1024), T_INT(proc->nr_tti_rx), + T(T_UE_PHY_MEAS, T_INT(gNB_id), T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_slot_rx), T_INT((int)(10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB)), T_INT((int)ue->measurements.rx_rssi_dBm[0]), T_INT((int)(ue->measurements.rx_power_avg_dB[0] - ue->measurements.n0_power_avg_dB)), @@ -2346,21 +326,6 @@ void nr_ue_measurement_procedures(uint16_t l, // symbol index of each slot [0 T_INT((int)ue->common_vars.freq_offset)); #endif } -#if 0 - if (l==(6-ue->frame_parms.Ncp)) { - - // make sure we have signal from PSS/SSS for N0 measurement - // LOG_I(PHY," l==(6-ue->frame_parms.Ncp) ue_rrc_measurements\n"); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_IN); - ue_rrc_measurements(ue, - slot, - abstraction_flag); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_OUT); - - - } -#endif // accumulate and filter timing offset estimation every subframe (instead of every frame) if (( slot == 2) && (l==(2-frame_parms->Ncp))) { @@ -2370,8 +335,8 @@ void nr_ue_measurement_procedures(uint16_t l, // symbol index of each slot [0 VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_IN); - //printf("start adjust gain power avg db %d\n", ue->measurements.rx_power_avg_dB[eNB_id]); - phy_adjust_gain_nr (ue,ue->measurements.rx_power_avg_dB[eNB_id],eNB_id); + //printf("start adjust gain power avg db %d\n", ue->measurements.rx_power_avg_dB[gNB_id]); + phy_adjust_gain_nr (ue,ue->measurements.rx_power_avg_dB[gNB_id],gNB_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT); @@ -2380,102 +345,28 @@ void nr_ue_measurement_procedures(uint16_t l, // symbol index of each slot [0 VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT); } - - -#if 0 -void restart_phy(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc, uint8_t eNB_id,uint8_t abstraction_flag) -{ - - // uint8_t last_slot; - uint8_t i; - LOG_I(PHY,"[UE %d] frame %d, slot %d, restarting PHY!\n",ue->Mod_id,proc->frame_rx,proc->nr_tti_rx); - //mac_xface->macphy_exit("restart_phy called"); - // first_run = 1; - - if (abstraction_flag ==0 ) { - ue->UE_mode[eNB_id] = NOT_SYNCHED; - } else { - ue->UE_mode[eNB_id] = PRACH; - ue->prach_resources[eNB_id]=NULL; - } - - proc->frame_rx = -1; - proc->frame_tx = -1; - // ue->synch_wait_cnt=0; - // ue->sched_cnt=-1; - - ue->pbch_vars[eNB_id]->pdu_errors_conseq=0; - ue->pbch_vars[eNB_id]->pdu_errors=0; - - ue->pdcch_vars[0][eNB_id]->dci_errors = 0; - ue->pdcch_vars[0][eNB_id]->dci_missed = 0; - ue->pdcch_vars[0][eNB_id]->dci_false = 0; - ue->pdcch_vars[0][eNB_id]->dci_received = 0; - - ue->pdcch_vars[1][eNB_id]->dci_errors = 0; - ue->pdcch_vars[1][eNB_id]->dci_missed = 0; - ue->pdcch_vars[1][eNB_id]->dci_false = 0; - ue->pdcch_vars[1][eNB_id]->dci_received = 0; - - ue->dlsch_errors[eNB_id] = 0; - ue->dlsch_errors_last[eNB_id] = 0; - ue->dlsch_received[eNB_id] = 0; - ue->dlsch_received_last[eNB_id] = 0; - ue->dlsch_fer[eNB_id] = 0; - ue->dlsch_SI_received[eNB_id] = 0; - ue->dlsch_ra_received[eNB_id] = 0; - ue->dlsch_p_received[eNB_id] = 0; - ue->dlsch_SI_errors[eNB_id] = 0; - ue->dlsch_ra_errors[eNB_id] = 0; - ue->dlsch_p_errors[eNB_id] = 0; - - ue->dlsch_mch_received[eNB_id] = 0; - - for (i=0; i < MAX_MBSFN_AREA ; i ++) { - ue->dlsch_mch_received_sf[i][eNB_id] = 0; - ue->dlsch_mcch_received[i][eNB_id] = 0; - ue->dlsch_mtch_received[i][eNB_id] = 0; - ue->dlsch_mcch_errors[i][eNB_id] = 0; - ue->dlsch_mtch_errors[i][eNB_id] = 0; - ue->dlsch_mcch_trials[i][eNB_id] = 0; - ue->dlsch_mtch_trials[i][eNB_id] = 0; - } - - //ue->total_TBS[eNB_id] = 0; - //ue->total_TBS_last[eNB_id] = 0; - //ue->bitrate[eNB_id] = 0; - //ue->total_received_bits[eNB_id] = 0; -} -#endif //(0) - void nr_ue_pbch_procedures(uint8_t gNB_id, PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t abstraction_flag) { - // int i; - //int pbch_tx_ant=0; - //uint8_t pbch_phase; int ret = 0; - //static uint8_t first_run = 1; - //uint8_t pbch_trials = 0; DevAssert(ue); int frame_rx = proc->frame_rx; - int nr_tti_rx = proc->nr_tti_rx; + int nr_slot_rx = proc->nr_slot_rx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN); - //LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,pbch_phase,ue->frame_parms.Nid_cell,gNB_id); + LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,nr_slot_rx,ue->frame_parms.Nid_cell,gNB_id); ret = nr_rx_pbch(ue, proc, - ue->pbch_vars[gNB_id], - &ue->frame_parms, - gNB_id, - (ue->frame_parms.ssb_index)&7, - SISO, - ue->high_speed_flag); + ue->pbch_vars[gNB_id], + &ue->frame_parms, + gNB_id, + (ue->frame_parms.ssb_index)&7, + SISO); if (ret==0) { @@ -2483,24 +374,38 @@ void nr_ue_pbch_procedures(uint8_t gNB_id, // Switch to PRACH state if it is first PBCH after initial synch and no timing correction is performed if (ue->UE_mode[gNB_id] == NOT_SYNCHED && ue->no_timing_correction == 1){ - ue->UE_mode[gNB_id] = PRACH; - ue->prach_resources[gNB_id]->sync_frame = frame_rx; - ue->prach_resources[gNB_id]->init_msg1 = 0; + if (get_softmodem_params()->do_ra) { + ue->UE_mode[gNB_id] = PRACH; + ue->prach_resources[gNB_id]->sync_frame = frame_rx; + ue->prach_resources[gNB_id]->init_msg1 = 0; + } else { + ue->UE_mode[gNB_id] = PUSCH; + } } #ifdef DEBUG_PHY_PROC uint16_t frame_tx; - LOG_D(PHY,"[UE %d] frame %d, nr_tti_rx %d, Received PBCH (MIB): frame_tx %d. N_RB_DL %d\n", + LOG_D(PHY,"[UE %d] frame %d, nr_slot_rx %d, Received PBCH (MIB): frame_tx %d. N_RB_DL %d\n", ue->Mod_id, frame_rx, - nr_tti_rx, + nr_slot_rx, frame_tx, ue->frame_parms.N_RB_DL); #endif } else { - LOG_E(PHY,"[UE %d] frame %d, nr_tti_rx %d, Error decoding PBCH!\n", - ue->Mod_id,frame_rx, nr_tti_rx); + LOG_E(PHY,"[UE %d] frame %d, nr_slot_rx %d, Error decoding PBCH!\n", + ue->Mod_id,frame_rx, nr_slot_rx); + /*FILE *fd; + if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) { + fwrite((void *)&ue->common_vars.rxdata[0][0], + sizeof(int32_t), + ue->frame_parms.samples_per_frame, + fd); + LOG_I(PHY,"Dummping Frame ... bye bye \n"); + fclose(fd); + exit(0); + }*/ /* write_output("rxsig0.m","rxs0", ue->common_vars.rxdata[0],ue->frame_parms.samples_per_subframe,1,1); @@ -2520,8 +425,13 @@ void nr_ue_pbch_procedures(uint8_t gNB_id, ue->pbch_vars[gNB_id]->pdu_errors++; if (ue->pbch_vars[gNB_id]->pdu_errors_conseq>=100) { - LOG_E(PHY,"More that 100 consecutive PBCH errors! Exiting!\n"); - exit_fun("More that 100 consecutive PBCH errors! Exiting!\n"); + if (get_softmodem_params()->non_stop) { + LOG_E(PHY,"More that 100 consecutive PBCH errors! Going back to Sync mode!\n"); + ue->lost_sync = 1; + } else { + LOG_E(PHY,"More that 100 consecutive PBCH errors! Exiting!\n"); + exit_fun("More that 100 consecutive PBCH errors! Exiting!\n"); + } } } @@ -2532,7 +442,7 @@ void nr_ue_pbch_procedures(uint8_t gNB_id, #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d] frame %d, slot %d, PBCH errors = %d, consecutive errors = %d!\n", - ue->Mod_id,frame_rx, nr_tti_rx, + ue->Mod_id,frame_rx, nr_slot_rx, ue->pbch_vars[gNB_id]->pdu_errors, ue->pbch_vars[gNB_id]->pdu_errors_conseq); #endif @@ -2561,12 +471,18 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb #ifdef NR_PDCCH_SCHED int nr_ue_pdcch_procedures(uint8_t gNB_id, - PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc) + PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int n_ss) { int frame_rx = proc->frame_rx; - int nr_tti_rx = proc->nr_tti_rx; + int nr_slot_rx = proc->nr_slot_rx; unsigned int dci_cnt=0; + fapi_nr_dci_indication_t dci_ind = {0}; + nr_downlink_indication_t dl_indication; + + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][gNB_id]; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &pdcch_vars->pdcch_config[n_ss]; /* // unsigned int dci_cnt=0, i; //removed for nr_ue_pdcch_procedures and added in the loop for nb_coreset_active @@ -2575,10 +491,10 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, #endif int frame_rx = proc->frame_rx; - int nr_tti_rx = proc->nr_tti_rx; + int nr_slot_rx = proc->nr_slot_rx; NR_DCI_ALLOC_t dci_alloc_rx[8]; - //uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); + //uint8_t next1_thread_id = proc->thread_id== (RX_NB_TH-1) ? 0:(proc->thread_id+1); //uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); @@ -2589,8 +505,8 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, uint8_t dci_fields_sizes_cnt[MAX_NR_DCI_DECODED_SLOT][NBR_NR_DCI_FIELDS][NBR_NR_FORMATS]; int nb_searchspace_active=0; - NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; - NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][gNB_id]; + NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[proc->thread_id]; + NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[proc->thread_id][gNB_id]; // s in TS 38.212 Subclause 10.1, for each active BWP the UE can deal with 10 different search spaces // Higher layers have updated the number of searchSpaces with are active in the current slot and this value is stored in variable nb_searchspace_total int nb_searchspace_total = pdcch_vars2->nb_search_space; @@ -2612,7 +528,7 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, #ifdef NR_PDCCH_SCHED_DEBUG printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> there is a bug in FAPI to calculate nb_searchspace_total so we set it to 1...\n"); printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> the number of searchSpaces active in the current slot(%d) is %d) \n", - nr_tti_rx,nb_searchspace_total); + nr_slot_rx,nb_searchspace_total); #endif //FK: we define dci_ind and dl_indication as local variables, this way the call to the mac should be thread safe @@ -2636,12 +552,12 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, // The following code has been removed as it is handled by higher layers (fapi) // - // Verify that monitoring is required at the slot nr_tti_rx. We will run pdcch procedure only if do_pdcch_monitoring_current_slot=1 + // Verify that monitoring is required at the slot nr_slot_rx. We will run pdcch procedure only if do_pdcch_monitoring_current_slot=1 // For Type0-PDCCH searchspace, we need to calculate the monitoring slot from Tables 13-1 .. 13-15 in TS 38.213 Subsection 13 //NR_UE_SLOT_PERIOD_OFFSET_t sl_period_offset_mon = pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset; //if (sl_period_offset_mon == nr_sl1) { //do_pdcch_monitoring_current_slot=1; // PDCCH monitoring in every slot - //} else if (nr_tti_rx%(uint16_t)sl_period_offset_mon == pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset_offset) { + //} else if (nr_slot_rx%(uint16_t)sl_period_offset_mon == pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset_offset) { //do_pdcch_monitoring_current_slot=1; // PDCCH monitoring in every monitoringSlotPeriodicityAndOffset slot with offset //} @@ -2660,7 +576,7 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, #endif // if (do_pdcch_monitoring_current_slot) { - // the searchSpace indicates that we need to monitor PDCCH in current nr_tti_rx + // the searchSpace indicates that we need to monitor PDCCH in current nr_slot_rx // get the parameters describing the current SEARCHSPACE // the CORESET id applicable to the current SearchSpace //int searchSpace_coreset_id = pdcch_vars2->searchSpace[nb_searchspace_active].controlResourceSetId; @@ -2722,9 +638,7 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_IN); -#if UE_TIMING_TRACE - start_meas(&ue->dlsch_rx_pdcch_stats); -#endif + start_meas(&ue->dlsch_rx_pdcch_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN); #ifdef NR_PDCCH_SCHED_DEBUG @@ -2733,8 +647,8 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, searchSpaceType); #endif nr_rx_pdcch(ue, - proc->frame_rx, - nr_tti_rx, + frame_rx, + nr_slot_rx, gNB_id, //(ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI, SISO, @@ -2752,42 +666,35 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, */ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN); - nr_rx_pdcch(ue, - proc->frame_rx, - nr_tti_rx); + nr_rx_pdcch(ue, proc, rel15); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_IN); #ifdef NR_PDCCH_SCHED_DEBUG - printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_dci_decoding_procedure with (nb_searchspace_active=%d)\n", - pdcch_vars->nb_search_space); + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_dci_decoding_procedure for search space %d)\n", + n_ss); #endif - fapi_nr_dci_indication_t dci_ind={0}; - nr_downlink_indication_t dl_indication={0}; - dci_cnt = nr_dci_decoding_procedure(ue, - proc->frame_rx, - nr_tti_rx, - &dci_ind); + dci_cnt = nr_dci_decoding_procedure(ue, proc, &dci_ind, rel15); #ifdef NR_PDCCH_SCHED_DEBUG LOG_I(PHY,"<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_dci_decoding_procedure() -> dci_cnt=%u\n",dci_cnt); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT); - //LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d PHICH RX\n",ue->Mod_id,frame_rx,nr_tti_rx); + //LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_slot_rx %d PHICH RX\n",ue->Mod_id,frame_rx,nr_slot_rx); for (int i=0; i rnti %x : format %d\n", - ue->Mod_id,frame_rx%1024,nr_tti_rx,nr_mode_string[ue->UE_mode[gNB_id]], + ue->Mod_id,frame_rx%1024,nr_slot_rx,nr_mode_string[ue->UE_mode[gNB_id]], i + 1, dci_cnt, dci_ind.dci_list[i].rnti, dci_ind.dci_list[i].dci_format); } - ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][gNB_id]->dci_received += dci_cnt; + ue->pdcch_vars[proc->thread_id][gNB_id]->dci_received += dci_cnt; dci_ind.number_of_dcis = dci_cnt; /* @@ -2809,7 +716,7 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, &dci_ind.dci_list[i].dci, dci_fields_sizes_cnt[i], dci_alloc_rx[i].format, - nr_tti_rx, + nr_slot_rx, pdcch_vars2->n_RB_BWP[nb_searchspace_active], pdcch_vars2->n_RB_BWP[nb_searchspace_active], crc_scrambled_values); @@ -2827,495 +734,156 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, */ // fill dl_indication message - dl_indication.module_id = ue->Mod_id; - dl_indication.cc_id = ue->CC_id; - dl_indication.gNB_index = gNB_id; - dl_indication.frame = frame_rx; - dl_indication.slot = nr_tti_rx; - dl_indication.rx_ind = NULL; //no data, only dci for now - dl_indication.dci_ind = &dci_ind; - + nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, gNB_id); // send to mac ue->if_inst->dl_indication(&dl_indication, NULL); -#if UE_TIMING_TRACE stop_meas(&ue->dlsch_rx_pdcch_stats); -#endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); return(dci_cnt); } #endif // NR_PDCCH_SCHED +int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_id, PDSCH_t pdsch, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1) { - - -#if 0 - - if (generate_ue_dlsch_params_from_dci(frame_rx, - nr_tti_rx, - (DCI1A_5MHz_TDD_1_6_t *)&dci_alloc_rx[i].dci_pdu, - ue->prach_resources[eNB_id]->ra_RNTI, - format1A, - ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id], - ue->pdsch_vars_ra[eNB_id], - &ue->dlsch_ra[eNB_id], - &ue->frame_parms, - ue->pdsch_config_dedicated, - SI_RNTI, - ue->prach_resources[eNB_id]->ra_RNTI, - P_RNTI, - ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], - 0)==0) { - - ue->dlsch_ra_received[eNB_id]++; - - #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE DLSCH RA_RNTI format 1A, rb_alloc %x, dlsch_ra[eNB_id] %p\n", - ue->Mod_id,ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even[0],ue->dlsch_ra[eNB_id]); - #endif - } - } else if( (dci_alloc_rx[i].rnti == ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti) && - (dci_alloc_rx[i].format == format0)) { - - #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d: Found rnti %x, format 0, dci_cnt %d\n", - ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].rnti,i); - #endif - - ue->ulsch_no_allocation_counter[eNB_id] = 0; - //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); - - if ((ue->UE_mode[eNB_id] > PRACH) && - (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, - ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, - nr_tti_rx, - format0, - ue, - proc, - SI_RNTI, - 0, - P_RNTI, - CBA_RNTI, - eNB_id, - 0)==0)) { - #if T_TRACER - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - uint8_t harq_pid = subframe2harq_pid(frame_parms, - pdcch_alloc2ul_frame(frame_parms,proc->frame_rx,proc->nr_tti_rx), - pdcch_alloc2ul_subframe(frame_parms,proc->nr_tti_rx)); - - T(T_UE_PHY_ULSCH_UE_DCI, T_INT(eNB_id), T_INT(proc->frame_rx%1024), T_INT(proc->nr_tti_rx), T_INT(ue->Mod_id), - T_INT(dci_alloc_rx[i].rnti), T_INT(harq_pid), - T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs), - T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->round), - T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb), - T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb), - T_INT(ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS)); - #endif - #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE ULSCH C_RNTI format 0 (nr_tti_rx %d)\n",ue->Mod_id,nr_tti_rx); - #endif - - } - } else if( (dci_alloc_rx[i].rnti == ue->ulsch[eNB_id]->cba_rnti[0]) && - (dci_alloc_rx[i].format == format0)) { - // UE could belong to more than one CBA group - // ue->Mod_id%ue->ulsch[eNB_id]->num_active_cba_groups] - #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][PUSCH] Frame %d nr_tti_rx %d: Found cba rnti %x, format 0, dci_cnt %d\n", - ue->Mod_id,frame_rx,nr_tti_rx,dci_alloc_rx[i].rnti,i); - - if (((frame_rx%100) == 0) || (frame_rx < 20)) - dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); - - #endif - - ue->ulsch_no_allocation_counter[eNB_id] = 0; - //dump_dci(&ue->frame_parms,&dci_alloc_rx[i]); - - if ((ue->UE_mode[eNB_id] > PRACH) && - (generate_ue_ulsch_params_from_dci((void *)&dci_alloc_rx[i].dci_pdu, - ue->ulsch[eNB_id]->cba_rnti[0], - nr_tti_rx, - format0, - ue, - proc, - SI_RNTI, - 0, - P_RNTI, - CBA_RNTI, - eNB_id, - 0)==0)) { - - #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Generate UE ULSCH CBA_RNTI format 0 (nr_tti_rx %d)\n",ue->Mod_id,nr_tti_rx); - #endif - ue->ulsch[eNB_id]->num_cba_dci[(nr_tti_rx+4)%10]++; - } - } - - else { - #ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] frame %d, nr_tti_rx %d: received DCI %d with RNTI=%x (C-RNTI:%x, CBA_RNTI %x) and format %d!\n",ue->Mod_id,frame_rx,nr_tti_rx,i,dci_alloc_rx[i].rnti, - ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->crnti, - ue->ulsch[eNB_id]->cba_rnti[0], - dci_alloc_rx[i].format); - - // dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); - #endif - }*/ - - } // end for loop dci_cnt -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_rx_pdcch_stats); -#endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); - - // } // end if do_pdcch_monitoring_current_slot - } // end for loop nb_searchspace_active - return(0); -} - - - -#endif - - -#if 0 -void copy_harq_proc_struct(NR_DL_UE_HARQ_t *harq_processes_dest, NR_DL_UE_HARQ_t *current_harq_processes) -{ - - harq_processes_dest->B = current_harq_processes->B ; - harq_processes_dest->C = current_harq_processes->C ; - harq_processes_dest->DCINdi = current_harq_processes->DCINdi ; - harq_processes_dest->F = current_harq_processes->F ; - harq_processes_dest->G = current_harq_processes->G ; - harq_processes_dest->K = current_harq_processes->K ; - harq_processes_dest->Nl = current_harq_processes->Nl ; - harq_processes_dest->Qm = current_harq_processes->Qm ; - harq_processes_dest->TBS = current_harq_processes->TBS ; - harq_processes_dest->b = current_harq_processes->b ; - harq_processes_dest->codeword = current_harq_processes->codeword ; - harq_processes_dest->delta_PUCCH = current_harq_processes->delta_PUCCH ; - harq_processes_dest->dl_power_off = current_harq_processes->dl_power_off ; - harq_processes_dest->first_tx = current_harq_processes->first_tx ; - harq_processes_dest->mcs = current_harq_processes->mcs ; - harq_processes_dest->mcs_table = current_harq_processes->mcs_table ; - harq_processes_dest->mimo_mode = current_harq_processes->mimo_mode ; - harq_processes_dest->nb_rb = current_harq_processes->nb_rb ; - harq_processes_dest->pmi_alloc = current_harq_processes->pmi_alloc ; - harq_processes_dest->rb_alloc_even[0] = current_harq_processes->rb_alloc_even[0] ; - harq_processes_dest->rb_alloc_even[1] = current_harq_processes->rb_alloc_even[1] ; - harq_processes_dest->rb_alloc_even[2] = current_harq_processes->rb_alloc_even[2] ; - harq_processes_dest->rb_alloc_even[3] = current_harq_processes->rb_alloc_even[3] ; - harq_processes_dest->rb_alloc_odd[0] = current_harq_processes->rb_alloc_odd[0] ; - harq_processes_dest->rb_alloc_odd[1] = current_harq_processes->rb_alloc_odd[1] ; - harq_processes_dest->rb_alloc_odd[2] = current_harq_processes->rb_alloc_odd[2] ; - harq_processes_dest->rb_alloc_odd[3] = current_harq_processes->rb_alloc_odd[3] ; - harq_processes_dest->round = current_harq_processes->round ; - harq_processes_dest->rvidx = current_harq_processes->rvidx ; - harq_processes_dest->status = current_harq_processes->status ; - harq_processes_dest->vrb_type = current_harq_processes->vrb_type ; - -} -#endif - -/*void copy_ack_struct(nr_harq_status_t *harq_ack_dest, nr_harq_status_t *current_harq_ack) - { - memcpy(harq_ack_dest, current_harq_ack, sizeof(nr_harq_status_t)); - }*/ - -void nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_id, PDSCH_t pdsch, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1) { - - int nr_tti_rx = proc->nr_tti_rx; + int frame_rx = proc->frame_rx; + int nr_slot_rx = proc->nr_slot_rx; int m; - int i_mod,eNB_id_i,dual_stream_UE; + int i_mod,gNB_id_i,dual_stream_UE; int first_symbol_flag=0; if (!dlsch0) - return; + return 0; if (dlsch0->active == 0) - return; + return 0; if (!dlsch1) { int harq_pid = dlsch0->current_harq_pid; - uint16_t BWPStart = dlsch0->harq_processes[harq_pid]->BWPStart; - // uint16_t BWPSize = dlsch0->harq_processes[harq_pid]->BWPSize; - uint16_t pdsch_start_rb = dlsch0->harq_processes[harq_pid]->start_rb; - uint16_t pdsch_nb_rb = dlsch0->harq_processes[harq_pid]->nb_rb; - uint16_t s0 = dlsch0->harq_processes[harq_pid]->start_symbol; - uint16_t s1 = dlsch0->harq_processes[harq_pid]->nb_symbols; + NR_DL_UE_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid]; + uint16_t BWPStart = dlsch0_harq->BWPStart; + uint16_t pdsch_start_rb = dlsch0_harq->start_rb; + uint16_t pdsch_nb_rb = dlsch0_harq->nb_rb; + uint16_t s0 = dlsch0_harq->start_symbol; + uint16_t s1 = dlsch0_harq->nb_symbols; + bool is_SI = dlsch0->rnti_type == _SI_RNTI_; - LOG_D(PHY,"[UE %d] PDSCH type %d active in nr_tti_rx %d, harq_pid %d, rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x\n",ue->Mod_id,pdsch,nr_tti_rx,harq_pid,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->harq_processes[harq_pid]->dlDmrsSymbPos); + LOG_D(PHY,"[UE %d] PDSCH type %d active in nr_slot_rx %d, harq_pid %d (%d), rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x\n", + ue->Mod_id,pdsch,nr_slot_rx,harq_pid,dlsch0_harq->status,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0_harq->dlDmrsSymbPos); - // do channel estimation for first DMRS only - for (m = s0; m < 3; m++) { - if (((1<harq_processes[harq_pid]->dlDmrsSymbPos) > 0) { - nr_pdsch_channel_estimation(ue, - 0 /*eNB_id*/, - nr_tti_rx, - 0 /*p*/, - m, - ue->frame_parms.first_carrier_offset+(BWPStart + pdsch_start_rb)*12, - pdsch_nb_rb); - LOG_D(PHY,"Channel Estimation in symbol %d\n",m); - break; + for (m = s0; m < (s0 +s1); m++) { + if (dlsch0_harq->dlDmrsSymbPos & (1 << m)) { + for (uint8_t aatx=0; aatxNl; aatx++) {//for MIMO Config: it shall loop over no_layers + nr_pdsch_channel_estimation(ue, + proc, + gNB_id, + is_SI, + nr_slot_rx, + aatx /*p*/, + m, + BWPStart, + ue->frame_parms.first_carrier_offset+(BWPStart + pdsch_start_rb)*12, + pdsch_nb_rb); + LOG_D(PHY,"PDSCH Channel estimation gNB id %d, PDSCH antenna port %d, slot %d, symbol %d\n",0,aatx,nr_slot_rx,m); +#if 0 + ///LOG_M: the channel estimation + int nr_frame_rx = proc->frame_rx; + char filename[100]; + for (uint8_t aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { + sprintf(filename,"PDSCH_CHANNEL_frame%d_slot%d_sym%d_port%d_rx%d.m", nr_frame_rx, nr_slot_rx, m, aatx,aarx); + int **dl_ch_estimates = ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates; + LOG_M(filename,"channel_F",&dl_ch_estimates[aatx*ue->frame_parms.nb_antennas_rx+aarx][ue->frame_parms.ofdm_symbol_size*m],ue->frame_parms.ofdm_symbol_size, 1, 1); + } +#endif + } } } + + uint16_t first_symbol_with_data = s0; + uint32_t dmrs_data_re; + + if (dlsch0_harq->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) + dmrs_data_re = 12 - 6 * dlsch0_harq->n_dmrs_cdm_groups; + else + dmrs_data_re = 12 - 4 * dlsch0_harq->n_dmrs_cdm_groups; + + while ((dmrs_data_re == 0) && (dlsch0_harq->dlDmrsSymbPos & (1 << first_symbol_with_data))) { + first_symbol_with_data++; + } + for (m = s0; m < (s1 + s0); m++) { dual_stream_UE = 0; - eNB_id_i = eNB_id+1; + gNB_id_i = gNB_id+1; i_mod = 0; - - if ((m==s0) && (m<3)) - first_symbol_flag = 1; + if (( m==first_symbol_with_data ) && (m<4)) + first_symbol_flag = 1; else - first_symbol_flag = 0; -#if UE_TIMING_TRACE + first_symbol_flag = 0; + uint8_t slot = 0; if(m >= ue->frame_parms.symbols_per_slot>>1) slot = 1; - start_meas(&ue->dlsch_llr_stats_parallelization[ue->current_thread_id[nr_tti_rx]][slot]); -#endif - // process DLSCH received in first slot - // skip DMRS symbols (will have to check later if PDSCH/DMRS are multiplexed - if (((1<harq_processes[harq_pid]->dlDmrsSymbPos) == 0) - nr_rx_pdsch(ue, - pdsch, - eNB_id, - eNB_id_i, - proc->frame_rx, - nr_tti_rx, // nr_tti_rx, - m, - first_symbol_flag, - dual_stream_UE, - i_mod, - dlsch0->current_harq_pid); - else { // This is to adjust the llr offset in the case of skipping over a dmrs symbol (i.e. in case of no PDSCH REs in DMRS) - if (pdsch == RA_PDSCH) ue->pdsch_vars_ra[eNB_id]->llr_offset[m]=ue->pdsch_vars_ra[eNB_id]->llr_offset[m-1]; - else if (pdsch == PDSCH) nr_rx_pdsch(ue, - pdsch, - eNB_id, - eNB_id_i, - proc->frame_rx, - nr_tti_rx, // nr_tti_rx, - m, - first_symbol_flag, - dual_stream_UE, - i_mod, - dlsch0->current_harq_pid); - else AssertFatal(1==0,"not RA_PDSCH or PDSCH\n"); - } - if (pdsch == PDSCH) LOG_D(PHY,"Done processing symbol %d : llr_offset %d\n",m,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->llr_offset[m]); -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_llr_stats_parallelization[ue->current_thread_id[nr_tti_rx]][slot]); -#if DISABLE_LOG_X - printf("[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",proc->frame_rx,nr_tti_rx,m,ue->dlsch_llr_stats_parallelization[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",proc->frame_rx,nr_tti_rx,m,ue->dlsch_llr_stats_parallelization[ue->current_thread_id[nr_tti_rx]][slot].p_time/(cpuf*1000.0)); -#endif -#endif + start_meas(&ue->dlsch_llr_stats_parallelization[proc->thread_id][slot]); + // process DLSCH received symbols in the slot + // symbol by symbol processing (if data/DMRS are multiplexed is checked inside the function) + if (pdsch == PDSCH || pdsch == SI_PDSCH || pdsch == RA_PDSCH) { + if (nr_rx_pdsch(ue, + proc, + pdsch, + gNB_id, + gNB_id_i, + frame_rx, + nr_slot_rx, + m, + first_symbol_flag, + dual_stream_UE, + i_mod, + harq_pid) < 0) + return -1; + } else AssertFatal(1==0,"Not RA_PDSCH, SI_PDSCH or PDSCH\n"); - if(first_symbol_flag) - { - proc->first_symbol_available = 1; - } + stop_meas(&ue->dlsch_llr_stats_parallelization[proc->thread_id][slot]); + LOG_D(PHY, "[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",frame_rx,nr_slot_rx,m,ue->dlsch_llr_stats_parallelization[proc->thread_id][slot].p_time/(cpuf*1000.0)); + + if(first_symbol_flag) { + proc->first_symbol_available = 1; + } } // CRNTI active } + return 0; } -// WIP fix: -// - time domain indication hardcoded to 0 for k2 offset -// - extend TS 38.213 ch 8.3 Msg3 PUSCH -// - b buffer -// - ulsch power offset -// - UE_mode == PUSCH case (should be handled by TA updates) -// - harq -// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures -void nr_process_rar(nr_downlink_indication_t *dl_info) { - - module_id_t module_id = dl_info->module_id; - int cc_id = dl_info->cc_id, frame_rx = dl_info->proc->frame_rx, nr_tti_rx = dl_info->proc->nr_tti_rx, ta_command, k2, delta; - uint8_t gNB_index = dl_info->gNB_index; // *rar; - //fapi_nr_dci_indication_t *dci_ind = dl_info->dci_ind; - PHY_VARS_NR_UE *ue = PHY_vars_UE_g[module_id][cc_id]; - NR_UE_DLSCH_t *dlsch0 = ue->dlsch_ra[gNB_index]; - UE_MODE_t UE_mode = ue->UE_mode[gNB_index]; - NR_PRACH_RESOURCES_t *prach_resources = ue->prach_resources[gNB_index]; - uint16_t slots_per_frame = ue->frame_parms.slots_per_frame; - - uint8_t mu_pusch = 1, sliv_S, sliv_L; - // definition table j Table 6.1.2.1.1-4 - uint8_t j = (mu_pusch==3)?3:(mu_pusch==2)?2:1; - uint8_t table_6_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PUSCH from TS 38.214 subclause 6.1.2.1.1 - {j, 0,14}, // row index 1 - {j, 0,12}, // row index 2 - {j, 0,10}, // row index 3 - {j, 2,10}, // row index 4 - {j, 4,10}, // row index 5 - {j, 4,8}, // row index 6 - {j, 4,6}, // row index 7 - {j+1,0,14}, // row index 8 - {j+1,0,12}, // row index 9 - {j+1,0,10}, // row index 10 - {j+2,0,14}, // row index 11 - {j+2,0,12}, // row index 12 - {j+2,0,10}, // row index 13 - {j, 8,6}, // row index 14 - {j+3,0,14}, // row index 15 - {j+3,0,10} // row index 16 - }; - - LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Received RAR mode %d\n", module_id, frame_rx, nr_tti_rx, UE_mode); - - if (ue->mac_enabled == 1) { - if ((UE_mode != PUSCH) && (prach_resources->Msg3 != NULL)) { - - LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Invoking MAC for RAR (current preamble %d)\n", module_id, frame_rx, nr_tti_rx, prach_resources->ra_PreambleIndex); - - ta_command = nr_ue_process_rar(ue->Mod_id, - cc_id, - frame_rx, - dlsch0->harq_processes[0]->b, - &ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][gNB_index]->pdcch_config[0].rnti, - prach_resources->ra_PreambleIndex, - dlsch0->harq_processes[0]->b); // alter the 'b' buffer so it contains only the selected RAR header and RAR payload - - if (ta_command != 0xffff) { - LOG_D(PHY,"[UE %d][RAPROC] Frame %d subframe %d Got Temporary C-RNTI %x and timing advance %d from RAR\n", - ue->Mod_id, - frame_rx, - nr_tti_rx, - ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][gNB_index]->pdcch_config[0].rnti, - ta_command); - - nr_process_timing_advance_rar(ue, dl_info->proc, ta_command); - - if (ue->mode != debug_prach) { - ue->ulsch_Msg3_active[gNB_index] = 1; - // TS 38.213 ch 8.3 Msg3 PUSCH - // PUSCH time domain resource allocation A for normal CP - // TS 38.214 ch 6.1.2.1.1 - k2 = table_6_1_2_1_1_2_time_dom_res_alloc_A[0][0]; - sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[0][1]; - sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[0][2]; - - switch (mu_pusch) { - case 0: - delta = 2; - break; - case 1: - delta = 3; - break; - case 2: - delta = 4; - break; - case 3: - delta = 6; - break; - } - - ue->Msg3_startSymbol[gNB_index] = sliv_S; - ue->Msg3_Length[gNB_index] = sliv_L; - ue->ulsch_Msg3_subframe[gNB_index] = (nr_tti_rx + k2 + delta) % slots_per_frame; - if (nr_tti_rx + k2 + delta > slots_per_frame){ - ue->ulsch_Msg3_frame[gNB_index] = (frame_rx + 1) % 1024; - } else { - ue->ulsch_Msg3_frame[gNB_index] = frame_rx; - } - - LOG_D(PHY,"[UE %d][RAPROC] Got Msg3_alloc Frame %d subframe %d: Msg3_frame %d, Msg3_subframe %d\n", - ue->Mod_id, - frame_rx, - nr_tti_rx, - ue->ulsch_Msg3_frame[gNB_index], - ue->ulsch_Msg3_subframe[gNB_index]); - // harq_pid = subframe2harq_pid(&ue->frame_parms, - // ue->ulsch_Msg3_frame[gNB_index], - // ue->ulsch_Msg3_subframe[gNB_index]); - // ue->ulsch[gNB_index]->harq_processes[harq_pid]->round = 0; - // ue->Msg3_timer[gNB_index] = 10; - // ue->ulsch[gNB_index].power_offset = 6; - // ue->ulsch_no_allocation_counter[gNB_index] = 0; - ue->UE_mode[gNB_index] = RA_RESPONSE; - } - } else { - LOG_W(PHY,"[UE %d][RAPROC] Received RAR preamble (%d) doesn't match !!!\n", ue->Mod_id, prach_resources->ra_PreambleIndex); - } - } - } else { - // rar = dlsch0->harq_processes[0]->b+1; - // ta_command = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); - // nr_process_timing_advance_rar(ue, dl_info->proc, ta_command); - } -} - -// if contention resolution fails, go back to UE mode PRACH -void nr_ra_failed(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index) { - - PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - ue->UE_mode[gNB_index] = PRACH; - - for (int i=0; i pdcch_vars[i][gNB_index]->pdcch_config[0].rnti = 0; - } - LOG_E(PHY,"[UE %d] [RAPROC] Random-access procedure fails, going back to PRACH\n", Mod_id); -} - -void nr_ra_succeeded(uint8_t Mod_id, - uint8_t CC_id, - uint8_t gNB_index){ - LOG_I(PHY,"[UE %d][RAPROC] RA procedure succeeded. UE set to PUSCH mode\n", Mod_id); - PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - ue->ulsch_Msg3_active[gNB_index] = 0; - ue->UE_mode[gNB_index] = PUSCH; -} - -void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - int eNB_id, - PDSCH_t pdsch, - NR_UE_DLSCH_t *dlsch0, - NR_UE_DLSCH_t *dlsch1, - int *dlsch_errors, - runmode_t mode) { - - int harq_pid = dlsch0->current_harq_pid; - int frame_rx = proc->frame_rx; - int nr_tti_rx = proc->nr_tti_rx; - int ret=0, ret1=0; - NR_UE_PDSCH *pdsch_vars; - uint8_t is_cw0_active = 0; - uint8_t is_cw1_active = 0; - uint8_t dmrs_type, nb_re_dmrs; - uint16_t length_dmrs = 1; - uint16_t nb_symb_sch = 9; - nr_downlink_indication_t dl_indication; - fapi_nr_rx_indication_t rx_ind; - // params for UL time alignment procedure - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[eNB_id]; - uint16_t slots_per_frame = ue->frame_parms.slots_per_frame; - uint16_t slots_per_subframe = ue->frame_parms.slots_per_subframe; - uint8_t numerology = ue->frame_parms.numerology_index, mapping_type_ul, mapping_type_dl; - int ul_tx_timing_adjustment, N_TA_max, factor_mu, N_t_1, N_t_2, N_1, N_2, d_1_1 = 0, d_2_1, d; - uint8_t d_2_2 = 0;// set to 0 because there is only 1 BWP - // TODO this should corresponds to the switching time as defined in - // TS 38.133 - uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; - uint16_t nb_prefix_samples = ue->frame_parms.nb_prefix_samples; - uint32_t t_subframe = 1; // subframe duration of 1 msec - uint16_t bw_scaling, start_symbol; - float tc_factor; +bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int gNB_id, + PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + int *dlsch_errors, + uint8_t dlsch_parallel) { if (dlsch0==NULL) AssertFatal(0,"dlsch0 should be defined at this level \n"); + bool dec = false; + int harq_pid = dlsch0->current_harq_pid; + int frame_rx = proc->frame_rx; + int nr_slot_rx = proc->nr_slot_rx; + uint32_t ret = UINT32_MAX, ret1 = UINT32_MAX; + NR_UE_PDSCH *pdsch_vars; + uint16_t dmrs_len = get_num_dmrs(dlsch0->harq_processes[dlsch0->current_harq_pid]->dlDmrsSymbPos); + nr_downlink_indication_t dl_indication; + fapi_nr_rx_indication_t rx_ind; + uint16_t number_pdus = 1; + // params for UL time alignment procedure + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id]; - is_cw0_active = dlsch0->harq_processes[harq_pid]->status; - nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; - start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; - dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; + uint8_t is_cw0_active = dlsch0->harq_processes[harq_pid]->status; + uint16_t nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; + uint16_t start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; + uint8_t dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; + + uint8_t nb_re_dmrs; if (dmrs_type==NFAPI_NR_DMRS_TYPE1) { nb_re_dmrs = 6*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; } @@ -3323,11 +891,12 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, nb_re_dmrs = 4*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; } + uint8_t is_cw1_active = 0; if(dlsch1) is_cw1_active = dlsch1->harq_processes[harq_pid]->status; - LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx%1024, nr_tti_rx, harq_pid, is_cw0_active); - LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx%1024, nr_tti_rx, harq_pid, is_cw1_active); + LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw0_active); + LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw1_active); if(is_cw0_active && is_cw1_active) { @@ -3341,26 +910,20 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, if (1) { switch (pdsch) { case SI_PDSCH: - pdsch_vars = ue->pdsch_vars_SI[eNB_id]; - break; case RA_PDSCH: - pdsch_vars = ue->pdsch_vars_ra[eNB_id]; - break; case P_PDSCH: - pdsch_vars = ue->pdsch_vars_p[eNB_id]; - break; case PDSCH: - pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; + pdsch_vars = ue->pdsch_vars[proc->thread_id][gNB_id]; break; case PMCH: case PDSCH1: LOG_E(PHY,"Illegal PDSCH %d for ue_pdsch_procedures\n",pdsch); pdsch_vars = NULL; - return; + return false; break; default: pdsch_vars = NULL; - return; + return false; break; } @@ -3368,26 +931,28 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, *dlsch_errors=0; if (pdsch == RA_PDSCH) { - if (ue->prach_resources[eNB_id]!=NULL) - dlsch0->rnti = ue->prach_resources[eNB_id]->ra_RNTI; + if (ue->prach_resources[gNB_id]!=NULL) + dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI; else { - LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_tti_rx); - //mac_xface->macphy_exit("prach_resources is NULL"); - return; + LOG_E(PHY,"[UE %d] Frame %d, nr_slot_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_slot_rx); + //mac_xface->macphy_exit("prach_resources is NULL"); + return false; } } + // exit dlsch procedures as there are no active dlsch + if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) + return false; // start ldpc decode for CW 0 dlsch0->harq_processes[harq_pid]->G = nr_get_G(dlsch0->harq_processes[harq_pid]->nb_rb, nb_symb_sch, nb_re_dmrs, - length_dmrs, + dmrs_len, dlsch0->harq_processes[harq_pid]->Qm, dlsch0->harq_processes[harq_pid]->Nl); -#if UE_TIMING_TRACE + start_meas(&ue->dlsch_unscrambling_stats); -#endif nr_dlsch_unscrambling(pdsch_vars->llr[0], dlsch0->harq_processes[harq_pid]->G, 0, @@ -3395,317 +960,279 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, dlsch0->rnti); -#if UE_TIMING_TRACE stop_meas(&ue->dlsch_unscrambling_stats); -#endif + #if 0 - LOG_I(PHY," ------ start ldpc decoder for AbsSubframe %d.%d / %d ------ \n", frame_rx, nr_tti_rx, harq_pid); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->nb_rb); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> rb_alloc_even %x \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->rb_alloc_even); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Qm %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Qm); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Nl); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->harq_processes[harq_pid]->G); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch0->Kmimo); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_tti_rx, harq_pid, ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols); + LOG_I(PHY," ------ start ldpc decoder for AbsSubframe %d.%d / %d ------ \n", frame_rx, nr_slot_rx, harq_pid); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->nb_rb); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> rb_alloc_even %x \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->rb_alloc_even); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Qm %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Qm); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Nl); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->G); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->Kmimo); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][gNB_id]->num_pdcch_symbols); #endif -#if UE_TIMING_TRACE - start_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]]); -#endif -#ifdef UE_DLSCH_PARALLELISATION - ret = nr_dlsch_decoding_mthread(ue, - proc, - eNB_id, - pdsch_vars->llr[0], - &ue->frame_parms, - dlsch0, - dlsch0->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_tti_rx, - harq_pid, - pdsch==PDSCH?1:0, - dlsch0->harq_processes[harq_pid]->TBS>256?1:0); - LOG_T(PHY,"UE_DLSCH_PARALLELISATION is defined, ret = %d\n", ret); -#else - ret = nr_dlsch_decoding(ue, - pdsch_vars->llr[0], - &ue->frame_parms, - dlsch0, - dlsch0->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_tti_rx, - harq_pid, - pdsch==PDSCH?1:0, - dlsch0->harq_processes[harq_pid]->TBS>256?1:0); - LOG_T(PHY,"UE_DLSCH_PARALLELISATION is NOT defined, ret = %d\n", ret); - //printf("start cW0 dlsch decoding\n"); -#endif + start_meas(&ue->dlsch_decoding_stats[proc->thread_id]); -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]]); -#if DISABLE_LOG_X - printf(" --> Unscrambling for CW0 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - printf("AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n", - frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); -#else - LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - LOG_I(PHY, "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n", - frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); -#endif + ret = nr_dlsch_decoding(ue, + proc, + gNB_id, + pdsch_vars->llr[0], + &ue->frame_parms, + dlsch0, + dlsch0->harq_processes[harq_pid], + frame_rx, + nb_symb_sch, + nr_slot_rx, + harq_pid, + pdsch==PDSCH?1:0, + dlsch0->harq_processes[harq_pid]->TBS>256?1:0); + if( dlsch_parallel) { + LOG_T(PHY,"dlsch decoding is parallelized, ret = %d\n", ret); + } + else { + LOG_T(PHY,"Sequential dlsch decoding , ret = %d\n", ret); + } -#endif - if(is_cw1_active) - { - // start ldpc decode for CW 1 - dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb, - nb_symb_sch, - nb_re_dmrs, - length_dmrs, - dlsch1->harq_processes[harq_pid]->Qm, - dlsch1->harq_processes[harq_pid]->Nl); -#if UE_TIMING_TRACE - start_meas(&ue->dlsch_unscrambling_stats); -#endif - nr_dlsch_unscrambling(pdsch_vars->llr[1], - dlsch1->harq_processes[harq_pid]->G, - 0, - ue->frame_parms.Nid_cell, - dlsch1->rnti); -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_unscrambling_stats); -#endif + if(retmax_ldpc_iterations+1) + dec = true; + + switch (pdsch) { + case RA_PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, NULL, number_pdus); + ue->UE_mode[gNB_id] = RA_RESPONSE; + break; + case PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, gNB_id, ue, dlsch0, NULL, number_pdus); + break; + case SI_PDSCH: + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, gNB_id, ue, dlsch0, NULL, number_pdus); + break; + default: + break; + } + + LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8); + + + + + stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); + LOG_D(PHY, " --> Unscrambling for CW0 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + LOG_D(PHY, "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + + if(is_cw1_active) { + // start ldpc decode for CW 1 + dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb, + nb_symb_sch, + nb_re_dmrs, + dmrs_len, + dlsch1->harq_processes[harq_pid]->Qm, + dlsch1->harq_processes[harq_pid]->Nl); + start_meas(&ue->dlsch_unscrambling_stats); + nr_dlsch_unscrambling(pdsch_vars->llr[1], + dlsch1->harq_processes[harq_pid]->G, + 0, + ue->frame_parms.Nid_cell, + dlsch1->rnti); + stop_meas(&ue->dlsch_unscrambling_stats); #if 0 - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->nb_rb); - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> rb_alloc_even %x \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->rb_alloc_even); - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Qm %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Qm); - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Nl); - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->harq_processes[harq_pid]->G); - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_tti_rx, harq_pid, dlsch1->Kmimo); - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_tti_rx, harq_pid, ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->num_pdcch_symbols); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->nb_rb); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> rb_alloc_even %x \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->rb_alloc_even); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Qm %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Qm); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Nl); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->G); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->Kmimo); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][gNB_id]->num_pdcch_symbols); #endif -#if UE_TIMING_TRACE - start_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]]); -#endif + start_meas(&ue->dlsch_decoding_stats[proc->thread_id]); -#ifdef UE_DLSCH_PARALLELISATION - ret1 = nr_dlsch_decoding_mthread(ue, - proc, - eNB_id, - pdsch_vars->llr[1], - &ue->frame_parms, - dlsch1, - dlsch1->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_tti_rx, - harq_pid, - pdsch==PDSCH?1:0, - dlsch1->harq_processes[harq_pid]->TBS>256?1:0); - LOG_T(PHY,"UE_DLSCH_PARALLELISATION is defined, ret1 = %d\n", ret1); -#else - ret1 = nr_dlsch_decoding(ue, - pdsch_vars->llr[1], - &ue->frame_parms, - dlsch1, - dlsch1->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_tti_rx, - harq_pid, - pdsch==PDSCH?1:0,//proc->decoder_switch, - dlsch1->harq_processes[harq_pid]->TBS>256?1:0); - LOG_T(PHY,"UE_DLSCH_PARALLELISATION is NOT defined, ret1 = %d\n", ret1); - printf("start cw1 dlsch decoding\n"); -#endif -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]]); -#if DISABLE_LOG_X - printf(" --> Unscrambling for CW1 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - printf("AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); -#else - LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); -#endif + ret1 = nr_dlsch_decoding(ue, + proc, + gNB_id, + pdsch_vars->llr[1], + &ue->frame_parms, + dlsch1, + dlsch1->harq_processes[harq_pid], + frame_rx, + nb_symb_sch, + nr_slot_rx, + harq_pid, + pdsch==PDSCH?1:0,//proc->decoder_switch, + dlsch1->harq_processes[harq_pid]->TBS>256?1:0); + if(dlsch_parallel) { + LOG_T(PHY,"CW dlsch decoding is parallelized, ret1 = %d\n", ret1); + } + else { -#endif - LOG_I(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_tti_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[nr_tti_rx]].p_time)/(cpuf*1000.0)); - - LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch1->harq_processes[harq_pid]->TBS); + LOG_T(PHY,"CWW sequential dlsch decoding, ret1 = %d\n", ret1); } - LOG_D(PHY," ------ end ldpc decoder for AbsSubframe %d.%d ------ \n", frame_rx, nr_tti_rx); - LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS); - - if(retmax_ldpc_iterations+1){ - // fill dl_indication message - dl_indication.module_id = ue->Mod_id; - dl_indication.cc_id = ue->CC_id; - dl_indication.gNB_index = eNB_id; - dl_indication.frame = frame_rx; - dl_indication.slot = nr_tti_rx; - dl_indication.rx_ind = &rx_ind; // hang on rx_ind instance - dl_indication.proc=proc; + stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); - //dl_indication.rx_ind->number_pdus - switch (pdsch) { - case RA_PDSCH: - rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_RAR; - break; - case PDSCH: - rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_DLSCH; - break; - default: - break; - } + LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + LOG_D(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); - rx_ind.rx_indication_body[0].pdsch_pdu.pdu = dlsch0->harq_processes[harq_pid]->b; - rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length = dlsch0->harq_processes[harq_pid]->TBS>>3; - LOG_D(PHY, "PDU length in bits: %d, in bytes: %d \n", dlsch0->harq_processes[harq_pid]->TBS, rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length); - rx_ind.number_pdus = 1; + LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch1->harq_processes[harq_pid]->TBS); + } - //ue->dl_indication.rx_ind = &dlsch1->harq_processes[harq_pid]->b; //no data, only dci for now - dl_indication.dci_ind = NULL; //&ue->dci_ind; - // send to mac - if (ue->if_inst && ue->if_inst->dl_indication) - ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); + LOG_D(PHY," ------ end ldpc decoder for AbsSubframe %d.%d ------ decoded in %d \n", frame_rx, nr_slot_rx, ret); + + // send to mac + if (ue->if_inst && ue->if_inst->dl_indication) { + ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); + } + + if (ue->mac_enabled == 1) { // TODO: move this from PHY to MAC layer! + + /* Time Alignment procedure + // - UE processing capability 1 + // - Setting the TA update to be applied after the reception of the TA command + // - Timing adjustment computed according to TS 38.213 section 4.2 + // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are + // computed according to sections 5.3 and 6.4 of TS 38.214 */ + const int numerology = ue->frame_parms.numerology_index; + const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; + const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples; + const int samples_per_subframe = ue->frame_parms.samples_per_subframe; + const int slots_per_frame = ue->frame_parms.slots_per_frame; + const int slots_per_subframe = ue->frame_parms.slots_per_subframe; + + const double tc_factor = 1.0 / samples_per_subframe; + const uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size); + + const int Ta_max = 3846; // Max value of 12 bits TA Command + const double N_TA_max = Ta_max * bw_scaling * tc_factor; + + NR_UE_MAC_INST_t *mac = get_mac_inst(0); + + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL; + if (mac->ULbwp[0] && + mac->ULbwp[0]->bwp_Dedicated && + mac->ULbwp[0]->bwp_Dedicated->pusch_Config && + mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup && + mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList->choice.setup; } + else if (mac->ULbwp[0] && + mac->ULbwp[0]->bwp_Common && + mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon && + mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup && + mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + } + else if (mac->scc_SIB && + mac->scc_SIB->uplinkConfigCommon && + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon && + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup && + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + } + long mapping_type_ul = pusch_TimeDomainAllocationList ? pusch_TimeDomainAllocationList->list.array[0]->mappingType : NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA; - // TODO CRC check for CW0 + NR_PDSCH_Config_t *pdsch_Config = (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup) ? mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup : NULL; + NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = NULL; + if (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList) + pdsch_TimeDomainAllocationList = pdsch_Config->pdsch_TimeDomainAllocationList->choice.setup; + else if (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList) + pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + else if (mac->scc_SIB && mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup) + pdsch_TimeDomainAllocationList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + long mapping_type_dl = pdsch_TimeDomainAllocationList ? pdsch_TimeDomainAllocationList->list.array[0]->mappingType : NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - // Check CRC for CW 0 - /*if (ret == (1+dlsch0->max_turbo_iterations)) { - *dlsch_errors=*dlsch_errors+1; - if(dlsch0->rnti != 0xffff){ - LOG_D(PHY,"[UE %d][PDSCH %x/%d] AbsSubframe %d.%d : DLSCH CW0 in error (rv %d,round %d, mcs %d,TBS %d)\n", - ue->Mod_id,dlsch0->rnti, - harq_pid,frame_rx,subframe_rx, - dlsch0->harq_processes[harq_pid]->rvidx, - dlsch0->harq_processes[harq_pid]->round, - dlsch0->harq_processes[harq_pid]->mcs, - dlsch0->harq_processes[harq_pid]->TBS); - } - } else { - if(dlsch0->rnti != 0xffff){ - LOG_D(PHY,"[UE %d][PDSCH %x/%d] AbsSubframe %d.%d : Received DLSCH CW0 (rv %d,round %d, mcs %d,TBS %d)\n", - ue->Mod_id,dlsch0->rnti, - harq_pid,frame_rx,subframe_rx, - dlsch0->harq_processes[harq_pid]->rvidx, - dlsch0->harq_processes[harq_pid]->round, - dlsch0->harq_processes[harq_pid]->mcs, - dlsch0->harq_processes[harq_pid]->TBS); - } - if ( LOG_DEBUGFLAG(DEBUG_UE_PHYPROC)){ - int j; - LOG_D(PHY,"dlsch harq_pid %d (rx): \n",dlsch0->current_harq_pid); - - for (j=0; jharq_processes[dlsch0->current_harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",dlsch0->harq_processes[dlsch0->current_harq_pid]->b[j]); - LOG_T(PHY,"\n"); - }*/ - - if (ue->mac_enabled == 1) { - - // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size - switch (ue->frame_parms.N_RB_DL) { - case 32: bw_scaling = 4; break; - case 66: bw_scaling = 8; break; - case 106: bw_scaling = 16; break; - case 217: bw_scaling = 32; break; - case 245: bw_scaling = 32; break; - case 273: bw_scaling = 32; break; - default: abort(); - } - - /* Time Alignment procedure - // - UE processing capability 1 - // - Setting the TA update to be applied after the reception of the TA command - // - Timing adjustment computed according to TS 38.213 section 4.2 - // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are - // computed according to sections 5.3 and 6.4 of TS 38.214 */ - factor_mu = 1 << numerology; - N_TA_max = 3846 * bw_scaling / factor_mu; - - /* PDSCH decoding time N_1 for processing capability 1 */ - if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos0) - N_1 = pdsch_N_1_capability_1[numerology][1]; - else if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos1 || ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == 2) // TODO set to pdsch_dmrs_pos2 when available - N_1 = pdsch_N_1_capability_1[numerology][2]; + NR_DMRS_DownlinkConfig_t *NR_DMRS_dlconfig = NULL; + if (pdsch_Config) { + if (mapping_type_dl == NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA) + NR_DMRS_dlconfig = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; else - N_1 = pdsch_N_1_capability_1[numerology][3]; + NR_DMRS_dlconfig = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup; + } - /* PUSCH preapration time N_2 for processing capability 1 */ - N_2 = pusch_N_2_timing_capability_1[numerology][1]; - mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType; - mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType; + pdsch_dmrs_AdditionalPosition_t add_pos_dl = pdsch_dmrs_pos2; + if (NR_DMRS_dlconfig && NR_DMRS_dlconfig->dmrs_AdditionalPosition) + add_pos_dl = *NR_DMRS_dlconfig->dmrs_AdditionalPosition; - /* d_1_1 depending on the number of PDSCH symbols allocated */ - d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH - if (mapping_type_dl == typeA) - if (nb_symb_sch + start_symbol < 7) + /* PDSCH decoding time N_1 for processing capability 1 */ + int N_1; + + if (add_pos_dl == pdsch_dmrs_pos0) + N_1 = pdsch_N_1_capability_1[numerology][1]; + else if (add_pos_dl == pdsch_dmrs_pos1 || add_pos_dl == pdsch_dmrs_pos2) + N_1 = pdsch_N_1_capability_1[numerology][2]; + else + N_1 = pdsch_N_1_capability_1[numerology][3]; + + /* PUSCH preapration time N_2 for processing capability 1 */ + const int N_2 = pusch_N_2_timing_capability_1[numerology][1]; + + /* d_1_1 depending on the number of PDSCH symbols allocated */ + const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH + int d_1_1 = 0; + if (mapping_type_dl == NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA) + if (nb_symb_sch + start_symbol < 7) d_1_1 = 7 - (nb_symb_sch + start_symbol); - else - d_1_1 = 0; - else // mapping type B - switch (nb_symb_sch){ - case 7: d_1_1 = 0; break; - case 4: d_1_1 = 3; break; - case 2: d_1_1 = 3 + d; break; - default: break; - } - - /* d_2_1 */ - if (mapping_type_ul == typeB && start_symbol != 0) - d_2_1 = 0; else - d_2_1 = 1; - - /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time - // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */ - N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) / factor_mu; - N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) / factor_mu; - if (N_t_2 < d_2_2) N_t_2 = d_2_2; - - /* Time alignment procedure */ - // N_t_1 + N_t_2 + N_TA_max is in unit of Ts, therefore must be converted to Tc - // N_t_1 + N_t_2 + N_TA_max must be in msec - tc_factor = 64 * 0.509 * 10e-7; - ul_tx_timing_adjustment = 1 + ceil(slots_per_subframe*((N_t_1 + N_t_2 + N_TA_max)*tc_factor + 0.5)/t_subframe); - - if (ul_time_alignment->apply_ta == 1){ - ul_time_alignment->ta_slot = (nr_tti_rx + ul_tx_timing_adjustment) % slots_per_frame; - if (nr_tti_rx + ul_tx_timing_adjustment > slots_per_frame){ - ul_time_alignment->ta_frame = (frame_rx + 1) % 1024; - } else { - ul_time_alignment->ta_frame = frame_rx; - } - // reset TA flag - ul_time_alignment->apply_ta = 0; - LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", frame_rx, nr_tti_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); + d_1_1 = 0; + else // mapping type B + switch (nb_symb_sch){ + case 7: d_1_1 = 0; break; + case 4: d_1_1 = 3; break; + case 2: d_1_1 = 3 + d; break; + default: break; } + + /* d_2_1 */ + int d_2_1; + if (mapping_type_ul == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB && start_symbol != 0) + d_2_1 = 0; + else + d_2_1 = 1; + + /* d_2_2 */ + const double d_2_2 = 0.0; // set to 0 because there is only 1 BWP: TODO this should corresponds to the switching time as defined in TS 38.133 + + /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time + // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */ + double N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; + double N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; + if (N_t_2 < d_2_2) N_t_2 = d_2_2; + + /* Time alignment procedure */ + // N_t_1 + N_t_2 + N_TA_max must be in msec + const double t_subframe = 1.0; // subframe duration of 1 msec + const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe); + + if (ul_time_alignment->apply_ta == 1){ + ul_time_alignment->ta_slot = (nr_slot_rx + ul_tx_timing_adjustment) % slots_per_frame; + if (nr_slot_rx + ul_tx_timing_adjustment > slots_per_frame){ + ul_time_alignment->ta_frame = (frame_rx + 1) % 1024; + } else { + ul_time_alignment->ta_frame = frame_rx; + } + // reset TA flag + ul_time_alignment->apply_ta = 0; + LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", + frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); } - - /*ue->total_TBS[eNB_id] = ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; - ue->total_received_bits[eNB_id] = ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; - }*/ - - // TODO CRC check for CW1 - + } } + return dec; } @@ -3724,17 +1251,10 @@ void *UE_thread_slot1_dl_processing(void *arg) { UE_nr_rxtx_proc_t *proc = rtd->proc; PHY_VARS_NR_UE *ue = rtd->UE; - int frame_rx; - uint8_t nr_tti_rx; - uint8_t pilot0; uint8_t pilot1; - uint8_t slot1; - - uint8_t next_nr_tti_rx; - uint8_t next_subframe_slot0; proc->instance_cnt_slot1_dl_processing=-1; - proc->nr_tti_rx=proc->sub_frame_start; + proc->nr_slot_rx = proc->sub_frame_start * ue->frame_parms.slots_per_subframe; char threadname[256]; sprintf(threadname,"UE_thread_slot1_dl_processing_%d", proc->sub_frame_start); @@ -3743,9 +1263,9 @@ void *UE_thread_slot1_dl_processing(void *arg) { CPU_ZERO(&cpuset); if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.slot1_proc_one != -1 ) CPU_SET(threads.slot1_proc_one, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 ) + if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 ) CPU_SET(threads.slot1_proc_two, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 ) + if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 ) CPU_SET(threads.slot1_proc_three, &cpuset); init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, @@ -3765,21 +1285,15 @@ void *UE_thread_slot1_dl_processing(void *arg) { exit_fun("nothing to add"); } - /*for(int th_idx=0; th_idx< RX_NB_TH; th_idx++) - { - frame_rx = ue->proc.proc_rxtx[0].frame_rx; - nr_tti_rx = ue->proc.proc_rxtx[0].nr_tti_rx; - printf("AbsSubframe %d.%d execute dl slot1 processing \n", frame_rx, nr_tti_rx); - }*/ - frame_rx = proc->frame_rx; - nr_tti_rx = proc->nr_tti_rx; - next_nr_tti_rx = (1+nr_tti_rx)%10; - next_subframe_slot0 = next_nr_tti_rx<<1; + int frame_rx = proc->frame_rx; + uint8_t subframe_rx = proc->nr_slot_rx / ue->frame_parms.slots_per_subframe; + uint8_t next_subframe_rx = (1 + subframe_rx) % NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + uint8_t next_subframe_slot0 = next_subframe_rx * ue->frame_parms.slots_per_subframe; - slot1 = (nr_tti_rx<<1) + 1; - pilot0 = 0; + uint8_t slot1 = proc->nr_slot_rx + 1; + uint8_t pilot0 = 0; - //printf("AbsSubframe %d.%d execute dl slot1 processing \n", frame_rx, nr_tti_rx); + //printf("AbsSubframe %d.%d execute dl slot1 processing \n", frame_rx, nr_slot_rx); if (ue->frame_parms.Ncp == 0) { // normal prefix pilot1 = 4; @@ -3788,14 +1302,14 @@ void *UE_thread_slot1_dl_processing(void *arg) { } /**** Slot1 FE Processing ****/ -#if UE_TIMING_TRACE - start_meas(&ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1]); -#endif + + start_meas(&ue->ue_front_end_per_slot_stat[proc->thread_id][1]); + // I- start dl slot1 processing - // do first symbol of next downlink nr_tti_rx for channel estimation + // do first symbol of next downlink nr_slot_rx for channel estimation /* - // 1- perform FFT for pilot ofdm symbols first (ofdmSym0 next nr_tti_rx ofdmSym11) - if (nr_subframe_select(&ue->frame_parms,next_nr_tti_rx) != SF_UL) + // 1- perform FFT for pilot ofdm symbols first (ofdmSym0 next nr_slot_rx ofdmSym11) + if (nr_subframe_select(&ue->frame_parms,next_nr_slot_rx) != SF_UL) { front_end_fft(ue, pilot0, @@ -3815,26 +1329,23 @@ void *UE_thread_slot1_dl_processing(void *arg) { { //if( (l != pilot0) && (l != pilot1)) { -#if UE_TIMING_TRACE + start_meas(&ue->ofdm_demod_stats); -#endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot1,l); + //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_slot_rx,slot1,l); front_end_fft(ue, l, slot1, 0, 0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE stop_meas(&ue->ofdm_demod_stats); -#endif } } // for l=1..l2 - if (nr_subframe_select(&ue->frame_parms,next_nr_tti_rx) != SF_UL) + if (nr_subframe_select(&ue->frame_parms,next_nr_slot_rx) != SF_UL) { - //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_tti_rx,next_subframe_slot0,pilot0); + //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_slot_rx,next_subframe_slot0,pilot0); front_end_fft(ue, pilot0, next_subframe_slot0, @@ -3856,39 +1367,34 @@ void *UE_thread_slot1_dl_processing(void *arg) { } //printf("[slot1 dl processing] ChanEst symbol %d slot %d wait%d\n",l,slot1,wait); } - //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_tti_rx,slot1,l); + //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_slot_rx,slot1,l); front_end_chanEst(ue, l, slot1, 0); - ue_measurement_procedures(l-1,ue,proc,0,1+(nr_tti_rx<<1),0,ue->mode); + ue_measurement_procedures(l-1,ue,proc,0,slot1,0,ue->mode); } - //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_tti_rx,next_subframe_slot0,pilot0); + //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_slot_rx,next_subframe_slot0,pilot0); front_end_chanEst(ue, pilot0, next_subframe_slot0, 0); - if ( (nr_tti_rx == 0) && (ue->decode_MIB == 1)) + if ( (nr_slot_rx == 0) && (ue->decode_MIB == 1)) { ue_pbch_procedures(0,ue,proc,0); } proc->chan_est_slot1_available = 1; - //printf("Set available slot 1channelEst to 1 AbsSubframe %d.%d \n",frame_rx,nr_tti_rx); - //printf(" [slot1 dl processing] ==> FFT/CHanEst Done for AbsSubframe %d.%d \n", proc->frame_rx, proc->nr_tti_rx); + //printf("Set available slot 1channelEst to 1 AbsSubframe %d.%d \n",frame_rx,nr_slot_rx); + //printf(" [slot1 dl processing] ==> FFT/CHanEst Done for AbsSubframe %d.%d \n", proc->frame_rx, proc->nr_slot_rx); - //printf(" [slot1 dl processing] ==> Start LLR Comuptation slot1 for AbsSubframe %d.%d \n", proc->frame_rx, proc->nr_tti_rx); + //printf(" [slot1 dl processing] ==> Start LLR Comuptation slot1 for AbsSubframe %d.%d \n", proc->frame_rx, proc->nr_slot_rx); -#if UE_TIMING_TRACE - stop_meas(&ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1]); -#if DISABLE_LOG_X - printf("[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_tti_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1].p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_tti_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1].p_time/(cpuf*1000.0)); -#endif -#endif + + stop_meas(&ue->ue_front_end_per_slot_stat[proc->thread_id][1]); + LOG_D(PHY, "[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_slot_rx,ue->ue_front_end_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0)); //wait until pdcch is decoded @@ -3898,22 +1404,21 @@ void *UE_thread_slot1_dl_processing(void *arg) { usleep(1); wait++; } - //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait DCI %d\n",frame_rx,nr_tti_rx,wait); + //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait DCI %d\n",frame_rx,nr_slot_rx,wait); /**** Pdsch Procedure Slot1 ****/ // start slot1 thread for Pdsch Procedure (slot1) // do procedures for C-RNTI - //printf("AbsSubframe %d.%d Pdsch Procedure (slot1)\n",frame_rx,nr_tti_rx); + //printf("AbsSubframe %d.%d Pdsch Procedure (slot1)\n",frame_rx,nr_slot_rx); -#if UE_TIMING_TRACE - start_meas(&ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1]); -#endif + start_meas(&ue->pdsch_procedures_per_slot_stat[proc->thread_id][1]); + // start slave thread for Pdsch Procedure (slot1) // do procedures for C-RNTI - uint8_t eNB_id = 0; + uint8_t gNB_id = 0; - if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { + if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) { //wait until first ofdm symbol is processed //wait = 0; //while(proc->first_symbol_available == 0) @@ -3921,29 +1426,29 @@ void *UE_thread_slot1_dl_processing(void *arg) { // usleep(1); // wait++; //} - //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait First Ofdm Sym %d\n",frame_rx,nr_tti_rx,wait); + //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait First Ofdm Sym %d\n",frame_rx,nr_slot_rx,wait); //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); ue_pdsch_procedures(ue, proc, - eNB_id, + gNB_id, PDSCH, - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], + ue->dlsch[proc->thread_id][gNB_id][0], NULL, (ue->frame_parms.symbols_per_slot>>1), ue->frame_parms.symbols_per_slot-1, abstraction_flag); - LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - LOG_D(PHY," ------ --> PDSCH Turbo Decoder slot 0/1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_slot_rx); + LOG_D(PHY," ------ --> PDSCH Turbo Decoder slot 0/1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_slot_rx); } // do procedures for SI-RNTI - if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) { ue_pdsch_procedures(ue, proc, - eNB_id, + gNB_id, SI_PDSCH, - ue->dlsch_SI[eNB_id], + ue->dlsch_SI[gNB_id], NULL, (ue->frame_parms.symbols_per_slot>>1), ue->frame_parms.symbols_per_slot-1, @@ -3951,24 +1456,24 @@ void *UE_thread_slot1_dl_processing(void *arg) { } // do procedures for P-RNTI - if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) { ue_pdsch_procedures(ue, proc, - eNB_id, + gNB_id, P_PDSCH, - ue->dlsch_p[eNB_id], + ue->dlsch_p[gNB_id], NULL, (ue->frame_parms.symbols_per_slot>>1), ue->frame_parms.symbols_per_slot-1, abstraction_flag); } // do procedures for RA-RNTI - if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1) && (UE_mode != PUSCH)) { ue_pdsch_procedures(ue, proc, - eNB_id, + gNB_id, RA_PDSCH, - ue->dlsch_ra[eNB_id], + ue->dlsch_ra[gNB_id], NULL, (ue->frame_parms.symbols_per_slot>>1), ue->frame_parms.symbols_per_slot-1, @@ -3976,16 +1481,10 @@ void *UE_thread_slot1_dl_processing(void *arg) { } proc->llr_slot1_available=1; - //printf("Set available LLR slot1 to 1 AbsSubframe %d.%d \n",frame_rx,nr_tti_rx); + //printf("Set available LLR slot1 to 1 AbsSubframe %d.%d \n",frame_rx,nr_slot_rx); -#if UE_TIMING_TRACE - stop_meas(&ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1]); -#if DISABLE_LOG_X - printf("[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_tti_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1].p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_tti_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[nr_tti_rx]][1].p_time/(cpuf*1000.0)); -#endif -#endif + stop_meas(&ue->pdsch_procedures_per_slot_stat[proc->thread_id][1]); + LOG_D(PHY, "[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_slot_rx,ue->pdsch_procedures_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0)); if (pthread_mutex_lock(&proc->mutex_slot1_dl_processing) != 0) { LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); @@ -4003,6 +1502,59 @@ void *UE_thread_slot1_dl_processing(void *arg) { } #endif +int is_ssb_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp) +{ + int mu = fp->numerology_index; + //uint8_t half_frame_index = fp->half_frame_bit; + //uint8_t i_ssb = fp->ssb_index; + uint8_t Lmax = fp->Lmax; + + if (!(frame%(1<<(config->ssb_table.ssb_period-1)))){ + + if(Lmax <= 8) { + if(slot <=3 && (((config->ssb_table.ssb_mask_list[0].ssb_mask << 2*slot)&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[0].ssb_mask << (2*slot +1))&0x80000000) == 0x80000000)) + return 1; + else return 0; + + } + else if(Lmax == 64) { + if (mu == NR_MU_3){ + + if (slot>=0 && slot <= 7){ + if(((config->ssb_table.ssb_mask_list[0].ssb_mask << 2*slot)&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[0].ssb_mask << (2*slot +1))&0x80000000) == 0x80000000) + return 1; + else return 0; + } + else if (slot>=10 && slot <=17){ + if(((config->ssb_table.ssb_mask_list[0].ssb_mask << 2*(slot-2))&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[0].ssb_mask << (2*(slot-2) +1))&0x80000000) == 0x80000000) + return 1; + else return 0; + } + else if (slot>=20 && slot <=27){ + if(((config->ssb_table.ssb_mask_list[1].ssb_mask << 2*(slot-20))&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[1].ssb_mask << (2*(slot-20) +1))&0x80000000) == 0x80000000) + return 1; + else return 0; + } + else if (slot>=30 && slot <=37){ + if(((config->ssb_table.ssb_mask_list[1].ssb_mask << 2*(slot-22))&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[1].ssb_mask << (2*(slot-22) +1))&0x80000000) == 0x80000000) + return 1; + else return 0; + } + else return 0; + + } + + + else if (mu == NR_MU_4) { + AssertFatal(0==1, "not implemented for mu = %d yet\n", mu); + } + else AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu); + } + else AssertFatal(0==1, "Invalid Lmax %u for the synchronization block\n", Lmax); + } + else return 0; + +} int is_pbch_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp) { @@ -4027,376 +1579,324 @@ int is_pbch_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, - uint8_t eNB_id, - uint8_t do_pdcch_flag, - runmode_t mode) -{ + uint8_t gNB_id, + uint8_t dlsch_parallel, + notifiedFIFO_t *txFifo + ) +{ int frame_rx = proc->frame_rx; - int nr_tti_rx = proc->nr_tti_rx; + int nr_slot_rx = proc->nr_slot_rx; int slot_pbch; - NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][0]; + int slot_ssb; + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; fapi_nr_config_request_t *cfg = &ue->nrUE_config; uint8_t nb_symb_pdcch = pdcch_vars->nb_search_space > 0 ? pdcch_vars->pdcch_config[0].coreset.duration : 0; uint8_t dci_cnt = 0; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); - LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ****** \n", frame_rx%1024, nr_tti_rx); + LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d (energy %d dB)****** \n", + frame_rx%1024, nr_slot_rx, + dB_fixed(signal_energy(ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0],2048*14))); /* - uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); + uint8_t next1_thread_id = proc->thread_id== (RX_NB_TH-1) ? 0:(proc->thread_id+1); uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); */ int coreset_nb_rb=0; int coreset_start_rb=0; + if (pdcch_vars->nb_search_space > 0) get_coreset_rballoc(pdcch_vars->pdcch_config[0].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); - - slot_pbch = is_pbch_in_slot(cfg, frame_rx, nr_tti_rx, fp); + + slot_pbch = is_pbch_in_slot(cfg, frame_rx, nr_slot_rx, fp); + slot_ssb = is_ssb_in_slot(cfg, frame_rx, nr_slot_rx, fp); // looking for pbch only in slot where it is supposed to be - if ((ue->decode_MIB == 1) && slot_pbch) - { - LOG_I(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + if (slot_ssb) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_IN); + LOG_D(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); + for (int i=1; i<4; i++) { - for (int i=1; i<4; i++) { + nr_slot_fep(ue, + proc, + (ue->symbol_offset+i)%(fp->symbols_per_slot), + nr_slot_rx); - nr_slot_fep(ue, - (ue->symbol_offset+i)%(fp->symbols_per_slot), - nr_tti_rx, - 0, - 0); -#if UE_TIMING_TRACE - start_meas(&ue->dlsch_channel_estimation_stats); -#endif - nr_pbch_channel_estimation(ue,0,nr_tti_rx,(ue->symbol_offset+i)%(fp->symbols_per_slot),i-1,(fp->ssb_index)&7,fp->half_frame_bit); -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_channel_estimation_stats); -#endif - - } - nr_ue_pbch_procedures(eNB_id,ue,proc,0); + start_meas(&ue->dlsch_channel_estimation_stats); + nr_pbch_channel_estimation(ue,proc,gNB_id,nr_slot_rx,(ue->symbol_offset+i)%(fp->symbols_per_slot),i-1,(fp->ssb_index)&7,fp->half_frame_bit); + stop_meas(&ue->dlsch_channel_estimation_stats); + } + + nr_ue_rsrp_measurements(ue, gNB_id, proc, nr_slot_rx, 0); + + if ((ue->decode_MIB == 1) && slot_pbch) { + + LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); + nr_ue_pbch_procedures(gNB_id, ue, proc, 0); if (ue->no_timing_correction==0) { - LOG_I(PHY,"start adjust sync slot = %d no timing %d\n", nr_tti_rx, ue->no_timing_correction); + LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction); nr_adjust_synch_ue(fp, ue, - eNB_id, + gNB_id, frame_rx, - nr_tti_rx, + nr_slot_rx, 0, 16384); } + + LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__); + nr_ue_rrc_measurements(ue, proc, nr_slot_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_OUT); } - -#ifdef NR_PDCCH_SCHED - nr_gold_pdcch(ue, 0, 2); - - LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - for (uint16_t l=0; lofdm_demod_stats); -#endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - nr_slot_fep(ue, - l, - nr_tti_rx, - 0, - 0); - - // note: this only works if RBs for PDCCH are contigous! - LOG_D(PHY,"pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d\n", - fp->first_carrier_offset,pdcch_vars->pdcch_config[0].BWPStart,coreset_start_rb); - if (coreset_nb_rb > 0) - nr_pdcch_channel_estimation(ue, - 0, - nr_tti_rx, - l, - fp->first_carrier_offset+(pdcch_vars->pdcch_config[0].BWPStart + coreset_start_rb)*12, - coreset_nb_rb); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(&ue->ofdm_demod_stats); -#endif - - //printf("phy procedure pdcch start measurement l =%d\n",l); - //nr_ue_measurement_procedures(l,ue,proc,eNB_id,(nr_tti_rx),mode); - } - dci_cnt = nr_ue_pdcch_procedures(eNB_id, ue, proc); + if ((frame_rx%64 == 0) && (nr_slot_rx==0)) { + LOG_I(NR_PHY,"============================================\n"); + LOG_I(NR_PHY,"Harq round stats for Downlink: %d/%d/%d/%d DLSCH errors: %d\n",ue->dl_stats[0],ue->dl_stats[1],ue->dl_stats[2],ue->dl_stats[3],ue->dl_stats[4]); + LOG_I(NR_PHY,"============================================\n"); + } + +#ifdef NR_PDCCH_SCHED + + LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_IN); + + for (uint16_t l=0; lofdm_demod_stats); + nr_slot_fep(ue, + proc, + l, + nr_slot_rx); + } + + dci_cnt = 0; + for(int n_ss = 0; n_ssnb_search_space; n_ss++) { + for (uint16_t l=0; lfirst_carrier_offset, pdcch_vars->pdcch_config[n_ss].BWPStart, coreset_start_rb, coreset_nb_rb); + + if (coreset_nb_rb > 0) + nr_pdcch_channel_estimation(ue, + proc, + gNB_id, + nr_slot_rx, + l, + fp->first_carrier_offset+(pdcch_vars->pdcch_config[n_ss].BWPStart + coreset_start_rb)*12, + coreset_nb_rb); + + stop_meas(&ue->ofdm_demod_stats); + + } + dci_cnt = dci_cnt + nr_ue_pdcch_procedures(gNB_id, ue, proc, n_ss); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT); if (dci_cnt > 0) { - LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_tti_rx, dci_cnt); + LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt); NR_UE_DLSCH_t *dlsch = NULL; - if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1){ - dlsch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]; + if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1){ + dlsch = ue->dlsch[proc->thread_id][gNB_id][0]; + } else if (ue->dlsch_SI[0]->active == 1){ + dlsch = ue->dlsch_SI[0]; } else if (ue->dlsch_ra[0]->active == 1){ dlsch = ue->dlsch_ra[0]; } - AssertFatal(dlsch != NULL, "Unsupported mode\n"); - uint8_t harq_pid = dlsch->current_harq_pid; - NR_DL_UE_HARQ_t *dlsch0_harq = dlsch->harq_processes[harq_pid]; - uint16_t nb_symb_sch = dlsch0_harq->nb_symbols; - uint16_t start_symb_sch = dlsch0_harq->start_symbol; - int symb_dmrs = -1; - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - //to update from pdsch config + if (dlsch) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_IN); + uint8_t harq_pid = dlsch->current_harq_pid; + NR_DL_UE_HARQ_t *dlsch0_harq = dlsch->harq_processes[harq_pid]; + uint16_t nb_symb_sch = dlsch0_harq->nb_symbols; + uint16_t start_symb_sch = dlsch0_harq->start_symbol; - for (int i=0;i<4;i++) if (((1<dlDmrsSymbPos) > 0) {symb_dmrs=i;break;} - AssertFatal(symb_dmrs>=0,"no dmrs in 0..3\n"); - LOG_D(PHY,"Initializing dmrs for symb %d DMRS mask %x\n",symb_dmrs,dlsch0_harq->dlDmrsSymbPos); - nr_gold_pdsch(ue,symb_dmrs,0, 1); - - for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ - nr_slot_fep(ue, - m, //to be updated from higher layer - nr_tti_rx, - 0, - 0); + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); + //to update from pdsch config + + for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ + nr_slot_fep(ue, + proc, + m, //to be updated from higher layer + nr_slot_rx); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT); } } else { - LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: No DCIs found\n", ue->Mod_id, frame_rx, nr_tti_rx); + LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: No DCIs found\n", ue->Mod_id, frame_rx, nr_slot_rx); } #endif //NR_PDCCH_SCHED -#if UE_TIMING_TRACE + // Start PUSCH processing here. It runs in parallel with PDSCH processing + notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), proc->nr_slot_tx,txFifo,processSlotTX); + nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(newElt); + curMsg->proc = *proc; + curMsg->UE = ue; + curMsg->ue_sched_mode = ONLY_PUSCH; + pushTpool(&(get_nrUE_params()->Tpool), newElt); start_meas(&ue->generic_stat); -#endif // do procedures for C-RNTI - if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); - nr_ue_pdsch_procedures(ue, - proc, - eNB_id, - PDSCH, - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], - NULL); + int ret_pdsch = 0; + if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) { - //printf("phy procedure pdsch start measurement\n"); - nr_ue_measurement_procedures(2,ue,proc,eNB_id,nr_tti_rx,mode); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_IN); + ret_pdsch = nr_ue_pdsch_procedures(ue, + proc, + gNB_id, + PDSCH, + ue->dlsch[proc->thread_id][gNB_id][0], + NULL); - /* - write_output("rxF.m","rxF",&ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0][0],fp->ofdm_symbol_size*14,1,1); - write_output("rxF_ch.m","rxFch",&ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_estimates[0][0],fp->ofdm_symbol_size*14,1,1); - write_output("rxF_ch_ext.m","rxFche",&ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->dl_ch_estimates_ext[0][2*50*12],50*12,1,1); - write_output("rxF_ext.m","rxFe",&ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->rxdataF_ext[0][0],50*12*14,1,1); - write_output("rxF_comp.m","rxFc",&ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->rxdataF_comp0[0][0],fp->N_RB_DL*12*14,1,1); - write_output("rxF_llr.m","rxFllr",ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->llr[0],(nb_symb_sch-1)*50*12+50*6,1,0); - */ - - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); + nr_ue_measurement_procedures(2, ue, proc, gNB_id, nr_slot_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_OUT); } // do procedures for SI-RNTI - if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN); nr_ue_pdsch_procedures(ue, - proc, - eNB_id, - SI_PDSCH, - ue->dlsch_SI[eNB_id], - NULL); + proc, + gNB_id, + SI_PDSCH, + ue->dlsch_SI[gNB_id], + NULL); + nr_ue_dlsch_procedures(ue, + proc, + gNB_id, + SI_PDSCH, + ue->dlsch_SI[gNB_id], + NULL, + &ue->dlsch_SI_errors[gNB_id], + dlsch_parallel); + + // deactivate dlsch once dlsch proc is done + ue->dlsch_SI[gNB_id]->active = 0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT); } - // do procedures for SI-RNTI - if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + // do procedures for P-RNTI + if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN); nr_ue_pdsch_procedures(ue, - proc, - eNB_id, - P_PDSCH, - ue->dlsch_p[eNB_id], - NULL); + proc, + gNB_id, + P_PDSCH, + ue->dlsch_p[gNB_id], + NULL); + nr_ue_dlsch_procedures(ue, + proc, + gNB_id, + P_PDSCH, + ue->dlsch_p[gNB_id], + NULL, + &ue->dlsch_p_errors[gNB_id], + dlsch_parallel); + + // deactivate dlsch once dlsch proc is done + ue->dlsch_p[gNB_id]->active = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT); } // do procedures for RA-RNTI - if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1) && (ue->UE_mode[gNB_id] != PUSCH)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN); nr_ue_pdsch_procedures(ue, - proc, - eNB_id, - RA_PDSCH, - ue->dlsch_ra[eNB_id], - NULL); - - // #if UE_TIMING_TRACE - // start_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); - // #endif + proc, + gNB_id, + RA_PDSCH, + ue->dlsch_ra[gNB_id], + NULL); nr_ue_dlsch_procedures(ue, proc, - eNB_id, + gNB_id, RA_PDSCH, - ue->dlsch_ra[eNB_id], + ue->dlsch_ra[gNB_id], NULL, - &ue->dlsch_ra_errors[eNB_id], - mode); + &ue->dlsch_ra_errors[gNB_id], + dlsch_parallel); - // #if UE_TIMING_TRACE - // stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); - #if DISABLE_LOG_X - printf("[SFN %d] Slot1: Pdsch Proc %5.2f\n", nr_tti_rx, ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); - printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n", nr_tti_rx, ue->dlsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0)); - #else - LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n", nr_tti_rx, ue->pdsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0)); - LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n", nr_tti_rx, ue->dlsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0)); - #endif - // #endif + // deactivate dlsch once dlsch proc is done + ue->dlsch_ra[gNB_id]->active = 0; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); } - // do procedures for C-RNTI - if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { + if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) { - LOG_D(PHY, "DLSCH data reception at nr_tti_rx: %d \n \n", nr_tti_rx); + LOG_D(PHY, "DLSCH data reception at nr_slot_rx: %d\n", nr_slot_rx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); -#if UE_TIMING_TRACE - start_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); -#endif + start_meas(&ue->dlsch_procedures_stat[proc->thread_id]); - nr_ue_dlsch_procedures(ue, + if (ret_pdsch >= 0) + nr_ue_dlsch_procedures(ue, proc, - eNB_id, + gNB_id, PDSCH, - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0], - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1], - &ue->dlsch_errors[eNB_id], - mode); + ue->dlsch[proc->thread_id][gNB_id][0], + ue->dlsch[proc->thread_id][gNB_id][1], + &ue->dlsch_errors[gNB_id], + dlsch_parallel); + stop_meas(&ue->dlsch_procedures_stat[proc->thread_id]); + LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n",nr_slot_rx,ue->pdsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0)); + LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_slot_rx,ue->dlsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0)); -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); -#if DISABLE_LOG_X - printf("[SFN %d] Slot1: Pdsch Proc %5.2f\n",nr_tti_rx,ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); - printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_tti_rx,ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n",nr_tti_rx,ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); - LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_tti_rx,ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); -#endif - -#endif // deactivate dlsch once dlsch proc is done - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 0; + ue->dlsch[proc->thread_id][gNB_id][0]->active = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); } -#if UE_TIMING_TRACE + start_meas(&ue->generic_stat); -#endif #if 0 - if(nr_tti_rx==5 && ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid]->nb_rb > 20){ + if(nr_slot_rx==5 && ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid]->nb_rb > 20){ //write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); - //write_output("llr.m","llr", &ue->pdsch_vars[eNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); + //write_output("llr.m","llr", &ue->pdsch_vars[proc->thread_id][gNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); - write_output("rxdataF0_current.m" , "rxdataF0", &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1); + write_output("rxdataF0_current.m" , "rxdataF0", &ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1); //write_output("rxdataF0_previous.m" , "rxdataF0_prev_sss", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1); //write_output("rxdataF0_previous.m" , "rxdataF0_prev", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1); - write_output("dl_ch_estimates.m", "dl_ch_estimates_sfn5", &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[0][0][0],14*fp->ofdm_symbol_size,1,1); - write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_estimates_ext[0][0],14*fp->N_RB_DL*12,1,1); - write_output("rxdataF_comp00.m","rxdataF_comp00", &ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->rxdataF_comp0[0][0],14*fp->N_RB_DL*12,1,1); - //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_mag0[0][0],14*fp->N_RB_DL*12,1,1); - //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_magb0[0][0],14*fp->N_RB_DL*12,1,1); + write_output("dl_ch_estimates.m", "dl_ch_estimates_sfn5", &ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].dl_ch_estimates[0][0][0],14*fp->ofdm_symbol_size,1,1); + write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates_ext[0][0],14*fp->N_RB_DL*12,1,1); + write_output("rxdataF_comp00.m","rxdataF_comp00", &ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_comp0[0][0],14*fp->N_RB_DL*12,1,1); + //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_mag0[0][0],14*fp->N_RB_DL*12,1,1); + //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_magb0[0][0],14*fp->N_RB_DL*12,1,1); AssertFatal (0,""); } #endif - // do procedures for SI-RNTI - if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { - nr_ue_pdsch_procedures(ue, - proc, - eNB_id, - SI_PDSCH, - ue->dlsch_SI[eNB_id], - NULL); - - /*ue_dlsch_procedures(ue, - proc, - eNB_id, - SI_PDSCH, - ue->dlsch_SI[eNB_id], - NULL, - &ue->dlsch_SI_errors[eNB_id], - mode, - abstraction_flag); - ue->dlsch_SI[eNB_id]->active = 0;*/ - } - - // do procedures for P-RNTI - if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { - nr_ue_pdsch_procedures(ue, - proc, - eNB_id, - P_PDSCH, - ue->dlsch_p[eNB_id], - NULL); - - - /*ue_dlsch_procedures(ue, - proc, - eNB_id, - P_PDSCH, - ue->dlsch_p[eNB_id], - NULL, - &ue->dlsch_p_errors[eNB_id], - mode, - abstraction_flag);*/ - ue->dlsch_p[eNB_id]->active = 0; - } - // do procedures for RA-RNTI - if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { - nr_ue_pdsch_procedures(ue, - proc, - eNB_id, - RA_PDSCH, - ue->dlsch_ra[eNB_id], - NULL); - - /*ue_dlsch_procedures(ue, - proc, - eNB_id, - RA_PDSCH, - ue->dlsch_ra[eNB_id], - NULL, - &ue->dlsch_ra_errors[eNB_id], - mode, - abstraction_flag);*/ - ue->dlsch_ra[eNB_id]->active = 0; - } - // duplicate harq structure - /* - uint8_t current_harq_pid = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid; - NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_processes[current_harq_pid]; - NR_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[next1_thread_id][eNB_id][0]->harq_processes[current_harq_pid]; - NR_DL_UE_HARQ_t *harq_processes_dest1 = ue->dlsch[next2_thread_id][eNB_id][0]->harq_processes[current_harq_pid]; +/* + uint8_t current_harq_pid = ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid; + NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[current_harq_pid]; + NR_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[next1_thread_id][gNB_id][0]->harq_processes[current_harq_pid]; + NR_DL_UE_HARQ_t *harq_processes_dest1 = ue->dlsch[next2_thread_id][gNB_id][0]->harq_processes[current_harq_pid]; */ - /*nr_harq_status_t *current_harq_ack = &ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->harq_ack[nr_tti_rx]; - nr_harq_status_t *harq_ack_dest = &ue->dlsch[next1_thread_id][eNB_id][0]->harq_ack[nr_tti_rx]; - nr_harq_status_t *harq_ack_dest1 = &ue->dlsch[next2_thread_id][eNB_id][0]->harq_ack[nr_tti_rx]; + /*nr_harq_status_t *current_harq_ack = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_ack[nr_slot_rx]; + nr_harq_status_t *harq_ack_dest = &ue->dlsch[next1_thread_id][gNB_id][0]->harq_ack[nr_slot_rx]; + nr_harq_status_t *harq_ack_dest1 = &ue->dlsch[next2_thread_id][gNB_id][0]->harq_ack[nr_slot_rx]; */ //copy_harq_proc_struct(harq_processes_dest, current_harq_processes); @@ -4405,54 +1905,45 @@ start_meas(&ue->generic_stat); //copy_harq_proc_struct(harq_processes_dest1, current_harq_processes); //copy_ack_struct(harq_ack_dest1, current_harq_ack); -if (nr_tti_rx==9) { +if (nr_slot_rx==9) { if (frame_rx % 10 == 0) { - if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) - ue->dlsch_fer[eNB_id] = (100*(ue->dlsch_errors[eNB_id] - ue->dlsch_errors_last[eNB_id]))/(ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]); + if ((ue->dlsch_received[gNB_id] - ue->dlsch_received_last[gNB_id]) != 0) + ue->dlsch_fer[gNB_id] = (100*(ue->dlsch_errors[gNB_id] - ue->dlsch_errors_last[gNB_id]))/(ue->dlsch_received[gNB_id] - ue->dlsch_received_last[gNB_id]); - ue->dlsch_errors_last[eNB_id] = ue->dlsch_errors[eNB_id]; - ue->dlsch_received_last[eNB_id] = ue->dlsch_received[eNB_id]; + ue->dlsch_errors_last[gNB_id] = ue->dlsch_errors[gNB_id]; + ue->dlsch_received_last[gNB_id] = ue->dlsch_received[gNB_id]; } - ue->bitrate[eNB_id] = (ue->total_TBS[eNB_id] - ue->total_TBS_last[eNB_id])*100; - ue->total_TBS_last[eNB_id] = ue->total_TBS[eNB_id]; + ue->bitrate[gNB_id] = (ue->total_TBS[gNB_id] - ue->total_TBS_last[gNB_id])*100; + ue->total_TBS_last[gNB_id] = ue->total_TBS[gNB_id]; LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", - ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], - ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); + ue->Mod_id,frame_rx,ue->total_TBS[gNB_id], + ue->total_TBS_last[gNB_id],(float) ue->bitrate[gNB_id]/1000.0); #if UE_AUTOTEST_TRACE if ((frame_rx % 100 == 0)) { - LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[eNB_id]/1000.0, frame_rx); + LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[gNB_id]/1000.0, frame_rx); } #endif } -#if UE_TIMING_TRACE stop_meas(&ue->generic_stat); -printf("after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0)); -#endif #ifdef EMOS -phy_procedures_emos_UE_RX(ue,slot,eNB_id); +phy_procedures_emos_UE_RX(ue,slot,gNB_id); #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE -stop_meas(&ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]]); -#if DISABLE_LOG_X -printf("------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_tti_rx,ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); -#else -LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_tti_rx,ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0)); -#endif -#endif +stop_meas(&ue->phy_proc_rx[proc->thread_id]); +LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_slot_rx,ue->phy_proc_rx[proc->thread_id].p_time/(cpuf*1000.0)); //#endif //pdsch -LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); +LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_slot_rx); return (0); } @@ -4461,7 +1952,7 @@ uint8_t nr_is_cqi_TXOp(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) { - int subframe = proc->subframe_tx; + int subframe = proc->nr_slot_tx / ue->frame_parms.slots_per_subframe; int frame = proc->frame_tx; CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[gNB_id].CQI_ReportPeriodic; @@ -4483,7 +1974,7 @@ uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) { - int subframe = proc->subframe_tx; + int subframe = proc->nr_slot_tx / ue->frame_parms.slots_per_subframe; int frame = proc->frame_tx; CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[gNB_id].CQI_ReportPeriodic; int log2Mri = cqirep->ri_ConfigIndex/161; @@ -4501,121 +1992,90 @@ uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue, return(0); } -// WIP // todo: -// - set tx_total_RE // - power control as per 38.213 ch 7.4 -void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, runmode_t runmode) { +void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) { - int frame_tx = proc->frame_tx, nr_tti_tx = proc->nr_tti_tx, prach_power; // tx_amp - uint16_t /*preamble_tx = 50,*/ pathloss; + int frame_tx = proc->frame_tx, nr_slot_tx = proc->nr_slot_tx, prach_power; // tx_amp uint8_t mod_id = ue->Mod_id; - UE_MODE_t UE_mode = get_nrUE_mode(mod_id, ue->CC_id, gNB_id); NR_PRACH_RESOURCES_t * prach_resources = ue->prach_resources[gNB_id]; + AssertFatal(prach_resources != NULL, "ue->prach_resources[%u] == NULL\n", gNB_id); uint8_t nr_prach = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN); if (ue->mac_enabled == 0){ - // prach_resources->ra_PreambleIndex = preamble_tx; + prach_resources->ra_TDD_map_index = 0; prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = 10; prach_resources->ra_RNTI = 0x1234; nr_prach = 1; - } else { - // ask L2 for RACH transport - if ((runmode != rx_calib_ue) && (runmode != rx_calib_ue_med) && (runmode != rx_calib_ue_byp) && (runmode != no_L2_connect) ) { - LOG_D(PHY, "Getting PRACH resources. Frame %d Slot %d \n", frame_tx, nr_tti_tx); - // flush Msg3 Buffer - if (prach_resources->Msg3 == NULL){ - for(int i = 0; iulsch_Msg3_active[i] = 0; - } - } - nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx); - } - } - - if (!prach_resources->init_msg1 && (frame_tx > ue->prach_resources[gNB_id]->sync_frame + 150)){ - ue->prach_cnt = 0; prach_resources->init_msg1 = 1; + + } else { + + nr_prach = nr_ue_get_rach(prach_resources, &ue->prach_vars[0]->prach_pdu, mod_id, ue->CC_id, frame_tx, gNB_id, nr_slot_tx); + LOG_D(PHY, "In %s:[%d.%d] getting PRACH resources : %d\n", __FUNCTION__, frame_tx, nr_slot_tx,nr_prach); } - if (ue->prach_resources[gNB_id] != NULL && nr_prach == 1 && prach_resources->init_msg1) { + if (nr_prach == GENERATE_PREAMBLE) { - pathloss = get_nr_PL(mod_id, ue->CC_id, gNB_id); - LOG_D(PHY,"runmode %d\n",runmode); + if (ue->mac_enabled == 1) { + int16_t pathloss = get_nr_PL(mod_id, ue->CC_id, gNB_id); + int16_t ra_preamble_rx_power = (int16_t)(prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER - pathloss + 30); + ue->tx_power_dBm[nr_slot_tx] = min(nr_get_Pcmax(mod_id), ra_preamble_rx_power); - if ((ue->mac_enabled == 1) && (runmode != calib_prach_tx)) { - ue->tx_power_dBm[nr_tti_tx] = prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER + pathloss; + LOG_D(PHY, "In %s: [UE %d][RAPROC][%d.%d]: Generating PRACH Msg1 (preamble %d, PL %d dB, P0_PRACH %d, TARGET_RECEIVED_POWER %d dBm, RA-RNTI %x)\n", + __FUNCTION__, + mod_id, + frame_tx, + nr_slot_tx, + prach_resources->ra_PreambleIndex, + pathloss, + ue->tx_power_dBm[nr_slot_tx], + prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER, + prach_resources->ra_RNTI); } - LOG_I(PHY,"[UE %d][RAPROC] Frame %d, nr_tti_tx %d : Generating PRACH, preamble %d, PL %d, P0_PRACH %d, TARGET_RECEIVED_POWER %d dBm, RA-RNTI %x\n", - ue->Mod_id, - frame_tx, - nr_tti_tx, - prach_resources->ra_PreambleIndex, - pathloss, - ue->tx_power_dBm[nr_tti_tx], - prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER, - prach_resources->ra_RNTI); - - //ue->tx_total_RE[nr_tti_tx] = 96; // todo ue->prach_vars[gNB_id]->amp = AMP; /* #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - tx_amp = get_tx_amp_prach(ue->tx_power_dBm[nr_tti_tx], ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL); + tx_amp = get_tx_amp_prach(ue->tx_power_dBm[nr_slot_tx], ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL); if (tx_amp != -1) ue->prach_vars[gNB_id]->amp = tx_amp; #else ue->prach_vars[gNB_id]->amp = AMP; #endif */ - if ((runmode == calib_prach_tx) && (((proc->frame_tx&0xfffe)%100)==0)) - LOG_D(PHY,"[UE %d][RAPROC] Frame %d, nr_tti_tx %d : PRACH TX power %d dBm, amp %d\n", ue->Mod_id, - proc->frame_rx, - proc->nr_tti_tx, - ue->tx_power_dBm[nr_tti_tx], - ue->prach_vars[gNB_id]->amp); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_IN); - prach_power = generate_nr_prach(ue, gNB_id, nr_tti_tx); + prach_power = generate_nr_prach(ue, gNB_id, nr_slot_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_OUT); - LOG_D(PHY,"[UE %d][RAPROC] PRACH PL %d dB, power %d dBm, digital power %d dB (amp %d)\n", - ue->Mod_id, - pathloss, - ue->tx_power_dBm[nr_tti_tx], + LOG_D(PHY, "In %s: [UE %d][RAPROC][%d.%d]: Generated PRACH Msg1 (TX power PRACH %d dBm, digital power %d dBW (amp %d)\n", + __FUNCTION__, + mod_id, + frame_tx, + nr_slot_tx, + ue->tx_power_dBm[nr_slot_tx], dB_fixed(prach_power), ue->prach_vars[gNB_id]->amp); if (ue->mac_enabled == 1) - nr_Msg1_transmitted(ue->Mod_id, ue->CC_id, frame_tx, gNB_id); + nr_Msg1_transmitted(mod_id, ue->CC_id, frame_tx, gNB_id); - LOG_I(PHY,"[UE %d][RAPROC] Frame %d, nr_tti_tx %d: Generated PRACH Msg1 (gNB %d) preamble index %d for UL, TX power %d dBm (PL %d dB) \n", - ue->Mod_id, - frame_tx, - nr_tti_tx, - gNB_id, - prach_resources->ra_PreambleIndex, - ue->tx_power_dBm[nr_tti_tx], - pathloss); - - LOG_D(PHY,"[UE %d] frame %d nr_tti_tx %d : prach_cnt %d\n", ue->Mod_id, frame_tx, nr_tti_tx, ue->prach_cnt); - - ue->prach_cnt++; - - if (ue->prach_cnt == 3) - ue->prach_cnt = 0; - } else if (nr_prach == 2) { - nr_ra_succeeded(mod_id, ue->CC_id, gNB_id); + } else if (nr_prach == WAIT_CONTENTION_RESOLUTION) { + LOG_D(PHY, "In %s: [UE %d] RA waiting contention resolution\n", __FUNCTION__, mod_id); + ue->UE_mode[gNB_id] = RA_WAIT_CR; + } else if (nr_prach == RA_SUCCEEDED) { + LOG_D(PHY, "In %s: [UE %d] RA completed, setting UE mode to PUSCH\n", __FUNCTION__, mod_id); + ue->UE_mode[gNB_id] = PUSCH; + } else if(nr_prach == RA_FAILED){ + LOG_D(PHY, "In %s: [UE %d] RA failed, setting UE mode to PRACH\n", __FUNCTION__, mod_id); + ue->UE_mode[gNB_id] = PRACH; } - // if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue - if (runmode == calib_prach_tx) - ue->prach_resources[gNB_id] = NULL; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_OUT); + } diff --git a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c b/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c deleted file mode 100644 index b51c8afbb0..0000000000 --- a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/************************************************************************ -* -* MODULE : PUCCH power control for UE NR -* -* DESCRIPTION : functions related to PUCCH Transmit power -* TS 38.213 7.2.1 UE behaviour -* -**************************************************************************/ - -#include "PHY/NR_REFSIG/ss_pbch_nr.h" -#include "PHY/defs_nr_UE.h" -#include "SCHED_NR_UE/pucch_uci_ue_nr.h" -#include "SCHED_NR_UE/pucch_power_control_ue_nr.h" -#include -#include - -/**************** defines **************************************/ - -/**************** variables **************************************/ - - -/**************** functions **************************************/ - - -/******************************************************************* -* -* NAME : get_pucch_tx_power_ue -* -* PARAMETERS : ue context -* gNB_id identity -* slots for rx and tx -* pucch_format_nr_t pucch format -* nb_of_prbs number of prb allocated to pucch -* N_sc_ctrl_RB subcarrier control rb related to current pucch format -* N_symb_PUCCH number of pucch symbols excluding those reserved for dmrs -* O_UCI number of bits for UCI Uplink Control Information -* O_SR number of bits for SR scheduling Request -* O_UCI number of bits for CSI Channel State Information -* O_ACK number of bits for HARQ-ACK -* O_CRC number of bits for CRC -* n_HARQ_ACK use for obtaining a PUCCH transmission power -* -* RETURN : pucch power level in dBm -* -* DESCRIPTION : determines pucch transmission power in dBm -* TS 38.213 7.2.1 UE behaviour -* -*********************************************************************/ - -int16_t get_pucch_tx_power_ue(PHY_VARS_NR_UE *ue, - uint8_t gNB_id, - UE_nr_rxtx_proc_t *proc, - pucch_format_nr_t pucch_format, - int nb_of_prbs, - int N_sc_ctrl_RB, - int N_symb_PUCCH, - int O_UCI, - int O_SR, - int O_CSI, - int O_ACK, - int O_CRC, - int n_HARQ_ACK) { - - int16_t P_O_NOMINAL_PUCCH = ue->pucch_config_common_nr[gNB_id].p0_nominal; - PUCCH_PowerControl_t *power_config = &ue->pucch_config_dedicated_nr[gNB_id].pucch_PowerControl; - int16_t P_O_UE_PUCCH; - int16_t G_b_f_c = 0; - - if (ue->pucch_config_dedicated_nr[gNB_id].spatial_Relation_Info[0] != NULL) { /* FFS TODO NR */ - LOG_E(PHY,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); - return (PUCCH_POWER_DEFAULT); - } - - if (power_config->p0_Set[0] != NULL) { - P_O_UE_PUCCH = power_config->p0_Set[0]->p0_PUCCH_Value; /* get from index 0 if no spatial relation set */ - G_b_f_c = 0; - } - else { - G_b_f_c = ue->dlsch[ue->current_thread_id[proc->subframe_rx]][gNB_id][0]->g_pucch; - LOG_W(PHY,"PUCCH Transmit power control command not yet implemented for NR : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); - return (PUCCH_POWER_DEFAULT); - } - - int P_O_PUCCH = P_O_NOMINAL_PUCCH + P_O_UE_PUCCH; - - int16_t PL = get_nr_PL(ue->Mod_id, ue->CC_id, gNB_id); /* LTE function because NR path loss not yet implemented FFS TODO NR */ - - int16_t delta_F_PUCCH = power_config->deltaF_PUCCH_f[pucch_format]; - - int DELTA_TF; - uint16_t N_ref_PUCCH; - - /* computing of pucch transmission power adjustment */ - switch (pucch_format) { - case pucch_format0_nr: - { - N_ref_PUCCH = 2; - DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); - break; - } - case pucch_format1_nr: - { - N_ref_PUCCH = N_SYMB_SLOT; - DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); - break; - } - case pucch_format2_nr: - case pucch_format3_nr: - case pucch_format4_nr: - { - float N_RE = nb_of_prbs * N_sc_ctrl_RB * N_symb_PUCCH; - float K1 = 6; - /* initial phase so no higher layer parameters */ - if (ue->UE_mode[gNB_id] != PUSCH) { - if (O_ACK == 0) { - n_HARQ_ACK = 0; - } - else { - n_HARQ_ACK = 1; - } - } - if (O_UCI < 12) { - - DELTA_TF = 10 * log10((double)(((K1 * (n_HARQ_ACK + O_SR + O_CSI))/N_RE))); - } - else { - float K2 = 2.4; - float BPRE = (O_ACK + O_SR + O_CSI + O_CRC)/N_RE; - DELTA_TF = 10 * log10((double)(pow(2,(K2*BPRE)) - 1)); - } - break; - } - default: - { - LOG_E(PHY,"PUCCH unknown pucch format : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); - return (0); - } - } - - int k2; - - if (power_config->twoPUCCH_PC_AdjustmentStates > 1) { - LOG_E(PHY,"PUCCH power control adjustment states with 2 states not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); - return (PUCCH_POWER_DEFAULT); - } - - /* response to a detection by the UE of a DCI format 1_0 or DCI format 1_1 */ - //int K_PUCCH = 0; - if (O_ACK != 0) { - /* it assumes that PDCCH is in the first symbol of receive slot FFS TDDO NR */ - //int slots_gap = (proc->nr_tti_tx > proc->nr_tti_rx ? (proc->nr_tti_tx - proc->nr_tti_rx - 1) : ((proc->nr_tti_tx + ue->frame_parms.ttis_per_subframe) - proc->nr_tti_rx - 1)); - //K_PUCCH = (slots_gap * (ue->frame_parms.symbols_per_tti)) - 1; - } - else { - /* field k2 is not present - to check k2 of pucch from upper layer FFS TDDO NR */ - if (ue->pusch_config.pusch_TimeDomainResourceAllocation[0] == NULL) { - if (ue->frame_parms.numerology_index == 0) { - k2 = 1; - } - else { - k2 = ue->frame_parms.numerology_index; - } - } - else - { - /* get minimum value of k2 */ - int i = 0; - int k2_min = 32; /* max value of k2 */ - do { - k2 = ue->pusch_config.pusch_TimeDomainResourceAllocation[i]->k2; - if (k2 < k2_min) { - k2_min = k2; - } - i++; - if (i >= MAX_NR_OF_UL_ALLOCATIONS) { - break; - } - } while(ue->pusch_config.pusch_TimeDomainResourceAllocation[i] != NULL); - k2 = k2_min; - } - //K_PUCCH = N_SYMB_SLOT * k2; /* the product of a number of symbols per slot and the minimum of the values provided by higher layer parameter k2 */ - } - - int contributor = (10 * log10((double)(pow(2,(ue->frame_parms.numerology_index)) * nb_of_prbs))); - - int16_t pucch_power = P_O_PUCCH + contributor + PL + delta_F_PUCCH + DELTA_TF + G_b_f_c; - - if (pucch_power > ue->tx_power_max_dBm) { - pucch_power = ue->tx_power_max_dBm; - } - - NR_TST_PHY_PRINTF("PUCCH ( Tx power : %d dBm ) ( 10Log(...) : %d ) ( from Path Loss : %d ) ( delta_F_PUCCH : %d ) ( DELTA_TF : %d ) ( G_b_f_c : %d ) \n", - pucch_power, contributor, PL, delta_F_PUCCH, DELTA_TF, G_b_f_c); - - return (pucch_power); -} - diff --git a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.h b/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.h deleted file mode 100644 index 3ebd263c94..0000000000 --- a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/************************************************************************ -* -* MODULE : PUCCH power control for UE NR -* -* DESCRIPTION : functions related to PUCCH Transmit power -* TS 38.213 7.2.1 UE behaviour -* -**************************************************************************/ - -#ifndef PUCCH_POWER_CONTROL_H -#define PUCCH_POWER_CONTROL_H - -/*************** INCLUDE *******************************************/ - -/*************** DEFINE ********************************************/ - -#define PUCCH_POWER_DEFAULT (0) /* in dBm */ - -/*************** VARIABLES *****************************************/ - -/*************** FUNCTIONS *****************************************/ - - -/** \brief This function returns pucch power level in dBm - @param ue context - @param gNB_id identity - @param slots for rx and tx - @param pucch_format_nr_t pucch format - @param nb_of_prbs number of prb allocated to pucch - @param N_sc_ctrl_RB subcarrier control rb related to current pucch format - @param N_symb_PUCCH number of pucch symbols excluding those reserved for dmrs - @param O_UCI number of bits for UCI Uplink Control Information - @param O_SR number of bits for SR scheduling Request - @param int O_UCI number of bits for CSI Channel State Information - @param O_ACK number of bits for HARQ-ACK - @param O_CRC number of bits for CRC - @param n_HARQ_ACK use for obtaining a PUCCH transmission power - @returns pucch power level in dBm */ - -int16_t get_pucch_tx_power_ue(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, pucch_format_nr_t pucch_format, - int nb_of_prbs, int N_sc_ctrl_RB, int N_symb_PUCCH, int O_UCI, int O_SR, int O_CSI, int O_ACK, - int O_CRC, int n_HARQ_ACK); - -#endif /* PUCCH_POWER_CONTROL_H */ diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index ccbe502194..77ac105e14 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -33,16 +33,19 @@ * **************************************************************************/ +#include "executables/softmodem-common.h" #include "PHY/NR_REFSIG/ss_pbch_nr.h" #include "PHY/defs_nr_UE.h" #include #include +#include "openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h" +#include +#include #ifndef NO_RAT_NR #include "SCHED_NR_UE/defs.h" #include "SCHED_NR_UE/harq_nr.h" -#include "SCHED_NR_UE/pucch_power_control_ue_nr.h" #define DEFINE_VARIABLES_PUCCH_UE_NR_H #include "SCHED_NR_UE/pucch_uci_ue_nr.h" @@ -51,15 +54,52 @@ #endif - uint8_t nr_is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id); uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id); + +long +binary_search_float_nr( + float elements[], + long numElem, + float value +) +//----------------------------------------------------------------------------- +{ + long first, last, middle; + first = 0; + last = numElem-1; + middle = (first+last)/2; + + if(value < elements[0]) { + return first; + } + + if(value >= elements[last]) { + return last; + } + + while (last - first > 1) { + if (elements[middle] > value) { + last = middle; + } else { + first = middle; + } + + middle = (first+last)/2; + } + + if (first < 0 || first >= numElem) { + LOG_E(RRC,"\n Error in binary search float!"); + } + + return first; +} /* void nr_generate_pucch0(int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, int16_t amp, - int nr_tti_tx, + int nr_slot_tx, uint8_t mcs, uint8_t nrofSymbols, uint8_t startingSymbolIndex, @@ -70,7 +110,7 @@ void nr_generate_pucch1(int32_t **txdataF, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, uint64_t payload, int16_t amp, - int nr_tti_tx, + int nr_slot_tx, uint8_t nrofSymbols, uint8_t startingSymbolIndex, uint16_t startingPRB, @@ -83,7 +123,7 @@ void nr_generate_pucch2(int32_t **txdataF, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, uint64_t payload, int16_t amp, - int nr_tti_tx, + int nr_slot_tx, uint8_t nrofSymbols, uint8_t startingSymbolIndex, uint8_t nrofPRB, @@ -96,7 +136,7 @@ void nr_generate_pucch3_4(int32_t **txdataF, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, uint64_t payload, int16_t amp, - int nr_tti_tx, + int nr_slot_tx, uint8_t nrofSymbols, uint8_t startingSymbolIndex, uint8_t nrofPRB, @@ -161,1106 +201,93 @@ void nr_generate_pucch3_4(int32_t **txdataF, * *********************************************************************/ -static int bwp_id = 1; +void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, + uint8_t gNB_id, + UE_nr_rxtx_proc_t *proc) { -bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, bool reset_harq) -{ - uint8_t sr_payload = 0; - uint32_t pucch_ack_payload = 0; /* maximum number of bits for pucch payload is supposed to be 32 */ - uint64_t pucch_payload = 0; - uint32_t csi_payload = 0; - int frame_tx = proc->frame_tx; - int nr_tti_tx = proc->nr_tti_tx; - int Mod_id = ue->Mod_id; - int CC_id = ue->CC_id; + int nr_slot_tx = proc->nr_slot_tx; + fapi_nr_ul_config_pucch_pdu *pucch_pdu; + NR_UE_PUCCH *pucch_vars = ue->pucch_vars[proc->thread_id][gNB_id]; - int O_SR = 0; - int O_ACK = 0; - int O_CSI = 0; /* channel state information */ - int N_UCI = 0; /* size in bits for Uplink Control Information */ - int cqi_status = 0; - int ri_status = 0; - int csi_status = 0; + for (int i=0; i<2; i++) { + if(pucch_vars->active[i]) { - int initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; - int pucch_resource_set = MAX_NB_OF_PUCCH_RESOURCE_SETS; - int pucch_resource_id = MAX_NB_OF_PUCCH_RESOURCES; - int pucch_resource_indicator = MAX_PUCCH_RESOURCE_INDICATOR; - int n_HARQ_ACK; + pucch_pdu = &pucch_vars->pucch_pdu[i]; + uint16_t nb_of_prbs = pucch_pdu->prb_size; + /* Generate PUCCH signal according to its format and parameters */ + ue->generate_ul_signal[gNB_id] = 1; - uint16_t crnti=0x1234; - int dmrs_scrambling_id=0,data_scrambling_id=0; + int16_t PL = get_nr_PL(ue->Mod_id, ue->CC_id, gNB_id); /* LTE function because NR path loss not yet implemented FFS TODO NR */ + int contributor = (10 * log10((double)(pow(2,(ue->frame_parms.numerology_index)) * nb_of_prbs))); + + int16_t pucch_tx_power = pucch_pdu->pucch_tx_power + contributor + PL; + + if (pucch_tx_power > ue->tx_power_max_dBm) + pucch_tx_power = ue->tx_power_max_dBm; + + /* set tx power */ + ue->tx_power_dBm[nr_slot_tx] = pucch_tx_power; + ue->tx_total_RE[nr_slot_tx] = nb_of_prbs*N_SC_RB; + + int tx_amp; + + /* + tx_amp = nr_get_tx_amp(pucch_tx_power, + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + nb_of_prbs); + if (tx_amp == 0)*/ + // FIXME temporarly using fixed amplitude before pucch power control implementation revised + tx_amp = AMP; - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - NR_PUCCH_Resource_t *pucch_resource; - //NR_UE_MAC_INST_t *mac = get_mac_inst(0); + LOG_D(PHY,"Generation of PUCCH format %d at frame.slot %d.%d\n",pucch_pdu->format_type,proc->frame_tx,nr_slot_tx); - /* update current context */ - - int subframe_number = (proc->nr_tti_rx)/(ue->frame_parms.slots_per_subframe);//ttis_per_subframe); - nb_pucch_format_4_in_subframes[subframe_number] = 0; /* reset pucch format 4 counter at current rx position */ - - int dl_harq_pid = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid; - - if (dl_harq_pid < ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->number_harq_processes_for_pdsch) { - /* pucch indicator can be reseted in function get_downlink_ack so it should be get now */ - pucch_resource_indicator = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid]->harq_ack.pucch_resource_indicator; - } - - /* Part - I - * Collect feedback that should be transmitted at this nr_tti_tx : - * - ACK/NACK, SR, CSI (CQI, RI, ...) - */ - - sr_payload = 0; - - if (trigger_periodic_scheduling_request( ue, gNB_id, proc ) == 1) { - O_SR = 1; /* sr should be transmitted */ - if (ue->mac_enabled == 1) { - - /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */ - sr_payload = nr_ue_get_SR(Mod_id, - CC_id, - frame_tx, - gNB_id, - 0,//ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti, - nr_tti_tx); // nr_tti_rx used for meas gap - } - else { - sr_payload = 1; - } - } - - O_ACK = get_downlink_ack( ue, gNB_id, proc, &pucch_ack_payload, - &n_HARQ_ACK, reset_harq); // 1 to reset ACK/NACK status : 0 otherwise - - cqi_status = ((ue->cqi_report_config[gNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0) && - (nr_is_cqi_TXOp(ue,proc,gNB_id) == 1)); - - ri_status = ((ue->cqi_report_config[gNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) && - (nr_is_ri_TXOp(ue,proc,gNB_id) == 1)); - - csi_status = get_csi_nr(ue, gNB_id, &csi_payload); - - O_CSI = cqi_status + ri_status + csi_status; - - /* Part - II */ - /* if payload is empty or only negative SR -> no pucch transmission */ - - if(O_ACK == 0) { - N_UCI = O_SR + O_CSI; - if ((N_UCI == 0) || ((O_CSI == 0) && (sr_payload == 0))) { /* TS 38.213 9.2.4 UE procedure for reporting SR */ - NR_TST_PHY_PRINTF("PUCCH No feedback AbsSubframe %d.%d \n", frame_tx%1024, nr_tti_tx); - LOG_D(PHY,"PUCCH No feedback AbsSubframe %d.%d \n", frame_tx%1024, nr_tti_tx); - return (FALSE); - } - else { - /* a resource set and a resource should be find according to payload size */ - pucch_resource_set = find_pucch_resource_set( mac, gNB_id, N_UCI); - if (pucch_resource_set != MAX_NB_OF_PUCCH_RESOURCE_SETS) { - pucch_resource_indicator = 0; - pucch_resource_id = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set]->resourceList.list.array[pucch_resource_indicator][0]; /* get the first resource of the set */ - } - else { - LOG_W(PHY,"PUCCH no resource set found for CSI at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - O_CSI = 0; - csi_payload = 0; - } - - if (O_CSI == 0) { - /* only SR has to be send */ - /* in this case there is no DCI related to PUCCH parameters so pucch resource should be get from sr configuration */ - /* TS 38.213 9.2.4 UE procedure for reporting SR */ - pucch_resource_set = 0; /* force it to a valid value */ - if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[ue->scheduling_request_config_nr[gNB_id].active_sr_id] != NULL) { - pucch_resource_id = ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[ue->scheduling_request_config_nr[gNB_id].active_sr_id]->resource; - } - else { - LOG_E(PHY,"PUCCH No scheduling request configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(FALSE); - } + switch(pucch_pdu->format_type) { + case 0: + nr_generate_pucch0(ue, + ue->common_vars.txdataF, + &ue->frame_parms, + tx_amp, + nr_slot_tx, + pucch_pdu); + break; + case 1: + nr_generate_pucch1(ue, + ue->common_vars.txdataF, + &ue->frame_parms, + tx_amp, + nr_slot_tx, + pucch_pdu); + break; + case 2: + nr_generate_pucch2(ue, + ue->common_vars.txdataF, + &ue->frame_parms, + tx_amp, + nr_slot_tx, + pucch_pdu); + break; + case 3: + case 4: + nr_generate_pucch3_4(ue, + ue->common_vars.txdataF, + &ue->frame_parms, + tx_amp, + nr_slot_tx, + pucch_pdu); + break; } } - } - else { - N_UCI = O_SR + O_ACK + O_CSI; - } - - /* Part - III */ - /* Choice PUCCH format and its related parameters */ - pucch_format_nr_t format = pucch_format0_nr; - uint8_t starting_symbol_index=0; - uint8_t nb_symbols_total = 0; - uint8_t nb_symbols = 0; - uint16_t starting_prb = 0;; /* it can be considered as first hop on case of pucch hopping */ - uint16_t second_hop = 0; /* second part for pucch for hopping */ - uint8_t nb_of_prbs = 0; - int m_0 = 0; /* format 0 only */ - int m_CS = 0; /* for all format except for format 0 */ - int index_additional_dmrs = I_PUCCH_NO_ADDITIONAL_DMRS; - int index_hopping = I_PUCCH_NO_HOPPING; - int time_domain_occ = 0; - int occ_length = 0; - int occ_Index = 0; - - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid]->harq_ack; - - if (select_pucch_resource(ue, mac, gNB_id, N_UCI, pucch_resource_indicator, &initial_pucch_id, &pucch_resource_set, - &pucch_resource_id, harq_status) == TRUE) { - /* use of initial pucch configuration provided by system information 1 */ - /***********************************************************************/ - if (initial_pucch_id != NB_INITIAL_PUCCH_RESOURCE) { - format = initial_pucch_resource[initial_pucch_id].format; - starting_symbol_index = initial_pucch_resource[initial_pucch_id].startingSymbolIndex; - nb_symbols_total = initial_pucch_resource[initial_pucch_id].nrofSymbols; - - int N_CS = initial_pucch_resource[initial_pucch_id].nb_CS_indexes; - /* see TS 38213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */ - int RB_BWP_offset; - if (initial_pucch_id == 15) { - RB_BWP_offset = ue->systemInformationBlockType1_nr.N_BWP_SIZE/4; - } - else - { - RB_BWP_offset = initial_pucch_resource[initial_pucch_id].PRB_offset; - } - if (initial_pucch_id/8 == 0) { - starting_prb = RB_BWP_offset + (initial_pucch_id/N_CS); - second_hop = ue->systemInformationBlockType1_nr.N_BWP_SIZE - 1 - RB_BWP_offset - (initial_pucch_id/N_CS); - m_0 = initial_pucch_resource[initial_pucch_id].initial_CS_indexes[initial_pucch_id%N_CS]; - } - else if (initial_pucch_id/8 == 1) - { - starting_prb = RB_BWP_offset + (initial_pucch_id/N_CS); - second_hop = ue->systemInformationBlockType1_nr.N_BWP_SIZE - 1 - RB_BWP_offset - ((initial_pucch_id - 8)/N_CS); - m_0 = initial_pucch_resource[initial_pucch_id].initial_CS_indexes[(initial_pucch_id - 8)%N_CS]; - } - if ((ue->UE_mode[gNB_id] != PUSCH) && (O_ACK > 1)) { - O_ACK = 1; - pucch_ack_payload &= 0x1; /* take only first ack */ - LOG_W(PHY,"PUCCH ue is not expected to generate more than one HARQ-ACK at AbsSubframe %d.%d \n", frame_tx%1024, nr_tti_tx); - } - NR_TST_PHY_PRINTF("PUCCH common configuration with index %d \n", initial_pucch_id); - } - /* use dedicated pucch resource configuration */ - /**********************************************/ - else if ((pucch_resource_set != MAX_NB_OF_PUCCH_RESOURCE_SETS) && (pucch_resource_id != MAX_NB_OF_PUCCH_RESOURCES)) { - /* check that current configuration is supported */ - if ((mac->scg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH != NULL) - || (mac->scg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook != 1)) { - LOG_E(PHY,"PUCCH Unsupported cell group configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(FALSE); - } - else if (mac->scg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { - LOG_E(PHY,"PUCCH Unsupported code block group for serving cell config : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(FALSE); - } - pucch_resource = select_resource_by_id(pucch_resource_id, mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup); - format = pucch_resource->format.present; - nb_symbols_total = get_nb_symbols_pucch(pucch_resource, format); - starting_symbol_index = get_starting_symb_idx(pucch_resource, format); - starting_prb = pucch_resource->startingPRB; - second_hop = starting_prb; - if (format==pucch_format1_nr) - time_domain_occ = pucch_resource->format.choice.format1->timeDomainOCC; - if (format==pucch_format4_nr) { - occ_length = pucch_resource->format.choice.format4->occ_Length; - occ_Index = pucch_resource->format.choice.format4->occ_Index; - } - - m_0 = get_ics_pucch(pucch_resource, format); - AssertFatal(m_0 >= 0, "Invalid m_0\n"); - if (format == pucch_format3_nr) { - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3->choice.setup->additionalDMRS[0] == 1) { - index_additional_dmrs = I_PUCCH_ADDITIONAL_DMRS; - } - } - else if (format == pucch_format4_nr) { - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4->choice.setup->additionalDMRS[0] == 1) { - index_additional_dmrs = I_PUCCH_ADDITIONAL_DMRS; - } - } - - if ((format == pucch_format3_nr) || (format == pucch_format4_nr)) { - if (pucch_resource->intraSlotFrequencyHopping[0] == 1) { - index_hopping = I_PUCCH_HOPING; - } - } - - NR_TST_PHY_PRINTF("PUCCH dedicated configuration with resource index %d \n", pucch_resource_id); - } - } - else { - LOG_W(PHY,"PUCCH No PUCCH resource found at AbsSubframe %d.%d \n", frame_tx%1024, nr_tti_tx); - return (FALSE); - } - - int max_code_rate = 0; - int Q_m = BITS_PER_SYMBOL_QPSK; /* default pucch modulation type is QPSK with 2 bits per symbol */ - int N_sc_ctrl_RB = 0; - int O_CRC = 0; - - nb_symbols = nb_symbols_total; /* by default, it can be reduced due to symbols reserved for dmrs */ - pucch_resource = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList->list.array[pucch_resource_id]; - - switch(format) { - case pucch_format0_nr: - { - nb_of_prbs = 1; - N_sc_ctrl_RB = N_SC_RB; - break; - } - case pucch_format1_nr: - { - nb_of_prbs = 1; - N_sc_ctrl_RB = N_SC_RB; - break; - } - case pucch_format2_nr: - { - nb_of_prbs = pucch_resource->format.choice.format2->nrofPRBs; - N_sc_ctrl_RB = N_SC_RB - 4; - break; - } - case pucch_format3_nr: - { - nb_of_prbs = pucch_resource->format.choice.format3->nrofPRBs; - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3->choice.setup->pi2BPSK[0] == 1) { - Q_m = BITS_PER_SYMBOL_BPSK; /* set bpsk modulation type with 1 bit per modulation symbol */ - } - N_sc_ctrl_RB = N_SC_RB; - nb_symbols = nb_symbols_excluding_dmrs[nb_symbols_total-4][index_additional_dmrs][index_hopping]; - break; - } - case pucch_format4_nr: - { - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4->choice.setup->pi2BPSK[0] == 1) { - Q_m = BITS_PER_SYMBOL_BPSK; /* set bpsk modulation type with 1 bit per modulation symbol */ - } - nb_symbols = nb_symbols_excluding_dmrs[nb_symbols_total-4][index_additional_dmrs][index_hopping]; - nb_of_prbs = 1; - subframe_number = nr_tti_tx/(ue->frame_parms.slots_per_subframe);//ttis_per_subframe); - nb_pucch_format_4_in_subframes[subframe_number]++; /* increment number of transmit pucch 4 in current subframe */ - NR_TST_PHY_PRINTF("PUCCH Number of pucch format 4 in subframe %d is %d \n", subframe_number, nb_pucch_format_4_in_subframes[subframe_number]); - N_sc_ctrl_RB = N_SC_RB/(nb_pucch_format_4_in_subframes[subframe_number]); - break; - } - } - - /* TS 38.213 9.2.5.2 UE procedure for multiplexing HARQ-ACK/SR and CSI */ - /* drop CSI report if simultaneous HARQ-ACK/SR and periodic/semi-periodic CSI cannot be transmitted at the same time */ - if (format != pucch_format0_nr) { - - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1 != NULL) { - max_code_rate = code_rate_r_time_100[mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1->choice.setup->maxCodeRate[0]]; /* it is code rate * 10 */ - - if ((O_ACK != 0) && (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1->choice.setup->simultaneousHARQ_ACK_CSI[0] == 0)) { - N_UCI = N_UCI - O_CSI; - O_CSI = cqi_status = ri_status = 0; - csi_payload = 0; /* csi should be dropped in this case */ - } - } - - /* TS 38.212 6.3.1.2 Code block segmentation and CRC attachment */ - /* crc attachment can be done depending of payload size */ - if (N_UCI < 11) { - O_CRC = 0; /* no additional crc bits */ - } - else if ((N_UCI >= 12) && (N_UCI <= 19)) { - O_CRC = 6; /* number of additional crc bits */ - } - else if (N_UCI >= 20) { - O_CRC = 11; /* number of additional crc bits */ - } - - N_UCI = N_UCI + O_CRC; - - /* for format 2 and 3, number of prb should be adjusted to minimum value which cope to information size */ - if (nb_of_prbs > 1 ) { - int nb_prb_min = 0; - int payload_in_bits; - do { - nb_prb_min++; - payload_in_bits = (nb_prb_min * N_sc_ctrl_RB * nb_symbols * Q_m * max_code_rate)/100; /* code rate has been multiplied by 100 */ - NR_TST_PHY_PRINTF("PUCCH Adjust number of prb : (N_UCI : %d ) (payload_in_bits : %d) (N_sc_ctrl_RB : %d) (nb_symbols : %d) (Q_m : %d) (max_code_rate*100 : %d) \n", - N_UCI, payload_in_bits, N_sc_ctrl_RB, nb_symbols, Q_m, max_code_rate); - } while (N_UCI > payload_in_bits); - - if (nb_prb_min > nb_of_prbs) { - LOG_E(PHY,"PUCCH Number of prbs too small for current pucch bits to transmit : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - else { - nb_of_prbs = nb_prb_min; - } - } - - /* TS 38.213 9.2.4 for a positive SR transmission, payload b(0) = 0 */ - if ((O_SR == 1) && (format == pucch_format1_nr)) { - sr_payload = 0; - } - } - else { /* only format 0 here */ - if ((O_SR == 0) && (O_CSI == 0)) { /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */ - if (O_ACK == 1) { - m_CS = sequence_cyclic_shift_1_harq_ack_bit[pucch_ack_payload & 0x1]; /* only harq of 1 bit */ - } - else { - m_CS = sequence_cyclic_shift_2_harq_ack_bits[pucch_ack_payload & 0x3]; /* only harq with 2 bits */ - } - } - else if ((O_SR == 1) && (O_CSI == 0)) { /* SR + eventually ack are transmitted TS 36.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR */ - if (sr_payload == 1) { /* positive scheduling request */ - if (O_ACK == 1) { - m_CS = sequence_cyclic_shift_1_harq_ack_bit_positive_sr[pucch_ack_payload & 0x1]; /* positive SR and harq of 1 bit */ - } - else if (O_ACK == 2) { - m_CS = sequence_cyclic_shift_2_harq_ack_bits_positive_sr[pucch_ack_payload & 0x3]; /* positive SR and harq with 2 bits */ - } - else { - m_CS = 0; /* only positive SR */ - } - } - } - N_UCI = O_SR = O_ACK = 0; - pucch_payload = sr_payload = pucch_ack_payload = 0; /* no data for format 0 */ - } - - /* TS 38.212 6.3.1 Uplink control information on PUCCH */ - /* information concatenation of payload */ - /* CSI SR HARQ-ACK */ - /* bit order of payload of size n : a(n)....................................a(0) */ - /* a(0) is the LSB and a(n) the MSB <--------><--------------><------------><----------> */ - /* O_CRC O_CSI O_SR O_ACK */ - /* */ - /* remark: crc is not part of payload, it is later added by block coding. */ - - if (N_UCI > (sizeof(uint64_t)*8)) { - LOG_E(PHY,"PUCCH number of UCI bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(0); - } - - pucch_payload = pucch_payload | (csi_payload << (O_ACK + O_SR)) | (sr_payload << O_ACK) | pucch_ack_payload; - - NR_TST_PHY_PRINTF("PUCCH ( AbsSubframe : %d.%d ) ( total payload size %d data 0x%02x ) ( ack length %d data 0x%02x ) ( sr length %d value %d ) ( csi length %d data : 0x%02x ) \n", - frame_tx%1024, nr_tti_tx, N_UCI, pucch_payload, O_ACK, pucch_ack_payload, O_SR, sr_payload, csi_status, csi_payload); - - NR_TST_PHY_PRINTF("PUCCH ( format : %d ) ( modulation : %s ) ( nb prb : %d ) ( nb symbols total: %d ) ( nb symbols : %d ) ( max code rate*100 : %d ) ( starting_symbol_index : %d ) \n", - format, (Q_m == BITS_PER_SYMBOL_QPSK ? " QPSK " : " BPSK "), nb_of_prbs, nb_symbols_total, nb_symbols, max_code_rate, starting_symbol_index); - - NR_TST_PHY_PRINTF("PUCCH ( starting_prb : %d ) ( second_hop : %d ) ( m_0 : %d ) ( m_CS : %d ) ( time_domain_occ %d ) (occ_length : %d ) ( occ_Index : %d ) \n", - starting_prb, second_hop, m_0, m_CS, time_domain_occ, occ_length, occ_Index); - - /* Part - IV */ - /* Generate PUCCH signal according to its format and parameters */ - ue->generate_ul_signal[gNB_id] = 1; - - int16_t pucch_tx_power = get_pucch_tx_power_ue( ue, gNB_id, proc, format, - nb_of_prbs, N_sc_ctrl_RB, nb_symbols, N_UCI, O_SR, O_CSI, O_ACK, - O_CRC, n_HARQ_ACK); - - /* set tx power */ - ue->tx_power_dBm[nr_tti_tx] = pucch_tx_power; - ue->tx_total_RE[nr_tti_tx] = nb_of_prbs*N_SC_RB; - - int tx_amp; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - - tx_amp = nr_get_tx_amp(pucch_tx_power, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - nb_of_prbs); -#else - tx_amp = AMP; -#endif - - switch(format) { - case pucch_format0_nr: - { - nr_generate_pucch0(ue,ue->common_vars.txdataF, - &ue->frame_parms, - mac->ULbwp[bwp_id-1]->bwp_Common->pucch_ConfigCommon->choice.setup->pucch_GroupHopping, - mac->ULbwp[bwp_id-1]->bwp_Common->pucch_ConfigCommon->choice.setup->hoppingId[0], - tx_amp, - nr_tti_tx, - (uint8_t)m_0, - (uint8_t)m_CS, - nb_symbols_total, - starting_symbol_index, - starting_prb); - break; - } - case pucch_format1_nr: - { - nr_generate_pucch1(ue,ue->common_vars.txdataF, - &ue->frame_parms, - &ue->pucch_config_dedicated[gNB_id], - pucch_payload, - tx_amp, - nr_tti_tx, - (uint8_t)m_0, - nb_symbols_total, - starting_symbol_index, - starting_prb, - second_hop, - (uint8_t)time_domain_occ, - (uint8_t)N_UCI); - break; - } - case pucch_format2_nr: - { - nr_generate_pucch2(ue, - crnti, - dmrs_scrambling_id, - data_scrambling_id, - ue->common_vars.txdataF, - &ue->frame_parms, - &ue->pucch_config_dedicated[gNB_id], - pucch_payload, - tx_amp, - nr_tti_tx, - nb_symbols_total, - starting_symbol_index, - nb_of_prbs, - starting_prb, - (uint8_t)N_UCI); - break; - } - case pucch_format3_nr: - case pucch_format4_nr: - { - nr_generate_pucch3_4(ue, - 0,//ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti, - ue->common_vars.txdataF, - &ue->frame_parms, - format, - &ue->pucch_config_dedicated[gNB_id], - pucch_payload, - tx_amp, - nr_tti_tx, - nb_symbols_total, - starting_symbol_index, - nb_of_prbs, - starting_prb, - second_hop, - (uint8_t)N_UCI, - (uint8_t)occ_length, - (uint8_t)occ_Index); - break; - } - } - return (TRUE); -} - -/******************************************************************* -* -* NAME : get_downlink_ack -* -* PARAMETERS : ue context -* processing slots of reception/transmission -* gNB_id identifier -* -* RETURN : o_ACK acknowledgment data -* o_ACK_number_bits number of bits for acknowledgment -* -* DESCRIPTION : return acknowledgment value -* TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination -* -* --+--------+-------+--------+-------+--- ---+-------+-- -* | PDCCH1 | | PDCCH2 |PDCCH3 | | PUCCH | -* --+--------+-------+--------+-------+--- ---+-------+-- -* DAI_DL 1 2 3 ACK for -* V V V PDCCH1, PDDCH2 and PCCH3 -* | | | ^ -* +-----------------+-------+---------------+ -* -* PDCCH1, PDCCH2 and PDCCH3 are PDCCH monitoring occasions -* M is the total of monitoring occasions -* -*********************************************************************/ - -uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, - uint32_t *o_ACK, int *n_HARQ_ACK, - bool do_reset) // 1 to reset ACK/NACK status : 0 otherwise -{ - NR_UE_HARQ_STATUS_t *harq_status; - uint32_t ack_data[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; - uint32_t dai[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for serving cell */ - uint32_t dai_total[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for multiple cells */ - int number_harq_feedback = 0; - uint32_t dai_current = 0; - uint32_t dai_max = 0; - int number_pid_dl = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->number_harq_processes_for_pdsch; - bool two_transport_blocks = FALSE; - int number_of_code_word = 1; - int U_DAI_c = 0; - int N_m_c_rx = 0; - int V_DAI_m_DL = 0; - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - - if (mac->DLbwp[0] == NULL) return 0; - - if (mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0] == 2) { - two_transport_blocks = TRUE; - number_of_code_word = 2; - } - else { - number_of_code_word = 1; - } - - if (ue->n_connected_eNB > 1) { - LOG_E(PHY,"PUCCH ACK feedback is not implemented for mutiple gNB cells : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - - /* look for dl acknowledgment which should be done on current uplink slot */ - for (int code_word = 0; code_word < number_of_code_word; code_word++) { - - for (int dl_harq_pid = 0; dl_harq_pid < number_pid_dl; dl_harq_pid++) { - - for (int thread_idx = 0; thread_idx < RX_NB_TH; thread_idx++) { - - harq_status = &ue->dlsch[thread_idx][gNB_id][code_word]->harq_processes[dl_harq_pid]->harq_ack; - - /* check if current tx slot should transmit downlink acknowlegment */ - if (harq_status->slot_for_feedback_ack == proc->nr_tti_tx) { - - if (harq_status->ack == DL_ACKNACK_NO_SET) { - LOG_E(PHY,"PUCCH Downlink acknowledgment has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - else if (harq_status->vDAI_DL == DL_DAI_NO_SET) { - LOG_E(PHY,"PUCCH Downlink DAI has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - else if (harq_status->vDAI_DL > NR_DL_MAX_DAI) { - LOG_E(PHY,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - else if (harq_status->send_harq_status == 0) { - LOG_E(PHY,"PUCCH Downlink ack can not be transmitted : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(0); - } - else { - - dai_current = harq_status->vDAI_DL+1; // DCI DAI to counter DAI conversion - - if (dai_current == 0) { - LOG_E(PHY,"PUCCH Downlink dai is invalid : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(0); - } else if (dai_current > dai_max) { - dai_max = dai_current; - } - - number_harq_feedback++; - ack_data[code_word][dai_current - 1] = harq_status->ack; - dai[code_word][dai_current - 1] = dai_current; - } - if (do_reset == TRUE) { - init_downlink_harq_status(ue->dlsch[thread_idx][gNB_id][code_word]->harq_processes[dl_harq_pid]); - } - } - } - } - } - - /* no any ack to transmit */ - if (number_harq_feedback == 0) { - *n_HARQ_ACK = 0; - return(0); - } - else if (number_harq_feedback > (sizeof(uint32_t)*8)) { - LOG_E(PHY,"PUCCH number of ack bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(0); - } - - /* for computing n_HARQ_ACK for power */ - V_DAI_m_DL = dai_max; - U_DAI_c = number_harq_feedback/number_of_code_word; - N_m_c_rx = number_harq_feedback; - int N_SPS_c = 0; /* FFS TODO_NR multicells and SPS are not supported at the moment */ - if (mac->scg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH == NULL) { - int N_TB_max_DL = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0]; - *n_HARQ_ACK = (((V_DAI_m_DL - U_DAI_c)%4) * N_TB_max_DL) + N_m_c_rx + N_SPS_c; - NR_TST_PHY_PRINTF("PUCCH power n(%d) = ( V(%d) - U(%d) )mod4 * N_TB(%d) + N(%d) \n", *n_HARQ_ACK, V_DAI_m_DL, U_DAI_c, N_TB_max_DL, N_m_c_rx); - } - - /* - * For a monitoring occasion of a PDCCH with DCI format 1_0 or DCI format 1_1 in at least one serving cell, - * when a UE receives a PDSCH with one transport block and the value of higher layer parameter maxNrofCodeWordsScheduledByDCI is 2, - * the HARQ-ACK response is associated with the first transport block and the UE generates a NACK for the second transport block - * if spatial bundling is not applied (HARQ-ACK-spatial-bundling-PUCCH = FALSE) and generates HARQ-ACK value of ACK for the second - * transport block if spatial bundling is applied. - */ - - for (int code_word = 0; code_word < number_of_code_word; code_word++) { - for (uint32_t i = 0; i < dai_max ; i++ ) { - if (dai[code_word][i] != i + 1) { /* fill table with consistent value for each dai */ - dai[code_word][i] = i + 1; /* it covers case for which PDCCH DCI has not been successfully decoded and so it has been missed */ - ack_data[code_word][i] = 0; /* nack data transport block which has been missed */ - number_harq_feedback++; - } - if (two_transport_blocks == TRUE) { - dai_total[code_word][i] = dai[code_word][i]; /* for a single cell, dai_total is the same as dai of first cell */ - } - } - } - - int M = dai_max; - int j = 0; - uint32_t V_temp = 0; - uint32_t V_temp2 = 0; - int O_ACK = 0; - int O_bit_number_cw0 = 0; - int O_bit_number_cw1 = 0; - - for (int m = 0; m < M ; m++) { - - if (dai[0][m] <= V_temp) { - j = j + 1; - } - - V_temp = dai[0][m]; /* value of the counter DAI for format 1_0 and format 1_1 on serving cell c */ - - if (dai_total[0][m] == 0) { - V_temp2 = dai[0][m]; - } else { - V_temp2 = dai[1][m]; /* second code word has been received */ - O_bit_number_cw1 = (8 * j) + 2*(V_temp - 1) + 1; - *o_ACK = *o_ACK | (ack_data[1][m] << O_bit_number_cw1); - } - - if (two_transport_blocks == TRUE) { - O_bit_number_cw0 = (8 * j) + 2*(V_temp - 1); - } - else { - O_bit_number_cw0 = (4 * j) + (V_temp - 1); - } - - *o_ACK = *o_ACK | (ack_data[0][m] << O_bit_number_cw0); - } - - if (V_temp2 < V_temp) { - j = j + 1; - } - - if (two_transport_blocks == TRUE) { - O_ACK = 2 * ( 4 * j + V_temp2); /* for two transport blocks */ - } - else { - O_ACK = 4 * j + V_temp2; /* only one transport block */ - } - - if (number_harq_feedback != O_ACK) { - LOG_E(PHY,"PUCCH Error for number of bits for acknowledgment : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - - return(number_harq_feedback); -} - -/******************************************************************* -* -* NAME : select_pucch_format -* -* PARAMETERS : ue context -* processing slots of reception/transmission -* gNB_id identifier -* -* RETURN : TRUE a valid resource has been found -* -* DESCRIPTION : return tx harq process identifier for given transmission slot -* TS 38.213 9.2.1 PUCCH Resource Sets -* TS 38.213 9.2.2 PUCCH Formats for UCI transmission -* In the case of pucch for scheduling request only, resource is already get from scheduling request configuration -* -*********************************************************************/ - -boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size, int pucch_resource_indicator, - int *initial_pucch_id, int *resource_set_id, int *resource_id, NR_UE_HARQ_STATUS_t *harq_status) -{ - boolean_t resource_set_found = FALSE; - int nb_symbols_for_tx = 0; - int current_resource_id = MAX_NB_OF_PUCCH_RESOURCES; - pucch_format_nr_t format_pucch; - int ready_pucch_resource_id = FALSE; /* in the case that it is already given */ - NR_PUCCH_Resource_t *pucch_resource; - - /* ini values to unset */ - *initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; - //*resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS; - //*resource_id = MAX_NB_OF_PUCCH_RESOURCES; - - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[0] == NULL) { - - /* No resource set has been already configured so pucch_configCommon from Sib1 should be used in this case */ - - if (ue->UE_mode[gNB_id] != PUSCH) { - *initial_pucch_id = mac->ULbwp[bwp_id-1]->bwp_Common->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon[0]; - if (*initial_pucch_id >= NB_INITIAL_PUCCH_RESOURCE) { - LOG_E(PHY,"PUCCH Invalid initial resource index : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - *initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; - return (FALSE); - } - } - else { - /* see TS 38.213 9.2.1 PUCCH Resource Sets */ - int delta_PRI = harq_status->pucch_resource_indicator; - // n_CCE can be obtained from ue->dci_ind.dci_list[i].n_CCE. FIXME!!! - // N_CCE can be obtained from ue->dci_ind.dci_list[i].N_CCE. FIXME!!! - //int n_CCE = ue->dci_ind.dci_list[0].n_CCE; - //int N_CCE = ue->dci_ind.dci_list[0].N_CCE; - int n_CCE_0 = harq_status->n_CCE; - int N_CCE_0 = harq_status->N_CCE; - if (N_CCE_0 == 0) { - LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - int r_PUCCH = ((2 * n_CCE_0)/N_CCE_0) + (2 * delta_PRI); - *initial_pucch_id = r_PUCCH; - } - nb_symbols_for_tx = initial_pucch_resource[*initial_pucch_id].nrofSymbols; - format_pucch = initial_pucch_resource[*initial_pucch_id].format; - if (check_pucch_format(mac, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) { - return (TRUE); - } - else { - LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - else { - /* dedicated resources have been configured */ - int pucch_resource_set_id = 0; - if (*resource_set_id == MAX_NB_OF_PUCCH_RESOURCE_SETS) { - /* from TS 38.331 field maxPayloadMinus1 - -- Maximum number of payload bits minus 1 that the UE may transmit using this PUCCH resource set. In a PUCCH occurrence, the UE - -- chooses the first of its PUCCH-ResourceSet which supports the number of bits that the UE wants to transmit. - -- The field is not present in the first set (Set0) since the maximum Size of Set0 is specified to be 3 bit. - -- The field is not present in the last configured set since the UE derives its maximum payload size as specified in 38.213. - -- This field can take integer values that are multiples of 4. Corresponds to L1 parameter 'N_2' or 'N_3' (see 38.213, section 9.2) - */ - /* look for the first resource set which supports uci_size number of bits for payload */ - pucch_resource_set_id = find_pucch_resource_set(mac, gNB_id, uci_size); - if (pucch_resource_set_id != MAX_NB_OF_PUCCH_RESOURCE_SETS) { - resource_set_found = TRUE; - } - } - else { - /* a valid resource has already be found outside this function */ - resource_set_found = TRUE; - ready_pucch_resource_id = TRUE; - //pucch_resource_indicator = pucch_resource_indicator; - } - - if (resource_set_found == TRUE) { - if (pucch_resource_indicator < MAX_PUCCH_RESOURCE_INDICATOR) { - /* check if resource indexing by pucch_resource_indicator of this set is compatible */ - if ((ready_pucch_resource_id == TRUE) || (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.array[pucch_resource_indicator][0] != MAX_NB_OF_PUCCH_RESOURCES)) { - - if (ready_pucch_resource_id == TRUE) { - current_resource_id = *resource_id; - } - else { - int R_PUCCH = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.count; - /* is it the first resource and its size exceeds 8 */ - if ((pucch_resource_set_id == 0) - && (R_PUCCH > MAX_NB_OF_PUCCH_RESOURCES_PER_SET_NOT_0)) { - /* see TS 38.213 9.2.3 UE procedure for reporting HARQ-ACK */ - int delta_PRI = pucch_resource_indicator; - int n_CCE_p = harq_status->n_CCE; - int N_CCE_p = harq_status->N_CCE; - int r_PUCCH; - if (N_CCE_p == 0) { - LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - if (pucch_resource_set_id < (R_PUCCH%8)) { - r_PUCCH = ((n_CCE_p * (R_PUCCH/8))/N_CCE_p) + (delta_PRI*(R_PUCCH/8)); - } - else { - r_PUCCH = ((n_CCE_p * (R_PUCCH/8))/N_CCE_p) + (delta_PRI*(R_PUCCH/8)) + (R_PUCCH%8); - } - current_resource_id = r_PUCCH; - } - else { - current_resource_id = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.array[pucch_resource_indicator][0]; - } - } - - /*uint8_t pucch_resource_count = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList.list.count; - for (uint8_t i=0; iULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList.list.array[i]->pucch_ResourceId == current_resource_id) - pucch_resource = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList.list.array[i]; - }*/ - - pucch_resource = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList->list.array[current_resource_id]; - if (pucch_resource != NULL) { - format_pucch = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList->list.array[current_resource_id]->format.present; - nb_symbols_for_tx = get_nb_symbols_pucch(pucch_resource, format_pucch); - - if (check_pucch_format(mac, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) { - *resource_set_id = pucch_resource_set_id; - *resource_id = current_resource_id; - return (TRUE); - } - else { - LOG_E(PHY,"PUCCH Found format no compatible with payload size and symbol length : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - } - else { - LOG_E(PHY,"PUCCH Undefined Resource related to pucch resource indicator: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - else { - LOG_E(PHY,"PUCCH Invalid pucch resource indicator: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - - /* check that a resource has been found */ - if (*resource_set_id == MAX_NB_OF_PUCCH_RESOURCES) { - LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - return (FALSE); -} - -/******************************************************************* -* -* NAME : find_pucch_resource_set -* -* PARAMETERS : ue context -* gNB_id identifier -* -* -* RETURN : harq process identifier -* -* DESCRIPTION : return tx harq process identifier for given transmission slot -* YS 38.213 9.2.2 PUCCH Formats for UCI transmission -* -*********************************************************************/ - -int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size) -{ - int pucch_resource_set_id = 0; - long *pucch_max_pl_bits = NULL; - - /* from TS 38.331 field maxPayloadMinus1 - -- Maximum number of payload bits minus 1 that the UE may transmit using this PUCCH resource set. In a PUCCH occurrence, the UE - -- chooses the first of its PUCCH-ResourceSet which supports the number of bits that the UE wants to transmit. - -- The field is not present in the first set (Set0) since the maximum Size of Set0 is specified to be 3 bit. - -- The field is not present in the last configured set since the UE derives its maximum payload size as specified in 38.213. - -- This field can take integer values that are multiples of 4. Corresponds to L1 parameter 'N_2' or 'N_3' (see 38.213, section 9.2) - */ - /* look for the first resource set which supports uci_size number of bits for payload */ - while (pucch_resource_set_id < MAX_NB_OF_PUCCH_RESOURCE_SETS) { - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL) { - pucch_max_pl_bits = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->maxPayloadMinus1; - if (uci_size <= (((pucch_max_pl_bits != NULL) ? *pucch_max_pl_bits : 1706) + 1)) { - NR_TST_PHY_PRINTF("PUCCH found resource set %d \n", pucch_resource_set_id); - return (pucch_resource_set_id); - break; - } - } - pucch_resource_set_id++; - } - - pucch_resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS; - - return (pucch_resource_set_id); -} - -/******************************************************************* -* -* NAME : check_pucch_format -* -* PARAMETERS : ue context -* processing slots of reception/transmission -* gNB_id identifier -* -* RETURN : harq process identifier -* -* DESCRIPTION : return tx harq process identifier for given transmission slot -* YS 38.213 9.2.2 PUCCH Formats for UCI transmission -* -*********************************************************************/ - -boolean_t check_pucch_format(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, pucch_format_nr_t format_pucch, int nb_symbols_for_tx, int uci_size) -{ - pucch_format_nr_t selected_pucch_format; - pucch_format_nr_t selected_pucch_format_second; - NR_SetupRelease_PUCCH_FormatConfig_t *identified_format = NULL; - - switch (format_pucch) { - case pucch_format1_nr: - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1 != NULL) - identified_format = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1; - break; - - case pucch_format2_nr: - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format2 != NULL) - identified_format = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format2; - break; - - case pucch_format3_nr: - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3 != NULL) - identified_format = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3; - break; - - case pucch_format4_nr: - if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4 != NULL) - identified_format = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4; - break; - - default: - break; - } - - if ((identified_format != NULL) && (identified_format->choice.setup->nrofSlots[0] != 1)) { - LOG_E(PHY,"PUCCH not implemented multislots transmission : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - - if (nb_symbols_for_tx <= 2) { - if (uci_size <= 2) { - selected_pucch_format = pucch_format0_nr; - selected_pucch_format_second = selected_pucch_format; - } - else { - selected_pucch_format = pucch_format2_nr; - selected_pucch_format_second = selected_pucch_format; - } - } - else { - if (nb_symbols_for_tx >= 4) { - if (uci_size <= 2) { - selected_pucch_format = pucch_format1_nr; - selected_pucch_format_second = selected_pucch_format; - } - else { - selected_pucch_format = pucch_format3_nr; /* in this case choice can be done between two formats */ - selected_pucch_format_second = pucch_format4_nr; - } - } - else { - LOG_D(PHY,"PUCCH Undefined PUCCH format : set PUCCH to format 4 : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } - - NR_TST_PHY_PRINTF("PUCCH format %d nb symbols total %d uci size %d selected format %d \n", format_pucch, nb_symbols_for_tx, uci_size, selected_pucch_format); - - if (format_pucch != selected_pucch_format) { - if (format_pucch != selected_pucch_format_second) { - NR_TST_PHY_PRINTF("PUCCH mismatched of selected format: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - LOG_D(PHY,"PUCCH format mismatched of selected format: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - else { - return (TRUE); - } - } - else { - return (TRUE); + pucch_vars->active[i] = false; } } -/******************************************************************* -* -* NAME : trigger_periodic_scheduling_request -* -* PARAMETERS : pointer to resource set -* -* RETURN : 1 if peridic scheduling request is triggered -* 0 no periodic scheduling request -* -* DESCRIPTION : TS 38.213 9.2.4 UE procedure for reporting SR -* -*********************************************************************/ -int trigger_periodic_scheduling_request(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc) -{ - const int max_sr_periodicity[NB_NUMEROLOGIES_NR] = { 80, 160, 320, 640, 640 }; - - int active_scheduling_request = ue->scheduling_request_config_nr[gNB_id].active_sr_id; - - /* is there any valid scheduling request configuration */ - if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request] == NULL) { - return (0); - } - - if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->periodicity < 2) { - LOG_W(PHY,"PUCCH Not supported scheduling request period smaller than 1 slot : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - - int16_t SR_periodicity = scheduling_request_periodicity[ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->periodicity]; - uint16_t SR_offset = ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->offset; - - if (SR_periodicity > max_sr_periodicity[ue->frame_parms.numerology_index]) { - LOG_W(PHY,"PUCCH Invalid scheduling request period : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); - } - - if (SR_offset > SR_periodicity) { - LOG_E(PHY,"PUCCH SR offset %d is greater than SR periodicity %d : at line %d in function %s of file %s \n", SR_offset, SR_periodicity, LINE_FILE , __func__, FILE_NAME); - return (0); - } - else if (SR_periodicity == 1) { - return (1); /* period is slot */ - } - - int16_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * ue->frame_parms.slots_per_subframe;//ttis_per_subframe; - if (((proc->frame_tx * N_slot_frame) + proc->nr_tti_tx - SR_offset)%SR_periodicity == 0) { - return (1); - } - else { - return (0); - } -} - -/******************************************************************* -* -* NAME : get_csi_nr -* PARAMETERS : ue context -* processing slots of reception/transmission -* gNB_id identifier -* -* RETURN : size of csi payload -* -* DESCRIPTION : CSI management is not already implemented -* so it has been simulated thank to two functions: -* - set_csi_nr -* - get_csi_nr -* -*********************************************************************/ int dummy_csi_status = 0; uint32_t dummy_csi_payload = 0; -/* FFS TODO_NR code that should be developed */ - -int get_csi_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint32_t *csi_payload) -{ - VOID_PARAMETER ue; - VOID_PARAMETER gNB_id; - - if (dummy_csi_status == 0) { - *csi_payload = 0; - } - else { - *csi_payload = dummy_csi_payload; - } - - return (dummy_csi_status); -} /* FFS TODO_NR code that should be removed */ @@ -1326,6 +353,9 @@ int get_ics_pucch(NR_PUCCH_Resource_t *pucch_resource, pucch_format_nr_t format_ case pucch_format1_nr: return pucch_resource->format.choice.format1->initialCyclicShift; + + case pucch_format2_nr: + return 0; default: return -1; diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h index 089fae9f55..37e24f43bc 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h @@ -41,8 +41,6 @@ /************** INCLUDE *******************************************/ #include "PHY/defs_nr_UE.h" -#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" -#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h" #include "RRC/NR_UE/rrc_proto.h" #ifdef DEFINE_VARIABLES_PUCCH_UE_NR_H @@ -58,180 +56,13 @@ #define BITS_PER_SYMBOL_BPSK (1) /* 1 bit per symbol for bpsk modulation */ #define BITS_PER_SYMBOL_QPSK (2) /* 2 bits per symbol for bpsk modulation */ -/************** VARIABLES *****************************************/ - -/* TS 36.213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */ -const initial_pucch_resource_t initial_pucch_resource[NB_INITIAL_PUCCH_RESOURCE] -#ifdef INIT_VARIABLES_PUCCH_UE_NR_H -= -{ -/* format first symbol Number of symbols PRB offset nb index for set of initial CS */ -/* 0 */ { pucch_format0_nr, 12, 2, 0, 2, { 0, 3, 0, 0 } }, -/* 1 */ { pucch_format0_nr, 12, 2, 0, 3, { 0, 4, 8, 0 } }, -/* 2 */ { pucch_format0_nr, 12, 2, 3, 3, { 0, 4, 8, 0 } }, -/* 3 */ { pucch_format1_nr, 10, 4, 0, 2, { 0, 6, 0, 0 } }, -/* 4 */ { pucch_format1_nr, 10, 4, 0, 4, { 0, 3, 6, 9 } }, -/* 5 */ { pucch_format1_nr, 10, 4, 2, 4, { 0, 3, 6, 9 } }, -/* 6 */ { pucch_format1_nr, 10, 4, 4, 4, { 0, 3, 6, 9 } }, -/* 7 */ { pucch_format1_nr, 4, 10, 0, 2, { 0, 6, 0, 0 } }, -/* 8 */ { pucch_format1_nr, 4, 10, 0, 4, { 0, 3, 6, 9 } }, -/* 9 */ { pucch_format1_nr, 4, 10, 2, 4, { 0, 3, 6, 9 } }, -/* 10 */ { pucch_format1_nr, 4, 10, 4, 4, { 0, 3, 6, 9 } }, -/* 11 */ { pucch_format1_nr, 0, 14, 0, 2, { 0, 6, 0, 0 } }, -/* 12 */ { pucch_format1_nr, 0, 14, 0, 4, { 0, 3, 6, 9 } }, -/* 13 */ { pucch_format1_nr, 0, 14, 2, 4, { 0, 3, 6, 9 } }, -/* 14 */ { pucch_format1_nr, 0, 14, 4, 4, { 0, 3, 6, 9 } }, -/* 15 */ { pucch_format1_nr, 0, 14, 0, 4, { 0, 3, 6, 9 } }, -} -#endif -; - -/* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */ -const int sequence_cyclic_shift_1_harq_ack_bit[2] -#ifdef INIT_VARIABLES_PUCCH_UE_NR_H -/* HARQ-ACK Value 0 1 */ -/* Sequence cyclic shift */ = { 0, 6 } -#endif -; - -/* TS 38.213 Table 9.2.3-4: Mapping of values for two HARQ-ACK bits to sequences */ -const int sequence_cyclic_shift_2_harq_ack_bits[4] -#ifdef INIT_VARIABLES_PUCCH_UE_NR_H -/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */ -/* Sequence cyclic shift */ = { 0, 3, 9, 6 } -#endif -; - -/* TS 36.213 Table 9.2.5-1: Mapping of values for one HARQ-ACK bit and positive SR to sequences */ -const int sequence_cyclic_shift_1_harq_ack_bit_positive_sr[2] -#ifdef INIT_VARIABLES_PUCCH_UE_NR_H -/* HARQ-ACK Value 0 1 */ -/* Sequence cyclic shift */ = { 3, 9 } -#endif -; - -/* TS 36.213 Table 9.2.5-2: Mapping of values for two HARQ-ACK bits and positive SR to sequences */ -const int sequence_cyclic_shift_2_harq_ack_bits_positive_sr[4] -#ifdef INIT_VARIABLES_PUCCH_UE_NR_H -/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */ -/* Sequence cyclic shift */ = { 1, 4, 10, 7 } -#endif -; - -/* TS 36.213 Table 9.2.5.2-1: Code rate corresponding to higher layer parameter PUCCH-F2-maximum-coderate, */ -/* or PUCCH-F3-maximum-coderate, or PUCCH-F4-maximum-coderate */ -/* add one additional element set to 0 for parsing the array until this end */ -/* stored values are code rates * 100 */ -const int code_rate_r_time_100[8] -#ifdef INIT_VARIABLES_PUCCH_UE_NR_H -= { (0.08 * 100), (0.15 * 100), (0.25*100), (0.35*100), (0.45*100), (0.60*100), (0.80*100), 0 } -#endif -; - -#define NB_SYMBOL_MINUS_FOUR (11) -#define I_PUCCH_NO_ADDITIONAL_DMRS (0) -#define I_PUCCH_ADDITIONAL_DMRS (1) -#define I_PUCCH_NO_HOPPING (0) -#define I_PUCCH_HOPING (1) - -/* TS 38.211 Table 6.4.1.3.3.2-1: DM-RS positions for PUCCH format 3 and 4 */ -const int nb_symbols_excluding_dmrs[NB_SYMBOL_MINUS_FOUR][2][2] -#ifdef INIT_VARIABLES_PUCCH_UE_NR_H -= { -/* No additional DMRS Additional DMRS */ -/* PUCCH length No hopping hopping No hopping hopping */ -/* index 0 1 0 1 */ -/* 4 */ {{ 3 , 2 } , { 3 , 2 }}, -/* 5 */ {{ 3 , 3 } , { 3 , 3 }}, -/* 6 */ {{ 4 , 4 } , { 4 , 4 }}, -/* 7 */ {{ 5 , 5 } , { 5 , 5 }}, -/* 8 */ {{ 6 , 6 } , { 6 , 6 }}, -/* 9 */ {{ 7 , 7 } , { 7 , 7 }}, -/* 10 */ {{ 8 , 8 } , { 6 , 6 }}, -/* 11 */ {{ 9 , 9 } , { 7 , 7 }}, -/* 12 */ {{ 10 , 10 } , { 8 , 8 }}, -/* 13 */ {{ 11 , 11 } , { 9 , 9 }}, -/* 14 */ {{ 12 , 12 } , { 10 , 10 }}, -} -#endif -; - -/* TS 38.213 9.2.5.2 UE procedure for multiplexing HARQ-ACK/SR and CSI in a PUCCH */ -/* this is a counter of number of pucch format 4 per subframe */ -int nb_pucch_format_4_in_subframes[LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] -#ifdef INIT_VARIABLES_PUCCH_UE_NR_H -= { 0 } -#endif -; /*************** FUNCTIONS ****************************************/ -bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, bool reset_harq); +void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, + uint8_t gNB_id, + UE_nr_rxtx_proc_t *proc); -/** \brief This function return number of downlink acknowledgement and its bitmap - @param ue context - @param gNB_id identity - @param slots for rx and tx - @param o_ACK HARQ-ACK information bits - @param n_HARQ_ACK use for obtaining a PUCCH transmission power - @param do_reset reset downlink HARQ context - @returns number of bits of o_ACK */ - -uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, uint32_t *o_ACK, - int *n_HARQ_ACK, bool do_reset); - -/** \brief This function selects a pucch resource - @param ue context - @param gNB_id identity - @param uci size number of uci bits - @param pucch_resource_indicator is from downlink DCI - @param initial_pucch_id pucch resource id for initial phase - @param resource_set_id pucch resource set if any - @param resource_id pucch resource id if any - @returns TRUE a pucch resource has been found FALSE no valid pucch resource */ - -boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size, int pucch_resource_indicator, - int *initial_pucch_id, int *resource_set_id, int *resource_id, NR_UE_HARQ_STATUS_t *harq_status); - -/** \brief This function select a pucch resource set - @param ue context - @param gNB_id identity - @param uci size number of uci bits - @returns number of the pucch resource set */ - -int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size); - -/** \brief This function check pucch format - @param ue context - @param gNB_id identity - @param format_pucch pucch format - @param nb_symbols_for_tx number of symbols for pucch transmission - @param uci size number of uci bits - @returns TRUE pucch format matched uci size and constraints, FALSE invalid pucch format */ - -boolean_t check_pucch_format(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, pucch_format_nr_t format_pucch, int nb_symbols_for_tx, - int uci_size); - -/** \brief This function selects a pucch resource - @param ue context - @param gNB_id identity - @param slots for rx and tx - @returns TRUE a scheduling request is triggered */ - -int trigger_periodic_scheduling_request(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc); - -/** \brief This function reads current CSI - @param ue context - @param gNB_id identity - @param csi_payload is updated with CSI - @returns number of bits of CSI */ - -int get_csi_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint32_t *csi_payload); - -/** \brief This dummy function sets current CSI for simulation - @param csi_status - @param csi_payload is updated with CSI - @returns none */ void set_csi_nr(int csi_status, uint32_t csi_payload); diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index 3215718f8e..5f8269c513 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -4948,7 +4948,7 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue, break; default: - LOG_E(PHY, "[UE %d] Received unexpected message %s\n", ITTI_MSG_INSTANCE (msg_p), ITTI_MSG_NAME (msg_p)); + LOG_E(PHY, "[UE %ld] Received unexpected message %s\n", ITTI_MSG_DESTINATION_INSTANCE (msg_p), ITTI_MSG_NAME (msg_p)); break; } diff --git a/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c b/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c index f71a8ee117..03fbfeffe0 100644 --- a/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c +++ b/openair1/SIMULATION/ETH_TRANSPORT/emu_transport.c @@ -231,7 +231,6 @@ void clear_UE_transport_info(uint8_t nb_UE) for (UE_id=0; UE_id *(double *)p2; -} - double median(varArray_t *input) { return *(double *)((uint8_t *)(input+1)+(input->size/2)*input->atomSize); } @@ -50,13 +46,13 @@ void sumUpStatsSlot(time_stats_t *res, time_stats_t src[RX_NB_TH][2], int lastAc } double squareRoot(time_stats_t *ptr) { - double timeBase=1/(1000*cpu_freq_GHz); + double timeBase=1/(1000*get_cpu_freq_GHz()); return sqrt((double)ptr->diff_square*pow(timeBase,2)/ptr->trials - pow((double)ptr->diff/ptr->trials*timeBase,2)); } void printDistribution(time_stats_t *ptr, varArray_t *sortedList, char *txt) { - double timeBase=1/(1000*cpu_freq_GHz); + double timeBase=1/(1000*get_cpu_freq_GHz()); printf("%-43s %6.2f us (%d trials)\n", txt, (double)ptr->diff/ptr->trials*timeBase, @@ -73,7 +69,7 @@ void printStatIndent(time_stats_t *ptr, char *txt) { } void printStatIndent2(time_stats_t *ptr, char *txt) { - double timeBase=1/(1000*cpu_freq_GHz); + double timeBase=1/(1000*get_cpu_freq_GHz()); printf(" |__ %-34s %6.2f us (%3d trials)\n", txt, ptr->trials?((double)ptr->diff)/ptr->trials*timeBase:0, @@ -81,7 +77,7 @@ void printStatIndent2(time_stats_t *ptr, char *txt) { } void printStatIndent3(time_stats_t *ptr, char *txt) { - double timeBase=1/(1000*cpu_freq_GHz); + double timeBase=1/(1000*get_cpu_freq_GHz()); printf(" |__ %-30s %6.2f us (%3d trials)\n", txt, ptr->trials?((double)ptr->diff)/ptr->trials*timeBase:0, diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index f65e1f9633..d4106cb29a 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -60,16 +60,19 @@ #include "dummy_functions.c" #include "executables/thread-common.h" #include "executables/split_headers.h" - +#include "common/ran_context.h" void feptx_ofdm(RU_t *ru, int frame, int subframe); void feptx_prec(RU_t *ru, int frame, int subframe); double cpuf; -#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) +#define inMicroS(a) (((double)(a))/(get_cpu_freq_GHz()*1000.0)) //#define MCS_COUNT 23//added for PHY abstraction #include int otg_enabled=0; +THREAD_STRUCT thread_struct; +nfapi_ue_release_request_body_t release_rntis; + /*the following parameters are used to control the processing times calculations*/ double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */ double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */ @@ -78,6 +81,12 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ +double DS_TDL = .03; +static int cmpdouble(const void *p1, const void *p2) { + return *(double *)p1 > *(double *)p2; +} +RAN_CONTEXT_t RC; + int emulate_rf = 0; int split73=0; void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { @@ -161,7 +170,7 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, // Multipath channel if (awgn_flag == 0) { multipath_channel(eNB2UE[round],s_re,s_im,r_re,r_im, - 2*UE->frame_parms.samples_per_tti,hold_channel); + 2*UE->frame_parms.samples_per_tti,hold_channel,0); // printf("amc: ****************** eNB2UE[%d]->n_rx = %d,dd %d\n",round,eNB2UE[round]->nb_rx,eNB2UE[round]->channel_offset); if(abstx==1 && num_rounds>1) @@ -173,7 +182,7 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, if (UE->perfect_ce==1) { // fill in perfect channel estimates - freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1); + freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1, 15); /* LOG_M("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8); LOG_M("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL + 1,1,8); @@ -184,52 +193,52 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, if(abstx) { if (trials==0 && round==0) { // calculate freq domain representation to compute SINR - freq_channel(eNB2UE[0], ru->frame_parms->N_RB_DL,2*ru->frame_parms->N_RB_DL + 1); + freq_channel(eNB2UE[0], ru->frame_parms->N_RB_DL,2*ru->frame_parms->N_RB_DL + 1, 15); // snr=pow(10.0,.1*SNR); fprintf(csv_fd,"%f,",SNR); for (u=0; u<2*ru->frame_parms->N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].x; - channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].y; + channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].r; + channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].i; fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } } if(num_rounds>1) { - freq_channel(eNB2UE[1], ru->frame_parms->N_RB_DL,2*ru->frame_parms->N_RB_DL + 1); + freq_channel(eNB2UE[1], ru->frame_parms->N_RB_DL,2*ru->frame_parms->N_RB_DL + 1, 15); for (u=0; u<2*ru->frame_parms->N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].x; - channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].y; + channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].r; + channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].i; fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } } - freq_channel(eNB2UE[2], ru->frame_parms->N_RB_DL,2*ru->frame_parms->N_RB_DL + 1); + freq_channel(eNB2UE[2], ru->frame_parms->N_RB_DL,2*ru->frame_parms->N_RB_DL + 1, 15); for (u=0; u<2*ru->frame_parms->N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].x; - channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].y; + channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].r; + channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].i; fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } } - freq_channel(eNB2UE[3], ru->frame_parms->N_RB_DL,2*ru->frame_parms->N_RB_DL + 1); + freq_channel(eNB2UE[3], ru->frame_parms->N_RB_DL,2*ru->frame_parms->N_RB_DL + 1, 15); for (u=0; u<2*ru->frame_parms->N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].x; - channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].y; + channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].r; + channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].i; fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } @@ -482,7 +491,7 @@ int n_ch_rlz = 1; int rx_sample_offset = 0; int xforms=0; int dump_table=0; -int loglvl=OAILOG_WARNING; +int loglvl=OAILOG_INFO; int mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0; int two_thread_flag=0; int num_rounds = 4;//,fix_rounds=0; @@ -665,7 +674,7 @@ int main(int argc, char **argv) { { "XForms", "Display the soft scope", PARAMFLAG_BOOL, iptr:&xforms, defintval:0, TYPE_INT, 0 }, { "Yperfect_ce","Perfect CE", PARAMFLAG_BOOL, iptr:&perfect_ce, defintval:0, TYPE_INT, 0 }, { "Zdump", "dump table",PARAMFLAG_BOOL, iptr:&dump_table, defintval:0, TYPE_INT, 0 }, - { "Loglvl", "log level",0, iptr:&loglvl, defintval:OAILOG_DEBUG, TYPE_INT, 0 }, + { "Loglvl", "log level",0, iptr:&loglvl, defintval:OAILOG_INFO, TYPE_INT, 0 }, { "zn_rx", "Number of RX antennas used in UE",0, iptr:NULL, defintval:2, TYPE_INT, 0 }, { "gchannel", "[A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M')",0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0 }, { "verbose", "display debug text", PARAMFLAG_BOOL, iptr:&verbose, defintval:0, TYPE_INT, 0 }, @@ -900,7 +909,6 @@ int main(int argc, char **argv) { // moreover you need to init itti with the following line // however itti will catch all signals, so ctrl-c won't work anymore // alternatively you can disable ITTI completely in CMakeLists.txt - //itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, NULL); T_stdout = 1; if (common_flag == 0) { @@ -929,9 +937,10 @@ int main(int argc, char **argv) { NB_RB = conv_nprb(0,DLSCH_RB_ALLOC,N_RB_DL); } else { - if (rballocset==0) NB_RB = 8; + if (rballocset==0) NB_RB = 2+TPC; else NB_RB = DLSCH_RB_ALLOC; + printf("Common PDSCH: NB_RB = %d\n",NB_RB); AssertFatal(NB_RB <= N_RB_DL,"illegal NB_RB %d\n",NB_RB); } @@ -1172,9 +1181,10 @@ int main(int argc, char **argv) { channel_model, N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), + DS_TDL, forgetting_factor, rx_sample_offset, - 0); + 0, 0); reset_meas(&eNB2UE[0]->random_channel); reset_meas(&eNB2UE[0]->interp_time); @@ -1185,9 +1195,10 @@ int main(int argc, char **argv) { channel_model, N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), + DS_TDL, forgetting_factor, rx_sample_offset, - 0); + 0, 0); reset_meas(&eNB2UE[n]->random_channel); reset_meas(&eNB2UE[n]->interp_time); } diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c index 2176e272c8..3b4e6782da 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm4.c @@ -689,7 +689,6 @@ int main(int argc, char **argv) // moreover you need to init itti with the following line // however itti will catch all signals, so ctrl-c won't work anymore // alternatively you can disable ITTI completely in CMakeLists.txt - //itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, NULL); if (common_flag == 0) { switch (N_RB_DL) { @@ -989,7 +988,7 @@ int main(int argc, char **argv) N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), forgetting_factor, rx_sample_offset, - 0); + 0, 0); if(num_rounds>1) { for(n=1; n<8; n++) @@ -1000,7 +999,7 @@ int main(int argc, char **argv) N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), forgetting_factor, rx_sample_offset, - 0); + 0, 0); } if (eNB2UE[0]==NULL) { diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c index 5973f80b55..bd164150c5 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c @@ -834,7 +834,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), forgetting_factor, rx_sample_offset, - 0); + 0, 0); if(num_rounds>1) { for(n=1; n<4; n++) @@ -845,7 +845,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), forgetting_factor, rx_sample_offset, - 0); + 0, 0); } if (eNB2UE[0]==NULL) { diff --git a/openair1/SIMULATION/LTE_PHY/gpib_send.c b/openair1/SIMULATION/LTE_PHY/gpib_send.c index a8ae48cdfa..06ce60da0f 100644 --- a/openair1/SIMULATION/LTE_PHY/gpib_send.c +++ b/openair1/SIMULATION/LTE_PHY/gpib_send.c @@ -19,10 +19,10 @@ * contact@openairinterface.org */ -#include -#include -#include -#include"gpib_send.h" +#include +#include +#include +#include "gpib_send.h" void gpib_send(unsigned int gpib_board, unsigned int gpib_device, char *command_string ) { unsigned short addlist[2] = {gpib_device, NOADDR}; diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index 5073be24f5..53c15ccc89 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -181,7 +181,7 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, if (UE->perfect_ce==1) { // fill in perfect channel estimates - freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1); + freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1, 15); /* LOG_M("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8); LOG_M("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL + 1,1,8); @@ -192,7 +192,7 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, if(abstx) { if (trials==0 && round==0) { // calculate freq domain representation to compute SINR - freq_channel(eNB2UE[0], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1); + freq_channel(eNB2UE[0], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1, 15); // snr=pow(10.0,.1*SNR); fprintf(csv_fd,"%f,",SNR); @@ -207,7 +207,7 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, } if(num_rounds>1) { - freq_channel(eNB2UE[1], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1); + freq_channel(eNB2UE[1], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1, 15); for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { @@ -219,7 +219,7 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, } } - freq_channel(eNB2UE[2], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1); + freq_channel(eNB2UE[2], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1, 15); for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { @@ -231,7 +231,7 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, } } - freq_channel(eNB2UE[3], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1); + freq_channel(eNB2UE[3], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1, 15); for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { @@ -997,7 +997,6 @@ int main(int argc, char **argv) { // moreover you need to init itti with the following line // however itti will catch all signals, so ctrl-c won't work anymore // alternatively you can disable ITTI completely in CMakeLists.txt - //itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, NULL); if (common_flag == 0) { switch (N_RB_DL) { @@ -1291,7 +1290,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), forgetting_factor, rx_sample_offset, - 0); + 0, 0); reset_meas(&eNB2UE[0]->random_channel); reset_meas(&eNB2UE[0]->interp_time); @@ -1304,7 +1303,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), forgetting_factor, rx_sample_offset, - 0); + 0, 0); reset_meas(&eNB2UE[n]->random_channel); reset_meas(&eNB2UE[n]->interp_time); } diff --git a/openair1/SIMULATION/LTE_PHY/pbchsim.c b/openair1/SIMULATION/LTE_PHY/pbchsim.c index 00ad03c52d..71286faafb 100644 --- a/openair1/SIMULATION/LTE_PHY/pbchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pbchsim.c @@ -386,7 +386,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), 0, 0, - 0); + 0, 0); if (interf1>-20) eNB2UE1 = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, @@ -396,7 +396,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), 0, 4, - 0); + 0, 0); if (interf2>-20) eNB2UE2 = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, @@ -406,7 +406,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), 0, 8, - 0); + 0, 0); if (eNB2UE==NULL) { msg("Problem generating channel model. Exiting.\n"); diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c index 004eb24243..bd2c2d66b9 100644 --- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c @@ -708,7 +708,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), 0, 0, - 0); + 0, 0); L1_rxtx_proc_t *proc_rxtx = (subframe == 0)? &eNB->proc.L1_proc: &eNB->proc.L1_proc_tx; eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,N_RB_DL,0); UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); diff --git a/openair1/SIMULATION/LTE_PHY/prachsim.c b/openair1/SIMULATION/LTE_PHY/prachsim.c index c997aa7639..229764a893 100644 --- a/openair1/SIMULATION/LTE_PHY/prachsim.c +++ b/openair1/SIMULATION/LTE_PHY/prachsim.c @@ -343,7 +343,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL), 0.0, delay, - 0); + 0, 0); if (UE2eNB==NULL) { msg("Problem generating channel model. Exiting.\n"); diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c index a58f844945..083a756afb 100644 --- a/openair1/SIMULATION/LTE_PHY/pucchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c @@ -283,7 +283,6 @@ int main(int argc, char **argv) { } logInit(); - //itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, NULL); g_log->log_component[PHY].level = LOG_DEBUG; g_log->log_component[PHY].flag = LOG_HIGH; @@ -324,7 +323,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL), 0.0, 0, - 0); + 0, 0); if (UE2eNB==NULL) { printf("Problem generating channel model. Exiting.\n"); diff --git a/openair1/SIMULATION/LTE_PHY/scansim.c b/openair1/SIMULATION/LTE_PHY/scansim.c index 5ceeee7f2f..839d30a8de 100644 --- a/openair1/SIMULATION/LTE_PHY/scansim.c +++ b/openair1/SIMULATION/LTE_PHY/scansim.c @@ -335,7 +335,7 @@ int main(int argc, char **argv) { N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), 0, 0, - 0); + 0, 0); if (eNB2UE==NULL) { msg("Problem generating channel model. Exiting.\n"); diff --git a/openair1/SIMULATION/LTE_PHY/syncsim.c b/openair1/SIMULATION/LTE_PHY/syncsim.c index 80598b37e4..e8ee7d3d5e 100644 --- a/openair1/SIMULATION/LTE_PHY/syncsim.c +++ b/openair1/SIMULATION/LTE_PHY/syncsim.c @@ -724,7 +724,7 @@ int main(int argc, char **argv) { BW, 0, 0, - 0); + 0, 0); if (interf1>-20) eNB2UE1 = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, @@ -733,7 +733,7 @@ int main(int argc, char **argv) { BW, 0, 0, - 0); + 0, 0); if (interf2>-20) eNB2UE2 = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, @@ -742,7 +742,7 @@ int main(int argc, char **argv) { BW, 0, 0, - 0); + 0, 0); if (eNB2UE==NULL) { msg("Problem generating channel model. Exiting.\n"); diff --git a/openair1/SIMULATION/LTE_PHY/test.c b/openair1/SIMULATION/LTE_PHY/test.c index 06785f7cdc..6b78dad4e7 100644 --- a/openair1/SIMULATION/LTE_PHY/test.c +++ b/openair1/SIMULATION/LTE_PHY/test.c @@ -75,7 +75,7 @@ int main(int argc, char **argv) double rx_gain; int rx_pwr2, target_rx_pwr_dB; - struct complex **ch; + struct complexd **ch; unsigned char first_call = 1; LTE_DL_FRAME_PARMS frame_parms; @@ -169,10 +169,10 @@ int main(int argc, char **argv) channel_length = (int) 11+2*BW*Td; - ch = (struct complex**) malloc(4 * sizeof(struct complex*)); + ch = (struct complexd**) malloc(4 * sizeof(struct complexd*)); for (i = 0; i<4; i++) - ch[i] = (struct complex*) malloc(channel_length * sizeof(struct complex)); + ch[i] = (struct complexd*) malloc(channel_length * sizeof(struct complexd)); randominit(0); set_taus_seed(0); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index c950d6f4da..39593a640c 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -55,9 +55,11 @@ #include "executables/thread-common.h" #include "targets/RT/USER/lte-softmodem.h" #include "executables/split_headers.h" +#include "common/ran_context.h" +#include "PHY/LTE_ESTIMATION/lte_estimation.h" double cpuf; -#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) +#define inMicroS(a) (((double)(a))/(get_cpu_freq_GHz()*1000.0)) //#define MCS_COUNT 23//added for PHY abstraction #include channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX]; @@ -70,6 +72,9 @@ node_desc_t *ue_data[NUMBER_OF_UE_MAX]; extern uint16_t beta_ack[16],beta_ri[16],beta_cqi[16]; //extern char* namepointer_chMag ; int xforms=0; +THREAD_STRUCT thread_struct; +nfapi_ue_release_request_body_t release_rntis; + FD_lte_phy_scope_enb *form_enb; char title[255]; @@ -80,8 +85,11 @@ double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */ double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ +static int cmpdouble(const void *p1, const void *p2) { + return *(double *)p1 > *(double *)p2; +} - +RAN_CONTEXT_t RC; int split73=0; void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { AssertFatal(false, "Must not be called in this context\n"); @@ -339,13 +347,12 @@ int main(int argc, char **argv) { int UE_id = 0; static int nb_rb=25,first_rb=0,mcs=0,round=0; //unsigned char l; - static int awgn_flag = 0 ; SCM_t channel_model=Rice1; unsigned char *input_buffer=0,harq_pid; unsigned short input_buffer_length; unsigned int ret; unsigned int coded_bits_per_codeword,nsymb; - unsigned int tx_lev=0,tx_lev_dB,trials,errs[4]= {0,0,0,0},round_trials[4]= {0,0,0,0}; + unsigned int tx_lev=0,tx_lev_dB,trials,errs[5]= {0,0,0,0,0},round_trials[4]= {0,0,0,0}; FILE *bler_fd=NULL; char bler_fname[512]; FILE *time_meas_fd=NULL; @@ -401,12 +408,11 @@ int main(int argc, char **argv) { printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz); AssertFatal(load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) != NULL, "Cannot load configuration module, exiting\n"); logInit(); - set_glog(OAILOG_WARNING); + set_glog(OAILOG_INFO); T_stdout = 1; // enable these lines if you need debug info // however itti will catch all signals, so ctrl-c won't work anymore // alternatively you can disable ITTI completely in CMakeLists.txt - // itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, NULL); // set_comp_log(PHY,LOG_DEBUG,LOG_HIGH,1); // set_glog(LOG_DEBUG,LOG_HIGH); //hapZEbm:n:Y:X:x:s:w:e:q:d:D:O:c:r:i:f:y:c:oA:C:R:g:N:l:S:T:QB:PI:LF @@ -729,9 +735,10 @@ int main(int argc, char **argv) { channel_model, N_RB2sampling_rate(eNB->frame_parms.N_RB_UL), N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL), + 30e-9, forgetting_factor, delay, - 0); + 0, 0); // set Doppler UE2eNB->max_Doppler = maxDoppler; @@ -1083,21 +1090,19 @@ int main(int argc, char **argv) { } } - if (awgn_flag == 0) { - if (UE2eNB->max_Doppler == 0) { - multipath_channel(UE2eNB,s_re,s_im,r_re,r_im, - eNB->frame_parms.samples_per_tti,hold_channel); - } else { - multipath_tv_channel(UE2eNB,s_re,s_im,r_re,r_im, - 2*eNB->frame_parms.samples_per_tti,hold_channel); - } + if (UE2eNB->max_Doppler == 0) { + multipath_channel(UE2eNB,s_re,s_im,r_re,r_im, + eNB->frame_parms.samples_per_tti,hold_channel,0); + } else { + multipath_tv_channel(UE2eNB,s_re,s_im,r_re,r_im, + 2*eNB->frame_parms.samples_per_tti,hold_channel); } if(abstx) { if(saving_bler==0) if (trials==0 && round==0) { // calculate freq domain representation to compute SINR - freq_channel(UE2eNB, N_RB_DL,12*N_RB_DL + 1); + freq_channel(UE2eNB, N_RB_DL,12*N_RB_DL + 1, 15); // snr=pow(10.0,.1*SNR); fprintf(csv_fdUL,"%f,%u,%u,%f,%f,%f,",SNR,tx_lev,tx_lev_dB,sigma2_dB,tx_gain,SNR2); @@ -1106,8 +1111,8 @@ int main(int argc, char **argv) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { // abs_channel = (eNB2UE->chF[aarx+(aatx*eNB2UE->nb_rx)][u].x*eNB2UE->chF[aarx+(aatx*eNB2UE->nb_rx)][u].x + eNB2UE->chF[aarx+(aatx*eNB2UE->nb_rx)][u].y*eNB2UE->chF[aarx+(aatx*eNB2UE->nb_rx)][u].y); - channelx = UE2eNB->chF[aarx+(aatx*UE2eNB->nb_rx)][u].x; - channely = UE2eNB->chF[aarx+(aatx*UE2eNB->nb_rx)][u].y; + channelx = UE2eNB->chF[aarx+(aatx*UE2eNB->nb_rx)][u].r; + channely = UE2eNB->chF[aarx+(aatx*UE2eNB->nb_rx)][u].i; // if(transmission_m==5){ fprintf(csv_fdUL,"%e+i*(%e),",channelx,channely); // } @@ -1133,6 +1138,15 @@ int main(int argc, char **argv) { sqrt(sigma2/2)*gaussdouble(0.0,1.0)); } } + if (n_frames==1) + for (i=0; iframe_parms.samples_per_tti; i++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { + ((short *) &ru->common.rxdata[aa][eNB->frame_parms.samples_per_tti*(subframe+1)%10])[2*i] = + (short) (sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + ((short *) &ru->common.rxdata[aa][eNB->frame_parms.samples_per_tti*(subframe+1)%10])[2*i+1] = + (short) (sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + } + } if (n_frames<=10) { printf("rx_level Null symbol %f\n",10*log10((double)signal_energy((int *) @@ -1158,9 +1172,10 @@ int main(int argc, char **argv) { start_meas(&eNB->phy_proc_rx); ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? ru_fep_full_2thread : fep_full; ru->feprx(ru,subframe); + if (n_frames==1) lte_eNB_I0_measurements(eNB,(subframe+1)%10,0,1); + phy_procedures_eNB_uespec_RX(eNB,proc_rxtx); stop_meas(&eNB->phy_proc_rx); - if (cqi_flag > 0) { cqi_error = 0; @@ -1200,6 +1215,9 @@ int main(int argc, char **argv) { eNB->ulsch[0]->harq_processes[harq_pid]->uci_format,0,eNB->frame_parms.N_RB_DL); dump_ulsch(eNB,eNB->proc.frame_rx,subframe,0,round); + dump_I0_stats(stdout,eNB); + dump_ulsch_stats(stdout,eNB,0); + exit(-1); } @@ -1260,14 +1278,16 @@ int main(int argc, char **argv) { if (t_rx > 2000 ) n_rx_dropped++; - appendVarArray(table_tx, &t_tx); - appendVarArray(table_tx_ifft, &t_tx_ifft); - appendVarArray(table_tx_mod, &t_tx_mod ); - appendVarArray(table_tx_enc, &t_tx_enc ); - appendVarArray(table_rx, &t_rx ); - appendVarArray(table_rx_fft, &t_rx_fft ); - appendVarArray(table_rx_demod, &t_rx_demod ); - appendVarArray(table_rx_dec, &t_rx_dec ); + if (trials < 1000) { + appendVarArray(table_tx, &t_tx); + appendVarArray(table_tx_ifft, &t_tx_ifft); + appendVarArray(table_tx_mod, &t_tx_mod ); + appendVarArray(table_tx_enc, &t_tx_enc ); + appendVarArray(table_rx, &t_rx ); + appendVarArray(table_rx_fft, &t_rx_fft ); + appendVarArray(table_rx_demod, &t_rx_demod ); + appendVarArray(table_rx_dec, &t_rx_dec ); + } } //trials // sort table @@ -1286,6 +1306,7 @@ int main(int argc, char **argv) { LOG_UDUMPMSG(SIM,dataArray(table_rx),table_rx->size,LOG_DUMP_DOUBLE,"The receiver raw data: \n"); } + dump_ulsch_stats(stdout,eNB,0); printf("\n**********rb: %d ***mcs : %d *********SNR = %f dB (%f): TX %u dB (gain %f dB), N0W %f dB, I0 %u dB, delta_IF %d [ (%d,%d) dB / (%u,%u) dB ]**************************\n", nb_rb,mcs,SNR,SNR2, tx_lev_dB, diff --git a/openair1/SIMULATION/LTE_PHY/ulsim2.c b/openair1/SIMULATION/LTE_PHY/ulsim2.c index 69d4dc2e3f..e994d4fc36 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim2.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim2.c @@ -49,7 +49,7 @@ int main(int argc, char **argv) double amps[8] = {0.3868472 , 0.3094778 , 0.1547389 , 0.0773694 , 0.0386847 , 0.0193424 , 0.0096712 , 0.0038685}; double aoa=.03,ricean_factor=1; //0.0000005; int channel_length; - struct complex **ch; + struct complexd **ch; unsigned char pbch_pdu[6]; int sync_pos, sync_pos_slot; FILE *rx_frame_file; @@ -170,10 +170,10 @@ int main(int argc, char **argv) bzero(r_im[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double)); } - ch = (struct complex**) malloc(4 * sizeof(struct complex*)); + ch = (struct complexd**) malloc(4 * sizeof(struct complexd*)); for (i = 0; i<4; i++) - ch[i] = (struct complex*) malloc(channel_length * sizeof(struct complex)); + ch[i] = (struct complexd*) malloc(channel_length * sizeof(struct complexd)); generate_srs_tx(lte_frame_parms,lte_ue_common_vars->txdataF[0],AMP,0); generate_drs_puch(lte_frame_parms,lte_ue_common_vars->txdataF[0],AMP,0,first_rb,nb_rb); diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 5e2d42a0f7..ff07422c6b 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -52,13 +52,15 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; +UE_nr_rxtx_proc_t proc; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; - +uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; +uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; // needed for some functions PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } }; @@ -107,15 +109,17 @@ int main(int argc, char **argv) int ret; //int run_initial_sync=0; int loglvl = OAILOG_WARNING; + uint8_t dlsch_threads = 0; float target_error_rate = 0.01; uint64_t SSB_positions=0x01; uint16_t nb_symb_sch = 12; uint16_t nb_rb = 50; uint8_t Imcs = 9; uint8_t mcs_table = 0; - + double DS_TDL = .03; cpuf = get_cpu_freq_GHz(); - + char gNBthreads[128]="n"; + if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) { exit_fun("[NR_DLSCHSIM] Error, configuration module init failed\n"); } @@ -123,7 +127,7 @@ int main(int argc, char **argv) //logInit(); randominit(0); - while ((c = getopt(argc, argv, "df:hpVg:i:j:n:l:m:r:s:S:y:z:M:N:F:R:P:L:")) != -1) { + while ((c = getopt(argc, argv, "df:hpVg:i:j:n:l:m:r:s:S:y:z:M:N:F:R:P:L:X:")) != -1) { switch (c) { /*case 'f': write_output_file = 1; @@ -136,9 +140,9 @@ int main(int argc, char **argv) break;*/ - /*case 'd': - frame_type = 1; - break;*/ + case 'd': + dlsch_threads = atoi(optarg); + break; case 'g': switch ((char) *optarg) { @@ -289,6 +293,11 @@ int main(int argc, char **argv) nb_rb = atoi(optarg); break; + case 'X': + strncpy(gNBthreads, optarg, sizeof(gNBthreads)); + gNBthreads[sizeof(gNBthreads)-1]=0; + break; + /*case 'x': transmission_mode = atoi(optarg); break;*/ @@ -318,6 +327,7 @@ int main(int argc, char **argv) //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n"); //printf("-f Output filename (.txt format) for Pe/SNR results\n"); printf("-F Input filename (.txt format) for RX conformance testing\n"); + printf("-d number of dlsch threads, 0: no dlsch parallelization\n"); exit(-1); break; } @@ -329,6 +339,7 @@ int main(int argc, char **argv) if (snr1set == 0) snr1 = snr0 + 10; + init_dlsch_tpool(dlsch_threads); if (ouput_vcd) vcd_signal_dumper_init("/tmp/openair_dump_nr_dlschsim.vcd"); @@ -336,7 +347,8 @@ int main(int argc, char **argv) gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, 61.44e6, //N_RB2sampling_rate(N_RB_DL), 40e6, //N_RB2channel_bandwidth(N_RB_DL), - 0, 0, 0); + DS_TDL, + 0, 0, 0, 0); if (gNB2UE == NULL) { printf("Problem generating channel model. Exiting.\n"); @@ -346,6 +358,8 @@ int main(int argc, char **argv) RC.gNB = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *)); RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; + gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); + initTpool(gNBthreads, gNB->threadPool, true); //gNB_config = &gNB->gNB_config; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; @@ -354,7 +368,7 @@ int main(int argc, char **argv) frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL; crcTableInit(); nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell,SSB_positions); - phy_init_nr_gNB(gNB, 0, 0); + phy_init_nr_gNB(gNB, 0, 1); //lowmem //init_eNB_afterRU(); frame_length_complex_samples = frame_parms->samples_per_subframe; //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP; @@ -423,8 +437,10 @@ int main(int argc, char **argv) UE->dlsch_SI[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0); UE->dlsch_ra[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0); unsigned char harq_pid = 0; //dlsch->harq_ids[subframe]; - NR_gNB_DLSCH_t *dlsch = gNB->dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15; + processingData_L1tx_t msgDataTx; + init_DLSCH_struct(gNB, &msgDataTx); + NR_gNB_DLSCH_t *dlsch = msgDataTx.dlsch[0][0]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; //time_stats_t *rm_stats, *te_stats, *i_stats; uint8_t is_crnti = 0, llr8_flag = 0; unsigned int TBS = 8424; @@ -460,7 +476,6 @@ int main(int argc, char **argv) double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc short *channel_output_fixed = malloc16(sizeof(short) * 16 * 68 * 384); short *channel_output_uncoded = malloc16(sizeof(unsigned short) * 16 * 68 * 384); - double errors_bit_uncoded = 0; //unsigned char *estimated_output; unsigned char *estimated_output_bit; unsigned char *test_input_bit; @@ -498,8 +513,10 @@ int main(int argc, char **argv) //printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32)); // generate signal + unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(32))); + bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); if (input_fd == NULL) { - nr_dlsch_encoding(test_input, frame, slot, dlsch, frame_parms,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + nr_dlsch_encoding(gNB, test_input, frame, slot, dlsch, frame_parms,output,NULL,NULL,NULL,NULL,NULL,NULL,NULL); } for (SNR = snr0; SNR < snr1; SNR += snr_step) { @@ -507,7 +524,6 @@ int main(int argc, char **argv) n_false_positive = 0; for (trial = 0; trial < n_trials; trial++) { - errors_bit_uncoded = 0; for (i = 0; i < available_bits; i++) { #ifdef DEBUG_CODER if ((i&0xf)==0) @@ -516,11 +532,12 @@ int main(int argc, char **argv) //if (i<16) // printf("encoder output f[%d] = %d\n",i,dlsch->harq_processes[0]->f[i]); - if (dlsch->harq_processes[0]->f[i] == 0) + + if (output[i] == 0) modulated_input[i] = 1.0; ///sqrt(2); //QPSK else modulated_input[i] = -1.0; ///sqrt(2); - + //if (i<16) printf("modulated_input[%d] = %d\n",i,modulated_input[i]); //SNR =10; SNR_lin = pow(10, SNR / 10.0); @@ -538,18 +555,14 @@ int main(int argc, char **argv) i,modulated_input[i], i,channel_output_fixed[i]); */ + //Uncoded BER if (channel_output_fixed[i] < 0) channel_output_uncoded[i] = 1; //QPSK demod else channel_output_uncoded[i] = 0; - - if (channel_output_uncoded[i] != dlsch->harq_processes[harq_pid]->f[i]) - errors_bit_uncoded = errors_bit_uncoded + 1; } - //if (errors_bit_uncoded>10) - //printf("errors bits uncoded %f\n", errors_bit_uncoded); #ifdef DEBUG_CODER printf("\n"); exit(-1); @@ -557,7 +570,7 @@ int main(int argc, char **argv) vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_IN); - ret = nr_dlsch_decoding(UE, channel_output_fixed, &UE->frame_parms, + ret = nr_dlsch_decoding(UE, &proc, 0, channel_output_fixed, &UE->frame_parms, dlsch0_ue, dlsch0_ue->harq_processes[0], frame, nb_symb_sch, slot,harq_pid, is_crnti, llr8_flag); @@ -631,7 +644,7 @@ int main(int argc, char **argv) for (i = 0; i < 2; i++) { printf("gNB %d\n", i); - free_gNB_dlsch(&(gNB->dlsch[0][i]),N_RB_DL); + free_gNB_dlsch(&(msgDataTx.dlsch[0][i]),N_RB_DL); printf("UE %d\n", i); free_nr_ue_dlsch(&(UE->dlsch[0][0][i]),N_RB_DL); } diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 64ab482db8..fa868a6896 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -27,6 +27,7 @@ #include #include "common/ran_context.h" #include "common/config/config_userapi.h" +#include "common/utils/nr/nr_common.h" #include "common/utils/LOG/log.h" #include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h" #include "LAYER2/NR_MAC_UE/mac_defs.h" @@ -38,8 +39,10 @@ #include "PHY/types.h" #include "PHY/INIT/phy_init.h" #include "PHY/MODULATION/modulation_eNB.h" +#include "PHY/MODULATION/nr_modulation.h" #include "PHY/MODULATION/modulation_UE.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "SCHED_NR/fapi_nr_l1.h" @@ -59,12 +62,18 @@ #include "openair1/SIMULATION/TOOLS/sim.h" #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" //#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" - +#include "PHY/NR_REFSIG/ptrs_nr.h" #include "NR_RRCReconfiguration.h" -#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) +#define inMicroS(a) (((double)(a))/(get_cpu_freq_GHz()*1000.0)) #include "SIMULATION/LTE_PHY/common_sim.h" +#include +#include +#include + +LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; +rlc_info_t Rlc_info_um,Rlc_info_am_config; PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; @@ -73,43 +82,119 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -int sf_ahead=4 ; -int sl_ahead=0; -uint8_t nfapi_mode = 0; -uint16_t NB_UE_INST = 1; +uint16_t sf_ahead=4 ; +uint16_t sl_ahead=0; +//uint8_t nfapi_mode = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; +THREAD_STRUCT thread_struct; +nfapi_ue_release_request_body_t release_rntis; +uint32_t N_RB_DL = 106; // dummy functions int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); } -void pdcp_run (const protocol_ctxt_t *const ctxt_pP) { return;} - -int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, - const int CC_id, - const uint8_t gNB_index, - const int8_t channel, - const uint8_t* pduP, - const sdu_size_t pdu_len) +int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, + const int CC_id, + const uint8_t gNB_index, + const frame_t frame, + const sub_frame_t sub_frame, + const rnti_t rnti, + const channel_t channel, + const uint8_t* pduP, + const sdu_size_t pdu_len) { return 0; } +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} -void pdcp_layer_init(void) {} -boolean_t -pdcp_data_ind( +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) +{ + return 0; +} + +void +rrc_data_ind( const protocol_ctxt_t *const ctxt_pP, - const srb_flag_t srb_flagP, - const MBMS_flag_t MBMS_flagP, - const rb_id_t rb_idP, - const sdu_size_t sdu_buffer_sizeP, - mem_block_t *const sdu_buffer_pP -) { return(false);} + const rb_id_t Srb_id, + const sdu_size_t sdu_sizeP, + const uint8_t *const buffer_pP +) +{ +} -int rrc_init_nr_global_param(void){return(0);} +int ocp_gtpv1u_create_s1u_tunnel(instance_t instance, + const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, + gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp) { + return 0; +} + +int +gtpv1u_create_s1u_tunnel( + const instance_t instanceP, + const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, + gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP +) { + return 0; +} + +int +rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +) { + return 0; +} + +int +gtpv1u_create_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ + return 0; +} + +int +gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +){ + return 0; +} + +int ocp_gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { + return 0; +} + +int +nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +){ + return 0; +} + +int nr_derive_key(int alg_type, uint8_t alg_id, + const uint8_t key[32], uint8_t **out) +{ + return 0; +} void config_common(int Mod_idP, - int pdsch_AntennaPorts, + int ssb_SubcarrierOffset, + int pdsch_AntennaPorts, + int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc ); @@ -122,13 +207,135 @@ int generate_dlsch_header(unsigned char *mac_header, unsigned char *ue_cont_res_id, unsigned char short_padding, unsigned short post_padding){return 0;} -void nr_ip_over_LTE_DRB_preconfiguration(void){} + +// Dummy function to avoid linking error at compilation of nr-dlsim +int is_x2ap_enabled(void) +{ + return 0; +} + +int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, + int CC_idP, + int UE_id, + rnti_t rntiP, + const uint8_t *sduP, + sdu_size_t sdu_lenP, + const uint8_t *sdu2P, + sdu_size_t sdu2_lenP) { + return 0; +} + +void processSlotTX(void *arg) {} + +//nFAPI P7 dummy functions to avoid linking errors + +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; +void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg); +void update_dmrs_config(NR_CellGroupConfig_t *scg, int8_t* dmrs_arg); +extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration +/* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs/nrOfLayers from command line of + dlsim, does not search for CCE/PUCCH occasion but simply sets to 0 */ +int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLayers = 1; +void nr_dlsim_preprocessor(module_id_t module_id, + frame_t frame, + sub_frame_t slot) { + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + AssertFatal(UE_info->num_UEs == 1, "can have only a single UE\n"); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[0]; + NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; + /* manually set free CCE to 0 */ + const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + sched_ctrl->search_space = get_searchspace(scc, sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Dedicated : NULL, target_ss); + uint8_t nr_of_candidates; + find_aggregation_candidates(&sched_ctrl->aggregation_level, + &nr_of_candidates, + sched_ctrl->search_space,4); + sched_ctrl->coreset = get_coreset(module_id, scc, sched_ctrl->active_bwp->bwp_Dedicated, sched_ctrl->search_space, target_ss); + sched_ctrl->cce_index = 0; + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + + ps->nrOfLayers = g_nrOfLayers; + + int dci_format = sched_ctrl->search_space && sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats ? + NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0; + + nr_set_pdsch_semi_static(scc, + UE_info->CellGroup[0], + sched_ctrl->active_bwp, + NULL, + /* tda = */ 0, + dci_format, + ps); + + NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; + sched_pdsch->rbStart = g_rbStart; + sched_pdsch->rbSize = g_rbSize; + sched_pdsch->mcs = g_mcsIndex; + /* the following might override the table that is mandated by RRC + * configuration */ + ps->mcsTableIdx = g_mcsTableIdx; + + sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); + sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); + sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm, + sched_pdsch->R, + sched_pdsch->rbSize, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->N_DMRS_SLOT, + 0 /* N_PRB_oh, 0 for initialBWP */, + 0 /* tb_scaling */, + ps->nrOfLayers) + >> 3; + + /* the simulator assumes the HARQ PID is equal to the slot number */ + sched_pdsch->dl_harq_pid = slot; + + /* The scheduler uses lists to track whether a HARQ process is + * free/busy/awaiting retransmission, and updates the HARQ process states. + * However, in the simulation, we never get ack or nack for any HARQ process, + * thus the list and HARQ states don't match what the scheduler expects. + * Therefore, below lines just "repair" everything so that the scheduler + * won't remark that there is no HARQ feedback */ + sched_ctrl->feedback_dl_harq.head = -1; // always overwrite feedback HARQ process + if (sched_ctrl->harq_processes[slot].round == 0) // depending on round set in simulation ... + add_front_nr_list(&sched_ctrl->available_dl_harq, slot); // ... make PID available + else + add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot); // ... make PID retransmission + sched_ctrl->harq_processes[slot].is_waiting = false; + AssertFatal(sched_pdsch->rbStart >= 0, "invalid rbStart %d\n", sched_pdsch->rbStart); + AssertFatal(sched_pdsch->rbSize > 0, "invalid rbSize %d\n", sched_pdsch->rbSize); + AssertFatal(sched_pdsch->mcs >= 0, "invalid mcs %d\n", sched_pdsch->mcs); + AssertFatal(ps->mcsTableIdx >= 0 && ps->mcsTableIdx <= 2, "invalid mcsTableIdx %d\n", ps->mcsTableIdx); +} + +typedef struct { + uint64_t optmask; //mask to store boolean config options + uint8_t nr_dlsch_parallel; // number of threads for dlsch decoding, 0 means no parallelization + tpool_t Tpool; // thread pool +} nrUE_params_t; + +nrUE_params_t nrUE_params; + +nrUE_params_t *get_nrUE_params(void) { + return &nrUE_params; +} + +void do_nothing(void *args) { +} int main(int argc, char **argv) { @@ -136,12 +343,15 @@ int main(int argc, char **argv) int i,aa;//,l; double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0; uint8_t snr1set=0; - float roundStats[50]; + double roundStats[500] = {0}; + double blerStats[500] = {0}; + double berStats[500] = {0}; + double snrStats[500] = {0}; float effRate; //float psnr; float eff_tp_check = 0.7; uint8_t snrRun; - uint32_t TBS; + uint32_t TBS = 0; int **txdata; double **s_re,**s_im,**r_re,**r_im; //double iqim = 0.0; @@ -156,9 +366,10 @@ int main(int argc, char **argv) // char fname[40], vname[40]; int trial, n_trials = 1, n_errors = 0, n_false_positive = 0; //int n_errors2, n_alamouti; - uint8_t transmission_mode = 1,n_tx=1,n_rx=1; + uint8_t n_tx=1,n_rx=1; uint8_t round; uint8_t num_rounds = 4; + char gNBthreads[128]="n"; channel_desc_t *gNB2UE; //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0; @@ -170,19 +381,18 @@ int main(int argc, char **argv) //uint8_t frame_mod4,num_pdcch_symbols = 0; - SCM_t channel_model=AWGN;//Rayleigh1_anticorr; + SCM_t channel_model = AWGN; // AWGN Rayleigh1 Rayleigh1_anticorr; + NB_UE_INST = 1; //double pbch_sinr; //int pbch_tx_ant; int N_RB_DL=106,mu=1; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t dlsch_config; - NR_sched_pucch pucch_sched; //unsigned char frame_type = 0; - int frame=0,slot=1; + int frame=1,slot=1; int frame_length_complex_samples; - int frame_length_complex_samples_no_prefix; + //int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; UE_nr_rxtx_proc_t UE_proc; NR_Sched_Rsp_t Sched_INFO; @@ -190,27 +400,38 @@ int main(int argc, char **argv) NR_UE_MAC_INST_t *UE_mac; int cyclic_prefix_type = NFAPI_CP_NORMAL; int run_initial_sync=0; - int do_pdcch_flag=1; - int loglvl=OAILOG_INFO; - float target_error_rate = 0.01; + //float target_error_rate = 0.01; int css_flag=0; cpuf = get_cpu_freq_GHz(); + int8_t enable_ptrs = 0; + int8_t modify_dmrs = 0; + int8_t dmrs_arg[3] = {-1,-1,-1};// Invalid values + /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */ + int8_t ptrs_arg[2] = {-1,-1};// Invalid values + + uint16_t ptrsRePerSymb = 0; + uint16_t pdu_bit_map = 0x0; + uint16_t dlPtrsSymPos = 0; + uint16_t ptrsSymbPerSlot = 0; + uint16_t rbSize = 106; + uint8_t mcsIndex = 9; + uint8_t dlsch_threads = 0; + int prb_inter = 0; if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) { exit_fun("[NR_DLSIM] Error, configuration module init failed\n"); } randominit(0); - int mcsIndex_set=0,rbStart_set=0,rbSize_set=0; int print_perf = 0; FILE *scg_fd=NULL; - while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:e:m:w")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:in:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:d:e:m:w:T:U:qX:")) != -1) { switch (c) { case 'f': scg_fd = fopen(optarg,"r"); @@ -255,6 +476,10 @@ int main(int argc, char **argv) channel_model=ETU; break; + case 'R': + channel_model=Rayleigh1; + break; + default: printf("Unsupported channel model!\n"); exit(-1); @@ -262,14 +487,10 @@ int main(int argc, char **argv) break; - /*case 'i': - interf1=atoi(optarg); + case 'i': + prb_inter=1; break; - case 'j': - interf2=atoi(optarg); - break;*/ - case 'n': n_trials = atoi(optarg); break; @@ -304,12 +525,11 @@ int main(int argc, char **argv) break; */ case 'x': - transmission_mode=atoi(optarg); + g_nrOfLayers=atoi(optarg); - if ((transmission_mode!=1) && - (transmission_mode!=2) && - (transmission_mode!=6)) { - printf("Unsupported transmission mode %d\n",transmission_mode); + if ((g_nrOfLayers!=1) && + (g_nrOfLayers!=2)) { + printf("Unsupported nr Of Layers %d\n",g_nrOfLayers); exit(-1); } @@ -318,7 +538,7 @@ int main(int argc, char **argv) case 'y': n_tx=atoi(optarg); - if ((n_tx==0) || (n_tx>2)) { + if ((n_tx==0) || (n_tx>4)) {//extend gNB to support n_tx = 4 printf("Unsupported number of tx antennas %d\n",n_tx); exit(-1); } @@ -328,7 +548,7 @@ int main(int argc, char **argv) case 'z': n_rx=atoi(optarg); - if ((n_rx==0) || (n_rx>2)) { + if ((n_rx==0) || (n_rx>4)) {//extend UE to support n_tx = 4 printf("Unsupported number of rx antennas %d\n",n_rx); exit(-1); } @@ -356,7 +576,7 @@ int main(int argc, char **argv) case 'I': run_initial_sync=1; - target_error_rate=0.1; + //target_error_rate=0.1; slot = 0; break; @@ -371,18 +591,22 @@ int main(int argc, char **argv) case 'a': - dlsch_config.rbStart = atoi(optarg); - rbStart_set=1; + g_rbStart = atoi(optarg); break; case 'b': - dlsch_config.rbSize = atoi(optarg); - rbSize_set=1; + g_rbSize = atoi(optarg); + break; + case 'D': + dlsch_threads = atoi(optarg); + break; + case 'e': + g_mcsIndex = atoi(optarg); break; - case 'e': - dlsch_config.mcsIndex[0] = atoi(optarg); - mcsIndex_set=1; + case 'q': + g_mcsTableIdx = 1; + get_softmodem_params()->use_256qam_table = 1; break; case 'm': @@ -397,6 +621,25 @@ int main(int argc, char **argv) output_fd = fopen("txdata.dat", "w+"); break; + case 'T': + enable_ptrs=1; + for(i=0; i < atoi(optarg); i++) { + ptrs_arg[i] = atoi(argv[optind++]); + } + break; + + case 'U': + modify_dmrs = 1; + for(i=0; i < atoi(optarg); i++) { + dmrs_arg[i] = atoi(argv[optind++]); + } + break; + + case 'X': + strncpy(gNBthreads, optarg, sizeof(gNBthreads)); + gNBthreads[sizeof(gNBthreads)-1]=0; + break; + default: case 'h': printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", @@ -408,10 +651,10 @@ int main(int argc, char **argv) printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n"); printf("-S Ending SNR, runs from SNR0 to SNR1\n"); printf("-t Delay spread for multipath channel\n"); - printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n"); + printf("-g [A,B,C,D,E,F,G,R] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models or R for MIMO model (ignores delay spread and Ricean factor)\n"); printf("-y Number of TX antennas used in gNB\n"); printf("-z Number of RX antennas used in UE\n"); - //printf("-i Relative strength of first intefering gNB (in dB) - cell_id mod 3 = 1\n"); + printf("-i Activate PRB based averaging for channel estimation. Frequncy domain interpolation by default.\n"); //printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n"); printf("-R N_RB_DL\n"); printf("-O oversampling factor (1,2,4,8,16)\n"); @@ -426,22 +669,31 @@ int main(int argc, char **argv) printf("-c Start symbol for PDSCH (fixed for now)\n"); printf("-j Number of symbols for PDSCH (fixed for now)\n"); printf("-e MSC index\n"); + printf("-q Use 2nd MCS table (256 QAM table) for PDSCH\n"); printf("-t Acceptable effective throughput (in percentage)\n"); + printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n"); + printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:2} DMRS ConfType{1:2}, e.g. -U 3 0 2 1 \n"); printf("-P Print DLSCH performances\n"); printf("-w Write txdata to binary file (one frame)\n"); + printf("-d number of dlsch threads, 0: no dlsch parallelization\n"); + printf("-X gNB thread pool configuration, n => no threads"); exit (-1); break; } } - + logInit(); set_glog(loglvl); T_stdout = 1; + /* initialize the sin table */ + InitSinLUT(); get_softmodem_params()->phy_test = 1; - + get_softmodem_params()->do_ra = 0; + if (snr1set==0) snr1 = snr0+10; + init_dlsch_tpool(dlsch_threads); RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *)); @@ -449,6 +701,7 @@ int main(int argc, char **argv) memset(RC.gNB[0],0,sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; + gNB->ofdm_offset_divisor = UINT_MAX; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; @@ -510,33 +763,56 @@ int main(int argc, char **argv) rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon)); NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon; + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup)); prepare_scc(rrc.carrier.servingcellconfigcommon); - uint64_t ssb_bitmap; - fill_scc(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu); - - fill_default_secondaryCellGroup(scc, - secondaryCellGroup, - 0, - 1, - n_tx, - 0); + uint64_t ssb_bitmap = 1; + fill_scc_sim(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu); + ssb_bitmap = 1;// Enable only first SSB with index ssb_indx=0 fix_scc(scc,ssb_bitmap); - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); + prepare_scd(scd); + + fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 6, 0, 0, 0); + + /* RRC parameter validation for secondaryCellGroup */ + fix_scd(scd); + /* -U option modify DMRS */ + if(modify_dmrs) { + update_dmrs_config(secondaryCellGroup, dmrs_arg); + } + /* -T option enable PTRS */ + if(enable_ptrs) { + update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg); + } + + + //xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface"); gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; // common configuration - rrc_mac_config_req_gNB(0,0,1,scc,0,0,NULL); + rrc_mac_config_req_gNB(0,0, n_tx, n_tx, 0, scc, NULL, 0, 0, NULL); // UE dedicated configuration - rrc_mac_config_req_gNB(0,0,1,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); - phy_init_nr_gNB(gNB,0,0); + rrc_mac_config_req_gNB(0,0, n_tx, n_tx, 0, scc, NULL, 1, secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); + // reset preprocessor to the one of DLSIM after it has been set during + // rrc_mac_config_req_gNB + gNB_mac->pre_processor_dl = nr_dlsim_preprocessor; + phy_init_nr_gNB(gNB,0,1); N_RB_DL = gNB->frame_parms.N_RB_DL; + NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info; + UE_info->num_UEs=1; + // stub to configure frame_parms // nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); // call MAC to configure common parameters + /* rrc_mac_config_req_gNB() has created one user, so set the scheduling + * parameters from command line in global variables that will be picked up by + * scheduling preprocessor */ + if (g_mcsIndex < 0) g_mcsIndex = 9; + if (g_rbStart < 0) g_rbStart=0; + if (g_rbSize < 0) g_rbSize = N_RB_DL - g_rbStart; double fs,bw; @@ -556,6 +832,14 @@ int main(int argc, char **argv) fs = 61.44e6; bw = 40e6; } + else if (mu == 1 && N_RB_DL == 133) { + fs = 61.44e6; + bw = 50e6; + } + else if (mu == 1 && N_RB_DL == 162) { + fs = 61.44e6; + bw = 60e6; + } else if (mu == 3 && N_RB_DL == 66) { fs = 122.88e6; bw = 100e6; @@ -569,11 +853,12 @@ int main(int argc, char **argv) gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, - fs, + fs/1e6,//sampling frequency in MHz bw, + 30e-9, 0, 0, - 0); + 0, 0); if (gNB2UE==NULL) { printf("Problem generating channel model. Exiting.\n"); @@ -581,30 +866,30 @@ int main(int argc, char **argv) } frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; - frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; - s_re = malloc(2*sizeof(double*)); - s_im = malloc(2*sizeof(double*)); - r_re = malloc(2*sizeof(double*)); - r_im = malloc(2*sizeof(double*)); - txdata = malloc(2*sizeof(int*)); - - for (i=0; i<2; i++) { + s_re = malloc(n_tx*sizeof(double*)); + s_im = malloc(n_tx*sizeof(double*)); + r_re = malloc(n_rx*sizeof(double*)); + r_im = malloc(n_rx*sizeof(double*)); + txdata = malloc(n_tx*sizeof(int*)); + for (i=0; iframe_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS)); + UE->frame_parms.nb_antennas_rx = n_rx; if (run_initial_sync==1) UE->is_synchronized = 0; else {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;} UE->perfect_ce = 0; - for (i=0;i<10;i++) UE->current_thread_id[i] = 0; if (init_nr_ue_signal(UE, 1, 0) != 0) { @@ -635,26 +920,28 @@ int main(int argc, char **argv) init_nr_ue_transport(UE,0); nr_gold_pbch(UE); - nr_gold_pdcch(UE,0,2); + nr_gold_pdcch(UE,0); nr_l2_init_ue(NULL); UE_mac = get_mac_inst(0); - + UE->if_inst = nr_ue_if_module_init(0); UE->if_inst->scheduled_response = nr_ue_scheduled_response; UE->if_inst->phy_config_request = nr_ue_phy_config_request; UE->if_inst->dl_indication = nr_ue_dl_indication; UE->if_inst->ul_indication = dummy_nr_ue_ul_indication; - + UE->prb_interpolation = prb_inter; + UE_mac->if_module = nr_ue_if_module_init(0); - + unsigned int available_bits=0; unsigned char *estimated_output_bit; unsigned char *test_input_bit; unsigned int errors_bit = 0; uint32_t errors_scrambling = 0; + initTpool("N", &(nrUE_params.Tpool), false); test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); @@ -662,18 +949,12 @@ int main(int argc, char **argv) // generate signal AssertFatal(input_fd==NULL,"Not ready for input signal file\n"); gNB->pbch_configured = 1; - gNB->ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234; - - if (mcsIndex_set==0) dlsch_config.mcsIndex[0]=9; - - if (rbStart_set==0) dlsch_config.rbStart=0; - if (rbSize_set==0) dlsch_config.rbSize=N_RB_DL-dlsch_config.rbStart; //Configure UE rrc.carrier.MIB = (uint8_t*) malloc(4); rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0); - nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,secondaryCellGroup); + nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib, NULL, NULL, secondaryCellGroup); nr_dcireq_t dcireq; @@ -691,17 +972,30 @@ int main(int argc, char **argv) scheduled_response.CC_id = 0; scheduled_response.frame = frame; scheduled_response.slot = slot; - + scheduled_response.thread_id = 0; nr_ue_phy_config_request(&UE_mac->phy_config); - NR_UE_list_t *UE_list = &RC.nrmac[0]->UE_list; //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels; snrRun = 0; + gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); + initTpool(gNBthreads, gNB->threadPool, true); + gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_L1_tx); + // we create 2 threads for L1 tx processing + notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,processSlotTX); + processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); + init_DLSCH_struct(gNB, msgDataTx); + msgDataTx->slot = slot; + msgDataTx->frame = frame; + memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t)); + reset_meas(&msgDataTx->phy_proc_tx); + gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx; + pushTpool(gNB->threadPool,msgL1Tx); + for (SNR = snr0; SNR < snr1; SNR += .2) { varArray_t *table_tx=initVarArray(1000,sizeof(double)); - reset_meas(&gNB->phy_proc_tx); // total gNB tx reset_meas(&gNB->dlsch_scrambling_stats); reset_meas(&gNB->dlsch_interleaving_stats); reset_meas(&gNB->dlsch_rate_matching_stats); @@ -711,7 +1005,9 @@ int main(int argc, char **argv) reset_meas(&gNB->tinput); reset_meas(&gNB->tprep); reset_meas(&gNB->tparity); - reset_meas(&gNB->toutput); + reset_meas(&gNB->toutput); + + clear_pdsch_stats(gNB); n_errors = 0; effRate = 0; @@ -719,6 +1015,8 @@ int main(int argc, char **argv) //n_alamouti = 0; errors_scrambling=0; n_false_positive = 0; + if (n_trials== 1) num_rounds = 1; + for (trial = 0; trial < n_trials; trial++) { errors_bit = 0; @@ -726,64 +1024,88 @@ int main(int argc, char **argv) //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0); UE->rx_offset=0; - UE_proc.frame_rx = frame; - UE_proc.nr_tti_rx= slot; - UE_proc.subframe_rx = slot; + UE_proc.thread_id = 0; + UE_proc.frame_rx = frame; + UE_proc.nr_slot_rx = slot; dcireq.frame = frame; dcireq.slot = slot; - NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE->current_thread_id[UE_proc.nr_tti_rx]][0][0]; + NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE_proc.thread_id][0][0]; int harq_pid = slot; NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid]; - NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_processes[slot]->pdsch_pdu.pdsch_pdu_rel15; + NR_gNB_DLSCH_t *gNB_dlsch = msgDataTx->dlsch[0][0]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; - UE_harq_process->harq_ack.ack = 0; + UE_harq_process->ack = 0; round = 0; UE_harq_process->round = round; - UE_harq_process->first_tx = 1; + UE_harq_process->first_rx = 1; - while ((roundharq_ack.ack==0)) { + while ((roundack==0)) { + memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int)); memset(RC.nrmac[0]->cce_list[1][1],0,MAX_NUM_CCE*sizeof(int)); clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); - UE_list->UE_sched_ctrl[0].harq_processes[harq_pid].ndi = !(trial&1); + UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].ndi = !(trial&1); - UE_list->UE_sched_ctrl[0].harq_processes[harq_pid].round = round; - UE_list->UE_sched_ctrl[0].current_harq_pid = harq_pid; - gNB->dlsch[0][0]->harq_processes[harq_pid]->round = round; + + UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round; + for (int i=0; iUE_info.num_pdcch_cand[0][i] = 0; - if (css_flag == 0) nr_schedule_uss_dlsch_phytest(0,frame,slot,&pucch_sched,&dlsch_config); - else nr_schedule_css_dlsch_phytest(0,frame,slot); + if (css_flag == 0) { + nr_schedule_ue_spec(0, frame, slot); + } else { + nr_schedule_css_dlsch_phytest(0,frame,slot); + } Sched_INFO.module_id = 0; Sched_INFO.CC_id = 0; Sched_INFO.frame = frame; Sched_INFO.slot = slot; Sched_INFO.DL_req = &gNB_mac->DL_req[0]; - Sched_INFO.UL_tti_req = &gNB_mac->UL_tti_req[0]; + Sched_INFO.UL_tti_req = gNB_mac->UL_tti_req_ahead[slot]; Sched_INFO.UL_dci_req = NULL; Sched_INFO.TX_req = &gNB_mac->TX_req[0]; nr_schedule_response(&Sched_INFO); - + + /* PTRS values for DLSIM calculations */ + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + pdu_bit_map = pdsch_pdu_rel15->pduBitmap; + if(pdu_bit_map & 0x1) { + set_ptrs_symb_idx(&dlPtrsSymPos, + pdsch_pdu_rel15->NrOfSymbols, + pdsch_pdu_rel15->StartSymbolIndex, + 1<PTRSTimeDensity, + pdsch_pdu_rel15->dlDmrsSymbPos); + ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols); + ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1)/rel15->PTRSFreqDensity); + printf("[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb ); + } + + msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234; + msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0; + msgDataTx->gNB = gNB; if (run_initial_sync) - nr_common_signal_procedures(gNB,frame,slot); + nr_common_signal_procedures(gNB,frame,slot,msgDataTx->ssb[0].ssb_pdu); else - phy_procedures_gNB_TX(gNB,frame,slot,0); + phy_procedures_gNB_TX(msgDataTx,frame,slot,1); int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP; if (n_trials==1) { - LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); + LOG_M("txsigF0.m","txsF0=", &gNB->common_vars.txdataF[0][txdataF_offset+2*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1); + LOG_M("txsigF1.m","txsF1=", &gNB->common_vars.txdataF[1][txdataF_offset+2*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); } int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); - if (n_trials==1) printf("samples_per_slot_wCP = %d\n", frame_parms->samples_per_slot_wCP); - + if (n_trials==1) printf("tx_offset %d, txdataF_offset %d \n", tx_offset,txdataF_offset); + //TODO: loop over slots for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { @@ -798,86 +1120,136 @@ int main(int argc, char **argv) nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset], &txdata[aa][tx_offset], 14, - frame_parms); + frame_parms, + slot); } } if (n_trials==1) { - LOG_M("txsig0.m","txs0", txdata[0],frame_length_complex_samples,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsig1.m","txs1", txdata[1],frame_length_complex_samples,1,1); + char filename[100];//LOG_M + for (aa=0;aaofdm_symbol_size+frame_parms->nb_prefix_samples0],6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples),1,1); + } } if (output_fd) { printf("writing txdata to binary file\n"); fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd); } - - int txlev = signal_energy(&txdata[0][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); - - // if (n_trials==1) printf("txlev %d (%f)\n",txlev,10*log10((double)txlev)); + + int txlev[n_tx]; + int txlev_sum = 0; + int l_ofdm = 6; + for (aa=0; aaofdm_symbol_size + (l_ofdm-1)*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); + txlev_sum += txlev[aa]; + if (n_trials==1) printf("txlev[%d] = %d (%f dB) txlev_sum %d\n",aa,txlev[aa],10*log10((double)txlev[aa]),txlev_sum); + } for (i=(frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)); i<(frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0)); i++) { for (aa=0; aanb_antennas_tx; aa++) { - r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); - r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); + s_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); + s_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); } } - - //AWGN - sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR; + + double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); + //Compute AWGN variance + sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR; sigma2 = pow(10, sigma2_dB/10); - if (n_trials==1) printf("sigma2 %f (%f dB), txlev %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize)); + if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize)); + + for (aa=0; aaget_samples_slot_timestamp(slot,frame_parms,0); iget_samples_slot_timestamp(slot+1,frame_parms,0); i++) { - for (aa=0; aanb_antennas_rx; aa++) { - ((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + for (int aa_rx=0; aa_rxcommon_vars.rxdata[aa_rx])[2*i] = (short) ((r_re[aa_rx][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) UE->common_vars.rxdata[aa_rx])[2*i+1] = (short) ((r_im[aa_rx][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + /* Add phase noise if enabled */ + if (pdu_bit_map & 0x1) { + phase_noise(ts, &((short*) UE->common_vars.rxdata[aa_rx])[2*i], + &((short*) UE->common_vars.rxdata[aa_rx])[2*i+1]); + } } } - + nr_ue_dcireq(&dcireq); //to be replaced with function pointer later nr_ue_scheduled_response(&scheduled_response); phy_procedures_nrUE_RX(UE, &UE_proc, 0, - do_pdcch_flag, - normal_txrx); + dlsch_threads, + NULL); //printf("dlsim round %d ends\n",round); round++; } // round - + //---------------------------------------------------------- //---------------------- count errors ---------------------- //---------------------------------------------------------- - - if (UE->dlsch[UE->current_thread_id[slot]][0][0]->last_iteration_cnt >= - UE->dlsch[UE->current_thread_id[slot]][0][0]->max_ldpc_iterations+1) + + if (UE->dlsch[UE_proc.thread_id][0][0]->last_iteration_cnt >= + UE->dlsch[UE_proc.thread_id][0][0]->max_ldpc_iterations+1) n_errors++; - - NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE->current_thread_id[UE_proc.nr_tti_rx]]; - int16_t *UE_llr = pdsch_vars[0]->llr[0]; - + + //NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE_proc.thread_id]; + //int16_t *UE_llr = pdsch_vars[0]->llr[0]; + TBS = UE_harq_process->TBS;//rel15->TBSize[0]; - uint16_t length_dmrs = 1; + uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos); uint16_t nb_rb = rel15->rbSize; uint8_t nb_re_dmrs = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4; uint8_t mod_order = rel15->qamModOrder[0]; uint8_t nb_symb_sch = rel15->NrOfSymbols; - + available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers); - + if(pdu_bit_map & 0x1) { + available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2); + printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) ); + } + + /* for (i = 0; i < available_bits; i++) { - - if(((gNB_dlsch->harq_processes[harq_pid]->f[i] == 0) && (UE_llr[i] <= 0)) || - ((gNB_dlsch->harq_processes[harq_pid]->f[i] == 1) && (UE_llr[i] >= 0))) + + if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) || + ((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0))) { if(errors_scrambling == 0) { LOG_D(PHY,"\n"); @@ -885,12 +1257,13 @@ int main(int argc, char **argv) } errors_scrambling++; } - + } + */ for (i = 0; i < TBS; i++) { - + estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7); - test_input_bit[i] = (gNB_dlsch->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments + test_input_bit[i] = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { if(errors_bit == 0) @@ -913,26 +1286,27 @@ int main(int argc, char **argv) printf("errors_bit = %u (trial %d)\n", errors_bit, trial); } roundStats[snrRun]+=((float)round); - if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round; + if (UE_harq_process->ack==1) effRate += ((float)TBS)/round; } // noise trials + blerStats[snrRun] = (float) n_errors / (float) n_trials; roundStats[snrRun]/=((float)n_trials); + berStats[snrRun] = (double)errors_scrambling/available_bits/n_trials; effRate /= n_trials; printf("*****************************************\n"); printf("SNR %f, (false positive %f)\n", SNR, (float) n_errors / (float) n_trials); printf("*****************************************\n"); printf("\n"); - printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %d bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS); + dump_pdsch_stats(stdout,gNB); + printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, BLER %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],berStats[snrRun],blerStats[snrRun],effRate,effRate/TBS*100,TBS); printf("\n"); if (print_perf==1) { - printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n", - 1000>>*scc->ssbSubcarrierSpacing,dlsch_config.rbSize,dlsch_config.mcsIndex[0], - gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3, - gNB->dlsch[0][0]->harq_processes[0]->K, - gNB->dlsch[0][0]->harq_processes[0]->K/((gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10)); - printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx"); + printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d)\n", + 1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex, + msgDataTx->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3); + printDistribution(gNB->phy_proc_tx_0,table_tx,"PHY proc tx"); printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time"); printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time"); printStatIndent3(&gNB->tinput,"DLSCH LDPC input processing time"); @@ -943,6 +1317,9 @@ int main(int argc, char **argv) printStatIndent3(&gNB->dlsch_interleaving_stats, "DLSCH Interleaving time"); printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time"); printStatIndent2(&gNB->dlsch_scrambling_stats, "DLSCH scrambling time"); + printStatIndent2(&gNB->dlsch_layer_mapping_stats, "DLSCH Layer Mapping time"); + printStatIndent2(&gNB->dlsch_resource_mapping_stats, "DLSCH Resource Mapping time"); + printStatIndent2(&gNB->dlsch_precoding_stats,"DLSCH Layer Precoding time"); printf("\nUE RX function statistics (per %d us slot)\n",1000>>*scc->ssbSubcarrierSpacing); @@ -960,9 +1337,9 @@ int main(int argc, char **argv) printStatIndent(&UE->dlsch_unscrambling_stats,"DLSCH unscrambling time"); printStatIndent(&UE->dlsch_rate_unmatching_stats,"DLSCH Rate Unmatching"); printf("|__ DLSCH Turbo Decoding(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n", - UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Cminus ? - UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kminus : - UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kplus, + UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Cminus ? + UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Kminus : + UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Kplus, UE->dlsch_tc_intl1_stats.trials/(double)UE->dlsch_tc_init_stats.trials, (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials*timeBase, (int)((double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials), @@ -982,20 +1359,27 @@ int main(int argc, char **argv) LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1); if (UE->frame_parms.nb_antennas_rx>1) LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1); - LOG_M("chestF0.m","chF0",UE->pdsch_vars[0][0]->dl_ch_estimates_ext,N_RB_DL*12*14,1,1); + LOG_M("chestF0.m","chF0",&UE->pdsch_vars[0][0]->dl_ch_estimates_ext[0][0],g_rbSize*12*14,1,1); write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1); + LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE_proc.thread_id][0]->llr[0],available_bits,1,0); + LOG_M("pdcch_rxFcomp.m","pdcch_rxFcomp",&UE->pdcch_vars[0][0]->rxdataF_comp[0][0],96*12,1,1); + LOG_M("pdcch_rxFllr.m","pdcch_rxFllr",UE->pdcch_vars[0][0]->llr,96*12,1,1); break; } - //if ((float)n_errors/(float)n_trials <= target_error_rate) { - if (effRate >= (eff_tp_check*TBS)) { + if (effRate > (eff_tp_check*TBS)) { printf("PDSCH test OK\n"); break; } + snrStats[snrRun] = SNR; snrRun++; } // NSR + LOG_M("dlsimStats.m","SNR",snrStats,snrRun,1,7); + LOG_MM("dlsimStats.m","BLER",blerStats,snrRun,1,7); + LOG_MM("dlsimStats.m","BER",berStats,snrRun,1,7); + LOG_MM("dlsimStats.m","rounds",roundStats,snrRun,1,7); /*if (n_trials>1) { printf("HARQ stats:\nSNR\tRounds\n"); psnr = snr0; @@ -1005,12 +1389,16 @@ int main(int argc, char **argv) } }*/ - for (i = 0; i < 2; i++) { + free_channel_desc_scm(gNB2UE); + + for (i = 0; i < n_tx; i++) { free(s_re[i]); free(s_im[i]); + free(txdata[i]); + } + for (i = 0; i < n_rx; i++) { free(r_re[i]); free(r_im[i]); - free(txdata[i]); } free(s_re); @@ -1032,3 +1420,136 @@ int main(int argc, char **argv) return(n_errors); } + + +void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg) +{ + NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0]; + int *ptrsFreqDenst = calloc(2, sizeof(long)); + ptrsFreqDenst[0]= 25; + ptrsFreqDenst[1]= 115; + int *ptrsTimeDenst = calloc(3, sizeof(long)); + ptrsTimeDenst[0]= 2; + ptrsTimeDenst[1]= 4; + ptrsTimeDenst[2]= 10; + + int epre_Ratio = 0; + int reOffset = 0; + + if(ptrs_arg[0] ==0) { + ptrsTimeDenst[2]= *mcsIndex -1; + } + else if(ptrs_arg[0] == 1) { + ptrsTimeDenst[1]= *mcsIndex - 1; + ptrsTimeDenst[2]= *mcsIndex + 1; + } + else if(ptrs_arg[0] ==2) { + ptrsTimeDenst[0]= *mcsIndex - 1; + ptrsTimeDenst[1]= *mcsIndex + 1; + } + else { + printf("[DLSIM] Wrong L_PTRS value, using default values 1\n"); + } + /* L = 4 if Imcs < MCS4 */ + if(ptrs_arg[1] ==2) { + ptrsFreqDenst[0]= *rbSize - 1; + ptrsFreqDenst[1]= *rbSize + 1; + } + else if(ptrs_arg[1] == 4) { + ptrsFreqDenst[1]= *rbSize - 1; + } + else { + printf("[DLSIM] Wrong K_PTRS value, using default values 2\n"); + } + printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<= 0 && dmrs_arg[1] <4 ) { + add_pos = dmrs_arg[1]; + } else { + AssertFatal(1==0,"Incorrect Additional Position, valid options 0-pos1, 1-pos1, 2-pos2, 3-pos3\n"); + } + + /* DMRS Conf Type 1 or 2 */ + if(dmrs_arg[2] == 1) { + dmrs_config_type = NFAPI_NR_DMRS_TYPE1; + } else if(dmrs_arg[2] == 2) { + dmrs_config_type = NFAPI_NR_DMRS_TYPE2; + } + + NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0]; + + AssertFatal((bwp->bwp_Dedicated->pdsch_Config != NULL && bwp->bwp_Dedicated->pdsch_Config->choice.setup != NULL), "Base RRC reconfig structures are not allocated.\n"); + + if(mapping_type == typeA) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + if (dmrs_config_type == NFAPI_NR_DMRS_TYPE2) + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type)); + else + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type = NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID0=NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID1=NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL; + printf("DLSIM: Allocated Mapping TypeA in RRC reconfig message\n"); + } + + if(mapping_type == typeB) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup)); + if (dmrs_config_type == NFAPI_NR_DMRS_TYPE2) + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type)); + else + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type = NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->maxLength=NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->scramblingID0=NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->scramblingID1=NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->phaseTrackingRS=NULL; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_AdditionalPosition = NULL; + printf("DLSIM: Allocated Mapping TypeB in RRC reconfig message\n"); + } + + struct NR_SetupRelease_DMRS_DownlinkConfig *dmrs_MappingtypeA = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA; + struct NR_SetupRelease_DMRS_DownlinkConfig *dmrs_MappingtypeB = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB; + + + NR_DMRS_DownlinkConfig_t *dmrs_config = (mapping_type == typeA) ? dmrs_MappingtypeA->choice.setup : dmrs_MappingtypeB->choice.setup; + + if (add_pos != 2) { // pos0,pos1,pos3 + if (dmrs_config->dmrs_AdditionalPosition == NULL) { + dmrs_config->dmrs_AdditionalPosition = calloc(1,sizeof(*dmrs_MappingtypeA->choice.setup->dmrs_AdditionalPosition)); + } + *dmrs_config->dmrs_AdditionalPosition = add_pos; + } else { // if NULL, Value pos2 + free(dmrs_config->dmrs_AdditionalPosition); + dmrs_config->dmrs_AdditionalPosition = NULL; + } + + for (int i=0;ibwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) { + bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type; + } + + printf("[DLSIM] DMRS Config is modified with Mapping Type %d, Additional Positions %d Config. Type %d \n", mapping_type, add_pos, dmrs_config_type); +} diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index c7ee863c35..056b018504 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -1,9 +1,37 @@ +#include "nfapi/oai_integration/vendor_ext.h" + int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { return(0); } int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } //int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } -//int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_config_request_t *dl_config_req) { return(0); } +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } + int32_t get_uldl_offset(int nr_bandP) { return(0); } NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);} +nfapi_mode_t nfapi_mod; +nfapi_mode_t nfapi_getmode(void) { + return nfapi_mod; +} int dummy_nr_ue_dl_indication(nr_downlink_indication_t *dl_info) { return(0); } int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); } +void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_rx_indication_t *rx_ind, + UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + uint8_t gNB_id) {} +void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, + uint8_t pdu_type, + uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + uint16_t n_pdus) {} diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c index bfb9150868..76f4e826ee 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c @@ -2,7 +2,16 @@ int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { re int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } -//int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_config_request_t *dl_config_req) { return(0); } +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } + int32_t get_uldl_offset(int nr_bandP) { return(0); } NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);} int dummy_nr_ue_dl_indication(nr_downlink_indication_t *dl_info) { return(0); } @@ -83,7 +92,6 @@ void nr_get_prach_resources(module_id_t mod_id, int CC_id, uint8_t gNB_id, uint8_t t_id, - uint8_t first_Msg3, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ @@ -206,9 +214,6 @@ void nr_get_prach_resources(module_id_t mod_id, AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB); } - // todo Msg3-DeltaPreamble should be provided from higher layers, otherwise is 0 - mac->deltaPreamble_Msg3 = 0; - deltaPreamble_Msg3 = mac->deltaPreamble_Msg3; } PLThreshold = prach_resources->RA_PCMAX - nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; @@ -316,7 +321,7 @@ void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint mac->RA_attempt_number++; } -void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){ +void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id){ AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Starting contention resolution timer\n", mod_id, frameP); NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index 7a465e0ea3..805913d055 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -55,190 +55,19 @@ signed char quantize(double D, double x, unsigned char B) { return ((char) qxd); } - -int8_t -mac_rrc_data_req_ue( - const module_id_t Mod_idP, - const int CC_id, - const frame_t frameP, - const rb_id_t Srb_id, - const uint8_t Nb_tb, - uint8_t *const buffer_pP, - const mac_enb_index_t eNB_indexP, - const uint8_t mbsfn_sync_area - ) { return(0);} - int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {return(0);} //NR_IF_Module_t *NR_IF_Module_init(int Mod_id){return(NULL);} int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } - -void fill_scc(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL,int N_RB_UL,int mu_dl,int mu_ul) { - - *scc->physCellId=0; \ - // *scc->n_TimingAdvanceOffset=NR_ServingCellConfigCommon__n_TimingAdvanceOffset_n0; - *scc->ssb_periodicityServingCell=NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms20; - scc->dmrs_TypeA_Position=NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2; - *scc->ssbSubcarrierSpacing=NR_SubcarrierSpacing_kHz30; - *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB=641032; - *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]=78; - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA=640000; - scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier=0; - scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing=NR_SubcarrierSpacing_kHz30; - - scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth=N_RB_DL; - scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth=13036; - scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing=mu_dl;//NR_SubcarrierSpacing_kHz30; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero=12; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero=0; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[0]->k0=0; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[0]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[0]->startSymbolAndLength=40; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[1]->k0=0; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[1]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[1]->startSymbolAndLength=53; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[2]->k0=0; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[2]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[2]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[3]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[3]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[3]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[4]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[4]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[4]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[5]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[5]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[5]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[6]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[6]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[6]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[7]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[7]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[7]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[8]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[8]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[8]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[9]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[9]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[9]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[10]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[10]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[10]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[11]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[11]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[11]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[12]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[12]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[12]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[13]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[13]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[13]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[14]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[14]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[14]->startSymbolAndLength=54; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[15]->k0=-1; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[15]->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[15]->startSymbolAndLength=54; - *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]=78; - *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA=-1; - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier=0; - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing=NR_SubcarrierSpacing_kHz30; - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth=N_RB_UL; - *scc->uplinkConfigCommon->frequencyInfoUL->p_Max=20; - scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth=13036; - scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing=mu_ul;//NR_SubcarrierSpacing_kHz30; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex=98; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM=NR_RACH_ConfigGeneric__msg1_FDM_one; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart=0; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig=13; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower=-118; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleTransMax=NR_RACH_ConfigGeneric__preambleTransMax_n10; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.powerRampingStep=NR_RACH_ConfigGeneric__powerRampingStep_dB2; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow=NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB__one_n64; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer=NR_RACH_ConfigCommon__ra_ContentionResolutionTimer_sf64; - *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB=19; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present=NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139=0; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig=NR_RACH_ConfigCommon__restrictedSetConfig_unrestrictedSet; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[0]->k2=2; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[0]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[0]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[1]->k2=2; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[1]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[1]->startSymbolAndLength=69; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[2]->k2=2; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[2]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[2]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[3]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[3]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[3]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[4]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[4]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[4]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[5]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[5]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[5]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[6]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[6]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[6]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[7]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[7]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[7]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[8]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[8]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[8]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[9]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[9]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[9]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[10]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[10]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[10]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[11]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[11]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[11]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[12]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[12]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[12]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[13]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[13]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[13]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[14]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[14]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[14]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[15]->k2=33; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[15]->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[15]->startSymbolAndLength=55; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble=1; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant=-90; - scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_GroupHopping=NR_PUCCH_ConfigCommon__pucch_GroupHopping_neither; - *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId=40; - *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal=-90; - scc->ssb_PositionsInBurst->present=NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap; - *ssb_bitmap=0xff; - scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing=NR_SubcarrierSpacing_kHz30; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity=NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms5; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots=7; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols=6; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots=2; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols=4; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity=321; - - scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots=-1; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols=-1; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSlots=-1; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSymbols=-1; - scc->ss_PBCH_BlockPower=20; - *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing=-1; -} - +void fill_scc_sim(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL,int N_RB_UL,int mu_dl,int mu_ul); void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap); void prepare_scc(NR_ServingCellConfigCommon_t *scc); -s1ap_eNB_config_t s1ap_config; -uint32_t s1ap_generate_eNB_id(void) {return 0;} +void prepare_scd(NR_ServingCellConfig_t *scd); +ngap_gNB_config_t ngap_config; +uint32_t ngap_generate_gNB_id(void) {return 0;} void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { return;} void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { return;} - +void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { return;} +void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { return;} #endif diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 8c37024858..1169b8ecd8 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -28,6 +28,7 @@ #include "common/config/config_userapi.h" #include "common/utils/LOG/log.h" #include "common/ran_context.h" +#include "common/utils/nr/nr_common.h" #include "PHY/types.h" #include "PHY/defs_nr_common.h" #include "PHY/defs_nr_UE.h" @@ -35,6 +36,7 @@ #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/MODULATION/modulation_eNB.h" #include "PHY/MODULATION/modulation_UE.h" +#include "PHY/MODULATION/nr_modulation.h" #include "PHY/INIT/phy_init.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" @@ -45,7 +47,8 @@ #include "openair1/SIMULATION/RF/rf.h" #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" #include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" - +#include "openair1/PHY/MODULATION/nr_modulation.h" +#include //#define DEBUG_NR_PBCHSIM PHY_VARS_gNB *gNB; @@ -54,15 +57,45 @@ RAN_CONTEXT_t RC; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; + +uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; +uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; + uint64_t get_softmodem_optmask(void) {return 0;} +softmodem_params_t *get_softmodem_params(void) {return 0;} void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} +int nr_ue_pdcch_procedures(uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int n_ss) { + return 0; +} + +int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int eNB_id, PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1) { + return 0; +} + +bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int gNB_id, + PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + int *dlsch_errors, + uint8_t dlsch_parallel) { + return false; +} + void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, int N_RB_DL, int N_RB_UL, @@ -95,22 +128,27 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, //gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED; gNB->mac_enabled = 1; - fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); - fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); if (mu>2) fp->nr_band = 257; else fp->nr_band = 78; fp->threequarter_fs= 0; gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band); + fp->ofdm_offset_divisor = UINT_MAX; nr_init_frame_parms(gNB_config, fp); + init_timeshift_rotation(fp); + + init_symbol_rotation(fp); + gNB->configured = 1; LOG_I(PHY,"gNB configured\n"); } int main(int argc, char **argv) { char c; - int i,aa;//,l; + int i,aa,start_symbol; double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0; double cfo=0; uint8_t snr1set=0; @@ -396,6 +434,7 @@ int main(int argc, char **argv) RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *)); RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; + gNB->ofdm_offset_divisor = UINT_MAX; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; @@ -405,7 +444,7 @@ int main(int argc, char **argv) frame_parms->ssb_type = nr_ssb_type_C; nr_phy_config_request_sim_pbchsim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); - phy_init_nr_gNB(gNB,0,0); + phy_init_nr_gNB(gNB,0,1); nr_set_ssb_first_subcarrier(&gNB->gNB_config,frame_parms); uint8_t n_hf = 0; @@ -417,29 +456,28 @@ int main(int argc, char **argv) switch (mu) { case 1: - scs = 30000; - if (N_RB_DL == 217) { - fs = 122.88e6; - bw = 80e6; - - } - else if (N_RB_DL == 245) { - fs = 122.88e6; - bw = 90e6; - } - else if (N_RB_DL == 273) { - fs = 122.88e6; - bw = 100e6; - } - else if (N_RB_DL == 106) { - fs = 61.44e6; - bw = 40e6; - } - else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL); - break; - - + scs = 30000; + frame_parms->Lmax = 8; + if (N_RB_DL == 217) { + fs = 122.88e6; + bw = 80e6; + } + else if (N_RB_DL == 245) { + fs = 122.88e6; + bw = 90e6; + } + else if (N_RB_DL == 273) { + fs = 122.88e6; + bw = 100e6; + } + else if (N_RB_DL == 106) { + fs = 61.44e6; + bw = 40e6; + } + else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL); + break; case 3: + frame_parms->Lmax = 64; scs = 120000; if (N_RB_DL == 66) { fs = 122.88e6; @@ -448,6 +486,7 @@ int main(int argc, char **argv) else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL); break; } + // cfo with respect to sub-carrier spacing eps = cfo/scs; @@ -467,9 +506,10 @@ int main(int argc, char **argv) channel_model, fs, bw, + 300e-9, 0, 0, - 0); + 0, 0); if (gNB2UE==NULL) { printf("Problem generating channel model. Exiting.\n"); @@ -500,7 +540,6 @@ int main(int argc, char **argv) printf("Allocating %d samples for txdata\n",frame_length_complex_samples); txdata[i] = malloc(frame_length_complex_samples*sizeof(int)); bzero(r_re[i],frame_length_complex_samples*sizeof(int)); - } if (pbch_file_fd!=NULL) { @@ -526,35 +565,69 @@ int main(int argc, char **argv) } nr_gold_pbch(UE); + + processingData_L1tx_t msgDataTx; // generate signal if (input_fd==NULL) { - gNB->pbch_configured = 1; - - gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0; - for (int slot=0;slotslots_per_frame;slot++) { - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) - memset(gNB->common_vars.txdataF[aa],0,frame_parms->samples_per_slot_wCP*sizeof(int32_t)); - - nr_common_signal_procedures (gNB,frame,slot); + for (i=0; iLmax; i++) { + if((SSB_positions >> i) & 0x01) { - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - if (cyclic_prefix_type == 1) { - PHY_ofdm_mod(gNB->common_vars.txdataF[aa], - &txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - } else { - nr_normal_prefix_mod(gNB->common_vars.txdataF[aa], - &txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], - 14, - frame_parms); - } - } + msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33; + msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i; + + start_symbol = nr_get_ssb_start_symbol(frame_parms,i); + int slot = start_symbol/14; + + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) + memset(gNB->common_vars.txdataF[aa],0,frame_parms->samples_per_slot_wCP*sizeof(int32_t)); + + nr_common_signal_procedures (gNB,frame,slot,msgDataTx.ssb[i].ssb_pdu); + + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + if (cyclic_prefix_type == 1) { + PHY_ofdm_mod(gNB->common_vars.txdataF[aa], + &txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], + frame_parms->ofdm_symbol_size, + 12, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } else { + /*nr_normal_prefix_mod(gNB->common_vars.txdataF[aa], + &txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], + 14, + frame_parms);*/ + PHY_ofdm_mod(gNB->common_vars.txdataF[aa], + (int*)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + + apply_nr_rotation(frame_parms, + (int16_t*)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], + slot, + 0, + 1, + frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0); + + PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][frame_parms->ofdm_symbol_size], + (int*)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+frame_parms->nb_prefix_samples0+frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size, + 13, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + + apply_nr_rotation(frame_parms, + (int16_t*)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+frame_parms->nb_prefix_samples0+frame_parms->ofdm_symbol_size], + slot, + 1, + 13, + frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); + } + } + } } - LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); if (gNB->frame_parms.nb_antennas_tx>1) LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1); @@ -563,9 +636,9 @@ int main(int argc, char **argv) printf("Reading %d samples from file to antenna buffer %d\n",frame_length_complex_samples,0); UE->UE_fo_compensation = 1; // perform fo compensation when samples from file are used if (fread(txdata[0], - sizeof(int32_t), - frame_length_complex_samples, - input_fd) != frame_length_complex_samples) { + sizeof(int32_t), + frame_length_complex_samples, + input_fd) != frame_length_complex_samples) { printf("error reading from file\n"); //exit(-1); } @@ -640,38 +713,35 @@ int main(int argc, char **argv) } if (UE->is_synchronized == 0) { UE_nr_rxtx_proc_t proc={0}; - ret = nr_initial_sync(&proc, UE, normal_txrx,1); + ret = nr_initial_sync(&proc, UE, 1, 0, 0); printf("nr_initial_sync1 returns %d\n",ret); if (ret<0) n_errors++; } else { + UE_nr_rxtx_proc_t proc={0}; UE->rx_offset=0; uint8_t ssb_index = 0; while (!((SSB_positions >> ssb_index) & 0x01)) ssb_index++; // to select the first transmitted ssb - frame_parms->ssb_index = ssb_index; - UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms); + UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms,ssb_index); - int ssb_slot = (ssb_index>>1)+(n_hf*frame_parms->slots_per_frame); + int ssb_slot = (UE->symbol_offset/14)+(n_hf*(frame_parms->slots_per_frame>>1)); for (int i=UE->symbol_offset+1; isymbol_offset+4; i++) { - nr_slot_fep(UE, - i%frame_parms->symbols_per_slot, - ssb_slot, - 0, - 0); + nr_slot_fep(UE, + &proc, + i%frame_parms->symbols_per_slot, + ssb_slot); - nr_pbch_channel_estimation(UE,0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf); + nr_pbch_channel_estimation(UE,&proc,0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf); } - UE_nr_rxtx_proc_t proc={0}; ret = nr_rx_pbch(UE, - &proc, - UE->pbch_vars[0], - frame_parms, - 0, - ssb_index%8, - SISO, - UE->high_speed_flag); + &proc, + UE->pbch_vars[0], + frame_parms, + 0, + ssb_index%8, + SISO); if (ret==0) { //UE->rx_ind.rx_indication_body->mib_pdu.ssb_index; //not yet detected automatically @@ -682,9 +752,9 @@ int main(int argc, char **argv) payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte); for (i=0;i<3;i++){ - payload_ret += (UE->pbch_vars[0]->decoded_output[i] == (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i))); + payload_ret += (UE->pbch_vars[0]->decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff)); } - //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->rx_ind.rx_indication_body->mib_pdu.additional_bits); + //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte); //printf("ret %d\n", payload_ret); if (payload_ret!=4) n_errors_payload++; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 950f9a67f6..a33713234c 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -37,6 +37,7 @@ #include "SCHED_NR_UE/phy_frame_config_nr.h" #include "PHY/phy_vars_nr_ue.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/MODULATION/nr_modulation.h" #include "PHY/MODULATION/modulation_eNB.h" #include "PHY/MODULATION/modulation_UE.h" #include "PHY/INIT/phy_init.h" @@ -45,53 +46,197 @@ #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "nr_unitary_defs.h" #include "OCG_vars.h" +#include +#include +#include +#include +#include +//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" #define NR_PRACH_DEBUG 1 #define PRACH_WRITE_OUTPUT_DEBUG 1 +LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; +rlc_info_t Rlc_info_um,Rlc_info_am_config; + PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; RU_t *ru; double cpuf; extern uint16_t prach_root_sequence_map0_3[838]; -uint16_t NB_UE_INST=1; openair0_config_t openair0_cfg[MAX_CARDS]; -uint8_t nfapi_mode=0; -int sl_ahead = 0; +//uint8_t nfapi_mode=0; +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +uint16_t sl_ahead = 0; +msc_interface_t msc_interface; +uint32_t N_RB_DL = 106; //void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe); /* temporary dummy implem of get_softmodem_optmask, till basic simulators implemented as device */ +msc_interface_t msc_interface; uint64_t get_softmodem_optmask(void) {return 0;} softmodem_params_t *get_softmodem_params(void) {return 0;} +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } -void pdcp_run (const protocol_ctxt_t *const ctxt_pP) { return;} +void +rrc_data_ind( + const protocol_ctxt_t *const ctxt_pP, + const rb_id_t Srb_id, + const sdu_size_t sdu_sizeP, + const uint8_t *const buffer_pP +) +{ +} -boolean_t pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, - const srb_flag_t srb_flagP, - const MBMS_flag_t MBMS_flagP, - const rb_id_t rb_idP, - const sdu_size_t sdu_buffer_sizeP, - mem_block_t *const sdu_buffer_pP) {return(false);} +int ocp_gtpv1u_create_s1u_tunnel(instance_t instance, + const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, + gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp) { + return 0; +} -void nr_ip_over_LTE_DRB_preconfiguration(void){} -void pdcp_layer_init(void) {} -int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) {return 0;} +int +gtpv1u_create_s1u_tunnel( + const instance_t instanceP, + const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, + gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP +) { + return 0; +} + +int +rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +) { + return 0; +} + +int +gtpv1u_create_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ + return 0; +} + +int +gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +){ + return 0; +} + +int ocp_gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { + return 0; +} + +int +nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +){ + return 0; +} + +int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, + const int CC_id, + const uint8_t gNB_index, + const frame_t frame, + const sub_frame_t sub_frame, + const rnti_t rnti, + const channel_t channel, + const uint8_t* pduP, + const sdu_size_t pdu_len) +{ + return 0; +} + +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} + +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) +{ + return 0; +} + +// Dummy function to avoid linking error at compilation of nr-prachsim +int is_x2ap_enabled(void) +{ + return 0; +} + +int nr_derive_key(int alg_type, uint8_t alg_id, + const uint8_t key[32], uint8_t **out) +{ + return 0; +} + +int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, + int CC_idP, + int UE_id, + rnti_t rntiP, + const uint8_t *sduP, + sdu_size_t sdu_lenP, + const uint8_t *sdu2P, + sdu_size_t sdu2_lenP) { + return 0; +} + +typedef struct { + uint64_t optmask; //mask to store boolean config options + uint8_t nr_dlsch_parallel; // number of threads for dlsch decoding, 0 means no parallelization + tpool_t Tpool; // thread pool +} nrUE_params_t; + +nrUE_params_t nrUE_params; + +nrUE_params_t *get_nrUE_params(void) { + return &nrUE_params; +} + +void processSlotTX(void *arg) {} int main(int argc, char **argv){ char c; double sigma2, sigma2_dB = 0, SNR, snr0 = -2.0, snr1 = 0.0, ue_speed0 = 0.0, ue_speed1 = 0.0; - double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs, bw; - int i, aa, aarx, **txdata, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1; + double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs=-1, bw; + int i, l, aa, aarx, **txdata, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1; int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0; uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0; - uint8_t frame = 1, subframe = 9, slot=19, slot_gNB=19, config_index = 98, prach_sequence_length = 1, num_root_sequences = 16, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol; + uint8_t frame = 1, slot=19, slot_gNB=19, config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol; uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1; - uint32_t tx_lev = 10000, prach_errors = 0, samp_count; //,tx_lev_dB; - uint64_t SSB_positions = 0x01, absoluteFrequencyPointA = 640000; + uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB; + uint64_t SSB_positions = 0x01; + uint16_t RA_sfn_index; + uint8_t N_RA_slot; + uint8_t config_period; + int prachOccasion = 0; + double DS_TDL = .03; + NB_UE_INST=1; // int8_t interf1=-19,interf2=-19; // uint8_t abstraction_flag=0,calibration_flag=0; @@ -119,7 +264,7 @@ int main(int argc, char **argv){ randominit(0); - while ((c = getopt (argc, argv, "hHaA:Cc:r:p:g:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) { + while ((c = getopt (argc, argv, "hHaA:Cc:l:r:p:g:m:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) { switch (c) { case 'a': printf("Running AWGN simulation\n"); @@ -132,6 +277,10 @@ int main(int argc, char **argv){ config_index = atoi(optarg); break; + case 'l': + loglvl = atoi(optarg); + break; + case 'r': msg1_frequencystart = atoi(optarg); break; @@ -209,6 +358,10 @@ int main(int argc, char **argv){ threequarter_fs=1; break; + case 'm': + mu = atoi(optarg); + break; + case 'n': n_frames = atoi(optarg); break; @@ -336,13 +489,6 @@ int main(int argc, char **argv){ } } - - if (config_index<67) { prach_sequence_length=0; slot = subframe*2; slot_gNB = 1+(subframe*2); } - uint16_t N_ZC; - N_ZC = prach_sequence_length == 0 ? 839 : 139; - - printf("Config_index %d, prach_sequence_length %d\n",config_index,prach_sequence_length); - // Configure log logInit(); set_glog(loglvl); @@ -377,12 +523,23 @@ int main(int argc, char **argv){ frame_parms->N_RB_UL = N_RB_UL; frame_parms->threequarter_fs = threequarter_fs; frame_parms->frame_type = TDD; - frame_parms->freq_range = nr_FR1; + frame_parms->freq_range = (mu==1 ? nr_FR1 : nr_FR2); frame_parms->numerology_index = mu; nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions); - //nsymb = (frame_parms->Ncp == 0) ? 14 : 12; + uint64_t absoluteFrequencyPointA = to_nrarfcn(frame_parms->nr_band, + frame_parms->dl_CarrierFreq, + frame_parms->numerology_index, + frame_parms->N_RB_UL*(180e3)*(1 << frame_parms->numerology_index)); + + uint8_t subframe = slot/frame_parms->slots_per_subframe; + + if (config_index<67 && mu==1) { prach_sequence_length=0; slot = subframe*2; slot_gNB = 1+(subframe*2); } + uint16_t N_ZC = prach_sequence_length == 0 ? 839 : 139; + + printf("Config_index %d, prach_sequence_length %d\n",config_index,prach_sequence_length); + printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Frame type %s, Frequency Range %s\n", NUMBER_OF_OFDM_CARRIERS, @@ -395,10 +552,18 @@ int main(int argc, char **argv){ ru->if_south = LOCAL_RF; ru->nb_tx = n_tx; ru->nb_rx = n_rx; - + ru->num_gNB = 1; + ru->gNB_list[0] = gNB; gNB->gNB_config.carrier_config.num_tx_ant.value = 1; gNB->gNB_config.carrier_config.num_rx_ant.value = 1; - gNB->gNB_config.tdd_table.tdd_period.value = 6; + if (mu==1) + gNB->gNB_config.tdd_table.tdd_period.value = 6; + else if (mu==3) + gNB->gNB_config.tdd_table.tdd_period.value = 3; + else { + printf("unsupported numerology %d\n",mu); + exit(-1); + } gNB->gNB_config.prach_config.num_prach_fd_occasions.value = num_prach_fd_occasions; gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(num_prach_fd_occasions*sizeof(nfapi_nr_num_prach_fd_occasions_t)); @@ -406,15 +571,18 @@ int main(int argc, char **argv){ gNB->proc.slot_rx = slot; int ret = get_nr_prach_info_from_index(config_index, - (int)frame, - (int)slot_gNB, - absoluteFrequencyPointA, - mu, - frame_parms->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur); + (int)frame, + (int)slot_gNB, + absoluteFrequencyPointA, + mu, + frame_parms->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period); if (ret == 0) {printf("No prach in %d.%d, mu %d, config_index %d\n",frame,slot,mu,config_index); exit(-1);} format0 = format&0xff; // first column of format from table @@ -423,60 +591,54 @@ int main(int argc, char **argv){ if (format1 != 0xff) { switch(format0) { case 0xa1: - prach_format = 9; + prach_format = 11; break; case 0xa2: - prach_format = 10; + prach_format = 12; break; case 0xa3: - prach_format = 11; + prach_format = 13; break; default: AssertFatal(1==0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); } } else { - switch(format0) { - case 0xa1: - prach_format = 0; - break; - case 0xa2: - prach_format = 1; - break; - case 0xa3: - prach_format = 2; - break; - case 0xb1: - prach_format = 3; - break; - case 0xb2: - prach_format = 4; - break; - case 0xb3: - prach_format = 5; - break; - case 0xb4: - prach_format = 6; - break; - case 0xc0: - prach_format = 7; - break; - case 0xc2: - prach_format = 8; - break; - case 0: - // long formats are handled @ PHY - break; - case 1: - // long formats are handled @ PHY - break; - case 2: - // long formats are handled @ PHY - break; - case 3: - // long formats are handled @ PHY - break; + switch(format0) { // single PRACH format + case 0: + prach_format = 0; + break; + case 1: + prach_format = 1; + break; + case 2: + prach_format = 2; + break; + case 3: + prach_format = 3; + break; + case 0xa1: + prach_format = 4; + break; + case 0xa2: + prach_format = 5; + break; + case 0xa3: + prach_format = 6; + break; + case 0xb1: + prach_format = 7; + break; + case 0xb4: + prach_format = 8; + break; + case 0xc0: + prach_format = 9; + break; + case 0xc2: + prach_format = 10; + break; default: - AssertFatal(1==0, "Invalid PRACH format"); + AssertFatal(1 == 0, "Invalid PRACH format"); } } @@ -492,7 +654,7 @@ int main(int argc, char **argv){ memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); RC.nb_nr_L1_inst=1; - phy_init_nr_gNB(gNB,0,0); + phy_init_nr_gNB(gNB,0,1); //lowmem nr_phy_init_RU(ru); gNB->common_vars.rxdata = ru->common.rxdata; set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); @@ -557,9 +719,10 @@ int main(int argc, char **argv){ channel_model, fs, bw, + DS_TDL, 0.0, delay, - 0); + 0, 0); if (UE2gNB==NULL) { printf("Problem generating channel model. Exiting.\n"); @@ -595,14 +758,14 @@ int main(int argc, char **argv){ subframe); */ //commented for testing purpose UE_nr_rxtx_proc_t proc={0}; - proc.frame_tx = frame; - proc.nr_tti_tx = slot; - nr_ue_prach_procedures(UE,&proc,0,0); + proc.frame_tx = frame; + proc.nr_slot_tx = slot; + nr_ue_prach_procedures(UE, &proc, 0); /* tx_lev_dB not used later, no need to set */ //tx_lev_dB = (unsigned int) dB_fixed(tx_lev); - prach_start = subframe*frame_parms->samples_per_subframe-UE->N_TA_offset; + prach_start = subframe*frame_parms->samples_per_subframe; #ifdef NR_PRACH_DEBUG LOG_M("txsig0.m", "txs0", &txdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); @@ -673,7 +836,7 @@ int main(int argc, char **argv){ // printf("Sigma2 %f (sigma2_dB %f)\n",sigma2,sigma2_dB); if (awgn_flag == 0) { - multipath_tv_channel(UE2gNB, s_re, s_im, r_re, r_im, frame_parms->samples_per_tti<<1, 0); + multipath_tv_channel(UE2gNB, s_re, s_im, r_re, r_im, frame_parms->samples_per_frame, 0); } if (n_frames==1) { @@ -697,12 +860,22 @@ int main(int argc, char **argv){ } } + for (l = 0; l < frame_parms->symbols_per_slot; l++) { + for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + nr_slot_fep_ul(frame_parms, + ru->common.rxdata[aa], + ru->common.rxdataF[aa], + l, + slot, + ru->N_TA_offset); + } + } + + rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, prachOccasion, frame, slot); - rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, frame, slot); - - gNB->prach_vars.rxsigF = ru->prach_rxsigF; + gNB->prach_vars.rxsigF = ru->prach_rxsigF[prachOccasion]; if (n_frames == 1) printf("ncs %d,num_seq %d\n",prach_pdu->num_cs, prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); - rx_nr_prach(gNB, prach_pdu, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay); + rx_nr_prach(gNB, prach_pdu, prachOccasion, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay); // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx); @@ -720,7 +893,8 @@ int main(int argc, char **argv){ LOG_M("prachF0.m","prachF0", &gNB->prach_vars.prachF[0], N_ZC, 1, 1); LOG_M("rxsig0.m","rxs0", &gNB->common_vars.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); - LOG_M("rxsigF0.m","rxsF0", gNB->prach_vars.rxsigF[0], N_ZC, 1, 1); + LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1); + LOG_M("ru_prach_rxsigF0.m","rxsF0", ru->prach_rxsigF[0][0], N_ZC, 1, 1); LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1); LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1); #endif diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 86f7d651e4..213924e5fd 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -35,6 +35,7 @@ #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/MODULATION/modulation_eNB.h" #include "PHY/MODULATION/modulation_UE.h" +#include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "PHY/INIT/phy_init.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" @@ -45,6 +46,7 @@ #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" #include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" + PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; @@ -52,8 +54,10 @@ openair0_config_t openair0_cfg[MAX_CARDS]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; +uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; +uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; // needed for some functions PHY_VARS_NR_UE * PHY_vars_UE_g[1][1]={{NULL}}; @@ -63,7 +67,7 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} int main(int argc, char **argv) { char c; - int i,aa=0;//,l; + int i;//,l; double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0; double cfo=0; uint8_t snr1set=0; @@ -77,17 +81,18 @@ int main(int argc, char **argv) //int freq_offset; //int subframe_offset; //char fname[40], vname[40]; - int trial,n_trials=100,n_errors=0,ack_nack_errors=0; + int trial,n_trials=100,n_errors=0,ack_nack_errors=0,sr_errors=0; uint8_t transmission_mode = 1,n_tx=1,n_rx=1; uint16_t Nid_cell=0; uint64_t SSB_positions=0x01; - channel_desc_t *gNB2UE; + channel_desc_t *UE2gNB; int format=0; //uint8_t extended_prefix_flag=0; FILE *input_fd=NULL; //uint8_t nacktoack_flag=0; int16_t amp=0x7FFF; - int nr_tti_tx=0; + int nr_slot_tx=0; + int nr_frame_tx=0; uint64_t actual_payload=0,payload_received; int nr_bit=1; // maximum value possible is 2 uint8_t m0=0;// higher layer paramater initial cyclic shift @@ -97,7 +102,10 @@ int main(int argc, char **argv) uint16_t nrofPRB=2; uint8_t timeDomainOCC=0; SCM_t channel_model=AWGN;//Rayleigh1_anticorr; - + + double DS_TDL = .03; + + double delay_us = 0; int N_RB_DL=273,mu=1; float target_error_rate=0.001; int frame_length_complex_samples; @@ -106,7 +114,7 @@ int main(int argc, char **argv) //unsigned char frame_type = 0; int loglvl=OAILOG_WARNING; int sr_flag = 0; - + int pucch_DTX_thres = 50; cpuf = get_cpu_freq_GHz(); if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) { @@ -116,7 +124,7 @@ int main(int argc, char **argv) randominit(0); logInit(); - while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:c")) != -1) { + while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:t:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:cd:")) != -1) { switch (c) { case 'f': //write_output_file=1; @@ -159,6 +167,20 @@ int main(int argc, char **argv) case 'G': channel_model=ETU; break; + case 'H': + channel_model = TDL_C; + DS_TDL = .030; // 30 ns + break; + + case 'I': + channel_model = TDL_C; + DS_TDL = .3; // 300ns + break; + + case 'J': + channel_model=TDL_D; + DS_TDL = .03; + break; default: printf("Unsupported channel model!\n"); @@ -186,11 +208,11 @@ int main(int argc, char **argv) printf("Setting SNR1 to %f\n",snr1); break; - /* + case 't': - Td= atof(optarg); + pucch_DTX_thres= atoi(optarg); break; - + /* case 'p': extended_prefix_flag=1; break; @@ -207,6 +229,9 @@ int main(int argc, char **argv) } break; */ + case 'd': + delay_us=atof(optarg); + break; case 'x': transmission_mode=atoi(optarg); @@ -230,7 +255,7 @@ int main(int argc, char **argv) case 'z': n_rx=atoi(optarg); - if ((n_rx==0) || (n_rx>2)) { + if ((n_rx==0) || (n_rx>8)) { printf("Unsupported number of rx antennas %d\n",n_rx); exit(-1); } @@ -325,29 +350,33 @@ int main(int argc, char **argv) } } + double phase = (1<2)&&(nr_bit<65)),"illegal combination format %d, nr_bit %d\n", format,nr_bit); + int do_DTX=0; + if ((format < 2) && (actual_payload == 4)) do_DTX=1; actual_payload &= ((1<pucch0_thres = pucch_DTX_thres; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; @@ -399,9 +428,9 @@ int main(int argc, char **argv) printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO); } - gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, fs, bw, 0, 0, 0); + UE2gNB = new_channel_desc_scm(n_tx, n_rx, channel_model, fs, bw, DS_TDL,0, 0, 0, 0); - if (gNB2UE==NULL) { + if (UE2gNB==NULL) { printf("Problem generating channel model. Exiting.\n"); exit(-1); } @@ -409,177 +438,313 @@ int main(int argc, char **argv) frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP; - s_re = malloc(2*sizeof(double*)); - s_im = malloc(2*sizeof(double*)); - r_re = malloc(2*sizeof(double*)); - r_im = malloc(2*sizeof(double*)); - txdataF = malloc(2*sizeof(int*)); - rxdataF = malloc(2*sizeof(int*)); + s_re = malloc(n_tx*sizeof(double*)); + s_im = malloc(n_tx*sizeof(double*)); + r_re = malloc(n_rx*sizeof(double*)); + r_im = malloc(n_rx*sizeof(double*)); + txdataF = malloc(n_tx*sizeof(int*)); + rxdataF = malloc(n_rx*sizeof(int*)); gNB->common_vars.rxdataF=rxdataF; memcpy((void*)&gNB->frame_parms,(void*)frame_parms,sizeof(frame_parms)); - for (i=0; i<2; i++) { - - s_re[i] = malloc(frame_length_complex_samples*sizeof(double)); - bzero(s_re[i],frame_length_complex_samples*sizeof(double)); - s_im[i] = malloc(frame_length_complex_samples*sizeof(double)); - bzero(s_im[i],frame_length_complex_samples*sizeof(double)); - - r_re[i] = malloc(frame_length_complex_samples*sizeof(double)); - bzero(r_re[i],frame_length_complex_samples*sizeof(double)); - r_im[i] = malloc(frame_length_complex_samples*sizeof(double)); - bzero(r_im[i],frame_length_complex_samples*sizeof(double)); - - printf("Allocating %d samples for txdataF/rxdataF\n",14*frame_parms->ofdm_symbol_size); - txdataF[i] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int)); - bzero(txdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int)); - rxdataF[i] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int)); - bzero(rxdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int)); + for (int aatx=0; aatxsymbols_per_slot*frame_parms->ofdm_symbol_size); + txdataF[aatx] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int)); + bzero(txdataF[aatx],14*frame_parms->ofdm_symbol_size*sizeof(int)); } + for (int aarx=0; aarxsymbols_per_slot*frame_parms->ofdm_symbol_size); + rxdataF[aarx] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int)); + bzero(rxdataF[aarx],14*frame_parms->ofdm_symbol_size*sizeof(int)); + } + + uint8_t mcs=0; + int shift = 0; + if(format==0){ + if (sr_flag) + shift = 1< 11) gNB->uci_polarParams = nr_polar_params(2, nr_bit, nrofPRB, 1, NULL); + + startingPRB_intraSlotHopping = N_RB_DL-1; + uint32_t hopping_id = Nid_cell; + uint32_t dmrs_scrambling_id = 0; + uint32_t data_scrambling_id = 0; //configure UE - UE = malloc(sizeof(PHY_VARS_NR_UE)); + UE = calloc(1,sizeof(PHY_VARS_NR_UE)); memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS)); - UE->pucch_config_common_nr->hoppingId = Nid_cell; - //phy_init_nr_top(UE); //called from init_nr_ue_signal - + UE->frame_parms.nb_antennas_rx=1; UE->perfect_ce = 0; if(eps!=0.0) - UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation + UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation if (init_nr_ue_signal(UE, 1, 0) != 0) { printf("Error at UE NR initialisation\n"); exit(-1); } - uint8_t mcs=0; - startingPRB_intraSlotHopping=N_RB_DL-1; - pucch_GroupHopping_t PUCCH_GroupHopping=UE->pucch_config_common_nr->pucch_GroupHopping; - uint32_t hopping_id=UE->pucch_config_common_nr->hoppingId; - uint32_t dmrs_scrambling_id = 0, data_scrambling_id=0; - //t_nrPolar_params *currentPtr; - if(format==0){ - // for now we are not considering SR just HARQ-ACK - if (nr_bit ==0) - mcs=table1_mcs[0]; - else if(nr_bit==1) - mcs=table1_mcs[actual_payload]; - else if(nr_bit==2) - mcs=table2_mcs[actual_payload]; - else AssertFatal(1==0,"Either nr_bit %d or sr_flag %d must be non-zero\n", nr_bit, sr_flag); + fapi_nr_ul_config_pucch_pdu pucch_tx_pdu; + if (format==0) { + pucch_tx_pdu.format_type = 0; + pucch_tx_pdu.nr_of_symbols = nrofSymbols; + pucch_tx_pdu.start_symbol_index = startingSymbolIndex; + pucch_tx_pdu.bwp_start = 0; + pucch_tx_pdu.prb_start = startingPRB; + pucch_tx_pdu.hopping_id = hopping_id; + pucch_tx_pdu.group_hop_flag = 0; + pucch_tx_pdu.sequence_hop_flag = 0; + pucch_tx_pdu.freq_hop_flag = 0; + pucch_tx_pdu.mcs = mcs; + pucch_tx_pdu.initial_cyclic_shift = 0; + pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping; } - else if (format == 2 && nr_bit > 11) gNB->uci_polarParams = nr_polar_params(2, nr_bit, nrofPRB, 1, NULL); - - for(SNR=snr0;SNR<=snr1;SNR=SNR+1){ + if (format==2) { + pucch_tx_pdu.format_type = 2; + pucch_tx_pdu.rnti = 0x1234; + pucch_tx_pdu.n_bit = nr_bit; + pucch_tx_pdu.payload = actual_payload; + pucch_tx_pdu.nr_of_symbols = nrofSymbols; + pucch_tx_pdu.start_symbol_index = startingSymbolIndex; + pucch_tx_pdu.bwp_start = 0; + pucch_tx_pdu.prb_start = startingPRB; + pucch_tx_pdu.prb_size = nrofPRB; + pucch_tx_pdu.hopping_id = hopping_id; + pucch_tx_pdu.group_hop_flag = 0; + pucch_tx_pdu.sequence_hop_flag = 0; + pucch_tx_pdu.freq_hop_flag = 0; + pucch_tx_pdu.dmrs_scrambling_id = dmrs_scrambling_id; + pucch_tx_pdu.data_scrambling_id = data_scrambling_id; + pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping; + } + + pucch_GroupHopping_t PUCCH_GroupHopping = pucch_tx_pdu.group_hop_flag + (pucch_tx_pdu.sequence_hop_flag<<1); + + for(SNR=snr0;SNR<=snr1;SNR+=1){ ack_nack_errors=0; + sr_errors=0; n_errors = 0; for (trial=0; trialofdm_symbol_size*sizeof(int)); + for (int aatx=0;aatx<1;aatx++) + bzero(txdataF[aatx],frame_parms->ofdm_symbol_size*sizeof(int)); + if(format==0 && do_DTX==0){ + nr_generate_pucch0(UE, txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu); + } else if (format == 1 && do_DTX==0){ + nr_generate_pucch1(UE, txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu); + } else if (do_DTX == 0){ + nr_generate_pucch2(UE, txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu); + } + + // SNR Computation + // standard says: SNR = S / N, where S is the total signal energy, N is the noise energy in the transmission bandwidth (i.e. N_RB_DL resource blocks) + // txlev = S. + int txlev = signal_energy(&txdataF[0][startingSymbolIndex*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size); + + // sigma2 is variance per dimension, so N/(N_RB*12) + // so, sigma2 = N/(N_RB_DL*12) => (S/SNR)/(N_RB*12) + int N_RB = (format == 0 || format == 1) ? 1 : nrofPRB; + sigma2_dB = 10*log10(txlev*(N_RB_DL/N_RB))-SNR; + sigma2 = pow(10.0,sigma2_dB/10.0); + + if (n_trials==1) printf("txlev %d (%f dB), offset %d, sigma2 %f ( %f dB)\n",txlev,10*log10(txlev),startingSymbolIndex*frame_parms->ofdm_symbol_size,sigma2,sigma2_dB); + + int i0; + double txr,txi,rxr,rxi,nr,ni; + for (int symb=0; symbframe_parms.symbols_per_slot;symb++) { + if (symb= startingSymbolIndex+nrofSymbols) { + i0 = symb*gNB->frame_parms.ofdm_symbol_size; + for (int re=0;reframe_parms.first_carrier_offset + re)%gNB->frame_parms.ofdm_symbol_size); + for (int aarx=0;aarxframe_parms.ofdm_symbol_size; + for (int re=0;reframe_parms.first_carrier_offset + re)%gNB->frame_parms.ofdm_symbol_size); + phasor.r = cos(2*M_PI*phase*re); + phasor.i = sin(2*M_PI*phase*re); + for (int aarx=0;aarxchF[aarx][re].r - txi*UE2gNB->chF[aarx][re].i; + rxi = txr*UE2gNB->chF[aarx][re].i + txi*UE2gNB->chF[aarx][re].r; + rxr_tmp = rxr*phasor.r - rxi*phasor.i; + rxi = rxr*phasor.i + rxi*phasor.r; + rxr = rxr_tmp; + nr = sqrt(sigma2/2)*gaussdouble(0.0,1.0); + ni = sqrt(sigma2/2)*gaussdouble(0.0,1.0); + ((int16_t*)rxdataF[aarx])[i<<1] = (int16_t)(100.0*(rxr + nr)/sqrt((double)txlev)); + ((int16_t*)rxdataF[aarx])[1+(i<<1)]=(int16_t)(100.0*(rxi + ni)/sqrt((double)txlev)); + + if (n_trials==1 && abs(txr) > 0) printf("symb %d, re %d , aarx %d : txr %f, txi %f, chr %f, chi %f, nr %f, ni %f, rxr %f, rxi %f => %d,%d\n", + symb, re, aarx, txr,txi, + UE2gNB->chF[aarx][re].r,UE2gNB->chF[aarx][re].i, + nr,ni, rxr,rxi, + ((int16_t*)rxdataF[aarx])[i<<1],((int16_t*)rxdataF[aarx])[1+(i<<1)]); + } + } + } + + int rxlev=0; + for (int aarx=0;aarxofdm_symbol_size], + frame_parms->ofdm_symbol_size); + + int rxlev_pucch=0; + + for (int aarx=0;aarxofdm_symbol_size], + 12); + + // set UL mask for pucch allocation + for (int s=0;ssymbols_per_slot;s++){ + if (s>=startingSymbolIndex && s<(startingSymbolIndex+nrofSymbols)) + for (int rb=0; rbrb_mask_ul[s][rb2>>5] |= (1<<(rb2&31)); + } + } + + // noise measurement (all PRBs) + gNB_I0_measurements(gNB, nr_slot_tx, 0, gNB->frame_parms.symbols_per_slot); + + if (n_trials==1) printf("noise rxlev %d (%d dB), rxlev pucch %d dB sigma2 %f dB, SNR %f, TX %f, I0 (pucch) %d, I0 (avg) %d\n",rxlev,dB_fixed(rxlev),dB_fixed(rxlev_pucch),sigma2_dB,SNR,10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/12),gNB->measurements.n0_subband_power_tot_dB[startingPRB],gNB->measurements.n0_subband_power_avg_dB); if(format==0){ - nr_generate_pucch0(UE,txdataF,frame_parms,PUCCH_GroupHopping,hopping_id,amp,nr_tti_tx,m0,mcs,nrofSymbols,startingSymbolIndex,startingPRB); - } - else if (format == 1){ - nr_generate_pucch1(UE,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,0,nr_bit); - } - else { - nr_generate_pucch2(UE,0x1234,dmrs_scrambling_id,data_scrambling_id,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,nrofSymbols,startingSymbolIndex,nrofPRB,startingPRB,nr_bit); - } - - int txlev = signal_energy(&txdataF[aa][startingSymbolIndex*frame_parms->ofdm_symbol_size], - frame_parms->ofdm_symbol_size); - // printf("txlev %d (%d dB), offset %d\n",txlev,dB_fixed(txlev),startingSymbolIndex*frame_parms->ofdm_symbol_size); - - // note : this scaling - int nb_re = (format == 0 || format == 1)? 12 : 12*nrofPRB; - sigma2_dB = 10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/nb_re)-SNR; - sigma2 = pow(10,sigma2_dB/10); - - for(i=startingSymbolIndex*frame_parms->ofdm_symbol_size; i<(startingSymbolIndex+1)*frame_parms->ofdm_symbol_size; i++) { - ((int16_t*)rxdataF[aa])[i<<1] = (int16_t)(100.0*((double)(((int16_t *)txdataF[aa])[(i<<1)]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))/sqrt((double)txlev)); - ((int16_t*)rxdataF[aa])[1+(i<<1)]=(int16_t)(100.0*((double)(((int16_t *)txdataF[aa])[(i<<1)+1])+ sqrt(sigma2/2)*gaussdouble(0.0,1.0))/sqrt((double)txlev)); - } - int rxlev = signal_energy(&rxdataF[aa][startingSymbolIndex*frame_parms->ofdm_symbol_size], - frame_parms->ofdm_symbol_size); - if (n_trials==1) printf("rxlev %d (%d dB), sigma2 %f dB, SNR %f, TX %f\n",rxlev,dB_fixed(rxlev),sigma2_dB,SNR,10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/12)); - if(format==0){ - nfapi_nr_uci_pucch_pdu_format_0_1_t uci_pdu; - nfapi_nr_pucch_pdu_t pucch_pdu; - pucch_pdu.subcarrier_spacing = 1; - pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; - pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; - pucch_pdu.bit_len_harq = nr_bit; - pucch_pdu.bit_len_csi_part1 = 0; - pucch_pdu.bit_len_csi_part2 = 0; - pucch_pdu.sr_flag = sr_flag; - pucch_pdu.nr_of_symbols = nrofSymbols; - pucch_pdu.hopping_id = hopping_id; - pucch_pdu.initial_cyclic_shift = 0; - pucch_pdu.start_symbol_index = startingSymbolIndex; - pucch_pdu.prb_start = startingPRB; - nr_decode_pucch0(gNB,nr_tti_tx,&uci_pdu,&pucch_pdu); - if(nr_bit==1) - ack_nack_errors+=(actual_payload^uci_pdu.harq->harq_list[0].harq_value); - else - ack_nack_errors+=(((actual_payload&1)^uci_pdu.harq->harq_list[0].harq_value)+((actual_payload>>1)^uci_pdu.harq->harq_list[1].harq_value)); - free(uci_pdu.harq->harq_list); + nfapi_nr_uci_pucch_pdu_format_0_1_t uci_pdu; + nfapi_nr_pucch_pdu_t pucch_pdu; + gNB->uci_stats[0].rnti = 0x1234; + pucch_pdu.rnti = 0x1234; + pucch_pdu.subcarrier_spacing = 1; + pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; + pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; + pucch_pdu.bit_len_harq = nr_bit; + pucch_pdu.bit_len_csi_part1 = 0; + pucch_pdu.bit_len_csi_part2 = 0; + pucch_pdu.sr_flag = sr_flag; + pucch_pdu.nr_of_symbols = nrofSymbols; + pucch_pdu.hopping_id = hopping_id; + pucch_pdu.initial_cyclic_shift = 0; + pucch_pdu.start_symbol_index = startingSymbolIndex; + pucch_pdu.prb_start = startingPRB; + pucch_pdu.bwp_start = 0; + pucch_pdu.bwp_size = N_RB_DL; + if (nrofSymbols>1) { + pucch_pdu.freq_hop_flag = 1; + pucch_pdu.second_hop_prb = N_RB_DL-1; + } + else pucch_pdu.freq_hop_flag = 0; + + nr_decode_pucch0(gNB, nr_frame_tx, nr_slot_tx,&uci_pdu,&pucch_pdu); + if(sr_flag==1){ + if (uci_pdu.sr->sr_indication == 0 || uci_pdu.sr->sr_confidence_level == 1) + sr_errors+=1; + } + // harq value 0 -> pass + // confidence value 0 -> good confidence + const int harq_value0 = uci_pdu.harq->harq_list[0].harq_value; + const int harq_value1 = uci_pdu.harq->harq_list[1].harq_value; + const int confidence_lvl = uci_pdu.harq->harq_confidence_level; + if(nr_bit>0){ + if (nr_bit==1 && do_DTX == 0) + ack_nack_errors+=(actual_payload^(!harq_value0)); + else if (do_DTX == 0) + ack_nack_errors+=(((actual_payload&1)^(!harq_value0))+((actual_payload>>1)^(!harq_value1))); + else if ((!confidence_lvl && !harq_value0) || + (!confidence_lvl && nr_bit == 2 && !harq_value1)) + ack_nack_errors++; + free(uci_pdu.harq->harq_list); + } } else if (format==1) { - - nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,hopping_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,hopping_id, + &(payload_received),frame_parms,amp,nr_slot_tx, + m0,nrofSymbols,startingSymbolIndex,startingPRB, + startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); if(nr_bit==1) ack_nack_errors+=((actual_payload^payload_received)&1); else ack_nack_errors+=((actual_payload^payload_received)&1) + (((actual_payload^payload_received)&2)>>1); } else if (format==2) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu; - nfapi_nr_pucch_pdu_t pucch_pdu; - pucch_pdu.rnti = 0x1234; - pucch_pdu.subcarrier_spacing = 1; - pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; - pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; - pucch_pdu.bit_len_csi_part1 = nr_bit; - pucch_pdu.bit_len_harq = 0; - pucch_pdu.bit_len_csi_part2 = 0; - pucch_pdu.sr_flag = 0; - pucch_pdu.nr_of_symbols = nrofSymbols; - pucch_pdu.hopping_id = hopping_id; - pucch_pdu.initial_cyclic_shift = 0; - pucch_pdu.start_symbol_index = startingSymbolIndex; - pucch_pdu.prb_size = nrofPRB; - pucch_pdu.prb_start = startingPRB; - pucch_pdu.dmrs_scrambling_id = dmrs_scrambling_id; - pucch_pdu.data_scrambling_id = data_scrambling_id; - nr_decode_pucch2(gNB,nr_tti_tx,&uci_pdu,&pucch_pdu); - int csi_part1_bytes=pucch_pdu.bit_len_csi_part1>>3; - if ((pucch_pdu.bit_len_csi_part1&7) > 0) csi_part1_bytes++; - for (int i=0;i>1)&1; + pucch_pdu.bit_len_csi_part1 = nr_bit; + pucch_pdu.bit_len_harq = 0; + pucch_pdu.bit_len_csi_part2 = 0; + pucch_pdu.sr_flag = 0; + pucch_pdu.nr_of_symbols = nrofSymbols; + pucch_pdu.hopping_id = hopping_id; + pucch_pdu.initial_cyclic_shift = 0; + pucch_pdu.start_symbol_index = startingSymbolIndex; + pucch_pdu.prb_size = nrofPRB; + pucch_pdu.prb_start = startingPRB; + pucch_pdu.dmrs_scrambling_id = dmrs_scrambling_id; + pucch_pdu.data_scrambling_id = data_scrambling_id; + if (nrofSymbols>1) { + pucch_pdu.freq_hop_flag = 1; + pucch_pdu.second_hop_prb = N_RB_DL-1; + } + else pucch_pdu.freq_hop_flag = 0; + nr_decode_pucch2(gNB,nr_slot_tx,&uci_pdu,&pucch_pdu); + int csi_part1_bytes=pucch_pdu.bit_len_csi_part1>>3; + if ((pucch_pdu.bit_len_csi_part1&7) > 0) csi_part1_bytes++; + for (int i=0;i>1)+(((actual_payload^payload_received)&4)>>2)+n_errors; } - printf("SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors); - if((float)ack_nack_errors/(float)(n_trials)<=target_error_rate){ + if (sr_flag == 1) + printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,sr_errors); + if(nr_bit > 0) + printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors); + if((float)(ack_nack_errors+sr_errors)/(float)(n_trials)<=target_error_rate){ printf("PUCCH test OK\n"); break; } } - for (i=0; i<2; i++) { - free(s_re[i]); - free(s_im[i]); - free(r_re[i]); - free(r_im[i]); - free(txdataF[i]); - free(rxdataF[i]); + for (int aatx=0; aatxulsch_harq; + NR_gNB_ULSCH_t *ulsch = rdata->ulsch; + int r = rdata->segment_r; + + bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter); + ulsch_harq->processedSegments++; + gNB->nbDecode--; + + if (decodeSuccess) { + memcpy(ulsch_harq->b+rdata->offset, + ulsch_harq->c[r], + rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0)); + } else { + if ( rdata->nbSegments != ulsch_harq->processedSegments ) { + int nb=abortTpool(gNB->threadPool, req->key); + nb+=abortNotifiedFIFO(gNB->respDecode, req->key); + gNB->nbDecode-=nb; + AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", + ulsch_harq->processedSegments, nb, rdata->nbSegments); + ulsch_harq->processedSegments=rdata->nbSegments; + return 1; + } + } + + // if all segments are done + if (rdata->nbSegments == ulsch_harq->processedSegments) { + if (decodeSuccess) { + return 0; + } else { + return 1; + } + + } + ulsch->last_iteration_cnt = rdata->decodeIterations; + return 0; +} int main(int argc, char **argv) { char c; @@ -89,13 +131,15 @@ int main(int argc, char **argv) NR_DL_FRAME_PARMS *frame_parms; double sigma; unsigned char qbits = 8; - int ret; + int ret=0; int loglvl = OAILOG_WARNING; uint64_t SSB_positions=0x01; uint16_t nb_symb_sch = 12; uint16_t nb_rb = 50; uint8_t Imcs = 9; + double DS_TDL = .03; + cpuf = get_cpu_freq_GHz(); if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) { @@ -315,13 +359,12 @@ int main(int argc, char **argv) snr1 = snr0 + 10; gNB2UE = new_channel_desc_scm(n_tx, - n_rx, - channel_model, + n_rx, + channel_model, 61.44e6, //N_RB2sampling_rate(N_RB_DL), 40e6, //N_RB2channel_bandwidth(N_RB_DL), - 0, - 0, - 0); + DS_TDL, + 0,0,0, 0); if (gNB2UE == NULL) { printf("Problem generating channel model. Exiting.\n"); @@ -334,6 +377,11 @@ int main(int argc, char **argv) gNB = RC.gNB[0]; //gNB_config = &gNB->gNB_config; + gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); + gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + char tp_param[] = "n"; + initTpool(tp_param, gNB->threadPool, true); + initNotifiedFIFO(gNB->respDecode); frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; @@ -346,7 +394,7 @@ int main(int argc, char **argv) nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions); - phy_init_nr_gNB(gNB, 0, 0); + phy_init_nr_gNB(gNB, 0, 1); //lowmem //configure UE UE = malloc(sizeof(PHY_VARS_NR_UE)); @@ -404,7 +452,7 @@ int main(int argc, char **argv) rel15_ul->pusch_data.rv_index = rvidx; rel15_ul->nrOfLayers = Nl; rel15_ul->target_code_rate = code_rate; - rel15_ul->pusch_data.tb_size = TBS>>3; + rel15_ul->pusch_data.tb_size = TBS/8; /////////////////////////////////////////////////// double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc @@ -440,7 +488,7 @@ int main(int argc, char **argv) harq_process_ul_ue->pusch_pdu.nr_of_symbols = nb_symb_sch; harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb*nb_codewords; harq_process_ul_ue->pusch_pdu.pusch_data.rv_index = rvidx; - harq_process_ul_ue->pusch_pdu.pusch_data.tb_size = TBS; + harq_process_ul_ue->pusch_pdu.pusch_data.tb_size = TBS/8; harq_process_ul_ue->a = &test_input[0]; } @@ -456,7 +504,7 @@ int main(int argc, char **argv) unsigned int G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, Nl); if (input_fd == NULL) { - nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid, G); + nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, G); } printf("\n"); @@ -527,10 +575,15 @@ int main(int argc, char **argv) rel15_ul->qam_mod_order, rel15_ul->nrOfLayers); - ret = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, + nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G); + while (gNB->nbDecode > 0) { + notifiedFIFO_elt_t *req=pullTpool(gNB->respDecode, gNB->threadPool); + ret = nr_postDecode_sim(gNB, req); + delNotifiedFIFO_elt(req); + } - if (ret > ulsch_gNB->max_ldpc_iterations) + if (ret) n_errors++; //count errors diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index ac4b93b973..d8e3437d03 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -55,27 +55,51 @@ //#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" - -#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) +#include "common/utils/threadPool/thread-pool.h" +#include "PHY/NR_REFSIG/ptrs_nr.h" +#define inMicroS(a) (((double)(a))/(get_cpu_freq_GHz()*1000.0)) #include "SIMULATION/LTE_PHY/common_sim.h" +#include +#include + +#include +#include "PHY/NR_REFSIG/ul_ref_seq_nr.h" //#define DEBUG_ULSIM +LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; +rlc_info_t Rlc_info_um,Rlc_info_am_config; + PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; -int sf_ahead=4 ; -int sl_ahead=0; +uint16_t sf_ahead=4 ; +int slot_ahead=6 ; +uint16_t sl_ahead=0; double cpuf; -uint8_t nfapi_mode = 0; -uint16_t NB_UE_INST = 1; +//uint8_t nfapi_mode = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; +THREAD_STRUCT thread_struct; +nfapi_ue_release_request_body_t release_rntis; +uint32_t N_RB_DL = 106; +extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration + +int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, + const int CC_id, + const uint8_t gNB_index, + const frame_t frame, + const sub_frame_t sub_frame, + const rnti_t rnti, + const channel_t channel, + const uint8_t* pduP, + const sdu_size_t pdu_len) +{ + return 0; +} -int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, - const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) { return 0; } int generate_dlsch_header(unsigned char *mac_header, unsigned char num_sdus, unsigned short *sdu_lengths, @@ -85,24 +109,140 @@ int generate_dlsch_header(unsigned char *mac_header, unsigned char *ue_cont_res_id, unsigned char short_padding, unsigned short post_padding){return 0;} -void pdcp_layer_init (void) {} -boolean_t pdcp_data_ind( + +void +rrc_data_ind( const protocol_ctxt_t *const ctxt_pP, - const srb_flag_t srb_flagP, - const MBMS_flag_t MBMS_flagP, - const rb_id_t rb_idP, - const sdu_size_t sdu_buffer_sizeP, - mem_block_t *const sdu_buffer_pP -) { return(false);} + const rb_id_t Srb_id, + const sdu_size_t sdu_sizeP, + const uint8_t *const buffer_pP +) +{ +} -void pdcp_run (const protocol_ctxt_t *const ctxt_pP) { return;} -void nr_ip_over_LTE_DRB_preconfiguration(void){} -int rrc_init_nr_global_param(void){return(0);} +int ocp_gtpv1u_create_s1u_tunnel(instance_t instance, + const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, + gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp) { + return 0; +} +int +gtpv1u_create_s1u_tunnel( + const instance_t instanceP, + const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, + gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP +) { + return 0; +} +int ocp_gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { + return 0; +} + +int +rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +) { + return 0; +} + +int +gtpv1u_create_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ + return 0; +} + +int +gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +){ + return 0; +} + +int +nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +){ + return 0; +} + +// Dummy function to avoid linking error at compilation of nr-ulsim +int is_x2ap_enabled(void) +{ + return 0; +} + +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} + +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) +{ + return 0; +} + +int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, + int CC_idP, + int UE_id, + rnti_t rntiP, + const uint8_t *sduP, + sdu_size_t sdu_lenP, + const uint8_t *sdu2P, + sdu_size_t sdu2_lenP) { + return 0; +} + +//nFAPI P7 dummy functions + +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } + +int nr_derive_key(int alg_type, uint8_t alg_id, + const uint8_t key[32], uint8_t **out) +{ + return 0; +} + +typedef struct { + uint64_t optmask; //mask to store boolean config options + uint8_t nr_dlsch_parallel; // number of threads for dlsch decoding, 0 means no parallelization + tpool_t Tpool; // thread pool +} nrUE_params_t; + +void processSlotTX(void *arg) {} + +nrUE_params_t nrUE_params; + +nrUE_params_t *get_nrUE_params(void) { + return &nrUE_params; +} // needed for some functions uint16_t n_rnti = 0x1234; openair0_config_t openair0_cfg[MAX_CARDS]; +//const uint8_t nr_rv_round_map[4] = {0, 2, 1, 3}; + +channel_desc_t *UE2gNB[NUMBER_OF_UE_MAX][NUMBER_OF_gNB_MAX]; int main(int argc, char **argv) { @@ -112,53 +252,85 @@ int main(int argc, char **argv) double sigma, sigma_dB; double snr_step = .2; uint8_t snr1set = 0; - int slot = 8, frame = 0; + int slot = 8, frame = 1; FILE *output_fd = NULL; + double **s_re,**s_im,**r_re,**r_im; //uint8_t write_output_file = 0; - int trial, n_trials = 1, n_errors = 0, n_false_positive = 0, delay = 0; + int trial, n_trials = 1, n_false_positive = 0, delay = 0; + double maxDoppler = 0.0; uint8_t n_tx = 1, n_rx = 1; //uint8_t transmission_mode = 1; //uint16_t Nid_cell = 0; - channel_desc_t *gNB2UE; + channel_desc_t *UE2gNB; uint8_t extended_prefix_flag = 0; //int8_t interf1 = -21, interf2 = -21; FILE *input_fd = NULL; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; + + NB_UE_INST = 1; + //unsigned char frame_type = 0; NR_DL_FRAME_PARMS *frame_parms; - int loglvl = OAILOG_WARNING; + int loglvl = OAILOG_INFO; //uint64_t SSB_positions=0x01; uint16_t nb_symb_sch = 12; - int start_symbol = 2; + int start_symbol = 0; uint16_t nb_rb = 50; - uint8_t Imcs = 9; + int Imcs = 9; uint8_t precod_nbr_layers = 1; int gNB_id = 0; int ap; int tx_offset; - double txlev_float; - int32_t txlev; + int32_t txlev=0; int start_rb = 0; int UE_id =0; // [hna] only works for UE_id = 0 because NUMBER_OF_NR_UE_MAX is set to 1 (phy_init_nr_gNB causes segmentation fault) float target_error_rate = 0.01; int print_perf = 0; cpuf = get_cpu_freq_GHz(); int msg3_flag = 0; + int rv_index = 0; + float roundStats[100]; + double effRate[100]; + double effTP[100]; + //float eff_tp_check = 0.7; + uint8_t snrRun; + int prb_inter = 0; + + int enable_ptrs = 0; + int modify_dmrs = 0; + /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */ + int ptrs_arg[2] = {-1,-1};// Invalid values + /* DMRS TYPE = dmrs_arg[0], Add Pos = dmrs_arg[1] */ + int dmrs_arg[2] = {-1,-1};// Invalid values + uint16_t ptrsSymPos = 0; + uint16_t ptrsSymbPerSlot = 0; + uint16_t ptrsRePerSymb = 0; + + uint8_t transform_precoding = 1; // 0 - ENABLE, 1 - DISABLE + uint8_t num_dmrs_cdm_grps_no_data = 1; + uint8_t mcs_table = 0; UE_nr_rxtx_proc_t UE_proc; FILE *scg_fd=NULL; + int file_offset = 0; + double DS_TDL = .03; int ibwps=24; int ibwp_rboffset=41; + int params_from_file = 0; + int threadCnt=1; if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) { exit_fun("[NR_ULSIM] Error, configuration module init failed\n"); } - + int ul_proc_error = 0; // uplink processing checking status flag //logInit(); randominit(0); - while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:i:j:kl:m:n:p:r:s:y:z:F:M:N:PR:S:L:")) != -1) { + /* initialize the sin-cos table */ + InitSinLUT(); + + while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:ikl:m:n:p:r:s:t:u:w:y:z:F:G:H:M:N:PR:S:T:U:L:Z")) != -1) { printf("handling optarg %c\n",c); switch (c) { @@ -227,7 +399,22 @@ int main(int argc, char **argv) case 'G': channel_model = ETU; break; - + + case 'H': + channel_model = TDL_C; + DS_TDL = .030; // 30 ns + break; + + case 'I': + channel_model = TDL_C; + DS_TDL = .3; // 300ns + break; + + case 'J': + channel_model=TDL_D; + DS_TDL = .03; + break; + default: printf("Unsupported channel model!\n"); exit(-1); @@ -235,14 +422,10 @@ int main(int argc, char **argv) break; - /*case 'i': - interf1 = atoi(optarg); - break; + case 'i': + prb_inter=1; + break; - case 'j': - interf2 = atoi(optarg); - break;*/ - case 'k': printf("Setting threequarter_fs_flag\n"); openair0_cfg[0].threequarter_fs= 1; @@ -272,7 +455,22 @@ int main(int argc, char **argv) snr0 = atof(optarg); printf("Setting SNR0 to %f\n", snr0); break; - + case 't': + threadCnt = atoi(optarg); + break; + case 'u': + mu = atoi(optarg); + break; + + case 'w': + start_rb = atoi(optarg); + break; + +/* + case 't': + eff_tp_check = (float)atoi(optarg)/100; + break; +*/ /* case 'r': ricean_factor = pow(10,-.1*atof(optarg)); @@ -300,7 +498,7 @@ int main(int argc, char **argv) case 'z': n_rx = atoi(optarg); - if ((n_rx == 0) || (n_rx > 2)) { + if ((n_rx == 0) || (n_rx > 8)) { printf("Unsupported number of rx antennas %d\n", n_rx); exit(-1); } @@ -316,7 +514,15 @@ int main(int argc, char **argv) } break; - + + case 'G': + file_offset = atoi(optarg); + break; + + case 'H': + slot = atoi(optarg); + break; + case 'M': // SSB_positions = atoi(optarg); break; @@ -344,35 +550,70 @@ int main(int argc, char **argv) case 'L': loglvl = atoi(optarg); break; + + case 'T': + enable_ptrs=1; + for(i=0; i < atoi(optarg); i++){ + ptrs_arg[i] = atoi(argv[optind++]); + } + break; + + case 'U': + modify_dmrs = 1; + for(i=0; i < atoi(optarg); i++){ + dmrs_arg[i] = atoi(argv[optind++]); + } + break; + + case 'Q': + params_from_file = 1; + break; + + case 'Z': + + transform_precoding = 0; // enabled + num_dmrs_cdm_grps_no_data = 2; + mcs_table = 3; + printf("NOTE: TRANSFORM PRECODING (SC-FDMA) is ENABLED in UPLINK (0 - ENABLE, 1 - DISABLE) : %d \n", transform_precoding); + + break; + default: case 'h': - printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]); + printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId -Z Enable SC-FDMA in Uplink \n", argv[0]); //printf("-d Use TDD\n"); printf("-d Introduce delay in terms of number of samples\n"); printf("-f Number of frames to simulate\n"); printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n"); printf("-h This message\n"); - //printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n"); + printf("-i Activate PRB based averaging for channel estimation. Frequncy domain interpolation by default.\n"); //printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n"); printf("-s Starting SNR, runs from SNR0 to SNR0 + 10 dB if ending SNR isn't given\n"); printf("-m MCS value\n"); printf("-n Number of trials to simulate\n"); printf("-p Use extended prefix mode\n"); printf("-t Delay spread for multipath channel\n"); + printf("-u Set the numerology\n"); + printf("-w Start PRB for PUSCH\n"); //printf("-x Transmission mode (1,2,6 for the moment)\n"); printf("-y Number of TX antennas used in eNB\n"); printf("-z Number of RX antennas used in UE\n"); printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n"); //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n"); printf("-F Input filename (.txt format) for RX conformance testing\n"); - printf("-G raw file containing RRC configuration (generated by gNB)\n"); + printf("-G Offset of samples to read from file (0 default)\n"); printf("-M Multiple SSB positions in burst\n"); printf("-N Nid_cell\n"); printf("-O oversampling factor (1,2,4,8,16)\n"); printf("-R N_RB_DL\n"); + printf("-t Acceptable effective throughput (in percentage)\n"); printf("-S Ending SNR, runs from SNR0 to SNR1\n"); printf("-P Print ULSCH performances\n"); + printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n"); + printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:3}, e.g. -U 2 0 2 \n"); + printf("-Q If -F used, read parameters from file\n"); + printf("-Z If -Z is used, SC-FDMA or transform precoding is enabled in Uplink \n"); exit(-1); break; @@ -390,20 +631,57 @@ int main(int argc, char **argv) if (snr1set == 0) snr1 = snr0 + 10; + double sampling_frequency; + double bandwidth; - gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, - 61.44e6, //N_RB2sampling_rate(N_RB_DL), - 40e6, //N_RB2channel_bandwidth(N_RB_DL), - 0, 0, 0); + if (N_RB_UL >= 217) sampling_frequency = 122.88; + else if (N_RB_UL >= 106) sampling_frequency = 61.44; + else if (N_RB_UL >= 32) sampling_frequency = 32.72; + else { printf("Need at least 106 PRBs\b"); exit(-1); } + if (N_RB_UL == 273) bandwidth = 100; + else if (N_RB_UL == 217) bandwidth = 80; + else if (N_RB_UL == 106) bandwidth = 40; + else if (N_RB_UL == 32) bandwidth = 50; + else { printf("Add N_RB_UL %d\n",N_RB_UL); exit(-1); } + + if (openair0_cfg[0].threequarter_fs == 1) sampling_frequency*=.75; - if (gNB2UE == NULL) { + UE2gNB = new_channel_desc_scm(n_tx, n_rx, channel_model, + sampling_frequency, + bandwidth, + DS_TDL, + 0, 0, 0, 0); + + if (UE2gNB == NULL) { printf("Problem generating channel model. Exiting.\n"); exit(-1); } + UE2gNB->max_Doppler = maxDoppler; + RC.gNB = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *)); - RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB)); + RC.gNB[0] = calloc(1,sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; + gNB->ofdm_offset_divisor = UINT_MAX; + gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); + gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + char tp_param[80]; + sprintf(tp_param,"-1"); + int s_offset = 0; + for (int icpu=1; icputhreadPool, false); + initNotifiedFIFO(gNB->respDecode); + gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_L1_tx); + notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,NULL); + processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); + msgDataTx->slot = -1; + gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx; + pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning //gNB_config = &gNB->gNB_config; //memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO)); @@ -411,15 +689,17 @@ int main(int argc, char **argv) gNB->UL_INFO.crc_ind.crc_list = (nfapi_nr_crc_t *)malloc(NB_UE_INST*sizeof(nfapi_nr_crc_t)); gNB->UL_INFO.rx_ind.number_of_pdus = 0; gNB->UL_INFO.crc_ind.number_crcs = 0; + gNB->prb_interpolation = prb_inter; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) - - frame_parms->nb_antennas_tx = n_tx; - frame_parms->nb_antennas_rx = n_rx; frame_parms->N_RB_DL = N_RB_DL; frame_parms->N_RB_UL = N_RB_UL; frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL; + s_re = malloc(n_tx*sizeof(double*)); + s_im = malloc(n_tx*sizeof(double*)); + r_re = malloc(n_rx*sizeof(double*)); + r_im = malloc(n_rx*sizeof(double*)); RC.nb_nr_macrlc_inst = 1; RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int)); @@ -433,39 +713,42 @@ int main(int argc, char **argv) rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon)); NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon; + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup)); prepare_scc(rrc.carrier.servingcellconfigcommon); uint64_t ssb_bitmap; - fill_scc(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu); + fill_scc_sim(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu); - fill_default_secondaryCellGroup(scc, - secondaryCellGroup, - 0, - 1, - n_tx, - 0); fix_scc(scc,ssb_bitmap); - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); + prepare_scd(scd); + + fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0, 0, 0); + + // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); + + /* RRC parameter validation for secondaryCellGroup */ + fix_scd(scd); AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface"); gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; // common configuration - rrc_mac_config_req_gNB(0,0,1,scc,0,0,NULL); + rrc_mac_config_req_gNB(0,0, n_tx, n_rx, 0, scc, &rrc.carrier.mib,0, 0, NULL); // UE dedicated configuration - rrc_mac_config_req_gNB(0,0,1,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); - phy_init_nr_gNB(gNB,0,0); + rrc_mac_config_req_gNB(0,0, n_tx, n_rx, 0, scc, &rrc.carrier.mib,1, secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); + frame_parms->nb_antennas_tx = n_tx; + frame_parms->nb_antennas_rx = n_rx; + nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; + cfg->carrier_config.num_tx_ant.value = n_tx; + cfg->carrier_config.num_rx_ant.value = n_rx; +// nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,0,0x01); + phy_init_nr_gNB(gNB,0,1); N_RB_DL = gNB->frame_parms.N_RB_DL; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; - //crcTableInit(); - - //nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_UL, mu, Nid_cell, SSB_positions); - //configure UE UE = malloc(sizeof(PHY_VARS_NR_UE)); @@ -497,8 +780,16 @@ int main(int argc, char **argv) } } */ - - nr_l2_init_ue(NULL); + + //Configure UE + NR_UE_RRC_INST_t rrcue; + memset(&rrcue,0,sizeof(NR_UE_RRC_INST_t)); + rrc.carrier.MIB = (uint8_t*) malloc(4); + rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0); + rrcue.mib = rrc.carrier.mib.message.choice.mib; + rrcue.scell_group_config=secondaryCellGroup; + nr_l2_init_ue(&rrcue); + NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0); UE->if_inst = nr_ue_if_module_init(0); @@ -509,11 +800,7 @@ int main(int argc, char **argv) UE_mac->if_module = nr_ue_if_module_init(0); - //Configure UE - rrc.carrier.MIB = (uint8_t*) malloc(4); - rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0); - - nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,secondaryCellGroup); +// nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib, NULL, NULL, secondaryCellGroup); nr_ue_phy_config_request(&UE_mac->phy_config); @@ -534,80 +821,240 @@ int main(int argc, char **argv) unsigned char *estimated_output_bit; unsigned char *test_input_bit; uint32_t errors_decoding = 0; - uint32_t errors_scrambling = 0; + test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); nr_scheduled_response_t scheduled_response; fapi_nr_ul_config_request_t ul_config; + fapi_nr_tx_request_t tx_req; + + memset(&scheduled_response, 0, sizeof(scheduled_response)); + memset(&ul_config, 0, sizeof(ul_config)); + memset(&tx_req, 0, sizeof(tx_req)); - unsigned int TBS; - uint16_t number_dmrs_symbols = 0; - unsigned int available_bits; - uint8_t nb_re_dmrs; - unsigned char mod_order; - uint16_t code_rate; uint8_t ptrs_mcs1 = 2; uint8_t ptrs_mcs2 = 4; uint8_t ptrs_mcs3 = 10; uint16_t n_rb0 = 25; uint16_t n_rb1 = 75; - uint8_t mcs_table = 0; + uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; // | PUSCH_PDU_BITMAP_PUSCH_PTRS; + uint8_t max_rounds = 4; + uint8_t crc_status = 0; + + unsigned char mod_order = nr_get_Qm_ul(Imcs, mcs_table); + uint16_t code_rate = nr_get_code_rate_ul(Imcs, mcs_table); + + uint8_t mapping_type = typeB; // Default Values + pusch_dmrs_type_t dmrs_config_type = pusch_dmrs_type1; // Default Values + pusch_dmrs_AdditionalPosition_t add_pos = pusch_dmrs_pos0; // Default Values + + /* validate parameters othwerwise default values are used */ + /* -U flag can be used to set DMRS parameters*/ + if(modify_dmrs) + { + if(dmrs_arg[0] == 0) + { + mapping_type = typeA; + } + else if (dmrs_arg[0] == 1) + { + mapping_type = typeB; + } + /* Additional DMRS positions */ + if(dmrs_arg[1] >= 0 && dmrs_arg[1] <=3 ) + { + add_pos = dmrs_arg[1]; + } + } + printf("NOTE: DMRS config is modified with Mapping Type %d , Additional Position %d \n", mapping_type, add_pos ); + + uint8_t length_dmrs = pusch_len1; + uint16_t l_prime_mask = get_l_prime(nb_symb_sch, mapping_type, add_pos, length_dmrs, start_symbol, NR_MIB__dmrs_TypeA_Position_pos2); + uint16_t number_dmrs_symbols = get_dmrs_symbols_in_slot(l_prime_mask, nb_symb_sch); + printf("num dmrs sym %d\n",number_dmrs_symbols); + uint8_t nb_re_dmrs = (dmrs_config_type == pusch_dmrs_type1) ? 6 : 4; + + // if transform precoding is enabled + if (transform_precoding == 0) { + + AssertFatal(enable_ptrs == 0, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n"); + + int8_t index = get_index_for_dmrs_lowpapr_seq((NR_NB_SC_PER_RB/2) * nb_rb); + AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n"); + + dmrs_config_type = pusch_dmrs_type1; + + printf("[ULSIM]: TRANSFORM PRECODING ENABLED. Num RBs: %d, index for DMRS_SEQ: %d\n", nb_rb, index); + } + + nb_re_dmrs = nb_re_dmrs * num_dmrs_cdm_grps_no_data; + + unsigned int available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, number_dmrs_symbols, mod_order, 1); + unsigned int TBS = nr_compute_tbs(mod_order, code_rate, nb_rb, nb_symb_sch, nb_re_dmrs * number_dmrs_symbols, 0, 0, precod_nbr_layers); + + + printf("[ULSIM]: length_dmrs: %u, l_prime_mask: %u number_dmrs_symbols: %u, mapping_type: %u add_pos: %d \n", length_dmrs, l_prime_mask, number_dmrs_symbols, mapping_type, add_pos); + printf("[ULSIM]: CDM groups: %u, dmrs_config_type: %d, num_rbs: %u, nb_symb_sch: %u\n", num_dmrs_cdm_grps_no_data, dmrs_config_type, nb_rb, nb_symb_sch); + printf("[ULSIM]: MCS: %d, mod order: %u, code_rate: %u\n", Imcs, mod_order, code_rate); + printf("[ULSIM]: VALUE OF G: %u, TBS: %u\n", available_bits, TBS); + + + + uint8_t ulsch_input_buffer[TBS/8]; + + ulsch_input_buffer[0] = 0x31; + for (i = 1; i < TBS/8; i++) { + ulsch_input_buffer[i] = (unsigned char) rand(); + } - uint8_t length_dmrs = pusch_len1; // [hna] remove dmrs struct - uint16_t l_prime_mask = get_l_prime(nb_symb_sch, typeB, pusch_dmrs_pos0, length_dmrs); // [hna] remove dmrs struct uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, Imcs, mcs_table); uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, nb_rb); + int ptrs_symbols = 0; // to calculate total PTRS RE's in a slot + + double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); + + /* -T option enable PTRS */ + if(enable_ptrs) + { + /* validate parameters othwerwise default values are used */ + if(ptrs_arg[0] == 0 || ptrs_arg[0] == 1 || ptrs_arg[0] == 2 ) + { + ptrs_time_density = ptrs_arg[0]; + } + if(ptrs_arg[1] == 2 || ptrs_arg[1] == 4 ) + { + ptrs_freq_density = ptrs_arg[1]; + } + pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; + printf("NOTE: PTRS Enabled with L %d, K %d \n", ptrs_time_density, ptrs_freq_density ); + } + + if (input_fd != NULL || n_trials == 1) max_rounds=1; if(1<= nb_symb_sch) pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - for (i = 0; i < nb_symb_sch; i++) { - number_dmrs_symbols += (l_prime_mask >> i) & 0x01; - } - - mod_order = nr_get_Qm_ul(Imcs, 0); - code_rate = nr_get_code_rate_ul(Imcs, 0); - printf("\n"); - for (int i=0;i<16;i++) printf("%f\n",gaussdouble(0.0,1.0)); + int frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + for (int aatx=0; aatxget_samples_slot_timestamp(slot,frame_parms,0); + int slot_length = slot_offset - frame_parms->get_samples_slot_timestamp(slot-1,frame_parms,0); + + if (input_fd != NULL) { + AssertFatal(frame_parms->nb_antennas_rx == 1, "nb_ant != 1\n"); + // 800 samples is N_TA_OFFSET for FR1 @ 30.72 Ms/s, + AssertFatal(frame_parms->subcarrier_spacing==30000,"only 30 kHz for file input for now (%d)\n",frame_parms->subcarrier_spacing); + + if (params_from_file) { + fseek(input_fd,file_offset*((slot_length<<2)+4000+16),SEEK_SET); + read_errors+=fread((void*)&n_rnti,sizeof(int16_t),1,input_fd); + printf("rnti %x\n",n_rnti); + read_errors+=fread((void*)&nb_rb,sizeof(int16_t),1,input_fd); + printf("nb_rb %d\n",nb_rb); + int16_t dummy; + read_errors+=fread((void*)&start_rb,sizeof(int16_t),1,input_fd); + //fread((void*)&dummy,sizeof(int16_t),1,input_fd); + printf("rb_start %d\n",start_rb); + read_errors+=fread((void*)&nb_symb_sch,sizeof(int16_t),1,input_fd); + //fread((void*)&dummy,sizeof(int16_t),1,input_fd); + printf("nb_symb_sch %d\n",nb_symb_sch); + read_errors+=fread((void*)&start_symbol,sizeof(int16_t),1,input_fd); + printf("start_symbol %d\n",start_symbol); + read_errors+=fread((void*)&Imcs,sizeof(int16_t),1,input_fd); + printf("mcs %d\n",Imcs); + read_errors+=fread((void*)&rv_index,sizeof(int16_t),1,input_fd); + printf("rv_index %d\n",rv_index); + // fread((void*)&harq_pid,sizeof(int16_t),1,input_fd); + read_errors+=fread((void*)&dummy,sizeof(int16_t),1,input_fd); + printf("harq_pid %d\n",harq_pid); + } + fseek(input_fd,file_offset*sizeof(int16_t)*2,SEEK_SET); + read_errors+=fread((void*)&gNB->common_vars.rxdata[0][slot_offset-delay], + sizeof(int16_t), + slot_length<<1, + input_fd); + if (read_errors==0) { + printf("error reading file\n"); + exit(1); + } + for (int i=0;i<16;i+=2) printf("slot_offset %d : %d,%d\n", + slot_offset, + ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i], + ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]); + + mod_order = nr_get_Qm_ul(Imcs, mcs_table); + code_rate = nr_get_code_rate_ul(Imcs, mcs_table); + } + + uint32_t errors_scrambling[4][100]; + int n_errors[4][100]; + int round_trials[4][100]; + double blerStats[4][100]; + double berStats[4][100]; + double snrStats[100]; + memset(errors_scrambling, 0, sizeof(uint32_t)*4*100); + memset(n_errors, 0, sizeof(int)*4*100); + memset(round_trials, 0, sizeof(int)*4*100); + memset(blerStats, 0, sizeof(double)*4*100); + memset(berStats, 0, sizeof(double)*4*100); + memset(snrStats, 0, sizeof(double)*100); for (SNR = snr0; SNR < snr1; SNR += snr_step) { + varArray_t *table_rx=initVarArray(1000,sizeof(double)); + int error_flag = 0; + n_false_positive = 0; + effRate[snrRun] = 0; + effTP[snrRun] = 0; + reset_meas(&gNB->phy_proc_rx); + reset_meas(&gNB->rx_pusch_stats); + reset_meas(&gNB->ulsch_decoding_stats); + reset_meas(&gNB->ulsch_deinterleaving_stats); + reset_meas(&gNB->ulsch_rate_unmatching_stats); + reset_meas(&gNB->ulsch_ldpc_decoding_stats); + reset_meas(&gNB->ulsch_unscrambling_stats); + reset_meas(&gNB->ulsch_channel_estimation_stats); + reset_meas(&gNB->ulsch_llr_stats); + reset_meas(&gNB->ulsch_channel_compensation_stats); + reset_meas(&gNB->ulsch_rbs_extraction_stats); + reset_meas(&UE->ulsch_ldpc_encoding_stats); + reset_meas(&UE->ulsch_rate_matching_stats); + reset_meas(&UE->ulsch_interleaving_stats); + reset_meas(&UE->ulsch_encoding_stats); - varArray_t *table_rx=initVarArray(1000,sizeof(double)); - reset_meas(&gNB->phy_proc_rx); - reset_meas(&gNB->ulsch_decoding_stats); - reset_meas(&gNB->ulsch_deinterleaving_stats); - reset_meas(&gNB->ulsch_rate_unmatching_stats); - reset_meas(&gNB->ulsch_ldpc_decoding_stats); - reset_meas(&gNB->ulsch_unscrambling_stats); - reset_meas(&gNB->ulsch_channel_estimation_stats); - reset_meas(&gNB->ulsch_llr_stats); - reset_meas(&gNB->ulsch_channel_compensation_stats); - reset_meas(&gNB->ulsch_rbs_extraction_stats); + clear_pusch_stats(gNB); + for (trial = 0; trial < n_trials; trial++) { + uint8_t round = 0; - UE_proc.nr_tti_tx = slot; + crc_status = 1; + errors_decoding = 0; + memset((void*)roundStats,0,50*sizeof(roundStats[0])); + while (roundharq_processes[harq_pid]->round = round; + gNB->ulsch[0][0]->harq_processes[harq_pid]->round = round; + rv_index = nr_rv_round_map[round]; + + UE_proc.thread_id = 0; + UE_proc.nr_slot_tx = slot; UE_proc.frame_tx = frame; - // --------- setting parameters for gNB -------- - /* - rel15_ul->rnti = n_rnti; - rel15_ul->ulsch_pdu_rel15.start_rb = start_rb; - rel15_ul->ulsch_pdu_rel15.number_rbs = nb_rb; - rel15_ul->ulsch_pdu_rel15.start_symbol = start_symbol; - rel15_ul->ulsch_pdu_rel15.number_symbols = nb_symb_sch; - rel15_ul->ulsch_pdu_rel15.length_dmrs = length_dmrs; - rel15_ul->ulsch_pdu_rel15.Qm = mod_order; - rel15_ul->ulsch_pdu_rel15.mcs = Imcs; - rel15_ul->ulsch_pdu_rel15.rv = 0; - rel15_ul->ulsch_pdu_rel15.ndi = 0; - rel15_ul->ulsch_pdu_rel15.n_layers = precod_nbr_layers; - rel15_ul->ulsch_pdu_rel15.R = code_rate; - /////////////////////////////////////////////////// - */ - UL_tti_req->SFN = frame; UL_tti_req->Slot = slot; UL_tti_req->n_pdus = 1; @@ -625,7 +1072,7 @@ int main(int argc, char **argv) else pusch_pdu->bwp_start = ibwp_start; pusch_pdu->bwp_size = ibwp_size; - start_rb += (ibwp_start - abwp_start); + start_rb = (ibwp_start - abwp_start); printf("msg3: ibwp_size %d, abwp_size %d, ibwp_start %d, abwp_start %d\n", ibwp_size,abwp_size,ibwp_start,abwp_start); } @@ -634,21 +1081,22 @@ int main(int argc, char **argv) pusch_pdu->bwp_size = abwp_size; } + pusch_pdu->pusch_data.tb_size = TBS/8; pusch_pdu->pdu_bit_map = pdu_bit_map; pusch_pdu->rnti = n_rnti; pusch_pdu->mcs_index = Imcs; pusch_pdu->mcs_table = mcs_table; pusch_pdu->target_code_rate = code_rate; pusch_pdu->qam_mod_order = mod_order; - pusch_pdu->transform_precoding = 1; + pusch_pdu->transform_precoding = transform_precoding; pusch_pdu->data_scrambling_id = *scc->physCellId; pusch_pdu->nrOfLayers = 1; - pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << start_symbol; - pusch_pdu->dmrs_config_type = 0; + pusch_pdu->ul_dmrs_symb_pos = l_prime_mask; + pusch_pdu->dmrs_config_type = dmrs_config_type; pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; pusch_pdu->scid = 0; pusch_pdu->dmrs_ports = 1; - pusch_pdu->num_dmrs_cdm_grps_no_data = 1; + pusch_pdu->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data; pusch_pdu->resource_alloc = 1; pusch_pdu->rb_start = start_rb; pusch_pdu->rb_size = nb_rb; @@ -657,15 +1105,23 @@ int main(int argc, char **argv) pusch_pdu->uplink_frequency_shift_7p5khz = 0; pusch_pdu->start_symbol_index = start_symbol; pusch_pdu->nr_of_symbols = nb_symb_sch; - pusch_pdu->pusch_data.rv_index = 0; + pusch_pdu->pusch_data.rv_index = rv_index; pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 0; + pusch_pdu->pusch_data.new_data_indicator = trial & 0x1; pusch_pdu->pusch_data.num_cb = 0; pusch_pdu->pusch_ptrs.ptrs_time_density = ptrs_time_density; pusch_pdu->pusch_ptrs.ptrs_freq_density = ptrs_freq_density; pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + // if transform precoding is enabled + if (transform_precoding == 0) { + + pusch_pdu->dfts_ofdm.low_papr_group_number = *scc->physCellId % 30; // U as defined in 38.211 section 6.4.1.1.1.2 + pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0; // V as defined in 38.211 section 6.4.1.1.1.2 + pusch_pdu->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data; + } + // prepare ULSCH/PUSCH reception nr_schedule_response(Sched_INFO); @@ -675,128 +1131,141 @@ int main(int argc, char **argv) scheduled_response.CC_id = 0; scheduled_response.frame = frame; scheduled_response.slot = slot; + scheduled_response.thread_id = UE_proc.thread_id; scheduled_response.dl_config = NULL; scheduled_response.ul_config = &ul_config; - scheduled_response.tx_request = (fapi_nr_tx_request_t *) malloc(sizeof(fapi_nr_tx_request_t)); - scheduled_response.tx_request->tx_request_body = (fapi_nr_tx_request_body_t *) malloc(sizeof(fapi_nr_tx_request_body_t)); + scheduled_response.tx_request = &tx_req; + + // Config UL TX PDU + tx_req.slot = slot; + tx_req.sfn = frame; + // tx_req->tx_config // TbD + tx_req.number_of_pdus = 1; + tx_req.tx_request_body[0].pdu_length = TBS/8; + tx_req.tx_request_body[0].pdu_index = 0; + tx_req.tx_request_body[0].pdu = &ulsch_input_buffer[0]; ul_config.slot = slot; ul_config.number_pdus = 1; ul_config.ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; ul_config.ul_config_list[0].pusch_config_pdu.rnti = n_rnti; ul_config.ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map; + ul_config.ul_config_list[0].pusch_config_pdu.qam_mod_order = mod_order; ul_config.ul_config_list[0].pusch_config_pdu.rb_size = nb_rb; ul_config.ul_config_list[0].pusch_config_pdu.rb_start = start_rb; ul_config.ul_config_list[0].pusch_config_pdu.nr_of_symbols = nb_symb_sch; ul_config.ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol; - ul_config.ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = l_prime_mask << start_symbol; - ul_config.ul_config_list[0].pusch_config_pdu.dmrs_config_type = 0; + ul_config.ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = l_prime_mask; + ul_config.ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type; ul_config.ul_config_list[0].pusch_config_pdu.mcs_index = Imcs; ul_config.ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table; - ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1; - ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0; - ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = 0; + ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data; ul_config.ul_config_list[0].pusch_config_pdu.nrOfLayers = precod_nbr_layers; + ul_config.ul_config_list[0].pusch_config_pdu.absolute_delta_PUSCH = 0; + + ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.tb_size = TBS/8; + ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = trial & 0x1; + ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index; ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_pid; + ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density; ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density; ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t)); ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - //there are plenty of other parameters that we don't seem to be using for now. e.g. - ul_config.ul_config_list[0].pusch_config_pdu.absolute_delta_PUSCH = 0; - nb_re_dmrs = ((ul_config.ul_config_list[0].pusch_config_pdu.dmrs_config_type == pusch_dmrs_type1) ? 6 : 4); + ul_config.ul_config_list[0].pusch_config_pdu.transform_precoding = transform_precoding; - available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, number_dmrs_symbols, mod_order, 1); - TBS = nr_compute_tbs(mod_order, code_rate, nb_rb, nb_symb_sch, nb_re_dmrs * number_dmrs_symbols, 0, 0, precod_nbr_layers); - pusch_pdu->pusch_data.tb_size = TBS>>3; - ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.tb_size = TBS; + // if transform precoding is enabled + if (transform_precoding == 0) { + + ul_config.ul_config_list[0].pusch_config_pdu.dfts_ofdm.low_papr_group_number = *scc->physCellId % 30;// U as defined in 38.211 section 6.4.1.1.1.2 + ul_config.ul_config_list[0].pusch_config_pdu.dfts_ofdm.low_papr_sequence_number = 0;// V as defined in 38.211 section 6.4.1.1.1.2 + //ul_config.ul_config_list[0].pusch_config_pdu.pdu_bit_map |= PUSCH_PDU_BITMAP_DFTS_OFDM; + ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data; - nr_fill_ulsch(gNB,frame,slot,pusch_pdu); - int slot_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);// - (int)(800*factor); - int slot_length = slot_offset - frame_parms->get_samples_slot_timestamp(slot-1,frame_parms,0); + } - for (int i=0;i<(TBS>>3);i++) ulsch_ue[0]->harq_processes[harq_pid]->a[i]=i&0xff; - double scale = 1; + //nr_fill_ulsch(gNB,frame,slot,pusch_pdu); // Not needed as its its already filled as apart of "nr_schedule_response(Sched_INFO);" + + for (int i=0;i<(TBS/8);i++) ulsch_ue[0]->harq_processes[harq_pid]->a[i]=i&0xff; if (input_fd == NULL) { - if (SNR==snr0) { - // set FAPI parameters for UE, put them in the scheduled response and call - nr_ue_scheduled_response(&scheduled_response); - - - /////////////////////////phy_procedures_nr_ue_TX/////////////////////// - /////////// - - phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id, 0); - - - if (n_trials==1) { - LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1); - LOG_M("txsig0F.m","txs0F", UE->common_vars.txdataF[0],frame_parms->ofdm_symbol_size*14,1,1); - } - /////////// - //////////////////////////////////////////////////// - tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); - - txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], - frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); - - txlev_float = (double)txlev/scale; // output of signal_energy is fixed point representation - - - //AWGN - } + // set FAPI parameters for UE, put them in the scheduled response and call + nr_ue_scheduled_response(&scheduled_response); + + + /////////////////////////phy_procedures_nr_ue_TX/////////////////////// + /////////// + + phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id); + + /* We need to call common sending function to send signal */ + LOG_D(PHY, "Sending Uplink data \n"); + nr_ue_pusch_common_procedures(UE, + slot, + &UE->frame_parms,1); + + if (n_trials==1) { + LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1); + LOG_M("txsig0F.m","txs0F", UE->common_vars.txdataF[0],frame_parms->ofdm_symbol_size*14,1,1); + } + /////////// + //////////////////////////////////////////////////// + tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); + + txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); } else n_trials = 1; + if (input_fd == NULL ) { - sigma_dB = 10*log10(txlev_float)-SNR; - sigma = pow(10,sigma_dB/10); - printf("txlev_float %f, sigma_dB %f\n",10*log10(txlev_float),sigma_dB); + sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;; + sigma = pow(10,sigma_dB/10); - n_errors = 0; - n_false_positive = 0; - errors_scrambling = 0; - errors_decoding = 0; + if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double) + frame_parms->ofdm_symbol_size/(12*nb_rb)); - int error_flag; - for (trial = 0; trial < n_trials; trial++) { - - error_flag = 0; - //---------------------------------------------------------- - //------------------------ add noise ----------------------- - //---------------------------------------------------------- - if (input_fd == NULL ) { - for (i=0; inb_antennas_rx; ap++) { - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((double)(((int16_t *)&UE->common_vars.txdata[ap][slot_offset])[(i<<1)])/sqrt(scale) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((double)(((int16_t *)&UE->common_vars.txdata[ap][slot_offset])[(i<<1)+1])/sqrt(scale) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); - } - } - } - else { - AssertFatal(frame_parms->nb_antennas_rx == 1, "nb_ant != 1\n"); - // 800 samples is N_TA_OFFSET for FR1 @ 30.72 Ms/s, - AssertFatal(frame_parms->subcarrier_spacing==30000,"only 30 kHz for file input for now (%d)\n",frame_parms->subcarrier_spacing); - double factor = 1; - if (openair0_cfg[0].threequarter_fs== 1) factor =.75; - int ta_offset=1600; - if (N_RB_DL <217) ta_offset=800; - else if (N_RB_DL < 106) ta_offset = 400; + for (i=0; inb_antennas_tx; aa++) { + s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)]); + s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]); + } + } - fread((void*)&gNB->common_vars.rxdata[0][slot_offset], - sizeof(int16_t), - slot_length<<1, - input_fd); - for (int i=0;i<16;i+=2) printf("slot_offset %d : %d,%d\n", - slot_offset, - ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i], - ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]); - fclose(input_fd); - } + + if (UE2gNB->max_Doppler == 0) { + multipath_channel(UE2gNB, s_re, s_im, r_re, r_im, slot_length, 0, (n_trials==1)?1:0); + } else { + multipath_tv_channel(UE2gNB, s_re, s_im, r_re, r_im, 2*slot_length, 0); + } + for (i=0; inb_antennas_rx; ap++) { + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); + /* Add phase noise if enabled */ + if (pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + phase_noise(ts, &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)], + &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1]); + } + } + } + + } /*End input_fd */ + + + if(pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + set_ptrs_symb_idx(&ptrsSymPos, + pusch_pdu->nr_of_symbols, + pusch_pdu->start_symbol_index, + 1<ul_dmrs_symb_pos); + ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymPos, pusch_pdu->start_symbol_index, pusch_pdu->nr_of_symbols); + ptrsRePerSymb = ((pusch_pdu->rb_size + ptrs_freq_density - 1)/ptrs_freq_density); + printf("[ULSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb ); + } //////////////////////////////////////////////////////////// //---------------------------------------------------------- @@ -805,117 +1274,265 @@ int main(int argc, char **argv) gNB->UL_INFO.rx_ind.number_of_pdus = 0; gNB->UL_INFO.crc_ind.number_crcs = 0; - start_meas(&gNB->phy_proc_rx); phy_procedures_gNB_common_RX(gNB, frame, slot); - if (n_trials==1) { - LOG_M("rxsig0.m","rx0",&gNB->common_vars.rxdata[0][0],frame_parms->samples_per_subframe*10,1,1); + ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot); + + if (n_trials==1 && round==0) { + LOG_M("rxsig0.m","rx0",&gNB->common_vars.rxdata[0][slot_offset],slot_length,1,1); LOG_M("rxsigF0.m","rxsF0",gNB->common_vars.rxdataF[0]+start_symbol*frame_parms->ofdm_symbol_size,nb_symb_sch*frame_parms->ofdm_symbol_size,1,1); } - phy_procedures_gNB_uespec_RX(gNB, frame, slot); - if (n_trials == 1) { + + + if (n_trials == 1 && round==0) { +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + LOG_M("rxsigF0_ext.m","rxsF0_ext", - &gNB->pusch_vars[0]->rxdataF_ext[0][(start_symbol+1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size,1,1); + &gNB->pusch_vars[0]->rxdataF_ext[0][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); LOG_M("chestF0.m","chF0", &gNB->pusch_vars[0]->ul_ch_estimates[0][start_symbol*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); + LOG_M("chestT0.m","chT0", + &gNB->pusch_vars[0]->ul_ch_estimates_time[0][0],frame_parms->ofdm_symbol_size,1,1); LOG_M("chestF0_ext.m","chF0_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(start_symbol+1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size,1,1); + &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); LOG_M("rxsigF0_comp.m","rxsF0_comp", - &gNB->pusch_vars[0]->rxdataF_comp[0][(start_symbol+1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size,1,1); + &gNB->pusch_vars[0]->rxdataF_comp[0][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("chmagF0.m","chmF0", + &gNB->pusch_vars[0]->ul_ch_mag[0][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("chmagbF0.m","chmbF0", + &gNB->pusch_vars[0]->ul_ch_magb[0][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + if (n_rx == 2) { + LOG_MM("rxsigF0_comp.m","rxsF1_comp", + &gNB->pusch_vars[0]->rxdataF_comp[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("rxsigF0_ext.m","rxsF1_ext", + &gNB->pusch_vars[0]->rxdataF_ext[1][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chestF0_ext.m","chF1_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[1][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chmagF0.m","chmF1", + &gNB->pusch_vars[0]->ul_ch_mag[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chmagbF0.m","chmbF1", + &gNB->pusch_vars[0]->ul_ch_magb[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + } else if (n_rx == 4) { + LOG_MM("rxsigF0_comp.m","rxsF1_comp", + &gNB->pusch_vars[0]->rxdataF_comp[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("rxsigF0_comp.m","rxsF2_comp", + &gNB->pusch_vars[0]->rxdataF_comp[2][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("rxsigF0_comp.m","rxsF3_comp", + &gNB->pusch_vars[0]->rxdataF_comp[3][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("rxsigF0_ext.m","rxsF1_ext", + &gNB->pusch_vars[0]->rxdataF_ext[1][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("rxsigF0_ext.m","rxsF2_ext", + &gNB->pusch_vars[0]->rxdataF_ext[2][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("rxsigF0_ext.m","rxsF3_ext", + &gNB->pusch_vars[0]->rxdataF_ext[3][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chestF0_ext.m","chF1_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[1][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chestF0_ext.m","chF2_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[2][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chestF0_ext.m","chF3_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[3][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chmagF0.m","chmF1", + &gNB->pusch_vars[0]->ul_ch_mag[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chmagF0.m","chmF2", + &gNB->pusch_vars[0]->ul_ch_mag[2][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chmagF0.m","chmF3", + &gNB->pusch_vars[0]->ul_ch_mag[3][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chmagbF0.m","chmbF1", + &gNB->pusch_vars[0]->ul_ch_magb[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chmagbF0.m","chmbF2", + &gNB->pusch_vars[0]->ul_ch_magb[2][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_MM("chmagbF0.m","chmbF3", + &gNB->pusch_vars[0]->ul_ch_magb[3][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + } + + LOG_M("rxsigF0_llr.m","rxsF0_llr", + &gNB->pusch_vars[0]->llr[0],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order,1,0); } - start_meas(&gNB->phy_proc_rx); //////////////////////////////////////////////////////////// - if (gNB->ulsch[0][0]->last_iteration_cnt >= - gNB->ulsch[0][0]->max_ldpc_iterations+1) { + if ((gNB->ulsch[0][0]->last_iteration_cnt >= + gNB->ulsch[0][0]->max_ldpc_iterations+1) || ul_proc_error == 1) { error_flag = 1; - n_errors++; + n_errors[round][snrRun]++; + crc_status = 1; + } else { + crc_status = 0; } - + if(n_trials==1) printf("end of round %d rv_index %d\n",round, rv_index); + //---------------------------------------------------------- //----------------- count and print errors ----------------- //---------------------------------------------------------- - for (i = 0; i < available_bits; i++) { - - if(((ulsch_ue[0]->g[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0)) || - ((ulsch_ue[0]->g[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0))) - { - /*if(errors_scrambling == 0) - printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/ - errors_scrambling++; - } + if ((pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) && (SNR==snr0) && (trial==0) && (round==0)) { + ptrs_symbols = 0; + for (int i = pusch_pdu->start_symbol_index; i < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; i++){ + ptrs_symbols += ((gNB->pusch_vars[UE_id]->ptrs_symbols) >> i) & 1; + } + /* 2*5*(50/2), for RB = 50,K = 2 for 5 OFDM PTRS symbols */ + available_bits -= 2 * ptrs_symbols * ((nb_rb + ptrs_freq_density - 1) /ptrs_freq_density); + printf("[ULSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5d \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * 2) ); } - if (errors_scrambling > 0) { - if (n_trials==1) - printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in unscrambling = %u\n" "\x1B[0m", frame, trial, errors_scrambling); - } - - for (i = 0; i < TBS; i++) { - - estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); - test_input_bit[i] = (ulsch_ue[0]->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); - - if (estimated_output_bit[i] != test_input_bit[i]) { - /*if(errors_decoding == 0) - printf("\x1B[34m""[frame %d][trial %d]\t1st bit in error in decoding = %d\n" "\x1B[0m", frame, trial, i);*/ - errors_decoding++; - } - } - if (n_trials == 1) { - for (int r=0;rharq_processes[harq_pid]->C;r++) - for (int i=0;iharq_processes[harq_pid]->K>>3;i++) { - if ((ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]) != 0) printf("************"); - printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r, - i,ulsch_ue[0]->harq_processes[harq_pid]->c[r][i], - i,ulsch_gNB->harq_processes[harq_pid]->c[r][i], - ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]); + for (i = 0; i < available_bits; i++) { + + if(((ulsch_ue[0]->g[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0)) || + ((ulsch_ue[0]->g[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0))) + { + /*if(errors_scrambling == 0) + printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/ + errors_scrambling[round][snrRun]++; } } - if (errors_decoding > 0 && error_flag == 0) { - n_false_positive++; - if (n_trials==1) - printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in decoding = %u\n" "\x1B[0m", frame, trial, errors_decoding); - } - } // trial loop + round++; - printf("*****************************************\n"); - printf("SNR %f: n_errors (negative CRC) = %d/%d, false_positive %d/%d, errors_scrambling %u/%u\n", SNR, n_errors, n_trials, n_false_positive, n_trials, errors_scrambling, available_bits*n_trials); - printf("\n"); - printf("SNR %f: Channel BLER %e, Channel BER %e\n", SNR,(double)n_errors/n_trials,(double)errors_scrambling/available_bits/n_trials); - printf("*****************************************\n"); - printf("\n"); - - if (print_perf==1) { - printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); - printStatIndent(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time"); - printStatIndent(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); - printStatIndent(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); - printStatIndent(&gNB->ulsch_llr_stats,"ULSCH llr computation"); - printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); - printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); - printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); - printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); - printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); - printf("\n"); - } - - if(n_trials==1) - break; - - if ((float)n_errors/(float)n_trials <= target_error_rate) { - printf("*************\n"); - printf("PUSCH test OK\n"); - printf("*************\n"); - break; - } + } // round + + if (n_trials == 1 && errors_scrambling[0][snrRun] > 0) { + printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in unscrambling = %u\n" "\x1B[0m", frame, trial, errors_scrambling[0][snrRun]); + } + + for (i = 0; i < TBS; i++) { + estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); + test_input_bit[i] = (ulsch_ue[0]->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); + + if (estimated_output_bit[i] != test_input_bit[i]) { + /*if(errors_decoding == 0) + printf("\x1B[34m""[frame %d][trial %d]\t1st bit in error in decoding = %d\n" "\x1B[0m", frame, trial, i);*/ + errors_decoding++; + } + } + if (n_trials == 1) { + for (int r=0;rharq_processes[harq_pid]->C;r++) + for (int i=0;iharq_processes[harq_pid]->K>>3;i++) { + if ((ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]) != 0) printf("************"); + /*printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r, + i,ulsch_ue[0]->harq_processes[harq_pid]->c[r][i], + i,ulsch_gNB->harq_processes[harq_pid]->c[r][i], + ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]);*/ + } + } + if (errors_decoding > 0 && error_flag == 0) { + n_false_positive++; + if (n_trials==1) + printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in decoding = %u\n" "\x1B[0m", frame, trial, errors_decoding); + } + roundStats[snrRun] += ((float)round); + if (!crc_status) effRate[snrRun] += ((double)TBS)/(double)round; + } // trial loop + + roundStats[snrRun]/=((float)n_trials); + effRate[snrRun] /= (double)n_trials; + + printf("*****************************************\n"); + printf("SNR %f: n_errors (%d/%d,%d/%d,%d/%d,%d/%d) (negative CRC), false_positive %d/%d, errors_scrambling (%u/%u,%u/%u,%u/%u,%u/%u\n", SNR, n_errors[0][snrRun], round_trials[0][snrRun],n_errors[1][snrRun], round_trials[1][snrRun],n_errors[2][snrRun], round_trials[2][snrRun],n_errors[3][snrRun], round_trials[3][snrRun], n_false_positive, n_trials, errors_scrambling[0][snrRun],available_bits*n_trials,errors_scrambling[1][snrRun],available_bits*n_trials,errors_scrambling[2][snrRun],available_bits*n_trials,errors_scrambling[3][snrRun],available_bits*n_trials); + printf("\n"); + blerStats[0][snrRun] = (double)n_errors[0][snrRun]/round_trials[0][snrRun]; + blerStats[1][snrRun] = (double)n_errors[1][snrRun]/round_trials[1][snrRun]; + blerStats[2][snrRun] = (double)n_errors[2][snrRun]/round_trials[2][snrRun]; + blerStats[3][snrRun] = (double)n_errors[3][snrRun]/round_trials[3][snrRun]; + + berStats[0][snrRun] = (double)errors_scrambling[0][snrRun]/available_bits/round_trials[0][snrRun]; + berStats[1][snrRun] = (double)errors_scrambling[1][snrRun]/available_bits/round_trials[1][snrRun]; + berStats[2][snrRun] = (double)errors_scrambling[2][snrRun]/available_bits/round_trials[2][snrRun]; + berStats[3][snrRun] = (double)errors_scrambling[3][snrRun]/available_bits/round_trials[3][snrRun]; + effTP[snrRun] = effRate[snrRun]/(double)TBS*(double)100; + printf("SNR %f: Channel BLER (%e,%e,%e,%e), Channel BER (%e,%e,%e,%e) Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", + SNR, + blerStats[0][snrRun], + blerStats[1][snrRun], + blerStats[2][snrRun], + blerStats[3][snrRun], + berStats[0][snrRun], + berStats[1][snrRun], + berStats[2][snrRun], + berStats[3][snrRun], + roundStats[snrRun],effRate[snrRun],effTP[snrRun],TBS); + + FILE *fd=fopen("nr_ulsim.log","w"); + dump_pusch_stats(fd,gNB); + + printf("*****************************************\n"); + printf("\n"); + + if (print_perf==1) { + printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); + printStatIndent(&gNB->rx_pusch_stats,"RX PUSCH time"); + printStatIndent2(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time"); + printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time"); + printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); + printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); + printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation"); + printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); + printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); + printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); + printStatIndent(&UE->ulsch_encoding_stats,"ULSCH total encoding time"); + printStatIndent2(&UE->ulsch_segmentation_stats,"ULSCH segmentation time"); + printStatIndent2(&UE->ulsch_ldpc_encoding_stats,"ULSCH LDPC encoder time"); + printStatIndent2(&UE->ulsch_rate_matching_stats,"ULSCH rate-matching time"); + printStatIndent2(&UE->ulsch_interleaving_stats,"ULSCH interleaving time"); + //printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); + //printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); + //printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); + printf("\n"); + } + + if(n_trials==1) + break; + + if ((float)n_errors[0][snrRun]/(float)n_trials <= target_error_rate) { + printf("*************\n"); + printf("PUSCH test OK\n"); + printf("*************\n"); + break; + } + + snrStats[snrRun] = SNR; + snrRun++; + n_errs = n_errors[0][snrRun]; } // SNR loop printf("\n"); + printf( "Num RB:\t%d\n" + "Num symbols:\t%d\n" + "MCS:\t%d\n" + "DMRS config type:\t%d\n" + "DMRS add pos:\t%d\n" + "PUSCH mapping type:\t%d\n" + "DMRS length:\t%d\n" + "DMRS CDM gr w/o data:\t%d\n", + nb_rb, + nb_symb_sch, + Imcs, + dmrs_config_type, + add_pos, + mapping_type, + length_dmrs, + num_dmrs_cdm_grps_no_data); + + LOG_M("ulsimStats.m","SNR",snrStats,snrRun,1,7); + LOG_MM("ulsimStats.m","BLER_round0",blerStats[0],snrRun,1,7); + LOG_MM("ulsimStats.m","BLER_round1",blerStats[1],snrRun,1,7); + LOG_MM("ulsimStats.m","BLER_round2",blerStats[2],snrRun,1,7); + LOG_MM("ulsimStats.m","BLER_round3",blerStats[3],snrRun,1,7); + LOG_MM("ulsimStats.m","BER_round0",berStats[0],snrRun,1,7); + LOG_MM("ulsimStats.m","BER_round1",berStats[1],snrRun,1,7); + LOG_MM("ulsimStats.m","BER_round2",berStats[2],snrRun,1,7); + LOG_MM("ulsimStats.m","BER_round3",berStats[3],snrRun,1,7); + LOG_MM("ulsimStats.m","EffRate",effRate,snrRun,1,7); + LOG_MM("ulsimStats.m","EffTP",effTP,snrRun,1,7); free(test_input_bit); free(estimated_output_bit); @@ -928,5 +1545,5 @@ int main(int argc, char **argv) if (scg_fd) fclose(scg_fd); - return (n_errors); + return (n_errs); } diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeCache.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeCache.txt new file mode 100644 index 0000000000..b9bfc668ed --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeCache.txt @@ -0,0 +1,313 @@ +# This is the CMakeCache file. +# For build in directory: /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or +// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler. +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release minsize builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler. +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release minsize builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/gmake + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If true, cmake will use relative paths in makefiles and projects. +CMAKE_USE_RELATIVE_PATHS:BOOL=OFF + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_BUILD_TOOL +CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 +//What is the target build tool cmake is generating for. +CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/gmake +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/usr/bin/ccmake +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Start directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS +CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 + diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake new file mode 100644 index 0000000000..20619f82ea --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake @@ -0,0 +1,56 @@ +set(CMAKE_C_COMPILER "/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "4.8.5") +set(CMAKE_C_PLATFORM_ID "Linux") + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + + + + +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "c") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") + + + diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake new file mode 100644 index 0000000000..5ae76367c4 --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake @@ -0,0 +1,57 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "4.8.5") +set(CMAKE_CXX_PLATFORM_ID "Linux") + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + + + + +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;c") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") + + + diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000..db27e43a89 Binary files /dev/null and b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin differ diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000..edbf852aaf Binary files /dev/null and b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin differ diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake new file mode 100644 index 0000000000..3980da44fc --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-3.10.0-957.21.3.rt56.935.el7.x86_64") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "3.10.0-957.21.3.rt56.935.el7.x86_64") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-3.10.0-957.21.3.rt56.935.el7.x86_64") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "3.10.0-957.21.3.rt56.935.el7.x86_64") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000000..cba81d4a6b --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,389 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_C = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) +# if defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" +# else +# if __IBMC__ >= 800 +# define COMPILER_ID "XL" +# else +# define COMPILER_ID "VisualAge" +# endif + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +/* Analog VisualDSP++ >= 4.5.6 */ +#elif defined(__VISUALDSPVERSION__) +# define COMPILER_ID "ADSP" + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) + +/* Analog VisualDSP++ < 4.5.6 */ +#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" + +/* IAR Systems compiler for embedded systems. + http://www.iar.com */ +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +/* sdcc, the small devices C compiler for embedded systems, + http://sdcc.sourceforge.net */ +#elif defined(SDCC) +# define COMPILER_ID "SDCC" + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + +/* This compiler is either not known or is too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" + +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#else /* unknown platform */ +# define PLATFORM_ID "" + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# define ARCHITECTURE_ID "ARM" + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID "" +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif + (void)argv; + return require; +} +#endif diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out new file mode 100755 index 0000000000..a13b3e1e72 Binary files /dev/null and b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out differ diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000000..e8220b26e5 --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,377 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) +# if defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" +# else +# if __IBMCPP__ >= 800 +# define COMPILER_ID "XL" +# else +# define COMPILER_ID "VisualAge" +# endif + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +/* Analog VisualDSP++ >= 4.5.6 */ +#elif defined(__VISUALDSPVERSION__) +# define COMPILER_ID "ADSP" + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) + +/* Analog VisualDSP++ < 4.5.6 */ +#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" + +/* IAR Systems compiler for embedded systems. + http://www.iar.com */ +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + +/* This compiler is either not known or is too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" + +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#else /* unknown platform */ +# define PLATFORM_ID "" + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# define ARCHITECTURE_ID "ARM" + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID "" +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif + (void)argv; + return require; +} diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out new file mode 100755 index 0000000000..7634d1e447 Binary files /dev/null and b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out differ diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeOutput.log b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeOutput.log new file mode 100644 index 0000000000..c922ff6230 --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeOutput.log @@ -0,0 +1,247 @@ +The system is: Linux - 3.10.0-957.21.3.rt56.935.el7.x86_64 - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /usr/bin/cc +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + +The C compiler identification is GNU, found in "/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out" + +Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. +Compiler: /usr/bin/c++ +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + +The CXX compiler identification is GNU, found in "/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out" + +Determining if the C compiler works passed with the following output: +Change Dir: /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp + +Run Build Command:/usr/bin/gmake "cmTryCompileExec2388936454/fast" +/usr/bin/gmake -f CMakeFiles/cmTryCompileExec2388936454.dir/build.make CMakeFiles/cmTryCompileExec2388936454.dir/build +gmake[1]: Entering directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp' +/usr/bin/cmake -E cmake_progress_report /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp/CMakeFiles 1 +Building C object CMakeFiles/cmTryCompileExec2388936454.dir/testCCompiler.c.o +/usr/bin/cc -o CMakeFiles/cmTryCompileExec2388936454.dir/testCCompiler.c.o -c /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp/testCCompiler.c +Linking C executable cmTryCompileExec2388936454 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2388936454.dir/link.txt --verbose=1 +/usr/bin/cc CMakeFiles/cmTryCompileExec2388936454.dir/testCCompiler.c.o -o cmTryCompileExec2388936454 -rdynamic +gmake[1]: Leaving directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp' + + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp + +Run Build Command:/usr/bin/gmake "cmTryCompileExec602265197/fast" +/usr/bin/gmake -f CMakeFiles/cmTryCompileExec602265197.dir/build.make CMakeFiles/cmTryCompileExec602265197.dir/build +gmake[1]: Entering directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp' +/usr/bin/cmake -E cmake_progress_report /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp/CMakeFiles 1 +Building C object CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o +/usr/bin/cc -o CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake/Modules/CMakeCCompilerABI.c +Linking C executable cmTryCompileExec602265197 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec602265197.dir/link.txt --verbose=1 +/usr/bin/cc -v CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec602265197 -rdynamic +Using built-in specs. +COLLECT_GCC=/usr/bin/cc +COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper +Target: x86_64-redhat-linux +Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux +Thread model: posix +gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) +COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec602265197' '-rdynamic' '-mtune=generic' '-march=x86-64' + /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTryCompileExec602265197 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o +gmake[1]: Leaving directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp' + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command:/usr/bin/gmake "cmTryCompileExec602265197/fast"] + ignore line: [/usr/bin/gmake -f CMakeFiles/cmTryCompileExec602265197.dir/build.make CMakeFiles/cmTryCompileExec602265197.dir/build] + ignore line: [gmake[1]: Entering directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp'] + ignore line: [/usr/bin/cmake -E cmake_progress_report /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp/CMakeFiles 1] + ignore line: [Building C object CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o] + ignore line: [/usr/bin/cc -o CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake/Modules/CMakeCCompilerABI.c] + ignore line: [Linking C executable cmTryCompileExec602265197] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec602265197.dir/link.txt --verbose=1] + ignore line: [/usr/bin/cc -v CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec602265197 -rdynamic ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper] + ignore line: [Target: x86_64-redhat-linux] + ignore line: [Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux] + ignore line: [Thread model: posix] + ignore line: [gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ] + ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec602265197' '-rdynamic' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTryCompileExec602265197 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o] + arg [/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2] ==> ignore + arg [--build-id] ==> ignore + arg [--no-add-needed] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-o] ==> ignore + arg [cmTryCompileExec602265197] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o] ==> ignore + arg [-L/usr/lib/gcc/x86_64-redhat-linux/4.8.5] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64] + arg [-L/lib/../lib64] ==> dir [/lib/../lib64] + arg [-L/usr/lib/../lib64] ==> dir [/usr/lib/../lib64] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../..] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../..] + arg [CMakeFiles/cmTryCompileExec602265197.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o] ==> ignore + remove lib [gcc] + remove lib [gcc_s] + remove lib [gcc] + remove lib [gcc_s] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5] ==> [/usr/lib/gcc/x86_64-redhat-linux/4.8.5] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64] ==> [/usr/lib64] + collapse library dir [/lib/../lib64] ==> [/lib64] + collapse library dir [/usr/lib/../lib64] ==> [/usr/lib64] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../..] ==> [/usr/lib] + implicit libs: [c] + implicit dirs: [/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib] + implicit fwks: [] + + +Determining if the CXX compiler works passed with the following output: +Change Dir: /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp + +Run Build Command:/usr/bin/gmake "cmTryCompileExec3828041398/fast" +/usr/bin/gmake -f CMakeFiles/cmTryCompileExec3828041398.dir/build.make CMakeFiles/cmTryCompileExec3828041398.dir/build +gmake[1]: Entering directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp' +/usr/bin/cmake -E cmake_progress_report /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp/CMakeFiles 1 +Building CXX object CMakeFiles/cmTryCompileExec3828041398.dir/testCXXCompiler.cxx.o +/usr/bin/c++ -o CMakeFiles/cmTryCompileExec3828041398.dir/testCXXCompiler.cxx.o -c /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp/testCXXCompiler.cxx +Linking CXX executable cmTryCompileExec3828041398 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3828041398.dir/link.txt --verbose=1 +/usr/bin/c++ CMakeFiles/cmTryCompileExec3828041398.dir/testCXXCompiler.cxx.o -o cmTryCompileExec3828041398 -rdynamic +gmake[1]: Leaving directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp' + + +Detecting CXX compiler ABI info compiled with the following output: +Change Dir: /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp + +Run Build Command:/usr/bin/gmake "cmTryCompileExec1700914889/fast" +/usr/bin/gmake -f CMakeFiles/cmTryCompileExec1700914889.dir/build.make CMakeFiles/cmTryCompileExec1700914889.dir/build +gmake[1]: Entering directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp' +/usr/bin/cmake -E cmake_progress_report /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp/CMakeFiles 1 +Building CXX object CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o +/usr/bin/c++ -o CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp +Linking CXX executable cmTryCompileExec1700914889 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec1700914889.dir/link.txt --verbose=1 +/usr/bin/c++ -v CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec1700914889 -rdynamic +Using built-in specs. +COLLECT_GCC=/usr/bin/c++ +COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper +Target: x86_64-redhat-linux +Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux +Thread model: posix +gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) +COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec1700914889' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTryCompileExec1700914889 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o +gmake[1]: Leaving directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp' + + +Parsed CXX implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command:/usr/bin/gmake "cmTryCompileExec1700914889/fast"] + ignore line: [/usr/bin/gmake -f CMakeFiles/cmTryCompileExec1700914889.dir/build.make CMakeFiles/cmTryCompileExec1700914889.dir/build] + ignore line: [gmake[1]: Entering directory `/home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp'] + ignore line: [/usr/bin/cmake -E cmake_progress_report /home/sy/openairinterface5g/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/CMakeTmp/CMakeFiles 1] + ignore line: [Building CXX object CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/bin/c++ -o CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Linking CXX executable cmTryCompileExec1700914889] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec1700914889.dir/link.txt --verbose=1] + ignore line: [/usr/bin/c++ -v CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec1700914889 -rdynamic ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper] + ignore line: [Target: x86_64-redhat-linux] + ignore line: [Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux] + ignore line: [Thread model: posix] + ignore line: [gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ] + ignore line: [COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec1700914889' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o cmTryCompileExec1700914889 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o] + arg [/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2] ==> ignore + arg [--build-id] ==> ignore + arg [--no-add-needed] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-o] ==> ignore + arg [cmTryCompileExec1700914889] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o] ==> ignore + arg [-L/usr/lib/gcc/x86_64-redhat-linux/4.8.5] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64] + arg [-L/lib/../lib64] ==> dir [/lib/../lib64] + arg [-L/usr/lib/../lib64] ==> dir [/usr/lib/../lib64] + arg [-L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../..] ==> dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../..] + arg [CMakeFiles/cmTryCompileExec1700914889.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o] ==> ignore + arg [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o] ==> ignore + remove lib [gcc_s] + remove lib [gcc] + remove lib [gcc_s] + remove lib [gcc] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5] ==> [/usr/lib/gcc/x86_64-redhat-linux/4.8.5] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64] ==> [/usr/lib64] + collapse library dir [/lib/../lib64] ==> [/lib64] + collapse library dir [/usr/lib/../lib64] ==> [/usr/lib64] + collapse library dir [/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;c] + implicit dirs: [/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib] + implicit fwks: [] + + diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/cmake.check_cache b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000000..3dccd73172 --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/frame_config_test.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/frame_config_test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/harq_test.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/harq_test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/pbch_test.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/pbch_test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/pss_test.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/pss_test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/pucch_uci_test.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/pucch_uci_test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/srs_test.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/srs_test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/sss_test.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/testlogs/sss_test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c index cc8c62a36d..b8a5c7a780 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c @@ -142,6 +142,15 @@ void thread_top_init(char *thread_name, int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { return(0);} int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); } +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/frame_config_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/frame_config_test.c index 1ab935fcae..c88c261667 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/frame_config_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/frame_config_test.c @@ -51,16 +51,16 @@ void display_frame_configuration(NR_DL_FRAME_PARMS *frame_parms) { - printf("\nTdd configuration tti %d downlink %d uplink %d period %d \n", frame_parms->ttis_per_subframe, frame_parms->p_tdd_UL_DL_Configuration->nrofDownlinkSlots, + printf("\nTdd configuration tti %d downlink %d uplink %d period %d \n", frame_parms->slots_per_subframe, frame_parms->p_tdd_UL_DL_Configuration->nrofDownlinkSlots, frame_parms->p_tdd_UL_DL_Configuration->nrofUplinkSlots, frame_parms->p_tdd_UL_DL_Configuration->dl_UL_TransmissionPeriodicity); int k = (TDD_CONFIG_NB_FRAMES * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) - 1; //19; int tti = 0; - for (int j = 0; j < TDD_CONFIG_NB_FRAMES * frame_parms->ttis_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; j++) { + for (int j = 0; j < TDD_CONFIG_NB_FRAMES * frame_parms->slots_per_frame; j++) { int frame = 0; if (j != 0) { - frame = (frame_parms->ttis_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME)/j; - tti = (j)%(frame_parms->ttis_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME); + frame = j / frame_parms->slots_per_frame; + tti = j % frame_parms->slots_per_frame; } else { frame = 0; @@ -99,9 +99,10 @@ void display_frame_configuration(NR_DL_FRAME_PARMS *frame_parms) { * *********************************************************************/ -void set_tti_test(NR_DL_FRAME_PARMS *frame_parms, int ttis_per_subframe) +void set_tti_test(NR_DL_FRAME_PARMS *frame_parms, int slots_per_subframe) { - frame_parms->ttis_per_subframe = ttis_per_subframe; + frame_parms->slots_per_subframe = slots_per_subframe; + frame_parms->slots_per_frame = slots_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; } /******************************************************************* diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pbch_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pbch_test.c index fc5360848c..7600dfb08f 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pbch_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pbch_test.c @@ -94,6 +94,7 @@ extern int pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode); int test_synchro_pss_sss_nr(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); + UE_nr_rxtx_proc_t proc = {0}; int synchro_position; int offset; int16_t *tmp; @@ -130,7 +131,7 @@ int test_synchro_pss_sss_nr(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, in #endif - rx_sss_nr(PHY_vars_UE, &metric_fdd_ncp, &phase_fdd_ncp); + rx_sss_nr(PHY_vars_UE, &proc, &metric_fdd_ncp, &phase_fdd_ncp); #if TEST_SYNCHRO_TIMING_PSS @@ -244,7 +245,7 @@ void set_sequence_sss(PHY_VARS_NR_UE *PHY_vars_UE, int offset, int slot_offset) void insert_sequence_sss(PHY_VARS_NR_UE *PHY_vars_UE, int offset) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); - int samples_for_half_frame = (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti)>>1; + int samples_for_half_frame = frame_parms->samples_per_frame / 2; set_sequence_sss(PHY_vars_UE, offset, 0); @@ -327,7 +328,7 @@ int test_synchro_pss_sss(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int s int sync_pos2 = synchro_position - frame_parms->nb_prefix_samples; - int sync_pos_slot = (frame_parms->samples_per_tti>>1) - frame_parms->ofdm_symbol_size - frame_parms->nb_prefix_samples; + int sync_pos_slot = (frame_parms->samples_per_slot>>1) - frame_parms->ofdm_symbol_size - frame_parms->nb_prefix_samples; if (sync_pos2 >= sync_pos_slot) PHY_vars_UE->rx_offset = sync_pos2 - sync_pos_slot; diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c index fa8b49842f..f3dbc78a73 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c @@ -300,7 +300,7 @@ typedef enum { void set_random_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int amp) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); - int samples_for_frame = (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); + int samples_for_frame = frame_parms->samples_per_frame; int16_t random; int16_t *data_p; random_data_format_t data_format = SINUSOIDAL_DATA; @@ -394,7 +394,7 @@ void set_random_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int amp) { int set_pss_in_rx_buffer_from_external_buffer(PHY_VARS_NR_UE *PHY_vars_UE, short *input_buffer) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); - int samples_for_frame = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe; /* both i and q */ + int samples_for_frame = frame_parms->samples_per_frame; /* both i and q */ for (int aa=0; aaframe_parms.nb_antennas_rx; aa++) { for (int i = 0; i < samples_for_frame; i++) { diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.h b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.h index 65755b0dfb..f0929e88c0 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.h +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.h @@ -69,12 +69,6 @@ typedef struct { int number_of_fail; } test_t; -typedef struct { - uint16_t ofdm_symbol_size; - uint32_t samples_per_tti; - uint32_t samples_per_subframe; -} save_frame_parms_t; - /*************** GLOBAL VARIABLES***********************************/ EXTERN PHY_VARS_eNB *PHY_vars_eNB; diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c index ab3ede4b8f..68acea6d98 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c @@ -58,7 +58,7 @@ int test_pucch_generators(PHY_VARS_NR_UE *ue) { int occ_Index = 0; uint64_t pucch_payload = 0; int tx_amp = 512; - int nr_tti_tx = 0; + int nr_slot_tx = 0; int N_UCI = 0; /* size in bits for Uplink Control Information */ switch(format) { @@ -67,7 +67,7 @@ int test_pucch_generators(PHY_VARS_NR_UE *ue) { &ue->frame_parms, &ue->pucch_config_dedicated_nr[gNB_id], tx_amp, - nr_tti_tx, + nr_slot_tx, (uint8_t)m_0, (uint8_t)m_CS, nb_symbols_total, @@ -82,7 +82,7 @@ int test_pucch_generators(PHY_VARS_NR_UE *ue) { &ue->pucch_config_dedicated_nr[gNB_id], pucch_payload, tx_amp, - nr_tti_tx, + nr_slot_tx, (uint8_t)m_0, nb_symbols_total, starting_symbol_index, @@ -95,13 +95,13 @@ int test_pucch_generators(PHY_VARS_NR_UE *ue) { case pucch_format2_nr: { nr_generate_pucch2(ue, - ue->pdcch_vars[ue->current_thread_id[nr_tti_tx]][gNB_id]->crnti, + ue->pdcch_vars[thread_number][gNB_id]->crnti, ue->common_vars.txdataF, &ue->frame_parms, &ue->pucch_config_dedicated_nr[gNB_id], pucch_payload, tx_amp, - nr_tti_tx, + nr_slot_tx, nb_symbols_total, starting_symbol_index, nb_of_prbs, @@ -113,14 +113,14 @@ int test_pucch_generators(PHY_VARS_NR_UE *ue) { case pucch_format3_nr: case pucch_format4_nr: { nr_generate_pucch3_4(ue, - ue->pdcch_vars[ue->current_thread_id[nr_tti_tx]][gNB_id]->crnti, + ue->pdcch_vars[thread_number][gNB_id]->crnti, ue->common_vars.txdataF, &ue->frame_parms, format, &ue->pucch_config_dedicated_nr[gNB_id], pucch_payload, tx_amp, - nr_tti_tx, + nr_slot_tx, nb_symbols_total, starting_symbol_index, nb_of_prbs, diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c index ff15dec6a4..f731edc20a 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c @@ -169,7 +169,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr printf("%s", tst_separator); - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; printf("\n => Test : No harq feedback on going\n"); @@ -180,9 +180,9 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr } /* set a tx slot with no ack */ - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; + NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; printf("\n => Test : Error due to acknownlegment not set \n"); @@ -232,7 +232,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr v_return = -1; } - ue->n_connected_eNB = 2; + ue->n_connected_gNB = 2; printf("\n => Test : Error due to PUCCH format with multiple cells not already implemented \n"); @@ -240,7 +240,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr v_return = -1; } - ue->n_connected_eNB = 1; + ue->n_connected_gNB = 1; return (v_return); } @@ -267,7 +267,7 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ common_pucch_configuration(ue, gNB_id, TST_PUCCH_COMMON_CONFIG_INDEX_OK); /* set a tx slot with no ack */ - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; + NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; harq_status->ack = DL_ACK; @@ -290,9 +290,9 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ /* set a second ack on a different downlink harq process */ - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_SECOND; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_SECOND; - harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_SECOND].harq_ack; + harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_SECOND].harq_ack; harq_status->n_CCE = 2; harq_status->N_CCE = 4; @@ -300,7 +300,7 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ harq_status->send_harq_status = 1; harq_status->vDAI_DL = 2; harq_status->ack = DL_ACK; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; printf("\n => Test : PUCCH format from common config in dedicated mode: two positive downlink ACKnowledgments \n"); @@ -316,7 +316,7 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ v_return = -1; } - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack.ack = DL_NACK; + ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack.ack = DL_NACK; printf("\n => Test : PUCCH format from common config in dedicated mode: two negative downlink ACKnowledgments \n"); @@ -563,11 +563,11 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, printf("%s", tst_separator); - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; - harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; + harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = 1; harq_status->ack = DL_ACK; @@ -582,11 +582,11 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, for (int i = 0; i < TST_NB_STEP_SINGLE_TRANSPORT_BLOCK; i++) { /* set a tx slot with no ack */ - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = dl_harq_pid[i]; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = i+1; harq_status->ack = DL_ACK; @@ -616,11 +616,11 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, for (i = 1; i < TST_NB_STEP_SINGLE_TRANSPORT_BLOCK; i = i+2) { /* set a tx slot with no ack */ - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = dl_harq_pid[i]; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = i+1; harq_status->ack = DL_ACK; @@ -677,14 +677,14 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE for (int code_word = 0; code_word < 2; code_word++) { - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->Number_MCS_HARQ_DL_DCI = 2; + ue->dlsch[proc->thread_id][gNB_id][code_word]->Number_MCS_HARQ_DL_DCI = 2; /* set a tx slot with no ack */ - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; + ue->dlsch[proc->thread_id][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = i+1; harq_status->ack = DL_ACK; @@ -697,7 +697,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE reset_harq = TRUE; } - harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; + harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; harq_status->pucch_resource_indicator = pucch_resource_indicator[i][j]; @@ -720,21 +720,21 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE for (int code_word = 0; code_word < 2; code_word++) { - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->Number_MCS_HARQ_DL_DCI = 2; + ue->dlsch[proc->thread_id][gNB_id][code_word]->Number_MCS_HARQ_DL_DCI = 2; /* set a tx slot with no ack */ - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; + ue->dlsch[proc->thread_id][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = i+1; harq_status->ack = DL_ACK; for (int j = 0 ; j < 2; j++) { - harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; + harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; harq_status->pucch_resource_indicator = pucch_resource_indicator[i][j]; } @@ -754,21 +754,21 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE for (int code_word = 0; code_word < 2; code_word++) { - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->Number_MCS_HARQ_DL_DCI = 2; + ue->dlsch[proc->thread_id][gNB_id][code_word]->Number_MCS_HARQ_DL_DCI = 2; /* set a tx slot with no ack */ - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; + ue->dlsch[proc->thread_id][gNB_id][code_word]->current_harq_pid = dl_harq_pid[i]; - NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; + NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[proc->thread_id][gNB_id][code_word]->harq_processes[dl_harq_pid[i]].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = i+1; harq_status->ack = DL_ACK; for (int j = 0 ; j < 2; j++) { - harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; + harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; harq_status->pucch_resource_indicator = pucch_resource_indicator[i][j]; } @@ -935,7 +935,7 @@ int test_sr_alone_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *p } /* restore single transport block */ - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->Number_MCS_HARQ_DL_DCI = 1; + ue->dlsch[proc->thread_id][gNB_id][0]->Number_MCS_HARQ_DL_DCI = 1; return (v_return); } @@ -976,11 +976,11 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro NR_UE_HARQ_STATUS_t *harq_status; - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; - harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; + harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = 1; harq_status->ack = DL_ACK; @@ -1015,11 +1015,11 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro /* set a second harq ack context */ - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_SECOND; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_SECOND; - harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_SECOND].harq_ack; + harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_SECOND].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = 2; harq_status->ack = DL_ACK; @@ -1073,7 +1073,7 @@ int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) printf("%s", tst_separator); - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = NR_MAX_DLSCH_HARQ_PROCESSES; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = NR_MAX_DLSCH_HARQ_PROCESSES; set_csi_nr( 4, 0x0E ); @@ -1090,11 +1090,11 @@ int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) NR_UE_HARQ_STATUS_t *harq_status; - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; + ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid = TST_DL_HARQ_PID_FIRST; - harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; + harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[TST_DL_HARQ_PID_FIRST].harq_ack; - harq_status->slot_for_feedback_ack = proc->nr_tti_tx; + harq_status->slot_for_feedback_ack = proc->nr_slot_tx; harq_status->send_harq_status = 1; harq_status->vDAI_DL = 1; harq_status->ack = DL_ACK; @@ -1168,9 +1168,11 @@ int test_pucch(PHY_VARS_NR_UE *ue) assert(0); } - proc->frame_tx = 0; - proc->nr_tti_rx = 0; - proc->nr_tti_tx = (proc->nr_tti_rx + NR_UE_CAPABILITY_SLOT_RX_TO_TX)%(ue->frame_parms.ttis_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); + proc->frame_rx = 0; + proc->nr_slot_rx = 0; + + proc->frame_tx = proc->frame_rx + (proc->nr_slot_rx + NR_UE_CAPABILITY_SLOT_RX_TO_TX) / ue->frame_parms.slots_per_frame; + proc->nr_slot_tx = (proc->nr_slot_rx + NR_UE_CAPABILITY_SLOT_RX_TO_TX) % ue->frame_parms.slots_per_frame; init_pucch_power_configuration( ue, gNB_id); diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/srs_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/srs_test.c index 0bbe7cac7f..aedb5729a3 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/srs_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/srs_test.c @@ -223,12 +223,12 @@ int test_srs_periodicity(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc) } printf("srs period %d offset %d \n", srs_current_period, p_srs_resource->SRS_Offset); - int duration = (10 * srs_current_period)/(NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->ttis_per_subframe); + int duration = (10 * srs_current_period) / frame_parms->slots_per_frame; for (int frame_tx = 0; frame_tx < duration; frame_tx++) { - for (int slot_tx = 0; slot_tx < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->ttis_per_subframe); slot_tx++) { - proc->frame_tx = frame_tx; - proc->nr_tti_tx = slot_tx; + for (int slot_tx = 0; slot_tx < frame_parms->slots_per_frame; slot_tx++) { + proc->frame_tx = frame_tx; + proc->nr_slot_tx = slot_tx; if (ue_srs_procedure_nr( ue, proc, 0) == 0) { printf("test_srs_periodicity srs at frame %d slot %d \n", frame_tx, slot_tx); } @@ -372,7 +372,7 @@ int test_srs(PHY_VARS_NR_UE *PHY_vars_UE) /* start test of sounding reference signals */ default_srs_configuration(frame_parms); - txptr = calloc(frame_parms->samples_per_tti , sizeof(int32_t)); + txptr = calloc(frame_parms->samples_per_slot , sizeof(int32_t)); if (txptr == NULL) { printf("Error test_srs: memory allocation problem txptr \n"); assert(0); diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/sss_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/sss_test.c index 81e232794e..34127b604f 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/sss_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/sss_test.c @@ -84,6 +84,7 @@ int test_synchro_pss_sss_nr(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, NR_DL_FRAME_PARMS *frame_parms_gNB, test_t *test) { + UE_nr_rxtx_proc_t proc = {0}; VOID_PARAMETER test; int synchro_position; int offset; @@ -133,7 +134,7 @@ int test_synchro_pss_sss_nr(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, NR #endif - rx_sss_nr(PHY_vars_UE, &metric_fdd_ncp, &phase_fdd_ncp); + rx_sss_nr(PHY_vars_UE, &proc, &metric_fdd_ncp, &phase_fdd_ncp); #if TEST_SYNCHRO_TIMING_PSS diff --git a/openair1/SIMULATION/TOOLS/DOC/arch.md b/openair1/SIMULATION/TOOLS/DOC/arch.md new file mode 100644 index 0000000000..30be337829 --- /dev/null +++ b/openair1/SIMULATION/TOOLS/DOC/arch.md @@ -0,0 +1,9 @@ +# Channel simulation source files + +1. [random_channel.c](../random_channel.c) +1. [sim.h](../sim.h) + + + +[channel simulation main page](channel_simulation.md) +[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) \ No newline at end of file diff --git a/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md b/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md new file mode 100644 index 0000000000..be2b987b40 --- /dev/null +++ b/openair1/SIMULATION/TOOLS/DOC/channel_simulation.md @@ -0,0 +1,13 @@ +# OAI channel simulation feature + +oai includes a channel simulation feature that any component can use to alter time domain samples of a RF channel by applying pre-defined models as defined, for example, in 3GPP TR 36.873 or TR 38.901 + +Definition, configuration and run-time modification of a channel model are implemented in common code included in UEs, gNb, eNB and used when running with the rfsimulator or the L1 simulator. Phy simulators are also using channel simulation but configuration is done via dedicated command line options. The rfsimulator is the only option to get access to all the configurations and run-time modifications features of oai channel simulation. + +## Documentation + +* [runtime usage](rtusage.md) +* [developer usage](devusage.md) +* [module architecture](arch.md) + +[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) diff --git a/openair1/SIMULATION/TOOLS/DOC/devusage.md b/openair1/SIMULATION/TOOLS/DOC/devusage.md new file mode 100644 index 0000000000..8fa6b3fe7a --- /dev/null +++ b/openair1/SIMULATION/TOOLS/DOC/devusage.md @@ -0,0 +1,7 @@ +### channel simulation developer usage + + +[Configuring the channel simulation](rtusage.md) + +[channel simulation main page](channel_simulation.md) +[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) \ No newline at end of file diff --git a/openair1/SIMULATION/TOOLS/DOC/rtusage.md b/openair1/SIMULATION/TOOLS/DOC/rtusage.md new file mode 100644 index 0000000000..37fc62b496 --- /dev/null +++ b/openair1/SIMULATION/TOOLS/DOC/rtusage.md @@ -0,0 +1,69 @@ +## configuring the channel simulation +Oai channel simulation is using the [config module](../../../config/config.md) to get its parameters at init time. The [telnet server](../../telnetsrv/DOC/telnetsrv.md) includes a set of commands which can be used to dynamically modify some channel model parameters + +All channel simulation parameters are defined in the `channelmod` section. Most parameters are specific to a channel model and are only used by the rfsimulator. + +### global parameters + +| name | type | default | description | +|:---:|:---:|:---:|:----| +| `max_chan` | integer | `25` | Maximum number of channel model that can be defined in the system. Must be greater than the number of model definitions in the model list loaded at init time. | +| `modellist` | character string | `DefaultChannelList` | Name of the channel models list to load at init time. | + +### Model lists + +Several model lists can be defined in the oai configuration file. One, defined by the `modellist` parameter is loaded at init time. In the configuration file each model list item describes a channel model using a group of parameters: + +| parameter name | type | default | description | +|:---:|:---:|:---:|:----| +| `model name` | character string | mandatory |name of the model, as used in the code to retrieve a model definition| +| `type` | | `AWGN` | name of the channel modelization algorithm applied on rf signal. The list of available model types can be listed via the [telnet server](../../telnetsrv/DOC/telnetsrv.md) or by entering an invalid type name | +| `ploss_dB` | real (float) | | path loss of the channel, in dB | +| `noise_power_dB` | real (double) | | noise of the channel in dB | +| `forgetfact` | real (double) | | | +| `offset` | integer | | | +| `ds_tdl` | real double | | | + +Channel simulation parameters can also be specified on the command line: + +```bash +./lte-softmodem -O ../../../ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf --noS1 --rfsim --rfsimulator.options chanmod --rfsimulator.serveraddr enb --telnetsrv --channelmod.modellist modellist_rfsimu_2 --channelmod.modellist_rfsimu_2.[1].offset 120 +``` +### Using the telnet server to modify channel simulator parameters +The telnet server includes a `channelmod` command which can be used to dynamically modify some channel model parameters. This command is only available when channel simulation is enabled (via `rfsimulator.options chanmod` option when running the rfsimulator. `channelmod` command has its own help: + +``` +$ telnet 127.0.0.1 9090 +Trying 127.0.0.1... +Connected to 127.0.0.1. +Escape character is '^]'. + +softmodem_enb> help +..................................... + module 6 = channelmod: + channelmod help + channelmod show + channelmod modify + module 7 = rfsimu: + rfsimu setmodel +softmodem_enb> channelmod help +channelmod commands can be used to display or modify channel models parameters +channelmod show predef: display predefined model algorithms available in oai +channelmod show current: display the currently used models in the running executable +channelmod modify : set the specified parameters in a current model to the given value + specifies the model, the show current model command can be used to list the current models indexes + can be one of "riceanf", "aoa", "randaoa", "ploss", "noise_power_dB", "offset", "forgetf" +softmodem_enb> + +``` + + + + + + + +The [rfsimulator documentation](../../../../targets/ARCH/rfsimulator/README.md ) has also some specific information when using the channel simulation via this tool. + +[channel simulation main page](channel_simulation.md) +[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) \ No newline at end of file diff --git a/openair1/SIMULATION/TOOLS/abstraction.c b/openair1/SIMULATION/TOOLS/abstraction.c index 7ac1980417..a6b0586882 100644 --- a/openair1/SIMULATION/TOOLS/abstraction.c +++ b/openair1/SIMULATION/TOOLS/abstraction.c @@ -39,7 +39,7 @@ double **cos_lut=NULL,* *sin_lut=NULL; -int init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) { +int init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples,int scs) { double delta_f,freq; // 90 kHz spacing double delay; int16_t f; @@ -52,7 +52,7 @@ int init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) { cos_lut = (double **)malloc(n_samples*sizeof(double *)); sin_lut = (double **)malloc(n_samples*sizeof(double *)); - delta_f = nb_rb*180000/(n_samples-1); + delta_f = nb_rb*12*scs*1000/(n_samples-1); for (f=-(n_samples>>1); f<=(n_samples>>1); f++) { freq=delta_f*(double)f*1e-6;// due to the fact that delays is in mus @@ -67,14 +67,14 @@ int init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) { cos_lut[f+(n_samples>>1)][l] = cos(2*M_PI*freq*delay); sin_lut[f+(n_samples>>1)][l] = sin(2*M_PI*freq*delay); - //printf("values cos:%d, sin:%d\n", cos_lut[f][l], sin_lut[f][l]); + // printf("values cos:%f, sin:%f\n", cos_lut[f+(n_samples>>1)][l], sin_lut[f+(n_samples>>1)][l]); } } return(0); } -int freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) { +int freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples,int scs) { int16_t f,f2,d; uint8_t aarx,aatx,l; double *clut,*slut; @@ -95,14 +95,14 @@ int freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) { // if called with n_samples<12*nb_rb+1, we decimate the lut n_samples_max=12*nb_rb+1; - if (init_freq_channel(desc,nb_rb,n_samples_max)==0) + if (init_freq_channel(desc,nb_rb,n_samples_max,scs)==0) freq_channel_init=1; else return(-1); } d=(n_samples_max-1)/(n_samples-1); - //printf("no_samples=%d, n_samples_max=%d, d=%d\n",n_samples,n_samples_max,d); + // printf("no_samples=%d, n_samples_max=%d, d=%d,nb_taps %d\n",n_samples,n_samples_max,d,desc->nb_taps); start_meas(&desc->interp_freq); for (f=-n_samples_max/2,f2=-n_samples/2; fnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].x=0.0; - desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].y=0.0; + AssertFatal(n_samples/2+f2 < (2+(275*12)),"reading past chF %d (n_samples %d, f2 %d)\n",n_samples/2+f2,n_samples,f2); + desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].r=0.0; + desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].i=0.0; for (l=0; l<(int)desc->nb_taps; l++) { - desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].x+=(desc->a[l][aarx+(aatx*desc->nb_rx)].x*clut[l]+ - desc->a[l][aarx+(aatx*desc->nb_rx)].y*slut[l]); - desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].y+=(-desc->a[l][aarx+(aatx*desc->nb_rx)].x*slut[l]+ - desc->a[l][aarx+(aatx*desc->nb_rx)].y*clut[l]); + desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].r+=(desc->a[l][aarx+(aatx*desc->nb_rx)].r*clut[l]+ + desc->a[l][aarx+(aatx*desc->nb_rx)].i*slut[l]); + desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].i+=(-desc->a[l][aarx+(aatx*desc->nb_rx)].r*slut[l]+ + desc->a[l][aarx+(aatx*desc->nb_rx)].i*clut[l]); } } } @@ -138,42 +139,42 @@ double compute_pbch_sinr(channel_desc_t *desc, uint16_t f; uint8_t aarx,aatx; double S; - struct complex S_i1; - struct complex S_i2; + struct complexd S_i1; + struct complexd S_i2; avg_sinr=0.0; // printf("nb_rb %d\n",nb_rb); for (f=(nb_rb-6); f<(nb_rb+6); f++) { S = 0.0; - S_i1.x =0.0; - S_i1.y =0.0; - S_i2.x =0.0; - S_i2.y =0.0; + S_i1.r =0.0; + S_i1.i =0.0; + S_i2.r =0.0; + S_i2.i =0.0; for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc->chF[aarx+(aatx*desc->nb_rx)][f].y); + S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc->chF[aarx+(aatx*desc->nb_rx)][f].i); // printf("%d %d chF[%d] => (%f,%f)\n",aarx,aatx,f,desc->chF[aarx+(aatx*desc->nb_rx)][f].x,desc->chF[aarx+(aatx*desc->nb_rx)][f].y); if (desc_i1) { - S_i1.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y); - S_i1.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y - - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x); + S_i1.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].i); + S_i1.i += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].i - + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].r); } if (desc_i2) { - S_i2.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y); - S_i2.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y - - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x); + S_i2.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].i); + S_i2.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].i - + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].r); } } } // printf("snr %f f %d : S %f, S_i1 %f, S_i2 %f\n",snr,f-nb_rb,S,snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y),snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y)); - avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y)+snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y))); + avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.r*S_i1.r + S_i1.i*S_i1.i)+snr_i2*sqrt(S_i2.r*S_i2.r + S_i2.i*S_i2.i))); } // printf("avg_sinr %f (%f,%f,%f)\n",avg_sinr/12.0,snr,snr_i1,snr_i2); @@ -191,42 +192,42 @@ double compute_sinr(channel_desc_t *desc, uint16_t f; uint8_t aarx,aatx; double S; - struct complex S_i1; - struct complex S_i2; + struct complexd S_i1; + struct complexd S_i2; DevAssert( nb_rb > 0 ); avg_sinr=0.0; // printf("nb_rb %d\n",nb_rb); for (f=0; f<2*nb_rb; f++) { S = 0.0; - S_i1.x =0.0; - S_i1.y =0.0; - S_i2.x =0.0; - S_i2.y =0.0; + S_i1.r =0.0; + S_i1.i =0.0; + S_i2.r =0.0; + S_i2.i =0.0; for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc->chF[aarx+(aatx*desc->nb_rx)][f].y); + S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc->chF[aarx+(aatx*desc->nb_rx)][f].i); if (desc_i1) { - S_i1.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y); - S_i1.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y - - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x); + S_i1.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].i); + S_i1.i += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].i - + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].r); } if (desc_i2) { - S_i2.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y); - S_i2.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y - - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x); + S_i2.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].i); + S_i2.i += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].i - + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].r); } } } // printf("f %d : S %f, S_i1 %f, S_i2 %f\n",f-nb_rb,snr*S,snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y),snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y)); - avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y)+snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y))); + avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.r*S_i1.r + S_i1.i*S_i1.i)+snr_i2*sqrt(S_i2.r*S_i2.r + S_i2.i*S_i2.i))); } // printf("avg_sinr %f (%f,%f,%f)\n",avg_sinr/12.0,snr,snr_i1,snr_i2); diff --git a/openair1/SIMULATION/TOOLS/channel_sim.c b/openair1/SIMULATION/TOOLS/channel_sim.c index c5628fbcef..197a296a51 100644 --- a/openair1/SIMULATION/TOOLS/channel_sim.c +++ b/openair1/SIMULATION/TOOLS/channel_sim.c @@ -70,16 +70,16 @@ void do_DL_sig(sim_t *sim, double s_re0[30720]; double s_re1[30720]; - double *s_re[2]; + double *s_re[RC.nb_RU]; double s_im0[30720]; double s_im1[30720]; - double *s_im[2]; + double *s_im[RC.nb_RU]; double r_re00[30720]; double r_re01[30720]; - double *r_re0[2]; + double *r_re0[RC.nb_RU]; double r_im00[30720]; double r_im01[30720]; - double *r_im0[2]; + double *r_im0[RC.nb_RU]; LTE_DL_FRAME_PARMS *frame_parms; s_re[0] = s_re0; @@ -180,7 +180,7 @@ void do_DL_sig(sim_t *sim, //RU2UE[eNB_id][UE_id]->path_loss_dB = 0; multipath_channel(sim->RU2UE[ru_id][UE_id][CC_id],s_re,s_im,r_re0,r_im0, - length,hold_channel); + length,hold_channel,0); #ifdef DEBUG_SIM rx_pwr = signal_energy_fp2(sim->RU2UE[ru_id][UE_id][CC_id]->ch[0], sim->RU2UE[ru_id][UE_id][CC_id]->channel_length)*sim->RU2UE[ru_id][UE_id][CC_id]->channel_length; @@ -320,16 +320,16 @@ void do_UL_sig(sim_t *sim, double s_re0[30720]; double s_re1[30720]; - double *s_re[2]; + double *s_re[NB_UE_INST]; double s_im0[30720]; double s_im1[30720]; - double *s_im[2]; + double *s_im[NB_UE_INST]; double r_re00[30720]; double r_re01[30720]; - double *r_re0[2]; + double *r_re0[NB_UE_INST]; double r_im00[30720]; double r_im01[30720]; - double *r_im0[2]; + double *r_im0[NB_UE_INST]; s_re[0] = s_re0; s_im[0] = s_im0; @@ -394,7 +394,7 @@ void do_UL_sig(sim_t *sim, multipath_channel(sim->UE2RU[UE_id][ru_id][CC_id],s_re,s_im,r_re0,r_im0, - frame_parms->samples_per_tti,hold_channel); + frame_parms->samples_per_tti,hold_channel,0); rx_pwr = signal_energy_fp2(sim->UE2RU[UE_id][ru_id][CC_id]->ch[0], diff --git a/openair1/SIMULATION/TOOLS/corr_mat.m b/openair1/SIMULATION/TOOLS/corr_mat.m index 6629030b7d..783310e6e5 100644 --- a/openair1/SIMULATION/TOOLS/corr_mat.m +++ b/openair1/SIMULATION/TOOLS/corr_mat.m @@ -57,11 +57,11 @@ R22_sqrt_int(2:2:end,:,:) = imag(R22_sqrt); %% fid = fopen('scm_corrmat.h','w'); -fprintf(fid,'double R22_sqrt[][] = {\n'); +fprintf(fid,'static double R22_sqrt[][] = {\n'); for i=1:size(Gamma,3) fprintf(fid,'{'); fprintf(fid,'%f, ',R22_sqrt_int(:,:,i)); fprintf(fid,'\b\b},\n'); end fprintf(fid,'};\n'); -fclose(fid) \ No newline at end of file +fclose(fid) diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index 70227c8e8d..3045d8ca6c 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -39,12 +39,13 @@ uint8_t multipath_channel_nosigconv(channel_desc_t *desc) //#define CHANNEL_SSE #ifdef CHANNEL_SSE void multipath_channel(channel_desc_t *desc, - double tx_sig_re[2][30720*2], - double tx_sig_im[2][30720*2], - double rx_sig_re[2][30720*2], - double rx_sig_im[2][30720*2], + double tx_sig_re[NB_ANTENNAS_TX][30720*2], + double tx_sig_im[NB_ANTENANS_TX][30720*2], + double rx_sig_re[NB_ANTENNAS_RX][30720*2], + double rx_sig_im[NB_ANTENNAS_RX][30720*2], uint32_t length, - uint8_t keep_channel) + uint8_t keep_channel, + int log_channel) { int i,ii,j,l; @@ -145,16 +146,17 @@ void multipath_channel(channel_desc_t *desc, #else void multipath_channel(channel_desc_t *desc, - double *tx_sig_re[2], - double *tx_sig_im[2], - double *rx_sig_re[2], - double *rx_sig_im[2], + double *tx_sig_re[NB_ANTENNAS_TX], + double *tx_sig_im[NB_ANTENNAS_TX], + double *rx_sig_re[NB_ANTENNAS_RX], + double *rx_sig_im[NB_ANTENNAS_RX], uint32_t length, - uint8_t keep_channel) + uint8_t keep_channel, + int log_channel) { int i,ii,j,l; - struct complex rx_tmp,tx; + struct complexd rx_tmp,tx; double path_loss = pow(10,desc->path_loss_dB/20); int dd; @@ -181,31 +183,37 @@ void multipath_channel(channel_desc_t *desc, for (i=0; i<((int)length-dd); i++) { for (ii=0; iinb_rx; ii++) { - rx_tmp.x = 0; - rx_tmp.y = 0; + rx_tmp.r = 0; + rx_tmp.i = 0; for (j=0; jnb_tx; j++) { for (l = 0; l<(int)desc->channel_length; l++) { if ((i>=0) && (i-l)>=0) { - tx.x = tx_sig_re[j][i-l]; - tx.y = tx_sig_im[j][i-l]; + tx.r = tx_sig_re[j][i-l]; + tx.i = tx_sig_im[j][i-l]; } else { - tx.x =0; - tx.y =0; + tx.r =0; + tx.i =0; } - rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y); - rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y); + rx_tmp.r += (tx.r * desc->ch[ii+(j*desc->nb_rx)][l].r) - (tx.i * desc->ch[ii+(j*desc->nb_rx)][l].i); + rx_tmp.i += (tx.i * desc->ch[ii+(j*desc->nb_rx)][l].r) + (tx.r * desc->ch[ii+(j*desc->nb_rx)][l].i); + + if (i==0 && log_channel == 1) { + printf("channel[%d][%d][%d] = %f dB (%e,%e)\n",ii,j,l,10*log10(pow(desc->ch[ii+(j*desc->nb_rx)][l].r,2.0)+pow(desc->ch[ii+(j*desc->nb_rx)][l].i,2.0)), + desc->ch[ii+(j*desc->nb_rx)][l].r, + desc->ch[ii+(j*desc->nb_rx)][l].i); + } } //l } // j - rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss; - rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss; - /* - if ((ii==0)&&((i%32)==0)) { - printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]); - } - */ + rx_sig_re[ii][i+dd] = rx_tmp.r*path_loss; + rx_sig_im[ii][i+dd] = rx_tmp.i*path_loss; +#ifdef DEBUG_CHANNEL + if ((i%32)==0) { + printf("rx aa %d: %p %p %f,%f => %e,%e\n",ii,rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]); + } +#endif //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]); //rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]); diff --git a/openair1/SIMULATION/TOOLS/multipath_tv_channel.c b/openair1/SIMULATION/TOOLS/multipath_tv_channel.c index d344992586..ece1f81335 100644 --- a/openair1/SIMULATION/TOOLS/multipath_tv_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_tv_channel.c @@ -40,19 +40,17 @@ void multipath_tv_channel(channel_desc_t *desc, uint8_t keep_channel) { - double complex **tx,**rx,***H_t,*rx_temp;//, *tv_H_t; + double complex **tx,**rx,***H_t; double path_loss = pow(10,desc->path_loss_dB/20); - int i,j,k,dd; + int i,j,dd; dd = abs(desc->channel_offset); #ifdef DEBUG_CH printf("[TV CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d max_doppler %g\n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length, desc->max_Doppler); #endif - tx = (double complex **)malloc(desc->nb_tx*sizeof(double complex)); - rx = (double complex **)malloc(desc->nb_rx*sizeof(double complex)); - H_t= (double complex ** *) malloc(desc->nb_tx*desc->nb_rx*sizeof(double complex **)); - // tv_H_t = (double complex *) malloc(length*sizeof(double complex)); - rx_temp= (double complex *) calloc(length,sizeof(double complex)); + tx = (double complex **)malloc(desc->nb_tx*sizeof(double complex *)); + rx = (double complex **)malloc(desc->nb_rx*sizeof(double complex *)); + H_t= (double complex ***) malloc(desc->nb_tx*desc->nb_rx*sizeof(double complex **)); for(i=0; inb_tx; i++) { tx[i] = (double complex *)calloc(length,sizeof(double complex)); @@ -63,10 +61,10 @@ void multipath_tv_channel(channel_desc_t *desc, } for(i=0; inb_tx*desc->nb_rx; i++) { - H_t[i] = (double complex **) malloc(length*sizeof(double complex *)); + H_t[i] = (double complex **)malloc(desc->nb_taps*sizeof(double complex *)); - for(j=0; jnb_taps,sizeof(double complex)); + for(j=0; jnb_taps; j++) { + H_t[i][j] = (double complex *)calloc(length,sizeof(double complex)); } } @@ -84,11 +82,7 @@ void multipath_tv_channel(channel_desc_t *desc, for(i=0; inb_rx; i++) { for(j=0; jnb_tx; j++) { - tv_conv(H_t[i+(j*desc->nb_rx)],tx[j],rx_temp,length,desc->nb_taps,dd); - - for(k=0; knb_rx)],tx[j],rx[i],length,desc->nb_taps,dd); } } @@ -99,10 +93,6 @@ void multipath_tv_channel(channel_desc_t *desc, } } - /* for(k=0;knb_tx; i++) { free(tx[i]); } @@ -116,7 +106,7 @@ void multipath_tv_channel(channel_desc_t *desc, free(rx); for(i=0; inb_rx*desc->nb_tx; i++) { - for(j=0; jnb_taps; j++) { free(H_t[i][j]); } @@ -124,21 +114,35 @@ void multipath_tv_channel(channel_desc_t *desc, } free(H_t); - free(rx_temp); } //TODO: make phi_rad a parameter of this function void tv_channel(channel_desc_t *desc,double complex ***H,uint32_t length){ int i,j,p,l,k; - double *alpha,*phi_rad,pi=acos(-1),*w_Hz; + double *alpha,***phi_rad,pi=acos(-1),***w_Hz; alpha = (double *)calloc(desc->nb_paths,sizeof(double)); - phi_rad = (double *)calloc(desc->nb_paths,sizeof(double)); - w_Hz = (double *)calloc(desc->nb_paths,sizeof(double)); + phi_rad = (double ***)malloc(desc->nb_rx*desc->nb_tx*sizeof(double **)); + w_Hz = (double ***)malloc(desc->nb_rx*desc->nb_tx*sizeof(double **)); - for(i=0; inb_paths; i++) { - w_Hz[i]=desc->max_Doppler*cos(frand_a_b(0,2*pi)); - phi_rad[i]=frand_a_b(0,2*pi); + for(i=0; inb_tx*desc->nb_rx; i++) { + phi_rad[i] = (double **) malloc(desc->nb_taps*sizeof(double *)); + w_Hz[i] = (double **) malloc(desc->nb_taps*sizeof(double *)); + for(j=0; jnb_taps; j++) { + phi_rad[i][j] = (double *) malloc(desc->nb_paths*sizeof(double)); + w_Hz[i][j] = (double *) malloc(desc->nb_paths*sizeof(double)); + } + } + + for(i=0; inb_tx*desc->nb_rx; i++) { + for (j = 0; jnb_taps; j++) { + for(k=0; knb_paths; k++) { + w_Hz[i][j][k] = desc->max_Doppler*cos(frand_a_b(0,2*M_PI)); + phi_rad[i][j][k] = frand_a_b(0,2*M_PI); + //printf("w_hz[%d][%d][%d]=f_d*cos(theta) = %f\n",i,j,k,w_Hz[i][j][k]); + //printf("phi_rad[%d][%d][%d] = %f\n",i,j,k,phi_rad[i][j][k]); + } + } } if(desc->ricean_factor == 1) { @@ -153,57 +157,45 @@ void tv_channel(channel_desc_t *desc,double complex ***H,uint32_t length){ } } - /* - // This is the code when we only consider a SISO case - for(i=0;inb_taps;j++) - { - for(p=0;pnb_paths;p++) - { - H[i][j] += sqrt(desc->amps[j]/2)*alpha[p]*cexp(-I*(2*pi*w_Hz[p]*i*(1/(desc->sampling_rate*1e6))+phi_rad[p])); - } - } - } - for(j=0;jnb_paths;j++) - { - phi_rad[j] = fmod(2*pi*w_Hz[j]*(length-1)*(1/desc->sampling_rate)+phi_rad[j],2*pi); - } - */ - - // if MIMO + // SISO or MIMO for (i=0; inb_rx; i++) { for(j=0; jnb_tx; j++) { - for(k=0; knb_taps; l++) { - H[i+(j*desc->nb_rx)][k][l] = 0; - + for(k=0; knb_taps; k++) { + for(l=0; lnb_paths; p++) { - H[i+(j*desc->nb_rx)][k][l] += sqrt(desc->amps[l]/2)*alpha[p]*cexp(I*(2*pi*w_Hz[p]*k*(1/(desc->sampling_rate*1e6))+phi_rad[p])); + H[i+(j*desc->nb_rx)][k][l] += sqrt(desc->amps[k])*alpha[p]*cexp(I*(2*pi*w_Hz[i+(j*desc->nb_rx)][k][p]*l*(1/(desc->sampling_rate*1e6))+phi_rad[i+(j*desc->nb_rx)][k][p])); } } - } - - for(j=0; jnb_paths; j++) { - phi_rad[j] = fmod(2*pi*w_Hz[j]*(length-1)*(1/desc->sampling_rate)+phi_rad[j],2*pi); + //printf("H[tx%d][rx%d][k%d][l%d] = %f+j%f \n",j,i,k,0,creal(H[i+(j*desc->nb_rx)][k][0]),cimag(H[i+(j*desc->nb_rx)][k][0])); } } } - + //accumlate the phase + /*for(k=0; knb_taps; k++) { + * for(j=0; jnb_paths; j++) { + * desc->random_phase[k][j] = fmod(2*pi*w_Hz[k][j]*(length-1)*(1/(desc->sampling_rate*1e6))+phi_rad[k][j],2*pi); + * } + * }*/ free(alpha); + for(i=0; inb_rx*desc->nb_tx; i++) { + for (j=0; jnb_taps; j++) { + free(w_Hz[i][j]); + free(phi_rad[i][j]); + } + free(w_Hz[i]); + free(phi_rad[i]); + } free(w_Hz); free(phi_rad); } // time varying convolution -void tv_conv(double complex **h, double complex *x, double complex *y, uint32_t nb_samples, uint8_t nb_taps, int dd){ - - int i,j; - - for(i=0; i<((int)nb_samples-dd); i++) { - for(j=0; jj) - y[i+dd] += creal(h[i][j])*creal(x[i-j])-cimag(h[i][j])*cimag(x[i-j]) + I*(creal(h[i][j])*cimag(x[i-j])+cimag(h[i][j])*creal(x[i-j])); +void tv_conv(double complex **h, double complex *x, double complex *y, uint32_t nb_samples, uint8_t nb_taps, int dd) +{ + for(int i = 0; i < ((int)nb_samples-dd); i++) { + for(int j = 0; j < nb_taps; j++) { + if(i >= j) + y[i+dd] += h[j][i] * x[i-j]; } } } diff --git a/openair1/SIMULATION/TOOLS/phase_noise.c b/openair1/SIMULATION/TOOLS/phase_noise.c new file mode 100644 index 0000000000..6cc24f23db --- /dev/null +++ b/openair1/SIMULATION/TOOLS/phase_noise.c @@ -0,0 +1,72 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include +#include "sim.h" + + +static uint16_t LUTSin[ResolSinCos+1]; +/* linear phase noise model */ +void phase_noise(double ts, int16_t * InRe, int16_t * InIm) +{ + static uint64_t i=0; + int32_t x=0 ,y=0; + double fd = 300;//0.01*30000 + int16_t SinValue = 0, CosValue= 0; + double IdxDouble = (double)(i*fd * ts * ResolSinCos * 4); + int16_t IdxModulo = ((int32_t)(IdxDouble>0 ? IdxDouble+0.5 : IdxDouble-0.5)) % (ResolSinCos*4); + IdxModulo = IdxModulo<0 ? IdxModulo+ResolSinCos*4 : IdxModulo; + + if(IdxModulo<2*ResolSinCos) {//< 2 check for 1st and 2nd + if(IdxModulo < ResolSinCos) {// 1st Quadrant + SinValue = LUTSin[IdxModulo]; + CosValue = LUTSin[ResolSinCos-IdxModulo]; + } + else {// 2nd Quadrant + SinValue = LUTSin[2*ResolSinCos-IdxModulo]; + CosValue = -LUTSin[IdxModulo-ResolSinCos]; + } + } + else {// 3rd and 4th Quadrant + if(IdxModulo < 3*ResolSinCos) {// 3rd Quadrant + SinValue = -LUTSin[IdxModulo-2*ResolSinCos]; + CosValue = -LUTSin[3*ResolSinCos-IdxModulo]; + } + else {//4th Quadrant + SinValue = -LUTSin[4*ResolSinCos-IdxModulo]; + CosValue = LUTSin[IdxModulo-3*ResolSinCos]; + } + } + x = ( ((int32_t)InRe[0] * CosValue) - ((int32_t)InIm[0] * SinValue )); + y = ( ((int32_t)InIm[0] * CosValue) + ((int32_t)InRe[0] * SinValue )); + InRe[0]= (int16_t)(x>>14); + InIm[0]= (int16_t)(y>>14); + i++; +} +/* Initialisation function for SIN table values */ +void InitSinLUT( void ) { + for ( int i=0; i<(ResolSinCos+1); i++ ) { + LUTSin[i] = sin((double)(M_PI*i)/(2*ResolSinCos)) * (1<<14); //Format: Q14 + } +} diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index f97b9dfb78..f09d1a7ce1 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -50,7 +50,7 @@ static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt) static telnetshell_cmddef_t channelmod_cmdarray[] = { {"help","",channelmod_print_help}, {"show","",channelmod_show_cmd}, - {"modify"," ",channelmod_modify_cmd}, + {"modify"," ",channelmod_modify_cmd}, {"","",NULL}, }; @@ -61,15 +61,18 @@ static telnetshell_vardef_t channelmod_vardef[] = { static double snr_dB=25; static double sinr_dB=0; static unsigned int max_chan; -static channel_desc_t** defined_channels; +static channel_desc_t **defined_channels; +static char modellist_name[MAX_OPTNAME_SIZE]= {0}; + + void fill_channel_desc(channel_desc_t *chan_desc, uint8_t nb_tx, uint8_t nb_rx, uint8_t nb_taps, uint8_t channel_length, double *amps, - double *delays, - struct complex **R_sqrt, + double *delays, + struct complexd *R_sqrt, double Td, double sampling_rate, double channel_bandwidth, @@ -113,50 +116,52 @@ void fill_channel_desc(channel_desc_t *chan_desc, chan_desc->first_run = 1; chan_desc->ip = 0.0; chan_desc->max_Doppler = max_Doppler; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(nb_taps*sizeof(struct complexd *)); LOG_D(OCM,"[CHANNEL] Filling ch \n"); for (i = 0; ich[i] = (struct complex *) malloc(channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); // allocate for up to 100 RBs, 12 samples per RB + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); // allocate for up to 100 RBs, 12 samples per RB LOG_D(OCM,"[CHANNEL] Filling a (nb_taps %d)\n",nb_taps); for (i = 0; ia[i],nb_tx*nb_rx * sizeof(struct complex)); - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + LOG_D(OCM,"tap %d (%p,%zu)\n",i,&chan_desc->a[i],nb_tx*nb_rx * sizeof(struct complexd)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); } LOG_D(OCM,"[CHANNEL] Doing R_sqrt ...\n"); if (R_sqrt == NULL) { - chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); + chan_desc->R_sqrt = (struct complexd **) calloc(nb_taps,sizeof(struct complexd *)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_NTAPS ; + for (i = 0; iR_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complexd)); + for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } } } else { - chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); - + chan_desc->R_sqrt = (struct complexd **) calloc(nb_taps,sizeof(struct complexd *)); + for (i = 0; iR_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); - //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; + //chan_desc->R_sqrt[i] = (struct complexd*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complexd)); + //chan_desc->R_sqrt = (struct complexd*)&R_sqrt[i][0]; /* all chan_desc share the same R_sqrt, coming from caller */ - chan_desc->R_sqrt[i] = R_sqrt[0]; + chan_desc->R_sqrt[i] = R_sqrt; } } for (i = 0; iR_sqrt[i][j].x,chan_desc->R_sqrt[i][j].y); + LOG_D(OCM,"Rsqrt[%d][%d] %f %f\n",i,j,chan_desc->R_sqrt[i][j].r,chan_desc->R_sqrt[i][j].i); } } @@ -172,135 +177,406 @@ void fill_channel_desc(channel_desc_t *chan_desc, reset_meas(&chan_desc->convolution); } -double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58}; -double mbsfn_amps_dB[] = {0,-1.5,-1.4,-3.6,-0.6,-7.0,-10,-11.5,-11.4,-13.6,-10.6,-17.0,-20,-21.5,-21.4,-23.6,-20.6,-27}; +static double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58}; +static double mbsfn_amps_dB[] = {0,-1.5,-1.4,-3.6,-0.6,-7.0,-10,-11.5,-11.4,-13.6,-10.6,-17.0,-20,-21.5,-21.4,-23.6,-20.6,-27}; -double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250}; -double scm_c_amps_dB[] = {0.00, -2.22, -3.98, -1.86, -4.08, -5.84, -1.08, -3.30, -5.06, -9.08, -11.30, -13.06, -15.14, -17.36, -19.12, -20.64, -22.85, -24.62}; +static double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250}; +static double scm_c_amps_dB[] = {0.00, -2.22, -3.98, -1.86, -4.08, -5.84, -1.08, -3.30, -5.06, -9.08, -11.30, -13.06, -15.14, -17.36, -19.12, -20.64, -22.85, -24.62}; -double epa_delays[] = { 0,.03,.07,.09,.11,.19,.41}; -double epa_amps_dB[] = {0.0,-1.0,-2.0,-3.0,-8.0,-17.2,-20.8}; +static double tdl_a_delays[] = {0.0000, + 0.3819, + 0.4025, + 0.5868, + 0.4610, + 0.5375, + 0.6708, + 0.5750, + 0.7618, + 1.5375, + 1.8978, + 2.2242, + 2.1718, + 2.4942, + 2.5119, + 3.0582, + 4.0810, + 4.4579, + 4.5695, + 4.7966, + 5.0066, + 5.3043, + 9.6586 + }; +static double tdl_a_amps_dB[] = {-13.4, + 0, + -2.2, + -4, + -6, + -8.2, + -9.9, + -10.5, + -7.5, + -15.9, + -6.6, + -16.7, + -12.4, + -15.2, + -10.8, + -11.3, + -12.7, + -16.2, + -18.3, + -18.9, + -16.6, + -19.9, + -29.7 + }; -double eva_delays[] = { 0,.03,.15,.31,.37,.71,1.09,1.73,2.51}; -double eva_amps_dB[] = {0.0,-1.5,-1.4,-3.6,-0.6,-9.1,-7.0,-12.0,-16.9}; +static double tdl_b_delays[] = {0.0000, + 0.1072, + 0.2155, + 0.2095, + 0.2870, + 0.2986, + 0.3752, + 0.5055, + 0.3681, + 0.3697, + 0.5700, + 0.5283, + 1.1021, + 1.2756, + 1.5474, + 1.7842, + 2.0169, + 2.8294, + 3.0219, + 3.6187, + 4.1067, + 4.2790, + 4.7834 + }; -double etu_delays[] = { 0,.05,.12,.2,.23,.5,1.6,2.3,5.0}; -double etu_amps_dB[] = {-1.0,-1.0,-1.0,0.0,0.0,0.0,-3.0,-5.0,-7.0}; +static double tdl_b_amps_dB[] = {0, + -2.2, + -4, + -3.2, + -9.8, + -1.2, + -3.4, + -5.2, + -7.6, + -3, + -8.9, + -9, + -4.8, + -5.7, + -7.5, + -1.9, + -7.6, + -12.2, + -9.8, + -11.4, + -14.9, + -9.2, + -11.3 + }; -double default_amps_lin[] = {0.3868472, 0.3094778, 0.1547389, 0.0773694, 0.0386847, 0.0193424, 0.0096712, 0.0038685}; -double default_amp_lin[] = {1}; +static double tdl_c_delays[] = {0, + 0.2099, + 0.2219, + 0.2329, + 0.2176, + 0.6366, + 0.6448, + 0.6560, + 0.6584, + 0.7935, + 0.8213, + 0.9336, + 1.2285, + 1.3083, + 2.1704, + 2.7105, + 4.2589, + 4.6003, + 5.4902, + 5.6077, + 6.3065, + 6.6374, + 7.0427, + 8.6523 + }; -double ts_shift_delays[] = {0, 1/7.68}; -double ts_shift_amps[] = {0, 1}; +static double tdl_c_amps_dB[] = {-4.4, + -1.2, + -3.5, + -5.2, + -2.5, + 0, + -2.2, + -3.9, + -7.4, + -7.1, + -10.7, + -11.1, + -5.1, + -6.8, + -8.7, + -13.2, + -13.9, + -13.9, + -15.8, + -17.1, + -16, + -15.7, + -21.6, + -22.8 + }; + +static double tdl_d_delays[] = {//0, + 0, + 0.035, + 0.612, + 1.363, + 1.405, + 1.804, + 2.596, + 1.775, + 4.042, + 7.937, + 9.424, + 9.708, + 12.525 +}; + +static double tdl_d_amps_dB[] = {//-0.2, + //-13.5, + -.00147, + -18.8, + -21, + -22.8, + -17.9, + -20.1, + -21.9, + -22.9, + -27.8, + -23.6, + -24.8, + -30.0, + -27.7 + }; + +#define TDL_D_RICEAN_FACTOR .046774 + +static double tdl_e_delays[] = {0, + 0.5133, + 0.5440, + 0.5630, + 0.5440, + 0.7112, + 1.9092, + 1.9293, + 1.9589, + 2.6426, + 3.7136, + 5.4524, + 12.0034, + 20.6519 + }; + +static double tdl_e_amps_dB[] = {//-0.03, + //-22.03, + -.00433, + -15.8, + -18.1, + -19.8, + -22.9, + -22.4, + -18.6, + -20.8, + -22.6, + -22.3, + -25.6, + -20.2, + -29.8, + -29.2 + }; + +#define TDL_E_RICEAN_FACTOR 0.0063096 + +static double epa_delays[] = { 0,.03,.07,.09,.11,.19,.41}; +static double epa_amps_dB[] = {0.0,-1.0,-2.0,-3.0,-8.0,-17.2,-20.8}; + +static double eva_delays[] = { 0,.03,.15,.31,.37,.71,1.09,1.73,2.51}; +static double eva_amps_dB[] = {0.0,-1.5,-1.4,-3.6,-0.6,-9.1,-7.0,-12.0,-16.9}; + +static double etu_delays[] = { 0,.05,.12,.2,.23,.5,1.6,2.3,5.0}; +static double etu_amps_dB[] = {-1.0,-1.0,-1.0,0.0,0.0,0.0,-3.0,-5.0,-7.0}; + +static double default_amps_lin[] = {0.3868472, 0.3094778, 0.1547389, 0.0773694, 0.0386847, 0.0193424, 0.0096712, 0.0038685}; +static double default_amp_lin[] = {1}; //correlation matrix for a 2x2 channel with full Tx correlation -struct complex R_sqrt_22_corr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, +static struct complexd R_sqrt_22_corr[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0} }; -struct complex *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap}; //correlation matrix for a fully correlated 2x1 channel (h1==h2) -struct complex R_sqrt_21_corr_tap[4] = {{0.70711,0}, {0.70711,0}, {0.70711,0}, {0.70711,0}}; -struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap}; +static struct complexd R_sqrt_21_corr[] = {{0.70711,0}, {0.70711,0}, {0.70711,0}, {0.70711,0}}; //correlation matrix for a 2x2 channel with full Tx anti-correlation -struct complex R_sqrt_22_anticorr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, +static struct complexd R_sqrt_22_anticorr[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0} }; -struct complex *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap}; //correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2) -struct complex R_sqrt_21_anticorr_tap[4] = {{0.70711,0}, {-0.70711,0}, {-0.70711,0}, {0.70711,0}}; -struct complex *R_sqrt_21_anticorr[1] = {R_sqrt_21_anticorr_tap}; - -struct complex **R_sqrt_ptr2; +static struct complexd R_sqrt_21_anticorr[4] = {{0.70711,0}, {-0.70711,0}, {-0.70711,0}, {0.70711,0}}; // full correlation matrix in vectorized form for 2x2 channel, where h1 is perfectly orthogonal to h2 -struct complex R_sqrt_22_orthogonal_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, +static struct complexd R_sqrt_22_orthogonal[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0} }; -struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; // full correlation matrix for TM4 to make orthogonal effective channel - - - - -struct complex R_sqrt_22_orth_eff_ch_TM4_prec_real_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, +static struct complexd R_sqrt_22_orth_eff_ch_TM4_prec_real[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {-0.70711,0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0} }; -struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_real_tap}; - - - -struct complex R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0}, +static struct complexd R_sqrt_22_orth_eff_ch_TM4_prec_imag[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0,0.70711}, {0.0,-0.70711}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.70711}, {0.0, 0.0}, {-0.70711,0.0} }; -struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_imag[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap}; //Correlation matrix for EPA channel -struct complex R_sqrt_22_EPA_low_tap[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, +static struct complexd R_sqrt_22_EPA_low[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0} }; -struct complex *R_sqrt_22_EPA_low[1] = {R_sqrt_22_EPA_low_tap}; -struct complex R_sqrt_22_EPA_high_tap[16] = { +static struct complexd R_sqrt_22_EPA_high[16] = { {0.7179,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.7179,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.7179,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.7179,0.0} }; -struct complex *R_sqrt_22_EPA_high[1] = {R_sqrt_22_EPA_high_tap}; -struct complex R_sqrt_22_EPA_medium_tap[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, +static struct complexd R_sqrt_22_EPA_medium[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, {0.5249,0.0}, {0.8375,0.0}, {0.0806,0.0}, {0.1286,0.0}, {0.1286,0.0}, {0.0806,0.0}, {0.8375,0.0}, {0.5249,0.0}, {0.0806,0.0}, {0.1286,0.0}, {0.5249,0.0}, {0.8375,0.0} }; -struct complex *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap}; - - //Rayleigh1_orth_eff_ch_TM4 +void tdlModel(int tdl_paths, double *tdl_delays, double *tdl_amps_dB, double DS_TDL, channel_desc_t *chan_desc ) { + int nb_rx=chan_desc-> nb_rx; + int nb_tx=chan_desc-> nb_tx; + int tdl_pathsby3 = tdl_paths/3; + + if ((tdl_paths%3)>0) + tdl_pathsby3++; + + chan_desc->nb_taps = tdl_paths; + chan_desc->Td = tdl_delays[tdl_paths-1]*DS_TDL; + printf("last path (%d) at %f * %e = %e\n",tdl_paths-1,tdl_delays[tdl_paths-1],DS_TDL,chan_desc->Td); + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + + 1 + + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + printf("TDL : %f Ms/s, nb_taps %d, Td %e, channel_length %d\n",chan_desc->sampling_rate,tdl_paths,chan_desc->Td,chan_desc->channel_length); + double sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (int i = 0; inb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*tdl_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + + for (int i = 0; inb_taps; i++) { + chan_desc->amps[i] /= sum_amps; + tdl_delays[i] *= DS_TDL; + } + + chan_desc->delays = tdl_delays; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); + + for (int i = 0; ich[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); + + for (int i = 0; ichF[i] = (struct complexd *) malloc((2+(275*12)) * sizeof(struct complexd)); + + for (int i = 0; inb_taps; i++) + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); + + chan_desc->R_sqrt = (struct complexd **) malloc(tdl_pathsby3*sizeof(struct complexd **)); + + if (nb_tx==2 && nb_rx==2) { + for (int i = 0; i<(tdl_pathsby3); i++) + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; + } else if (nb_tx==2 && nb_rx==1) { + for (int i = 0; i<(tdl_pathsby3); i++) + chan_desc->R_sqrt[i] = (struct complexd *) &R21_sqrt[i][0]; + } else if (nb_tx==1 && nb_rx==2) { + for (int i = 0; i<(tdl_pathsby3); i++) + chan_desc->R_sqrt[i] = (struct complexd *) &R12_sqrt[i][0]; + } else { + for (int i = 0; i<(tdl_pathsby3); i++) { + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); + + for (int j = 0; jR_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; + } + + LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); + } + } +} + channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, uint8_t nb_rx, SCM_t channel_model, double sampling_rate, double channel_bandwidth, - double forgetting_factor, + double DS_TDL, + double forgetting_factor, int32_t channel_offset, - double path_loss_dB) { + double path_loss_dB, + float noise_power_dB) { channel_desc_t *chan_desc = (channel_desc_t *)calloc(1,sizeof(channel_desc_t)); - for(int i=0; ichan_idx=i; - break; - } - else { - AssertFatal(i<(max_chan-1), - "No more channel descriptors available, increase channelmod.max_chan parameter above %u\n",max_chan); - } + + for(int i=0; ichan_idx=i; + break; + } else { + AssertFatal(i<(max_chan-1), + "No more channel descriptors available, increase channelmod.max_chan parameter above %u\n",max_chan); + } } + uint16_t i,j; double sum_amps; double aoa,ricean_factor,Td,maxDoppler; int channel_length,nb_taps; + struct complexd *R_sqrt_ptr2; chan_desc->modelid = channel_model; chan_desc->nb_tx = nb_tx; chan_desc->nb_rx = nb_rx; @@ -311,8 +587,13 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->path_loss_dB = path_loss_dB; chan_desc->first_run = 1; chan_desc->ip = 0.0; + chan_desc->noise_power_dB = noise_power_dB; LOG_I(OCM,"Channel Model (inside of new_channel_desc_scm)=%d\n\n", channel_model); + int tdl_paths=0; + double *tdl_amps_dB; + double *tdl_delays; + /* Spatial Channel Models (SCM) channel model from TR 38.901 Section 7.7.2 */ switch (channel_model) { case SCM_A: LOG_W(OCM,"channel model not yet supported\n"); @@ -330,7 +611,8 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -343,38 +625,39 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); if (nb_tx==2 && nb_rx==2) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else if (nb_tx==2 && nb_rx==1) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R21_sqrt[i][0]; } else if (nb_tx==1 && nb_rx==2) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R12_sqrt[i][0]; } else { - chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; + for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); + for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); @@ -391,6 +674,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -403,38 +687,39 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 0.1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); if (nb_tx==2 && nb_rx==2) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else if (nb_tx==2 && nb_rx==1) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R21_sqrt[i][0]; } else if (nb_tx==1 && nb_rx==2) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R12_sqrt[i][0]; } else { - chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; + for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); @@ -442,7 +727,43 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, } break; - + /* tapped delay line (TDL) channel model from TR 38.901 Section 7.7.2 */ +#define tdl_m(MoDel)\ + DevAssert(sizeof(tdl_ ## MoDel ## _amps_dB) == sizeof(tdl_ ## MoDel ## _delays)); \ + tdl_paths=sizeof(tdl_ ## MoDel ## _amps_dB)/sizeof(*tdl_ ## MoDel ## _amps_dB);\ + tdl_delays=tdl_ ## MoDel ## _delays;\ + tdl_amps_dB=tdl_ ## MoDel ## _amps_dB + + case TDL_A: + chan_desc->ricean_factor = 1; + tdl_m(a); + tdlModel(tdl_paths, tdl_delays, tdl_amps_dB, DS_TDL, chan_desc); + break; + + case TDL_B: + chan_desc->ricean_factor = 1; + tdl_m(b); + tdlModel(tdl_paths, tdl_delays, tdl_amps_dB, DS_TDL, chan_desc); + break; + + case TDL_C: + chan_desc->ricean_factor = 1; + tdl_m(c); + tdlModel(tdl_paths, tdl_delays, tdl_amps_dB, DS_TDL, chan_desc); + break; + + case TDL_D: + chan_desc->ricean_factor = TDL_D_RICEAN_FACTOR; + tdl_m(d); + tdlModel(tdl_paths, tdl_delays, tdl_amps_dB, DS_TDL, chan_desc); + break; + + case TDL_E: + chan_desc->ricean_factor = TDL_E_RICEAN_FACTOR; + tdl_m(e); + tdlModel(tdl_paths, tdl_delays, tdl_amps_dB, DS_TDL, chan_desc); + break; + case EPA: chan_desc->nb_taps = 7; chan_desc->Td = .410; @@ -450,6 +771,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -462,33 +784,34 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); - + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); + for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; + for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); @@ -504,6 +827,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -516,32 +840,32 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd **)); for (i = 0; inb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0]; + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low; } else { printf("Correlation matrices are implemented for 2 x 2 only"); } /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + chan_desc->R_sqrt = (struct complexd**) malloc(6*sizeof(struct complexd**)); for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -549,7 +873,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); } }*/ - break; + break; case EPA_high: chan_desc->nb_taps = 7; @@ -558,6 +882,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -570,32 +895,32 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd **)); for (i = 0; inb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0]; + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high; } else { printf("Correlation matrices are implemented for 2 x 2 only"); } /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + chan_desc->R_sqrt = (struct complexd**) malloc(6*sizeof(struct complexd**)); for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -611,7 +936,8 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -624,32 +950,32 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd **)); for (i = 0; inb_taps; i++) - chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0]; + chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium; } else { printf("Correlation matrices are implemented for 2 x 2 only"); } /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + chan_desc->R_sqrt = (struct complexd**) malloc(6*sizeof(struct complexd**)); for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -666,6 +992,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -678,33 +1005,34 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; - for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + + for (i = 0; i<6; i++) { + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); @@ -720,6 +1048,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -732,33 +1061,34 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; + for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); @@ -774,6 +1104,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; + for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -786,27 +1117,28 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex *)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd *)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6; + for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); @@ -867,11 +1199,11 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, 1); break; - case Rayleigh1: + case Rayleigh1://MIMO Test uses Rayleigh1 nb_taps = 1; Td = 0; channel_length = 1; - ricean_factor = 1; + ricean_factor = 0.0; aoa = .03; maxDoppler = 0; fill_channel_desc(chan_desc,nb_tx, @@ -1042,11 +1374,13 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, case TS_SHIFT: nb_taps = 2; + double ts_shift_delays[] = {0, 1/7.68}; Td = ts_shift_delays[1]; channel_length = 10; ricean_factor = 0.0; aoa = 0.0; maxDoppler = 0; + double ts_shift_amps[] = {0, 1}; fill_channel_desc(chan_desc,nb_tx, nb_rx, nb_taps, @@ -1310,54 +1644,80 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->nb_paths = 10; return(chan_desc); -} - +} /* channel_desc_t *new_channel_desc_scm */ + +channel_desc_t *find_channel_desc_fromname( char *modelname ) { + for(int i=0; imodel_name,modelname) == 0) + return defined_channels[i]; + } + } + + LOG_E(OCM,"Model %s not found \n", modelname); + return NULL; +} /* channel_desc_t * new_channel_desc_fromconfig */ + + + void free_channel_desc_scm(channel_desc_t *ch) { // Must be made cleanly, a lot of leaks... - defined_channels[ch->chan_idx]=NULL; + if (max_chan != 0) defined_channels[ch->chan_idx]=NULL; if(ch->free_flags&CHANMODEL_FREE_AMPS) free(ch->amps); - for (int i = 0; inb_tx*ch->nb_rx; i++) { + + for (int i = 0; inb_tx*ch->nb_rx; i++) { free(ch->ch[i]); free(ch->chF[i]); } - + for (int i = 0; inb_taps; i++) { - free(ch->a[i]); - } + free(ch->a[i]); + } + if(ch->free_flags&CHANMODEL_FREE_DELAY) - free(ch->delays); + free(ch->delays); + if(ch->free_flags&CHANMODEL_FREE_RSQRT_6) - for (int i = 0; i<6; i++) - free(ch->R_sqrt[i]); + for (int i = 0; i<6; i++) + free(ch->R_sqrt[i]); + if(ch->free_flags&CHANMODEL_FREE_RSQRT_NTAPS) - for (int i = 0; inb_taps;i++) - free(ch->R_sqrt[i]); - free(ch->R_sqrt); - free(ch->ch); + for (int i = 0; inb_taps; i++) + free(ch->R_sqrt[i]); + + free(ch->R_sqrt); + free(ch->ch); free(ch->chF); - free(ch->a); - free(ch); + free(ch->a); + free(ch->model_name); + free(ch); } void set_channeldesc_owner(channel_desc_t *cdesc, uint32_t module_id) { - cdesc->module_id=module_id; + cdesc->module_id=module_id; +} + +void set_channeldesc_name(channel_desc_t *cdesc,char *modelname) { + if(cdesc->model_name != NULL) + free(cdesc->model_name); + + cdesc->model_name=strdup(modelname); } int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { double s; int i,k,l,aarx,aatx; - struct complex anew[NB_ANTENNAS_TX*NB_ANTENNAS_RX],acorr[NB_ANTENNAS_TX*NB_ANTENNAS_RX]; - struct complex phase, alpha, beta; - AssertFatal(desc->nb_tx<=NB_ANTENNAS_TX && desc->nb_rx <= NB_ANTENNAS_RX, - "random_channel.c: Error: temporary buffer for channel not big enough (%d,%d)\n",desc->nb_tx,desc->nb_rx); + struct complexd anew[desc->nb_tx*desc->nb_rx]; + struct complexd acorr[desc->nb_tx*desc->nb_rx]; + struct complexd phase, alpha, beta; start_meas(&desc->random_channel); for (i=0; i<(int)desc->nb_taps; i++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - anew[aarx+(aatx*desc->nb_rx)].x = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); - anew[aarx+(aatx*desc->nb_rx)].y = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); + anew[aarx+(aatx*desc->nb_rx)].r = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); + anew[aarx+(aatx*desc->nb_rx)].i = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); if ((i==0) && (desc->ricean_factor != 1.0)) { if (desc->random_aoa==1) { @@ -1367,14 +1727,14 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { // this assumes that both RX and TX have linear antenna arrays with lambda/2 antenna spacing. // Furhter it is assumed that the arrays are parallel to each other and that they are far enough apart so // that we can safely assume plane wave propagation. - phase.x = cos(M_PI*((aarx-aatx)*sin(desc->aoa))); - phase.y = sin(M_PI*((aarx-aatx)*sin(desc->aoa))); - anew[aarx+(aatx*desc->nb_rx)].x += phase.x * sqrt(1.0-desc->ricean_factor); - anew[aarx+(aatx*desc->nb_rx)].y += phase.y * sqrt(1.0-desc->ricean_factor); + phase.r = cos(M_PI*((aarx-aatx)*sin(desc->aoa))); + phase.i = sin(M_PI*((aarx-aatx)*sin(desc->aoa))); + anew[aarx+(aatx*desc->nb_rx)].r += phase.r * sqrt(1.0-desc->ricean_factor); + anew[aarx+(aatx*desc->nb_rx)].i += phase.i * sqrt(1.0-desc->ricean_factor); } #ifdef DEBUG_CH - printf("(%d,%d,%d) %f->(%f,%f) (%f,%f) phase (%f,%f)\n",aarx,aatx,i,desc->amps[i],anew[aarx+(aatx*desc->nb_rx)].x,anew[aarx+(aatx*desc->nb_rx)].y,desc->aoa,desc->ricean_factor,phase.x,phase.y); + printf("(%d,%d,%d) %f->(%f,%f) (%f,%f) phase (%f,%f)\n",aarx,aatx,i,desc->amps[i],anew[aarx+(aatx*desc->nb_rx)].r,anew[aarx+(aatx*desc->nb_rx)].i,desc->aoa,desc->ricean_factor,phase.r,phase.i); #endif } //aatx } //aarx @@ -1391,13 +1751,19 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { */ //apply correlation matrix //compute acorr = R_sqrt[i] * anew - alpha.x = 1.0; - alpha.y = 0.0; - beta.x = 0.0; - beta.y = 0.0; + bzero(acorr,desc->nb_tx*desc->nb_rx*sizeof(struct complexd)); + cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) desc->R_sqrt[i/3], (void *) anew, 1, (void *) acorr, 1); + + /* + FIXME: Function cblas_zgemv has an undefined output (for the same input) after a second call in RHEL8 (acorr = nan) + alpha.r = 1.0; + alpha.i = 0.0; + beta.r = 0.0; + beta.i = 0.0; cblas_zgemv(CblasRowMajor, CblasNoTrans, desc->nb_tx*desc->nb_rx, desc->nb_tx*desc->nb_rx, (void *) &alpha, (void *) desc->R_sqrt[i/3], desc->nb_rx*desc->nb_tx, (void *) anew, 1, (void *) &beta, (void *) acorr, 1); + */ /* for (aarx=0;aarxnb_rx;aarx++) { @@ -1415,10 +1781,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { // a = alpha*acorr+beta*a // a = beta*a // a = a+alpha*acorr - alpha.x = sqrt(1-desc->forgetting_factor); - alpha.y = 0; - beta.x = sqrt(desc->forgetting_factor); - beta.y = 0; + alpha.r = sqrt(1-desc->forgetting_factor); + alpha.i = 0; + beta.r = sqrt(desc->forgetting_factor); + beta.i = 0; cblas_zscal(desc->nb_tx*desc->nb_rx, (void *) &beta, (void *) desc->a[i], 1); cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) &alpha, (void *) acorr, 1, (void *) desc->a[i], 1); // desc->a[i][aarx+(aatx*desc->nb_rx)].x = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].x) + sqrt(1-desc->forgetting_factor)*anew.x; @@ -1438,7 +1804,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { stop_meas(&desc->random_channel); - //memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complex)); + //memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complexd)); if (abstraction_flag==0) { start_meas(&desc->interp_time); @@ -1446,12 +1812,12 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { if (desc->channel_length == 1) { - desc->ch[aarx+(aatx*desc->nb_rx)][0].x = desc->a[0][aarx+(aatx*desc->nb_rx)].x; - desc->ch[aarx+(aatx*desc->nb_rx)][0].y = desc->a[0][aarx+(aatx*desc->nb_rx)].y; + desc->ch[aarx+(aatx*desc->nb_rx)][0].r = desc->a[0][aarx+(aatx*desc->nb_rx)].r; + desc->ch[aarx+(aatx*desc->nb_rx)][0].i = desc->a[0][aarx+(aatx*desc->nb_rx)].i; } else { for (k=0; k<(int)desc->channel_length; k++) { - desc->ch[aarx+(aatx*desc->nb_rx)][k].x = 0.0; - desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0; + desc->ch[aarx+(aatx*desc->nb_rx)][k].r = 0.0; + desc->ch[aarx+(aatx*desc->nb_rx)][k].i = 0.0; for (l=0; lnb_taps; l++) { if ((k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset) == 0) @@ -1460,17 +1826,16 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { s = sin(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset))/ (M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset)); - desc->ch[aarx+(aatx*desc->nb_rx)][k].x += s*desc->a[l][aarx+(aatx*desc->nb_rx)].x; - desc->ch[aarx+(aatx*desc->nb_rx)][k].y += s*desc->a[l][aarx+(aatx*desc->nb_rx)].y; - // printf("l %d : desc->ch.x %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x); + desc->ch[aarx+(aatx*desc->nb_rx)][k].r += s*desc->a[l][aarx+(aatx*desc->nb_rx)].r; + desc->ch[aarx+(aatx*desc->nb_rx)][k].i += s*desc->a[l][aarx+(aatx*desc->nb_rx)].i; + // printf("l %d : desc->ch.x %f, s %e, delay %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x,s,desc->delays[l]); } //nb_taps #ifdef DEBUG_CH - k=0; - printf("(%d,%d,%d)->(%f,%f)\n",k,aarx,aatx,desc->ch[aarx+(aatx*desc->nb_rx)][k].x,desc->ch[aarx+(aatx*desc->nb_rx)][k].y); + printf("(%d,%d,%d)->(%e,%e)\n",k,aarx,aatx,desc->ch[aarx+(aatx*desc->nb_rx)][k].r,desc->ch[aarx+(aatx*desc->nb_rx)][k].i); #endif - } - } //channel_length + } //channel_length + } } //aatx } //aarx @@ -1482,7 +1847,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { return (0); } - + double N_RB2sampling_rate(uint16_t N_RB) { double sampling_rate; @@ -1531,128 +1896,143 @@ double N_RB2channel_bandwidth(uint16_t N_RB) { break; default: - LOG_E(PHY,"Unknown N_PRB\n"); + LOG_E(OCM,"Unknown N_PRB\n"); return(-1); } - return(channel_bandwidth); -} - + return(channel_bandwidth); +} + + static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt ) { - prnt("channelmod commands can be used to display or modify channel models parameters\n"); - prnt("channelmod show predef: display predefined model algorithms available in oai\n"); - prnt("channelmod show current: display the currently used models in the running executable\n"); - prnt("channelmod modify : set the specified parameters in a current model to the given value\n"); - prnt(" specifies the model, the show current model command can be used to list the current models indexes\n"); - prnt(" can be one of \"riceanf\", \"aoa\", \"randaoa\", \"ploss\", \"offset\", \"forgetf\"\n"); - return CMDSTATUS_FOUND; + prnt("channelmod commands can be used to display or modify channel models parameters\n"); + prnt("channelmod show predef: display predefined model algorithms available in oai\n"); + prnt("channelmod show current: display the currently used models in the running executable\n"); + prnt("channelmod modify : set the specified parameters in a current model to the given value\n"); + prnt(" specifies the model, the show current model command can be used to list the current models indexes\n"); + prnt(" can be one of \"riceanf\", \"aoa\", \"randaoa\", \"ploss\", \"noise_power_dB\", \"offset\", \"forgetf\"\n"); + return CMDSTATUS_FOUND; } static void display_channelmodel(channel_desc_t *cd,int debug, telnet_printfunc_t prnt) { - char *module_id_str[]=MODULEID_STR_INIT; - if (cd->module_id != 0) { - prnt("model owner: %s\n",module_id_str[cd->module_id]); - } - prnt("nb_tx: %i nb_rx: %i taps: %i bandwidth: %lf sampling: %lf\n",cd->nb_tx, cd->nb_rx, cd->nb_taps, cd->channel_bandwidth, cd->sampling_rate); - prnt("channel length: %i Max path delay: %lf ricean fact.: %lf angle of arrival: %lf (randomized:%s)\n", - cd->channel_length, cd->Td, cd->ricean_factor, cd->aoa, (cd->random_aoa?"Yes":"No")); - prnt("max Doppler: %lf path loss: %lf rchannel offset: %i forget factor; %lf\n", - cd->max_Doppler, cd->path_loss_dB, cd->channel_offset, cd->forgetting_factor); - prnt("Initial phase: %lf nb_path: %i \n", - cd->ip, cd->nb_paths); - for (int i=0; inb_taps ; i++) { - prnt("taps: %i lin. ampli. : %lf delay: %lf \n",i,cd->amps[i], cd->delays[i]); - } + char *module_id_str[]=MODULEID_STR_INIT; + prnt("model owner: %s\n",(cd->module_id != 0)?module_id_str[cd->module_id]:"not set"); + prnt("nb_tx: %i nb_rx: %i taps: %i bandwidth: %lf sampling: %lf\n",cd->nb_tx, cd->nb_rx, cd->nb_taps, cd->channel_bandwidth, cd->sampling_rate); + prnt("channel length: %i Max path delay: %lf ricean fact.: %lf angle of arrival: %lf (randomized:%s)\n", + cd->channel_length, cd->Td, cd->ricean_factor, cd->aoa, (cd->random_aoa?"Yes":"No")); + prnt("max Doppler: %lf path loss: %lf noise: %lf rchannel offset: %i forget factor; %lf\n", + cd->max_Doppler, cd->path_loss_dB, cd->noise_power_dB, cd->channel_offset, cd->forgetting_factor); + prnt("Initial phase: %lf nb_path: %i \n", + cd->ip, cd->nb_paths); + + for (int i=0; inb_taps ; i++) { + prnt("taps: %i lin. ampli. : %lf delay: %lf \n",i,cd->amps[i], cd->delays[i]); + } } - - + + static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) { - char *subcmd=NULL; + char *subcmd=NULL; int s = sscanf(buff,"%ms\n",&subcmd); if (s>0) { if ( strcmp(subcmd,"predef") == 0) { for (int i=0; channelmod_names[i].name != NULL ; i++) { prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i )); - } + } } else if ( strcmp(subcmd,"current") == 0) { for (int i=0; i < max_chan ; i++) { - if (defined_channels[i] != NULL) { - prnt("model %i %s: \n----------------\n", i, map_int_to_str(channelmod_names,defined_channels[i]->modelid)); - display_channelmodel(defined_channels[i],debug,prnt); + if (defined_channels[i] != NULL) { + prnt("model %i %s type %s: \n----------------\n", i, (defined_channels[i]->model_name !=NULL)?defined_channels[i]->model_name:"(no name set)", + map_int_to_str(channelmod_names,defined_channels[i]->modelid)); + display_channelmodel(defined_channels[i],debug,prnt); } } } else { - channelmod_print_help(buff, debug, prnt); + channelmod_print_help(buff, debug, prnt); } - free(subcmd); + + free(subcmd); } + return CMDSTATUS_FOUND; } - + static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt) { - char *param=NULL, *value=NULL; + char *param=NULL, *value=NULL; int cd_id= -1; int s = sscanf(buff,"%i %ms %ms \n",&cd_id,¶m, &value); + if (cd_id<0 || cd_id >= max_chan) { - prnt("ERROR, %i: Channel model id outof range (0-%i)\n",cd_id,max_chan-1); - return CMDSTATUS_FOUND; + prnt("ERROR, %i: Channel model id outof range (0-%i)\n",cd_id,max_chan-1); + return CMDSTATUS_FOUND; } + if (defined_channels[cd_id]==NULL) { - prnt("ERROR, %i: Channel model has not been set\n",cd_id); - return CMDSTATUS_FOUND; - } - + prnt("ERROR, %i: Channel model has not been set\n",cd_id); + return CMDSTATUS_FOUND; + } + if (s==3) { if ( strcmp(param,"riceanf") == 0) { - double dbl = atof(value); - if (dbl <0 || dbl > 1) - prnt("ERROR: ricean factor range: 0 to 1, %lf is outof range\n",dbl); - else - defined_channels[cd_id]->ricean_factor=dbl; + double dbl = atof(value); + + if (dbl <0 || dbl > 1) + prnt("ERROR: ricean factor range: 0 to 1, %lf is outof range\n",dbl); + else + defined_channels[cd_id]->ricean_factor=dbl; } else if ( strcmp(param,"aoa") == 0) { - double dbl = atof(value); - if (dbl <0 || dbl >6.28) - prnt("ERROR: angle of arrival range: 0 to 2*Pi, %lf is outof range\n",dbl); - else - defined_channels[cd_id]->aoa=dbl; + double dbl = atof(value); + + if (dbl <0 || dbl >6.28) + prnt("ERROR: angle of arrival range: 0 to 2*Pi, %lf is outof range\n",dbl); + else + defined_channels[cd_id]->aoa=dbl; } else if ( strcmp(param,"randaoa") == 0) { - int i = atoi(value); - if (i!=0 && i!=1) - prnt("ERROR: randaoa is a boolean, must be 0 or 1\n"); - else - defined_channels[cd_id]->random_aoa=i; + int i = atoi(value); + + if (i!=0 && i!=1) + prnt("ERROR: randaoa is a boolean, must be 0 or 1\n"); + else + defined_channels[cd_id]->random_aoa=i; } else if ( strcmp(param,"ploss") == 0) { - double dbl = atof(value); - defined_channels[cd_id]->path_loss_dB=dbl; + double dbl = atof(value); + defined_channels[cd_id]->path_loss_dB=dbl; + } else if ( strcmp(param,"noise_power_dB") == 0) { + double dbl = atof(value); + defined_channels[cd_id]->noise_power_dB=dbl; } else if ( strcmp(param,"offset") == 0) { - int i = atoi(value); - defined_channels[cd_id]->channel_offset=i; + int i = atoi(value); + defined_channels[cd_id]->channel_offset=i; } else if ( strcmp(param,"forgetf") == 0) { - double dbl = atof(value); - if (dbl <0 || dbl > 1) - prnt("ERROR: forgetting factor range: 0 to 1 (disable variation), %lf is outof range\n",dbl); - else - defined_channels[cd_id]->forgetting_factor=dbl; + double dbl = atof(value); + + if (dbl <0 || dbl > 1) + prnt("ERROR: forgetting factor range: 0 to 1 (disable variation), %lf is outof range\n",dbl); + else + defined_channels[cd_id]->forgetting_factor=dbl; } else { - prnt("ERROR: %s, unknown channel parameter\n",param); - return CMDSTATUS_FOUND; + prnt("ERROR: %s, unknown channel parameter\n",param); + return CMDSTATUS_FOUND; } - display_channelmodel(defined_channels[cd_id],debug,prnt); - free(param); - free(value); - random_channel(defined_channels[cd_id],false); + display_channelmodel(defined_channels[cd_id],debug,prnt); + free(param); + free(value); + random_channel(defined_channels[cd_id],false); } - return CMDSTATUS_FOUND; + + return CMDSTATUS_FOUND; } - -int modelid_fromname(char *modelname) { - int modelid=map_str_to_int(channelmod_names,modelname); - if (modelid < 0) - LOG_E(OCM,"random_channel.c: Error channel model %s unknown\n",modelname); + +int modelid_fromstrtype(char *modeltype) { + int modelid=map_str_to_int(channelmod_names,modeltype); + + if (modelid < 0) + LOG_E(OCM,"random_channel.c: Error channel model %s unknown\n",modeltype); + return modelid; } @@ -1666,25 +2046,68 @@ double channelmod_get_sinr_dB(void) { void init_channelmod(void) { paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC; - int ret = config_get( channelmod_params,sizeof(channelmod_params)/sizeof(paramdef_t),CHANNELMOD_SECTION); + int numparams=sizeof(channelmod_params)/sizeof(paramdef_t); + int ret = config_get( channelmod_params,numparams,CHANNELMOD_SECTION); AssertFatal(ret >= 0, "configuration couldn't be performed"); - defined_channels=calloc(max_chan,sizeof( channel_desc_t*)); + defined_channels=calloc(max_chan,sizeof( channel_desc_t *)); AssertFatal(defined_channels!=NULL, "couldn't allocate %u channel descriptors\n",max_chan); - /* look for telnet server, if it is loaded, add the channel modeling commands to it */ add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); if (addcmd != NULL) { addcmd("channelmod",channelmod_vardef,channelmod_cmdarray); } -} +} /* init_channelmod */ + + +int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, double channel_bandwidth) { + paramdef_t achannel_params[] = CHANNELMOD_MODEL_PARAMS_DESC; + paramlist_def_t channel_list; + memset(&channel_list,0,sizeof(paramlist_def_t)); + memcpy(channel_list.listname,modellist_name,sizeof(channel_list.listname)-1); + int numparams = sizeof(achannel_params)/sizeof(paramdef_t); + config_getlist( &channel_list,achannel_params,numparams, CHANNELMOD_SECTION); + AssertFatal(channel_list.numelt>0, "List %s.%s not found in config file\n",CHANNELMOD_SECTION,channel_list.listname); + int pindex_NAME = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_NAME_PNAME); + int pindex_DT = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_DT_PNAME ); + int pindex_FF = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_FF_PNAME ); + int pindex_CO = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_CO_PNAME ); + int pindex_PL = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_PL_PNAME ); + int pindex_NP = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_NP_PNAME ); + int pindex_TYPE = config_paramidx_fromname(achannel_params,numparams, CHANNELMOD_MODEL_TYPE_PNAME); + + for (int i=0; imodel_name = strdup(*(channel_list.paramarray[i][pindex_NAME].strptr)); + LOG_I(OCM,"Model %s type %s allocated from config file, list %s\n",*(channel_list.paramarray[i][pindex_NAME].strptr), + *(channel_list.paramarray[i][pindex_TYPE].strptr), modellist_name); + } /* for loop on channel_list */ + + return channel_list.numelt; +} /* load_channelist */ #ifdef RANDOM_CHANNEL_MAIN #define sampling_rate 5.0 #define Td 2.0 main(int argc,char **argv) { double amps[8] = {.8,.2,.1,.04,.02,.01,.005}; - struct complex ch[(int)(1+2*sampling_rate*Td)],phase; + struct complexd ch[(int)(1+2*sampling_rate*Td)],phase; int i; randominit(); phase.x = 1.0; diff --git a/openair1/SIMULATION/TOOLS/scm_corrmat.h b/openair1/SIMULATION/TOOLS/scm_corrmat.h index 6ee6567ce9..5695e0bd0f 100644 --- a/openair1/SIMULATION/TOOLS/scm_corrmat.h +++ b/openair1/SIMULATION/TOOLS/scm_corrmat.h @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -double R22_sqrt[6][32] = { +static double R22_sqrt[6][32] = { {0.921700, -0.000000, 0.010380, -0.027448, -0.250153, 0.294754, 0.005961, 0.010769, 0.010380, 0.027448, 0.921700, 0.000000, -0.011595, -0.004130, -0.250153, 0.294754, -0.250153, -0.294754, -0.011595, 0.004130, 0.921700, 0.000000, 0.010380, -0.027448, 0.005961, -0.010769, -0.250153, -0.294754, 0.010380, 0.027448, 0.921700, 0.000000}, {0.923810, 0.000000, 0.004069, 0.027832, 0.151730, 0.350180, -0.009882, 0.006114, 0.004069, -0.027832, 0.923810, 0.000000, 0.011218, -0.003029, 0.151730, 0.350180, 0.151730, -0.350180, 0.011218, 0.003029, 0.923810, -0.000000, 0.004069, 0.027832, -0.009882, -0.006114, 0.151730, -0.350180, 0.004069, -0.027832, 0.923810, 0.000000}, {0.927613, 0.000000, 0.014253, 0.025767, -0.061171, -0.367133, 0.009258, -0.007340, 0.014253, -0.025767, 0.927613, -0.000000, -0.011138, -0.003942, -0.061171, -0.367133, -0.061171, 0.367133, -0.011138, 0.003942, 0.927613, 0.000000, 0.014253, 0.025767, 0.009258, 0.007340, -0.061171, 0.367133, 0.014253, -0.025767, 0.927613, 0.000000}, @@ -27,7 +27,7 @@ double R22_sqrt[6][32] = { {0.919726, -0.000000, 0.038700, -0.111146, 0.217804, 0.300925, 0.045531, -0.013659, 0.038700, 0.111146, 0.919726, 0.000000, -0.027201, 0.038983, 0.217804, 0.300925, 0.217804, -0.300925, -0.027201, -0.038983, 0.919726, 0.000000, 0.038700, -0.111146, 0.045531, 0.013659, 0.217804, -0.300925, 0.038700, 0.111146, 0.919726, 0.000000}, {0.867608, -0.000000, 0.194097, -0.112414, -0.418811, 0.095938, -0.081264, 0.075727, 0.194097, 0.112414, 0.867608, -0.000000, -0.106125, -0.032801, -0.418811, 0.095938, -0.418811, -0.095938, -0.106125, 0.032801, 0.867608, 0.000000, 0.194097, -0.112414, -0.081264, -0.075727, -0.418811, -0.095938, 0.194097, 0.112414, 0.867608, 0.000000}, }; -double R21_sqrt[6][8] = { +static double R21_sqrt[6][8] = { {0.922167, 0.000000,-0.250280, 0.294903,-0.250280, -0.294903,0.922167, 0.000000}, {0.924238, 0.000000,0.151801, 0.350342,0.151801, -0.350342,0.924238, 0.000000}, {0.928080, 0.000000,-0.061202, -0.367318,-0.061202, 0.367318,0.928080, 0.000000}, @@ -35,7 +35,7 @@ double R21_sqrt[6][8] = { {0.927225, 0.000000,0.219580, 0.303378,0.219580, -0.303378,0.927225, 0.000000}, {0.896133, 0.000000,-0.432581, 0.099092,-0.432581, -0.099092,0.896133, 0.000000}, }; -double R12_sqrt[6][8] = { +static double R12_sqrt[6][8] = { {0.999494, 0.000000,0.011256, -0.029765,0.011256, 0.029765,0.999494, 0.000000}, {0.999537, 0.000000,0.004402, 0.030114,0.004402, -0.030114,0.999537, 0.000000}, {0.999497, 0.000000,0.015358, 0.027764,0.015358, -0.027764,0.999497, 0.000000}, diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index cc06e2f85c..ce470fe0b0 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -64,11 +64,11 @@ typedef struct { ///length of impulse response. should be set to 11+2*bw*t_max uint8_t channel_length; ///channel state vector. size(state) = nb_taps * (n_tx * n_rx); - struct complex **a; + struct complexd **a; ///interpolated (sample-spaced) channel impulse response. size(ch) = (n_tx * n_rx) * channel_length. ATTENTION: the dimensions of ch are the transposed ones of a. This is to allow the use of BLAS when applying the correlation matrices to the state. - struct complex **ch; + struct complexd **ch; ///Sampled frequency response (90 kHz resolution) - struct complex **chF; + struct complexd **chF; ///Maximum path delay in mus. double Td; ///Channel bandwidth in MHz. @@ -84,11 +84,12 @@ typedef struct { ///in Hz. if >0 generate a channel with a Clarke's Doppler profile with a maximum Doppler bandwidth max_Doppler. CURRENTLY NOT IMPLEMENTED! double max_Doppler; ///Square root of the full correlation matrix size(R_tx) = nb_taps * (n_tx * n_rx) * (n_tx * n_rx). - struct complex **R_sqrt; + struct complexd **R_sqrt; ///path loss including shadow fading in dB double path_loss_dB; ///additional delay of channel in samples. int32_t channel_offset; + float noise_power_dB; ///This parameter (0...1) allows for simple 1st order temporal variation. 0 means a new channel every call, 1 means keep channel constant all the time double forgetting_factor; ///needs to be set to 1 for the first call, 0 otherwise. @@ -106,8 +107,10 @@ typedef struct { unsigned int chan_idx; /// id of the channel modeling algorithm int modelid; - /// identifies channel descriptor owner (the module which created this descriptor) + /// identifies channel descriptor owner (the module which created this descriptor channelmod_moduleid_t module_id; + /// name of this descriptor,used for model created from config file at init time + char *model_name; /// flags to properly trigger memory free unsigned int free_flags; } channel_desc_t; @@ -178,6 +181,11 @@ typedef enum { EVA, ETU, MBSFN, + TDL_A, + TDL_B, + TDL_C, + TDL_D, + TDL_E, Rayleigh8, Rayleigh1, Rayleigh1_800, @@ -208,6 +216,11 @@ typedef enum { {"EVA",EVA},\ {"ETU",ETU},\ {"MBSFN",MBSFN},\ + {"TDL_A",TDL_A},\ + {"TDL_B",TDL_B},\ + {"TDL_C",TDL_C},\ + {"TDL_D",TDL_D},\ + {"TDL_E",TDL_E},\ {"Rayleigh8",Rayleigh8},\ {"Rayleigh1",Rayleigh1},\ {"Rayleigh1_800",Rayleigh1_800},\ @@ -231,12 +244,37 @@ typedef enum { #define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n" #define CHANNELMOD_SECTION "channelmod" + +/* global channel modelization parameters */ +#define CHANNELMOD_MODELLIST_PARANAME "modellist" + +#define CHANNELMOD_HELP_MODELLIST " channel list name in config file describing the model type and its parameters\n" #define CHANNELMOD_PARAMS_DESC { \ - {"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\ - {"sinr_dB", NULL, 0 , dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\ - {"max_chan, CONFIG_HLP_MAX_CHAN", 0, uptr:&max_chan, defintval:10, TYPE_UINT, 0},\ + {"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\ + {"sinr_dB", NULL, 0, dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\ + {"max_chan", "Max number of runtime models", 0, uptr:&max_chan, defintval:10, TYPE_UINT, 0},\ + {CHANNELMOD_MODELLIST_PARANAME, CHANNELMOD_HELP_MODELLIST, 0, strptr:(char **)&modellist_name, defstrval:"DefaultChannelList", TYPE_STRING, 60 },\ } +/* parameters for one model */ +#define CHANNELMOD_MODEL_NAME_PNAME "model_name" +#define CHANNELMOD_MODEL_TYPE_PNAME "type" +#define CHANNELMOD_MODEL_PL_PNAME "ploss_dB" +#define CHANNELMOD_MODEL_NP_PNAME "noise_power_dB" +#define CHANNELMOD_MODEL_FF_PNAME "forgetfact" +#define CHANNELMOD_MODEL_CO_PNAME "offset" +#define CHANNELMOD_MODEL_DT_PNAME "ds_tdl" + +#define CHANNELMOD_MODEL_PARAMS_DESC { \ + {CHANNELMOD_MODEL_NAME_PNAME, "name of the model\n", 0, strptr:NULL , defstrval:"", TYPE_STRING, 0 },\ + {CHANNELMOD_MODEL_TYPE_PNAME, "name of the model type\n", 0, strptr:NULL , defstrval:"AWGN", TYPE_STRING, 0 },\ + {CHANNELMOD_MODEL_PL_PNAME, "channel path loss in dB\n", 0, dblptr:NULL, defdblval:0, TYPE_DOUBLE, 0 },\ + {CHANNELMOD_MODEL_NP_PNAME, "channel noise in dB\n", 0, dblptr:NULL, defdblval:-50, TYPE_DOUBLE, 0 },\ + {CHANNELMOD_MODEL_FF_PNAME, "channel forget factor ((0 to 1)\n", 0, dblptr:NULL, defdblval:0, TYPE_DOUBLE, 0 },\ + {CHANNELMOD_MODEL_CO_PNAME, "channel offset in samps\n", 0, iptr:NULL, defintval:0, TYPE_INT, 0 },\ + {CHANNELMOD_MODEL_DT_PNAME, "delay spread for TDL models\n", 0, dblptr:NULL, defdblval:0, TYPE_DOUBLE, 0 }\ +} + #include "platform_constants.h" typedef struct { @@ -262,36 +300,20 @@ typedef struct { } sim_t; -/** -\brief This routine initializes a new channel descriptor -\param nb_tx Number of TX antennas -\param nb_rx Number of RX antennas -\param nb_taps Number of taps -\param channel_length Length of the interpolated channel impulse response -\param amps Linear amplitudes of the taps (length(amps)=channel_length). The values should sum up to 1. -\param delays Delays of the taps. If delays==NULL the taps are assumed to be spaced equidistantly between 0 and t_max. -\param R_sqrt Channel correlation matrix. If R_sqrt==NULL, no channel correlation is applied. -\param Td Maximum path delay in mus. -\param BW Channel bandwidth in MHz. -\param ricean_factor Ricean factor applied to all taps. -\param aoa Anlge of arrival -\param forgetting_factor This parameter (0...1) allows for simple 1st order temporal variation -\param max_Doppler This is the maximum Doppler frequency for Jakes' Model -\param channel_offset This is a time delay to apply to channel -\param path_loss_dB This is the path loss in dB -\param random_aoa If set to 1, AoA of ricean component is randomized -*/ - -//channel_desc_t *new_channel_desc(uint8_t nb_tx,uint8_t nb_rx, uint8_t nb_taps, uint8_t channel_length, double *amps, double* delays, struct complex** R_sqrt, double Td, double BW, double ricean_factor, double aoa, double forgetting_factor, double max_Doppler, int32_t channel_offset, double path_loss_dB,uint8_t random_aoa); - channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, uint8_t nb_rx, SCM_t channel_model, double sampling_rate, double channel_bandwidth, + double TDL_DS, double forgetting_factor, int32_t channel_offset, - double path_loss_dB); + double path_loss_dB, + float noise_power_dB); + +channel_desc_t *find_channel_desc_fromname( char *modelname ); + + /** \brief free memory allocated for a model descriptor \param ch points to the model, which cannot be used after calling this fuction @@ -304,6 +326,12 @@ void free_channel_desc_scm(channel_desc_t *ch); \param module_id identifies the channel model. should be define as a macro in simu.h */ void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id); +/** +\brief This function set a model name to a model descriptor, can be later used to identify a allocated channel model +\param cdesc points to the model descriptor +\param module_name is the C string to use as model name for the channel pointed by cdesc +*/ +void set_channeldesc_name(channel_desc_t *cdesc,char *modelname); /** \fn void random_channel(channel_desc_t *desc) \brief This routine generates a random channel response (time domain) according to a tapped delay line model. \param desc Pointer to the channel descriptor @@ -311,12 +339,13 @@ void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_i int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); /**\fn void multipath_channel(channel_desc_t *desc, - double tx_sig_re[2], - double tx_sig_im[2], - double rx_sig_re[2], - double rx_sig_im[2], + double tx_sig_re[NB_ANTENNAS_TX], + double tx_sig_im[NB_ANTENANS_TX], + double rx_sig_re[NB_ANTENNAS_RX], + double rx_sig_im[NB_ANTENNAS_RX], uint32_t length, - uint8_t keep_channel) + uint8_t keep_channel, + int log_channel) \brief This function generates and applys a random frequency selective random channel model. @param desc Pointer to channel descriptor @@ -326,15 +355,17 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); @param rx_sig_im output signal (imaginary component) @param length Length of input signal @param keep_channel Set to 1 to keep channel constant for null-B/F +@param log_channel=1 make channel coefficients come out for first sample of input */ void multipath_channel(channel_desc_t *desc, - double *tx_sig_re[2], - double *tx_sig_im[2], - double *rx_sig_re[2], - double *rx_sig_im[2], + double *tx_sig_re[NB_ANTENNAS_TX], + double *tx_sig_im[NB_ANTENNAS_TX], + double *rx_sig_re[NB_ANTENNAS_RX], + double *rx_sig_im[NB_ANTENNAS_RX], uint32_t length, - uint8_t keep_channel); + uint8_t keep_channel, + int log_channel); /* \fn double compute_pbch_sinr(channel_desc_t *desc, channel_desc_t *desc_i1, @@ -446,8 +477,8 @@ int gauss(unsigned int *gauss_LUT,unsigned char Nbits); double gaussdouble(double,double); void randominit(unsigned int seed_init); double uniformrandom(void); -int freq_channel(channel_desc_t *desc,uint16_t nb_rb, int16_t n_samples); -int init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples); +int freq_channel(channel_desc_t *desc,uint16_t nb_rb, int16_t n_samples,int scs); +int init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples,int scs); uint8_t multipath_channel_nosigconv(channel_desc_t *desc); void multipath_tv_channel(channel_desc_t *desc, double **tx_sig_re, @@ -460,15 +491,25 @@ void multipath_tv_channel(channel_desc_t *desc, /**@} */ /**@} */ -int modelid_fromname(char *modelname); +int modelid_fromstrtype(char *modeltype); double channelmod_get_snr_dB(void); double channelmod_get_sinr_dB(void); void init_channelmod(void) ; - +int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, double channel_bandwidth) ; double N_RB2sampling_rate(uint16_t N_RB); double N_RB2channel_bandwidth(uint16_t N_RB); -#include "targets/RT/USER/rfsim.h" +/* Linear phase noise model */ +/*! + \brief This function produce phase noise and add to input signal + \param ts Sampling time + \param *Re *Im Real and Imag part of the signal +*/ +//look-up table for the sine (cosine) function +#define ResolSinCos 100 +void InitSinLUT( void ); +void phase_noise(double ts, int16_t * InRe, int16_t * InIm); + void do_DL_sig(sim_t *sim, uint16_t subframe, diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 9e341f9bcb..6b1c6d9495 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -24,10 +24,13 @@ MESSAGE_DEF(F1AP_CU_SCTP_REQ , MESSAGE_PRIORITY_MED, f1ap_cu_setup_req_t /* eNB_DU application layer -> F1AP messages or CU F1AP -> RRC*/ MESSAGE_DEF(F1AP_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_setup_req_t , f1ap_setup_req) +MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_acknowledge_t , f1ap_gnb_cu_configuration_update_acknowledge) +MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_failure_t , f1ap_gnb_cu_configuration_update_failure) /* F1AP -> eNB_DU or eNB_CU_RRC -> F1AP application layer messages */ MESSAGE_DEF(F1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, f1ap_setup_resp_t , f1ap_setup_resp) MESSAGE_DEF(F1AP_SETUP_FAILURE , MESSAGE_PRIORITY_MED, f1ap_setup_failure_t , f1ap_setup_failure) +MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_t , f1ap_gnb_cu_configuration_update) /* MAC -> F1AP messages */ MESSAGE_DEF(F1AP_INITIAL_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_initial_ul_rrc_message_t , f1ap_initial_ul_rrc_message) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index d83f9cb71d..c2fb4a9cf7 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -31,6 +31,9 @@ #define F1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_req #define F1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_resp +#define F1AP_GNB_CU_CONFIGURATION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update +#define F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_acknowledge +#define F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_failure #define F1AP_SETUP_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_failure #define F1AP_INITIAL_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_initial_ul_rrc_message @@ -55,6 +58,8 @@ // Note this should be 512 from maxval in 38.473 #define F1AP_MAX_NB_CELLS 2 +#define F1AP_MAX_NO_OF_TNL_ASSOCIATIONS 32 +#define F1AP_MAX_NO_UE_ID 1024 typedef struct f1ap_net_ip_address_s { unsigned ipv4:1; unsigned ipv6:1; @@ -98,7 +103,7 @@ typedef struct f1ap_setup_req_s { // Served Cell Information /* Tracking area code */ - uint16_t tac[F1AP_MAX_NB_CELLS]; + uint32_t tac[F1AP_MAX_NB_CELLS]; /* Mobile Country Codes * Mobile Network Codes @@ -174,6 +179,24 @@ typedef struct f1ap_setup_req_s { } f1ap_setup_req_t; +typedef struct served_cells_to_activate_s { + /// mcc of DU cells + uint16_t mcc; + /// mnc of DU cells + uint16_t mnc; + /// mnc digit length of DU cells + uint8_t mnc_digit_length; + // NR Global Cell Id + uint64_t nr_cellid; + /// NRPCI + uint16_t nrpci; + /// num SI messages per DU cell + uint8_t num_SI; + /// SI message containers (up to 21 messages per cell) + uint8_t *SI_container[21]; + int SI_container_length[21]; +} served_cells_to_activate_t; + typedef struct f1ap_setup_resp_s { /* Connexion id used between SCTP/F1AP */ uint16_t cnx_id; @@ -189,29 +212,62 @@ typedef struct f1ap_setup_resp_s { char *gNB_CU_name; /// number of DU cells to activate uint16_t num_cells_to_activate; //0< num_cells_to_activate <= 512; - /// mcc of DU cells - uint16_t mcc[F1AP_MAX_NB_CELLS]; - /// mnc of DU cells - uint16_t mnc[F1AP_MAX_NB_CELLS]; - /// mnc digit length of DU cells - uint8_t mnc_digit_length[F1AP_MAX_NB_CELLS]; - // NR Global Cell Id - uint64_t nr_cellid[F1AP_MAX_NB_CELLS]; - /// NRPCI - uint16_t nrpci[F1AP_MAX_NB_CELLS]; - /// num SI messages per DU cell - uint8_t num_SI[F1AP_MAX_NB_CELLS]; - /// SI message containers (up to 21 messages per cell) - uint8_t *SI_container[F1AP_MAX_NB_CELLS][21]; - int SI_container_length[F1AP_MAX_NB_CELLS][21]; + served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS]; } f1ap_setup_resp_t; +typedef struct f1ap_gnb_cu_configuration_update_s { + /* Connexion id used between SCTP/F1AP */ + uint16_t cnx_id; + + /* SCTP association id */ + int32_t assoc_id; + + /* Number of SCTP streams used for a mme association */ + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; + + /// string holding gNB_CU_name + char *gNB_CU_name; + /// number of DU cells to activate + uint16_t num_cells_to_activate; //0< num_cells_to_activate/mod <= 512; + served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS]; +} f1ap_gnb_cu_configuration_update_t; + typedef struct f1ap_setup_failure_s { uint16_t cause; uint16_t time_to_wait; uint16_t criticality_diagnostics; } f1ap_setup_failure_t; +typedef struct f1ap_gnb_cu_configuration_update_acknowledge_s { + uint16_t num_cells_failed_to_be_activated; + uint16_t mcc[F1AP_MAX_NB_CELLS]; + uint16_t mnc[F1AP_MAX_NB_CELLS]; + uint8_t mnc_digit_length[F1AP_MAX_NB_CELLS]; + uint64_t nr_cellid[F1AP_MAX_NB_CELLS]; + uint16_t cause[F1AP_MAX_NB_CELLS]; + int have_criticality; + uint16_t criticality_diagnostics; + uint16_t noofTNLAssociations_to_setup; + uint16_t have_port[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; + in_addr_t tl_address[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; // currently only IPv4 supported + uint16_t noofTNLAssociations_failed; + in_addr_t tl_address_failed[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; // currently only IPv4 supported + uint16_t cause_failed[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; + uint16_t noofDedicatedSIDeliveryNeededUEs; + uint32_t gNB_CU_ue_id[F1AP_MAX_NO_UE_ID]; + uint16_t ue_mcc[F1AP_MAX_NO_UE_ID]; + uint16_t ue_mnc[F1AP_MAX_NO_UE_ID]; + uint8_t ue_mnc_digit_length[F1AP_MAX_NO_UE_ID]; + uint64_t ue_nr_cellid[F1AP_MAX_NO_UE_ID]; +} f1ap_gnb_cu_configuration_update_acknowledge_t; + +typedef struct f1ap_gnb_cu_configuration_update_failure_s { + uint16_t cause; + uint16_t time_to_wait; + uint16_t criticality_diagnostics; +} f1ap_gnb_cu_configuration_update_failure_t; + typedef struct f1ap_dl_rrc_message_s { uint32_t gNB_CU_ue_id; @@ -243,7 +299,7 @@ typedef struct f1ap_initial_ul_rrc_message_s { uint16_t crnti; uint8_t *rrc_container; int rrc_container_length; - uint8_t *du2cu_rrc_container; + int8_t *du2cu_rrc_container; int du2cu_rrc_container_length; } f1ap_initial_ul_rrc_message_t; diff --git a/openair2/COMMON/gtpv1_u_messages_def.h b/openair2/COMMON/gtpv1_u_messages_def.h index 1948f1596a..e5ce496701 100644 --- a/openair2/COMMON/gtpv1_u_messages_def.h +++ b/openair2/COMMON/gtpv1_u_messages_def.h @@ -30,3 +30,8 @@ MESSAGE_DEF(GTPV1U_ENB_DATA_FORWARDING_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_dat MESSAGE_DEF(GTPV1U_ENB_END_MARKER_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_req_t, Gtpv1uEndMarkerReq) MESSAGE_DEF(GTPV1U_ENB_END_MARKER_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_ind_t, Gtpv1uEndMarkerInd) MESSAGE_DEF(GTPV1U_ENB_S1_REQ, MESSAGE_PRIORITY_MED, Gtpv1uS1Req, gtpv1uS1Req) + +MESSAGE_DEF(GTPV1U_GNB_DELETE_TUNNEL_REQ, MESSAGE_PRIORITY_MED, gtpv1u_gnb_delete_tunnel_req_t, NRGtpv1uDeleteTunnelReq) +MESSAGE_DEF(GTPV1U_GNB_DELETE_TUNNEL_RESP, MESSAGE_PRIORITY_MED, gtpv1u_gnb_delete_tunnel_resp_t, NRGtpv1uDeleteTunnelResp) +MESSAGE_DEF(GTPV1U_GNB_NG_REQ, MESSAGE_PRIORITY_MED, Gtpv1uNGReq, gtpv1uNGReq) +MESSAGE_DEF(GTPV1U_GNB_TUNNEL_DATA_REQ, MESSAGE_PRIORITY_MED, gtpv1u_gnb_tunnel_data_req_t, NRGtpv1uTunnelDataReq) diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 054f3f3734..3c82076510 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -26,6 +26,7 @@ #define GTPV1U_MAX_BEARERS_PER_UE max_val_LTE_DRB_Identity +#define NR_GTPV1U_MAX_BEARERS_PER_UE max_val_NR_DRB_Identity #define GTPV1U_ENB_UPDATE_TUNNEL_REQ(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uUpdateTunnelReq #define GTPV1U_ENB_UPDATE_TUNNEL_RESP(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uUpdateTunnelResp @@ -40,6 +41,11 @@ #define GTPV1U_ENB_S1_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uS1Req +#define GTPV1U_GNB_DELETE_TUNNEL_REQ(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uDeleteTunnelReq +#define GTPV1U_GNB_DELETE_TUNNEL_RESP(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uDeleteTunnelResp +#define GTPV1U_GNB_NG_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uNGReq +#define GTPV1U_GNB_TUNNEL_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uTunnelDataReq + #define GTPV1U_ALL_TUNNELS_TEID (teid_t)0xFFFFFFFF typedef struct gtpv1u_enb_create_x2u_tunnel_req_s { @@ -98,6 +104,7 @@ typedef struct gtpv1u_enb_delete_tunnel_req_s { uint8_t num_erab; ebi_t eps_bearer_id[GTPV1U_MAX_BEARERS_PER_UE]; //teid_t enb_S1u_teid; ///< local SGW S11 Tunnel Endpoint Identifier + int from_gnb; ///< Indicates if the message comes from gNB or eNB (1 = comes from gNB, 0 from eNB) } gtpv1u_enb_delete_tunnel_req_t; typedef struct gtpv1u_enb_delete_tunnel_resp_s { @@ -161,13 +168,60 @@ typedef struct gtpv1u_enb_end_marker_ind_s { uint32_t sdu_size; uint8_t *sdu_p; uint8_t mode; - uint16_t rnti; - uint8_t module_id; + uint16_t rnti; + uint8_t module_id; uint8_t eNB_index; } gtpv1u_enb_end_marker_ind_t; typedef struct { in_addr_t enb_ip_address_for_S1u_S12_S4_up; tcp_udp_port_t enb_port_for_S1u_S12_S4_up; + char addrStr[256]; + char portStr[256]; } Gtpv1uS1Req; + +typedef struct { + in_addr_t gnb_ip_address_for_NGu_up; + tcp_udp_port_t gnb_port_for_NGu_up; + char addrStr[256]; + char portStr[256]; +} Gtpv1uNGReq; +typedef struct gtpv1u_gnb_create_tunnel_req_s { + rnti_t rnti; + int num_tunnels; + teid_t upf_NGu_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier + pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + ebi_t incoming_rb_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + transport_layer_addr_t upf_addr[NR_GTPV1U_MAX_BEARERS_PER_UE]; +} gtpv1u_gnb_create_tunnel_req_t; + +typedef struct gtpv1u_gnb_create_tunnel_resp_s { + uint8_t status; ///< Status of S1U endpoint creation (Failed = 0xFF or Success = 0x0) + rnti_t rnti; + int num_tunnels; + teid_t gnb_NGu_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier + pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + transport_layer_addr_t gnb_addr; +} gtpv1u_gnb_create_tunnel_resp_t; + +typedef struct gtpv1u_gnb_delete_tunnel_req_s { + rnti_t rnti; + uint8_t num_pdusession; + pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; +} gtpv1u_gnb_delete_tunnel_req_t; + +typedef struct gtpv1u_gnb_delete_tunnel_resp_s { + rnti_t rnti; + uint8_t status; ///< Status of NGU endpoint deleteion (Failed = 0xFF or Success = 0x0) + teid_t gnb_NGu_teid; ///< local NGU Tunnel Endpoint Identifier to be deleted +} gtpv1u_gnb_delete_tunnel_resp_t; + +typedef struct gtpv1u_gnb_tunnel_data_req_s { + uint8_t *buffer; + uint32_t length; + uint32_t offset; ///< start of message offset in buffer + rnti_t rnti; + pdusessionid_t pdusession_id; +} gtpv1u_gnb_tunnel_data_req_t; + #endif /* GTPV1_U_MESSAGES_TYPES_H_ */ diff --git a/openair2/COMMON/itti_sim_messages_def.h b/openair2/COMMON/itti_sim_messages_def.h new file mode 100644 index 0000000000..681fc932dd --- /dev/null +++ b/openair2/COMMON/itti_sim_messages_def.h @@ -0,0 +1,36 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file itti_sim_messages_def.h + * \brief itti message for itti simulator + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + + + +MESSAGE_DEF(GNB_RRC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED, itti_sim_rrc_ch_t, GNBBCCHind) +MESSAGE_DEF(GNB_RRC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED, itti_sim_rrc_ch_t, GNBCCCHind) +MESSAGE_DEF(GNB_RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED, itti_sim_rrc_ch_t, GNBDCCHind) +MESSAGE_DEF(UE_RRC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED, itti_sim_rrc_ch_t, UECCCHind) +MESSAGE_DEF(UE_RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED, itti_sim_rrc_ch_t, UEDCCHind) diff --git a/openair2/COMMON/itti_sim_messages_types.h b/openair2/COMMON/itti_sim_messages_types.h new file mode 100644 index 0000000000..2e29e8f508 --- /dev/null +++ b/openair2/COMMON/itti_sim_messages_types.h @@ -0,0 +1,51 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file itti_sim_messages_types.h + * \brief itti message for itti simulator + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + +#ifndef ITTI_SIM_MESSAGES_TYPES_H_ +#define ITTI_SIM_MESSAGES_TYPES_H_ + +#include "LTE_asn_constant.h" + + + +#define GNB_RRC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.GNBBCCHind +#define GNB_RRC_CCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.GNBCCCHind +#define GNB_RRC_DCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.GNBDCCHind +#define UE_RRC_CCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.UECCCHind +#define UE_RRC_DCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.UEDCCHind + + + +typedef struct itti_sim_rrc_ch_s { + rb_id_t rbid; + uint8_t *sdu; + int size; +} itti_sim_rrc_ch_t; + +#endif /* ITTI_SIM_MESSAGES_TYPES_H_ */ diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h index 09b3f2aab4..eeef0d4494 100644 --- a/openair2/COMMON/mac_messages_def.h +++ b/openair2/COMMON/mac_messages_def.h @@ -41,10 +41,16 @@ MESSAGE_DEF(RRC_MAC_CCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacCcchDat MESSAGE_DEF(RRC_MAC_CCCH_DATA_CNF, MESSAGE_PRIORITY_MED_PLUS, RrcMacCcchDataCnf, rrc_mac_ccch_data_cnf) MESSAGE_DEF(RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacCcchDataInd, rrc_mac_ccch_data_ind) + MESSAGE_DEF(RRC_MAC_MCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacMcchDataReq, rrc_mac_mcch_data_req) MESSAGE_DEF(RRC_MAC_MCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcMacMcchDataInd, rrc_mac_mcch_data_ind) MESSAGE_DEF(RRC_MAC_PCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacPcchDataReq, rrc_mac_pcch_data_req) /* RRC configures DRX context (MAC timers) of a UE */ -MESSAGE_DEF(RRC_MAC_DRX_CONFIG_REQ, MESSAGE_PRIORITY_MED, rrc_mac_drx_config_req_t, rrc_mac_drx_config_req) \ No newline at end of file +MESSAGE_DEF(RRC_MAC_DRX_CONFIG_REQ, MESSAGE_PRIORITY_MED, rrc_mac_drx_config_req_t, rrc_mac_drx_config_req) + +// gNB +MESSAGE_DEF(NR_RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacCcchDataInd, nr_rrc_mac_ccch_data_ind) +MESSAGE_DEF(NR_RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacBcchDataInd, nr_rrc_mac_bcch_data_ind) + diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index e227296d05..a9336a58a9 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -30,6 +30,7 @@ #define MAC_MESSAGES_TYPES_H_ #include +#include "OCTET_STRING.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. @@ -38,6 +39,7 @@ #define RRC_MAC_BCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_req #define RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_ind +#define NR_RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_bcch_data_ind #define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req #define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind @@ -45,6 +47,7 @@ #define RRC_MAC_CCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_ccch_data_req #define RRC_MAC_CCCH_DATA_CNF(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_ccch_data_cnf #define RRC_MAC_CCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_ccch_data_ind +#define NR_RRC_MAC_CCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_ccch_data_ind #define RRC_MAC_MCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_mcch_data_req #define RRC_MAC_MCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_mcch_data_ind @@ -86,6 +89,15 @@ typedef struct RrcMacBcchDataInd_s { uint8_t rsrp; } RrcMacBcchDataInd; +typedef struct NRRrcMacBcchDataInd_s { + uint32_t frame; + uint8_t sub_frame; + uint32_t sdu_size; + uint8_t sdu[BCCH_SDU_SIZE]; + uint8_t gnb_index; + uint8_t rsrq; + uint8_t rsrp; +} NRRrcMacBcchDataInd; typedef struct RrcMacBcchMbmsDataReq_s { uint32_t frame; @@ -126,6 +138,17 @@ typedef struct RrcMacCcchDataInd_s { int CC_id; } RrcMacCcchDataInd; +typedef struct NRRrcMacCcchDataInd_s { + uint32_t frame; + uint8_t sub_frame; + uint16_t rnti; + uint32_t sdu_size; + uint8_t sdu[CCCH_SDU_SIZE]; + OCTET_STRING_t *du_to_cu_rrc_container; + uint8_t gnb_index; + int CC_id; +} NRRrcMacCcchDataInd; + typedef struct RrcMacMcchDataReq_s { uint32_t frame; uint32_t sdu_size; diff --git a/openair2/COMMON/mac_rrc_primitives.h b/openair2/COMMON/mac_rrc_primitives.h index 4a0a6027bc..d258bb872a 100644 --- a/openair2/COMMON/mac_rrc_primitives.h +++ b/openair2/COMMON/mac_rrc_primitives.h @@ -22,9 +22,7 @@ #ifndef __MAC_RRC_PRIMITIVES_H__ #define __MAC_RRC_PRIMITIVES_H__ -#ifndef OPENAIR2_IN - #include "LAYER2/RLC/rlc.h" -#endif +#include "LAYER2/RLC/rlc.h" #include "COMMON/platform_types.h" #include "COMMON/platform_constants.h" #include "openair2/RRC/LTE/rrc_defs.h" @@ -189,7 +187,7 @@ typedef struct MEAS_REQ_TABLE_ENTRY { MAC_MEAS_REQ Mac_meas_req; unsigned int Last_report_frame; unsigned int Next_check_frame; - uint8_t Status; + uint8_t StatusMeas; uint8_t Meas_req_status; uint8_t Rx_activity; //uint8_t Meas_Direction;//??? @@ -269,7 +267,7 @@ typedef struct { char Wideband_sinr; uint8_t Forg_fact; unsigned short Rep_interval; - uint8_t Status; + uint8_t StatusMeas; unsigned int Last_report_frame; unsigned int Next_check_frame; uint8_t Active; @@ -299,15 +297,13 @@ typedef struct { unsigned short Rep_interval; unsigned int Last_report_frame; unsigned int Next_check_frame; - uint8_t Status; //IDLE,NEED_rADIO_CONFIG, RADIO_CONFIG_TX, RADIO_CONFIG_ok + uint8_t StatusMeas; //IDLE,NEED_rADIO_CONFIG, RADIO_CONFIG_TX, RADIO_CONFIG_ok uint8_t Active; } __attribute__ ((__packed__)) DEFAULT_CH_MEAS; #define DEFAULT_eNB_MEAS_SIZE sizeof(DEFAULT_eNB_MEAS) -#ifndef OPENAIR2_IN - typedef struct { //RRC_INTERFACE_FUNCTIONS unsigned int Frame_index; unsigned short UE_index[NB_MODULES_MAX][NB_SIG_CNX_UE]; @@ -375,10 +371,6 @@ typedef struct { } MAC_RLC_XFACE; -#endif - - - //#define IDLE 0 #define NEED_RADIO_CONFIG 3 #define RADIO_CONFIG_TX 2 diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h new file mode 100644 index 0000000000..87d8a59fba --- /dev/null +++ b/openair2/COMMON/ngap_messages_def.h @@ -0,0 +1,90 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* + * ngap_messages_def.h + * + * Created on: 2020 + * Author: Yoshio INOUE, Masayuki HARADA + * Email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +/* Messages for NGAP logging */ +MESSAGE_DEF(NGAP_UPLINK_NAS_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_uplink_nas_log) +MESSAGE_DEF(NGAP_UE_CAPABILITY_IND_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_capability_ind_log) +MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_initial_context_setup_log) +MESSAGE_DEF(NGAP_NAS_NON_DELIVERY_IND_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_nas_non_delivery_ind_log) +MESSAGE_DEF(NGAP_DOWNLINK_NAS_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_downlink_nas_log) +MESSAGE_DEF(NGAP_S1_SETUP_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_s1_setup_log) +MESSAGE_DEF(NGAP_INITIAL_UE_MESSAGE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_initial_ue_message_log) +MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ_LOG, MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_context_release_req_log) +MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND_LOG, MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_context_release_command_log) +MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMPLETE_LOG, MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_context_release_complete_log) +MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_context_release_log) +MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_setup_request_log) +MESSAGE_DEF(NGAP_PDUSESSION_SETUP_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_setup_response_log) +MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_modify_request_log) +MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_modify_response_log) +MESSAGE_DEF(NGAP_PAGING_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_paging_log) +MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_release_request_log) +MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_pdusession_release_response_log) +MESSAGE_DEF(NGAP_ERROR_INDICATION_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_error_indication_log) +MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_path_switch_req_log) +MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_path_switch_req_ack_log) + +/* gNB application layer -> NGAP messages */ +MESSAGE_DEF(NGAP_REGISTER_GNB_REQ , MESSAGE_PRIORITY_MED, ngap_register_gnb_req_t , ngap_register_gnb_req) + +/* NGAP -> gNB application layer messages */ +MESSAGE_DEF(NGAP_REGISTER_GNB_CNF , MESSAGE_PRIORITY_MED, ngap_register_gnb_cnf_t , ngap_register_gnb_cnf) +MESSAGE_DEF(NGAP_DEREGISTERED_GNB_IND , MESSAGE_PRIORITY_MED, ngap_deregistered_gnb_ind_t , ngap_deregistered_gnb_ind) + +/* RRC -> NGAP messages */ +MESSAGE_DEF(NGAP_NAS_FIRST_REQ , MESSAGE_PRIORITY_MED, ngap_nas_first_req_t , ngap_nas_first_req) +MESSAGE_DEF(NGAP_UPLINK_NAS , MESSAGE_PRIORITY_MED, ngap_uplink_nas_t , ngap_uplink_nas) +MESSAGE_DEF(NGAP_UE_CAPABILITIES_IND , MESSAGE_PRIORITY_MED, ngap_ue_cap_info_ind_t , ngap_ue_cap_info_ind) +MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_resp_t, ngap_initial_context_setup_resp) +MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_FAIL, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_fail_t, ngap_initial_context_setup_fail) +MESSAGE_DEF(NGAP_NAS_NON_DELIVERY_IND , MESSAGE_PRIORITY_MED, ngap_nas_non_delivery_ind_t , ngap_nas_non_delivery_ind) +MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_RESP , MESSAGE_PRIORITY_MED, ngap_ue_release_resp_t , ngap_ue_release_resp) +MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, ngap_ue_release_complete_t , ngap_ue_release_complete) +MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_resp_t , ngap_ue_ctxt_modification_resp) +MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_fail_t , ngap_ue_ctxt_modification_fail) +MESSAGE_DEF(NGAP_PDUSESSION_SETUP_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_setup_resp_t , ngap_pdusession_setup_resp) +MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, ngap_pdusession_setup_req_fail_t , ngap_pdusession_setup_request_fail) +MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_resp_t , ngap_pdusession_modify_resp) +MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_pdusession_release_resp_t , ngap_pdusession_release_resp) +MESSAGE_DEF(NGAP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, ngap_path_switch_req_t , ngap_path_switch_req) +MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, ngap_path_switch_req_ack_t , ngap_path_switch_req_ack) +MESSAGE_DEF(NGAP_PDUSESSION_MODIFICATION_IND , MESSAGE_PRIORITY_MED, ngap_pdusession_modification_ind_t , ngap_pdusession_modification_ind) + +/* NGAP -> RRC messages */ +MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas ) +MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, ngap_initial_context_setup_req_t , ngap_initial_context_setup_req ) +MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_req_t , ngap_ue_ctxt_modification_req) +MESSAGE_DEF(NGAP_PAGING_IND , MESSAGE_PRIORITY_MED, ngap_paging_ind_t , ngap_paging_ind ) +MESSAGE_DEF(NGAP_PDUSESSION_SETUP_REQ , MESSAGE_PRIORITY_MED, ngap_pdusession_setup_req_t , ngap_pdusession_setup_req ) +MESSAGE_DEF(NGAP_PDUSESSION_MODIFY_REQ , MESSAGE_PRIORITY_MED, ngap_pdusession_modify_req_t , ngap_pdusession_modify_req ) +MESSAGE_DEF(NGAP_PDUSESSION_RELEASE_COMMAND , MESSAGE_PRIORITY_MED, ngap_pdusession_release_command_t , ngap_pdusession_release_command) +MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND, MESSAGE_PRIORITY_MED, ngap_ue_release_command_t , ngap_ue_release_command) + +/* NGAP <-> RRC messages (can be initiated either by MME or gNB) */ +MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h new file mode 100644 index 0000000000..60d48c8284 --- /dev/null +++ b/openair2/COMMON/ngap_messages_types.h @@ -0,0 +1,880 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* + * ngap_messages_types.h + * + * Created on: 2020 + * Author: Yoshio INOUE, Masayuki HARADA + * Email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#ifndef NGAP_MESSAGES_TYPES_H_ +#define NGAP_MESSAGES_TYPES_H_ + +#include "LTE_asn_constant.h" +//-------------------------------------------------------------------------------------------// +// Defines to access message fields. + +#define NGAP_REGISTER_GNB_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_register_gnb_req + +#define NGAP_REGISTER_GNB_CNF(mSGpTR) (mSGpTR)->ittiMsg.ngap_register_gnb_cnf +#define NGAP_DEREGISTERED_GNB_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_deregistered_gnb_ind + +#define NGAP_NAS_FIRST_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_nas_first_req +#define NGAP_UPLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.ngap_uplink_nas +#define NGAP_UE_CAPABILITIES_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_cap_info_ind +#define NGAP_INITIAL_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_resp +#define NGAP_INITIAL_CONTEXT_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_fail +#define NGAP_UE_CONTEXT_RELEASE_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_resp +#define NGAP_NAS_NON_DELIVERY_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_nas_non_delivery_ind +#define NGAP_UE_CTXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_resp +#define NGAP_UE_CTXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_fail +#define NGAP_PDUSESSION_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_setup_resp +#define NGAP_PDUSESSION_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_setup_req_fail +#define NGAP_PDUSESSION_MODIFY_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_modify_resp +#define NGAP_PATH_SWITCH_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_path_switch_req +#define NGAP_PATH_SWITCH_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.ngap_path_switch_req_ack +#define NGAP_PDUSESSION_MODIFICATION_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_modification_ind + +#define NGAP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_nas +#define NGAP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_req +#define NGAP_UE_CTXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_req +#define NGAP_UE_CONTEXT_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_command +#define NGAP_UE_CONTEXT_RELEASE_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_complete +#define NGAP_PDUSESSION_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_setup_req +#define NGAP_PDUSESSION_MODIFY_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_modify_req +#define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind + +#define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req +#define NGAP_PDUSESSION_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_command +#define NGAP_PDUSESSION_RELEASE_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.ngap_pdusession_release_resp + +//-------------------------------------------------------------------------------------------// +/* Maximum number of e-rabs to be setup/deleted in a single message. + * Even if only one bearer will be modified by message. + */ +#define NGAP_MAX_PDUSESSION (LTE_maxDRB + 3) + +/* Length of the transport layer address string + * 160 bits / 8 bits by char. + */ +#define NGAP_TRANSPORT_LAYER_ADDRESS_SIZE (160 / 8) + +#define NGAP_MAX_NB_AMF_IP_ADDRESS 10 +#define NGAP_IMSI_LENGTH 16 + +#define QOSFLOW_MAX_VALUE 64 + +/* Security key length used within gNB + * Even if only 16 bytes will be effectively used, + * the key length is 32 bytes (256 bits) + */ +#define SECURITY_KEY_LENGTH 32 + +typedef enum ngap_paging_drx_e { + NGAP_PAGING_DRX_32 = 0x0, + NGAP_PAGING_DRX_64 = 0x1, + NGAP_PAGING_DRX_128 = 0x2, + NGAP_PAGING_DRX_256 = 0x3 +} ngap_paging_drx_t; + +/* Lower value codepoint + * indicates higher priority. + */ +typedef enum ngap_paging_priority_s { + NGAP_PAGING_PRIO_LEVEL1 = 0, + NGAP_PAGING_PRIO_LEVEL2 = 1, + NGAP_PAGING_PRIO_LEVEL3 = 2, + NGAP_PAGING_PRIO_LEVEL4 = 3, + NGAP_PAGING_PRIO_LEVEL5 = 4, + NGAP_PAGING_PRIO_LEVEL6 = 5, + NGAP_PAGING_PRIO_LEVEL7 = 6, + NGAP_PAGING_PRIO_LEVEL8 = 7 +} ngap_paging_priority_t; + +typedef enum ngap_cn_domain_s { + NGAP_CN_DOMAIN_PS = 1, + NGAP_CN_DOMAIN_CS = 2 +} ngap_cn_domain_t; + +typedef struct ngap_net_ip_address_s { + unsigned ipv4:1; + unsigned ipv6:1; + char ipv4_address[16]; + char ipv6_address[46]; +} ngap_net_ip_address_t; + +typedef uint64_t bitrate_t; + +typedef struct ngap_ambr_s { + bitrate_t br_ul; + bitrate_t br_dl; +} ngap_ambr_t; + +typedef enum ngap_priority_level_s { + NGAP_PRIORITY_LEVEL_SPARE = 0, + NGAP_PRIORITY_LEVEL_HIGHEST = 1, + NGAP_PRIORITY_LEVEL_LOWEST = 14, + NGAP_PRIORITY_LEVEL_NO_PRIORITY = 15 +} ngap_priority_level_t; + +typedef enum ngap_pre_emp_capability_e { + NGAP_PRE_EMPTION_CAPABILITY_ENABLED = 0, + NGAP_PRE_EMPTION_CAPABILITY_DISABLED = 1, + NGAP_PRE_EMPTION_CAPABILITY_MAX, +} ngap_pre_emp_capability_t; + +typedef enum ngap_pre_emp_vulnerability_e { + NGAP_PRE_EMPTION_VULNERABILITY_ENABLED = 0, + NGAP_PRE_EMPTION_VULNERABILITY_DISABLED = 1, + NGAP_PRE_EMPTION_VULNERABILITY_MAX, +} ngap_pre_emp_vulnerability_t; + +typedef struct ngap_allocation_retention_priority_s { + ngap_priority_level_t priority_level; + ngap_pre_emp_capability_t pre_emp_capability; + ngap_pre_emp_vulnerability_t pre_emp_vulnerability; +} ngap_allocation_retention_priority_t; + +typedef struct ngap_security_capabilities_s { + uint16_t nRencryption_algorithms; + uint16_t nRintegrity_algorithms; + uint16_t eUTRAencryption_algorithms; + uint16_t eUTRAintegrity_algorithms; +} ngap_security_capabilities_t; + +/* Provides the establishment cause for the RRC connection request as provided + * by the upper layers. W.r.t. the cause value names: highPriorityAccess + * concerns AC11..AC15, ‘mtâ€�Estands for ‘Mobile Terminatingâ€�Eand ‘moâ€�Efor + * 'Mobile Originating'. Defined in TS 36.331. + */ +typedef enum ngap_rrc_establishment_cause_e { + NGAP_RRC_CAUSE_EMERGENCY = 0x0, + NGAP_RRC_CAUSE_HIGH_PRIO_ACCESS = 0x1, + NGAP_RRC_CAUSE_MT_ACCESS = 0x2, + NGAP_RRC_CAUSE_MO_SIGNALLING = 0x3, + NGAP_RRC_CAUSE_MO_DATA = 0x4, + NGAP_RRC_CAUSE_MO_VOICECALL = 0x5, + NGAP_RRC_CAUSE_MO_VIDEOCALL = 0x6, + NGAP_RRC_CAUSE_MO_SMS = 0x7, + NGAP_RRC_CAUSE_MPS_PRIORITY_ACCESS = 0x8, + NGAP_RRC_CAUSE_MCS_PRIORITY_ACCESS = 0x9, + NGAP_RRC_CAUSE_NOTAVAILABLE = 0x10, + NGAP_RRC_CAUSE_LAST +} ngap_rrc_establishment_cause_t; + +typedef struct ngap_guami_s { + uint16_t mcc; + uint16_t mnc; + uint8_t mnc_len; + uint8_t amf_region_id; + uint16_t amf_set_id; + uint8_t amf_pointer; +} ngap_guami_t; + +typedef struct ngap_allowed_NSSAI_s{ + uint8_t sST; + uint8_t sD_flag; + uint8_t sD[3]; +}ngap_allowed_NSSAI_t; + +typedef struct fiveg_s_tmsi_s { + uint16_t amf_set_id; + uint8_t amf_pointer; + uint32_t m_tmsi; +} fiveg_s_tmsi_t; + +typedef struct ngap_tai_plmn_identity_s { + uint16_t mcc; + uint16_t mnc; + uint8_t mnc_digit_length; +} ngap_plmn_identity_t; + +typedef struct ngap_ue_paging_identity_s { + fiveg_s_tmsi_t s_tmsi; +} ngap_ue_paging_identity_t; + +typedef enum ngap_ue_identities_presenceMask_e { + NGAP_UE_IDENTITIES_NONE = 0, + NGAP_UE_IDENTITIES_FiveG_s_tmsi = 1 << 1, + NGAP_UE_IDENTITIES_guami = 1 << 2, +} ngap_ue_identities_presenceMask_t; + +typedef struct ngap_ue_identity_s { + ngap_ue_identities_presenceMask_t presenceMask; + fiveg_s_tmsi_t s_tmsi; + ngap_guami_t guami; +} ngap_ue_identity_t; + +typedef struct ngap_nas_pdu_s { + /* Octet string data */ + uint8_t *buffer; + /* Length of the octet string */ + uint32_t length; +} ngap_nas_pdu_t, ngap_ue_radio_cap_t; + +typedef struct ngap_mobility_restriction_s{ + ngap_plmn_identity_t serving_plmn; +}ngap_mobility_restriction_t; + +typedef enum pdu_session_type_e { + PDUSessionType_ipv4 = 0, + PDUSessionType_ipv6 = 1, + PDUSessionType_ipv4v6 = 2, + PDUSessionType_ethernet = 3, + PDUSessionType_unstructured = 4 +}pdu_session_type_t; + +typedef struct ngap_transport_layer_addr_s { + /* Length of the transport layer address buffer in bits. NGAP layer received a + * bit string<1..160> containing one of the following addresses: ipv4, + * ipv6, or ipv4 and ipv6. The layer doesn't interpret the buffer but + * silently forward it to NG-U. + */ + uint8_t pdu_session_type; + uint8_t length; + uint8_t buffer[20]; // in network byte order +} ngap_transport_layer_addr_t; + +#define TRANSPORT_LAYER_ADDR_COPY(dEST,sOURCE) \ + do { \ + AssertFatal(sOURCE.len <= 20); \ + memcpy(dEST.buffer, sOURCE.buffer, sOURCE.len); \ + dEST.length = sOURCE.length; \ + } while (0) + +typedef struct pdusession_level_qos_parameter_s { + uint8_t qfi; + uint64_t fiveQI; + ngap_allocation_retention_priority_t allocation_retention_priority; +} pdusession_level_qos_parameter_t; + +typedef struct pdusession_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; + + uint8_t nb_qos; + /* Quality of service for this pdusession */ + pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE]; + /* The NAS PDU should be forwarded by the RRC layer to the NAS layer */ + ngap_nas_pdu_t nas_pdu; + /* The transport layer address for the IP packets */ + ngap_transport_layer_addr_t upf_addr; + /* S-GW Tunnel endpoint identifier */ + uint32_t gtp_teid; +} pdusession_t; + + +typedef enum pdusession_qosflow_mapping_ind_e{ + QOSFLOW_MAPPING_INDICATION_UL = 0, + QOSFLOW_MAPPING_INDICATION_DL = 1, + QOSFLOW_MAPPING_INDICATION_NON = 0xFF +}pdusession_qosflow_mapping_ind_t; + +typedef struct pdusession_associate_qosflow_s{ + uint8_t qfi; + pdusession_qosflow_mapping_ind_t qos_flow_mapping_ind; +}pdusession_associate_qosflow_t; + +typedef struct pdusession_setup_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; + + /* The transport layer address for the IP packets */ + ngap_transport_layer_addr_t gNB_addr; + + /* UPF Tunnel endpoint identifier */ + uint32_t gtp_teid; + + /* qos flow list number */ + uint8_t nb_of_qos_flow; + + /* qos flow list(1 ~ 64) */ + pdusession_associate_qosflow_t associated_qos_flows[QOSFLOW_MAX_VALUE]; +} pdusession_setup_t; + +typedef struct pdusession_tobe_added_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; + + /* Unique drb_ID for the UE. */ + uint8_t drb_ID; + + /* The transport layer address for the IP packets */ + ngap_transport_layer_addr_t upf_addr; + + /* S-GW Tunnel endpoint identifier */ + uint32_t gtp_teid; +} pdusession_tobe_added_t; + +typedef struct pdusession_admitted_tobe_added_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; + + /* Unique drb_ID for the UE. */ + uint8_t drb_ID; + + /* The transport layer address for the IP packets */ + ngap_transport_layer_addr_t gnb_addr; + + /* S-GW Tunnel endpoint identifier */ + uint32_t gtp_teid; +} pdusession_admitted_tobe_added_t; + + + +typedef struct pdusession_tobeswitched_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; + + /* The transport layer address for the IP packets */ + ngap_transport_layer_addr_t upf_addr; + + /* S-GW Tunnel endpoint identifier */ + uint32_t gtp_teid; +} pdusession_tobeswitched_t; + +typedef struct pdusession_modify_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; +} pdusession_modify_t; + +typedef enum ngap_Cause_e { + NGAP_CAUSE_NOTHING, /* No components present */ + NGAP_CAUSE_RADIO_NETWORK, + NGAP_CAUSE_TRANSPORT, + NGAP_CAUSE_NAS, + NGAP_CAUSE_PROTOCOL, + NGAP_CAUSE_MISC, + /* Extensions may appear below */ + +} ngap_Cause_t; + +typedef enum ngap_Cause_radio_network_e { + NGAP_CAUSE_RADIO_NETWORK_UNSPECIFIED, + NGAP_CAUSE_RADIO_NETWORK_TXNRELOCOVERALL_EXPIRY, + NGAP_CAUSE_RADIO_NETWORK_SUCCESSFUL_HANDOVER, + NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_NGRAN_GENERATED_REASON, + NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_5GC_GENERATED_REASON, + NGAP_CAUSE_RADIO_NETWORK_HANDOVER_CANCELLED, + NGAP_CAUSE_RADIO_NETWORK_PARTIAL_HANDOVER, + NGAP_CAUSE_RADIO_NETWORK_HO_FAILURE_IN_TARGET_5GC_NGRAN_NODE_OR_TARGET_SYSTEM, + NGAP_CAUSE_RADIO_NETWORK_HO_TARGET_NOT_ALLOWED, + NGAP_CAUSE_RADIO_NETWORK_TNGRELOCOVERALL_EXPIRY, + NGAP_CAUSE_RADIO_NETWORK_TNGRELOCPREP_EXPIRY, + NGAP_CAUSE_RADIO_NETWORK_CELL_NOT_AVAILABLE, + NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_TARGETID, + NGAP_CAUSE_RADIO_NETWORK_NO_RADIO_RESOURCES_AVAILABLE_IN_TARGET_CELL, + NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_LOCAL_UE_NGAP_ID, + NGAP_CAUSE_RADIO_NETWORK_INCONSISTENT_REMOTE_UE_NGAP_ID, + NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON, + NGAP_CAUSE_RADIO_NETWORK_TIME_CRITICAL_HANDOVER, + NGAP_CAUSE_RADIO_NETWORK_RESOURCE_OPTIMISATION_HANDOVER, + NGAP_CAUSE_RADIO_NETWORK_REDUCE_LOAD_IN_SERVING_CELL, + NGAP_CAUSE_RADIO_NETWORK_USER_INACTIVITY, + NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST, + NGAP_CAUSE_RADIO_NETWORK_RADIO_RESOURCES_NOT_AVAILABLE, + NGAP_CAUSE_RADIO_NETWORK_INVALID_QOS_COMBINATION, + NGAP_CAUSE_RADIO_NETWORK_FAILURE_IN_RADIO_INTERFACE_PROCEDURE, + NGAP_CAUSE_RADIO_NETWORK_INTERACTION_WITH_OTHER_PROCEDURE, + NGAP_CAUSE_RADIO_NETWORK_UNKNOWN_PDU_SESSION_ID, + NGAP_CAUSE_RADIO_NETWORK_UNKOWN_QOS_FLOW_ID, + NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_PDU_SESSION_ID_INSTANCES, + NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_QOS_FLOW_ID_INSTANCES, + NGAP_CAUSE_RADIO_NETWORK_ENCRYPTION_AND_OR_INTEGRITY_PROTECTION_ALGORITHMS_NOT_SUPPORTED, + NGAP_CAUSE_RADIO_NETWORK_NG_INTRA_SYSTEM_HANDOVER_TRIGGERED, + NGAP_CAUSE_RADIO_NETWORK_NG_INTER_SYSTEM_HANDOVER_TRIGGERED, + NGAP_CAUSE_RADIO_NETWORK_XN_HANDOVER_TRIGGERED, + NGAP_CAUSE_RADIO_NETWORK_NOT_SUPPORTED_5QI_VALUE, + NGAP_CAUSE_RADIO_NETWORK_UE_CONTEXT_TRANSFER, + NGAP_CAUSE_RADIO_NETWORK_IMS_VOICE_EPS_FALLBACK_OR_RAT_FALLBACK_TRIGGERED, + NGAP_CAUSE_RADIO_NETWORK_UP_INTEGRITY_PROTECTION_NOT_POSSIBLE, + NGAP_CAUSE_RADIO_NETWORK_UP_CONFIDENTIALITY_PROTECTION_NOT_POSSIBLE, + NGAP_CAUSE_RADIO_NETWORK_SLICE_NOT_SUPPORTED, + NGAP_CAUSE_RADIO_NETWORK_UE_IN_RRC_INACTIVE_STATE_NOT_REACHABLE, + NGAP_CAUSE_RADIO_NETWORK_REDIRECTION, + NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE, + NGAP_CAUSE_RADIO_NETWORK_UE_MAX_INTEGRITY_PROTECTED_DATA_RATE_REASON, + NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_CN_DETECTED_MOBILITY, + NGAP_CAUSE_RADIO_NETWORK_N26_INTERFACE_NOT_AVAILABLE, + NGAP_CAUSE_RADIO_NETWORK_RELEASE_DUE_TO_PRE_EMPTION, + NGAP_CAUSE_RADIO_NETWORK_MULTIPLE_LOCATION_REPORTING_REFERENCE_ID_INSTANCES +} ngap_Cause_radio_network_t; + +typedef struct pdusession_failed_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; + /* Cause of the failure */ + // cause_t cause; + ngap_Cause_t cause; + uint8_t cause_value; +} pdusession_failed_t; + +typedef enum ngap_ue_ctxt_modification_present_s { + NGAP_UE_CONTEXT_MODIFICATION_SECURITY_KEY = (1 << 0), + NGAP_UE_CONTEXT_MODIFICATION_UE_AMBR = (1 << 1), + NGAP_UE_CONTEXT_MODIFICATION_UE_SECU_CAP = (1 << 2), +} ngap_ue_ctxt_modification_present_t; + +typedef enum ngap_paging_ind_present_s { + NGAP_PAGING_IND_PAGING_DRX = (1 << 0), + NGAP_PAGING_IND_PAGING_PRIORITY = (1 << 1), +} ngap_paging_ind_present_t; + +//-------------------------------------------------------------------------------------------// +// gNB application layer -> NGAP messages +typedef struct ngap_register_gnb_req_s { + /* Unique gNB_id to identify the gNB within EPC. + * For macro gNB ids this field should be 20 bits long. + * For home gNB ids this field should be 28 bits long. + */ + uint32_t gNB_id; + /* The type of the cell */ + enum cell_type_e cell_type; + + /* Optional name for the cell + * NOTE: the name can be NULL (i.e no name) and will be cropped to 150 + * characters. + */ + char *gNB_name; + + /* Tracking area code */ + uint32_t tac; + +#define PLMN_LIST_MAX_SIZE 6 + /* Mobile Country Code + * Mobile Network Code + */ + uint16_t mcc[PLMN_LIST_MAX_SIZE]; + uint16_t mnc[PLMN_LIST_MAX_SIZE]; + uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; + uint8_t num_plmn; + + uint16_t num_nssai[PLMN_LIST_MAX_SIZE]; + ngap_allowed_NSSAI_t s_nssai[PLMN_LIST_MAX_SIZE][8]; + + /* Default Paging DRX of the gNB as defined in TS 38.304 */ + ngap_paging_drx_t default_drx; + + /* The gNB IP address to bind */ + net_ip_address_t gnb_ip_address; + + /* Nb of AMF to connect to */ + uint8_t nb_amf; + /* List of AMF to connect to */ + net_ip_address_t amf_ip_address[NGAP_MAX_NB_AMF_IP_ADDRESS]; + uint8_t broadcast_plmn_num[NGAP_MAX_NB_AMF_IP_ADDRESS]; + uint8_t broadcast_plmn_index[NGAP_MAX_NB_AMF_IP_ADDRESS][PLMN_LIST_MAX_SIZE]; + + /* Number of SCTP streams used for a amf association */ + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; +} ngap_register_gnb_req_t; + +//-------------------------------------------------------------------------------------------// +// NGAP -> gNB application layer messages +typedef struct ngap_register_gnb_cnf_s { + /* Nb of AMF connected */ + uint8_t nb_amf; +} ngap_register_gnb_cnf_t; + +typedef struct ngap_deregistered_gnb_ind_s { + /* Nb of AMF connected */ + uint8_t nb_amf; +} ngap_deregistered_gnb_ind_t; + +//-------------------------------------------------------------------------------------------// +// RRC -> NGAP messages + +/* The NAS First Req is the first message exchanged between RRC and NGAP + * for an UE. + * The rnti uniquely identifies an UE within a cell. Later the gnb_ue_ngap_id + * will be the unique identifier used between RRC and NGAP. + */ +typedef struct ngap_nas_first_req_s { + /* UE id for initial connection to NGAP */ + uint16_t ue_initial_id; + + /* the chosen PLMN identity as index, see TS 36.331 6.2.2 RRC Connection + * Setup Complete. This index here is zero-based, unlike the standard! */ + int selected_plmn_identity; + + /* Establishment cause as sent by UE */ + ngap_rrc_establishment_cause_t establishment_cause; + + /* NAS PDU */ + ngap_nas_pdu_t nas_pdu; + + /* If this flag is set NGAP layer is expecting the GUAMI. If = 0, + * the temporary s-tmsi is used. + */ + ngap_ue_identity_t ue_identity; +} ngap_nas_first_req_t; + +typedef struct ngap_uplink_nas_s { + /* Unique UE identifier within an gNB */ + uint32_t gNB_ue_ngap_id; + + /* NAS pdu */ + ngap_nas_pdu_t nas_pdu; +} ngap_uplink_nas_t; + +typedef struct ngap_ue_cap_info_ind_s { + uint32_t gNB_ue_ngap_id; + ngap_ue_radio_cap_t ue_radio_cap; +} ngap_ue_cap_info_ind_t; + +typedef struct ngap_initial_context_setup_resp_s { + uint32_t gNB_ue_ngap_id; + + /* Number of pdusession setup-ed in the list */ + uint8_t nb_of_pdusessions; + /* list of pdusession setup-ed by RRC layers */ + pdusession_setup_t pdusessions[NGAP_MAX_PDUSESSION]; + + /* Number of pdusession failed to be setup in list */ + uint8_t nb_of_pdusessions_failed; + /* list of pdusessions that failed to be setup */ + pdusession_failed_t pdusessions_failed[NGAP_MAX_PDUSESSION]; +} ngap_initial_context_setup_resp_t; + +typedef struct ngap_initial_context_setup_fail_s { + uint32_t gNB_ue_ngap_id; + + /* TODO add cause */ +} ngap_initial_context_setup_fail_t, ngap_ue_ctxt_modification_fail_t, ngap_pdusession_setup_req_fail_t; + +typedef struct ngap_nas_non_delivery_ind_s { + uint32_t gNB_ue_ngap_id; + ngap_nas_pdu_t nas_pdu; + /* TODO: add cause */ +} ngap_nas_non_delivery_ind_t; + +typedef struct ngap_ue_ctxt_modification_req_s { + uint32_t gNB_ue_ngap_id; + + /* Bit-mask of possible present parameters */ + ngap_ue_ctxt_modification_present_t present; + + /* Following fields are optionnaly present */ + + /* Security key */ + uint8_t security_key[SECURITY_KEY_LENGTH]; + + /* UE aggregate maximum bitrate */ + ngap_ambr_t ue_ambr; + + /* NR Security capabilities */ + ngap_security_capabilities_t security_capabilities; +} ngap_ue_ctxt_modification_req_t; + +typedef struct ngap_ue_ctxt_modification_resp_s { + uint32_t gNB_ue_ngap_id; +} ngap_ue_ctxt_modification_resp_t; + +typedef struct ngap_ue_release_complete_s { + + uint32_t gNB_ue_ngap_id; + +} ngap_ue_release_complete_t; + +//-------------------------------------------------------------------------------------------// +// NGAP -> RRC messages +typedef struct ngap_downlink_nas_s { + /* UE id for initial connection to NGAP */ + uint16_t ue_initial_id; + + /* Unique UE identifier within an gNB */ + uint32_t gNB_ue_ngap_id; + + /* NAS pdu */ + ngap_nas_pdu_t nas_pdu; +} ngap_downlink_nas_t; + + +typedef struct ngap_initial_context_setup_req_s { + /* UE id for initial connection to NGAP */ + uint16_t ue_initial_id; + + /* gNB ue ngap id as initialized by NGAP layer */ + uint32_t gNB_ue_ngap_id; + + uint64_t amf_ue_ngap_id:40; + + /* UE aggregate maximum bitrate */ + ngap_ambr_t ue_ambr; + + /* guami */ + ngap_guami_t guami; + + /* allowed nssai */ + uint8_t nb_allowed_nssais; + ngap_allowed_NSSAI_t allowed_nssai[8]; + + /* Security algorithms */ + ngap_security_capabilities_t security_capabilities; + + /* Security key */ + uint8_t security_key[SECURITY_KEY_LENGTH]; + + /* Number of pdusession to be setup in the list */ + uint8_t nb_of_pdusessions; + /* list of pdusession to be setup by RRC layers */ + pdusession_t pdusession_param[NGAP_MAX_PDUSESSION]; + + /* Mobility Restriction List */ + uint8_t mobility_restriction_flag; + ngap_mobility_restriction_t mobility_restriction; + + /* Nas Pdu */ + uint8_t nas_pdu_flag; + ngap_nas_pdu_t nas_pdu; +} ngap_initial_context_setup_req_t; + + +typedef struct ngap_paging_ind_s { + /* UE paging identity */ + ngap_ue_paging_identity_t ue_paging_identity; + + /* Indicates origin of paging */ + ngap_cn_domain_t cn_domain; + + /* PLMN_identity in TAI of Paging*/ + ngap_plmn_identity_t plmn_identity[256]; + + /* TAC in TAIList of Paging*/ + int16_t tac[256]; + + /* size of TAIList*/ + int16_t tai_size; + + /* Optional fields */ + ngap_paging_drx_t paging_drx; + + ngap_paging_priority_t paging_priority; +} ngap_paging_ind_t; + +typedef struct ngap_pdusession_setup_req_s { + /* UE id for initial connection to NGAP */ + uint16_t ue_initial_id; + + /* AMF UE id */ + uint64_t amf_ue_ngap_id:40; + + /* gNB ue ngap id as initialized by NGAP layer */ + uint32_t gNB_ue_ngap_id; + + /* Number of pdusession to be setup in the list */ + uint8_t nb_pdusessions_tosetup; + + /* E RAB setup request */ + pdusession_t pdusession_setup_params[NGAP_MAX_PDUSESSION]; + +} ngap_pdusession_setup_req_t; + +typedef struct ngap_pdusession_setup_resp_s { + uint32_t gNB_ue_ngap_id; + + /* Number of pdusession setup-ed in the list */ + uint8_t nb_of_pdusessions; + /* list of pdusession setup-ed by RRC layers */ + pdusession_setup_t pdusessions[NGAP_MAX_PDUSESSION]; + + /* Number of pdusession failed to be setup in list */ + uint8_t nb_of_pdusessions_failed; + /* list of pdusessions that failed to be setup */ + pdusession_failed_t pdusessions_failed[NGAP_MAX_PDUSESSION]; +} ngap_pdusession_setup_resp_t; + +typedef struct ngap_path_switch_req_s { + + uint32_t gNB_ue_ngap_id; + + /* Number of pdusession setup-ed in the list */ + uint8_t nb_of_pdusessions; + + /* list of pdusession setup-ed by RRC layers */ + pdusession_setup_t pdusessions_tobeswitched[NGAP_MAX_PDUSESSION]; + + /* AMF UE id */ + uint64_t amf_ue_ngap_id:40; + + ngap_guami_t ue_guami; + + uint16_t ue_initial_id; + + /* Security algorithms */ + ngap_security_capabilities_t security_capabilities; + +} ngap_path_switch_req_t; + +typedef struct ngap_path_switch_req_ack_s { + + /* UE id for initial connection to NGAP */ + uint16_t ue_initial_id; + + uint32_t gNB_ue_ngap_id; + + /* AMF UE id */ + uint64_t amf_ue_ngap_id:40; + + /* UE aggregate maximum bitrate */ + ngap_ambr_t ue_ambr; + + /* Number of pdusession setup-ed in the list */ + uint8_t nb_pdusessions_tobeswitched; + + /* list of pdusession to be switched by RRC layers */ + pdusession_tobeswitched_t pdusessions_tobeswitched[NGAP_MAX_PDUSESSION]; + + /* Number of pdusessions to be released by RRC */ + uint8_t nb_pdusessions_tobereleased; + + /* list of pdusessions to be released */ + pdusession_failed_t pdusessions_tobereleased[NGAP_MAX_PDUSESSION]; + + /* Security key */ + int next_hop_chain_count; + uint8_t next_security_key[SECURITY_KEY_LENGTH]; + +} ngap_path_switch_req_ack_t; + +typedef struct ngap_pdusession_modification_ind_s { + + uint32_t gNB_ue_ngap_id; + + /* AMF UE id */ + uint64_t amf_ue_ngap_id:40; + + /* Number of pdusession setup-ed in the list */ + uint8_t nb_of_pdusessions_tobemodified; + + uint8_t nb_of_pdusessions_nottobemodified; + + /* list of pdusession setup-ed by RRC layers */ + pdusession_setup_t pdusessions_tobemodified[NGAP_MAX_PDUSESSION]; + + pdusession_setup_t pdusessions_nottobemodified[NGAP_MAX_PDUSESSION]; + + uint16_t ue_initial_id; + +} ngap_pdusession_modification_ind_t; + +// NGAP --> RRC messages +typedef struct ngap_ue_release_command_s { + + uint32_t gNB_ue_ngap_id; + +} ngap_ue_release_command_t; + + +//-------------------------------------------------------------------------------------------// +// NGAP <-- RRC messages +typedef struct pdusession_release_s { + /* Unique pdusession_id for the UE. */ + uint8_t pdusession_id; + /* Octet string data */ + uint8_t *transfer_buffer; + /* Length of the octet string */ + uint32_t transfer_length; +} pdusession_release_t; + +typedef struct ngap_ue_release_req_s { + uint32_t gNB_ue_ngap_id; + /* Number of pdusession resource in the list */ + uint8_t nb_of_pdusessions; + /* list of pdusession resource by RRC layers */ + pdusession_release_t pdusessions[NGAP_MAX_PDUSESSION]; + ngap_Cause_t cause; + long cause_value; +} ngap_ue_release_req_t, ngap_ue_release_resp_t; + +typedef struct ngap_pdusession_modify_req_s { + /* UE id for initial connection to NGAP */ + uint16_t ue_initial_id; + + /* AMF UE id */ + uint64_t amf_ue_ngap_id:40; + + /* gNB ue ngap id as initialized by NGAP layer */ + uint32_t gNB_ue_ngap_id; + + /* Number of pdusession to be modify in the list */ + uint8_t nb_pdusessions_tomodify; + + /* E RAB modify request */ + pdusession_t pdusession_modify_params[NGAP_MAX_PDUSESSION]; +} ngap_pdusession_modify_req_t; + +typedef struct ngap_pdusession_modify_resp_s { + uint32_t gNB_ue_ngap_id; + + /* Number of pdusession modify-ed in the list */ + uint8_t nb_of_pdusessions; + /* list of pdusession modify-ed by RRC layers */ + pdusession_modify_t pdusessions[NGAP_MAX_PDUSESSION]; + + /* Number of pdusession failed to be modify in list */ + uint8_t nb_of_pdusessions_failed; + /* list of pdusessions that failed to be modify */ + pdusession_failed_t pdusessions_failed[NGAP_MAX_PDUSESSION]; +} ngap_pdusession_modify_resp_t; + +typedef struct ngap_pdusession_release_command_s { + /* AMF UE id */ + uint64_t amf_ue_ngap_id:40; + + /* gNB ue ngap id as initialized by NGAP layer */ + uint32_t gNB_ue_ngap_id; + + /* The NAS PDU should be forwarded by the RRC layer to the NAS layer */ + ngap_nas_pdu_t nas_pdu; + + /* Number of pdusession to be released in the list */ + uint8_t nb_pdusessions_torelease; + + /* PDUSession release command */ + pdusession_release_t pdusession_release_params[NGAP_MAX_PDUSESSION]; + +} ngap_pdusession_release_command_t; + +typedef struct ngap_pdusession_release_resp_s { + /* AMF UE id */ + uint64_t amf_ue_ngap_id:40; + + /* gNB ue ngap id as initialized by NGAP layer */ + uint32_t gNB_ue_ngap_id; + + /* Number of pdusession released in the list */ + uint8_t nb_of_pdusessions_released; + + /* list of pdusessions released */ + pdusession_release_t pdusession_release[NGAP_MAX_PDUSESSION]; + + /* Number of pdusession failed to be released in list */ + uint8_t nb_of_pdusessions_failed; + /* list of pdusessions that failed to be released */ + pdusession_failed_t pdusessions_failed[NGAP_MAX_PDUSESSION]; + +} ngap_pdusession_release_resp_t; + +#endif /* NGAP_MESSAGES_TYPES_H_ */ diff --git a/openair2/COMMON/pdcp_messages_def.h b/openair2/COMMON/pdcp_messages_def.h index c4be4b2957..59d47eb81b 100644 --- a/openair2/COMMON/pdcp_messages_def.h +++ b/openair2/COMMON/pdcp_messages_def.h @@ -31,3 +31,7 @@ MESSAGE_DEF(RRC_DCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataReq, rrc_dcch_data_req) MESSAGE_DEF(RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataInd, rrc_dcch_data_ind) MESSAGE_DEF(RRC_PCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcPcchDataReq, rrc_pcch_data_req) + +// gNB +MESSAGE_DEF(NR_RRC_DCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataReq, nr_rrc_dcch_data_req) +MESSAGE_DEF(NR_RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataInd, nr_rrc_dcch_data_ind) diff --git a/openair2/COMMON/pdcp_messages_types.h b/openair2/COMMON/pdcp_messages_types.h index 1551e4283f..0390fd80f4 100644 --- a/openair2/COMMON/pdcp_messages_types.h +++ b/openair2/COMMON/pdcp_messages_types.h @@ -35,6 +35,10 @@ #define RRC_DCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_dcch_data_ind #define RRC_PCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_pcch_data_req +// gNB +#define NR_RRC_DCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_dcch_data_req +#define NR_RRC_DCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_dcch_data_ind + //-------------------------------------------------------------------------------------------// // Messages between RRC and PDCP layers typedef struct RrcDcchDataReq_s { @@ -61,6 +65,30 @@ typedef struct RrcDcchDataInd_s { uint8_t eNB_index; // LG: needed in UE } RrcDcchDataInd; +typedef struct NRRrcDcchDataReq_s { + uint32_t frame; + uint8_t gnb_flag; + rb_id_t rb_id; + uint32_t muip; + uint32_t confirmp; + uint32_t sdu_size; + uint8_t *sdu_p; + uint8_t mode; + uint16_t rnti; + uint8_t module_id; + uint8_t gNB_index; +} NRRrcDcchDataReq; + +typedef struct NRRrcDcchDataInd_s { + uint32_t frame; + uint8_t dcch_index; + uint32_t sdu_size; + uint8_t *sdu_p; + uint16_t rnti; + uint8_t module_id; + uint8_t gNB_index; // LG: needed in UE +} NRRrcDcchDataInd; + typedef struct RrcPcchDataReq_s { uint32_t sdu_size; uint8_t *sdu_p; diff --git a/openair2/COMMON/platform_constants.h b/openair2/COMMON/platform_constants.h index 77f7e26c67..355f56f9c9 100644 --- a/openair2/COMMON/platform_constants.h +++ b/openair2/COMMON/platform_constants.h @@ -28,11 +28,14 @@ ***************************************************************************/ -#include "LTE_asn_constant.h" #ifndef __PLATFORM_CONSTANTS_H__ # define __PLATFORM_CONSTANTS_H__ +#include "LTE_asn_constant.h" +#include "NR_asn_constant.h" +#define NR_MAXDRB 14 + #ifdef JUMBO_FRAME #define NL_MAX_PAYLOAD 18000 /* this should cover the max mtu size*/ #else @@ -65,18 +68,6 @@ #define MAX_NR_RRC_UE_CONTEXTS 64 #ifndef UE_EXPANSION - // TODO:L2 FAPI simulator. - // UESIM_EXPANSION is used to be same value of MAX_MOBILES_PER_ENB - // in eNB and UE. - // now , if we use --mu option in UE, compiling error will occur. - // This problem will be fixed in the future. - #ifdef UESIM_EXPANSION - #define MAX_MOBILES_PER_ENB 256 - #define MAX_MOBILES_PER_ENB_NB_IoT 256 - #define MAX_MOBILES_PER_GNB 256 - #define MAX_eNB 2 - #define MAX_gNB 2 - #else #ifdef LARGE_SCALE #define MAX_MOBILES_PER_ENB 128 #define MAX_MOBILES_PER_ENB_NB_IoT 128 @@ -86,11 +77,10 @@ #else #define MAX_MOBILES_PER_ENB 4 #define MAX_MOBILES_PER_ENB_NB_IoT 4 - #define MAX_MOBILES_PER_GNB 2//16 + #define MAX_MOBILES_PER_GNB 4//16 #define MAX_eNB 2 #define MAX_gNB 2 #endif - #endif #else #define MAX_MOBILES_PER_ENB 256 #define MAX_MOBILES_PER_ENB_NB_IoT 256 @@ -99,12 +89,7 @@ #define MAX_gNB 2 #endif -#define NUMBER_OF_NR_DLSCH_MAX 2//16 -#define NUMBER_OF_NR_ULSCH_MAX 2//16 -#define NUMBER_OF_NR_PUCCH_MAX 2 -#define NUMBER_OF_NR_SR_MAX 16 - - +#define NUMBER_OF_NR_UCI_STATS_MAX 16 #define MAX_MANAGED_ENB_PER_MOBILE 2 #define MAX_MANAGED_GNB_PER_MOBILE 2 @@ -115,6 +100,7 @@ #define DEFAULT_RAB_ID 1 #define NB_RB_MAX (LTE_maxDRB + 3) /* was 11, now 14, maxDRB comes from asn1_constants.h, + 3 because of 3 SRB, one invisible id 0, then id 1 and 2 */ +#define NR_NB_RB_MAX (NR_maxDRB + 3) #define NB_RB_MBMS_MAX (LTE_maxSessionPerPMCH*LTE_maxServiceCount) diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h index 2555be081a..23b33dd8b1 100644 --- a/openair2/COMMON/platform_types.h +++ b/openair2/COMMON/platform_types.h @@ -28,10 +28,13 @@ ***************************************************************************/ #ifndef __PLATFORM_TYPES_H__ -# define __PLATFORM_TYPES_H__ +#define __PLATFORM_TYPES_H__ #if !defined(NAS_NETLINK) - #include +#include +#else +#include +typedef void * intptr_t; #endif //----------------------------------------------------------------------------- @@ -192,21 +195,13 @@ typedef uint8_t mme_code_t; typedef uint32_t m_tmsi_t; //Random UE identity length = 40 bits -#if ! defined(NOT_A_RANDOM_UE_IDENTITY) #define NOT_A_RANDOM_UE_IDENTITY (uint64_t)0xFFFFFFFF -#endif -#if ! defined(NOT_A_RNTI) #define NOT_A_RNTI (rnti_t)0 -#endif -#if ! defined(M_RNTI) #define M_RNTI (rnti_t)0xFFFD -#endif -#if ! defined(P_RNTI) #define P_RNTI (rnti_t)0xFFFE -#endif -#if ! defined(SI_RNTI) #define SI_RNTI (rnti_t)0xFFFF -#endif +#define CBA_RNTI (rnti_t)0xfff4 +#define OAI_C_RNTI (rnti_t)0x1234 typedef enum config_action_e { CONFIG_ACTION_NULL = 0, CONFIG_ACTION_ADD = 1, @@ -222,16 +217,14 @@ typedef enum config_action_e { //----------------------------------------------------------------------------- typedef uint32_t teid_t; // tunnel endpoint identifier typedef uint8_t ebi_t; // eps bearer id - +typedef uint8_t pdusessionid_t; //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- // may be ITTI not enabled, but type instance is useful also for OTG, -#if !defined(instance_t) - typedef uint16_t instance_t; -#endif +typedef intptr_t instance_t; typedef struct protocol_ctxt_s { module_id_t module_id; /*!< \brief Virtualized module identifier */ eNB_flag_t enb_flag; /*!< \brief Flag to indicate eNB (1) or UE (0) */ @@ -292,13 +285,19 @@ typedef struct protocol_ctxt_s { (Ctxt_Pp)->subframe = sUBfRAME; \ PROTOCOL_CTXT_COMPUTE_MODULE_ID(Ctxt_Pp) -#define PROTOCOL_CTXT_FMT "[FRAME %05u][%s][MOD %02u][RNTI %" PRIx16 "]" +#define PROTOCOL_CTXT_FMT "[FRAME %05u][%s][MOD %02d][RNTI %" PRIx16 "]" #define PROTOCOL_CTXT_ARGS(CTXT_Pp) \ (CTXT_Pp)->frame, \ ((CTXT_Pp)->enb_flag == ENB_FLAG_YES) ? "eNB":" UE", \ (CTXT_Pp)->module_id, \ (CTXT_Pp)->rnti +#define PROTOCOL_NR_CTXT_ARGS(CTXT_Pp) \ + (CTXT_Pp)->frame, \ + ((CTXT_Pp)->enb_flag == GNB_FLAG_YES) ? "gNB":" UE", \ + (CTXT_Pp)->module_id, \ + (CTXT_Pp)->rnti + #define CHECK_CTXT_ARGS(CTXT_Pp) #define exit_fun(msg) exit_function(__FILE__,__FUNCTION__,__LINE__,msg) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 7582de65ba..e1886b57ff 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -42,6 +42,7 @@ #include "LTE_SL-DiscResourcePool-r12.h" #include "NR_RACH-ConfigCommon.h" #include "NR_ServingCellConfigCommon.h" +#include "NR_ServingCellConfig.h" //-------------------------------------------------------------------------------------------// // Messages for RRC logging #if defined(DISABLE_ITTI_XER_PRINT) @@ -323,6 +324,8 @@ typedef struct RrcConfigurationReq_s { char *discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[MAX_NUM_CCs]; long discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[MAX_NUM_CCs]; long discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[MAX_NUM_CCs]; + //Nr secondary cell group SSB central frequency (for ENDC NSA) + int nr_scg_ssb_freq; } RrcConfigurationReq; #define MAX_NUM_NBIOT_CELEVELS 3 @@ -397,14 +400,22 @@ typedef struct NbIoTRrcConfigurationReq_s { // gNB: GNB_APP -> RRC messages typedef struct NRRrcConfigurationReq_s { - uint32_t cell_identity; - uint16_t tac; + uint64_t cell_identity; + uint32_t tac; uint16_t mcc[PLMN_LIST_MAX_SIZE]; uint16_t mnc[PLMN_LIST_MAX_SIZE]; uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; + uint8_t num_plmn; NR_ServingCellConfigCommon_t *scc; - int ssb_SubcarrierOffset; - int pdsch_AntennaPorts; + NR_ServingCellConfig_t *scd; + int ssb_SubcarrierOffset; + int sib1_tda; + int pdsch_AntennaPorts; + int pusch_AntennaPorts; + int minRXTXTIME; + int do_CSIRS; + int pusch_TargetSNRx10; + int pucch_TargetSNRx10; } gNB_RrcConfigurationReq; diff --git a/openair2/COMMON/rrm_config_structs.h b/openair2/COMMON/rrm_config_structs.h deleted file mode 100644 index 9d060d102d..0000000000 --- a/openair2/COMMON/rrm_config_structs.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/* - rrm_config_structs.h - ------------------- - AUTHOR : Linus GASSER modified by Lionel GAUTHIER Raymond KNOPP - COMPANY : EURECOM - EMAIL : linus.gasser@epfl.ch - EMAIL : lionel.gauthier@eurecom.fr - EMAIL : raymond.knopp@eurecom.fr - - - - ***************************************************************************/ -#ifdef OLD_RRC_CELLULAR -# ifndef __RRM_CONFIG_STRUCTS_H__ -# define __RRM_CONFIG_STRUCTS_H__ - -# include "platform_types.h" -# include "platform_constants.h" -# include "rrm_constants.h" -# include "rlc.h" - -typedef volatile struct { - uint32_t e_r; - int timer_poll; - int timer_poll_prohibit; - int timer_discard; - int timer_poll_periodic; - int timer_status_prohibit; - int timer_status_periodic; - int timer_rst; - int timer_mrw; - int missing_pdu_indicator; - uint32_t pdu_size; - // int in_sequence_delivery; // not implemented - uint8_t max_rst; - uint8_t max_dat; - uint16_t poll_pdu; - uint16_t poll_sdu; - uint8_t poll_window; - uint32_t tx_window_size; - uint32_t rx_window_size; - uint8_t max_mrw; - uint8_t last_transmission_pdu_poll_trigger; - uint8_t last_retransmission_pdu_poll_trigger; - enum RLC_SDU_DISCARD_MODE sdu_discard_mode; - uint32_t send_mrw; -} AM; - -typedef volatile struct { - uint32_t e_r; - uint32_t timer_discard; - uint32_t sdu_discard_mode; - uint32_t segmentation_indication; - uint32_t delivery_of_erroneous_sdu; -} TM; - -typedef volatile struct { - uint32_t e_r; - uint32_t timer_discard; - uint32_t sdu_discard_mode; -} UM; - -typedef volatile struct { - uint8_t logch_identity; - uint8_t mac_logch_priority; -} MAP_INFO; - -typedef volatile struct { - uint32_t rlc_mode; - AM am; - TM tm; - UM um; -} RLC_INFO; - -typedef volatile struct { - int header_compression_algorithm; -} PDCP_INFO; - - - - -typedef volatile struct { - rb_type_t rb_type; - RLC_INFO rlc_info; - PDCP_INFO pdcp_info; - uint16_t rb_id; - // Added for OPENAIR MAC - //LCHAN_DESC Lchan_desc; - -} RADIOBEARER; - - -typedef volatile struct { - int TIMER300; - int TIMER302; - int TIMER305; - int TIMER307; - int TIMER308; - int TIMER312; - int TIMER313; - int TIMER314; - int TIMER315; -} L3TIMERS_; - -typedef volatile struct { - int COUNTERN300; - int COUNTERN302; - int COUNTERN308; - int COUNTERN312; - int COUNTERN313; -} L3COUNTERS_; - - -typedef volatile struct { - int MaxNumRemote; - L3TIMERS_ Timers; - L3COUNTERS_ Counters; -} L3_; - - -typedef volatile struct { - uint8_t rrm_action; // ACTION_NULL,ADD,REMOVE,MODIFY - uint8_t rrm_element; // rb,trch,cctrch - uint8_t rrm_element_index; // rb/trch/cctrch index -} RRM_COMMAND_MT; - -typedef volatile struct { - uint8_t rrm_action; // ACTION_NULL,ADD,REMOVE,MODIFY - uint8_t mobile; - uint8_t rrm_element; // rb,trch,cctrch - uint8_t rrm_element_index; // rb/trch/cctrch index -} RRM_COMMAND_RG; - - -typedef volatile struct { - uint8_t nb_commands; - RRM_COMMAND_RG rrm_commands[JRRM_MAX_COMMANDS_PER_TRANSACTION]; - - - RADIOBEARER bearer[MAX_RB_RG]; - L3_ L3; - -} RG_CONFIG; - -typedef volatile struct { - uint8_t nb_commands; - RRM_COMMAND_MT rrm_commands[JRRM_MAX_COMMANDS_PER_TRANSACTION]; - - RADIOBEARER bearer[MAX_RB_MOBILE]; - L3_ L3; - -} MT_CONFIG; - -# ifdef NODE_RG -typedef volatile struct { - RG_CONFIG rg_config; - MT_CONFIG mt_config[MAX_MOBILES_PER_RG]; -} RRM_VARS; - -# else -/* NODE_RG */ -typedef volatile struct { - MT_CONFIG mt_config[MAX_MANAGED_RG_PER_MOBILE]; - - - -} RRM_VARS; -# endif -/* NODE_RG */ -//typedef MT_CONFIG MAIN_MOBILE ; -//typedef RG_CONFIG MAIN_RADIO_GATEWAY; - -# endif -#endif diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h index befab4ebdf..2151375686 100644 --- a/openair2/COMMON/s1ap_messages_types.h +++ b/openair2/COMMON/s1ap_messages_types.h @@ -155,6 +155,11 @@ typedef struct security_capabilities_s { uint16_t integrity_algorithms; } security_capabilities_t; +typedef struct nr_security_capabilities_s { + uint16_t encryption_algorithms; + uint16_t integrity_algorithms; +} nr_security_capabilities_t; + /* Provides the establishment cause for the RRC connection request as provided * by the upper layers. W.r.t. the cause value names: highPriorityAccess * concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for @@ -386,12 +391,18 @@ typedef struct s1ap_register_enb_req_s { uint8_t nb_mme; /* List of MME to connect to */ net_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS]; + uint16_t mme_port[S1AP_MAX_NB_MME_IP_ADDRESS]; uint8_t broadcast_plmn_num[S1AP_MAX_NB_MME_IP_ADDRESS]; uint8_t broadcast_plmn_index[S1AP_MAX_NB_MME_IP_ADDRESS][PLMN_LIST_MAX_SIZE]; /* Number of SCTP streams used for a mme association */ uint16_t sctp_in_streams; uint16_t sctp_out_streams; + uint16_t s1_setuprsp_wait_timer; + uint16_t s1_setupreq_wait_timer; + uint16_t s1_setupreq_count; + uint16_t sctp_req_timer; + uint16_t sctp_req_count; } s1ap_register_enb_req_t; //-------------------------------------------------------------------------------------------// @@ -537,6 +548,9 @@ typedef struct s1ap_initial_context_setup_req_s { uint8_t nb_of_e_rabs; /* list of e_rab to be setup by RRC layers */ e_rab_t e_rab_param[S1AP_MAX_E_RAB]; + + /* NR Security algorithms (if any, set to 0 if not present) */ + nr_security_capabilities_t nr_security_capabilities; } s1ap_initial_context_setup_req_t; typedef struct tai_plmn_identity_s { diff --git a/openair2/COMMON/tasks_def.h b/openair2/COMMON/tasks_def.h deleted file mode 100644 index 0fb1bd6b30..0000000000 --- a/openair2/COMMON/tasks_def.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -// This task is mandatory and must always be placed in first position -TASK_DEF(TASK_TIMER, TASK_PRIORITY_MAX, 10) - -// Other possible tasks in the process - -// Common tasks: - -/// Bearers Manager task -TASK_DEF(TASK_BM, TASK_PRIORITY_MED, 200) - -// eNodeB tasks and sub-tasks: - -/// Radio Resource Control task -TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200) - -// Define here for now -TASK_DEF(TASK_RRC_ENB_NB_IoT, TASK_PRIORITY_MED, 200) - -TASK_DEF(TASK_RRC_GNB, TASK_PRIORITY_MED, 200) - -/// S1ap task -/// RAL task for ENB -TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200) - -// UDP TASK -TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000) -// GTP_V1U task -TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000) -TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200) -TASK_DEF(TASK_CU_F1, TASK_PRIORITY_MED, 200) -TASK_DEF(TASK_DU_F1, TASK_PRIORITY_MED, 200) -/// M3ap task, acts as both source and target -TASK_DEF(TASK_M3AP, TASK_PRIORITY_MED, 200) -/// M3ap task, acts as both source and target -TASK_DEF(TASK_M3AP_MME, TASK_PRIORITY_MED, 200) -/// M3ap task, acts as both source and target -TASK_DEF(TASK_M3AP_MCE, TASK_PRIORITY_MED, 200) -/// M2ap task, acts as both source and target -TASK_DEF(TASK_M2AP_MCE, TASK_PRIORITY_MED, 200) -TASK_DEF(TASK_M2AP_ENB, TASK_PRIORITY_MED, 200) -/// X2ap task, acts as both source and target -TASK_DEF(TASK_X2AP, TASK_PRIORITY_MED, 200) -/// Sctp task (Used by both S1AP and X2AP) -TASK_DEF(TASK_SCTP, TASK_PRIORITY_MED, 200) -/// eNB APP task -TASK_DEF(TASK_ENB_APP, TASK_PRIORITY_MED, 200) -/// gNB APP task -TASK_DEF(TASK_GNB_APP, TASK_PRIORITY_MED, 200) -/// eNB Agent task -TASK_DEF(TASK_FLEXRAN_AGENT, TASK_PRIORITY_MED, 200) -TASK_DEF(TASK_PROTO_AGENT, TASK_PRIORITY_MED, 200) -// UE tasks and sub-tasks: - -/// Radio Resource Control task -TASK_DEF(TASK_RRC_UE, TASK_PRIORITY_MED, 200) -/// Non Access Stratum task -TASK_DEF(TASK_NAS_UE, TASK_PRIORITY_MED, 200) -TASK_DEF(TASK_RAL_UE, TASK_PRIORITY_MED, 200) - -//MESSAGE GENERATOR TASK -TASK_DEF(TASK_MSC, TASK_PRIORITY_MED, 200) - diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h index 8438fd1037..25600253a6 100644 --- a/openair2/COMMON/x2ap_messages_def.h +++ b/openair2/COMMON/x2ap_messages_def.h @@ -33,7 +33,7 @@ MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgT /* eNB application layer -> X2AP messages */ MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req) MESSAGE_DEF(X2AP_SUBFRAME_PROCESS , MESSAGE_PRIORITY_MED, x2ap_subframe_process_t , x2ap_subframe_process) - +MESSAGE_DEF(X2AP_RESET_REQ , MESSAGE_PRIORITY_MED, x2ap_reset_req_t , x2ap_reset_req) /* X2AP -> eNB application layer messages */ MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf) MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind) @@ -48,10 +48,19 @@ MESSAGE_DEF(X2AP_HANDOVER_CANCEL , MESSAGE_PRIORITY_MED, x2ap_han /* handover messages X2AP <-> S1AP */ MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t , x2ap_ue_context_release) -/*Senb bearer addition messages X2AP <-> RRC */ +/* Senb bearer addition messages X2AP <-> RRC */ MESSAGE_DEF(X2AP_SENB_ADDITION_REQ , MESSAGE_PRIORITY_MED, x2ap_senb_addition_req_t , x2ap_senb_addition_req) -/*SGnb bearer addition messages X2AP <-> RRC */ -MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_t , x2ap_ENDC_sgnb_addition_req) -MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_ACK_t , x2ap_ENDC_sgnb_addition_req_ACK) -MESSAGE_DEF(X2AP_ENDC_SGNB_RECONF_COMPLETE , MESSAGE_PRIORITY_MED, x2ap_ENDC_reconf_complete_t , x2ap_ENDC_sgnb_reconf_complete) +/* SGnb bearer addition messages X2AP <-> RRC */ +MESSAGE_DEF(X2AP_ENDC_SETUP_REQ , MESSAGE_PRIORITY_MED, x2ap_ENDC_setup_req_t , x2ap_ENDC_setup_req) +MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_t , x2ap_ENDC_sgnb_addition_req) +MESSAGE_DEF(X2AP_ENDC_SGNB_ADDITION_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_addition_req_ACK_t, x2ap_ENDC_sgnb_addition_req_ACK) +MESSAGE_DEF(X2AP_ENDC_SGNB_RECONF_COMPLETE , MESSAGE_PRIORITY_MED, x2ap_ENDC_reconf_complete_t , x2ap_ENDC_sgnb_reconf_complete) + +/* SGnb UE releases ('request' is for enb starting the process, 'required' for gnb) */ +MESSAGE_DEF(X2AP_ENDC_SGNB_RELEASE_REQUEST , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_release_request_t , x2ap_ENDC_sgnb_release_request) +MESSAGE_DEF(X2AP_ENDC_SGNB_RELEASE_REQUIRED , MESSAGE_PRIORITY_MED, x2ap_ENDC_sgnb_release_required_t, x2ap_ENDC_sgnb_release_required) + +/* ENDC timers' timeout X2AP <-> RRC */ +MESSAGE_DEF(X2AP_ENDC_DC_PREP_TIMEOUT , MESSAGE_PRIORITY_MED, x2ap_ENDC_dc_prep_timeout_t , x2ap_ENDC_dc_prep_timeout) +MESSAGE_DEF(X2AP_ENDC_DC_OVERALL_TIMEOUT , MESSAGE_PRIORITY_MED, x2ap_ENDC_dc_overall_timeout_t , x2ap_ENDC_dc_overall_timeout) diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index f0743e60a5..9339ab12f3 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -25,22 +25,36 @@ #include "s1ap_messages_types.h" #include "LTE_PhysCellId.h" +typedef enum { + X2AP_CAUSE_T_DC_PREP_TIMEOUT, + X2AP_CAUSE_T_DC_OVERALL_TIMEOUT, + X2AP_CAUSE_RADIO_CONNECTION_WITH_UE_LOST, +} x2ap_cause_t; + //-------------------------------------------------------------------------------------------// // Defines to access message fields. -#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req -#define X2AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_req -#define X2AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_resp -#define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req -#define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack -#define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf -#define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind -#define X2AP_UE_CONTEXT_RELEASE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ue_context_release -#define X2AP_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_cancel -#define X2AP_SENB_ADDITION_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_senb_addition_req -#define X2AP_ENDC_SGNB_ADDITION_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req -#define X2AP_ENDC_SGNB_ADDITION_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req_ACK -#define X2AP_ENDC_SGNB_RECONF_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_reconf_complete + +#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req +#define X2AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_req +#define X2AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_resp +#define X2AP_RESET_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_reset_req +#define X2AP_RESET_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_reset_resp +#define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req +#define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack +#define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf +#define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind +#define X2AP_UE_CONTEXT_RELEASE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ue_context_release +#define X2AP_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_cancel +#define X2AP_SENB_ADDITION_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_senb_addition_req +#define X2AP_ENDC_SGNB_ADDITION_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req +#define X2AP_ENDC_SGNB_ADDITION_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_addition_req_ACK +#define X2AP_ENDC_SGNB_RECONF_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_reconf_complete +#define X2AP_ENDC_SGNB_RELEASE_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_release_request +#define X2AP_ENDC_SGNB_RELEASE_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_sgnb_release_required +#define X2AP_ENDC_DC_PREP_TIMEOUT(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_dc_prep_timeout +#define X2AP_ENDC_DC_OVERALL_TIMEOUT(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_dc_overall_timeout +#define X2AP_ENDC_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ENDC_setup_req #define X2AP_MAX_NB_ENB_IP_ADDRESS 2 @@ -56,6 +70,14 @@ typedef struct x2ap_setup_resp_s { int num_cc; } x2ap_setup_resp_t; +typedef struct x2ap_reset_req_s { + uint32_t cause; +} x2ap_reset_req_t; + +typedef struct x2ap_reset_resp_s { + int dummy; +} x2ap_reset_resp_t; + /* X2AP UE CONTEXT RELEASE */ typedef struct x2ap_ue_context_release_s { /* used for X2AP->RRC in source and RRC->X2AP in target */ @@ -110,6 +132,8 @@ typedef struct x2ap_register_enb_req_s { * CC Params */ int16_t eutra_band[MAX_NUM_CCs]; + int32_t nr_band[MAX_NUM_CCs]; + int32_t nrARFCN[MAX_NUM_CCs]; uint32_t downlink_frequency[MAX_NUM_CCs]; int32_t uplink_frequency_offset[MAX_NUM_CCs]; uint32_t Nid_cell[MAX_NUM_CCs]; @@ -144,6 +168,8 @@ typedef struct x2ap_register_enb_req_s { /* timers (unit: millisecond) */ int t_reloc_prep; int tx2_reloc_overall; + int t_dc_prep; + int t_dc_overall; } x2ap_register_enb_req_t; typedef struct x2ap_subframe_process_s { @@ -288,10 +314,6 @@ typedef struct x2ap_senb_addition_req_s { }x2ap_senb_addition_req_t; - - - -//Panos: Have to see what should be the additional/different elements comparing to handover req ack typedef struct x2ap_senb_addition_req_ack_s { int MeNB_UE_X2_id; @@ -313,13 +335,20 @@ typedef struct x2ap_senb_addition_req_ack_s { } x2ap_senb_addition_req_ack_t; + +typedef struct x2ap_ENDC_setup_req_s { + uint32_t Nid_cell[MAX_NUM_CCs]; + int num_cc; + uint32_t servedNrCell_band[MAX_NUM_CCs]; +} x2ap_ENDC_setup_req_t; + typedef struct x2ap_ENDC_sgnb_addition_req_s { int ue_x2_id; LTE_PhysCellId_t target_physCellId; /* used for RRC->X2AP in source eNB */ int rnti; - security_capabilities_t security_capabilities; + nr_security_capabilities_t security_capabilities; /* SgNB Security Key */ uint8_t kgnb[32]; @@ -357,6 +386,8 @@ typedef struct x2ap_ENDC_sgnb_addition_req_ACK_s { int SgNB_ue_x2_id; + int gnb_x2_assoc_id; // to be stored in the rrc's ue context, used when sending 'sgnb reconfiguration complete' + /* used for X2AP->RRC in source eNB */ int rnti; @@ -384,16 +415,26 @@ typedef struct x2ap_ENDC_sgnb_addition_req_ACK_s { typedef struct x2ap_ENDC_reconf_complete_s { int MeNB_ue_x2_id; - int SgNB_ue_x2_id; - LTE_PhysCellId_t target_physCellId; - - x2ap_sgNB_reconf_response_information_t reconf_response; - - uint8_t rrc_buffer[4096 /* arbitrary, big enough */]; - int rrc_buffer_size; - + int gnb_x2_assoc_id; } x2ap_ENDC_reconf_complete_t; +typedef struct x2ap_ENDC_sgnb_release_request_s { + int rnti; + x2ap_cause_t cause; + int assoc_id; +} x2ap_ENDC_sgnb_release_request_t; + +typedef struct x2ap_ENDC_sgnb_release_required_s { + int gnb_rnti; +} x2ap_ENDC_sgnb_release_required_t; + +typedef struct x2ap_ENDC_dc_prep_timeout_s { + int rnti; +} x2ap_ENDC_dc_prep_timeout_t; + +typedef struct x2ap_ENDC_dc_overall_timeout_s { + int rnti; +} x2ap_ENDC_dc_overall_timeout_t; #endif /* X2AP_MESSAGES_TYPES_H_ */ diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index f1daacbb65..51e495b027 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -40,6 +40,11 @@ #include "common/utils/LOG/log.h" +#include + +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + /*Array containing the Agent-MAC interfaces*/ AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB]; @@ -53,10 +58,20 @@ struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB]; +/* Ringbuffer related to slice configuration if we need to wait for additional + * controller information */ +struct lfds700_ringbuffer_element *store_slice_config_array[NUM_MAX_ENB]; +struct lfds700_ringbuffer_state store_slice_config_ringbuffer_state[NUM_MAX_ENB]; +/* stores the (increasing) xid for messages to prevent double use */ +int xid = 50; + /* Ringbuffer-related to slice configuration */ struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB]; +/* a list of shared objects that are loaded into the user plane */ +SLIST_HEAD(flexran_so_handle, flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB]; + int flexran_agent_mac_stats_reply_ue(mid_t mod_id, Protocol__FlexUeStatsReport **ue_report, int n_ue, @@ -1363,6 +1378,19 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { &scrng, NULL); + struct lfds700_misc_prng_state sscrng; + i = posix_memalign((void **) &store_slice_config_array[mod_id], + LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, + sizeof(struct lfds700_ringbuffer_element) * num_elements); + AssertFatal(i == 0, + "posix_memalign(): could not allocate aligned memory\n"); + lfds700_ringbuffer_init_valid_on_current_logical_core( + &store_slice_config_ringbuffer_state[mod_id], + store_slice_config_array[mod_id], + num_elements, + &sscrng, + NULL); + struct lfds700_misc_prng_state uarng; i = posix_memalign((void **) &ue_assoc_array[mod_id], LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, @@ -1382,6 +1410,8 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0; } } + + SLIST_INIT(&flexran_handles[mod_id]); } /*********************************************** @@ -1659,6 +1689,8 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) free(dl_mac_config_array[mod_id]); lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL ); free(slice_config_array[mod_id]); + lfds700_ringbuffer_cleanup(&store_slice_config_ringbuffer_state[mod_id], NULL ); + free(store_slice_config_array[mod_id]); lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL ); free(ue_assoc_array[mod_id]); lfds700_misc_library_cleanup(); @@ -1698,7 +1730,81 @@ void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { flexran_agent_destroy_mac_slice_config(&helper); } -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) { +int check_scheduler(mid_t mod_id, char *s) { + if (!s) + return 1; + if (dlsym(NULL, s)) + return 1; + flexran_agent_so_handle_t *so = NULL; + SLIST_FOREACH(so, &flexran_handles[mod_id], entries) { + if (strcmp(so->name, s) == 0) + return 1; + } + return 0; +} + +void request_scheduler(mid_t mod_id, char *s, int xid) { + LOG_W(FLEXRAN_AGENT, + "unknown scheduler %s, requesting controller to send it\n", + s); + Protocol__FlexControlDelegationRequest *req = malloc(sizeof(Protocol__FlexControlDelegationRequest)); + DevAssert(req); + protocol__flex_control_delegation_request__init(req); + Protocol__FlexHeader *header = NULL; + int rc = flexran_create_header( + xid, PROTOCOL__FLEX_TYPE__FLPT_DELEGATE_REQUEST, &header); + AssertFatal(rc == 0, "%s(): cannot create header\n", __func__); + req->header = header; + req->delegation_type = PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER; + req->name = strdup(s); + + Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage)); + DevAssert(msg); + protocol__flexran_message__init(msg); + msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG; + msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; + msg->control_del_req_msg = req; + + int size = 0; + void *data = flexran_agent_pack_message(msg, &size); + if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_DEFAULT, data, size, 0) < 0) + LOG_E(FLEXRAN_AGENT, "%s(): error while sending message\n", __func__); +} + +Protocol__FlexranMessage *request_scheduler_timeout( + mid_t mod_id, + const Protocol__FlexranMessage *msg) { + const Protocol__FlexEnbConfigReply *ecr = msg->enb_config_reply_msg; + + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + + Protocol__FlexranMessage *smsg = NULL; + struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &smsg, &ls)) { + AssertFatal(msg == smsg, + "expected and returned enb_config_reply are not the same\n"); + AssertFatal(ecr->header->xid == smsg->enb_config_reply_msg->header->xid, + "expected and returned enb_config_reply are not the same\n"); + } else { + LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__); + } + /* call the helper so that scheduler names are correctly freed */ + helper_destroy_mac_slice_config(ecr->cell_config[0]->slice_config); + ecr->cell_config[0]->slice_config = NULL; + /* we should not call flexran_agent_destroy_enb_config_reply(smsg); since + * upon timer removal, this is automatically done */ + LOG_W(FLEXRAN_AGENT, + "remove stored slice config (xid %d) after timeout\n", + ecr->header->xid); + flexran_agent_destroy_timer(mod_id, ecr->header->xid); + return NULL; +} + +void prepare_update_slice_config(mid_t mod_id, + Protocol__FlexSliceConfig **slice_config, + int request_objects) { if (!*slice_config) return; /* just use the memory and set to NULL in original */ Protocol__FlexSliceConfig *sc = *slice_config; @@ -1709,6 +1815,63 @@ void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice lfds700_misc_prng_init(&ls); enum lfds700_misc_flag overwrite_occurred_flag; + int put_on_hold = 0; + if (request_objects + && sc->dl->scheduler + && !check_scheduler(mod_id, sc->dl->scheduler)) { + request_scheduler(mod_id, sc->dl->scheduler, xid++); + put_on_hold = 1; + } + for (int i = 0; request_objects && i < sc->dl->n_slices; ++i) { + Protocol__FlexSlice *sl = sc->dl->slices[i]; + if (sl->scheduler && !check_scheduler(mod_id, sl->scheduler)) { + request_scheduler(mod_id, sl->scheduler, xid++); + put_on_hold = 1; + } + } + if (put_on_hold) { + Protocol__FlexEnbConfigReply *reply = malloc(sizeof(Protocol__FlexEnbConfigReply)); + DevAssert(reply); + protocol__flex_enb_config_reply__init(reply); + /* use the last used xid so we can correlate answer and waiting config */ + int rc = flexran_create_header( + xid - 1, PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REPLY, &reply->header); + AssertFatal(rc == 0, "%s(): cannot create header\n", __func__); + reply->n_cell_config = 1; + reply->cell_config = malloc(sizeof(Protocol__FlexCellConfig *)); + DevAssert(reply->cell_config); + reply->cell_config[0] = malloc(sizeof(Protocol__FlexCellConfig)); + DevAssert(reply->cell_config[0]); + protocol__flex_cell_config__init(reply->cell_config[0]); + reply->cell_config[0]->slice_config = sc; + + Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage)); + DevAssert(msg); + protocol__flexran_message__init(msg); + msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG; + msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; + msg->enb_config_reply_msg = reply; + + Protocol__FlexEnbConfigReply *o; + lfds700_ringbuffer_write(&store_slice_config_ringbuffer_state[mod_id], + NULL, + (void *)msg, + &overwrite_occurred_flag, + NULL, + (void **) &o, + &ls); + AssertFatal(overwrite_occurred_flag == LFDS700_MISC_FLAG_LOWERED, + "unhandled: stored slice config for controller has been overwritten\n"); + + flexran_agent_create_timer(mod_id, + 3000, + FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, + xid - 1, + request_scheduler_timeout, + msg); /* need reply for xid */ + return; + } + Protocol__FlexSliceConfig *overwritten_sc; lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id], NULL, @@ -1756,6 +1919,69 @@ void flexran_agent_slice_update(mid_t mod_id) { apply_update_dl_slice_config(mod_id, sc->dl); apply_update_ul_slice_config(mod_id, sc->ul); helper_destroy_mac_slice_config(sc); + + flexran_agent_so_handle_t *so = NULL; + flexran_agent_so_handle_t *prev = NULL; // the previous to current element, if we delete in order to go back + //SLIST_FOREACH(so, &flexran_handles[mod_id], entries) + for(so = flexran_handles[mod_id].slh_first; so;) { + char *name = so->name; + int in_use = strcmp(flexran_get_dl_scheduler_name(mod_id), name) == 0 + || strcmp(flexran_get_ul_scheduler_name(mod_id), name) == 0; + Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id); + if (!in_use && dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + int n = flexran_get_num_dl_slices(mod_id); + for (int i = 0; i < n; ++i) { + Protocol__FlexSlice s; + /* NONE so it won't do any allocations */ + flexran_get_dl_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None); + if (strcmp(s.scheduler, name) == 0) { + in_use = 1; + break; + } + } + } + Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id); + if (!in_use && ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + int n = flexran_get_num_ul_slices(mod_id); + for (int i = 0; i < n; ++i) { + Protocol__FlexSlice s; + /* NONE so it won't do any allocations */ + flexran_get_ul_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None); + if (strcmp(s.scheduler, name) == 0) { + in_use = 1; + break; + } + } + } + if (!in_use) { + char s[512]; + int rc = flexran_agent_map_name_to_delegated_object(mod_id, so->name, s, 512); + LOG_W(FLEXRAN_AGENT, + "removing %s (library handle %p) since it is not used in the user " + "plane anymore\n", + s, + so->dl_handle); + dlclose(so->dl_handle); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", so->name); + } else { + int rc = remove(s); + if (rc < 0) + LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", s, strerror(errno)); + } + free (so->name); + if (!prev) { //it's the head, start over + SLIST_REMOVE_HEAD(&flexran_handles[mod_id], entries); + so = flexran_handles[mod_id].slh_first; + } else { + SLIST_REMOVE(&flexran_handles[mod_id], so, flexran_agent_so_handle_s, entries); + so = prev->entries.sle_next; + } + } else { + prev = so; + so = so->entries.sle_next; + } + } } Protocol__FlexUeConfig *ue_config = NULL; @@ -1765,3 +1991,92 @@ void flexran_agent_slice_update(mid_t mod_id) { free(ue_config); } } + +void flexran_agent_mac_inform_delegation(mid_t mod_id, + Protocol__FlexControlDelegation *cdm) { + LOG_W(FLEXRAN_AGENT, + "received FlexControlDelegation message for object '%s' xid %d\n", + cdm->name, + cdm->header->xid); + if (cdm->header->xid < xid - 1) { + LOG_I(FLEXRAN_AGENT, + "waiting for %d more messages (up to xid %d)\n", + xid - 1 - cdm->header->xid, + xid - 1); + return; + } + /* should receive up to xid - 1, otherwise it means there was no request */ + AssertFatal(xid > cdm->header->xid, + "received control delegation with xid %d that we never requested " + "(last request %d)\n", + cdm->header->xid, + xid - 1); + + /* Load the library so the user plane can search it */ + char s[512]; + int rc = flexran_agent_map_name_to_delegated_object(mod_id, cdm->name, s, 512); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", cdm->name); + return; + } + /* TODO where to unload/save handle?? */ + void *h = dlopen(s, RTLD_NOW); + if (!h) { + LOG_E(FLEXRAN_AGENT, "dlopen(): %s\n", dlerror()); + return; + } + LOG_I(FLEXRAN_AGENT, "library handle %p\n", h); + + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + + Protocol__FlexranMessage *msg = NULL; + struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &msg, &ls) == 0) { + LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__); + return; + } + AssertFatal(cdm->header->xid == msg->enb_config_reply_msg->header->xid, + "expected and retrieved xid of stored slice configuration does " + "not match (expected %d, retrieved %d)\n", + cdm->header->xid, + msg->enb_config_reply_msg->header->xid); + + /* Since we recover, stop the timeout */ + rc = flexran_agent_destroy_timer(mod_id, cdm->header->xid); + + prepare_update_slice_config( + mod_id, + &msg->enb_config_reply_msg->cell_config[0]->slice_config, + 0 /* don't do a request */); + /* we should not call flexran_agent_destroy_enb_config_reply(smsg); since + * upon timer removal, this is automatically done. + * prepare_update_slice_config() takes ownership of the slice config, it is + * freed inside */ + + flexran_agent_so_handle_t *so = malloc(sizeof(flexran_agent_so_handle_t)); + DevAssert(so); + so->name = strdup(cdm->name); + DevAssert(so->name); + so->dl_handle = h; + SLIST_INSERT_HEAD(&flexran_handles[mod_id], so, entries); +} + +void flexran_agent_mac_fill_loaded_mac_objects( + mid_t mod_id, + Protocol__FlexEnbConfigReply *reply) { + int n = 0; + flexran_agent_so_handle_t *so = NULL; + SLIST_FOREACH(so, &flexran_handles[mod_id], entries) + ++n; + reply->n_loadedmacobjects = n; + reply->loadedmacobjects = calloc(n, sizeof(char *)); + if (!reply->loadedmacobjects) { + reply->n_loadedmacobjects = 0; + return; + } + n = 0; + SLIST_FOREACH(so, &flexran_handles[mod_id], entries) + reply->loadedmacobjects[n++] = so->name; +} diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h index 5a8d4f31aa..18e567c061 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h @@ -39,6 +39,12 @@ // for flexran_agent_get_mac_xface() #include "flexran_agent_extern.h" +/* Type for a list of shared objects used in the user plane (schedulers) */ +typedef struct flexran_agent_so_handle_s { + char *name; // name of the object + void *dl_handle; // handle of associated objects + SLIST_ENTRY (flexran_agent_so_handle_s) entries; +} flexran_agent_so_handle_t; /* Initialization function for the agent structures etc */ void flexran_agent_init_mac_agent(mid_t mod_id); @@ -117,7 +123,9 @@ void flexran_agent_slice_update(mid_t mod_id); /* marks slice_config so that it can be applied later. Takes ownership of the * FlexSliceConfig message */ -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice); +void prepare_update_slice_config(mid_t mod_id, + Protocol__FlexSliceConfig **slice, + int request_objects); /* inserts a new ue_config into the structure keeping ue to slice association * updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */ @@ -127,4 +135,13 @@ void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_con * flexran_agent_fill_mac_cell_config() */ void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf); +/* information about a new (potentially relevant) control delegation message */ +void flexran_agent_mac_inform_delegation(mid_t mod_id, + Protocol__FlexControlDelegation *cdm); + +/* fill the enb_config_reply with the shared objects in use by the MAC sublayer */ +void flexran_agent_mac_fill_loaded_mac_objects( + mid_t mod_id, + Protocol__FlexEnbConfigReply *reply); + #endif diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 93de0b11ec..e05fa98854 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -33,6 +33,12 @@ #include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_slice_verification.h" +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + +extern SLIST_HEAD(flexran_so_handle, + flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB]; + Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message, Protocol__FlexranMessage *old_message) { @@ -1025,6 +1031,19 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { } +void *search_so(mid_t mod_id, char *name) { + if (!name) // no name -> nothing to return, so use NULL for executable + return NULL; + if (dlsym(NULL, name)) // found it in executable + return NULL; + flexran_agent_so_handle_t *so = NULL; + SLIST_FOREACH(so, &flexran_handles[mod_id], entries) { + if (strcmp(so->name, name) == 0) + return so->dl_handle; + } + return NULL; +} + void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET && !s->label && !s->scheduler) { @@ -1033,8 +1052,12 @@ void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { if (!rc) LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); } else { - LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id); - const int rc = flexran_create_dl_slice(mod_id, s); + void *lib = search_so(mod_id, s->scheduler); + LOG_I(FLEXRAN_AGENT, + "updating DL slice ID %d (library handle %p)\n", + s->id, + lib); + const int rc = flexran_create_dl_slice(mod_id, s, lib); if (rc < 0) LOG_W(FLEXRAN_AGENT, "error while update slice ID %d: flexran_create_dl_slice() -> %d\n", @@ -1050,8 +1073,12 @@ void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) { if (!rc) LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); } else { - LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id); - const int rc = flexran_create_ul_slice(mod_id, s); + void *lib = search_so(mod_id, s->scheduler); + LOG_I(FLEXRAN_AGENT, + "updating UL slice ID %d (library handle %p)\n", + s->id, + lib); + const int rc = flexran_create_ul_slice(mod_id, s, lib); if (rc < 0) LOG_W(FLEXRAN_AGENT, "error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n", @@ -1099,8 +1126,12 @@ void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *d LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); return; } - LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler); - const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler); + void *lib = search_so(mod_id, dl->scheduler); + LOG_I(FLEXRAN_AGENT, + "loading DL new scheduling algorithm '%s' (library handle %p)\n", + dl->scheduler, + lib); + const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler, lib); if (rc < 0) { LOG_E(FLEXRAN_AGENT, "error while updating scheduling algorithm: " @@ -1147,8 +1178,12 @@ void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *u LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); return; } - LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler); - const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler); + void *lib = search_so(mod_id, ul->scheduler); + LOG_I(FLEXRAN_AGENT, + "loading new UL scheduling algorithm '%s' (library handle %p)\n", + ul->scheduler, + lib); + const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler, lib); if (rc < 0) { LOG_E(FLEXRAN_AGENT, "error while updating scheduling algorithm: " diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h index 9db5d61a11..d6dd6e3b6f 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h @@ -51,8 +51,6 @@ typedef struct { pthread_mutex_t *mutex; } mac_stats_updates_context_t; -/*Array holding the last stats reports for each eNB. Used for continuous reporting*/ -mac_stats_updates_context_t mac_stats_context[NUM_MAX_ENB]; /*Functions to initialize and destroy the struct required for the *continuous stats update report*/ diff --git a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_defs.h b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_defs.h index 5f6432732f..a9236af80b 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_defs.h +++ b/openair2/ENB_APP/CONTROL_MODULES/RRC/flexran_agent_rrc_defs.h @@ -49,8 +49,6 @@ typedef struct /*To Be Extended*/ }rrc_meas_stats; -/* RRC CMI statistics */ -rrc_meas_stats * meas_stats; /* FLEXRAN AGENT-RRC Interface */ diff --git a/openair2/ENB_APP/L1_paramdef.h b/openair2/ENB_APP/L1_paramdef.h index 72e77c3800..c4e6670ea3 100644 --- a/openair2/ENB_APP/L1_paramdef.h +++ b/openair2/ENB_APP/L1_paramdef.h @@ -61,6 +61,7 @@ #define CONFIG_STRING_L1_PRACH_DTX_EMTC3_THRESHOLD "prach_dtx_emtc3_threshold" #define CONFIG_STRING_L1_PUCCH1_DTX_EMTC3_THRESHOLD "pucch1_dtx_emtc3_threshold" #define CONFIG_STRING_L1_PUCCH1AB_DTX_EMTC3_THRESHOLD "pucch1ab_dtx_emtc3_threshold" +#define CONFIG_STRING_L1_PUSCH_SIGNAL_THRESHOLD "pusch_signal_threshold" /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ /* L1 configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -89,7 +90,8 @@ {CONFIG_STRING_L1_PUCCH1AB_DTX_EMTC2_THRESHOLD, NULL, 0, iptr:NULL, defintval:4, TYPE_INT, 0}, \ {CONFIG_STRING_L1_PRACH_DTX_EMTC3_THRESHOLD, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ {CONFIG_STRING_L1_PUCCH1_DTX_EMTC3_THRESHOLD, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \ - {CONFIG_STRING_L1_PUCCH1AB_DTX_EMTC3_THRESHOLD, NULL, 0, iptr:NULL, defintval:4, TYPE_INT, 0} \ +{CONFIG_STRING_L1_PUCCH1AB_DTX_EMTC3_THRESHOLD, NULL, 0, iptr:NULL, defintval:4, TYPE_INT, 0}, \ +{CONFIG_STRING_L1_PUSCH_SIGNAL_THRESHOLD, NULL, 0, iptr:NULL, defintval:635, TYPE_INT, 0} \ } #define L1_CC_IDX 0 #define L1_TRANSPORT_N_PREFERENCE_IDX 1 @@ -115,6 +117,7 @@ #define L1_PRACH_DTX_EMTC3_THRESHOLD_IDX 21 #define L1_PUCCH1_DTX_EMTC3_THRESHOLD_IDX 22 #define L1_PUCCH1AB_DTX_EMTC3_THRESHOLD_IDX 23 +#define L1_PUSCH_SIGNAL_THRESHOLD_IDX 24 /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/ENB_APP/MACRLC_paramdef.h b/openair2/ENB_APP/MACRLC_paramdef.h index fcee6142f0..11cbe445b8 100644 --- a/openair2/ENB_APP/MACRLC_paramdef.h +++ b/openair2/ENB_APP/MACRLC_paramdef.h @@ -56,10 +56,14 @@ #define CONFIG_STRING_MACRLC_LOCAL_S_PORTD "local_s_portd" #define CONFIG_STRING_MACRLC_REMOTE_S_PORTD "remote_s_portd" #define CONFIG_STRING_MACRLC_SCHED_MODE "scheduler_mode" -#define CONFIG_MACRLC_PUSCH10xSNR "puSch10xSnr" -#define CONFIG_MACRLC_PUCCH10xSNR "puCch10xSnr" +#define CONFIG_STRING_MACRLC_PUSCH10xSNR "puSch10xSnr" +#define CONFIG_STRING_MACRLC_PUCCH10xSNR "puCch10xSnr" #define CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO "default_sched_dl_algo" - +#define CONFIG_STRING_MACRLC_UE_MULTIPLE_MAX "ue_multiple_max" +#define CONFIG_STRING_MACRLC_USE_MCS_OFFSET "use_mcs_offset" +#define CONFIG_STRING_MACRLC_BLER_TARGET_LOWER "bler_target_lower" +#define CONFIG_STRING_MACRLC_BLER_TARGET_UPPER "bler_target_upper" +#define CONFIG_STRING_MACRLC_MAX_UL_RB_INDEX "max_ul_rb_index" /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* MacRLC configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -83,10 +87,15 @@ {CONFIG_STRING_MACRLC_LOCAL_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \ {CONFIG_STRING_MACRLC_REMOTE_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \ {CONFIG_STRING_MACRLC_SCHED_MODE, NULL, 0, strptr:NULL, defstrval:"default", TYPE_STRING, 0}, \ -{CONFIG_MACRLC_PUSCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ -{CONFIG_MACRLC_PUCCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ -{CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO, NULL, 0, strptr:NULL, defstrval:"round_robin_dl", TYPE_STRING, 0}, \ -} +{CONFIG_STRING_MACRLC_PUSCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_PUCCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO, NULL, 0, strptr:NULL, defstrval:"round_robin_dl", TYPE_STRING, 0}, \ +{CONFIG_STRING_MACRLC_UE_MULTIPLE_MAX, NULL, 0, iptr:NULL, defintval:4, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_USE_MCS_OFFSET, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_BLER_TARGET_LOWER, NULL, 0, dblptr:NULL, defdblval:.5, TYPE_DOUBLE, 0}, \ +{CONFIG_STRING_MACRLC_BLER_TARGET_UPPER, NULL, 0, dblptr:NULL, defdblval:2, TYPE_DOUBLE, 0}, \ +{CONFIG_STRING_MACRLC_MAX_UL_RB_INDEX, NULL, 0, iptr:NULL, defintval:22, TYPE_INT, 0}} + #define MACRLC_CC_IDX 0 #define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1 #define MACRLC_LOCAL_N_IF_NAME_IDX 2 @@ -108,6 +117,11 @@ #define MACRLC_PUSCH10xSNR_IDX 18 #define MACRLC_PUCCH10xSNR_IDX 19 #define MACRLC_DEFAULT_SCHED_DL_ALGO_IDX 20 +#define MACRLC_UE_MULTIPLE_MAX_IDX 21 +#define MACRLC_USE_MCS_OFFSET_IDX 22 +#define MACRLC_BLER_TARGET_LOWER_IDX 23 +#define MACRLC_BLER_TARGET_UPPER_IDX 24 +#define MACRLC_MAX_UL_RB_INDEX_IDX 25 /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto index ef0eea3bd2..a646a978a9 100644 --- a/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto +++ b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto @@ -3,4 +3,25 @@ package protocol; enum flex_control_delegation_type { FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation + FLCDT_AGENT_CONTROL_APP = 2; // Generic control application +} + +message flex_agent_reconfiguration_system { + optional string system = 1; + repeated flex_agent_reconfiguration_subsystem subsystems = 2; +} + +message flex_agent_reconfiguration_subsystem { + optional string name = 1; // Name of the object (app name or user plane object) + optional string behavior = 2; // For an app: a callback in a shared library. For any other subsystem: an object name (shared library) with defined syntax. + map params = 3; // Param configurations depending on callback/shared library above. +} + +message flex_agent_reconfiguration_param { + oneof param { + int32 integer = 1; + float floating = 2; + bool boolean = 3; + string str = 4; + } } diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index 3b47ff263b..cec7f84b6e 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -7,6 +7,7 @@ import "time_common.proto"; import "config_messages.proto"; import "controller_commands.proto"; import "config_common.proto"; +import "control_delegation.proto"; message flexran_message { optional flexran_direction msg_dir = 100; @@ -32,6 +33,7 @@ message flexran_message { flex_ul_mac_config ul_mac_config_msg = 19; flex_disconnect disconnect_msg = 20; flex_ho_command ho_command_msg = 21; + flex_control_delegation_request control_del_req_msg = 22; } } @@ -157,6 +159,8 @@ message flex_enb_config_reply { repeated flex_cell_config cell_config = 3; optional uint32 device_spec = 4; optional flex_s1ap_config s1ap = 5; + repeated string loadedApps = 6; + repeated string loadedMacObjects = 7; } message flex_ue_config_request { @@ -225,11 +229,17 @@ message flex_ue_state_change { message flex_control_delegation { optional flex_header header = 1; - optional uint32 delegation_type = 2; // Bitmap of FLCDT_* flags + optional flex_control_delegation_type delegation_type = 2; // The delegated object type, decides about further processing optional bytes payload = 3; // Byte array of shared lib containing the delegated functions optional string name = 4; // The delegated functions names ordered based on bitmap flags } +message flex_control_delegation_request { + optional flex_header header = 1; + optional flex_control_delegation_type delegation_type = 2; + optional string name = 4; +} + // // Agent reconfiguration message // @@ -237,6 +247,7 @@ message flex_control_delegation { message flex_agent_reconfiguration { optional flex_header header = 1; optional string policy = 2; // The policy changes using YAML syntax in string format + repeated flex_agent_reconfiguration_system systems = 3; // The policy changes. } // Extensions of the echo request and reply diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto index 41b2b37f7a..5e224f64f7 100644 --- a/openair2/ENB_APP/MESSAGES/V2/header.proto +++ b/openair2/ENB_APP/MESSAGES/V2/header.proto @@ -44,5 +44,6 @@ enum flex_type { FLPT_RECONFIGURE_AGENT = 16; FLPT_RRC_TRIGGERING = 17; FLPT_UL_MAC_CONFIG = 18; + FLPT_DELEGATE_REQUEST = 22; } diff --git a/openair2/ENB_APP/NB_IoT_interface.c b/openair2/ENB_APP/NB_IoT_interface.c index 7355233d71..8fc6de78af 100644 --- a/openair2/ENB_APP/NB_IoT_interface.c +++ b/openair2/ENB_APP/NB_IoT_interface.c @@ -35,6 +35,9 @@ #define NBIOT_INTERFACE_SOURCE #include "NB_IoT_interface.h" +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + diff --git a/openair2/ENB_APP/NB_IoT_interface.h b/openair2/ENB_APP/NB_IoT_interface.h index b3454b077b..c13f6dd1cb 100644 --- a/openair2/ENB_APP/NB_IoT_interface.h +++ b/openair2/ENB_APP/NB_IoT_interface.h @@ -31,6 +31,7 @@ #define NBIOT_MODULENAME "NB_IoT" +#include "common/ran_context.h" typedef void(*RCConfig_NbIoT_f_t)(RAN_CONTEXT_t *RC); #define NBIOT_RCCONFIG_FNAME "RCConfig_NbIoT" diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 1d001022d2..2e6c94540d 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -53,7 +53,6 @@ #include "openair1/PHY/INIT/phy_init.h" extern unsigned char NB_eNB_INST; -#include extern RAN_CONTEXT_t RC; # define ENB_REGISTER_RETRY_DELAY 10 @@ -70,7 +69,7 @@ extern RAN_CONTEXT_t RC; // for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) { // { // -// //msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ); +// //msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, S1AP_REGISTER_ENB_REQ); // //RCconfig_S1(msg_p, enb_id); // // if (enb_id == 0) RCconfig_gtpu(); @@ -93,14 +92,14 @@ static uint32_t eNB_app_register_m2(uint32_t enb_id_start, uint32_t enb_id_end) MessageDef *msg_p; uint32_t register_enb_m2_pending = 0; -// msg_p = itti_alloc_new_message (TASK_ENB_APP,MESSAGE_TEST ); +// msg_p = itti_alloc_new_message (TASK_ENB_APP, 0,MESSAGE_TEST ); // itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); LOG_D(ENB_APP,"Register ...\n"); for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) { { - msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_REGISTER_ENB_REQ); + msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, M2AP_REGISTER_ENB_REQ); RCconfig_M2(msg_p, enb_id); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); register_enb_m2_pending++; @@ -115,28 +114,28 @@ static uint32_t eNB_app_register_m2(uint32_t enb_id_start, uint32_t enb_id_end) static uint32_t eNB_app_handle_m2ap_mbms_scheduling_information(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SCHEDULING_INFORMATION_RESP); + msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, M2AP_MBMS_SCHEDULING_INFORMATION_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; } static uint32_t eNB_app_handle_m2ap_mbms_session_start_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_START_RESP); + msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, M2AP_MBMS_SESSION_START_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; } static uint32_t eNB_app_handle_m2ap_mbms_session_stop_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_STOP_RESP); + msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, M2AP_MBMS_SESSION_STOP_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; } static uint32_t eNB_app_handle_m2ap_mbms_session_update_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_ENB_APP, M2AP_MBMS_SESSION_UPDATE_RESP); + msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, M2AP_MBMS_SESSION_UPDATE_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; } @@ -155,7 +154,7 @@ static uint32_t eNB_app_register(ngran_node_t node_type,uint32_t enb_id_start, u if (NODE_IS_DU(node_type)) { // F1AP registration // configure F1AP here for F1C LOG_I(ENB_APP,"ngran_eNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); - msg_p = itti_alloc_new_message (TASK_ENB_APP, F1AP_SETUP_REQ); + msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, F1AP_SETUP_REQ); RCconfig_DU_F1(msg_p, enb_id); LOG_I(ENB_APP,"[eNB %d] eNB_app_register via F1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id)); @@ -164,7 +163,7 @@ static uint32_t eNB_app_register(ngran_node_t node_type,uint32_t enb_id_start, u } else { // S1AP registration /* note: there is an implicit relationship between the data structure and the message name */ - msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ); + msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, S1AP_REGISTER_ENB_REQ); RCconfig_S1(msg_p, enb_id); if (enb_id == 0) RCconfig_gtpu(); @@ -191,7 +190,7 @@ static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end) for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) { { - msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ); + msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, X2AP_REGISTER_ENB_REQ); RCconfig_X2(msg_p, enb_id); itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); register_enb_x2_pending++; @@ -244,10 +243,12 @@ void *eNB_app_task(void *args_p) { } + LOG_I(ENB_APP,"TASK_ENB_APP is ready\n"); + do { // Wait for a message itti_receive_msg (TASK_ENB_APP, &msg_p); - instance = ITTI_MSG_INSTANCE (msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: @@ -266,7 +267,7 @@ void *eNB_app_task(void *args_p) { case S1AP_REGISTER_ENB_CNF: AssertFatal(!NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received S1AP_REGISTER_ENB_CNF\n"); if (EPC_MODE_ENABLED) { - LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_I(ENB_APP, "[eNB %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), S1AP_REGISTER_ENB_CNF(msg_p).nb_mme); register_enb_pending--; @@ -280,7 +281,7 @@ void *eNB_app_task(void *args_p) { if (registered_enb == enb_nb) { /* If all eNB are registered, start L2L1 task */ MessageDef *msg_init_p; - msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE); + msg_init_p = itti_alloc_new_message (TASK_ENB_APP, 0, INITIALIZE_MESSAGE); itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); } else { LOG_W(ENB_APP, " %d eNB not associated with a MME, retrying registration in %d seconds ...\n", @@ -323,7 +324,7 @@ void *eNB_app_task(void *args_p) { /* If all eNB cells are registered, start L2L1 task */ MessageDef *msg_init_p; - msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE); + msg_init_p = itti_alloc_new_message (TASK_ENB_APP, 0, INITIALIZE_MESSAGE); itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); } else { @@ -347,7 +348,7 @@ void *eNB_app_task(void *args_p) { case S1AP_DEREGISTERED_ENB_IND: if (EPC_MODE_ENABLED) { - LOG_W(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_W(ENB_APP, "[eNB %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme); /* TODO handle recovering of registration */ } @@ -380,13 +381,13 @@ void *eNB_app_task(void *args_p) { break; case X2AP_DEREGISTERED_ENB_IND: - LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_W(ENB_APP, "[eNB %ld] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p), X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2); /* TODO handle recovering of registration */ break; case X2AP_REGISTER_ENB_CNF: - LOG_I(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_I(ENB_APP, "[eNB %ld] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p), X2AP_REGISTER_ENB_CNF(msg_p).nb_x2); DevAssert(x2_register_enb_pending > 0); x2_register_enb_pending--; @@ -422,13 +423,13 @@ void *eNB_app_task(void *args_p) { break; case M2AP_DEREGISTERED_ENB_IND: - LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_W(ENB_APP, "[eNB %ld] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p), M2AP_DEREGISTERED_ENB_IND(msg_p).nb_m2); /* TODO handle recovering of registration */ break; case M2AP_REGISTER_ENB_CNF: - LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_W(ENB_APP, "[eNB %ld] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p), M2AP_REGISTER_ENB_CNF(msg_p).nb_m2); DevAssert(m2_register_enb_pending > 0); m2_register_enb_pending--; @@ -485,7 +486,7 @@ void *eNB_app_task(void *args_p) { // /* If all eNB cells are registered, start L2L1 task */ // MessageDef *msg_init_p; - // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE); + // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, 0, INITIALIZE_MESSAGE); // itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); // } else { @@ -508,15 +509,15 @@ void *eNB_app_task(void *args_p) { case M2AP_MBMS_SCHEDULING_INFORMATION: LOG_I(ENB_APP,"M2AP_SCHEDULING_INFORMATION received\n"); - eNB_app_handle_m2ap_mbms_scheduling_information(ITTI_MESSAGE_GET_INSTANCE(msg_p)); + eNB_app_handle_m2ap_mbms_scheduling_information(ITTI_MSG_DESTINATION_INSTANCE(msg_p)); break; case M2AP_MBMS_SESSION_START_REQ: LOG_I(ENB_APP,"M2AP_MBMS_SESSION_START_REQ received\n"); - eNB_app_handle_m2ap_mbms_session_start_req(ITTI_MESSAGE_GET_INSTANCE(msg_p)); + eNB_app_handle_m2ap_mbms_session_start_req(ITTI_MSG_DESTINATION_INSTANCE(msg_p)); break; case M2AP_MBMS_SESSION_STOP_REQ: LOG_I(ENB_APP,"M2AP_MBMS_SESSION_STOP_REQ received\n"); - eNB_app_handle_m2ap_mbms_session_stop_req(ITTI_MESSAGE_GET_INSTANCE(msg_p)); + eNB_app_handle_m2ap_mbms_session_stop_req(ITTI_MSG_DESTINATION_INSTANCE(msg_p)); break; case M2AP_RESET: LOG_I(ENB_APP,"M2AP_RESET received\n"); @@ -529,7 +530,7 @@ void *eNB_app_task(void *args_p) { break; case M2AP_ERROR_INDICATION: LOG_I(ENB_APP,"M2AP_MBMS_SESSION_UPDATE_REQ\n"); - eNB_app_handle_m2ap_mbms_session_update_req(ITTI_MESSAGE_GET_INSTANCE(msg_p)); + eNB_app_handle_m2ap_mbms_session_update_req(ITTI_MSG_DESTINATION_INSTANCE(msg_p)); break; case M2AP_MBMS_SERVICE_COUNTING_REQ: LOG_I(ENB_APP,"M2AP_MBMS_SERVICE_COUNTING_REQ\n"); diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 4c6a7885c3..4751596931 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -57,12 +57,15 @@ #include "enb_paramdef.h" #include "proto_agent.h" #include "executables/thread-common.h" +#include extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw); extern uint32_t to_earfcn_UL(int eutra_bandP, uint32_t ul_CarrierFreq, uint32_t bw); extern char *parallel_config; extern char *worker_config; +RAN_CONTEXT_t RC; + void RCconfig_flexran() { /* get number of eNBs */ paramdef_t ENBSParams[] = ENBSPARAMS_DESC; @@ -121,15 +124,14 @@ void RCconfig_L1(void) { RC.nb_L1_CC[j] = *(L1_ParamList.paramarray[j][L1_CC_IDX].uptr); if (RC.eNB[j] == NULL) { - RC.eNB[j] = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB *)); + RC.eNB[j] = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB *)); LOG_I(PHY,"RC.eNB[%d] = %p\n",j,RC.eNB[j]); memset(RC.eNB[j],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB *)); } for (i=0; iMod_id = j; RC.eNB[j][i]->CC_id = i; @@ -170,6 +172,10 @@ void RCconfig_L1(void) { RC.eNB[j][0]->pucch1_DTX_threshold_emtc[ce_level] = *(L1_ParamList.paramarray[j][L1_PUCCH1_DTX_EMTC0_THRESHOLD_IDX+ce_level].iptr); RC.eNB[j][0]->pucch1ab_DTX_threshold_emtc[ce_level] = *(L1_ParamList.paramarray[j][L1_PUCCH1AB_DTX_EMTC0_THRESHOLD_IDX+ce_level].iptr); } + + + RC.eNB[j][0]->pusch_signal_threshold = *(L1_ParamList.paramarray[j][L1_PUSCH_SIGNAL_THRESHOLD_IDX].iptr); + LOG_I(ENB_APP,"PUSCH singal threshold = %d \n",RC.eNB[j][0]->pusch_signal_threshold); }// j=0..num_inst LOG_I(ENB_APP,"Initializing northbound interface for L1\n"); @@ -214,13 +220,26 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) { for (j = 0; j < RC.nb_macrlc_inst; j++) { RC.mac[j]->puSch10xSnr = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCH10xSNR_IDX ].iptr); RC.mac[j]->puCch10xSnr = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCH10xSNR_IDX ].iptr); + RC.mac[j]->ue_multiple_max = *(MacRLC_ParamList.paramarray[j][MACRLC_UE_MULTIPLE_MAX_IDX ].iptr); + RC.mac[j]->use_mcs_offset = *(MacRLC_ParamList.paramarray[j][MACRLC_USE_MCS_OFFSET_IDX ].iptr); + RC.mac[j]->bler_lower = *(MacRLC_ParamList.paramarray[j][MACRLC_BLER_TARGET_LOWER_IDX ].dblptr); + RC.mac[j]->bler_upper = *(MacRLC_ParamList.paramarray[j][MACRLC_BLER_TARGET_UPPER_IDX ].dblptr); + RC.mac[j]->max_ul_rb_index = *(MacRLC_ParamList.paramarray[j][MACRLC_MAX_UL_RB_INDEX_IDX ].iptr); RC.nb_mac_CC[j] = *(MacRLC_ParamList.paramarray[j][MACRLC_CC_IDX].iptr); - + LOG_I(ENB_APP,"MAC instance %d parameters : pusch_snr %lf, pucch_snr %lf, ue_multiple_max %d, use_mcs_offset %d, bler_lower %lf, bler_upper %lf,max_ul_rb_index %d\n", + j, + RC.mac[j]->puSch10xSnr/10.0, + RC.mac[j]->puCch10xSnr/10.0, + RC.mac[j]->ue_multiple_max, + RC.mac[j]->use_mcs_offset, + RC.mac[j]->bler_lower, + RC.mac[j]->bler_upper, + RC.mac[j]->max_ul_rb_index); if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_RRC") == 0) { // check number of instances is same as RRC/PDCP - printf("Configuring local RRC for MACRLC\n"); + LOG_I(ENB_APP,"Configuring local RRC for MACRLC\n"); } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) { - printf("Configuring F1 interfaces for MACRLC\n"); + LOG_I(ENB_APP,"Configuring F1 interfaces for MACRLC\n"); RC.mac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr)); RC.mac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); RC.mac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr)); @@ -287,7 +306,7 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { int32_t offsetMaxLimit = 0; int32_t cycleNb = 0; - MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_CONFIGURATION_REQ); + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_ENB, 0, RRC_CONFIGURATION_REQ); ccparams_lte_t ccparams_lte; ccparams_sidelink_t SLconfig; ccparams_eMTC_t eMTCconfig; @@ -1576,6 +1595,8 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { } // !NODE_IS_DU(node_type) } + RRC_CONFIGURATION_REQ (msg_p).nr_scg_ssb_freq = ccparams_lte.nr_scg_ssb_freq; + if (!NODE_IS_DU(rrc->node_type)) { char srb1path[MAX_OPTNAME_SIZE*2 + 8]; sprintf(srb1path,"%s.%s",enbpath,ENB_CONFIG_STRING_SRB1); @@ -1987,7 +2008,7 @@ int RCconfig_DU_F1(MessageDef *msg_p, uint32_t i) { F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.nrb = rrc->carrier[0].mib.message.dl_Bandwidth; F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.num_frequency_bands = 1; F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.nr_band[0] = rrc->carrier[0].sib1->freqBandIndicator; - F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.sul_active = 0; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.sul_active = 0; } else { LOG_I(ENB_APP,"ngran_DU: Configuring Cell %d for FDD\n",k); F1AP_SETUP_REQ (msg_p).fdd_flag = 1; @@ -2049,11 +2070,13 @@ int RCconfig_gtpu(void ) { if (address) { MessageDef *message; - AssertFatal((message = itti_alloc_new_message(TASK_ENB_APP, GTPV1U_ENB_S1_REQ))!=NULL,""); + AssertFatal((message = itti_alloc_new_message(TASK_ENB_APP, 0, GTPV1U_ENB_S1_REQ))!=NULL,""); IPV4_STR_ADDR_TO_INT_NWBO ( address, GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" ); LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up); GTPV1U_ENB_S1_REQ(message).enb_port_for_S1u_S12_S4_up = enb_port_for_S1U; - itti_send_msg_to_task (TASK_GTPV1_U, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id) + strcpy(GTPV1U_ENB_S1_REQ(message).addrStr,address); + sprintf(GTPV1U_ENB_S1_REQ(message).portStr,"%d", enb_port_for_S1U); + itti_send_msg_to_task (TASK_VARIABLE, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id) } else LOG_E(GTPU,"invalid address for S1U\n"); @@ -2424,6 +2447,65 @@ int RCconfig_S1( "to\n" " tracking_area_code = 1; // no string!!\n" " plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n"); + if(*ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_rsp_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = 5; + } + + if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_req_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = 5; + } + + if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_req_count value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = 0xffff; + } + + if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "sctp_req_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = 180; + } + + if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr; + } + else + { + LOG_E(S1AP, + "sctp_req_count value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = 0xffff; + } config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix); if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) { @@ -2509,6 +2591,9 @@ int RCconfig_S1( S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] = 0; } + /* set S1-mme port (sctp) */ + S1AP_REGISTER_ENB_REQ(msg_p).mme_port[l] = *S1ParamList.paramarray[l][ENB_MME_PORT_IDX].u16ptr; + AssertFatal(S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] <= S1AP_REGISTER_ENB_REQ(msg_p).num_plmn, "List of broadcast PLMN to be sent to MME can not be longer than actual " "PLMN list (max %d, but is %d)\n", @@ -2709,12 +2794,13 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { "value of X2ParamList.numelt %d must be lower than X2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase X2AP_MAX_NB_ENB_IP_ADDRESS\n", X2ParamList.numelt,X2AP_MAX_NB_ENB_IP_ADDRESS); X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 = 0; - + LOG_I(X2AP,"X2ParamList.numelt %d\n",X2ParamList.numelt); for (l = 0; l < X2ParamList.numelt; l++) { X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 += 1; strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4_address,*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr)); strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6_address,*(X2ParamList.paramarray[l][ENB_X2_IPV6_ADDRESS_IDX].strptr)); + LOG_I(X2AP,"registering with ip : %s\n",*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr)); if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) { X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1; X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 0; @@ -2731,20 +2817,28 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { { int t_reloc_prep = 0; int tx2_reloc_overall = 0; + int t_dc_prep = 0; + int t_dc_overall = 0; paramdef_t p[] = { { "t_reloc_prep", "t_reloc_prep", 0, iptr:&t_reloc_prep, defintval:0, TYPE_INT, 0 }, - { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 } + { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 }, + { "t_dc_prep", "t_dc_prep", 0, iptr:&t_dc_prep, defintval:0, TYPE_INT, 0 }, + { "t_dc_overall", "t_dc_overall", 0, iptr:&t_dc_overall, defintval:0, TYPE_INT, 0 } }; config_get(p, sizeof(p)/sizeof(paramdef_t), aprefix); if (t_reloc_prep <= 0 || t_reloc_prep > 10000 || - tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000) { - LOG_E(X2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000]\n"); + tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000 || + t_dc_prep <= 0 || t_dc_prep > 10000 || + t_dc_overall <= 0 || t_dc_overall > 20000) { + LOG_E(X2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000] and [0 < t_dc_prep <= 10000] and [0 < t_dc_overall <= 20000]\n"); exit(1); } X2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep; X2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall; + X2AP_REGISTER_ENB_REQ (msg_p).t_dc_prep = t_dc_prep; + X2AP_REGISTER_ENB_REQ (msg_p).t_dc_overall = t_dc_overall; } // SCTP SETTING X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; @@ -2886,7 +2980,7 @@ void extract_and_decode_SI(int inst,int si_ind,uint8_t *si_container,int si_cont eNB_RRC_INST *rrc = RC.rrc[inst]; rrc_eNB_carrier_data_t *carrier = &rrc->carrier[0]; LTE_BCCH_DL_SCH_Message_t *bcch_message ; - AssertFatal(si_ind==0,"Can only handle a single SI block for now\n"); + AssertFatal(si_ind==2,"Can only handle a single SI block for now\n"); LOG_I(ENB_APP, "rrc inst %d: Trying to decode SI block %d @ %p, length %d\n",inst,si_ind,si_container,si_container_length); // point to first SI block bcch_message = &carrier->systemInformation; @@ -3067,21 +3161,25 @@ void handle_f1ap_setup_resp(f1ap_setup_resp_t *resp) { rrc_eNB_carrier_data_t *carrier = &RC.rrc[i]->carrier[0]; // identify local index of cell j by nr_cellid, plmn identity and physical cell ID LOG_I(ENB_APP, "Checking cell %d, rrc inst %d : rrc->nr_cellid %lx, resp->nr_cellid %lx\n", - j,i,RC.rrc[i]->nr_cellid,resp->nr_cellid[j]); + j,i,RC.rrc[i]->nr_cellid,resp->cells_to_activate[j].nr_cellid); - if (RC.rrc[i]->nr_cellid == resp->nr_cellid[j] && - (check_plmn_identity(carrier, resp->mcc[j], resp->mnc[j], resp->mnc_digit_length[j])>0 && - resp->nrpci[j] == carrier->physCellId)) { + if (RC.rrc[i]->nr_cellid == resp->cells_to_activate[j].nr_cellid && + (check_plmn_identity(carrier, resp->cells_to_activate[j].mcc, resp->cells_to_activate[j].mnc, resp->cells_to_activate[j].mnc_digit_length)>0 && + resp->cells_to_activate[j].nrpci == carrier->physCellId)) { // copy system information and decode it - for (si_ind=0; si_indnum_SI[j]; si_ind++) { - //printf("SI %d size %d: ", si_ind, resp->SI_container_length[j][si_ind]); - //for (int n=0;nSI_container_length[j][si_ind];n++) - // printf("%02x ",resp->SI_container[j][si_ind][n]); + for (si_ind=2; si_indcells_to_activate[j].num_SI + 2; si_ind++) { + //printf("SI %d size %d: ", si_ind, resp->cells_to_activate[j].SI_container_length[si_ind]); + //for (int n=0;ncells_to_activate[j].SI_container_length[si_ind];n++) + // printf("%02x ",resp->cells_to_activate[j].SI_container[si_ind][n]); //printf("\n"); - extract_and_decode_SI(i, - si_ind, - resp->SI_container[j][si_ind], - resp->SI_container_length[j][si_ind]); + if (si_ind==6) si_ind=9; + if (resp->cells_to_activate[j].SI_container[si_ind] != NULL) { + extract_and_decode_SI(i, + si_ind, + resp->cells_to_activate[j].SI_container[si_ind], + resp->cells_to_activate[j].SI_container_length[si_ind]); + } + } // perform MAC/L1 common configuration diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 4bc4f5bf22..b95bf90f70 100644 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -100,7 +100,6 @@ typedef struct ru_config_s { uint8_t if_compress; } ru_config_t; -extern void RCconfig_RU(void); extern void RCconfig_flexran(void); extern void RCconfig_L1(void); extern void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]); diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 344214a1f1..22af2a6de0 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -34,6 +34,7 @@ #define ENB_PARAMDEF_H_ #include "common/config/config_paramdesc.h" #include "RRC_paramsvalues.h" +#include "s1ap_eNB_default_values.h" #define ENB_CONFIG_STRING_CC_NODE_FUNCTION "node_function" #define ENB_CONFIG_STRING_CC_NODE_TIMING "node_timing" @@ -96,6 +97,8 @@ typedef enum { #define CONFIG_STRING_RU_OTA_SYNC_ENABLE "ota_sync_enabled" #define CONFIG_STRING_RU_BF_WEIGHTS_LIST "bf_weights" #define CONFIG_STRING_RU_IF_FREQUENCY "if_freq" +#define CONFIG_STRING_RU_IF_FREQ_OFFSET "if_offset" +#define CONFIG_STRING_RU_DO_PRECODING "do_precoding" #define RU_LOCAL_IF_NAME_IDX 0 #define RU_LOCAL_ADDRESS_IDX 1 @@ -124,7 +127,8 @@ typedef enum { #define RU_OTA_SYNC_ENABLE_IDX 24 #define RU_BF_WEIGHTS_LIST_IDX 25 #define RU_IF_FREQUENCY 26 - +#define RU_IF_FREQ_OFFSET 27 +#define RU_DO_PRECODING 28 /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* RU configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -152,11 +156,13 @@ typedef enum { {CONFIG_STRING_RU_SDR_ADDRS, NULL, 0, strptr:NULL, defstrval:"type=b200", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_SDR_CLK_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_SDR_TME_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \ - {CONFIG_STRING_RU_SF_EXTENSION, NULL, 0, uptr:NULL, defuintval:312, TYPE_UINT, 0}, \ + {CONFIG_STRING_RU_SF_EXTENSION, NULL, 0, uptr:NULL, defuintval:320, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_END_OF_BURST_DELAY, NULL, 0, uptr:NULL, defuintval:400, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_OTA_SYNC_ENABLE, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_BF_WEIGHTS_LIST, NULL, 0, iptr:NULL, defintarrayval:DEFBFW, TYPE_INTARRAY, 0}, \ {CONFIG_STRING_RU_IF_FREQUENCY, NULL, 0, u64ptr:NULL, defuintval:0, TYPE_UINT64, 0}, \ + {CONFIG_STRING_RU_IF_FREQ_OFFSET, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \ + {CONFIG_STRING_RU_DO_PRECODING, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \ } /*---------------------------------------------------------------------------------------------------------------------------------------*/ @@ -210,6 +216,11 @@ typedef enum { #define ENB_CONFIG_STRING_X2 "enable_x2" #define ENB_CONFIG_STRING_ENB_M2 "enable_enb_m2" #define ENB_CONFIG_STRING_MCE_M2 "enable_mce_m2" +#define ENB_CONFIG_STRING_S1SETUP_RSP_TIMER "s1setup_rsp_timer" +#define ENB_CONFIG_STRING_S1SETUP_REQ_TIMER "s1setup_req_timer" +#define ENB_CONFIG_STRING_S1SETUP_REQ_COUNT "s1setup_req_count" +#define ENB_CONFIG_STRING_SCTP_REQ_TIMER "sctp_req_timer" +#define ENB_CONFIG_STRING_SCTP_REQ_COUNT "sctp_req_count" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -235,6 +246,11 @@ typedef enum { {ENB_CONFIG_STRING_X2, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_MCE_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_RSP_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_SCTP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:180, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_SCTP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \ } #define ENB_ENB_ID_IDX 0 @@ -257,6 +273,11 @@ typedef enum { #define ENB_ENABLE_X2 17 #define ENB_ENABLE_ENB_M2 18 #define ENB_ENABLE_MCE_M2 19 +#define ENB_S1SETUP_RSP_TIMER_IDX 20 +#define ENB_S1SETUP_REQ_TIMER_IDX 21 +#define ENB_S1SETUP_REQ_COUNT_IDX 22 +#define ENB_SCTP_REQ_TIMER_IDX 23 +#define ENB_SCTP_REQ_COUNT_IDX 24 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define ENBPARAMS_CHECK { \ @@ -429,6 +450,9 @@ typedef enum { //SIB1-MBMS #define ENB_CONFIG_STRING_MBMS_DEDICATED_SERVING_CELL "mbms_dedicated_serving_cell" +//NSA NR Cell SSB Absolute Frequency +#define ENB_CONFIG_STRING_NR_SCG_SSB_FREQ "nr_scg_ssb_freq" + #define ENB_CONFIG_STRING_PDSCH_MAX_NUM_REPETITION_CE_MODE_A_R13 "pdsch_maxNumRepetitionCEmodeA_r13" @@ -577,6 +601,7 @@ typedef struct ccparams_lte_s { int32_t srb1_poll_pdu; int32_t srb1_poll_byte; int32_t srb1_max_retx_threshold; + int32_t nr_scg_ssb_freq; } ccparams_lte_t; #define CCPARAMS_CHECK { \ @@ -780,7 +805,8 @@ typedef struct ccparams_lte_s { {ENB_CONFIG_STRING_UETIMERS_N311, NULL, 0, iptr:&ccparams.ue_TimersAndConstants_n311, defintval:1, TYPE_UINT, 0}, \ {ENB_CONFIG_STRING_UE_TRANSMISSION_MODE, NULL, 0, iptr:&ccparams.ue_TransmissionMode, defintval:1, TYPE_UINT, 0}, \ {ENB_CONFIG_STRING_UE_MULTIPLE_MAX, NULL, 0, iptr:&ccparams.ue_multiple_max, defintval:4, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_MBMS_DEDICATED_SERVING_CELL, NULL, 0, strptr:&ccparams.mbms_dedicated_serving_cell, defstrval:"DISABLE", TYPE_STRING, 0} \ + {ENB_CONFIG_STRING_MBMS_DEDICATED_SERVING_CELL, NULL, 0, strptr:&ccparams.mbms_dedicated_serving_cell, defstrval:"DISABLE", TYPE_STRING, 0}, \ + {ENB_CONFIG_STRING_NR_SCG_SSB_FREQ, NULL, 0, iptr:&ccparams.nr_scg_ssb_freq, defintval:641272, TYPE_INT, 0} \ } @@ -902,6 +928,7 @@ typedef struct srb1_params_s { #define ENB_CONFIG_STRING_MME_IPV4_ADDRESS "ipv4" #define ENB_CONFIG_STRING_MME_IPV6_ADDRESS "ipv6" +#define ENB_CONFIG_STRING_MME_PORT "port" #define ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE "active" #define ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE "preference" #define ENB_CONFIG_STRING_MME_BROADCAST_PLMN_INDEX "broadcast_plmn_index" @@ -916,14 +943,20 @@ typedef struct srb1_params_s { {ENB_CONFIG_STRING_MME_IPV6_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ - {ENB_CONFIG_STRING_MME_BROADCAST_PLMN_INDEX, NULL, 0, uptr:NULL, defintarrayval:NULL, TYPE_UINTARRAY, 6} \ + {ENB_CONFIG_STRING_MME_BROADCAST_PLMN_INDEX, NULL, 0, uptr:NULL, defintarrayval:NULL, TYPE_UINTARRAY, 6}, \ + {ENB_CONFIG_STRING_MME_PORT, NULL, 0, u16ptr:NULL, defuintval:S1AP_PORT_NUMBER, TYPE_UINT16, 0}, \ } + + + + #define ENB_MME_IPV4_ADDRESS_IDX 0 #define ENB_MME_IPV6_ADDRESS_IDX 1 #define ENB_MME_IP_ADDRESS_ACTIVE_IDX 2 #define ENB_MME_IP_ADDRESS_PREFERENCE_IDX 3 #define ENB_MME_BROADCAST_PLMN_INDEX 4 +#define ENB_MME_PORT_IDX 5 /*---------------------------------------------------------------------------------------------------------------------------------------*/ /* X2 configuration parameters section name */ diff --git a/openair2/ENB_APP/flexran_agent.c b/openair2/ENB_APP/flexran_agent.c index 519d2bef4b..af7ff6ff6f 100644 --- a/openair2/ENB_APP/flexran_agent.c +++ b/openair2/ENB_APP/flexran_agent.c @@ -33,6 +33,9 @@ #include #include +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + int agent_task_created = 0; /* * enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller @@ -115,7 +118,6 @@ error: return NULL; } - int channel_container_init = 0; int flexran_agent_start(mid_t mod_id) { @@ -233,6 +235,9 @@ int flexran_agent_start(mid_t mod_id) agent_task_created = 1; } + /* Init the app sublayer */ + flexran_agent_app_init(mod_id); + pthread_mutex_init(&flexran->mutex_node_ctrl, NULL); pthread_cond_init(&flexran->cond_node_ctrl, NULL); @@ -249,7 +254,7 @@ int flexran_agent_start(mid_t mod_id) pthread_mutex_unlock(&flexran->mutex_node_ctrl); /* reconfigure RRC again, the agent might have changed the configuration */ - MessageDef *msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ); + MessageDef *msg_p = itti_alloc_new_message(TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ); RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[mod_id]->configuration; itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg_p); } diff --git a/openair2/ENB_APP/flexran_agent.h b/openair2/ENB_APP/flexran_agent.h index 42295fc111..43e7d7210a 100644 --- a/openair2/ENB_APP/flexran_agent.h +++ b/openair2/ENB_APP/flexran_agent.h @@ -41,6 +41,7 @@ #include "flexran_agent_rrc.h" #include "flexran_agent_pdcp.h" #include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" #include "common/utils/LOG/log.h" #include "assertions.h" diff --git a/openair2/ENB_APP/flexran_agent_app.c b/openair2/ENB_APP/flexran_agent_app.c new file mode 100644 index 0000000000..5bf06ca631 --- /dev/null +++ b/openair2/ENB_APP/flexran_agent_app.c @@ -0,0 +1,207 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file flexran_agent_app.c + * \brief CM for handling of applications + * \author Robert Schmidt + * \date 2020 + * \version 0.1 + */ + +#include "flexran_agent_app.h" +#include "queue.h" +#include + +/* app definition */ +typedef struct flexran_agent_app_internal_s { + char *name; + void *dl_handle; + flexran_agent_app_t *app; + + SLIST_ENTRY (flexran_agent_app_internal_s) entries; +} flexran_agent_app_internal_t; + +/* a list of all apps */ +SLIST_HEAD(flexran_apps_s, flexran_agent_app_internal_s) flexran_apps[NUM_MAX_ENB]; + +void flexran_agent_app_init(mid_t mod_id) { + //flexran_apps[mod_id] = SLIST_HEAD_INITIALIZER(flexran_apps[mod_id]); + SLIST_INIT(&flexran_apps[mod_id]); +} + +int flexran_agent_start_app_direct(mid_t mod_id, flexran_agent_app_t *app, char *name) { + app->start(mod_id, NULL, 0); + + flexran_agent_app_internal_t *so = malloc(sizeof(flexran_agent_app_internal_t)); + DevAssert(so); + so->name = strdup(name); + DevAssert(so->name); + so->dl_handle = NULL; + so->app = app; + SLIST_INSERT_HEAD(&flexran_apps[mod_id], so, entries); + return 0; +} + +int flexran_agent_start_app(mid_t mod_id, Protocol__FlexAgentReconfigurationSubsystem *sub) { + char s[512]; + int rc = flexran_agent_map_name_to_delegated_object(mod_id, sub->name, s, 512); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", sub->name); + return -1; + } + void *h = dlopen(s, RTLD_NOW); + if (!h) { + LOG_E(FLEXRAN_AGENT, "cannot open shared object %s\n", s); + return -1; + } + flexran_agent_app_t *app = dlsym(h, "app"); + if (!app) { + LOG_E(FLEXRAN_AGENT, "cannot locate app inside of shared object %s\n", s); + return -1; + } + app->start(mod_id, sub->params, sub->n_params); + + flexran_agent_app_internal_t *so = malloc(sizeof(flexran_agent_app_internal_t)); + DevAssert(so); + so->name = strdup(sub->name); + DevAssert(so->name); + so->dl_handle = h; + so->app = app; + SLIST_INSERT_HEAD(&flexran_apps[mod_id], so, entries); + + return 0; +} + +int flexran_agent_stop_app(mid_t mod_id, char *name) { + flexran_agent_app_internal_t *so = NULL; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) { + if (strcmp(so->name, name) == 0) { + LOG_I(FLEXRAN_AGENT, "application %s seems to be running\n", name); + break; + } + } + if (!so) { + LOG_E(FLEXRAN_AGENT, "no such application %s found\n", name); + return -1; + } + flexran_agent_app_t *app = so->app; + app->stop(mod_id); + + SLIST_REMOVE(&flexran_apps[mod_id], so, flexran_agent_app_internal_s, entries); + free(so->name); + if (so->dl_handle) + dlclose(so->dl_handle); + free(so); + so = NULL; + return 0; +} + +int flexran_agent_reconfig_app( + mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem *sub) +{ + flexran_agent_app_internal_t *so = NULL; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) { + if (strcmp(so->name, sub->name) == 0) { + LOG_I(FLEXRAN_AGENT, "application %s is running\n", sub->name); + break; + } + } + if (!so) { + LOG_E(FLEXRAN_AGENT, "no such application %s found\n", sub->name); + return -1; + } + flexran_agent_app_t *app = so->app; + LOG_I(FLEXRAN_AGENT, "reconfiguring app %s\n", so->name); + app->reconfig(mod_id, sub->params, sub->n_params); + return 0; +} + +int flexran_agent_custom_command_app( + mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem *sub) +{ + flexran_agent_app_internal_t *so = NULL; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) { + if (strcmp(so->name, sub->name) == 0) { + LOG_I(FLEXRAN_AGENT, "application %s is running\n", sub->name); + break; + } + } + if (!so) { + LOG_E(FLEXRAN_AGENT, "no such application %s found\n", sub->name); + return -1; + } + void (*cmd)(mid_t, Protocol__FlexAgentReconfigurationSubsystem *) = dlsym(so->dl_handle, sub->behavior); + if (!cmd) { + LOG_E(FLEXRAN_AGENT, + "cannot locate command %s inside of app %s\n", + sub->behavior, + so->name); + return -1; + } + + LOG_I(FLEXRAN_AGENT, + "calling command %s inside of app %s\n", + sub->behavior, + so->name); + (*cmd)(mod_id, sub); + return 0; +} + +void flexran_agent_handle_apps( + mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem **subs, + int n_subs) { + for (int i = 0; i < n_subs; ++i) { + Protocol__FlexAgentReconfigurationSubsystem *s = subs[i]; + if (strcmp(s->behavior, "start") == 0) { + int rc = flexran_agent_start_app(mod_id, s); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "application \"%s\" started\n", s->name); + } else if (strcmp(s->behavior, "stop") == 0) { + int rc = flexran_agent_stop_app(mod_id, s->name); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "application \"%s\" stopped\n", s->name); + } else if (strcmp(s->behavior, "reconfig") == 0) { + flexran_agent_reconfig_app(mod_id, s); + } else { + flexran_agent_custom_command_app(mod_id, s); + } + } +} + +void flexran_agent_fill_loaded_apps(mid_t mod_id, + Protocol__FlexEnbConfigReply *reply) { + int n = 0; + flexran_agent_app_internal_t *so = NULL; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) + ++n; + reply->n_loadedapps = n; + reply->loadedapps = calloc(n, sizeof(char *)); + if (!reply->loadedapps) { + reply->n_loadedapps = 0; + return; + } + n = 0; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) + reply->loadedapps[n++] = so->name; +} diff --git a/openair2/ENB_APP/flexran_agent_app.h b/openair2/ENB_APP/flexran_agent_app.h new file mode 100644 index 0000000000..4723b344bf --- /dev/null +++ b/openair2/ENB_APP/flexran_agent_app.h @@ -0,0 +1,74 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file flexran_agent_app.h + * \brief Common app definitions + * \author Robert Schmidt + * \date 2020 + * \version 0.1 + */ + +#ifndef BURST_ANALYSIS_LL_H_ +#define BURST_ANALYSIS_LL_H_ + +#include "flexran_agent_common.h" +#include "flexran_agent_async.h" +#include "flexran_agent_extern.h" +#include "flexran_agent_timer.h" +#include "flexran_agent_defs.h" +#include "flexran_agent_net_comm.h" +#include "flexran_agent_ran_api.h" +#include "flexran_agent_phy.h" +#include "flexran_agent_mac.h" +#include "flexran_agent_rrc.h" +#include "flexran_agent_pdcp.h" +#include "flexran_agent_s1ap.h" +#include "common/utils/LOG/log.h" +#include "assertions.h" + +/* App type: to be implemented by shared libraries */ +typedef struct { + int (*start)(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p); + int (*reconfig)(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p); + int (* stop)(mid_t mod_id); +} flexran_agent_app_t; + +/* FlexRAN agent app handling init */ +void flexran_agent_app_init(mid_t mod_id); + +/* Start an app from within the agent */ +int flexran_agent_start_app_direct(mid_t mod_id, flexran_agent_app_t *app, char *name); + +/* FlexRAN agent handler to setup/teardown apps */ +void flexran_agent_handle_apps( + mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem **subs, + int n_subs); + +/* Fills the enb_config_reply with the currently loaded (started) apps */ +void flexran_agent_fill_loaded_apps(mid_t mod_id, + Protocol__FlexEnbConfigReply *reply); + +#endif diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 7569ca1ac1..55a1c61b25 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include "flexran_agent_common.h" #include "flexran_agent_common_internal.h" @@ -39,6 +42,7 @@ #include "flexran_agent_mac.h" #include "flexran_agent_rrc.h" #include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" //#include "PHY/extern.h" #include "common/utils/LOG/log.h" #include "flexran_agent_mac_internal.h" @@ -49,6 +53,9 @@ #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" #include "rrc_eNB_UE_context.h" +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + /* * message primitives */ @@ -326,6 +333,12 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { if (reply->s1ap) flexran_agent_free_s1ap_cell_config(&reply->s1ap); + if (reply->loadedapps) + free(reply->loadedapps); + + if (reply->loadedmacobjects) + free(reply->loadedmacobjects); + free(reply->cell_config); free(reply); free(msg); @@ -424,26 +437,65 @@ long timer_end(struct timespec start_time) { int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg; - // struct timespec vartime = timer_start(); - //Write the payload lib into a file in the cache and load the lib - char lib_name[120]; - char target[512]; - snprintf(lib_name, sizeof(lib_name), "/%s.so", control_delegation_msg->name); - strcpy(target, RC.flexran[mod_id]->cache_name); - strcat(target, lib_name); - FILE *f; - f = fopen(target, "wb"); + *msg = NULL; - if (f) { - fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f); - fclose(f); + char target[512]; + int len = snprintf(target, sizeof(target), "%s/libflex.%s.so", + RC.flexran[mod_id]->cache_name, + control_delegation_msg->name); + if (len >= sizeof(target)) { + LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot write file name\n"); + return 0; + } + + if (control_delegation_msg->has_payload) { + /* use low-level API: check whether exists while creating so we can abort if + * it exists to not overwrite anything */ + int fd = open(target, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); + if (fd >= 0) { + ssize_t l = write(fd, + control_delegation_msg->payload.data, + control_delegation_msg->payload.len); + close(fd); + if (l < control_delegation_msg->payload.len) { + LOG_E(FLEXRAN_AGENT, + "could not write complete control delegation to %s: only %ld out of " + "%ld bytes\n", + target, + l, + control_delegation_msg->payload.len); + return 0; + } else if (l < 0) { + LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", + target, strerror(errno)); + return 0; + } + LOG_I(FLEXRAN_AGENT, "wrote shared object %s\n", target); + } else { + if (errno == EEXIST) { + LOG_W(FLEXRAN_AGENT, "file %s already exists, remove it first\n", target); + } else { + LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", + target, strerror(errno)); + } + return 0; + } } else { - LOG_W(FLEXRAN_AGENT, "[%d] can not write control delegation data to %s\n", - mod_id, target); + LOG_W(FLEXRAN_AGENT, "remove file %s\n", target); + int rc = remove(target); + if (rc < 0) + LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", target, strerror(errno)); + } + + if (control_delegation_msg->has_delegation_type + && control_delegation_msg->delegation_type == PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER + && control_delegation_msg->header + && control_delegation_msg->header->has_xid) { + /* Inform the MAC subsystem that a control delegation for it has arrived */ + /* TODO this should be triggered by an agent reconfiguration? */ + flexran_agent_mac_inform_delegation(mod_id, control_delegation_msg); } - // long time_elapsed_nanos = timer_end(vartime); - *msg = NULL; return 0; } @@ -452,10 +504,44 @@ int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) { return 0; } +int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name, + char *path, int maxlen) { + int len = snprintf(path, maxlen, "%s/libflex.%s.so", + RC.flexran[mod_id]->cache_name, name); + if (len >= maxlen) { + LOG_E(FLEXRAN_AGENT, "path has been truncated, cannot read object\n"); + return -1; + } + + struct stat buf; + int status = stat(path, &buf); + if (status < 0) { + LOG_E(FLEXRAN_AGENT, "Could not stat object %s: %s\n", path, strerror(errno)); + return -1; + } + return 0; +} + int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg; - apply_reconfiguration_policy(mod_id, agent_reconfiguration_msg->policy, strlen(agent_reconfiguration_msg->policy)); + if (agent_reconfiguration_msg->policy) { + /* for compatibility: call old YAML configuration code, although we don't + * use it anymore */ + apply_reconfiguration_policy(mod_id, + agent_reconfiguration_msg->policy, + strlen(agent_reconfiguration_msg->policy)); + } + for (int i = 0; i < agent_reconfiguration_msg->n_systems; ++i) { + const Protocol__FlexAgentReconfigurationSystem *sys = agent_reconfiguration_msg->systems[i]; + if (strcmp(sys->system, "app") == 0) { + flexran_agent_handle_apps(mod_id, sys->subsystems, sys->n_subsystems); + } else { + LOG_E(FLEXRAN_AGENT, + "unknown system name %s in flex_agent_reconfiguration message\n", + sys->system); + } + } *msg = NULL; return 0; } @@ -465,6 +551,15 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) { return 0; } +int flexran_agent_destroy_control_delegation_request(Protocol__FlexranMessage *msg) { + if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG) + return -1; + + free(msg->control_del_req_msg->header); + free(msg->control_del_req_msg->name); + free(msg); + return 0; +} int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { xid_t xid; @@ -556,18 +651,6 @@ error: * ************************************ */ -int sort_ue_config(const void *a, const void *b) { - const Protocol__FlexUeConfig *fa = a; - const Protocol__FlexUeConfig *fb = b; - - if (fa->rnti < fb->rnti) - return -1; - else if (fa->rnti < fb->rnti) - return 1; - - return 0; -} - int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { xid_t xid; Protocol__FlexHeader *header = NULL; @@ -750,6 +833,10 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F if (flexran_agent_get_s1ap_xface(mod_id)) flexran_agent_fill_s1ap_cell_config(mod_id, &enb_config_reply_msg->s1ap); + flexran_agent_fill_loaded_apps(mod_id, enb_config_reply_msg); + + flexran_agent_mac_fill_loaded_mac_objects(mod_id, enb_config_reply_msg); + *msg = malloc(sizeof(Protocol__FlexranMessage)); if(*msg == NULL) { @@ -880,7 +967,9 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot if (enb_config->n_cell_config > 0) { if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { - prepare_update_slice_config(mod_id, &enb_config->cell_config[0]->slice_config); + prepare_update_slice_config(mod_id, + &enb_config->cell_config[0]->slice_config, + 1 /* request objects if necessary */); } if (enb_config->cell_config[0]->has_eutra_band && enb_config->cell_config[0]->has_dl_freq diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h index fe7b49107c..18d32421dd 100644 --- a/openair2/ENB_APP/flexran_agent_common.h +++ b/openair2/ENB_APP/flexran_agent_common.h @@ -70,7 +70,6 @@ typedef struct { pthread_mutex_t *mutex; } stats_updates_context_t; -stats_updates_context_t stats_context[NUM_MAX_ENB]; /********************************** * FlexRAN protocol messages helper @@ -131,11 +130,20 @@ int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg); /* Control delegation message constructor and destructor */ int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg); +/* Map a name from a control_delegation message to a file name. The function + * stat()s the file to check existence and returns the complete path name in + * path. The length in path needs to be maxlen, the maximum length the path may + * have. */ +int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name, + char *path, int maxlen); /* Policy reconfiguration message constructor and destructor */ int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg); +/* Policy reconfiguration request message destructor */ +int flexran_agent_destroy_control_delegation_request(Protocol__FlexranMessage *msg); + /* rrc triggering measurement message constructor and destructor */ int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg); diff --git a/openair2/ENB_APP/flexran_agent_common_internal.c b/openair2/ENB_APP/flexran_agent_common_internal.c index 9091753f9a..a893982824 100644 --- a/openair2/ENB_APP/flexran_agent_common_internal.c +++ b/openair2/ENB_APP/flexran_agent_common_internal.c @@ -565,6 +565,6 @@ void initiate_soft_restart(module_id_t mod_id, Protocol__FlexCellConfig *c) } MessageDef *msg; - msg = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SOFT_RESTART_MESSAGE); + msg = itti_alloc_new_message(TASK_FLEXRAN_AGENT, 0, SOFT_RESTART_MESSAGE); itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); } diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index d991078cf7..addcd6a142 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -32,6 +32,7 @@ #include "flexran_agent_rrc.h" #include "flexran_agent_pdcp.h" #include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" #include "flexran_agent_timer.h" #include "flexran_agent_ran_api.h" #include "common/utils/LOG/log.h" @@ -80,6 +81,11 @@ flexran_agent_message_destruction_callback message_destruction_callback[] = { flexran_agent_destroy_ue_state_change, flexran_agent_destroy_control_delegation, flexran_agent_destroy_agent_reconfiguration, + NULL, /* flex_rrc_triggering */ + NULL, /* flex_ul_mac_config */ + NULL, /* flex_disconnect */ + NULL, /* flex_ho_command */ + flexran_agent_destroy_control_delegation_request, }; /* static const char *flexran_agent_direction2String[] = { */ diff --git a/openair2/ENB_APP/flexran_agent_net_comm.c b/openair2/ENB_APP/flexran_agent_net_comm.c index 0d1c52096d..568a0e32cc 100644 --- a/openair2/ENB_APP/flexran_agent_net_comm.c +++ b/openair2/ENB_APP/flexran_agent_net_comm.c @@ -30,7 +30,7 @@ #include "common/utils/LOG/log.h" flexran_agent_channel_t *agent_channel[NUM_MAX_ENB][FLEXRAN_AGENT_MAX]; -flexran_agent_channel_instance_t channel_instance; +static flexran_agent_channel_instance_t channel_instance; int flexran_agent_channel_id = 0; int flexran_agent_msg_send(mid_t mod_id, agent_id_t agent_id, void *data, int size, int priority) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 79c992a4d7..68d1f3311f 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -32,6 +32,9 @@ #include "s1ap_eNB_management_procedures.h" #include "openair2/LAYER2/MAC/slicing/slicing.h" +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) { return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id]; } @@ -885,7 +888,7 @@ uint8_t flexran_get_rrc_status(mid_t mod_id, rnti_t rnti) { if (!ue_context_p) return RRC_INACTIVE; - return ue_context_p->ue_context.Status; + return ue_context_p->ue_context.StatusRrc; } uint64_t flexran_get_ue_aggregated_max_bitrate_dl(mid_t mod_id, mid_t ue_id) { @@ -3092,12 +3095,13 @@ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { return slices->s[idx]->id; } -void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; +int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { + if (!mac_is_present(mod_id)) return 0; int idx = flexran_find_dl_slice(mod_id, slice_id); - if (idx < 0) return; + if (idx < 0) return 0; pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; dl->move_UE(dl->slices, ue_id, idx); + return 1; } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { @@ -3108,15 +3112,16 @@ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { return slices->s[idx]->id; } -void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; +int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { + if (!mac_is_present(mod_id)) return 0; int idx = flexran_find_ul_slice(mod_id, slice_id); - if (idx < 0) return; + if (idx < 0) return 0; pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; ul->move_UE(ul->slices, ue_id, idx); + return 1; } -int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) { if (!mac_is_present(mod_id)) return 0; void *params = NULL; switch (s->params_case) { @@ -3133,7 +3138,7 @@ int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { char *l = s->label ? strdup(s->label) : NULL; void *algo = &dl->dl_algo; // default scheduler if (s->scheduler) { - algo = dlsym(NULL, s->scheduler); + algo = dlsym(object, s->scheduler); if (!algo) { free(params); LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); @@ -3193,7 +3198,7 @@ int flexran_get_num_dl_slices(mid_t mod_id) { return RC.mac[mod_id]->pre_processor_dl.slices->num; } -int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) { if (!mac_is_present(mod_id)) return -1; void *params = NULL; switch (s->params_case) { @@ -3210,7 +3215,7 @@ int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { char *l = s->label ? strdup(s->label) : NULL; void *algo = &ul->ul_algo; // default scheduler if (s->scheduler) { - algo = dlsym(NULL, s->scheduler); + algo = dlsym(object, s->scheduler); if (!algo) { free(params); LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); @@ -3276,9 +3281,9 @@ char *flexran_get_dl_scheduler_name(mid_t mod_id) { return RC.mac[mod_id]->pre_processor_dl.dl_algo.name; } -int flexran_set_dl_scheduler(mid_t mod_id, char *sched) { +int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object) { if (!mac_is_present(mod_id)) return -1; - void *d = dlsym(NULL, sched); + void *d = dlsym(object, sched); if (!d) return -2; pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl; dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); @@ -3292,9 +3297,9 @@ char *flexran_get_ul_scheduler_name(mid_t mod_id) { return RC.mac[mod_id]->pre_processor_ul.ul_algo.name; } -int flexran_set_ul_scheduler(mid_t mod_id, char *sched) { +int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object) { if (!mac_is_present(mod_id)) return -1; - void *d = dlsym(NULL, sched); + void *d = dlsym(object, sched); if (!d) return -2; pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul; ul_pp->ul_algo.unset(&ul_pp->ul_algo.data); @@ -3463,7 +3468,7 @@ int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { if (!rrc_is_present(mod_id)) return -2; /* Reconstruct S1AP_REGISTER_ENB_REQ */ - MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, S1AP_REGISTER_ENB_REQ); + MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, 0, S1AP_REGISTER_ENB_REQ); RCconfig_S1(m, mod_id); const int CC_id = 0; @@ -3489,22 +3494,22 @@ int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num; for (int i = 0; i < mme->broadcast_plmn_num; ++i) S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i]; + S1AP_REGISTER_ENB_REQ(m).mme_port[n] = mme->mme_port; S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; } if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS) return -1; - for (int i = 0; i < n_mme; ++i) { - const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme; - strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]); - S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1; - S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0; - S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn; - for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i) - S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i; - S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; - } + const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]); + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1; + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0; + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn; + for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i) + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i; + S1AP_REGISTER_ENB_REQ(m).mme_port[n] = S1AP_PORT_NUMBER; + S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m); @@ -3523,7 +3528,7 @@ int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { if (!mme) return -2; - MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SCTP_CLOSE_ASSOCIATION); + MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, 0, SCTP_CLOSE_ASSOCIATION); SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id; itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m); diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 2d8a86f7d0..79115b0a16 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -669,15 +669,16 @@ int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); /* Get the DL slice ID for a UE */ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id); /* Set the DL slice for a UE */ -void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); +int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); /* Get the UL slice ID for a UE */ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); /* Set the UL slice for a UE */ -void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); +int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); -/* Create slice in DL, returns the new slice index */ -int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); +/* Create slice in DL, returns the new slice index, object can be shared + * library for the scheduler or NULL */ +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object); /* Remove slice in DL, returns new number of slices or -1 on error */ int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); @@ -691,8 +692,9 @@ void flexran_get_dl_slice(mid_t mod_id, /* Get the number of slices in DL */ int flexran_get_num_dl_slices(mid_t mod_id); -/* Create slice in UL, returns the new slice index */ -int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); +/* Create slice in UL, returns the new slice index, object can be shared library + * for the scheduler or NULL */ +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object); /* Remove slice in UL */ int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); @@ -708,14 +710,14 @@ int flexran_get_num_ul_slices(mid_t mod_id); /* Get the name of/Set the DL scheduling algorithm. If slicing is active, this * corresponds to the default algorithm for slices, otherwise the currently - * used one. */ + * used one. object is a shared object in which to find the scheduler */ char *flexran_get_dl_scheduler_name(mid_t mod_id); -int flexran_set_dl_scheduler(mid_t mod_id, char *sched); +int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object); /* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL - * case */ + * case. object is a shared object in which to find the scheduler */ char *flexran_get_ul_scheduler_name(mid_t mod_id); -int flexran_set_ul_scheduler(mid_t mod_id, char *sched); +int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object); /************************** S1AP **************************/ /* Get the number of MMEs to be connected */ diff --git a/openair2/ENB_APP/flexran_agent_ran_api_to_fix.c b/openair2/ENB_APP/flexran_agent_ran_api_to_fix.c new file mode 100644 index 0000000000..a5eb850712 --- /dev/null +++ b/openair2/ENB_APP/flexran_agent_ran_api_to_fix.c @@ -0,0 +1,33 @@ +#include +#include +#include +pdcp_enb_t pdcp_enb[MAX_NUM_CCs]; +uint32_t Pdcp_stats_tx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB]; +uint32_t Pdcp_stats_tx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_throughput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; + +uint32_t Pdcp_stats_rx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB]; +uint32_t Pdcp_stats_rx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_goodput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_outoforder[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; + diff --git a/openair2/ENB_APP/flexran_agent_timer.c b/openair2/ENB_APP/flexran_agent_timer.c index ffbac39983..3a613ca8e5 100644 --- a/openair2/ENB_APP/flexran_agent_timer.c +++ b/openair2/ENB_APP/flexran_agent_timer.c @@ -58,6 +58,11 @@ struct timesync { int timer_num; flexran_agent_timer_element_t *timer[MAX_NUM_TIMERS]; + + int add_num; + flexran_agent_timer_element_t *add_list[MAX_NUM_TIMERS]; + int remove_num; + int remove_list[MAX_NUM_TIMERS]; pthread_mutex_t mutex_timer; int exit; @@ -76,8 +81,12 @@ err_code_t flexran_agent_timer_init(mid_t mod_id) { sync->current = 0; sync->next = 0; sync->timer_num = 0; - for (int i = 0; i < MAX_NUM_TIMERS; ++i) + sync->add_num = 0; + sync->remove_num = 0; + for (int i = 0; i < MAX_NUM_TIMERS; ++i) { sync->timer[i] = NULL; + sync->add_list[i] = NULL; + } pthread_mutex_init(&sync->mutex_timer, NULL); sync->exit = 0; @@ -170,12 +179,19 @@ void *flexran_agent_timer_thread(void *args) { break; pthread_mutex_lock(&sync->mutex_timer); - sync->current++; - - if (sync->current < sync->next) { - pthread_mutex_unlock(&sync->mutex_timer); - continue; + for (int i = 0; i < sync->add_num; ++i) { + sync->timer[sync->timer_num] = sync->add_list[i]; + sync->timer_num++; } + sync->add_num = 0; + for (int i = 0; i < sync->remove_num; ++i) + flexran_agent_timer_remove_internal(sync, sync->remove_list[i]); + sync->remove_num = 0; + pthread_mutex_unlock(&sync->mutex_timer); + + sync->current++; + if (sync->current < sync->next) + continue; for (int i = 0; i < sync->timer_num; ++i) { flexran_agent_timer_element_t *t = sync->timer[i]; @@ -186,7 +202,6 @@ void *flexran_agent_timer_thread(void *args) { if (sync->next == sync->current || t->next < sync->next) sync->next = t->next; } - pthread_mutex_unlock(&sync->mutex_timer); } LOG_W(FLEXRAN_AGENT, "terminated timer thread\n"); return NULL; @@ -230,45 +245,35 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, struct timesync *sync = ×ync[mod_id]; pthread_mutex_lock(&sync->mutex_timer); - if (sync->timer_num >= MAX_NUM_TIMERS) { + if (sync->timer_num + sync->add_num >= MAX_NUM_TIMERS) { pthread_mutex_unlock(&sync->mutex_timer); LOG_E(FLEXRAN_AGENT, "maximum number of timers (%d) reached while adding timer %d\n", - sync->timer_num, xid); + sync->timer_num + sync->add_num, xid); free(t); return TIMER_SETUP_FAILED; } /* TODO check that xid does not exist? */ - t->next = sync->current + 1; + t->next = sync->current + sf; if (sync->next <= sync->current || t->next < sync->next) sync->next = t->next; - sync->timer[sync->timer_num] = t; - sync->timer_num++; - pthread_mutex_unlock(&sync->mutex_timer); - LOG_D(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id); - return 0; -} - -err_code_t flexran_agent_destroy_timers(mid_t mod_id) { - struct timesync *sync = ×ync[mod_id]; - pthread_mutex_lock(&sync->mutex_timer); - for (int i = sync->timer_num - 1; i < 0; --i) { - flexran_agent_timer_remove_internal(sync, i); - } + sync->add_list[sync->add_num] = t; + sync->add_num++; pthread_mutex_unlock(&sync->mutex_timer); + LOG_I(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id); return 0; } err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) { struct timesync *sync = ×ync[mod_id]; - pthread_mutex_lock(&sync->mutex_timer); for (int i = 0; i < sync->timer_num; ++i) { if (sync->timer[i]->xid == xid) { - flexran_agent_timer_remove_internal(sync, i); + pthread_mutex_lock(&sync->mutex_timer); + sync->remove_list[sync->remove_num] = i; + sync->remove_num++; pthread_mutex_unlock(&sync->mutex_timer); return 0; } } - pthread_mutex_unlock(&sync->mutex_timer); LOG_E(FLEXRAN_AGENT, "could not find timer %d\n", xid); return TIMER_ELEMENT_NOT_FOUND; } @@ -277,7 +282,8 @@ err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) { void flexran_agent_timer_remove_internal(struct timesync *sync, int index) { LOG_I(FLEXRAN_AGENT, "remove timer xid %d (index %d) for agent %d\n", sync->timer[index]->xid, index, sync->timer[index]->mod_id); - flexran_agent_destroy_flexran_message(sync->timer[index]->msg); + if (sync->timer[index]->msg) + flexran_agent_destroy_flexran_message(sync->timer[index]->msg); free(sync->timer[index]); for (int i = index + 1; i < sync->timer_num; ++i) sync->timer[i - 1] = sync->timer[i]; diff --git a/openair2/ENB_APP/flexran_agent_timer.h b/openair2/ENB_APP/flexran_agent_timer.h index b1cf8df51f..c61f2543a3 100644 --- a/openair2/ENB_APP/flexran_agent_timer.h +++ b/openair2/ENB_APP/flexran_agent_timer.h @@ -61,9 +61,6 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, flexran_agent_timer_callback_t cb, Protocol__FlexranMessage *msg); -/* Destroy all existing timers */ -err_code_t flexran_agent_destroy_timers(mid_t mod_id); - /* Destroy the timer for task with id xid */ err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid); diff --git a/openair2/ENB_APP/flexran_apps/imsi.c b/openair2/ENB_APP/flexran_apps/imsi.c new file mode 100644 index 0000000000..6f75033f38 --- /dev/null +++ b/openair2/ENB_APP/flexran_apps/imsi.c @@ -0,0 +1,245 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file imsi.c + * \brief flexran IMSI UE-slice association app + * \author Robert Schmidt, Firas Abdeljelil + * \date 2020 + * \version 0.1 + */ + +#include +#include +#include +#include "flexran_agent_common.h" +#include "flexran_agent_async.h" +#include "flexran_agent_extern.h" +#include "flexran_agent_timer.h" +#include "flexran_agent_defs.h" +#include "flexran_agent_net_comm.h" +#include "flexran_agent_ran_api.h" +#include "flexran_agent_phy.h" +#include "flexran_agent_mac.h" +#include "flexran_agent_rrc.h" +#include "flexran_agent_pdcp.h" +#include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" +#include "common/utils/LOG/log.h" +#include "assertions.h" +#include "queue.h" +typedef struct Map_regex_slice slist_data_t; +struct Map_regex_slice { + char regex_[30] ; + int slice_dl; + int slice_ul; + regex_t regex; + SLIST_ENTRY (Map_regex_slice) entries; +}; +bool reconfig = false; +int ue[MAX_MOBILES_PER_ENB]={ [0 ... MAX_MOBILES_PER_ENB - 1] = -1 }; + +SLIST_HEAD(slisthead, Map_regex_slice) head; + +int dump_list(void) { + int len = 1; + slist_data_t *datap = NULL; + SLIST_FOREACH(datap, &head, entries) { + LOG_W(FLEXRAN_AGENT, "%d: regex %s DL %d UL %d\n", len++, datap->regex_, + datap->slice_dl, datap->slice_ul); + } + return len; +} + +void add(char *regex, int dl, int ul) { + slist_data_t *datap = malloc(sizeof(slist_data_t)); + if (!datap) { + LOG_E(FLEXRAN_AGENT, "cannot allocate memory for slist_data_t\n"); + return; + } + strcpy(datap->regex_, regex); + datap->slice_dl = dl; + datap->slice_ul = ul; + regcomp(&datap->regex, datap->regex_, 0); + SLIST_INSERT_HEAD(&head, datap, entries); + if (ul==-1) + LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice DL %d\n" ,regex, dl); + else if (dl==-1) + LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice UL %d\n" ,regex, ul); + else + LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice DL %d UL %d\n", + regex, dl, ul); +} +void remove_(char *regex) { + slist_data_t *datap = NULL; + SLIST_FOREACH(datap, &head, entries) { + if (strcmp(datap->regex_, regex) == 0) { + SLIST_REMOVE(&head, datap, Map_regex_slice, entries); + if (datap->slice_dl==-1) + LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice UL %d\n",datap->regex_, datap->slice_ul); + else if (datap->slice_ul==-1) + LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice DL %d\n",datap->regex_, datap->slice_dl); + else + LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice DL %d UL %d\n", + datap->regex_, datap->slice_dl, datap->slice_ul); + regfree(&datap->regex); + free(datap); + return; + } + } + LOG_E(FLEXRAN_AGENT, "no regex %s found in list\n", regex); +} + +Protocol__FlexranMessage *matching_tick( + mid_t mod_id, + const Protocol__FlexranMessage *msg) { + const int num = flexran_get_mac_num_ues(mod_id); + for (int i = 0; i < num; i++) { + int ue_id = flexran_get_mac_ue_id(mod_id, i); + if (ue[ue_id] >= 0 && !reconfig) + continue; + rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); + uint64_t imsi = flexran_get_ue_imsi(mod_id, rnti); + char snum[20]; + sprintf(snum, "%" PRIu64, imsi); + slist_data_t *datap = NULL; + SLIST_FOREACH(datap, &head, entries) { + if (regexec(&datap->regex, snum, 0, NULL, 0) == 0) { + + int dl = datap->slice_dl; + if (dl >= 0 && dl != flexran_get_ue_dl_slice_id(mod_id, ue_id)) { + int ra = flexran_set_ue_dl_slice_id(mod_id, ue_id, dl); + if (ra) + LOG_I(FLEXRAN_AGENT, + "RNTI %04x/IMSI %s in the slice_dl %d\n", + rnti, + snum, + dl); + else + LOG_W(FLEXRAN_AGENT, "No such DL slice %d\n", dl); + } + + int ul = datap->slice_ul; + if (ul >= 0 && ul != flexran_get_ue_ul_slice_id(mod_id, ue_id)) { + int rb = flexran_set_ue_ul_slice_id(mod_id, ue_id, ul); + if (rb) + LOG_I(FLEXRAN_AGENT, + "RNTI %04x/IMSI %s in the slice_ul %d\n", + rnti, + snum, + ul); + else + LOG_W(FLEXRAN_AGENT, "No such DL slice %d\n", dl); + } + } + } + ue[ue_id] = ue_id; + } + reconfig = false; + return NULL; +} +void add_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) { + char s[30]; + reconfig = true; + bool supp=false; + bool sl_E=false; + int dl=-1; + int ul=-1; + slist_data_t *datap = NULL; + for (int i = 0; i < n_p; ++i) { + switch (p[i]->value->param_case) { + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM__NOT_SET: + LOG_I(FLEXRAN_AGENT, " param %s is not set\n", p[i]->key); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_INTEGER: + if( strcmp(p[i]->key, "slice_dl")==0) + dl= p[i]->value->integer; + else + ul= p[i]->value->integer; + sl_E=true; + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_STR: + strcpy(s,p[i]->value->str); + break; + default: + LOG_W(FLEXRAN_AGENT, " type of param %s is unknown\n", p[i]->key); + break; + }; + } + if (!SLIST_EMPTY(&head)){ + SLIST_FOREACH(datap, &head, entries) { + if (strcmp(datap->regex_, s) == 0) { + if (datap->slice_dl!=dl || datap->slice_ul!=ul) + supp=true; + } + } + } + if (sl_E==false) + remove_(s); + else { + if (supp==true) + remove_(s); + add(s,dl,ul); + } + /* re-verify all UEs again */ + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + ue[i] = -1; +} +/* imsi_start: entry point for imsi app. Installs a callback using the timer + * API to have function imsi_tick() called every 5s */ +#define TIMER 32 +int imsi_start(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p) +{ + LOG_W(FLEXRAN_AGENT, "%s(): enable IMSI app timer\n", __func__); + flexran_agent_create_timer(mod_id, + 500, + FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, + TIMER, + matching_tick, + NULL); + SLIST_INIT(&head); + return 0; +} + +int imsi_reconfig(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p) +{ + add_param(p, n_p); + return 0; +} + +/* stop function: cleans up before app can be unloaded. Here: stop the timer */ +int imsi_stop(mid_t mod_id) { + LOG_W(FLEXRAN_AGENT, "%s(): disable IMSI app timer\n", __func__); + flexran_agent_destroy_timer(mod_id, TIMER); + + return 0; +} + +/* app definition. visibility should be set to default so this symbol is + * reachable from outside */ +flexran_agent_app_t __attribute__ ((visibility ("default"))) app = { + .start = imsi_start, + .reconfig = imsi_reconfig, + .stop = imsi_stop +}; diff --git a/openair2/ENB_APP/flexran_apps/sample.c b/openair2/ENB_APP/flexran_apps/sample.c new file mode 100644 index 0000000000..65be2a43df --- /dev/null +++ b/openair2/ENB_APP/flexran_apps/sample.c @@ -0,0 +1,121 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file sample.c + * \brief flexran sample app + * \author Robert Schmidt + * \date 2020 + * \version 0.1 + */ + +#include "flexran_agent_common.h" +#include "flexran_agent_async.h" +#include "flexran_agent_extern.h" +#include "flexran_agent_timer.h" +#include "flexran_agent_defs.h" +#include "flexran_agent_net_comm.h" +#include "flexran_agent_ran_api.h" +#include "flexran_agent_phy.h" +#include "flexran_agent_mac.h" +#include "flexran_agent_rrc.h" +#include "flexran_agent_pdcp.h" +#include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" +#include "common/utils/LOG/log.h" +#include "assertions.h" + +/* callback to be called for event: shows exemplary variable use and use of RAN + * API */ +int tick; +Protocol__FlexranMessage *sample_tick( + mid_t mod_id, + const Protocol__FlexranMessage *msg) { + tick++; + const int num = flexran_get_mac_num_ues(mod_id); + LOG_I(FLEXRAN_AGENT, "%s(): tick %d number UEs %d\n", __func__, tick, num); + return NULL; +} + +void print_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) { + LOG_I(FLEXRAN_AGENT, "%s(): received %d parameters\n", __func__, n_p); + for (int i = 0; i < n_p; ++i) { + switch (p[i]->value->param_case) { + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM__NOT_SET: + LOG_I(FLEXRAN_AGENT, " param %s is not set\n", p[i]->key); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_INTEGER: + LOG_I(FLEXRAN_AGENT, " param %s is %d\n", p[i]->key, p[i]->value->integer); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_FLOATING: + LOG_I(FLEXRAN_AGENT, " param %s is %f\n", p[i]->key, p[i]->value->floating); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_BOOLEAN: + LOG_I(FLEXRAN_AGENT, " param %s is %s\n", p[i]->key, p[i]->value->boolean ? "true" : "false"); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_STR: + LOG_I(FLEXRAN_AGENT, " param %s is %s\n", p[i]->key, p[i]->value->str); + break; + default: + LOG_W(FLEXRAN_AGENT, " type of param %s is unknown\n", p[i]->key); + break; + }; + } +} + +/* sa_start: entry point for sample app. Installs a callback using the timer + * API to have function sample_tick() called every 5s */ +#define TIMER 22 +int sa_start(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p) { + LOG_W(FLEXRAN_AGENT, "%s(): enable sample app timer\n", __func__); + flexran_agent_create_timer(mod_id, + 5000, + FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, + TIMER, + sample_tick, + NULL); + print_param(p, n_p); + return 0; +} + +int sa_reconfig(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p) +{ + print_param(p, n_p); + return 0; +} + +/* stop function: cleans up before app can be unloaded. Here: stop the timer */ +int sa_stop(mid_t mod_id) { + LOG_W(FLEXRAN_AGENT, "%s(): disable sample app timer\n", __func__); + flexran_agent_destroy_timer(mod_id, TIMER); + return 0; +} + +/* app definition. visibility should be set to default so this symbol is + * reachable from outside */ +flexran_agent_app_t __attribute__ ((visibility ("default"))) app = { + .start = sa_start, + .reconfig = sa_reconfig, + .stop = sa_stop +}; diff --git a/openair2/F1AP/MESSAGES/ASN1/R16.3.1/38473-g31.asn b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/38473-g31.asn new file mode 100644 index 0000000000..c821c52010 --- /dev/null +++ b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/38473-g31.asn @@ -0,0 +1,10721 @@ +-- ASN1START +-- ************************************************************** +-- +-- Elementary Procedure definitions +-- +-- ************************************************************** + +F1AP-PDU-Descriptions { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-PDU-Descriptions (0)} + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + Criticality, + ProcedureCode + +FROM F1AP-CommonDataTypes + Reset, + ResetAcknowledge, + F1SetupRequest, + F1SetupResponse, + F1SetupFailure, + GNBDUConfigurationUpdate, + GNBDUConfigurationUpdateAcknowledge, + GNBDUConfigurationUpdateFailure, + GNBCUConfigurationUpdate, + GNBCUConfigurationUpdateAcknowledge, + GNBCUConfigurationUpdateFailure, + UEContextSetupRequest, + UEContextSetupResponse, + UEContextSetupFailure, + UEContextReleaseCommand, + UEContextReleaseComplete, + UEContextModificationRequest, + UEContextModificationResponse, + UEContextModificationFailure, + UEContextModificationRequired, + UEContextModificationConfirm, + ErrorIndication, + UEContextReleaseRequest, + DLRRCMessageTransfer, + ULRRCMessageTransfer, + GNBDUResourceCoordinationRequest, + GNBDUResourceCoordinationResponse, + PrivateMessage, + UEInactivityNotification, + InitialULRRCMessageTransfer, + SystemInformationDeliveryCommand, + Paging, + Notify, + WriteReplaceWarningRequest, + WriteReplaceWarningResponse, + PWSCancelRequest, + PWSCancelResponse, + PWSRestartIndication, + PWSFailureIndication, + GNBDUStatusIndication, + RRCDeliveryReport, + UEContextModificationRefuse, + F1RemovalRequest, + F1RemovalResponse, + F1RemovalFailure, + NetworkAccessRateReduction, + TraceStart, + DeactivateTrace, + DUCURadioInformationTransfer, + CUDURadioInformationTransfer, + BAPMappingConfiguration, + BAPMappingConfigurationAcknowledge, + GNBDUResourceConfiguration, + GNBDUResourceConfigurationAcknowledge, + IABTNLAddressRequest, + IABTNLAddressResponse, + IABUPConfigurationUpdateRequest, + IABUPConfigurationUpdateResponse, + IABUPConfigurationUpdateFailure, + ResourceStatusRequest, + ResourceStatusResponse, + ResourceStatusFailure, + ResourceStatusUpdate, + AccessAndMobilityIndication, + ReferenceTimeInformationReportingControl, + ReferenceTimeInformationReport, + AccessSuccess, + CellTrafficTrace, + PositioningMeasurementRequest, + PositioningMeasurementResponse, + PositioningMeasurementFailure, + PositioningAssistanceInformationControl, + PositioningAssistanceInformationFeedback, + PositioningMeasurementReport, + PositioningMeasurementAbort, + PositioningMeasurementFailureIndication, + PositioningMeasurementUpdate, + TRPInformationRequest, + TRPInformationResponse, + TRPInformationFailure, + PositioningInformationRequest, + PositioningInformationResponse, + PositioningInformationFailure, + PositioningActivationRequest, + PositioningActivationResponse, + PositioningActivationFailure, + PositioningDeactivation, + PositioningInformationUpdate, + E-CIDMeasurementInitiationRequest, + E-CIDMeasurementInitiationResponse, + E-CIDMeasurementInitiationFailure, + E-CIDMeasurementFailureIndication, + E-CIDMeasurementReport, + E-CIDMeasurementTerminationCommand + + + +FROM F1AP-PDU-Contents + id-Reset, + id-F1Setup, + id-gNBDUConfigurationUpdate, + id-gNBCUConfigurationUpdate, + id-UEContextSetup, + id-UEContextRelease, + id-UEContextModification, + id-UEContextModificationRequired, + id-ErrorIndication, + id-UEContextReleaseRequest, + id-DLRRCMessageTransfer, + id-ULRRCMessageTransfer, + id-GNBDUResourceCoordination, + id-privateMessage, + id-UEInactivityNotification, + id-InitialULRRCMessageTransfer, + id-SystemInformationDeliveryCommand, + id-Paging, + id-Notify, + id-WriteReplaceWarning, + id-PWSCancel, + id-PWSRestartIndication, + id-PWSFailureIndication, + id-GNBDUStatusIndication, + id-RRCDeliveryReport, + id-F1Removal, + id-NetworkAccessRateReduction, + id-TraceStart, + id-DeactivateTrace, + id-DUCURadioInformationTransfer, + id-CUDURadioInformationTransfer, + id-BAPMappingConfiguration, + id-GNBDUResourceConfiguration, + id-IABTNLAddressAllocation, + id-IABUPConfigurationUpdate, + id-resourceStatusReportingInitiation, + id-resourceStatusReporting, + id-accessAndMobilityIndication, + id-ReferenceTimeInformationReportingControl, + id-ReferenceTimeInformationReport, + id-accessSuccess, + id-cellTrafficTrace, + id-PositioningMeasurementExchange, + id-PositioningAssistanceInformationControl, + id-PositioningAssistanceInformationFeedback, + id-PositioningMeasurementReport, + id-PositioningMeasurementAbort, + id-PositioningMeasurementFailureIndication, + id-PositioningMeasurementUpdate, + id-TRPInformationExchange, + id-PositioningInformationExchange, + id-PositioningActivation, + id-PositioningDeactivation, + id-PositioningInformationUpdate, + id-E-CIDMeasurementInitiation, + id-E-CIDMeasurementFailureIndication, + id-E-CIDMeasurementReport, + id-E-CIDMeasurementTermination + + +FROM F1AP-Constants + + ProtocolIE-SingleContainer{}, + F1AP-PROTOCOL-IES + +FROM F1AP-Containers; + + +-- ************************************************************** +-- +-- Interface Elementary Procedure Class +-- +-- ************************************************************** + +F1AP-ELEMENTARY-PROCEDURE ::= CLASS { + &InitiatingMessage , + &SuccessfulOutcome OPTIONAL, + &UnsuccessfulOutcome OPTIONAL, + &procedureCode ProcedureCode UNIQUE, + &criticality Criticality DEFAULT ignore +} +WITH SYNTAX { + INITIATING MESSAGE &InitiatingMessage + [SUCCESSFUL OUTCOME &SuccessfulOutcome] + [UNSUCCESSFUL OUTCOME &UnsuccessfulOutcome] + PROCEDURE CODE &procedureCode + [CRITICALITY &criticality] +} + +-- ************************************************************** +-- +-- Interface PDU Definition +-- +-- ************************************************************** + +F1AP-PDU ::= CHOICE { + initiatingMessage InitiatingMessage, + successfulOutcome SuccessfulOutcome, + unsuccessfulOutcome UnsuccessfulOutcome, + choice-extension ProtocolIE-SingleContainer { { F1AP-PDU-ExtIEs} } +} + +F1AP-PDU-ExtIEs F1AP-PROTOCOL-IES ::= { -- this extension is not used + ... +} + +InitiatingMessage ::= SEQUENCE { + procedureCode F1AP-ELEMENTARY-PROCEDURE.&procedureCode ({F1AP-ELEMENTARY-PROCEDURES}), + criticality F1AP-ELEMENTARY-PROCEDURE.&criticality ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value F1AP-ELEMENTARY-PROCEDURE.&InitiatingMessage ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +SuccessfulOutcome ::= SEQUENCE { + procedureCode F1AP-ELEMENTARY-PROCEDURE.&procedureCode ({F1AP-ELEMENTARY-PROCEDURES}), + criticality F1AP-ELEMENTARY-PROCEDURE.&criticality ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value F1AP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +UnsuccessfulOutcome ::= SEQUENCE { + procedureCode F1AP-ELEMENTARY-PROCEDURE.&procedureCode ({F1AP-ELEMENTARY-PROCEDURES}), + criticality F1AP-ELEMENTARY-PROCEDURE.&criticality ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value F1AP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +-- ************************************************************** +-- +-- Interface Elementary Procedure List +-- +-- ************************************************************** + +F1AP-ELEMENTARY-PROCEDURES F1AP-ELEMENTARY-PROCEDURE ::= { + F1AP-ELEMENTARY-PROCEDURES-CLASS-1 | + F1AP-ELEMENTARY-PROCEDURES-CLASS-2, + ... +} + + +F1AP-ELEMENTARY-PROCEDURES-CLASS-1 F1AP-ELEMENTARY-PROCEDURE ::= { + reset | + f1Setup | + gNBDUConfigurationUpdate | + gNBCUConfigurationUpdate | + uEContextSetup | + uEContextRelease | + uEContextModification | + uEContextModificationRequired | + writeReplaceWarning | + pWSCancel | + gNBDUResourceCoordination | + f1Removal | + bAPMappingConfiguration | + gNBDUResourceConfiguration | + iABTNLAddressAllocation | + iABUPConfigurationUpdate | + resourceStatusReportingInitiation | + positioningMeasurementExchange | + tRPInformationExchange | + positioningInformationExchange | + positioningActivation | + e-CIDMeasurementInitiation, + ... +} + +F1AP-ELEMENTARY-PROCEDURES-CLASS-2 F1AP-ELEMENTARY-PROCEDURE ::= { + errorIndication | + uEContextReleaseRequest | + dLRRCMessageTransfer | + uLRRCMessageTransfer | + uEInactivityNotification | + privateMessage | + initialULRRCMessageTransfer | + systemInformationDelivery | + paging | + notify | + pWSRestartIndication | + pWSFailureIndication | + gNBDUStatusIndication | + rRCDeliveryReport | + networkAccessRateReduction | + traceStart | + deactivateTrace | + dUCURadioInformationTransfer | + cUDURadioInformationTransfer | + resourceStatusReporting | + accessAndMobilityIndication | + referenceTimeInformationReportingControl| + referenceTimeInformationReport | + accessSuccess | + cellTrafficTrace | + positioningAssistanceInformationControl | + positioningAssistanceInformationFeedback | + positioningMeasurementReport | + positioningMeasurementAbort | + positioningMeasurementFailureIndication | + positioningMeasurementUpdate | + positioningDeactivation | + e-CIDMeasurementFailureIndication | + e-CIDMeasurementReport | + e-CIDMeasurementTermination | + positioningInformationUpdate, + ... +} +-- ************************************************************** +-- +-- Interface Elementary Procedures +-- +-- ************************************************************** + +reset F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE Reset + SUCCESSFUL OUTCOME ResetAcknowledge + PROCEDURE CODE id-Reset + CRITICALITY reject +} + +f1Setup F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE F1SetupRequest + SUCCESSFUL OUTCOME F1SetupResponse + UNSUCCESSFUL OUTCOME F1SetupFailure + PROCEDURE CODE id-F1Setup + CRITICALITY reject +} + +gNBDUConfigurationUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBDUConfigurationUpdate + SUCCESSFUL OUTCOME GNBDUConfigurationUpdateAcknowledge + UNSUCCESSFUL OUTCOME GNBDUConfigurationUpdateFailure + PROCEDURE CODE id-gNBDUConfigurationUpdate + CRITICALITY reject +} + +gNBCUConfigurationUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBCUConfigurationUpdate + SUCCESSFUL OUTCOME GNBCUConfigurationUpdateAcknowledge + UNSUCCESSFUL OUTCOME GNBCUConfigurationUpdateFailure + PROCEDURE CODE id-gNBCUConfigurationUpdate + CRITICALITY reject +} + +uEContextSetup F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextSetupRequest + SUCCESSFUL OUTCOME UEContextSetupResponse + UNSUCCESSFUL OUTCOME UEContextSetupFailure + PROCEDURE CODE id-UEContextSetup + CRITICALITY reject +} + +uEContextRelease F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextReleaseCommand + SUCCESSFUL OUTCOME UEContextReleaseComplete + PROCEDURE CODE id-UEContextRelease + CRITICALITY reject +} + +uEContextModification F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextModificationRequest + SUCCESSFUL OUTCOME UEContextModificationResponse + UNSUCCESSFUL OUTCOME UEContextModificationFailure + PROCEDURE CODE id-UEContextModification + CRITICALITY reject +} + +uEContextModificationRequired F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextModificationRequired + SUCCESSFUL OUTCOME UEContextModificationConfirm + UNSUCCESSFUL OUTCOME UEContextModificationRefuse + PROCEDURE CODE id-UEContextModificationRequired + CRITICALITY reject +} + +writeReplaceWarning F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE WriteReplaceWarningRequest + SUCCESSFUL OUTCOME WriteReplaceWarningResponse + PROCEDURE CODE id-WriteReplaceWarning + CRITICALITY reject +} + +pWSCancel F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSCancelRequest + SUCCESSFUL OUTCOME PWSCancelResponse + PROCEDURE CODE id-PWSCancel + CRITICALITY reject +} + +errorIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ErrorIndication + PROCEDURE CODE id-ErrorIndication + CRITICALITY ignore +} + +uEContextReleaseRequest F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextReleaseRequest + PROCEDURE CODE id-UEContextReleaseRequest + CRITICALITY ignore +} + + +initialULRRCMessageTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE InitialULRRCMessageTransfer + PROCEDURE CODE id-InitialULRRCMessageTransfer + CRITICALITY ignore +} + +dLRRCMessageTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DLRRCMessageTransfer + PROCEDURE CODE id-DLRRCMessageTransfer + CRITICALITY ignore +} + +uLRRCMessageTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ULRRCMessageTransfer + PROCEDURE CODE id-ULRRCMessageTransfer + CRITICALITY ignore +} + + +uEInactivityNotification F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEInactivityNotification + PROCEDURE CODE id-UEInactivityNotification + CRITICALITY ignore +} + +gNBDUResourceCoordination F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBDUResourceCoordinationRequest + SUCCESSFUL OUTCOME GNBDUResourceCoordinationResponse + PROCEDURE CODE id-GNBDUResourceCoordination + CRITICALITY reject +} + +privateMessage F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PrivateMessage + PROCEDURE CODE id-privateMessage + CRITICALITY ignore +} + +systemInformationDelivery F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE SystemInformationDeliveryCommand + PROCEDURE CODE id-SystemInformationDeliveryCommand + CRITICALITY ignore +} + + +paging F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE Paging + PROCEDURE CODE id-Paging + CRITICALITY ignore +} + +notify F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE Notify + PROCEDURE CODE id-Notify + CRITICALITY ignore +} + +networkAccessRateReduction F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE NetworkAccessRateReduction + PROCEDURE CODE id-NetworkAccessRateReduction + CRITICALITY ignore +} + + +pWSRestartIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSRestartIndication + PROCEDURE CODE id-PWSRestartIndication + CRITICALITY ignore +} + +pWSFailureIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSFailureIndication + PROCEDURE CODE id-PWSFailureIndication + CRITICALITY ignore +} + +gNBDUStatusIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBDUStatusIndication + PROCEDURE CODE id-GNBDUStatusIndication + CRITICALITY ignore +} + + +rRCDeliveryReport F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RRCDeliveryReport + PROCEDURE CODE id-RRCDeliveryReport + CRITICALITY ignore +} + +f1Removal F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE F1RemovalRequest + SUCCESSFUL OUTCOME F1RemovalResponse + UNSUCCESSFUL OUTCOME F1RemovalFailure + PROCEDURE CODE id-F1Removal + CRITICALITY reject +} + +traceStart F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE TraceStart + PROCEDURE CODE id-TraceStart + CRITICALITY ignore +} + +deactivateTrace F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DeactivateTrace + PROCEDURE CODE id-DeactivateTrace + CRITICALITY ignore +} + +dUCURadioInformationTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DUCURadioInformationTransfer + PROCEDURE CODE id-DUCURadioInformationTransfer + CRITICALITY ignore +} + +cUDURadioInformationTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CUDURadioInformationTransfer + PROCEDURE CODE id-CUDURadioInformationTransfer + CRITICALITY ignore +} + +bAPMappingConfiguration F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE BAPMappingConfiguration + SUCCESSFUL OUTCOME BAPMappingConfigurationAcknowledge + PROCEDURE CODE id-BAPMappingConfiguration + CRITICALITY reject +} + +gNBDUResourceConfiguration F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBDUResourceConfiguration + SUCCESSFUL OUTCOME GNBDUResourceConfigurationAcknowledge + PROCEDURE CODE id-GNBDUResourceConfiguration + CRITICALITY reject +} + +iABTNLAddressAllocation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE IABTNLAddressRequest + SUCCESSFUL OUTCOME IABTNLAddressResponse + PROCEDURE CODE id-IABTNLAddressAllocation + CRITICALITY reject +} + +iABUPConfigurationUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE IABUPConfigurationUpdateRequest + SUCCESSFUL OUTCOME IABUPConfigurationUpdateResponse + UNSUCCESSFUL OUTCOME IABUPConfigurationUpdateFailure + PROCEDURE CODE id-IABUPConfigurationUpdate + CRITICALITY reject +} + +resourceStatusReportingInitiation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ResourceStatusRequest + SUCCESSFUL OUTCOME ResourceStatusResponse + UNSUCCESSFUL OUTCOME ResourceStatusFailure + PROCEDURE CODE id-resourceStatusReportingInitiation + CRITICALITY reject +} + +resourceStatusReporting F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ResourceStatusUpdate + PROCEDURE CODE id-resourceStatusReporting + CRITICALITY ignore +} + +accessAndMobilityIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE AccessAndMobilityIndication + PROCEDURE CODE id-accessAndMobilityIndication + CRITICALITY ignore +} + +referenceTimeInformationReportingControl F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ReferenceTimeInformationReportingControl + PROCEDURE CODE id-ReferenceTimeInformationReportingControl + CRITICALITY ignore +} + +referenceTimeInformationReport F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ReferenceTimeInformationReport + PROCEDURE CODE id-ReferenceTimeInformationReport + CRITICALITY ignore +} + +accessSuccess F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE AccessSuccess + PROCEDURE CODE id-accessSuccess + CRITICALITY ignore +} + +cellTrafficTrace F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellTrafficTrace + PROCEDURE CODE id-cellTrafficTrace + CRITICALITY ignore +} + +positioningAssistanceInformationControl F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningAssistanceInformationControl + PROCEDURE CODE id-PositioningAssistanceInformationControl + CRITICALITY ignore +} + +positioningAssistanceInformationFeedback F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningAssistanceInformationFeedback + PROCEDURE CODE id-PositioningAssistanceInformationFeedback + CRITICALITY ignore +} + +positioningMeasurementExchange F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementRequest + SUCCESSFUL OUTCOME PositioningMeasurementResponse + UNSUCCESSFUL OUTCOME PositioningMeasurementFailure + PROCEDURE CODE id-PositioningMeasurementExchange + CRITICALITY reject +} + +positioningMeasurementReport F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementReport + PROCEDURE CODE id-PositioningMeasurementReport + CRITICALITY ignore +} + +positioningMeasurementAbort F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementAbort + PROCEDURE CODE id-PositioningMeasurementAbort + CRITICALITY ignore +} + +positioningMeasurementFailureIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementFailureIndication + PROCEDURE CODE id-PositioningMeasurementFailureIndication + CRITICALITY ignore +} + +positioningMeasurementUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementUpdate + PROCEDURE CODE id-PositioningMeasurementUpdate + CRITICALITY ignore +} + + +tRPInformationExchange F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE TRPInformationRequest + SUCCESSFUL OUTCOME TRPInformationResponse + UNSUCCESSFUL OUTCOME TRPInformationFailure + PROCEDURE CODE id-TRPInformationExchange + CRITICALITY reject +} + +positioningInformationExchange F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningInformationRequest + SUCCESSFUL OUTCOME PositioningInformationResponse + UNSUCCESSFUL OUTCOME PositioningInformationFailure + PROCEDURE CODE id-PositioningInformationExchange + CRITICALITY reject +} + +positioningActivation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningActivationRequest + SUCCESSFUL OUTCOME PositioningActivationResponse + UNSUCCESSFUL OUTCOME PositioningActivationFailure + PROCEDURE CODE id-PositioningActivation + CRITICALITY reject +} + +positioningDeactivation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningDeactivation + PROCEDURE CODE id-PositioningDeactivation + CRITICALITY ignore +} + +e-CIDMeasurementInitiation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE E-CIDMeasurementInitiationRequest + SUCCESSFUL OUTCOME E-CIDMeasurementInitiationResponse + UNSUCCESSFUL OUTCOME E-CIDMeasurementInitiationFailure + PROCEDURE CODE id-E-CIDMeasurementInitiation + CRITICALITY reject +} + +e-CIDMeasurementFailureIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE E-CIDMeasurementFailureIndication + PROCEDURE CODE id-E-CIDMeasurementFailureIndication + CRITICALITY ignore +} + +e-CIDMeasurementReport F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE E-CIDMeasurementReport + PROCEDURE CODE id-E-CIDMeasurementReport + CRITICALITY ignore +} + +e-CIDMeasurementTermination F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE E-CIDMeasurementTerminationCommand + PROCEDURE CODE id-E-CIDMeasurementTermination + CRITICALITY ignore +} + +positioningInformationUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningInformationUpdate + PROCEDURE CODE id-PositioningInformationUpdate + CRITICALITY ignore +} + + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- PDU definitions for F1AP. +-- +-- ************************************************************** + +F1AP-PDU-Contents { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-PDU-Contents (1) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + Candidate-SpCell-Item, + Cause, + Cells-Failed-to-be-Activated-List-Item, + Cells-Status-Item, + Cells-to-be-Activated-List-Item, + Cells-to-be-Deactivated-List-Item, + CellULConfigured, + CriticalityDiagnostics, + C-RNTI, + CUtoDURRCInformation, + DRB-Activity-Item, + DRBID, + DRBs-FailedToBeModified-Item, + DRBs-FailedToBeSetup-Item, + DRBs-FailedToBeSetupMod-Item, + DRB-Notify-Item, + DRBs-ModifiedConf-Item, + DRBs-Modified-Item, + DRBs-Required-ToBeModified-Item, + DRBs-Required-ToBeReleased-Item, + DRBs-Setup-Item, + DRBs-SetupMod-Item, + DRBs-ToBeModified-Item, + DRBs-ToBeReleased-Item, + DRBs-ToBeSetup-Item, + DRBs-ToBeSetupMod-Item, + DRXCycle, + DRXConfigurationIndicator, + DUtoCURRCInformation, + EUTRANQoS, + ExecuteDuplication, + FullConfiguration, + GNB-CU-UE-F1AP-ID, + GNB-DU-UE-F1AP-ID, + GNB-DU-ID, + GNB-DU-Served-Cells-Item, + GNB-DU-System-Information, + GNB-CU-Name, + GNB-DU-Name, + InactivityMonitoringRequest, + InactivityMonitoringResponse, + LowerLayerPresenceStatusChange, + NotificationControl, + NRCGI, + NRPCI, + UEContextNotRetrievable, + Potential-SpCell-Item, + RAT-FrequencyPriorityInformation, + RequestedSRSTransmissionCharacteristics, + ResourceCoordinationTransferContainer, + RRCContainer, + RRCContainer-RRCSetupComplete, + RRCReconfigurationCompleteIndicator, + SCellIndex, + SCell-ToBeRemoved-Item, + SCell-ToBeSetup-Item, + SCell-ToBeSetupMod-Item, + SCell-FailedtoSetup-Item, + SCell-FailedtoSetupMod-Item, + ServCellIndex, + Served-Cell-Information, + Served-Cells-To-Add-Item, + Served-Cells-To-Delete-Item, + Served-Cells-To-Modify-Item, + ServingCellMO, + SRBID, + SRBs-FailedToBeSetup-Item, + SRBs-FailedToBeSetupMod-Item, + SRBs-Required-ToBeReleased-Item, + SRBs-ToBeReleased-Item, + SRBs-ToBeSetup-Item, + SRBs-ToBeSetupMod-Item, + SRBs-Modified-Item, + SRBs-Setup-Item, + SRBs-SetupMod-Item, + TimeToWait, + TransactionID, + TransmissionActionIndicator, + UE-associatedLogicalF1-ConnectionItem, + DUtoCURRCContainer, + PagingCell-Item, + SItype-List, + UEIdentityIndexValue, + GNB-CU-TNL-Association-Setup-Item, + GNB-CU-TNL-Association-Failed-To-Setup-Item, + GNB-CU-TNL-Association-To-Add-Item, + GNB-CU-TNL-Association-To-Remove-Item, + GNB-CU-TNL-Association-To-Update-Item, + MaskedIMEISV, + PagingDRX, + PagingPriority, + PagingIdentity, + Cells-to-be-Barred-Item, + PWSSystemInformation, + Broadcast-To-Be-Cancelled-Item, + Cells-Broadcast-Cancelled-Item, + NR-CGI-List-For-Restart-Item, + PWS-Failed-NR-CGI-Item, + RepetitionPeriod, + NumberofBroadcastRequest, + Cells-To-Be-Broadcast-Item, + Cells-Broadcast-Completed-Item, + Cancel-all-Warning-Messages-Indicator, + EUTRA-NR-CellResourceCoordinationReq-Container, + EUTRA-NR-CellResourceCoordinationReqAck-Container, + RequestType, + PLMN-Identity, + RLCFailureIndication, + UplinkTxDirectCurrentListInformation, + SULAccessIndication, + Protected-EUTRA-Resources-Item, + GNB-DUConfigurationQuery, + BitRate, + RRC-Version, + GNBDUOverloadInformation, + RRCDeliveryStatusRequest, + NeedforGap, + RRCDeliveryStatus, + ResourceCoordinationTransferInformation, + Dedicated-SIDelivery-NeededUE-Item, + Associated-SCell-Item, + IgnoreResourceCoordinationContainer, + PagingOrigin, + UAC-Assistance-Info, + RANUEID, + GNB-DU-TNL-Association-To-Remove-Item, + NotificationInformation, + TraceActivation, + TraceID, + Neighbour-Cell-Information-Item, + SymbolAllocInSlot, + NumDLULSymbols, + AdditionalRRMPriorityIndex, + DUCURadioInformationType, + CUDURadioInformationType, + Transport-Layer-Address-Info, + BHChannels-ToBeSetup-Item, + BHChannels-Setup-Item, + BHChannels-FailedToBeSetup-Item, + BHChannels-ToBeModified-Item, + BHChannels-ToBeReleased-Item, + BHChannels-ToBeSetupMod-Item, + BHChannels-FailedToBeModified-Item, + BHChannels-FailedToBeSetupMod-Item, + BHChannels-Modified-Item, + BHChannels-SetupMod-Item, + BHChannels-Required-ToBeReleased-Item, + BAPAddress, + BAPPathID, + BAPRoutingID, + BH-Routing-Information-Added-List-Item, + BH-Routing-Information-Removed-List-Item, + Child-Nodes-List, + Child-Nodes-List-Item, + Child-Node-Cells-List, + Child-Node-Cells-List-Item, + Activated-Cells-to-be-Updated-List, + Activated-Cells-to-be-Updated-List-Item, + UL-BH-Non-UP-Traffic-Mapping, + IABTNLAddressesRequested, + IABIPv6RequestType, + IAB-TNL-Addresses-To-Remove-Item, + IABTNLAddress, + IAB-Allocated-TNL-Address-Item, + IABv4AddressesRequested, + TrafficMappingInfo, + UL-UP-TNL-Information-to-Update-List-Item, + UL-UP-TNL-Address-to-Update-List-Item, + DL-UP-TNL-Address-to-Update-List-Item, + NRV2XServicesAuthorized, + LTEV2XServicesAuthorized, + NRUESidelinkAggregateMaximumBitrate, + LTEUESidelinkAggregateMaximumBitrate, + SLDRBs-SetupMod-Item, + SLDRBs-ModifiedConf-Item, + SLDRBID, + SLDRBs-FailedToBeModified-Item, + SLDRBs-FailedToBeSetup-Item, + SLDRBs-FailedToBeSetupMod-Item, + SLDRBs-Modified-Item, + SLDRBs-Required-ToBeModified-Item, + SLDRBs-Required-ToBeReleased-Item, + SLDRBs-Setup-Item, + SLDRBs-ToBeModified-Item, + SLDRBs-ToBeReleased-Item, + SLDRBs-ToBeSetup-Item, + SLDRBs-ToBeSetupMod-Item, + GNBCUMeasurementID, + GNBDUMeasurementID, + RegistrationRequest, + ReportCharacteristics, + CellToReportList, + HardwareLoadIndicator, + CellMeasurementResultList, + ReportingPeriodicity, + TNLCapacityIndicator, + RACHReportInformationList, + RLFReportInformationList, + ReportingRequestType, + TimeReferenceInformation, + ConditionalInterDUMobilityInformation, + ConditionalIntraDUMobilityInformation, + TargetCellList, + MDTPLMNList, + PrivacyIndicator, + TransportLayerAddress, + URI-address, + NID, + PosAssistance-Information, + PosBroadcast, + PositioningBroadcastCells, + RoutingID, + PosAssistanceInformationFailureList, + PosMeasurementQuantities, + PosMeasurementResultList, + PosMeasurementPeriodicity, + PosReportCharacteristics, + TRPInformationTypeItem, + TRPInformationItem, + LMF-MeasurementID, + RAN-MeasurementID, + SRSResourceSetID, + SRSSpatialRelation, + SRSResourceTrigger, + SRSConfiguration, + TRPList, + E-CID-MeasurementQuantities, + E-CID-MeasurementPeriodicity, + E-CID-MeasurementResult, + Cell-Portion-ID, + LMF-UE-MeasurementID, + RAN-UE-MeasurementID, + SFNInitialisationTime, + SystemFrameNumber, + SlotNumber, + AbortTransmission, + TRP-MeasurementRequestList, + MeasurementBeamInfoRequest, + E-CID-ReportCharacteristics, + Extended-GNB-CU-Name, + Extended-GNB-DU-Name + + + +FROM F1AP-IEs + + PrivateIE-Container{}, + ProtocolExtensionContainer{}, + ProtocolIE-Container{}, + ProtocolIE-ContainerPair{}, + ProtocolIE-SingleContainer{}, + F1AP-PRIVATE-IES, + F1AP-PROTOCOL-EXTENSION, + F1AP-PROTOCOL-IES, + F1AP-PROTOCOL-IES-PAIR + +FROM F1AP-Containers + + id-Candidate-SpCell-Item, + id-Candidate-SpCell-List, + id-Cause, + id-Cancel-all-Warning-Messages-Indicator, + id-Cells-Failed-to-be-Activated-List, + id-Cells-Failed-to-be-Activated-List-Item, + id-Cells-Status-Item, + id-Cells-Status-List, + id-Cells-to-be-Activated-List, + id-Cells-to-be-Activated-List-Item, + id-Cells-to-be-Deactivated-List, + id-Cells-to-be-Deactivated-List-Item, + id-ConfirmedUEID, + id-CriticalityDiagnostics, + id-C-RNTI, + id-CUtoDURRCInformation, + id-DRB-Activity-Item, + id-DRB-Activity-List, + id-DRBs-FailedToBeModified-Item, + id-DRBs-FailedToBeModified-List, + id-DRBs-FailedToBeSetup-Item, + id-DRBs-FailedToBeSetup-List, + id-DRBs-FailedToBeSetupMod-Item, + id-DRBs-FailedToBeSetupMod-List, + id-DRBs-ModifiedConf-Item, + id-DRBs-ModifiedConf-List, + id-DRBs-Modified-Item, + id-DRBs-Modified-List, + id-DRB-Notify-Item, + id-DRB-Notify-List, + id-DRBs-Required-ToBeModified-Item, + id-DRBs-Required-ToBeModified-List, + id-DRBs-Required-ToBeReleased-Item, + id-DRBs-Required-ToBeReleased-List, + id-DRBs-Setup-Item, + id-DRBs-Setup-List, + id-DRBs-SetupMod-Item, + id-DRBs-SetupMod-List, + id-DRBs-ToBeModified-Item, + id-DRBs-ToBeModified-List, + id-DRBs-ToBeReleased-Item, + id-DRBs-ToBeReleased-List, + id-DRBs-ToBeSetup-Item, + id-DRBs-ToBeSetup-List, + id-DRBs-ToBeSetupMod-Item, + id-DRBs-ToBeSetupMod-List, + id-DRXCycle, + id-DUtoCURRCInformation, + id-ExecuteDuplication, + id-FullConfiguration, + id-gNB-CU-UE-F1AP-ID, + id-gNB-DU-UE-F1AP-ID, + id-gNB-DU-ID, + id-GNB-DU-Served-Cells-Item, + id-gNB-DU-Served-Cells-List, + id-gNB-CU-Name, + id-gNB-DU-Name, + id-Extended-GNB-CU-Name, + id-Extended-GNB-DU-Name, + id-InactivityMonitoringRequest, + id-InactivityMonitoringResponse, + id-new-gNB-CU-UE-F1AP-ID, + id-new-gNB-DU-UE-F1AP-ID, + id-oldgNB-DU-UE-F1AP-ID, + id-PLMNAssistanceInfoForNetShar, + id-Potential-SpCell-Item, + id-Potential-SpCell-List, + id-RAT-FrequencyPriorityInformation, + id-RedirectedRRCmessage, + id-ResetType, + id-RequestedSRSTransmissionCharacteristics, + id-ResourceCoordinationTransferContainer, + id-RRCContainer, + id-RRCContainer-RRCSetupComplete, + id-RRCReconfigurationCompleteIndicator, + id-SCell-FailedtoSetup-List, + id-SCell-FailedtoSetup-Item, + id-SCell-FailedtoSetupMod-List, + id-SCell-FailedtoSetupMod-Item, + id-SCell-ToBeRemoved-Item, + id-SCell-ToBeRemoved-List, + id-SCell-ToBeSetup-Item, + id-SCell-ToBeSetup-List, + id-SCell-ToBeSetupMod-Item, + id-SCell-ToBeSetupMod-List, + id-SelectedPLMNID, + id-Served-Cells-To-Add-Item, + id-Served-Cells-To-Add-List, + id-Served-Cells-To-Delete-Item, + id-Served-Cells-To-Delete-List, + id-Served-Cells-To-Modify-Item, + id-Served-Cells-To-Modify-List, + id-ServCellIndex, + id-ServingCellMO, + id-SpCell-ID, + id-SpCellULConfigured, + id-SRBID, + id-SRBs-FailedToBeSetup-Item, + id-SRBs-FailedToBeSetup-List, + id-SRBs-FailedToBeSetupMod-Item, + id-SRBs-FailedToBeSetupMod-List, + id-SRBs-Required-ToBeReleased-Item, + id-SRBs-Required-ToBeReleased-List, + id-SRBs-ToBeReleased-Item, + id-SRBs-ToBeReleased-List, + id-SRBs-ToBeSetup-Item, + id-SRBs-ToBeSetup-List, + id-SRBs-ToBeSetupMod-Item, + id-SRBs-ToBeSetupMod-List, + id-SRBs-Modified-Item, + id-SRBs-Modified-List, + id-SRBs-Setup-Item, + id-SRBs-Setup-List, + id-SRBs-SetupMod-Item, + id-SRBs-SetupMod-List, + id-TimeToWait, + id-TransactionID, + id-TransmissionActionIndicator, + id-UEContextNotRetrievable, + id-UE-associatedLogicalF1-ConnectionItem, + id-UE-associatedLogicalF1-ConnectionListResAck, + id-DUtoCURRCContainer, + id-NRCGI, + id-PagingCell-Item, + id-PagingCell-List, + id-PagingDRX, + id-PagingPriority, + id-SItype-List, + id-UEIdentityIndexValue, + id-GNB-CU-TNL-Association-Setup-List, + id-GNB-CU-TNL-Association-Setup-Item, + id-GNB-CU-TNL-Association-Failed-To-Setup-List, + id-GNB-CU-TNL-Association-Failed-To-Setup-Item, + id-GNB-CU-TNL-Association-To-Add-Item, + id-GNB-CU-TNL-Association-To-Add-List, + id-GNB-CU-TNL-Association-To-Remove-Item, + id-GNB-CU-TNL-Association-To-Remove-List, + id-GNB-CU-TNL-Association-To-Update-Item, + id-GNB-CU-TNL-Association-To-Update-List, + id-MaskedIMEISV, + id-PagingIdentity, + id-Cells-to-be-Barred-List, + id-Cells-to-be-Barred-Item, + id-PWSSystemInformation, + id-RepetitionPeriod, + id-NumberofBroadcastRequest, + id-Cells-To-Be-Broadcast-List, + id-Cells-To-Be-Broadcast-Item, + id-Cells-Broadcast-Completed-List, + id-Cells-Broadcast-Completed-Item, + id-Broadcast-To-Be-Cancelled-List, + id-Broadcast-To-Be-Cancelled-Item, + id-Cells-Broadcast-Cancelled-List, + id-Cells-Broadcast-Cancelled-Item, + id-NR-CGI-List-For-Restart-List, + id-NR-CGI-List-For-Restart-Item, + id-PWS-Failed-NR-CGI-List, + id-PWS-Failed-NR-CGI-Item, + id-EUTRA-NR-CellResourceCoordinationReq-Container, + id-EUTRA-NR-CellResourceCoordinationReqAck-Container, + id-Protected-EUTRA-Resources-List, + id-RequestType, + id-ServingPLMN, + id-DRXConfigurationIndicator, + id-RLCFailureIndication, + id-UplinkTxDirectCurrentListInformation, + id-SULAccessIndication, + id-Protected-EUTRA-Resources-Item, + id-GNB-DUConfigurationQuery, + id-GNB-DU-UE-AMBR-UL, + id-GNB-CU-RRC-Version, + id-GNB-DU-RRC-Version, + id-GNBDUOverloadInformation, + id-NeedforGap, + id-RRCDeliveryStatusRequest, + id-RRCDeliveryStatus, + id-Dedicated-SIDelivery-NeededUE-List, + id-Dedicated-SIDelivery-NeededUE-Item, + id-ResourceCoordinationTransferInformation, + id-Associated-SCell-List, + id-Associated-SCell-Item, + id-IgnoreResourceCoordinationContainer, + id-UAC-Assistance-Info, + id-RANUEID, + id-PagingOrigin, + id-GNB-DU-TNL-Association-To-Remove-Item, + id-GNB-DU-TNL-Association-To-Remove-List, + id-NotificationInformation, + id-TraceActivation, + id-TraceID, + id-Neighbour-Cell-Information-List, + id-Neighbour-Cell-Information-Item, + id-SymbolAllocInSlot, + id-NumDLULSymbols, + id-AdditionalRRMPriorityIndex, + id-DUCURadioInformationType, + id-CUDURadioInformationType, + id-LowerLayerPresenceStatusChange, + id-Transport-Layer-Address-Info, + id-BHChannels-ToBeSetup-List, + id-BHChannels-ToBeSetup-Item, + id-BHChannels-Setup-List, + id-BHChannels-Setup-Item, + id-BHChannels-ToBeModified-Item, + id-BHChannels-ToBeModified-List, + id-BHChannels-ToBeReleased-Item, + id-BHChannels-ToBeReleased-List, + id-BHChannels-ToBeSetupMod-Item, + id-BHChannels-ToBeSetupMod-List, + id-BHChannels-FailedToBeSetup-Item, + id-BHChannels-FailedToBeSetup-List, + id-BHChannels-FailedToBeModified-Item, + id-BHChannels-FailedToBeModified-List, + id-BHChannels-FailedToBeSetupMod-Item, + id-BHChannels-FailedToBeSetupMod-List, + id-BHChannels-Modified-Item, + id-BHChannels-Modified-List, + id-BHChannels-SetupMod-Item, + id-BHChannels-SetupMod-List, + id-BHChannels-Required-ToBeReleased-Item, + id-BHChannels-Required-ToBeReleased-List, + id-BAPAddress, + id-ConfiguredBAPAddress, + id-BH-Routing-Information-Added-List, + id-BH-Routing-Information-Added-List-Item, + id-BH-Routing-Information-Removed-List, + id-BH-Routing-Information-Removed-List-Item, + id-UL-BH-Non-UP-Traffic-Mapping, + id-Child-Nodes-List, + id-Activated-Cells-to-be-Updated-List, + id-IABIPv6RequestType, + id-IAB-TNL-Addresses-To-Remove-List, + id-IAB-TNL-Addresses-To-Remove-Item, + id-IAB-Allocated-TNL-Address-List, + id-IAB-Allocated-TNL-Address-Item, + id-IABv4AddressesRequested, + id-TrafficMappingInformation, + id-UL-UP-TNL-Information-to-Update-List, + id-UL-UP-TNL-Information-to-Update-List-Item, + id-UL-UP-TNL-Address-to-Update-List, + id-UL-UP-TNL-Address-to-Update-List-Item, + id-DL-UP-TNL-Address-to-Update-List, + id-DL-UP-TNL-Address-to-Update-List-Item, + id-NRV2XServicesAuthorized, + id-LTEV2XServicesAuthorized, + id-NRUESidelinkAggregateMaximumBitrate, + id-LTEUESidelinkAggregateMaximumBitrate, + id-PC5LinkAMBR, + id-SLDRBs-FailedToBeModified-Item, + id-SLDRBs-FailedToBeModified-List, + id-SLDRBs-FailedToBeSetup-Item, + id-SLDRBs-FailedToBeSetup-List, + id-SLDRBs-Modified-Item, + id-SLDRBs-Modified-List, + id-SLDRBs-Required-ToBeModified-Item, + id-SLDRBs-Required-ToBeModified-List, + id-SLDRBs-Required-ToBeReleased-Item, + id-SLDRBs-Required-ToBeReleased-List, + id-SLDRBs-Setup-Item, + id-SLDRBs-Setup-List, + id-SLDRBs-ToBeModified-Item, + id-SLDRBs-ToBeModified-List, + id-SLDRBs-ToBeReleased-Item, + id-SLDRBs-ToBeReleased-List, + id-SLDRBs-ToBeSetup-Item, + id-SLDRBs-ToBeSetup-List, + id-SLDRBs-ToBeSetupMod-Item, + id-SLDRBs-ToBeSetupMod-List, + id-SLDRBs-SetupMod-List, + id-SLDRBs-FailedToBeSetupMod-List, + id-SLDRBs-SetupMod-Item, + id-SLDRBs-FailedToBeSetupMod-Item, + id-SLDRBs-ModifiedConf-List, + id-SLDRBs-ModifiedConf-Item, + id-gNBCUMeasurementID, + id-gNBDUMeasurementID, + id-RegistrationRequest, + id-ReportCharacteristics, + id-CellToReportList, + id-CellMeasurementResultList, + id-HardwareLoadIndicator, + id-ReportingPeriodicity, + id-TNLCapacityIndicator, + id-RACHReportInformationList, + id-RLFReportInformationList, + id-ReportingRequestType, + id-TimeReferenceInformation, + id-ConditionalInterDUMobilityInformation, + id-ConditionalIntraDUMobilityInformation, + id-targetCellsToCancel, + id-requestedTargetCellGlobalID, + id-TraceCollectionEntityIPAddress, + id-ManagementBasedMDTPLMNList, + id-PrivacyIndicator, + id-TraceCollectionEntityURI, + id-ServingNID, + id-PosAssistance-Information, + id-PosBroadcast, + id-PositioningBroadcastCells, + id-RoutingID, + id-PosAssistanceInformationFailureList, + id-PosMeasurementQuantities, + id-PosMeasurementResultList, + id-PosMeasurementPeriodicity, + id-PosReportCharacteristics, + id-TRPInformationTypeListTRPReq, + id-TRPInformationTypeItem, + id-TRPInformationListTRPResp, + id-TRPInformationItem, + id-LMF-MeasurementID, + id-RAN-MeasurementID, + id-SRSType, + id-ActivationTime, + id-AbortTransmission, + id-SRSConfiguration, + id-TRPList, + id-E-CID-MeasurementQuantities, + id-E-CID-MeasurementPeriodicity, + id-E-CID-MeasurementResult, + id-Cell-Portion-ID, + id-LMF-UE-MeasurementID, + id-RAN-UE-MeasurementID, + id-SFNInitialisationTime, + id-SystemFrameNumber, + id-SlotNumber, + id-TRP-MeasurementRequestList, + id-MeasurementBeamInfoRequest, + id-E-CID-ReportCharacteristics, + + maxCellingNBDU, + maxnoofCandidateSpCells, + maxnoofDRBs, + maxnoofErrors, + maxnoofIndividualF1ConnectionsToReset, + maxnoofPotentialSpCells, + maxnoofSCells, + maxnoofSRBs, + maxnoofPagingCells, + maxnoofTNLAssociations, + maxCellineNB, + maxnoofUEIDs, + maxnoofBHRLCChannels, + maxnoofRoutingEntries, + maxnoofChildIABNodes, + maxnoofServedCellsIAB, + maxnoofTLAsIAB, + maxnoofULUPTNLInformationforIAB, + maxnoofUPTNLAddresses, + maxnoofSLDRBs, + maxnoofTRPInfoTypes, + maxnoofTRPs + + + +FROM F1AP-Constants; + + +-- ************************************************************** +-- +-- RESET ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Reset +-- +-- ************************************************************** + +Reset ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {ResetIEs} }, + ... +} + +ResetIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-ResetType CRITICALITY reject TYPE ResetType PRESENCE mandatory }, + ... +} + +ResetType ::= CHOICE { + f1-Interface ResetAll, + partOfF1-Interface UE-associatedLogicalF1-ConnectionListRes, + choice-extension ProtocolIE-SingleContainer { { ResetType-ExtIEs} } +} + +ResetType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +ResetAll ::= ENUMERATED { + reset-all, + ... +} + +UE-associatedLogicalF1-ConnectionListRes ::= SEQUENCE (SIZE(1.. maxnoofIndividualF1ConnectionsToReset)) OF ProtocolIE-SingleContainer { { UE-associatedLogicalF1-ConnectionItemRes } } + +UE-associatedLogicalF1-ConnectionItemRes F1AP-PROTOCOL-IES ::= { + { ID id-UE-associatedLogicalF1-ConnectionItem CRITICALITY reject TYPE UE-associatedLogicalF1-ConnectionItem PRESENCE mandatory}, + ... +} + + +-- ************************************************************** +-- +-- Reset Acknowledge +-- +-- ************************************************************** + +ResetAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {ResetAcknowledgeIEs} }, + ... +} + +ResetAcknowledgeIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-UE-associatedLogicalF1-ConnectionListResAck CRITICALITY ignore TYPE UE-associatedLogicalF1-ConnectionListResAck PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +UE-associatedLogicalF1-ConnectionListResAck ::= SEQUENCE (SIZE(1.. maxnoofIndividualF1ConnectionsToReset)) OF ProtocolIE-SingleContainer { { UE-associatedLogicalF1-ConnectionItemResAck } } + +UE-associatedLogicalF1-ConnectionItemResAck F1AP-PROTOCOL-IES ::= { + { ID id-UE-associatedLogicalF1-ConnectionItem CRITICALITY ignore TYPE UE-associatedLogicalF1-ConnectionItem PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- ERROR INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Error Indication +-- +-- ************************************************************** + +ErrorIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ErrorIndicationIEs}}, + ... +} + +ErrorIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE optional }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- F1 SETUP ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- F1 Setup Request +-- +-- ************************************************************** + +F1SetupRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {F1SetupRequestIEs} }, + ... +} + +F1SetupRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNB-DU-ID CRITICALITY reject TYPE GNB-DU-ID PRESENCE mandatory }| + { ID id-gNB-DU-Name CRITICALITY ignore TYPE GNB-DU-Name PRESENCE optional }| + { ID id-gNB-DU-Served-Cells-List CRITICALITY reject TYPE GNB-DU-Served-Cells-List PRESENCE optional }| + { ID id-GNB-DU-RRC-Version CRITICALITY reject TYPE RRC-Version PRESENCE mandatory }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }| + { ID id-BAPAddress CRITICALITY ignore TYPE BAPAddress PRESENCE optional }| + { ID id-Extended-GNB-CU-Name CRITICALITY ignore TYPE Extended-GNB-CU-Name PRESENCE optional }, + ... +} + + +GNB-DU-Served-Cells-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { GNB-DU-Served-Cells-ItemIEs } } + +GNB-DU-Served-Cells-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-DU-Served-Cells-Item CRITICALITY reject TYPE GNB-DU-Served-Cells-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- F1 Setup Response +-- +-- ************************************************************** + +F1SetupResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {F1SetupResponseIEs} }, + ... +} + + +F1SetupResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNB-CU-Name CRITICALITY ignore TYPE GNB-CU-Name PRESENCE optional }| + { ID id-Cells-to-be-Activated-List CRITICALITY reject TYPE Cells-to-be-Activated-List PRESENCE optional }| + { ID id-GNB-CU-RRC-Version CRITICALITY reject TYPE RRC-Version PRESENCE mandatory }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }| + { ID id-UL-BH-Non-UP-Traffic-Mapping CRITICALITY reject TYPE UL-BH-Non-UP-Traffic-Mapping PRESENCE optional }| + { ID id-BAPAddress CRITICALITY ignore TYPE BAPAddress PRESENCE optional }| + { ID id-Extended-GNB-DU-Name CRITICALITY ignore TYPE Extended-GNB-DU-Name PRESENCE optional }, + ... +} + + +Cells-to-be-Activated-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-to-be-Activated-List-ItemIEs } } + +Cells-to-be-Activated-List-ItemIEs F1AP-PROTOCOL-IES::= { + { ID id-Cells-to-be-Activated-List-Item CRITICALITY reject TYPE Cells-to-be-Activated-List-Item PRESENCE mandatory}, + ... +} + + + +-- ************************************************************** +-- +-- F1 Setup Failure +-- +-- ************************************************************** + +F1SetupFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {F1SetupFailureIEs} }, + ... +} + +F1SetupFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- GNB-DU CONFIGURATION UPDATE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- GNB-DU CONFIGURATION UPDATE +-- +-- ************************************************************** + +GNBDUConfigurationUpdate::= SEQUENCE { + protocolIEs ProtocolIE-Container { {GNBDUConfigurationUpdateIEs} }, + ... +} + +GNBDUConfigurationUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Served-Cells-To-Add-List CRITICALITY reject TYPE Served-Cells-To-Add-List PRESENCE optional }| + { ID id-Served-Cells-To-Modify-List CRITICALITY reject TYPE Served-Cells-To-Modify-List PRESENCE optional }| + { ID id-Served-Cells-To-Delete-List CRITICALITY reject TYPE Served-Cells-To-Delete-List PRESENCE optional }| + { ID id-Cells-Status-List CRITICALITY reject TYPE Cells-Status-List PRESENCE optional }| + { ID id-Dedicated-SIDelivery-NeededUE-List CRITICALITY ignore TYPE Dedicated-SIDelivery-NeededUE-List PRESENCE optional }| + { ID id-gNB-DU-ID CRITICALITY reject TYPE GNB-DU-ID PRESENCE optional }| + { ID id-GNB-DU-TNL-Association-To-Remove-List CRITICALITY reject TYPE GNB-DU-TNL-Association-To-Remove-List PRESENCE optional }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }, + ... +} + +Served-Cells-To-Add-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Served-Cells-To-Add-ItemIEs } } +Served-Cells-To-Modify-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Served-Cells-To-Modify-ItemIEs } } +Served-Cells-To-Delete-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Served-Cells-To-Delete-ItemIEs } } +Cells-Status-List ::= SEQUENCE (SIZE(0.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-Status-ItemIEs } } + +Dedicated-SIDelivery-NeededUE-List::= SEQUENCE (SIZE(1.. maxnoofUEIDs)) OF ProtocolIE-SingleContainer { { Dedicated-SIDelivery-NeededUE-ItemIEs } } + +GNB-DU-TNL-Association-To-Remove-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-DU-TNL-Association-To-Remove-ItemIEs } } + + +Served-Cells-To-Add-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Served-Cells-To-Add-Item CRITICALITY reject TYPE Served-Cells-To-Add-Item PRESENCE mandatory }, + ... +} + +Served-Cells-To-Modify-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Served-Cells-To-Modify-Item CRITICALITY reject TYPE Served-Cells-To-Modify-Item PRESENCE mandatory }, + ... +} + +Served-Cells-To-Delete-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Served-Cells-To-Delete-Item CRITICALITY reject TYPE Served-Cells-To-Delete-Item PRESENCE mandatory }, + ... +} + +Cells-Status-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-Status-Item CRITICALITY reject TYPE Cells-Status-Item PRESENCE mandatory }, + ... +} + +Dedicated-SIDelivery-NeededUE-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Dedicated-SIDelivery-NeededUE-Item CRITICALITY ignore TYPE Dedicated-SIDelivery-NeededUE-Item PRESENCE mandatory }, + ... +} + +GNB-DU-TNL-Association-To-Remove-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-DU-TNL-Association-To-Remove-Item CRITICALITY reject TYPE GNB-DU-TNL-Association-To-Remove-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- GNB-DU CONFIGURATION UPDATE ACKNOWLEDGE +-- +-- ************************************************************** + +GNBDUConfigurationUpdateAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {GNBDUConfigurationUpdateAcknowledgeIEs} }, + ... +} + + +GNBDUConfigurationUpdateAcknowledgeIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-to-be-Activated-List CRITICALITY reject TYPE Cells-to-be-Activated-List PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-Cells-to-be-Deactivated-List CRITICALITY reject TYPE Cells-to-be-Deactivated-List PRESENCE optional }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }| + { ID id-UL-BH-Non-UP-Traffic-Mapping CRITICALITY reject TYPE UL-BH-Non-UP-Traffic-Mapping PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- GNB-DU CONFIGURATION UPDATE FAILURE +-- +-- ************************************************************** + +GNBDUConfigurationUpdateFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {GNBDUConfigurationUpdateFailureIEs} }, + ... +} + +GNBDUConfigurationUpdateFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- GNB-CU CONFIGURATION UPDATE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- GNB-CU CONFIGURATION UPDATE +-- +-- ************************************************************** + +GNBCUConfigurationUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { GNBCUConfigurationUpdateIEs} }, + ... +} + +GNBCUConfigurationUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-to-be-Activated-List CRITICALITY reject TYPE Cells-to-be-Activated-List PRESENCE optional }| + { ID id-Cells-to-be-Deactivated-List CRITICALITY reject TYPE Cells-to-be-Deactivated-List PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-To-Add-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Add-List PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-To-Remove-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Remove-List PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-To-Update-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Update-List PRESENCE optional }| + { ID id-Cells-to-be-Barred-List CRITICALITY ignore TYPE Cells-to-be-Barred-List PRESENCE optional }| + { ID id-Protected-EUTRA-Resources-List CRITICALITY reject TYPE Protected-EUTRA-Resources-List PRESENCE optional }| + { ID id-Neighbour-Cell-Information-List CRITICALITY ignore TYPE Neighbour-Cell-Information-List PRESENCE optional }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }| + { ID id-UL-BH-Non-UP-Traffic-Mapping CRITICALITY reject TYPE UL-BH-Non-UP-Traffic-Mapping PRESENCE optional }, + ... +} + +Cells-to-be-Deactivated-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-to-be-Deactivated-List-ItemIEs } } +GNB-CU-TNL-Association-To-Add-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-To-Add-ItemIEs } } +GNB-CU-TNL-Association-To-Remove-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-To-Remove-ItemIEs } } +GNB-CU-TNL-Association-To-Update-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-To-Update-ItemIEs } } +Cells-to-be-Barred-List ::= SEQUENCE(SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-to-be-Barred-ItemIEs } } + + +Cells-to-be-Deactivated-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-to-be-Deactivated-List-Item CRITICALITY reject TYPE Cells-to-be-Deactivated-List-Item PRESENCE mandatory }, + ... +} + + +GNB-CU-TNL-Association-To-Add-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-To-Add-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Add-Item PRESENCE mandatory }, + ... +} + +GNB-CU-TNL-Association-To-Remove-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-To-Remove-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Remove-Item PRESENCE mandatory }, + ... +} + +GNB-CU-TNL-Association-To-Update-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-To-Update-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Update-Item PRESENCE mandatory }, + ... +} + +Cells-to-be-Barred-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-to-be-Barred-Item CRITICALITY ignore TYPE Cells-to-be-Barred-Item PRESENCE mandatory }, + ... +} + +Protected-EUTRA-Resources-List ::= SEQUENCE (SIZE(1.. maxCellineNB)) OF ProtocolIE-SingleContainer { { Protected-EUTRA-Resources-ItemIEs } } +Protected-EUTRA-Resources-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Protected-EUTRA-Resources-Item CRITICALITY reject TYPE Protected-EUTRA-Resources-Item PRESENCE mandatory}, + ... +} + +Neighbour-Cell-Information-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Neighbour-Cell-Information-ItemIEs } } +Neighbour-Cell-Information-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Neighbour-Cell-Information-Item CRITICALITY ignore TYPE Neighbour-Cell-Information-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- GNB-CU CONFIGURATION UPDATE ACKNOWLEDGE +-- +-- ************************************************************** + +GNBCUConfigurationUpdateAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { GNBCUConfigurationUpdateAcknowledgeIEs} }, + ... +} + + +GNBCUConfigurationUpdateAcknowledgeIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-Failed-to-be-Activated-List CRITICALITY reject TYPE Cells-Failed-to-be-Activated-List PRESENCE optional}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-Setup-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-Setup-List PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-Failed-To-Setup-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-Failed-To-Setup-List PRESENCE optional }| + { ID id-Dedicated-SIDelivery-NeededUE-List CRITICALITY ignore TYPE Dedicated-SIDelivery-NeededUE-List PRESENCE optional }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }, + ... +} + +Cells-Failed-to-be-Activated-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-Failed-to-be-Activated-List-ItemIEs } } +GNB-CU-TNL-Association-Setup-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-Setup-ItemIEs } } +GNB-CU-TNL-Association-Failed-To-Setup-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-Failed-To-Setup-ItemIEs } } + +Cells-Failed-to-be-Activated-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-Failed-to-be-Activated-List-Item CRITICALITY reject TYPE Cells-Failed-to-be-Activated-List-Item PRESENCE mandatory }, + ... +} + +GNB-CU-TNL-Association-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-Setup-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-Setup-Item PRESENCE mandatory }, + ... +} + + +GNB-CU-TNL-Association-Failed-To-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-Failed-To-Setup-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-Failed-To-Setup-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- GNB-CU CONFIGURATION UPDATE FAILURE +-- +-- ************************************************************** + +GNBCUConfigurationUpdateFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { GNBCUConfigurationUpdateFailureIEs} }, + ... +} + +GNBCUConfigurationUpdateFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- GNB-DU RESOURCE COORDINATION REQUEST +-- +-- ************************************************************** + +GNBDUResourceCoordinationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{GNBDUResourceCoordinationRequest-IEs}}, + ... +} + +GNBDUResourceCoordinationRequest-IEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-RequestType CRITICALITY reject TYPE RequestType PRESENCE mandatory }| + { ID id-EUTRA-NR-CellResourceCoordinationReq-Container CRITICALITY reject TYPE EUTRA-NR-CellResourceCoordinationReq-Container PRESENCE mandatory}| + { ID id-IgnoreResourceCoordinationContainer CRITICALITY reject TYPE IgnoreResourceCoordinationContainer PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- GNB-DU RESOURCE COORDINATION RESPONSE +-- +-- ************************************************************** + +GNBDUResourceCoordinationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{GNBDUResourceCoordinationResponse-IEs}}, + ... +} + +GNBDUResourceCoordinationResponse-IEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-EUTRA-NR-CellResourceCoordinationReqAck-Container CRITICALITY reject TYPE EUTRA-NR-CellResourceCoordinationReqAck-Container PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE Context Setup ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT SETUP REQUEST +-- +-- ************************************************************** + +UEContextSetupRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextSetupRequestIEs} }, + ... +} + +UEContextSetupRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-SpCell-ID CRITICALITY reject TYPE NRCGI PRESENCE mandatory }| + { ID id-ServCellIndex CRITICALITY reject TYPE ServCellIndex PRESENCE mandatory }| + { ID id-SpCellULConfigured CRITICALITY ignore TYPE CellULConfigured PRESENCE optional }| + { ID id-CUtoDURRCInformation CRITICALITY reject TYPE CUtoDURRCInformation PRESENCE mandatory}| + { ID id-Candidate-SpCell-List CRITICALITY ignore TYPE Candidate-SpCell-List PRESENCE optional }| + { ID id-DRXCycle CRITICALITY ignore TYPE DRXCycle PRESENCE optional }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-SCell-ToBeSetup-List CRITICALITY ignore TYPE SCell-ToBeSetup-List PRESENCE optional }| + { ID id-SRBs-ToBeSetup-List CRITICALITY reject TYPE SRBs-ToBeSetup-List PRESENCE optional }| + { ID id-DRBs-ToBeSetup-List CRITICALITY reject TYPE DRBs-ToBeSetup-List PRESENCE optional }| + { ID id-InactivityMonitoringRequest CRITICALITY reject TYPE InactivityMonitoringRequest PRESENCE optional }| + { ID id-RAT-FrequencyPriorityInformation CRITICALITY reject TYPE RAT-FrequencyPriorityInformation PRESENCE optional }| + { ID id-RRCContainer CRITICALITY ignore TYPE RRCContainer PRESENCE optional }| + { ID id-MaskedIMEISV CRITICALITY ignore TYPE MaskedIMEISV PRESENCE optional }| + { ID id-ServingPLMN CRITICALITY ignore TYPE PLMN-Identity PRESENCE optional }| + { ID id-GNB-DU-UE-AMBR-UL CRITICALITY ignore TYPE BitRate PRESENCE conditional }| + { ID id-RRCDeliveryStatusRequest CRITICALITY ignore TYPE RRCDeliveryStatusRequest PRESENCE optional }| + { ID id-ResourceCoordinationTransferInformation CRITICALITY ignore TYPE ResourceCoordinationTransferInformation PRESENCE optional }| + { ID id-ServingCellMO CRITICALITY ignore TYPE ServingCellMO PRESENCE optional }| + { ID id-new-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-RANUEID CRITICALITY ignore TYPE RANUEID PRESENCE optional }| + { ID id-TraceActivation CRITICALITY ignore TYPE TraceActivation PRESENCE optional }| + { ID id-AdditionalRRMPriorityIndex CRITICALITY ignore TYPE AdditionalRRMPriorityIndex PRESENCE optional }| + { ID id-BHChannels-ToBeSetup-List CRITICALITY reject TYPE BHChannels-ToBeSetup-List PRESENCE optional }| + { ID id-ConfiguredBAPAddress CRITICALITY reject TYPE BAPAddress PRESENCE optional }| + { ID id-NRV2XServicesAuthorized CRITICALITY ignore TYPE NRV2XServicesAuthorized PRESENCE optional }| + { ID id-LTEV2XServicesAuthorized CRITICALITY ignore TYPE LTEV2XServicesAuthorized PRESENCE optional }| + { ID id-NRUESidelinkAggregateMaximumBitrate CRITICALITY ignore TYPE NRUESidelinkAggregateMaximumBitrate PRESENCE optional }| + { ID id-LTEUESidelinkAggregateMaximumBitrate CRITICALITY ignore TYPE LTEUESidelinkAggregateMaximumBitrate PRESENCE optional }| + { ID id-PC5LinkAMBR CRITICALITY ignore TYPE BitRate PRESENCE optional}| + { ID id-SLDRBs-ToBeSetup-List CRITICALITY reject TYPE SLDRBs-ToBeSetup-List PRESENCE optional }| + { ID id-ConditionalInterDUMobilityInformation CRITICALITY reject TYPE ConditionalInterDUMobilityInformation PRESENCE optional}| + { ID id-ManagementBasedMDTPLMNList CRITICALITY ignore TYPE MDTPLMNList PRESENCE optional }| + { ID id-ServingNID CRITICALITY reject TYPE NID PRESENCE optional }, + ... +} + +Candidate-SpCell-List::= SEQUENCE (SIZE(1..maxnoofCandidateSpCells)) OF ProtocolIE-SingleContainer { { Candidate-SpCell-ItemIEs} } +SCell-ToBeSetup-List::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-ToBeSetup-ItemIEs} } +SRBs-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-ToBeSetup-ItemIEs} } +DRBs-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ToBeSetup-ItemIEs} } +BHChannels-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-ToBeSetup-ItemIEs} } +SLDRBs-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ToBeSetup-ItemIEs} } + +Candidate-SpCell-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Candidate-SpCell-Item CRITICALITY ignore TYPE Candidate-SpCell-Item PRESENCE mandatory }, + ... +} + + +SCell-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-ToBeSetup-Item CRITICALITY ignore TYPE SCell-ToBeSetup-Item PRESENCE mandatory }, + ... +} + +SRBs-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-ToBeSetup-Item CRITICALITY reject TYPE SRBs-ToBeSetup-Item PRESENCE mandatory}, + ... +} + +DRBs-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ToBeSetup-Item CRITICALITY reject TYPE DRBs-ToBeSetup-Item PRESENCE mandatory}, + ... +} + +BHChannels-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-ToBeSetup-Item CRITICALITY reject TYPE BHChannels-ToBeSetup-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ToBeSetup-Item CRITICALITY reject TYPE SLDRBs-ToBeSetup-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT SETUP RESPONSE +-- +-- ************************************************************** + +UEContextSetupResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextSetupResponseIEs} }, + ... +} + + +UEContextSetupResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-DUtoCURRCInformation CRITICALITY reject TYPE DUtoCURRCInformation PRESENCE mandatory }| + { ID id-C-RNTI CRITICALITY ignore TYPE C-RNTI PRESENCE optional }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-FullConfiguration CRITICALITY reject TYPE FullConfiguration PRESENCE optional }| + { ID id-DRBs-Setup-List CRITICALITY ignore TYPE DRBs-Setup-List PRESENCE optional }| + { ID id-SRBs-FailedToBeSetup-List CRITICALITY ignore TYPE SRBs-FailedToBeSetup-List PRESENCE optional }| + { ID id-DRBs-FailedToBeSetup-List CRITICALITY ignore TYPE DRBs-FailedToBeSetup-List PRESENCE optional }| + { ID id-SCell-FailedtoSetup-List CRITICALITY ignore TYPE SCell-FailedtoSetup-List PRESENCE optional }| + { ID id-InactivityMonitoringResponse CRITICALITY reject TYPE InactivityMonitoringResponse PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-SRBs-Setup-List CRITICALITY ignore TYPE SRBs-Setup-List PRESENCE optional }| + { ID id-BHChannels-Setup-List CRITICALITY ignore TYPE BHChannels-Setup-List PRESENCE optional }| + { ID id-BHChannels-FailedToBeSetup-List CRITICALITY ignore TYPE BHChannels-FailedToBeSetup-List PRESENCE optional }| + { ID id-SLDRBs-Setup-List CRITICALITY ignore TYPE SLDRBs-Setup-List PRESENCE optional }| + { ID id-SLDRBs-FailedToBeSetup-List CRITICALITY ignore TYPE SLDRBs-FailedToBeSetup-List PRESENCE optional }| + { ID id-requestedTargetCellGlobalID CRITICALITY reject TYPE NRCGI PRESENCE optional}, + ... +} + +DRBs-Setup-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-Setup-ItemIEs} } + + +SRBs-FailedToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-FailedToBeSetup-ItemIEs} } +DRBs-FailedToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-FailedToBeSetup-ItemIEs} } +SCell-FailedtoSetup-List ::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-FailedtoSetup-ItemIEs} } +SRBs-Setup-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-Setup-ItemIEs} } +BHChannels-Setup-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-Setup-ItemIEs} } +BHChannels-FailedToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-FailedToBeSetup-ItemIEs} } + +DRBs-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-Setup-Item CRITICALITY ignore TYPE DRBs-Setup-Item PRESENCE mandatory}, + ... +} + +SRBs-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-Setup-Item CRITICALITY ignore TYPE SRBs-Setup-Item PRESENCE mandatory}, + ... +} + +SRBs-FailedToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-FailedToBeSetup-Item CRITICALITY ignore TYPE SRBs-FailedToBeSetup-Item PRESENCE mandatory}, + ... +} + + +DRBs-FailedToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-FailedToBeSetup-Item CRITICALITY ignore TYPE DRBs-FailedToBeSetup-Item PRESENCE mandatory}, + ... +} + +SCell-FailedtoSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-FailedtoSetup-Item CRITICALITY ignore TYPE SCell-FailedtoSetup-Item PRESENCE mandatory}, + ... +} + +BHChannels-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-Setup-Item CRITICALITY ignore TYPE BHChannels-Setup-Item PRESENCE mandatory}, + ... +} + +BHChannels-FailedToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-FailedToBeSetup-Item CRITICALITY ignore TYPE BHChannels-FailedToBeSetup-Item PRESENCE mandatory}, + ... +} + +SLDRBs-Setup-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-Setup-ItemIEs} } + +SLDRBs-FailedToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-FailedToBeSetup-ItemIEs} } + +SLDRBs-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-Setup-Item CRITICALITY ignore TYPE SLDRBs-Setup-Item PRESENCE mandatory}, + ... +} + +SLDRBs-FailedToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-FailedToBeSetup-Item CRITICALITY ignore TYPE SLDRBs-FailedToBeSetup-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT SETUP FAILURE +-- +-- ************************************************************** + +UEContextSetupFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextSetupFailureIEs} }, + ... +} + +UEContextSetupFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-Potential-SpCell-List CRITICALITY ignore TYPE Potential-SpCell-List PRESENCE optional }| + { ID id-requestedTargetCellGlobalID CRITICALITY reject TYPE NRCGI PRESENCE optional}, + ... +} + +Potential-SpCell-List::= SEQUENCE (SIZE(0..maxnoofPotentialSpCells)) OF ProtocolIE-SingleContainer { { Potential-SpCell-ItemIEs} } + +Potential-SpCell-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Potential-SpCell-Item CRITICALITY ignore TYPE Potential-SpCell-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE Context Release Request ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE Context Release Request +-- +-- ************************************************************** + +UEContextReleaseRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ UEContextReleaseRequestIEs}}, + ... +} + +UEContextReleaseRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-targetCellsToCancel CRITICALITY reject TYPE TargetCellList PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- UE Context Release (gNB-CU initiated) ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT RELEASE COMMAND +-- +-- ************************************************************** + +UEContextReleaseCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextReleaseCommandIEs} }, + ... +} + +UEContextReleaseCommandIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-RRCContainer CRITICALITY ignore TYPE RRCContainer PRESENCE optional }| + { ID id-SRBID CRITICALITY ignore TYPE SRBID PRESENCE conditional }| + { ID id-oldgNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-ExecuteDuplication CRITICALITY ignore TYPE ExecuteDuplication PRESENCE optional}| + { ID id-RRCDeliveryStatusRequest CRITICALITY ignore TYPE RRCDeliveryStatusRequest PRESENCE optional }| + { ID id-targetCellsToCancel CRITICALITY reject TYPE TargetCellList PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT RELEASE COMPLETE +-- +-- ************************************************************** + +UEContextReleaseComplete ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextReleaseCompleteIEs} }, + ... +} + + +UEContextReleaseCompleteIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE Context Modification ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION REQUEST +-- +-- ************************************************************** + +UEContextModificationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationRequestIEs} }, + ... +} + +UEContextModificationRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SpCell-ID CRITICALITY ignore TYPE NRCGI PRESENCE optional }| + { ID id-ServCellIndex CRITICALITY reject TYPE ServCellIndex PRESENCE optional }| + { ID id-SpCellULConfigured CRITICALITY ignore TYPE CellULConfigured PRESENCE optional }| + { ID id-DRXCycle CRITICALITY ignore TYPE DRXCycle PRESENCE optional }| + { ID id-CUtoDURRCInformation CRITICALITY reject TYPE CUtoDURRCInformation PRESENCE optional }| + { ID id-TransmissionActionIndicator CRITICALITY ignore TYPE TransmissionActionIndicator PRESENCE optional }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-RRCReconfigurationCompleteIndicator CRITICALITY ignore TYPE RRCReconfigurationCompleteIndicator PRESENCE optional }| + { ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE optional }| + { ID id-SCell-ToBeSetupMod-List CRITICALITY ignore TYPE SCell-ToBeSetupMod-List PRESENCE optional }| + { ID id-SCell-ToBeRemoved-List CRITICALITY ignore TYPE SCell-ToBeRemoved-List PRESENCE optional }| + { ID id-SRBs-ToBeSetupMod-List CRITICALITY reject TYPE SRBs-ToBeSetupMod-List PRESENCE optional }| + { ID id-DRBs-ToBeSetupMod-List CRITICALITY reject TYPE DRBs-ToBeSetupMod-List PRESENCE optional }| + { ID id-DRBs-ToBeModified-List CRITICALITY reject TYPE DRBs-ToBeModified-List PRESENCE optional }| + { ID id-SRBs-ToBeReleased-List CRITICALITY reject TYPE SRBs-ToBeReleased-List PRESENCE optional }| + { ID id-DRBs-ToBeReleased-List CRITICALITY reject TYPE DRBs-ToBeReleased-List PRESENCE optional }| + { ID id-InactivityMonitoringRequest CRITICALITY reject TYPE InactivityMonitoringRequest PRESENCE optional }| + { ID id-RAT-FrequencyPriorityInformation CRITICALITY reject TYPE RAT-FrequencyPriorityInformation PRESENCE optional }| + { ID id-DRXConfigurationIndicator CRITICALITY ignore TYPE DRXConfigurationIndicator PRESENCE optional }| + { ID id-RLCFailureIndication CRITICALITY ignore TYPE RLCFailureIndication PRESENCE optional }| + { ID id-UplinkTxDirectCurrentListInformation CRITICALITY ignore TYPE UplinkTxDirectCurrentListInformation PRESENCE optional }| + { ID id-GNB-DUConfigurationQuery CRITICALITY reject TYPE GNB-DUConfigurationQuery PRESENCE optional }| + { ID id-GNB-DU-UE-AMBR-UL CRITICALITY ignore TYPE BitRate PRESENCE optional }| + { ID id-ExecuteDuplication CRITICALITY ignore TYPE ExecuteDuplication PRESENCE optional}| + { ID id-RRCDeliveryStatusRequest CRITICALITY ignore TYPE RRCDeliveryStatusRequest PRESENCE optional }| + { ID id-ResourceCoordinationTransferInformation CRITICALITY ignore TYPE ResourceCoordinationTransferInformation PRESENCE optional }| + { ID id-ServingCellMO CRITICALITY ignore TYPE ServingCellMO PRESENCE optional }| + { ID id-NeedforGap CRITICALITY ignore TYPE NeedforGap PRESENCE optional }| + { ID id-FullConfiguration CRITICALITY reject TYPE FullConfiguration PRESENCE optional }| + { ID id-AdditionalRRMPriorityIndex CRITICALITY ignore TYPE AdditionalRRMPriorityIndex PRESENCE optional }| + { ID id-LowerLayerPresenceStatusChange CRITICALITY ignore TYPE LowerLayerPresenceStatusChange PRESENCE optional }| + { ID id-BHChannels-ToBeSetupMod-List CRITICALITY reject TYPE BHChannels-ToBeSetupMod-List PRESENCE optional }| + { ID id-BHChannels-ToBeModified-List CRITICALITY reject TYPE BHChannels-ToBeModified-List PRESENCE optional }| + { ID id-BHChannels-ToBeReleased-List CRITICALITY reject TYPE BHChannels-ToBeReleased-List PRESENCE optional }| + { ID id-NRV2XServicesAuthorized CRITICALITY ignore TYPE NRV2XServicesAuthorized PRESENCE optional }| + { ID id-LTEV2XServicesAuthorized CRITICALITY ignore TYPE LTEV2XServicesAuthorized PRESENCE optional }| + { ID id-NRUESidelinkAggregateMaximumBitrate CRITICALITY ignore TYPE NRUESidelinkAggregateMaximumBitrate PRESENCE optional }| + { ID id-LTEUESidelinkAggregateMaximumBitrate CRITICALITY ignore TYPE LTEUESidelinkAggregateMaximumBitrate PRESENCE optional }| + { ID id-PC5LinkAMBR CRITICALITY ignore TYPE BitRate PRESENCE optional}| + { ID id-SLDRBs-ToBeSetupMod-List CRITICALITY reject TYPE SLDRBs-ToBeSetupMod-List PRESENCE optional }| + { ID id-SLDRBs-ToBeModified-List CRITICALITY reject TYPE SLDRBs-ToBeModified-List PRESENCE optional }| + { ID id-SLDRBs-ToBeReleased-List CRITICALITY reject TYPE SLDRBs-ToBeReleased-List PRESENCE optional }| + { ID id-ConditionalIntraDUMobilityInformation CRITICALITY reject TYPE ConditionalIntraDUMobilityInformation PRESENCE optional}, + ... +} + +SCell-ToBeSetupMod-List::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-ToBeSetupMod-ItemIEs} } +SCell-ToBeRemoved-List::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-ToBeRemoved-ItemIEs} } +SRBs-ToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-ToBeSetupMod-ItemIEs} } +DRBs-ToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ToBeSetupMod-ItemIEs} } +BHChannels-ToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-ToBeSetupMod-ItemIEs} } + +DRBs-ToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ToBeModified-ItemIEs} } +BHChannels-ToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-ToBeModified-ItemIEs} } +SRBs-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-ToBeReleased-ItemIEs} } +DRBs-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ToBeReleased-ItemIEs} } +BHChannels-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-ToBeReleased-ItemIEs} } + +SCell-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-ToBeSetupMod-Item CRITICALITY ignore TYPE SCell-ToBeSetupMod-Item PRESENCE mandatory }, + ... +} + +SCell-ToBeRemoved-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-ToBeRemoved-Item CRITICALITY ignore TYPE SCell-ToBeRemoved-Item PRESENCE mandatory }, + ... +} + + +SRBs-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-ToBeSetupMod-Item CRITICALITY reject TYPE SRBs-ToBeSetupMod-Item PRESENCE mandatory}, + ... +} + + +DRBs-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ToBeSetupMod-Item CRITICALITY reject TYPE DRBs-ToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +DRBs-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ToBeModified-Item CRITICALITY reject TYPE DRBs-ToBeModified-Item PRESENCE mandatory}, + ... +} + + +SRBs-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-ToBeReleased-Item CRITICALITY reject TYPE SRBs-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +DRBs-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ToBeReleased-Item CRITICALITY reject TYPE DRBs-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +BHChannels-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-ToBeSetupMod-Item CRITICALITY reject TYPE BHChannels-ToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +BHChannels-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-ToBeModified-Item CRITICALITY reject TYPE BHChannels-ToBeModified-Item PRESENCE mandatory}, + ... +} + +BHChannels-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-ToBeReleased-Item CRITICALITY reject TYPE BHChannels-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ToBeSetupMod-ItemIEs} } +SLDRBs-ToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ToBeModified-ItemIEs} } +SLDRBs-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ToBeReleased-ItemIEs} } + +SLDRBs-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ToBeSetupMod-Item CRITICALITY reject TYPE SLDRBs-ToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ToBeModified-Item CRITICALITY reject TYPE SLDRBs-ToBeModified-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ToBeReleased-Item CRITICALITY reject TYPE SLDRBs-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION RESPONSE +-- +-- ************************************************************** + +UEContextModificationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationResponseIEs} }, + ... +} + + +UEContextModificationResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-DUtoCURRCInformation CRITICALITY reject TYPE DUtoCURRCInformation PRESENCE optional}| + { ID id-DRBs-SetupMod-List CRITICALITY ignore TYPE DRBs-SetupMod-List PRESENCE optional}| + { ID id-DRBs-Modified-List CRITICALITY ignore TYPE DRBs-Modified-List PRESENCE optional}| + { ID id-SRBs-FailedToBeSetupMod-List CRITICALITY ignore TYPE SRBs-FailedToBeSetupMod-List PRESENCE optional }| + { ID id-DRBs-FailedToBeSetupMod-List CRITICALITY ignore TYPE DRBs-FailedToBeSetupMod-List PRESENCE optional }| + { ID id-SCell-FailedtoSetupMod-List CRITICALITY ignore TYPE SCell-FailedtoSetupMod-List PRESENCE optional }| + { ID id-DRBs-FailedToBeModified-List CRITICALITY ignore TYPE DRBs-FailedToBeModified-List PRESENCE optional }| + { ID id-InactivityMonitoringResponse CRITICALITY reject TYPE InactivityMonitoringResponse PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-C-RNTI CRITICALITY ignore TYPE C-RNTI PRESENCE optional }| + { ID id-Associated-SCell-List CRITICALITY ignore TYPE Associated-SCell-List PRESENCE optional }| + { ID id-SRBs-SetupMod-List CRITICALITY ignore TYPE SRBs-SetupMod-List PRESENCE optional }| + { ID id-SRBs-Modified-List CRITICALITY ignore TYPE SRBs-Modified-List PRESENCE optional }| + { ID id-FullConfiguration CRITICALITY reject TYPE FullConfiguration PRESENCE optional }| + { ID id-BHChannels-SetupMod-List CRITICALITY ignore TYPE BHChannels-SetupMod-List PRESENCE optional}| + { ID id-BHChannels-Modified-List CRITICALITY ignore TYPE BHChannels-Modified-List PRESENCE optional}| + { ID id-BHChannels-FailedToBeSetupMod-List CRITICALITY ignore TYPE BHChannels-FailedToBeSetupMod-List PRESENCE optional }| + { ID id-BHChannels-FailedToBeModified-List CRITICALITY ignore TYPE BHChannels-FailedToBeModified-List PRESENCE optional }| + { ID id-SLDRBs-SetupMod-List CRITICALITY ignore TYPE SLDRBs-SetupMod-List PRESENCE optional }| + { ID id-SLDRBs-Modified-List CRITICALITY ignore TYPE SLDRBs-Modified-List PRESENCE optional }| + { ID id-SLDRBs-FailedToBeSetupMod-List CRITICALITY ignore TYPE SLDRBs-FailedToBeSetupMod-List PRESENCE optional }| + { ID id-SLDRBs-FailedToBeModified-List CRITICALITY ignore TYPE SLDRBs-FailedToBeModified-List PRESENCE optional }| + { ID id-requestedTargetCellGlobalID CRITICALITY reject TYPE NRCGI PRESENCE optional}, + ... +} + + +DRBs-SetupMod-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-SetupMod-ItemIEs} } +DRBs-Modified-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-Modified-ItemIEs } } +SRBs-SetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-SetupMod-ItemIEs} } +SRBs-Modified-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-Modified-ItemIEs } } +DRBs-FailedToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-FailedToBeModified-ItemIEs} } +SRBs-FailedToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-FailedToBeSetupMod-ItemIEs} } +DRBs-FailedToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-FailedToBeSetupMod-ItemIEs} } +SCell-FailedtoSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-FailedtoSetupMod-ItemIEs} } +BHChannels-SetupMod-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-SetupMod-ItemIEs} } +BHChannels-Modified-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-Modified-ItemIEs } } +BHChannels-FailedToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-FailedToBeModified-ItemIEs} } +BHChannels-FailedToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-FailedToBeSetupMod-ItemIEs} } + +Associated-SCell-List ::= SEQUENCE (SIZE(1.. maxnoofSCells)) OF ProtocolIE-SingleContainer { { Associated-SCell-ItemIEs} } + +DRBs-SetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-SetupMod-Item CRITICALITY ignore TYPE DRBs-SetupMod-Item PRESENCE mandatory}, + ... +} + + +DRBs-Modified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-Modified-Item CRITICALITY ignore TYPE DRBs-Modified-Item PRESENCE mandatory}, + ... +} + +SRBs-SetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-SetupMod-Item CRITICALITY ignore TYPE SRBs-SetupMod-Item PRESENCE mandatory}, + ... +} + + +SRBs-Modified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-Modified-Item CRITICALITY ignore TYPE SRBs-Modified-Item PRESENCE mandatory}, + ... +} + +SRBs-FailedToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-FailedToBeSetupMod-Item CRITICALITY ignore TYPE SRBs-FailedToBeSetupMod-Item PRESENCE mandatory}, + ... +} + + +DRBs-FailedToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-FailedToBeSetupMod-Item CRITICALITY ignore TYPE DRBs-FailedToBeSetupMod-Item PRESENCE mandatory}, + ... +} + + +DRBs-FailedToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-FailedToBeModified-Item CRITICALITY ignore TYPE DRBs-FailedToBeModified-Item PRESENCE mandatory}, + ... +} + +SCell-FailedtoSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-FailedtoSetupMod-Item CRITICALITY ignore TYPE SCell-FailedtoSetupMod-Item PRESENCE mandatory}, + ... +} + +Associated-SCell-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Associated-SCell-Item CRITICALITY ignore TYPE Associated-SCell-Item PRESENCE mandatory}, + ... +} + +BHChannels-SetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-SetupMod-Item CRITICALITY ignore TYPE BHChannels-SetupMod-Item PRESENCE mandatory}, + ... +} + + +BHChannels-Modified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-Modified-Item CRITICALITY ignore TYPE BHChannels-Modified-Item PRESENCE mandatory}, + ... +} + +BHChannels-FailedToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-FailedToBeSetupMod-Item CRITICALITY ignore TYPE BHChannels-FailedToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +BHChannels-FailedToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-FailedToBeModified-Item CRITICALITY ignore TYPE BHChannels-FailedToBeModified-Item PRESENCE mandatory}, + ... +} + +SLDRBs-SetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-SetupMod-ItemIEs} } +SLDRBs-Modified-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-Modified-ItemIEs } } +SLDRBs-FailedToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-FailedToBeModified-ItemIEs} } +SLDRBs-FailedToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-FailedToBeSetupMod-ItemIEs} } + +SLDRBs-SetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-SetupMod-Item CRITICALITY ignore TYPE SLDRBs-SetupMod-Item PRESENCE mandatory}, + ... +} + +SLDRBs-Modified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-Modified-Item CRITICALITY ignore TYPE SLDRBs-Modified-Item PRESENCE mandatory}, + ... +} + +SLDRBs-FailedToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-FailedToBeSetupMod-Item CRITICALITY ignore TYPE SLDRBs-FailedToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +SLDRBs-FailedToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-FailedToBeModified-Item CRITICALITY ignore TYPE SLDRBs-FailedToBeModified-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION FAILURE +-- +-- ************************************************************** + +UEContextModificationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationFailureIEs} }, + ... +} + +UEContextModificationFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-requestedTargetCellGlobalID CRITICALITY reject TYPE NRCGI PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- UE Context Modification Required (gNB-DU initiated) ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION REQUIRED +-- +-- ************************************************************** + +UEContextModificationRequired ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationRequiredIEs} }, + ... +} + +UEContextModificationRequiredIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-DUtoCURRCInformation CRITICALITY reject TYPE DUtoCURRCInformation PRESENCE optional}| + { ID id-DRBs-Required-ToBeModified-List CRITICALITY reject TYPE DRBs-Required-ToBeModified-List PRESENCE optional}| + { ID id-SRBs-Required-ToBeReleased-List CRITICALITY reject TYPE SRBs-Required-ToBeReleased-List PRESENCE optional}| + { ID id-DRBs-Required-ToBeReleased-List CRITICALITY reject TYPE DRBs-Required-ToBeReleased-List PRESENCE optional}| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-BHChannels-Required-ToBeReleased-List CRITICALITY reject TYPE BHChannels-Required-ToBeReleased-List PRESENCE optional}| + { ID id-SLDRBs-Required-ToBeModified-List CRITICALITY reject TYPE SLDRBs-Required-ToBeModified-List PRESENCE optional}| + { ID id-SLDRBs-Required-ToBeReleased-List CRITICALITY reject TYPE SLDRBs-Required-ToBeReleased-List PRESENCE optional}| + { ID id-targetCellsToCancel CRITICALITY reject TYPE TargetCellList PRESENCE optional}, + ... +} + +DRBs-Required-ToBeModified-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-Required-ToBeModified-ItemIEs } } +DRBs-Required-ToBeReleased-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-Required-ToBeReleased-ItemIEs } } + +SRBs-Required-ToBeReleased-List::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-Required-ToBeReleased-ItemIEs } } + +BHChannels-Required-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-Required-ToBeReleased-ItemIEs } } + +DRBs-Required-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-Required-ToBeModified-Item CRITICALITY reject TYPE DRBs-Required-ToBeModified-Item PRESENCE mandatory}, + ... +} + +DRBs-Required-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-Required-ToBeReleased-Item CRITICALITY reject TYPE DRBs-Required-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +SRBs-Required-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-Required-ToBeReleased-Item CRITICALITY reject TYPE SRBs-Required-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +BHChannels-Required-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-Required-ToBeReleased-Item CRITICALITY reject TYPE BHChannels-Required-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +SLDRBs-Required-ToBeModified-List::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-Required-ToBeModified-ItemIEs } } +SLDRBs-Required-ToBeReleased-List::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-Required-ToBeReleased-ItemIEs } } + +SLDRBs-Required-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-Required-ToBeModified-Item CRITICALITY reject TYPE SLDRBs-Required-ToBeModified-Item PRESENCE mandatory}, + ... +} + +SLDRBs-Required-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-Required-ToBeReleased-Item CRITICALITY reject TYPE SLDRBs-Required-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION CONFIRM +-- +-- ************************************************************** + +UEContextModificationConfirm::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationConfirmIEs} }, + ... +} + + +UEContextModificationConfirmIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-DRBs-ModifiedConf-List CRITICALITY ignore TYPE DRBs-ModifiedConf-List PRESENCE optional}| + { ID id-RRCContainer CRITICALITY ignore TYPE RRCContainer PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-ExecuteDuplication CRITICALITY ignore TYPE ExecuteDuplication PRESENCE optional}| + { ID id-ResourceCoordinationTransferInformation CRITICALITY ignore TYPE ResourceCoordinationTransferInformation PRESENCE optional }| + { ID id-SLDRBs-ModifiedConf-List CRITICALITY ignore TYPE SLDRBs-ModifiedConf-List PRESENCE optional}, + ... +} + +DRBs-ModifiedConf-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ModifiedConf-ItemIEs } } + +DRBs-ModifiedConf-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ModifiedConf-Item CRITICALITY ignore TYPE DRBs-ModifiedConf-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ModifiedConf-List::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ModifiedConf-ItemIEs } } + +SLDRBs-ModifiedConf-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ModifiedConf-Item CRITICALITY ignore TYPE SLDRBs-ModifiedConf-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION REFUSE +-- +-- ************************************************************** + +UEContextModificationRefuse::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationRefuseIEs} }, + ... +} + + +UEContextModificationRefuseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- WRITE-REPLACE WARNING ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Write-Replace Warning Request +-- +-- ************************************************************** + +WriteReplaceWarningRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {WriteReplaceWarningRequestIEs} }, + ... +} + +WriteReplaceWarningRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-PWSSystemInformation CRITICALITY reject TYPE PWSSystemInformation PRESENCE mandatory }| + { ID id-RepetitionPeriod CRITICALITY reject TYPE RepetitionPeriod PRESENCE mandatory }| + { ID id-NumberofBroadcastRequest CRITICALITY reject TYPE NumberofBroadcastRequest PRESENCE mandatory }| + { ID id-Cells-To-Be-Broadcast-List CRITICALITY reject TYPE Cells-To-Be-Broadcast-List PRESENCE optional }, + ... +} + +Cells-To-Be-Broadcast-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-To-Be-Broadcast-List-ItemIEs } } + +Cells-To-Be-Broadcast-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-To-Be-Broadcast-Item CRITICALITY reject TYPE Cells-To-Be-Broadcast-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- Write-Replace Warning Response +-- +-- ************************************************************** + +WriteReplaceWarningResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {WriteReplaceWarningResponseIEs} }, + ... +} + +WriteReplaceWarningResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-Broadcast-Completed-List CRITICALITY reject TYPE Cells-Broadcast-Completed-List PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-Dedicated-SIDelivery-NeededUE-List CRITICALITY ignore TYPE Dedicated-SIDelivery-NeededUE-List PRESENCE optional }, + ... +} + +Cells-Broadcast-Completed-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-Broadcast-Completed-List-ItemIEs } } + +Cells-Broadcast-Completed-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-Broadcast-Completed-Item CRITICALITY reject TYPE Cells-Broadcast-Completed-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- PWS CANCEL ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS Cancel Request +-- +-- ************************************************************** + +PWSCancelRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PWSCancelRequestIEs} }, + ... +} + +PWSCancelRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-NumberofBroadcastRequest CRITICALITY reject TYPE NumberofBroadcastRequest PRESENCE mandatory }| + { ID id-Broadcast-To-Be-Cancelled-List CRITICALITY reject TYPE Broadcast-To-Be-Cancelled-List PRESENCE optional }| + { ID id-Cancel-all-Warning-Messages-Indicator CRITICALITY reject TYPE Cancel-all-Warning-Messages-Indicator PRESENCE optional }| + { ID id-NotificationInformation CRITICALITY reject TYPE NotificationInformation PRESENCE optional}, + ... +} + +Broadcast-To-Be-Cancelled-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Broadcast-To-Be-Cancelled-List-ItemIEs } } + +Broadcast-To-Be-Cancelled-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Broadcast-To-Be-Cancelled-Item CRITICALITY reject TYPE Broadcast-To-Be-Cancelled-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PWS Cancel Response +-- +-- ************************************************************** + +PWSCancelResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PWSCancelResponseIEs} }, + ... +} + +PWSCancelResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-Broadcast-Cancelled-List CRITICALITY reject TYPE Cells-Broadcast-Cancelled-List PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +Cells-Broadcast-Cancelled-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-Broadcast-Cancelled-List-ItemIEs } } + +Cells-Broadcast-Cancelled-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-Broadcast-Cancelled-Item CRITICALITY reject TYPE Cells-Broadcast-Cancelled-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE Inactivity Notification ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE Inactivity Notification +-- +-- ************************************************************** + +UEInactivityNotification ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ UEInactivityNotificationIEs}}, + ... +} + +UEInactivityNotificationIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-DRB-Activity-List CRITICALITY reject TYPE DRB-Activity-List PRESENCE mandatory } , + ... +} + +DRB-Activity-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRB-Activity-ItemIEs } } + +DRB-Activity-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRB-Activity-Item CRITICALITY reject TYPE DRB-Activity-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- Initial UL RRC Message Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- INITIAL UL RRC Message Transfer +-- +-- ************************************************************** + +InitialULRRCMessageTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ InitialULRRCMessageTransferIEs}}, + ... +} + +InitialULRRCMessageTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-NRCGI CRITICALITY reject TYPE NRCGI PRESENCE mandatory }| + { ID id-C-RNTI CRITICALITY reject TYPE C-RNTI PRESENCE mandatory }| + { ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE mandatory }| + { ID id-DUtoCURRCContainer CRITICALITY reject TYPE DUtoCURRCContainer PRESENCE optional }| + { ID id-SULAccessIndication CRITICALITY ignore TYPE SULAccessIndication PRESENCE optional }| + { ID id-TransactionID CRITICALITY ignore TYPE TransactionID PRESENCE mandatory }| + { ID id-RANUEID CRITICALITY ignore TYPE RANUEID PRESENCE optional }| + { ID id-RRCContainer-RRCSetupComplete CRITICALITY ignore TYPE RRCContainer-RRCSetupComplete PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- DL RRC Message Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- DL RRC Message Transfer +-- +-- ************************************************************** + +DLRRCMessageTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ DLRRCMessageTransferIEs}}, + ... +} + +DLRRCMessageTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-oldgNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-SRBID CRITICALITY reject TYPE SRBID PRESENCE mandatory }| + { ID id-ExecuteDuplication CRITICALITY ignore TYPE ExecuteDuplication PRESENCE optional}| + { ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE mandatory }| + { ID id-RAT-FrequencyPriorityInformation CRITICALITY reject TYPE RAT-FrequencyPriorityInformation PRESENCE optional }| + { ID id-RRCDeliveryStatusRequest CRITICALITY ignore TYPE RRCDeliveryStatusRequest PRESENCE optional }| + { ID id-UEContextNotRetrievable CRITICALITY reject TYPE UEContextNotRetrievable PRESENCE optional }| + { ID id-RedirectedRRCmessage CRITICALITY reject TYPE OCTET STRING PRESENCE optional }| + { ID id-PLMNAssistanceInfoForNetShar CRITICALITY ignore TYPE PLMN-Identity PRESENCE optional }| + { ID id-new-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE optional }| + { ID id-AdditionalRRMPriorityIndex CRITICALITY ignore TYPE AdditionalRRMPriorityIndex PRESENCE optional }, + ... +} +-- ************************************************************** +-- +-- UL RRC Message Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UL RRC Message Transfer +-- +-- ************************************************************** + +ULRRCMessageTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ ULRRCMessageTransferIEs}}, + ... +} + +ULRRCMessageTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SRBID CRITICALITY reject TYPE SRBID PRESENCE mandatory }| + { ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE mandatory }| + { ID id-SelectedPLMNID CRITICALITY reject TYPE PLMN-Identity PRESENCE optional }| + { ID id-new-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PRIVATE MESSAGE +-- +-- ************************************************************** + +PrivateMessage ::= SEQUENCE { + privateIEs PrivateIE-Container {{PrivateMessage-IEs}}, + ... +} + +PrivateMessage-IEs F1AP-PRIVATE-IES ::= { + ... +} + + +-- ************************************************************** +-- +-- System Information ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- System information Delivery Command +-- +-- ************************************************************** + +SystemInformationDeliveryCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ SystemInformationDeliveryCommandIEs}}, + ... +} + +SystemInformationDeliveryCommandIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-NRCGI CRITICALITY reject TYPE NRCGI PRESENCE mandatory }| + { ID id-SItype-List CRITICALITY reject TYPE SItype-List PRESENCE mandatory }| + { ID id-ConfirmedUEID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- Paging PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Paging +-- +-- ************************************************************** + +Paging ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ PagingIEs}}, + ... +} + +PagingIEs F1AP-PROTOCOL-IES ::= { + { ID id-UEIdentityIndexValue CRITICALITY reject TYPE UEIdentityIndexValue PRESENCE mandatory }| + { ID id-PagingIdentity CRITICALITY reject TYPE PagingIdentity PRESENCE mandatory }| + { ID id-PagingDRX CRITICALITY ignore TYPE PagingDRX PRESENCE optional }| + { ID id-PagingPriority CRITICALITY ignore TYPE PagingPriority PRESENCE optional }| + { ID id-PagingCell-List CRITICALITY ignore TYPE PagingCell-list PRESENCE mandatory }| + { ID id-PagingOrigin CRITICALITY ignore TYPE PagingOrigin PRESENCE optional }, + ... +} + +PagingCell-list::= SEQUENCE (SIZE(1.. maxnoofPagingCells)) OF ProtocolIE-SingleContainer { { PagingCell-ItemIEs } } + +PagingCell-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-PagingCell-Item CRITICALITY ignore TYPE PagingCell-Item PRESENCE mandatory} , + ... +} + + + +-- ************************************************************** +-- +-- Notify +-- +-- ************************************************************** + +Notify ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ NotifyIEs}}, + ... +} + +NotifyIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-DRB-Notify-List CRITICALITY reject TYPE DRB-Notify-List PRESENCE mandatory }, + ... +} + +DRB-Notify-List::= SEQUENCE (SIZE(1.. maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRB-Notify-ItemIEs } } + +DRB-Notify-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRB-Notify-Item CRITICALITY reject TYPE DRB-Notify-Item PRESENCE mandatory}, + ... +} + + +-- ************************************************************** +-- +-- NETWORK ACCESS RATE REDUCTION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Network Access Rate Reduction +-- +-- ************************************************************** + +NetworkAccessRateReduction ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ NetworkAccessRateReductionIEs }}, + ... +} + +NetworkAccessRateReductionIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-UAC-Assistance-Info CRITICALITY reject TYPE UAC-Assistance-Info PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PWS RESTART INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS Restart Indication +-- +-- ************************************************************** + +PWSRestartIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PWSRestartIndicationIEs} }, + ... +} + +PWSRestartIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-NR-CGI-List-For-Restart-List CRITICALITY reject TYPE NR-CGI-List-For-Restart-List PRESENCE mandatory }, + ... +} + +NR-CGI-List-For-Restart-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { NR-CGI-List-For-Restart-List-ItemIEs } } + +NR-CGI-List-For-Restart-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-NR-CGI-List-For-Restart-Item CRITICALITY reject TYPE NR-CGI-List-For-Restart-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PWS FAILURE INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS Failure Indication +-- +-- ************************************************************** + +PWSFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PWSFailureIndicationIEs} }, + ... +} + +PWSFailureIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-PWS-Failed-NR-CGI-List CRITICALITY reject TYPE PWS-Failed-NR-CGI-List PRESENCE optional }, + ... +} + +PWS-Failed-NR-CGI-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { PWS-Failed-NR-CGI-List-ItemIEs } } + +PWS-Failed-NR-CGI-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-PWS-Failed-NR-CGI-Item CRITICALITY reject TYPE PWS-Failed-NR-CGI-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- gNB-DU STATUS INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- gNB-DU Status Indication +-- +-- ************************************************************** + +GNBDUStatusIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {GNBDUStatusIndicationIEs} }, + ... +} + +GNBDUStatusIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-GNBDUOverloadInformation CRITICALITY reject TYPE GNBDUOverloadInformation PRESENCE mandatory }, + ... +} + + + +-- ************************************************************** +-- +-- RRC Delivery Report ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- RRC Delivery Report +-- +-- ************************************************************** + +RRCDeliveryReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ RRCDeliveryReportIEs}}, + ... +} + +RRCDeliveryReportIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-RRCDeliveryStatus CRITICALITY ignore TYPE RRCDeliveryStatus PRESENCE mandatory }| + { ID id-SRBID CRITICALITY ignore TYPE SRBID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- F1 Removal ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- F1 Removal Request +-- +-- ************************************************************** + +F1RemovalRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ F1RemovalRequestIEs }}, + ... +} + +F1RemovalRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- F1 Removal Response +-- +-- ************************************************************** + +F1RemovalResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ F1RemovalResponseIEs }}, + ... +} + +F1RemovalResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + + ... +} + +-- ************************************************************** +-- +-- F1 Removal Failure +-- +-- ************************************************************** + +F1RemovalFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ F1RemovalFailureIEs }}, + ... +} + +F1RemovalFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + + ... +} + + +-- ************************************************************** +-- +-- TRACE ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- TRACE START +-- +-- ************************************************************** + +TraceStart ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {TraceStartIEs} }, + ... +} + +TraceStartIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-TraceActivation CRITICALITY ignore TYPE TraceActivation PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- DEACTIVATE TRACE +-- +-- ************************************************************** + +DeactivateTrace ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {DeactivateTraceIEs} }, + ... +} + +DeactivateTraceIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-TraceID CRITICALITY ignore TYPE TraceID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- CELL TRAFFIC TRACE +-- +-- ************************************************************** + +CellTrafficTrace ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {CellTrafficTraceIEs} }, + ... +} + +CellTrafficTraceIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + {ID id-TraceID CRITICALITY ignore TYPE TraceID PRESENCE mandatory }| + {ID id-TraceCollectionEntityIPAddress CRITICALITY ignore TYPE TransportLayerAddress PRESENCE mandatory }| + {ID id-PrivacyIndicator CRITICALITY ignore TYPE PrivacyIndicator PRESENCE optional }| + + {ID id-TraceCollectionEntityURI CRITICALITY ignore TYPE URI-address PRESENCE optional }, + ... + +} + +-- ************************************************************** +-- +-- DU-CU Radio Information Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- DU-CU Radio Information Transfer +-- +-- ************************************************************** + +DUCURadioInformationTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ DUCURadioInformationTransferIEs}}, + ... +} + +DUCURadioInformationTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-DUCURadioInformationType CRITICALITY ignore TYPE DUCURadioInformationType PRESENCE mandatory }, + ... +} + + + +-- ************************************************************** +-- +-- CU-DU Radio Information Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- CU-DU Radio Information Transfer +-- +-- ************************************************************** + +CUDURadioInformationTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ CUDURadioInformationTransferIEs}}, + ... +} + +CUDURadioInformationTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-CUDURadioInformationType CRITICALITY ignore TYPE CUDURadioInformationType PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- IAB PROCEDURES +-- +-- ************************************************************** +-- ************************************************************** +-- +-- BAP Mapping Configuration ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- BAP MAPPING CONFIGURATION +-- ************************************************************** + + +BAPMappingConfiguration ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {BAPMappingConfiguration-IEs} }, + ... + } + +BAPMappingConfiguration-IEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-BH-Routing-Information-Added-List CRITICALITY ignore TYPE BH-Routing-Information-Added-List PRESENCE optional}| + { ID id-BH-Routing-Information-Removed-List CRITICALITY ignore TYPE BH-Routing-Information-Removed-List PRESENCE optional}| + { ID id-TrafficMappingInformation CRITICALITY ignore TYPE TrafficMappingInfo PRESENCE optional}, + ... +} + +BH-Routing-Information-Added-List ::= SEQUENCE (SIZE(1.. maxnoofRoutingEntries)) OF ProtocolIE-SingleContainer { { BH-Routing-Information-Added-List-ItemIEs } } +BH-Routing-Information-Removed-List ::= SEQUENCE (SIZE(1.. maxnoofRoutingEntries)) OF ProtocolIE-SingleContainer { { BH-Routing-Information-Removed-List-ItemIEs } } + +BH-Routing-Information-Added-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BH-Routing-Information-Added-List-Item CRITICALITY ignore TYPE BH-Routing-Information-Added-List-Item PRESENCE optional}, + ... +} + +BH-Routing-Information-Removed-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BH-Routing-Information-Removed-List-Item CRITICALITY ignore TYPE BH-Routing-Information-Removed-List-Item PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- BAP MAPPING CONFIGURATION ACKNOWLEDGE +-- ************************************************************** + +BAPMappingConfigurationAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {BAPMappingConfigurationAcknowledge-IEs} }, + ... +} + +BAPMappingConfigurationAcknowledge-IEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional}, + ... +} + + + +-- ************************************************************** +-- +-- GNB-DU Configuration ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- GNB-DU RESOURCE CONFIGURATION +-- ************************************************************** + + +GNBDUResourceConfiguration ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ GNBDUResourceConfigurationIEs}}, + ... +} + + +GNBDUResourceConfigurationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Activated-Cells-to-be-Updated-List CRITICALITY reject TYPE Activated-Cells-to-be-Updated-List PRESENCE optional}| + { ID id-Child-Nodes-List CRITICALITY reject TYPE Child-Nodes-List PRESENCE optional}, + ... +} + + + + +-- ************************************************************** +-- +-- GNB-DU RESOURCE CONFIGURATION ACKNOWLEDGE +-- ************************************************************** + + +GNBDUResourceConfigurationAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { GNBDUResourceConfigurationAcknowledgeIEs} }, + ... +} + + +GNBDUResourceConfigurationAcknowledgeIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- IAB TNL Address Allocation ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- IAB TNL ADDRESS REQUEST +-- ************************************************************** + + + +IABTNLAddressRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {IABTNLAddressRequestIEs} }, + ... +} + +IABTNLAddressRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-IABv4AddressesRequested CRITICALITY reject TYPE IABv4AddressesRequested PRESENCE optional }| + { ID id-IABIPv6RequestType CRITICALITY reject TYPE IABIPv6RequestType PRESENCE optional }| + { ID id-IAB-TNL-Addresses-To-Remove-List CRITICALITY reject TYPE IAB-TNL-Addresses-To-Remove-List PRESENCE optional }, + ... +} + + +IAB-TNL-Addresses-To-Remove-List ::= SEQUENCE (SIZE(1..maxnoofTLAsIAB)) OF ProtocolIE-SingleContainer { { IAB-TNL-Addresses-To-Remove-ItemIEs } } + +IAB-TNL-Addresses-To-Remove-ItemIEs F1AP-PROTOCOL-IES::= { + { ID id-IAB-TNL-Addresses-To-Remove-Item CRITICALITY reject TYPE IAB-TNL-Addresses-To-Remove-Item PRESENCE mandatory}, + ... +} + + +-- ************************************************************** +-- +-- IAB TNL ADDRESS RESPONSE +-- ************************************************************** + + +IABTNLAddressResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {IABTNLAddressResponseIEs} }, + ... +} + + +IABTNLAddressResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-IAB-Allocated-TNL-Address-List CRITICALITY reject TYPE IAB-Allocated-TNL-Address-List PRESENCE mandatory }, + ... +} + + +IAB-Allocated-TNL-Address-List ::= SEQUENCE (SIZE(1.. maxnoofTLAsIAB)) OF ProtocolIE-SingleContainer { { IAB-Allocated-TNL-Address-List-ItemIEs } } + + +IAB-Allocated-TNL-Address-List-ItemIEs F1AP-PROTOCOL-IES::= { + { ID id-IAB-Allocated-TNL-Address-Item CRITICALITY reject TYPE IAB-Allocated-TNL-Address-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- IAB UP Configuration Update ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- IAB UP Configuration Update Request +-- +-- ************************************************************** + +IABUPConfigurationUpdateRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { IABUPConfigurationUpdateRequestIEs} }, + ... +} + +IABUPConfigurationUpdateRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-UL-UP-TNL-Information-to-Update-List CRITICALITY ignore TYPE UL-UP-TNL-Information-to-Update-List PRESENCE optional }| + { ID id-UL-UP-TNL-Address-to-Update-List CRITICALITY ignore TYPE UL-UP-TNL-Address-to-Update-List PRESENCE optional }, + ... +} + +UL-UP-TNL-Information-to-Update-List ::= SEQUENCE (SIZE(1.. maxnoofULUPTNLInformationforIAB)) OF ProtocolIE-SingleContainer { { UL-UP-TNL-Information-to-Update-List-ItemIEs } } + +UL-UP-TNL-Information-to-Update-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-UL-UP-TNL-Information-to-Update-List-Item CRITICALITY ignore TYPE UL-UP-TNL-Information-to-Update-List-Item PRESENCE optional}, + ... +} + +UL-UP-TNL-Address-to-Update-List ::= SEQUENCE (SIZE(1.. maxnoofUPTNLAddresses)) OF ProtocolIE-SingleContainer { { UL-UP-TNL-Address-to-Update-List-ItemIEs } } + +UL-UP-TNL-Address-to-Update-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-UL-UP-TNL-Address-to-Update-List-Item CRITICALITY ignore TYPE UL-UP-TNL-Address-to-Update-List-Item PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- IAB UP Configuration Update Response +-- +-- ************************************************************** + +IABUPConfigurationUpdateResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { IABUPConfigurationUpdateResponseIEs} }, + ... +} + +IABUPConfigurationUpdateResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-DL-UP-TNL-Address-to-Update-List CRITICALITY reject TYPE DL-UP-TNL-Address-to-Update-List PRESENCE optional }, + ... +} + +DL-UP-TNL-Address-to-Update-List ::= SEQUENCE (SIZE(1.. maxnoofUPTNLAddresses)) OF ProtocolIE-SingleContainer { { DL-UP-TNL-Address-to-Update-List-ItemIEs } } + +DL-UP-TNL-Address-to-Update-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DL-UP-TNL-Address-to-Update-List-Item CRITICALITY ignore TYPE DL-UP-TNL-Address-to-Update-List-Item PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- IAB UP Configuration Update Failure +-- +-- ************************************************************** + +IABUPConfigurationUpdateFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { IABUPConfigurationUpdateFailureIEs} }, + ... +} + +IABUPConfigurationUpdateFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Resource Status Reporting Initiation ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Resource Status Request +-- +-- ************************************************************** + +ResourceStatusRequest::= SEQUENCE { + protocolIEs ProtocolIE-Container { {ResourceStatusRequestIEs} }, + ... +} + +ResourceStatusRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNBCUMeasurementID CRITICALITY reject TYPE GNBCUMeasurementID PRESENCE mandatory }| + { ID id-gNBDUMeasurementID CRITICALITY ignore TYPE GNBDUMeasurementID PRESENCE conditional }| + { ID id-RegistrationRequest CRITICALITY ignore TYPE RegistrationRequest PRESENCE mandatory }| + { ID id-ReportCharacteristics CRITICALITY ignore TYPE ReportCharacteristics PRESENCE conditional }| + { ID id-CellToReportList CRITICALITY ignore TYPE CellToReportList PRESENCE optional }| + { ID id-ReportingPeriodicity CRITICALITY ignore TYPE ReportingPeriodicity PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- Resource Status Response +-- +-- ************************************************************** + +ResourceStatusResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { ResourceStatusResponseIEs} }, + ... +} + + +ResourceStatusResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNBCUMeasurementID CRITICALITY reject TYPE GNBCUMeasurementID PRESENCE mandatory }| + { ID id-gNBDUMeasurementID CRITICALITY ignore TYPE GNBDUMeasurementID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- Resource Status Failure +-- +-- ************************************************************** + +ResourceStatusFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { ResourceStatusFailureIEs} }, + ... +} + +ResourceStatusFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNBCUMeasurementID CRITICALITY reject TYPE GNBCUMeasurementID PRESENCE mandatory }| + { ID id-gNBDUMeasurementID CRITICALITY ignore TYPE GNBDUMeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Resource Status Reporting ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Resource Status Update +-- +-- ************************************************************** + +ResourceStatusUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ ResourceStatusUpdateIEs}}, + ... +} + +ResourceStatusUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNBCUMeasurementID CRITICALITY reject TYPE GNBCUMeasurementID PRESENCE mandatory }| + { ID id-gNBDUMeasurementID CRITICALITY ignore TYPE GNBDUMeasurementID PRESENCE mandatory }| + { ID id-HardwareLoadIndicator CRITICALITY ignore TYPE HardwareLoadIndicator PRESENCE optional }| + { ID id-TNLCapacityIndicator CRITICALITY ignore TYPE TNLCapacityIndicator PRESENCE optional }| + { ID id-CellMeasurementResultList CRITICALITY ignore TYPE CellMeasurementResultList PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Access And Mobility Indication ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Access And Mobility Indication +-- +-- ************************************************************** + +AccessAndMobilityIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { AccessAndMobilityIndicationIEs} }, + ... +} + +AccessAndMobilityIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-RACHReportInformationList CRITICALITY ignore TYPE RACHReportInformationList PRESENCE optional }| + { ID id-RLFReportInformationList CRITICALITY ignore TYPE RLFReportInformationList PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- REFERENCE TIME INFORMATION REPORTING CONTROL +-- +-- ************************************************************** + +ReferenceTimeInformationReportingControl::= SEQUENCE { + protocolIEs ProtocolIE-Container { { ReferenceTimeInformationReportingControlIEs} }, + ... +} + +ReferenceTimeInformationReportingControlIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-ReportingRequestType CRITICALITY reject TYPE ReportingRequestType PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- REFERENCE TIME INFORMATION REPORT +-- +-- ************************************************************** + +ReferenceTimeInformationReport::= SEQUENCE { + protocolIEs ProtocolIE-Container { { ReferenceTimeInformationReportIEs} }, + ... +} + +ReferenceTimeInformationReportIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY ignore TYPE TransactionID PRESENCE mandatory }| + { ID id-TimeReferenceInformation CRITICALITY ignore TYPE TimeReferenceInformation PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- Access Success +-- +-- ************************************************************** + +AccessSuccess ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ AccessSuccessIEs}}, + ... +} + +AccessSuccessIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-NRCGI CRITICALITY reject TYPE NRCGI PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING ASSISTANCE INFORMATION CONTROL ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Assistance Information Control +-- +-- ************************************************************** + +PositioningAssistanceInformationControl ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ PositioningAssistanceInformationControlIEs}}, + ... +} + +PositioningAssistanceInformationControlIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-PosAssistance-Information CRITICALITY reject TYPE PosAssistance-Information PRESENCE optional}| + { ID id-PosBroadcast CRITICALITY reject TYPE PosBroadcast PRESENCE optional}| + { ID id-PositioningBroadcastCells CRITICALITY reject TYPE PositioningBroadcastCells PRESENCE optional}| + { ID id-RoutingID CRITICALITY reject TYPE RoutingID PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- POSITIONING ASSISTANCE INFORMATION FEEDBACK ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Assistance Information Feedback +-- +-- ************************************************************** + +PositioningAssistanceInformationFeedback ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ PositioningAssistanceInformationFeedbackIEs}}, + ... +} + +PositioningAssistanceInformationFeedbackIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-PosAssistanceInformationFailureList CRITICALITY reject TYPE PosAssistanceInformationFailureList PRESENCE optional}| + { ID id-PositioningBroadcastCells CRITICALITY reject TYPE PositioningBroadcastCells PRESENCE optional}| + { ID id-RoutingID CRITICALITY reject TYPE RoutingID PRESENCE optional}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- POSITONING MEASUREMENT EXCHANGE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Request +-- +-- ************************************************************** + +PositioningMeasurementRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementRequestIEs} }, + ... +} + +PositioningMeasurementRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory}| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory}| + { ID id-TRP-MeasurementRequestList CRITICALITY reject TYPE TRP-MeasurementRequestList PRESENCE mandatory}| + { ID id-PosReportCharacteristics CRITICALITY reject TYPE PosReportCharacteristics PRESENCE mandatory}| + { ID id-PosMeasurementPeriodicity CRITICALITY reject TYPE PosMeasurementPeriodicity PRESENCE conditional }| + -- The above IE shall be present if the PosReportCharacteristics IE is set to “periodic” -- + { ID id-PosMeasurementQuantities CRITICALITY reject TYPE PosMeasurementQuantities PRESENCE mandatory}| + { ID id-SFNInitialisationTime CRITICALITY ignore TYPE SFNInitialisationTime PRESENCE optional }| + { ID id-SRSConfiguration CRITICALITY ignore TYPE SRSConfiguration PRESENCE optional}| + { ID id-MeasurementBeamInfoRequest CRITICALITY ignore TYPE MeasurementBeamInfoRequest PRESENCE optional }| + { ID id-SystemFrameNumber CRITICALITY ignore TYPE SystemFrameNumber PRESENCE optional}| + { ID id-SlotNumber CRITICALITY ignore TYPE SlotNumber PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- Positioning Measurement Response +-- +-- ************************************************************** + +PositioningMeasurementResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementResponseIEs} }, + ... +} + + +PositioningMeasurementResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory}| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory}| + { ID id-PosMeasurementResultList CRITICALITY reject TYPE PosMeasurementResultList PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- Positioning Measurement Failure +-- +-- ************************************************************** + +PositioningMeasurementFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementFailureIEs} }, + ... +} + +PositioningMeasurementFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING MEASUREMENT REPORT ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Report +-- +-- ************************************************************** + +PositioningMeasurementReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementReportIEs} }, + ... +} + +PositioningMeasurementReportIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }| + { ID id-PosMeasurementResultList CRITICALITY reject TYPE PosMeasurementResultList PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- POSITIONING MEASUREMENT ABORT ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Abort +-- +-- ************************************************************** + +PositioningMeasurementAbort ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementAbortIEs} }, + ... +} + +PositioningMeasurementAbortIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- POSITIONING MEASUREMENT FAILURE INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Failure Indication +-- +-- ************************************************************** + +PositioningMeasurementFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementFailureIndicationIEs} }, + ... +} + +PositioningMeasurementFailureIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- POSITIONING MEASUREMENT UPDATE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Update +-- +-- ************************************************************** + +PositioningMeasurementUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementUpdateIEs} }, + ... +} + +PositioningMeasurementUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }| + { ID id-SRSConfiguration CRITICALITY ignore TYPE SRSConfiguration PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- TRP INFORMATION EXCHANGE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- TRP Information Request +-- +-- ************************************************************** + +TRPInformationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { TRPInformationRequestIEs} }, + ... +} + +TRPInformationRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-TRPList CRITICALITY ignore TYPE TRPList PRESENCE optional }| + { ID id-TRPInformationTypeListTRPReq CRITICALITY reject TYPE TRPInformationTypeListTRPReq PRESENCE mandatory }, + ... +} + +TRPInformationTypeListTRPReq ::= SEQUENCE (SIZE(1.. maxnoofTRPInfoTypes)) OF ProtocolIE-SingleContainer { { TRPInformationTypeItemTRPReq } } + +TRPInformationTypeItemTRPReq F1AP-PROTOCOL-IES ::= { + { ID id-TRPInformationTypeItem CRITICALITY reject TYPE TRPInformationTypeItem PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- TRP Information Response +-- +-- ************************************************************** + +TRPInformationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { TRPInformationResponseIEs} }, + ... +} + +TRPInformationResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-TRPInformationListTRPResp CRITICALITY ignore TYPE TRPInformationListTRPResp PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +TRPInformationListTRPResp ::= SEQUENCE (SIZE(1.. maxnoofTRPs)) OF ProtocolIE-SingleContainer { { TRPInformationItemTRPResp } } + +TRPInformationItemTRPResp F1AP-PROTOCOL-IES ::= { + { ID id-TRPInformationItem CRITICALITY ignore TYPE TRPInformationItem PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- TRP Information Failure +-- +-- ************************************************************** + +TRPInformationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { TRPInformationFailureIEs} }, + ... +} + +TRPInformationFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING INFORMATION EXCHANGE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Information Request +-- +-- ************************************************************** + +PositioningInformationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningInformationRequestIEs} }, + ... +} + +PositioningInformationRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-RequestedSRSTransmissionCharacteristics CRITICALITY ignore TYPE RequestedSRSTransmissionCharacteristics PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- Positioning Information Response +-- +-- ************************************************************** + +PositioningInformationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningInformationResponseIEs} }, + ... +} + + +PositioningInformationResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SRSConfiguration CRITICALITY ignore TYPE SRSConfiguration PRESENCE optional}| + { ID id-SFNInitialisationTime CRITICALITY ignore TYPE SFNInitialisationTime PRESENCE optional}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- Positioning Information Failure +-- +-- ************************************************************** + +PositioningInformationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningInformationFailureIEs} }, + ... +} + +PositioningInformationFailureIEs F1AP-PROTOCOL-IES ::= { + + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING ACTIVATION PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Activation Request +-- +-- ************************************************************** + +PositioningActivationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningActivationRequestIEs} }, + ... +} + +PositioningActivationRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SRSType CRITICALITY reject TYPE SRSType PRESENCE mandatory }| + { ID id-ActivationTime CRITICALITY ignore TYPE SFNInitialisationTime PRESENCE optional }, + ... +} + +SRSType ::= CHOICE { + semipersistentSRS SemipersistentSRS, + aperiodicSRS AperiodicSRS, + choice-extension ProtocolIE-SingleContainer { { SRSType-ExtIEs} } +} + +SRSType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SemipersistentSRS ::= SEQUENCE { + sRSResourceSetID SRSResourceSetID, + sRSSpatialRelation SRSSpatialRelation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {SemipersistentSRS-ExtIEs} } OPTIONAL, + ... +} + +SemipersistentSRS-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AperiodicSRS ::= SEQUENCE { + aperiodic ENUMERATED {true, ...}, + sRSResourceTrigger SRSResourceTrigger OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {AperiodicSRS-ExtIEs} } OPTIONAL, + ... +} + +AperiodicSRS-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +-- ************************************************************** +-- +-- Positioning Activation Response +-- +-- ************************************************************** + +PositioningActivationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningActivationResponseIEs} }, + ... +} + + +PositioningActivationResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SystemFrameNumber CRITICALITY ignore TYPE SystemFrameNumber PRESENCE optional }| + { ID id-SlotNumber CRITICALITY ignore TYPE SlotNumber PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + + + +-- ************************************************************** +-- +-- Positioning Activation Failure +-- +-- ************************************************************** + +PositioningActivationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningActivationFailureIEs} }, + ... +} + +PositioningActivationFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING DEACTIVATION PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Deactivation +-- +-- ************************************************************** + +PositioningDeactivation ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningDeactivationIEs} }, + ... +} + +PositioningDeactivationIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-AbortTransmission CRITICALITY ignore TYPE AbortTransmission PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- POSITIONING INFORMATION UPDATE PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Information Update +-- +-- ************************************************************** + +PositioningInformationUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningInformationUpdateIEs} }, + ... +} + + +PositioningInformationUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SRSConfiguration CRITICALITY ignore TYPE SRSConfiguration PRESENCE optional}| + { ID id-SFNInitialisationTime CRITICALITY ignore TYPE SFNInitialisationTime PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- E-CID MEASUREMENT PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- E-CID Measurement Initiation Request +-- +-- ************************************************************** + +E-CIDMeasurementInitiationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementInitiationRequest-IEs}}, + ... +} + +E-CIDMeasurementInitiationRequest-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-E-CID-ReportCharacteristics CRITICALITY reject TYPE E-CID-ReportCharacteristics PRESENCE mandatory }| + { ID id-E-CID-MeasurementPeriodicity CRITICALITY reject TYPE E-CID-MeasurementPeriodicity PRESENCE conditional }| +-- The above IE shall be present if the E-CID-ReportCharacteristics IE is set to “periodic” –- + { ID id-E-CID-MeasurementQuantities CRITICALITY reject TYPE E-CID-MeasurementQuantities PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- E-CID Measurement Initiation Response +-- +-- ************************************************************** + +E-CIDMeasurementInitiationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementInitiationResponse-IEs}}, + ... +} + +E-CIDMeasurementInitiationResponse-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-E-CID-MeasurementResult CRITICALITY ignore TYPE E-CID-MeasurementResult PRESENCE optional}| + { ID id-Cell-Portion-ID CRITICALITY ignore TYPE Cell-Portion-ID PRESENCE optional}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- E-CID Measurement Initiation Failure +-- +-- ************************************************************** + +E-CIDMeasurementInitiationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementInitiationFailure-IEs}}, + ... +} + + +E-CIDMeasurementInitiationFailure-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- E-CID MEASUREMENT FAILURE INDICATION PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- E-CID Measurement Failure Indication +-- +-- ************************************************************** + +E-CIDMeasurementFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementFailureIndication-IEs}}, + ... +} + + +E-CIDMeasurementFailureIndication-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- E-CID MEASUREMENT REPORT PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- E-CID Measurement Report +-- +-- ************************************************************** + +E-CIDMeasurementReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementReport-IEs}}, + ... +} + + +E-CIDMeasurementReport-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-E-CID-MeasurementResult CRITICALITY ignore TYPE E-CID-MeasurementResult PRESENCE mandatory }| + { ID id-Cell-Portion-ID CRITICALITY ignore TYPE Cell-Portion-ID PRESENCE optional}, + + ... +} + +-- ************************************************************** +-- +-- E-CID MEASUREMENT TERMINATION PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- E-CID Measurement Termination Command +-- +-- ************************************************************** + + +E-CIDMeasurementTerminationCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementTerminationCommand-IEs}}, + ... +} + + +E-CIDMeasurementTerminationCommand-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }, + ... +} + + + +END +-- ASN1STOP + + +-- ASN1START +-- ************************************************************** +-- +-- Information Element Definitions +-- +-- ************************************************************** + +F1AP-IEs { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-IEs (2) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + id-gNB-CUSystemInformation, + id-HandoverPreparationInformation, + id-TAISliceSupportList, + id-RANAC, + id-BearerTypeChange, + id-Cell-Direction, + id-Cell-Type, + id-CellGroupConfig, + id-AvailablePLMNList, + id-PDUSessionID, + id-ULPDUSessionAggregateMaximumBitRate, + id-DC-Based-Duplication-Configured, + id-DC-Based-Duplication-Activation, + id-Duplication-Activation, + id-DLPDCPSNLength, + id-ULPDCPSNLength, + id-RLC-Status, + id-MeasurementTimingConfiguration, + id-DRB-Information, + id-QoSFlowMappingIndication, + id-ServingCellMO, + id-RLCMode, + id-ExtendedServedPLMNs-List, + id-ExtendedAvailablePLMN-List, + id-DRX-LongCycleStartOffset, + id-SelectedBandCombinationIndex, + id-SelectedFeatureSetEntryIndex, + id-Ph-InfoSCG, + id-latest-RRC-Version-Enhanced, + id-RequestedBandCombinationIndex, + id-RequestedFeatureSetEntryIndex, + id-DRX-Config, + id-UEAssistanceInformation, + id-PDCCH-BlindDetectionSCG, + id-Requested-PDCCH-BlindDetectionSCG, + id-BPLMN-ID-Info-List, + id-NotificationInformation, + id-TNLAssociationTransportLayerAddressgNBDU, + id-portNumber, + id-AdditionalSIBMessageList, + id-IgnorePRACHConfiguration, + id-CG-Config, + id-Ph-InfoMCG, + id-AggressorgNBSetID, + id-VictimgNBSetID, + id-MeasGapSharingConfig, + id-systemInformationAreaID, + id-areaScope, + id-IntendedTDD-DL-ULConfig, + id-QosMonitoringRequest, + id-BHInfo, + id-IAB-Info-IAB-DU, + id-IAB-Info-IAB-donor-CU, + id-IAB-Barred, + id-SIB12-message, + id-SIB13-message, + id-SIB14-message, + id-UEAssistanceInformationEUTRA, + id-SL-PHY-MAC-RLC-Config, + id-SL-ConfigDedicatedEUTRA, + id-AlternativeQoSParaSetList, + id-CurrentQoSParaSetIndex, + id-CarrierList, + id-ULCarrierList, + id-FrequencyShift7p5khz, + id-SSB-PositionsInBurst, + id-NRPRACHConfig, + id-TDD-UL-DLConfigCommonNR, + id-CNPacketDelayBudgetDownlink, + id-CNPacketDelayBudgetUplink, + id-ExtendedPacketDelayBudget, + id-TSCTrafficCharacteristics, + id-AdditionalPDCPDuplicationTNL-List, + id-RLCDuplicationInformation, + id-AdditionalDuplicationIndication, + id-mdtConfiguration, + id-TraceCollectionEntityURI, + id-NID, + id-NPNSupportInfo, + id-NPNBroadcastInformation, + id-AvailableSNPN-ID-List, + id-SIB10-message, + id-RequestedP-MaxFR2, + id-DLCarrierList, + id-ExtendedTAISliceSupportList, + id-E-CID-MeasurementQuantities-Item, + id-ConfiguredTACIndication, + maxNRARFCN, + maxnoofErrors, + maxnoofBPLMNs, + maxnoofBPLMNsNR, + maxnoofDLUPTNLInformation, + maxnoofNrCellBands, + maxnoofULUPTNLInformation, + maxnoofQoSFlows, + maxnoofSliceItems, + maxnoofSIBTypes, + maxnoofSITypes, + maxCellineNB, + maxnoofExtendedBPLMNs, + maxnoofAdditionalSIBs, + maxnoofUACPLMNs, + maxnoofUACperPLMN, + maxCellingNBDU, + maxnoofTLAs, + maxnoofGTPTLAs, + maxnoofslots, + maxnoofNonUPTrafficMappings, + maxnoofServingCells, + maxnoofServedCellsIAB, + maxnoofChildIABNodes, + maxnoofIABSTCInfo, + maxnoofSymbols, + maxnoofDUFSlots, + maxnoofHSNASlots, + maxnoofEgressLinks, + maxnoofMappingEntries, + maxnoofDSInfo, + maxnoofQoSParaSets, + maxnoofPC5QoSFlows, + maxnoofSSBAreas, + maxnoofBPLMNsNR, + maxnoofNRSCSs, + maxnoofPhysicalResourceBlocks, + maxnoofPhysicalResourceBlocks-1, + maxnoofPRACHconfigs, + maxnoofRACHReports, + maxnoofRLFReports, + maxnoofAdditionalPDCPDuplicationTNL, + maxnoofRLCDuplicationState, + maxnoofCHOcells, + maxnoofMDTPLMNs, + maxnoofCAGsupported, + maxnoofNIDsupported, + maxnoofNRSCSs, + maxnoofPhysicalResourceBlocks, + maxnoofExtSliceItems, + maxnoofPosMeas, + maxnoofTRPInfoTypes, + maxnoofSRSTriggerStates, + maxnoofSpatialRelations, + maxnoBcastCell, + maxnoofTRPs, + maxnoofAngleInfo, + maxnooflcs-gcs-translation, + maxnoofPath, + maxnoofMeasE-CID, + maxnoofSSBs, + maxnoSRS-ResourceSets, + maxnoSRS-ResourcePerSet, + maxnoSRS-Carriers, + maxnoSCSs, + maxnoSRS-Resources, + maxnoSRS-PosResources, + maxnoSRS-PosResourceSets, + maxnoSRS-PosResourcePerSet, + maxnoofPRS-ResourceSets, + maxnoofPRS-ResourcesPerSet, + maxNoOfMeasTRPs, + maxnoofPRSresourceSets, + maxnoofPRSresources + + + +FROM F1AP-Constants + + Criticality, + ProcedureCode, + ProtocolIE-ID, + TriggeringMessage + +FROM F1AP-CommonDataTypes + + ProtocolExtensionContainer{}, + F1AP-PROTOCOL-EXTENSION, + ProtocolIE-SingleContainer{}, + F1AP-PROTOCOL-IES + +FROM F1AP-Containers; + +-- A + +AbortTransmission ::= CHOICE { + sRSResourceSetID SRSResourceSetID, + releaseALL NULL, + choice-extension ProtocolIE-SingleContainer { { AbortTransmission-ExtIEs } } +} + +AbortTransmission-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +AccessPointPosition ::= SEQUENCE { + latitudeSign ENUMERATED {north, south}, + latitude INTEGER (0..8388607), + longitude INTEGER (-8388608..8388607), + directionOfAltitude ENUMERATED {height, depth}, + altitude INTEGER (0..32767), + uncertaintySemi-major INTEGER (0..127), + uncertaintySemi-minor INTEGER (0..127), + orientationOfMajorAxis INTEGER (0..179), + uncertaintyAltitude INTEGER (0..127), + confidence INTEGER (0..100), + iE-Extensions ProtocolExtensionContainer { { AccessPointPosition-ExtIEs} } OPTIONAL +} + +AccessPointPosition-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Activated-Cells-to-be-Updated-List ::= SEQUENCE (SIZE(1..maxnoofServedCellsIAB)) OF Activated-Cells-to-be-Updated-List-Item + +Activated-Cells-to-be-Updated-List-Item ::= SEQUENCE{ + nRCGI NRCGI, + iAB-DU-Cell-Resource-Configuration-Mode-Info IAB-DU-Cell-Resource-Configuration-Mode-Info, + iE-Extensions ProtocolExtensionContainer { { Activated-Cells-to-be-Updated-List-Item-ExtIEs} } OPTIONAL +} + +Activated-Cells-to-be-Updated-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ActiveULBWP ::= SEQUENCE { + locationAndBandwidth INTEGER (0..37949,...), + subcarrierSpacing ENUMERATED {kHz15, kHz30, kHz60, kHz120,...}, + cyclicPrefix ENUMERATED {normal, extended}, + txDirectCurrentLocation INTEGER (0..3301,...), + shift7dot5kHz ENUMERATED {true, ...} OPTIONAL, + sRSConfig SRSConfig, + iE-Extensions ProtocolExtensionContainer { { ActiveULBWP-ExtIEs} } OPTIONAL +} + +ActiveULBWP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AdditionalDuplicationIndication ::= ENUMERATED { + three, + four, + ... +} + + +AdditionalPath-List::= SEQUENCE (SIZE(1..maxnoofPath)) OF AdditionalPath-Item + +AdditionalPath-Item ::=SEQUENCE { + relativePathDelay RelativePathDelay, + pathQuality TRPMeasurementQuality OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { AdditionalPath-Item-ExtIEs } } OPTIONAL +} + +AdditionalPath-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +AdditionalPDCPDuplicationTNL-List ::= SEQUENCE (SIZE(1..maxnoofAdditionalPDCPDuplicationTNL)) OF AdditionalPDCPDuplicationTNL-Item + +AdditionalPDCPDuplicationTNL-Item ::=SEQUENCE { + additionalPDCPDuplicationUPTNLInformation UPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { { AdditionalPDCPDuplicationTNL-ItemExtIEs } } OPTIONAL, + ... +} + +AdditionalPDCPDuplicationTNL-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AdditionalSIBMessageList ::= SEQUENCE (SIZE(1..maxnoofAdditionalSIBs)) OF AdditionalSIBMessageList-Item + +AdditionalSIBMessageList-Item ::= SEQUENCE { + additionalSIB OCTET STRING, + iE-Extensions ProtocolExtensionContainer { { AdditionalSIBMessageList-Item-ExtIEs} } OPTIONAL +} + +AdditionalSIBMessageList-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AdditionalRRMPriorityIndex ::= BIT STRING (SIZE(32)) + +AggressorCellList ::= SEQUENCE (SIZE(1..maxCellingNBDU)) OF AggressorCellList-Item + +AggressorCellList-Item ::= SEQUENCE { + aggressorCell-ID NRCGI, + iE-Extensions ProtocolExtensionContainer { { AggressorCellList-Item-ExtIEs } } OPTIONAL +} + +AggressorCellList-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AggressorgNBSetID ::= SEQUENCE { + aggressorgNBSetID GNBSetID, + iE-Extensions ProtocolExtensionContainer { { AggressorgNBSetID-ExtIEs } } OPTIONAL +} + +AggressorgNBSetID-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AllocationAndRetentionPriority ::= SEQUENCE { + priorityLevel PriorityLevel, + pre-emptionCapability Pre-emptionCapability, + pre-emptionVulnerability Pre-emptionVulnerability, + iE-Extensions ProtocolExtensionContainer { {AllocationAndRetentionPriority-ExtIEs} } OPTIONAL, + ... +} + +AllocationAndRetentionPriority-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AlternativeQoSParaSetList ::= SEQUENCE (SIZE(1..maxnoofQoSParaSets)) OF AlternativeQoSParaSetItem + +AlternativeQoSParaSetItem ::= SEQUENCE { + alternativeQoSParaSetIndex QoSParaSetIndex, + guaranteedFlowBitRateDL BitRate OPTIONAL, + guaranteedFlowBitRateUL BitRate OPTIONAL, + packetDelayBudget PacketDelayBudget OPTIONAL, + packetErrorRate PacketErrorRate OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {AlternativeQoSParaSetItem-ExtIEs} } OPTIONAL, + ... +} + +AlternativeQoSParaSetItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +AngleMeasurementQuality ::= SEQUENCE { + azimuthQuality INTEGER(0..255), + zenithQuality INTEGER(0..255) OPTIONAL, + resolution ENUMERATED{deg0dot1,...}, + iE-Extensions ProtocolExtensionContainer { { AngleMeasurementQuality-ExtIEs } } OPTIONAL +} + +AngleMeasurementQuality-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +AperiodicSRSResourceTriggerList ::= SEQUENCE (SIZE(1..maxnoofSRSTriggerStates)) OF AperiodicSRSResourceTrigger + +AperiodicSRSResourceTrigger ::= INTEGER (0..3, ...) + +Associated-SCell-Item ::= SEQUENCE { + sCell-ID NRCGI, + iE-Extensions ProtocolExtensionContainer { { Associated-SCell-ItemExtIEs } } OPTIONAL +} + +Associated-SCell-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AvailablePLMNList ::= SEQUENCE (SIZE(1..maxnoofBPLMNs)) OF AvailablePLMNList-Item + +AvailablePLMNList-Item ::= SEQUENCE { + pLMNIdentity PLMN-Identity, + iE-Extensions ProtocolExtensionContainer { { AvailablePLMNList-Item-ExtIEs} } OPTIONAL +} + +AvailablePLMNList-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AvailableSNPN-ID-List ::= SEQUENCE (SIZE(1..maxnoofNIDsupported)) OF AvailableSNPN-ID-List-Item + +AvailableSNPN-ID-List-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + availableNIDList BroadcastNIDList, + iE-Extensions ProtocolExtensionContainer { { AvailableSNPN-ID-List-ItemExtIEs} } OPTIONAL, + ... +} + +AvailableSNPN-ID-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AveragingWindow ::= INTEGER (0..4095, ...) + +AreaScope ::= ENUMERATED {true, ...} + +-- B + +BandwidthSRS ::= CHOICE { + fR1 FR1-Bandwidth, + fR2 FR2-Bandwidth, + choice-extension ProtocolIE-SingleContainer {{ BandwidthSRS-ExtIEs }} +} + +BandwidthSRS-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +BAPAddress ::= BIT STRING (SIZE(10)) + +BAPCtrlPDUChannel ::= ENUMERATED {true, ...} + +BAPlayerBHRLCchannelMappingInfo ::= SEQUENCE { + bAPlayerBHRLCchannelMappingInfoToAdd BAPlayerBHRLCchannelMappingInfoList OPTIONAL, + bAPlayerBHRLCchannelMappingInfoToRemove MappingInformationtoRemove OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BAPlayerBHRLCchannelMappingInfo-ExtIEs} } OPTIONAL, + ... +} + +BAPlayerBHRLCchannelMappingInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BAPlayerBHRLCchannelMappingInfoList ::= SEQUENCE (SIZE(1..maxnoofMappingEntries)) OF BAPlayerBHRLCchannelMappingInfo-Item + +BAPlayerBHRLCchannelMappingInfo-Item ::= SEQUENCE { + mappingInformationIndex MappingInformationIndex, + priorHopBAPAddress BAPAddress OPTIONAL, + ingressbHRLCChannelID BHRLCChannelID OPTIONAL, + nextHopBAPAddress BAPAddress OPTIONAL, + egressbHRLCChannelID BHRLCChannelID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BAPlayerBHRLCchannelMappingInfo-ItemExtIEs} } OPTIONAL, + ... +} + +BAPlayerBHRLCchannelMappingInfo-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BAPPathID ::= BIT STRING (SIZE(10)) + +BAPRoutingID ::= SEQUENCE { + bAPAddress BAPAddress, + bAPPathID BAPPathID, + iE-Extensions ProtocolExtensionContainer { { BAPRoutingIDExtIEs } } OPTIONAL +} + +BAPRoutingIDExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BitRate ::= INTEGER (0..4000000000000,...) + +BearerTypeChange ::= ENUMERATED {true, ...} + +BHRLCChannelID ::= BIT STRING (SIZE(16)) + +BHChannels-FailedToBeModified-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-FailedToBeModified-ItemExtIEs } } OPTIONAL +} + +BHChannels-FailedToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-FailedToBeSetup-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-FailedToBeSetup-ItemExtIEs } } OPTIONAL +} + +BHChannels-FailedToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-FailedToBeSetupMod-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { BHChannels-FailedToBeSetupMod-ItemExtIEs } } OPTIONAL +} + +BHChannels-FailedToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-Modified-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-Modified-ItemExtIEs } } OPTIONAL +} + +BHChannels-Modified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-Required-ToBeReleased-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-Required-ToBeReleased-ItemExtIEs } } OPTIONAL +} + +BHChannels-Required-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-Setup-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-Setup-ItemExtIEs } } OPTIONAL +} + +BHChannels-Setup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-SetupMod-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-SetupMod-ItemExtIEs } } OPTIONAL +} + +BHChannels-SetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-ToBeModified-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + bHQoSInformation BHQoSInformation, + rLCmode RLCMode OPTIONAL, + bAPCtrlPDUChannel BAPCtrlPDUChannel OPTIONAL, + trafficMappingInfo TrafficMappingInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-ToBeModified-ItemExtIEs } } OPTIONAL +} + +BHChannels-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-ToBeReleased-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-ToBeReleased-ItemExtIEs } } OPTIONAL +} + +BHChannels-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-ToBeSetup-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + bHQoSInformation BHQoSInformation, + rLCmode RLCMode, + bAPCtrlPDUChannel BAPCtrlPDUChannel OPTIONAL, + trafficMappingInfo TrafficMappingInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-ToBeSetup-ItemExtIEs } } OPTIONAL +} + +BHChannels-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-ToBeSetupMod-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + bHQoSInformation BHQoSInformation, + rLCmode RLCMode, + bAPCtrlPDUChannel BAPCtrlPDUChannel OPTIONAL, + trafficMappingInfo TrafficMappingInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-ToBeSetupMod-ItemExtIEs } } OPTIONAL +} + +BHChannels-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHInfo ::= SEQUENCE { + bAProutingID BAPRoutingID OPTIONAL, + egressBHRLCCHList EgressBHRLCCHList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHInfo-ExtIEs} } OPTIONAL +} + +BHInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHQoSInformation ::= CHOICE { + bHRLCCHQoS QoSFlowLevelQoSParameters, + eUTRANBHRLCCHQoS EUTRANQoS, + cPTrafficType CPTrafficType, + choice-extension ProtocolIE-SingleContainer { { BHQoSInformation-ExtIEs} } +} + +BHQoSInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +BH-Routing-Information-Added-List-Item ::= SEQUENCE { + bAPRoutingID BAPRoutingID, + nextHopBAPAddress BAPAddress, + iE-Extensions ProtocolExtensionContainer { { BH-Routing-Information-Added-List-ItemExtIEs} } OPTIONAL +} + +BH-Routing-Information-Added-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BH-Routing-Information-Removed-List-Item ::= SEQUENCE { + bAPRoutingID BAPRoutingID, + iE-Extensions ProtocolExtensionContainer { { BH-Routing-Information-Removed-List-ItemExtIEs} } OPTIONAL +} + +BH-Routing-Information-Removed-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BPLMN-ID-Info-List ::= SEQUENCE (SIZE(1..maxnoofBPLMNsNR)) OF BPLMN-ID-Info-Item + +BPLMN-ID-Info-Item ::= SEQUENCE { + pLMN-Identity-List AvailablePLMNList, + extended-PLMN-Identity-List ExtendedAvailablePLMN-List OPTIONAL, + fiveGS-TAC FiveGS-TAC OPTIONAL, + nr-cell-ID NRCellIdentity, + ranac RANAC OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BPLMN-ID-Info-ItemExtIEs} } OPTIONAL, + ... +} + +BPLMN-ID-Info-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ConfiguredTACIndication CRITICALITY ignore EXTENSION ConfiguredTACIndication PRESENCE optional }| + { ID id-NPNBroadcastInformation CRITICALITY reject EXTENSION NPNBroadcastInformation PRESENCE optional}, + ... +} + +ServedPLMNs-List ::= SEQUENCE (SIZE(1..maxnoofBPLMNs)) OF ServedPLMNs-Item + +ServedPLMNs-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + iE-Extensions ProtocolExtensionContainer { { ServedPLMNs-ItemExtIEs} } OPTIONAL, + ... +} + +ServedPLMNs-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { +{ ID id-TAISliceSupportList CRITICALITY ignore EXTENSION SliceSupportList PRESENCE optional }| +{ ID id-NPNSupportInfo CRITICALITY reject EXTENSION NPNSupportInfo PRESENCE optional }| +{ ID id-ExtendedTAISliceSupportList CRITICALITY reject EXTENSION ExtendedSliceSupportList PRESENCE optional }, + ... +} + +BroadcastCAGList ::= SEQUENCE (SIZE(1..maxnoofCAGsupported)) OF CAGID + +BroadcastNIDList ::= SEQUENCE (SIZE(1..maxnoofNIDsupported)) OF NID + +BroadcastSNPN-ID-List ::= SEQUENCE (SIZE(1..maxnoofNIDsupported)) OF BroadcastSNPN-ID-List-Item + +BroadcastSNPN-ID-List-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + broadcastNIDList BroadcastNIDList, + iE-Extensions ProtocolExtensionContainer { { BroadcastSNPN-ID-List-ItemExtIEs} } OPTIONAL, + ... +} + +BroadcastSNPN-ID-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BroadcastPNI-NPN-ID-List ::= SEQUENCE (SIZE(1..maxnoofCAGsupported)) OF BroadcastPNI-NPN-ID-List-Item + +BroadcastPNI-NPN-ID-List-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + broadcastCAGList BroadcastCAGList, + iE-Extensions ProtocolExtensionContainer { { BroadcastPNI-NPN-ID-List-ItemExtIEs} } OPTIONAL, + ... +} + +BroadcastPNI-NPN-ID-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} +BurstArrivalTime ::= OCTET STRING + +-- C +CAGID ::= BIT STRING (SIZE(32)) + +Cancel-all-Warning-Messages-Indicator ::= ENUMERATED {true, ...} + +Candidate-SpCell-Item ::= SEQUENCE { + candidate-SpCell-ID NRCGI , + iE-Extensions ProtocolExtensionContainer { { Candidate-SpCell-ItemExtIEs } } OPTIONAL, + ... +} + +Candidate-SpCell-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CapacityValue::= SEQUENCE { + capacityValue INTEGER (0..100), + sSBAreaCapacityValueList SSBAreaCapacityValueList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { CapacityValue-ExtIEs} } OPTIONAL +} + +CapacityValue-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cause ::= CHOICE { + radioNetwork CauseRadioNetwork, + transport CauseTransport, + protocol CauseProtocol, + misc CauseMisc, + choice-extension ProtocolIE-SingleContainer { { Cause-ExtIEs} } +} + +Cause-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +CauseMisc ::= ENUMERATED { + control-processing-overload, + not-enough-user-plane-processing-resources, + hardware-failure, + om-intervention, + unspecified, + ... +} + +CauseProtocol ::= ENUMERATED { + transfer-syntax-error, + abstract-syntax-error-reject, + abstract-syntax-error-ignore-and-notify, + message-not-compatible-with-receiver-state, + semantic-error, + abstract-syntax-error-falsely-constructed-message, + unspecified, + ... +} + +CauseRadioNetwork ::= ENUMERATED { + unspecified, + rl-failure-rlc, + unknown-or-already-allocated-gnb-cu-ue-f1ap-id, + unknown-or-already-allocated-gnb-du-ue-f1ap-id, + unknown-or-inconsistent-pair-of-ue-f1ap-id, + interaction-with-other-procedure, + not-supported-qci-Value, + action-desirable-for-radio-reasons, + no-radio-resources-available, + procedure-cancelled, + normal-release, + ..., + cell-not-available, + rl-failure-others, + ue-rejection, + resources-not-available-for-the-slice, + amf-initiated-abnormal-release, + release-due-to-pre-emption, + plmn-not-served-by-the-gNB-CU, + multiple-drb-id-instances, + unknown-drb-id, + multiple-bh-rlc-ch-id-instances, + unknown-bh-rlc-ch-id, + cho-cpc-resources-tobechanged, + nPN-not-supported, + nPN-access-denied, + gNB-CU-Cell-Capacity-Exceeded, + report-characteristics-empty, + existing-measurement-ID, + measurement-temporarily-not-available, + measurement-not-supported-for-the-object + +} + +CauseTransport ::= ENUMERATED { + unspecified, + transport-resource-unavailable, + ..., + unknown-TNL-address-for-IAB, + unknown-UP-TNL-information-for-IAB +} + +CellGroupConfig ::= OCTET STRING + +CellCapacityClassValue ::= INTEGER (1..100,...) + +Cell-Direction ::= ENUMERATED {dl-only, ul-only} + +CellMeasurementResultList ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF CellMeasurementResultItem + +CellMeasurementResultItem ::= SEQUENCE { + cellID NRCGI, + radioResourceStatus RadioResourceStatus OPTIONAL, + compositeAvailableCapacityGroup CompositeAvailableCapacityGroup OPTIONAL, + sliceAvailableCapacity SliceAvailableCapacity OPTIONAL, + numberofActiveUEs NumberofActiveUEs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { CellMeasurementResultItem-ExtIEs} } OPTIONAL +} + +CellMeasurementResultItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cell-Portion-ID ::= INTEGER (0..4095,...) + +Cells-Failed-to-be-Activated-List-Item ::= SEQUENCE { + nRCGI NRCGI, + cause Cause, + iE-Extensions ProtocolExtensionContainer { { Cells-Failed-to-be-Activated-List-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-Failed-to-be-Activated-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-Status-Item ::= SEQUENCE { + nRCGI NRCGI, + service-status Service-Status, + iE-Extensions ProtocolExtensionContainer { { Cells-Status-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-Status-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-To-Be-Broadcast-Item ::= SEQUENCE { + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { Cells-To-Be-Broadcast-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-To-Be-Broadcast-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-Broadcast-Completed-Item ::= SEQUENCE { + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { Cells-Broadcast-Completed-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-Broadcast-Completed-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Broadcast-To-Be-Cancelled-Item ::= SEQUENCE { + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { Broadcast-To-Be-Cancelled-ItemExtIEs } } OPTIONAL, + ... +} + +Broadcast-To-Be-Cancelled-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +Cells-Broadcast-Cancelled-Item ::= SEQUENCE { + nRCGI NRCGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { { Cells-Broadcast-Cancelled-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-Broadcast-Cancelled-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-to-be-Activated-List-Item ::= SEQUENCE { + nRCGI NRCGI, + nRPCI NRPCI OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Cells-to-be-Activated-List-ItemExtIEs} } OPTIONAL, + ... +} + +Cells-to-be-Activated-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-gNB-CUSystemInformation CRITICALITY reject EXTENSION GNB-CUSystemInformation PRESENCE optional }| + { ID id-AvailablePLMNList CRITICALITY ignore EXTENSION AvailablePLMNList PRESENCE optional }| + { ID id-ExtendedAvailablePLMN-List CRITICALITY ignore EXTENSION ExtendedAvailablePLMN-List PRESENCE optional }| + { ID id-IAB-Info-IAB-donor-CU CRITICALITY ignore EXTENSION IAB-Info-IAB-donor-CU PRESENCE optional}| + { ID id-AvailableSNPN-ID-List CRITICALITY ignore EXTENSION AvailableSNPN-ID-List PRESENCE optional }, + ... +} + +Cells-to-be-Deactivated-List-Item ::= SEQUENCE { + nRCGI NRCGI , + iE-Extensions ProtocolExtensionContainer { { Cells-to-be-Deactivated-List-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-to-be-Deactivated-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-to-be-Barred-Item::= SEQUENCE { + nRCGI NRCGI , + cellBarred CellBarred, + iE-Extensions ProtocolExtensionContainer { { Cells-to-be-Barred-Item-ExtIEs } } OPTIONAL +} + +Cells-to-be-Barred-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-IAB-Barred CRITICALITY ignore EXTENSION IAB-Barred PRESENCE optional }, + + ... +} + + +CellBarred ::= ENUMERATED {barred, not-barred, ...} + +CellSize ::= ENUMERATED {verysmall, small, medium, large, ...} + +CellToReportList ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF CellToReportItem + +CellToReportItem ::= SEQUENCE { + cellID NRCGI, + sSBToReportList SSBToReportList OPTIONAL, + sliceToReportList SliceToReportList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { CellToReportItem-ExtIEs} } OPTIONAL +} + +CellToReportItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CellType ::= SEQUENCE { + cellSize CellSize, + iE-Extensions ProtocolExtensionContainer { {CellType-ExtIEs} } OPTIONAL, + ... +} + +CellType-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CellULConfigured ::= ENUMERATED {none, ul, sul, ul-and-sul, ...} + +Child-Node-Cells-List ::= SEQUENCE (SIZE(1..maxnoofChildIABNodes)) OF Child-Node-Cells-List-Item + +Child-Node-Cells-List-Item ::= SEQUENCE{ + nRCGI NRCGI, + iAB-DU-Cell-Resource-Configuration-Mode-Info IAB-DU-Cell-Resource-Configuration-Mode-Info OPTIONAL, + iAB-STC-Info IAB-STC-Info OPTIONAL, + rACH-Config-Common RACH-Config-Common OPTIONAL, + rACH-Config-Common-IAB RACH-Config-Common-IAB OPTIONAL, + cSI-RS-Configuration OCTET STRING OPTIONAL, + sR-Configuration OCTET STRING OPTIONAL, + pDCCH-ConfigSIB1 OCTET STRING OPTIONAL, + sCS-Common OCTET STRING OPTIONAL, + multiplexingInfo MultiplexingInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer {{Child-Node-Cells-List-Item-ExtIEs}} OPTIONAL +} + +Child-Node-Cells-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Child-Nodes-List ::= SEQUENCE (SIZE(1..maxnoofChildIABNodes)) OF Child-Nodes-List-Item + +Child-Nodes-List-Item ::= SEQUENCE{ + gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID, + gNB-DU-UE-F1AP-ID GNB-DU-UE-F1AP-ID, + child-Node-Cells-List Child-Node-Cells-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer {{Child-Nodes-List-Item-ExtIEs}} OPTIONAL +} + +Child-Nodes-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CHOtrigger-InterDU ::= ENUMERATED { + cho-initiation, + cho-replace, + ... +} + +CHOtrigger-IntraDU ::= ENUMERATED { + cho-initiation, + cho-replace, + cho-cancel, + ... +} + +CNUEPagingIdentity ::= CHOICE { + fiveG-S-TMSI BIT STRING (SIZE(48)), + choice-extension ProtocolIE-SingleContainer { { CNUEPagingIdentity-ExtIEs } } +} + +CNUEPagingIdentity-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +CompositeAvailableCapacityGroup ::= SEQUENCE { + compositeAvailableCapacityDownlink CompositeAvailableCapacity, + compositeAvailableCapacityUplink CompositeAvailableCapacity, + iE-Extensions ProtocolExtensionContainer { { CompositeAvailableCapacityGroup-ExtIEs} } OPTIONAL +} + +CompositeAvailableCapacityGroup-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CompositeAvailableCapacity ::= SEQUENCE { + cellCapacityClassValue CellCapacityClassValue OPTIONAL, + capacityValue CapacityValue, + iE-Extensions ProtocolExtensionContainer { { CompositeAvailableCapacity-ExtIEs} } OPTIONAL +} + +CompositeAvailableCapacity-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ConditionalInterDUMobilityInformation ::= SEQUENCE { + cho-trigger CHOtrigger-InterDU, + targetgNB-DUUEF1APID GNB-DU-UE-F1AP-ID OPTIONAL + -- This IE shall be present if the cho-trigger IE is present and set to "cho-replace" --, + iE-Extensions ProtocolExtensionContainer { { ConditionalInterDUMobilityInformation-ExtIEs} } OPTIONAL, + ... +} + +ConditionalInterDUMobilityInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::={ + ... +} + +ConditionalIntraDUMobilityInformation ::= SEQUENCE { + cho-trigger CHOtrigger-IntraDU, + targetCellsTocancel TargetCellList OPTIONAL, + -- This IE may be present if the cho-trigger IE is present and set to "cho-cancel" + iE-Extensions ProtocolExtensionContainer { { ConditionalIntraDUMobilityInformation-ExtIEs} } OPTIONAL, + ... +} + +ConditionalIntraDUMobilityInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::={ + ... +} + +ConfiguredTACIndication ::= ENUMERATED { + true, + ... +} + + +CoordinateID ::= INTEGER (0..511, ...) + +CP-TransportLayerAddress ::= CHOICE { + endpoint-IP-address TransportLayerAddress, + endpoint-IP-address-and-port Endpoint-IP-address-and-port, + choice-extension ProtocolIE-SingleContainer { { CP-TransportLayerAddress-ExtIEs } } +} + +CP-TransportLayerAddress-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +CPTrafficType ::= INTEGER (1..3,...) + +CriticalityDiagnostics ::= SEQUENCE { + procedureCode ProcedureCode OPTIONAL, + triggeringMessage TriggeringMessage OPTIONAL, + procedureCriticality Criticality OPTIONAL, + transactionID TransactionID OPTIONAL, + iEsCriticalityDiagnostics CriticalityDiagnostics-IE-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer {{CriticalityDiagnostics-ExtIEs}} OPTIONAL, + ... +} + +CriticalityDiagnostics-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CriticalityDiagnostics-IE-List ::= SEQUENCE (SIZE (1.. maxnoofErrors)) OF CriticalityDiagnostics-IE-Item + +CriticalityDiagnostics-IE-Item ::= SEQUENCE { + iECriticality Criticality, + iE-ID ProtocolIE-ID, + typeOfError TypeOfError, + iE-Extensions ProtocolExtensionContainer {{CriticalityDiagnostics-IE-Item-ExtIEs}} OPTIONAL, + ... +} + +CriticalityDiagnostics-IE-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +C-RNTI ::= INTEGER (0..65535, ...) + +CUDURadioInformationType ::= CHOICE { + rIM CUDURIMInformation, + choice-extension ProtocolIE-SingleContainer { { CUDURadioInformationType-ExtIEs} } +} + +CUDURadioInformationType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +CUDURIMInformation ::= SEQUENCE { + victimgNBSetID GNBSetID, + rIMRSDetectionStatus RIMRSDetectionStatus, + iE-Extensions ProtocolExtensionContainer { { CUDURIMInformation-ExtIEs} } OPTIONAL +} + +CUDURIMInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CUtoDURRCInformation ::= SEQUENCE { + cG-ConfigInfo CG-ConfigInfo OPTIONAL, + uE-CapabilityRAT-ContainerList UE-CapabilityRAT-ContainerList OPTIONAL, + measConfig MeasConfig OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { CUtoDURRCInformation-ExtIEs} } OPTIONAL, + ... +} + +CUtoDURRCInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-HandoverPreparationInformation CRITICALITY ignore EXTENSION HandoverPreparationInformation PRESENCE optional }| + { ID id-CellGroupConfig CRITICALITY ignore EXTENSION CellGroupConfig PRESENCE optional }| + { ID id-MeasurementTimingConfiguration CRITICALITY ignore EXTENSION MeasurementTimingConfiguration PRESENCE optional }| + { ID id-UEAssistanceInformation CRITICALITY ignore EXTENSION UEAssistanceInformation PRESENCE optional }| + { ID id-CG-Config CRITICALITY ignore EXTENSION CG-Config PRESENCE optional }| + { ID id-UEAssistanceInformationEUTRA CRITICALITY ignore EXTENSION UEAssistanceInformationEUTRA PRESENCE optional }, + ... +} + +-- D + +DCBasedDuplicationConfigured::= ENUMERATED{true,..., false} + +Dedicated-SIDelivery-NeededUE-Item ::= SEQUENCE { + gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID, + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { DedicatedSIDeliveryNeededUE-Item-ExtIEs} } OPTIONAL, + ... +} + +DedicatedSIDeliveryNeededUE-Item-ExtIEs F1AP-PROTOCOL-EXTENSION::={ + ... +} + + +DL-PRS ::= SEQUENCE { + prsid INTEGER (0..255), + dl-PRSResourceSetID PRS-Resource-Set-ID, + dl-PRSResourceID PRS-Resource-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {DL-PRS-ExtIEs} } OPTIONAL +} + +DL-PRS-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DL-PRSMutingPattern ::= CHOICE { + two BIT STRING (SIZE(2)), + four BIT STRING (SIZE(4)), + six BIT STRING (SIZE(6)), + eight BIT STRING (SIZE(8)), + sixteen BIT STRING (SIZE(16)), + thirty-two BIT STRING (SIZE(32)), + choice-extension ProtocolIE-SingleContainer { { DL-PRSMutingPattern-ExtIEs } } +} + +DL-PRSMutingPattern-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +DLPRSResourceCoordinates ::= SEQUENCE { + listofDL-PRSResourceSetARP SEQUENCE (SIZE(1.. maxnoofPRS-ResourceSets)) OF DLPRSResourceSetARP, + iE-Extensions ProtocolExtensionContainer { { DLPRSResourceCoordinates-ExtIEs } } OPTIONAL +} + +DLPRSResourceCoordinates-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DLPRSResourceSetARP ::= SEQUENCE { + dl-PRSResourceSetID INTEGER (0..7), + dL-PRSResourceSetARPLocation DL-PRSResourceSetARPLocation, + listofDL-PRSResourceARP SEQUENCE (SIZE(1.. maxnoofPRS-ResourcesPerSet)) OF DLPRSResourceARP, + iE-Extensions ProtocolExtensionContainer { { DLPRSResourceSetARP-ExtIEs } } OPTIONAL +} + +DLPRSResourceSetARP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +DL-PRSResourceSetARPLocation ::= CHOICE { + relativeGeodeticLocation RelativeGeodeticLocation, + relativeCartesianLocation RelativeCartesianLocation, + choice-Extension ProtocolIE-SingleContainer { { DL-PRSResourceSetARPLocation-ExtIEs } } +} + +DL-PRSResourceSetARPLocation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +DLPRSResourceARP ::= SEQUENCE { + dl-PRSResourceID INTEGER (0..63), + dL-PRSResourceARPLocation DL-PRSResourceARPLocation, + iE-Extensions ProtocolExtensionContainer { { DLPRSResourceARP-ExtIEs } } OPTIONAL +} + +DLPRSResourceARP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DL-PRSResourceARPLocation ::= CHOICE { + relativeGeodeticLocation RelativeGeodeticLocation, + relativeCartesianLocation RelativeCartesianLocation, + choice-Extension ProtocolIE-SingleContainer { { DL-PRSResourceARPLocation-ExtIEs } } +} + +DL-PRSResourceARPLocation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +DL-UP-TNL-Address-to-Update-List-Item ::= SEQUENCE { + oldIPAdress TransportLayerAddress, + newIPAdress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { { DL-UP-TNL-Address-to-Update-List-ItemExtIEs } } OPTIONAL, + ... +} + +DL-UP-TNL-Address-to-Update-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DLUPTNLInformation-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofDLUPTNLInformation)) OF DLUPTNLInformation-ToBeSetup-Item + +DLUPTNLInformation-ToBeSetup-Item ::= SEQUENCE { + dLUPTNLInformation UPTransportLayerInformation , + iE-Extensions ProtocolExtensionContainer { { DLUPTNLInformation-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +DLUPTNLInformation-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRB-Activity-Item ::= SEQUENCE { + dRBID DRBID, + dRB-Activity DRB-Activity OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRB-Activity-ItemExtIEs } } OPTIONAL, + ... +} + +DRB-Activity-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRB-Activity ::= ENUMERATED {active, not-active} + +DRBID ::= INTEGER (1..32, ...) + +DRBs-FailedToBeModified-Item ::= SEQUENCE { + dRBID DRBID , + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-FailedToBeModified-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-FailedToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBs-FailedToBeSetup-Item ::= SEQUENCE { + dRBID DRBID, + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-FailedToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-FailedToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +DRBs-FailedToBeSetupMod-Item ::= SEQUENCE { + dRBID DRBID , + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { DRBs-FailedToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-FailedToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRB-Information ::= SEQUENCE { + dRB-QoS QoSFlowLevelQoSParameters, + sNSSAI SNSSAI, + notificationControl NotificationControl OPTIONAL, + flows-Mapped-To-DRB-List Flows-Mapped-To-DRB-List, + iE-Extensions ProtocolExtensionContainer { { DRB-Information-ItemExtIEs } } OPTIONAL +} + +DRB-Information-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBs-Modified-Item ::= SEQUENCE { + dRBID DRBID, + lCID LCID OPTIONAL, + dLUPTNLInformation-ToBeSetup-List DLUPTNLInformation-ToBeSetup-List, + iE-Extensions ProtocolExtensionContainer { { DRBs-Modified-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-Modified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-RLC-Status CRITICALITY ignore EXTENSION RLC-Status PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + +DRBs-ModifiedConf-Item ::= SEQUENCE { + dRBID DRBID, + uLUPTNLInformation-ToBeSetup-List ULUPTNLInformation-ToBeSetup-List , + iE-Extensions ProtocolExtensionContainer { { DRBs-ModifiedConf-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ModifiedConf-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + +DRB-Notify-Item ::= SEQUENCE { + dRBID DRBID, + notification-Cause Notification-Cause, + iE-Extensions ProtocolExtensionContainer { { DRB-Notify-ItemExtIEs } } OPTIONAL, + ... +} + +DRB-Notify-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-CurrentQoSParaSetIndex CRITICALITY ignore EXTENSION QoSParaSetNotifyIndex PRESENCE optional }, + ... +} + +DRBs-Required-ToBeModified-Item ::= SEQUENCE { + dRBID DRBID, + dLUPTNLInformation-ToBeSetup-List DLUPTNLInformation-ToBeSetup-List , + iE-Extensions ProtocolExtensionContainer { { DRBs-Required-ToBeModified-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-Required-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-RLC-Status CRITICALITY ignore EXTENSION RLC-Status PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + +DRBs-Required-ToBeReleased-Item ::= SEQUENCE { + dRBID DRBID, + iE-Extensions ProtocolExtensionContainer { { DRBs-Required-ToBeReleased-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-Required-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBs-Setup-Item ::= SEQUENCE { + dRBID DRBID, + lCID LCID OPTIONAL, + dLUPTNLInformation-ToBeSetup-List DLUPTNLInformation-ToBeSetup-List , + iE-Extensions ProtocolExtensionContainer { { DRBs-Setup-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-Setup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }| + { ID id-RLCDuplicationInformation CRITICALITY ignore EXTENSION RLCDuplicationInformation PRESENCE optional}, ... +} + +DRBs-SetupMod-Item ::= SEQUENCE { + dRBID DRBID, + lCID LCID OPTIONAL, + dLUPTNLInformation-ToBeSetup-List DLUPTNLInformation-ToBeSetup-List , + iE-Extensions ProtocolExtensionContainer { { DRBs-SetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-SetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + + +DRBs-ToBeModified-Item ::= SEQUENCE { + dRBID DRBID, + qoSInformation QoSInformation OPTIONAL, + uLUPTNLInformation-ToBeSetup-List ULUPTNLInformation-ToBeSetup-List , + uLConfiguration ULConfiguration OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-ToBeModified-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-DLPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + { ID id-ULPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + {ID id-BearerTypeChange CRITICALITY ignore EXTENSION BearerTypeChange PRESENCE optional}| + { ID id-RLCMode CRITICALITY ignore EXTENSION RLCMode PRESENCE optional }| + { ID id-Duplication-Activation CRITICALITY reject EXTENSION DuplicationActivation PRESENCE optional }| + { ID id-DC-Based-Duplication-Configured CRITICALITY reject EXTENSION DCBasedDuplicationConfigured PRESENCE optional }| + { ID id-DC-Based-Duplication-Activation CRITICALITY reject EXTENSION DuplicationActivation PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }| + { ID id-RLCDuplicationInformation CRITICALITY ignore EXTENSION RLCDuplicationInformation PRESENCE optional}, + ... +} + +DRBs-ToBeReleased-Item ::= SEQUENCE { + dRBID DRBID, + iE-Extensions ProtocolExtensionContainer { { DRBs-ToBeReleased-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBs-ToBeSetup-Item ::= SEQUENCE { + dRBID DRBID, + qoSInformation QoSInformation, + uLUPTNLInformation-ToBeSetup-List ULUPTNLInformation-ToBeSetup-List , + rLCMode RLCMode, + uLConfiguration ULConfiguration OPTIONAL, + duplicationActivation DuplicationActivation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-DC-Based-Duplication-Configured CRITICALITY reject EXTENSION DCBasedDuplicationConfigured PRESENCE optional }| + { ID id-DC-Based-Duplication-Activation CRITICALITY reject EXTENSION DuplicationActivation PRESENCE optional }| + { ID id-DLPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE mandatory }| + { ID id-ULPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + + +DRBs-ToBeSetupMod-Item ::= SEQUENCE { + dRBID DRBID, + qoSInformation QoSInformation, + uLUPTNLInformation-ToBeSetup-List ULUPTNLInformation-ToBeSetup-List, + rLCMode RLCMode, + uLConfiguration ULConfiguration OPTIONAL, + duplicationActivation DuplicationActivation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-ToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-DC-Based-Duplication-Configured CRITICALITY reject EXTENSION DCBasedDuplicationConfigured PRESENCE optional }| + { ID id-DC-Based-Duplication-Activation CRITICALITY reject EXTENSION DuplicationActivation PRESENCE optional }| + { ID id-DLPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + { ID id-ULPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }| + { ID id-RLCDuplicationInformation CRITICALITY ignore EXTENSION RLCDuplicationInformation PRESENCE optional}, + ... +} + +DRXCycle ::= SEQUENCE { + longDRXCycleLength LongDRXCycleLength, + shortDRXCycleLength ShortDRXCycleLength OPTIONAL, + shortDRXCycleTimer ShortDRXCycleTimer OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRXCycle-ExtIEs} } OPTIONAL, + ... +} + +DRXCycle-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRX-Config ::= OCTET STRING + +DRXConfigurationIndicator ::= ENUMERATED{ release, ...} + +DRX-LongCycleStartOffset ::= INTEGER (0..10239) + +DSInformationList ::= SEQUENCE (SIZE(0..maxnoofDSInfo)) OF DSCP + +DSCP ::= BIT STRING (SIZE (6)) + +DUtoCURRCContainer ::= OCTET STRING + +DUCURadioInformationType ::= CHOICE { + rIM DUCURIMInformation, + choice-extension ProtocolIE-SingleContainer { { DUCURadioInformationType-ExtIEs} } +} + +DUCURadioInformationType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +DUCURIMInformation ::= SEQUENCE { + victimgNBSetID GNBSetID, + rIMRSDetectionStatus RIMRSDetectionStatus, + aggressorCellList AggressorCellList, + iE-Extensions ProtocolExtensionContainer { { DUCURIMInformation-ExtIEs} } OPTIONAL +} + +DUCURIMInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DUF-Slot-Config-Item ::= CHOICE { + explicitFormat ExplicitFormat, + implicitFormat ImplicitFormat, + choice-extension ProtocolIE-SingleContainer { { DUF-Slot-Config-Item-ExtIEs} } +} + +DUF-Slot-Config-Item-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} +DUF-Slot-Config-List ::= SEQUENCE (SIZE(1..maxnoofDUFSlots)) OF DUF-Slot-Config-Item + +DUFSlotformatIndex ::= INTEGER(0..254) + +DUFTransmissionPeriodicity ::= ENUMERATED { ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms5, ms10, ...} + +DU-RX-MT-RX ::= ENUMERATED {supported, not-supported} + +DU-TX-MT-TX ::= ENUMERATED {supported, not-supported} + +DU-RX-MT-TX ::= ENUMERATED {supported, not-supported} + +DU-TX-MT-RX ::= ENUMERATED {supported, not-supported} + +DUtoCURRCInformation ::= SEQUENCE { + cellGroupConfig CellGroupConfig, + measGapConfig MeasGapConfig OPTIONAL, + requestedP-MaxFR1 OCTET STRING OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DUtoCURRCInformation-ExtIEs} } OPTIONAL, + ... +} + +DUtoCURRCInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-DRX-LongCycleStartOffset CRITICALITY ignore EXTENSION DRX-LongCycleStartOffset PRESENCE optional }| + { ID id-SelectedBandCombinationIndex CRITICALITY ignore EXTENSION SelectedBandCombinationIndex PRESENCE optional }| + { ID id-SelectedFeatureSetEntryIndex CRITICALITY ignore EXTENSION SelectedFeatureSetEntryIndex PRESENCE optional }| + { ID id-Ph-InfoSCG CRITICALITY ignore EXTENSION Ph-InfoSCG PRESENCE optional }| + { ID id-RequestedBandCombinationIndex CRITICALITY ignore EXTENSION RequestedBandCombinationIndex PRESENCE optional }| + { ID id-RequestedFeatureSetEntryIndex CRITICALITY ignore EXTENSION RequestedFeatureSetEntryIndex PRESENCE optional }| + { ID id-DRX-Config CRITICALITY ignore EXTENSION DRX-Config PRESENCE optional }| + { ID id-PDCCH-BlindDetectionSCG CRITICALITY ignore EXTENSION PDCCH-BlindDetectionSCG PRESENCE optional }| + { ID id-Requested-PDCCH-BlindDetectionSCG CRITICALITY ignore EXTENSION Requested-PDCCH-BlindDetectionSCG PRESENCE optional }| + { ID id-Ph-InfoMCG CRITICALITY ignore EXTENSION Ph-InfoMCG PRESENCE optional }| + { ID id-MeasGapSharingConfig CRITICALITY ignore EXTENSION MeasGapSharingConfig PRESENCE optional }| + { ID id-SL-PHY-MAC-RLC-Config CRITICALITY ignore EXTENSION SL-PHY-MAC-RLC-Config PRESENCE optional }| + { ID id-SL-ConfigDedicatedEUTRA CRITICALITY ignore EXTENSION SL-ConfigDedicatedEUTRA PRESENCE optional }| + { ID id-RequestedP-MaxFR2 CRITICALITY ignore EXTENSION RequestedP-MaxFR2 PRESENCE optional }, + ... +} + +DuplicationActivation ::= ENUMERATED{active,inactive,... } + +DuplicationIndication ::= ENUMERATED {true, ... , false } + +DuplicationState ::= ENUMERATED { + active, + inactive, + ... +} + +Dynamic5QIDescriptor ::= SEQUENCE { + qoSPriorityLevel INTEGER (1..127), + packetDelayBudget PacketDelayBudget, + packetErrorRate PacketErrorRate, + fiveQI INTEGER (0..255, ...) OPTIONAL, + delayCritical ENUMERATED {delay-critical, non-delay-critical} OPTIONAL, + -- C-ifGBRflow: This IE shall be present if the GBR QoS Flow Information IE is present in the QoS Flow Level QoS Parameters IE. + averagingWindow AveragingWindow OPTIONAL, + -- C-ifGBRflow: This IE shall be present if the GBR QoS Flow Information IE is present in the QoS Flow Level QoS Parameters IE. + maxDataBurstVolume MaxDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Dynamic5QIDescriptor-ExtIEs } } OPTIONAL +} + +Dynamic5QIDescriptor-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ExtendedPacketDelayBudget CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }| + { ID id-CNPacketDelayBudgetDownlink CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }| + { ID id-CNPacketDelayBudgetUplink CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }, + ... +} + +DynamicPQIDescriptor ::= SEQUENCE { + resourceType ENUMERATED {gbr, non-gbr, delay-critical-grb, ...} OPTIONAL, + qoSPriorityLevel INTEGER (1..8, ...), + packetDelayBudget PacketDelayBudget, + packetErrorRate PacketErrorRate, + averagingWindow AveragingWindow OPTIONAL, + -- C-ifGBRflow: This IE shall be present if the GBR QoS Flow Information IE is present in the QoS Flow Level QoS Parameters IE. + maxDataBurstVolume MaxDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DynamicPQIDescriptor-ExtIEs } } OPTIONAL +} + +DynamicPQIDescriptor-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- E + +E-CID-MeasurementPeriodicity ::= ENUMERATED { + ms120, + ms240, + ms480, + ms640, + ms1024, + ms2048, + ms5120, + ms10240, + min1, + min6, + min12, + min30, + min60, + ... +} + +E-CID-MeasurementQuantities ::= SEQUENCE (SIZE (1.. maxnoofMeasE-CID)) OF ProtocolIE-SingleContainer { {E-CID-MeasurementQuantities-ItemIEs} } + +E-CID-MeasurementQuantities-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-E-CID-MeasurementQuantities-Item CRITICALITY reject TYPE E-CID-MeasurementQuantities-Item PRESENCE mandatory} +} + +E-CID-MeasurementQuantities-Item ::= SEQUENCE { + e-CIDmeasurementQuantitiesValue E-CID-MeasurementQuantitiesValue, + iE-Extensions ProtocolExtensionContainer { { E-CID-MeasurementQuantitiesValue-ExtIEs} } OPTIONAL +} + +E-CID-MeasurementQuantitiesValue-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +E-CID-MeasurementQuantitiesValue ::= ENUMERATED { + cell-Portion, + angleOfArrivalNR, + ... +} + +E-CID-MeasurementResult ::= SEQUENCE { + geographicalCoordinates GeographicalCoordinates OPTIONAL, + measuredResults-List E-CID-MeasuredResults-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { E-CID-MeasurementResult-ExtIEs} } OPTIONAL +} + +E-CID-MeasurementResult-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +E-CID-MeasuredResults-List ::= SEQUENCE (SIZE(1..maxnoofMeasE-CID)) OF E-CID-MeasuredResults-Item + +E-CID-MeasuredResults-Item ::= SEQUENCE { + e-CID-MeasuredResults-Value E-CID-MeasuredResults-Value, + iE-Extensions ProtocolExtensionContainer {{ E-CID-MeasuredResults-Item-ExtIEs }} OPTIONAL +} + +E-CID-MeasuredResults-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +E-CID-MeasuredResults-Value ::= CHOICE { + valueAngleofArrivalNR UL-AoA, + choice-extension ProtocolIE-SingleContainer { { E-CID-MeasuredResults-Value-ExtIEs} } +} + +E-CID-MeasuredResults-Value-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +E-CID-ReportCharacteristics ::= ENUMERATED { + onDemand, + periodic, + ... +} + +EgressBHRLCCHList ::= SEQUENCE (SIZE(1..maxnoofEgressLinks)) OF EgressBHRLCCHItem + +EgressBHRLCCHItem ::= SEQUENCE { + nextHopBAPAddress BAPAddress, + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer {{EgressBHRLCCHItemExtIEs }} OPTIONAL +} + +EgressBHRLCCHItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Endpoint-IP-address-and-port ::=SEQUENCE { + endpointIPAddress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { { Endpoint-IP-address-and-port-ExtIEs} } OPTIONAL +} + +Endpoint-IP-address-and-port-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-portNumber CRITICALITY reject EXTENSION PortNumber PRESENCE optional}, + ... +} + +ExtendedAvailablePLMN-List ::= SEQUENCE (SIZE(1..maxnoofExtendedBPLMNs)) OF ExtendedAvailablePLMN-Item + +ExtendedAvailablePLMN-Item ::= SEQUENCE { + pLMNIdentity PLMN-Identity, + iE-Extensions ProtocolExtensionContainer { { ExtendedAvailablePLMN-Item-ExtIEs} } OPTIONAL +} + +ExplicitFormat ::= SEQUENCE { + permutation Permutation, + noofDownlinkSymbols NoofDownlinkSymbols OPTIONAL, + noofUplinkSymbols NoofUplinkSymbols OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { ExplicitFormat-ExtIEs} } OPTIONAL +} + +ExplicitFormat-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ExtendedAvailablePLMN-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ExtendedServedPLMNs-List ::= SEQUENCE (SIZE(1.. maxnoofExtendedBPLMNs)) OF ExtendedServedPLMNs-Item + +ExtendedServedPLMNs-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + tAISliceSupportList SliceSupportList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { ExtendedServedPLMNs-ItemExtIEs} } OPTIONAL, + ... +} + +ExtendedServedPLMNs-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-NPNSupportInfo CRITICALITY reject EXTENSION NPNSupportInfo PRESENCE optional }| +{ ID id-ExtendedTAISliceSupportList CRITICALITY reject EXTENSION ExtendedSliceSupportList PRESENCE optional }, + ... +} + +ExtendedSliceSupportList ::= SEQUENCE (SIZE(1.. maxnoofExtSliceItems)) OF SliceSupportItem + +EUTRACells-List ::= SEQUENCE (SIZE (1.. maxCellineNB)) OF EUTRACells-List-item + +EUTRACells-List-item ::= SEQUENCE { + eUTRA-Cell-ID EUTRA-Cell-ID, + served-EUTRA-Cells-Information Served-EUTRA-Cells-Information, + iE-Extensions ProtocolExtensionContainer { { EUTRACells-List-itemExtIEs } } OPTIONAL +} + +EUTRACells-List-itemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +EUTRA-Cell-ID ::= BIT STRING (SIZE(28)) + +EUTRA-Coex-FDD-Info ::= SEQUENCE { + uL-EARFCN ExtendedEARFCN OPTIONAL, + dL-EARFCN ExtendedEARFCN, + uL-Transmission-Bandwidth EUTRA-Transmission-Bandwidth OPTIONAL, + dL-Transmission-Bandwidth EUTRA-Transmission-Bandwidth, + iE-Extensions ProtocolExtensionContainer { {EUTRA-Coex-FDD-Info-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-Coex-FDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ULCarrierList CRITICALITY ignore EXTENSION NRCarrierList PRESENCE optional }| + { ID id-DLCarrierList CRITICALITY ignore EXTENSION NRCarrierList PRESENCE optional }, + ... +} + +EUTRA-Coex-Mode-Info ::= CHOICE { + fDD EUTRA-Coex-FDD-Info, + tDD EUTRA-Coex-TDD-Info, + ... +} + +EUTRA-Coex-TDD-Info ::= SEQUENCE { + eARFCN ExtendedEARFCN, + transmission-Bandwidth EUTRA-Transmission-Bandwidth, + subframeAssignment EUTRA-SubframeAssignment, + specialSubframe-Info EUTRA-SpecialSubframe-Info, + iE-Extensions ProtocolExtensionContainer { {EUTRA-Coex-TDD-Info-ExtIEs} } OPTIONAL, + ... +} +EUTRA-Coex-TDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} +EUTRA-CyclicPrefixDL ::= ENUMERATED { + normal, + extended, + ... +} + +EUTRA-CyclicPrefixUL ::= ENUMERATED { + normal, + extended, + ... +} + +EUTRA-PRACH-Configuration ::= SEQUENCE { + rootSequenceIndex INTEGER (0..837), + zeroCorrelationIndex INTEGER (0..15), + highSpeedFlag BOOLEAN, + prach-FreqOffset INTEGER (0..94), + prach-ConfigIndex INTEGER (0..63) OPTIONAL, + -- C-ifTDD: This IE shall be present if the EUTRA-Mode-Info IE in the Resource Coordination E-UTRA Cell Information IE is set to the value "TDD" + iE-Extensions ProtocolExtensionContainer { {EUTRA-PRACH-Configuration-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-PRACH-Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +EUTRA-SpecialSubframe-Info ::= SEQUENCE { + specialSubframePatterns EUTRA-SpecialSubframePatterns, + cyclicPrefixDL EUTRA-CyclicPrefixDL, + cyclicPrefixUL EUTRA-CyclicPrefixUL, + iE-Extensions ProtocolExtensionContainer { { EUTRA-SpecialSubframe-Info-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-SpecialSubframe-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +EUTRA-SpecialSubframePatterns ::= ENUMERATED { + ssp0, + ssp1, + ssp2, + ssp3, + ssp4, + ssp5, + ssp6, + ssp7, + ssp8, + ssp9, + ssp10, + ... +} + +EUTRA-SubframeAssignment ::= ENUMERATED { + sa0, + sa1, + sa2, + sa3, + sa4, + sa5, + sa6, + ... +} + +EUTRA-Transmission-Bandwidth ::= ENUMERATED { + bw6, + bw15, + bw25, + bw50, + bw75, + bw100, + ... +} + +EUTRANQoS ::= SEQUENCE { + qCI QCI, + allocationAndRetentionPriority AllocationAndRetentionPriority, + gbrQosInformation GBR-QosInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { EUTRANQoS-ExtIEs} } OPTIONAL, + ... +} + +EUTRANQoS-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ExecuteDuplication ::= ENUMERATED{true,...} + +ExtendedEARFCN ::= INTEGER (0..262143) + +EUTRA-Mode-Info ::= CHOICE { + eUTRAFDD EUTRA-FDD-Info, + eUTRATDD EUTRA-TDD-Info, + choice-extension ProtocolIE-SingleContainer { { EUTRA-Mode-Info-ExtIEs} } +} + +EUTRA-Mode-Info-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +EUTRA-NR-CellResourceCoordinationReq-Container ::= OCTET STRING + +EUTRA-NR-CellResourceCoordinationReqAck-Container ::= OCTET STRING + +EUTRA-FDD-Info ::= SEQUENCE { + uL-offsetToPointA OffsetToPointA, + dL-offsetToPointA OffsetToPointA, + iE-Extensions ProtocolExtensionContainer { {EUTRA-FDD-Info-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-FDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +EUTRA-TDD-Info ::= SEQUENCE { + offsetToPointA OffsetToPointA, + iE-Extensions ProtocolExtensionContainer { {EUTRA-TDD-Info-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-TDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +EventType ::= ENUMERATED { + on-demand, + periodic, + stop, + ... +} + +ExtendedPacketDelayBudget ::= INTEGER (1..65535, ...) + +-- F + +FDD-Info ::= SEQUENCE { + uL-NRFreqInfo NRFreqInfo, + dL-NRFreqInfo NRFreqInfo, + uL-Transmission-Bandwidth Transmission-Bandwidth, + dL-Transmission-Bandwidth Transmission-Bandwidth, + iE-Extensions ProtocolExtensionContainer { {FDD-Info-ExtIEs} } OPTIONAL, + ... +} + +FDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +Flows-Mapped-To-DRB-List ::= SEQUENCE (SIZE(1.. maxnoofQoSFlows)) OF Flows-Mapped-To-DRB-Item + +Flows-Mapped-To-DRB-Item ::= SEQUENCE { + qoSFlowIdentifier QoSFlowIdentifier, + qoSFlowLevelQoSParameters QoSFlowLevelQoSParameters, + iE-Extensions ProtocolExtensionContainer { { Flows-Mapped-To-DRB-ItemExtIEs} } OPTIONAL +} + +Flows-Mapped-To-DRB-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-QoSFlowMappingIndication CRITICALITY ignore EXTENSION QoSFlowMappingIndication PRESENCE optional}| + {ID id-TSCTrafficCharacteristics CRITICALITY ignore EXTENSION TSCTrafficCharacteristics PRESENCE optional}, + ... +} + +FR1-Bandwidth ::= ENUMERATED {bw5, bw10, bw20, bw40, bw50, bw80, bw100, ...} + +FR2-Bandwidth ::= ENUMERATED {bw50, bw100, bw200, bw400, ...} + +FreqBandNrItem ::= SEQUENCE { + freqBandIndicatorNr INTEGER (1..1024,...), + supportedSULBandList SEQUENCE (SIZE(0..maxnoofNrCellBands)) OF SupportedSULFreqBandItem, + iE-Extensions ProtocolExtensionContainer { {FreqBandNrItem-ExtIEs} } OPTIONAL, + ... +} + +FreqBandNrItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +FreqDomainLength ::= CHOICE { + l839 L839Info, + l139 L139Info, + choice-extension ProtocolIE-SingleContainer { {FreqDomainLength-ExtIEs} } +} + +FreqDomainLength-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +FrequencyShift7p5khz ::= ENUMERATED {false, true, ...} + +FullConfiguration ::= ENUMERATED {full, ...} + +FlowsMappedToSLDRB-List ::= SEQUENCE (SIZE(1.. maxnoofPC5QoSFlows)) OF FlowsMappedToSLDRB-Item + +FlowsMappedToSLDRB-Item ::= SEQUENCE { + pc5QoSFlowIdentifier PC5QoSFlowIdentifier, + iE-Extensions ProtocolExtensionContainer { {FlowsMappedToSLDRB-Item-ExtIEs} } OPTIONAL, + ... +} + +FlowsMappedToSLDRB-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- G + + +GBR-QosInformation ::= SEQUENCE { + e-RAB-MaximumBitrateDL BitRate, + e-RAB-MaximumBitrateUL BitRate, + e-RAB-GuaranteedBitrateDL BitRate, + e-RAB-GuaranteedBitrateUL BitRate, + iE-Extensions ProtocolExtensionContainer { { GBR-QosInformation-ExtIEs} } OPTIONAL, + ... +} + +GBR-QosInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GBR-QoSFlowInformation::= SEQUENCE { + maxFlowBitRateDownlink BitRate, + maxFlowBitRateUplink BitRate, + guaranteedFlowBitRateDownlink BitRate, + guaranteedFlowBitRateUplink BitRate, + maxPacketLossRateDownlink MaxPacketLossRate OPTIONAL, + maxPacketLossRateUplink MaxPacketLossRate OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GBR-QosFlowInformation-ExtIEs} } OPTIONAL, + ... +} + +GBR-QosFlowInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AlternativeQoSParaSetList CRITICALITY ignore EXTENSION AlternativeQoSParaSetList PRESENCE optional }, + ... +} + +CG-Config ::= OCTET STRING + +GeographicalCoordinates ::= SEQUENCE { + tRPPositionDefinitionType TRPPositionDefinitionType, + dLPRSResourceCoordinates DLPRSResourceCoordinates OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GeographicalCoordinates-ExtIEs } } OPTIONAL +} + +GeographicalCoordinates-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNBCUMeasurementID ::= INTEGER (0.. 4095, ...) + +GNBDUMeasurementID ::= INTEGER (0.. 4095, ...) + +GNB-CUSystemInformation::= SEQUENCE { + sibtypetobeupdatedlist SEQUENCE (SIZE(1.. maxnoofSIBTypes)) OF SibtypetobeupdatedListItem, + iE-Extensions ProtocolExtensionContainer { { GNB-CUSystemInformation-ExtIEs} } OPTIONAL, + ... +} + +GNB-CUSystemInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-systemInformationAreaID CRITICALITY ignore EXTENSION SystemInformationAreaID PRESENCE optional}, + ... +} + +GNB-CU-TNL-Association-Setup-Item::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-Setup-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-Setup-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-CU-TNL-Association-Failed-To-Setup-Item ::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + cause Cause, + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-Failed-To-Setup-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-Failed-To-Setup-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +GNB-CU-TNL-Association-To-Add-Item ::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + tNLAssociationUsage TNLAssociationUsage, + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-To-Add-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-To-Add-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-CU-TNL-Association-To-Remove-Item::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-To-Remove-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-To-Remove-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-TNLAssociationTransportLayerAddressgNBDU CRITICALITY reject EXTENSION CP-TransportLayerAddress PRESENCE optional}, + ... +} + + +GNB-CU-TNL-Association-To-Update-Item::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + tNLAssociationUsage TNLAssociationUsage OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-To-Update-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-To-Update-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-CU-UE-F1AP-ID ::= INTEGER (0..4294967295) + +GNB-DU-Cell-Resource-Configuration ::= SEQUENCE { + subcarrierSpacing SubcarrierSpacing, + dUFTransmissionPeriodicity DUFTransmissionPeriodicity OPTIONAL, + dUF-Slot-Config-List DUF-Slot-Config-List OPTIONAL, + hSNATransmissionPeriodicity HSNATransmissionPeriodicity, + hNSASlotConfigList HSNASlotConfigList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-DU-Cell-Resource-Configuration-ExtIEs } } OPTIONAL +} + +GNB-DU-Cell-Resource-Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-DU-UE-F1AP-ID ::= INTEGER (0..4294967295) + +GNB-DU-ID ::= INTEGER (0..68719476735) + +GNB-CU-Name ::= PrintableString(SIZE(1..150,...)) + +GNB-DU-Name ::= PrintableString(SIZE(1..150,...)) + +Extended-GNB-CU-Name ::= SEQUENCE { + gNB-CU-NameVisibleString GNB-CU-NameVisibleString OPTIONAL, + gNB-CU-NameUTF8String GNB-CU-NameUTF8String OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Extended-GNB-CU-Name-ExtIEs } } OPTIONAL, + ... +} + +Extended-GNB-CU-Name-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-CU-NameVisibleString ::= VisibleString(SIZE(1..150,...)) + +GNB-CU-NameUTF8String ::= UTF8String(SIZE(1..150,...)) + +Extended-GNB-DU-Name ::= SEQUENCE { + gNB-DU-NameVisibleString GNB-DU-NameVisibleString OPTIONAL, + gNB-DU-NameUTF8String GNB-DU-NameUTF8String OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Extended-GNB-DU-Name-ExtIEs } } OPTIONAL, + ... +} + +Extended-GNB-DU-Name-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-DU-NameVisibleString ::= VisibleString(SIZE(1..150,...)) + +GNB-DU-NameUTF8String ::= UTF8String(SIZE(1..150,...)) + + +GNB-DU-Served-Cells-Item ::= SEQUENCE { + served-Cell-Information Served-Cell-Information, + gNB-DU-System-Information GNB-DU-System-Information OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-DU-Served-Cells-ItemExtIEs} } OPTIONAL, + ... +} + +GNB-DU-Served-Cells-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-DU-System-Information ::= SEQUENCE { + mIB-message MIB-message, + sIB1-message SIB1-message, + iE-Extensions ProtocolExtensionContainer { { GNB-DU-System-Information-ExtIEs } } OPTIONAL, + ... +} + +GNB-DU-System-Information-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-SIB12-message CRITICALITY ignore EXTENSION SIB12-message PRESENCE optional}| + { ID id-SIB13-message CRITICALITY ignore EXTENSION SIB13-message PRESENCE optional}| + { ID id-SIB14-message CRITICALITY ignore EXTENSION SIB14-message PRESENCE optional}| + { ID id-SIB10-message CRITICALITY ignore EXTENSION SIB10-message PRESENCE optional}, + ... +} + +GNB-DUConfigurationQuery ::= ENUMERATED {true, ...} + +GNBDUOverloadInformation ::= ENUMERATED {overloaded, not-overloaded} + +GNB-DU-TNL-Association-To-Remove-Item::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + tNLAssociationTransportLayerAddressgNBCU CP-TransportLayerAddress OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-DU-TNL-Association-To-Remove-Item-ExtIEs} } OPTIONAL +} + +GNB-DU-TNL-Association-To-Remove-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-RxTxTimeDiff ::= SEQUENCE { + rxTxTimeDiff GNBRxTxTimeDiffMeas, + additionalPath-List AdditionalPath-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-RxTxTimeDiff-ExtIEs} } OPTIONAL +} + +GNB-RxTxTimeDiff-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + + ... +} + +GNBRxTxTimeDiffMeas ::= CHOICE { + k0 INTEGER (0.. 1970049), + k1 INTEGER (0.. 985025), + k2 INTEGER (0.. 492513), + k3 INTEGER (0.. 246257), + k4 INTEGER (0.. 123129), + k5 INTEGER (0.. 61565), + choice-extension ProtocolIE-SingleContainer { { GNBRxTxTimeDiffMeas-ExtIEs } } +} + +GNBRxTxTimeDiffMeas-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +GNBSetID ::= BIT STRING (SIZE(22)) + +GTP-TEID ::= OCTET STRING (SIZE (4)) + +GTPTLAs ::= SEQUENCE (SIZE(1.. maxnoofGTPTLAs)) OF GTPTLA-Item + + +GTPTLA-Item ::= SEQUENCE { + gTPTransportLayerAddress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { { GTPTLA-Item-ExtIEs } } OPTIONAL +} + +GTPTLA-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GTPTunnel ::= SEQUENCE { + transportLayerAddress TransportLayerAddress, + gTP-TEID GTP-TEID, + iE-Extensions ProtocolExtensionContainer { { GTPTunnel-ExtIEs } } OPTIONAL, + ... +} + +GTPTunnel-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- H + +HandoverPreparationInformation ::= OCTET STRING + +HardwareLoadIndicator ::= SEQUENCE { + dLHardwareLoadIndicator INTEGER (0..100, ...), + uLHardwareLoadIndicator INTEGER (0..100, ...), + iE-Extensions ProtocolExtensionContainer { { HardwareLoadIndicator-ExtIEs } } OPTIONAL, + ... +} + +HardwareLoadIndicator-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +HSNASlotConfigList ::= SEQUENCE (SIZE(1..maxnoofHSNASlots)) OF HSNASlotConfigItem + +HSNASlotConfigItem ::= SEQUENCE { + hSNADownlink HSNADownlink OPTIONAL, + hSNAUplink HSNAUplink OPTIONAL, + hSNAFlexible HSNAFlexible OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { HSNASlotConfigItem-ExtIEs } } OPTIONAL +} + +HSNASlotConfigItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} +HSNADownlink ::= ENUMERATED { hard, soft, notavailable } + +HSNAFlexible ::= ENUMERATED { hard, soft, notavailable } + +HSNAUplink ::= ENUMERATED { hard, soft, notavailable } + +HSNATransmissionPeriodicity ::= ENUMERATED { ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms5, ms10, ms20, ms40, ms80, ms160, ...} + +-- I + +IAB-Barred ::= ENUMERATED {barred, not-barred, ...} + +IAB-Info-IAB-donor-CU ::= SEQUENCE{ + iAB-STC-Info IAB-STC-Info OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IAB-Info-IAB-donor-CU-ExtIEs } } OPTIONAL +} + +IAB-Info-IAB-donor-CU-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-Info-IAB-DU ::= SEQUENCE{ + multiplexingInfo MultiplexingInfo OPTIONAL, + iAB-STC-Info IAB-STC-Info OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IAB-Info-IAB-DU-ExtIEs } } OPTIONAL +} + +IAB-Info-IAB-DU-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-MT-Cell-List ::= SEQUENCE (SIZE(1..maxnoofServingCells)) OF IAB-MT-Cell-List-Item + +IAB-MT-Cell-List-Item ::= SEQUENCE { + nRCellIdentity NRCellIdentity, + dU-RX-MT-RX DU-RX-MT-RX, + dU-TX-MT-TX DU-TX-MT-TX, + dU-RX-MT-TX DU-RX-MT-TX, + dU-TX-MT-RX DU-TX-MT-RX, + iE-Extensions ProtocolExtensionContainer { { IAB-MT-Cell-List-Item-ExtIEs } } OPTIONAL +} + +IAB-MT-Cell-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-STC-Info ::= SEQUENCE{ + iAB-STC-Info-List IAB-STC-Info-List, + iE-Extensions ProtocolExtensionContainer { { IAB-STC-Info-ExtIEs } } OPTIONAL +} + +IAB-STC-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-STC-Info-List ::= SEQUENCE (SIZE(1..maxnoofIABSTCInfo)) OF IAB-STC-Info-Item + +IAB-STC-Info-Item::= SEQUENCE { + sSB-freqInfo SSB-freqInfo, + sSB-subcarrierSpacing SSB-subcarrierSpacing, + sSB-transmissionPeriodicity SSB-transmissionPeriodicity, + sSB-transmissionTimingOffset SSB-transmissionTimingOffset, + sSB-transmissionBitmap SSB-transmissionBitmap, + iE-Extensions ProtocolExtensionContainer { { IAB-STC-Info-Item-ExtIEs } } OPTIONAL +} + +IAB-STC-Info-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-Allocated-TNL-Address-Item ::= SEQUENCE { + iABTNLAddress IABTNLAddress, + iABTNLAddressUsage IABTNLAddressUsage OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IAB-Allocated-TNL-Address-Item-ExtIEs } } OPTIONAL +} + +IAB-Allocated-TNL-Address-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-DU-Cell-Resource-Configuration-Mode-Info ::= CHOICE { + fDD IAB-DU-Cell-Resource-Configuration-FDD-Info, + tDD IAB-DU-Cell-Resource-Configuration-TDD-Info, + choice-extension ProtocolIE-SingleContainer { { IAB-DU-Cell-Resource-Configuration-Mode-Info-ExtIEs} } +} + +IAB-DU-Cell-Resource-Configuration-Mode-Info-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +IAB-DU-Cell-Resource-Configuration-FDD-Info ::= SEQUENCE { + gNB-DU-Cell-Resource-Configuration-FDD-UL GNB-DU-Cell-Resource-Configuration, + gNB-DU-Cell-Resource-Configuration-FDD-DL GNB-DU-Cell-Resource-Configuration, + iE-Extensions ProtocolExtensionContainer { {IAB-DU-Cell-Resource-Configuration-FDD-Info-ExtIEs} } OPTIONAL, + ... +} + +IAB-DU-Cell-Resource-Configuration-FDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-DU-Cell-Resource-Configuration-TDD-Info ::= SEQUENCE { + gNB-DU-Cell-Resourc-Configuration-TDD GNB-DU-Cell-Resource-Configuration, + iE-Extensions ProtocolExtensionContainer { {IAB-DU-Cell-Resource-Configuration-TDD-Info-ExtIEs} } OPTIONAL, + ... +} + +IAB-DU-Cell-Resource-Configuration-TDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IABIPv6RequestType ::= CHOICE { + iPv6Address IABTNLAddressesRequested, + iPv6Prefix IABTNLAddressesRequested, + choice-extension ProtocolIE-SingleContainer { { IABIPv6RequestType-ExtIEs} } +} + +IABIPv6RequestType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +IABTNLAddress ::= CHOICE { + iPv4Address BIT STRING (SIZE(32)), + iPv6Address BIT STRING (SIZE(128)), + iPv6Prefix BIT STRING (SIZE(64)), + choice-extension ProtocolIE-SingleContainer { { IABTNLAddress-ExtIEs} } +} + +IABTNLAddress-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +IABTNLAddressesRequested ::= SEQUENCE { + tNLAddressesOrPrefixesRequestedAllTraffic INTEGER (1..256) OPTIONAL, + tNLAddressesOrPrefixesRequestedF1-C INTEGER (1..256) OPTIONAL, + tNLAddressesOrPrefixesRequestedF1-U INTEGER (1..256) OPTIONAL, + tNLAddressesOrPrefixesRequestedNoNF1 INTEGER (1..256) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IABTNLAddressesRequested-ExtIEs } } OPTIONAL +} + +IABTNLAddressesRequested-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-TNL-Addresses-To-Remove-Item ::= SEQUENCE { + iABTNLAddress IABTNLAddress, + iE-Extensions ProtocolExtensionContainer { { IAB-TNL-Addresses-To-Remove-Item-ExtIEs} } OPTIONAL +} + +IAB-TNL-Addresses-To-Remove-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IABTNLAddressUsage ::= ENUMERATED { + f1-c, + f1-u, + non-f1, + ... +} + + +IABv4AddressesRequested ::= SEQUENCE { + iABv4AddressesRequested IABTNLAddressesRequested, + iE-Extensions ProtocolExtensionContainer { { IABv4AddressesRequested-ExtIEs} } OPTIONAL +} + +IABv4AddressesRequested-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ImplicitFormat ::= SEQUENCE { + dUFSlotformatIndex DUFSlotformatIndex, + iE-Extensions ProtocolExtensionContainer { { ImplicitFormat-ExtIEs } } OPTIONAL +} + +ImplicitFormat-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IgnorePRACHConfiguration::= ENUMERATED { true,...} + +IgnoreResourceCoordinationContainer ::= ENUMERATED { yes,...} +InactivityMonitoringRequest ::= ENUMERATED { true,...} +InactivityMonitoringResponse ::= ENUMERATED { not-supported,...} +InterfacesToTrace ::= BIT STRING (SIZE(8)) + +IntendedTDD-DL-ULConfig ::= SEQUENCE { + nRSCS ENUMERATED { scs15, scs30, scs60, scs120,...}, + nRCP ENUMERATED { normal, extended,...}, + nRDLULTxPeriodicity ENUMERATED { ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms3, ms4, ms5, ms10, ms20, ms40, ms60, ms80, ms100, ms120, ms140, ms160, ...}, + slot-Configuration-List Slot-Configuration-List, + iE-Extensions ProtocolExtensionContainer { {IntendedTDD-DL-ULConfig-ExtIEs} } OPTIONAL +} + +IntendedTDD-DL-ULConfig-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IPHeaderInformation ::= SEQUENCE { + destinationIABTNLAddress IABTNLAddress, + dsInformationList DSInformationList OPTIONAL, + iPv6FlowLabel BIT STRING (SIZE (20)) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IPHeaderInformation-ItemExtIEs} } OPTIONAL, + ... +} + +IPHeaderInformation-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IPtolayer2TrafficMappingInfo ::= SEQUENCE { + iPtolayer2TrafficMappingInfoToAdd IPtolayer2TrafficMappingInfoList OPTIONAL, + iPtolayer2TrafficMappingInfoToRemove MappingInformationtoRemove OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IPtolayer2TrafficMappingInfo-ItemExtIEs} } OPTIONAL, + ... +} + +IPtolayer2TrafficMappingInfoList ::= SEQUENCE (SIZE(1..maxnoofMappingEntries)) OF IPtolayer2TrafficMappingInfo-Item + +IPtolayer2TrafficMappingInfo-Item ::= SEQUENCE { + mappingInformationIndex MappingInformationIndex, + iPHeaderInformation IPHeaderInformation, + bHInfo BHInfo, iE-Extensions ProtocolExtensionContainer { { IPtolayer2TrafficMappingInfo-ItemExtIEs} } OPTIONAL, + ... +} + +IPtolayer2TrafficMappingInfo-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- J + +-- K + +-- L + +L139Info ::= SEQUENCE { + msg1SCS ENUMERATED {scs15, scs30, scs60, scs120, ...}, + rootSequenceIndex INTEGER (0..137) OPTIONAL, + iE-Extension ProtocolExtensionContainer { {L139Info-ExtIEs} } OPTIONAL, + ... +} + +L139Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +L839Info ::= SEQUENCE { + rootSequenceIndex INTEGER (0..837), + restrictedSetConfig ENUMERATED {unrestrictedSet, restrictedSetTypeA, + restrictedSetTypeB, ...}, + iE-Extension ProtocolExtensionContainer { {L839Info-ExtIEs} } OPTIONAL, + ... +} + +L839Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +LCID ::= INTEGER (1..32, ...) + + +LCStoGCSTranslationList ::= SEQUENCE (SIZE (1.. maxnooflcs-gcs-translation)) OF LCStoGCSTranslation + +LCStoGCSTranslation ::= SEQUENCE { + alpha INTEGER (0..359), + alpha-fine INTEGER (0..9), + beta INTEGER (0..359), + beta-fine INTEGER (0..9), + gamma INTEGER (0..359), + gamma-fine INTEGER (0..9), + iE-Extensions ProtocolExtensionContainer { {LCStoGCSTranslation-ExtIEs} } OPTIONAL +} + +LCStoGCSTranslation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +LMF-MeasurementID ::= INTEGER (1.. 65536, ...) + +LMF-UE-MeasurementID ::= INTEGER (1.. 256, ...) + +LocationUncertainty ::= SEQUENCE { + horizontalUncertainty INTEGER (0..255), + horizontalConfidence INTEGER (0..100), + verticalUncertainty INTEGER (0..255), + verticalConfidence INTEGER (0..100), + iE-Extensions ProtocolExtensionContainer { { LocationUncertainty-ExtIEs} } OPTIONAL +} + +LocationUncertainty-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +LongDRXCycleLength ::= ENUMERATED +{ms10, ms20, ms32, ms40, ms60, ms64, ms70, ms80, ms128, ms160, ms256, ms320, ms512, ms640, ms1024, ms1280, ms2048, ms2560, ms5120, ms10240, ...} + +LowerLayerPresenceStatusChange ::= ENUMERATED { + suspend-lower-layers, + resume-lower-layers, + ... + +} + +LTEUESidelinkAggregateMaximumBitrate ::= SEQUENCE { + uELTESidelinkAggregateMaximumBitrate BitRate, + iE-Extensions ProtocolExtensionContainer { {LTEUESidelinkAggregateMaximumBitrate-ExtIEs} } OPTIONAL +} + +LTEUESidelinkAggregateMaximumBitrate-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +LTEV2XServicesAuthorized ::= SEQUENCE { + vehicleUE VehicleUE OPTIONAL, + pedestrianUE PedestrianUE OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {LTEV2XServicesAuthorized-ExtIEs} } OPTIONAL +} + +LTEV2XServicesAuthorized-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- M + +MappingInformationIndex ::= BIT STRING (SIZE (26)) + +MappingInformationtoRemove ::= SEQUENCE (SIZE(1..maxnoofMappingEntries)) OF MappingInformationIndex + +MaskedIMEISV ::= BIT STRING (SIZE (64)) + +MaxDataBurstVolume ::= INTEGER (0..4095, ..., 4096.. 2000000) +MaxPacketLossRate ::= INTEGER (0..1000) + +MIB-message ::= OCTET STRING + +MeasConfig ::= OCTET STRING + +MeasGapConfig ::= OCTET STRING + +MeasGapSharingConfig ::= OCTET STRING + +MeasurementBeamInfoRequest ::= ENUMERATED {true, ...} + +MeasurementBeamInfo ::= SEQUENCE { + pRS-Resource-ID PRS-Resource-ID OPTIONAL, + pRS-Resource-Set-ID PRS-Resource-Set-ID OPTIONAL, + sSB-Index SSB-Index OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { MeasurementBeamInfo-ExtIEs} } OPTIONAL +} + +MeasurementBeamInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +MeasurementTimingConfiguration ::= OCTET STRING + +MessageIdentifier ::= BIT STRING (SIZE (16)) + +MultiplexingInfo ::= SEQUENCE{ + iAB-MT-Cell-List IAB-MT-Cell-List, + iE-Extensions ProtocolExtensionContainer { {MultiplexingInfo-ExtIEs} } OPTIONAL +} + +MultiplexingInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +M2Configuration ::= ENUMERATED {true, ...} + + +M5Configuration ::= SEQUENCE { + m5period M5period, + m5-links-to-log M5-Links-to-log, + iE-Extensions ProtocolExtensionContainer { { M5Configuration-ExtIEs} } OPTIONAL, + ... +} + +M5Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +M5period ::= ENUMERATED { ms1024, ms2048, ms5120, ms10240, min1, ... } + +M5-Links-to-log ::= ENUMERATED {uplink, downlink, both-uplink-and-downlink, ...} + + +M6Configuration ::= SEQUENCE { + m6report-Interval M6report-Interval, + m6-links-to-log M6-Links-to-log, + iE-Extensions ProtocolExtensionContainer { { M6Configuration-ExtIEs} } OPTIONAL, + ... +} + +M6Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +M6report-Interval ::= ENUMERATED { ms120, ms240, ms640, ms1024, ms2048, ms5120, ms10240, ms20480, ms40960, min1, min6, min12, min30, ... } + + + +M6-Links-to-log ::= ENUMERATED {uplink, downlink, both-uplink-and-downlink, ...} + + +M7Configuration ::= SEQUENCE { + m7period M7period, + m7-links-to-log M7-Links-to-log, + iE-Extensions ProtocolExtensionContainer { { M7Configuration-ExtIEs} } OPTIONAL, + ... +} + +M7Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +M7period ::= INTEGER(1..60, ...) + +M7-Links-to-log ::= ENUMERATED {downlink, ...} + +MDT-Activation ::= ENUMERATED { + immediate-MDT-only, + immediate-MDT-and-Trace, + ... +} + +MDTConfiguration ::= SEQUENCE { + mdt-Activation MDT-Activation, + measurementsToActivate MeasurementsToActivate, + m2Configuration M2Configuration OPTIONAL, + -- C-ifM2: This IE shall be present if the Measurements to Activate IE has the second bit set to "1". + m5Configuration M5Configuration OPTIONAL, + -- C-ifM5: This IE shall be present if the Measurements to Activate IE has the fifth bit set to "1". + m6Configuration M6Configuration OPTIONAL, + -- C-ifM6: This IE shall be present if the Measurements to Activate IE has the seventh bit set to "1". + m7Configuration M7Configuration OPTIONAL, + -- C-ifM7: This IE shall be present if the Measurements to Activate IE has the eighth bit set to "1". + iE-Extensions ProtocolExtensionContainer { { MDTConfiguration-ExtIEs} } OPTIONAL, + ... +} +MDTConfiguration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +MDTPLMNList ::= SEQUENCE (SIZE(1..maxnoofMDTPLMNs)) OF PLMN-Identity + + +MeasuredResultsValue ::= CHOICE { + uL-AngleOfArrival UL-AoA, + uL-SRS-RSRP UL-SRS-RSRP, + uL-RTOA UL-RTOA-Measurement, + gNB-RxTxTimeDiff GNB-RxTxTimeDiff, + choice-extension ProtocolIE-SingleContainer { { MeasuredResultsValue-ExtIEs } } +} + +MeasuredResultsValue-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +MeasurementsToActivate ::= BIT STRING (SIZE (8)) + +-- N + +NeedforGap::= ENUMERATED {true, ...} + +Neighbour-Cell-Information-Item ::= SEQUENCE { + nRCGI NRCGI, + intendedTDD-DL-ULConfig IntendedTDD-DL-ULConfig OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Neighbour-Cell-Information-ItemExtIEs } } OPTIONAL +} + +Neighbour-Cell-Information-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NGRANAllocationAndRetentionPriority ::= SEQUENCE { + priorityLevel PriorityLevel, + pre-emptionCapability Pre-emptionCapability, + pre-emptionVulnerability Pre-emptionVulnerability, + iE-Extensions ProtocolExtensionContainer { {NGRANAllocationAndRetentionPriority-ExtIEs} } OPTIONAL +} + +NGRANAllocationAndRetentionPriority-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +NGRANHighAccuracyAccessPointPosition ::= SEQUENCE { + latitude INTEGER (-2147483648.. 2147483647), + longitude INTEGER (-2147483648.. 2147483647), + altitude INTEGER (-64000..1280000), + uncertaintySemi-major INTEGER (0..255), + uncertaintySemi-minor INTEGER (0..255), + orientationOfMajorAxis INTEGER (0..179), + horizontalConfidence INTEGER (0..100), + uncertaintyAltitude INTEGER (0..255), + verticalConfidence INTEGER (0..100), + + iE-Extensions ProtocolExtensionContainer { { NGRANHighAccuracyAccessPointPosition-ExtIEs} } OPTIONAL +} + +NGRANHighAccuracyAccessPointPosition-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NID ::= BIT STRING (SIZE(44)) + +NR-CGI-List-For-Restart-Item ::= SEQUENCE { + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { NR-CGI-List-For-Restart-ItemExtIEs } } OPTIONAL, + ... +} + +NR-CGI-List-For-Restart-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NR-PRSBeamInformation ::= SEQUENCE { + nR-PRSBeamInformationList NR-PRSBeamInformationList, + lCStoGCSTranslationList LCStoGCSTranslationList, + iE-Extensions ProtocolExtensionContainer { { NR-PRSBeamInformation-ExtIEs } } OPTIONAL +} + +NR-PRSBeamInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NR-PRSBeamInformationList ::= SEQUENCE (SIZE(1.. maxnoofPRS-ResourceSets)) OF NR-PRSBeamInformationItem + +NR-PRSBeamInformationItem ::= SEQUENCE { + pRSResourceSetID INTEGER (0..7), + pRSAngleList PRSAngleList, + iE-Extensions ProtocolExtensionContainer { { NR-PRSBeamInformationItem-ExtIEs } } OPTIONAL +} + +NR-PRSBeamInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NonDynamic5QIDescriptor ::= SEQUENCE { + fiveQI INTEGER (0..255, ...), + qoSPriorityLevel INTEGER (1..127) OPTIONAL, + averagingWindow AveragingWindow OPTIONAL, + maxDataBurstVolume MaxDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { NonDynamic5QIDescriptor-ExtIEs } } OPTIONAL +} + +NonDynamic5QIDescriptor-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-CNPacketDelayBudgetDownlink CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }| + { ID id-CNPacketDelayBudgetUplink CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }, + ... +} + +NonDynamicPQIDescriptor ::= SEQUENCE { + fiveQI INTEGER (0..255, ...), + qoSPriorityLevel INTEGER (1..8, ...) OPTIONAL, + averagingWindow AveragingWindow OPTIONAL, + maxDataBurstVolume MaxDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { NonDynamicPQIDescriptor-ExtIEs } } OPTIONAL +} + +NonDynamicPQIDescriptor-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NonUPTrafficType ::= ENUMERATED {ue-associated, non-ue-associated, non-f1, bap-control-pdu,...} + +NoofDownlinkSymbols ::= INTEGER (0..14) + +NoofUplinkSymbols ::= INTEGER (0..14) + +Notification-Cause ::= ENUMERATED {fulfilled, not-fulfilled, ...} + +NotificationControl ::= ENUMERATED {active, not-active, ...} + +NotificationInformation ::= SEQUENCE { + message-Identifier MessageIdentifier, + serialNumber SerialNumber, + iE-Extensions ProtocolExtensionContainer { { NotificationInformationExtIEs} } OPTIONAL, + ... +} + +NotificationInformationExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NPNBroadcastInformation ::= CHOICE { + sNPN-Broadcast-Information NPN-Broadcast-Information-SNPN, + pNI-NPN-Broadcast-Information NPN-Broadcast-Information-PNI-NPN, + choice-extension ProtocolIE-SingleContainer { {NPNBroadcastInformation-ExtIEs} } +} + +NPNBroadcastInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +NPN-Broadcast-Information-SNPN ::= SEQUENCE { + broadcastSNPNID-List BroadcastSNPN-ID-List, + iE-Extension ProtocolExtensionContainer { {NPN-Broadcast-Information-SNPN-ExtIEs} } OPTIONAL, + ... +} + +NPN-Broadcast-Information-SNPN-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} +NPN-Broadcast-Information-PNI-NPN ::= SEQUENCE { + broadcastPNI-NPN-ID-Information BroadcastPNI-NPN-ID-List, + iE-Extension ProtocolExtensionContainer { {NPN-Broadcast-Information-PNI-NPN-ExtIEs} } OPTIONAL, + ... +} + +NPN-Broadcast-Information-PNI-NPN-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +NPNSupportInfo ::= CHOICE { + sNPN-Information NID, + choice-extension ProtocolIE-SingleContainer { { NPNSupportInfo-ExtIEs } } +} + +NPNSupportInfo-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +NRCarrierList ::= SEQUENCE (SIZE(1..maxnoofNRSCSs)) OF NRCarrierItem + +NRCarrierItem ::= SEQUENCE { + carrierSCS NRSCS, + offsetToCarrier INTEGER (0..2199, ...), + carrierBandwidth INTEGER (0..maxnoofPhysicalResourceBlocks, ...), + iE-Extension ProtocolExtensionContainer { {NRCarrierItem-ExtIEs} } OPTIONAL, + ... +} + +NRCarrierItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRFreqInfo ::= SEQUENCE { + nRARFCN INTEGER (0..maxNRARFCN), + sul-Information SUL-Information OPTIONAL, + freqBandListNr SEQUENCE (SIZE(1..maxnoofNrCellBands)) OF FreqBandNrItem, + iE-Extensions ProtocolExtensionContainer { { NRFreqInfoExtIEs} } OPTIONAL, + ... +} + +NRFreqInfoExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-FrequencyShift7p5khz CRITICALITY ignore EXTENSION FrequencyShift7p5khz PRESENCE optional }, + ... +} + +NRCGI ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + nRCellIdentity NRCellIdentity, + iE-Extensions ProtocolExtensionContainer { {NRCGI-ExtIEs} } OPTIONAL, + ... +} + +NRCGI-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NR-Mode-Info ::= CHOICE { + fDD FDD-Info, + tDD TDD-Info, + choice-extension ProtocolIE-SingleContainer { { NR-Mode-Info-ExtIEs} } +} + +NR-Mode-Info-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + + +NRPRACHConfig ::= SEQUENCE { + ulPRACHConfigList NRPRACHConfigList OPTIONAL, + sulPRACHConfigList NRPRACHConfigList OPTIONAL, + iE-Extension ProtocolExtensionContainer { {NRPRACHConfig-ExtIEs} } OPTIONAL, + ... +} + +NRPRACHConfig-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRCellIdentity ::= BIT STRING (SIZE(36)) + +NRNRB ::= ENUMERATED { nrb11, nrb18, nrb24, nrb25, nrb31, nrb32, nrb38, nrb51, nrb52, nrb65, nrb66, nrb78, nrb79, nrb93, nrb106, nrb107, nrb121, nrb132, nrb133, nrb135, nrb160, nrb162, nrb189, nrb216, nrb217, nrb245, nrb264, nrb270, nrb273, ...} + +NRPCI ::= INTEGER(0..1007) + + +NRPRACHConfigList ::= SEQUENCE (SIZE(0..maxnoofPRACHconfigs)) OF NRPRACHConfigItem + +NRPRACHConfigItem ::= SEQUENCE { + nRSCS NRSCS, + prachFreqStartfromCarrier INTEGER (0..maxnoofPhysicalResourceBlocks-1, ...), + msg1FDM ENUMERATED {one, two, four, eight, ...}, + parchConfigIndex INTEGER (0..255, ...), + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, + two, four, eight, sixteen, ...}, + freqDomainLength FreqDomainLength, + zeroCorrelZoneConfig INTEGER (0..15), + iE-Extension ProtocolExtensionContainer { { NRPRACHConfigItem-ExtIEs} } OPTIONAL, + ... +} + +NRPRACHConfigItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRSCS ::= ENUMERATED { scs15, scs30, scs60, scs120, ...} + +NRUERLFReportContainer ::= OCTET STRING + +NumberofActiveUEs ::= INTEGER(0..16777215, ...) + +NumberOfBroadcasts ::= INTEGER (0..65535) + +NumberofBroadcastRequest ::= INTEGER (0..65535) + +NumDLULSymbols ::= SEQUENCE { + numDLSymbols INTEGER (0..13, ...), + numULSymbols INTEGER (0..13, ...), + iE-Extensions ProtocolExtensionContainer { { NumDLULSymbols-ExtIEs} } OPTIONAL +} + +NumDLULSymbols-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRV2XServicesAuthorized ::= SEQUENCE { + vehicleUE VehicleUE OPTIONAL, + pedestrianUE PedestrianUE OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {NRV2XServicesAuthorized-ExtIEs} } OPTIONAL +} + +NRV2XServicesAuthorized-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRUESidelinkAggregateMaximumBitrate ::= SEQUENCE { + uENRSidelinkAggregateMaximumBitrate BitRate, + iE-Extensions ProtocolExtensionContainer { {NRUESidelinkAggregateMaximumBitrate-ExtIEs} } OPTIONAL +} + +NRUESidelinkAggregateMaximumBitrate-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NZP-CSI-RS-ResourceID::= INTEGER (0..191, ...) + + +-- O + +OffsetToPointA ::= INTEGER (0..2199,...) + + +-- P + +PacketDelayBudget ::= INTEGER (0..1023, ...) + +PacketErrorRate ::= SEQUENCE { + pER-Scalar PER-Scalar, + pER-Exponent PER-Exponent, + iE-Extensions ProtocolExtensionContainer { {PacketErrorRate-ExtIEs} } OPTIONAL, + ... +} + +PacketErrorRate-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PER-Scalar ::= INTEGER (0..9, ...) +PER-Exponent ::= INTEGER (0..9, ...) + +PagingCell-Item ::= SEQUENCE { + nRCGI NRCGI , + iE-Extensions ProtocolExtensionContainer { { PagingCell-ItemExtIEs } } OPTIONAL +} + +PagingCell-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PagingDRX ::= ENUMERATED { + v32, + v64, + v128, + v256, + ... +} + +PagingIdentity ::= CHOICE { + rANUEPagingIdentity RANUEPagingIdentity, + cNUEPagingIdentity CNUEPagingIdentity, + choice-extension ProtocolIE-SingleContainer { { PagingIdentity-ExtIEs } } +} + +PagingIdentity-ExtIEs F1AP-PROTOCOL-IES::= { + ... +} + +PagingOrigin ::= ENUMERATED { non-3gpp, ...} + +PagingPriority ::= ENUMERATED { priolevel1, priolevel2, priolevel3, priolevel4, priolevel5, priolevel6, priolevel7, priolevel8,...} + + +RelativePathDelay ::= CHOICE { + k0 INTEGER (0..16351,...), + k1 INTEGER (0..8176,...), + k2 INTEGER (0..4088,...), + k3 INTEGER (0..2044,...), + k4 INTEGER (0..1022,...), + k5 INTEGER (0..511,...), + choice-extension ProtocolIE-SingleContainer { { RelativePathDelay-ExtIEs } } +} + +RelativePathDelay-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +PathlossReferenceInfo ::= SEQUENCE { + pathlossReferenceSignal PathlossReferenceSignal, + iE-Extensions ProtocolExtensionContainer { {PathlossReferenceInfo-ExtIEs} } OPTIONAL +} + +PathlossReferenceInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PathlossReferenceSignal ::= CHOICE { + sSB SSB, + dL-PRS DL-PRS, + choice-extension ProtocolIE-SingleContainer {{PathlossReferenceSignal-ExtIEs }} +} + +PathlossReferenceSignal-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +PC5QoSFlowIdentifier ::= INTEGER (1..2048) + +PC5-QoS-Characteristics ::= CHOICE { + non-Dynamic-PQI NonDynamicPQIDescriptor, + dynamic-PQI DynamicPQIDescriptor, + choice-extension ProtocolIE-SingleContainer { { PC5-QoS-Characteristics-ExtIEs } } +} + +PC5-QoS-Characteristics-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +PC5QoSParameters ::= SEQUENCE { + pC5-QoS-Characteristics PC5-QoS-Characteristics, + pC5-QoS-Flow-Bit-Rates PC5FlowBitRates OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PC5QoSParameters-ExtIEs } } OPTIONAL, + ... +} + +PC5QoSParameters-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PC5FlowBitRates ::= SEQUENCE { + guaranteedFlowBitRate BitRate, + maximumFlowBitRate BitRate, + iE-Extensions ProtocolExtensionContainer { { PC5FlowBitRates-ExtIEs } } OPTIONAL, + ... +} + +PC5FlowBitRates-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PDCCH-BlindDetectionSCG ::= OCTET STRING + +PDCP-SN ::= INTEGER (0..4095) + +PDCPSNLength ::= ENUMERATED { twelve-bits,eighteen-bits,...} + +PDUSessionID ::= INTEGER (0..255) + +ReportingPeriodicityValue ::= INTEGER (0..512, ...) + +Periodicity ::= INTEGER (0..640000, ...) + +PeriodicitySRS ::= ENUMERATED { ms0p125, ms0p25, ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms4, ms5, ms8, ms10, ms16, ms20, ms32, ms40, ms64, ms80, ms160, ms320, ms640, ms1280, ms2560, ms5120, ms10240, ...} + +PeriodicityList ::= SEQUENCE (SIZE(1.. maxnoSRS-ResourcePerSet)) OF PeriodicityList-Item + +PeriodicityList-Item ::= SEQUENCE { + periodicitySRS PeriodicitySRS, + iE-Extensions ProtocolExtensionContainer { { PeriodicityList-ItemExtIEs} } OPTIONAL +} + +PeriodicityList-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +Permutation ::= ENUMERATED {dfu, ufd, ...} + +Ph-InfoMCG ::= OCTET STRING + +Ph-InfoSCG ::= OCTET STRING + +PLMN-Identity ::= OCTET STRING (SIZE(3)) + +PortNumber ::= BIT STRING (SIZE (16)) + + +PosAssistance-Information ::= OCTET STRING + +PosAssistanceInformationFailureList ::= OCTET STRING + +PosBroadcast ::= ENUMERATED { + start, + stop, + ... +} + +PositioningBroadcastCells ::= SEQUENCE (SIZE (1..maxnoBcastCell)) OF NRCGI + +PosMeasurementPeriodicity ::= ENUMERATED +{ms120, ms240, ms480, ms640, ms1024, ms2048, ms5120, ms10240, min1, min6, min12, min30, min60, ...} + + +PosMeasurementQuantities ::= SEQUENCE (SIZE(1.. maxnoofPosMeas)) OF PosMeasurementQuantities-Item + +PosMeasurementQuantities-Item ::= SEQUENCE { + posMeasurementType PosMeasurementType, + timingReportingGranularityFactor INTEGER (0..5) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PosMeasurementQuantities-ItemExtIEs} } OPTIONAL +} + +PosMeasurementQuantities-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosMeasurementResult ::= SEQUENCE (SIZE (1.. maxnoofPosMeas)) OF PosMeasurementResultItem + +PosMeasurementResultItem ::= SEQUENCE { + measuredResultsValue MeasuredResultsValue, + timeStamp TimeStamp, + measurementQuality TRPMeasurementQuality OPTIONAL, + measurementBeamInfo MeasurementBeamInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PosMeasurementResultItemExtIEs } } OPTIONAL +} + +PosMeasurementResultItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosMeasurementResultList ::= SEQUENCE (SIZE(1.. maxNoOfMeasTRPs)) OF PosMeasurementResultList-Item + +PosMeasurementResultList-Item ::= SEQUENCE { + posMeasurementResult PosMeasurementResult, + tRPID TRPID, + iE-Extensions ProtocolExtensionContainer { { PosMeasurementResultList-ItemExtIEs} } OPTIONAL +} + +PosMeasurementResultList-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosMeasurementType ::= ENUMERATED { + gnb-rx-tx, + ul-srs-rsrp, + ul-aoa, + ul-rtoa, + ... +} + +PosReportCharacteristics ::= ENUMERATED { + ondemand, + periodic, + ... +} + +PosResourceSetType ::= CHOICE { + periodic PosResourceSetTypePR, + semi-persistent PosResourceSetTypeSP, + aperiodic PosResourceSetTypeAP, + choice-extension ProtocolIE-SingleContainer {{ PosResourceSetType-ExtIEs }} +} + +PosResourceSetType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +PosResourceSetTypePR ::= SEQUENCE { + posperiodicSet ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { PosResourceSetTypePR-ExtIEs} } OPTIONAL +} + +PosResourceSetTypePR-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosResourceSetTypeSP ::= SEQUENCE { + possemi-persistentSet ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { PosResourceSetTypeSP-ExtIEs} } OPTIONAL +} + +PosResourceSetTypeSP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosResourceSetTypeAP ::= SEQUENCE { + sRSResourceTrigger-List INTEGER(1..3), + iE-Extensions ProtocolExtensionContainer { { PosResourceSetTypeAP-ExtIEs} } OPTIONAL +} + +PosResourceSetTypeAP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosSRSResourceID-List ::= SEQUENCE (SIZE (1..maxnoSRS-PosResourcePerSet)) OF SRSPosResourceID + +PosSRSResource-Item ::= SEQUENCE { + srs-PosResourceId SRSPosResourceID, + transmissionCombPos TransmissionCombPos, + startPosition INTEGER (0..13), + nrofSymbols ENUMERATED {n1, n2, n4, n8, n12}, + freqDomainShift INTEGER (0..268), + c-SRS INTEGER (0..63), + groupOrSequenceHopping ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceTypePos ResourceTypePos, + sequenceId INTEGER (0.. 65535), + spatialRelationPos SpatialRelationPos OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PosSRSResource-Item-ExtIEs} } OPTIONAL +} + +PosSRSResource-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosSRSResource-List ::= SEQUENCE (SIZE (1..maxnoSRS-PosResources)) OF PosSRSResource-Item + +PosSRSResourceSet-Item ::= SEQUENCE { + possrsResourceSetID INTEGER(0..15), + possRSResourceID-List PosSRSResourceID-List, + posresourceSetType PosResourceSetType, + iE-Extensions ProtocolExtensionContainer { { PosSRSResourceSet-Item-ExtIEs} } OPTIONAL +} + +PosSRSResourceSet-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosSRSResourceSet-List ::= SEQUENCE (SIZE (1..maxnoSRS-PosResourceSets)) OF PosSRSResourceSet-Item + +PrimaryPathIndication ::= ENUMERATED { + true, + false, + ... +} + +Pre-emptionCapability ::= ENUMERATED { + shall-not-trigger-pre-emption, + may-trigger-pre-emption +} + +Pre-emptionVulnerability ::= ENUMERATED { + not-pre-emptable, + pre-emptable +} + +PriorityLevel ::= INTEGER { spare (0), highest (1), lowest (14), no-priority (15) } (0..15) + +ProtectedEUTRAResourceIndication ::= OCTET STRING + +Protected-EUTRA-Resources-Item ::= SEQUENCE { + spectrumSharingGroupID SpectrumSharingGroupID, + eUTRACells-List EUTRACells-List, + iE-Extensions ProtocolExtensionContainer { { Protected-EUTRA-Resources-ItemExtIEs } } OPTIONAL +} + +Protected-EUTRA-Resources-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSConfiguration ::= SEQUENCE { + pRSResourceSet-List PRSResourceSet-List, + iE-Extensions ProtocolExtensionContainer { { PRSConfiguration-ExtIEs } } OPTIONAL +} + +PRSConfiguration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSInformationPos ::= SEQUENCE { + pRS-IDPos INTEGER(0..255) OPTIONAL, + pRS-Resource-Set-IDPos INTEGER(0..7), + pRS-Resource-IDPos INTEGER(0..63), + iE-Extensions ProtocolExtensionContainer { { PRSInformationPos-ExtIEs} } OPTIONAL +} + +PRSInformationPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Potential-SpCell-Item ::= SEQUENCE { + potential-SpCell-ID NRCGI , + iE-Extensions ProtocolExtensionContainer { { Potential-SpCell-ItemExtIEs } } OPTIONAL, + ... +} + +Potential-SpCell-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +PRSAngleList ::= SEQUENCE (SIZE(1.. maxnoofPRS-ResourcesPerSet)) OF PRSAngleItem + +PRSAngleItem ::= SEQUENCE { + nR-PRS-Azimuth INTEGER (0..359), + nR-PRS-Azimuth-fine INTEGER (0..9), + nR-PRS-Elevation INTEGER (0..180), + nR-PRS-Elevation-fine INTEGER (0..9), + iE-Extensions ProtocolExtensionContainer { { PRSAngleItem-ItemExtIEs } } OPTIONAL +} + +PRSAngleItem-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSMuting::= SEQUENCE { + pRSMutingOption1 PRSMutingOption1, + pRSMutingOption2 PRSMutingOption2, + iE-Extensions ProtocolExtensionContainer { { PRSMuting-ExtIEs} } OPTIONAL +} + +PRSMuting-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSMutingOption1 ::= SEQUENCE { + mutingPattern DL-PRSMutingPattern, + mutingBitRepetitionFactor ENUMERATED{rf1,rf2,rf4,rf8,...}, + iE-Extensions ProtocolExtensionContainer { { PRSMutingOption1-ExtIEs} } OPTIONAL +} + +PRSMutingOption1-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSMutingOption2 ::= SEQUENCE { + mutingPattern DL-PRSMutingPattern, + iE-Extensions ProtocolExtensionContainer { { PRSMutingOption2-ExtIEs} } OPTIONAL +} + +PRSMutingOption2-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRS-Resource-ID ::= INTEGER (0..63) + +PRSResource-List::= SEQUENCE (SIZE (1..maxnoofPRSresources)) OF PRSResource-Item + +PRSResource-Item ::= SEQUENCE { + pRSResourceID INTEGER(0..63), + sequenceID INTEGER(0..4095,...), + rEOffset INTEGER(0..11), + resourceSlotOffset INTEGER(0..511,...), + resourceSymbolOffset INTEGER(0..12,...), + qCLInfo PRSResource-QCLInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PRSResource-Item-ExtIEs} } OPTIONAL +} + +PRSResource-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSResource-QCLInfo ::= SEQUENCE { + qCLSourceSSBIndex INTEGER(0..63) OPTIONAL, + qCLSourcePRSInfo PRSResource-QCLSourcePRSInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PRSResource-QCLInfo-ExtIEs} } OPTIONAL, + ... +} +PRSResource-QCLInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSResource-QCLSourcePRSInfo ::= SEQUENCE { + qCLSourcePRSResourceSetID INTEGER(0..7), + qCLSourcePRSResourceID INTEGER(0..63) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PRSResource-QCLSourcePRSInfo-ExtIEs} } OPTIONAL +} + +PRSResource-QCLSourcePRSInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRS-Resource-Set-ID ::= INTEGER(0..7) + +PRSResourceSet-List ::= SEQUENCE (SIZE (1.. maxnoofPRSresourceSets)) OF PRSResourceSet-Item +PRSResourceSet-Item ::= SEQUENCE { + pRSResourceSetID PRS-Resource-Set-ID, + subcarrierSpacing ENUMERATED{kHz15, kHz30, kHz60, kHz120, ...}, + pRSbandwidth INTEGER(1..63), + startPRB INTEGER(0..2176), + pointA INTEGER (0..3279165), + combSize ENUMERATED{n2, n4, n6, n12, ...}, + cPType ENUMERATED{normal, extended, ...}, + resourceSetPeriodicity ENUMERATED{n4,n5,n8,n10,n16,n20,n32,n40,n64,n80,n160,n320,n640,n1280,n2560,n5120,n10240,n20480,n40960, n81920,...}, + resourceSetSlotOffset INTEGER(0..81919,...), + resourceRepetitionFactor ENUMERATED{rf1,rf2,rf4,rf6,rf8,rf16,rf32,...}, + resourceTimeGap ENUMERATED{tg1,tg2,tg4,tg8,tg16,tg32,...}, + resourceNumberofSymbols ENUMERATED{n2,n4,n6,n12,...}, + pRSMuting PRSMuting OPTIONAL, + pRSResourceTransmitPower INTEGER(-60..50), + pRSResource-List PRSResource-List, + iE-Extensions ProtocolExtensionContainer { { PRSResourceSet-Item-ExtIEs} } OPTIONAL +} + +PRSResourceSet-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PWS-Failed-NR-CGI-Item ::= SEQUENCE { + nRCGI NRCGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { { PWS-Failed-NR-CGI-ItemExtIEs } } OPTIONAL, + ... +} + +PWS-Failed-NR-CGI-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PWSSystemInformation ::= SEQUENCE { + sIBtype SIBType-PWS, + sIBmessage OCTET STRING, + iE-Extensions ProtocolExtensionContainer { { PWSSystemInformationExtIEs } } OPTIONAL, + ... +} + +PWSSystemInformationExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-NotificationInformation CRITICALITY ignore EXTENSION NotificationInformation PRESENCE optional}| + { ID id-AdditionalSIBMessageList CRITICALITY reject EXTENSION AdditionalSIBMessageList PRESENCE optional}, + ... +} + +PrivacyIndicator ::= ENUMERATED {immediate-MDT, logged-MDT, ...} + +-- Q + +QCI ::= INTEGER (0..255) + +QoS-Characteristics ::= CHOICE { + non-Dynamic-5QI NonDynamic5QIDescriptor, + dynamic-5QI Dynamic5QIDescriptor, + choice-extension ProtocolIE-SingleContainer { { QoS-Characteristics-ExtIEs } } +} + +QoS-Characteristics-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +QoSFlowIdentifier ::= INTEGER (0..63) + +QoSFlowLevelQoSParameters ::= SEQUENCE { + qoS-Characteristics QoS-Characteristics, + nGRANallocationRetentionPriority NGRANAllocationAndRetentionPriority, + gBR-QoS-Flow-Information GBR-QoSFlowInformation OPTIONAL, + reflective-QoS-Attribute ENUMERATED {subject-to, ...} OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { QoSFlowLevelQoSParameters-ExtIEs } } OPTIONAL +} + +QoSFlowLevelQoSParameters-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-PDUSessionID CRITICALITY ignore EXTENSION PDUSessionID PRESENCE optional}| + { ID id-ULPDUSessionAggregateMaximumBitRate CRITICALITY ignore EXTENSION BitRate PRESENCE optional}| + { ID id-QosMonitoringRequest CRITICALITY ignore EXTENSION QosMonitoringRequest PRESENCE optional}, + ... +} + +QoSFlowMappingIndication ::= ENUMERATED {ul,dl,...} + +QoSInformation ::= CHOICE { + eUTRANQoS EUTRANQoS, + choice-extension ProtocolIE-SingleContainer { { QoSInformation-ExtIEs} } +} + +QoSInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRB-Information CRITICALITY ignore TYPE DRB-Information PRESENCE mandatory}, + ... +} + +QosMonitoringRequest ::= ENUMERATED {ul, dl, both, ...} + +QoSParaSetIndex ::= INTEGER (1..8, ...) + +QoSParaSetNotifyIndex ::= INTEGER (0..8, ...) + +-- R + +RACH-Config-Common ::= OCTET STRING + +RACH-Config-Common-IAB ::= OCTET STRING + +RACHReportContainer::= OCTET STRING + +RACHReportInformationList ::= SEQUENCE (SIZE(1.. maxnoofRACHReports)) OF RACHReportInformationItem + +RACHReportInformationItem ::= SEQUENCE { + rACHReportContainer RACHReportContainer, + uEAssitantIdentifier GNB-DU-UE-F1AP-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { RACHReportInformationItem-ExtIEs} } OPTIONAL, + ... +} + +RACHReportInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + + +RadioResourceStatus ::= SEQUENCE { + sSBAreaRadioResourceStatusList SSBAreaRadioResourceStatusList, + iE-Extensions ProtocolExtensionContainer { { RadioResourceStatus-ExtIEs} } OPTIONAL +} + +RadioResourceStatus-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RANAC ::= INTEGER (0..255) + +RAN-MeasurementID ::= INTEGER (1.. 65536, ...) + +RAN-UE-MeasurementID ::= INTEGER (1.. 256, ...) + +RANUEID ::= OCTET STRING (SIZE (8)) + +RANUEPagingIdentity ::= SEQUENCE { + iRNTI BIT STRING (SIZE(40)), + iE-Extensions ProtocolExtensionContainer { { RANUEPagingIdentity-ExtIEs } } OPTIONAL} + +RANUEPagingIdentity-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RAT-FrequencyPriorityInformation::= CHOICE { + eNDC SubscriberProfileIDforRFP, + nGRAN RAT-FrequencySelectionPriority, + choice-extension ProtocolIE-SingleContainer { { RAT-FrequencyPriorityInformation-ExtIEs} } +} + +RAT-FrequencyPriorityInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +RAT-FrequencySelectionPriority::= INTEGER (1.. 256, ...) + +Reestablishment-Indication ::= ENUMERATED { + reestablished, + ... +} + +ReferencePoint ::= CHOICE { + coordinateID CoordinateID, + referencePointCoordinate AccessPointPosition, + referencePointCoordinateHA NGRANHighAccuracyAccessPointPosition, + choice-Extension ProtocolIE-SingleContainer { { ReferencePoint-ExtIEs} } +} + +ReferencePoint-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +ReferenceSFN ::= INTEGER (0..1023) + +ReferenceSignal ::= CHOICE { + nZP-CSI-RS NZP-CSI-RS-ResourceID, + sSB SSB, + sRS SRSResourceID, + positioningSRS SRSPosResourceID, + dL-PRS DL-PRS, + choice-extension ProtocolIE-SingleContainer {{ReferenceSignal-ExtIEs }} +} + +ReferenceSignal-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +RelativeCartesianLocation ::= SEQUENCE { + xYZunit ENUMERATED {mm, cm, dm, ...}, + xvalue INTEGER (-65536..65535), + yvalue INTEGER (-65536..65535), + zvalue INTEGER (-32768..32767), + locationUncertainty LocationUncertainty, + iE-Extensions ProtocolExtensionContainer { { RelativeCartesianLocation-ExtIEs} } OPTIONAL +} + +RelativeCartesianLocation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RelativeGeodeticLocation ::= SEQUENCE { + milli-Arc-SecondUnits ENUMERATED {zerodot03, zerodot3, three, ...}, + heightUnits ENUMERATED {mm, cm, m, ...}, + deltaLatitude INTEGER (-1024.. 1023), + deltaLongitude INTEGER (-1024.. 1023), + deltaHeight INTEGER (-1024.. 1023), + locationUncertainty LocationUncertainty, + iE-extensions ProtocolExtensionContainer {{RelativeGeodeticLocation-ExtIEs }} OPTIONAL +} + +RelativeGeodeticLocation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ReferenceTime ::= OCTET STRING + +RegistrationRequest ::= ENUMERATED{start, stop, add, ...} + +ReportCharacteristics ::= BIT STRING (SIZE(32)) + +ReportingPeriodicity ::= ENUMERATED{ms500, ms1000, ms2000, ms5000, ms10000, ...} + +RequestedBandCombinationIndex ::= OCTET STRING + +RequestedFeatureSetEntryIndex ::= OCTET STRING + +RequestedP-MaxFR2 ::= OCTET STRING + +Requested-PDCCH-BlindDetectionSCG ::= OCTET STRING + + +RequestedSRSTransmissionCharacteristics ::= SEQUENCE { + numberOfTransmissions INTEGER (0..500, ...) OPTIONAL, + resourceType ENUMERATED {periodic, semi-persistent, aperiodic,...}, + bandwidthSRS BandwidthSRS, + sRSResourceSetList SRSResourceSetList OPTIONAL, + sSBInformation SSBInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { RequestedSRSTransmissionCharacteristics-ExtIEs} } OPTIONAL +} + +RequestedSRSTransmissionCharacteristics-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RequestType ::= ENUMERATED {offer, execution, ...} + +ResourceCoordinationEUTRACellInfo ::= SEQUENCE { + eUTRA-Mode-Info EUTRA-Coex-Mode-Info, + eUTRA-PRACH-Configuration EUTRA-PRACH-Configuration, + iE-Extensions ProtocolExtensionContainer { { ResourceCoordinationEUTRACellInfo-ExtIEs } } OPTIONAL, + ... +} + +ResourceCoordinationEUTRACellInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-IgnorePRACHConfiguration CRITICALITY reject EXTENSION IgnorePRACHConfiguration PRESENCE optional }, + ... +} + +ResourceCoordinationTransferInformation ::= SEQUENCE { + meNB-Cell-ID EUTRA-Cell-ID, + resourceCoordinationEUTRACellInfo ResourceCoordinationEUTRACellInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { ResourceCoordinationTransferInformation-ExtIEs } } OPTIONAL, + ... +} + +ResourceCoordinationTransferInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceCoordinationTransferContainer ::= OCTET STRING + +ResourceSetType ::= CHOICE { + periodic ResourceSetTypePeriodic, + semi-persistent ResourceSetTypeSemi-persistent, + aperiodic ResourceSetTypeAperiodic, + choice-extension ProtocolIE-SingleContainer {{ ResourceSetType-ExtIEs }} +} + +ResourceSetType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +ResourceSetTypePeriodic ::= SEQUENCE { + periodicSet ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { ResourceSetTypePeriodic-ExtIEs} } OPTIONAL +} + +ResourceSetTypePeriodic-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceSetTypeSemi-persistent ::= SEQUENCE { + semi-persistentSet ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { ResourceSetTypeSemi-persistent-ExtIEs} } OPTIONAL +} + +ResourceSetTypeSemi-persistent-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceSetTypeAperiodic ::= SEQUENCE { + sRSResourceTrigger-List INTEGER(1..3), + slotoffset INTEGER(1..32), + iE-Extensions ProtocolExtensionContainer { { ResourceSetTypeAperiodic-ExtIEs} } OPTIONAL +} + +ResourceSetTypeAperiodic-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RepetitionPeriod ::= INTEGER (0..131071, ...) + +ReportingRequestType ::= SEQUENCE { + eventType EventType, + reportingPeriodicityValue ReportingPeriodicityValue OPTIONAL, + -- C-ifEventTypeisPeriodic: This IE shall be present if the Event Type IE is set to "periodic" in the Event Type IE. + iE-Extensions ProtocolExtensionContainer { {ReportingRequestType-ExtIEs} } OPTIONAL +} + +ReportingRequestType-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceType ::= CHOICE { + periodic ResourceTypePeriodic, + semi-persistent ResourceTypeSemi-persistent, + aperiodic ResourceTypeAperiodic, + choice-extension ProtocolIE-SingleContainer {{ ResourceType-ExtIEs }} +} + +ResourceType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +ResourceTypePeriodic ::= SEQUENCE { + periodicity ENUMERATED{slot1, slot2, slot4, slot5, slot8, slot10, slot16, slot20, slot32, slot40, slot64, slot80, slot160, slot320, slot640, slot1280, slot2560, ...}, + offset INTEGER(0..2559, ...), + iE-Extensions ProtocolExtensionContainer { { ResourceTypePeriodic-ExtIEs} } OPTIONAL +} + +ResourceTypePeriodic-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypeSemi-persistent ::= SEQUENCE { + periodicity ENUMERATED{slot1, slot2, slot4, slot5, slot8, slot10, slot16, slot20, slot32, slot40, slot64, slot80, slot160, slot320, slot640, slot1280, slot2560, ...}, + offset INTEGER(0..2559, ...), + iE-Extensions ProtocolExtensionContainer { { ResourceTypeSemi-persistent-ExtIEs} } OPTIONAL +} + +ResourceTypeSemi-persistent-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypeAperiodic ::= SEQUENCE { + aperiodicResourceType ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { ResourceTypeAperiodic-ExtIEs} } OPTIONAL +} + +ResourceTypeAperiodic-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypePos ::= CHOICE { + periodic ResourceTypePeriodicPos, + semi-persistent ResourceTypeSemi-persistentPos, + aperiodic ResourceTypeAperiodicPos, + choice-extension ProtocolIE-SingleContainer {{ ResourceTypePos-ExtIEs }} +} + +ResourceTypePos-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +ResourceTypePeriodicPos ::= SEQUENCE { + periodicity ENUMERATED{slot1, slot2, slot4, slot5, slot8, slot10, slot16, slot20, slot32, slot40, slot64, slot80, slot160, slot320, slot640, slot1280, slot2560, slot5120, slot10240, slot20480, slot40960, slot81920, ...}, + offset INTEGER(0..81919, ...), + iE-Extensions ProtocolExtensionContainer { { ResourceTypePeriodicPos-ExtIEs} } OPTIONAL +} + +ResourceTypePeriodicPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypeSemi-persistentPos ::= SEQUENCE { + periodicity ENUMERATED{slot1, slot2, slot4, slot5, slot8, slot10, slot16, slot20, slot32, slot40, slot64, slot80, slot160, slot320, slot640, slot1280, slot2560, slot5120, slot10240, slot20480, slot40960, slot81920, ...}, + offset INTEGER(0..81919, ...), + iE-Extensions ProtocolExtensionContainer { { ResourceTypeSemi-persistentPos-ExtIEs} } OPTIONAL +} + +ResourceTypeSemi-persistentPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypeAperiodicPos ::= SEQUENCE { + slotOffset INTEGER (1..32), + iE-Extensions ProtocolExtensionContainer { { ResourceTypeAperiodicPos-ExtIEs} } OPTIONAL +} + +ResourceTypeAperiodicPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLCDuplicationInformation ::= SEQUENCE { + rLCDuplicationStateList RLCDuplicationStateList, + primaryPathIndication PrimaryPathIndication OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {RLCDuplicationInformation-ExtIEs} } OPTIONAL +} + +RLCDuplicationInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLCDuplicationStateList ::= SEQUENCE (SIZE(1..maxnoofRLCDuplicationState)) OF RLCDuplicationState-Item + +RLCDuplicationState-Item ::=SEQUENCE { + duplicationState DuplicationState, + iE-Extensions ProtocolExtensionContainer { {RLCDuplicationState-Item-ExtIEs } } OPTIONAL, + ... +} + + +RLCDuplicationState-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLCFailureIndication ::= SEQUENCE { + assocatedLCID LCID, + iE-Extensions ProtocolExtensionContainer { {RLCFailureIndication-ExtIEs} } OPTIONAL +} + +RLCFailureIndication-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLCMode ::= ENUMERATED { + rlc-am, + rlc-um-bidirectional, + rlc-um-unidirectional-ul, + rlc-um-unidirectional-dl, + ... +} + +RLC-Status ::= SEQUENCE { + reestablishment-Indication Reestablishment-Indication, + iE-Extensions ProtocolExtensionContainer { { RLC-Status-ExtIEs } } OPTIONAL, + ... +} + +RLC-Status-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLFReportInformationList ::= SEQUENCE (SIZE(1.. maxnoofRLFReports)) OF RLFReportInformationItem + +RLFReportInformationItem ::= SEQUENCE { + nRUERLFReportContainer NRUERLFReportContainer, + uEAssitantIdentifier GNB-DU-UE-F1AP-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { RLFReportInformationItem-ExtIEs} } OPTIONAL, + ... +} + +RLFReportInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RIMRSDetectionStatus ::= ENUMERATED {rs-detected, rs-disappeared, ...} + +RRCContainer ::= OCTET STRING + +RRCContainer-RRCSetupComplete ::= OCTET STRING + +RRCDeliveryStatus ::= SEQUENCE { + delivery-status PDCP-SN, + triggering-message PDCP-SN, + iE-Extensions ProtocolExtensionContainer { { RRCDeliveryStatus-ExtIEs } } OPTIONAL} + +RRCDeliveryStatus-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +RRCDeliveryStatusRequest ::= ENUMERATED {true, ...} + +RRCReconfigurationCompleteIndicator ::= ENUMERATED { + true, + ..., + failure +} + +RRC-Version ::= SEQUENCE { + latest-RRC-Version BIT STRING (SIZE(3)), + iE-Extensions ProtocolExtensionContainer { { RRC-Version-ExtIEs } } OPTIONAL} + +RRC-Version-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-latest-RRC-Version-Enhanced CRITICALITY ignore EXTENSION OCTET STRING (SIZE(3)) PRESENCE optional }, + ... +} + +RoutingID ::= OCTET STRING + +-- S + +SCell-FailedtoSetup-Item ::= SEQUENCE { + sCell-ID NRCGI , + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { SCell-FailedtoSetup-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-FailedtoSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SCell-FailedtoSetupMod-Item ::= SEQUENCE { + sCell-ID NRCGI , + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { SCell-FailedtoSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-FailedtoSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SCell-ToBeRemoved-Item ::= SEQUENCE { + sCell-ID NRCGI , + iE-Extensions ProtocolExtensionContainer { { SCell-ToBeRemoved-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-ToBeRemoved-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SCell-ToBeSetup-Item ::= SEQUENCE { + sCell-ID NRCGI , + sCellIndex SCellIndex, + sCellULConfigured CellULConfigured OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SCell-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ServingCellMO CRITICALITY ignore EXTENSION ServingCellMO PRESENCE optional }, + ... +} + +SCell-ToBeSetupMod-Item ::= SEQUENCE { + sCell-ID NRCGI , + sCellIndex SCellIndex, + sCellULConfigured CellULConfigured OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SCell-ToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ServingCellMO CRITICALITY ignore EXTENSION ServingCellMO PRESENCE optional }, + ... +} + +SCellIndex ::=INTEGER (1..31, ...) + +SCS-SpecificCarrier ::= SEQUENCE { + offsetToCarrier INTEGER (0..2199,...), + subcarrierSpacing ENUMERATED {kHz15, kHz30, kHz60, kHz120,...}, + carrierBandwidth INTEGER (0..275,...), + iE-Extensions ProtocolExtensionContainer { { SCS-SpecificCarrier-ExtIEs } } OPTIONAL +} + +SCS-SpecificCarrier-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Search-window-information ::= SEQUENCE { + expectedPropagationDelay INTEGER (-3841..3841,...), + delayUncertainty INTEGER (1..246,...), + iE-Extensions ProtocolExtensionContainer { { Search-window-information-ExtIEs } } OPTIONAL +} + +Search-window-information-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SerialNumber ::= BIT STRING (SIZE (16)) + +SIBType-PWS ::=INTEGER (6..8, ...) + +SelectedBandCombinationIndex ::= OCTET STRING + +SelectedFeatureSetEntryIndex ::= OCTET STRING + +CG-ConfigInfo ::= OCTET STRING + +ServCellIndex ::= INTEGER (0..31, ...) + +ServingCellMO ::= INTEGER (1..64, ...) + +Served-Cell-Information ::= SEQUENCE { + nRCGI NRCGI, + nRPCI NRPCI, + fiveGS-TAC FiveGS-TAC OPTIONAL, + configured-EPS-TAC Configured-EPS-TAC OPTIONAL, + servedPLMNs ServedPLMNs-List, + nR-Mode-Info NR-Mode-Info, + measurementTimingConfiguration OCTET STRING, + iE-Extensions ProtocolExtensionContainer { {Served-Cell-Information-ExtIEs} } OPTIONAL, + ... +} + +Served-Cell-Information-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-RANAC CRITICALITY ignore EXTENSION RANAC PRESENCE optional }| + { ID id-ExtendedServedPLMNs-List CRITICALITY ignore EXTENSION ExtendedServedPLMNs-List PRESENCE optional }| + { ID id-Cell-Direction CRITICALITY ignore EXTENSION Cell-Direction PRESENCE optional }| + { ID id-BPLMN-ID-Info-List CRITICALITY ignore EXTENSION BPLMN-ID-Info-List PRESENCE optional }| + { ID id-Cell-Type CRITICALITY ignore EXTENSION CellType PRESENCE optional}| + { ID id-ConfiguredTACIndication CRITICALITY ignore EXTENSION ConfiguredTACIndication PRESENCE optional }| + { ID id-AggressorgNBSetID CRITICALITY ignore EXTENSION AggressorgNBSetID PRESENCE optional}| + { ID id-VictimgNBSetID CRITICALITY ignore EXTENSION VictimgNBSetID PRESENCE optional}| + { ID id-IAB-Info-IAB-DU CRITICALITY ignore EXTENSION IAB-Info-IAB-DU PRESENCE optional}| + { ID id-SSB-PositionsInBurst CRITICALITY ignore EXTENSION SSB-PositionsInBurst PRESENCE optional }| + { ID id-NRPRACHConfig CRITICALITY ignore EXTENSION NRPRACHConfig PRESENCE optional }, + ... +} + +Served-Cells-To-Add-Item ::= SEQUENCE { + served-Cell-Information Served-Cell-Information, + gNB-DU-System-Information GNB-DU-System-Information OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Served-Cells-To-Add-ItemExtIEs} } OPTIONAL, + ... +} + +Served-Cells-To-Add-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Served-Cells-To-Delete-Item ::= SEQUENCE { + oldNRCGI NRCGI , + iE-Extensions ProtocolExtensionContainer { { Served-Cells-To-Delete-ItemExtIEs } } OPTIONAL, + ... +} + +Served-Cells-To-Delete-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Served-Cells-To-Modify-Item ::= SEQUENCE { + oldNRCGI NRCGI , + served-Cell-Information Served-Cell-Information , + gNB-DU-System-Information GNB-DU-System-Information OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { Served-Cells-To-Modify-ItemExtIEs } } OPTIONAL, + ... +} + +Served-Cells-To-Modify-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Served-EUTRA-Cells-Information::= SEQUENCE { + eUTRA-Mode-Info EUTRA-Mode-Info, + protectedEUTRAResourceIndication ProtectedEUTRAResourceIndication, + iE-Extensions ProtocolExtensionContainer { {Served-EUTRA-Cell-Information-ExtIEs} } OPTIONAL, + ... +} + +Served-EUTRA-Cell-Information-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Service-State ::= ENUMERATED { + in-service, + out-of-service, + ... +} + +Service-Status ::= SEQUENCE { + service-state Service-State, + switchingOffOngoing ENUMERATED {true, ...} OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Service-Status-ExtIEs } } OPTIONAL, + ... +} + +Service-Status-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +SFNInitialisationTime ::= BIT STRING (SIZE (64)) + +ShortDRXCycleLength ::= ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, ...} + +ShortDRXCycleTimer ::= INTEGER (1..16) + +SIB1-message ::= OCTET STRING + +SIB10-message ::= OCTET STRING + +SIB12-message ::= OCTET STRING + +SIB13-message ::= OCTET STRING + +SIB14-message ::= OCTET STRING + +SItype ::= INTEGER (1..32, ...) + +SItype-List ::= SEQUENCE (SIZE(1.. maxnoofSITypes)) OF SItype-Item + +SItype-Item ::= SEQUENCE { + sItype SItype , + iE-Extensions ProtocolExtensionContainer { { SItype-ItemExtIEs } } OPTIONAL +} + +SItype-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SibtypetobeupdatedListItem ::= SEQUENCE { + sIBtype INTEGER (2..32,...), + sIBmessage OCTET STRING, + valueTag INTEGER (0..31,...), + iE-Extensions ProtocolExtensionContainer { { SibtypetobeupdatedListItem-ExtIEs } } OPTIONAL, + ... +} + +SibtypetobeupdatedListItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-areaScope CRITICALITY ignore EXTENSION AreaScope PRESENCE optional}, + ... +} + +SLDRBID ::= INTEGER (1..512, ...) + +SLDRBInformation ::= SEQUENCE { + sLDRB-QoS PC5QoSParameters, + flowsMappedToSLDRB-List FlowsMappedToSLDRB-List, + ... +} + +SLDRBs-FailedToBeModified-Item ::= SEQUENCE { + sLDRBID SLDRBID , + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-FailedToBeModified-ItemExtIEs } } OPTIONAL +} + +SLDRBs-FailedToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-FailedToBeSetup-Item ::= SEQUENCE { + sLDRBID SLDRBID, + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-FailedToBeSetup-ItemExtIEs } } OPTIONAL +} + +SLDRBs-FailedToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-FailedToBeSetupMod-Item ::= SEQUENCE { + sLDRBID SLDRBID , + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { SLDRBs-FailedToBeSetupMod-ItemExtIEs } } OPTIONAL +} + +SLDRBs-FailedToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-Modified-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-Modified-ItemExtIEs } } OPTIONAL +} + +SLDRBs-Modified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ModifiedConf-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ModifiedConf-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ModifiedConf-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-Required-ToBeModified-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-Required-ToBeModified-ItemExtIEs } } OPTIONAL +} + +SLDRBs-Required-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-Required-ToBeReleased-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-Required-ToBeReleased-ItemExtIEs } } OPTIONAL +} + +SLDRBs-Required-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-Setup-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-Setup-ItemExtIEs } } OPTIONAL +} + +SLDRBs-Setup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-SetupMod-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-SetupMod-ItemExtIEs } } OPTIONAL +} + +SLDRBs-SetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ToBeModified-Item ::= SEQUENCE { + sLDRBID SLDRBID, + sLDRBInformation SLDRBInformation OPTIONAL, + rLCMode RLCMode OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ToBeModified-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ToBeReleased-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ToBeReleased-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ToBeSetup-Item ::= SEQUENCE { + sLDRBID SLDRBID, + sLDRBInformation SLDRBInformation, + rLCMode RLCMode, + + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ToBeSetup-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ToBeSetupMod-Item ::= SEQUENCE { + sLDRBID SLDRBID, + sLDRBInformation SLDRBInformation, + rLCMode RLCMode OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ToBeSetupMod-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SL-PHY-MAC-RLC-Config ::= OCTET STRING + +SL-ConfigDedicatedEUTRA ::= OCTET STRING + +SliceAvailableCapacity ::= SEQUENCE { + sliceAvailableCapacityList SliceAvailableCapacityList, + iE-Extensions ProtocolExtensionContainer { { SliceAvailableCapacity-ExtIEs} } OPTIONAL +} + +SliceAvailableCapacity-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SliceAvailableCapacityList ::= SEQUENCE (SIZE(1.. maxnoofBPLMNsNR)) OF SliceAvailableCapacityItem + +SliceAvailableCapacityItem ::= SEQUENCE { + pLMNIdentity PLMN-Identity, + sNSSAIAvailableCapacity-List SNSSAIAvailableCapacity-List, + iE-Extensions ProtocolExtensionContainer { { SliceAvailableCapacityItem-ExtIEs} } OPTIONAL +} + +SliceAvailableCapacityItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SNSSAIAvailableCapacity-List ::= SEQUENCE (SIZE(1.. maxnoofSliceItems)) OF SNSSAIAvailableCapacity-Item + +SNSSAIAvailableCapacity-Item ::= SEQUENCE { + sNSSAI SNSSAI, + sliceAvailableCapacityValueDownlink INTEGER (0..100) OPTIONAL, + sliceAvailableCapacityValueUplink INTEGER (0..100) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SNSSAIAvailableCapacity-Item-ExtIEs } } OPTIONAL +} + +SNSSAIAvailableCapacity-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SliceSupportList ::= SEQUENCE (SIZE(1.. maxnoofSliceItems)) OF SliceSupportItem + +SliceSupportItem ::= SEQUENCE { + sNSSAI SNSSAI, + iE-Extensions ProtocolExtensionContainer { { SliceSupportItem-ExtIEs } } OPTIONAL +} + +SliceSupportItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SliceToReportList ::= SEQUENCE (SIZE(1.. maxnoofBPLMNsNR)) OF SliceToReportItem + +SliceToReportItem ::= SEQUENCE { + pLMNIdentity PLMN-Identity, + sNSSAIlist SNSSAI-list, + iE-Extensions ProtocolExtensionContainer { { SliceToReportItem-ExtIEs} } OPTIONAL +} + +SliceToReportItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SlotNumber ::= INTEGER (0..79) + +SNSSAI-list ::= SEQUENCE (SIZE(1.. maxnoofSliceItems)) OF SNSSAI-Item + +SNSSAI-Item ::= SEQUENCE { + sNSSAI SNSSAI, + iE-Extensions ProtocolExtensionContainer { { SNSSAI-Item-ExtIEs } } OPTIONAL +} + +SNSSAI-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Slot-Configuration-List ::= SEQUENCE (SIZE(1.. maxnoofslots)) OF Slot-Configuration-Item + +Slot-Configuration-Item ::= SEQUENCE { + slotIndex INTEGER (0..5119, ...), + symbolAllocInSlot SymbolAllocInSlot, + iE-Extensions ProtocolExtensionContainer { { Slot-Configuration-ItemExtIEs } } OPTIONAL +} + +Slot-Configuration-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +SNSSAI ::= SEQUENCE { + sST OCTET STRING (SIZE(1)), + sD OCTET STRING (SIZE(3)) OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { SNSSAI-ExtIEs } } OPTIONAL +} + +SNSSAI-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SpatialDirectionInformation ::= SEQUENCE { + nR-PRSBeamInformation NR-PRSBeamInformation, + iE-Extensions ProtocolExtensionContainer { { SpatialDirectionInformation-ExtIEs } } OPTIONAL +} + +SpatialDirectionInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SpatialRelationInfo ::= SEQUENCE { + spatialRelationforResourceID SpatialRelationforResourceID, + iE-Extensions ProtocolExtensionContainer { {SpatialRelationInfo-ExtIEs} } OPTIONAL +} + +SpatialRelationInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SpatialRelationforResourceID ::= SEQUENCE (SIZE(1..maxnoofSpatialRelations)) OF SpatialRelationforResourceIDItem + +SpatialRelationforResourceIDItem ::= SEQUENCE { + referenceSignal ReferenceSignal, + iE-Extensions ProtocolExtensionContainer { {SpatialRelationforResourceIDItem-ExtIEs} } OPTIONAL +} + +SpatialRelationforResourceIDItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SpatialRelationPos ::= CHOICE { + sSBPos SSBPos, + pRSInformationPos PRSInformationPos, + choice-extension ProtocolIE-SingleContainer {{ SpatialInformationPos-ExtIEs }} +} + +SpatialInformationPos-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SpectrumSharingGroupID ::= INTEGER (1..maxCellineNB) + +SRBID ::= INTEGER (0..3, ...) + +SRBs-FailedToBeSetup-Item ::= SEQUENCE { + sRBID SRBID , + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRBs-FailedToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-FailedToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-FailedToBeSetupMod-Item ::= SEQUENCE { + sRBID SRBID , + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRBs-FailedToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-FailedToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-Modified-Item ::= SEQUENCE { + sRBID SRBID, + lCID LCID, + iE-Extensions ProtocolExtensionContainer { { SRBs-Modified-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-Modified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-Required-ToBeReleased-Item ::= SEQUENCE { + sRBID SRBID, + iE-Extensions ProtocolExtensionContainer { { SRBs-Required-ToBeReleased-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-Required-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-Setup-Item ::= SEQUENCE { + sRBID SRBID, + lCID LCID, + iE-Extensions ProtocolExtensionContainer { { SRBs-Setup-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-Setup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-SetupMod-Item ::= SEQUENCE { + sRBID SRBID, + lCID LCID, + iE-Extensions ProtocolExtensionContainer { { SRBs-SetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-SetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-ToBeReleased-Item ::= SEQUENCE { + sRBID SRBID, + iE-Extensions ProtocolExtensionContainer { { SRBs-ToBeReleased-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-ToBeSetup-Item ::= SEQUENCE { + sRBID SRBID , + duplicationIndication DuplicationIndication OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRBs-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalDuplicationIndication CRITICALITY ignore EXTENSION AdditionalDuplicationIndication PRESENCE optional }, + ... +} + +SRBs-ToBeSetupMod-Item ::= SEQUENCE { + sRBID SRBID, + duplicationIndication DuplicationIndication OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRBs-ToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalDuplicationIndication CRITICALITY ignore EXTENSION AdditionalDuplicationIndication PRESENCE optional }, + ... +} + +SRSCarrier-List ::= SEQUENCE (SIZE(1.. maxnoSRS-Carriers)) OF SRSCarrier-List-Item + +SRSCarrier-List-Item ::= SEQUENCE { + pointA INTEGER (0..3279165,...), + uplinkChannelBW-PerSCS-List UplinkChannelBW-PerSCS-List, + activeULBWP ActiveULBWP, + pci NRPCI, + iE-Extensions ProtocolExtensionContainer { { SRSCarrier-List-Item-ExtIEs } } OPTIONAL +} + +SRSCarrier-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSConfig ::= SEQUENCE { + sRSResource-List SRSResource-List OPTIONAL, + posSRSResource-List PosSRSResource-List OPTIONAL, + sRSResourceSet-List SRSResourceSet-List OPTIONAL, + posSRSResourceSet-List PosSRSResourceSet-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRSConfig-ExtIEs } } OPTIONAL +} + +SRSConfig-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSConfiguration ::= SEQUENCE { + sRSCarrier-List SRSCarrier-List, + iE-Extensions ProtocolExtensionContainer { { SRSConfiguration-ExtIEs } } OPTIONAL +} + +SRSConfiguration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSPosResourceID ::= INTEGER (0..63, ...) + +SRSResource::= SEQUENCE { + sRSResourceID SRSResourceID, + nrofSRS-Ports ENUMERATED {port1, ports2, ports4}, + transmissionComb TransmissionComb, + startPosition INTEGER (0..13), + nrofSymbols ENUMERATED {n1, n2, n4}, + repetitionFactor ENUMERATED {n1, n2, n4}, + freqDomainPosition INTEGER (0..67), + freqDomainShift INTEGER (0..268), + c-SRS INTEGER (0..63), + b-SRS INTEGER (0..3), + b-hop INTEGER (0..3), + groupOrSequenceHopping ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceType ResourceType, + slotOffset INTEGER (0..2559), + sequenceId INTEGER (0..1023), + iE-Extensions ProtocolExtensionContainer { { SRSResource-ExtIEs } } OPTIONAL +} + +SRSResource-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSResourceID ::= INTEGER (0..63, ...) + +SRSResourceID-List::= SEQUENCE (SIZE (1..maxnoSRS-ResourcePerSet)) OF SRSResourceID + +SRSResource-List ::= SEQUENCE (SIZE (1..maxnoSRS-Resources)) OF SRSResource + +SRSResourceSet::= SEQUENCE { + sRSResourceSetID SRSResourceSetID, + sRSResourceID-List SRSResourceID-List, + resourceSetType ResourceSetType, + iE-Extensions ProtocolExtensionContainer { { SRSResourceSet-ExtIEs } } OPTIONAL +} + +SRSResourceSet-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSResourceSetID ::= INTEGER (0..15, ...) + +SRSResourceSetList ::= SEQUENCE (SIZE(1.. maxnoSRS-ResourceSets)) OF SRSResourceSetItem + +SRSResourceSetItem ::= SEQUENCE { + numSRSresourcesperset INTEGER (1..16, ...) OPTIONAL, + periodicityList PeriodicityList OPTIONAL, + spatialRelationInfo SpatialRelationInfo OPTIONAL, + pathlossReferenceInfo PathlossReferenceInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRSResourceSetItemExtIEs } } OPTIONAL +} + +SRSResourceSetItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSResourceSet-List ::= SEQUENCE (SIZE (1..maxnoSRS-ResourceSets)) OF SRSResourceSet + +SRSResourceTrigger ::= SEQUENCE { + aperiodicSRSResourceTriggerList AperiodicSRSResourceTriggerList, + iE-Extensions ProtocolExtensionContainer { {SRSResourceTrigger-ExtIEs} } OPTIONAL +} + +SRSResourceTrigger-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSSpatialRelation ::= SEQUENCE { + spatialRelationforResourceID SpatialRelationforResourceID, + iE-Extensions ProtocolExtensionContainer { {SRSSpatialRelation-ExtIEs} } OPTIONAL +} + +SRSSpatialRelation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSB ::= SEQUENCE { + pCI-NR NRPCI, + ssb-index SSB-Index OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {SSB-ExtIEs} } OPTIONAL +} + +SSB-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSB-freqInfo ::= INTEGER (0..maxNRARFCN) + +SSB-Index ::= INTEGER(0..63) + +SSBPos ::= SEQUENCE { + pCI-NR NRPCI OPTIONAL, + ssb-index SSB-Index, + iE-Extensions ProtocolExtensionContainer { {SSBPos-ExtIEs} } OPTIONAL +} + +SSBPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSB-subcarrierSpacing ::= ENUMERATED {kHz15, kHz30, kHz120, kHz240, spare3, spare2, spare1, ...} + +SSB-transmissionPeriodicity ::= ENUMERATED {sf10, sf20, sf40, sf80, sf160, sf320, sf640, ...} + +SSB-transmissionTimingOffset ::= INTEGER (0..127, ...) + +SSB-transmissionBitmap ::= CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)), + choice-extension ProtocolIE-SingleContainer { { SSB-transmisisonBitmap-ExtIEs} } +} + +SSB-transmisisonBitmap-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SSBAreaCapacityValueList ::= SEQUENCE (SIZE(1.. maxnoofSSBAreas)) OF SSBAreaCapacityValueItem + +SSBAreaCapacityValueItem ::= SEQUENCE { + sSBIndex INTEGER(0..63), + sSBAreaCapacityValue INTEGER (0..100), + iE-Extensions ProtocolExtensionContainer { { SSBAreaCapacityValueItem-ExtIEs} } OPTIONAL +} + +SSBAreaCapacityValueItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSBAreaRadioResourceStatusList::= SEQUENCE (SIZE(1.. maxnoofSSBAreas)) OF SSBAreaRadioResourceStatusItem + +SSBAreaRadioResourceStatusItem::= SEQUENCE { + sSBIndex INTEGER(0..63), + sSBAreaDLGBRPRBusage INTEGER (0..100), + sSBAreaULGBRPRBusage INTEGER (0..100), + sSBAreaDLnon-GBRPRBusage INTEGER (0..100), + sSBAreaULnon-GBRPRBusage INTEGER (0..100), + sSBAreaDLTotalPRBusage INTEGER (0..100), + sSBAreaULTotalPRBusage INTEGER (0..100), + dLschedulingPDCCHCCEusage INTEGER (0..100) OPTIONAL, + uLschedulingPDCCHCCEusage INTEGER (0..100) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SSBAreaRadioResourceStatusItem-ExtIEs} } OPTIONAL +} + +SSBAreaRadioResourceStatusItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSBInformation ::= SEQUENCE { + sSBInformationList SSBInformationList, + iE-Extensions ProtocolExtensionContainer { { SSBInformation-ExtIEs } } OPTIONAL +} + +SSBInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSBInformationList ::= SEQUENCE (SIZE(1.. maxnoofSSBs)) OF SSBInformationItem + +SSBInformationItem ::= SEQUENCE { + sSB-Configuration SSB-TF-Configuration, + pCI-NR NRPCI, + iE-Extensions ProtocolExtensionContainer { { SSBInformationItem-ExtIEs } } OPTIONAL +} + +SSBInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSB-PositionsInBurst ::= CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)), + choice-extension ProtocolIE-SingleContainer { {SSB-PositionsInBurst-ExtIEs} } +} + +SSB-PositionsInBurst-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SSB-TF-Configuration ::= SEQUENCE { + sSB-frequency INTEGER (0..3279165), + sSB-subcarrier-spacing ENUMERATED {kHz15, kHz30, kHz60, kHz120, kHz240, ...}, + sSB-Transmit-power INTEGER (-60..50), + sSB-periodicity ENUMERATED {ms5, ms10, ms20, ms40, ms80, ms160, ...}, + sSB-half-frame-offset INTEGER(0..1), + sSB-SFN-offset INTEGER(0..15), + sSB-position-in-burst SSB-PositionsInBurst OPTIONAL, + sFNInitialisationTime SFNInitialisationTime OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SSB-TF-Configuration-ExtIEs} } OPTIONAL +} + +SSB-TF-Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +SSBToReportList ::= SEQUENCE (SIZE(1.. maxnoofSSBAreas)) OF SSBToReportItem + +SSBToReportItem ::= SEQUENCE { + sSBIndex INTEGER(0..63), + iE-Extensions ProtocolExtensionContainer { { SSBToReportItem-ExtIEs} } OPTIONAL +} + +SSBToReportItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SUL-Information ::= SEQUENCE { + sUL-NRARFCN INTEGER (0..maxNRARFCN), + sUL-transmission-Bandwidth Transmission-Bandwidth, + iE-Extensions ProtocolExtensionContainer { { SUL-InformationExtIEs} } OPTIONAL, + ... +} + +SUL-InformationExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-CarrierList CRITICALITY ignore EXTENSION NRCarrierList PRESENCE optional }| + { ID id-FrequencyShift7p5khz CRITICALITY ignore EXTENSION FrequencyShift7p5khz PRESENCE optional }, + ... +} + +SubcarrierSpacing ::= ENUMERATED { kHz15, kHz30, kHz60, kHz120, kHz240, spare3, spare2, spare1, ...} + +SubscriberProfileIDforRFP ::= INTEGER (1..256, ...) + +SULAccessIndication ::= ENUMERATED {true,...} + + +SupportedSULFreqBandItem ::= SEQUENCE { + freqBandIndicatorNr INTEGER (1..1024,...), + iE-Extensions ProtocolExtensionContainer { { SupportedSULFreqBandItem-ExtIEs} } OPTIONAL, + ... +} + +SupportedSULFreqBandItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SymbolAllocInSlot ::= CHOICE { + all-DL NULL, + all-UL NULL, + both-DL-and-UL NumDLULSymbols, + choice-extension ProtocolIE-SingleContainer { { SymbolAllocInSlot-ExtIEs } } +} + +SymbolAllocInSlot-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SystemFrameNumber ::= INTEGER (0..1023) + +SystemInformationAreaID ::=BIT STRING (SIZE (24)) + +-- T + +FiveGS-TAC ::= OCTET STRING (SIZE(3)) + +Configured-EPS-TAC ::= OCTET STRING (SIZE(2)) + +TargetCellList ::= SEQUENCE (SIZE(1..maxnoofCHOcells)) OF TargetCellList-Item + +TargetCellList-Item ::= SEQUENCE { + target-cell NRCGI, + iE-Extensions ProtocolExtensionContainer { { TargetCellList-Item-ExtIEs} } OPTIONAL +} + +TargetCellList-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TDD-Info ::= SEQUENCE { + nRFreqInfo NRFreqInfo, + transmission-Bandwidth Transmission-Bandwidth, + iE-Extensions ProtocolExtensionContainer { {TDD-Info-ExtIEs} } OPTIONAL, + ... +} + +TDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-IntendedTDD-DL-ULConfig CRITICALITY ignore EXTENSION IntendedTDD-DL-ULConfig PRESENCE optional}| + {ID id-TDD-UL-DLConfigCommonNR CRITICALITY ignore EXTENSION TDD-UL-DLConfigCommonNR PRESENCE optional }| + {ID id-CarrierList CRITICALITY ignore EXTENSION NRCarrierList PRESENCE optional }, + ... +} + +TDD-UL-DLConfigCommonNR ::= OCTET STRING + +TimeReferenceInformation ::= SEQUENCE { + referenceTime ReferenceTime, + referenceSFN ReferenceSFN, + uncertainty Uncertainty, + timeInformationType TimeInformationType, + iE-Extensions ProtocolExtensionContainer { {TimeReferenceInformation-ExtIEs} } OPTIONAL +} + +TimeReferenceInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TimeInformationType ::= ENUMERATED {localClock} + +TimeStamp ::= SEQUENCE { + systemFrameNumber SystemFrameNumber, + slotIndex TimeStampSlotIndex, + measurementTime SFNInitialisationTime OPTIONAL, + iE-Extension ProtocolExtensionContainer { { TimeStamp-ExtIEs} } OPTIONAL +} + +TimeStamp-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TimeStampSlotIndex ::= CHOICE { + sCS-15 INTEGER(0..9), + sCS-30 INTEGER(0..19), + sCS-60 INTEGER(0..39), + sCS-120 INTEGER(0..79), + choice-extension ProtocolIE-SingleContainer { { TimeStampSlotIndex-ExtIEs} } +} + +TimeStampSlotIndex-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TimeToWait ::= ENUMERATED {v1s, v2s, v5s, v10s, v20s, v60s, ...} + +TimingMeasurementQuality ::= SEQUENCE { + measurementQuality INTEGER(0..31), + resolution ENUMERATED{m0dot1, m1, m10, m30, ...}, + iE-Extensions ProtocolExtensionContainer { { TimingMeasurementQuality-ExtIEs} } OPTIONAL +} + +TimingMeasurementQuality-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TNLAssociationUsage ::= ENUMERATED { + ue, + non-ue, + both, + ... +} + +TNLCapacityIndicator::= SEQUENCE { + dLTNLOfferedCapacity INTEGER (1.. 16777216,...), + dLTNLAvailableCapacity INTEGER (0.. 100,...), + uLTNLOfferedCapacity INTEGER (1.. 16777216,...), + uLTNLAvailableCapacity INTEGER (0.. 100,...), + iE-Extensions ProtocolExtensionContainer { { TNLCapacityIndicator-ExtIEs} } OPTIONAL +} + +TNLCapacityIndicator-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TraceActivation ::= SEQUENCE { + traceID TraceID, + interfacesToTrace InterfacesToTrace, + traceDepth TraceDepth, + traceCollectionEntityIPAddress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { {TraceActivation-ExtIEs} } OPTIONAL +} + +TraceActivation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-mdtConfiguration CRITICALITY ignore EXTENSION MDTConfiguration PRESENCE optional}| + {ID id-TraceCollectionEntityURI CRITICALITY ignore EXTENSION URI-address PRESENCE optional }, + ... +} + +TraceDepth ::= ENUMERATED { + minimum, + medium, + maximum, + minimumWithoutVendorSpecificExtension, + mediumWithoutVendorSpecificExtension, + maximumWithoutVendorSpecificExtension, + ... +} + +TraceID ::= OCTET STRING (SIZE(8)) + +TrafficMappingInfo ::= CHOICE { + iPtolayer2TrafficMappingInfo IPtolayer2TrafficMappingInfo, + bAPlayerBHRLCchannelMappingInfo BAPlayerBHRLCchannelMappingInfo, + choice-extension ProtocolIE-SingleContainer { { TrafficMappingInfo-ExtIEs} } +} + +TrafficMappingInfo-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TransportLayerAddress ::= BIT STRING (SIZE(1..160, ...)) + +TransactionID ::= INTEGER (0..255, ...) + +Transmission-Bandwidth ::= SEQUENCE { + nRSCS NRSCS, + nRNRB NRNRB, + iE-Extensions ProtocolExtensionContainer { { Transmission-Bandwidth-ExtIEs} } OPTIONAL, + ... +} + +Transmission-Bandwidth-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TransmissionComb ::= CHOICE { + n2 SEQUENCE { + combOffset-n2 INTEGER (0..1), + cyclicShift-n2 INTEGER (0..7) + }, + n4 SEQUENCE { + combOffset-n4 INTEGER (0..3), + cyclicShift-n4 INTEGER (0..11) + }, + choice-extension ProtocolIE-SingleContainer { { TransmissionComb-ExtIEs} } +} +TransmissionComb-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TransmissionCombPos ::= CHOICE { + n2 SEQUENCE { + combOffset-n2 INTEGER (0..1), + cyclicShift-n2 INTEGER (0..7) + }, + n4 SEQUENCE { + combOffset-n4 INTEGER (0..3), + cyclicShift-n4 INTEGER (0..11) + }, + n8 SEQUENCE { + combOffset-n8 INTEGER (0..7), + cyclicShift-n8 INTEGER (0..5) + }, + + choice-extension ProtocolIE-SingleContainer { { TransmissionCombPos-ExtIEs} } +} +TransmissionCombPos-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +Transport-UP-Layer-Address-Info-To-Add-List ::= SEQUENCE (SIZE(1.. maxnoofTLAs)) OF Transport-UP-Layer-Address-Info-To-Add-Item + +Transport-UP-Layer-Address-Info-To-Add-Item ::= SEQUENCE { + iP-SecTransportLayerAddress TransportLayerAddress, + gTPTransportLayerAddressToAdd GTPTLAs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Transport-UP-Layer-Address-Info-To-Add-ItemExtIEs } } OPTIONAL +} + +Transport-UP-Layer-Address-Info-To-Add-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Transport-UP-Layer-Address-Info-To-Remove-List ::= SEQUENCE (SIZE(1.. maxnoofTLAs)) OF Transport-UP-Layer-Address-Info-To-Remove-Item + +Transport-UP-Layer-Address-Info-To-Remove-Item ::= SEQUENCE { + iP-SecTransportLayerAddress TransportLayerAddress, + gTPTransportLayerAddressToRemove GTPTLAs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Transport-UP-Layer-Address-Info-To-Remove-ItemExtIEs } } OPTIONAL +} + +Transport-UP-Layer-Address-Info-To-Remove-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TransmissionActionIndicator ::= ENUMERATED {stop, ..., restart } + +TRPID ::= INTEGER (0.. maxnoofTRPs, ...) + +TRPInformation ::= SEQUENCE { + tRPID TRPID, + tRPInformationTypeResponseList TRPInformationTypeResponseList, + iE-Extensions ProtocolExtensionContainer { { TRPInformation-ExtIEs } } OPTIONAL +} + +TRPInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPInformationItem ::= SEQUENCE { + tRPInformation TRPInformation, + iE-Extensions ProtocolExtensionContainer { { TRPInformationItem-ExtIEs } } OPTIONAL +} + +TRPInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPInformationTypeItem ::= ENUMERATED { + nrPCI, + nG-RAN-CGI, + arfcn, + pRSConfig, + sSBConfig, + sFNInitTime, + spatialDirectInfo, + geoCoord, +...} + + +TRPInformationTypeResponseList ::= SEQUENCE (SIZE(1.. maxnoofTRPInfoTypes)) OF TRPInformationTypeResponseItem + +TRPInformationTypeResponseItem ::= CHOICE { + pCI-NR NRPCI, + nG-RAN-CGI NRCGI, + nRARFCN INTEGER (0..maxNRARFCN), + pRSConfiguration PRSConfiguration, + sSBinformation SSBInformation, + sFNInitialisationTime SFNInitialisationTime, + spatialDirectionInformation SpatialDirectionInformation, + geographicalCoordinates GeographicalCoordinates, + choice-extension ProtocolIE-SingleContainer { { TRPInformationTypeResponseItem-ExtIEs} } +} + +TRPInformationTypeResponseItem-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +TRPList ::= SEQUENCE (SIZE(1.. maxnoofTRPs)) OF TRPListItem + +TRPListItem ::= SEQUENCE { + tRPID TRPID, + iE-Extensions ProtocolExtensionContainer { { TRPListItem-ExtIEs } } OPTIONAL +} + +TRPListItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPMeasurementQuality ::= SEQUENCE { + tRPmeasurementQuality-Item TRPMeasurementQuality-Item, + iE-Extensions ProtocolExtensionContainer { {TRPMeasurementQuality-ExtIEs} } OPTIONAL +} + +TRPMeasurementQuality-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPMeasurementQuality-Item ::= CHOICE { + timingMeasurementQuality TimingMeasurementQuality, + angleMeasurementQuality AngleMeasurementQuality, + choice-extension ProtocolIE-SingleContainer { { TRPMeasurementQuality-Item-ExtIEs } } +} + +TRPMeasurementQuality-Item-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TRP-MeasurementRequestList ::= SEQUENCE (SIZE (1..maxNoOfMeasTRPs)) OF TRP-MeasurementRequestItem + +TRP-MeasurementRequestItem ::= SEQUENCE { + tRPID TRPID, + search-window-information Search-window-information OPTIONAL, + iE-extensions ProtocolExtensionContainer { { TRP-MeasurementRequestItem-ExtIEs } } OPTIONAL +} + +TRP-MeasurementRequestItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPPositionDefinitionType ::= CHOICE { + direct TRPPositionDirect, + referenced TRPPositionReferenced, + choice-extension ProtocolIE-SingleContainer { { TRPPositionDefinitionType-ExtIEs } } +} + +TRPPositionDefinitionType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TRPPositionDirect ::= SEQUENCE { + accuracy TRPPositionDirectAccuracy, + iE-extensions ProtocolExtensionContainer { { TRPPositionDirect-ExtIEs } } OPTIONAL +} + +TRPPositionDirect-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPPositionDirectAccuracy ::= CHOICE { + tRPPosition AccessPointPosition, + tRPHAposition NGRANHighAccuracyAccessPointPosition, + choice-extension ProtocolIE-SingleContainer { { TRPPositionDirectAccuracy-ExtIEs } } +} + +TRPPositionDirectAccuracy-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TRPPositionReferenced ::= SEQUENCE { + referencePoint ReferencePoint, + referencePointType TRPReferencePointType, + iE-extensions ProtocolExtensionContainer { { TRPPositionReferenced-ExtIEs } } OPTIONAL +} + +TRPPositionReferenced-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPReferencePointType ::= CHOICE { + tRPPositionRelativeGeodetic RelativeGeodeticLocation, + tRPPositionRelativeCartesian RelativeCartesianLocation, + choice-extension ProtocolIE-SingleContainer { { TRPReferencePointType-ExtIEs } } +} + +TRPReferencePointType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TypeOfError ::= ENUMERATED { + not-understood, + missing, + ... +} + +Transport-Layer-Address-Info ::= SEQUENCE { + transport-UP-Layer-Address-Info-To-Add-List Transport-UP-Layer-Address-Info-To-Add-List OPTIONAL, + transport-UP-Layer-Address-Info-To-Remove-List Transport-UP-Layer-Address-Info-To-Remove-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Transport-Layer-Address-Info-ExtIEs } } OPTIONAL +} + +Transport-Layer-Address-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TSCAssistanceInformation ::= SEQUENCE { + periodicity Periodicity, + burstArrivalTime BurstArrivalTime OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {TSCAssistanceInformation-ExtIEs} } OPTIONAL, + ... +} + +TSCAssistanceInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TSCTrafficCharacteristics ::= SEQUENCE { + tSCAssistanceInformationDL TSCAssistanceInformation OPTIONAL, + tSCAssistanceInformationUL TSCAssistanceInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {TSCTrafficCharacteristics-ExtIEs} } OPTIONAL, + ... +} + +TSCTrafficCharacteristics-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- U +UAC-Assistance-Info ::= SEQUENCE { + uACPLMN-List UACPLMN-List, + iE-Extensions ProtocolExtensionContainer { { UAC-Assistance-InfoExtIEs} } OPTIONAL +} + +UAC-Assistance-InfoExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UACPLMN-List ::= SEQUENCE (SIZE(1..maxnoofUACPLMNs)) OF UACPLMN-Item + +UACPLMN-Item::= SEQUENCE { + pLMNIdentity PLMN-Identity, + uACType-List UACType-List, iE-Extensions ProtocolExtensionContainer { { UACPLMN-Item-ExtIEs} } OPTIONAL +} + +UACPLMN-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-NID CRITICALITY ignore EXTENSION NID PRESENCE optional }, + ... +} + +UACType-List ::= SEQUENCE (SIZE(1..maxnoofUACperPLMN)) OF UACType-Item + +UACType-Item::= SEQUENCE { + uACReductionIndication UACReductionIndication, + uACCategoryType UACCategoryType, + iE-Extensions ProtocolExtensionContainer { { UACType-Item-ExtIEs } } OPTIONAL +} + +UACType-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UACCategoryType ::= CHOICE { + uACstandardized UACAction, + uACOperatorDefined UACOperatorDefined, + choice-extension ProtocolIE-SingleContainer { { UACCategoryType-ExtIEs } } +} + +UACCategoryType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +UACOperatorDefined ::= SEQUENCE { + accessCategory INTEGER (32..63,...), + accessIdentity BIT STRING (SIZE(7)), + iE-Extensions ProtocolExtensionContainer { { UACOperatorDefined-ExtIEs} } OPTIONAL +} + +UACOperatorDefined-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +UACAction ::= ENUMERATED { + reject-non-emergency-mo-dt, + reject-rrc-cr-signalling, + permit-emergency-sessions-and-mobile-terminated-services-only, + permit-high-priority-sessions-and-mobile-terminated-services-only, + ... +} + +UACReductionIndication ::= INTEGER (0..100) + + +UE-associatedLogicalF1-ConnectionItem ::= SEQUENCE { + gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID OPTIONAL, + gNB-DU-UE-F1AP-ID GNB-DU-UE-F1AP-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { UE-associatedLogicalF1-ConnectionItemExtIEs} } OPTIONAL, + ... +} + +UEAssistanceInformation ::= OCTET STRING + +UEAssistanceInformationEUTRA ::= OCTET STRING + +UE-associatedLogicalF1-ConnectionItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UE-CapabilityRAT-ContainerList::= OCTET STRING + +UEContextNotRetrievable ::= ENUMERATED {true, ...} + +UEIdentityIndexValue ::= CHOICE { + indexLength10 BIT STRING (SIZE (10)), + choice-extension ProtocolIE-SingleContainer { {UEIdentityIndexValueChoice-ExtIEs} } +} + +UEIdentityIndexValueChoice-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +UL-AoA ::= SEQUENCE { + azimuthAoA INTEGER (0..3599), + zenithAoA INTEGER (0..1799) OPTIONAL, + angleCoordinateSystem ENUMERATED {lCS, gCS} OPTIONAL, + iE-extensions ProtocolExtensionContainer { { UL-AoA-ExtIEs } } +} + +UL-AoA-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-BH-Non-UP-Traffic-Mapping ::= SEQUENCE { + uL-BH-Non-UP-Traffic-Mapping-List UL-BH-Non-UP-Traffic-Mapping-List, + iE-Extensions ProtocolExtensionContainer { { UL-BH-Non-UP-Traffic-Mapping-ExtIEs } } OPTIONAL +} + +UL-BH-Non-UP-Traffic-Mapping-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-BH-Non-UP-Traffic-Mapping-List ::= SEQUENCE (SIZE(1..maxnoofNonUPTrafficMappings)) OF UL-BH-Non-UP-Traffic-Mapping-Item + +UL-BH-Non-UP-Traffic-Mapping-Item ::= SEQUENCE { + nonUPTrafficType NonUPTrafficType, + bHInfo BHInfo, + iE-Extensions ProtocolExtensionContainer { { UL-BH-Non-UP-Traffic-Mapping-ItemExtIEs } } OPTIONAL +} + +UL-BH-Non-UP-Traffic-Mapping-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ULConfiguration ::= SEQUENCE { + uLUEConfiguration ULUEConfiguration, + iE-Extensions ProtocolExtensionContainer { { ULConfigurationExtIEs } } OPTIONAL, + ... +} +ULConfigurationExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-RTOA-Measurement ::= SEQUENCE { + uL-RTOA-MeasurementItem UL-RTOA-MeasurementItem, + additionalPath-List AdditionalPath-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { UL-RTOA-Measurement-ExtIEs } } OPTIONAL +} + +UL-RTOA-Measurement-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-RTOA-MeasurementItem ::= CHOICE { + k0 INTEGER (0..1970049), + k1 INTEGER (0..985025), + k2 INTEGER (0..492513), + k3 INTEGER (0..246257), + k4 INTEGER (0..123129), + k5 INTEGER (0..61565), + choice-extension ProtocolIE-SingleContainer { { UL-RTOA-MeasurementItem-ExtIEs } } +} + +UL-RTOA-MeasurementItem-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +UL-SRS-RSRP ::= INTEGER (0..127) + +ULUEConfiguration ::= ENUMERATED {no-data, shared, only, ...} + +UL-UP-TNL-Information-to-Update-List-Item ::= SEQUENCE { + uLUPTNLInformation UPTransportLayerInformation, + newULUPTNLInformation UPTransportLayerInformation OPTIONAL, + bHInfo BHInfo, + iE-Extensions ProtocolExtensionContainer { { UL-UP-TNL-Information-to-Update-List-ItemExtIEs } } OPTIONAL, + ... +} + +UL-UP-TNL-Information-to-Update-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-UP-TNL-Address-to-Update-List-Item ::= SEQUENCE { + oldIPAdress TransportLayerAddress, + newIPAdress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { { UL-UP-TNL-Address-to-Update-List-ItemExtIEs } } OPTIONAL, + ... +} + +UL-UP-TNL-Address-to-Update-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ULUPTNLInformation-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofULUPTNLInformation)) OF ULUPTNLInformation-ToBeSetup-Item + +ULUPTNLInformation-ToBeSetup-Item ::=SEQUENCE { + uLUPTNLInformation UPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { { ULUPTNLInformation-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +ULUPTNLInformation-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-BHInfo CRITICALITY ignore EXTENSION BHInfo PRESENCE optional }, + ... +} + +Uncertainty ::= INTEGER (0..32767, ...) + +UplinkChannelBW-PerSCS-List ::= SEQUENCE (SIZE (1..maxnoSCSs)) OF SCS-SpecificCarrier + +UplinkTxDirectCurrentListInformation ::= OCTET STRING + +UPTransportLayerInformation ::= CHOICE { + gTPTunnel GTPTunnel, + choice-extension ProtocolIE-SingleContainer { { UPTransportLayerInformation-ExtIEs} } +} + +UPTransportLayerInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +URI-address ::= VisibleString + +-- V + +VictimgNBSetID ::= SEQUENCE { + victimgNBSetID GNBSetID, + iE-Extensions ProtocolExtensionContainer { { VictimgNBSetID-ExtIEs } } OPTIONAL +} + +VictimgNBSetID-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +VehicleUE ::= ENUMERATED { + authorized, + not-authorized, + ... +} + +PedestrianUE ::= ENUMERATED { + authorized, + not-authorized, + ... +} + +-- W + +-- X + +-- Y + +-- Z + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- Common definitions +-- +-- ************************************************************** + +F1AP-CommonDataTypes { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-CommonDataTypes (3) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +Criticality ::= ENUMERATED { reject, ignore, notify } + +Presence ::= ENUMERATED { optional, conditional, mandatory } + +PrivateIE-ID ::= CHOICE { + local INTEGER (0..65535), + global OBJECT IDENTIFIER +} + +ProcedureCode ::= INTEGER (0..255) + +ProtocolExtensionID ::= INTEGER (0..65535) + +ProtocolIE-ID ::= INTEGER (0..65535) + +TriggeringMessage ::= ENUMERATED { initiating-message, successful-outcome, unsuccessful-outcome } + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- Constant definitions +-- +-- ************************************************************** + +F1AP-Constants { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-Constants (4) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + ProcedureCode, + ProtocolIE-ID + +FROM F1AP-CommonDataTypes; + + +-- ************************************************************** +-- +-- Elementary Procedures +-- +-- ************************************************************** + +id-Reset ProcedureCode ::= 0 +id-F1Setup ProcedureCode ::= 1 +id-ErrorIndication ProcedureCode ::= 2 +id-gNBDUConfigurationUpdate ProcedureCode ::= 3 +id-gNBCUConfigurationUpdate ProcedureCode ::= 4 +id-UEContextSetup ProcedureCode ::= 5 +id-UEContextRelease ProcedureCode ::= 6 +id-UEContextModification ProcedureCode ::= 7 +id-UEContextModificationRequired ProcedureCode ::= 8 +id-UEMobilityCommand ProcedureCode ::= 9 +id-UEContextReleaseRequest ProcedureCode ::= 10 +id-InitialULRRCMessageTransfer ProcedureCode ::= 11 +id-DLRRCMessageTransfer ProcedureCode ::= 12 +id-ULRRCMessageTransfer ProcedureCode ::= 13 +id-privateMessage ProcedureCode ::= 14 +id-UEInactivityNotification ProcedureCode ::= 15 +id-GNBDUResourceCoordination ProcedureCode ::= 16 +id-SystemInformationDeliveryCommand ProcedureCode ::= 17 +id-Paging ProcedureCode ::= 18 +id-Notify ProcedureCode ::= 19 +id-WriteReplaceWarning ProcedureCode ::= 20 +id-PWSCancel ProcedureCode ::= 21 +id-PWSRestartIndication ProcedureCode ::= 22 +id-PWSFailureIndication ProcedureCode ::= 23 +id-GNBDUStatusIndication ProcedureCode ::= 24 +id-RRCDeliveryReport ProcedureCode ::= 25 +id-F1Removal ProcedureCode ::= 26 +id-NetworkAccessRateReduction ProcedureCode ::= 27 +id-TraceStart ProcedureCode ::= 28 +id-DeactivateTrace ProcedureCode ::= 29 +id-DUCURadioInformationTransfer ProcedureCode ::= 30 +id-CUDURadioInformationTransfer ProcedureCode ::= 31 +id-BAPMappingConfiguration ProcedureCode ::= 32 +id-GNBDUResourceConfiguration ProcedureCode ::= 33 +id-IABTNLAddressAllocation ProcedureCode ::= 34 +id-IABUPConfigurationUpdate ProcedureCode ::= 35 +id-resourceStatusReportingInitiation ProcedureCode ::= 36 +id-resourceStatusReporting ProcedureCode ::= 37 +id-accessAndMobilityIndication ProcedureCode ::= 38 +id-accessSuccess ProcedureCode ::= 39 +id-cellTrafficTrace ProcedureCode ::= 40 +id-PositioningMeasurementExchange ProcedureCode ::= 41 +id-PositioningAssistanceInformationControl ProcedureCode ::= 42 +id-PositioningAssistanceInformationFeedback ProcedureCode ::= 43 +id-PositioningMeasurementReport ProcedureCode ::= 44 +id-PositioningMeasurementAbort ProcedureCode ::= 45 +id-PositioningMeasurementFailureIndication ProcedureCode ::= 46 +id-PositioningMeasurementUpdate ProcedureCode ::= 47 +id-TRPInformationExchange ProcedureCode ::= 48 +id-PositioningInformationExchange ProcedureCode ::= 49 +id-PositioningActivation ProcedureCode ::= 50 +id-PositioningDeactivation ProcedureCode ::= 51 +id-E-CIDMeasurementInitiation ProcedureCode ::= 52 +id-E-CIDMeasurementFailureIndication ProcedureCode ::= 53 +id-E-CIDMeasurementReport ProcedureCode ::= 54 +id-E-CIDMeasurementTermination ProcedureCode ::= 55 +id-PositioningInformationUpdate ProcedureCode ::= 56 +id-ReferenceTimeInformationReport ProcedureCode ::= 57 +id-ReferenceTimeInformationReportingControl ProcedureCode ::= 58 + + + +-- ************************************************************** +-- +-- Extension constants +-- +-- ************************************************************** + +maxPrivateIEs INTEGER ::= 65535 +maxProtocolExtensions INTEGER ::= 65535 +maxProtocolIEs INTEGER ::= 65535 +-- ************************************************************** +-- +-- Lists +-- +-- ************************************************************** + +maxNRARFCN INTEGER ::= 3279165 +maxnoofErrors INTEGER ::= 256 +maxnoofIndividualF1ConnectionsToReset INTEGER ::= 65536 +maxCellingNBDU INTEGER ::= 512 +maxnoofSCells INTEGER ::= 32 +maxnoofSRBs INTEGER ::= 8 +maxnoofDRBs INTEGER ::= 64 +maxnoofULUPTNLInformation INTEGER ::= 2 +maxnoofDLUPTNLInformation INTEGER ::= 2 +maxnoofBPLMNs INTEGER ::= 6 +maxnoofCandidateSpCells INTEGER ::= 64 +maxnoofPotentialSpCells INTEGER ::= 64 +maxnoofNrCellBands INTEGER ::= 32 +maxnoofSIBTypes INTEGER ::= 32 +maxnoofSITypes INTEGER ::= 32 +maxnoofPagingCells INTEGER ::= 512 +maxnoofTNLAssociations INTEGER ::= 32 +maxnoofQoSFlows INTEGER ::= 64 +maxnoofSliceItems INTEGER ::= 1024 +maxCellineNB INTEGER ::= 256 +maxnoofExtendedBPLMNs INTEGER ::= 6 +maxnoofUEIDs INTEGER ::= 65536 +maxnoofBPLMNsNR INTEGER ::= 12 +maxnoofUACPLMNs INTEGER ::= 12 +maxnoofUACperPLMN INTEGER ::= 64 +maxnoofAdditionalSIBs INTEGER ::= 63 +maxnoofslots INTEGER ::= 5120 +maxnoofTLAs INTEGER ::= 16 +maxnoofGTPTLAs INTEGER ::= 16 +maxnoofBHRLCChannels INTEGER ::= 65536 +maxnoofRoutingEntries INTEGER ::= 1024 +maxnoofIABSTCInfo INTEGER ::= 45 +maxnoofSymbols INTEGER ::= 14 +maxnoofServingCells INTEGER ::= 32 +maxnoofDUFSlots INTEGER ::= 320 +maxnoofHSNASlots INTEGER ::= 5120 +maxnoofServedCellsIAB INTEGER ::= 512 +maxnoofChildIABNodes INTEGER ::= 1024 +maxnoofNonUPTrafficMappings INTEGER ::= 32 +maxnoofTLAsIAB INTEGER ::= 1024 +maxnoofMappingEntries INTEGER ::= 67108864 +maxnoofDSInfo INTEGER ::= 64 +maxnoofEgressLinks INTEGER ::= 2 +maxnoofULUPTNLInformationforIAB INTEGER ::= 32678 +maxnoofUPTNLAddresses INTEGER ::= 8 +maxnoofSLDRBs INTEGER ::= 512 +maxnoofQoSParaSets INTEGER ::= 8 +maxnoofPC5QoSFlows INTEGER ::= 2048 +maxnoofSSBAreas INTEGER ::= 64 +maxnoofPhysicalResourceBlocks INTEGER ::= 275 +maxnoofPhysicalResourceBlocks-1 INTEGER ::= 274 +maxnoofPRACHconfigs INTEGER ::= 16 +maxnoofRACHReports INTEGER ::= 64 +maxnoofRLFReports INTEGER ::= 64 +maxnoofAdditionalPDCPDuplicationTNL INTEGER ::= 2 +maxnoofRLCDuplicationState INTEGER ::= 3 +maxnoofCHOcells INTEGER ::= 8 +maxnoofMDTPLMNs INTEGER ::= 16 +maxnoofCAGsupported INTEGER ::= 12 +maxnoofNIDsupported INTEGER ::= 12 +maxnoofNRSCSs INTEGER ::= 5 +maxnoofExtSliceItems INTEGER ::= 65535 +maxnoofPosMeas INTEGER ::= 16384 +maxnoofTRPInfoTypes INTEGER ::= 64 +maxnoofTRPs INTEGER ::= 65535 +maxnoofSRSTriggerStates INTEGER ::= 3 +maxnoofSpatialRelations INTEGER ::= 64 +maxnoBcastCell INTEGER ::= 16384 +maxnoofAngleInfo INTEGER ::= 65535 +maxnooflcs-gcs-translation INTEGER ::= 3 +maxnoofPath INTEGER ::= 2 +maxnoofMeasE-CID INTEGER ::= 64 +maxnoofSSBs INTEGER ::= 255 +maxnoSRS-ResourceSets INTEGER ::= 16 +maxnoSRS-ResourcePerSet INTEGER ::= 16 +maxnoSRS-Carriers INTEGER ::= 32 +maxnoSCSs INTEGER ::= 5 +maxnoSRS-Resources INTEGER ::= 64 +maxnoSRS-PosResources INTEGER ::= 64 +maxnoSRS-PosResourceSets INTEGER ::= 16 +maxnoSRS-PosResourcePerSet INTEGER ::= 16 +maxnoofPRS-ResourceSets INTEGER ::= 2 +maxnoofPRS-ResourcesPerSet INTEGER ::= 64 +maxNoOfMeasTRPs INTEGER ::= 64 +maxnoofPRSresourceSets INTEGER ::= 8 +maxnoofPRSresources INTEGER ::= 64 + + + +-- ************************************************************** +-- +-- IEs +-- +-- ************************************************************** + +id-Cause ProtocolIE-ID ::= 0 +id-Cells-Failed-to-be-Activated-List ProtocolIE-ID ::= 1 +id-Cells-Failed-to-be-Activated-List-Item ProtocolIE-ID ::= 2 +id-Cells-to-be-Activated-List ProtocolIE-ID ::= 3 +id-Cells-to-be-Activated-List-Item ProtocolIE-ID ::= 4 +id-Cells-to-be-Deactivated-List ProtocolIE-ID ::= 5 +id-Cells-to-be-Deactivated-List-Item ProtocolIE-ID ::= 6 +id-CriticalityDiagnostics ProtocolIE-ID ::= 7 +id-CUtoDURRCInformation ProtocolIE-ID ::= 9 +id-DRBs-FailedToBeModified-Item ProtocolIE-ID ::= 12 +id-DRBs-FailedToBeModified-List ProtocolIE-ID ::= 13 +id-DRBs-FailedToBeSetup-Item ProtocolIE-ID ::= 14 +id-DRBs-FailedToBeSetup-List ProtocolIE-ID ::= 15 +id-DRBs-FailedToBeSetupMod-Item ProtocolIE-ID ::= 16 +id-DRBs-FailedToBeSetupMod-List ProtocolIE-ID ::= 17 +id-DRBs-ModifiedConf-Item ProtocolIE-ID ::= 18 +id-DRBs-ModifiedConf-List ProtocolIE-ID ::= 19 +id-DRBs-Modified-Item ProtocolIE-ID ::= 20 +id-DRBs-Modified-List ProtocolIE-ID ::= 21 +id-DRBs-Required-ToBeModified-Item ProtocolIE-ID ::= 22 +id-DRBs-Required-ToBeModified-List ProtocolIE-ID ::= 23 +id-DRBs-Required-ToBeReleased-Item ProtocolIE-ID ::= 24 +id-DRBs-Required-ToBeReleased-List ProtocolIE-ID ::= 25 +id-DRBs-Setup-Item ProtocolIE-ID ::= 26 +id-DRBs-Setup-List ProtocolIE-ID ::= 27 +id-DRBs-SetupMod-Item ProtocolIE-ID ::= 28 +id-DRBs-SetupMod-List ProtocolIE-ID ::= 29 +id-DRBs-ToBeModified-Item ProtocolIE-ID ::= 30 +id-DRBs-ToBeModified-List ProtocolIE-ID ::= 31 +id-DRBs-ToBeReleased-Item ProtocolIE-ID ::= 32 +id-DRBs-ToBeReleased-List ProtocolIE-ID ::= 33 +id-DRBs-ToBeSetup-Item ProtocolIE-ID ::= 34 +id-DRBs-ToBeSetup-List ProtocolIE-ID ::= 35 +id-DRBs-ToBeSetupMod-Item ProtocolIE-ID ::= 36 +id-DRBs-ToBeSetupMod-List ProtocolIE-ID ::= 37 +id-DRXCycle ProtocolIE-ID ::= 38 +id-DUtoCURRCInformation ProtocolIE-ID ::= 39 +id-gNB-CU-UE-F1AP-ID ProtocolIE-ID ::= 40 +id-gNB-DU-UE-F1AP-ID ProtocolIE-ID ::= 41 +id-gNB-DU-ID ProtocolIE-ID ::= 42 +id-GNB-DU-Served-Cells-Item ProtocolIE-ID ::= 43 +id-gNB-DU-Served-Cells-List ProtocolIE-ID ::= 44 +id-gNB-DU-Name ProtocolIE-ID ::= 45 +id-NRCellID ProtocolIE-ID ::= 46 +id-oldgNB-DU-UE-F1AP-ID ProtocolIE-ID ::= 47 +id-ResetType ProtocolIE-ID ::= 48 +id-ResourceCoordinationTransferContainer ProtocolIE-ID ::= 49 +id-RRCContainer ProtocolIE-ID ::= 50 +id-SCell-ToBeRemoved-Item ProtocolIE-ID ::= 51 +id-SCell-ToBeRemoved-List ProtocolIE-ID ::= 52 +id-SCell-ToBeSetup-Item ProtocolIE-ID ::= 53 +id-SCell-ToBeSetup-List ProtocolIE-ID ::= 54 +id-SCell-ToBeSetupMod-Item ProtocolIE-ID ::= 55 +id-SCell-ToBeSetupMod-List ProtocolIE-ID ::= 56 +id-Served-Cells-To-Add-Item ProtocolIE-ID ::= 57 +id-Served-Cells-To-Add-List ProtocolIE-ID ::= 58 +id-Served-Cells-To-Delete-Item ProtocolIE-ID ::= 59 +id-Served-Cells-To-Delete-List ProtocolIE-ID ::= 60 +id-Served-Cells-To-Modify-Item ProtocolIE-ID ::= 61 +id-Served-Cells-To-Modify-List ProtocolIE-ID ::= 62 +id-SpCell-ID ProtocolIE-ID ::= 63 +id-SRBID ProtocolIE-ID ::= 64 +id-SRBs-FailedToBeSetup-Item ProtocolIE-ID ::= 65 +id-SRBs-FailedToBeSetup-List ProtocolIE-ID ::= 66 +id-SRBs-FailedToBeSetupMod-Item ProtocolIE-ID ::= 67 +id-SRBs-FailedToBeSetupMod-List ProtocolIE-ID ::= 68 +id-SRBs-Required-ToBeReleased-Item ProtocolIE-ID ::= 69 +id-SRBs-Required-ToBeReleased-List ProtocolIE-ID ::= 70 +id-SRBs-ToBeReleased-Item ProtocolIE-ID ::= 71 +id-SRBs-ToBeReleased-List ProtocolIE-ID ::= 72 +id-SRBs-ToBeSetup-Item ProtocolIE-ID ::= 73 +id-SRBs-ToBeSetup-List ProtocolIE-ID ::= 74 +id-SRBs-ToBeSetupMod-Item ProtocolIE-ID ::= 75 +id-SRBs-ToBeSetupMod-List ProtocolIE-ID ::= 76 +id-TimeToWait ProtocolIE-ID ::= 77 +id-TransactionID ProtocolIE-ID ::= 78 +id-TransmissionActionIndicator ProtocolIE-ID ::= 79 +id-UE-associatedLogicalF1-ConnectionItem ProtocolIE-ID ::= 80 +id-UE-associatedLogicalF1-ConnectionListResAck ProtocolIE-ID ::= 81 +id-gNB-CU-Name ProtocolIE-ID ::= 82 +id-SCell-FailedtoSetup-List ProtocolIE-ID ::= 83 +id-SCell-FailedtoSetup-Item ProtocolIE-ID ::= 84 +id-SCell-FailedtoSetupMod-List ProtocolIE-ID ::= 85 +id-SCell-FailedtoSetupMod-Item ProtocolIE-ID ::= 86 +id-RRCReconfigurationCompleteIndicator ProtocolIE-ID ::= 87 +id-Cells-Status-Item ProtocolIE-ID ::= 88 +id-Cells-Status-List ProtocolIE-ID ::= 89 +id-Candidate-SpCell-List ProtocolIE-ID ::= 90 +id-Candidate-SpCell-Item ProtocolIE-ID ::= 91 +id-Potential-SpCell-List ProtocolIE-ID ::= 92 +id-Potential-SpCell-Item ProtocolIE-ID ::= 93 +id-FullConfiguration ProtocolIE-ID ::= 94 +id-C-RNTI ProtocolIE-ID ::= 95 +id-SpCellULConfigured ProtocolIE-ID ::= 96 +id-InactivityMonitoringRequest ProtocolIE-ID ::= 97 +id-InactivityMonitoringResponse ProtocolIE-ID ::= 98 +id-DRB-Activity-Item ProtocolIE-ID ::= 99 +id-DRB-Activity-List ProtocolIE-ID ::= 100 +id-EUTRA-NR-CellResourceCoordinationReq-Container ProtocolIE-ID ::= 101 +id-EUTRA-NR-CellResourceCoordinationReqAck-Container ProtocolIE-ID ::= 102 +id-Protected-EUTRA-Resources-List ProtocolIE-ID ::= 105 +id-RequestType ProtocolIE-ID ::= 106 +id-ServCellIndex ProtocolIE-ID ::= 107 +id-RAT-FrequencyPriorityInformation ProtocolIE-ID ::= 108 +id-ExecuteDuplication ProtocolIE-ID ::= 109 +id-NRCGI ProtocolIE-ID ::= 111 +id-PagingCell-Item ProtocolIE-ID ::= 112 +id-PagingCell-List ProtocolIE-ID ::= 113 +id-PagingDRX ProtocolIE-ID ::= 114 +id-PagingPriority ProtocolIE-ID ::= 115 +id-SItype-List ProtocolIE-ID ::= 116 +id-UEIdentityIndexValue ProtocolIE-ID ::= 117 +id-gNB-CUSystemInformation ProtocolIE-ID ::= 118 +id-HandoverPreparationInformation ProtocolIE-ID ::= 119 +id-GNB-CU-TNL-Association-To-Add-Item ProtocolIE-ID ::= 120 +id-GNB-CU-TNL-Association-To-Add-List ProtocolIE-ID ::= 121 +id-GNB-CU-TNL-Association-To-Remove-Item ProtocolIE-ID ::= 122 +id-GNB-CU-TNL-Association-To-Remove-List ProtocolIE-ID ::= 123 +id-GNB-CU-TNL-Association-To-Update-Item ProtocolIE-ID ::= 124 +id-GNB-CU-TNL-Association-To-Update-List ProtocolIE-ID ::= 125 +id-MaskedIMEISV ProtocolIE-ID ::= 126 +id-PagingIdentity ProtocolIE-ID ::= 127 +id-DUtoCURRCContainer ProtocolIE-ID ::= 128 +id-Cells-to-be-Barred-List ProtocolIE-ID ::= 129 +id-Cells-to-be-Barred-Item ProtocolIE-ID ::= 130 +id-TAISliceSupportList ProtocolIE-ID ::= 131 +id-GNB-CU-TNL-Association-Setup-List ProtocolIE-ID ::= 132 +id-GNB-CU-TNL-Association-Setup-Item ProtocolIE-ID ::= 133 +id-GNB-CU-TNL-Association-Failed-To-Setup-List ProtocolIE-ID ::= 134 +id-GNB-CU-TNL-Association-Failed-To-Setup-Item ProtocolIE-ID ::= 135 +id-DRB-Notify-Item ProtocolIE-ID ::= 136 +id-DRB-Notify-List ProtocolIE-ID ::= 137 +id-NotficationControl ProtocolIE-ID ::= 138 +id-RANAC ProtocolIE-ID ::= 139 +id-PWSSystemInformation ProtocolIE-ID ::= 140 +id-RepetitionPeriod ProtocolIE-ID ::= 141 +id-NumberofBroadcastRequest ProtocolIE-ID ::= 142 +id-Cells-To-Be-Broadcast-List ProtocolIE-ID ::= 144 +id-Cells-To-Be-Broadcast-Item ProtocolIE-ID ::= 145 +id-Cells-Broadcast-Completed-List ProtocolIE-ID ::= 146 +id-Cells-Broadcast-Completed-Item ProtocolIE-ID ::= 147 +id-Broadcast-To-Be-Cancelled-List ProtocolIE-ID ::= 148 +id-Broadcast-To-Be-Cancelled-Item ProtocolIE-ID ::= 149 +id-Cells-Broadcast-Cancelled-List ProtocolIE-ID ::= 150 +id-Cells-Broadcast-Cancelled-Item ProtocolIE-ID ::= 151 +id-NR-CGI-List-For-Restart-List ProtocolIE-ID ::= 152 +id-NR-CGI-List-For-Restart-Item ProtocolIE-ID ::= 153 +id-PWS-Failed-NR-CGI-List ProtocolIE-ID ::= 154 +id-PWS-Failed-NR-CGI-Item ProtocolIE-ID ::= 155 +id-ConfirmedUEID ProtocolIE-ID ::= 156 +id-Cancel-all-Warning-Messages-Indicator ProtocolIE-ID ::= 157 +id-GNB-DU-UE-AMBR-UL ProtocolIE-ID ::= 158 +id-DRXConfigurationIndicator ProtocolIE-ID ::= 159 +id-RLC-Status ProtocolIE-ID ::= 160 +id-DLPDCPSNLength ProtocolIE-ID ::= 161 +id-GNB-DUConfigurationQuery ProtocolIE-ID ::= 162 +id-MeasurementTimingConfiguration ProtocolIE-ID ::= 163 +id-DRB-Information ProtocolIE-ID ::= 164 +id-ServingPLMN ProtocolIE-ID ::= 165 +id-Protected-EUTRA-Resources-Item ProtocolIE-ID ::= 168 +id-GNB-CU-RRC-Version ProtocolIE-ID ::= 170 +id-GNB-DU-RRC-Version ProtocolIE-ID ::= 171 +id-GNBDUOverloadInformation ProtocolIE-ID ::= 172 +id-CellGroupConfig ProtocolIE-ID ::= 173 +id-RLCFailureIndication ProtocolIE-ID ::= 174 +id-UplinkTxDirectCurrentListInformation ProtocolIE-ID ::= 175 +id-DC-Based-Duplication-Configured ProtocolIE-ID ::= 176 +id-DC-Based-Duplication-Activation ProtocolIE-ID ::= 177 +id-SULAccessIndication ProtocolIE-ID ::= 178 +id-AvailablePLMNList ProtocolIE-ID ::= 179 +id-PDUSessionID ProtocolIE-ID ::= 180 +id-ULPDUSessionAggregateMaximumBitRate ProtocolIE-ID ::= 181 +id-ServingCellMO ProtocolIE-ID ::= 182 +id-QoSFlowMappingIndication ProtocolIE-ID ::= 183 +id-RRCDeliveryStatusRequest ProtocolIE-ID ::= 184 +id-RRCDeliveryStatus ProtocolIE-ID ::= 185 +id-BearerTypeChange ProtocolIE-ID ::= 186 +id-RLCMode ProtocolIE-ID ::= 187 +id-Duplication-Activation ProtocolIE-ID ::= 188 +id-Dedicated-SIDelivery-NeededUE-List ProtocolIE-ID ::= 189 +id-Dedicated-SIDelivery-NeededUE-Item ProtocolIE-ID ::= 190 +id-DRX-LongCycleStartOffset ProtocolIE-ID ::= 191 +id-ULPDCPSNLength ProtocolIE-ID ::= 192 +id-SelectedBandCombinationIndex ProtocolIE-ID ::= 193 +id-SelectedFeatureSetEntryIndex ProtocolIE-ID ::= 194 +id-ResourceCoordinationTransferInformation ProtocolIE-ID ::= 195 +id-ExtendedServedPLMNs-List ProtocolIE-ID ::= 196 +id-ExtendedAvailablePLMN-List ProtocolIE-ID ::= 197 +id-Associated-SCell-List ProtocolIE-ID ::= 198 +id-latest-RRC-Version-Enhanced ProtocolIE-ID ::= 199 +id-Associated-SCell-Item ProtocolIE-ID ::= 200 +id-Cell-Direction ProtocolIE-ID ::= 201 +id-SRBs-Setup-List ProtocolIE-ID ::= 202 +id-SRBs-Setup-Item ProtocolIE-ID ::= 203 +id-SRBs-SetupMod-List ProtocolIE-ID ::= 204 +id-SRBs-SetupMod-Item ProtocolIE-ID ::= 205 +id-SRBs-Modified-List ProtocolIE-ID ::= 206 +id-SRBs-Modified-Item ProtocolIE-ID ::= 207 +id-Ph-InfoSCG ProtocolIE-ID ::= 208 +id-RequestedBandCombinationIndex ProtocolIE-ID ::= 209 +id-RequestedFeatureSetEntryIndex ProtocolIE-ID ::= 210 +id-RequestedP-MaxFR2 ProtocolIE-ID ::= 211 +id-DRX-Config ProtocolIE-ID ::= 212 +id-IgnoreResourceCoordinationContainer ProtocolIE-ID ::= 213 +id-UEAssistanceInformation ProtocolIE-ID ::= 214 +id-NeedforGap ProtocolIE-ID ::= 215 +id-PagingOrigin ProtocolIE-ID ::= 216 +id-new-gNB-CU-UE-F1AP-ID ProtocolIE-ID ::= 217 +id-RedirectedRRCmessage ProtocolIE-ID ::= 218 +id-new-gNB-DU-UE-F1AP-ID ProtocolIE-ID ::= 219 +id-NotificationInformation ProtocolIE-ID ::= 220 +id-PLMNAssistanceInfoForNetShar ProtocolIE-ID ::= 221 +id-UEContextNotRetrievable ProtocolIE-ID ::= 222 +id-BPLMN-ID-Info-List ProtocolIE-ID ::= 223 +id-SelectedPLMNID ProtocolIE-ID ::= 224 +id-UAC-Assistance-Info ProtocolIE-ID ::= 225 +id-RANUEID ProtocolIE-ID ::= 226 +id-GNB-DU-TNL-Association-To-Remove-Item ProtocolIE-ID ::= 227 +id-GNB-DU-TNL-Association-To-Remove-List ProtocolIE-ID ::= 228 +id-TNLAssociationTransportLayerAddressgNBDU ProtocolIE-ID ::= 229 +id-portNumber ProtocolIE-ID ::= 230 +id-AdditionalSIBMessageList ProtocolIE-ID ::= 231 +id-Cell-Type ProtocolIE-ID ::= 232 +id-IgnorePRACHConfiguration ProtocolIE-ID ::= 233 +id-CG-Config ProtocolIE-ID ::= 234 +id-PDCCH-BlindDetectionSCG ProtocolIE-ID ::= 235 +id-Requested-PDCCH-BlindDetectionSCG ProtocolIE-ID ::= 236 +id-Ph-InfoMCG ProtocolIE-ID ::= 237 +id-MeasGapSharingConfig ProtocolIE-ID ::= 238 +id-systemInformationAreaID ProtocolIE-ID ::= 239 +id-areaScope ProtocolIE-ID ::= 240 +id-RRCContainer-RRCSetupComplete ProtocolIE-ID ::= 241 +id-TraceActivation ProtocolIE-ID ::= 242 +id-TraceID ProtocolIE-ID ::= 243 +id-Neighbour-Cell-Information-List ProtocolIE-ID ::= 244 +id-SymbolAllocInSlot ProtocolIE-ID ::= 246 +id-NumDLULSymbols ProtocolIE-ID ::= 247 +id-AdditionalRRMPriorityIndex ProtocolIE-ID ::= 248 +id-DUCURadioInformationType ProtocolIE-ID ::= 249 +id-CUDURadioInformationType ProtocolIE-ID ::= 250 +id-AggressorgNBSetID ProtocolIE-ID ::= 251 +id-VictimgNBSetID ProtocolIE-ID ::= 252 +id-LowerLayerPresenceStatusChange ProtocolIE-ID ::= 253 +id-Transport-Layer-Address-Info ProtocolIE-ID ::= 254 +id-Neighbour-Cell-Information-Item ProtocolIE-ID ::= 255 +id-IntendedTDD-DL-ULConfig ProtocolIE-ID ::= 256 +id-QosMonitoringRequest ProtocolIE-ID ::= 257 +id-BHChannels-ToBeSetup-List ProtocolIE-ID ::= 258 +id-BHChannels-ToBeSetup-Item ProtocolIE-ID ::= 259 +id-BHChannels-Setup-List ProtocolIE-ID ::= 260 +id-BHChannels-Setup-Item ProtocolIE-ID ::= 261 +id-BHChannels-ToBeModified-Item ProtocolIE-ID ::= 262 +id-BHChannels-ToBeModified-List ProtocolIE-ID ::= 263 +id-BHChannels-ToBeReleased-Item ProtocolIE-ID ::= 264 +id-BHChannels-ToBeReleased-List ProtocolIE-ID ::= 265 +id-BHChannels-ToBeSetupMod-Item ProtocolIE-ID ::= 266 +id-BHChannels-ToBeSetupMod-List ProtocolIE-ID ::= 267 +id-BHChannels-FailedToBeModified-Item ProtocolIE-ID ::= 268 +id-BHChannels-FailedToBeModified-List ProtocolIE-ID ::= 269 +id-BHChannels-FailedToBeSetupMod-Item ProtocolIE-ID ::= 270 +id-BHChannels-FailedToBeSetupMod-List ProtocolIE-ID ::= 271 +id-BHChannels-Modified-Item ProtocolIE-ID ::= 272 +id-BHChannels-Modified-List ProtocolIE-ID ::= 273 +id-BHChannels-SetupMod-Item ProtocolIE-ID ::= 274 +id-BHChannels-SetupMod-List ProtocolIE-ID ::= 275 +id-BHChannels-Required-ToBeReleased-Item ProtocolIE-ID ::= 276 +id-BHChannels-Required-ToBeReleased-List ProtocolIE-ID ::= 277 +id-BHChannels-FailedToBeSetup-Item ProtocolIE-ID ::= 278 +id-BHChannels-FailedToBeSetup-List ProtocolIE-ID ::= 279 +id-BHInfo ProtocolIE-ID ::= 280 +id-BAPAddress ProtocolIE-ID ::= 281 +id-ConfiguredBAPAddress ProtocolIE-ID ::= 282 +id-BH-Routing-Information-Added-List ProtocolIE-ID ::= 283 +id-BH-Routing-Information-Added-List-Item ProtocolIE-ID ::= 284 +id-BH-Routing-Information-Removed-List ProtocolIE-ID ::= 285 +id-BH-Routing-Information-Removed-List-Item ProtocolIE-ID ::= 286 +id-UL-BH-Non-UP-Traffic-Mapping ProtocolIE-ID ::= 287 +id-Activated-Cells-to-be-Updated-List ProtocolIE-ID ::= 288 +id-Child-Nodes-List ProtocolIE-ID ::= 289 +id-IAB-Info-IAB-DU ProtocolIE-ID ::= 290 +id-IAB-Info-IAB-donor-CU ProtocolIE-ID ::= 291 +id-IAB-TNL-Addresses-To-Remove-List ProtocolIE-ID ::= 292 +id-IAB-TNL-Addresses-To-Remove-Item ProtocolIE-ID ::= 293 +id-IAB-Allocated-TNL-Address-List ProtocolIE-ID ::= 294 +id-IAB-Allocated-TNL-Address-Item ProtocolIE-ID ::= 295 +id-IABIPv6RequestType ProtocolIE-ID ::= 296 +id-IABv4AddressesRequested ProtocolIE-ID ::= 297 +id-IAB-Barred ProtocolIE-ID ::= 298 +id-TrafficMappingInformation ProtocolIE-ID ::= 299 +id-UL-UP-TNL-Information-to-Update-List ProtocolIE-ID ::= 300 +id-UL-UP-TNL-Information-to-Update-List-Item ProtocolIE-ID ::= 301 +id-UL-UP-TNL-Address-to-Update-List ProtocolIE-ID ::= 302 +id-UL-UP-TNL-Address-to-Update-List-Item ProtocolIE-ID ::= 303 +id-DL-UP-TNL-Address-to-Update-List ProtocolIE-ID ::= 304 +id-DL-UP-TNL-Address-to-Update-List-Item ProtocolIE-ID ::= 305 +id-NRV2XServicesAuthorized ProtocolIE-ID ::= 306 +id-LTEV2XServicesAuthorized ProtocolIE-ID ::= 307 +id-NRUESidelinkAggregateMaximumBitrate ProtocolIE-ID ::= 308 +id-LTEUESidelinkAggregateMaximumBitrate ProtocolIE-ID ::= 309 +id-SIB12-message ProtocolIE-ID ::= 310 +id-SIB13-message ProtocolIE-ID ::= 311 +id-SIB14-message ProtocolIE-ID ::= 312 +id-SLDRBs-FailedToBeModified-Item ProtocolIE-ID ::= 313 +id-SLDRBs-FailedToBeModified-List ProtocolIE-ID ::= 314 +id-SLDRBs-FailedToBeSetup-Item ProtocolIE-ID ::= 315 +id-SLDRBs-FailedToBeSetup-List ProtocolIE-ID ::= 316 +id-SLDRBs-Modified-Item ProtocolIE-ID ::= 317 +id-SLDRBs-Modified-List ProtocolIE-ID ::= 318 +id-SLDRBs-Required-ToBeModified-Item ProtocolIE-ID ::= 319 +id-SLDRBs-Required-ToBeModified-List ProtocolIE-ID ::= 320 +id-SLDRBs-Required-ToBeReleased-Item ProtocolIE-ID ::= 321 +id-SLDRBs-Required-ToBeReleased-List ProtocolIE-ID ::= 322 +id-SLDRBs-Setup-Item ProtocolIE-ID ::= 323 +id-SLDRBs-Setup-List ProtocolIE-ID ::= 324 +id-SLDRBs-ToBeModified-Item ProtocolIE-ID ::= 325 +id-SLDRBs-ToBeModified-List ProtocolIE-ID ::= 326 +id-SLDRBs-ToBeReleased-Item ProtocolIE-ID ::= 327 +id-SLDRBs-ToBeReleased-List ProtocolIE-ID ::= 328 +id-SLDRBs-ToBeSetup-Item ProtocolIE-ID ::= 329 +id-SLDRBs-ToBeSetup-List ProtocolIE-ID ::= 330 +id-SLDRBs-ToBeSetupMod-Item ProtocolIE-ID ::= 331 +id-SLDRBs-ToBeSetupMod-List ProtocolIE-ID ::= 332 +id-SLDRBs-SetupMod-List ProtocolIE-ID ::= 333 +id-SLDRBs-FailedToBeSetupMod-List ProtocolIE-ID ::= 334 +id-SLDRBs-SetupMod-Item ProtocolIE-ID ::= 335 +id-SLDRBs-FailedToBeSetupMod-Item ProtocolIE-ID ::= 336 +id-SLDRBs-ModifiedConf-List ProtocolIE-ID ::= 337 +id-SLDRBs-ModifiedConf-Item ProtocolIE-ID ::= 338 +id-UEAssistanceInformationEUTRA ProtocolIE-ID ::= 339 +id-PC5LinkAMBR ProtocolIE-ID ::= 340 +id-SL-PHY-MAC-RLC-Config ProtocolIE-ID ::= 341 +id-SL-ConfigDedicatedEUTRA ProtocolIE-ID ::= 342 +id-AlternativeQoSParaSetList ProtocolIE-ID ::= 343 +id-CurrentQoSParaSetIndex ProtocolIE-ID ::= 344 +id-gNBCUMeasurementID ProtocolIE-ID ::= 345 +id-gNBDUMeasurementID ProtocolIE-ID ::= 346 +id-RegistrationRequest ProtocolIE-ID ::= 347 +id-ReportCharacteristics ProtocolIE-ID ::= 348 +id-CellToReportList ProtocolIE-ID ::= 349 +id-CellMeasurementResultList ProtocolIE-ID ::= 350 +id-HardwareLoadIndicator ProtocolIE-ID ::= 351 +id-ReportingPeriodicity ProtocolIE-ID ::= 352 +id-TNLCapacityIndicator ProtocolIE-ID ::= 353 +id-CarrierList ProtocolIE-ID ::= 354 +id-ULCarrierList ProtocolIE-ID ::= 355 +id-FrequencyShift7p5khz ProtocolIE-ID ::= 356 +id-SSB-PositionsInBurst ProtocolIE-ID ::= 357 +id-NRPRACHConfig ProtocolIE-ID ::= 358 +id-RACHReportInformationList ProtocolIE-ID ::= 359 +id-RLFReportInformationList ProtocolIE-ID ::= 360 +id-TDD-UL-DLConfigCommonNR ProtocolIE-ID ::= 361 +id-CNPacketDelayBudgetDownlink ProtocolIE-ID ::= 362 +id-ExtendedPacketDelayBudget ProtocolIE-ID ::= 363 +id-TSCTrafficCharacteristics ProtocolIE-ID ::= 364 +id-ReportingRequestType ProtocolIE-ID ::= 365 +id-TimeReferenceInformation ProtocolIE-ID ::= 366 +id-CNPacketDelayBudgetUplink ProtocolIE-ID ::= 369 +id-AdditionalPDCPDuplicationTNL-List ProtocolIE-ID ::= 370 +id-RLCDuplicationInformation ProtocolIE-ID ::= 371 +id-AdditionalDuplicationIndication ProtocolIE-ID ::= 372 +id-ConditionalInterDUMobilityInformation ProtocolIE-ID ::= 373 +id-ConditionalIntraDUMobilityInformation ProtocolIE-ID ::= 374 +id-targetCellsToCancel ProtocolIE-ID ::= 375 +id-requestedTargetCellGlobalID ProtocolIE-ID ::= 376 +id-ManagementBasedMDTPLMNList ProtocolIE-ID ::= 377 +id-TraceCollectionEntityIPAddress ProtocolIE-ID ::= 378 +id-PrivacyIndicator ProtocolIE-ID ::= 379 +id-TraceCollectionEntityURI ProtocolIE-ID ::= 380 +id-mdtConfiguration ProtocolIE-ID ::= 381 +id-ServingNID ProtocolIE-ID ::= 382 +id-NPNBroadcastInformation ProtocolIE-ID ::= 383 +id-NPNSupportInfo ProtocolIE-ID ::= 384 +id-NID ProtocolIE-ID ::= 385 +id-AvailableSNPN-ID-List ProtocolIE-ID ::= 386 +id-SIB10-message ProtocolIE-ID ::= 387 +id-DLCarrierList ProtocolIE-ID ::= 389 + id-ExtendedTAISliceSupportList ProtocolIE-ID ::= 390 +id-RequestedSRSTransmissionCharacteristics ProtocolIE-ID ::= 391 +id-PosAssistance-Information ProtocolIE-ID ::= 392 +id-PosBroadcast ProtocolIE-ID ::= 393 +id-RoutingID ProtocolIE-ID ::= 394 +id-PosAssistanceInformationFailureList ProtocolIE-ID ::= 395 +id-PosMeasurementQuantities ProtocolIE-ID ::= 396 +id-PosMeasurementResultList ProtocolIE-ID ::= 397 +id-TRPInformationTypeListTRPReq ProtocolIE-ID ::= 398 +id-TRPInformationTypeItem ProtocolIE-ID ::= 399 +id-TRPInformationListTRPResp ProtocolIE-ID ::= 400 +id-TRPInformationItem ProtocolIE-ID ::= 401 +id-LMF-MeasurementID ProtocolIE-ID ::= 402 +id-SRSType ProtocolIE-ID ::= 403 +id-ActivationTime ProtocolIE-ID ::= 404 +id-AbortTransmission ProtocolIE-ID ::= 405 +id-PositioningBroadcastCells ProtocolIE-ID ::= 406 +id-SRSConfiguration ProtocolIE-ID ::= 407 +id-PosReportCharacteristics ProtocolIE-ID ::= 408 +id-PosMeasurementPeriodicity ProtocolIE-ID ::= 409 +id-TRPList ProtocolIE-ID ::= 410 +id-RAN-MeasurementID ProtocolIE-ID ::= 411 +id-LMF-UE-MeasurementID ProtocolIE-ID ::= 412 +id-RAN-UE-MeasurementID ProtocolIE-ID ::= 413 +id-E-CID-MeasurementQuantities ProtocolIE-ID ::= 414 +id-E-CID-MeasurementQuantities-Item ProtocolIE-ID ::= 415 +id-E-CID-MeasurementPeriodicity ProtocolIE-ID ::= 416 +id-E-CID-MeasurementResult ProtocolIE-ID ::= 417 +id-Cell-Portion-ID ProtocolIE-ID ::= 418 +id-SFNInitialisationTime ProtocolIE-ID ::= 419 +id-SystemFrameNumber ProtocolIE-ID ::= 420 +id-SlotNumber ProtocolIE-ID ::= 421 +id-TRP-MeasurementRequestList ProtocolIE-ID ::= 422 +id-MeasurementBeamInfoRequest ProtocolIE-ID ::= 423 +id-E-CID-ReportCharacteristics ProtocolIE-ID ::= 424 +id-ConfiguredTACIndication ProtocolIE-ID ::= 425 +id-Extended-GNB-DU-Name ProtocolIE-ID ::= 426 +id-Extended-GNB-CU-Name ProtocolIE-ID ::= 427 + + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- Container definitions +-- +-- ************************************************************** + +F1AP-Containers { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-Containers (5) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + Criticality, + Presence, + PrivateIE-ID, + ProtocolExtensionID, + ProtocolIE-ID + +FROM F1AP-CommonDataTypes + maxPrivateIEs, + maxProtocolExtensions, + maxProtocolIEs + +FROM F1AP-Constants; + +-- ************************************************************** +-- +-- Class Definition for Protocol IEs +-- +-- ************************************************************** + +F1AP-PROTOCOL-IES ::= CLASS { + &id ProtocolIE-ID UNIQUE, + &criticality Criticality, + &Value, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + TYPE &Value + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Protocol IEs +-- +-- ************************************************************** + +F1AP-PROTOCOL-IES-PAIR ::= CLASS { + &id ProtocolIE-ID UNIQUE, + &firstCriticality Criticality, + &FirstValue, + &secondCriticality Criticality, + &SecondValue, + &presence Presence +} +WITH SYNTAX { + ID &id + FIRST CRITICALITY &firstCriticality + FIRST TYPE &FirstValue + SECOND CRITICALITY &secondCriticality + SECOND TYPE &SecondValue + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Protocol Extensions +-- +-- ************************************************************** + +F1AP-PROTOCOL-EXTENSION ::= CLASS { + &id ProtocolExtensionID UNIQUE, + &criticality Criticality, + &Extension, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + EXTENSION &Extension + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Private IEs +-- +-- ************************************************************** + +F1AP-PRIVATE-IES ::= CLASS { + &id PrivateIE-ID, + &criticality Criticality, + &Value, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + TYPE &Value + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Container for Protocol IEs +-- +-- ************************************************************** + +ProtocolIE-Container {F1AP-PROTOCOL-IES : IEsSetParam} ::= + SEQUENCE (SIZE (0..maxProtocolIEs)) OF + ProtocolIE-Field {{IEsSetParam}} + +ProtocolIE-SingleContainer {F1AP-PROTOCOL-IES : IEsSetParam} ::= + ProtocolIE-Field {{IEsSetParam}} + +ProtocolIE-Field {F1AP-PROTOCOL-IES : IEsSetParam} ::= SEQUENCE { + id F1AP-PROTOCOL-IES.&id ({IEsSetParam}), + criticality F1AP-PROTOCOL-IES.&criticality ({IEsSetParam}{@id}), + value F1AP-PROTOCOL-IES.&Value ({IEsSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container for Protocol IE Pairs +-- +-- ************************************************************** + +ProtocolIE-ContainerPair {F1AP-PROTOCOL-IES-PAIR : IEsSetParam} ::= + SEQUENCE (SIZE (0..maxProtocolIEs)) OF + ProtocolIE-FieldPair {{IEsSetParam}} + +ProtocolIE-FieldPair {F1AP-PROTOCOL-IES-PAIR : IEsSetParam} ::= SEQUENCE { + id F1AP-PROTOCOL-IES-PAIR.&id ({IEsSetParam}), + firstCriticality F1AP-PROTOCOL-IES-PAIR.&firstCriticality ({IEsSetParam}{@id}), + firstValue F1AP-PROTOCOL-IES-PAIR.&FirstValue ({IEsSetParam}{@id}), + secondCriticality F1AP-PROTOCOL-IES-PAIR.&secondCriticality ({IEsSetParam}{@id}), + secondValue F1AP-PROTOCOL-IES-PAIR.&SecondValue ({IEsSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container for Protocol Extensions +-- +-- ************************************************************** + +ProtocolExtensionContainer {F1AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= + SEQUENCE (SIZE (1..maxProtocolExtensions)) OF + ProtocolExtensionField {{ExtensionSetParam}} + +ProtocolExtensionField {F1AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= SEQUENCE { + id F1AP-PROTOCOL-EXTENSION.&id ({ExtensionSetParam}), + criticality F1AP-PROTOCOL-EXTENSION.&criticality ({ExtensionSetParam}{@id}), + extensionValue F1AP-PROTOCOL-EXTENSION.&Extension ({ExtensionSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container for Private IEs +-- +-- ************************************************************** + +PrivateIE-Container {F1AP-PRIVATE-IES : IEsSetParam } ::= + SEQUENCE (SIZE (1.. maxPrivateIEs)) OF + PrivateIE-Field {{IEsSetParam}} + +PrivateIE-Field {F1AP-PRIVATE-IES : IEsSetParam} ::= SEQUENCE { + id F1AP-PRIVATE-IES.&id ({IEsSetParam}), + criticality F1AP-PRIVATE-IES.&criticality ({IEsSetParam}{@id}), + value F1AP-PRIVATE-IES.&Value ({IEsSetParam}{@id}) +} + +END +-- ASN1STOP diff --git a/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-CommonDataTypes.asn b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-CommonDataTypes.asn new file mode 100644 index 0000000000..da3092376e --- /dev/null +++ b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-CommonDataTypes.asn @@ -0,0 +1,32 @@ +-- ************************************************************** +-- +-- Common definitions +-- +-- ************************************************************** + +F1AP-CommonDataTypes { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-CommonDataTypes (3) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +Criticality ::= ENUMERATED { reject, ignore, notify } + +Presence ::= ENUMERATED { optional, conditional, mandatory } + +PrivateIE-ID ::= CHOICE { + local INTEGER (0..65535), + global OBJECT IDENTIFIER +} + +ProcedureCode ::= INTEGER (0..255) + +ProtocolExtensionID ::= INTEGER (0..65535) + +ProtocolIE-ID ::= INTEGER (0..65535) + +TriggeringMessage ::= ENUMERATED { initiating-message, successful-outcome, unsuccessful-outcome } + +END diff --git a/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-Constants.asn b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-Constants.asn new file mode 100644 index 0000000000..9b5a3dd624 --- /dev/null +++ b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-Constants.asn @@ -0,0 +1,622 @@ +-- ************************************************************** +-- +-- Constant definitions +-- +-- ************************************************************** + +F1AP-Constants { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-Constants (4) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + ProcedureCode, + ProtocolIE-ID + +FROM F1AP-CommonDataTypes; + + +-- ************************************************************** +-- +-- Elementary Procedures +-- +-- ************************************************************** + +id-Reset ProcedureCode ::= 0 +id-F1Setup ProcedureCode ::= 1 +id-ErrorIndication ProcedureCode ::= 2 +id-gNBDUConfigurationUpdate ProcedureCode ::= 3 +id-gNBCUConfigurationUpdate ProcedureCode ::= 4 +id-UEContextSetup ProcedureCode ::= 5 +id-UEContextRelease ProcedureCode ::= 6 +id-UEContextModification ProcedureCode ::= 7 +id-UEContextModificationRequired ProcedureCode ::= 8 +id-UEMobilityCommand ProcedureCode ::= 9 +id-UEContextReleaseRequest ProcedureCode ::= 10 +id-InitialULRRCMessageTransfer ProcedureCode ::= 11 +id-DLRRCMessageTransfer ProcedureCode ::= 12 +id-ULRRCMessageTransfer ProcedureCode ::= 13 +id-privateMessage ProcedureCode ::= 14 +id-UEInactivityNotification ProcedureCode ::= 15 +id-GNBDUResourceCoordination ProcedureCode ::= 16 +id-SystemInformationDeliveryCommand ProcedureCode ::= 17 +id-Paging ProcedureCode ::= 18 +id-Notify ProcedureCode ::= 19 +id-WriteReplaceWarning ProcedureCode ::= 20 +id-PWSCancel ProcedureCode ::= 21 +id-PWSRestartIndication ProcedureCode ::= 22 +id-PWSFailureIndication ProcedureCode ::= 23 +id-GNBDUStatusIndication ProcedureCode ::= 24 +id-RRCDeliveryReport ProcedureCode ::= 25 +id-F1Removal ProcedureCode ::= 26 +id-NetworkAccessRateReduction ProcedureCode ::= 27 +id-TraceStart ProcedureCode ::= 28 +id-DeactivateTrace ProcedureCode ::= 29 +id-DUCURadioInformationTransfer ProcedureCode ::= 30 +id-CUDURadioInformationTransfer ProcedureCode ::= 31 +id-BAPMappingConfiguration ProcedureCode ::= 32 +id-GNBDUResourceConfiguration ProcedureCode ::= 33 +id-IABTNLAddressAllocation ProcedureCode ::= 34 +id-IABUPConfigurationUpdate ProcedureCode ::= 35 +id-resourceStatusReportingInitiation ProcedureCode ::= 36 +id-resourceStatusReporting ProcedureCode ::= 37 +id-accessAndMobilityIndication ProcedureCode ::= 38 +id-accessSuccess ProcedureCode ::= 39 +id-cellTrafficTrace ProcedureCode ::= 40 +id-PositioningMeasurementExchange ProcedureCode ::= 41 +id-PositioningAssistanceInformationControl ProcedureCode ::= 42 +id-PositioningAssistanceInformationFeedback ProcedureCode ::= 43 +id-PositioningMeasurementReport ProcedureCode ::= 44 +id-PositioningMeasurementAbort ProcedureCode ::= 45 +id-PositioningMeasurementFailureIndication ProcedureCode ::= 46 +id-PositioningMeasurementUpdate ProcedureCode ::= 47 +id-TRPInformationExchange ProcedureCode ::= 48 +id-PositioningInformationExchange ProcedureCode ::= 49 +id-PositioningActivation ProcedureCode ::= 50 +id-PositioningDeactivation ProcedureCode ::= 51 +id-E-CIDMeasurementInitiation ProcedureCode ::= 52 +id-E-CIDMeasurementFailureIndication ProcedureCode ::= 53 +id-E-CIDMeasurementReport ProcedureCode ::= 54 +id-E-CIDMeasurementTermination ProcedureCode ::= 55 +id-PositioningInformationUpdate ProcedureCode ::= 56 +id-ReferenceTimeInformationReport ProcedureCode ::= 57 +id-ReferenceTimeInformationReportingControl ProcedureCode ::= 58 + + + +-- ************************************************************** +-- +-- Extension constants +-- +-- ************************************************************** + +maxPrivateIEs INTEGER ::= 65535 +maxProtocolExtensions INTEGER ::= 65535 +maxProtocolIEs INTEGER ::= 65535 +-- ************************************************************** +-- +-- Lists +-- +-- ************************************************************** + +maxNRARFCN INTEGER ::= 3279165 +maxnoofErrors INTEGER ::= 256 +maxnoofIndividualF1ConnectionsToReset INTEGER ::= 65536 +maxCellingNBDU INTEGER ::= 512 +maxnoofSCells INTEGER ::= 32 +maxnoofSRBs INTEGER ::= 8 +maxnoofDRBs INTEGER ::= 64 +maxnoofULUPTNLInformation INTEGER ::= 2 +maxnoofDLUPTNLInformation INTEGER ::= 2 +maxnoofBPLMNs INTEGER ::= 6 +maxnoofCandidateSpCells INTEGER ::= 64 +maxnoofPotentialSpCells INTEGER ::= 64 +maxnoofNrCellBands INTEGER ::= 32 +maxnoofSIBTypes INTEGER ::= 32 +maxnoofSITypes INTEGER ::= 32 +maxnoofPagingCells INTEGER ::= 512 +maxnoofTNLAssociations INTEGER ::= 32 +maxnoofQoSFlows INTEGER ::= 64 +maxnoofSliceItems INTEGER ::= 1024 +maxCellineNB INTEGER ::= 256 +maxnoofExtendedBPLMNs INTEGER ::= 6 +maxnoofUEIDs INTEGER ::= 65536 +maxnoofBPLMNsNR INTEGER ::= 12 +maxnoofUACPLMNs INTEGER ::= 12 +maxnoofUACperPLMN INTEGER ::= 64 +maxnoofAdditionalSIBs INTEGER ::= 63 +maxnoofslots INTEGER ::= 5120 +maxnoofTLAs INTEGER ::= 16 +maxnoofGTPTLAs INTEGER ::= 16 +maxnoofBHRLCChannels INTEGER ::= 65536 +maxnoofRoutingEntries INTEGER ::= 1024 +maxnoofIABSTCInfo INTEGER ::= 45 +maxnoofSymbols INTEGER ::= 14 +maxnoofServingCells INTEGER ::= 32 +maxnoofDUFSlots INTEGER ::= 320 +maxnoofHSNASlots INTEGER ::= 5120 +maxnoofServedCellsIAB INTEGER ::= 512 +maxnoofChildIABNodes INTEGER ::= 1024 +maxnoofNonUPTrafficMappings INTEGER ::= 32 +maxnoofTLAsIAB INTEGER ::= 1024 +maxnoofMappingEntries INTEGER ::= 67108864 +maxnoofDSInfo INTEGER ::= 64 +maxnoofEgressLinks INTEGER ::= 2 +maxnoofULUPTNLInformationforIAB INTEGER ::= 32678 +maxnoofUPTNLAddresses INTEGER ::= 8 +maxnoofSLDRBs INTEGER ::= 512 +maxnoofQoSParaSets INTEGER ::= 8 +maxnoofPC5QoSFlows INTEGER ::= 2048 +maxnoofSSBAreas INTEGER ::= 64 +maxnoofPhysicalResourceBlocks INTEGER ::= 275 +maxnoofPhysicalResourceBlocks-1 INTEGER ::= 274 +maxnoofPRACHconfigs INTEGER ::= 16 +maxnoofRACHReports INTEGER ::= 64 +maxnoofRLFReports INTEGER ::= 64 +maxnoofAdditionalPDCPDuplicationTNL INTEGER ::= 2 +maxnoofRLCDuplicationState INTEGER ::= 3 +maxnoofCHOcells INTEGER ::= 8 +maxnoofMDTPLMNs INTEGER ::= 16 +maxnoofCAGsupported INTEGER ::= 12 +maxnoofNIDsupported INTEGER ::= 12 +maxnoofNRSCSs INTEGER ::= 5 +maxnoofExtSliceItems INTEGER ::= 65535 +maxnoofPosMeas INTEGER ::= 16384 +maxnoofTRPInfoTypes INTEGER ::= 64 +maxnoofTRPs INTEGER ::= 65535 +maxnoofSRSTriggerStates INTEGER ::= 3 +maxnoofSpatialRelations INTEGER ::= 64 +maxnoBcastCell INTEGER ::= 16384 +maxnoofAngleInfo INTEGER ::= 65535 +maxnooflcs-gcs-translation INTEGER ::= 3 +maxnoofPath INTEGER ::= 2 +maxnoofMeasE-CID INTEGER ::= 64 +maxnoofSSBs INTEGER ::= 255 +maxnoSRS-ResourceSets INTEGER ::= 16 +maxnoSRS-ResourcePerSet INTEGER ::= 16 +maxnoSRS-Carriers INTEGER ::= 32 +maxnoSCSs INTEGER ::= 5 +maxnoSRS-Resources INTEGER ::= 64 +maxnoSRS-PosResources INTEGER ::= 64 +maxnoSRS-PosResourceSets INTEGER ::= 16 +maxnoSRS-PosResourcePerSet INTEGER ::= 16 +maxnoofPRS-ResourceSets INTEGER ::= 2 +maxnoofPRS-ResourcesPerSet INTEGER ::= 64 +maxNoOfMeasTRPs INTEGER ::= 64 +maxnoofPRSresourceSets INTEGER ::= 8 +maxnoofPRSresources INTEGER ::= 64 + + + +-- ************************************************************** +-- +-- IEs +-- +-- ************************************************************** + +id-Cause ProtocolIE-ID ::= 0 +id-Cells-Failed-to-be-Activated-List ProtocolIE-ID ::= 1 +id-Cells-Failed-to-be-Activated-List-Item ProtocolIE-ID ::= 2 +id-Cells-to-be-Activated-List ProtocolIE-ID ::= 3 +id-Cells-to-be-Activated-List-Item ProtocolIE-ID ::= 4 +id-Cells-to-be-Deactivated-List ProtocolIE-ID ::= 5 +id-Cells-to-be-Deactivated-List-Item ProtocolIE-ID ::= 6 +id-CriticalityDiagnostics ProtocolIE-ID ::= 7 +id-CUtoDURRCInformation ProtocolIE-ID ::= 9 +id-DRBs-FailedToBeModified-Item ProtocolIE-ID ::= 12 +id-DRBs-FailedToBeModified-List ProtocolIE-ID ::= 13 +id-DRBs-FailedToBeSetup-Item ProtocolIE-ID ::= 14 +id-DRBs-FailedToBeSetup-List ProtocolIE-ID ::= 15 +id-DRBs-FailedToBeSetupMod-Item ProtocolIE-ID ::= 16 +id-DRBs-FailedToBeSetupMod-List ProtocolIE-ID ::= 17 +id-DRBs-ModifiedConf-Item ProtocolIE-ID ::= 18 +id-DRBs-ModifiedConf-List ProtocolIE-ID ::= 19 +id-DRBs-Modified-Item ProtocolIE-ID ::= 20 +id-DRBs-Modified-List ProtocolIE-ID ::= 21 +id-DRBs-Required-ToBeModified-Item ProtocolIE-ID ::= 22 +id-DRBs-Required-ToBeModified-List ProtocolIE-ID ::= 23 +id-DRBs-Required-ToBeReleased-Item ProtocolIE-ID ::= 24 +id-DRBs-Required-ToBeReleased-List ProtocolIE-ID ::= 25 +id-DRBs-Setup-Item ProtocolIE-ID ::= 26 +id-DRBs-Setup-List ProtocolIE-ID ::= 27 +id-DRBs-SetupMod-Item ProtocolIE-ID ::= 28 +id-DRBs-SetupMod-List ProtocolIE-ID ::= 29 +id-DRBs-ToBeModified-Item ProtocolIE-ID ::= 30 +id-DRBs-ToBeModified-List ProtocolIE-ID ::= 31 +id-DRBs-ToBeReleased-Item ProtocolIE-ID ::= 32 +id-DRBs-ToBeReleased-List ProtocolIE-ID ::= 33 +id-DRBs-ToBeSetup-Item ProtocolIE-ID ::= 34 +id-DRBs-ToBeSetup-List ProtocolIE-ID ::= 35 +id-DRBs-ToBeSetupMod-Item ProtocolIE-ID ::= 36 +id-DRBs-ToBeSetupMod-List ProtocolIE-ID ::= 37 +id-DRXCycle ProtocolIE-ID ::= 38 +id-DUtoCURRCInformation ProtocolIE-ID ::= 39 +id-gNB-CU-UE-F1AP-ID ProtocolIE-ID ::= 40 +id-gNB-DU-UE-F1AP-ID ProtocolIE-ID ::= 41 +id-gNB-DU-ID ProtocolIE-ID ::= 42 +id-GNB-DU-Served-Cells-Item ProtocolIE-ID ::= 43 +id-gNB-DU-Served-Cells-List ProtocolIE-ID ::= 44 +id-gNB-DU-Name ProtocolIE-ID ::= 45 +id-NRCellID ProtocolIE-ID ::= 46 +id-oldgNB-DU-UE-F1AP-ID ProtocolIE-ID ::= 47 +id-ResetType ProtocolIE-ID ::= 48 +id-ResourceCoordinationTransferContainer ProtocolIE-ID ::= 49 +id-RRCContainer ProtocolIE-ID ::= 50 +id-SCell-ToBeRemoved-Item ProtocolIE-ID ::= 51 +id-SCell-ToBeRemoved-List ProtocolIE-ID ::= 52 +id-SCell-ToBeSetup-Item ProtocolIE-ID ::= 53 +id-SCell-ToBeSetup-List ProtocolIE-ID ::= 54 +id-SCell-ToBeSetupMod-Item ProtocolIE-ID ::= 55 +id-SCell-ToBeSetupMod-List ProtocolIE-ID ::= 56 +id-Served-Cells-To-Add-Item ProtocolIE-ID ::= 57 +id-Served-Cells-To-Add-List ProtocolIE-ID ::= 58 +id-Served-Cells-To-Delete-Item ProtocolIE-ID ::= 59 +id-Served-Cells-To-Delete-List ProtocolIE-ID ::= 60 +id-Served-Cells-To-Modify-Item ProtocolIE-ID ::= 61 +id-Served-Cells-To-Modify-List ProtocolIE-ID ::= 62 +id-SpCell-ID ProtocolIE-ID ::= 63 +id-SRBID ProtocolIE-ID ::= 64 +id-SRBs-FailedToBeSetup-Item ProtocolIE-ID ::= 65 +id-SRBs-FailedToBeSetup-List ProtocolIE-ID ::= 66 +id-SRBs-FailedToBeSetupMod-Item ProtocolIE-ID ::= 67 +id-SRBs-FailedToBeSetupMod-List ProtocolIE-ID ::= 68 +id-SRBs-Required-ToBeReleased-Item ProtocolIE-ID ::= 69 +id-SRBs-Required-ToBeReleased-List ProtocolIE-ID ::= 70 +id-SRBs-ToBeReleased-Item ProtocolIE-ID ::= 71 +id-SRBs-ToBeReleased-List ProtocolIE-ID ::= 72 +id-SRBs-ToBeSetup-Item ProtocolIE-ID ::= 73 +id-SRBs-ToBeSetup-List ProtocolIE-ID ::= 74 +id-SRBs-ToBeSetupMod-Item ProtocolIE-ID ::= 75 +id-SRBs-ToBeSetupMod-List ProtocolIE-ID ::= 76 +id-TimeToWait ProtocolIE-ID ::= 77 +id-TransactionID ProtocolIE-ID ::= 78 +id-TransmissionActionIndicator ProtocolIE-ID ::= 79 +id-UE-associatedLogicalF1-ConnectionItem ProtocolIE-ID ::= 80 +id-UE-associatedLogicalF1-ConnectionListResAck ProtocolIE-ID ::= 81 +id-gNB-CU-Name ProtocolIE-ID ::= 82 +id-SCell-FailedtoSetup-List ProtocolIE-ID ::= 83 +id-SCell-FailedtoSetup-Item ProtocolIE-ID ::= 84 +id-SCell-FailedtoSetupMod-List ProtocolIE-ID ::= 85 +id-SCell-FailedtoSetupMod-Item ProtocolIE-ID ::= 86 +id-RRCReconfigurationCompleteIndicator ProtocolIE-ID ::= 87 +id-Cells-Status-Item ProtocolIE-ID ::= 88 +id-Cells-Status-List ProtocolIE-ID ::= 89 +id-Candidate-SpCell-List ProtocolIE-ID ::= 90 +id-Candidate-SpCell-Item ProtocolIE-ID ::= 91 +id-Potential-SpCell-List ProtocolIE-ID ::= 92 +id-Potential-SpCell-Item ProtocolIE-ID ::= 93 +id-FullConfiguration ProtocolIE-ID ::= 94 +id-C-RNTI ProtocolIE-ID ::= 95 +id-SpCellULConfigured ProtocolIE-ID ::= 96 +id-InactivityMonitoringRequest ProtocolIE-ID ::= 97 +id-InactivityMonitoringResponse ProtocolIE-ID ::= 98 +id-DRB-Activity-Item ProtocolIE-ID ::= 99 +id-DRB-Activity-List ProtocolIE-ID ::= 100 +id-EUTRA-NR-CellResourceCoordinationReq-Container ProtocolIE-ID ::= 101 +id-EUTRA-NR-CellResourceCoordinationReqAck-Container ProtocolIE-ID ::= 102 +id-Protected-EUTRA-Resources-List ProtocolIE-ID ::= 105 +id-RequestType ProtocolIE-ID ::= 106 +id-ServCellIndex ProtocolIE-ID ::= 107 +id-RAT-FrequencyPriorityInformation ProtocolIE-ID ::= 108 +id-ExecuteDuplication ProtocolIE-ID ::= 109 +id-NRCGI ProtocolIE-ID ::= 111 +id-PagingCell-Item ProtocolIE-ID ::= 112 +id-PagingCell-List ProtocolIE-ID ::= 113 +id-PagingDRX ProtocolIE-ID ::= 114 +id-PagingPriority ProtocolIE-ID ::= 115 +id-SItype-List ProtocolIE-ID ::= 116 +id-UEIdentityIndexValue ProtocolIE-ID ::= 117 +id-gNB-CUSystemInformation ProtocolIE-ID ::= 118 +id-HandoverPreparationInformation ProtocolIE-ID ::= 119 +id-GNB-CU-TNL-Association-To-Add-Item ProtocolIE-ID ::= 120 +id-GNB-CU-TNL-Association-To-Add-List ProtocolIE-ID ::= 121 +id-GNB-CU-TNL-Association-To-Remove-Item ProtocolIE-ID ::= 122 +id-GNB-CU-TNL-Association-To-Remove-List ProtocolIE-ID ::= 123 +id-GNB-CU-TNL-Association-To-Update-Item ProtocolIE-ID ::= 124 +id-GNB-CU-TNL-Association-To-Update-List ProtocolIE-ID ::= 125 +id-MaskedIMEISV ProtocolIE-ID ::= 126 +id-PagingIdentity ProtocolIE-ID ::= 127 +id-DUtoCURRCContainer ProtocolIE-ID ::= 128 +id-Cells-to-be-Barred-List ProtocolIE-ID ::= 129 +id-Cells-to-be-Barred-Item ProtocolIE-ID ::= 130 +id-TAISliceSupportList ProtocolIE-ID ::= 131 +id-GNB-CU-TNL-Association-Setup-List ProtocolIE-ID ::= 132 +id-GNB-CU-TNL-Association-Setup-Item ProtocolIE-ID ::= 133 +id-GNB-CU-TNL-Association-Failed-To-Setup-List ProtocolIE-ID ::= 134 +id-GNB-CU-TNL-Association-Failed-To-Setup-Item ProtocolIE-ID ::= 135 +id-DRB-Notify-Item ProtocolIE-ID ::= 136 +id-DRB-Notify-List ProtocolIE-ID ::= 137 +id-NotficationControl ProtocolIE-ID ::= 138 +id-RANAC ProtocolIE-ID ::= 139 +id-PWSSystemInformation ProtocolIE-ID ::= 140 +id-RepetitionPeriod ProtocolIE-ID ::= 141 +id-NumberofBroadcastRequest ProtocolIE-ID ::= 142 +id-Cells-To-Be-Broadcast-List ProtocolIE-ID ::= 144 +id-Cells-To-Be-Broadcast-Item ProtocolIE-ID ::= 145 +id-Cells-Broadcast-Completed-List ProtocolIE-ID ::= 146 +id-Cells-Broadcast-Completed-Item ProtocolIE-ID ::= 147 +id-Broadcast-To-Be-Cancelled-List ProtocolIE-ID ::= 148 +id-Broadcast-To-Be-Cancelled-Item ProtocolIE-ID ::= 149 +id-Cells-Broadcast-Cancelled-List ProtocolIE-ID ::= 150 +id-Cells-Broadcast-Cancelled-Item ProtocolIE-ID ::= 151 +id-NR-CGI-List-For-Restart-List ProtocolIE-ID ::= 152 +id-NR-CGI-List-For-Restart-Item ProtocolIE-ID ::= 153 +id-PWS-Failed-NR-CGI-List ProtocolIE-ID ::= 154 +id-PWS-Failed-NR-CGI-Item ProtocolIE-ID ::= 155 +id-ConfirmedUEID ProtocolIE-ID ::= 156 +id-Cancel-all-Warning-Messages-Indicator ProtocolIE-ID ::= 157 +id-GNB-DU-UE-AMBR-UL ProtocolIE-ID ::= 158 +id-DRXConfigurationIndicator ProtocolIE-ID ::= 159 +id-RLC-Status ProtocolIE-ID ::= 160 +id-DLPDCPSNLength ProtocolIE-ID ::= 161 +id-GNB-DUConfigurationQuery ProtocolIE-ID ::= 162 +id-MeasurementTimingConfiguration ProtocolIE-ID ::= 163 +id-DRB-Information ProtocolIE-ID ::= 164 +id-ServingPLMN ProtocolIE-ID ::= 165 +id-Protected-EUTRA-Resources-Item ProtocolIE-ID ::= 168 +id-GNB-CU-RRC-Version ProtocolIE-ID ::= 170 +id-GNB-DU-RRC-Version ProtocolIE-ID ::= 171 +id-GNBDUOverloadInformation ProtocolIE-ID ::= 172 +id-CellGroupConfig ProtocolIE-ID ::= 173 +id-RLCFailureIndication ProtocolIE-ID ::= 174 +id-UplinkTxDirectCurrentListInformation ProtocolIE-ID ::= 175 +id-DC-Based-Duplication-Configured ProtocolIE-ID ::= 176 +id-DC-Based-Duplication-Activation ProtocolIE-ID ::= 177 +id-SULAccessIndication ProtocolIE-ID ::= 178 +id-AvailablePLMNList ProtocolIE-ID ::= 179 +id-PDUSessionID ProtocolIE-ID ::= 180 +id-ULPDUSessionAggregateMaximumBitRate ProtocolIE-ID ::= 181 +id-ServingCellMO ProtocolIE-ID ::= 182 +id-QoSFlowMappingIndication ProtocolIE-ID ::= 183 +id-RRCDeliveryStatusRequest ProtocolIE-ID ::= 184 +id-RRCDeliveryStatus ProtocolIE-ID ::= 185 +id-BearerTypeChange ProtocolIE-ID ::= 186 +id-RLCMode ProtocolIE-ID ::= 187 +id-Duplication-Activation ProtocolIE-ID ::= 188 +id-Dedicated-SIDelivery-NeededUE-List ProtocolIE-ID ::= 189 +id-Dedicated-SIDelivery-NeededUE-Item ProtocolIE-ID ::= 190 +id-DRX-LongCycleStartOffset ProtocolIE-ID ::= 191 +id-ULPDCPSNLength ProtocolIE-ID ::= 192 +id-SelectedBandCombinationIndex ProtocolIE-ID ::= 193 +id-SelectedFeatureSetEntryIndex ProtocolIE-ID ::= 194 +id-ResourceCoordinationTransferInformation ProtocolIE-ID ::= 195 +id-ExtendedServedPLMNs-List ProtocolIE-ID ::= 196 +id-ExtendedAvailablePLMN-List ProtocolIE-ID ::= 197 +id-Associated-SCell-List ProtocolIE-ID ::= 198 +id-latest-RRC-Version-Enhanced ProtocolIE-ID ::= 199 +id-Associated-SCell-Item ProtocolIE-ID ::= 200 +id-Cell-Direction ProtocolIE-ID ::= 201 +id-SRBs-Setup-List ProtocolIE-ID ::= 202 +id-SRBs-Setup-Item ProtocolIE-ID ::= 203 +id-SRBs-SetupMod-List ProtocolIE-ID ::= 204 +id-SRBs-SetupMod-Item ProtocolIE-ID ::= 205 +id-SRBs-Modified-List ProtocolIE-ID ::= 206 +id-SRBs-Modified-Item ProtocolIE-ID ::= 207 +id-Ph-InfoSCG ProtocolIE-ID ::= 208 +id-RequestedBandCombinationIndex ProtocolIE-ID ::= 209 +id-RequestedFeatureSetEntryIndex ProtocolIE-ID ::= 210 +id-RequestedP-MaxFR2 ProtocolIE-ID ::= 211 +id-DRX-Config ProtocolIE-ID ::= 212 +id-IgnoreResourceCoordinationContainer ProtocolIE-ID ::= 213 +id-UEAssistanceInformation ProtocolIE-ID ::= 214 +id-NeedforGap ProtocolIE-ID ::= 215 +id-PagingOrigin ProtocolIE-ID ::= 216 +id-new-gNB-CU-UE-F1AP-ID ProtocolIE-ID ::= 217 +id-RedirectedRRCmessage ProtocolIE-ID ::= 218 +id-new-gNB-DU-UE-F1AP-ID ProtocolIE-ID ::= 219 +id-NotificationInformation ProtocolIE-ID ::= 220 +id-PLMNAssistanceInfoForNetShar ProtocolIE-ID ::= 221 +id-UEContextNotRetrievable ProtocolIE-ID ::= 222 +id-BPLMN-ID-Info-List ProtocolIE-ID ::= 223 +id-SelectedPLMNID ProtocolIE-ID ::= 224 +id-UAC-Assistance-Info ProtocolIE-ID ::= 225 +id-RANUEID ProtocolIE-ID ::= 226 +id-GNB-DU-TNL-Association-To-Remove-Item ProtocolIE-ID ::= 227 +id-GNB-DU-TNL-Association-To-Remove-List ProtocolIE-ID ::= 228 +id-TNLAssociationTransportLayerAddressgNBDU ProtocolIE-ID ::= 229 +id-portNumber ProtocolIE-ID ::= 230 +id-AdditionalSIBMessageList ProtocolIE-ID ::= 231 +id-Cell-Type ProtocolIE-ID ::= 232 +id-IgnorePRACHConfiguration ProtocolIE-ID ::= 233 +id-CG-Config ProtocolIE-ID ::= 234 +id-PDCCH-BlindDetectionSCG ProtocolIE-ID ::= 235 +id-Requested-PDCCH-BlindDetectionSCG ProtocolIE-ID ::= 236 +id-Ph-InfoMCG ProtocolIE-ID ::= 237 +id-MeasGapSharingConfig ProtocolIE-ID ::= 238 +id-systemInformationAreaID ProtocolIE-ID ::= 239 +id-areaScope ProtocolIE-ID ::= 240 +id-RRCContainer-RRCSetupComplete ProtocolIE-ID ::= 241 +id-TraceActivation ProtocolIE-ID ::= 242 +id-TraceID ProtocolIE-ID ::= 243 +id-Neighbour-Cell-Information-List ProtocolIE-ID ::= 244 +id-SymbolAllocInSlot ProtocolIE-ID ::= 246 +id-NumDLULSymbols ProtocolIE-ID ::= 247 +id-AdditionalRRMPriorityIndex ProtocolIE-ID ::= 248 +id-DUCURadioInformationType ProtocolIE-ID ::= 249 +id-CUDURadioInformationType ProtocolIE-ID ::= 250 +id-AggressorgNBSetID ProtocolIE-ID ::= 251 +id-VictimgNBSetID ProtocolIE-ID ::= 252 +id-LowerLayerPresenceStatusChange ProtocolIE-ID ::= 253 +id-Transport-Layer-Address-Info ProtocolIE-ID ::= 254 +id-Neighbour-Cell-Information-Item ProtocolIE-ID ::= 255 +id-IntendedTDD-DL-ULConfig ProtocolIE-ID ::= 256 +id-QosMonitoringRequest ProtocolIE-ID ::= 257 +id-BHChannels-ToBeSetup-List ProtocolIE-ID ::= 258 +id-BHChannels-ToBeSetup-Item ProtocolIE-ID ::= 259 +id-BHChannels-Setup-List ProtocolIE-ID ::= 260 +id-BHChannels-Setup-Item ProtocolIE-ID ::= 261 +id-BHChannels-ToBeModified-Item ProtocolIE-ID ::= 262 +id-BHChannels-ToBeModified-List ProtocolIE-ID ::= 263 +id-BHChannels-ToBeReleased-Item ProtocolIE-ID ::= 264 +id-BHChannels-ToBeReleased-List ProtocolIE-ID ::= 265 +id-BHChannels-ToBeSetupMod-Item ProtocolIE-ID ::= 266 +id-BHChannels-ToBeSetupMod-List ProtocolIE-ID ::= 267 +id-BHChannels-FailedToBeModified-Item ProtocolIE-ID ::= 268 +id-BHChannels-FailedToBeModified-List ProtocolIE-ID ::= 269 +id-BHChannels-FailedToBeSetupMod-Item ProtocolIE-ID ::= 270 +id-BHChannels-FailedToBeSetupMod-List ProtocolIE-ID ::= 271 +id-BHChannels-Modified-Item ProtocolIE-ID ::= 272 +id-BHChannels-Modified-List ProtocolIE-ID ::= 273 +id-BHChannels-SetupMod-Item ProtocolIE-ID ::= 274 +id-BHChannels-SetupMod-List ProtocolIE-ID ::= 275 +id-BHChannels-Required-ToBeReleased-Item ProtocolIE-ID ::= 276 +id-BHChannels-Required-ToBeReleased-List ProtocolIE-ID ::= 277 +id-BHChannels-FailedToBeSetup-Item ProtocolIE-ID ::= 278 +id-BHChannels-FailedToBeSetup-List ProtocolIE-ID ::= 279 +id-BHInfo ProtocolIE-ID ::= 280 +id-BAPAddress ProtocolIE-ID ::= 281 +id-ConfiguredBAPAddress ProtocolIE-ID ::= 282 +id-BH-Routing-Information-Added-List ProtocolIE-ID ::= 283 +id-BH-Routing-Information-Added-List-Item ProtocolIE-ID ::= 284 +id-BH-Routing-Information-Removed-List ProtocolIE-ID ::= 285 +id-BH-Routing-Information-Removed-List-Item ProtocolIE-ID ::= 286 +id-UL-BH-Non-UP-Traffic-Mapping ProtocolIE-ID ::= 287 +id-Activated-Cells-to-be-Updated-List ProtocolIE-ID ::= 288 +id-Child-Nodes-List ProtocolIE-ID ::= 289 +id-IAB-Info-IAB-DU ProtocolIE-ID ::= 290 +id-IAB-Info-IAB-donor-CU ProtocolIE-ID ::= 291 +id-IAB-TNL-Addresses-To-Remove-List ProtocolIE-ID ::= 292 +id-IAB-TNL-Addresses-To-Remove-Item ProtocolIE-ID ::= 293 +id-IAB-Allocated-TNL-Address-List ProtocolIE-ID ::= 294 +id-IAB-Allocated-TNL-Address-Item ProtocolIE-ID ::= 295 +id-IABIPv6RequestType ProtocolIE-ID ::= 296 +id-IABv4AddressesRequested ProtocolIE-ID ::= 297 +id-IAB-Barred ProtocolIE-ID ::= 298 +id-TrafficMappingInformation ProtocolIE-ID ::= 299 +id-UL-UP-TNL-Information-to-Update-List ProtocolIE-ID ::= 300 +id-UL-UP-TNL-Information-to-Update-List-Item ProtocolIE-ID ::= 301 +id-UL-UP-TNL-Address-to-Update-List ProtocolIE-ID ::= 302 +id-UL-UP-TNL-Address-to-Update-List-Item ProtocolIE-ID ::= 303 +id-DL-UP-TNL-Address-to-Update-List ProtocolIE-ID ::= 304 +id-DL-UP-TNL-Address-to-Update-List-Item ProtocolIE-ID ::= 305 +id-NRV2XServicesAuthorized ProtocolIE-ID ::= 306 +id-LTEV2XServicesAuthorized ProtocolIE-ID ::= 307 +id-NRUESidelinkAggregateMaximumBitrate ProtocolIE-ID ::= 308 +id-LTEUESidelinkAggregateMaximumBitrate ProtocolIE-ID ::= 309 +id-SIB12-message ProtocolIE-ID ::= 310 +id-SIB13-message ProtocolIE-ID ::= 311 +id-SIB14-message ProtocolIE-ID ::= 312 +id-SLDRBs-FailedToBeModified-Item ProtocolIE-ID ::= 313 +id-SLDRBs-FailedToBeModified-List ProtocolIE-ID ::= 314 +id-SLDRBs-FailedToBeSetup-Item ProtocolIE-ID ::= 315 +id-SLDRBs-FailedToBeSetup-List ProtocolIE-ID ::= 316 +id-SLDRBs-Modified-Item ProtocolIE-ID ::= 317 +id-SLDRBs-Modified-List ProtocolIE-ID ::= 318 +id-SLDRBs-Required-ToBeModified-Item ProtocolIE-ID ::= 319 +id-SLDRBs-Required-ToBeModified-List ProtocolIE-ID ::= 320 +id-SLDRBs-Required-ToBeReleased-Item ProtocolIE-ID ::= 321 +id-SLDRBs-Required-ToBeReleased-List ProtocolIE-ID ::= 322 +id-SLDRBs-Setup-Item ProtocolIE-ID ::= 323 +id-SLDRBs-Setup-List ProtocolIE-ID ::= 324 +id-SLDRBs-ToBeModified-Item ProtocolIE-ID ::= 325 +id-SLDRBs-ToBeModified-List ProtocolIE-ID ::= 326 +id-SLDRBs-ToBeReleased-Item ProtocolIE-ID ::= 327 +id-SLDRBs-ToBeReleased-List ProtocolIE-ID ::= 328 +id-SLDRBs-ToBeSetup-Item ProtocolIE-ID ::= 329 +id-SLDRBs-ToBeSetup-List ProtocolIE-ID ::= 330 +id-SLDRBs-ToBeSetupMod-Item ProtocolIE-ID ::= 331 +id-SLDRBs-ToBeSetupMod-List ProtocolIE-ID ::= 332 +id-SLDRBs-SetupMod-List ProtocolIE-ID ::= 333 +id-SLDRBs-FailedToBeSetupMod-List ProtocolIE-ID ::= 334 +id-SLDRBs-SetupMod-Item ProtocolIE-ID ::= 335 +id-SLDRBs-FailedToBeSetupMod-Item ProtocolIE-ID ::= 336 +id-SLDRBs-ModifiedConf-List ProtocolIE-ID ::= 337 +id-SLDRBs-ModifiedConf-Item ProtocolIE-ID ::= 338 +id-UEAssistanceInformationEUTRA ProtocolIE-ID ::= 339 +id-PC5LinkAMBR ProtocolIE-ID ::= 340 +id-SL-PHY-MAC-RLC-Config ProtocolIE-ID ::= 341 +id-SL-ConfigDedicatedEUTRA ProtocolIE-ID ::= 342 +id-AlternativeQoSParaSetList ProtocolIE-ID ::= 343 +id-CurrentQoSParaSetIndex ProtocolIE-ID ::= 344 +id-gNBCUMeasurementID ProtocolIE-ID ::= 345 +id-gNBDUMeasurementID ProtocolIE-ID ::= 346 +id-RegistrationRequest ProtocolIE-ID ::= 347 +id-ReportCharacteristics ProtocolIE-ID ::= 348 +id-CellToReportList ProtocolIE-ID ::= 349 +id-CellMeasurementResultList ProtocolIE-ID ::= 350 +id-HardwareLoadIndicator ProtocolIE-ID ::= 351 +id-ReportingPeriodicity ProtocolIE-ID ::= 352 +id-TNLCapacityIndicator ProtocolIE-ID ::= 353 +id-CarrierList ProtocolIE-ID ::= 354 +id-ULCarrierList ProtocolIE-ID ::= 355 +id-FrequencyShift7p5khz ProtocolIE-ID ::= 356 +id-SSB-PositionsInBurst ProtocolIE-ID ::= 357 +id-NRPRACHConfig ProtocolIE-ID ::= 358 +id-RACHReportInformationList ProtocolIE-ID ::= 359 +id-RLFReportInformationList ProtocolIE-ID ::= 360 +id-TDD-UL-DLConfigCommonNR ProtocolIE-ID ::= 361 +id-CNPacketDelayBudgetDownlink ProtocolIE-ID ::= 362 +id-ExtendedPacketDelayBudget ProtocolIE-ID ::= 363 +id-TSCTrafficCharacteristics ProtocolIE-ID ::= 364 +id-ReportingRequestType ProtocolIE-ID ::= 365 +id-TimeReferenceInformation ProtocolIE-ID ::= 366 +id-CNPacketDelayBudgetUplink ProtocolIE-ID ::= 369 +id-AdditionalPDCPDuplicationTNL-List ProtocolIE-ID ::= 370 +id-RLCDuplicationInformation ProtocolIE-ID ::= 371 +id-AdditionalDuplicationIndication ProtocolIE-ID ::= 372 +id-ConditionalInterDUMobilityInformation ProtocolIE-ID ::= 373 +id-ConditionalIntraDUMobilityInformation ProtocolIE-ID ::= 374 +id-targetCellsToCancel ProtocolIE-ID ::= 375 +id-requestedTargetCellGlobalID ProtocolIE-ID ::= 376 +id-ManagementBasedMDTPLMNList ProtocolIE-ID ::= 377 +id-TraceCollectionEntityIPAddress ProtocolIE-ID ::= 378 +id-PrivacyIndicator ProtocolIE-ID ::= 379 +id-TraceCollectionEntityURI ProtocolIE-ID ::= 380 +id-mdtConfiguration ProtocolIE-ID ::= 381 +id-ServingNID ProtocolIE-ID ::= 382 +id-NPNBroadcastInformation ProtocolIE-ID ::= 383 +id-NPNSupportInfo ProtocolIE-ID ::= 384 +id-NID ProtocolIE-ID ::= 385 +id-AvailableSNPN-ID-List ProtocolIE-ID ::= 386 +id-SIB10-message ProtocolIE-ID ::= 387 +id-DLCarrierList ProtocolIE-ID ::= 389 + id-ExtendedTAISliceSupportList ProtocolIE-ID ::= 390 +id-RequestedSRSTransmissionCharacteristics ProtocolIE-ID ::= 391 +id-PosAssistance-Information ProtocolIE-ID ::= 392 +id-PosBroadcast ProtocolIE-ID ::= 393 +id-RoutingID ProtocolIE-ID ::= 394 +id-PosAssistanceInformationFailureList ProtocolIE-ID ::= 395 +id-PosMeasurementQuantities ProtocolIE-ID ::= 396 +id-PosMeasurementResultList ProtocolIE-ID ::= 397 +id-TRPInformationTypeListTRPReq ProtocolIE-ID ::= 398 +id-TRPInformationTypeItem ProtocolIE-ID ::= 399 +id-TRPInformationListTRPResp ProtocolIE-ID ::= 400 +id-TRPInformationItem ProtocolIE-ID ::= 401 +id-LMF-MeasurementID ProtocolIE-ID ::= 402 +id-SRSType ProtocolIE-ID ::= 403 +id-ActivationTime ProtocolIE-ID ::= 404 +id-AbortTransmission ProtocolIE-ID ::= 405 +id-PositioningBroadcastCells ProtocolIE-ID ::= 406 +id-SRSConfiguration ProtocolIE-ID ::= 407 +id-PosReportCharacteristics ProtocolIE-ID ::= 408 +id-PosMeasurementPeriodicity ProtocolIE-ID ::= 409 +id-TRPList ProtocolIE-ID ::= 410 +id-RAN-MeasurementID ProtocolIE-ID ::= 411 +id-LMF-UE-MeasurementID ProtocolIE-ID ::= 412 +id-RAN-UE-MeasurementID ProtocolIE-ID ::= 413 +id-E-CID-MeasurementQuantities ProtocolIE-ID ::= 414 +id-E-CID-MeasurementQuantities-Item ProtocolIE-ID ::= 415 +id-E-CID-MeasurementPeriodicity ProtocolIE-ID ::= 416 +id-E-CID-MeasurementResult ProtocolIE-ID ::= 417 +id-Cell-Portion-ID ProtocolIE-ID ::= 418 +id-SFNInitialisationTime ProtocolIE-ID ::= 419 +id-SystemFrameNumber ProtocolIE-ID ::= 420 +id-SlotNumber ProtocolIE-ID ::= 421 +id-TRP-MeasurementRequestList ProtocolIE-ID ::= 422 +id-MeasurementBeamInfoRequest ProtocolIE-ID ::= 423 +id-E-CID-ReportCharacteristics ProtocolIE-ID ::= 424 +id-ConfiguredTACIndication ProtocolIE-ID ::= 425 +id-Extended-GNB-DU-Name ProtocolIE-ID ::= 426 +id-Extended-GNB-CU-Name ProtocolIE-ID ::= 427 + + +END diff --git a/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-Containers.asn b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-Containers.asn new file mode 100644 index 0000000000..72c6d6e551 --- /dev/null +++ b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-Containers.asn @@ -0,0 +1,178 @@ +F1AP-Containers { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-Containers (5) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + Criticality, + Presence, + PrivateIE-ID, + ProtocolExtensionID, + ProtocolIE-ID + +FROM F1AP-CommonDataTypes + maxPrivateIEs, + maxProtocolExtensions, + maxProtocolIEs + +FROM F1AP-Constants; + +-- ************************************************************** +-- +-- Class Definition for Protocol IEs +-- +-- ************************************************************** + +F1AP-PROTOCOL-IES ::= CLASS { + &id ProtocolIE-ID UNIQUE, + &criticality Criticality, + &Value, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + TYPE &Value + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Protocol IEs +-- +-- ************************************************************** + +F1AP-PROTOCOL-IES-PAIR ::= CLASS { + &id ProtocolIE-ID UNIQUE, + &firstCriticality Criticality, + &FirstValue, + &secondCriticality Criticality, + &SecondValue, + &presence Presence +} +WITH SYNTAX { + ID &id + FIRST CRITICALITY &firstCriticality + FIRST TYPE &FirstValue + SECOND CRITICALITY &secondCriticality + SECOND TYPE &SecondValue + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Protocol Extensions +-- +-- ************************************************************** + +F1AP-PROTOCOL-EXTENSION ::= CLASS { + &id ProtocolExtensionID UNIQUE, + &criticality Criticality, + &Extension, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + EXTENSION &Extension + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Private IEs +-- +-- ************************************************************** + +F1AP-PRIVATE-IES ::= CLASS { + &id PrivateIE-ID, + &criticality Criticality, + &Value, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + TYPE &Value + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Container for Protocol IEs +-- +-- ************************************************************** + +ProtocolIE-Container {F1AP-PROTOCOL-IES : IEsSetParam} ::= + SEQUENCE (SIZE (0..maxProtocolIEs)) OF + ProtocolIE-Field {{IEsSetParam}} + +ProtocolIE-SingleContainer {F1AP-PROTOCOL-IES : IEsSetParam} ::= + ProtocolIE-Field {{IEsSetParam}} + +ProtocolIE-Field {F1AP-PROTOCOL-IES : IEsSetParam} ::= SEQUENCE { + id F1AP-PROTOCOL-IES.&id ({IEsSetParam}), + criticality F1AP-PROTOCOL-IES.&criticality ({IEsSetParam}{@id}), + value F1AP-PROTOCOL-IES.&Value ({IEsSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container for Protocol IE Pairs +-- +-- ************************************************************** + +ProtocolIE-ContainerPair {F1AP-PROTOCOL-IES-PAIR : IEsSetParam} ::= + SEQUENCE (SIZE (0..maxProtocolIEs)) OF + ProtocolIE-FieldPair {{IEsSetParam}} + +ProtocolIE-FieldPair {F1AP-PROTOCOL-IES-PAIR : IEsSetParam} ::= SEQUENCE { + id F1AP-PROTOCOL-IES-PAIR.&id ({IEsSetParam}), + firstCriticality F1AP-PROTOCOL-IES-PAIR.&firstCriticality ({IEsSetParam}{@id}), + firstValue F1AP-PROTOCOL-IES-PAIR.&FirstValue ({IEsSetParam}{@id}), + secondCriticality F1AP-PROTOCOL-IES-PAIR.&secondCriticality ({IEsSetParam}{@id}), + secondValue F1AP-PROTOCOL-IES-PAIR.&SecondValue ({IEsSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container for Protocol Extensions +-- +-- ************************************************************** + +ProtocolExtensionContainer {F1AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= + SEQUENCE (SIZE (1..maxProtocolExtensions)) OF + ProtocolExtensionField {{ExtensionSetParam}} + +ProtocolExtensionField {F1AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= SEQUENCE { + id F1AP-PROTOCOL-EXTENSION.&id ({ExtensionSetParam}), + criticality F1AP-PROTOCOL-EXTENSION.&criticality ({ExtensionSetParam}{@id}), + extensionValue F1AP-PROTOCOL-EXTENSION.&Extension ({ExtensionSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container for Private IEs +-- +-- ************************************************************** + +PrivateIE-Container {F1AP-PRIVATE-IES : IEsSetParam } ::= + SEQUENCE (SIZE (1.. maxPrivateIEs)) OF + PrivateIE-Field {{IEsSetParam}} + +PrivateIE-Field {F1AP-PRIVATE-IES : IEsSetParam} ::= SEQUENCE { + id F1AP-PRIVATE-IES.&id ({IEsSetParam}), + criticality F1AP-PRIVATE-IES.&criticality ({IEsSetParam}{@id}), + value F1AP-PRIVATE-IES.&Value ({IEsSetParam}{@id}) +} + +END diff --git a/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-IEs.asn b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-IEs.asn new file mode 100644 index 0000000000..3e02e1b27e --- /dev/null +++ b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-IEs.asn @@ -0,0 +1,5509 @@ +-- ************************************************************** +-- +-- Information Element Definitions +-- +-- ************************************************************** + +F1AP-IEs { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-IEs (2) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + id-gNB-CUSystemInformation, + id-HandoverPreparationInformation, + id-TAISliceSupportList, + id-RANAC, + id-BearerTypeChange, + id-Cell-Direction, + id-Cell-Type, + id-CellGroupConfig, + id-AvailablePLMNList, + id-PDUSessionID, + id-ULPDUSessionAggregateMaximumBitRate, + id-DC-Based-Duplication-Configured, + id-DC-Based-Duplication-Activation, + id-Duplication-Activation, + id-DLPDCPSNLength, + id-ULPDCPSNLength, + id-RLC-Status, + id-MeasurementTimingConfiguration, + id-DRB-Information, + id-QoSFlowMappingIndication, + id-ServingCellMO, + id-RLCMode, + id-ExtendedServedPLMNs-List, + id-ExtendedAvailablePLMN-List, + id-DRX-LongCycleStartOffset, + id-SelectedBandCombinationIndex, + id-SelectedFeatureSetEntryIndex, + id-Ph-InfoSCG, + id-latest-RRC-Version-Enhanced, + id-RequestedBandCombinationIndex, + id-RequestedFeatureSetEntryIndex, + id-DRX-Config, + id-UEAssistanceInformation, + id-PDCCH-BlindDetectionSCG, + id-Requested-PDCCH-BlindDetectionSCG, + id-BPLMN-ID-Info-List, + id-NotificationInformation, + id-TNLAssociationTransportLayerAddressgNBDU, + id-portNumber, + id-AdditionalSIBMessageList, + id-IgnorePRACHConfiguration, + id-CG-Config, + id-Ph-InfoMCG, + id-AggressorgNBSetID, + id-VictimgNBSetID, + id-MeasGapSharingConfig, + id-systemInformationAreaID, + id-areaScope, + id-IntendedTDD-DL-ULConfig, + id-QosMonitoringRequest, + id-BHInfo, + id-IAB-Info-IAB-DU, + id-IAB-Info-IAB-donor-CU, + id-IAB-Barred, + id-SIB12-message, + id-SIB13-message, + id-SIB14-message, + id-UEAssistanceInformationEUTRA, + id-SL-PHY-MAC-RLC-Config, + id-SL-ConfigDedicatedEUTRA, + id-AlternativeQoSParaSetList, + id-CurrentQoSParaSetIndex, + id-CarrierList, + id-ULCarrierList, + id-FrequencyShift7p5khz, + id-SSB-PositionsInBurst, + id-NRPRACHConfig, + id-TDD-UL-DLConfigCommonNR, + id-CNPacketDelayBudgetDownlink, + id-CNPacketDelayBudgetUplink, + id-ExtendedPacketDelayBudget, + id-TSCTrafficCharacteristics, + id-AdditionalPDCPDuplicationTNL-List, + id-RLCDuplicationInformation, + id-AdditionalDuplicationIndication, + id-mdtConfiguration, + id-TraceCollectionEntityURI, + id-NID, + id-NPNSupportInfo, + id-NPNBroadcastInformation, + id-AvailableSNPN-ID-List, + id-SIB10-message, + id-RequestedP-MaxFR2, + id-DLCarrierList, + id-ExtendedTAISliceSupportList, + id-E-CID-MeasurementQuantities-Item, + id-ConfiguredTACIndication, + maxNRARFCN, + maxnoofErrors, + maxnoofBPLMNs, + maxnoofBPLMNsNR, + maxnoofDLUPTNLInformation, + maxnoofNrCellBands, + maxnoofULUPTNLInformation, + maxnoofQoSFlows, + maxnoofSliceItems, + maxnoofSIBTypes, + maxnoofSITypes, + maxCellineNB, + maxnoofExtendedBPLMNs, + maxnoofAdditionalSIBs, + maxnoofUACPLMNs, + maxnoofUACperPLMN, + maxCellingNBDU, + maxnoofTLAs, + maxnoofGTPTLAs, + maxnoofslots, + maxnoofNonUPTrafficMappings, + maxnoofServingCells, + maxnoofServedCellsIAB, + maxnoofChildIABNodes, + maxnoofIABSTCInfo, + maxnoofSymbols, + maxnoofDUFSlots, + maxnoofHSNASlots, + maxnoofEgressLinks, + maxnoofMappingEntries, + maxnoofDSInfo, + maxnoofQoSParaSets, + maxnoofPC5QoSFlows, + maxnoofSSBAreas, + maxnoofBPLMNsNR, + maxnoofNRSCSs, + maxnoofPhysicalResourceBlocks, + maxnoofPhysicalResourceBlocks-1, + maxnoofPRACHconfigs, + maxnoofRACHReports, + maxnoofRLFReports, + maxnoofAdditionalPDCPDuplicationTNL, + maxnoofRLCDuplicationState, + maxnoofCHOcells, + maxnoofMDTPLMNs, + maxnoofCAGsupported, + maxnoofNIDsupported, + maxnoofNRSCSs, + maxnoofPhysicalResourceBlocks, + maxnoofExtSliceItems, + maxnoofPosMeas, + maxnoofTRPInfoTypes, + maxnoofSRSTriggerStates, + maxnoofSpatialRelations, + maxnoBcastCell, + maxnoofTRPs, + maxnoofAngleInfo, + maxnooflcs-gcs-translation, + maxnoofPath, + maxnoofMeasE-CID, + maxnoofSSBs, + maxnoSRS-ResourceSets, + maxnoSRS-ResourcePerSet, + maxnoSRS-Carriers, + maxnoSCSs, + maxnoSRS-Resources, + maxnoSRS-PosResources, + maxnoSRS-PosResourceSets, + maxnoSRS-PosResourcePerSet, + maxnoofPRS-ResourceSets, + maxnoofPRS-ResourcesPerSet, + maxNoOfMeasTRPs, + maxnoofPRSresourceSets, + maxnoofPRSresources + + + +FROM F1AP-Constants + + Criticality, + ProcedureCode, + ProtocolIE-ID, + TriggeringMessage + +FROM F1AP-CommonDataTypes + + ProtocolExtensionContainer{}, + F1AP-PROTOCOL-EXTENSION, + ProtocolIE-SingleContainer{}, + F1AP-PROTOCOL-IES + +FROM F1AP-Containers; + +-- A + +AbortTransmission ::= CHOICE { + sRSResourceSetID SRSResourceSetID, + releaseALL NULL, + choice-extension ProtocolIE-SingleContainer { { AbortTransmission-ExtIEs } } +} + +AbortTransmission-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +AccessPointPosition ::= SEQUENCE { + latitudeSign ENUMERATED {north, south}, + latitude INTEGER (0..8388607), + longitude INTEGER (-8388608..8388607), + directionOfAltitude ENUMERATED {height, depth}, + altitude INTEGER (0..32767), + uncertaintySemi-major INTEGER (0..127), + uncertaintySemi-minor INTEGER (0..127), + orientationOfMajorAxis INTEGER (0..179), + uncertaintyAltitude INTEGER (0..127), + confidence INTEGER (0..100), + iE-Extensions ProtocolExtensionContainer { { AccessPointPosition-ExtIEs} } OPTIONAL +} + +AccessPointPosition-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Activated-Cells-to-be-Updated-List ::= SEQUENCE (SIZE(1..maxnoofServedCellsIAB)) OF Activated-Cells-to-be-Updated-List-Item + +Activated-Cells-to-be-Updated-List-Item ::= SEQUENCE{ + nRCGI NRCGI, + iAB-DU-Cell-Resource-Configuration-Mode-Info IAB-DU-Cell-Resource-Configuration-Mode-Info, + iE-Extensions ProtocolExtensionContainer { { Activated-Cells-to-be-Updated-List-Item-ExtIEs} } OPTIONAL +} + +Activated-Cells-to-be-Updated-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ActiveULBWP ::= SEQUENCE { + locationAndBandwidth INTEGER (0..37949,...), + subcarrierSpacing ENUMERATED {kHz15, kHz30, kHz60, kHz120,...}, + cyclicPrefix ENUMERATED {normal, extended}, + txDirectCurrentLocation INTEGER (0..3301,...), + shift7dot5kHz ENUMERATED {true, ...} OPTIONAL, + sRSConfig SRSConfig, + iE-Extensions ProtocolExtensionContainer { { ActiveULBWP-ExtIEs} } OPTIONAL +} + +ActiveULBWP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AdditionalDuplicationIndication ::= ENUMERATED { + three, + four, + ... +} + + +AdditionalPath-List::= SEQUENCE (SIZE(1..maxnoofPath)) OF AdditionalPath-Item + +AdditionalPath-Item ::=SEQUENCE { + relativePathDelay RelativePathDelay, + pathQuality TRPMeasurementQuality OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { AdditionalPath-Item-ExtIEs } } OPTIONAL +} + +AdditionalPath-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +AdditionalPDCPDuplicationTNL-List ::= SEQUENCE (SIZE(1..maxnoofAdditionalPDCPDuplicationTNL)) OF AdditionalPDCPDuplicationTNL-Item + +AdditionalPDCPDuplicationTNL-Item ::=SEQUENCE { + additionalPDCPDuplicationUPTNLInformation UPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { { AdditionalPDCPDuplicationTNL-ItemExtIEs } } OPTIONAL, + ... +} + +AdditionalPDCPDuplicationTNL-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AdditionalSIBMessageList ::= SEQUENCE (SIZE(1..maxnoofAdditionalSIBs)) OF AdditionalSIBMessageList-Item + +AdditionalSIBMessageList-Item ::= SEQUENCE { + additionalSIB OCTET STRING, + iE-Extensions ProtocolExtensionContainer { { AdditionalSIBMessageList-Item-ExtIEs} } OPTIONAL +} + +AdditionalSIBMessageList-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AdditionalRRMPriorityIndex ::= BIT STRING (SIZE(32)) + +AggressorCellList ::= SEQUENCE (SIZE(1..maxCellingNBDU)) OF AggressorCellList-Item + +AggressorCellList-Item ::= SEQUENCE { + aggressorCell-ID NRCGI, + iE-Extensions ProtocolExtensionContainer { { AggressorCellList-Item-ExtIEs } } OPTIONAL +} + +AggressorCellList-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AggressorgNBSetID ::= SEQUENCE { + aggressorgNBSetID GNBSetID, + iE-Extensions ProtocolExtensionContainer { { AggressorgNBSetID-ExtIEs } } OPTIONAL +} + +AggressorgNBSetID-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AllocationAndRetentionPriority ::= SEQUENCE { + priorityLevel PriorityLevel, + pre-emptionCapability Pre-emptionCapability, + pre-emptionVulnerability Pre-emptionVulnerability, + iE-Extensions ProtocolExtensionContainer { {AllocationAndRetentionPriority-ExtIEs} } OPTIONAL, + ... +} + +AllocationAndRetentionPriority-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AlternativeQoSParaSetList ::= SEQUENCE (SIZE(1..maxnoofQoSParaSets)) OF AlternativeQoSParaSetItem + +AlternativeQoSParaSetItem ::= SEQUENCE { + alternativeQoSParaSetIndex QoSParaSetIndex, + guaranteedFlowBitRateDL BitRate OPTIONAL, + guaranteedFlowBitRateUL BitRate OPTIONAL, + packetDelayBudget PacketDelayBudget OPTIONAL, + packetErrorRate PacketErrorRate OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {AlternativeQoSParaSetItem-ExtIEs} } OPTIONAL, + ... +} + +AlternativeQoSParaSetItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +AngleMeasurementQuality ::= SEQUENCE { + azimuthQuality INTEGER(0..255), + zenithQuality INTEGER(0..255) OPTIONAL, + resolution ENUMERATED{deg0dot1,...}, + iE-Extensions ProtocolExtensionContainer { { AngleMeasurementQuality-ExtIEs } } OPTIONAL +} + +AngleMeasurementQuality-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +AperiodicSRSResourceTriggerList ::= SEQUENCE (SIZE(1..maxnoofSRSTriggerStates)) OF AperiodicSRSResourceTrigger + +AperiodicSRSResourceTrigger ::= INTEGER (0..3, ...) + +Associated-SCell-Item ::= SEQUENCE { + sCell-ID NRCGI, + iE-Extensions ProtocolExtensionContainer { { Associated-SCell-ItemExtIEs } } OPTIONAL +} + +Associated-SCell-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AvailablePLMNList ::= SEQUENCE (SIZE(1..maxnoofBPLMNs)) OF AvailablePLMNList-Item + +AvailablePLMNList-Item ::= SEQUENCE { + pLMNIdentity PLMN-Identity, + iE-Extensions ProtocolExtensionContainer { { AvailablePLMNList-Item-ExtIEs} } OPTIONAL +} + +AvailablePLMNList-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AvailableSNPN-ID-List ::= SEQUENCE (SIZE(1..maxnoofNIDsupported)) OF AvailableSNPN-ID-List-Item + +AvailableSNPN-ID-List-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + availableNIDList BroadcastNIDList, + iE-Extensions ProtocolExtensionContainer { { AvailableSNPN-ID-List-ItemExtIEs} } OPTIONAL, + ... +} + +AvailableSNPN-ID-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AveragingWindow ::= INTEGER (0..4095, ...) + +AreaScope ::= ENUMERATED {true, ...} + +-- B + +BandwidthSRS ::= CHOICE { + fR1 FR1-Bandwidth, + fR2 FR2-Bandwidth, + choice-extension ProtocolIE-SingleContainer {{ BandwidthSRS-ExtIEs }} +} + +BandwidthSRS-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +BAPAddress ::= BIT STRING (SIZE(10)) + +BAPCtrlPDUChannel ::= ENUMERATED {true, ...} + +BAPlayerBHRLCchannelMappingInfo ::= SEQUENCE { + bAPlayerBHRLCchannelMappingInfoToAdd BAPlayerBHRLCchannelMappingInfoList OPTIONAL, + bAPlayerBHRLCchannelMappingInfoToRemove MappingInformationtoRemove OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BAPlayerBHRLCchannelMappingInfo-ExtIEs} } OPTIONAL, + ... +} + +BAPlayerBHRLCchannelMappingInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BAPlayerBHRLCchannelMappingInfoList ::= SEQUENCE (SIZE(1..maxnoofMappingEntries)) OF BAPlayerBHRLCchannelMappingInfo-Item + +BAPlayerBHRLCchannelMappingInfo-Item ::= SEQUENCE { + mappingInformationIndex MappingInformationIndex, + priorHopBAPAddress BAPAddress OPTIONAL, + ingressbHRLCChannelID BHRLCChannelID OPTIONAL, + nextHopBAPAddress BAPAddress OPTIONAL, + egressbHRLCChannelID BHRLCChannelID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BAPlayerBHRLCchannelMappingInfo-ItemExtIEs} } OPTIONAL, + ... +} + +BAPlayerBHRLCchannelMappingInfo-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BAPPathID ::= BIT STRING (SIZE(10)) + +BAPRoutingID ::= SEQUENCE { + bAPAddress BAPAddress, + bAPPathID BAPPathID, + iE-Extensions ProtocolExtensionContainer { { BAPRoutingIDExtIEs } } OPTIONAL +} + +BAPRoutingIDExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BitRate ::= INTEGER (0..4000000000000,...) + +BearerTypeChange ::= ENUMERATED {true, ...} + +BHRLCChannelID ::= BIT STRING (SIZE(16)) + +BHChannels-FailedToBeModified-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-FailedToBeModified-ItemExtIEs } } OPTIONAL +} + +BHChannels-FailedToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-FailedToBeSetup-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-FailedToBeSetup-ItemExtIEs } } OPTIONAL +} + +BHChannels-FailedToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-FailedToBeSetupMod-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { BHChannels-FailedToBeSetupMod-ItemExtIEs } } OPTIONAL +} + +BHChannels-FailedToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-Modified-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-Modified-ItemExtIEs } } OPTIONAL +} + +BHChannels-Modified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-Required-ToBeReleased-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-Required-ToBeReleased-ItemExtIEs } } OPTIONAL +} + +BHChannels-Required-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-Setup-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-Setup-ItemExtIEs } } OPTIONAL +} + +BHChannels-Setup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-SetupMod-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-SetupMod-ItemExtIEs } } OPTIONAL +} + +BHChannels-SetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-ToBeModified-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + bHQoSInformation BHQoSInformation, + rLCmode RLCMode OPTIONAL, + bAPCtrlPDUChannel BAPCtrlPDUChannel OPTIONAL, + trafficMappingInfo TrafficMappingInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-ToBeModified-ItemExtIEs } } OPTIONAL +} + +BHChannels-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-ToBeReleased-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer { { BHChannels-ToBeReleased-ItemExtIEs } } OPTIONAL +} + +BHChannels-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-ToBeSetup-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + bHQoSInformation BHQoSInformation, + rLCmode RLCMode, + bAPCtrlPDUChannel BAPCtrlPDUChannel OPTIONAL, + trafficMappingInfo TrafficMappingInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-ToBeSetup-ItemExtIEs } } OPTIONAL +} + +BHChannels-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHChannels-ToBeSetupMod-Item ::= SEQUENCE { + bHRLCChannelID BHRLCChannelID, + bHQoSInformation BHQoSInformation, + rLCmode RLCMode, + bAPCtrlPDUChannel BAPCtrlPDUChannel OPTIONAL, + trafficMappingInfo TrafficMappingInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHChannels-ToBeSetupMod-ItemExtIEs } } OPTIONAL +} + +BHChannels-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHInfo ::= SEQUENCE { + bAProutingID BAPRoutingID OPTIONAL, + egressBHRLCCHList EgressBHRLCCHList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BHInfo-ExtIEs} } OPTIONAL +} + +BHInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BHQoSInformation ::= CHOICE { + bHRLCCHQoS QoSFlowLevelQoSParameters, + eUTRANBHRLCCHQoS EUTRANQoS, + cPTrafficType CPTrafficType, + choice-extension ProtocolIE-SingleContainer { { BHQoSInformation-ExtIEs} } +} + +BHQoSInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +BH-Routing-Information-Added-List-Item ::= SEQUENCE { + bAPRoutingID BAPRoutingID, + nextHopBAPAddress BAPAddress, + iE-Extensions ProtocolExtensionContainer { { BH-Routing-Information-Added-List-ItemExtIEs} } OPTIONAL +} + +BH-Routing-Information-Added-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BH-Routing-Information-Removed-List-Item ::= SEQUENCE { + bAPRoutingID BAPRoutingID, + iE-Extensions ProtocolExtensionContainer { { BH-Routing-Information-Removed-List-ItemExtIEs} } OPTIONAL +} + +BH-Routing-Information-Removed-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BPLMN-ID-Info-List ::= SEQUENCE (SIZE(1..maxnoofBPLMNsNR)) OF BPLMN-ID-Info-Item + +BPLMN-ID-Info-Item ::= SEQUENCE { + pLMN-Identity-List AvailablePLMNList, + extended-PLMN-Identity-List ExtendedAvailablePLMN-List OPTIONAL, + fiveGS-TAC FiveGS-TAC OPTIONAL, + nr-cell-ID NRCellIdentity, + ranac RANAC OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { BPLMN-ID-Info-ItemExtIEs} } OPTIONAL, + ... +} + +BPLMN-ID-Info-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ConfiguredTACIndication CRITICALITY ignore EXTENSION ConfiguredTACIndication PRESENCE optional }| + { ID id-NPNBroadcastInformation CRITICALITY reject EXTENSION NPNBroadcastInformation PRESENCE optional}, + ... +} + +ServedPLMNs-List ::= SEQUENCE (SIZE(1..maxnoofBPLMNs)) OF ServedPLMNs-Item + +ServedPLMNs-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + iE-Extensions ProtocolExtensionContainer { { ServedPLMNs-ItemExtIEs} } OPTIONAL, + ... +} + +ServedPLMNs-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { +{ ID id-TAISliceSupportList CRITICALITY ignore EXTENSION SliceSupportList PRESENCE optional }| +{ ID id-NPNSupportInfo CRITICALITY reject EXTENSION NPNSupportInfo PRESENCE optional }| +{ ID id-ExtendedTAISliceSupportList CRITICALITY reject EXTENSION ExtendedSliceSupportList PRESENCE optional }, + ... +} + +BroadcastCAGList ::= SEQUENCE (SIZE(1..maxnoofCAGsupported)) OF CAGID + +BroadcastNIDList ::= SEQUENCE (SIZE(1..maxnoofNIDsupported)) OF NID + +BroadcastSNPN-ID-List ::= SEQUENCE (SIZE(1..maxnoofNIDsupported)) OF BroadcastSNPN-ID-List-Item + +BroadcastSNPN-ID-List-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + broadcastNIDList BroadcastNIDList, + iE-Extensions ProtocolExtensionContainer { { BroadcastSNPN-ID-List-ItemExtIEs} } OPTIONAL, + ... +} + +BroadcastSNPN-ID-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +BroadcastPNI-NPN-ID-List ::= SEQUENCE (SIZE(1..maxnoofCAGsupported)) OF BroadcastPNI-NPN-ID-List-Item + +BroadcastPNI-NPN-ID-List-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + broadcastCAGList BroadcastCAGList, + iE-Extensions ProtocolExtensionContainer { { BroadcastPNI-NPN-ID-List-ItemExtIEs} } OPTIONAL, + ... +} + +BroadcastPNI-NPN-ID-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} +BurstArrivalTime ::= OCTET STRING + +-- C +CAGID ::= BIT STRING (SIZE(32)) + +Cancel-all-Warning-Messages-Indicator ::= ENUMERATED {true, ...} + +Candidate-SpCell-Item ::= SEQUENCE { + candidate-SpCell-ID NRCGI , + iE-Extensions ProtocolExtensionContainer { { Candidate-SpCell-ItemExtIEs } } OPTIONAL, + ... +} + +Candidate-SpCell-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CapacityValue::= SEQUENCE { + capacityValue INTEGER (0..100), + sSBAreaCapacityValueList SSBAreaCapacityValueList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { CapacityValue-ExtIEs} } OPTIONAL +} + +CapacityValue-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cause ::= CHOICE { + radioNetwork CauseRadioNetwork, + transport CauseTransport, + protocol CauseProtocol, + misc CauseMisc, + choice-extension ProtocolIE-SingleContainer { { Cause-ExtIEs} } +} + +Cause-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +CauseMisc ::= ENUMERATED { + control-processing-overload, + not-enough-user-plane-processing-resources, + hardware-failure, + om-intervention, + unspecified, + ... +} + +CauseProtocol ::= ENUMERATED { + transfer-syntax-error, + abstract-syntax-error-reject, + abstract-syntax-error-ignore-and-notify, + message-not-compatible-with-receiver-state, + semantic-error, + abstract-syntax-error-falsely-constructed-message, + unspecified, + ... +} + +CauseRadioNetwork ::= ENUMERATED { + unspecified, + rl-failure-rlc, + unknown-or-already-allocated-gnb-cu-ue-f1ap-id, + unknown-or-already-allocated-gnb-du-ue-f1ap-id, + unknown-or-inconsistent-pair-of-ue-f1ap-id, + interaction-with-other-procedure, + not-supported-qci-Value, + action-desirable-for-radio-reasons, + no-radio-resources-available, + procedure-cancelled, + normal-release, + ..., + cell-not-available, + rl-failure-others, + ue-rejection, + resources-not-available-for-the-slice, + amf-initiated-abnormal-release, + release-due-to-pre-emption, + plmn-not-served-by-the-gNB-CU, + multiple-drb-id-instances, + unknown-drb-id, + multiple-bh-rlc-ch-id-instances, + unknown-bh-rlc-ch-id, + cho-cpc-resources-tobechanged, + nPN-not-supported, + nPN-access-denied, + gNB-CU-Cell-Capacity-Exceeded, + report-characteristics-empty, + existing-measurement-ID, + measurement-temporarily-not-available, + measurement-not-supported-for-the-object + +} + +CauseTransport ::= ENUMERATED { + unspecified, + transport-resource-unavailable, + ..., + unknown-TNL-address-for-IAB, + unknown-UP-TNL-information-for-IAB +} + +CellGroupConfig ::= OCTET STRING + +CellCapacityClassValue ::= INTEGER (1..100,...) + +Cell-Direction ::= ENUMERATED {dl-only, ul-only} + +CellMeasurementResultList ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF CellMeasurementResultItem + +CellMeasurementResultItem ::= SEQUENCE { + cellID NRCGI, + radioResourceStatus RadioResourceStatus OPTIONAL, + compositeAvailableCapacityGroup CompositeAvailableCapacityGroup OPTIONAL, + sliceAvailableCapacity SliceAvailableCapacity OPTIONAL, + numberofActiveUEs NumberofActiveUEs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { CellMeasurementResultItem-ExtIEs} } OPTIONAL +} + +CellMeasurementResultItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cell-Portion-ID ::= INTEGER (0..4095,...) + +Cells-Failed-to-be-Activated-List-Item ::= SEQUENCE { + nRCGI NRCGI, + cause Cause, + iE-Extensions ProtocolExtensionContainer { { Cells-Failed-to-be-Activated-List-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-Failed-to-be-Activated-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-Status-Item ::= SEQUENCE { + nRCGI NRCGI, + service-status Service-Status, + iE-Extensions ProtocolExtensionContainer { { Cells-Status-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-Status-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-To-Be-Broadcast-Item ::= SEQUENCE { + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { Cells-To-Be-Broadcast-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-To-Be-Broadcast-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-Broadcast-Completed-Item ::= SEQUENCE { + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { Cells-Broadcast-Completed-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-Broadcast-Completed-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Broadcast-To-Be-Cancelled-Item ::= SEQUENCE { + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { Broadcast-To-Be-Cancelled-ItemExtIEs } } OPTIONAL, + ... +} + +Broadcast-To-Be-Cancelled-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +Cells-Broadcast-Cancelled-Item ::= SEQUENCE { + nRCGI NRCGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { { Cells-Broadcast-Cancelled-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-Broadcast-Cancelled-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-to-be-Activated-List-Item ::= SEQUENCE { + nRCGI NRCGI, + nRPCI NRPCI OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Cells-to-be-Activated-List-ItemExtIEs} } OPTIONAL, + ... +} + +Cells-to-be-Activated-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-gNB-CUSystemInformation CRITICALITY reject EXTENSION GNB-CUSystemInformation PRESENCE optional }| + { ID id-AvailablePLMNList CRITICALITY ignore EXTENSION AvailablePLMNList PRESENCE optional }| + { ID id-ExtendedAvailablePLMN-List CRITICALITY ignore EXTENSION ExtendedAvailablePLMN-List PRESENCE optional }| + { ID id-IAB-Info-IAB-donor-CU CRITICALITY ignore EXTENSION IAB-Info-IAB-donor-CU PRESENCE optional}| + { ID id-AvailableSNPN-ID-List CRITICALITY ignore EXTENSION AvailableSNPN-ID-List PRESENCE optional }, + ... +} + +Cells-to-be-Deactivated-List-Item ::= SEQUENCE { + nRCGI NRCGI , + iE-Extensions ProtocolExtensionContainer { { Cells-to-be-Deactivated-List-ItemExtIEs } } OPTIONAL, + ... +} + +Cells-to-be-Deactivated-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Cells-to-be-Barred-Item::= SEQUENCE { + nRCGI NRCGI , + cellBarred CellBarred, + iE-Extensions ProtocolExtensionContainer { { Cells-to-be-Barred-Item-ExtIEs } } OPTIONAL +} + +Cells-to-be-Barred-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-IAB-Barred CRITICALITY ignore EXTENSION IAB-Barred PRESENCE optional }, + + ... +} + + +CellBarred ::= ENUMERATED {barred, not-barred, ...} + +CellSize ::= ENUMERATED {verysmall, small, medium, large, ...} + +CellToReportList ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF CellToReportItem + +CellToReportItem ::= SEQUENCE { + cellID NRCGI, + sSBToReportList SSBToReportList OPTIONAL, + sliceToReportList SliceToReportList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { CellToReportItem-ExtIEs} } OPTIONAL +} + +CellToReportItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CellType ::= SEQUENCE { + cellSize CellSize, + iE-Extensions ProtocolExtensionContainer { {CellType-ExtIEs} } OPTIONAL, + ... +} + +CellType-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CellULConfigured ::= ENUMERATED {none, ul, sul, ul-and-sul, ...} + +Child-Node-Cells-List ::= SEQUENCE (SIZE(1..maxnoofChildIABNodes)) OF Child-Node-Cells-List-Item + +Child-Node-Cells-List-Item ::= SEQUENCE{ + nRCGI NRCGI, + iAB-DU-Cell-Resource-Configuration-Mode-Info IAB-DU-Cell-Resource-Configuration-Mode-Info OPTIONAL, + iAB-STC-Info IAB-STC-Info OPTIONAL, + rACH-Config-Common RACH-Config-Common OPTIONAL, + rACH-Config-Common-IAB RACH-Config-Common-IAB OPTIONAL, + cSI-RS-Configuration OCTET STRING OPTIONAL, + sR-Configuration OCTET STRING OPTIONAL, + pDCCH-ConfigSIB1 OCTET STRING OPTIONAL, + sCS-Common OCTET STRING OPTIONAL, + multiplexingInfo MultiplexingInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer {{Child-Node-Cells-List-Item-ExtIEs}} OPTIONAL +} + +Child-Node-Cells-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Child-Nodes-List ::= SEQUENCE (SIZE(1..maxnoofChildIABNodes)) OF Child-Nodes-List-Item + +Child-Nodes-List-Item ::= SEQUENCE{ + gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID, + gNB-DU-UE-F1AP-ID GNB-DU-UE-F1AP-ID, + child-Node-Cells-List Child-Node-Cells-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer {{Child-Nodes-List-Item-ExtIEs}} OPTIONAL +} + +Child-Nodes-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CHOtrigger-InterDU ::= ENUMERATED { + cho-initiation, + cho-replace, + ... +} + +CHOtrigger-IntraDU ::= ENUMERATED { + cho-initiation, + cho-replace, + cho-cancel, + ... +} + +CNUEPagingIdentity ::= CHOICE { + fiveG-S-TMSI BIT STRING (SIZE(48)), + choice-extension ProtocolIE-SingleContainer { { CNUEPagingIdentity-ExtIEs } } +} + +CNUEPagingIdentity-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +CompositeAvailableCapacityGroup ::= SEQUENCE { + compositeAvailableCapacityDownlink CompositeAvailableCapacity, + compositeAvailableCapacityUplink CompositeAvailableCapacity, + iE-Extensions ProtocolExtensionContainer { { CompositeAvailableCapacityGroup-ExtIEs} } OPTIONAL +} + +CompositeAvailableCapacityGroup-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CompositeAvailableCapacity ::= SEQUENCE { + cellCapacityClassValue CellCapacityClassValue OPTIONAL, + capacityValue CapacityValue, + iE-Extensions ProtocolExtensionContainer { { CompositeAvailableCapacity-ExtIEs} } OPTIONAL +} + +CompositeAvailableCapacity-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ConditionalInterDUMobilityInformation ::= SEQUENCE { + cho-trigger CHOtrigger-InterDU, + targetgNB-DUUEF1APID GNB-DU-UE-F1AP-ID OPTIONAL + -- This IE shall be present if the cho-trigger IE is present and set to "cho-replace" --, + iE-Extensions ProtocolExtensionContainer { { ConditionalInterDUMobilityInformation-ExtIEs} } OPTIONAL, + ... +} + +ConditionalInterDUMobilityInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::={ + ... +} + +ConditionalIntraDUMobilityInformation ::= SEQUENCE { + cho-trigger CHOtrigger-IntraDU, + targetCellsTocancel TargetCellList OPTIONAL, + -- This IE may be present if the cho-trigger IE is present and set to "cho-cancel" + iE-Extensions ProtocolExtensionContainer { { ConditionalIntraDUMobilityInformation-ExtIEs} } OPTIONAL, + ... +} + +ConditionalIntraDUMobilityInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::={ + ... +} + +ConfiguredTACIndication ::= ENUMERATED { + true, + ... +} + + +CoordinateID ::= INTEGER (0..511, ...) + +CP-TransportLayerAddress ::= CHOICE { + endpoint-IP-address TransportLayerAddress, + endpoint-IP-address-and-port Endpoint-IP-address-and-port, + choice-extension ProtocolIE-SingleContainer { { CP-TransportLayerAddress-ExtIEs } } +} + +CP-TransportLayerAddress-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +CPTrafficType ::= INTEGER (1..3,...) + +CriticalityDiagnostics ::= SEQUENCE { + procedureCode ProcedureCode OPTIONAL, + triggeringMessage TriggeringMessage OPTIONAL, + procedureCriticality Criticality OPTIONAL, + transactionID TransactionID OPTIONAL, + iEsCriticalityDiagnostics CriticalityDiagnostics-IE-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer {{CriticalityDiagnostics-ExtIEs}} OPTIONAL, + ... +} + +CriticalityDiagnostics-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CriticalityDiagnostics-IE-List ::= SEQUENCE (SIZE (1.. maxnoofErrors)) OF CriticalityDiagnostics-IE-Item + +CriticalityDiagnostics-IE-Item ::= SEQUENCE { + iECriticality Criticality, + iE-ID ProtocolIE-ID, + typeOfError TypeOfError, + iE-Extensions ProtocolExtensionContainer {{CriticalityDiagnostics-IE-Item-ExtIEs}} OPTIONAL, + ... +} + +CriticalityDiagnostics-IE-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +C-RNTI ::= INTEGER (0..65535, ...) + +CUDURadioInformationType ::= CHOICE { + rIM CUDURIMInformation, + choice-extension ProtocolIE-SingleContainer { { CUDURadioInformationType-ExtIEs} } +} + +CUDURadioInformationType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +CUDURIMInformation ::= SEQUENCE { + victimgNBSetID GNBSetID, + rIMRSDetectionStatus RIMRSDetectionStatus, + iE-Extensions ProtocolExtensionContainer { { CUDURIMInformation-ExtIEs} } OPTIONAL +} + +CUDURIMInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +CUtoDURRCInformation ::= SEQUENCE { + cG-ConfigInfo CG-ConfigInfo OPTIONAL, + uE-CapabilityRAT-ContainerList UE-CapabilityRAT-ContainerList OPTIONAL, + measConfig MeasConfig OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { CUtoDURRCInformation-ExtIEs} } OPTIONAL, + ... +} + +CUtoDURRCInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-HandoverPreparationInformation CRITICALITY ignore EXTENSION HandoverPreparationInformation PRESENCE optional }| + { ID id-CellGroupConfig CRITICALITY ignore EXTENSION CellGroupConfig PRESENCE optional }| + { ID id-MeasurementTimingConfiguration CRITICALITY ignore EXTENSION MeasurementTimingConfiguration PRESENCE optional }| + { ID id-UEAssistanceInformation CRITICALITY ignore EXTENSION UEAssistanceInformation PRESENCE optional }| + { ID id-CG-Config CRITICALITY ignore EXTENSION CG-Config PRESENCE optional }| + { ID id-UEAssistanceInformationEUTRA CRITICALITY ignore EXTENSION UEAssistanceInformationEUTRA PRESENCE optional }, + ... +} + +-- D + +DCBasedDuplicationConfigured::= ENUMERATED{true,..., false} + +Dedicated-SIDelivery-NeededUE-Item ::= SEQUENCE { + gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID, + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { DedicatedSIDeliveryNeededUE-Item-ExtIEs} } OPTIONAL, + ... +} + +DedicatedSIDeliveryNeededUE-Item-ExtIEs F1AP-PROTOCOL-EXTENSION::={ + ... +} + + +DL-PRS ::= SEQUENCE { + prsid INTEGER (0..255), + dl-PRSResourceSetID PRS-Resource-Set-ID, + dl-PRSResourceID PRS-Resource-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {DL-PRS-ExtIEs} } OPTIONAL +} + +DL-PRS-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DL-PRSMutingPattern ::= CHOICE { + two BIT STRING (SIZE(2)), + four BIT STRING (SIZE(4)), + six BIT STRING (SIZE(6)), + eight BIT STRING (SIZE(8)), + sixteen BIT STRING (SIZE(16)), + thirty-two BIT STRING (SIZE(32)), + choice-extension ProtocolIE-SingleContainer { { DL-PRSMutingPattern-ExtIEs } } +} + +DL-PRSMutingPattern-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +DLPRSResourceCoordinates ::= SEQUENCE { + listofDL-PRSResourceSetARP SEQUENCE (SIZE(1.. maxnoofPRS-ResourceSets)) OF DLPRSResourceSetARP, + iE-Extensions ProtocolExtensionContainer { { DLPRSResourceCoordinates-ExtIEs } } OPTIONAL +} + +DLPRSResourceCoordinates-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DLPRSResourceSetARP ::= SEQUENCE { + dl-PRSResourceSetID INTEGER (0..7), + dL-PRSResourceSetARPLocation DL-PRSResourceSetARPLocation, + listofDL-PRSResourceARP SEQUENCE (SIZE(1.. maxnoofPRS-ResourcesPerSet)) OF DLPRSResourceARP, + iE-Extensions ProtocolExtensionContainer { { DLPRSResourceSetARP-ExtIEs } } OPTIONAL +} + +DLPRSResourceSetARP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +DL-PRSResourceSetARPLocation ::= CHOICE { + relativeGeodeticLocation RelativeGeodeticLocation, + relativeCartesianLocation RelativeCartesianLocation, + choice-Extension ProtocolIE-SingleContainer { { DL-PRSResourceSetARPLocation-ExtIEs } } +} + +DL-PRSResourceSetARPLocation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +DLPRSResourceARP ::= SEQUENCE { + dl-PRSResourceID INTEGER (0..63), + dL-PRSResourceARPLocation DL-PRSResourceARPLocation, + iE-Extensions ProtocolExtensionContainer { { DLPRSResourceARP-ExtIEs } } OPTIONAL +} + +DLPRSResourceARP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DL-PRSResourceARPLocation ::= CHOICE { + relativeGeodeticLocation RelativeGeodeticLocation, + relativeCartesianLocation RelativeCartesianLocation, + choice-Extension ProtocolIE-SingleContainer { { DL-PRSResourceARPLocation-ExtIEs } } +} + +DL-PRSResourceARPLocation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +DL-UP-TNL-Address-to-Update-List-Item ::= SEQUENCE { + oldIPAdress TransportLayerAddress, + newIPAdress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { { DL-UP-TNL-Address-to-Update-List-ItemExtIEs } } OPTIONAL, + ... +} + +DL-UP-TNL-Address-to-Update-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DLUPTNLInformation-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofDLUPTNLInformation)) OF DLUPTNLInformation-ToBeSetup-Item + +DLUPTNLInformation-ToBeSetup-Item ::= SEQUENCE { + dLUPTNLInformation UPTransportLayerInformation , + iE-Extensions ProtocolExtensionContainer { { DLUPTNLInformation-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +DLUPTNLInformation-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRB-Activity-Item ::= SEQUENCE { + dRBID DRBID, + dRB-Activity DRB-Activity OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRB-Activity-ItemExtIEs } } OPTIONAL, + ... +} + +DRB-Activity-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRB-Activity ::= ENUMERATED {active, not-active} + +DRBID ::= INTEGER (1..32, ...) + +DRBs-FailedToBeModified-Item ::= SEQUENCE { + dRBID DRBID , + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-FailedToBeModified-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-FailedToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBs-FailedToBeSetup-Item ::= SEQUENCE { + dRBID DRBID, + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-FailedToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-FailedToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +DRBs-FailedToBeSetupMod-Item ::= SEQUENCE { + dRBID DRBID , + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { DRBs-FailedToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-FailedToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRB-Information ::= SEQUENCE { + dRB-QoS QoSFlowLevelQoSParameters, + sNSSAI SNSSAI, + notificationControl NotificationControl OPTIONAL, + flows-Mapped-To-DRB-List Flows-Mapped-To-DRB-List, + iE-Extensions ProtocolExtensionContainer { { DRB-Information-ItemExtIEs } } OPTIONAL +} + +DRB-Information-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBs-Modified-Item ::= SEQUENCE { + dRBID DRBID, + lCID LCID OPTIONAL, + dLUPTNLInformation-ToBeSetup-List DLUPTNLInformation-ToBeSetup-List, + iE-Extensions ProtocolExtensionContainer { { DRBs-Modified-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-Modified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-RLC-Status CRITICALITY ignore EXTENSION RLC-Status PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + +DRBs-ModifiedConf-Item ::= SEQUENCE { + dRBID DRBID, + uLUPTNLInformation-ToBeSetup-List ULUPTNLInformation-ToBeSetup-List , + iE-Extensions ProtocolExtensionContainer { { DRBs-ModifiedConf-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ModifiedConf-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + +DRB-Notify-Item ::= SEQUENCE { + dRBID DRBID, + notification-Cause Notification-Cause, + iE-Extensions ProtocolExtensionContainer { { DRB-Notify-ItemExtIEs } } OPTIONAL, + ... +} + +DRB-Notify-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-CurrentQoSParaSetIndex CRITICALITY ignore EXTENSION QoSParaSetNotifyIndex PRESENCE optional }, + ... +} + +DRBs-Required-ToBeModified-Item ::= SEQUENCE { + dRBID DRBID, + dLUPTNLInformation-ToBeSetup-List DLUPTNLInformation-ToBeSetup-List , + iE-Extensions ProtocolExtensionContainer { { DRBs-Required-ToBeModified-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-Required-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-RLC-Status CRITICALITY ignore EXTENSION RLC-Status PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + +DRBs-Required-ToBeReleased-Item ::= SEQUENCE { + dRBID DRBID, + iE-Extensions ProtocolExtensionContainer { { DRBs-Required-ToBeReleased-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-Required-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBs-Setup-Item ::= SEQUENCE { + dRBID DRBID, + lCID LCID OPTIONAL, + dLUPTNLInformation-ToBeSetup-List DLUPTNLInformation-ToBeSetup-List , + iE-Extensions ProtocolExtensionContainer { { DRBs-Setup-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-Setup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }| + { ID id-RLCDuplicationInformation CRITICALITY ignore EXTENSION RLCDuplicationInformation PRESENCE optional}, ... +} + +DRBs-SetupMod-Item ::= SEQUENCE { + dRBID DRBID, + lCID LCID OPTIONAL, + dLUPTNLInformation-ToBeSetup-List DLUPTNLInformation-ToBeSetup-List , + iE-Extensions ProtocolExtensionContainer { { DRBs-SetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-SetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + + +DRBs-ToBeModified-Item ::= SEQUENCE { + dRBID DRBID, + qoSInformation QoSInformation OPTIONAL, + uLUPTNLInformation-ToBeSetup-List ULUPTNLInformation-ToBeSetup-List , + uLConfiguration ULConfiguration OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-ToBeModified-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-DLPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + { ID id-ULPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + {ID id-BearerTypeChange CRITICALITY ignore EXTENSION BearerTypeChange PRESENCE optional}| + { ID id-RLCMode CRITICALITY ignore EXTENSION RLCMode PRESENCE optional }| + { ID id-Duplication-Activation CRITICALITY reject EXTENSION DuplicationActivation PRESENCE optional }| + { ID id-DC-Based-Duplication-Configured CRITICALITY reject EXTENSION DCBasedDuplicationConfigured PRESENCE optional }| + { ID id-DC-Based-Duplication-Activation CRITICALITY reject EXTENSION DuplicationActivation PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }| + { ID id-RLCDuplicationInformation CRITICALITY ignore EXTENSION RLCDuplicationInformation PRESENCE optional}, + ... +} + +DRBs-ToBeReleased-Item ::= SEQUENCE { + dRBID DRBID, + iE-Extensions ProtocolExtensionContainer { { DRBs-ToBeReleased-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBs-ToBeSetup-Item ::= SEQUENCE { + dRBID DRBID, + qoSInformation QoSInformation, + uLUPTNLInformation-ToBeSetup-List ULUPTNLInformation-ToBeSetup-List , + rLCMode RLCMode, + uLConfiguration ULConfiguration OPTIONAL, + duplicationActivation DuplicationActivation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-DC-Based-Duplication-Configured CRITICALITY reject EXTENSION DCBasedDuplicationConfigured PRESENCE optional }| + { ID id-DC-Based-Duplication-Activation CRITICALITY reject EXTENSION DuplicationActivation PRESENCE optional }| + { ID id-DLPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE mandatory }| + { ID id-ULPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }, + ... +} + + +DRBs-ToBeSetupMod-Item ::= SEQUENCE { + dRBID DRBID, + qoSInformation QoSInformation, + uLUPTNLInformation-ToBeSetup-List ULUPTNLInformation-ToBeSetup-List, + rLCMode RLCMode, + uLConfiguration ULConfiguration OPTIONAL, + duplicationActivation DuplicationActivation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRBs-ToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +DRBs-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-DC-Based-Duplication-Configured CRITICALITY reject EXTENSION DCBasedDuplicationConfigured PRESENCE optional }| + { ID id-DC-Based-Duplication-Activation CRITICALITY reject EXTENSION DuplicationActivation PRESENCE optional }| + { ID id-DLPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + { ID id-ULPDCPSNLength CRITICALITY ignore EXTENSION PDCPSNLength PRESENCE optional }| + { ID id-AdditionalPDCPDuplicationTNL-List CRITICALITY ignore EXTENSION AdditionalPDCPDuplicationTNL-List PRESENCE optional }| + { ID id-RLCDuplicationInformation CRITICALITY ignore EXTENSION RLCDuplicationInformation PRESENCE optional}, + ... +} + +DRXCycle ::= SEQUENCE { + longDRXCycleLength LongDRXCycleLength, + shortDRXCycleLength ShortDRXCycleLength OPTIONAL, + shortDRXCycleTimer ShortDRXCycleTimer OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DRXCycle-ExtIEs} } OPTIONAL, + ... +} + +DRXCycle-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DRX-Config ::= OCTET STRING + +DRXConfigurationIndicator ::= ENUMERATED{ release, ...} + +DRX-LongCycleStartOffset ::= INTEGER (0..10239) + +DSInformationList ::= SEQUENCE (SIZE(0..maxnoofDSInfo)) OF DSCP + +DSCP ::= BIT STRING (SIZE (6)) + +DUtoCURRCContainer ::= OCTET STRING + +DUCURadioInformationType ::= CHOICE { + rIM DUCURIMInformation, + choice-extension ProtocolIE-SingleContainer { { DUCURadioInformationType-ExtIEs} } +} + +DUCURadioInformationType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +DUCURIMInformation ::= SEQUENCE { + victimgNBSetID GNBSetID, + rIMRSDetectionStatus RIMRSDetectionStatus, + aggressorCellList AggressorCellList, + iE-Extensions ProtocolExtensionContainer { { DUCURIMInformation-ExtIEs} } OPTIONAL +} + +DUCURIMInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +DUF-Slot-Config-Item ::= CHOICE { + explicitFormat ExplicitFormat, + implicitFormat ImplicitFormat, + choice-extension ProtocolIE-SingleContainer { { DUF-Slot-Config-Item-ExtIEs} } +} + +DUF-Slot-Config-Item-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} +DUF-Slot-Config-List ::= SEQUENCE (SIZE(1..maxnoofDUFSlots)) OF DUF-Slot-Config-Item + +DUFSlotformatIndex ::= INTEGER(0..254) + +DUFTransmissionPeriodicity ::= ENUMERATED { ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms5, ms10, ...} + +DU-RX-MT-RX ::= ENUMERATED {supported, not-supported} + +DU-TX-MT-TX ::= ENUMERATED {supported, not-supported} + +DU-RX-MT-TX ::= ENUMERATED {supported, not-supported} + +DU-TX-MT-RX ::= ENUMERATED {supported, not-supported} + +DUtoCURRCInformation ::= SEQUENCE { + cellGroupConfig CellGroupConfig, + measGapConfig MeasGapConfig OPTIONAL, + requestedP-MaxFR1 OCTET STRING OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DUtoCURRCInformation-ExtIEs} } OPTIONAL, + ... +} + +DUtoCURRCInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-DRX-LongCycleStartOffset CRITICALITY ignore EXTENSION DRX-LongCycleStartOffset PRESENCE optional }| + { ID id-SelectedBandCombinationIndex CRITICALITY ignore EXTENSION SelectedBandCombinationIndex PRESENCE optional }| + { ID id-SelectedFeatureSetEntryIndex CRITICALITY ignore EXTENSION SelectedFeatureSetEntryIndex PRESENCE optional }| + { ID id-Ph-InfoSCG CRITICALITY ignore EXTENSION Ph-InfoSCG PRESENCE optional }| + { ID id-RequestedBandCombinationIndex CRITICALITY ignore EXTENSION RequestedBandCombinationIndex PRESENCE optional }| + { ID id-RequestedFeatureSetEntryIndex CRITICALITY ignore EXTENSION RequestedFeatureSetEntryIndex PRESENCE optional }| + { ID id-DRX-Config CRITICALITY ignore EXTENSION DRX-Config PRESENCE optional }| + { ID id-PDCCH-BlindDetectionSCG CRITICALITY ignore EXTENSION PDCCH-BlindDetectionSCG PRESENCE optional }| + { ID id-Requested-PDCCH-BlindDetectionSCG CRITICALITY ignore EXTENSION Requested-PDCCH-BlindDetectionSCG PRESENCE optional }| + { ID id-Ph-InfoMCG CRITICALITY ignore EXTENSION Ph-InfoMCG PRESENCE optional }| + { ID id-MeasGapSharingConfig CRITICALITY ignore EXTENSION MeasGapSharingConfig PRESENCE optional }| + { ID id-SL-PHY-MAC-RLC-Config CRITICALITY ignore EXTENSION SL-PHY-MAC-RLC-Config PRESENCE optional }| + { ID id-SL-ConfigDedicatedEUTRA CRITICALITY ignore EXTENSION SL-ConfigDedicatedEUTRA PRESENCE optional }| + { ID id-RequestedP-MaxFR2 CRITICALITY ignore EXTENSION RequestedP-MaxFR2 PRESENCE optional }, + ... +} + +DuplicationActivation ::= ENUMERATED{active,inactive,... } + +DuplicationIndication ::= ENUMERATED {true, ... , false } + +DuplicationState ::= ENUMERATED { + active, + inactive, + ... +} + +Dynamic5QIDescriptor ::= SEQUENCE { + qoSPriorityLevel INTEGER (1..127), + packetDelayBudget PacketDelayBudget, + packetErrorRate PacketErrorRate, + fiveQI INTEGER (0..255, ...) OPTIONAL, + delayCritical ENUMERATED {delay-critical, non-delay-critical} OPTIONAL, + -- C-ifGBRflow: This IE shall be present if the GBR QoS Flow Information IE is present in the QoS Flow Level QoS Parameters IE. + averagingWindow AveragingWindow OPTIONAL, + -- C-ifGBRflow: This IE shall be present if the GBR QoS Flow Information IE is present in the QoS Flow Level QoS Parameters IE. + maxDataBurstVolume MaxDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Dynamic5QIDescriptor-ExtIEs } } OPTIONAL +} + +Dynamic5QIDescriptor-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ExtendedPacketDelayBudget CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }| + { ID id-CNPacketDelayBudgetDownlink CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }| + { ID id-CNPacketDelayBudgetUplink CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }, + ... +} + +DynamicPQIDescriptor ::= SEQUENCE { + resourceType ENUMERATED {gbr, non-gbr, delay-critical-grb, ...} OPTIONAL, + qoSPriorityLevel INTEGER (1..8, ...), + packetDelayBudget PacketDelayBudget, + packetErrorRate PacketErrorRate, + averagingWindow AveragingWindow OPTIONAL, + -- C-ifGBRflow: This IE shall be present if the GBR QoS Flow Information IE is present in the QoS Flow Level QoS Parameters IE. + maxDataBurstVolume MaxDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { DynamicPQIDescriptor-ExtIEs } } OPTIONAL +} + +DynamicPQIDescriptor-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- E + +E-CID-MeasurementPeriodicity ::= ENUMERATED { + ms120, + ms240, + ms480, + ms640, + ms1024, + ms2048, + ms5120, + ms10240, + min1, + min6, + min12, + min30, + min60, + ... +} + +E-CID-MeasurementQuantities ::= SEQUENCE (SIZE (1.. maxnoofMeasE-CID)) OF ProtocolIE-SingleContainer { {E-CID-MeasurementQuantities-ItemIEs} } + +E-CID-MeasurementQuantities-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-E-CID-MeasurementQuantities-Item CRITICALITY reject TYPE E-CID-MeasurementQuantities-Item PRESENCE mandatory} +} + +E-CID-MeasurementQuantities-Item ::= SEQUENCE { + e-CIDmeasurementQuantitiesValue E-CID-MeasurementQuantitiesValue, + iE-Extensions ProtocolExtensionContainer { { E-CID-MeasurementQuantitiesValue-ExtIEs} } OPTIONAL +} + +E-CID-MeasurementQuantitiesValue-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +E-CID-MeasurementQuantitiesValue ::= ENUMERATED { + cell-Portion, + angleOfArrivalNR, + ... +} + +E-CID-MeasurementResult ::= SEQUENCE { + geographicalCoordinates GeographicalCoordinates OPTIONAL, + measuredResults-List E-CID-MeasuredResults-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { E-CID-MeasurementResult-ExtIEs} } OPTIONAL +} + +E-CID-MeasurementResult-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +E-CID-MeasuredResults-List ::= SEQUENCE (SIZE(1..maxnoofMeasE-CID)) OF E-CID-MeasuredResults-Item + +E-CID-MeasuredResults-Item ::= SEQUENCE { + e-CID-MeasuredResults-Value E-CID-MeasuredResults-Value, + iE-Extensions ProtocolExtensionContainer {{ E-CID-MeasuredResults-Item-ExtIEs }} OPTIONAL +} + +E-CID-MeasuredResults-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +E-CID-MeasuredResults-Value ::= CHOICE { + valueAngleofArrivalNR UL-AoA, + choice-extension ProtocolIE-SingleContainer { { E-CID-MeasuredResults-Value-ExtIEs} } +} + +E-CID-MeasuredResults-Value-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +E-CID-ReportCharacteristics ::= ENUMERATED { + onDemand, + periodic, + ... +} + +EgressBHRLCCHList ::= SEQUENCE (SIZE(1..maxnoofEgressLinks)) OF EgressBHRLCCHItem + +EgressBHRLCCHItem ::= SEQUENCE { + nextHopBAPAddress BAPAddress, + bHRLCChannelID BHRLCChannelID, + iE-Extensions ProtocolExtensionContainer {{EgressBHRLCCHItemExtIEs }} OPTIONAL +} + +EgressBHRLCCHItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Endpoint-IP-address-and-port ::=SEQUENCE { + endpointIPAddress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { { Endpoint-IP-address-and-port-ExtIEs} } OPTIONAL +} + +Endpoint-IP-address-and-port-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-portNumber CRITICALITY reject EXTENSION PortNumber PRESENCE optional}, + ... +} + +ExtendedAvailablePLMN-List ::= SEQUENCE (SIZE(1..maxnoofExtendedBPLMNs)) OF ExtendedAvailablePLMN-Item + +ExtendedAvailablePLMN-Item ::= SEQUENCE { + pLMNIdentity PLMN-Identity, + iE-Extensions ProtocolExtensionContainer { { ExtendedAvailablePLMN-Item-ExtIEs} } OPTIONAL +} + +ExplicitFormat ::= SEQUENCE { + permutation Permutation, + noofDownlinkSymbols NoofDownlinkSymbols OPTIONAL, + noofUplinkSymbols NoofUplinkSymbols OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { ExplicitFormat-ExtIEs} } OPTIONAL +} + +ExplicitFormat-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ExtendedAvailablePLMN-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ExtendedServedPLMNs-List ::= SEQUENCE (SIZE(1.. maxnoofExtendedBPLMNs)) OF ExtendedServedPLMNs-Item + +ExtendedServedPLMNs-Item ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + tAISliceSupportList SliceSupportList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { ExtendedServedPLMNs-ItemExtIEs} } OPTIONAL, + ... +} + +ExtendedServedPLMNs-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-NPNSupportInfo CRITICALITY reject EXTENSION NPNSupportInfo PRESENCE optional }| +{ ID id-ExtendedTAISliceSupportList CRITICALITY reject EXTENSION ExtendedSliceSupportList PRESENCE optional }, + ... +} + +ExtendedSliceSupportList ::= SEQUENCE (SIZE(1.. maxnoofExtSliceItems)) OF SliceSupportItem + +EUTRACells-List ::= SEQUENCE (SIZE (1.. maxCellineNB)) OF EUTRACells-List-item + +EUTRACells-List-item ::= SEQUENCE { + eUTRA-Cell-ID EUTRA-Cell-ID, + served-EUTRA-Cells-Information Served-EUTRA-Cells-Information, + iE-Extensions ProtocolExtensionContainer { { EUTRACells-List-itemExtIEs } } OPTIONAL +} + +EUTRACells-List-itemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +EUTRA-Cell-ID ::= BIT STRING (SIZE(28)) + +EUTRA-Coex-FDD-Info ::= SEQUENCE { + uL-EARFCN ExtendedEARFCN OPTIONAL, + dL-EARFCN ExtendedEARFCN, + uL-Transmission-Bandwidth EUTRA-Transmission-Bandwidth OPTIONAL, + dL-Transmission-Bandwidth EUTRA-Transmission-Bandwidth, + iE-Extensions ProtocolExtensionContainer { {EUTRA-Coex-FDD-Info-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-Coex-FDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ULCarrierList CRITICALITY ignore EXTENSION NRCarrierList PRESENCE optional }| + { ID id-DLCarrierList CRITICALITY ignore EXTENSION NRCarrierList PRESENCE optional }, + ... +} + +EUTRA-Coex-Mode-Info ::= CHOICE { + fDD EUTRA-Coex-FDD-Info, + tDD EUTRA-Coex-TDD-Info, + ... +} + +EUTRA-Coex-TDD-Info ::= SEQUENCE { + eARFCN ExtendedEARFCN, + transmission-Bandwidth EUTRA-Transmission-Bandwidth, + subframeAssignment EUTRA-SubframeAssignment, + specialSubframe-Info EUTRA-SpecialSubframe-Info, + iE-Extensions ProtocolExtensionContainer { {EUTRA-Coex-TDD-Info-ExtIEs} } OPTIONAL, + ... +} +EUTRA-Coex-TDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} +EUTRA-CyclicPrefixDL ::= ENUMERATED { + normal, + extended, + ... +} + +EUTRA-CyclicPrefixUL ::= ENUMERATED { + normal, + extended, + ... +} + +EUTRA-PRACH-Configuration ::= SEQUENCE { + rootSequenceIndex INTEGER (0..837), + zeroCorrelationIndex INTEGER (0..15), + highSpeedFlag BOOLEAN, + prach-FreqOffset INTEGER (0..94), + prach-ConfigIndex INTEGER (0..63) OPTIONAL, + -- C-ifTDD: This IE shall be present if the EUTRA-Mode-Info IE in the Resource Coordination E-UTRA Cell Information IE is set to the value "TDD" + iE-Extensions ProtocolExtensionContainer { {EUTRA-PRACH-Configuration-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-PRACH-Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +EUTRA-SpecialSubframe-Info ::= SEQUENCE { + specialSubframePatterns EUTRA-SpecialSubframePatterns, + cyclicPrefixDL EUTRA-CyclicPrefixDL, + cyclicPrefixUL EUTRA-CyclicPrefixUL, + iE-Extensions ProtocolExtensionContainer { { EUTRA-SpecialSubframe-Info-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-SpecialSubframe-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +EUTRA-SpecialSubframePatterns ::= ENUMERATED { + ssp0, + ssp1, + ssp2, + ssp3, + ssp4, + ssp5, + ssp6, + ssp7, + ssp8, + ssp9, + ssp10, + ... +} + +EUTRA-SubframeAssignment ::= ENUMERATED { + sa0, + sa1, + sa2, + sa3, + sa4, + sa5, + sa6, + ... +} + +EUTRA-Transmission-Bandwidth ::= ENUMERATED { + bw6, + bw15, + bw25, + bw50, + bw75, + bw100, + ... +} + +EUTRANQoS ::= SEQUENCE { + qCI QCI, + allocationAndRetentionPriority AllocationAndRetentionPriority, + gbrQosInformation GBR-QosInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { EUTRANQoS-ExtIEs} } OPTIONAL, + ... +} + +EUTRANQoS-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ExecuteDuplication ::= ENUMERATED{true,...} + +ExtendedEARFCN ::= INTEGER (0..262143) + +EUTRA-Mode-Info ::= CHOICE { + eUTRAFDD EUTRA-FDD-Info, + eUTRATDD EUTRA-TDD-Info, + choice-extension ProtocolIE-SingleContainer { { EUTRA-Mode-Info-ExtIEs} } +} + +EUTRA-Mode-Info-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +EUTRA-NR-CellResourceCoordinationReq-Container ::= OCTET STRING + +EUTRA-NR-CellResourceCoordinationReqAck-Container ::= OCTET STRING + +EUTRA-FDD-Info ::= SEQUENCE { + uL-offsetToPointA OffsetToPointA, + dL-offsetToPointA OffsetToPointA, + iE-Extensions ProtocolExtensionContainer { {EUTRA-FDD-Info-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-FDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +EUTRA-TDD-Info ::= SEQUENCE { + offsetToPointA OffsetToPointA, + iE-Extensions ProtocolExtensionContainer { {EUTRA-TDD-Info-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-TDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +EventType ::= ENUMERATED { + on-demand, + periodic, + stop, + ... +} + +ExtendedPacketDelayBudget ::= INTEGER (1..65535, ...) + +-- F + +FDD-Info ::= SEQUENCE { + uL-NRFreqInfo NRFreqInfo, + dL-NRFreqInfo NRFreqInfo, + uL-Transmission-Bandwidth Transmission-Bandwidth, + dL-Transmission-Bandwidth Transmission-Bandwidth, + iE-Extensions ProtocolExtensionContainer { {FDD-Info-ExtIEs} } OPTIONAL, + ... +} + +FDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +Flows-Mapped-To-DRB-List ::= SEQUENCE (SIZE(1.. maxnoofQoSFlows)) OF Flows-Mapped-To-DRB-Item + +Flows-Mapped-To-DRB-Item ::= SEQUENCE { + qoSFlowIdentifier QoSFlowIdentifier, + qoSFlowLevelQoSParameters QoSFlowLevelQoSParameters, + iE-Extensions ProtocolExtensionContainer { { Flows-Mapped-To-DRB-ItemExtIEs} } OPTIONAL +} + +Flows-Mapped-To-DRB-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-QoSFlowMappingIndication CRITICALITY ignore EXTENSION QoSFlowMappingIndication PRESENCE optional}| + {ID id-TSCTrafficCharacteristics CRITICALITY ignore EXTENSION TSCTrafficCharacteristics PRESENCE optional}, + ... +} + +FR1-Bandwidth ::= ENUMERATED {bw5, bw10, bw20, bw40, bw50, bw80, bw100, ...} + +FR2-Bandwidth ::= ENUMERATED {bw50, bw100, bw200, bw400, ...} + +FreqBandNrItem ::= SEQUENCE { + freqBandIndicatorNr INTEGER (1..1024,...), + supportedSULBandList SEQUENCE (SIZE(0..maxnoofNrCellBands)) OF SupportedSULFreqBandItem, + iE-Extensions ProtocolExtensionContainer { {FreqBandNrItem-ExtIEs} } OPTIONAL, + ... +} + +FreqBandNrItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +FreqDomainLength ::= CHOICE { + l839 L839Info, + l139 L139Info, + choice-extension ProtocolIE-SingleContainer { {FreqDomainLength-ExtIEs} } +} + +FreqDomainLength-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +FrequencyShift7p5khz ::= ENUMERATED {false, true, ...} + +FullConfiguration ::= ENUMERATED {full, ...} + +FlowsMappedToSLDRB-List ::= SEQUENCE (SIZE(1.. maxnoofPC5QoSFlows)) OF FlowsMappedToSLDRB-Item + +FlowsMappedToSLDRB-Item ::= SEQUENCE { + pc5QoSFlowIdentifier PC5QoSFlowIdentifier, + iE-Extensions ProtocolExtensionContainer { {FlowsMappedToSLDRB-Item-ExtIEs} } OPTIONAL, + ... +} + +FlowsMappedToSLDRB-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- G + + +GBR-QosInformation ::= SEQUENCE { + e-RAB-MaximumBitrateDL BitRate, + e-RAB-MaximumBitrateUL BitRate, + e-RAB-GuaranteedBitrateDL BitRate, + e-RAB-GuaranteedBitrateUL BitRate, + iE-Extensions ProtocolExtensionContainer { { GBR-QosInformation-ExtIEs} } OPTIONAL, + ... +} + +GBR-QosInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GBR-QoSFlowInformation::= SEQUENCE { + maxFlowBitRateDownlink BitRate, + maxFlowBitRateUplink BitRate, + guaranteedFlowBitRateDownlink BitRate, + guaranteedFlowBitRateUplink BitRate, + maxPacketLossRateDownlink MaxPacketLossRate OPTIONAL, + maxPacketLossRateUplink MaxPacketLossRate OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GBR-QosFlowInformation-ExtIEs} } OPTIONAL, + ... +} + +GBR-QosFlowInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AlternativeQoSParaSetList CRITICALITY ignore EXTENSION AlternativeQoSParaSetList PRESENCE optional }, + ... +} + +CG-Config ::= OCTET STRING + +GeographicalCoordinates ::= SEQUENCE { + tRPPositionDefinitionType TRPPositionDefinitionType, + dLPRSResourceCoordinates DLPRSResourceCoordinates OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GeographicalCoordinates-ExtIEs } } OPTIONAL +} + +GeographicalCoordinates-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNBCUMeasurementID ::= INTEGER (0.. 4095, ...) + +GNBDUMeasurementID ::= INTEGER (0.. 4095, ...) + +GNB-CUSystemInformation::= SEQUENCE { + sibtypetobeupdatedlist SEQUENCE (SIZE(1.. maxnoofSIBTypes)) OF SibtypetobeupdatedListItem, + iE-Extensions ProtocolExtensionContainer { { GNB-CUSystemInformation-ExtIEs} } OPTIONAL, + ... +} + +GNB-CUSystemInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-systemInformationAreaID CRITICALITY ignore EXTENSION SystemInformationAreaID PRESENCE optional}, + ... +} + +GNB-CU-TNL-Association-Setup-Item::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-Setup-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-Setup-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-CU-TNL-Association-Failed-To-Setup-Item ::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + cause Cause, + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-Failed-To-Setup-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-Failed-To-Setup-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +GNB-CU-TNL-Association-To-Add-Item ::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + tNLAssociationUsage TNLAssociationUsage, + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-To-Add-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-To-Add-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-CU-TNL-Association-To-Remove-Item::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-To-Remove-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-To-Remove-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-TNLAssociationTransportLayerAddressgNBDU CRITICALITY reject EXTENSION CP-TransportLayerAddress PRESENCE optional}, + ... +} + + +GNB-CU-TNL-Association-To-Update-Item::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + tNLAssociationUsage TNLAssociationUsage OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-CU-TNL-Association-To-Update-Item-ExtIEs} } OPTIONAL +} + +GNB-CU-TNL-Association-To-Update-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-CU-UE-F1AP-ID ::= INTEGER (0..4294967295) + +GNB-DU-Cell-Resource-Configuration ::= SEQUENCE { + subcarrierSpacing SubcarrierSpacing, + dUFTransmissionPeriodicity DUFTransmissionPeriodicity OPTIONAL, + dUF-Slot-Config-List DUF-Slot-Config-List OPTIONAL, + hSNATransmissionPeriodicity HSNATransmissionPeriodicity, + hNSASlotConfigList HSNASlotConfigList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-DU-Cell-Resource-Configuration-ExtIEs } } OPTIONAL +} + +GNB-DU-Cell-Resource-Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-DU-UE-F1AP-ID ::= INTEGER (0..4294967295) + +GNB-DU-ID ::= INTEGER (0..68719476735) + +GNB-CU-Name ::= PrintableString(SIZE(1..150,...)) + +GNB-DU-Name ::= PrintableString(SIZE(1..150,...)) + +Extended-GNB-CU-Name ::= SEQUENCE { + gNB-CU-NameVisibleString GNB-CU-NameVisibleString OPTIONAL, + gNB-CU-NameUTF8String GNB-CU-NameUTF8String OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Extended-GNB-CU-Name-ExtIEs } } OPTIONAL, + ... +} + +Extended-GNB-CU-Name-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-CU-NameVisibleString ::= VisibleString(SIZE(1..150,...)) + +GNB-CU-NameUTF8String ::= UTF8String(SIZE(1..150,...)) + +Extended-GNB-DU-Name ::= SEQUENCE { + gNB-DU-NameVisibleString GNB-DU-NameVisibleString OPTIONAL, + gNB-DU-NameUTF8String GNB-DU-NameUTF8String OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Extended-GNB-DU-Name-ExtIEs } } OPTIONAL, + ... +} + +Extended-GNB-DU-Name-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-DU-NameVisibleString ::= VisibleString(SIZE(1..150,...)) + +GNB-DU-NameUTF8String ::= UTF8String(SIZE(1..150,...)) + + +GNB-DU-Served-Cells-Item ::= SEQUENCE { + served-Cell-Information Served-Cell-Information, + gNB-DU-System-Information GNB-DU-System-Information OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-DU-Served-Cells-ItemExtIEs} } OPTIONAL, + ... +} + +GNB-DU-Served-Cells-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-DU-System-Information ::= SEQUENCE { + mIB-message MIB-message, + sIB1-message SIB1-message, + iE-Extensions ProtocolExtensionContainer { { GNB-DU-System-Information-ExtIEs } } OPTIONAL, + ... +} + +GNB-DU-System-Information-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-SIB12-message CRITICALITY ignore EXTENSION SIB12-message PRESENCE optional}| + { ID id-SIB13-message CRITICALITY ignore EXTENSION SIB13-message PRESENCE optional}| + { ID id-SIB14-message CRITICALITY ignore EXTENSION SIB14-message PRESENCE optional}| + { ID id-SIB10-message CRITICALITY ignore EXTENSION SIB10-message PRESENCE optional}, + ... +} + +GNB-DUConfigurationQuery ::= ENUMERATED {true, ...} + +GNBDUOverloadInformation ::= ENUMERATED {overloaded, not-overloaded} + +GNB-DU-TNL-Association-To-Remove-Item::= SEQUENCE { + tNLAssociationTransportLayerAddress CP-TransportLayerAddress , + tNLAssociationTransportLayerAddressgNBCU CP-TransportLayerAddress OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-DU-TNL-Association-To-Remove-Item-ExtIEs} } OPTIONAL +} + +GNB-DU-TNL-Association-To-Remove-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GNB-RxTxTimeDiff ::= SEQUENCE { + rxTxTimeDiff GNBRxTxTimeDiffMeas, + additionalPath-List AdditionalPath-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { GNB-RxTxTimeDiff-ExtIEs} } OPTIONAL +} + +GNB-RxTxTimeDiff-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + + ... +} + +GNBRxTxTimeDiffMeas ::= CHOICE { + k0 INTEGER (0.. 1970049), + k1 INTEGER (0.. 985025), + k2 INTEGER (0.. 492513), + k3 INTEGER (0.. 246257), + k4 INTEGER (0.. 123129), + k5 INTEGER (0.. 61565), + choice-extension ProtocolIE-SingleContainer { { GNBRxTxTimeDiffMeas-ExtIEs } } +} + +GNBRxTxTimeDiffMeas-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +GNBSetID ::= BIT STRING (SIZE(22)) + +GTP-TEID ::= OCTET STRING (SIZE (4)) + +GTPTLAs ::= SEQUENCE (SIZE(1.. maxnoofGTPTLAs)) OF GTPTLA-Item + + +GTPTLA-Item ::= SEQUENCE { + gTPTransportLayerAddress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { { GTPTLA-Item-ExtIEs } } OPTIONAL +} + +GTPTLA-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +GTPTunnel ::= SEQUENCE { + transportLayerAddress TransportLayerAddress, + gTP-TEID GTP-TEID, + iE-Extensions ProtocolExtensionContainer { { GTPTunnel-ExtIEs } } OPTIONAL, + ... +} + +GTPTunnel-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- H + +HandoverPreparationInformation ::= OCTET STRING + +HardwareLoadIndicator ::= SEQUENCE { + dLHardwareLoadIndicator INTEGER (0..100, ...), + uLHardwareLoadIndicator INTEGER (0..100, ...), + iE-Extensions ProtocolExtensionContainer { { HardwareLoadIndicator-ExtIEs } } OPTIONAL, + ... +} + +HardwareLoadIndicator-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +HSNASlotConfigList ::= SEQUENCE (SIZE(1..maxnoofHSNASlots)) OF HSNASlotConfigItem + +HSNASlotConfigItem ::= SEQUENCE { + hSNADownlink HSNADownlink OPTIONAL, + hSNAUplink HSNAUplink OPTIONAL, + hSNAFlexible HSNAFlexible OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { HSNASlotConfigItem-ExtIEs } } OPTIONAL +} + +HSNASlotConfigItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} +HSNADownlink ::= ENUMERATED { hard, soft, notavailable } + +HSNAFlexible ::= ENUMERATED { hard, soft, notavailable } + +HSNAUplink ::= ENUMERATED { hard, soft, notavailable } + +HSNATransmissionPeriodicity ::= ENUMERATED { ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms5, ms10, ms20, ms40, ms80, ms160, ...} + +-- I + +IAB-Barred ::= ENUMERATED {barred, not-barred, ...} + +IAB-Info-IAB-donor-CU ::= SEQUENCE{ + iAB-STC-Info IAB-STC-Info OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IAB-Info-IAB-donor-CU-ExtIEs } } OPTIONAL +} + +IAB-Info-IAB-donor-CU-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-Info-IAB-DU ::= SEQUENCE{ + multiplexingInfo MultiplexingInfo OPTIONAL, + iAB-STC-Info IAB-STC-Info OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IAB-Info-IAB-DU-ExtIEs } } OPTIONAL +} + +IAB-Info-IAB-DU-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-MT-Cell-List ::= SEQUENCE (SIZE(1..maxnoofServingCells)) OF IAB-MT-Cell-List-Item + +IAB-MT-Cell-List-Item ::= SEQUENCE { + nRCellIdentity NRCellIdentity, + dU-RX-MT-RX DU-RX-MT-RX, + dU-TX-MT-TX DU-TX-MT-TX, + dU-RX-MT-TX DU-RX-MT-TX, + dU-TX-MT-RX DU-TX-MT-RX, + iE-Extensions ProtocolExtensionContainer { { IAB-MT-Cell-List-Item-ExtIEs } } OPTIONAL +} + +IAB-MT-Cell-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-STC-Info ::= SEQUENCE{ + iAB-STC-Info-List IAB-STC-Info-List, + iE-Extensions ProtocolExtensionContainer { { IAB-STC-Info-ExtIEs } } OPTIONAL +} + +IAB-STC-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-STC-Info-List ::= SEQUENCE (SIZE(1..maxnoofIABSTCInfo)) OF IAB-STC-Info-Item + +IAB-STC-Info-Item::= SEQUENCE { + sSB-freqInfo SSB-freqInfo, + sSB-subcarrierSpacing SSB-subcarrierSpacing, + sSB-transmissionPeriodicity SSB-transmissionPeriodicity, + sSB-transmissionTimingOffset SSB-transmissionTimingOffset, + sSB-transmissionBitmap SSB-transmissionBitmap, + iE-Extensions ProtocolExtensionContainer { { IAB-STC-Info-Item-ExtIEs } } OPTIONAL +} + +IAB-STC-Info-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-Allocated-TNL-Address-Item ::= SEQUENCE { + iABTNLAddress IABTNLAddress, + iABTNLAddressUsage IABTNLAddressUsage OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IAB-Allocated-TNL-Address-Item-ExtIEs } } OPTIONAL +} + +IAB-Allocated-TNL-Address-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-DU-Cell-Resource-Configuration-Mode-Info ::= CHOICE { + fDD IAB-DU-Cell-Resource-Configuration-FDD-Info, + tDD IAB-DU-Cell-Resource-Configuration-TDD-Info, + choice-extension ProtocolIE-SingleContainer { { IAB-DU-Cell-Resource-Configuration-Mode-Info-ExtIEs} } +} + +IAB-DU-Cell-Resource-Configuration-Mode-Info-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +IAB-DU-Cell-Resource-Configuration-FDD-Info ::= SEQUENCE { + gNB-DU-Cell-Resource-Configuration-FDD-UL GNB-DU-Cell-Resource-Configuration, + gNB-DU-Cell-Resource-Configuration-FDD-DL GNB-DU-Cell-Resource-Configuration, + iE-Extensions ProtocolExtensionContainer { {IAB-DU-Cell-Resource-Configuration-FDD-Info-ExtIEs} } OPTIONAL, + ... +} + +IAB-DU-Cell-Resource-Configuration-FDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-DU-Cell-Resource-Configuration-TDD-Info ::= SEQUENCE { + gNB-DU-Cell-Resourc-Configuration-TDD GNB-DU-Cell-Resource-Configuration, + iE-Extensions ProtocolExtensionContainer { {IAB-DU-Cell-Resource-Configuration-TDD-Info-ExtIEs} } OPTIONAL, + ... +} + +IAB-DU-Cell-Resource-Configuration-TDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IABIPv6RequestType ::= CHOICE { + iPv6Address IABTNLAddressesRequested, + iPv6Prefix IABTNLAddressesRequested, + choice-extension ProtocolIE-SingleContainer { { IABIPv6RequestType-ExtIEs} } +} + +IABIPv6RequestType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +IABTNLAddress ::= CHOICE { + iPv4Address BIT STRING (SIZE(32)), + iPv6Address BIT STRING (SIZE(128)), + iPv6Prefix BIT STRING (SIZE(64)), + choice-extension ProtocolIE-SingleContainer { { IABTNLAddress-ExtIEs} } +} + +IABTNLAddress-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +IABTNLAddressesRequested ::= SEQUENCE { + tNLAddressesOrPrefixesRequestedAllTraffic INTEGER (1..256) OPTIONAL, + tNLAddressesOrPrefixesRequestedF1-C INTEGER (1..256) OPTIONAL, + tNLAddressesOrPrefixesRequestedF1-U INTEGER (1..256) OPTIONAL, + tNLAddressesOrPrefixesRequestedNoNF1 INTEGER (1..256) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IABTNLAddressesRequested-ExtIEs } } OPTIONAL +} + +IABTNLAddressesRequested-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IAB-TNL-Addresses-To-Remove-Item ::= SEQUENCE { + iABTNLAddress IABTNLAddress, + iE-Extensions ProtocolExtensionContainer { { IAB-TNL-Addresses-To-Remove-Item-ExtIEs} } OPTIONAL +} + +IAB-TNL-Addresses-To-Remove-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IABTNLAddressUsage ::= ENUMERATED { + f1-c, + f1-u, + non-f1, + ... +} + + +IABv4AddressesRequested ::= SEQUENCE { + iABv4AddressesRequested IABTNLAddressesRequested, + iE-Extensions ProtocolExtensionContainer { { IABv4AddressesRequested-ExtIEs} } OPTIONAL +} + +IABv4AddressesRequested-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ImplicitFormat ::= SEQUENCE { + dUFSlotformatIndex DUFSlotformatIndex, + iE-Extensions ProtocolExtensionContainer { { ImplicitFormat-ExtIEs } } OPTIONAL +} + +ImplicitFormat-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IgnorePRACHConfiguration::= ENUMERATED { true,...} + +IgnoreResourceCoordinationContainer ::= ENUMERATED { yes,...} +InactivityMonitoringRequest ::= ENUMERATED { true,...} +InactivityMonitoringResponse ::= ENUMERATED { not-supported,...} +InterfacesToTrace ::= BIT STRING (SIZE(8)) + +IntendedTDD-DL-ULConfig ::= SEQUENCE { + nRSCS ENUMERATED { scs15, scs30, scs60, scs120,...}, + nRCP ENUMERATED { normal, extended,...}, + nRDLULTxPeriodicity ENUMERATED { ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms3, ms4, ms5, ms10, ms20, ms40, ms60, ms80, ms100, ms120, ms140, ms160, ...}, + slot-Configuration-List Slot-Configuration-List, + iE-Extensions ProtocolExtensionContainer { {IntendedTDD-DL-ULConfig-ExtIEs} } OPTIONAL +} + +IntendedTDD-DL-ULConfig-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IPHeaderInformation ::= SEQUENCE { + destinationIABTNLAddress IABTNLAddress, + dsInformationList DSInformationList OPTIONAL, + iPv6FlowLabel BIT STRING (SIZE (20)) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IPHeaderInformation-ItemExtIEs} } OPTIONAL, + ... +} + +IPHeaderInformation-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +IPtolayer2TrafficMappingInfo ::= SEQUENCE { + iPtolayer2TrafficMappingInfoToAdd IPtolayer2TrafficMappingInfoList OPTIONAL, + iPtolayer2TrafficMappingInfoToRemove MappingInformationtoRemove OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { IPtolayer2TrafficMappingInfo-ItemExtIEs} } OPTIONAL, + ... +} + +IPtolayer2TrafficMappingInfoList ::= SEQUENCE (SIZE(1..maxnoofMappingEntries)) OF IPtolayer2TrafficMappingInfo-Item + +IPtolayer2TrafficMappingInfo-Item ::= SEQUENCE { + mappingInformationIndex MappingInformationIndex, + iPHeaderInformation IPHeaderInformation, + bHInfo BHInfo, iE-Extensions ProtocolExtensionContainer { { IPtolayer2TrafficMappingInfo-ItemExtIEs} } OPTIONAL, + ... +} + +IPtolayer2TrafficMappingInfo-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- J + +-- K + +-- L + +L139Info ::= SEQUENCE { + msg1SCS ENUMERATED {scs15, scs30, scs60, scs120, ...}, + rootSequenceIndex INTEGER (0..137) OPTIONAL, + iE-Extension ProtocolExtensionContainer { {L139Info-ExtIEs} } OPTIONAL, + ... +} + +L139Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +L839Info ::= SEQUENCE { + rootSequenceIndex INTEGER (0..837), + restrictedSetConfig ENUMERATED {unrestrictedSet, restrictedSetTypeA, + restrictedSetTypeB, ...}, + iE-Extension ProtocolExtensionContainer { {L839Info-ExtIEs} } OPTIONAL, + ... +} + +L839Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +LCID ::= INTEGER (1..32, ...) + + +LCStoGCSTranslationList ::= SEQUENCE (SIZE (1.. maxnooflcs-gcs-translation)) OF LCStoGCSTranslation + +LCStoGCSTranslation ::= SEQUENCE { + alpha INTEGER (0..359), + alpha-fine INTEGER (0..9), + beta INTEGER (0..359), + beta-fine INTEGER (0..9), + gamma INTEGER (0..359), + gamma-fine INTEGER (0..9), + iE-Extensions ProtocolExtensionContainer { {LCStoGCSTranslation-ExtIEs} } OPTIONAL +} + +LCStoGCSTranslation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +LMF-MeasurementID ::= INTEGER (1.. 65536, ...) + +LMF-UE-MeasurementID ::= INTEGER (1.. 256, ...) + +LocationUncertainty ::= SEQUENCE { + horizontalUncertainty INTEGER (0..255), + horizontalConfidence INTEGER (0..100), + verticalUncertainty INTEGER (0..255), + verticalConfidence INTEGER (0..100), + iE-Extensions ProtocolExtensionContainer { { LocationUncertainty-ExtIEs} } OPTIONAL +} + +LocationUncertainty-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +LongDRXCycleLength ::= ENUMERATED +{ms10, ms20, ms32, ms40, ms60, ms64, ms70, ms80, ms128, ms160, ms256, ms320, ms512, ms640, ms1024, ms1280, ms2048, ms2560, ms5120, ms10240, ...} + +LowerLayerPresenceStatusChange ::= ENUMERATED { + suspend-lower-layers, + resume-lower-layers, + ... + +} + +LTEUESidelinkAggregateMaximumBitrate ::= SEQUENCE { + uELTESidelinkAggregateMaximumBitrate BitRate, + iE-Extensions ProtocolExtensionContainer { {LTEUESidelinkAggregateMaximumBitrate-ExtIEs} } OPTIONAL +} + +LTEUESidelinkAggregateMaximumBitrate-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +LTEV2XServicesAuthorized ::= SEQUENCE { + vehicleUE VehicleUE OPTIONAL, + pedestrianUE PedestrianUE OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {LTEV2XServicesAuthorized-ExtIEs} } OPTIONAL +} + +LTEV2XServicesAuthorized-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- M + +MappingInformationIndex ::= BIT STRING (SIZE (26)) + +MappingInformationtoRemove ::= SEQUENCE (SIZE(1..maxnoofMappingEntries)) OF MappingInformationIndex + +MaskedIMEISV ::= BIT STRING (SIZE (64)) + +MaxDataBurstVolume ::= INTEGER (0..4095, ..., 4096.. 2000000) +MaxPacketLossRate ::= INTEGER (0..1000) + +MIB-message ::= OCTET STRING + +MeasConfig ::= OCTET STRING + +MeasGapConfig ::= OCTET STRING + +MeasGapSharingConfig ::= OCTET STRING + +MeasurementBeamInfoRequest ::= ENUMERATED {true, ...} + +MeasurementBeamInfo ::= SEQUENCE { + pRS-Resource-ID PRS-Resource-ID OPTIONAL, + pRS-Resource-Set-ID PRS-Resource-Set-ID OPTIONAL, + sSB-Index SSB-Index OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { MeasurementBeamInfo-ExtIEs} } OPTIONAL +} + +MeasurementBeamInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +MeasurementTimingConfiguration ::= OCTET STRING + +MessageIdentifier ::= BIT STRING (SIZE (16)) + +MultiplexingInfo ::= SEQUENCE{ + iAB-MT-Cell-List IAB-MT-Cell-List, + iE-Extensions ProtocolExtensionContainer { {MultiplexingInfo-ExtIEs} } OPTIONAL +} + +MultiplexingInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +M2Configuration ::= ENUMERATED {true, ...} + + +M5Configuration ::= SEQUENCE { + m5period M5period, + m5-links-to-log M5-Links-to-log, + iE-Extensions ProtocolExtensionContainer { { M5Configuration-ExtIEs} } OPTIONAL, + ... +} + +M5Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +M5period ::= ENUMERATED { ms1024, ms2048, ms5120, ms10240, min1, ... } + +M5-Links-to-log ::= ENUMERATED {uplink, downlink, both-uplink-and-downlink, ...} + + +M6Configuration ::= SEQUENCE { + m6report-Interval M6report-Interval, + m6-links-to-log M6-Links-to-log, + iE-Extensions ProtocolExtensionContainer { { M6Configuration-ExtIEs} } OPTIONAL, + ... +} + +M6Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +M6report-Interval ::= ENUMERATED { ms120, ms240, ms640, ms1024, ms2048, ms5120, ms10240, ms20480, ms40960, min1, min6, min12, min30, ... } + + + +M6-Links-to-log ::= ENUMERATED {uplink, downlink, both-uplink-and-downlink, ...} + + +M7Configuration ::= SEQUENCE { + m7period M7period, + m7-links-to-log M7-Links-to-log, + iE-Extensions ProtocolExtensionContainer { { M7Configuration-ExtIEs} } OPTIONAL, + ... +} + +M7Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +M7period ::= INTEGER(1..60, ...) + +M7-Links-to-log ::= ENUMERATED {downlink, ...} + +MDT-Activation ::= ENUMERATED { + immediate-MDT-only, + immediate-MDT-and-Trace, + ... +} + +MDTConfiguration ::= SEQUENCE { + mdt-Activation MDT-Activation, + measurementsToActivate MeasurementsToActivate, + m2Configuration M2Configuration OPTIONAL, + -- C-ifM2: This IE shall be present if the Measurements to Activate IE has the second bit set to "1". + m5Configuration M5Configuration OPTIONAL, + -- C-ifM5: This IE shall be present if the Measurements to Activate IE has the fifth bit set to "1". + m6Configuration M6Configuration OPTIONAL, + -- C-ifM6: This IE shall be present if the Measurements to Activate IE has the seventh bit set to "1". + m7Configuration M7Configuration OPTIONAL, + -- C-ifM7: This IE shall be present if the Measurements to Activate IE has the eighth bit set to "1". + iE-Extensions ProtocolExtensionContainer { { MDTConfiguration-ExtIEs} } OPTIONAL, + ... +} +MDTConfiguration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +MDTPLMNList ::= SEQUENCE (SIZE(1..maxnoofMDTPLMNs)) OF PLMN-Identity + + +MeasuredResultsValue ::= CHOICE { + uL-AngleOfArrival UL-AoA, + uL-SRS-RSRP UL-SRS-RSRP, + uL-RTOA UL-RTOA-Measurement, + gNB-RxTxTimeDiff GNB-RxTxTimeDiff, + choice-extension ProtocolIE-SingleContainer { { MeasuredResultsValue-ExtIEs } } +} + +MeasuredResultsValue-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +MeasurementsToActivate ::= BIT STRING (SIZE (8)) + +-- N + +NeedforGap::= ENUMERATED {true, ...} + +Neighbour-Cell-Information-Item ::= SEQUENCE { + nRCGI NRCGI, + intendedTDD-DL-ULConfig IntendedTDD-DL-ULConfig OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Neighbour-Cell-Information-ItemExtIEs } } OPTIONAL +} + +Neighbour-Cell-Information-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NGRANAllocationAndRetentionPriority ::= SEQUENCE { + priorityLevel PriorityLevel, + pre-emptionCapability Pre-emptionCapability, + pre-emptionVulnerability Pre-emptionVulnerability, + iE-Extensions ProtocolExtensionContainer { {NGRANAllocationAndRetentionPriority-ExtIEs} } OPTIONAL +} + +NGRANAllocationAndRetentionPriority-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +NGRANHighAccuracyAccessPointPosition ::= SEQUENCE { + latitude INTEGER (-2147483648.. 2147483647), + longitude INTEGER (-2147483648.. 2147483647), + altitude INTEGER (-64000..1280000), + uncertaintySemi-major INTEGER (0..255), + uncertaintySemi-minor INTEGER (0..255), + orientationOfMajorAxis INTEGER (0..179), + horizontalConfidence INTEGER (0..100), + uncertaintyAltitude INTEGER (0..255), + verticalConfidence INTEGER (0..100), + + iE-Extensions ProtocolExtensionContainer { { NGRANHighAccuracyAccessPointPosition-ExtIEs} } OPTIONAL +} + +NGRANHighAccuracyAccessPointPosition-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NID ::= BIT STRING (SIZE(44)) + +NR-CGI-List-For-Restart-Item ::= SEQUENCE { + nRCGI NRCGI, + iE-Extensions ProtocolExtensionContainer { { NR-CGI-List-For-Restart-ItemExtIEs } } OPTIONAL, + ... +} + +NR-CGI-List-For-Restart-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NR-PRSBeamInformation ::= SEQUENCE { + nR-PRSBeamInformationList NR-PRSBeamInformationList, + lCStoGCSTranslationList LCStoGCSTranslationList, + iE-Extensions ProtocolExtensionContainer { { NR-PRSBeamInformation-ExtIEs } } OPTIONAL +} + +NR-PRSBeamInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NR-PRSBeamInformationList ::= SEQUENCE (SIZE(1.. maxnoofPRS-ResourceSets)) OF NR-PRSBeamInformationItem + +NR-PRSBeamInformationItem ::= SEQUENCE { + pRSResourceSetID INTEGER (0..7), + pRSAngleList PRSAngleList, + iE-Extensions ProtocolExtensionContainer { { NR-PRSBeamInformationItem-ExtIEs } } OPTIONAL +} + +NR-PRSBeamInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NonDynamic5QIDescriptor ::= SEQUENCE { + fiveQI INTEGER (0..255, ...), + qoSPriorityLevel INTEGER (1..127) OPTIONAL, + averagingWindow AveragingWindow OPTIONAL, + maxDataBurstVolume MaxDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { NonDynamic5QIDescriptor-ExtIEs } } OPTIONAL +} + +NonDynamic5QIDescriptor-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-CNPacketDelayBudgetDownlink CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }| + { ID id-CNPacketDelayBudgetUplink CRITICALITY ignore EXTENSION ExtendedPacketDelayBudget PRESENCE optional }, + ... +} + +NonDynamicPQIDescriptor ::= SEQUENCE { + fiveQI INTEGER (0..255, ...), + qoSPriorityLevel INTEGER (1..8, ...) OPTIONAL, + averagingWindow AveragingWindow OPTIONAL, + maxDataBurstVolume MaxDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { NonDynamicPQIDescriptor-ExtIEs } } OPTIONAL +} + +NonDynamicPQIDescriptor-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NonUPTrafficType ::= ENUMERATED {ue-associated, non-ue-associated, non-f1, bap-control-pdu,...} + +NoofDownlinkSymbols ::= INTEGER (0..14) + +NoofUplinkSymbols ::= INTEGER (0..14) + +Notification-Cause ::= ENUMERATED {fulfilled, not-fulfilled, ...} + +NotificationControl ::= ENUMERATED {active, not-active, ...} + +NotificationInformation ::= SEQUENCE { + message-Identifier MessageIdentifier, + serialNumber SerialNumber, + iE-Extensions ProtocolExtensionContainer { { NotificationInformationExtIEs} } OPTIONAL, + ... +} + +NotificationInformationExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NPNBroadcastInformation ::= CHOICE { + sNPN-Broadcast-Information NPN-Broadcast-Information-SNPN, + pNI-NPN-Broadcast-Information NPN-Broadcast-Information-PNI-NPN, + choice-extension ProtocolIE-SingleContainer { {NPNBroadcastInformation-ExtIEs} } +} + +NPNBroadcastInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +NPN-Broadcast-Information-SNPN ::= SEQUENCE { + broadcastSNPNID-List BroadcastSNPN-ID-List, + iE-Extension ProtocolExtensionContainer { {NPN-Broadcast-Information-SNPN-ExtIEs} } OPTIONAL, + ... +} + +NPN-Broadcast-Information-SNPN-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} +NPN-Broadcast-Information-PNI-NPN ::= SEQUENCE { + broadcastPNI-NPN-ID-Information BroadcastPNI-NPN-ID-List, + iE-Extension ProtocolExtensionContainer { {NPN-Broadcast-Information-PNI-NPN-ExtIEs} } OPTIONAL, + ... +} + +NPN-Broadcast-Information-PNI-NPN-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +NPNSupportInfo ::= CHOICE { + sNPN-Information NID, + choice-extension ProtocolIE-SingleContainer { { NPNSupportInfo-ExtIEs } } +} + +NPNSupportInfo-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +NRCarrierList ::= SEQUENCE (SIZE(1..maxnoofNRSCSs)) OF NRCarrierItem + +NRCarrierItem ::= SEQUENCE { + carrierSCS NRSCS, + offsetToCarrier INTEGER (0..2199, ...), + carrierBandwidth INTEGER (0..maxnoofPhysicalResourceBlocks, ...), + iE-Extension ProtocolExtensionContainer { {NRCarrierItem-ExtIEs} } OPTIONAL, + ... +} + +NRCarrierItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRFreqInfo ::= SEQUENCE { + nRARFCN INTEGER (0..maxNRARFCN), + sul-Information SUL-Information OPTIONAL, + freqBandListNr SEQUENCE (SIZE(1..maxnoofNrCellBands)) OF FreqBandNrItem, + iE-Extensions ProtocolExtensionContainer { { NRFreqInfoExtIEs} } OPTIONAL, + ... +} + +NRFreqInfoExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-FrequencyShift7p5khz CRITICALITY ignore EXTENSION FrequencyShift7p5khz PRESENCE optional }, + ... +} + +NRCGI ::= SEQUENCE { + pLMN-Identity PLMN-Identity, + nRCellIdentity NRCellIdentity, + iE-Extensions ProtocolExtensionContainer { {NRCGI-ExtIEs} } OPTIONAL, + ... +} + +NRCGI-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NR-Mode-Info ::= CHOICE { + fDD FDD-Info, + tDD TDD-Info, + choice-extension ProtocolIE-SingleContainer { { NR-Mode-Info-ExtIEs} } +} + +NR-Mode-Info-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + + +NRPRACHConfig ::= SEQUENCE { + ulPRACHConfigList NRPRACHConfigList OPTIONAL, + sulPRACHConfigList NRPRACHConfigList OPTIONAL, + iE-Extension ProtocolExtensionContainer { {NRPRACHConfig-ExtIEs} } OPTIONAL, + ... +} + +NRPRACHConfig-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRCellIdentity ::= BIT STRING (SIZE(36)) + +NRNRB ::= ENUMERATED { nrb11, nrb18, nrb24, nrb25, nrb31, nrb32, nrb38, nrb51, nrb52, nrb65, nrb66, nrb78, nrb79, nrb93, nrb106, nrb107, nrb121, nrb132, nrb133, nrb135, nrb160, nrb162, nrb189, nrb216, nrb217, nrb245, nrb264, nrb270, nrb273, ...} + +NRPCI ::= INTEGER(0..1007) + + +NRPRACHConfigList ::= SEQUENCE (SIZE(0..maxnoofPRACHconfigs)) OF NRPRACHConfigItem + +NRPRACHConfigItem ::= SEQUENCE { + nRSCS NRSCS, + prachFreqStartfromCarrier INTEGER (0..maxnoofPhysicalResourceBlocks-1, ...), + msg1FDM ENUMERATED {one, two, four, eight, ...}, + parchConfigIndex INTEGER (0..255, ...), + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, + two, four, eight, sixteen, ...}, + freqDomainLength FreqDomainLength, + zeroCorrelZoneConfig INTEGER (0..15), + iE-Extension ProtocolExtensionContainer { { NRPRACHConfigItem-ExtIEs} } OPTIONAL, + ... +} + +NRPRACHConfigItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRSCS ::= ENUMERATED { scs15, scs30, scs60, scs120, ...} + +NRUERLFReportContainer ::= OCTET STRING + +NumberofActiveUEs ::= INTEGER(0..16777215, ...) + +NumberOfBroadcasts ::= INTEGER (0..65535) + +NumberofBroadcastRequest ::= INTEGER (0..65535) + +NumDLULSymbols ::= SEQUENCE { + numDLSymbols INTEGER (0..13, ...), + numULSymbols INTEGER (0..13, ...), + iE-Extensions ProtocolExtensionContainer { { NumDLULSymbols-ExtIEs} } OPTIONAL +} + +NumDLULSymbols-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRV2XServicesAuthorized ::= SEQUENCE { + vehicleUE VehicleUE OPTIONAL, + pedestrianUE PedestrianUE OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {NRV2XServicesAuthorized-ExtIEs} } OPTIONAL +} + +NRV2XServicesAuthorized-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NRUESidelinkAggregateMaximumBitrate ::= SEQUENCE { + uENRSidelinkAggregateMaximumBitrate BitRate, + iE-Extensions ProtocolExtensionContainer { {NRUESidelinkAggregateMaximumBitrate-ExtIEs} } OPTIONAL +} + +NRUESidelinkAggregateMaximumBitrate-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +NZP-CSI-RS-ResourceID::= INTEGER (0..191, ...) + + +-- O + +OffsetToPointA ::= INTEGER (0..2199,...) + + +-- P + +PacketDelayBudget ::= INTEGER (0..1023, ...) + +PacketErrorRate ::= SEQUENCE { + pER-Scalar PER-Scalar, + pER-Exponent PER-Exponent, + iE-Extensions ProtocolExtensionContainer { {PacketErrorRate-ExtIEs} } OPTIONAL, + ... +} + +PacketErrorRate-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PER-Scalar ::= INTEGER (0..9, ...) +PER-Exponent ::= INTEGER (0..9, ...) + +PagingCell-Item ::= SEQUENCE { + nRCGI NRCGI , + iE-Extensions ProtocolExtensionContainer { { PagingCell-ItemExtIEs } } OPTIONAL +} + +PagingCell-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PagingDRX ::= ENUMERATED { + v32, + v64, + v128, + v256, + ... +} + +PagingIdentity ::= CHOICE { + rANUEPagingIdentity RANUEPagingIdentity, + cNUEPagingIdentity CNUEPagingIdentity, + choice-extension ProtocolIE-SingleContainer { { PagingIdentity-ExtIEs } } +} + +PagingIdentity-ExtIEs F1AP-PROTOCOL-IES::= { + ... +} + +PagingOrigin ::= ENUMERATED { non-3gpp, ...} + +PagingPriority ::= ENUMERATED { priolevel1, priolevel2, priolevel3, priolevel4, priolevel5, priolevel6, priolevel7, priolevel8,...} + + +RelativePathDelay ::= CHOICE { + k0 INTEGER (0..16351,...), + k1 INTEGER (0..8176,...), + k2 INTEGER (0..4088,...), + k3 INTEGER (0..2044,...), + k4 INTEGER (0..1022,...), + k5 INTEGER (0..511,...), + choice-extension ProtocolIE-SingleContainer { { RelativePathDelay-ExtIEs } } +} + +RelativePathDelay-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +PathlossReferenceInfo ::= SEQUENCE { + pathlossReferenceSignal PathlossReferenceSignal, + iE-Extensions ProtocolExtensionContainer { {PathlossReferenceInfo-ExtIEs} } OPTIONAL +} + +PathlossReferenceInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PathlossReferenceSignal ::= CHOICE { + sSB SSB, + dL-PRS DL-PRS, + choice-extension ProtocolIE-SingleContainer {{PathlossReferenceSignal-ExtIEs }} +} + +PathlossReferenceSignal-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +PC5QoSFlowIdentifier ::= INTEGER (1..2048) + +PC5-QoS-Characteristics ::= CHOICE { + non-Dynamic-PQI NonDynamicPQIDescriptor, + dynamic-PQI DynamicPQIDescriptor, + choice-extension ProtocolIE-SingleContainer { { PC5-QoS-Characteristics-ExtIEs } } +} + +PC5-QoS-Characteristics-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +PC5QoSParameters ::= SEQUENCE { + pC5-QoS-Characteristics PC5-QoS-Characteristics, + pC5-QoS-Flow-Bit-Rates PC5FlowBitRates OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PC5QoSParameters-ExtIEs } } OPTIONAL, + ... +} + +PC5QoSParameters-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PC5FlowBitRates ::= SEQUENCE { + guaranteedFlowBitRate BitRate, + maximumFlowBitRate BitRate, + iE-Extensions ProtocolExtensionContainer { { PC5FlowBitRates-ExtIEs } } OPTIONAL, + ... +} + +PC5FlowBitRates-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PDCCH-BlindDetectionSCG ::= OCTET STRING + +PDCP-SN ::= INTEGER (0..4095) + +PDCPSNLength ::= ENUMERATED { twelve-bits,eighteen-bits,...} + +PDUSessionID ::= INTEGER (0..255) + +ReportingPeriodicityValue ::= INTEGER (0..512, ...) + +Periodicity ::= INTEGER (0..640000, ...) + +PeriodicitySRS ::= ENUMERATED { ms0p125, ms0p25, ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms4, ms5, ms8, ms10, ms16, ms20, ms32, ms40, ms64, ms80, ms160, ms320, ms640, ms1280, ms2560, ms5120, ms10240, ...} + +PeriodicityList ::= SEQUENCE (SIZE(1.. maxnoSRS-ResourcePerSet)) OF PeriodicityList-Item + +PeriodicityList-Item ::= SEQUENCE { + periodicitySRS PeriodicitySRS, + iE-Extensions ProtocolExtensionContainer { { PeriodicityList-ItemExtIEs} } OPTIONAL +} + +PeriodicityList-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +Permutation ::= ENUMERATED {dfu, ufd, ...} + +Ph-InfoMCG ::= OCTET STRING + +Ph-InfoSCG ::= OCTET STRING + +PLMN-Identity ::= OCTET STRING (SIZE(3)) + +PortNumber ::= BIT STRING (SIZE (16)) + + +PosAssistance-Information ::= OCTET STRING + +PosAssistanceInformationFailureList ::= OCTET STRING + +PosBroadcast ::= ENUMERATED { + start, + stop, + ... +} + +PositioningBroadcastCells ::= SEQUENCE (SIZE (1..maxnoBcastCell)) OF NRCGI + +PosMeasurementPeriodicity ::= ENUMERATED +{ms120, ms240, ms480, ms640, ms1024, ms2048, ms5120, ms10240, min1, min6, min12, min30, min60, ...} + + +PosMeasurementQuantities ::= SEQUENCE (SIZE(1.. maxnoofPosMeas)) OF PosMeasurementQuantities-Item + +PosMeasurementQuantities-Item ::= SEQUENCE { + posMeasurementType PosMeasurementType, + timingReportingGranularityFactor INTEGER (0..5) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PosMeasurementQuantities-ItemExtIEs} } OPTIONAL +} + +PosMeasurementQuantities-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosMeasurementResult ::= SEQUENCE (SIZE (1.. maxnoofPosMeas)) OF PosMeasurementResultItem + +PosMeasurementResultItem ::= SEQUENCE { + measuredResultsValue MeasuredResultsValue, + timeStamp TimeStamp, + measurementQuality TRPMeasurementQuality OPTIONAL, + measurementBeamInfo MeasurementBeamInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PosMeasurementResultItemExtIEs } } OPTIONAL +} + +PosMeasurementResultItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosMeasurementResultList ::= SEQUENCE (SIZE(1.. maxNoOfMeasTRPs)) OF PosMeasurementResultList-Item + +PosMeasurementResultList-Item ::= SEQUENCE { + posMeasurementResult PosMeasurementResult, + tRPID TRPID, + iE-Extensions ProtocolExtensionContainer { { PosMeasurementResultList-ItemExtIEs} } OPTIONAL +} + +PosMeasurementResultList-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosMeasurementType ::= ENUMERATED { + gnb-rx-tx, + ul-srs-rsrp, + ul-aoa, + ul-rtoa, + ... +} + +PosReportCharacteristics ::= ENUMERATED { + ondemand, + periodic, + ... +} + +PosResourceSetType ::= CHOICE { + periodic PosResourceSetTypePR, + semi-persistent PosResourceSetTypeSP, + aperiodic PosResourceSetTypeAP, + choice-extension ProtocolIE-SingleContainer {{ PosResourceSetType-ExtIEs }} +} + +PosResourceSetType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +PosResourceSetTypePR ::= SEQUENCE { + posperiodicSet ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { PosResourceSetTypePR-ExtIEs} } OPTIONAL +} + +PosResourceSetTypePR-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosResourceSetTypeSP ::= SEQUENCE { + possemi-persistentSet ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { PosResourceSetTypeSP-ExtIEs} } OPTIONAL +} + +PosResourceSetTypeSP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosResourceSetTypeAP ::= SEQUENCE { + sRSResourceTrigger-List INTEGER(1..3), + iE-Extensions ProtocolExtensionContainer { { PosResourceSetTypeAP-ExtIEs} } OPTIONAL +} + +PosResourceSetTypeAP-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosSRSResourceID-List ::= SEQUENCE (SIZE (1..maxnoSRS-PosResourcePerSet)) OF SRSPosResourceID + +PosSRSResource-Item ::= SEQUENCE { + srs-PosResourceId SRSPosResourceID, + transmissionCombPos TransmissionCombPos, + startPosition INTEGER (0..13), + nrofSymbols ENUMERATED {n1, n2, n4, n8, n12}, + freqDomainShift INTEGER (0..268), + c-SRS INTEGER (0..63), + groupOrSequenceHopping ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceTypePos ResourceTypePos, + sequenceId INTEGER (0.. 65535), + spatialRelationPos SpatialRelationPos OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PosSRSResource-Item-ExtIEs} } OPTIONAL +} + +PosSRSResource-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosSRSResource-List ::= SEQUENCE (SIZE (1..maxnoSRS-PosResources)) OF PosSRSResource-Item + +PosSRSResourceSet-Item ::= SEQUENCE { + possrsResourceSetID INTEGER(0..15), + possRSResourceID-List PosSRSResourceID-List, + posresourceSetType PosResourceSetType, + iE-Extensions ProtocolExtensionContainer { { PosSRSResourceSet-Item-ExtIEs} } OPTIONAL +} + +PosSRSResourceSet-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PosSRSResourceSet-List ::= SEQUENCE (SIZE (1..maxnoSRS-PosResourceSets)) OF PosSRSResourceSet-Item + +PrimaryPathIndication ::= ENUMERATED { + true, + false, + ... +} + +Pre-emptionCapability ::= ENUMERATED { + shall-not-trigger-pre-emption, + may-trigger-pre-emption +} + +Pre-emptionVulnerability ::= ENUMERATED { + not-pre-emptable, + pre-emptable +} + +PriorityLevel ::= INTEGER { spare (0), highest (1), lowest (14), no-priority (15) } (0..15) + +ProtectedEUTRAResourceIndication ::= OCTET STRING + +Protected-EUTRA-Resources-Item ::= SEQUENCE { + spectrumSharingGroupID SpectrumSharingGroupID, + eUTRACells-List EUTRACells-List, + iE-Extensions ProtocolExtensionContainer { { Protected-EUTRA-Resources-ItemExtIEs } } OPTIONAL +} + +Protected-EUTRA-Resources-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSConfiguration ::= SEQUENCE { + pRSResourceSet-List PRSResourceSet-List, + iE-Extensions ProtocolExtensionContainer { { PRSConfiguration-ExtIEs } } OPTIONAL +} + +PRSConfiguration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSInformationPos ::= SEQUENCE { + pRS-IDPos INTEGER(0..255) OPTIONAL, + pRS-Resource-Set-IDPos INTEGER(0..7), + pRS-Resource-IDPos INTEGER(0..63), + iE-Extensions ProtocolExtensionContainer { { PRSInformationPos-ExtIEs} } OPTIONAL +} + +PRSInformationPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Potential-SpCell-Item ::= SEQUENCE { + potential-SpCell-ID NRCGI , + iE-Extensions ProtocolExtensionContainer { { Potential-SpCell-ItemExtIEs } } OPTIONAL, + ... +} + +Potential-SpCell-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +PRSAngleList ::= SEQUENCE (SIZE(1.. maxnoofPRS-ResourcesPerSet)) OF PRSAngleItem + +PRSAngleItem ::= SEQUENCE { + nR-PRS-Azimuth INTEGER (0..359), + nR-PRS-Azimuth-fine INTEGER (0..9), + nR-PRS-Elevation INTEGER (0..180), + nR-PRS-Elevation-fine INTEGER (0..9), + iE-Extensions ProtocolExtensionContainer { { PRSAngleItem-ItemExtIEs } } OPTIONAL +} + +PRSAngleItem-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSMuting::= SEQUENCE { + pRSMutingOption1 PRSMutingOption1, + pRSMutingOption2 PRSMutingOption2, + iE-Extensions ProtocolExtensionContainer { { PRSMuting-ExtIEs} } OPTIONAL +} + +PRSMuting-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSMutingOption1 ::= SEQUENCE { + mutingPattern DL-PRSMutingPattern, + mutingBitRepetitionFactor ENUMERATED{rf1,rf2,rf4,rf8,...}, + iE-Extensions ProtocolExtensionContainer { { PRSMutingOption1-ExtIEs} } OPTIONAL +} + +PRSMutingOption1-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSMutingOption2 ::= SEQUENCE { + mutingPattern DL-PRSMutingPattern, + iE-Extensions ProtocolExtensionContainer { { PRSMutingOption2-ExtIEs} } OPTIONAL +} + +PRSMutingOption2-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRS-Resource-ID ::= INTEGER (0..63) + +PRSResource-List::= SEQUENCE (SIZE (1..maxnoofPRSresources)) OF PRSResource-Item + +PRSResource-Item ::= SEQUENCE { + pRSResourceID INTEGER(0..63), + sequenceID INTEGER(0..4095,...), + rEOffset INTEGER(0..11), + resourceSlotOffset INTEGER(0..511,...), + resourceSymbolOffset INTEGER(0..12,...), + qCLInfo PRSResource-QCLInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PRSResource-Item-ExtIEs} } OPTIONAL +} + +PRSResource-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSResource-QCLInfo ::= SEQUENCE { + qCLSourceSSBIndex INTEGER(0..63) OPTIONAL, + qCLSourcePRSInfo PRSResource-QCLSourcePRSInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PRSResource-QCLInfo-ExtIEs} } OPTIONAL, + ... +} +PRSResource-QCLInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRSResource-QCLSourcePRSInfo ::= SEQUENCE { + qCLSourcePRSResourceSetID INTEGER(0..7), + qCLSourcePRSResourceID INTEGER(0..63) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { PRSResource-QCLSourcePRSInfo-ExtIEs} } OPTIONAL +} + +PRSResource-QCLSourcePRSInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PRS-Resource-Set-ID ::= INTEGER(0..7) + +PRSResourceSet-List ::= SEQUENCE (SIZE (1.. maxnoofPRSresourceSets)) OF PRSResourceSet-Item +PRSResourceSet-Item ::= SEQUENCE { + pRSResourceSetID PRS-Resource-Set-ID, + subcarrierSpacing ENUMERATED{kHz15, kHz30, kHz60, kHz120, ...}, + pRSbandwidth INTEGER(1..63), + startPRB INTEGER(0..2176), + pointA INTEGER (0..3279165), + combSize ENUMERATED{n2, n4, n6, n12, ...}, + cPType ENUMERATED{normal, extended, ...}, + resourceSetPeriodicity ENUMERATED{n4,n5,n8,n10,n16,n20,n32,n40,n64,n80,n160,n320,n640,n1280,n2560,n5120,n10240,n20480,n40960, n81920,...}, + resourceSetSlotOffset INTEGER(0..81919,...), + resourceRepetitionFactor ENUMERATED{rf1,rf2,rf4,rf6,rf8,rf16,rf32,...}, + resourceTimeGap ENUMERATED{tg1,tg2,tg4,tg8,tg16,tg32,...}, + resourceNumberofSymbols ENUMERATED{n2,n4,n6,n12,...}, + pRSMuting PRSMuting OPTIONAL, + pRSResourceTransmitPower INTEGER(-60..50), + pRSResource-List PRSResource-List, + iE-Extensions ProtocolExtensionContainer { { PRSResourceSet-Item-ExtIEs} } OPTIONAL +} + +PRSResourceSet-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PWS-Failed-NR-CGI-Item ::= SEQUENCE { + nRCGI NRCGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { { PWS-Failed-NR-CGI-ItemExtIEs } } OPTIONAL, + ... +} + +PWS-Failed-NR-CGI-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +PWSSystemInformation ::= SEQUENCE { + sIBtype SIBType-PWS, + sIBmessage OCTET STRING, + iE-Extensions ProtocolExtensionContainer { { PWSSystemInformationExtIEs } } OPTIONAL, + ... +} + +PWSSystemInformationExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-NotificationInformation CRITICALITY ignore EXTENSION NotificationInformation PRESENCE optional}| + { ID id-AdditionalSIBMessageList CRITICALITY reject EXTENSION AdditionalSIBMessageList PRESENCE optional}, + ... +} + +PrivacyIndicator ::= ENUMERATED {immediate-MDT, logged-MDT, ...} + +-- Q + +QCI ::= INTEGER (0..255) + +QoS-Characteristics ::= CHOICE { + non-Dynamic-5QI NonDynamic5QIDescriptor, + dynamic-5QI Dynamic5QIDescriptor, + choice-extension ProtocolIE-SingleContainer { { QoS-Characteristics-ExtIEs } } +} + +QoS-Characteristics-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +QoSFlowIdentifier ::= INTEGER (0..63) + +QoSFlowLevelQoSParameters ::= SEQUENCE { + qoS-Characteristics QoS-Characteristics, + nGRANallocationRetentionPriority NGRANAllocationAndRetentionPriority, + gBR-QoS-Flow-Information GBR-QoSFlowInformation OPTIONAL, + reflective-QoS-Attribute ENUMERATED {subject-to, ...} OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { QoSFlowLevelQoSParameters-ExtIEs } } OPTIONAL +} + +QoSFlowLevelQoSParameters-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-PDUSessionID CRITICALITY ignore EXTENSION PDUSessionID PRESENCE optional}| + { ID id-ULPDUSessionAggregateMaximumBitRate CRITICALITY ignore EXTENSION BitRate PRESENCE optional}| + { ID id-QosMonitoringRequest CRITICALITY ignore EXTENSION QosMonitoringRequest PRESENCE optional}, + ... +} + +QoSFlowMappingIndication ::= ENUMERATED {ul,dl,...} + +QoSInformation ::= CHOICE { + eUTRANQoS EUTRANQoS, + choice-extension ProtocolIE-SingleContainer { { QoSInformation-ExtIEs} } +} + +QoSInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRB-Information CRITICALITY ignore TYPE DRB-Information PRESENCE mandatory}, + ... +} + +QosMonitoringRequest ::= ENUMERATED {ul, dl, both, ...} + +QoSParaSetIndex ::= INTEGER (1..8, ...) + +QoSParaSetNotifyIndex ::= INTEGER (0..8, ...) + +-- R + +RACH-Config-Common ::= OCTET STRING + +RACH-Config-Common-IAB ::= OCTET STRING + +RACHReportContainer::= OCTET STRING + +RACHReportInformationList ::= SEQUENCE (SIZE(1.. maxnoofRACHReports)) OF RACHReportInformationItem + +RACHReportInformationItem ::= SEQUENCE { + rACHReportContainer RACHReportContainer, + uEAssitantIdentifier GNB-DU-UE-F1AP-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { RACHReportInformationItem-ExtIEs} } OPTIONAL, + ... +} + +RACHReportInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + + +RadioResourceStatus ::= SEQUENCE { + sSBAreaRadioResourceStatusList SSBAreaRadioResourceStatusList, + iE-Extensions ProtocolExtensionContainer { { RadioResourceStatus-ExtIEs} } OPTIONAL +} + +RadioResourceStatus-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RANAC ::= INTEGER (0..255) + +RAN-MeasurementID ::= INTEGER (1.. 65536, ...) + +RAN-UE-MeasurementID ::= INTEGER (1.. 256, ...) + +RANUEID ::= OCTET STRING (SIZE (8)) + +RANUEPagingIdentity ::= SEQUENCE { + iRNTI BIT STRING (SIZE(40)), + iE-Extensions ProtocolExtensionContainer { { RANUEPagingIdentity-ExtIEs } } OPTIONAL} + +RANUEPagingIdentity-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RAT-FrequencyPriorityInformation::= CHOICE { + eNDC SubscriberProfileIDforRFP, + nGRAN RAT-FrequencySelectionPriority, + choice-extension ProtocolIE-SingleContainer { { RAT-FrequencyPriorityInformation-ExtIEs} } +} + +RAT-FrequencyPriorityInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +RAT-FrequencySelectionPriority::= INTEGER (1.. 256, ...) + +Reestablishment-Indication ::= ENUMERATED { + reestablished, + ... +} + +ReferencePoint ::= CHOICE { + coordinateID CoordinateID, + referencePointCoordinate AccessPointPosition, + referencePointCoordinateHA NGRANHighAccuracyAccessPointPosition, + choice-Extension ProtocolIE-SingleContainer { { ReferencePoint-ExtIEs} } +} + +ReferencePoint-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +ReferenceSFN ::= INTEGER (0..1023) + +ReferenceSignal ::= CHOICE { + nZP-CSI-RS NZP-CSI-RS-ResourceID, + sSB SSB, + sRS SRSResourceID, + positioningSRS SRSPosResourceID, + dL-PRS DL-PRS, + choice-extension ProtocolIE-SingleContainer {{ReferenceSignal-ExtIEs }} +} + +ReferenceSignal-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +RelativeCartesianLocation ::= SEQUENCE { + xYZunit ENUMERATED {mm, cm, dm, ...}, + xvalue INTEGER (-65536..65535), + yvalue INTEGER (-65536..65535), + zvalue INTEGER (-32768..32767), + locationUncertainty LocationUncertainty, + iE-Extensions ProtocolExtensionContainer { { RelativeCartesianLocation-ExtIEs} } OPTIONAL +} + +RelativeCartesianLocation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RelativeGeodeticLocation ::= SEQUENCE { + milli-Arc-SecondUnits ENUMERATED {zerodot03, zerodot3, three, ...}, + heightUnits ENUMERATED {mm, cm, m, ...}, + deltaLatitude INTEGER (-1024.. 1023), + deltaLongitude INTEGER (-1024.. 1023), + deltaHeight INTEGER (-1024.. 1023), + locationUncertainty LocationUncertainty, + iE-extensions ProtocolExtensionContainer {{RelativeGeodeticLocation-ExtIEs }} OPTIONAL +} + +RelativeGeodeticLocation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ReferenceTime ::= OCTET STRING + +RegistrationRequest ::= ENUMERATED{start, stop, add, ...} + +ReportCharacteristics ::= BIT STRING (SIZE(32)) + +ReportingPeriodicity ::= ENUMERATED{ms500, ms1000, ms2000, ms5000, ms10000, ...} + +RequestedBandCombinationIndex ::= OCTET STRING + +RequestedFeatureSetEntryIndex ::= OCTET STRING + +RequestedP-MaxFR2 ::= OCTET STRING + +Requested-PDCCH-BlindDetectionSCG ::= OCTET STRING + + +RequestedSRSTransmissionCharacteristics ::= SEQUENCE { + numberOfTransmissions INTEGER (0..500, ...) OPTIONAL, + resourceType ENUMERATED {periodic, semi-persistent, aperiodic,...}, + bandwidthSRS BandwidthSRS, + sRSResourceSetList SRSResourceSetList OPTIONAL, + sSBInformation SSBInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { RequestedSRSTransmissionCharacteristics-ExtIEs} } OPTIONAL +} + +RequestedSRSTransmissionCharacteristics-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RequestType ::= ENUMERATED {offer, execution, ...} + +ResourceCoordinationEUTRACellInfo ::= SEQUENCE { + eUTRA-Mode-Info EUTRA-Coex-Mode-Info, + eUTRA-PRACH-Configuration EUTRA-PRACH-Configuration, + iE-Extensions ProtocolExtensionContainer { { ResourceCoordinationEUTRACellInfo-ExtIEs } } OPTIONAL, + ... +} + +ResourceCoordinationEUTRACellInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-IgnorePRACHConfiguration CRITICALITY reject EXTENSION IgnorePRACHConfiguration PRESENCE optional }, + ... +} + +ResourceCoordinationTransferInformation ::= SEQUENCE { + meNB-Cell-ID EUTRA-Cell-ID, + resourceCoordinationEUTRACellInfo ResourceCoordinationEUTRACellInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { ResourceCoordinationTransferInformation-ExtIEs } } OPTIONAL, + ... +} + +ResourceCoordinationTransferInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceCoordinationTransferContainer ::= OCTET STRING + +ResourceSetType ::= CHOICE { + periodic ResourceSetTypePeriodic, + semi-persistent ResourceSetTypeSemi-persistent, + aperiodic ResourceSetTypeAperiodic, + choice-extension ProtocolIE-SingleContainer {{ ResourceSetType-ExtIEs }} +} + +ResourceSetType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +ResourceSetTypePeriodic ::= SEQUENCE { + periodicSet ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { ResourceSetTypePeriodic-ExtIEs} } OPTIONAL +} + +ResourceSetTypePeriodic-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceSetTypeSemi-persistent ::= SEQUENCE { + semi-persistentSet ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { ResourceSetTypeSemi-persistent-ExtIEs} } OPTIONAL +} + +ResourceSetTypeSemi-persistent-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceSetTypeAperiodic ::= SEQUENCE { + sRSResourceTrigger-List INTEGER(1..3), + slotoffset INTEGER(1..32), + iE-Extensions ProtocolExtensionContainer { { ResourceSetTypeAperiodic-ExtIEs} } OPTIONAL +} + +ResourceSetTypeAperiodic-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RepetitionPeriod ::= INTEGER (0..131071, ...) + +ReportingRequestType ::= SEQUENCE { + eventType EventType, + reportingPeriodicityValue ReportingPeriodicityValue OPTIONAL, + -- C-ifEventTypeisPeriodic: This IE shall be present if the Event Type IE is set to "periodic" in the Event Type IE. + iE-Extensions ProtocolExtensionContainer { {ReportingRequestType-ExtIEs} } OPTIONAL +} + +ReportingRequestType-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceType ::= CHOICE { + periodic ResourceTypePeriodic, + semi-persistent ResourceTypeSemi-persistent, + aperiodic ResourceTypeAperiodic, + choice-extension ProtocolIE-SingleContainer {{ ResourceType-ExtIEs }} +} + +ResourceType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +ResourceTypePeriodic ::= SEQUENCE { + periodicity ENUMERATED{slot1, slot2, slot4, slot5, slot8, slot10, slot16, slot20, slot32, slot40, slot64, slot80, slot160, slot320, slot640, slot1280, slot2560, ...}, + offset INTEGER(0..2559, ...), + iE-Extensions ProtocolExtensionContainer { { ResourceTypePeriodic-ExtIEs} } OPTIONAL +} + +ResourceTypePeriodic-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypeSemi-persistent ::= SEQUENCE { + periodicity ENUMERATED{slot1, slot2, slot4, slot5, slot8, slot10, slot16, slot20, slot32, slot40, slot64, slot80, slot160, slot320, slot640, slot1280, slot2560, ...}, + offset INTEGER(0..2559, ...), + iE-Extensions ProtocolExtensionContainer { { ResourceTypeSemi-persistent-ExtIEs} } OPTIONAL +} + +ResourceTypeSemi-persistent-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypeAperiodic ::= SEQUENCE { + aperiodicResourceType ENUMERATED{true, ...}, + iE-Extensions ProtocolExtensionContainer { { ResourceTypeAperiodic-ExtIEs} } OPTIONAL +} + +ResourceTypeAperiodic-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypePos ::= CHOICE { + periodic ResourceTypePeriodicPos, + semi-persistent ResourceTypeSemi-persistentPos, + aperiodic ResourceTypeAperiodicPos, + choice-extension ProtocolIE-SingleContainer {{ ResourceTypePos-ExtIEs }} +} + +ResourceTypePos-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +ResourceTypePeriodicPos ::= SEQUENCE { + periodicity ENUMERATED{slot1, slot2, slot4, slot5, slot8, slot10, slot16, slot20, slot32, slot40, slot64, slot80, slot160, slot320, slot640, slot1280, slot2560, slot5120, slot10240, slot20480, slot40960, slot81920, ...}, + offset INTEGER(0..81919, ...), + iE-Extensions ProtocolExtensionContainer { { ResourceTypePeriodicPos-ExtIEs} } OPTIONAL +} + +ResourceTypePeriodicPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypeSemi-persistentPos ::= SEQUENCE { + periodicity ENUMERATED{slot1, slot2, slot4, slot5, slot8, slot10, slot16, slot20, slot32, slot40, slot64, slot80, slot160, slot320, slot640, slot1280, slot2560, slot5120, slot10240, slot20480, slot40960, slot81920, ...}, + offset INTEGER(0..81919, ...), + iE-Extensions ProtocolExtensionContainer { { ResourceTypeSemi-persistentPos-ExtIEs} } OPTIONAL +} + +ResourceTypeSemi-persistentPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ResourceTypeAperiodicPos ::= SEQUENCE { + slotOffset INTEGER (1..32), + iE-Extensions ProtocolExtensionContainer { { ResourceTypeAperiodicPos-ExtIEs} } OPTIONAL +} + +ResourceTypeAperiodicPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLCDuplicationInformation ::= SEQUENCE { + rLCDuplicationStateList RLCDuplicationStateList, + primaryPathIndication PrimaryPathIndication OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {RLCDuplicationInformation-ExtIEs} } OPTIONAL +} + +RLCDuplicationInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLCDuplicationStateList ::= SEQUENCE (SIZE(1..maxnoofRLCDuplicationState)) OF RLCDuplicationState-Item + +RLCDuplicationState-Item ::=SEQUENCE { + duplicationState DuplicationState, + iE-Extensions ProtocolExtensionContainer { {RLCDuplicationState-Item-ExtIEs } } OPTIONAL, + ... +} + + +RLCDuplicationState-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLCFailureIndication ::= SEQUENCE { + assocatedLCID LCID, + iE-Extensions ProtocolExtensionContainer { {RLCFailureIndication-ExtIEs} } OPTIONAL +} + +RLCFailureIndication-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLCMode ::= ENUMERATED { + rlc-am, + rlc-um-bidirectional, + rlc-um-unidirectional-ul, + rlc-um-unidirectional-dl, + ... +} + +RLC-Status ::= SEQUENCE { + reestablishment-Indication Reestablishment-Indication, + iE-Extensions ProtocolExtensionContainer { { RLC-Status-ExtIEs } } OPTIONAL, + ... +} + +RLC-Status-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RLFReportInformationList ::= SEQUENCE (SIZE(1.. maxnoofRLFReports)) OF RLFReportInformationItem + +RLFReportInformationItem ::= SEQUENCE { + nRUERLFReportContainer NRUERLFReportContainer, + uEAssitantIdentifier GNB-DU-UE-F1AP-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { RLFReportInformationItem-ExtIEs} } OPTIONAL, + ... +} + +RLFReportInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +RIMRSDetectionStatus ::= ENUMERATED {rs-detected, rs-disappeared, ...} + +RRCContainer ::= OCTET STRING + +RRCContainer-RRCSetupComplete ::= OCTET STRING + +RRCDeliveryStatus ::= SEQUENCE { + delivery-status PDCP-SN, + triggering-message PDCP-SN, + iE-Extensions ProtocolExtensionContainer { { RRCDeliveryStatus-ExtIEs } } OPTIONAL} + +RRCDeliveryStatus-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +RRCDeliveryStatusRequest ::= ENUMERATED {true, ...} + +RRCReconfigurationCompleteIndicator ::= ENUMERATED { + true, + ..., + failure +} + +RRC-Version ::= SEQUENCE { + latest-RRC-Version BIT STRING (SIZE(3)), + iE-Extensions ProtocolExtensionContainer { { RRC-Version-ExtIEs } } OPTIONAL} + +RRC-Version-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-latest-RRC-Version-Enhanced CRITICALITY ignore EXTENSION OCTET STRING (SIZE(3)) PRESENCE optional }, + ... +} + +RoutingID ::= OCTET STRING + +-- S + +SCell-FailedtoSetup-Item ::= SEQUENCE { + sCell-ID NRCGI , + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { SCell-FailedtoSetup-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-FailedtoSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SCell-FailedtoSetupMod-Item ::= SEQUENCE { + sCell-ID NRCGI , + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { SCell-FailedtoSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-FailedtoSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SCell-ToBeRemoved-Item ::= SEQUENCE { + sCell-ID NRCGI , + iE-Extensions ProtocolExtensionContainer { { SCell-ToBeRemoved-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-ToBeRemoved-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SCell-ToBeSetup-Item ::= SEQUENCE { + sCell-ID NRCGI , + sCellIndex SCellIndex, + sCellULConfigured CellULConfigured OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SCell-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ServingCellMO CRITICALITY ignore EXTENSION ServingCellMO PRESENCE optional }, + ... +} + +SCell-ToBeSetupMod-Item ::= SEQUENCE { + sCell-ID NRCGI , + sCellIndex SCellIndex, + sCellULConfigured CellULConfigured OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SCell-ToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SCell-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-ServingCellMO CRITICALITY ignore EXTENSION ServingCellMO PRESENCE optional }, + ... +} + +SCellIndex ::=INTEGER (1..31, ...) + +SCS-SpecificCarrier ::= SEQUENCE { + offsetToCarrier INTEGER (0..2199,...), + subcarrierSpacing ENUMERATED {kHz15, kHz30, kHz60, kHz120,...}, + carrierBandwidth INTEGER (0..275,...), + iE-Extensions ProtocolExtensionContainer { { SCS-SpecificCarrier-ExtIEs } } OPTIONAL +} + +SCS-SpecificCarrier-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Search-window-information ::= SEQUENCE { + expectedPropagationDelay INTEGER (-3841..3841,...), + delayUncertainty INTEGER (1..246,...), + iE-Extensions ProtocolExtensionContainer { { Search-window-information-ExtIEs } } OPTIONAL +} + +Search-window-information-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SerialNumber ::= BIT STRING (SIZE (16)) + +SIBType-PWS ::=INTEGER (6..8, ...) + +SelectedBandCombinationIndex ::= OCTET STRING + +SelectedFeatureSetEntryIndex ::= OCTET STRING + +CG-ConfigInfo ::= OCTET STRING + +ServCellIndex ::= INTEGER (0..31, ...) + +ServingCellMO ::= INTEGER (1..64, ...) + +Served-Cell-Information ::= SEQUENCE { + nRCGI NRCGI, + nRPCI NRPCI, + fiveGS-TAC FiveGS-TAC OPTIONAL, + configured-EPS-TAC Configured-EPS-TAC OPTIONAL, + servedPLMNs ServedPLMNs-List, + nR-Mode-Info NR-Mode-Info, + measurementTimingConfiguration OCTET STRING, + iE-Extensions ProtocolExtensionContainer { {Served-Cell-Information-ExtIEs} } OPTIONAL, + ... +} + +Served-Cell-Information-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-RANAC CRITICALITY ignore EXTENSION RANAC PRESENCE optional }| + { ID id-ExtendedServedPLMNs-List CRITICALITY ignore EXTENSION ExtendedServedPLMNs-List PRESENCE optional }| + { ID id-Cell-Direction CRITICALITY ignore EXTENSION Cell-Direction PRESENCE optional }| + { ID id-BPLMN-ID-Info-List CRITICALITY ignore EXTENSION BPLMN-ID-Info-List PRESENCE optional }| + { ID id-Cell-Type CRITICALITY ignore EXTENSION CellType PRESENCE optional}| + { ID id-ConfiguredTACIndication CRITICALITY ignore EXTENSION ConfiguredTACIndication PRESENCE optional }| + { ID id-AggressorgNBSetID CRITICALITY ignore EXTENSION AggressorgNBSetID PRESENCE optional}| + { ID id-VictimgNBSetID CRITICALITY ignore EXTENSION VictimgNBSetID PRESENCE optional}| + { ID id-IAB-Info-IAB-DU CRITICALITY ignore EXTENSION IAB-Info-IAB-DU PRESENCE optional}| + { ID id-SSB-PositionsInBurst CRITICALITY ignore EXTENSION SSB-PositionsInBurst PRESENCE optional }| + { ID id-NRPRACHConfig CRITICALITY ignore EXTENSION NRPRACHConfig PRESENCE optional }, + ... +} + +Served-Cells-To-Add-Item ::= SEQUENCE { + served-Cell-Information Served-Cell-Information, + gNB-DU-System-Information GNB-DU-System-Information OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Served-Cells-To-Add-ItemExtIEs} } OPTIONAL, + ... +} + +Served-Cells-To-Add-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Served-Cells-To-Delete-Item ::= SEQUENCE { + oldNRCGI NRCGI , + iE-Extensions ProtocolExtensionContainer { { Served-Cells-To-Delete-ItemExtIEs } } OPTIONAL, + ... +} + +Served-Cells-To-Delete-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Served-Cells-To-Modify-Item ::= SEQUENCE { + oldNRCGI NRCGI , + served-Cell-Information Served-Cell-Information , + gNB-DU-System-Information GNB-DU-System-Information OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { Served-Cells-To-Modify-ItemExtIEs } } OPTIONAL, + ... +} + +Served-Cells-To-Modify-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Served-EUTRA-Cells-Information::= SEQUENCE { + eUTRA-Mode-Info EUTRA-Mode-Info, + protectedEUTRAResourceIndication ProtectedEUTRAResourceIndication, + iE-Extensions ProtocolExtensionContainer { {Served-EUTRA-Cell-Information-ExtIEs} } OPTIONAL, + ... +} + +Served-EUTRA-Cell-Information-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Service-State ::= ENUMERATED { + in-service, + out-of-service, + ... +} + +Service-Status ::= SEQUENCE { + service-state Service-State, + switchingOffOngoing ENUMERATED {true, ...} OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Service-Status-ExtIEs } } OPTIONAL, + ... +} + +Service-Status-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +SFNInitialisationTime ::= BIT STRING (SIZE (64)) + +ShortDRXCycleLength ::= ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, ...} + +ShortDRXCycleTimer ::= INTEGER (1..16) + +SIB1-message ::= OCTET STRING + +SIB10-message ::= OCTET STRING + +SIB12-message ::= OCTET STRING + +SIB13-message ::= OCTET STRING + +SIB14-message ::= OCTET STRING + +SItype ::= INTEGER (1..32, ...) + +SItype-List ::= SEQUENCE (SIZE(1.. maxnoofSITypes)) OF SItype-Item + +SItype-Item ::= SEQUENCE { + sItype SItype , + iE-Extensions ProtocolExtensionContainer { { SItype-ItemExtIEs } } OPTIONAL +} + +SItype-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SibtypetobeupdatedListItem ::= SEQUENCE { + sIBtype INTEGER (2..32,...), + sIBmessage OCTET STRING, + valueTag INTEGER (0..31,...), + iE-Extensions ProtocolExtensionContainer { { SibtypetobeupdatedListItem-ExtIEs } } OPTIONAL, + ... +} + +SibtypetobeupdatedListItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-areaScope CRITICALITY ignore EXTENSION AreaScope PRESENCE optional}, + ... +} + +SLDRBID ::= INTEGER (1..512, ...) + +SLDRBInformation ::= SEQUENCE { + sLDRB-QoS PC5QoSParameters, + flowsMappedToSLDRB-List FlowsMappedToSLDRB-List, + ... +} + +SLDRBs-FailedToBeModified-Item ::= SEQUENCE { + sLDRBID SLDRBID , + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-FailedToBeModified-ItemExtIEs } } OPTIONAL +} + +SLDRBs-FailedToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-FailedToBeSetup-Item ::= SEQUENCE { + sLDRBID SLDRBID, + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-FailedToBeSetup-ItemExtIEs } } OPTIONAL +} + +SLDRBs-FailedToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-FailedToBeSetupMod-Item ::= SEQUENCE { + sLDRBID SLDRBID , + cause Cause OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { SLDRBs-FailedToBeSetupMod-ItemExtIEs } } OPTIONAL +} + +SLDRBs-FailedToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-Modified-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-Modified-ItemExtIEs } } OPTIONAL +} + +SLDRBs-Modified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ModifiedConf-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ModifiedConf-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ModifiedConf-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-Required-ToBeModified-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-Required-ToBeModified-ItemExtIEs } } OPTIONAL +} + +SLDRBs-Required-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-Required-ToBeReleased-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-Required-ToBeReleased-ItemExtIEs } } OPTIONAL +} + +SLDRBs-Required-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-Setup-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-Setup-ItemExtIEs } } OPTIONAL +} + +SLDRBs-Setup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-SetupMod-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-SetupMod-ItemExtIEs } } OPTIONAL +} + +SLDRBs-SetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ToBeModified-Item ::= SEQUENCE { + sLDRBID SLDRBID, + sLDRBInformation SLDRBInformation OPTIONAL, + rLCMode RLCMode OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ToBeModified-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ToBeModified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ToBeReleased-Item ::= SEQUENCE { + sLDRBID SLDRBID, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ToBeReleased-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ToBeSetup-Item ::= SEQUENCE { + sLDRBID SLDRBID, + sLDRBInformation SLDRBInformation, + rLCMode RLCMode, + + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ToBeSetup-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SLDRBs-ToBeSetupMod-Item ::= SEQUENCE { + sLDRBID SLDRBID, + sLDRBInformation SLDRBInformation, + rLCMode RLCMode OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SLDRBs-ToBeSetupMod-ItemExtIEs } } OPTIONAL +} + +SLDRBs-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SL-PHY-MAC-RLC-Config ::= OCTET STRING + +SL-ConfigDedicatedEUTRA ::= OCTET STRING + +SliceAvailableCapacity ::= SEQUENCE { + sliceAvailableCapacityList SliceAvailableCapacityList, + iE-Extensions ProtocolExtensionContainer { { SliceAvailableCapacity-ExtIEs} } OPTIONAL +} + +SliceAvailableCapacity-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SliceAvailableCapacityList ::= SEQUENCE (SIZE(1.. maxnoofBPLMNsNR)) OF SliceAvailableCapacityItem + +SliceAvailableCapacityItem ::= SEQUENCE { + pLMNIdentity PLMN-Identity, + sNSSAIAvailableCapacity-List SNSSAIAvailableCapacity-List, + iE-Extensions ProtocolExtensionContainer { { SliceAvailableCapacityItem-ExtIEs} } OPTIONAL +} + +SliceAvailableCapacityItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SNSSAIAvailableCapacity-List ::= SEQUENCE (SIZE(1.. maxnoofSliceItems)) OF SNSSAIAvailableCapacity-Item + +SNSSAIAvailableCapacity-Item ::= SEQUENCE { + sNSSAI SNSSAI, + sliceAvailableCapacityValueDownlink INTEGER (0..100) OPTIONAL, + sliceAvailableCapacityValueUplink INTEGER (0..100) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SNSSAIAvailableCapacity-Item-ExtIEs } } OPTIONAL +} + +SNSSAIAvailableCapacity-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SliceSupportList ::= SEQUENCE (SIZE(1.. maxnoofSliceItems)) OF SliceSupportItem + +SliceSupportItem ::= SEQUENCE { + sNSSAI SNSSAI, + iE-Extensions ProtocolExtensionContainer { { SliceSupportItem-ExtIEs } } OPTIONAL +} + +SliceSupportItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SliceToReportList ::= SEQUENCE (SIZE(1.. maxnoofBPLMNsNR)) OF SliceToReportItem + +SliceToReportItem ::= SEQUENCE { + pLMNIdentity PLMN-Identity, + sNSSAIlist SNSSAI-list, + iE-Extensions ProtocolExtensionContainer { { SliceToReportItem-ExtIEs} } OPTIONAL +} + +SliceToReportItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SlotNumber ::= INTEGER (0..79) + +SNSSAI-list ::= SEQUENCE (SIZE(1.. maxnoofSliceItems)) OF SNSSAI-Item + +SNSSAI-Item ::= SEQUENCE { + sNSSAI SNSSAI, + iE-Extensions ProtocolExtensionContainer { { SNSSAI-Item-ExtIEs } } OPTIONAL +} + +SNSSAI-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Slot-Configuration-List ::= SEQUENCE (SIZE(1.. maxnoofslots)) OF Slot-Configuration-Item + +Slot-Configuration-Item ::= SEQUENCE { + slotIndex INTEGER (0..5119, ...), + symbolAllocInSlot SymbolAllocInSlot, + iE-Extensions ProtocolExtensionContainer { { Slot-Configuration-ItemExtIEs } } OPTIONAL +} + +Slot-Configuration-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +SNSSAI ::= SEQUENCE { + sST OCTET STRING (SIZE(1)), + sD OCTET STRING (SIZE(3)) OPTIONAL , + iE-Extensions ProtocolExtensionContainer { { SNSSAI-ExtIEs } } OPTIONAL +} + +SNSSAI-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SpatialDirectionInformation ::= SEQUENCE { + nR-PRSBeamInformation NR-PRSBeamInformation, + iE-Extensions ProtocolExtensionContainer { { SpatialDirectionInformation-ExtIEs } } OPTIONAL +} + +SpatialDirectionInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SpatialRelationInfo ::= SEQUENCE { + spatialRelationforResourceID SpatialRelationforResourceID, + iE-Extensions ProtocolExtensionContainer { {SpatialRelationInfo-ExtIEs} } OPTIONAL +} + +SpatialRelationInfo-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SpatialRelationforResourceID ::= SEQUENCE (SIZE(1..maxnoofSpatialRelations)) OF SpatialRelationforResourceIDItem + +SpatialRelationforResourceIDItem ::= SEQUENCE { + referenceSignal ReferenceSignal, + iE-Extensions ProtocolExtensionContainer { {SpatialRelationforResourceIDItem-ExtIEs} } OPTIONAL +} + +SpatialRelationforResourceIDItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SpatialRelationPos ::= CHOICE { + sSBPos SSBPos, + pRSInformationPos PRSInformationPos, + choice-extension ProtocolIE-SingleContainer {{ SpatialInformationPos-ExtIEs }} +} + +SpatialInformationPos-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SpectrumSharingGroupID ::= INTEGER (1..maxCellineNB) + +SRBID ::= INTEGER (0..3, ...) + +SRBs-FailedToBeSetup-Item ::= SEQUENCE { + sRBID SRBID , + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRBs-FailedToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-FailedToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-FailedToBeSetupMod-Item ::= SEQUENCE { + sRBID SRBID , + cause Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRBs-FailedToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-FailedToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-Modified-Item ::= SEQUENCE { + sRBID SRBID, + lCID LCID, + iE-Extensions ProtocolExtensionContainer { { SRBs-Modified-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-Modified-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-Required-ToBeReleased-Item ::= SEQUENCE { + sRBID SRBID, + iE-Extensions ProtocolExtensionContainer { { SRBs-Required-ToBeReleased-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-Required-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-Setup-Item ::= SEQUENCE { + sRBID SRBID, + lCID LCID, + iE-Extensions ProtocolExtensionContainer { { SRBs-Setup-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-Setup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-SetupMod-Item ::= SEQUENCE { + sRBID SRBID, + lCID LCID, + iE-Extensions ProtocolExtensionContainer { { SRBs-SetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-SetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-ToBeReleased-Item ::= SEQUENCE { + sRBID SRBID, + iE-Extensions ProtocolExtensionContainer { { SRBs-ToBeReleased-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-ToBeReleased-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRBs-ToBeSetup-Item ::= SEQUENCE { + sRBID SRBID , + duplicationIndication DuplicationIndication OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRBs-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalDuplicationIndication CRITICALITY ignore EXTENSION AdditionalDuplicationIndication PRESENCE optional }, + ... +} + +SRBs-ToBeSetupMod-Item ::= SEQUENCE { + sRBID SRBID, + duplicationIndication DuplicationIndication OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRBs-ToBeSetupMod-ItemExtIEs } } OPTIONAL, + ... +} + +SRBs-ToBeSetupMod-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalDuplicationIndication CRITICALITY ignore EXTENSION AdditionalDuplicationIndication PRESENCE optional }, + ... +} + +SRSCarrier-List ::= SEQUENCE (SIZE(1.. maxnoSRS-Carriers)) OF SRSCarrier-List-Item + +SRSCarrier-List-Item ::= SEQUENCE { + pointA INTEGER (0..3279165,...), + uplinkChannelBW-PerSCS-List UplinkChannelBW-PerSCS-List, + activeULBWP ActiveULBWP, + pci NRPCI, + iE-Extensions ProtocolExtensionContainer { { SRSCarrier-List-Item-ExtIEs } } OPTIONAL +} + +SRSCarrier-List-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSConfig ::= SEQUENCE { + sRSResource-List SRSResource-List OPTIONAL, + posSRSResource-List PosSRSResource-List OPTIONAL, + sRSResourceSet-List SRSResourceSet-List OPTIONAL, + posSRSResourceSet-List PosSRSResourceSet-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRSConfig-ExtIEs } } OPTIONAL +} + +SRSConfig-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSConfiguration ::= SEQUENCE { + sRSCarrier-List SRSCarrier-List, + iE-Extensions ProtocolExtensionContainer { { SRSConfiguration-ExtIEs } } OPTIONAL +} + +SRSConfiguration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSPosResourceID ::= INTEGER (0..63, ...) + +SRSResource::= SEQUENCE { + sRSResourceID SRSResourceID, + nrofSRS-Ports ENUMERATED {port1, ports2, ports4}, + transmissionComb TransmissionComb, + startPosition INTEGER (0..13), + nrofSymbols ENUMERATED {n1, n2, n4}, + repetitionFactor ENUMERATED {n1, n2, n4}, + freqDomainPosition INTEGER (0..67), + freqDomainShift INTEGER (0..268), + c-SRS INTEGER (0..63), + b-SRS INTEGER (0..3), + b-hop INTEGER (0..3), + groupOrSequenceHopping ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceType ResourceType, + slotOffset INTEGER (0..2559), + sequenceId INTEGER (0..1023), + iE-Extensions ProtocolExtensionContainer { { SRSResource-ExtIEs } } OPTIONAL +} + +SRSResource-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSResourceID ::= INTEGER (0..63, ...) + +SRSResourceID-List::= SEQUENCE (SIZE (1..maxnoSRS-ResourcePerSet)) OF SRSResourceID + +SRSResource-List ::= SEQUENCE (SIZE (1..maxnoSRS-Resources)) OF SRSResource + +SRSResourceSet::= SEQUENCE { + sRSResourceSetID SRSResourceSetID, + sRSResourceID-List SRSResourceID-List, + resourceSetType ResourceSetType, + iE-Extensions ProtocolExtensionContainer { { SRSResourceSet-ExtIEs } } OPTIONAL +} + +SRSResourceSet-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSResourceSetID ::= INTEGER (0..15, ...) + +SRSResourceSetList ::= SEQUENCE (SIZE(1.. maxnoSRS-ResourceSets)) OF SRSResourceSetItem + +SRSResourceSetItem ::= SEQUENCE { + numSRSresourcesperset INTEGER (1..16, ...) OPTIONAL, + periodicityList PeriodicityList OPTIONAL, + spatialRelationInfo SpatialRelationInfo OPTIONAL, + pathlossReferenceInfo PathlossReferenceInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SRSResourceSetItemExtIEs } } OPTIONAL +} + +SRSResourceSetItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSResourceSet-List ::= SEQUENCE (SIZE (1..maxnoSRS-ResourceSets)) OF SRSResourceSet + +SRSResourceTrigger ::= SEQUENCE { + aperiodicSRSResourceTriggerList AperiodicSRSResourceTriggerList, + iE-Extensions ProtocolExtensionContainer { {SRSResourceTrigger-ExtIEs} } OPTIONAL +} + +SRSResourceTrigger-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SRSSpatialRelation ::= SEQUENCE { + spatialRelationforResourceID SpatialRelationforResourceID, + iE-Extensions ProtocolExtensionContainer { {SRSSpatialRelation-ExtIEs} } OPTIONAL +} + +SRSSpatialRelation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSB ::= SEQUENCE { + pCI-NR NRPCI, + ssb-index SSB-Index OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {SSB-ExtIEs} } OPTIONAL +} + +SSB-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSB-freqInfo ::= INTEGER (0..maxNRARFCN) + +SSB-Index ::= INTEGER(0..63) + +SSBPos ::= SEQUENCE { + pCI-NR NRPCI OPTIONAL, + ssb-index SSB-Index, + iE-Extensions ProtocolExtensionContainer { {SSBPos-ExtIEs} } OPTIONAL +} + +SSBPos-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSB-subcarrierSpacing ::= ENUMERATED {kHz15, kHz30, kHz120, kHz240, spare3, spare2, spare1, ...} + +SSB-transmissionPeriodicity ::= ENUMERATED {sf10, sf20, sf40, sf80, sf160, sf320, sf640, ...} + +SSB-transmissionTimingOffset ::= INTEGER (0..127, ...) + +SSB-transmissionBitmap ::= CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)), + choice-extension ProtocolIE-SingleContainer { { SSB-transmisisonBitmap-ExtIEs} } +} + +SSB-transmisisonBitmap-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SSBAreaCapacityValueList ::= SEQUENCE (SIZE(1.. maxnoofSSBAreas)) OF SSBAreaCapacityValueItem + +SSBAreaCapacityValueItem ::= SEQUENCE { + sSBIndex INTEGER(0..63), + sSBAreaCapacityValue INTEGER (0..100), + iE-Extensions ProtocolExtensionContainer { { SSBAreaCapacityValueItem-ExtIEs} } OPTIONAL +} + +SSBAreaCapacityValueItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSBAreaRadioResourceStatusList::= SEQUENCE (SIZE(1.. maxnoofSSBAreas)) OF SSBAreaRadioResourceStatusItem + +SSBAreaRadioResourceStatusItem::= SEQUENCE { + sSBIndex INTEGER(0..63), + sSBAreaDLGBRPRBusage INTEGER (0..100), + sSBAreaULGBRPRBusage INTEGER (0..100), + sSBAreaDLnon-GBRPRBusage INTEGER (0..100), + sSBAreaULnon-GBRPRBusage INTEGER (0..100), + sSBAreaDLTotalPRBusage INTEGER (0..100), + sSBAreaULTotalPRBusage INTEGER (0..100), + dLschedulingPDCCHCCEusage INTEGER (0..100) OPTIONAL, + uLschedulingPDCCHCCEusage INTEGER (0..100) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SSBAreaRadioResourceStatusItem-ExtIEs} } OPTIONAL +} + +SSBAreaRadioResourceStatusItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSBInformation ::= SEQUENCE { + sSBInformationList SSBInformationList, + iE-Extensions ProtocolExtensionContainer { { SSBInformation-ExtIEs } } OPTIONAL +} + +SSBInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSBInformationList ::= SEQUENCE (SIZE(1.. maxnoofSSBs)) OF SSBInformationItem + +SSBInformationItem ::= SEQUENCE { + sSB-Configuration SSB-TF-Configuration, + pCI-NR NRPCI, + iE-Extensions ProtocolExtensionContainer { { SSBInformationItem-ExtIEs } } OPTIONAL +} + +SSBInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SSB-PositionsInBurst ::= CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)), + choice-extension ProtocolIE-SingleContainer { {SSB-PositionsInBurst-ExtIEs} } +} + +SSB-PositionsInBurst-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SSB-TF-Configuration ::= SEQUENCE { + sSB-frequency INTEGER (0..3279165), + sSB-subcarrier-spacing ENUMERATED {kHz15, kHz30, kHz60, kHz120, kHz240, ...}, + sSB-Transmit-power INTEGER (-60..50), + sSB-periodicity ENUMERATED {ms5, ms10, ms20, ms40, ms80, ms160, ...}, + sSB-half-frame-offset INTEGER(0..1), + sSB-SFN-offset INTEGER(0..15), + sSB-position-in-burst SSB-PositionsInBurst OPTIONAL, + sFNInitialisationTime SFNInitialisationTime OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { SSB-TF-Configuration-ExtIEs} } OPTIONAL +} + +SSB-TF-Configuration-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +SSBToReportList ::= SEQUENCE (SIZE(1.. maxnoofSSBAreas)) OF SSBToReportItem + +SSBToReportItem ::= SEQUENCE { + sSBIndex INTEGER(0..63), + iE-Extensions ProtocolExtensionContainer { { SSBToReportItem-ExtIEs} } OPTIONAL +} + +SSBToReportItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SUL-Information ::= SEQUENCE { + sUL-NRARFCN INTEGER (0..maxNRARFCN), + sUL-transmission-Bandwidth Transmission-Bandwidth, + iE-Extensions ProtocolExtensionContainer { { SUL-InformationExtIEs} } OPTIONAL, + ... +} + +SUL-InformationExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-CarrierList CRITICALITY ignore EXTENSION NRCarrierList PRESENCE optional }| + { ID id-FrequencyShift7p5khz CRITICALITY ignore EXTENSION FrequencyShift7p5khz PRESENCE optional }, + ... +} + +SubcarrierSpacing ::= ENUMERATED { kHz15, kHz30, kHz60, kHz120, kHz240, spare3, spare2, spare1, ...} + +SubscriberProfileIDforRFP ::= INTEGER (1..256, ...) + +SULAccessIndication ::= ENUMERATED {true,...} + + +SupportedSULFreqBandItem ::= SEQUENCE { + freqBandIndicatorNr INTEGER (1..1024,...), + iE-Extensions ProtocolExtensionContainer { { SupportedSULFreqBandItem-ExtIEs} } OPTIONAL, + ... +} + +SupportedSULFreqBandItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +SymbolAllocInSlot ::= CHOICE { + all-DL NULL, + all-UL NULL, + both-DL-and-UL NumDLULSymbols, + choice-extension ProtocolIE-SingleContainer { { SymbolAllocInSlot-ExtIEs } } +} + +SymbolAllocInSlot-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SystemFrameNumber ::= INTEGER (0..1023) + +SystemInformationAreaID ::=BIT STRING (SIZE (24)) + +-- T + +FiveGS-TAC ::= OCTET STRING (SIZE(3)) + +Configured-EPS-TAC ::= OCTET STRING (SIZE(2)) + +TargetCellList ::= SEQUENCE (SIZE(1..maxnoofCHOcells)) OF TargetCellList-Item + +TargetCellList-Item ::= SEQUENCE { + target-cell NRCGI, + iE-Extensions ProtocolExtensionContainer { { TargetCellList-Item-ExtIEs} } OPTIONAL +} + +TargetCellList-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TDD-Info ::= SEQUENCE { + nRFreqInfo NRFreqInfo, + transmission-Bandwidth Transmission-Bandwidth, + iE-Extensions ProtocolExtensionContainer { {TDD-Info-ExtIEs} } OPTIONAL, + ... +} + +TDD-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-IntendedTDD-DL-ULConfig CRITICALITY ignore EXTENSION IntendedTDD-DL-ULConfig PRESENCE optional}| + {ID id-TDD-UL-DLConfigCommonNR CRITICALITY ignore EXTENSION TDD-UL-DLConfigCommonNR PRESENCE optional }| + {ID id-CarrierList CRITICALITY ignore EXTENSION NRCarrierList PRESENCE optional }, + ... +} + +TDD-UL-DLConfigCommonNR ::= OCTET STRING + +TimeReferenceInformation ::= SEQUENCE { + referenceTime ReferenceTime, + referenceSFN ReferenceSFN, + uncertainty Uncertainty, + timeInformationType TimeInformationType, + iE-Extensions ProtocolExtensionContainer { {TimeReferenceInformation-ExtIEs} } OPTIONAL +} + +TimeReferenceInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TimeInformationType ::= ENUMERATED {localClock} + +TimeStamp ::= SEQUENCE { + systemFrameNumber SystemFrameNumber, + slotIndex TimeStampSlotIndex, + measurementTime SFNInitialisationTime OPTIONAL, + iE-Extension ProtocolExtensionContainer { { TimeStamp-ExtIEs} } OPTIONAL +} + +TimeStamp-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TimeStampSlotIndex ::= CHOICE { + sCS-15 INTEGER(0..9), + sCS-30 INTEGER(0..19), + sCS-60 INTEGER(0..39), + sCS-120 INTEGER(0..79), + choice-extension ProtocolIE-SingleContainer { { TimeStampSlotIndex-ExtIEs} } +} + +TimeStampSlotIndex-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TimeToWait ::= ENUMERATED {v1s, v2s, v5s, v10s, v20s, v60s, ...} + +TimingMeasurementQuality ::= SEQUENCE { + measurementQuality INTEGER(0..31), + resolution ENUMERATED{m0dot1, m1, m10, m30, ...}, + iE-Extensions ProtocolExtensionContainer { { TimingMeasurementQuality-ExtIEs} } OPTIONAL +} + +TimingMeasurementQuality-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TNLAssociationUsage ::= ENUMERATED { + ue, + non-ue, + both, + ... +} + +TNLCapacityIndicator::= SEQUENCE { + dLTNLOfferedCapacity INTEGER (1.. 16777216,...), + dLTNLAvailableCapacity INTEGER (0.. 100,...), + uLTNLOfferedCapacity INTEGER (1.. 16777216,...), + uLTNLAvailableCapacity INTEGER (0.. 100,...), + iE-Extensions ProtocolExtensionContainer { { TNLCapacityIndicator-ExtIEs} } OPTIONAL +} + +TNLCapacityIndicator-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TraceActivation ::= SEQUENCE { + traceID TraceID, + interfacesToTrace InterfacesToTrace, + traceDepth TraceDepth, + traceCollectionEntityIPAddress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { {TraceActivation-ExtIEs} } OPTIONAL +} + +TraceActivation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + {ID id-mdtConfiguration CRITICALITY ignore EXTENSION MDTConfiguration PRESENCE optional}| + {ID id-TraceCollectionEntityURI CRITICALITY ignore EXTENSION URI-address PRESENCE optional }, + ... +} + +TraceDepth ::= ENUMERATED { + minimum, + medium, + maximum, + minimumWithoutVendorSpecificExtension, + mediumWithoutVendorSpecificExtension, + maximumWithoutVendorSpecificExtension, + ... +} + +TraceID ::= OCTET STRING (SIZE(8)) + +TrafficMappingInfo ::= CHOICE { + iPtolayer2TrafficMappingInfo IPtolayer2TrafficMappingInfo, + bAPlayerBHRLCchannelMappingInfo BAPlayerBHRLCchannelMappingInfo, + choice-extension ProtocolIE-SingleContainer { { TrafficMappingInfo-ExtIEs} } +} + +TrafficMappingInfo-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TransportLayerAddress ::= BIT STRING (SIZE(1..160, ...)) + +TransactionID ::= INTEGER (0..255, ...) + +Transmission-Bandwidth ::= SEQUENCE { + nRSCS NRSCS, + nRNRB NRNRB, + iE-Extensions ProtocolExtensionContainer { { Transmission-Bandwidth-ExtIEs} } OPTIONAL, + ... +} + +Transmission-Bandwidth-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TransmissionComb ::= CHOICE { + n2 SEQUENCE { + combOffset-n2 INTEGER (0..1), + cyclicShift-n2 INTEGER (0..7) + }, + n4 SEQUENCE { + combOffset-n4 INTEGER (0..3), + cyclicShift-n4 INTEGER (0..11) + }, + choice-extension ProtocolIE-SingleContainer { { TransmissionComb-ExtIEs} } +} +TransmissionComb-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TransmissionCombPos ::= CHOICE { + n2 SEQUENCE { + combOffset-n2 INTEGER (0..1), + cyclicShift-n2 INTEGER (0..7) + }, + n4 SEQUENCE { + combOffset-n4 INTEGER (0..3), + cyclicShift-n4 INTEGER (0..11) + }, + n8 SEQUENCE { + combOffset-n8 INTEGER (0..7), + cyclicShift-n8 INTEGER (0..5) + }, + + choice-extension ProtocolIE-SingleContainer { { TransmissionCombPos-ExtIEs} } +} +TransmissionCombPos-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +Transport-UP-Layer-Address-Info-To-Add-List ::= SEQUENCE (SIZE(1.. maxnoofTLAs)) OF Transport-UP-Layer-Address-Info-To-Add-Item + +Transport-UP-Layer-Address-Info-To-Add-Item ::= SEQUENCE { + iP-SecTransportLayerAddress TransportLayerAddress, + gTPTransportLayerAddressToAdd GTPTLAs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Transport-UP-Layer-Address-Info-To-Add-ItemExtIEs } } OPTIONAL +} + +Transport-UP-Layer-Address-Info-To-Add-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +Transport-UP-Layer-Address-Info-To-Remove-List ::= SEQUENCE (SIZE(1.. maxnoofTLAs)) OF Transport-UP-Layer-Address-Info-To-Remove-Item + +Transport-UP-Layer-Address-Info-To-Remove-Item ::= SEQUENCE { + iP-SecTransportLayerAddress TransportLayerAddress, + gTPTransportLayerAddressToRemove GTPTLAs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Transport-UP-Layer-Address-Info-To-Remove-ItemExtIEs } } OPTIONAL +} + +Transport-UP-Layer-Address-Info-To-Remove-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TransmissionActionIndicator ::= ENUMERATED {stop, ..., restart } + +TRPID ::= INTEGER (0.. maxnoofTRPs, ...) + +TRPInformation ::= SEQUENCE { + tRPID TRPID, + tRPInformationTypeResponseList TRPInformationTypeResponseList, + iE-Extensions ProtocolExtensionContainer { { TRPInformation-ExtIEs } } OPTIONAL +} + +TRPInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPInformationItem ::= SEQUENCE { + tRPInformation TRPInformation, + iE-Extensions ProtocolExtensionContainer { { TRPInformationItem-ExtIEs } } OPTIONAL +} + +TRPInformationItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPInformationTypeItem ::= ENUMERATED { + nrPCI, + nG-RAN-CGI, + arfcn, + pRSConfig, + sSBConfig, + sFNInitTime, + spatialDirectInfo, + geoCoord, +...} + + +TRPInformationTypeResponseList ::= SEQUENCE (SIZE(1.. maxnoofTRPInfoTypes)) OF TRPInformationTypeResponseItem + +TRPInformationTypeResponseItem ::= CHOICE { + pCI-NR NRPCI, + nG-RAN-CGI NRCGI, + nRARFCN INTEGER (0..maxNRARFCN), + pRSConfiguration PRSConfiguration, + sSBinformation SSBInformation, + sFNInitialisationTime SFNInitialisationTime, + spatialDirectionInformation SpatialDirectionInformation, + geographicalCoordinates GeographicalCoordinates, + choice-extension ProtocolIE-SingleContainer { { TRPInformationTypeResponseItem-ExtIEs} } +} + +TRPInformationTypeResponseItem-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +TRPList ::= SEQUENCE (SIZE(1.. maxnoofTRPs)) OF TRPListItem + +TRPListItem ::= SEQUENCE { + tRPID TRPID, + iE-Extensions ProtocolExtensionContainer { { TRPListItem-ExtIEs } } OPTIONAL +} + +TRPListItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPMeasurementQuality ::= SEQUENCE { + tRPmeasurementQuality-Item TRPMeasurementQuality-Item, + iE-Extensions ProtocolExtensionContainer { {TRPMeasurementQuality-ExtIEs} } OPTIONAL +} + +TRPMeasurementQuality-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPMeasurementQuality-Item ::= CHOICE { + timingMeasurementQuality TimingMeasurementQuality, + angleMeasurementQuality AngleMeasurementQuality, + choice-extension ProtocolIE-SingleContainer { { TRPMeasurementQuality-Item-ExtIEs } } +} + +TRPMeasurementQuality-Item-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TRP-MeasurementRequestList ::= SEQUENCE (SIZE (1..maxNoOfMeasTRPs)) OF TRP-MeasurementRequestItem + +TRP-MeasurementRequestItem ::= SEQUENCE { + tRPID TRPID, + search-window-information Search-window-information OPTIONAL, + iE-extensions ProtocolExtensionContainer { { TRP-MeasurementRequestItem-ExtIEs } } OPTIONAL +} + +TRP-MeasurementRequestItem-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPPositionDefinitionType ::= CHOICE { + direct TRPPositionDirect, + referenced TRPPositionReferenced, + choice-extension ProtocolIE-SingleContainer { { TRPPositionDefinitionType-ExtIEs } } +} + +TRPPositionDefinitionType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TRPPositionDirect ::= SEQUENCE { + accuracy TRPPositionDirectAccuracy, + iE-extensions ProtocolExtensionContainer { { TRPPositionDirect-ExtIEs } } OPTIONAL +} + +TRPPositionDirect-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPPositionDirectAccuracy ::= CHOICE { + tRPPosition AccessPointPosition, + tRPHAposition NGRANHighAccuracyAccessPointPosition, + choice-extension ProtocolIE-SingleContainer { { TRPPositionDirectAccuracy-ExtIEs } } +} + +TRPPositionDirectAccuracy-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TRPPositionReferenced ::= SEQUENCE { + referencePoint ReferencePoint, + referencePointType TRPReferencePointType, + iE-extensions ProtocolExtensionContainer { { TRPPositionReferenced-ExtIEs } } OPTIONAL +} + +TRPPositionReferenced-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TRPReferencePointType ::= CHOICE { + tRPPositionRelativeGeodetic RelativeGeodeticLocation, + tRPPositionRelativeCartesian RelativeCartesianLocation, + choice-extension ProtocolIE-SingleContainer { { TRPReferencePointType-ExtIEs } } +} + +TRPReferencePointType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +TypeOfError ::= ENUMERATED { + not-understood, + missing, + ... +} + +Transport-Layer-Address-Info ::= SEQUENCE { + transport-UP-Layer-Address-Info-To-Add-List Transport-UP-Layer-Address-Info-To-Add-List OPTIONAL, + transport-UP-Layer-Address-Info-To-Remove-List Transport-UP-Layer-Address-Info-To-Remove-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { Transport-Layer-Address-Info-ExtIEs } } OPTIONAL +} + +Transport-Layer-Address-Info-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TSCAssistanceInformation ::= SEQUENCE { + periodicity Periodicity, + burstArrivalTime BurstArrivalTime OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {TSCAssistanceInformation-ExtIEs} } OPTIONAL, + ... +} + +TSCAssistanceInformation-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +TSCTrafficCharacteristics ::= SEQUENCE { + tSCAssistanceInformationDL TSCAssistanceInformation OPTIONAL, + tSCAssistanceInformationUL TSCAssistanceInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {TSCTrafficCharacteristics-ExtIEs} } OPTIONAL, + ... +} + +TSCTrafficCharacteristics-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +-- U +UAC-Assistance-Info ::= SEQUENCE { + uACPLMN-List UACPLMN-List, + iE-Extensions ProtocolExtensionContainer { { UAC-Assistance-InfoExtIEs} } OPTIONAL +} + +UAC-Assistance-InfoExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UACPLMN-List ::= SEQUENCE (SIZE(1..maxnoofUACPLMNs)) OF UACPLMN-Item + +UACPLMN-Item::= SEQUENCE { + pLMNIdentity PLMN-Identity, + uACType-List UACType-List, iE-Extensions ProtocolExtensionContainer { { UACPLMN-Item-ExtIEs} } OPTIONAL +} + +UACPLMN-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-NID CRITICALITY ignore EXTENSION NID PRESENCE optional }, + ... +} + +UACType-List ::= SEQUENCE (SIZE(1..maxnoofUACperPLMN)) OF UACType-Item + +UACType-Item::= SEQUENCE { + uACReductionIndication UACReductionIndication, + uACCategoryType UACCategoryType, + iE-Extensions ProtocolExtensionContainer { { UACType-Item-ExtIEs } } OPTIONAL +} + +UACType-Item-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UACCategoryType ::= CHOICE { + uACstandardized UACAction, + uACOperatorDefined UACOperatorDefined, + choice-extension ProtocolIE-SingleContainer { { UACCategoryType-ExtIEs } } +} + +UACCategoryType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +UACOperatorDefined ::= SEQUENCE { + accessCategory INTEGER (32..63,...), + accessIdentity BIT STRING (SIZE(7)), + iE-Extensions ProtocolExtensionContainer { { UACOperatorDefined-ExtIEs} } OPTIONAL +} + +UACOperatorDefined-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +UACAction ::= ENUMERATED { + reject-non-emergency-mo-dt, + reject-rrc-cr-signalling, + permit-emergency-sessions-and-mobile-terminated-services-only, + permit-high-priority-sessions-and-mobile-terminated-services-only, + ... +} + +UACReductionIndication ::= INTEGER (0..100) + + +UE-associatedLogicalF1-ConnectionItem ::= SEQUENCE { + gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID OPTIONAL, + gNB-DU-UE-F1AP-ID GNB-DU-UE-F1AP-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { UE-associatedLogicalF1-ConnectionItemExtIEs} } OPTIONAL, + ... +} + +UEAssistanceInformation ::= OCTET STRING + +UEAssistanceInformationEUTRA ::= OCTET STRING + +UE-associatedLogicalF1-ConnectionItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UE-CapabilityRAT-ContainerList::= OCTET STRING + +UEContextNotRetrievable ::= ENUMERATED {true, ...} + +UEIdentityIndexValue ::= CHOICE { + indexLength10 BIT STRING (SIZE (10)), + choice-extension ProtocolIE-SingleContainer { {UEIdentityIndexValueChoice-ExtIEs} } +} + +UEIdentityIndexValueChoice-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +UL-AoA ::= SEQUENCE { + azimuthAoA INTEGER (0..3599), + zenithAoA INTEGER (0..1799) OPTIONAL, + angleCoordinateSystem ENUMERATED {lCS, gCS} OPTIONAL, + iE-extensions ProtocolExtensionContainer { { UL-AoA-ExtIEs } } +} + +UL-AoA-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-BH-Non-UP-Traffic-Mapping ::= SEQUENCE { + uL-BH-Non-UP-Traffic-Mapping-List UL-BH-Non-UP-Traffic-Mapping-List, + iE-Extensions ProtocolExtensionContainer { { UL-BH-Non-UP-Traffic-Mapping-ExtIEs } } OPTIONAL +} + +UL-BH-Non-UP-Traffic-Mapping-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-BH-Non-UP-Traffic-Mapping-List ::= SEQUENCE (SIZE(1..maxnoofNonUPTrafficMappings)) OF UL-BH-Non-UP-Traffic-Mapping-Item + +UL-BH-Non-UP-Traffic-Mapping-Item ::= SEQUENCE { + nonUPTrafficType NonUPTrafficType, + bHInfo BHInfo, + iE-Extensions ProtocolExtensionContainer { { UL-BH-Non-UP-Traffic-Mapping-ItemExtIEs } } OPTIONAL +} + +UL-BH-Non-UP-Traffic-Mapping-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ULConfiguration ::= SEQUENCE { + uLUEConfiguration ULUEConfiguration, + iE-Extensions ProtocolExtensionContainer { { ULConfigurationExtIEs } } OPTIONAL, + ... +} +ULConfigurationExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-RTOA-Measurement ::= SEQUENCE { + uL-RTOA-MeasurementItem UL-RTOA-MeasurementItem, + additionalPath-List AdditionalPath-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { UL-RTOA-Measurement-ExtIEs } } OPTIONAL +} + +UL-RTOA-Measurement-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-RTOA-MeasurementItem ::= CHOICE { + k0 INTEGER (0..1970049), + k1 INTEGER (0..985025), + k2 INTEGER (0..492513), + k3 INTEGER (0..246257), + k4 INTEGER (0..123129), + k5 INTEGER (0..61565), + choice-extension ProtocolIE-SingleContainer { { UL-RTOA-MeasurementItem-ExtIEs } } +} + +UL-RTOA-MeasurementItem-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +UL-SRS-RSRP ::= INTEGER (0..127) + +ULUEConfiguration ::= ENUMERATED {no-data, shared, only, ...} + +UL-UP-TNL-Information-to-Update-List-Item ::= SEQUENCE { + uLUPTNLInformation UPTransportLayerInformation, + newULUPTNLInformation UPTransportLayerInformation OPTIONAL, + bHInfo BHInfo, + iE-Extensions ProtocolExtensionContainer { { UL-UP-TNL-Information-to-Update-List-ItemExtIEs } } OPTIONAL, + ... +} + +UL-UP-TNL-Information-to-Update-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-UP-TNL-Address-to-Update-List-Item ::= SEQUENCE { + oldIPAdress TransportLayerAddress, + newIPAdress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { { UL-UP-TNL-Address-to-Update-List-ItemExtIEs } } OPTIONAL, + ... +} + +UL-UP-TNL-Address-to-Update-List-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +ULUPTNLInformation-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofULUPTNLInformation)) OF ULUPTNLInformation-ToBeSetup-Item + +ULUPTNLInformation-ToBeSetup-Item ::=SEQUENCE { + uLUPTNLInformation UPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { { ULUPTNLInformation-ToBeSetup-ItemExtIEs } } OPTIONAL, + ... +} + +ULUPTNLInformation-ToBeSetup-ItemExtIEs F1AP-PROTOCOL-EXTENSION ::= { + { ID id-BHInfo CRITICALITY ignore EXTENSION BHInfo PRESENCE optional }, + ... +} + +Uncertainty ::= INTEGER (0..32767, ...) + +UplinkChannelBW-PerSCS-List ::= SEQUENCE (SIZE (1..maxnoSCSs)) OF SCS-SpecificCarrier + +UplinkTxDirectCurrentListInformation ::= OCTET STRING + +UPTransportLayerInformation ::= CHOICE { + gTPTunnel GTPTunnel, + choice-extension ProtocolIE-SingleContainer { { UPTransportLayerInformation-ExtIEs} } +} + +UPTransportLayerInformation-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +URI-address ::= VisibleString + +-- V + +VictimgNBSetID ::= SEQUENCE { + victimgNBSetID GNBSetID, + iE-Extensions ProtocolExtensionContainer { { VictimgNBSetID-ExtIEs } } OPTIONAL +} + +VictimgNBSetID-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +VehicleUE ::= ENUMERATED { + authorized, + not-authorized, + ... +} + +PedestrianUE ::= ENUMERATED { + authorized, + not-authorized, + ... +} + +-- W + +-- X + +-- Y + +-- Z + +END diff --git a/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-PDU-Contents.asn b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-PDU-Contents.asn new file mode 100644 index 0000000000..ba6351eddd --- /dev/null +++ b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-PDU-Contents.asn @@ -0,0 +1,3633 @@ +-- ************************************************************** +-- +-- PDU definitions for F1AP. +-- +-- ************************************************************** + +F1AP-PDU-Contents { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-PDU-Contents (1) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + Candidate-SpCell-Item, + Cause, + Cells-Failed-to-be-Activated-List-Item, + Cells-Status-Item, + Cells-to-be-Activated-List-Item, + Cells-to-be-Deactivated-List-Item, + CellULConfigured, + CriticalityDiagnostics, + C-RNTI, + CUtoDURRCInformation, + DRB-Activity-Item, + DRBID, + DRBs-FailedToBeModified-Item, + DRBs-FailedToBeSetup-Item, + DRBs-FailedToBeSetupMod-Item, + DRB-Notify-Item, + DRBs-ModifiedConf-Item, + DRBs-Modified-Item, + DRBs-Required-ToBeModified-Item, + DRBs-Required-ToBeReleased-Item, + DRBs-Setup-Item, + DRBs-SetupMod-Item, + DRBs-ToBeModified-Item, + DRBs-ToBeReleased-Item, + DRBs-ToBeSetup-Item, + DRBs-ToBeSetupMod-Item, + DRXCycle, + DRXConfigurationIndicator, + DUtoCURRCInformation, + EUTRANQoS, + ExecuteDuplication, + FullConfiguration, + GNB-CU-UE-F1AP-ID, + GNB-DU-UE-F1AP-ID, + GNB-DU-ID, + GNB-DU-Served-Cells-Item, + GNB-DU-System-Information, + GNB-CU-Name, + GNB-DU-Name, + InactivityMonitoringRequest, + InactivityMonitoringResponse, + LowerLayerPresenceStatusChange, + NotificationControl, + NRCGI, + NRPCI, + UEContextNotRetrievable, + Potential-SpCell-Item, + RAT-FrequencyPriorityInformation, + RequestedSRSTransmissionCharacteristics, + ResourceCoordinationTransferContainer, + RRCContainer, + RRCContainer-RRCSetupComplete, + RRCReconfigurationCompleteIndicator, + SCellIndex, + SCell-ToBeRemoved-Item, + SCell-ToBeSetup-Item, + SCell-ToBeSetupMod-Item, + SCell-FailedtoSetup-Item, + SCell-FailedtoSetupMod-Item, + ServCellIndex, + Served-Cell-Information, + Served-Cells-To-Add-Item, + Served-Cells-To-Delete-Item, + Served-Cells-To-Modify-Item, + ServingCellMO, + SRBID, + SRBs-FailedToBeSetup-Item, + SRBs-FailedToBeSetupMod-Item, + SRBs-Required-ToBeReleased-Item, + SRBs-ToBeReleased-Item, + SRBs-ToBeSetup-Item, + SRBs-ToBeSetupMod-Item, + SRBs-Modified-Item, + SRBs-Setup-Item, + SRBs-SetupMod-Item, + TimeToWait, + TransactionID, + TransmissionActionIndicator, + UE-associatedLogicalF1-ConnectionItem, + DUtoCURRCContainer, + PagingCell-Item, + SItype-List, + UEIdentityIndexValue, + GNB-CU-TNL-Association-Setup-Item, + GNB-CU-TNL-Association-Failed-To-Setup-Item, + GNB-CU-TNL-Association-To-Add-Item, + GNB-CU-TNL-Association-To-Remove-Item, + GNB-CU-TNL-Association-To-Update-Item, + MaskedIMEISV, + PagingDRX, + PagingPriority, + PagingIdentity, + Cells-to-be-Barred-Item, + PWSSystemInformation, + Broadcast-To-Be-Cancelled-Item, + Cells-Broadcast-Cancelled-Item, + NR-CGI-List-For-Restart-Item, + PWS-Failed-NR-CGI-Item, + RepetitionPeriod, + NumberofBroadcastRequest, + Cells-To-Be-Broadcast-Item, + Cells-Broadcast-Completed-Item, + Cancel-all-Warning-Messages-Indicator, + EUTRA-NR-CellResourceCoordinationReq-Container, + EUTRA-NR-CellResourceCoordinationReqAck-Container, + RequestType, + PLMN-Identity, + RLCFailureIndication, + UplinkTxDirectCurrentListInformation, + SULAccessIndication, + Protected-EUTRA-Resources-Item, + GNB-DUConfigurationQuery, + BitRate, + RRC-Version, + GNBDUOverloadInformation, + RRCDeliveryStatusRequest, + NeedforGap, + RRCDeliveryStatus, + ResourceCoordinationTransferInformation, + Dedicated-SIDelivery-NeededUE-Item, + Associated-SCell-Item, + IgnoreResourceCoordinationContainer, + PagingOrigin, + UAC-Assistance-Info, + RANUEID, + GNB-DU-TNL-Association-To-Remove-Item, + NotificationInformation, + TraceActivation, + TraceID, + Neighbour-Cell-Information-Item, + SymbolAllocInSlot, + NumDLULSymbols, + AdditionalRRMPriorityIndex, + DUCURadioInformationType, + CUDURadioInformationType, + Transport-Layer-Address-Info, + BHChannels-ToBeSetup-Item, + BHChannels-Setup-Item, + BHChannels-FailedToBeSetup-Item, + BHChannels-ToBeModified-Item, + BHChannels-ToBeReleased-Item, + BHChannels-ToBeSetupMod-Item, + BHChannels-FailedToBeModified-Item, + BHChannels-FailedToBeSetupMod-Item, + BHChannels-Modified-Item, + BHChannels-SetupMod-Item, + BHChannels-Required-ToBeReleased-Item, + BAPAddress, + BAPPathID, + BAPRoutingID, + BH-Routing-Information-Added-List-Item, + BH-Routing-Information-Removed-List-Item, + Child-Nodes-List, + Child-Nodes-List-Item, + Child-Node-Cells-List, + Child-Node-Cells-List-Item, + Activated-Cells-to-be-Updated-List, + Activated-Cells-to-be-Updated-List-Item, + UL-BH-Non-UP-Traffic-Mapping, + IABTNLAddressesRequested, + IABIPv6RequestType, + IAB-TNL-Addresses-To-Remove-Item, + IABTNLAddress, + IAB-Allocated-TNL-Address-Item, + IABv4AddressesRequested, + TrafficMappingInfo, + UL-UP-TNL-Information-to-Update-List-Item, + UL-UP-TNL-Address-to-Update-List-Item, + DL-UP-TNL-Address-to-Update-List-Item, + NRV2XServicesAuthorized, + LTEV2XServicesAuthorized, + NRUESidelinkAggregateMaximumBitrate, + LTEUESidelinkAggregateMaximumBitrate, + SLDRBs-SetupMod-Item, + SLDRBs-ModifiedConf-Item, + SLDRBID, + SLDRBs-FailedToBeModified-Item, + SLDRBs-FailedToBeSetup-Item, + SLDRBs-FailedToBeSetupMod-Item, + SLDRBs-Modified-Item, + SLDRBs-Required-ToBeModified-Item, + SLDRBs-Required-ToBeReleased-Item, + SLDRBs-Setup-Item, + SLDRBs-ToBeModified-Item, + SLDRBs-ToBeReleased-Item, + SLDRBs-ToBeSetup-Item, + SLDRBs-ToBeSetupMod-Item, + GNBCUMeasurementID, + GNBDUMeasurementID, + RegistrationRequest, + ReportCharacteristics, + CellToReportList, + HardwareLoadIndicator, + CellMeasurementResultList, + ReportingPeriodicity, + TNLCapacityIndicator, + RACHReportInformationList, + RLFReportInformationList, + ReportingRequestType, + TimeReferenceInformation, + ConditionalInterDUMobilityInformation, + ConditionalIntraDUMobilityInformation, + TargetCellList, + MDTPLMNList, + PrivacyIndicator, + TransportLayerAddress, + URI-address, + NID, + PosAssistance-Information, + PosBroadcast, + PositioningBroadcastCells, + RoutingID, + PosAssistanceInformationFailureList, + PosMeasurementQuantities, + PosMeasurementResultList, + PosMeasurementPeriodicity, + PosReportCharacteristics, + TRPInformationTypeItem, + TRPInformationItem, + LMF-MeasurementID, + RAN-MeasurementID, + SRSResourceSetID, + SRSSpatialRelation, + SRSResourceTrigger, + SRSConfiguration, + TRPList, + E-CID-MeasurementQuantities, + E-CID-MeasurementPeriodicity, + E-CID-MeasurementResult, + Cell-Portion-ID, + LMF-UE-MeasurementID, + RAN-UE-MeasurementID, + SFNInitialisationTime, + SystemFrameNumber, + SlotNumber, + AbortTransmission, + TRP-MeasurementRequestList, + MeasurementBeamInfoRequest, + E-CID-ReportCharacteristics, + Extended-GNB-CU-Name, + Extended-GNB-DU-Name + + + +FROM F1AP-IEs + + PrivateIE-Container{}, + ProtocolExtensionContainer{}, + ProtocolIE-Container{}, + ProtocolIE-ContainerPair{}, + ProtocolIE-SingleContainer{}, + F1AP-PRIVATE-IES, + F1AP-PROTOCOL-EXTENSION, + F1AP-PROTOCOL-IES, + F1AP-PROTOCOL-IES-PAIR + +FROM F1AP-Containers + + id-Candidate-SpCell-Item, + id-Candidate-SpCell-List, + id-Cause, + id-Cancel-all-Warning-Messages-Indicator, + id-Cells-Failed-to-be-Activated-List, + id-Cells-Failed-to-be-Activated-List-Item, + id-Cells-Status-Item, + id-Cells-Status-List, + id-Cells-to-be-Activated-List, + id-Cells-to-be-Activated-List-Item, + id-Cells-to-be-Deactivated-List, + id-Cells-to-be-Deactivated-List-Item, + id-ConfirmedUEID, + id-CriticalityDiagnostics, + id-C-RNTI, + id-CUtoDURRCInformation, + id-DRB-Activity-Item, + id-DRB-Activity-List, + id-DRBs-FailedToBeModified-Item, + id-DRBs-FailedToBeModified-List, + id-DRBs-FailedToBeSetup-Item, + id-DRBs-FailedToBeSetup-List, + id-DRBs-FailedToBeSetupMod-Item, + id-DRBs-FailedToBeSetupMod-List, + id-DRBs-ModifiedConf-Item, + id-DRBs-ModifiedConf-List, + id-DRBs-Modified-Item, + id-DRBs-Modified-List, + id-DRB-Notify-Item, + id-DRB-Notify-List, + id-DRBs-Required-ToBeModified-Item, + id-DRBs-Required-ToBeModified-List, + id-DRBs-Required-ToBeReleased-Item, + id-DRBs-Required-ToBeReleased-List, + id-DRBs-Setup-Item, + id-DRBs-Setup-List, + id-DRBs-SetupMod-Item, + id-DRBs-SetupMod-List, + id-DRBs-ToBeModified-Item, + id-DRBs-ToBeModified-List, + id-DRBs-ToBeReleased-Item, + id-DRBs-ToBeReleased-List, + id-DRBs-ToBeSetup-Item, + id-DRBs-ToBeSetup-List, + id-DRBs-ToBeSetupMod-Item, + id-DRBs-ToBeSetupMod-List, + id-DRXCycle, + id-DUtoCURRCInformation, + id-ExecuteDuplication, + id-FullConfiguration, + id-gNB-CU-UE-F1AP-ID, + id-gNB-DU-UE-F1AP-ID, + id-gNB-DU-ID, + id-GNB-DU-Served-Cells-Item, + id-gNB-DU-Served-Cells-List, + id-gNB-CU-Name, + id-gNB-DU-Name, + id-Extended-GNB-CU-Name, + id-Extended-GNB-DU-Name, + id-InactivityMonitoringRequest, + id-InactivityMonitoringResponse, + id-new-gNB-CU-UE-F1AP-ID, + id-new-gNB-DU-UE-F1AP-ID, + id-oldgNB-DU-UE-F1AP-ID, + id-PLMNAssistanceInfoForNetShar, + id-Potential-SpCell-Item, + id-Potential-SpCell-List, + id-RAT-FrequencyPriorityInformation, + id-RedirectedRRCmessage, + id-ResetType, + id-RequestedSRSTransmissionCharacteristics, + id-ResourceCoordinationTransferContainer, + id-RRCContainer, + id-RRCContainer-RRCSetupComplete, + id-RRCReconfigurationCompleteIndicator, + id-SCell-FailedtoSetup-List, + id-SCell-FailedtoSetup-Item, + id-SCell-FailedtoSetupMod-List, + id-SCell-FailedtoSetupMod-Item, + id-SCell-ToBeRemoved-Item, + id-SCell-ToBeRemoved-List, + id-SCell-ToBeSetup-Item, + id-SCell-ToBeSetup-List, + id-SCell-ToBeSetupMod-Item, + id-SCell-ToBeSetupMod-List, + id-SelectedPLMNID, + id-Served-Cells-To-Add-Item, + id-Served-Cells-To-Add-List, + id-Served-Cells-To-Delete-Item, + id-Served-Cells-To-Delete-List, + id-Served-Cells-To-Modify-Item, + id-Served-Cells-To-Modify-List, + id-ServCellIndex, + id-ServingCellMO, + id-SpCell-ID, + id-SpCellULConfigured, + id-SRBID, + id-SRBs-FailedToBeSetup-Item, + id-SRBs-FailedToBeSetup-List, + id-SRBs-FailedToBeSetupMod-Item, + id-SRBs-FailedToBeSetupMod-List, + id-SRBs-Required-ToBeReleased-Item, + id-SRBs-Required-ToBeReleased-List, + id-SRBs-ToBeReleased-Item, + id-SRBs-ToBeReleased-List, + id-SRBs-ToBeSetup-Item, + id-SRBs-ToBeSetup-List, + id-SRBs-ToBeSetupMod-Item, + id-SRBs-ToBeSetupMod-List, + id-SRBs-Modified-Item, + id-SRBs-Modified-List, + id-SRBs-Setup-Item, + id-SRBs-Setup-List, + id-SRBs-SetupMod-Item, + id-SRBs-SetupMod-List, + id-TimeToWait, + id-TransactionID, + id-TransmissionActionIndicator, + id-UEContextNotRetrievable, + id-UE-associatedLogicalF1-ConnectionItem, + id-UE-associatedLogicalF1-ConnectionListResAck, + id-DUtoCURRCContainer, + id-NRCGI, + id-PagingCell-Item, + id-PagingCell-List, + id-PagingDRX, + id-PagingPriority, + id-SItype-List, + id-UEIdentityIndexValue, + id-GNB-CU-TNL-Association-Setup-List, + id-GNB-CU-TNL-Association-Setup-Item, + id-GNB-CU-TNL-Association-Failed-To-Setup-List, + id-GNB-CU-TNL-Association-Failed-To-Setup-Item, + id-GNB-CU-TNL-Association-To-Add-Item, + id-GNB-CU-TNL-Association-To-Add-List, + id-GNB-CU-TNL-Association-To-Remove-Item, + id-GNB-CU-TNL-Association-To-Remove-List, + id-GNB-CU-TNL-Association-To-Update-Item, + id-GNB-CU-TNL-Association-To-Update-List, + id-MaskedIMEISV, + id-PagingIdentity, + id-Cells-to-be-Barred-List, + id-Cells-to-be-Barred-Item, + id-PWSSystemInformation, + id-RepetitionPeriod, + id-NumberofBroadcastRequest, + id-Cells-To-Be-Broadcast-List, + id-Cells-To-Be-Broadcast-Item, + id-Cells-Broadcast-Completed-List, + id-Cells-Broadcast-Completed-Item, + id-Broadcast-To-Be-Cancelled-List, + id-Broadcast-To-Be-Cancelled-Item, + id-Cells-Broadcast-Cancelled-List, + id-Cells-Broadcast-Cancelled-Item, + id-NR-CGI-List-For-Restart-List, + id-NR-CGI-List-For-Restart-Item, + id-PWS-Failed-NR-CGI-List, + id-PWS-Failed-NR-CGI-Item, + id-EUTRA-NR-CellResourceCoordinationReq-Container, + id-EUTRA-NR-CellResourceCoordinationReqAck-Container, + id-Protected-EUTRA-Resources-List, + id-RequestType, + id-ServingPLMN, + id-DRXConfigurationIndicator, + id-RLCFailureIndication, + id-UplinkTxDirectCurrentListInformation, + id-SULAccessIndication, + id-Protected-EUTRA-Resources-Item, + id-GNB-DUConfigurationQuery, + id-GNB-DU-UE-AMBR-UL, + id-GNB-CU-RRC-Version, + id-GNB-DU-RRC-Version, + id-GNBDUOverloadInformation, + id-NeedforGap, + id-RRCDeliveryStatusRequest, + id-RRCDeliveryStatus, + id-Dedicated-SIDelivery-NeededUE-List, + id-Dedicated-SIDelivery-NeededUE-Item, + id-ResourceCoordinationTransferInformation, + id-Associated-SCell-List, + id-Associated-SCell-Item, + id-IgnoreResourceCoordinationContainer, + id-UAC-Assistance-Info, + id-RANUEID, + id-PagingOrigin, + id-GNB-DU-TNL-Association-To-Remove-Item, + id-GNB-DU-TNL-Association-To-Remove-List, + id-NotificationInformation, + id-TraceActivation, + id-TraceID, + id-Neighbour-Cell-Information-List, + id-Neighbour-Cell-Information-Item, + id-SymbolAllocInSlot, + id-NumDLULSymbols, + id-AdditionalRRMPriorityIndex, + id-DUCURadioInformationType, + id-CUDURadioInformationType, + id-LowerLayerPresenceStatusChange, + id-Transport-Layer-Address-Info, + id-BHChannels-ToBeSetup-List, + id-BHChannels-ToBeSetup-Item, + id-BHChannels-Setup-List, + id-BHChannels-Setup-Item, + id-BHChannels-ToBeModified-Item, + id-BHChannels-ToBeModified-List, + id-BHChannels-ToBeReleased-Item, + id-BHChannels-ToBeReleased-List, + id-BHChannels-ToBeSetupMod-Item, + id-BHChannels-ToBeSetupMod-List, + id-BHChannels-FailedToBeSetup-Item, + id-BHChannels-FailedToBeSetup-List, + id-BHChannels-FailedToBeModified-Item, + id-BHChannels-FailedToBeModified-List, + id-BHChannels-FailedToBeSetupMod-Item, + id-BHChannels-FailedToBeSetupMod-List, + id-BHChannels-Modified-Item, + id-BHChannels-Modified-List, + id-BHChannels-SetupMod-Item, + id-BHChannels-SetupMod-List, + id-BHChannels-Required-ToBeReleased-Item, + id-BHChannels-Required-ToBeReleased-List, + id-BAPAddress, + id-ConfiguredBAPAddress, + id-BH-Routing-Information-Added-List, + id-BH-Routing-Information-Added-List-Item, + id-BH-Routing-Information-Removed-List, + id-BH-Routing-Information-Removed-List-Item, + id-UL-BH-Non-UP-Traffic-Mapping, + id-Child-Nodes-List, + id-Activated-Cells-to-be-Updated-List, + id-IABIPv6RequestType, + id-IAB-TNL-Addresses-To-Remove-List, + id-IAB-TNL-Addresses-To-Remove-Item, + id-IAB-Allocated-TNL-Address-List, + id-IAB-Allocated-TNL-Address-Item, + id-IABv4AddressesRequested, + id-TrafficMappingInformation, + id-UL-UP-TNL-Information-to-Update-List, + id-UL-UP-TNL-Information-to-Update-List-Item, + id-UL-UP-TNL-Address-to-Update-List, + id-UL-UP-TNL-Address-to-Update-List-Item, + id-DL-UP-TNL-Address-to-Update-List, + id-DL-UP-TNL-Address-to-Update-List-Item, + id-NRV2XServicesAuthorized, + id-LTEV2XServicesAuthorized, + id-NRUESidelinkAggregateMaximumBitrate, + id-LTEUESidelinkAggregateMaximumBitrate, + id-PC5LinkAMBR, + id-SLDRBs-FailedToBeModified-Item, + id-SLDRBs-FailedToBeModified-List, + id-SLDRBs-FailedToBeSetup-Item, + id-SLDRBs-FailedToBeSetup-List, + id-SLDRBs-Modified-Item, + id-SLDRBs-Modified-List, + id-SLDRBs-Required-ToBeModified-Item, + id-SLDRBs-Required-ToBeModified-List, + id-SLDRBs-Required-ToBeReleased-Item, + id-SLDRBs-Required-ToBeReleased-List, + id-SLDRBs-Setup-Item, + id-SLDRBs-Setup-List, + id-SLDRBs-ToBeModified-Item, + id-SLDRBs-ToBeModified-List, + id-SLDRBs-ToBeReleased-Item, + id-SLDRBs-ToBeReleased-List, + id-SLDRBs-ToBeSetup-Item, + id-SLDRBs-ToBeSetup-List, + id-SLDRBs-ToBeSetupMod-Item, + id-SLDRBs-ToBeSetupMod-List, + id-SLDRBs-SetupMod-List, + id-SLDRBs-FailedToBeSetupMod-List, + id-SLDRBs-SetupMod-Item, + id-SLDRBs-FailedToBeSetupMod-Item, + id-SLDRBs-ModifiedConf-List, + id-SLDRBs-ModifiedConf-Item, + id-gNBCUMeasurementID, + id-gNBDUMeasurementID, + id-RegistrationRequest, + id-ReportCharacteristics, + id-CellToReportList, + id-CellMeasurementResultList, + id-HardwareLoadIndicator, + id-ReportingPeriodicity, + id-TNLCapacityIndicator, + id-RACHReportInformationList, + id-RLFReportInformationList, + id-ReportingRequestType, + id-TimeReferenceInformation, + id-ConditionalInterDUMobilityInformation, + id-ConditionalIntraDUMobilityInformation, + id-targetCellsToCancel, + id-requestedTargetCellGlobalID, + id-TraceCollectionEntityIPAddress, + id-ManagementBasedMDTPLMNList, + id-PrivacyIndicator, + id-TraceCollectionEntityURI, + id-ServingNID, + id-PosAssistance-Information, + id-PosBroadcast, + id-PositioningBroadcastCells, + id-RoutingID, + id-PosAssistanceInformationFailureList, + id-PosMeasurementQuantities, + id-PosMeasurementResultList, + id-PosMeasurementPeriodicity, + id-PosReportCharacteristics, + id-TRPInformationTypeListTRPReq, + id-TRPInformationTypeItem, + id-TRPInformationListTRPResp, + id-TRPInformationItem, + id-LMF-MeasurementID, + id-RAN-MeasurementID, + id-SRSType, + id-ActivationTime, + id-AbortTransmission, + id-SRSConfiguration, + id-TRPList, + id-E-CID-MeasurementQuantities, + id-E-CID-MeasurementPeriodicity, + id-E-CID-MeasurementResult, + id-Cell-Portion-ID, + id-LMF-UE-MeasurementID, + id-RAN-UE-MeasurementID, + id-SFNInitialisationTime, + id-SystemFrameNumber, + id-SlotNumber, + id-TRP-MeasurementRequestList, + id-MeasurementBeamInfoRequest, + id-E-CID-ReportCharacteristics, + + maxCellingNBDU, + maxnoofCandidateSpCells, + maxnoofDRBs, + maxnoofErrors, + maxnoofIndividualF1ConnectionsToReset, + maxnoofPotentialSpCells, + maxnoofSCells, + maxnoofSRBs, + maxnoofPagingCells, + maxnoofTNLAssociations, + maxCellineNB, + maxnoofUEIDs, + maxnoofBHRLCChannels, + maxnoofRoutingEntries, + maxnoofChildIABNodes, + maxnoofServedCellsIAB, + maxnoofTLAsIAB, + maxnoofULUPTNLInformationforIAB, + maxnoofUPTNLAddresses, + maxnoofSLDRBs, + maxnoofTRPInfoTypes, + maxnoofTRPs + + + +FROM F1AP-Constants; + + +-- ************************************************************** +-- +-- RESET ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Reset +-- +-- ************************************************************** + +Reset ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {ResetIEs} }, + ... +} + +ResetIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-ResetType CRITICALITY reject TYPE ResetType PRESENCE mandatory }, + ... +} + +ResetType ::= CHOICE { + f1-Interface ResetAll, + partOfF1-Interface UE-associatedLogicalF1-ConnectionListRes, + choice-extension ProtocolIE-SingleContainer { { ResetType-ExtIEs} } +} + +ResetType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + + +ResetAll ::= ENUMERATED { + reset-all, + ... +} + +UE-associatedLogicalF1-ConnectionListRes ::= SEQUENCE (SIZE(1.. maxnoofIndividualF1ConnectionsToReset)) OF ProtocolIE-SingleContainer { { UE-associatedLogicalF1-ConnectionItemRes } } + +UE-associatedLogicalF1-ConnectionItemRes F1AP-PROTOCOL-IES ::= { + { ID id-UE-associatedLogicalF1-ConnectionItem CRITICALITY reject TYPE UE-associatedLogicalF1-ConnectionItem PRESENCE mandatory}, + ... +} + + +-- ************************************************************** +-- +-- Reset Acknowledge +-- +-- ************************************************************** + +ResetAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {ResetAcknowledgeIEs} }, + ... +} + +ResetAcknowledgeIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-UE-associatedLogicalF1-ConnectionListResAck CRITICALITY ignore TYPE UE-associatedLogicalF1-ConnectionListResAck PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +UE-associatedLogicalF1-ConnectionListResAck ::= SEQUENCE (SIZE(1.. maxnoofIndividualF1ConnectionsToReset)) OF ProtocolIE-SingleContainer { { UE-associatedLogicalF1-ConnectionItemResAck } } + +UE-associatedLogicalF1-ConnectionItemResAck F1AP-PROTOCOL-IES ::= { + { ID id-UE-associatedLogicalF1-ConnectionItem CRITICALITY ignore TYPE UE-associatedLogicalF1-ConnectionItem PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- ERROR INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Error Indication +-- +-- ************************************************************** + +ErrorIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ErrorIndicationIEs}}, + ... +} + +ErrorIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE optional }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- F1 SETUP ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- F1 Setup Request +-- +-- ************************************************************** + +F1SetupRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {F1SetupRequestIEs} }, + ... +} + +F1SetupRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNB-DU-ID CRITICALITY reject TYPE GNB-DU-ID PRESENCE mandatory }| + { ID id-gNB-DU-Name CRITICALITY ignore TYPE GNB-DU-Name PRESENCE optional }| + { ID id-gNB-DU-Served-Cells-List CRITICALITY reject TYPE GNB-DU-Served-Cells-List PRESENCE optional }| + { ID id-GNB-DU-RRC-Version CRITICALITY reject TYPE RRC-Version PRESENCE mandatory }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }| + { ID id-BAPAddress CRITICALITY ignore TYPE BAPAddress PRESENCE optional }| + { ID id-Extended-GNB-CU-Name CRITICALITY ignore TYPE Extended-GNB-CU-Name PRESENCE optional }, + ... +} + + +GNB-DU-Served-Cells-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { GNB-DU-Served-Cells-ItemIEs } } + +GNB-DU-Served-Cells-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-DU-Served-Cells-Item CRITICALITY reject TYPE GNB-DU-Served-Cells-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- F1 Setup Response +-- +-- ************************************************************** + +F1SetupResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {F1SetupResponseIEs} }, + ... +} + + +F1SetupResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNB-CU-Name CRITICALITY ignore TYPE GNB-CU-Name PRESENCE optional }| + { ID id-Cells-to-be-Activated-List CRITICALITY reject TYPE Cells-to-be-Activated-List PRESENCE optional }| + { ID id-GNB-CU-RRC-Version CRITICALITY reject TYPE RRC-Version PRESENCE mandatory }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }| + { ID id-UL-BH-Non-UP-Traffic-Mapping CRITICALITY reject TYPE UL-BH-Non-UP-Traffic-Mapping PRESENCE optional }| + { ID id-BAPAddress CRITICALITY ignore TYPE BAPAddress PRESENCE optional }| + { ID id-Extended-GNB-DU-Name CRITICALITY ignore TYPE Extended-GNB-DU-Name PRESENCE optional }, + ... +} + + +Cells-to-be-Activated-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-to-be-Activated-List-ItemIEs } } + +Cells-to-be-Activated-List-ItemIEs F1AP-PROTOCOL-IES::= { + { ID id-Cells-to-be-Activated-List-Item CRITICALITY reject TYPE Cells-to-be-Activated-List-Item PRESENCE mandatory}, + ... +} + + + +-- ************************************************************** +-- +-- F1 Setup Failure +-- +-- ************************************************************** + +F1SetupFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {F1SetupFailureIEs} }, + ... +} + +F1SetupFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- GNB-DU CONFIGURATION UPDATE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- GNB-DU CONFIGURATION UPDATE +-- +-- ************************************************************** + +GNBDUConfigurationUpdate::= SEQUENCE { + protocolIEs ProtocolIE-Container { {GNBDUConfigurationUpdateIEs} }, + ... +} + +GNBDUConfigurationUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Served-Cells-To-Add-List CRITICALITY reject TYPE Served-Cells-To-Add-List PRESENCE optional }| + { ID id-Served-Cells-To-Modify-List CRITICALITY reject TYPE Served-Cells-To-Modify-List PRESENCE optional }| + { ID id-Served-Cells-To-Delete-List CRITICALITY reject TYPE Served-Cells-To-Delete-List PRESENCE optional }| + { ID id-Cells-Status-List CRITICALITY reject TYPE Cells-Status-List PRESENCE optional }| + { ID id-Dedicated-SIDelivery-NeededUE-List CRITICALITY ignore TYPE Dedicated-SIDelivery-NeededUE-List PRESENCE optional }| + { ID id-gNB-DU-ID CRITICALITY reject TYPE GNB-DU-ID PRESENCE optional }| + { ID id-GNB-DU-TNL-Association-To-Remove-List CRITICALITY reject TYPE GNB-DU-TNL-Association-To-Remove-List PRESENCE optional }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }, + ... +} + +Served-Cells-To-Add-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Served-Cells-To-Add-ItemIEs } } +Served-Cells-To-Modify-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Served-Cells-To-Modify-ItemIEs } } +Served-Cells-To-Delete-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Served-Cells-To-Delete-ItemIEs } } +Cells-Status-List ::= SEQUENCE (SIZE(0.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-Status-ItemIEs } } + +Dedicated-SIDelivery-NeededUE-List::= SEQUENCE (SIZE(1.. maxnoofUEIDs)) OF ProtocolIE-SingleContainer { { Dedicated-SIDelivery-NeededUE-ItemIEs } } + +GNB-DU-TNL-Association-To-Remove-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-DU-TNL-Association-To-Remove-ItemIEs } } + + +Served-Cells-To-Add-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Served-Cells-To-Add-Item CRITICALITY reject TYPE Served-Cells-To-Add-Item PRESENCE mandatory }, + ... +} + +Served-Cells-To-Modify-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Served-Cells-To-Modify-Item CRITICALITY reject TYPE Served-Cells-To-Modify-Item PRESENCE mandatory }, + ... +} + +Served-Cells-To-Delete-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Served-Cells-To-Delete-Item CRITICALITY reject TYPE Served-Cells-To-Delete-Item PRESENCE mandatory }, + ... +} + +Cells-Status-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-Status-Item CRITICALITY reject TYPE Cells-Status-Item PRESENCE mandatory }, + ... +} + +Dedicated-SIDelivery-NeededUE-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Dedicated-SIDelivery-NeededUE-Item CRITICALITY ignore TYPE Dedicated-SIDelivery-NeededUE-Item PRESENCE mandatory }, + ... +} + +GNB-DU-TNL-Association-To-Remove-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-DU-TNL-Association-To-Remove-Item CRITICALITY reject TYPE GNB-DU-TNL-Association-To-Remove-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- GNB-DU CONFIGURATION UPDATE ACKNOWLEDGE +-- +-- ************************************************************** + +GNBDUConfigurationUpdateAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {GNBDUConfigurationUpdateAcknowledgeIEs} }, + ... +} + + +GNBDUConfigurationUpdateAcknowledgeIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-to-be-Activated-List CRITICALITY reject TYPE Cells-to-be-Activated-List PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-Cells-to-be-Deactivated-List CRITICALITY reject TYPE Cells-to-be-Deactivated-List PRESENCE optional }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }| + { ID id-UL-BH-Non-UP-Traffic-Mapping CRITICALITY reject TYPE UL-BH-Non-UP-Traffic-Mapping PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- GNB-DU CONFIGURATION UPDATE FAILURE +-- +-- ************************************************************** + +GNBDUConfigurationUpdateFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {GNBDUConfigurationUpdateFailureIEs} }, + ... +} + +GNBDUConfigurationUpdateFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- GNB-CU CONFIGURATION UPDATE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- GNB-CU CONFIGURATION UPDATE +-- +-- ************************************************************** + +GNBCUConfigurationUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { GNBCUConfigurationUpdateIEs} }, + ... +} + +GNBCUConfigurationUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-to-be-Activated-List CRITICALITY reject TYPE Cells-to-be-Activated-List PRESENCE optional }| + { ID id-Cells-to-be-Deactivated-List CRITICALITY reject TYPE Cells-to-be-Deactivated-List PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-To-Add-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Add-List PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-To-Remove-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Remove-List PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-To-Update-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Update-List PRESENCE optional }| + { ID id-Cells-to-be-Barred-List CRITICALITY ignore TYPE Cells-to-be-Barred-List PRESENCE optional }| + { ID id-Protected-EUTRA-Resources-List CRITICALITY reject TYPE Protected-EUTRA-Resources-List PRESENCE optional }| + { ID id-Neighbour-Cell-Information-List CRITICALITY ignore TYPE Neighbour-Cell-Information-List PRESENCE optional }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }| + { ID id-UL-BH-Non-UP-Traffic-Mapping CRITICALITY reject TYPE UL-BH-Non-UP-Traffic-Mapping PRESENCE optional }, + ... +} + +Cells-to-be-Deactivated-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-to-be-Deactivated-List-ItemIEs } } +GNB-CU-TNL-Association-To-Add-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-To-Add-ItemIEs } } +GNB-CU-TNL-Association-To-Remove-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-To-Remove-ItemIEs } } +GNB-CU-TNL-Association-To-Update-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-To-Update-ItemIEs } } +Cells-to-be-Barred-List ::= SEQUENCE(SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-to-be-Barred-ItemIEs } } + + +Cells-to-be-Deactivated-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-to-be-Deactivated-List-Item CRITICALITY reject TYPE Cells-to-be-Deactivated-List-Item PRESENCE mandatory }, + ... +} + + +GNB-CU-TNL-Association-To-Add-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-To-Add-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Add-Item PRESENCE mandatory }, + ... +} + +GNB-CU-TNL-Association-To-Remove-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-To-Remove-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Remove-Item PRESENCE mandatory }, + ... +} + +GNB-CU-TNL-Association-To-Update-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-To-Update-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-To-Update-Item PRESENCE mandatory }, + ... +} + +Cells-to-be-Barred-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-to-be-Barred-Item CRITICALITY ignore TYPE Cells-to-be-Barred-Item PRESENCE mandatory }, + ... +} + +Protected-EUTRA-Resources-List ::= SEQUENCE (SIZE(1.. maxCellineNB)) OF ProtocolIE-SingleContainer { { Protected-EUTRA-Resources-ItemIEs } } +Protected-EUTRA-Resources-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Protected-EUTRA-Resources-Item CRITICALITY reject TYPE Protected-EUTRA-Resources-Item PRESENCE mandatory}, + ... +} + +Neighbour-Cell-Information-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Neighbour-Cell-Information-ItemIEs } } +Neighbour-Cell-Information-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Neighbour-Cell-Information-Item CRITICALITY ignore TYPE Neighbour-Cell-Information-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- GNB-CU CONFIGURATION UPDATE ACKNOWLEDGE +-- +-- ************************************************************** + +GNBCUConfigurationUpdateAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { GNBCUConfigurationUpdateAcknowledgeIEs} }, + ... +} + + +GNBCUConfigurationUpdateAcknowledgeIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-Failed-to-be-Activated-List CRITICALITY reject TYPE Cells-Failed-to-be-Activated-List PRESENCE optional}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-Setup-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-Setup-List PRESENCE optional }| + { ID id-GNB-CU-TNL-Association-Failed-To-Setup-List CRITICALITY ignore TYPE GNB-CU-TNL-Association-Failed-To-Setup-List PRESENCE optional }| + { ID id-Dedicated-SIDelivery-NeededUE-List CRITICALITY ignore TYPE Dedicated-SIDelivery-NeededUE-List PRESENCE optional }| + { ID id-Transport-Layer-Address-Info CRITICALITY ignore TYPE Transport-Layer-Address-Info PRESENCE optional }, + ... +} + +Cells-Failed-to-be-Activated-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-Failed-to-be-Activated-List-ItemIEs } } +GNB-CU-TNL-Association-Setup-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-Setup-ItemIEs } } +GNB-CU-TNL-Association-Failed-To-Setup-List ::= SEQUENCE (SIZE(1.. maxnoofTNLAssociations)) OF ProtocolIE-SingleContainer { { GNB-CU-TNL-Association-Failed-To-Setup-ItemIEs } } + +Cells-Failed-to-be-Activated-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-Failed-to-be-Activated-List-Item CRITICALITY reject TYPE Cells-Failed-to-be-Activated-List-Item PRESENCE mandatory }, + ... +} + +GNB-CU-TNL-Association-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-Setup-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-Setup-Item PRESENCE mandatory }, + ... +} + + +GNB-CU-TNL-Association-Failed-To-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-GNB-CU-TNL-Association-Failed-To-Setup-Item CRITICALITY ignore TYPE GNB-CU-TNL-Association-Failed-To-Setup-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- GNB-CU CONFIGURATION UPDATE FAILURE +-- +-- ************************************************************** + +GNBCUConfigurationUpdateFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { GNBCUConfigurationUpdateFailureIEs} }, + ... +} + +GNBCUConfigurationUpdateFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- GNB-DU RESOURCE COORDINATION REQUEST +-- +-- ************************************************************** + +GNBDUResourceCoordinationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{GNBDUResourceCoordinationRequest-IEs}}, + ... +} + +GNBDUResourceCoordinationRequest-IEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-RequestType CRITICALITY reject TYPE RequestType PRESENCE mandatory }| + { ID id-EUTRA-NR-CellResourceCoordinationReq-Container CRITICALITY reject TYPE EUTRA-NR-CellResourceCoordinationReq-Container PRESENCE mandatory}| + { ID id-IgnoreResourceCoordinationContainer CRITICALITY reject TYPE IgnoreResourceCoordinationContainer PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- GNB-DU RESOURCE COORDINATION RESPONSE +-- +-- ************************************************************** + +GNBDUResourceCoordinationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{GNBDUResourceCoordinationResponse-IEs}}, + ... +} + +GNBDUResourceCoordinationResponse-IEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-EUTRA-NR-CellResourceCoordinationReqAck-Container CRITICALITY reject TYPE EUTRA-NR-CellResourceCoordinationReqAck-Container PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE Context Setup ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT SETUP REQUEST +-- +-- ************************************************************** + +UEContextSetupRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextSetupRequestIEs} }, + ... +} + +UEContextSetupRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-SpCell-ID CRITICALITY reject TYPE NRCGI PRESENCE mandatory }| + { ID id-ServCellIndex CRITICALITY reject TYPE ServCellIndex PRESENCE mandatory }| + { ID id-SpCellULConfigured CRITICALITY ignore TYPE CellULConfigured PRESENCE optional }| + { ID id-CUtoDURRCInformation CRITICALITY reject TYPE CUtoDURRCInformation PRESENCE mandatory}| + { ID id-Candidate-SpCell-List CRITICALITY ignore TYPE Candidate-SpCell-List PRESENCE optional }| + { ID id-DRXCycle CRITICALITY ignore TYPE DRXCycle PRESENCE optional }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-SCell-ToBeSetup-List CRITICALITY ignore TYPE SCell-ToBeSetup-List PRESENCE optional }| + { ID id-SRBs-ToBeSetup-List CRITICALITY reject TYPE SRBs-ToBeSetup-List PRESENCE optional }| + { ID id-DRBs-ToBeSetup-List CRITICALITY reject TYPE DRBs-ToBeSetup-List PRESENCE optional }| + { ID id-InactivityMonitoringRequest CRITICALITY reject TYPE InactivityMonitoringRequest PRESENCE optional }| + { ID id-RAT-FrequencyPriorityInformation CRITICALITY reject TYPE RAT-FrequencyPriorityInformation PRESENCE optional }| + { ID id-RRCContainer CRITICALITY ignore TYPE RRCContainer PRESENCE optional }| + { ID id-MaskedIMEISV CRITICALITY ignore TYPE MaskedIMEISV PRESENCE optional }| + { ID id-ServingPLMN CRITICALITY ignore TYPE PLMN-Identity PRESENCE optional }| + { ID id-GNB-DU-UE-AMBR-UL CRITICALITY ignore TYPE BitRate PRESENCE conditional }| + { ID id-RRCDeliveryStatusRequest CRITICALITY ignore TYPE RRCDeliveryStatusRequest PRESENCE optional }| + { ID id-ResourceCoordinationTransferInformation CRITICALITY ignore TYPE ResourceCoordinationTransferInformation PRESENCE optional }| + { ID id-ServingCellMO CRITICALITY ignore TYPE ServingCellMO PRESENCE optional }| + { ID id-new-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-RANUEID CRITICALITY ignore TYPE RANUEID PRESENCE optional }| + { ID id-TraceActivation CRITICALITY ignore TYPE TraceActivation PRESENCE optional }| + { ID id-AdditionalRRMPriorityIndex CRITICALITY ignore TYPE AdditionalRRMPriorityIndex PRESENCE optional }| + { ID id-BHChannels-ToBeSetup-List CRITICALITY reject TYPE BHChannels-ToBeSetup-List PRESENCE optional }| + { ID id-ConfiguredBAPAddress CRITICALITY reject TYPE BAPAddress PRESENCE optional }| + { ID id-NRV2XServicesAuthorized CRITICALITY ignore TYPE NRV2XServicesAuthorized PRESENCE optional }| + { ID id-LTEV2XServicesAuthorized CRITICALITY ignore TYPE LTEV2XServicesAuthorized PRESENCE optional }| + { ID id-NRUESidelinkAggregateMaximumBitrate CRITICALITY ignore TYPE NRUESidelinkAggregateMaximumBitrate PRESENCE optional }| + { ID id-LTEUESidelinkAggregateMaximumBitrate CRITICALITY ignore TYPE LTEUESidelinkAggregateMaximumBitrate PRESENCE optional }| + { ID id-PC5LinkAMBR CRITICALITY ignore TYPE BitRate PRESENCE optional}| + { ID id-SLDRBs-ToBeSetup-List CRITICALITY reject TYPE SLDRBs-ToBeSetup-List PRESENCE optional }| + { ID id-ConditionalInterDUMobilityInformation CRITICALITY reject TYPE ConditionalInterDUMobilityInformation PRESENCE optional}| + { ID id-ManagementBasedMDTPLMNList CRITICALITY ignore TYPE MDTPLMNList PRESENCE optional }| + { ID id-ServingNID CRITICALITY reject TYPE NID PRESENCE optional }, + ... +} + +Candidate-SpCell-List::= SEQUENCE (SIZE(1..maxnoofCandidateSpCells)) OF ProtocolIE-SingleContainer { { Candidate-SpCell-ItemIEs} } +SCell-ToBeSetup-List::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-ToBeSetup-ItemIEs} } +SRBs-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-ToBeSetup-ItemIEs} } +DRBs-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ToBeSetup-ItemIEs} } +BHChannels-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-ToBeSetup-ItemIEs} } +SLDRBs-ToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ToBeSetup-ItemIEs} } + +Candidate-SpCell-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Candidate-SpCell-Item CRITICALITY ignore TYPE Candidate-SpCell-Item PRESENCE mandatory }, + ... +} + + +SCell-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-ToBeSetup-Item CRITICALITY ignore TYPE SCell-ToBeSetup-Item PRESENCE mandatory }, + ... +} + +SRBs-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-ToBeSetup-Item CRITICALITY reject TYPE SRBs-ToBeSetup-Item PRESENCE mandatory}, + ... +} + +DRBs-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ToBeSetup-Item CRITICALITY reject TYPE DRBs-ToBeSetup-Item PRESENCE mandatory}, + ... +} + +BHChannels-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-ToBeSetup-Item CRITICALITY reject TYPE BHChannels-ToBeSetup-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ToBeSetup-Item CRITICALITY reject TYPE SLDRBs-ToBeSetup-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT SETUP RESPONSE +-- +-- ************************************************************** + +UEContextSetupResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextSetupResponseIEs} }, + ... +} + + +UEContextSetupResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-DUtoCURRCInformation CRITICALITY reject TYPE DUtoCURRCInformation PRESENCE mandatory }| + { ID id-C-RNTI CRITICALITY ignore TYPE C-RNTI PRESENCE optional }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-FullConfiguration CRITICALITY reject TYPE FullConfiguration PRESENCE optional }| + { ID id-DRBs-Setup-List CRITICALITY ignore TYPE DRBs-Setup-List PRESENCE optional }| + { ID id-SRBs-FailedToBeSetup-List CRITICALITY ignore TYPE SRBs-FailedToBeSetup-List PRESENCE optional }| + { ID id-DRBs-FailedToBeSetup-List CRITICALITY ignore TYPE DRBs-FailedToBeSetup-List PRESENCE optional }| + { ID id-SCell-FailedtoSetup-List CRITICALITY ignore TYPE SCell-FailedtoSetup-List PRESENCE optional }| + { ID id-InactivityMonitoringResponse CRITICALITY reject TYPE InactivityMonitoringResponse PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-SRBs-Setup-List CRITICALITY ignore TYPE SRBs-Setup-List PRESENCE optional }| + { ID id-BHChannels-Setup-List CRITICALITY ignore TYPE BHChannels-Setup-List PRESENCE optional }| + { ID id-BHChannels-FailedToBeSetup-List CRITICALITY ignore TYPE BHChannels-FailedToBeSetup-List PRESENCE optional }| + { ID id-SLDRBs-Setup-List CRITICALITY ignore TYPE SLDRBs-Setup-List PRESENCE optional }| + { ID id-SLDRBs-FailedToBeSetup-List CRITICALITY ignore TYPE SLDRBs-FailedToBeSetup-List PRESENCE optional }| + { ID id-requestedTargetCellGlobalID CRITICALITY reject TYPE NRCGI PRESENCE optional}, + ... +} + +DRBs-Setup-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-Setup-ItemIEs} } + + +SRBs-FailedToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-FailedToBeSetup-ItemIEs} } +DRBs-FailedToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-FailedToBeSetup-ItemIEs} } +SCell-FailedtoSetup-List ::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-FailedtoSetup-ItemIEs} } +SRBs-Setup-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-Setup-ItemIEs} } +BHChannels-Setup-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-Setup-ItemIEs} } +BHChannels-FailedToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-FailedToBeSetup-ItemIEs} } + +DRBs-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-Setup-Item CRITICALITY ignore TYPE DRBs-Setup-Item PRESENCE mandatory}, + ... +} + +SRBs-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-Setup-Item CRITICALITY ignore TYPE SRBs-Setup-Item PRESENCE mandatory}, + ... +} + +SRBs-FailedToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-FailedToBeSetup-Item CRITICALITY ignore TYPE SRBs-FailedToBeSetup-Item PRESENCE mandatory}, + ... +} + + +DRBs-FailedToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-FailedToBeSetup-Item CRITICALITY ignore TYPE DRBs-FailedToBeSetup-Item PRESENCE mandatory}, + ... +} + +SCell-FailedtoSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-FailedtoSetup-Item CRITICALITY ignore TYPE SCell-FailedtoSetup-Item PRESENCE mandatory}, + ... +} + +BHChannels-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-Setup-Item CRITICALITY ignore TYPE BHChannels-Setup-Item PRESENCE mandatory}, + ... +} + +BHChannels-FailedToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-FailedToBeSetup-Item CRITICALITY ignore TYPE BHChannels-FailedToBeSetup-Item PRESENCE mandatory}, + ... +} + +SLDRBs-Setup-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-Setup-ItemIEs} } + +SLDRBs-FailedToBeSetup-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-FailedToBeSetup-ItemIEs} } + +SLDRBs-Setup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-Setup-Item CRITICALITY ignore TYPE SLDRBs-Setup-Item PRESENCE mandatory}, + ... +} + +SLDRBs-FailedToBeSetup-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-FailedToBeSetup-Item CRITICALITY ignore TYPE SLDRBs-FailedToBeSetup-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT SETUP FAILURE +-- +-- ************************************************************** + +UEContextSetupFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextSetupFailureIEs} }, + ... +} + +UEContextSetupFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-Potential-SpCell-List CRITICALITY ignore TYPE Potential-SpCell-List PRESENCE optional }| + { ID id-requestedTargetCellGlobalID CRITICALITY reject TYPE NRCGI PRESENCE optional}, + ... +} + +Potential-SpCell-List::= SEQUENCE (SIZE(0..maxnoofPotentialSpCells)) OF ProtocolIE-SingleContainer { { Potential-SpCell-ItemIEs} } + +Potential-SpCell-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Potential-SpCell-Item CRITICALITY ignore TYPE Potential-SpCell-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE Context Release Request ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE Context Release Request +-- +-- ************************************************************** + +UEContextReleaseRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ UEContextReleaseRequestIEs}}, + ... +} + +UEContextReleaseRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-targetCellsToCancel CRITICALITY reject TYPE TargetCellList PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- UE Context Release (gNB-CU initiated) ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT RELEASE COMMAND +-- +-- ************************************************************** + +UEContextReleaseCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextReleaseCommandIEs} }, + ... +} + +UEContextReleaseCommandIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-RRCContainer CRITICALITY ignore TYPE RRCContainer PRESENCE optional }| + { ID id-SRBID CRITICALITY ignore TYPE SRBID PRESENCE conditional }| + { ID id-oldgNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-ExecuteDuplication CRITICALITY ignore TYPE ExecuteDuplication PRESENCE optional}| + { ID id-RRCDeliveryStatusRequest CRITICALITY ignore TYPE RRCDeliveryStatusRequest PRESENCE optional }| + { ID id-targetCellsToCancel CRITICALITY reject TYPE TargetCellList PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT RELEASE COMPLETE +-- +-- ************************************************************** + +UEContextReleaseComplete ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextReleaseCompleteIEs} }, + ... +} + + +UEContextReleaseCompleteIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE Context Modification ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION REQUEST +-- +-- ************************************************************** + +UEContextModificationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationRequestIEs} }, + ... +} + +UEContextModificationRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SpCell-ID CRITICALITY ignore TYPE NRCGI PRESENCE optional }| + { ID id-ServCellIndex CRITICALITY reject TYPE ServCellIndex PRESENCE optional }| + { ID id-SpCellULConfigured CRITICALITY ignore TYPE CellULConfigured PRESENCE optional }| + { ID id-DRXCycle CRITICALITY ignore TYPE DRXCycle PRESENCE optional }| + { ID id-CUtoDURRCInformation CRITICALITY reject TYPE CUtoDURRCInformation PRESENCE optional }| + { ID id-TransmissionActionIndicator CRITICALITY ignore TYPE TransmissionActionIndicator PRESENCE optional }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-RRCReconfigurationCompleteIndicator CRITICALITY ignore TYPE RRCReconfigurationCompleteIndicator PRESENCE optional }| + { ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE optional }| + { ID id-SCell-ToBeSetupMod-List CRITICALITY ignore TYPE SCell-ToBeSetupMod-List PRESENCE optional }| + { ID id-SCell-ToBeRemoved-List CRITICALITY ignore TYPE SCell-ToBeRemoved-List PRESENCE optional }| + { ID id-SRBs-ToBeSetupMod-List CRITICALITY reject TYPE SRBs-ToBeSetupMod-List PRESENCE optional }| + { ID id-DRBs-ToBeSetupMod-List CRITICALITY reject TYPE DRBs-ToBeSetupMod-List PRESENCE optional }| + { ID id-DRBs-ToBeModified-List CRITICALITY reject TYPE DRBs-ToBeModified-List PRESENCE optional }| + { ID id-SRBs-ToBeReleased-List CRITICALITY reject TYPE SRBs-ToBeReleased-List PRESENCE optional }| + { ID id-DRBs-ToBeReleased-List CRITICALITY reject TYPE DRBs-ToBeReleased-List PRESENCE optional }| + { ID id-InactivityMonitoringRequest CRITICALITY reject TYPE InactivityMonitoringRequest PRESENCE optional }| + { ID id-RAT-FrequencyPriorityInformation CRITICALITY reject TYPE RAT-FrequencyPriorityInformation PRESENCE optional }| + { ID id-DRXConfigurationIndicator CRITICALITY ignore TYPE DRXConfigurationIndicator PRESENCE optional }| + { ID id-RLCFailureIndication CRITICALITY ignore TYPE RLCFailureIndication PRESENCE optional }| + { ID id-UplinkTxDirectCurrentListInformation CRITICALITY ignore TYPE UplinkTxDirectCurrentListInformation PRESENCE optional }| + { ID id-GNB-DUConfigurationQuery CRITICALITY reject TYPE GNB-DUConfigurationQuery PRESENCE optional }| + { ID id-GNB-DU-UE-AMBR-UL CRITICALITY ignore TYPE BitRate PRESENCE optional }| + { ID id-ExecuteDuplication CRITICALITY ignore TYPE ExecuteDuplication PRESENCE optional}| + { ID id-RRCDeliveryStatusRequest CRITICALITY ignore TYPE RRCDeliveryStatusRequest PRESENCE optional }| + { ID id-ResourceCoordinationTransferInformation CRITICALITY ignore TYPE ResourceCoordinationTransferInformation PRESENCE optional }| + { ID id-ServingCellMO CRITICALITY ignore TYPE ServingCellMO PRESENCE optional }| + { ID id-NeedforGap CRITICALITY ignore TYPE NeedforGap PRESENCE optional }| + { ID id-FullConfiguration CRITICALITY reject TYPE FullConfiguration PRESENCE optional }| + { ID id-AdditionalRRMPriorityIndex CRITICALITY ignore TYPE AdditionalRRMPriorityIndex PRESENCE optional }| + { ID id-LowerLayerPresenceStatusChange CRITICALITY ignore TYPE LowerLayerPresenceStatusChange PRESENCE optional }| + { ID id-BHChannels-ToBeSetupMod-List CRITICALITY reject TYPE BHChannels-ToBeSetupMod-List PRESENCE optional }| + { ID id-BHChannels-ToBeModified-List CRITICALITY reject TYPE BHChannels-ToBeModified-List PRESENCE optional }| + { ID id-BHChannels-ToBeReleased-List CRITICALITY reject TYPE BHChannels-ToBeReleased-List PRESENCE optional }| + { ID id-NRV2XServicesAuthorized CRITICALITY ignore TYPE NRV2XServicesAuthorized PRESENCE optional }| + { ID id-LTEV2XServicesAuthorized CRITICALITY ignore TYPE LTEV2XServicesAuthorized PRESENCE optional }| + { ID id-NRUESidelinkAggregateMaximumBitrate CRITICALITY ignore TYPE NRUESidelinkAggregateMaximumBitrate PRESENCE optional }| + { ID id-LTEUESidelinkAggregateMaximumBitrate CRITICALITY ignore TYPE LTEUESidelinkAggregateMaximumBitrate PRESENCE optional }| + { ID id-PC5LinkAMBR CRITICALITY ignore TYPE BitRate PRESENCE optional}| + { ID id-SLDRBs-ToBeSetupMod-List CRITICALITY reject TYPE SLDRBs-ToBeSetupMod-List PRESENCE optional }| + { ID id-SLDRBs-ToBeModified-List CRITICALITY reject TYPE SLDRBs-ToBeModified-List PRESENCE optional }| + { ID id-SLDRBs-ToBeReleased-List CRITICALITY reject TYPE SLDRBs-ToBeReleased-List PRESENCE optional }| + { ID id-ConditionalIntraDUMobilityInformation CRITICALITY reject TYPE ConditionalIntraDUMobilityInformation PRESENCE optional}, + ... +} + +SCell-ToBeSetupMod-List::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-ToBeSetupMod-ItemIEs} } +SCell-ToBeRemoved-List::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-ToBeRemoved-ItemIEs} } +SRBs-ToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-ToBeSetupMod-ItemIEs} } +DRBs-ToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ToBeSetupMod-ItemIEs} } +BHChannels-ToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-ToBeSetupMod-ItemIEs} } + +DRBs-ToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ToBeModified-ItemIEs} } +BHChannels-ToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-ToBeModified-ItemIEs} } +SRBs-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-ToBeReleased-ItemIEs} } +DRBs-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ToBeReleased-ItemIEs} } +BHChannels-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-ToBeReleased-ItemIEs} } + +SCell-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-ToBeSetupMod-Item CRITICALITY ignore TYPE SCell-ToBeSetupMod-Item PRESENCE mandatory }, + ... +} + +SCell-ToBeRemoved-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-ToBeRemoved-Item CRITICALITY ignore TYPE SCell-ToBeRemoved-Item PRESENCE mandatory }, + ... +} + + +SRBs-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-ToBeSetupMod-Item CRITICALITY reject TYPE SRBs-ToBeSetupMod-Item PRESENCE mandatory}, + ... +} + + +DRBs-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ToBeSetupMod-Item CRITICALITY reject TYPE DRBs-ToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +DRBs-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ToBeModified-Item CRITICALITY reject TYPE DRBs-ToBeModified-Item PRESENCE mandatory}, + ... +} + + +SRBs-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-ToBeReleased-Item CRITICALITY reject TYPE SRBs-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +DRBs-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ToBeReleased-Item CRITICALITY reject TYPE DRBs-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +BHChannels-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-ToBeSetupMod-Item CRITICALITY reject TYPE BHChannels-ToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +BHChannels-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-ToBeModified-Item CRITICALITY reject TYPE BHChannels-ToBeModified-Item PRESENCE mandatory}, + ... +} + +BHChannels-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-ToBeReleased-Item CRITICALITY reject TYPE BHChannels-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ToBeSetupMod-ItemIEs} } +SLDRBs-ToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ToBeModified-ItemIEs} } +SLDRBs-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ToBeReleased-ItemIEs} } + +SLDRBs-ToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ToBeSetupMod-Item CRITICALITY reject TYPE SLDRBs-ToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ToBeModified-Item CRITICALITY reject TYPE SLDRBs-ToBeModified-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ToBeReleased-Item CRITICALITY reject TYPE SLDRBs-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION RESPONSE +-- +-- ************************************************************** + +UEContextModificationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationResponseIEs} }, + ... +} + + +UEContextModificationResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-DUtoCURRCInformation CRITICALITY reject TYPE DUtoCURRCInformation PRESENCE optional}| + { ID id-DRBs-SetupMod-List CRITICALITY ignore TYPE DRBs-SetupMod-List PRESENCE optional}| + { ID id-DRBs-Modified-List CRITICALITY ignore TYPE DRBs-Modified-List PRESENCE optional}| + { ID id-SRBs-FailedToBeSetupMod-List CRITICALITY ignore TYPE SRBs-FailedToBeSetupMod-List PRESENCE optional }| + { ID id-DRBs-FailedToBeSetupMod-List CRITICALITY ignore TYPE DRBs-FailedToBeSetupMod-List PRESENCE optional }| + { ID id-SCell-FailedtoSetupMod-List CRITICALITY ignore TYPE SCell-FailedtoSetupMod-List PRESENCE optional }| + { ID id-DRBs-FailedToBeModified-List CRITICALITY ignore TYPE DRBs-FailedToBeModified-List PRESENCE optional }| + { ID id-InactivityMonitoringResponse CRITICALITY reject TYPE InactivityMonitoringResponse PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-C-RNTI CRITICALITY ignore TYPE C-RNTI PRESENCE optional }| + { ID id-Associated-SCell-List CRITICALITY ignore TYPE Associated-SCell-List PRESENCE optional }| + { ID id-SRBs-SetupMod-List CRITICALITY ignore TYPE SRBs-SetupMod-List PRESENCE optional }| + { ID id-SRBs-Modified-List CRITICALITY ignore TYPE SRBs-Modified-List PRESENCE optional }| + { ID id-FullConfiguration CRITICALITY reject TYPE FullConfiguration PRESENCE optional }| + { ID id-BHChannels-SetupMod-List CRITICALITY ignore TYPE BHChannels-SetupMod-List PRESENCE optional}| + { ID id-BHChannels-Modified-List CRITICALITY ignore TYPE BHChannels-Modified-List PRESENCE optional}| + { ID id-BHChannels-FailedToBeSetupMod-List CRITICALITY ignore TYPE BHChannels-FailedToBeSetupMod-List PRESENCE optional }| + { ID id-BHChannels-FailedToBeModified-List CRITICALITY ignore TYPE BHChannels-FailedToBeModified-List PRESENCE optional }| + { ID id-SLDRBs-SetupMod-List CRITICALITY ignore TYPE SLDRBs-SetupMod-List PRESENCE optional }| + { ID id-SLDRBs-Modified-List CRITICALITY ignore TYPE SLDRBs-Modified-List PRESENCE optional }| + { ID id-SLDRBs-FailedToBeSetupMod-List CRITICALITY ignore TYPE SLDRBs-FailedToBeSetupMod-List PRESENCE optional }| + { ID id-SLDRBs-FailedToBeModified-List CRITICALITY ignore TYPE SLDRBs-FailedToBeModified-List PRESENCE optional }| + { ID id-requestedTargetCellGlobalID CRITICALITY reject TYPE NRCGI PRESENCE optional}, + ... +} + + +DRBs-SetupMod-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-SetupMod-ItemIEs} } +DRBs-Modified-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-Modified-ItemIEs } } +SRBs-SetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-SetupMod-ItemIEs} } +SRBs-Modified-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-Modified-ItemIEs } } +DRBs-FailedToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-FailedToBeModified-ItemIEs} } +SRBs-FailedToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-FailedToBeSetupMod-ItemIEs} } +DRBs-FailedToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-FailedToBeSetupMod-ItemIEs} } +SCell-FailedtoSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSCells)) OF ProtocolIE-SingleContainer { { SCell-FailedtoSetupMod-ItemIEs} } +BHChannels-SetupMod-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-SetupMod-ItemIEs} } +BHChannels-Modified-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-Modified-ItemIEs } } +BHChannels-FailedToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-FailedToBeModified-ItemIEs} } +BHChannels-FailedToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-FailedToBeSetupMod-ItemIEs} } + +Associated-SCell-List ::= SEQUENCE (SIZE(1.. maxnoofSCells)) OF ProtocolIE-SingleContainer { { Associated-SCell-ItemIEs} } + +DRBs-SetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-SetupMod-Item CRITICALITY ignore TYPE DRBs-SetupMod-Item PRESENCE mandatory}, + ... +} + + +DRBs-Modified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-Modified-Item CRITICALITY ignore TYPE DRBs-Modified-Item PRESENCE mandatory}, + ... +} + +SRBs-SetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-SetupMod-Item CRITICALITY ignore TYPE SRBs-SetupMod-Item PRESENCE mandatory}, + ... +} + + +SRBs-Modified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-Modified-Item CRITICALITY ignore TYPE SRBs-Modified-Item PRESENCE mandatory}, + ... +} + +SRBs-FailedToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-FailedToBeSetupMod-Item CRITICALITY ignore TYPE SRBs-FailedToBeSetupMod-Item PRESENCE mandatory}, + ... +} + + +DRBs-FailedToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-FailedToBeSetupMod-Item CRITICALITY ignore TYPE DRBs-FailedToBeSetupMod-Item PRESENCE mandatory}, + ... +} + + +DRBs-FailedToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-FailedToBeModified-Item CRITICALITY ignore TYPE DRBs-FailedToBeModified-Item PRESENCE mandatory}, + ... +} + +SCell-FailedtoSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SCell-FailedtoSetupMod-Item CRITICALITY ignore TYPE SCell-FailedtoSetupMod-Item PRESENCE mandatory}, + ... +} + +Associated-SCell-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Associated-SCell-Item CRITICALITY ignore TYPE Associated-SCell-Item PRESENCE mandatory}, + ... +} + +BHChannels-SetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-SetupMod-Item CRITICALITY ignore TYPE BHChannels-SetupMod-Item PRESENCE mandatory}, + ... +} + + +BHChannels-Modified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-Modified-Item CRITICALITY ignore TYPE BHChannels-Modified-Item PRESENCE mandatory}, + ... +} + +BHChannels-FailedToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-FailedToBeSetupMod-Item CRITICALITY ignore TYPE BHChannels-FailedToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +BHChannels-FailedToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-FailedToBeModified-Item CRITICALITY ignore TYPE BHChannels-FailedToBeModified-Item PRESENCE mandatory}, + ... +} + +SLDRBs-SetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-SetupMod-ItemIEs} } +SLDRBs-Modified-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-Modified-ItemIEs } } +SLDRBs-FailedToBeModified-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-FailedToBeModified-ItemIEs} } +SLDRBs-FailedToBeSetupMod-List ::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-FailedToBeSetupMod-ItemIEs} } + +SLDRBs-SetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-SetupMod-Item CRITICALITY ignore TYPE SLDRBs-SetupMod-Item PRESENCE mandatory}, + ... +} + +SLDRBs-Modified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-Modified-Item CRITICALITY ignore TYPE SLDRBs-Modified-Item PRESENCE mandatory}, + ... +} + +SLDRBs-FailedToBeSetupMod-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-FailedToBeSetupMod-Item CRITICALITY ignore TYPE SLDRBs-FailedToBeSetupMod-Item PRESENCE mandatory}, + ... +} + +SLDRBs-FailedToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-FailedToBeModified-Item CRITICALITY ignore TYPE SLDRBs-FailedToBeModified-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION FAILURE +-- +-- ************************************************************** + +UEContextModificationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationFailureIEs} }, + ... +} + +UEContextModificationFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-requestedTargetCellGlobalID CRITICALITY reject TYPE NRCGI PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- UE Context Modification Required (gNB-DU initiated) ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION REQUIRED +-- +-- ************************************************************** + +UEContextModificationRequired ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationRequiredIEs} }, + ... +} + +UEContextModificationRequiredIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-DUtoCURRCInformation CRITICALITY reject TYPE DUtoCURRCInformation PRESENCE optional}| + { ID id-DRBs-Required-ToBeModified-List CRITICALITY reject TYPE DRBs-Required-ToBeModified-List PRESENCE optional}| + { ID id-SRBs-Required-ToBeReleased-List CRITICALITY reject TYPE SRBs-Required-ToBeReleased-List PRESENCE optional}| + { ID id-DRBs-Required-ToBeReleased-List CRITICALITY reject TYPE DRBs-Required-ToBeReleased-List PRESENCE optional}| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-BHChannels-Required-ToBeReleased-List CRITICALITY reject TYPE BHChannels-Required-ToBeReleased-List PRESENCE optional}| + { ID id-SLDRBs-Required-ToBeModified-List CRITICALITY reject TYPE SLDRBs-Required-ToBeModified-List PRESENCE optional}| + { ID id-SLDRBs-Required-ToBeReleased-List CRITICALITY reject TYPE SLDRBs-Required-ToBeReleased-List PRESENCE optional}| + { ID id-targetCellsToCancel CRITICALITY reject TYPE TargetCellList PRESENCE optional}, + ... +} + +DRBs-Required-ToBeModified-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-Required-ToBeModified-ItemIEs } } +DRBs-Required-ToBeReleased-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-Required-ToBeReleased-ItemIEs } } + +SRBs-Required-ToBeReleased-List::= SEQUENCE (SIZE(1..maxnoofSRBs)) OF ProtocolIE-SingleContainer { { SRBs-Required-ToBeReleased-ItemIEs } } + +BHChannels-Required-ToBeReleased-List ::= SEQUENCE (SIZE(1..maxnoofBHRLCChannels)) OF ProtocolIE-SingleContainer { { BHChannels-Required-ToBeReleased-ItemIEs } } + +DRBs-Required-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-Required-ToBeModified-Item CRITICALITY reject TYPE DRBs-Required-ToBeModified-Item PRESENCE mandatory}, + ... +} + +DRBs-Required-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-Required-ToBeReleased-Item CRITICALITY reject TYPE DRBs-Required-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +SRBs-Required-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SRBs-Required-ToBeReleased-Item CRITICALITY reject TYPE SRBs-Required-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +BHChannels-Required-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BHChannels-Required-ToBeReleased-Item CRITICALITY reject TYPE BHChannels-Required-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +SLDRBs-Required-ToBeModified-List::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-Required-ToBeModified-ItemIEs } } +SLDRBs-Required-ToBeReleased-List::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-Required-ToBeReleased-ItemIEs } } + +SLDRBs-Required-ToBeModified-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-Required-ToBeModified-Item CRITICALITY reject TYPE SLDRBs-Required-ToBeModified-Item PRESENCE mandatory}, + ... +} + +SLDRBs-Required-ToBeReleased-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-Required-ToBeReleased-Item CRITICALITY reject TYPE SLDRBs-Required-ToBeReleased-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION CONFIRM +-- +-- ************************************************************** + +UEContextModificationConfirm::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationConfirmIEs} }, + ... +} + + +UEContextModificationConfirmIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-ResourceCoordinationTransferContainer CRITICALITY ignore TYPE ResourceCoordinationTransferContainer PRESENCE optional }| + { ID id-DRBs-ModifiedConf-List CRITICALITY ignore TYPE DRBs-ModifiedConf-List PRESENCE optional}| + { ID id-RRCContainer CRITICALITY ignore TYPE RRCContainer PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-ExecuteDuplication CRITICALITY ignore TYPE ExecuteDuplication PRESENCE optional}| + { ID id-ResourceCoordinationTransferInformation CRITICALITY ignore TYPE ResourceCoordinationTransferInformation PRESENCE optional }| + { ID id-SLDRBs-ModifiedConf-List CRITICALITY ignore TYPE SLDRBs-ModifiedConf-List PRESENCE optional}, + ... +} + +DRBs-ModifiedConf-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRBs-ModifiedConf-ItemIEs } } + +DRBs-ModifiedConf-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRBs-ModifiedConf-Item CRITICALITY ignore TYPE DRBs-ModifiedConf-Item PRESENCE mandatory}, + ... +} + +SLDRBs-ModifiedConf-List::= SEQUENCE (SIZE(1..maxnoofSLDRBs)) OF ProtocolIE-SingleContainer { { SLDRBs-ModifiedConf-ItemIEs } } + +SLDRBs-ModifiedConf-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-SLDRBs-ModifiedConf-Item CRITICALITY ignore TYPE SLDRBs-ModifiedConf-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION REFUSE +-- +-- ************************************************************** + +UEContextModificationRefuse::= SEQUENCE { + protocolIEs ProtocolIE-Container { { UEContextModificationRefuseIEs} }, + ... +} + + +UEContextModificationRefuseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- WRITE-REPLACE WARNING ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Write-Replace Warning Request +-- +-- ************************************************************** + +WriteReplaceWarningRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {WriteReplaceWarningRequestIEs} }, + ... +} + +WriteReplaceWarningRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-PWSSystemInformation CRITICALITY reject TYPE PWSSystemInformation PRESENCE mandatory }| + { ID id-RepetitionPeriod CRITICALITY reject TYPE RepetitionPeriod PRESENCE mandatory }| + { ID id-NumberofBroadcastRequest CRITICALITY reject TYPE NumberofBroadcastRequest PRESENCE mandatory }| + { ID id-Cells-To-Be-Broadcast-List CRITICALITY reject TYPE Cells-To-Be-Broadcast-List PRESENCE optional }, + ... +} + +Cells-To-Be-Broadcast-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-To-Be-Broadcast-List-ItemIEs } } + +Cells-To-Be-Broadcast-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-To-Be-Broadcast-Item CRITICALITY reject TYPE Cells-To-Be-Broadcast-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- Write-Replace Warning Response +-- +-- ************************************************************** + +WriteReplaceWarningResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {WriteReplaceWarningResponseIEs} }, + ... +} + +WriteReplaceWarningResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-Broadcast-Completed-List CRITICALITY reject TYPE Cells-Broadcast-Completed-List PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-Dedicated-SIDelivery-NeededUE-List CRITICALITY ignore TYPE Dedicated-SIDelivery-NeededUE-List PRESENCE optional }, + ... +} + +Cells-Broadcast-Completed-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-Broadcast-Completed-List-ItemIEs } } + +Cells-Broadcast-Completed-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-Broadcast-Completed-Item CRITICALITY reject TYPE Cells-Broadcast-Completed-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- PWS CANCEL ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS Cancel Request +-- +-- ************************************************************** + +PWSCancelRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PWSCancelRequestIEs} }, + ... +} + +PWSCancelRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-NumberofBroadcastRequest CRITICALITY reject TYPE NumberofBroadcastRequest PRESENCE mandatory }| + { ID id-Broadcast-To-Be-Cancelled-List CRITICALITY reject TYPE Broadcast-To-Be-Cancelled-List PRESENCE optional }| + { ID id-Cancel-all-Warning-Messages-Indicator CRITICALITY reject TYPE Cancel-all-Warning-Messages-Indicator PRESENCE optional }| + { ID id-NotificationInformation CRITICALITY reject TYPE NotificationInformation PRESENCE optional}, + ... +} + +Broadcast-To-Be-Cancelled-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Broadcast-To-Be-Cancelled-List-ItemIEs } } + +Broadcast-To-Be-Cancelled-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Broadcast-To-Be-Cancelled-Item CRITICALITY reject TYPE Broadcast-To-Be-Cancelled-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PWS Cancel Response +-- +-- ************************************************************** + +PWSCancelResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PWSCancelResponseIEs} }, + ... +} + +PWSCancelResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cells-Broadcast-Cancelled-List CRITICALITY reject TYPE Cells-Broadcast-Cancelled-List PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +Cells-Broadcast-Cancelled-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { Cells-Broadcast-Cancelled-List-ItemIEs } } + +Cells-Broadcast-Cancelled-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-Cells-Broadcast-Cancelled-Item CRITICALITY reject TYPE Cells-Broadcast-Cancelled-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE Inactivity Notification ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE Inactivity Notification +-- +-- ************************************************************** + +UEInactivityNotification ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ UEInactivityNotificationIEs}}, + ... +} + +UEInactivityNotificationIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-DRB-Activity-List CRITICALITY reject TYPE DRB-Activity-List PRESENCE mandatory } , + ... +} + +DRB-Activity-List::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRB-Activity-ItemIEs } } + +DRB-Activity-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRB-Activity-Item CRITICALITY reject TYPE DRB-Activity-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- Initial UL RRC Message Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- INITIAL UL RRC Message Transfer +-- +-- ************************************************************** + +InitialULRRCMessageTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ InitialULRRCMessageTransferIEs}}, + ... +} + +InitialULRRCMessageTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-NRCGI CRITICALITY reject TYPE NRCGI PRESENCE mandatory }| + { ID id-C-RNTI CRITICALITY reject TYPE C-RNTI PRESENCE mandatory }| + { ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE mandatory }| + { ID id-DUtoCURRCContainer CRITICALITY reject TYPE DUtoCURRCContainer PRESENCE optional }| + { ID id-SULAccessIndication CRITICALITY ignore TYPE SULAccessIndication PRESENCE optional }| + { ID id-TransactionID CRITICALITY ignore TYPE TransactionID PRESENCE mandatory }| + { ID id-RANUEID CRITICALITY ignore TYPE RANUEID PRESENCE optional }| + { ID id-RRCContainer-RRCSetupComplete CRITICALITY ignore TYPE RRCContainer-RRCSetupComplete PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- DL RRC Message Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- DL RRC Message Transfer +-- +-- ************************************************************** + +DLRRCMessageTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ DLRRCMessageTransferIEs}}, + ... +} + +DLRRCMessageTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-oldgNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }| + { ID id-SRBID CRITICALITY reject TYPE SRBID PRESENCE mandatory }| + { ID id-ExecuteDuplication CRITICALITY ignore TYPE ExecuteDuplication PRESENCE optional}| + { ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE mandatory }| + { ID id-RAT-FrequencyPriorityInformation CRITICALITY reject TYPE RAT-FrequencyPriorityInformation PRESENCE optional }| + { ID id-RRCDeliveryStatusRequest CRITICALITY ignore TYPE RRCDeliveryStatusRequest PRESENCE optional }| + { ID id-UEContextNotRetrievable CRITICALITY reject TYPE UEContextNotRetrievable PRESENCE optional }| + { ID id-RedirectedRRCmessage CRITICALITY reject TYPE OCTET STRING PRESENCE optional }| + { ID id-PLMNAssistanceInfoForNetShar CRITICALITY ignore TYPE PLMN-Identity PRESENCE optional }| + { ID id-new-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE optional }| + { ID id-AdditionalRRMPriorityIndex CRITICALITY ignore TYPE AdditionalRRMPriorityIndex PRESENCE optional }, + ... +} +-- ************************************************************** +-- +-- UL RRC Message Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UL RRC Message Transfer +-- +-- ************************************************************** + +ULRRCMessageTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ ULRRCMessageTransferIEs}}, + ... +} + +ULRRCMessageTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SRBID CRITICALITY reject TYPE SRBID PRESENCE mandatory }| + { ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE mandatory }| + { ID id-SelectedPLMNID CRITICALITY reject TYPE PLMN-Identity PRESENCE optional }| + { ID id-new-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PRIVATE MESSAGE +-- +-- ************************************************************** + +PrivateMessage ::= SEQUENCE { + privateIEs PrivateIE-Container {{PrivateMessage-IEs}}, + ... +} + +PrivateMessage-IEs F1AP-PRIVATE-IES ::= { + ... +} + + +-- ************************************************************** +-- +-- System Information ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- System information Delivery Command +-- +-- ************************************************************** + +SystemInformationDeliveryCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ SystemInformationDeliveryCommandIEs}}, + ... +} + +SystemInformationDeliveryCommandIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-NRCGI CRITICALITY reject TYPE NRCGI PRESENCE mandatory }| + { ID id-SItype-List CRITICALITY reject TYPE SItype-List PRESENCE mandatory }| + { ID id-ConfirmedUEID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- Paging PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Paging +-- +-- ************************************************************** + +Paging ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ PagingIEs}}, + ... +} + +PagingIEs F1AP-PROTOCOL-IES ::= { + { ID id-UEIdentityIndexValue CRITICALITY reject TYPE UEIdentityIndexValue PRESENCE mandatory }| + { ID id-PagingIdentity CRITICALITY reject TYPE PagingIdentity PRESENCE mandatory }| + { ID id-PagingDRX CRITICALITY ignore TYPE PagingDRX PRESENCE optional }| + { ID id-PagingPriority CRITICALITY ignore TYPE PagingPriority PRESENCE optional }| + { ID id-PagingCell-List CRITICALITY ignore TYPE PagingCell-list PRESENCE mandatory }| + { ID id-PagingOrigin CRITICALITY ignore TYPE PagingOrigin PRESENCE optional }, + ... +} + +PagingCell-list::= SEQUENCE (SIZE(1.. maxnoofPagingCells)) OF ProtocolIE-SingleContainer { { PagingCell-ItemIEs } } + +PagingCell-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-PagingCell-Item CRITICALITY ignore TYPE PagingCell-Item PRESENCE mandatory} , + ... +} + + + +-- ************************************************************** +-- +-- Notify +-- +-- ************************************************************** + +Notify ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ NotifyIEs}}, + ... +} + +NotifyIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-DRB-Notify-List CRITICALITY reject TYPE DRB-Notify-List PRESENCE mandatory }, + ... +} + +DRB-Notify-List::= SEQUENCE (SIZE(1.. maxnoofDRBs)) OF ProtocolIE-SingleContainer { { DRB-Notify-ItemIEs } } + +DRB-Notify-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DRB-Notify-Item CRITICALITY reject TYPE DRB-Notify-Item PRESENCE mandatory}, + ... +} + + +-- ************************************************************** +-- +-- NETWORK ACCESS RATE REDUCTION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Network Access Rate Reduction +-- +-- ************************************************************** + +NetworkAccessRateReduction ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ NetworkAccessRateReductionIEs }}, + ... +} + +NetworkAccessRateReductionIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-UAC-Assistance-Info CRITICALITY reject TYPE UAC-Assistance-Info PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PWS RESTART INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS Restart Indication +-- +-- ************************************************************** + +PWSRestartIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PWSRestartIndicationIEs} }, + ... +} + +PWSRestartIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-NR-CGI-List-For-Restart-List CRITICALITY reject TYPE NR-CGI-List-For-Restart-List PRESENCE mandatory }, + ... +} + +NR-CGI-List-For-Restart-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { NR-CGI-List-For-Restart-List-ItemIEs } } + +NR-CGI-List-For-Restart-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-NR-CGI-List-For-Restart-Item CRITICALITY reject TYPE NR-CGI-List-For-Restart-Item PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PWS FAILURE INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS Failure Indication +-- +-- ************************************************************** + +PWSFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PWSFailureIndicationIEs} }, + ... +} + +PWSFailureIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-PWS-Failed-NR-CGI-List CRITICALITY reject TYPE PWS-Failed-NR-CGI-List PRESENCE optional }, + ... +} + +PWS-Failed-NR-CGI-List ::= SEQUENCE (SIZE(1.. maxCellingNBDU)) OF ProtocolIE-SingleContainer { { PWS-Failed-NR-CGI-List-ItemIEs } } + +PWS-Failed-NR-CGI-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-PWS-Failed-NR-CGI-Item CRITICALITY reject TYPE PWS-Failed-NR-CGI-Item PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- gNB-DU STATUS INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- gNB-DU Status Indication +-- +-- ************************************************************** + +GNBDUStatusIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {GNBDUStatusIndicationIEs} }, + ... +} + +GNBDUStatusIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-GNBDUOverloadInformation CRITICALITY reject TYPE GNBDUOverloadInformation PRESENCE mandatory }, + ... +} + + + +-- ************************************************************** +-- +-- RRC Delivery Report ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- RRC Delivery Report +-- +-- ************************************************************** + +RRCDeliveryReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ RRCDeliveryReportIEs}}, + ... +} + +RRCDeliveryReportIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-RRCDeliveryStatus CRITICALITY ignore TYPE RRCDeliveryStatus PRESENCE mandatory }| + { ID id-SRBID CRITICALITY ignore TYPE SRBID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- F1 Removal ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- F1 Removal Request +-- +-- ************************************************************** + +F1RemovalRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ F1RemovalRequestIEs }}, + ... +} + +F1RemovalRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- F1 Removal Response +-- +-- ************************************************************** + +F1RemovalResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ F1RemovalResponseIEs }}, + ... +} + +F1RemovalResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + + ... +} + +-- ************************************************************** +-- +-- F1 Removal Failure +-- +-- ************************************************************** + +F1RemovalFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ F1RemovalFailureIEs }}, + ... +} + +F1RemovalFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + + ... +} + + +-- ************************************************************** +-- +-- TRACE ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- TRACE START +-- +-- ************************************************************** + +TraceStart ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {TraceStartIEs} }, + ... +} + +TraceStartIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-TraceActivation CRITICALITY ignore TYPE TraceActivation PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- DEACTIVATE TRACE +-- +-- ************************************************************** + +DeactivateTrace ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {DeactivateTraceIEs} }, + ... +} + +DeactivateTraceIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-TraceID CRITICALITY ignore TYPE TraceID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- CELL TRAFFIC TRACE +-- +-- ************************************************************** + +CellTrafficTrace ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {CellTrafficTraceIEs} }, + ... +} + +CellTrafficTraceIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + {ID id-TraceID CRITICALITY ignore TYPE TraceID PRESENCE mandatory }| + {ID id-TraceCollectionEntityIPAddress CRITICALITY ignore TYPE TransportLayerAddress PRESENCE mandatory }| + {ID id-PrivacyIndicator CRITICALITY ignore TYPE PrivacyIndicator PRESENCE optional }| + + {ID id-TraceCollectionEntityURI CRITICALITY ignore TYPE URI-address PRESENCE optional }, + ... + +} + +-- ************************************************************** +-- +-- DU-CU Radio Information Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- DU-CU Radio Information Transfer +-- +-- ************************************************************** + +DUCURadioInformationTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ DUCURadioInformationTransferIEs}}, + ... +} + +DUCURadioInformationTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-DUCURadioInformationType CRITICALITY ignore TYPE DUCURadioInformationType PRESENCE mandatory }, + ... +} + + + +-- ************************************************************** +-- +-- CU-DU Radio Information Transfer ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- CU-DU Radio Information Transfer +-- +-- ************************************************************** + +CUDURadioInformationTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ CUDURadioInformationTransferIEs}}, + ... +} + +CUDURadioInformationTransferIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-CUDURadioInformationType CRITICALITY ignore TYPE CUDURadioInformationType PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- IAB PROCEDURES +-- +-- ************************************************************** +-- ************************************************************** +-- +-- BAP Mapping Configuration ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- BAP MAPPING CONFIGURATION +-- ************************************************************** + + +BAPMappingConfiguration ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {BAPMappingConfiguration-IEs} }, + ... + } + +BAPMappingConfiguration-IEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-BH-Routing-Information-Added-List CRITICALITY ignore TYPE BH-Routing-Information-Added-List PRESENCE optional}| + { ID id-BH-Routing-Information-Removed-List CRITICALITY ignore TYPE BH-Routing-Information-Removed-List PRESENCE optional}| + { ID id-TrafficMappingInformation CRITICALITY ignore TYPE TrafficMappingInfo PRESENCE optional}, + ... +} + +BH-Routing-Information-Added-List ::= SEQUENCE (SIZE(1.. maxnoofRoutingEntries)) OF ProtocolIE-SingleContainer { { BH-Routing-Information-Added-List-ItemIEs } } +BH-Routing-Information-Removed-List ::= SEQUENCE (SIZE(1.. maxnoofRoutingEntries)) OF ProtocolIE-SingleContainer { { BH-Routing-Information-Removed-List-ItemIEs } } + +BH-Routing-Information-Added-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BH-Routing-Information-Added-List-Item CRITICALITY ignore TYPE BH-Routing-Information-Added-List-Item PRESENCE optional}, + ... +} + +BH-Routing-Information-Removed-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-BH-Routing-Information-Removed-List-Item CRITICALITY ignore TYPE BH-Routing-Information-Removed-List-Item PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- BAP MAPPING CONFIGURATION ACKNOWLEDGE +-- ************************************************************** + +BAPMappingConfigurationAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {BAPMappingConfigurationAcknowledge-IEs} }, + ... +} + +BAPMappingConfigurationAcknowledge-IEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional}, + ... +} + + + +-- ************************************************************** +-- +-- GNB-DU Configuration ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- GNB-DU RESOURCE CONFIGURATION +-- ************************************************************** + + +GNBDUResourceConfiguration ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ GNBDUResourceConfigurationIEs}}, + ... +} + + +GNBDUResourceConfigurationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Activated-Cells-to-be-Updated-List CRITICALITY reject TYPE Activated-Cells-to-be-Updated-List PRESENCE optional}| + { ID id-Child-Nodes-List CRITICALITY reject TYPE Child-Nodes-List PRESENCE optional}, + ... +} + + + + +-- ************************************************************** +-- +-- GNB-DU RESOURCE CONFIGURATION ACKNOWLEDGE +-- ************************************************************** + + +GNBDUResourceConfigurationAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { GNBDUResourceConfigurationAcknowledgeIEs} }, + ... +} + + +GNBDUResourceConfigurationAcknowledgeIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- IAB TNL Address Allocation ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- IAB TNL ADDRESS REQUEST +-- ************************************************************** + + + +IABTNLAddressRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {IABTNLAddressRequestIEs} }, + ... +} + +IABTNLAddressRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-IABv4AddressesRequested CRITICALITY reject TYPE IABv4AddressesRequested PRESENCE optional }| + { ID id-IABIPv6RequestType CRITICALITY reject TYPE IABIPv6RequestType PRESENCE optional }| + { ID id-IAB-TNL-Addresses-To-Remove-List CRITICALITY reject TYPE IAB-TNL-Addresses-To-Remove-List PRESENCE optional }, + ... +} + + +IAB-TNL-Addresses-To-Remove-List ::= SEQUENCE (SIZE(1..maxnoofTLAsIAB)) OF ProtocolIE-SingleContainer { { IAB-TNL-Addresses-To-Remove-ItemIEs } } + +IAB-TNL-Addresses-To-Remove-ItemIEs F1AP-PROTOCOL-IES::= { + { ID id-IAB-TNL-Addresses-To-Remove-Item CRITICALITY reject TYPE IAB-TNL-Addresses-To-Remove-Item PRESENCE mandatory}, + ... +} + + +-- ************************************************************** +-- +-- IAB TNL ADDRESS RESPONSE +-- ************************************************************** + + +IABTNLAddressResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {IABTNLAddressResponseIEs} }, + ... +} + + +IABTNLAddressResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-IAB-Allocated-TNL-Address-List CRITICALITY reject TYPE IAB-Allocated-TNL-Address-List PRESENCE mandatory }, + ... +} + + +IAB-Allocated-TNL-Address-List ::= SEQUENCE (SIZE(1.. maxnoofTLAsIAB)) OF ProtocolIE-SingleContainer { { IAB-Allocated-TNL-Address-List-ItemIEs } } + + +IAB-Allocated-TNL-Address-List-ItemIEs F1AP-PROTOCOL-IES::= { + { ID id-IAB-Allocated-TNL-Address-Item CRITICALITY reject TYPE IAB-Allocated-TNL-Address-Item PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- IAB UP Configuration Update ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- IAB UP Configuration Update Request +-- +-- ************************************************************** + +IABUPConfigurationUpdateRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { IABUPConfigurationUpdateRequestIEs} }, + ... +} + +IABUPConfigurationUpdateRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-UL-UP-TNL-Information-to-Update-List CRITICALITY ignore TYPE UL-UP-TNL-Information-to-Update-List PRESENCE optional }| + { ID id-UL-UP-TNL-Address-to-Update-List CRITICALITY ignore TYPE UL-UP-TNL-Address-to-Update-List PRESENCE optional }, + ... +} + +UL-UP-TNL-Information-to-Update-List ::= SEQUENCE (SIZE(1.. maxnoofULUPTNLInformationforIAB)) OF ProtocolIE-SingleContainer { { UL-UP-TNL-Information-to-Update-List-ItemIEs } } + +UL-UP-TNL-Information-to-Update-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-UL-UP-TNL-Information-to-Update-List-Item CRITICALITY ignore TYPE UL-UP-TNL-Information-to-Update-List-Item PRESENCE optional}, + ... +} + +UL-UP-TNL-Address-to-Update-List ::= SEQUENCE (SIZE(1.. maxnoofUPTNLAddresses)) OF ProtocolIE-SingleContainer { { UL-UP-TNL-Address-to-Update-List-ItemIEs } } + +UL-UP-TNL-Address-to-Update-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-UL-UP-TNL-Address-to-Update-List-Item CRITICALITY ignore TYPE UL-UP-TNL-Address-to-Update-List-Item PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- IAB UP Configuration Update Response +-- +-- ************************************************************** + +IABUPConfigurationUpdateResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { IABUPConfigurationUpdateResponseIEs} }, + ... +} + +IABUPConfigurationUpdateResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-DL-UP-TNL-Address-to-Update-List CRITICALITY reject TYPE DL-UP-TNL-Address-to-Update-List PRESENCE optional }, + ... +} + +DL-UP-TNL-Address-to-Update-List ::= SEQUENCE (SIZE(1.. maxnoofUPTNLAddresses)) OF ProtocolIE-SingleContainer { { DL-UP-TNL-Address-to-Update-List-ItemIEs } } + +DL-UP-TNL-Address-to-Update-List-ItemIEs F1AP-PROTOCOL-IES ::= { + { ID id-DL-UP-TNL-Address-to-Update-List-Item CRITICALITY ignore TYPE DL-UP-TNL-Address-to-Update-List-Item PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- IAB UP Configuration Update Failure +-- +-- ************************************************************** + +IABUPConfigurationUpdateFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { IABUPConfigurationUpdateFailureIEs} }, + ... +} + +IABUPConfigurationUpdateFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Resource Status Reporting Initiation ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Resource Status Request +-- +-- ************************************************************** + +ResourceStatusRequest::= SEQUENCE { + protocolIEs ProtocolIE-Container { {ResourceStatusRequestIEs} }, + ... +} + +ResourceStatusRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNBCUMeasurementID CRITICALITY reject TYPE GNBCUMeasurementID PRESENCE mandatory }| + { ID id-gNBDUMeasurementID CRITICALITY ignore TYPE GNBDUMeasurementID PRESENCE conditional }| + { ID id-RegistrationRequest CRITICALITY ignore TYPE RegistrationRequest PRESENCE mandatory }| + { ID id-ReportCharacteristics CRITICALITY ignore TYPE ReportCharacteristics PRESENCE conditional }| + { ID id-CellToReportList CRITICALITY ignore TYPE CellToReportList PRESENCE optional }| + { ID id-ReportingPeriodicity CRITICALITY ignore TYPE ReportingPeriodicity PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- Resource Status Response +-- +-- ************************************************************** + +ResourceStatusResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { ResourceStatusResponseIEs} }, + ... +} + + +ResourceStatusResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNBCUMeasurementID CRITICALITY reject TYPE GNBCUMeasurementID PRESENCE mandatory }| + { ID id-gNBDUMeasurementID CRITICALITY ignore TYPE GNBDUMeasurementID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- Resource Status Failure +-- +-- ************************************************************** + +ResourceStatusFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { ResourceStatusFailureIEs} }, + ... +} + +ResourceStatusFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNBCUMeasurementID CRITICALITY reject TYPE GNBCUMeasurementID PRESENCE mandatory }| + { ID id-gNBDUMeasurementID CRITICALITY ignore TYPE GNBDUMeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Resource Status Reporting ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Resource Status Update +-- +-- ************************************************************** + +ResourceStatusUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ ResourceStatusUpdateIEs}}, + ... +} + +ResourceStatusUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-gNBCUMeasurementID CRITICALITY reject TYPE GNBCUMeasurementID PRESENCE mandatory }| + { ID id-gNBDUMeasurementID CRITICALITY ignore TYPE GNBDUMeasurementID PRESENCE mandatory }| + { ID id-HardwareLoadIndicator CRITICALITY ignore TYPE HardwareLoadIndicator PRESENCE optional }| + { ID id-TNLCapacityIndicator CRITICALITY ignore TYPE TNLCapacityIndicator PRESENCE optional }| + { ID id-CellMeasurementResultList CRITICALITY ignore TYPE CellMeasurementResultList PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Access And Mobility Indication ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Access And Mobility Indication +-- +-- ************************************************************** + +AccessAndMobilityIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { AccessAndMobilityIndicationIEs} }, + ... +} + +AccessAndMobilityIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-RACHReportInformationList CRITICALITY ignore TYPE RACHReportInformationList PRESENCE optional }| + { ID id-RLFReportInformationList CRITICALITY ignore TYPE RLFReportInformationList PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- REFERENCE TIME INFORMATION REPORTING CONTROL +-- +-- ************************************************************** + +ReferenceTimeInformationReportingControl::= SEQUENCE { + protocolIEs ProtocolIE-Container { { ReferenceTimeInformationReportingControlIEs} }, + ... +} + +ReferenceTimeInformationReportingControlIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-ReportingRequestType CRITICALITY reject TYPE ReportingRequestType PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- REFERENCE TIME INFORMATION REPORT +-- +-- ************************************************************** + +ReferenceTimeInformationReport::= SEQUENCE { + protocolIEs ProtocolIE-Container { { ReferenceTimeInformationReportIEs} }, + ... +} + +ReferenceTimeInformationReportIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY ignore TYPE TransactionID PRESENCE mandatory }| + { ID id-TimeReferenceInformation CRITICALITY ignore TYPE TimeReferenceInformation PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- Access Success +-- +-- ************************************************************** + +AccessSuccess ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ AccessSuccessIEs}}, + ... +} + +AccessSuccessIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-NRCGI CRITICALITY reject TYPE NRCGI PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING ASSISTANCE INFORMATION CONTROL ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Assistance Information Control +-- +-- ************************************************************** + +PositioningAssistanceInformationControl ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ PositioningAssistanceInformationControlIEs}}, + ... +} + +PositioningAssistanceInformationControlIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-PosAssistance-Information CRITICALITY reject TYPE PosAssistance-Information PRESENCE optional}| + { ID id-PosBroadcast CRITICALITY reject TYPE PosBroadcast PRESENCE optional}| + { ID id-PositioningBroadcastCells CRITICALITY reject TYPE PositioningBroadcastCells PRESENCE optional}| + { ID id-RoutingID CRITICALITY reject TYPE RoutingID PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- POSITIONING ASSISTANCE INFORMATION FEEDBACK ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Assistance Information Feedback +-- +-- ************************************************************** + +PositioningAssistanceInformationFeedback ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{ PositioningAssistanceInformationFeedbackIEs}}, + ... +} + +PositioningAssistanceInformationFeedbackIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-PosAssistanceInformationFailureList CRITICALITY reject TYPE PosAssistanceInformationFailureList PRESENCE optional}| + { ID id-PositioningBroadcastCells CRITICALITY reject TYPE PositioningBroadcastCells PRESENCE optional}| + { ID id-RoutingID CRITICALITY reject TYPE RoutingID PRESENCE optional}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- POSITONING MEASUREMENT EXCHANGE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Request +-- +-- ************************************************************** + +PositioningMeasurementRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementRequestIEs} }, + ... +} + +PositioningMeasurementRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory}| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory}| + { ID id-TRP-MeasurementRequestList CRITICALITY reject TYPE TRP-MeasurementRequestList PRESENCE mandatory}| + { ID id-PosReportCharacteristics CRITICALITY reject TYPE PosReportCharacteristics PRESENCE mandatory}| + { ID id-PosMeasurementPeriodicity CRITICALITY reject TYPE PosMeasurementPeriodicity PRESENCE conditional }| + -- The above IE shall be present if the PosReportCharacteristics IE is set to “periodic” -- + { ID id-PosMeasurementQuantities CRITICALITY reject TYPE PosMeasurementQuantities PRESENCE mandatory}| + { ID id-SFNInitialisationTime CRITICALITY ignore TYPE SFNInitialisationTime PRESENCE optional }| + { ID id-SRSConfiguration CRITICALITY ignore TYPE SRSConfiguration PRESENCE optional}| + { ID id-MeasurementBeamInfoRequest CRITICALITY ignore TYPE MeasurementBeamInfoRequest PRESENCE optional }| + { ID id-SystemFrameNumber CRITICALITY ignore TYPE SystemFrameNumber PRESENCE optional}| + { ID id-SlotNumber CRITICALITY ignore TYPE SlotNumber PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- Positioning Measurement Response +-- +-- ************************************************************** + +PositioningMeasurementResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementResponseIEs} }, + ... +} + + +PositioningMeasurementResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory}| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory}| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory}| + { ID id-PosMeasurementResultList CRITICALITY reject TYPE PosMeasurementResultList PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- Positioning Measurement Failure +-- +-- ************************************************************** + +PositioningMeasurementFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementFailureIEs} }, + ... +} + +PositioningMeasurementFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING MEASUREMENT REPORT ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Report +-- +-- ************************************************************** + +PositioningMeasurementReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementReportIEs} }, + ... +} + +PositioningMeasurementReportIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }| + { ID id-PosMeasurementResultList CRITICALITY reject TYPE PosMeasurementResultList PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- POSITIONING MEASUREMENT ABORT ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Abort +-- +-- ************************************************************** + +PositioningMeasurementAbort ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementAbortIEs} }, + ... +} + +PositioningMeasurementAbortIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- POSITIONING MEASUREMENT FAILURE INDICATION ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Failure Indication +-- +-- ************************************************************** + +PositioningMeasurementFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementFailureIndicationIEs} }, + ... +} + +PositioningMeasurementFailureIndicationIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- POSITIONING MEASUREMENT UPDATE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Measurement Update +-- +-- ************************************************************** + +PositioningMeasurementUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningMeasurementUpdateIEs} }, + ... +} + +PositioningMeasurementUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-LMF-MeasurementID CRITICALITY reject TYPE LMF-MeasurementID PRESENCE mandatory }| + { ID id-RAN-MeasurementID CRITICALITY reject TYPE RAN-MeasurementID PRESENCE mandatory }| + { ID id-SRSConfiguration CRITICALITY ignore TYPE SRSConfiguration PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- TRP INFORMATION EXCHANGE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- TRP Information Request +-- +-- ************************************************************** + +TRPInformationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { TRPInformationRequestIEs} }, + ... +} + +TRPInformationRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-TRPList CRITICALITY ignore TYPE TRPList PRESENCE optional }| + { ID id-TRPInformationTypeListTRPReq CRITICALITY reject TYPE TRPInformationTypeListTRPReq PRESENCE mandatory }, + ... +} + +TRPInformationTypeListTRPReq ::= SEQUENCE (SIZE(1.. maxnoofTRPInfoTypes)) OF ProtocolIE-SingleContainer { { TRPInformationTypeItemTRPReq } } + +TRPInformationTypeItemTRPReq F1AP-PROTOCOL-IES ::= { + { ID id-TRPInformationTypeItem CRITICALITY reject TYPE TRPInformationTypeItem PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- TRP Information Response +-- +-- ************************************************************** + +TRPInformationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { TRPInformationResponseIEs} }, + ... +} + +TRPInformationResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-TRPInformationListTRPResp CRITICALITY ignore TYPE TRPInformationListTRPResp PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +TRPInformationListTRPResp ::= SEQUENCE (SIZE(1.. maxnoofTRPs)) OF ProtocolIE-SingleContainer { { TRPInformationItemTRPResp } } + +TRPInformationItemTRPResp F1AP-PROTOCOL-IES ::= { + { ID id-TRPInformationItem CRITICALITY ignore TYPE TRPInformationItem PRESENCE mandatory }, + ... +} + + +-- ************************************************************** +-- +-- TRP Information Failure +-- +-- ************************************************************** + +TRPInformationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { TRPInformationFailureIEs} }, + ... +} + +TRPInformationFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-TransactionID CRITICALITY reject TYPE TransactionID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING INFORMATION EXCHANGE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Information Request +-- +-- ************************************************************** + +PositioningInformationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningInformationRequestIEs} }, + ... +} + +PositioningInformationRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-RequestedSRSTransmissionCharacteristics CRITICALITY ignore TYPE RequestedSRSTransmissionCharacteristics PRESENCE optional}, + ... +} + + +-- ************************************************************** +-- +-- Positioning Information Response +-- +-- ************************************************************** + +PositioningInformationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningInformationResponseIEs} }, + ... +} + + +PositioningInformationResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SRSConfiguration CRITICALITY ignore TYPE SRSConfiguration PRESENCE optional}| + { ID id-SFNInitialisationTime CRITICALITY ignore TYPE SFNInitialisationTime PRESENCE optional}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- Positioning Information Failure +-- +-- ************************************************************** + +PositioningInformationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningInformationFailureIEs} }, + ... +} + +PositioningInformationFailureIEs F1AP-PROTOCOL-IES ::= { + + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING ACTIVATION PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Activation Request +-- +-- ************************************************************** + +PositioningActivationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningActivationRequestIEs} }, + ... +} + +PositioningActivationRequestIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SRSType CRITICALITY reject TYPE SRSType PRESENCE mandatory }| + { ID id-ActivationTime CRITICALITY ignore TYPE SFNInitialisationTime PRESENCE optional }, + ... +} + +SRSType ::= CHOICE { + semipersistentSRS SemipersistentSRS, + aperiodicSRS AperiodicSRS, + choice-extension ProtocolIE-SingleContainer { { SRSType-ExtIEs} } +} + +SRSType-ExtIEs F1AP-PROTOCOL-IES ::= { + ... +} + +SemipersistentSRS ::= SEQUENCE { + sRSResourceSetID SRSResourceSetID, + sRSSpatialRelation SRSSpatialRelation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {SemipersistentSRS-ExtIEs} } OPTIONAL, + ... +} + +SemipersistentSRS-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + +AperiodicSRS ::= SEQUENCE { + aperiodic ENUMERATED {true, ...}, + sRSResourceTrigger SRSResourceTrigger OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {AperiodicSRS-ExtIEs} } OPTIONAL, + ... +} + +AperiodicSRS-ExtIEs F1AP-PROTOCOL-EXTENSION ::= { + ... +} + + +-- ************************************************************** +-- +-- Positioning Activation Response +-- +-- ************************************************************** + +PositioningActivationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningActivationResponseIEs} }, + ... +} + + +PositioningActivationResponseIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SystemFrameNumber CRITICALITY ignore TYPE SystemFrameNumber PRESENCE optional }| + { ID id-SlotNumber CRITICALITY ignore TYPE SlotNumber PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + + + +-- ************************************************************** +-- +-- Positioning Activation Failure +-- +-- ************************************************************** + +PositioningActivationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningActivationFailureIEs} }, + ... +} + +PositioningActivationFailureIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- POSITIONING DEACTIVATION PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Deactivation +-- +-- ************************************************************** + +PositioningDeactivation ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningDeactivationIEs} }, + ... +} + +PositioningDeactivationIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-AbortTransmission CRITICALITY ignore TYPE AbortTransmission PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- POSITIONING INFORMATION UPDATE PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Positioning Information Update +-- +-- ************************************************************** + +PositioningInformationUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PositioningInformationUpdateIEs} }, + ... +} + + +PositioningInformationUpdateIEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-SRSConfiguration CRITICALITY ignore TYPE SRSConfiguration PRESENCE optional}| + { ID id-SFNInitialisationTime CRITICALITY ignore TYPE SFNInitialisationTime PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- E-CID MEASUREMENT PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- E-CID Measurement Initiation Request +-- +-- ************************************************************** + +E-CIDMeasurementInitiationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementInitiationRequest-IEs}}, + ... +} + +E-CIDMeasurementInitiationRequest-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY reject TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY reject TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-E-CID-ReportCharacteristics CRITICALITY reject TYPE E-CID-ReportCharacteristics PRESENCE mandatory }| + { ID id-E-CID-MeasurementPeriodicity CRITICALITY reject TYPE E-CID-MeasurementPeriodicity PRESENCE conditional }| +-- The above IE shall be present if the E-CID-ReportCharacteristics IE is set to “periodic” –- + { ID id-E-CID-MeasurementQuantities CRITICALITY reject TYPE E-CID-MeasurementQuantities PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- E-CID Measurement Initiation Response +-- +-- ************************************************************** + +E-CIDMeasurementInitiationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementInitiationResponse-IEs}}, + ... +} + +E-CIDMeasurementInitiationResponse-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-E-CID-MeasurementResult CRITICALITY ignore TYPE E-CID-MeasurementResult PRESENCE optional}| + { ID id-Cell-Portion-ID CRITICALITY ignore TYPE Cell-Portion-ID PRESENCE optional}| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- E-CID Measurement Initiation Failure +-- +-- ************************************************************** + +E-CIDMeasurementInitiationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementInitiationFailure-IEs}}, + ... +} + + +E-CIDMeasurementInitiationFailure-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional}, + ... +} + +-- ************************************************************** +-- +-- E-CID MEASUREMENT FAILURE INDICATION PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- E-CID Measurement Failure Indication +-- +-- ************************************************************** + +E-CIDMeasurementFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementFailureIndication-IEs}}, + ... +} + + +E-CIDMeasurementFailureIndication-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory}, + ... +} + +-- ************************************************************** +-- +-- E-CID MEASUREMENT REPORT PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- E-CID Measurement Report +-- +-- ************************************************************** + +E-CIDMeasurementReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementReport-IEs}}, + ... +} + + +E-CIDMeasurementReport-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }| + { ID id-E-CID-MeasurementResult CRITICALITY ignore TYPE E-CID-MeasurementResult PRESENCE mandatory }| + { ID id-Cell-Portion-ID CRITICALITY ignore TYPE Cell-Portion-ID PRESENCE optional}, + + ... +} + +-- ************************************************************** +-- +-- E-CID MEASUREMENT TERMINATION PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- E-CID Measurement Termination Command +-- +-- ************************************************************** + + +E-CIDMeasurementTerminationCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container {{E-CIDMeasurementTerminationCommand-IEs}}, + ... +} + + +E-CIDMeasurementTerminationCommand-IEs F1AP-PROTOCOL-IES ::= { + { ID id-gNB-CU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-CU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-gNB-DU-UE-F1AP-ID CRITICALITY ignore TYPE GNB-DU-UE-F1AP-ID PRESENCE mandatory }| + { ID id-LMF-UE-MeasurementID CRITICALITY reject TYPE LMF-UE-MeasurementID PRESENCE mandatory }| + { ID id-RAN-UE-MeasurementID CRITICALITY reject TYPE RAN-UE-MeasurementID PRESENCE mandatory }, + ... +} + + + +END diff --git a/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-PDU-Descriptions.asn b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-PDU-Descriptions.asn new file mode 100644 index 0000000000..6ec795ab10 --- /dev/null +++ b/openair2/F1AP/MESSAGES/ASN1/R16.3.1/F1AP-PDU-Descriptions.asn @@ -0,0 +1,723 @@ +-- ************************************************************** +-- +-- Elementary Procedure definitions +-- +-- ************************************************************** + +F1AP-PDU-Descriptions { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-access (22) modules (3) f1ap (3) version1 (1) f1ap-PDU-Descriptions (0)} + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + Criticality, + ProcedureCode + +FROM F1AP-CommonDataTypes + Reset, + ResetAcknowledge, + F1SetupRequest, + F1SetupResponse, + F1SetupFailure, + GNBDUConfigurationUpdate, + GNBDUConfigurationUpdateAcknowledge, + GNBDUConfigurationUpdateFailure, + GNBCUConfigurationUpdate, + GNBCUConfigurationUpdateAcknowledge, + GNBCUConfigurationUpdateFailure, + UEContextSetupRequest, + UEContextSetupResponse, + UEContextSetupFailure, + UEContextReleaseCommand, + UEContextReleaseComplete, + UEContextModificationRequest, + UEContextModificationResponse, + UEContextModificationFailure, + UEContextModificationRequired, + UEContextModificationConfirm, + ErrorIndication, + UEContextReleaseRequest, + DLRRCMessageTransfer, + ULRRCMessageTransfer, + GNBDUResourceCoordinationRequest, + GNBDUResourceCoordinationResponse, + PrivateMessage, + UEInactivityNotification, + InitialULRRCMessageTransfer, + SystemInformationDeliveryCommand, + Paging, + Notify, + WriteReplaceWarningRequest, + WriteReplaceWarningResponse, + PWSCancelRequest, + PWSCancelResponse, + PWSRestartIndication, + PWSFailureIndication, + GNBDUStatusIndication, + RRCDeliveryReport, + UEContextModificationRefuse, + F1RemovalRequest, + F1RemovalResponse, + F1RemovalFailure, + NetworkAccessRateReduction, + TraceStart, + DeactivateTrace, + DUCURadioInformationTransfer, + CUDURadioInformationTransfer, + BAPMappingConfiguration, + BAPMappingConfigurationAcknowledge, + GNBDUResourceConfiguration, + GNBDUResourceConfigurationAcknowledge, + IABTNLAddressRequest, + IABTNLAddressResponse, + IABUPConfigurationUpdateRequest, + IABUPConfigurationUpdateResponse, + IABUPConfigurationUpdateFailure, + ResourceStatusRequest, + ResourceStatusResponse, + ResourceStatusFailure, + ResourceStatusUpdate, + AccessAndMobilityIndication, + ReferenceTimeInformationReportingControl, + ReferenceTimeInformationReport, + AccessSuccess, + CellTrafficTrace, + PositioningMeasurementRequest, + PositioningMeasurementResponse, + PositioningMeasurementFailure, + PositioningAssistanceInformationControl, + PositioningAssistanceInformationFeedback, + PositioningMeasurementReport, + PositioningMeasurementAbort, + PositioningMeasurementFailureIndication, + PositioningMeasurementUpdate, + TRPInformationRequest, + TRPInformationResponse, + TRPInformationFailure, + PositioningInformationRequest, + PositioningInformationResponse, + PositioningInformationFailure, + PositioningActivationRequest, + PositioningActivationResponse, + PositioningActivationFailure, + PositioningDeactivation, + PositioningInformationUpdate, + E-CIDMeasurementInitiationRequest, + E-CIDMeasurementInitiationResponse, + E-CIDMeasurementInitiationFailure, + E-CIDMeasurementFailureIndication, + E-CIDMeasurementReport, + E-CIDMeasurementTerminationCommand + + + +FROM F1AP-PDU-Contents + id-Reset, + id-F1Setup, + id-gNBDUConfigurationUpdate, + id-gNBCUConfigurationUpdate, + id-UEContextSetup, + id-UEContextRelease, + id-UEContextModification, + id-UEContextModificationRequired, + id-ErrorIndication, + id-UEContextReleaseRequest, + id-DLRRCMessageTransfer, + id-ULRRCMessageTransfer, + id-GNBDUResourceCoordination, + id-privateMessage, + id-UEInactivityNotification, + id-InitialULRRCMessageTransfer, + id-SystemInformationDeliveryCommand, + id-Paging, + id-Notify, + id-WriteReplaceWarning, + id-PWSCancel, + id-PWSRestartIndication, + id-PWSFailureIndication, + id-GNBDUStatusIndication, + id-RRCDeliveryReport, + id-F1Removal, + id-NetworkAccessRateReduction, + id-TraceStart, + id-DeactivateTrace, + id-DUCURadioInformationTransfer, + id-CUDURadioInformationTransfer, + id-BAPMappingConfiguration, + id-GNBDUResourceConfiguration, + id-IABTNLAddressAllocation, + id-IABUPConfigurationUpdate, + id-resourceStatusReportingInitiation, + id-resourceStatusReporting, + id-accessAndMobilityIndication, + id-ReferenceTimeInformationReportingControl, + id-ReferenceTimeInformationReport, + id-accessSuccess, + id-cellTrafficTrace, + id-PositioningMeasurementExchange, + id-PositioningAssistanceInformationControl, + id-PositioningAssistanceInformationFeedback, + id-PositioningMeasurementReport, + id-PositioningMeasurementAbort, + id-PositioningMeasurementFailureIndication, + id-PositioningMeasurementUpdate, + id-TRPInformationExchange, + id-PositioningInformationExchange, + id-PositioningActivation, + id-PositioningDeactivation, + id-PositioningInformationUpdate, + id-E-CIDMeasurementInitiation, + id-E-CIDMeasurementFailureIndication, + id-E-CIDMeasurementReport, + id-E-CIDMeasurementTermination + + +FROM F1AP-Constants + + ProtocolIE-SingleContainer{}, + F1AP-PROTOCOL-IES + +FROM F1AP-Containers; + + +-- ************************************************************** +-- +-- Interface Elementary Procedure Class +-- +-- ************************************************************** + +F1AP-ELEMENTARY-PROCEDURE ::= CLASS { + &InitiatingMessage , + &SuccessfulOutcome OPTIONAL, + &UnsuccessfulOutcome OPTIONAL, + &procedureCode ProcedureCode UNIQUE, + &criticality Criticality DEFAULT ignore +} +WITH SYNTAX { + INITIATING MESSAGE &InitiatingMessage + [SUCCESSFUL OUTCOME &SuccessfulOutcome] + [UNSUCCESSFUL OUTCOME &UnsuccessfulOutcome] + PROCEDURE CODE &procedureCode + [CRITICALITY &criticality] +} + +-- ************************************************************** +-- +-- Interface PDU Definition +-- +-- ************************************************************** + +F1AP-PDU ::= CHOICE { + initiatingMessage InitiatingMessage, + successfulOutcome SuccessfulOutcome, + unsuccessfulOutcome UnsuccessfulOutcome, + choice-extension ProtocolIE-SingleContainer { { F1AP-PDU-ExtIEs} } +} + +F1AP-PDU-ExtIEs F1AP-PROTOCOL-IES ::= { -- this extension is not used + ... +} + +InitiatingMessage ::= SEQUENCE { + procedureCode F1AP-ELEMENTARY-PROCEDURE.&procedureCode ({F1AP-ELEMENTARY-PROCEDURES}), + criticality F1AP-ELEMENTARY-PROCEDURE.&criticality ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value F1AP-ELEMENTARY-PROCEDURE.&InitiatingMessage ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +SuccessfulOutcome ::= SEQUENCE { + procedureCode F1AP-ELEMENTARY-PROCEDURE.&procedureCode ({F1AP-ELEMENTARY-PROCEDURES}), + criticality F1AP-ELEMENTARY-PROCEDURE.&criticality ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value F1AP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +UnsuccessfulOutcome ::= SEQUENCE { + procedureCode F1AP-ELEMENTARY-PROCEDURE.&procedureCode ({F1AP-ELEMENTARY-PROCEDURES}), + criticality F1AP-ELEMENTARY-PROCEDURE.&criticality ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value F1AP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome ({F1AP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +-- ************************************************************** +-- +-- Interface Elementary Procedure List +-- +-- ************************************************************** + +F1AP-ELEMENTARY-PROCEDURES F1AP-ELEMENTARY-PROCEDURE ::= { + F1AP-ELEMENTARY-PROCEDURES-CLASS-1 | + F1AP-ELEMENTARY-PROCEDURES-CLASS-2, + ... +} + + +F1AP-ELEMENTARY-PROCEDURES-CLASS-1 F1AP-ELEMENTARY-PROCEDURE ::= { + reset | + f1Setup | + gNBDUConfigurationUpdate | + gNBCUConfigurationUpdate | + uEContextSetup | + uEContextRelease | + uEContextModification | + uEContextModificationRequired | + writeReplaceWarning | + pWSCancel | + gNBDUResourceCoordination | + f1Removal | + bAPMappingConfiguration | + gNBDUResourceConfiguration | + iABTNLAddressAllocation | + iABUPConfigurationUpdate | + resourceStatusReportingInitiation | + positioningMeasurementExchange | + tRPInformationExchange | + positioningInformationExchange | + positioningActivation | + e-CIDMeasurementInitiation, + ... +} + +F1AP-ELEMENTARY-PROCEDURES-CLASS-2 F1AP-ELEMENTARY-PROCEDURE ::= { + errorIndication | + uEContextReleaseRequest | + dLRRCMessageTransfer | + uLRRCMessageTransfer | + uEInactivityNotification | + privateMessage | + initialULRRCMessageTransfer | + systemInformationDelivery | + paging | + notify | + pWSRestartIndication | + pWSFailureIndication | + gNBDUStatusIndication | + rRCDeliveryReport | + networkAccessRateReduction | + traceStart | + deactivateTrace | + dUCURadioInformationTransfer | + cUDURadioInformationTransfer | + resourceStatusReporting | + accessAndMobilityIndication | + referenceTimeInformationReportingControl| + referenceTimeInformationReport | + accessSuccess | + cellTrafficTrace | + positioningAssistanceInformationControl | + positioningAssistanceInformationFeedback | + positioningMeasurementReport | + positioningMeasurementAbort | + positioningMeasurementFailureIndication | + positioningMeasurementUpdate | + positioningDeactivation | + e-CIDMeasurementFailureIndication | + e-CIDMeasurementReport | + e-CIDMeasurementTermination | + positioningInformationUpdate, + ... +} +-- ************************************************************** +-- +-- Interface Elementary Procedures +-- +-- ************************************************************** + +reset F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE Reset + SUCCESSFUL OUTCOME ResetAcknowledge + PROCEDURE CODE id-Reset + CRITICALITY reject +} + +f1Setup F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE F1SetupRequest + SUCCESSFUL OUTCOME F1SetupResponse + UNSUCCESSFUL OUTCOME F1SetupFailure + PROCEDURE CODE id-F1Setup + CRITICALITY reject +} + +gNBDUConfigurationUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBDUConfigurationUpdate + SUCCESSFUL OUTCOME GNBDUConfigurationUpdateAcknowledge + UNSUCCESSFUL OUTCOME GNBDUConfigurationUpdateFailure + PROCEDURE CODE id-gNBDUConfigurationUpdate + CRITICALITY reject +} + +gNBCUConfigurationUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBCUConfigurationUpdate + SUCCESSFUL OUTCOME GNBCUConfigurationUpdateAcknowledge + UNSUCCESSFUL OUTCOME GNBCUConfigurationUpdateFailure + PROCEDURE CODE id-gNBCUConfigurationUpdate + CRITICALITY reject +} + +uEContextSetup F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextSetupRequest + SUCCESSFUL OUTCOME UEContextSetupResponse + UNSUCCESSFUL OUTCOME UEContextSetupFailure + PROCEDURE CODE id-UEContextSetup + CRITICALITY reject +} + +uEContextRelease F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextReleaseCommand + SUCCESSFUL OUTCOME UEContextReleaseComplete + PROCEDURE CODE id-UEContextRelease + CRITICALITY reject +} + +uEContextModification F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextModificationRequest + SUCCESSFUL OUTCOME UEContextModificationResponse + UNSUCCESSFUL OUTCOME UEContextModificationFailure + PROCEDURE CODE id-UEContextModification + CRITICALITY reject +} + +uEContextModificationRequired F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextModificationRequired + SUCCESSFUL OUTCOME UEContextModificationConfirm + UNSUCCESSFUL OUTCOME UEContextModificationRefuse + PROCEDURE CODE id-UEContextModificationRequired + CRITICALITY reject +} + +writeReplaceWarning F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE WriteReplaceWarningRequest + SUCCESSFUL OUTCOME WriteReplaceWarningResponse + PROCEDURE CODE id-WriteReplaceWarning + CRITICALITY reject +} + +pWSCancel F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSCancelRequest + SUCCESSFUL OUTCOME PWSCancelResponse + PROCEDURE CODE id-PWSCancel + CRITICALITY reject +} + +errorIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ErrorIndication + PROCEDURE CODE id-ErrorIndication + CRITICALITY ignore +} + +uEContextReleaseRequest F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextReleaseRequest + PROCEDURE CODE id-UEContextReleaseRequest + CRITICALITY ignore +} + + +initialULRRCMessageTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE InitialULRRCMessageTransfer + PROCEDURE CODE id-InitialULRRCMessageTransfer + CRITICALITY ignore +} + +dLRRCMessageTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DLRRCMessageTransfer + PROCEDURE CODE id-DLRRCMessageTransfer + CRITICALITY ignore +} + +uLRRCMessageTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ULRRCMessageTransfer + PROCEDURE CODE id-ULRRCMessageTransfer + CRITICALITY ignore +} + + +uEInactivityNotification F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEInactivityNotification + PROCEDURE CODE id-UEInactivityNotification + CRITICALITY ignore +} + +gNBDUResourceCoordination F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBDUResourceCoordinationRequest + SUCCESSFUL OUTCOME GNBDUResourceCoordinationResponse + PROCEDURE CODE id-GNBDUResourceCoordination + CRITICALITY reject +} + +privateMessage F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PrivateMessage + PROCEDURE CODE id-privateMessage + CRITICALITY ignore +} + +systemInformationDelivery F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE SystemInformationDeliveryCommand + PROCEDURE CODE id-SystemInformationDeliveryCommand + CRITICALITY ignore +} + + +paging F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE Paging + PROCEDURE CODE id-Paging + CRITICALITY ignore +} + +notify F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE Notify + PROCEDURE CODE id-Notify + CRITICALITY ignore +} + +networkAccessRateReduction F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE NetworkAccessRateReduction + PROCEDURE CODE id-NetworkAccessRateReduction + CRITICALITY ignore +} + + +pWSRestartIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSRestartIndication + PROCEDURE CODE id-PWSRestartIndication + CRITICALITY ignore +} + +pWSFailureIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSFailureIndication + PROCEDURE CODE id-PWSFailureIndication + CRITICALITY ignore +} + +gNBDUStatusIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBDUStatusIndication + PROCEDURE CODE id-GNBDUStatusIndication + CRITICALITY ignore +} + + +rRCDeliveryReport F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RRCDeliveryReport + PROCEDURE CODE id-RRCDeliveryReport + CRITICALITY ignore +} + +f1Removal F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE F1RemovalRequest + SUCCESSFUL OUTCOME F1RemovalResponse + UNSUCCESSFUL OUTCOME F1RemovalFailure + PROCEDURE CODE id-F1Removal + CRITICALITY reject +} + +traceStart F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE TraceStart + PROCEDURE CODE id-TraceStart + CRITICALITY ignore +} + +deactivateTrace F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DeactivateTrace + PROCEDURE CODE id-DeactivateTrace + CRITICALITY ignore +} + +dUCURadioInformationTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DUCURadioInformationTransfer + PROCEDURE CODE id-DUCURadioInformationTransfer + CRITICALITY ignore +} + +cUDURadioInformationTransfer F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CUDURadioInformationTransfer + PROCEDURE CODE id-CUDURadioInformationTransfer + CRITICALITY ignore +} + +bAPMappingConfiguration F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE BAPMappingConfiguration + SUCCESSFUL OUTCOME BAPMappingConfigurationAcknowledge + PROCEDURE CODE id-BAPMappingConfiguration + CRITICALITY reject +} + +gNBDUResourceConfiguration F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE GNBDUResourceConfiguration + SUCCESSFUL OUTCOME GNBDUResourceConfigurationAcknowledge + PROCEDURE CODE id-GNBDUResourceConfiguration + CRITICALITY reject +} + +iABTNLAddressAllocation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE IABTNLAddressRequest + SUCCESSFUL OUTCOME IABTNLAddressResponse + PROCEDURE CODE id-IABTNLAddressAllocation + CRITICALITY reject +} + +iABUPConfigurationUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE IABUPConfigurationUpdateRequest + SUCCESSFUL OUTCOME IABUPConfigurationUpdateResponse + UNSUCCESSFUL OUTCOME IABUPConfigurationUpdateFailure + PROCEDURE CODE id-IABUPConfigurationUpdate + CRITICALITY reject +} + +resourceStatusReportingInitiation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ResourceStatusRequest + SUCCESSFUL OUTCOME ResourceStatusResponse + UNSUCCESSFUL OUTCOME ResourceStatusFailure + PROCEDURE CODE id-resourceStatusReportingInitiation + CRITICALITY reject +} + +resourceStatusReporting F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ResourceStatusUpdate + PROCEDURE CODE id-resourceStatusReporting + CRITICALITY ignore +} + +accessAndMobilityIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE AccessAndMobilityIndication + PROCEDURE CODE id-accessAndMobilityIndication + CRITICALITY ignore +} + +referenceTimeInformationReportingControl F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ReferenceTimeInformationReportingControl + PROCEDURE CODE id-ReferenceTimeInformationReportingControl + CRITICALITY ignore +} + +referenceTimeInformationReport F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ReferenceTimeInformationReport + PROCEDURE CODE id-ReferenceTimeInformationReport + CRITICALITY ignore +} + +accessSuccess F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE AccessSuccess + PROCEDURE CODE id-accessSuccess + CRITICALITY ignore +} + +cellTrafficTrace F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE CellTrafficTrace + PROCEDURE CODE id-cellTrafficTrace + CRITICALITY ignore +} + +positioningAssistanceInformationControl F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningAssistanceInformationControl + PROCEDURE CODE id-PositioningAssistanceInformationControl + CRITICALITY ignore +} + +positioningAssistanceInformationFeedback F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningAssistanceInformationFeedback + PROCEDURE CODE id-PositioningAssistanceInformationFeedback + CRITICALITY ignore +} + +positioningMeasurementExchange F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementRequest + SUCCESSFUL OUTCOME PositioningMeasurementResponse + UNSUCCESSFUL OUTCOME PositioningMeasurementFailure + PROCEDURE CODE id-PositioningMeasurementExchange + CRITICALITY reject +} + +positioningMeasurementReport F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementReport + PROCEDURE CODE id-PositioningMeasurementReport + CRITICALITY ignore +} + +positioningMeasurementAbort F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementAbort + PROCEDURE CODE id-PositioningMeasurementAbort + CRITICALITY ignore +} + +positioningMeasurementFailureIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementFailureIndication + PROCEDURE CODE id-PositioningMeasurementFailureIndication + CRITICALITY ignore +} + +positioningMeasurementUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningMeasurementUpdate + PROCEDURE CODE id-PositioningMeasurementUpdate + CRITICALITY ignore +} + + +tRPInformationExchange F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE TRPInformationRequest + SUCCESSFUL OUTCOME TRPInformationResponse + UNSUCCESSFUL OUTCOME TRPInformationFailure + PROCEDURE CODE id-TRPInformationExchange + CRITICALITY reject +} + +positioningInformationExchange F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningInformationRequest + SUCCESSFUL OUTCOME PositioningInformationResponse + UNSUCCESSFUL OUTCOME PositioningInformationFailure + PROCEDURE CODE id-PositioningInformationExchange + CRITICALITY reject +} + +positioningActivation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningActivationRequest + SUCCESSFUL OUTCOME PositioningActivationResponse + UNSUCCESSFUL OUTCOME PositioningActivationFailure + PROCEDURE CODE id-PositioningActivation + CRITICALITY reject +} + +positioningDeactivation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningDeactivation + PROCEDURE CODE id-PositioningDeactivation + CRITICALITY ignore +} + +e-CIDMeasurementInitiation F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE E-CIDMeasurementInitiationRequest + SUCCESSFUL OUTCOME E-CIDMeasurementInitiationResponse + UNSUCCESSFUL OUTCOME E-CIDMeasurementInitiationFailure + PROCEDURE CODE id-E-CIDMeasurementInitiation + CRITICALITY reject +} + +e-CIDMeasurementFailureIndication F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE E-CIDMeasurementFailureIndication + PROCEDURE CODE id-E-CIDMeasurementFailureIndication + CRITICALITY ignore +} + +e-CIDMeasurementReport F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE E-CIDMeasurementReport + PROCEDURE CODE id-E-CIDMeasurementReport + CRITICALITY ignore +} + +e-CIDMeasurementTermination F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE E-CIDMeasurementTerminationCommand + PROCEDURE CODE id-E-CIDMeasurementTermination + CRITICALITY ignore +} + +positioningInformationUpdate F1AP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PositioningInformationUpdate + PROCEDURE CODE id-PositioningInformationUpdate + CRITICALITY ignore +} + + +END diff --git a/openair2/F1AP/dummy_enb.c b/openair2/F1AP/dummy_enb.c new file mode 100644 index 0000000000..fe6dfb6a06 --- /dev/null +++ b/openair2/F1AP/dummy_enb.c @@ -0,0 +1,34 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "COMMON/platform_types.h" +#include "common/ran_context.h" +#include "common/utils/LOG/log.h" +#include "NR_BCCH-BCH-Message.h" +#include "NR_ServingCellConfigCommon.h" +#include "NR_MIB.h" + +void apply_macrlc_config(gNB_RRC_INST *rrc, + rrc_gNB_ue_context_t *const ue_context_pP, + const protocol_ctxt_t *const ctxt_pP ) { +abort(); +} + diff --git a/openair2/F1AP/f1ap_common.h b/openair2/F1AP/f1ap_common.h index ee57a7ec83..7781a78412 100644 --- a/openair2/F1AP/f1ap_common.h +++ b/openair2/F1AP/f1ap_common.h @@ -46,7 +46,6 @@ inline void ASN_DEBUG(const char *fmt, ...); #endif -#include "F1AP_Active-Cells-List.h" #include "F1AP_RAT-FrequencyPriorityInformation.h" #include "F1AP_DLUPTNLInformation-ToBeSetup-Item.h" #include "F1AP_PrivateMessage.h" @@ -55,6 +54,7 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_NRPCI.h" #include "F1AP_Transmission-Bandwidth.h" #include "F1AP_SIB1-message.h" +#include "F1AP_SibtypetobeupdatedListItem.h" #include "F1AP_GNBCUConfigurationUpdateAcknowledge.h" #include "F1AP_DRBs-Setup-Item.h" #include "F1AP_EUTRA-NR-CellResourceCoordinationReqAck-Container.h" @@ -75,7 +75,6 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_DRBs-Required-ToBeModified-Item.h" #include "F1AP_BitRate.h" #include "F1AP_SRBs-ToBeSetup-List.h" -#include "F1AP_ConcurrentWarningMessageIndicator.h" #include "F1AP_CriticalityDiagnostics-IE-Item.h" #include "F1AP_GNB-CU-TNL-Association-To-Update-List.h" #include "F1AP_DRB-Notify-List.h" @@ -85,6 +84,7 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_PWS-Failed-NR-CGI-List.h" #include "F1AP_InitialULRRCMessageTransfer.h" #include "F1AP_Served-Cell-Information.h" +#include "F1AP_ServedPLMNs-Item.h" #include "F1AP_Served-EUTRA-Cells-Information.h" #include "F1AP_Cells-Broadcast-Cancelled-Item.h" #include "F1AP_F1SetupRequest.h" @@ -128,13 +128,11 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_TransactionID.h" #include "F1AP_AllocationAndRetentionPriority.h" #include "F1AP_ShortDRXCycleLength.h" -#include "F1AP_BroadcastPLMNs-Item.h" #include "F1AP_DRB-Information.h" #include "F1AP_TimeToWait.h" #include "F1AP_NonDynamic5QIDescriptor.h" #include "F1AP_C-RNTI.h" #include "F1AP_MIB-message.h" -#include "F1AP_SIBtype-Item.h" #include "F1AP_Served-Cells-To-Modify-List.h" #include "F1AP_NRCGI.h" #include "F1AP_DuplicationActivation.h" @@ -187,6 +185,7 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_CellULConfigured.h" #include "F1AP_DRB-Activity.h" #include "F1AP_GNB-CU-TNL-Association-Failed-To-Setup-Item.h" +#include "F1AP_ProtocolIE-ID.h" #include "F1AP_PrivateIE-ID.h" #include "F1AP_WriteReplaceWarningResponse.h" #include "F1AP_CauseMisc.h" @@ -231,9 +230,7 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_SUL-Information.h" #include "F1AP_CriticalityDiagnostics-IE-List.h" #include "F1AP_EUTRA-FDD-Info.h" -#include "F1AP_BroadcastPLMNs-List.h" #include "F1AP_Served-Cells-To-Delete-Item.h" -#include "F1AP_ListofEUTRACellsinGNBDUCoordination.h" #include "F1AP_Candidate-SpCell-Item.h" #include "F1AP_Cells-To-Be-Broadcast-List.h" #include "F1AP_ULRRCMessageTransfer.h" @@ -255,7 +252,6 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_SRBs-ToBeReleased-List.h" #include "F1AP_MeasGapConfig.h" #include "F1AP_NR-Mode-Info.h" -#include "F1AP_Active-Cells-Item.h" #include "F1AP_Protected-EUTRA-Resources-List.h" #include "F1AP_SRBs-FailedToBeSetup-Item.h" #include "F1AP_ResetAll.h" @@ -287,7 +283,6 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_UEContextReleaseRequest.h" #include "F1AP_GNB-DU-Name.h" #include "F1AP_DRBs-ToBeModified-Item.h" -#include "F1AP_SIBtype-List.h" #include "F1AP_EUTRA-NR-CellResourceCoordinationReq-Container.h" #include "F1AP_DRBs-SetupMod-List.h" #include "F1AP_DRBs-Required-ToBeModified-List.h" @@ -296,7 +291,6 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_PacketDelayBudget.h" #include "F1AP_GNBCUConfigurationUpdate.h" #include "F1AP_Cells-Broadcast-Completed-Item.h" -#include "F1AP_RRCRconfigurationCompleteIndicator.h" #include "F1AP_PagingPriority.h" #include "F1AP_Cells-Failed-to-be-Activated-List.h" #include "F1AP_Endpoint-IP-address-and-port.h" @@ -306,7 +300,6 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_ResetType.h" #include "F1AP_FDD-Info.h" #include "F1AP_DLUPTNLInformation-ToBeSetup-List.h" -#include "F1AP_QoSFlowIndicator.h" #include "F1AP_NR-CGI-List-For-Restart-List.h" #include "F1AP_F1SetupResponse.h" #include "F1AP_UEContextSetupResponse.h" @@ -325,7 +318,6 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_Cells-to-be-Barred-List.h" #include "F1AP_Presence.h" #include "F1AP_CellBarred.h" -#include "F1AP_SIBtype.h" #include "F1AP_RequestType.h" #include "F1AP_NRFreqInfo.h" #include "F1AP_Potential-SpCell-Item.h" @@ -348,7 +340,6 @@ inline void ASN_DEBUG(const char *fmt, ...); #include "F1AP_GBR-QoSFlowInformation.h" #include "F1AP_SCellIndex.h" #include "F1AP_DRBs-SetupMod-Item.h" -#include "F1AP_TransmissionStopIndicator.h" #include "F1AP_UEContextSetupFailure.h" #include "F1AP_DRBs-FailedToBeModified-List.h" #include "F1AP_DRBs-FailedToBeSetupMod-Item.h" diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 48c5c2de11..057d0d97a0 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -37,6 +37,7 @@ #include "f1ap_cu_interface_management.h" extern f1ap_setup_req_t *f1ap_du_data_from_du; +extern RAN_CONTEXT_t RC; int CU_send_RESET(instance_t instance, F1AP_Reset_t *Reset) { AssertFatal(1==0,"Not implemented yet\n"); @@ -102,8 +103,12 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message(TASK_RRC_ENB, F1AP_SETUP_REQ); - + if(RC.nrrrc) { + message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_SETUP_REQ); + } else { + message_p = itti_alloc_new_message(TASK_RRC_ENB, 0, F1AP_SETUP_REQ); + } + /* assoc_id */ F1AP_SETUP_REQ(message_p).assoc_id = assoc_id; @@ -134,57 +139,57 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, int num_cells_available = F1AP_SETUP_REQ(message_p).num_cells_available; for (i=0; ivalue.choice.GNB_DU_Served_Cells_List.list.array[i])->value.choice.GNB_DU_Served_Cells_Item); + served_cells_item_p = &(((F1AP_GNB_DU_Served_Cells_ItemIEs_t *)ie->value.choice.GNB_DU_Served_Cells_List.list.array[i])->value.choice.GNB_DU_Served_Cells_Item); /* tac */ - OCTET_STRING_TO_INT16(&(served_celles_item_p->served_Cell_Information.fiveGS_TAC), F1AP_SETUP_REQ(message_p).tac[i]); - LOG_D(F1AP, "F1AP_SETUP_REQ(message_p).tac[%d] %d \n", - i, F1AP_SETUP_REQ(message_p).tac[i]); - + if (served_cells_item_p->served_Cell_Information.fiveGS_TAC) { + OCTET_STRING_TO_INT16(served_cells_item_p->served_Cell_Information.fiveGS_TAC, F1AP_SETUP_REQ(message_p).tac[i]); + LOG_D(F1AP, "F1AP_SETUP_REQ(message_p).tac[%d] %d \n", i, F1AP_SETUP_REQ(message_p).tac[i]); + } /* - nRCGI */ - TBCD_TO_MCC_MNC(&(served_celles_item_p->served_Cell_Information.nRCGI.pLMN_Identity), F1AP_SETUP_REQ(message_p).mcc[i], + TBCD_TO_MCC_MNC(&(served_cells_item_p->served_Cell_Information.nRCGI.pLMN_Identity), F1AP_SETUP_REQ(message_p).mcc[i], F1AP_SETUP_REQ(message_p).mnc[i], F1AP_SETUP_REQ(message_p).mnc_digit_length[i]); // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity, + BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item_p->served_Cell_Information.nRCGI.nRCellIdentity, F1AP_SETUP_REQ(message_p).nr_cellid[i]); LOG_D(F1AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id, F1AP_SETUP_REQ(message_p).mcc[i], F1AP_SETUP_REQ(message_p).mnc[i], (long long unsigned int)F1AP_SETUP_REQ(message_p).nr_cellid[i]); LOG_D(F1AP, "nr_cellId : %x %x %x %x %x\n", - served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[0], - served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[1], - served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[2], - served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[3], - served_celles_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[4]); + served_cells_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[0], + served_cells_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[1], + served_cells_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[2], + served_cells_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[3], + served_cells_item_p->served_Cell_Information.nRCGI.nRCellIdentity.buf[4]); /* - nRPCI */ - F1AP_SETUP_REQ(message_p).nr_pci[i] = served_celles_item_p->served_Cell_Information.nRPCI; + F1AP_SETUP_REQ(message_p).nr_pci[i] = served_cells_item_p->served_Cell_Information.nRPCI; LOG_D(F1AP, "F1AP_SETUP_REQ(message_p).nr_pci[%d] %d \n", i, F1AP_SETUP_REQ(message_p).nr_pci[i]); // System Information /* mib */ - F1AP_SETUP_REQ(message_p).mib[i] = calloc(served_celles_item_p->gNB_DU_System_Information->mIB_message.size + 1, sizeof(char)); - memcpy(F1AP_SETUP_REQ(message_p).mib[i], served_celles_item_p->gNB_DU_System_Information->mIB_message.buf, - served_celles_item_p->gNB_DU_System_Information->mIB_message.size); + F1AP_SETUP_REQ(message_p).mib[i] = calloc(served_cells_item_p->gNB_DU_System_Information->mIB_message.size + 1, sizeof(char)); + memcpy(F1AP_SETUP_REQ(message_p).mib[i], served_cells_item_p->gNB_DU_System_Information->mIB_message.buf, + served_cells_item_p->gNB_DU_System_Information->mIB_message.size); /* Convert the mme name to a printable string */ - F1AP_SETUP_REQ(message_p).mib[i][served_celles_item_p->gNB_DU_System_Information->mIB_message.size] = '\0'; - F1AP_SETUP_REQ(message_p).mib_length[i] = served_celles_item_p->gNB_DU_System_Information->mIB_message.size; + F1AP_SETUP_REQ(message_p).mib[i][served_cells_item_p->gNB_DU_System_Information->mIB_message.size] = '\0'; + F1AP_SETUP_REQ(message_p).mib_length[i] = served_cells_item_p->gNB_DU_System_Information->mIB_message.size; LOG_D(F1AP, "F1AP_SETUP_REQ(message_p).mib[%d] %s , len = %d \n", i, F1AP_SETUP_REQ(message_p).mib[i], F1AP_SETUP_REQ(message_p).mib_length[i]); /* sib1 */ - F1AP_SETUP_REQ(message_p).sib1[i] = calloc(served_celles_item_p->gNB_DU_System_Information->sIB1_message.size + 1, sizeof(char)); - memcpy(F1AP_SETUP_REQ(message_p).sib1[i], served_celles_item_p->gNB_DU_System_Information->sIB1_message.buf, - served_celles_item_p->gNB_DU_System_Information->sIB1_message.size); + F1AP_SETUP_REQ(message_p).sib1[i] = calloc(served_cells_item_p->gNB_DU_System_Information->sIB1_message.size + 1, sizeof(char)); + memcpy(F1AP_SETUP_REQ(message_p).sib1[i], served_cells_item_p->gNB_DU_System_Information->sIB1_message.buf, + served_cells_item_p->gNB_DU_System_Information->sIB1_message.size); /* Convert the mme name to a printable string */ - F1AP_SETUP_REQ(message_p).sib1[i][served_celles_item_p->gNB_DU_System_Information->sIB1_message.size] = '\0'; - F1AP_SETUP_REQ(message_p).sib1_length[i] = served_celles_item_p->gNB_DU_System_Information->sIB1_message.size; + F1AP_SETUP_REQ(message_p).sib1[i][served_cells_item_p->gNB_DU_System_Information->sIB1_message.size] = '\0'; + F1AP_SETUP_REQ(message_p).sib1_length[i] = served_cells_item_p->gNB_DU_System_Information->sIB1_message.size; LOG_D(F1AP, "F1AP_SETUP_REQ(message_p).sib1[%d] %s , len = %d \n", i, F1AP_SETUP_REQ(message_p).sib1[i], F1AP_SETUP_REQ(message_p).sib1_length[i]); } @@ -245,10 +250,18 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, ); if (num_cells_available > 0) { - itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); + if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_CU) { + itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); + } else { + itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); + } } else { CU_send_F1_SETUP_FAILURE(instance); - itti_free(TASK_RRC_ENB,message_p); + if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_CU) { + itti_free(TASK_RRC_GNB,message_p); + } else { + itti_free(TASK_RRC_ENB,message_p); + } return -1; } return 0; @@ -305,45 +318,51 @@ int CU_send_F1_SETUP_RESPONSE(instance_t instance, /* mandatory */ /* c3. cells to be Activated list */ - ie = (F1AP_F1SetupResponseIEs_t *)calloc(1, sizeof(F1AP_F1SetupResponseIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List; - int num_cells_to_activate = f1ap_setup_resp->num_cells_to_activate; LOG_D(F1AP, "num_cells_to_activate = %d \n", num_cells_to_activate); - for (i=0; - i0) { + ie = (F1AP_F1SetupResponseIEs_t *)calloc(1, sizeof(F1AP_F1SetupResponseIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List; - F1AP_Cells_to_be_Activated_List_ItemIEs_t *cells_to_be_activated_list_item_ies; - cells_to_be_activated_list_item_ies = (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Activated_List_ItemIEs_t)); - cells_to_be_activated_list_item_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; - cells_to_be_activated_list_item_ies->criticality = F1AP_Criticality_reject; - cells_to_be_activated_list_item_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; + for (i=0; icells_to_activate[i].mcc, + f1ap_setup_resp->cells_to_activate[i].mnc, + f1ap_setup_resp->cells_to_activate[i].mnc_digit_length, + f1ap_setup_resp->cells_to_activate[i].nr_cellid); - /* - nRCGI */ - F1AP_NRCGI_t nRCGI; - memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); - MCC_MNC_TO_PLMNID(f1ap_setup_resp->mcc[i], f1ap_setup_resp->mnc[i], f1ap_setup_resp->mnc_digit_length[i], - &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(f1ap_setup_resp->nr_cellid[i], &nRCGI.nRCellIdentity); - cells_to_be_activated_list_item.nRCGI = nRCGI; + F1AP_Cells_to_be_Activated_List_ItemIEs_t *cells_to_be_activated_list_item_ies; + cells_to_be_activated_list_item_ies = (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Activated_List_ItemIEs_t)); + cells_to_be_activated_list_item_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; + cells_to_be_activated_list_item_ies->criticality = F1AP_Criticality_reject; + cells_to_be_activated_list_item_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; - /* optional */ - /* - nRPCI */ - if (1) { - cells_to_be_activated_list_item.nRPCI = (F1AP_NRPCI_t *)calloc(1, sizeof(F1AP_NRPCI_t)); - *cells_to_be_activated_list_item.nRPCI = f1ap_setup_resp->nrpci[i]; // int 0..1007 - } + /* 3.1 cells to be Activated list item */ + F1AP_Cells_to_be_Activated_List_Item_t cells_to_be_activated_list_item; + memset((void *)&cells_to_be_activated_list_item, 0, sizeof(F1AP_Cells_to_be_Activated_List_Item_t)); - /* optional */ - /* - gNB-CU System Information */ - if (1) { + /* - nRCGI */ + F1AP_NRCGI_t nRCGI; + memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); + MCC_MNC_TO_PLMNID(f1ap_setup_resp->cells_to_activate[i].mcc, f1ap_setup_resp->cells_to_activate[i].mnc, f1ap_setup_resp->cells_to_activate[i].mnc_digit_length, + &nRCGI.pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(f1ap_setup_resp->cells_to_activate[i].nr_cellid, &nRCGI.nRCellIdentity); + cells_to_be_activated_list_item.nRCGI = nRCGI; + + /* optional */ + /* - nRPCI */ + if (1) { + cells_to_be_activated_list_item.nRPCI = (F1AP_NRPCI_t *)calloc(1, sizeof(F1AP_NRPCI_t)); + *cells_to_be_activated_list_item.nRPCI = f1ap_setup_resp->cells_to_activate[i].nrpci; // int 0..1007 + } + + /* optional */ + /* - gNB-CU System Information */ + if (1) { /* 3.1.2 gNB-CUSystem Information */ F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs; cells_to_be_activated_list_itemExtIEs = (F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Activated_List_ItemExtIEs_t)); @@ -355,35 +374,44 @@ int CU_send_F1_SETUP_RESPONSE(instance_t instance, //LOG_I(F1AP, "%s() SI %d size %d: ", __func__, i, f1ap_setup_resp->SI_container_length[i][0]); //for (int n = 0; n < f1ap_setup_resp->SI_container_length[i][0]; n++) // printf("%02x ", f1ap_setup_resp->SI_container[i][0][n]); - //printf("\n"); - OCTET_STRING_fromBuf(&gNB_CUSystemInformation->sImessage, - (const char*)f1ap_setup_resp->SI_container[i][0], - f1ap_setup_resp->SI_container_length[i][0]); + //printf("\n"); - LOG_D(F1AP, "f1ap_setup_resp->SI_container_length = %d \n", f1ap_setup_resp->SI_container_length[0][0]); + // for (int sIBtype=2;sIBtype<33;sIBtype++) { //21 ? 33 ? + for (int sIBtype=2;sIBtype<21;sIBtype++) { + if (f1ap_setup_resp->cells_to_activate[i].SI_container[sIBtype]!=NULL) { + AssertFatal(sIBtype < 6 || sIBtype == 9, "Illegal SI type %d\n",sIBtype); + F1AP_SibtypetobeupdatedListItem_t *sib_item = calloc(1,sizeof(*sib_item)); + memset((void*)sib_item,0,sizeof(*sib_item)); + sib_item->sIBtype = sIBtype; + OCTET_STRING_fromBuf(&sib_item->sIBmessage, + (const char*)f1ap_setup_resp->cells_to_activate[i].SI_container[sIBtype], + f1ap_setup_resp->cells_to_activate[i].SI_container_length[sIBtype]); + + LOG_D(F1AP, "f1ap_setup_resp->SI_container_length[%d][%d] = %d \n", i,sIBtype,f1ap_setup_resp->cells_to_activate[i].SI_container_length[sIBtype]); + ASN_SEQUENCE_ADD(&gNB_CUSystemInformation->sibtypetobeupdatedlist.list,sib_item); + } + } cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation = *gNB_CUSystemInformation; + F1AP_ProtocolExtensionContainer_154P112_t p_154P112_t; + memset((void *)&p_154P112_t, 0, sizeof(F1AP_ProtocolExtensionContainer_154P112_t)); - F1AP_ProtocolExtensionContainer_160P9_t p_160P9_t; - memset((void *)&p_160P9_t, 0, sizeof(F1AP_ProtocolExtensionContainer_160P9_t)); - - ASN_SEQUENCE_ADD(&p_160P9_t.list, - cells_to_be_activated_list_itemExtIEs); - cells_to_be_activated_list_item.iE_Extensions = (struct F1AP_ProtocolExtensionContainer*)&p_160P9_t; + ASN_SEQUENCE_ADD(&p_154P112_t.list, cells_to_be_activated_list_itemExtIEs); + cells_to_be_activated_list_item.iE_Extensions = (struct F1AP_ProtocolExtensionContainer*)&p_154P112_t; free(gNB_CUSystemInformation); gNB_CUSystemInformation = NULL; + } + /* ADD */ + cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item = cells_to_be_activated_list_item; + ASN_SEQUENCE_ADD(&ie->value.choice.Cells_to_be_Activated_List.list, cells_to_be_activated_list_item_ies); } - /* ADD */ - cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item = cells_to_be_activated_list_item; - ASN_SEQUENCE_ADD(&ie->value.choice.Cells_to_be_Activated_List.list, - cells_to_be_activated_list_item_ies); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 setup response\n"); return -1; } @@ -469,7 +497,7 @@ int CU_send_F1_SETUP_FAILURE(instance_t instance) { /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 setup failure\n"); return -1; } @@ -508,7 +536,7 @@ int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, */ //void CU_send_gNB_CU_CONFIGURATION_UPDATE(F1AP_GNBCUConfigurationUpdate_t *GNBCUConfigurationUpdate) { -int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_idP) { +int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, f1ap_gnb_cu_configuration_update_t *f1ap_gnb_cu_configuration_update) { F1AP_F1AP_PDU_t pdu; F1AP_GNBCUConfigurationUpdate_t *out; F1AP_GNBCUConfigurationUpdateIEs_t *ie; @@ -517,10 +545,6 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_ uint32_t len; int i = 0; - // for test - int mcc = 208; - int mnc = 93; - int mnc_digit_length = 8; /* Create */ /* 0. Message Type */ @@ -538,308 +562,355 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_ ie->id = F1AP_ProtocolIE_ID_id_TransactionID; ie->criticality = F1AP_Criticality_reject; ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID; - ie->value.choice.TransactionID = F1AP_get_next_transaction_identifier(instance, du_mod_idP); + ie->value.choice.TransactionID = F1AP_get_next_transaction_identifier(instance, 0); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - /* mandatory */ - /* c2. Cells_to_be_Activated_List */ - ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List; + // mandatory + // c2. Cells_to_be_Activated_List + if (f1ap_gnb_cu_configuration_update->num_cells_to_activate > 0) { + ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List; - for (i=0; - i<1; - i++) { + for (i=0; inum_cells_to_activate; i++) { - F1AP_Cells_to_be_Activated_List_ItemIEs_t *cells_to_be_activated_list_item_ies; - cells_to_be_activated_list_item_ies = (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Activated_List_ItemIEs_t)); - cells_to_be_activated_list_item_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; - cells_to_be_activated_list_item_ies->criticality = F1AP_Criticality_reject; - cells_to_be_activated_list_item_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; + LOG_D(F1AP, "[c2] (cell %d) mcc = %d, mnc = %d, mnc_digit_length = %d, nr_cellid = %lu\n", + i, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mcc, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mnc, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mnc_digit_length, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].nr_cellid); - /* 2.1 cells to be Activated list item */ - F1AP_Cells_to_be_Activated_List_Item_t cells_to_be_activated_list_item; - memset((void *)&cells_to_be_activated_list_item, 0, sizeof(F1AP_Cells_to_be_Activated_List_Item_t)); + F1AP_Cells_to_be_Activated_List_ItemIEs_t *cells_to_be_activated_list_item_ies; + cells_to_be_activated_list_item_ies = (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Activated_List_ItemIEs_t)); + cells_to_be_activated_list_item_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; + cells_to_be_activated_list_item_ies->criticality = F1AP_Criticality_reject; + cells_to_be_activated_list_item_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; - /* - nRCGI */ - F1AP_NRCGI_t nRCGI; - memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); - MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, - &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); - cells_to_be_activated_list_item.nRCGI = nRCGI; + // 2.1 cells to be Activated list item + F1AP_Cells_to_be_Activated_List_Item_t cells_to_be_activated_list_item; + memset((void *)&cells_to_be_activated_list_item, 0, sizeof(F1AP_Cells_to_be_Activated_List_Item_t)); - /* optional */ - /* - nRPCI */ - if (0) { - cells_to_be_activated_list_item.nRPCI = (F1AP_NRPCI_t *)calloc(1, sizeof(F1AP_NRPCI_t)); - *cells_to_be_activated_list_item.nRPCI = 321L; // int 0..1007 - } + // - nRCGI + F1AP_NRCGI_t nRCGI; + memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); + MCC_MNC_TO_PLMNID(f1ap_gnb_cu_configuration_update->cells_to_activate[i].mcc, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mnc, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mnc_digit_length, + &nRCGI.pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(f1ap_gnb_cu_configuration_update->cells_to_activate[i].nr_cellid, + &nRCGI.nRCellIdentity); + cells_to_be_activated_list_item.nRCGI = nRCGI; - /* optional */ - /* - gNB-CU System Information */ - //if (1) { + if(RC.nrrrc) { - //} - /* ADD */ - cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item = cells_to_be_activated_list_item; - ASN_SEQUENCE_ADD(&ie->value.choice.Cells_to_be_Activated_List.list, - cells_to_be_activated_list_item_ies); - } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + // optional + // -nRPCI + cells_to_be_activated_list_item.nRPCI = (F1AP_NRPCI_t *)calloc(1, sizeof(F1AP_NRPCI_t)); + *cells_to_be_activated_list_item.nRPCI = f1ap_gnb_cu_configuration_update->cells_to_activate[i].nrpci; // int 0..1007 + + // optional + // 3.1.2 gNB-CUSystem Information + F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs; + cells_to_be_activated_list_itemExtIEs = (F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Activated_List_ItemExtIEs_t)); + cells_to_be_activated_list_itemExtIEs->id = F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation; + cells_to_be_activated_list_itemExtIEs->criticality = F1AP_Criticality_reject; + cells_to_be_activated_list_itemExtIEs->extensionValue.present = F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation; + + if (f1ap_gnb_cu_configuration_update->cells_to_activate[i].num_SI > 0) { + F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = (F1AP_GNB_CUSystemInformation_t *)calloc(1, sizeof(F1AP_GNB_CUSystemInformation_t)); + //LOG_I(F1AP, "%s() SI %d size %d: ", __func__, i, f1ap_setup_resp->SI_container_length[i][0]); + //for (int n = 0; n < f1ap_setup_resp->SI_container_length[i][0]; n++) + // printf("%02x ", f1ap_setup_resp->SI_container[i][0][n]); + //printf("\n"); + + // for (int sIBtype=2;sIBtype<33;sIBtype++) { //21 ? 33 ? + for (int sIBtype=2;sIBtype<21;sIBtype++) { + if (f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container[sIBtype]!=NULL) { + AssertFatal(sIBtype < 6 || sIBtype == 9, "Illegal SI type %d\n",sIBtype); + F1AP_SibtypetobeupdatedListItem_t *sib_item = calloc(1,sizeof(*sib_item)); + memset((void*)sib_item,0,sizeof(*sib_item)); + sib_item->sIBtype = sIBtype; + OCTET_STRING_fromBuf(&sib_item->sIBmessage, + (const char*)f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container[sIBtype], + f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container_length[sIBtype]); + + LOG_D(F1AP, "f1ap_setup_resp->SI_container_length[%d][%d] = %d \n", i,sIBtype,f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container_length[sIBtype]); + ASN_SEQUENCE_ADD(&gNB_CUSystemInformation->sibtypetobeupdatedlist.list,sib_item); + } + } + cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation = *gNB_CUSystemInformation; + F1AP_ProtocolExtensionContainer_154P112_t p_154P112_t; + memset((void *)&p_154P112_t, 0, sizeof(F1AP_ProtocolExtensionContainer_154P112_t)); - /* mandatory */ - /* c3. Cells_to_be_Deactivated_List */ - ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Deactivated_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Deactivated_List; + ASN_SEQUENCE_ADD(&p_154P112_t.list, + cells_to_be_activated_list_itemExtIEs); + cells_to_be_activated_list_item.iE_Extensions = (struct F1AP_ProtocolExtensionContainer*)&p_154P112_t; - for (i=0; - i<1; - i++) { + free(gNB_CUSystemInformation); + gNB_CUSystemInformation = NULL; + } + } - F1AP_Cells_to_be_Deactivated_List_ItemIEs_t *cells_to_be_deactivated_list_item_ies; - cells_to_be_deactivated_list_item_ies = (F1AP_Cells_to_be_Deactivated_List_ItemIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Deactivated_List_ItemIEs_t)); - cells_to_be_deactivated_list_item_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; - cells_to_be_deactivated_list_item_ies->criticality = F1AP_Criticality_reject; - cells_to_be_deactivated_list_item_ies->value.present = F1AP_Cells_to_be_Deactivated_List_ItemIEs__value_PR_Cells_to_be_Deactivated_List_Item; + // ADD + cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item = cells_to_be_activated_list_item; + ASN_SEQUENCE_ADD(&ie->value.choice.Cells_to_be_Activated_List.list, + cells_to_be_activated_list_item_ies); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - /* 3.1 cells to be Deactivated list item */ - F1AP_Cells_to_be_Deactivated_List_Item_t cells_to_be_deactivated_list_item; - memset((void *)&cells_to_be_deactivated_list_item, 0, sizeof(F1AP_Cells_to_be_Deactivated_List_Item_t)); - - /* - nRCGI */ - F1AP_NRCGI_t nRCGI; - memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); - MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, - &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); - cells_to_be_deactivated_list_item.nRCGI = nRCGI; - - //} - /* ADD */ - cells_to_be_deactivated_list_item_ies->value.choice.Cells_to_be_Deactivated_List_Item = cells_to_be_deactivated_list_item; - ASN_SEQUENCE_ADD(&ie->value.choice.Cells_to_be_Deactivated_List.list, - cells_to_be_deactivated_list_item_ies); - } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - - - /* mandatory */ - /* c4. GNB_CU_TNL_Association_To_Add_List */ - ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Add_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_GNB_CU_TNL_Association_To_Add_List; - - for (i=0; - i<1; - i++) { - - F1AP_GNB_CU_TNL_Association_To_Add_ItemIEs_t *gnb_cu_tnl_association_to_add_item_ies; - gnb_cu_tnl_association_to_add_item_ies = (F1AP_GNB_CU_TNL_Association_To_Add_ItemIEs_t *)calloc(1, sizeof(F1AP_GNB_CU_TNL_Association_To_Add_ItemIEs_t)); - gnb_cu_tnl_association_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Add_Item; - gnb_cu_tnl_association_to_add_item_ies->criticality = F1AP_Criticality_reject; - gnb_cu_tnl_association_to_add_item_ies->value.present = F1AP_GNB_CU_TNL_Association_To_Add_ItemIEs__value_PR_GNB_CU_TNL_Association_To_Add_Item; - - /* 4.1 GNB_CU_TNL_Association_To_Add_Item */ - F1AP_GNB_CU_TNL_Association_To_Add_Item_t gnb_cu_tnl_association_to_add_item; - memset((void *)&gnb_cu_tnl_association_to_add_item, 0, sizeof(F1AP_GNB_CU_TNL_Association_To_Add_Item_t)); - - - /* 4.1.1 tNLAssociationTransportLayerAddress */ - F1AP_CP_TransportLayerAddress_t transportLayerAddress; - memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); - transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); - - // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); - // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; - // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); - // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); - - gnb_cu_tnl_association_to_add_item.tNLAssociationTransportLayerAddress = transportLayerAddress; - - /* 4.1.2 tNLAssociationUsage */ - gnb_cu_tnl_association_to_add_item.tNLAssociationUsage = F1AP_TNLAssociationUsage_non_ue; - - - /* ADD */ - gnb_cu_tnl_association_to_add_item_ies->value.choice.GNB_CU_TNL_Association_To_Add_Item = gnb_cu_tnl_association_to_add_item; - ASN_SEQUENCE_ADD(&ie->value.choice.GNB_CU_TNL_Association_To_Add_List.list, - gnb_cu_tnl_association_to_add_item_ies); - } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - - - - /* mandatory */ - /* c5. GNB_CU_TNL_Association_To_Remove_List */ - ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Remove_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_GNB_CU_TNL_Association_To_Remove_List; - for (i=0; - i<1; - i++) { - - F1AP_GNB_CU_TNL_Association_To_Remove_ItemIEs_t *gnb_cu_tnl_association_to_remove_item_ies; - gnb_cu_tnl_association_to_remove_item_ies = (F1AP_GNB_CU_TNL_Association_To_Remove_ItemIEs_t *)calloc(1, sizeof(F1AP_GNB_CU_TNL_Association_To_Remove_ItemIEs_t)); - gnb_cu_tnl_association_to_remove_item_ies->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Remove_Item; - gnb_cu_tnl_association_to_remove_item_ies->criticality = F1AP_Criticality_reject; - gnb_cu_tnl_association_to_remove_item_ies->value.present = F1AP_GNB_CU_TNL_Association_To_Remove_ItemIEs__value_PR_GNB_CU_TNL_Association_To_Remove_Item; - - /* 4.1 GNB_CU_TNL_Association_To_Remove_Item */ - F1AP_GNB_CU_TNL_Association_To_Remove_Item_t gnb_cu_tnl_association_to_remove_item; - memset((void *)&gnb_cu_tnl_association_to_remove_item, 0, sizeof(F1AP_GNB_CU_TNL_Association_To_Remove_Item_t)); - - - /* 4.1.1 tNLAssociationTransportLayerAddress */ - F1AP_CP_TransportLayerAddress_t transportLayerAddress; - memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); - transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); - - // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); - // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; - // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); - // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); - - gnb_cu_tnl_association_to_remove_item.tNLAssociationTransportLayerAddress = transportLayerAddress; - - - /* ADD */ - gnb_cu_tnl_association_to_remove_item_ies->value.choice.GNB_CU_TNL_Association_To_Remove_Item = gnb_cu_tnl_association_to_remove_item; - ASN_SEQUENCE_ADD(&ie->value.choice.GNB_CU_TNL_Association_To_Remove_List.list, - gnb_cu_tnl_association_to_remove_item_ies); - } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - - /* mandatory */ - /* c6. GNB_CU_TNL_Association_To_Update_List */ - ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Update_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_GNB_CU_TNL_Association_To_Update_List; - for (i=0; - i<1; - i++) { - - F1AP_GNB_CU_TNL_Association_To_Update_ItemIEs_t *gnb_cu_tnl_association_to_update_item_ies; - gnb_cu_tnl_association_to_update_item_ies = (F1AP_GNB_CU_TNL_Association_To_Update_ItemIEs_t *)calloc(1, sizeof(F1AP_GNB_CU_TNL_Association_To_Update_ItemIEs_t)); - gnb_cu_tnl_association_to_update_item_ies->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Update_Item; - gnb_cu_tnl_association_to_update_item_ies->criticality = F1AP_Criticality_reject; - gnb_cu_tnl_association_to_update_item_ies->value.present = F1AP_GNB_CU_TNL_Association_To_Update_ItemIEs__value_PR_GNB_CU_TNL_Association_To_Update_Item; - - /* 4.1 GNB_CU_TNL_Association_To_Update_Item */ - F1AP_GNB_CU_TNL_Association_To_Update_Item_t gnb_cu_tnl_association_to_update_item; - memset((void *)&gnb_cu_tnl_association_to_update_item, 0, sizeof(F1AP_GNB_CU_TNL_Association_To_Update_Item_t)); - - - /* 4.1.1 tNLAssociationTransportLayerAddress */ - F1AP_CP_TransportLayerAddress_t transportLayerAddress; - memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); - transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); - - // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); - // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; - // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); - // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); - - gnb_cu_tnl_association_to_update_item.tNLAssociationTransportLayerAddress = transportLayerAddress; - - - /* 4.1.2 tNLAssociationUsage */ - if (1) { - gnb_cu_tnl_association_to_update_item.tNLAssociationUsage = (F1AP_TNLAssociationUsage_t *)calloc(1, sizeof(F1AP_TNLAssociationUsage_t)); - *gnb_cu_tnl_association_to_update_item.tNLAssociationUsage = F1AP_TNLAssociationUsage_non_ue; - } - - /* ADD */ - gnb_cu_tnl_association_to_update_item_ies->value.choice.GNB_CU_TNL_Association_To_Update_Item = gnb_cu_tnl_association_to_update_item; - ASN_SEQUENCE_ADD(&ie->value.choice.GNB_CU_TNL_Association_To_Update_List.list, - gnb_cu_tnl_association_to_update_item_ies); - } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - - - - /* mandatory */ - /* c7. Cells_to_be_Barred_List */ - ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Barred_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Barred_List; - for (i=0; - i<1; - i++) { - - F1AP_Cells_to_be_Barred_ItemIEs_t *cells_to_be_barred_item_ies; - cells_to_be_barred_item_ies = (F1AP_Cells_to_be_Barred_ItemIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Barred_ItemIEs_t)); - cells_to_be_barred_item_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; - cells_to_be_barred_item_ies->criticality = F1AP_Criticality_reject; - cells_to_be_barred_item_ies->value.present = F1AP_Cells_to_be_Barred_ItemIEs__value_PR_Cells_to_be_Barred_Item; - - /* 7.1 cells to be Deactivated list item */ - F1AP_Cells_to_be_Barred_Item_t cells_to_be_barred_item; - memset((void *)&cells_to_be_barred_item, 0, sizeof(F1AP_Cells_to_be_Barred_Item_t)); - - /* - nRCGI */ - F1AP_NRCGI_t nRCGI; - memset(&nRCGI,0,sizeof(F1AP_NRCGI_t)); - MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, - &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); - cells_to_be_barred_item.nRCGI = nRCGI; - - /* 7.2 cellBarred*/ - cells_to_be_barred_item.cellBarred = F1AP_CellBarred_not_barred; - - /* ADD */ - cells_to_be_barred_item_ies->value.choice.Cells_to_be_Barred_Item = cells_to_be_barred_item; - ASN_SEQUENCE_ADD(&ie->value.choice.Cells_to_be_Barred_List.list, - cells_to_be_barred_item_ies); } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + if(!RC.nrrrc) { + + /* mandatory */ + /* c3. Cells_to_be_Deactivated_List */ + ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Deactivated_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Deactivated_List; + + for (i=0; + i<1; + i++) { + + F1AP_Cells_to_be_Deactivated_List_ItemIEs_t *cells_to_be_deactivated_list_item_ies; + cells_to_be_deactivated_list_item_ies = (F1AP_Cells_to_be_Deactivated_List_ItemIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Deactivated_List_ItemIEs_t)); + cells_to_be_deactivated_list_item_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; + cells_to_be_deactivated_list_item_ies->criticality = F1AP_Criticality_reject; + cells_to_be_deactivated_list_item_ies->value.present = F1AP_Cells_to_be_Deactivated_List_ItemIEs__value_PR_Cells_to_be_Deactivated_List_Item; + + // 3.1 cells to be Deactivated list item + F1AP_Cells_to_be_Deactivated_List_Item_t cells_to_be_deactivated_list_item; + memset((void *)&cells_to_be_deactivated_list_item, 0, sizeof(F1AP_Cells_to_be_Deactivated_List_Item_t)); + + + F1AP_NRCGI_t nRCGI; + memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); + MCC_MNC_TO_PLMNID(f1ap_gnb_cu_configuration_update->cells_to_activate[i].mcc, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mnc, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mnc_digit_length, + &nRCGI.pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(f1ap_gnb_cu_configuration_update->cells_to_activate[i].nr_cellid, &nRCGI.nRCellIdentity); + cells_to_be_deactivated_list_item.nRCGI = nRCGI; + + cells_to_be_deactivated_list_item_ies->value.choice.Cells_to_be_Deactivated_List_Item = cells_to_be_deactivated_list_item; + ASN_SEQUENCE_ADD(&ie->value.choice.Cells_to_be_Deactivated_List.list, + cells_to_be_deactivated_list_item_ies); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + /* mandatory */ + /* c4. GNB_CU_TNL_Association_To_Add_List */ + ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Add_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_GNB_CU_TNL_Association_To_Add_List; + + for (i=0; + i<1; + i++) { + + F1AP_GNB_CU_TNL_Association_To_Add_ItemIEs_t *gnb_cu_tnl_association_to_add_item_ies; + gnb_cu_tnl_association_to_add_item_ies = (F1AP_GNB_CU_TNL_Association_To_Add_ItemIEs_t *)calloc(1, sizeof(F1AP_GNB_CU_TNL_Association_To_Add_ItemIEs_t)); + gnb_cu_tnl_association_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Add_Item; + gnb_cu_tnl_association_to_add_item_ies->criticality = F1AP_Criticality_reject; + gnb_cu_tnl_association_to_add_item_ies->value.present = F1AP_GNB_CU_TNL_Association_To_Add_ItemIEs__value_PR_GNB_CU_TNL_Association_To_Add_Item; + + // 4.1 GNB_CU_TNL_Association_To_Add_Item + F1AP_GNB_CU_TNL_Association_To_Add_Item_t gnb_cu_tnl_association_to_add_item; + memset((void *)&gnb_cu_tnl_association_to_add_item, 0, sizeof(F1AP_GNB_CU_TNL_Association_To_Add_Item_t)); + + + // 4.1.1 tNLAssociationTransportLayerAddress + F1AP_CP_TransportLayerAddress_t transportLayerAddress; + memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); + transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); + + // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); + // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; + // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); + // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); + + gnb_cu_tnl_association_to_add_item.tNLAssociationTransportLayerAddress = transportLayerAddress; + + // 4.1.2 tNLAssociationUsage + gnb_cu_tnl_association_to_add_item.tNLAssociationUsage = F1AP_TNLAssociationUsage_non_ue; - /* mandatory */ - /* c8. Protected_EUTRA_Resources_List */ - ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_Protected_EUTRA_Resources_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Protected_EUTRA_Resources_List; - - for (i=0; - i<1; - i++) { + gnb_cu_tnl_association_to_add_item_ies->value.choice.GNB_CU_TNL_Association_To_Add_Item = gnb_cu_tnl_association_to_add_item; + ASN_SEQUENCE_ADD(&ie->value.choice.GNB_CU_TNL_Association_To_Add_List.list, + gnb_cu_tnl_association_to_add_item_ies); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - F1AP_Protected_EUTRA_Resources_ItemIEs_t *protected_eutra_resources_item_ies; + /* mandatory */ + /* c5. GNB_CU_TNL_Association_To_Remove_List */ + ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Remove_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_GNB_CU_TNL_Association_To_Remove_List; + for (i=0; + i<1; + i++) { - /* 8.1 SpectrumSharingGroupID */ - protected_eutra_resources_item_ies = (F1AP_Protected_EUTRA_Resources_ItemIEs_t *)calloc(1, sizeof(F1AP_Protected_EUTRA_Resources_ItemIEs_t)); - protected_eutra_resources_item_ies->id = F1AP_ProtocolIE_ID_id_Protected_EUTRA_Resources_List; - protected_eutra_resources_item_ies->criticality = F1AP_Criticality_reject; - protected_eutra_resources_item_ies->value.present = F1AP_Protected_EUTRA_Resources_ItemIEs__value_PR_SpectrumSharingGroupID; - protected_eutra_resources_item_ies->value.choice.SpectrumSharingGroupID = 1L; + F1AP_GNB_CU_TNL_Association_To_Remove_ItemIEs_t *gnb_cu_tnl_association_to_remove_item_ies; + gnb_cu_tnl_association_to_remove_item_ies = (F1AP_GNB_CU_TNL_Association_To_Remove_ItemIEs_t *)calloc(1, sizeof(F1AP_GNB_CU_TNL_Association_To_Remove_ItemIEs_t)); + gnb_cu_tnl_association_to_remove_item_ies->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Remove_Item; + gnb_cu_tnl_association_to_remove_item_ies->criticality = F1AP_Criticality_reject; + gnb_cu_tnl_association_to_remove_item_ies->value.present = F1AP_GNB_CU_TNL_Association_To_Remove_ItemIEs__value_PR_GNB_CU_TNL_Association_To_Remove_Item; - ASN_SEQUENCE_ADD(&ie->value.choice.Protected_EUTRA_Resources_List.list, protected_eutra_resources_item_ies); + // 4.1 GNB_CU_TNL_Association_To_Remove_Item + F1AP_GNB_CU_TNL_Association_To_Remove_Item_t gnb_cu_tnl_association_to_remove_item; + memset((void *)&gnb_cu_tnl_association_to_remove_item, 0, sizeof(F1AP_GNB_CU_TNL_Association_To_Remove_Item_t)); - /* 8.2 ListofEUTRACellsinGNBDUCoordination */ - protected_eutra_resources_item_ies = (F1AP_Protected_EUTRA_Resources_ItemIEs_t *)calloc(1, sizeof(F1AP_Protected_EUTRA_Resources_ItemIEs_t)); - protected_eutra_resources_item_ies->id = F1AP_ProtocolIE_ID_id_Protected_EUTRA_Resources_List; - protected_eutra_resources_item_ies->criticality = F1AP_Criticality_reject; - protected_eutra_resources_item_ies->value.present = F1AP_Protected_EUTRA_Resources_ItemIEs__value_PR_ListofEUTRACellsinGNBDUCoordination; + // 4.1.1 tNLAssociationTransportLayerAddress + F1AP_CP_TransportLayerAddress_t transportLayerAddress; + memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); + transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); + + // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); + // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; + // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); + // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); + + gnb_cu_tnl_association_to_remove_item.tNLAssociationTransportLayerAddress = transportLayerAddress; + + + + gnb_cu_tnl_association_to_remove_item_ies->value.choice.GNB_CU_TNL_Association_To_Remove_Item = gnb_cu_tnl_association_to_remove_item; + ASN_SEQUENCE_ADD(&ie->value.choice.GNB_CU_TNL_Association_To_Remove_List.list, + gnb_cu_tnl_association_to_remove_item_ies); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + /* mandatory */ + /* c6. GNB_CU_TNL_Association_To_Update_List */ + ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Update_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_GNB_CU_TNL_Association_To_Update_List; + for (i=0; + i<1; + i++) { + + F1AP_GNB_CU_TNL_Association_To_Update_ItemIEs_t *gnb_cu_tnl_association_to_update_item_ies; + gnb_cu_tnl_association_to_update_item_ies = (F1AP_GNB_CU_TNL_Association_To_Update_ItemIEs_t *)calloc(1, sizeof(F1AP_GNB_CU_TNL_Association_To_Update_ItemIEs_t)); + gnb_cu_tnl_association_to_update_item_ies->id = F1AP_ProtocolIE_ID_id_GNB_CU_TNL_Association_To_Update_Item; + gnb_cu_tnl_association_to_update_item_ies->criticality = F1AP_Criticality_reject; + gnb_cu_tnl_association_to_update_item_ies->value.present = F1AP_GNB_CU_TNL_Association_To_Update_ItemIEs__value_PR_GNB_CU_TNL_Association_To_Update_Item; + + // 4.1 GNB_CU_TNL_Association_To_Update_Item + F1AP_GNB_CU_TNL_Association_To_Update_Item_t gnb_cu_tnl_association_to_update_item; + memset((void *)&gnb_cu_tnl_association_to_update_item, 0, sizeof(F1AP_GNB_CU_TNL_Association_To_Update_Item_t)); + + + // 4.1.1 tNLAssociationTransportLayerAddress + F1AP_CP_TransportLayerAddress_t transportLayerAddress; + memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); + transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address; + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address); + + // memset((void *)&transportLayerAddress, 0, sizeof(F1AP_CP_TransportLayerAddress_t)); + // transportLayerAddress.present = F1AP_CP_TransportLayerAddress_PR_endpoint_IP_address_and_port; + // transportLayerAddress.choice.endpoint_IP_address_and_port = (F1AP_Endpoint_IP_address_and_port_t *)calloc(1, sizeof(F1AP_Endpoint_IP_address_and_port_t)); + // TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &transportLayerAddress.choice.endpoint_IP_address_and_port.endpoint_IP_address); + + gnb_cu_tnl_association_to_update_item.tNLAssociationTransportLayerAddress = transportLayerAddress; + + + // 4.1.2 tNLAssociationUsage + if (1) { + gnb_cu_tnl_association_to_update_item.tNLAssociationUsage = (F1AP_TNLAssociationUsage_t *)calloc(1, sizeof(F1AP_TNLAssociationUsage_t)); + *gnb_cu_tnl_association_to_update_item.tNLAssociationUsage = F1AP_TNLAssociationUsage_non_ue; + } + + + gnb_cu_tnl_association_to_update_item_ies->value.choice.GNB_CU_TNL_Association_To_Update_Item = gnb_cu_tnl_association_to_update_item; + ASN_SEQUENCE_ADD(&ie->value.choice.GNB_CU_TNL_Association_To_Update_List.list, + gnb_cu_tnl_association_to_update_item_ies); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + /* mandatory */ + /* c7. Cells_to_be_Barred_List */ + ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Barred_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Barred_List; + for (i=0; + i<1; + i++) { + + F1AP_Cells_to_be_Barred_ItemIEs_t *cells_to_be_barred_item_ies; + cells_to_be_barred_item_ies = (F1AP_Cells_to_be_Barred_ItemIEs_t *)calloc(1, sizeof(F1AP_Cells_to_be_Barred_ItemIEs_t)); + cells_to_be_barred_item_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; + cells_to_be_barred_item_ies->criticality = F1AP_Criticality_reject; + cells_to_be_barred_item_ies->value.present = F1AP_Cells_to_be_Barred_ItemIEs__value_PR_Cells_to_be_Barred_Item; + + // 7.1 cells to be Deactivated list item + F1AP_Cells_to_be_Barred_Item_t cells_to_be_barred_item; + memset((void *)&cells_to_be_barred_item, 0, sizeof(F1AP_Cells_to_be_Barred_Item_t)); + + // - nRCGI + F1AP_NRCGI_t nRCGI; + memset(&nRCGI,0,sizeof(F1AP_NRCGI_t)); + MCC_MNC_TO_PLMNID(f1ap_gnb_cu_configuration_update->cells_to_activate[i].mcc, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mnc, + f1ap_gnb_cu_configuration_update->cells_to_activate[i].mnc_digit_length, + &nRCGI.pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(f1ap_gnb_cu_configuration_update->cells_to_activate[i].nr_cellid, &nRCGI.nRCellIdentity); + cells_to_be_barred_item.nRCGI = nRCGI; + + // 7.2 cellBarred + cells_to_be_barred_item.cellBarred = F1AP_CellBarred_not_barred; + + cells_to_be_barred_item_ies->value.choice.Cells_to_be_Barred_Item = cells_to_be_barred_item; + ASN_SEQUENCE_ADD(&ie->value.choice.Cells_to_be_Barred_List.list, + cells_to_be_barred_item_ies); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + /* mandatory */ + /* c8. Protected_EUTRA_Resources_List */ + ie = (F1AP_GNBCUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBCUConfigurationUpdateIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_Protected_EUTRA_Resources_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Protected_EUTRA_Resources_List; + + for (i=0; + i<1; + i++) { + + + F1AP_Protected_EUTRA_Resources_ItemIEs_t *protected_eutra_resources_item_ies; + + // 8.1 SpectrumSharingGroupID + protected_eutra_resources_item_ies = (F1AP_Protected_EUTRA_Resources_ItemIEs_t *)calloc(1, sizeof(F1AP_Protected_EUTRA_Resources_ItemIEs_t)); + protected_eutra_resources_item_ies->id = F1AP_ProtocolIE_ID_id_Protected_EUTRA_Resources_List; + protected_eutra_resources_item_ies->criticality = F1AP_Criticality_reject; + protected_eutra_resources_item_ies->value.present = F1AP_Protected_EUTRA_Resources_ItemIEs__value_PR_Protected_EUTRA_Resources_Item; + ((F1AP_Protected_EUTRA_Resources_Item_t*)&protected_eutra_resources_item_ies->value.choice.Protected_EUTRA_Resources_Item)->spectrumSharingGroupID = 123L; + memset(&protected_eutra_resources_item_ies->value.choice.Protected_EUTRA_Resources_Item,0, + sizeof(F1AP_Protected_EUTRA_Resources_Item_t)); + ASN_SEQUENCE_ADD(&ie->value.choice.Protected_EUTRA_Resources_List.list, protected_eutra_resources_item_ies); + + /* F1AP_Served_EUTRA_Cells_Information_t served_eutra_cells_information; memset((void *)&served_eutra_cells_information, 0, sizeof(F1AP_Served_EUTRA_Cells_Information_t)); @@ -870,16 +941,22 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_ ASN_SEQUENCE_ADD(&protected_eutra_resources_item_ies->value.choice.ListofEUTRACellsinGNBDUCoordination.list, &served_eutra_cells_information); ASN_SEQUENCE_ADD(&ie->value.choice.Protected_EUTRA_Resources_List.list, protected_eutra_resources_item_ies); + */ + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 gNB-CU CONFIGURATION UPDATE\n"); return -1; } + LOG_D(F1AP, "F1AP gNB-CU CONFIGURATION UPDATE\n"); + //for (int i=0;iassoc_id, buffer, len, 0); return 0; } @@ -895,7 +972,8 @@ int CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); + LOG_D(F1AP,"Cell Configuration ok (assoc_id %d)\n",assoc_id); + return(0); } diff --git a/openair2/F1AP/f1ap_cu_interface_management.h b/openair2/F1AP/f1ap_cu_interface_management.h index acad13836d..de7dcfe99b 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.h +++ b/openair2/F1AP/f1ap_cu_interface_management.h @@ -85,8 +85,7 @@ int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, /* * gNB-CU Configuration Update */ -int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, module_id_t du_mod_idP); - +int CU_send_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, f1ap_gnb_cu_configuration_update_t *f1ap_gnb_cu_configuration_update); int CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE(instance_t instance, uint32_t assoc_id, uint32_t stream, diff --git a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c index 9bd04cc5e8..8a5b9785b5 100644 --- a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c @@ -38,13 +38,6 @@ #include "common/ran_context.h" #include "openair3/UTILS/conversions.h" -// undefine C_RNTI from -// openair1/PHY/LTE_TRANSPORT/transport_common.h which -// replaces in ie->value.choice.C_RNTI, causing -// a compile error -#undef C_RNTI - - // Bing Kai: create CU and DU context, and put all the information there. uint64_t du_ue_f1ap_id = 0; uint32_t f1ap_assoc_id = 0; @@ -109,33 +102,67 @@ int CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instance, /* RNTI */ F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_C_RNTI, true); - BUFFER_TO_INT16(ie->value.choice.C_RNTI.buf, rnti); + rnti = ie->value.choice.C_RNTI; /* RRC Container */ F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); - + AssertFatal(ie!=NULL,"RRCContainer is missing\n"); // create an ITTI message and copy SDU - message_p = itti_alloc_new_message (TASK_CU_F1, RRC_MAC_CCCH_DATA_IND); - memset (RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); - ccch_sdu_len = ie->value.choice.RRCContainer.size; - memcpy(RRC_MAC_CCCH_DATA_IND (message_p).sdu, ie->value.choice.RRCContainer.buf, - ccch_sdu_len); + if (RC.nrrrc && RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CU) { + message_p = itti_alloc_new_message (TASK_CU_F1, 0, NR_RRC_MAC_CCCH_DATA_IND); + memset (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); + ccch_sdu_len = ie->value.choice.RRCContainer.size; + memcpy(NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, ie->value.choice.RRCContainer.buf, + ccch_sdu_len); + } else { + message_p = itti_alloc_new_message (TASK_CU_F1, 0, RRC_MAC_CCCH_DATA_IND); + memset (RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); + ccch_sdu_len = ie->value.choice.RRCContainer.size; + memcpy(RRC_MAC_CCCH_DATA_IND (message_p).sdu, ie->value.choice.RRCContainer.buf, + ccch_sdu_len); + } - //LOG_I(F1AP, "%s() RRCContainer (CCCH) size %ld: ", __func__, - // ie->value.choice.RRCContainer.size); - //for (int i = 0; i < ie->value.choice.RRCContainer.size; i++) - // printf("%02x ", RRC_MAC_CCCH_DATA_IND (message_p).sdu[i]); - //printf("\n"); + if (RC.nrrrc && RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CU) { + + LOG_D(F1AP, "%s() RRCContainer (CCCH) size %ld: ", __func__, ie->value.choice.RRCContainer.size); + //for (int i = 0; i < ie->value.choice.RRCContainer.size; i++) + // printf("%02x ", RRC_MAC_CCCH_DATA_IND (message_p).sdu[i]); + //printf("\n"); + + /* DUtoCURRCContainer */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_DUtoCURRCContainer, true); + if (ie) { + NR_RRC_MAC_CCCH_DATA_IND (message_p).du_to_cu_rrc_container = malloc(sizeof(OCTET_STRING_t)); + NR_RRC_MAC_CCCH_DATA_IND (message_p).du_to_cu_rrc_container->size = ie->value.choice.DUtoCURRCContainer.size; + NR_RRC_MAC_CCCH_DATA_IND (message_p).du_to_cu_rrc_container->buf = malloc( + ie->value.choice.DUtoCURRCContainer.size); + memcpy(NR_RRC_MAC_CCCH_DATA_IND (message_p).du_to_cu_rrc_container->buf, + ie->value.choice.DUtoCURRCContainer.buf, + ie->value.choice.DUtoCURRCContainer.size); + } + } // Find instance from nr_cellid int rrc_inst = -1; - for (int i=0;inode_type == ngran_gNB_CU) { + for (int i=0;inr_cellid == nr_cellid) { + rrc_inst = i; + break; + } + } + } else { + for (int i=0;inr_cellid == nr_cellid) { - rrc_inst = i; - break; + eNB_RRC_INST *rrc = RC.rrc[i]; + if (rrc->nr_cellid == nr_cellid) { + rrc_inst = i; + break; + } } } AssertFatal(rrc_inst>=0,"couldn't find an RRC instance for nr_cell %llu\n",(unsigned long long int)nr_cellid); @@ -148,15 +175,23 @@ int CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instance, } f1ap_cu_inst[rrc_inst].f1ap_ue[f1ap_uid].du_ue_f1ap_id = du_ue_f1ap_id; - - RRC_MAC_CCCH_DATA_IND (message_p).frame = 0; - RRC_MAC_CCCH_DATA_IND (message_p).sub_frame = 0; - RRC_MAC_CCCH_DATA_IND (message_p).sdu_size = ccch_sdu_len; - RRC_MAC_CCCH_DATA_IND (message_p).enb_index = rrc_inst; // CU instance - RRC_MAC_CCCH_DATA_IND (message_p).rnti = rnti; - RRC_MAC_CCCH_DATA_IND (message_p).CC_id = CC_id; - itti_send_msg_to_task (TASK_RRC_ENB, instance, message_p); - + if (RC.nrrrc && RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CU) { + NR_RRC_MAC_CCCH_DATA_IND (message_p).frame = 0; + NR_RRC_MAC_CCCH_DATA_IND (message_p).sub_frame = 0; + NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu_size = ccch_sdu_len; + NR_RRC_MAC_CCCH_DATA_IND (message_p).gnb_index = rrc_inst; // CU instance + NR_RRC_MAC_CCCH_DATA_IND (message_p).rnti = rnti; + NR_RRC_MAC_CCCH_DATA_IND (message_p).CC_id = CC_id; + itti_send_msg_to_task (TASK_RRC_GNB, instance, message_p); + } else { + RRC_MAC_CCCH_DATA_IND (message_p).frame = 0; + RRC_MAC_CCCH_DATA_IND (message_p).sub_frame = 0; + RRC_MAC_CCCH_DATA_IND (message_p).sdu_size = ccch_sdu_len; + RRC_MAC_CCCH_DATA_IND (message_p).enb_index = rrc_inst; // CU instance + RRC_MAC_CCCH_DATA_IND (message_p).rnti = rnti; + RRC_MAC_CCCH_DATA_IND (message_p).CC_id = CC_id; + itti_send_msg_to_task (TASK_RRC_ENB, instance, message_p); + } return 0; } @@ -171,7 +206,8 @@ int CU_send_DL_RRC_MESSAGE_TRANSFER(instance_t instance, f1ap_dl_rrc_message_t *f1ap_dl_rrc) { - F1AP_F1AP_PDU_t pdu; + LOG_D(F1AP, "CU send DL_RRC_MESSAGE_TRANSFER \n"); + F1AP_F1AP_PDU_t pdu; F1AP_DLRRCMessageTransfer_t *out; F1AP_DLRRCMessageTransferIEs_t *ie; @@ -197,7 +233,7 @@ int CU_send_DL_RRC_MESSAGE_TRANSFER(instance_t instance, ie->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; ie->value.choice.GNB_CU_UE_F1AP_ID = f1ap_get_cu_ue_f1ap_id(&f1ap_cu_inst[instance], f1ap_dl_rrc->rnti); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - LOG_I(F1AP, "Setting GNB_CU_UE_F1AP_ID %llu associated with UE RNTI %x (instance %d)\n", + LOG_I(F1AP, "Setting GNB_CU_UE_F1AP_ID %llu associated with UE RNTI %x (instance %ld)\n", (unsigned long long int)ie->value.choice.GNB_CU_UE_F1AP_ID, f1ap_dl_rrc->rnti, instance); @@ -252,31 +288,36 @@ int CU_send_DL_RRC_MESSAGE_TRANSFER(instance_t instance, OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, (const char*)f1ap_dl_rrc->rrc_container, f1ap_dl_rrc->rrc_container_length); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - //LOG_I(F1AP, "%s() RRCContainer size %d: ", __func__, f1ap_dl_rrc->rrc_container_length); - //for (int i = 0; i < ie->value.choice.RRCContainer.size; i++) - // printf("%02x ", f1ap_dl_rrc->rrc_container[i]); - //printf("\n"); + if (RC.nrrrc && RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CU) { + LOG_I(F1AP, "%s() RRCContainer size %d: ", __func__, f1ap_dl_rrc->rrc_container_length); + for (int i = 0; i < ie->value.choice.RRCContainer.size; i++) + printf("%02x ", f1ap_dl_rrc->rrc_container[i]); + printf("\n"); + } /* optional */ /* c7. RAT_FrequencyPriorityInformation */ /* TODO */ - if (0) { - ie = (F1AP_DLRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_DLRRCMessageTransferIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_RAT_FrequencyPriorityInformation; - - ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_subscriberProfileIDforRFP; - ie->value.choice.RAT_FrequencyPriorityInformation.choice.subscriberProfileIDforRFP = 123L; - + int endc=1; + ie = (F1AP_DLRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_DLRRCMessageTransferIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_RAT_FrequencyPriorityInformation; + if (endc==1) { + ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_eNDC; + ie->value.choice.RAT_FrequencyPriorityInformation.choice.eNDC = 123L; + } + else { + ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN; + ie->value.choice.RAT_FrequencyPriorityInformation.choice.nGRAN = 11L; + } //ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_rAT_FrequencySelectionPriority; //ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority = 123L; - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 DL RRC MESSAGE TRANSFER \n"); return -1; } @@ -299,7 +340,6 @@ int CU_handle_UL_RRC_MESSAGE_TRANSFER(instance_t instance, F1AP_ULRRCMessageTransfer_t *container; F1AP_ULRRCMessageTransferIEs_t *ie; - uint64_t cu_ue_f1ap_id; uint64_t du_ue_f1ap_id; uint64_t srb_id; @@ -348,9 +388,10 @@ int CU_handle_UL_RRC_MESSAGE_TRANSFER(instance_t instance, // print message in debug mode // create an ITTI message and copy SDU + /* - message_p = itti_alloc_new_message (TASK_CU_F1, RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_CU_F1, 0, RRC_DCCH_DATA_IND); RRC_DCCH_DATA_IND (message_p).sdu_p = malloc(ie->value.choice.RRCContainer.size); @@ -370,6 +411,8 @@ int CU_handle_UL_RRC_MESSAGE_TRANSFER(instance_t instance, ctxt.instance = instance; ctxt.rnti = f1ap_get_rnti_by_cu_id(&f1ap_cu_inst[instance], cu_ue_f1ap_id); ctxt.enb_flag = 1; + ctxt.eNB_index = 0; + ctxt.configured = 1; mem_block_t *mb = get_free_mem_block(ie->value.choice.RRCContainer.size,__func__); memcpy((void*)mb->data,(void*)ie->value.choice.RRCContainer.buf,ie->value.choice.RRCContainer.size); LOG_I(F1AP, "Calling pdcp_data_ind for UE RNTI %x srb_id %lu with size %ld (DCCH) \n", ctxt.rnti, srb_id, ie->value.choice.RRCContainer.size); diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 9ab84e6bc9..b261d8e85b 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -39,6 +39,7 @@ #include "proto_agent.h" extern RAN_CONTEXT_t RC; +extern uint8_t proto_agent_flag; f1ap_setup_req_t *f1ap_du_data_from_du; f1ap_cudu_inst_t f1ap_cu_inst[MAX_eNB]; @@ -52,7 +53,7 @@ void cu_task_handle_sctp_association_resp(instance_t instance, sctp_new_associat DevAssert(sctp_new_association_resp != NULL); if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - LOG_W(F1AP, "Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", + LOG_W(F1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", sctp_new_association_resp->sctp_state, instance, sctp_new_association_resp->ulp_cnx_id); @@ -71,14 +72,20 @@ void cu_task_handle_sctp_association_resp(instance_t instance, sctp_new_associat f1ap_du_data_from_du->sctp_out_streams = sctp_new_association_resp->out_streams; /* setup parameters for F1U and start the server */ - const cudu_params_t params = { + const cudu_params_t params = (RC.nrrrc && RC.nrrrc[instance]->node_type == ngran_gNB_CU) ? (cudu_params_t){ + .local_ipv4_address = RC.nrrrc[instance]->eth_params_s.my_addr, + .local_port = RC.nrrrc[instance]->eth_params_s.my_portd, + .remote_ipv4_address = RC.nrrrc[instance]->eth_params_s.remote_addr, + .remote_port = RC.nrrrc[instance]->eth_params_s.remote_portd + } : (cudu_params_t){ .local_ipv4_address = RC.rrc[instance]->eth_params_s.my_addr, .local_port = RC.rrc[instance]->eth_params_s.my_portd, .remote_ipv4_address = RC.rrc[instance]->eth_params_s.remote_addr, .remote_port = RC.rrc[instance]->eth_params_s.remote_portd }; AssertFatal(proto_agent_start(instance, ¶ms) == 0, - "could not start PROTO_AGENT for F1U on instance %d!\n", instance); + "could not start PROTO_AGENT for F1U on instance %ld!\n", instance); + proto_agent_flag = 1; } void cu_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) { @@ -101,13 +108,17 @@ void cu_task_send_sctp_init_req(instance_t enb_id) { LOG_I(F1AP, "F1AP_CU_SCTP_REQ(create socket)\n"); MessageDef *message_p = NULL; - message_p = itti_alloc_new_message (TASK_CU_F1, SCTP_INIT_MSG); + message_p = itti_alloc_new_message (TASK_CU_F1, 0, SCTP_INIT_MSG); message_p->ittiMsg.sctp_init.port = F1AP_PORT_NUMBER; message_p->ittiMsg.sctp_init.ppid = F1AP_SCTP_PPID; message_p->ittiMsg.sctp_init.ipv4 = 1; message_p->ittiMsg.sctp_init.ipv6 = 0; message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1; - message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr); + if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_CU) { + message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.nrrrc[enb_id]->eth_params_s.my_addr); + } else{ + message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr); + } /* * SR WARNING: ipv6 multi-homing fails sometimes for localhost. * * * * Disable it for now. @@ -138,43 +149,57 @@ void *F1AP_CU_task(void *arg) { switch (ITTI_MSG_ID(received_msg)) { case SCTP_NEW_ASSOCIATION_IND: - LOG_I(F1AP, "CU Task Received SCTP_NEW_ASSOCIATION_IND for instance %d\n", - ITTI_MESSAGE_GET_INSTANCE(received_msg)); - cu_task_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + LOG_I(F1AP, "CU Task Received SCTP_NEW_ASSOCIATION_IND for instance %ld\n", + ITTI_MSG_DESTINATION_INSTANCE(received_msg)); + cu_task_handle_sctp_association_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_ind); break; case SCTP_NEW_ASSOCIATION_RESP: - LOG_I(F1AP, "CU Task Received SCTP_NEW_ASSOCIATION_RESP for instance %d\n", - ITTI_MESSAGE_GET_INSTANCE(received_msg)); - cu_task_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + LOG_I(F1AP, "CU Task Received SCTP_NEW_ASSOCIATION_RESP for instance %ld\n", + ITTI_MSG_DESTINATION_INSTANCE(received_msg)); + cu_task_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_DATA_IND: - LOG_I(F1AP, "CU Task Received SCTP_DATA_IND for Instance %d\n", - ITTI_MESSAGE_GET_INSTANCE(received_msg)); - cu_task_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + LOG_I(F1AP, "CU Task Received SCTP_DATA_IND for Instance %ld\n", + ITTI_MSG_DESTINATION_INSTANCE(received_msg)); + cu_task_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; case F1AP_SETUP_RESP: // from rrc LOG_I(F1AP, "CU Task Received F1AP_SETUP_RESP\n"); - // CU_send_f1setup_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + // CU_send_f1setup_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &F1AP_SETUP_RESP(received_msg)); - CU_send_F1_SETUP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + CU_send_F1_SETUP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_SETUP_RESP(received_msg)); break; - case F1AP_DL_RRC_MESSAGE: // from rrc + case F1AP_GNB_CU_CONFIGURATION_UPDATE: // from rrc + LOG_I(F1AP, "CU Task Received F1AP_GNB_CU_CONFIGURAITON_UPDATE\n"); + // CU_send_f1setup_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + // &F1AP_SETUP_RESP(received_msg)); + CU_send_gNB_CU_CONFIGURATION_UPDATE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &F1AP_GNB_CU_CONFIGURATION_UPDATE(received_msg)); + break; + + case F1AP_DL_RRC_MESSAGE: // from rrc LOG_I(F1AP, "CU Task Received F1AP_DL_RRC_MESSAGE\n"); - CU_send_DL_RRC_MESSAGE_TRANSFER(ITTI_MESSAGE_GET_INSTANCE(received_msg), + CU_send_DL_RRC_MESSAGE_TRANSFER(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_DL_RRC_MESSAGE(received_msg)); break; - case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc + case F1AP_UE_CONTEXT_SETUP_REQ: // from rrc + LOG_I(F1AP, "CU Task Received F1AP_UE_CONTEXT_SETUP_REQ\n"); + CU_send_UE_CONTEXT_SETUP_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); + break; + + case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc LOG_I(F1AP, "CU Task Received F1AP_UE_CONTEXT_RELEASE_CMD\n"); - CU_send_UE_CONTEXT_RELEASE_COMMAND(ITTI_MESSAGE_GET_INSTANCE(received_msg), + CU_send_UE_CONTEXT_RELEASE_COMMAND(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); break; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 789ce4c715..da723ba5a3 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -39,12 +39,15 @@ #include "rrc_extern.h" #include "rrc_eNB_UE_context.h" +#include "openair2/RRC/NR/rrc_gNB_UE_context.h" #include "rrc_eNB_S1AP.h" #include "rrc_eNB_GTPV1U.h" +#include "openair2/RRC/NR/rrc_gNB_NGAP.h" extern f1ap_setup_req_t *f1ap_du_data_from_du; extern f1ap_cudu_inst_t f1ap_cu_inst[MAX_eNB]; extern RAN_CONTEXT_t RC; +extern uint32_t f1ap_assoc_id; int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, f1ap_ue_context_setup_req_t *f1ap_ue_context_setup_req) { @@ -108,7 +111,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, /* mandatory */ /* c4. ServCellIndex */ ie = (F1AP_UEContextSetupRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextSetupRequestIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_ServCellndex; + ie->id = F1AP_ProtocolIE_ID_id_ServCellIndex; ie->criticality = F1AP_Criticality_reject; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex; ie->value.choice.ServCellIndex = 2; @@ -263,7 +266,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, f1ap_ue_context_setup_req->mnc, f1ap_ue_context_setup_req->mnc_digit_length, &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); + NR_CELL_ID_TO_BIT_STRING(12345678, &nRCGI.nRCellIdentity); scell_toBeSetup_item.sCell_ID = nRCGI; /* 10.1.2 sCellIndex */ @@ -379,75 +382,86 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, } } else { - /* 12.1.2 dRB_Information */ - drbs_toBeSetup_item.qoSInformation.present = F1AP_QoSInformation_PR_dRB_Information; - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information = (F1AP_DRB_Information_t *)calloc(1, sizeof(F1AP_DRB_Information_t)); - + /* 12.1.2 DRB_Information */ + drbs_toBeSetup_item.qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; + + F1AP_QoSInformation_ExtIEs_t *ie; + ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(F1AP_QoS_Characteristics_ExtIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; + F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; + + drbs_toBeSetup_item.qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer*)ie; + + /* 12.1.2.1 dRB_QoS */ { /* qoS_Characteristics */ { int some_decide_qoS_characteristics = 1; // BK: Need Check if (some_decide_qoS_characteristics) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI = (F1AP_NonDynamic5QIDescriptor_t *)calloc(1, sizeof(F1AP_NonDynamic5QIDescriptor_t)); + DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI = (F1AP_NonDynamic5QIDescriptor_t *)calloc(1, sizeof(F1AP_NonDynamic5QIDescriptor_t)); /* fiveQI */ - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI = 1L; /* OPTIONAL */ /* qoSPriorityLevel */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->qoSPriorityLevel = (long *)calloc(1, sizeof(long)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->qoSPriorityLevel = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->qoSPriorityLevel = (long *)calloc(1, sizeof(long)); + *DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->qoSPriorityLevel = 1L; } /* OPTIONAL */ /* averagingWindow */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->averagingWindow = (F1AP_AveragingWindow_t *)calloc(1, sizeof(F1AP_AveragingWindow_t)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->averagingWindow = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->averagingWindow = (F1AP_AveragingWindow_t *)calloc(1, sizeof(F1AP_AveragingWindow_t)); + *DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->averagingWindow = 1L; } /* OPTIONAL */ /* maxDataBurstVolume */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->maxDataBurstVolume = (F1AP_MaxDataBurstVolume_t *)calloc(1, sizeof(F1AP_MaxDataBurstVolume_t)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->maxDataBurstVolume = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->maxDataBurstVolume = (F1AP_MaxDataBurstVolume_t *)calloc(1, sizeof(F1AP_MaxDataBurstVolume_t)); + *DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI->maxDataBurstVolume = 1L; } } else { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI = (F1AP_Dynamic5QIDescriptor_t *)calloc(1, sizeof(F1AP_Dynamic5QIDescriptor_t)); + DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI = (F1AP_Dynamic5QIDescriptor_t *)calloc(1, sizeof(F1AP_Dynamic5QIDescriptor_t)); /* qoSPriorityLevel */ - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->qoSPriorityLevel = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->qoSPriorityLevel = 1L; /* packetDelayBudget */ - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->packetDelayBudget = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->packetDelayBudget = 1L; /* packetErrorRate */ - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->packetErrorRate = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->packetErrorRate.pER_Scalar = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->packetErrorRate.pER_Exponent = 6L; + /* OPTIONAL */ /* delayCritical */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->delayCritical = (long *)calloc(1, sizeof(long)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->delayCritical = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->delayCritical = (long *)calloc(1, sizeof(long)); + *DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->delayCritical = 1L; } /* OPTIONAL */ /* averagingWindow */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->averagingWindow = (F1AP_AveragingWindow_t *)calloc(1, sizeof(F1AP_AveragingWindow_t)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->averagingWindow = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->averagingWindow = (F1AP_AveragingWindow_t *)calloc(1, sizeof(F1AP_AveragingWindow_t)); + *DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->averagingWindow = 1L; } /* OPTIONAL */ /* maxDataBurstVolume */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume = (F1AP_MaxDataBurstVolume_t *)calloc(1, sizeof(F1AP_MaxDataBurstVolume_t)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume = 1L; + DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume = (F1AP_MaxDataBurstVolume_t *)calloc(1, sizeof(F1AP_MaxDataBurstVolume_t)); + *DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume = 1L; } } // if some_decide_qoS_characteristics @@ -456,32 +470,32 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, /* nGRANallocationRetentionPriority */ { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.nGRANallocationRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_shall_not_trigger_pre_emption; // enum - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum + DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum + DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_shall_not_trigger_pre_emption; // enum + DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum } // nGRANallocationRetentionPriority /* OPTIONAL */ /* gBR_QoS_Flow_Information */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information = (F1AP_GBR_QoSFlowInformation_t *)calloc(1, sizeof(F1AP_GBR_QoSFlowInformation_t)); - asn_long2INTEGER(&drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxFlowBitRateDownlink, 1L); - asn_long2INTEGER(&drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxFlowBitRateUplink, 1L); - asn_long2INTEGER(&drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information->guaranteedFlowBitRateDownlink, 1L); - asn_long2INTEGER(&drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information->guaranteedFlowBitRateUplink, 1L); + DRB_Information->dRB_QoS.gBR_QoS_Flow_Information = (F1AP_GBR_QoSFlowInformation_t *)calloc(1, sizeof(F1AP_GBR_QoSFlowInformation_t)); + asn_long2INTEGER(&DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxFlowBitRateDownlink, 1L); + asn_long2INTEGER(&DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxFlowBitRateUplink, 1L); + asn_long2INTEGER(&DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->guaranteedFlowBitRateDownlink, 1L); + asn_long2INTEGER(&DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->guaranteedFlowBitRateUplink, 1L); /* OPTIONAL */ /* maxPacketLossRateDownlink */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateDownlink = (F1AP_MaxPacketLossRate_t *)calloc(1, sizeof(F1AP_MaxPacketLossRate_t)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateDownlink = 1L; + DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateDownlink = (F1AP_MaxPacketLossRate_t *)calloc(1, sizeof(F1AP_MaxPacketLossRate_t)); + *DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateDownlink = 1L; } /* OPTIONAL */ /* maxPacketLossRateUplink */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateUplink = (F1AP_MaxPacketLossRate_t *)calloc(1, sizeof(F1AP_MaxPacketLossRate_t)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateUplink = 1L; + DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateUplink = (F1AP_MaxPacketLossRate_t *)calloc(1, sizeof(F1AP_MaxPacketLossRate_t)); + *DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateUplink = 1L; } } @@ -489,8 +503,8 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, /* OPTIONAL */ /* reflective_QoS_Attribute */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.reflective_QoS_Attribute = (long *)calloc(1, sizeof(long)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->dRB_QoS.reflective_QoS_Attribute = 1L; + DRB_Information->dRB_QoS.reflective_QoS_Attribute = (long *)calloc(1, sizeof(long)); + *DRB_Information->dRB_QoS.reflective_QoS_Attribute = 1L; } } // dRB_QoS @@ -498,21 +512,21 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, /* 12.1.2.2 sNSSAI */ { /* sST */ - OCTET_STRING_fromBuf(&drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->sNSSAI.sST, "asdsa1d32sa1d31asd31as", + OCTET_STRING_fromBuf(&DRB_Information->sNSSAI.sST, "asdsa1d32sa1d31asd31as", strlen("asdsa1d32sa1d31asd31as")); /* OPTIONAL */ /* sD */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->sNSSAI.sD = (OCTET_STRING_t *)calloc(1, sizeof(OCTET_STRING_t)); - OCTET_STRING_fromBuf(drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->sNSSAI.sD, "asdsa1d32sa1d31asd31as", + DRB_Information->sNSSAI.sD = (OCTET_STRING_t *)calloc(1, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(DRB_Information->sNSSAI.sD, "asdsa1d32sa1d31asd31as", strlen("asdsa1d32sa1d31asd31as")); } } /* OPTIONAL */ /* 12.1.2.3 notificationControl */ if (0) { - drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->notificationControl = (F1AP_NotificationControl_t *)calloc(1, sizeof(F1AP_NotificationControl_t)); - *drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->notificationControl = F1AP_NotificationControl_active; // enum + DRB_Information->notificationControl = (F1AP_NotificationControl_t *)calloc(1, sizeof(F1AP_NotificationControl_t)); + *DRB_Information->notificationControl = F1AP_NotificationControl_active; // enum } /* 12.1.2.4 flows_Mapped_To_DRB_List */ // BK: need verifiy @@ -523,7 +537,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, memset((void *)&flows_mapped_to_drb_item, 0, sizeof(F1AP_Flows_Mapped_To_DRB_Item_t)); /* qoSFlowIndicator */ - flows_mapped_to_drb_item.qoSFlowIndicator = 1L; + flows_mapped_to_drb_item.qoSFlowIdentifier = 1L; /* qoSFlowLevelQoSParameters */ { @@ -569,9 +583,10 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, flows_mapped_to_drb_item.qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI->packetDelayBudget = 1L; /* packetErrorRate */ - flows_mapped_to_drb_item.qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI->packetErrorRate = 1L; + flows_mapped_to_drb_item.qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI->packetErrorRate.pER_Scalar = 1L; + flows_mapped_to_drb_item.qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI->packetErrorRate.pER_Exponent = 6L; - /* OPTIONAL */ + /* OPTIONAL */ /* delayCritical */ if (0) { flows_mapped_to_drb_item.qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI->delayCritical = (long *)calloc(1, sizeof(long)); @@ -637,7 +652,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, } // qoSFlowLevelQoSParameters // BK: need check - ASN_SEQUENCE_ADD(&drbs_toBeSetup_item.qoSInformation.choice.dRB_Information->flows_Mapped_To_DRB_List.list, &flows_mapped_to_drb_item); + ASN_SEQUENCE_ADD(&DRB_Information->flows_Mapped_To_DRB_List.list, &flows_mapped_to_drb_item); } } // if some_decide_qos @@ -672,7 +687,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_am; break; default: - drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_um; + drbs_toBeSetup_item.rLCMode = F1AP_RLCMode_rlc_um_bidirectional; } /* OPTIONAL */ @@ -716,26 +731,26 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, ie->criticality = F1AP_Criticality_reject; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RAT_FrequencyPriorityInformation; - int some_decide_rat = 1; // BK: Need Check - if (some_decide_rat) { - ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_subscriberProfileIDforRFP; - ie->value.choice.RAT_FrequencyPriorityInformation.choice.subscriberProfileIDforRFP = 11L; + int endc = 1; // RK: Get this from somewhere ... + if (endc) { + ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_eNDC; + ie->value.choice.RAT_FrequencyPriorityInformation.choice.eNDC = 11L; } else { - ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_rAT_FrequencySelectionPriority; - ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority = 11L; + ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN; + ie->value.choice.RAT_FrequencyPriorityInformation.choice.nGRAN = 11L; } ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); } /* OPTIONAL */ /* RRCContainer */ - if (0) { + if(RC.nrrrc) { ie = (F1AP_UEContextSetupRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextSetupRequestIEs_t)); ie->id = F1AP_ProtocolIE_ID_id_RRCContainer; ie->criticality = F1AP_Criticality_reject; ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); + OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, (const char*)f1ap_ue_context_setup_req->rrc_container, + f1ap_ue_context_setup_req->rrc_container_length); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); } @@ -752,10 +767,28 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP REQUEST\n"); return -1; } + // xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, (void *)pdu); + + // asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + // res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_F1AP_F1AP_PDU, pdu); + // buffer = res.buffer; + // len = res.result.encoded; + + // if (res.result.encoded <= 0) { + // LOG_E(F1AP, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); + // return -1; + // } + + LOG_D(F1AP,"F1AP UEContextSetupRequest Encoded %u bits\n", len); + + if(RC.nrrrc) { + cu_f1ap_itti_send_sctp_data_req(instance, f1ap_assoc_id /* BK: fix me*/ , buffer, len, 0 /* BK: fix me*/); + } + return 0; } @@ -763,7 +796,42 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); + F1AP_UEContextSetupResponse_t *container; + F1AP_UEContextSetupResponseIEs_t *ie; + + DevAssert(pdu); + + container = &pdu->choice.successfulOutcome->value.choice.UEContextSetupResponse; + + /* GNB_CU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + + /* GNB_DU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + /* DUtoCURRCInformation */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, true); + + /* DRBs_Setup_List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_DRBs_Setup_List, true); + + /* SRBs_FailedToBeSetup_List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_List, true); + + /* DRBs_FailedToBeSetup_List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_List, true); + + /* SCell_FailedtoSetup_List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_List, true); + + return 0; } int CU_handle_UE_CONTEXT_SETUP_FAILURE(instance_t instance, @@ -963,35 +1031,55 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, // F1AP_CriticalityDiagnostics_IE_List } - struct rrc_eNB_ue_context_s *ue_context_p = - rrc_eNB_get_ue_context(RC.rrc[instance], rnti); protocol_ctxt_t ctxt; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, instance, ENB_FLAG_YES, rnti, 0, 0, instance); - if (ue_context_p) { - /* The following is normally done in the function rrc_rx_tx() */ - rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_CPLT(instance, - ue_context_p->ue_context.eNB_ue_s1ap_id); + if (RC.nrrrc[instance]->node_type == ngran_gNB_CU) { + struct rrc_gNB_ue_context_s *ue_context_p = + rrc_gNB_get_ue_context(RC.nrrrc[instance], rnti); - rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(instance, ue_context_p); - // erase data of GTP tunnels in UE context - for (int e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) { - ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0; - memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], - 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab])); - ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0; + if (ue_context_p) { + MessageDef *msg = itti_alloc_new_message(TASK_CU_F1, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE); + NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).gNB_ue_ngap_id = ue_context_p->ue_context.gNB_ue_ngap_id; + itti_send_msg_to_task(TASK_NGAP, instance, msg); + + rrc_gNB_remove_ue_context(&ctxt, RC.nrrrc[instance], ue_context_p); + } else { + LOG_E(F1AP, "could not find ue_context of UE RNTI %x\n", rnti); } +#ifdef ITTI_SIM + return 0; +#endif - struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = - rrc_eNB_S1AP_get_ue_ids(RC.rrc[instance], 0, - ue_context_p->ue_context.eNB_ue_s1ap_id); - if (rrc_ue_s1ap_ids) - rrc_eNB_S1AP_remove_ue_ids(RC.rrc[instance], rrc_ue_s1ap_ids); - - /* trigger UE release in RRC */ - rrc_eNB_remove_ue_context(&ctxt, RC.rrc[instance], ue_context_p); } else { - LOG_E(F1AP, "could not find ue_context of UE RNTI %x\n", rnti); + struct rrc_eNB_ue_context_s *ue_context_p = + rrc_eNB_get_ue_context(RC.rrc[instance], rnti); + + if (ue_context_p) { + /* The following is normally done in the function rrc_rx_tx() */ + rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_CPLT(instance, + ue_context_p->ue_context.eNB_ue_s1ap_id); + + rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(instance, ue_context_p); + // erase data of GTP tunnels in UE context + for (int e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) { + ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0; + memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], + 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab])); + ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0; + } + + struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = + rrc_eNB_S1AP_get_ue_ids(RC.rrc[instance], 0, + ue_context_p->ue_context.eNB_ue_s1ap_id); + if (rrc_ue_s1ap_ids) + rrc_eNB_S1AP_remove_ue_ids(RC.rrc[instance], rrc_ue_s1ap_ids); + + /* trigger UE release in RRC */ + rrc_eNB_remove_ue_context(&ctxt, RC.rrc[instance], ue_context_p); + } else { + LOG_E(F1AP, "could not find ue_context of UE RNTI %x\n", rnti); + } } pdcp_remove_UE(&ctxt); @@ -1019,8 +1107,8 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { // for test int mcc = 208; - int mnc = 93; - int mnc_digit_length = 8; + int mnc = 92; + int mnc_digit_length = 2; /* Create */ /* 0. Message Type */ @@ -1061,7 +1149,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { F1AP_NRCGI_t nRCGI; MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); + NR_CELL_ID_TO_BIT_STRING(12345678, &nRCGI.nRCellIdentity); ie->value.choice.NRCGI = nRCGI; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); @@ -1070,7 +1158,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { /* mandatory */ /* c4. ServCellIndex */ ie = (F1AP_UEContextModificationRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextModificationRequestIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_ServCellndex; + ie->id = F1AP_ProtocolIE_ID_id_ServCellIndex; ie->criticality = F1AP_Criticality_reject; ie->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex; ie->value.choice.ServCellIndex = 5L; @@ -1114,13 +1202,13 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { } /* optional */ - /* c6. TransmissionStopIndicator */ + /* c6. TransmissionActionIndicator */ if (1) { ie = (F1AP_UEContextModificationRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextModificationRequestIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_TransmissionStopIndicator; + ie->id = F1AP_ProtocolIE_ID_id_TransmissionActionIndicator; ie->criticality = F1AP_Criticality_ignore; - ie->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionStopIndicator; - ie->value.choice.TransmissionStopIndicator = F1AP_TransmissionStopIndicator_true; + ie->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator; + ie->value.choice.TransmissionActionIndicator = F1AP_TransmissionActionIndicator_stop; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); } @@ -1140,10 +1228,10 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { /* c7. RRCRconfigurationCompleteIndicator */ if (1) { ie = (F1AP_UEContextModificationRequestIEs_t *)calloc(1, sizeof(F1AP_UEContextModificationRequestIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_RRCRconfigurationCompleteIndicator; + ie->id = F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator; ie->criticality = F1AP_Criticality_ignore; - ie->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCRconfigurationCompleteIndicator; - ie->value.choice.RRCRconfigurationCompleteIndicator = F1AP_RRCRconfigurationCompleteIndicator_true; + ie->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator; + ie->value.choice.RRCReconfigurationCompleteIndicator = F1AP_RRCReconfigurationCompleteIndicator_true; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); } @@ -1186,7 +1274,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); + NR_CELL_ID_TO_BIT_STRING(12345678, &nRCGI.nRCellIdentity); scell_toBeSetupMod_item.sCell_ID = nRCGI; /* sCellIndex */ @@ -1226,7 +1314,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); MCC_MNC_TO_PLMNID(mcc, mnc, mnc_digit_length, &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(123456, &nRCGI.nRCellIdentity); + NR_CELL_ID_TO_BIT_STRING(12345678, &nRCGI.nRCellIdentity); scell_toBeRemoved_item.sCell_ID = nRCGI; /* ADD */ @@ -1325,7 +1413,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { } /* rLCMode */ - drbs_toBeSetupMod_item.rLCMode = F1AP_RLCMode_rlc_um; // enum + drbs_toBeSetupMod_item.rLCMode = F1AP_RLCMode_rlc_um_bidirectional; // enum /* OPTIONAL */ /* ULConfiguration */ @@ -1366,9 +1454,10 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { drbs_toBeModified_item.dRBID = 30L; /* qoSInformation */ - drbs_toBeModified_item.qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS; - drbs_toBeModified_item.qoSInformation.choice.eUTRANQoS = (F1AP_EUTRANQoS_t *)calloc(1, sizeof(F1AP_EUTRANQoS_t)); - drbs_toBeModified_item.qoSInformation.choice.eUTRANQoS->qCI = 254L; + drbs_toBeModified_item.qoSInformation =calloc(1,sizeof(*drbs_toBeModified_item.qoSInformation)); + drbs_toBeModified_item.qoSInformation->present = F1AP_QoSInformation_PR_eUTRANQoS; + drbs_toBeModified_item.qoSInformation->choice.eUTRANQoS = (F1AP_EUTRANQoS_t *)calloc(1, sizeof(F1AP_EUTRANQoS_t)); + drbs_toBeModified_item.qoSInformation->choice.eUTRANQoS->qCI = 254L; /* ULTunnels_ToBeModified_List */ int j = 0; @@ -1472,7 +1561,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 UE CONTEXT_MODIFICATION REQUEST\n"); return -1; } diff --git a/openair2/F1AP/f1ap_decoder.c b/openair2/F1AP/f1ap_decoder.c index 7bd5359e29..ac55db7fda 100644 --- a/openair2/F1AP/f1ap_decoder.c +++ b/openair2/F1AP/f1ap_decoder.c @@ -49,6 +49,11 @@ static int f1ap_decode_initiating_message(F1AP_F1AP_PDU_t *pdu) LOG_I(F1AP, "%s(): F1AP_ProcedureCode_id_F1Setup\n", __func__); break; + case F1AP_ProcedureCode_id_gNBCUConfigurationUpdate: + //res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_F1AP_F1AP_PDU, pdu); + LOG_I(F1AP, "%s(): F1AP_ProcedureCode_id_gNBCUConfigurationUpdate\n", __func__); + break; + case F1AP_ProcedureCode_id_InitialULRRCMessageTransfer: //res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_F1AP_F1AP_PDU, pdu); LOG_I(F1AP, "%s(): F1AP_ProcedureCode_id_InitialULRRCMessageTransfer\n", __func__); @@ -69,6 +74,9 @@ static int f1ap_decode_initiating_message(F1AP_F1AP_PDU_t *pdu) case F1AP_ProcedureCode_id_UEContextReleaseRequest: LOG_I(F1AP, "%s(): F1AP_ProcedureCode_id_UEContextReleaseRequest\n", __func__); break; + case F1AP_ProcedureCode_id_UEContextSetup: + LOG_I(F1AP, "%s(): F1AP_ProcedureCode_id_UEContextSetup\n", __func__); + break; // case F1AP_ProcedureCode_id_InitialContextSetup: // res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_F1AP_F1AP_PDU, pdu); // message_id = F1AP_INITIAL_CONTEXT_SETUP_LOG; @@ -102,6 +110,10 @@ static int f1ap_decode_successful_outcome(F1AP_F1AP_PDU_t *pdu) LOG_I(F1AP, "%s(): F1AP_ProcedureCode_id_F1Setup\n", __func__); break; + case F1AP_ProcedureCode_id_gNBCUConfigurationUpdate: + LOG_I(F1AP, "%s(): F1AP_ProcedureCode_id_gNBCUConfigurationUpdate\n", __func__); + break; + case F1AP_ProcedureCode_id_UEContextRelease: LOG_I(F1AP, "%s(): F1AP_ProcedureCode_id_UEContextRelease\n", __func__); break; @@ -157,7 +169,7 @@ int f1ap_decode_pdu(F1AP_F1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t //LOG_I(F1AP, "f1ap_decode_pdu.dec_ret.code = %d\n", dec_ret.code); if (dec_ret.code != RC_OK) { - LOG_E(F1AP, "Failed to decode pdu\n"); + AssertFatal(1==0,"Failed to decode pdu\n"); return -1; } diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 341c050f55..b6ece9b13f 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -38,7 +38,18 @@ #include "assertions.h" extern f1ap_setup_req_t *f1ap_du_data; +extern RAN_CONTEXT_t RC; +int nrb_lut[29] = {11, 18, 24, 25, 31, 32, 38, 51, 52, 65, 66, 78, 79, 93, 106, 107, 121, 132, 133, 135, 160, 162, 189, 216, 217, 245, 264, 270, 273}; + +int to_NRNRB(int nrb) { + if (RC.nrrrc) { + for (int i=0;i<29;i++) if (nrb_lut[i] == nrb) return i; + AssertFatal(1==0,"nrb %d is not in the list of possible NRNRB\n",nrb); + } else { + return nrb; + } +} int DU_handle_RESET(instance_t instance, uint32_t assoc_id, @@ -95,7 +106,6 @@ int DU_send_F1_SETUP_REQUEST(instance_t instance) { uint8_t *buffer; uint32_t len; int i = 0; - int j = 0; /* Create */ /* 0. pdu Type */ @@ -189,9 +199,19 @@ int DU_send_F1_SETUP_REQUEST(instance_t instance) { served_cell_information.nRPCI = f1ap_du_data->nr_pci[i]; // int 0..1007 /* - fiveGS_TAC */ - OCTET_STRING_fromBuf(&served_cell_information.fiveGS_TAC, - (const char*)&f1ap_du_data->tac[i], - 3); + if (RC.nrrrc) { + uint8_t fiveGS_TAC[3]; + fiveGS_TAC[0] = ((uint8_t*)&f1ap_du_data->tac[i])[2]; + fiveGS_TAC[1] = ((uint8_t*)&f1ap_du_data->tac[i])[1]; + fiveGS_TAC[2] = ((uint8_t*)&f1ap_du_data->tac[i])[0]; + OCTET_STRING_fromBuf(served_cell_information.fiveGS_TAC, + (const char *)fiveGS_TAC, + 3); + } else { + OCTET_STRING_fromBuf(served_cell_information.fiveGS_TAC, + (const char*)&f1ap_du_data->tac[i], + 3); + } /* - Configured_EPS_TAC */ if(0){ @@ -201,19 +221,11 @@ int DU_send_F1_SETUP_REQUEST(instance_t instance) { 2); } - /* - broadcast PLMNs */ - // RK: add the num_available_broadcast_PLMNs to the message - int num_available_broadcast_PLMNs = 1; //f1ap_du_data->num_available_broadcast_PLMNs; - LOG_D(F1AP, "num_available_broadcast_PLMNs = %d \n", num_available_broadcast_PLMNs); - for (j=0; - j PLMN BroadcastPLMNs Item */ - F1AP_BroadcastPLMNs_Item_t *broadcastPLMNs_Item = (F1AP_BroadcastPLMNs_Item_t *)calloc(1, sizeof(F1AP_BroadcastPLMNs_Item_t)); - //MCC_MNC_TO_PLMNID(208, 95, 2, &broadcastPLMNs_Item->pLMN_Identity); - MCC_MNC_TO_PLMNID(f1ap_du_data->mcc[i], f1ap_du_data->mnc[i], f1ap_du_data->mnc_digit_length[i], &broadcastPLMNs_Item->pLMN_Identity); - ASN_SEQUENCE_ADD(&served_cell_information.servedPLMNs.list, broadcastPLMNs_Item); - } + /* servedPLMN information */ + F1AP_ServedPLMNs_Item_t *servedPLMN_item = calloc(1,sizeof(*servedPLMN_item)); + memset(servedPLMN_item,0,sizeof(*servedPLMN_item)); + MCC_MNC_TO_PLMNID(f1ap_du_data->mcc[i], f1ap_du_data->mnc[i], f1ap_du_data->mnc_digit_length[i], &servedPLMN_item->pLMN_Identity); + ASN_SEQUENCE_ADD(&served_cell_information.servedPLMNs.list, servedPLMN_item); // // /* - CHOICE NR-MODE-Info */ F1AP_NR_Mode_Info_t nR_Mode_Info; @@ -237,7 +249,7 @@ int DU_send_F1_SETUP_REQUEST(instance_t instance) { /* FDD.1.3 freqBandListNr */ int fdd_ul_num_available_freq_Bands = f1ap_du_data->nr_mode_info[i].fdd.ul_num_frequency_bands; - LOG_D(F1AP, "fdd_ul_num_available_freq_Bands = %d \n", fdd_ul_num_available_freq_Bands); + LOG_I(F1AP, "fdd_ul_num_available_freq_Bands = %d \n", fdd_ul_num_available_freq_Bands); int fdd_ul_j; for (fdd_ul_j=0; fdd_ul_jnr_mode_info[i].fdd.dl_num_frequency_bands; - LOG_D(F1AP, "fdd_dl_num_available_freq_Bands = %d \n", fdd_dl_num_available_freq_Bands); + LOG_I(F1AP, "fdd_dl_num_available_freq_Bands = %d \n", fdd_dl_num_available_freq_Bands); int fdd_dl_j; for (fdd_dl_j=0; fdd_dl_juL_Transmission_Bandwidth.nRSCS = f1ap_du_data->nr_mode_info[i].fdd.ul_scs; - fDD_Info->uL_Transmission_Bandwidth.nRNRB = f1ap_du_data->nr_mode_info[i].fdd.ul_nrb; + fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(f1ap_du_data->nr_mode_info[i].fdd.ul_nrb); /* FDD.4 DL Transmission Bandwidth */ fDD_Info->dL_Transmission_Bandwidth.nRSCS = f1ap_du_data->nr_mode_info[i].fdd.dl_scs; - fDD_Info->dL_Transmission_Bandwidth.nRNRB = f1ap_du_data->nr_mode_info[i].fdd.dl_nrb; + fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(f1ap_du_data->nr_mode_info[i].fdd.dl_nrb); nR_Mode_Info.choice.fDD = fDD_Info; } else { // TDD @@ -333,7 +345,8 @@ int DU_send_F1_SETUP_REQUEST(instance_t instance) { /* TDD.1.3 freqBandListNr */ int tdd_num_available_freq_Bands = f1ap_du_data->nr_mode_info[i].tdd.num_frequency_bands; - LOG_D(F1AP, "tdd_num_available_freq_Bands = %d \n", tdd_num_available_freq_Bands); + LOG_I(F1AP, "tdd_num_available_freq_Bands = %d \n", tdd_num_available_freq_Bands); + AssertFatal(tdd_num_available_freq_Bands > 0, "should have at least one TDD band available\n"); int j; for (j=0; jtransmission_Bandwidth.nRSCS = f1ap_du_data->nr_mode_info[i].tdd.scs; - tDD_Info->transmission_Bandwidth.nRNRB = f1ap_du_data->nr_mode_info[i].tdd.nrb; + tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(f1ap_du_data->nr_mode_info[i].tdd.nrb); nR_Mode_Info.choice.tDD = tDD_Info; } // if nR_Mode_Info @@ -384,6 +397,7 @@ int DU_send_F1_SETUP_REQUEST(instance_t instance) { (const char*)f1ap_du_data->mib[i],//f1ap_du_data->mib, f1ap_du_data->mib_length[i]); + LOG_D(F1AP,"Filling SIB1_message for cell %d, length %d\n",i,f1ap_du_data->sib1_length[i]); OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, // sept. 2018 (const char*)f1ap_du_data->sib1[i], f1ap_du_data->sib1_length[i]); @@ -399,6 +413,20 @@ int DU_send_F1_SETUP_REQUEST(instance_t instance) { } ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + /* c5. RRC VERSION */ + if(RC.nrrrc) { + ie = (F1AP_F1SetupRequestIEs_t *) calloc(1, sizeof(F1AP_F1SetupRequestIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version; + ie->value.choice.RRC_Version.latest_RRC_Version.buf = calloc(1, sizeof(char)); + ie->value.choice.RRC_Version.latest_RRC_Version.buf[0] = 0xe0; + ie->value.choice.RRC_Version.latest_RRC_Version.size = 1; + ie->value.choice.RRC_Version.latest_RRC_Version.bits_unused = 5; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup request\n"); @@ -425,126 +453,175 @@ int DU_handle_F1_SETUP_RESPONSE(instance_t instance, F1AP_F1AP_PDU_t *pdu) { - LOG_D(F1AP, "DU_handle_F1_SETUP_RESPONSE\n"); + LOG_D(F1AP, "DU_handle_F1_SETUP_RESPONSE\n"); - AssertFatal(pdu->present == F1AP_F1AP_PDU_PR_successfulOutcome, - "pdu->present != F1AP_F1AP_PDU_PR_successfulOutcome\n"); - AssertFatal(pdu->choice.successfulOutcome->procedureCode == F1AP_ProcedureCode_id_F1Setup, - "pdu->choice.successfulOutcome->procedureCode != F1AP_ProcedureCode_id_F1Setup\n"); - AssertFatal(pdu->choice.successfulOutcome->criticality == F1AP_Criticality_reject, - "pdu->choice.successfulOutcome->criticality != F1AP_Criticality_reject\n"); - AssertFatal(pdu->choice.successfulOutcome->value.present == F1AP_SuccessfulOutcome__value_PR_F1SetupResponse, - "pdu->choice.successfulOutcome->value.present != F1AP_SuccessfulOutcome__value_PR_F1SetupResponse\n"); + AssertFatal(pdu->present == F1AP_F1AP_PDU_PR_successfulOutcome, + "pdu->present != F1AP_F1AP_PDU_PR_successfulOutcome\n"); + AssertFatal(pdu->choice.successfulOutcome->procedureCode == F1AP_ProcedureCode_id_F1Setup, + "pdu->choice.successfulOutcome->procedureCode != F1AP_ProcedureCode_id_F1Setup\n"); + AssertFatal(pdu->choice.successfulOutcome->criticality == F1AP_Criticality_reject, + "pdu->choice.successfulOutcome->criticality != F1AP_Criticality_reject\n"); + AssertFatal(pdu->choice.successfulOutcome->value.present == F1AP_SuccessfulOutcome__value_PR_F1SetupResponse, + "pdu->choice.successfulOutcome->value.present != F1AP_SuccessfulOutcome__value_PR_F1SetupResponse\n"); - F1AP_F1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; + F1AP_F1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; - F1AP_F1SetupResponseIEs_t *ie; - int TransactionId = -1; - int num_cells_to_activate = 0; - F1AP_Cells_to_be_Activated_List_Item_t *cell; + F1AP_F1SetupResponseIEs_t *ie; + int TransactionId = -1; + int num_cells_to_activate = 0; + F1AP_Cells_to_be_Activated_List_Item_t *cell; - MessageDef *msg_p = itti_alloc_new_message (TASK_DU_F1, F1AP_SETUP_RESP); + MessageDef *msg_p = itti_alloc_new_message (TASK_DU_F1, 0, F1AP_SETUP_RESP); - LOG_D(F1AP, "F1AP: F1Setup-Resp: protocolIEs.list.count %d\n", - in->protocolIEs.list.count); - for (int i=0;i < in->protocolIEs.list.count; i++) { - ie = in->protocolIEs.list.array[i]; - switch (ie->id) { - case F1AP_ProtocolIE_ID_id_TransactionID: - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_TransactionID, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_TransactionID\n"); - TransactionId=ie->value.choice.TransactionID; - LOG_D(F1AP, "F1AP: F1Setup-Resp: TransactionId %d\n", - TransactionId); - break; - case F1AP_ProtocolIE_ID_id_gNB_CU_Name: - AssertFatal(ie->criticality == F1AP_Criticality_ignore, - "ie->criticality != F1AP_Criticality_ignore\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_TransactionID\n"); - F1AP_SETUP_RESP (msg_p).gNB_CU_name = malloc(ie->value.choice.GNB_CU_Name.size+1); - memcpy(F1AP_SETUP_RESP (msg_p).gNB_CU_name,ie->value.choice.GNB_CU_Name.buf,ie->value.choice.GNB_CU_Name.size); - F1AP_SETUP_RESP (msg_p).gNB_CU_name[ie->value.choice.GNB_CU_Name.size]='\0'; - LOG_D(F1AP, "F1AP: F1Setup-Resp: gNB_CU_name %s\n", - F1AP_SETUP_RESP (msg_p).gNB_CU_name); - break; - case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List\n"); - num_cells_to_activate = ie->value.choice.Cells_to_be_Activated_List.list.count; - LOG_D(F1AP, "F1AP: Activating %d cells\n",num_cells_to_activate); - for (int i=0;ivalue.choice.Cells_to_be_Activated_List.list.array[i]; + LOG_D(F1AP, "F1AP: F1Setup-Resp: protocolIEs.list.count %d\n", + in->protocolIEs.list.count); + for (int i=0;i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + AssertFatal(ie->criticality == F1AP_Criticality_reject, + "ie->criticality != F1AP_Criticality_reject\n"); + AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_TransactionID, + "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_TransactionID\n"); + TransactionId=ie->value.choice.TransactionID; + LOG_D(F1AP, "F1AP: F1Setup-Resp: TransactionId %d\n", + TransactionId); + break; + case F1AP_ProtocolIE_ID_id_gNB_CU_Name: + AssertFatal(ie->criticality == F1AP_Criticality_ignore, + "ie->criticality != F1AP_Criticality_ignore\n"); + AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name, + "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_TransactionID\n"); + F1AP_SETUP_RESP (msg_p).gNB_CU_name = malloc(ie->value.choice.GNB_CU_Name.size+1); + memcpy(F1AP_SETUP_RESP (msg_p).gNB_CU_name,ie->value.choice.GNB_CU_Name.buf,ie->value.choice.GNB_CU_Name.size); + F1AP_SETUP_RESP (msg_p).gNB_CU_name[ie->value.choice.GNB_CU_Name.size]='\0'; + LOG_D(F1AP, "F1AP: F1Setup-Resp: gNB_CU_name %s\n", + F1AP_SETUP_RESP (msg_p).gNB_CU_name); + break; + case F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version: + LOG_D(F1AP, "F1AP: Received GNB-CU-RRC-Version, ignoring\n"); + break; + case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: + { + AssertFatal(ie->criticality == F1AP_Criticality_reject, + "ie->criticality != F1AP_Criticality_reject\n"); + AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List, + "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List\n"); + num_cells_to_activate = ie->value.choice.Cells_to_be_Activated_List.list.count; + LOG_D(F1AP, "F1AP: Activating %d cells\n",num_cells_to_activate); + for (int i=0;iid == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->id != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item"); - AssertFatal(cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject, - "cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject"); - AssertFatal(cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item"); + F1AP_Cells_to_be_Activated_List_ItemIEs_t *cells_to_be_activated_list_item_ies = (F1AP_Cells_to_be_Activated_List_ItemIEs_t *) ie->value.choice.Cells_to_be_Activated_List.list.array[i]; - cell = &cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item; + AssertFatal(cells_to_be_activated_list_item_ies->id == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, + "cells_to_be_activated_list_item_ies->id != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item"); + AssertFatal(cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject, + "cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject"); + AssertFatal(cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, + "cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item"); - TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, F1AP_SETUP_RESP (msg_p).mcc[i], F1AP_SETUP_RESP (msg_p).mnc[i], F1AP_SETUP_RESP (msg_p).mnc_digit_length[i]); - AssertFatal(cell->nRPCI != NULL, "nRPCI is null\n"); - LOG_D(F1AP, "nr_cellId : %x %x %x %x %x\n", - cell->nRCGI.nRCellIdentity.buf[0], - cell->nRCGI.nRCellIdentity.buf[1], - cell->nRCGI.nRCellIdentity.buf[2], - cell->nRCGI.nRCellIdentity.buf[3], - cell->nRCGI.nRCellIdentity.buf[4]); - BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, - F1AP_SETUP_RESP (msg_p).nr_cellid[i]); - F1AP_SETUP_RESP (msg_p).nrpci[i] = *cell->nRPCI; + cell = &cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item; - F1AP_ProtocolExtensionContainer_160P9_t *ext = (F1AP_ProtocolExtensionContainer_160P9_t *)cell->iE_Extensions; - AssertFatal(ext!=NULL,"Extension for SI is null\n"); - F1AP_SETUP_RESP (msg_p).num_SI[i] = ext->list.count; - AssertFatal(ext->list.count==1,"At least one SI message should be there, and only 1 for now!\n"); - LOG_D(F1AP, "F1AP: F1Setup-Resp Cell %d MCC %d MNC %d NRCellid %lx num_si %d\n", - i, F1AP_SETUP_RESP (msg_p).mcc[i], F1AP_SETUP_RESP (msg_p).mnc[i], - F1AP_SETUP_RESP (msg_p).nr_cellid[i], F1AP_SETUP_RESP (msg_p).num_SI[i]); - for (int si =0;si < ext->list.count;si++) { - size_t size = ext->list.array[si]->extensionValue.choice.GNB_CUSystemInformation.sImessage.size; - F1AP_SETUP_RESP (msg_p).SI_container_length[i][si] = size; - LOG_D(F1AP, "F1AP: F1Setup-Resp SI_container_length[%d][%d] %ld bytes\n", i, si, size); - F1AP_SETUP_RESP (msg_p).SI_container[i][si] = malloc(F1AP_SETUP_RESP (msg_p).SI_container_length[i][si]); + TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, F1AP_SETUP_RESP (msg_p).cells_to_activate[i].mcc, F1AP_SETUP_RESP (msg_p).cells_to_activate[i].mnc, F1AP_SETUP_RESP (msg_p).cells_to_activate[i].mnc_digit_length); - memcpy((void*)F1AP_SETUP_RESP (msg_p).SI_container[i][si], - (void*)ext->list.array[si]->extensionValue.choice.GNB_CUSystemInformation.sImessage.buf, - F1AP_SETUP_RESP (msg_p).SI_container_length[i][si]); - } - } - break; - } - } - AssertFatal(TransactionId!=-1,"TransactionId was not sent\n"); - AssertFatal(num_cells_to_activate>0,"No cells activated\n"); - F1AP_SETUP_RESP (msg_p).num_cells_to_activate = num_cells_to_activate; + LOG_D(F1AP, "nr_cellId : %x %x %x %x %x\n", + cell->nRCGI.nRCellIdentity.buf[0], + cell->nRCGI.nRCellIdentity.buf[1], + cell->nRCGI.nRCellIdentity.buf[2], + cell->nRCGI.nRCellIdentity.buf[3], + cell->nRCGI.nRCellIdentity.buf[4]); - for (int i=0;i 0, "System Information %d is missing",i); + BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, + F1AP_SETUP_RESP (msg_p).cells_to_activate[i].nr_cellid); + F1AP_ProtocolExtensionContainer_154P112_t *ext = (F1AP_ProtocolExtensionContainer_154P112_t *)cell->iE_Extensions; - MSC_LOG_RX_MESSAGE( - MSC_F1AP_DU, - MSC_F1AP_CU, - 0, - 0, - MSC_AS_TIME_FMT" DU_handle_F1_SETUP_RESPONSE successfulOutcome assoc_id %d", - 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), - assoc_id); - - LOG_D(F1AP, "Sending F1AP_SETUP_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n", + if (ext==NULL) continue; + + for (int cnt=0;cntlist.count;cnt++) { + F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs=(F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)ext->list.array[cnt]; + switch (cells_to_be_activated_list_itemExtIEs->id) { + /* + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_NOTHING: + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation, + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailablePLMNList, + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_ExtendedAvailablePLMN_List, + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_IAB_Info_IAB_donor_CU, + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailableSNPN_ID_List + */ + case F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation: + { + F1AP_SETUP_RESP (msg_p).cells_to_activate[i].nrpci = (cell->nRPCI != NULL) ? *cell->nRPCI : 0; + F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = (F1AP_GNB_CUSystemInformation_t*)&cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; + F1AP_SETUP_RESP (msg_p).cells_to_activate[i].num_SI = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; + AssertFatal(ext->list.count==1,"At least one SI message should be there, and only 1 for now!\n"); + LOG_D(F1AP, "F1AP: Cell %d MCC %d MNC %d NRCellid %lx num_si %d\n", + i, F1AP_SETUP_RESP (msg_p).cells_to_activate[i].mcc, F1AP_SETUP_RESP (msg_p).cells_to_activate[i].mnc, + F1AP_SETUP_RESP (msg_p).cells_to_activate[i].nr_cellid, F1AP_SETUP_RESP (msg_p).cells_to_activate[i].num_SI); + for (int si = 0;si < gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count;si++) { + F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[si]; + size_t size = sib_item->sIBmessage.size; + F1AP_SETUP_RESP (msg_p).cells_to_activate[i].SI_container_length[sib_item->sIBtype] = size; + LOG_I(F1AP, "F1AP: SI_container_length[%d][%d] %ld bytes\n", i, (int)sib_item->sIBtype, size); + F1AP_SETUP_RESP (msg_p).cells_to_activate[i].SI_container[sib_item->sIBtype] = malloc(size); + memcpy((void*)F1AP_SETUP_RESP (msg_p).cells_to_activate[i].SI_container[sib_item->sIBtype], + (void*)sib_item->sIBmessage.buf, + size); + } + break; + } + case F1AP_ProtocolIE_ID_id_AvailablePLMNList: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); + break; + case F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); + break; + case F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); + break; + case F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); + break; + default: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n",(int)cells_to_be_activated_list_itemExtIEs->id); + break; + } + } // for (cnt=... + } // for (cells_to_activate... + break; + } // case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List + + default: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n", (int)ie->id); + break; + } // switch ie + } // for IE + AssertFatal(TransactionId!=-1,"TransactionId was not sent\n"); + F1AP_SETUP_RESP (msg_p).num_cells_to_activate = num_cells_to_activate; + + for (int i=0;i 0, "System Information %d is missing",i); + + MSC_LOG_RX_MESSAGE( + MSC_F1AP_DU, + MSC_F1AP_CU, + 0, + 0, + MSC_AS_TIME_FMT" DU_handle_F1_SETUP_RESPONSE successfulOutcome assoc_id %d", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + assoc_id); + + if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_DU) { + LOG_D(F1AP, "Sending F1AP_SETUP_RESP ITTI message to GNB_APP with assoc_id (%d->%d)\n", assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id)); - itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); + itti_send_msg_to_task(TASK_GNB_APP, GNB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); + } else { + LOG_D(F1AP, "Sending F1AP_SETUP_RESP ITTI message to ENB_APP with assoc_id (%d->%d)\n", + assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id)); + itti_send_msg_to_task(TASK_ENB_APP, instance, msg_p); + } - return 0; + return 0; } // SETUP FAILURE @@ -553,6 +630,26 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_E(F1AP, "DU_handle_F1_SETUP_FAILURE\n"); + + F1AP_F1SetupFailure_t *out; + F1AP_F1SetupFailureIEs_t *ie; + + out = &pdu->choice.unsuccessfulOutcome->value.choice.F1SetupFailure; + + /* Transaction ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, + F1AP_ProtocolIE_ID_id_TransactionID, true); + + /* Cause */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, + F1AP_ProtocolIE_ID_id_Cause, true); + + if(0) { + /* TimeToWait */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, + F1AP_ProtocolIE_ID_id_TimeToWait, true); + } + return 0; } @@ -635,9 +732,19 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, served_cell_information.nRPCI = f1ap_setup_req->nr_pci[i]; // int 0..1007 /* - fiveGS_TAC */ - OCTET_STRING_fromBuf(&served_cell_information.fiveGS_TAC, - (const char *) &f1ap_setup_req->tac[i], - 3); + if (RC.nrrrc) { + uint8_t fiveGS_TAC[3]; + fiveGS_TAC[0] = ((uint8_t*)&f1ap_setup_req->tac[i])[2]; + fiveGS_TAC[1] = ((uint8_t*)&f1ap_setup_req->tac[i])[1]; + fiveGS_TAC[2] = ((uint8_t*)&f1ap_setup_req->tac[i])[0]; + OCTET_STRING_fromBuf(served_cell_information.fiveGS_TAC, + (const char *)fiveGS_TAC, + 3); + } else { + OCTET_STRING_fromBuf(served_cell_information.fiveGS_TAC, + (const char *) &f1ap_setup_req->tac[i], + 3); + } /* - Configured_EPS_TAC */ if(1){ @@ -647,17 +754,10 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, 2); } - /* - broadcast PLMNs */ - int maxnoofBPLMNS = 1; - for (i=0; - i PLMN BroadcastPLMNs Item */ - F1AP_BroadcastPLMNs_Item_t *broadcastPLMNs_Item = (F1AP_BroadcastPLMNs_Item_t *)calloc(1, sizeof(F1AP_BroadcastPLMNs_Item_t)); - //memset((void *)&broadcastPLMNs_Item, 0, sizeof(F1AP_BroadcastPLMNs_Item_t)); - MCC_MNC_TO_PLMNID(f1ap_setup_req->mcc[i], f1ap_setup_req->mnc[i], f1ap_setup_req->mnc_digit_length[i], &broadcastPLMNs_Item->pLMN_Identity); - ASN_SEQUENCE_ADD(&served_cell_information.servedPLMNs.list, broadcastPLMNs_Item); - } + F1AP_ServedPLMNs_Item_t *servedPLMN_item = calloc(1,sizeof(*servedPLMN_item)); + memset(servedPLMN_item,0,sizeof(*servedPLMN_item)); + MCC_MNC_TO_PLMNID(f1ap_du_data->mcc[i], f1ap_du_data->mnc[i], f1ap_du_data->mnc_digit_length[i], &servedPLMN_item->pLMN_Identity); + ASN_SEQUENCE_ADD(&served_cell_information.servedPLMNs.list, servedPLMN_item); // // /* - CHOICE NR-MODE-Info */ F1AP_NR_Mode_Info_t nR_Mode_Info; @@ -803,7 +903,7 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, served_cell_information.nRPCI = f1ap_setup_req->nr_pci[i]; // int 0..1007 /* - fiveGS_TAC */ - OCTET_STRING_fromBuf(&served_cell_information.fiveGS_TAC, + OCTET_STRING_fromBuf(served_cell_information.fiveGS_TAC, (const char *) &f1ap_setup_req->tac[i], 3); @@ -815,17 +915,10 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, 2); } - /* - broadcast PLMNs */ - int maxnoofBPLMNS = 1; - for (i=0; - i PLMN BroadcastPLMNs Item */ - F1AP_BroadcastPLMNs_Item_t *broadcastPLMNs_Item = (F1AP_BroadcastPLMNs_Item_t *)calloc(1, sizeof(F1AP_BroadcastPLMNs_Item_t)); - //memset((void *)&broadcastPLMNs_Item, 0, sizeof(F1AP_BroadcastPLMNs_Item_t)); - MCC_MNC_TO_PLMNID(f1ap_setup_req->mcc[i], f1ap_setup_req->mnc[i], f1ap_setup_req->mnc_digit_length[i], &broadcastPLMNs_Item->pLMN_Identity); - ASN_SEQUENCE_ADD(&served_cell_information.servedPLMNs.list, broadcastPLMNs_Item); - } + F1AP_ServedPLMNs_Item_t *servedPLMN_item = calloc(1,sizeof(*servedPLMN_item)); + memset(servedPLMN_item,0,sizeof(*servedPLMN_item)); + MCC_MNC_TO_PLMNID(f1ap_du_data->mcc[i], f1ap_du_data->mnc[i], f1ap_du_data->mnc_digit_length[i], &servedPLMN_item->pLMN_Identity); + ASN_SEQUENCE_ADD(&served_cell_information.servedPLMNs.list, servedPLMN_item); // // /* - CHOICE NR-MODE-Info */ F1AP_NR_Mode_Info_t nR_Mode_Info; @@ -963,45 +1056,9 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - /* mandatory */ - /* c5. Active_Cells_List */ - ie = (F1AP_GNBDUConfigurationUpdateIEs_t *)calloc(1, sizeof(F1AP_GNBDUConfigurationUpdateIEs_t)); - ie->id = F1AP_ProtocolIE_ID_id_Active_Cells_List; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Active_Cells_List; - - for (i=0; - i<1; - i++) { - // - F1AP_Active_Cells_ItemIEs_t *active_cells_item_ies; - active_cells_item_ies = (F1AP_Active_Cells_ItemIEs_t *)calloc(1, sizeof(F1AP_Active_Cells_ItemIEs_t)); - active_cells_item_ies->id = F1AP_ProtocolIE_ID_id_Active_Cells_Item; - active_cells_item_ies->criticality = F1AP_Criticality_reject; - active_cells_item_ies->value.present = F1AP_Active_Cells_ItemIEs__value_PR_Active_Cells_Item; - - F1AP_Active_Cells_Item_t active_cells_item; - memset((void *)&active_cells_item, 0, sizeof(F1AP_Active_Cells_Item_t)); - - /* 3.1 oldNRCGI */ - F1AP_NRCGI_t nRCGI; - memset(&nRCGI, 0, sizeof(F1AP_NRCGI_t)); - MCC_MNC_TO_PLMNID(f1ap_setup_req->mcc[i], f1ap_setup_req->mnc[i], f1ap_setup_req->mnc_digit_length[i], - &nRCGI.pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(f1ap_setup_req->nr_cellid[i], &nRCGI.nRCellIdentity); - active_cells_item.nRCGI = nRCGI; - - /* ADD */ - active_cells_item_ies->value.choice.Active_Cells_Item = active_cells_item; - - ASN_SEQUENCE_ADD(&ie->value.choice.Active_Cells_List.list, - active_cells_item_ies); - } - ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n"); return -1; } @@ -1029,17 +1086,229 @@ int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); + + if(!RC.nrrrc) { + return 0; + } + + LOG_D(F1AP, "DU_handle_gNB_CU_CONFIGURATION_UPDATE\n"); + + AssertFatal(pdu->present == F1AP_F1AP_PDU_PR_initiatingMessage, + "pdu->present != F1AP_F1AP_PDU_PR_initiatingMessage\n"); + AssertFatal(pdu->choice.initiatingMessage->procedureCode == F1AP_ProcedureCode_id_gNBCUConfigurationUpdate, + "pdu->choice.initiatingMessage->procedureCode != F1AP_ProcedureCode_id_gNBCUConfigurationUpdate\n"); + AssertFatal(pdu->choice.initiatingMessage->criticality == F1AP_Criticality_reject, + "pdu->choice.initiatingMessage->criticality != F1AP_Criticality_reject\n"); + AssertFatal(pdu->choice.initiatingMessage->value.present == F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate, + "pdu->choice.initiatingMessage->value.present != F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate\n"); + + F1AP_GNBCUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; + + + F1AP_GNBCUConfigurationUpdateIEs_t *ie; + int TransactionId = -1; + int num_cells_to_activate = 0; + F1AP_Cells_to_be_Activated_List_Item_t *cell; + + MessageDef *msg_p = itti_alloc_new_message (TASK_DU_F1, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE); + + LOG_D(F1AP, "F1AP: gNB_CU_Configuration_Update: protocolIEs.list.count %d\n", + in->protocolIEs.list.count); + for (int i=0;i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + AssertFatal(ie->criticality == F1AP_Criticality_reject, + "ie->criticality != F1AP_Criticality_reject\n"); + AssertFatal(ie->value.present == F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID, + "ie->value.present != F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID\n"); + TransactionId=ie->value.choice.TransactionID; + LOG_D(F1AP, "F1AP: GNB-CU-ConfigurationUpdate: TransactionId %d\n", + TransactionId); + break; + case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: + { + AssertFatal(ie->criticality == F1AP_Criticality_reject, + "ie->criticality != F1AP_Criticality_reject\n"); + AssertFatal(ie->value.present == F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List, + "ie->value.present != F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List\n"); + num_cells_to_activate = ie->value.choice.Cells_to_be_Activated_List.list.count; + LOG_D(F1AP, "F1AP: Activating %d cells\n",num_cells_to_activate); + for (int i=0;ivalue.choice.Cells_to_be_Activated_List.list.array[i]; + + AssertFatal(cells_to_be_activated_list_item_ies->id == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, + "cells_to_be_activated_list_item_ies->id != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item"); + AssertFatal(cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject, + "cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject"); + AssertFatal(cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, + "cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item"); + + cell = &cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item; + + TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].mcc, F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].mnc, F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].mnc_digit_length); + + LOG_D(F1AP, "nr_cellId : %x %x %x %x %x\n", + cell->nRCGI.nRCellIdentity.buf[0], + cell->nRCGI.nRCellIdentity.buf[1], + cell->nRCGI.nRCellIdentity.buf[2], + cell->nRCGI.nRCellIdentity.buf[3], + cell->nRCGI.nRCellIdentity.buf[4]); + BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].nr_cellid); + F1AP_ProtocolExtensionContainer_154P112_t *ext = (F1AP_ProtocolExtensionContainer_154P112_t *)cell->iE_Extensions; + + if (ext==NULL) continue; + + for (int cnt=0;cntlist.count;cnt++) { + F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs=(F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)ext->list.array[cnt]; + switch (cells_to_be_activated_list_itemExtIEs->id) { + /* + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_NOTHING: + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation, + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailablePLMNList, + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_ExtendedAvailablePLMN_List, + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_IAB_Info_IAB_donor_CU, + case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailableSNPN_ID_List + */ + case F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation: + { + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].nrpci = (cell->nRPCI != NULL) ? *cell->nRPCI : 0; + F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = (F1AP_GNB_CUSystemInformation_t*)&cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].num_SI = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; + AssertFatal(ext->list.count==1,"At least one SI message should be there, and only 1 for now!\n"); + LOG_D(F1AP, "F1AP: Cell %d MCC %d MNC %d NRCellid %lx num_si %d\n", + i, F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].mcc, F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].mnc, + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].nr_cellid, F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].num_SI); + for (int si = 0;si < gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count;si++) { + F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[si]; + size_t size = sib_item->sIBmessage.size; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container_length[sib_item->sIBtype] = size; + LOG_I(F1AP, "F1AP: SI_container_length[%d][%d] %ld bytes\n", i, (int)sib_item->sIBtype, size); + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container[sib_item->sIBtype] = malloc(size); + memcpy((void*)F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container[sib_item->sIBtype], + (void*)sib_item->sIBmessage.buf, + size); + } + break; + } + case F1AP_ProtocolIE_ID_id_AvailablePLMNList: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); + break; + case F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); + break; + case F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); + break; + case F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); + break; + default: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n",(int)cells_to_be_activated_list_itemExtIEs->id); + break; + } + } // for (cnt=... + } // for (cells_to_activate... + break; + } // case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List + + default: + AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n", (int)ie->id); + break; + } // switch ie + } // for IE + AssertFatal(TransactionId!=-1,"TransactionId was not sent\n"); + LOG_D(F1AP,"F1AP: num_cells_to_activate %d\n",num_cells_to_activate); + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).num_cells_to_activate = num_cells_to_activate; + + MSC_LOG_RX_MESSAGE( + MSC_F1AP_DU, + MSC_F1AP_CU, + 0, + 0, + MSC_AS_TIME_FMT" DU_handle_GNB_CU_CONFIGURATION_UPDATE initiatingMessage assoc_id %d", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + assoc_id); + + if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_DU) { + LOG_D(F1AP, "Sending F1AP_GNB_CU_CONFIGURATION_UPDATE ITTI message to GNB_APP with assoc_id (%d->%d)\n", + assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id)); + itti_send_msg_to_task(TASK_GNB_APP, GNB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); + } else { + LOG_D(F1AP, "Sending F1AP_GNB_CU_CONFIGURATION_UPDATE ITTI message to ENB_APP with assoc_id (%d->%d)\n", + assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id)); + itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); + } + + return 0; } int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(instance_t instance, - F1AP_GNBCUConfigurationUpdateFailure_t *GNBCUConfigurationUpdateFailure) { - AssertFatal(1==0,"Not implemented yet\n"); + f1ap_gnb_cu_configuration_update_failure_t *GNBCUConfigurationUpdateFailure) { + AssertFatal(1==0,"received gNB CU CONFIGURATION UPDATE FAILURE with cause %d\n", + GNBCUConfigurationUpdateFailure->cause); } int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, - F1AP_GNBCUConfigurationUpdateAcknowledge_t *GNBCUConfigurationUpdateAcknowledge) { - AssertFatal(1==0,"Not implemented yet\n"); + f1ap_gnb_cu_configuration_update_acknowledge_t *GNBCUConfigurationUpdateAcknowledge) { + + if(!RC.nrrrc) { + return 0; + } + + AssertFatal(GNBCUConfigurationUpdateAcknowledge->num_cells_failed_to_be_activated == 0, + "%d cells failed to activate\n", + GNBCUConfigurationUpdateAcknowledge->num_cells_failed_to_be_activated); + + AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_to_setup == 0, + "%d TNLAssociations to setup, handle this ...\n", + GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_to_setup); + + + AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_failed == 0, + "%d TNLAssociations failed\n", + GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_failed); + + AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofDedicatedSIDeliveryNeededUEs == 0, + "%d DedicatedSIDeliveryNeededUEs\n", + GNBCUConfigurationUpdateAcknowledge->noofDedicatedSIDeliveryNeededUEs); + + F1AP_F1AP_PDU_t pdu; + uint8_t *buffer; + uint32_t len; + + /* Create */ + /* 0. pdu Type */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = (F1AP_SuccessfulOutcome_t *)calloc(1, sizeof(F1AP_SuccessfulOutcome_t)); + pdu.choice.successfulOutcome->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; + pdu.choice.successfulOutcome->criticality = F1AP_Criticality_reject; + pdu.choice.successfulOutcome->value.present = F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge; + F1AP_GNBCUConfigurationUpdateAcknowledge_t *out = &pdu.choice.successfulOutcome->value.choice.GNBCUConfigurationUpdateAcknowledge; + + /* mandatory */ + /* c1. Transaction ID (integer value)*/ + F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t *ie = (F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t *)calloc(1, sizeof(F1AP_F1SetupResponseIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; + ie->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* encode */ + if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode GNB-DU-Configuration-Update-Acknowledge\n"); + return -1; + } + + du_f1ap_itti_send_sctp_data_req(instance, f1ap_du_data->assoc_id, buffer, len, 0); + + + + return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.h b/openair2/F1AP/f1ap_du_interface_management.h index 941b86a6d4..619b725f38 100644 --- a/openair2/F1AP/f1ap_du_interface_management.h +++ b/openair2/F1AP/f1ap_du_interface_management.h @@ -98,17 +98,17 @@ int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, F1AP_F1AP_PDU_t *pdu); int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(instance_t instance, - F1AP_GNBCUConfigurationUpdateFailure_t *GNBCUConfigurationUpdateFailure); + f1ap_gnb_cu_configuration_update_failure_t *GNBCUConfigurationUpdateFailure); int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, - F1AP_GNBCUConfigurationUpdateAcknowledge_t *GNBCUConfigurationUpdateAcknowledge); + f1ap_gnb_cu_configuration_update_acknowledge_t *GNBCUConfigurationUpdateAcknowledge); /* * gNB-DU Resource Coordination */ int DU_send_gNB_DU_RESOURCE_COORDINATION_REQUEST(instance_t instance, - F1AP_GNBDUResourceCoordinationRequest_t *GNBDUResourceCoordinationRequest); + F1AP_GNBDUResourceCoordinationRequest_t *GNBDUResourceCoordinationRequest); int DU_handle_gNB_DU_RESOURCE_COORDINATION_RESPONSE(instance_t instance, uint32_t assoc_id, diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 6953588818..0c8f566fd6 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -42,32 +42,50 @@ #include "LTE_DL-DCCH-Message.h" #include "LTE_UL-DCCH-Message.h" +#include "NR_DL-CCCH-Message.h" +#include "NR_UL-CCCH-Message.h" +#include "NR_DL-DCCH-Message.h" +#include "NR_UL-DCCH-Message.h" // for SRB1_logicalChannelConfig_defaultValue #include "rrc_extern.h" #include "common/ran_context.h" #include "rrc_eNB_UE_context.h" +#include "openair2/RRC/NR/rrc_gNB_UE_context.h" #include "asn1_msg.h" #include "intertask_interface.h" - -// undefine C_RNTI from -// openair1/PHY/LTE_TRANSPORT/transport_common.h which -// replaces in ie->value.choice.C_RNTI, causing -// a compile error - -#undef C_RNTI +#include "LAYER2/NR_MAC_gNB/mac_proto.h" extern f1ap_setup_req_t *f1ap_du_data; extern RAN_CONTEXT_t RC; extern f1ap_cudu_inst_t f1ap_du_inst[MAX_eNB]; +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_srb_bearer2add_list, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_drb_bearer2add_list); +uint8_t du_ccch_flag = 1; + +int DU_handle_DL_NR_RRC_MESSAGE_TRANSFER(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + F1AP_F1AP_PDU_t *pdu); /* DL RRC Message Transfer */ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { + + if (RC.nrrrc && RC.nrrrc[instance]->node_type == ngran_gNB_DU) { + LOG_I(F1AP, "node is gNB DU, call DU_handle_DL_NR_RRC_MESSAGE_TRANSFER \n"); + return DU_handle_DL_NR_RRC_MESSAGE_TRANSFER(instance, assoc_id, stream, pdu); + } + LOG_D(F1AP, "DU_handle_DL_RRC_MESSAGE_TRANSFER \n"); F1AP_DLRRCMessageTransfer_t *container; @@ -143,7 +161,7 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, // BK: need check // create an ITTI message and copy SDU - // message_p = itti_alloc_new_message (TASK_CU_F1, RRC_MAC_CCCH_DATA_IND); + // message_p = itti_alloc_new_message (TASK_CU_F1, 0, RRC_MAC_CCCH_DATA_IND); // memset (RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); rrc_dl_sdu_len = ie->value.choice.RRCContainer.size; // memcpy(RRC_MAC_CCCH_DATA_IND (message_p).sdu, ie->value.choice.RRCContainer.buf, @@ -161,10 +179,10 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation, true); switch(ie->value.choice.RAT_FrequencyPriorityInformation.present) { - case F1AP_RAT_FrequencyPriorityInformation_PR_subscriberProfileIDforRFP: + case F1AP_RAT_FrequencyPriorityInformation_PR_eNDC: //subscriberProfileIDforRFP = ie->value.choice.RAT_FrequencyPriorityInformation.choice.subscriberProfileIDforRFP; break; - case F1AP_RAT_FrequencyPriorityInformation_PR_rAT_FrequencySelectionPriority: + case F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN: //rAT_FrequencySelectionPriority = ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority; break; default: @@ -402,7 +420,7 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, MessageDef *message_p = NULL; /* Send DRX configuration to MAC task to configure timers of local UE context */ - message_p = itti_alloc_new_message(TASK_DU_F1, RRC_MAC_DRX_CONFIG_REQ); + message_p = itti_alloc_new_message(TASK_DU_F1, 0, RRC_MAC_DRX_CONFIG_REQ); RRC_MAC_DRX_CONFIG_REQ(message_p).rnti = ctxt.rnti; RRC_MAC_DRX_CONFIG_REQ(message_p).drx_Configuration = mac_MainConfig->drx_Config; itti_send_msg_to_task(TASK_MAC_ENB, ctxt.module_id, message_p); @@ -454,36 +472,36 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, DRB2LCHAN[i] = (uint8_t) * DRB_configList->list.array[i]->logicalChannelIdentity; } - rrc_mac_config_req_eNB( - ctxt.module_id, - 0,0,0,0,0,0, - 0, - ue_context_p->ue_context.rnti, - (LTE_BCCH_BCH_Message_t *) NULL, - (LTE_RadioResourceConfigCommonSIB_t *) NULL, - (LTE_RadioResourceConfigCommonSIB_t *) NULL, - physicalConfigDedicated, - (LTE_SCellToAddMod_r10_t *)NULL, - //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, - (LTE_MeasObjectToAddMod_t **) NULL, - mac_MainConfig, - DRB2LCHAN[i], - DRB_configList->list.array[i]->logicalChannelConfig, - measGapConfig, - (LTE_TDD_Config_t *) NULL, - NULL, - (LTE_SchedulingInfoList_t *) NULL, - 0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL - , 0, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) NULL, - (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL, - 0, - (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL, - (LTE_SchedulingInfo_MBMS_r14_t *) NULL, - (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, - (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL, - (LTE_MBSFNAreaConfiguration_r9_t*) NULL - ); + rrc_mac_config_req_eNB( + ctxt.module_id, + 0,0,0,0,0,0, + 0, + ue_context_p->ue_context.rnti, + (LTE_BCCH_BCH_Message_t *) NULL, + (LTE_RadioResourceConfigCommonSIB_t *) NULL, + (LTE_RadioResourceConfigCommonSIB_t *) NULL, + physicalConfigDedicated, + (LTE_SCellToAddMod_r10_t *)NULL, + //(struct PhysicalConfigDedicatedSCell_r10 *)NULL, + (LTE_MeasObjectToAddMod_t **) NULL, + mac_MainConfig, + DRB2LCHAN[i], + DRB_configList->list.array[i]->logicalChannelConfig, + measGapConfig, + (LTE_TDD_Config_t *) NULL, + NULL, + (LTE_SchedulingInfoList_t *) NULL, + 0, NULL, NULL, (LTE_MBSFN_SubframeConfigList_t *) NULL + , 0, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) NULL, + (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL, + 0, + (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL, + (LTE_SchedulingInfo_MBMS_r14_t *) NULL, + (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, + (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*) NULL + ); } } else { // remove LCHAN from MAC/PHY @@ -599,7 +617,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, uint32_t len; - LOG_I(F1AP, "[DU %d] %s: size %d UE RNTI %x in SRB %d\n", + LOG_I(F1AP, "[DU %ld] %s: size %d UE RNTI %x in SRB %d\n", instance, __func__, msg->rrc_container_length, rnti, msg->srb_id); //LOG_I(F1AP, "%s() RRCContainer size %d: ", __func__, msg->rrc_container_length); @@ -721,7 +739,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, } else { LOG_I(F1AP, "Processing RRCConnectionSetupComplete UE %x\n", rnti); - ue_context_p->ue_context.Status = RRC_CONNECTED; + ue_context_p->ue_context.StatusRrc = RRC_CONNECTED; } break; @@ -765,7 +783,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, } /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 UL RRC MESSAGE TRANSFER\n"); return -1; } @@ -780,7 +798,10 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, int UE_id, rnti_t rntiP, const uint8_t *sduP, - sdu_size_t sdu_lenP) { + sdu_size_t sdu_lenP, + const int8_t *sdu2P, + sdu_size_t sdu2_lenP) { + F1AP_F1AP_PDU_t pdu; F1AP_InitialULRRCMessageTransfer_t *out; F1AP_InitialULRRCMessageTransferIEs_t *ie; @@ -836,7 +857,7 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, ie->id = F1AP_ProtocolIE_ID_id_C_RNTI; ie->criticality = F1AP_Criticality_reject; ie->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_C_RNTI; - C_RNTI_TO_BIT_STRING(rntiP, &ie->value.choice.C_RNTI); + ie->value.choice.C_RNTI=rntiP; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); /* mandatory */ @@ -850,29 +871,36 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, /* optional */ /* c5. DUtoCURRCContainer */ - if (0) { + if (sdu2P && RC.nrrrc) { ie = (F1AP_InitialULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_InitialULRRCMessageTransferIEs_t)); ie->id = F1AP_ProtocolIE_ID_id_DUtoCURRCContainer; ie->criticality = F1AP_Criticality_reject; ie->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_DUtoCURRCContainer; - OCTET_STRING_fromBuf(&ie->value.choice.DUtoCURRCContainer, "dummy_val", - strlen("dummy_val")); + OCTET_STRING_fromBuf(&ie->value.choice.DUtoCURRCContainer, (char *)sdu2P, sdu2_lenP); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - } + } /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 INITIAL UL RRC MESSAGE TRANSFER\n"); return -1; } - - struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_allocate_new_UE_context(RC.rrc[module_idP]); - ue_context_p->ue_id_rnti = rntiP; - ue_context_p->ue_context.rnti = rntiP; - ue_context_p->ue_context.random_ue_identity = rntiP; - ue_context_p->ue_context.Srb0.Active = 1; - RB_INSERT(rrc_ue_tree_s, &RC.rrc[module_idP]->rrc_ue_head, ue_context_p); + if (RC.nrrrc && RC.nrrrc[module_idP]->node_type == ngran_gNB_DU) { + struct rrc_gNB_ue_context_s* ue_context_p = rrc_gNB_allocate_new_UE_context(RC.nrrrc[module_idP]); + ue_context_p->ue_id_rnti = rntiP; + ue_context_p->ue_context.rnti = rntiP; + ue_context_p->ue_context.random_ue_identity = rntiP; + ue_context_p->ue_context.Srb0.Active = 1; + RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[module_idP]->rrc_ue_head, ue_context_p); + } else { + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_allocate_new_UE_context(RC.rrc[module_idP]); + ue_context_p->ue_id_rnti = rntiP; + ue_context_p->ue_context.rnti = rntiP; + ue_context_p->ue_context.random_ue_identity = rntiP; + ue_context_p->ue_context.Srb0.Active = 1; + RB_INSERT(rrc_ue_tree_s, &RC.rrc[module_idP]->rrc_ue_head, ue_context_p); + } du_f1ap_itti_send_sctp_data_req(module_idP, f1ap_du_data->assoc_id, buffer, len, f1ap_du_data->default_sctp_stream_id); return 0; @@ -884,4 +912,473 @@ void init_f1ap_du_ue_inst (void) { memset(f1ap_du_inst, 0, sizeof(f1ap_du_inst)); } +int DU_send_UL_NR_RRC_MESSAGE_TRANSFER(instance_t instance, + const f1ap_ul_rrc_message_t *msg) { + const rnti_t rnti = msg->rnti; + F1AP_F1AP_PDU_t pdu; + F1AP_ULRRCMessageTransfer_t *out; + F1AP_ULRRCMessageTransferIEs_t *ie; + + uint8_t *buffer = NULL; + uint32_t len; + + + LOG_I(F1AP, "[DU %ld] %s: size %d UE RNTI %x in SRB %d\n", + instance, __func__, msg->rrc_container_length, rnti, msg->srb_id); + + //LOG_I(F1AP, "%s() RRCContainer size %d: ", __func__, msg->rrc_container_length); + //for (int i = 0;i < msg->rrc_container_length; i++) + // printf("%02x ", msg->rrc_container[i]); + //printf("\n"); + + /* Create */ + /* 0. Message Type */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = (F1AP_InitiatingMessage_t *)calloc(1, sizeof(F1AP_InitiatingMessage_t)); + pdu.choice.initiatingMessage->procedureCode = F1AP_ProcedureCode_id_ULRRCMessageTransfer; + pdu.choice.initiatingMessage->criticality = F1AP_Criticality_ignore; + pdu.choice.initiatingMessage->value.present = F1AP_InitiatingMessage__value_PR_ULRRCMessageTransfer; + out = &pdu.choice.initiatingMessage->value.choice.ULRRCMessageTransfer; + + /* mandatory */ + /* c1. GNB_CU_UE_F1AP_ID */ + ie = (F1AP_ULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_ULRRCMessageTransferIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; + + ie->value.choice.GNB_CU_UE_F1AP_ID = f1ap_get_cu_ue_f1ap_id(&f1ap_du_inst[instance], rnti); + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + /* c2. GNB_DU_UE_F1AP_ID */ + ie = (F1AP_ULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_ULRRCMessageTransferIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie->value.choice.GNB_DU_UE_F1AP_ID = f1ap_get_du_ue_f1ap_id(&f1ap_du_inst[instance], rnti); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + /* c3. SRBID */ + ie = (F1AP_ULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_ULRRCMessageTransferIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_SRBID; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_SRBID; + ie->value.choice.SRBID = msg->srb_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + // issue in here + /* mandatory */ + /* c4. RRCContainer */ + ie = (F1AP_ULRRCMessageTransferIEs_t *)calloc(1, sizeof(F1AP_ULRRCMessageTransferIEs_t)); + ie->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, + (const char *) msg->rrc_container, + msg->rrc_container_length); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* encode */ + if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UL RRC MESSAGE TRANSFER \n"); + return -1; + } + + du_f1ap_itti_send_sctp_data_req(instance, f1ap_du_data->assoc_id, buffer, len, f1ap_du_data->default_sctp_stream_id); + return 0; +} + +/* DL NR RRC Message Transfer */ +int DU_handle_DL_NR_RRC_MESSAGE_TRANSFER(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + F1AP_F1AP_PDU_t *pdu) { + LOG_D(F1AP, "DU_handle_DL_NR_RRC_MESSAGE_TRANSFER \n"); + + F1AP_DLRRCMessageTransfer_t *container; + F1AP_DLRRCMessageTransferIEs_t *ie; + + uint64_t cu_ue_f1ap_id; + uint64_t du_ue_f1ap_id; + uint64_t srb_id; + int executeDuplication; + sdu_size_t rrc_dl_sdu_len; + //uint64_t subscriberProfileIDforRFP; + //uint64_t rAT_FrequencySelectionPriority; + + DevAssert(pdu != NULL); + + if (stream != 0) { + LOG_E(F1AP, "[SCTP %d] Received F1 on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } + + container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer; + + + /* GNB_CU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + cu_ue_f1ap_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + LOG_D(F1AP, "cu_ue_f1ap_id %lu \n", cu_ue_f1ap_id); + + + /* GNB_DU_UE_F1AP_ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + du_ue_f1ap_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + LOG_D(F1AP, "du_ue_f1ap_id %lu associated with UE RNTI %x \n", + du_ue_f1ap_id, + f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], du_ue_f1ap_id)); // this should be the one transmitted via initial ul rrc message transfer + + if (f1ap_du_add_cu_ue_id(&f1ap_du_inst[instance],du_ue_f1ap_id, cu_ue_f1ap_id) < 0 ) { + LOG_E(F1AP, "Failed to find the F1AP UID \n"); + //return -1; + } + + /* optional */ + /* oldgNB_DU_UE_F1AP_ID */ + if (0) { + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, true); + } + + /* mandatory */ + /* SRBID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_SRBID, true); + srb_id = ie->value.choice.SRBID; + LOG_D(F1AP, "srb_id %lu \n", srb_id); + + /* optional */ + /* ExecuteDuplication */ + if (0) { + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_ExecuteDuplication, true); + executeDuplication = ie->value.choice.ExecuteDuplication; + LOG_D(F1AP, "ExecuteDuplication %d \n", executeDuplication); + } + + // issue in here + /* mandatory */ + /* RRC Container */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_RRCContainer, true); + // BK: need check + // create an ITTI message and copy SDU + + // message_p = itti_alloc_new_message (TASK_CU_F1, RRC_MAC_CCCH_DATA_IND); + // memset (RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); + rrc_dl_sdu_len = ie->value.choice.RRCContainer.size; + // memcpy(RRC_MAC_CCCH_DATA_IND (message_p).sdu, ie->value.choice.RRCContainer.buf, + // ccch_sdu_len); + + //LOG_I(F1AP, "%s() RRCContainer size %lu: ", __func__, ie->value.choice.RRCContainer.size); + //for (int i = 0;i < ie->value.choice.RRCContainer.size; i++) + // printf("%02x ", ie->value.choice.RRCContainer.buf[i]); + //printf("\n"); + + /* optional */ + /* RAT_FrequencyPriorityInformation */ + if (0) { + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation, true); + + switch(ie->value.choice.RAT_FrequencyPriorityInformation.present) { + case F1AP_RAT_FrequencyPriorityInformation_PR_eNDC: + //subscriberProfileIDforRFP = ie->value.choice.RAT_FrequencyPriorityInformation.choice.subscriberProfileIDforRFP; + break; + case F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN: + //rAT_FrequencySelectionPriority = ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority; + break; + default: + LOG_W(F1AP, "unhandled IE RAT_FrequencyPriorityInformation.present\n"); + break; + } + } + + // decode RRC Container and act on the message type + AssertFatal(srb_id<3,"illegal srb_id\n"); + + protocol_ctxt_t ctxt; + ctxt.rnti = f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], du_ue_f1ap_id); + ctxt.module_id = instance; + ctxt.instance = instance; + ctxt.enb_flag = 1; + + struct rrc_gNB_ue_context_s* ue_context_p = rrc_gNB_get_ue_context( + RC.nrrrc[ctxt.module_id], + ctxt.rnti); + + gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; + if (srb_id == 0) { + NR_DL_CCCH_Message_t* dl_ccch_msg=NULL; + asn_dec_rval_t dec_rval; + dec_rval = uper_decode(NULL, + &asn_DEF_NR_DL_CCCH_Message, + (void**)&dl_ccch_msg, + ie->value.choice.RRCContainer.buf, + rrc_dl_sdu_len,0,0); + AssertFatal(dec_rval.code == RC_OK, "could not decode F1AP message\n"); + switch (dl_ccch_msg->message.choice.c1->present) { + + case NR_DL_CCCH_MessageType__c1_PR_NOTHING: + + LOG_I(F1AP, "Received PR_NOTHING on DL-CCCH-Message\n"); + break; + + case NR_DL_CCCH_MessageType__c1_PR_rrcReject: + LOG_I(F1AP, + "Logical Channel DL-CCCH (SRB0), Received RRCReject\n"); + break; + + case NR_DL_CCCH_MessageType__c1_PR_rrcSetup: + { + LOG_I(F1AP, + "Logical Channel DL-CCCH (SRB0), Received RRCSetup DU_ID %lx/RNTI %x\n", + du_ue_f1ap_id, + f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], du_ue_f1ap_id)); + // Get configuration + + NR_RRCSetup_t* rrcSetup = dl_ccch_msg->message.choice.c1->choice.rrcSetup; + AssertFatal(rrcSetup!=NULL, "rrcSetup is null\n"); + NR_RRCSetup_IEs_t *rrcSetup_ies = rrcSetup->criticalExtensions.choice.rrcSetup; + + ue_context_p->ue_context.SRB_configList = rrcSetup_ies->radioBearerConfig.srb_ToAddModList; + AssertFatal(rrcSetup_ies->masterCellGroup.buf!=NULL,"masterCellGroup is null\n"); + asn_dec_rval_t dec_rval; + dec_rval = uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, + (void**)&ue_context_p->ue_context.masterCellGroup, + rrcSetup_ies->masterCellGroup.buf, + rrcSetup_ies->masterCellGroup.size,0,0); + AssertFatal(dec_rval.code == RC_OK, "could not decode masterCellGroup\n"); + + apply_macrlc_config(rrc,ue_context_p,&ctxt); + + gNB_RRC_UE_t *ue_p = &ue_context_p->ue_context; + AssertFatal(ue_p->Srb0.Active == 1,"SRB0 is not active\n"); + + memcpy((void*)ue_p->Srb0.Tx_buffer.Payload, + (void*)ie->value.choice.RRCContainer.buf, + rrc_dl_sdu_len); // ie->value.choice.RRCContainer.size + + ue_p->Srb0.Tx_buffer.payload_size = rrc_dl_sdu_len; + + break; + } // case + + case NR_DL_CCCH_MessageType__c1_PR_spare2: + LOG_I(F1AP, + "Logical Channel DL-CCCH (SRB0), Received spare2\n"); + break; + + case NR_DL_CCCH_MessageType__c1_PR_spare1: + LOG_I(F1AP, + "Logical Channel DL-CCCH (SRB0), Received spare1\n"); + break; + + default: + AssertFatal(1==0, + "Unknown message\n"); + break; + }// switch case + return(0); + } else if (srb_id == 1) { + + NR_DL_DCCH_Message_t* dl_dcch_msg=NULL; + asn_dec_rval_t dec_rval; + dec_rval = uper_decode(NULL, + &asn_DEF_NR_DL_DCCH_Message, + (void**)&dl_dcch_msg, + &ie->value.choice.RRCContainer.buf[2], // buf[0] includes the pdcp header + rrc_dl_sdu_len-6,0,0); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) + LOG_E(F1AP," Failed to decode DL-DCCH (%zu bytes)\n",dec_rval.consumed); + else + LOG_D(F1AP, "Received message: present %d and c1 present %d\n", + dl_dcch_msg->message.present, dl_dcch_msg->message.choice.c1->present); + + if (dl_dcch_msg->message.present == NR_DL_DCCH_MessageType_PR_c1) { + switch (dl_dcch_msg->message.choice.c1->present) { + case NR_DL_DCCH_MessageType__c1_PR_NOTHING: + LOG_I(F1AP, "Received PR_NOTHING on DL-DCCH-Message\n"); + return 0; + + case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: + // handle RRCReconfiguration + LOG_I(F1AP, + "Logical Channel DL-DCCH (SRB1), Received RRCReconfiguration DU_ID %lx/RNTI %x\n", + du_ue_f1ap_id, + f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], du_ue_f1ap_id)); + + NR_RRCReconfiguration_t* rrcReconfiguration = dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration; + + if (rrcReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration) { + NR_RRCReconfiguration_IEs_t* rrcReconfiguration_ies = + rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration; + + if (rrcReconfiguration_ies->measConfig != NULL) { + LOG_I(F1AP, "Measurement Configuration is present\n"); + } + + if (rrcReconfiguration_ies->radioBearerConfig) { + LOG_I(F1AP, "Radio Resource Configuration is present\n"); + long drb_id; + int i; + NR_DRB_ToAddModList_t *DRB_configList = rrcReconfiguration_ies->radioBearerConfig->drb_ToAddModList; + NR_SRB_ToAddModList_t *SRB_configList = rrcReconfiguration_ies->radioBearerConfig->srb_ToAddModList; + // NR_DRB_ToReleaseList_t *DRB_ReleaseList = rrcReconfiguration_ies->radioBearerConfig->drb_ToReleaseList; + + // rrc_rlc_config_asn1_req + + if (SRB_configList != NULL) { + for (i = 0; (i < SRB_configList->list.count) && (i < 3); i++) { + if (SRB_configList->list.array[i]->srb_Identity == 1 ){ + ue_context_p->ue_context.Srb1.Active=1; + } + else if (SRB_configList->list.array[i]->srb_Identity == 2 ) { + ue_context_p->ue_context.Srb2.Active=1; + ue_context_p->ue_context.Srb2.Srb_info.Srb_id=2; + LOG_I(F1AP, "[DU %d] SRB2 is now active\n",ctxt.module_id); + } else { + LOG_W(F1AP, "[DU %d] invalide SRB identity %ld\n",ctxt.module_id, + SRB_configList->list.array[i]->srb_Identity); + } + } + } + + if (DRB_configList != NULL) { + for (i = 0; i < DRB_configList->list.count; i++) { // num max DRB (11-3-8) + if (DRB_configList->list.array[i]) { + drb_id = (int)DRB_configList->list.array[i]->drb_Identity; + LOG_I(F1AP, + "[DU %d] Logical Channel UL-DCCH, Received RRCConnectionReconfiguration for UE rnti %x, reconfiguring DRB %d\n", + ctxt.module_id, + ctxt.rnti, + (int)DRB_configList->list.array[i]->drb_Identity); + // (int)*DRB_configList->list.array[i]->logicalChannelIdentity); + + if (ue_context_p->ue_context.DRB_active[drb_id] == 0) { + ue_context_p->ue_context.DRB_active[drb_id] = 1; + + // logicalChannelIdentity + // rrc_mac_config_req_eNB + } + + } else { // remove LCHAN from MAC/PHY + AssertFatal(1==0,"Can't handle this yet in DU\n"); + } + } + } + } + } + break; + case NR_DL_DCCH_MessageType__c1_PR_rrcResume: + LOG_I(F1AP,"Received rrcResume\n"); + break; + case NR_DL_DCCH_MessageType__c1_PR_rrcRelease: + LOG_I(F1AP,"Received rrcRelease\n"); + break; + case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: + LOG_I(F1AP,"Received rrcReestablishment\n"); + break; + case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: + LOG_I(F1AP,"Received securityModeCommand\n"); + break; + case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: + LOG_I(F1AP, "Received dlInformationTransfer\n"); + break; + case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry: + LOG_I(F1AP, "Received ueCapabilityEnquiry\n"); + break; + case NR_DL_DCCH_MessageType__c1_PR_counterCheck: + LOG_I(F1AP, "Received counterCheck\n"); + break; + case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand: + case NR_DL_DCCH_MessageType__c1_PR_dlDedicatedMessageSegment_r16: + case NR_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r16: + case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransferMRDC_r16: + case NR_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r16: + case NR_DL_DCCH_MessageType__c1_PR_spare3: + case NR_DL_DCCH_MessageType__c1_PR_spare2: + case NR_DL_DCCH_MessageType__c1_PR_spare1: + break; + } + } + } + else if (srb_id == 2) { + // TODO + } + + LOG_I(F1AP, "Received DL RRC Transfer on srb_id %ld\n", srb_id); + + +// rlc_op_status_t rlc_status; +// boolean_t ret = TRUE; + mem_block_t *pdcp_pdu_p = NULL; + pdcp_pdu_p = get_free_mem_block(rrc_dl_sdu_len, __func__); + + //LOG_I(F1AP, "PRRCContainer size %lu:", ie->value.choice.RRCContainer.size); + //for (int i = 0; i < ie->value.choice.RRCContainer.size; i++) + // printf("%02x ", ie->value.choice.RRCContainer.buf[i]); + + //printf (", PDCP PDU size %d:", rrc_dl_sdu_len); + //for (int i=0;idata[i]); + //printf("\n"); + + if (pdcp_pdu_p != NULL) { + memset(pdcp_pdu_p->data, 0, rrc_dl_sdu_len); + memcpy(&pdcp_pdu_p->data[0], ie->value.choice.RRCContainer.buf, rrc_dl_sdu_len); + + /* for rfsim */ + du_rlc_data_req(&ctxt, 1, 0x00, 1, 1, 0, rrc_dl_sdu_len, pdcp_pdu_p); + // rlc_status = rlc_data_req(&ctxt + // , 1 + // , MBMS_FLAG_NO + // , srb_id + // , 0 + // , 0 + // , rrc_dl_sdu_len + // , pdcp_pdu_p + // ,NULL + // ,NULL + // ); + // switch (rlc_status) { + // case RLC_OP_STATUS_OK: + // //LOG_I(F1AP, "Data sending request over RLC succeeded!\n"); + // ret=TRUE; + // break; + + // case RLC_OP_STATUS_BAD_PARAMETER: + // LOG_W(F1AP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n"); + // ret= FALSE; + // break; + + // case RLC_OP_STATUS_INTERNAL_ERROR: + // LOG_W(F1AP, "Data sending request over RLC failed with 'Internal Error' reason!\n"); + // ret= FALSE; + // break; + + // case RLC_OP_STATUS_OUT_OF_RESSOURCES: + // LOG_W(F1AP, "Data sending request over RLC failed with 'Out of Resources' reason!\n"); + // ret= FALSE; + // break; + + // default: + // LOG_W(F1AP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status); + // ret= FALSE; + // break; + // } // switch case + // return ret; + } // if pdcp_pdu_p + + return 0; +} diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.h b/openair2/F1AP/f1ap_du_rrc_message_transfer.h index 1406e48f3d..3036c66d70 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.h +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.h @@ -42,12 +42,15 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, F1AP_F1AP_PDU_t *pdu); int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, const f1ap_ul_rrc_message_t *msg); +int DU_send_UL_NR_RRC_MESSAGE_TRANSFER(instance_t instance, const f1ap_ul_rrc_message_t *msg); int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, int CC_idP, int UE_id, rnti_t rntiP, const uint8_t *sduP, - sdu_size_t sdu_lenP); + sdu_size_t sdu_lenP, + const int8_t *sdu2P, + sdu_size_t sdu2_lenP); #endif /* F1AP_DU_RRC_MESSAGE_TRANSFER_H_ */ diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index 566391ac7a..50f7cdff80 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -50,7 +50,7 @@ void du_task_send_sctp_association_req(instance_t instance, f1ap_setup_req_t *f1 MessageDef *message_p = NULL; sctp_new_association_req_t *sctp_new_association_req_p = NULL; - message_p = itti_alloc_new_message(TASK_DU_F1, SCTP_NEW_ASSOCIATION_REQ); + message_p = itti_alloc_new_message(TASK_DU_F1, 0, SCTP_NEW_ASSOCIATION_REQ); sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; sctp_new_association_req_p->ulp_cnx_id = instance; @@ -86,9 +86,9 @@ void du_task_handle_sctp_association_resp(instance_t instance, sctp_new_associat DevAssert(sctp_new_association_resp != NULL); if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - LOG_W(F1AP, "Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", + LOG_E(F1AP, "Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", sctp_new_association_resp->sctp_state, - instance, + (int)instance, sctp_new_association_resp->ulp_cnx_id); //f1ap_handle_setup_message(instance, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); @@ -102,14 +102,19 @@ void du_task_handle_sctp_association_resp(instance_t instance, sctp_new_associat f1ap_du_data->default_sctp_stream_id = 0; /* setup parameters for F1U and start the server */ - const cudu_params_t params = { + const cudu_params_t params = (RC.nrrrc && RC.nrrrc[instance]->node_type == ngran_gNB_DU) ? (cudu_params_t){ + .local_ipv4_address = RC.nrmac[instance]->eth_params_n.my_addr, + .local_port = RC.nrmac[instance]->eth_params_n.my_portd, + .remote_ipv4_address = RC.nrmac[instance]->eth_params_n.remote_addr, + .remote_port = RC.nrmac[instance]->eth_params_n.remote_portd + } : (cudu_params_t){ .local_ipv4_address = RC.mac[instance]->eth_params_n.my_addr, .local_port = RC.mac[instance]->eth_params_n.my_portd, .remote_ipv4_address = RC.mac[instance]->eth_params_n.remote_addr, .remote_port = RC.mac[instance]->eth_params_n.remote_portd }; AssertFatal(proto_agent_start(instance, ¶ms) == 0, - "could not start PROTO_AGENT for F1U on instance %d!\n", instance); + "could not start PROTO_AGENT for F1U on instance %ld!\n", instance); DU_send_F1_SETUP_REQUEST(instance); } @@ -156,34 +161,58 @@ void *F1AP_DU_task(void *arg) { // 2. store the message in f1ap context, that is also stored in RC // 2. send a sctp_association req LOG_I(F1AP, "DU Task Received F1AP_SETUP_REQ\n"); - du_task_send_sctp_association_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + du_task_send_sctp_association_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_SETUP_REQ(received_msg)); break; + case F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE: + DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(received_msg)); + break; + case F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE: + DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(received_msg)); + break; case SCTP_NEW_ASSOCIATION_RESP: // 1. store the respon // 2. send the f1setup_req LOG_I(F1AP, "DU Task Received SCTP_NEW_ASSOCIATION_RESP\n"); - du_task_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + du_task_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_DATA_IND: // ex: any F1 incoming message for DU ends here LOG_I(F1AP, "DU Task Received SCTP_DATA_IND\n"); - du_task_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + du_task_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; + case F1AP_INITIAL_UL_RRC_MESSAGE: // to rrc + LOG_I(F1AP, "DU Task Received F1AP_INITIAL_UL_RRC_MESSAGE\n"); + + f1ap_initial_ul_rrc_message_t *msg = &F1AP_INITIAL_UL_RRC_MESSAGE(received_msg); + DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(0,0,0,msg->crnti, + msg->rrc_container, + msg->rrc_container_length, + (const int8_t*)msg->du2cu_rrc_container, + msg->du2cu_rrc_container_length); + break; + case F1AP_UL_RRC_MESSAGE: // to rrc LOG_I(F1AP, "DU Task Received F1AP_UL_RRC_MESSAGE\n"); - DU_send_UL_RRC_MESSAGE_TRANSFER(ITTI_MESSAGE_GET_INSTANCE(received_msg), - &F1AP_UL_RRC_MESSAGE(received_msg)); + if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_DU) { + DU_send_UL_NR_RRC_MESSAGE_TRANSFER(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &F1AP_UL_RRC_MESSAGE(received_msg)); + } else { + DU_send_UL_RRC_MESSAGE_TRANSFER(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &F1AP_UL_RRC_MESSAGE(received_msg)); + } break; case F1AP_UE_CONTEXT_RELEASE_REQ: // from MAC LOG_I(F1AP, "DU Task Received F1AP_UE_CONTEXT_RELEASE_REQ\n"); - DU_send_UE_CONTEXT_RELEASE_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg), + DU_send_UE_CONTEXT_RELEASE_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_UE_CONTEXT_RELEASE_REQ(received_msg)); break; diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index bae59a509e..131dbce8ef 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -38,13 +38,8 @@ #include "rrc_extern.h" #include "rrc_eNB_UE_context.h" - -// undefine C_RNTI from -// openair1/PHY/LTE_TRANSPORT/transport_common.h which -// replaces in ie->value.choice.C_RNTI, causing -// a compile error - -#undef C_RNTI +#include "openair2/RRC/NR/rrc_gNB_UE_context.h" +#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" extern f1ap_setup_req_t *f1ap_du_data; extern f1ap_cudu_inst_t f1ap_du_inst[MAX_eNB]; @@ -59,7 +54,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, F1AP_UEContextSetupRequestIEs_t *ie; int i; DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, F1AP_UE_CONTEXT_SETUP_REQ); + msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_REQ); f1ap_ue_context_setup_req_t *f1ap_ue_context_setup_req; f1ap_ue_context_setup_req = &F1AP_UE_CONTEXT_SETUP_REQ(msg_p); container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; @@ -91,7 +86,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, BIT_STRING_TO_NR_CELL_IDENTITY(&ie->value.choice.NRCGI.nRCellIdentity, f1ap_ue_context_setup_req->nr_cellid); /* ServCellIndex */ F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_ServCellndex, true); + F1AP_ProtocolIE_ID_id_ServCellIndex, true); f1ap_ue_context_setup_req->servCellIndex = ie->value.choice.ServCellIndex; /* optional */ /* CellULConfigured */ @@ -108,51 +103,82 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, f1ap_ue_context_setup_req->cellULConfigured = NULL; } - /* CUtoDURRCInformation */ - /* Candidate_SpCell_List */ - /* optional */ - /* DRXCycle */ - /* optional */ - /* ResourceCoordinationTransferContainer */ - /* SCell_ToBeSetup_List */ - /* SRBs_ToBeSetup_List */ - /* DRBs_ToBeSetup_List */ - /* Decode DRBs_ToBeSetup_List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List, true); - f1ap_ue_context_setup_req->drbs_to_be_setup_length = ie->value.choice.DRBs_ToBeSetup_List.list.count; - f1ap_ue_context_setup_req->drbs_to_be_setup = calloc(f1ap_ue_context_setup_req->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_req->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n"); + if (RC.nrrrc) { + /* RRCContainer */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_RRCContainer, false); + if (ie) { + /* correct here */ + f1ap_ue_context_setup_req->rrc_container = malloc(ie->value.choice.RRCContainer.size); + memcpy(f1ap_ue_context_setup_req->rrc_container, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size); + } else { + LOG_E(F1AP, "can't find RRCContainer in UEContextSetupRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer); + } - for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_req->drbs_to_be_setup[i]; - F1AP_DRBs_ToBeSetup_Item_t *drbs_tobesetup_item_p; - drbs_tobesetup_item_p = &((F1AP_DRBs_ToBeSetup_ItemIEs_t *)ie->value.choice.DRBs_ToBeSetup_List.list.array[i])->value.choice.DRBs_ToBeSetup_Item; - drb_p->drb_id = drbs_tobesetup_item_p->dRBID; - /* TODO in the following, assume only one UP UL TNL is present. - * this matches/assumes OAI CU implementation, can be up to 2! */ - drb_p->up_ul_tnl_length = 1; - AssertFatal(drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no UL UP TNL Information in DRBs to be Setup list\n"); - F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].gtp_teid); + // AssertFatal(0, "check configuration, send to appropriate handler\n"); - switch (drbs_tobesetup_item_p->rLCMode) { - case F1AP_RLCMode_rlc_am: - drb_p->rlc_mode = RLC_MODE_AM; - break; + protocol_ctxt_t ctxt; + // ctxt.rnti = f1ap_get_rnti_by_du_id(&f1ap_du_inst[instance], ie->value.choice.GNB_DU_UE_F1AP_ID); + ctxt.rnti = 0x1234; + ctxt.module_id = instance; + ctxt.instance = instance; + ctxt.enb_flag = 1; - default: - drb_p->rlc_mode = RLC_MODE_TM; - break; + mem_block_t *pdcp_pdu_p = NULL; + pdcp_pdu_p = get_free_mem_block(ie->value.choice.RRCContainer.size, __func__); + if (pdcp_pdu_p != NULL) { + memset(pdcp_pdu_p->data, 0, ie->value.choice.RRCContainer.size); + memcpy(&pdcp_pdu_p->data[0], ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size); + + /* for rfsim */ + du_rlc_data_req(&ctxt, 1, 0x00, 1, 1, 0, ie->value.choice.RRCContainer.size, pdcp_pdu_p); + } + } else { + /* CUtoDURRCInformation */ + /* Candidate_SpCell_List */ + /* optional */ + /* DRXCycle */ + /* optional */ + /* ResourceCoordinationTransferContainer */ + /* SCell_ToBeSetup_List */ + /* SRBs_ToBeSetup_List */ + /* DRBs_ToBeSetup_List */ + /* Decode DRBs_ToBeSetup_List */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ie, container, + F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List, true); + f1ap_ue_context_setup_req->drbs_to_be_setup_length = ie->value.choice.DRBs_ToBeSetup_List.list.count; + f1ap_ue_context_setup_req->drbs_to_be_setup = calloc(f1ap_ue_context_setup_req->drbs_to_be_setup_length, + sizeof(f1ap_drb_to_be_setup_t)); + AssertFatal(f1ap_ue_context_setup_req->drbs_to_be_setup, + "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n"); + + for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; ++i) { + f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_req->drbs_to_be_setup[i]; + F1AP_DRBs_ToBeSetup_Item_t *drbs_tobesetup_item_p; + drbs_tobesetup_item_p = &((F1AP_DRBs_ToBeSetup_ItemIEs_t *)ie->value.choice.DRBs_ToBeSetup_List.list.array[i])->value.choice.DRBs_ToBeSetup_Item; + drb_p->drb_id = drbs_tobesetup_item_p->dRBID; + /* TODO in the following, assume only one UP UL TNL is present. + * this matches/assumes OAI CU implementation, can be up to 2! */ + drb_p->up_ul_tnl_length = 1; + AssertFatal(drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0, + "no UL UP TNL Information in DRBs to be Setup list\n"); + F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; + F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); + OCTET_STRING_TO_INT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].gtp_teid); + + switch (drbs_tobesetup_item_p->rLCMode) { + case F1AP_RLCMode_rlc_am: + drb_p->rlc_mode = RLC_MODE_AM; + break; + + default: + drb_p->rlc_mode = RLC_MODE_TM; + break; + } } } - AssertFatal(0, "check configuration, send to appropriate handler\n"); return 0; } @@ -227,7 +253,8 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(instance_t instance) { ie->id = F1AP_ProtocolIE_ID_id_C_RNTI; ie->criticality = F1AP_Criticality_ignore; ie->value.present = F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI; - C_RNTI_TO_BIT_STRING(rntiP, &ie->value.choice.C_RNTI); + //C_RNTI_TO_BIT_STRING(rntiP, &ie->value.choice.C_RNTI); + ie->value.choice.C_RNTI=rntiP; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); } @@ -510,7 +537,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(instance_t instance) { /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP RESPONSE\n"); return -1; } @@ -632,11 +659,21 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, rnti, ctxt.rnti); int UE_out_of_sync = 0; - for (int n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[instance]->UE_info.active[n] == TRUE - && rnti == UE_RNTI(instance, n)) { - UE_out_of_sync = RC.mac[instance]->UE_info.UE_sched_ctrl[n].ul_out_of_sync; - break; + if (RC.nrrrc[instance]->node_type == ngran_gNB_DU) { + for (int n = 0; n < MAX_MOBILES_PER_GNB; ++n) { + if (RC.nrmac[instance]->UE_info.active[n] == TRUE + && rnti == RC.nrmac[instance]->UE_info.rnti[n]) { + UE_out_of_sync = 0; + break; + } + } + } else { + for (int n = 0; n < MAX_MOBILES_PER_ENB; ++n) { + if (RC.mac[instance]->UE_info.active[n] == TRUE + && rnti == UE_RNTI(instance, n)) { + UE_out_of_sync = RC.mac[instance]->UE_info.UE_sched_ctrl[n].ul_out_of_sync; + break; + } } } @@ -686,6 +723,15 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, } } + if (RC.nrrrc[instance]->node_type == ngran_gNB_DU) { + // struct rrc_gNB_ue_context_s *ue_context_p; + + f1ap_ue_context_release_cplt_t cplt; + cplt.rnti = ctxt.rnti; + DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance, &cplt); + return 0; + } + struct rrc_eNB_ue_context_s *ue_context_p; ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ctxt.module_id], ctxt.rnti); @@ -1016,7 +1062,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { srbs_failedToBeSetupMod_item.sRBID = 50L; srbs_failedToBeSetupMod_item.cause = (F1AP_Cause_t *)calloc(1, sizeof(F1AP_Cause_t)); srbs_failedToBeSetupMod_item.cause->present = F1AP_Cause_PR_radioNetwork; - srbs_failedToBeSetupMod_item.cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnd_du_ue_f1ap_id; + srbs_failedToBeSetupMod_item.cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; /* ADD */ srbs_failedToBeSetupMod_item_ies->value.choice.SRBs_FailedToBeSetupMod_Item = srbs_failedToBeSetupMod_item; ASN_SEQUENCE_ADD(&ie->value.choice.SRBs_FailedToBeSetupMod_List.list, @@ -1047,7 +1093,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { drbs_failedToBeSetupMod_item.dRBID = 30L; drbs_failedToBeSetupMod_item.cause = (F1AP_Cause_t *)calloc(1, sizeof(F1AP_Cause_t)); drbs_failedToBeSetupMod_item.cause->present = F1AP_Cause_PR_radioNetwork; - drbs_failedToBeSetupMod_item.cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnd_du_ue_f1ap_id; + drbs_failedToBeSetupMod_item.cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; /* ADD */ drbs_failedToBeSetupMod_item_ies->value.choice.DRBs_FailedToBeSetupMod_Item = drbs_failedToBeSetupMod_item; ASN_SEQUENCE_ADD(&ie->value.choice.DRBs_FailedToBeSetupMod_List.list, @@ -1083,7 +1129,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { scell_failedtoSetupMod_item.sCell_ID = nRCGI; scell_failedtoSetupMod_item.cause = (F1AP_Cause_t *)calloc(1, sizeof(F1AP_Cause_t)); scell_failedtoSetupMod_item.cause->present = F1AP_Cause_PR_radioNetwork; - scell_failedtoSetupMod_item.cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnd_du_ue_f1ap_id; + scell_failedtoSetupMod_item.cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; /* ADD */ scell_failedtoSetupMod_item_ies->value.choice.SCell_FailedtoSetupMod_Item = scell_failedtoSetupMod_item; ASN_SEQUENCE_ADD(&ie->value.choice.SCell_FailedtoSetupMod_List.list, @@ -1114,7 +1160,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { drbs_failedToBeModified_item.dRBID = 30L; drbs_failedToBeModified_item.cause = (F1AP_Cause_t *)calloc(1, sizeof(F1AP_Cause_t)); drbs_failedToBeModified_item.cause->present = F1AP_Cause_PR_radioNetwork; - drbs_failedToBeModified_item.cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnd_du_ue_f1ap_id; + drbs_failedToBeModified_item.cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; /* ADD */ drbs_failedToBeModified_item_ies->value.choice.DRBs_FailedToBeModified_Item = drbs_failedToBeModified_item; ASN_SEQUENCE_ADD(&ie->value.choice.DRBs_FailedToBeModified_List.list, @@ -1180,7 +1226,7 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { /* encode */ if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 setup request\n"); + LOG_E(F1AP, "Failed to encode F1 UE CONTEXT MODIFICATION RESPONSE\n"); return -1; } diff --git a/openair2/F1AP/f1ap_encoder.c b/openair2/F1AP/f1ap_encoder.c index e448690139..6e5f0f4e49 100644 --- a/openair2/F1AP/f1ap_encoder.c +++ b/openair2/F1AP/f1ap_encoder.c @@ -84,12 +84,8 @@ int f1ap_encode_pdu(F1AP_F1AP_PDU_t *pdu, uint8_t **buffer, uint32_t *length) LOG_E(F1AP, "----------------- ASN1 ENCODER PRINT END----------------- \n"); } - encoded = aper_encode_to_new_buffer(&asn_DEF_F1AP_F1AP_PDU, 0, pdu, (void **)buffer); - - if (encoded < 0) { - LOG_E(F1AP, "Failed to encode F1AP message\n"); - return -1; - } + AssertFatal((encoded = aper_encode_to_new_buffer(&asn_DEF_F1AP_F1AP_PDU, 0, pdu, (void **)buffer))>0, + "Failed to encode F1AP message\n"); *length = encoded; diff --git a/openair2/F1AP/f1ap_handlers.c b/openair2/F1AP/f1ap_handlers.c index 12aba18a9d..5aca059ae4 100644 --- a/openair2/F1AP/f1ap_handlers.c +++ b/openair2/F1AP/f1ap_handlers.c @@ -50,7 +50,7 @@ f1ap_message_decoded_callback f1ap_messages_callback[][3] = { { CU_handle_F1_SETUP_REQUEST, DU_handle_F1_SETUP_RESPONSE, DU_handle_F1_SETUP_FAILURE }, /* F1Setup */ { 0, 0, 0 }, /* ErrorIndication */ { 0, 0, 0 }, /* gNBDUConfigurationUpdate */ - { 0, 0, 0 }, /* gNBCUConfigurationUpdate */ + { DU_handle_gNB_CU_CONFIGURATION_UPDATE, CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE, CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE }, /* gNBCUConfigurationUpdate */ { DU_handle_UE_CONTEXT_SETUP_REQUEST, CU_handle_UE_CONTEXT_SETUP_RESPONSE, 0 }, /* UEContextSetup */ { DU_handle_UE_CONTEXT_RELEASE_COMMAND, CU_handle_UE_CONTEXT_RELEASE_COMPLETE, 0 }, /* UEContextRelease */ { 0, 0, 0 }, /* UEContextModification */ @@ -119,7 +119,7 @@ int f1ap_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream, } /* Calling the right handler */ - LOG_I(F1AP, "Calling handler with instance %d\n",instance); + LOG_I(F1AP, "Calling handler with instance %ld\n",instance); ret = (*f1ap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1]) (instance, assoc_id, stream, &pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_F1AP_F1AP_PDU, &pdu); diff --git a/openair2/F1AP/f1ap_itti_messaging.c b/openair2/F1AP/f1ap_itti_messaging.c index fa8951536a..443357a45e 100644 --- a/openair2/F1AP/f1ap_itti_messaging.c +++ b/openair2/F1AP/f1ap_itti_messaging.c @@ -28,7 +28,7 @@ void cu_f1ap_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint MessageDef *message_p; sctp_data_req_t *sctp_data_req; - message_p = itti_alloc_new_message(TASK_CU_F1, SCTP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_CU_F1, 0, SCTP_DATA_REQ); sctp_data_req = &message_p->ittiMsg.sctp_data_req; @@ -46,7 +46,7 @@ void du_f1ap_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint MessageDef *message_p; sctp_data_req_t *sctp_data_req; - message_p = itti_alloc_new_message(TASK_DU_F1, SCTP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_DU_F1, 0, SCTP_DATA_REQ); sctp_data_req = &message_p->ittiMsg.sctp_data_req; @@ -64,7 +64,7 @@ void f1ap_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id MessageDef *message_p = NULL; sctp_close_association_t *sctp_close_association_p = NULL; - message_p = itti_alloc_new_message(TASK_S1AP, SCTP_CLOSE_ASSOCIATION); + message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_CLOSE_ASSOCIATION); sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; sctp_close_association_p->assoc_id = assoc_id; diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h index a5a808c281..0306713845 100644 --- a/openair2/GNB_APP/L1_nr_paramdef.h +++ b/openair2/GNB_APP/L1_nr_paramdef.h @@ -46,7 +46,11 @@ #define CONFIG_STRING_L1_LOCAL_N_PORTD "local_n_portd" #define CONFIG_STRING_L1_REMOTE_N_PORTD "remote_n_portd" #define CONFIG_STRING_L1_TRANSPORT_N_PREFERENCE "tr_n_preference" - +#define CONFIG_STRING_L1_PUSCH_PROC_THREADS "pusch_proc_threads" +#define CONFIG_STRING_L1_OFDM_OFFSET_DIVISOR "ofdm_offset_divisor" +#define CONFIG_STRING_L1_PUCCH0_DTX_THRESHOLD "pucch0_dtx_threshold" +#define CONFIG_STRING_L1_PRACH_DTX_THRESHOLD "prach_dtx_threshold" +#define CONFIG_STRING_L1_PUSCH_DTX_THRESHOLD "pusch_dtx_threshold" /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ /* L1 configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -61,6 +65,11 @@ {CONFIG_STRING_L1_REMOTE_N_PORTC, NULL, 0, uptr:NULL, defintval:50030, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_LOCAL_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_REMOTE_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ +{CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:3, TYPE_UINT, 0}, \ +{CONFIG_STRING_L1_OFDM_OFFSET_DIVISOR, NULL, 0, uptr:NULL, defuintval:8, TYPE_UINT, 0}, \ +{CONFIG_STRING_L1_PUCCH0_DTX_THRESHOLD, NULL, 0, uptr:NULL, defintval:100, TYPE_UINT, 0}, \ +{CONFIG_STRING_L1_PRACH_DTX_THRESHOLD, NULL, 0, uptr:NULL, defintval:150, TYPE_UINT, 0}, \ +{CONFIG_STRING_L1_PUSCH_DTX_THRESHOLD, NULL, 0, uptr:NULL, defintval:50, TYPE_UINT, 0} \ } #define L1_CC_IDX 0 #define L1_TRANSPORT_N_PREFERENCE_IDX 1 @@ -71,6 +80,11 @@ #define L1_REMOTE_N_PORTC_IDX 6 #define L1_LOCAL_N_PORTD_IDX 7 #define L1_REMOTE_N_PORTD_IDX 8 +#define L1_PUSCH_PROC_THREADS 9 +#define L1_OFDM_OFFSET_DIVISOR 10 +#define L1_PUCCH0_DTX_THRESHOLD 11 +#define L1_PRACH_DTX_THRESHOLD 12 +#define L1_PUSCH_DTX_THRESHOLD 13 /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index 308af2eeb9..b17fced7b7 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -55,6 +55,15 @@ #define CONFIG_STRING_MACRLC_REMOTE_S_PORTC "remote_s_portc" #define CONFIG_STRING_MACRLC_LOCAL_S_PORTD "local_s_portd" #define CONFIG_STRING_MACRLC_REMOTE_S_PORTD "remote_s_portd" +#define CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY "ulsch_max_frame_inactivity" +#define CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10 "pusch_TargetSNRx10" +#define CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10 "pucch_TargetSNRx10" +#define CONFIG_STRING_MACRLC_PUCCHFAILURETHRES "pucch_FailureThres" +#define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres" +#define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper" +#define CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER "dl_bler_target_lower" +#define CONFIG_STRING_MACRLC_DL_RD2_BLER_THRESHOLD "dl_rd2_bler_threshold" +#define CONFIG_STRING_MACRLC_DL_MAX_MCS "dl_max_mcs" /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ @@ -79,6 +88,15 @@ {CONFIG_STRING_MACRLC_REMOTE_S_PORTC, NULL, 0, uptr:NULL, defintval:50020, TYPE_UINT, 0}, \ {CONFIG_STRING_MACRLC_LOCAL_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \ {CONFIG_STRING_MACRLC_REMOTE_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \ +{CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY, NULL, 0, uptr:NULL, defintval:10, TYPE_UINT, 0}, \ +{CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:150, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_PUCCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, "Upper threshold of BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.15, TYPE_DOUBLE, 0}, \ +{CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER, "Lower threshold of BLER to increase DL MCS", 0, dblptr:NULL, defdblval:0.05, TYPE_DOUBLE, 0}, \ +{CONFIG_STRING_MACRLC_DL_RD2_BLER_THRESHOLD, "Threshold of RD2/RETX2 BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.01, TYPE_DOUBLE, 0}, \ +{CONFIG_STRING_MACRLC_DL_MAX_MCS, "Maximum DL MCS that should be used", 0, u8ptr:NULL, defintval:28, TYPE_UINT8, 0}, \ } #define MACRLC_CC_IDX 0 #define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1 @@ -97,5 +115,15 @@ #define MACRLC_REMOTE_S_PORTC_IDX 14 #define MACRLC_LOCAL_S_PORTD_IDX 15 #define MACRLC_REMOTE_S_PORTD_IDX 16 +#define MACRLC_ULSCH_MAX_FRAME_INACTIVITY 17 +#define MACRLC_PUSCHTARGETSNRX10_IDX 18 +#define MACRLC_PUCCHTARGETSNRX10_IDX 19 +#define MACRLC_PUCCHFAILURETHRES_IDX 20 +#define MACRLC_PUSCHFAILURETHRES_IDX 21 +#define MACRLC_DL_BLER_TARGET_UPPER_IDX 22 +#define MACRLC_DL_BLER_TARGET_LOWER_IDX 23 +#define MACRLC_DL_RD2_BLER_THRESHOLD_IDX 24 +#define MACRLC_DL_MAX_MCS_IDX 25 + /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index bc4c4cf9d9..8a7ce64d91 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -38,8 +38,8 @@ /* cell configuration section name */ #define GNB_CONFIG_STRING_GNB_LIST "gNBs" -#define GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET "ssb_SubcarrierOffset" -#define GNB_CONFIG_STRING_PDSCHANTENNAPORTS "pdsch_AntennaPorts" + +#define GNB_CONFIG_STRING_PDCCH_CONFIGSIB1 "pdcch_ConfigSIB1" #define GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON "servingCellConfigCommon" #define GNB_CONFIG_STRING_PHYSCELLID "physCellId" #define GNB_CONFIG_STRING_NTIMINGADVANCEOFFSET "n_TimingAdvanceOffset" @@ -58,56 +58,6 @@ #define GNB_CONFIG_STRING_INITIALDLBWPCONTROLRESOURCESETZERO "initialDLBWPcontrolResourceSetZero" #define GNB_CONFIG_STRING_INITIALDLBWPSEARCHSPACEZERO "initialDLBWPsearchSpaceZero" - -#define GNB_CONFIG_STRING_INITIALDLBWPK0_0 "initialDLBWPk0_0" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_0 "initialDLBWPmappingType_0" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_0 "initialDLBWPstartSymbolAndLength_0" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_1 "initialDLBWPk0_1" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_1 "initialDLBWPmappingType_1" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_1 "initialDLBWPstartSymbolAndLength_1" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_2 "initialDLBWPk0_2" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_2 "initialDLBWPmappingType_2" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_2 "initialDLBWPstartSymbolAndLength_2" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_3 "initialDLBWPk0_3" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_3 "initialDLBWPmappingType_3" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_3 "initialDLBWPstartSymbolAndLength_3" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_4 "initialDLBWPk0_4" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_4 "initialDLBWPmappingType_4" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_4 "initialDLBWPstartSymbolAndLength_4" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_5 "initialDLBWPk0_5" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_5 "initialDLBWPmappingType_5" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_5 "initialDLBWPstartSymbolAndLength_5" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_6 "initialDLBWPk0_6" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_6 "initialDLBWPmappingType_6" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_6 "initialDLBWPstartSymbolAndLength_6" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_7 "initialDLBWPk0_7" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_7 "initialDLBWPmappingType_7" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_7 "initialDLBWPstartSymbolAndLength_7" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_8 "initialDLBWPk0_8" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_8 "initialDLBWPmappingType_8" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_8 "initialDLBWPstartSymbolAndLength_8" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_9 "initialDLBWPk0_9" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_9 "initialDLBWPmappingType_9" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_9 "initialDLBWPstartSymbolAndLength_9" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_10 "initialDLBWPk0_10" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_10 "initialDLBWPmappingType_10" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_10 "initialDLBWPstartSymbolAndLength_10" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_11 "initialDLBWPk0_11" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_11 "initialDLBWPmappingType_11" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_11 "initialDLBWPstartSymbolAndLength_11" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_12 "initialDLBWPk0_12" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_12 "initialDLBWPmappingType_12" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_12 "initialDLBWPstartSymbolAndLength_12" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_13 "initialDLBWPk0_13" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_13 "initialDLBWPmappingType_13" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_13 "initialDLBWPstartSymbolAndLength_13" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_14 "initialDLBWPk0_14" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_14 "initialDLBWPmappingType_14" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_14 "initialDLBWPstartSymbolAndLength_14" -#define GNB_CONFIG_STRING_INITIALDLBWPK0_15 "initialDLBWPk0_15" -#define GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_15 "initialDLBWPmappingType_15" -#define GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_15 "initialDLBWPstartSymbolAndLength_15" - #define GNB_CONFIG_STRING_ULFREQUENCYBAND "ul_frequencyBand" #define GNB_CONFIG_STRING_ULABSOLUEFREQUENCYPOINTA "ul_absoluteFrequencyPointA" #define GNB_CONFIG_STRING_ULOFFSETTOCARRIER "ul_offstToCarrier" @@ -141,54 +91,7 @@ #define GNB_CONFIG_STRING_PUCCHGROUPHOPPING "pucchGroupHopping" #define GNB_CONFIG_STRING_HOPPINGID "hoppingId" #define GNB_CONFIG_STRING_P0NOMINAL "p0_nominal" -#define GNB_CONFIG_STRING_INITIALULBWPK2_0 "initialULBWPk2_0" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_0 "initialULBWPmappingType_0" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_0 "initialULBWPstartSymbolAndLength_0" -#define GNB_CONFIG_STRING_INITIALULBWPK2_1 "initialULBWPk2_1" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_1 "initialULBWPmappingType_1" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_1 "initialULBWPstartSymbolAndLength_1" -#define GNB_CONFIG_STRING_INITIALULBWPK2_2 "initialULBWPk2_2" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_2 "initialULBWPmappingType_2" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_2 "initialULBWPstartSymbolAndLength_2" -#define GNB_CONFIG_STRING_INITIALULBWPK2_3 "initialULBWPk2_3" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_3 "initialULBWPmappingType_3" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_3 "initialULBWPstartSymbolAndLength_3" -#define GNB_CONFIG_STRING_INITIALULBWPK2_4 "initialULBWPk2_4" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_4 "initialULBWPmappingType_4" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_4 "initialULBWPstartSymbolAndLength_4" -#define GNB_CONFIG_STRING_INITIALULBWPK2_5 "initialULBWPk2_5" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_5 "initialULBWPmappingType_5" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_5 "initialULBWPstartSymbolAndLength_5" -#define GNB_CONFIG_STRING_INITIALULBWPK2_6 "initialULBWPk2_6" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_6 "initialULBWPmappingType_6" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_6 "initialULBWPstartSymbolAndLength_6" -#define GNB_CONFIG_STRING_INITIALULBWPK2_7 "initialULBWPk2_7" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_7 "initialULBWPmappingType_7" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_7 "initialULBWPstartSymbolAndLength_7" -#define GNB_CONFIG_STRING_INITIALULBWPK2_8 "initialULBWPk2_8" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_8 "initialULBWPmappingType_8" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_8 "initialULBWPstartSymbolAndLength_8" -#define GNB_CONFIG_STRING_INITIALULBWPK2_9 "initialULBWPk2_9" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_9 "initialULBWPmappingType_9" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_9 "initialULBWPstartSymbolAndLength_9" -#define GNB_CONFIG_STRING_INITIALULBWPK2_10 "initialULBWPk2_10" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_10 "initialULBWPmappingType_10" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_10 "initialULBWPstartSymbolAndLength_10" -#define GNB_CONFIG_STRING_INITIALULBWPK2_11 "initialULBWPk2_11" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_11 "initialULBWPmappingType_11" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_11 "initialULBWPstartSymbolAndLength_11" -#define GNB_CONFIG_STRING_INITIALULBWPK2_12 "initialULBWPk2_12" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_12 "initialULBWPmappingType_12" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_12 "initialULBWPstartSymbolAndLength_12" -#define GNB_CONFIG_STRING_INITIALULBWPK2_13 "initialULBWPk2_13" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_13 "initialULBWPmappingType_13" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_13 "initialULBWPstartSymbolAndLength_13" -#define GNB_CONFIG_STRING_INITIALULBWPK2_14 "initialULBWPk2_14" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_14 "initialULBWPmappingType_14" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_14 "initialULBWPstartSymbolAndLength_14" -#define GNB_CONFIG_STRING_INITIALULBWPK2_15 "initialULBWPk2_15" -#define GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_15 "initialULBWPmappingType_15" -#define GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_15 "initialULBWPstartSymbolAndLength_15" +#define GNB_CONFIG_STRING_PUCCHRES "pucch_ResourceCommon" #define GNB_CONFIG_STRING_SSBPOSITIONSINBURSTPR "ssb_PositionsInBurst_PR" @@ -211,6 +114,39 @@ #define CARRIERBANDWIDTH_OKVALUES {11,18,24,25,31,32,38,51,52,65,66,78,79,93,106,107,121,132,133,135,160,162,189,216,217,245,264,270,273} +/* Serving Cell Config Dedicated */ +#define GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED "servingCellConfigDedicated" +#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0 "dl_ptrsFreqDensity0_0" +#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0 "dl_ptrsFreqDensity1_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0 "dl_ptrsTimeDensity0_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0 "dl_ptrsTimeDensity1_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0 "dl_ptrsTimeDensity2_0" +#define GNB_CONFIG_STRING_DLPTRSEPRERATIO_0 "dl_ptrsEpreRatio_0" +#define GNB_CONFIG_STRING_DLPTRSREOFFSET_0 "dl_ptrsReOffset_0" +#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0 "ul_ptrsFreqDensity0_0" +#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0 "ul_ptrsFreqDensity1_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0 "ul_ptrsTimeDensity0_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0 "ul_ptrsTimeDensity1_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0 "ul_ptrsTimeDensity2_0" +#define GNB_CONFIG_STRING_ULPTRSREOFFSET_0 "ul_ptrsReOffset_0" +#define GNB_CONFIG_STRING_ULPTRSMAXPORTS_0 "ul_ptrsMaxPorts_0" +#define GNB_CONFIG_STRING_ULPTRSPOWER_0 "ul_ptrsPower_0" + +/*--------------------------------------------------------------------------------------------------------------------*/ +/* pdcch_ConfigSIB1 parameters */ +/*--------------------------------------------------------------------------------------------------------------------*/ +#define CONTROL_RESOURCE_SET_ZERO "controlResourceSetZero" +#define SEARCH_SPACE_ZERO "searchSpaceZero" + +#define PDCCH_CONFIGSIB1PARAMS_DESC(pdcch_ConfigSIB1) { \ +{CONTROL_RESOURCE_SET_ZERO, NULL, 0, i64ptr:&pdcch_ConfigSIB1->controlResourceSetZero, defintval:0, TYPE_INT64, 0}, \ +{SEARCH_SPACE_ZERO, NULL, 0, i64ptr:&pdcch_ConfigSIB1->searchSpaceZero, defintval:0, TYPE_INT64, 0} \ +} + +#define CONTROL_RESOURCE_SET_ZERO_IDX 0 +#define SEARCH_SPACE_ZERO_IDX 1 +/*--------------------------------------------------------------------------------------------------------------------*/ + /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Serving Cell Config Common configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -223,9 +159,6 @@ #define GNB_CONFIG_DLCARRIERBANDWIDTH_IDX 10 -#define SSBPARAMS_DESC {{GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET,NULL,0,iptr:&ssb_SubcarrierOffset,defintval:0,TYPE_INT,0}} -#define PDSCHANTENNAPARAMS_DESC {{GNB_CONFIG_STRING_PDSCHANTENNAPORTS,NULL,0,iptr:&pdsch_AntennaPorts,defintval:1,TYPE_INT,0}} - #define SCCPARAMS_DESC(scc) { \ {GNB_CONFIG_STRING_PHYSCELLID,NULL,0,i64ptr:scc->physCellId,defint64val:0,TYPE_INT64,0/*0*/}, \ {GNB_CONFIG_STRING_NTIMINGADVANCEOFFSET,NULL,0,i64ptr:scc->n_TimingAdvanceOffset,defint64val:NR_ServingCellConfigCommon__n_TimingAdvanceOffset_n0,TYPE_INT64,0/*1*/},\ @@ -242,54 +175,6 @@ {GNB_CONFIG_STRING_INITIALDLBWPSUBCARRIERSPACING,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing,defint64val:NR_SubcarrierSpacing_kHz30,TYPE_INT64,0/*12*/},\ {GNB_CONFIG_STRING_INITIALDLBWPCONTROLRESOURCESETZERO,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero,defint64val:12,TYPE_INT64,0/*13*/},\ {GNB_CONFIG_STRING_INITIALDLBWPSEARCHSPACEZERO,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero,defint64val:0,TYPE_INT64,0/*14*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_0,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[0]->k0,defint64val:-1,TYPE_INT64,0/*15*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_0,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[0]->mappingType,defint64val:-1,TYPE_INT64,0/*16*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_0,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[0]->startSymbolAndLength,defint64val:-1,TYPE_INT64,0/*17*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_1,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[1]->k0,defint64val:-1,TYPE_INT64,0/*18*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_1,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[1]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*19*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_1,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[1]->startSymbolAndLength,defint64val:53,TYPE_INT64,0/*20*/}, \ -{GNB_CONFIG_STRING_INITIALDLBWPK0_2,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[2]->k0,defint64val:-1,TYPE_INT64,0/*21*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_2,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[2]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*22*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_2,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[2]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*23*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_3,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[3]->k0,defint64val:-1,TYPE_INT64,0/*24*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_3,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[3]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*25*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_3,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[3]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*26*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_4,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[4]->k0,defint64val:-1,TYPE_INT64,0/*27*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_4,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[4]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*28*/}, \ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_4,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[4]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*29*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_5,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[5]->k0,defint64val:-1,TYPE_INT64,0/*30*/}, \ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_5,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[5]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*31*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_5,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[5]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*32*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_6,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[6]->k0,defint64val:-1,TYPE_INT64,0/*33*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_6,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[6]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*34*/}, \ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_6,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[6]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*35*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_7,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[7]->k0,defint64val:-1,TYPE_INT64,0/*36*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_7,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[7]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*37*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_7,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[7]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*38*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_8,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[8]->k0,defint64val:-1,TYPE_INT64,0/*39*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_8,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[8]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*40*/}, \ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_8,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[8]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*41*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_9,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[9]->k0,defint64val:-1,TYPE_INT64,0/*42*/}, \ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_9,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[9]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*43*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_9,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[9]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*44*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_10,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[10]->k0,defint64val:-1,TYPE_INT64,0/*45*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_10,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[10]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*46*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_10,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[10]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*47*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_11,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[11]->k0,defint64val:-1,TYPE_INT64,0/*48*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_11,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[11]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*49*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_11,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[11]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*50*/}, \ -{GNB_CONFIG_STRING_INITIALDLBWPK0_12,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[12]->k0,defint64val:-1,TYPE_INT64,0/*51*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_12,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[12]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*52*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_12,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[12]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*53*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_13,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[13]->k0,defint64val:-1,TYPE_INT64,0/*54*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_13,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[13]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*55*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_13,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[13]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*56*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_14,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[14]->k0,defint64val:-1,TYPE_INT64,0/*57*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_14,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[14]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*58*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_14,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[14]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*59*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPK0_15,NULL,0,i64ptr:scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[15]->k0,defint64val:-1,TYPE_INT64,0/*60*/}, \ -{GNB_CONFIG_STRING_INITIALDLBWPMAPPINGTYPE_15,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[15]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA,TYPE_INT64,0/*61*/},\ -{GNB_CONFIG_STRING_INITIALDLBWPSTARTSYMBOLANDLENGTH_15,NULL,0,i64ptr:&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[15]->startSymbolAndLength,defint64val:54,TYPE_INT64,0/*62*/},\ {GNB_CONFIG_STRING_ULFREQUENCYBAND,NULL,0,i64ptr:scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0],defint64val:-1,TYPE_INT64,0/*63*/},\ {GNB_CONFIG_STRING_ULABSOLUEFREQUENCYPOINTA,NULL,0,i64ptr:scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA,defint64val:-1,TYPE_INT64,0/*64*/},\ {GNB_CONFIG_STRING_ULOFFSETTOCARRIER,NULL,0,i64ptr:&scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier,defint64val:0,TYPE_INT64,0/*65*/},\ @@ -314,59 +199,12 @@ {GNB_CONFIG_STRING_PRACHROOTSEQUENCEINDEX,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139,defint64val:0,TYPE_INT64,0/*84*/},\ {GNB_CONFIG_STRING_RESTRICTEDSETCONFIG,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig,defintval:NR_RACH_ConfigCommon__restrictedSetConfig_unrestrictedSet,TYPE_INT64,0/*85*/}, \ {GNB_CONFIG_STRING_MSG3TRANSFPREC,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder,defintval:1,TYPE_INT64,0/*86*/}, \ -{GNB_CONFIG_STRING_INITIALULBWPK2_0,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[0]->k2,defint64val:-1,TYPE_INT64,0/*87*/},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_0,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[0]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,/*88*/},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_0,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[0]->startSymbolAndLength,defint64val:55,TYPE_INT64,0/*89*/},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_1,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[1]->k2,defint64val:-1,TYPE_INT64,0/*90*/}, \ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_1,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[1]->mappingType,defint64val:NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_1,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[1]->startSymbolAndLength,defint64val:53,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_2,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[2]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_2,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[2]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_2,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[2]->startSymbolAndLength,defint64val:55,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_3,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[3]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_3,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[3]->mappingType,defint64val:NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_3,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[3]->startSymbolAndLength,defint64val:53,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_4,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[4]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_4,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[4]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0 /*100*/}, \ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_4,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[4]->startSymbolAndLength,defint64val:55,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_5,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[5]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_5,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[5]->mappingType,defint64val:NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_5,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[5]->startSymbolAndLength,defint64val:53,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_6,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[6]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_6,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[6]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_6,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[6]->startSymbolAndLength,defint64val:55,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_7,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[7]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_7,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[7]->mappingType,defint64val:NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_7,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[7]->startSymbolAndLength,defint64val:53,TYPE_INT64,0/*110*/}, \ -{GNB_CONFIG_STRING_INITIALULBWPK2_8,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[8]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_8,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[8]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_8,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[8]->startSymbolAndLength,defint64val:55,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_9,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[9]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_9,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[9]->mappingType,defint64val:NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_9,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[9]->startSymbolAndLength,defint64val:53,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_10,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[10]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_10,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[10]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_10,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[10]->startSymbolAndLength,defint64val:55,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_11,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[11]->k2,defint64val:-1,TYPE_INT64,0/*120*/}, \ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_11,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[11]->mappingType,defint64val:NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_11,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[11]->startSymbolAndLength,defint64val:53,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_12,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[12]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_12,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[12]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_12,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[12]->startSymbolAndLength,defint64val:55,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_13,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[13]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_13,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[13]->mappingType,defint64val:NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_13,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[13]->startSymbolAndLength,defint64val:53,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_14,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[14]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_14,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[14]->mappingType,defint64val:NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0 /*130*/}, \ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_14,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[14]->startSymbolAndLength,defint64val:55,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPK2_15,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[15]->k2,defint64val:-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPMAPPINGTYPE_15,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[15]->mappingType,defint64val:NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_INITIALULBWPSTARTSYMBOLANDLENGTH_15,NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[15]->startSymbolAndLength,defint64val:53,TYPE_INT64,0},\ {GNB_CONFIG_STRING_MSG3DELTAPREABMLE, NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble,defint64val:1,TYPE_INT64,0},\ {GNB_CONFIG_STRING_P0NOMINALWITHGRANT, NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant,defint64val:1,TYPE_INT64,0},\ {GNB_CONFIG_STRING_PUCCHGROUPHOPPING, NULL,0,i64ptr:&scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_GroupHopping,defint64val:NR_PUCCH_ConfigCommon__pucch_GroupHopping_neither,TYPE_INT64,0},\ {GNB_CONFIG_STRING_HOPPINGID, NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId,defint64val:40,TYPE_INT64,0},\ {GNB_CONFIG_STRING_P0NOMINAL, NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal,defint64val:1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_PUCCHRES, NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon,defint64val:0,TYPE_INT64,0},\ {GNB_CONFIG_STRING_SSBPOSITIONSINBURSTPR,NULL,0,uptr:&scc->ssb_PositionsInBurst->present,defuintval:NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap,TYPE_UINT,0/*140*/}, \ {GNB_CONFIG_STRING_SSBPOSITIONSINBURST,NULL,0,u64ptr:&ssb_bitmap,defintval:0xff,TYPE_UINT64,0}, \ {GNB_CONFIG_STRING_REFERENCESUBCARRIERSPACING,NULL,0,i64ptr:&scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing,defint64val:NR_SubcarrierSpacing_kHz30,TYPE_INT64,0},\ @@ -383,6 +221,26 @@ {GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,i64ptr:&scc->ss_PBCH_BlockPower,defint64val:20,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,defintval:-1,TYPE_INT64,0}} +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* Serving Cell Config Dedicated configuration parameters */ +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +#define SCDPARAMS_DESC(scd) { \ +{GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[2],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSEPRERATIO_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio,defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSREOFFSET_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset,defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[2],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSREOFFSET_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset,defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSMAXPORTS_0,NULL,0,i64ptr:&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->maxNrofPorts,defint64val:0,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSPOWER_0,NULL,0,i64ptr:&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->ptrs_Power,defint64val:0,TYPE_INT64,0}} diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 9bdd709262..5104021399 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -29,6 +29,10 @@ #include #include +#include +#include +#include +#include #include "gnb_app.h" #include "gnb_config.h" @@ -39,11 +43,14 @@ #include "x2ap_eNB.h" #include "intertask_interface.h" -#include "s1ap_eNB.h" +#include "ngap_gNB.h" #include "sctp_eNB_task.h" #include "gtpv1u_eNB_task.h" #include "PHY/INIT/phy_init.h" - +#include "f1ap_cu_task.h" +#include "f1ap_du_task.h" +#include "nfapi/oai_integration/vendor_ext.h" +#include extern unsigned char NB_gNB_INST; extern RAN_CONTEXT_t RC; @@ -56,12 +63,12 @@ static void configure_nr_rrc(uint32_t gnb_id) MessageDef *msg_p = NULL; // int CC_id; - msg_p = itti_alloc_new_message (TASK_GNB_APP, NRRRC_CONFIGURATION_REQ); + msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, NRRRC_CONFIGURATION_REQ); if (RC.nrrrc[gnb_id]) { RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]); - + LOG_I(GNB_APP, "RRC starting with node type %d\n", RC.nrrrc[gnb_id]->node_type); LOG_I(GNB_APP,"Sending configuration message to NR_RRC task\n"); itti_send_msg_to_task (TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p); @@ -75,30 +82,32 @@ static void configure_nr_rrc(uint32_t gnb_id) static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, const Enb_properties_array_t *enb_properties) { uint32_t gnb_id; - //MessageDef *msg_p; + MessageDef *msg_p; uint32_t register_gnb_pending = 0; for (gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) { { - //s1ap_register_enb_req_t *s1ap_register_gNB; //Type Temporarily reuse + if(NGAP_CONF_MODE){ + ngap_register_gnb_req_t *ngap_register_gNB; //Type Temporarily reuse + + // note: there is an implicit relationship between the data structure and the message name + msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, NGAP_REGISTER_GNB_REQ); //Message Temporarily reuse - // note: there is an implicit relationship between the data structure and the message name - /*msg_p = itti_alloc_new_message (TASK_GNB_APP, S1AP_REGISTER_ENB_REQ); //Message Temporarily reuse + RCconfig_NR_NG(msg_p, gnb_id); - RCconfig_NR_S1(msg_p, gnb_id);*/ + ngap_register_gNB = &NGAP_REGISTER_GNB_REQ(msg_p); //Message Temporarily reuse + LOG_I(GNB_APP,"default drx %d\n",ngap_register_gNB->default_drx); + + itti_send_msg_to_task (TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p); + } if (gnb_id == 0) RCconfig_nr_gtpu(); - - /*s1ap_register_gNB = &S1AP_REGISTER_ENB_REQ(msg_p); //Message Temporarily reuse - LOG_I(GNB_APP,"default drx %d\n",s1ap_register_gNB->default_drx);*/ - - LOG_I(GNB_APP,"[gNB %d] gNB_app_register for instance %d\n", gnb_id, GNB_MODULE_ID_TO_INSTANCE(gnb_id)); - - //itti_send_msg_to_task (TASK_S1AP, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p); - - register_gnb_pending++; } - } + + LOG_I(GNB_APP,"[gNB %d] gNB_app_register for instance %d\n", gnb_id, GNB_MODULE_ID_TO_INSTANCE(gnb_id)); + + register_gnb_pending++; + } return register_gnb_pending; } @@ -112,7 +121,7 @@ static uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) for (gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) { { - msg_p = itti_alloc_new_message (TASK_GNB_APP, X2AP_REGISTER_ENB_REQ); + msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, X2AP_REGISTER_ENB_REQ); LOG_I(X2AP, "GNB_ID: %d \n", gnb_id); RCconfig_NR_X2(msg_p, gnb_id); itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p); @@ -123,15 +132,42 @@ static uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) return register_gnb_x2_pending; } +/*------------------------------------------------------------------------------*/ + +static void init_pdcp(void) { + if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) { + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + if (IS_SOFTMODEM_NOS1) { + LOG_I(PDCP, "IS_SOFTMODEM_NOS1 option enabled\n"); + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT; + } + + pdcp_module_init(pdcp_initmask); + + if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + LOG_I(PDCP, "node is CU, pdcp send rlc_data_req by proto_agent \n"); + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + } else { + LOG_I(PDCP, "node is gNB \n"); + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); + } + } else { + LOG_I(PDCP, "node is DU, rlc send pdcp_data_ind by proto_agent \n"); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); + } +} /*------------------------------------------------------------------------------*/ + void *gNB_app_task(void *args_p) { uint32_t gnb_nb = RC.nb_nr_inst; uint32_t gnb_id_start = 0; uint32_t gnb_id_end = gnb_id_start + gnb_nb; - uint32_t gnb_id; MessageDef *msg_p = NULL; const char *msg_name = NULL; @@ -140,13 +176,12 @@ void *gNB_app_task(void *args_p) /* for no gcc warnings */ (void)instance; + int cell_to_activate = 0; itti_mark_task_ready (TASK_GNB_APP); LOG_I(PHY, "%s() Task ready initialize structures\n", __FUNCTION__); - RCconfig_NR_L1(); - - RCconfig_nr_macrlc(); + if (RC.nb_nr_macrlc_inst>0) RCconfig_nr_macrlc(); LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst); @@ -168,27 +203,52 @@ void *gNB_app_task(void *args_p) configure_nr_rrc(gnb_id); } + if (RC.nb_nr_inst > 0) { + init_pdcp(); + } + if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(RC.rrc[0]->node_type) LOG_I(X2AP, "X2AP enabled \n"); __attribute__((unused)) uint32_t x2_register_gnb_pending = gNB_app_register_x2 (gnb_id_start, gnb_id_end); } - if (EPC_MODE_ENABLED) { - /* Try to register each gNB */ - //registered_gnb = 0; - __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end);//, gnb_properties_p); - } else { - /* Start L2L1 task */ - msg_p = itti_alloc_new_message(TASK_GNB_APP, INITIALIZE_MESSAGE); - itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p); + /* For the CU case the gNB registration with the AMF might have to take place after the F1 setup, as the PLMN info + * can originate from the DU. Add check on whether x2ap is enabled to account for ENDC NSA scenario.*/ + if ((AMF_MODE_ENABLED || is_x2ap_enabled()) && !NODE_IS_DU(RC.nrrrc[0]->node_type) && !NODE_IS_CU(RC.nrrrc[0]->node_type)) { + /* Try to register each gNB */ + //registered_gnb = 0; + __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); } + + if (RC.nb_nr_inst > 0) { + if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { + LOG_E(F1AP, "Create task for F1AP CU failed\n"); + AssertFatal(1==0,"exiting"); + } + } + + if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { + + if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) { + LOG_E(F1AP, "Create task for F1AP DU failed\n"); + AssertFatal(1==0,"exiting"); + } + // configure F1AP here for F1C + LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); + msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_SETUP_REQ); + RCconfig_NR_DU_F1(msg_p, 0); + + itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); + } + } do { // Wait for a message itti_receive_msg (TASK_GNB_APP, &msg_p); msg_name = ITTI_MSG_NAME (msg_p); - instance = ITTI_MSG_INSTANCE (msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: @@ -201,16 +261,16 @@ void *gNB_app_task(void *args_p) break; -/* - case S1AP_REGISTER_ENB_CNF: - LOG_I(GNB_APP, "[gNB %d] Received %s: associated MME %d\n", instance, msg_name, - S1AP_REGISTER_ENB_CNF(msg_p).nb_mme); + case NGAP_REGISTER_GNB_CNF: + LOG_I(GNB_APP, "[gNB %ld] Received %s: associated AMF %d\n", instance, msg_name, + NGAP_REGISTER_GNB_CNF(msg_p).nb_amf); +/* DevAssert(register_gnb_pending > 0); register_gnb_pending--; - // Check if at least gNB is registered with one MME - if (S1AP_REGISTER_ENB_CNF(msg_p).nb_mme > 0) { + // Check if at least gNB is registered with one AMF + if (NGAP_REGISTER_GNB_CNF(msg_p).nb_amf > 0) { registered_gnb++; } @@ -220,13 +280,13 @@ void *gNB_app_task(void *args_p) // If all gNB are registered, start L2L1 task MessageDef *msg_init_p; - msg_init_p = itti_alloc_new_message (TASK_GNB_APP, INITIALIZE_MESSAGE); + msg_init_p = itti_alloc_new_message (TASK_GNB_APP, 0, INITIALIZE_MESSAGE); itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); } else { uint32_t not_associated = gnb_nb - registered_gnb; - LOG_W(GNB_APP, " %d gNB %s not associated with a MME, retrying registration in %d seconds ...\n", + LOG_W(GNB_APP, " %d gNB %s not associated with a AMF, retrying registration in %d seconds ...\n", not_associated, not_associated > 1 ? "are" : "is", GNB_REGISTER_RETRY_DELAY); // Restart the gNB registration process in GNB_REGISTER_RETRY_DELAY seconds @@ -241,12 +301,35 @@ void *gNB_app_task(void *args_p) } } } +*/ + break; + + case F1AP_SETUP_RESP: + AssertFatal(NODE_IS_DU(RC.nrrrc[0]->node_type), "Should not have received F1AP_SETUP_RESP in CU/gNB\n"); + + LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p), + F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate); + cell_to_activate = F1AP_SETUP_RESP(msg_p).num_cells_to_activate; + + gNB_app_handle_f1ap_setup_resp(&F1AP_SETUP_RESP(msg_p)); break; -*/ - case S1AP_DEREGISTERED_ENB_IND: - LOG_W(GNB_APP, "[gNB %d] Received %s: associated MME %d\n", instance, msg_name, - S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme); + case F1AP_GNB_CU_CONFIGURATION_UPDATE: + AssertFatal(NODE_IS_DU(RC.nrrrc[0]->node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n"); + + LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p), + F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).gNB_CU_name,F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate); + + cell_to_activate += F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate; + gNB_app_handle_f1ap_gnb_cu_configuration_update(&F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p)); + + /* Check if at least gNB is registered with one AMF */ + AssertFatal(cell_to_activate == 1,"No cells to activate or cells > 1 %d\n",cell_to_activate); + + break; + case NGAP_DEREGISTERED_GNB_IND: + LOG_W(GNB_APP, "[gNB %ld] Received %s: associated AMF %d\n", instance, msg_name, + NGAP_DEREGISTERED_GNB_IND(msg_p).nb_amf); /* TODO handle recovering of registration */ break; diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 61aa10e47b..d069bfe2f4 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -34,12 +34,16 @@ #include "common/utils/LOG/log_extern.h" #include "assertions.h" #include "gnb_config.h" +#include "gnb_paramdef.h" +#include "enb_paramdef.h" #include "UTIL/OTG/otg.h" #include "UTIL/OTG/otg_externs.h" #include "intertask_interface.h" #include "s1ap_eNB.h" +#include "ngap_gNB.h" #include "sctp_eNB_task.h" #include "sctp_default_values.h" +#include "F1AP_CauseRadioNetwork.h" // #include "SystemInformationBlockType2.h" // #include "LAYER2/MAC/extern.h" // #include "LAYER2/MAC/proto.h" @@ -49,12 +53,14 @@ #include "nfapi_vnf.h" #include "nfapi_pnf.h" -#include "L1_paramdef.h" -#include "MACRLC_paramdef.h" +//#include "L1_paramdef.h" +#include "L1_nr_paramdef.h" +#include "MACRLC_nr_paramdef.h" #include "common/config/config_userapi.h" //#include "RRC_config_tools.h" #include "gnb_paramdef.h" #include "NR_MAC_gNB/mac_proto.h" +#include #include "NR_asn_constant.h" #include "executables/thread-common.h" @@ -74,7 +80,12 @@ #include "NR_ControlResourceSet.h" #include "NR_EUTRA-MBSFN-SubframeConfig.h" +#include "RRC/NR/MESSAGES/asn1_msg.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp.h" + extern uint16_t sf_ahead; +int macrlc_has_f1 = 0; +extern ngran_node_t node_type; extern int config_check_band_frequencies(int ind, int16_t band, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint32_t frame_type); @@ -83,8 +94,6 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) { NR_FreqBandIndicatorNR_t *dl_frequencyBandList,*ul_frequencyBandList; struct NR_SCS_SpecificCarrier *dl_scs_SpecificCarrierList,*ul_scs_SpecificCarrierList; - struct NR_PDSCH_TimeDomainResourceAllocation *bwp_dl_timedomainresourceallocation; - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_configcommontimedomainresourceallocation; // struct NR_RateMatchPattern *ratematchpattern; // NR_RateMatchPatternId_t *ratematchpatternid; // NR_TCI_StateId_t *TCI_StateId; @@ -120,7 +129,8 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) { scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon)); scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero = CALLOC(1,sizeof(long)); scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero = CALLOC(1,sizeof(long)); - // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = CALLOC(1,sizeof(struct NR_ControlResourceSet)); + + scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = NULL; // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = CALLOC(1,sizeof(NR_SearchSpaceId_t)); @@ -131,14 +141,6 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) { scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->present = NR_SetupRelease_PDSCH_ConfigCommon_PR_setup; scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PDSCH_ConfigCommon)); scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList = CALLOC(1,sizeof(struct NR_PDSCH_TimeDomainResourceAllocationList)); - // - for (int i=0;ik0 = CALLOC(1,sizeof(long)); - *bwp_dl_timedomainresourceallocation->k0=0; - ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, - bwp_dl_timedomainresourceallocation); - } ul_frequencyBandList = CALLOC(1,sizeof(NR_FreqBandIndicatorNR_t)); scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList = CALLOC(1,sizeof(struct NR_MultiFrequencyBandListNR)); @@ -153,13 +155,15 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) { scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_RACH_ConfigCommon_t)); scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->present = NR_SetupRelease_RACH_ConfigCommon_PR_setup; scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon)); - // scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles = CALLOC(1,sizeof(long)); + // scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles = CALLOC(1,sizeof(long)); scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB)); // scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->groupBconfigured = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon__groupBconfigured)); scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB = CALLOC(1,sizeof(NR_RSRP_Range_t)); // scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB_SUL = CALLOC(1,sizeof(NR_RSRP_Range_t)); scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t)); scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = CALLOC(1,sizeof(long)); + // 0 - ENABLE, 1 - DISABLE, hence explicitly setting to DISABLED. + *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_PUSCH_ConfigCommon_t)); scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->present = NR_SetupRelease_PUSCH_ConfigCommon_PR_setup; scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PUSCH_ConfigCommon)); @@ -185,12 +189,6 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) { ul_scs_SpecificCarrierList = CALLOC(1,sizeof(struct NR_SCS_SpecificCarrier)); ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list,ul_scs_SpecificCarrierList); - for (int i=0;ik2 = CALLOC(1,sizeof(long)); - *pusch_configcommontimedomainresourceallocation->k2=0; - ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_configcommontimedomainresourceallocation); - } //ratematchpattern = CALLOC(1,sizeof(struct NR_RateMatchPattern)); //ratematchpattern->patternType.choice.bitmaps = CALLOC(1,sizeof(struct NR_RateMatchPattern__patternType__bitmaps)); //ratematchpattern->patternType.choice.bitmaps->resourceBlocks.buf = MALLOC(35); @@ -209,6 +207,92 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) { } +void fill_scc_sim(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL,int N_RB_UL,int mu_dl,int mu_ul) { + + *scc->physCellId=0; \ + // *scc->n_TimingAdvanceOffset=NR_ServingCellConfigCommon__n_TimingAdvanceOffset_n0; + *scc->ssb_periodicityServingCell=NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms20; + scc->dmrs_TypeA_Position=NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2; + *scc->ssbSubcarrierSpacing=NR_SubcarrierSpacing_kHz30; + *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB=641032; + *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]=78; + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA=640000; + scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier=0; + scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing=NR_SubcarrierSpacing_kHz30; + + scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth=N_RB_DL; + scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth=13036; + scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing=mu_dl;//NR_SubcarrierSpacing_kHz30; + *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero=12; + *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero=0; + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation0 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); + timedomainresourceallocation0->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation0->startSymbolAndLength=54; + ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, + timedomainresourceallocation0); + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation1 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); + timedomainresourceallocation1->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation1->startSymbolAndLength=57; + ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, + timedomainresourceallocation1); + *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]=78; + *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA=-1; + scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier=0; + scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing=NR_SubcarrierSpacing_kHz30; + scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth=N_RB_UL; + *scc->uplinkConfigCommon->frequencyInfoUL->p_Max=20; + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth=13036; + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing=mu_ul;//NR_SubcarrierSpacing_kHz30; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex=98; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM=NR_RACH_ConfigGeneric__msg1_FDM_one; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart=0; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig=13; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower=-118; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleTransMax=NR_RACH_ConfigGeneric__preambleTransMax_n10; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.powerRampingStep=NR_RACH_ConfigGeneric__powerRampingStep_dB2; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow=NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB__one_n64; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer=NR_RACH_ConfigCommon__ra_ContentionResolutionTimer_sf64; + *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB=19; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present=NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139=0; + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig=NR_RACH_ConfigCommon__restrictedSetConfig_unrestrictedSet; + struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation0 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); + pusch_timedomainresourceallocation0->k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation0->k2=6; + pusch_timedomainresourceallocation0->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation0->startSymbolAndLength=55; + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation0); + struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation1 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); + pusch_timedomainresourceallocation1->k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation1->k2=6; + pusch_timedomainresourceallocation1->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation1->startSymbolAndLength=38; + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation1); + *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble=1; + *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant=-90; + scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_GroupHopping=NR_PUCCH_ConfigCommon__pucch_GroupHopping_neither; + *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId=40; + *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal=-90; + scc->ssb_PositionsInBurst->present=NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap; + *ssb_bitmap=0xff; + scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing=NR_SubcarrierSpacing_kHz30; + scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity=NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms5; + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots=7; + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols=6; + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots=2; + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols=4; + scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity=321; + + scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots=-1; + scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols=-1; + scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSlots=-1; + scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSymbols=-1; + scc->ss_PBCH_BlockPower=20; + *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing=-1; +} + void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { @@ -231,8 +315,8 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] |= curr_bit<ssb_PositionsInBurst->choice.mediumBitmap.size = 1; - scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; + scc->ssb_PositionsInBurst->choice.mediumBitmap.size = 1; + scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; scc->ssb_PositionsInBurst->choice.mediumBitmap.buf = CALLOC(1,1); scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = 0; for (int i=0; i<8; i++) @@ -242,10 +326,10 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { scc->ssb_PositionsInBurst->choice.longBitmap.bits_unused = 0; scc->ssb_PositionsInBurst->choice.longBitmap.buf = CALLOC(1,8); for (int j=0; j<8; j++) { - scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] = 0; + scc->ssb_PositionsInBurst->choice.longBitmap.buf[j] = 0; curr_bit = (ssbmap>>(j<<3))&(0xff); for (int i=0; i<8; i++) - scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] |= (((curr_bit>>(7-i))&0x01)<ssb_PositionsInBurst->choice.longBitmap.buf[j] |= (((curr_bit>>(7-i))&0x01)<uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder!=0) scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = NULL; - // fix DL and UL Allocation lists - - for (int i=scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count-1;i>=0;i--) { - printf("Checking element %d : %ld\n",i,*scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0); - if (*scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0>32) { - printf("removing pdsch_TimeDomainAllocationList element %d\n",i); - free(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0); - asn_sequence_del(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,i,1); - printf("List size now %d\n",scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count); - } - } + // prepare DL Allocation lists + nr_rrc_config_dl_tda(scc); - for (int i=scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count-1;i>=0;i--) { - if (*scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[i]->k2>32) { - free(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[i]->k2); - asn_sequence_del(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,i,1); - } - } if (scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity > 320 ) { free(scc->tdd_UL_DL_ConfigurationCommon->pattern2); scc->tdd_UL_DL_ConfigurationCommon->pattern2=NULL; @@ -286,6 +355,167 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { free(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing); scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing=NULL; } + + // check pucch_ResourceConfig + AssertFatal(*scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon < 2, + "pucch_ResourceConfig should be 0 or 1 for now\n"); +} + +/* Function to allocate dedicated serving cell config strutures */ +void prepare_scd(NR_ServingCellConfig_t *scd) { + // Allocate downlink structures + + scd->downlinkBWP_ToAddModList = CALLOC(1, sizeof(*scd->downlinkBWP_ToAddModList)); + + // Downlink bandwidth part + NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); + bwp->bwp_Id = 1; + + // Allocate downlink dedicated bandwidth part and PDSCH structures + bwp->bwp_Dedicated = calloc(1, sizeof(*bwp->bwp_Dedicated)); + bwp->bwp_Dedicated->pdsch_Config = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config)); + bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; + bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; + + // Allocate DL DMRS and PTRS configuration + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + NR_DMRS_DownlinkConfig_t *NR_DMRS_DownlinkCfg = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; + NR_DMRS_DownlinkCfg->phaseTrackingRS=CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS)); + NR_DMRS_DownlinkCfg->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup; + NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup)); + NR_PTRS_DownlinkConfig_t *NR_PTRS_DownlinkCfg = NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup; + NR_PTRS_DownlinkCfg->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->frequencyDensity)); + long *dl_rbs = CALLOC(2, sizeof(long)); + for (int i=0;i<2;i++) { + ASN_SEQUENCE_ADD(&NR_PTRS_DownlinkCfg->frequencyDensity->list, &dl_rbs[i]); + } + NR_PTRS_DownlinkCfg->timeDensity = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->timeDensity)); + long *dl_mcs = CALLOC(3, sizeof(long)); + for (int i=0;i<3;i++) { + ASN_SEQUENCE_ADD(&NR_PTRS_DownlinkCfg->timeDensity->list, &dl_mcs[i]); + } + NR_PTRS_DownlinkCfg->epre_Ratio = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->epre_Ratio)); + NR_PTRS_DownlinkCfg->resourceElementOffset = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->resourceElementOffset)); + *NR_PTRS_DownlinkCfg->resourceElementOffset = 0; + ASN_SEQUENCE_ADD(&scd->downlinkBWP_ToAddModList->list,bwp); + + // Allocate uplink structures + + scd->uplinkConfig = CALLOC(1, sizeof(*scd->uplinkConfig)); + scd->uplinkConfig->uplinkBWP_ToAddModList = CALLOC(1, sizeof(*scd->uplinkConfig->uplinkBWP_ToAddModList)); + + NR_PUSCH_Config_t *pusch_Config = CALLOC(1, sizeof(*pusch_Config)); + + // Allocate UL DMRS and PTRS structures + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + NR_DMRS_UplinkConfig->phaseTrackingRS = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS)); + NR_DMRS_UplinkConfig->phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup; + NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup)); + NR_PTRS_UplinkConfig_t *NR_PTRS_UplinkConfig = NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup; + NR_PTRS_UplinkConfig->transformPrecoderDisabled = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled)); + NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity)); + long *n_rbs = CALLOC(2, sizeof(long)); + for (int i=0;i<2;i++) { + ASN_SEQUENCE_ADD(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity->list, &n_rbs[i]); + } + NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity)); + long *ptrs_mcs = CALLOC(3, sizeof(long)); + for (int i = 0; i < 3; i++) { + ASN_SEQUENCE_ADD(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity->list, &ptrs_mcs[i]); + } + NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset)); + *NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = 0; + + // UL bandwidth part + NR_BWP_Uplink_t *ubwp = CALLOC(1, sizeof(*ubwp)); + ubwp->bwp_Id = 1; + ubwp->bwp_Dedicated = CALLOC(1, sizeof(*ubwp->bwp_Dedicated)); + + ubwp->bwp_Dedicated->pusch_Config = CALLOC(1, sizeof(*ubwp->bwp_Dedicated->pusch_Config)); + ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; + ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config; + + ASN_SEQUENCE_ADD(&scd->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); +} + +/* This function checks dedicated serving cell configuration and performs fixes as needed */ +void fix_scd(NR_ServingCellConfig_t *scd) { + // Check for DL PTRS parameters validity + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) { + // If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present + for (int i = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.count-1; i >= 0; i--) { + if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] < 1) + || (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] > 276)) { + LOG_I(RRC, "DL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) { + // If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present + for (int i = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.count-1; i >= 0; i--) { + if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] < 0) + || (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] > 29)) { + LOG_I(RRC, "DL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) { + if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset > 2) { + LOG_I(RRC, "Freeing DL PTRS resourceElementOffset \n"); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = NULL; + } + if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio > 1) { + LOG_I(RRC, "Freeing DL PTRS epre_Ratio \n"); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = NULL; + } + } + + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { + // If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present + for (int i = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.count-1; i >= 0; i--) { + if ((*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] < 1) + || (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] > 276)) { + LOG_I(RRC, "UL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { + // If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present + for (int i = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.count-1; i >= 0; i--) { + if ((*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] < 0) + || (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] > 29)) { + LOG_I(RRC, "UL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { + // Check for UL PTRS parameters validity + if (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset > 2) { + LOG_I(RRC, "Freeing UL PTRS resourceElementOffset \n"); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset = NULL; + } + } } void RCconfig_nr_flexran() @@ -341,8 +571,8 @@ void RCconfig_nr_flexran() /* gNB ID from configuration, as read in by RCconfig_RRC() */ if (!GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr) { // Calculate a default gNB ID - if (EPC_MODE_ENABLED) - gnb_id = i + (s1ap_generate_eNB_id () & 0xFFFF8); + if (AMF_MODE_ENABLED) + gnb_id = i + (ngap_generate_gNB_id () & 0xFFFFFF8); else gnb_id = i; } else { @@ -374,6 +604,32 @@ void RCconfig_nr_flexran() void RCconfig_NR_L1(void) { int j; + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + ////////// Identification parameters + paramdef_t GNBParams[] = GNBPARAMS_DESC; + + paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; + + config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); + int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; + AssertFatal (num_gnbs > 0,"Failed to parse config file no gnbs %s \n",GNB_CONFIG_STRING_ACTIVE_GNBS); + + config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); + char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr; + if (ulprbbl) LOG_I(NR_PHY,"PRB blacklist %s\n",ulprbbl); + char *pt = strtok(ulprbbl,","); + int prbbl[275]; + int num_prbbl=0; + memset(prbbl,0,275*sizeof(int)); + + while (pt) { + prbbl[atoi(pt)] = 1; + LOG_I(NR_PHY,"Blacklisting prb %d\n",atoi(pt)); + pt = strtok(NULL,","); + num_prbbl++; + } + + paramdef_t L1_Params[] = L1PARAMS_DESC; paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST,NULL,0}; @@ -394,9 +650,17 @@ void RCconfig_NR_L1(void) { RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB)); LOG_I(NR_PHY,"RC.gNB[%d] = %p\n",j,RC.gNB[j]); memset(RC.gNB[j],0,sizeof(PHY_VARS_gNB)); - RC.gNB[j]->Mod_id = j; + RC.gNB[j]->Mod_id = j; } + RC.gNB[j]->pusch_proc_threads = *(L1_ParamList.paramarray[j][L1_PUSCH_PROC_THREADS].uptr); + RC.gNB[j]->ofdm_offset_divisor = *(L1_ParamList.paramarray[j][L1_OFDM_OFFSET_DIVISOR].uptr); + RC.gNB[j]->pucch0_thres = *(L1_ParamList.paramarray[j][L1_PUCCH0_DTX_THRESHOLD].uptr); + RC.gNB[j]->prach_thres = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_THRESHOLD].uptr); + RC.gNB[j]->pusch_thres = *(L1_ParamList.paramarray[j][L1_PUSCH_DTX_THRESHOLD].uptr); + RC.gNB[j]->num_ulprbbl = num_prbbl; + LOG_I(NR_PHY,"Copying %d blacklisted PRB to L1 context\n",num_prbbl); + memcpy(RC.gNB[j]->ulprbbl,prbbl,275*sizeof(int)); if(strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) { //sf_ahead = 2; // Need 4 subframe gap between RX and TX }else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) { @@ -417,15 +681,17 @@ void RCconfig_NR_L1(void) { RC.nb_nr_CC = (int *)malloc((1+RC.nb_nr_inst)*sizeof(int)); RC.nb_nr_CC[0]=1; - RC.nb_nr_inst =1; // DJP - feptx_prec uses num_gNB but phy_init_RU uses nb_nr_inst - LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_nr_inst=1 this is because phy_init_RU() uses that to index and not RC.num_gNB - why the 2 similar variables?\n", __FUNCTION__); LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_nr_CC[0]=%d for init_gNB_afterRU()\n", __FUNCTION__, RC.nb_nr_CC[0]); LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_nr_macrlc_inst:%d because used by mac_top_init_gNB()\n", __FUNCTION__, RC.nb_nr_macrlc_inst); mac_top_init_gNB(); - configure_nfapi_pnf(RC.gNB[j]->eth_params_n.remote_addr, RC.gNB[j]->eth_params_n.remote_portc, RC.gNB[j]->eth_params_n.my_addr, RC.gNB[j]->eth_params_n.my_portd, RC.gNB[j]->eth_params_n .remote_portd); + configure_nr_nfapi_pnf(RC.gNB[j]->eth_params_n.remote_addr, + RC.gNB[j]->eth_params_n.remote_portc, + RC.gNB[j]->eth_params_n.my_addr, + RC.gNB[j]->eth_params_n.my_portd, + RC.gNB[j]->eth_params_n.remote_portd); }else { // other midhaul } }// for (j = 0; j < RC.nb_nr_L1_inst; j++) @@ -451,6 +717,30 @@ void RCconfig_NR_L1(void) { void RCconfig_nr_macrlc() { int j; + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + ////////// Identification parameters + paramdef_t GNBParams[] = GNBPARAMS_DESC; + + paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; + + config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); + int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; + AssertFatal (num_gnbs > 0,"Failed to parse config file no gnbs %s \n",GNB_CONFIG_STRING_ACTIVE_GNBS); + + config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); + char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr; + char *pt = strtok(ulprbbl,","); + int prbbl[275]; + int num_prbbl=0; + int prb; + memset(prbbl,0,275*sizeof(int)); + while (pt) { + prb=atoi(pt); + prbbl[prb] = 1; + pt = strtok(NULL,","); + num_prbbl++; + } + paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC; paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0}; @@ -464,10 +754,30 @@ void RCconfig_nr_macrlc() { for (j=0;jpusch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHTARGETSNRX10_IDX].iptr); + RC.nrmac[j]->pucch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHTARGETSNRX10_IDX].iptr); + RC.nrmac[j]->pucch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHFAILURETHRES_IDX].iptr); + RC.nrmac[j]->pusch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHFAILURETHRES_IDX].iptr); + + LOG_I(NR_MAC,"PUSCH Target %d, PUCCH Target %d, PUCCH Failure %d, PUSCH Failure %d\n", + RC.nrmac[j]->pusch_target_snrx10, + RC.nrmac[j]->pucch_target_snrx10, + RC.nrmac[j]->pucch_failure_thres, + RC.nrmac[j]->pusch_failure_thres); if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_RRC") == 0) { // check number of instances is same as RRC/PDCP + }else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) { + printf("Configuring F1 interfaces for MACRLC\n"); + RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr)); + RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); + RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr)); + RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr); + RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr); + RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr); + RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);; + RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE; + macrlc_has_f1 = 1; }else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "cudu") == 0) { RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr)); RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); @@ -493,44 +803,173 @@ void RCconfig_nr_macrlc() { RC.nrmac[j]->eth_params_s.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr); RC.nrmac[j]->eth_params_s.transp_preference = ETH_UDP_MODE; - //sf_ahead = 2; // Cannot cope with 4 subframes between RX and TX - set it to 2 - - printf("**************** vnf_port:%d\n", RC.mac[j]->eth_params_s.my_portc); - configure_nfapi_vnf(RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc); + printf("**************** vnf_port:%d\n", RC.nrmac[j]->eth_params_s.my_portc); + configure_nr_nfapi_vnf(RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc); printf("**************** RETURNED FROM configure_nfapi_vnf() vnf_port:%d\n", RC.nrmac[j]->eth_params_s.my_portc); }else { // other midhaul AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr)); } + RC.nrmac[j]->ulsch_max_frame_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_FRAME_INACTIVITY].uptr); + RC.nrmac[j]->dl_bler_target_upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr); + RC.nrmac[j]->dl_bler_target_lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr); + RC.nrmac[j]->dl_rd2_bler_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_RD2_BLER_THRESHOLD_IDX].dblptr); + RC.nrmac[j]->dl_max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr); + RC.nrmac[j]->num_ulprbbl = num_prbbl; + LOG_I(NR_MAC,"Blacklisted PRBS %d\n",num_prbbl); + memcpy(RC.nrmac[j]->ulprbbl,prbbl,275*sizeof(prbbl[0])); + }// for (j=0;j 0 - AssertFatal (0,"No " CONFIG_STRING_MACRLC_LIST " configuration found"); + LOG_E(PHY,"No %s configuration found\n", CONFIG_STRING_MACRLC_LIST); + // AssertFatal (0,"No " CONFIG_STRING_MACRLC_LIST " configuration found"); } } +void config_security(gNB_RRC_INST *rrc) +{ + paramdef_t sec_params[] = SECURITY_GLOBALPARAMS_DESC; + int ret = config_get(sec_params, + sizeof(sec_params) / sizeof(paramdef_t), + CONFIG_STRING_SECURITY); + int i; + + if (ret < 0) { + LOG_W(RRC, "configuration file does not contain a \"security\" section, applying default parameters (nia2 nea0, integrity disabled for DRBs)\n"); + rrc->security.ciphering_algorithms[0] = 0; /* nea0 = no ciphering */ + rrc->security.ciphering_algorithms_count = 1; + rrc->security.integrity_algorithms[0] = 2; /* nia2 */ + rrc->security.integrity_algorithms[1] = 0; /* nia0 = no integrity, as a fallback (but nia2 should be supported by all UEs) */ + rrc->security.integrity_algorithms_count = 2; + rrc->security.do_drb_ciphering = 1; /* even if nea0 let's activate so that we don't generate cipheringDisabled in pdcp_Config */ + rrc->security.do_drb_integrity = 0; + return; + } + + if (sec_params[SECURITY_CONFIG_CIPHERING_IDX].numelt > 4) { + LOG_E(RRC, "too much ciphering algorithms in section \"security\" of the configuration file, maximum is 4\n"); + exit(1); + } + if (sec_params[SECURITY_CONFIG_INTEGRITY_IDX].numelt > 4) { + LOG_E(RRC, "too much integrity algorithms in section \"security\" of the configuration file, maximum is 4\n"); + exit(1); + } + + /* get ciphering algorithms */ + rrc->security.ciphering_algorithms_count = 0; + for (i = 0; i < sec_params[SECURITY_CONFIG_CIPHERING_IDX].numelt; i++) { + if (!strcmp(sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea0")) { + rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 0; + rrc->security.ciphering_algorithms_count++; + continue; + } + if (!strcmp(sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea1")) { + rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 1; + rrc->security.ciphering_algorithms_count++; + continue; + } + if (!strcmp(sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea2")) { + rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 2; + rrc->security.ciphering_algorithms_count++; + continue; + } + if (!strcmp(sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea3")) { + rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 3; + rrc->security.ciphering_algorithms_count++; + continue; + } + LOG_E(RRC, "unknown ciphering algorithm \"%s\" in section \"security\" of the configuration file\n", + sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i]); + exit(1); + } + + /* get integrity algorithms */ + rrc->security.integrity_algorithms_count = 0; + for (i = 0; i < sec_params[SECURITY_CONFIG_INTEGRITY_IDX].numelt; i++) { + if (!strcmp(sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia0")) { + rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 0; + rrc->security.integrity_algorithms_count++; + continue; + } + if (!strcmp(sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia1")) { + rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 1; + rrc->security.integrity_algorithms_count++; + continue; + } + if (!strcmp(sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia2")) { + rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 2; + rrc->security.integrity_algorithms_count++; + continue; + } + if (!strcmp(sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia3")) { + rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 3; + rrc->security.integrity_algorithms_count++; + continue; + } + LOG_E(RRC, "unknown integrity algorithm \"%s\" in section \"security\" of the configuration file\n", + sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i]); + exit(1); + } + + if (rrc->security.ciphering_algorithms_count == 0) { + LOG_W(RRC, "no preferred ciphering algorithm set in configuration file, applying default parameters (no security)\n"); + rrc->security.ciphering_algorithms[0] = 0; /* nea0 = no ciphering */ + rrc->security.ciphering_algorithms_count = 1; + } + + if (rrc->security.integrity_algorithms_count == 0) { + LOG_W(RRC, "no preferred integrity algorithm set in configuration file, applying default parameters (nia2)\n"); + rrc->security.integrity_algorithms[0] = 2; /* nia2 */ + rrc->security.integrity_algorithms[1] = 0; /* nia0 = no integrity */ + rrc->security.integrity_algorithms_count = 2; + } + + if (!strcmp(*sec_params[SECURITY_CONFIG_DO_DRB_CIPHERING_IDX].strptr, "yes")) { + rrc->security.do_drb_ciphering = 1; + } else if (!strcmp(*sec_params[SECURITY_CONFIG_DO_DRB_CIPHERING_IDX].strptr, "no")) { + rrc->security.do_drb_ciphering = 0; + } else { + LOG_E(RRC, "in configuration file, bad drb_ciphering value '%s', only 'yes' and 'no' allowed\n", + *sec_params[SECURITY_CONFIG_DO_DRB_CIPHERING_IDX].strptr); + exit(1); + } + + if (!strcmp(*sec_params[SECURITY_CONFIG_DO_DRB_INTEGRITY_IDX].strptr, "yes")) { + rrc->security.do_drb_integrity = 1; + } else if (!strcmp(*sec_params[SECURITY_CONFIG_DO_DRB_INTEGRITY_IDX].strptr, "no")) { + rrc->security.do_drb_integrity = 0; + } else { + LOG_E(RRC, "in configuration file, bad drb_integrity value '%s', only 'yes' and 'no' allowed\n", + *sec_params[SECURITY_CONFIG_DO_DRB_INTEGRITY_IDX].strptr); + exit(1); + } +} + void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { int num_gnbs = 0; char aprefix[MAX_OPTNAME_SIZE*2 + 8]; int32_t gnb_id = 0; - int k; + int k = 0; + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; ////////// Identification parameters paramdef_t GNBParams[] = GNBPARAMS_DESC; paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(NR_ServingCellConfigCommon_t)); - int ssb_SubcarrierOffset = 31; - int pdsch_AntennaPorts = 1; uint64_t ssb_bitmap=0xff; memset((void*)scc,0,sizeof(NR_ServingCellConfigCommon_t)); prepare_scc(scc); paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc); paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0}; - paramdef_t SSBsParams[] = SSBPARAMS_DESC; - paramlist_def_t SSBsParamList = {GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET, NULL, 0}; - paramdef_t PDSCHANTENNAParams[] = PDSCHANTENNAPARAMS_DESC; - paramlist_def_t PDSCHANTENNAParamList = {GNB_CONFIG_STRING_PDSCHANTENNAPORTS, NULL, 0}; + + // Serving Cell Config Dedicated + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); + memset((void*)scd,0,sizeof(NR_ServingCellConfig_t)); + prepare_scd(scd); + paramdef_t SCDsParams[] = SCDPARAMS_DESC(scd); + paramlist_def_t SCDsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, NULL, 0}; ////////// Physical parameters @@ -541,7 +980,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { AssertFatal (icarrier.pdcch_ConfigSIB1 = calloc(1,sizeof(NR_PDCCH_ConfigSIB1_t)); + paramdef_t pdcch_ConfigSIB1[] = PDCCH_CONFIGSIB1PARAMS_DESC(rrc->carrier.pdcch_ConfigSIB1); + paramlist_def_t pdcch_ConfigSIB1ParamList = {GNB_CONFIG_STRING_PDCCH_CONFIGSIB1, NULL, 0}; sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); - config_getlist(&SSBsParamList, NULL, 0, aprefix); - if (SSBsParamList.numelt > 0) config_get(SSBsParams,sizeof(SSBsParams)/sizeof(paramdef_t),aprefix); - - config_getlist(&PDSCHANTENNAParamList, NULL, 0, aprefix); - if (PDSCHANTENNAParamList.numelt > 0) config_get(PDSCHANTENNAParams,sizeof(PDSCHANTENNAParams)/sizeof(paramdef_t),aprefix); + config_getlist(&pdcch_ConfigSIB1ParamList, NULL, 0, aprefix); + if (pdcch_ConfigSIB1ParamList.numelt > 0) { + sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_PDCCH_CONFIGSIB1, 0); + config_get(pdcch_ConfigSIB1,sizeof(pdcch_ConfigSIB1)/sizeof(paramdef_t),aprefix); + } + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); config_getlist(&SCCsParamList, NULL, 0, aprefix); if (SCCsParamList.numelt > 0) { @@ -599,7 +1043,59 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { (int)scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower); fix_scc(scc,ssb_bitmap); } + + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + + config_getlist(&SCDsParamList, NULL, 0, aprefix); + if (SCDsParamList.numelt > 0) { + sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 0); + config_get( SCDsParams,sizeof(SCDsParams)/sizeof(paramdef_t),aprefix); + LOG_I(RRC,"Read in ServingCellConfigDedicated UL (FreqDensity_0 %d, FreqDensity_1 %d, TimeDensity_0 %d, TimeDensity_1 %d, TimeDensity_2 %d, RE offset %d \n", + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[0], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[1], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[0], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[1], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[2], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset); + } + fix_scd(scd); + printf("NRRRC %d: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr)); + + if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) { + paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC; + char aprefix[MAX_OPTNAME_SIZE*2 + 8]; + sprintf(aprefix,"%s.[%u].%s",GNB_CONFIG_STRING_GNB_LIST,i,GNB_CONFIG_STRING_SCTP_CONFIG); + config_get(SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix); + rrc->node_id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr); + LOG_I(GNB_APP,"F1AP: gNB_CU_id[%d] %d\n",k,rrc->node_id); + rrc->node_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr)); + LOG_I(GNB_APP,"F1AP: gNB_CU_name[%d] %s\n",k,rrc->node_name); + rrc->eth_params_s.local_if_name = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_IF_NAME_IDX].strptr)); + rrc->eth_params_s.my_addr = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_ADDRESS_IDX].strptr)); + rrc->eth_params_s.remote_addr = strdup(*(GNBParamList.paramarray[i][GNB_REMOTE_S_ADDRESS_IDX].strptr)); + rrc->eth_params_s.my_portc = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTC_IDX].uptr); + rrc->eth_params_s.remote_portc = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTC_IDX].uptr); + rrc->eth_params_s.my_portd = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTD_IDX].uptr); + rrc->eth_params_s.remote_portd = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTD_IDX].uptr); + rrc->eth_params_s.transp_preference = ETH_UDP_MODE; + rrc->node_type = ngran_gNB_CU; + rrc->sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); + rrc->sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); + } else { + // set to ngran_gNB for now, it will get set to ngran_gNB_DU if macrlc entity which uses F1 is present + // Note: we will have to handle the case of ngran_ng_gNB_DU + if (macrlc_has_f1 == 0) { + rrc->node_type = ngran_gNB; + LOG_I(NR_RRC,"Setting node_type to ngran_gNB\n"); + } else { + rrc->node_type = ngran_gNB_DU; + LOG_I(NR_RRC,"Setting node_type to ngran_gNB_DU\n"); + } + } + + rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr); + if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) { } else if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "cudu") == 0) { @@ -649,7 +1145,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n", PLMNParamList.numelt); - RRC_CONFIGURATION_REQ(msg_p).num_plmn = PLMNParamList.numelt; + NRRRC_CONFIGURATION_REQ(msg_p).num_plmn = PLMNParamList.numelt; for (int l = 0; l < PLMNParamList.numelt; ++l) { @@ -660,21 +1156,27 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { (NRRRC_CONFIGURATION_REQ (msg_p).mnc_digit_length[l] == 3),"BAD MNC DIGIT LENGTH %d", NRRRC_CONFIGURATION_REQ (msg_p).mnc_digit_length[l]); } - - // Parse optional physical parameters - sprintf(gnbpath,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k), + printf("SSB SCO %d\n",*GNBParamList.paramarray[i][GNB_SSB_SUBCARRIEROFFSET_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).ssb_SubcarrierOffset = *GNBParamList.paramarray[i][GNB_SSB_SUBCARRIEROFFSET_IDX].iptr; + printf("pdsch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr; + printf("pusch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).pusch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr; + printf("minTXRXTIME %d\n",*GNBParamList.paramarray[i][GNB_MINRXTXTIME_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).minRXTXTIME = *GNBParamList.paramarray[i][GNB_MINRXTXTIME_IDX].iptr; + NRRRC_CONFIGURATION_REQ (msg_p).sib1_tda = *GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr; + printf("Do CSI-RS %d\n",*GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).do_CSIRS = *GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr; + NRRRC_CONFIGURATION_REQ (msg_p).scc = scc; + NRRRC_CONFIGURATION_REQ (msg_p).scd = scd; - printf("SSB SCO %d\n",ssb_SubcarrierOffset); - NRRRC_CONFIGURATION_REQ (msg_p).ssb_SubcarrierOffset = ssb_SubcarrierOffset; - printf("pdsch_AntennaPorts %d\n",pdsch_AntennaPorts); - NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts = pdsch_AntennaPorts; - NRRRC_CONFIGURATION_REQ (msg_p).scc = scc; }// }//End for (k=0; k configuration, &NRRRC_CONFIGURATION_REQ(msg_p), sizeof(NRRRC_CONFIGURATION_REQ(msg_p))); }//End if (num_gnbs>0) - + config_security(rrc); }//End RCconfig_NRRRC function int RCconfig_nr_gtpu(void ) { @@ -683,16 +1185,19 @@ int RCconfig_nr_gtpu(void ) { + char* gnb_interface_name_for_NGU = NULL; + char* gnb_ipv4_address_for_NGU = NULL; + uint32_t gnb_port_for_NGU = 0; char* gnb_interface_name_for_S1U = NULL; char* gnb_ipv4_address_for_S1U = NULL; uint32_t gnb_port_for_S1U = 0; char *address = NULL; char *cidr = NULL; char gtpupath[MAX_OPTNAME_SIZE*2 + 8]; - + uint8_t gnb_mode = 0; paramdef_t GNBSParams[] = GNBSPARAMS_DESC; - + paramdef_t NETParams[] = GNBNETPARAMS_DESC; paramdef_t GTPUParams[] = GNBGTPUPARAMS_DESC; LOG_I(GTPU,"Configuring GTPu\n"); @@ -702,34 +1207,54 @@ int RCconfig_nr_gtpu(void ) { AssertFatal (num_gnbs >0, "Failed to parse config file no active gNodeBs in %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS); - sprintf(gtpupath,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); - config_get( GTPUParams,sizeof(GTPUParams)/sizeof(paramdef_t),gtpupath); - + config_get(GTPUParams,sizeof(GTPUParams)/sizeof(paramdef_t),gtpupath); + config_get(NETParams,sizeof(NETParams)/sizeof(paramdef_t),gtpupath); + if (NETParams[0].strptr != NULL) { // SA + LOG_I(GTPU, "SA mode \n"); + cidr = gnb_ipv4_address_for_NGU; + gnb_mode = 0; + } else {// NSA + LOG_I(GTPU, "NSA mode \n"); cidr = gnb_ipv4_address_for_S1U; + gnb_mode = 1; + } + address = strtok(cidr, "/"); - + if (address) { MessageDef *message; - AssertFatal((message = itti_alloc_new_message(TASK_GNB_APP, GTPV1U_ENB_S1_REQ))!=NULL,""); - // IPV4_STR_ADDR_TO_INT_NWBO ( address, RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" ); - // LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up); - - IPV4_STR_ADDR_TO_INT_NWBO ( address, GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" ); - LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up); - GTPV1U_ENB_S1_REQ(message).enb_port_for_S1u_S12_S4_up = gnb_port_for_S1U; - itti_send_msg_to_task (TASK_GTPV1_U, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id) + if (gnb_mode == 1) { // NSA + message = itti_alloc_new_message(TASK_GNB_APP, 0, GTPV1U_ENB_S1_REQ); + AssertFatal(message!=NULL,""); + // IPV4_STR_ADDR_TO_INT_NWBO ( address, RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" ); + // LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up); + IPV4_STR_ADDR_TO_INT_NWBO (address, GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" ); + LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up); + GTPV1U_ENB_S1_REQ(message).enb_port_for_S1u_S12_S4_up = gnb_port_for_S1U; + strcpy(GTPV1U_ENB_S1_REQ(message).addrStr,address); + sprintf(GTPV1U_ENB_S1_REQ(message).portStr,"%d", gnb_port_for_NGU); + } else {// TODO SA + message = itti_alloc_new_message(TASK_GNB_APP, 0, GTPV1U_GNB_NG_REQ); + AssertFatal(message!=NULL,""); + IPV4_STR_ADDR_TO_INT_NWBO (address, GTPV1U_GNB_NG_REQ(message).gnb_ip_address_for_NGu_up, "BAD IP ADDRESS FORMAT FOR gNB NG_U !\n" ); + LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_GNB_NG_REQ(message).gnb_ip_address_for_NGu_up); + GTPV1U_GNB_NG_REQ(message).gnb_port_for_NGu_up = gnb_port_for_NGU; + strcpy(GTPV1U_GNB_NG_REQ(message).addrStr,address); + sprintf(GTPV1U_GNB_NG_REQ(message).portStr,"%d", gnb_port_for_NGU); + } + itti_send_msg_to_task (TASK_VARIABLE, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id) } else - LOG_E(GTPU,"invalid address for S1U\n"); + LOG_E(GTPU,"invalid address for NGU\n"); return 0; } -int RCconfig_NR_S1(MessageDef *msg_p, uint32_t i) { +int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) { int j,k = 0; int gnb_id; @@ -752,7 +1277,7 @@ int RCconfig_NR_S1(MessageDef *msg_p, uint32_t i) { config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); /* - if (EPC_MODE_ENABLED) { + if (AMF_MODE_ENABLED) { if (strcasecmp( *(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr), GNB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) { asn_debug = 0; asn1_xer_print = 0; @@ -777,60 +1302,61 @@ int RCconfig_NR_S1(MessageDef *msg_p, uint32_t i) { if (GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt>0) { // Output a list of all gNBs. config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); - - - - - if (GNBParamList.numelt > 0) { for (k = 0; k < GNBParamList.numelt; k++) { - if (GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr == NULL) { - // Calculate a default gNB ID - if (EPC_MODE_ENABLED) { - uint32_t hash; - - hash = s1ap_generate_eNB_id (); - gnb_id = k + (hash & 0xFFFF8); - } else { - gnb_id = k; - } - } else { + if (GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr == NULL) { + // Calculate a default gNB ID + if (AMF_MODE_ENABLED) { + uint32_t hash; + + hash = ngap_generate_gNB_id (); + gnb_id = k + (hash & 0xFFFFFF8); + } else { + gnb_id = k; + } + } else { gnb_id = *(GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr); } - // search if in active list - for (j=0; j < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; j++) { - if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[j], *(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)) == 0) { + // search if in active list + for (j=0; j < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; j++) { + if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[j], *(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)) == 0) { paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC; paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0}; + paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC; + paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0}; /* map parameter checking array instances to parameter definition array instances */ checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK; + checkedparam_t config_check_SNSSAIParams [] = SNSSAIPARAMS_CHECK; for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I) PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]); + for (int J = 0; J < sizeof(SNSSAIParams) / sizeof(paramdef_t); ++J) + SNSSAIParams[J].chkPptr = &(config_check_SNSSAIParams[J]); - paramdef_t S1Params[] = GNBS1PARAMS_DESC; - paramlist_def_t S1ParamList = {GNB_CONFIG_STRING_MME_IP_ADDRESS,NULL,0}; - - paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC; - paramdef_t NETParams[] = GNBNETPARAMS_DESC; - char aprefix[MAX_OPTNAME_SIZE*2 + 8]; - - S1AP_REGISTER_ENB_REQ (msg_p).eNB_id = gnb_id; - - if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_MACRO_GNB") == 0) { - S1AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB; - } else if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_HOME_GNB") == 0) { - S1AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB; - } else { - AssertFatal (0, - "Failed to parse gNB configuration file %s, gnb %d unknown value \"%s\" for cell_type choice: CELL_MACRO_GNB or CELL_HOME_GNB !\n", - RC.config_file_name, i, *(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr)); - } - - S1AP_REGISTER_ENB_REQ (msg_p).eNB_name = strdup(*(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)); - S1AP_REGISTER_ENB_REQ (msg_p).tac = *GNBParamList.paramarray[k][GNB_TRACKING_AREA_CODE_IDX].uptr; + paramdef_t NGParams[] = GNBNGPARAMS_DESC; + paramlist_def_t NGParamList = {GNB_CONFIG_STRING_AMF_IP_ADDRESS,NULL,0}; + + paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC; + paramdef_t NETParams[] = GNBNETPARAMS_DESC; + char aprefix[MAX_OPTNAME_SIZE*2 + 8]; + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k); + + NGAP_REGISTER_GNB_REQ (msg_p).gNB_id = gnb_id; + + if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_MACRO_GNB") == 0) { + NGAP_REGISTER_GNB_REQ (msg_p).cell_type = CELL_MACRO_GNB; + } else if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_HOME_GNB") == 0) { + NGAP_REGISTER_GNB_REQ (msg_p).cell_type = CELL_HOME_ENB; + } else { + AssertFatal (0, + "Failed to parse gNB configuration file %s, gnb %d unknown value \"%s\" for cell_type choice: CELL_MACRO_GNB or CELL_HOME_GNB !\n", + RC.config_file_name, i, *(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr)); + } + + NGAP_REGISTER_GNB_REQ (msg_p).gNB_name = strdup(*(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)); + NGAP_REGISTER_GNB_REQ (msg_p).tac = *GNBParamList.paramarray[k][GNB_TRACKING_AREA_CODE_IDX].uptr; AssertFatal(!GNBParamList.paramarray[k][GNB_MOBILE_COUNTRY_CODE_IDX_OLD].strptr && !GNBParamList.paramarray[k][GNB_MOBILE_NETWORK_CODE_IDX_OLD].strptr, "It seems that you use an old configuration file. Please change the existing\n" @@ -846,100 +1372,118 @@ int RCconfig_NR_S1(MessageDef *msg_p, uint32_t i) { AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n", PLMNParamList.numelt); - S1AP_REGISTER_ENB_REQ(msg_p).num_plmn = PLMNParamList.numelt; + NGAP_REGISTER_GNB_REQ(msg_p).num_plmn = PLMNParamList.numelt; for (int l = 0; l < PLMNParamList.numelt; ++l) { - - S1AP_REGISTER_ENB_REQ (msg_p).mcc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_COUNTRY_CODE_IDX].uptr; - S1AP_REGISTER_ENB_REQ (msg_p).mnc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_NETWORK_CODE_IDX].uptr; - S1AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length[l] = *PLMNParamList.paramarray[l][GNB_MNC_DIGIT_LENGTH].u8ptr; - S1AP_REGISTER_ENB_REQ (msg_p).default_drx = 0; - AssertFatal((S1AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length[l] == 2) || - (S1AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length[l] == 3), - "BAD MNC DIGIT LENGTH %d", - S1AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length[l]); - } - sprintf(aprefix,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k); - config_getlist( &S1ParamList,S1Params,sizeof(S1Params)/sizeof(paramdef_t),aprefix); - - S1AP_REGISTER_ENB_REQ (msg_p).nb_mme = 0; - - for (int l = 0; l < S1ParamList.numelt; l++) { - - S1AP_REGISTER_ENB_REQ (msg_p).nb_mme += 1; - - strcpy(S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4_address,*(S1ParamList.paramarray[l][GNB_MME_IPV4_ADDRESS_IDX].strptr)); - strcpy(S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6_address,*(S1ParamList.paramarray[l][GNB_MME_IPV6_ADDRESS_IDX].strptr)); + char snssaistr[MAX_OPTNAME_SIZE*2 + 8]; + sprintf(snssaistr, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_PLMN_LIST, l); + config_getlist(&SNSSAIParamList, SNSSAIParams, sizeof(SNSSAIParams)/sizeof(paramdef_t), snssaistr); - if (strcmp(*(S1ParamList.paramarray[l][GNB_MME_IP_ADDRESS_ACTIVE_IDX].strptr), "yes") == 0) { - } - if (strcmp(*(S1ParamList.paramarray[l][GNB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) { - S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[j].ipv4 = 1; - } else if (strcmp(*(S1ParamList.paramarray[l][GNB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) { - S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[j].ipv6 = 1; - } else if (strcmp(*(S1ParamList.paramarray[l][GNB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) { - S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[j].ipv4 = 1; - S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[j].ipv6 = 1; - } + NGAP_REGISTER_GNB_REQ (msg_p).mcc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_COUNTRY_CODE_IDX].uptr; + NGAP_REGISTER_GNB_REQ (msg_p).mnc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_NETWORK_CODE_IDX].uptr; + NGAP_REGISTER_GNB_REQ (msg_p).mnc_digit_length[l] = *PLMNParamList.paramarray[l][GNB_MNC_DIGIT_LENGTH].u8ptr; + NGAP_REGISTER_GNB_REQ (msg_p).default_drx = 0; + AssertFatal((NGAP_REGISTER_GNB_REQ (msg_p).mnc_digit_length[l] == 2) || + (NGAP_REGISTER_GNB_REQ (msg_p).mnc_digit_length[l] == 3), + "BAD MNC DIGIT LENGTH %d", + NGAP_REGISTER_GNB_REQ (msg_p).mnc_digit_length[l]); + + NGAP_REGISTER_GNB_REQ (msg_p).num_nssai[l] = SNSSAIParamList.numelt; + for (int s = 0; s < SNSSAIParamList.numelt; ++s) { + + NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sST = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERIVE_TYPE_IDX].uptr; + NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD_flag = 0; + if(*SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr != 0) { + NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD_flag = 1; + NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD[0] = (*SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr & 0xFF0000) >> 16; + NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD[1] = (*SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr & 0x00FF00) >> 8; + NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD[2] = (*SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr & 0x0000FF); + } + } + } + sprintf(aprefix,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k); + config_getlist( &NGParamList,NGParams,sizeof(NGParams)/sizeof(paramdef_t),aprefix); + + NGAP_REGISTER_GNB_REQ (msg_p).nb_amf = 0; + + for (int l = 0; l < NGParamList.numelt; l++) { + + NGAP_REGISTER_GNB_REQ (msg_p).nb_amf += 1; + + strcpy(NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[l].ipv4_address,*(NGParamList.paramarray[l][GNB_AMF_IPV4_ADDRESS_IDX].strptr)); + strcpy(NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[l].ipv6_address,*(NGParamList.paramarray[l][GNB_AMF_IPV6_ADDRESS_IDX].strptr)); - if (S1ParamList.paramarray[l][GNB_MME_BROADCAST_PLMN_INDEX].iptr) - S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] = S1ParamList.paramarray[l][GNB_MME_BROADCAST_PLMN_INDEX].numelt; + if (strcmp(*(NGParamList.paramarray[l][GNB_AMF_IP_ADDRESS_ACTIVE_IDX].strptr), "yes") == 0) { + } + if (strcmp(*(NGParamList.paramarray[l][GNB_AMF_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) { + NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv4 = 1; + } else if (strcmp(*(NGParamList.paramarray[l][GNB_AMF_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) { + NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv6 = 1; + } else if (strcmp(*(NGParamList.paramarray[l][GNB_AMF_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) { + NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv4 = 1; + NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv6 = 1; + } + + /* not in configuration yet ... + if (NGParamList.paramarray[l][GNB_AMF_BROADCAST_PLMN_INDEX].iptr) + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] = NGParamList.paramarray[l][GNB_AMF_BROADCAST_PLMN_INDEX].numelt; else - S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] = 0; + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] = 0; + */ - AssertFatal(S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] <= S1AP_REGISTER_ENB_REQ(msg_p).num_plmn, - "List of broadcast PLMN to be sent to MME can not be longer than actual " + AssertFatal(NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] <= NGAP_REGISTER_GNB_REQ(msg_p).num_plmn, + "List of broadcast PLMN to be sent to AMF can not be longer than actual " "PLMN list (max %d, but is %d)\n", - S1AP_REGISTER_ENB_REQ(msg_p).num_plmn, - S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l]); + NGAP_REGISTER_GNB_REQ(msg_p).num_plmn, + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l]); - for (int el = 0; el < S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l]; ++el) { + for (int el = 0; el < NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l]; ++el) { /* UINTARRAY gets mapped to int, see config_libconfig.c:223 */ - S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el] = S1ParamList.paramarray[l][GNB_MME_BROADCAST_PLMN_INDEX].iptr[el]; - AssertFatal(S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el] >= 0 - && S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el] < S1AP_REGISTER_ENB_REQ(msg_p).num_plmn, - "index for MME's MCC/MNC (%d) is an invalid index for the registered PLMN IDs (%d)\n", - S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el], - S1AP_REGISTER_ENB_REQ(msg_p).num_plmn); + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] = NGParamList.paramarray[l][GNB_AMF_BROADCAST_PLMN_INDEX].iptr[el]; + AssertFatal(NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] >= 0 + && NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] < NGAP_REGISTER_GNB_REQ(msg_p).num_plmn, + "index for AMF's MCC/MNC (%d) is an invalid index for the registered PLMN IDs (%d)\n", + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el], + NGAP_REGISTER_GNB_REQ(msg_p).num_plmn); } /* if no broadcasst_plmn array is defined, fill default values */ - if (S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] == 0) { - S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_num[l] = S1AP_REGISTER_ENB_REQ(msg_p).num_plmn; + if (NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] == 0) { + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] = NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; - for (int el = 0; el < S1AP_REGISTER_ENB_REQ(msg_p).num_plmn; ++el) - S1AP_REGISTER_ENB_REQ(msg_p).broadcast_plmn_index[l][el] = el; + for (int el = 0; el < NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; ++el) + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] = el; } - - } + + } - - // SCTP SETTING - S1AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; - S1AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; - if (EPC_MODE_ENABLED) { - sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_SCTP_CONFIG); - config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix); - S1AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); - S1AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); - } + + // SCTP SETTING + NGAP_REGISTER_GNB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; + NGAP_REGISTER_GNB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; + if (AMF_MODE_ENABLED) { + sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_SCTP_CONFIG); + config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix); + NGAP_REGISTER_GNB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); + NGAP_REGISTER_GNB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); + } sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); - // NETWORK_INTERFACES + // NETWORK_INTERFACES config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix); - - // S1AP_REGISTER_ENB_REQ (msg_p).enb_interface_name_for_S1U = strdup(enb_interface_name_for_S1U); - cidr = *(NETParams[GNB_IPV4_ADDRESS_FOR_S1_MME_IDX].strptr); - address = strtok(cidr, "/"); - - S1AP_REGISTER_ENB_REQ (msg_p).enb_ip_address.ipv6 = 0; - S1AP_REGISTER_ENB_REQ (msg_p).enb_ip_address.ipv4 = 1; - - strcpy(S1AP_REGISTER_ENB_REQ (msg_p).enb_ip_address.ipv4_address, address); - - break; - } - } + + // NGAP_REGISTER_GNB_REQ (msg_p).enb_interface_name_for_NGU = strdup(enb_interface_name_for_NGU); + cidr = *(NETParams[GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX].strptr); + address = strtok(cidr, "/"); + + NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv6 = 0; + NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv4 = 1; + + strcpy(NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv4_address, address); + + break; + } + } } } } @@ -983,16 +1527,15 @@ void NRRCConfig(void) { paramdef_t GNBSParams[] = GNBSPARAMS_DESC; /* get global parameters, defined outside any section in the config file */ - + LOG_I(GNB_APP, "Getting GNBSParams\n"); config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); RC.nb_nr_inst = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; - // Get num MACRLC instances config_getlist( &MACRLCParamList,NULL,0, NULL); - RC.nb_macrlc_inst = MACRLCParamList.numelt; + RC.nb_nr_macrlc_inst = MACRLCParamList.numelt; // Get num L1 instances config_getlist( &L1ParamList,NULL,0, NULL); RC.nb_nr_L1_inst = L1ParamList.numelt; @@ -1006,27 +1549,32 @@ void NRRCConfig(void) { } + int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) { int J, l; char *address = NULL; char *cidr = NULL; - //int num_gnbs = 0; //int num_component_carriers = 0; int j,k = 0; int32_t gnb_id = 0; paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + ////////// Identification parameters paramdef_t GNBParams[] = GNBPARAMS_DESC; paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; /* get global parameters, defined outside any section in the config file */ config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); - - //paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0}; + NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(NR_ServingCellConfigCommon_t)); + uint64_t ssb_bitmap=0xff; + memset((void*)scc,0,sizeof(NR_ServingCellConfigCommon_t)); + prepare_scc(scc); + paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc); + paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0}; AssertFatal(i < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt, "Failed to parse config file %s, %uth attribute %s \n", - RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS); + RC.config_file_name, i, GNB_CONFIG_STRING_ACTIVE_GNBS); if (GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt > 0) { // Output a list of all gNBs. @@ -1036,10 +1584,10 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) { for (k = 0; k < GNBParamList.numelt; k++) { if (GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr == NULL) { // Calculate a default eNB ID - if (EPC_MODE_ENABLED) { + if (AMF_MODE_ENABLED) { uint32_t hash; - hash = s1ap_generate_eNB_id (); - gnb_id = k + (hash & 0xFFFF8); + hash = ngap_generate_gNB_id (); + gnb_id = k + (hash & 0xFFFFFF8); } else { gnb_id = k; } @@ -1096,19 +1644,28 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) { "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n", X2AP_REGISTER_ENB_REQ(msg_p).mnc); - X2AP_REGISTER_ENB_REQ (msg_p).num_cc = 1; - J = 0; - X2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = 78; //ccparams_nr_x2.nr_band; //78 - X2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = 3600000000; //ccparams_nr_x2.downlink_frequency; //3600000000 - X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = 0; //(unsigned int) ccparams_nr_x2.uplink_frequency_offset; //0 - X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= 0; //ccparams_nr_x2.Nid_cell; //0 - X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= 106; //ccparams_nr_x2.N_RB_DL; //106 + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); - X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD; - - //Temp out - /*X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency, ccparams_lte.N_RB_DL); - X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency + ccparams_lte.uplink_frequency_offset, ccparams_lte.N_RB_DL);*/ + config_getlist(&SCCsParamList, NULL, 0, aprefix); + if (SCCsParamList.numelt > 0) { + sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0); + config_get( SCCsParams,sizeof(SCCsParams)/sizeof(paramdef_t),aprefix); + fix_scc(scc,ssb_bitmap); + } + X2AP_REGISTER_ENB_REQ (msg_p).num_cc = SCCsParamList.numelt; + for (J = 0; J < SCCsParamList.numelt ; J++) { + X2AP_REGISTER_ENB_REQ (msg_p).nr_band[J] = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; //nr_band; //78 + X2AP_REGISTER_ENB_REQ (msg_p).nrARFCN[J] = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; + X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; //0 + X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= *scc->physCellId; //0 + X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;//106 + X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD; + LOG_I(X2AP, "gNB configuration parameters: nr_band: %d, nr_ARFCN: %d, DL_RBs: %d, num_cc: %d \n", + X2AP_REGISTER_ENB_REQ (msg_p).nr_band[J], + X2AP_REGISTER_ENB_REQ (msg_p).nrARFCN[J], + X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J], + X2AP_REGISTER_ENB_REQ (msg_p).num_cc); + } sprintf(aprefix,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k); config_getlist( &X2ParamList,X2Params,sizeof(X2Params)/sizeof(paramdef_t),aprefix); @@ -1138,26 +1695,34 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) { { int t_reloc_prep = 0; int tx2_reloc_overall = 0; + int t_dc_prep = 0; + int t_dc_overall = 0; paramdef_t p[] = { { "t_reloc_prep", "t_reloc_prep", 0, iptr:&t_reloc_prep, defintval:0, TYPE_INT, 0 }, - { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 } + { "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 }, + { "t_dc_prep", "t_dc_prep", 0, iptr:&t_dc_prep, defintval:0, TYPE_INT, 0 }, + { "t_dc_overall", "t_dc_overall", 0, iptr:&t_dc_overall, defintval:0, TYPE_INT, 0 } }; config_get(p, sizeof(p)/sizeof(paramdef_t), aprefix); if (t_reloc_prep <= 0 || t_reloc_prep > 10000 || - tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000) { - LOG_E(X2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000]\n"); + tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000 || + t_dc_prep <= 0 || t_dc_prep > 10000 || + t_dc_overall <= 0 || t_dc_overall > 20000) { + LOG_E(X2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000] and [0 < t_dc_prep <= 10000] and [0 < t_dc_overall <= 20000]\n"); exit(1); } X2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep; X2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall; + X2AP_REGISTER_ENB_REQ (msg_p).t_dc_prep = t_dc_prep; + X2AP_REGISTER_ENB_REQ (msg_p).t_dc_overall = t_dc_overall; } // SCTP SETTING X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; - if (EPC_MODE_ENABLED) { + if (AMF_MODE_ENABLED) { sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_SCTP_CONFIG); config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix); X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); @@ -1189,4 +1754,463 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) { return 0; } +int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i) { + int k; + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + paramdef_t GNBParams[] = GNBPARAMS_DESC; + paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; + config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); + int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; + AssertFatal (i < num_gnbs, + "Failed to parse config file no %uth element in %s \n",i, GNB_CONFIG_STRING_ACTIVE_GNBS); + if (num_gnbs > 0) { + // Output a list of all eNBs. + config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); + AssertFatal(GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr != NULL, + "gNB id %u is not defined in configuration file\n",i); + F1AP_SETUP_REQ (msg_p).num_cells_available = 0; + + for (k=0; k eth_params_n.remote_addr); + LOG_I(GNB_APP,"FIAP: CU_ip4_address in DU %p, strlen %d\n",F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4_address,(int)strlen(RC.nrmac[k]->eth_params_n.remote_addr)); + F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv6 = 0; + F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4 = 1; + //strcpy(F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv6_address, ""); + strcpy(F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4_address, RC.nrmac[k]->eth_params_n.remote_addr); + LOG_I(GNB_APP,"F1AP: DU_ip4_address in DU %s\n",RC.nrmac[k]->eth_params_n.my_addr); + LOG_I(GNB_APP,"FIAP: DU_ip4_address in DU %p, strlen %d\n",F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4_address,(int)strlen(RC.nrmac[k]->eth_params_n.my_addr)); + F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv6 = 0; + F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4 = 1; + //strcpy(F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv6_address, ""); + strcpy(F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4_address, RC.nrmac[k]->eth_params_n.my_addr); + //strcpy(F1AP_SETUP_REQ (msg_p).CU_ip_address[l].ipv6_address,*(F1ParamList.paramarray[l][ENB_CU_IPV6_ADDRESS_IDX].strptr)); + sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_SCTP_CONFIG); + config_get(SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix); + F1AP_SETUP_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); + F1AP_SETUP_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); + gNB_RRC_INST *rrc = RC.nrrrc[k]; + // wait until RRC cell information is configured + int cell_info_configured = 0; + + do { + LOG_I(GNB_APP,"ngran_gNB_DU: Waiting for basic cell configuration\n"); + usleep(100000); + pthread_mutex_lock(&rrc->cell_info_mutex); + cell_info_configured = rrc->cell_info_configured; + pthread_mutex_unlock(&rrc->cell_info_mutex); + } while (cell_info_configured == 0); + + rrc->configuration.mcc[0] = F1AP_SETUP_REQ (msg_p).mcc[k]; + rrc->configuration.mnc[0] = F1AP_SETUP_REQ (msg_p).mnc[k]; + rrc->configuration.tac = F1AP_SETUP_REQ (msg_p).tac[k]; + rrc->nr_cellid = F1AP_SETUP_REQ (msg_p).nr_cellid[k]; + F1AP_SETUP_REQ (msg_p).nr_pci[k] = *rrc->configuration.scc->physCellId; + F1AP_SETUP_REQ (msg_p).num_ssi[k] = 0; + + if (rrc->configuration.scc->tdd_UL_DL_ConfigurationCommon) { + LOG_I(GNB_APP,"ngran_DU: Configuring Cell %d for TDD\n",k); + F1AP_SETUP_REQ (msg_p).fdd_flag = 0; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.nr_arfcn = rrc->configuration.scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.scs = rrc->configuration.scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.nrb = rrc->configuration.scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.num_frequency_bands = 1; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.nr_band[0] = *rrc->configuration.scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.sul_active = 0; + } else { + /***************** for test *****************/ + LOG_I(GNB_APP,"ngran_DU: Configuring Cell %d for FDD\n",k); + F1AP_SETUP_REQ (msg_p).fdd_flag = 1; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_nr_arfcn = 26200UL; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nr_arfcn = 26200UL; + // For LTE use scs field to carry prefix type and number of antennas + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_scs = 0; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_scs = 0; + // use nrb field to hold LTE N_RB_DL (0...5) + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nrb = 3; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nrb = 3; + // RK: we need to check there value for FDD's frequency_bands DL/UL + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_num_frequency_bands = 1; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nr_band[0] = 7; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_num_frequency_bands = 1; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_nr_band[0] = 7; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_num_sul_frequency_bands = 0; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nr_sul_band[0] = 7; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_num_sul_frequency_bands = 0; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_nr_sul_band[0] = 7; + F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.sul_active = 0; + /***************** for test *****************/ + } + + F1AP_SETUP_REQ (msg_p).measurement_timing_information[k] = "0"; + F1AP_SETUP_REQ (msg_p).ranac[k] = 0; + F1AP_SETUP_REQ (msg_p).mib[k] = rrc->carrier.MIB; + F1AP_SETUP_REQ (msg_p).sib1[k] = rrc->carrier.SIB1; + F1AP_SETUP_REQ (msg_p).mib_length[k] = rrc->carrier.sizeof_MIB; + F1AP_SETUP_REQ (msg_p).sib1_length[k] = rrc->carrier.sizeof_SIB1; + break; + } + } + } + return 0; +} + +int du_check_plmn_identity(rrc_gNB_carrier_data_t *carrier,uint16_t mcc,uint16_t mnc,uint8_t mnc_digit_length) { + NR_SIB1_t *sib1 = carrier->siblock1->message.choice.c1->choice.systemInformationBlockType1; + AssertFatal(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->plmn_IdentityList.list.count > 0, + "plmn info isn't there\n"); + AssertFatal(mnc_digit_length == 2 || mnc_digit_length == 3, + "impossible mnc_digit_length %d\n", mnc_digit_length); + NR_PLMN_Identity_t *plmn_Identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0] + ->plmn_IdentityList.list.array[0]; + + // check if mcc is different and return failure if so + if (mcc != + ((*plmn_Identity->mcc->list.array[0])*100)+ + ((*plmn_Identity->mcc->list.array[1])*10) + + (*plmn_Identity->mcc->list.array[2])) { + LOG_E(GNB_APP, "mcc in F1AP_SETUP_RESP message is different from mcc in DU \n"); + return(0); + } + + // check that mnc digit length is different and return failure if so + if (mnc_digit_length != plmn_Identity->mnc.list.count) { + LOG_E(GNB_APP, "mnc(length: %d) in F1AP_SETUP_RESP message is different from mnc(length: %d) in DU \n", + mnc_digit_length, plmn_Identity->mnc.list.count); + return 0; + } + + // check that 2 digit mnc is different and return failure if so + if (mnc_digit_length == 2 && + (mnc != + (*plmn_Identity->mnc.list.array[0]*10) + + (*plmn_Identity->mnc.list.array[1]))) { + LOG_E(GNB_APP, "mnc(%d) in F1AP_SETUP_RESP message is different from mnc(%ld%ld) in DU \n", + mnc, *plmn_Identity->mnc.list.array[0], *plmn_Identity->mnc.list.array[1]); + return(0); + } + else if (mnc_digit_length == 3 && + (mnc != + (*plmn_Identity->mnc.list.array[0]*100) + + (*plmn_Identity->mnc.list.array[1]*10) + + (*plmn_Identity->mnc.list.array[2]))) { + LOG_E(GNB_APP, "mnc(%d) in F1AP_SETUP_RESP message is different from mnc(%ld%ld%ld) in DU \n", + mnc, *plmn_Identity->mnc.list.array[0], *plmn_Identity->mnc.list.array[1], *plmn_Identity->mnc.list.array[2]); + return(0); + } + + // if we're here, the mcc/mnc match so return success + return(1); +} + +void du_extract_and_decode_SI(int inst, int si_ind, uint8_t *si_container, int si_container_length) { + gNB_RRC_INST *rrc = RC.nrrrc[inst]; + rrc_gNB_carrier_data_t *carrier = &rrc->carrier; + NR_BCCH_DL_SCH_Message_t *bcch_message ; + AssertFatal(si_ind == 0, "Can only handle a single SI block for now\n"); + LOG_I(GNB_APP, "rrc inst %d: Trying to decode SI block %d @ %p, length %d\n", inst, si_ind, si_container, si_container_length); + // point to first SI block + bcch_message = &carrier->systemInformation; + asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + &asn_DEF_NR_BCCH_DL_SCH_Message, + (void **)&bcch_message, + (const void *)si_container, + si_container_length); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + AssertFatal(1==0, "[GNB_APP][NR_RRC inst %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", + inst, + dec_rval.consumed ); + } + + if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) { + switch (bcch_message->message.choice.c1->present) { + case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1: + AssertFatal(1 == 0, "Should have received SIB1 from CU\n"); + break; + + case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: + { + NR_SystemInformation_t *si = bcch_message->message.choice.c1->choice.systemInformation; + + if (si->criticalExtensions.present == NR_SystemInformation__criticalExtensions_PR_systemInformation) { + for (int i = 0; i < si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count; i++) { + LOG_I(GNB_APP, "Extracting SI %d/%d\n", i, si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count); + SystemInformation_IEs__sib_TypeAndInfo__Member *typeAndInfo; + typeAndInfo = si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.array[i]; + + switch(typeAndInfo->present) { + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_NOTHING: + AssertFatal(0, "Should have received SIB2 SIB3 from CU\n"); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB2 in CU F1AP_SETUP_RESP message\n", inst); + carrier->sib2 = typeAndInfo->choice.sib2; + carrier->SIB23 = (uint8_t *)malloc(64); + memcpy((void *)carrier->SIB23, (void *)si_container, si_container_length); + carrier->sizeof_SIB23 = si_container_length; + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3: + carrier->sib3 = typeAndInfo->choice.sib3; + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB3 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib4: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB4 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib5: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB5 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib6: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB6 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib7: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB7 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib8: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB8 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib9: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB9 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib10_v1610: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB10 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib11_v1610: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB11 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib12_v1610: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB12 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib13_v1610: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB13 in CU F1AP_SETUP_RESP message\n", inst); + break; + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib14_v1610: + LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB14 in CU F1AP_SETUP_RESP message\n", inst); + break; + default: + AssertFatal(1 == 0,"Shouldn't have received this SI %d\n", typeAndInfo->present); + break; + } + } + } + + break; + } + + case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: + AssertFatal(0, "Should have received SIB1 from CU\n"); + break; + } + } else AssertFatal(1 == 0, "No SI messages\n"); +} + +void configure_gnb_du_mac(int inst) { + gNB_RRC_INST *rrc = RC.nrrrc[inst]; + // LOG_I(GNB_APP,"Configuring MAC/L1 %d, carrier->sib2 %p\n", inst, &carrier->sib2->radioResourceConfigCommon); + LOG_I(GNB_APP,"Configuring gNB DU MAC/L1 %d \n", inst); + rrc_mac_config_req_gNB(rrc->module_id, + rrc->configuration.ssb_SubcarrierOffset, + rrc->configuration.pdsch_AntennaPorts, + rrc->configuration.pusch_AntennaPorts, + rrc->configuration.sib1_tda, + rrc->configuration.scc, + NULL, + 0, + 0, // rnti + (NR_CellGroupConfig_t *)NULL + ); +} + + +int gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp) { + int i, j, si_ind; + int ret=0; + LOG_I(GNB_APP, "cells_to_activate %d, RRC instances %d\n", + resp->num_cells_to_activate, RC.nb_nr_inst); + + for (j = 0; j < resp->num_cells_to_activate; j++) { + for (i = 0; i < RC.nb_nr_inst; i++) { + rrc_gNB_carrier_data_t *carrier = &RC.nrrrc[i]->carrier; + // identify local index of cell j by nr_cellid, plmn identity and physical cell ID + LOG_I(GNB_APP, "Checking cell %d, rrc inst %d : rrc->nr_cellid %lx, resp->nr_cellid %lx\n", + j, i, RC.nrrrc[i]->nr_cellid, resp->cells_to_activate[j].nr_cellid); + + if (RC.nrrrc[i]->nr_cellid == resp->cells_to_activate[j].nr_cellid && + (du_check_plmn_identity(carrier, resp->cells_to_activate[j].mcc, resp->cells_to_activate[j].mnc, resp->cells_to_activate[j].mnc_digit_length)>0 && + resp->cells_to_activate[j].nrpci == carrier->physCellId)) { + // copy system information and decode it + for (si_ind=0; si_indcells_to_activate[j].num_SI; si_ind++) { + + du_extract_and_decode_SI(i, + si_ind, + resp->cells_to_activate[j].SI_container[2+si_ind], + resp->cells_to_activate[j].SI_container_length[2+si_ind]); + } + + // perform MAC/L1 common configuration + configure_gnb_du_mac(i); + ret++; + } else { + LOG_E(GNB_APP, "F1 Setup Response not matching\n"); + } + } + } + return(ret); +} + +int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update) { + int i, j, si_ind, ret=0; + LOG_I(GNB_APP, "cells_to_activate %d, RRC instances %d\n", + gnb_cu_cfg_update->num_cells_to_activate, RC.nb_nr_inst); + + for (j = 0; j < gnb_cu_cfg_update->num_cells_to_activate; j++) { + for (i = 0; i < RC.nb_nr_inst; i++) { + rrc_gNB_carrier_data_t *carrier = &RC.nrrrc[i]->carrier; + // identify local index of cell j by nr_cellid, plmn identity and physical cell ID + LOG_I(GNB_APP, "Checking cell %d, rrc inst %d : rrc->nr_cellid %lx, gnb_cu_cfg_updatenr_cellid %lx\n", + j, i, RC.nrrrc[i]->nr_cellid, gnb_cu_cfg_update->cells_to_activate[j].nr_cellid); + + if (RC.nrrrc[i]->nr_cellid == gnb_cu_cfg_update->cells_to_activate[j].nr_cellid && + (du_check_plmn_identity(carrier, gnb_cu_cfg_update->cells_to_activate[j].mcc, gnb_cu_cfg_update->cells_to_activate[j].mnc, gnb_cu_cfg_update->cells_to_activate[j].mnc_digit_length)>0 && + gnb_cu_cfg_update->cells_to_activate[j].nrpci == carrier->physCellId)) { + // copy system information and decode it + for (si_ind=0; si_indcells_to_activate[j].num_SI; si_ind++) { + + du_extract_and_decode_SI(i, + si_ind, + gnb_cu_cfg_update->cells_to_activate[j].SI_container[2+si_ind], + gnb_cu_cfg_update->cells_to_activate[j].SI_container_length[2+si_ind]); + } + + // perform MAC/L1 common configuration + configure_gnb_du_mac(i); + ret++; + } else { + LOG_E(GNB_APP, "GNB_CU_CONFIGURATION_UPDATE not matching\n"); + } + } + } + MessageDef *msg_ack_p = NULL; + if (ret > 0) { + // generate gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE + msg_ack_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE); + F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).num_cells_failed_to_be_activated = 0; + F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).have_criticality = 0; + F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofTNLAssociations_to_setup =0; + F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofTNLAssociations_failed = 0; + F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofDedicatedSIDeliveryNeededUEs = 0; + itti_send_msg_to_task (TASK_DU_F1, INSTANCE_DEFAULT, msg_ack_p); + + } + else { + // generate gNB_CU_CONFIGURATION_UPDATE_FAILURE + msg_ack_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE); + F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(msg_ack_p).cause = F1AP_CauseRadioNetwork_cell_not_available; + + itti_send_msg_to_task (TASK_DU_F1, INSTANCE_DEFAULT, msg_ack_p); + + } + + return(ret); +} + +void set_node_type(void) { + int j; + paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC; + paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0}; + paramdef_t GNBParams[] = GNBPARAMS_DESC; + paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; + + config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL); + config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); + + if ( MacRLC_ParamList.numelt > 0) { + RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; + for (j=0;j0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n"); + + AssertFatal (gnb_nb <= RC.nb_nr_inst, + "Number of gNB is greater than gNB defined in configuration file (%d/%d)!", + gnb_nb, RC.nb_nr_inst); + + LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst); + + RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *)); + LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc); + + for (gnb_id = 0; gnb_id < RC.nb_nr_inst ; gnb_id++) { + RC.nrrrc[gnb_id] = (gNB_RRC_INST*)malloc(sizeof(gNB_RRC_INST)); + LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, RC.nb_nr_inst); + memset((void *)RC.nrrrc[gnb_id],0,sizeof(gNB_RRC_INST)); + msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, NRRRC_CONFIGURATION_REQ); + RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]); + } + + if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + pdcp_layer_init(); +// nr_DRB_preconfiguration(0x1234); + rrc_init_nr_global_param(); + } +} diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index e2588d9e4d..013997f439 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -39,11 +39,10 @@ #include "platform_constants.h" #include "PHY/defs_eNB.h" #include "s1ap_messages_types.h" +#include "ngap_messages_types.h" +#include "f1ap_messages_types.h" -#ifdef CMAKER #include "rrc_messages_types.h" -#endif - #include "intertask_interface.h" #include "RRC/NR/nr_rrc_defs.h" @@ -91,7 +90,7 @@ typedef struct ru_config_s { uint8_t if_compress; } ru_config_t; */ -extern void RCconfig_RU(void); +extern void NRRCconfig_RU(void); extern void RCconfig_nr_flexran(void); extern void RCconfig_NR_L1(void); extern void RCconfig_nr_macrlc(void); @@ -102,8 +101,12 @@ extern void NRRCConfig(void); //void ru_config_display(void); void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc); -int RCconfig_NR_S1(MessageDef *msg_p, uint32_t i); +int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i); int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i); +int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i); +int gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp); +int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update); +void nr_read_config_and_init(void); #endif /* GNB_CONFIG_H_ */ /** @} */ diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 84045fc622..730b6b85b6 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -78,7 +78,6 @@ typedef enum { #define GNB_CONFIG_STRING_ASN1_VERBOSITY_NONE "none" #define GNB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING "annoying" #define GNB_CONFIG_STRING_ASN1_VERBOSITY_INFO "info" - /* global parameters, not under a specific section */ #define GNB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity" @@ -91,6 +90,7 @@ typedef enum { {GNB_CONFIG_STRING_ASN1_VERBOSITY, NULL, 0, uptr:NULL, defstrval:GNB_CONFIG_STRING_ASN1_VERBOSITY_NONE, TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_ACTIVE_GNBS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRINGLIST, 0} \ } + #define GNB_ASN1_VERBOSITY_IDX 0 #define GNB_ACTIVE_GNBS_IDX 1 @@ -113,29 +113,15 @@ typedef enum { #define GNB_CONFIG_STRING_REMOTE_S_PORTC "remote_s_portc" #define GNB_CONFIG_STRING_LOCAL_S_PORTD "local_s_portd" #define GNB_CONFIG_STRING_REMOTE_S_PORTD "remote_s_portd" +#define GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET "ssb_SubcarrierOffset" +#define GNB_CONFIG_STRING_PDSCHANTENNAPORTS "pdsch_AntennaPorts" +#define GNB_CONFIG_STRING_PUSCHANTENNAPORTS "pusch_AntennaPorts" +#define GNB_CONFIG_STRING_SIB1TDA "sib1_tda" +#define GNB_CONFIG_STRING_DOCSIRS "do_CSIRS" +#define GNB_CONFIG_STRING_NRCELLID "nr_cellid" +#define GNB_CONFIG_STRING_MINRXTXTIME "min_rxtxtime" +#define GNB_CONFIG_STRING_ULPRBBLACKLIST "ul_prbblacklist" -typedef struct ccparams_nr_x2 { - char *frame_type; - int32_t tdd_config; - int32_t tdd_config_s; - int32_t nr_band; - long long int downlink_frequency; - int32_t uplink_frequency_offset; - int32_t Nid_cell; - int32_t N_RB_DL; - } ccparams_nr_x2_t; - - -#define CCPARAMS_NR_X2_DESC(ccparams) { \ - {ENB_CONFIG_STRING_FRAME_TYPE, NULL, 0, strptr:&ccparams.frame_type, defstrval:"TDD", TYPE_STRING, 0}, \ - {ENB_CONFIG_STRING_TDD_CONFIG, NULL, 0, iptr:&ccparams.tdd_config, defintval:3, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_TDD_CONFIG_S, NULL, 0, iptr:&ccparams.tdd_config_s, defintval:0, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_EUTRA_BAND, NULL, 0, iptr:&ccparams.nr_band, defintval:78, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_DOWNLINK_FREQUENCY, NULL, 0, i64ptr:(int64_t *)&ccparams.downlink_frequency, defint64val:3600000000, TYPE_UINT64, 0}, \ - {ENB_CONFIG_STRING_UPLINK_FREQUENCY_OFFSET, NULL, 0, iptr:&ccparams.uplink_frequency_offset, defintval:0, TYPE_INT, 0}, \ - {ENB_CONFIG_STRING_NID_CELL, NULL, 0, iptr:&ccparams.Nid_cell, defintval:0, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_N_RB_DL, NULL, 0, iptr:&ccparams.N_RB_DL, defintval:106, TYPE_UINT, 0} \ -} /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ @@ -145,7 +131,7 @@ typedef struct ccparams_nr_x2 { {GNB_CONFIG_STRING_GNB_ID, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_CELL_TYPE, NULL, 0, strptr:NULL, defstrval:"CELL_MACRO_GNB", TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_GNB_NAME, NULL, 0, strptr:NULL, defstrval:"OAIgNodeB", TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_TRACKING_AREA_CODE, NULL, 0, strptr:NULL, defstrval:"0", TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_TRACKING_AREA_CODE, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_MOBILE_COUNTRY_CODE_OLD, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_MOBILE_NETWORK_CODE_OLD, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_TRANSPORT_S_PREFERENCE, NULL, 0, strptr:NULL, defstrval:"local_mac", TYPE_STRING, 0}, \ @@ -156,7 +142,16 @@ typedef struct ccparams_nr_x2 { {GNB_CONFIG_STRING_REMOTE_S_PORTC, NULL, 0, uptr:NULL, defuintval:50000, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_LOCAL_S_PORTD, NULL, 0, uptr:NULL, defuintval:50001, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_REMOTE_S_PORTD, NULL, 0, uptr:NULL, defuintval:50001, TYPE_UINT, 0}, \ -} +{GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET, NULL, 0, iptr:NULL, defintval:31, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_PDSCHANTENNAPORTS, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_PUSCHANTENNAPORTS, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_SIB1TDA, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_DOCSIRS, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_NRCELLID, NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \ +{GNB_CONFIG_STRING_MINRXTXTIME, NULL, 0, iptr:NULL, defintval:2, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_ULPRBBLACKLIST, NULL, 0, strptr:NULL, defstrval:"", TYPE_STRING, 0} \ +} + #define GNB_GNB_ID_IDX 0 #define GNB_CELL_TYPE_IDX 1 #define GNB_GNB_NAME_IDX 2 @@ -171,6 +166,14 @@ typedef struct ccparams_nr_x2 { #define GNB_REMOTE_S_PORTC_IDX 11 #define GNB_LOCAL_S_PORTD_IDX 12 #define GNB_REMOTE_S_PORTD_IDX 13 +#define GNB_SSB_SUBCARRIEROFFSET_IDX 14 +#define GNB_PDSCH_ANTENNAPORTS_IDX 15 +#define GNB_PUSCH_ANTENNAPORTS_IDX 16 +#define GNB_SIB1_TDA_IDX 17 +#define GNB_DO_CSIRS_IDX 18 +#define GNB_NRCELLID_IDX 19 +#define GNB_MINRXTXTIME_IDX 20 +#define GNB_ULPRBBLACKLIST_IDX 21 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define GNBPARAMS_CHECK { \ @@ -222,38 +225,58 @@ typedef struct ccparams_nr_x2 { } +/* SNSSAI ID configuration */ +#define GNB_CONFIG_STRING_SNSSAI_LIST "snssaiList" +#define GNB_CONFIG_STRING_SLICE_SERIVE_TYPE "sst" +#define GNB_CONFIG_STRING_SLICE_DIFFERENTIATOR "sd" -/* MME configuration parameters section name */ -#define GNB_CONFIG_STRING_MME_IP_ADDRESS "mme_ip_address" +#define GNB_SLICE_SERIVE_TYPE_IDX 0 +#define GNB_SLICE_DIFFERENTIATOR_IDX 1 + +#define GNBSNSSAIPARAMS_DESC { \ +/* optname helpstr paramflags XXXptr def val type numelt */ \ + {GNB_CONFIG_STRING_SLICE_SERIVE_TYPE, "slice serive type", 0, uptr:NULL, defuintval:1, TYPE_UINT, 0}, \ + {GNB_CONFIG_STRING_SLICE_DIFFERENTIATOR, "slice differentiator", 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \ +} + +#define SLICE_SERIVE_TYPE_OKRANGES {1,2,3,4} + +#define SNSSAIPARAMS_CHECK { \ + { .s1 = { config_check_intval, SLICE_SERIVE_TYPE_OKRANGES, 4 } }, \ + { .s5 = { NULL } }, \ +} + +/* AMF configuration parameters section name */ +#define GNB_CONFIG_STRING_AMF_IP_ADDRESS "amf_ip_address" /* SRB1 configuration parameters names */ -#define GNB_CONFIG_STRING_MME_IPV4_ADDRESS "ipv4" -#define GNB_CONFIG_STRING_MME_IPV6_ADDRESS "ipv6" -#define GNB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE "active" -#define GNB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE "preference" -#define GNB_CONFIG_STRING_MME_BROADCAST_PLMN_INDEX "broadcast_plmn_index" +#define GNB_CONFIG_STRING_AMF_IPV4_ADDRESS "ipv4" +#define GNB_CONFIG_STRING_AMF_IPV6_ADDRESS "ipv6" +#define GNB_CONFIG_STRING_AMF_IP_ADDRESS_ACTIVE "active" +#define GNB_CONFIG_STRING_AMF_IP_ADDRESS_PREFERENCE "preference" +#define GNB_CONFIG_STRING_AMF_BROADCAST_PLMN_INDEX "broadcast_plmn_index" /*-------------------------------------------------------------------------------------------------------------------------------------*/ /* MME configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-------------------------------------------------------------------------------------------------------------------------------------*/ -#define GNBS1PARAMS_DESC { \ -{GNB_CONFIG_STRING_MME_IPV4_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_MME_IPV6_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ +#define GNBNGPARAMS_DESC { \ +{GNB_CONFIG_STRING_AMF_IPV4_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_AMF_IPV6_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_AMF_IP_ADDRESS_ACTIVE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_AMF_IP_ADDRESS_PREFERENCE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ } -#define GNB_MME_IPV4_ADDRESS_IDX 0 -#define GNB_MME_IPV6_ADDRESS_IDX 1 -#define GNB_MME_IP_ADDRESS_ACTIVE_IDX 2 -#define GNB_MME_IP_ADDRESS_PREFERENCE_IDX 3 -#define GNB_MME_BROADCAST_PLMN_INDEX 4 +#define GNB_AMF_IPV4_ADDRESS_IDX 0 +#define GNB_AMF_IPV6_ADDRESS_IDX 1 +#define GNB_AMF_IP_ADDRESS_ACTIVE_IDX 2 +#define GNB_AMF_IP_ADDRESS_PREFERENCE_IDX 3 +#define GNB_AMF_BROADCAST_PLMN_INDEX 4 /*---------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------------------------------*/ /* SCTP configuration parameters section name */ @@ -281,11 +304,11 @@ typedef struct ccparams_nr_x2 { /* S1 interface configuration parameters section name */ #define GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG "NETWORK_INTERFACES" -#define GNB_INTERFACE_NAME_FOR_S1_MME_IDX 0 -#define GNB_IPV4_ADDRESS_FOR_S1_MME_IDX 1 -#define GNB_INTERFACE_NAME_FOR_S1U_IDX 2 -#define GNB_IPV4_ADDR_FOR_S1U_IDX 3 -#define GNB_PORT_FOR_S1U_IDX 4 +#define GNB_INTERFACE_NAME_FOR_NG_AMF_IDX 0 +#define GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX 1 +#define GNB_INTERFACE_NAME_FOR_NGU_IDX 2 +#define GNB_IPV4_ADDR_FOR_NGU_IDX 3 +#define GNB_PORT_FOR_NGU_IDX 4 #define GNB_IPV4_ADDR_FOR_X2C_IDX 5 #define GNB_PORT_FOR_X2C_IDX 6 @@ -293,9 +316,15 @@ typedef struct ccparams_nr_x2 { #define GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_S1_MME "GNB_INTERFACE_NAME_FOR_S1_MME" #define GNB_CONFIG_STRING_GNB_IPV4_ADDRESS_FOR_S1_MME "GNB_IPV4_ADDRESS_FOR_S1_MME" #define GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_S1U "GNB_INTERFACE_NAME_FOR_S1U" -#define GNB_CONFIG_STRING_GNB_IPV4_ADDR_FOR_S1U "GNB_IPV4_ADDRESS_FOR_S1U" +#define GNB_CONFIG_STRING_GNB_IPV4_ADDRESS_FOR_S1U "GNB_IPV4_ADDRESS_FOR_S1U" #define GNB_CONFIG_STRING_GNB_PORT_FOR_S1U "GNB_PORT_FOR_S1U" +#define GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_NG_AMF "GNB_INTERFACE_NAME_FOR_NG_AMF" +#define GNB_CONFIG_STRING_GNB_IPV4_ADDRESS_FOR_NG_AMF "GNB_IPV4_ADDRESS_FOR_NG_AMF" +#define GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_NGU "GNB_INTERFACE_NAME_FOR_NGU" +#define GNB_CONFIG_STRING_GNB_IPV4_ADDR_FOR_NGU "GNB_IPV4_ADDRESS_FOR_NGU" +#define GNB_CONFIG_STRING_GNB_PORT_FOR_NGU "GNB_PORT_FOR_NGU" + /* X2 interface configuration parameters names */ #define GNB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C "GNB_IPV4_ADDRESS_FOR_X2C" #define GNB_CONFIG_STRING_ENB_PORT_FOR_X2C "GNB_PORT_FOR_X2C" @@ -305,11 +334,11 @@ typedef struct ccparams_nr_x2 { /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*--------------------------------------------------------------------------------------------------------------------------------------------------*/ #define GNBNETPARAMS_DESC { \ -{GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_S1_MME, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_GNB_IPV4_ADDRESS_FOR_S1_MME, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_S1U, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_GNB_IPV4_ADDR_FOR_S1U, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_GNB_PORT_FOR_S1U, NULL, 0, uptr:NULL, defintval:2152L, TYPE_UINT, 0}, \ +{GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_NG_AMF, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_GNB_IPV4_ADDRESS_FOR_NG_AMF, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_NGU, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_GNB_IPV4_ADDR_FOR_NGU, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_GNB_PORT_FOR_NGU, NULL, 0, uptr:NULL, defintval:2152L, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_ENB_PORT_FOR_X2C, NULL, 0, uptr:NULL, defintval:0L, TYPE_UINT, 0} \ } @@ -321,8 +350,11 @@ typedef struct ccparams_nr_x2 { /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define GNBGTPUPARAMS_DESC { \ +{GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_NGU, NULL, 0, strptr:&gnb_interface_name_for_NGU, defstrval:"lo", TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_GNB_IPV4_ADDR_FOR_NGU, NULL, 0, strptr:&gnb_ipv4_address_for_NGU, defstrval:"127.0.0.1", TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_GNB_PORT_FOR_NGU, NULL, 0, uptr:&gnb_port_for_NGU, defintval:2152, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_GNB_INTERFACE_NAME_FOR_S1U, NULL, 0, strptr:&gnb_interface_name_for_S1U, defstrval:"lo", TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_GNB_IPV4_ADDR_FOR_S1U, NULL, 0, strptr:&gnb_ipv4_address_for_S1U, defstrval:"127.0.0.1", TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_GNB_IPV4_ADDRESS_FOR_S1U, NULL, 0, strptr:&gnb_ipv4_address_for_S1U, defstrval:"127.0.0.1", TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_GNB_PORT_FOR_S1U, NULL, 0, uptr:&gnb_port_for_S1U, defintval:2152, TYPE_UINT, 0} \ } /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ @@ -433,4 +465,34 @@ typedef struct ccparams_nr_x2 { #define CONFIG_HLP_WORKER "coding and FEP worker thread WORKER_DISABLE or WORKER_ENABLE\n" #define CONFIG_HLP_PARALLEL "PARALLEL_SINGLE_THREAD, PARALLEL_RU_L1_SPLIT, or PARALLEL_RU_L1_TRX_SPLIT(RU_L1_TRX_SPLIT by defult)\n" /*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* security configuration */ +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CONFIG_STRING_SECURITY "security" + +#define SECURITY_CONFIG_CIPHERING "ciphering_algorithms" +#define SECURITY_CONFIG_INTEGRITY "integrity_algorithms" +#define SECURITY_CONFIG_DO_DRB_CIPHERING "drb_ciphering" +#define SECURITY_CONFIG_DO_DRB_INTEGRITY "drb_integrity" + +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* security configuration */ +/* optname help paramflags XXXptr defXXXval type numelt */ +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define SECURITY_GLOBALPARAMS_DESC { \ + {SECURITY_CONFIG_CIPHERING, "preferred ciphering algorithms\n", 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST, 0}, \ + {SECURITY_CONFIG_INTEGRITY, "preferred integrity algorithms\n", 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST, 0}, \ + {SECURITY_CONFIG_DO_DRB_CIPHERING, "use ciphering for DRBs", 0, strptr:NULL, defstrval:"yes", TYPE_STRING, 0}, \ + {SECURITY_CONFIG_DO_DRB_INTEGRITY, "use integrity for DRBs", 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ +} + +#define SECURITY_CONFIG_CIPHERING_IDX 0 +#define SECURITY_CONFIG_INTEGRITY_IDX 1 +#define SECURITY_CONFIG_DO_DRB_CIPHERING_IDX 2 +#define SECURITY_CONFIG_DO_DRB_INTEGRITY_IDX 3 + +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + #endif diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 781347abaa..8d4a53da6c 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -51,7 +51,7 @@ #include "LTE_MBSFN-SubframeConfigList.h" #include "LTE_MBSFN-SubframeConfig.h" #include "LTE_PMCH-InfoList-r9.h" - +#include extern RAN_CONTEXT_t RC; extern int l2_init_eNB(void); @@ -337,7 +337,8 @@ config_sib2(int Mod_idP, LTE_ARFCN_ValueEUTRA_t *ul_CArrierFreqP, long *ul_BandwidthP, LTE_AdditionalSpectrumEmission_t *additionalSpectrumEmissionP, - struct LTE_MBSFN_SubframeConfigList *mbsfn_SubframeConfigListP) { + struct LTE_MBSFN_SubframeConfigList *mbsfn_SubframeConfigListP, + int dl_Bandwidth) { nfapi_config_request_t *cfg = &RC.mac[Mod_idP]->config[CC_idP]; cfg->subframe_config.pb.value = radioResourceConfigCommonP->pdsch_ConfigCommon.p_b; cfg->subframe_config.pb.tl.tag = NFAPI_SUBFRAME_CONFIG_PB_TAG; @@ -345,7 +346,7 @@ config_sib2(int Mod_idP, cfg->rf_config.reference_signal_power.value = radioResourceConfigCommonP->pdsch_ConfigCommon.referenceSignalPower; cfg->rf_config.reference_signal_power.tl.tag = NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG; cfg->num_tlv++; - cfg->nfapi_config.max_transmit_power.value = cfg->rf_config.reference_signal_power.value + power_off_dB[cfg->rf_config.dl_channel_bandwidth.value]; + cfg->nfapi_config.max_transmit_power.value = cfg->rf_config.reference_signal_power.value + power_off_dB[dl_Bandwidth]; cfg->nfapi_config.max_transmit_power.tl.tag = NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG; cfg->num_tlv++; cfg->prach_config.configuration_index.value = radioResourceConfigCommonP->prach_Config.prach_ConfigInfo.prach_ConfigIndex; @@ -870,7 +871,8 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, config_sib2(Mod_idP, CC_idP, radioResourceConfigCommon, radioResourceConfigCommon_BR, NULL, ul_Bandwidth, additionalSpectrumEmission, - mbsfn_SubframeConfigList); + mbsfn_SubframeConfigList, + mib->message.dl_Bandwidth); } // mib != NULL if (mobilityControlInfo !=NULL) { diff --git a/openair2/LAYER2/MAC/config_ue.c b/openair2/LAYER2/MAC/config_ue.c index 1c5e706218..f5c12e710d 100644 --- a/openair2/LAYER2/MAC/config_ue.c +++ b/openair2/LAYER2/MAC/config_ue.c @@ -57,6 +57,7 @@ #include "LTE_PMCH-InfoList-r9.h" +#include extern void mac_init_cell_params(int Mod_idP,int CC_idP); extern void phy_reset_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index); @@ -85,10 +86,6 @@ void ue_mac_reset(module_id_t module_idP, uint8_t eNB_index) { ue_init_mac(module_idP); //This will hopefully do the rest of the MAC reset procedure } -int32_t **rxdata; -int32_t **txdata; - - int rrc_mac_config_req_ue(module_id_t Mod_idP, int CC_idP, diff --git a/openair2/LAYER2/MAC/defs_NB_IoT.h b/openair2/LAYER2/MAC/defs_NB_IoT.h index 517f01d1b9..d4945f0182 100644 --- a/openair2/LAYER2/MAC/defs_NB_IoT.h +++ b/openair2/LAYER2/MAC/defs_NB_IoT.h @@ -9,11 +9,9 @@ */ #ifndef __LAYER2_MAC_DEFS_NB_IOT_H__ #define __LAYER2_MAC_DEFS_NB_IOT_H__ -#ifdef USER_MODE #include #include #include -#endif //#include "COMMON/openair_defs.h" #include "COMMON/platform_constants.h" #include "COMMON/mac_rrc_primitives.h" @@ -537,9 +535,6 @@ typedef struct { // global variables -nprach_parameters_NB_IoT_t nprach_list[3]; -//DLSF Table -DLSF_INFO_t DLSF_information; #endif /*__LAYER2_MAC_DEFS_NB_IoT_H__ */ diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 8f5aab99a7..9d07018e2f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -473,7 +473,7 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 4000) { // note: probably ul_failure_timer should be less than UE radio link failure time(see T310/N310/N311) if (NODE_IS_DU(RC.rrc[module_idP]->node_type)) { - MessageDef *m = itti_alloc_new_message(TASK_MAC_ENB, F1AP_UE_CONTEXT_RELEASE_REQ); + MessageDef *m = itti_alloc_new_message(TASK_MAC_ENB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); F1AP_UE_CONTEXT_RELEASE_REQ(m).rnti = rnti; F1AP_UE_CONTEXT_RELEASE_REQ(m).cause = F1AP_CAUSE_RADIO_NETWORK; F1AP_UE_CONTEXT_RELEASE_REQ(m).cause_value = 1; // 1 = F1AP_CauseRadioNetwork_rl_failure @@ -556,10 +556,7 @@ copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { } } -extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); -extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); -extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); -extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); +#include void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, @@ -586,6 +583,23 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, memset(cc[CC_id].vrb_map_UL, 0, 100); cc[CC_id].mcch_active = 0; clear_nfapi_information(RC.mac[module_idP], CC_id, frameP, subframeP); + + /* hack: skip BCH RBs in subframe 0 for DL scheduling, + * because with high MCS we may exceed code rate 0.93 + * when using those RBs (36.213 7.1.7 says the UE may + * skip decoding if the code rate is higher than 0.93) + * TODO: remove this hack, deal with physical bits properly + * i.e. reduce MCS in the scheduler if code rate > 0.93 + */ + if (subframeP == 0) { + int i; + int bw = cc[CC_id].mib->message.dl_Bandwidth; + /* start and count defined for RBs: 6, 15, 25, 50, 75, 100 */ + int start[6] = { 0, 4, 9, 22, 34, 47 }; + int count[6] = { 6, 7, 7, 6, 7, 6 }; + for (i = 0; i < count[bw]; i++) + cc[CC_id].vrb_map[start[bw] + i] = 1; + } } /* Refresh UE list based on UEs dropped by PHY in previous subframe */ @@ -595,16 +609,45 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, CC_id = UE_PCCID(module_idP, UE_id); UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); +/* to be merged with MAC_stats.log generation. probably redundant if (((frameP & 127) == 0) && (subframeP == 0)) { - LOG_I(MAC,"UE rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n", + double total_bler; + if(UE_scheduling_control->pusch_rx_num[CC_id] == 0 && UE_scheduling_control->pusch_rx_error_num[CC_id] == 0) { + total_bler = 0; + } + else { + total_bler = (double)UE_scheduling_control->pusch_rx_error_num[CC_id] / (double)(UE_scheduling_control->pusch_rx_error_num[CC_id] + UE_scheduling_control->pusch_rx_num[CC_id]) * 100; + } + LOG_I(MAC,"UE %x : %s, PHR %d DLCQI %d PUSCH %d PUCCH %d RLC disc %d UL-stat rcv %lu err %lu bler %lf mcsoff %d bsr %u sched %u tbs %lu cnt %u , DL-stat tbs %lu cnt %u rb %u buf %u 1st %u ret %u ri %d\n", rnti, UE_scheduling_control->ul_out_of_sync == 0 ? "in synch" : "out of sync", UE_info->UE_template[CC_id][UE_id].phr_info, UE_scheduling_control->dl_cqi[CC_id], - (5 * UE_scheduling_control->pusch_snr[CC_id] - 640) / 10, - (5 * UE_scheduling_control->pucch1_snr[CC_id] - 640) / 10); + UE_scheduling_control->pusch_snr_avg[CC_id], + UE_scheduling_control->pucch1_snr[CC_id], + UE_scheduling_control->rlc_out_of_resources_cnt, + UE_scheduling_control->pusch_rx_num[CC_id], + UE_scheduling_control->pusch_rx_error_num[CC_id], + total_bler, + UE_scheduling_control->mcs_offset[CC_id], + UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer, + UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus, + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used, +#if defined(PRE_SCD_THREAD) + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, +#else + 0, +#endif + UE_scheduling_control->first_cnt[CC_id], + UE_scheduling_control->ret_cnt[CC_id], + UE_scheduling_control->aperiodic_ri_received[CC_id] + ); } - +*/ RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = -63; if (UE_id == UE_info->list.head) { @@ -914,7 +957,9 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, #if (!defined(PRE_SCD_THREAD)) if (!NODE_IS_DU(RC.rrc[module_idP]->node_type)) { + void rlc_tick(int, int); PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP, module_idP); + rlc_tick(frameP, subframeP); pdcp_run(&ctxt); pdcp_mbms_run(&ctxt); rrc_rx_tx(&ctxt, CC_id); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index d1365b9ac3..8a400af1f3 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -212,13 +212,6 @@ add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP, hi_dci0_req->sfn_sf = sfnsf_add_subframe(frameP, subframeP, sf_ahead_dl); hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST; - if (NFAPI_MODE != NFAPI_MONOLITHIC) { - oai_nfapi_hi_dci0_req(hi_dci0_req); - hi_dci0_req_body->number_of_hi=0; - } - - LOG_D(MAC, "MSG3: HI_DCI0 SFN/SF:%d number_of_dci:%d number_of_hi:%d\n", NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req_body->number_of_dci, hi_dci0_req_body->number_of_hi); - // save UL scheduling information for preprocessor for (j = 0; j < ra->msg3_nb_rb; j++) cc->vrb_map_UL[ra->msg3_first_rb + j] = 1; @@ -483,8 +476,8 @@ void generate_Msg2(module_id_t module_idP, first_rb = 0; vrb_map[first_rb] = 1; vrb_map[first_rb + 1] = 1; - vrb_map[first_rb + 2] = 1; - vrb_map[first_rb + 3] = 1; + //vrb_map[first_rb + 2] = 1; + //vrb_map[first_rb + 3] = 1; memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); @@ -495,12 +488,12 @@ void generate_Msg2(module_id_t module_idP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // RA-RNTI : see Table 4-10 from SCF082 - nFAPI specifications dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 0; // no TPC dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 1; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 2); // This checks if the above DCI allocation is feasible in current subframe if (!CCE_allocation_infeasible(module_idP, CC_idP, 0, subframeP, @@ -519,7 +512,7 @@ void generate_Msg2(module_id_t module_idP, dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = ra->RA_rnti; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 4); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL, first_rb, 2); dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1; // first block @@ -908,7 +901,7 @@ generate_Msg4(module_id_t module_idP, } // rach_resource_type > 0 else { // This is normal LTE case - LOG_I(MAC, "generate_Msg4 ra->Msg4_frame SFN/SF: %d.%d, frameP SFN/SF: %d.%d FOR eNB_Mod: %d \n", ra->Msg4_frame, ra->Msg4_subframe, frameP, subframeP, module_idP); + LOG_D(MAC, "generate_Msg4 ra->Msg4_frame SFN/SF: %d.%d, frameP SFN/SF: %d.%d FOR eNB_Mod: %d \n", ra->Msg4_frame, ra->Msg4_subframe, frameP, subframeP, module_idP); if ((ra->Msg4_frame == frameP) && (ra->Msg4_subframe == subframeP)) { // Get RRCConnectionSetup for Piggyback @@ -925,7 +918,7 @@ generate_Msg4(module_id_t module_idP, module_idP, CC_idP, frameP, subframeP, UE_id, rrc_sdu_length); // AssertFatal(rrc_sdu_length > 0, // "[MAC][eNB Scheduler] CCCH not allocated, rrc_sdu_length: %d\n", rrc_sdu_length); - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RNTI %x)\n", + LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RNTI %x)\n", module_idP, CC_idP, frameP, subframeP, ra->rnti); /// Choose first 4 RBs for Msg4, should really check that these are free! first_rb = 0; @@ -1093,7 +1086,7 @@ generate_Msg4(module_id_t module_idP, } } // CCE Allocation feasible } else { - LOG_I(MAC, + LOG_D(MAC, "eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Delaying Msg4 for RRC Piggyback (RNTI %x)\n", module_idP, CC_idP, frameP, subframeP, ra->rnti); ra->Msg4_subframe ++; @@ -1296,8 +1289,8 @@ initiate_ra_proc(module_id_t module_idP, } LOG_D(MAC, - "[eNB %d][RAPROC] CC_id %d Frame %d, Subframe %d Initiating RA procedure for preamble index %d\n", - module_idP, CC_id, frameP, subframeP, preamble_index); + "[eNB %d][RAPROC] CC_id %d Frame %d, Subframe %d Initiating RA procedure for preamble index %d, timing offset %d\n", + module_idP, CC_id, frameP, subframeP, preamble_index, timing_offset); LOG_D(MAC, "[eNB %d][RAPROC] CC_id %d Frame %d, Subframe %d PRACH resource type %d\n", module_idP, CC_id, frameP, subframeP, rach_resource_type); @@ -1339,6 +1332,9 @@ initiate_ra_proc(module_id_t module_idP, abort(); case 1 : + case 3 : + case 4 : + case 5 : offset = 6; break; } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 1f99f50ece..596d978a98 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -651,7 +651,7 @@ schedule_ue_spec(module_id_t module_idP, eNB_UE_stats->rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); eNB_UE_stats->harq_pid = harq_pid; eNB_UE_stats->harq_round = round_DL; - + eNB_UE_stats->dlsch_rounds[round_DL&7]++; if (eNB_UE_stats->rrc_status < RRC_RECONFIGURED) { ue_sched_ctrl->uplane_inactivity_timer = 0; } @@ -792,7 +792,6 @@ schedule_ue_spec(module_id_t module_idP, // No TX request for retransmission (check if null request for FAPI) } - //eNB_UE_stats->dlsch_trials[round]++; eNB_UE_stats->num_retransmission += 1; eNB_UE_stats->rbs_used_retx = nb_rb; eNB_UE_stats->total_rbs_used_retx += nb_rb; @@ -821,6 +820,7 @@ schedule_ue_spec(module_id_t module_idP, /* reset ta_update */ ue_sched_ctrl->ta_update = 31; + ue_sched_ctrl->ta_update_f = 31.0; } int ta_len = (ta_update != 31) ? 2 : 0; @@ -1050,7 +1050,7 @@ schedule_ue_spec(module_id_t module_idP, // this is the snr // unit is not dBm, it's special from nfapi // converting to dBm - int snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; + int snr = ue_sched_ctrl->pucch1_snr[CC_id]; int target_snr = eNB->puCch10xSnr / 10; // this assumes accumulated tpc // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out @@ -1064,20 +1064,23 @@ schedule_ue_spec(module_id_t module_idP, ue_template->pucch_tpc_tx_frame = frameP; ue_template->pucch_tpc_tx_subframe = subframeP; - if (snr > target_snr + 4) { + if (snr > target_snr + PUCCH_PCHYST) { tpc = 0; //-1 - } else if (snr < target_snr - 4) { + ue_sched_ctrl->pucch_tpc_accumulated[CC_id]--; + } else if (snr < target_snr - PUCCH_PCHYST) { tpc = 2; //+1 + ue_sched_ctrl->pucch_tpc_accumulated[CC_id]--; } else { tpc = 1; //0 } - LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n", + LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d (accumulated %d), snr/target snr %d/%d (normal case)\n", module_idP, frameP, subframeP, harq_pid, tpc, + ue_sched_ctrl->pucch_tpc_accumulated[CC_id], snr, target_snr); } // Po_PUCCH has been updated @@ -1366,6 +1369,7 @@ schedule_ue_spec_br(module_id_t module_idP, /* Reset ta_update */ ue_sched_ctl->ta_update = 31; + ue_sched_ctl->ta_update_f = 31.0; } else { ta_update = 31; } @@ -1684,7 +1688,7 @@ schedule_ue_spec_br(module_id_t module_idP, /* Do PUCCH power control */ /* This is the snr */ /* unit is not dBm, it's special from nfapi, convert to dBm */ - snr = (5 * ue_sched_ctl->pucch1_snr[CC_id] - 640) / 10; + snr = ue_sched_ctl->pucch1_snr[CC_id]; target_snr = mac->puCch10xSnr / 10; /* This assumes accumulated tpc */ /* Make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out */ @@ -1698,9 +1702,9 @@ schedule_ue_spec_br(module_id_t module_idP, UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frameP; UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframeP; - if (snr > target_snr + 4) { + if (snr > target_snr + PUCCH_PCHYST) { tpc = 0; //-1 - } else if (snr < target_snr - 4) { + } else if (snr < target_snr - PUCCH_PCHYST) { tpc = 2; //+1 } else { tpc = 1; //0 diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index f6220fa46d..e9f0b807c4 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -47,7 +47,7 @@ #include "OCG_extern.h" #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" #include "rlc.h" - +#include "common/utils/lte/prach_utils.h" #include "T.h" @@ -61,7 +61,9 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset); /* internal vars */ DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]; int last_dlsch_ue_id[MAX_NUM_CCs] = {-1}; +int last_dlsch_ue_id_volte[MAX_NUM_CCs] = {-1}; int last_ulsch_ue_id[MAX_NUM_CCs] = {-1}; +int last_ulsch_ue_id_volte[MAX_NUM_CCs] = {-1}; #if defined(PRE_SCD_THREAD) uint16_t pre_nb_rbs_required[2][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; @@ -193,7 +195,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( // Initialization for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - dlsch_ue_max_num[CC_id] = (uint16_t)RC.rrc[module_idP]->configuration.radioresourceconfig[CC_id].ue_multiple_max; + dlsch_ue_max_num[CC_id] = eNB->ue_multiple_max; // save origin DL PDU number DL_req = &eNB->DL_req[CC_id].dl_config_request_body; saved_dlsch_dci[CC_id] = DL_req->number_pdu; @@ -1042,48 +1044,6 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, } } -#ifdef TM5 - - // This has to be revisited!!!! - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - i1 = 0; - i2 = 0; - i3 = 0; - - for (j = 0; j < N_RBG[CC_id]; j++) { - if (MIMO_mode_indicator[CC_id][j] == 2) { - i1 = i1 + 1; - } else if (MIMO_mode_indicator[CC_id][j] == 1) { - i2 = i2 + 1; - } else if (MIMO_mode_indicator[CC_id][j] == 0) { - i3 = i3 + 1; - } - } - - if ((i1 < N_RBG[CC_id]) && (i2 > 0) && (i3 == 0)) { - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions = - PHY_vars_eNB_g[Mod_id][CC_id]-> - check_for_SUMIMO_transmissions + 1; - } - - if (i3 == N_RBG[CC_id] && i1 == 0 && i2 == 0) { - PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions = - PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions + - 1; - } - - if((i1 < N_RBG[CC_id]) && (i3 > 0)) { - PHY_vars_eNB_g[Mod_id][CC_id]-> - check_for_MUMIMO_transmissions + 1; - } - - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions = - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions + - 1; - } - -#endif - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) { if(dlsch_ue_select[CC_id].list[i].ue_priority == SCH_DL_MSG2) { @@ -1152,7 +1112,6 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // int continue_flag = 0; int32_t snr, target_snr; int32_t tpc = 1; - static int32_t tpc_accumulated = 0; UE_sched_ctrl_t *ue_sched_ctl; int mcs; int i; @@ -1538,7 +1497,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, subframeP, S_DL_SCHEDULED, rnti); - //eNB_UE_stats->dlsch_trials[round]++; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[round]++; UE_info->eNB_UE_stats[CC_id][UE_id].num_retransmission += 1; UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_retx = nb_rb; UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx += nb_rb; @@ -1567,6 +1526,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, /* reset ta_update */ ue_sched_ctl->ta_update = 31; + ue_sched_ctl->ta_update_f = 31.0; } else { ta_update = 31; } @@ -1979,6 +1939,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // store stats eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total; eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[0]++; UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; @@ -1998,32 +1959,33 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // this is the snr eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; /* Unit is not dBm, it's special from nfapi */ - snr = (5 * ue_sched_ctl->pucch1_snr[CC_id] - 640) / 10; - target_snr = eNB->puCch10xSnr / 10; + snr = ue_sched_ctl->pucch1_snr[CC_id]; + target_snr = eNB->puCch10xSnr/10; // this assumes accumulated tpc // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out int32_t framex10psubframe = UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; + int pucch_tpc_interval=10; - if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case - ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around + if (((framex10psubframe+pucch_tpc_interval)<=(frameP*10+subframeP)) || //normal case + ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=pucch_tpc_interval)))) //frame wrap-around if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) { ue_sched_ctl->pucch1_cqi_update[CC_id] = 0; UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP; UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP; - if (snr > target_snr + 4) { + if (snr > target_snr + PUCCH_PCHYST) { tpc = 0; //-1 - tpc_accumulated--; - } else if (snr < target_snr - 4) { + ue_sched_ctl->pucch_tpc_accumulated[CC_id]--; + } else if (snr < target_snr - PUCCH_PCHYST) { tpc = 2; //+1 - tpc_accumulated++; + ue_sched_ctl->pucch_tpc_accumulated[CC_id]++; } else { tpc = 1; //0 } LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n", module_idP,frameP, subframeP,harq_pid,tpc, - tpc_accumulated,snr,target_snr); + ue_sched_ctl->pucch_tpc_accumulated[CC_id],snr,target_snr); } // Po_PUCCH has been updated else { tpc = 1; //0 @@ -2241,7 +2203,6 @@ void ulsch_scheduler_pre_ue_select_fairRR( uint8_t first_ue_id[MAX_NUM_CCs][20]; uint8_t ul_inactivity_num[MAX_NUM_CCs]; uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={{0}}; - // LTE_DL_FRAME_PARMS *frame_parms; uint8_t ulsch_ue_max_num[MAX_NUM_CCs]; uint16_t saved_ulsch_dci[MAX_NUM_CCs]; rnti_t rnti; @@ -2259,7 +2220,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( //save ulsch dci number saved_ulsch_dci[CC_id] = eNB->HI_DCI0_req[CC_id][subframeP].hi_dci0_request_body.number_of_dci; // maximum multiplicity number - ulsch_ue_max_num[CC_id] =RC.rrc[module_idP]->configuration.radioresourceconfig[CC_id].ue_multiple_max; + ulsch_ue_max_num[CC_id] =eNB->ue_multiple_max; cc_id_flag[CC_id] = 0; ue_first_num[CC_id] = 0; ul_inactivity_num[CC_id] = 0; @@ -2286,6 +2247,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( // UL DCI HI_DCI0_req = &eNB->HI_DCI0_req[CC_id][subframeP].hi_dci0_request_body; + if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) { cc_id_flag[CC_id] = 1; HI_DCI0_req->number_of_dci = saved_ulsch_dci[CC_id]; @@ -2300,12 +2262,25 @@ void ulsch_scheduler_pre_ue_select_fairRR( } } + if (mac_eNB_get_rrc_status(module_idP, rnti) == RRC_HO_EXECUTION) { + aggregation = 4; + + if(get_aggregation(get_bw_index(module_idP, CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0)>4) + aggregation = get_aggregation(get_bw_index(module_idP, CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + }else{ + //aggregation = 2; + aggregation = get_aggregation(get_bw_index(module_idP, CC_id), + UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id], + format0); + } + cc = &eNB->common_channels[CC_id]; //harq_pid harq_pid = subframe2harqpid(cc,(frameP+(sched_subframePUE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; + if ( round > 0 ) { hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; @@ -2331,7 +2306,11 @@ void ulsch_scheduler_pre_ue_select_fairRR( // int bytes_to_schedule = UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes; - if (bytes_to_schedule < 0) bytes_to_schedule = 0; + if (bytes_to_schedule < 0) { + bytes_to_schedule = 0; + UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes = 0; + } + if ( UE_id > last_ulsch_ue_id[CC_id] && ((ulsch_ue_select[CC_id].ue_num+ue_first_num[CC_id]) < ulsch_ue_max_num[CC_id]) ) { if ( bytes_to_schedule > 0 ) { @@ -2350,10 +2329,8 @@ void ulsch_scheduler_pre_ue_select_fairRR( UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); - - if ( ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) || - ((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(rrc_status < RRC_CONNECTED)) || - ((UE_sched_ctl->cqi_req_timer>300)&&((rrc_status >= RRC_CONNECTED))) ) { + if ( ((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(rrc_status < RRC_CONNECTED)) || + ((UE_sched_ctl->cqi_req_timer>64)&&((rrc_status >= RRC_CONNECTED))) ) { first_ue_id[CC_id][ue_first_num[CC_id]]= UE_id; first_ue_total[CC_id] [ue_first_num[CC_id]] = 0; ue_first_num[CC_id]++; @@ -2457,16 +2434,29 @@ void ulsch_scheduler_pre_ue_select_fairRR( UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; int bytes_to_schedule = UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes; - if (bytes_to_schedule < 0) bytes_to_schedule = 0; + if (bytes_to_schedule < 0) { + bytes_to_schedule = 0; + UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes = 0; + } rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); + if ( (bytes_to_schedule > 0) || (UE_info->UE_template[CC_id][UE_id].ul_SR > 0) || - ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) || + ((UE_sched_ctl->ul_inactivity_timer>64)&&(UE_sched_ctl->ul_scheduled==0)) || ((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(rrc_status < RRC_CONNECTED)) || - ((UE_sched_ctl->cqi_req_timer>300)&&((rrc_status >= RRC_CONNECTED))) ) { + ((UE_sched_ctl->cqi_req_timer>64)&&((rrc_status >= RRC_CONNECTED))) ) { hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + if (mac_eNB_get_rrc_status(module_idP, rnti) == RRC_HO_EXECUTION) { + aggregation = 4; + + if(get_aggregation(get_bw_index(module_idP, CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0)>4) + aggregation = get_aggregation(get_bw_index(module_idP, CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + }else { + aggregation = get_aggregation(get_bw_index(module_idP, CC_id), + UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id], + format0); + } if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2564,12 +2554,14 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, eNB_MAC_INST *eNB = RC.mac[module_idP]; UE_info_t *UE_info= &eNB->UE_info; UE_TEMPLATE *UE_template = NULL; - LTE_DL_FRAME_PARMS *frame_parms = NULL; uint8_t ue_num_temp; uint8_t total_rbs=0; uint8_t average_rbs; uint16_t first_rb[MAX_NUM_CCs]; - uint8_t mcs; + int8_t mcs; + uint8_t snr; + double bler_filter=0.9; + double bler; uint8_t rb_table_index; uint8_t num_pucch_rb; uint32_t tbs; @@ -2583,18 +2575,17 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, // MCS and RB assgin for ( CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++ ) { cc = &RC.mac[module_idP]->common_channels[CC_id]; - frame_parms = &(RC.eNB[module_idP][CC_id]->frame_parms); - + int N_RB_UL = to_prb(cc->ul_Bandwidth); if (cc->tdd_Config) { //TDD - if (frame_parms->N_RB_UL == 25) { + if (N_RB_UL == 25) { num_pucch_rb = 1; - } else if (frame_parms->N_RB_UL == 50) { + } else if (N_RB_UL == 50) { num_pucch_rb = 2; } else { num_pucch_rb = 3; } } else {//FDD - if (frame_parms->N_RB_UL == 25) { + if (N_RB_UL == 25) { num_pucch_rb = 1; } else { num_pucch_rb = 2; @@ -2619,13 +2610,13 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, continue; } - if (first_rb[CC_id] >= frame_parms->N_RB_UL-num_pucch_rb ) { + if (first_rb[CC_id] >= N_RB_UL-num_pucch_rb ) { LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n", module_idP,frameP,subframeP,UE_id,UE_RNTI(CC_id,UE_id),CC_id); break; } - total_rbs = frame_parms->N_RB_UL-num_pucch_rb-first_rb[CC_id]; + total_rbs = N_RB_UL-num_pucch_rb-first_rb[CC_id]; average_rbs = (int)round((double)total_rbs/(double)ue_num_temp); if ( average_rbs < 3 ) { @@ -2663,35 +2654,82 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, } else { UE_template = &UE_info->UE_template[CC_id][UE_id]; - if ( UE_info->UE_sched_ctrl[UE_id].phr_received == 1 ) { - mcs = 20; - } else { - mcs = 10; + int32_t framex10psubframe = UE_template->pusch_bler_calc_frame*10+UE_template->pusch_bler_calc_subframe; + int pusch_bler_interval=50; + double total_bler; + + if(UE_info->UE_sched_ctrl[UE_id].pusch_rx_num[CC_id] == 0 && UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num[CC_id] == 0) { + total_bler = 0; + } + else { + total_bler = (double)UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num[CC_id] / (double)(UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num[CC_id] + UE_info->UE_sched_ctrl[UE_id].pusch_rx_num[CC_id]) * 100; + } + + if (((framex10psubframe+pusch_bler_interval)<=(frameP*10+subframeP)) || //normal case + ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=pusch_bler_interval)))) { //frame wrap-around + + UE_template->pusch_bler_calc_frame=frameP; + UE_template->pusch_bler_calc_subframe=subframeP; + + int pusch_rx_num_diff = UE_info->UE_sched_ctrl[UE_id].pusch_rx_num[CC_id] - UE_info->UE_sched_ctrl[UE_id].pusch_rx_num_old[CC_id]; + int pusch_rx_error_num_diff = UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num[CC_id] - UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num_old[CC_id]; + + if((pusch_rx_num_diff == 0) && (pusch_rx_error_num_diff == 0)) { /* first rx case or no rx among interval time */ + bler = UE_info->UE_sched_ctrl[UE_id].pusch_bler[CC_id]; + } + else { + bler = (double)pusch_rx_error_num_diff / (double)(pusch_rx_num_diff + pusch_rx_error_num_diff) * 100; + } + UE_info->UE_sched_ctrl[UE_id].pusch_bler[CC_id] = UE_info->UE_sched_ctrl[UE_id].pusch_bler[CC_id] * bler_filter + bler * (1.0-bler_filter); + UE_info->UE_sched_ctrl[UE_id].pusch_rx_num_old[CC_id] = UE_info->UE_sched_ctrl[UE_id].pusch_rx_num[CC_id]; + UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num_old[CC_id] = UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num[CC_id]; + + if (eNB->use_mcs_offset == 1) { + if(bler < eNB->bler_lower) { + if(UE_info->UE_sched_ctrl[UE_id].mcs_offset[CC_id] !=0) { + UE_info->UE_sched_ctrl[UE_id].mcs_offset[CC_id]--; + } + } + if(bler >= eNB->bler_upper) { + UE_info->UE_sched_ctrl[UE_id].mcs_offset[CC_id]++; + if(UE_info->UE_sched_ctrl[UE_id].mcs_offset[CC_id] >= 20) { + UE_info->UE_sched_ctrl[UE_id].mcs_offset[CC_id]=20; + } + } + } + } + snr = UE_info->UE_sched_ctrl[UE_id].pusch_snr_avg[CC_id]; + + mcs = 20 - UE_info->UE_sched_ctrl[UE_id].mcs_offset[CC_id]; + if(mcs < 6) { + mcs = 6; } if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_FIRST ) { int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes; - if (bytes_to_schedule < 0) bytes_to_schedule = 0; + if (bytes_to_schedule < 0) { + bytes_to_schedule = 0; + UE_template->scheduled_ul_bytes = 0; + } if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ul_total_buffer > 0 ) { rb_table_index = 2; tbs = get_TBS_UL(mcs,rb_table[rb_table_index]); - tx_power= estimate_ue_tx_power(tbs*8,rb_table[rb_table_index],0,frame_parms->Ncp,0); + tx_power= estimate_ue_tx_power(0,tbs*8,rb_table[rb_table_index],0,cc->Ncp,0); while ( (((UE_template->phr_info - tx_power) < 0 ) || (tbs > bytes_to_schedule)) && (mcs > 3) ) { mcs--; tbs = get_TBS_UL(mcs,rb_table[rb_table_index]); - tx_power= estimate_ue_tx_power(tbs*8,rb_table[rb_table_index],0,frame_parms->Ncp,0); + tx_power= estimate_ue_tx_power(0,tbs*8,rb_table[rb_table_index],0,cc->Ncp,0); } - while ( (tbs < bytes_to_schedule) && (rb_table[rb_table_index]<(frame_parms->N_RB_UL-num_pucch_rb-first_rb[CC_id])) && - ((UE_template->phr_info - tx_power) > 0) && (rb_table_index < 32 )) { + while ( (tbs < bytes_to_schedule) && (rb_table[rb_table_index]<(N_RB_UL-num_pucch_rb-first_rb[CC_id])) && + ((UE_template->phr_info - tx_power) > 0) && (rb_table_index < eNB->max_ul_rb_index )) { rb_table_index++; tbs = get_TBS_UL(mcs,rb_table[rb_table_index]); - tx_power= estimate_ue_tx_power(tbs*8,rb_table[rb_table_index],0,frame_parms->Ncp,0); + tx_power= estimate_ue_tx_power(0,tbs*8,rb_table[rb_table_index],0,cc->Ncp,0); } - if ( rb_table[rb_table_index]<3 ) { rb_table_index=2; } @@ -2719,6 +2757,10 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; } + LOG_D(MAC,"[eNB %hu] frame %u subframe %u, UE %d/%x CC %d snr %hhu snr_inst %hhu mcs %hhd mcs_offset %hhu bler %lf total_bler %lf ( %lu %lu ) rb_num %hhu phr_info %hhd tx_power %hd bsr %d estimated_ul_buffer %d scheduled_ul_bytes %d\n", + module_idP,frameP,subframeP,UE_id,UE_RNTI(CC_id,UE_id),CC_id, snr, UE_info->UE_sched_ctrl[UE_id].pusch_snr[CC_id], mcs, UE_info->UE_sched_ctrl[UE_id].mcs_offset[CC_id], UE_info->UE_sched_ctrl[UE_id].pusch_bler[CC_id], + total_bler, UE_info->UE_sched_ctrl[UE_id].pusch_rx_num[CC_id], UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num[CC_id], rb_table[rb_table_index-1], UE_template->phr_info, tx_power, bytes_to_schedule, UE_template->estimated_ul_buffer, UE_template->scheduled_ul_bytes); + } else { if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) { // assigne RBS( 6 RBs) @@ -2728,11 +2770,12 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } else { // assigne RBS( 3 RBs) +/* first_rb[CC_id] = first_rb[CC_id] + 3; UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3; UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; - UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; - } + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; +*/ } } } else if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE ) { // assigne RBS( 3 RBs) @@ -2834,12 +2877,10 @@ schedule_ulsch_fairRR(module_id_t module_idP, frame_t frameP, ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]; memset(ulsch_ue_select, 0, sizeof(ulsch_ue_select)); - LTE_DL_FRAME_PARMS *frame_parms ; for (CC_id=0; CC_idcommon_channels[CC_id]; - frame_parms= &RC.eNB[module_idP][CC_id]->frame_parms; - + int N_RB_UL=to_prb(cc->ul_Bandwidth); // output of scheduling, the UE numbers in RBs, where it is in the code??? // check if RA (Msg3) is active in this subframeP, if so skip the PRBs used for Msg3 // Msg3 is using 1 PRB so we need to increase first_rb accordingly @@ -2849,13 +2890,13 @@ schedule_ulsch_fairRR(module_id_t module_idP, frame_t frameP, ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_MSG3; if (cc->tdd_Config == NULL) { - if(frame_parms->N_RB_UL == 25) { + if(N_RB_UL == 25) { ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = 1; } else { ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = 2; } } else { - switch(frame_parms->N_RB_UL) { + switch(N_RB_UL) { case 25: default: ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = 1; @@ -2879,14 +2920,18 @@ schedule_ulsch_fairRR(module_id_t module_idP, frame_t frameP, } //PRACH - if (is_prach_subframe(frame_parms,sched_frame,sched_subframe)==1) { + if (is_prach_subframe0(cc->tdd_Config!=NULL ? cc->tdd_Config->subframeAssignment : 0,cc->tdd_Config!=NULL ? 1 : 0, + cc->radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex, + sched_frame,sched_subframe)==1) { ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_PRACH; - ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = get_prach_prb_offset( - frame_parms, - frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset, - 0,//tdd_mapindex - frameP); //Nf --> shouldn't it be sched_frame ??? + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = + get_prach_prb_offset(cc->tdd_Config!=NULL ? 1 : 0, + cc->tdd_Config!=NULL ? cc->tdd_Config->subframeAssignment : 0, + to_prb(cc->ul_Bandwidth), + cc->radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex, + cc->radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset, + 0, + sched_frame); ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = 6; ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = -1; ulsch_ue_select[CC_id].ue_num++; @@ -2914,7 +2959,6 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, uint32_t cqi_req,cshift,ndi,tpc; int32_t snr; int32_t target_snr=0; - static int32_t tpc_accumulated=0; int CC_id,ulsch_ue_num; int N_RB_UL; eNB_MAC_INST *eNB = RC.mac[module_idP]; @@ -2933,7 +2977,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu; nfapi_ul_config_request_body_t *ul_req_tmp; nfapi_ul_config_ulsch_harq_information *ulsch_harq_information; - LOG_D(MAC,"entering ulsch preprocesor\n"); + LOG_D(MAC,"entering ulsch preprocesor for %d.%d\n",sched_frame,sched_subframeP); ulsch_scheduler_pre_processor_fairRR(module_idP, frameP, subframeP, @@ -3032,12 +3076,24 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = subframe2harqpid(cc,sched_frame,sched_subframeP); rnti = UE_RNTI(CC_id,UE_id); - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + if (mac_eNB_get_rrc_status(module_idP, rnti) == RRC_HO_EXECUTION) { + aggregation = 4; + if(get_aggregation(get_bw_index(module_idP, CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0)>4) + aggregation = get_aggregation(get_bw_index(module_idP, CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + }else{ + //aggregation = 2; + aggregation = get_aggregation(get_bw_index(module_idP, CC_id), + UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id], + format0); + } LOG_D(MAC,"[eNB %d] frame %d subframe %d,Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n", module_idP,frameP,subframeP,harq_pid,UE_id,rnti,CC_id, aggregation,N_RB_UL); int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes; - if (bytes_to_schedule < 0) bytes_to_schedule = 0; + if (bytes_to_schedule < 0) { + bytes_to_schedule = 0; + UE_template->scheduled_ul_bytes = 0; + } RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = bytes_to_schedule; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO,RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP]); @@ -3051,7 +3107,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, UE_sched_ctrl->cqi_received = 0; UE_sched_ctrl->cqi_req_timer = 0; cqi_req = 0; - }else if (UE_sched_ctrl->cqi_req_timer>30) { + }else if (UE_sched_ctrl->cqi_req_timer>64) { cqi_req = 1; // To be safe , do not ask CQI in special SFs:36.213/7.2.3 CQI definition @@ -3082,23 +3138,24 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, //power control //compute the expected ULSCH RX power (for the stats) // this is the normalized RX power and this should be constant (regardless of mcs - snr = (5 * UE_sched_ctrl->pusch_snr[CC_id] - 640) / 10; + snr = UE_sched_ctrl->pusch_snr_avg[CC_id]; target_snr = eNB->puSch10xSnr / 10; // this assumes accumulated tpc // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe; + int pusch_tpc_interval=500; - if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case - ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) { //frame wrap-around + if (((framex10psubframe+pusch_tpc_interval)<=(frameP*10+subframeP)) || //normal case + ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=pusch_tpc_interval)))) { //frame wrap-around UE_template->pusch_tpc_tx_frame=frameP; UE_template->pusch_tpc_tx_subframe=subframeP; - if (snr > target_snr + 4) { + if (snr > target_snr + PUSCH_PCHYST) { tpc = 0; //-1 - tpc_accumulated--; - } else if (snr < target_snr - 4) { + UE_sched_ctrl->pusch_tpc_accumulated[CC_id]--; + } else if (snr < target_snr - PUSCH_PCHYST) { tpc = 2; //+1 - tpc_accumulated++; + UE_sched_ctrl->pusch_tpc_accumulated[CC_id]++; } else { tpc = 1; //0 } @@ -3109,7 +3166,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, if (tpc!=1) { LOG_D(MAC,"[eNB %d] ULSCH schedulerRR: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n", module_idP,frameP,subframeP,harq_pid,tpc, - tpc_accumulated,snr,target_snr); + UE_sched_ctrl->pusch_tpc_accumulated[CC_id],snr,target_snr); } // new transmission @@ -3122,6 +3179,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, UE_sched_ctrl->cqi_req_timer); ndi = 1-UE_template->oldNDI_UL[harq_pid]; UE_template->oldNDI_UL[harq_pid]=ndi; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[0]++; UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul; @@ -3133,6 +3191,17 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, UE_template->mcs_UL[harq_pid]=10;//cmin (10, openair_daq_vars.target_ue_ul_mcs); rb_table_index=5; // for PHR } + if( (UE_sched_ctrl->ul_scheduled | (1<0 ){ + UE_template->scheduled_ul_bytes -= UE_template->TBS_UL[harq_pid]; + + if (UE_template->scheduled_ul_bytes < 0) { + UE_template->scheduled_ul_bytes = 0; + } + UE_template->estimated_ul_buffer -= UE_template->TBS_UL[harq_pid]; + if (UE_template->estimated_ul_buffer < 0) { + UE_template->estimated_ul_buffer = 0; + } + } UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid]; UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],rb_table[rb_table_index]); @@ -3194,8 +3263,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, nfapi_hi_dci0_request_t *nfapi_hi_dci0_req = &eNB->HI_DCI0_req[CC_id][subframeP]; nfapi_hi_dci0_req->sfn_sf = frameP<<4|subframeP; // sfnsf_add_subframe(sched_frame, sched_subframeP, 0); // sunday! nfapi_hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST; - LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", - harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP); + LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d mcs %d first_rb %d num_rb %d round %d mcs %d sinr %d bler %lf\n", + harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP,UE_template->mcs_UL[harq_pid],first_rb[CC_id],rb_table[rb_table_index],0,UE_template->mcs_UL[harq_pid],UE_sched_ctrl->pusch_snr_avg[CC_id],UE_sched_ctrl->pusch_bler[CC_id]); ul_req_index = 0; dlsch_flag = 0; @@ -3299,6 +3368,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, T_INT(round)); UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + uint8_t mcs_rv = 0; if(rvidx_tab[round&3]==1) { @@ -3309,7 +3379,6 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, mcs_rv = 31; } - UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb); UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED) @@ -3345,8 +3414,9 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; hi_dci0_req->number_of_dci++; // Add UL_config PDUs - LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", - harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP); + LOG_D(MAC,"[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d mcs %d first_rb %d num_rb %d round %d mcs %d sinr %d bler %lf\n", + harq_pid,frameP,subframeP,UE_id,rnti,sched_frame,sched_subframeP,mcs_rv,ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb,ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb,UE_sched_ctrl->round_UL[CC_id][harq_pid],UE_template->mcs_UL[harq_pid],UE_sched_ctrl->pusch_snr_avg[CC_id],UE_sched_ctrl->pusch_bler[CC_id]); + ul_req_index = 0; dlsch_flag = 0; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c index 0c686a6475..1272b16ec0 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c @@ -84,7 +84,7 @@ get_mbsfn_sf_alloction(module_id_t module_idP, uint8_t CC_id, static uint32_t bytes_in_buffer=0; static uint32_t msi_pmch_stop=0; -uint16_t mbms_rab_id=2047;//[8] = {2047,2047,2047,2047,2047,2047,2047,2047}; +rb_id_t mbms_rab_id=2047;//[8] = {2047,2047,2047,2047,2047,2047,2047,2047}; static uint32_t msi_sfs=0; @@ -211,7 +211,7 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, msi_pos++; while((non_mbsfn_SubframeConfig & (0x100 >> msi_pos)) == (0x100>>msi_pos)) msi_pos++; - mbms_mch_i=0; + mbms_mch_i=0; if((subframeP==0)){ x=0; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c index 689db8e208..1e595f11b5 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c @@ -238,7 +238,7 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s //power control //compute the expected ULSCH RX power (for the stats) // this is the snr and this should be constant (regardless of mcs) - snr = (5 * UE_sched_ctrl->pusch_snr[CC_id] - 640) / 10; + snr = UE_sched_ctrl->pusch_snr[CC_id]; // new transmission ndi = 1-UE_template->oldNDI_UL[harq_pid]; UE_template->oldNDI_UL[harq_pid]=ndi; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 89c2ecc83d..d53e0cadd3 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1985,10 +1985,13 @@ find_UE_id(module_id_t mod_idP, { int UE_id; UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; + if(!UE_info) + return -1; for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { if (UE_info->active[UE_id] == TRUE) { - if (UE_info->UE_template[UE_PCCID(mod_idP, UE_id)][UE_id].rnti == rntiP) { + int CC_id = UE_PCCID(mod_idP, UE_id); + if (CC_id>=0 && CC_idUE_template[CC_id][UE_id].rnti == rntiP) { return UE_id; } } @@ -2173,6 +2176,7 @@ add_new_ue(module_id_t mod_idP, ) //------------------------------------------------------------------------------ { + eNB_MAC_INST *eNB = RC.mac[mod_idP]; int UE_id; int i, j; UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; @@ -2215,7 +2219,19 @@ add_new_ue(module_id_t mod_idP, 0, sizeof(eNB_UE_STATS)); UE_info->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; + UE_info->UE_sched_ctrl[UE_id].ta_update_f = 31.0; UE_info->UE_sched_ctrl[UE_id].ta_update = 31; + UE_info->UE_sched_ctrl[UE_id].pusch_snr[cc_idP] = 0; + UE_info->UE_sched_ctrl[UE_id].pusch_cqi_f[cc_idP] = (eNB->puSch10xSnr+640)/5; + UE_info->UE_sched_ctrl[UE_id].pusch_cqi[cc_idP] = (eNB->puSch10xSnr+640)/5; + UE_info->UE_sched_ctrl[UE_id].pusch_snr_avg[cc_idP] = eNB->puSch10xSnr/10; + UE_info->UE_sched_ctrl[UE_id].pusch_rx_num[cc_idP] = 0; + UE_info->UE_sched_ctrl[UE_id].pusch_rx_num_old[cc_idP] = 0; + UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num[cc_idP] = 0; + UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num_old[cc_idP] = 0; + UE_info->UE_sched_ctrl[UE_id].pusch_bler[cc_idP] = 0; + UE_info->UE_sched_ctrl[UE_id].ret_cnt[cc_idP] = 0; + UE_info->UE_sched_ctrl[UE_id].first_cnt[cc_idP] = 0; for (j = 0; j < 8; j++) { UE_info->UE_template[cc_idP][UE_id].oldNDI[j] = 0; @@ -4934,6 +4950,7 @@ cqi_indication(module_id_t mod_idP, { int UE_id = find_UE_id(mod_idP, rntiP); UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; + uint64_t pdu_val = *(uint64_t *) pdu; if (UE_id == -1) { LOG_W(MAC, "cqi_indication: UE %x not found\n", rntiP); @@ -4973,10 +4990,10 @@ cqi_indication(module_id_t mod_idP, subframeP, pdu, rel9->length); - LOG_D(MAC,"Frame %d Subframe %d update CQI:%d\n", + LOG_D(MAC,"Frame %d Subframe %d update CQI:%d pdu 0x%016"PRIx64"\n", frameP, subframeP, - sched_ctl->dl_cqi[CC_idP]); + sched_ctl->dl_cqi[CC_idP],pdu_val); sched_ctl->cqi_req_flag &= (~(1 << subframeP)); sched_ctl->cqi_received = 1; } @@ -5164,7 +5181,7 @@ harq_indication(module_id_t mod_idP, /* don't care about cqi reporting if NACK/DTX is there */ if (channel == 0 && !nack_or_dtx_reported(cc, harq_pdu)) { - sched_ctl->pucch1_snr[CC_idP] = ul_cqi; + sched_ctl->pucch1_snr[CC_idP] = (5 * ul_cqi - 640) / 10; sched_ctl->pucch1_cqi_update[CC_idP] = 1; } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 2de45db856..d4f486f761 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -56,6 +56,8 @@ #include "flexran.pb-c.h" #include "flexran_agent_mac.h" #include +#include +#include "common/utils/lte/prach_utils.h" #include "T.h" @@ -142,29 +144,47 @@ rx_sdu(const module_id_t enb_mod_idP, if (UE_id != -1) { UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; - LOG_D(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu round %d from PHY (rnti %x, UE_id %d) ul_cqi %d\n", + LOG_D(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH (%s) sdu round %d from PHY (rnti %x, UE_id %d) ul_cqi %d, timing_advance %d\n", enb_mod_idP, harq_pid, CC_idP, frameP, subframeP, + sduP==NULL ? "in error" : "OK", UE_scheduling_control->round_UL[CC_idP][harq_pid], current_rnti, UE_id, - ul_cqi); + ul_cqi, + timing_advance); AssertFatal(UE_scheduling_control->round_UL[CC_idP][harq_pid] < 8, "round >= 8\n"); if (sduP != NULL) { UE_scheduling_control->ul_inactivity_timer = 0; UE_scheduling_control->ul_failure_timer = 0; UE_scheduling_control->ul_scheduled &= (~(1 << harq_pid)); + UE_scheduling_control->pusch_rx_num[CC_idP]++; + /* Update with smoothing: 3/4 of old value and 1/4 of new. * This is the logic that was done in the function * lte_est_timing_advance_pusch, maybe it's not necessary? * maybe it's even not correct at all? */ - UE_scheduling_control->ta_update = (UE_scheduling_control->ta_update * 3 + timing_advance) / 4; - UE_scheduling_control->pusch_snr[CC_idP] = ul_cqi; + UE_scheduling_control->ta_update_f = ((double)UE_scheduling_control->ta_update_f * 3 + (double)timing_advance) / 4; + UE_scheduling_control->ta_update = (int)UE_scheduling_control->ta_update_f; + int tmp_snr = (5 * ul_cqi - 640) / 10; + UE_scheduling_control->pusch_snr[CC_idP] = tmp_snr; + + if(tmp_snr > 0 && tmp_snr < 63) { + double snr_filter_tpc=0.7; + int snr_thres_tpc=30; + int diff = UE_scheduling_control->pusch_snr_avg[CC_idP] - UE_scheduling_control->pusch_snr[CC_idP]; + if(abs(diff) < snr_thres_tpc) { + UE_scheduling_control->pusch_cqi_f[CC_idP] = ((double)UE_scheduling_control->pusch_cqi_f[CC_idP] * snr_filter_tpc + (double)ul_cqi * (1-snr_filter_tpc)); + UE_scheduling_control->pusch_cqi[CC_idP] = (int)UE_scheduling_control->pusch_cqi_f[CC_idP]; + UE_scheduling_control->pusch_snr_avg[CC_idP] = (5 * UE_scheduling_control->pusch_cqi[CC_idP] - 640) / 10; + } + } + UE_scheduling_control->ul_consecutive_errors = 0; first_rb = UE_template_ptr->first_rb_ul[harq_pid]; @@ -180,7 +200,8 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->scheduled_ul_bytes = 0; } } else { // sduP == NULL => error - LOG_W(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d, UE_id %d, RNTI %x (len %d)\n", + UE_scheduling_control->pusch_rx_error_num[CC_idP]++; + LOG_D(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d, UE_id %d, RNTI %x (len %d)\n", enb_mod_idP, harq_pid, CC_idP, @@ -193,14 +214,14 @@ rx_sdu(const module_id_t enb_mod_idP, sdu_lenP); if (ul_cqi > 200) { // too high energy pattern - UE_scheduling_control->pusch_snr[CC_idP] = ul_cqi; + UE_scheduling_control->pusch_snr[CC_idP] = (5 * ul_cqi - 640) / 10; LOG_W(MAC, "[MAC] Too high energy pattern\n"); } if (UE_scheduling_control->round_UL[CC_idP][harq_pid] == 3) { UE_scheduling_control->ul_scheduled &= (~(1 << harq_pid)); UE_scheduling_control->round_UL[CC_idP][harq_pid] = 0; - + UE_info->eNB_UE_stats[CC_idP][UE_id].ulsch_errors++; if (UE_scheduling_control->ul_consecutive_errors++ == 10) { UE_scheduling_control->ul_failure_timer = 1; } @@ -217,6 +238,7 @@ rx_sdu(const module_id_t enb_mod_idP, } } else { UE_scheduling_control->round_UL[CC_idP][harq_pid]++; + UE_info->eNB_UE_stats[CC_idP][UE_id].ulsch_rounds[UE_scheduling_control->round_UL[CC_idP][harq_pid]]++; } /* CDRX UL HARQ timers */ @@ -268,17 +290,35 @@ rx_sdu(const module_id_t enb_mod_idP, AssertFatal(mac->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx > 1, "maxHARQ %d should be greater than 1\n", (int) mac->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx); - LOG_D(MAC, "[eNB %d][PUSCH %d] CC_id %d [RAPROC Msg3] Received ULSCH sdu round %d from PHY (rnti %x, RA_id %d) ul_cqi %d\n", + LOG_D(MAC, "[eNB %d][PUSCH %d] CC_id %d [RAPROC Msg3] Received ULSCH sdu (%s) round %d from PHY (rnti %x, RA_id %d) ul_cqi %d, timing advance %d\n", enb_mod_idP, harq_pid, CC_idP, + sduP!=NULL ? "OK" : "in error", ra->msg3_round, current_rnti, RA_id, - ul_cqi); + ul_cqi, + timing_advance); + first_rb = ra->msg3_first_rb; - if (sduP == NULL) { // we've got an error on Msg3 + bool no_sig = true; + if (sduP) { + for (int k = 0; k < sdu_lenP; k++) { + if(sduP[k]!=0) { + no_sig = false; + break; + } + } + } + + if (no_sig || sduP == NULL) { // we've got an error on Msg3 + + if(no_sig) { + LOG_D(MAC,"No signal in Msg3\n"); + } + LOG_D(MAC, "[eNB %d] CC_id %d, RA %d ULSCH in error in round %d/%d\n", enb_mod_idP, CC_idP, @@ -287,7 +327,38 @@ rx_sdu(const module_id_t enb_mod_idP, (int) mac->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx); if (ra->msg3_round >= mac->common_channels[CC_idP].radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx - 1) { + + // Release RNTI of LTE PHY when RA does not succeed + UE_free_list_t *free_list = NULL; + pthread_mutex_lock(&lock_ue_freelist); + free_list = &mac->UE_free_list; + free_list->UE_free_ctrl[free_list->tail_freelist].rnti = current_rnti; + free_list->UE_free_ctrl[free_list->tail_freelist].removeContextFlg = 1; + free_list->UE_free_ctrl[free_list->tail_freelist].raFlag = 1; + free_list->num_UEs++; + mac->UE_release_req.ue_release_request_body.ue_release_request_TLVs_list[mac->UE_release_req.ue_release_request_body.number_of_TLVs].rnti = current_rnti; + mac->UE_release_req.ue_release_request_body.number_of_TLVs++; + free_list->tail_freelist = (free_list->tail_freelist + 1) % (NUMBER_OF_UE_MAX+1); + pthread_mutex_unlock(&lock_ue_freelist); + cancel_ra_proc(enb_mod_idP, CC_idP, frameP, current_rnti); + nfapi_hi_dci0_request_t *hi_dci0_req = NULL; + uint8_t sf_ahead_dl = ul_subframe2_k_phich(&mac->common_channels[CC_idP], subframeP); + hi_dci0_req = &mac->HI_DCI0_req[CC_idP][(subframeP + sf_ahead_dl) % 10]; + nfapi_hi_dci0_request_body_t *hi_dci0_req_body = &hi_dci0_req->hi_dci0_request_body; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi]; + memset((void *) hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; + hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_hi_pdu); + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = first_rb; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 0; + hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 0; + hi_dci0_req_body->number_of_hi++; + hi_dci0_req_body->sfnsf = sfnsf_add_subframe(frameP, subframeP, 0); + hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG; + hi_dci0_req->sfn_sf = sfnsf_add_subframe(frameP, subframeP, sf_ahead_dl); + hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST; } else { if (ra->rach_resource_type > 0) { cancel_ra_proc(enb_mod_idP, CC_idP, frameP, current_rnti); // TODO: Currently we don't support retransmission of Msg3 ( If in error Cancel RA procedure and reattach) @@ -367,7 +438,8 @@ rx_sdu(const module_id_t enb_mod_idP, switch (rx_ces[i]) { // implement and process PHR + CRNTI + BSR case POWER_HEADROOM: if (UE_id != -1) { - UE_template_ptr->phr_info = (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET + (int8_t)(hundred_times_log10_NPRB[UE_template_ptr->nb_rb_ul[harq_pid] - 1] / 100); + /*UE_template_ptr->phr_info = (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET + (int8_t)(hundred_times_log10_NPRB[UE_template_ptr->nb_rb_ul[harq_pid] - 1] / 100);i*/ + UE_template_ptr->phr_info = (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET + estimate_ue_tx_power(0,sdu_lenP*8,UE_template_ptr->nb_rb_ul[harq_pid],0,mac->common_channels[CC_idP].Ncp,0); if (UE_template_ptr->phr_info > 40) { UE_template_ptr->phr_info = 40; @@ -388,7 +460,7 @@ rx_sdu(const module_id_t enb_mod_idP, case CRNTI: old_rnti = (((uint16_t) payload_ptr[0]) << 8) + payload_ptr[1]; old_UE_id = find_UE_id(enb_mod_idP, old_rnti); - LOG_D(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n", + LOG_I(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n", enb_mod_idP, frameP, subframeP, @@ -402,7 +474,7 @@ rx_sdu(const module_id_t enb_mod_idP, /* Receiving CRNTI means that the current rnti has to go away */ if (old_UE_id != -1) { if (mac_eNB_get_rrc_status(enb_mod_idP,old_rnti) == RRC_HO_EXECUTION) { - LOG_I(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) Handover case\n", + LOG_D(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) Handover case\n", enb_mod_idP, frameP, subframeP, @@ -636,7 +708,7 @@ rx_sdu(const module_id_t enb_mod_idP, switch (rx_lcids[i]) { case CCCH: - if (rx_lengths[i] > CCCH_PAYLOAD_SIZE_MAX) { + if ((rx_lengths[i] > CCCH_PAYLOAD_SIZE_MAX) || (rx_lengths[i] < 0) || (rx_lengths[i] > (sdu_lenP - (payload_ptr - sduP)))) { LOG_E(MAC, "[eNB %d/%d] frame %d received CCCH of size %d (too big, maximum allowed is %d, sdu_len %d), dropping packet\n", enb_mod_idP, CC_idP, @@ -647,6 +719,19 @@ rx_sdu(const module_id_t enb_mod_idP, break; } + bool no_sig = true; + for (int k = 0; k < sdu_lenP; k++) { + if(sduP[k]!=0) { + no_sig = false; + break; + } + } + + if(no_sig) { + LOG_D(MAC, "No signal\n"); + break; + } + LOG_D(MAC, "[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH: %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n", enb_mod_idP, CC_idP, @@ -757,6 +842,17 @@ rx_sdu(const module_id_t enb_mod_idP, LOG_T(MAC, "\n"); #endif + if ((rx_lengths[i] > DCH_PAYLOAD_SIZE_MAX) || (rx_lengths[i] < 0) || (rx_lengths[i] > (sdu_lenP - (payload_ptr - sduP)))) { + LOG_E(MAC, "[eNB %d/%d] frame %d received DCCH of size %d (too big, maximum allowed is %d, sdu_len %d), dropping packet\n", + enb_mod_idP, + CC_idP, + frameP, + rx_lengths[i], + DCH_PAYLOAD_SIZE_MAX, + sdu_lenP); + break; + } + if (UE_id != -1) { if (lcgid_updated[UE_template_ptr->lcgidmap[rx_lcids[i]]] == 0) { /* Adjust buffer occupancy of the correponding logical channel group */ @@ -801,8 +897,18 @@ rx_sdu(const module_id_t enb_mod_idP, LOG_T(MAC, "\n"); #endif - if (rx_lcids[i] < NB_RB_MAX) { + if ((rx_lengths[i] > SCH_PAYLOAD_SIZE_MAX) || (rx_lengths[i] < 0) || (rx_lengths[i] > (sdu_lenP - (payload_ptr - sduP)))) { + LOG_E(MAC, "[eNB %d/%d] frame %d received DTCH of size %d (too big, maximum allowed is %d, sdu_len %d), dropping packet\n", + enb_mod_idP, + CC_idP, + frameP, + rx_lengths[i], + DCH_PAYLOAD_SIZE_MAX, + sdu_lenP); + UE_info->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1; + break; + } LOG_D(MAC, "[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n", enb_mod_idP, CC_idP, @@ -812,6 +918,25 @@ rx_sdu(const module_id_t enb_mod_idP, rx_lcids[i]); if (UE_id != -1) { + ue_contextP = rrc_eNB_get_ue_context(RC.rrc[enb_mod_idP], current_rnti); + if (ue_contextP != NULL) { + if (ue_contextP->ue_context.DRB_active[rx_lcids[i] - 2] == 0) { + LOG_E(MAC, "[eNB %d/%d] frame %d received non active DTCH of size %d ( sdu_len %d, lcid %d), dropping packet\n", + enb_mod_idP, + CC_idP, + frameP, + rx_lengths[i], + sdu_lenP,rx_lcids[i]); + UE_info->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1; + break; + } + }else{ + LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", + enb_mod_idP, + CC_idP, + current_rnti); + break; + } /* Adjust buffer occupancy of the correponding logical channel group */ LOG_D(MAC, "[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d, removing from LCGID %ld, %d\n", enb_mod_idP, @@ -835,48 +960,45 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->ul_buffer_info[1] + UE_template_ptr->ul_buffer_info[2] + UE_template_ptr->ul_buffer_info[3]; + if (UE_template_ptr->estimated_ul_buffer == 0) { + UE_template_ptr->scheduled_ul_bytes = 0; + } } - if ((rx_lengths[i] < SCH_PAYLOAD_SIZE_MAX) && (rx_lengths[i] > 0)) { // MAX SIZE OF transport block mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL); UE_info->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; UE_info->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; /* Clear uplane_inactivity_timer */ UE_scheduling_control->uplane_inactivity_timer = 0; /* Reset RRC inactivity timer after uplane activity */ - ue_contextP = rrc_eNB_get_ue_context(RC.rrc[enb_mod_idP], current_rnti); - - if (ue_contextP != NULL) { ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; - } else { - LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", - enb_mod_idP, - CC_idP, - current_rnti); - } - } else { /* rx_length[i] Max size */ - UE_info->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1; - LOG_E(MAC, "[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ", + + } else { // end if (UE_id != -1) + LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ", enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id); } - } else { // end if (UE_id != -1) - LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ", + }else { + LOG_E(MAC, "[eNB %d/%d] frame %d received a invalid LCID of size %d ( sdu_len %d, lcid %d), dropping packet\n", enb_mod_idP, CC_idP, frameP, - rx_lcids[i], - UE_id); - } + rx_lengths[i], + sdu_lenP,rx_lcids[i]); } break; } - + if((sdu_lenP - (payload_ptr - sduP)) >= rx_lengths[i]){ payload_ptr += rx_lengths[i]; + }else{ + LOG_E(MAC,"[eNB %d/%d] frame %d subframe %d rnti %x sdu_len %d remain_len %d rx_lengths %d\n", + enb_mod_idP,CC_idP,frameP,subframeP,rntiP,sdu_lenP,(uint16_t)(sdu_lenP - (payload_ptr - sduP)), rx_lengths[i]); + return; + } } /* CDRX UL HARQ timers */ @@ -1029,6 +1151,10 @@ parse_ulsch_header(unsigned char *mac_header, tb_length, length, mac_header_ptr - mac_header); + if(num_sdus >= NB_RB_MAX){ + LOG_E(MAC,"parse_ulsch_header: num_sdus(%d) reach max\n",num_sdus); + return NULL; + } rx_lcids[num_sdus] = lcid; rx_lengths[num_sdus] = length; num_sdus++; @@ -1036,6 +1162,10 @@ parse_ulsch_header(unsigned char *mac_header, if (lcid == SHORT_PADDING) { mac_header_ptr++; } else { + if(num_ces >= MAX_NUM_CE){ + LOG_E(MAC,"parse_ulsch_header: num_ces(%d) reach max\n",num_ces); + return NULL; + } rx_ces[num_ces] = lcid; num_ces++; mac_header_ptr++; @@ -1212,16 +1342,19 @@ schedule_ulsch(module_id_t module_idP, /* Note: RC.nb_mac_CC[module_idP] should be lower than or equal to NFAPI_CC_MAX */ for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++, cc++) { - LTE_DL_FRAME_PARMS *frame_parms = &RC.eNB[module_idP][CC_id]->frame_parms; - if (is_prach_subframe(frame_parms, sched_frame, sched_subframe)) { - int start_rb = get_prach_prb_offset( - frame_parms, - frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset, - 0, // tdd_mapindex - sched_frame); // Nf + + if (is_prach_subframe0(cc->tdd_Config!=NULL ? cc->tdd_Config->subframeAssignment : 0,cc->tdd_Config!=NULL ? 1 : 0, + cc->radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex, + sched_frame, sched_subframe)) { + int start_rb = get_prach_prb_offset(cc->tdd_Config!=NULL ? 1 : 0, + cc->tdd_Config!=NULL ? cc->tdd_Config->subframeAssignment : 0, + to_prb(cc->ul_Bandwidth), + cc->radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex, + cc->radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset, + 0, // tdd_mapindex + sched_frame); // Nf for (int i = 0; i < 6; i++) - cc[CC_id].vrb_map_UL[start_rb + i] = 1; + cc->vrb_map_UL[start_rb + i] = 1; } /* HACK: let's remove the PUCCH from available RBs @@ -1233,24 +1366,24 @@ schedule_ulsch(module_id_t module_idP, */ switch (to_prb(cc[CC_id].ul_Bandwidth)) { case 25: - cc[CC_id].vrb_map_UL[0] = 1; - cc[CC_id].vrb_map_UL[24] = 1; + cc->vrb_map_UL[0] = 1; + cc->vrb_map_UL[24] = 1; break; case 50: - cc[CC_id].vrb_map_UL[0] = 1; - cc[CC_id].vrb_map_UL[1] = 1; - cc[CC_id].vrb_map_UL[48] = 1; - cc[CC_id].vrb_map_UL[49] = 1; + cc->vrb_map_UL[0] = 1; + cc->vrb_map_UL[1] = 1; + cc->vrb_map_UL[48] = 1; + cc->vrb_map_UL[49] = 1; break; case 100: - cc[CC_id].vrb_map_UL[0] = 1; - cc[CC_id].vrb_map_UL[1] = 1; - cc[CC_id].vrb_map_UL[2] = 1; - cc[CC_id].vrb_map_UL[97] = 1; - cc[CC_id].vrb_map_UL[98] = 1; - cc[CC_id].vrb_map_UL[99] = 1; + cc->vrb_map_UL[0] = 1; + cc->vrb_map_UL[1] = 1; + cc->vrb_map_UL[2] = 1; + cc->vrb_map_UL[97] = 1; + cc->vrb_map_UL[98] = 1; + cc->vrb_map_UL[99] = 1; break; default: @@ -1268,6 +1401,8 @@ schedule_ulsch(module_id_t module_idP, /* * Schedule the DCI0 for ULSCH */ + + void schedule_ulsch_rnti(module_id_t module_idP, int CC_id, @@ -1275,13 +1410,13 @@ schedule_ulsch_rnti(module_id_t module_idP, sub_frame_t subframeP, unsigned char sched_subframeP) { /* TODO: does this need to be static? */ - static int32_t tpc_accumulated = 0; /* values from 0 to 7 can be used for mapping the cyclic shift * (36.211 , Table 5.5.2.1.1-1) */ const uint32_t cshift = 0; eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = mac->common_channels; UE_info_t *UE_info = &mac->UE_info; + //uint8_t aggregation = 2; int sched_frame = frameP; @@ -1399,10 +1534,9 @@ schedule_ulsch_rnti(module_id_t module_idP, /* Power control */ /* * Compute the expected ULSCH RX snr (for the stats) - * This is the normalized RX snr and this should be constant (regardless - * of mcs) Is not in dBm, unit from nfapi, converting to dBm + * */ - const int32_t snr = (5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10; + const int32_t snr = UE_sched_ctrl_ptr->pusch_snr[CC_id]; const int32_t target_snr = mac->puSch10xSnr / 10; /* @@ -1419,12 +1553,12 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_template_ptr->pusch_tpc_tx_frame = frameP; UE_template_ptr->pusch_tpc_tx_subframe = subframeP; - if (snr > target_snr + 4) { + if (snr > target_snr + PUSCH_PCHYST) { tpc = 0; // -1 - tpc_accumulated--; - } else if (snr < target_snr - 4) { + UE_sched_ctrl_ptr->pusch_tpc_accumulated[CC_id]--; + } else if (snr < target_snr - PUSCH_PCHYST) { tpc = 2; // +1 - tpc_accumulated++; + UE_sched_ctrl_ptr->pusch_tpc_accumulated[CC_id]++; } } if (tpc != 1) { @@ -1436,7 +1570,7 @@ schedule_ulsch_rnti(module_id_t module_idP, subframeP, harq_pid, tpc, - tpc_accumulated, + UE_sched_ctrl_ptr->pusch_tpc_accumulated[CC_id], snr, target_snr); } @@ -1490,6 +1624,7 @@ schedule_ulsch_rnti(module_id_t module_idP, const uint8_t ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator const uint8_t mcs = UE_template_ptr->pre_assigned_mcs_ul; UE_template_ptr->oldNDI_UL[harq_pid] = ndi; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[0]++; UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; UE_template_ptr->mcs_UL[harq_pid] = mcs; @@ -1511,8 +1646,6 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs; - while (rb_table[rb_table_index] > 45 && rb_table_index > 0) - rb_table_index--; UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(mcs, rb_table[rb_table_index]); UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; @@ -1560,8 +1693,10 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_template_ptr->cshift[harq_pid] = cshift; /* Setting DCI0 NFAPI struct */ hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[dci_ul_pdu_idx]; + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = UE_template_ptr->pre_first_nb_rb_ul; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = @@ -1983,7 +2118,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, cqi_req = 0; /* Power control: compute the expected ULSCH RX snr (for the stats) */ /* This is the normalized snr and this should be constant (regardless of mcs) */ - snr = (5 * UE_sched_ctrl->pusch_snr[CC_id] - 640) / 10; + snr = UE_sched_ctrl->pusch_snr[CC_id]; target_snr = eNB->puSch10xSnr / 10; /* TODO: target_rx_power was 178, what to put? */ /* This assumes accumulated tpc */ /* Make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out */ @@ -1996,10 +2131,10 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, if (snr > target_snr + 4) { tpc = 0; //-1 - UE_sched_ctrl->tpc_accumulated[CC_id]--; + UE_sched_ctrl->pusch_tpc_accumulated[CC_id]--; } else if (snr < target_snr - 4) { tpc = 2; //+1 - UE_sched_ctrl->tpc_accumulated[CC_id]++; + UE_sched_ctrl->pusch_tpc_accumulated[CC_id]++; } else { tpc = 1; //0 } @@ -2014,7 +2149,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, subframeP, harq_pid, tpc, - UE_sched_ctrl->tpc_accumulated[CC_id], + UE_sched_ctrl->pusch_tpc_accumulated[CC_id], snr, target_snr); } diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 7eccc6222d..cb93c2feb8 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -83,7 +83,7 @@ #define MAX_MAC_INST 16 #define BCCH_PAYLOAD_SIZE_MAX 128 -#define CCCH_PAYLOAD_SIZE_MAX 128 +#define CCCH_PAYLOAD_SIZE_MAX 512 #define PCCH_PAYLOAD_SIZE_MAX 128 #define RAR_PAYLOAD_SIZE_MAX 128 @@ -143,7 +143,10 @@ #define MAX_SUPPORTED_BW 4 /*!\brief CQI values range from 1 to 15 (4 bits) */ #define CQI_VALUE_RANGE 16 - +/*!\brief Hysteresis of PUSCH power control loop */ +#define PUSCH_PCHYST 1 +/*!\brief Hysteresis of PUCCH power control loop */ +#define PUCCH_PCHYST 1 /*!\brief value for indicating BSR Timer is not running */ #define MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) @@ -469,6 +472,7 @@ typedef struct { #define BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */ + /*! \brief Downlink SCH PDU Structure */ typedef struct { uint8_t payload[8][SCH_PAYLOAD_SIZE_MAX]; @@ -489,7 +493,7 @@ typedef struct { /*! \brief Uplink SCH PDU Structure */ typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ + uint8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ uint16_t Pdu_size; } __attribute__ ((__packed__)) ULSCH_PDU; @@ -614,6 +618,8 @@ typedef struct { // here for RX // + + uint32_t ulsch_rounds[4]; uint32_t ulsch_bitrate; // uint32_t ulsch_bytes_rx; @@ -683,6 +689,17 @@ typedef struct { // Length of SDU Got from LC DL uint32_t sdu_length_tx[NB_RB_MAX]; + int lc_bytes_tx[64]; + int dlsch_rounds[8]; + int dlsch_errors; + int dlsch_total_bytes; + + int lc_bytes_rx[64]; + int ulsch_rounds[8]; + int ulsch_errors; + int ulsch_total_bytes_scheduled; + int ulsch_total_bytes_rx; + /// overall // @@ -775,7 +792,6 @@ typedef struct { uint32_t num_mac_sdu_rx; // Length of SDU Got from LC UL - Size array can be refined uint32_t sdu_length_rx[NB_RB_MAX]; - } eNB_UE_STATS; /*! \brief eNB template for UE context information */ @@ -906,6 +922,11 @@ typedef struct { uint32_t pucch_tpc_tx_frame; uint32_t pucch_tpc_tx_subframe; + /// stores the frame where the last bler was calculated + uint32_t pusch_bler_calc_frame; + uint32_t pusch_bler_calc_subframe; + + uint8_t rach_resource_type; uint16_t mpdcch_repetition_cnt; frame_t Msg2_frame; @@ -928,6 +949,8 @@ typedef struct { /// Current DL harq round per harq_pid on each CC uint8_t round[NFAPI_CC_MAX][10]; + uint32_t ret_cnt[NFAPI_CC_MAX]; + uint32_t first_cnt[NFAPI_CC_MAX]; /// Current Active TBs per harq_pid on each CC uint8_t tbcnt[NFAPI_CC_MAX][10]; /// Current UL harq round per harq_pid on each CC @@ -937,6 +960,7 @@ typedef struct { unsigned char rballoc_sub_UE[NFAPI_CC_MAX][N_RBG_MAX]; int pre_dci_dl_pdu_idx; uint16_t ta_timer; + double ta_update_f; int16_t ta_update; uint16_t ul_consecutive_errors; int32_t context_active_timer; @@ -954,17 +978,27 @@ typedef struct { int32_t phr_received; uint8_t periodic_ri_received[NFAPI_CC_MAX]; uint8_t aperiodic_ri_received[NFAPI_CC_MAX]; - uint8_t pucch1_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch1_snr[NFAPI_CC_MAX]; - uint8_t pucch2_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch2_snr[NFAPI_CC_MAX]; - uint8_t pucch3_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch3_snr[NFAPI_CC_MAX]; - uint8_t pusch_snr[NFAPI_CC_MAX]; + int16_t pucch1_cqi_update[NFAPI_CC_MAX]; + int16_t pucch1_snr[NFAPI_CC_MAX]; + int16_t pucch2_cqi_update[NFAPI_CC_MAX]; + int16_t pucch2_snr[NFAPI_CC_MAX]; + int16_t pucch3_cqi_update[NFAPI_CC_MAX]; + int16_t pucch3_snr[NFAPI_CC_MAX]; + double pusch_cqi_f[NFAPI_CC_MAX]; + int16_t pusch_cqi[NFAPI_CC_MAX]; + int16_t pusch_snr[NFAPI_CC_MAX]; + int16_t pusch_snr_avg[NFAPI_CC_MAX]; + uint64_t pusch_rx_num[NFAPI_CC_MAX]; + uint64_t pusch_rx_num_old[NFAPI_CC_MAX]; + uint64_t pusch_rx_error_num[NFAPI_CC_MAX]; + uint64_t pusch_rx_error_num_old[NFAPI_CC_MAX]; + double pusch_bler[NFAPI_CC_MAX]; + uint8_t mcs_offset[NFAPI_CC_MAX]; uint16_t feedback_cnt[NFAPI_CC_MAX]; uint16_t timing_advance; uint16_t timing_advance_r9; - uint8_t tpc_accumulated[NFAPI_CC_MAX]; + int8_t pusch_tpc_accumulated[NFAPI_CC_MAX]; + int8_t pucch_tpc_accumulated[NFAPI_CC_MAX]; uint8_t periodic_wideband_cqi[NFAPI_CC_MAX]; uint8_t periodic_wideband_spatial_diffcqi[NFAPI_CC_MAX]; uint8_t periodic_wideband_pmi[NFAPI_CC_MAX]; @@ -1039,6 +1073,7 @@ typedef struct { /// DRX UL retransmission timer, one per UL HARQ process /* Not implemented yet */ /* End of C-DRX related timers */ + uint32_t rlc_out_of_resources_cnt; } UE_sched_ctrl_t; /*! \brief eNB template for the Random access information */ @@ -1157,6 +1192,8 @@ typedef struct { rnti_t rnti; ///remove UE context flag boolean_t removeContextFlg; + ///remove RA flag + boolean_t raFlag; } UE_free_ctrl_t; /*! \brief REMOVE UE list used by eNB to order UEs/CC for deleting*/ typedef struct { @@ -1323,6 +1360,7 @@ typedef struct { uint8_t FeMBMS_flag; } COMMON_channels_t; /*! \brief top level eNB MAC structure */ + typedef struct eNB_MAC_INST_s { /// Ethernet parameters for northbound midhaul interface eth_params_t eth_params_n; @@ -1416,6 +1454,17 @@ typedef struct eNB_MAC_INST_s { int32_t puSch10xSnr; int32_t puCch10xSnr; + + int max_ul_rb_index; + + int ue_multiple_max; + + int use_mcs_offset; + + double bler_lower; + + double bler_upper; + pthread_t mac_stats_thread; } eNB_MAC_INST; /* diff --git a/openair2/LAYER2/MAC/mac_extern.h b/openair2/LAYER2/MAC/mac_extern.h index cee6066a9e..522dc2721f 100644 --- a/openair2/LAYER2/MAC/mac_extern.h +++ b/openair2/LAYER2/MAC/mac_extern.h @@ -58,13 +58,13 @@ extern unsigned char NB_eNB_INST; extern uint16_t NB_UE_INST; extern uint16_t NB_THREAD_INST; extern unsigned char NB_RN_INST; -extern unsigned short NODE_ID[1]; extern const int cqi_to_mcs[16]; extern uint32_t RRC_CONNECTION_FLAG; extern uint8_t rb_table[34]; +extern rb_id_t mbms_rab_id; #if defined(PRE_SCD_THREAD) @@ -77,4 +77,8 @@ extern eNB_UE_STATS pre_scd_eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; extern mac_rlc_am_muilist_t rlc_am_mui; extern SCHEDULER_MODES global_scheduler_mode; + +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; +extern rb_id_t mbms_rab_id; #endif //DEF_H diff --git a/openair2/LAYER2/MAC/mac_vars.h b/openair2/LAYER2/MAC/mac_vars.h index bd25bd6047..3b51820171 100644 --- a/openair2/LAYER2/MAC/mac_vars.h +++ b/openair2/LAYER2/MAC/mac_vars.h @@ -105,13 +105,11 @@ eNB_ULSCH_INFO eNB_ulsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][MAX_MOBILES_PER_EN eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][MAX_MOBILES_PER_ENB]; // eNBxUE = 8x8 -#ifdef OPENAIR2 unsigned char NB_eNB_INST = 0; uint16_t NB_UE_INST = 0; uint16_t NB_THREAD_INST = 0; unsigned char NB_RN_INST = 0; unsigned char NB_INST = 0; -#endif DCI0_5MHz_TDD_1_6_t UL_alloc_pdu; diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index af6d1a7ac3..a4e924c68b 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -40,8 +40,84 @@ #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" #include "common/ran_context.h" #include "intertask_interface.h" +#include extern RAN_CONTEXT_t RC; +extern int oai_exit; + +void *mac_stats_thread(void *param) { + eNB_MAC_INST *mac = (eNB_MAC_INST *)param; + FILE *fd; + UE_info_t *UE_info = &(mac->UE_info); + + while (!oai_exit) { + sleep(1); + fd=fopen("MAC_stats.log","w+"); + AssertFatal(fd!=NULL,"Cannot open MAC_stats.log\n"); + + for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { + if (UE_info->active[UE_id]) { + int rnti = UE_RNTI(mac->Mod_id, UE_id); + int CC_id = UE_PCCID(mac->Mod_id, UE_id); + UE_sched_ctrl_t *UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); + + double total_bler; + if(UE_scheduling_control->pusch_rx_num[CC_id] == 0 && UE_scheduling_control->pusch_rx_error_num[CC_id] == 0) { + total_bler = 0; + } + else { + total_bler = (double)UE_scheduling_control->pusch_rx_error_num[CC_id] / (double)(UE_scheduling_control->pusch_rx_error_num[CC_id] + UE_scheduling_control->pusch_rx_num[CC_id]) * 100; + } + fprintf(fd,"MAC UE rnti %x : %s, PHR %d DLCQI %d PUSCH %d PUCCH %d RLC disc %d UL-stat rcv %lu err %lu bler %lf (%lf/%lf) total_bler %lf mcsoff %d pre_allocated nb_rb %d, mcs %d, bsr %u sched %u tbs %lu cnt %u , DL-stat tbs %lu cnt %u rb %u buf %u 1st %u ret %u ri %d\n", + rnti, + UE_scheduling_control->ul_out_of_sync == 0 ? "in synch" : "out of sync", + UE_info->UE_template[CC_id][UE_id].phr_info, + UE_scheduling_control->dl_cqi[CC_id], + UE_scheduling_control->pusch_snr/*_avg*/[CC_id], + UE_scheduling_control->pucch1_snr[CC_id], + UE_scheduling_control->rlc_out_of_resources_cnt, + UE_scheduling_control->pusch_rx_num[CC_id], + UE_scheduling_control->pusch_rx_error_num[CC_id], + UE_scheduling_control->pusch_bler[CC_id], + mac->bler_lower,mac->bler_upper,total_bler, + UE_scheduling_control->mcs_offset[CC_id], + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul, + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul, + UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer, + UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus, + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used, +#if defined(PRE_SCD_THREAD) + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, +#else + 0, +#endif + UE_scheduling_control->first_cnt[CC_id], + UE_scheduling_control->ret_cnt[CC_id], + UE_scheduling_control->aperiodic_ri_received[CC_id] + ); + fprintf(fd," ULSCH rounds %d/%d/%d/%d, DLSCH rounds %d/%d/%d/%d, ULSCH errors %d, DLSCH errors %d\n", + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[0], + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[1], + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[2], + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_rounds[3], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[0], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[1], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[2], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_rounds[3], + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_errors, + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_errors); + + + } + } + fclose(fd); + } + return(NULL); +} void init_UE_info(UE_info_t *UE_info) { @@ -128,6 +204,9 @@ void mac_top_init_eNB(void) pdcp_layer_init(); rrc_init_global_param(); + + for (i=0;imac_stats_thread,NULL,mac_stats_thread,(void*)mac[i]); + } void mac_init_cell_params(int Mod_idP, int CC_idP) @@ -219,7 +298,7 @@ void *mac_enb_task(void *arg) case RRC_MAC_DRX_CONFIG_REQ: LOG_I(MAC, "MAC Task Received RRC_MAC_DRX_CONFIG_REQ\n"); /* Set timers and thresholds values in local MAC context of UE */ - eNB_Config_Local_DRX(ITTI_MESSAGE_GET_INSTANCE(received_msg), &received_msg->ittiMsg.rrc_mac_drx_config_req); + eNB_Config_Local_DRX(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.rrc_mac_drx_config_req); break; case TERMINATE_MESSAGE: diff --git a/openair2/LAYER2/MAC/main_ue.c b/openair2/LAYER2/MAC/main_ue.c index e8b0593717..2140d66a10 100644 --- a/openair2/LAYER2/MAC/main_ue.c +++ b/openair2/LAYER2/MAC/main_ue.c @@ -44,9 +44,7 @@ #include "common/ran_context.h" -extern FILL_UL_INFO_MUTEX_t fill_ul_mutex; -extern void openair_rrc_top_init_ue( int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); - +#include void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync) { //init as MR LOG_D(MAC, "[UE %d] Frame %d: PHY Sync to eNB_index %d successful \n", module_idP, frameP, eNB_index); @@ -90,16 +88,6 @@ mac_top_init_ue(int eMBMS_active, char *uecap_xer, UE_mac_inst = NULL; } - // mutex below are used for multiple UE's L2 FAPI simulation. - if (NFAPI_MODE == NFAPI_UE_STUB_PNF) { - pthread_mutex_init(&fill_ul_mutex.rx_mutex,NULL); - pthread_mutex_init(&fill_ul_mutex.crc_mutex,NULL); - pthread_mutex_init(&fill_ul_mutex.sr_mutex,NULL); - pthread_mutex_init(&fill_ul_mutex.harq_mutex,NULL); - pthread_mutex_init(&fill_ul_mutex.cqi_mutex,NULL); - pthread_mutex_init(&fill_ul_mutex.rach_mutex,NULL); - } - LOG_I(MAC, "[MAIN] calling RRC\n"); openair_rrc_top_init_ue(eMBMS_active, uecap_xer, cba_group_active, HO_active); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 6477d60021..bb969668d6 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -69,6 +69,89 @@ int get_rbg_size_last(module_id_t Mod_id, int CC_id) { return RBGsize; } +bool try_allocate_harq_retransmission(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + int UE_id, + int start_rbg, + int *n_rbg_sched, + uint8_t *rbgalloc_mask) { + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + // check whether there are HARQ retransmissions + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + // retransmission: allocate + const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + if (nb_rb == 0) { + return false; + } + int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; + // needs more RBGs than we can allocate + if (nb_rbg > *n_rbg_sched) { + LOG_D(MAC, + "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", + UE_id, nb_rbg, *n_rbg_sched); + return false; + } + // ensure that the number of RBs can be contained by the RBGs (!), i.e. + // if we allocate the last RBG this one should have the full RBGsize + if ((nb_rb % RBGsize) == 0 && nb_rbg == *n_rbg_sched + && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { + LOG_D(MAC, + "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", + UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); + return false; + } + const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) { // cannot allocate CCE + LOG_D(MAC, "cannot allocate UE %d: no CCE can be allocated\n", UE_id); + return false; + } + /* if nb_rb is not multiple of RBGsize, then last RBG must be free + * (it will be allocated just below) + */ + if (nb_rb % RBGsize && !rbgalloc_mask[N_RBG-1]) { + LOG_E(MAC, "retransmission: last RBG already allocated (this should not happen)\n"); + return false; + } + ue_ctrl->pre_dci_dl_pdu_idx = idx; + // retransmissions: directly allocate + *n_rbg_sched -= nb_rbg; + ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; + if (nb_rb % RBGsize) { + /* special case: if nb_rb is not multiple of RBGsize, then allocate last RBG. + * If we instead allocated another RBG then we will retransmit with more + * RBs and the UE will not accept it. + * (This has been seen in a test with cots UEs, if not true, then change + * code as needed.) + * At this point rbgalloc_mask[N_RBG-1] == 1 due to the test above. + */ + ue_ctrl->rballoc_sub_UE[CC_id][N_RBG-1] = 1; + rbgalloc_mask[N_RBG-1] = 0; + nb_rbg--; + } + for (; nb_rbg > 0; start_rbg++) { + if (!rbgalloc_mask[start_rbg]) + continue; + ue_ctrl->rballoc_sub_UE[CC_id][start_rbg] = 1; + rbgalloc_mask[start_rbg] = 0; + nb_rbg--; + } + LOG_D(MAC, + "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " + "retx nb_rb %d pre_nb_available_rbs %d\n", + frame, subframe, *n_rbg_sched, UE_id, + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], + ue_ctrl->pre_nb_available_rbs[CC_id]); + return true; +} + void *rr_dl_setup(void) { void *data = malloc(sizeof(int)); *(int *) data = 0; @@ -115,64 +198,25 @@ int rr_dl_run(module_id_t Mod_id, const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; - if (round != 8) { // retransmission: allocate - const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - if (nb_rb == 0) - goto skip_ue; - int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; - // needs more RBGs than we can allocate - if (nb_rbg > n_rbg_sched) { - LOG_D(MAC, - "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", - UE_id, nb_rbg, n_rbg_sched); - goto skip_ue; + if (round != 8) { + bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe, + UE_id, rbg, &n_rbg_sched, + rbgalloc_mask); + if (r) { + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } - // ensure that the number of RBs can be contained by the RBGs (!), i.e. - // if we allocate the last RBG this one should have the full RBGsize - if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched - && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { - LOG_D(MAC, - "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", - UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); - goto skip_ue; - } - const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; - const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); - if (idx < 0) - goto skip_ue; // cannot allocate CCE - ue_ctrl->pre_dci_dl_pdu_idx = idx; - // retransmissions: directly allocate - n_rbg_sched -= nb_rbg; - ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; - for (; nb_rbg > 0; rbg++) { - if (!rbgalloc_mask[rbg]) - continue; - ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; - rbgalloc_mask[rbg] = 0; - nb_rbg--; - } - LOG_D(MAC, - "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " - "round %d retx nb_rb %d pre_nb_available_rbs %d\n", - frame, subframe, n_rbg_sched, UE_id, round, - UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], - ue_ctrl->pre_nb_available_rbs[CC_id]); - /* if there are no more RBG to give, return */ - if (n_rbg_sched <= 0) - return 0; - max_num_ue--; - /* if there are no UEs that can be allocated anymore, return */ - if (max_num_ue == 0) - return n_rbg_sched; - for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } else { if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) { *cur_UE = UE_id; cur_UE = &UE_sched.next[UE_id]; } } - -skip_ue: UE_id = next_ue_list_looped(UE_list, UE_id); } while (UE_id != *start_ue); *cur_UE = -1; // mark end @@ -187,11 +231,12 @@ skip_ue: cur_UE = &UE_sched.head; while (*cur_UE >= 0 && max_num_ue > 0) { const int UE_id = *cur_UE; - cur_UE = &UE_sched.next[UE_id]; // go to next const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); if (idx < 0) { LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id); + // SKIP this UE in the list by marking the next as the current + *cur_UE = UE_sched.next[UE_id]; continue; } UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; @@ -200,6 +245,7 @@ skip_ue: const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total; rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize); max_num_ue--; + cur_UE = &UE_sched.next[UE_id]; // go to next } *cur_UE = -1; // not all UEs might be allocated, mark end @@ -284,56 +330,19 @@ int pf_wbcqi_dl_run(module_id_t Mod_id, const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; - if (round != 8) { // retransmission: allocate - const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - if (nb_rb == 0) - continue; - int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; - // needs more RBGs than we can allocate - if (nb_rbg > n_rbg_sched) { - LOG_D(MAC, - "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", - UE_id, nb_rbg, n_rbg_sched); - continue; + if (round != 8) { + bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe, + UE_id, rbg, &n_rbg_sched, + rbgalloc_mask); + if (r) { + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } - // ensure that the number of RBs can be contained by the RBGs (!), i.e. - // if we allocate the last RBG this one should have the full RBGsize - if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched - && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { - LOG_D(MAC, - "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", - UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); - continue; - } - const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; - const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); - if (idx < 0) - continue; // cannot allocate CCE - ue_ctrl->pre_dci_dl_pdu_idx = idx; - // retransmissions: directly allocate - n_rbg_sched -= nb_rbg; - ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; - for (; nb_rbg > 0; rbg++) { - if (!rbgalloc_mask[rbg]) - continue; - ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; - rbgalloc_mask[rbg] = 0; - nb_rbg--; - } - LOG_D(MAC, - "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " - "round %d retx nb_rb %d pre_nb_available_rbs %d\n", - frame, subframe, n_rbg_sched, UE_id, round, - UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], - ue_ctrl->pre_nb_available_rbs[CC_id]); - /* if there are no more RBG to give, return */ - if (n_rbg_sched <= 0) - return 0; - max_num_ue--; - /* if there are no UEs that can be allocated anymore, return */ - if (max_num_ue == 0) - return n_rbg_sched; - for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } else { if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) continue; @@ -436,56 +445,19 @@ int mt_wbcqi_dl_run(module_id_t Mod_id, const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; - if (round != 8) { // retransmission: allocate - const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - if (nb_rb == 0) - continue; - int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; - // needs more RBGs than we can allocate - if (nb_rbg > n_rbg_sched) { - LOG_D(MAC, - "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", - UE_id, nb_rbg, n_rbg_sched); - continue; + if (round != 8) { + bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe, + UE_id, rbg, &n_rbg_sched, + rbgalloc_mask); + if (r) { + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } - // ensure that the number of RBs can be contained by the RBGs (!), i.e. - // if we allocate the last RBG this one should have the full RBGsize - if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched - && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { - LOG_D(MAC, - "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", - UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); - continue; - } - const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; - const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); - if (idx < 0) - continue; // cannot allocate CCE - ue_ctrl->pre_dci_dl_pdu_idx = idx; - // retransmissions: directly allocate - n_rbg_sched -= nb_rbg; - ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; - for (; nb_rbg > 0; rbg++) { - if (!rbgalloc_mask[rbg]) - continue; - ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; - rbgalloc_mask[rbg] = 0; - nb_rbg--; - } - LOG_D(MAC, - "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " - "round %d retx nb_rb %d pre_nb_available_rbs %d\n", - frame, subframe, n_rbg_sched, UE_id, round, - UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], - ue_ctrl->pre_nb_available_rbs[CC_id]); - /* if there are no more RBG to give, return */ - if (n_rbg_sched <= 0) - return 0; - max_num_ue--; - /* if there are no UEs that can be allocated anymore, return */ - if (max_num_ue == 0) - return n_rbg_sched; - for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } else { if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) continue; @@ -777,13 +749,13 @@ void calculate_max_mcs_min_rb(module_id_t mod_id, int tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); // fixme: set use_srs flag - *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + *tx_power = estimate_ue_tx_power(0,tbs * 8, rb_table[*rb_index], 0, Ncp, 0); /* find maximum MCS */ while ((phr - *tx_power < 0 || tbs > bytes) && *mcs > 3) { - mcs--; + (*mcs)--; tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); - *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + *tx_power = estimate_ue_tx_power(0,tbs * 8, rb_table[*rb_index], 0, Ncp, 0); } /* find minimum necessary RBs */ @@ -793,7 +765,7 @@ void calculate_max_mcs_min_rb(module_id_t mod_id, && phr - *tx_power > 0) { (*rb_index)++; tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); - *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + *tx_power = estimate_ue_tx_power(0,tbs * 8, rb_table[*rb_index], 0, Ncp, 0); } /* Decrease if we went to far in last iteration */ @@ -848,7 +820,7 @@ int rr_ul_run(module_id_t Mod_id, AssertFatal(num_contig_rb <= 2, "cannot handle more than two contiguous RB regions\n"); UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; const int max_rb = num_contig_rb > 1 ? MAX(rbs[0].length, rbs[1].length) : rbs[0].length; - + eNB_MAC_INST *mac = RC.mac[Mod_id]; /* for every UE: check whether we have to handle a retransmission (and * allocate, if so). If not, compute how much RBs this UE would need */ int rb_idx_required[MAX_MOBILES_PER_ENB]; @@ -856,7 +828,7 @@ int rr_ul_run(module_id_t Mod_id, int num_ue_req = 0; for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; - uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id], + uint8_t harq_pid = subframe2harqpid(&mac->common_channels[CC_id], sched_frame, sched_subframe); if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) { /* this UE has a retransmission, allocate it right away */ @@ -892,11 +864,11 @@ int rr_ul_run(module_id_t Mod_id, } } else { LOG_W(MAC, - "cannot allocate UL retransmission for UE %d (nb_rb %d)\n", - UE_id, - nb_rb); + "%d.%d cannot allocate UL retransmission for UE %d (nb_rb %d, rbs0.length %d, rbs1.length %d,rbs0.start %d,rbs1.start %d)\n", + sched_frame,sched_subframe,UE_id, + nb_rb, rbs[0].length,rbs[1].length,rbs[0].start,rbs[1].start); UE_template->pre_dci_ul_pdu_idx = -1; // do not need CCE - RC.mac[Mod_id]->HI_DCI0_req[CC_id][subframe].hi_dci0_request_body.number_of_dci--; + mac->HI_DCI0_req[CC_id][subframe].hi_dci0_request_body.number_of_dci--; continue; } LOG_D(MAC, "%4d.%d UE %d retx %d RBs at start %d\n", @@ -942,7 +914,9 @@ int rr_ul_run(module_id_t Mod_id, &tx_power); UE_template->pre_assigned_mcs_ul = mcs; - rb_idx_required[UE_id] = rb_table_index; + /* rb_idx_given >= MAX index: limit RBs to value in configuration file + * RBs in the uplink. */ + rb_idx_required[UE_id] = min(mac->max_ul_rb_index, rb_table_index); //UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index]; /* only print log when PHR changed */ static int phr = 0; diff --git a/openair2/LAYER2/MAC/rar_tools.c b/openair2/LAYER2/MAC/rar_tools.c index 23ac209389..740923cc08 100644 --- a/openair2/LAYER2/MAC/rar_tools.c +++ b/openair2/LAYER2/MAC/rar_tools.c @@ -41,7 +41,6 @@ #define DEBUG_RAR extern unsigned int localRIV2alloc_LUT25[512]; -extern unsigned int distRIV2alloc_LUT25[512]; extern unsigned short RIV2nb_rb_LUT25[512]; extern unsigned short RIV2first_rb_LUT25[512]; extern RAN_CONTEXT_t RC; @@ -67,8 +66,10 @@ fill_rar(const module_id_t module_idP, rar[5] = (uint8_t) (ra->rnti & 0xff); //ra->timing_offset = 0; ra->timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps - rar[0] = (uint8_t) (ra->timing_offset >> (2 + 4)); // 7 MSBs of timing advance + divide by 4 - rar[1] = (uint8_t) (ra->timing_offset << (4 - 2)) & 0xf0; // 4 LSBs of timing advance + divide by 4 + //rar[0] = (uint8_t) (ra->timing_offset >> (2 + 4)); // 7 MSBs of timing advance + divide by 4 + //rar[1] = (uint8_t) (ra->timing_offset << (4 - 2)) & 0xf0; // 4 LSBs of timing advance + divide by 4 + rar[0] = (uint8_t) (ra->timing_offset >> (4)); // 7 MSBs of timing advance + divide by 4 + rar[1] = (uint8_t) (ra->timing_offset << (4)) & 0xf0; // 4 LSBs of timing advance + divide by 4 COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; if(N_RB_UL == 25) { diff --git a/openair2/LAYER2/MAC/slicing/slicing.c b/openair2/LAYER2/MAC/slicing/slicing.c index 9c88f6cffb..48dd99afeb 100644 --- a/openair2/LAYER2/MAC/slicing/slicing.c +++ b/openair2/LAYER2/MAC/slicing/slicing.c @@ -336,6 +336,8 @@ void static_dl(module_id_t mod_id, rbgalloc_slice_mask[rbg] = rbgalloc_mask[rbg]; n_rbg_sched += rbgalloc_mask[rbg]; } + if (n_rbg_sched == 0) /* no free RBGs, e.g., taken by RA */ + continue; s->s[i]->dl_algo.run(mod_id, CC_id, @@ -445,6 +447,8 @@ void static_ul(module_id_t mod_id, } if (!last_rb_blocked) rbs[n_contig - 1].length = p->posHigh - rbs[n_contig - 1].start + 1; + if (n_contig == 1 && rbs[0].length == 0) /* no RBs, e.g., taken by RA */ + continue; s->s[i]->ul_algo.run(mod_id, CC_id, diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index e97f1bebdd..21d349ea52 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -72,18 +72,11 @@ extern UL_IND_t *UL_INFO; extern int next_ra_frame; extern module_id_t next_Mod_id; -int mbms_rab_id=2047;//[8] = {2047,2047,2047,2047,2047,2047,2047,2047}; +rb_id_t mbms_rab_id=2047;//[8] = {2047,2047,2047,2047,2047,2047,2047,2047}; static int mbms_mch_i=0; //static int num_msi_per_CSA[28]; -/* - * -#ifndef USER_MODE -#define msg debug_msg -#endif - */ - mapping BSR_names[] = { {"NONE", 0}, {"SHORT BSR", 1}, @@ -1251,65 +1244,6 @@ int ue_query_mch_fembms(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, } - - -#ifdef OLD - // Acount for sf_allocable in CSA - int num_sf_alloc = 0; - - for (l = 0; l < 8; l++) { - if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) - continue; - - if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) - continue; - - uint32_t common_mbsfn_SubframeConfig = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.choice.oneFrame.buf[0]; - - - for (j = 0; j < 6; j++) - num_sf_alloc += ((common_mbsfn_SubframeConfig & (0x80 >> j)) == (0x80 >> j)); - //num_sf_alloc=1; - } - - num_sf_alloc = 10; - - num_non_mbsfn_SubframeConfig = (UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]<<1 | UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]>>7); - int ones=0; - for(j=0; j < 16; j++){ - if(num_non_mbsfn_SubframeConfig & 1) - ones++; - num_non_mbsfn_SubframeConfig>>=1; - } - - for (l = 0; l < 28; l++) { - if (UE_mac_inst[module_idP].pmch_stop_mtch[l] >= 1/*num_sf_alloc*/) { - if (UE_mac_inst[module_idP].pmch_stop_mtch[l] != 2047) { - if (UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch] != NULL){ - mtch_mcs = UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch]->dataMCS_r9; - //int common_mbsfn_alloc_offset = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[0]->radioframeAllocationOffset; - long common_mbsfn_period = 1 << UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[0]->radioframeAllocationPeriod; - long commonSF_AllocPeriod = 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9; - if(UE_mac_inst[module_idP].common_num_sf_alloc >= UE_mac_inst[module_idP].pmch_stop_mtch[l]){ - //LOG_E(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d\n",UE_mac_inst[module_idP].common_num_sf_alloc); - - mtch_mcs = -1; - }/*else - OG_W(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d\n",UE_mac_inst[module_idP].common_num_sf_alloc);*/ - LOG_D(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d num_sf_alloc %d commonSF_AllocPeriod %ld, common_mbsfn_period %ld num_non_mbsfn_SubframeConfig %x ones %d\n",UE_mac_inst[module_idP].common_num_sf_alloc,num_sf_alloc, commonSF_AllocPeriod,common_mbsfn_period,num_non_mbsfn_SubframeConfig,ones); - UE_mac_inst[module_idP].common_num_sf_alloc++; - UE_mac_inst[module_idP].common_num_sf_alloc = UE_mac_inst[module_idP].common_num_sf_alloc % (num_sf_alloc * commonSF_AllocPeriod / common_mbsfn_period-(1+ones)*(commonSF_AllocPeriod/4)); //TODO - } - else - mtch_mcs = -1; - - mch_lcid = (uint8_t)l; - break; - } - } - } -#endif - { // Acount for sf_allocable in Common SF Allocation int num_sf_alloc = 0; @@ -1869,49 +1803,7 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ //} } -#ifdef OLD - // Acount for sf_allocable in CSA - int num_sf_alloc = 0; - for (l = 0; l < 8; l++) { - if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) - continue; - - if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) - continue; - - uint32_t common_mbsfn_SubframeConfig = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.choice.oneFrame.buf[0]; - - for (j = 0; j < 6; j++) - num_sf_alloc += ((common_mbsfn_SubframeConfig & (0x80 >> j)) == (0x80 >> j)); - //num_sf_alloc=1; - } - - for (l = 0; l < 28; l++) { - if (UE_mac_inst[module_idP].pmch_stop_mtch[l] >= 1/*num_sf_alloc*/) { - if (UE_mac_inst[module_idP].pmch_stop_mtch[l] != 2047) { - if (UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch] != NULL){ - mtch_mcs = UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch]->dataMCS_r9; - long common_mbsfn_period = 1 << UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[0]->radioframeAllocationPeriod; - long commonSF_AllocPeriod = 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9; - if(UE_mac_inst[module_idP].common_num_sf_alloc >= UE_mac_inst[module_idP].pmch_stop_mtch[l]){ - //LOG_E(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d\n",UE_mac_inst[module_idP].common_num_sf_alloc); - - mtch_mcs = -1; - }/*else - LOG_W(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d\n",UE_mac_inst[module_idP].common_num_sf_alloc);*/ - UE_mac_inst[module_idP].common_num_sf_alloc++; - UE_mac_inst[module_idP].common_num_sf_alloc = UE_mac_inst[module_idP].common_num_sf_alloc % (num_sf_alloc * commonSF_AllocPeriod / common_mbsfn_period); - } - else - mtch_mcs = -1; - - mch_lcid = (uint8_t)l; - break; - } - } - } -#endif { // Acount for sf_allocable in Common SF Allocation @@ -3064,8 +2956,8 @@ ue_scheduler(const module_id_t module_idP, switch (ITTI_MSG_ID(msg_p)) { case RRC_MAC_CCCH_DATA_REQ: LOG_I(MAC, - "Received %s from %s: instance %d, frameP %d, eNB_index %d\n", - ITTI_MSG_NAME(msg_p), ITTI_MSG_ORIGIN_NAME(msg_p), ITTI_MSG_INSTANCE(msg_p), + "Received %s from %s: instance %ld, frameP %d, eNB_index %d\n", + ITTI_MSG_NAME(msg_p), ITTI_MSG_ORIGIN_NAME(msg_p), ITTI_MSG_DESTINATION_INSTANCE(msg_p), RRC_MAC_CCCH_DATA_REQ(msg_p).frame, RRC_MAC_CCCH_DATA_REQ(msg_p).enb_index); // TODO process CCCH data req. @@ -3099,6 +2991,9 @@ ue_scheduler(const module_id_t module_idP, } } + void rlc_tick(int, int); + rlc_tick(rxFrameP % 1024, rxSubframeP); + //#endif UE_mac_inst[module_idP].txFrame = txFrameP; UE_mac_inst[module_idP].txSubframe = txSubframeP; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_compute_tbs_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c similarity index 65% rename from openair2/LAYER2/NR_MAC_gNB/nr_compute_tbs_common.c rename to openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c index df23b64e07..4fcbd322db 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_compute_tbs_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c @@ -27,76 +27,76 @@ #include "common/utils/nr/nr_common.h" #include +#include "PHY/defs_nr_common.h" //Table 5.1.2.2-2 uint16_t Tbstable_nr[INDEX_MAX_TBS_TABLE] = {24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,208,224,240,256,272,288,304,320,336,352,368,384,408,432,456,480,504,528,552,576,608,640,672,704,736,768,808,848,888,928,984,1032,1064,1128,1160,1192,1224,1256,1288,1320,1352,1416,1480,1544,1608,1672,1736,1800,1864,1928,2024,2088,2152,2216,2280,2408,2472,2536,2600,2664,2728,2792,2856,2976,3104,3240,3368,3496,3624,3752,3824}; uint16_t NPRB_LBRM[7] = {32,66,107,135,162,217,273}; +// Transport block size determination according to 6.1.4.2 of TS 38.214 +// returns the TBS in bits uint32_t nr_compute_tbs(uint16_t Qm, uint16_t R, - uint16_t nb_rb, - uint16_t nb_symb_sch, - uint16_t nb_dmrs_prb, + uint16_t nb_rb, + uint16_t nb_symb_sch, + uint16_t nb_dmrs_prb, uint16_t nb_rb_oh, uint8_t tb_scaling, - uint8_t Nl) + uint8_t Nl) { - uint16_t nbp_re, nb_re; - uint32_t nr_tbs=0; - uint32_t Ninfo, Np_info, C; - uint8_t n, scale; + uint16_t nbp_re, nb_re; + uint32_t nr_tbs=0; + uint32_t Ninfo, Np_info, C; + uint8_t n, scale; - nbp_re = 12 * nb_symb_sch - nb_dmrs_prb - nb_rb_oh; + LOG_D(NR_MAC,"nb_symb_sch %d, nb_dmrs_prb %d, nb_rb_oh %d\n",nb_symb_sch,nb_dmrs_prb,nb_rb_oh); - nb_re = min(156, nbp_re) * nb_rb; - - scale = (R>1024)?11:10; + nbp_re = NR_NB_SC_PER_RB * nb_symb_sch - nb_dmrs_prb - nb_rb_oh; + nb_re = min(156, nbp_re) * nb_rb; + scale = (R>1024)?11:10; + // Intermediate number of information bits + Ninfo = ((nb_re * R * Qm * Nl)>>scale)>>tb_scaling; - // Intermediate number of information bits - Ninfo = ((nb_re * R * Qm * Nl)>>scale)>>tb_scaling; - if (Ninfo <=3824) { - n = max(3, floor(log2(Ninfo)) - 6); - Np_info = max(24, (Ninfo>>n)<= Np_info){ - nr_tbs = Tbstable_nr[i]; - break; - } + if (Ninfo <=3824) { + n = max(3, floor(log2(Ninfo)) - 6); + Np_info = max(24, (Ninfo>>n)<= Np_info){ + nr_tbs = Tbstable_nr[i]; + break; } + } + } else { + n = log2(Ninfo-24)-5; + Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1< 8424){ + C = CEILIDIV((Np_info+24),8424); + nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24; + } else { + nr_tbs = ((CEILIDIV((Np_info+24),8))<<3) - 24; + } } - else { - n = log2(Ninfo-24)-5; - Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1< 8424){ - C = CEILIDIV((Np_info+24),8424); - nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24; - } - else { - nr_tbs = ((CEILIDIV((Np_info+24),8))<<3) - 24; - } + LOG_D(NR_MAC, "In %s: Ninfo %d nbp_re %d nb_re %d Qm %d, R %d, tbs %d\n", __FUNCTION__, Ninfo, nbp_re, nb_re, Qm, R, nr_tbs); - } + return nr_tbs; - } - //printf("Ninfo %d nbp_re %d nb_re %d Qm %d, R %d, tbs %d\n", Ninfo, nbp_re, nb_re, Qm, R, nr_tbs); - return nr_tbs; } //tbslbrm calculation according to 5.4.2.1 of 38.212 uint32_t nr_compute_tbslbrm(uint16_t table, uint16_t nb_rb, - uint8_t Nl, - uint8_t C) + uint8_t Nl) { uint16_t R, nb_re; @@ -104,14 +104,14 @@ uint32_t nr_compute_tbslbrm(uint16_t table, uint8_t Qm; int i; uint32_t nr_tbs=0; - uint32_t Ninfo, Np_info; + uint32_t Ninfo, Np_info, C; uint8_t n; for (i=0; i<7; i++) { - if (NPRB_LBRM[i] >= nb_rb){ - nb_rb_lbrm = NPRB_LBRM[i]; - break; - } + if (NPRB_LBRM[i] >= nb_rb){ + nb_rb_lbrm = NPRB_LBRM[i]; + break; + } } Qm = ((table == 1)? 8 : 6); @@ -136,10 +136,12 @@ uint32_t nr_compute_tbslbrm(uint16_t table, Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1< 8424){ + C = CEILIDIV((Np_info+24),8424); nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24; } else { @@ -150,5 +152,4 @@ uint32_t nr_compute_tbslbrm(uint16_t table, } return nr_tbs; - } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index d8583167dd..4ef0a55c6b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -20,7 +20,7 @@ */ /* \file nr_mac.h - * \brief common MAC data structures, constant, and function prototype + * \brief common MAC data structures and constants * \author R. Knopp, K.H. HSU, G. Casati * \date 2019 * \version 0.1 @@ -36,14 +36,42 @@ #include #include #include +#include +#include "NR_SubcarrierSpacing.h" + +#define NR_SHORT_BSR_TABLE_SIZE 32 +#define NR_LONG_BSR_TABLE_SIZE 256 + +#define TABLE_38213_13_1_NUM_INDEXES 15 +#define TABLE_38213_13_2_NUM_INDEXES 14 +#define TABLE_38213_13_3_NUM_INDEXES 9 +#define TABLE_38213_13_4_NUM_INDEXES 16 +#define TABLE_38213_13_5_NUM_INDEXES 9 +#define TABLE_38213_13_6_NUM_INDEXES 10 +#define TABLE_38213_13_7_NUM_INDEXES 12 +#define TABLE_38213_13_8_NUM_INDEXES 8 +#define TABLE_38213_13_9_NUM_INDEXES 4 +#define TABLE_38213_13_10_NUM_INDEXES 8 +#define TABLE_38213_13_11_NUM_INDEXES 16 +#define TABLE_38213_13_12_NUM_INDEXES 14 + +// Definitions for MAC control and data #define NR_BCCH_DL_SCH 3 // SI - #define NR_BCCH_BCH 5 // MIB - -#define CCCH_PAYLOAD_SIZE_MAX 128 - +#define CCCH_PAYLOAD_SIZE_MAX 512 #define RAR_PAYLOAD_SIZE_MAX 128 +#define MAX_BWP_SIZE 275 + +typedef enum frequency_range_e { + FR1 = 0, + FR2 +} frequency_range_t; + +#define NR_BSR_TRIGGER_NONE (0) /* No BSR Trigger */ +#define NR_BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */ +#define NR_BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */ +#define NR_BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */ // For both DL/UL-SCH // Except: @@ -102,22 +130,22 @@ typedef NR_BSR_SHORT NR_BSR_SHORT_TRUNCATED; // Long BSR for all logical channel group ID typedef struct { - uint8_t Buffer_size7: 8; - uint8_t Buffer_size6: 8; - uint8_t Buffer_size5: 8; - uint8_t Buffer_size4: 8; - uint8_t Buffer_size3: 8; - uint8_t Buffer_size2: 8; - uint8_t Buffer_size1: 8; - uint8_t Buffer_size0: 8; - uint8_t LcgID0: 1; - uint8_t LcgID1: 1; - uint8_t LcgID2: 1; - uint8_t LcgID3: 1; - uint8_t LcgID4: 1; - uint8_t LcgID5: 1; - uint8_t LcgID6: 1; - uint8_t LcgID7: 1; + uint8_t LcgID0: 1; // octet 1 [0] + uint8_t LcgID1: 1; // octet 1 [1] + uint8_t LcgID2: 1; // octet 1 [2] + uint8_t LcgID3: 1; // octet 1 [3] + uint8_t LcgID4: 1; // octet 1 [4] + uint8_t LcgID5: 1; // octet 1 [5] + uint8_t LcgID6: 1; // octet 1 [6] + uint8_t LcgID7: 1; // octet 1 [7] + uint8_t Buffer_size0: 8; // octet 2 [7:0] + uint8_t Buffer_size1: 8; // octet 3 [7:0] + uint8_t Buffer_size2: 8; // octet 4 [7:0] + uint8_t Buffer_size3: 8; // octet 5 [7:0] + uint8_t Buffer_size4: 8; // octet 6 [7:0] + uint8_t Buffer_size5: 8; // octet 7 [7:0] + uint8_t Buffer_size6: 8; // octet 8 [7:0] + uint8_t Buffer_size7: 8; // octet 9 [7:0] } __attribute__ ((__packed__)) NR_BSR_LONG; typedef NR_BSR_LONG NR_BSR_LONG_TRUNCATED; @@ -131,10 +159,10 @@ typedef struct { // single Entry PHR MAC CE // TS 38.321 ch. 6.1.3.8 typedef struct { - uint8_t PH: 6; - uint8_t R1: 2; - uint8_t PCMAX: 6; - uint8_t R2: 6; + uint8_t PH: 6; // octet 1 [5:0] + uint8_t R1: 2; // octet 1 [7:6] + uint8_t PCMAX: 6; // octet 2 [5:0] + uint8_t R2: 2; // octet 2 [7:6] } __attribute__ ((__packed__)) NR_SINGLE_ENTRY_PHR_MAC_CE; @@ -317,12 +345,12 @@ typedef struct { #define DL_SCH_LCID_CON_RES_ID 0x3E #define DL_SCH_LCID_PADDING 0x3F -#define UL_SCH_LCID_CCCH 0x00 +#define UL_SCH_LCID_CCCH1 0x00 #define UL_SCH_LCID_SRB1 0x01 #define UL_SCH_LCID_SRB2 0x02 #define UL_SCH_LCID_SRB3 0x03 #define UL_SCH_LCID_DTCH 0x04 -#define UL_SCH_LCID_CCCH_MSG3 0x21 +#define UL_SCH_LCID_CCCH 0x34 #define UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY 0x35 #define UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT 0x36 #define UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION 0x37 @@ -339,6 +367,108 @@ typedef struct { #define NR_MAX_NUM_LCGID 8 #define MAX_RLC_SDU_SUBHEADER_SIZE 3 +//=========== +// PRACH defs +//=========== + +// =============================================== +// SSB to RO mapping public defines and structures +// =============================================== +#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO +#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot +#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot + +// PRACH occasion details +typedef struct prach_occasion_info { + uint8_t start_symbol; // 0 - 13 (14 symbols in a slot) + uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8) + uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz) + uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) + uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs + uint8_t nb_mapped_ssb; + uint16_t format; // RO preamble format +} prach_occasion_info_t; + +// PRACH occasion slot details +// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency +typedef struct prach_occasion_slot { + prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot + uint8_t nb_of_prach_occasion_in_time; + uint8_t nb_of_prach_occasion_in_freq; +} prach_occasion_slot_t; + +//========= +// DCI defs +//========= + +typedef enum { + NR_DL_DCI_FORMAT_1_0 = 0, + NR_DL_DCI_FORMAT_1_1, + NR_DL_DCI_FORMAT_2_0, + NR_DL_DCI_FORMAT_2_1, + NR_DL_DCI_FORMAT_2_2, + NR_DL_DCI_FORMAT_2_3, + NR_UL_DCI_FORMAT_0_0, + NR_UL_DCI_FORMAT_0_1 +} nr_dci_format_t; + +typedef enum { + NR_RNTI_new = 0, + NR_RNTI_C, + NR_RNTI_RA, + NR_RNTI_P, + NR_RNTI_CS, + NR_RNTI_TC, + NR_RNTI_SP_CSI, + NR_RNTI_SI, + NR_RNTI_SFI, + NR_RNTI_INT, + NR_RNTI_TPC_PUSCH, + NR_RNTI_TPC_PUCCH, + NR_RNTI_TPC_SRS, + NR_RNTI_MCS_C, +} nr_rnti_type_t; + +typedef enum channel_bandwidth_e { + bw_5MHz = 0x1, + bw_10MHz = 0x2, + bw_20MHz = 0x4, + bw_40MHz = 0x8, + bw_80MHz = 0x16, + bw_100MHz = 0x32 +} channel_bandwidth_t; + +typedef enum nr_ssb_and_cset_mux_pattern_type_e { + NR_SSB_AND_CSET_MUX_PATTERN_TYPE1=1, + NR_SSB_AND_CSET_MUX_PATTERN_TYPE2, + NR_SSB_AND_CSET_MUX_PATTERN_TYPE3 +} nr_ssb_and_cset_mux_pattern_type_t; + +typedef enum { + SFN_C_MOD_2_EQ_0, + SFN_C_MOD_2_EQ_1, + SFN_C_IMPOSSIBLE +} SFN_C_TYPE; + +typedef struct Type0_PDCCH_CSS_config_s { + int32_t num_rbs; + int32_t num_symbols; + int32_t rb_offset; // Offset from SSB RB0 + uint32_t type0_pdcch_ss_mux_pattern; + uint16_t frame; + SFN_C_TYPE sfn_c; + uint32_t n_c; + uint32_t n_0; + uint32_t number_of_search_space_per_slot; + uint32_t first_symbol_index; + uint32_t search_space_duration; + uint32_t search_space_frame_period; // in slots + uint32_t ssb_length; + uint32_t ssb_index; + uint32_t cset_start_rb; + NR_SubcarrierSpacing_t scs_pdcch; + bool active; +} NR_Type0_PDCCH_CSS_config_t; #endif /*__LAYER2_MAC_H__ */ diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index f40d822b6b..3f4be9dd58 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -31,8 +31,58 @@ */ #include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include "common/utils/nr/nr_common.h" #include +#define reserved 0xffff + + +void reverse_n_bits(uint8_t *value, uint16_t bitlen) { + uint16_t j; + uint8_t i; + for(j = bitlen - 1,i = 0; j > i; j--, i++) { + if(((*value>>j)&1) != ((*value>>i)&1)) { + *value ^= (1<=1 && L<=16,"L %d not ok\n",L); + *nr_of_candidates = 0; + switch(L) { + case 1: + if (ss->nrofCandidates->aggregationLevel1 != NR_SearchSpace__nrofCandidates__aggregationLevel1_n0) { + *aggregation_level = 1; + *nr_of_candidates = ss->nrofCandidates->aggregationLevel1; + } + break; + case 2: + if (ss->nrofCandidates->aggregationLevel2 != NR_SearchSpace__nrofCandidates__aggregationLevel2_n0) { + *aggregation_level = 2; + *nr_of_candidates = ss->nrofCandidates->aggregationLevel2; + } + break; + case 4: + if (ss->nrofCandidates->aggregationLevel4 != NR_SearchSpace__nrofCandidates__aggregationLevel4_n0) { + *aggregation_level = 4; + *nr_of_candidates = ss->nrofCandidates->aggregationLevel4; + } + break; + case 8: + if (ss->nrofCandidates->aggregationLevel8 != NR_SearchSpace__nrofCandidates__aggregationLevel8_n0) { + *aggregation_level = 8; + *nr_of_candidates = ss->nrofCandidates->aggregationLevel8; + } + break; + case 16: + if (ss->nrofCandidates->aggregationLevel16 != NR_SearchSpace__nrofCandidates__aggregationLevel16_n0) { + *aggregation_level = 16; + *nr_of_candidates = ss->nrofCandidates->aggregationLevel16; + } + break; + } +} + + +void set_monitoring_periodicity_offset(NR_SearchSpace_t *ss, + uint16_t period, + uint16_t offset) { + + switch(period) { + case 1: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; + break; + case 2: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2; + ss->monitoringSlotPeriodicityAndOffset->choice.sl2 = offset; + break; + case 4: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4; + ss->monitoringSlotPeriodicityAndOffset->choice.sl4 = offset; + break; + case 5: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5; + ss->monitoringSlotPeriodicityAndOffset->choice.sl5 = offset; + break; + case 8: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8; + ss->monitoringSlotPeriodicityAndOffset->choice.sl8 = offset; + break; + case 10: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10; + ss->monitoringSlotPeriodicityAndOffset->choice.sl10 = offset; + break; + case 16: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16; + ss->monitoringSlotPeriodicityAndOffset->choice.sl16 = offset; + break; + case 20: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20; + ss->monitoringSlotPeriodicityAndOffset->choice.sl20 = offset; + break; + case 40: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40; + ss->monitoringSlotPeriodicityAndOffset->choice.sl40 = offset; + break; + case 80: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80; + ss->monitoringSlotPeriodicityAndOffset->choice.sl80 = offset; + break; + case 160: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160; + ss->monitoringSlotPeriodicityAndOffset->choice.sl160 = offset; + break; + case 320: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320; + ss->monitoringSlotPeriodicityAndOffset->choice.sl320 = offset; + break; + case 640: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640; + ss->monitoringSlotPeriodicityAndOffset->choice.sl640 = offset; + break; + case 1280: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280; + ss->monitoringSlotPeriodicityAndOffset->choice.sl1280 = offset; + break; + case 2560: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560; + ss->monitoringSlotPeriodicityAndOffset->choice.sl2560 = offset; break; + default: + AssertFatal(1==0,"Invalid monitoring slot periodicity value\n"); + break; + } +} + + void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset) { @@ -955,6 +1492,113 @@ void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, } } +int get_nr_prach_occasion_info_from_index(uint8_t index, + uint32_t pointa, + uint8_t mu, + uint8_t unpaired, + uint16_t *format, + uint8_t *start_symbol, + uint8_t *N_t_slot, + uint8_t *N_dur, + uint8_t *N_RA_slot, + uint16_t *N_RA_sfn, + uint8_t *max_association_period) { + + int x; + int64_t s_map; + uint8_t format2 = 0xff; + if (pointa > 2016666) { //FR2 + x = table_6_3_3_2_4_prachConfig_Index[index][2]; + s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; + for(int i = 0; i < 64 ;i++) { + if ( (s_map >> i) & 0x01) { + (*N_RA_sfn)++; + } + } + *N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe + *max_association_period = 160/(x * 10); + if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ + *start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];//multiple prach occasions in diff slot + *N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8]; + *N_dur = table_6_3_3_2_4_prachConfig_Index[index][9]; + if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1]; + + *format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8); + LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n", + index, + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur, + *N_RA_sfn); + } + return 1; + } + else { + + if (unpaired) { + x = table_6_3_3_2_3_prachConfig_Index[index][2]; + s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; + for(int i = 0; i < 64 ;i++) { + if ( (s_map >> i) & 0x01) { + (*N_RA_sfn)++; + } + } + *N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe + *max_association_period = 160/(x * 10); + if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ + *start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5]; + *N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7]; + *N_dur = table_6_3_3_2_3_prachConfig_Index[index][8]; + if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; + *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); + LOG_D(NR_MAC,"Getting Total PRACH info from index %d (col %lu ) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n", + index, table_6_3_3_2_3_prachConfig_Index[index][6], + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur, + *N_RA_sfn); + } + return 1; + } + else { // FDD + x = table_6_3_3_2_2_prachConfig_Index[index][2]; + s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; + for(int i = 0; i < 64 ; i++) { + if ( (s_map >> i) & 0x01) { + (*N_RA_sfn)++; + } + } + *N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; + if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ + *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; + *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; + *N_dur = table_6_3_3_2_2_prachConfig_Index[index][8]; + if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1) + format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1]; + *format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8); + LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", + index, + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur); + } + return 1; + } + } +} + + int get_nr_prach_info_from_index(uint8_t index, int frame, int slot, @@ -964,7 +1608,10 @@ int get_nr_prach_info_from_index(uint8_t index, uint16_t *format, uint8_t *start_symbol, uint8_t *N_t_slot, - uint8_t *N_dur) { + uint8_t *N_dur, + uint16_t *RA_sfn_index, + uint8_t *N_RA_slot, + uint8_t *config_period) { int x,y; int64_t s_map; @@ -980,27 +1627,39 @@ int get_nr_prach_info_from_index(uint8_t index, if ( (frame%x)==y || (frame%x)==y2 ) { slot_60khz = slot >> (mu-2); // in table slots are numbered wrt 60kHz s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; + if ((s_map >> slot_60khz) & 0x01 ) { + for(int i = 0; i <= slot_60khz ;i++) { + if ( (s_map >> i) & 0x01) { + (*RA_sfn_index)++; + } + } + } if ( ((s_map>>slot_60khz)&0x01) ) { + *N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe if (mu == 3) { - if ( (table_6_3_3_2_4_prachConfig_Index[index][7] == 1) && (slot%2 == 0) ) + if ( (*N_RA_slot == 1) && (slot%2 == 0) ) return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot } if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ + *config_period = x; *start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6]; *N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8]; *N_dur = table_6_3_3_2_4_prachConfig_Index[index][9]; if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1) format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1]; *format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, - slot, - index, - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur); + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u\n", + frame, + slot, + index, + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur, + *N_RA_slot, + *RA_sfn_index); } return 1; } @@ -1018,19 +1677,28 @@ int get_nr_prach_info_from_index(uint8_t index, if ( (frame%x)==y ) { subframe = slot >> mu; s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; - if ( (s_map>>subframe)&0x01 ) { - if (mu == 1) { - if ( (table_6_3_3_2_3_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) - return 0; // no prach in even slots @ 30kHz for 1 prach per subframe + if ((s_map >> subframe) & 0x01 ) { + for(int i = 0; i <= subframe ;i++) { + if ( (s_map >> i) & 0x01) { + (*RA_sfn_index)++; + } } + } + if ( (s_map>>subframe)&0x01 ) { + *N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe + if (mu == 1) { + if ( (*N_RA_slot <= 1) && (slot%2 == 0) ) + return 0; // no prach in even slots @ 30kHz for 1 prach per subframe + } if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ + *config_period = x; *start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5]; *N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7]; *N_dur = table_6_3_3_2_3_prachConfig_Index[index][8]; if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %ld) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n", frame, slot, index, table_6_3_3_2_3_prachConfig_Index[index][6], pointa, @@ -1038,7 +1706,9 @@ int get_nr_prach_info_from_index(uint8_t index, unpaired, *start_symbol, *N_t_slot, - *N_dur); + *N_dur, + *N_RA_slot, + *RA_sfn_index); } return 1; } @@ -1059,6 +1729,11 @@ int get_nr_prach_info_from_index(uint8_t index, if ( (table_6_3_3_2_2_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) return 0; // no prach in even slots @ 30kHz for 1 prach per subframe } + for(int i = 0; i <= subframe ; i++) { + if ( (s_map >> i) & 0x01) { + (*RA_sfn_index)++; + } + } if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; @@ -1066,15 +1741,16 @@ int get_nr_prach_info_from_index(uint8_t index, if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1) format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1]; *format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, - slot, - index, - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur); + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", + frame, + slot, + index, + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur); } return 1; } @@ -1135,11 +1811,12 @@ uint16_t table_63313[838] = { uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, uint8_t nb_preambles, - uint8_t unpaired) { + uint8_t unpaired, + frequency_range_t frequency_range) { uint8_t config_index = rach_config->rach_ConfigGeneric.prach_ConfigurationIndex; uint8_t ncs_index = rach_config->rach_ConfigGeneric.zeroCorrelationZoneConfig; - uint16_t format0 = get_format0(config_index, unpaired); + uint16_t format0 = get_format0(config_index, unpaired, frequency_range); uint16_t NCS = get_NCS(ncs_index, format0, rach_config->restrictedSetConfig); uint16_t L_ra = (rach_config->prach_RootSequenceIndex.present==NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139) ? 139 : 839; uint16_t r,u,index,q,d_u,n_shift_ra,n_shift_ra_bar,d_start; @@ -1151,8 +1828,9 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, if (NCS == 0) return nb_preambles; else { r = L_ra/NCS; - printf(" found_sequences %u\n", (nb_preambles/r)); - return (nb_preambles/r); + found_sequences = (nb_preambles/r) + (nb_preambles%r!=0); //ceil(nb_preambles/r) + LOG_D(MAC, "Computing NR root sequences: found %u sequences\n", found_sequences); + return (found_sequences); } } else{ @@ -1189,60 +1867,52 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, AssertFatal(1==0,"Procedure to find nb of sequences for restricted type B not implemented yet"); } } - printf(" found_sequences %u\n", found_sequences); + LOG_D(MAC, "Computing NR root sequences: found %u sequences\n", found_sequences); return found_sequences; } } +// TS 38.211 Table 7.4.1.1.2-3: PDSCH DMRS positions l' within a slot for single-symbol DMRS and intra-slot frequency hopping disabled. +// The first 4 colomns are PDSCH mapping type A and the last 4 colomns are PDSCH mapping type B. +// When l' = l0, it is represented by 1 +// E.g. when symbol duration is 12 in colomn 7, value 1057 ('10000100001') which means l' = l0, 5, 10. -nr_bandentry_t nr_bandtable[] = { - {1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, - {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, - {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, - {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, - {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, - {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, - {12, 698000, 716000, 728000, 746000, 20, 145800, 100}, - {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, - {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, - {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, - {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, - {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, - {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, - {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, - {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, - {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, - {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, - {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, - {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, - {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, - {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, - {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, - {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, - {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, - {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, - {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, - {79, 4400000, 5000000, 4400000, 5000000, 1, 693334, 15}, - {79, 4400000, 5000000, 4400000, 5000000, 2, 693334, 30}, - {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {81, 860000, 915000, 000, 000, 20, 176000, 100}, - {82, 832000, 862000, 000, 000, 20, 166400, 100}, - {83, 703000, 748000, 000, 000, 20, 140600, 100}, - {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, - {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {257,26500000,29500000,26500000,29500000, 1,2054166, 60}, - {257,26500000,29500000,26500000,29500000, 2,2054167, 120}, - {258,24250000,27500000,24250000,27500000, 1,2016667, 60}, - {258,24250000,27500000,24250000,27500000, 2,2016667, 120}, - {260,37000000,40000000,37000000,40000000, 1,2229166, 60}, - {260,37000000,40000000,37000000,40000000, 2,2229167, 120}, - {261,27500000,28350000,27500000,28350000, 1,2070833, 60}, - {261,27500000,28350000,27500000,28350000, 2,2070833, 120} +int32_t table_7_4_1_1_2_3_pdsch_dmrs_positions_l [13][8] = { // Duration in symbols +{-1, -1, -1, -1, 1, 1, 1, 1}, //2 // (DMRS l' position) +{0, 0, 0, 0, 1, 1, 1, 1}, //3 // (DMRS l' position) +{0, 0, 0, 0, 1, 1, 1, 1}, //4 // (DMRS l' position) +{0, 0, 0, 0, 1, 17, 17, 17}, //5 // (DMRS l' position) +{0, 0, 0, 0, 1, 17, 17, 17}, //6 // (DMRS l' position) +{0, 0, 0, 0, 1, 17, 17, 17}, //7 // (DMRS l' position) +{0, 128, 128, 128, 1, 65, 73, 73}, //8 // (DMRS l' position) +{0, 128, 128, 128, 1, 129, 145, 145}, //9 // (DMRS l' position) +{0, 512, 576, 576, 1, 129, 145, 145}, //10 // (DMRS l' position) +{0, 512, 576, 576, 1, 257, 273, 585}, //11 // (DMRS l' position) +{0, 512, 576, 2336, 1, 513, 545, 585}, //12 // (DMRS l' position) +{0, 2048, 2176, 2336, 1, 513, 545, 585}, //13 // (DMRS l' position) +{0, 2048, 2176, 2336, -1, -1, -1, -1}, //14 // (DMRS l' position) }; +// TS 38.211 Table 7.4.1.1.2-4: PDSCH DMRS positions l' within a slot for double-symbol DMRS and intra-slot frequency hopping disabled. +// The first 4 colomns are PDSCH mapping type A and the last 4 colomns are PDSCH mapping type B. +// When l' = l0, it is represented by 1 + +int32_t table_7_4_1_1_2_4_pdsch_dmrs_positions_l [12][8] = { // Duration in symbols +{-1, -1, -1, -1, -1, -1, -1, -1}, //<4 // (DMRS l' position) +{0, 0, -1, -1, -1, -1, -1, -1}, //4 // (DMRS l' position) +{0, 0, -1, -1, 3, 3, -1, -1}, //5 // (DMRS l' position) +{0, 0, -1, -1, 3, 3, -1, -1}, //6 // (DMRS l' position) +{0, 0, -1, -1, 3, 3, -1, -1}, //7 // (DMRS l' position) +{0, 0, -1, -1, 3, 99, -1, -1}, //8 // (DMRS l' position) +{0, 0, -1, -1, 3, 99, -1, -1}, //9 // (DMRS l' position) +{0, 768, -1, -1, 3, 387, -1, -1}, //10 // (DMRS l' position) +{0, 768, -1, -1, 3, 387, -1, -1}, //11 // (DMRS l' position) +{0, 768, -1, -1, 3, 771, -1, -1}, //12 // (DMRS l' position) +{0, 3072, -1, -1, 3, 771, -1, -1}, //13 // (DMRS l' position) +{0, 3072, -1, -1, -1, -1, -1, -1}, //14 // (DMRS l' position) +}; + // TS 38.211 Table 6.4.1.1.3-3: PUSCH DMRS positions l' within a slot for single-symbol DMRS and intra-slot frequency hopping disabled. // The first 4 colomns are PUSCH mapping type A and the last 4 colomns are PUSCH mapping type B. // When l' = l0, it is represented by 1 @@ -1250,17 +1920,17 @@ nr_bandentry_t nr_bandtable[] = { int32_t table_6_4_1_1_3_3_pusch_dmrs_positions_l [12][8] = { // Duration in symbols {-1, -1, -1, -1, 1, 1, 1, 1}, //<4 // (DMRS l' position) -{1, 1, 1, 1, 1, 1, 1, 1}, //4 // (DMRS l' position) -{1, 1, 1, 1, 1, 5, 5, 5}, //5 // (DMRS l' position) -{1, 1, 1, 1, 1, 5, 5, 5}, //6 // (DMRS l' position) -{1, 1, 1, 1, 1, 5, 5, 5}, //7 // (DMRS l' position) -{1, 129, 129, 129, 1, 65, 73, 73}, //8 // (DMRS l' position) -{1, 129, 129, 129, 1, 65, 73, 73}, //9 // (DMRS l' position) -{1, 513, 577, 577, 1, 257, 273, 585}, //10 // (DMRS l' position) -{1, 513, 577, 577, 1, 257, 273, 585}, //11 // (DMRS l' position) -{1, 513, 577, 2337, 1, 1025, 1057, 585}, //12 // (DMRS l' position) -{1, 2049, 2177, 2337, 1, 1025, 1057, 585}, //13 // (DMRS l' position) -{1, 2049, 2177, 2337, 1, 1025, 1057, 585}, //14 // (DMRS l' position) +{0, 0, 0, 0, 1, 1, 1, 1}, //4 // (DMRS l' position) +{0, 0, 0, 0, 1, 17, 17, 17}, //5 // (DMRS l' position) +{0, 0, 0, 0, 1, 17, 17, 17}, //6 // (DMRS l' position) +{0, 0, 0, 0, 1, 17, 17, 17}, //7 // (DMRS l' position) +{0, 128, 128, 128, 1, 65, 73, 73}, //8 // (DMRS l' position) +{0, 128, 128, 128, 1, 65, 73, 73}, //9 // (DMRS l' position) +{0, 512, 576, 576, 1, 257, 273, 585}, //10 // (DMRS l' position) +{0, 512, 576, 576, 1, 257, 273, 585}, //11 // (DMRS l' position) +{0, 512, 576, 2336, 1, 1025, 1057, 585}, //12 // (DMRS l' position) +{0, 2048, 2176, 2336, 1, 1025, 1057, 585}, //13 // (DMRS l' position) +{0, 2048, 2176, 2336, 1, 1025, 1057, 585}, //14 // (DMRS l' position) }; @@ -1270,173 +1940,26 @@ int32_t table_6_4_1_1_3_3_pusch_dmrs_positions_l [12][8] = { int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l [12][8] = { // Duration in symbols {-1, -1, -1, -1, -1, -1, -1, -1}, //<4 // (DMRS l' position) -{1, 1, -1, -1, -1, -1, -1, -1}, //4 // (DMRS l' position) -{1, 1, -1, -1, 1, 1, -1, -1}, //5 // (DMRS l' position) -{1, 1, -1, -1, 1, 1, -1, -1}, //6 // (DMRS l' position) -{1, 1, -1, -1, 1, 1, -1, -1}, //7 // (DMRS l' position) -{1, 1, -1, -1, 1, 33, -1, -1}, //8 // (DMRS l' position) -{1, 1, -1, -1, 1, 33, -1, -1}, //9 // (DMRS l' position) -{1, 257, -1, -1, 1, 129, -1, -1}, //10 // (DMRS l' position) -{1, 257, -1, -1, 1, 129, -1, -1}, //11 // (DMRS l' position) -{1, 257, -1, -1, 1, 513, -1, -1}, //12 // (DMRS l' position) -{1, 1025, -1, -1, 1, 513, -1, -1}, //13 // (DMRS l' position) -{1, 1025, -1, -1, 1, 513, -1, -1}, //14 // (DMRS l' position) +{0, 0, -1, -1, -1, -1, -1, -1}, //4 // (DMRS l' position) +{0, 0, -1, -1, 3, 3, -1, -1}, //5 // (DMRS l' position) +{0, 0, -1, -1, 3, 3, -1, -1}, //6 // (DMRS l' position) +{0, 0, -1, -1, 3, 3, -1, -1}, //7 // (DMRS l' position) +{0, 0, -1, -1, 3, 99, -1, -1}, //8 // (DMRS l' position) +{0, 0, -1, -1, 3, 99, -1, -1}, //9 // (DMRS l' position) +{0, 768, -1, -1, 3, 387, -1, -1}, //10 // (DMRS l' position) +{0, 768, -1, -1, 3, 387, -1, -1}, //11 // (DMRS l' position) +{0, 768, -1, -1, 3, 1539, -1, -1}, //12 // (DMRS l' position) +{0, 3072, -1, -1, 3, 1539, -1, -1}, //13 // (DMRS l' position) +{0, 3072, -1, -1, 3, 1539, -1, -1}, //14 // (DMRS l' position) }; -#define NR_BANDTABLE_SIZE (sizeof(nr_bandtable)/sizeof(nr_bandentry_t)) -void get_band(uint64_t downlink_frequency, - uint16_t *current_band, - int32_t *current_offset, - lte_frame_type_t *current_type) -{ - int ind; - uint64_t center_frequency_khz; - uint64_t center_freq_diff_khz; - uint64_t dl_freq_khz = downlink_frequency/1000; +void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs){ - center_freq_diff_khz = 999999999999999999; // 2^64 - *current_band = 0; + uint32_t delta_arfcn = nrarfcn - N_OFFs; - for ( ind=0; - ind < sizeof(nr_bandtable) / sizeof(nr_bandtable[0]); - ind++) { - - LOG_I(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min,nr_bandtable[ind].ul_min); - - if ( nr_bandtable[ind].dl_min <= dl_freq_khz && nr_bandtable[ind].dl_max >= dl_freq_khz ) { - - center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min)/2; - if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ - *current_band = nr_bandtable[ind].band; - *current_offset = (nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min)*1000; - center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); - - if (*current_offset == 0) - *current_type = TDD; - else - *current_type = FDD; - } - } - } - - LOG_I( PHY, "DL frequency %"PRIu64": band %d, frame_type %d, UL frequency %"PRIu64"\n", - downlink_frequency, *current_band, *current_type, downlink_frequency+*current_offset); - - AssertFatal(*current_band != 0, - "Can't find EUTRA band for frequency %lu\n", downlink_frequency); -} - -uint16_t config_bandwidth(int mu, int nb_rb, int nr_band) -{ - - if (nr_band < 100) { //FR1 - switch(mu) { - case 0 : - if (nb_rb<=25) - return 5; - if (nb_rb<=52) - return 10; - if (nb_rb<=79) - return 15; - if (nb_rb<=106) - return 20; - if (nb_rb<=133) - return 25; - if (nb_rb<=160) - return 30; - if (nb_rb<=216) - return 40; - if (nb_rb<=270) - return 50; - AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); - break; - case 1 : - if (nb_rb<=11) - return 5; - if (nb_rb<=24) - return 10; - if (nb_rb<=38) - return 15; - if (nb_rb<=51) - return 20; - if (nb_rb<=65) - return 25; - if (nb_rb<=78) - return 30; - if (nb_rb<=106) - return 40; - if (nb_rb<=133) - return 50; - if (nb_rb<=162) - return 60; - if (nb_rb<=189) - return 70; - if (nb_rb<=217) - return 80; - if (nb_rb<=245) - return 90; - if (nb_rb<=273) - return 100; - AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); - break; - case 2 : - if (nb_rb<=11) - return 10; - if (nb_rb<=18) - return 15; - if (nb_rb<=24) - return 20; - if (nb_rb<=31) - return 25; - if (nb_rb<=38) - return 30; - if (nb_rb<=51) - return 40; - if (nb_rb<=65) - return 50; - if (nb_rb<=79) - return 60; - if (nb_rb<=93) - return 70; - if (nb_rb<=107) - return 80; - if (nb_rb<=121) - return 90; - if (nb_rb<=135) - return 100; - AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); - break; - default: - AssertFatal(1==0,"Numerology %d undefined for band %d in FR1\n", mu,nr_band); - } - } - else { - switch(mu) { - case 2 : - if (nb_rb<=66) - return 50; - if (nb_rb<=132) - return 100; - if (nb_rb<=264) - return 200; - AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); - break; - case 3 : - if (nb_rb<=32) - return 50; - if (nb_rb<=66) - return 100; - if (nb_rb<=132) - return 200; - if (nb_rb<=264) - return 400; - AssertFatal(1==0,"Number of DL resource blocks %d undefined for mu %d and band %d\n", nb_rb, mu, nr_band); - break; - default: - AssertFatal(1==0,"Numerology %d undefined for band %d in FR1\n", mu,nr_band); - } - } + if(delta_arfcn%(nr_bandtable[i].step_size)!=0) + AssertFatal(1 == 0, "nrarfcn %u is not on the channel raster for step size %lu", nrarfcn, nr_bandtable[i].step_size); } @@ -1447,17 +1970,10 @@ uint32_t to_nrarfcn(int nr_bandP, { uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000; int bw_kHz = bw / 1000; - int scs_khz = 15< 260\n", nr_bandP); - for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++); - - // selection of correct Deltaf raster according to SCS - if ( (nr_bandtable[i].deltaf_raster != 100) && (nr_bandtable[i].deltaf_raster != scs_khz)) - i++; + LOG_I(NR_MAC,"Searching for nr band %d DL Carrier frequency %llu bw %u\n",nr_bandP,(long long unsigned int)dl_CarrierFreq,bw); AssertFatal(dl_CarrierFreq_by_1k >= nr_bandtable[i].dl_min, "Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n", @@ -1469,72 +1985,89 @@ uint32_t to_nrarfcn(int nr_bandP, (long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz)); int deltaFglobal = 60; + uint32_t N_REF_Offs = 2016667; + uint64_t F_REF_Offs_khz = 24250080; - if (dl_CarrierFreq < 3e9) deltaFglobal = 15; - if (dl_CarrierFreq < 24.25e9) deltaFglobal = 5; + if (dl_CarrierFreq < 24.25e9) { + deltaFglobal = 15; + N_REF_Offs = 600000; + F_REF_Offs_khz = 3000000; + } + if (dl_CarrierFreq < 3e9) { + deltaFglobal = 5; + N_REF_Offs = 0; + F_REF_Offs_khz = 0; + } // This is equation before Table 5.4.2.1-1 in 38101-1-f30 // F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs) - nrarfcn = (((dl_CarrierFreq_by_1k - nr_bandtable[i].dl_min)/deltaFglobal)+nr_bandtable[i].N_OFFs_DL); - - delta_arfcn = nrarfcn - nr_bandtable[i].N_OFFs_DL; - if(delta_arfcn%(nr_bandtable[i].step_size)!=0) - AssertFatal(1==0,"dl_CarrierFreq %lu corresponds to %u which is not on the raster for step size %lu", - dl_CarrierFreq,nrarfcn,nr_bandtable[i].step_size); + nrarfcn = (((dl_CarrierFreq_by_1k - F_REF_Offs_khz)/deltaFglobal)+N_REF_Offs); + get_delta_arfcn(i, nrarfcn, nr_bandtable[i].N_OFFs_DL); return nrarfcn; } - +// This function computes the RF reference frequency from the NR-ARFCN according to 5.4.2.1 of 3GPP TS 38.104 +// this function applies to both DL and UL uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, - uint32_t dl_nrarfcn) + uint32_t nrarfcn) { - int i; int deltaFglobal = 5; - int scs_khz = 15< 599999 && dl_nrarfcn < 2016667) - deltaFglobal = 15; - if (dl_nrarfcn > 2016666 && dl_nrarfcn < 3279166) + if (nrarfcn > 599999 && nrarfcn < 2016667) { + deltaFglobal = 15; + N_REF_Offs = 600000; + F_REF_Offs_khz = 3000000; + } + if (nrarfcn > 2016666 && nrarfcn < 3279166) { deltaFglobal = 60; - - AssertFatal(nr_bandP <= 261, "nr_band %d > 260\n", nr_bandP); - for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++); - AssertFatal(dl_nrarfcn>=nr_bandtable[i].N_OFFs_DL,"dl_nrarfcn %u < N_OFFs_DL[%d] %llu\n",dl_nrarfcn, nr_bandtable[i].band,(long long unsigned int)nr_bandtable[i].N_OFFs_DL); - - // selection of correct Deltaf raster according to SCS - if ( (nr_bandtable[i].deltaf_raster != 100) && (nr_bandtable[i].deltaf_raster != scs_khz)) - i++; + N_REF_Offs = 2016667; + F_REF_Offs_khz = 24250080; + } - delta_arfcn = dl_nrarfcn - nr_bandtable[i].N_OFFs_DL; - if(delta_arfcn%(nr_bandtable[i].step_size)!=0) - AssertFatal(1==0,"dl_nrarfcn %u is not on the raster for step size %lu",dl_nrarfcn,nr_bandtable[i].step_size); + int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index); - LOG_I(PHY,"Computing dl_frequency (pointA %llu => %llu (dlmin %llu, nr_bandtable[%d].N_OFFs_DL %llu))\n", - (unsigned long long)dl_nrarfcn, - (unsigned long long)(1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal)), - (unsigned long long)nr_bandtable[i].dl_min, - i, - (unsigned long long)nr_bandtable[i].N_OFFs_DL); + if (delta_duplex <= 0){ // DL band >= UL band + if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL + N_OFFs = nr_bandtable[i].N_OFFs_DL; + freq_min = nr_bandtable[i].dl_min; + } else {// is FDD UL + N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal; + freq_min = nr_bandtable[i].ul_min; + } + } else { // UL band > DL band + if (nrarfcn >= nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal){ // is FDD UL + N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal; + freq_min = nr_bandtable[i].ul_min; + } else { // is FDD DL + N_OFFs = nr_bandtable[i].N_OFFs_DL; + freq_min = nr_bandtable[i].dl_min; + } + } + + LOG_D(NR_MAC, "Frequency from NR-ARFCN for N_OFFs %lu, duplex spacing %d KHz, deltaFglobal %d KHz\n", N_OFFs, delta_duplex, deltaFglobal); + + AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %llu\n", nrarfcn, nr_bandtable[i].band, (long long unsigned int)N_OFFs); + get_delta_arfcn(i, nrarfcn, N_OFFs); + + frequency = 1000*(F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal); + + LOG_I(NR_MAC, "Computing frequency (pointA %llu => %llu KHz (freq_min %llu KHz, NR band %d N_OFFs %llu))\n", + (unsigned long long)nrarfcn, + (unsigned long long)frequency/1000, + (unsigned long long)freq_min, + nr_bandP, + (unsigned long long)N_OFFs); + + return frequency; - return 1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal); } - -int32_t get_nr_uldl_offset(int nr_bandP) -{ - int i; - - for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++); - - AssertFatal(i < NR_BANDTABLE_SIZE, "i %d >= BANDTABLE_SIZE %ld\n", i, NR_BANDTABLE_SIZE); - - return (nr_bandtable[i].dl_min - nr_bandtable[i].ul_min); -} - - void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, int x_overhead, uint8_t numdmrscdmgroupnodata, @@ -1555,7 +2088,8 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, } uint8_t N_sh_symb = pdsch_rel15->NrOfSymbols; uint8_t Imcs = pdsch_rel15->mcsIndex[0]; - uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS - N_PRB_oh; + uint16_t dmrs_length = get_num_dmrs(pdsch_rel15->dlDmrsSymbPos); + uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS*dmrs_length - N_PRB_oh; LOG_D(MAC, "N_RE_prime %d for %d symbols %d DMRS per PRB and %d overhead\n", N_RE_prime, N_sh_symb, N_PRB_DMRS, N_PRB_oh); uint16_t R; @@ -1572,10 +2106,10 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, TBS = nr_compute_tbs(Qm, R, - pdsch_rel15->rbSize, - N_sh_symb, - N_PRB_DMRS, // FIXME // This should be multiplied by the number of dmrs symbols - N_PRB_oh, + pdsch_rel15->rbSize, + N_sh_symb, + N_PRB_DMRS*dmrs_length, + N_PRB_oh, tb_scaling, pdsch_rel15->nrOfLayers)>>3; @@ -1602,11 +2136,9 @@ uint16_t Table_51312[28][2] = {{2,120},{2,193},{2,308},{2,449},{2,602},{4,378},{ uint16_t Table_51313[29][2] = {{2,30},{2,40},{2,50},{2,64},{2,78},{2,99},{2,120},{2,157},{2,193},{2,251},{2,308},{2,379},{2,449},{2,526},{2,602},{4,340}, {4,378},{4,434},{4,490},{4,553},{4,616},{6,438},{6,466},{6,517},{6,567},{6,616},{6,666}, {6,719}, {6,772}}; -//Table 6.1.4.1-1 of 38.214 TODO fix for tp-pi2BPSK uint16_t Table_61411[28][2] = {{2,120},{2,157},{2,193},{2,251},{2,308},{2,379},{2,449},{2,526},{2,602},{2,679},{4,340},{4,378},{4,434},{4,490},{4,553},{4,616}, {4,658},{6,466},{6,517},{6,567},{6,616},{6,666},{6,719},{6,772},{6,822},{6,873}, {6,910}, {6,948}}; -//Table 6.1.4.1-2 of 38.214 TODO fix for tp-pi2BPSK uint16_t Table_61412[28][2] = {{2,30},{2,40},{2,50},{2,64},{2,78},{2,99},{2,120},{2,157},{2,193},{2,251},{2,308},{2,379},{2,449},{2,526},{2,602},{2,679}, {4,378},{4,434},{4,490},{4,553},{4,616},{4,658},{4,699},{4,772},{6,567},{6,616},{6,666}, {6,772}}; @@ -1615,92 +2147,160 @@ uint16_t Table_61412[28][2] = {{2,30},{2,40},{2,50},{2,64},{2,78},{2,99},{2,120} uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx) { switch(table_idx) { case 0: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,28])\n", Imcs); + return 0; + } return (Table_51311[Imcs][0]); break; case 1: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,27])\n", Imcs); + return 0; + } return (Table_51312[Imcs][0]); break; case 2: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,28])\n", Imcs); + return 0; + } return (Table_51313[Imcs][0]); break; default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,3])\n", table_idx); + LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx); + return 0; } } uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx) { switch(table_idx) { case 0: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,28])\n", Imcs); + return 0; + } return (Table_51311[Imcs][1]); break; case 1: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,27])\n", Imcs); + return 0; + } return (Table_51312[Imcs][1]); break; case 2: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,28])\n", Imcs); + return 0; + } return (Table_51313[Imcs][1]); break; default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,3])\n", table_idx); + LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx); + return 0; } } uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx) { switch(table_idx) { case 0: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,28])\n", Imcs); + return 0; + } return (Table_51311[Imcs][0]); break; case 1: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,27])\n", Imcs); + return 0; + } return (Table_51312[Imcs][0]); break; case 2: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,28])\n", Imcs); + return 0; + } return (Table_51313[Imcs][0]); break; case 3: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,27])\n", Imcs); + return 0; + } return (Table_61411[Imcs][0]); break; case 4: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,27])\n", Imcs); + return 0; + } return (Table_61412[Imcs][0]); break; default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,2])\n", table_idx); + LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx); + return 0; } } uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx) { switch(table_idx) { case 0: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,28])\n", Imcs); + return 0; + } return (Table_51311[Imcs][1]); break; case 1: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,27])\n", Imcs); + return 0; + } return (Table_51312[Imcs][1]); break; case 2: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,28])\n", Imcs); + return 0; + } return (Table_51313[Imcs][1]); break; case 3: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,27])\n", Imcs); + return 0; + } return (Table_61411[Imcs][1]); break; case 4: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,27])\n", Imcs); + return 0; + } return (Table_61412[Imcs][1]); break; default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,2])\n", table_idx); + LOG_E(MAC, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx); + return 0; } } @@ -1724,12 +2324,10 @@ static inline uint8_t get_table_idx(uint8_t mcs_table, uint8_t dci_format, uint8 return 1; } -int get_num_dmrs(uint16_t dmrs_mask ) { - int num_dmrs=0; - - for (int i=0;i<16;i++) num_dmrs+=((dmrs_mask>>i)&1); - return(num_dmrs); +/* returns the total DMRS symbols in a slot*/ +uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols, int startSymbol, int mappingtype){ + return get_num_dmrs(fill_dmrs_mask(pdsch_Config,dmrs_TypeA_Position,NrOfSymbols, startSymbol, mappingtype)); } // Table 5.1.2.2.1-1 38.214 @@ -1793,29 +2391,46 @@ uint8_t get_l0_ul(uint8_t mapping_type, uint8_t dmrs_typeA_position) { } -int32_t get_l_prime(uint8_t duration_in_symbols, uint8_t mapping_type, pusch_dmrs_AdditionalPosition_t additional_pos, pusch_maxLength_t pusch_maxLength) { +int32_t get_l_prime(uint8_t duration_in_symbols, uint8_t mapping_type, pusch_dmrs_AdditionalPosition_t additional_pos, pusch_maxLength_t pusch_maxLength, uint8_t start_symbol, uint8_t dmrs_typeA_position) { uint8_t row, colomn; int32_t l_prime; + LOG_D(NR_MAC, "PUSCH: NrofSymbols:%d, startSymbol:%d, mappingtype:%d, dmrs_TypeA_Position:%d\n", duration_in_symbols, start_symbol, mapping_type, dmrs_typeA_position); + + // Section 6.4.1.1.3 in Spec 38.211 + // For PDSCH Mapping TypeA, ld is duration between first OFDM of the slot and last OFDM symbol of the scheduled PUSCH resources + // For TypeB, ld is the duration of the scheduled PUSCH resources + uint8_t ld = (mapping_type == typeA) ? (duration_in_symbols + start_symbol) : duration_in_symbols; + uint8_t l0 = (dmrs_typeA_position == NR_MIB__dmrs_TypeA_Position_pos2) ? 2 : 3 ; + colomn = additional_pos; if (mapping_type == typeB) colomn += 4; - if (duration_in_symbols < 4) + if (ld < 4) row = 0; else - row = duration_in_symbols - 3; + row = ld - 3; - if (pusch_maxLength == pusch_len1) + if (pusch_maxLength == pusch_len1) { l_prime = table_6_4_1_1_3_3_pusch_dmrs_positions_l[row][colomn]; - else + l0 = 1 << l0; + } + else { l_prime = table_6_4_1_1_3_4_pusch_dmrs_positions_l[row][colomn]; + l0 = 1<0,"invalid l_prime < 0\n"); + LOG_D(NR_MAC, "PUSCH - l0:%d, ld:%d,row:%d, column:%d, addpos:%d, maxlen:%d\n", l0, ld, row, colomn, additional_pos, pusch_maxLength); + AssertFatal(l_prime>=0,"invalid l_prime < 0\n"); + + l_prime = (mapping_type == typeA) ? (l_prime | l0) : (l_prime << start_symbol); + LOG_D(MAC, " PUSCH DMRS MASK in HEX:%x\n", l_prime); return l_prime; + } /******************************************************************* @@ -1842,7 +2457,7 @@ uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint mcs4 = 28; if (I_mcs < mcs1) { - LOG_I(PHY, "PUSH PT-RS is not present.\n"); + LOG_D(PHY, "PUSH PT-RS is not present.\n"); return -1; } else if (I_mcs >= mcs1 && I_mcs < mcs2) return 2; @@ -1851,7 +2466,7 @@ uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint else if (I_mcs >= mcs3 && I_mcs < mcs4) return 0; else { - LOG_I(PHY, "PT-RS time-density determination is obtained from the DCI for the same transport block in the initial transmission\n"); + LOG_D(NR_MAC, "PT-RS time-density determination is obtained from the DCI for the same transport block in the initial transmission\n"); return -1; } } @@ -1860,7 +2475,7 @@ uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint * * NAME : get_K_ptrs * -* PARAMETERS : ptrs_UplinkConfig PTRS uplink configuration +* PARAMETERS : nrb0, nrb1 PTRS uplink configuration * N_RB number of RBs scheduled for PUSCH * * RETURN : the parameter K_ptrs @@ -1872,16 +2487,53 @@ uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) { if (N_RB < nrb0) { - LOG_I(PHY,"PUSH PT-RS is not present.\n"); + LOG_D(PHY,"PUSH PT-RS is not present.\n"); return -1; } else if (N_RB >= nrb0 && N_RB < nrb1) - return 0; + return 2; else - return 1; + return 4; } -uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *secondaryCellGroup, +// Set the transform precoding status according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16: +// - "UE procedure for applying transform precoding on PUSCH" +uint8_t get_transformPrecoding(const NR_BWP_UplinkCommon_t *initialUplinkBWP, + const NR_PUSCH_Config_t *pusch_config, + const NR_BWP_UplinkDedicated_t *ubwp, + uint8_t *dci_format, + int rnti_type, + uint8_t configuredGrant){ + + if (configuredGrant) { + if (ubwp->configuredGrantConfig) { + if (ubwp->configuredGrantConfig->choice.setup->transformPrecoder) { + return *ubwp->configuredGrantConfig->choice.setup->transformPrecoder; + } + } + } + + if (rnti_type != NR_RNTI_RA && rnti_type != NR_RNTI_TC) { + if (*dci_format != NR_UL_DCI_FORMAT_0_0) { + if (pusch_config && pusch_config->transformPrecoder != NULL) { + return *pusch_config->transformPrecoder; + } + } + } + + if (initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) { + return 1; // Transformprecoding disabled + } else { + LOG_D(PHY, "MAC_COMMON: Transform Precodig enabled through msg3_transformPrecoder\n"); + return 0; // Enabled + } + + LOG_E(MAC, "In %s: could not fetch transform precoder status...\n", __FUNCTION__); + return -1; +} + +uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDownlinkBWP, + const NR_BWP_UplinkCommon_t *initialUplinkBWP, + const NR_CellGroupConfig_t *cg, dci_pdu_rel15_t *dci_pdu, nr_dci_format_t format, nr_rnti_type_t rnti_type, @@ -1893,19 +2545,48 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, long rbg_size_config; int num_entries = 0; int pusch_antenna_ports = 1; // TODO hardcoded number of antenna ports for pusch - NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; - NR_PDSCH_Config_t *pdsch_config = bwp->bwp_Dedicated->pdsch_Config->choice.setup; - NR_PUSCH_Config_t *pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; - NR_SRS_Config_t *srs_config = ubwp->bwp_Dedicated->srs_Config->choice.setup; + const NR_BWP_DownlinkDedicated_t *bwpd = NULL; + const NR_BWP_UplinkDedicated_t *ubwpd = NULL; + const NR_BWP_DownlinkCommon_t *bwpc = NULL; + const NR_BWP_UplinkCommon_t *ubwpc = NULL; + const NR_PDSCH_Config_t *pdsch_Config = NULL; + const NR_PUSCH_Config_t *pusch_Config = NULL; + const NR_PUCCH_Config_t *pucch_Config = NULL; + const NR_PDCCH_Config_t *pdcch_Config = NULL; + const NR_SRS_Config_t *srs_config = NULL; + if(bwp_id > 0) { + AssertFatal(cg!=NULL,"Cellgroup is null and bwp_id!=0"); + bwpd=cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated; + bwpc=cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common; + ubwpd=cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated; + ubwpc=cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Common; + pdsch_Config = (bwpd->pdsch_Config) ? bwpd->pdsch_Config->choice.setup : NULL; + pdcch_Config = (bwpd->pdcch_Config) ? bwpd->pdcch_Config->choice.setup : NULL; + pucch_Config = (ubwpd->pucch_Config) ? ubwpd->pucch_Config->choice.setup : NULL; + pusch_Config = (ubwpd->pusch_Config) ? ubwpd->pusch_Config->choice.setup : NULL; + srs_config = (ubwpd->srs_Config) ? ubwpd->srs_Config->choice.setup : NULL; + } + else if (cg){ + bwpd=cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP; + bwpc=initialDownlinkBWP; + ubwpd=cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; + ubwpc=initialUplinkBWP; + pdsch_Config = (bwpd->pdsch_Config) ? bwpd->pdsch_Config->choice.setup : NULL; + pdcch_Config = (bwpd->pdcch_Config) ? bwpd->pdcch_Config->choice.setup : NULL; + pucch_Config = (ubwpd->pucch_Config) ? ubwpd->pucch_Config->choice.setup : NULL; + pusch_Config = (ubwpd->pusch_Config) ? ubwpd->pusch_Config->choice.setup : NULL; + srs_config = (ubwpd->srs_Config) ? ubwpd->srs_Config->choice.setup: NULL; + } + + int n_ul_bwp=1,n_dl_bwp=1; switch(format) { /*Only sizes for 0_0 and 1_0 are correct at the moment*/ case NR_UL_DCI_FORMAT_0_0: /// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20 size += 20; size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment -- hopping scenario to be updated - size += nr_dci_size(scc,secondaryCellGroup,dci_pdu,NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB, bwp_id) - size; // Padding to match 1_0 size + size += nr_dci_size(initialDownlinkBWP,initialUplinkBWP,cg,dci_pdu,NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB, bwp_id) - size; // Padding to match 1_0 size // UL/SUL indicator assumed to be 0 break; @@ -1913,66 +2594,81 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, /// fixed: Format identifier 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2, ULSCH indicator 1 --16 size += 16; // Carrier indicator - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) { + if (cg->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) { dci_pdu->carrier_indicator.nbits=3; size += dci_pdu->carrier_indicator.nbits; } // UL/SUL indicator - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL) { + if (cg->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL) { dci_pdu->carrier_indicator.nbits=1; size += dci_pdu->ul_sul_indicator.nbits; } // BWP Indicator - uint8_t n_ul_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; + n_ul_bwp = 0; + if (cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList) + n_ul_bwp = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; if (n_ul_bwp < 2) dci_pdu->bwp_indicator.nbits = n_ul_bwp; else dci_pdu->bwp_indicator.nbits = 2; size += dci_pdu->bwp_indicator.nbits; // Freq domain assignment - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pusch_Config->choice.setup->rbg_Size != NULL) - rbg_size_config = 1; - else - rbg_size_config = 0; - numRBG = getNRBG(NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275), - NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275), - rbg_size_config); - if (pusch_Config->resourceAllocation == 0) - dci_pdu->frequency_domain_assignment.nbits = numRBG; - else if (pusch_Config->resourceAllocation == 1) - dci_pdu->frequency_domain_assignment.nbits = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - else - dci_pdu->frequency_domain_assignment.nbits = ((int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )>numRBG) ? (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )+1 : numRBG+1; + if (pusch_Config) { + if (pusch_Config->rbg_Size != NULL) + rbg_size_config = 1; + else + rbg_size_config = 0; + numRBG = getNRBG(NRRIV2BW(ubwpc->genericParameters.locationAndBandwidth, MAX_BWP_SIZE), + NRRIV2PRBOFFSET(ubwpc->genericParameters.locationAndBandwidth, MAX_BWP_SIZE), + rbg_size_config); + if (pusch_Config->resourceAllocation == 0) + dci_pdu->frequency_domain_assignment.nbits = numRBG; + else if (pusch_Config->resourceAllocation == 1) + dci_pdu->frequency_domain_assignment.nbits = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); + else + dci_pdu->frequency_domain_assignment.nbits = ((int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )>numRBG) ? (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )+1 : numRBG+1; + } + else dci_pdu->frequency_domain_assignment.nbits = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); + LOG_D(NR_MAC,"PUSCH Frequency Domain Assignment nbits %d, N_RB %d\n",dci_pdu->frequency_domain_assignment.nbits,N_RB); size += dci_pdu->frequency_domain_assignment.nbits; // Time domain assignment - if (pusch_Config->pusch_TimeDomainAllocationList==NULL) { - if (ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList==NULL) + if (pusch_Config==NULL || pusch_Config->pusch_TimeDomainAllocationList==NULL) { + if (ubwpc->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList==NULL) num_entries = 16; // num of entries in default table else - num_entries = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count; + num_entries = ubwpc->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count; } else num_entries = pusch_Config->pusch_TimeDomainAllocationList->choice.setup->list.count; dci_pdu->time_domain_assignment.nbits = (int)ceil(log2(num_entries)); + LOG_D(NR_MAC,"PUSCH Time Domain Allocation nbits %d, pusch_Config %p\n",dci_pdu->time_domain_assignment.nbits,pusch_Config); size += dci_pdu->time_domain_assignment.nbits; // Frequency Hopping flag - if ((pusch_Config->frequencyHopping!=NULL) && (pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0)) { + if (pusch_Config && + pusch_Config->frequencyHopping!=NULL && + pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0) { dci_pdu->frequency_hopping_flag.nbits = 1; size += 1; } // 1st DAI - if (secondaryCellGroup->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook==NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic) + if (cg->physicalCellGroupConfig && + cg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook==NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic) dci_pdu->dai[0].nbits = 2; else dci_pdu->dai[0].nbits = 1; size += dci_pdu->dai[0].nbits; + LOG_D(NR_MAC,"DAI1 nbits %d\n",dci_pdu->dai[0].nbits); // 2nd DAI - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { //TODO not sure about that + if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig && + cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { //TODO not sure about that dci_pdu->dai[1].nbits = 2; size += dci_pdu->dai[1].nbits; } // SRS resource indicator - if (pusch_Config->txConfig != NULL){ + if (srs_config && + pusch_Config && + pusch_Config->txConfig != NULL){ int count=0; if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){ for (int i=0; isrs_ResourceSetToAddModList->list.count; i++) { @@ -1987,9 +2683,10 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, else { int lmin,Lmax = 0; int lsum = 0; - if ( secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig != NULL) { - if ( secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers != NULL) - Lmax = *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers; + if ( cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig != NULL) { + if ( cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers != NULL) + Lmax = *cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers; else AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n"); } @@ -2007,19 +2704,13 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, dci_pdu->srs_resource_indicator.nbits = (int)ceil(log2(lsum)); size += dci_pdu->srs_resource_indicator.nbits; } - } + } else dci_pdu->srs_resource_indicator.nbits = 0; + LOG_D(NR_MAC,"dci_pdu->srs_resource_indicator.nbits %d\n",dci_pdu->srs_resource_indicator.nbits); // Precoding info and number of layers - long transformPrecoder; - if (pusch_Config->transformPrecoder == NULL){ - // if transform precoder is null, apply the values from msg3 - if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - transformPrecoder = 1; - else - transformPrecoder = 0; - } - else - transformPrecoder = *pusch_Config->transformPrecoder; - if (pusch_Config->txConfig != NULL){ + long transformPrecoder = get_transformPrecoding(initialUplinkBWP, pusch_Config, ubwpd, (uint8_t*)&format, rnti_type, 0); + dci_pdu->precoding_information.nbits=0; + if (pusch_Config && + pusch_Config->txConfig != NULL){ if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){ if (pusch_antenna_ports > 1) { if (pusch_antenna_ports == 4) { @@ -2043,15 +2734,18 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, } } size += dci_pdu->precoding_information.nbits; + LOG_D(NR_MAC,"dci_pdu->precoding_informaiton.nbits=%d\n",dci_pdu->precoding_information.nbits); // Antenna ports NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = NULL; int xa=0; int xb=0; - if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL){ + if(pusch_Config && + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL){ NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; xa = ul_ant_bits(NR_DMRS_UplinkConfig,transformPrecoder); } - if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL){ + if(pusch_Config && + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL){ NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; xb = ul_ant_bits(NR_DMRS_UplinkConfig,transformPrecoder); } @@ -2060,34 +2754,41 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, else dci_pdu->antenna_ports.nbits = xb; size += dci_pdu->antenna_ports.nbits; + LOG_D(NR_MAC,"dci_pdu->antenna_ports.nbits = %d\n",dci_pdu->antenna_ports.nbits); // SRS request - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink==NULL) + if (cg->spCellConfig->spCellConfigDedicated->supplementaryUplink==NULL) dci_pdu->srs_request.nbits = 2; else dci_pdu->srs_request.nbits = 3; size += dci_pdu->srs_request.nbits; // CSI request - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig != NULL) { - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup->reportTriggerSize != NULL) { - dci_pdu->csi_request.nbits = *secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup->reportTriggerSize; + if (cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig != NULL) { + if (cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup->reportTriggerSize != NULL) { + dci_pdu->csi_request.nbits = *cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup->reportTriggerSize; size += dci_pdu->csi_request.nbits; } } // CBGTI - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { - int num = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->maxCodeBlockGroupsPerTransportBlock; + if (cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig && + cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { + int num = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->maxCodeBlockGroupsPerTransportBlock; dci_pdu->cbgti.nbits = 2 + (num<<1); size += dci_pdu->cbgti.nbits; } // PTRS - DMRS association - if ( (NR_DMRS_UplinkConfig->phaseTrackingRS == NULL && transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) || - transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled || (*pusch_Config->maxRank==1) ) + if ( (NR_DMRS_UplinkConfig && + NR_DMRS_UplinkConfig->phaseTrackingRS == NULL && + transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) || + transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled || + (pusch_Config && pusch_Config->maxRank && + *pusch_Config->maxRank==1) ) dci_pdu->ptrs_dmrs_association.nbits = 0; else dci_pdu->ptrs_dmrs_association.nbits = 2; size += dci_pdu->ptrs_dmrs_association.nbits; // beta offset indicator - if (pusch_Config->uci_OnPUSCH!=NULL){ + if (pusch_Config && + pusch_Config->uci_OnPUSCH!=NULL){ if (pusch_Config->uci_OnPUSCH->choice.setup->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_dynamic) { dci_pdu->beta_offset_indicator.nbits = 2; size += dci_pdu->beta_offset_indicator.nbits; @@ -2102,121 +2803,143 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, case NR_DL_DCI_FORMAT_1_0: /// fixed: Format identifier 1, VRB2PRB 1, MCS 5, NDI 1, RV 2, HARQ PID 4, DAI 2, PUCCH TPC 2, PUCCH RInd 3, PDSCH to HARQ TInd 3 Time Domain assgnmt 4 -- 28 - size += 28; + size = 28; size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment + + dci_pdu->frequency_domain_assignment.nbits = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); + dci_pdu->time_domain_assignment.nbits = 4; + dci_pdu->vrb_to_prb_mapping.nbits = 1; break; case NR_DL_DCI_FORMAT_1_1: + LOG_D(NR_MAC,"DCI_FORMAT 1_1 : pdsch_Config %p, pucch_Config %p\n",pdsch_Config,pucch_Config); // General note: 0 bits condition is ignored as default nbits is 0. // Format identifier size = 1; // Carrier indicator - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) { + if (cg->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) { dci_pdu->carrier_indicator.nbits=3; size += dci_pdu->carrier_indicator.nbits; } + // BWP Indicator - uint8_t n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; + n_dl_bwp = 0; + if (cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList) + n_dl_bwp = cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; if (n_dl_bwp < 2) dci_pdu->bwp_indicator.nbits = n_dl_bwp; else dci_pdu->bwp_indicator.nbits = 2; size += dci_pdu->bwp_indicator.nbits; // Freq domain assignment - rbg_size_config = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size; - numRBG = getNRBG(NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), - NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), + if (pdsch_Config) rbg_size_config = pdsch_Config->rbg_Size; + else rbg_size_config = 0; + + numRBG = getNRBG(NRRIV2BW(bwpc->genericParameters.locationAndBandwidth, MAX_BWP_SIZE), + NRRIV2PRBOFFSET(bwpc->genericParameters.locationAndBandwidth, MAX_BWP_SIZE), rbg_size_config); - if (pdsch_config->resourceAllocation == 0) - dci_pdu->frequency_domain_assignment.nbits = numRBG; - else if (pdsch_config->resourceAllocation == 1) - dci_pdu->frequency_domain_assignment.nbits = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); + if (pdsch_Config && pdsch_Config->resourceAllocation == 0) + dci_pdu->frequency_domain_assignment.nbits = numRBG; + else if (pdsch_Config == NULL || pdsch_Config->resourceAllocation == 1) + dci_pdu->frequency_domain_assignment.nbits = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); else - dci_pdu->frequency_domain_assignment.nbits = ((int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )>numRBG) ? (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )+1 : numRBG+1; + dci_pdu->frequency_domain_assignment.nbits = ((int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )>numRBG) ? (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )+1 : numRBG+1; size += dci_pdu->frequency_domain_assignment.nbits; + LOG_D(NR_MAC,"dci_pdu->frequency_domain_assignment.nbits %d (N_RB %d)\n",dci_pdu->frequency_domain_assignment.nbits,N_RB); // Time domain assignment (see table 5.1.2.1.1-1 in 38.214 - if (pdsch_config->pdsch_TimeDomainAllocationList==NULL) { - if (bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList==NULL) + if (pdsch_Config == NULL || pdsch_Config->pdsch_TimeDomainAllocationList==NULL) { + if (bwpc->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList==NULL) num_entries = 16; // num of entries in default table else - num_entries = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; + num_entries = bwpc->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; } else - num_entries = pdsch_config->pdsch_TimeDomainAllocationList->choice.setup->list.count; + num_entries = pdsch_Config->pdsch_TimeDomainAllocationList->choice.setup->list.count; dci_pdu->time_domain_assignment.nbits = (int)ceil(log2(num_entries)); + LOG_D(NR_MAC,"pdsch tda.nbits= %d\n",dci_pdu->time_domain_assignment.nbits); size += dci_pdu->time_domain_assignment.nbits; // VRB to PRB mapping - if ((pdsch_config->resourceAllocation == 1) && (bwp->bwp_Dedicated->pdsch_Config->choice.setup->vrb_ToPRB_Interleaver != NULL)) { + if (pdsch_Config && + pdsch_Config->resourceAllocation == 1 && + pdsch_Config->vrb_ToPRB_Interleaver != NULL) { dci_pdu->vrb_to_prb_mapping.nbits = 1; size += dci_pdu->vrb_to_prb_mapping.nbits; } // PRB bundling size indicator - if (pdsch_config->prb_BundlingType.present == NR_PDSCH_Config__prb_BundlingType_PR_dynamicBundling) { + if (pdsch_Config && + pdsch_Config->prb_BundlingType.present == NR_PDSCH_Config__prb_BundlingType_PR_dynamicBundling) { dci_pdu->prb_bundling_size_indicator.nbits = 1; size += dci_pdu->prb_bundling_size_indicator.nbits; } // Rate matching indicator - NR_RateMatchPatternGroup_t *group1 = pdsch_config->rateMatchPatternGroup1; - NR_RateMatchPatternGroup_t *group2 = pdsch_config->rateMatchPatternGroup2; + NR_RateMatchPatternGroup_t *group1 = pdsch_Config ? pdsch_Config->rateMatchPatternGroup1 : NULL; + NR_RateMatchPatternGroup_t *group2 = pdsch_Config ? pdsch_Config->rateMatchPatternGroup2 : NULL; if ((group1 != NULL) && (group2 != NULL)) dci_pdu->rate_matching_indicator.nbits = 2; if ((group1 != NULL) != (group2 != NULL)) dci_pdu->rate_matching_indicator.nbits = 1; size += dci_pdu->rate_matching_indicator.nbits; // ZP CSI-RS trigger - if (pdsch_config->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList != NULL) { - uint8_t nZP = pdsch_config->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList->list.count; + if (pdsch_Config && + pdsch_Config->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList != NULL) { + uint8_t nZP = pdsch_Config->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList->list.count; dci_pdu->zp_csi_rs_trigger.nbits = (int)ceil(log2(nZP+1)); } size += dci_pdu->zp_csi_rs_trigger.nbits; // TB1- MCS 5, NDI 1, RV 2 size += 8; // TB2 - long *maxCWperDCI = pdsch_config->maxNrofCodeWordsScheduledByDCI; + long *maxCWperDCI = pdsch_Config ? pdsch_Config->maxNrofCodeWordsScheduledByDCI : NULL; if ((maxCWperDCI != NULL) && (*maxCWperDCI == 2)) { size += 8; } // HARQ PID size += 4; // DAI - if (secondaryCellGroup->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook == NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic) { // FIXME in case of more than one serving cell + if (cg->physicalCellGroupConfig && + cg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook == NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic) { // FIXME in case of more than one serving cell dci_pdu->dai[0].nbits = 2; size += dci_pdu->dai[0].nbits; } + LOG_D(NR_MAC,"dci_pdu->dai[0].nbits %d\n",dci_pdu->dai[0].nbits); // TPC PUCCH size += 2; // PUCCH resource indicator size += 3; // PDSCH to HARQ timing indicator - uint8_t I = ubwp->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.count; + uint8_t I = pucch_Config->dl_DataToUL_ACK ? pucch_Config->dl_DataToUL_ACK->list.count : 8; dci_pdu->pdsch_to_harq_feedback_timing_indicator.nbits = (int)ceil(log2(I)); size += dci_pdu->pdsch_to_harq_feedback_timing_indicator.nbits; + LOG_D(NR_MAC,"dci_pdu->pdsch_to_harq_feedback_timing_indicator.nbits %d\n",dci_pdu->pdsch_to_harq_feedback_timing_indicator.nbits); // Antenna ports - NR_SetupRelease_DMRS_DownlinkConfig_t *typeA = pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA; - NR_SetupRelease_DMRS_DownlinkConfig_t *typeB = pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeB; + NR_SetupRelease_DMRS_DownlinkConfig_t *typeA = pdsch_Config ? pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA : NULL; + NR_SetupRelease_DMRS_DownlinkConfig_t *typeB = pdsch_Config ? pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB : NULL; + AssertFatal(typeA!=NULL || typeB!=NULL, "either dmrs_typeA or typeB must be configured\n"); dci_pdu->antenna_ports.nbits = getAntPortBitWidth(typeA,typeB); size += dci_pdu->antenna_ports.nbits; + LOG_D(NR_MAC,"dci_pdu->antenna_ports.nbits %d\n",dci_pdu->antenna_ports.nbits); // Tx Config Indication - long *isTciEnable = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]->tci_PresentInDCI; + long *isTciEnable = pdcch_Config->controlResourceSetToAddModList->list.array[0]->tci_PresentInDCI; if (isTciEnable != NULL) { dci_pdu->transmission_configuration_indication.nbits = 3; size += dci_pdu->transmission_configuration_indication.nbits; } // SRS request - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink==NULL) + if (cg->spCellConfig->spCellConfigDedicated->supplementaryUplink==NULL) dci_pdu->srs_request.nbits = 2; else dci_pdu->srs_request.nbits = 3; size += dci_pdu->srs_request.nbits; // CBGTI - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { - uint8_t maxCBGperTB = (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->maxCodeBlockGroupsPerTransportBlock + 1) * 2; - long *maxCWperDCI_rrc = pdsch_config->maxNrofCodeWordsScheduledByDCI; + if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig&& + cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { + uint8_t maxCBGperTB = (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->maxCodeBlockGroupsPerTransportBlock + 1) * 2; + long *maxCWperDCI_rrc = pdsch_Config->maxNrofCodeWordsScheduledByDCI; uint8_t maxCW = (maxCWperDCI_rrc == NULL) ? 1 : *maxCWperDCI_rrc; dci_pdu->cbgti.nbits = maxCBGperTB * maxCW; size += dci_pdu->cbgti.nbits; // CBGFI - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->codeBlockGroupFlushIndicator) { + if (cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->codeBlockGroupFlushIndicator) { dci_pdu->cbgfi.nbits = 1; size += dci_pdu->cbgfi.nbits; } @@ -2267,143 +2990,184 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrec int tdd_period_to_num[8] = {500,625,1000,1250,2000,2500,5000,10000}; -int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) { +int is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slot_t slot) { int period,period1,period2=0; - if (scc->tdd_UL_DL_ConfigurationCommon==NULL) return(1); + if (tdd_UL_DL_ConfigurationCommon==NULL) return(1); - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 && - scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530) - period1 = 3000+*scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; + if (tdd_UL_DL_ConfigurationCommon->pattern1.ext1 && + tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530) + period1 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; else - period1 = tdd_period_to_num[scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity]; + period1 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity]; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern2) { - if (scc->tdd_UL_DL_ConfigurationCommon->pattern2->ext1 && - scc->tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530) - period2 = 3000+*scc->tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530; + if (tdd_UL_DL_ConfigurationCommon->pattern2) { + if (tdd_UL_DL_ConfigurationCommon->pattern2->ext1 && + tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530) + period2 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530; else - period2 = tdd_period_to_num[scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity]; + period2 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity]; } period = period1+period2; - int scs=scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; + int scs=tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; int slots=period*(1<tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots ? 1 : 0); - else return(slot_in_period <= slots1+scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); + if (slot_in_period < slots1) return(slot_in_period <= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots ? 1 : 0); + else return(slot_in_period <= slots1+tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); } -int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) { +int is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slot, lte_frame_type_t frame_type) { int period,period1,period2=0; - if (scc->tdd_UL_DL_ConfigurationCommon==NULL) return(1); + // Note: condition on frame_type + // goal: the UL scheduler assumes mode is TDD therefore this hack is needed to make FDD work + if (tdd_UL_DL_ConfigurationCommon == NULL || frame_type == FDD) { + return(1); + } - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 && - scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530) - period1 = 3000+*scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; + if (tdd_UL_DL_ConfigurationCommon->pattern1.ext1 && + tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530) + period1 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; else - period1 = tdd_period_to_num[scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity]; + period1 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity]; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern2) { - if (scc->tdd_UL_DL_ConfigurationCommon->pattern2->ext1 && - scc->tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530) - period2 = 3000+*scc->tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530; + if (tdd_UL_DL_ConfigurationCommon->pattern2) { + if (tdd_UL_DL_ConfigurationCommon->pattern2->ext1 && + tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530) + period2 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530; else - period2 = tdd_period_to_num[scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity]; + period2 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity]; } period = period1+period2; - int scs=scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; + int scs=tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; int slots=period*(1<= scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots ? 1 : 0); - else return(slot_in_period >= slots1+scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); + if (slot_in_period < slots1) return(slot_in_period >= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots ? 1 : 0); + else return(slot_in_period >= slots1+tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); } -int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols) { +int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols, int startSymbol, int mappingtype_fromDCI) { + + int l0;int dmrs_AdditionalPosition = 0;int maxLength = 0; + NR_DMRS_DownlinkConfig_t *dmrs_config = NULL; + + LOG_D(MAC, "NrofSymbols:%d, startSymbol:%d, mappingtype:%d, dmrs_TypeA_Position:%d\n", NrOfSymbols, startSymbol, mappingtype_fromDCI, dmrs_TypeA_Position); - int l0; if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2) l0=2; else if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3) l0=3; else AssertFatal(1==0,"Illegal dmrs_TypeA_Position %d\n",(int)dmrs_TypeA_Position); - if (pdsch_Config == NULL) { // Initial BWP - return(1<dmrs_DownlinkForPDSCH_MappingTypeA && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) + dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; + } else if (mappingtype_fromDCI == typeB) { + if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) + dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup; + } else { + AssertFatal(1==0,"Incorrect Mappingtype\n"); + } + + AssertFatal(dmrs_config != NULL," DMRS configs not present in PDSCH DMRS Downlink config\n"); + + // default values of maxlength = len2, additionalposition is pos2 + if (dmrs_config->maxLength != NULL) maxLength = 2; + if (dmrs_config->dmrs_AdditionalPosition != NULL) dmrs_AdditionalPosition = *dmrs_config->dmrs_AdditionalPosition; + } + + uint8_t ld, row, column; + int32_t l_prime = -1; + + // columns 0-3 for TypeA, 4-7 for TypeB + column = (mappingtype_fromDCI == typeA) ? dmrs_AdditionalPosition : (dmrs_AdditionalPosition + 4); + + // Section 7.4.1.1.2 in Spec 38.211 + // For PDSCH Mapping TypeA, ld is duration between first OFDM of the slot and last OFDM symbol of the scheduled PDSCH resources + // For TypeB, ld is the duration of the scheduled PDSCH resources + ld = (mappingtype_fromDCI == typeA) ? (NrOfSymbols + startSymbol) : NrOfSymbols; + + // Section 7.4.1.1.2 in Spec 38.211 + //For PDSCH Mapping typeB, if PDSCH duration ld <=4, only single symbol DMRS is supported + if (mappingtype_fromDCI == typeB && ld <= 4) + maxLength = 1; + + AssertFatal(ld > 2 && ld < 15,"Illegal NrOfSymbols according to Table 5.1.2.1-1 Spec 38.214 %d\n",ld); + AssertFatal((NrOfSymbols + startSymbol) < 15,"Illegal S+L according to Table 5.1.2.1-1 Spec 38.214 S:%d L:%d\n",startSymbol, NrOfSymbols); + + if (mappingtype_fromDCI == typeA) { + + // Section 7.4.1.1.2 in Spec 38.211 + AssertFatal((l0 == 2) || (l0 == 3 && dmrs_AdditionalPosition != 3),"Wrong config, If dmrs_TypeA_Position POS3, ADD POS cannot be POS3 \n"); + + // Table 5.1.2.1-1 in Spec 38.214 + AssertFatal(startSymbol <= l0, "Wrong config, Start symbol %d cannot be later than dmrs_TypeA_Position %d \n", startSymbol, l0); + + // Section 7.4.1.1.2 in Spec 38.211 + AssertFatal(l0 == 2 || (l0 == 3 && (ld != 3 || ld != 4)), "ld 3 or 4 symbols only possible with dmrs_TypeA_Position POS2 \n"); + + } + + if (maxLength == 1) { + row = ld - 2; + l_prime = table_7_4_1_1_2_3_pdsch_dmrs_positions_l[row][column]; + l0 = 1 << l0; } else { - if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA && - pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) { - // Relative to start of slot - NR_DMRS_DownlinkConfig_t *dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; - AssertFatal(NrOfSymbols>1 && NrOfSymbols < 15,"Illegal NrOfSymbols %d\n",NrOfSymbols); - int pos2=0; - if (dmrs_config->maxLength == NULL) { - // this is Table 7.4.1.1.2-3: PDSCH DM-RS positions l for single-symbol DM-RS - if (dmrs_config->dmrs_AdditionalPosition == NULL) pos2=1; - else if (dmrs_config->dmrs_AdditionalPosition && *dmrs_config->dmrs_AdditionalPosition == NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0 ) - return(1<dmrs_AdditionalPosition); - break; - case 8 : - case 9: - return(1<dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1) - return(1<dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1) - return(1<dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos3) - return(1<dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1) - return(1<dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos3) - return(1<3,"Illegal NrOfSymbols %d for len2 DMRS\n",NrOfSymbols); - if (NrOfSymbols < 10) return(1<dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1) return(1<=0,"ERROR in configuration.Check Time Domain allocation of this Grant. l_prime < 1. row:%d, column:%d\n", row, column); + + l_prime = (mappingtype_fromDCI == typeA) ? (l_prime | l0) : (l_prime << startSymbol); + LOG_D(MAC, " PDSCH DMRS MASK in HEX:%x\n", l_prime); + + return l_prime; +} + +uint8_t get_pusch_mcs_table(long *mcs_Table, + int is_tp, + int dci_format, + int rnti_type, + int target_ss, + bool config_grant) { + + // implementing 6.1.4.1 in 38.214 + if (mcs_Table != NULL) { + if (config_grant || (rnti_type == NR_RNTI_CS)) { + if (*mcs_Table == NR_PUSCH_Config__mcs_Table_qam256) + return 1; + else + return (2+(is_tp<<1)); } - else if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB && - pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) { - // Relative to start of PDSCH resource - AssertFatal(1==0,"TypeB DMRS not supported yet\n"); + else { + if ((*mcs_Table == NR_PUSCH_Config__mcs_Table_qam256) && + (dci_format == NR_UL_DCI_FORMAT_0_1) && + ((rnti_type == NR_RNTI_C ) || (rnti_type == NR_RNTI_SP_CSI))) + return 1; + // TODO take into account UE configuration + if ((*mcs_Table == NR_PUSCH_Config__mcs_Table_qam64LowSE) && + (target_ss == NR_SearchSpace__searchSpaceType_PR_ue_Specific) && + ((rnti_type == NR_RNTI_C ) || (rnti_type == NR_RNTI_SP_CSI))) + return (2+(is_tp<<1)); + if (rnti_type == NR_RNTI_MCS_C) + return (2+(is_tp<<1)); + AssertFatal(1==0,"Invalid configuration to set MCS table"); } } - AssertFatal(1==0,"Shouldn't get here\n"); - return(-1); + else + return (0+(is_tp*3)); } @@ -2422,3 +3186,913 @@ int binomial(int n, int k) { return c; } +/* extract PTRS values from RC and validate it based upon 38.214 5.1.6.3 */ +bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, + uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs, + uint8_t *portIndex,uint8_t *nERatio, uint8_t *reOffset, + uint8_t NrOfSymbols) +{ + bool valid = true; + + /* as defined in T 38.214 5.1.6.3 */ + if(rbSize < 3) { + valid = false; + return valid; + } + /* Check for Frequency Density values */ + if(ptrs_config->frequencyDensity->list.count < 2) { + /* Default value for K_PTRS = 2 as defined in T 38.214 5.1.6.3 */ + *K_ptrs = 2; + } + else { + *K_ptrs = get_K_ptrs(*ptrs_config->frequencyDensity->list.array[0], + *ptrs_config->frequencyDensity->list.array[1], + rbSize); + } + /* Check for time Density values */ + if(ptrs_config->timeDensity->list.count < 3) { + /* Default value for L_PTRS = 1 as defined in T 38.214 5.1.6.3 */ + *L_ptrs = 1; + } + else { + *L_ptrs = get_L_ptrs(*ptrs_config->timeDensity->list.array[0], + *ptrs_config->timeDensity->list.array[1], + *ptrs_config->timeDensity->list.array[2], + mcsIndex, + mcsTable); + } + *portIndex =*ptrs_config->epre_Ratio; + *nERatio = *ptrs_config->resourceElementOffset; + *reOffset = 0; + /* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table + * 5.1.6.3-1 and Table 5.1.6.3-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present + */ + if(*K_ptrs ==2 || *K_ptrs ==4 ) { + valid = true; + } + else { + valid = false; + return valid; + } + if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2 ) { + valid = true; + } + else { + valid = false; + return valid; + } + /* PTRS is not present also : + * When the UE is receiving a PDSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume + * PT-RS is not transmitted + * When the UE is receiving a PDSCH with allocation duration of 2 symbols as defined in Clause 7.4.1.1.2 of [4, TS + * 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted. + */ + if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) { + valid = false; + return valid; + } + + /* Moved below check from scheduler function to here */ + if (*L_ptrs >= NrOfSymbols) { + valid = false; + return valid; + } + return valid; +} + +uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i_ssb) { + + switch (scs) { + case NR_SubcarrierSpacing_kHz15: + return symbol_ssb_AC[i_ssb]; //type A + case NR_SubcarrierSpacing_kHz30: + if (band == 5 || band == 66) + return symbol_ssb_BD[i_ssb]; //type B + else + return symbol_ssb_AC[i_ssb]; //type C + case NR_SubcarrierSpacing_kHz120: + return symbol_ssb_BD[i_ssb]; //type D + case NR_SubcarrierSpacing_kHz240: + return symbol_ssb_E[i_ssb]; + default: + AssertFatal(1 == 0, "SCS %ld not allowed for SSB \n",scs); + } +} + + +void csi_period_offset(NR_CSI_ReportConfig_t *csirep, + NR_NZP_CSI_RS_Resource_t *nzpcsi, + int *period, int *offset) { + + if(nzpcsi != NULL) { + + NR_CSI_ResourcePeriodicityAndOffset_PR p_and_o = nzpcsi->periodicityAndOffset->present; + + switch(p_and_o){ + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots4: + *period = 4; + *offset = nzpcsi->periodicityAndOffset->choice.slots4; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots5: + *period = 5; + *offset = nzpcsi->periodicityAndOffset->choice.slots5; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots8: + *period = 8; + *offset = nzpcsi->periodicityAndOffset->choice.slots8; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots10: + *period = 10; + *offset = nzpcsi->periodicityAndOffset->choice.slots10; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots16: + *period = 16; + *offset = nzpcsi->periodicityAndOffset->choice.slots16; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots20: + *period = 20; + *offset = nzpcsi->periodicityAndOffset->choice.slots20; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots32: + *period = 32; + *offset = nzpcsi->periodicityAndOffset->choice.slots32; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots40: + *period = 40; + *offset = nzpcsi->periodicityAndOffset->choice.slots40; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots64: + *period = 64; + *offset = nzpcsi->periodicityAndOffset->choice.slots64; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots80: + *period = 80; + *offset = nzpcsi->periodicityAndOffset->choice.slots80; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots160: + *period = 160; + *offset = nzpcsi->periodicityAndOffset->choice.slots160; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots320: + *period = 320; + *offset = nzpcsi->periodicityAndOffset->choice.slots320; + break; + case NR_CSI_ResourcePeriodicityAndOffset_PR_slots640: + *period = 640; + *offset = nzpcsi->periodicityAndOffset->choice.slots640; + break; + default: + AssertFatal(1==0,"No periodicity and offset found in CSI resource"); + } + + } + + if(csirep != NULL) { + + NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present; + + switch(p_and_o){ + case NR_CSI_ReportPeriodicityAndOffset_PR_slots4: + *period = 4; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots5: + *period = 5; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots8: + *period = 8; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots10: + *period = 10; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots16: + *period = 16; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots20: + *period = 20; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots40: + *period = 40; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots80: + *period = 80; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots160: + *period = 160; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots320: + *period = 320; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320; + break; + default: + AssertFatal(1==0,"No periodicity and offset resource found in CSI report"); + } + } +} + + +void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + frame_t frameP, + NR_MIB_t *mib, + uint8_t num_slot_per_frame, + uint8_t ssb_subcarrier_offset, + uint16_t ssb_start_symbol, + NR_SubcarrierSpacing_t scs_ssb, + frequency_range_t frequency_range, + int nr_band, + uint32_t ssb_index, + uint32_t ssb_period, + uint32_t ssb_offset_point_a) { + + NR_SubcarrierSpacing_t scs_pdcch; + + channel_bandwidth_t min_channel_bw; + + // according to Table 5.3.5-1 in 38.104 + // band 79 is the only one which minimum is 40 + // for all the other channels it is either 10 or 5 + // and there is no difference between the two for this implementation so it is set it to 10 + if (nr_band == 79) + min_channel_bw = bw_40MHz; + else + min_channel_bw = bw_10MHz; + + if (frequency_range == FR2) { + if(mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60) + scs_pdcch = NR_SubcarrierSpacing_kHz60; + else + scs_pdcch = NR_SubcarrierSpacing_kHz120; + } + else { + frequency_range = FR1; + if(mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60) + scs_pdcch = NR_SubcarrierSpacing_kHz15; + else + scs_pdcch = NR_SubcarrierSpacing_kHz30; + } + type0_PDCCH_CSS_config->scs_pdcch = scs_pdcch; + type0_PDCCH_CSS_config->ssb_index = ssb_index; + type0_PDCCH_CSS_config->frame = frameP; + + uint8_t ssb_slot = ssb_start_symbol/14; + + uint32_t is_condition_A = (ssb_subcarrier_offset == 0); // 38.213 ch.13 + uint32_t index_4msb = (mib->pdcch_ConfigSIB1.controlResourceSetZero); + uint32_t index_4lsb = (mib->pdcch_ConfigSIB1.searchSpaceZero); + + type0_PDCCH_CSS_config->num_rbs = -1; + type0_PDCCH_CSS_config->num_symbols = -1; + type0_PDCCH_CSS_config->rb_offset = -1; + LOG_D(NR_MAC,"NR_SubcarrierSpacing_kHz30 %d, scs_ssb %d, scs_pdcch %d, min_chan_bw %d\n",(int)NR_SubcarrierSpacing_kHz30,(int)scs_ssb,(int)scs_pdcch,min_channel_bw); + + // type0-pdcch coreset + switch( ((int)scs_ssb << 3) | (int)scs_pdcch ){ + case (NR_SubcarrierSpacing_kHz15 << 5) | NR_SubcarrierSpacing_kHz15: + AssertFatal(index_4msb < 15, "38.213 Table 13-1 4 MSB out of range\n"); + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_1_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_1_c3[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_1_c4[index_4msb]; + break; + + case (NR_SubcarrierSpacing_kHz15 << 3) | NR_SubcarrierSpacing_kHz30: + AssertFatal(index_4msb < 14, "38.213 Table 13-2 4 MSB out of range\n"); + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_2_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_2_c3[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_2_c4[index_4msb]; + break; + + case (NR_SubcarrierSpacing_kHz30 << 3) | NR_SubcarrierSpacing_kHz15: + if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)){ + AssertFatal(index_4msb < 9, "38.213 Table 13-3 4 MSB out of range\n"); + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_3_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_3_c3[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_3_c4[index_4msb]; + }else if(min_channel_bw & bw_40MHz){ + AssertFatal(index_4msb < 9, "38.213 Table 13-5 4 MSB out of range\n"); + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_5_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_5_c3[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_5_c4[index_4msb]; + }else{ ; } + + break; + + case (NR_SubcarrierSpacing_kHz30 << 3) | NR_SubcarrierSpacing_kHz30: + if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)){ + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_4_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_4_c3[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_4_c4[index_4msb]; + + }else if(min_channel_bw & bw_40MHz){ + AssertFatal(index_4msb < 10, "38.213 Table 13-6 4 MSB out of range\n"); + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_6_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_6_c3[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_6_c4[index_4msb]; + }else{ ; } + break; + + case (NR_SubcarrierSpacing_kHz120 << 3) | NR_SubcarrierSpacing_kHz60: + AssertFatal(index_4msb < 12, "38.213 Table 13-7 4 MSB out of range\n"); + if(index_4msb & 0x7){ + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + }else if(index_4msb & 0x18){ + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 2; + }else{ ; } + + type0_PDCCH_CSS_config->num_rbs = table_38213_13_7_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_7_c3[index_4msb]; + if(!is_condition_A && (index_4msb == 8 || index_4msb == 10)){ + type0_PDCCH_CSS_config->rb_offset = table_38213_13_7_c4[index_4msb] - 1; + }else{ + type0_PDCCH_CSS_config->rb_offset = table_38213_13_7_c4[index_4msb]; + } + break; + + case (NR_SubcarrierSpacing_kHz120 << 3) | NR_SubcarrierSpacing_kHz120: + AssertFatal(index_4msb < 8, "38.213 Table 13-8 4 MSB out of range\n"); + if(index_4msb & 0x3){ + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + }else if(index_4msb & 0x0c){ + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 3; + } + + type0_PDCCH_CSS_config->num_rbs = table_38213_13_8_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_8_c3[index_4msb]; + if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)){ + type0_PDCCH_CSS_config->rb_offset = table_38213_13_8_c4[index_4msb] - 1; + }else{ + type0_PDCCH_CSS_config->rb_offset = table_38213_13_8_c4[index_4msb]; + } + break; + + case (NR_SubcarrierSpacing_kHz240 << 3) | NR_SubcarrierSpacing_kHz60: + AssertFatal(index_4msb < 4, "38.213 Table 13-9 4 MSB out of range\n"); + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_9_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_9_c3[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_9_c4[index_4msb]; + break; + + case (NR_SubcarrierSpacing_kHz240 << 3) | NR_SubcarrierSpacing_kHz120: + AssertFatal(index_4msb < 8, "38.213 Table 13-10 4 MSB out of range\n"); + if(index_4msb & 0x3){ + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; + }else if(index_4msb & 0x0c){ + type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 2; + } + type0_PDCCH_CSS_config->num_rbs = table_38213_13_10_c2[index_4msb]; + type0_PDCCH_CSS_config->num_symbols = table_38213_13_10_c3[index_4msb]; + if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)){ + type0_PDCCH_CSS_config->rb_offset = table_38213_13_10_c4[index_4msb]-1; + }else{ + type0_PDCCH_CSS_config->rb_offset = table_38213_13_10_c4[index_4msb]; + } + + break; + + default: + LOG_E(NR_MAC,"NR_SubcarrierSpacing_kHz30 %d, scs_ssb %d, scs_pdcch %d, min_chan_bw %d\n",NR_SubcarrierSpacing_kHz30,(int)scs_ssb,(int)scs_pdcch,min_channel_bw); + break; + } + + LOG_D(NR_MAC,"Coreset0: index_4msb=%d, num_rbs=%d, num_symb=%d, rb_offset=%d\n", + index_4msb,type0_PDCCH_CSS_config->num_rbs,type0_PDCCH_CSS_config->num_symbols,type0_PDCCH_CSS_config->rb_offset ); + + AssertFatal(type0_PDCCH_CSS_config->num_rbs != -1, "Type0 PDCCH coreset num_rbs undefined, index_4msb=%d, min_channel_bw %d, scs_ssb %d, scs_pdcch %d\n",index_4msb,min_channel_bw,(int)scs_ssb,(int)scs_pdcch); + AssertFatal(type0_PDCCH_CSS_config->num_symbols != -1, "Type0 PDCCH coreset num_symbols undefined"); + AssertFatal(type0_PDCCH_CSS_config->rb_offset != -1, "Type0 PDCCH coreset rb_offset undefined"); + + + //uint32_t cell_id = 0; // obtain from L1 later + + //mac->type0_pdcch_dci_config.coreset.rb_start = rb_offset; + //mac->type0_pdcch_dci_config.coreset.rb_end = rb_offset + num_rbs - 1; + +// uint64_t mask = 0x0; +// uint8_t i; +// for(i=0; i<(type0_PDCCH_CSS_config->num_rbs/6); ++i){ // 38.331 Each bit corresponds a group of 6 RBs +// mask = mask >> 1; +// mask = mask | 0x100000000000; +// } + + //LOG_I(MAC,">>>>>>>>mask %x num_rbs %d rb_offset %d\n", mask, num_rbs, rb_offset); + +// mac->type0_pdcch_dci_config.coreset.frequency_domain_resource = mask; +// mac->type0_pdcch_dci_config.coreset.rb_offset = rb_offset; // additional parameter other than coreset +// +// //mac->type0_pdcch_dci_config.type0_pdcch_coreset.duration = num_symbols; +// mac->type0_pdcch_dci_config.coreset.cce_reg_mapping_type = CCE_REG_MAPPING_TYPE_INTERLEAVED; +// mac->type0_pdcch_dci_config.coreset.cce_reg_interleaved_reg_bundle_size = 6; // L 38.211 7.3.2.2 +// mac->type0_pdcch_dci_config.coreset.cce_reg_interleaved_interleaver_size = 2; // R 38.211 7.3.2.2 +// mac->type0_pdcch_dci_config.coreset.cce_reg_interleaved_shift_index = cell_id; +// mac->type0_pdcch_dci_config.coreset.precoder_granularity = PRECODER_GRANULARITY_SAME_AS_REG_BUNDLE; +// mac->type0_pdcch_dci_config.coreset.pdcch_dmrs_scrambling_id = cell_id; + + + // type0-pdcch search space + float big_o = 0.0f; + float big_m = 0.0f; + type0_PDCCH_CSS_config->sfn_c = SFN_C_IMPOSSIBLE; // only valid for mux=1 + type0_PDCCH_CSS_config->n_c = UINT_MAX; + type0_PDCCH_CSS_config->number_of_search_space_per_slot = UINT_MAX; + type0_PDCCH_CSS_config->first_symbol_index = UINT_MAX; + type0_PDCCH_CSS_config->search_space_duration = 0; // element of search space + // 38.213 table 10.1-1 + + /// MUX PATTERN 1 + if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR1){ + big_o = table_38213_13_11_c1[index_4lsb]; + type0_PDCCH_CSS_config->number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb]; + big_m = table_38213_13_11_c3[index_4lsb]; + + uint32_t temp = (uint32_t)(big_o*(1<ssb_index*big_m); + type0_PDCCH_CSS_config->n_c = temp / num_slot_per_frame; + if((temp/num_slot_per_frame) & 0x1){ + type0_PDCCH_CSS_config->sfn_c = SFN_C_MOD_2_EQ_1; + }else{ + type0_PDCCH_CSS_config->sfn_c = SFN_C_MOD_2_EQ_0; + } + + if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (type0_PDCCH_CSS_config->ssb_index&1)){ + type0_PDCCH_CSS_config->first_symbol_index = type0_PDCCH_CSS_config->num_symbols; + }else{ + type0_PDCCH_CSS_config->first_symbol_index = table_38213_13_11_c4[index_4lsb]; + } + // 38.213 chapter 13: over two consecutive slots + type0_PDCCH_CSS_config->search_space_duration = 2; + // two frames + type0_PDCCH_CSS_config->search_space_frame_period = nr_slots_per_frame[scs_ssb]<<1; + } + + if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){ + big_o = table_38213_13_12_c1[index_4lsb]; + type0_PDCCH_CSS_config->number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb]; + big_m = table_38213_13_12_c3[index_4lsb]; + + if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (type0_PDCCH_CSS_config->ssb_index&1)){ + type0_PDCCH_CSS_config->first_symbol_index = 7; + }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (type0_PDCCH_CSS_config->ssb_index&1)){ + type0_PDCCH_CSS_config->first_symbol_index = type0_PDCCH_CSS_config->num_symbols; + }else{ + type0_PDCCH_CSS_config->first_symbol_index = 0; + } + // 38.213 chapter 13: over two consecutive slots + type0_PDCCH_CSS_config->search_space_duration = 2; + // two frames + type0_PDCCH_CSS_config->search_space_frame_period = nr_slots_per_frame[scs_ssb]<<1; + } + + /// MUX PATTERN 2 + if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 2){ + + if((scs_ssb == NR_SubcarrierSpacing_kHz120) && (scs_pdcch == NR_SubcarrierSpacing_kHz60)){ + // 38.213 Table 13-13 + AssertFatal(index_4lsb == 0, "38.213 Table 13-13 4 LSB out of range\n"); + // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot + // sfn_c = SFN_C_EQ_SFN_SSB; + type0_PDCCH_CSS_config->n_c = ssb_slot; + switch(type0_PDCCH_CSS_config->ssb_index & 0x3){ // ssb_index(i) mod 4 + case 0: + type0_PDCCH_CSS_config->first_symbol_index = 0; + break; + case 1: + type0_PDCCH_CSS_config->first_symbol_index = 1; + break; + case 2: + type0_PDCCH_CSS_config->first_symbol_index = 6; + break; + case 3: + type0_PDCCH_CSS_config->first_symbol_index = 7; + break; + default: break; + } + + }else if((scs_ssb == NR_SubcarrierSpacing_kHz240) && (scs_pdcch == NR_SubcarrierSpacing_kHz120)){ + // 38.213 Table 13-14 + AssertFatal(index_4lsb == 0, "38.213 Table 13-14 4 LSB out of range\n"); + // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot + // sfn_c = SFN_C_EQ_SFN_SSB; + type0_PDCCH_CSS_config->n_c = ssb_slot; + switch(type0_PDCCH_CSS_config->ssb_index & 0x7){ // ssb_index(i) mod 8 + case 0: + type0_PDCCH_CSS_config->first_symbol_index = 0; + break; + case 1: + type0_PDCCH_CSS_config->first_symbol_index = 1; + break; + case 2: + type0_PDCCH_CSS_config->first_symbol_index = 2; + break; + case 3: + type0_PDCCH_CSS_config->first_symbol_index = 3; + break; + case 4: + type0_PDCCH_CSS_config->first_symbol_index = 12; + type0_PDCCH_CSS_config->n_c = ssb_slot - 1; + break; + case 5: + type0_PDCCH_CSS_config->first_symbol_index = 13; + type0_PDCCH_CSS_config->n_c = ssb_slot - 1; + break; + case 6: + type0_PDCCH_CSS_config->first_symbol_index = 0; + break; + case 7: + type0_PDCCH_CSS_config->first_symbol_index = 1; + break; + default: break; + } + }else{ ; } + // 38.213 chapter 13: over one slot + type0_PDCCH_CSS_config->search_space_duration = 1; + // SSB periodicity in slots + type0_PDCCH_CSS_config->search_space_frame_period = ssb_period*nr_slots_per_frame[scs_ssb]; + } + + /// MUX PATTERN 3 + if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 3){ + if((scs_ssb == NR_SubcarrierSpacing_kHz120) && (scs_pdcch == NR_SubcarrierSpacing_kHz120)){ + // 38.213 Table 13-15 + AssertFatal(index_4lsb == 0, "38.213 Table 13-15 4 LSB out of range\n"); + // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot + // sfn_c = SFN_C_EQ_SFN_SSB; + type0_PDCCH_CSS_config->n_c = ssb_slot; + switch(type0_PDCCH_CSS_config->ssb_index & 0x3){ // ssb_index(i) mod 4 + case 0: + type0_PDCCH_CSS_config->first_symbol_index = 4; + break; + case 1: + type0_PDCCH_CSS_config->first_symbol_index = 8; + break; + case 2: + type0_PDCCH_CSS_config->first_symbol_index = 2; + break; + case 3: + type0_PDCCH_CSS_config->first_symbol_index = 6; + break; + default: break; + } + }else{ ; } + // 38.213 chapter 13: over one slot + type0_PDCCH_CSS_config->search_space_duration = 1; + // SSB periodicity in slots + type0_PDCCH_CSS_config->search_space_frame_period = ssb_period*nr_slots_per_frame[scs_ssb]; + } + + AssertFatal(type0_PDCCH_CSS_config->number_of_search_space_per_slot!=UINT_MAX,""); + +// uint32_t coreset_duration = num_symbols * number_of_search_space_per_slot; +// mac->type0_pdcch_dci_config.number_of_candidates[0] = table_38213_10_1_1_c2[0]; +// mac->type0_pdcch_dci_config.number_of_candidates[1] = table_38213_10_1_1_c2[1]; +// mac->type0_pdcch_dci_config.number_of_candidates[2] = table_38213_10_1_1_c2[2]; // CCE aggregation level = 4 +// mac->type0_pdcch_dci_config.number_of_candidates[3] = table_38213_10_1_1_c2[3]; // CCE aggregation level = 8 +// mac->type0_pdcch_dci_config.number_of_candidates[4] = table_38213_10_1_1_c2[4]; // CCE aggregation level = 16 +// mac->type0_pdcch_dci_config.duration = search_space_duration; +// mac->type0_pdcch_dci_config.coreset.duration = coreset_duration; // coreset +// AssertFatal(first_symbol_index!=UINT_MAX,""); +// mac->type0_pdcch_dci_config.monitoring_symbols_within_slot = (0x3fff << first_symbol_index) & (0x3fff >> (14-coreset_duration-first_symbol_index)) & 0x3fff; + + AssertFatal(type0_PDCCH_CSS_config->sfn_c!=SFN_C_IMPOSSIBLE,""); + AssertFatal(type0_PDCCH_CSS_config->n_c!=UINT_MAX,""); + + type0_PDCCH_CSS_config->n_0 = ((uint32_t)(big_o*(1<ssb_index*big_m))%num_slot_per_frame; + type0_PDCCH_CSS_config->cset_start_rb = ssb_offset_point_a - type0_PDCCH_CSS_config->rb_offset; + +} + +void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { + + int32_t duration; + + if (coreset0 == NULL) + coreset0 = calloc(1,sizeof(*coreset0)); + + coreset0->controlResourceSetId = 0; + + AssertFatal(type0_PDCCH_CSS_config!=NULL,"No type0 CSS configuration\n"); + + duration = type0_PDCCH_CSS_config->num_symbols; + + if(coreset0->frequencyDomainResources.buf == NULL) coreset0->frequencyDomainResources.buf = calloc(1,6); + + switch(type0_PDCCH_CSS_config->num_rbs){ + case 24: + coreset0->frequencyDomainResources.buf[0] = 0xf0; + coreset0->frequencyDomainResources.buf[1] = 0; + break; + case 48: + coreset0->frequencyDomainResources.buf[0] = 0xff; + coreset0->frequencyDomainResources.buf[1] = 0; + break; + case 96: + coreset0->frequencyDomainResources.buf[0] = 0xff; + coreset0->frequencyDomainResources.buf[1] = 0xff; + break; + default: + AssertFatal(1==0,"Invalid number of PRBs %d for Coreset0\n",type0_PDCCH_CSS_config->num_rbs); + } + coreset0->frequencyDomainResources.buf[2] = 0; + coreset0->frequencyDomainResources.buf[3] = 0; + coreset0->frequencyDomainResources.buf[4] = 0; + coreset0->frequencyDomainResources.buf[5] = 0; + coreset0->frequencyDomainResources.size = 6; + coreset0->frequencyDomainResources.bits_unused = 3; + + coreset0->duration = duration; + coreset0->cce_REG_MappingType.present=NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved; + coreset0->cce_REG_MappingType.choice.interleaved=calloc(1,sizeof(*coreset0->cce_REG_MappingType.choice.interleaved)); + coreset0->cce_REG_MappingType.choice.interleaved->reg_BundleSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6; + coreset0->cce_REG_MappingType.choice.interleaved->interleaverSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n2; + coreset0->cce_REG_MappingType.choice.interleaved->shiftIndex = NULL; // -> use cell_id + coreset0->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; + + coreset0->tci_StatesPDCCH_ToAddList = NULL; + coreset0->tci_StatesPDCCH_ToReleaseList = NULL; + coreset0->tci_PresentInDCI = NULL; + coreset0->pdcch_DMRS_ScramblingID = NULL; + +} + +void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { + + if(ss0 == NULL) ss0=calloc(1,sizeof(*ss0)); + if(ss0->controlResourceSetId == NULL) ss0->controlResourceSetId=calloc(1,sizeof(*ss0->controlResourceSetId)); + if(ss0->monitoringSymbolsWithinSlot == NULL) ss0->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss0->monitoringSymbolsWithinSlot)); + if(ss0->monitoringSymbolsWithinSlot->buf == NULL) ss0->monitoringSymbolsWithinSlot->buf = calloc(1,2); + if(ss0->nrofCandidates == NULL) ss0->nrofCandidates = calloc(1,sizeof(*ss0->nrofCandidates)); + if(ss0->searchSpaceType == NULL) ss0->searchSpaceType = calloc(1,sizeof(*ss0->searchSpaceType)); + if(ss0->searchSpaceType->choice.common == NULL) ss0->searchSpaceType->choice.common=calloc(1,sizeof(*ss0->searchSpaceType->choice.common)); + if(ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 == NULL) + ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); + + uint32_t duration,periodicity,offset; + uint16_t symbols,max_agg; + + AssertFatal(type0_PDCCH_CSS_config!=NULL,"No type0 CSS configuration\n"); + + max_agg = (type0_PDCCH_CSS_config->num_symbols*type0_PDCCH_CSS_config->num_rbs)/6; + + symbols = (1-(1<num_symbols))<first_symbol_index; + duration = type0_PDCCH_CSS_config->search_space_duration; + periodicity = type0_PDCCH_CSS_config->search_space_frame_period; + if (type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1) + offset = type0_PDCCH_CSS_config->n_0; + else + offset = type0_PDCCH_CSS_config->n_c; + + ss0->searchSpaceId = 0; + *ss0->controlResourceSetId = 0; + ss0->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss0->monitoringSlotPeriodicityAndOffset)); + set_monitoring_periodicity_offset(ss0,periodicity,offset); + if (duration==1) + ss0->duration = NULL; + else{ + ss0->duration = calloc(1,sizeof(*ss0->duration)); + *ss0->duration = duration; + } + + ss0->monitoringSymbolsWithinSlot->size = 2; + ss0->monitoringSymbolsWithinSlot->bits_unused = 2; + ss0->monitoringSymbolsWithinSlot->buf[1] = 0; + ss0->monitoringSymbolsWithinSlot->buf[0] = 0; + for (int i=0; i<8; i++) { + ss0->monitoringSymbolsWithinSlot->buf[1] |= ((symbols>>(i+8))&0x01)<<(7-i); + ss0->monitoringSymbolsWithinSlot->buf[0] |= ((symbols>>i)&0x01)<<(7-i); + } + + // max values are set according to TS38.213 Section 10.1 Table 10.1-1 + ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + ss0->nrofCandidates->aggregationLevel4 = (((max_agg>>2) > 4)? 4 : max_agg>>2); + ss0->nrofCandidates->aggregationLevel8 = (((max_agg>>3) > 2)? 2 : max_agg>>3); + ss0->nrofCandidates->aggregationLevel16 = (((max_agg>>4) > 1)? 1 : max_agg>>4); + + ss0->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; +} + + +void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset) { + NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR P_O = SchedulingReqRec->periodicityAndOffset->present; + switch (P_O){ + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1: + *period = 1; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl1; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl2: + *period = 2; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl2; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl4: + *period = 4; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl4; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl5: + *period = 5; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl5; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl8: + *period = 8; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl8; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10: + *period = 10; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl10; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl16: + *period = 16; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl16; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20: + *period = 20; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl20; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40: + *period = 40; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl40; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80: + *period = 80; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl80; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160: + *period = 160; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl160; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320: + *period = 320; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl320; + break; + case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640: + *period = 640; + *offset = SchedulingReqRec->periodicityAndOffset->choice.sl640; + break; + default: + AssertFatal(1==0,"No periodicityAndOffset resources found in schedulingrequestresourceconfig"); + } +} + +uint16_t compute_pucch_prb_size(uint8_t format, + uint8_t nr_prbs, + uint16_t O_tot, + uint16_t O_csi, + NR_PUCCH_MaxCodeRate_t *maxCodeRate, + uint8_t Qm, + uint8_t n_symb, + uint8_t n_re_ctrl) { + + uint16_t O_crc; + + if (O_tot<12) + O_crc = 0; + else{ + if (O_tot<20) + O_crc = 6; + else { + if (O_tot<360) + O_crc = 11; + else + AssertFatal(1==0,"Case for segmented PUCCH not yet implemented"); + } + } + + int rtimes100; + switch(*maxCodeRate){ + case NR_PUCCH_MaxCodeRate_zeroDot08 : + rtimes100 = 8; + break; + case NR_PUCCH_MaxCodeRate_zeroDot15 : + rtimes100 = 15; + break; + case NR_PUCCH_MaxCodeRate_zeroDot25 : + rtimes100 = 25; + break; + case NR_PUCCH_MaxCodeRate_zeroDot35 : + rtimes100 = 35; + break; + case NR_PUCCH_MaxCodeRate_zeroDot45 : + rtimes100 = 45; + break; + case NR_PUCCH_MaxCodeRate_zeroDot60 : + rtimes100 = 60; + break; + case NR_PUCCH_MaxCodeRate_zeroDot80 : + rtimes100 = 80; + break; + default : + AssertFatal(1==0,"Invalid MaxCodeRate"); + } + + float r = (float)rtimes100/100; + + if (O_csi == O_tot) { + if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r)) + AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs", + r,O_tot,O_crc,nr_prbs); + else + return nr_prbs; + } + + if (format==2){ + // TODO fix this for multiple CSI reports + for (int i=1; i<=nr_prbs; i++){ + if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) && + (O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r)) + return i; + } + AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs", + r,O_tot,O_crc,nr_prbs); + } + else{ + AssertFatal(1==0,"Not yet implemented"); + } +} + +/* extract UL PTRS values from RRC and validate it based upon 38.214 6.2.3 */ +bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, + uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs, + uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower, + uint8_t NrOfSymbols) +{ + bool valid = true; + + /* as defined in T 38.214 6.2.3 */ + if(rbSize < 3) { + valid = false; + return valid; + } + /* Check for Frequency Density values */ + if(ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.count < 2) { + /* Default value for K_PTRS = 2 as defined in T 38.214 6.2.3 */ + *K_ptrs = 2; + } + else { + *K_ptrs = get_K_ptrs(*ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[0], + *ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[1], + rbSize); + } + /* Check for time Density values */ + if(ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.count < 3) { + *L_ptrs = 0; + } + else { + *L_ptrs = get_L_ptrs(*ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[0], + *ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[1], + *ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[2], + mcsIndex, + mcsTable); + } + + *reOffset = *ul_ptrs_config->transformPrecoderDisabled->resourceElementOffset; + *maxNumPorts = ul_ptrs_config->transformPrecoderDisabled->maxNrofPorts; + *ulPower = ul_ptrs_config->transformPrecoderDisabled->ptrs_Power; + /* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table + * 6.2.3.1-1 and Table 6.2.3.1-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present + */ + if(*K_ptrs ==2 || *K_ptrs ==4 ) { + valid = true; + } + else { + valid = false; + return valid; + } + if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2 ) { + valid = true; + } + else { + valid = false; + return valid; + } + /* PTRS is not present also : + * When the UE is receiving a PUSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume + * PT-RS is not transmitted + * When the UE is receiving a PUSCH with allocation duration of 2 symbols as defined in Clause 6.4.1.2.2 of [4, TS + * 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted. + */ + if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) { + valid = false; + return valid; + } + + /* Moved below check from nr_ue_scheduler function to here */ + if (*L_ptrs >= NrOfSymbols) { + valid = false; + return valid; + } + return valid; +} + diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index a5e38bf128..8182e1c930 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -20,71 +20,47 @@ */ /*! \file mac.h -* \brief MAC data structures, constant, and function prototype +* \brief common MAC function prototypes * \author Navid Nikaein and Raymond Knopp, WIE-TAI CHEN * \date Dec. 2019 * \version 0.1 * \company Eurecom * \email raymond.knopp@eurecom.fr - */ #ifndef __LAYER2_NR_MAC_COMMON_H__ #define __LAYER2_NR_MAC_COMMON_H__ +#include "NR_MIB.h" #include "NR_PDSCH-Config.h" #include "NR_CellGroupConfig.h" #include "nr_mac.h" - -typedef enum { - NR_DL_DCI_FORMAT_1_0 = 0, - NR_DL_DCI_FORMAT_1_1, - NR_DL_DCI_FORMAT_2_0, - NR_DL_DCI_FORMAT_2_1, - NR_DL_DCI_FORMAT_2_2, - NR_DL_DCI_FORMAT_2_3, - NR_UL_DCI_FORMAT_0_0, - NR_UL_DCI_FORMAT_0_1 -} nr_dci_format_t; - -typedef enum { - NR_RNTI_new = 0, - NR_RNTI_C, - NR_RNTI_RA, - NR_RNTI_P, - NR_RNTI_CS, - NR_RNTI_TC, - NR_RNTI_SP_CSI, - NR_RNTI_SI, - NR_RNTI_SFI, - NR_RNTI_INT, - NR_RNTI_TPC_PUSCH, - NR_RNTI_TPC_PUCCH, - NR_RNTI_TPC_SRS -} nr_rnti_type_t; - -uint16_t config_bandwidth(int mu, int nb_rb, int nr_band); - -void get_band(uint64_t downlink_frequency, uint16_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type); +#include "openair1/PHY/impl_defs_nr.h" uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw); -int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols); +int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols,int startSymbol,int mappingtype_fromDCI); -int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); +int is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slot_t slotP); -int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); +int is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slotP, lte_frame_type_t frame_type); -uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *secondaryCellGroup, +uint16_t nr_dci_size(const NR_BWP_DownlinkCommon_t *initialDLBWP, + const NR_BWP_UplinkCommon_t *initialULBWP, + const NR_CellGroupConfig_t *cg, dci_pdu_rel15_t *dci_pdu, nr_dci_format_t format, - nr_rnti_type_t rnti_type, - uint16_t N_RB, + nr_rnti_type_t rnti_type, + uint16_t N_RB, int bwp_id); +void find_aggregation_candidates(uint8_t *aggregation_level, + uint8_t *nr_of_candidates, + NR_SearchSpace_t *ss, + int maxL); + void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset); @@ -98,23 +74,131 @@ int get_nr_prach_info_from_index(uint8_t index, uint16_t *format, uint8_t *start_symbol, uint8_t *N_t_slot, - uint8_t *N_dur); + uint8_t *N_dur, + uint16_t *RA_sfn_index, + uint8_t *N_RA_slot, + uint8_t *config_period); + +int get_nr_prach_occasion_info_from_index(uint8_t index, + uint32_t pointa, + uint8_t mu, + uint8_t unpaired, + uint16_t *format, + uint8_t *start_symbol, + uint8_t *N_t_slot, + uint8_t *N_dur, + uint8_t *N_RA_slot, + uint16_t *N_RA_sfn, + uint8_t *max_association_period); + +uint8_t get_pusch_mcs_table(long *mcs_Table, + int is_tp, + int dci_format, + int rnti_type, + int target_ss, + bool config_grant); uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, uint8_t nb_preambles, - uint8_t unpaired); + uint8_t unpaired, + frequency_range_t); int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPrecoder); -int get_format0(uint8_t index, uint8_t unpaired); +int get_format0(uint8_t index, uint8_t unpaired,frequency_range_t); + +int64_t *get_prach_config_info(frequency_range_t freq_range, + uint8_t index, + uint8_t unpaired); uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); -int get_num_dmrs(uint16_t dmrs_mask ); uint8_t get_l0_ul(uint8_t mapping_type, uint8_t dmrs_typeA_position); -int32_t get_l_prime(uint8_t duration_in_symbols, uint8_t mapping_type, pusch_dmrs_AdditionalPosition_t additional_pos, pusch_maxLength_t pusch_maxLength); +int32_t get_l_prime(uint8_t duration_in_symbols, uint8_t mapping_type, pusch_dmrs_AdditionalPosition_t additional_pos, pusch_maxLength_t pusch_maxLength, uint8_t start_symbolt, uint8_t dmrs_typeA_position); uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint8_t mcs_table); uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB); +void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + frame_t frameP, + NR_MIB_t *mib, + uint8_t num_slot_per_frame, + uint8_t ssb_subcarrier_offset, + uint16_t ssb_start_symbol, + NR_SubcarrierSpacing_t scs_ssb, + frequency_range_t frequency_range, + int nr_band, + uint32_t ssb_index, + uint32_t ssb_period, + uint32_t ssb_offset_point_a); + +uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i_ssb); + +void get_info_from_tda_tables(int default_abc, + int tda, + int dmrs_TypeA_Position, + int normal_CP, + int *startSymbolIndex, + int *nrOfSymbols); + +void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); +void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); + +uint16_t compute_pucch_prb_size(uint8_t format, + uint8_t nr_prbs, + uint16_t O_tot, + uint16_t O_csi, + NR_PUCCH_MaxCodeRate_t *maxCodeRate, + uint8_t Qm, + uint8_t n_symb, + uint8_t n_re_ctrl); + +int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); + +void find_period_offest_SR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset); + +void csi_period_offset(NR_CSI_ReportConfig_t *csirep, + NR_NZP_CSI_RS_Resource_t *nzpcsi, + int *period, int *offset); + +void reverse_n_bits(uint8_t *value, uint16_t bitlen); + +bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, + uint16_t rbSize, uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex, + uint8_t *nERatio,uint8_t *reOffset, + uint8_t NrOfSymbols); + +bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, + uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs, + uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower, + uint8_t NrOfSymbols); + +uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols,int startSymbol,int mappingtype); + +/* \brief Set the transform precoding according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16 +@param *pusch_config, pointer to pusch config +@param *ubwp pointer to uplink bwp +@param *dci_format pointer to dci format +@param rnti_type rnti type +@param configuredGrant indicates whether a configured grant was received or not +@returns transformPrecoding value */ +uint8_t get_transformPrecoding(const NR_BWP_UplinkCommon_t *initialUplinkBWP, + const NR_PUSCH_Config_t *pusch_config, + const NR_BWP_UplinkDedicated_t *ubwp, + uint8_t *dci_format, + int rnti_type, + uint8_t configuredGrant); + +void nr_mac_gNB_rrc_ul_failure(const module_id_t Mod_instP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t subframeP, + const rnti_t rntiP); + +void nr_mac_gNB_rrc_ul_failure_reset(const module_id_t Mod_instP, + const frame_t frameP, + const sub_frame_t subframeP, + const rnti_t rntiP); #endif diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h index 5c714e4a93..5def748d42 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h @@ -37,6 +37,8 @@ /*#include "PHY/defs_common.h"*/ +extern const uint8_t nr_slots_per_frame[5]; + /* extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE]; extern const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE]; extern const uint8_t cqi2fmt0_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]; @@ -54,7 +56,6 @@ extern unsigned char NB_UE_INST;*/ extern unsigned char NB_INST; extern unsigned char NB_eNB_INST; extern unsigned char NB_RN_INST; -extern unsigned short NODE_ID[1]; /* Scheduler */ extern RAN_CONTEXT_t RC; @@ -75,5 +76,69 @@ extern boolean_t pre_scd_activeUE[NUMBER_OF_UE_MAX]; extern eNB_UE_STATS pre_scd_eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; #endif*/ +extern const uint32_t NR_SHORT_BSR_TABLE[NR_SHORT_BSR_TABLE_SIZE]; +extern const uint32_t NR_LONG_BSR_TABLE[NR_LONG_BSR_TABLE_SIZE]; + +// Type0-PDCCH search space +extern const int32_t table_38213_13_1_c1[16]; +extern const int32_t table_38213_13_1_c2[16]; +extern const int32_t table_38213_13_1_c3[16]; +extern const int32_t table_38213_13_1_c4[16]; + +extern const int32_t table_38213_13_2_c1[16]; +extern const int32_t table_38213_13_2_c2[16]; +extern const int32_t table_38213_13_2_c3[16]; +extern const int32_t table_38213_13_2_c4[16]; + +extern const int32_t table_38213_13_3_c1[16]; +extern const int32_t table_38213_13_3_c2[16]; +extern const int32_t table_38213_13_3_c3[16]; +extern const int32_t table_38213_13_3_c4[16]; + +extern const int32_t table_38213_13_4_c1[16]; +extern const int32_t table_38213_13_4_c2[16]; +extern const int32_t table_38213_13_4_c3[16]; +extern const int32_t table_38213_13_4_c4[16]; + +extern const int32_t table_38213_13_5_c1[16]; +extern const int32_t table_38213_13_5_c2[16]; +extern const int32_t table_38213_13_5_c3[16]; +extern const int32_t table_38213_13_5_c4[16]; + +extern const int32_t table_38213_13_6_c1[16]; +extern const int32_t table_38213_13_6_c2[16]; +extern const int32_t table_38213_13_6_c3[16]; +extern const int32_t table_38213_13_6_c4[16]; + +extern const int32_t table_38213_13_7_c1[16]; +extern const int32_t table_38213_13_7_c2[16]; +extern const int32_t table_38213_13_7_c3[16]; +extern const int32_t table_38213_13_7_c4[16]; + +extern const int32_t table_38213_13_8_c1[16]; +extern const int32_t table_38213_13_8_c2[16]; +extern const int32_t table_38213_13_8_c3[16]; +extern const int32_t table_38213_13_8_c4[16]; + +extern const int32_t table_38213_13_9_c1[16]; +extern const int32_t table_38213_13_9_c2[16]; +extern const int32_t table_38213_13_9_c3[16]; +extern const int32_t table_38213_13_9_c4[16]; + +extern const int32_t table_38213_13_10_c1[16]; +extern const int32_t table_38213_13_10_c2[16]; +extern const int32_t table_38213_13_10_c3[16]; +extern const int32_t table_38213_13_10_c4[16]; + +extern const float table_38213_13_11_c1[16]; +extern const int32_t table_38213_13_11_c2[16]; +extern const float table_38213_13_11_c3[16]; +extern const int32_t table_38213_13_11_c4[16]; + +extern const float table_38213_13_12_c1[16]; +extern const int32_t table_38213_13_12_c2[16]; +extern const float table_38213_13_12_c3[16]; + +extern const int32_t table_38213_10_1_1_c2[5]; #endif //DEF_H diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c old mode 100755 new mode 100644 index bc98e16d39..764c92ecb7 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -31,9 +31,12 @@ */ //#include "mac_defs.h" +#include #include "NR_MAC_UE/mac_proto.h" #include "NR_MAC-CellGroupConfig.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" +#include "common/utils/nr/nr_common.h" +#include "executables/softmodem-common.h" int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, @@ -41,47 +44,11 @@ int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int nrofUplinkSlots, int nrofUplinkSymbols) { int slot_number = 0; - int nb_periods_per_frame; + int nb_periods_per_frame = get_nb_periods_per_frame(cfg->tdd_table.tdd_period); int nb_slots_to_set = TDD_CONFIG_NB_FRAMES*(1<tdd_table.tdd_period) { - case 0: - nb_periods_per_frame = 20; // 10ms/0p5ms - break; - - case 1: - nb_periods_per_frame = 16; // 10ms/0p625ms - break; - - case 2: - nb_periods_per_frame = 10; // 10ms/1ms - break; - - case 3: - nb_periods_per_frame = 8; // 10ms/1p25ms - break; - - case 4: - nb_periods_per_frame = 5; // 10ms/2ms - break; - - case 5: - nb_periods_per_frame = 4; // 10ms/2p5ms - break; - - case 6: - nb_periods_per_frame = 2; // 10ms/5ms - break; - - case 7: - nb_periods_per_frame = 1; // 10ms/10ms - break; - - default: - AssertFatal(1==0,"Undefined tdd period %d\n", cfg->tdd_table.tdd_period); - } - int nb_slots_per_period = ((1<tdd_table.tdd_period_in_slots = nb_slots_per_period; if ( (nrofDownlinkSymbols + nrofUplinkSymbols) == 0 ) AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots), @@ -140,33 +107,31 @@ int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, } -void config_common_ue(NR_UE_MAC_INST_t *mac, - module_id_t module_id, - int cc_idP) { +void config_common_ue_sa(NR_UE_MAC_INST_t *mac, + module_id_t module_id, + int cc_idP) { - fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - NR_ServingCellConfigCommon_t *scc = mac->scc; - int i; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + NR_ServingCellConfigCommonSIB_t *scc = mac->scc_SIB; mac->phy_config.Mod_id = module_id; mac->phy_config.CC_id = cc_idP; - + + LOG_D(MAC, "Entering SA UE Config Common\n"); + // carrier config + cfg->carrier_config.dl_bandwidth = config_bandwidth(scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + *scc->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR); - LOG_I(MAC,"UE Config Common\n"); + uint64_t dl_bw_khz = (12*scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth)* + (15<downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing); + cfg->carrier_config.dl_frequency = (downlink_frequency[cc_idP][0]/1000) - (dl_bw_khz>>1); - cfg->carrier_config.dl_bandwidth = config_bandwidth(scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, - *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); - - cfg->carrier_config.dl_frequency = from_nrarfcn(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], - *scc->ssbSubcarrierSpacing, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA)/1000; // freq in kHz - - for (i=0; i<5; i++) { - if (i==scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { - cfg->carrier_config.dl_grid_size[i] = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - cfg->carrier_config.dl_k0[i] = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; + for (int i=0; i<5; i++) { + if (i==scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { + cfg->carrier_config.dl_grid_size[i] = scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + cfg->carrier_config.dl_k0[i] = scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->offsetToCarrier; } else { cfg->carrier_config.dl_grid_size[i] = 0; @@ -174,25 +139,23 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, } } - cfg->carrier_config.uplink_bandwidth = config_bandwidth(scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, - *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]); + cfg->carrier_config.uplink_bandwidth = config_bandwidth(scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + scc->uplinkConfigCommon->frequencyInfoUL.frequencyBandList==NULL ? + *scc->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR : + *scc->uplinkConfigCommon->frequencyInfoUL.frequencyBandList->list.array[0]->freqBandIndicatorNR); - int UL_pointA; - if (scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA == NULL) - UL_pointA = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; + + if (scc->uplinkConfigCommon->frequencyInfoUL.absoluteFrequencyPointA == NULL) + cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency; else - UL_pointA = *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA; + // TODO check if corresponds to what reported in SIB1 + cfg->carrier_config.uplink_frequency = (downlink_frequency[cc_idP][0]/1000) + uplink_frequency_offset[cc_idP][0]; - cfg->carrier_config.uplink_frequency = from_nrarfcn(*scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0], - *scc->ssbSubcarrierSpacing, - UL_pointA)/1000; // freq in kHz - - - for (i=0; i<5; i++) { - if (i==scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { - cfg->carrier_config.ul_grid_size[i] = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - cfg->carrier_config.ul_k0[i] = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; + for (int i=0; i<5; i++) { + if (i==scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { + cfg->carrier_config.ul_grid_size[i] = scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + cfg->carrier_config.ul_k0[i] = scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->offsetToCarrier; } else { cfg->carrier_config.ul_grid_size[i] = 0; @@ -200,55 +163,31 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, } } - lte_frame_type_t frame_type; - uint16_t band; - int32_t offset; - - get_band((cfg->carrier_config.dl_frequency)*1000, - &band, - &offset, - &frame_type); - - + mac->nr_band = *scc->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR; + mac->frame_type = get_frame_type(mac->nr_band, get_softmodem_params()->numerology); // cell config - cfg->cell_config.phy_cell_id = *scc->physCellId; - cfg->cell_config.frame_duplex_type = frame_type; + cfg->cell_config.phy_cell_id = mac->physCellId; + cfg->cell_config.frame_duplex_type = mac->frame_type; // SSB config cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; - cfg->ssb_config.scs_common = *scc->ssbSubcarrierSpacing; + cfg->ssb_config.scs_common = get_softmodem_params()->numerology; // SSB Table config - int scs_scaling = 1<<(cfg->ssb_config.scs_common); - if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) - scs_scaling = scs_scaling*3; - if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) - scs_scaling = scs_scaling>>2; - uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); - cfg->ssb_table.ssb_offset_point_a = absolute_diff/(12*scs_scaling) - 10; - cfg->ssb_table.ssb_period = *scc->ssb_periodicityServingCell; - cfg->ssb_table.ssb_subcarrier_offset = 0; // TODO currently not in RRC? + cfg->ssb_table.ssb_offset_point_a = scc->downlinkConfigCommon.frequencyInfoDL.offsetToPointA; + cfg->ssb_table.ssb_period = scc->ssb_PeriodicityServingCell; + cfg->ssb_table.ssb_subcarrier_offset = mac->ssb_subcarrier_offset; - switch (scc->ssb_PositionsInBurst->present) { - case 1 : - cfg->ssb_table.ssb_mask_list[0].ssb_mask = scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0]<<24; - cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; - break; - case 2 : - cfg->ssb_table.ssb_mask_list[0].ssb_mask = scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0]<<24; - cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; - break; - case 3 : - cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0; - cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; - for (i=0; i<4; i++) { - cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<ssb_PositionsInBurst->present); + if (mac->frequency_range == FR1){ + cfg->ssb_table.ssb_mask_list[0].ssb_mask = scc->ssb_PositionsInBurst.inOneGroup.buf[0]<<24; + cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; + } + else{ + for (int i=0; i<8; i++){ + if ((scc->ssb_PositionsInBurst.groupPresence->buf[0]>>(7-i))&0x01) + cfg->ssb_table.ssb_mask_list[i>>2].ssb_mask |= scc->ssb_PositionsInBurst.inOneGroup.buf[0]<<(24-8*(i%4)); + } } // TDD Table Configuration @@ -256,13 +195,13 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, cfg->tdd_table.tdd_period = scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity; else { AssertFatal(scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL, - "scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n"); + "scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n"); cfg->tdd_table.tdd_period = *scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; } - LOG_I(MAC,"Setting TDD configuration period to %d\n",cfg->tdd_table.tdd_period); if(cfg->cell_config.frame_duplex_type == TDD){ + LOG_I(MAC,"Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period); int return_tdd = set_tdd_config_nr_ue(cfg, - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots, scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, @@ -278,19 +217,202 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, // PRACH configuration uint8_t nb_preambles = 64; - if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) - nb_preambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; + if(scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) + nb_preambles = *scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; - cfg->prach_config.prach_sequence_length = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present-1; + cfg->prach_config.prach_sequence_length = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present-1; - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) - cfg->prach_config.prach_sub_c_spacing = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; - else - cfg->prach_config.prach_sub_c_spacing = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + if (scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) + cfg->prach_config.prach_sub_c_spacing = *scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; + else + cfg->prach_config.prach_sub_c_spacing = scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - cfg->prach_config.restricted_set_config = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig; + cfg->prach_config.restricted_set_config = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->restrictedSetConfig; - switch (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM) { + switch (scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM) { + case 0 : + cfg->prach_config.num_prach_fd_occasions = 1; + break; + case 1 : + cfg->prach_config.num_prach_fd_occasions = 2; + break; + case 2 : + cfg->prach_config.num_prach_fd_occasions = 4; + break; + case 3 : + cfg->prach_config.num_prach_fd_occasions = 8; + break; + default: + AssertFatal(1==0,"msg1 FDM identifier %ld undefined (0,1,2,3) \n", scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM); + } + + cfg->prach_config.num_prach_fd_occasions_list = (fapi_nr_num_prach_fd_occasions_t *) malloc(cfg->prach_config.num_prach_fd_occasions*sizeof(fapi_nr_num_prach_fd_occasions_t)); + for (int i=0; iprach_config.num_prach_fd_occasions; i++) { + cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i; + if (cfg->prach_config.prach_sequence_length) + cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; + else + cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839; + cfg->prach_config.num_prach_fd_occasions_list[i].k1 = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + + scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing, scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i); + cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; + cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup, + nb_preambles, mac->frame_type, mac->frequency_range); + //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ??? + } + cfg->prach_config.ssb_per_rach = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present-1; + +} + +void config_common_ue(NR_UE_MAC_INST_t *mac, + module_id_t module_id, + int cc_idP) { + + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + NR_ServingCellConfigCommon_t *scc = mac->scc; + int i; + + mac->phy_config.Mod_id = module_id; + mac->phy_config.CC_id = cc_idP; + + // carrier config + LOG_D(MAC, "Entering UE Config Common\n"); + + AssertFatal(scc!=NULL,"scc cannot be null\n"); + + if (scc) { + cfg->carrier_config.dl_bandwidth = config_bandwidth(scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); + + cfg->carrier_config.dl_frequency = from_nrarfcn(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], + *scc->ssbSubcarrierSpacing, + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA)/1000; // freq in kHz + + for (i=0; i<5; i++) { + if (i==scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { + cfg->carrier_config.dl_grid_size[i] = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + cfg->carrier_config.dl_k0[i] = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; + } + else { + cfg->carrier_config.dl_grid_size[i] = 0; + cfg->carrier_config.dl_k0[i] = 0; + } + } + + cfg->carrier_config.uplink_bandwidth = config_bandwidth(scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]); + + int UL_pointA; + if (scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA == NULL) + UL_pointA = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; + else + UL_pointA = *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA; + + cfg->carrier_config.uplink_frequency = from_nrarfcn(*scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0], + *scc->ssbSubcarrierSpacing, + UL_pointA)/1000; // freq in kHz + + + for (i=0; i<5; i++) { + if (i==scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { + cfg->carrier_config.ul_grid_size[i] = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + cfg->carrier_config.ul_k0[i] = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; + } + else { + cfg->carrier_config.ul_grid_size[i] = 0; + cfg->carrier_config.ul_k0[i] = 0; + } + } + + uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + mac->frequency_range = band<100?FR1:FR2; + + lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); + + // cell config + + cfg->cell_config.phy_cell_id = *scc->physCellId; + cfg->cell_config.frame_duplex_type = frame_type; + + // SSB config + cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; + cfg->ssb_config.scs_common = *scc->ssbSubcarrierSpacing; + + // SSB Table config + int scs_scaling = 1<<(cfg->ssb_config.scs_common); + if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) + scs_scaling = scs_scaling*3; + if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) + scs_scaling = scs_scaling>>2; + uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); + cfg->ssb_table.ssb_offset_point_a = absolute_diff/(12*scs_scaling) - 10; + cfg->ssb_table.ssb_period = *scc->ssb_periodicityServingCell; + cfg->ssb_table.ssb_subcarrier_offset = mac->ssb_subcarrier_offset; + + switch (scc->ssb_PositionsInBurst->present) { + case 1 : + cfg->ssb_table.ssb_mask_list[0].ssb_mask = scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0]<<24; + cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; + break; + case 2 : + cfg->ssb_table.ssb_mask_list[0].ssb_mask = scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0]<<24; + cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; + break; + case 3 : + cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0; + cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; + for (i=0; i<4; i++) { + cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[3-i]<ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-i]<ssb_PositionsInBurst->present); + } + + // TDD Table Configuration + if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 == NULL) + cfg->tdd_table.tdd_period = scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity; + else { + AssertFatal(scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL, + "scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n"); + cfg->tdd_table.tdd_period = *scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; + } + if(cfg->cell_config.frame_duplex_type == TDD){ + LOG_I(MAC,"Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period); + int return_tdd = set_tdd_config_nr_ue(cfg, + scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols + ); + + if (return_tdd !=0) + LOG_E(PHY,"TDD configuration can not be done\n"); + else + LOG_I(PHY,"TDD has been properly configurated\n"); + } + + // PRACH configuration + + uint8_t nb_preambles = 64; + if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) + nb_preambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; + + cfg->prach_config.prach_sequence_length = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present-1; + + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) + cfg->prach_config.prach_sub_c_spacing = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; + else + cfg->prach_config.prach_sub_c_spacing = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + cfg->prach_config.restricted_set_config = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig; + + switch (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM) { case 0 : cfg->prach_config.num_prach_fd_occasions = 1; break; @@ -305,23 +427,68 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, break; default: AssertFatal(1==0,"msg1 FDM identifier %ld undefined (0,1,2,3) \n", scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM); - } + } + + cfg->prach_config.num_prach_fd_occasions_list = (fapi_nr_num_prach_fd_occasions_t *) malloc(cfg->prach_config.num_prach_fd_occasions*sizeof(fapi_nr_num_prach_fd_occasions_t)); + for (i=0; iprach_config.num_prach_fd_occasions; i++) { + cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i; + if (cfg->prach_config.prach_sequence_length) + cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; + else + cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839; + + cfg->prach_config.num_prach_fd_occasions_list[i].k1 = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart; + cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; + cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, + nb_preambles, frame_type,mac->frequency_range); + //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ??? + } - cfg->prach_config.num_prach_fd_occasions_list = (fapi_nr_num_prach_fd_occasions_t *) malloc(cfg->prach_config.num_prach_fd_occasions*sizeof(fapi_nr_num_prach_fd_occasions_t)); - for (i=0; iprach_config.num_prach_fd_occasions; i++) { - cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i; - if (cfg->prach_config.prach_sequence_length) - cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; + cfg->prach_config.ssb_per_rach = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present-1; + + } // scc + +} + +/** \brief This function performs some configuration routines according to clause 12 "Bandwidth part operation" 3GPP TS 38.213 version 16.3.0 Release 16 + @param NR_UE_MAC_INST_t mac: pointer to local MAC instance + @returns void + */ + +void config_bwp_ue(NR_UE_MAC_INST_t *mac, uint16_t *bwp_ind, uint8_t *dci_format){ + + NR_ServingCellConfig_t *scd = mac->cg->spCellConfig->spCellConfigDedicated; + + if (bwp_ind && dci_format){ + + switch(*dci_format){ + case NR_UL_DCI_FORMAT_0_1: + mac->UL_BWP_Id = *bwp_ind; + break; + case NR_DL_DCI_FORMAT_1_1: + mac->DL_BWP_Id = *bwp_ind; + break; + default: + LOG_E(MAC, "In %s: failed to configure BWP Id from DCI with format %d \n", __FUNCTION__, *dci_format); + } + + } else { + + if (scd->firstActiveDownlinkBWP_Id) + mac->DL_BWP_Id = *scd->firstActiveDownlinkBWP_Id; + else if (scd->defaultDownlinkBWP_Id) + mac->DL_BWP_Id = *scd->defaultDownlinkBWP_Id; else - cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839; + mac->DL_BWP_Id = 0; + + if (scd->uplinkConfig && scd->uplinkConfig->firstActiveUplinkBWP_Id) + mac->UL_BWP_Id = *scd->uplinkConfig->firstActiveUplinkBWP_Id; + else + mac->UL_BWP_Id = 0; - cfg->prach_config.num_prach_fd_occasions_list[i].k1 = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart; - cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; - cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, frame_type); - //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ??? } - cfg->prach_config.ssb_per_rach = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present-1; + LOG_D(MAC, "In %s setting DL_BWP_Id %ld UL_BWP_Id %ld \n", __FUNCTION__, mac->DL_BWP_Id, mac->UL_BWP_Id); } @@ -332,16 +499,23 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, */ void config_control_ue(NR_UE_MAC_INST_t *mac){ - uint8_t bwp_id = 1, coreset_id = 1, ss_id; - NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; - AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n"); - AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count); + uint8_t coreset_id = 1, ss_id; + NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id; + NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; + NR_ServingCellConfig_t *scd = mac->cg->spCellConfig->spCellConfigDedicated; + if (dl_bwp_id==0) AssertFatal(mac->scc_SIB,"dl_bwp_id 0 (DL %d,UL %d) means mac->scc_SIB should exist here!\n",(int)mac->DL_BWP_Id,(int)mac->UL_BWP_Id); + NR_BWP_DownlinkCommon_t *bwp_Common = dl_bwp_id>0 ? scd->downlinkBWP_ToAddModList->list.array[dl_bwp_id - 1]->bwp_Common : + &mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP; - NR_BWP_DownlinkCommon_t *bwp_Common = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Common; - AssertFatal(bwp_Common != NULL, "bwp_Common is null\n"); - NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Dedicated; + if (dl_bwp_id > 0 ) { + AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n"); + AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count); + } + NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated = dl_bwp_id>0 ? scd->downlinkBWP_ToAddModList->list.array[dl_bwp_id - 1]->bwp_Dedicated: + scd->initialDownlinkBWP; AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n"); + config_bwp_ue(mac, NULL, NULL); NR_SetupRelease_PDCCH_Config_t *pdcch_Config = dl_bwp_Dedicated->pdcch_Config; AssertFatal(pdcch_Config != NULL, "pdcch_Config is null\n"); @@ -362,19 +536,20 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ struct NR_PDCCH_Config__searchSpacesToAddModList *searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList; AssertFatal(searchSpacesToAddModList != NULL, "searchSpacesToAddModList is null\n"); AssertFatal(searchSpacesToAddModList->list.count > 0, "list of UE specifically configured Search Spaces is empty\n"); - AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS_PER_CORESET, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count); + AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count); struct NR_UplinkConfig__uplinkBWP_ToAddModList *uplinkBWP_ToAddModList = scd->uplinkConfig->uplinkBWP_ToAddModList; - AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n"); - AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count); - + if (ul_bwp_id > 0) { + AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n"); + AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count); + } // check pdcch_Config, pdcch_ConfigCommon and DL BWP - mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]; - mac->coreset[bwp_id - 1][coreset_id - 1] = controlResourceSetToAddModList->list.array[0]; + mac->DLbwp[0] = dl_bwp_id>0?scd->downlinkBWP_ToAddModList->list.array[dl_bwp_id - 1]:NULL; + mac->coreset[dl_bwp_id][coreset_id - 1] = controlResourceSetToAddModList->list.array[0]; // Check dedicated UL BWP and pass to MAC - mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[0]; - AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n"); + mac->ULbwp[0] = ul_bwp_id>0?uplinkBWP_ToAddModList->list.array[0]:NULL; + if (mac->ULbwp[0]) AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n"); // check available Search Spaces in the searchSpacesToAddModList and pass to MAC // note: the network configures at most 10 Search Spaces per BWP per cell (including UE-specific and common Search Spaces). @@ -382,10 +557,10 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ NR_SearchSpace_t *ss = searchSpacesToAddModList->list.array[ss_id]; AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n"); - AssertFatal(*ss->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); + AssertFatal(*ss->controlResourceSetId == mac->coreset[dl_bwp_id][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); AssertFatal(ss->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n"); AssertFatal(ss->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n"); - mac->SSpace[0][0][ss_id] = ss; + mac->SSpace[dl_bwp_id][ss_id] = ss; } // Check available CSSs in the commonSearchSpaceList (list of additional common search spaces) @@ -393,46 +568,106 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ for (int css_id = 0; css_id < commonSearchSpaceList->list.count; css_id++) { NR_SearchSpace_t *css = commonSearchSpaceList->list.array[css_id]; AssertFatal(css->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); - AssertFatal(*css->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); - AssertFatal(css->searchSpaceId != 0, "css->searchSpaceId is 0\n"); + AssertFatal(*css->controlResourceSetId == 0 || *css->controlResourceSetId == mac->coreset[dl_bwp_id][coreset_id - 1]->controlResourceSetId, "css->controlResourceSetId %ld is unknown, mac->coreset[%ld][%d]->controlResourceSetId %ld\n",*css->controlResourceSetId,dl_bwp_id,coreset_id-1,mac->coreset[dl_bwp_id][coreset_id - 1]->controlResourceSetId); + AssertFatal(css->searchSpaceType != NULL, "css->searchSpaceType is null\n"); AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n"); AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n"); - mac->SSpace[0][0][ss_id] = css; + mac->SSpace[dl_bwp_id][ss_id] = css; ss_id++; } } +// todo handle mac_LogicalChannelConfig +int nr_rrc_mac_config_req_ue_logicalChannelBearer( + module_id_t module_id, + int cc_idP, + uint8_t gNB_index, + long logicalChannelIdentity, + boolean_t status){ + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + mac->logicalChannelBearer_exist[logicalChannelIdentity] = status; + return 0; +} + int nr_rrc_mac_config_req_ue( module_id_t module_id, int cc_idP, uint8_t gNB_index, NR_MIB_t *mibP, - // NR_ServingCellConfigCommon_t *sccP, + NR_ServingCellConfigCommonSIB_t *sccP, // NR_MAC_CellGroupConfig_t *mac_cell_group_configP, // NR_PhysicalCellGroupConfig_t *phy_cell_group_configP, - NR_CellGroupConfig_t *cell_group_config ){ + NR_CellGroupConfig_t *cell_group_config, + NR_CellGroupConfig_t *scell_group_config){ NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + RA_config_t *ra = &mac->ra; // TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc. if(mibP != NULL){ mac->mib = mibP; // update by every reception + mac->phy_config.Mod_id = module_id; + mac->phy_config.CC_id = cc_idP; } + AssertFatal(scell_group_config == NULL || cell_group_config == NULL, + "both scell_group_config and cell_group_config cannot be non-NULL\n"); + + if (sccP != NULL) { + + mac->scc_SIB=sccP; + LOG_D(MAC,"Keeping ServingCellConfigCommonSIB\n"); + config_common_ue_sa(mac,module_id,cc_idP); + int num_slots_ul = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if (mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols>0) num_slots_ul++; + LOG_I(MAC, "Initializing ul_config_request. num_slots_ul = %d\n", num_slots_ul); + mac->ul_config_request = (fapi_nr_ul_config_request_t *)calloc(num_slots_ul, sizeof(fapi_nr_ul_config_request_t)); + for (int i=0; iul_config_request[i].mutex_ul_config), NULL); + // Setup the SSB to Rach Occasions mapping according to the config + build_ssb_to_ro_map(mac);//->scc, mac->phy_config.config_req.cell_config.frame_duplex_type); + mac->if_module->phy_config_request(&mac->phy_config); + mac->common_configuration_complete = 1; + } + if(scell_group_config != NULL ){ + mac->cg = scell_group_config; + mac->servCellIndex = *scell_group_config->spCellConfig->servCellIndex; + mac->DL_BWP_Id=mac->cg->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id ? *mac->cg->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id : 0; + mac->UL_BWP_Id=mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id ? *mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id : 0; - if(cell_group_config != NULL ){ - mac->scg = cell_group_config; - mac->servCellIndex = *cell_group_config->spCellConfig->servCellIndex; config_control_ue(mac); - if (cell_group_config->spCellConfig->reconfigurationWithSync) { - mac->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; - mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; - config_common_ue(mac,module_id,cc_idP); - mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; - LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); + if (scell_group_config->spCellConfig->reconfigurationWithSync) { + if (scell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated) { + ra->rach_ConfigDedicated = scell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; + } + mac->scc = scell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; + mac->physCellId = *mac->scc->physCellId; + config_common_ue(mac,module_id,cc_idP); + mac->crnti = scell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; + LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); } + // Setup the SSB to Rach Occasions mapping according to the config + build_ssb_to_ro_map(mac); + } + else if (cell_group_config != NULL ){ + LOG_I(MAC,"Applying CellGroupConfig from gNodeB\n"); + mac->cg = cell_group_config; + mac->servCellIndex = cell_group_config->spCellConfig->servCellIndex ? *cell_group_config->spCellConfig->servCellIndex : 0; + + mac->scheduling_info.periodicBSR_SF = + MAC_UE_BSR_TIMER_NOT_RUNNING; + mac->scheduling_info.retxBSR_SF = + MAC_UE_BSR_TIMER_NOT_RUNNING; + mac->BSR_reporting_active = NR_BSR_TRIGGER_NONE; + LOG_D(MAC, "[UE %d]: periodic BSR %d (SF), retx BSR %d (SF)\n", + module_id, + mac->scheduling_info.periodicBSR_SF, + mac->scheduling_info.retxBSR_SF); + + config_control_ue(mac); + //config_common_ue(mac,module_id,cc_idP); /* if(mac_cell_group_configP != NULL){ if(mac_cell_group_configP->drx_Config != NULL ){ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h old mode 100755 new mode 100644 index e45f6a9b69..edfd37c3a0 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -20,7 +20,7 @@ */ /* \file mac_defs.h - * \brief MAC data structures, constant, and function prototype + * \brief MAC data structures and constants * \author R. Knopp, K.H. HSU * \date 2018 * \version 0.1 @@ -63,21 +63,112 @@ #include "NR_PhysicalCellGroupConfig.h" #include "NR_CellGroupConfig.h" #include "NR_ServingCellConfig.h" +#include "NR_MeasConfig.h" +#include "fapi_nr_ue_interface.h" +#include "NR_IF_Module.h" +#include "PHY/defs_nr_common.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" +// ========== +// NR UE defs +// ========== #define NB_NR_UE_MAC_INST 1 -/*!\brief Maximum number of logical channl group IDs */ - +#define MAX_NUM_BWP 2 +#define NUM_SLOT_FRAME 10 /*!\brief value for indicating BSR Timer is not running */ #define NR_MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) +// ================================================ +// SSB to RO mapping private defines and structures +// ================================================ +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms +#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms +#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms +#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) +#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period +#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes +#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config + +// Maximum number of ROs that can be mapped to an SSB in an association pattern +// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB +// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot +#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD) + +// =============== +// DCI fields defs +// =============== + +#define NBR_NR_FORMATS 8 // The number of formats is 8 (0_0, 0_1, 1_0, 1_1, 2_0, 2_1, 2_2, 2_3) +#define NBR_NR_DCI_FIELDS 56 // The number of different dci fields defined in TS 38.212 subclause 7.3.1 + +#define IDENTIFIER_DCI_FORMATS 0 +#define CARRIER_IND 1 +#define SUL_IND_0_1 2 +#define SLOT_FORMAT_IND 3 +#define PRE_EMPTION_IND 4 +#define BLOCK_NUMBER 5 +#define CLOSE_LOOP_IND 6 +#define BANDWIDTH_PART_IND 7 +#define SHORT_MESSAGE_IND 8 +#define SHORT_MESSAGES 9 +#define FREQ_DOM_RESOURCE_ASSIGNMENT_UL 10 +#define FREQ_DOM_RESOURCE_ASSIGNMENT_DL 11 +#define TIME_DOM_RESOURCE_ASSIGNMENT 12 +#define VRB_TO_PRB_MAPPING 13 +#define PRB_BUNDLING_SIZE_IND 14 +#define RATE_MATCHING_IND 15 +#define ZP_CSI_RS_TRIGGER 16 +#define FREQ_HOPPING_FLAG 17 +#define TB1_MCS 18 +#define TB1_NDI 19 +#define TB1_RV 20 +#define TB2_MCS 21 +#define TB2_NDI 22 +#define TB2_RV 23 +#define MCS 24 +#define NDI 25 +#define RV 26 +#define HARQ_PROCESS_NUMBER 27 +#define DAI_ 28 +#define FIRST_DAI 29 +#define SECOND_DAI 30 +#define TB_SCALING 31 +#define TPC_PUSCH 32 +#define TPC_PUCCH 33 +#define PUCCH_RESOURCE_IND 34 +#define PDSCH_TO_HARQ_FEEDBACK_TIME_IND 35 +#define SRS_RESOURCE_IND 36 +#define PRECOD_NBR_LAYERS 37 +#define ANTENNA_PORTS 38 +#define TCI 39 +#define SRS_REQUEST 40 +#define TPC_CMD 41 +#define CSI_REQUEST 42 +#define CBGTI 43 +#define CBGFI 44 +#define PTRS_DMRS 45 +#define BETA_OFFSET_IND 46 +#define DMRS_SEQ_INI 47 +#define UL_SCH_IND 48 +#define PADDING_NR_DCI 49 +#define SUL_IND_0_0 50 +#define RA_PREAMBLE_INDEX 51 +#define SUL_IND_1_0 52 +#define SS_PBCH_INDEX 53 +#define PRACH_MASK_INDEX 54 +#define RESERVED_NR_DCI 55 + +/*!\brief UE layer 2 status */ typedef enum { - SFN_C_MOD_2_EQ_0, - SFN_C_MOD_2_EQ_1, - SFN_C_IMPOSSIBLE -} SFN_C_TYPE; + UE_CONNECTION_OK = 0, + UE_CONNECTION_LOST, + UE_PHY_RESYNCH, + UE_PHY_HO_PRACH +} NR_UE_L2_STATE_t; // LTE structure, might need to be adapted for NR typedef struct { @@ -91,9 +182,9 @@ typedef struct { uint16_t All_lcid_buffer_size_lastTTI; /// buffer status for each lcid uint8_t LCID_status[NR_MAX_NUM_LCID]; - /// SR pending as defined in 36.321 + /// SR pending as defined in 38.321 uint8_t SR_pending; - /// SR_COUNTER as defined in 36.321 + /// SR_COUNTER as defined in 38.321 uint16_t SR_COUNTER; /// logical channel group ide for each LCID uint8_t LCGID[NR_MAX_NUM_LCID]; @@ -141,36 +232,150 @@ typedef struct { int16_t bucket_size[NR_MAX_NUM_LCID]; } NR_UE_SCHEDULING_INFO; - -#define MAX_NUM_BWP 2 - typedef enum { RA_UE_IDLE = 0, - WAIT_RAR = 1, - WAIT_CONTENTION_RESOLUTION = 2, - RA_SUCCEEDED = 3 + GENERATE_IDLE = 0, + GENERATE_PREAMBLE = 1, + WAIT_RAR = 2, + WAIT_CONTENTION_RESOLUTION = 3, + RA_SUCCEEDED = 4, + RA_FAILED = 5 } RA_state_t; +typedef struct { + + // pointer to RACH config dedicated + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated; + /// state of RA procedure + RA_state_t ra_state; + /// RA contention type + uint8_t cfra; + /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. + uint8_t RA_offset; + /// RA-rnti + uint16_t ra_rnti; + /// Temporary CRNTI + uint16_t t_crnti; + /// number of attempt for rach + uint8_t RA_attempt_number; + /// Random-access procedure flag + uint8_t RA_active; + /// Random-access preamble index + int ra_PreambleIndex; + /// Flag for the Msg1 generation: enabled at every occurrence of nr prach slot + RA_state_t generate_nr_prach; + + /// Random-access window counter + int16_t RA_window_cnt; + /// Flag to monitor if matching RAPID was received in RAR + uint8_t RA_RAPID_found; + /// Flag to monitor if BI was received in RAR + uint8_t RA_BI_found; + /// Random-access backoff counter + int16_t RA_backoff_indicator; + /// Flag to indicate whether preambles Group A was used + uint8_t RA_usedGroupA; + /// RA backoff counter + int16_t RA_backoff_cnt; + /// RA max number of preamble transmissions + int preambleTransMax; + /// Nb of preambles per SSB + long cb_preambles_per_ssb; + int starting_preamble_nb; + + /// Received TPC command (in dB) from RAR + int8_t Msg3_TPC; + /// Flag to indicate whether it is the first Msg3 to be transmitted + uint8_t first_Msg3; + /// RA Msg3 size in bytes + uint8_t Msg3_size; + + /// Random-access Contention Resolution Timer active flag + uint8_t RA_contention_resolution_timer_active; + int RA_contention_resolution_target_frame; + int RA_contention_resolution_target_slot; + /// Transmitted UE Contention Resolution Identifier + uint8_t cont_res_id[6]; + + /// BeamfailurerecoveryConfig + NR_BeamFailureRecoveryConfig_t RA_BeamFailureRecoveryConfig; + + /// RA SearchSpace + NR_SearchSpace_t *ss; +} RA_config_t; + +typedef struct { + bool active; + bool ack_received; + uint8_t pucch_resource_indicator; + uint16_t feedback_to_ul; + int is_common; + frame_t dl_frame; + int dl_slot; + uint8_t ack; + uint8_t dai; + int n_CCE; + int N_CCE; + int8_t delta_pucch; +} NR_UE_HARQ_STATUS_t; + +typedef struct { + + uint8_t freq_hopping; + uint8_t mcs; + uint8_t Msg3_t_alloc; + uint16_t Msg3_f_alloc; + +} RAR_grant_t; + +typedef struct { + int n_HARQ_ACK; + uint32_t ack_payload; + uint8_t sr_payload; + uint32_t csi_part1_payload; + uint32_t csi_part2_payload; + int resource_indicator; + int resource_set_id; + int is_common; + int initial_pucch_id; + NR_PUCCH_Resource_t *pucch_resource; + int n_CCE; + int N_CCE; + int8_t delta_pucch; +} PUCCH_sched_t; + + /*!\brief Top level UE MAC structure */ typedef struct { NR_ServingCellConfigCommon_t *scc; - NR_CellGroupConfig_t *scg; - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated; + NR_ServingCellConfigCommonSIB_t *scc_SIB; + NR_CellGroupConfig_t *cg; int servCellIndex; + NR_CSI_ReportConfig_t *csirc; + long physCellId; //// MAC config + int common_configuration_complete; NR_DRX_Config_t *drx_Config; NR_SchedulingRequestConfig_t *schedulingRequestConfig; NR_BSR_Config_t *bsr_Config; NR_TAG_Config_t *tag_Config; NR_PHR_Config_t *phr_Config; NR_RNTI_Value_t *cs_RNTI; - NR_MIB_t *mib; + NR_MIB_t *mib; NR_BWP_Downlink_t *DLbwp[MAX_NUM_BWP]; NR_BWP_Uplink_t *ULbwp[MAX_NUM_BWP]; NR_ControlResourceSet_t *coreset[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP]; - NR_SearchSpace_t *SSpace[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP][FAPI_NR_MAX_SS_PER_CORESET]; + NR_SearchSpace_t *SSpace[MAX_NUM_BWP][FAPI_NR_MAX_SS]; + + lte_frame_type_t frame_type; + + /*BWP*/ + // dedicated active DL BWP + NR_BWP_Id_t DL_BWP_Id; + // dedicated active UL BWP + NR_BWP_Id_t UL_BWP_Id; /// Type0-PDCCH seach space fapi_nr_dl_config_dci_dl_pdu_rel15_t type0_pdcch_dci_config; @@ -184,80 +389,49 @@ typedef struct { CCCH_PDU CCCH_pdu; ULSCH_PDU ulsch_pdu; - /* Random Access parameters */ - /// state of RA procedure - RA_state_t ra_state; - /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. - uint8_t RA_offset; - /// RA-rnti - uint16_t ra_rnti; - /// Temporary CRNTI - uint16_t t_crnti; + /* Random Access */ /// CRNTI uint16_t crnti; - /// number of attempt for rach - uint8_t RA_attempt_number; - /// Random-access procedure flag - uint8_t RA_active; - /// Random-access window counter - int8_t RA_window_cnt; - /// Random-access Msg3 size in bytes - uint8_t RA_Msg3_size; - /// Random-access prachMaskIndex - uint8_t RA_prachMaskIndex; - /// Flag indicating Preamble set (A,B) used for first Msg3 transmission - uint8_t RA_usedGroupA; - /// BeamfailurerecoveryConfig - NR_BeamFailureRecoveryConfig_t RA_BeamFailureRecoveryConfig; - /// Preamble Tx Counter - uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; - /// Preamble Power Ramping Counter - uint8_t RA_PREAMBLE_POWER_RAMPING_COUNTER; - /// Random-access backoff counter - int16_t RA_backoff_indicator; - /// Random-access backoff counter - int16_t RA_backoff_cnt; - /// Random-access variable for window calculation (frame of last change in window counter) - uint32_t RA_tx_frame; - /// Random-access variable for window calculation (subframe of last change in window counter) - uint8_t RA_tx_subframe; - /// Random-access variable for backoff (frame of last change in backoff counter) - uint32_t RA_backoff_frame; - /// Random-access variable for backoff (subframe of last change in backoff counter) - uint8_t RA_backoff_subframe; - /// Random-access Group B maximum path-loss - uint16_t RA_maxPL; - /// Random-access Contention Resolution Timer active flag - uint8_t RA_contention_resolution_timer_active; - /// Random-access Contention Resolution Timer count value - uint8_t RA_contention_resolution_cnt; - /// Msg3 Delta Preamble - int8_t deltaPreamble_Msg3; - /// Received TPC command (in dB) from RAR - int8_t Msg3_TPC; - /// Flag to monitor if matching RAPID was received in RAR - uint8_t RA_RAPID_found; - /// Flag to monitor if BI was received in RAR - uint8_t RA_BI_found; - /// Flag for the Msg1 generation: enabled at every occurrence of nr prach slot - uint8_t generate_nr_prach; + /// RA configuration + RA_config_t ra; + /// SSB index from MIB decoding + uint8_t mib_ssb; + /// measured SSB RSRP in dBm + short ssb_rsrp_dBm; + /// Last NDI of UL HARQ processes + uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES]; + /// first ULTX of UL HARQ processes + int first_ul_tx[NR_MAX_HARQ_PROCESSES]; //// FAPI-like interface message - fapi_nr_tx_request_t tx_request; - fapi_nr_ul_config_request_t ul_config_request; + fapi_nr_ul_config_request_t *ul_config_request; fapi_nr_dl_config_request_t dl_config_request; /// Interface module instances nr_ue_if_module_t *if_module; - nr_scheduled_response_t scheduled_response; nr_phy_config_t phy_config; /// BSR report flag management uint8_t BSR_reporting_active; + + /// LogicalChannelConfig has bearer. + boolean_t logicalChannelBearer_exist[NR_MAX_NUM_LCID]; NR_UE_SCHEDULING_INFO scheduling_info; /// PHR uint8_t PHR_reporting_active; + + NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config; + NR_SearchSpace_t *search_space_zero; + NR_ControlResourceSet_t *coreset0; + frequency_range_t frequency_range; + uint16_t nr_band; + uint8_t ssb_subcarrier_offset; + + dci_pdu_rel15_t def_dci_pdu_rel15[8]; + + NR_UE_HARQ_STATUS_t dl_harq_info[16]; + } NR_UE_MAC_INST_t; typedef enum seach_space_mask_e { @@ -268,28 +442,6 @@ typedef enum seach_space_mask_e { type3_pdcch = 0x10 } search_space_mask_t; -typedef enum subcarrier_spacing_e { - scs_15kHz = 0x1, - scs_30kHz = 0x2, - scs_60kHz = 0x4, - scs_120kHz = 0x8, - scs_240kHz = 0x16 -} subcarrier_spacing_t; - -typedef enum channel_bandwidth_e { - bw_5MHz = 0x1, - bw_10MHz = 0x2, - bw_20MHz = 0x4, - bw_40MHz = 0x8, - bw_80MHz = 0x16, - bw_100MHz = 0x32 -} channel_bandwidth_t; - -typedef enum frequency_range_e { - FR1 = 0, - FR2 -} frequency_range_t; - typedef struct { uint8_t identifier_dci_formats ; // 0 IDENTIFIER_DCI_FORMATS: uint8_t carrier_ind ; // 1 CARRIER_IND: 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] @@ -362,67 +514,45 @@ typedef struct { uint8_t reserved_nr_dci ; // 55 RESERVED_NR_DCI } nr_dci_pdu_rel15_t; -#define NUM_SLOT_FRAME 10 +// The PRACH Config period is a series of selected slots in one or multiple frames +typedef struct prach_conf_period { + prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME]; + uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period + uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames + uint8_t nb_of_slot; // Nb of slots in each frame +} prach_conf_period_t; -#define NBR_NR_FORMATS 8 // The number of formats is 8 (0_0, 0_1, 1_0, 1_1, 2_0, 2_1, 2_2, 2_3) -#define NBR_NR_DCI_FIELDS 56 // The number of different dci fields defined in TS 38.212 subclause 7.3.1 +// The association period is a series of PRACH Config periods +typedef struct prach_association_period { + prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; + uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period + uint8_t nb_of_frame; // Total number of frames included in the association period +} prach_association_period_t; -#define IDENTIFIER_DCI_FORMATS 0 -#define CARRIER_IND 1 -#define SUL_IND_0_1 2 -#define SLOT_FORMAT_IND 3 -#define PRE_EMPTION_IND 4 -#define BLOCK_NUMBER 5 -#define CLOSE_LOOP_IND 6 -#define BANDWIDTH_PART_IND 7 -#define SHORT_MESSAGE_IND 8 -#define SHORT_MESSAGES 9 -#define FREQ_DOM_RESOURCE_ASSIGNMENT_UL 10 -#define FREQ_DOM_RESOURCE_ASSIGNMENT_DL 11 -#define TIME_DOM_RESOURCE_ASSIGNMENT 12 -#define VRB_TO_PRB_MAPPING 13 -#define PRB_BUNDLING_SIZE_IND 14 -#define RATE_MATCHING_IND 15 -#define ZP_CSI_RS_TRIGGER 16 -#define FREQ_HOPPING_FLAG 17 -#define TB1_MCS 18 -#define TB1_NDI 19 -#define TB1_RV 20 -#define TB2_MCS 21 -#define TB2_NDI 22 -#define TB2_RV 23 -#define MCS 24 -#define NDI 25 -#define RV 26 -#define HARQ_PROCESS_NUMBER 27 -#define DAI_ 28 -#define FIRST_DAI 29 -#define SECOND_DAI 30 -#define TB_SCALING 31 -#define TPC_PUSCH 32 -#define TPC_PUCCH 33 -#define PUCCH_RESOURCE_IND 34 -#define PDSCH_TO_HARQ_FEEDBACK_TIME_IND 35 -#define SRS_RESOURCE_IND 36 -#define PRECOD_NBR_LAYERS 37 -#define ANTENNA_PORTS 38 -#define TCI 39 -#define SRS_REQUEST 40 -#define TPC_CMD 41 -#define CSI_REQUEST 42 -#define CBGTI 43 -#define CBGFI 44 -#define PTRS_DMRS 45 -#define BETA_OFFSET_IND 46 -#define DMRS_SEQ_INI 47 -#define UL_SCH_IND 48 -#define PADDING_NR_DCI 49 -#define SUL_IND_0_0 50 -#define RA_PREAMBLE_INDEX 51 -#define SUL_IND_1_0 52 -#define SS_PBCH_INDEX 53 -#define PRACH_MASK_INDEX 54 -#define RESERVED_NR_DCI 55 +// The association pattern is a series of Association periods +typedef struct prach_association_pattern { + prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern + uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH + uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) +} prach_association_pattern_t; + +// SSB details +typedef struct ssb_info { + boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration + prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index + uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index +} ssb_info_t; + +// List of all the possible SSBs and their details +typedef struct ssb_list_info { + ssb_info_t tx_ssb[MAX_NB_SSB]; + uint8_t nb_tx_ssb; +} ssb_list_info_t; + +void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id); +void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); /*@}*/ #endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_extern.h b/openair2/LAYER2/NR_MAC_UE/mac_extern.h index 54cdc4d149..e551790f7a 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_extern.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_extern.h @@ -34,62 +34,53 @@ //extern NR_UE_MAC_INST_t *UE_mac_inst; -// Type0-PDCCH search space -extern const int32_t table_38213_13_1_c2[16]; -extern const int32_t table_38213_13_1_c3[16]; -extern const int32_t table_38213_13_1_c4[16]; - -extern const int32_t table_38213_13_2_c2[16]; -extern const int32_t table_38213_13_2_c3[16]; -extern const int32_t table_38213_13_2_c4[16]; - -extern const int32_t table_38213_13_3_c2[16]; -extern const int32_t table_38213_13_3_c3[16]; -extern const int32_t table_38213_13_3_c4[16]; - -extern const int32_t table_38213_13_4_c2[16]; -extern const int32_t table_38213_13_4_c3[16]; -extern const int32_t table_38213_13_4_c4[16]; - -extern const int32_t table_38213_13_5_c2[16]; -extern const int32_t table_38213_13_5_c3[16]; -extern const int32_t table_38213_13_5_c4[16]; - -extern const int32_t table_38213_13_6_c2[16]; -extern const int32_t table_38213_13_6_c3[16]; -extern const int32_t table_38213_13_6_c4[16]; - -extern const int32_t table_38213_13_7_c2[16]; -extern const int32_t table_38213_13_7_c3[16]; -extern const int32_t table_38213_13_7_c4[16]; - -extern const int32_t table_38213_13_8_c2[16]; -extern const int32_t table_38213_13_8_c3[16]; -extern const int32_t table_38213_13_8_c4[16]; - -extern const int32_t table_38213_13_9_c2[16]; -extern const int32_t table_38213_13_9_c3[16]; -extern const int32_t table_38213_13_9_c4[16]; - -extern const int32_t table_38213_13_10_c2[16]; -extern const int32_t table_38213_13_10_c3[16]; -extern const int32_t table_38213_13_10_c4[16]; - -extern const float table_38213_13_11_c1[16]; -extern const int32_t table_38213_13_11_c2[16]; -extern const float table_38213_13_11_c3[16]; -extern const int32_t table_38213_13_11_c4[16]; - -extern const float table_38213_13_12_c1[16]; -extern const int32_t table_38213_13_12_c2[16]; -extern const float table_38213_13_12_c3[16]; - -extern const int32_t table_38213_10_1_1_c2[5]; - // DCI extraction // for PUSCH from TS 38.214 subclause 6.1.2.1.1 extern uint8_t table_6_1_2_1_1_2_time_dom_res_alloc_A[16][3]; // for PDSCH from TS 38.214 subclause 5.1.2.1.1 extern uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]; +extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; + +// DCI +extern const uint8_t table_7_3_1_1_2_2_3_4_5[64][20]; +extern const uint8_t table_7_3_1_1_2_12[14][3]; +extern const uint8_t table_7_3_1_1_2_13[10][4]; +extern const uint8_t table_7_3_1_1_2_14[3][5]; +extern const uint8_t table_7_3_1_1_2_15[4][6]; +extern const uint8_t table_7_3_1_1_2_16[12][2]; +extern const uint8_t table_7_3_1_1_2_17[7][3]; +extern const uint8_t table_7_3_1_1_2_18[3][4]; +extern const uint8_t table_7_3_1_1_2_19[2][5]; +extern const uint8_t table_7_3_1_1_2_20[28][3]; +extern const uint8_t table_7_3_1_1_2_21[19][4]; +extern const uint8_t table_7_3_1_1_2_22[6][5]; +extern const uint8_t table_7_3_1_1_2_23[5][6]; +extern const uint8_t table_7_3_2_3_3_1[12][5]; +extern const uint8_t table_7_3_2_3_3_2_oneCodeword[31][6]; +extern const uint8_t table_7_3_2_3_3_2_twoCodeword[4][10]; +extern const uint8_t table_7_3_2_3_3_3_oneCodeword[24][5]; +extern const uint8_t table_7_3_2_3_3_3_twoCodeword[2][7]; +extern const uint8_t table_7_3_2_3_3_4_oneCodeword[58][6]; +extern const uint8_t table_7_3_2_3_3_4_twoCodeword[6][10]; + +extern const uint16_t table_7_2_1[16]; + extern dci_pdu_rel15_t *def_dci_pdu_rel15; + +extern dci_pdu_rel15_t *def_dci_pdu_rel15; + +extern void mac_rlc_data_ind(const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + char *buffer_pP, + const tb_size_t tb_sizeP, + num_tb_t num_tbP, + crc_t *crcs_pP); + +extern const char *rnti_types[]; +extern const char *dci_formats[]; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h old mode 100755 new mode 100644 index e9d7a97a5d..288716ed85 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -34,10 +34,15 @@ #define __LAYER2_MAC_UE_PROTO_H__ #include "mac_defs.h" -#include "mac.h" #include "PHY/defs_nr_UE.h" #include "RRC/NR_UE/rrc_defs.h" +#define NR_DL_MAX_DAI (4) /* TS 38.213 table 9.1.3-1 Value of counter DAI for DCI format 1_0 and 1_1 */ +#define NR_DL_MAX_NB_CW (2) /* number of downlink code word */ + +/**\brief initialize the field in nr_mac instance + \param module_id module id */ +void nr_ue_init_mac(module_id_t module_idP); /**\brief decode mib pdu in NR_UE, from if_module ul_ind with P7 tx_ind message \param module_id module id @@ -55,9 +60,37 @@ int8_t nr_ue_decode_mib( uint8_t extra_bits, uint32_t ssb_length, uint32_t ssb_index, - void *pduP, + void *pduP, + uint16_t ssb_start_subcarrier, uint16_t cell_id ); +/**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind + \param module_id module id + \param cc_id component carrier id + \param gNB_index gNB index + \param sibs_mask sibs mask + \param pduP pointer to pdu + \param pdu_length length of pdu */ +int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, + int cc_id, + unsigned int gNB_index, + uint8_t ack_nack, + uint8_t *pduP, + uint32_t pdu_len); + +/**\brief primitive from RRC layer to MAC layer to set if bearer exists for a logical channel. todo handle mac_LogicalChannelConfig + \param module_id module id + \param cc_id component carrier id + \param gNB_index gNB index + \param long logicalChannelIdentity + \param boolean_t status*/ +int nr_rrc_mac_config_req_ue_logicalChannelBearer( + module_id_t module_id, + int cc_idP, + uint8_t gNB_index, + long logicalChannelIdentity, + boolean_t status +); /**\brief primitive from RRC layer to MAC layer for configuration L1/L2, now supported 4 rrc messages: MIB, cell_group_config for MAC/PHY, spcell_config(serving cell config) \param module_id module id @@ -71,8 +104,10 @@ int nr_rrc_mac_config_req_ue( int cc_idP, uint8_t gNB_index, NR_MIB_t *mibP, - //NR_ServingCellConfigCommon_t *sccP, - NR_CellGroupConfig_t *cell_group_config); + NR_ServingCellConfigCommonSIB_t *sccP, + NR_CellGroupConfig_t *cell_group_config, + NR_CellGroupConfig_t *scell_group_config +); /**\brief initialization NR UE MAC instance(s), total number of MAC instance based on NB_NR_UE_MAC_INST*/ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst); @@ -88,103 +123,220 @@ NR_UE_MAC_INST_t *get_mac_inst( \param ul_info UL indication*/ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_indication_t *ul_info); -/* \brief Get SR payload (0,1) from UE MAC -@param Mod_id Instance id of UE in machine -@param CC_id Component Carrier index -@param eNB_id Index of eNB that UE is attached to -@param rnti C_RNTI of UE -@param subframe subframe number -@returns 0 for no SR, 1 for SR +/**\brief fill nr_scheduled_response struct instance + @param nr_scheduled_response_t * pointer to scheduled_response instance to fill + @param fapi_nr_dl_config_request_t* pointer to dl_config, + @param fapi_nr_ul_config_request_t* pointer to ul_config, + @param fapi_nr_tx_request_t* pointer to tx_request; + @param module_id_t mod_id module ID + @param int cc_id CC ID + @param frame_t frame frame number + @param int slot reference number + @param UE_nr_rxtx_proc_t *proc pointer to process context */ +void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, + fapi_nr_dl_config_request_t *dl_config, + fapi_nr_ul_config_request_t *ul_config, + fapi_nr_tx_request_t *tx_request, + module_id_t mod_id, + int cc_id, + frame_t frame, + int slot, + int thread_id); + +/*! \fn int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slotP); + \brief Called by PHY to get sdu for PUSCH transmission. It performs the following operations: Checks BSR for DCCH, DCCH1 and DTCH corresponding to previous values computed either in SR or BSR procedures. It gets rlc status indications on DCCH,DCCH1 and DTCH and forms BSR elements and PHR in MAC header. CRNTI element is not supported yet. It computes transport block for up to 3 SDUs and generates header and forms the complete MAC SDU. +\param[in] Mod_id Instance id of UE in machine +\param[in] frameP subframe number +\param[in] slotP slot number */ -uint32_t ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, - uint8_t eNB_id, rnti_t rnti, sub_frame_t subframe); +int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slotP); -int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); +/*! \fn boolean_t update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index) + \brief get the rlc stats and update the bsr level for each lcid +\param[in] Mod_id instance of the UE +\param[in] frameP Frame index +\param[in] slot slotP number +\param[in] uint8_t gNB_index +*/ +boolean_t nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index); -int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dci_pdu_rel15_t *dci, uint16_t rnti, uint32_t dci_format); -int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_index,fapi_nr_dci_indication_pdu_t *dci); +/*! \fn nr_locate_BsrIndexByBufferSize (int *table, int size, int value) + \brief locate the BSR level in the table as defined in 38.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table. +\param[in] *table Pointer to BSR table +\param[in] size Size of the table +\param[in] value Value of the buffer +\return the index in the BSR_LEVEL table +*/ +uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, + int value); + +/*! \fn int nr_get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer) + \brief get the number of subframe from the periodic BSR timer configured by the higher layers +\param[in] periodicBSR_Timer timer for periodic BSR +\return the number of subframe +*/ +int nr_get_sf_periodicBSRTimer(uint8_t bucketSize); + +/*! \fn int nr_get_ms_bucketsizeduration(uint8_t bucketSize) + \brief get the time in ms form the bucket size duration configured by the higher layer +\param[in] bucketSize the bucket size duration +\return the time in ms +*/ +int nr_get_ms_bucketsizeduration(uint8_t bucketsizeduration); + +/*! \fn int nr_get_sf_retxBSRTimer(uint8_t retxBSR_Timer) + \brief get the number of subframe form the bucket size duration configured by the higher layer +\param[in] retxBSR_Timer timer for regular BSR +\return the time in sf +*/ +int nr_get_sf_retxBSRTimer(uint8_t retxBSR_Timer); + +int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind); +int nr_ue_process_dci_indication_pdu(module_id_t module_id, int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); uint32_t get_ssb_frame(uint32_t test); -uint32_t get_ssb_slot(uint32_t ssb_index); +bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + frame_t frame, + int slot); -uint32_t mr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); +uint8_t nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, + frame_t frame, + int slot, + PUCCH_sched_t *pucch); + +uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig); + +uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + NR_CSI_MeasConfig_t *csi_MeasConfig); + +uint8_t get_rsrp_index(int rsrp); +uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp); /* \brief Get payload (MAC PDU) from UE PHY -@param module_idP Instance id of UE in machine -@param CC_id Component Carrier index -@param frameP Current Rx frame -@param slotP Current Rx slot -@param pdu Pointer to the MAC PDU -@param pdu_len Length of the MAC PDU -@param gNB_id Index of gNB that UE is attached to -@param ul_time_alignment of struct handling the timing advance parameters +@param dl_info pointer to dl indication +@param ul_time_alignment pointer to timing advance parameters +@param pdu_id index of DL PDU @returns void */ -void nr_ue_send_sdu(module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - int slotP, - uint8_t * pdu, - uint16_t pdu_len, - uint8_t gNB_index, - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); +void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, + int pdu_id); -void nr_ue_process_mac_pdu(module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - uint8_t *pduP, - uint16_t mac_pdu_len, - uint8_t gNB_index, - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); +void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, + int pdu_id); +int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, + NR_UE_MAC_INST_t *mac, + uint8_t power_headroom, // todo: NR_POWER_HEADROOM_CMD *power_headroom, + uint16_t *crnti, + NR_BSR_SHORT *truncated_bsr, + NR_BSR_SHORT *short_bsr, + NR_BSR_LONG *long_bsr + ); -uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload, - uint8_t *pdu, - uint8_t num_sdus, - uint16_t *sdu_lengths, - uint8_t *sdu_lcids, - uint8_t power_headroom, - uint16_t crnti, - uint16_t truncated_bsr, - uint16_t short_bsr, - uint16_t long_bsr, - unsigned short post_padding, - uint16_t buflen); +void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); -int8_t nr_ue_process_dlsch(module_id_t module_id, int cc_id, uint8_t gNB_index, fapi_nr_dci_indication_t *dci_ind, void *pduP, uint32_t pdu_len); +void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id); void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, frame_t frame, int slot); -void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, - int dci_format, - uint8_t dci_length, - uint16_t rnti, - uint64_t *dci_pdu, - dci_pdu_rel15_t *nr_pdci_info_extracted); +void get_bwp_info(NR_UE_MAC_INST_t *mac, + int dl_bwp_id, + int ul_bwp_id, + NR_BWP_DownlinkDedicated_t **bwpd, + NR_BWP_DownlinkCommon_t **bwpc, + NR_BWP_UplinkDedicated_t **ubwpd, + NR_BWP_UplinkCommon_t **ubwpc); +uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, + uint8_t dci_format, + uint8_t dci_length, + uint16_t rnti, + uint64_t *dci_pdu, + dci_pdu_rel15_t *nr_pdci_info_extracted); -uint8_t -nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, - sub_frame_t subframe, uint8_t eNB_index, - uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) ; +NR_PUSCH_TimeDomainResourceAllocationList_t *choose_ul_tda_list(NR_PUSCH_Config_t *pusch_Config,NR_PUSCH_ConfigCommon_t *pusch_ConfigCommon); +NR_PDSCH_TimeDomainResourceAllocationList_t *choose_dl_tda_list(NR_PDSCH_Config_t *pdsch_Config,NR_PDSCH_ConfigCommon_t *pdsch_ConfigCommon); + +int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList, + NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList, + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, + uint8_t time_domain_ind, + int default_abc, + bool use_default); + +uint8_t nr_ue_get_sdu(module_id_t module_idP, + int cc_id, + frame_t frameP, + sub_frame_t subframe, + uint8_t gNB_index, + uint8_t *ulsch_buffer, + uint16_t buflen); int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSlots, int nrofUplinkSymbols); -/** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure. - @param Mod_id Module id of UE - @returns Po_NOMINAL_PUSCH (PREAMBLE_RECEIVED_TARGET_POWER+DELTA_PREAMBLE -*/ -int nr_get_Po_NOMINAL_PUSCH(NR_PRACH_RESOURCES_t *prach_resources, module_id_t module_idP, uint8_t CC_id); +void set_harq_status(NR_UE_MAC_INST_t *mac, + uint8_t pucch_id, + uint8_t harq_id, + int8_t delta_pucch, + uint8_t data_toul_fb, + uint8_t dai, + int n_CCE, + int N_CCE, + int is_common, + frame_t frame, + int slot); + +uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, + frame_t frame, + int slot, + PUCCH_sched_t *pucch); + +int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, int uci_size); + +void select_pucch_resource(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch); + +int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, + NR_PUCCH_Config_t *pucch_Config, + PUCCH_sched_t *pucch, + uint8_t format_type, + uint16_t nb_of_prbs, + uint8_t freq_hop_flag, + uint8_t add_dmrs_flag, + uint8_t N_symb_PUCCH, + int subframe_number, + int O_ACK, int O_SR, + int O_CSI, int O_CRC); + +int get_deltatf(uint16_t nb_of_prbs, + uint8_t N_symb_PUCCH, + uint8_t freq_hop_flag, + uint8_t add_dmrs_flag, + int N_sc_ctrl_RB, + int n_HARQ_ACK, + int O_ACK, int O_SR, + int O_CSI, int O_CRC); + +void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, + int slot, + uint16_t rnti, + PUCCH_sched_t *pucch, + fapi_nr_ul_config_pucch_pdu *pucch_pdu, + int O_SR, int O_ACK, int O_CSI); -/** \brief Function to compute DELTA_PREAMBLE from 38.321 subclause 7.3 - (for RA power ramping procedure and Msg3 PUSCH power control policy) - @param Mod_id Module id of UE - @returns DELTA_PREAMBLE -*/ -int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_format); /* Random Access */ @@ -193,9 +345,31 @@ and fills the PRACH PDU per each FD occasion. @param module_idP Index of UE instance @param frameP Frame index @param slotP Slot index +@param thread_id RX/TX Thread ID @returns void */ -void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); +void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, int thread_id); +void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, int thread_id); + +/* \brief This function schedules the Msg3 transmission +@param +@param +@param +@returns void +*/ +void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac, + frame_t current_frame, + sub_frame_t current_slot, + uint8_t Msg3_tda_id); + +void nr_ue_sib1_scheduler(module_id_t module_idP, + int cc_id, + uint16_t ssb_start_symbol, + uint16_t frame, + uint8_t ssb_subcarrier_offset, + uint32_t ssb_index, + uint16_t ssb_start_subcarrier, + frequency_range_t frequency_range); /* \brief Function called by PHY to process the received RAR and check that the preamble matches what was sent by the gNB. It provides the timing advance and t-CRNTI. @param Mod_id Index of UE instance @@ -209,60 +383,94 @@ random-access procedure @param selected_rar_buffer the output buffer for storing the selected RAR header and RAR payload @returns timing advance or 0xffff if preamble doesn't match */ -uint16_t nr_ue_process_rar(module_id_t mod_id, - int CC_id, - frame_t frameP, - uint8_t * dlsch_buffer, - rnti_t * t_crnti, - uint8_t preamble_index, - uint8_t * selected_rar_buffer); +int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id); void nr_process_rar(nr_downlink_indication_t *dl_info); -void ue_contention_resolution(module_id_t module_id, uint8_t gNB_index, int cc_id, frame_t tx_frame); +void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources); -void nr_ra_failed(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index); +void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot); -void nr_ra_succeeded(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index); +void nr_ra_succeeded(module_id_t mod_id, frame_t frame, int slot); /* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure. If the UE is not in PUSCH mode for a particular eNB index, this is assumed to be an Msg3 and MAC attempts to retrieves the CCCH message from RRC. If the UE is in PUSCH mode for a particular eNB index and PUCCH format 0 (Scheduling Request) is not activated, the MAC may use this resource for -andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 from 36.321) +andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 from 38.321) @param mod_id Index of UE instance @param CC_id Component Carrier Index @param frame @param gNB_id gNB index -@param nr_tti_tx slot for PRACH transmission +@param nr_slot_tx slot for PRACH transmission @returns indication to generate PRACH to phy */ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, + fapi_nr_ul_config_prach_pdu *prach_pdu, module_id_t mod_id, int CC_id, - UE_MODE_t UE_mode, frame_t frame, uint8_t gNB_id, - int nr_tti_tx); + int nr_slot_tx); /* \brief Function implementing the routine for the selection of Random Access resources (5.1.2 TS 38.321). @param module_idP Index of UE instance @param CC_id Component Carrier Index @param gNB_index gNB index -@param t_id @param rach_ConfigDedicated @returns void */ void nr_get_prach_resources(module_id_t mod_id, int CC_id, uint8_t gNB_id, - uint8_t t_id, - uint8_t first_Msg3, NR_PRACH_RESOURCES_t *prach_resources, + fapi_nr_ul_config_prach_pdu *prach_pdu, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id); -void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id); +void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); void nr_ue_msg2_scheduler(module_id_t mod_id, uint16_t rach_frame, uint16_t rach_slot, uint16_t *msg2_frame, uint16_t *msg2_slot); + +int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, + uint16_t n_RB_ULBWP, + uint16_t n_RB_DLBWP, + uint16_t riv); + +void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id); +void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); + +void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac); + +void config_bwp_ue(NR_UE_MAC_INST_t *mac, uint16_t *bwp_ind, uint8_t *dci_format); + +fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot); + +void fill_ul_config(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx, uint8_t pdu_type); + +// PUSCH scheduler: +// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, +// - where K2 is the offset between the slot in which UL DCI is received and the slot +// - in which ULSCH should be scheduled. K2 is configured in RRC configuration. +// PUSCH Msg3 scheduler: +// - scheduled by RAR UL grant according to 8.3 of TS 38.213 +int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, uint8_t is_Msg3, frame_t current_frame, int current_slot, frame_t *frame_tx, int *slot_tx, uint8_t tda_id); + +int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti); + +// Configuration of Msg3 PDU according to clauses: +// - 8.3 of 3GPP TS 38.213 version 16.3.0 Release 16 +// - 6.1.2.2 of TS 38.214 +// - 6.1.3 of TS 38.214 +// - 6.2.2 of TS 38.214 +// - 6.1.4.2 of TS 38.214 +// - 6.4.1.1.1 of TS 38.211 +// - 6.3.1.7 of 38.211 +int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, + dci_pdu_rel15_t *dci, + RAR_grant_t *rar_grant, + uint16_t rnti, + uint8_t *dci_format); #endif /** @}*/ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_vars.c b/openair2/LAYER2/NR_MAC_UE/mac_vars.c index 95dea61a45..383267090f 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_vars.c +++ b/openair2/LAYER2/NR_MAC_UE/mac_vars.c @@ -30,106 +30,404 @@ * \warning */ -#include "mac_defs.h" +#include -#define reserved 0xffff +const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC", "NR_RNTI_SP_CSI", "NR_RNTI_SI"}; +const char *dci_formats[]={"1_0", "1_1", "2_0", "2_1", "2_2", "2_3", "0_0", "0_1"}; -// specification mapping talbe, table_38$x_$y_$z_c$a -// - $x: specification -// - $y: subclause-major -// - $z: subclause-minor -// - $a: ($a)th of column in table, start from zero -const int32_t table_38213_13_1_c2[16] = {24, 24, 24, 24, 24, 24, 48, 48, 48, 48, 48, 48, 96, 96, 96, reserved}; // index 15 reserved -const int32_t table_38213_13_1_c3[16] = { 2, 2, 2, 3, 3, 3, 1, 1, 2, 2, 3, 3, 1, 2, 3, reserved}; // index 15 reserved -const int32_t table_38213_13_1_c4[16] = { 0, 2, 4, 0, 2, 4, 12, 16, 12, 16, 12, 16, 38, 38, 38, reserved}; // index 15 reserved +// table_7_3_1_1_2_2_3_4_5 contains values for number of layers and precoding information for tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2 +// the first 6 columns contain table 7.3.1.1.2-2: Precoding information and number of layers, for 4 antenna ports, if transformPrecoder=disabled and maxRank = 2 or 3 or 4 +// next six columns contain table 7.3.1.1.2-3: Precoding information and number of layers for 4 antenna ports, if transformPrecoder= enabled, or if transformPrecoder=disabled and maxRank = 1 +// next four columns contain table 7.3.1.1.2-4: Precoding information and number of layers, for 2 antenna ports, if transformPrecoder=disabled and maxRank = 2 +// next four columns contain table 7.3.1.1.2-5: Precoding information and number of layers, for 2 antenna ports, if transformPrecoder= enabled, or if transformPrecoder= disabled and maxRank = 1 +const uint8_t table_7_3_1_1_2_2_3_4_5[64][20] = { + {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 0, 2, 0, 1, 2, 0, 0}, + {1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 2, 0, 0, 1, 3, 0, 0}, + {2, 0, 2, 0, 2, 0, 1, 4, 1, 4, 0, 0, 1, 3, 0, 0, 1, 4, 0, 0}, + {2, 1, 2, 1, 2, 1, 1, 5, 1, 5, 0, 0, 1, 4, 0, 0, 1, 5, 0, 0}, + {2, 2, 2, 2, 2, 2, 1, 6, 1, 6, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0}, + {2, 3, 2, 3, 2, 3, 1, 7, 1, 7, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0}, + {2, 4, 2, 4, 2, 4, 1, 8, 1, 8, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0}, + {2, 5, 2, 5, 2, 5, 1, 9, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 0, 3, 0, 3, 0, 1, 10, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 0, 4, 0, 4, 0, 1, 11, 1, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 4, 1, 4, 0, 0, 1, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 5, 1, 5, 0, 0, 1, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 6, 1, 6, 0, 0, 1, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 7, 1, 7, 0, 0, 1, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 8, 1, 8, 0, 0, 1, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 9, 1, 9, 0, 0, 1, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 10, 1, 10, 0, 0, 1, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 11, 1, 11, 0, 0, 1, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 6, 2, 6, 0, 0, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 7, 2, 7, 0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 8, 2, 8, 0, 0, 1, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 9, 2, 9, 0, 0, 1, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 10, 2, 10, 0, 0, 1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 11, 2, 11, 0, 0, 1, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 12, 2, 12, 0, 0, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 13, 2, 13, 0, 0, 1, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 1, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 2, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; -const int32_t table_38213_13_2_c2[16] = {24, 24, 24, 24, 24, 24, 24, 24, 48, 48, 48, 48, 48, 48, reserved, reserved}; // index 14-15 reserved -const int32_t table_38213_13_2_c3[16] = { 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 2, 2, 3, 3, reserved, reserved}; // index 14-15 reserved -const int32_t table_38213_13_2_c4[16] = { 5, 6, 7, 8, 5, 6, 7, 8, 18, 20, 18, 20, 18, 20, reserved, reserved}; // index 14-15 reserved +const uint8_t table_7_3_1_1_2_12[14][3] = { + {1,0,1}, + {1,1,1}, + {2,0,1}, + {2,1,1}, + {2,2,1}, + {2,3,1}, + {2,0,2}, + {2,1,2}, + {2,2,2}, + {2,3,2}, + {2,4,2}, + {2,5,2}, + {2,6,2}, + {2,7,2} +}; -const int32_t table_38213_13_3_c2[16] = {48, 48, 48, 48, 48, 48, 96, 96, 96, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved -const int32_t table_38213_13_3_c3[16] = { 1, 1, 2, 2, 3, 3, 1, 2, 3, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved -const int32_t table_38213_13_3_c4[16] = { 2, 6, 2, 6, 2, 6, 28, 28, 28, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved +const uint8_t table_7_3_1_1_2_13[10][4] = { + {1,0,1,1}, + {2,0,1,1}, + {2,2,3,1}, + {2,0,2,1}, + {2,0,1,2}, + {2,2,3,2}, + {2,4,5,2}, + {2,6,7,2}, + {2,0,4,2}, + {2,2,6,2} +}; -const int32_t table_38213_13_4_c2[16] = {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 48, 48, 48, 48, 48, 48}; -const int32_t table_38213_13_4_c3[16] = { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 1, 1, 1, 2, 2, 2}; -const int32_t table_38213_13_4_c4[16] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 12, 14, 16, 12, 14, 16}; +const uint8_t table_7_3_1_1_2_14[3][5] = { + {2,0,1,2,1}, + {2,0,1,4,2}, + {2,2,3,6,2} +}; -const int32_t table_38213_13_5_c2[16] = {48, 48, 48, 96, 96, 96, 96, 96, 96, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved -const int32_t table_38213_13_5_c3[16] = { 1, 2, 3, 1, 1, 2, 2, 3, 3, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved -const int32_t table_38213_13_5_c4[16] = { 4, 4, 4, 0, 56, 0, 56, 0, 56, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 09-15 reserved +const uint8_t table_7_3_1_1_2_15[4][6] = { + {2,0,1,2,3,1}, + {2,0,1,4,5,2}, + {2,2,3,6,7,2}, + {2,0,2,4,6,2} +}; -const int32_t table_38213_13_6_c2[16] = {24, 24, 24, 24, 48, 48, 48, 48, 48, 48, reserved, reserved, reserved, reserved, reserved, reserved}; // index 10-15 reserved -const int32_t table_38213_13_6_c3[16] = { 2, 2, 3, 3, 1, 1, 2, 2, 3, 3, reserved, reserved, reserved, reserved, reserved, reserved}; // index 10-15 reserved -const int32_t table_38213_13_6_c4[16] = { 0, 4, 0, 4, 0, 28, 0, 28, 0, 28, reserved, reserved, reserved, reserved, reserved, reserved}; // index 10-15 reserved +const uint8_t table_7_3_1_1_2_16[12][2] = { + {1,0}, + {1,1}, + {2,0}, + {2,1}, + {2,2}, + {2,3}, + {3,0}, + {3,1}, + {3,2}, + {3,3}, + {3,4}, + {3,5} +}; -const int32_t table_38213_13_7_c2[16] = {48, 48, 48, 48, 48, 48, 96, 96, 48, 48, 96, 96, reserved, reserved, reserved, reserved}; // index 12-15 reserved -const int32_t table_38213_13_7_c3[16] = { 1, 1, 2, 2, 3, 3, 1, 2, 1, 1, 1, 1, reserved, reserved, reserved, reserved}; // index 12-15 reserved -const int32_t table_38213_13_7_c4[16] = { 0, 8, 0, 8, 0, 8, 28, 28,-41, 49,-41, 97, reserved, reserved, reserved, reserved}; // index 12-15 reserved, condition A as default +const uint8_t table_7_3_1_1_2_17[7][3] = { + {1,0,1}, + {2,0,1}, + {2,2,3}, + {3,0,1}, + {3,2,3}, + {3,4,5}, + {2,0,2} +}; -const int32_t table_38213_13_8_c2[16] = { 1, 1, 1, 1, 3, 3, 3, 3, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 15 reserved -const int32_t table_38213_13_8_c3[16] = {24, 24, 48, 48, 24, 24, 48, 48, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 15 reserved -const int32_t table_38213_13_8_c4[16] = { 0, 4, 14, 14,-20, 24,-20, 48, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 15 reserved, condition A as default +const uint8_t table_7_3_1_1_2_18[3][4] = { + {2,0,1,2}, + {3,0,1,2}, + {3,3,4,5} +}; -const int32_t table_38213_13_9_c2[16] = {96, 96, 96, 96, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 04-15 reserved -const int32_t table_38213_13_9_c3[16] = { 1, 1, 2, 2, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 04-15 reserved -const int32_t table_38213_13_9_c4[16] = { 0, 16, 0, 16, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 04-15 reserved +const uint8_t table_7_3_1_1_2_19[2][5] = { + {2,0,1,2,3}, + {3,0,1,2,3} +}; -const int32_t table_38213_13_10_c2[16] = {48, 48, 48, 48, 24, 24, 48, 48, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 08-15 reserved -const int32_t table_38213_13_10_c3[16] = { 1, 1, 2, 2, 1, 1, 1, 1, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 08-15 reserved -const int32_t table_38213_13_10_c4[16] = { 0, 8, 0, 8,-41, 25,-41, 49, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved}; // index 08-15 reserved, condition A as default +const uint8_t table_7_3_1_1_2_20[28][3] = { + {1,0,1}, + {1,1,1}, + {2,0,1}, + {2,1,1}, + {2,2,1}, + {2,3,1}, + {3,0,1}, + {3,1,1}, + {3,2,1}, + {3,3,1}, + {3,4,1}, + {3,5,1}, + {3,0,2}, + {3,1,2}, + {3,2,2}, + {3,3,2}, + {3,4,2}, + {3,5,2}, + {3,6,2}, + {3,7,2}, + {3,8,2}, + {3,9,2}, + {3,10,2}, + {3,11,2}, + {1,0,2}, + {1,1,2}, + {1,6,2}, + {1,7,2} +}; -const float table_38213_13_11_c1[16] = { 0, 0, 2, 2, 5, 5, 7, 7, 0, 5, 0, 0, 2, 2, 5, 5}; // O -const int32_t table_38213_13_11_c2[16] = { 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1}; -const float table_38213_13_11_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 1, 0.5f, 1, 1, 1, 1, 1, 1, 1, 1}; // M -const int32_t table_38213_13_11_c4[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2}; // i is even as default +const uint8_t table_7_3_1_1_2_21[19][4] = { + {1,0,1,1}, + {2,0,1,1}, + {2,2,3,1}, + {3,0,1,1}, + {3,2,3,1}, + {3,4,5,1}, + {2,0,2,1}, + {3,0,1,2}, + {3,2,3,2}, + {3,4,5,2}, + {3,6,7,2}, + {3,8,9,2}, + {3,10,11,2}, + {1,0,1,2}, + {1,6,7,2}, + {2,0,1,2}, + {2,2,3,2}, + {2,6,7,2}, + {2,8,9,2} +}; -const float table_38213_13_12_c1[16] = { 0, 0, 2.5f, 2.5f, 5, 5, 0, 2.5f, 5, 7.5f, 7.5f, 7.5f, 0, 5, reserved, reserved}; // O, index 14-15 reserved -const int32_t table_38213_13_12_c2[16] = { 1, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, reserved, reserved}; // index 14-15 reserved -const float table_38213_13_12_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 0.5f, 0.5f, 0.5f, 1, 0.5f, 0.5f, 1, 1, reserved, reserved}; // M, index 14-15 reserved +const uint8_t table_7_3_1_1_2_22[6][5] = { + {2,0,1,2,1}, + {3,0,1,2,1}, + {3,3,4,5,1}, + {3,0,1,6,2}, + {3,2,3,8,2}, + {3,4,5,10,2} +}; -const int32_t table_38213_10_1_1_c2[5] = { 0, 0, 4, 2, 1 }; +const uint8_t table_7_3_1_1_2_23[5][6] = { + {2,0,1,2,3,1}, + {3,0,1,2,3,1}, + {3,0,1,6,7,2}, + {3,2,3,8,9,2}, + {3,4,5,10,11,2} +}; -/* - #define mu_pusch 1 -// definition table j Table 6.1.2.1.1-4 - #define j ((mu_pusch==3)?3:(mu_pusch==2)?2:1) - uint8_t table_6_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PUSCH from TS 38.214 subclause 6.1.2.1.1 - {j, 0,14}, // row index 1 - {j, 0,12}, // row index 2 - {j, 0,10}, // row index 3 - {j, 2,10}, // row index 4 - {j, 4,10}, // row index 5 - {j, 4,8}, // row index 6 - {j, 4,6}, // row index 7 - {j+1,0,14}, // row index 8 - {j+1,0,12}, // row index 9 - {j+1,0,10}, // row index 10 - {j+2,0,14}, // row index 11 - {j+2,0,12}, // row index 12 - {j+2,0,10}, // row index 13 - {j, 8,6}, // row index 14 - {j+3,0,14}, // row index 15 - {j+3,0,10} // row index 16 - }; +const uint8_t table_7_3_2_3_3_1[12][5] = { + {1,0,0,0,0}, + {1,1,0,0,0}, + {1,0,1,0,0}, + {2,0,0,0,0}, + {2,1,0,0,0}, + {2,2,0,0,0}, + {2,3,0,0,0}, + {2,0,1,0,0}, + {2,2,3,0,0}, + {2,0,1,2,0}, + {2,0,1,2,3}, + {2,0,2,0,0} +}; - #define dmrs_typeA_pos 2 - uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?12:11}, // row index 1 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?10:9}, // row index 2 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?9:8}, // row index 3 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?7:6}, // row index 4 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?5:4}, // row index 5 - {0,(dmrs_typeA_pos == 2)?9:10,(dmrs_typeA_pos == 2)?4:4}, // row index 6 - {0,(dmrs_typeA_pos == 2)?4:6, (dmrs_typeA_pos == 2)?4:4}, // row index 7 - {0,5,7}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,12,2}, // row index 11 - {0,1,13}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,7}, // row index 15 - {0,8,4} // row index 16 - }; -*/ +const uint8_t table_7_3_2_3_3_2_oneCodeword[31][6] = { + {1,0,0,0,0,1}, + {1,1,0,0,0,1}, + {1,0,1,0,0,1}, + {2,0,0,0,0,1}, + {2,1,0,0,0,1}, + {2,2,0,0,0,1}, + {2,3,0,0,0,1}, + {2,0,1,0,0,1}, + {2,2,3,0,0,1}, + {2,0,1,2,0,1}, + {2,0,1,2,3,1}, + {2,0,2,0,0,1}, + {2,0,0,0,0,2}, + {2,1,0,0,0,2}, + {2,2,0,0,0,2}, + {2,3,0,0,0,2}, + {2,4,0,0,0,2}, + {2,5,0,0,0,2}, + {2,6,0,0,0,2}, + {2,7,0,0,0,2}, + {2,0,1,0,0,2}, + {2,2,3,0,0,2}, + {2,4,5,0,0,2}, + {2,6,7,0,0,2}, + {2,0,4,0,0,2}, + {2,2,6,0,0,2}, + {2,0,1,4,0,2}, + {2,2,3,6,0,2}, + {2,0,1,4,5,2}, + {2,2,3,6,7,2}, + {2,0,2,4,6,2} +}; + +const uint8_t table_7_3_2_3_3_2_twoCodeword[4][10] = { + {2,0,1,2,3,4,0,0,0,2}, + {2,0,1,2,3,4,6,0,0,2}, + {2,0,1,2,3,4,5,6,0,2}, + {2,0,1,2,3,4,5,6,7,2} +}; + +const uint8_t table_7_3_2_3_3_3_oneCodeword[24][5] = { + {1,0,0,0,0}, + {1,1,0,0,0}, + {1,0,1,0,0}, + {2,0,0,0,0}, + {2,1,0,0,0}, + {2,2,0,0,0}, + {2,3,0,0,0}, + {2,0,1,0,0}, + {2,2,3,0,0}, + {2,0,1,2,0}, + {2,0,1,2,3}, + {3,0,0,0,0}, + {3,1,0,0,0}, + {3,2,0,0,0}, + {3,3,0,0,0}, + {3,4,0,0,0}, + {3,5,0,0,0}, + {3,0,1,0,0}, + {3,2,3,0,0}, + {3,4,5,0,0}, + {3,0,1,2,0}, + {3,3,4,5,0}, + {3,0,1,2,3}, + {2,0,2,0,0} +}; + +const uint8_t table_7_3_2_3_3_3_twoCodeword[2][7] = { + {3,0,1,2,3,4,0}, + {3,0,1,2,3,4,5} +}; + +const uint8_t table_7_3_2_3_3_4_oneCodeword[58][6] = { + {1,0,0,0,0,1}, + {1,1,0,0,0,1}, + {1,0,1,0,0,1}, + {2,0,0,0,0,1}, + {2,1,0,0,0,1}, + {2,2,0,0,0,1}, + {2,3,0,0,0,1}, + {2,0,1,0,0,1}, + {2,2,3,0,0,1}, + {2,0,1,2,0,1}, + {2,0,1,2,3,1}, + {3,0,0,0,0,1}, + {3,1,0,0,0,1}, + {3,2,0,0,0,1}, + {3,3,0,0,0,1}, + {3,4,0,0,0,1}, + {3,5,0,0,0,1}, + {3,0,1,0,0,1}, + {3,2,3,0,0,1}, + {3,4,5,0,0,1}, + {3,0,1,2,0,1}, + {3,3,4,5,0,1}, + {3,0,1,2,3,1}, + {2,0,2,0,0,1}, + {3,0,0,0,0,2}, + {3,1,0,0,0,2}, + {3,2,0,0,0,2}, + {3,3,0,0,0,2}, + {3,4,0,0,0,2}, + {3,5,0,0,0,2}, + {3,6,0,0,0,2}, + {3,7,0,0,0,2}, + {3,8,0,0,0,2}, + {3,9,0,0,0,2}, + {3,10,0,0,0,2}, + {3,11,0,0,0,2}, + {3,0,1,0,0,2}, + {3,2,3,0,0,2}, + {3,4,5,0,0,2}, + {3,6,7,0,0,2}, + {3,8,9,0,0,2}, + {3,10,11,0,0,2}, + {3,0,1,6,0,2}, + {3,2,3,8,0,2}, + {3,4,5,10,0,2}, + {3,0,1,6,7,2}, + {3,2,3,8,9,2}, + {3,4,5,10,11,2}, + {1,0,0,0,0,2}, + {1,1,0,0,0,2}, + {1,6,0,0,0,2}, + {1,7,0,0,0,2}, + {1,0,1,0,0,2}, + {1,6,7,0,0,2}, + {2,0,1,0,0,2}, + {2,2,3,0,0,2}, + {2,6,7,0,0,2}, + {2,8,9,0,0,2} +}; + +const uint8_t table_7_3_2_3_3_4_twoCodeword[6][10] = { + {3,0,1,2,3,4,0,0,0,1}, + {3,0,1,2,3,4,5,0,0,1}, + {2,0,1,2,3,6,0,0,0,2}, + {2,0,1,2,3,6,8,0,0,2}, + {2,0,1,2,3,6,7,8,0,2}, + {2,0,1,2,3,6,7,8,9,2} +}; + +// table 7.2-1 TS 38.321 +const uint16_t table_7_2_1[16] = { + 5, // row index 0 + 10, // row index 1 + 20, // row index 2 + 30, // row index 3 + 40, // row index 4 + 60, // row index 5 + 80, // row index 6 + 120, // row index 7 + 160, // row index 8 + 240, // row index 9 + 320, // row index 10 + 480, // row index 11 + 960, // row index 12 + 1920, // row index 13 +}; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index af9822a5df..73b5a35b62 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -37,32 +37,55 @@ #include "assertions.h" #include "PHY/types.h" #include "PHY/defs_UE.h" -#include "openair2/LAYER2/RLC/rlc.h" -#include "openair2/LAYER2/PDCP_v10.1.0/pdcp.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "executables/softmodem-common.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp.h" +#include static NR_UE_MAC_INST_t *nr_ue_mac_inst; -NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) -{ +NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { + //LOG_I(MAC, "[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n"); //LOG_I(MAC, "[MAIN] init UE MAC functions \n"); //init mac here nr_ue_mac_inst = (NR_UE_MAC_INST_t *)calloc(sizeof(NR_UE_MAC_INST_t),NB_NR_UE_MAC_INST); - if (rrc_inst) { - nr_rrc_mac_config_req_ue(0,0,0,NULL,rrc_inst->cell_group_config); - + + for (int j=0;jscell_group_config) { + + nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,rrc_inst->scell_group_config); + AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); if (IS_SOFTMODEM_NOS1){ - if (rlc_module_init(0) != 0) { - LOG_I(RLC, "Problem at RLC initiation \n"); - } - pdcp_layer_init(); - nr_ip_over_LTE_DRB_preconfiguration(); + pdcp_layer_init(); + nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); + } + // Allocate memory for ul_config_request in the mac instance. This is now a pointer and will + // point to a list of structures (one for each UL slot) to store PUSCH scheduling parameters + // received from UL DCI. + if (nr_ue_mac_inst->scc) { + int num_slots_ul = nr_ue_mac_inst->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if (nr_ue_mac_inst->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols>0) + num_slots_ul++; + LOG_D(MAC, "Initializing ul_config_request. num_slots_ul = %d\n", num_slots_ul); + nr_ue_mac_inst->ul_config_request = (fapi_nr_ul_config_request_t *)calloc(num_slots_ul, sizeof(fapi_nr_ul_config_request_t)); + for (int i=0; iul_config_request[i].mutex_ul_config), NULL); + } + } + else { + LOG_I(MAC,"Running without CellGroupConfig\n"); + nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,NULL); + if(get_softmodem_params()->sa == 1) { + AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); } } - else LOG_I(MAC,"Running without RRC instance\n"); return (nr_ue_mac_inst); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.c b/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.c index f8bb1e5f8e..eaaa5f5f72 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.c @@ -20,7 +20,7 @@ */ /*! \file nr_l1_helper.c -* \brief PHY helper functions for PRACH adapted to NR +* \brief PHY/MAC helper functions * \author Guido Casati * \date 2019 * \version 2.0 @@ -30,124 +30,91 @@ */ #include "PHY/defs_nr_common.h" +//#include "PHY/impl_defs_top.h" #include "mac_defs.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" #include "LAYER2/NR_MAC_UE/mac_proto.h" +#include "LAYER2/NR_MAC_UE/nr_l1_helpers.h" +#include "NR_P-Max.h" -/* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */ -int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_format){ + +// Implementation of 6.2.4 Configured ransmitted power +// 3GPP TS 38.101-1 version 16.5.0 Release 16 +// - +// The UE is allowed to set its configured maximum output power PCMAX,f,c for carrier f of serving cell c in each slot. +// The configured maximum output power PCMAX,f,c is set within the following bounds: PCMAX_L,f,c <= PCMAX,f,c <= PCMAX_H,f,c +// - +// Measurement units: +// - p_max: dBm +// - delta_TC_c: dB +// - P_powerclass: dBm +// - delta_P_powerclass: dB +// - MPR_c: dB +// - delta_MPR_c: dB +// - delta_T_IB_c dB +// - delta_rx_SRS dB +// note: +// - Assuming: +// -- Powerclass 3 capable UE (which is default power class unless otherwise stated) +// -- Maximum power reduction (MPR_c) for power class 3, QPSK, inner RB allocations +// -- no additional MPR (A_MPR_c) +// todo: +// - in current implementation delta_P_powerclass is not handling power classes different from 3 +long nr_get_Pcmax(module_id_t mod_id){ NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_SubcarrierSpacing_t scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing; - int prach_sequence_length = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present - 1; - uint8_t prachConfigIndex, mu; + uint32_t band = (mac->scc!=NULL) ? *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] : + *mac->scc_SIB->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR; + NR_P_Max_t p_max = 0; + uint8_t P_powerclass = 23; + uint8_t delta_P_powerclass = 0; + uint8_t MPR_c = 1.5; + uint8_t delta_MPR_c = 0; + uint8_t A_MPR_c = 0; + uint8_t delta_T_IB_c = 0; + uint8_t delta_TC_c = 0; + uint8_t delta_rx_SRS = 0; + uint8_t P_MPR_c = 0; + long P_cmax_l = 0; + long P_cmax_h = 0; + long P_cmax = 0; - AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); - - // SCS configuration from msg1_SubcarrierSpacing and table 4.2-1 in TS 38.211 - - switch (scs){ - case NR_SubcarrierSpacing_kHz15: - mu = 0; - break; - - case NR_SubcarrierSpacing_kHz30: - mu = 1; - break; - - case NR_SubcarrierSpacing_kHz60: - mu = 2; - break; - - case NR_SubcarrierSpacing_kHz120: - mu = 3; - break; - - case NR_SubcarrierSpacing_kHz240: - mu = 4; - break; - - case NR_SubcarrierSpacing_spare3: - mu = 5; - break; - - case NR_SubcarrierSpacing_spare2: - mu = 6; - break; - - case NR_SubcarrierSpacing_spare1: - mu = 7; - break; - - default: - AssertFatal(1 == 0,"Unknown msg1_SubcarrierSpacing %lu\n", scs); + if (band == 28 && mac->phy_config.config_req.carrier_config.uplink_bandwidth == 30){ + delta_MPR_c = 0.5; } - // Preamble formats given by prach_ConfigurationIndex and tables 6.3.3.2-2 and 6.3.3.2-2 in TS 38.211 - - prachConfigIndex = nr_rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - - if (prach_sequence_length == 0) { - AssertFatal(prach_format < 4, "Illegal PRACH format %d for sequence length 839\n", prach_format); - switch (prach_format) { - - // long preamble formats - case 0: - case 3: - return 0; - - case 1: - return -3; - - case 2: - return -6; + if (mac->cg && mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->ext1){ + if (*mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->ext1->powerBoostPi2BPSK == 1){ + // TbD: assuming power class 3 capable UE operating in TDD bands n40, n41, n77, n78, and n79 with Pi/2 BPSK modulation + delta_P_powerclass = -3; + p_max += 3; } + } + + NR_P_Max_t *p_Max = (mac->scc!=NULL) ? mac->scc->uplinkConfigCommon->frequencyInfoUL->p_Max : mac->scc_SIB->uplinkConfigCommon->frequencyInfoUL.p_Max; + if (p_Max){ + + p_max += *p_Max; + + LOG_D(MAC, "In %s maximum UL transmission power p_max is %ld dBm \n", __FUNCTION__, p_max); + + P_cmax_l = min(p_max - delta_TC_c, (P_powerclass - delta_P_powerclass) - max(max(MPR_c + delta_MPR_c, A_MPR_c) + delta_T_IB_c + delta_TC_c + delta_rx_SRS, P_MPR_c)); + + P_cmax_h = min(p_max, P_powerclass - delta_P_powerclass); + } else { - switch (prach_format) { // short preamble formats - case 0: - case 3: - return 8 + 3*mu; - case 1: - case 4: - case 8: - return 5 + 3*mu; + P_cmax_l = (P_powerclass - delta_P_powerclass) - max(max(MPR_c + delta_MPR_c, A_MPR_c) + delta_T_IB_c + delta_TC_c + delta_rx_SRS, P_MPR_c); - case 2: - case 5: - return 3 + 3*mu; + P_cmax_h = P_powerclass - delta_P_powerclass; - case 6: - return 3*mu; - - case 7: - return 5 + 3*mu; - - default: - AssertFatal(1 == 0, "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n", mod_id, prach_format, prachConfigIndex); - } } - return 0; -} -/* TS 38.321 subclause 5.1.3 - RA preamble transmission - ra_PREAMBLE_RECEIVED_TARGET_POWER configuration */ -int nr_get_Po_NOMINAL_PUSCH(NR_PRACH_RESOURCES_t *prach_resources, module_id_t mod_id, uint8_t CC_id){ - - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - int8_t receivedTargerPower, delta_preamble; - long preambleReceivedTargetPower; + P_cmax = (P_cmax_h + P_cmax_l) / 2; - AssertFatal(nr_rach_ConfigCommon != NULL, "[UE %d] CCid %d FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id, CC_id); + LOG_D(MAC, "In %s configured maximum output power: %ld dBm <= PCMAX %ld dBm <= %ld dBm \n", __FUNCTION__, P_cmax_l, P_cmax, P_cmax_h); - preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower; - delta_preamble = nr_get_DELTA_PREAMBLE(mod_id, CC_id, prach_resources->prach_format); + return P_cmax; - receivedTargerPower = preambleReceivedTargetPower + delta_preamble + (mac->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP; - - return receivedTargerPower; } diff --git a/common/utils/itti_analyzer/libparser/file_type.h b/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.h old mode 100644 new mode 100755 similarity index 82% rename from common/utils/itti_analyzer/libparser/file_type.h rename to openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.h index 34ebea6745..8b3f00af43 --- a/common/utils/itti_analyzer/libparser/file_type.h +++ b/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.h @@ -19,13 +19,8 @@ * contact@openairinterface.org */ -#include "types.h" - -#ifndef FILE_TYPE_H_ -#define FILE_TYPE_H_ - -int file_type_file_print(types_t *type, int indent, FILE *file); - -int file_type_hr_display(types_t *type, int indent); - -#endif /* FILE_TYPE_H_ */ +/** \brief Function to compute configured maximum output power according to clause 6.2.4 of 3GPP TS 38.101-1 version 16.5.0 Release 16 + @param Mod_id Module id of UE +*/ +long nr_get_Pcmax(module_id_t mod_id); +/** @}*/ diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 351bcc292f..2d059783fe 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -30,118 +30,401 @@ * \warning */ -#include "mac.h" - -/* -#include "common/utils/LOG/vcd_signal_dumper.h" -#include "PHY_INTERFACE/phy_interface_extern.h" -#include "SCHED_UE/sched_UE.h" -#include "COMMON/mac_rrc_primitives.h" -#include "RRC/LTE/rrc_extern.h" -#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" -#include "common/utils/LOG/log.h" -#include "UTIL/OPT/opt.h" -#include "OCG.h" -#include "OCG_extern.h" -#include "PHY/LTE_ESTIMATION/lte_estimation.h"*/ - -/* Tools */ -#include "SIMULATION/TOOLS/sim.h" // for taus - /* RRC */ #include "NR_RACH-ConfigCommon.h" +#include "RRC/NR_UE/rrc_proto.h" /* PHY */ -#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" -#include "PHY/defs_common.h" -#include "PHY/defs_nr_common.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" /* MAC */ #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" #include "NR_MAC_COMMON/nr_mac.h" #include "LAYER2/NR_MAC_UE/mac_proto.h" +#include "LAYER2/NR_MAC_UE/nr_l1_helpers.h" -extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; -extern const uint8_t nr_slots_per_frame[5]; - -//extern uint8_t nfapi_mode; +#include void nr_get_RA_window(NR_UE_MAC_INST_t *mac); -// WIP -// This routine implements Section 5.1.2 (UE Random Access Resource Selection) -// and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321 -void nr_get_prach_resources(module_id_t mod_id, - int CC_id, - uint8_t gNB_id, - uint8_t t_id, - uint8_t first_Msg3, - NR_PRACH_RESOURCES_t *prach_resources, - NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ +// Random Access procedure initialization as per 5.1.1 and initialization of variables specific +// to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16) +// todo: +// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX (currently hardcoded to 0) +void init_RA(module_id_t mod_id, + NR_PRACH_RESOURCES_t *prach_resources, + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric, + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated) { NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric; - // NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo + RA_config_t *ra = &mac->ra; + ra->RA_active = 1; + ra->ra_PreambleIndex = -1; + ra->RA_usedGroupA = 1; + ra->RA_RAPID_found = 0; + ra->preambleTransMax = 0; + ra->first_Msg3 = 1; + ra->starting_preamble_nb = 0; + ra->RA_backoff_cnt = 0; - int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, i, deltaPreamble_Msg3 = 0; - uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, prach_ConfigIndex, SFN_nbr, Msg3_size; + prach_resources->RA_PREAMBLE_BACKOFF = 0; + prach_resources->RA_PCMAX = nr_get_Pcmax(mod_id); + prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; + prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1; + prach_resources->POWER_OFFSET_2STEP_RA = 0; + prach_resources->RA_SCALING_FACTOR_BI = 1; - AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id); - nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - rach_ConfigGeneric = &nr_rach_ConfigCommon->rach_ConfigGeneric; + struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList; + NR_SearchSpaceId_t *ra_ss; + NR_SearchSpaceId_t ss_id = -1; + NR_SearchSpace_t *ss = NULL; - // NR_RSRP_Range_t rsrp_ThresholdSSB; // todo + if(mac->scc_SIB) { + commonSearchSpaceList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ss_id = *mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } + else{ + if (mac->scc) { + NR_SearchSpaceId_t *ra_ss = mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + if (ra_ss) { + commonSearchSpaceList = mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ss_id = *mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } + } + if (ss_id < 0) { + ra_ss = mac->DLbwp[0]->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + if (ra_ss) { + commonSearchSpaceList = mac->DLbwp[0]->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ss_id = *mac->DLbwp[0]->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } + } + } - /////////////////////////////////////////////////////////// - //////////* UE Random Access Resource Selection *////////// - /////////////////////////////////////////////////////////// - - // todo: - // - switch initialisation cases - // -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) - // --- SSB selection, set prach_resources->ra_PreambleIndex - // -- RA initiated by PDCCH: ra_preamble_index provided by PDCCH && ra_PreambleIndex != 0b000000 - // --- set PREAMBLE_INDEX to ra_preamble_index - // --- select the SSB signalled by PDCCH - // -- RA initiated for SI request: - // --- SSB selection, set prach_resources->ra_PreambleIndex + AssertFatal(ss_id>-1,"Didn't find ra-SearchSpace\n"); + AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n"); + // Common searchspace list + for (int i = 0; i < commonSearchSpaceList->list.count; i++) { + ss = commonSearchSpaceList->list.array[i]; + if (ss->searchSpaceId == ss_id) + ra->ss = ss; + } if (rach_ConfigDedicated) { - //////////* Contention free RA *////////// - // - the PRACH preamble for the UE to transmit is set through RRC configuration - // - this is the default mode in current implementation! - // Operation for contention-free RA resources when: - // - available SSB with SS-RSRP above rsrp-ThresholdSSB: SSB selection - // - available CSI-RS with CSI-RSRP above rsrp-ThresholdCSI-RS: CSI-RS selection - // - network controlled Mobility - uint8_t cfra_ssb_resource_idx = 0; - prach_resources->ra_PreambleIndex = rach_ConfigDedicated->cfra->resources.choice.ssb->ssb_ResourceList.list.array[cfra_ssb_resource_idx]->ra_PreambleIndex; - LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-free random access procedure... \n", prach_resources->ra_PreambleIndex); - } else { - //////////* Contention-based RA preamble selection *////////// - // todo: - // - selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB - // - todo determine next available PRACH occasion - - // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB; - - Msg3_size = mac->RA_Msg3_size; - - numberOfRA_Preambles = 64; - if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL) - numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles); - - if (!nr_rach_ConfigCommon->groupBconfigured) { - noGroupB = 1; + if (rach_ConfigDedicated->cfra){ + LOG_I(MAC, "Initialization of 2-step contention-free random access procedure\n"); + prach_resources->RA_TYPE = RA_2STEP; + ra->cfra = 1; + } else if (rach_ConfigDedicated->ext1){ + if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16){ + LOG_I(MAC, "In %s: setting RA type to 2-step...\n", __FUNCTION__); + prach_resources->RA_TYPE = RA_2STEP; + ra->cfra = 1; + } else { + LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__); + } } else { - // RA preambles group B is configured - // - Defining the number of RA preambles in RA Preamble Group A for each SSB */ - sizeOfRA_PreamblesGroupA = nr_rach_ConfigCommon->groupBconfigured->numberOfRA_PreamblesGroupA; - switch (nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA){ + LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__); + } + } else if (nr_rach_ConfigCommon){ + LOG_I(MAC, "Initialization of 4-step contention-based random access procedure\n"); + prach_resources->RA_TYPE = RA_4STEP; + ra->cfra = 0; + } else { + LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__); + } + + switch (rach_ConfigGeneric->powerRampingStep){ // in dB + case 0: + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 0; + break; + case 1: + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 2; + break; + case 2: + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 4; + break; + case 3: + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 6; + break; + } + + switch (rach_ConfigGeneric->preambleTransMax) { + case 0: + ra->preambleTransMax = 3; + break; + case 1: + ra->preambleTransMax = 4; + break; + case 2: + ra->preambleTransMax = 5; + break; + case 3: + ra->preambleTransMax = 6; + break; + case 4: + ra->preambleTransMax = 7; + break; + case 5: + ra->preambleTransMax = 8; + break; + case 6: + ra->preambleTransMax = 10; + break; + case 7: + ra->preambleTransMax = 20; + break; + case 8: + ra->preambleTransMax = 50; + break; + case 9: + ra->preambleTransMax = 100; + break; + case 10: + ra->preambleTransMax = 200; + break; + } + + if (nr_rach_ConfigCommon->ext1) { + if (nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity_r16){ + LOG_D(MAC, "In %s:%d: Missing implementation for Access Identity initialization procedures\n", __FUNCTION__, __LINE__); + } + } +} + + +/* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */ +int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_format){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = (mac->scc!=NULL) ? + mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup: + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + NR_SubcarrierSpacing_t scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing; + int prach_sequence_length = (mac->scc!=NULL)?(mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present - 1) : (mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present-1); + uint8_t prachConfigIndex, mu; + + AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); + + // SCS configuration from msg1_SubcarrierSpacing and table 4.2-1 in TS 38.211 + + switch (scs){ + case NR_SubcarrierSpacing_kHz15: + mu = 0; + break; + + case NR_SubcarrierSpacing_kHz30: + mu = 1; + break; + + case NR_SubcarrierSpacing_kHz60: + mu = 2; + break; + + case NR_SubcarrierSpacing_kHz120: + mu = 3; + break; + + case NR_SubcarrierSpacing_kHz240: + mu = 4; + break; + + case NR_SubcarrierSpacing_spare3: + mu = 5; + break; + + case NR_SubcarrierSpacing_spare2: + mu = 6; + break; + + case NR_SubcarrierSpacing_spare1: + mu = 7; + break; + + default: + AssertFatal(1 == 0,"Unknown msg1_SubcarrierSpacing %lu\n", scs); + } + + // Preamble formats given by prach_ConfigurationIndex and tables 6.3.3.2-2 and 6.3.3.2-2 in TS 38.211 + + prachConfigIndex = nr_rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; + + if (prach_sequence_length == 0) { + AssertFatal(prach_format < 4, "Illegal PRACH format %d for sequence length 839\n", prach_format); + switch (prach_format) { + + // long preamble formats + case 0: + case 3: + return 0; + + case 1: + return -3; + + case 2: + return -6; + } + } else { + switch (prach_format) { // short preamble formats + case 0: + case 3: + return 8 + 3*mu; + + case 1: + case 4: + case 8: + return 5 + 3*mu; + + case 2: + case 5: + return 3 + 3*mu; + + case 6: + return 3*mu; + + case 7: + return 5 + 3*mu; + + default: + AssertFatal(1 == 0, "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n", mod_id, prach_format, prachConfigIndex); + } + } + return 0; +} + +// TS 38.321 subclause 5.1.3 - RA preamble transmission - ra_PREAMBLE_RECEIVED_TARGET_POWER configuration +// Measurement units: +// - preambleReceivedTargetPower dBm (-202..-60, 2 dBm granularity) +// - delta_preamble dB +// - RA_PREAMBLE_POWER_RAMPING_STEP dB +// - POWER_OFFSET_2STEP_RA dB +// returns receivedTargerPower in dBm +int nr_get_Po_NOMINAL_PUSCH(NR_PRACH_RESOURCES_t *prach_resources, module_id_t mod_id, uint8_t CC_id){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + int8_t receivedTargerPower; + int8_t delta_preamble; + + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = (mac->scc != NULL) ? mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup: mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower; + delta_preamble = nr_get_DELTA_PREAMBLE(mod_id, CC_id, prach_resources->prach_format); + + receivedTargerPower = preambleReceivedTargetPower + delta_preamble + (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP + prach_resources->POWER_OFFSET_2STEP_RA; + + LOG_D(MAC, "In %s: receivedTargerPower is %d dBm \n", __FUNCTION__, receivedTargerPower); + + return receivedTargerPower; +} + +void ssb_rach_config(RA_config_t *ra, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, fapi_nr_ul_config_prach_pdu *prach_pdu){ + + // Determine the SSB to RACH mapping ratio + // ======================================= + + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; + boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB + uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB + int total_preambles_per_ssb; + uint8_t ssb_nb_in_ro; + int numberOfRA_Preambles = 64; + + switch (ssb_perRACH_config){ + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 8; + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 4; + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 2; + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 1; + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 2; + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 4; + ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 8; + ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 16; + ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen; + break; + default: + AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); + } + + if (nr_rach_ConfigCommon->totalNumberOfRA_Preambles) + numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles); + + // Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration + if ((true == multiple_ssb_per_ro) && (ssb_rach_ratio > 1)) { + total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio; + + ssb_nb_in_ro = prach_pdu->ssb_nb_in_ro; + ra->starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro; + } else { + total_preambles_per_ssb = numberOfRA_Preambles; + ra->starting_preamble_nb = 0; + } +} + +// This routine implements RA preamble configuration according to +// section 5.1 (Random Access procedure) of 3GPP TS 38.321 version 16.2.1 Release 16 +void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t *mac, int16_t dl_pathloss){ + + int messageSizeGroupA = 0; + int sizeOfRA_PreamblesGroupA = 0; + int messagePowerOffsetGroupB = 0; + int PLThreshold = 0; + long deltaPreamble_Msg3 = 0; + uint8_t noGroupB = 0; + // Random seed generation + long long tmp = rdtsc_oai(); + unsigned short int *seed = (unsigned short int*)&tmp; + + RA_config_t *ra = &mac->ra; + NR_RACH_ConfigCommon_t *setup; + if (mac->scc) setup = mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + else setup = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + + NR_BWP_UplinkCommon_t *initialUplinkBWP = (mac->scc) ? mac->scc->uplinkConfigCommon->initialUplinkBWP : &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + if (initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble){ + deltaPreamble_Msg3 = (*initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble) * 2; // dB + LOG_D(MAC, "In %s: deltaPreamble_Msg3 set to %ld\n", __FUNCTION__, deltaPreamble_Msg3); + } + + if (!setup->groupBconfigured) { + noGroupB = 1; + LOG_D(MAC, "In %s:%d: preambles group B is not configured...\n", __FUNCTION__, __LINE__); + } else { + // RA preambles group B is configured + // - Random Access Preambles group B is configured for 4-step RA type + // - Defining the number of RA preambles in RA Preamble Group A for each SSB + LOG_D(MAC, "In %s:%d: preambles group B is configured...\n", __FUNCTION__, __LINE__); + sizeOfRA_PreamblesGroupA = setup->groupBconfigured->numberOfRA_PreamblesGroupA; + switch (setup->groupBconfigured->ra_Msg3SizeGroupA){ /* - Threshold to determine the groups of RA preambles */ case 0: messageSizeGroupA = 56; @@ -174,13 +457,13 @@ void nr_get_prach_resources(module_id_t mod_id, messageSizeGroupA = 72; break; default: - AssertFatal(1 == 0,"Unknown ra_Msg3SizeGroupA %lu\n", nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA); + AssertFatal(1 == 0, "Unknown ra_Msg3SizeGroupA %lu\n", setup->groupBconfigured->ra_Msg3SizeGroupA); /* todo cases 10 -15*/ } /* Power offset for preamble selection in dB */ messagePowerOffsetGroupB = -9999; - switch (nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB){ + switch (setup->groupBconfigured->messagePowerOffsetGroupB){ case 0: messagePowerOffsetGroupB = -9999; break; @@ -206,438 +489,502 @@ void nr_get_prach_resources(module_id_t mod_id, messagePowerOffsetGroupB = 18; break; default: - AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB); - } - - // todo Msg3-DeltaPreamble should be provided from higher layers, otherwise is 0 - mac->deltaPreamble_Msg3 = 0; - deltaPreamble_Msg3 = mac->deltaPreamble_Msg3; + AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", setup->groupBconfigured->messagePowerOffsetGroupB); } PLThreshold = prach_resources->RA_PCMAX - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; - /* Msg3 has not been transmitted yet */ - if (first_Msg3 == 1) { - if (noGroupB == 1) { + } + + /* Msg3 has not been transmitted yet */ + if (ra->first_Msg3) { + if(ra->ra_PreambleIndex < 0 || ra->ra_PreambleIndex > 63) { + if (noGroupB) { // use Group A preamble - prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; - mac->RA_usedGroupA = 1; - } else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) { + ra->ra_PreambleIndex = ra->starting_preamble_nb + (nrand48(seed) % ra->cb_preambles_per_ssb); + ra->RA_usedGroupA = 1; + } else if ((ra->Msg3_size < messageSizeGroupA) && (dl_pathloss > PLThreshold)) { // Group B is configured and RA preamble Group A is used // - todo add condition on CCCH_sdu_size for initiation by CCCH - prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; - mac->RA_usedGroupA = 1; + ra->ra_PreambleIndex = ra->starting_preamble_nb + (nrand48(seed) % sizeOfRA_PreamblesGroupA); + ra->RA_usedGroupA = 1; } else { // Group B preamble is configured and used // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A // the remaining belong to RA Preambles Group B - prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); - mac->RA_usedGroupA = 0; - } - } else { // Msg3 is being retransmitted - if (mac->RA_usedGroupA == 1 && noGroupB == 1) { - prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; - } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){ - prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; - } else { - prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); + ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (nrand48(seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); + ra->RA_usedGroupA = 0; } } + } else { // Msg3 is being retransmitted + if (ra->RA_usedGroupA && noGroupB) { + ra->ra_PreambleIndex = ra->starting_preamble_nb + (nrand48(seed) % ra->cb_preambles_per_ssb); + } else if (ra->RA_usedGroupA && !noGroupB){ + ra->ra_PreambleIndex = ra->starting_preamble_nb + (nrand48(seed) % sizeOfRA_PreamblesGroupA); + } else { + ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (nrand48(seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); + } + } + prach_resources->ra_PreambleIndex = ra->ra_PreambleIndex; +} + +// RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted) +// - this does not apply to contention-free RA Preamble for beam failure recovery request +// - getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario) +// - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier +// - f_id: index of the PRACH occasion in the frequency domain +// - s_id is starting symbol of the PRACH occasion [0...14] +// - t_id is the first slot of the PRACH occasion in a system frame [0...80] +uint16_t set_ra_rnti(NR_UE_MAC_INST_t *mac, fapi_nr_ul_config_prach_pdu *prach_pdu){ + + RA_config_t *ra = &mac->ra; + uint8_t ul_carrier_id = 0; // NUL + uint8_t f_id = prach_pdu->num_ra; + uint8_t t_id = prach_pdu->prach_slot; + uint8_t s_id = prach_pdu->prach_start_symbol; + + ra->ra_rnti = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; + + LOG_D(MAC, "Computed ra_RNTI is %x \n", ra->ra_rnti); + + return ra->ra_rnti; + +} + +// This routine implements Section 5.1.2 (UE Random Access Resource Selection) +// and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321 +// - currently the PRACH preamble is set through RRC configuration for 4-step CFRA mode +// todo: +// - determine next available PRACH occasion +// -- if RA initiated for SI request and ra_AssociationPeriodIndex and si-RequestPeriod are configured +// -- else if SSB is selected above +// -- else if CSI-RS is selected above +// - switch initialisation cases +// -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) +// --- SSB selection, set prach_resources->ra_PreambleIndex +// -- RA initiated by PDCCH: ra_preamble_index provided by PDCCH && ra_PreambleIndex != 0b000000 +// --- set PREAMBLE_INDEX to ra_preamble_index +// --- select the SSB signalled by PDCCH +// -- RA initiated for SI request: +// --- SSB selection, set prach_resources->ra_PreambleIndex +// - condition on notification of suspending power ramping counter from lower layer (5.1.3 TS 38.321) +// - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission +// - Contention-based RA preamble selection: +// -- selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB +void nr_get_prach_resources(module_id_t mod_id, + int CC_id, + uint8_t gNB_id, + NR_PRACH_RESOURCES_t *prach_resources, + fapi_nr_ul_config_prach_pdu *prach_pdu, + NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = (mac->scc)? + mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup : + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + + LOG_D(PHY, "In %s: getting PRACH resources frame (first_Msg3 %d)\n", __FUNCTION__, ra->first_Msg3); + + if (rach_ConfigDedicated) { + if (rach_ConfigDedicated->cfra){ + uint8_t cfra_ssb_resource_idx = 0; + ra->ra_PreambleIndex = rach_ConfigDedicated->cfra->resources.choice.ssb->ssb_ResourceList.list.array[cfra_ssb_resource_idx]->ra_PreambleIndex; + prach_resources->ra_PreambleIndex = ra->ra_PreambleIndex; + LOG_D(MAC, "In %s: selected RA preamble index %d for contention-free random access procedure for SSB with Id %d\n", __FUNCTION__, prach_resources->ra_PreambleIndex, cfra_ssb_resource_idx); + } + } else { + int16_t dl_pathloss = get_nr_PL(mod_id, CC_id, gNB_id); + ssb_rach_config(ra, prach_resources, nr_rach_ConfigCommon, prach_pdu); + ra_preambles_config(prach_resources, mac, dl_pathloss); LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex); } - // todo determine next available PRACH occasion - // - if RA initiated for SI request and ra_AssociationPeriodIndex and si-RequestPeriod are configured - // - else if SSB is selected above - // - else if CSI-RS is selected above - - ///////////////////////////////////////////////////////////////////////////// - //////////* Random Access Preamble Transmission (5.1.3 TS 38.321) *////////// - ///////////////////////////////////////////////////////////////////////////// - // todo: - // - condition on notification of suspending power ramping counter from lower layer (5.1.3 TS 38.321) - // - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission - // - Extend RA_rnti computation (e.g. f_id selection, ul_carrier_id are hardcoded) - - if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER > 1) - mac->RA_PREAMBLE_POWER_RAMPING_COUNTER++; - + if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER > 1) + prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER++; prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id); + prach_resources->ra_RNTI = set_ra_rnti(mac, prach_pdu); - // RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted) - // 1) this does not apply to contention-free RA Preamble for beam failure recovery request - // 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario) - - prach_ConfigIndex = rach_ConfigGeneric->prach_ConfigurationIndex; - - // ra_RNTI computation - // - todo: this is for TDD FR1 only - // - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier - // - f_id: index of the PRACH occasion in the frequency domain - // - s_id is starting symbol of the PRACH occasion [0...14] - // - t_id is the first slot of the PRACH occasion in a system frame [0...80] - - ul_carrier_id = 0; // NUL - f_id = rach_ConfigGeneric->msg1_FrequencyStart; - SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4]; - s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5]; - - // Pick the first slot of the PRACH occasion in a system frame - for (i = 0; i < 10; i++){ - if (((SFN_nbr & (1 << i)) >> i) == 1){ - t_id = 2*i; - break; - } - } - prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; - mac->ra_rnti = prach_resources->ra_RNTI; - - LOG_D(MAC, "Computed ra_RNTI is %x \n", prach_resources->ra_RNTI); } // TbD: RA_attempt_number not used void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){ - AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - mac->ra_state = WAIT_RAR; - // Start contention resolution timer - mac->RA_attempt_number++; + RA_config_t *ra = &mac->ra; + ra->ra_state = WAIT_RAR; + ra->RA_attempt_number++; } -void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){ - AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); - LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Starting contention resolution timer\n", mod_id, frameP); +void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id){ + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - // start contention resolution timer - mac->RA_contention_resolution_cnt = 0; - mac->RA_contention_resolution_timer_active = 1; + RA_config_t *ra = &mac->ra; + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = (mac->scc) ? + mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup: + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + long mu = (mac->scc) ? + mac->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing : + mac->scc_SIB->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + int subframes_per_slot = nr_slots_per_frame[mu]/10; + + // start contention resolution timer (cnt in slots) + int RA_contention_resolution_timer_subframes = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1)<<3; + + ra->RA_contention_resolution_target_frame = frameP + (RA_contention_resolution_timer_subframes/10); + ra->RA_contention_resolution_target_slot = (slotP + (RA_contention_resolution_timer_subframes * subframes_per_slot)) % nr_slots_per_frame[mu]; + + LOG_D(MAC,"In %s: [UE %d] CB-RA: contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n", + __FUNCTION__, mod_id, frameP, slotP, ra->RA_contention_resolution_target_frame, ra->RA_contention_resolution_target_slot); + + ra->RA_contention_resolution_timer_active = 1; + ra->ra_state = WAIT_CONTENTION_RESOLUTION; + } -///////////////////////////////////////////////////////////////////////// -///////* Random Access Preamble Initialization (5.1.1 TS 38.321) */////// -///////////////////////////////////////////////////////////////////////// -/// Handling inizialization by PDCCH order, MAC entity or RRC (TS 38.300) -/// Only one RA procedure is ongoing at any point in time in a MAC entity -/// the RA procedure on a SCell shall only be initiated by PDCCH order -/// in the current implementation, RA is contention free only - -// WIP -// todo TS 38.321: -// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX -// - BWP operation (subclause 5.15 TS 38.321) -// - handle initialization by beam failure recovery -// - handle initialization by handover -// - handle transmission on DCCH using PRACH (during handover, or sending SR for example) -// - take into account MAC CEs in size_sdu (currently hardcoded size to 1 MAC subPDU and 1 padding subheader) -// - fix rrc data req logic -// - retrieve TBS -// - add mac_rrc_nr_data_req_ue, etc ... -// - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) - +/** + * Function: handles Random Access Preamble Initialization (5.1.1 TS 38.321) + * handles Random Access Response reception (5.1.4 TS 38.321) + * Note: In SA mode the Msg3 contains a CCCH SDU, therefore no C-RNTI MAC CE is transmitted. + * + * @prach_resources pointer to PRACH resources + * @prach_pdu pointer to FAPI UL PRACH PDU + * @mod_id module ID + * @CC_id CC ID + * @frame current UL TX frame + * @gNB_id gNB ID + * @nr_slot_tx current UL TX slot + */ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, + fapi_nr_ul_config_prach_pdu *prach_pdu, module_id_t mod_id, int CC_id, - UE_MODE_t UE_mode, frame_t frame, uint8_t gNB_id, - int nr_tti_tx){ + int nr_slot_tx){ NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - uint8_t mac_sdus[MAX_NR_ULSCH_PAYLOAD_BYTES]; - uint8_t lcid = UL_SCH_LCID_CCCH_MSG3, *payload; - //uint8_t ra_ResponseWindow; - uint16_t size_sdu = 0; - unsigned short post_padding; - //fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + RA_config_t *ra = &mac->ra; + NR_RACH_ConfigCommon_t *setup; + if (mac->scc) setup = mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + else setup = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - //NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = mac->rach_ConfigDedicated; + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated; - // int32_t frame_diff = 0; + // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side + if (!prach_resources->init_msg1) { + if ( (mac->common_configuration_complete>0 || get_softmodem_params()->do_ra==1) && ((MAX_FRAME_NUMBER+frame-prach_resources->sync_frame)%MAX_FRAME_NUMBER)>150 ){ + prach_resources->init_msg1 = 1; + } else { + LOG_D(NR_MAC,"PRACH Condition not met: frame %d, prach_resources->sync_frame %d\n",frame,prach_resources->sync_frame); + return 0; + } + } - uint8_t sdu_lcids[NB_RB_MAX] = {0}; - uint16_t sdu_lengths[NB_RB_MAX] = {0}; - int TBS_bytes = 848, header_length_total=0, num_sdus, offset, preambleTransMax, mac_ce_len; + LOG_D(NR_MAC, "In %s: [UE %d][%d.%d]: init_msg1 %d, ra_state %d, RA_active %d\n", + __FUNCTION__, + mod_id, + frame, + nr_slot_tx, + prach_resources->init_msg1, + ra->ra_state, + ra->RA_active); - AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n"); + if (prach_resources->init_msg1 && ra->ra_state != RA_SUCCEEDED) { - if (UE_mode < PUSCH && prach_resources->init_msg1) { - - LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active); - - AssertFatal(setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id); - - if (mac->RA_active == 0) { + if (ra->RA_active == 0) { /* RA not active - checking if RRC is ready to initiate the RA procedure */ - LOG_I(MAC, "RA not active. Starting RA preamble initialization.\n"); + LOG_D(NR_MAC, "In %s: RA not active. Checking for data to transmit from upper layers...\n", __FUNCTION__); - mac->RA_RAPID_found = 0; + const uint8_t lcid = UL_SCH_LCID_CCCH; + const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_FIXED); + const uint8_t TBS_max = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // Note: unclear the reason behind the selection of such TBS_max + int8_t size_sdu = 0; + uint8_t mac_ce[16] = {0}; + uint8_t *pdu = get_softmodem_params()->sa ? mac->CCCH_pdu.payload : mac_ce; + uint8_t *payload = pdu; - /* Set RA_PREAMBLE_POWER_RAMPING_STEP */ - switch (rach_ConfigGeneric->powerRampingStep){ // in dB - case 0: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 0; - break; - case 1: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 2; - break; - case 2: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 4; - break; - case 3: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 6; - break; - } + // Concerning the C-RNTI MAC CE, it has to be included if the UL transmission (Msg3) is not being made for the CCCH logical channel. + // Therefore it has been assumed that this event only occurs only when RA is done and it is not SA mode. + if (get_softmodem_params()->sa) { - prach_resources->RA_PREAMBLE_BACKOFF = 0; - prach_resources->RA_SCALING_FACTOR_BI = 1; - prach_resources->RA_PCMAX = 0; // currently hardcoded to 0 + NR_MAC_SUBHEADER_FIXED *header = (NR_MAC_SUBHEADER_FIXED *) pdu; + pdu += sh_size; - payload = (uint8_t*) &mac->CCCH_pdu.payload; - - mac_ce_len = 0; - num_sdus = 1; - post_padding = 1; - - if (0){ // initialisation by RRC + nr_rrc_ue_generate_RRCSetupRequest(mod_id,gNB_id); + // CCCH PDU - // size_sdu = (uint16_t) mac_rrc_data_req_ue(mod_id, - // CC_id, - // frame, - // CCCH, - // 1, - // mac_sdus, - // gNB_id, - // 0); - LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu); - } else { - // fill ulsch_buffer with random data - for (int i = 0; i < TBS_bytes; i++){ - mac_sdus[i] = (unsigned char) (lrand48()&0xff); + size_sdu = nr_mac_rrc_data_req_ue(mod_id, CC_id, gNB_id, frame, CCCH, pdu); + LOG_D(NR_MAC, "In %s: [UE %d][%d.%d]: Requested RRCConnectionRequest, got %d bytes for LCID 0x%02x \n", __FUNCTION__, mod_id, frame, nr_slot_tx, size_sdu, lcid); + + if (size_sdu > 0) { + + // UE Contention Resolution Identity + // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to determine whether or not the + // Random Access Procedure has been successful after reception of Msg4 + memcpy(ra->cont_res_id, pdu, sizeof(uint8_t) * 6); + + pdu += size_sdu; + ra->Msg3_size = size_sdu + sh_size; + + // Build header + header->R = 0; + header->LCID = lcid; + + } else { + pdu -= sh_size; } - //Sending SDUs with size 1 - //Initialize elements of sdu_lcids and sdu_lengths - sdu_lcids[0] = lcid; - sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len; - header_length_total += 2 + (sdu_lengths[0] >= 128); - size_sdu += sdu_lengths[0]; + + } else { + + size_sdu = nr_write_ce_ulsch_pdu(pdu, mac, 0, &(mac->crnti), NULL, NULL, NULL); + pdu += size_sdu; + ra->Msg3_size = size_sdu; + } - //mac->RA_tx_frame = frame; - //mac->RA_tx_subframe = nr_tti_tx; - //mac->RA_backoff_frame = frame; - //mac->RA_backoff_subframe = nr_tti_tx; + if (size_sdu > 0 && ra->generate_nr_prach == GENERATE_PREAMBLE) { - if (size_sdu > 0) { - - LOG_I(MAC, "[UE %d] Frame %d: Initialisation Random Access Procedure\n", mod_id, frame); - - mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; - mac->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1; - mac->RA_Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); - mac->RA_prachMaskIndex = 0; - // todo: add the backoff condition here - mac->RA_backoff_cnt = 0; - mac->RA_active = 1; - prach_resources->Msg3 = payload; + LOG_D(NR_MAC, "In %s: [UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", __FUNCTION__, mod_id, frame, nr_slot_tx); + AssertFatal(TBS_max > ra->Msg3_size, "In %s: allocated resources are not enough for Msg3!\n", __FUNCTION__); + // Init RA procedure + init_RA(mod_id, prach_resources, setup, rach_ConfigGeneric, rach_ConfigDedicated); nr_get_RA_window(mac); - // Fill in preamble and PRACH resources - if (mac->generate_nr_prach == 1) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated); - - offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer - (uint8_t *) payload, // UL MAC pdu pointer - num_sdus, // num sdus - sdu_lengths, // sdu length - sdu_lcids, // sdu lcid - 0, // power headroom - 0, // crnti - 0, // truncated bsr - 0, // short bsr - 0, // long_bsr - post_padding, - 0); + nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated); // Padding: fill remainder with 0 - if (post_padding > 0){ - for (int j = 0; j < (TBS_bytes - offset); j++) - payload[offset + j] = 0; // mac_pdu[offset + j] = 0; + if (TBS_max - ra->Msg3_size > 0) { + LOG_D(NR_MAC, "In %s: remaining %d bytes, filling with padding\n", __FUNCTION__, TBS_max - ra->Msg3_size); + ((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0; + ((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = UL_SCH_LCID_PADDING; + pdu += sizeof(NR_MAC_SUBHEADER_FIXED); + for (int j = 0; j < TBS_max - ra->Msg3_size - sizeof(NR_MAC_SUBHEADER_FIXED); j++) { + pdu[j] = 0; + } } - } - } else if (mac->RA_window_cnt != -1) { // RACH is active - //////////////////////////////////////////////////////////////// - /////* Random Access Response reception (5.1.4 TS 38.321) *///// - //////////////////////////////////////////////////////////////// - // Handling ra_responseWindow, RA_PREAMBLE_TRANSMISSION_COUNTER - // and RA_backoff_cnt - // todo: - // - handle beam failure recovery request - // - handle DL assignment on PDCCH for RA-RNTI - // - handle backoff and raResponseWindow params + // Dumping ULSCH payload + LOG_D(NR_MAC, "In %s: dumping UL Msg3 MAC PDU with length %d: \n", __FUNCTION__, TBS_max); + for(int k = 0; k < TBS_max; k++) { + LOG_D(NR_MAC,"(%i): %i\n", k, payload[k]); + } - // LOG_D(MAC, "[MAC][UE %d][RAPROC] frame %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n", - // mod_id, frame, nr_tti_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe); + // Msg3 was initialized with TBS_max bytes because the RA_Msg3_size will only be known after + // receiving Msg2 (which contains the Msg3 resource reserve). + // Msg3 will be transmitted with RA_Msg3_size bytes, removing unnecessary 0s. + mac->ulsch_pdu.Pdu_size = TBS_max; + memcpy(mac->ulsch_pdu.payload, payload, TBS_max); - if (mac->RA_BI_found){ - prach_resources->RA_PREAMBLE_BACKOFF = prach_resources->RA_SCALING_FACTOR_BI * mac->RA_backoff_indicator; + } else { + return 0; + } + } else if (ra->RA_window_cnt != -1) { // RACH is active + + LOG_D(MAC, "In %s [%d.%d] RA is active: RA window count %d, RA backoff count %d\n", __FUNCTION__, frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt); + + if (ra->RA_BI_found){ + prach_resources->RA_PREAMBLE_BACKOFF = prach_resources->RA_SCALING_FACTOR_BI * ra->RA_backoff_indicator; } else { prach_resources->RA_PREAMBLE_BACKOFF = 0; } - if (mac->RA_window_cnt >= 0 && mac->RA_RAPID_found == 1) { + if (ra->RA_window_cnt >= 0 && ra->RA_RAPID_found == 1) { - mac->RA_window_cnt = -1; - mac->ra_state = RA_SUCCEEDED; - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR successfully received \n", mod_id, frame, nr_tti_tx); - - } else if (mac->RA_window_cnt == 0 && !mac->RA_RAPID_found) { - - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception failed \n", mod_id, frame, nr_tti_tx); - - mac->ra_state = RA_UE_IDLE; - mac->RA_PREAMBLE_TRANSMISSION_COUNTER++; - - preambleTransMax = -1; - switch (rach_ConfigGeneric->preambleTransMax) { - case 0: - preambleTransMax = 3; - break; - case 1: - preambleTransMax = 4; - break; - case 2: - preambleTransMax = 5; - break; - case 3: - preambleTransMax = 6; - break; - case 4: - preambleTransMax = 7; - break; - case 5: - preambleTransMax = 8; - break; - case 6: - preambleTransMax = 10; - break; - case 7: - preambleTransMax = 20; - break; - case 8: - preambleTransMax = 50; - break; - case 9: - preambleTransMax = 100; - break; - case 10: - preambleTransMax = 200; - break; + if(ra->cfra) { + // Reset RA_active flag: it disables Msg3 retransmission (8.3 of TS 38.213) + nr_ra_succeeded(mod_id, frame, nr_slot_tx); + } else { + ra->generate_nr_prach = GENERATE_IDLE; } - // Resetting RA window - nr_get_RA_window(mac); + } else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found) { - if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax + 1){ - LOG_D(MAC, "[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n", mod_id, frame, preambleTransMax); - mac->RA_backoff_cnt = rand() % (prach_resources->RA_PREAMBLE_BACKOFF + 1); - mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP << 1; // 2 dB increment - prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id); + LOG_I(MAC, "[UE %d][%d:%d] RAR reception failed \n", mod_id, frame, nr_slot_tx); + + nr_ra_failed(mod_id, CC_id, prach_resources, frame, nr_slot_tx); + + } else if (ra->RA_window_cnt > 0) { + + LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA window count %d) \n", mod_id, frame, nr_slot_tx, ra->RA_window_cnt); + + // Fill in preamble and PRACH resources + ra->RA_window_cnt--; + if (ra->generate_nr_prach == GENERATE_PREAMBLE) { + nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated); } + } else if (ra->RA_backoff_cnt > 0) { - // compute backoff parameters - // if (mac->RA_backoff_cnt > 0){ - // frame_diff = (sframe_t) frame - mac->RA_backoff_frame; - // if (frame_diff < 0) frame_diff = -frame_diff; - // mac->RA_backoff_frame = frame; - // mac->RA_backoff_subframe = nr_tti_tx; - // } - // compute RA window parameters - // if (mac->RA_window_cnt > 0){ - // frame_diff = (frame_t) frame - mac->RA_tx_frame; - // if (frame_diff < 0) frame_diff = -frame_diff; - // mac->RA_window_cnt -= ((10 * frame_diff) + (nr_tti_tx - mac->RA_tx_subframe)); - // LOG_D(MAC, "[MAC][UE %d][RAPROC] Frame %d, subframe %d: RA Active, adjusted window cnt %d\n", mod_id, frame, nr_tti_tx, mac->RA_window_cnt); - // } + LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA backoff count %d) \n", mod_id, frame, nr_slot_tx, ra->RA_backoff_cnt); - // mac->RA_tx_frame = frame; - // mac->RA_tx_subframe = nr_tti_tx; + ra->RA_backoff_cnt--; - // Fill in preamble and PRACH resources - if (mac->generate_nr_prach == 1) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); - - } else { - - mac->RA_window_cnt--; - - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception not successful, (RA window count %d) \n", - mod_id, - frame, - nr_tti_tx, - mac->RA_window_cnt); - - // Fill in preamble and PRACH resources - if (mac->generate_nr_prach == 1) - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); + if ((ra->RA_backoff_cnt > 0 && ra->generate_nr_prach == GENERATE_PREAMBLE) || ra->RA_backoff_cnt == 0) { + nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated); + } } } - } else if (UE_mode == PUSCH) { - LOG_D(MAC, "[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...", mod_id); - AssertFatal(1 == 0, ""); } - return mac->generate_nr_prach; + + if (ra->RA_contention_resolution_timer_active){ + nr_ue_contention_resolution(mod_id, CC_id, frame, nr_slot_tx, prach_resources); + } + + LOG_D(MAC,"ra->generate_nr_prach %d ra->ra_state %d (GENERATE_IDLE %d)\n",ra->generate_nr_prach,ra->ra_state,GENERATE_IDLE); + if(ra->generate_nr_prach != GENERATE_IDLE) { + return ra->generate_nr_prach; + } else { + return ra->ra_state; + } + } void nr_get_RA_window(NR_UE_MAC_INST_t *mac){ uint8_t mu, ra_ResponseWindow; - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + RA_config_t *ra = &mac->ra; + NR_RACH_ConfigCommon_t *setup; + if (mac->scc) setup = mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + else setup = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - + long scs = (mac->scc) ? + mac->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing : + mac->scc_SIB->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; if (setup->msg1_SubcarrierSpacing) mu = *setup->msg1_SubcarrierSpacing; else - mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + mu = scs; - mac->RA_window_cnt = mac->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB + ra->RA_window_cnt = ra->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB switch (ra_ResponseWindow) { case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: - mac->RA_window_cnt += 1; + ra->RA_window_cnt += 1; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: - mac->RA_window_cnt += 2; + ra->RA_window_cnt += 2; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: - mac->RA_window_cnt += 4; + ra->RA_window_cnt += 4; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: - mac->RA_window_cnt += 8; + ra->RA_window_cnt += 8; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: - mac->RA_window_cnt += 10; + ra->RA_window_cnt += 10; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: - mac->RA_window_cnt += 20; + ra->RA_window_cnt += 20; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: - mac->RA_window_cnt += 40; + ra->RA_window_cnt += 40; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: - mac->RA_window_cnt += 80; + ra->RA_window_cnt += 80; break; } } + +//////////////////////////////////////////////////////////////////////////// +/////////* Random Access Contention Resolution (5.1.35 TS 38.321) *///////// +//////////////////////////////////////////////////////////////////////////// +// Handling contention resolution timer +// WIP todo: +// - beam failure recovery +// - RA completed +void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + RA_config_t *ra = &mac->ra; + + if (ra->RA_contention_resolution_timer_active == 1) { + if (frame >= ra->RA_contention_resolution_target_frame && + slot >= ra->RA_contention_resolution_target_slot) { + ra->t_crnti = 0; + ra->RA_active = 0; + ra->RA_contention_resolution_timer_active = 0; + // Signal PHY to quit RA procedure + LOG_E(MAC, "[UE %d] CB-RA: Contention resolution timer has expired, RA procedure has failed...\n", module_id); + nr_ra_failed(module_id, cc_id, prach_resources, frame, slot); + } + } +} + +// Handlig successful RA completion @ MAC layer +// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16 +// todo: +// - complete handling of received contention-based RA preamble +void nr_ra_succeeded(module_id_t mod_id, frame_t frame, int slot){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + + if (ra->cfra) { + + LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CF-RA: RAR successfully received.\n", mod_id, frame, slot); + + ra->RA_window_cnt = -1; + + } else { + + LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CB-RA: Contention Resolution is successful.\n", mod_id, frame, slot); + + ra->RA_contention_resolution_timer_active = 0; + mac->crnti = ra->t_crnti; + ra->t_crnti = 0; + + LOG_D(MAC, "In %s: [UE %d][%d.%d] CB-RA: cleared contention resolution timer...\n", __FUNCTION__, mod_id, frame, slot); + + } + + LOG_D(MAC, "In %s: [UE %d] clearing RA_active flag...\n", __FUNCTION__, mod_id); + ra->RA_active = 0; + ra->generate_nr_prach = GENERATE_IDLE; + ra->ra_state = RA_SUCCEEDED; + +} + +// Handling failure of RA procedure @ MAC layer +// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16 +// todo: +// - complete handling of received contention-based RA preamble +void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot) { + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + // Random seed generation + long long tmp = rdtsc_oai(); + unsigned short int *seed = (unsigned short int*)&tmp; + + ra->first_Msg3 = 1; + ra->ra_PreambleIndex = -1; + ra->generate_nr_prach = RA_FAILED; + ra->ra_state = RA_UE_IDLE; + + prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER++; + + if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER == ra->preambleTransMax + 1){ + + LOG_D(MAC, "In %s: [UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n", + __FUNCTION__, mod_id, frame, slot, ra->preambleTransMax); + + ra->RA_backoff_cnt = nrand48(seed) % (prach_resources->RA_PREAMBLE_BACKOFF + 1); + prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += 2; // 2 dB increment + prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id); + + } else { + // Resetting RA window + nr_get_RA_window(mac); + } + +} diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 2285fc5999..ad82161fb9 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -38,6 +38,7 @@ #include "common/utils/nr/nr_common.h" #include "executables/softmodem-common.h" #include +#include "nfapi_nr_interface.h" #ifdef NR_PDCCH_DCI_TOOLS_DEBUG #define LOG_DCI_D(a...) printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) ->" a) @@ -46,104 +47,184 @@ #endif #define LOG_DCI_PARM(a...) LOG_D(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci)" a) -// #define DEBUG_DCI - -dci_pdu_rel15_t *def_dci_pdu_rel15; +//#define DEBUG_DCI void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) { - LOG_D(MAC,"Filling search candidates for DCI\n"); - - rel15->number_of_candidates=3; - rel15->CCE[0]=0; - rel15->L[0]=4; - rel15->CCE[1]=4; - rel15->L[1]=4; - rel15->CCE[2]=8; - rel15->L[2]=4; + LOG_D(NR_MAC,"Filling search candidates for DCI\n"); + uint8_t aggregation; + uint8_t number_of_candidates=0; + rel15->number_of_candidates=0; + int i=0; + for (int maxL=16;maxL>0;maxL>>=1) { + find_aggregation_candidates(&aggregation, + &number_of_candidates, + ss,maxL); + + if (number_of_candidates>0) { + LOG_D(NR_MAC,"L %d, number of candidates %d, aggregation %d\n",maxL,number_of_candidates,aggregation); + rel15->number_of_candidates += number_of_candidates; + for (int j=0; jCCE[i] = j*aggregation; + rel15->L[i] = aggregation; + } + } + } } -void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id, uint8_t dci_format){ +void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id){ - uint16_t monitoringSymbolsWithinSlot; - uint8_t bwp_id = 1, coreset_id = 1; - int sps; - def_dci_pdu_rel15 = calloc(1,sizeof(dci_pdu_rel15_t)); - AssertFatal(mac->scc != NULL, "scc is null\n"); + uint16_t monitoringSymbolsWithinSlot = 0; + int sps = 0; + + AssertFatal(mac->scc == NULL || mac->scc_SIB == NULL, "both scc and scc_SIB cannot be non-null\n"); + + NR_BWP_Id_t bwp_id = mac->DL_BWP_Id; NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_BWP_DownlinkCommon_t *bwp_Common = mac->DLbwp[bwp_id - 1]->bwp_Common; - NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; - NR_SearchSpace_t *ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id]; + NR_ServingCellConfigCommonSIB_t *scc_SIB = mac->scc_SIB; + NR_BWP_DownlinkCommon_t *bwp_Common=NULL; + NR_BWP_DownlinkCommon_t *initialDownlinkBWP=NULL; + NR_BWP_UplinkCommon_t *initialUplinkBWP=NULL; - // DCI format configuration - rel15->dci_format = dci_format; + if (scc!=NULL || scc_SIB != NULL) { + initialDownlinkBWP = scc!=NULL ? scc->downlinkConfigCommon->initialDownlinkBWP : &scc_SIB->downlinkConfigCommon.initialDownlinkBWP; + initialUplinkBWP = scc!=NULL ? scc->uplinkConfigCommon->initialUplinkBWP : &scc_SIB->uplinkConfigCommon->initialUplinkBWP; + } + bwp_Common = bwp_id>0 ? mac->DLbwp[bwp_id-1]->bwp_Common : NULL; + + NR_SearchSpace_t *ss; + NR_ControlResourceSet_t *coreset; + if(ss_id>=0) { + if (rnti_type == NR_RNTI_TC || rnti_type == NR_RNTI_RA) { + ss = mac->ra.ss; + AssertFatal(mac->ra.ss->searchSpaceId == ss_id,"Search Space id %d does not correspond to the one in ra->ss %ld for RA procedures\n", + ss_id,mac->ra.ss->searchSpaceId); + } + else + ss = mac->SSpace[bwp_id][ss_id]; + } + else + ss = mac->search_space_zero; + + uint8_t coreset_id = *ss->controlResourceSetId; + + if(coreset_id>0) { + coreset = mac->coreset[bwp_id][coreset_id - 1]; + rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; + } else { + coreset = mac->coreset0; + if(rnti_type == NR_RNTI_SI) { + rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; + } else { + rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG_CSET_0; + } + } - // CORESET configuration - NR_ControlResourceSet_t *coreset = mac->coreset[bwp_id - 1][coreset_id - 1]; rel15->coreset.duration = coreset->duration; + for (int i = 0; i < 6; i++) rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i]; - rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; + rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == + NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) { struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved; rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize); rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize); - AssertFatal(scc->physCellId != NULL, "mac->scc->physCellId is null\n"); - rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : *scc->physCellId; + rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : mac->physCellId; } else { rel15->coreset.RegBundleSize = 0; rel15->coreset.InterleaverSize = 0; rel15->coreset.ShiftIndex = 0; } - rel15->coreset.CoreSetType = 1; + rel15->coreset.precoder_granularity = coreset->precoderGranularity; // Scrambling RNTI if (coreset->pdcch_DMRS_ScramblingID) { rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID; - rel15->coreset.scrambling_rnti = mac->t_crnti; + rel15->coreset.scrambling_rnti = mac->crnti; } else { - rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId; + rel15->coreset.pdcch_dmrs_scrambling_id = mac->physCellId; rel15->coreset.scrambling_rnti = 0; } - #ifdef DEBUG_DCI - LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: ss_id %d bwp %p bwp_Id %d controlResourceSetId %d\n", ss_id, mac->DLbwp[bwp_id - 1], mac->DLbwp[bwp_id - 1]->bwp_Id, coreset->controlResourceSetId); - #endif - // loop over RNTI type and configure resource allocation for DCI switch(rnti_type) { case NR_RNTI_C: // we use DL BWP dedicated - sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; + sps = bwp_Common ? + (bwp_Common->genericParameters.cyclicPrefix ? 12 : 14) : + initialDownlinkBWP->genericParameters.cyclicPrefix ? 12 : 14; // for SPS=14 8 MSBs in positions 13 down to 6 monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); rel15->rnti = mac->crnti; - rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275); - rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); - rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing; - rel15->dci_length = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format, NR_RNTI_C, rel15->BWPSize, bwp_id); + if (!bwp_Common) { + rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + rel15->BWPStart = NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } + else { + rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing; + } + for (int i = 0; i < rel15->num_dci_options; i++) { + rel15->dci_length_options[i] = nr_dci_size(initialDownlinkBWP,initialUplinkBWP, mac->cg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[i]], rel15->dci_format_options[i], NR_RNTI_C, rel15->BWPSize, bwp_id); + } break; case NR_RNTI_RA: // we use the initial DL BWP sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12; monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - rel15->rnti = mac->ra_rnti; - rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); - rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); //NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); + rel15->rnti = mac->ra.ra_rnti; + if (get_softmodem_params()->sa) { + rel15->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs; + rel15->BWPStart = mac->type0_PDCCH_CSS_config.cset_start_rb; + } else { // NSA mode is not using the Initial BWP + rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; - rel15->dci_length = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format, NR_RNTI_RA, rel15->BWPSize, bwp_id); + rel15->dci_length_options[0] = nr_dci_size(initialDownlinkBWP,initialUplinkBWP, mac->cg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[0]], rel15->dci_format_options[0], NR_RNTI_RA, rel15->BWPSize, bwp_id); break; case NR_RNTI_P: break; case NR_RNTI_CS: break; case NR_RNTI_TC: + // we use the initial DL BWP + sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12; + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = mac->ra.t_crnti; + rel15->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs; + rel15->BWPStart = mac->type0_PDCCH_CSS_config.cset_start_rb; + rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; + for (int i = 0; i < rel15->num_dci_options; i++) { + rel15->dci_length_options[i] = nr_dci_size(initialDownlinkBWP,initialUplinkBWP, mac->cg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[i]], rel15->dci_format_options[i], NR_RNTI_TC, rel15->BWPSize, bwp_id); + } break; case NR_RNTI_SP_CSI: break; case NR_RNTI_SI: + // we use DL BWP dedicated + if (bwp_Common) sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; + else sps=14; // note: normally this would be found with SSS detection + + // for SPS=14 8 MSBs in positions 13 down to 6 + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + + rel15->rnti = SI_RNTI; // SI-RNTI - 3GPP TS 38.321 Table 7.1-1: RNTI values + rel15->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs; + rel15->BWPStart = mac->type0_PDCCH_CSS_config.cset_start_rb; + + if(mac->frequency_range == FR1) + rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon; + else + rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2; + + for (int i = 0; i < rel15->num_dci_options; i++) { + rel15->dci_length_options[i] = nr_dci_size(initialDownlinkBWP,initialUplinkBWP, mac->cg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[i]], rel15->dci_format_options[i], NR_RNTI_SI, rel15->BWPSize, 0); + } break; case NR_RNTI_SFI: break; @@ -170,155 +251,206 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t rel15->BWPSize, rel15->BWPStart, rel15->SubcarrierSpacing, - rel15->dci_format, - rel15->dci_length, + rel15->dci_format_options[0], + rel15->dci_length_options[0], sps, monitoringSymbolsWithinSlot); #endif // add DCI dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - dl_config->number_pdus = dl_config->number_pdus + 1; + dl_config->number_pdus += 1; } void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, frame_t frame, int slot) { + RA_config_t *ra = &mac->ra; int ss_id; - uint8_t bwp_id = 1, coreset_id = 1; - NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; - NR_BWP_Downlink_t *bwp = mac->DLbwp[bwp_id - 1]; - #ifdef DEBUG_DCI - LOG_D(MAC, "[DCI_CONFIG] ra_rnti %p (%x) crnti %p (%x) t_crnti %p (%x)\n", &mac->ra_rnti, mac->ra_rnti, &mac->crnti, mac->crnti, &mac->t_crnti, mac->t_crnti); - #endif + uint8_t bwp_id = (mac->cg) ? mac->DL_BWP_Id : 0; + //NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; + NR_BWP_DownlinkDedicated_t *bwpd = (bwp_id>0) ? mac->DLbwp[bwp_id-1]->bwp_Dedicated : mac->cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP; + NR_BWP_DownlinkCommon_t *bwp_Common = (bwp_id>0) ? mac->DLbwp[bwp_id-1]->bwp_Common : &mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP; - // loop over all available SS for BWP ID 1, CORESET ID 1 - for (ss_id = 0; ss_id < FAPI_NR_MAX_SS_PER_CORESET && mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id] != NULL; ss_id++){ - NR_SearchSpace_t *ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id]; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; - NR_BWP_DownlinkCommon_t *bwp_Common = bwp->bwp_Common; - NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; - struct NR_PhysicalCellGroupConfig *phy_cgc = mac->scg->physicalCellGroupConfig; - switch (ss->searchSpaceType->present){ - case NR_SearchSpace__searchSpaceType_PR_common: - // this is for CSSs, we use BWP common and pdcch_ConfigCommon + LOG_D(NR_MAC, "[DCI_CONFIG] ra_rnti %p (%x) crnti %p (%x) t_crnti %p (%x)\n", &ra->ra_rnti, ra->ra_rnti, &mac->crnti, mac->crnti, &ra->t_crnti, ra->t_crnti); - // Fetch configuration for searchSpaceZero - // note: The search space with the SearchSpaceId = 0 identifies the search space configured via PBCH (MIB) and in ServingCellConfigCommon (searchSpaceZero). - if (pdcch_ConfigCommon->choice.setup->searchSpaceZero){ - LOG_D(MAC, "[DCI_CONFIG] Configure SearchSpace#0 of the initial BWP\n"); - LOG_W(MAC, "[DCI_CONFIG] This should not be available yet..."); - } - if (ss->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0){ - // check available SS IDs - if (pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ - if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type1-PDCCH common random access search space\n"); - switch(mac->ra_state){ - case WAIT_RAR: - config_dci_pdu(mac, rel15, dl_config, NR_RNTI_RA, ss_id, NR_DL_DCI_FORMAT_1_0); - fill_dci_search_candidates(ss, rel15); - break; - case WAIT_CONTENTION_RESOLUTION: - rel15->rnti = mac->t_crnti; - break; - default: - break; - } - } - } - if (pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ - if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ - // Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG - LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); - } - } - if (pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){ - if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){ - // Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG - LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); - } - } - if (pdcch_ConfigCommon->choice.setup->pagingSearchSpace){ - if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->pagingSearchSpace){ - // Configure monitoring of PDCCH candidates in Type2-PDCCH common search space on the MCG - LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); - } - } - if (phy_cgc){ - if (phy_cgc->cs_RNTI){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n"); - LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); - } - if (phy_cgc->ext1){ - if (phy_cgc->ext1->mcs_C_RNTI){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n"); - LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); - } - } - } - } // end DCI 00 and 01 - // DCI 2_0 - if (ss->searchSpaceType->choice.common->dci_Format2_0){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_0 with CRC scrambled by SFI-RNTI \n"); - LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); - } - // DCI 2_1 - if (ss->searchSpaceType->choice.common->dci_Format2_1){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_1 with CRC scrambled by INT-RNTI \n"); - LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); - } - // DCI 2_2 - if (ss->searchSpaceType->choice.common->dci_Format2_2){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_2 with CRC scrambled by TPC-RNTI \n"); - LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); - } - // DCI 2_3 - if (ss->searchSpaceType->choice.common->dci_Format2_3){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_3 with CRC scrambled by TPC-SRS-RNTI \n"); - LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); - } + // loop over all available SS for CORESET ID 1 + if (bwpd) { + for (ss_id = 0; ss_id < FAPI_NR_MAX_SS && mac->SSpace[bwp_id][ss_id] != NULL; ss_id++){ + LOG_D(NR_MAC, "[DCI_CONFIG] ss_id %d\n",ss_id); + NR_SearchSpace_t *ss = mac->SSpace[bwp_id][ss_id]; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; + struct NR_PhysicalCellGroupConfig *phy_cgc = mac->cg->physicalCellGroupConfig; + switch (ss->searchSpaceType->present){ + case NR_SearchSpace__searchSpaceType_PR_common: + // this is for CSSs, we use BWP common and pdcch_ConfigCommon - break; - case NR_SearchSpace__searchSpaceType_PR_ue_Specific: - // this is an USS - if (ss->searchSpaceType->choice.ue_Specific){ - if(ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_1_And_1_1){ - // Monitors DCI 01 and 11 scrambled with C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI - if (get_softmodem_params()->phy_test == 1 && mac->crnti > 0) { - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in the user specific search space\n"); - config_dci_pdu(mac, rel15, dl_config, NR_RNTI_C, ss_id, NR_DL_DCI_FORMAT_1_1); + // Fetch configuration for searchSpaceZero + // note: The search space with the SearchSpaceId = 0 identifies the search space configured via PBCH (MIB) and in ServingCellConfigCommon (searchSpaceZero). + if (pdcch_ConfigCommon->choice.setup->searchSpaceZero){ + if (pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 == NULL){ + pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=calloc(1,sizeof(*pdcch_ConfigCommon->choice.setup->searchSpaceSIB1)); + } + *pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = 0; + LOG_D(NR_MAC, "[DCI_CONFIG] Configure SearchSpace#0 of the initial BWP\n"); + } + if (ss->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0){ + // check available SS IDs + if (pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ + switch(ra->ra_state){ + case WAIT_RAR: + LOG_D(NR_MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type1-PDCCH common random access search space (RA-Msg2)\n"); + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + if (get_softmodem_params()->sa) { + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_RA, -1); + } else { + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_RA, ss_id); + } + fill_dci_search_candidates(ss, rel15); + break; + case WAIT_CONTENTION_RESOLUTION: + LOG_D(NR_MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type1-PDCCH common random access search space (RA-Msg4)\n"); + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_TC, -1); + fill_dci_search_candidates(ss, rel15); + break; + default: + break; + } + } + } + if (pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ + // Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG + //LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){ + // Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG + //LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (pdcch_ConfigCommon->choice.setup->pagingSearchSpace){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->pagingSearchSpace){ + // Configure monitoring of PDCCH candidates in Type2-PDCCH common search space on the MCG + //LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (phy_cgc){ + if (phy_cgc->cs_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet...\n"); + } + if (phy_cgc->ext1){ + if (phy_cgc->ext1->mcs_C_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet...\n"); + } + } + } + } // end DCI 00 and 01 + // DCI 2_0 + if (ss->searchSpaceType->choice.common->dci_Format2_0){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_0 with CRC scrambled by SFI-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet...\n"); + } + // DCI 2_1 + if (ss->searchSpaceType->choice.common->dci_Format2_1){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_1 with CRC scrambled by INT-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet...\n"); + } + // DCI 2_2 + if (ss->searchSpaceType->choice.common->dci_Format2_2){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_2 with CRC scrambled by TPC-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet...\n"); + } + // DCI 2_3 + if (ss->searchSpaceType->choice.common->dci_Format2_3){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_3 with CRC scrambled by TPC-SRS-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet...\n"); + } + + break; + case NR_SearchSpace__searchSpaceType_PR_ue_Specific: + // this is an USS + if (ss->searchSpaceType->choice.ue_Specific && + ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_1_And_1_1 && + (ra->ra_state == RA_SUCCEEDED || get_softmodem_params()->phy_test) && + mac->crnti > 0) { + // Monitors DCI 01 and 11 scrambled with C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI + LOG_D(NR_MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in the user specific search space\n"); + rel15->num_dci_options = 2; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_1; + rel15->dci_format_options[1] = NR_UL_DCI_FORMAT_0_1; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_C, ss_id); fill_dci_search_candidates(ss, rel15); - #ifdef DEBUG_DCI - LOG_D(MAC, "[DCI_CONFIG] ss %d ue_Specific %p searchSpaceType->present %d dci_Formats %d\n", - ss_id, - ss->searchSpaceType->choice.ue_Specific, - ss->searchSpaceType->present, - ss->searchSpaceType->choice.ue_Specific->dci_Formats); - #endif - } - if (phy_cgc){ +//#ifdef DEBUG_DCI + LOG_D(NR_MAC, "[DCI_CONFIG] ss %d ue_Specific %p searchSpaceType->present %d dci_Formats %d\n", + ss_id, + ss->searchSpaceType->choice.ue_Specific, + (int)ss->searchSpaceType->present, + (int)ss->searchSpaceType->choice.ue_Specific->dci_Formats); +//#endif + } + if (phy_cgc){ if (phy_cgc->cs_RNTI){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n"); - LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); } if (phy_cgc->sp_CSI_RNTI){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by SP-CSI-RNTI...\n"); - LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by SP-CSI-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); } - if (phy_cgc->ext1){ - if (phy_cgc->ext1->mcs_C_RNTI){ - LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n"); - LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); - } + if (phy_cgc->ext1 && + phy_cgc->ext1->mcs_C_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); } - } - } + } + break; + default: + AssertFatal(1 == 0, "[DCI_CONFIG] Unrecognized search space type..."); + break; + } // switch searchspace + } // for ss_id + } + else { + + AssertFatal(1==0,"Handle DCI searching when CellGroup without dedicated BWP\n"); + } + // Search space 0, CORESET ID 0 + + NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; + + if (pdcch_ConfigCommon && + pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ + + NR_SearchSpace_t *ss0 = mac->search_space_zero; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + + if (ss0->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ + if( (frame%2 == mac->type0_PDCCH_CSS_config.sfn_c) && (slot == mac->type0_PDCCH_CSS_config.n_0) ){ + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); + fill_dci_search_candidates(ss0, rel15); } - break; - default: - AssertFatal(1 == 0, "[DCI_CONFIG] Unrecognized search space type..."); - break; + } + } + else { // use coreset0/ss0 + NR_SearchSpace_t *ss0 = mac->search_space_zero; + if(ss0) { + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15; + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_C , -1); + fill_dci_search_candidates(ss0, rel15); + dl_config->number_pdus = 1; } } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 60f331a086..2f4ceb48ec 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -45,214 +45,246 @@ #include "NR_PDCCH-ConfigCommon.h" /* MAC */ -#include "mac_defs.h" #include "NR_MAC_COMMON/nr_mac.h" #include "NR_MAC_UE/mac_proto.h" #include "NR_MAC_UE/mac_extern.h" +#include "NR_MAC_COMMON/nr_mac_extern.h" #include "common/utils/nr/nr_common.h" -/* PHY UE */ -#include "SCHED_NR_UE/defs.h" -#include "PHY/defs_nr_UE.h" - -/*Openair Packet Tracer */ -#include "UTIL/OPT/opt.h" -#include "OCG.h" +/* PHY */ +#include "PHY/NR_TRANSPORT/nr_dci.h" #include "executables/softmodem-common.h" /* utils */ #include "assertions.h" - +#include "asn1_conversions.h" #include "common/utils/LOG/log.h" -#include "SIMULATION/TOOLS/sim.h" // for taus -#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include -#include - +//#define DEBUG_MIB //#define ENABLE_MAC_PAYLOAD_DEBUG 1 -#define DEBUG_EXTRACT_DCI 1 +//#define DEBUG_EXTRACT_DCI +//#define DEBUG_RAR -extern int bwp_id; -extern dci_pdu_rel15_t *def_dci_pdu_rel15; -extern const uint16_t nr_slots_per_frame[5]; +extern uint32_t N_RB_DL; -extern void mac_rlc_data_ind ( - const module_id_t module_idP, - const rnti_t rntiP, - const eNB_index_t eNB_index, - const frame_t frameP, - const eNB_flag_t enb_flagP, - const MBMS_flag_t MBMS_flagP, - const logical_chan_id_t channel_idP, - char *buffer_pP, - const tb_size_t tb_sizeP, - num_tb_t num_tbP, - crc_t *crcs_pP); +/* TS 38.213 9.2.5.2 UE procedure for multiplexing HARQ-ACK/SR and CSI in a PUCCH */ +/* this is a counter of number of pucch format 4 per subframe */ +static int nb_pucch_format_4_in_subframes[LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] = { 0 } ; + +/* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */ +static const int sequence_cyclic_shift_1_harq_ack_bit[2] +/* HARQ-ACK Value 0 1 */ +/* Sequence cyclic shift */ = { 0, 6 }; + +/* TS 36.213 Table 9.2.5-1: Mapping of values for one HARQ-ACK bit and positive SR to sequences */ +static const int sequence_cyclic_shift_1_harq_ack_bit_positive_sr[2] +/* HARQ-ACK Value 0 1 */ +/* Sequence cyclic shift */ = { 3, 9 }; + +/* TS 36.213 Table 9.2.5-2: Mapping of values for two HARQ-ACK bits and positive SR to sequences */ +static const int sequence_cyclic_shift_2_harq_ack_bits_positive_sr[4] +/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */ +/* Sequence cyclic shift */ = { 1, 4, 10, 7 }; + +/* TS 38.213 Table 9.2.3-4: Mapping of values for two HARQ-ACK bits to sequences */ +static const int sequence_cyclic_shift_2_harq_ack_bits[4] +/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */ +/* Sequence cyclic shift */ = { 0, 3, 9, 6 }; -uint32_t get_ssb_slot(uint32_t ssb_index){ - // this function now only support f <= 3GHz - return ssb_index & 0x3 ; +/* TS 38.211 Table 6.4.1.3.3.2-1: DM-RS positions for PUCCH format 3 and 4 */ +static const int nb_symbols_excluding_dmrs[11][2][2] += { +/* No additional DMRS Additional DMRS */ +/* PUCCH length No hopping hopping No hopping hopping */ +/* index 0 1 0 1 */ +/* 4 */ {{ 3 , 2 } , { 3 , 2 }}, +/* 5 */ {{ 3 , 3 } , { 3 , 3 }}, +/* 6 */ {{ 4 , 4 } , { 4 , 4 }}, +/* 7 */ {{ 5 , 5 } , { 5 , 5 }}, +/* 8 */ {{ 6 , 6 } , { 6 , 6 }}, +/* 9 */ {{ 7 , 7 } , { 7 , 7 }}, +/* 10 */ {{ 8 , 8 } , { 6 , 6 }}, +/* 11 */ {{ 9 , 9 } , { 7 , 7 }}, +/* 12 */ {{ 10 , 10 } , { 8 , 8 }}, +/* 13 */ {{ 11 , 11 } , { 9 , 9 }}, +/* 14 */ {{ 12 , 12 } , { 10 , 10 }}, +}; - // return first_symbol(case, freq, ssb_index) / 14 -} - -uint8_t table_9_2_2_1[16][8]={ - {0,12,2, 0, 0,3,0,0}, - {0,12,2, 0, 0,4,8,0}, - {0,12,2, 3, 0,4,8,0}, - {1,10,4, 0, 0,6,0,0}, - {1,10,4, 0, 0,3,6,9}, - {1,10,4, 2, 0,3,6,9}, - {1,10,4, 4, 0,3,6,9}, - {1,4, 10,0, 0,6,0,0}, - {1,4, 10,0, 0,3,6,9}, - {1,4, 10,2, 0,3,6,9}, - {1,4, 10,4, 0,3,6,9}, - {1,0, 14,0, 0,6,0,0}, - {1,0, 14,0, 0,3,6,9}, - {1,0, 14,2, 0,3,6,9}, - {1,0, 14,4, 0,3,6,9}, - {1,0, 14,26,0,3,0,0} +/* TS 36.213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */ +const initial_pucch_resource_t initial_pucch_resource[16] = { +/* format first symbol Number of symbols PRB offset nb index for set of initial CS */ +/* 0 */ { 0, 12, 2, 0, 2, { 0, 3, 0, 0 } }, +/* 1 */ { 0, 12, 2, 0, 3, { 0, 4, 8, 0 } }, +/* 2 */ { 0, 12, 2, 3, 3, { 0, 4, 8, 0 } }, +/* 3 */ { 1, 10, 4, 0, 2, { 0, 6, 0, 0 } }, +/* 4 */ { 1, 10, 4, 0, 4, { 0, 3, 6, 9 } }, +/* 5 */ { 1, 10, 4, 2, 4, { 0, 3, 6, 9 } }, +/* 6 */ { 1, 10, 4, 4, 4, { 0, 3, 6, 9 } }, +/* 7 */ { 1, 4, 10, 0, 2, { 0, 6, 0, 0 } }, +/* 8 */ { 1, 4, 10, 0, 4, { 0, 3, 6, 9 } }, +/* 9 */ { 1, 4, 10, 2, 4, { 0, 3, 6, 9 } }, +/* 10 */ { 1, 4, 10, 4, 4, { 0, 3, 6, 9 } }, +/* 11 */ { 1, 0, 14, 0, 2, { 0, 6, 0, 0 } }, +/* 12 */ { 1, 0, 14, 0, 4, { 0, 3, 6, 9 } }, +/* 13 */ { 1, 0, 14, 2, 4, { 0, 3, 6, 9 } }, +/* 14 */ { 1, 0, 14, 4, 4, { 0, 3, 6, 9 } }, +/* 15 */ { 1, 0, 14, 0, 4, { 0, 3, 6, 9 } }, }; -int8_t nr_ue_process_dlsch(module_id_t module_id, - int cc_id, - uint8_t gNB_index, - fapi_nr_dci_indication_t *dci_ind, - void *pduP, - uint32_t pdu_len) -{ - NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; - //fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - nr_phy_config_t *phy_config = &mac->phy_config; +void nr_ue_init_mac(module_id_t module_idP) { + int i; - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rnti = rnti; - // First we need to verify if DCI ind contains a ul-sch to be perfomred. If it does, we will handle a PUSCH in the UL_CONFIG_REQ. - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUCCH; - for (int i=0; i<10; i++) { - if(dci_ind!=NULL){ - if (dci_ind->dci_list[i].dci_format < 2) ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - } - } - if (ul_config->ul_config_list[ul_config->number_pdus].pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) { - // fill in the elements in config request inside P5 message - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.bandwidth_part_ind = 0; //FIXME - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rb_size = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rb_start = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.nr_of_symbols = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.start_symbol_index = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.frequency_hopping = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.mcs_index = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.pusch_data.new_data_indicator = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.pusch_data.rv_index = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.pusch_data.harq_process_id = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.absolute_delta_PUSCH = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.nrOfLayers = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.transform_precoding = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.dmrs_ports = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.dmrs_config_type = 0; - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.n_front_load_symb = 0; //FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.srs_config = 0; //FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.csi_reportTriggerSize = 0; //FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.maxCodeBlockGroupsPerTransportBlock = 0; //FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.ptrs_dmrs_association_port = 0; FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.beta_offset_ind = 0; //FIXME - } else { // If DCI ind is not format 0_0 or 0_1, we will handle a PUCCH in the UL_CONFIG_REQ - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUCCH; - // If we handle PUCCH common - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.format = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][0]; /* format 0 1 2 3 4 */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.initialCyclicShift = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][4]; /* x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSymbols = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][2]; /* x x x x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.startingSymbolIndex = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][1]; /* x x x x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.timeDomainOCC = 0; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofPRBs = 0; /* x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.startingPRB = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][3]; /* maxNrofPhysicalResourceBlocks = 275 */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.occ_length = 0; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.occ_Index = 0; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.intraSlotFrequencyHopping = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.secondHopPRB = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pucch_GroupHopping = phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_group_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.hoppingId = phy_config->config_req.ul_bwp_common.pucch_config_common.hopping_id; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_nominal = phy_config->config_req.ul_bwp_common.pucch_config_common.p0_nominal; - for (int i=0;iul_config_list[ul_config->number_pdus].pucch_config_pdu.deltaF_PUCCH_f[i] = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_PUCCH_Id = 0; /* INTEGER (1..8) */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_PUCCH_Value = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.twoPUCCH_PC_AdjustmentStates = 0; - // If we handle PUCCH dedicated - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.format = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].format; /* format 0 1 2 3 4 */ - switch (ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.format){ - case pucch_format1_nr: - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.inter_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.additional_dmrs; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.max_code_rate; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.number_of_slots; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.pi2bpsk; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.simultaneous_harq_ack_csi; - break; - case pucch_format2_nr: - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.inter_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.additional_dmrs; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.max_code_rate; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.number_of_slots; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.pi2bpsk; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.simultaneous_harq_ack_csi; - break; - case pucch_format3_nr: - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.inter_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.additional_dmrs; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.max_code_rate; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.number_of_slots; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.pi2bpsk; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.simultaneous_harq_ack_csi; - break; - case pucch_format4_nr: - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.inter_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.additional_dmrs; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.max_code_rate; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.number_of_slots; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.pi2bpsk; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.simultaneous_harq_ack_csi; - break; - default: - break; - } - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.initialCyclicShift = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].initial_cyclic_shift; /* x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSymbols = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].number_of_symbols; /* x x x x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.startingSymbolIndex = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].starting_symbol_index; /* x x x x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.timeDomainOCC = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].time_domain_occ; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofPRBs = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].number_of_prbs; /* x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.startingPRB = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].starting_prb; /* maxNrofPhysicalResourceBlocks = 275 */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.occ_length = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].occ_length; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.occ_Index = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].occ_index; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.intraSlotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].intra_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.secondHopPRB = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].second_hop_prb; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pucch_GroupHopping = phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_group_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.hoppingId = phy_config->config_req.ul_bwp_common.pucch_config_common.hopping_id; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_nominal = phy_config->config_req.ul_bwp_common.pucch_config_common.p0_nominal; - for (int i=0;iul_config_list[ul_config->number_pdus].pucch_config_pdu.deltaF_PUCCH_f[i] = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_PUCCH_Id = 0; /* INTEGER (1..8) */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_PUCCH_Value = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.twoPUCCH_PC_AdjustmentStates = 0; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + // default values as deined in 38.331 sec 9.2.2 + LOG_I(NR_MAC, "[UE%d] Applying default macMainConfig\n", module_idP); + //mac->scheduling_info.macConfig=NULL; + mac->scheduling_info.retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf10240; + mac->scheduling_info.periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_infinity; +// mac->scheduling_info.periodicPHR_Timer = NR_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; +// mac->scheduling_info.prohibitPHR_Timer = NR_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; +// mac->scheduling_info.PathlossChange_db = NR_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1; +// mac->PHR_state = NR_MAC_MainConfig__phr_Config_PR_setup; + mac->scheduling_info.SR_COUNTER = 0; + mac->scheduling_info.sr_ProhibitTimer = 0; + mac->scheduling_info.sr_ProhibitTimer_Running = 0; +// mac->scheduling_info.maxHARQ_Tx = NR_MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5; +// mac->scheduling_info.ttiBundling = 0; +// mac->scheduling_info.extendedBSR_Sizes_r10 = 0; +// mac->scheduling_info.extendedPHR_r10 = 0; +// mac->scheduling_info.drx_config = NULL; +// mac->scheduling_info.phr_config = NULL; + // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value configured by the NW. + mac->scheduling_info.periodicBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING; + mac->scheduling_info.retxBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING; + mac->BSR_reporting_active = BSR_TRIGGER_NONE; +// mac->scheduling_info.periodicPHR_SF = nr_get_sf_perioidicPHR_Timer(mac->scheduling_info.periodicPHR_Timer); +// mac->scheduling_info.prohibitPHR_SF = nr_get_sf_prohibitPHR_Timer(mac->scheduling_info.prohibitPHR_Timer); +// mac->scheduling_info.PathlossChange_db = nr_get_db_dl_PathlossChange(mac->scheduling_info.PathlossChange); +// mac->PHR_reporting_active = 0; + for (i = 0; i < NR_MAX_NUM_LCID; i++) { + LOG_D(NR_MAC, "[UE%d] Applying default logical channel config for LCGID %d\n", + module_idP, i); + mac->scheduling_info.Bj[i] = -1; + mac->scheduling_info.bucket_size[i] = -1; + + if (i < UL_SCH_LCID_DTCH) { // initialize all control channels lcgid to 0 + mac->scheduling_info.LCGID[i] = 0; + } else { // initialize all the data channels lcgid to 1 + mac->scheduling_info.LCGID[i] = 1; + } + + mac->scheduling_info.LCID_status[i] = LCID_EMPTY; + mac->scheduling_info.LCID_buffer_remain[i] = 0; + for (int i=0;ifirst_ul_tx[i]=1; } - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&mac->scheduled_response); - } - return 0; } +void get_bwp_info(NR_UE_MAC_INST_t *mac, + int dl_bwp_id, + int ul_bwp_id, + NR_BWP_DownlinkDedicated_t **bwpd, + NR_BWP_DownlinkCommon_t **bwpc, + NR_BWP_UplinkDedicated_t **ubwpd, + NR_BWP_UplinkCommon_t **ubwpc) { + + if (dl_bwp_id > 0) { + AssertFatal(mac->DLbwp[dl_bwp_id-1]!=NULL,"mac->DLbwp[%d] is null, shouldn't be\n", + (int)dl_bwp_id-1); + *bwpd = mac->DLbwp[dl_bwp_id-1]->bwp_Dedicated; + if (mac->DLbwp[dl_bwp_id-1]->bwp_Common) *bwpc = mac->DLbwp[dl_bwp_id-1]->bwp_Common; + else if (mac->scc_SIB) *bwpc = &mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP; + else if (mac->scc) *bwpc = mac->scc->downlinkConfigCommon->initialDownlinkBWP; + AssertFatal(*bwpc!=NULL,"bwpc shouldn't be null\n"); + } else { + if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP) + *bwpd = mac->cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP; + if (mac->scc_SIB) *bwpc = &mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP; + else if (mac->scc) *bwpc = mac->scc->downlinkConfigCommon->initialDownlinkBWP; + AssertFatal(*bwpc!=NULL,"bwpc shouldn't be null\n"); + } + + if (ul_bwp_id > 0) { + AssertFatal(mac->ULbwp[ul_bwp_id-1]!=NULL,"mac->ULbwp[%d] is null, shouldn't be\n", + ul_bwp_id-1); + *ubwpd = mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated; + if (mac->ULbwp[ul_bwp_id-1]->bwp_Common) *ubwpc = mac->ULbwp[ul_bwp_id-1]->bwp_Common; + else if (mac->scc_SIB) *ubwpc = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + else if (mac->scc) *ubwpc = mac->scc->uplinkConfigCommon->initialUplinkBWP; + AssertFatal(*bwpc!=NULL,"bwpc shouldn't be null\n"); + + } + else { + if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) + *ubwpd = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; + if (mac->scc_SIB) *ubwpc = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + else if (mac->scc) *ubwpc = mac->scc->uplinkConfigCommon->initialUplinkBWP; + AssertFatal(*ubwpc!=NULL,"ubwpc shouldn't be null\n"); + } +} + +NR_PDSCH_TimeDomainResourceAllocationList_t *choose_dl_tda_list(NR_PDSCH_Config_t *pdsch_Config,NR_PDSCH_ConfigCommon_t *pdsch_ConfigCommon) { + + NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList=NULL; + + if (pdsch_Config && + pdsch_Config->pdsch_TimeDomainAllocationList) + pdsch_TimeDomainAllocationList = pdsch_Config->pdsch_TimeDomainAllocationList->choice.setup; + else if (pdsch_ConfigCommon->pdsch_TimeDomainAllocationList) + pdsch_TimeDomainAllocationList = pdsch_ConfigCommon->pdsch_TimeDomainAllocationList; + + return(pdsch_TimeDomainAllocationList); +} + +NR_PUSCH_TimeDomainResourceAllocationList_t *choose_ul_tda_list(NR_PUSCH_Config_t *pusch_Config,NR_PUSCH_ConfigCommon_t *pusch_ConfigCommon) { + + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList=NULL; + + if (pusch_Config && + pusch_Config->pusch_TimeDomainAllocationList) + pusch_TimeDomainAllocationList = pusch_Config->pusch_TimeDomainAllocationList->choice.setup; + else if (pusch_ConfigCommon->pusch_TimeDomainAllocationList) + pusch_TimeDomainAllocationList = pusch_ConfigCommon->pusch_TimeDomainAllocationList; + + return(pusch_TimeDomainAllocationList); +} + +int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti){ + + RA_config_t *ra = &mac->ra; + int rnti_type; + + if (rnti == ra->ra_rnti) { + rnti_type = NR_RNTI_RA; + } else if (rnti == ra->t_crnti && (ra->ra_state == WAIT_RAR || ra->ra_state == WAIT_CONTENTION_RESOLUTION) ) { + rnti_type = NR_RNTI_TC; + } else if (rnti == mac->crnti) { + rnti_type = NR_RNTI_C; + } else if (rnti == 0xFFFE) { + rnti_type = NR_RNTI_P; + } else if (rnti == 0xFFFF) { + rnti_type = NR_RNTI_SI; + } else { + AssertFatal(1 == 0, "In %s: Not identified/handled rnti %d \n", __FUNCTION__, rnti); + } + + LOG_D(MAC, "In %s: returning rnti_type %s \n", __FUNCTION__, rnti_types[rnti_type]); + + return rnti_type; + +} + + int8_t nr_ue_decode_mib(module_id_t module_id, int cc_id, uint8_t gNB_index, @@ -260,1800 +292,116 @@ int8_t nr_ue_decode_mib(module_id_t module_id, uint32_t ssb_length, uint32_t ssb_index, void *pduP, + uint16_t ssb_start_subcarrier, uint16_t cell_id) { - LOG_I(MAC,"[L2][MAC] decode mib\n"); + LOG_D(MAC,"[L2][MAC] decode mib\n"); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + mac->physCellId = cell_id; - nr_mac_rrc_data_ind_ue( module_id, cc_id, gNB_index, NR_BCCH_BCH, (uint8_t *) pduP, 3 ); // fixed 3 bytes MIB PDU + nr_mac_rrc_data_ind_ue( module_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_BCH, (uint8_t *) pduP, 3 ); // fixed 3 bytes MIB PDU AssertFatal(mac->mib != NULL, "nr_ue_decode_mib() mac->mib == NULL\n"); //if(mac->mib != NULL){ uint16_t frame = (mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused); uint16_t frame_number_4lsb = 0; + for (int i=0; i<4; i++) frame_number_4lsb |= ((extra_bits>>i)&1)<<(3-i); - //uint8_t half_frame_bit = ( extra_bits >> 4 ) & 0x1; // extra bits[4] + uint8_t ssb_subcarrier_offset_msb = ( extra_bits >> 5 ) & 0x1; // extra bits[5] uint8_t ssb_subcarrier_offset = (uint8_t)mac->mib->ssb_SubcarrierOffset; - //uint32_t ssb_index = 0; // TODO: ssb_index should obtain from L1 in case Lssb != 64 - frame = frame << 4; frame = frame | frame_number_4lsb; - if(ssb_length == 64){ - ssb_index = ssb_index & (( extra_bits >> 2 ) & 0x1C ); // { extra_bits[5:7], ssb_index[2:0] } + mac->frequency_range = FR2; + for (int i=0; i<3; i++) + ssb_index += (((extra_bits>>(7-i))&0x01)<<(3+i)); }else{ + mac->frequency_range = FR1; if(ssb_subcarrier_offset_msb){ ssb_subcarrier_offset = ssb_subcarrier_offset | 0x10; } } #ifdef DEBUG_MIB + uint8_t half_frame_bit = ( extra_bits >> 4 ) & 0x1; // extra bits[4] LOG_I(MAC,"system frame number(6 MSB bits): %d\n", mac->mib->systemFrameNumber.buf[0]); LOG_I(MAC,"system frame number(with LSB): %d\n", (int)frame); LOG_I(MAC,"subcarrier spacing (0=15or60, 1=30or120): %d\n", (int)mac->mib->subCarrierSpacingCommon); LOG_I(MAC,"ssb carrier offset(with MSB): %d\n", (int)ssb_subcarrier_offset); LOG_I(MAC,"dmrs type A position (0=pos2,1=pos3): %d\n", (int)mac->mib->dmrs_TypeA_Position); - LOG_I(MAC,"pdcch config sib1: %d\n", (int)mac->mib->pdcch_ConfigSIB1); + LOG_I(MAC,"controlResourceSetZero: %d\n", (int)mac->mib->pdcch_ConfigSIB1.controlResourceSetZero); + LOG_I(MAC,"searchSpaceZero: %d\n", (int)mac->mib->pdcch_ConfigSIB1.searchSpaceZero); LOG_I(MAC,"cell barred (0=barred,1=notBarred): %d\n", (int)mac->mib->cellBarred); LOG_I(MAC,"intra frequency reselection (0=allowed,1=notAllowed): %d\n", (int)mac->mib->intraFreqReselection); LOG_I(MAC,"half frame bit(extra bits): %d\n", (int)half_frame_bit); LOG_I(MAC,"ssb index(extra bits): %d\n", (int)ssb_index); #endif - subcarrier_spacing_t scs_ssb = scs_30kHz; // default for - //const uint32_t scs_index = 0; - const uint32_t num_slot_per_frame = 20; - subcarrier_spacing_t scs_pdcch; + //storing ssb index in the mac structure + mac->mib_ssb = ssb_index; + mac->ssb_subcarrier_offset = ssb_subcarrier_offset; - // assume carrier frequency < 6GHz - if(mac->mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60){ - scs_pdcch = scs_15kHz; - }else{ //NR_MIB__subCarrierSpacingCommon_scs30or120 - scs_pdcch = scs_30kHz; + uint8_t scs_ssb; + uint32_t band; + uint16_t ssb_start_symbol; + + if (get_softmodem_params()->sa == 1) { + + scs_ssb = get_softmodem_params()->numerology; + band = mac->nr_band; + ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); + + if (mac->common_configuration_complete == 0) + nr_ue_sib1_scheduler(module_id, + cc_id, + ssb_start_symbol, + frame, + ssb_subcarrier_offset, + ssb_index, + ssb_start_subcarrier, + mac->frequency_range); } - - channel_bandwidth_t min_channel_bw = bw_10MHz; // deafult for testing - - uint32_t is_condition_A = (ssb_subcarrier_offset == 0); // 38.213 ch.13 - frequency_range_t frequency_range = FR1; - uint32_t index_4msb = (mac->mib->pdcch_ConfigSIB1.controlResourceSetZero); - uint32_t index_4lsb = (mac->mib->pdcch_ConfigSIB1.searchSpaceZero); - int32_t num_rbs = -1; - int32_t num_symbols = -1; - int32_t rb_offset = -1; - //LOG_I(MAC,"<<<<<<<<mib->pdcch_ConfigSIB1,index_4msb,index_4lsb,scs_ssb,scs_pdcch, (scs_ssb << 5)|scs_pdcch); - - // type0-pdcch coreset - switch( (scs_ssb << 5)|scs_pdcch ){ - case (scs_15kHz << 5) | scs_15kHz : - AssertFatal(index_4msb < 15, "38.213 Table 13-1 4 MSB out of range\n"); - mac->type0_pdcch_ss_mux_pattern = 1; - num_rbs = table_38213_13_1_c2[index_4msb]; - num_symbols = table_38213_13_1_c3[index_4msb]; - rb_offset = table_38213_13_1_c4[index_4msb]; - break; - - case (scs_15kHz << 5) | scs_30kHz: - AssertFatal(index_4msb < 14, "38.213 Table 13-2 4 MSB out of range\n"); - mac->type0_pdcch_ss_mux_pattern = 1; - num_rbs = table_38213_13_2_c2[index_4msb]; - num_symbols = table_38213_13_2_c3[index_4msb]; - rb_offset = table_38213_13_2_c4[index_4msb]; - break; - - case (scs_30kHz << 5) | scs_15kHz: - if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)){ - AssertFatal(index_4msb < 9, "38.213 Table 13-3 4 MSB out of range\n"); - mac->type0_pdcch_ss_mux_pattern = 1; - num_rbs = table_38213_13_3_c2[index_4msb]; - num_symbols = table_38213_13_3_c3[index_4msb]; - rb_offset = table_38213_13_3_c4[index_4msb]; - }else if(min_channel_bw & bw_40MHz){ - AssertFatal(index_4msb < 9, "38.213 Table 13-5 4 MSB out of range\n"); - mac->type0_pdcch_ss_mux_pattern = 1; - num_rbs = table_38213_13_5_c2[index_4msb]; - num_symbols = table_38213_13_5_c3[index_4msb]; - rb_offset = table_38213_13_5_c4[index_4msb]; - }else{ ; } - - break; - - case (scs_30kHz << 5) | scs_30kHz: - if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)){ - mac->type0_pdcch_ss_mux_pattern = 1; - num_rbs = table_38213_13_4_c2[index_4msb]; - num_symbols = table_38213_13_4_c3[index_4msb]; - rb_offset = table_38213_13_4_c4[index_4msb]; - LOG_I(MAC,"<<<<<<<<type0_pdcch_ss_mux_pattern = 1; - num_rbs = table_38213_13_6_c2[index_4msb]; - num_symbols = table_38213_13_6_c3[index_4msb]; - rb_offset = table_38213_13_6_c4[index_4msb]; - }else{ ; } - break; - - case (scs_120kHz << 5) | scs_60kHz: - AssertFatal(index_4msb < 12, "38.213 Table 13-7 4 MSB out of range\n"); - if(index_4msb & 0x7){ - mac->type0_pdcch_ss_mux_pattern = 1; - }else if(index_4msb & 0x18){ - mac->type0_pdcch_ss_mux_pattern = 2; - }else{ ; } - - num_rbs = table_38213_13_7_c2[index_4msb]; - num_symbols = table_38213_13_7_c3[index_4msb]; - if(!is_condition_A && (index_4msb == 8 || index_4msb == 10)){ - rb_offset = table_38213_13_7_c4[index_4msb] - 1; - }else{ - rb_offset = table_38213_13_7_c4[index_4msb]; - } - break; - - case (scs_120kHz << 5) | scs_120kHz: - AssertFatal(index_4msb < 8, "38.213 Table 13-8 4 MSB out of range\n"); - if(index_4msb & 0x3){ - mac->type0_pdcch_ss_mux_pattern = 1; - }else if(index_4msb & 0x0c){ - mac->type0_pdcch_ss_mux_pattern = 3; - } - - num_rbs = table_38213_13_8_c2[index_4msb]; - num_symbols = table_38213_13_8_c3[index_4msb]; - if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)){ - rb_offset = table_38213_13_8_c4[index_4msb] - 1; - }else{ - rb_offset = table_38213_13_8_c4[index_4msb]; - } - break; - - case (scs_240kHz << 5) | scs_60kHz: - AssertFatal(index_4msb < 4, "38.213 Table 13-9 4 MSB out of range\n"); - mac->type0_pdcch_ss_mux_pattern = 1; - num_rbs = table_38213_13_9_c2[index_4msb]; - num_symbols = table_38213_13_9_c3[index_4msb]; - rb_offset = table_38213_13_9_c4[index_4msb]; - break; - - case (scs_240kHz << 5) | scs_120kHz: - AssertFatal(index_4msb < 8, "38.213 Table 13-10 4 MSB out of range\n"); - if(index_4msb & 0x3){ - mac->type0_pdcch_ss_mux_pattern = 1; - }else if(index_4msb & 0x0c){ - mac->type0_pdcch_ss_mux_pattern = 2; - } - num_rbs = table_38213_13_10_c2[index_4msb]; - num_symbols = table_38213_13_10_c3[index_4msb]; - if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)){ - rb_offset = table_38213_13_10_c4[index_4msb]-1; - }else{ - rb_offset = table_38213_13_10_c4[index_4msb]; - } - - break; - - default: - break; + else { + NR_ServingCellConfigCommon_t *scc = mac->scc; + scs_ssb = *scc->ssbSubcarrierSpacing; + band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); } - AssertFatal(num_rbs != -1, "Type0 PDCCH coreset num_rbs undefined"); - AssertFatal(num_symbols != -1, "Type0 PDCCH coreset num_symbols undefined"); - AssertFatal(rb_offset != -1, "Type0 PDCCH coreset rb_offset undefined"); - - //uint32_t cell_id = 0; // obtain from L1 later - - //mac->type0_pdcch_dci_config.coreset.rb_start = rb_offset; - //mac->type0_pdcch_dci_config.coreset.rb_end = rb_offset + num_rbs - 1; - uint64_t mask = 0x0; - uint8_t i; - for(i=0; i<(num_rbs/6); ++i){ // 38.331 Each bit corresponds a group of 6 RBs - mask = mask >> 1; - mask = mask | 0x100000000000; - } - //LOG_I(MAC,">>>>>>>>mask %x num_rbs %d rb_offset %d\n", mask, num_rbs, rb_offset); - /* - mac->type0_pdcch_dci_config.coreset.frequency_domain_resource = mask; - mac->type0_pdcch_dci_config.coreset.rb_offset = rb_offset; // additional parameter other than coreset - - //mac->type0_pdcch_dci_config.type0_pdcch_coreset.duration = num_symbols; - mac->type0_pdcch_dci_config.coreset.cce_reg_mapping_type = CCE_REG_MAPPING_TYPE_INTERLEAVED; - mac->type0_pdcch_dci_config.coreset.cce_reg_interleaved_reg_bundle_size = 6; // L 38.211 7.3.2.2 - mac->type0_pdcch_dci_config.coreset.cce_reg_interleaved_interleaver_size = 2; // R 38.211 7.3.2.2 - mac->type0_pdcch_dci_config.coreset.cce_reg_interleaved_shift_index = cell_id; - mac->type0_pdcch_dci_config.coreset.precoder_granularity = PRECODER_GRANULARITY_SAME_AS_REG_BUNDLE; - mac->type0_pdcch_dci_config.coreset.pdcch_dmrs_scrambling_id = cell_id; - */ - - - // type0-pdcch search space - float big_o; - float big_m; - uint32_t temp; - SFN_C_TYPE sfn_c=SFN_C_IMPOSSIBLE; // only valid for mux=1 - uint32_t n_c=UINT_MAX; - uint32_t number_of_search_space_per_slot=UINT_MAX; - uint32_t first_symbol_index=UINT_MAX; - uint32_t search_space_duration; // element of search space - // 38.213 table 10.1-1 - - /// MUX PATTERN 1 - if(mac->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR1){ - big_o = table_38213_13_11_c1[index_4lsb]; - number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb]; - big_m = table_38213_13_11_c3[index_4lsb]; - - temp = (uint32_t)(big_o*pow(2, scs_pdcch)) + (uint32_t)(ssb_index*big_m); - n_c = temp / num_slot_per_frame; - if((temp/num_slot_per_frame) & 0x1){ - sfn_c = SFN_C_MOD_2_EQ_1; - }else{ - sfn_c = SFN_C_MOD_2_EQ_0; - } - - if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (ssb_index&1)){ - first_symbol_index = num_symbols; - }else{ - first_symbol_index = table_38213_13_11_c4[index_4lsb]; - } - // 38.213 chapter 13: over two consecutive slots - search_space_duration = 2; - } - - if(mac->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){ - big_o = table_38213_13_12_c1[index_4lsb]; - number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb]; - big_m = table_38213_13_12_c3[index_4lsb]; - - if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (ssb_index&1)){ - first_symbol_index = 7; - }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (ssb_index&1)){ - first_symbol_index = num_symbols; - }else{ - first_symbol_index = 0; - } - // 38.213 chapter 13: over two consecutive slots - search_space_duration = 2; - } - - /// MUX PATTERN 2 - if(mac->type0_pdcch_ss_mux_pattern == 2){ - - if((scs_ssb == scs_120kHz) && (scs_pdcch == scs_60kHz)){ - // 38.213 Table 13-13 - AssertFatal(index_4lsb == 0, "38.213 Table 13-13 4 LSB out of range\n"); - // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot - // sfn_c = SFN_C_EQ_SFN_SSB; - n_c = get_ssb_slot(ssb_index); - switch(ssb_index & 0x3){ // ssb_index(i) mod 4 - case 0: - first_symbol_index = 0; - break; - case 1: - first_symbol_index = 1; - break; - case 2: - first_symbol_index = 6; - break; - case 3: - first_symbol_index = 7; - break; - default: break; - } - - }else if((scs_ssb == scs_240kHz) && (scs_pdcch == scs_120kHz)){ - // 38.213 Table 13-14 - AssertFatal(index_4lsb == 0, "38.213 Table 13-14 4 LSB out of range\n"); - // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot - // sfn_c = SFN_C_EQ_SFN_SSB; - n_c = get_ssb_slot(ssb_index); - switch(ssb_index & 0x7){ // ssb_index(i) mod 8 - case 0: - first_symbol_index = 0; - break; - case 1: - first_symbol_index = 1; - break; - case 2: - first_symbol_index = 2; - break; - case 3: - first_symbol_index = 3; - break; - case 4: - first_symbol_index = 12; - n_c = get_ssb_slot(ssb_index) - 1; - break; - case 5: - first_symbol_index = 13; - n_c = get_ssb_slot(ssb_index) - 1; - break; - case 6: - first_symbol_index = 0; - break; - case 7: - first_symbol_index = 1; - break; - default: break; - } - }else{ ; } - // 38.213 chapter 13: over one slot - search_space_duration = 1; - } - - /// MUX PATTERN 3 - if(mac->type0_pdcch_ss_mux_pattern == 3){ - if((scs_ssb == scs_120kHz) && (scs_pdcch == scs_120kHz)){ - // 38.213 Table 13-15 - AssertFatal(index_4lsb == 0, "38.213 Table 13-15 4 LSB out of range\n"); - // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot - // sfn_c = SFN_C_EQ_SFN_SSB; - n_c = get_ssb_slot(ssb_index); - switch(ssb_index & 0x3){ // ssb_index(i) mod 4 - case 0: - first_symbol_index = 4; - break; - case 1: - first_symbol_index = 8; - break; - case 2: - first_symbol_index = 2; - break; - case 3: - first_symbol_index = 6; - break; - default: break; - } - }else{ ; } - // 38.213 chapter 13: over one slot - search_space_duration = 1; - } - - AssertFatal(number_of_search_space_per_slot!=UINT_MAX,""); - /* - uint32_t coreset_duration = num_symbols * number_of_search_space_per_slot; - mac->type0_pdcch_dci_config.number_of_candidates[0] = table_38213_10_1_1_c2[0]; - mac->type0_pdcch_dci_config.number_of_candidates[1] = table_38213_10_1_1_c2[1]; - mac->type0_pdcch_dci_config.number_of_candidates[2] = table_38213_10_1_1_c2[2]; // CCE aggregation level = 4 - mac->type0_pdcch_dci_config.number_of_candidates[3] = table_38213_10_1_1_c2[3]; // CCE aggregation level = 8 - mac->type0_pdcch_dci_config.number_of_candidates[4] = table_38213_10_1_1_c2[4]; // CCE aggregation level = 16 - mac->type0_pdcch_dci_config.duration = search_space_duration; - mac->type0_pdcch_dci_config.coreset.duration = coreset_duration; // coreset - AssertFatal(first_symbol_index!=UINT_MAX,""); - mac->type0_pdcch_dci_config.monitoring_symbols_within_slot = (0x3fff << first_symbol_index) & (0x3fff >> (14-coreset_duration-first_symbol_index)) & 0x3fff; - */ - AssertFatal(sfn_c!=SFN_C_IMPOSSIBLE,""); - AssertFatal(n_c!=UINT_MAX,""); - mac->type0_pdcch_ss_sfn_c = sfn_c; - mac->type0_pdcch_ss_n_c = n_c; - - // fill in the elements in config request inside P5 message - mac->phy_config.Mod_id = module_id; - mac->phy_config.CC_id = cc_id; - mac->dl_config_request.sfn = frame; - mac->dl_config_request.slot = (ssb_index>>1) + ((ssb_index>>4)<<1); // not valid for 240kHz SCS + mac->dl_config_request.slot = ssb_start_symbol/14; - //} return 0; - } +int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, + int cc_id, + unsigned int gNB_index, + uint8_t ack_nack, + uint8_t *pduP, + uint32_t pdu_len) { + if(ack_nack) { + LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); + nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); + } + else + LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); + return 0; +} // TODO: change to UE parameter, scs: 15KHz, slot duration: 1ms uint32_t get_ssb_frame(uint32_t test){ return test; } -// Performs : -// 1. TODO: Call RRC for link status return to PHY -// 2. TODO: Perform SR/BSR procedures for scheduling feedback -// 3. TODO: Perform PHR procedures -NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_indication_t *ul_info){ - - uint32_t search_space_mask = 0; - - if (dl_info){ - - module_id_t mod_id = dl_info->module_id; - uint32_t gNB_index = dl_info->gNB_index; - int cc_id = dl_info->cc_id; - frame_t rx_frame = dl_info->frame; - slot_t rx_slot = dl_info->slot; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - nr_scheduled_response_t scheduled_response; - nr_dcireq_t dcireq; - - // check type0 from 38.213 13 if we have no CellGroupConfig - // TODO: implementation to be completed - if (mac->scg == NULL) { - if(dl_info->ssb_index != -1){ - - if(mac->type0_pdcch_ss_mux_pattern == 1){ - // 38.213 chapter 13 - if((mac->type0_pdcch_ss_sfn_c == SFN_C_MOD_2_EQ_0) && !(rx_frame & 0x1) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - if((mac->type0_pdcch_ss_sfn_c == SFN_C_MOD_2_EQ_1) && (rx_frame & 0x1) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - if(mac->type0_pdcch_ss_mux_pattern == 2){ - // 38.213 Table 13-13, 13-14 - if((rx_frame == get_ssb_frame(rx_frame)) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - if(mac->type0_pdcch_ss_mux_pattern == 3){ - // 38.213 Table 13-15 - if((rx_frame == get_ssb_frame(rx_frame)) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - } // ssb_index != -1 - - // Type0 PDCCH search space - if((search_space_mask & type0_pdcch) || ( mac->type0_pdcch_consecutive_slots != 0 )){ - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_consecutive_slots - 1; - - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15 = mac->type0_pdcch_dci_config; - dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - - /* - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.rnti = 0xaaaa; // to be set - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = 106; // to be set - - LOG_I(MAC,"nr_ue_scheduler Type0 PDCCH with rnti %x, BWP %d\n", - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.rnti, - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP); - */ - dl_config->number_pdus = dl_config->number_pdus + 1; - mac->scheduled_response.dl_config = dl_config; - } - } else { // we have an scg - - dcireq.module_id = mod_id; - dcireq.gNB_index = gNB_index; - dcireq.cc_id = cc_id; - dcireq.frame = rx_frame; - dcireq.slot = rx_slot; - nr_ue_dcireq(&dcireq); //to be replaced with function pointer later - - // we should have received a DL DCI here, so configure DL accordingly - scheduled_response.dl_config = &dcireq.dl_config_req; - scheduled_response.ul_config = NULL; - scheduled_response.tx_request = NULL; - scheduled_response.module_id = mod_id; - scheduled_response.CC_id = cc_id; - scheduled_response.frame = rx_frame; - scheduled_response.slot = rx_slot; - - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&scheduled_response); - } - - /* - if(search_space_mask & type0a_pdcch){ - } - - if(search_space_mask & type1_pdcch){ - } - - if(search_space_mask & type2_pdcch){ - } - - if(search_space_mask & type3_pdcch){ - } - */ - } - } else if (ul_info) { - - if (get_softmodem_params()->phy_test && ul_info->slot_tx == 8) { // ULSCH is handled only in phy-test mode (consistently with OAI gNB) - - uint8_t nb_dmrs_re_per_rb; - uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; - uint8_t data_existing = 0; - uint16_t TBS_bytes; - uint32_t TBS; - int i; - - module_id_t mod_id = ul_info->module_id; - uint32_t gNB_index = ul_info->gNB_index; - int cc_id = ul_info->cc_id; - frame_t rx_frame = ul_info->frame_rx; - slot_t rx_slot = ul_info->slot_rx; - frame_t frame_tx = ul_info->frame_tx; - slot_t slot_tx = ul_info->slot_tx; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - uint8_t access_mode = SCHEDULED_ACCESS; - - // program PUSCH. this should actually be done upon reception of an UL DCI - nr_dcireq_t dcireq; - nr_scheduled_response_t scheduled_response; - fapi_nr_tx_request_t tx_req; - fapi_nr_tx_request_body_t tx_req_body; - - //--------------------------Temporary configuration-----------------------------// - uint16_t rnti = 0x1234; - uint32_t rb_size = 50; - uint32_t rb_start = 0; - uint8_t nr_of_symbols = 11; - uint8_t start_symbol_index = 0; - uint8_t nrOfLayers = 1; - uint8_t mcs_index = 9; - uint8_t mcs_table = 0; - uint8_t harq_process_id = 0; - uint8_t rv_index = 0; - uint16_t l_prime_mask = get_l_prime(nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); - uint8_t dmrs_config_type = 0; - uint8_t ptrs_mcs1 = 2; - uint8_t ptrs_mcs2 = 4; - uint8_t ptrs_mcs3 = 10; - uint16_t n_rb0 = 25; - uint16_t n_rb1 = 75; - uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, mcs_index, mcs_table); - uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, rb_size); - uint8_t no_data_in_dmrs = 1; - uint16_t number_dmrs_symbols = 0; - uint16_t ul_dmrs_symb_pos = l_prime_mask << start_symbol_index; - //------------------------------------------------------------------------------// - - for (i = start_symbol_index; i < start_symbol_index + nr_of_symbols; i++) { - if((ul_dmrs_symb_pos >> i) & 0x01) - number_dmrs_symbols += 1; - } - - if(no_data_in_dmrs) - nb_dmrs_re_per_rb = 12; - else - nb_dmrs_re_per_rb = ((dmrs_config_type == pusch_dmrs_type1) ? 6:4); - - TBS = nr_compute_tbs(nr_get_Qm_ul(mcs_index, 0), - nr_get_code_rate_ul(mcs_index, 0), - rb_size, - nr_of_symbols, - nb_dmrs_re_per_rb*number_dmrs_symbols, - 0, - 0, - nrOfLayers); - TBS_bytes = TBS/8; - - if (IS_SOFTMODEM_NOS1){ - // Getting IP traffic to be transmitted - data_existing = nr_ue_get_sdu(mod_id, - cc_id, - frame_tx, - slot_tx, - 0, - ulsch_input_buffer, - TBS_bytes, - &access_mode); - } - - //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity - if (!IS_SOFTMODEM_NOS1 || !data_existing) { - //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid - //and block this traffic from being forwarded to the upper layers at the gNB - LOG_D(PHY, "Random data to be tranmsitted: \n"); - - //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) - //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should - //have a valid LCID (nr_process_mac_pdu function) - ulsch_input_buffer[0] = 0x31; - - for (i = 1; i < TBS_bytes; i++) { - ulsch_input_buffer[i] = (unsigned char) rand(); - //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - } - } - -#ifdef DEBUG_MAC_PDU - - LOG_D(PHY, "Is data existing ?: %d \n", data_existing); - LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS_bytes); - for (i = 0; i < TBS_bytes; i++) { - printf("%02x", ulsch_input_buffer[i]); - } - printf("\n"); - -#endif - - dcireq.module_id = mod_id; - dcireq.gNB_index = gNB_index; - dcireq.cc_id = cc_id; - dcireq.frame = rx_frame; - dcireq.slot = rx_slot; - - scheduled_response.dl_config = NULL; - scheduled_response.ul_config = &dcireq.ul_config_req; - // Config UL TX PDU - tx_req.slot = slot_tx; - tx_req.sfn = frame_tx; - // tx_req->tx_config // TbD - tx_req.number_of_pdus = 1; - tx_req_body.pdu_length = TBS_bytes; - tx_req_body.pdu_index = 0; - tx_req_body.pdu = ulsch_input_buffer; - - scheduled_response.tx_request = &tx_req; - scheduled_response.tx_request->tx_request_body = &tx_req_body; - scheduled_response.module_id = mod_id; - scheduled_response.CC_id = cc_id; - scheduled_response.frame = rx_frame; - scheduled_response.slot = rx_slot; - - scheduled_response.ul_config->slot = ul_info->slot_tx; - scheduled_response.ul_config->number_pdus = 1; - scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rnti = rnti; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_size = rb_size; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_start = rb_start; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nr_of_symbols = nr_of_symbols; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = ul_dmrs_symb_pos; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_index = mcs_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nrOfLayers = nrOfLayers; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_process_id; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t)); - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - - if (1 << ptrs_time_density >= nr_of_symbols) { - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - } - - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&scheduled_response); - } - - // TODO: expand - // Note: Contention resolution is currently not active - if (mac->RA_contention_resolution_timer_active == 1) - ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx); - } - } - return UE_CONNECTION_OK; -} - -// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x -// It fills the PRACH PDU per each FD occasion. -// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. -// - todo: -// - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config -void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - - uint8_t config_index, mu, N_dur, N_t_slot, start_symbol; - uint16_t format, format0, format1, ncs; - int msg1_FDM, is_nr_prach_slot, fdm; - - NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); - - fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; - fapi_nr_ul_config_prach_pdu *prach_config_pdu; - fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - fapi_nr_prach_config_t *prach_config = &cfg->prach_config; - - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - config_index = rach_ConfigGeneric->prach_ConfigurationIndex; - - mac->RA_offset = 2; // to compensate the rx frame offset at the gNB - mac->generate_nr_prach = 0; // Reset flag for PRACH generation - - if (is_nr_UL_slot(scc, slotP)) { - - if (setup->msg1_SubcarrierSpacing) - mu = *setup->msg1_SubcarrierSpacing; - else - mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - - is_nr_prach_slot = get_nr_prach_info_from_index(config_index, - (int)frameP, - (int)slotP, - frequencyInfoDL->absoluteFrequencyPointA, - mu, - cfg->cell_config.frame_duplex_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur); - - if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) { - - mac->generate_nr_prach = 1; - - fdm = rach_ConfigGeneric->msg1_FDM; - - switch (fdm){ - case 0: - case 1: - case 2: - case 3: - msg1_FDM = 1 << fdm; - break; - default: - AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", fdm); - } - - format0 = format & 0xff; // single PRACH format - format1 = (format >> 8) & 0xff; // dual PRACH format - - ul_config->sfn = frameP; - ul_config->slot = slotP; - - for (int n = 0; n < msg1_FDM; n++) { // one structure per frequency domain occasion - - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; - prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; - memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); - ul_config->number_pdus += 1; - - ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); - - // filling PRACH PDU for FAPI config request - prach_config_pdu->phys_cell_id = *scc->physCellId; - prach_config_pdu->num_prach_ocas = N_t_slot; - prach_config_pdu->prach_start_symbol = start_symbol; - prach_config_pdu->num_ra = n; - prach_config_pdu->num_cs = ncs; - prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[n].prach_root_sequence_index; - prach_config_pdu->restricted_set = prach_config->restricted_set_config; - prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; - - if (format1 != 0xff) { - switch(format0) { // dual PRACH format - case 0xa1: - prach_config_pdu->prach_format = 9; - break; - case 0xa2: - prach_config_pdu->prach_format = 10; - break; - case 0xa3: - prach_config_pdu->prach_format = 11; - break; - default: - AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); - } - } else { - switch(format0) { // single PRACH format - case 0xa1: - prach_config_pdu->prach_format = 0; - break; - case 0xa2: - prach_config_pdu->prach_format = 1; - break; - case 0xa3: - prach_config_pdu->prach_format = 2; - break; - case 0xb1: - prach_config_pdu->prach_format = 3; - break; - case 0xb2: - prach_config_pdu->prach_format = 4; - break; - case 0xb3: - prach_config_pdu->prach_format = 5; - break; - case 0xb4: - prach_config_pdu->prach_format = 6; - break; - case 0xc0: - prach_config_pdu->prach_format = 7; - break; - case 0xc2: - prach_config_pdu->prach_format = 8; - break; - case 0: - // long formats are handled @ PHY - break; - case 1: - // long formats are handled @ PHY - break; - case 2: - // long formats are handled @ PHY - break; - case 3: - // long formats are handled @ PHY - break; - default: - AssertFatal(1 == 0, "Invalid PRACH format"); - } - } - } - } else if (mac->ra_state == RA_SUCCEEDED){ - mac->generate_nr_prach = 2; - } - mac->scheduled_response.ul_config = ul_config; - } -} - -//////////////////////////////////////////////////////////////////////////// -/////////* Random Access Contention Resolution (5.1.35 TS 38.321) *///////// -//////////////////////////////////////////////////////////////////////////// -// Handling contention resolution timer -// WIP todo: -// - beam failure recovery -// - RA completed - -void ue_contention_resolution(module_id_t module_id, uint8_t gNB_index, int cc_id, frame_t tx_frame){ - - NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - - if (mac->RA_contention_resolution_timer_active == 1) { - if (nr_rach_ConfigCommon){ - LOG_I(MAC, "Frame %d: Contention resolution timer %d/%ld\n", - tx_frame, - mac->RA_contention_resolution_cnt, - ((1 + nr_rach_ConfigCommon->ra_ContentionResolutionTimer) << 3)); - mac->RA_contention_resolution_cnt++; - - if (mac->RA_contention_resolution_cnt == ((1 + nr_rach_ConfigCommon->ra_ContentionResolutionTimer) << 3)) { - mac->t_crnti = 0; - mac->RA_active = 0; - mac->RA_contention_resolution_timer_active = 0; - // Signal PHY to quit RA procedure - LOG_E(MAC, "[UE %u] [RAPROC] Contention resolution timer expired, RA failed, discarded TC-RNTI\n", module_id); - nr_ra_failed(module_id, cc_id, gNB_index); - } - } - } -} - -#if 0 -uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, - uint8_t slot, - int p, - crc_scrambled_t crc_scrambled, - uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS], - uint8_t format) { - LOG_DDD("crc_scrambled=%d, n_RB_ULBWP=%d, n_RB_DLBWP=%d\n",crc_scrambled,n_RB_ULBWP,n_RB_DLBWP); - /* - * function nr_dci_format_size calculates and returns the size in bits of a determined format - * it also returns an bi-dimensional array 'dci_fields_sizes' with x rows and y columns, where: - * x is the number of fields defined in TS 38.212 subclause 7.3.1 (Each field is mapped in the order in which it appears in the description in the specification) - * y is the number of formats - * e.g.: dci_fields_sizes[10][0] contains the size in bits of the field FREQ_DOM_RESOURCE_ASSIGNMENT_UL for format 0_0 - */ - // pdsch_config contains the PDSCH-Config IE is used to configure the UE specific PDSCH parameters (TS 38.331) - PDSCH_Config_t pdsch_config = ue->PDSCH_Config; - // pusch_config contains the PUSCH-Config IE is used to configure the UE specific PUSCH parameters (TS 38.331) - PUSCH_Config_t pusch_config = ue->pusch_config; - PUCCH_Config_t pucch_config_dedicated = ue->pucch_config_dedicated_nr[eNB_id]; - crossCarrierSchedulingConfig_t crossCarrierSchedulingConfig = ue->crossCarrierSchedulingConfig; - dmrs_UplinkConfig_t dmrs_UplinkConfig = ue->dmrs_UplinkConfig; - dmrs_DownlinkConfig_t dmrs_DownlinkConfig = ue->dmrs_DownlinkConfig; - csi_MeasConfig_t csi_MeasConfig = ue->csi_MeasConfig; - PUSCH_ServingCellConfig_t PUSCH_ServingCellConfig= ue->PUSCH_ServingCellConfig; - PDSCH_ServingCellConfig_t PDSCH_ServingCellConfig= ue->PDSCH_ServingCellConfig; - NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; - // 1 CARRIER_IN - // crossCarrierSchedulingConfig from higher layers, variable crossCarrierSchedulingConfig indicates if 'cross carrier scheduling' is enabled or not: - // if No cross carrier scheduling: number of bits for CARRIER_IND is 0 - // if Cross carrier scheduling: number of bits for CARRIER_IND is 3 - // The IE CrossCarrierSchedulingConfig is used to specify the configuration when the cross-carrier scheduling is used in a cell - uint8_t crossCarrierSchedulingConfig_ind = 0; - - if (crossCarrierSchedulingConfig.schedulingCellInfo.other.cif_InSchedulingCell !=0 ) crossCarrierSchedulingConfig_ind=1; - - // 2 SUL_IND_0_1, // 40 SRS_REQUEST, // 50 SUL_IND_0_0 - // UL/SUL indicator (TS 38.331, supplementary uplink is indicated in higher layer parameter ServCellAdd-SUL from IE ServingCellConfig and ServingCellConfigCommon): - // 0 bit for UEs not configured with SUL in the cell or UEs configured with SUL in the cell but only PUCCH carrier in the cell is configured for PUSCH transmission - // 1 bit for UEs configured with SUL in the cell as defined in Table 7.3.1.1.1-1 - // sul_ind indicates whether SUL is configured in cell or not - uint8_t sul_ind=ue->supplementaryUplink.supplementaryUplink; // this value will be 0 or 1 depending on higher layer parameter ServCellAdd-SUL. FIXME!!! - // 7 BANDWIDTH_PART_IND - // number of UL BWPs configured by higher layers - uint8_t n_UL_BWP_RRC=1; // initialized to 1 but it has to be initialized by higher layers FIXME!!! - n_UL_BWP_RRC = ((n_UL_BWP_RRC > 3)?n_UL_BWP_RRC:(n_UL_BWP_RRC+1)); - // number of DL BWPs configured by higher layers - uint8_t n_DL_BWP_RRC=1; // initialized to 1 but it has to be initialized by higher layers FIXME!!! - n_DL_BWP_RRC = ((n_DL_BWP_RRC > 3)?n_DL_BWP_RRC:(n_DL_BWP_RRC+1)); - // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL - // if format0_0, only resource allocation type 1 is allowed - // if format0_1, then resource allocation type 0 can be configured and N_RBG is defined in TS 38.214 subclause 6.1.2.2.1 - // for PUSCH hopping with resource allocation type 1 - // n_UL_hopping = 1 if the higher layer parameter frequencyHoppingOffsetLists contains two offset values - // n_UL_hopping = 2 if the higher layer parameter frequencyHoppingOffsetLists contains four offset values - uint8_t n_UL_hopping=pusch_config.n_frequencyHoppingOffsetLists; - - if (n_UL_hopping == 2) { - n_UL_hopping = 1; - } else if (n_UL_hopping == 4) { - n_UL_hopping = 2; - } else { - n_UL_hopping = 0; - } - - ul_resourceAllocation_t ul_resource_allocation_type = pusch_config.ul_resourceAllocation; - uint8_t ul_res_alloc_type_0 = 0; - uint8_t ul_res_alloc_type_1 = 0; - - if (ul_resource_allocation_type == ul_resourceAllocationType0) ul_res_alloc_type_0 = 1; - - if (ul_resource_allocation_type == ul_resourceAllocationType1) ul_res_alloc_type_1 = 1; - - if (ul_resource_allocation_type == ul_dynamicSwitch) { - ul_res_alloc_type_0 = 1; - ul_res_alloc_type_1 = 1; - } - - uint8_t n_bits_freq_dom_res_assign_ul=0,n_ul_RGB_tmp; - - if (ul_res_alloc_type_0 == 1) { // implementation of Table 6.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 - // config1: PUSCH-Config IE contains rbg-Size ENUMERATED {config1 config2} - ul_rgb_Size_t config = pusch_config.ul_rgbSize; - uint8_t nominal_RBG_P = (config==ul_rgb_config1?2:4); - - if (n_RB_ULBWP > 36) nominal_RBG_P = (config==ul_rgb_config1?4:8); - - if (n_RB_ULBWP > 72) nominal_RBG_P = (config==ul_rgb_config1?8:16); - - if (n_RB_ULBWP > 144) nominal_RBG_P = 16; - - n_bits_freq_dom_res_assign_ul = (uint8_t)ceil((n_RB_ULBWP+(0%nominal_RBG_P))/nominal_RBG_P); //FIXME!!! what is 0??? - n_ul_RGB_tmp = n_bits_freq_dom_res_assign_ul; - } - - if (ul_res_alloc_type_1 == 1) n_bits_freq_dom_res_assign_ul = (uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping; - - if ((ul_res_alloc_type_0 == 1) && (ul_res_alloc_type_1 == 1)) - n_bits_freq_dom_res_assign_ul = ((n_bits_freq_dom_res_assign_ul>n_ul_RGB_tmp)?(n_bits_freq_dom_res_assign_ul+1):(n_ul_RGB_tmp+1)); - - // 11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL - // if format1_0, only resource allocation type 1 is allowed - // if format1_1, then resource allocation type 0 can be configured and N_RBG is defined in TS 38.214 subclause 5.1.2.2.1 - dl_resourceAllocation_t dl_resource_allocation_type = pdsch_config.dl_resourceAllocation; - uint8_t dl_res_alloc_type_0 = 0; - uint8_t dl_res_alloc_type_1 = 0; - - if (dl_resource_allocation_type == dl_resourceAllocationType0) dl_res_alloc_type_0 = 1; - - if (dl_resource_allocation_type == dl_resourceAllocationType1) dl_res_alloc_type_1 = 1; - - if (dl_resource_allocation_type == dl_dynamicSwitch) { - dl_res_alloc_type_0 = 1; - dl_res_alloc_type_1 = 1; - } - - uint8_t n_bits_freq_dom_res_assign_dl=0,n_dl_RGB_tmp; - - if (dl_res_alloc_type_0 == 1) { // implementation of Table 5.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 - // config1: PDSCH-Config IE contains rbg-Size ENUMERATED {config1, config2} - dl_rgb_Size_t config = pdsch_config.dl_rgbSize; - uint8_t nominal_RBG_P = (config==dl_rgb_config1?2:4); - - if (n_RB_DLBWP > 36) nominal_RBG_P = (config==dl_rgb_config1?4:8); - - if (n_RB_DLBWP > 72) nominal_RBG_P = (config==dl_rgb_config1?8:16); - - if (n_RB_DLBWP > 144) nominal_RBG_P = 16; - - n_bits_freq_dom_res_assign_dl = (uint8_t)ceil((n_RB_DLBWP+(0%nominal_RBG_P))/nominal_RBG_P); //FIXME!!! what is 0??? - n_dl_RGB_tmp = n_bits_freq_dom_res_assign_dl; - } - - if (dl_res_alloc_type_1 == 1) n_bits_freq_dom_res_assign_dl = (uint8_t)(ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2))); - - if ((dl_res_alloc_type_0 == 1) && (dl_res_alloc_type_1 == 1)) - n_bits_freq_dom_res_assign_dl = ((n_bits_freq_dom_res_assign_dl>n_dl_RGB_tmp)?(n_bits_freq_dom_res_assign_dl+1):(n_dl_RGB_tmp+1)); - - // 12 TIME_DOM_RESOURCE_ASSIGNMENT - uint8_t pusch_alloc_list = pusch_config.n_push_alloc_list; - uint8_t pdsch_alloc_list = pdsch_config.n_pdsh_alloc_list; - // 14 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] - static_bundleSize_t static_prb_BundlingType = pdsch_config.prbBundleType.staticBundling; - bundleSizeSet1_t dynamic_prb_BundlingType1 = pdsch_config.prbBundleType.dynamicBundlig.bundleSizeSet1; - bundleSizeSet2_t dynamic_prb_BundlingType2 = pdsch_config.prbBundleType.dynamicBundlig.bundleSizeSet2; - uint8_t prb_BundlingType_size=0; - - if ((static_prb_BundlingType==st_n4)||(static_prb_BundlingType==st_wideband)) prb_BundlingType_size=0; - - if ((dynamic_prb_BundlingType1==dy_1_n4)||(dynamic_prb_BundlingType1==dy_1_wideband)||(dynamic_prb_BundlingType1==dy_1_n2_wideband)||(dynamic_prb_BundlingType1==dy_1_n4_wideband)|| - (dynamic_prb_BundlingType2==dy_2_n4)||(dynamic_prb_BundlingType2==dy_2_wideband)) prb_BundlingType_size=1; - - // 15 RATE_MATCHING_IND FIXME!!! - // according to TS 38.212: Rate matching indicator – 0, 1, or 2 bits according to higher layer parameter rateMatchPattern - uint8_t rateMatching_bits = pdsch_config.n_rateMatchPatterns; - // 16 ZP_CSI_RS_TRIGGER FIXME!!! - // 0, 1, or 2 bits as defined in Subclause 5.1.4.2 of [6, TS 38.214]. - // is the number of ZP CSI-RS resource sets in the higher layer parameter zp-CSI-RS-Resource - uint8_t n_zp_bits = pdsch_config.n_zp_CSI_RS_ResourceId; - // 17 FREQ_HOPPING_FLAG - // freqHopping is defined by higher layer parameter frequencyHopping from IE PUSCH-Config. Values are ENUMERATED{mode1, mode2} - frequencyHopping_t f_hopping = pusch_config.frequencyHopping; - uint8_t freqHopping = 0; - - if ((f_hopping==f_hop_mode1)||(f_hopping==f_hop_mode2)) freqHopping = 1; - - // 28 DAI - pdsch_HARQ_ACK_Codebook_t pdsch_HARQ_ACK_Codebook = pdsch_config.pdsch_HARQ_ACK_Codebook; - uint8_t n_dai = 0; - uint8_t n_serving_cell_dl = 1; // this is hardcoded to 1 as we need to get this value from RRC higher layers parameters. FIXME!!! - - if ((pdsch_HARQ_ACK_Codebook == dynamic) && (n_serving_cell_dl == 1)) n_dai = 2; - - if ((pdsch_HARQ_ACK_Codebook == dynamic) && (n_serving_cell_dl > 1)) n_dai = 4; - - // 29 FIRST_DAI - uint8_t codebook_HARQ_ACK = 0; // We need to get this value to calculate number of bits of fields 1st DAI and 2nd DAI. - - if (pdsch_HARQ_ACK_Codebook == semiStatic) codebook_HARQ_ACK = 1; - - if (pdsch_HARQ_ACK_Codebook == dynamic) codebook_HARQ_ACK = 2; - - // 30 SECOND_DAI - uint8_t n_HARQ_ACK_sub_codebooks = 0; // We need to get this value to calculate number of bits of fields 1st DAI and 2nd DAI. FIXME!!! - // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND - uint8_t pdsch_harq_t_ind = (uint8_t)ceil(log2(pucch_config_dedicated.dl_DataToUL_ACK[0])); - // 36 SRS_RESOURCE_IND - // n_SRS is the number of configured SRS resources in the SRS resource set associated with the higher layer parameter usage of value 'codeBook' or 'nonCodeBook' - // from SRS_ResourceSet_t type we should get the information of the usage parameter (with possible values beamManagement, codebook, nonCodebook, antennaSwitching) - // at frame_parms->srs_nr->p_SRS_ResourceSetList[]->usage - uint8_t n_SRS = ue->srs.number_srs_Resource_Set; - // 37 PRECOD_NBR_LAYERS - // 38 ANTENNA_PORTS - txConfig_t txConfig = pusch_config.txConfig; - transformPrecoder_t transformPrecoder = pusch_config.transformPrecoder; - codebookSubset_t codebookSubset = pusch_config.codebookSubset; - uint8_t maxRank = pusch_config.maxRank; - uint8_t num_antenna_ports = 1; // this is hardcoded. We need to get the real value FIXME!!! - uint8_t precond_nbr_layers_bits = 0; - uint8_t antenna_ports_bits_ul = 0; - - // searching number of bits at tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2 - if (txConfig == txConfig_codebook) { - if (num_antenna_ports == 4) { - if ((transformPrecoder == transformPrecoder_disabled) && ((maxRank == 2)||(maxRank == 3)||(maxRank == 4))) { // Table 7.3.1.1.2-2 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=6; - - if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=5; - - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=4; - } - - if (((transformPrecoder == transformPrecoder_enabled)||(transformPrecoder == transformPrecoder_disabled)) && (maxRank == 1)) { // Table 7.3.1.1.2-3 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=5; - - if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=4; - - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; - } - } - - if (num_antenna_ports == 2) { - if ((transformPrecoder == transformPrecoder_disabled) && (maxRank == 2)) { // Table 7.3.1.1.2-4 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=4; - - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; - } - - if (((transformPrecoder == transformPrecoder_enabled)||(transformPrecoder == transformPrecoder_disabled)) && (maxRank == 1)) { // Table 7.3.1.1.2-5 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=3; - - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=1; - } - } - } - - if (txConfig == txConfig_nonCodebook) { - } - - // searching number of bits at tables 7.3.1.1.2-6/7/8/9/10/11/12/13/14/15/16/17/18/19 - if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)) { - if ((transformPrecoder == transformPrecoder_enabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 2; - - if ((transformPrecoder == transformPrecoder_enabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 4; - - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 3; - - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 4; - } - - if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type2)) { - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 4; - - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 5; - } - - // for format 1_1 number of bits as defined by Tables 7.3.1.2.2-1/2/3/4 - uint8_t antenna_ports_bits_dl = 0; - - if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type1) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len1)) antenna_ports_bits_dl = 4; // Table 7.3.1.2.2-1 - - if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type1) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len2)) antenna_ports_bits_dl = 5; // Table 7.3.1.2.2-2 - - if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type2) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len1)) antenna_ports_bits_dl = 5; // Table 7.3.1.2.2-3 - - if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type2) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len2)) antenna_ports_bits_dl = 6; // Table 7.3.1.2.2-4 - - // 39 TCI - uint8_t tci_bits=0; - - if (pdcch_vars2->coreset[p].tciPresentInDCI == tciPresentInDCI_enabled) tci_bits=3; - - // 42 CSI_REQUEST - // reportTriggerSize is defined in the CSI-MeasConfig IE (TS 38.331). - // Size of CSI request field in DCI (bits). Corresponds to L1 parameter 'ReportTriggerSize' (see 38.214, section 5.2) - uint8_t reportTriggerSize = csi_MeasConfig.reportTriggerSize; // value from 0..6 - // 43 CBGTI - // for format 0_1 - uint8_t maxCodeBlockGroupsPerTransportBlock = 0; - - if (PUSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock != 0) - maxCodeBlockGroupsPerTransportBlock = (uint8_t)PUSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock; - - // for format 1_1, as defined in Subclause 5.1.7 of [6, TS38.214] - uint8_t maxCodeBlockGroupsPerTransportBlock_dl = 0; - - if (PDSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock_dl != 0) - maxCodeBlockGroupsPerTransportBlock_dl = pdsch_config.maxNrofCodeWordsScheduledByDCI; // FIXME!!! - - // 44 CBGFI - uint8_t cbgfi_bit = PDSCH_ServingCellConfig.codeBlockGroupFlushIndicator; - // 45 PTRS_DMRS - // 0 bit if PTRS-UplinkConfig is not configured and transformPrecoder=disabled, or if transformPrecoder=enabled, or if maxRank=1 - // 2 bits otherwise - uint8_t ptrs_dmrs_bits=0; //FIXME!!! - // 46 BETA_OFFSET_IND - // at IE PUSCH-Config, beta_offset indicator – 0 if the higher layer parameter betaOffsets = semiStatic; otherwise 2 bits - // uci-OnPUSCH - // Selection between and configuration of dynamic and semi-static beta-offset. If the field is absent or released, the UE applies the value 'semiStatic' and the BetaOffsets - uint8_t betaOffsets = 0; - - if (pusch_config.uci_onPusch.betaOffset_type == betaOffset_semiStatic); - - if (pusch_config.uci_onPusch.betaOffset_type == betaOffset_dynamic) betaOffsets = 2; - - // 47 DMRS_SEQ_INI - uint8_t dmrs_seq_ini_bits_ul = 0; - uint8_t dmrs_seq_ini_bits_dl = 0; - - //1 bit if both scramblingID0 and scramblingID1 are configured in DMRS-UplinkConfig - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.scramblingID0 != 0) && (dmrs_UplinkConfig.scramblingID1 != 0)) dmrs_seq_ini_bits_ul = 1; - - //1 bit if both scramblingID0 and scramblingID1 are configured in DMRS-DownlinkConfig - if ((dmrs_DownlinkConfig.scramblingID0 != 0) && (dmrs_DownlinkConfig.scramblingID0 != 0)) dmrs_seq_ini_bits_dl = 1; - - /* - * For format 2_2 - * - * This format supports power control commands for semi-persistent scheduling. - * As we can already support power control commands dynamically with formats 0_0/0_1 (TPC PUSCH) and 1_0/1_1 (TPC PUCCH) - * - * This format will be implemented in the future FIXME!!! - * - */ - // 5 BLOCK_NUMBER: The parameter tpc-PUSCH or tpc-PUCCH provided by higher layers determines the index to the block number for an UL of a cell - // The following fields are defined for each block: Closed loop indicator and TPC command - // 6 CLOSE_LOOP_IND - // 41 TPC_CMD - uint8_t tpc_cmd_bit_2_2 = 2; - /* - * For format 2_3 - * - * This format is used for power control of uplink sounding reference signals for devices which have not coupled SRS power control to the PUSCH power control - * either because independent control is desirable or because the device is configured without PUCCH and PUSCH - * - * This format will be implemented in the future FIXME!!! - * - */ - // 40 SRS_REQUEST - // 41 TPC_CMD - uint8_t tpc_cmd_bit_2_3 = 0; - uint8_t dci_field_size_table [NBR_NR_DCI_FIELDS][NBR_NR_FORMATS] = { // This table contains the number of bits for each field (row) contained in each dci format (column). - // The values of the variables indicate field sizes in number of bits - //Format0_0 Format0_1 Format1_0 Format1_1 Formats2_0/1/2/3 - { - 1, 1, (((crc_scrambled == _p_rnti) || (crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti)) ? 0:1), - 1, 0,0,0,0 - }, // 0 IDENTIFIER_DCI_FORMATS: - { - 0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), - 0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), - 0,0,0,0 - }, // 1 CARRIER_IND: 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] - {0, (sul_ind == 0)?0:1, 0, 0, 0,0,0,0}, // 2 SUL_IND_0_1: - {0, 0, 0, 0, 1,0,0,0}, // 3 SLOT_FORMAT_IND: size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213] - {0, 0, 0, 0, 0,1,0,0}, // 4 PRE_EMPTION_IND: size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits - {0, 0, 0, 0, 0,0,0,0}, // 5 BLOCK_NUMBER: starting position of a block is determined by the parameter startingBitOfFormat2_3 - {0, 0, 0, 0, 0,0,1,0}, // 6 CLOSE_LOOP_IND - { - 0, (uint8_t)ceil(log2(n_UL_BWP_RRC)), - 0, (uint8_t)ceil(log2(n_DL_BWP_RRC)), - 0,0,0,0 - }, // 7 BANDWIDTH_PART_IND: - { - 0, 0, ((crc_scrambled == _p_rnti) ? 2:0), - 0, 0,0,0,0 - }, // 8 SHORT_MESSAGE_IND 2 bits if crc scrambled with P-RNTI - { - 0, 0, ((crc_scrambled == _p_rnti) ? 8:0), - 0, 0,0,0,0 - }, // 9 SHORT_MESSAGES 8 bit8 if crc scrambled with P-RNTI - { - (uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping, - n_bits_freq_dom_res_assign_ul, - 0, 0, 0,0,0,0 - }, // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered - // (NOTE 1) If DCI format 0_0 is monitored in common search space - // and if the number of information bits in the DCI format 0_0 prior to padding - // is larger than the payload size of the DCI format 1_0 monitored in common search space - // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 - // is reduced such that the size of DCI format 0_0 equals to the size of the DCI format 1_0 - { - 0, 0, (uint8_t)ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2)), - n_bits_freq_dom_res_assign_dl, - 0,0,0,0 - }, // 11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: - { - 4, (uint8_t)log2(pusch_alloc_list), - 4, (uint8_t)log2(pdsch_alloc_list), - 0,0,0,0 - }, // 12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, - // where I the number of entries in the higher layer parameter pusch-AllocationList - { - 0, 0, 1, (((dl_res_alloc_type_0==1) &&(dl_res_alloc_type_1==0))?0:1), - 0,0,0,0 - }, // 13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0 - {0, 0, 0, prb_BundlingType_size, 0,0,0,0}, // 14 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] - {0, 0, 0, rateMatching_bits, 0,0,0,0}, // 15 RATE_MATCHING_IND: 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set - {0, 0, 0, n_zp_bits, 0,0,0,0}, // 16 ZP_CSI_RS_TRIGGER: - { - 1, (((ul_res_alloc_type_0==1) &&(ul_res_alloc_type_1==0))||(freqHopping == 0))?0:1, - 0, 0, 0,0,0,0 - }, // 17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0 - {0, 0, 0, 5, 0,0,0,0}, // 18 TB1_MCS: - {0, 0, 0, 1, 0,0,0,0}, // 19 TB1_NDI: - {0, 0, 0, 2, 0,0,0,0}, // 20 TB1_RV: - {0, 0, 0, 5, 0,0,0,0}, // 21 TB2_MCS: - {0, 0, 0, 1, 0,0,0,0}, // 22 TB2_NDI: - {0, 0, 0, 2, 0,0,0,0}, // 23 TB2_RV: - {5, 5, 5, 0, 0,0,0,0}, // 24 MCS: - {1, 1, (crc_scrambled == _c_rnti)?1:0,0, 0,0,0,0}, // 25 NDI: - { - 2, 2, (((crc_scrambled == _c_rnti) || (crc_scrambled == _si_rnti)) ? 2:0), - 0, 0,0,0,0 - }, // 26 RV: - {4, 4, (crc_scrambled == _c_rnti)?4:0,4, 0,0,0,0}, // 27 HARQ_PROCESS_NUMBER: - {0, 0, (crc_scrambled == _c_rnti)?2:0,n_dai, 0,0,0,0}, // 28 DAI: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI - // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI - // 0 otherwise - {0, codebook_HARQ_ACK, 0, 0, 0,0,0,0}, // 29 FIRST_DAI: (1 or 2 bits) 1 bit for semi-static HARQ-ACK // 2 bits for dynamic HARQ-ACK codebook with single HARQ-ACK codebook - { - 0, (((codebook_HARQ_ACK == 2) &&(n_HARQ_ACK_sub_codebooks==2))?2:0), - 0, 0, 0,0,0,0 - }, // 30 SECOND_DAI: (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks // 0 bits otherwise - { - 0, 0, (((crc_scrambled == _p_rnti) || (crc_scrambled == _ra_rnti)) ? 2:0), - 0, 0,0,0,0 - }, // 31 TB_SCALING - {2, 2, 0, 0, 0,0,0,0}, // 32 TPC_PUSCH: - {0, 0, (crc_scrambled == _c_rnti)?2:0,2, 0,0,0,0}, // 33 TPC_PUCCH: - {0, 0, (crc_scrambled == _c_rnti)?3:0,3, 0,0,0,0}, // 34 PUCCH_RESOURCE_IND: - {0, 0, (crc_scrambled == _c_rnti)?3:0,pdsch_harq_t_ind, 0,0,0,0}, // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: - {0, (uint8_t)log2(n_SRS), 0, 0, 0,0,0,0}, // 36 SRS_RESOURCE_IND: - {0, precond_nbr_layers_bits, 0, 0, 0,0,0,0}, // 37 PRECOD_NBR_LAYERS: - {0, antenna_ports_bits_ul, 0, antenna_ports_bits_dl, 0,0,0,0}, // 38 ANTENNA_PORTS: - {0, 0, 0, tci_bits, 0,0,0,0}, // 39 TCI: 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits - {0, (sul_ind == 0)?2:3, 0, (sul_ind == 0)?2:3, 0,0,0,2}, // 40 SRS_REQUEST: - { - 0, 0, 0, 0, 0,0,tpc_cmd_bit_2_2, - tpc_cmd_bit_2_3 - }, - // 41 TPC_CMD: - {0, reportTriggerSize, 0, 0, 0,0,0,0}, // 42 CSI_REQUEST: - { - 0, maxCodeBlockGroupsPerTransportBlock, - 0, maxCodeBlockGroupsPerTransportBlock_dl, - 0,0,0,0 - }, // 43 CBGTI: 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH - {0, 0, 0, cbgfi_bit, 0,0,0,0}, // 44 CBGFI: 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator - {0, ptrs_dmrs_bits, 0, 0, 0,0,0,0}, // 45 PTRS_DMRS: - {0, betaOffsets, 0, 0, 0,0,0,0}, // 46 BETA_OFFSET_IND: - {0, dmrs_seq_ini_bits_ul, 0, dmrs_seq_ini_bits_dl, 0,0,0,0}, // 47 DMRS_SEQ_INI: 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding - // is larger than the number of bits for DCI format 0_0 before padding; 0 bit otherwise - {0, 1, 0, 0, 0,0,0,0}, // 48 UL_SCH_IND: value of "1" indicates UL-SCH shall be transmitted on the PUSCH and a value of "0" indicates UL-SCH shall not be transmitted on the PUSCH - {0, 0, 0, 0, 0,0,0,0}, // 49 PADDING_NR_DCI: - // (NOTE 2) If DCI format 0_0 is monitored in common search space - // and if the number of information bits in the DCI format 0_0 prior to padding - // is less than the payload size of the DCI format 1_0 monitored in common search space - // zeros shall be appended to the DCI format 0_0 - // until the payload size equals that of the DCI format 1_0 - {(sul_ind == 0)?0:1, 0, 0, 0, 0,0,0,0}, // 50 SUL_IND_0_0: - {0, 0, 0, 0, 0,0,0,0}, // 51 RA_PREAMBLE_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - {0, 0, 0, 0, 0,0,0,0}, // 52 SUL_IND_1_0 (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - {0, 0, 0, 0, 0,0,0,0}, // 53 SS_PBCH_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - {0, 0, 0, 0, 0,0,0,0}, // 54 PRACH_MASK_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - { - 0, 0, ((crc_scrambled == _p_rnti)?6:(((crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti))?16:0)), - 0, 0,0,0,0 - } // 55 RESERVED_NR_DCI - }; - // NOTE 1: adjustments in freq_dom_resource_assignment_UL to be done if necessary - // NOTE 2: adjustments in padding to be done if necessary - uint8_t dci_size [8] = {0,0,0,0,0,0,0,0}; // will contain size for each format - - for (int i=0 ; i position in table is 2) - dci_fields_sizes[j][i] = dci_field_size_table[j][i]; // dci_fields_sizes[j] contains the sizes of each field (j) for a determined format i - //} - } - - LOG_DDD("(nr_dci_format_size) dci_size[%d]=%d for n_RB_ULBWP=%d\n", - i,dci_size[i],n_RB_ULBWP); - } - - LOG_DDD("(nr_dci_format_size) dci_fields_sizes[][] = { \n"); - -#ifdef NR_PDCCH_DCI_DEBUG - for (int j=0; j dci_size[2])) { - dci_field_size_table[SUL_IND_0_0][0] = 0; - dci_size[0]=dci_size[0]-1; - } - - // if ((format == format0_0) || (format == format1_0)) { - // According to Section 7.3.1.1.1 in TS 38.212 - // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding - // is less than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, - // zeros shall be appended to the DCI format 0_0 until the payload size equals that of the DCI format 1_0. - if (dci_size[0] < dci_size[2]) { // '0' corresponding to index for format0_0 and '2' corresponding to index of format1_0 - //if (format == format0_0) { - dci_fields_sizes[PADDING_NR_DCI][0] = dci_size[2] - dci_size[0]; - dci_size[0] = dci_size[2]; - LOG_DDD("(nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); - //} - } - - // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding - // is larger than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, - // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 is reduced - // such that the size of DCI format 0_0 equals to the size of the DCI format 1_0.. - if (dci_size[0] > dci_size[2]) { - //if (format == format0_0) { - dci_fields_sizes[FREQ_DOM_RESOURCE_ASSIGNMENT_UL][0] -= (dci_size[0] - dci_size[2]); - dci_size[0] = dci_size[2]; - LOG_DDD("(nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); - //} - } - - /* - * TS 38.212 subclause 7.3.1.1.2 - * For a UE configured with SUL in a cell: - * if PUSCH is configured to be transmitted on both the SUL and the non-SUL of the cell and - * if the number of information bits in format 0_1 for the SUL - * is not equal to the number of information bits in format 0_1 for the non-SUL, - * zeros shall be appended to smaller format 0_1 until the payload size equals that of the larger format 0_1 - * - * Not implemented. FIXME!!! - * - */ - // } - LOG_DDD("(nr_dci_format_size) dci_fields_sizes[][] = { \n"); - -#ifdef NR_PDCCH_DCI_DEBUG - for (int j=0; jnumber_rbs = NRRIV2BW(riv,n_RB_DLBWP); dlsch_config_pdu->start_rb = NRRIV2PRBOFFSET(riv,n_RB_DLBWP); + // Sanity check in case a false or erroneous DCI is received + if ((dlsch_config_pdu->number_rbs < 1 ) || (dlsch_config_pdu->number_rbs > n_RB_DLBWP - dlsch_config_pdu->start_rb)) { + // DCI is invalid! + LOG_W(MAC, "Frequency domain assignment values are invalid! #RBs: %d, Start RB: %d, n_RB_DLBWP: %d \n", dlsch_config_pdu->number_rbs, dlsch_config_pdu->start_rb, n_RB_DLBWP); + return -1; + } + + LOG_D(MAC,"DLSCH riv = %i\n", riv); + LOG_D(MAC,"DLSCH n_RB_DLBWP = %i\n", n_RB_DLBWP); + LOG_D(MAC,"DLSCH number_rbs = %i\n", dlsch_config_pdu->number_rbs); + LOG_D(MAC,"DLSCH start_rb = %i\n", dlsch_config_pdu->start_rb); + } if(pusch_config_pdu != NULL){ /* @@ -2090,92 +450,37 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p pusch_config_pdu->rb_size = NRRIV2BW(riv,n_RB_ULBWP); pusch_config_pdu->rb_start = NRRIV2PRBOFFSET(riv,n_RB_ULBWP); + + // Sanity check in case a false or erroneous DCI is received + if ((pusch_config_pdu->rb_size < 1) || (pusch_config_pdu->rb_size > n_RB_ULBWP - pusch_config_pdu->rb_start)) { + // DCI is invalid! + LOG_W(MAC, "Frequency domain assignment values are invalid! #RBs: %d, Start RB: %d, n_RB_ULBWP: %d \n",pusch_config_pdu->rb_size, pusch_config_pdu->rb_start, n_RB_ULBWP); + return -1; + } + LOG_D(MAC,"ULSCH riv = %i\n", riv); + LOG_D(MAC,"ULSCH n_RB_DLBWP = %i\n", n_RB_ULBWP); + LOG_D(MAC,"ULSCH number_rbs = %i\n", pusch_config_pdu->rb_size); + LOG_D(MAC,"ULSCH start_rb = %i\n", pusch_config_pdu->rb_start); } return 0; } int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList, + NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, - uint8_t time_domain_ind - ){ - int dmrs_typeA_pos = mac->scc->dmrs_TypeA_Position; - uint8_t k_offset=0; - uint8_t sliv_S=0; - uint8_t sliv_L=0; - uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?12:11}, // row index 1 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?10:9}, // row index 2 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?9:8}, // row index 3 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?7:6}, // row index 4 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?5:4}, // row index 5 - {0,(dmrs_typeA_pos == 0)?9:10,(dmrs_typeA_pos == 0)?4:4}, // row index 6 - {0,(dmrs_typeA_pos == 0)?4:6, (dmrs_typeA_pos == 0)?4:4}, // row index 7 - {0,5,7}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,12,2}, // row index 11 - {0,1,13}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,7}, // row index 15 - {0,8,4} // row index 16 - }; - /*uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?6:5}, // row index 1 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?10:9}, // row index 2 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?9:8}, // row index 3 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?7:6}, // row index 4 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?5:4}, // row index 5 - {0,(dmrs_typeA_pos == 0)?6:8, (dmrs_typeA_pos == 0)?4:2}, // row index 6 - {0,(dmrs_typeA_pos == 0)?4:6, (dmrs_typeA_pos == 0)?4:4}, // row index 7 - {0,5,6}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,10,2}, // row index 11 - {0,1,11}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,6}, // row index 15 - {0,8,4} // row index 16 - };*/ - /*uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,2,2}, // row index 1 - {0,4,2}, // row index 2 - {0,6,2}, // row index 3 - {0,8,2}, // row index 4 - {0,10,2}, // row index 5 - {1,2,2}, // row index 6 - {1,4,2}, // row index 7 - {0,2,4}, // row index 8 - {0,4,4}, // row index 9 - {0,6,4}, // row index 10 - {0,8,4}, // row index 11 - {0,10,4}, // row index 12 - {0,2,7}, // row index 13 - {0,(dmrs_typeA_pos == 0)?2:3,(dmrs_typeA_pos == 0)?12:11}, // row index 14 - {1,2,4}, // row index 15 - {0,0,0} // row index 16 - };*/ - /*uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,2,2}, // row index 1 - {0,4,2}, // row index 2 - {0,6,2}, // row index 3 - {0,8,2}, // row index 4 - {0,10,2}, // row index 5 - {0,0,0}, // row index 6 - {0,0,0}, // row index 7 - {0,2,4}, // row index 8 - {0,4,4}, // row index 9 - {0,6,4}, // row index 10 - {0,8,4}, // row index 11 - {0,10,4}, // row index 12 - {0,2,7}, // row index 13 - {0,(dmrs_typeA_pos == 0)?2:3,(dmrs_typeA_pos == 0)?12:11}, // row index 14 - {0,0,6}, // row index 15 - {0,2,6} // row index 16 - };*/ + uint8_t time_domain_ind, + int default_abc, + bool use_default){ + + int dmrs_typeA_pos = (mac->scc != NULL) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position; + +// uint8_t k_offset=0; + int sliv_S=0; + int sliv_L=0; uint8_t mu_pusch = 1; + // definition table j Table 6.1.2.1.1-4 uint8_t j = (mu_pusch==3)?3:(mu_pusch==2)?2:1; uint8_t table_6_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PUSCH from TS 38.214 subclause 6.1.2.1.1 @@ -2219,12 +524,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, * TS 38.214 subclause 5.1.2.1 Resource allocation in time domain (downlink) */ if(dlsch_config_pdu != NULL){ - NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = NULL; - if (mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList) - pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList->choice.setup; - else if (mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList) - pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; - if (pdsch_TimeDomainAllocationList) { + if (pdsch_TimeDomainAllocationList && use_default==false) { if (time_domain_ind >= pdsch_TimeDomainAllocationList->list.count) { LOG_E(MAC, "time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n", @@ -2239,20 +539,21 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, SLIV2SL(startSymbolAndLength,&S,&L); dlsch_config_pdu->start_symbol=S; dlsch_config_pdu->number_symbols=L; + + LOG_D(MAC,"SLIV = %i\n", startSymbolAndLength); + LOG_D(MAC,"start_symbol = %i\n", dlsch_config_pdu->start_symbol); + LOG_D(MAC,"number_symbols = %i\n", dlsch_config_pdu->number_symbols); + } else {// Default configuration from tables - k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; - sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1]; - sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2]; - // k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; - // sliv_S = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1]; - // sliv_L = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2]; - // k_offset = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][0]; - // sliv_S = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][1]; - // sliv_L = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][2]; - // k_offset = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][0]; - // sliv_S = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][1]; - // sliv_L = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][2]; + + get_info_from_tda_tables(default_abc, + time_domain_ind, + dmrs_typeA_pos, + 1, // normal CP + &sliv_S, + &sliv_L); + dlsch_config_pdu->number_symbols = sliv_L; dlsch_config_pdu->start_symbol = sliv_S; } @@ -2260,14 +561,16 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, * TS 38.214 subclause 6.1.2.1 Resource allocation in time domain (uplink) */ if(pusch_config_pdu != NULL){ - NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL; - if (mac->ULbwp[0]->bwp_Dedicated->pusch_Config) - pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList->choice.setup; - - if (pusch_TimeDomainAllocationList) { - AssertFatal(pusch_TimeDomainAllocationList->list.count > time_domain_ind, - "time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n", - time_domain_ind,pusch_TimeDomainAllocationList->list.count); + if (pusch_TimeDomainAllocationList && use_default==false) { + if (time_domain_ind >= pusch_TimeDomainAllocationList->list.count) { + LOG_E(MAC, "time_domain_ind %d >= pusch->TimeDomainAllocationList->list.count %d\n", + time_domain_ind, pusch_TimeDomainAllocationList->list.count); + pusch_config_pdu->start_symbol_index=0; + pusch_config_pdu->nr_of_symbols=0; + return -1; + } + + LOG_D(NR_MAC,"Filling Time-Domain Allocation from pusch_TimeDomainAllocationList\n"); int startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[time_domain_ind]->startSymbolAndLength; int S,L; SLIV2SL(startSymbolAndLength,&S,&L); @@ -2275,51 +578,64 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, pusch_config_pdu->nr_of_symbols=L; } else { - k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; - sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1]; - sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2]; + LOG_D(NR_MAC,"Filling Time-Domain Allocation from tables\n"); +// k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; + sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind][1]; + sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind][2]; // k_offset = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; // sliv_S = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1]; // sliv_L = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2]; pusch_config_pdu->nr_of_symbols = sliv_L; pusch_config_pdu->start_symbol_index = sliv_S; } + LOG_D(NR_MAC,"start_symbol = %i\n", pusch_config_pdu->start_symbol_index); + LOG_D(NR_MAC,"number_symbols = %i\n", pusch_config_pdu->nr_of_symbols); } return 0; } -////////////// -int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_index,fapi_nr_dci_indication_pdu_t *dci) { + +int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format]; LOG_D(MAC,"Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", dci->rnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits); - - nr_extract_dci_info(mac,dci->dci_format,dci->payloadSize,dci->rnti,(uint64_t *)dci->payloadBits,def_dci_pdu_rel15); - return (nr_ue_process_dci(module_id, cc_id, gNB_index, def_dci_pdu_rel15, dci->rnti, dci->dci_format)); + int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15); + if ((ret&1) == 1) return -1; + else if (ret == 2) { + dci->dci_format = NR_UL_DCI_FORMAT_0_0; + def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format]; + } + int8_t ret_proc = nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci); + memset(def_dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t)); + return ret_proc; } -int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dci_pdu_rel15_t *dci, uint16_t rnti, uint32_t dci_format){ - - int bwp_id = 1; +int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind) { + uint16_t rnti = dci_ind->rnti; + uint8_t dci_format = dci_ind->dci_format; + int ret = 0; + int pucch_res_set_cnt = 0, valid = 0; + frame_t frame_tx = 0; + int slot_tx = 0; + bool valid_ptrs_setup = 0; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + RA_config_t *ra = &mac->ra; fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; - - //const uint16_t n_RB_DLBWP = dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP; //make sure this has been set - AssertFatal(mac->DLbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); - AssertFatal(mac->ULbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); + uint8_t is_Msg3 = 0; + int default_abc = 1; - const uint16_t n_RB_DLBWP = (mac->ra_state == WAIT_RAR) ? NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275) : NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); - const uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); + uint16_t n_RB_DLBWP; + if (mac->DLbwp[0]) n_RB_DLBWP = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + else if (mac->scc_SIB) n_RB_DLBWP = NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + else n_RB_DLBWP = mac->type0_PDCCH_CSS_config.num_rbs; - LOG_D(MAC,"nr_ue_process_dci at MAC layer with dci_format=%d (DL BWP %d, UL BWP %d)\n",dci_format,n_RB_DLBWP,n_RB_ULBWP); - - NR_PDSCH_Config_t *pdsch_config=mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup; + LOG_D(MAC, "In %s: Processing received DCI format %s (DL BWP %d)\n", __FUNCTION__, dci_formats[dci_format], n_RB_DLBWP); switch(dci_format){ - case NR_UL_DCI_FORMAT_0_0: + case NR_UL_DCI_FORMAT_0_0: { /* * with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI * 0 IDENTIFIER_DCI_FORMATS: @@ -2334,48 +650,39 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc * 49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space * 50 SUL_IND_0_0: */ - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rnti = rnti; - nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu_0_0 = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; - /* IDENTIFIER_DCI_FORMATS */ - /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ - nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val); - /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_0,NULL,dci->time_domain_assignment.val) < 0) - break; - /* FREQ_HOPPING_FLAG */ - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) - pusch_config_pdu_0_0->frequency_hopping = dci->frequency_hopping_flag.val; + // Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, + // where K2 is the offset between the slot in which UL DCI is received and the slot + // in which ULSCH should be scheduled. K2 is configured in RRC configuration. + // todo: + // - SUL_IND_0_0 - /* MCS */ - pusch_config_pdu_0_0->mcs_index = dci->mcs; - /* NDI */ - pusch_config_pdu_0_0->pusch_data.new_data_indicator = dci->ndi; - /* RV */ - pusch_config_pdu_0_0->pusch_data.rv_index = dci->rv; - /* HARQ_PROCESS_NUMBER */ - pusch_config_pdu_0_0->pusch_data.harq_process_id = dci->harq_pid; - /* TPC_PUSCH */ - // according to TS 38.213 Table Table 7.1.1-1 - if (dci->tpc == 0) { - pusch_config_pdu_0_0->absolute_delta_PUSCH = -4; - } - if (dci->tpc == 1) { - pusch_config_pdu_0_0->absolute_delta_PUSCH = -1; - } - if (dci->tpc == 2) { - pusch_config_pdu_0_0->absolute_delta_PUSCH = 1; - } - if (dci->tpc == 3) { - pusch_config_pdu_0_0->absolute_delta_PUSCH = 4; - } - /* SUL_IND_0_0 */ // To be implemented, FIXME!!! + // Schedule PUSCH + ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, dci->time_domain_assignment.val); - ul_config->number_pdus = ul_config->number_pdus + 1; + if (ret != -1){ + + // Get UL config request corresponding slot_tx + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx); + + if (!ul_config) { + LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot); + return -1; + } + pthread_mutex_lock(&ul_config->mutex_ul_config); + AssertFatal(ul_config->number_pdusnumber_pdus %d out of bounds\n",ul_config->number_pdus); + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; + + fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + pthread_mutex_unlock(&ul_config->mutex_ul_config); + + // Config PUSCH PDU + ret = nr_config_pusch_pdu(mac, pusch_config_pdu, dci, NULL, rnti, &dci_format); + } + break; + } - case NR_UL_DCI_FORMAT_0_1: + case NR_UL_DCI_FORMAT_0_1: { /* * with CRC scrambled by C-RNTI or CS-RNTI or SP-CSI-RNTI or new-RNTI * 0 IDENTIFIER_DCI_FORMATS: @@ -2404,287 +711,38 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc * 48 UL_SCH_IND * 49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space */ - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rnti = rnti; - nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu_0_1 = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; - /* IDENTIFIER_DCI_FORMATS */ - /* CARRIER_IND */ - /* SUL_IND_0_1 */ - /* BANDWIDTH_PART_IND */ - //pusch_config_pdu_0_1->bandwidth_part_ind = dci->bwp_indicator.val; - /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ - nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val); - /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,dci->time_domain_assignment.val) < 0) - break; - /* FREQ_HOPPING_FLAG */ - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) - pusch_config_pdu_0_1->frequency_hopping = dci->frequency_hopping_flag.val; - /* MCS */ - pusch_config_pdu_0_1->mcs_index = dci->mcs; - /* NDI */ - pusch_config_pdu_0_1->pusch_data.new_data_indicator = dci->ndi; - /* RV */ - pusch_config_pdu_0_1->pusch_data.rv_index = dci->rv; - /* HARQ_PROCESS_NUMBER */ - pusch_config_pdu_0_1->pusch_data.harq_process_id = dci->harq_pid; - /* FIRST_DAI */ //To be implemented, FIXME!!! - /* SECOND_DAI */ //To be implemented, FIXME!!! - /* TPC_PUSCH */ - // according to TS 38.213 Table Table 7.1.1-1 - if (dci->tpc == 0) { - pusch_config_pdu_0_1->absolute_delta_PUSCH = -4; - } - if (dci->tpc == 1) { - pusch_config_pdu_0_1->absolute_delta_PUSCH = -1; - } - if (dci->tpc == 2) { - pusch_config_pdu_0_1->absolute_delta_PUSCH = 1; - } - if (dci->tpc == 3) { - pusch_config_pdu_0_1->absolute_delta_PUSCH = 4; - } - /* SRS_RESOURCE_IND */ - //FIXME!! - /* PRECOD_NBR_LAYERS */ - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.tx_config == tx_config_nonCodebook)); - // 0 bits if the higher layer parameter txConfig = nonCodeBook - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.tx_config == tx_config_codebook)){ - uint8_t n_antenna_port = 0; //FIXME!!! - if (n_antenna_port == 1); // 1 antenna port and the higher layer parameter txConfig = codebook 0 bits - if (n_antenna_port == 4){ // 4 antenna port and the higher layer parameter txConfig = codebook - // Table 7.3.1.1.2-2: transformPrecoder=disabled and maxRank = 2 or 3 or 4 - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) - && ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 2) || - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 3) || - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 4))){ - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][0]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][1]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_partialAndNonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][2]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][3]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_nonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][4]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][5]; - } - } - // Table 7.3.1.1.2-3: transformPrecoder= enabled, or transformPrecoder=disabled and maxRank = 1 - if (((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) - || (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled)) - && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 1)){ - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][6]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][7]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_partialAndNonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][8]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][9]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_nonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][10]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][11]; - } - } - } - if (n_antenna_port == 4){ // 2 antenna port and the higher layer parameter txConfig = codebook - // Table 7.3.1.1.2-4: transformPrecoder=disabled and maxRank = 2 - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) - && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 2)){ - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][12]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][13]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_nonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][14]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][15]; - } - } - // Table 7.3.1.1.2-5: transformPrecoder= enabled, or transformPrecoder= disabled and maxRank = 1 - if (((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) - || (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled)) - && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 1)){ - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][16]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][17]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_nonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][18]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][19]; - } - } - } - } - /* ANTENNA_PORTS */ - uint8_t rank=0; // We need to initialize rank FIXME!!! - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-6 - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = dci->antenna_ports.val; //TBC - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-7 - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = (dci->antenna_ports.val > 3)?(dci->antenna_ports.val-4):(dci->antenna_ports.val); //TBC - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports > 3)?2:1; //FIXME - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-8/9/10/11 - if (rank == 1){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC - pusch_config_pdu_0_1->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val-2):(dci->antenna_ports.val); //TBC - } - if (rank == 2){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?2:1; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = (dci->antenna_ports > 1)?(dci->antenna_ports > 2 ?0:2):0; - //pusch_config_pdu_0_1->dmrs_ports[1] = (dci->antenna_ports > 1)?(dci->antenna_ports > 2 ?2:3):1; - } - if (rank == 3){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = 0; - //pusch_config_pdu_0_1->dmrs_ports[1] = 1; - //pusch_config_pdu_0_1->dmrs_ports[2] = 2; - } - if (rank == 4){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = 0; - //pusch_config_pdu_0_1->dmrs_ports[1] = 1; - //pusch_config_pdu_0_1->dmrs_ports[2] = 2; - //pusch_config_pdu_0_1->dmrs_ports[3] = 3; - } - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-12/13/14/15 - if (rank == 1){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC - pusch_config_pdu_0_1->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val > 5 ?(dci->antenna_ports.val-6):(dci->antenna_ports.val-2)):dci->antenna_ports.val; //TBC - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports.val > 6)?2:1; //FIXME - } - if (rank == 2){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?2:1; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_13[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_13[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports.val > 3)?2:1; // FIXME - } - if (rank == 3){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_14[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_14[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_14[dci->antenna_ports.val][3]; - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports.val > 1)?2:1; //FIXME - } - if (rank == 4){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_15[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_15[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_15[dci->antenna_ports.val][3]; - //pusch_config_pdu_0_1->dmrs_ports[3] = table_7_3_1_1_2_15[dci->antenna_ports.val][4]; - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports.val > 1)?2:1; //FIXME - } - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 2) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-16/17/18/19 - if (rank == 1){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?((dci->antenna_ports.val > 5)?3:2):1; //TBC - pusch_config_pdu_0_1->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val > 5 ?(dci->antenna_ports.val-6):(dci->antenna_ports.val-2)):dci->antenna_ports.val; //TBC - } - if (rank == 2){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?((dci->antenna_ports.val > 2)?3:2):1; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_17[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_17[dci->antenna_ports.val][2]; - } - if (rank == 3){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?3:2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_18[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_18[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_18[dci->antenna_ports.val][3]; - } - if (rank == 4){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = dci->antenna_ports.val + 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = 0; - //pusch_config_pdu_0_1->dmrs_ports[1] = 1; - //pusch_config_pdu_0_1->dmrs_ports[2] = 2; - //pusch_config_pdu_0_1->dmrs_ports[3] = 3; - } - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 2) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-20/21/22/23 - if (rank == 1){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_20[dci->antenna_ports.val][0]; //TBC - pusch_config_pdu_0_1->dmrs_ports = table_7_3_1_1_2_20[dci->antenna_ports.val][1]; //TBC - //pusch_config_pdu_0_1->n_front_load_symb = table_7_3_1_1_2_20[dci->antenna_ports.val][2]; //FIXME - } - if (rank == 2){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_21[dci->antenna_ports.val][0]; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_21[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_21[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->n_front_load_symb = table_7_3_1_1_2_21[dci->antenna_ports.val][3]; //FIXME - } - if (rank == 3){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_22[dci->antenna_ports.val][0]; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_22[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_22[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_22[dci->antenna_ports.val][3]; - //pusch_config_pdu_0_1->n_front_load_symb = table_7_3_1_1_2_22[dci->antenna_ports.val][4]; //FIXME - } - if (rank == 4){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_23[dci->antenna_ports.val][0]; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_23[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_23[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_23[dci->antenna_ports.val][3]; - //pusch_config_pdu_0_1->dmrs_ports[3] = table_7_3_1_1_2_23[dci->antenna_ports.val][4]; - //pusch_config_pdu_0_1->n_front_load_symb = table_7_3_1_1_2_23[dci->antenna_ports.val][5]; //FIXME - } - } - /* SRS_REQUEST */ - // if SUL is supported in the cell, there is an additional bit in thsi field and the value of this bit represents table 7.1.1.1-1 TS 38.212 FIXME!!! - //pusch_config_pdu_0_1->srs_config.aperiodicSRS_ResourceTrigger = (dci->srs_request.val & 0x11); // as per Table 7.3.1.1.2-24 TS 38.212 //FIXME - /* CSI_REQUEST */ - //pusch_config_pdu_0_1->csi_reportTriggerSize = dci->csi_request.val; //FIXME - /* CBGTI */ - //pusch_config_pdu_0_1->maxCodeBlockGroupsPerTransportBlock = dci->cbgti.val; //FIXME - /* PTRS_DMRS */ - if (((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.ptrs_uplink_config == 0)) || - ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 1))){ - } else { - //pusch_config_pdu_0_1->ptrs_dmrs_association_port = dci->ptrs_dmrs_association.val; //FIXME - } - /* BETA_OFFSET_IND */ - // Table 9.3-3 in [5, TS 38.213] - //pusch_config_pdu_0_1->beta_offset_ind = dci->beta_offset_indicator.val; //FIXME - /* DMRS_SEQ_INI */ - // FIXME!! - /* UL_SCH_IND */ - // A value of "1" indicates UL-SCH shall be transmitted on the PUSCH and - // a value of "0" indicates UL-SCH shall not be transmitted on the PUSCH + // TODO: + // - FIRST_DAI + // - SECOND_DAI + // - SRS_RESOURCE_IND - ul_config->number_pdus = ul_config->number_pdus + 1; + // Schedule PUSCH + ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, dci->time_domain_assignment.val); + + if (ret != -1){ + + // Get UL config request corresponding slot_tx + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx); + + if (!ul_config) { + LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot); + return -1; + } + + pthread_mutex_lock(&ul_config->mutex_ul_config); + AssertFatal(ul_config->number_pdusnumber_pdus %d out of bounds\n",ul_config->number_pdus); + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; + + fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + pthread_mutex_unlock(&ul_config->mutex_ul_config); + + // Config PUSCH PDU + ret = nr_config_pusch_pdu(mac, pusch_config_pdu, dci, NULL, rnti, &dci_format); + } else AssertFatal(1==0,"Cannot schedule PUSCH\n"); break; + } - case NR_DL_DCI_FORMAT_1_0: + case NR_DL_DCI_FORMAT_1_0: { /* * with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI * 0 IDENTIFIER_DCI_FORMATS: @@ -2737,22 +795,85 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc */ dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti; - //fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config_pdu_1_0 = dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_0 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; - dlsch_config_pdu_1_0->BWPSize = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); - dlsch_config_pdu_1_0->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); - dlsch_config_pdu_1_0->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; + + NR_PDSCH_Config_t *pdsch_config= (mac->DLbwp[0]) ? mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup : NULL; + int is_common=0; + if(rnti == SI_RNTI) { + NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config = mac->type0_PDCCH_CSS_config; + default_abc = type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern; + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH; + dlsch_config_pdu_1_0->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs; + dlsch_config_pdu_1_0->BWPStart = mac->type0_PDCCH_CSS_config.cset_start_rb; + dlsch_config_pdu_1_0->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon; + if (pdsch_config) pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL; // For PDSCH with mapping type A, the UE shall assume dmrs-AdditionalPosition='pos2' + } else { + if (ra->RA_window_cnt >= 0 && rnti == ra->ra_rnti){ + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; + } else { + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; + } + if( (ra->RA_window_cnt >= 0 && rnti == ra->ra_rnti) || (rnti == ra->t_crnti) ) { + if (mac->scc == NULL) { // use coreset0 + dlsch_config_pdu_1_0->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs; + dlsch_config_pdu_1_0->BWPStart = mac->type0_PDCCH_CSS_config.cset_start_rb; + is_common=1; + } + else { + dlsch_config_pdu_1_0->BWPSize = NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_0->BWPStart = NRRIV2PRBOFFSET(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } + if (!get_softmodem_params()->sa) { // NSA mode is not using the Initial BWP + dlsch_config_pdu_1_0->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pdsch_config = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup; + } + } else if (mac->DLbwp[0]) { + dlsch_config_pdu_1_0->BWPSize = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_0->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_0->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; + pdsch_config = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup; + } else if (mac->scc_SIB) { + dlsch_config_pdu_1_0->BWPSize = NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_0->BWPStart = NRRIV2PRBOFFSET(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_0->SubcarrierSpacing = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.subcarrierSpacing; + pdsch_config = NULL; + } + } + /* IDENTIFIER_DCI_FORMATS */ /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ - nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->frequency_domain_assignment.val); + if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,dlsch_config_pdu_1_0->BWPSize,dci->frequency_domain_assignment.val) < 0) { + LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); + return -1; + } + + + NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = NULL; + if (mac->DLbwp[0] && + mac->DLbwp[0]->bwp_Dedicated && + mac->DLbwp[0]->bwp_Dedicated->pdsch_Config && + mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList) + pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList->choice.setup; + else if (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList) + pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + else if (mac->scc_SIB && mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup) + pdsch_TimeDomainAllocationList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0) - break; + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,pdsch_TimeDomainAllocationList,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val,default_abc,rnti==SI_RNTI) < 0) { + LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); + return -1; + } + int mappingtype = pdsch_TimeDomainAllocationList ? pdsch_TimeDomainAllocationList->list.array[dci->time_domain_assignment.val]->mappingType : ((dlsch_config_pdu_1_0->start_symbol <= 3)? typeA: typeB); + /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, - mac->scc->dmrs_TypeA_Position, - dlsch_config_pdu_1_0->number_symbols); - dlsch_config_pdu_1_0->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + mac->mib->dmrs_TypeA_Position, + dlsch_config_pdu_1_0->number_symbols, + dlsch_config_pdu_1_0->start_symbol, + mappingtype); + dlsch_config_pdu_1_0->dmrsConfigType = (mac->DLbwp[0] != NULL) ? + (mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1) : 0; /* number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214 version 15.9.0 Release 15 */ if (dlsch_config_pdu_1_0->number_symbols == 2) dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 1; @@ -2760,16 +881,21 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 2; /* VRB_TO_PRB_MAPPING */ dlsch_config_pdu_1_0->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; + /* MCS TABLE INDEX */ + dlsch_config_pdu_1_0->mcs_table = (pdsch_config) ? ((pdsch_config->mcs_Table) ? (*pdsch_config->mcs_Table + 1) : 0) : 0; /* MCS */ dlsch_config_pdu_1_0->mcs = dci->mcs; + // Basic sanity check for MCS value to check for a false or erroneous DCI + if (dlsch_config_pdu_1_0->mcs > 28) { + LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_0->mcs); + return -1; + } /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ dlsch_config_pdu_1_0->ndi = dci->ndi; /* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ dlsch_config_pdu_1_0->rv = dci->rv; /* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ dlsch_config_pdu_1_0->harq_process_nbr = dci->harq_pid; - /* DAI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ - dlsch_config_pdu_1_0->dai = dci->dai[0].val; /* TB_SCALING (only if CRC scrambled by P-RNTI or RA-RNTI) */ // according to TS 38.214 Table 5.1.3.2-3 if (dci->tb_scaling == 0) dlsch_config_pdu_1_0->scaling_factor_S = 1; @@ -2782,18 +908,54 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc if (dci->tpc == 1) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 0; if (dci->tpc == 2) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 1; if (dci->tpc == 3) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 3; - /* PUCCH_RESOURCE_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/ - //if (dci->pucch_resource_indicator == 0) dlsch_config_pdu_1_0->pucch_resource_id = 1; //pucch-ResourceId obtained from the 1st value of resourceList FIXME!!! - //if (dci->pucch_resource_indicator == 1) dlsch_config_pdu_1_0->pucch_resource_id = 2; //pucch-ResourceId obtained from the 2nd value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 2) dlsch_config_pdu_1_0->pucch_resource_id = 3; //pucch-ResourceId obtained from the 3rd value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 3) dlsch_config_pdu_1_0->pucch_resource_id = 4; //pucch-ResourceId obtained from the 4th value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 4) dlsch_config_pdu_1_0->pucch_resource_id = 5; //pucch-ResourceId obtained from the 5th value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 5) dlsch_config_pdu_1_0->pucch_resource_id = 6; //pucch-ResourceId obtained from the 6th value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 6) dlsch_config_pdu_1_0->pucch_resource_id = 7; //pucch-ResourceId obtained from the 7th value of resourceList FIXME!! - //if (dci->pucch_resource_indicator == 7) dlsch_config_pdu_1_0->pucch_resource_id = 8; //pucch-ResourceId obtained from the 8th value of resourceList FIXME!! - dlsch_config_pdu_1_0->pucch_resource_id = dci->pucch_resource_indicator; - /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/ - dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind = dci->pdsch_to_harq_feedback_timing_indicator.val; + // Sanity check for pucch_resource_indicator value received to check for false DCI. + valid = 0; + if (mac->ULbwp[0] && + mac->ULbwp[0]->bwp_Dedicated && + mac->ULbwp[0]->bwp_Dedicated->pucch_Config && + mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup&& + mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList) { + pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count; + for (int id = 0; id < pucch_res_set_cnt; id++) { + if (dci->pucch_resource_indicator < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + valid = 1; + break; + } + } + } + else if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList){ + pucch_res_set_cnt = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.count; + for (int id = 0; id < pucch_res_set_cnt; id++) { + if (dci->pucch_resource_indicator < mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + valid = 1; + break; + } + } + } else valid=1; + if (!valid) { + LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dci->pucch_resource_indicator); + return -1; + } + + if(rnti != ra->ra_rnti && rnti != SI_RNTI) + AssertFatal(1+dci->pdsch_to_harq_feedback_timing_indicator.val>=DURATION_RX_TO_TX,"PDSCH to HARQ feedback time (%d) cannot be less than DURATION_RX_TO_TX (%d).\n", + 1+dci->pdsch_to_harq_feedback_timing_indicator.val,DURATION_RX_TO_TX); + + // set the harq status at MAC for feedback + set_harq_status(mac,dci->pucch_resource_indicator, + dci->harq_pid, + dlsch_config_pdu_1_0->accumulated_delta_PUCCH, + 1+dci->pdsch_to_harq_feedback_timing_indicator.val, + dci->dai[0].val, + dci_ind->n_CCE,dci_ind->N_CCE,is_common, + frame,slot); LOG_D(MAC,"(nr_ue_procedures.c) rnti = %x dl_config->number_pdus = %d\n", dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti, @@ -2812,26 +974,22 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_0->ndi, dlsch_config_pdu_1_0->rv, dlsch_config_pdu_1_0->harq_process_nbr, - dlsch_config_pdu_1_0->dai, + dci->dai[0].val, dlsch_config_pdu_1_0->scaling_factor_S, dlsch_config_pdu_1_0->accumulated_delta_PUCCH, - dlsch_config_pdu_1_0->pucch_resource_id, - dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind); - - if (mac->RA_window_cnt >= 0 && rnti == mac->ra_rnti){ - dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; - } else { - dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; - } + dci->pucch_resource_indicator, + 1+dci->pdsch_to_harq_feedback_timing_indicator.val); // dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = n_RB_DLBWP; LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); dl_config->number_pdus = dl_config->number_pdus + 1; - break; - case NR_DL_DCI_FORMAT_1_1: + break; + } + + case NR_DL_DCI_FORMAT_1_1: { /* * with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI * 0 IDENTIFIER_DCI_FORMATS: @@ -2861,28 +1019,63 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc * 44 CBGFI: * 47 DMRS_SEQ_INI: */ + + if (dci->bwp_indicator.val > 1) { + LOG_W(NR_MAC,"[%d.%d] bwp_indicator %d > 1 Possibly due to false DCI. Ignoring DCI!\n", frame, slot,dci->bwp_indicator.val); + return -1; + } + config_bwp_ue(mac, &dci->bwp_indicator.val, &dci_format); + NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id; + NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; + NR_PDSCH_Config_t *pdsch_Config=NULL; + NR_BWP_DownlinkDedicated_t *bwpd=NULL; + NR_BWP_DownlinkCommon_t *bwpc=NULL; + NR_BWP_UplinkDedicated_t *ubwpd=NULL; + NR_BWP_UplinkCommon_t *ubwpc=NULL; + get_bwp_info(mac,dl_bwp_id,ul_bwp_id,&bwpd,&bwpc,&ubwpd,&ubwpc); + + pdsch_Config = bwpd->pdsch_Config->choice.setup; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti; + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_1 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; + + dlsch_config_pdu_1_1->BWPSize = NRRIV2BW(bwpc->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_1->BWPStart = NRRIV2PRBOFFSET(bwpc->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_1->SubcarrierSpacing = bwpc->genericParameters.subcarrierSpacing; + /* IDENTIFIER_DCI_FORMATS */ /* CARRIER_IND */ /* BANDWIDTH_PART_IND */ // dlsch_config_pdu_1_1->bandwidth_part_ind = dci->bandwidth_part_ind; /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ - nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val); + if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val) < 0) { + LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); + return -1; + } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0) - break; + NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = choose_dl_tda_list(pdsch_Config,bwpc->pdsch_ConfigCommon->choice.setup); + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,pdsch_TimeDomainAllocationList,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val,0,false) < 0) { + LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); + return -1; + } + + int mappingtype = pdsch_TimeDomainAllocationList ? pdsch_TimeDomainAllocationList->list.array[dci->time_domain_assignment.val]->mappingType : ((dlsch_config_pdu_1_1->start_symbol <= 3)? typeA: typeB); + /* dmrs symbol positions*/ - dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, - mac->scc->dmrs_TypeA_Position, - dlsch_config_pdu_1_1->number_symbols); - dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_Config, + mac->scc? mac->scc->dmrs_TypeA_Position:mac->mib->dmrs_TypeA_Position, + dlsch_config_pdu_1_1->number_symbols, + dlsch_config_pdu_1_1->start_symbol, + mappingtype); + + dlsch_config_pdu_1_1->dmrsConfigType = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? NFAPI_NR_DMRS_TYPE1 : NFAPI_NR_DMRS_TYPE2; + /* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214, using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */ dlsch_config_pdu_1_1->n_dmrs_cdm_groups = 1; /* VRB_TO_PRB_MAPPING */ - if (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.resource_allocation != 0) + if ((pdsch_Config->resourceAllocation == 1) && (pdsch_Config->vrb_ToPRB_Interleaver != NULL)) dlsch_config_pdu_1_1->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; /* PRB_BUNDLING_SIZE_IND */ dlsch_config_pdu_1_1->prb_bundling_size_ind = dci->prb_bundling_size_indicator.val; @@ -2892,35 +1085,62 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_1->zp_csi_rs_trigger = dci->zp_csi_rs_trigger.val; /* MCS (for transport block 1)*/ dlsch_config_pdu_1_1->mcs = dci->mcs; + // Basic sanity check for MCS value to check for a false or erroneous DCI + if (dlsch_config_pdu_1_1->mcs > 28) { + LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_1->mcs); + return -1; + } /* NDI (for transport block 1)*/ dlsch_config_pdu_1_1->ndi = dci->ndi; /* RV (for transport block 1)*/ dlsch_config_pdu_1_1->rv = dci->rv; /* MCS (for transport block 2)*/ dlsch_config_pdu_1_1->tb2_mcs = dci->mcs2.val; + // Basic sanity check for MCS value to check for a false or erroneous DCI + if (dlsch_config_pdu_1_1->tb2_mcs > 28) { + LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_1->tb2_mcs); + return -1; + } /* NDI (for transport block 2)*/ dlsch_config_pdu_1_1->tb2_ndi = dci->ndi2.val; /* RV (for transport block 2)*/ dlsch_config_pdu_1_1->tb2_rv = dci->rv2.val; /* HARQ_PROCESS_NUMBER */ dlsch_config_pdu_1_1->harq_process_nbr = dci->harq_pid; - /* DAI */ - dlsch_config_pdu_1_1->dai = dci->dai[0].val; /* TPC_PUCCH */ // according to TS 38.213 Table 7.2.1-1 if (dci->tpc == 0) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = -1; if (dci->tpc == 1) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 0; if (dci->tpc == 2) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 1; if (dci->tpc == 3) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 3; - /* PUCCH_RESOURCE_IND */ - dlsch_config_pdu_1_1->pucch_resource_id = dci->pucch_resource_indicator; - /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ - // according to TS 38.213 Table 9.2.3-1 - dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; + + // Sanity check for pucch_resource_indicator value received to check for false DCI. + valid = 0; + pucch_res_set_cnt = ubwpd->pucch_Config->choice.setup->resourceSetToAddModList->list.count; + for (int id = 0; id < pucch_res_set_cnt; id++) { + if (dci->pucch_resource_indicator < ubwpd->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + valid = 1; + break; + } + } + if (!valid) { + LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dci->pucch_resource_indicator); + return -1; + } + /* ANTENNA_PORTS */ uint8_t n_codewords = 1; // FIXME!!! - if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.max_length == 1)){ + long *max_length = NULL; + long *dmrs_type = NULL; + if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA) { + max_length = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength; + dmrs_type = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type; + } + if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB) { + max_length = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->maxLength; + dmrs_type = pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type; + } + if ((dmrs_type == NULL) && (max_length == NULL)){ // Table 7.3.1.2.2-1: Antenna port(s) (1000 + DMRS port), dmrs-Type=1, maxLength=1 dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_1[dci->antenna_ports.val][0]; dlsch_config_pdu_1_1->dmrs_ports[0] = table_7_3_2_3_3_1[dci->antenna_ports.val][1]; @@ -2928,8 +1148,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_1->dmrs_ports[2] = table_7_3_2_3_3_1[dci->antenna_ports.val][3]; dlsch_config_pdu_1_1->dmrs_ports[3] = table_7_3_2_3_3_1[dci->antenna_ports.val][4]; } - if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.max_length == 2)){ + if ((dmrs_type == NULL) && (max_length != NULL)){ // Table 7.3.1.2.2-2: Antenna port(s) (1000 + DMRS port), dmrs-Type=1, maxLength=2 if (n_codewords == 1) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][0]; @@ -2939,7 +1158,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_1->dmrs_ports[3] = table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][4]; dlsch_config_pdu_1_1->n_front_load_symb = table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][5]; } - if (n_codewords == 1) { + if (n_codewords == 2) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][0]; dlsch_config_pdu_1_1->dmrs_ports[0] = table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][1]; dlsch_config_pdu_1_1->dmrs_ports[1] = table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][2]; @@ -2952,8 +1171,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_1->n_front_load_symb = table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][9]; } } - if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 2) && - (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.max_length == 1)){ + if ((dmrs_type != NULL) && (max_length == NULL)){ // Table 7.3.1.2.2-3: Antenna port(s) (1000 + DMRS port), dmrs-Type=2, maxLength=1 if (n_codewords == 1) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][0]; @@ -2962,7 +1180,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_1->dmrs_ports[2] = table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][3]; dlsch_config_pdu_1_1->dmrs_ports[3] = table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][4]; } - if (n_codewords == 1) { + if (n_codewords == 2) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][0]; dlsch_config_pdu_1_1->dmrs_ports[0] = table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][1]; dlsch_config_pdu_1_1->dmrs_ports[1] = table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][2]; @@ -2972,8 +1190,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_1->dmrs_ports[5] = table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][6]; } } - if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 2) && - (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.max_length == 2)){ + if ((dmrs_type != NULL) && (max_length != NULL)){ // Table 7.3.1.2.2-4: Antenna port(s) (1000 + DMRS port), dmrs-Type=2, maxLength=2 if (n_codewords == 1) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][0]; @@ -2983,7 +1200,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_1->dmrs_ports[3] = table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][4]; dlsch_config_pdu_1_1->n_front_load_symb = table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][5]; } - if (n_codewords == 1) { + if (n_codewords == 2) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][0]; dlsch_config_pdu_1_1->dmrs_ports[0] = table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][1]; dlsch_config_pdu_1_1->dmrs_ports[1] = table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][2]; @@ -3013,13 +1230,45 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc //FIXME!!! // dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = n_RB_DLBWP; - + + /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ + // according to TS 38.213 Table 9.2.3-1 + uint8_t feedback_ti = + ubwpd->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; + + AssertFatal(feedback_ti>=DURATION_RX_TO_TX,"PDSCH to HARQ feedback time (%d) cannot be less than DURATION_RX_TO_TX (%d). Min feedback time set in config file (min_rxtxtime).\n", + feedback_ti,DURATION_RX_TO_TX); + + // set the harq status at MAC for feedback + set_harq_status(mac,dci->pucch_resource_indicator, + dci->harq_pid, + dlsch_config_pdu_1_1->accumulated_delta_PUCCH, + feedback_ti, + dci->dai[0].val, + dci_ind->n_CCE,dci_ind->N_CCE, + 0, frame,slot); + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); dl_config->number_pdus = dl_config->number_pdus + 1; + /* TODO same calculation for MCS table as done in UL */ + dlsch_config_pdu_1_1->mcs_table = (pdsch_Config->mcs_Table) ? (*pdsch_Config->mcs_Table + 1) : 0; + /*PTRS configuration */ + if(pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) { + valid_ptrs_setup = set_dl_ptrs_values(pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup, + dlsch_config_pdu_1_1->number_rbs, dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table, + &dlsch_config_pdu_1_1->PTRSFreqDensity,&dlsch_config_pdu_1_1->PTRSTimeDensity, + &dlsch_config_pdu_1_1->PTRSPortIndex,&dlsch_config_pdu_1_1->nEpreRatioOfPDSCHToPTRS, + &dlsch_config_pdu_1_1->PTRSReOffset, dlsch_config_pdu_1_1->number_symbols); + if(valid_ptrs_setup==true) { + dlsch_config_pdu_1_1->pduBitmap |= 0x1; + LOG_D(MAC, "DL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", dlsch_config_pdu_1_1->PTRSTimeDensity, dlsch_config_pdu_1_1->PTRSFreqDensity); + } + } break; + } case NR_DL_DCI_FORMAT_2_0: break; @@ -3053,87 +1302,1306 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc /// else normal DL-SCH grant } - return 0; + + return ret; + } -int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe){ +void set_harq_status(NR_UE_MAC_INST_t *mac, + uint8_t pucch_id, + uint8_t harq_id, + int8_t delta_pucch, + uint8_t data_toul_fb, + uint8_t dai, + int n_CCE, + int N_CCE, + int is_common, + frame_t frame, + int slot) { - return 0; + NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id]; + + current_harq->active = true; + current_harq->ack_received = false; + current_harq->pucch_resource_indicator = pucch_id; + current_harq->feedback_to_ul = data_toul_fb; + current_harq->is_common = is_common; + current_harq->dai = dai; + current_harq->n_CCE = n_CCE; + current_harq->N_CCE = N_CCE; + current_harq->delta_pucch = delta_pucch; + // FIXME k0 != 0 currently not taken into consideration + current_harq->dl_frame = frame; + current_harq->dl_slot = slot; + + LOG_D(PHY,"Setting harq_status for harq_id %d, dl %d.%d\n",harq_id,frame,slot); } -void nr_ue_send_sdu(module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - int slotP, - uint8_t * pdu, uint16_t pdu_len, uint8_t gNB_index, - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ - LOG_D(MAC, "Handling PDU frame %d slot %d\n", frameP, slotP); +void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, + int slot, + uint16_t rnti, + PUCCH_sched_t *pucch, + fapi_nr_ul_config_pucch_pdu *pucch_pdu, + int O_SR, int O_ACK, int O_CSI) { - uint8_t * pduP = pdu; + int O_CRC = 0; //FIXME + uint16_t O_uci = O_CSI + O_ACK; + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + NR_PUCCH_FormatConfig_t *pucchfmt; + long *pusch_id = NULL; + long *id0 = NULL; + int scs; + NR_BWP_UplinkCommon_t *initialUplinkBWP; + if (mac->scc) initialUplinkBWP = mac->scc->uplinkConfigCommon->initialUplinkBWP; + else initialUplinkBWP = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + if (mac->cg && ubwp && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + } + else + scs = initialUplinkBWP->genericParameters.subcarrierSpacing; + + int subframe_number = slot / (nr_slots_per_frame[scs]/10); + nb_pucch_format_4_in_subframes[subframe_number] = 0; + + pucch_pdu->rnti = rnti; + + LOG_D(NR_MAC,"initial_pucch_id %d, pucch_resource %p\n",pucch->initial_pucch_id,pucch->pucch_resource); + // configure pucch from Table 9.2.1-1 + if (pucch->initial_pucch_id > -1 && + pucch->pucch_resource == NULL) { + + pucch_pdu->format_type = initial_pucch_resource[pucch->initial_pucch_id].format; + pucch_pdu->start_symbol_index = initial_pucch_resource[pucch->initial_pucch_id].startingSymbolIndex; + pucch_pdu->nr_of_symbols = initial_pucch_resource[pucch->initial_pucch_id].nrofSymbols; + + pucch_pdu->bwp_size = NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + pucch_pdu->bwp_start = NRRIV2PRBOFFSET(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + + pucch_pdu->prb_size = 1; // format 0 or 1 + int RB_BWP_offset; + if (pucch->initial_pucch_id == 15) + RB_BWP_offset = pucch_pdu->bwp_size>>2; + else + RB_BWP_offset = initial_pucch_resource[pucch->initial_pucch_id].PRB_offset; + + int N_CS = initial_pucch_resource[pucch->initial_pucch_id].nb_CS_indexes; + pucch_pdu->prb_start = RB_BWP_offset + (pucch->initial_pucch_id/N_CS); + if (pucch->initial_pucch_id>>3 == 0) { + pucch_pdu->second_hop_prb = pucch_pdu->bwp_size - 1 - RB_BWP_offset - (pucch->initial_pucch_id/N_CS); + pucch_pdu->initial_cyclic_shift = initial_pucch_resource[pucch->initial_pucch_id].initial_CS_indexes[pucch->initial_pucch_id%N_CS]; + } + else { + pucch_pdu->second_hop_prb = pucch_pdu->bwp_size - 1 - RB_BWP_offset - ((pucch->initial_pucch_id - 8)/N_CS); + pucch_pdu->initial_cyclic_shift = initial_pucch_resource[pucch->initial_pucch_id].initial_CS_indexes[(pucch->initial_pucch_id - 8)%N_CS]; + } + pucch_pdu->freq_hop_flag = 1; + pucch_pdu->time_domain_occ_idx = 0; + + if (O_SR == 0 || pucch->sr_payload == 0) { /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */ + if (O_ACK == 1) + pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit[pucch->ack_payload & 0x1]; /* only harq of 1 bit */ + else + pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits[pucch->ack_payload & 0x3]; /* only harq with 2 bits */ + } + else { /* SR + eventually ack are transmitted TS 36.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR */ + if (pucch->sr_payload == 1) { /* positive scheduling request */ + if (O_ACK == 1) + pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit_positive_sr[pucch->ack_payload & 0x1]; /* positive SR and harq of 1 bit */ + else if (O_ACK == 2) + pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits_positive_sr[pucch->ack_payload & 0x3]; /* positive SR and harq with 2 bits */ + else + pucch_pdu->mcs = 0; /* only positive SR */ + } + } + + // TODO verify if SR can be transmitted in this mode + pucch_pdu->payload = (pucch->sr_payload << O_ACK) | pucch->ack_payload; + + } + else if (pucch->pucch_resource != NULL) { + + NR_PUCCH_Resource_t *pucchres = pucch->pucch_resource; + + if (mac->cg && + mac->cg->physicalCellGroupConfig && + (mac->cg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH != NULL || + mac->cg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook != 1)) { + LOG_E(MAC,"PUCCH Unsupported cell group configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return; + } + else if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup && + mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { + LOG_E(MAC,"PUCCH Unsupported code block group for serving cell config : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return; + } + NR_PUCCH_Config_t *pucch_Config; + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) { + NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pusch_Config->choice.setup; + pusch_id = pusch_Config->dataScramblingIdentityPUSCH; + if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) + id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->transformPrecodingDisabled->scramblingID0; + else if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL) + id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->transformPrecodingDisabled->scramblingID0; + else *id0 = mac->physCellId; + pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; + pucch_pdu->bwp_size = NRRIV2BW(mac->ULbwp[bwp_id-1]->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + pucch_pdu->bwp_start = NRRIV2PRBOFFSET(mac->ULbwp[bwp_id-1]->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + } + else if (bwp_id==0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + pucch_pdu->bwp_size = NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + pucch_pdu->bwp_start = NRRIV2PRBOFFSET(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + } + else AssertFatal(1==0,"no pucch_Config\n"); + + + pucch_pdu->prb_start = pucchres->startingPRB; + pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0; + pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0; + pucch_pdu->prb_size = 1; // format 0 or 1 + + if ((O_SR+O_CSI+O_SR) > (sizeof(uint64_t)*8)) { + LOG_E(MAC,"PUCCH number of UCI bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return; + } + pucch_pdu->payload = (pucch->csi_part1_payload << (O_ACK + O_SR)) | (pucch->sr_payload << O_ACK) | pucch->ack_payload; + + switch(pucchres->format.present) { + case NR_PUCCH_Resource__format_PR_format0 : + pucch_pdu->format_type = 0; + pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex; + if (O_SR == 0 || pucch->sr_payload == 0) { /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */ + if (O_ACK == 1) + pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit[pucch->ack_payload & 0x1]; /* only harq of 1 bit */ + else + pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits[pucch->ack_payload & 0x3]; /* only harq with 2 bits */ + } + else { /* SR + eventually ack are transmitted TS 36.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR */ + if (pucch->sr_payload == 1) { /* positive scheduling request */ + if (O_ACK == 1) + pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit_positive_sr[pucch->ack_payload & 0x1]; /* positive SR and harq of 1 bit */ + else if (O_ACK == 2) + pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits_positive_sr[pucch->ack_payload & 0x3]; /* positive SR and harq with 2 bits */ + else + pucch_pdu->mcs = 0; /* only positive SR */ + } + } + break; + case NR_PUCCH_Resource__format_PR_format1 : + pucch_pdu->format_type = 1; + pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format1->initialCyclicShift; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex; + pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC; + break; + case NR_PUCCH_Resource__format_PR_format2 : + pucch_pdu->format_type = 2; + pucch_pdu->n_bit = O_uci+O_SR; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : mac->physCellId; + pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : mac->physCellId; + pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs, + O_uci+O_SR,O_CSI,pucch_Config->format2->choice.setup->maxCodeRate, + 2,pucchres->format.choice.format2->nrofSymbols,8); + break; + case NR_PUCCH_Resource__format_PR_format3 : + pucch_pdu->format_type = 3; + pucch_pdu->n_bit = O_uci+O_SR; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : mac->physCellId; + if (pucch_Config->format3 == NULL) { + pucch_pdu->pi_2bpsk = 0; + pucch_pdu->add_dmrs_flag = 0; + } + else { + pucchfmt = pucch_Config->format3->choice.setup; + pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; + pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; + } + int f3_dmrs_symbols; + if (pucchres->format.choice.format3->nrofSymbols==4) + f3_dmrs_symbols = 1<freq_hop_flag; + else { + if(pucchres->format.choice.format3->nrofSymbols<10) + f3_dmrs_symbols = 2; + else + f3_dmrs_symbols = 2<add_dmrs_flag; + } + pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs, + O_uci+O_SR,O_CSI,pucch_Config->format3->choice.setup->maxCodeRate, + 2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12); + break; + case NR_PUCCH_Resource__format_PR_format4 : + pucch_pdu->format_type = 4; + pucch_pdu->nr_of_symbols = pucchres->format.choice.format4->nrofSymbols; + pucch_pdu->start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex; + pucch_pdu->pre_dft_occ_len = pucchres->format.choice.format4->occ_Length; + pucch_pdu->pre_dft_occ_idx = pucchres->format.choice.format4->occ_Index; + pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : mac->physCellId; + if (pucch_Config->format3 == NULL) { + pucch_pdu->pi_2bpsk = 0; + pucch_pdu->add_dmrs_flag = 0; + } + else { + pucchfmt = pucch_Config->format3->choice.setup; + pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; + pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; + } + break; + default : + AssertFatal(1==0,"Undefined PUCCH format \n"); + } + + pucch_pdu->pucch_tx_power = get_pucch_tx_power_ue(mac, + pucch_Config, + pucch, + pucch_pdu->format_type, + pucch_pdu->prb_size, + pucch_pdu->freq_hop_flag, + pucch_pdu->add_dmrs_flag, + pucch_pdu->nr_of_symbols, + subframe_number, + O_ACK, O_SR, + O_CSI, O_CRC); + } + else AssertFatal(1==0,"problem with pucch configuration\n"); + + NR_PUCCH_ConfigCommon_t *pucch_ConfigCommon; + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Common && + mac->ULbwp[bwp_id-1]->bwp_Common->pucch_ConfigCommon) + pucch_ConfigCommon = mac->ULbwp[bwp_id-1]->bwp_Common->pucch_ConfigCommon->choice.setup; + else if (mac->scc) pucch_ConfigCommon = mac->scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup; + else pucch_ConfigCommon = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup; + if (pucch_ConfigCommon->hoppingId != NULL) + pucch_pdu->hopping_id = *pucch_ConfigCommon->hoppingId; + else + pucch_pdu->hopping_id = mac->physCellId; + + switch (pucch_ConfigCommon->pucch_GroupHopping){ + case 0 : + // if neither, both disabled + pucch_pdu->group_hop_flag = 0; + pucch_pdu->sequence_hop_flag = 0; + break; + case 1 : + // if enable, group enabled + pucch_pdu->group_hop_flag = 1; + pucch_pdu->sequence_hop_flag = 0; + break; + case 2 : + // if disable, sequence disabled + pucch_pdu->group_hop_flag = 0; + pucch_pdu->sequence_hop_flag = 1; + break; + default: + AssertFatal(1==0,"Group hopping flag undefined (0,1,2) \n"); + } + + +} + + +int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, + NR_PUCCH_Config_t *pucch_Config, + PUCCH_sched_t *pucch, + uint8_t format_type, + uint16_t nb_of_prbs, + uint8_t freq_hop_flag, + uint8_t add_dmrs_flag, + uint8_t N_symb_PUCCH, + int subframe_number, + int O_ACK, int O_SR, + int O_CSI, int O_CRC) { + + int PUCCH_POWER_DEFAULT = 0; + int16_t P_O_NOMINAL_PUCCH; + if (mac->scc) P_O_NOMINAL_PUCCH = *mac->scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal; + else P_O_NOMINAL_PUCCH = *mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon->choice.setup->p0_nominal; + + struct NR_PUCCH_PowerControl *power_config = pucch_Config->pucch_PowerControl; + + if (!power_config) + return (PUCCH_POWER_DEFAULT); + + int16_t P_O_UE_PUCCH; + int16_t G_b_f_c = 0; + + if (pucch_Config->spatialRelationInfoToAddModList != NULL) { /* FFS TODO NR */ + LOG_D(MAC,"PUCCH Spatial relation infos are not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + return (PUCCH_POWER_DEFAULT); + } + + if (power_config->p0_Set != NULL) { + P_O_UE_PUCCH = power_config->p0_Set->list.array[0]->p0_PUCCH_Value; /* get from index 0 if no spatial relation set */ + G_b_f_c = 0; + } + else { + G_b_f_c = pucch->delta_pucch; + LOG_D(MAC,"PUCCH Transmit power control command not yet implemented for NR : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + return (PUCCH_POWER_DEFAULT); + } + + int P_O_PUCCH = P_O_NOMINAL_PUCCH + P_O_UE_PUCCH; + + int16_t delta_F_PUCCH; + int DELTA_TF; + uint16_t N_ref_PUCCH; + int N_sc_ctrl_RB = 0; + + /* computing of pucch transmission power adjustment */ + switch (format_type) { + case 0: + N_ref_PUCCH = 2; + DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f0; + break; + case 1: + N_ref_PUCCH = 14; + DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f1; + break; + case 2: + N_sc_ctrl_RB = 10; + DELTA_TF = get_deltatf(nb_of_prbs, + N_symb_PUCCH, + freq_hop_flag, + add_dmrs_flag, + N_sc_ctrl_RB, + pucch->n_HARQ_ACK, + O_ACK, O_SR, + O_CSI, O_CRC); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f2; + break; + case 3: + N_sc_ctrl_RB = 14; + DELTA_TF = get_deltatf(nb_of_prbs, + N_symb_PUCCH, + freq_hop_flag, + add_dmrs_flag, + N_sc_ctrl_RB, + pucch->n_HARQ_ACK, + O_ACK, O_SR, + O_CSI, O_CRC); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f3; + break; + case 4: + N_sc_ctrl_RB = 14/(nb_pucch_format_4_in_subframes[subframe_number]); + DELTA_TF = get_deltatf(nb_of_prbs, + N_symb_PUCCH, + freq_hop_flag, + add_dmrs_flag, + N_sc_ctrl_RB, + pucch->n_HARQ_ACK, + O_ACK, O_SR, + O_CSI, O_CRC); + delta_F_PUCCH = *power_config->deltaF_PUCCH_f4; + break; + default: + { + LOG_E(MAC,"PUCCH unknown pucch format : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + return (0); + } + } + + if (*power_config->twoPUCCH_PC_AdjustmentStates > 1) { + LOG_E(MAC,"PUCCH power control adjustment states with 2 states not yet implemented : at line %d in function %s of file %s \n", LINE_FILE , __func__, __FILE__); + return (PUCCH_POWER_DEFAULT); + } + + int16_t pucch_power = P_O_PUCCH + delta_F_PUCCH + DELTA_TF + G_b_f_c; + + NR_TST_PHY_PRINTF("PUCCH ( Tx power : %d dBm ) ( 10Log(...) : %d ) ( from Path Loss : %d ) ( delta_F_PUCCH : %d ) ( DELTA_TF : %d ) ( G_b_f_c : %d ) \n", + pucch_power, contributor, PL, delta_F_PUCCH, DELTA_TF, G_b_f_c); + + return (pucch_power); +} + +int get_deltatf(uint16_t nb_of_prbs, + uint8_t N_symb_PUCCH, + uint8_t freq_hop_flag, + uint8_t add_dmrs_flag, + int N_sc_ctrl_RB, + int n_HARQ_ACK, + int O_ACK, int O_SR, + int O_CSI, int O_CRC){ + + int DELTA_TF; + int O_UCI = O_ACK + O_SR + O_CSI + O_CRC; + int N_symb = nb_symbols_excluding_dmrs[N_symb_PUCCH-4][add_dmrs_flag][freq_hop_flag]; + float N_RE = nb_of_prbs * N_sc_ctrl_RB * N_symb; + float K1 = 6; + if (O_UCI < 12) + DELTA_TF = 10 * log10((double)(((K1 * (n_HARQ_ACK + O_SR + O_CSI))/N_RE))); + else { + float K2 = 2.4; + float BPRE = O_UCI/N_RE; + DELTA_TF = 10 * log10((double)(pow(2,(K2*BPRE)) - 1)); + } + return DELTA_TF; +} + +/******************************************************************* +* +* NAME : find_pucch_resource_set +* +* PARAMETERS : ue context +* gNB_id identifier +* +* +* RETURN : harq process identifier +* +* DESCRIPTION : return tx harq process identifier for given transmission slot +* YS 38.213 9.2.2 PUCCH Formats for UCI transmission +* +*********************************************************************/ + +int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, int uci_size) { + int pucch_resource_set_id = 0; + NR_BWP_Id_t bwp_id = mac->DL_BWP_Id; + + //long *pucch_max_pl_bits = NULL; + + /* from TS 38.331 field maxPayloadMinus1 + -- Maximum number of payload bits minus 1 that the UE may transmit using this PUCCH resource set. In a PUCCH occurrence, the UE + -- chooses the first of its PUCCH-ResourceSet which supports the number of bits that the UE wants to transmit. + -- The field is not present in the first set (Set0) since the maximum Size of Set0 is specified to be 3 bit. + -- The field is not present in the last configured set since the UE derives its maximum payload size as specified in 38.213. + -- This field can take integer values that are multiples of 4. Corresponds to L1 parameter 'N_2' or 'N_3' (see 38.213, section 9.2) + */ + /* look for the first resource set which supports uci_size number of bits for payload */ + while (pucch_resource_set_id < MAX_NB_OF_PUCCH_RESOURCE_SETS) { + if ((bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL) || + (bwp_id==0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL)) { + if (uci_size <= 2) { + pucch_resource_set_id = 0; + return (pucch_resource_set_id); + break; + } + else { + pucch_resource_set_id = 1; + return (pucch_resource_set_id); + break; + } + } + pucch_resource_set_id++; + } + + pucch_resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS; + + return (pucch_resource_set_id); +} + + +/******************************************************************* +* +* NAME : select_pucch_format +* +* PARAMETERS : ue context +* processing slots of reception/transmission +* gNB_id identifier +* +* RETURN : TRUE a valid resource has been found +* +* DESCRIPTION : return tx harq process identifier for given transmission slot +* TS 38.213 9.2.1 PUCCH Resource Sets +* TS 38.213 9.2.2 PUCCH Formats for UCI transmission +* In the case of pucch for scheduling request only, resource is already get from scheduling request configuration +* +*********************************************************************/ + +void select_pucch_resource(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch) { + + NR_PUCCH_ResourceId_t *current_resource_id = NULL; + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + int n_list; + + if (pucch->is_common == 1 || + (bwp_id == 0 && + mac->cg == NULL) || + (bwp_id == 0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList->list.array[0] == NULL) || + (mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[0] == NULL) + ){ + + /* see TS 38.213 9.2.1 PUCCH Resource Sets */ + int delta_PRI = pucch->resource_indicator; + int n_CCE_0 = pucch->n_CCE; + int N_CCE_0 = pucch->N_CCE; + if (N_CCE_0 == 0) { + AssertFatal(1==0,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + } + int r_PUCCH = ((2 * n_CCE_0)/N_CCE_0) + (2 * delta_PRI); + pucch->initial_pucch_id = r_PUCCH; + pucch->pucch_resource = NULL; + } + else { + struct NR_PUCCH_Config__resourceSetToAddModList *resourceSetToAddModList = NULL; + struct NR_PUCCH_Config__resourceToAddModList *resourceToAddModList = NULL; + if (bwp_id > 0 && mac->ULbwp[bwp_id-1]) { + AssertFatal(mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList!=NULL, + "mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList is null\n"); + resourceSetToAddModList = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList; + resourceToAddModList = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList; + } + else if (bwp_id == 0 && mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList!=NULL) { + resourceSetToAddModList = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceSetToAddModList; + resourceToAddModList = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup->resourceToAddModList; + } + + n_list = resourceSetToAddModList->list.count; + if (pucch->resource_set_id > n_list) { + LOG_E(MAC,"Invalid PUCCH resource set id %d\n",pucch->resource_set_id); + pucch->pucch_resource = NULL; + return; + } + n_list = resourceSetToAddModList->list.array[pucch->resource_set_id]->resourceList.list.count; + if (pucch->resource_indicator > n_list) { + LOG_E(MAC,"Invalid PUCCH resource id %d\n",pucch->resource_indicator); + pucch->pucch_resource = NULL; + return; + } + current_resource_id = resourceSetToAddModList->list.array[pucch->resource_set_id]->resourceList.list.array[pucch->resource_indicator]; + n_list = resourceToAddModList->list.count; + int res_found = 0; + for (int i=0; ilist.array[i]->pucch_ResourceId == *current_resource_id) { + pucch->pucch_resource = resourceToAddModList->list.array[i]; + res_found = 1; + break; + } + } + if (res_found == 0) { + LOG_E(MAC,"Couldn't find PUCCH Resource\n"); + pucch->pucch_resource = NULL; + } + } +} + +/******************************************************************* +* +* NAME : get_downlink_ack +* +* PARAMETERS : ue context +* processing slots of reception/transmission +* gNB_id identifier +* +* RETURN : o_ACK acknowledgment data +* o_ACK_number_bits number of bits for acknowledgment +* +* DESCRIPTION : return acknowledgment value +* TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination +* +* --+--------+-------+--------+-------+--- ---+-------+-- +* | PDCCH1 | | PDCCH2 |PDCCH3 | | PUCCH | +* --+--------+-------+--------+-------+--- ---+-------+-- +* DAI_DL 1 2 3 ACK for +* V V V PDCCH1, PDDCH2 and PCCH3 +* | | | ^ +* +-----------------+-------+---------------+ +* +* PDCCH1, PDCCH2 and PDCCH3 are PDCCH monitoring occasions +* M is the total of monitoring occasions +* +*********************************************************************/ + +uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, + frame_t frame, + int slot, + PUCCH_sched_t *pucch) { + + + uint32_t ack_data[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; + uint32_t dai[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for serving cell */ + uint32_t dai_total[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for multiple cells */ + int number_harq_feedback = 0; + uint32_t dai_current = 0; + uint32_t dai_max = 0; + bool two_transport_blocks = FALSE; + int number_of_code_word = 1; + int U_DAI_c = 0; + int N_m_c_rx = 0; + int V_DAI_m_DL = 0; + NR_UE_HARQ_STATUS_t *current_harq; + int sched_frame,sched_slot; + int slots_per_frame,scs; + + NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id; + NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; + NR_BWP_DownlinkDedicated_t *bwpd=NULL; + NR_BWP_DownlinkCommon_t *bwpc=NULL; + NR_BWP_UplinkDedicated_t *ubwpd=NULL; + NR_BWP_UplinkCommon_t *ubwpc=NULL; + get_bwp_info(mac,dl_bwp_id,ul_bwp_id,&bwpd,&bwpc,&ubwpd,&ubwpc); + + if (bwpd && + bwpd->pdsch_Config && + bwpd->pdsch_Config->choice.setup && + bwpd->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI && + bwpd->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0] == 2) { + two_transport_blocks = TRUE; + number_of_code_word = 2; + } + + scs = ubwpc->genericParameters.subcarrierSpacing; + + slots_per_frame = nr_slots_per_frame[scs]; + + /* look for dl acknowledgment which should be done on current uplink slot */ + for (int code_word = 0; code_word < number_of_code_word; code_word++) { + + for (int dl_harq_pid = 0; dl_harq_pid < 16; dl_harq_pid++) { + + current_harq = &mac->dl_harq_info[dl_harq_pid]; + + if (current_harq->active) { + + sched_slot = current_harq->dl_slot + current_harq->feedback_to_ul; + sched_frame = current_harq->dl_frame; + if (sched_slot>=slots_per_frame){ + sched_slot %= slots_per_frame; + sched_frame++; + } + LOG_D(PHY,"HARQ pid %d is active for %d.%d (dl_slot %d, feedback_to_ul %d, is_common %d\n",dl_harq_pid, sched_frame,sched_slot,current_harq->dl_slot,current_harq->feedback_to_ul,current_harq->is_common); + /* check if current tx slot should transmit downlink acknowlegment */ + if (sched_frame == frame && sched_slot == slot) { + + if (current_harq->dai > NR_DL_MAX_DAI) { + LOG_E(MAC,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + } + else { + + if ((pucch->resource_indicator != -1) && (pucch->resource_indicator != current_harq->pucch_resource_indicator)) + LOG_E(MAC, "Value of pucch_resource_indicator %d not matching with what set before %d (Possibly due to a false DCI) \n", + current_harq->pucch_resource_indicator,pucch->resource_indicator); + else{ + dai_current = current_harq->dai+1; // DCI DAI to counter DAI conversion + + if (dai_current == 0) { + LOG_E(MAC,"PUCCH Downlink dai is invalid : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return(0); + } else if (dai_current > dai_max) { + dai_max = dai_current; + } + + number_harq_feedback++; + if (current_harq->ack_received) + ack_data[code_word][dai_current - 1] = current_harq->ack; + else + ack_data[code_word][dai_current - 1] = 0; + dai[code_word][dai_current - 1] = dai_current; + + pucch->resource_indicator = current_harq->pucch_resource_indicator; + pucch->n_CCE = current_harq->n_CCE; + pucch->N_CCE = current_harq->N_CCE; + pucch->delta_pucch = current_harq->delta_pucch; + pucch->is_common = current_harq->is_common; + current_harq->active = false; + current_harq->ack_received = false; + } + } + } + } + } + } + + /* no any ack to transmit */ + if (number_harq_feedback == 0) { + pucch->n_HARQ_ACK = 0; + return(0); + } + else if (number_harq_feedback > (sizeof(uint32_t)*8)) { + LOG_E(MAC,"PUCCH number of ack bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return(0); + } + + /* for computing n_HARQ_ACK for power */ + V_DAI_m_DL = dai_max; + U_DAI_c = number_harq_feedback/number_of_code_word; + N_m_c_rx = number_harq_feedback; + int N_SPS_c = 0; /* FFS TODO_NR multicells and SPS are not supported at the moment */ + if (mac->cg != NULL && + mac->cg->physicalCellGroupConfig != NULL && + mac->cg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH != NULL) { + int N_TB_max_DL = bwpd->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0]; + pucch->n_HARQ_ACK = (((V_DAI_m_DL - U_DAI_c)%4) * N_TB_max_DL) + N_m_c_rx + N_SPS_c; + NR_TST_PHY_PRINTF("PUCCH power n(%d) = ( V(%d) - U(%d) )mod4 * N_TB(%d) + N(%d) \n", pucch->n_HARQ_ACK, V_DAI_m_DL, U_DAI_c, N_TB_max_DL, N_m_c_rx); + } + + /* + * For a monitoring occasion of a PDCCH with DCI format 1_0 or DCI format 1_1 in at least one serving cell, + * when a UE receives a PDSCH with one transport block and the value of higher layer parameter maxNrofCodeWordsScheduledByDCI is 2, + * the HARQ-ACK response is associated with the first transport block and the UE generates a NACK for the second transport block + * if spatial bundling is not applied (HARQ-ACK-spatial-bundling-PUCCH = FALSE) and generates HARQ-ACK value of ACK for the second + * transport block if spatial bundling is applied. + */ + + for (int code_word = 0; code_word < number_of_code_word; code_word++) { + for (uint32_t i = 0; i < dai_max ; i++ ) { + if (dai[code_word][i] != i + 1) { /* fill table with consistent value for each dai */ + dai[code_word][i] = i + 1; /* it covers case for which PDCCH DCI has not been successfully decoded and so it has been missed */ + ack_data[code_word][i] = 0; /* nack data transport block which has been missed */ + number_harq_feedback++; + } + if (two_transport_blocks == TRUE) { + dai_total[code_word][i] = dai[code_word][i]; /* for a single cell, dai_total is the same as dai of first cell */ + } + } + } + + int M = dai_max; + int j = 0; + uint32_t V_temp = 0; + uint32_t V_temp2 = 0; + int O_ACK = 0; + uint8_t o_ACK = 0; + int O_bit_number_cw0 = 0; + int O_bit_number_cw1 = 0; + + for (int m = 0; m < M ; m++) { + + if (dai[0][m] <= V_temp) { + j = j + 1; + } + + V_temp = dai[0][m]; /* value of the counter DAI for format 1_0 and format 1_1 on serving cell c */ + + if (dai_total[0][m] == 0) { + V_temp2 = dai[0][m]; + } else { + V_temp2 = dai[1][m]; /* second code word has been received */ + O_bit_number_cw1 = (8 * j) + 2*(V_temp - 1) + 1; + o_ACK = o_ACK | (ack_data[1][m] << O_bit_number_cw1); + } + + if (two_transport_blocks == TRUE) { + O_bit_number_cw0 = (8 * j) + 2*(V_temp - 1); + } + else { + O_bit_number_cw0 = (4 * j) + (V_temp - 1); + } + + o_ACK = o_ACK | (ack_data[0][m] << O_bit_number_cw0); + LOG_D(MAC,"m %d bit number %d o_ACK %d\n",m,O_bit_number_cw0,o_ACK); + } + + if (V_temp2 < V_temp) { + j = j + 1; + } + + if (two_transport_blocks == TRUE) { + O_ACK = 2 * ( 4 * j + V_temp2); /* for two transport blocks */ + } + else { + O_ACK = 4 * j + V_temp2; /* only one transport block */ + } + + if (number_harq_feedback != O_ACK) { + LOG_E(MAC,"PUCCH Error for number of bits for acknowledgment : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return (0); + } + + reverse_n_bits(&o_ACK,number_harq_feedback); + pucch->ack_payload = o_ACK; + + LOG_D(MAC,"frame %d slot %d pucch acknack payload %d\n",frame,slot,o_ACK); + + return(number_harq_feedback); +} + + +bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + frame_t frame, + int slot) { + + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + NR_PUCCH_Config_t *pucch_Config = NULL; + int scs; + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + NR_BWP_UplinkCommon_t *initialUplinkBWP; + if (mac->scc) initialUplinkBWP = mac->scc->uplinkConfigCommon->initialUplinkBWP; + else initialUplinkBWP = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + + if (mac->cg && ubwp && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + } + else + scs = initialUplinkBWP->genericParameters.subcarrierSpacing; + + const int n_slots_frame = nr_slots_per_frame[scs]; + + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) { + pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; + } + else if (bwp_id==0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + } + if(!pucch_Config || + !pucch_Config->schedulingRequestResourceToAddModList || + pucch_Config->schedulingRequestResourceToAddModList->list.count==0) + return false; // SR not configured + + for (int SR_resource_id =0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++) { + NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id]; + int SR_period; int SR_offset; + + find_period_offest_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); + int sfn_sf = frame * n_slots_frame + slot; + + if ((sfn_sf - SR_offset) % SR_period == 0) { + LOG_D(MAC, "Scheduling Request active in frame %d slot %d \n", frame, slot); + NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource; + + int found = -1; + NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1 + int n_list = pucchresset->resourceList.list.count; + for (int i=0; iresourceList.list.array[i] == *PucchResourceId ) { + found = i; + break; + } + } + if (found == -1) { + LOG_E(MAC,"Couldn't find PUCCH resource for SR\n"); + return false; + } + pucch->resource_indicator = found; + return true; + } + } + return false; +} + +int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot){ + // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti + DevCheck(module_idP < (int) NB_UE_INST, module_idP, NB_NR_UE_MAC_INST, 0); + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + DSR_TRANSMAX_t dsr_TransMax = sr_n64; // todo + LOG_D(NR_MAC, "[UE %d] Frame %d slot %d send SR indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n", + module_idP, frameP, slot, + mac->scheduling_info.SR_COUNTER, + (1 << (2 + dsr_TransMax)), + mac->scheduling_info.SR_pending); // todo + + if ((mac->scheduling_info.SR_pending == 1) && + (mac->scheduling_info.SR_COUNTER < (1 << (2 + dsr_TransMax)))) { + LOG_D(NR_MAC, "[UE %d] Frame %d slot %d PHY asks for SR (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d, increment SR_COUNTER\n", + module_idP, frameP, slot, + mac->scheduling_info.SR_COUNTER, + (1 << (2 + dsr_TransMax)), + mac->scheduling_info.SR_pending); // todo + mac->scheduling_info.SR_COUNTER++; + + // start the sr-prohibittimer : rel 9 and above + if (mac->scheduling_info.sr_ProhibitTimer > 0) { // timer configured + mac->scheduling_info.sr_ProhibitTimer--; + mac->scheduling_info. + sr_ProhibitTimer_Running = 1; + } else { + mac->scheduling_info. + sr_ProhibitTimer_Running = 0; + } + //mac->ul_active =1; + return (1); //instruct phy to signal SR + } else { + // notify RRC to relase PUCCH/SRS + // clear any configured dl/ul + // initiate RA + if (mac->scheduling_info.SR_pending) { + // release all pucch resource + //mac->physicalConfigDedicated = NULL; // todo + //mac->ul_active = 0; // todo + mac->BSR_reporting_active = + NR_BSR_TRIGGER_NONE; + LOG_I(NR_MAC, "[UE %d] Release all SRs \n", module_idP); + } + + mac->scheduling_info.SR_pending = 0; + mac->scheduling_info.SR_COUNTER = 0; + return (0); + } +} + + +uint8_t nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, + frame_t frame, + int slot, + PUCCH_sched_t *pucch) { + + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + NR_PUCCH_Config_t *pucch_Config = NULL; + int csi_bits = 0; + + if(mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig) { + + NR_CSI_MeasConfig_t *csi_measconfig = mac->cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + + for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + + if(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic){ + int period, offset; + csi_period_offset(csirep, NULL, &period, &offset); + + int scs; + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + NR_BWP_UplinkCommon_t *initialUplinkBWP; + if (mac->scc) initialUplinkBWP = mac->scc->uplinkConfigCommon->initialUplinkBWP; + else initialUplinkBWP = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + + if (ubwp && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + else + scs = initialUplinkBWP->genericParameters.subcarrierSpacing; + + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) { + pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; + } + else if (bwp_id==0 && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + } + + const int n_slots_frame = nr_slots_per_frame[scs]; + if (((n_slots_frame*frame + slot - offset)%period) == 0 && pucch_Config) { + + NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; + NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 + int n = pucchresset->resourceList.list.count; + + int res_index; + int found = -1; + for (res_index = 0; res_index < n; res_index++) { + if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) { + found = res_index; + break; + } + } + AssertFatal(found != -1, + "CSI resource not found among PUCCH resources\n"); + + pucch->resource_indicator = found; + csi_bits = nr_get_csi_payload(mac, pucch, csi_measconfig); + } + } + else + AssertFatal(1==0,"Only periodic CSI reporting is currently implemented\n"); + } + } + + return csi_bits; +} + + +uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + NR_CSI_MeasConfig_t *csi_MeasConfig) { + + int n_csi_bits = 0; + + AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count>0,"No CSI Report configuration available\n"); + + for (int csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement; + switch(csi_reportconfig->reportQuantity.present) { + case NR_CSI_ReportConfig__reportQuantity_PR_none: + break; + case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP: + n_csi_bits += get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig); + break; + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI: + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI: + AssertFatal(1==0,"Measurement report based on CSI-RS not availalble\n"); + default: + AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present); + } + } + return (n_csi_bits); +} + + +uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + PUCCH_sched_t *pucch, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig) { + + int nb_ssb = 0; // nb of ssb in the resource + int nb_meas = 0; // nb of ssb to report measurements on + int bits = 0; + uint32_t temp_payload = 0; + + for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { + struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; + if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) { + + if (csi_reportconfig->groupBasedBeamReporting.present == NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled) { + if (csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS != NULL) + nb_meas = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; + else + nb_meas = 1; + } else + nb_meas = 2; + + for (int csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) { + if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ + + ///only one SSB resource set from spec 38.331 IE CSI-ResourceConfig + nb_ssb = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; + break; + } + } + + AssertFatal(nb_ssb>0,"No SSB found in the resource set\n"); + int ssbri_bits = ceil(log2(nb_ssb)); + + //TODO measurement of multiple SSBs at PHY and indication to MAC + if(nb_ssb>1) + LOG_E(MAC, "In current implementation only the SSB of synchronization is measured at PHY. This works only for a single SSB scenario\n"); + + int ssb_rsrp[2][nb_meas]; // the array contains index and RSRP of each SSB to be reported (nb_meas highest RSRPs) + + //TODO replace the following 2 lines with a function to order the nb_meas highest SSB RSRPs + ssb_rsrp[0][0] = mac->mib_ssb; + ssb_rsrp[1][0] = mac->ssb_rsrp_dBm; + + uint8_t ssbi; + + if (ssbri_bits > 0) { + ssbi = ssb_rsrp[0][0]; + reverse_n_bits(&ssbi, ssbri_bits); + temp_payload = ssbi; + bits += ssbri_bits; + } + + uint8_t rsrp_idx = get_rsrp_index(ssb_rsrp[1][0]); + reverse_n_bits(&rsrp_idx, 7); + temp_payload |= (rsrp_idx<csi_part1_payload = temp_payload; + return bits; +} + + +// returns index from RSRP +// according to Table 10.1.6.1-1 in 38.133 + +uint8_t get_rsrp_index(int rsrp) { + + int index = rsrp + 157; + if (rsrp>-44) + index = 113; + if (rsrp<-140) + index = 16; + + return index; +} + + +// returns index from differential RSRP +// according to Table 10.1.6.1-2 in 38.133 +uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp) { + + int diff = best_rsrp-current_rsrp; + if (diff>30) + return 15; + else + return (diff>>1); + +} + +void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN); - //LOG_D(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]); - - /* - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE %d] ue_send_sdu : Frame %d gNB_index %d : num_ce %d num_sdu %d\n", - module_idP, frameP, gNB_index, num_ce, num_sdu); - #endif - */ - - /* - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); - for (i = 0; i < 32; i++) { - LOG_T(MAC, "%x.", sdu[i]); - } - LOG_T(MAC, "\n"); - #endif - */ + LOG_D(MAC, "In %s [%d.%d] Handling DLSCH PDU...\n", __FUNCTION__, dl_info->frame, dl_info->slot); // Processing MAC PDU // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs - if (pduP != NULL) - nr_ue_process_mac_pdu(module_idP, CC_id, frameP, pduP, pdu_len, gNB_index, ul_time_alignment); + switch (dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type){ + case FAPI_NR_RX_PDU_TYPE_DLSCH: + nr_ue_process_mac_pdu(dl_info, ul_time_alignment, pdu_id); + break; + case FAPI_NR_RX_PDU_TYPE_RAR: + nr_ue_process_rar(dl_info, ul_time_alignment, pdu_id); + break; + default: + break; + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); } -void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, - int dci_format, - uint8_t dci_size, - uint16_t rnti, - uint64_t *dci_pdu, - dci_pdu_rel15_t *dci_pdu_rel15) { - int rnti_type=-1; +// N_RB configuration according to 7.3.1.0 (DCI size alignment) of TS 38.212 +int get_n_rb(NR_UE_MAC_INST_t *mac, int rnti_type){ - if (rnti == mac->ra_rnti) rnti_type = NR_RNTI_RA; - else if (rnti == mac->crnti) rnti_type = NR_RNTI_C; - else if (rnti == mac->t_crnti) rnti_type = NR_RNTI_TC; - else if (rnti == 0xFFFE) rnti_type = NR_RNTI_P; - else if (rnti == 0xFFFF) rnti_type = NR_RNTI_SI; + int N_RB = 0, start_RB; + switch(rnti_type) { + case NR_RNTI_RA: + case NR_RNTI_TC: + case NR_RNTI_P: { + NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id; + if (mac->DLbwp[dl_bwp_id-1]->bwp_Common->pdcch_ConfigCommon->choice.setup->controlResourceSetZero) { + uint8_t coreset_id = 0; // assuming controlResourceSetId is 0 for controlResourceSetZero + NR_ControlResourceSet_t *coreset = mac->coreset[dl_bwp_id-1][coreset_id]; + get_coreset_rballoc(coreset->frequencyDomainResources.buf,&N_RB,&start_RB); + } else { + N_RB = NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } + break; + } + case NR_RNTI_SI: + N_RB = mac->type0_PDCCH_CSS_config.num_rbs; + break; + case NR_RNTI_C: + N_RB = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + break; + } + return N_RB; - AssertFatal(rnti_type!=-1,"no identified/handled rnti\n"); - AssertFatal(mac->DLbwp[0] != NULL, "DLbwp[0] shouldn't be null here!\n"); - AssertFatal(mac->ULbwp[0] != NULL, "ULbwp[0] shouldn't be null here!\n"); - int N_RB = (mac->scg != NULL) ? - NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275) : - NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275); - int N_RB_UL = (mac->scg != NULL) ? - NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275) : - NRRIV2BW(mac->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth,275); +} - int pos=0; - int fsize=0; +uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, + uint8_t dci_format, + uint8_t dci_size, + uint16_t rnti, + uint64_t *dci_pdu, + dci_pdu_rel15_t *dci_pdu_rel15) { + + int N_RB = 0; + int pos = 0; + int fsize = 0; + + int rnti_type = get_rnti_type(mac, rnti); + + int N_RB_UL = 0; + if(mac->scc_SIB) { + N_RB_UL = NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } else if(mac->ULbwp[0]) { + N_RB_UL = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } else if(mac->scc) { + N_RB_UL = NRRIV2BW(mac->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } + + LOG_D(MAC,"nr_extract_dci_info : dci_pdu %lx, size %d\n",*dci_pdu,dci_size); switch(dci_format) { case NR_DL_DCI_FORMAT_1_0: switch(rnti_type) { case NR_RNTI_RA: - N_RB = NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); // TBR hotfix + if(mac->scc_SIB) { + N_RB = mac->type0_PDCCH_CSS_config.num_rbs; + } else { + N_RB = get_n_rb(mac, rnti_type); + } // Freq domain assignment fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); pos=fsize; @@ -3169,14 +2637,24 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, break; case NR_RNTI_C: - - // indicating a DL DCI format 1bit + + //Identifier for DCI formats pos++; dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; + + //switch to DCI_0_0 + if (dci_pdu_rel15->format_indicator == 0) { + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; + return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, dci_pdu, dci_pdu_rel15); + } #ifdef DEBUG_EXTRACT_DCI LOG_D(MAC,"Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,N_RB,dci_size-pos,*dci_pdu); #endif - + + // check BWP id + if (mac->DLbwp[0]) N_RB=NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + else N_RB=NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + // Freq domain assignment (275rb >> fsize = 16) fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); pos+=fsize; @@ -3286,13 +2764,13 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, } //end else break; - + case NR_RNTI_P: /* - // Short Messages Indicator – 2 bits + // Short Messages Indicator �E2 bits for (int i=0; i<2; i++) dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator>>(1-i))&1)<<(dci_size-pos++); - // Short Messages – 8 bits + // Short Messages �E8 bits for (int i=0; i<8; i++) *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages>>(7-i))&1)<<(dci_size-pos++); // Freq domain assignment 0-16 bit @@ -3316,95 +2794,192 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, break; case NR_RNTI_SI: - /* - // Freq domain assignment 0-16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4 bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_size-pos++); - // VRB to PRB mapping 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++); - // MCS 5bit //bit over 32, so dci_pdu ++ - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - // Redundancy version 2bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - */ - break; - - case NR_RNTI_TC: - // indicating a DL DCI format 1bit - pos++; - dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; + N_RB = mac->type0_PDCCH_CSS_config.num_rbs; // Freq domain assignment 0-16 bit fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); pos+=fsize; dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf; + // VRB to PRB mapping 1 bit - dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&1; + pos++; + dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&0x1; + // MCS 5bit //bit over 32, so dci_pdu ++ pos+=5; dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f; - // New data indicator 1bit - dci_pdu_rel15->ndi = (*dci_pdu>>(dci_size-pos))&1; - // Redundancy version 2bit + + // Redundancy version 2 bit pos+=2; dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&3; - // HARQ process number 4bit + + // System information indicator 1 bit + pos++; + dci_pdu_rel15->system_info_indicator = (*dci_pdu>>(dci_size-pos))&0x1; + + LOG_D(MAC,"N_RB = %i\n", N_RB); + LOG_D(MAC,"dci_size = %i\n", dci_size); + LOG_D(MAC,"fsize = %i\n", fsize); + LOG_D(MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + LOG_D(MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + LOG_D(MAC,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val); + LOG_D(MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); + LOG_D(MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + LOG_D(MAC,"dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator); + + break; + + case NR_RNTI_TC: + + // check BWP id + if (mac->DLbwp[0]) N_RB=NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + else N_RB=mac->type0_PDCCH_CSS_config.num_rbs; +; + + // indicating a DL DCI format 1bit + pos++; + dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; + + //switch to DCI_0_0 + if (dci_pdu_rel15->format_indicator == 0) { + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; + return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, dci_pdu, dci_pdu_rel15); + } + + if (dci_pdu_rel15->format_indicator == 0) + return 1; // discard dci, format indicator not corresponding to dci_format + + // Freq domain assignment 0-16 bit + fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); + pos+=fsize; + dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf; + + // VRB to PRB mapping - 1 bit + pos++; + dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&1; + + // MCS 5bit //bit over 32, so dci_pdu ++ + pos+=5; + dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f; + + // New data indicator - 1 bit + pos++; + dci_pdu_rel15->ndi = (*dci_pdu>>(dci_size-pos))&1; + + // Redundancy version - 2 bits + pos+=2; + dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&3; + + // HARQ process number - 4 bits pos+=4; dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf; - // Downlink assignment index – 2 bits + + // Downlink assignment index - 2 bits pos+=2; dci_pdu_rel15->dai[0].val = (*dci_pdu>>(dci_size-pos))&3; - // TPC command for scheduled PUCCH – 2 bits + + // TPC command for scheduled PUCCH - 2 bits pos+=2; dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3; - // PDSCH-to-HARQ_feedback timing indicator – 3 bits + + // PUCCH resource indicator - 3 bits + pos+=3; + dci_pdu_rel15->pucch_resource_indicator = (*dci_pdu>>(dci_size-pos))&7; + + // PDSCH-to-HARQ_feedback timing indicator - 3 bits pos+=3; dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = (*dci_pdu>>(dci_size-pos))&7; - + + LOG_D(NR_MAC,"N_RB = %i\n", N_RB); + LOG_D(NR_MAC,"dci_size = %i\n", dci_size); + LOG_D(NR_MAC,"fsize = %i\n", fsize); + LOG_D(NR_MAC,"dci_pdu_rel15->format_indicator = %i\n", dci_pdu_rel15->format_indicator); + LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val); + LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); + LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid); + LOG_D(NR_MAC,"dci_pdu_rel15->dai[0].val = %i\n", dci_pdu_rel15->dai[0].val); + LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc); + LOG_D(NR_MAC,"dci_pdu_rel15->pucch_resource_indicator = %i\n", dci_pdu_rel15->pucch_resource_indicator); + LOG_D(NR_MAC,"dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = %i\n", dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val); + break; } break; case NR_UL_DCI_FORMAT_0_0: + if (mac->ULbwp[0]) N_RB_UL=NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + else N_RB_UL=NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + switch(rnti_type) { case NR_RNTI_C: - // indicating a DL DCI format 1bit - dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; - // Freq domain assignment max 16 bit + //Identifier for DCI formats + pos++; + dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_D(MAC,"Format indicator %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,dci_size-pos,*dci_pdu); +#endif + if (dci_pdu_rel15->format_indicator == 1) + return 1; // discard dci, format indicator not corresponding to dci_format fsize = (int)ceil( log2( (N_RB_UL*(N_RB_UL+1))>>1 ) ); pos+=fsize; dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu); +#endif // Time domain assignment 4bit pos+=4; dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf; - // Frequency hopping flag – 1 bit +#ifdef DEBUG_EXTRACT_DCI + LOG_D(MAC,"time-domain assignment %d (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu); +#endif + // Frequency hopping flag �E1 bit pos++; dci_pdu_rel15->frequency_hopping_flag.val= (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_D(MAC,"frequency_hopping %d (1 bit)=> %d (0x%lx)\n",dci_pdu_rel15->frequency_hopping_flag.val,dci_size-pos,*dci_pdu); +#endif // MCS 5 bit pos+=5; dci_pdu_rel15->mcs= (*dci_pdu>>(dci_size-pos))&0x1f; +#ifdef DEBUG_EXTRACT_DCI + LOG_D(MAC,"mcs %d (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu); +#endif // New data indicator 1bit pos++; dci_pdu_rel15->ndi= (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_D(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu); +#endif // Redundancy version 2bit pos+=2; dci_pdu_rel15->rv= (*dci_pdu>>(dci_size-pos))&3; +#ifdef DEBUG_EXTRACT_DCI + LOG_D(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu); +#endif // HARQ process number 4bit pos+=4; dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf; - // TPC command for scheduled PUSCH – 2 bits +#ifdef DEBUG_EXTRACT_DCI + LOG_D(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu); +#endif + // TPC command for scheduled PUSCH �E2 bits pos+=2; dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3; - // UL/SUL indicator – 1 bit +#ifdef DEBUG_EXTRACT_DCI + LOG_D(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu); +#endif + // UL/SUL indicator �E1 bit /* commented for now (RK): need to get this from BWP descriptor if (cfg->pucch_config.pucch_GroupHopping.value) dci_pdu->= ((uint64_t)*dci_pdu>>(dci_size-pos)ul_sul_indicator&1)<<(dci_size-pos++); @@ -3412,702 +2987,952 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, break; case NR_RNTI_TC: - /* - // indicating a DL DCI format 1bit - dci_pdu->= (*dci_pdu>>(dci_size-pos)format_indicator&1)<<(dci_size-pos++); - // Freq domain assignment max 16 bit + //Identifier for DCI formats + pos++; + dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"Format indicator %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,dci_size-pos,*dci_pdu); +#endif + if (dci_pdu_rel15->format_indicator == 1) + return 1; // discard dci, format indicator not corresponding to dci_format fsize = (int)ceil( log2( (N_RB_UL*(N_RB_UL+1))>>1 ) ); - for (int i=0; i= ((*dci_pdu>>(dci_size-pos)frequency_domain_assignment>>(fsize-i-1))&1)<<(dci_size-pos++); + pos+=fsize; + dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu); +#endif // Time domain assignment 4bit - for (int i=0; i<4; i++) - dci_pdu->= (((uint64_t)*dci_pdu>>(dci_size-pos)time_domain_assignment>>(3-i))&1)<<(dci_size-pos++); - // Frequency hopping flag – 1 bit - dci_pdu->= ((uint64_t)*dci_pdu>>(dci_size-pos)frequency_hopping_flag&1)<<(dci_size-pos++); + pos+=4; + dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"time-domain assignment %d (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu); +#endif + // Frequency hopping flag �E1 bit + pos++; + dci_pdu_rel15->frequency_hopping_flag.val= (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"frequency_hopping %d (1 bit)=> %d (0x%lx)\n",dci_pdu_rel15->frequency_hopping_flag.val,dci_size-pos,*dci_pdu); +#endif // MCS 5 bit - for (int i=0; i<5; i++) - dci_pdu->= (((uint64_t)*dci_pdu>>(dci_size-pos)mcs>>(4-i))&1)<<(dci_size-pos++); + pos+=5; + dci_pdu_rel15->mcs= (*dci_pdu>>(dci_size-pos))&0x1f; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"mcs %d (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu); +#endif // New data indicator 1bit - dci_pdu->= ((uint64_t)*dci_pdu>>(dci_size-pos)ndi&1)<<(dci_size-pos++); + pos++; + dci_pdu_rel15->ndi= (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu); +#endif // Redundancy version 2bit - for (int i=0; i<2; i++) - dci_pdu->= (((uint64_t)*dci_pdu>>(dci_size-pos)rv>>(1-i))&1)<<(dci_size-pos++); + pos+=2; + dci_pdu_rel15->rv= (*dci_pdu>>(dci_size-pos))&3; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu); +#endif // HARQ process number 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)*dci_pdu>>(dci_size-pos)harq_pid>>(3-i))&1)<<(dci_size-pos++); - - // TPC command for scheduled PUSCH – 2 bits - for (int i=0; i<2; i++) - dci_pdu->= (((uint64_t)*dci_pdu>>(dci_size-pos)tpc>>(1-i))&1)<<(dci_size-pos++); - */ - // UL/SUL indicator – 1 bit - /* - commented for now (RK): need to get this information from BWP descriptor - if (cfg->pucch_config.pucch_GroupHopping.value) - dci_pdu->= ((uint64_t)dci_pdu_rel15->ul_sul_indicator&1)<<(dci_size-pos++); - */ + pos+=4; + dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu); +#endif + // TPC command for scheduled PUSCH �E2 bits + pos+=2; + dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu); +#endif break; } break; case NR_DL_DCI_FORMAT_1_1: - // Format indicator - pos=1; - dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; - // Carrier indicator - pos+=dci_pdu_rel15->carrier_indicator.nbits; - dci_pdu_rel15->carrier_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<carrier_indicator.nbits)-1); - // BWP Indicator - pos+=dci_pdu_rel15->bwp_indicator.nbits; - dci_pdu_rel15->bwp_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<bwp_indicator.nbits)-1); - // Frequency domain resource assignment - pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; - dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<frequency_domain_assignment.nbits)-1); - // Time domain resource assignment - pos+=dci_pdu_rel15->time_domain_assignment.nbits; - dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<time_domain_assignment.nbits)-1); - // VRB-to-PRB mapping - pos+=dci_pdu_rel15->vrb_to_prb_mapping.nbits; - dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&((1<vrb_to_prb_mapping.nbits)-1); - // PRB bundling size indicator - pos+=dci_pdu_rel15->prb_bundling_size_indicator.nbits; - dci_pdu_rel15->prb_bundling_size_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<prb_bundling_size_indicator.nbits)-1); - // Rate matching indicator - pos+=dci_pdu_rel15->rate_matching_indicator.nbits; - dci_pdu_rel15->rate_matching_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<rate_matching_indicator.nbits)-1); - // ZP CSI-RS trigger - pos+=dci_pdu_rel15->zp_csi_rs_trigger.nbits; - dci_pdu_rel15->zp_csi_rs_trigger.val = (*dci_pdu>>(dci_size-pos))&((1<zp_csi_rs_trigger.nbits)-1); - //TB1 - // MCS 5bit - pos+=5; - dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f; - // New data indicator 1bit - pos+=1; - dci_pdu_rel15->ndi = (*dci_pdu>>(dci_size-pos))&0x1; - // Redundancy version 2bit - pos+=2; - dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&0x3; - //TB2 - // MCS 5bit - pos+=dci_pdu_rel15->mcs2.nbits; - dci_pdu_rel15->mcs2.val = (*dci_pdu>>(dci_size-pos))&((1<mcs2.nbits)-1); - // New data indicator 1bit - pos+=dci_pdu_rel15->ndi2.nbits; - dci_pdu_rel15->ndi2.val = (*dci_pdu>>(dci_size-pos))&((1<ndi2.nbits)-1); - // Redundancy version 2bit - pos+=dci_pdu_rel15->rv2.nbits; - dci_pdu_rel15->rv2.val = (*dci_pdu>>(dci_size-pos))&((1<rv2.nbits)-1); - // HARQ process number 4bit - pos+=4; - dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf; - // Downlink assignment index - pos+=dci_pdu_rel15->dai[0].nbits; - dci_pdu_rel15->dai[0].val = (*dci_pdu>>(dci_size-pos))&((1<dai[0].nbits)-1); - // TPC command for scheduled PUCCH 2bit - pos+=2; - dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&0x3; - // PUCCH resource indicator 3bit - pos+=3; - dci_pdu_rel15->pucch_resource_indicator = (*dci_pdu>>(dci_size-pos))&0x3; - // PDSCH-to-HARQ_feedback timing indicator - pos+=dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits; - dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<pdsch_to_harq_feedback_timing_indicator.nbits)-1); - // Antenna ports - pos+=dci_pdu_rel15->antenna_ports.nbits; - dci_pdu_rel15->antenna_ports.val = (*dci_pdu>>(dci_size-pos))&((1<antenna_ports.nbits)-1); - // TCI - pos+=dci_pdu_rel15->transmission_configuration_indication.nbits; - dci_pdu_rel15->transmission_configuration_indication.val = (*dci_pdu>>(dci_size-pos))&((1<transmission_configuration_indication.nbits)-1); - // SRS request - pos+=dci_pdu_rel15->srs_request.nbits; - dci_pdu_rel15->srs_request.val = (*dci_pdu>>(dci_size-pos))&((1<srs_request.nbits)-1); - // CBG transmission information - pos+=dci_pdu_rel15->cbgti.nbits; - dci_pdu_rel15->cbgti.val = (*dci_pdu>>(dci_size-pos))&((1<cbgti.nbits)-1); - // CBG flushing out information - pos+=dci_pdu_rel15->cbgfi.nbits; - dci_pdu_rel15->cbgfi.val = (*dci_pdu>>(dci_size-pos))&((1<cbgfi.nbits)-1); - // DMRS sequence init - pos+=1; - dci_pdu_rel15->dmrs_sequence_initialization.val = (*dci_pdu>>(dci_size-pos))&0x1; - break; - - } -} - - -void nr_ue_process_mac_pdu(module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - uint8_t *pduP, - uint16_t mac_pdu_len, - uint8_t gNB_index, - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ - - // This function is adapting code from the old - // parse_header(...) and ue_send_sdu(...) functions of OAI LTE - - uint8_t *pdu_ptr = pduP, rx_lcid, done = 0; - int pdu_len = mac_pdu_len; - uint16_t mac_ce_len, mac_subheader_len, mac_sdu_len; - NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); - - //NR_UE_MAC_INST_t *UE_mac_inst = get_mac_inst(module_idP); - //uint8_t scs = UE_mac_inst->mib->subCarrierSpacingCommon; - //uint16_t bwp_ul_NB_RB = UE_mac_inst->initial_bwp_ul.N_RB; - - // For both DL/UL-SCH - // Except: - // - UL/DL-SCH: fixed-size MAC CE(known by LCID) - // - UL/DL-SCH: padding - // - UL-SCH: MSG3 48-bits - // |0|1|2|3|4|5|6|7| bit-wise - // |R|F| LCID | - // | L | - // |0|1|2|3|4|5|6|7| bit-wise - // |R|F| LCID | - // | L | - // | L | - - // For both DL/UL-SCH - // For: - // - UL/DL-SCH: fixed-size MAC CE(known by LCID) - // - UL/DL-SCH: padding, for single/multiple 1-oct padding CE(s) - // - UL-SCH: MSG3 48-bits - // |0|1|2|3|4|5|6|7| bit-wise - // |R|R| LCID | - // LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; - // L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; - // F: lenght of L is 0:8 or 1:16 bits wide - // R: Reserved bit, set to zero. - - while (!done && pdu_len > 0){ - mac_ce_len = 0x0000; - mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct - mac_sdu_len = 0x0000; - rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID; - - switch(rx_lcid){ - // MAC CE - - /*#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID, pdu_len); - #endif*/ - case DL_SCH_LCID_CCCH: - // MSG4 RRC Connection Setup 38.331 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - } - - break; - - case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH: - - // 38.321 Ch6.1.3.14 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - } - break; - case DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL: - // 38.321 Ch6.1.3.13 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - } - break; - case DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT: - // 38.321 Ch6.1.3.12 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - } - break; - case DL_SCH_LCID_SP_SRS_ACTIVATION: - // 38.321 Ch6.1.3.17 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - } - break; - - case DL_SCH_LCID_RECOMMENDED_BITRATE: - // 38.321 Ch6.1.3.20 - mac_ce_len = 2; - break; - case DL_SCH_LCID_SP_ZP_CSI_RS_RES_SET_ACT: - // 38.321 Ch6.1.3.19 - mac_ce_len = 2; - break; - case DL_SCH_LCID_PUCCH_SPATIAL_RELATION_ACT: - // 38.321 Ch6.1.3.18 - mac_ce_len = 3; - break; - case DL_SCH_LCID_SP_CSI_REP_PUCCH_ACT: - // 38.321 Ch6.1.3.16 - mac_ce_len = 2; - break; - case DL_SCH_LCID_TCI_STATE_IND_UE_SPEC_PDCCH: - // 38.321 Ch6.1.3.15 - mac_ce_len = 2; - break; - case DL_SCH_LCID_DUPLICATION_ACT: - // 38.321 Ch6.1.3.11 - mac_ce_len = 1; - break; - case DL_SCH_LCID_SCell_ACT_4_OCT: - // 38.321 Ch6.1.3.10 - mac_ce_len = 4; - break; - case DL_SCH_LCID_SCell_ACT_1_OCT: - // 38.321 Ch6.1.3.10 - mac_ce_len = 1; - break; - case DL_SCH_LCID_L_DRX: - // 38.321 Ch6.1.3.6 - // fixed length but not yet specify. - mac_ce_len = 0; - break; - case DL_SCH_LCID_DRX: - // 38.321 Ch6.1.3.5 - // fixed length but not yet specify. - mac_ce_len = 0; - break; - case DL_SCH_LCID_TA_COMMAND: - // 38.321 Ch6.1.3.4 - mac_ce_len = 1; - - /*uint8_t ta_command = ((NR_MAC_CE_TA *)pdu_ptr)[1].TA_COMMAND; - uint8_t tag_id = ((NR_MAC_CE_TA *)pdu_ptr)[1].TAGID;*/ - - ul_time_alignment->apply_ta = 1; - ul_time_alignment->ta_command = ((NR_MAC_CE_TA *)pdu_ptr)[1].TA_COMMAND; - ul_time_alignment->tag_id = ((NR_MAC_CE_TA *)pdu_ptr)[1].TAGID; - - /* - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pdu_ptr[1]); - #endif - */ - - LOG_D(MAC, "Received TA_COMMAND %u TAGID %u CC_id %d\n", ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); - - break; - case DL_SCH_LCID_CON_RES_ID: - // 38.321 Ch6.1.3.3 - // WIP todo: handle CCCH_pdu - mac_ce_len = 6; - - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n", module_idP, frameP, pdu_ptr[0], pdu_ptr[1], pdu_ptr[2], pdu_ptr[3], pdu_ptr[4], pdu_ptr[5]); - - if (mac->RA_active == 1) { - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n", module_idP, frameP); - mac->RA_active = 0; - // // check if RA procedure has finished completely (no contention) - // tx_sdu = &mac->CCCH_pdu.payload[3]; - // //Note: 3 assumes sizeof(SCH_SUBHEADER_SHORT) + PADDING CE, which is when UL-Grant has TBS >= 9 (64 bits) - // // (other possibility is 1 for TBS=7 (SCH_SUBHEADER_FIXED), or 2 for TBS=8 (SCH_SUBHEADER_FIXED+PADDING or // SCH_SUBHEADER_SHORT) - // for (i = 0; i < 6; i++) - // if (tx_sdu[i] != payload_ptr[i]) { - // LOG_E(MAC, "[UE %d][RAPROC] Contention detected, RA failed\n", module_idP); - // nr_ra_failed(module_idP, CC_id, eNB_index); - // mac->RA_contention_resolution_timer_active = 0; - // return; - // } - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : Cleared contention resolution timer. Set C-RNTI to TC-RNTI\n", - module_idP, - frameP); - mac->RA_contention_resolution_timer_active = 0; - nr_ra_succeeded(module_idP, CC_id, gNB_index); - mac->crnti = mac->t_crnti; - mac->t_crnti = 0; - mac->ra_state = RA_SUCCEEDED; - } - break; - case DL_SCH_LCID_PADDING: - done = 1; - // end of MAC PDU, can ignore the rest. - break; - - // MAC SDU - - case DL_SCH_LCID_DCCH: - // check if LCID is valid at current time. - - case DL_SCH_LCID_DCCH1: - // check if LCID is valid at current time. - - default: - // check if LCID is valid at current time. - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L1 & 0x7f) << 8) - | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L2 & 0xff); - - } else { - mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - } - - LOG_D(MAC, "[UE %d] Frame %d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, gNB_index, mac_sdu_len); - - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); - - for (i = 0; i < 32; i++) - LOG_T(MAC, "%x.", (pdu_ptr + mac_subheader_len)[i]); - - LOG_T(MAC, "\n"); - #endif - - if (IS_SOFTMODEM_NOS1){ - if (rx_lcid < NB_RB_MAX && rx_lcid >= DL_SCH_LCID_DTCH) { - - mac_rlc_data_ind(module_idP, - 0x1234, - gNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pdu_ptr + mac_subheader_len), - mac_sdu_len, - 1, - NULL); - } else { - LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, gNB_index); - } - } - - break; - } - pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); - pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); - AssertFatal(pdu_len >= 0, "[MAC] nr_ue_process_mac_pdu, residual mac pdu length < 0!\n"); - } -} - -//////////////////////////////////////////////////////// -/////* ULSCH MAC PDU generation (6.1.2 TS 38.321) *///// -//////////////////////////////////////////////////////// - -uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload, - uint8_t *pdu, - uint8_t num_sdus, - uint16_t *sdu_lengths, - uint8_t *sdu_lcids, - uint8_t power_headroom, - uint16_t crnti, - uint16_t truncated_bsr, - uint16_t short_bsr, - uint16_t long_bsr, - unsigned short post_padding, - uint16_t buflen) { - - NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) pdu; - unsigned char last_size = 0, i, mac_header_control_elements[16], *ce_ptr, bsr = 0; - int mac_ce_size; - uint16_t offset = 0; - - LOG_D(MAC, "[UE] Generating ULSCH PDU : num_sdus %d\n", num_sdus); - - #ifdef DEBUG_HEADER_PARSING - - for (i = 0; i < num_sdus; i++) - LOG_D(MAC, "[UE] MAC subPDU %d (lcid %d length %d bytes \n", i, sdu_lcids[i], sdu_lengths[i]); - - #endif - - // Generating UL MAC subPDUs including MAC SDU and subheader - - for (i = 0; i < num_sdus; i++) { - LOG_D(MAC, "[UE] Generating UL MAC subPDUs for SDU with lenght %d ( num_sdus %d )\n", sdu_lengths[i], num_sdus); - - if (sdu_lcids[i] != UL_SCH_LCID_CCCH){ - if (sdu_lengths[i] < 128) { - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = sdu_lcids[i]; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->L = (unsigned char) sdu_lengths[i]; - last_size = 2; - } else { - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->F = 1; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->LCID = sdu_lcids[i]; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0x7f; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L2 = (unsigned short) sdu_lengths[i] & 0xff; - last_size = 3; + switch(rnti_type) + { + case NR_RNTI_C: + //Identifier for DCI formats + pos++; + dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; + if (dci_pdu_rel15->format_indicator == 0) + return 1; // discard dci, format indicator not corresponding to dci_format + // Carrier indicator + pos+=dci_pdu_rel15->carrier_indicator.nbits; + dci_pdu_rel15->carrier_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<carrier_indicator.nbits)-1); + // BWP Indicator + pos+=dci_pdu_rel15->bwp_indicator.nbits; + dci_pdu_rel15->bwp_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<bwp_indicator.nbits)-1); + // Frequency domain resource assignment + pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; + dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<frequency_domain_assignment.nbits)-1); + // Time domain resource assignment + pos+=dci_pdu_rel15->time_domain_assignment.nbits; + dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<time_domain_assignment.nbits)-1); + // VRB-to-PRB mapping + pos+=dci_pdu_rel15->vrb_to_prb_mapping.nbits; + dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&((1<vrb_to_prb_mapping.nbits)-1); + // PRB bundling size indicator + pos+=dci_pdu_rel15->prb_bundling_size_indicator.nbits; + dci_pdu_rel15->prb_bundling_size_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<prb_bundling_size_indicator.nbits)-1); + // Rate matching indicator + pos+=dci_pdu_rel15->rate_matching_indicator.nbits; + dci_pdu_rel15->rate_matching_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<rate_matching_indicator.nbits)-1); + // ZP CSI-RS trigger + pos+=dci_pdu_rel15->zp_csi_rs_trigger.nbits; + dci_pdu_rel15->zp_csi_rs_trigger.val = (*dci_pdu>>(dci_size-pos))&((1<zp_csi_rs_trigger.nbits)-1); + //TB1 + // MCS 5bit + pos+=5; + dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f; + // New data indicator 1bit + pos+=1; + dci_pdu_rel15->ndi = (*dci_pdu>>(dci_size-pos))&0x1; + // Redundancy version 2bit + pos+=2; + dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&0x3; + //TB2 + // MCS 5bit + pos+=dci_pdu_rel15->mcs2.nbits; + dci_pdu_rel15->mcs2.val = (*dci_pdu>>(dci_size-pos))&((1<mcs2.nbits)-1); + // New data indicator 1bit + pos+=dci_pdu_rel15->ndi2.nbits; + dci_pdu_rel15->ndi2.val = (*dci_pdu>>(dci_size-pos))&((1<ndi2.nbits)-1); + // Redundancy version 2bit + pos+=dci_pdu_rel15->rv2.nbits; + dci_pdu_rel15->rv2.val = (*dci_pdu>>(dci_size-pos))&((1<rv2.nbits)-1); + // HARQ process number 4bit + pos+=4; + dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf; + // Downlink assignment index + pos+=dci_pdu_rel15->dai[0].nbits; + dci_pdu_rel15->dai[0].val = (*dci_pdu>>(dci_size-pos))&((1<dai[0].nbits)-1); + // TPC command for scheduled PUCCH 2bit + pos+=2; + dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&0x3; + // PUCCH resource indicator 3bit + pos+=3; + dci_pdu_rel15->pucch_resource_indicator = (*dci_pdu>>(dci_size-pos))&0x3; + // PDSCH-to-HARQ_feedback timing indicator + pos+=dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits; + dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<pdsch_to_harq_feedback_timing_indicator.nbits)-1); + // Antenna ports + pos+=dci_pdu_rel15->antenna_ports.nbits; + dci_pdu_rel15->antenna_ports.val = (*dci_pdu>>(dci_size-pos))&((1<antenna_ports.nbits)-1); + // TCI + pos+=dci_pdu_rel15->transmission_configuration_indication.nbits; + dci_pdu_rel15->transmission_configuration_indication.val = (*dci_pdu>>(dci_size-pos))&((1<transmission_configuration_indication.nbits)-1); + // SRS request + pos+=dci_pdu_rel15->srs_request.nbits; + dci_pdu_rel15->srs_request.val = (*dci_pdu>>(dci_size-pos))&((1<srs_request.nbits)-1); + // CBG transmission information + pos+=dci_pdu_rel15->cbgti.nbits; + dci_pdu_rel15->cbgti.val = (*dci_pdu>>(dci_size-pos))&((1<cbgti.nbits)-1); + // CBG flushing out information + pos+=dci_pdu_rel15->cbgfi.nbits; + dci_pdu_rel15->cbgfi.val = (*dci_pdu>>(dci_size-pos))&((1<cbgfi.nbits)-1); + // DMRS sequence init + pos+=1; + dci_pdu_rel15->dmrs_sequence_initialization.val = (*dci_pdu>>(dci_size-pos))&0x1; + break; } - } else { // UL CCCH SDU - mac_pdu_ptr->R = 0; - mac_pdu_ptr->LCID = sdu_lcids[i]; - } + break; - mac_pdu_ptr += last_size; + case NR_UL_DCI_FORMAT_0_1: + switch(rnti_type) + { + case NR_RNTI_C: + //Identifier for DCI formats + pos++; + dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; + if (dci_pdu_rel15->format_indicator == 1) + return 1; // discard dci, format indicator not corresponding to dci_format + // Carrier indicator + pos+=dci_pdu_rel15->carrier_indicator.nbits; + dci_pdu_rel15->carrier_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<carrier_indicator.nbits)-1); + + // UL/SUL Indicator + pos+=dci_pdu_rel15->ul_sul_indicator.nbits; + dci_pdu_rel15->ul_sul_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<ul_sul_indicator.nbits)-1); + + // BWP Indicator + pos+=dci_pdu_rel15->bwp_indicator.nbits; + dci_pdu_rel15->bwp_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<bwp_indicator.nbits)-1); - // cycle through SDUs, compute each relevant and place ulsch_buffer in - memcpy((void *) mac_pdu_ptr, (void *) sdus_payload, sdu_lengths[i]); - sdus_payload += sdu_lengths[i]; - mac_pdu_ptr += sdu_lengths[i]; + // Freq domain assignment max 16 bit + fsize = (int)ceil( log2( (N_RB_UL*(N_RB_UL+1))>>1 ) ); + pos+=fsize; + dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<time_domain_assignment.nbits; + dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<time_domain_assignment.nbits)-1); + + // Not supported yet - skip for now + // Frequency hopping flag – 1 bit + //pos++; + //dci_pdu_rel15->frequency_hopping_flag.val= (*dci_pdu>>(dci_size-pos))&1; + + // MCS 5 bit + pos+=5; + dci_pdu_rel15->mcs= (*dci_pdu>>(dci_size-pos))&0x1f; + + // New data indicator 1bit + pos++; + dci_pdu_rel15->ndi= (*dci_pdu>>(dci_size-pos))&1; + + // Redundancy version 2bit + pos+=2; + dci_pdu_rel15->rv= (*dci_pdu>>(dci_size-pos))&3; + + // HARQ process number 4bit + pos+=4; + dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf; + + // 1st Downlink assignment index + pos+=dci_pdu_rel15->dai[0].nbits; + dci_pdu_rel15->dai[0].val = (*dci_pdu>>(dci_size-pos))&((1<dai[0].nbits)-1); + + // 2nd Downlink assignment index + pos+=dci_pdu_rel15->dai[1].nbits; + dci_pdu_rel15->dai[1].val = (*dci_pdu>>(dci_size-pos))&((1<dai[1].nbits)-1); + + // TPC command for scheduled PUSCH – 2 bits + pos+=2; + dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3; + + // SRS resource indicator + pos+=dci_pdu_rel15->srs_resource_indicator.nbits; + dci_pdu_rel15->srs_resource_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<srs_resource_indicator.nbits)-1); + + // Precoding info and n. of layers + pos+=dci_pdu_rel15->precoding_information.nbits; + dci_pdu_rel15->precoding_information.val = (*dci_pdu>>(dci_size-pos))&((1<precoding_information.nbits)-1); + + // Antenna ports + pos+=dci_pdu_rel15->antenna_ports.nbits; + dci_pdu_rel15->antenna_ports.val = (*dci_pdu>>(dci_size-pos))&((1<antenna_ports.nbits)-1); + + // SRS request + pos+=dci_pdu_rel15->srs_request.nbits; + dci_pdu_rel15->srs_request.val = (*dci_pdu>>(dci_size-pos))&((1<srs_request.nbits)-1); + + // CSI request + pos+=dci_pdu_rel15->csi_request.nbits; + dci_pdu_rel15->csi_request.val = (*dci_pdu>>(dci_size-pos))&((1<csi_request.nbits)-1); + + // CBG transmission information + pos+=dci_pdu_rel15->cbgti.nbits; + dci_pdu_rel15->cbgti.val = (*dci_pdu>>(dci_size-pos))&((1<cbgti.nbits)-1); + + // PTRS DMRS association + pos+=dci_pdu_rel15->ptrs_dmrs_association.nbits; + dci_pdu_rel15->ptrs_dmrs_association.val = (*dci_pdu>>(dci_size-pos))&((1<ptrs_dmrs_association.nbits)-1); + + // Beta offset indicator + pos+=dci_pdu_rel15->beta_offset_indicator.nbits; + dci_pdu_rel15->beta_offset_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<beta_offset_indicator.nbits)-1); + + // DMRS sequence initialization + pos+=dci_pdu_rel15->dmrs_sequence_initialization.nbits; + dci_pdu_rel15->dmrs_sequence_initialization.val = (*dci_pdu>>(dci_size-pos))&((1<dmrs_sequence_initialization.nbits)-1); + + // UL-SCH indicator + pos+=1; + dci_pdu_rel15->ulsch_indicator = (*dci_pdu>>(dci_size-pos))&0x1; + + // UL/SUL indicator – 1 bit + /* commented for now (RK): need to get this from BWP descriptor + if (cfg->pucch_config.pucch_GroupHopping.value) + dci_pdu->= ((uint64_t)*dci_pdu>>(dci_size-pos)ul_sul_indicator&1)<<(dci_size-pos++); + */ + break; + } + break; + } + + return 0; +} + +/////////////////////////////////// +// brief: nr_ue_process_mac_pdu +// function: parsing DL PDU header +/////////////////////////////////// +// Header for DLSCH: +// Except: +// - DL-SCH: fixed-size MAC CE(known by LCID) +// - DL-SCH: padding +// +// |0|1|2|3|4|5|6|7| bit-wise +// |R|F| LCID | +// | L | +// |0|1|2|3|4|5|6|7| bit-wise +// |R|F| LCID | +// | L | +// | L | +//////////////////////////////// +// Header for DLSCH: +// - DLSCH: fixed-size MAC CE(known by LCID) +// - DLSCH: padding, for single/multiple 1-oct padding CE(s) +// +// |0|1|2|3|4|5|6|7| bit-wise +// |R|R| LCID | +// LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described +// in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; +// L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders +// corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; +// F: lenght of L is 0:8 or 1:16 bits wide +// R: Reserved bit, set to zero. +//////////////////////////////// +void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, + int pdu_id){ + + uint8_t rx_lcid; + uint16_t mac_ce_len; + uint16_t mac_subheader_len; + uint16_t mac_sdu_len; + module_id_t module_idP = dl_info->module_id; + frame_t frameP = dl_info->frame; + int slot = dl_info->slot; + uint8_t *pduP = (dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu; + int32_t pdu_len = (int32_t)(dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu_length; + uint8_t gNB_index = dl_info->gNB_index; + uint8_t CC_id = dl_info->cc_id; + uint8_t done = 0; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + RA_config_t *ra = &mac->ra; + + if (!pduP){ + return; } - // Generating UL MAC subPDUs including MAC CEs (MAC CE and subheader) + LOG_D(MAC, "In %s [%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, frameP, slot, pdu_id, pdu_len, dl_info->rx_ind->number_pdus); - ce_ptr = &mac_header_control_elements[0]; + while (!done && pdu_len > 0){ + mac_ce_len = 0x0000; + mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct + mac_sdu_len = 0x0000; + rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; + LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", rx_lcid, pdu_len); + switch(rx_lcid){ + // MAC CE + case DL_SCH_LCID_CCCH: + // MSG4 RRC Setup 38.331 + // variable length + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8) + | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff); + mac_subheader_len = 3; + } else { + mac_sdu_len = ((NR_MAC_SUBHEADER_SHORT *) pduP)->L; + mac_subheader_len = 2; + } + + // Check if it is a valid CCCH message, we get all 00's messages very often + int i = 0; + for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) { + if(pduP[i] != 0) { + break; + } + } + if (i == (mac_subheader_len+mac_sdu_len)) { + LOG_D(NR_MAC, "%s() Invalid CCCH message!, pdu_len: %d\n", __func__, pdu_len); + done = 1; + break; + } + + if ( mac_sdu_len > 0 ) { + LOG_D(NR_MAC,"DL_SCH_LCID_CCCH (e.g. RRCSetup) with payload len %d\n", mac_sdu_len); + for (int i = 0; i < mac_subheader_len; i++) { + LOG_D(NR_MAC, "MAC header %d: 0x%x\n", i, pduP[i]); + } + for (int i = 0; i < mac_sdu_len; i++) { + LOG_D(NR_MAC, "%d: 0x%x\n", i, pduP[mac_subheader_len + i]); + } + nr_mac_rrc_data_ind_ue(module_idP, CC_id, gNB_index, frameP, 0, mac->crnti, CCCH, pduP+mac_subheader_len, mac_sdu_len); + } + break; + case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH: + + // 38.321 Ch6.1.3.14 + // varialbe length + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + } + break; + case DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL: + // 38.321 Ch6.1.3.13 + // varialbe length + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + } + break; + case DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT: + // 38.321 Ch6.1.3.12 + // varialbe length + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + } + break; + case DL_SCH_LCID_SP_SRS_ACTIVATION: + // 38.321 Ch6.1.3.17 + // varialbe length + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + } + break; + case DL_SCH_LCID_RECOMMENDED_BITRATE: + // 38.321 Ch6.1.3.20 + mac_ce_len = 2; + break; + case DL_SCH_LCID_SP_ZP_CSI_RS_RES_SET_ACT: + // 38.321 Ch6.1.3.19 + mac_ce_len = 2; + break; + case DL_SCH_LCID_PUCCH_SPATIAL_RELATION_ACT: + // 38.321 Ch6.1.3.18 + mac_ce_len = 3; + break; + case DL_SCH_LCID_SP_CSI_REP_PUCCH_ACT: + // 38.321 Ch6.1.3.16 + mac_ce_len = 2; + break; + case DL_SCH_LCID_TCI_STATE_IND_UE_SPEC_PDCCH: + // 38.321 Ch6.1.3.15 + mac_ce_len = 2; + break; + case DL_SCH_LCID_DUPLICATION_ACT: + // 38.321 Ch6.1.3.11 + mac_ce_len = 1; + break; + case DL_SCH_LCID_SCell_ACT_4_OCT: + // 38.321 Ch6.1.3.10 + mac_ce_len = 4; + break; + case DL_SCH_LCID_SCell_ACT_1_OCT: + // 38.321 Ch6.1.3.10 + mac_ce_len = 1; + break; + case DL_SCH_LCID_L_DRX: + // 38.321 Ch6.1.3.6 + // fixed length but not yet specify. + mac_ce_len = 0; + break; + case DL_SCH_LCID_DRX: + // 38.321 Ch6.1.3.5 + // fixed length but not yet specify. + mac_ce_len = 0; + break; + case DL_SCH_LCID_TA_COMMAND: + // 38.321 Ch6.1.3.4 + mac_ce_len = 1; + + /*uint8_t ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + uint8_t tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID;*/ + + ul_time_alignment->apply_ta = 1; + ul_time_alignment->ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + ul_time_alignment->tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID; + + /* + #ifdef DEBUG_HEADER_PARSING + LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]); + #endif + */ + + LOG_I(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d\n", frameP, slot, ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); + + break; + case DL_SCH_LCID_CON_RES_ID: + // Clause 5.1.5 and 6.1.3.3 of 3GPP TS 38.321 version 16.2.1 Release 16 + // MAC Header: 1 byte (R/R/LCID) + // MAC SDU: 6 bytes (UE Contention Resolution Identity) + mac_ce_len = 6; + + if(ra->ra_state == WAIT_CONTENTION_RESOLUTION) { + LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", + module_idP, frameP, pduP[1], pduP[2], pduP[3], pduP[4], pduP[5], pduP[6]); + + bool ra_success = true; + for(int i = 0; icont_res_id[i] != pduP[i+1]) { + ra_success = false; + break; + } + } + + if ( (ra->RA_active == 1) && ra_success) { + nr_ra_succeeded(module_idP, frameP, slot); + } else if (!ra_success){ + // TODO: Handle failure of RA procedure @ MAC layer + // nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure + ra->ra_state = RA_UE_IDLE; + ra->RA_active = 0; + } + } + break; + case DL_SCH_LCID_PADDING: + done = 1; + // end of MAC PDU, can ignore the rest. + break; + // MAC SDU + case DL_SCH_LCID_DCCH: + // check if LCID is valid at current time. + case DL_SCH_LCID_DCCH1: + // check if LCID is valid at current time. + default: + // check if LCID is valid at current time. + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8) + | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff); + + } else { + mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + } + + LOG_D(MAC, "[UE %d] Frame %d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, gNB_index, mac_sdu_len); + + #if defined(ENABLE_MAC_PAYLOAD_DEBUG) + LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); + + for (i = 0; i < 32; i++) + LOG_T(MAC, "%x.", (pduP + mac_subheader_len)[i]); + + LOG_T(MAC, "\n"); + #endif + + if (rx_lcid < NB_RB_MAX && rx_lcid >= DL_SCH_LCID_DCCH) { + + mac_rlc_data_ind(module_idP, + mac->crnti, + gNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pduP + mac_subheader_len), + mac_sdu_len, + 1, + NULL); + } else { + LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, gNB_index); + } + + break; + } + pduP += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); + pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); + if (pdu_len < 0) + LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", module_idP, frameP, slot, pdu_len); + } +} + +/** + * Function: generating MAC CEs (MAC CE and subheader) for the ULSCH PDU + * Notes: TODO: PHR and BSR reporting + * Parameters: + * @mac_ce pointer to the MAC sub-PDUs including the MAC CEs + * @mac pointer to the MAC instance + * Return: number of written bytes + */ +int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, + NR_UE_MAC_INST_t *mac, + uint8_t power_headroom, // todo: NR_POWER_HEADROOM_CMD *power_headroom, + uint16_t *crnti, + NR_BSR_SHORT *truncated_bsr, + NR_BSR_SHORT *short_bsr, + NR_BSR_LONG *long_bsr) { + + int mac_ce_len = 0; + uint8_t mac_ce_size = 0; + uint8_t *pdu = mac_ce; if (power_headroom) { + // MAC CE fixed subheader - mac_pdu_ptr->R = 0; - mac_pdu_ptr->LCID = UL_SCH_LCID_SINGLE_ENTRY_PHR; - mac_pdu_ptr++; + ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0; + ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_SINGLE_ENTRY_PHR; + mac_ce++; // PHR MAC CE (1 octet) - ((NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr)->PH = power_headroom; - ((NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr)->R1 = 0; - ((NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr)->PCMAX = 0; // todo - ((NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr)->R2 = 0; + ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PH = power_headroom; + ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R1 = 0; + ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PCMAX = 0; // todo + ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R2 = 0; + // update pointer and length mac_ce_size = sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE); - - // Copying bytes for PHR MAC CEs to the mac pdu pointer - memcpy((void *) mac_pdu_ptr, (void *) ce_ptr, mac_ce_size); - ce_ptr += mac_ce_size; - mac_pdu_ptr += (unsigned char) mac_ce_size; + mac_ce += mac_ce_size; + mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED); + LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : power_headroom pdu %p mac_ce %p b\n", + pdu, mac_ce); } - if (crnti) { + if (crnti && (!get_softmodem_params()->sa && get_softmodem_params()->do_ra && mac->ra.ra_state != RA_SUCCEEDED)) { + + LOG_D(NR_MAC, "In %s: generating C-RNTI MAC CE with C-RNTI %x\n", __FUNCTION__, (*crnti)); + // MAC CE fixed subheader - mac_pdu_ptr->R = 0; - mac_pdu_ptr->LCID = CRNTI; - mac_pdu_ptr++; + ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0; + ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_C_RNTI; + mac_ce++; // C-RNTI MAC CE (2 octets) - * (uint16_t *) ce_ptr = crnti; + *(uint16_t *) mac_ce = (*crnti); + + // update pointer and length mac_ce_size = sizeof(uint16_t); + mac_ce += mac_ce_size; + mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED); - // Copying bytes for CRNTI MAC CE to the mac pdu pointer - memcpy((void *) mac_pdu_ptr, (void *) ce_ptr, mac_ce_size); - ce_ptr += mac_ce_size; - mac_pdu_ptr += (unsigned char) mac_ce_size; } if (truncated_bsr) { - // MAC CE fixed subheader - mac_pdu_ptr->R = 0; - mac_pdu_ptr->LCID = UL_SCH_LCID_S_TRUNCATED_BSR; - mac_pdu_ptr++; + + // MAC CE fixed subheader + ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0; + ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_S_TRUNCATED_BSR; + mac_ce++; // Short truncated BSR MAC CE (1 octet) - ((NR_BSR_SHORT_TRUNCATED *) ce_ptr)-> Buffer_size = truncated_bsr; - ((NR_BSR_SHORT_TRUNCATED *) ce_ptr)-> LcgID = 0; // todo + ((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> Buffer_size = truncated_bsr->Buffer_size; + ((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> LcgID = truncated_bsr->LcgID;; + + // update pointer and length mac_ce_size = sizeof(NR_BSR_SHORT_TRUNCATED); + mac_ce += mac_ce_size; + mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED); + LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : truncated_bsr Buffer_size %d LcgID %d pdu %p mac_ce %p\n", + truncated_bsr->Buffer_size, truncated_bsr->LcgID, pdu, mac_ce); - bsr = 1 ; } else if (short_bsr) { - // MAC CE fixed subheader - mac_pdu_ptr->R = 0; - mac_pdu_ptr->LCID = UL_SCH_LCID_S_BSR; - mac_pdu_ptr++; + + // MAC CE fixed subheader + ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0; + ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_S_BSR; + mac_ce++; // Short truncated BSR MAC CE (1 octet) - ((NR_BSR_SHORT *) ce_ptr)->Buffer_size = short_bsr; - ((NR_BSR_SHORT *) ce_ptr)->LcgID = 0; // todo + ((NR_BSR_SHORT *) mac_ce)->Buffer_size = short_bsr->Buffer_size; + ((NR_BSR_SHORT *) mac_ce)->LcgID = short_bsr->LcgID; + + // update pointer and length mac_ce_size = sizeof(NR_BSR_SHORT); - - bsr = 1 ; + mac_ce += mac_ce_size; + mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED); + LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : short_bsr Buffer_size %d LcgID %d pdu %p mac_ce %p\n", + short_bsr->Buffer_size, short_bsr->LcgID, pdu, mac_ce); } else if (long_bsr) { - // MAC CE variable subheader - // todo ch 6.1.3.1. TS 38.321 - // ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0; - // ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0; - // ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = UL_SCH_LCID_L_BSR; - // ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->L = 0; - // last_size = 2; - // mac_pdu_ptr += last_size; - // Short truncated BSR MAC CE (1 octet) - // ((NR_BSR_LONG *) ce_ptr)->Buffer_size0 = short_bsr; - // ((NR_BSR_LONG *) ce_ptr)->LCGID0 = 0; - // mac_ce_size = sizeof(NR_BSR_LONG); // size is variable + // MAC CE variable subheader + // ch 6.1.3.1. TS 38.321 + ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->R = 0; + ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->F = 0; + ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->LCID = UL_SCH_LCID_L_BSR; + + NR_MAC_SUBHEADER_SHORT *mac_pdu_subheader_ptr = (NR_MAC_SUBHEADER_SHORT *) mac_ce; + mac_ce += 2; + + // Could move to nr_get_sdu() + uint8_t *Buffer_size_ptr= (uint8_t*) mac_ce + 1; + //int NR_BSR_LONG_SIZE = 1; + if (long_bsr->Buffer_size0 == 0) { + ((NR_BSR_LONG *) mac_ce)->LcgID0 = 0; + } else { + ((NR_BSR_LONG *) mac_ce)->LcgID0 = 1; + *Buffer_size_ptr++ = long_bsr->Buffer_size0; + } + if (long_bsr->Buffer_size1 == 0) { + ((NR_BSR_LONG *) mac_ce)->LcgID1 = 0; + } else { + ((NR_BSR_LONG *) mac_ce)->LcgID1 = 1; + *Buffer_size_ptr++ = long_bsr->Buffer_size1; + } + if (long_bsr->Buffer_size2 == 0) { + ((NR_BSR_LONG *) mac_ce)->LcgID2 = 0; + } else { + ((NR_BSR_LONG *) mac_ce)->LcgID2 = 1; + *Buffer_size_ptr++ = long_bsr->Buffer_size2; + } + if (long_bsr->Buffer_size3 == 0) { + ((NR_BSR_LONG *) mac_ce)->LcgID3 = 0; + } else { + ((NR_BSR_LONG *) mac_ce)->LcgID3 = 1; + *Buffer_size_ptr++ = long_bsr->Buffer_size3; + } + if (long_bsr->Buffer_size4 == 0) { + ((NR_BSR_LONG *) mac_ce)->LcgID4 = 0; + } else { + ((NR_BSR_LONG *) mac_ce)->LcgID4 = 1; + *Buffer_size_ptr++ = long_bsr->Buffer_size4; + } + if (long_bsr->Buffer_size5 == 0) { + ((NR_BSR_LONG *) mac_ce)->LcgID5 = 0; + } else { + ((NR_BSR_LONG *) mac_ce)->LcgID5 = 1; + *Buffer_size_ptr++ = long_bsr->Buffer_size5; + } + if (long_bsr->Buffer_size6 == 0) { + ((NR_BSR_LONG *) mac_ce)->LcgID6 = 0; + } else { + ((NR_BSR_LONG *) mac_ce)->LcgID6 = 1; + *Buffer_size_ptr++ = long_bsr->Buffer_size6; + } + if (long_bsr->Buffer_size7 == 0) { + ((NR_BSR_LONG *) mac_ce)->LcgID7 = 0; + } else { + ((NR_BSR_LONG *) mac_ce)->LcgID7 = 1; + *Buffer_size_ptr++ = long_bsr->Buffer_size7; + } + ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_subheader_ptr)->L = mac_ce_size = (uint8_t*) Buffer_size_ptr - (uint8_t*) mac_ce; + LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : long_bsr size %d Lcgbit 0x%02x Buffer_size %d %d %d %d %d %d %d %d\n", mac_ce_size, *((uint8_t*) mac_ce), + ((NR_BSR_LONG *) mac_ce)->Buffer_size0, ((NR_BSR_LONG *) mac_ce)->Buffer_size1, ((NR_BSR_LONG *) mac_ce)->Buffer_size2, ((NR_BSR_LONG *) mac_ce)->Buffer_size3, + ((NR_BSR_LONG *) mac_ce)->Buffer_size4, ((NR_BSR_LONG *) mac_ce)->Buffer_size5, ((NR_BSR_LONG *) mac_ce)->Buffer_size6, ((NR_BSR_LONG *) mac_ce)->Buffer_size7); + // update pointer and length + mac_ce = Buffer_size_ptr; + mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_SHORT); } - if (bsr){ - // Copying bytes for BSR MAC CE to the mac pdu pointer - memcpy((void *) mac_pdu_ptr, (void *) ce_ptr, mac_ce_size); - ce_ptr += mac_ce_size; - mac_pdu_ptr += (unsigned char) mac_ce_size; - } + return mac_ce_len; - // compute offset before adding padding (if necessary) - offset = ((unsigned char *) mac_pdu_ptr - pdu); - uint16_t padding_bytes = 0; - - if(buflen > 0) // If the buflen is provided - padding_bytes = buflen - offset; - - // Compute final offset for padding - if (post_padding > 0 || padding_bytes>0) { - ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->LCID = UL_SCH_LCID_PADDING; - mac_pdu_ptr++; - } else { - // no MAC subPDU with padding - } - - // compute final offset - offset = ((unsigned char *) mac_pdu_ptr - pdu); - - //printf("Offset %d \n", ((unsigned char *) mac_pdu_ptr - pdu)); - - return offset; } -uint8_t -nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, - sub_frame_t subframe, uint8_t eNB_index, - uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) { - uint8_t total_rlc_pdu_header_len = 0; - int16_t buflen_remain = 0; - uint8_t lcid = 0; - uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - uint16_t payload_offset = 0, num_sdus = 0; - uint8_t ulsch_sdus[MAX_ULSCH_PAYLOAD_BYTES]; - uint16_t sdu_length_total = 0; - //unsigned short post_padding = 0; - rlc_buffer_occupancy_t lcid_buffer_occupancy_old = - 0, lcid_buffer_occupancy_new = 0; - LOG_D(MAC, - "[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n", - module_idP, frameP, subframe, buflen); - AssertFatal(CC_id == 0, - "Transmission on secondary CCs is not supported yet\n"); -#if UE_TIMING_TRACE - start_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu); +///////////////////////////////////// +// Random Access Response PDU // +// TS 38.213 ch 8.2 // +// TS 38.321 ch 6.2.3 // +///////////////////////////////////// +//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise +//| E | T | R A P I D |// +//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// +//| R | T A |// +//| T A | UL grant |// +//| UL grant |// +//| UL grant |// +//| UL grant |// +//| T C - R N T I |// +//| T C - R N T I |// +///////////////////////////////////// +// UL grant (27 bits) // +///////////////////////////////////// +//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise +//|-------------------|FHF|F_alloc|// +//| Freq allocation |// +//| F_alloc |Time allocation|// +//| MCS | TPC |CSI|// +///////////////////////////////////// +// TbD WIP Msg3 development ongoing +// - apply UL grant freq alloc & time alloc as per 8.2 TS 38.213 +// - apply tpc command +// WIP fix: +// - time domain indication hardcoded to 0 for k2 offset +// - extend TS 38.213 ch 8.3 Msg3 PUSCH +// - b buffer +// - ulsch power offset +// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures +int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ + + module_id_t mod_id = dl_info->module_id; + frame_t frame = dl_info->frame; + int slot = dl_info->slot; + + if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack == 0) { + LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] CRC check failed on RAR (NAK)\n", mod_id, frame, slot); + return 0; + } + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + uint8_t n_subPDUs = 0; // number of RAR payloads + uint8_t n_subheaders = 0; // number of MAC RAR subheaders + uint8_t *dlsch_buffer = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu; + uint8_t is_Msg3 = 1; + frame_t frame_tx = 0; + int slot_tx = 0; + int ret = 0; + NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer + NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer + uint8_t preamble_index = ra->ra_PreambleIndex; + + LOG_D(NR_MAC, "In %s:[%d.%d]: [UE %d][RAPROC] invoking MAC for received RAR (current preamble %d)\n", __FUNCTION__, frame, slot, mod_id, preamble_index); + + while (1) { + n_subheaders++; + if (rarh->T == 1) { + n_subPDUs++; + LOG_I(NR_MAC, "[UE %d][RAPROC] Got RAPID RAR subPDU\n", mod_id); + } else { + ra->RA_backoff_indicator = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI]; + ra->RA_BI_found = 1; + LOG_I(NR_MAC, "[UE %d][RAPROC] Got BI RAR subPDU %d ms\n", mod_id, ra->RA_backoff_indicator); + if ( ((NR_RA_HEADER_BI *)rarh)->E == 1) { + rarh += sizeof(NR_RA_HEADER_BI); + continue; + } else { + break; + } + } + if (rarh->RAPID == preamble_index) { + LOG_I(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mod_id, frame, slot, rarh->RAPID); + rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR)); + ra->RA_RAPID_found = 1; + break; + } + if (rarh->E == 0) { + LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] Received RAR preamble (%d) doesn't match the intended RAPID (%d)\n", mod_id, frame, slot, rarh->RAPID, preamble_index); + break; + } else { + rarh += sizeof(NR_MAC_RAR) + 1; + } + } + + #ifdef DEBUG_RAR + LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", frame, slot, n_subheaders, n_subPDUs); + LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index); + #endif + + if (ra->RA_RAPID_found) { + + RAR_grant_t rar_grant; + + unsigned char tpc_command; +#ifdef DEBUG_RAR + unsigned char csi_req; #endif - //NR_UE_MAC_INST_t *nr_ue_mac_inst = get_mac_inst(0); + // TA command + ul_time_alignment->apply_ta = 1; + ul_time_alignment->ta_command = 31 + rar->TA2 + (rar->TA1 << 5); - // Check for DCCH first - // TO DO: Multiplex in the order defined by the logical channel prioritization - for (lcid = UL_SCH_LCID_SRB1; - lcid < NR_MAX_NUM_LCID; lcid++) { - - lcid_buffer_occupancy_old = - //TODO: Replace static value with CRNTI - mac_rlc_get_buffer_occupancy_ind(module_idP, - 0x1234, eNB_index, frameP, //nr_ue_mac_inst->crnti - subframe, ENB_FLAG_NO, - lcid); - lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; - - if(lcid_buffer_occupancy_new){ - - buflen_remain = - buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); - LOG_D(MAC, - "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to " - "send (Transport Block size %d SDU Length Total %d , mac header len %d, buflen_remain %d )\n", //BSR byte before Tx=%d - module_idP, frameP, lcid, lcid_buffer_occupancy_new, - buflen, sdu_length_total, - total_rlc_pdu_header_len, buflen_remain); // ,nr_ue_mac_inst->scheduling_info.BSR_bytes[nr_ue_mac_inst->scheduling_info.LCGID[lcid]] - - while(buflen_remain > 0 && lcid_buffer_occupancy_new){ - - //TODO: Replace static value with CRNTI - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - 0x1234, eNB_index, //nr_ue_mac_inst->crnti - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - lcid, - buflen_remain, - (char *)&ulsch_sdus[sdu_length_total],0, - 0 - ); - AssertFatal(buflen_remain >= sdu_lengths[num_sdus], - "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", - lcid, sdu_lengths[num_sdus], buflen_remain); - - if (sdu_lengths[num_sdus]) { - sdu_length_total += sdu_lengths[num_sdus]; - sdu_lcids[num_sdus] = lcid; - - total_rlc_pdu_header_len += MAX_RLC_SDU_SUBHEADER_SIZE; //rlc_pdu_header_len_last; - - //Update number of SDU - num_sdus++; - } - - /* Get updated BO after multiplexing this PDU */ - //TODO: Replace static value with CRNTI - - lcid_buffer_occupancy_new = - mac_rlc_get_buffer_occupancy_ind(module_idP, - 0x1234, //nr_ue_mac_inst->crnti - eNB_index, frameP, - subframe, ENB_FLAG_NO, - lcid); - buflen_remain = - buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); - } - } - -} - - // Generate ULSCH PDU - if (num_sdus>0) { - payload_offset = nr_generate_ulsch_pdu(ulsch_sdus, - ulsch_buffer, // mac header - num_sdus, // num sdus - sdu_lengths, // sdu length - sdu_lcids, // sdu lcid - 0, // power_headroom - 0, // crnti - 0, // truncated_bsr - 0, // short_bsr - 0, // long_bsr - 0, // post_padding - buflen); // TBS in bytes - } - else - return 0; - - // Padding: fill remainder of ULSCH with 0 - if (buflen - payload_offset > 0){ - for (int j = payload_offset; j < buflen; j++) - ulsch_buffer[j] = 0; - } - -#if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_I(MAC, "Printing UL MAC payload UE side, payload_offset: %d \n", payload_offset); - for (int i = 0; i < buflen ; i++) { - //harq_process_ul_ue->a[i] = (unsigned char) rand(); - //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - printf("%02x ",(unsigned char)ulsch_buffer[i]); - } - printf("\n"); +#ifdef DEBUG_RAR + // CSI + csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); #endif - return 1; + // TPC + tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); + switch (tpc_command){ + case 0: + ra->Msg3_TPC = -6; + break; + case 1: + ra->Msg3_TPC = -4; + break; + case 2: + ra->Msg3_TPC = -2; + break; + case 3: + ra->Msg3_TPC = 0; + break; + case 4: + ra->Msg3_TPC = 2; + break; + case 5: + ra->Msg3_TPC = 4; + break; + case 6: + ra->Msg3_TPC = 6; + break; + case 7: + ra->Msg3_TPC = 8; + break; + } + // MCS + rar_grant.mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); + // time alloc + rar_grant.Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07); + // frequency alloc + rar_grant.Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); + // frequency hopping + rar_grant.freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2); + +#ifdef DEBUG_RAR + LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E); + LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T); + LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID); + + LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R); + LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1); + + LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2); + LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1); + + LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2); + LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3); + LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4); + + LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1); + LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2); + + LOG_I(NR_MAC, "In %s:[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d t_crnti %x \n", + __FUNCTION__, + frame, + slot, + mod_id, + rar_grant.Msg3_t_alloc, + rar_grant.Msg3_f_alloc, + ul_time_alignment->ta_command, + rar_grant.mcs, + rar_grant.freq_hopping, + tpc_command, + ra->t_crnti); +#endif + + // Schedule Msg3 + ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, rar_grant.Msg3_t_alloc); + + if (ret != -1){ + + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx); + uint16_t rnti = mac->crnti; + + if (!ul_config) { + LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot); + return -1; + } + + // Upon successful reception, set the T-CRNTI to the RAR value if the RA preamble is selected among the contention-based RA Preambles + if (!ra->cfra) { + ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); + rnti = ra->t_crnti; + } + + pthread_mutex_lock(&ul_config->mutex_ul_config); + AssertFatal(ul_config->number_pdusnumber_pdus %d out of bounds\n",ul_config->number_pdus); + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; + + fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + pthread_mutex_unlock(&ul_config->mutex_ul_config); + + // Config Msg3 PDU + nr_config_pusch_pdu(mac, pusch_config_pdu, NULL, &rar_grant, rnti, NULL); + } + + } else { + + ra->t_crnti = 0; + ul_time_alignment->ta_command = (0xffff); + + } + + return ret; + } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c new file mode 100644 index 0000000000..3d45877979 --- /dev/null +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -0,0 +1,2858 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* \file nr_ue_scheduler.c + * \brief Routines for UE scheduling + * \author Guido Casati + * \date Jan 2021 + * \version 0.1 + * \company Fraunhofer IIS + * \email guido.casati@iis.fraunhofer.de + */ + +#include +#include +#include + +/* exe */ +#include + +/* RRC*/ +#include "RRC/NR_UE/rrc_proto.h" +#include "NR_RACH-ConfigCommon.h" +#include "NR_RACH-ConfigGeneric.h" +#include "NR_FrequencyInfoDL.h" +#include "NR_PDCCH-ConfigCommon.h" + +/* MAC */ +#include "NR_MAC_COMMON/nr_mac.h" +#include "NR_MAC_UE/mac_proto.h" +#include "NR_MAC_UE/mac_extern.h" + +/* utils */ +#include "assertions.h" +#include "asn1_conversions.h" +#include "SIMULATION/TOOLS/sim.h" // for taus + +#include + +#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" + +static prach_association_pattern_t prach_assoc_pattern; +static ssb_list_info_t ssb_list; + +void fill_ul_config(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx, uint8_t pdu_type){ + // clear ul_config for new frame/slot + if ((ul_config->slot != slot_tx || ul_config->sfn != frame_tx) && ul_config->number_pdus != 0) { + LOG_D(MAC, "%d.%d %d.%d f clear ul_config %p t %d pdu %d\n", frame_tx, slot_tx, ul_config->sfn, ul_config->slot, ul_config, pdu_type, ul_config->number_pdus); + ul_config->number_pdus = 0; + memset(ul_config->ul_config_list, 0, sizeof(ul_config->ul_config_list)); + } + ul_config->ul_config_list[ul_config->number_pdus].pdu_type = pdu_type; + ul_config->slot = slot_tx; + ul_config->sfn = frame_tx; + ul_config->number_pdus++; + + LOG_D(NR_MAC, "In %s: Set config request for UL transmission in [%d.%d], number of UL PDUs: %d\n", __FUNCTION__, ul_config->sfn, ul_config->slot, ul_config->number_pdus); + +} + +void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, + fapi_nr_dl_config_request_t *dl_config, + fapi_nr_ul_config_request_t *ul_config, + fapi_nr_tx_request_t *tx_request, + module_id_t mod_id, + int cc_id, + frame_t frame, + int slot, + int thread_id){ + + scheduled_response->dl_config = dl_config; + scheduled_response->ul_config = ul_config; + scheduled_response->tx_request = tx_request; + scheduled_response->module_id = mod_id; + scheduled_response->CC_id = cc_id; + scheduled_response->frame = frame; + scheduled_response->slot = slot; + scheduled_response->thread_id = thread_id; + +} + +/* + * This function returns the slot offset K2 corresponding to a given time domain + * indication value from RRC configuration. + */ +long get_k2(NR_UE_MAC_INST_t *mac, uint8_t time_domain_ind) { + long k2 = -1; + // Get K2 from RRC configuration + NR_PUSCH_Config_t *pusch_config=mac->ULbwp[0] ? mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup : NULL; + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL; + if (pusch_config && pusch_config->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = pusch_config->pusch_TimeDomainAllocationList->choice.setup; + } + else if (mac->ULbwp[0] && + mac->ULbwp[0]->bwp_Common&& + mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon&& + mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup && + mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + } + else if (mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) + pusch_TimeDomainAllocationList=mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + else AssertFatal(1==0,"need to fall back to default PUSCH time-domain allocations\n"); + + if (pusch_TimeDomainAllocationList) { + if (time_domain_ind >= pusch_TimeDomainAllocationList->list.count) { + LOG_E(NR_MAC, "time_domain_ind %d >= pusch->TimeDomainAllocationList->list.count %d\n", + time_domain_ind, pusch_TimeDomainAllocationList->list.count); + return -1; + } + k2 = *pusch_TimeDomainAllocationList->list.array[time_domain_ind]->k2; + } + + AssertFatal(k2 >= DURATION_RX_TO_TX, + "Slot offset K2 (%ld) cannot be less than DURATION_RX_TO_TX (%d). K2 set according to min_rxtxtime in config file.\n", + k2,DURATION_RX_TO_TX); + + LOG_D(NR_MAC, "get_k2(): k2 is %ld\n", k2); + return k2; +} + +/* + * This function returns the UL config corresponding to a given UL slot + * from MAC instance . + */ +fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) +{ + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; + + //Check if request to access ul_config is for a UL slot + if (is_nr_UL_slot(tdd_config, slot, mac->frame_type) == 0) { + LOG_W(NR_MAC, "Slot %d is not a UL slot. %s called for wrong slot!!!\n", slot, __FUNCTION__); + return NULL; + } + + // Calculate the index of the UL slot in mac->ul_config_request list. This is + // based on the TDD pattern (slot configuration period) and number of UL+mixed + // slots in the period. TS 38.213 Sec 11.1 + int mu = mac->ULbwp[0] ? + mac->ULbwp[0]->bwp_Common->genericParameters.subcarrierSpacing : + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.subcarrierSpacing; + NR_TDD_UL_DL_Pattern_t *tdd_pattern = &tdd_config->pattern1; + const int num_slots_per_tdd = nr_slots_per_frame[mu] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity); + const int num_slots_ul = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0); + int index = slot % num_slots_ul; + + LOG_D(NR_MAC, "In %s slots per tdd %d, num_slots_ul %d, index %d\n", __FUNCTION__, + num_slots_per_tdd, + num_slots_ul, + index); + + return &mac->ul_config_request[index]; +} + +void ul_layers_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci) { + + NR_ServingCellConfigCommon_t *scc = mac->scc; + NR_BWP_UplinkDedicated_t *ubwpd=NULL; + + if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) + ubwpd = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; + + NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0] ? + mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup : + (ubwpd? + ubwpd->pusch_Config->choice.setup: + NULL); + + long transformPrecoder; + if (pusch_Config && pusch_Config->transformPrecoder) + transformPrecoder = *pusch_Config->transformPrecoder; + else { + if(scc && scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder) + transformPrecoder = NR_PUSCH_Config__transformPrecoder_enabled; + else + transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; + } + + + /* PRECOD_NBR_LAYERS */ + if ((*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook)); + // 0 bits if the higher layer parameter txConfig = nonCodeBook + + if ((*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook)){ + + uint8_t n_antenna_port = 0; //FIXME!!! + + if (n_antenna_port == 1); // 1 antenna port and the higher layer parameter txConfig = codebook 0 bits + + if (n_antenna_port == 4){ // 4 antenna port and the higher layer parameter txConfig = codebook + + // Table 7.3.1.1.2-2: transformPrecoder=disabled and maxRank = 2 or 3 or 4 + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) + && ((*pusch_Config->maxRank == 2) || + (*pusch_Config->maxRank == 3) || + (*pusch_Config->maxRank == 4))){ + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_fullyAndPartialAndNonCoherent) { + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][0]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][1]; + } + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][2]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][3]; + } + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][4]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][5]; + } + } + + // Table 7.3.1.1.2-3: transformPrecoder= enabled, or transformPrecoder=disabled and maxRank = 1 + if (((transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled) + || (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled)) + && (*pusch_Config->maxRank == 1)){ + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_fullyAndPartialAndNonCoherent) { + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][6]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][7]; + } + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][8]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][9]; + } + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][10]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][11]; + } + } + } + + if (n_antenna_port == 4){ // 2 antenna port and the higher layer parameter txConfig = codebook + // Table 7.3.1.1.2-4: transformPrecoder=disabled and maxRank = 2 + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank == 2)){ + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_fullyAndPartialAndNonCoherent) { + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][12]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][13]; + } + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][14]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][15]; + } + + } + + // Table 7.3.1.1.2-5: transformPrecoder= enabled, or transformPrecoder= disabled and maxRank = 1 + if (((transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled) + || (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled)) + && (*pusch_Config->maxRank == 1)){ + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_fullyAndPartialAndNonCoherent) { + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][16]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][17]; + } + + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][18]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][19]; + } + + } + } + } + + /*-------------------- Changed to enable Transform precoding in RF SIM------------------------------------------------*/ + + /*if (pusch_config_pdu->transform_precoding == transform_precoder_enabled) { + + pusch_config_dedicated->transform_precoder = transform_precoder_enabled; + + if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) { + + NR_DMRS_UplinkConfig_t *NR_DMRS_ulconfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; + + if (NR_DMRS_ulconfig->dmrs_Type == NULL) + pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type = 1; + if (NR_DMRS_ulconfig->maxLength == NULL) + pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length = 1; + + } else if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL) { + + NR_DMRS_UplinkConfig_t *NR_DMRS_ulconfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + + if (NR_DMRS_ulconfig->dmrs_Type == NULL) + pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_b.dmrs_type = 1; + if (NR_DMRS_ulconfig->maxLength == NULL) + pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_b.max_length = 1; + + } + } else + pusch_config_dedicated->transform_precoder = transform_precoder_disabled;*/ +} + +// todo: this function shall be reviewed completely because of the many comments left by the author +void ul_ports_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci) { + + /* ANTENNA_PORTS */ + uint8_t rank = 1; // We need to initialize rank FIXME!!! + + NR_ServingCellConfigCommon_t *scc = mac->scc; + NR_BWP_UplinkDedicated_t *ubwpd=NULL; + + if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) + ubwpd = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; + + NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0] ? mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup : (ubwpd?ubwpd->pusch_Config->choice.setup:NULL); + AssertFatal(pusch_Config!=NULL,"pusch_Config shouldn't be null\n"); + + long transformPrecoder; + if (pusch_Config->transformPrecoder) + transformPrecoder = *pusch_Config->transformPrecoder; + else { + if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder) + transformPrecoder = NR_PUSCH_Config__transformPrecoder_enabled; + else + transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; + } + long *max_length = NULL; + long *dmrs_type = NULL; + LOG_D(NR_MAC,"transformPrecoder %s\n",transformPrecoder==NR_PUSCH_Config__transformPrecoder_disabled?"disabled":"enabled"); + + if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA) { + max_length = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->maxLength; + dmrs_type = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->dmrs_Type; + } + else { + max_length = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->maxLength; + dmrs_type = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->dmrs_Type; + } + + LOG_D(NR_MAC,"MappingType%s max_length %s, dmrs_type %s, antenna_ports %d\n",pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA?"A":"B",max_length?"len2":"len1",dmrs_type?"type2":"type1",dci->antenna_ports.val); + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled) && + (dmrs_type == NULL) && (max_length == NULL)) { // tables 7.3.1.1.2-6 + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = dci->antenna_ports.val; //TBC + } + + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled) && + (dmrs_type == NULL) && (max_length != NULL)) { // tables 7.3.1.1.2-7 + + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 3)?(dci->antenna_ports.val-4):(dci->antenna_ports.val); //TBC + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports > 3)?2:1; //FIXME + } + + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && + (dmrs_type == NULL) && (max_length == NULL)) { // tables 7.3.1.1.2-8/9/10/11 + + if (rank == 1) { + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC + pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val-2):(dci->antenna_ports.val); //TBC + } + + if (rank == 2){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?2:1; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = (dci->antenna_ports > 1)?(dci->antenna_ports > 2 ?0:2):0; + //pusch_config_pdu->dmrs_ports[1] = (dci->antenna_ports > 1)?(dci->antenna_ports > 2 ?2:3):1; + } + + if (rank == 3){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = 0; + //pusch_config_pdu->dmrs_ports[1] = 1; + //pusch_config_pdu->dmrs_ports[2] = 2; + } + + if (rank == 4){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = 0; + //pusch_config_pdu->dmrs_ports[1] = 1; + //pusch_config_pdu->dmrs_ports[2] = 2; + //pusch_config_pdu->dmrs_ports[3] = 3; + } + } + + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && + (dmrs_type == NULL) && (max_length != NULL)) { // tables 7.3.1.1.2-12/13/14/15 + + if (rank == 1){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC + pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val > 5 ?(dci->antenna_ports.val-6):(dci->antenna_ports.val-2)):dci->antenna_ports.val; //TBC + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports.val > 6)?2:1; //FIXME + } + + if (rank == 2){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?2:1; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_13[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_13[dci->antenna_ports.val][2]; + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports.val > 3)?2:1; // FIXME + } + + if (rank == 3){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_14[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_14[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_14[dci->antenna_ports.val][3]; + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports.val > 1)?2:1; //FIXME + } + + if (rank == 4){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_15[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_15[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_15[dci->antenna_ports.val][3]; + //pusch_config_pdu->dmrs_ports[3] = table_7_3_1_1_2_15[dci->antenna_ports.val][4]; + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports.val > 1)?2:1; //FIXME + } + } + + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && + (dmrs_type != NULL) && + (max_length == NULL)) { // tables 7.3.1.1.2-16/17/18/19 + + if (rank == 1){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?((dci->antenna_ports.val > 5)?3:2):1; //TBC + pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val > 5 ?(dci->antenna_ports.val-6):(dci->antenna_ports.val-2)):dci->antenna_ports.val; //TBC + } + + if (rank == 2){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?((dci->antenna_ports.val > 2)?3:2):1; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_17[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_17[dci->antenna_ports.val][2]; + } + + if (rank == 3){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?3:2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_18[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_18[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_18[dci->antenna_ports.val][3]; + } + + if (rank == 4){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = dci->antenna_ports.val + 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = 0; + //pusch_config_pdu->dmrs_ports[1] = 1; + //pusch_config_pdu->dmrs_ports[2] = 2; + //pusch_config_pdu->dmrs_ports[3] = 3; + } + } + + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && + (dmrs_type != NULL) && (max_length != NULL)) { // tables 7.3.1.1.2-20/21/22/23 + + if (rank == 1){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_20[dci->antenna_ports.val][0]; //TBC + pusch_config_pdu->dmrs_ports = table_7_3_1_1_2_20[dci->antenna_ports.val][1]; //TBC + //pusch_config_pdu->n_front_load_symb = table_7_3_1_1_2_20[dci->antenna_ports.val][2]; //FIXME + } + + if (rank == 2){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_21[dci->antenna_ports.val][0]; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_21[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_21[dci->antenna_ports.val][2]; + //pusch_config_pdu->n_front_load_symb = table_7_3_1_1_2_21[dci->antenna_ports.val][3]; //FIXME + } + + if (rank == 3){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_22[dci->antenna_ports.val][0]; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_22[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_22[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_22[dci->antenna_ports.val][3]; + //pusch_config_pdu->n_front_load_symb = table_7_3_1_1_2_22[dci->antenna_ports.val][4]; //FIXME + } + + if (rank == 4){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_23[dci->antenna_ports.val][0]; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_23[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_23[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_23[dci->antenna_ports.val][3]; + //pusch_config_pdu->dmrs_ports[3] = table_7_3_1_1_2_23[dci->antenna_ports.val][4]; + //pusch_config_pdu->n_front_load_symb = table_7_3_1_1_2_23[dci->antenna_ports.val][5]; //FIXME + } + } + LOG_D(NR_MAC,"num_dmrs_cdm_grps_no_data %d, dmrs_ports %d\n",pusch_config_pdu->num_dmrs_cdm_grps_no_data,pusch_config_pdu->dmrs_ports); +} + +// Configuration of Msg3 PDU according to clauses: +// - 8.3 of 3GPP TS 38.213 version 16.3.0 Release 16 +// - 6.1.2.2 of TS 38.214 +// - 6.1.3 of TS 38.214 +// - 6.2.2 of TS 38.214 +// - 6.1.4.2 of TS 38.214 +// - 6.4.1.1.1 of TS 38.211 +// - 6.3.1.7 of 38.211 +int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, + dci_pdu_rel15_t *dci, + RAR_grant_t *rar_grant, + uint16_t rnti, + uint8_t *dci_format){ + + int f_alloc; + int mask; + int StartSymbolIndex; + int NrOfSymbols; + uint8_t nb_dmrs_re_per_rb; + + uint16_t l_prime_mask = 0; + uint16_t number_dmrs_symbols = 0; + int N_PRB_oh = 0; + + int rnti_type = get_rnti_type(mac, rnti); + + // Common configuration + pusch_config_pdu->dmrs_config_type = pusch_dmrs_type1; + pusch_config_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + pusch_config_pdu->nrOfLayers = 1; + pusch_config_pdu->rnti = rnti; + NR_BWP_UplinkCommon_t *initialUplinkBWP; + if (mac->scc) initialUplinkBWP = mac->scc->uplinkConfigCommon->initialUplinkBWP; + else initialUplinkBWP = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; + + pusch_dmrs_AdditionalPosition_t add_pos = pusch_dmrs_pos2; + pusch_maxLength_t dmrslength = pusch_len1; + + if (rar_grant) { + + // Note: for Msg3 or MsgA PUSCH transmission the N_PRB_oh is always set to 0 + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + NR_BWP_UplinkDedicated_t *ibwp; + int scs,abwp_start,abwp_size,startSymbolAndLength,mappingtype; + NR_PUSCH_Config_t *pusch_Config=NULL; + if (mac->cg && ubwp && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + + ibwp = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; + pusch_Config = ibwp->pusch_Config->choice.setup; + startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[rar_grant->Msg3_t_alloc]->startSymbolAndLength; + mappingtype = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[rar_grant->Msg3_t_alloc]->mappingType; + + // active BWP start + abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + abwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + } + else { + startSymbolAndLength = initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[rar_grant->Msg3_t_alloc]->startSymbolAndLength; + mappingtype = initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[rar_grant->Msg3_t_alloc]->mappingType; + + // active BWP start + abwp_start = NRRIV2PRBOFFSET(initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + abwp_size = NRRIV2BW(initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + scs = initialUplinkBWP->genericParameters.subcarrierSpacing; + } + int ibwp_start = NRRIV2PRBOFFSET(initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int ibwp_size = NRRIV2BW(initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + // BWP start selection according to 8.3 of TS 38.213 + if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size)) { + pusch_config_pdu->bwp_start = abwp_start; + pusch_config_pdu->bwp_size = abwp_size; + } else { + pusch_config_pdu->bwp_start = ibwp_start; + pusch_config_pdu->bwp_size = ibwp_size; + } + + //// Resource assignment from RAR + // Frequency domain allocation according to 8.3 of TS 38.213 + if (ibwp_size < 180) + mask = (1 << ((int) ceil(log2((ibwp_size*(ibwp_size+1))>>1)))) - 1; + else + mask = (1 << (28 - (int)(ceil(log2((ibwp_size*(ibwp_size+1))>>1))))) - 1; + + f_alloc = rar_grant->Msg3_f_alloc & mask; + if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu, NULL, ibwp_size, 0, f_alloc) < 0) + return -1; + + // virtual resource block to physical resource mapping for Msg3 PUSCH (6.3.1.7 in 38.211) + //pusch_config_pdu->rb_start += ibwp_start - abwp_start; + + // Time domain allocation + SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols); + pusch_config_pdu->start_symbol_index = StartSymbolIndex; + pusch_config_pdu->nr_of_symbols = NrOfSymbols; + + l_prime_mask = get_l_prime(NrOfSymbols, mappingtype, add_pos, dmrslength, StartSymbolIndex, mac->scc ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position); + LOG_D(MAC, "MSG3 start_sym:%d NR Symb:%d mappingtype:%d , DMRS_MASK:%x\n", pusch_config_pdu->start_symbol_index, pusch_config_pdu->nr_of_symbols, mappingtype, l_prime_mask); + + #ifdef DEBUG_MSG3 + LOG_D(NR_MAC, "In %s BWP assignment (BWP (start %d, size %d) \n", __FUNCTION__, pusch_config_pdu->bwp_start, pusch_config_pdu->bwp_size); + #endif + + // MCS + pusch_config_pdu->mcs_index = rar_grant->mcs; + // Frequency hopping + pusch_config_pdu->frequency_hopping = rar_grant->freq_hopping; + + // DM-RS configuration according to 6.2.2 UE DM-RS transmission procedure in 38.214 + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + pusch_config_pdu->dmrs_ports = 1; + + // DMRS sequence initialization [TS 38.211, sec 6.4.1.1.1]. + // Should match what is sent in DCI 0_1, otherwise set to 0. + pusch_config_pdu->scid = 0; + + // Transform precoding according to 6.1.3 UE procedure for applying transform precoding on PUSCH in 38.214 + pusch_config_pdu->transform_precoding = get_transformPrecoding(initialUplinkBWP, pusch_Config, NULL, NULL, NR_RNTI_TC, 0); // TBR fix rnti and take out + + // Resource allocation in frequency domain according to 6.1.2.2 in TS 38.214 + pusch_config_pdu->resource_alloc = (mac->cg) ? pusch_Config->resourceAllocation : 1; + + //// Completing PUSCH PDU + pusch_config_pdu->mcs_table = 0; + pusch_config_pdu->cyclic_prefix = 0; + pusch_config_pdu->data_scrambling_id = mac->physCellId; + pusch_config_pdu->ul_dmrs_scrambling_id = mac->physCellId; + pusch_config_pdu->subcarrier_spacing = scs; + pusch_config_pdu->vrb_to_prb_mapping = 0; + pusch_config_pdu->uplink_frequency_shift_7p5khz = 0; + //Optional Data only included if indicated in pduBitmap + pusch_config_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 + pusch_config_pdu->pusch_data.harq_process_id = 0; + pusch_config_pdu->pusch_data.new_data_indicator = 1; // new data + pusch_config_pdu->pusch_data.num_cb = 0; + + } else if (dci) { + NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id; + NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; + NR_BWP_DownlinkDedicated_t *bwpd=NULL; + NR_BWP_DownlinkCommon_t *bwpc=NULL; + NR_BWP_UplinkDedicated_t *ubwpd=NULL; + NR_BWP_UplinkCommon_t *ubwpc=NULL; + get_bwp_info(mac,dl_bwp_id,ul_bwp_id,&bwpd,&bwpc,&ubwpd,&ubwpc); + + int target_ss; + bool valid_ptrs_setup = 0; + uint16_t n_RB_ULBWP; + n_RB_ULBWP = NRRIV2BW(ubwpc->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pusch_config_pdu->bwp_start = NRRIV2PRBOFFSET(ubwpc->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pusch_config_pdu->bwp_size = n_RB_ULBWP; + + AssertFatal(ubwpd->pusch_Config != NULL,"pusch_Config shouldn't be null\n"); + NR_PUSCH_Config_t *pusch_Config = ubwpd->pusch_Config->choice.setup; + + // Basic sanity check for MCS value to check for a false or erroneous DCI + if (dci->mcs > 28) { + LOG_W(NR_MAC, "MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", dci->mcs); + return -1; + } + + /* Transform precoding */ + if (rnti_type != NR_RNTI_CS || (rnti_type == NR_RNTI_CS && dci->ndi == 1)) { + pusch_config_pdu->transform_precoding = get_transformPrecoding(initialUplinkBWP, pusch_Config, NULL, dci_format, rnti_type, 0); + } + + /*DCI format-related configuration*/ + if (*dci_format == NR_UL_DCI_FORMAT_0_0) { + + target_ss = NR_SearchSpace__searchSpaceType_PR_common; + + } else if (*dci_format == NR_UL_DCI_FORMAT_0_1) { + + config_bwp_ue(mac, &dci->bwp_indicator.val, dci_format); + get_bwp_info(mac,dl_bwp_id,ul_bwp_id,&bwpd,&bwpc,&ubwpd,&ubwpc); + + target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + ul_layers_config(mac, pusch_config_pdu, dci); + ul_ports_config(mac, pusch_config_pdu, dci); + + } else { + + LOG_E(NR_MAC, "In %s: UL grant from DCI format %d is not handled...\n", __FUNCTION__, *dci_format); + return -1; + + } + NR_PUSCH_ConfigCommon_t *pusch_ConfigCommon = ubwpc->pusch_ConfigCommon->choice.setup; + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = choose_ul_tda_list(pusch_Config,pusch_ConfigCommon); + + int mappingtype = pusch_TimeDomainAllocationList->list.array[dci->time_domain_assignment.val]->mappingType; + + NR_DMRS_UplinkConfig_t *NR_DMRS_ulconfig = NULL; + if(pusch_Config) { + NR_DMRS_ulconfig = (mappingtype == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA) + ? pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup : pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + } + + /* TRANSFORM PRECODING ------------------------------------------------------------------------------------------*/ + + if (pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled) { + + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + + uint32_t n_RS_Id = 0; + if (NR_DMRS_ulconfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) + n_RS_Id = *NR_DMRS_ulconfig->transformPrecodingEnabled->nPUSCH_Identity; + else + n_RS_Id = *mac->scc->physCellId; + + // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled + pusch_config_pdu->dfts_ofdm.low_papr_group_number = n_RS_Id % 30; + + // V as specified in section 6.4.1.1.1.2 in 38.211 V = 0 if sequence hopping and group hopping are disabled + if ((NR_DMRS_ulconfig->transformPrecodingEnabled->sequenceGroupHopping == NULL) && + (NR_DMRS_ulconfig->transformPrecodingEnabled->sequenceHopping == NULL)) + pusch_config_pdu->dfts_ofdm.low_papr_sequence_number = 0; + else + AssertFatal(1==0,"SequenceGroupHopping or sequenceHopping are NOT Supported\n"); + + LOG_D(NR_MAC,"TRANSFORM PRECODING IS ENABLED. CDM groups: %d, U: %d \n", pusch_config_pdu->num_dmrs_cdm_grps_no_data, + pusch_config_pdu->dfts_ofdm.low_papr_group_number); + } + + /* TRANSFORM PRECODING --------------------------------------------------------------------------------------------------------*/ + + /* IDENTIFIER_DCI_FORMATS */ + /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ + if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu, NULL, n_RB_ULBWP, 0, dci->frequency_domain_assignment.val) < 0){ + return -1; + } + /* TIME_DOM_RESOURCE_ASSIGNMENT */ + if (nr_ue_process_dci_time_dom_resource_assignment(mac, pusch_TimeDomainAllocationList, NULL, pusch_config_pdu, NULL, dci->time_domain_assignment.val,0,false) < 0) { + return -1; + } + + /* FREQ_HOPPING_FLAG */ + if ((pusch_Config!=NULL) && (pusch_Config->frequencyHopping!=NULL) && (pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0)){ + pusch_config_pdu->frequency_hopping = dci->frequency_hopping_flag.val; + } + + /* MCS */ + pusch_config_pdu->mcs_index = dci->mcs; + + /* MCS TABLE */ + if (pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled) { + pusch_config_pdu->mcs_table = get_pusch_mcs_table(pusch_Config ? pusch_Config->mcs_Table : NULL, 0, *dci_format, rnti_type, target_ss, false); + } else { + pusch_config_pdu->mcs_table = get_pusch_mcs_table(pusch_Config ? pusch_Config->mcs_TableTransformPrecoder : NULL, 1, *dci_format, rnti_type, target_ss, false); + } + + /* NDI */ + pusch_config_pdu->pusch_data.new_data_indicator = dci->ndi; + /* RV */ + pusch_config_pdu->pusch_data.rv_index = dci->rv; + /* HARQ_PROCESS_NUMBER */ + pusch_config_pdu->pusch_data.harq_process_id = dci->harq_pid; + /* TPC_PUSCH */ + // according to TS 38.213 Table Table 7.1.1-1 + if (dci->tpc == 0) { + pusch_config_pdu->absolute_delta_PUSCH = -4; + } + if (dci->tpc == 1) { + pusch_config_pdu->absolute_delta_PUSCH = -1; + } + if (dci->tpc == 2) { + pusch_config_pdu->absolute_delta_PUSCH = 1; + } + if (dci->tpc == 3) { + pusch_config_pdu->absolute_delta_PUSCH = 4; + } + + if (NR_DMRS_ulconfig != NULL) { + add_pos = (NR_DMRS_ulconfig->dmrs_AdditionalPosition == NULL) ? 2 : *NR_DMRS_ulconfig->dmrs_AdditionalPosition; + dmrslength = NR_DMRS_ulconfig->maxLength == NULL ? pusch_len1 : pusch_len2; + } + + /* DMRS */ + l_prime_mask = get_l_prime(pusch_config_pdu->nr_of_symbols, + mappingtype, add_pos, dmrslength, + pusch_config_pdu->start_symbol_index, + mac->scc ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position); + if ((mac->ULbwp[0] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled)) + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 1; + else if (*dci_format == NR_UL_DCI_FORMAT_0_0 || (mac->ULbwp[0] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled)) + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + + // Num PRB Overhead from PUSCH-ServingCellConfig + if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->xOverhead) + N_PRB_oh = *mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->xOverhead; + + else N_PRB_oh = 0; + + /* PTRS */ + if (mac->ULbwp[0] && + mac->ULbwp[0]->bwp_Dedicated && + mac->ULbwp[0]->bwp_Dedicated->pusch_Config && + mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup && + mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB && + mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { + if (pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled) { + nfapi_nr_ue_ptrs_ports_t ptrs_ports_list; + pusch_config_pdu->pusch_ptrs.ptrs_ports_list = &ptrs_ports_list; + valid_ptrs_setup = set_ul_ptrs_values(mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup, + pusch_config_pdu->rb_size, pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table, + &pusch_config_pdu->pusch_ptrs.ptrs_freq_density,&pusch_config_pdu->pusch_ptrs.ptrs_time_density, + &pusch_config_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_config_pdu->pusch_ptrs.num_ptrs_ports, + &pusch_config_pdu->pusch_ptrs.ul_ptrs_power, pusch_config_pdu->nr_of_symbols); + if(valid_ptrs_setup==true) { + pusch_config_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; + } + LOG_D(NR_MAC, "UL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", pusch_config_pdu->pusch_ptrs.ptrs_time_density, pusch_config_pdu->pusch_ptrs.ptrs_freq_density); + } + } + + } + + LOG_D(NR_MAC, "In %s: received UL grant (rb_start %d, rb_size %d, start_symbol_index %d, nr_of_symbols %d) for RNTI type %s \n", + __FUNCTION__, + pusch_config_pdu->rb_start, + pusch_config_pdu->rb_size, + pusch_config_pdu->start_symbol_index, + pusch_config_pdu->nr_of_symbols, + rnti_types[rnti_type]); + + pusch_config_pdu->ul_dmrs_symb_pos = l_prime_mask; + pusch_config_pdu->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); + pusch_config_pdu->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); + + if (pusch_config_pdu->target_code_rate == 0 || pusch_config_pdu->qam_mod_order == 0) { + LOG_W(NR_MAC, "In %s: Invalid code rate or Mod order, likely due to unexpected UL DCI. Ignoring DCI! \n", __FUNCTION__); + return -1; + } + + int start_symbol = pusch_config_pdu->start_symbol_index; + int number_of_symbols = pusch_config_pdu->nr_of_symbols; + for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) { + if((pusch_config_pdu->ul_dmrs_symb_pos >> i) & 0x01) + number_dmrs_symbols += 1; + } + + nb_dmrs_re_per_rb = ((pusch_config_pdu->dmrs_config_type == pusch_dmrs_type1) ? 6:4)*pusch_config_pdu->num_dmrs_cdm_grps_no_data; + + // Compute TBS + pusch_config_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_config_pdu->qam_mod_order, + pusch_config_pdu->target_code_rate, + pusch_config_pdu->rb_size, + pusch_config_pdu->nr_of_symbols, + nb_dmrs_re_per_rb*number_dmrs_symbols, + N_PRB_oh, + 0, // TBR to verify tb scaling + pusch_config_pdu->nrOfLayers)/8; + + return 0; + +} + +// Performs : +// 1. TODO: Call RRC for link status return to PHY +// 2. TODO: Perform SR/BSR procedures for scheduling feedback +// 3. TODO: Perform PHR procedures +NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_indication_t *ul_info){ + + if (dl_info){ + + module_id_t mod_id = dl_info->module_id; + uint32_t gNB_index = dl_info->gNB_index; + int cc_id = dl_info->cc_id; + frame_t rx_frame = dl_info->frame; + slot_t rx_slot = dl_info->slot; + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + + fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + + nr_scheduled_response_t scheduled_response; + nr_dcireq_t dcireq; + + if(mac->cg != NULL){ // we have a cg + dcireq.module_id = mod_id; + dcireq.gNB_index = gNB_index; + dcireq.cc_id = cc_id; + dcireq.frame = rx_frame; + dcireq.slot = rx_slot; + dcireq.dl_config_req.number_pdus = 0; + nr_ue_dcireq(&dcireq); //to be replaced with function pointer later + + fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); + } + else { + // this is for Msg2/Msg4 + if (mac->ra.ra_state >= WAIT_RAR) { + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + rel15->num_dci_options = mac->ra.ra_state == WAIT_RAR ? 1 : 2; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + if (mac->ra.ra_state == WAIT_CONTENTION_RESOLUTION) + rel15->dci_format_options[1] = NR_UL_DCI_FORMAT_0_0; // msg3 retransmission + config_dci_pdu(mac, rel15, dl_config, mac->ra.ra_state == WAIT_RAR ? NR_RNTI_RA : NR_RNTI_TC , mac->ra.ss->searchSpaceId); + fill_dci_search_candidates(mac->ra.ss, rel15); + dl_config->number_pdus = 1; + LOG_D(MAC,"mac->cg %p: Calling fill_scheduled_response rnti %x, type0_pdcch, num_pdus %d\n",mac->cg,rel15->rnti,dl_config->number_pdus); + fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); + } + } + } else if (ul_info) { + + int cc_id = ul_info->cc_id; + //frame_t rx_frame = ul_info->frame_rx; + //slot_t rx_slot = ul_info->slot_rx; + frame_t frame_tx = ul_info->frame_tx; + slot_t slot_tx = ul_info->slot_tx; + module_id_t mod_id = ul_info->module_id; + uint32_t gNB_index = ul_info->gNB_index; + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx); + + // Schedule ULSCH only if the current frame and slot match those in ul_config_req + // AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus) + if (ul_config){ + pthread_mutex_lock(&ul_config->mutex_ul_config); + if ((ul_info->slot_tx == ul_config->slot && ul_info->frame_tx == ul_config->sfn) && ul_config->number_pdus > 0){ + + LOG_D(NR_MAC, "In %s:[%d.%d]: number of UL PDUs: %d with UL transmission in [%d.%d]\n", __FUNCTION__, frame_tx, slot_tx, ul_config->number_pdus, ul_config->sfn, ul_config->slot); + + uint8_t ulsch_input_buffer_array[NFAPI_MAX_NUM_UL_PDU][MAX_ULSCH_PAYLOAD_BYTES]; + nr_scheduled_response_t scheduled_response; + fapi_nr_tx_request_t tx_req; + tx_req.slot = slot_tx; + tx_req.sfn = frame_tx; + tx_req.number_of_pdus = 0; + + for (int j = 0; j < ul_config->number_pdus; j++) { + uint8_t *ulsch_input_buffer = &(ulsch_input_buffer_array[tx_req.number_of_pdus][MAX_ULSCH_PAYLOAD_BYTES]); + + fapi_nr_ul_config_request_pdu_t *ulcfg_pdu = &ul_config->ul_config_list[j]; + + if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) { + int mac_pdu_exist = 0; + uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size; + LOG_D(NR_MAC,"harq_id %d, NDI %d NDI_DCI %d, TBS_bytes %d (ra_state %d)\n", + ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id, + mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id], + ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator, + TBS_bytes,ra->ra_state); + if (ra->ra_state == WAIT_RAR && !ra->cfra){ + memcpy(ulsch_input_buffer, mac->ulsch_pdu.payload, TBS_bytes); + LOG_D(NR_MAC,"[RAPROC] Msg3 to be transmitted:\n"); + for (int k = 0; k < TBS_bytes; k++) { + LOG_D(NR_MAC,"(%i): 0x%x\n",k,mac->ulsch_pdu.payload[k]); + } + LOG_D(NR_MAC,"Flipping NDI for harq_id %d (Msg3)\n",ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator); + mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; + mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = 0; + mac_pdu_exist = 1; + } else { + + if ((mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator || + mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id]==1) && + ((get_softmodem_params()->phy_test == 1) || + (ra->ra_state == RA_SUCCEEDED) || + (ra->ra_state == WAIT_RAR && ra->cfra))){ + + // Getting IP traffic to be transmitted + nr_ue_get_sdu(mod_id, cc_id,frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes); + mac_pdu_exist = 1; + } + + LOG_D(NR_MAC,"Flipping NDI for harq_id %d\n",ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator); + mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; + mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = 0; + + } + + // Config UL TX PDU + if (mac_pdu_exist) { + tx_req.tx_request_body[tx_req.number_of_pdus].pdu_length = TBS_bytes; + tx_req.tx_request_body[tx_req.number_of_pdus].pdu_index = j; + tx_req.tx_request_body[tx_req.number_of_pdus].pdu = ulsch_input_buffer; + tx_req.number_of_pdus++; + } + if (ra->ra_state == WAIT_CONTENTION_RESOLUTION && !ra->cfra){ + LOG_I(NR_MAC,"[RAPROC][%d.%d] RA-Msg3 retransmitted\n", frame_tx, slot_tx); + // 38.321 restart the ra-ContentionResolutionTimer at each HARQ retransmission in the first symbol after the end of the Msg3 transmission + nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->gNB_index); + } + if (ra->ra_state == WAIT_RAR && !ra->cfra){ + LOG_I(NR_MAC,"[RAPROC][%d.%d] RA-Msg3 transmitted\n", frame_tx, slot_tx); + nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->gNB_index); + } + } + } + pthread_mutex_unlock(&ul_config->mutex_ul_config); // avoid double lock + + fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, mod_id, cc_id, frame_tx, slot_tx, ul_info->thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ + mac->if_module->scheduled_response(&scheduled_response); + } + pthread_mutex_lock(&ul_config->mutex_ul_config); + } + pthread_mutex_unlock(&ul_config->mutex_ul_config); + } + } + + if (dl_info) { + return (CONNECTION_OK); + } + module_id_t mod_id = ul_info->module_id; + frame_t txFrameP = ul_info->frame_tx; + slot_t txSlotP = ul_info->slot_tx; + + // Handle the SR/BSR procedures per subframe + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + uint8_t gNB_indexP=0; + + // Call BSR procedure as described in Section 5.4.5 in 38.321 + + // First check ReTxBSR Timer because it is always configured + // Decrement ReTxBSR Timer if it is running and not null + if ((mac->scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING) && (mac->scheduling_info.retxBSR_SF != 0)) { + mac->scheduling_info.retxBSR_SF--; + } + + // Decrement Periodic Timer if it is running and not null + if ((mac->scheduling_info.periodicBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING) && (mac->scheduling_info.periodicBSR_SF != 0)) { + mac->scheduling_info.periodicBSR_SF--; + } + + //Check whether Regular BSR is triggered + if (nr_update_bsr(mod_id, txFrameP, txSlotP, gNB_indexP) == TRUE) { + // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures + // outlined in Sections 5.4.4 an 5.4.5 of 38.321 + mac->scheduling_info.SR_pending = 1; + // Regular BSR trigger + mac->BSR_reporting_active |= NR_BSR_TRIGGER_REGULAR; + LOG_D(NR_MAC, "[UE %d][BSR] Regular BSR Triggered Frame %d slot %d SR for PUSCH is pending\n", + mod_id, txFrameP, txSlotP); + } + return UE_CONNECTION_OK; + +} + +boolean_t +nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index) { + mac_rlc_status_resp_t rlc_status; + boolean_t bsr_regular_triggered = FALSE; + uint8_t lcid; + uint8_t lcgid; + uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined + uint32_t lcgid_buffer_remain[NR_MAX_NUM_LCGID] = {0,0,0,0,0,0,0,0}; + int32_t lcid_bytes_in_buffer[NR_MAX_NUM_LCID]; + /* Array for ordering LCID with data per decreasing priority order */ + uint8_t lcid_reordered_array[NR_MAX_NUM_LCID]= + {NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID, + NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID, + NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID, + NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID,NR_MAX_NUM_LCID, + }; + uint8_t pos_next = 0; + //uint8_t highest_priority = 16; + uint8_t array_index = 0; + // Reset All BSR Infos + lcid_bytes_in_buffer[0] = 0; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + for (lcid=DCCH; lcid < NR_MAX_NUM_LCID; lcid++) { + // Reset transmission status + lcid_bytes_in_buffer[lcid] = 0; + mac->scheduling_info.LCID_status[lcid]=LCID_EMPTY; + } + + for (lcgid=0; lcgid < NR_MAX_NUM_LCGID; lcgid++) { + // Reset Buffer Info + mac->scheduling_info.BSR[lcgid]=0; + mac->scheduling_info.BSR_bytes[lcgid]=0; + } + + //Get Buffer Occupancy and fill lcid_reordered_array + for (lcid=DCCH; lcid < NR_MAX_NUM_LCID; lcid++) { + //if (mac->logicalChannelConfig[lcid]) { + if (mac->logicalChannelBearer_exist[lcid] ) { // todo + lcgid = mac->scheduling_info.LCGID[lcid]; + + // Store already available data to transmit per Group + if (lcgid < NR_MAX_NUM_LCGID) { + lcgid_buffer_remain[lcgid] += mac->scheduling_info.LCID_buffer_remain[lcid]; + } + + rlc_status = mac_rlc_status_ind(module_idP, mac->crnti,gNB_index,frameP,slotP,ENB_FLAG_NO,MBMS_FLAG_NO, lcid, 0, 0); + + lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer; + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(NR_MAC,"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d slot %d\n", + module_idP, lcid,lcgid,rlc_status.bytes_in_buffer,frameP,slotP); + mac->scheduling_info.LCID_status[lcid] = LCID_NOT_EMPTY; + + //Update BSR_bytes and position in lcid_reordered_array only if Group is defined + if (lcgid < NR_MAX_NUM_LCGID) { + num_lcid_with_data ++; + // sum lcid buffer which has same lcgid + mac->scheduling_info.BSR_bytes[lcgid] += rlc_status.bytes_in_buffer; + //Fill in the array + array_index = 0; + + do { + //if (mac->logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority) { + if (1) { // todo + //Insert if priority is higher or equal (lower or equal in value) + for (pos_next=num_lcid_with_data-1; pos_next > array_index; pos_next--) { + lcid_reordered_array[pos_next] = lcid_reordered_array[pos_next - 1]; + } + + lcid_reordered_array[array_index] = lcid; + break; + } + + array_index ++; + } while ((array_index < num_lcid_with_data) && (array_index < NR_MAX_NUM_LCID)); + } + } + } + } + + // Check whether a regular BSR can be triggered according to the first cases in 38.321 + if (num_lcid_with_data) { + LOG_D(NR_MAC, "[UE %d] PDCCH Tick at frame %d slot %d: NumLCID with data=%d Reordered LCID0=%d LCID1=%d LCID2=%d\n", + module_idP, frameP, slotP, num_lcid_with_data, + lcid_reordered_array[0], lcid_reordered_array[1], + lcid_reordered_array[2]); + + for (array_index = 0; array_index < num_lcid_with_data; array_index++) { + lcid = lcid_reordered_array[array_index]; + + /* UL data, for a logical channel which belongs to a LCG, becomes available for transmission in the RLC entity + either the data belongs to a logical channel with higher priority than the priorities of the logical channels + which belong to any LCG and for which data is already available for transmission + */ + { + bsr_regular_triggered = TRUE; + LOG_D(NR_MAC, "[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d slot %d\n", + module_idP, lcid, + mac->scheduling_info.LCGID[lcid], + frameP, slotP); + break; + } + } + + // Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission + if (mac->scheduling_info.retxBSR_SF == 0) { + bsr_regular_triggered = TRUE; + + if ((mac->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0) { + LOG_I(NR_MAC, "[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d slot %d\n", + module_idP, frameP, slotP); + } + } + } + + //Store Buffer Occupancy in remain buffers for next TTI + for (lcid = DCCH; lcid < NR_MAX_NUM_LCID; lcid++) { + mac->scheduling_info.LCID_buffer_remain[lcid] = lcid_bytes_in_buffer[lcid]; + } + + return bsr_regular_triggered; +} + +uint8_t +nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int value) { + uint8_t ju, jm, jl; + int ascend; + //DevAssert(size > 0); + //DevAssert(size <= 256); + + if (value == 0) { + return 0; //elseif (value > 150000) return 63; + } + + jl = 0; // lower bound + ju = size - 1; // upper bound + ascend = (table[ju] >= table[jl]) ? 1 : 0; // determine the order of the the table: 1 if ascending order of table, 0 otherwise + + while (ju - jl > 1) { //If we are not yet done, + jm = (ju + jl) >> 1; //compute a midpoint, + + if ((value >= table[jm]) == ascend) { + jl = jm; // replace the lower limit + } else { + ju = jm; //replace the upper limit + } + + LOG_T(NR_MAC, "[UE] searching BSR index %d for (BSR TABLE %d < value %d)\n", + jm, table[jm], value); + } + + if (value == table[jl]) { + return jl; + } else { + return jl + 1; //equally ju + } +} + +int nr_get_sf_periodicBSRTimer(uint8_t sf_offset) { + switch (sf_offset) { + case NR_BSR_Config__periodicBSR_Timer_sf1: + return 1; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf5: + return 5; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf10: + return 10; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf16: + return 16; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf20: + return 20; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf32: + return 32; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf40: + return 40; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf64: + return 64; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf80: + return 80; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf128: + return 128; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf160: + return 160; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf320: + return 320; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf640: + return 640; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf1280: + return 1280; + break; + + case NR_BSR_Config__periodicBSR_Timer_sf2560: + return 2560; + break; + + case NR_BSR_Config__periodicBSR_Timer_infinity: + default: + return 0xFFFF; + break; + } +} + +int nr_get_sf_retxBSRTimer(uint8_t sf_offset) { + switch (sf_offset) { + case NR_BSR_Config__retxBSR_Timer_sf10: + return 10; + break; + + case NR_BSR_Config__retxBSR_Timer_sf20: + return 20; + break; + + case NR_BSR_Config__retxBSR_Timer_sf40: + return 40; + break; + + case NR_BSR_Config__retxBSR_Timer_sf80: + return 80; + break; + + case NR_BSR_Config__retxBSR_Timer_sf160: + return 160; + break; + + case NR_BSR_Config__retxBSR_Timer_sf320: + return 320; + break; + + case NR_BSR_Config__retxBSR_Timer_sf640: + return 640; + break; + + case NR_BSR_Config__retxBSR_Timer_sf1280: + return 1280; + break; + + case NR_BSR_Config__retxBSR_Timer_sf2560: + return 2560; + break; + + case NR_BSR_Config__retxBSR_Timer_sf5120: + return 5120; + break; + + case NR_BSR_Config__retxBSR_Timer_sf10240: + return 10240; + break; + + default: + return -1; + break; + } +} + +// PUSCH scheduler: +// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, +// - where K2 is the offset between the slot in which UL DCI is received and the slot +// - in which ULSCH should be scheduled. K2 is configured in RRC configuration. +// PUSCH Msg3 scheduler: +// - scheduled by RAR UL grant according to 8.3 of TS 38.213 +// Note: Msg3 tx in the uplink symbols of mixed slot +int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, + uint8_t is_Msg3, + frame_t current_frame, + int current_slot, + frame_t *frame_tx, + int *slot_tx, + uint8_t tda_id){ + + int delta = 0; + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + // Get the numerology to calculate the Tx frame and slot + int mu = ubwp ? + ubwp->bwp_Common->genericParameters.subcarrierSpacing : + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.subcarrierSpacing; + + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ubwp ? + ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList: + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + // k2 as per 3GPP TS 38.214 version 15.9.0 Release 15 ch 6.1.2.1.1 + // PUSCH time domain resource allocation is higher layer configured from uschTimeDomainAllocationList in either pusch-ConfigCommon + int k2; + + if (is_Msg3) { + k2 = *pusch_TimeDomainAllocationList->list.array[tda_id]->k2; + + switch (mu) { + case 0: + delta = 2; + break; + case 1: + delta = 3; + break; + case 2: + delta = 4; + break; + case 3: + delta = 6; + break; + } + + AssertFatal((k2+delta) >= DURATION_RX_TO_TX, + "Slot offset (%d) for Msg3 cannot be less than DURATION_RX_TO_TX (%d)\n", + k2+delta,DURATION_RX_TO_TX); + + *slot_tx = (current_slot + k2 + delta) % nr_slots_per_frame[mu]; + if (current_slot + k2 + delta > nr_slots_per_frame[mu]){ + *frame_tx = (current_frame + 1) % 1024; + } else { + *frame_tx = current_frame; + } + + } else { + + // Get slot offset K2 which will be used to calculate TX slot + k2 = get_k2(mac, tda_id); + if (k2 < 0) { // This can happen when a false DCI is received + LOG_W(PHY,"%d.%d. Received k2 %d, tda_id %d\n",current_frame,current_slot,k2,tda_id); + return -1; + } + + // Calculate TX slot and frame + *slot_tx = (current_slot + k2) % nr_slots_per_frame[mu]; + *frame_tx = ((current_slot + k2) > nr_slots_per_frame[mu]) ? (current_frame + 1) % 1024 : current_frame; + + } + + LOG_D(NR_MAC, "In %s: currently at [%d.%d] UL transmission in [%d.%d] (k2 %d delta %d)\n", __FUNCTION__, current_frame, current_slot, *frame_tx, *slot_tx, k2, delta); + + return 0; + +} + +// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config +static void build_ro_list(NR_UE_MAC_INST_t *mac) { + + int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers + int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers + uint8_t slot_shift_for_map; + uint8_t map_shift; + boolean_t even_slot_invalid; + int64_t s_map; + uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot + uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot + uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols) + uint8_t frame; // Maximum is NB_FRAMES_IN_MAX_ASSOCIATION_PATTERN_PERIOD + uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz + uint16_t format = 0xffff; + uint8_t format2 = 0xff; + int nb_fdm; + + uint8_t config_index, mu; + int msg1_FDM; + + uint8_t prach_conf_period_idx; + uint8_t nb_of_frames_per_prach_conf_period; + uint8_t prach_conf_period_frame_idx; + int64_t *prach_config_info_p; + + NR_RACH_ConfigCommon_t *setup = (mac->scc) ? + mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup: + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + + config_index = rach_ConfigGeneric->prach_ConfigurationIndex; + + if (setup->msg1_SubcarrierSpacing) { + mu = *setup->msg1_SubcarrierSpacing; + } else if(mac->scc) { + mu = mac->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + } else { + mu = get_softmodem_params()->numerology; + } + + msg1_FDM = rach_ConfigGeneric->msg1_FDM; + + switch (msg1_FDM){ + case 0: + case 1: + case 2: + case 3: + nb_fdm = 1 << msg1_FDM; + break; + default: + AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM); + } + + // Create the PRACH occasions map + // ============================== + // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule + + int unpaired = mac->phy_config.config_req.cell_config.frame_duplex_type; + + prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, unpaired); + + // Identify the proper PRACH Configuration Index table according to the operating frequency + LOG_D(NR_MAC,"mu = %u, PRACH config index = %u, unpaired = %u\n", mu, config_index, unpaired); + + if (mac->frequency_range == FR2) { //FR2 + + x = prach_config_info_p[2]; + y = prach_config_info_p[3]; + y2 = prach_config_info_p[4]; + + s_map = prach_config_info_p[5]; + + prach_conf_start_symbol = prach_config_info_p[6]; + N_t_slot = prach_config_info_p[8]; + N_dur = prach_config_info_p[9]; + if (prach_config_info_p[1] != -1) + format2 = (uint8_t) prach_config_info_p[1]; + format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); + + slot_shift_for_map = mu-2; + if ( (mu == 3) && (prach_config_info_p[7] == 1) ) + even_slot_invalid = true; + else + even_slot_invalid = false; + } + else { // FR1 + x = prach_config_info_p[2]; + y = prach_config_info_p[3]; + y2 = y; + + s_map = prach_config_info_p[4]; + + prach_conf_start_symbol = prach_config_info_p[5]; + N_t_slot = prach_config_info_p[7]; + N_dur = prach_config_info_p[8]; + LOG_D(NR_MAC,"N_t_slot %d, N_dur %d\n",N_t_slot,N_dur); + if (prach_config_info_p[1] != -1) + format2 = (uint8_t) prach_config_info_p[1]; + format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); + + slot_shift_for_map = mu; + if ( (mu == 1) && (prach_config_info_p[6] <= 1) ) + // no prach in even slots @ 30kHz for 1 prach per subframe + even_slot_invalid = true; + else + even_slot_invalid = false; + } // FR2 / FR1 + + prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; + nb_of_frames_per_prach_conf_period = x; + + LOG_D(NR_MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); + + // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period + // ---------------------------------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------------------------------- + // For every PRACH configuration periods + // ------------------------------------- + for (prach_conf_period_idx=0; prach_conf_period_idx> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz + if ( (s_map>>map_shift)&0x01 ) { + // Valid slot + + // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also + if ( even_slot_invalid && (slot%2 == 0) ) + continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe + + // We're good: valid frame and valid slot + // Compute all the PRACH occasions in the slot + + uint8_t n_prach_occ_in_time; + uint8_t n_prach_occ_in_freq; + + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm; + + for (n_prach_occ_in_time=0; n_prach_occ_in_timestart_symbol = start_symbol; + prach_occasion_p->fdm = n_prach_occ_in_freq; + prach_occasion_p->frame = frame; + prach_occasion_p->slot = slot; + prach_occasion_p->format = format; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; + + LOG_D(NR_MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", + frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq); + } // For every freq in the slot + } // For every time occasions in the slot + } // Valid slot? + } // For every slots in a frame + } // Valid frame? + } // For every frames in a prach configuration period + } // For every prach configuration periods in the maximum association pattern period (160ms) +} + +// Build the list of all the valid/transmitted SSBs according to the config +static void build_ssb_list(NR_UE_MAC_INST_t *mac) { + + // Create the list of transmitted SSBs + // =================================== + BIT_STRING_t *ssb_bitmap; + uint64_t ssb_positionsInBurst; + uint8_t ssb_idx = 0; + + if (mac->scc) { + NR_ServingCellConfigCommon_t *scc = mac->scc; + switch (scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(NR_MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(NR_MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); + LOG_D(NR_MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + default: + AssertFatal(false,"ssb_PositionsInBurst not present\n"); + break; + } + } else { // This is configuration from SIB1 + + AssertFatal(mac->scc_SIB->ssb_PositionsInBurst.groupPresence == NULL, "Handle case for >8 SSBs\n"); + ssb_bitmap = &mac->scc_SIB->ssb_PositionsInBurst.inOneGroup; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + + LOG_D(NR_MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + } +} + +// Map the transmitted SSBs to the ROs and create the association pattern according to the config +static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac) { + + // Map SSBs to PRACH occasions + // =========================== + // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule + NR_RACH_ConfigCommon_t *setup = (mac->scc) ? + mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup: + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; + + boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB + uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB + uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs + uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs + + // Determine the SSB to RACH mapping ratio + // ======================================= + switch (ssb_perRACH_config){ + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 8; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 4; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 1; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 4; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 8; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 16; + break; + default: + AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); + break; + } + LOG_D(NR_MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro); + + // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period + // ============================================================================================================== + // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions + // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) + // There is only one possible association period which can contain up to 16 PRACH configuration periods + LOG_D(NR_MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); + if (true == multiple_ssb_per_ro) { + required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio; + } + else { + required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio; + } + + AssertFatal(prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion>0, + "prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion shouldn't be 0 (ssb_list.nb_tx_ssb %d, ssb_rach_ratio %d\n", + ssb_list.nb_tx_ssb,ssb_rach_ratio); + required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion; + + if (required_nb_of_prach_conf_period == 1) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1; + } + else if (required_nb_of_prach_conf_period == 2) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 2; + } + else if (required_nb_of_prach_conf_period <= 4) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 4; + } + else if (required_nb_of_prach_conf_period <= 8) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 8; + } + else if (required_nb_of_prach_conf_period <= 16) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 16; + } + else { + AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period); + } + + prach_assoc_pattern.nb_of_assoc_period = 1; // WIP: only one possible association period + prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; + prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame; + + LOG_D(NR_MAC,"Assoc period %d, Nb of frames in assoc period %d\n", + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period, + prach_assoc_pattern.prach_association_period_list[0].nb_of_frame); + + // Proceed to the SSB to RO mapping + // ================================ + uint8_t association_period_idx; // Association period index within the association pattern + uint8_t ssb_idx = 0; + uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern + prach_conf_period_t *prach_conf_period_p; + + // Map all the association periods within the association pattern period + LOG_D(NR_MAC,"Proceed to the SSB to RO mapping\n"); + for (association_period_idx=0; association_period_idxnb_of_frame; frame++) { + for (slot=0; slotnb_of_slot; slot++) { + for (ro_in_time=0; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { + for (ro_in_freq=0; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + + // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO + // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + for (; ssb_idxmapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; + ro_p->nb_mapped_ssb++; + ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + + LOG_D(NR_MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", + ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, + prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(NR_MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + + // If all the required SSBs are mapped to this RO, exit the loop of SSBs + if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { + ssb_idx++; + break; + } + } // if ssb_idx is transmitted + } // for ssb_idx + + // Exit the loop of ROs if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for ro_in_freq + + // Exit the loop of ROs if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for ro_in_time + + // Exit the loop of slots if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for slot + + // Exit the loop frames if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for frame + + // Exit the loop of PRACH configurations if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for n_prach_conf + + // WIP: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation + + } // if multiple_ssbs_per_ro + + else { + // -------------------- + // -------------------- + // Multiple ROs per SSB + // -------------------- + // -------------------- + + n_prach_conf = 0; + + // Go through the list of transmitted SSBs + for (ssb_idx=0; ssb_idx %d\n", + ssb_idx,ssb_list.tx_ssb[ssb_idx].transmitted); + + // Map only the transmitted ssb_idx + if (true == ssb_list.tx_ssb[ssb_idx].transmitted) { + + // Map all the required ROs to this SSB + // Go through the list of PRACH config periods within this association period + for (; n_prach_confnb_of_frame; frame++) { + for (; slotnb_of_slot; slot++) { + for (; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { + for (; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + + ro_p->mapped_ssb_idx[0] = ssb_idx; + ro_p->nb_mapped_ssb = 1; + ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + nb_mapped_ro_in_association_period++; + + LOG_D(NR_MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", + ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, + prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(NR_MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); + + // Exit the loop if this SSB has been mapped to all the required ROs + // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period: + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + ro_in_freq++; + break; + } + } // for ro_in_freq + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index + } // for ro_in_time + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index + } // for slot + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index + } // for frame + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index + } // for n_prach_conf + + } // if ssb_idx is transmitted + } // for ssb_idx + } // else if multiple_ssbs_per_ro + + } // for association_period_index +} + +// Returns a RACH occasion if any matches the SSB idx, the frame and the slot +static int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, + int frame, + int slot, + prach_occasion_info_t **prach_occasion_info_pp) { + + ssb_info_t *ssb_info_p; + prach_occasion_slot_t *prach_occasion_slot_p = NULL; + + *prach_occasion_info_pp = NULL; + + // Search for a matching RO slot in the SSB_to_RO map + // A valid RO slot will match: + // - ssb_idx mapped to one of the ROs in that RO slot + // - exact slot number + // - frame offset + ssb_info_p = &ssb_list.tx_ssb[ssb_idx]; + LOG_D(NR_MAC,"checking for prach : ssb_info_p->nb_mapped_ro %d\n",ssb_info_p->nb_mapped_ro); + for (uint8_t n_mapped_ro=0; n_mapped_ronb_mapped_ro; n_mapped_ro++) { + LOG_D(NR_MAC,"%d.%d: mapped_ro[%d]->frame.slot %d.%d, prach_assoc_pattern.nb_of_frame %d\n", + frame,slot,n_mapped_ro,ssb_info_p->mapped_ro[n_mapped_ro]->frame,ssb_info_p->mapped_ro[n_mapped_ro]->slot,prach_assoc_pattern.nb_of_frame); + if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && + (ssb_info_p->mapped_ro[n_mapped_ro]->frame == (frame % prach_assoc_pattern.nb_of_frame))) { + + uint8_t prach_config_period_nb = ssb_info_p->mapped_ro[n_mapped_ro]->frame / prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; + uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ro[n_mapped_ro]->frame % prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; + prach_occasion_slot_p = &prach_assoc_pattern.prach_conf_period_list[prach_config_period_nb].prach_occasion_slot_map[frame_nb_in_prach_config_period][slot]; + } + } + + // If there is a matching RO slot in the SSB_to_RO map + if (NULL != prach_occasion_slot_p) + { + // A random RO mapped to the SSB index should be selected in the slot + + // First count the number of times the SSB index is found in that RO + uint8_t nb_mapped_ssb = 0; + + for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) { + for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { + if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { + nb_mapped_ssb++; + } + } + } + } + + // Choose a random SSB nb + uint8_t random_ssb_nb = 0; + + random_ssb_nb = ((taus()) % nb_mapped_ssb); + + // Select the RO according to the chosen random SSB nb + nb_mapped_ssb=0; + for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) { + for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { + if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { + if (nb_mapped_ssb == random_ssb_nb) { + *prach_occasion_info_pp = prach_occasion_info_p; + return 1; + } + else { + nb_mapped_ssb++; + } + } + } + } + } + } + + return 0; +} + +// Build the SSB to RO mapping upon RRC configuration update +void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac) { + + // Clear all the lists and maps + memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); + memset(&ssb_list, 0, sizeof(ssb_list_info_t)); + + // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config + LOG_D(NR_MAC,"Build RO list\n"); + build_ro_list(mac); + + // Build the list of all the valid/transmitted SSBs according to the config + LOG_D(NR_MAC,"Build SSB list\n"); + build_ssb_list(mac); + + // Map the transmitted SSBs to the ROs and create the association pattern according to the config + LOG_D(NR_MAC,"Map SSB to RO\n"); + map_ssb_to_ro(mac); + LOG_D(NR_MAC,"Map SSB to RO done\n"); +} + + +void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, int thread_id) { + + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + int O_SR = 0; + int O_ACK = 0; + int O_CSI = 0; + int N_UCI = 0; + + PUCCH_sched_t *pucch = calloc(1,sizeof(*pucch)); + pucch->resource_indicator = -1; + pucch->initial_pucch_id = -1; + uint16_t rnti = mac->crnti; //FIXME not sure this is valid for all pucch instances + + // SR + if(trigger_periodic_scheduling_request(mac, pucch, frameP, slotP)) { + O_SR = 1; + /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */ + pucch->sr_payload = nr_ue_get_SR(module_idP, + frameP, + slotP); + } + + // CSI + if (mac->ra.ra_state == RA_SUCCEEDED || + get_softmodem_params()->phy_test == 1) + O_CSI = nr_get_csi_measurements(mac, frameP, slotP, pucch); + + // ACKNACK + O_ACK = get_downlink_ack(mac, frameP, slotP, pucch); + + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; + NR_PUCCH_Config_t *pucch_Config = NULL; + + if (bwp_id>0 && + mac->ULbwp[bwp_id-1] && + mac->ULbwp[bwp_id-1]->bwp_Dedicated && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config && + mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup) { + pucch_Config = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup; + } + else if (bwp_id==0 && + mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + } + + + // if multiplexing of HARQ and CSI is not possible, transmit only HARQ bits + if ((O_ACK != 0) && (O_CSI != 0) && + pucch_Config && + pucch_Config->format2 && + (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)) { + O_CSI = 0; + pucch->csi_part1_payload = 0; + pucch->csi_part2_payload = 0; + } + + N_UCI = O_SR + O_ACK + O_CSI; + + // do no transmit pucch if only SR scheduled and it is negative + if ((O_ACK + O_CSI) == 0 && pucch->sr_payload == 0) + return; + + if (N_UCI > 0) { + + LOG_D(NR_MAC,"%d.%d configure pucch, O_SR %d, O_ACK %d, O_CSI %d\n",frameP,slotP,O_SR,O_ACK,O_CSI); + pucch->resource_set_id = find_pucch_resource_set(mac, O_ACK + O_CSI); + select_pucch_resource(mac, pucch); + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slotP); + pthread_mutex_lock(&ul_config->mutex_ul_config); + AssertFatal(ul_config->number_pdusnumber_pdus %d out of bounds\n",ul_config->number_pdus); + fapi_nr_ul_config_pucch_pdu *pucch_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu; + + fill_ul_config(ul_config, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PUCCH); + pthread_mutex_unlock(&ul_config->mutex_ul_config); + + nr_ue_configure_pucch(mac, + slotP, + rnti, + pucch, + pucch_pdu, + O_SR, O_ACK, O_CSI); + LOG_D(NR_MAC,"Configuring pucch, is_common = %d\n",pucch->is_common); + nr_scheduled_response_t scheduled_response; + fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); + } + +} + +// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x +// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. +// - todo: +// - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config +void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, int thread_id) { + + uint16_t format, format0, format1, ncs; + int is_nr_prach_slot; + prach_occasion_info_t *prach_occasion_info_p; + + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + RA_config_t *ra = &mac->ra; + + //fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slotP); + fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request[0]; + fapi_nr_ul_config_prach_pdu *prach_config_pdu; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + fapi_nr_prach_config_t *prach_config = &cfg->prach_config; + nr_scheduled_response_t scheduled_response; + + NR_ServingCellConfigCommon_t *scc = mac->scc; + NR_ServingCellConfigCommonSIB_t *scc_SIB = mac->scc_SIB; + NR_RACH_ConfigCommon_t *setup; + if (scc!=NULL) setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + else setup = scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + + ra->RA_offset = 2; // to compensate the rx frame offset at the gNB + ra->generate_nr_prach = GENERATE_IDLE; // Reset flag for PRACH generation + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = scc==NULL ? scc_SIB->tdd_UL_DL_ConfigurationCommon : scc->tdd_UL_DL_ConfigurationCommon; + + if (is_nr_UL_slot(tdd_config, slotP, mac->frame_type)) { + + // WIP Need to get the proper selected ssb_idx + // Initial beam selection functionality is not available yet + uint8_t selected_gnb_ssb_idx = mac->mib_ssb; + + // Get any valid PRACH occasion in the current slot for the selected SSB index + is_nr_prach_slot = get_nr_prach_info_from_ssb_index(selected_gnb_ssb_idx, + (int)frameP, + (int)slotP, + &prach_occasion_info_p); + + if (is_nr_prach_slot && ra->ra_state == RA_UE_IDLE) { + AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n"); + + ra->generate_nr_prach = GENERATE_PREAMBLE; + + format = prach_occasion_info_p->format; + format0 = format & 0xff; // single PRACH format + format1 = (format >> 8) & 0xff; // dual PRACH format + + pthread_mutex_lock(&ul_config->mutex_ul_config); + AssertFatal(ul_config->number_pdusnumber_pdus %d out of bounds\n",ul_config->number_pdus); + prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; + + fill_ul_config(ul_config, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH); + pthread_mutex_unlock(&ul_config->mutex_ul_config); + LOG_D(PHY, "In %s: (%p) %d UL PDUs:\n", __FUNCTION__, ul_config, ul_config->number_pdus); + + memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); + + ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); + + prach_config_pdu->phys_cell_id = mac->physCellId; + prach_config_pdu->num_prach_ocas = 1; + prach_config_pdu->prach_slot = prach_occasion_info_p->slot; + prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; + prach_config_pdu->num_ra = prach_occasion_info_p->fdm; + + prach_config_pdu->num_cs = ncs; + prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index; + prach_config_pdu->restricted_set = prach_config->restricted_set_config; + prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; + + LOG_D(NR_MAC,"Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", frameP, prach_config_pdu->prach_slot, prach_config_pdu->prach_start_symbol, prach_config_pdu->num_ra); + + // Search which SSB is mapped in the RO (among all the SSBs mapped to this RO) + for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ronb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) { + if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx) + break; + } + AssertFatal(prach_config_pdu->ssb_nb_in_ronb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx); + + if (format1 != 0xff) { + switch(format0) { // dual PRACH format + case 0xa1: + prach_config_pdu->prach_format = 11; + break; + case 0xa2: + prach_config_pdu->prach_format = 12; + break; + case 0xa3: + prach_config_pdu->prach_format = 13; + break; + default: + AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); + } + } else { + switch(format0) { // single PRACH format + case 0: + prach_config_pdu->prach_format = 0; + break; + case 1: + prach_config_pdu->prach_format = 1; + break; + case 2: + prach_config_pdu->prach_format = 2; + break; + case 3: + prach_config_pdu->prach_format = 3; + break; + case 0xa1: + prach_config_pdu->prach_format = 4; + break; + case 0xa2: + prach_config_pdu->prach_format = 5; + break; + case 0xa3: + prach_config_pdu->prach_format = 6; + break; + case 0xb1: + prach_config_pdu->prach_format = 7; + break; + case 0xb4: + prach_config_pdu->prach_format = 8; + break; + case 0xc0: + prach_config_pdu->prach_format = 9; + break; + case 0xc2: + prach_config_pdu->prach_format = 10; + break; + default: + AssertFatal(1 == 0, "Invalid PRACH format"); + } + } // if format1 + + fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); + } // is_nr_prach_slot + } // if is_nr_UL_slot +} + +// This function schedules the reception of SIB1 after initial sync and before going to real time state +void nr_ue_sib1_scheduler(module_id_t module_idP, + int cc_id, + uint16_t ssb_start_symbol, + uint16_t frame, + uint8_t ssb_subcarrier_offset, + uint32_t ssb_index, + uint16_t ssb_start_subcarrier, + frequency_range_t frequency_range) { + + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + nr_scheduled_response_t scheduled_response; + int frame_s,slot_s; + fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; + + uint8_t scs_ssb = get_softmodem_params()->numerology; + uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; + + get_type0_PDCCH_CSS_config_parameters(&mac->type0_PDCCH_CSS_config, + frame, + mac->mib, + nr_slots_per_frame[scs_ssb], + ssb_subcarrier_offset, + ssb_start_symbol, + scs_ssb, + frequency_range, + mac->nr_band, + ssb_index, + 1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame + ssb_offset_point_a); + + if(mac->search_space_zero == NULL) mac->search_space_zero=calloc(1,sizeof(*mac->search_space_zero)); + if(mac->coreset0 == NULL) mac->coreset0 = calloc(1,sizeof(*mac->coreset0)); + + fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); + fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config); + rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); + fill_dci_search_candidates(mac->search_space_zero, rel15); + + if(mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern == 1){ + // same frame as ssb + if ((mac->type0_PDCCH_CSS_config.frame & 0x1) == mac->type0_PDCCH_CSS_config.sfn_c) + frame_s = 0; + else + frame_s = 1; + slot_s = mac->type0_PDCCH_CSS_config.n_0; + } + else{ + frame_s = 0; // same frame as ssb + slot_s = mac->type0_PDCCH_CSS_config.n_c; + } + LOG_D(MAC,"Calling fill_scheduled_response, type0_pdcch, num_pdus %d\n",dl_config->number_pdus); + fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, module_idP, cc_id, frame_s, slot_s, 0); // TODO fix thread_id, for now assumed 0 + + if (dl_config->number_pdus) { + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); + } + else + AssertFatal(1==0,"Unable to find aggregation level for type0 CSS\n"); +} + + +#define MAX_LCID 8 // NR_MAX_NUM_LCID shall be used but the mac_rlc_data_req function can fetch data for max 8 LCID +typedef struct { + uint8_t bsr_len; + uint8_t bsr_ce_len; + uint8_t bsr_header_len; + uint8_t phr_len; + uint8_t phr_ce_len; + uint8_t phr_header_len; + uint16_t sdu_length_total; + NR_BSR_SHORT *bsr_s; + NR_BSR_LONG *bsr_l; + NR_BSR_SHORT *bsr_t; + //NR_POWER_HEADROOM_CMD *phr_pr; + int tot_mac_ce_len; + uint8_t total_mac_pdu_header_len; +} NR_UE_MAC_CE_INFO; + +/* +nr_ue_get_sdu_mac_ce_pre finds length in various mac_ce field +Need nothing from mac_ce_p: +Update the following in mac_ce_p: + bsr_len; + bsr_ce_len; + bsr_header_len; + phr_len; TBD + phr_ce_len; TBD + phr_header_len; TBD +*/ +int nr_ue_get_sdu_mac_ce_pre(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t subframe, + uint8_t gNB_index, + uint8_t *ulsch_buffer, + uint16_t buflen, + NR_UE_MAC_CE_INFO *mac_ce_p) { + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + + int num_lcg_id_with_data = 0; + // Preparing the MAC CEs sub-PDUs and get the total size + mac_ce_p->bsr_header_len = 0; + mac_ce_p->phr_header_len = 0; //sizeof(SCH_SUBHEADER_FIXED); + int lcg_id = 0; + while (lcg_id < NR_MAX_NUM_LCGID) { + if (mac->scheduling_info.BSR_bytes[lcg_id]) { + num_lcg_id_with_data++; + } + + lcg_id++; + } + + //Restart ReTxBSR Timer at new grant indication (38.321) + if (mac->scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING) { + mac->scheduling_info.retxBSR_SF = nr_get_sf_retxBSRTimer(mac->scheduling_info.retxBSR_Timer); + } + + // periodicBSR-Timer expires, trigger BSR + if ((mac->scheduling_info.periodicBSR_Timer != NR_BSR_Config__periodicBSR_Timer_infinity) + && (mac->scheduling_info.periodicBSR_SF == 0)) { + // Trigger BSR Periodic + mac->BSR_reporting_active |= NR_BSR_TRIGGER_PERIODIC; + LOG_D(NR_MAC, "[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n", + module_idP, frameP, subframe, buflen); + } + + //Compute BSR Length if Regular or Periodic BSR is triggered + //WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing if there remains less than 1 LCGROUP with data after Tx + if (mac->BSR_reporting_active) { + AssertFatal((mac->BSR_reporting_active & NR_BSR_TRIGGER_PADDING) == 0, + "Inconsistent BSR Trigger=%d !\n", + mac->BSR_reporting_active); + + //A Regular or Periodic BSR can only be sent if TBS is sufficient as transmitting only a BSR is not allowed if UE has data to transmit + if (num_lcg_id_with_data <= 1) { + if (buflen >= (sizeof(NR_BSR_SHORT)+sizeof(NR_MAC_SUBHEADER_FIXED)+1)) { + mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); //1 byte + mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); //1 byte + } + } else { + if (buflen >= (num_lcg_id_with_data+1+sizeof(NR_MAC_SUBHEADER_SHORT)+1)) { + mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; //variable size + mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); //2 bytes + } + } + } + + mac_ce_p->bsr_len = mac_ce_p->bsr_ce_len + mac_ce_p->bsr_header_len; + return (mac_ce_p->bsr_len + mac_ce_p->phr_len); +} + +/* +nr_ue_get_sdu_mac_ce_post recalculates length and prepares the mac_ce field +Need the following from mac_ce_p: + bsr_ce_len + bsr_len + sdu_length_total + total_mac_pdu_header_len +Update the following in mac_ce_p: + bsr_ce_len + bsr_header_len + bsr_len + tot_mac_ce_len + total_mac_pdu_header_len + bsr_s + bsr_l + bsr_t +*/ +void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t subframe, + uint8_t gNB_index, + uint8_t *ulsch_buffer, + uint16_t buflen, + NR_UE_MAC_CE_INFO *mac_ce_p) { + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + + // Compute BSR Values and update Nb LCGID with data after multiplexing + unsigned short padding_len = 0; + uint8_t lcid = 0; + int lcg_id = 0; + int num_lcg_id_with_data = 0; + int lcg_id_bsr_trunc = 0; + for (lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++) { + if (mac_ce_p->bsr_ce_len == sizeof(NR_BSR_SHORT)) { + mac->scheduling_info.BSR[lcg_id] = nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE, NR_SHORT_BSR_TABLE_SIZE, mac->scheduling_info.BSR_bytes[lcg_id]); + } else { + mac->scheduling_info.BSR[lcg_id] = nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE, NR_LONG_BSR_TABLE_SIZE, mac->scheduling_info.BSR_bytes[lcg_id]); + } + if (mac->scheduling_info.BSR_bytes[lcg_id]) { + num_lcg_id_with_data++; + lcg_id_bsr_trunc = lcg_id; + } + } + + // TS 38.321 Section 5.4.5 + // Check BSR padding: it is done after PHR according to Logical Channel Prioritization order + // Check for max padding size, ie MAC Hdr for last RLC PDU = 1 + /* For Padding BSR: + - if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader: + - if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission; + - else report Short BSR. + - else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR. + */ + if (mac_ce_p->sdu_length_total) { + padding_len = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total); + } + + if ((padding_len) && (mac_ce_p->bsr_len == 0)) { + /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR */ + if (padding_len >= (num_lcg_id_with_data+1+sizeof(NR_MAC_SUBHEADER_SHORT))) { + mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; //variable size + mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); //2 bytes + // Trigger BSR Padding + mac->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING; + } else if (padding_len >= (sizeof(NR_BSR_SHORT)+sizeof(NR_MAC_SUBHEADER_FIXED))) { + mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); //1 byte + mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); //1 byte + + if (num_lcg_id_with_data > 1) { + // REPORT SHORT TRUNCATED BSR + //Get LCGID of highest priority LCID with data (todo) + for (lcid = DCCH; lcid < NR_MAX_NUM_LCID; lcid++) { + lcg_id = mac->scheduling_info.LCGID[lcid]; + if ((lcg_id < NR_MAX_NUM_LCGID) && (mac->scheduling_info.BSR_bytes[lcg_id])) { + lcg_id_bsr_trunc = lcg_id; + } + } + } else { + //Report SHORT BSR, clear bsr_t + mac_ce_p->bsr_t = NULL; + } + + // Trigger BSR Padding + mac->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING; + } + + mac_ce_p->bsr_len = mac_ce_p->bsr_header_len + mac_ce_p->bsr_ce_len; + mac_ce_p->tot_mac_ce_len += mac_ce_p->bsr_len; + mac_ce_p->total_mac_pdu_header_len += mac_ce_p->bsr_len; + } + + //Fill BSR Infos + if (mac_ce_p->bsr_ce_len == 0) { + mac_ce_p->bsr_s = NULL; + mac_ce_p->bsr_l = NULL; + mac_ce_p->bsr_t = NULL; + } else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_SHORT)) { + mac_ce_p->bsr_s = NULL; + mac_ce_p->bsr_t = NULL; + mac_ce_p->bsr_l->Buffer_size0 = mac->scheduling_info.BSR[0]; + mac_ce_p->bsr_l->Buffer_size1 = mac->scheduling_info.BSR[1]; + mac_ce_p->bsr_l->Buffer_size2 = mac->scheduling_info.BSR[2]; + mac_ce_p->bsr_l->Buffer_size3 = mac->scheduling_info.BSR[3]; + mac_ce_p->bsr_l->Buffer_size4 = mac->scheduling_info.BSR[4]; + mac_ce_p->bsr_l->Buffer_size5 = mac->scheduling_info.BSR[5]; + mac_ce_p->bsr_l->Buffer_size6 = mac->scheduling_info.BSR[6]; + mac_ce_p->bsr_l->Buffer_size7 = mac->scheduling_info.BSR[7]; + LOG_D(NR_MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report LONG BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d level LCGID4 %d,level LCGID5 %d,level LCGID6 %d,level LCGID7 %d)\n", + module_idP, frameP, subframe, + mac->BSR_reporting_active, + mac->scheduling_info.BSR[0], + mac->scheduling_info.BSR[1], + mac->scheduling_info.BSR[2], + mac->scheduling_info.BSR[3], + mac->scheduling_info.BSR[4], + mac->scheduling_info.BSR[5], + mac->scheduling_info.BSR[6], + mac->scheduling_info.BSR[7]); + } else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_FIXED)) { + mac_ce_p->bsr_l = NULL; + + if ((mac_ce_p->bsr_t != NULL) && (mac->BSR_reporting_active & NR_BSR_TRIGGER_PADDING)) { + //Truncated BSR + mac_ce_p->bsr_s = NULL; + mac_ce_p->bsr_t->LcgID = lcg_id_bsr_trunc; + mac_ce_p->bsr_t->Buffer_size = mac->scheduling_info.BSR[lcg_id_bsr_trunc]; + LOG_D(NR_MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n", + module_idP, frameP, subframe, + mac->BSR_reporting_active, + mac->scheduling_info.BSR[lcg_id_bsr_trunc], lcg_id_bsr_trunc); + } else { + mac_ce_p->bsr_t = NULL; + mac_ce_p->bsr_s->LcgID = lcg_id_bsr_trunc; + mac_ce_p->bsr_s->Buffer_size = mac->scheduling_info.BSR[lcg_id_bsr_trunc]; + LOG_D(NR_MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n", + module_idP, frameP, subframe, + mac->BSR_reporting_active, + mac->scheduling_info.BSR[lcg_id_bsr_trunc], lcg_id_bsr_trunc); + } + } + + LOG_D(NR_MAC, "[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", module_idP); + mac->scheduling_info.SR_pending = 0; + mac->scheduling_info.SR_COUNTER = 0; + + /* Actions when a BSR is sent */ + if (mac_ce_p->bsr_ce_len) { + LOG_D(NR_MAC, "[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n", + module_idP, mac_ce_p->bsr_ce_len, mac_ce_p->bsr_header_len, buflen); + // Reset ReTx BSR Timer + mac->scheduling_info.retxBSR_SF = nr_get_sf_retxBSRTimer(mac->scheduling_info.retxBSR_Timer); + LOG_D(NR_MAC, "[UE %d] MAC ReTx BSR Timer Reset =%d\n", module_idP, mac->scheduling_info.retxBSR_SF); + + // Reset Periodic Timer except when BSR is truncated + if ((mac_ce_p->bsr_t == NULL) && (mac->scheduling_info.periodicBSR_Timer != NR_BSR_Config__periodicBSR_Timer_infinity)) { + mac->scheduling_info.periodicBSR_SF = nr_get_sf_periodicBSRTimer(mac->scheduling_info.periodicBSR_Timer); + LOG_D(NR_MAC, "[UE %d] MAC Periodic BSR Timer Reset =%d\n", + module_idP, + mac->scheduling_info.periodicBSR_SF); + } + + // Reset BSR Trigger flags + mac->BSR_reporting_active = BSR_TRIGGER_NONE; + } +} + +/** + * Function: to fetch data to be transmitted from RLC, place it in the ULSCH PDU buffer + to generate the complete MAC PDU with sub-headers and MAC CEs according to ULSCH MAC PDU generation (6.1.2 TS 38.321) + the selected sub-header for the payload sub-PDUs is NR_MAC_SUBHEADER_LONG + * @module_idP Module ID + * @CC_id Component Carrier index + * @frameP current UL frame + * @subframe current UL slot + * @gNB_index gNB index + * @ulsch_buffer Pointer to ULSCH PDU + * @buflen TBS + */ +uint8_t nr_ue_get_sdu(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t subframe, + uint8_t gNB_index, + uint8_t *ulsch_buffer, + uint16_t buflen) { + NR_UE_MAC_CE_INFO mac_ce_info; + NR_UE_MAC_CE_INFO *mac_ce_p=&mac_ce_info; + int16_t buflen_remain = 0; + mac_ce_p->bsr_len = 0; + mac_ce_p->bsr_ce_len = 0; + mac_ce_p->bsr_header_len = 0; + mac_ce_p->phr_len = 0; + //mac_ce_p->phr_ce_len = 0; + //mac_ce_p->phr_header_len = 0; + + uint8_t lcid = 0; + uint16_t sdu_length = 0; + uint16_t num_sdus = 0; + mac_ce_p->sdu_length_total = 0; + NR_BSR_SHORT bsr_short, bsr_truncated; + NR_BSR_LONG bsr_long; + mac_ce_p->bsr_s = &bsr_short; + mac_ce_p->bsr_l = &bsr_long; + mac_ce_p->bsr_t = &bsr_truncated; + //NR_POWER_HEADROOM_CMD phr; + //mac_ce_p->phr_p = &phr; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + //int highest_priority = 16; + const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG); + + // Pointer used to build the MAC PDU by placing the RLC SDUs in the ULSCH buffer + uint8_t *pdu = ulsch_buffer; + + //nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length + mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(module_idP, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p); + mac_ce_p->total_mac_pdu_header_len = mac_ce_p->tot_mac_ce_len; + + LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", __FUNCTION__, module_idP, frameP, subframe, buflen); + + // Check for DCCH first + // TO DO: Multiplex in the order defined by the logical channel prioritization + for (lcid = UL_SCH_LCID_SRB1; lcid < MAX_LCID; lcid++) { + + buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size); + + LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header len %d bytes, buflen_remain %d bytes)\n", + __FUNCTION__, + module_idP, + frameP, + subframe, + lcid, + buflen, + mac_ce_p->sdu_length_total, + mac_ce_p->tot_mac_ce_len, + buflen_remain); + + while (buflen_remain > 0){ + + // Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU + NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) pdu; + + pdu += sh_size; + + sdu_length = mac_rlc_data_req(module_idP, + mac->crnti, + gNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + lcid, + buflen_remain, + (char *)pdu, + 0, + 0); + + AssertFatal(buflen_remain >= sdu_length, "In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n", + __FUNCTION__, + lcid, + sdu_length, + buflen_remain); + + if (sdu_length > 0) { + + LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] UL-DXCH -> ULSCH, Generating UL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID 0x%02x (buflen (TBS) %d bytes)\n", + __FUNCTION__, + module_idP, + frameP, + subframe, + num_sdus + 1, + sdu_length, + lcid, + buflen); + + header->R = 0; + header->F = 1; + header->LCID = lcid; + header->L1 = ((unsigned short) sdu_length >> 8) & 0x7f; + header->L2 = (unsigned short) sdu_length & 0xff; + + #ifdef ENABLE_MAC_PAYLOAD_DEBUG + LOG_I(NR_MAC, "In %s: dumping MAC sub-header with length %d: \n", __FUNCTION__, sh_size); + log_dump(NR_MAC, header, sh_size, LOG_DUMP_CHAR, "\n"); + LOG_I(NR_MAC, "In %s: dumping MAC SDU with length %d \n", __FUNCTION__, sdu_length); + log_dump(NR_MAC, pdu, sdu_length, LOG_DUMP_CHAR, "\n"); + #endif + + pdu += sdu_length; + mac_ce_p->sdu_length_total += sdu_length; + mac_ce_p->total_mac_pdu_header_len += sh_size; + + num_sdus++; + + } else { + pdu -= sh_size; + LOG_D(NR_MAC, "In %s: no data to transmit for RB with LCID 0x%02x\n", __FUNCTION__, lcid); + break; + } + + buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size); + + //Update Buffer remain and BSR bytes after transmission + mac->scheduling_info.LCID_buffer_remain[lcid] -= sdu_length; + mac->scheduling_info.BSR_bytes[mac->scheduling_info.LCGID[lcid]] -= sdu_length; + LOG_D(NR_MAC, "[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%d=%d\n", + module_idP, frameP, subframe, mac->scheduling_info.LCGID[lcid], + mac->scheduling_info.BSR_bytes[mac->scheduling_info.LCGID[lcid]]); + if (mac->scheduling_info.BSR_bytes[mac->scheduling_info.LCGID[lcid]] < 0) + mac->scheduling_info.BSR_bytes[mac->scheduling_info.LCGID[lcid]] = 0; + } + } + + //nr_ue_get_sdu_mac_ce_post recalculates all mac_ce related header fields since buffer has been changed after mac_rlc_data_req. + //Also, BSR padding is handled here after knowing mac_ce_p->sdu_length_total. + nr_ue_get_sdu_mac_ce_post(module_idP, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p); + + if (mac_ce_p->tot_mac_ce_len > 0) { + + LOG_D(NR_MAC, "In %s copying %d bytes of MAC CEs to the UL PDU \n", __FUNCTION__, mac_ce_p->tot_mac_ce_len); + nr_write_ce_ulsch_pdu(pdu, mac, 0, NULL, mac_ce_p->bsr_t, mac_ce_p->bsr_s, mac_ce_p->bsr_l); + pdu += (unsigned char) mac_ce_p->tot_mac_ce_len; + + #ifdef ENABLE_MAC_PAYLOAD_DEBUG + LOG_I(NR_MAC, "In %s: dumping MAC CE with length tot_mac_ce_len %d: \n", __FUNCTION__, mac_ce_p->tot_mac_ce_len); + log_dump(NR_MAC, mac_header_control_elements, mac_ce_p->tot_mac_ce_len, LOG_DUMP_CHAR, "\n"); + #endif + + } + + buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total); + + // Compute final offset for padding and fill remainder of ULSCH with 0 + if (buflen_remain > 0) { + + LOG_D(NR_MAC, "In %s filling remainder %d bytes to the UL PDU \n", __FUNCTION__, buflen_remain); + ((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0; + ((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = UL_SCH_LCID_PADDING; + + #ifdef ENABLE_MAC_PAYLOAD_DEBUG + LOG_I(NR_MAC, "In %s: padding MAC sub-header with length %ld bytes \n", __FUNCTION__, sizeof(NR_MAC_SUBHEADER_FIXED)); + log_dump(NR_MAC, pdu, sizeof(NR_MAC_SUBHEADER_FIXED), LOG_DUMP_CHAR, "\n"); + #endif + + pdu++; + buflen_remain--; + + if (IS_SOFTMODEM_RFSIM) { + for (int j = 0; j < buflen_remain; j++) { + pdu[j] = (unsigned char) rand(); + } + } else { + memset(pdu, 0, buflen_remain); + } + + #ifdef ENABLE_MAC_PAYLOAD_DEBUG + LOG_I(NR_MAC, "In %s: MAC padding sub-PDU with length %d bytes \n", __FUNCTION__, buflen_remain); + log_dump(NR_MAC, pdu, buflen_remain, LOG_DUMP_CHAR, "\n"); + #endif + + } + + #ifdef ENABLE_MAC_PAYLOAD_DEBUG + LOG_I(NR_MAC, "In %s: dumping MAC PDU with length %d: \n", __FUNCTION__, buflen); + log_dump(NR_MAC, ulsch_buffer, buflen, LOG_DUMP_CHAR, "\n"); + #endif + + return num_sdus > 0 ? 1 : 0; + +} diff --git a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c deleted file mode 100644 index 8d52db6747..0000000000 --- a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file rar_tools_nrUE.c - * \brief RA tools for NR UE - * \author Guido Casati - * \date 2019 - * \version 1.0 - * @ingroup _mac - - */ - -/* Sim */ -#include "SIMULATION/TOOLS/sim.h" - -/* Utils */ -#include "common/utils/LOG/log.h" -#include "OCG.h" -#include "OCG_extern.h" -#include "UTIL/OPT/opt.h" - -/* Common */ -#include "common/ran_context.h" - -/* MAC */ -#include "NR_MAC_UE/mac.h" -#include "NR_MAC_UE/mac_proto.h" -#include "NR_MAC_COMMON/nr_mac_extern.h" -#include - -#define DEBUG_RAR - -// table 7.2-1 TS 38.321 -uint16_t table_7_2_1[16] = { - 5, // row index 0 - 10, // row index 1 - 20, // row index 2 - 30, // row index 3 - 40, // row index 4 - 60, // row index 5 - 80, // row index 6 - 120, // row index 7 - 160, // row index 8 - 240, // row index 9 - 320, // row index 10 - 480, // row index 11 - 960, // row index 12 - 1920, // row index 13 -}; - -///////////////////////////////////// -// Random Access Response PDU // -// TS 38.213 ch 8.2 // -// TS 38.321 ch 6.2.3 // -///////////////////////////////////// -//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise -//| E | T | R A P I D |// -//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// -//| R | T A |// -//| T A | UL grant |// -//| UL grant |// -//| UL grant |// -//| UL grant |// -//| T C - R N T I |// -//| T C - R N T I |// -///////////////////////////////////// -// UL grant (27 bits) // -///////////////////////////////////// -//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise -//|-------------------|FHF|F_alloc|// -//| Freq allocation |// -//| F_alloc |Time allocation|// -//| MCS | TPC |CSI|// -///////////////////////////////////// -// WIP todo: -// - apply UL grant freq alloc & time alloc as per 8.2 TS 38.213 -// - apply tpc command, csi req, mcs -uint16_t nr_ue_process_rar(module_id_t mod_id, - int CC_id, - frame_t frameP, - uint8_t * dlsch_buffer, - rnti_t * t_crnti, - uint8_t preamble_index, - uint8_t * selected_rar_buffer){ - - NR_UE_MAC_INST_t *ue_mac = get_mac_inst(mod_id); - NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer - NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer - uint8_t n_subPDUs = 0; // number of RAR payloads - uint8_t n_subheaders = 0; // number of MAC RAR subheaders - //uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs - //unsigned char freq_hopping, msg3_t_alloc, mcs, tpc_command, csi_req; // WIP - //uint16_t ta_command = 0, msg3_f_alloc, bwp_size; // WIP - uint16_t ta_command = 0; - //int f_alloc, mask; // WIP - - AssertFatal(CC_id == 0, "RAR reception on secondary CCs is not supported yet\n"); - - while (1) { - n_subheaders++; - if (rarh->T == 1) { - n_subPDUs++; - LOG_D(MAC, "[UE %d][RAPROC] Got RAPID RAR subPDU\n", mod_id); - } else { - n_subPDUs++; - ue_mac->RA_backoff_indicator = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI]; - ue_mac->RA_BI_found = 1; - LOG_D(MAC, "[UE %d][RAPROC] Got BI RAR subPDU %d\n", mod_id, ue_mac->RA_backoff_indicator); - } - if (rarh->RAPID == preamble_index) { - LOG_D(PHY, "[UE %d][RAPROC] Found RAR with the intended RAPID %d\n", mod_id, rarh->RAPID); - rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR)); - ue_mac->RA_RAPID_found = 1; - break; - } - if (rarh->E == 0) { - LOG_I(PHY, "No RAR found with the intended RAPID. \n"); - break; - } else { - rarh += sizeof(NR_MAC_RAR) + 1; - } - }; - - LOG_D(MAC, "number of RAR subheader %d; number of RAR pyloads %d\n", n_subheaders, n_subPDUs); - - // LOG_I(MAC, "[UE %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", - // mod_id, frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index); - - #if 0 // TbD WIP Msg3 development ongoing - if (ue_mac->RA_RAPID_found) { - // TC-RNTI - *t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); - ue_mac->t_crnti = *t_crnti; - ue_mac->rnti_type = NR_RNTI_TC; - // TA command - ta_command = rar->TA2 + (rar->TA1 << 5); - // CSI - csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); - // TPC - tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); - switch (tpc_command){ - case 0: - ue_mac->Msg3_TPC = -6; - break; - case 1: - ue_mac->Msg3_TPC = -4; - break; - case 2: - ue_mac->Msg3_TPC = -2; - break; - case 3: - ue_mac->Msg3_TPC = 0; - break; - case 4: - ue_mac->Msg3_TPC = 2; - break; - case 5: - ue_mac->Msg3_TPC = 4; - break; - case 6: - ue_mac->Msg3_TPC = 6; - break; - case 7: - ue_mac->Msg3_TPC = 8; - break; - } - //MCS - mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); - // time and frequency alloc - bwp_size = NRRIV2BW(ue_mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); - msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07); - msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); - - if (bwp_size < 180) - mask = (1 << ((int) ceil(log2((bwp_size*(bwp_size+1))>>1)))) - 1; - else - mask = (1 << (28 - (int)(ceil(log2((bwp_size*(bwp_size+1))>>1))))) - 1; - - f_alloc = msg3_f_alloc & mask; - - // frequency hopping flag - freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2); - } else { - ue_mac->t_crnti = 0; - ta_command = (0xffff); - } - #endif - - // move the selected RAR to the front of the RA_PDSCH buffer - memcpy((void *) (selected_rar_buffer + 0), (void *) rarh, 1); - memcpy((void *) (selected_rar_buffer + 1), (void *) rar, sizeof(NR_MAC_RAR)); - - return ta_command; -} diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 36b81927f8..ae3a3bba24 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -33,7 +33,7 @@ #include "COMMON/platform_types.h" #include "COMMON/platform_constants.h" #include "common/ran_context.h" - +#include "common/utils/nr/nr_common.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -45,13 +45,97 @@ #include "NR_MIB.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" +#include "../../../../nfapi/oai_integration/vendor_ext.h" +/* Softmodem params */ +#include "executables/softmodem-common.h" extern RAN_CONTEXT_t RC; //extern int l2_init_gNB(void); extern void mac_top_init_gNB(void); extern uint8_t nfapi_mode; -void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) { +void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list, + struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_bearer2release_list, + NR_UE_sched_ctrl_t *sched_ctrl) { + + if (rlc_bearer2add_list) + // keep lcids + for (int i=0;ilist.count;i++) { + sched_ctrl->lcid_mask |= (1<list.array[i]->logicalChannelIdentity); + LOG_I(NR_MAC,"Adding LCID %d (%s %d)\n", + (int)rlc_bearer2add_list->list.array[i]->logicalChannelIdentity, + rlc_bearer2add_list->list.array[i]->logicalChannelIdentity<4 ? "SRB" : "DRB", + (int)rlc_bearer2add_list->list.array[i]->logicalChannelIdentity); + } + if (rlc_bearer2release_list) + for (int i=0;ilist.count;i++) + sched_ctrl->lcid_mask |= (1<<*rlc_bearer2release_list->list.array[i]); + +} + + +void process_drx_Config(NR_UE_sched_ctrl_t *sched_ctrl,NR_SetupRelease_DRX_Config_t *drx_Config) { + if (!drx_Config) return; + AssertFatal(drx_Config->present != NR_SetupRelease_DRX_Config_PR_NOTHING, "Cannot have NR_SetupRelease_DRX_Config_PR_NOTHING\n"); + + if (drx_Config->present == NR_SetupRelease_DRX_Config_PR_setup) { + LOG_I(NR_MAC,"Adding DRX config\n"); + } + else { + LOG_I(NR_MAC,"Removing DRX config\n"); + } +} + +void process_schedulingRequestConfig(NR_UE_sched_ctrl_t *sched_ctrl,NR_SchedulingRequestConfig_t *schedulingRequestConfig) { + if (!schedulingRequestConfig) return; + + LOG_I(NR_MAC,"Adding SchedulingRequestconfig\n"); +} + +void process_bsrConfig(NR_UE_sched_ctrl_t *sched_ctrl,NR_BSR_Config_t *bsr_Config) { + if (!bsr_Config) return; + LOG_I(NR_MAC,"Adding BSR config\n"); +} + +void process_tag_Config(NR_UE_sched_ctrl_t *sched_ctrl,NR_TAG_Config_t *tag_Config) { + if (!tag_Config) return; + LOG_I(NR_MAC,"Adding TAG config\n"); +} + +void process_phr_Config(NR_UE_sched_ctrl_t *sched_ctrl,NR_SetupRelease_PHR_Config_t *phr_Config) { + if (!phr_Config) return; + AssertFatal(phr_Config->present != NR_SetupRelease_PHR_Config_PR_NOTHING, "Cannot have NR_SetupRelease_PHR_Config_PR_NOTHING\n"); + + if (phr_Config->present == NR_SetupRelease_PHR_Config_PR_setup) { + LOG_I(NR_MAC,"Adding PHR config\n"); + } + else { + LOG_I(NR_MAC,"Removing PHR config\n"); + } +} + +void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl) { + + AssertFatal(CellGroup, "CellGroup is null\n"); + NR_MAC_CellGroupConfig_t *mac_CellGroupConfig = CellGroup->mac_CellGroupConfig; + + + if (mac_CellGroupConfig) { + process_drx_Config(sched_ctrl,mac_CellGroupConfig->drx_Config); + process_schedulingRequestConfig(sched_ctrl,mac_CellGroupConfig->schedulingRequestConfig); + process_bsrConfig(sched_ctrl,mac_CellGroupConfig->bsr_Config); + process_tag_Config(sched_ctrl,mac_CellGroupConfig->tag_Config); + process_phr_Config(sched_ctrl,mac_CellGroupConfig->phr_Config); + } + else { + // apply defaults + + } + + process_rlcBearerConfig(CellGroup->rlc_BearerToAddModList,CellGroup->rlc_BearerToReleaseList,sched_ctrl); + +} +void config_common(int Mod_idP, int ssb_SubcarrierOffset, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) { nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[Mod_idP]->config[0]; RC.nrmac[Mod_idP]->common_channels[0].ServingCellConfigCommon = scc; @@ -64,7 +148,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); cfg->carrier_config.dl_bandwidth.tl.tag = NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG; //temporary cfg->num_tlv++; - LOG_I(PHY,"%s() dl_BandwidthP:%d\n", __FUNCTION__, cfg->carrier_config.dl_bandwidth.value); + LOG_I(NR_MAC,"%s() dl_BandwidthP:%d\n", __FUNCTION__, cfg->carrier_config.dl_bandwidth.value); cfg->carrier_config.dl_frequency.value = from_nrarfcn(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, @@ -92,7 +176,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]); cfg->carrier_config.uplink_bandwidth.tl.tag = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; //temporary cfg->num_tlv++; - LOG_I(PHY,"%s() dl_BandwidthP:%d\n", __FUNCTION__, cfg->carrier_config.uplink_bandwidth.value); + LOG_I(NR_MAC,"%s() dl_BandwidthP:%d\n", __FUNCTION__, cfg->carrier_config.uplink_bandwidth.value); int UL_pointA; if (scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA == NULL) @@ -121,15 +205,10 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm } } - lte_frame_type_t frame_type; - uint16_t band; - int32_t offset; - - get_band((cfg->carrier_config.dl_frequency.value)*1000, - &band, - &offset, - &frame_type); + uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + frequency_range_t frequency_range = band<100?FR1:FR2; + lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); RC.nrmac[Mod_idP]->common_channels[0].frame_type = frame_type; // Cell configuration @@ -147,6 +226,10 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm cfg->ssb_config.ss_pbch_power.tl.tag = NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG; cfg->num_tlv++; + cfg->ssb_config.bch_payload.value = 1; + cfg->ssb_config.bch_payload.tl.tag = NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG; + cfg->num_tlv++; + cfg->ssb_config.scs_common.value = *scc->ssbSubcarrierSpacing; cfg->ssb_config.scs_common.tl.tag = NFAPI_NR_CONFIG_SCS_COMMON_TAG; cfg->num_tlv++; @@ -170,6 +253,9 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm cfg->prach_config.restricted_set_config.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig; cfg->prach_config.restricted_set_config.tl.tag = NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG; cfg->num_tlv++; + cfg->prach_config.prach_ConfigurationIndex.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; + cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG; + cfg->num_tlv++; switch (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM) { case 0 : @@ -190,26 +276,34 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm cfg->prach_config.num_prach_fd_occasions.tl.tag = NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG; cfg->num_tlv++; + cfg->prach_config.prach_ConfigurationIndex.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; + cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG; + cfg->num_tlv++; + cfg->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(cfg->prach_config.num_prach_fd_occasions.value*sizeof(nfapi_nr_num_prach_fd_occasions_t)); for (i=0; iprach_config.num_prach_fd_occasions.value; i++) { - cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i; +// cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i; if (cfg->prach_config.prach_sequence_length.value) cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; else cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839; cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.tl.tag = NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG; cfg->num_tlv++; - cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart; + cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + (get_N_RA_RB( cfg->prach_config.prach_sub_c_spacing.value, scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i); + if (get_softmodem_params()->sa) { + cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + (get_N_RA_RB( cfg->prach_config.prach_sub_c_spacing.value, scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i); + } else { + cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + (get_N_RA_RB( cfg->prach_config.prach_sub_c_spacing.value, scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i); + } cfg->prach_config.num_prach_fd_occasions_list[i].k1.tl.tag = NFAPI_NR_CONFIG_K1_TAG; cfg->num_tlv++; cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf.tl.tag = NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG; cfg->num_tlv++; - cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.value = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, - nb_preambles, frame_type); + cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.value = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup,nb_preambles, frame_type, frequency_range); cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.tl.tag = NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG; cfg->num_tlv++; - //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences.value = ??? + cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences.value = 1; } cfg->prach_config.ssb_per_rach.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present-1; @@ -224,13 +318,25 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm scs_scaling = scs_scaling>>2; uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); uint16_t sco = absolute_diff%(12*scs_scaling); - AssertFatal(sco==0,"absoluteFrequencySSB has a subcarrier offset of %d while it should be alligned with CRBs\n",sco); + // values of subcarrier offset larger than the limit only indicates CORESET for Type0-PDCCH CSS set is not present + uint8_t ssb_SubcarrierOffset_limit = 0; + if(frequency_range == FR1) { + ssb_SubcarrierOffset_limit = 24; + } else { + ssb_SubcarrierOffset_limit = 12; + } + if (ssb_SubcarrierOffsetssb_table.ssb_offset_point_a.value = absolute_diff/(12*scs_scaling) - 10; //absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total cfg->ssb_table.ssb_offset_point_a.tl.tag = NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG; cfg->num_tlv++; cfg->ssb_table.ssb_period.value = *scc->ssb_periodicityServingCell; cfg->ssb_table.ssb_period.tl.tag = NFAPI_NR_CONFIG_SSB_PERIOD_TAG; cfg->num_tlv++; + cfg->ssb_table.ssb_subcarrier_offset.value = ssb_SubcarrierOffset; + cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG; + cfg->num_tlv++; switch (scc->ssb_PositionsInBurst->present) { case 1 : @@ -245,8 +351,8 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = 0; cfg->ssb_table.ssb_mask_list[1].ssb_mask.value = 0; for (i=0; i<4; i++) { - cfg->ssb_table.ssb_mask_list[0].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<ssb_table.ssb_mask_list[1].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<ssb_table.ssb_mask_list[0].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[3-i]<ssb_table.ssb_mask_list[1].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-i]<ssb_table.ssb_mask_list[0].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG; - cfg->num_tlv++; + cfg->ssb_table.ssb_mask_list[1].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG; + cfg->num_tlv+=2; cfg->carrier_config.num_tx_ant.value = pdsch_AntennaPorts; AssertFatal(pdsch_AntennaPorts > 0 && pdsch_AntennaPorts < 13, "pdsch_AntennaPorts in 1...12\n"); cfg->carrier_config.num_tx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_TX_ANT_TAG; + int num_ssb=0; for (int i=0;i<32;i++) { - num_ssb += (cfg->ssb_table.ssb_mask_list[0].ssb_mask.value>>i)&1; - num_ssb += (cfg->ssb_table.ssb_mask_list[1].ssb_mask.value>>i)&1; + cfg->ssb_table.ssb_beam_id_list[i].beam_id.tl.tag = NFAPI_NR_CONFIG_BEAM_ID_TAG; + if ((cfg->ssb_table.ssb_mask_list[0].ssb_mask.value>>(31-i))&1) { + cfg->ssb_table.ssb_beam_id_list[i].beam_id.value = num_ssb; + num_ssb++; + } + cfg->num_tlv++; + } + for (int i=0;i<32;i++) { + cfg->ssb_table.ssb_beam_id_list[32+i].beam_id.tl.tag = NFAPI_NR_CONFIG_BEAM_ID_TAG; + if ((cfg->ssb_table.ssb_mask_list[1].ssb_mask.value>>(31-i))&1) { + cfg->ssb_table.ssb_beam_id_list[32+i].beam_id.value = num_ssb; + num_ssb++; + } + cfg->num_tlv++; } - cfg->carrier_config.num_rx_ant.value = cfg->carrier_config.num_tx_ant.value; + cfg->carrier_config.num_rx_ant.value = pusch_AntennaPorts; + AssertFatal(pusch_AntennaPorts > 0 && pusch_AntennaPorts < 13, "pusch_AntennaPorts in 1...12\n"); cfg->carrier_config.num_rx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_RX_ANT_TAG; - LOG_I(MAC,"Set TX/RX antenna number to %d (num ssb %d: %x,%x)\n",cfg->carrier_config.num_tx_ant.value,num_ssb,cfg->ssb_table.ssb_mask_list[0].ssb_mask.value,cfg->ssb_table.ssb_mask_list[1].ssb_mask.value); + LOG_I(NR_MAC,"Set TX/RX antenna number to %d (num ssb %d: %x,%x)\n",cfg->carrier_config.num_tx_ant.value,num_ssb,cfg->ssb_table.ssb_mask_list[0].ssb_mask.value,cfg->ssb_table.ssb_mask_list[1].ssb_mask.value); AssertFatal(cfg->carrier_config.num_tx_ant.value > 0,"carrier_config.num_tx_ant.value %d !\n",cfg->carrier_config.num_tx_ant.value ); cfg->num_tlv++; cfg->num_tlv++; @@ -283,108 +404,243 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm "scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n"); cfg->tdd_table.tdd_period.value = *scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; } - LOG_I(MAC,"Setting TDD configuration period to %d\n",cfg->tdd_table.tdd_period.value); if(cfg->cell_config.frame_duplex_type.value == TDD){ - int return_tdd = set_tdd_config_nr(cfg, - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols); + LOG_I(NR_MAC,"Setting TDD configuration period to %d\n",cfg->tdd_table.tdd_period.value); + int periods_per_frame = set_tdd_config_nr(cfg, + scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols); - if (return_tdd !=0){ - LOG_E(PHY,"TDD configuration can not be done\n"); + if (periods_per_frame < 0) + LOG_E(NR_MAC,"TDD configuration can not be done\n"); + else { + LOG_I(NR_MAC,"TDD has been properly configurated\n"); + RC.nrmac[Mod_idP]->tdd_beam_association = (int16_t *)malloc16(periods_per_frame*sizeof(int16_t)); + } } - else LOG_I(PHY,"TDD has been properly configurated\n"); - } - -/* - // PDCCH-ConfigCommon - cfg->pdcch_config.controlResourceSetZero.value = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero; - cfg->pdcch_config.searchSpaceZero.value = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero; - - // PDSCH-ConfigCommon - cfg->pdsch_config.num_PDSCHTimeDomainResourceAllocations.value = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; - cfg->pdsch_config.dmrs_TypeA_Position.value = scc->dmrs_TypeA_Position; - AssertFatal(cfg->pdsch_config.num_PDSCHTimeDomainResourceAllocations.value<=NFAPI_NR_PDSCH_CONFIG_MAXALLOCATIONS,"illegal TimeDomainAllocation count %d\n",cfg->pdsch_config.num_PDSCHTimeDomainResourceAllocations.value); - for (int i=0;ipdsch_config.num_PDSCHTimeDomainResourceAllocations.value;i++) { - cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_k0[i].value=*scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0; - cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_mappingType[i].value=scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType; - cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_startSymbolAndLength[i].value=scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength; - } - - // PUSCH-ConfigCommon - cfg->pusch_config.num_PUSCHTimeDomainResourceAllocations.value = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count; - cfg->pusch_config.dmrs_TypeA_Position.value = scc->dmrs_TypeA_Position+2; - AssertFatal(cfg->pusch_config.num_PUSCHTimeDomainResourceAllocations.value<=NFAPI_NR_PUSCH_CONFIG_MAXALLOCATIONS,"illegal TimeDomainAllocation count %d\n",cfg->pusch_config.num_PUSCHTimeDomainResourceAllocations.value); - for (int i=0;ipusch_config.num_PUSCHTimeDomainResourceAllocations.value;i++) { - cfg->pusch_config.PUSCHTimeDomainResourceAllocation_k2[i].value=*scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[0]->k2; - }*/ - } - -int rrc_mac_config_req_gNB(module_id_t Mod_idP, - int ssb_SubcarrierOffset, +extern uint16_t sl_ahead; +int rrc_mac_config_req_gNB(module_id_t Mod_idP, + int ssb_SubcarrierOffset, int pdsch_AntennaPorts, + int pusch_AntennaPorts, + int sib1_tda, NR_ServingCellConfigCommon_t *scc, - int add_ue, - uint32_t rnti, - NR_CellGroupConfig_t *secondaryCellGroup - ){ + NR_BCCH_BCH_Message_t *mib, + int add_ue, + uint32_t rnti, + NR_CellGroupConfig_t *CellGroup) { if (scc != NULL ) { AssertFatal((scc->ssb_PositionsInBurst->present > 0) && (scc->ssb_PositionsInBurst->present < 4), "SSB Bitmap type %d is not valid\n",scc->ssb_PositionsInBurst->present); - LOG_I(MAC,"Configuring common parameters from NR ServingCellConfig\n"); + /* dimension UL_tti_req_ahead for number of slots in frame */ + const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; + const int n = slots_per_frame[*scc->ssbSubcarrierSpacing]; + RC.nrmac[Mod_idP]->UL_tti_req_ahead[0] = calloc(n, sizeof(nfapi_nr_ul_tti_request_t)); + AssertFatal(RC.nrmac[Mod_idP]->UL_tti_req_ahead[0], + "could not allocate memory for RC.nrmac[]->UL_tti_req_ahead[]\n"); + /* fill in slot/frame numbers: slot is fixed, frame will be updated by + * scheduler */ + for (int i = 0; i < n; ++i) { + nfapi_nr_ul_tti_request_t *req = &RC.nrmac[Mod_idP]->UL_tti_req_ahead[0][i]; + /* consider that scheduler runs sl_ahead: the first sl_ahead slots are + * already "in the past" and thus we put frame 1 instead of 0! Note that + * variable sl_ahead seems to not be correctly initialized, but I leave + * it for information purposes here (the fix would always put 0, what + * happens now, too) */ + req->SFN = i < sl_ahead; + req->Slot = i; + } + + RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL = + calloc(n * MAX_BWP_SIZE, sizeof(uint16_t)); + AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL, + "could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n"); + + LOG_I(NR_MAC,"Configuring common parameters from NR ServingCellConfig\n"); config_common(Mod_idP, - pdsch_AntennaPorts, + ssb_SubcarrierOffset, + pdsch_AntennaPorts, + pusch_AntennaPorts, scc); - LOG_E(MAC, "%s() %s:%d RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req:%p\n", __FUNCTION__, __FILE__, __LINE__, RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req); + LOG_D(NR_MAC, "%s() %s:%d RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req:%p\n", __FUNCTION__, __FILE__, __LINE__, RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req); // if in nFAPI mode - if ( (nfapi_mode == 1 || nfapi_mode == 2) && (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req == NULL) ){ + if ( (NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) && (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req == NULL) ){ while(RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req == NULL) { - // DJP AssertFatal(RC.nrmac[Mod_idP]->if_inst->PHY_config_req != NULL,"if_inst->phy_config_request is null\n"); - usleep(100 * 1000); - printf("Waiting for PHY_config_req\n"); + // DJP AssertFatal(RC.nrmac[Mod_idP]->if_inst->PHY_config_req != NULL,"if_inst->phy_config_request is null\n"); + usleep(100 * 1000); + printf("Waiting for PHY_config_req\n"); } } - - + RC.nrmac[Mod_idP]->ssb_SubcarrierOffset = ssb_SubcarrierOffset; + NR_PHY_Config_t phycfg; phycfg.Mod_id = Mod_idP; phycfg.CC_id = 0; phycfg.cfg = &RC.nrmac[Mod_idP]->config[0]; - phycfg.cfg->ssb_table.ssb_subcarrier_offset.value = ssb_SubcarrierOffset; - phycfg.cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG; - phycfg.cfg->num_tlv++; + if (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req) RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req(&phycfg); - if (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req) RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req(&phycfg); - } - - if (secondaryCellGroup) { + find_SSB_and_RO_available(Mod_idP); - NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; - int UE_id; - if (add_ue == 1) { - UE_id = add_new_nr_ue(Mod_idP,rnti); - UE_list->secondaryCellGroup[UE_id] = secondaryCellGroup; - uint8_t num_preamble = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list.count; - UE_list->preambles[UE_id].num_preambles = num_preamble; - UE_list->preambles[UE_id].preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t)); - for (int i=0; ipreambles[UE_id].preamble_list[i] = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list.array[i]->ra_PreambleIndex; - } - LOG_I(PHY,"Added new UE_id %d/%x with initial secondaryCellGroup\n",UE_id,rnti); + const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots; + const int nr_dlmix_slots = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0); + const int nr_ulstart_slot = tdd->nrofDownlinkSlots + (tdd->nrofUplinkSymbols == 0); + + for (int slot = 0; slot < n; ++slot) { + /* FIXME: it seems there is a problem with slot 0/10/slots right after UL: + * we just get retransmissions. Thus, do not schedule such slots in DL */ + if (slot % nr_slots_period != 0) + RC.nrmac[Mod_idP]->dlsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) < nr_dlmix_slots) << (slot % 64); + RC.nrmac[Mod_idP]->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64); + LOG_D(NR_MAC, "slot %d DL %d UL %d\n", + slot, + (RC.nrmac[Mod_idP]->dlsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0, + (RC.nrmac[Mod_idP]->ulsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0); } - else { // secondaryCellGroup has been updated - UE_id = find_nr_UE_id(Mod_idP,rnti); - UE_list->secondaryCellGroup[UE_id] = secondaryCellGroup; - LOG_I(PHY,"Modified UE_id %d/%x with secondaryCellGroup\n",UE_id,rnti); + + if (get_softmodem_params()->phy_test) { + RC.nrmac[Mod_idP]->pre_processor_dl = nr_preprocessor_phytest; + RC.nrmac[Mod_idP]->pre_processor_ul = nr_ul_preprocessor_phytest; + } else { + RC.nrmac[Mod_idP]->pre_processor_dl = nr_init_fr1_dlsch_preprocessor(Mod_idP, 0); + RC.nrmac[Mod_idP]->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(Mod_idP, 0); + } + + if (get_softmodem_params()->sa > 0) { + NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[0]; + RC.nrmac[Mod_idP]->sib1_tda = sib1_tda; + for (int n=0;nra[n].cfra = false; + cc->ra[n].msg3_dcch_dtch = false; + cc->ra[n].rnti = 0; + cc->ra[n].preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES; + cc->ra[n].preambles.preamble_list = (uint8_t *) malloc(MAX_NUM_NR_PRACH_PREAMBLES*sizeof(uint8_t)); + for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++) + cc->ra[n].preambles.preamble_list[i] = i; + } + } + } + + if (mib) RC.nrmac[Mod_idP]->common_channels[0].mib = mib; + + if (CellGroup) { + + const NR_ServingCellConfig_t *servingCellConfig = CellGroup->spCellConfig->spCellConfigDedicated; + + const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList; + if(bwpList) { + AssertFatal(bwpList->list.count > 0, "downlinkBWP_ToAddModList has no BWPs!\n"); + for (int i = 0; i < bwpList->list.count; ++i) { + const NR_BWP_Downlink_t *bwp = bwpList->list.array[i]; + calculate_preferred_dl_tda(Mod_idP, bwp); + } + } else { + calculate_preferred_dl_tda(Mod_idP, NULL); + } + + const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList; + if(ubwpList) { + AssertFatal(ubwpList->list.count > 0, "uplinkBWP_ToAddModList no BWPs!\n"); + for (int i = 0; i < ubwpList->list.count; ++i) { + const NR_BWP_Uplink_t *ubwp = ubwpList->list.array[i]; + calculate_preferred_ul_tda(Mod_idP, ubwp); + } + } + + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + if (add_ue == 1 && get_softmodem_params()->phy_test) { + const int UE_id = add_new_nr_ue(Mod_idP, rnti, CellGroup); + LOG_I(NR_MAC,"Added new UE_id %d/%x with initial CellGroup\n",UE_id,rnti); + process_CellGroup(CellGroup,&UE_info->UE_sched_ctrl[UE_id]); + } else if (add_ue == 1 && !get_softmodem_params()->phy_test) { + const int CC_id = 0; + NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[CC_id]; + uint8_t ra_index = 0; + /* checking for free RA process */ + for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) { + if((cc->ra[ra_index].state == RA_IDLE) && (!cc->ra[ra_index].cfra)) break; + } + if (ra_index == NR_NB_RA_PROC_MAX) { + LOG_E(NR_MAC, "%s() %s:%d RA processes are not available for CFRA RNTI :%x\n", __FUNCTION__, __FILE__, __LINE__, rnti); + return -1; + } + NR_RA_t *ra = &cc->ra[ra_index]; + ra->CellGroup = CellGroup; + if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync && + CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated!=NULL) { + if (CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) { + ra->cfra = true; + ra->rnti = rnti; + struct NR_CFRA *cfra = CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra; + uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count; + ra->preambles.num_preambles = num_preamble; + ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t)); + for(int i=0; inum_active_ssb; i++) { + for(int j=0; jssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) { + // one dedicated preamble for each beam + ra->preambles.preamble_list[i] = + cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ra_PreambleIndex; + break; + } + } + } + } + } else { + ra->cfra = false; + ra->rnti = 0; + ra->preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES; + ra->preambles.preamble_list = (uint8_t *) malloc(MAX_NUM_NR_PRACH_PREAMBLES*sizeof(uint8_t)); + for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++) + ra->preambles.preamble_list[i] = i; + } + ra->msg3_dcch_dtch = false; + LOG_I(NR_MAC,"Added new RA process for UE RNTI %04x with initial CellGroup\n", rnti); + } else { // CellGroup has been updated + const int UE_id = find_nr_UE_id(Mod_idP,rnti); + int target_ss; + UE_info->CellGroup[UE_id] = CellGroup; + LOG_I(NR_MAC,"Modified UE_id %d/%x with CellGroup\n",UE_id,rnti); + process_CellGroup(CellGroup,&UE_info->UE_sched_ctrl[UE_id]); + const NR_ServingCellConfig_t *servingCellConfig = CellGroup ? CellGroup->spCellConfig->spCellConfigDedicated : NULL; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig ? servingCellConfig->pdsch_ServingCellConfig->choice.setup : NULL; + if (sched_ctrl->available_dl_harq.len == 0) { + // add all available DL HARQ processes for this UE in SA + create_dl_harq_list(sched_ctrl, pdsch); + } + else { + const int nrofHARQ = pdsch && pdsch->nrofHARQ_ProcessesForPDSCH ? + get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8; + AssertFatal(sched_ctrl->available_dl_harq.len==nrofHARQ, + "Reconfiguration of available harq processes not yet supported\n"); + } + // update coreset/searchspace + void *bwpd = NULL; + target_ss = NR_SearchSpace__searchSpaceType_PR_common; + if ((sched_ctrl->active_bwp)) { + target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + bwpd = (void*)sched_ctrl->active_bwp->bwp_Dedicated; + } + else if (CellGroup->spCellConfig && + CellGroup->spCellConfig->spCellConfigDedicated && + (CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP)) { + target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + bwpd = (void*)CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP; + } + sched_ctrl->search_space = get_searchspace(scc, bwpd, target_ss); + sched_ctrl->coreset = get_coreset(Mod_idP, scc, bwpd, sched_ctrl->search_space, target_ss); + sched_ctrl->maxL = 2; } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index e25680e861..ae52f8cc60 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -32,9 +32,7 @@ #include "assertions.h" -#include "LAYER2/MAC/mac.h" #include "NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" #include "NR_MAC_gNB/mac_proto.h" #include "common/utils/LOG/log.h" @@ -48,54 +46,61 @@ //#include "LAYER2/MAC/pre_processor.c" #include "pdcp.h" -#include "openair1/PHY/defs_gNB.h" -#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" - -//Agent-related headers -#include "flexran_agent_extern.h" -#include "flexran_agent_mac.h" - #include "intertask_interface.h" #include "executables/softmodem-common.h" +#include "nfapi/oai_integration/vendor_ext.h" +#include "executables/nr-softmodem.h" + +#include +#include -const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; +uint8_t vnf_first_sched_entry = 1; + void clear_nr_nfapi_information(gNB_MAC_INST * gNB, int CC_idP, frame_t frameP, sub_frame_t slotP){ + NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon; + const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; nfapi_nr_dl_tti_request_t *DL_req = &gNB->DL_req[0]; - nfapi_nr_ul_tti_request_t *UL_tti_req = &gNB->UL_tti_req[0]; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***)gNB->pdcch_pdu_idx[CC_idP]; + nfapi_nr_ul_tti_request_t *future_ul_tti_req = + &gNB->UL_tti_req_ahead[CC_idP][(slotP + num_slots - 1) % num_slots]; nfapi_nr_ul_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0]; nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; gNB->pdu_index[CC_idP] = 0; - if (nfapi_mode==0 || nfapi_mode == 1) { // monolithic or PNF + DL_req[CC_idP].SFN = frameP; + DL_req[CC_idP].Slot = slotP; + DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; + DL_req[CC_idP].dl_tti_request_body.nGroup = 0; + //DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000; + memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); - DL_req[CC_idP].SFN = frameP; - DL_req[CC_idP].Slot = slotP; - DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; - DL_req[CC_idP].dl_tti_request_body.nGroup = 0; - //DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000; + UL_dci_req[CC_idP].SFN = frameP; + UL_dci_req[CC_idP].Slot = slotP; + UL_dci_req[CC_idP].numPdus = 0; - UL_dci_req[CC_idP].SFN = frameP; - UL_dci_req[CC_idP].Slot = slotP; - UL_dci_req[CC_idP].numPdus = 0; + /* advance last round's future UL_tti_req to be ahead of current frame/slot */ + future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024; + LOG_D(MAC,"Future_ul_tti SFN = %d for slot %d \n", future_ul_tti_req->SFN, (slotP + num_slots - 1) % num_slots); + /* future_ul_tti_req->Slot is fixed! */ + future_ul_tti_req->n_pdus = 0; + future_ul_tti_req->n_ulsch = 0; + future_ul_tti_req->n_ulcch = 0; + future_ul_tti_req->n_group = 0; - UL_tti_req[CC_idP].SFN = frameP; - UL_tti_req[CC_idP].Slot = slotP; - UL_tti_req[CC_idP].n_pdus = 0; - UL_tti_req[CC_idP].n_ulsch = 0; - UL_tti_req[CC_idP].n_ulcch = 0; - UL_tti_req[CC_idP].n_group = 0; + /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., + * it walks over UL_tti_req_ahead in a circular fashion */ + gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][slotP]; - TX_req[CC_idP].Number_of_PDUs = 0; + TX_req[CC_idP].Number_of_PDUs = 0; - } } /* void check_nr_ul_failure(module_id_t module_idP, @@ -104,18 +109,18 @@ void check_nr_ul_failure(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - UE_list_t *UE_list = &RC.nrmac[module_idP]->UE_list; + NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info; nfapi_nr_dl_dci_request_t *DL_req = &RC.nrmac[module_idP]->DL_req[0]; uint16_t rnti = UE_RNTI(module_idP, UE_id); NR_COMMON_channels_t *cc = RC.nrmac[module_idP]->common_channels; // check uplink failure - if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 0) && - (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) { + if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 0) && + (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) { LOG_I(MAC, "UE %d rnti %x: UL Failure timer %d \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); - if (UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) { - UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1; + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer); + if (UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) { + UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1; // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe) nfapi_nr_dl_dci_request_pdu_t *dl_config_pdu = &DL_req[CC_id].dl_tti_request_body.dl_config_pdu_list[DL_req[CC_id].dl_tti_request_body.number_pdu]; @@ -125,7 +130,7 @@ void check_nr_ul_failure(module_id_t module_idP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_DCI_REQUEST_DCI_DL_PDU_REL8_TAG; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = get_aggregation(get_bw_index(module_idP, CC_id), - UE_list->UE_sched_ctrl[UE_id]. + UE_info->UE_sched_ctrl[UE_id]. dl_cqi[CC_id], format1A); dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications @@ -141,27 +146,27 @@ void check_nr_ul_failure(module_id_t module_idP, LOG_I(MAC, "UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer, + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer, dl_config_pdu->dci_dl_pdu. dci_dl_pdu_rel8.resource_block_coding); } else { // ra_pdcch_sent==1 LOG_I(MAC, "UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); - if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 40) == 0) UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0; // resend every 4 frames + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer); + if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer % 40) == 0) UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0; // resend every 4 frames } - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++; + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer++; // check threshold - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 20000) { + if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 20000) { // inform RRC of failure and clear timer LOG_I(MAC, "UE %d rnti %x: UL Failure after repeated PDCCH orders: Triggering RRC \n", UE_id, rnti); mac_eNB_rrc_ul_failure(module_idP, CC_id, frameP, subframeP,rnti); - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; - UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 1; + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 0; + UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync = 1; //Inform the controller about the UE deactivation. Should be moved to RRC agent in the future if (rrc_agent_registered[module_idP]) { @@ -178,7 +183,7 @@ void check_nr_ul_failure(module_id_t module_idP, void schedule_nr_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { gNB_MAC_INST *gNB = RC.nrmac[module_idP]; - UE_list_t *UE_list = &gNB->UE_list; + NR_UE_info_t *UE_info = &gNB->UE_info; nfapi_ul_config_request_body_t *ul_req; int CC_id, UE_id; NR_COMMON_channels_t *cc = RC.nrmac[module_idP]->common_channels; @@ -212,16 +217,16 @@ void schedule_nr_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subfram if ((1 << tmp) & deltaTSFC) { // This is an SRS subframe, loop over UEs for (UE_id = 0; UE_id < MAX_MOBILES_PER_GNB; UE_id++) { - if (!RC.nrmac[module_idP]->UE_list.active[UE_id]) continue; + if (!RC.nrmac[module_idP]->UE_info.active[UE_id]) continue; ul_req = &RC.nrmac[module_idP]->UL_req[CC_id].ul_config_request_body; // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue; - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", UE_id); - if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) { + if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) { if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) { get_srs_pos(&cc[CC_id], soundingRS_UL_ConfigDedicated->choice. @@ -236,7 +241,7 @@ void schedule_nr_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subfram ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_srs_pdu)); ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG; ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu); - ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth; ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition; ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;; @@ -249,7 +254,7 @@ void schedule_nr_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subfram ul_req->number_of_pdus++; } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset) } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) - } // if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) + } // if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) } // for (UE_id ... } // if((1<UL_tti_req[CC_id]; - - *ul_req = *ul_req_tmp; - - // Restore the pointer - ul_req->ul_config_request_body.ul_config_pdu_list = ul_req_pdu; - ul_req->sfn_sf = (frameP<<7) + slotP; - ul_req_tmp->ul_config_request_body.number_of_pdus = 0; - - if (ul_req->ul_config_request_body.number_of_pdus>0) - { - LOG_D(PHY, "%s() active NOW (frameP:%d slotP:%d) pdus:%d\n", __FUNCTION__, frameP, slotP, ul_req->ul_config_request_body.number_of_pdus); - } - - memcpy((void*)ul_req->ul_config_request_body.ul_config_pdu_list, - (void*)ul_req_tmp->ul_config_request_body.ul_config_pdu_list, - ul_req->ul_config_request_body.number_of_pdus*sizeof(nfapi_ul_config_request_pdu_t)); - } -} -*/ - -void nr_schedule_pucch(int Mod_idP, - int UE_id, - frame_t frameP, - sub_frame_t slotP) { - - uint16_t O_uci; - uint16_t O_ack; - uint8_t SR_flag = 0; // no SR in PUCCH implemented for now - NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; - NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; - AssertFatal(UE_list->active[UE_id] >=0,"Cannot find UE_id %d is not active\n",UE_id); - - NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id]; - int bwp_id=1; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; - - NR_sched_pucch *curr_pucch; - int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) - nr_ulmix_slots++; - - for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k]; - if ((curr_pucch->dai_c > 0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) { - UL_tti_req->SFN = frameP; - UL_tti_req->Slot = slotP; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t); - nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu; - memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t)); - UL_tti_req->n_pdus+=1; - O_ack = curr_pucch->dai_c; - O_uci = O_ack; // for now we are just sending acknacks in pucch - - LOG_I(MAC, "Scheduling pucch reception for frame %d slot %d\n", frameP, slotP); - - nr_configure_pucch(pucch_pdu, - scc, - ubwp, - curr_pucch->resource_indicator, - O_uci, - O_ack, - SR_flag); - - curr_pucch->dai_c = 0; - } - } -} - -bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot){ - - if((bitmap>>slot)&0x01) - return true; - else - return false; +bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { + if (slot>=64) return false; //quickfix for FR2 where there are more than 64 slots (bitmap to be removed) + return (bitmap >> slot) & 0x01; } void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame_rxP, - sub_frame_t slot_rxP, - frame_t frame_txP, - sub_frame_t slot_txP){ + frame_t frame, + sub_frame_t slot){ - //printf("gNB_dlsch_ulsch_scheduler frameRX %d slotRX %d frameTX %d slotTX %d\n",frame_rxP,slot_rxP,frame_txP,slot_txP); - - protocol_ctxt_t ctxt; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame_txP, slot_txP,module_idP); - - int CC_id; - int UE_id; - uint64_t *dlsch_in_slot_bitmap=NULL; - uint64_t *ulsch_in_slot_bitmap=NULL; - int pucch_sched; + protocol_ctxt_t ctxt={0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); - UE_id=0; - int bwp_id = 1; + const int bwp_id = 1; + char stats_output[16384]; gNB_MAC_INST *gNB = RC.nrmac[module_idP]; - NR_UE_list_t *UE_list = &gNB->UE_list; - NR_UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - int num_slots_per_tdd = (slots_per_frame[*scc->ssbSubcarrierSpacing])>>(7-scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); - int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) - nr_ulmix_slots++; - - if (slot_txP== 0 && (UE_list->fiveG_connected[UE_id] || get_softmodem_params()->phy_test)) { - for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k], - 0, - sizeof(NR_sched_pucch)); - } + if (slot==0 && (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]>=257)) { + const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots; + const int nb_periods_per_frame = n / nr_slots_period; + // re-initialization of tdd_beam_association at beginning of frame (only for FR2) + for (int i=0; itdd_beam_association[i] = -1; } start_meas(&RC.nrmac[module_idP]->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN); pdcp_run(&ctxt); - //rrc_rx_tx(&ctxt, CC_id); - - RC.nrmac[module_idP]->frame = frame_rxP; - RC.nrmac[module_idP]->slot = slot_rxP; - - dlsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch - ulsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].ulsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains ulsch - - // hardcoding dlsch to be in slot 1 - if (!(slot_txP%num_slots_per_tdd)) { - if(slot_txP==0) - *dlsch_in_slot_bitmap = 0x02; - else - *dlsch_in_slot_bitmap = 0x00; + /* send tick to RLC and RRC every ms */ + if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) { + void nr_rlc_tick(int frame, int subframe); + void nr_pdcp_tick(int frame, int subframe); + nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing); + nr_pdcp_tick(frame, slot >> *scc->ssbSubcarrierSpacing); + nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing); } - // hardcoding ulsch to be in slot 8 - if (!(slot_rxP%num_slots_per_tdd)) { - if(slot_rxP==0) - *ulsch_in_slot_bitmap = 0x100; - else - *ulsch_in_slot_bitmap = 0x00; - } + memset(RC.nrmac[module_idP]->cce_list[0][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0 + memset(RC.nrmac[module_idP]->cce_list[0][1],0,MAX_NUM_CCE*sizeof(int)); // coreset1 on initialBWP + memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1 + NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) + for (int i=0; inum_pdcch_cand[UE_id][i] = 0; + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + //mbsfn_status[CC_id] = 0; - // Check if there are downlink symbols in the slot, - if (is_nr_DL_slot(cc->ServingCellConfigCommon,slot_txP)) { - memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0 - memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1 - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - //mbsfn_status[CC_id] = 0; + // clear vrb_maps + memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * MAX_BWP_SIZE); + // clear last scheduled slot's content (only)! + const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int last_slot = (slot + num_slots - 1) % num_slots; + uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; + memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); - // clear vrb_maps - memset(cc[CC_id].vrb_map, 0, 100); - memset(cc[CC_id].vrb_map_UL, 0, 100); + clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); - clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame_txP, slot_txP); - } + /*VNF first entry into scheduler. Since frame numbers for future_ul_tti_req of some future slots + will not be set before we encounter them, set them here */ - // refresh UE list based on UEs dropped by PHY in previous subframe - /* - for (i = 0; i < MAX_MOBILES_PER_GNB; i++) { - if (UE_list->active[i]) { - - nfapi_nr_config_request_t *cfg = &RC.nrmac[module_idP]->config[CC_id]; - - rnti = 0;//UE_RNTI(module_idP, i); - CC_id = 0;//UE_PCCID(module_idP, i); - - } //END if (UE_list->active[i]) - } //END for (i = 0; i < MAX_MOBILES_PER_GNB; i++) - */ - - // This schedules MIB - if((slot_txP == 0) && (frame_txP & 7) == 0){ - schedule_nr_mib(module_idP, frame_txP, slot_txP); - } - - if (get_softmodem_params()->phy_test == 0) - nr_schedule_RA(module_idP, frame_txP, slot_txP); - else - UE_list->fiveG_connected[UE_id] = true; - - // Phytest scheduling - - if (get_softmodem_params()->phy_test) { - - // TbD once RACH is available, start ta_timer when UE is connected - if (ue_sched_ctl->ta_timer) - ue_sched_ctl->ta_timer--; - - if (ue_sched_ctl->ta_timer == 0) { - gNB->ta_command = ue_sched_ctl->ta_update; - /* if time is up, then set the timer to not send it for 5 frames - // regardless of the TA value */ - ue_sched_ctl->ta_timer = 100; - /* reset ta_update */ - ue_sched_ctl->ta_update = 31; - /* MAC CE flag indicating TA length */ - gNB->ta_len = 2; - } - } - - if (UE_list->fiveG_connected[UE_id] && (is_xlsch_in_slot(*dlsch_in_slot_bitmap,slot_txP%num_slots_per_tdd))) { - ue_sched_ctl->current_harq_pid = slot_txP % num_slots_per_tdd; - nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,&pucch_sched); - nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, &UE_list->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL); - // resetting ta flag - gNB->ta_len = 0; - } - - /* - // Allocate CCEs for good after scheduling is done - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) - allocate_CCEs(module_idP, CC_id, subframeP, 0); - */ - - } //is_nr_DL_slot - - if (is_nr_UL_slot(cc->ServingCellConfigCommon,slot_rxP)) { - - if (get_softmodem_params()->phy_test == 0) { - if (UE_list->fiveG_connected[UE_id]) - nr_schedule_pucch(module_idP, UE_id, frame_rxP, slot_rxP); - schedule_nr_prach(module_idP, (frame_rxP+1)&1023, slot_rxP); - nr_schedule_reception_msg3(module_idP, 0, frame_rxP, slot_rxP); - } - if (get_softmodem_params()->phy_test){ - nr_schedule_pucch(module_idP, UE_id, frame_rxP, slot_rxP); - if (is_xlsch_in_slot(*ulsch_in_slot_bitmap,slot_rxP%num_slots_per_tdd)){ - nr_schedule_uss_ulsch_phytest(module_idP, frame_rxP, slot_rxP); + if (NFAPI_MODE == NFAPI_MODE_VNF){ + if(vnf_first_sched_entry == 1) + { + for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = (frame + 1) % 1024; + else + gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; + } + vnf_first_sched_entry = 0; } } } + + if ((slot == 0) && (frame & 127) == 0) { + stats_output[0]='\0'; + dump_mac_stats(RC.nrmac[module_idP],stats_output,16384,true); + LOG_I(NR_MAC,"Frame.Slot %d.%d\n%s\n",frame,slot,stats_output); + } + + // This schedules MIB + schedule_nr_mib(module_idP, frame, slot); + + // This schedules SIB1 + if ( get_softmodem_params()->sa == 1 ) + schedule_nr_sib1(module_idP, frame, slot); + + + // This schedule PRACH if we are not in phy_test mode + if (get_softmodem_params()->phy_test == 0) { + /* we need to make sure that resources for PRACH are free. To avoid that + e.g. PUSCH has already been scheduled, make sure we schedule before + anything else: below, we simply assume an advance one frame (minus one + slot, because otherwise we would allocate the current slot in + UL_tti_req_ahead), but be aware that, e.g., K2 is allowed to be larger + (schedule_nr_prach will assert if resources are not free). */ + const sub_frame_t n_slots_ahead = nr_slots_per_frame[*scc->ssbSubcarrierSpacing] - 1; + const frame_t f = (frame + (slot + n_slots_ahead) / nr_slots_per_frame[*scc->ssbSubcarrierSpacing]) % 1024; + const sub_frame_t s = (slot + n_slots_ahead) % nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + schedule_nr_prach(module_idP, f, s); + } + + // This schedule SR + nr_sr_reporting(module_idP, frame, slot); + + // Schedule CSI-RS transmission + nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]); + + // Schedule CSI measurement reporting: check in slot 0 for the whole frame + if (slot == 0) + nr_csi_meas_reporting(module_idP, frame, slot); + + // This schedule RA procedure if not in phy_test mode + // Otherwise already consider 5G already connected + if (get_softmodem_params()->phy_test == 0) { + nr_schedule_RA(module_idP, frame, slot); + } + + // This schedules the DCI for Uplink and subsequently PUSCH + nr_schedule_ulsch(module_idP, frame, slot); + + // This schedules the DCI for Downlink and PDSCH + nr_schedule_ue_spec(module_idP, frame, slot); + + nr_schedule_pucch(module_idP, frame, slot); + stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index e90a69638c..2705b85b8c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -41,21 +41,148 @@ #include "UTIL/OPT/opt.h" #include "SIMULATION/TOOLS/sim.h" // for taus +#include extern RAN_CONTEXT_t RC; extern const uint8_t nr_slots_per_frame[5]; +extern uint16_t sl_ahead; uint8_t DELTA[4]= {2,3,4,6}; -void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { +#define MAX_NUMBER_OF_SSB 64 +float ssb_per_rach_occasion[8] = {0.125,0.25,0.5,1,2,4,8}; +int16_t ssb_index_from_prach(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + uint16_t preamble_index, + uint8_t freq_index, + uint8_t symbol) { + gNB_MAC_INST *gNB = RC.nrmac[module_idP]; - NR_COMMON_channels_t *cc = gNB->common_channels; + NR_COMMON_channels_t *cc = &gNB->common_channels[0]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req[0]; + nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; - uint8_t mu,N_dur,N_t_slot,start_symbol; - uint16_t format; + uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; + + uint8_t total_RApreambles = MAX_NUM_NR_PRACH_PREAMBLES; + if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) + total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; + + float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; + uint16_t start_symbol_index = 0; + uint8_t mu,N_dur=0,N_t_slot=0,start_symbol = 0, temp_start_symbol = 0, N_RA_slot=0; + uint16_t format,RA_sfn_index = -1; + uint8_t config_period = 1; + uint16_t prach_occasion_id = -1; + uint8_t num_active_ssb = cc->num_active_ssb; + + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) + mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; + else + mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + get_nr_prach_info_from_index(config_index, + (int)frameP, + (int)slotP, + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, + mu, + cc->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period); + uint8_t index = 0,slot_index = 0; + for (slot_index = 0;slot_index < N_RA_slot; slot_index++) { + if (N_RA_slot <= 1) { //1 PRACH slot in a subframe + if((mu == 1) || (mu == 3)) + slot_index = 1; //For scs = 30khz and 120khz + } + for (int i=0; i< N_t_slot; i++) { + temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14; + if(symbol == temp_start_symbol) { + start_symbol_index = i; + break; + } + } + } + if (N_RA_slot <= 1) { //1 PRACH slot in a subframe + if((mu == 1) || (mu == 3)) + slot_index = 0; //For scs = 30khz and 120khz + } + + // prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index; + prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period)*cc->total_prach_occasions_per_config_period) + + (RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index; + + //one RO is shared by one or more SSB + if(num_ssb_per_RO <= 1 ) + index = (int) (prach_occasion_id / (int)(1/num_ssb_per_RO)) % num_active_ssb; + //one SSB have more than one continuous RO + else if ( num_ssb_per_RO > 1) { + index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ; + for(int j = 0;j < num_ssb_per_RO;j++) { + if(preamble_index < (((j+1) * total_RApreambles) / num_ssb_per_RO)) + index = index + j; + } + } + + LOG_D(NR_MAC, "Frame %d, Slot %d: Prach Occasion id = %d ssb per RO = %f number of active SSB %u index = %d fdm %u symbol index %u freq_index %u total_RApreambles %u\n", + frameP, slotP, prach_occasion_id, num_ssb_per_RO, num_active_ssb, index, fdm, start_symbol_index, freq_index, total_RApreambles); + + return index; +} + + +//Compute Total active SSBs and RO available +void find_SSB_and_RO_available(module_id_t module_idP) { + + gNB_MAC_INST *gNB = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = &gNB->common_channels[0]; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; + + uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; + uint8_t mu,N_dur=0,N_t_slot=0,start_symbol=0,N_RA_slot = 0; + uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0; + uint8_t num_active_ssb = 0; + uint8_t max_association_period = 1; + + struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB; + + switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present){ + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen; + break; + default: + AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present); + break; + } if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; @@ -63,110 +190,217 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 - if ( get_nr_prach_info_from_index(config_index, - (int)frameP, - (int)slotP, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - mu, - cc->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur) ) { + get_nr_prach_occasion_info_from_index(config_index, + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, + mu, + cc->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &N_RA_slot, + &N_RA_sfn, + &max_association_period); - int fdm = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM; - uint16_t format0 = format&0xff; // first column of format from table - uint16_t format1 = (format>>8)&0xff; // second column of format from table + float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; + uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; + uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ; + uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm; - UL_tti_req->SFN = frameP; - UL_tti_req->Slot = slotP; - for (int n=0; n<(1<pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t); - nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu; - memset(prach_pdu,0,sizeof(nfapi_nr_prach_pdu_t)); - UL_tti_req->n_pdus+=1; + for(int i = 0;i < 64;i++) { + if ((L_ssb >> (63-i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1 + cc->ssb_index[num_active_ssb] = i; + num_active_ssb++; + } + } - // filling the prach fapi structure - prach_pdu->phys_cell_id = *scc->physCellId; - prach_pdu->num_prach_ocas = N_t_slot; - prach_pdu->prach_start_symbol = start_symbol; - prach_pdu->num_ra = n; - prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig, - format0, - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig); - // SCF PRACH PDU format field does not consider A1/B1 etc. possibilities - // We added 9 = A1/B1 10 = A2/B2 11 A3/B3 - if (format1!=0xff) { - switch(format0) { - case 0xa1: - prach_pdu->prach_format = 9; - break; - case 0xa2: - prach_pdu->prach_format = 10; - break; - case 0xa3: - prach_pdu->prach_format = 11; - break; - default: - AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); - } + cc->total_prach_occasions_per_config_period = total_RA_occasions; + for(int i=1; (1 << (i-1)) <= max_association_period; i++) { + cc->max_association_period = (1 <<(i-1)); + total_RA_occasions = total_RA_occasions * cc->max_association_period; + if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) { + repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb); + break; + } + } + + unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO); + cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion; + cc->num_active_ssb = num_active_ssb; + + LOG_I(NR_MAC, + "Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u total_prach_occasions_per_config_period %u\n", + cc->total_prach_occasions, + cc->num_active_ssb, + unused_RA_occasion, + cc->max_association_period, + N_RA_sfn, + cc->total_prach_occasions_per_config_period); +} + +void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) +{ + gNB_MAC_INST *gNB = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = gNB->common_channels; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][slotP]; + nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; + + if (is_nr_UL_slot(scc->tdd_UL_DL_ConfigurationCommon, slotP, cc->frame_type)) { + + uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; + uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot; + uint16_t RA_sfn_index = -1; + uint8_t config_period = 1; + uint16_t format; + int slot_index = 0; + uint16_t prach_occasion_id = -1; + + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) + mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; + else + mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + int bwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; + // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 + if ( get_nr_prach_info_from_index(config_index, + (int)frameP, + (int)slotP, + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, + mu, + cc->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period) ) { + + uint16_t format0 = format&0xff; // first column of format from table + uint16_t format1 = (format>>8)&0xff; // second column of format from table + + if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe + if (slotP%2 == 1) + slot_index = 1; + else + slot_index = 0; + }else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe + slot_index = 0; } - else{ - switch(format0) { - case 0xa1: - prach_pdu->prach_format = 0; - break; - case 0xa2: - prach_pdu->prach_format = 1; - break; - case 0xa3: - prach_pdu->prach_format = 2; - break; - case 0xb1: - prach_pdu->prach_format = 3; - break; - case 0xb2: - prach_pdu->prach_format = 4; - break; - case 0xb3: - prach_pdu->prach_format = 5; - break; - case 0xb4: - prach_pdu->prach_format = 6; - break; - case 0xc0: - prach_pdu->prach_format = 7; - break; - case 0xc2: - prach_pdu->prach_format = 8; - break; - case 0: - // long formats are handled @ PHY - break; - case 1: - // long formats are handled @ PHY - break; - case 2: - // long formats are handled @ PHY - break; - case 3: - // long formats are handled @ PHY - break; - default: - AssertFatal(1==0,"Invalid PRACH format"); + + UL_tti_req->SFN = frameP; + UL_tti_req->Slot = slotP; + for (int fdm_index=0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion + for (int td_index=0; td_indexmax_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + + (RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index; + + if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)){ + + UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE; + UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t); + nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu; + memset(prach_pdu,0,sizeof(nfapi_nr_prach_pdu_t)); + UL_tti_req->n_pdus+=1; + + // filling the prach fapi structure + prach_pdu->phys_cell_id = *scc->physCellId; + prach_pdu->num_prach_ocas = N_t_slot; + prach_pdu->prach_start_symbol = start_symbol; + prach_pdu->num_ra = fdm_index; + prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig, + format0, + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig); + + LOG_D(NR_MAC, "Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n", + frameP, slotP, + prach_occasion_id, prach_pdu->num_ra, + prach_pdu->prach_start_symbol, + slot_index, RA_sfn_index); + // SCF PRACH PDU format field does not consider A1/B1 etc. possibilities + // We added 9 = A1/B1 10 = A2/B2 11 A3/B3 + if (format1!=0xff) { + switch(format0) { + case 0xa1: + prach_pdu->prach_format = 11; + break; + case 0xa2: + prach_pdu->prach_format = 12; + break; + case 0xa3: + prach_pdu->prach_format = 13; + break; + default: + AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); + } + } + else{ + switch(format0) { + case 0: + prach_pdu->prach_format = 0; + break; + case 1: + prach_pdu->prach_format = 1; + break; + case 2: + prach_pdu->prach_format = 2; + break; + case 3: + prach_pdu->prach_format = 3; + break; + case 0xa1: + prach_pdu->prach_format = 4; + break; + case 0xa2: + prach_pdu->prach_format = 5; + break; + case 0xa3: + prach_pdu->prach_format = 6; + break; + case 0xb1: + prach_pdu->prach_format = 7; + break; + case 0xb4: + prach_pdu->prach_format = 8; + break; + case 0xc0: + prach_pdu->prach_format = 9; + break; + case 0xc2: + prach_pdu->prach_format = 10; + break; + default: + AssertFatal(1==0,"Invalid PRACH format"); + } + } + } } } + + // block resources in vrb_map_UL + const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = + &scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric; + const uint8_t mu_pusch = + scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + const int16_t N_RA_RB = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch); + uint16_t *vrb_map_UL = &cc->vrb_map_UL[slotP * MAX_BWP_SIZE]; + for (int i = 0; i < N_RA_RB * fdm; ++i) + vrb_map_UL[bwp_start + rach_ConfigGeneric->msg1_FrequencyStart + i] = 0xff; // all symbols } } } - void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, uint16_t *msg2_frame, uint16_t *msg2_slot, NR_ServingCellConfigCommon_t *scc, uint16_t monitoring_slot_period, - uint16_t monitoring_offset){ + uint16_t monitoring_offset,uint8_t beam_index, + uint8_t num_active_ssb, + int16_t *tdd_beam_association){ // preferentially we schedule the msg2 in the mixed slot or in the last dl slot // if they are allowed by search space configuration @@ -183,11 +417,6 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, if ((scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols > 0) || (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols > 0)) tdd_period_slot++; - // computing start of next period - uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu]; - *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot - *msg2_frame = (*msg2_slot>(rach_slot))? rach_frame : (rach_frame +1); - switch(response_window){ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: slot_window = 1; @@ -220,12 +449,36 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, // slot and frame limit to transmit msg2 according to response window uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu]; - //uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1); + uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1); + // computing start of next period + + int FR = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257 ? nr_FR2 : nr_FR1; + + uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu]; + *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot + *msg2_frame = ((*msg2_slot>(rach_slot))? rach_frame : (rach_frame+1))%1024; + + // we can't schedule msg2 before sl_ahead since prach + int eff_slot = *msg2_slot+(*msg2_frame-rach_frame)*nr_slots_per_frame[mu]; + if ((eff_slot-rach_slot)<=sl_ahead) { + *msg2_slot = (*msg2_slot+tdd_period_slot)%nr_slots_per_frame[mu]; + *msg2_frame = ((*msg2_slot>(rach_slot))? rach_frame : (rach_frame+1))%1024; + } + if (FR==nr_FR2) { + int num_tdd_period = *msg2_slot/tdd_period_slot; + while((tdd_beam_association[num_tdd_period]!=-1)&&(tdd_beam_association[num_tdd_period]!=beam_index)) { + *msg2_slot = (*msg2_slot+tdd_period_slot)%nr_slots_per_frame[mu]; + *msg2_frame = ((*msg2_slot>(rach_slot))? rach_frame : (rach_frame+1))%1024; + num_tdd_period = *msg2_slot/tdd_period_slot; + } + if(tdd_beam_association[num_tdd_period] == -1) + tdd_beam_association[num_tdd_period] = beam_index; + } // go to previous slot if the current scheduled slot is beyond the response window // and if the slot is not among the PDCCH monitored ones (38.213 10.1) - while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) { + while (((*msg2_slot>slot_limit)&&(*msg2_frame>frame_limit)) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) { if((*msg2_slot%tdd_period_slot) > 0) (*msg2_slot)--; else @@ -245,239 +498,487 @@ void nr_initiate_ra_proc(module_id_t module_idP, uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL NR_SearchSpace_t *ss; - int UE_id = 0; - // ra_rnti from 5.1.3 in 38.321 - uint16_t ra_rnti=1+symbol+(slotP*14)+(freq_index*14*80)+(ul_carrier_id*14*80*8); uint16_t msg2_frame, msg2_slot,monitoring_slot_period,monitoring_offset; gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; - NR_UE_list_t *UE_list = &nr_mac->UE_list; - NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_RA_t *ra = &cc->ra[0]; - // if the preamble received correspond to one of the listed - // the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries - int pr_found=0; - for (int i=0;ipreambles[UE_id].num_preambles;i++) { - if (preamble_index == UE_list->preambles[UE_id].preamble_list[i]) { - pr_found=1; - break; - } - } - if (pr_found) - UE_list->fiveG_connected[UE_id] = false; - else { - LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated for UE_id %d\n", - module_idP, preamble_index, UE_id); - return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc + uint8_t total_RApreambles = MAX_NUM_NR_PRACH_PREAMBLES; + uint8_t num_ssb_per_RO = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; + int pr_found; + + if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) + total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; + + if(num_ssb_per_RO > 3) { /*num of ssb per RO >= 1*/ + num_ssb_per_RO -= 3; + total_RApreambles = total_RApreambles/num_ssb_per_RO ; } - // This should be handled differently when we use the initialBWP for RA - ra->bwp_id=1; - NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &cc->ra[i]; + pr_found = 0; + if (ra->state == RA_IDLE) { + for(int j = 0; j < ra->preambles.num_preambles; j++) { + //check if the preamble received correspond to one of the listed or configured preambles + if (preamble_index == ra->preambles.preamble_list[j]) { + pr_found=1; + break; + } + } + if (pr_found == 0) { + continue; + } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1); + uint16_t ra_rnti; - LOG_I(MAC, "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d Initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, slotP, preamble_index); + // ra_rnti from 5.1.3 in 38.321 + // FK: in case of long PRACH the phone seems to expect the subframe number instead of the slot number here. + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present + == NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l839) + ra_rnti = 1 + symbol + (9 /*slotP*/ * 14) + (freq_index * 14 * 80) + (ul_carrier_id * 14 * 80 * 8); + else + ra_rnti = 1 + symbol + (slotP * 14) + (freq_index * 14 * 80) + (ul_carrier_id * 14 * 80 * 8); - if (ra->state == RA_IDLE) { - int loop = 0; - LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP); - ra->state = Msg2; - ra->timing_offset = timing_offset; - ra->preamble_slot = slotP; + // This should be handled differently when we use the initialBWP for RA + ra->bwp_id = 0; + NR_BWP_Downlink_t *bwp=NULL; + if (ra->CellGroup && ra->CellGroup->spCellConfig && ra->CellGroup->spCellConfig->spCellConfigDedicated && + ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList) { + ra->bwp_id = 1; + bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; + } - struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - AssertFatal(commonSearchSpaceList->list.count>0, - "common SearchSpace list has 0 elements\n"); - // Common searchspace list - for (int i=0;ilist.count;i++) { - ss=commonSearchSpaceList->list.array[i]; - if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace) - ra->ra_ss=ss; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1); + + LOG_D(NR_MAC, + "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d Initiating RA procedure for preamble index %d\n", + module_idP, + CC_id, + frameP, + slotP, + preamble_index); + + uint8_t beam_index = ssb_index_from_prach(module_idP, frameP, slotP, preamble_index, freq_index, symbol); + + // the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries + if (ra->cfra) { + // if the preamble received correspond to one of the listed + if (!(preamble_index == ra->preambles.preamble_list[beam_index])) { + LOG_E( + NR_MAC, + "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n", + module_idP, + preamble_index); + continue; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc + } + } + LOG_D(NR_MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP); + ra->state = Msg2; + ra->timing_offset = timing_offset; + ra->preamble_slot = slotP; + + NR_SearchSpaceId_t ra_SearchSpace = 0; + struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = NULL; + if(bwp) { + commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ra_SearchSpace = *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } else { + commonSearchSpaceList = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ra_SearchSpace = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } + AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n"); + + // Common SearchSpace list + for (int i = 0; i < commonSearchSpaceList->list.count; i++) { + ss = commonSearchSpaceList->list.array[i]; + if (ss->searchSpaceId == ra_SearchSpace) + ra->ra_ss = ss; + } + + AssertFatal(ra->ra_ss!=NULL,"SearchSpace cannot be null for RA\n"); + + // retrieving ra pdcch monitoring period and offset + find_monitoring_periodicity_offset_common(ra->ra_ss, &monitoring_slot_period, &monitoring_offset); + + nr_schedule_msg2(frameP, + slotP, + &msg2_frame, + &msg2_slot, + scc, + monitoring_slot_period, + monitoring_offset, + beam_index, + cc->num_active_ssb, + nr_mac->tdd_beam_association); + + ra->Msg2_frame = msg2_frame; + ra->Msg2_slot = msg2_slot; + + LOG_D(NR_MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP); + + int loop = 0; + if (ra->rnti == 0) { // This condition allows for the usage of a preconfigured rnti for the CFRA + do { + ra->rnti = (taus() % 65518) + 1; + loop++; + } while (loop != 100 + && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) + && ra->rnti >= 1 && ra->rnti <= 65519)); + if (loop == 100) { + LOG_E(NR_MAC, "%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__); + abort(); + } + } + + ra->RA_rnti = ra_rnti; + ra->preamble_index = preamble_index; + ra->beam_id = beam_index; + + LOG_D(NR_MAC, + "[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB " + "index %u\n", + module_idP, + CC_id, + frameP, + ra->Msg2_frame, + ra->Msg2_slot, + ra->RA_rnti, + cc->ssb_index[beam_index]); + + return; } - - // retrieving ra pdcch monitoring period and offset - find_monitoring_periodicity_offset_common(ra->ra_ss, - &monitoring_slot_period, - &monitoring_offset); - - nr_schedule_msg2(frameP, slotP, &msg2_frame, &msg2_slot, scc, monitoring_slot_period, monitoring_offset); - - ra->Msg2_frame = msg2_frame; - ra->Msg2_slot = msg2_slot; - - LOG_D(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP); - - do { - ra->rnti = (taus() % 65518) + 1; - loop++; - } - while (loop != 100 && !(find_nr_UE_id(module_idP, ra->rnti) == -1 && ra->rnti >= 1 && ra->rnti <= 65519)); - if (loop == 100) { - LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__); - abort(); - } - - ra->RA_rnti = ra_rnti; - ra->preamble_index = preamble_index; - UE_list->tc_rnti[UE_id] = ra->rnti; - - LOG_I(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x\n", - module_idP, - CC_id, - frameP, - ra->Msg2_frame, - ra->Msg2_slot, - ra->RA_rnti); - - return; } - LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index); + LOG_E(NR_MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } -void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){ +void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - //uint8_t i = 0; - int CC_id = 0; gNB_MAC_INST *mac = RC.nrmac[module_idP]; - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - NR_RA_t *ra = &cc->ra[0]; start_meas(&mac->schedule_ra); - - //for (i = 0; i < NR_NB_RA_PROC_MAX; i++) { - LOG_D(MAC,"RA[state:%d]\n",ra->state); - switch (ra->state){ - case Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP); - break; - case Msg4: - //generate_Msg4(module_idP, CC_id, frameP, slotP, ra); - break; - case WAIT_Msg4_ACK: - //check_Msg4_retransmission(module_idP, CC_id, frameP, slotP, ra); - break; - default: - break; + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &cc->ra[i]; + LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); + switch (ra->state) { + case Msg2: + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra); + break; + case Msg3_retransmission: + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra); + break; + case Msg4: + nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra); + break; + case WAIT_Msg4_ACK: + nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); + break; + default: + break; + } + } } - //} stop_meas(&mac->schedule_ra); } -void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc, + +void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { + + gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + + NR_BWP_Uplink_t *ubwp = NULL; + NR_BWP_UplinkDedicated_t *ubwpd = NULL; + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL; + NR_BWP_t *genericParameters = NULL; + if(ra->CellGroup) { + ubwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1]; + ubwpd = ra->CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; + genericParameters = &ubwp->bwp_Common->genericParameters; + pusch_TimeDomainAllocationList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + } else { + genericParameters = &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + pusch_TimeDomainAllocationList = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + } + + int mu = genericParameters->subcarrierSpacing; + uint8_t K2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2; + const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]); + const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; + + if (is_xlsch_in_slot(RC.nrmac[module_idP]->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) { + // beam association for FR2 + int16_t *tdd_beam_association = nr_mac->tdd_beam_association; + if (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257) { + uint8_t tdd_period_slot = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if ((scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols > 0) || (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols > 0)) + tdd_period_slot++; + int num_tdd_period = sched_slot/tdd_period_slot; + if((tdd_beam_association[num_tdd_period]!=-1)&&(tdd_beam_association[num_tdd_period]!=ra->beam_id)) + return; // can't schedule retransmission in this slot + else + tdd_beam_association[num_tdd_period] = ra->beam_id; + } + + int scs = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + int fh = 0; + int startSymbolAndLength = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; + int mappingtype = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType; + + uint16_t *vrb_map_UL = &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; + + int BWPStart = nr_mac->type0_PDCCH_CSS_config[ra->beam_id].cset_start_rb; + int BWPSize = nr_mac->type0_PDCCH_CSS_config[ra->beam_id].num_rbs; + int rbStart = 0; + for (int i = 0; (i < ra->msg3_nb_rb) && (rbStart <= (BWPSize - ra->msg3_nb_rb)); i++) { + if (vrb_map_UL[rbStart + BWPStart + i]) { + rbStart += i; + i = 0; + } + } + if (rbStart > (BWPSize - ra->msg3_nb_rb)) { + // cannot find free vrb_map for msg3 retransmission in this slot + return; + } + + LOG_I(NR_MAC, "[gNB %d][RAPROC] Frame %d, Slot %d : CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n", + module_idP, frame, slot, CC_id, sched_frame, sched_slot); + + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][sched_slot]; + AssertFatal(future_ul_tti_req->SFN == sched_frame + && future_ul_tti_req->Slot == sched_slot, + "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + sched_frame, + sched_slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; + memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + + fill_msg3_pusch_pdu(pusch_pdu, scc, + ra->msg3_round, + startSymbolAndLength, + ra->rnti, scs, + BWPSize, BWPStart, + mappingtype, fh, + rbStart, ra->msg3_nb_rb); + future_ul_tti_req->n_pdus += 1; + + // generation of DCI 0_0 to schedule msg3 retransmission + NR_SearchSpace_t *ss = ra->ra_ss; + NR_ControlResourceSet_t *coreset = get_coreset(module_idP, scc, NULL, ss, NR_SearchSpace__searchSpaceType_PR_common); + AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg3 retransmission\n"); + + nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->UL_dci_req[CC_id]; + + const int coresetid = coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][ra->bwp_id][coresetid]; + if (!pdcch_pdu_rel15) { + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; + memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); + ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; + ul_dci_req->numPdus += 1; + nr_configure_pdcch(nr_mac, pdcch_pdu_rel15, ss, coreset, scc, genericParameters, NULL); + nr_mac->pdcch_pdu_idx[CC_id][ra->bwp_id][coresetid] = pdcch_pdu_rel15; + } + + uint8_t aggregation_level; + uint8_t nr_of_candidates; + for (int i=0; i<5; i++) { + // for now taking the lowest value among the available aggregation levels + find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss, 1<0) break; + } + AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n"); + int CCEIndex = allocate_nr_CCEs(nr_mac, NULL, coreset, aggregation_level, 0, 0, nr_of_candidates); + if (CCEIndex < 0) { + LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti); + return; + } + + // Fill PDCCH DL DCI PDU + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + pdcch_pdu_rel15->numDlDci++; + dci_pdu->RNTI = ra->rnti; + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + dci_pdu->AggregationLevel = aggregation_level; + dci_pdu->CceIndex = CCEIndex; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + + dci_pdu_rel15_t uldci_payload; + memset(&uldci_payload, 0, sizeof(uldci_payload)); + + config_uldci(ubwp, + ubwpd, + scc, + pusch_pdu, + &uldci_payload, + NR_UL_DCI_FORMAT_0_0, + ra->Msg3_tda_id, + ra->msg3_TPC, + 0, // not used in format 0_0 + ra->bwp_id); + + fill_dci_pdu_rel15(scc, + ra->CellGroup, + dci_pdu, + &uldci_payload, + NR_UL_DCI_FORMAT_0_0, + NR_RNTI_TC, + pusch_pdu->bwp_size, + ra->bwp_id); + + // Mark the corresponding RBs as used + for (int rb = 0; rb < ra->msg3_nb_rb; rb++) { + vrb_map_UL[rbStart + BWPStart + rb] = 1; + } + + // reset state to wait msg3 + ra->state = WAIT_Msg3; + ra->Msg3_frame = sched_frame; + ra->Msg3_slot = sched_slot; + + } + +} + +void nr_get_Msg3alloc(module_id_t module_id, + int CC_id, + NR_ServingCellConfigCommon_t *scc, NR_BWP_Uplink_t *ubwp, sub_frame_t current_slot, frame_t current_frame, - NR_RA_t *ra) { + NR_RA_t *ra, + int16_t *tdd_beam_association) { - // msg3 is schedulend in mixed slot in the following TDD period - // for now we consider a TBS of 18 bytes + // msg3 is scheduled in mixed slot in the following TDD period - int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing; - int StartSymbolIndex, NrOfSymbols, startSymbolAndLength, temp_slot; + uint16_t msg3_nb_rb = 8; // sdu has 6 or 8 bytes + + int mu = ubwp ? + ubwp->bwp_Common->genericParameters.subcarrierSpacing : + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + int temp_slot = 0; ra->Msg3_tda_id = 16; // initialization to a value above limit - for (int i=0; ibwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count; i++) { - startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength; - SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols); - // we want to transmit in the uplink symbols of mixed slot - if (NrOfSymbols == scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols) { - ra->Msg3_tda_id = i; - break; + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList= ubwp ? + ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList: + scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + + uint8_t k2 = 0; + lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); + if (frame_type == TDD) { + int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); + int nb_slots_per_period = ((1<list.count; i++) { + k2 = *pusch_TimeDomainAllocationList->list.array[i]->k2; + // we want to transmit in the uplink symbols of mixed slot + if ((k2 + DELTA[mu])%nb_slots_per_period == 0) { + temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213 + ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu]; + if (is_xlsch_in_slot(RC.nrmac[module_id]->ulsch_slot_bitmap[ra->Msg3_slot / 64], ra->Msg3_slot)) { + ra->Msg3_tda_id = i; + break; + } + } } } + else { + ra->Msg3_tda_id = 0; + k2 = *pusch_TimeDomainAllocationList->list.array[0]->k2; + temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213 + ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu]; + } + AssertFatal(ra->Msg3_tda_id<16,"Unable to find Msg3 time domain allocation in list\n"); - uint8_t k2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2; - - temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213 - ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu]; if (nr_slots_per_frame[mu]>temp_slot) ra->Msg3_frame = current_frame; else - ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame[mu]); + ra->Msg3_frame = (current_frame + (temp_slot/nr_slots_per_frame[mu]))%1024; - ra->msg3_nb_rb = 18; - ra->msg3_first_rb = 0; -} - - -void nr_schedule_reception_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){ - gNB_MAC_INST *mac = RC.nrmac[module_idP]; - nfapi_nr_ul_tti_request_t *ul_req = &mac->UL_tti_req[0]; - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - NR_RA_t *ra = &cc->ra[0]; - - if (ra->state == WAIT_Msg3) { - if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot) ){ - ul_req->SFN = ra->Msg3_frame; - ul_req->Slot = ra->Msg3_slot; - ul_req->pdus_list[ul_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; - ul_req->pdus_list[ul_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - ul_req->pdus_list[ul_req->n_pdus].pusch_pdu = ra->pusch_pdu; - ul_req->n_pdus+=1; - ra->state = RA_IDLE; - } + // beam association for FR2 + if (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257) { + uint8_t tdd_period_slot = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if ((scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols > 0) || (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols > 0)) + tdd_period_slot++; + int num_tdd_period = ra->Msg3_slot/tdd_period_slot; + if((tdd_beam_association[num_tdd_period]!=-1)&&(tdd_beam_association[num_tdd_period]!=ra->beam_id)) + AssertFatal(1==0,"Cannot schedule MSG3\n"); + else + tdd_beam_association[num_tdd_period] = ra->beam_id; } + + LOG_D(NR_MAC, "[RAPROC] Msg3 slot %d: current slot %u Msg3 frame %u k2 %u Msg3_tda_id %u\n", ra->Msg3_slot, current_slot, ra->Msg3_frame, k2,ra->Msg3_tda_id); + uint16_t *vrb_map_UL = + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE]; + + int bwpSize = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int bwpStart = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + if (ra->CellGroup) { + AssertFatal(ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, + "downlinkBWP_ToAddModList has %d BWP!\n", ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); + NR_BWP_Uplink_t *ubwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; + int act_bwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int act_bwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + if (!((bwpStart >= act_bwp_start) && ((bwpStart+bwpSize) <= (act_bwp_start+act_bwp_size)))) + bwpStart = act_bwp_start; + } + + /* search msg3_nb_rb free RBs */ + int rbSize = 0; + int rbStart = 0; + while (rbSize < msg3_nb_rb) { + rbStart += rbSize; /* last iteration rbSize was not enough, skip it */ + rbSize = 0; + while (rbStart < bwpSize && vrb_map_UL[rbStart + bwpStart]) + rbStart++; + AssertFatal(rbStart < bwpSize - msg3_nb_rb, "no space to allocate Msg 3 for RA!\n"); + while (rbStart + rbSize < bwpSize + && !vrb_map_UL[rbStart + bwpStart + rbSize] + && rbSize < msg3_nb_rb) + rbSize++; + } + ra->msg3_nb_rb = msg3_nb_rb; + ra->msg3_first_rb = rbStart; + ra->msg3_bwp_start = bwpStart; } -void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){ - gNB_MAC_INST *mac = RC.nrmac[module_idP]; - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_RA_t *ra = &cc->ra[0]; - NR_UE_list_t *UE_list = &mac->UE_list; - int UE_id = 0; - - AssertFatal(ra->state != RA_IDLE, "RA is not active for RA %X\n", ra->rnti); - - LOG_D(MAC, "[gNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot); - - nfapi_nr_pusch_pdu_t *pusch_pdu = &ra->pusch_pdu; - memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); +void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_ServingCellConfigCommon_t *scc, + int round, + int startSymbolAndLength, + rnti_t rnti, int scs, + int bwp_size, int bwp_start, + int mappingtype, int fh, + int msg3_first_rb, int msg3_nb_rb) { - AssertFatal(UE_list->active[UE_id] >=0,"Cannot find UE_id %d is not active\n", UE_id); - - NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id]; - AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1]; - LOG_D(MAC, "Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d) for rnti: %d\n", - frameP, - slotP, - ra->Msg3_frame, - ra->Msg3_slot, - ra->msg3_nb_rb, - ra->msg3_first_rb, - ra->msg3_round, - ra->rnti); - - int startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; int start_symbol_index,nr_of_symbols; SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols); pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = ra->rnti; + pusch_pdu->rnti = rnti; pusch_pdu->handle = 0; - int abwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - int abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - int ibwp_size = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth,275); - int ibwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth,275); - if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size)) - pusch_pdu->bwp_start = abwp_start; - else - pusch_pdu->bwp_start = ibwp_start; - pusch_pdu->bwp_size = ibwp_size; - pusch_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + pusch_pdu->bwp_start = bwp_start; + pusch_pdu->bwp_size = bwp_size; + pusch_pdu->subcarrier_spacing = scs; pusch_pdu->cyclic_prefix = 0; - pusch_pdu->mcs_index = 0; + pusch_pdu->mcs_index = 1; pusch_pdu->mcs_table = 0; pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table); pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table); @@ -487,244 +988,860 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t pusch_pdu->transform_precoding = 0; pusch_pdu->data_scrambling_id = *scc->physCellId; pusch_pdu->nrOfLayers = 1; - pusch_pdu->ul_dmrs_symb_pos = 1<ul_dmrs_symb_pos = get_l_prime(nr_of_symbols,mappingtype,pusch_dmrs_pos2,pusch_len1,start_symbol_index, scc->dmrs_TypeA_Position); + LOG_D(MAC, "MSG3 start_sym:%d NR Symb:%d mappingtype:%d , ul_dmrs_symb_pos:%x\n", start_symbol_index, nr_of_symbols, mappingtype, pusch_pdu->ul_dmrs_symb_pos); pusch_pdu->dmrs_config_type = 0; pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0. pusch_pdu->dmrs_ports = 1; // 6.2.2 in 38.214 only port 0 to be used pusch_pdu->num_dmrs_cdm_grps_no_data = 2; // no data in dmrs symbols as in 6.2.2 in 38.214 pusch_pdu->resource_alloc = 1; //type 1 - pusch_pdu->rb_start = ra->msg3_first_rb + ibwp_start - abwp_start; // as for 6.3.1.7 in 38.211 - if (ra->msg3_nb_rb > pusch_pdu->bwp_size) + + pusch_pdu->rb_start = msg3_first_rb; + if (msg3_nb_rb > pusch_pdu->bwp_size) AssertFatal(1==0,"MSG3 allocated number of RBs exceed the BWP size\n"); else - pusch_pdu->rb_size = ra->msg3_nb_rb; + pusch_pdu->rb_size = msg3_nb_rb; pusch_pdu->vrb_to_prb_mapping = 0; - if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->frequencyHopping == NULL) - pusch_pdu->frequency_hopping = 0; - else - pusch_pdu->frequency_hopping = 1; + + pusch_pdu->frequency_hopping = fh; //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] pusch_pdu->uplink_frequency_shift_7p5khz = 0; //Resource Allocation in time domain pusch_pdu->start_symbol_index = start_symbol_index; pusch_pdu->nr_of_symbols = nr_of_symbols; //Optional Data only included if indicated in pduBitmap - pusch_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 + pusch_pdu->pusch_data.rv_index = nr_rv_round_map[round]; pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 1; // new data + pusch_pdu->pusch_data.new_data_indicator = 1; pusch_pdu->pusch_data.num_cb = 0; + int num_dmrs_symb = 0; + for(int i = start_symbol_index; i < start_symbol_index+nr_of_symbols; i++) + num_dmrs_symb += (pusch_pdu->ul_dmrs_symb_pos >> i) & 1; pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, pusch_pdu->target_code_rate, pusch_pdu->rb_size, pusch_pdu->nr_of_symbols, - 12, // nb dmrs set for no data in dmrs symbol + num_dmrs_symb*12, // nb dmrs set for no data in dmrs symbol 0, //nb_rb_oh 0, // to verify tb scaling - pusch_pdu->nrOfLayers = 1)>>3; - - // calling function to fill rar message - nr_fill_rar(module_idP, ra, cc->RAR_pdu.payload, pusch_pdu); + pusch_pdu->nrOfLayers)>>3; } -// WIP -// todo: -// - fix me -// - get msg3 alloc (see nr_process_rar) -void nr_generate_Msg2(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP){ +void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu) +{ + gNB_MAC_INST *mac = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - int UE_id = 0, dci_formats[2], rnti_types[2], mcsIndex; - int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment; - gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; - NR_COMMON_channels_t *cc = &nr_mac->common_channels[0]; - NR_RA_t *ra = &cc->ra[0]; - NR_UE_list_t *UE_list = &nr_mac->UE_list; - NR_SearchSpace_t *ss = ra->ra_ss; - - uint16_t RA_rnti = ra->RA_rnti; - long locationAndBandwidth; - // uint8_t *vrb_map = cc[CC_id].vrb_map, CC_id; - - // check if UE is doing RA on CORESET0 , InitialBWP or configured BWP from SCD - // get the BW of the PDCCH for PDCCH size and RAR PDSCH size - - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - int dci10_bw; - - if (ra->coreset0_configured == 1) { - AssertFatal(1==0,"This is a standalone condition\n"); + if (ra->state == RA_IDLE) { + LOG_W(NR_MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti); + return; } - else { // on configured BWP or initial LDBWP, bandwidth parameters in DCI correspond size of initialBWP - locationAndBandwidth = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth; - dci10_bw = NRRIV2BW(locationAndBandwidth,275); + + uint16_t *vrb_map_UL = + &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE]; + for (int i = 0; i < ra->msg3_nb_rb; ++i) { + AssertFatal(!vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start], + "RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n", + i + ra->msg3_first_rb, + ra->Msg3_frame, + ra->Msg3_slot); + vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] = 1; } + LOG_D(NR_MAC, "[gNB %d][RAPROC] Frame %d, Slot %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot); + + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][ra->Msg3_slot]; + AssertFatal(future_ul_tti_req->SFN == ra->Msg3_frame + && future_ul_tti_req->Slot == ra->Msg3_slot, + "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + ra->Msg3_frame, + ra->Msg3_slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; + memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + + int ibwp_size = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int scs = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + int fh = 0; + int startSymbolAndLength = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; + int mappingtype = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType; + + if (ra->CellGroup) { + AssertFatal(ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, + "downlinkBWP_ToAddModList has %d BWP!\n", ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); + NR_BWP_Uplink_t *ubwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; + + startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; + mappingtype = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType; + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + fh = ubwp->bwp_Dedicated->pusch_Config->choice.setup->frequencyHopping ? 1 : 0; + } + + LOG_D(NR_MAC, "Frame %d, Slot %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d) for rnti: %d\n", + frameP, + slotP, + ra->Msg3_frame, + ra->Msg3_slot, + ra->msg3_nb_rb, + ra->msg3_first_rb, + ra->msg3_round, + ra->rnti); + + fill_msg3_pusch_pdu(pusch_pdu,scc, + ra->msg3_round, + startSymbolAndLength, + ra->rnti, scs, + ibwp_size, ra->msg3_bwp_start, + mappingtype, fh, + ra->msg3_first_rb, ra->msg3_nb_rb); + future_ul_tti_req->n_pdus += 1; + + // calling function to fill rar message + nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); +} + +void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) +{ + + gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; + if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) { - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; - nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + //TODO time domain assignment for msg2 needs to be improved + uint8_t time_domain_assignment; + if(cc->frame_type == TDD) + time_domain_assignment = 1; + else + time_domain_assignment = 0; + uint8_t mcsIndex = 0; + int rbStart = 0; + int rbSize = 8; - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; - memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + NR_SearchSpace_t *ss = ra->ra_ss; - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1]; - memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; - dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + NR_BWP_Downlink_t *bwp = NULL; + NR_ControlResourceSet_t *coreset = NULL; + NR_BWP_t *genericParameters = NULL; + NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList=NULL; - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + if (ra->CellGroup && + ra->CellGroup->spCellConfig && + ra->CellGroup->spCellConfig->spCellConfigDedicated && + ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList && + ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]) { + bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]; + genericParameters = &bwp->bwp_Common->genericParameters; + pdsch_TimeDomainAllocationList = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + } + else { + genericParameters= &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + pdsch_TimeDomainAllocationList = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + } - // Checking if the DCI allocation is feasible in current subframe - if (dl_req->nPDUs == NFAPI_NR_MAX_DL_TTI_PDUS) { - LOG_I(MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, RA_rnti); + long BWPStart = 0; + long BWPSize = 0; + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL; + if(*ss->controlResourceSetId!=0) { + BWPStart = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + BWPSize = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } else { + type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[ra->beam_id]; + BWPStart = type0_PDCCH_CSS_config->cset_start_rb; + BWPSize = type0_PDCCH_CSS_config->num_rbs; + } + + coreset = get_coreset(module_idP, scc, bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); + + AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg2\n"); + + uint16_t *vrb_map = cc[CC_id].vrb_map; + for (int i = 0; (i < rbSize) && (rbStart <= (BWPSize - rbSize)); i++) { + if (vrb_map[BWPStart + rbStart + i]) { + rbStart += i; + i = 0; + } + } + + if (rbStart > (BWPSize - rbSize)) { + LOG_E(NR_MAC, "%s(): cannot find free vrb_map for RA RNTI %04x!\n", __func__, ra->RA_rnti); return; } - LOG_I(MAC,"[gNB %d] [RAPROC] CC_id %d Frame %d, slotP %d: Generating RAR DCI, state %d\n", module_idP, CC_id, frameP, slotP, ra->state); + // Checking if the DCI allocation is feasible in current subframe + nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { + LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->RA_rnti); + return; + } - // This code from this point on will not work on initialBWP or CORESET0 - AssertFatal(ra->bwp_id>0,"cannot work on initialBWP for now\n"); + uint8_t aggregation_level; + uint8_t nr_of_candidates; + for (int i=0; i<5; i++) { + // for now taking the lowest value among the available aggregation levels + find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss, 1<0) break; + } + AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n"); + int CCEIndex = allocate_nr_CCEs(nr_mac, bwp, coreset, aggregation_level,0,0,nr_of_candidates); + if (CCEIndex < 0) { + LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti); + return; + } - NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id]; - AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); - NR_BWP_Downlink_t *bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1]; + // Calculate number of symbols + int startSymbolIndex, nrOfSymbols; + const int startSymbolAndLength = pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); + AssertFatal(startSymbolIndex >= 0, "StartSymbolIndex is negative\n"); - LOG_D(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw); + LOG_D(NR_MAC,"Msg2 startSymbolIndex.nrOfSymbols %d.%d\n",startSymbolIndex,nrOfSymbols); - // Qm>2 not allowed for RAR - if (get_softmodem_params()->do_ra) - mcsIndex = 9; - else - mcsIndex = 0; + int mappingtype = pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; + + // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially + // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them + const int bwpid = bwp ? bwp->bwp_Id : 0; + const int coresetid = coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; + if (!pdcch_pdu_rel15) { + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + dl_req->nPDUs += 1; + pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + nr_configure_pdcch(nr_mac, pdcch_pdu_rel15, ss, coreset, scc, genericParameters, NULL); + nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu_rel15; + } + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; + dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + dl_req->nPDUs+=1; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + + LOG_I(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d, slotP %d: Generating RA-Msg2 DCI, rnti 0x%04x, state %d, CoreSetType %d\n", + module_idP, CC_id, frameP, slotP, ra->RA_rnti, ra->state,pdcch_pdu_rel15->CoreSetType); + + // SCF222: PDU index incremented for each PDSCH PDU sent in TX control message. This is used to associate control + // information to data and is reset every slot. + const int pduindex = nr_mac->pdu_index[CC_id]++; + + uint8_t mcsTableIdx = 0; + if (bwp && + bwp->bwp_Dedicated && + bwp->bwp_Dedicated->pdsch_Config && + bwp->bwp_Dedicated->pdsch_Config->choice.setup && + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table) { + if (*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table == 0) + mcsTableIdx = 1; + else + mcsTableIdx = 2; + } + else mcsTableIdx = 0; + + int dmrsConfigType=0; + if (bwp && + bwp->bwp_Dedicated && + bwp->bwp_Dedicated->pdsch_Config && + bwp->bwp_Dedicated->pdsch_Config->choice.setup && + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA && + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup && + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type) + dmrsConfigType = 1; + + NR_PDSCH_Config_t *pdsch_config = bwp && bwp->bwp_Dedicated && bwp->bwp_Dedicated->pdsch_Config ? bwp->bwp_Dedicated->pdsch_Config->choice.setup : NULL; pdsch_pdu_rel15->pduBitmap = 0; - pdsch_pdu_rel15->rnti = RA_rnti; - pdsch_pdu_rel15->pduIndex = 0; - - - pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; + pdsch_pdu_rel15->rnti = ra->RA_rnti; + pdsch_pdu_rel15->pduIndex = pduindex; + pdsch_pdu_rel15->BWPSize = BWPSize; + pdsch_pdu_rel15->BWPStart = BWPStart; + pdsch_pdu_rel15->SubcarrierSpacing = genericParameters->subcarrierSpacing; pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; - pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcsIndex,0); + pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcsIndex,mcsTableIdx); pdsch_pdu_rel15->qamModOrder[0] = 2; pdsch_pdu_rel15->mcsIndex[0] = mcsIndex; - if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table == NULL) - pdsch_pdu_rel15->mcsTable[0] = 0; - else{ - if (*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table == 0) - pdsch_pdu_rel15->mcsTable[0] = 1; - else - pdsch_pdu_rel15->mcsTable[0] = 2; - } + pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx; pdsch_pdu_rel15->rvIndex[0] = 0; pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; pdsch_pdu_rel15->nrOfLayers = 1; pdsch_pdu_rel15->transmissionScheme = 0; pdsch_pdu_rel15->refPoint = 0; - pdsch_pdu_rel15->dmrsConfigType = 0; + pdsch_pdu_rel15->dmrsConfigType = dmrsConfigType; pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; pdsch_pdu_rel15->SCID = 0; - pdsch_pdu_rel15->numDmrsCdmGrpsNoData = 2; + pdsch_pdu_rel15->numDmrsCdmGrpsNoData = nrOfSymbols <= 2 ? 1 : 2; pdsch_pdu_rel15->dmrsPorts = 1; pdsch_pdu_rel15->resourceAlloc = 1; - pdsch_pdu_rel15->rbStart = 0; - pdsch_pdu_rel15->rbSize = 6; - pdsch_pdu_rel15->VRBtoPRBMapping = 0; // non interleaved + pdsch_pdu_rel15->rbStart = rbStart; + pdsch_pdu_rel15->rbSize = rbSize; + pdsch_pdu_rel15->VRBtoPRBMapping = 0; + pdsch_pdu_rel15->StartSymbolIndex = startSymbolIndex; + pdsch_pdu_rel15->NrOfSymbols = nrOfSymbols; + pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, + nr_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, + nrOfSymbols, + startSymbolIndex, + mappingtype); - for (int i=0; ibwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; i++) { - startSymbolAndLength = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength; - SLIV2SL(startSymbolAndLength, &StartSymbolIndex_tmp, &NrOfSymbols_tmp); - if (NrOfSymbols_tmp < NrOfSymbols) { - NrOfSymbols = NrOfSymbols_tmp; - StartSymbolIndex = StartSymbolIndex_tmp; - time_domain_assignment = i; // this is short PDSCH added to the config to fit mixed slot - } - } + int x_Overhead = 0; + uint8_t tb_scaling = 0; + nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, tb_scaling); - AssertFatal(StartSymbolIndex >= 0, "StartSymbolIndex is negative\n"); + // Fill PDCCH DL DCI PDU + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + pdcch_pdu_rel15->numDlDci++; + dci_pdu->RNTI = ra->RA_rnti; + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + dci_pdu->AggregationLevel = aggregation_level; + dci_pdu->CceIndex = CCEIndex; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; - pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; - pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; - pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, NrOfSymbols); + dci_pdu_rel15_t dci_payload; + dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, + pdsch_pdu_rel15->rbStart, + BWPSize); - dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; - dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, - pdsch_pdu_rel15->rbStart,dci10_bw); - dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; - dci_pdu_rel15[0].vrb_to_prb_mapping.val = 0; - dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0]; - dci_pdu_rel15[0].tb_scaling = 0; + LOG_D(NR_MAC,"Msg2 rbSize.rbStart.BWPsize %d.%d.%ld\n",pdsch_pdu_rel15->rbSize, + pdsch_pdu_rel15->rbStart, + BWPSize); - LOG_I(MAC, "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n", - dci_pdu_rel15[0].frequency_domain_assignment.val, - pdsch_pdu_rel15->rbStart, - pdsch_pdu_rel15->rbSize, - dci10_bw, - dci_pdu_rel15[0].time_domain_assignment.val, - dci_pdu_rel15[0].vrb_to_prb_mapping.val, - dci_pdu_rel15[0].mcs, - dci_pdu_rel15[0].tb_scaling); + dci_payload.time_domain_assignment.val = time_domain_assignment; + dci_payload.vrb_to_prb_mapping.val = 0; + dci_payload.mcs = pdsch_pdu_rel15->mcsIndex[0]; + dci_payload.tb_scaling = tb_scaling; - nr_configure_pdcch(nr_mac, pdcch_pdu_rel15, RA_rnti, 0, ss, scc, bwp); + LOG_D(NR_MAC, + "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%ld), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n", + dci_payload.frequency_domain_assignment.val, + pdsch_pdu_rel15->rbStart, + pdsch_pdu_rel15->rbSize, + BWPSize, + dci_payload.time_domain_assignment.val, + dci_payload.vrb_to_prb_mapping.val, + dci_payload.mcs, + dci_payload.tb_scaling); - LOG_I(MAC, "Frame %d: Subframe %d : Adding common DL DCI for RA_RNTI %x\n", frameP, slotP, RA_rnti); + LOG_D(NR_MAC, + "[RAPROC] DCI params: rnti 0x%x, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", + pdcch_pdu_rel15->dci_pdu[0].RNTI, + NR_RNTI_RA, + NR_DL_DCI_FORMAT_1_0, + *(unsigned long long *)pdcch_pdu_rel15->FreqDomainResource, + pdcch_pdu_rel15->StartSymbolIndex, + pdcch_pdu_rel15->DurationSymbols); - dci_formats[0] = NR_DL_DCI_FORMAT_1_0; - rnti_types[0] = NR_RNTI_RA; - - LOG_D(MAC, "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", - pdcch_pdu_rel15->dci_pdu.RNTI[0], - rnti_types[0], - dci_formats[0], - (unsigned long long)pdcch_pdu_rel15->FreqDomainResource, - pdcch_pdu_rel15->StartSymbolIndex, - pdcch_pdu_rel15->DurationSymbols); - - fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id); - - dl_req->nPDUs+=2; - - // Program UL processing for Msg3 - nr_get_Msg3alloc(scc, ubwp, slotP, frameP, ra); - LOG_I(MAC, "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); - nr_add_msg3(module_idP, CC_id, frameP, slotP); - ra->state = WAIT_Msg3; - LOG_D(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state); - - x_Overhead = 0; - nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_pdu_rel15[0].tb_scaling); + fill_dci_pdu_rel15(scc, + ra->CellGroup, + &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1], + &dci_payload, + NR_DL_DCI_FORMAT_1_0, + NR_RNTI_RA, + BWPSize, + bwpid); // DL TX request + nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + + // Program UL processing for Msg3 + NR_BWP_Uplink_t *ubwp = ra->CellGroup ? + ra->CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1] : + NULL; + nr_get_Msg3alloc(module_idP, CC_id, scc, ubwp, slotP, frameP, ra, nr_mac->tdd_beam_association); + nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *) &tx_req->TLVs[0].value.direct[0]); + + if(ra->cfra) { + LOG_I(NR_MAC, "Frame %d, Subframe %d: Setting RA-Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); + } + + T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->RA_rnti), T_INT(frameP), + T_INT(slotP), T_INT(0), T_BUFFER(&tx_req->TLVs[0].value.direct[0], tx_req->TLVs[0].length)); + tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0]; - tx_req->PDU_index = nr_mac->pdu_index[CC_id]++; + tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; - tx_req->TLVs[0].length = 8; + tx_req->TLVs[0].length = tx_req->PDU_length + 2; nr_mac->TX_req[CC_id].SFN = frameP; nr_mac->TX_req[CC_id].Number_of_PDUs++; nr_mac->TX_req[CC_id].Slot = slotP; - memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length); + + // Mark the corresponding RBs as used + for (int rb = 0; rb < rbSize; rb++) { + vrb_map[BWPStart + rb + rbStart] = 1; + } + + ra->state = WAIT_Msg3; + LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state); } } -void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP){ - NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[0]; - LOG_D(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra->rnti); - ra->state = IDLE; +void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) { + + gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; + + if (ra->Msg4_frame == frameP && ra->Msg4_slot == slotP ) { + + uint8_t time_domain_assignment = 0; + uint8_t mcsIndex = 0; + + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + NR_SearchSpace_t *ss = ra->ra_ss; + + NR_BWP_Downlink_t *bwp = NULL; + NR_ControlResourceSet_t *coreset = NULL; + NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList=NULL; + + if (ra->CellGroup && + ra->CellGroup->spCellConfig && + ra->CellGroup->spCellConfig->spCellConfigDedicated && + ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList && + ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]) { + bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]; + pdsch_TimeDomainAllocationList = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + } + else { + pdsch_TimeDomainAllocationList = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + } + + coreset = get_coreset(module_idP, scc, bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); + + AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n"); + + rnti_t tc_rnti = ra->rnti; + // If UE is known by the network, C-RNTI to be used instead of TC-RNTI + if(ra->msg3_dcch_dtch) { + ra->rnti = ra->crnti; + } + + int UE_id = find_nr_UE_id(module_idP, ra->rnti); + NR_UE_info_t *UE_info = &nr_mac->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + NR_BWP_t *genericParameters = bwp ? & bwp->bwp_Common->genericParameters : &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + + long BWPStart = 0; + long BWPSize = 0; + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL; + if(*ss->controlResourceSetId!=0) { + BWPStart = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + BWPSize = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + } else { + type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[ra->beam_id]; + BWPStart = type0_PDCCH_CSS_config->cset_start_rb; + BWPSize = type0_PDCCH_CSS_config->num_rbs; + } + + /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ + int current_harq_pid = sched_ctrl->retrans_dl_harq.head; + // HARQ management + if (current_harq_pid < 0) { + AssertFatal(sched_ctrl->available_dl_harq.head >= 0, + "UE context not initialized: no HARQ processes found\n"); + current_harq_pid = sched_ctrl->available_dl_harq.head; + remove_front_nr_list(&sched_ctrl->available_dl_harq); + } + NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; + DevAssert(!harq->is_waiting); + add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); + harq->is_waiting = true; + ra->harq_pid = current_harq_pid; + + // Remove UE associated to TC-RNTI + if(harq->round==0 && ra->msg3_dcch_dtch) { + mac_remove_nr_ue(module_idP, tc_rnti); + } + + // get CCEindex, needed also for PUCCH and then later for PDCCH + uint8_t aggregation_level; + uint8_t nr_of_candidates; + for (int i=0; i<5; i++) { + // for now taking the lowest value among the available aggregation levels + find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss, 1<0) break; + } + AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n"); + int CCEIndex = allocate_nr_CCEs(nr_mac, bwp, coreset, aggregation_level,0,0,nr_of_candidates); + if (CCEIndex < 0) { + LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI 0x%04x!\n", __func__, ra->rnti); + return; + } + + int n_rb=0; + for (int i=0;i<6;i++) + for (int j=0;j<8;j++) { + n_rb+=((coreset->frequencyDomainResources.buf[i]>>j)&1); + } + n_rb*=6; + const uint16_t N_cce = n_rb * coreset->duration / NR_NB_REG_PER_CCE; + const int delta_PRI=0; + int r_pucch = ((CCEIndex<<1)/N_cce)+(delta_PRI<<1); + + LOG_D(NR_MAC,"[RAPROC] Msg4 r_pucch %d (CCEIndex %d, N_cce %d, nb_of_candidates %d,delta_PRI %d)\n",r_pucch,CCEIndex,N_cce,nr_of_candidates,delta_PRI); + int alloc = nr_acknack_scheduling(module_idP, UE_id, frameP, slotP, r_pucch, 1); + AssertFatal(alloc>=0,"Couldn't find a pucch allocation for ack nack (msg4)\n"); + NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[alloc]; + harq->feedback_slot = pucch->ul_slot; + harq->feedback_frame = pucch->frame; + + uint8_t *buf = (uint8_t *) harq->tb; + // Bytes to be transmitted + if (harq->round == 0) { + if (ra->msg3_dcch_dtch) { + // If the UE used MSG3 to transfer a DCCH or DTCH message, then contention resolution is successful if the UE receives a PDCCH transmission which has its CRC bits scrambled by the C-RNTI + // Just send padding LCID + ra->mac_pdu_length = 0; + } else { + uint16_t mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id); + LOG_D(NR_MAC,"Encoded contention resolution mac_pdu_length %d\n",mac_pdu_length); + uint16_t mac_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, CCCH, ra->rnti, 1, &buf[mac_pdu_length+2]); + ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->R = 0; + ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->F = 0; + ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->LCID = DL_SCH_LCID_CCCH; + ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->L = mac_sdu_length; + ra->mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_SHORT); + LOG_D(NR_MAC,"Encoded RRCSetup Piggyback (%d + %d bytes), mac_pdu_length %d\n", mac_sdu_length, (int)sizeof(NR_MAC_SUBHEADER_SHORT), ra->mac_pdu_length); + } + } + + // Calculate number of symbols + int startSymbolIndex, nrOfSymbols; + const int startSymbolAndLength = pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); + AssertFatal(startSymbolIndex >= 0, "StartSymbolIndex is negative\n"); + + int mappingtype = pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; + + uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, + scc->dmrs_TypeA_Position, + nrOfSymbols, + startSymbolIndex, + mappingtype); + + uint16_t N_DMRS_SLOT = get_num_dmrs(dlDmrsSymbPos); + + long dmrsConfigType = bwp!=NULL ? (bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1) : 0; + + nr_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData = 2; + if (nrOfSymbols == 2) { + nr_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData = 1; + } + + AssertFatal(nr_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData == 1 + || nr_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData == 2, + "nr_mac->schedCtrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData %d is not possible", + nr_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData); + + uint8_t N_PRB_DMRS = 0; + if (dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { + N_PRB_DMRS = nr_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData * 6; + } + else { + N_PRB_DMRS = nr_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData * 4; + } + + uint8_t mcsTableIdx = 0; + if (bwp && + bwp->bwp_Dedicated && + bwp->bwp_Dedicated->pdsch_Config && + bwp->bwp_Dedicated->pdsch_Config->choice.setup && + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table) { + if (*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table == 0) + mcsTableIdx = 1; + else + mcsTableIdx = 2; + } + else mcsTableIdx = 0; + + int rbStart = 0; + int rbSize = 0; + uint8_t tb_scaling = 0; + uint16_t *vrb_map = cc[CC_id].vrb_map; + do { + rbSize++; + LOG_D(NR_MAC,"Calling nr_compute_tbs with N_PRB_DMRS %d, N_DMRS_SLOT %d\n",N_PRB_DMRS,N_DMRS_SLOT); + harq->tb_size = nr_compute_tbs(nr_get_Qm_dl(mcsIndex, mcsTableIdx), + nr_get_code_rate_dl(mcsIndex, mcsTableIdx), + rbSize, nrOfSymbols, N_PRB_DMRS * N_DMRS_SLOT, 0, tb_scaling,1) >> 3; + } while (rbSize < BWPSize && harq->tb_size < ra->mac_pdu_length); + + int i = 0; + while ((i < rbSize) && (rbStart + rbSize <= BWPSize)) { + if (vrb_map[BWPStart + rbStart + i]) { + rbStart += i+1; + i = 0; + } else { + i++; + } + } + + if (rbStart > (BWPSize - rbSize)) { + LOG_E(NR_MAC, "%s(): cannot find free vrb_map for RNTI %04x!\n", __func__, ra->rnti); + return; + } + + // Checking if the DCI allocation is feasible in current subframe + nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { + LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->rnti); + return; + } + + + // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially + // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them + const int bwpid = bwp ? bwp->bwp_Id : 0; + const int coresetid = coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; + if (!pdcch_pdu_rel15) { + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + dl_req->nPDUs += 1; + pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + nr_configure_pdcch(nr_mac, pdcch_pdu_rel15, ss, coreset, scc, genericParameters, NULL); + nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu_rel15; + } + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; + dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + dl_req->nPDUs+=1; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + + LOG_I(NR_MAC,"[gNB %d] [RAPROC] CC_id %d Frame %d, slotP %d: Generating RA-Msg4 DCI, state %d\n", module_idP, CC_id, frameP, slotP, ra->state); + + // SCF222: PDU index incremented for each PDSCH PDU sent in TX control message. This is used to associate control + // information to data and is reset every slot. + const int pduindex = nr_mac->pdu_index[CC_id]++; + + pdsch_pdu_rel15->pduBitmap = 0; + pdsch_pdu_rel15->rnti = ra->rnti; + pdsch_pdu_rel15->pduIndex = pduindex; + pdsch_pdu_rel15->BWPSize = BWPSize; + pdsch_pdu_rel15->BWPStart = BWPStart; + pdsch_pdu_rel15->SubcarrierSpacing = genericParameters->subcarrierSpacing; + pdsch_pdu_rel15->CyclicPrefix = 0; + pdsch_pdu_rel15->NrOfCodewords = 1; + pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcsIndex,mcsTableIdx); + pdsch_pdu_rel15->qamModOrder[0] = 2; + pdsch_pdu_rel15->mcsIndex[0] = mcsIndex; + pdsch_pdu_rel15->mcsTable[0] = mcsTableIdx; + pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[harq->round]; + pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; + pdsch_pdu_rel15->nrOfLayers = 1; + pdsch_pdu_rel15->transmissionScheme = 0; + pdsch_pdu_rel15->refPoint = 0; + pdsch_pdu_rel15->dmrsConfigType = dmrsConfigType; + pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; + pdsch_pdu_rel15->SCID = 0; + pdsch_pdu_rel15->numDmrsCdmGrpsNoData = nrOfSymbols <= 2 ? 1 : 2; + pdsch_pdu_rel15->dmrsPorts = 1; + pdsch_pdu_rel15->resourceAlloc = 1; + pdsch_pdu_rel15->rbStart = rbStart; + pdsch_pdu_rel15->rbSize = rbSize; + pdsch_pdu_rel15->VRBtoPRBMapping = 0; + pdsch_pdu_rel15->StartSymbolIndex = startSymbolIndex; + pdsch_pdu_rel15->NrOfSymbols = nrOfSymbols; + pdsch_pdu_rel15->dlDmrsSymbPos = dlDmrsSymbPos; + + int x_Overhead = 0; + nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, tb_scaling); + + pdsch_pdu_rel15->precodingAndBeamforming.num_prgs=1; + pdsch_pdu_rel15->precodingAndBeamforming.prg_size=275; + pdsch_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces=1; + pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0; + pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + pdcch_pdu_rel15->numDlDci++; + dci_pdu->RNTI = ra->rnti; + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + dci_pdu->AggregationLevel = aggregation_level; + dci_pdu->CceIndex = CCEIndex; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + + dci_pdu_rel15_t dci_payload; + dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, + pdsch_pdu_rel15->rbStart, + BWPSize); + + dci_payload.format_indicator = 1; + dci_payload.time_domain_assignment.val = time_domain_assignment; + dci_payload.vrb_to_prb_mapping.val = 0; + dci_payload.mcs = pdsch_pdu_rel15->mcsIndex[0]; + dci_payload.tb_scaling = tb_scaling; + dci_payload.rv = pdsch_pdu_rel15->rvIndex[0]; + dci_payload.harq_pid = current_harq_pid; + dci_payload.ndi = harq->ndi; + dci_payload.dai[0].val = (pucch->dai_c-1)&3; + dci_payload.tpc = sched_ctrl->tpc1; // TPC for PUCCH: table 7.2.1-1 in 38.213 + dci_payload.pucch_resource_indicator = delta_PRI; // This is delta_PRI from 9.2.1 in 38.213 + dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch->timing_indicator; + + LOG_D(NR_MAC, + "[RAPROC] DCI 1_0 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d pucchres %d harqtiming %d\n", + dci_payload.frequency_domain_assignment.val, + pdsch_pdu_rel15->rbStart, + pdsch_pdu_rel15->rbSize, + pdsch_pdu_rel15->BWPSize, + dci_payload.time_domain_assignment.val, + dci_payload.vrb_to_prb_mapping.val, + dci_payload.mcs, + dci_payload.tb_scaling, + dci_payload.pucch_resource_indicator, + dci_payload.pdsch_to_harq_feedback_timing_indicator.val); + + LOG_D(NR_MAC, + "[RAPROC] DCI params: rnti 0x%x, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d, BWPsize %d\n", + pdcch_pdu_rel15->dci_pdu[0].RNTI, + NR_RNTI_TC, + NR_DL_DCI_FORMAT_1_0, + (unsigned long long)pdcch_pdu_rel15->FreqDomainResource, + pdcch_pdu_rel15->StartSymbolIndex, + pdcch_pdu_rel15->DurationSymbols, + pdsch_pdu_rel15->BWPSize); + + fill_dci_pdu_rel15(scc, + ra->CellGroup, + &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1], + &dci_payload, + NR_DL_DCI_FORMAT_1_0, + NR_RNTI_TC, + pdsch_pdu_rel15->BWPSize, + bwpid); + + // Add padding header and zero rest out if there is space left + if (ra->mac_pdu_length < harq->tb_size) { + NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) &buf[ra->mac_pdu_length]; + padding->R = 0; + padding->LCID = DL_SCH_LCID_PADDING; + for(int k = ra->mac_pdu_length+1; ktb_size; k++) { + buf[k] = 0; + } + } + + T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti), + T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->tb, harq->tb_size)); + + // DL TX request + nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; + memcpy(tx_req->TLVs[0].value.direct, harq->tb, sizeof(uint8_t) * harq->tb_size); + tx_req->PDU_length = harq->tb_size; + tx_req->PDU_index = pduindex; + tx_req->num_TLV = 1; + tx_req->TLVs[0].length = harq->tb_size + 2; + nr_mac->TX_req[CC_id].SFN = frameP; + nr_mac->TX_req[CC_id].Number_of_PDUs++; + nr_mac->TX_req[CC_id].Slot = slotP; + + // Mark the corresponding RBs as used + for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++) { + vrb_map[BWPStart + rb + pdsch_pdu_rel15->rbStart] = 1; + } + + LOG_D(NR_MAC,"BWPSize: %i\n", pdcch_pdu_rel15->BWPSize); + LOG_D(NR_MAC,"BWPStart: %i\n", pdcch_pdu_rel15->BWPStart); + LOG_D(NR_MAC,"SubcarrierSpacing: %i\n", pdcch_pdu_rel15->SubcarrierSpacing); + LOG_D(NR_MAC,"CyclicPrefix: %i\n", pdcch_pdu_rel15->CyclicPrefix); + LOG_D(NR_MAC,"StartSymbolIndex: %i\n", pdcch_pdu_rel15->StartSymbolIndex); + LOG_D(NR_MAC,"DurationSymbols: %i\n", pdcch_pdu_rel15->DurationSymbols); + for(int n=0;n<6;n++) LOG_D(NR_MAC,"FreqDomainResource[%i]: %x\n",n, pdcch_pdu_rel15->FreqDomainResource[n]); + LOG_D(NR_MAC,"CceRegMappingType: %i\n", pdcch_pdu_rel15->CceRegMappingType); + LOG_D(NR_MAC,"RegBundleSize: %i\n", pdcch_pdu_rel15->RegBundleSize); + LOG_D(NR_MAC,"InterleaverSize: %i\n", pdcch_pdu_rel15->InterleaverSize); + LOG_D(NR_MAC,"CoreSetType: %i\n", pdcch_pdu_rel15->CoreSetType); + LOG_D(NR_MAC,"ShiftIndex: %i\n", pdcch_pdu_rel15->ShiftIndex); + LOG_D(NR_MAC,"precoderGranularity: %i\n", pdcch_pdu_rel15->precoderGranularity); + LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); + + if(ra->msg3_dcch_dtch) { + // If the UE used MSG3 to transfer a DCCH or DTCH message, then contention resolution is successful upon transmission of PDCCH + LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) CBRA procedure succeeded!\n", UE_id, ra->rnti); + nr_clear_ra_proc(module_idP, CC_id, frameP, ra); + UE_info->active[UE_id] = true; + UE_info->Msg4_ACKed[UE_id] = true; + + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + harq->feedback_slot = -1; + harq->is_waiting = false; + add_tail_nr_list(&sched_ctrl->available_dl_harq, current_harq_pid); + harq->round = 0; + harq->ndi ^= 1; + } else { + ra->state = WAIT_Msg4_ACK; + LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state); + } + } +} + +void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { + + int UE_id = find_nr_UE_id(module_id, ra->rnti); + const int current_harq_pid = ra->harq_pid; + + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + + LOG_D(NR_MAC, "ue %d, rnti 0x%04x, harq is waiting %d, round %d, frame %d %d, harq id %d\n", UE_id, ra->rnti, harq->is_waiting, harq->round, frame, slot, current_harq_pid); + + if (harq->is_waiting == 0) { + if (harq->round == 0) { + if (stats->dlsch_errors == 0) { + LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", UE_id, ra->rnti); + UE_info->active[UE_id] = true; + UE_info->Msg4_ACKed[UE_id] = true; + } + else { + LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) RA Procedure failed at Msg4!\n", UE_id, ra->rnti); + } + + nr_clear_ra_proc(module_id, CC_id, frame, ra); + if(sched_ctrl->retrans_dl_harq.head >= 0) { + remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); + } + } + else { + LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) Received Nack of RA-Msg4. Preparing retransmission!\n", UE_id, ra->rnti); + ra->Msg4_frame = (frame + 1) % 1024; + ra->Msg4_slot = 1; + ra->state = Msg4; + } + } +} + +void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t *ra){ + LOG_D(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra->rnti); + ra->state = RA_IDLE; ra->timing_offset = 0; ra->RRC_timer = 20; - ra->rnti = 0; ra->msg3_round = 0; + ra->msg3_dcch_dtch = false; + ra->crnti = 0; + if(ra->cfra == false) { + ra->rnti = 0; + } } @@ -763,9 +1880,10 @@ void nr_fill_rar(uint8_t Mod_idP, uint8_t * dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu){ - LOG_D(MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d ", ra->Msg2_frame, ra-> Msg2_slot); - NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; - NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); + LOG_I(NR_MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index, ra->timing_offset); + NR_RA_HEADER_BI *rarbi = (NR_RA_HEADER_BI *) dlsch_buffer; + NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) (dlsch_buffer + 1); + NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 2); unsigned char csi_req = 0, tpc_command; //uint8_t N_UL_Hop; uint8_t valid_bits; @@ -774,6 +1892,16 @@ void nr_fill_rar(uint8_t Mod_idP, tpc_command = 3; // this is 0 dB + /// E/T/R/R/BI subheader /// + // E = 1, MAC PDU includes another MAC sub-PDU (RAPID) + // T = 0, Back-off indicator subheader + // R = 2, Reserved + // BI = 0, 5ms + rarbi->E = 1; + rarbi->T = 0; + rarbi->R = 0; + rarbi->BI = 0; + /// E/T/RAPID subheader /// // E = 0, one only RAR, first and last // T = 1, RAPID @@ -820,4 +1948,50 @@ void nr_fill_rar(uint8_t Mod_idP, rar->UL_GRANT_3 = (uint8_t) (ul_grant >> 8) & 0xff; rar->UL_GRANT_4 = (uint8_t) ul_grant & 0xff; +#ifdef DEBUG_RAR + //LOG_I(NR_MAC, "rarbi->E = 0x%x\n", rarbi->E); + //LOG_I(NR_MAC, "rarbi->T = 0x%x\n", rarbi->T); + //LOG_I(NR_MAC, "rarbi->R = 0x%x\n", rarbi->R); + //LOG_I(NR_MAC, "rarbi->BI = 0x%x\n", rarbi->BI); + + LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E); + LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T); + LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID); + + LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R); + LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1); + + LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2); + LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1); + + LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2); + LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3); + LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4); + + LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1); + LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2); +#endif + + int mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); + // time alloc + int Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07); + // frequency alloc + int Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); + // frequency hopping + int freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2); + // TA command + int ta_command = rar->TA2 + (rar->TA1 << 5); + // TC-RNTI + int t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); + + LOG_D(NR_MAC, "In %s: Transmitted RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d csi_req %d t_crnti %x \n", + __FUNCTION__, + Msg3_t_alloc, + Msg3_f_alloc, + ta_command, + mcs, + freq_hopping, + tpc_command, + csi_req, + t_crnti); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 5fa77c6ca7..df25b085e6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -30,6 +30,7 @@ */ +#include "GNB_APP/RRC_nr_paramsvalues.h" #include "assertions.h" #include "NR_MAC_gNB/nr_mac_gNB.h" #include "NR_MAC_gNB/mac_proto.h" @@ -38,107 +39,608 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "UTIL/OPT/opt.h" #include "OCG.h" -#include "OCG_extern.h" - #include "RRC/NR/nr_rrc_extern.h" +#include "common/utils/nr/nr_common.h" -//#include "LAYER2/MAC/pre_processor.c" #include "pdcp.h" -#include "intertask_interface.h" - #define ENABLE_MAC_PAYLOAD_DEBUG #define DEBUG_eNB_SCHEDULER 1 #include "common/ran_context.h" +#include "executables/softmodem-common.h" + extern RAN_CONTEXT_t RC; -void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){ +uint16_t get_ssboffset_pointa(NR_ServingCellConfigCommon_t *scc,const long band) { + + int ratio; + switch (*scc->ssbSubcarrierSpacing) { + case NR_SubcarrierSpacing_kHz15: + AssertFatal(band <= 95, + "Band %ld is not possible for SSB with 15 kHz SCS\n", + band); + // no band available above 3GHz using 15kHz + ratio = 3; // NRARFCN step is 5 kHz + break; + case NR_SubcarrierSpacing_kHz30: + AssertFatal(band <= 96, + "Band %ld is not possible for SSB with 30 kHz SCS\n", + band); + if (band == 46 || band == 48 || band == 77 || + band == 78 || band == 79 || band == 96) // above 3GHz + ratio = 2; // NRARFCN step is 15 kHz + else + ratio = 6; // NRARFCN step is 5 kHz + break; + case NR_SubcarrierSpacing_kHz120: + AssertFatal(band >= 257, + "Band %ld is not possible for SSB with 120 kHz SCS\n", + band); + ratio = 2; // NRARFCN step is 15 kHz + break; + case NR_SubcarrierSpacing_kHz240: + AssertFatal(band >= 257, + "Band %ld is not possible for SSB with 240 kHz SCS\n", + band); + ratio = 4; // NRARFCN step is 15 kHz + break; + default: + AssertFatal(1 == 0, "SCS %ld not allowed for SSB \n", + *scc->ssbSubcarrierSpacing); + } + + const uint32_t ssb_offset0 = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; + + return (ssb_offset0/(ratio*12) - 10); // absoluteFrequencySSB is the center of SSB + +} + + +void schedule_ssb(frame_t frame, sub_frame_t slot, + NR_ServingCellConfigCommon_t *scc, + nfapi_nr_dl_tti_request_body_t *dl_req, + int i_ssb, uint8_t scoffset, uint16_t offset_pointa, uint32_t payload) { + + uint8_t beam_index = 0; + nfapi_nr_dl_tti_request_pdu_t *dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_config_pdu->PDUType = NFAPI_NR_DL_TTI_SSB_PDU_TYPE; + dl_config_pdu->PDUSize =2 + sizeof(nfapi_nr_dl_tti_ssb_pdu_rel15_t); + + AssertFatal(scc->physCellId!=NULL,"ServingCellConfigCommon->physCellId is null\n"); + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.PhysCellId = *scc->physCellId; + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.BetaPss = 0; + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i_ssb; + AssertFatal(scc->downlinkConfigCommon!=NULL,"scc->downlinkConfigCommonL is null\n"); + AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n"); + AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB is null\n"); + AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count==1,"Frequency Band list does not have 1 element (%d)\n", + scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count); + AssertFatal(scc->ssbSubcarrierSpacing,"ssbSubcarrierSpacing is null\n"); + AssertFatal(scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],"band is null\n"); + + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = scoffset; //kSSB + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = offset_pointa; + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1; + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = payload; + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.num_prgs=1; + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size=275; //1 PRG of max size for analogue beamforming + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.dig_bf_interfaces=1; + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].pm_idx = 0; + dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; + dl_req->nPDUs++; + + LOG_D(MAC,"Scheduling ssb %d at frame %d and slot %d\n",i_ssb,frame,slot); + +} + +void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc; - nfapi_nr_dl_tti_request_t *dl_tti_request; nfapi_nr_dl_tti_request_body_t *dl_req; - nfapi_nr_dl_tti_request_pdu_t *dl_config_pdu; - + NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib.message.choice.mib; + uint8_t num_tdd_period,num_ssb; int mib_sdu_length; int CC_id; - AssertFatal(slotP == 0, "Subframe must be 0\n"); - AssertFatal((frameP & 7) == 0, "Frame must be a multiple of 8\n"); - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - + cc = &gNB->common_channels[CC_id]; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + const int slots_per_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; dl_tti_request = &gNB->DL_req[CC_id]; dl_req = &dl_tti_request->dl_tti_request_body; - cc = &gNB->common_channels[CC_id]; - mib_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, MIBCH, 1, &cc->MIB_pdu.payload[0]); // not used in this case + // get MIB every 8 frames + if(((slotP == 0) && (frameP & 7) == 0) || + gNB->first_MIB) { - LOG_D(MAC, "Frame %d, slot %d: BCH PDU length %d\n", frameP, slotP, mib_sdu_length); + mib_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, MIBCH, 0, 1, &cc->MIB_pdu.payload[0]); - if (mib_sdu_length > 0) { + // flag to avoid sending an empty MIB in the first frames of execution since gNB doesn't get at the beginning in frame 0 slot 0 + gNB->first_MIB = false; - LOG_I(MAC, "Frame %d, slot %d: Adding BCH PDU in position %d (length %d)\n", frameP, slotP, dl_req->nPDUs, mib_sdu_length); + LOG_D(MAC, + "[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n", + module_idP, + frameP, + CC_id, + mib_sdu_length); + } - if ((frameP & 1023) < 80){ - LOG_I(MAC,"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",module_idP, frameP, CC_id, mib_sdu_length); + int8_t ssb_period = *scc->ssb_periodicityServingCell; + uint8_t ssb_frame_periodicity = 1; // every how many frames SSB are generated + + if (ssb_period > 1) // 0 is every half frame + ssb_frame_periodicity = 1 << (ssb_period -1); + + if (!(frameP%ssb_frame_periodicity) && + ((slotP<(slots_per_frame>>1)) || (ssb_period == 0))) { + // schedule SSB only for given frames according to SSB periodicity + // and in first half frame unless periodicity of 5ms + int rel_slot; + if (ssb_period == 0) // scheduling every half frame + rel_slot = slotP%(slots_per_frame>>1); + else + rel_slot = slotP; + + NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing; + const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + uint16_t offset_pointa = get_ssboffset_pointa(scc,band); + uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset; + + const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; + const BIT_STRING_t *mediumBitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; + const BIT_STRING_t *longBitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + + uint16_t ssb_start_symbol; + + switch (scc->ssb_PositionsInBurst->present) { + case 1: + // short bitmap (<3GHz) max 4 SSBs + for (int i_ssb=0; i_ssb<4; i_ssb++) { + if ((shortBitmap->buf[0]>>(7-i_ssb))&0x01) { + ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); + // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters + if ((ssb_start_symbol/14) == rel_slot){ + schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); + fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); + if (get_softmodem_params()->sa == 1) { + get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], + frameP, + mib, + slots_per_frame, + ssbSubcarrierOffset, + ssb_start_symbol, + scs, + FR1, + band, + i_ssb, + ssb_frame_periodicity, + offset_pointa); + gNB->type0_PDCCH_CSS_config[i_ssb].active = true; + } + } + } + } + break; + case 2: + // medium bitmap (<6GHz) max 8 SSBs + for (int i_ssb=0; i_ssb<8; i_ssb++) { + if ((mediumBitmap->buf[0]>>(7-i_ssb))&0x01) { + ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); + // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters + if ((ssb_start_symbol/14) == rel_slot){ + schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); + fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); + if (get_softmodem_params()->sa == 1) { + get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], + frameP, + mib, + slots_per_frame, + ssbSubcarrierOffset, + ssb_start_symbol, + scs, + FR1, + band, + i_ssb, + ssb_frame_periodicity, + offset_pointa); + gNB->type0_PDCCH_CSS_config[i_ssb].active = true; + } + } + } + } + break; + case 3: + // long bitmap FR2 max 64 SSBs + num_ssb = 0; + for (int i_ssb=0; i_ssb<64; i_ssb++) { + if ((longBitmap->buf[i_ssb/8]>>(7-(i_ssb%8)))&0x01) { + ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); + // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters + if ((ssb_start_symbol/14) == rel_slot){ + schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); + fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); + const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots; + num_tdd_period = rel_slot/nr_slots_period; + gNB->tdd_beam_association[num_tdd_period]=i_ssb; + num_ssb++; + AssertFatal(num_ssb<2,"beamforming currently not supported for more than one SSB per slot\n"); + if (get_softmodem_params()->sa == 1) { + get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], + frameP, + mib, + slots_per_frame, + ssbSubcarrierOffset, + ssb_start_symbol, + scs, + FR2, + band, + i_ssb, + ssb_frame_periodicity, + offset_pointa); + gNB->type0_PDCCH_CSS_config[i_ssb].active = true; + } + } + } + } + break; + default: + AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n", + scc->ssb_PositionsInBurst->present); } - - dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; - memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_config_pdu->PDUType = NFAPI_NR_DL_TTI_SSB_PDU_TYPE; - dl_config_pdu->PDUSize =2 + sizeof(nfapi_nr_dl_tti_ssb_pdu_rel15_t); - - AssertFatal(cc->ServingCellConfigCommon->physCellId!=NULL,"cc->ServingCellConfigCommon->physCellId is null\n"); - dl_config_pdu->ssb_pdu.ssb_pdu_rel15.PhysCellId = *cc->ServingCellConfigCommon->physCellId; - dl_config_pdu->ssb_pdu.ssb_pdu_rel15.BetaPss = 0; - dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0; - AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon!=NULL,"scc->downlinkConfigCommonL is null\n"); - AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n"); - AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB is null\n"); - AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count==1,"Frequency Band list does not have 1 element (%d)\n",cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count); - AssertFatal(cc->ServingCellConfigCommon->ssbSubcarrierSpacing,"ssbSubcarrierSpacing is null\n"); - AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],"band is null\n"); - long band = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - uint32_t ssb_offset0 = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; - int ratio; - switch (*cc->ServingCellConfigCommon->ssbSubcarrierSpacing) { - case NR_SubcarrierSpacing_kHz15: - AssertFatal(band <= 79, "Band %ld is not possible for SSB with 15 kHz SCS\n",band); - if (band<77) // below 3GHz - ratio=3; // NRARFCN step is 5 kHz - else - ratio=1; // NRARFCN step is 15 kHz - break; - case NR_SubcarrierSpacing_kHz30: - AssertFatal(band <= 79, "Band %ld is not possible for SSB with 15 kHz SCS\n",band); - if (band<77) // below 3GHz - ratio=6; // NRARFCN step is 5 kHz - else - ratio=2; // NRARFCN step is 15 kHz - break; - case NR_SubcarrierSpacing_kHz120: - AssertFatal(band >= 257, "Band %ld is not possible for SSB with 120 kHz SCS\n",band); - ratio=2; // NRARFCN step is 15 kHz - break; - case NR_SubcarrierSpacing_kHz240: - AssertFatal(band >= 257, "Band %ld is not possible for SSB with 240 kHz SCS\n",band); - ratio=4; // NRARFCN step is 15 kHz - break; - default: - AssertFatal(1==0,"SCS %ld not allowed for SSB \n", *cc->ServingCellConfigCommon->ssbSubcarrierSpacing); - } - dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = 0; //kSSB - dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = ssb_offset0/(ratio*12) - 10; // absoluteFrequencySSB is the center of SSB - dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1; - dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1); - dl_req->nPDUs++; } } } +void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { +//---------------------------------------- +} + +void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart, int CC_id) { + + AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing != + NR_SubcarrierSpacing_kHz240, + "240kHZ subcarrier won't work with current VRB map because a single SSB might be across 2 slots\n"); + + uint16_t *vrb_map = cc[CC_id].vrb_map; + + for (int rb = 0; rb < 20; rb++) + vrb_map[rbStart + rb] = 15<common_channels[CC_id].vrb_map; + + if (gNB_mac->sched_ctrlCommon == NULL){ + LOG_D(NR_MAC,"schedule_control_common: Filling nr_mac->sched_ctrlCommon\n"); + gNB_mac->sched_ctrlCommon = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon)); + gNB_mac->sched_ctrlCommon->search_space = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->search_space)); + gNB_mac->sched_ctrlCommon->coreset = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->coreset)); + fill_searchSpaceZero(gNB_mac->sched_ctrlCommon->search_space,type0_PDCCH_CSS_config); + fill_coresetZero(gNB_mac->sched_ctrlCommon->coreset,type0_PDCCH_CSS_config); + gNB_mac->cset0_bwp_start = type0_PDCCH_CSS_config->cset_start_rb; + gNB_mac->cset0_bwp_size = type0_PDCCH_CSS_config->num_rbs; + } + + gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation = time_domain_allocation; + gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx = 0; + gNB_mac->sched_ctrlCommon->sched_pdsch.mcs = 0; // starting from mcs 0 + gNB_mac->sched_ctrlCommon->num_total_bytes = num_total_bytes; + + uint8_t nr_of_candidates; + + for (int i=0; i<3; i++) { + find_aggregation_candidates(&gNB_mac->sched_ctrlCommon->aggregation_level, &nr_of_candidates, gNB_mac->sched_ctrlCommon->search_space,4<0) break; // choosing the lower value of aggregation level available + } + AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n"); + gNB_mac->sched_ctrlCommon->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], + NULL, + gNB_mac->sched_ctrlCommon->coreset, + gNB_mac->sched_ctrlCommon->aggregation_level, + 0, + candidate_idx, + nr_of_candidates); + + AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n"); + + const uint16_t bwpSize = type0_PDCCH_CSS_config->num_rbs; + int rbStart = type0_PDCCH_CSS_config->cset_start_rb; + + // TODO: There are exceptions to this in table 5.1.2.1.1-4,5 (Default time domain allocation tables B, C) + int mappingtype = (startSymbolIndex <= 3)? typeA: typeB; + + if (nrOfSymbols == 2) { + gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData = 1; + } else { + gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData = 2; + } + + // Calculate number of PRB_DMRS + uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData * 6; + uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos); + + LOG_D(MAC,"dlDmrsSymbPos %x\n",dlDmrsSymbPos); + int rbSize = 0; + uint32_t TBS = 0; + do { + if(rbSize < bwpSize && !vrb_map[rbStart + rbSize]) + rbSize++; + else{ + if (gNB_mac->sched_ctrlCommon->sched_pdsch.mcs<10) + gNB_mac->sched_ctrlCommon->sched_pdsch.mcs++; + else + break; + } + TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx), + nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx), + rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3; + } while (TBS < gNB_mac->sched_ctrlCommon->num_total_bytes); + + AssertFatal(TBS>=gNB_mac->sched_ctrlCommon->num_total_bytes,"Couldn't allocate enough resources for %d bytes in SIB1 PDSCH\n", + gNB_mac->sched_ctrlCommon->num_total_bytes); + + gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize = rbSize; + gNB_mac->sched_ctrlCommon->sched_pdsch.rbStart = 0; + + LOG_D(MAC,"mcs = %i\n", gNB_mac->sched_ctrlCommon->sched_pdsch.mcs); + LOG_D(MAC,"startSymbolIndex = %i\n", startSymbolIndex); + LOG_D(MAC,"nrOfSymbols = %i\n", nrOfSymbols); + LOG_D(MAC, "rbSize = %i\n", gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize); + LOG_D(MAC,"TBS = %i\n", TBS); + LOG_D(MAC,"dmrs_length %d\n",dmrs_length); + LOG_D(MAC,"N_PRB_DMRS = %d\n",N_PRB_DMRS); + LOG_D(MAC,"mappingtype = %d\n", mappingtype); + + // Mark the corresponding RBs as used + for (int rb = 0; rb < gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize; rb++) { + vrb_map[rb + rbStart] = 1; + } + return TBS; +} + +void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, + nfapi_nr_dl_tti_request_body_t *dl_req, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + uint32_t TBS, + int StartSymbolIndex, + int NrOfSymbols, + uint16_t dlDmrsSymbPos) { + + gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; + NR_COMMON_channels_t *cc = gNB_mac->common_channels; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + dl_req->nPDUs += 1; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + nr_configure_pdcch(NULL, + pdcch_pdu_rel15, + gNB_mac->sched_ctrlCommon->search_space, + gNB_mac->sched_ctrlCommon->coreset, + scc, + NULL, + type0_PDCCH_CSS_config); + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; + dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + dl_req->nPDUs += 1; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + + pdcch_pdu_rel15->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; + + pdsch_pdu_rel15->pduBitmap = 0; + pdsch_pdu_rel15->rnti = SI_RNTI; + pdsch_pdu_rel15->pduIndex = gNB_mac->pdu_index[0]++; + + pdsch_pdu_rel15->BWPSize = type0_PDCCH_CSS_config->num_rbs; + pdsch_pdu_rel15->BWPStart = type0_PDCCH_CSS_config->cset_start_rb; + + pdsch_pdu_rel15->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch; + pdsch_pdu_rel15->CyclicPrefix = 0; + + pdsch_pdu_rel15->NrOfCodewords = 1; + pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, 0); + pdsch_pdu_rel15->qamModOrder[0] = 2; + pdsch_pdu_rel15->mcsIndex[0] = gNB_mac->sched_ctrlCommon->sched_pdsch.mcs; + pdsch_pdu_rel15->mcsTable[0] = 0; + pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[0]; + pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; + pdsch_pdu_rel15->nrOfLayers = 1; + pdsch_pdu_rel15->transmissionScheme = 0; + pdsch_pdu_rel15->refPoint = 1; + pdsch_pdu_rel15->dmrsConfigType = 0; + pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; + pdsch_pdu_rel15->SCID = 0; + pdsch_pdu_rel15->numDmrsCdmGrpsNoData = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData; + pdsch_pdu_rel15->dmrsPorts = 1; + pdsch_pdu_rel15->resourceAlloc = 1; + pdsch_pdu_rel15->rbStart = gNB_mac->sched_ctrlCommon->sched_pdsch.rbStart; + pdsch_pdu_rel15->rbSize = gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize; + pdsch_pdu_rel15->VRBtoPRBMapping = 0; + pdsch_pdu_rel15->qamModOrder[0] = nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, + gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx); + pdsch_pdu_rel15->TBSize[0] = TBS; + pdsch_pdu_rel15->mcsTable[0] = gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx; + pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; + pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; + pdsch_pdu_rel15->dlDmrsSymbPos = dlDmrsSymbPos; + LOG_D(MAC,"dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos); + + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + pdcch_pdu_rel15->numDlDci++; + dci_pdu->RNTI = SI_RNTI; + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + dci_pdu->AggregationLevel = gNB_mac->sched_ctrlCommon->aggregation_level; + dci_pdu->CceIndex = gNB_mac->sched_ctrlCommon->cce_index; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + + /* DCI payload */ + dci_pdu_rel15_t dci_payload; + memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t)); + + dci_payload.bwp_indicator.val = 0; + + // frequency domain assignment + dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0( + pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, type0_PDCCH_CSS_config->num_rbs); + + dci_payload.time_domain_assignment.val = gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation; + dci_payload.mcs = gNB_mac->sched_ctrlCommon->sched_pdsch.mcs; + dci_payload.rv = pdsch_pdu_rel15->rvIndex[0]; + dci_payload.harq_pid = 0; + dci_payload.ndi = 0; + dci_payload.dai[0].val = 0; + dci_payload.tpc = 0; // table 7.2.1-1 in 38.213 + dci_payload.pucch_resource_indicator = 0; + dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0; + dci_payload.antenna_ports.val = 0; + dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; + + int dci_format = NR_DL_DCI_FORMAT_1_0; + int rnti_type = NR_RNTI_SI; + + fill_dci_pdu_rel15(scc, + NULL, + &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1], + &dci_payload, + dci_format, + rnti_type, + pdsch_pdu_rel15->BWPSize, + 0); + + LOG_D(MAC,"BWPSize: %i\n", pdcch_pdu_rel15->BWPSize); + LOG_D(MAC,"BWPStart: %i\n", pdcch_pdu_rel15->BWPStart); + LOG_D(MAC,"SubcarrierSpacing: %i\n", pdcch_pdu_rel15->SubcarrierSpacing); + LOG_D(MAC,"CyclicPrefix: %i\n", pdcch_pdu_rel15->CyclicPrefix); + LOG_D(MAC,"StartSymbolIndex: %i\n", pdcch_pdu_rel15->StartSymbolIndex); + LOG_D(MAC,"DurationSymbols: %i\n", pdcch_pdu_rel15->DurationSymbols); + for(int n=0;n<6;n++) LOG_D(MAC,"FreqDomainResource[%i]: %x\n",n, pdcch_pdu_rel15->FreqDomainResource[n]); + LOG_D(MAC,"CceRegMappingType: %i\n", pdcch_pdu_rel15->CceRegMappingType); + LOG_D(MAC,"RegBundleSize: %i\n", pdcch_pdu_rel15->RegBundleSize); + LOG_D(MAC,"InterleaverSize: %i\n", pdcch_pdu_rel15->InterleaverSize); + LOG_D(MAC,"CoreSetType: %i\n", pdcch_pdu_rel15->CoreSetType); + LOG_D(MAC,"ShiftIndex: %i\n", pdcch_pdu_rel15->ShiftIndex); + LOG_D(MAC,"precoderGranularity: %i\n", pdcch_pdu_rel15->precoderGranularity); + LOG_D(MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); + +} + +void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { + + // TODO: Get these values from RRC + const int CC_id = 0; + uint8_t candidate_idx = 0; + + gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; + NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; + + int time_domain_allocation = gNB_mac->sib1_tda; + + int L_max; + switch (scc->ssb_PositionsInBurst->present) { + case 1: + L_max = 4; + break; + case 2: + L_max = 8; + break; + case 3: + L_max = 64; + break; + default: + AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n", + scc->ssb_PositionsInBurst->present); + } + + for (int i=0; itype0_PDCCH_CSS_config[i]; + + if((frameP%2 == type0_PDCCH_CSS_config->sfn_c) && + (slotP == type0_PDCCH_CSS_config->n_0) && + (type0_PDCCH_CSS_config->num_rbs > 0) && + (type0_PDCCH_CSS_config->active == true)) { + + LOG_D(NR_MAC,"(%d.%d) SIB1 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index); + + // Get SIB1 + uint8_t sib1_payload[NR_MAX_SIB_LENGTH/8]; + uint8_t sib1_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, BCCH, SI_RNTI, 1, sib1_payload); + LOG_D(NR_MAC,"sib1_sdu_length = %i\n", sib1_sdu_length); + LOG_D(NR_MAC,"SIB1: \n"); + for (int k=0;ktype0_pdcch_ss_mux_pattern, + time_domain_allocation, + gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, + 1, &startSymbolIndex, &nrOfSymbols); + + // TODO: There are exceptions to this in table 5.1.2.1.1-4,5 (Default time domain allocation tables B, C) + int mappingtype = (startSymbolIndex <= 3)? typeA: typeB; + + uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, nrOfSymbols, startSymbolIndex, mappingtype); + + // Configure sched_ctrlCommon for SIB1 + uint32_t TBS = schedule_control_sib1(module_idP, CC_id, + type0_PDCCH_CSS_config, + time_domain_allocation, + startSymbolIndex, + nrOfSymbols, + dlDmrsSymbPos, + candidate_idx, sib1_sdu_length); + + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nr_fill_nfapi_dl_sib1_pdu(module_idP, dl_req, type0_PDCCH_CSS_config, TBS, startSymbolIndex, nrOfSymbols, dlDmrsSymbPos); + + const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; + + // Data to be transmitted + bzero(tx_req->TLVs[0].value.direct,MAX_NR_DLSCH_PAYLOAD_BYTES); + memcpy(tx_req->TLVs[0].value.direct, sib1_payload, sib1_sdu_length); + + tx_req->PDU_length = TBS; + tx_req->PDU_index = gNB_mac->pdu_index[0]++; + tx_req->num_TLV = 1; + tx_req->TLVs[0].length = TBS + 2; + gNB_mac->TX_req[CC_id].Number_of_PDUs++; + gNB_mac->TX_req[CC_id].SFN = frameP; + gNB_mac->TX_req[CC_id].Slot = slotP; + + type0_PDCCH_CSS_config->active = false; + } + } +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index cf2323f571..f9209f4cfe 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -29,21 +29,22 @@ */ -/*PHY*/ -#include "PHY/CODING/coding_defs.h" -#include "PHY/defs_nr_common.h" -#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "common/utils/nr/nr_common.h" /*MAC*/ #include "NR_MAC_COMMON/nr_mac.h" #include "NR_MAC_gNB/nr_mac_gNB.h" #include "NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac.h" +#include "LAYER2/NR_MAC_gNB/mac_proto.h" /*NFAPI*/ #include "nfapi_nr_interface.h" /*TAG*/ #include "NR_TAG-Id.h" +/*Softmodem params*/ +#include "executables/softmodem-common.h" +#include "../../../nfapi/oai_integration/vendor_ext.h" + //////////////////////////////////////////////////////// /////* DLSCH MAC PDU generation (6.1.2 TS 38.321) *///// //////////////////////////////////////////////////////// @@ -52,31 +53,104 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) -int nr_generate_dlsch_pdu(module_id_t module_idP, - unsigned char *sdus_payload, +void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp) +{ + gNB_MAC_INST *nrmac = RC.nrmac[module_id]; + const int bwp_id = bwp ? bwp->bwp_Id : 0; + if (nrmac->preferred_dl_tda[bwp_id]) + return; + + /* there is a mixed slot only when in TDD */ + NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon; + const NR_TDD_UL_DL_Pattern_t *tdd = + scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + const int symb_dlMixed = tdd ? (1 << tdd->nrofDownlinkSymbols) - 1 : 0; + + int target_ss; + if (bwp) { + target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + } + else { + target_ss = NR_SearchSpace__searchSpaceType_PR_common; + } + NR_SearchSpace_t *search_space = get_searchspace(scc, bwp ? bwp->bwp_Dedicated : NULL, target_ss); + NR_ControlResourceSet_t *coreset = get_coreset(module_id, scc, bwp ? bwp->bwp_Dedicated : NULL, search_space, target_ss); + // get coreset symbol "map" + const uint16_t symb_coreset = (1 << coreset->duration) - 1; + + /* check that TDA index 0 fits into DL and does not overlap CORESET */ + const struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = bwp ? + bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList : + scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + AssertFatal(tdaList->list.count >= 1, "need to have at least one TDA for DL slots\n"); + const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_DL = tdaList->list.array[0]; + AssertFatal(!tdaP_DL->k0 || *tdaP_DL->k0 == 0, + "TimeDomainAllocation at index 1: non-null k0 (%ld) is not supported by the scheduler\n", + *tdaP_DL->k0); + int start, len; + SLIV2SL(tdaP_DL->startSymbolAndLength, &start, &len); + const uint16_t symb_tda = ((1 << len) - 1) << start; + // check whether coreset and TDA overlap: then we cannot use it. Note that + // here we assume that the coreset is scheduled every slot (which it + // currently is) and starting at symbol 0 + AssertFatal((symb_coreset & symb_tda) == 0, "TDA index 0 for DL overlaps with CORESET\n"); + + /* check that TDA index 1 fits into DL part of mixed slot, if it exists */ + int tdaMi = -1; + if (tdaList->list.count > 1) { + const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1]; + AssertFatal(!tdaP_Mi->k0 || *tdaP_Mi->k0 == 0, + "TimeDomainAllocation at index 1: non-null k0 (%ld) is not supported by the scheduler\n", + *tdaP_Mi->k0); + int start, len; + SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len); + const uint16_t symb_tda = ((1 << len) - 1) << start; + // check whether coreset and TDA overlap: then, we cannot use it. Also, + // check whether TDA is entirely within mixed slot DL. Note that + // here we assume that the coreset is scheduled every slot (which it + // currently is) + if ((symb_coreset & symb_tda) == 0 && (symb_dlMixed & symb_tda) == symb_tda) { + tdaMi = 1; + } else { + LOG_E(MAC, + "TDA index 1 DL overlaps with CORESET or is not entirely in mixed slot (symb_coreset %x symb_dlMixed %x symb_tda %x), won't schedule DL mixed slot\n", + symb_coreset, + symb_dlMixed, + symb_tda); + } + } + + const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; + const int n = slots_per_frame[*scc->ssbSubcarrierSpacing]; + nrmac->preferred_dl_tda[bwp_id] = malloc(n * sizeof(*nrmac->preferred_dl_tda[bwp_id])); + + const int nr_mix_slots = tdd ? tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0 : 0; + const int nr_slots_period = tdd ? tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots : n; + for (int i = 0; i < n; ++i) { + nrmac->preferred_dl_tda[bwp_id][i] = -1; + if (!tdd || i % nr_slots_period < tdd->nrofDownlinkSlots) + nrmac->preferred_dl_tda[bwp_id][i] = 0; + else if (tdd && nr_mix_slots && i % nr_slots_period == tdd->nrofDownlinkSlots) + nrmac->preferred_dl_tda[bwp_id][i] = tdaMi; + LOG_D(MAC, "slot %d preferred_dl_tda %d\n", i, nrmac->preferred_dl_tda[bwp_id][i]); + } +} + +// Compute and write all MAC CEs and subheaders, and return number of written +// bytes +int nr_write_ce_dlsch_pdu(module_id_t module_idP, + const NR_UE_sched_ctrl_t *ue_sched_ctl, unsigned char *mac_pdu, - unsigned char num_sdus, - unsigned short *sdu_lengths, - unsigned char *sdu_lcids, unsigned char drx_cmd, - unsigned char *ue_cont_res_id, - unsigned short post_padding) { + unsigned char *ue_cont_res_id) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) mac_pdu; - unsigned char *dlsch_buffer_ptr = sdus_payload; uint8_t last_size = 0; int offset = 0, mac_ce_size, i, timing_advance_cmd, tag_id = 0; // MAC CEs uint8_t mac_header_control_elements[16], *ce_ptr; ce_ptr = &mac_header_control_elements[0]; - uint16_t UE_id = 0; //TODO need to get as a function parameter or need to invoke api to UE_id using module Id and RNTI - gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; - NR_UE_list_t *UE_list = &gNB_mac->UE_list; - NR_UE_sched_ctrl_t *ue_sched_ctl = NULL; - //NR_CellGroupConfig_t *config = UE_list->secondaryCellGroup[UE_id]; - ue_sched_ctl = &(UE_list->UE_sched_ctrl[UE_id]); - - // 1) Compute MAC CE and related subheaders // DRX command subheader (MAC CE size 0) if (drx_cmd != 255) { @@ -91,13 +165,13 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, // now TA is always send when ta_timer resets regardless of its value // this is done to avoid issues with the timeAlignmentTimer which is // supposed to monitor if the UE received TA or not */ - if (gNB->ta_len) { + if (ue_sched_ctl->ta_apply) { mac_pdu_ptr->R = 0; mac_pdu_ptr->LCID = DL_SCH_LCID_TA_COMMAND; //last_size = 1; mac_pdu_ptr++; // TA MAC CE (1 octet) - timing_advance_cmd = gNB->ta_command; + timing_advance_cmd = ue_sched_ctl->ta_update; AssertFatal(timing_advance_cmd < 64, "timing_advance_cmd %d > 63\n", timing_advance_cmd); ((NR_MAC_CE_TA *) ce_ptr)->TA_COMMAND = timing_advance_cmd; //(timing_advance_cmd+31)&0x3f; @@ -106,12 +180,14 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, ((NR_MAC_CE_TA *) ce_ptr)->TAGID = tag_id; } - LOG_D(MAC, "NR MAC CE timing advance command = %d (%d) TAG ID = %d\n", timing_advance_cmd, ((NR_MAC_CE_TA *) ce_ptr)->TA_COMMAND, tag_id); + LOG_D(NR_MAC, "NR MAC CE timing advance command = %d (%d) TAG ID = %d\n", timing_advance_cmd, ((NR_MAC_CE_TA *) ce_ptr)->TA_COMMAND, tag_id); mac_ce_size = sizeof(NR_MAC_CE_TA); // Copying bytes for MAC CEs to the mac pdu pointer memcpy((void *) mac_pdu_ptr, (void *) ce_ptr, mac_ce_size); ce_ptr += mac_ce_size; mac_pdu_ptr += (unsigned char) mac_ce_size; + + } // Contention resolution fixed subheader and MAC CE @@ -123,7 +199,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, // contention resolution identity MAC ce has a fixed 48 bit size // this contains the UL CCCH SDU. If UL CCCH SDU is longer than 48 bits, // it contains the first 48 bits of the UL CCCH SDU - LOG_T(MAC, "[gNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n", + LOG_T(NR_MAC, "[gNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n", ue_cont_res_id[0], ue_cont_res_id[1], ue_cont_res_id[2], ue_cont_res_id[3], ue_cont_res_id[4], ue_cont_res_id[5]); // Copying bytes (6 octects) to CEs pointer @@ -148,7 +224,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, nr_UESpec_TCI_StateInd_PDCCH.ServingCellId = (ue_sched_ctl->UE_mac_ce_ctrl.pdcch_state_ind.servingCellId) & 0x1F; //extracting LSB 5 Bits nr_UESpec_TCI_StateInd_PDCCH.TciStateId = (ue_sched_ctl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId) & 0x7F; //extracting LSB 7 bits nr_UESpec_TCI_StateInd_PDCCH.CoresetId2 = (ue_sched_ctl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId) & 0x1; //extracting LSB 1 bit - LOG_D(MAC, "NR MAC CE TCI state indication for UE Specific PDCCH = %d \n", nr_UESpec_TCI_StateInd_PDCCH.TciStateId); + LOG_D(NR_MAC, "NR MAC CE TCI state indication for UE Specific PDCCH = %d \n", nr_UESpec_TCI_StateInd_PDCCH.TciStateId); mac_ce_size = sizeof(NR_TCI_PDCCH); // Copying bytes for MAC CEs to the mac pdu pointer memcpy((void *) mac_pdu_ptr, (void *)&nr_UESpec_TCI_StateInd_PDCCH, mac_ce_size); @@ -259,7 +335,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, ((NR_MAC_CE_SP_ZP_CSI_RS_RES_SET *) mac_pdu_ptr)->BWPID = ue_sched_ctl->UE_mac_ce_ctrl.sp_zp_csi_rs.bwpid & 0x3; //2 bits ((NR_MAC_CE_SP_ZP_CSI_RS_RES_SET *) mac_pdu_ptr)->CSIRS_RSC_ID = ue_sched_ctl->UE_mac_ce_ctrl.sp_zp_csi_rs.rsc_id & 0xF; //4 bits ((NR_MAC_CE_SP_ZP_CSI_RS_RES_SET *) mac_pdu_ptr)->R = 0; - LOG_D(MAC, "NR MAC CE of ZP CSIRS Serv cell ID = %d BWPID= %d Rsc set ID = %d\n", ue_sched_ctl->UE_mac_ce_ctrl.sp_zp_csi_rs.serv_cell_id, ue_sched_ctl->UE_mac_ce_ctrl.sp_zp_csi_rs.bwpid, + LOG_D(NR_MAC, "NR MAC CE of ZP CSIRS Serv cell ID = %d BWPID= %d Rsc set ID = %d\n", ue_sched_ctl->UE_mac_ce_ctrl.sp_zp_csi_rs.serv_cell_id, ue_sched_ctl->UE_mac_ce_ctrl.sp_zp_csi_rs.bwpid, ue_sched_ctl->UE_mac_ce_ctrl.sp_zp_csi_rs.rsc_id); mac_ce_size = sizeof(NR_MAC_CE_SP_ZP_CSI_RS_RES_SET); mac_pdu_ptr += (unsigned char) mac_ce_size; @@ -300,47 +376,977 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, } } - // 2) Generation of DLSCH MAC subPDUs including subheaders and MAC SDUs - for (i = 0; i < num_sdus; i++) { - LOG_D(MAC, "[gNB] Generate DLSCH header num sdu %d len sdu %d\n", num_sdus, sdu_lengths[i]); - - if (sdu_lengths[i] < 128) { - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = sdu_lcids[i]; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->L = (unsigned char) sdu_lengths[i]; - last_size = 2; - } else { - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->F = 1; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->LCID = sdu_lcids[i]; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0x7f; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L2 = (unsigned short) sdu_lengths[i] & 0xff; - last_size = 3; - } - - mac_pdu_ptr += last_size; - // 3) cycle through SDUs, compute each relevant and place dlsch_buffer in - memcpy((void *) mac_pdu_ptr, (void *) dlsch_buffer_ptr, sdu_lengths[i]); - dlsch_buffer_ptr += sdu_lengths[i]; - mac_pdu_ptr += sdu_lengths[i]; - } - - // 4) Compute final offset for padding - if (post_padding > 0) { - ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->LCID = DL_SCH_LCID_PADDING; - mac_pdu_ptr++; - } else { - // no MAC subPDU with padding - } - // compute final offset offset = ((unsigned char *) mac_pdu_ptr - mac_pdu); //printf("Offset %d \n", ((unsigned char *) mac_pdu_ptr - mac_pdu)); return offset; } -/* functionalities of this function have been moved to nr_schedule_uss_dlsch_phytest */ -void nr_schedule_ue_spec(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { +#define BLER_UPDATE_FRAME 10 +#define BLER_FILTER 0.9f +int get_mcs_from_bler(module_id_t mod_id, int CC_id, frame_t frame, sub_frame_t slot, int UE_id) +{ + gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; + const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; + const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + + NR_DL_bler_stats_t *bler_stats = &nrmac->UE_info.UE_sched_ctrl[UE_id].dl_bler_stats; + /* first call: everything is zero. Initialize to sensible default */ + if (bler_stats->last_frame_slot == 0 && bler_stats->mcs == 0) { + bler_stats->last_frame_slot = frame * n + slot; + bler_stats->mcs = 9; + bler_stats->bler = (nrmac->dl_bler_target_lower + nrmac->dl_bler_target_upper) / 2; + bler_stats->rd2_bler = nrmac->dl_rd2_bler_threshold; + } + const int now = frame * n + slot; + int diff = now - bler_stats->last_frame_slot; + if (diff < 0) // wrap around + diff += 1024 * n; + + const uint8_t old_mcs = bler_stats->mcs; + const NR_mac_stats_t *stats = &nrmac->UE_info.mac_stats[UE_id]; + // TODO put back this condition when relevant + /*const int dret3x = stats->dlsch_rounds[3] - bler_stats->dlsch_rounds[3]; + if (dret3x > 0) { + if there is a third retransmission, decrease MCS for stabilization and + restart averaging window to stabilize transmission + bler_stats->last_frame_slot = now; + bler_stats->mcs = max(9, bler_stats->mcs - 1); + memcpy(bler_stats->dlsch_rounds, stats->dlsch_rounds, sizeof(stats->dlsch_rounds)); + LOG_D(MAC, "%4d.%2d: %d retx in 3rd round, setting MCS to %d and restarting window\n", frame, slot, dret3x, bler_stats->mcs); + return bler_stats->mcs; + }*/ + if (diff < BLER_UPDATE_FRAME * n) + return old_mcs; // no update + + // last update is longer than x frames ago + const int dtx = (int)(stats->dlsch_rounds[0] - bler_stats->dlsch_rounds[0]); + const int dretx = (int)(stats->dlsch_rounds[1] - bler_stats->dlsch_rounds[1]); + const int dretx2 = (int)(stats->dlsch_rounds[2] - bler_stats->dlsch_rounds[2]); + const float bler_window = dtx > 0 ? (float) dretx / dtx : bler_stats->bler; + const float rd2_bler_wnd = dtx > 0 ? (float) dretx2 / dtx : bler_stats->rd2_bler; + bler_stats->bler = BLER_FILTER * bler_stats->bler + (1 - BLER_FILTER) * bler_window; + bler_stats->rd2_bler = BLER_FILTER / 4 * bler_stats->rd2_bler + (1 - BLER_FILTER / 4) * rd2_bler_wnd; + + int new_mcs = old_mcs; + // TODO put back this condition when relevant + /* first ensure that number of 2nd retx is below threshold. If this is the + * case, use 1st retx to adjust faster + if (bler_stats->rd2_bler > nrmac->dl_rd2_bler_threshold && old_mcs > 6) { + new_mcs -= 2; + } else if (bler_stats->rd2_bler < nrmac->dl_rd2_bler_threshold) {*/ + if (bler_stats->bler < nrmac->dl_bler_target_lower && old_mcs < nrmac->dl_max_mcs && dtx > 9) + new_mcs += 1; + else if (bler_stats->bler > nrmac->dl_bler_target_upper && old_mcs > 6) + new_mcs -= 1; + // else we are within threshold boundaries + + + bler_stats->last_frame_slot = now; + bler_stats->mcs = new_mcs; + memcpy(bler_stats->dlsch_rounds, stats->dlsch_rounds, sizeof(stats->dlsch_rounds)); + LOG_D(MAC, "%4d.%2d MCS %d -> %d (dtx %d, dretx %d, BLER wnd %.3f avg %.6f, dretx2 %d, RD2 BLER wnd %.3f avg %.6f)\n", + frame, slot, old_mcs, new_mcs, dtx, dretx, bler_window, bler_stats->bler, dretx2, rd2_bler_wnd, bler_stats->rd2_bler); + return new_mcs; +} + +void nr_store_dlsch_buffer(module_id_t module_id, + frame_t frame, + sub_frame_t slot) { + + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + sched_ctrl->num_total_bytes = 0; + + int lcid; + const uint16_t rnti = UE_info->rnti[UE_id]; + LOG_D(NR_MAC,"UE %d/%x : lcid_mask %x\n",UE_id,rnti,sched_ctrl->lcid_mask); + if ((sched_ctrl->lcid_mask&(1<<2)) > 0) + sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1] = mac_rlc_status_ind(module_id, + rnti, + module_id, + frame, + slot, + ENB_FLAG_YES, + MBMS_FLAG_NO, + DL_SCH_LCID_DCCH1, + 0, + 0); + if ((sched_ctrl->lcid_mask&(1<<1)) > 0) + sched_ctrl->rlc_status[DL_SCH_LCID_DCCH] = mac_rlc_status_ind(module_id, + rnti, + module_id, + frame, + slot, + ENB_FLAG_YES, + MBMS_FLAG_NO, + DL_SCH_LCID_DCCH, + 0, + 0); + if ((sched_ctrl->lcid_mask&(1<<4)) > 0) + sched_ctrl->rlc_status[DL_SCH_LCID_DTCH] = mac_rlc_status_ind(module_id, + rnti, + module_id, + frame, + slot, + ENB_FLAG_YES, + MBMS_FLAG_NO, + DL_SCH_LCID_DTCH, + 0, + 0); + + if(sched_ctrl->rlc_status[DL_SCH_LCID_DCCH].bytes_in_buffer > 0){ + lcid = DL_SCH_LCID_DCCH; + } + else if (sched_ctrl->rlc_status[DL_SCH_LCID_DCCH1].bytes_in_buffer > 0) + { + lcid = DL_SCH_LCID_DCCH1; + }else{ + lcid = DL_SCH_LCID_DTCH; + } + + sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; + //later multiplex here. Just select DCCH/SRB before DTCH/DRB + sched_ctrl->lcid_to_schedule = lcid; + + if (sched_ctrl->num_total_bytes == 0 + && !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */ + continue; + + LOG_D(NR_MAC, + "[%s][%d.%d], %s%d->DLSCH, RLC status %d bytes TA %d\n", + __func__, + frame, + slot, + lcid<4?"DCCH":"DTCH", + lcid, + sched_ctrl->rlc_status[lcid].bytes_in_buffer, + sched_ctrl->ta_apply); + } +} + +bool allocate_dl_retransmission(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + uint8_t *rballoc_mask, + int *n_rb_sched, + int UE_id, + int current_harq_pid) { + + const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels->ServingCellConfigCommon; + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_sched_pdsch_t *retInfo = &sched_ctrl->harq_processes[current_harq_pid].sched_pdsch; + NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id]; + NR_BWP_DownlinkDedicated_t *bwpd= cg ? cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP:NULL; + + + NR_BWP_t *genericParameters = sched_ctrl->active_bwp ? + &sched_ctrl->active_bwp->bwp_Common->genericParameters : + &RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + + const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + int rbStart = 0; // start wrt BWPstart + + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + const long f = (sched_ctrl->active_bwp ||bwpd) ? sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats : 0; + int rbSize = 0; + const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot]; + AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n"); + if (tda == retInfo->time_domain_allocation) { + /* Check that there are enough resources for retransmission */ + while (rbSize < retInfo->rbSize) { + rbStart += rbSize; /* last iteration rbSize was not enough, skip it */ + rbSize = 0; + while (rbStart < bwpSize && !rballoc_mask[rbStart]) + rbStart++; + if (rbStart >= bwpSize) { + LOG_D(NR_MAC, "cannot allocate retransmission for UE %d/RNTI %04x: no resources\n", UE_id, UE_info->rnti[UE_id]); + return false; + } + while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize] && rbSize < retInfo->rbSize) + rbSize++; + } + /* check whether we need to switch the TDA allocation since the last + * (re-)transmission */ + if (ps->time_domain_allocation != tda) + nr_set_pdsch_semi_static(scc, cg, sched_ctrl->active_bwp, bwpd, tda, f, ps); + } else { + /* the retransmission will use a different time domain allocation, check + * that we have enough resources */ + while (rbStart < bwpSize && !rballoc_mask[rbStart]) + rbStart++; + while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize]) + rbSize++; + NR_pdsch_semi_static_t temp_ps; + temp_ps.nrOfLayers = 1; + nr_set_pdsch_semi_static(scc, cg, sched_ctrl->active_bwp, bwpd, tda, f, &temp_ps); + uint32_t new_tbs; + uint16_t new_rbSize; + bool success = nr_find_nb_rb(retInfo->Qm, + retInfo->R, + temp_ps.nrOfSymbols, + temp_ps.N_PRB_DMRS * temp_ps.N_DMRS_SLOT, + retInfo->tb_size, + rbSize, + &new_tbs, + &new_rbSize); + if (!success || new_tbs != retInfo->tb_size) { + LOG_D(MAC, "%s(): new TBsize %d of new TDA does not match old TBS %d\n", __func__, new_tbs, retInfo->tb_size); + return false; /* the maximum TBsize we might have is smaller than what we need */ + } + /* we can allocate it. Overwrite the time_domain_allocation, the number + * of RBs, and the new TB size. The rest is done below */ + retInfo->tb_size = new_tbs; + retInfo->rbSize = new_rbSize; + retInfo->time_domain_allocation = tda; + sched_ctrl->pdsch_semi_static = temp_ps; + } + + /* Find a free CCE */ + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(MAC, "%4d.%2d could not find CCE for DL DCI retransmission UE %d/RNTI %04x\n", + frame, slot, UE_id, UE_info->rnti[UE_id]); + return false; + } + + /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH + * allocation after CCE alloc fail would be more complex) */ + const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, -1, 0); + if (alloc<0) { + LOG_D(MAC, + "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", + __func__, + UE_id, + UE_info->rnti[UE_id], + frame, + slot); + int cid = sched_ctrl->coreset->controlResourceSetId; + UE_info->num_pdcch_cand[UE_id][cid]--; + int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp?sched_ctrl->active_bwp->bwp_Id:0][cid]; + for (int i = 0; i < sched_ctrl->aggregation_level; i++) + cce_list[sched_ctrl->cce_index + i] = 0; + return false; + } + + /* just reuse from previous scheduling opportunity, set new start RB */ + sched_ctrl->sched_pdsch = *retInfo; + sched_ctrl->sched_pdsch.rbStart = rbStart; + + sched_ctrl->sched_pdsch.pucch_allocation = alloc; + + /* retransmissions: directly allocate */ + *n_rb_sched -= sched_ctrl->sched_pdsch.rbSize; + for (int rb = 0; rb < sched_ctrl->sched_pdsch.rbSize; rb++) + rballoc_mask[rb + sched_ctrl->sched_pdsch.rbStart] = 0; + return true; +} + +float thr_ue[MAX_MOBILES_PER_GNB]; +uint32_t pf_tbs[3][29]; // pre-computed, approximate TBS values for PF coefficient + +void pf_dl(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + NR_list_t *UE_list, + int max_num_ue, + int n_rb_sched, + uint8_t *rballoc_mask) { + + gNB_MAC_INST *mac = RC.nrmac[module_id]; + NR_UE_info_t *UE_info = &mac->UE_info; + NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon; + float coeff_ue[MAX_MOBILES_PER_GNB]; + // UEs that could be scheduled + int ue_array[MAX_MOBILES_PER_GNB]; + NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB }; + + /* Loop UE_info->list to check retransmission */ + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + if (UE_info->Msg4_ACKed[UE_id] != true) continue; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue; + NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ + sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head; + + /* Calculate Throughput */ + const float a = 0.0005f; // corresponds to 200ms window + const uint32_t b = UE_info->mac_stats[UE_id].dlsch_current_bytes; + thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b; + + /* retransmission */ + if (sched_pdsch->dl_harq_pid >= 0) { + /* Allocate retransmission */ + bool r = allocate_dl_retransmission( + module_id, frame, slot, rballoc_mask, &n_rb_sched, UE_id, sched_pdsch->dl_harq_pid); + if (!r) { + LOG_D(NR_MAC, "%4d.%2d retransmission can NOT be allocated\n", frame, slot); + continue; + } + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) return; + } else { + /* Check DL buffer and skip this UE if no bytes and no TA necessary */ + if (sched_ctrl->num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 10) % 1024) + continue; + + /* Calculate coeff */ + ps->nrOfLayers = 1; + sched_pdsch->mcs = get_mcs_from_bler(module_id, /* CC_id = */ 0, frame, slot, UE_id); + uint32_t tbs = pf_tbs[ps->mcsTableIdx][sched_pdsch->mcs]; + coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id]; + LOG_D(NR_MAC,"b %d, thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n", + b, UE_id, thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]); + /* Create UE_sched list for UEs eligible for new transmission*/ + add_tail_nr_list(&UE_sched, UE_id); + } + } + + /* Loop UE_sched to find max coeff and allocate transmission */ + while (max_num_ue > 0 && n_rb_sched > 0 && UE_sched.head >= 0) { + + /* Find max coeff from UE_sched*/ + int *max = &UE_sched.head; /* assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* if the current one has larger coeff, save for later */ + if (coeff_ue[*p] > coeff_ue[*max]) + max = p; + p = &UE_sched.next[*p]; + } + /* remove the max one: do not use remove_nr_list() it goes through the + * whole list every time. Note that UE_sched.tail might not be set + * correctly anymore */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id]; + NR_BWP_DownlinkDedicated_t *bwpd= cg ? cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP:NULL; + + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + int bwp_Id = sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0; + const uint16_t rnti = UE_info->rnti[UE_id]; + NR_BWP_t *genericParameters = sched_ctrl->active_bwp ? + &sched_ctrl->active_bwp->bwp_Common->genericParameters: + &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + + const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth,MAX_BWP_SIZE); + int rbStart = 0; // start wrt BWPstart + + /* Find a free CCE */ + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(NR_MAC, "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", frame, slot, UE_id, rnti); + continue; + } + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) return; + + /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH + * allocation after CCE alloc fail would be more complex) */ + const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, -1, 0); + if (alloc<0) { + LOG_D(NR_MAC, + "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", + __func__, + UE_id, + rnti, + frame, + slot); + int cid = sched_ctrl->coreset->controlResourceSetId; + UE_info->num_pdcch_cand[UE_id][cid]--; + int *cce_list = mac->cce_list[bwp_Id][cid]; + for (int i = 0; i < sched_ctrl->aggregation_level; i++) + cce_list[sched_ctrl->cce_index + i] = 0; + return; + } + + // Freq-demain allocation + while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++; + + uint16_t max_rbSize = 1; + while (rbStart + max_rbSize < bwpSize && rballoc_mask[rbStart + max_rbSize]) + max_rbSize++; + + /* MCS has been set above */ + + const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0][slot]; + AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n"); + NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + const long f = (sched_ctrl->active_bwp || bwpd) ? sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats : 0; + if (ps->time_domain_allocation != tda) + nr_set_pdsch_semi_static(scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, bwpd, tda, f, ps); + sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); + sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); + sched_pdsch->pucch_allocation = alloc; + uint32_t TBS = 0; + uint16_t rbSize; + const int oh = 3 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024); + nr_find_nb_rb(sched_pdsch->Qm, + sched_pdsch->R, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->N_DMRS_SLOT, + sched_ctrl->num_total_bytes + oh, + max_rbSize, + &TBS, + &rbSize); + sched_pdsch->rbSize = rbSize; + sched_pdsch->rbStart = rbStart; + sched_pdsch->tb_size = TBS; + + /* transmissions: directly allocate */ + n_rb_sched -= sched_pdsch->rbSize; + for (int rb = 0; rb < sched_pdsch->rbSize; rb++) + rballoc_mask[rb + sched_pdsch->rbStart] = 0; + } +} + +void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) +{ + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + if (UE_info->num_UEs == 0) + return; + + NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon; + const int CC_id = 0; + + /* Get bwpSize from the first UE */ + int UE_id = UE_info->list.head; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp ? + sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth: + scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + const uint16_t BWPStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp ? + sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth: + scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + + uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; + uint8_t rballoc_mask[bwpSize]; + int n_rb_sched = 0; + for (int i = 0; i < bwpSize; i++) { + // calculate mask: init with "NOT" vrb_map: + // if any RB in vrb_map is blocked (1), the current RBG will be 0 + rballoc_mask[i] = !vrb_map[i+BWPStart]; + n_rb_sched += rballoc_mask[i]; + } + + /* Retrieve amount of data to send for this UE */ + nr_store_dlsch_buffer(module_id, frame, slot); + + /* proportional fair scheduling algorithm */ + pf_dl(module_id, + frame, + slot, + &UE_info->list, + 2, + n_rb_sched, + rballoc_mask); +} + +nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(module_id_t module_id, int CC_id) +{ + /* in the PF algorithm, we have to use the TBsize to compute the coefficient. + * This would include the number of DMRS symbols, which in turn depends on + * the time domain allocation. In case we are in a mixed slot, we do not want + * to recalculate all these values just, and therefore we provide a look-up + * table which should approximately give us the TBsize */ + for (int mcsTableIdx = 0; mcsTableIdx < 3; ++mcsTableIdx) { + for (int mcs = 0; mcs < 29; ++mcs) { + if (mcs > 27 && mcsTableIdx == 1) + continue; + const uint8_t Qm = nr_get_Qm_dl(mcs, mcsTableIdx); + const uint16_t R = nr_get_code_rate_dl(mcs, mcsTableIdx); + pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm, + R, + 1, /* rbSize */ + 10, /* hypothetical number of slots */ + 0, /* N_PRB_DMRS * N_DMRS_SLOT */ + 0 /* N_PRB_oh, 0 for initialBWP */, + 0 /* tb_scaling */, + 1 /* nrOfLayers */) + >> 3; + } + } + + return nr_fr1_dlsch_preprocessor; +} + +void nr_schedule_ue_spec(module_id_t module_id, + frame_t frame, + sub_frame_t slot) { + gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; + if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) + return; + + /* PREPROCESSOR */ + gNB_mac->pre_processor_dl(module_id, frame, slot); + + const int CC_id = 0; + NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; + NR_UE_info_t *UE_info = &gNB_mac->UE_info; + + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + + NR_list_t *UE_list = &UE_info->list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue; + NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; + UE_info->mac_stats[UE_id].dlsch_current_bytes = 0; + NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id]; + NR_BWP_DownlinkDedicated_t *bwpd= cg ? cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP:NULL; + + /* update TA and set ta_apply every 10 frames. + * Possible improvement: take the periodicity from input file. + * If such UE is not scheduled now, it will be by the preprocessor later. + * If we add the CE, ta_apply will be reset */ + if (frame == (sched_ctrl->ta_frame + 10) % 1024){ + sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */ + LOG_D(NR_MAC, "[UE %d][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE_id, frame, slot); + } + + if (sched_pdsch->rbSize <= 0) + continue; + + const rnti_t rnti = UE_info->rnti[UE_id]; + + /* pre-computed PDSCH values that only change if time domain + * allocation/DMRS parameters change. Updated in the preprocessor through + * nr_set_pdsch_semi_static() */ + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + + /* POST processing */ + const uint8_t nrOfLayers = ps->nrOfLayers; + const uint16_t R = sched_pdsch->R; + const uint8_t Qm = sched_pdsch->Qm; + const uint32_t TBS = sched_pdsch->tb_size; + + int8_t current_harq_pid = sched_pdsch->dl_harq_pid; + if (current_harq_pid < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + current_harq_pid = sched_ctrl->available_dl_harq.head; + AssertFatal(current_harq_pid >= 0, + "no free HARQ process available for UE %d\n", + UE_id); + remove_front_nr_list(&sched_ctrl->available_dl_harq); + sched_pdsch->dl_harq_pid = current_harq_pid; + } else { + /* PP selected a specific HARQ process. Check whether it will be a new + * transmission or a retransmission, and remove from the corresponding + * list */ + if (sched_ctrl->harq_processes[current_harq_pid].round == 0) + remove_nr_list(&sched_ctrl->available_dl_harq, current_harq_pid); + else + remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); + } + NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; + DevAssert(!harq->is_waiting); + add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); + NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[sched_pdsch->pucch_allocation]; + harq->feedback_frame = pucch->frame; + harq->feedback_slot = pucch->ul_slot; + harq->is_waiting = true; + UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++; + + LOG_D(NR_MAC, + "%4d.%2d [DLSCH/PDSCH/PUCCH] UE %d RNTI %04x DCI L %d start %3d RBs %3d startSymbol %2d nb_symbol %2d dmrspos %x MCS %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d dl_data_to_ULACK %d (%d.%d) PUCCH allocation %d TPC %d\n", + frame, + slot, + UE_id, + rnti, + sched_ctrl->aggregation_level, + sched_pdsch->rbStart, + sched_pdsch->rbSize, + ps->startSymbolIndex, + ps->nrOfSymbols, + ps->dl_dmrs_symb_pos, + sched_pdsch->mcs, + TBS, + current_harq_pid, + harq->round, + nr_rv_round_map[harq->round], + harq->ndi, + pucch->timing_indicator, + pucch->frame, + pucch->ul_slot, + sched_pdsch->pucch_allocation, + sched_ctrl->tpc1); + + NR_BWP_Downlink_t *bwp = sched_ctrl->active_bwp; + + /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not + * exist, create it */ + + // BWP + NR_BWP_t *genericParameters = bwp ? &bwp->bwp_Common->genericParameters : &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + + const int bwpid = bwp ? bwp->bwp_Id : 0; + const int coresetid = (bwp||bwpd) ? sched_ctrl->coreset->controlResourceSetId : gNB_mac->sched_ctrlCommon->coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; + if (!pdcch_pdu) { + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + dl_req->nPDUs += 1; + pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + LOG_D(NR_MAC,"Trying to configure DL pdcch for UE %d, bwp %d, cs %d\n",UE_id,bwpid,coresetid); + NR_SearchSpace_t *ss = (bwp||bwpd) ? sched_ctrl->search_space:gNB_mac->sched_ctrlCommon->search_space; + NR_ControlResourceSet_t *coreset = (bwp||bwpd)? sched_ctrl->coreset:gNB_mac->sched_ctrlCommon->coreset; + nr_configure_pdcch(gNB_mac, pdcch_pdu, ss, coreset, scc, genericParameters, NULL); + gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu; + } + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset(dl_tti_pdsch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; + dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + dl_req->nPDUs += 1; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + + pdsch_pdu->pduBitmap = 0; + pdsch_pdu->rnti = rnti; + /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control + * message. This is used to associate control information to data and is + * reset every slot. */ + const int pduindex = gNB_mac->pdu_index[CC_id]++; + pdsch_pdu->pduIndex = pduindex; + + pdsch_pdu->BWPSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + pdsch_pdu->BWPStart = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth,MAX_BWP_SIZE); + pdsch_pdu->SubcarrierSpacing = genericParameters->subcarrierSpacing; + + pdsch_pdu->CyclicPrefix = genericParameters->cyclicPrefix ? *genericParameters->cyclicPrefix : 0; + + // Codeword information + pdsch_pdu->NrOfCodewords = 1; + pdsch_pdu->targetCodeRate[0] = R; + pdsch_pdu->qamModOrder[0] = Qm; + pdsch_pdu->mcsIndex[0] = sched_pdsch->mcs; + pdsch_pdu->mcsTable[0] = ps->mcsTableIdx; + AssertFatal(harq!=NULL,"harq is null\n"); + AssertFatal(harq->round<4,"%d",harq->round); + pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round]; + pdsch_pdu->TBSize[0] = TBS; + + pdsch_pdu->dataScramblingId = *scc->physCellId; + pdsch_pdu->nrOfLayers = nrOfLayers; + pdsch_pdu->transmissionScheme = 0; + pdsch_pdu->refPoint = 0; // Point A + + // DMRS + pdsch_pdu->dlDmrsSymbPos = ps->dl_dmrs_symb_pos; + pdsch_pdu->dmrsConfigType = ps->dmrsConfigType; + pdsch_pdu->dlDmrsScramblingId = *scc->physCellId; + pdsch_pdu->SCID = 0; + pdsch_pdu->numDmrsCdmGrpsNoData = ps->numDmrsCdmGrpsNoData; + pdsch_pdu->dmrsPorts = (1<resourceAlloc = 1; + pdsch_pdu->rbStart = sched_pdsch->rbStart; + pdsch_pdu->rbSize = sched_pdsch->rbSize; + pdsch_pdu->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP + + // Resource Allocation in time domain + pdsch_pdu->StartSymbolIndex = ps->startSymbolIndex; + pdsch_pdu->NrOfSymbols = ps->nrOfSymbols; + + NR_PDSCH_Config_t *pdsch_Config=NULL; + if (bwp && + bwp->bwp_Dedicated && + bwp->bwp_Dedicated->pdsch_Config && + bwp->bwp_Dedicated->pdsch_Config->choice.setup) + pdsch_Config = bwp->bwp_Dedicated->pdsch_Config->choice.setup; + + /* Check and validate PTRS values */ + struct NR_SetupRelease_PTRS_DownlinkConfig *phaseTrackingRS = + pdsch_Config ? pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS : NULL; + if (phaseTrackingRS) { + bool valid_ptrs_setup = set_dl_ptrs_values(phaseTrackingRS->choice.setup, + pdsch_pdu->rbSize, + pdsch_pdu->mcsIndex[0], + pdsch_pdu->mcsTable[0], + &pdsch_pdu->PTRSFreqDensity, + &pdsch_pdu->PTRSTimeDensity, + &pdsch_pdu->PTRSPortIndex, + &pdsch_pdu->nEpreRatioOfPDSCHToPTRS, + &pdsch_pdu->PTRSReOffset, + pdsch_pdu->NrOfSymbols); + if (valid_ptrs_setup) + pdsch_pdu->pduBitmap |= 0x1; // Bit 0: pdschPtrs - Indicates PTRS included (FR2) + } + + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci]; + pdcch_pdu->numDlDci++; + dci_pdu->RNTI = rnti; + if (sched_ctrl->coreset && + sched_ctrl->search_space && + sched_ctrl->coreset->pdcch_DMRS_ScramblingID && + sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { + dci_pdu->ScramblingId = *sched_ctrl->coreset->pdcch_DMRS_ScramblingID; + dci_pdu->ScramblingRNTI = rnti; + } else { + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + } + dci_pdu->AggregationLevel = sched_ctrl->aggregation_level; + dci_pdu->CceIndex = sched_ctrl->cce_index; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + + /* DCI payload */ + dci_pdu_rel15_t dci_payload; + memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t)); + // bwp indicator + const int n_dl_bwp = bwp ? UE_info->CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count : 0; + AssertFatal(n_dl_bwp <= 1, "downlinkBWP_ToAddModList has %d BWP!\n", n_dl_bwp); + + // as per table 7.3.1.1.2-1 in 38.212 + dci_payload.bwp_indicator.val = bwp ? (n_dl_bwp < 4 ? bwp->bwp_Id : bwp->bwp_Id - 1) : 0; + if (bwp) AssertFatal(bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, + "Only frequency resource allocation type 1 is currently supported\n"); + dci_payload.frequency_domain_assignment.val = + PRBalloc_to_locationandbandwidth0( + pdsch_pdu->rbSize, + pdsch_pdu->rbStart, + pdsch_pdu->BWPSize); + dci_payload.format_indicator = 1; + dci_payload.time_domain_assignment.val = ps->time_domain_allocation; + dci_payload.mcs = sched_pdsch->mcs; + dci_payload.rv = pdsch_pdu->rvIndex[0]; + dci_payload.harq_pid = current_harq_pid; + dci_payload.ndi = harq->ndi; + dci_payload.dai[0].val = (pucch->dai_c-1)&3; + dci_payload.tpc = sched_ctrl->tpc1; // TPC for PUCCH: table 7.2.1-1 in 38.213 + dci_payload.pucch_resource_indicator = pucch->resource_indicator; + dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch->timing_indicator; // PDSCH to HARQ TI + dci_payload.antenna_ports.val = ps->dmrs_ports_id; + dci_payload.dmrs_sequence_initialization.val = pdsch_pdu->SCID; + LOG_D(NR_MAC, + "%4d.%2d DCI type 1 payload: freq_alloc %d (%d,%d,%d), " + "time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d tpc %d ti %d\n", + frame, + slot, + dci_payload.frequency_domain_assignment.val, + pdsch_pdu->rbStart, + pdsch_pdu->rbSize, + pdsch_pdu->BWPSize, + dci_payload.time_domain_assignment.val, + dci_payload.vrb_to_prb_mapping.val, + dci_payload.mcs, + dci_payload.tb_scaling, + dci_payload.ndi, + dci_payload.rv, + dci_payload.tpc, + pucch->timing_indicator); + + const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; + int dci_format; + if (sched_ctrl->search_space) { + dci_format = f ? NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0; + } + else { + dci_format = NR_DL_DCI_FORMAT_1_0; + } + const int rnti_type = NR_RNTI_C; + + fill_dci_pdu_rel15(scc, + UE_info->CellGroup[UE_id], + dci_pdu, + &dci_payload, + dci_format, + rnti_type, + pdsch_pdu->BWPSize, + bwp? bwp->bwp_Id : 0); + + LOG_D(NR_MAC, + "coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", + (unsigned long long)pdcch_pdu->FreqDomainResource, + pdcch_pdu->StartSymbolIndex, + pdcch_pdu->DurationSymbols); + + if (harq->round != 0) { /* retransmission */ + /* we do not have to do anything, since we do not require to get data + * from RLC or encode MAC CEs. The TX_req structure is filled below + * or copy data to FAPI structures */ + LOG_D(NR_MAC, + "%d.%2d DL retransmission UE %d/RNTI %04x HARQ PID %d round %d NDI %d\n", + frame, + slot, + UE_id, + rnti, + current_harq_pid, + harq->round, + harq->ndi); + + AssertFatal(harq->sched_pdsch.tb_size == TBS, + "UE %d mismatch between scheduled TBS and buffered TB for HARQ PID %d\n", + UE_id, + current_harq_pid); + + T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), + T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->tb, TBS)); + } else { /* initial transmission */ + + LOG_D(NR_MAC, "[%s] Initial HARQ transmission in %d.%d\n", __FUNCTION__, frame, slot); + + uint8_t *buf = (uint8_t *) harq->tb; + + /* first, write all CEs that might be there */ + int written = nr_write_ce_dlsch_pdu(module_id, + sched_ctrl, + (unsigned char *)buf, + 255, // no drx + NULL); // contention res id + buf += written; + int size = TBS - written; + DevAssert(size >= 0); + + /* next, get RLC data */ + + // const int lcid = DL_SCH_LCID_DTCH; + const int lcid = sched_ctrl->lcid_to_schedule; + int dlsch_total_bytes = 0; + if (sched_ctrl->num_total_bytes > 0) { + tbs_size_t len = 0; + while (size > 3) { + // we do not know how much data we will get from RLC, i.e., whether it + // will be longer than 256B or not. Therefore, reserve space for long header, then + // fetch data, then fill real length + NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; + buf += 3; + size -= 3; + + /* limit requested number of bytes to what preprocessor specified, or + * such that TBS is full */ + const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, size); + len = mac_rlc_data_req(module_id, + rnti, + module_id, + frame, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + ndata, + (char *)buf, + 0, + 0); + + LOG_D(NR_MAC, + "%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %d)\n", + frame, + slot, + rnti, + len, + lcid < 4 ? "DCCH" : "DTCH", + lcid, + ndata, + size); + if (len == 0) + break; + + header->R = 0; + header->F = 1; + header->LCID = lcid; + header->L1 = (len >> 8) & 0xff; + header->L2 = len & 0xff; + size -= len; + buf += len; + dlsch_total_bytes += len; + } + if (len == 0) { + /* RLC did not have data anymore, mark buffer as unused */ + buf -= 3; + size += 3; + } + } + else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra || get_softmodem_params()->sa) { + /* we will need the large header, phy-test typically allocates all + * resources and fills to the last byte below */ + NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; + buf += 3; + size -= 3; + DevAssert(size > 0); + LOG_D(NR_MAC, "Configuring DL_TX in %d.%d: TBS %d with %d B of random data\n", frame, slot, TBS, size); + // fill dlsch_buffer with random data + for (int i = 0; i < size; i++) + buf[i] = lrand48() & 0xff; + header->R = 0; + header->F = 1; + header->LCID = DL_SCH_LCID_PADDING; + header->L1 = (size >> 8) & 0xff; + header->L2 = size & 0xff; + size -= size; + buf += size; + dlsch_total_bytes += size; + } + + // Add padding header and zero rest out if there is space left + if (size > 0) { + NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) buf; + padding->R = 0; + padding->LCID = DL_SCH_LCID_PADDING; + size -= 1; + buf += 1; + while (size > 0) { + *buf = 0; + buf += 1; + size -= 1; + } + } + + UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS; + UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS; + UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes; + + /* save retransmission information */ + harq->sched_pdsch = *sched_pdsch; + /* save which time allocation has been used, to be used on + * retransmissions */ + harq->sched_pdsch.time_domain_allocation = ps->time_domain_allocation; + + // ta command is sent, values are reset + if (sched_ctrl->ta_apply) { + sched_ctrl->ta_apply = false; + sched_ctrl->ta_frame = frame; + LOG_D(NR_MAC, + "%d.%2d UE %d TA scheduled, resetting TA frame\n", + frame, + slot, + UE_id); + } + + T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), + T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->tb, TBS)); + } + + const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; + tx_req->PDU_length = TBS; + tx_req->PDU_index = pduindex; + tx_req->num_TLV = 1; + tx_req->TLVs[0].length = TBS + 2; + memcpy(tx_req->TLVs[0].value.direct, harq->tb, TBS); + gNB_mac->TX_req[CC_id].Number_of_PDUs++; + gNB_mac->TX_req[CC_id].SFN = frame; + gNB_mac->TX_req[CC_id].Slot = slot; + + /* mark UE as scheduled */ + sched_pdsch->rbSize = 0; + } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 9f5d4f5ec7..c0107c5fc6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -29,11 +29,8 @@ */ #include "nr_mac_gNB.h" -#include "SCHED_NR/sched_nr.h" #include "NR_MAC_gNB/mac_proto.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" -#include "PHY/NR_TRANSPORT/nr_dlsch.h" -#include "PHY/NR_TRANSPORT/nr_dci.h" #include "executables/nr-softmodem.h" #include "LAYER2/NR_MAC_COMMON/nr_mac.h" #include "executables/softmodem-common.h" @@ -53,7 +50,10 @@ #include "NR_SearchSpace.h" #include "NR_ControlResourceSet.h" +//#define UL_HARQ_PRINT extern RAN_CONTEXT_t RC; + +const uint8_t nr_rv_round_map[4] = {0, 2, 3, 1}; //#define ENABLE_MAC_PAYLOAD_DEBUG 1 //uint8_t mac_pdu[MAX_NR_DLSCH_PAYLOAD_BYTES]; @@ -77,7 +77,7 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, NR_ServingCellConfigCommon_t *scc=cc->ServingCellConfigCommon; - int dlBWP_carrier_bandwidth = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275); + int dlBWP_carrier_bandwidth = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); /* @@ -91,7 +91,7 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, for (CC_id=0; CC_iddownlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275)); + NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE)); dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; @@ -100,7 +100,7 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1]; + dl_tti_pdsch_pdu = &nr_mac->DL_req[CC_id].dl_tti_request_body.dl_tti_pdu_list[nr_mac->DL_req[CC_id].dl_tti_request_body.nPDUs+1]; memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); @@ -114,8 +114,8 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, pdsch_pdu_rel15->pduIndex = 0; // BWP - pdsch_pdu_rel15->BWPSize = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275); + pdsch_pdu_rel15->BWPSize = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); pdsch_pdu_rel15->SubcarrierSpacing = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing; pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; @@ -143,15 +143,18 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, int startSymbolAndLength=0; int StartSymbolIndex=-1,NrOfSymbols=14; int StartSymbolIndex_tmp,NrOfSymbols_tmp; + int mappingtype_tmp, mappingtype=0; for (int i=0; idownlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; i++) { startSymbolAndLength = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength; SLIV2SL(startSymbolAndLength,&StartSymbolIndex_tmp,&NrOfSymbols_tmp); + mappingtype_tmp = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType; if (NrOfSymbols_tmp < NrOfSymbols) { NrOfSymbols = NrOfSymbols_tmp; StartSymbolIndex = StartSymbolIndex_tmp; + mappingtype = mappingtype_tmp; // k0 = *scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0; // time_domain_assignment = i; } @@ -160,8 +163,10 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, - scc->dmrs_TypeA_Position, - NrOfSymbols); + scc->dmrs_TypeA_Position, + NrOfSymbols, + StartSymbolIndex, + mappingtype); /* AssertFatal(k0==0,"k0 is not zero for Initial DL BWP TimeDomain Alloc\n"); @@ -235,827 +240,310 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, pdsch_pdu_rel15->mcsIndex[0]); */ - dl_req->nPDUs+=2; + nr_mac->DL_req[CC_id].dl_tti_request_body.nPDUs+=2; TX_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; TX_req->PDU_length = 6; TX_req->PDU_index = nr_mac->pdu_index[CC_id]++; TX_req->num_TLV = 1; TX_req->TLVs[0].length = 8; - memcpy((void*)&TX_req->TLVs[0].value.direct[0],(void*)&cc[CC_id].RAR_pdu.payload[0],TX_req->TLVs[0].length); + // why do we copy from RAR_pdu here? Shouldn't we fill some more or less + // meaningful data, e.g., padding + random data? + //memcpy((void *)&TX_req->TLVs[0].value.direct[0], (void *)&cc[CC_id].RAR_pdu[0].payload[0], TX_req->TLVs[0].length); nr_mac->TX_req[CC_id].Number_of_PDUs++; nr_mac->TX_req[CC_id].SFN=frameP; nr_mac->TX_req[CC_id].Slot=slotP; } } - -int configure_fapi_dl_pdu(int Mod_idP, - nfapi_nr_dl_tti_request_body_t *dl_req, - NR_sched_pucch *pucch_sched, - uint8_t *mcsIndex, - uint16_t *rbSize, - uint16_t *rbStart) { - - - - gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP]; - NR_COMMON_channels_t *cc = nr_mac->common_channels; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu; - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu; - - int TBS; - int bwp_id=1; - int UE_id = 0; - - NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; - - NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id]; - AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); - NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; - memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - - dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1]; - memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; - dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); - - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; - - - pdsch_pdu_rel15->pduBitmap = 0; - pdsch_pdu_rel15->rnti = UE_list->rnti[UE_id]; - pdsch_pdu_rel15->pduIndex = 0; - - // BWP - pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; - if (bwp->bwp_Common->genericParameters.cyclicPrefix) pdsch_pdu_rel15->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix; - else pdsch_pdu_rel15->CyclicPrefix=0; - - pdsch_pdu_rel15->NrOfCodewords = 1; - int mcs = (mcsIndex!=NULL) ? *mcsIndex : 9; - int current_harq_pid = UE_list->UE_sched_ctrl[UE_id].current_harq_pid; - pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcs,0); - pdsch_pdu_rel15->qamModOrder[0] = 2; - pdsch_pdu_rel15->mcsIndex[0] = mcs; - pdsch_pdu_rel15->mcsTable[0] = 0; - pdsch_pdu_rel15->rvIndex[0] = (get_softmodem_params()->phy_test==1) ? 0 : UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round; - pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; - pdsch_pdu_rel15->nrOfLayers = 1; - pdsch_pdu_rel15->transmissionScheme = 0; - pdsch_pdu_rel15->refPoint = 0; // Point A - - pdsch_pdu_rel15->dmrsConfigType = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; - pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; - pdsch_pdu_rel15->SCID = 0; - pdsch_pdu_rel15->numDmrsCdmGrpsNoData = 1; - pdsch_pdu_rel15->dmrsPorts = 1; - pdsch_pdu_rel15->resourceAlloc = 1; - pdsch_pdu_rel15->rbStart = (rbStart!=NULL) ? *rbStart : 0; - pdsch_pdu_rel15->rbSize = (rbSize!=NULL) ? *rbSize : pdsch_pdu_rel15->BWPSize; - pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP - - int startSymbolAndLength=0; - int time_domain_assignment=2; - int StartSymbolIndex,NrOfSymbols; - - AssertFatal(time_domain_assignmentbwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count,"time_domain_assignment %d>=%d\n",time_domain_assignment,bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count); - startSymbolAndLength = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; - SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols); - pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; - pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; - - // k0 = *bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0; - pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup, - scc->dmrs_TypeA_Position, - pdsch_pdu_rel15->NrOfSymbols); - - dci_pdu_rel15_t *dci_pdu_rel15 = calloc(MAX_DCI_CORESET,sizeof(dci_pdu_rel15_t)); - - // bwp indicator - int n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; - if (n_dl_bwp < 4) - dci_pdu_rel15[0].bwp_indicator.val = bwp_id; - else - dci_pdu_rel15[0].bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 - // frequency domain assignment - if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation==NR_PDSCH_Config__resourceAllocation_resourceAllocationType1) - dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, - pdsch_pdu_rel15->rbStart, - NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275)); - else - AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); - // time domain assignment - dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; // row index used here instead of SLIV; - // mcs and rv - dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0]; - dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0]; - // harq pid and ndi - dci_pdu_rel15[0].harq_pid = current_harq_pid; - dci_pdu_rel15[0].ndi = UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].ndi; - // DAI - dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3; - - // TPC for PUCCH - dci_pdu_rel15[0].tpc = 1; // table 7.2.1-1 in 38.213 - // PUCCH resource indicator - dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator; - // PDSCH to HARQ TI - dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = pucch_sched->timing_indicator; - UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].feedback_slot = pucch_sched->ul_slot; - UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].is_waiting = 1; - // antenna ports - dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 - // dmrs sequence initialization - dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; - LOG_D(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n", - dci_pdu_rel15[0].frequency_domain_assignment.val, - pdsch_pdu_rel15->rbStart, - pdsch_pdu_rel15->rbSize, - NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), - dci_pdu_rel15[0].time_domain_assignment.val, - dci_pdu_rel15[0].vrb_to_prb_mapping.val, - dci_pdu_rel15[0].mcs, - dci_pdu_rel15[0].tb_scaling, - dci_pdu_rel15[0].ndi, - dci_pdu_rel15[0].rv); - - NR_SearchSpace_t *ss; - int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - int found=0; - - for (int i=0;ibwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) { - ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; - AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n"); - AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n"); - if (ss->searchSpaceType->present == target_ss) { - found=1; +extern int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda); +extern uint8_t getN_PRB_DMRS(NR_BWP_Downlink_t *bwp, int numDmrsCdmGrpsNoData); +uint32_t target_dl_mcs = 9; +uint32_t target_dl_Nl = 1; +uint32_t target_dl_bw = 50; +uint64_t dlsch_slot_bitmap = (1<<1); +/* schedules whole bandwidth for first user, all the time */ +void nr_preprocessor_phytest(module_id_t module_id, + frame_t frame, + sub_frame_t slot) +{ + if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot)) + return; + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon; + const int UE_id = 0; + const int CC_id = 0; + AssertFatal(UE_info->active[UE_id], + "%s(): expected UE %d to be active\n", + __func__, + UE_id); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + /* find largest unallocated chunk */ + const int bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + const int BWPStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int rbStart = 0; + int rbSize = 0; + if (target_dl_bw>bwpSize) + target_dl_bw = bwpSize; + uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; + /* loop ensures that we allocate exactly target_dl_bw, or return */ + while (true) { + /* advance to first free RB */ + while (rbStart < bwpSize && vrb_map[rbStart + BWPStart]) + rbStart++; + rbSize = 1; + /* iterate until we are at target_dl_bw or no available RBs */ + while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize + BWPStart] && rbSize < target_dl_bw) + rbSize++; + /* found target_dl_bw? */ + if (rbSize == target_dl_bw) break; + /* at end and below target_dl_bw? */ + if (rbStart + rbSize >= bwpSize) + return; + rbStart += rbSize; + } + + sched_ctrl->num_total_bytes = 0; + const int lcid = DL_SCH_LCID_DTCH; + const uint16_t rnti = UE_info->rnti[UE_id]; + /* update sched_ctrl->num_total_bytes so that postprocessor schedules data, + * if available */ + sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id, + rnti, + module_id, + frame, + slot, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + 0, + 0); + sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; + sched_ctrl->lcid_to_schedule = lcid; + + uint8_t nr_of_candidates; + for (int i=0; i<5; i++) { + // for now taking the lowest value among the available aggregation levels + find_aggregation_candidates(&sched_ctrl->aggregation_level, + &nr_of_candidates, + sched_ctrl->search_space, + 1<0) break; + } + AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n"); + + const int cid = sched_ctrl->coreset->controlResourceSetId; + const uint16_t Y = UE_info->Y[UE_id][cid][slot]; + const int m = UE_info->num_pdcch_cand[UE_id][cid]; + sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], + sched_ctrl->active_bwp, + sched_ctrl->coreset, + sched_ctrl->aggregation_level, + Y, + m, + nr_of_candidates); + AssertFatal(sched_ctrl->cce_index >= 0, + "%s(): could not find CCE for UE %d\n", + __func__, + UE_id); + + const int alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot, -1, 0); + if (alloc < 0) { + LOG_D(MAC, + "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", + __func__, + UE_id, + rnti, + frame, + slot); + UE_info->num_pdcch_cand[UE_id][cid]--; + int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid]; + for (int i = 0; i < sched_ctrl->aggregation_level; i++) + cce_list[sched_ctrl->cce_index + i] = 0; + return; + } + + //AssertFatal(alloc, + // "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n", + // rnti, frame, slot); + + NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + sched_pdsch->pucch_allocation = alloc; + sched_pdsch->rbStart = rbStart; + sched_pdsch->rbSize = rbSize; + const int tda = sched_ctrl->active_bwp ? RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot] : 1; + const long f = sched_ctrl->active_bwp ? sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats : 0; + ps->nrOfLayers = target_dl_Nl; + if (ps->time_domain_allocation != tda) + nr_set_pdsch_semi_static( + scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, NULL, tda, f, ps); + + sched_pdsch->mcs = target_dl_mcs; + sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); + sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); + sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm, + sched_pdsch->R, + sched_pdsch->rbSize, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->N_DMRS_SLOT, + 0 /* N_PRB_oh, 0 for initialBWP */, + 0 /* tb_scaling */, + ps->nrOfLayers) + >> 3; + + /* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */ + sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head; + + /* mark the corresponding RBs as used */ + for (int rb = 0; rb < sched_pdsch->rbSize; rb++) + vrb_map[rb + sched_pdsch->rbStart + BWPStart] = 1; + + if ((frame&127) == 0) LOG_D(MAC,"phytest: %d.%d DL mcs %d, DL rbStart %d, DL rbSize %d\n", frame, slot, sched_pdsch->mcs, rbStart,rbSize); +} + +uint32_t target_ul_mcs = 9; +uint32_t target_ul_bw = 50; +uint64_t ulsch_slot_bitmap = (1 << 8); +bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot) +{ + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + NR_COMMON_channels_t *cc = nr_mac->common_channels; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + NR_UE_info_t *UE_info = &nr_mac->UE_info; + + AssertFatal(UE_info->num_UEs <= 1, + "%s() cannot handle more than one UE, but found %d\n", + __func__, + UE_info->num_UEs); + if (UE_info->num_UEs == 0) + return false; + + const int UE_id = 0; + const int CC_id = 0; + + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + const int tda = sched_ctrl->active_ubwp ? RC.nrmac[module_id]->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 1; + if (tda < 0) + return false; + const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = + sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + AssertFatal(tda < tdaList->list.count, + "time domain assignment %d >= %d\n", + tda, + tdaList->list.count); + int K2 = get_K2(scc,sched_ctrl->active_ubwp, tda, mu); + const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]); + const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; + /* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE + * limitations). Note that if K2 or the TDD configuration is changed, below + * conditions might exclude each other and never be true */ + if (!is_xlsch_in_slot(ulsch_slot_bitmap, sched_slot)) + return false; + + const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; + const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0; + const uint8_t num_dmrs_cdm_grps_no_data = 1; + /* we want to avoid a lengthy deduction of DMRS and other parameters in + * every TTI if we can save it, so check whether dci_format, TDA, or + * num_dmrs_cdm_grps_no_data has changed and only then recompute */ + NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static; + if (ps->time_domain_allocation != tda + || ps->dci_format != dci_format + || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data) + nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, NULL,dci_format, tda, num_dmrs_cdm_grps_no_data, ps); + + uint16_t rbStart = 0; + uint16_t rbSize; + + const int bw = NRRIV2BW(sched_ctrl->active_ubwp ? + sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth : + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + const int BWPStart = NRRIV2PRBOFFSET(sched_ctrl->active_ubwp ? + sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth : + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + if (target_ul_bw>bw) + rbSize = bw; + else + rbSize = target_ul_bw; + + uint16_t *vrb_map_UL = + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; + const uint16_t symb = ((1 << ps->nrOfSymbols) - 1) << ps->startSymbolIndex; + for (int i = rbStart; i < rbStart + rbSize; ++i) { + if ((vrb_map_UL[i+BWPStart] & symb) != 0) { + LOG_E(MAC, + "%s(): %4d.%2d RB %d is already reserved, cannot schedule UE\n", + __func__, + frame, + slot, + i); + return false; } } - AssertFatal(found==1,"Couldn't find an adequate searchspace\n"); - int ret = nr_configure_pdcch(nr_mac, - pdcch_pdu_rel15, - UE_list->rnti[UE_id], - 1, // ue-specific - ss, - scc, - bwp); - if (ret < 0) { - LOG_I(MAC,"CCE list not empty, couldn't schedule PDSCH\n"); - free(dci_pdu_rel15); - return (0); + sched_ctrl->sched_pusch.slot = sched_slot; + sched_ctrl->sched_pusch.frame = sched_frame; + + uint8_t nr_of_candidates; + for (int i=0; i<5; i++) { + // for now taking the lowest value among the available aggregation levels + find_aggregation_candidates(&sched_ctrl->aggregation_level, + &nr_of_candidates, + sched_ctrl->search_space, + 1<0) break; } + AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n"); - int dci_formats[2]; - int rnti_types[2]; - - if (ss->searchSpaceType->choice.ue_Specific->dci_Formats) - dci_formats[0] = NR_DL_DCI_FORMAT_1_1; - else - dci_formats[0] = NR_DL_DCI_FORMAT_1_0; - - rnti_types[0] = NR_RNTI_C; - - fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id); - - LOG_D(MAC, "DCI params: rnti %x, rnti_type %d, dci_format %d\n \ - coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", - pdcch_pdu_rel15->dci_pdu.RNTI[0], - rnti_types[0], - dci_formats[0], - (unsigned long long)pdcch_pdu_rel15->FreqDomainResource, - pdcch_pdu_rel15->StartSymbolIndex, - pdcch_pdu_rel15->DurationSymbols); - - int x_Overhead = 0; // should be 0 for initialBWP - nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu,x_Overhead,pdsch_pdu_rel15->numDmrsCdmGrpsNoData,0); - - // Hardcode it for now - TBS = dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]; - LOG_D(MAC, "DLSCH PDU: start PRB %d n_PRB %d startSymbolAndLength %d start symbol %d nb_symbols %d nb_layers %d nb_codewords %d mcs %d TBS: %d\n", - pdsch_pdu_rel15->rbStart, - pdsch_pdu_rel15->rbSize, - startSymbolAndLength, - pdsch_pdu_rel15->StartSymbolIndex, - pdsch_pdu_rel15->NrOfSymbols, - pdsch_pdu_rel15->nrOfLayers, - pdsch_pdu_rel15->NrOfCodewords, - pdsch_pdu_rel15->mcsIndex[0], - TBS); - - free(dci_pdu_rel15); - return TBS; //Return TBS in bytes -} - -void config_uldci(NR_BWP_Uplink_t *ubwp, - nfapi_nr_pusch_pdu_t *pusch_pdu, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, - dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, int *rnti_types, - int time_domain_assignment, - int n_ubwp, int bwp_id) { - - switch(dci_formats[(pdcch_pdu_rel15->numDlDci)-1]) { - case NR_UL_DCI_FORMAT_0_0: - dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, - pusch_pdu->rb_start, - NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); - - dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; - dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; - dci_pdu_rel15->mcs = 9; - - dci_pdu_rel15->format_indicator = 0; - dci_pdu_rel15->ndi = 1; - dci_pdu_rel15->rv = 0; - dci_pdu_rel15->harq_pid = 0; - dci_pdu_rel15->tpc = 2; - break; - case NR_UL_DCI_FORMAT_0_1: - dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; - dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; - dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; - dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; - dci_pdu_rel15->dai[0].val = 0; //TODO - // bwp indicator - if (n_ubwp < 4) - dci_pdu_rel15->bwp_indicator.val = bwp_id; - else - dci_pdu_rel15->bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 - // frequency domain assignment - if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) - dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, - pusch_pdu->rb_start, - NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); - else - AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); - // time domain assignment - dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; - // mcs - dci_pdu_rel15->mcs = pusch_pdu->mcs_index; - // tpc command for pusch - dci_pdu_rel15->tpc = 2; //TODO - // SRS resource indicator - if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig != NULL) { - if (*ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook) - dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS - else - AssertFatal(1==0,"Non Codebook configuration non supported\n"); - } - // Antenna Ports - dci_pdu_rel15->antenna_ports.val = 0; // TODO for now it is hardcoded, it should depends on cdm group no data and rank - // DMRS sequence initialization - dci_pdu_rel15->dmrs_sequence_initialization.val = pusch_pdu->scid; - break; - default : - AssertFatal(1==0,"Valid UL formats are 0_0 and 0_1 \n"); + const int cid = sched_ctrl->coreset->controlResourceSetId; + const uint16_t Y = UE_info->Y[UE_id][cid][slot]; + const int m = UE_info->num_pdcch_cand[UE_id][cid]; + sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], + sched_ctrl->active_bwp, + sched_ctrl->coreset, + sched_ctrl->aggregation_level, + Y, + m, + nr_of_candidates); + if (sched_ctrl->cce_index < 0) { + LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__); + return false; } + UE_info->num_pdcch_cand[UE_id][cid]++; - LOG_D(MAC, "[gNB scheduler phytest] ULDCI type 0 payload: PDCCH CCEIndex %d, freq_alloc %d, time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n", - pdcch_pdu_rel15->dci_pdu.CceIndex[pdcch_pdu_rel15->numDlDci], - dci_pdu_rel15->frequency_domain_assignment.val, - dci_pdu_rel15->time_domain_assignment.val, - dci_pdu_rel15->frequency_hopping_flag.val, - dci_pdu_rel15->mcs, - dci_pdu_rel15->tpc, - dci_pdu_rel15->ndi, - dci_pdu_rel15->rv); + const int mcs = target_ul_mcs; + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + sched_pusch->mcs = mcs; + sched_pusch->rbStart = rbStart; + sched_pusch->rbSize = rbSize; + /* get the PID of a HARQ process awaiting retransmission, or -1 for "any new" */ + sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head; -} - - -void configure_fapi_dl_Tx(module_id_t Mod_idP, - frame_t frameP, - sub_frame_t slotP, - nfapi_nr_dl_tti_request_body_t *dl_req, - nfapi_nr_pdu_t *tx_req, - int tbs_bytes, - int16_t pdu_index){ - - int CC_id = 0; - - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; - gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP]; - - LOG_D(MAC, "DLSCH PDU: start PRB %d n_PRB %d start symbol %d nb_symbols %d nb_layers %d nb_codewords %d mcs %d TBS (bytes): %d\n", - pdsch_pdu_rel15->rbStart, - pdsch_pdu_rel15->rbSize, - pdsch_pdu_rel15->StartSymbolIndex, - pdsch_pdu_rel15->NrOfSymbols, - pdsch_pdu_rel15->nrOfLayers, - pdsch_pdu_rel15->NrOfCodewords, - pdsch_pdu_rel15->mcsIndex[0], - tbs_bytes); - - dl_req->nPDUs+=2; - - tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0]; - tx_req->PDU_index = nr_mac->pdu_index[0]++; - tx_req->num_TLV = 1; - tx_req->TLVs[0].length = tbs_bytes +2; - - memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&nr_mac->UE_list.DLSCH_pdu[0][0].payload[0], tbs_bytes); - - nr_mac->TX_req[CC_id].Number_of_PDUs++; - nr_mac->TX_req[CC_id].SFN = frameP; - nr_mac->TX_req[CC_id].Slot = slotP; -} - -void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, - frame_t frameP, - sub_frame_t slotP, - NR_sched_pucch *pucch_sched, - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *dlsch_config){ - - LOG_D(MAC, "In nr_schedule_uss_dlsch_phytest frame %d slot %d\n",frameP,slotP); - - int post_padding = 0, ta_len = 0, header_length_total = 0, sdu_length_total = 0, num_sdus = 0; - int lcid, offset, i, header_length_last, TBS_bytes; - int UE_id = 0, CC_id = 0; - - gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; - //NR_COMMON_channels_t *cc = nr_mac->common_channels; - //NR_ServingCellConfigCommon_t *scc=cc->ServingCellConfigCommon; - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; - nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[gNB_mac->TX_req[CC_id].Number_of_PDUs]; - - mac_rlc_status_resp_t rlc_status; - - NR_UE_list_t *UE_list = &gNB_mac->UE_list; - - if (UE_list->num_UEs ==0) return; - - unsigned char sdu_lcids[NB_RB_MAX] = {0}; - uint16_t sdu_lengths[NB_RB_MAX] = {0}; - uint16_t rnti = UE_list->rnti[UE_id]; - - uint8_t mac_sdus[MAX_NR_DLSCH_PAYLOAD_BYTES]; - - LOG_D(MAC, "Scheduling UE specific search space DCI type 1\n"); - - ta_len = gNB_mac->ta_len; - - TBS_bytes = configure_fapi_dl_pdu(module_idP, - dl_req, - pucch_sched, - dlsch_config!=NULL ? dlsch_config->mcsIndex : NULL, - dlsch_config!=NULL ? &dlsch_config->rbSize : NULL, - dlsch_config!=NULL ? &dlsch_config->rbStart : NULL); - - if (TBS_bytes == 0) - return; - - //The --NOS1 use case currently schedules DLSCH transmissions only when there is IP traffic arriving - //through the LTE stack - if (IS_SOFTMODEM_NOS1){ - - for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { - - // TODO: check if the lcid is active - - LOG_D(MAC, "[gNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (TBS %d bytes, len %d)\n", - module_idP, frameP, lcid, TBS_bytes, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3); - - if (TBS_bytes - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - slotP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, + /* Calculate TBS from MCS */ + sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table); + sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table); + if (ps->pusch_Config->tp_pi2BPSK + && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) { + sched_pusch->R >>= 1; + sched_pusch->Qm <<= 1; + } + sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, + sched_pusch->R, + sched_pusch->rbSize, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->num_dmrs_symb, + 0, // nb_rb_oh 0, - 0); - - if (rlc_status.bytes_in_buffer > 0) { - - LOG_D(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d), TBS_bytes: %d \n \n", - module_idP, frameP, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, - lcid, header_length_total, TBS_bytes); - - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, - (char *)&mac_sdus[sdu_length_total], - 0, - 0); - - LOG_D(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", module_idP, sdu_lengths[num_sdus], lcid); - - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - - num_sdus++; - - //ue_sched_ctl->uplane_inactivity_timer = 0; - } - } else { // no TBS_bytes left - break; - } - } - - } //if (IS_SOFTMODEM_NOS1) - else { - - //When the --NOS1 option is not enabled, DLSCH transmissions with random data - //occur every time that the current function is called (dlsch phytest mode) - - LOG_D(MAC,"Configuring DL_TX in %d.%d\n", frameP, slotP); - - // fill dlsch_buffer with random data - for (i = 0; i < TBS_bytes; i++){ - mac_sdus[i] = (unsigned char) (lrand48()&0xff); - //((uint8_t *)gNB_mac->UE_list.DLSCH_pdu[0][0].payload[0])[i] = (unsigned char) (lrand48()&0xff); - } - //Sending SDUs with size 1 - //Initialize elements of sdu_lcids and sdu_lengths - sdu_lcids[0] = 0x3f; // DRB - sdu_lengths[0] = TBS_bytes - ta_len - 3; - header_length_total += 2 + (sdu_lengths[0] >= 128); - sdu_length_total += sdu_lengths[0]; - num_sdus +=1; - - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - if (frameP%100 == 0){ - LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n", frameP, slotP, TBS_bytes); - for(int i = 0; i < 10; i++) { - LOG_I(MAC, "%x. ", ((uint8_t *)gNB_mac->UE_list.DLSCH_pdu[CC_id][0][0].payload[0])[i]); - } - } - #endif - - } // else IS_SOFTMODEM_NOS1 - - // there is at least one SDU or TA command - // if (num_sdus > 0 ){ - if (ta_len + sdu_length_total + header_length_total > 0) { - - // Check if there is data from RLC or CE - if (TBS_bytes >= 2 + header_length_total + sdu_length_total + ta_len) { - // we have to consider padding - // padding param currently not in use - //padding = TBS_bytes - header_length_total - sdu_length_total - ta_len - 1; - post_padding = 1; - } else { - //padding = 0; - post_padding = 0; - } - - offset = nr_generate_dlsch_pdu(module_idP, - (unsigned char *) mac_sdus, - (unsigned char *) gNB_mac->UE_list.DLSCH_pdu[0][0].payload[0], - num_sdus, //num_sdus - sdu_lengths, - sdu_lcids, - 255, // no drx - NULL, // contention res id - post_padding); - - // Padding: fill remainder of DLSCH with 0 - if (post_padding > 0){ - for (int j = 0; j < (TBS_bytes - offset); j++) - gNB_mac->UE_list.DLSCH_pdu[0][0].payload[0][offset + j] = 0; // mac_pdu[offset + j] = 0; - } - - configure_fapi_dl_Tx(module_idP, frameP, slotP, dl_req, tx_req, TBS_bytes, gNB_mac->pdu_index[CC_id]); - - if(IS_SOFTMODEM_NOS1){ - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n \n", frameP, slotP, TBS_bytes); - for(int i = 0; i < 10; i++) { // TBS_bytes dlsch_pdu_rel15->transport_block_size/8 6784/8 - LOG_I(MAC, "%x. ", mac_payload[i]); - } - #endif - } else { - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - if (frameP%100 == 0){ - LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n", frameP, slotP, TBS_bytes); - for(int i = 0; i < 10; i++) { - LOG_I(MAC, "%x. ", ((uint8_t *)gNB_mac->UE_list.DLSCH_pdu[CC_id][0][0].payload[0])[i]); //LOG_I(MAC, "%x. ", mac_payload[i]); - } - } - #endif - } - } - else { // There is no data from RLC or MAC header, so don't schedule - } + 1 /* NrOfLayers */) + >> 3; + /* mark the corresponding RBs as used */ + for (int rb = rbStart; rb < rbStart + rbSize; rb++) + vrb_map_UL[rb+BWPStart] = 1; + return true; } - - -void nr_schedule_uss_ulsch_phytest(int Mod_idP, - frame_t frameP, - sub_frame_t slotP) { - - gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP]; - NR_COMMON_channels_t *cc = nr_mac->common_channels; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - - int bwp_id=1; - int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; - int UE_id = 0; - NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; - AssertFatal(UE_list->active[UE_id] >=0,"Cannot find UE_id %d is not active\n",UE_id); - - NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id]; - AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; - int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; - NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; - NR_PUSCH_Config_t *pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; - nfapi_nr_ul_dci_request_t *UL_dci_req = &RC.nrmac[Mod_idP]->UL_dci_req[0]; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - uint16_t rnti = UE_list->rnti[UE_id]; - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu; - - UL_tti_req->SFN = frameP; - UL_tti_req->Slot = slotP; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - nfapi_nr_pusch_pdu_t *pusch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pusch_pdu; - memset(pusch_pdu,0,sizeof(nfapi_nr_pusch_pdu_t)); - UL_tti_req->n_pdus+=1; - - LOG_D(MAC, "Scheduling UE specific PUSCH\n"); - //UL_tti_req = &nr_mac->UL_tti_req[CC_id]; - - //Resource Allocation in time domain - int startSymbolAndLength=0; - int time_domain_assignment=1; - int StartSymbolIndex,NrOfSymbols,K2,mapping_type; - - AssertFatal(time_domain_assignmentbwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count, - "time_domain_assignment %d>=%d\n",time_domain_assignment,ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count); - startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; - SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols); - pusch_pdu->start_symbol_index = StartSymbolIndex; - pusch_pdu->nr_of_symbols = NrOfSymbols; - - mapping_type = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; - if (ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2 != NULL) - K2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2; - else { - if (mu<2) K2=1; - else if(mu==2) K2=2; - else K2=3; - } - - pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = rnti; - pusch_pdu->handle = 0; //not yet used - - pusch_pdu->bwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pusch_pdu->bwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pusch_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing; - pusch_pdu->cyclic_prefix = 0; - //pusch information always include - //this informantion seems to be redundant. with hthe mcs_index and the modulation table, the mod_order and target_code_rate can be determined. - pusch_pdu->mcs_index = 9; - pusch_pdu->mcs_table = 0; //0: notqam256 [TS38.214, table 5.1.3.1-1] - corresponds to nr_target_code_rate_table1 in PHY - pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; - pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; - if (pusch_Config->transformPrecoder == NULL) { - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - pusch_pdu->transform_precoding = 1; - else - pusch_pdu->transform_precoding = 0; - } - else - pusch_pdu->transform_precoding = *pusch_Config->transformPrecoder; - if (pusch_Config->dataScramblingIdentityPUSCH != NULL) - pusch_pdu->data_scrambling_id = *pusch_Config->dataScramblingIdentityPUSCH; - else - pusch_pdu->data_scrambling_id = *scc->physCellId; - - pusch_pdu->nrOfLayers = 1; - - //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] - if (pusch_Config->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) { - pusch_pdu->resource_alloc = 1; //type 1 - pusch_pdu->rb_start = 0; - pusch_pdu->rb_size = 50; - } - else - AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); - - pusch_pdu->vrb_to_prb_mapping = 0; - - if (pusch_Config->frequencyHopping==NULL) - pusch_pdu->frequency_hopping = 0; - else - pusch_pdu->frequency_hopping = 1; - - //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] - //pusch_pdu->uplink_frequency_shift_7p5khz = 0; - - - // -------------------- - // ------- DMRS ------- - // -------------------- - NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; - if (mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA) - NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; - else - NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - if (NR_DMRS_UplinkConfig->dmrs_Type == NULL) - pusch_pdu->dmrs_config_type = 0; - else - pusch_pdu->dmrs_config_type = 1; - pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] - if (pusch_pdu->transform_precoding) { // transform precoding disabled - long *scramblingid; - if (pusch_pdu->scid == 0) - scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; - else - scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; - if (scramblingid == NULL) - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - else - pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; - } - else { - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - if (NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) - pusch_pdu->pusch_identity = *NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; - else - pusch_pdu->pusch_identity = *scc->physCellId; - } - pusch_dmrs_AdditionalPosition_t additional_pos; - if (NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL) - additional_pos = 2; - else { - if (*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3) - additional_pos = 3; - else - additional_pos = *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition; - } - pusch_maxLength_t pusch_maxLength; - if (NR_DMRS_UplinkConfig->maxLength == NULL) - pusch_maxLength = 1; - else - pusch_maxLength = 2; - uint16_t l_prime_mask = get_l_prime(pusch_pdu->nr_of_symbols, mapping_type, additional_pos, pusch_maxLength); - pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_pdu->start_symbol_index; - - pusch_pdu->num_dmrs_cdm_grps_no_data = 1; - pusch_pdu->dmrs_ports = 1; - // -------------------------------------------------------------------------------------------------------------------------------------------- - - // -------------------- - // ------- PTRS ------- - // -------------------- - if (NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { - // TODO to be fixed from RRC config - uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig - pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); - pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); - pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - - pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS - } - else{ - pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - } - - // -------------------------------------------------------------------------------------------------------------------------------------------- - - //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] - //Optional Data only included if indicated in pduBitmap - // TODO from harq function as in pdsch - pusch_pdu->pusch_data.rv_index = 0; - pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 1; - - uint8_t num_dmrs_symb = 0; - - for(int dmrs_counter = pusch_pdu->start_symbol_index; dmrs_counter < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; dmrs_counter++) - num_dmrs_symb += ((pusch_pdu->ul_dmrs_symb_pos >> dmrs_counter) & 1); - - uint8_t N_PRB_DMRS; - if (pusch_pdu->dmrs_config_type == 0) { - N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*6; - } - else { - N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*4; - } - - pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, - pusch_pdu->target_code_rate, - pusch_pdu->rb_size, - pusch_pdu->nr_of_symbols, - N_PRB_DMRS * num_dmrs_symb, - 0, //nb_rb_oh - 0, - pusch_pdu->nrOfLayers)>>3; - - - pusch_pdu->pusch_data.num_cb = 0; //CBG not supported - //pusch_pdu->pusch_data.cb_present_and_position; - //pusch_pdu->pusch_uci; - //pusch_pdu->pusch_ptrs; - //pusch_pdu->dfts_ofdm; - //beamforming - //pusch_pdu->beamforming; //not used for now - - - ul_dci_request_pdu = &UL_dci_req->ul_dci_pdu_list[UL_dci_req->numPdus]; - memset((void*)ul_dci_request_pdu,0,sizeof(nfapi_nr_ul_dci_request_pdus_t)); - ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; - - int dci_formats[2]; - int rnti_types[2]; - - NR_SearchSpace_t *ss; - int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - int found=0; - - for (int i=0;ibwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) { - ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; - AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n"); - AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n"); - if (ss->searchSpaceType->present == target_ss) { - found=1; - break; - } - } - AssertFatal(found==1,"Couldn't find an adequate searchspace\n"); - - if (ss->searchSpaceType->choice.ue_Specific->dci_Formats) - dci_formats[0] = NR_UL_DCI_FORMAT_0_1; - else - dci_formats[0] = NR_UL_DCI_FORMAT_0_0; - - rnti_types[0] = NR_RNTI_C; - LOG_D(MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frameP,slotP); - - int ret = nr_configure_pdcch(nr_mac, - pdcch_pdu_rel15, - UE_list->rnti[UE_id], - 1, // ue-specific, - ss, - scc, - bwp); - - if (ret < 0) { - LOG_I(MAC,"CCE list not empty, couldn't schedule PUSCH\n"); - UL_tti_req->n_pdus-=1; - return; - } - else { - dci_pdu_rel15_t *dci_pdu_rel15 = calloc(MAX_DCI_CORESET,sizeof(dci_pdu_rel15_t)); - config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15,&dci_pdu_rel15[0],dci_formats,rnti_types,time_domain_assignment,n_ubwp,bwp_id); - fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); - free(dci_pdu_rel15); - } -} - diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index acb239ee39..7b7b5c771b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -30,9 +30,9 @@ */ +#include #include "assertions.h" -#include "LAYER2/MAC/mac.h" #include "NR_MAC_gNB/nr_mac_gNB.h" #include "NR_MAC_COMMON/nr_mac_extern.h" @@ -48,9 +48,6 @@ #include "RRC/NR/nr_rrc_extern.h" #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" -//#include "LAYER2/MAC/pre_processor.c" -#include "pdcp.h" - #include "intertask_interface.h" #include "T.h" @@ -63,7 +60,6 @@ #define ENABLE_MAC_PAYLOAD_DEBUG #define DEBUG_gNB_SCHEDULER 1 - #include "common/ran_context.h" extern RAN_CONTEXT_t RC; @@ -125,39 +121,109 @@ static inline uint8_t get_max_candidates(uint8_t scs) { static inline uint8_t get_max_cces(uint8_t scs) { AssertFatal(scs<4, "Invalid PDCCH subcarrier spacing %d\n", scs); return (nr_max_number_of_cces_per_slot[scs]); -} +} + +void set_dl_dmrs_ports(NR_pdsch_semi_static_t *ps) { + + //TODO first basic implementation of dmrs port selection + // only vaild for a single codeword + // for now it assumes a selection of Nl consecutive dmrs ports + // and a single front loaded symbol + // dmrs_ports_id is the index of Tables 7.3.1.2.2-1/2/3/4 + + switch (ps->nrOfLayers) { + case 1: + ps->dmrs_ports_id = 0; + ps->numDmrsCdmGrpsNoData = 1; + break; + case 2: + ps->dmrs_ports_id = 2; + ps->numDmrsCdmGrpsNoData = 1; + break; + case 3: + ps->dmrs_ports_id = 9; + ps->numDmrsCdmGrpsNoData = 2; + break; + case 4: + ps->dmrs_ports_id = 10; + ps->numDmrsCdmGrpsNoData = 2; + break; + default: + AssertFatal(1==0,"Number of layers %d\n not supported or not valid\n",ps->nrOfLayers); + } +} + +NR_ControlResourceSet_t *get_coreset(module_id_t module_idP, + NR_ServingCellConfigCommon_t *scc, + void *bwp, + NR_SearchSpace_t *ss, + NR_SearchSpace__searchSpaceType_PR ss_type) { + NR_ControlResourceSetId_t coreset_id = *ss->controlResourceSetId; + if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) { // common search space + NR_ControlResourceSet_t *coreset; + if(coreset_id == 0) { + coreset = RC.nrmac[module_idP]->sched_ctrlCommon->coreset; // this is coreset 0 + } else if (bwp) { + coreset = ((NR_BWP_Downlink_t*)bwp)->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet; + } else if (scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet) { + coreset = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet; + } else { + coreset = NULL; + } + + if (coreset) AssertFatal(coreset_id == coreset->controlResourceSetId, + "ID of common ss coreset does not correspond to id set in the " + "search space\n"); + return coreset; + } else { + const int n = ((NR_BWP_DownlinkDedicated_t*)bwp)->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.count; + for (int i = 0; i < n; i++) { + NR_ControlResourceSet_t *coreset = + ((NR_BWP_DownlinkDedicated_t*)bwp)->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[i]; + if (coreset_id == coreset->controlResourceSetId) { + return coreset; + } + } + AssertFatal(0, "Couldn't find coreset with id %ld\n", coreset_id); + } +} + +NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, + NR_BWP_DownlinkDedicated_t *bwp_Dedicated, + NR_SearchSpace__searchSpaceType_PR target_ss) { + + const int n = bwp_Dedicated ? + bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count: + scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.count; + for (int i=0;ipdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]: + scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list.array[i]; + AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); + AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n"); + if (ss->searchSpaceType->present == target_ss) { + return ss; + } + } + AssertFatal(0, "Couldn't find an adequate searchspace bwp_Dedicated %p\n",bwp_Dedicated); +} int allocate_nr_CCEs(gNB_MAC_INST *nr_mac, - int bwp_id, - int list_id, - int aggregation, - int search_space, // 0 common, 1 ue-specific - int UE_id, - int m) { - // uncomment these when we allocate for common search space - // NR_COMMON_channels_t *cc = nr_mac->common_channels; - // NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - - NR_UE_list_t *UE_list = &nr_mac->UE_list; - - NR_BWP_Downlink_t *bwp; - NR_CellGroupConfig_t *secondaryCellGroup; - - NR_ControlResourceSet_t *coreset; - - AssertFatal(UE_list->active[UE_id] >=0,"UE_id %d is not active\n",UE_id); - secondaryCellGroup = UE_list->secondaryCellGroup[UE_id]; - bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; - - if (search_space == 1) { - coreset = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[list_id]; - } - else { - coreset = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet; - } + NR_BWP_Downlink_t *bwp, + NR_ControlResourceSet_t *coreset, + int aggregation, + uint16_t Y, + int m, + int nr_of_candidates) { int coreset_id = coreset->controlResourceSetId; - int *cce_list = nr_mac->cce_list[bwp_id][coreset_id]; + + int *cce_list; + if(bwp == NULL) { + cce_list = nr_mac->cce_list[0][coreset_id]; + } else { + cce_list = nr_mac->cce_list[bwp->bwp_Id][coreset_id]; + } int n_rb=0; for (int i=0;i<6;i++) @@ -167,18 +233,18 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac, n_rb*=6; uint16_t N_reg = n_rb * coreset->duration; - uint16_t Y=0, N_cce, M_s_max, n_CI=0; - uint16_t n_RNTI = search_space == 1 ? UE_list->rnti[UE_id]:0; - uint32_t A[3]={39827,39829,39839}; + uint16_t n_CI = 0; - N_cce = N_reg / NR_NB_REG_PER_CCE; + const uint16_t N_cce = N_reg / NR_NB_REG_PER_CCE; + const uint16_t M_s_max = nr_of_candidates; - M_s_max = (aggregation==4)?4:(aggregation==8)?2:1; + LOG_D(PHY,"allocate_NR_CCes : bwp_id %d, coreset_id %d : N_cce %d, m %d, nr_of_candidates %d, Y %d\n", + (int)(bwp ? bwp->bwp_Id : 0),coreset_id,N_cce,m,nr_of_candidates, Y); + //PDCCH candidate index m in CORESET exceeds the maximum number of PDCCH candidates + if(m >= nr_of_candidates) + return -1; - if (search_space == 1) { - Y = (A[0]*n_RNTI)%65537; // Candidate 0, antenna port 0 - } - int first_cce = aggregation * (( Y + (m*N_cce)/(aggregation*M_s_max) + n_CI ) % CEILIDIV(N_cce,aggregation)); + int first_cce = aggregation * (( Y + CEILIDIV((m*N_cce),(aggregation*M_s_max)) + n_CI ) % CEILIDIV(N_cce,aggregation)); for (int i=0;i> 3; + /* check whether it does not fit, or whether it exactly fits. Some algorithms + * might depend on the return value! */ + if (bytes > *tbs) + return false; + if (bytes == *tbs) + return true; + + /* is the minimum enough? */ + *nb_rb = 5; + *tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, 1) >> 3; + if (bytes <= *tbs) + return true; + + /* perform binary search to allocate all bytes within a TBS up to nb_rb_max + * RBs */ + int hi = nb_rb_max; + int lo = 1; + for (int p = (hi + lo) / 2; lo + 1 < hi; p = (hi + lo) / 2) { + const uint32_t TBS = nr_compute_tbs(Qm, R, p, nb_symb_sch, nb_dmrs_prb, 0, 0, 1) >> 3; + if (bytes == TBS) { + hi = p; + break; + } else if (bytes < TBS) { + hi = p; + } else { + lo = p; + } + } + *nb_rb = hi; + *tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, 1) >> 3; + /* return whether we could allocate all bytes and stay below nb_rb_max */ + return *tbs >= bytes && *nb_rb <= nb_rb_max; +} + +void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc, + const NR_CellGroupConfig_t *secondaryCellGroup, + const NR_BWP_Downlink_t *bwp, + const NR_BWP_DownlinkDedicated_t *bwpd0, + int tda, + const long dci_format, + NR_pdsch_semi_static_t *ps) +{ + ps->time_domain_allocation = tda; + + const struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = bwp ? + bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList : + scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + AssertFatal(tda < tdaList->list.count, "time_domain_allocation %d>=%d\n", tda, tdaList->list.count); + const int mapping_type = tdaList->list.array[tda]->mappingType; + const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength, &ps->startSymbolIndex, &ps->nrOfSymbols); + NR_BWP_DownlinkDedicated_t *bwpd; + + if (bwp && bwp->bwp_Dedicated) { + bwpd = bwp->bwp_Dedicated; + } else { + bwpd = (NR_BWP_DownlinkDedicated_t*)bwpd0; + } + + ps->mcsTableIdx = 0; + if (bwpd->pdsch_Config && + bwpd->pdsch_Config->choice.setup && + bwpd->pdsch_Config->choice.setup->mcs_Table) { + if (*bwpd->pdsch_Config->choice.setup->mcs_Table == 0) + ps->mcsTableIdx = 1; + else + ps->mcsTableIdx = 2; + } + else ps->mcsTableIdx = 0; + + if(dci_format == 0) // format 1_0 + ps->numDmrsCdmGrpsNoData = (ps->nrOfSymbols == 2 ? 1 : 2); + else + set_dl_dmrs_ports(ps); + ps->dmrsConfigType = bwp!=NULL ? (bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1) : 0; + + ps->N_PRB_DMRS = ps->numDmrsCdmGrpsNoData * (ps->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); + ps->dl_dmrs_symb_pos = fill_dmrs_mask(bwpd ? bwpd->pdsch_Config->choice.setup : NULL, scc->dmrs_TypeA_Position, ps->nrOfSymbols, ps->startSymbolIndex, mapping_type); + ps->N_DMRS_SLOT = get_num_dmrs(ps->dl_dmrs_symb_pos); + LOG_D(NR_MAC,"bwpd0 %p, bwpd %p : Filling dmrs info, ps->N_PRB_DMRS %d, ps->dl_dmrs_symb_pos %x, ps->N_DMRS_SLOT %d\n",bwpd0,bwpd,ps->N_PRB_DMRS,ps->dl_dmrs_symb_pos,ps->N_DMRS_SLOT); +} + +void nr_set_pusch_semi_static(const NR_ServingCellConfigCommon_t *scc, + const NR_BWP_Uplink_t *ubwp, + const NR_BWP_UplinkDedicated_t *ubwpd, + long dci_format, + int tda, + uint8_t num_dmrs_cdm_grps_no_data, + NR_pusch_semi_static_t *ps) +{ + ps->dci_format = dci_format; + ps->time_domain_allocation = tda; + + const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = + ubwp? + ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList: + scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList ; + const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength, + &ps->startSymbolIndex, + &ps->nrOfSymbols); + + ps->pusch_Config = ubwp?ubwp->bwp_Dedicated->pusch_Config->choice.setup:(ubwpd ? ubwpd->pusch_Config->choice.setup : NULL); + if (ps->pusch_Config == NULL || !ps->pusch_Config->transformPrecoder) + ps->transform_precoding = !scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder; + else + ps->transform_precoding = *ps->pusch_Config->transformPrecoder; + const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + if (ps->transform_precoding) + ps->mcs_table = get_pusch_mcs_table(ps->pusch_Config ? ps->pusch_Config->mcs_Table : NULL, + 0, + ps->dci_format, + NR_RNTI_C, + target_ss, + false); + else { + ps->mcs_table = get_pusch_mcs_table(ps->pusch_Config ? ps->pusch_Config->mcs_TableTransformPrecoder : NULL, + 1, + ps->dci_format, + NR_RNTI_C, + target_ss, + false); + num_dmrs_cdm_grps_no_data = 2; // in case of transform precoding - no Data sent in DMRS symbol + } + + ps->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data; + + /* DMRS calculations */ + ps->mapping_type = tdaList->list.array[tda]->mappingType; + ps->NR_DMRS_UplinkConfig = ps->pusch_Config ? + (ps->mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA ? + ps->pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup : + ps->pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup) : NULL; + ps->dmrs_config_type = ps->NR_DMRS_UplinkConfig ? ((ps->NR_DMRS_UplinkConfig->dmrs_Type == NULL ? 0 : 1)) : 0; + const pusch_dmrs_AdditionalPosition_t additional_pos = + ps->NR_DMRS_UplinkConfig ? (ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL + ? 2 + : (*ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == + NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3 + ? 3 + : *ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition)):2; + const pusch_maxLength_t pusch_maxLength = + ps->NR_DMRS_UplinkConfig ? (ps->NR_DMRS_UplinkConfig->maxLength == NULL ? 1 : 2) : 1; + ps->ul_dmrs_symb_pos = get_l_prime(ps->nrOfSymbols, + ps->mapping_type, + additional_pos, + pusch_maxLength, + ps->startSymbolIndex, + scc->dmrs_TypeA_Position); + uint8_t num_dmrs_symb = 0; + for(int i = ps->startSymbolIndex; i < ps->startSymbolIndex + ps->nrOfSymbols; i++) + num_dmrs_symb += (ps->ul_dmrs_symb_pos >> i) & 1; + ps->num_dmrs_symb = num_dmrs_symb; + ps->N_PRB_DMRS = ps->dmrs_config_type == 0 + ? num_dmrs_cdm_grps_no_data * 6 + : num_dmrs_cdm_grps_no_data * 4; +} + void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, nr_scs_e scs_common, nr_scs_e pdcch_scs, @@ -407,146 +643,188 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, } -int nr_configure_pdcch(gNB_MAC_INST *nr_mac, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, - uint16_t rnti, - int ss_type, - NR_SearchSpace_t *ss, - NR_ServingCellConfigCommon_t *scc, - NR_BWP_Downlink_t *bwp){ +void config_uldci(const NR_BWP_Uplink_t *ubwp, + const NR_BWP_UplinkDedicated_t *ubwpd, + const NR_ServingCellConfigCommon_t *scc, + const nfapi_nr_pusch_pdu_t *pusch_pdu, + dci_pdu_rel15_t *dci_pdu_rel15, + int dci_format, + int time_domain_assignment, + uint8_t tpc, + int n_ubwp, + int bwp_id) { - int CCEIndex = -1; - int cid = 0; - NR_ControlResourceSet_t *coreset = NULL; + const int bw = NRRIV2BW(ubwp ? + ubwp->bwp_Common->genericParameters.locationAndBandwidth : + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - if (bwp) { // This is not the InitialBWP - NR_ControlResourceSet_t *temp_coreset; - NR_ControlResourceSetId_t coresetid = *ss->controlResourceSetId; - if (ss_type == 0) { // common search space - if (coresetid == 0){ - AssertFatal(1==0,"coreset0 currently not supported\n"); - } - else { - coreset = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet; - AssertFatal(coresetid==coreset->controlResourceSetId,"ID of common ss coreset does not correspond to id set in the search space\n"); + dci_pdu_rel15->frequency_domain_assignment.val = + PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw); + dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; + dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; + dci_pdu_rel15->mcs = pusch_pdu->mcs_index; + dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; + dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; + dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; + dci_pdu_rel15->tpc = tpc; + const NR_BWP_UplinkDedicated_t *ubwpd2 = (ubwp) ? ubwp->bwp_Dedicated : ubwpd; + + if (ubwpd2) AssertFatal(ubwpd2->pusch_Config->choice.setup->resourceAllocation == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1, + "Only frequency resource allocation type 1 is currently supported\n"); + switch (dci_format) { + case NR_UL_DCI_FORMAT_0_0: + dci_pdu_rel15->format_indicator = 0; + break; + case NR_UL_DCI_FORMAT_0_1: + LOG_D(NR_MAC,"Configuring DCI Format 0_1\n"); + dci_pdu_rel15->dai[0].val = 0; //TODO + // bwp indicator as per table 7.3.1.1.2-1 in 38.212 + dci_pdu_rel15->bwp_indicator.val = n_ubwp < 4 ? bwp_id : bwp_id - 1; + // SRS resource indicator + if (ubwpd2 && + ubwpd2->pusch_Config && + ubwpd2->pusch_Config->choice.setup && + ubwpd2->pusch_Config->choice.setup->txConfig != NULL) { + AssertFatal(*ubwpd2->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook, + "Non Codebook configuration non supported\n"); + dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS } + // Antenna Ports + dci_pdu_rel15->antenna_ports.val = 0; // TODO for now it is hardcoded, it should depends on cdm group no data and rank + // DMRS sequence initialization + dci_pdu_rel15->dmrs_sequence_initialization.val = pusch_pdu->scid; + break; + default : + AssertFatal(0, "Valid UL formats are 0_0 and 0_1\n"); + } + + LOG_D(NR_MAC, + "%s() ULDCI type 0 payload: freq_alloc %d, time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n", + __func__, + dci_pdu_rel15->frequency_domain_assignment.val, + dci_pdu_rel15->time_domain_assignment.val, + dci_pdu_rel15->frequency_hopping_flag.val, + dci_pdu_rel15->mcs, + dci_pdu_rel15->tpc, + dci_pdu_rel15->ndi, + dci_pdu_rel15->rv); +} + +const int default_pucch_fmt[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1}; +const int default_pucch_firstsymb[] = {12,12,12,10,10,10,10,4,4,4,4,0,0,0,0,0}; +const int default_pucch_numbsymb[] = {2,2,2,2,4,4,4,4,10,10,10,10,14,14,14,14,14}; +const int default_pucch_prboffset[] = {0,0,3,0,0,2,4,0,0,2,4,0,0,2,4,-1}; +const int default_pucch_csset[] = {2,3,3,2,4,4,4,2,4,4,4,2,4,4,4,4}; + +int nr_get_default_pucch_res(int pucch_ResourceCommon) { + + AssertFatal(pucch_ResourceCommon>=0 && pucch_ResourceCommon < 16, "illegal pucch_ResourceCommon %d\n",pucch_ResourceCommon); + + return(default_pucch_csset[pucch_ResourceCommon]); +} + +void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, + NR_SearchSpace_t *ss, + NR_ControlResourceSet_t *coreset, + NR_ServingCellConfigCommon_t *scc, + NR_BWP_t *bwp, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { + + int sps; + AssertFatal(*ss->controlResourceSetId == coreset->controlResourceSetId, + "coreset id in SS %ld does not correspond to the one in coreset %ld", + *ss->controlResourceSetId, coreset->controlResourceSetId); + + if (bwp) { // This is not for SIB1 + if(coreset->controlResourceSetId == 0){ + pdcch_pdu->BWPSize = gNB_mac->cset0_bwp_size; + pdcch_pdu->BWPStart = gNB_mac->cset0_bwp_start; } else { - int n_list = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.count; - for (int i=0; ibwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[i]; - if (coresetid==temp_coreset->controlResourceSetId) { - coreset = temp_coreset; - cid = i; - break; - } - } - if(coreset==NULL) - AssertFatal(1==0,"Couldn't find coreset with id %ld\n",coresetid); + pdcch_pdu->BWPSize = NRRIV2BW(bwp->locationAndBandwidth, MAX_BWP_SIZE); + pdcch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->locationAndBandwidth, MAX_BWP_SIZE); } - - pdcch_pdu->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdcch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdcch_pdu->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; - pdcch_pdu->CyclicPrefix = (bwp->bwp_Common->genericParameters.cyclicPrefix==NULL) ? 0 : *bwp->bwp_Common->genericParameters.cyclicPrefix; + pdcch_pdu->SubcarrierSpacing = bwp->subcarrierSpacing; + pdcch_pdu->CyclicPrefix = (bwp->cyclicPrefix==NULL) ? 0 : *bwp->cyclicPrefix; - // first symbol //AssertFatal(pdcch_scs==kHz15, "PDCCH SCS above 15kHz not allowed if a symbol above 2 is monitored"); - int sps = bwp->bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; - - AssertFatal(ss->monitoringSymbolsWithinSlot!=NULL,"ss->monitoringSymbolsWithinSlot is null\n"); - AssertFatal(ss->monitoringSymbolsWithinSlot->buf!=NULL,"ss->monitoringSymbolsWithinSlot->buf is null\n"); - - // for SPS=14 8 MSBs in positions 13 downto 6 - uint16_t monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | - (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - - for (int i=0; i>(sps-1-i))&1) { - pdcch_pdu->StartSymbolIndex=i; - break; - } - } - - pdcch_pdu->DurationSymbols = coreset->duration; - - for (int i=0;i<6;i++) - pdcch_pdu->FreqDomainResource[i] = coreset->frequencyDomainResources.buf[i]; - - - //cce-REG-MappingType - pdcch_pdu->CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved? - NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED : NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED; - - if (pdcch_pdu->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { - pdcch_pdu->RegBundleSize = (coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize); - pdcch_pdu->InterleaverSize = (coreset->cce_REG_MappingType.choice.interleaved->interleaverSize==NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->interleaverSize); - AssertFatal(scc->physCellId != NULL,"scc->physCellId is null\n"); - pdcch_pdu->ShiftIndex = coreset->cce_REG_MappingType.choice.interleaved->shiftIndex != NULL ? *coreset->cce_REG_MappingType.choice.interleaved->shiftIndex : *scc->physCellId; - } - else { - pdcch_pdu->RegBundleSize = 0; - pdcch_pdu->InterleaverSize = 0; - pdcch_pdu->ShiftIndex = 0; - } - - pdcch_pdu->CoreSetType = 1; - - //precoderGranularity - pdcch_pdu->precoderGranularity = coreset->precoderGranularity; - - pdcch_pdu->dci_pdu.RNTI[pdcch_pdu->numDlDci]=rnti; - - if (coreset->pdcch_DMRS_ScramblingID != NULL && - ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { - pdcch_pdu->dci_pdu.ScramblingId[pdcch_pdu->numDlDci] = *coreset->pdcch_DMRS_ScramblingID; - pdcch_pdu->dci_pdu.ScramblingRNTI[pdcch_pdu->numDlDci]=rnti; - } - else { - pdcch_pdu->dci_pdu.ScramblingId[pdcch_pdu->numDlDci] = *scc->physCellId; - pdcch_pdu->dci_pdu.ScramblingRNTI[pdcch_pdu->numDlDci]=0; - } - - uint8_t nr_of_candidates,aggregation_level; - find_aggregation_candidates(&aggregation_level, - &nr_of_candidates, - ss); - - CCEIndex = allocate_nr_CCEs(nr_mac, - 1, // bwp_id - cid, - aggregation_level, - ss->searchSpaceType->present-1, // search_space, 0 common, 1 ue-specific - 0, // UE-id - 0); // m - - if (CCEIndex<0) - return (CCEIndex); - - pdcch_pdu->dci_pdu.AggregationLevel[pdcch_pdu->numDlDci] = aggregation_level; - pdcch_pdu->dci_pdu.CceIndex[pdcch_pdu->numDlDci] = CCEIndex; - - if (ss->searchSpaceType->choice.ue_Specific->dci_Formats==NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_0_And_1_0) - pdcch_pdu->dci_pdu.beta_PDCCH_1_0[pdcch_pdu->numDlDci]=0; - - pdcch_pdu->dci_pdu.powerControlOffsetSS[pdcch_pdu->numDlDci]=1; - pdcch_pdu->numDlDci++; - return (0); + sps = bwp->cyclicPrefix == NULL ? 14 : 12; } - else { // this is for InitialBWP - AssertFatal(1==0,"Fill in InitialBWP PDCCH configuration\n"); + else { + AssertFatal(type0_PDCCH_CSS_config!=NULL,"type0_PDCCH_CSS_config is null,bwp %p\n",bwp); + pdcch_pdu->BWPSize = type0_PDCCH_CSS_config->num_rbs; + pdcch_pdu->BWPStart = type0_PDCCH_CSS_config->cset_start_rb; + pdcch_pdu->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch; + pdcch_pdu->CyclicPrefix = 0; + sps = 14; } + + AssertFatal(ss->monitoringSymbolsWithinSlot!=NULL,"ss->monitoringSymbolsWithinSlot is null\n"); + AssertFatal(ss->monitoringSymbolsWithinSlot->buf!=NULL,"ss->monitoringSymbolsWithinSlot->buf is null\n"); + + // for SPS=14 8 MSBs in positions 13 downto 6 + uint16_t monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | + (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + + for (int i=0; i>(sps-1-i))&1) { + pdcch_pdu->StartSymbolIndex=i; + break; + } + } + + pdcch_pdu->DurationSymbols = coreset->duration; + + for (int i=0;i<6;i++) + pdcch_pdu->FreqDomainResource[i] = coreset->frequencyDomainResources.buf[i]; + + LOG_D(MAC,"Coreset : BWPstart %d, BWPsize %d, SCS %d, freq %x, , duration %d, \n",pdcch_pdu->BWPStart,pdcch_pdu->BWPSize,(int)pdcch_pdu->SubcarrierSpacing,(int)coreset->frequencyDomainResources.buf[0],(int)coreset->duration); + + //cce-REG-MappingType + pdcch_pdu->CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved? + NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED : NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED; + + if (pdcch_pdu->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { + pdcch_pdu->RegBundleSize = (coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize == + NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize); + pdcch_pdu->InterleaverSize = (coreset->cce_REG_MappingType.choice.interleaved->interleaverSize == + NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->interleaverSize); + AssertFatal(scc->physCellId != NULL,"scc->physCellId is null\n"); + pdcch_pdu->ShiftIndex = coreset->cce_REG_MappingType.choice.interleaved->shiftIndex != NULL ? *coreset->cce_REG_MappingType.choice.interleaved->shiftIndex : *scc->physCellId; + } + else { + pdcch_pdu->RegBundleSize = 0; + pdcch_pdu->InterleaverSize = 0; + pdcch_pdu->ShiftIndex = 0; + } + + if(coreset->controlResourceSetId == 0) { + if(bwp == NULL) + pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; + else + pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG_CSET_0; + } else{ + pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; + } + + //precoderGranularity + pdcch_pdu->precoderGranularity = coreset->precoderGranularity; } // This function configures pucch pdu fapi structure void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, - NR_ServingCellConfigCommon_t *scc, - NR_BWP_Uplink_t *bwp, + NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *CellGroup, + NR_BWP_Uplink_t *bwp, + NR_BWP_UplinkDedicated_t *bwpd, + uint16_t rnti, uint8_t pucch_resource, - uint16_t O_uci, + uint16_t O_csi, uint16_t O_ack, - uint8_t SR_flag) { + uint8_t O_sr, + int r_pucch) { NR_PUCCH_Config_t *pucch_Config; NR_PUCCH_Resource_t *pucchres; @@ -560,75 +838,93 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, int res_found = 0; pucch_pdu->bit_len_harq = O_ack; + pucch_pdu->bit_len_csi_part1 = O_csi; - if (bwp) { // This is not the InitialBWP + uint16_t O_uci = O_csi + O_ack; - NR_PUSCH_Config_t *pusch_Config = bwp->bwp_Dedicated->pusch_Config->choice.setup; - long *pusch_id = pusch_Config->dataScramblingIdentityPUSCH; + NR_PUSCH_Config_t *pusch_Config = bwp ? bwp->bwp_Dedicated->pusch_Config->choice.setup : bwpd->pusch_Config->choice.setup; + long *pusch_id = pusch_Config ? pusch_Config->dataScramblingIdentityPUSCH : NULL; - if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) - id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->transformPrecodingDisabled->scramblingID0; - if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL) - id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->transformPrecodingDisabled->scramblingID0; + if (pusch_Config && pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) + id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->transformPrecodingDisabled->scramblingID0; + else if (pusch_Config && pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL) + id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->transformPrecodingDisabled->scramblingID0; + else id0 = scc->physCellId; - // hop flags and hopping id are valid for any BWP - switch (bwp->bwp_Common->pucch_ConfigCommon->choice.setup->pucch_GroupHopping){ - case 0 : - // if neither, both disabled - pucch_pdu->group_hop_flag = 0; - pucch_pdu->sequence_hop_flag = 0; - break; - case 1 : - // if enable, group enabled - pucch_pdu->group_hop_flag = 1; - pucch_pdu->sequence_hop_flag = 0; - break; - case 2 : - // if disable, sequence disabled - pucch_pdu->group_hop_flag = 0; - pucch_pdu->sequence_hop_flag = 1; - break; - default: - AssertFatal(1==0,"Group hopping flag %ld undefined (0,1,2) \n", bwp->bwp_Common->pucch_ConfigCommon->choice.setup->pucch_GroupHopping); - } + NR_PUCCH_ConfigCommon_t *pucch_ConfigCommon = bwp ? + bwp->bwp_Common->pucch_ConfigCommon->choice.setup : + scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup; + // hop flags and hopping id are valid for any BWP + switch (pucch_ConfigCommon->pucch_GroupHopping){ + case 0 : + // if neither, both disabled + pucch_pdu->group_hop_flag = 0; + pucch_pdu->sequence_hop_flag = 0; + break; + case 1 : + // if enable, group enabled + pucch_pdu->group_hop_flag = 1; + pucch_pdu->sequence_hop_flag = 0; + break; + case 2 : + // if disable, sequence disabled + pucch_pdu->group_hop_flag = 0; + pucch_pdu->sequence_hop_flag = 1; + break; + default: + AssertFatal(1==0,"Group hopping flag %ld undefined (0,1,2) \n", pucch_ConfigCommon->pucch_GroupHopping); + } - if (bwp->bwp_Common->pucch_ConfigCommon->choice.setup->hoppingId != NULL) - pucch_pdu->hopping_id = *bwp->bwp_Common->pucch_ConfigCommon->choice.setup->hoppingId; - else - pucch_pdu->hopping_id = *scc->physCellId; + if (pucch_ConfigCommon->hoppingId != NULL) + pucch_pdu->hopping_id = *pucch_ConfigCommon->hoppingId; + else + pucch_pdu->hopping_id = *scc->physCellId; + NR_BWP_t *genericParameters = bwp ? + &bwp->bwp_Common->genericParameters: + &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + pucch_pdu->bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + pucch_pdu->bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth,MAX_BWP_SIZE); + pucch_pdu->subcarrier_spacing = genericParameters->subcarrierSpacing; + pucch_pdu->cyclic_prefix = (genericParameters->cyclicPrefix==NULL) ? 0 : *genericParameters->cyclicPrefix; + if (r_pucch<0 || bwp ){ + LOG_D(NR_MAC,"pucch_acknak: Filling dedicated configuration for PUCCH\n"); + // we have either a dedicated BWP or Dedicated PUCCH configuration on InitialBWP + AssertFatal(bwp!=NULL || bwpd!=NULL,"We need one dedicated configuration for a BWP (neither additional or initial BWP has a dedicated configuration)\n"); + pucch_Config = bwp ? + bwp->bwp_Dedicated->pucch_Config->choice.setup: + bwpd->pucch_Config->choice.setup; - pucch_pdu->bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pucch_pdu->bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pucch_pdu->subcarrier_spacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; - pucch_pdu->cyclic_prefix = (bwp->bwp_Common->genericParameters.cyclicPrefix==NULL) ? 0 : *bwp->bwp_Common->genericParameters.cyclicPrefix; + AssertFatal(pucch_Config->resourceSetToAddModList!=NULL, + "PUCCH resourceSetToAddModList is null\n"); - pucch_Config = bwp->bwp_Dedicated->pucch_Config->choice.setup; + n_set = pucch_Config->resourceSetToAddModList->list.count; + AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n"); - AssertFatal(pucch_Config->resourceSetToAddModList!=NULL, - "PUCCH resourceSetToAddModList is null\n"); + LOG_D(NR_MAC, "UCI n_set= %d\n", n_set); - n_set = pucch_Config->resourceSetToAddModList->list.count; - AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n"); - - N2 = 2; - // procedure to select pucch resource id from resource sets according to - // number of uci bits and pucch resource indicator pucch_resource - // ( see table 9.2.3.2 in 38.213) - for (int i=0; iresourceSetToAddModList->list.array[i]; - n_list = pucchresset->resourceList.list.count; - if (pucchresset->pucch_ResourceSetId == 0 && O_uci<3) { - if (pucch_resource < n_list) - resource_id = pucchresset->resourceList.list.array[pucch_resource]; - else - AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); - } - else { + N2 = 2; + // procedure to select pucch resource id from resource sets according to + // number of uci bits and pucch resource indicator pucch_resource + // ( see table 9.2.3.2 in 38.213) + for (int i=0; iresourceSetToAddModList->list.array[i]; + n_list = pucchresset->resourceList.list.count; + if (pucchresset->pucch_ResourceSetId == 0 && O_uci<3) { + if (pucch_resource < n_list) + resource_id = pucchresset->resourceList.list.array[pucch_resource]; + else + AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); + } + if (pucchresset->pucch_ResourceSetId == 1 && O_uci>2) { +#if (NR_RRC_VERSION >= MAKE_VERSION(16, 0, 0)) + N3 = pucchresset->maxPayloadSize!= NULL ? *pucchresset->maxPayloadSize : 1706; +#else N3 = pucchresset->maxPayloadMinus1!= NULL ? *pucchresset->maxPayloadMinus1 : 1706; +#endif if (N2O_uci) { if (pucch_resource < n_list) resource_id = pucchresset->resourceList.list.array[pucch_resource]; - else + else AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci); } else N2 = N3; @@ -638,9 +934,9 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, AssertFatal(resource_id!=NULL,"Couldn-t find any matching PUCCH resource in the PUCCH resource sets"); AssertFatal(pucch_Config->resourceToAddModList!=NULL, - "PUCCH resourceToAddModList is null\n"); + "PUCCH resourceToAddModList is null\n"); - n_list = pucch_Config->resourceToAddModList->list.count; + n_list = pucch_Config->resourceToAddModList->list.count; AssertFatal(n_list>0,"PUCCH resourceToAddModList is empty\n"); // going through the list of PUCCH resources to find the one indexed by resource_id @@ -649,6 +945,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, if (pucchres->pucch_ResourceId == *resource_id) { res_found = 1; pucch_pdu->prb_start = pucchres->startingPRB; + pucch_pdu->rnti = rnti; // FIXME why there is only one frequency hopping flag // what about inter slot frequency hopping? pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0; @@ -659,7 +956,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift; pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols; pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex; - pucch_pdu->sr_flag = SR_flag; + pucch_pdu->sr_flag = O_sr; + pucch_pdu->prb_size = 1; break; case NR_PUCCH_Resource__format_PR_format1 : pucch_pdu->format_type = 1; @@ -667,21 +965,24 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols; pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex; pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC; - pucch_pdu->sr_flag = SR_flag; + pucch_pdu->sr_flag = O_sr; + pucch_pdu->prb_size = 1; break; case NR_PUCCH_Resource__format_PR_format2 : pucch_pdu->format_type = 2; pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols; pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex; - pucch_pdu->prb_size = pucchres->format.choice.format2->nrofPRBs; pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId; + pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs, + O_uci+O_sr,O_csi,pucch_Config->format2->choice.setup->maxCodeRate, + 2,pucchres->format.choice.format2->nrofSymbols,8); + pucch_pdu->bit_len_csi_part1 = O_csi; break; case NR_PUCCH_Resource__format_PR_format3 : pucch_pdu->format_type = 3; pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols; pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex; - pucch_pdu->prb_size = pucchres->format.choice.format3->nrofPRBs; pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId; if (pucch_Config->format3 == NULL) { pucch_pdu->pi_2bpsk = 0; @@ -692,6 +993,19 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; } + int f3_dmrs_symbols; + if (pucchres->format.choice.format3->nrofSymbols==4) + f3_dmrs_symbols = 1<freq_hop_flag; + else { + if(pucchres->format.choice.format3->nrofSymbols<10) + f3_dmrs_symbols = 2; + else + f3_dmrs_symbols = 2<add_dmrs_flag; + } + pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs, + O_uci+O_sr,O_csi,pucch_Config->format3->choice.setup->maxCodeRate, + 2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12); + pucch_pdu->bit_len_csi_part1 = O_csi; break; case NR_PUCCH_Resource__format_PR_format4 : pucch_pdu->format_type = 4; @@ -709,6 +1023,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; } + pucch_pdu->bit_len_csi_part1 = O_csi; break; default : AssertFatal(1==0,"Undefined PUCCH format \n"); @@ -716,30 +1031,64 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, } } AssertFatal(res_found==1,"No PUCCH resource found corresponding to id %ld\n",*resource_id); - } - else { // this is for InitialBWP - AssertFatal(1==0,"Fill in InitialBWP PUCCH configuration\n"); } - + else { // this is the default PUCCH configuration, PUCCH format 0 or 1 + LOG_D(NR_MAC,"pucch_acknak: Filling default PUCCH configuration from Tables (r_pucch %d, bwp %p)\n",r_pucch,bwp); + int rsetindex = *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon; + int prboffset = r_pucch/default_pucch_csset[rsetindex]; + int prboffsetm8 = (r_pucch-8)/default_pucch_csset[rsetindex]; + pucch_pdu->prb_start = (r_pucch>>3)==0 ? + default_pucch_prboffset[rsetindex] + prboffset: + pucch_pdu->bwp_size-1-default_pucch_prboffset[rsetindex]-prboffsetm8; + pucch_pdu->rnti = rnti; + pucch_pdu->freq_hop_flag = 1; + pucch_pdu->second_hop_prb = (r_pucch>>3)==0? + pucch_pdu->bwp_size-1-default_pucch_prboffset[rsetindex]-prboffset: + default_pucch_prboffset[rsetindex] + prboffsetm8; + pucch_pdu->format_type = default_pucch_fmt[rsetindex]; + pucch_pdu->initial_cyclic_shift = r_pucch%default_pucch_csset[rsetindex]; + if (rsetindex==3||rsetindex==7||rsetindex==11) pucch_pdu->initial_cyclic_shift*=6; + else if (rsetindex==1||rsetindex==2) pucch_pdu->initial_cyclic_shift*=3; + else pucch_pdu->initial_cyclic_shift*=4; + pucch_pdu->nr_of_symbols = default_pucch_numbsymb[rsetindex]; + pucch_pdu->start_symbol_index = default_pucch_firstsymb[rsetindex]; + if (pucch_pdu->format_type == 1) pucch_pdu->time_domain_occ_idx = 0; // check this!! + pucch_pdu->sr_flag = O_sr; + pucch_pdu->prb_size=1; + } } -void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, +void prepare_dci(const NR_CellGroupConfig_t *CellGroup, dci_pdu_rel15_t *dci_pdu_rel15, nr_dci_format_t format, int bwp_id) { - NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + AssertFatal(CellGroup!=NULL,"CellGroup shouldn't be null here\n"); + + const NR_BWP_DownlinkDedicated_t *bwpd = NULL; + const NR_PDSCH_Config_t *pdsch_Config = NULL; + const NR_PDCCH_Config_t *pdcch_Config = NULL; + + if (bwp_id>0) { + bwpd=CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated; + } + else { + bwpd=CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP; + } + pdsch_Config = (bwpd->pdsch_Config) ? bwpd->pdsch_Config->choice.setup : NULL; + pdcch_Config = (bwpd->pdcch_Config) ? bwpd->pdcch_Config->choice.setup : NULL; + switch(format) { case NR_UL_DCI_FORMAT_0_1: // format indicator dci_pdu_rel15->format_indicator = 0; // carrier indicator - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) + if (CellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) AssertFatal(1==0,"Cross Carrier Scheduling Config currently not supported\n"); // supplementary uplink - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL) + if (CellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL) AssertFatal(1==0,"Supplementary Uplink currently not supported\n"); // SRS request dci_pdu_rel15->srs_request.val = 0; @@ -749,29 +1098,29 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, // format indicator dci_pdu_rel15->format_indicator = 1; // carrier indicator - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) + if (CellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) AssertFatal(1==0,"Cross Carrier Scheduling Config currently not supported\n"); //vrb to prb mapping - if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->vrb_ToPRB_Interleaver==NULL) + if (pdsch_Config->vrb_ToPRB_Interleaver==NULL) dci_pdu_rel15->vrb_to_prb_mapping.val = 0; else dci_pdu_rel15->vrb_to_prb_mapping.val = 1; //bundling size indicator - if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present == NR_PDSCH_Config__prb_BundlingType_PR_dynamicBundling) + if (pdsch_Config->prb_BundlingType.present == NR_PDSCH_Config__prb_BundlingType_PR_dynamicBundling) AssertFatal(1==0,"Dynamic PRB bundling type currently not supported\n"); //rate matching indicator - uint16_t msb = (bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup1==NULL)?0:1; - uint16_t lsb = (bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup2==NULL)?0:1; + uint16_t msb = (pdsch_Config->rateMatchPatternGroup1==NULL)?0:1; + uint16_t lsb = (pdsch_Config->rateMatchPatternGroup2==NULL)?0:1; dci_pdu_rel15->rate_matching_indicator.val = lsb | (msb<<1); // aperiodic ZP CSI-RS trigger - if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList != NULL) + if (pdsch_Config->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList != NULL) AssertFatal(1==0,"Aperiodic ZP CSI-RS currently not supported\n"); // transmission configuration indication - if (bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]->tci_PresentInDCI != NULL) + if (pdcch_Config->controlResourceSetToAddModList->list.array[0]->tci_PresentInDCI != NULL) AssertFatal(1==0,"TCI in DCI currently not supported\n"); //srs resource set - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching!=NULL) { - NR_SRS_CarrierSwitching_t *cs = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching->choice.setup; + if (CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching!=NULL) { + NR_SRS_CarrierSwitching_t *cs = CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching->choice.setup; if (cs->srs_TPC_PDCCH_Group!=NULL){ switch(cs->srs_TPC_PDCCH_Group->present) { case NR_SRS_CarrierSwitching__srs_TPC_PDCCH_Group_PR_NOTHING: @@ -791,7 +1140,9 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, else dci_pdu_rel15->srs_request.val = 0; // CBGTI and CBGFI - if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) + if (CellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig && + CellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup && + CellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) AssertFatal(1==0,"CBG transmission currently not supported\n"); break; default : @@ -800,571 +1151,553 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, } -void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *secondaryCellGroup, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, +void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, + const NR_CellGroupConfig_t *CellGroup, + nfapi_nr_dl_dci_pdu_t *pdcch_dci_pdu, dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, - int *rnti_types, + int dci_format, + int rnti_type, int N_RB, int bwp_id) { + uint8_t fsize = 0, pos = 0; - uint8_t fsize=0, pos=0; + uint64_t *dci_pdu = (uint64_t *)pdcch_dci_pdu->Payload; + *dci_pdu=0; + int dci_size = nr_dci_size(scc->downlinkConfigCommon->initialDownlinkBWP,scc->uplinkConfigCommon->initialUplinkBWP, CellGroup, dci_pdu_rel15, dci_format, rnti_type, N_RB, bwp_id); + pdcch_dci_pdu->PayloadSizeBits = dci_size; + AssertFatal(dci_size <= 64, "DCI sizes above 64 bits not yet supported"); + if (dci_format == NR_DL_DCI_FORMAT_1_1 || dci_format == NR_UL_DCI_FORMAT_0_1) + prepare_dci(CellGroup, dci_pdu_rel15, dci_format, bwp_id); - for (int d=0;dnumDlDci;d++) { + /// Payload generation + switch (dci_format) { + case NR_DL_DCI_FORMAT_1_0: + switch (rnti_type) { + case NR_RNTI_RA: + // Freq domain assignment + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + pos = fsize; + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos)); + LOG_D(NR_MAC, + "RA_RNTI, size %d frequency-domain assignment %d (%d bits) N_RB_BWP %d=> %d (0x%lx)\n", + dci_size,dci_pdu_rel15->frequency_domain_assignment.val, + fsize, + N_RB, + dci_size - pos, + *dci_pdu); + // Time domain assignment + pos += 4; + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val & 0xf) << (dci_size - pos)); + LOG_D(NR_MAC, + "time-domain assignment %d (4 bits)=> %d (0x%lx)\n", + dci_pdu_rel15->time_domain_assignment.val, + dci_size - pos, + *dci_pdu); + // VRB to PRB mapping + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 0x1) << (dci_size - pos); + LOG_D(NR_MAC, + "vrb to prb mapping %d (1 bits)=> %d (0x%lx)\n", + dci_pdu_rel15->vrb_to_prb_mapping.val, + dci_size - pos, + *dci_pdu); + // MCS + pos += 5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + LOG_D(NR_MAC, "mcs %d (5 bits)=> %d (0x%lx)\n", dci_pdu_rel15->mcs, dci_size - pos, *dci_pdu); + // TB scaling + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tb_scaling & 0x3) << (dci_size - pos); + LOG_D(NR_MAC, "tb_scaling %d (2 bits)=> %d (0x%lx)\n", dci_pdu_rel15->tb_scaling, dci_size - pos, *dci_pdu); + break; - uint64_t *dci_pdu = (uint64_t *)pdcch_pdu_rel15->dci_pdu.Payload[d]; - int dci_size = nr_dci_size(scc,secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],rnti_types[d],N_RB,bwp_id); - pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d] = dci_size; - AssertFatal(pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d]<=64, "DCI sizes above 64 bits not yet supported"); - - if(dci_formats[d]==NR_DL_DCI_FORMAT_1_1 || dci_formats[d]==NR_UL_DCI_FORMAT_0_1) - prepare_dci(secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],bwp_id); - - /// Payload generation - switch(dci_formats[d]) { - case NR_DL_DCI_FORMAT_1_0: - switch(rnti_types[d]) { - case NR_RNTI_RA: - // Freq domain assignment - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - pos=fsize; - *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,N_RB,dci_size-pos,*dci_pdu); - // Time domain assignment - pos+=4; - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val&0xf) << (dci_size-pos)); - LOG_D(MAC,"time-domain assignment %d (3 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu); - // VRB to PRB mapping - - pos++; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&0x1)<<(dci_size-pos); - LOG_D(MAC,"vrb to prb mapping %d (1 bits)=> %d (0x%lx)\n",dci_pdu_rel15->vrb_to_prb_mapping.val,dci_size-pos,*dci_pdu); - // MCS - pos+=5; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); -#ifdef DEBUG_FILL_DCI - LOG_I(MAC,"mcs %d (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu); -#endif - // TB scaling - pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->tb_scaling&0x3)<<(dci_size-pos); -#ifdef DEBUG_FILL_DCI - LOG_I(MAC,"tb_scaling %d (2 bits)=> %d (0x%lx)\n",dci_pdu_rel15->tb_scaling,dci_size-pos,*dci_pdu); -#endif - break; - - case NR_RNTI_C: - - // indicating a DL DCI format 1bit - pos++; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos); - LOG_D(MAC,"Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,N_RB,dci_size-pos,*dci_pdu); - - // Freq domain assignment (275rb >> fsize = 16) - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - pos+=fsize; - *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu); - - uint16_t is_ra = 1; - for (int i=0; ifrequency_domain_assignment.val>>i)&1)) { - is_ra = 0; - break; - } - if (is_ra) //fsize are all 1 38.212 p86 - { - // ra_preamble_index 6 bits - pos+=6; - *dci_pdu |= ((dci_pdu_rel15->ra_preamble_index&0x3f)<<(dci_size-pos)); - - // UL/SUL indicator 1 bit - pos++; - *dci_pdu |= (dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos); - - // SS/PBCH index 6 bits - pos+=6; - *dci_pdu |= ((dci_pdu_rel15->ss_pbch_index&0x3f)<<(dci_size-pos)); - - // prach_mask_index 4 bits - pos+=4; - *dci_pdu |= ((dci_pdu_rel15->prach_mask_index&0xf)<<(dci_size-pos)); - - } //end if - - else { - - // Time domain assignment 4bit - - pos+=4; - *dci_pdu |= ((dci_pdu_rel15->time_domain_assignment.val&0xf) << (dci_size-pos)); - LOG_D(MAC,"Time domain assignment %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,4,dci_size-pos,*dci_pdu); - - // VRB to PRB mapping 1bit - pos++; - *dci_pdu |= (dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos); - LOG_D(MAC,"VRB to PRB %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->vrb_to_prb_mapping.val,1,dci_size-pos,*dci_pdu); - - // MCS 5bit //bit over 32, so dci_pdu ++ - pos+=5; - *dci_pdu |= (dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); - LOG_D(MAC,"MCS %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,5,dci_size-pos,*dci_pdu); - - // New data indicator 1bit - pos++; - *dci_pdu |= (dci_pdu_rel15->ndi&1)<<(dci_size-pos); - LOG_D(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu); - - // Redundancy version 2bit - pos+=2; - *dci_pdu |= (dci_pdu_rel15->rv&0x3)<<(dci_size-pos); - LOG_D(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu); - - // HARQ process number 4bit - pos+=4; - *dci_pdu |= ((dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos)); - LOG_D(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu); - - // Downlink assignment index 2bit - pos+=2; - *dci_pdu |= ((dci_pdu_rel15->dai[0].val&3)<<(dci_size-pos)); - LOG_D(MAC,"DAI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->dai[0].val,2,dci_size-pos,*dci_pdu); - - // TPC command for scheduled PUCCH 2bit - pos+=2; - *dci_pdu |= ((dci_pdu_rel15->tpc&3)<<(dci_size-pos)); - LOG_D(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu); - - // PUCCH resource indicator 3bit - pos+=3; - *dci_pdu |= ((dci_pdu_rel15->pucch_resource_indicator&0x7)<<(dci_size-pos)); - LOG_D(MAC,"PUCCH RI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->pucch_resource_indicator,3,dci_size-pos,*dci_pdu); - - // PDSCH-to-HARQ_feedback timing indicator 3bit - pos+=3; - *dci_pdu |= ((dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val&0x7)<<(dci_size-pos)); - LOG_D(MAC,"PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val,3,dci_size-pos,*dci_pdu); - - } //end else - break; - - case NR_RNTI_P: - - // Short Messages Indicator – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator>>(1-i))&1)<<(dci_size-pos++); - // Short Messages – 8 bits - for (int i=0; i<8; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages>>(7-i))&1)<<(dci_size-pos++); - // Freq domain assignment 0-16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4 bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // VRB to PRB mapping 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++); - // MCS 5 bit - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - - // TB scaling 2 bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tb_scaling>>(1-i))&1)<<(dci_size-pos++); - - - break; - - case NR_RNTI_SI: - // Freq domain assignment 0-16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4 bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // VRB to PRB mapping 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++); - // MCS 5bit //bit over 32, so dci_pdu ++ - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - // Redundancy version 2bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - - break; - - case NR_RNTI_TC: - // indicating a DL DCI format 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++); - // Freq domain assignment 0-16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4 bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // VRB to PRB mapping 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++); - // MCS 5bit //bit over 32, so dci_pdu ++ - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - // New data indicator 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++); - // Redundancy version 2bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - // HARQ process number 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++); - - // Downlink assignment index – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->dai[0].val>>(1-i))&1)<<(dci_size-pos++); - - // TPC command for scheduled PUCCH – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++); - - - // LOG_D(MAC, "DCI PDU: [0]->0x%08llx \t [1]->0x%08llx \t [2]->0x%08llx \t [3]->0x%08llx\n", - // dci_pdu[0], dci_pdu[1], dci_pdu[2], dci_pdu[3]); - - - // PDSCH-to-HARQ_feedback timing indicator – 3 bits - for (int i=0; i<3; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val>>(2-i))&1)<<(dci_size-pos++); - - break; + case NR_RNTI_C: + // indicating a DL DCI format 1bit + pos++; + *dci_pdu |= ((uint64_t)1) << (dci_size - pos); + LOG_D(NR_MAC, + "DCI1_0 (size %d): Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n", + dci_size, + dci_pdu_rel15->format_indicator, + 1, + N_RB, + dci_size - pos, + *dci_pdu); + // Freq domain assignment (275rb >> fsize = 16) + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + pos += fsize; + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos)); + LOG_D(NR_MAC, + "Freq domain assignment %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->frequency_domain_assignment.val, + fsize, + dci_size - pos, + *dci_pdu); + uint16_t is_ra = 1; + for (int i = 0; i < fsize; i++) { + if (!((dci_pdu_rel15->frequency_domain_assignment.val >> i) & 1)) { + is_ra = 0; + break; + } } - break; - - case NR_UL_DCI_FORMAT_0_0: - switch(rnti_types[d]) - { - case NR_RNTI_C: - // indicating a DL DCI format 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++); - // Freq domain assignment max 16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // Frequency hopping flag – 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&1)<<(dci_size-pos++); - // MCS 5 bit - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - // New data indicator 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++); - // Redundancy version 2bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - // HARQ process number 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++); - - // TPC command for scheduled PUSCH – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++); - - // Padding bits - for(int a = pos;a<32;a++) - *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding&1)<<(dci_size-pos++); - - // UL/SUL indicator – 1 bit - /* commented for now (RK): need to get this from BWP descriptor - if (cfg->pucch_config.pucch_GroupHopping.value) - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); - */ - break; - - case NFAPI_NR_RNTI_TC: - - // indicating a DL DCI format 1bit - *dci_pdu |= (dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++); - // Freq domain assignment max 16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // Frequency hopping flag – 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&1)<<(dci_size-pos++); - // MCS 5 bit - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - // New data indicator 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++); - // Redundancy version 2bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - // HARQ process number 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++); - - // TPC command for scheduled PUSCH – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++); - - // Padding bits - for(int a = pos;a<32;a++) - *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding&1)<<(dci_size-pos++); - - // UL/SUL indicator – 1 bit - /* - commented for now (RK): need to get this information from BWP descriptor - if (cfg->pucch_config.pucch_GroupHopping.value) - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); - */ - break; - - } + if (is_ra) { // fsize are all 1 38.212 p86 + // ra_preamble_index 6 bits + pos += 6; + *dci_pdu |= ((dci_pdu_rel15->ra_preamble_index & 0x3f) << (dci_size - pos)); + // UL/SUL indicator 1 bit + pos++; + *dci_pdu |= (dci_pdu_rel15->ul_sul_indicator.val & 1) << (dci_size - pos); + // SS/PBCH index 6 bits + pos += 6; + *dci_pdu |= ((dci_pdu_rel15->ss_pbch_index & 0x3f) << (dci_size - pos)); + // prach_mask_index 4 bits + pos += 4; + *dci_pdu |= ((dci_pdu_rel15->prach_mask_index & 0xf) << (dci_size - pos)); + } else { + // Time domain assignment 4bit + pos += 4; + *dci_pdu |= ((dci_pdu_rel15->time_domain_assignment.val & 0xf) << (dci_size - pos)); + LOG_D(NR_MAC, + "Time domain assignment %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->time_domain_assignment.val, + 4, + dci_size - pos, + *dci_pdu); + // VRB to PRB mapping 1bit + pos++; + *dci_pdu |= (dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos); + LOG_D(NR_MAC, + "VRB to PRB %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->vrb_to_prb_mapping.val, + 1, + dci_size - pos, + *dci_pdu); + // MCS 5bit //bit over 32, so dci_pdu ++ + pos += 5; + *dci_pdu |= (dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + LOG_D(NR_MAC, "MCS %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->mcs, 5, dci_size - pos, *dci_pdu); + // New data indicator 1bit + pos++; + *dci_pdu |= (dci_pdu_rel15->ndi & 1) << (dci_size - pos); + LOG_D(NR_MAC, "NDI %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->ndi, 1, dci_size - pos, *dci_pdu); + // Redundancy version 2bit + pos += 2; + *dci_pdu |= (dci_pdu_rel15->rv & 0x3) << (dci_size - pos); + LOG_D(NR_MAC, "RV %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->rv, 2, dci_size - pos, *dci_pdu); + // HARQ process number 4bit + pos += 4; + *dci_pdu |= ((dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos)); + LOG_D(NR_MAC, "HARQ_PID %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->harq_pid, 4, dci_size - pos, *dci_pdu); + // Downlink assignment index 2bit + pos += 2; + *dci_pdu |= ((dci_pdu_rel15->dai[0].val & 3) << (dci_size - pos)); + LOG_D(NR_MAC, "DAI %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->dai[0].val, 2, dci_size - pos, *dci_pdu); + // TPC command for scheduled PUCCH 2bit + pos += 2; + *dci_pdu |= ((dci_pdu_rel15->tpc & 3) << (dci_size - pos)); + LOG_D(NR_MAC, "TPC %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->tpc, 2, dci_size - pos, *dci_pdu); + // PUCCH resource indicator 3bit + pos += 3; + *dci_pdu |= ((dci_pdu_rel15->pucch_resource_indicator & 0x7) << (dci_size - pos)); + LOG_D(NR_MAC, + "PUCCH RI %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->pucch_resource_indicator, + 3, + dci_size - pos, + *dci_pdu); + // PDSCH-to-HARQ_feedback timing indicator 3bit + pos += 3; + *dci_pdu |= ((dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val & 0x7) << (dci_size - pos)); + LOG_D(NR_MAC, + "PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val, + 3, + dci_size - pos, + *dci_pdu); + } // end else break; - case NR_UL_DCI_FORMAT_0_1: - switch(rnti_types[d]) - { - case NR_RNTI_C: - // Indicating a DL DCI format 1bit - pos=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&0x1)<<(dci_size-pos); - - // Carrier indicator - pos+=dci_pdu_rel15->carrier_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val&((1<carrier_indicator.nbits)-1))<<(dci_size-pos); - - // UL/SUL Indicator - pos+=dci_pdu_rel15->ul_sul_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&((1<ul_sul_indicator.nbits)-1))<<(dci_size-pos); - - // BWP indicator - pos+=dci_pdu_rel15->bwp_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val&((1<bwp_indicator.nbits)-1))<<(dci_size-pos); - - // Frequency domain resource assignment - pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1<frequency_domain_assignment.nbits)-1)) << (dci_size-pos); - - // Time domain resource assignment - pos+=dci_pdu_rel15->time_domain_assignment.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val&((1<time_domain_assignment.nbits)-1)) << (dci_size-pos); - - // Frequency hopping - pos+=dci_pdu_rel15->frequency_hopping_flag.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&((1<frequency_hopping_flag.nbits)-1)) << (dci_size-pos); - - // MCS 5bit - pos+=5; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); - - // New data indicator 1bit - pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&0x1)<<(dci_size-pos); - - // Redundancy version 2bit - pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv&0x3)<<(dci_size-pos); - - // HARQ process number 4bit - pos+=4; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos); - - // 1st Downlink assignment index - pos+=dci_pdu_rel15->dai[0].nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val&((1<dai[0].nbits)-1))<<(dci_size-pos); - - // 2nd Downlink assignment index - pos+=dci_pdu_rel15->dai[1].nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val&((1<dai[1].nbits)-1))<<(dci_size-pos); - - // TPC command for scheduled PUSCH 2bit - pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc&0x3)<<(dci_size-pos); - - // SRS resource indicator - pos+=dci_pdu_rel15->srs_resource_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val&((1<srs_resource_indicator.nbits)-1))<<(dci_size-pos); - - // Precoding info and n. of layers - pos+=dci_pdu_rel15->precoding_information.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val&((1<precoding_information.nbits)-1))<<(dci_size-pos); - - // Antenna ports - pos+=dci_pdu_rel15->antenna_ports.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val&((1<antenna_ports.nbits)-1))<<(dci_size-pos); - - // SRS request - pos+=dci_pdu_rel15->srs_request.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val&((1<srs_request.nbits)-1))<<(dci_size-pos); - - // CSI request - pos+=dci_pdu_rel15->csi_request.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val&((1<csi_request.nbits)-1))<<(dci_size-pos); - - // CBG transmission information - pos+=dci_pdu_rel15->cbgti.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val&((1<cbgti.nbits)-1))<<(dci_size-pos); - - // PTRS DMRS association - pos+=dci_pdu_rel15->ptrs_dmrs_association.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val&((1<ptrs_dmrs_association.nbits)-1))<<(dci_size-pos); - - // Beta offset indicator - pos+=dci_pdu_rel15->beta_offset_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val&((1<beta_offset_indicator.nbits)-1))<<(dci_size-pos); - - // DMRS sequence initialization - pos+=dci_pdu_rel15->dmrs_sequence_initialization.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&((1<dmrs_sequence_initialization.nbits)-1))<<(dci_size-pos); - - // UL-SCH indicator - pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator&0x1)<<(dci_size-pos); - - break; - } + case NR_RNTI_P: + // Short Messages Indicator – 2 bits + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator >> (1 - i)) & 1) << (dci_size - pos++); + // Short Messages – 8 bits + for (int i = 0; i < 8; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages >> (7 - i)) & 1) << (dci_size - pos++); + // Freq domain assignment 0-16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + for (int i = 0; i < fsize; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + // Time domain assignment 4 bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + // VRB to PRB mapping 1 bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++); + // MCS 5 bit + for (int i = 0; i < 5; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); + // TB scaling 2 bit + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->tb_scaling >> (1 - i)) & 1) << (dci_size - pos++); break; - case NR_DL_DCI_FORMAT_1_1: - // Indicating a DL DCI format 1bit - pos=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&0x1)<<(dci_size-pos); + case NR_RNTI_SI: + pos = 1; + // Freq domain assignment 0-16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + LOG_D(NR_MAC, "fsize = %i\n", fsize); + for (int i = 0; i < fsize; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + LOG_D(NR_MAC, "dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + // Time domain assignment 4 bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + LOG_D(NR_MAC, "dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + // VRB to PRB mapping 1 bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++); + LOG_D(NR_MAC, "dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val); + // MCS 5bit //bit over 32, so dci_pdu ++ + for (int i = 0; i < 5; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); + LOG_D(NR_MAC, "dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); + // Redundancy version 2bit + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++); + LOG_D(NR_MAC, "dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + // System information indicator 1bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->system_info_indicator&1)<<(dci_size-pos++); + LOG_D(NR_MAC, "dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator); + break; - // Carrier indicator - pos+=dci_pdu_rel15->carrier_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val&((1<carrier_indicator.nbits)-1))<<(dci_size-pos); - - // BWP indicator - pos+=dci_pdu_rel15->bwp_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val&((1<bwp_indicator.nbits)-1))<<(dci_size-pos); - - // Frequency domain resource assignment - pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1<frequency_domain_assignment.nbits)-1)) << (dci_size-pos); - - // Time domain resource assignment - pos+=dci_pdu_rel15->time_domain_assignment.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val&((1<time_domain_assignment.nbits)-1)) << (dci_size-pos); - - // VRB-to-PRB mapping - pos+=dci_pdu_rel15->vrb_to_prb_mapping.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&((1<vrb_to_prb_mapping.nbits)-1))<<(dci_size-pos); - - // PRB bundling size indicator - pos+=dci_pdu_rel15->prb_bundling_size_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->prb_bundling_size_indicator.val&((1<prb_bundling_size_indicator.nbits)-1))<<(dci_size-pos); - - // Rate matching indicator - pos+=dci_pdu_rel15->rate_matching_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->rate_matching_indicator.val&((1<rate_matching_indicator.nbits)-1))<<(dci_size-pos); - - // ZP CSI-RS trigger - pos+=dci_pdu_rel15->zp_csi_rs_trigger.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->zp_csi_rs_trigger.val&((1<zp_csi_rs_trigger.nbits)-1)) << (dci_size-pos); - - //TB1 - // MCS 5bit - pos+=5; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); - + case NR_RNTI_TC: + pos = 1; + // indicating a DL DCI format 1bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++); + // Freq domain assignment 0-16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + for (int i = 0; i < fsize; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + // Time domain assignment 4 bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + // VRB to PRB mapping 1 bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++); + // MCS 5bit //bit over 32, so dci_pdu ++ + for (int i = 0; i < 5; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); // New data indicator 1bit - pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&0x1)<<(dci_size-pos); - + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++); + // Redundancy version 2bit + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++); + // HARQ process number 4bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++); + // Downlink assignment index – 2 bits + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->dai[0].val >> (1 - i)) & 1) << (dci_size - pos++); + // TPC command for scheduled PUCCH – 2 bits + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++); + // PUCCH resource indicator – 3 bits + for (int i = 0; i < 3; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->pucch_resource_indicator >> (2 - i)) & 1) << (dci_size - pos++); + // PDSCH-to-HARQ_feedback timing indicator – 3 bits + for (int i = 0; i < 3; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val >> (2 - i)) & 1) << (dci_size - pos++); + + LOG_D(NR_MAC,"N_RB = %i\n", N_RB); + LOG_D(NR_MAC,"dci_size = %i\n", dci_size); + LOG_D(NR_MAC,"fsize = %i\n", fsize); + LOG_D(NR_MAC,"dci_pdu_rel15->format_indicator = %i\n", dci_pdu_rel15->format_indicator); + LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val); + LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); + LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid); + LOG_D(NR_MAC,"dci_pdu_rel15->dai[0].val = %i\n", dci_pdu_rel15->dai[0].val); + LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc); + LOG_D(NR_MAC,"dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = %i\n", dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val); + + break; + } + break; + + case NR_UL_DCI_FORMAT_0_0: + switch (rnti_type) { + case NR_RNTI_C: + LOG_D(NR_MAC,"Filling format 0_0 DCI for CRNTI (size %d bits, format ind %d)\n",dci_size,dci_pdu_rel15->format_indicator); + // indicating a UL DCI format 1bit + pos=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos); + // Freq domain assignment max 16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + pos+=fsize; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos); + // Time domain assignment 4bit + pos += 4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << 4) - 1)) << (dci_size - pos); + // Frequency hopping flag – 1 bit + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos); + // MCS 5 bit + pos+=5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + // New data indicator 1bit + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos); // Redundancy version 2bit pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv&0x3)<<(dci_size-pos); - - //TB2 - // MCS 5bit - pos+=dci_pdu_rel15->mcs2.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs2.val&((1<mcs2.nbits)-1))<<(dci_size-pos); - - // New data indicator 1bit - pos+=dci_pdu_rel15->ndi2.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi2.val&((1<ndi2.nbits)-1))<<(dci_size-pos); - - // Redundancy version 2bit - pos+=dci_pdu_rel15->rv2.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv2.val&((1<rv2.nbits)-1))<<(dci_size-pos); - + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); // HARQ process number 4bit pos+=4; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos); - - // Downlink assignment index - pos+=dci_pdu_rel15->dai[0].nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val&((1<dai[0].nbits)-1))<<(dci_size-pos); - - // TPC command for scheduled PUCCH 2bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); + // TPC command for scheduled PUSCH – 2 bits pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc&0x3)<<(dci_size-pos); - - // PUCCH resource indicator 3bit - pos+=3; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->pucch_resource_indicator&0x7)<<(dci_size-pos); + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos); + // Padding bits + for (int a = pos; a < 32; a++) + *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++); + // UL/SUL indicator – 1 bit + /* commented for now (RK): need to get this from BWP descriptor + if (cfg->pucch_config.pucch_GroupHopping.value) + *dci_pdu |= + ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); + */ - // PDSCH-to-HARQ_feedback timing indicator - pos+=dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val&((1<pdsch_to_harq_feedback_timing_indicator.nbits)-1))<<(dci_size-pos); + LOG_D(NR_MAC,"N_RB = %i\n", N_RB); + LOG_D(NR_MAC,"dci_size = %i\n", dci_size); + LOG_D(NR_MAC,"fsize = %i\n", fsize); + LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->frequency_hopping_flag.val = %i\n", dci_pdu_rel15->frequency_hopping_flag.val); + LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); + LOG_D(NR_MAC,"dci_pdu_rel15->ndi = %i\n", dci_pdu_rel15->ndi); + LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid); + LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc); + LOG_D(NR_MAC,"dci_pdu_rel15->padding = %i\n", dci_pdu_rel15->padding); + break; - // Antenna ports - pos+=dci_pdu_rel15->antenna_ports.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val&((1<antenna_ports.nbits)-1))<<(dci_size-pos); + case NFAPI_NR_RNTI_TC: + // indicating a UL DCI format 1bit + pos=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos); + // Freq domain assignment max 16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + pos+=fsize; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos); + // Time domain assignment 4bit + pos += 4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << 4) - 1)) << (dci_size - pos); + // Frequency hopping flag – 1 bit + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos); + // MCS 5 bit + pos+=5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + // New data indicator 1bit + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos); + // Redundancy version 2bit + pos+=2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); + // HARQ process number 4bit + pos+=4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); + // Padding bits + for (int a = pos; a < 32; a++) + *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++); + // UL/SUL indicator – 1 bit + /* commented for now (RK): need to get this from BWP descriptor + if (cfg->pucch_config.pucch_GroupHopping.value) + *dci_pdu |= + ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); + */ + LOG_D(NR_MAC,"N_RB = %i\n", N_RB); + LOG_D(NR_MAC,"dci_size = %i\n", dci_size); + LOG_D(NR_MAC,"fsize = %i\n", fsize); + LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->frequency_hopping_flag.val = %i\n", dci_pdu_rel15->frequency_hopping_flag.val); + LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); + LOG_D(NR_MAC,"dci_pdu_rel15->ndi = %i\n", dci_pdu_rel15->ndi); + LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid); + LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc); + LOG_D(NR_MAC,"dci_pdu_rel15->padding = %i\n", dci_pdu_rel15->padding); - // TCI - pos+=dci_pdu_rel15->transmission_configuration_indication.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->transmission_configuration_indication.val&((1<transmission_configuration_indication.nbits)-1))<<(dci_size-pos); - - // SRS request - pos+=dci_pdu_rel15->srs_request.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val&((1<srs_request.nbits)-1))<<(dci_size-pos); - - // CBG transmission information - pos+=dci_pdu_rel15->cbgti.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val&((1<cbgti.nbits)-1))<<(dci_size-pos); - - // CBG flushing out information - pos+=dci_pdu_rel15->cbgfi.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgfi.val&((1<cbgfi.nbits)-1))<<(dci_size-pos); - - // DMRS sequence init - pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&0x1)<<(dci_size-pos); + break; } + break; + + case NR_UL_DCI_FORMAT_0_1: + switch (rnti_type) { + case NR_RNTI_C: + LOG_D(NR_MAC,"Filling NR_UL_DCI_FORMAT_0_1 size %d format indicator %d\n",dci_size,dci_pdu_rel15->format_indicator); + // Indicating a DL DCI format 1bit + pos = 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos); + // Carrier indicator + pos += dci_pdu_rel15->carrier_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val & ((1 << dci_pdu_rel15->carrier_indicator.nbits) - 1)) << (dci_size - pos); + // UL/SUL Indicator + pos += dci_pdu_rel15->ul_sul_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val & ((1 << dci_pdu_rel15->ul_sul_indicator.nbits) - 1)) << (dci_size - pos); + // BWP indicator + pos += dci_pdu_rel15->bwp_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val & ((1 << dci_pdu_rel15->bwp_indicator.nbits) - 1)) << (dci_size - pos); + // Frequency domain resource assignment + pos += dci_pdu_rel15->frequency_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << dci_pdu_rel15->frequency_domain_assignment.nbits) - 1)) << (dci_size - pos); + // Time domain resource assignment + pos += dci_pdu_rel15->time_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << dci_pdu_rel15->time_domain_assignment.nbits) - 1)) << (dci_size - pos); + // Frequency hopping + pos += dci_pdu_rel15->frequency_hopping_flag.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & ((1 << dci_pdu_rel15->frequency_hopping_flag.nbits) - 1)) << (dci_size - pos); + // MCS 5bit + pos += 5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + // New data indicator 1bit + pos += 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 0x1) << (dci_size - pos); + // Redundancy version 2bit + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); + // HARQ process number 4bit + pos += 4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); + // 1st Downlink assignment index + pos += dci_pdu_rel15->dai[0].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val & ((1 << dci_pdu_rel15->dai[0].nbits) - 1)) << (dci_size - pos); + // 2nd Downlink assignment index + pos += dci_pdu_rel15->dai[1].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val & ((1 << dci_pdu_rel15->dai[1].nbits) - 1)) << (dci_size - pos); + // TPC command for scheduled PUSCH 2bit + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos); + // SRS resource indicator + pos += dci_pdu_rel15->srs_resource_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val & ((1 << dci_pdu_rel15->srs_resource_indicator.nbits) - 1)) << (dci_size - pos); + // Precoding info and n. of layers + pos += dci_pdu_rel15->precoding_information.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val & ((1 << dci_pdu_rel15->precoding_information.nbits) - 1)) << (dci_size - pos); + // Antenna ports + pos += dci_pdu_rel15->antenna_ports.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val & ((1 << dci_pdu_rel15->antenna_ports.nbits) - 1)) << (dci_size - pos); + // SRS request + pos += dci_pdu_rel15->srs_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val & ((1 << dci_pdu_rel15->srs_request.nbits) - 1)) << (dci_size - pos); + // CSI request + pos += dci_pdu_rel15->csi_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val & ((1 << dci_pdu_rel15->csi_request.nbits) - 1)) << (dci_size - pos); + // CBG transmission information + pos += dci_pdu_rel15->cbgti.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val & ((1 << dci_pdu_rel15->cbgti.nbits) - 1)) << (dci_size - pos); + // PTRS DMRS association + pos += dci_pdu_rel15->ptrs_dmrs_association.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val & ((1 << dci_pdu_rel15->ptrs_dmrs_association.nbits) - 1)) << (dci_size - pos); + // Beta offset indicator + pos += dci_pdu_rel15->beta_offset_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val & ((1 << dci_pdu_rel15->beta_offset_indicator.nbits) - 1)) << (dci_size - pos); + // DMRS sequence initialization + pos += dci_pdu_rel15->dmrs_sequence_initialization.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val & ((1 << dci_pdu_rel15->dmrs_sequence_initialization.nbits) - 1)) << (dci_size - pos); + // UL-SCH indicator + pos += 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator & 0x1) << (dci_size - pos); + break; + } + break; + + case NR_DL_DCI_FORMAT_1_1: + // Indicating a DL DCI format 1bit + LOG_D(NR_MAC,"Filling Format 1_1 DCI of size %d\n",dci_size); + pos = 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos); + // Carrier indicator + pos += dci_pdu_rel15->carrier_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val & ((1 << dci_pdu_rel15->carrier_indicator.nbits) - 1)) << (dci_size - pos); + // BWP indicator + pos += dci_pdu_rel15->bwp_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val & ((1 << dci_pdu_rel15->bwp_indicator.nbits) - 1)) << (dci_size - pos); + // Frequency domain resource assignment + pos += dci_pdu_rel15->frequency_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << dci_pdu_rel15->frequency_domain_assignment.nbits) - 1)) << (dci_size - pos); + // Time domain resource assignment + pos += dci_pdu_rel15->time_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << dci_pdu_rel15->time_domain_assignment.nbits) - 1)) << (dci_size - pos); + // VRB-to-PRB mapping + pos += dci_pdu_rel15->vrb_to_prb_mapping.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & ((1 << dci_pdu_rel15->vrb_to_prb_mapping.nbits) - 1)) << (dci_size - pos); + // PRB bundling size indicator + pos += dci_pdu_rel15->prb_bundling_size_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->prb_bundling_size_indicator.val & ((1 << dci_pdu_rel15->prb_bundling_size_indicator.nbits) - 1)) << (dci_size - pos); + // Rate matching indicator + pos += dci_pdu_rel15->rate_matching_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rate_matching_indicator.val & ((1 << dci_pdu_rel15->rate_matching_indicator.nbits) - 1)) << (dci_size - pos); + // ZP CSI-RS trigger + pos += dci_pdu_rel15->zp_csi_rs_trigger.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->zp_csi_rs_trigger.val & ((1 << dci_pdu_rel15->zp_csi_rs_trigger.nbits) - 1)) << (dci_size - pos); + // TB1 + // MCS 5bit + pos += 5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + // New data indicator 1bit + pos += 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 0x1) << (dci_size - pos); + // Redundancy version 2bit + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); + // TB2 + // MCS 5bit + pos += dci_pdu_rel15->mcs2.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs2.val & ((1 << dci_pdu_rel15->mcs2.nbits) - 1)) << (dci_size - pos); + // New data indicator 1bit + pos += dci_pdu_rel15->ndi2.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi2.val & ((1 << dci_pdu_rel15->ndi2.nbits) - 1)) << (dci_size - pos); + // Redundancy version 2bit + pos += dci_pdu_rel15->rv2.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv2.val & ((1 << dci_pdu_rel15->rv2.nbits) - 1)) << (dci_size - pos); + // HARQ process number 4bit + pos += 4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); + // Downlink assignment index + pos += dci_pdu_rel15->dai[0].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val & ((1 << dci_pdu_rel15->dai[0].nbits) - 1)) << (dci_size - pos); + // TPC command for scheduled PUCCH 2bit + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos); + // PUCCH resource indicator 3bit + pos += 3; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->pucch_resource_indicator & 0x7) << (dci_size - pos); + // PDSCH-to-HARQ_feedback timing indicator + pos += dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val & ((1 << dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits) - 1)) << (dci_size - pos); + // Antenna ports + pos += dci_pdu_rel15->antenna_ports.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val & ((1 << dci_pdu_rel15->antenna_ports.nbits) - 1)) << (dci_size - pos); + // TCI + pos += dci_pdu_rel15->transmission_configuration_indication.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->transmission_configuration_indication.val & ((1 << dci_pdu_rel15->transmission_configuration_indication.nbits) - 1)) << (dci_size - pos); + // SRS request + pos += dci_pdu_rel15->srs_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val & ((1 << dci_pdu_rel15->srs_request.nbits) - 1)) << (dci_size - pos); + // CBG transmission information + pos += dci_pdu_rel15->cbgti.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val & ((1 << dci_pdu_rel15->cbgti.nbits) - 1)) << (dci_size - pos); + // CBG flushing out information + pos += dci_pdu_rel15->cbgfi.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgfi.val & ((1 << dci_pdu_rel15->cbgfi.nbits) - 1)) << (dci_size - pos); + // DMRS sequence init + pos += 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val & 0x1) << (dci_size - pos); } + LOG_D(NR_MAC, "DCI has %d bits and the payload is %lx\n", dci_size, *dci_pdu); } - - /* - int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space, - nfapi_nr_coreset_t coreset, - uint16_t frame, - uint16_t slot, - nfapi_nr_config_request_scf_t cfg) { - - AssertFatal(search_space.coreset_id==coreset.coreset_id, "Invalid association of coreset(%d) and search space(%d)\n", - search_space.search_space_id, coreset.coreset_id); - - uint8_t is_dci_opportunity=0; - uint16_t Ks=search_space.slot_monitoring_periodicity; - uint16_t Os=search_space.slot_monitoring_offset; - uint8_t Ts=search_space.duration; - - if (((frame*get_spf(&cfg) + slot - Os)%Ks)ssb_config.scs_common.value; @@ -1396,39 +1729,118 @@ int extract_length(int startSymbolAndLength) { } /* - * Dump the UL or DL UE_list into LOG_T(MAC) + * Dump the UL or DL UE_info into LOG_T(MAC) */ -void -dump_nr_ue_list(NR_UE_list_t *listP, - int ul_flag) -//------------------------------------------------------------------------------ +void dump_nr_list(NR_list_t *listP) { - if (ul_flag == 0) { - for (int j = listP->head; j >= 0; j = listP->next[j]) { - LOG_T(MAC, "DL list node %d => %d\n", - j, - listP->next[j]); - } - } else { - for (int j = listP->head_ul; j >= 0; j = listP->next_ul[j]) { - LOG_T(MAC, "UL list node %d => %d\n", - j, - listP->next_ul[j]); - } - } + for (int j = listP->head; j >= 0; j = listP->next[j]) + LOG_T(NR_MAC, "NR list node %d => %d\n", j, listP->next[j]); +} - return; +/* + * Create a new NR_list + */ +void create_nr_list(NR_list_t *list, int len) +{ + list->head = -1; + list->next = calloc(len, sizeof(*list->next)); + AssertFatal(list, "cannot calloc() memory for NR_list_t->next\n"); + for (int i = 0; i < len; ++i) + list->next[i] = -1; + list->tail = -1; + list->len = len; +} + +/* + * Destroy an NR_list + */ +void destroy_nr_list(NR_list_t *list) +{ + free(list->next); +} + +/* + * Add an ID to an NR_list at the end, traversing the whole list. Note: + * add_tail_nr_list() is a faster alternative, but this implementation ensures + * we do not add an existing ID. + */ +void add_nr_list(NR_list_t *listP, int id) +{ + int *cur = &listP->head; + while (*cur >= 0) { + AssertFatal(*cur != id, "id %d already in NR_UE_list!\n", id); + cur = &listP->next[*cur]; + } + *cur = id; + if (listP->next[id] < 0) + listP->tail = id; +} + +/* + * Remove an ID from an NR_list + */ +void remove_nr_list(NR_list_t *listP, int id) +{ + int *cur = &listP->head; + int *prev = &listP->head; + while (*cur != -1 && *cur != id) { + prev = cur; + cur = &listP->next[*cur]; + } + AssertFatal(*cur != -1, "ID %d not found in UE_list\n", id); + int *next = &listP->next[*cur]; + *cur = listP->next[*cur]; + *next = -1; + listP->tail = *prev >= 0 && listP->next[*prev] >= 0 ? listP->tail : *prev; +} + +/* + * Add an ID to the tail of the NR_list in O(1). Note that there is + * corresponding remove_tail_nr_list(), as we cannot set the tail backwards and + * therefore need to go through the whole list (use remove_nr_list()) + */ +void add_tail_nr_list(NR_list_t *listP, int id) +{ + int *last = listP->tail < 0 ? &listP->head : &listP->next[listP->tail]; + *last = id; + listP->next[id] = -1; + listP->tail = id; +} + +/* + * Add an ID to the front of the NR_list in O(1) + */ +void add_front_nr_list(NR_list_t *listP, int id) +{ + const int ohead = listP->head; + listP->head = id; + listP->next[id] = ohead; + if (listP->tail < 0) + listP->tail = id; +} + +/* + * Remove an ID from the front of the NR_list in O(1) + */ +void remove_front_nr_list(NR_list_t *listP) +{ + AssertFatal(listP->head >= 0, "Nothing to remove\n"); + const int ohead = listP->head; + listP->head = listP->next[ohead]; + listP->next[ohead] = -1; + if (listP->head < 0) + listP->tail = -1; } int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP) //------------------------------------------------------------------------------ { int UE_id; - NR_UE_list_t *UE_list = &RC.nrmac[mod_idP]->UE_list; + NR_UE_info_t *UE_info = &RC.nrmac[mod_idP]->UE_info; for (UE_id = 0; UE_id < MAX_MOBILES_PER_GNB; UE_id++) { - if (UE_list->active[UE_id] == TRUE) { - if (UE_list->rnti[UE_id] == rntiP) { + if (UE_info->active[UE_id]) { + if (UE_info->rnti[UE_id] == rntiP) { return UE_id; } } @@ -1437,76 +1849,327 @@ int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP) return -1; } -int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){ +void set_Y(int Y[3][160], rnti_t rnti) { + const int A[3] = {39827, 39829, 39839}; + const int D = 65537; - int UE_id; - int i; - NR_UE_list_t *UE_list = &RC.nrmac[mod_idP]->UE_list; - NR_COMMON_channels_t *cc = RC.nrmac[mod_idP]->common_channels; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - int num_slots_ul = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols>0) - num_slots_ul++; - LOG_I(MAC, "[gNB %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n", + Y[0][0] = (A[0] * rnti) % D; + Y[1][0] = (A[1] * rnti) % D; + Y[2][0] = (A[2] * rnti) % D; + + for (int s = 1; s < 160; s++) { + Y[0][s] = (A[0] * Y[0][s - 1]) % D; + Y[1][s] = (A[1] * Y[1][s - 1]) % D; + Y[2][s] = (A[2] * Y[2][s - 1]) % D; + } +} + +int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP) { +//------------------------------------------------------------------------------ + int RA_id; + RA_t *ra = (RA_t *) &RC.nrmac[mod_idP]->common_channels[CC_idP].ra[0]; + + for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++) { + LOG_D(NR_MAC, "Checking RA_id %d for %x : state %d\n", + RA_id, + rntiP, + ra[RA_id].state); + + if (ra[RA_id].state != IDLE && ra[RA_id].rnti == rntiP) + return RA_id; + } + + return -1; +} + +int get_nrofHARQ_ProcessesForPDSCH(e_NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH n) +{ + switch (n) { + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n2: + return 2; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n4: + return 4; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n6: + return 6; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n10: + return 10; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n12: + return 12; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16: + return 16; + default: + return 8; + } +} + +int get_dl_bwp_id(const NR_ServingCellConfig_t *servingCellConfig) +{ + if (servingCellConfig->firstActiveDownlinkBWP_Id) + return *servingCellConfig->firstActiveDownlinkBWP_Id; + else if (servingCellConfig->defaultDownlinkBWP_Id) + return *servingCellConfig->defaultDownlinkBWP_Id; + else + return 1; +} + +int get_ul_bwp_id(const NR_ServingCellConfig_t *servingCellConfig) +{ + if (servingCellConfig->uplinkConfig && servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id) + return *servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id; + else + return 1; +} + +//------------------------------------------------------------------------------ +int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup) +{ + NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_idP]->common_channels[0].ServingCellConfigCommon; + NR_UE_info_t *UE_info = &RC.nrmac[mod_idP]->UE_info; + LOG_I(NR_MAC, "[gNB %d] Adding UE with rnti 0x%04x (num_UEs %d)\n", mod_idP, rntiP, - UE_list->avail, - UE_list->num_UEs); - dump_nr_ue_list(UE_list, 0); + UE_info->num_UEs); + dump_nr_list(&UE_info->list); - for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { - if (UE_list->active[i] == TRUE) + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + if (UE_info->active[i]) { + LOG_D(NR_MAC,"UE %x is active, skipping\n",rntiP); continue; + } + int UE_id = i; + UE_info->num_UEs++; + UE_info->active[UE_id] = true; + if (CellGroup) UE_info->Msg4_ACKed[UE_id] = true; + else UE_info->Msg4_ACKed[UE_id] = false; + UE_info->rnti[UE_id] = rntiP; + UE_info->CellGroup[UE_id] = CellGroup; + add_nr_list(&UE_info->list, UE_id); + memset(&UE_info->mac_stats[UE_id], 0, sizeof(NR_mac_stats_t)); + set_Y(UE_info->Y[UE_id], rntiP); + if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) + compute_csi_bitlen (CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE_info, UE_id, mod_idP); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + memset(sched_ctrl, 0, sizeof(*sched_ctrl)); + sched_ctrl->lcid_mask = 0; + if (!get_softmodem_params()->phy_test && !get_softmodem_params()->do_ra && !get_softmodem_params()->sa) { + sched_ctrl->lcid_mask = 1<ta_frame = 0; + sched_ctrl->ta_update = 31; + sched_ctrl->ta_apply = false; + sched_ctrl->ul_rssi = 0; + sched_ctrl->pucch_consecutive_dtx_cnt = 0; + sched_ctrl->pusch_consecutive_dtx_cnt = 0; + sched_ctrl->ul_failure = 0; + /* set illegal time domain allocation to force recomputation of all fields */ + sched_ctrl->pdsch_semi_static.time_domain_allocation = -1; + sched_ctrl->pusch_semi_static.time_domain_allocation = -1; + const NR_ServingCellConfig_t *servingCellConfig = CellGroup ? CellGroup->spCellConfig->spCellConfigDedicated : NULL; - UE_id = i; - UE_list->num_UEs++; - UE_list->active[UE_id] = TRUE; - UE_list->rnti[UE_id] = rntiP; - memset((void *) &UE_list->UE_sched_ctrl[UE_id], - 0, - sizeof(NR_UE_sched_ctrl_t)); - UE_list->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch *)malloc(num_slots_ul*sizeof(NR_sched_pucch)); - LOG_I(MAC, "gNB %d] Add NR UE_id %d : rnti %x\n", + /* Set default BWPs */ + const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig ? servingCellConfig->downlinkBWP_ToAddModList : NULL; + if (bwpList) AssertFatal(bwpList->list.count == 1, + "downlinkBWP_ToAddModList has %d BWP!\n", + bwpList->list.count); + const int bwp_id = servingCellConfig ? *servingCellConfig->firstActiveDownlinkBWP_Id : 0; + sched_ctrl->active_bwp = bwpList && bwp_id > 0 ? bwpList->list.array[bwp_id - 1] : NULL; + const int target_ss = sched_ctrl->active_bwp ? NR_SearchSpace__searchSpaceType_PR_ue_Specific : NR_SearchSpace__searchSpaceType_PR_common; + sched_ctrl->search_space = get_searchspace(scc, + sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Dedicated : NULL, + target_ss); + sched_ctrl->coreset = get_coreset(mod_idP, scc, + sched_ctrl->active_bwp ? (void*)sched_ctrl->active_bwp->bwp_Dedicated : NULL, + sched_ctrl->search_space, target_ss); + const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig ? servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList : NULL; + if (ubwpList) AssertFatal(ubwpList->list.count == 1, + "uplinkBWP_ToAddModList has %d BWP!\n", + ubwpList->list.count); + const int ul_bwp_id = servingCellConfig ? *servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id : 0; + sched_ctrl->active_ubwp = ubwpList && ul_bwp_id > 0 ? ubwpList->list.array[ul_bwp_id - 1] : NULL; + + /* get Number of HARQ processes for this UE */ + if (servingCellConfig) AssertFatal(servingCellConfig->pdsch_ServingCellConfig->present == NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup, + "no pdsch-ServingCellConfig found for UE %d\n", + UE_id); + const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig ? servingCellConfig->pdsch_ServingCellConfig->choice.setup : NULL; + // add DL HARQ processes for this UE only in NSA + // (SA still doesn't have information on nrofHARQ_ProcessesForPDSCH at this stage) + if (!get_softmodem_params()->sa) + create_dl_harq_list(sched_ctrl,pdsch); + // add all available UL HARQ processes for this UE + // nb of ul harq processes not configurable + create_nr_list(&sched_ctrl->available_ul_harq, 16); + for (int harq = 0; harq < 16; harq++) + add_tail_nr_list(&sched_ctrl->available_ul_harq, harq); + create_nr_list(&sched_ctrl->feedback_ul_harq, 16); + create_nr_list(&sched_ctrl->retrans_ul_harq, 16); + LOG_D(NR_MAC, "[gNB %d] Add NR UE_id %d : rnti %x\n", mod_idP, UE_id, rntiP); - dump_nr_ue_list(UE_list, - 0); + dump_nr_list(&UE_info->list); return (UE_id); } // printf("MAC: cannot add new UE for rnti %x\n", rntiP); - LOG_E(MAC, "error in add_new_ue(), could not find space in UE_list, Dumping UE list\n"); - dump_nr_ue_list(UE_list, - 0); + LOG_E(NR_MAC, "error in add_new_ue(), could not find space in UE_info, Dumping UE list\n"); + dump_nr_list(&UE_info->list); return -1; } + +void create_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl, + const NR_PDSCH_ServingCellConfig_t *pdsch) { + const int nrofHARQ = pdsch && pdsch->nrofHARQ_ProcessesForPDSCH ? + get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8; + // add all available DL HARQ processes for this UE + create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ); + for (int harq = 0; harq < nrofHARQ; harq++) + add_tail_nr_list(&sched_ctrl->available_dl_harq, harq); + create_nr_list(&sched_ctrl->feedback_dl_harq, nrofHARQ); + create_nr_list(&sched_ctrl->retrans_dl_harq, nrofHARQ); +} + +/* hack data to remove UE in the phy */ +int rnti_to_remove[10]; +volatile int rnti_to_remove_count; +pthread_mutex_t rnti_to_remove_mutex = PTHREAD_MUTEX_INITIALIZER; + +void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti) +{ + int UE_id; + int i; + int cc_id; + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + + for (i = 0; i < MAX_MOBILES_PER_GNB; i++) { + + if (UE_info->active[i] != TRUE) + continue; + if (UE_info->rnti[i] != rnti) + continue; + + /* UE found, remove it */ + UE_id = i; + + UE_info->num_UEs--; + UE_info->active[UE_id] = FALSE; + UE_info->rnti[UE_id] = 0; + remove_nr_list(&UE_info->list, UE_id); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + destroy_nr_list(&sched_ctrl->available_dl_harq); + destroy_nr_list(&sched_ctrl->feedback_dl_harq); + destroy_nr_list(&sched_ctrl->retrans_dl_harq); + destroy_nr_list(&sched_ctrl->available_ul_harq); + destroy_nr_list(&sched_ctrl->feedback_ul_harq); + destroy_nr_list(&sched_ctrl->retrans_ul_harq); + LOG_I(NR_MAC, "[gNB %d] Remove NR UE_id %d: rnti 0x%04x\n", + mod_id, + UE_id, + rnti); + + /* hack to remove UE in the phy */ + if (pthread_mutex_lock(&rnti_to_remove_mutex)) exit(1); + if (rnti_to_remove_count == 10) exit(1); + rnti_to_remove[rnti_to_remove_count] = rnti; + LOG_W(NR_MAC, "to remove in mac rnti_to_remove[%d] = 0x%04x\n", rnti_to_remove_count, rnti); + rnti_to_remove_count++; + if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); + } + + /* clear RA process(es?) associated to the UE */ + for (cc_id = 0; cc_id < NFAPI_CC_MAX; cc_id++) { + NR_COMMON_channels_t *cc = &RC.nrmac[mod_id]->common_channels[cc_id]; + for (i = 0; i < NR_NB_RA_PROC_MAX; i++) { + if (cc->ra[i].rnti == rnti) { + LOG_D(NR_MAC, "free RA process %d for rnti %d\n", i, rnti); + /* is it enough? */ + cc->ra[i].cfra = false; + cc->ra[i].rnti = 0; + cc->ra[i].crnti = 0; + } + } + } +} + +void nr_mac_remove_ra_rnti(module_id_t mod_id, rnti_t rnti) { + // Hack to remove UE in the phy (following the same procedure as in function mac_remove_nr_ue) + if (pthread_mutex_lock(&rnti_to_remove_mutex)) exit(1); + if (rnti_to_remove_count == 10) exit(1); + rnti_to_remove[rnti_to_remove_count] = rnti; + LOG_W(NR_MAC, "to remove in mac rnti_to_remove[%d] = 0x%04x\n", rnti_to_remove_count, rnti); + rnti_to_remove_count++; + if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); +} + +uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) { + // al values passed to this function are x10 + int snrx10 = (cqi*5) - 640; + if (snrx10 > target + incr) return 0; // decrease 1dB + if (snrx10 < target - (3*incr)) return 3; // increase 3dB + if (snrx10 < target - incr) return 2; // increase 1dB + LOG_D(NR_MAC,"tpc : target %d, snrx10 %d\n",target,snrx10); + return 1; // no change +} + + void get_pdsch_to_harq_feedback(int Mod_idP, int UE_id, + int bwp_id, NR_SearchSpace__searchSpaceType_PR ss_type, + int *max_fb_time, uint8_t *pdsch_to_harq_feedback) { - int bwp_id=1; - NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; - NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id]; - NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id]; + NR_BWP_DownlinkDedicated_t *bwpd=NULL; + NR_BWP_UplinkDedicated_t *ubwpd=NULL; - NR_SearchSpace_t *ss; + if (ss_type == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { + AssertFatal(CellGroup!=NULL,"Cellgroup is not defined for UE_id %d\n",UE_id); + AssertFatal(CellGroup->spCellConfig!=NULL,"Cellgroup->spCellConfig is null\n"); + AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated!=NULL,"CellGroup->spCellConfig->spCellConfigDedicated is null\n"); + } + if (bwp_id>0) { + AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList!=NULL, + "CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList is null\n"); + AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList!=NULL, + "CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList is null\n"); + AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count >= bwp_id, + "CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count %d < bwp_id %d\n", + CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count,bwp_id); + AssertFatal(CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count >= bwp_id, + "CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count %d < bwp_id %d\n", + CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count,bwp_id); + + bwpd = CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated; + ubwpd = CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]->bwp_Dedicated; + } + else if (CellGroup) { // this is an initialBWP + AssertFatal((bwpd=CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP)!=NULL, + "CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP is null\n"); + AssertFatal((ubwpd=CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP)!=NULL, + "CellGroup->spCellConfig->spCellConfigDedicated->uplnikConfig->initialUplinkBWP is null\n"); + } + NR_SearchSpace_t *ss=NULL; // common search type uses DCI format 1_0 if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) { - for (int i=0; i<8; i++) + for (int i=0; i<8; i++) { pdsch_to_harq_feedback[i] = i+1; + if(pdsch_to_harq_feedback[i]>*max_fb_time) + *max_fb_time = pdsch_to_harq_feedback[i]; + } } else { // searching for a ue specific search space int found=0; - - for (int i=0;ibwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) { - ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; + AssertFatal(bwpd->pdcch_Config!=NULL,"bwpd->pdcch_Config is null\n"); + AssertFatal(bwpd->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL, + "bwpd->pdcch_Config->choice.setup->searchSpacesToAddModList is null\n"); + for (int i=0;ipdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) { + ss=bwpd->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n"); AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n"); if (ss->searchSpaceType->present == ss_type) { @@ -1518,13 +2181,20 @@ void get_pdsch_to_harq_feedback(int Mod_idP, if (ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_0_And_1_0) { - for (int i=0; i<8; i++) + for (int i=0; i<8; i++) { pdsch_to_harq_feedback[i] = i+1; + if(pdsch_to_harq_feedback[i]>*max_fb_time) + *max_fb_time = pdsch_to_harq_feedback[i]; + } } else { - if(ubwp->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK != NULL) { - for (int i=0; i<8; i++) - pdsch_to_harq_feedback[i] = *ubwp->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[i]; + AssertFatal(ubwpd!=NULL,"ubwpd shouldn't be null here\n"); + if(ubwpd->pucch_Config->choice.setup->dl_DataToUL_ACK != NULL) { + for (int i=0; i<8; i++) { + pdsch_to_harq_feedback[i] = *ubwpd->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[i]; + if(pdsch_to_harq_feedback[i]>*max_fb_time) + *max_fb_time = pdsch_to_harq_feedback[i]; + } } else AssertFatal(0==1,"There is no allocated dl_DataToUL_ACK for pdsch to harq feedback\n"); @@ -1532,81 +2202,238 @@ void get_pdsch_to_harq_feedback(int Mod_idP, } } -// function to update pucch scheduling parameters in UE list when a USS DL is scheduled -void nr_update_pucch_scheduling(int Mod_idP, - int UE_id, - frame_t frameP, - sub_frame_t slotP, - int slots_per_tdd, - int *pucch_id) { - NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; - NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; - NR_sched_pucch *curr_pucch; - int first_ul_slot_tdd,k,i; - uint8_t pdsch_to_harq_feedback[8]; - int found = 0; - int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) - nr_ulmix_slots++; - // this is hardcoded for now as ue specific - NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback); +void nr_csirs_scheduling(int Mod_idP, + frame_t frame, + sub_frame_t slot, + int n_slots_frame){ - // for each possible ul or mixed slot - for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k]; - // if there is free room in current pucch structure - if (curr_pucch->dai_cframe = frameP; - curr_pucch->dai_c++; - curr_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource - // first pucch occasion in first UL or MIXED slot - first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; - i = 0; - while (i<8 && found == 0) { // look if timing indicator is among allowed values - if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd)) - found = 1; - if (found == 0) i++; - } - if (found == 1) { - // computing slot in which pucch is scheduled - curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd)); - curr_pucch->timing_indicator = i; // index in the list of timing indicators - *pucch_id = k; - return; + int CC_id = 0; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_list_t *UE_list = &UE_info->list; + gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; + uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map; + + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id]; + + if (!CellGroup || !CellGroup->spCellConfig || !CellGroup->spCellConfig->spCellConfigDedicated || + !CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig) continue; + + NR_CSI_MeasConfig_t *csi_measconfig = CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + + if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList != NULL) { + + NR_NZP_CSI_RS_Resource_t *nzpcsi; + int period, offset; + + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + NR_BWP_Downlink_t *bwp=CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[sched_ctrl->active_bwp->bwp_Id-1]; + + for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){ + nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id]; + NR_CSI_RS_ResourceMapping_t resourceMapping = nzpcsi->resourceMapping; + csi_period_offset(NULL,nzpcsi,&period,&offset); + + if((frame*n_slots_frame+slot-offset)%period == 0) { + + LOG_I(MAC,"Scheduling CSI-RS in frame %d slot %d\n",frame,slot); + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_csirs_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset((void*)dl_tti_csirs_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_csirs_pdu->PDUType = NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE; + dl_tti_csirs_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_csi_rs_pdu)); + + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csirs_pdu_rel15 = &dl_tti_csirs_pdu->csi_rs_pdu.csi_rs_pdu_rel15; + + csirs_pdu_rel15->bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + csirs_pdu_rel15->bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + csirs_pdu_rel15->subcarrier_spacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; + if (bwp->bwp_Common->genericParameters.cyclicPrefix) + csirs_pdu_rel15->cyclic_prefix = *bwp->bwp_Common->genericParameters.cyclicPrefix; + else + csirs_pdu_rel15->cyclic_prefix = 0; + + csirs_pdu_rel15->start_rb = resourceMapping.freqBand.startingRB; + csirs_pdu_rel15->nr_of_rbs = resourceMapping.freqBand.nrofRBs; + csirs_pdu_rel15->csi_type = 1; // NZP-CSI-RS + csirs_pdu_rel15->symb_l0 = resourceMapping.firstOFDMSymbolInTimeDomain; + if (resourceMapping.firstOFDMSymbolInTimeDomain2) + csirs_pdu_rel15->symb_l1 = *resourceMapping.firstOFDMSymbolInTimeDomain2; + csirs_pdu_rel15->cdm_type = resourceMapping.cdm_Type; + csirs_pdu_rel15->freq_density = resourceMapping.density.present; + if ((resourceMapping.density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5) + && (resourceMapping.density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs)) + csirs_pdu_rel15->freq_density--; + csirs_pdu_rel15->scramb_id = nzpcsi->scramblingID; + csirs_pdu_rel15->power_control_offset = nzpcsi->powerControlOffset + 8; + if (nzpcsi->powerControlOffsetSS) + csirs_pdu_rel15->power_control_offset_ss = *nzpcsi->powerControlOffsetSS; + else + csirs_pdu_rel15->power_control_offset_ss = 1; // 0 dB + switch(resourceMapping.frequencyDomainAllocation.present){ + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1: + csirs_pdu_rel15->row = 1; + csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row1.buf[0])>>4)&0x0f; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (1 << csirs_pdu_rel15->symb_l0); + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2: + csirs_pdu_rel15->row = 2; + csirs_pdu_rel15->freq_domain = (((resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]>>4)&0x0f) | + ((resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]<<8)&0xff0)); + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (1 << csirs_pdu_rel15->symb_l0); + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4: + csirs_pdu_rel15->row = 4; + csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.row4.buf[0])>>5)&0x07; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (1 << csirs_pdu_rel15->symb_l0); + break; + case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other: + csirs_pdu_rel15->freq_domain = ((resourceMapping.frequencyDomainAllocation.choice.other.buf[0])>>2)&0x3f; + // determining the row of table 7.4.1.5.3-1 in 38.211 + switch(resourceMapping.nrofPorts){ + case NR_CSI_RS_ResourceMapping__nrofPorts_p1: + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p2: + csirs_pdu_rel15->row = 3; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (1 << csirs_pdu_rel15->symb_l0); + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p4: + csirs_pdu_rel15->row = 5; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p8: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { + csirs_pdu_rel15->row = 8; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); + } + else{ + int num_k = 0; + for (int k=0; k<6; k++) + num_k+=(((csirs_pdu_rel15->freq_domain)>>k)&0x01); + if(num_k==4) { + csirs_pdu_rel15->row = 6; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (1 << csirs_pdu_rel15->symb_l0); + } + else { + csirs_pdu_rel15->row = 7; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); + } + } + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p12: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { + csirs_pdu_rel15->row = 10; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); + } + else { + csirs_pdu_rel15->row = 9; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (1 << csirs_pdu_rel15->symb_l0); + } + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p16: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) + csirs_pdu_rel15->row = 12; + else + csirs_pdu_rel15->row = 11; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((1 << csirs_pdu_rel15->symb_l0) | (2 << csirs_pdu_rel15->symb_l0)); + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p24: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { + csirs_pdu_rel15->row = 14; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); + } + else{ + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) { + csirs_pdu_rel15->row = 15; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (7 << csirs_pdu_rel15->symb_l0); + } + else { + csirs_pdu_rel15->row = 13; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); + } + } + break; + case NR_CSI_RS_ResourceMapping__nrofPorts_p32: + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2) { + csirs_pdu_rel15->row = 17; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); + } + else{ + if (resourceMapping.cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4) { + csirs_pdu_rel15->row = 18; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= (7 << csirs_pdu_rel15->symb_l0); + } + else { + csirs_pdu_rel15->row = 16; + for (int rb = csirs_pdu_rel15->start_rb; rb < (csirs_pdu_rel15->start_rb + csirs_pdu_rel15->nr_of_rbs); rb++) + vrb_map[rb+csirs_pdu_rel15->bwp_start] |= ((3 << csirs_pdu_rel15->symb_l0) | (3 << csirs_pdu_rel15->symb_l1)); + } + } + break; + default: + AssertFatal(1==0,"Invalid number of ports in CSI-RS resource\n"); + } + break; + default: + AssertFatal(1==0,"Invalid freqency domain allocation in CSI-RS resource\n"); + } + dl_req->nPDUs++; + } } } } - AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n"); } +bool find_free_CCE(module_id_t module_id, + sub_frame_t slot, + int UE_id){ + NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id]; + uint8_t nr_of_candidates; + for (int i=0; i<5; i++) { + // for now taking the lowest value among the available aggregation levels + find_aggregation_candidates(&sched_ctrl->aggregation_level, + &nr_of_candidates, + sched_ctrl->search_space, + 1<0) break; + } + AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n"); + const int cid = sched_ctrl->coreset->controlResourceSetId; + const uint16_t Y = RC.nrmac[module_id]->UE_info.Y[UE_id][cid][slot]; + const int m = RC.nrmac[module_id]->UE_info.num_pdcch_cand[UE_id][cid]; + if (UE_id >= 0) LOG_D(NR_MAC,"calling allocate_nr_CCEs with L %d, nr_of_candidates %d, Y %x\n",sched_ctrl->aggregation_level,nr_of_candidates,Y); + sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], + sched_ctrl->active_bwp, + sched_ctrl->coreset, + sched_ctrl->aggregation_level, + Y, + m, + nr_of_candidates); + if (sched_ctrl->cce_index < 0) + return false; -void find_aggregation_candidates(uint8_t *aggregation_level, - uint8_t *nr_of_candidates, - NR_SearchSpace_t *ss) { - - if (ss->nrofCandidates->aggregationLevel1 != NR_SearchSpace__nrofCandidates__aggregationLevel1_n0) { - *aggregation_level = 1; - *nr_of_candidates = ss->nrofCandidates->aggregationLevel1; - } - if (ss->nrofCandidates->aggregationLevel2 != NR_SearchSpace__nrofCandidates__aggregationLevel2_n0) { - *aggregation_level = 2; - *nr_of_candidates = ss->nrofCandidates->aggregationLevel2; - } - if (ss->nrofCandidates->aggregationLevel4 != NR_SearchSpace__nrofCandidates__aggregationLevel4_n0) { - *aggregation_level = 4; - *nr_of_candidates = ss->nrofCandidates->aggregationLevel4; - } - if (ss->nrofCandidates->aggregationLevel8 != NR_SearchSpace__nrofCandidates__aggregationLevel8_n0) { - *aggregation_level = 8; - *nr_of_candidates = ss->nrofCandidates->aggregationLevel8; - } - if (ss->nrofCandidates->aggregationLevel16 != NR_SearchSpace__nrofCandidates__aggregationLevel16_n0) { - *aggregation_level = 16; - *nr_of_candidates = ss->nrofCandidates->aggregationLevel16; - } + RC.nrmac[module_id]->UE_info.num_pdcch_cand[UE_id][cid]++; + return true; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c new file mode 100644 index 0000000000..a94559769d --- /dev/null +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -0,0 +1,1545 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file gNB_scheduler_uci.c + * \brief MAC procedures related to UCI + * \date 2020 + * \version 1.0 + * \company Eurecom + */ + +#include +#include "LAYER2/MAC/mac.h" +#include "NR_MAC_gNB/nr_mac_gNB.h" +#include "NR_MAC_COMMON/nr_mac_extern.h" +#include "NR_MAC_gNB/mac_proto.h" +#include "common/ran_context.h" +#include "nfapi/oai_integration/vendor_ext.h" + +extern RAN_CONTEXT_t RC; + + +void nr_fill_nfapi_pucch(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const NR_sched_pucch_t *pucch, + int UE_id) +{ + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + + nfapi_nr_ul_tti_request_t *future_ul_tti_req = + &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot]; + AssertFatal(future_ul_tti_req->SFN == pucch->frame + && future_ul_tti_req->Slot == pucch->ul_slot, + "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n", + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + pucch->frame, + pucch->ul_slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t); + nfapi_nr_pucch_pdu_t *pucch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pucch_pdu; + memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t)); + future_ul_tti_req->n_pdus += 1; + + LOG_D(NR_MAC, + "%s %4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, DAI %d, CSI %d on res %d\n", + pucch->dai_c>0 ? "pucch_acknak" : "", + frame, + slot, + pucch->frame, + pucch->ul_slot, + pucch->sr_flag, + pucch->dai_c, + pucch->csi_bits, + pucch->resource_indicator); + + NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + NR_CellGroupConfig_t *cg=UE_info->CellGroup[UE_id]; + + NR_BWP_UplinkDedicated_t *ubwpd; + ubwpd = cg ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP:NULL; + + LOG_D(NR_MAC,"pucch_acknak: %d.%d Calling nr_configure_pucch (ubwpd %p,r_pucch %d) pucch in %d.%d\n",frame,slot,ubwpd,pucch->r_pucch,pucch->frame,pucch->ul_slot); + nr_configure_pucch(pucch_pdu, + scc, + UE_info->CellGroup[UE_id], + UE_info->UE_sched_ctrl[UE_id].active_ubwp, + ubwpd, + UE_info->rnti[UE_id], + pucch->resource_indicator, + pucch->csi_bits, + pucch->dai_c, + pucch->sr_flag, + pucch->r_pucch); +} + +#define MIN_RSRP_VALUE -141 +#define MAX_NUM_SSB 128 +#define MAX_SSB_SCHED 8 +#define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any +//#define L1_DIFF_RSRP_STEP_SIZE 2 + +int ssb_index_sorted[MAX_NUM_SSB] = {0}; +int ssb_rsrp_sorted[MAX_NUM_SSB] = {0}; + +//Measured RSRP Values Table 10.1.16.1-1 from 36.133 +//Stored all the upper limits[Max RSRP Value of corresponding index] +//stored -1 for invalid values +int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9 + -1, -1, -1, -1, -1, -1, INT_MIN, -140, -139, -138, //10 - 19 + -137, -136, -135, -134, -133, -132, -131, -130, -129, -128, //20 - 29 + -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, //30 - 39 + -117,-116, -115, -114, -113, -112, -111, -110, -109, -108, //40 - 49 + -107, -106, -105, -104, -103, -102, -101, -100, -99, -98, //50 - 59 + -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, //60 - 69 + -87, -86, -85, -84, -83, -82, -81, -80, -79, -78, //70 - 79 + -77, -76, -75, -74, -73, -72, -71, -70, -69, -68, //80 - 89 + -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, //90 - 99 + -57, -56, -55, -54, -53, -52, -51, -50, -49, -48, //100 - 109 + -47, -46, -45, -44, INT_MAX, -1, -1, -1, -1, -1, //110 - 119 + -1, -1, -1, -1, -1, -1, -1, -1//120 - 127 + }; + +//Differential RSRP values Table 10.1.6.1-2 from 36.133 +//Stored the upper limits[MAX RSRP Value] +int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { + 0, -2, -4, -6, -8, -10, -12, -14, -16, -18, //0 - 9 + -20, -22, -24, -26, -28, -30 //10 - 15 +}; + + +void nr_schedule_pucch(int Mod_idP, + frame_t frameP, + sub_frame_t slotP) +{ + gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP]; + if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slotP / 64], slotP)) + return; + + NR_UE_info_t *UE_info = &nrmac->UE_info; + const NR_list_t *UE_list = &UE_info->list; + + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue; + const int n = sizeof(sched_ctrl->sched_pucch) / sizeof(*sched_ctrl->sched_pucch); + for (int i = 0; i < n; i++) { + NR_sched_pucch_t *curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[i]; + const uint16_t O_ack = curr_pucch->dai_c; + const uint16_t O_csi = curr_pucch->csi_bits; + const uint8_t O_sr = curr_pucch->sr_flag; + if (O_ack + O_csi + O_sr == 0 + || frameP != curr_pucch->frame + || slotP != curr_pucch->ul_slot) + continue; + LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); + nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id); + memset(curr_pucch, 0, sizeof(*curr_pucch)); + } + } +} + + +//! Calculating number of bits set +uint8_t number_of_bits_set (uint8_t buf,uint8_t * max_ri){ + uint8_t nb_of_bits_set = 0; + uint8_t mask = 0xff; + uint8_t index = 0; + + for (index=7; (buf & mask) && (index>=0) ; index--){ + if (buf & (1<>=1; + } + *max_ri = 8-index; + return nb_of_bits_set; +} + + +void compute_rsrp_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t nb_resources, + nr_csi_report_t *csi_report){ + + if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) { + if (NULL != csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; + else + /*! From Spec 38.331 + * nrofReportedRS + * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE + * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. + * When the field is absent the UE applies the value 1 + */ + csi_report->CSI_report_bitlen.nb_ssbri_cri= 1; + } else + csi_report->CSI_report_bitlen.nb_ssbri_cri= 2; + + if (nb_resources) { + csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_resources)); + csi_report->CSI_report_bitlen.rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + csi_report->CSI_report_bitlen.diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + } else { + csi_report->CSI_report_bitlen.cri_ssbri_bitlen =0; + csi_report->CSI_report_bitlen.rsrp_bitlen = 0; + csi_report->CSI_report_bitlen.diff_rsrp_bitlen =0; + } +} + + +uint8_t compute_ri_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + nr_csi_report_t *csi_report){ + + struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; + uint8_t nb_allowed_ri, ri_restriction,ri_bitlen; + uint8_t max_ri = 0; + + if (codebookConfig == NULL) { + csi_report->csi_meas_bitlen.ri_bitlen=0; + return max_ri; + } + + // codebook type1 single panel + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==codebookConfig->codebookType.choice.type1->subType.present){ + struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel; + if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two){ + // two antenna ports case + /* From Spec 38.212 + * If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator + * values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6, + * TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause + * 5.2.2.2.1 [6, TS 38.214]. + * + * But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to + * calculate RI for antennas equal or more than two. + * */ + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present */ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0), &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction, &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + ri_bitlen = ri_bitlen<1?ri_bitlen:1; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + } + if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo){ + if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present == + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) { + // 4 ports + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present*/ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0), &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction,&max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + ri_bitlen = ri_bitlen<2?ri_bitlen:2; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + } + else { + // more than 4 ports + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present */ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0),&max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction, &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + } + } + return max_ri; + } + else + AssertFatal(1==0,"Other configurations not yet implemented\n"); + return -1; +} + +void compute_li_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t max_ri, + nr_csi_report_t *csi_report){ + + struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; + if (codebookConfig == NULL) { + csi_report->csi_meas_bitlen.li_bitlen=0; + return; + } + // codebook type1 single panel + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==codebookConfig->codebookType.choice.type1->subType.present){ + /* From Spec 38.212 + * If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator + * values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6, + * TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause + * 5.2.2.2.1 [6, TS 38.214]. + * + * But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to + * calculate RI for antennas equal or more than two. + */ + //! TODO: The bit length of LI is as follows LI = log2(RI), Need to confirm wheather we should consider maximum RI can be reported from ri_restricted + // or we should consider reported RI. If we need to consider reported RI for calculating LI bit length then we need to modify the code. + csi_report->csi_meas_bitlen.li_bitlen=ceil(log2(max_ri))<2?ceil(log2(max_ri)):2; + } + else + AssertFatal(1==0,"Other configurations not yet implemented\n"); +} + + +void compute_cqi_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig, + uint8_t max_ri, + nr_csi_report_t *csi_report){ + + struct NR_CodebookConfig *codebookConfig = csi_reportconfig->codebookConfig; + struct NR_CSI_ReportConfig__reportFreqConfiguration *freq_config = csi_reportconfig->reportFreqConfiguration; + + if (*freq_config->cqi_FormatIndicator == NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI) { + csi_report->csi_meas_bitlen.cqi_bitlen = 4; + if(codebookConfig != NULL) { + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel == codebookConfig->codebookType.choice.type1->subType.present){ + struct NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel *type1single = codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel; + if (type1single->nrOfAntennaPorts.present == NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_moreThanTwo) { + if (type1single->nrOfAntennaPorts.choice.moreThanTwo->n1_n2.present > + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts__moreThanTwo__n1_n2_PR_two_one_TypeI_SinglePanel_Restriction) { + // more than 4 antenna ports + if (max_ri > 4) + csi_report->csi_meas_bitlen.cqi_bitlen += 4; // CQI for second TB + } + } + } + } + } + else + AssertFatal(1==0,"Sub-band CQI reporting not yet supported"); +} + +//!TODO : same function can be written to handle csi_resources +void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP){ + uint8_t csi_report_id = 0; + uint8_t nb_resources = 0; + uint8_t max_ri = 0; + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; + NR_CSI_ResourceConfigId_t csi_ResourceConfigId; + struct NR_CSI_ResourceConfig *csi_resourceconfig; + + // for each CSI measurement report configuration (list of CSI-ReportConfig) + for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + // MAC structure for CSI measurement reports (per UE and per report) + nr_csi_report_t *csi_report = &UE_info->csi_report_template[UE_id][csi_report_id]; + // csi-ResourceConfigId of a CSI-ResourceConfig included in the configuration + // (either CSI-RS or SSB) + csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement; + // looking for CSI-ResourceConfig + int found_resource = 0; + int csi_resourceidx = 0; + while (found_resource == 0 && csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count) { + csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; + if ( csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) + found_resource = 1; + csi_resourceidx++; + } + AssertFatal(found_resource==1,"Not able to found any CSI-ResourceConfig with csi-ResourceConfigId %ld\n", + csi_ResourceConfigId); + + long resourceType = csi_resourceconfig->resourceType; + + reportQuantity_type = csi_reportconfig->reportQuantity.present; + csi_report->reportQuantity_type = reportQuantity_type; + + // setting the CSI or SSB index list + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type) { + for (int csi_idx = 0; csi_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_idx++) { + if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ + //We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig + nb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.count; + csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_idx]->csi_SSB_ResourceList.list.array; + csi_report->CSI_Index_list = NULL; + break; + } + } + } + else { + if (resourceType == NR_CSI_ResourceConfig__resourceType_periodic) { + AssertFatal(csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList != NULL, + "Wrong settings! Report quantity requires CSI-RS but csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList is NULL\n"); + for (int csi_idx = 0; csi_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_idx++) { + if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { + //For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 + nb_resources = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.count; + csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_RS_Resources.list.array; + csi_report->SSB_Index_list = NULL; + break; + } + } + } + else AssertFatal(1==0,"Only periodic resource configuration currently supported\n"); + } + + // computation of bit length depending on the report type + switch(reportQuantity_type){ + case (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP): + compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report); + break; + case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP): + compute_rsrp_bitlen(csi_reportconfig, nb_resources, csi_report); + break; + case (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI): + csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2(nb_resources)); + max_ri = compute_ri_bitlen(csi_reportconfig, csi_report); + compute_cqi_bitlen(csi_reportconfig, max_ri, csi_report); + break; + default: + AssertFatal(1==0,"Not yet supported CSI report quantity type"); + } + } +} + + +uint16_t nr_get_csi_bitlen(int Mod_idP, + int UE_id, + uint8_t csi_report_id) { + + uint16_t csi_bitlen =0; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + L1_RSRP_bitlen_t * CSI_report_bitlen = NULL; + CSI_Meas_bitlen_t * csi_meas_bitlen = NULL; + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP==UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type|| + NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP==UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type){ + CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements + csi_bitlen+= ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + + CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * + (CSI_report_bitlen->nb_ssbri_cri -1 ))); + } else{ + csi_meas_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].csi_meas_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements + csi_bitlen+= (csi_meas_bitlen->cri_bitlen +csi_meas_bitlen->ri_bitlen+csi_meas_bitlen->li_bitlen+csi_meas_bitlen->cqi_bitlen+csi_meas_bitlen->pmi_x1_bitlen+csi_meas_bitlen->pmi_x2_bitlen); + } + + return csi_bitlen; +} + + +void nr_csi_meas_reporting(int Mod_idP, + frame_t frame, + sub_frame_t slot) { + + NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; + const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_list_t *UE_list = &UE_info->list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id]; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue; + if (!CellGroup || !CellGroup->spCellConfig || !CellGroup->spCellConfig->spCellConfigDedicated || + !CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig) continue; + const NR_CSI_MeasConfig_t *csi_measconfig = CellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count > 0, + "NO CSI report configuration available"); + NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup; + + for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + + AssertFatal(csirep->reportConfigType.choice.periodic, + "Only periodic CSI reporting is implemented currently\n"); + int period, offset; + csi_period_offset(csirep, NULL, &period, &offset); + const int sched_slot = (period + offset) % n_slots_frame; + // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214 + // preparation is done in first slot of tdd period + if (frame % (period / n_slots_frame) != offset / n_slots_frame) + continue; + LOG_D(NR_MAC, "CSI reporting in frame %d slot %d\n", frame, sched_slot); + + const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; + const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 + const int n = pucchresset->resourceList.list.count; + int res_index = 0; + for (; res_index < n; res_index++) + if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) + break; + AssertFatal(res_index < n, + "CSI resource not found among PUCCH resources\n"); + + // find free PUCCH that is in order with possibly existing PUCCH + // schedulings (other CSI, SR) + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; + AssertFatal(curr_pucch->csi_bits == 0 + && !curr_pucch->sr_flag + && curr_pucch->dai_c == 0, + "PUCCH not free at index 1 for UE %04x\n", + UE_info->rnti[UE_id]); + curr_pucch->r_pucch = -1; + curr_pucch->frame = frame; + curr_pucch->ul_slot = sched_slot; + curr_pucch->resource_indicator = res_index; + curr_pucch->csi_bits += + nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); + + NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ? + &sched_ctrl->active_ubwp->bwp_Common->genericParameters: + &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + int bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth,MAX_BWP_SIZE); + + // going through the list of PUCCH resources to find the one indexed by resource_id + uint16_t *vrb_map_UL = &RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; + const int m = pucch_Config->resourceToAddModList->list.count; + for (int j = 0; j < m; j++) { + NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j]; + if (pucchres->pucch_ResourceId != *pucchresset->resourceList.list.array[res_index]) + continue; + int start = pucchres->startingPRB; + int len = 1; + uint64_t mask = 0; + switch(pucchres->format.present){ + case NR_PUCCH_Resource__format_PR_format2: + len = pucchres->format.choice.format2->nrofPRBs; + mask = ((1 << pucchres->format.choice.format2->nrofSymbols) - 1) << pucchres->format.choice.format2->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI; + break; + case NR_PUCCH_Resource__format_PR_format3: + len = pucchres->format.choice.format3->nrofPRBs; + mask = ((1 << pucchres->format.choice.format3->nrofSymbols) - 1) << pucchres->format.choice.format3->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI; + break; + case NR_PUCCH_Resource__format_PR_format4: + mask = ((1 << pucchres->format.choice.format4->nrofSymbols) - 1) << pucchres->format.choice.format4->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI; + break; + default: + AssertFatal(0, "Invalid PUCCH format type\n"); + } + // verify resources are free + for (int i = start; i < start + len; ++i) { + vrb_map_UL[i+bwp_start] |= mask; + } + } + } + } +} + +static void handle_dl_harq(module_id_t mod_id, + int UE_id, + int8_t harq_pid, + bool success) +{ + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_harq_t *harq = &UE_info->UE_sched_ctrl[UE_id].harq_processes[harq_pid]; + harq->feedback_slot = -1; + harq->is_waiting = false; + if (success) { + add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid); + harq->round = 0; + harq->ndi ^= 1; + } else if (harq->round >= MAX_HARQ_ROUNDS - 1) { + add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid); + harq->round = 0; + harq->ndi ^= 1; + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + stats->dlsch_errors++; + LOG_D(NR_MAC, "retransmission error for UE %d (total %"PRIu64")\n", UE_id, stats->dlsch_errors); + } else { + add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].retrans_dl_harq, harq_pid); + harq->round++; + } +} + +int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, int Mod_idP, int UE_id) { + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id] ; + int nb_tci_states = CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.count; + NR_TCI_State_t *tci =NULL; + int i; + + for(i=0; ispCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.array[i]; + + if(tci != NULL) { + if(tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t) + return tci->tci_StateId; // returned TCI state ID + } + // if type2 is configured + else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type2->referenceSignal.choice.ssb == ssb_index_t) + return tci->tci_StateId; // returned TCI state ID + } else LOG_I(NR_MAC,"SSB index is not found in first 64 TCI states of TCI_statestoAddModList[%d]", i); + } + } + + // tci state not identified in first 64 TCI States of PDSCH Config + return -1; +} + +int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, int Mod_idP, int UE_id) { + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id] ; + int nb_tci_states = CellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.count; + NR_TCI_State_t *tci =NULL; + NR_TCI_StateId_t *tci_id = NULL; + int bwp_id = 1; + NR_BWP_Downlink_t *bwp = CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + NR_ControlResourceSet_t *coreset = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]; + int i; + int flag = 0; + int tci_stateID = -1; + + for(i=0; ispCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.array[i]; + + if(tci != NULL && tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t) { + flag = 1; + tci_stateID = tci->tci_StateId; + break; + } else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + flag = 1; + tci_stateID = tci->tci_StateId; + break; + } + } + + if(flag != 0 && tci_stateID != -1 && coreset != NULL) { + for(i=0; i<64 && itci_StatesPDCCH_ToAddList->list.count; i++) { + tci_id = coreset->tci_StatesPDCCH_ToAddList->list.array[i]; + + if(tci_id != NULL && *tci_id == tci_stateID) + return tci_stateID; + } + } + } + + // Need to implement once configuration is received + return -1; +} + +//returns the measured RSRP value (upper limit) +int get_measured_rsrp(uint8_t index) { + //if index is invalid returning minimum rsrp -140 + if(index <= 15 || index >= 114) + return MIN_RSRP_VALUE; + + return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index]; +} + +//returns the differential RSRP value (upper limit) +int get_diff_rsrp(uint8_t index, int strongest_rsrp) { + if(strongest_rsrp != -1) { + return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; + } else + return MIN_RSRP_VALUE; +} + +//identifies the target SSB Beam index +//keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally +//handles triggering of PDCCH and PDSCH MAC CEs +void tci_handling(module_id_t Mod_idP, int UE_id, frame_t frame, slot_t slot) { + + int strongest_ssb_rsrp = 0; + int cqi_idx = 0; + int curr_ssb_beam_index = 0; //ToDo: yet to know how to identify the serving ssb beam index + uint8_t target_ssb_beam_index = curr_ssb_beam_index; + uint8_t is_triggering_ssb_beam_switch =0; + uint8_t ssb_idx = 0; + int pdsch_bwp_id =0; + int ssb_index[MAX_NUM_SSB] = {0}; + int ssb_rsrp[MAX_NUM_SSB] = {0}; + uint8_t idx = 0; + int bwp_id = 1; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *CellGroup = UE_info->CellGroup[UE_id]; + NR_BWP_Downlink_t *bwp = CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + //bwp indicator + int n_dl_bwp = CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; + uint8_t nr_ssbri_cri = 0; + uint8_t nb_of_csi_ssb_report = UE_info->csi_report_template[UE_id][cqi_idx].nb_of_csi_ssb_report; + int better_rsrp_reported = -140-(-0); /*minimum_measured_RSRP_value - minimum_differntail_RSRP_value*///considering the minimum RSRP value as better RSRP initially + uint8_t diff_rsrp_idx = 0; + uint8_t i, j; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + if (n_dl_bwp < 4) + pdsch_bwp_id = bwp_id; + else + pdsch_bwp_id = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 + + /*Example: + CRI_SSBRI: 1 2 3 4| 5 6 7 8| 9 10 1 2| + nb_of_csi_ssb_report = 3 //3 sets as above + nr_ssbri_cri = 4 //each set has 4 elements + storing ssb indexes in ssb_index array as ssb_index[0] = 1 .. ssb_index[4] = 5 + ssb_rsrp[0] = strongest rsrp in first set, ssb_rsrp[4] = strongest rsrp in second set, .. + idx: resource set index + */ + + //for all reported SSB + for (idx = 0; idx < nb_of_csi_ssb_report; idx++) { + nr_ssbri_cri = sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri; + //extracting the ssb indexes + for (ssb_idx = 0; ssb_idx < nr_ssbri_cri; ssb_idx++) { + ssb_index[idx * nb_of_csi_ssb_report + ssb_idx] = sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI[ssb_idx]; + } + + //if strongest measured RSRP is configured + strongest_ssb_rsrp = get_measured_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP); + ssb_rsrp[idx * nb_of_csi_ssb_report] = strongest_ssb_rsrp; + LOG_D(NR_MAC,"ssb_rsrp = %d\n",strongest_ssb_rsrp); + + //if current ssb rsrp is greater than better rsrp + if(ssb_rsrp[idx * nb_of_csi_ssb_report] > better_rsrp_reported) { + better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report]; + target_ssb_beam_index = idx * nb_of_csi_ssb_report; + } + + for(diff_rsrp_idx =1; diff_rsrp_idx < nr_ssbri_cri; diff_rsrp_idx++) { + ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] = get_diff_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx-1], strongest_ssb_rsrp); + + //if current reported rsrp is greater than better rsrp + if(ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] > better_rsrp_reported) { + better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx]; + target_ssb_beam_index = idx * nb_of_csi_ssb_report + diff_rsrp_idx; + } + } + } + + + if(ssb_index[target_ssb_beam_index] != ssb_index[curr_ssb_beam_index] && ssb_rsrp[target_ssb_beam_index] > ssb_rsrp[curr_ssb_beam_index]) { + if( ssb_rsrp[target_ssb_beam_index] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + is_triggering_ssb_beam_switch = 1; + LOG_D(NR_MAC, "Triggering ssb beam switching using tci\n"); + } + } + + if(is_triggering_ssb_beam_switch) { + //filling pdcch tci state activativation mac ce structure fields + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 1; + //OAI currently focusing on Non CA usecase hence 0 is considered as serving + //cell id + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.servingCellId = 0; //0 for PCell as 38.331 v15.9.0 page 353 //serving cell id for which this MAC CE applies + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId = 0; //coreset id for which the TCI State id is being indicated + + /* 38.321 v15.8.0 page 66 + TCI State ID: This field indicates the TCI state identified by TCI-StateId as specified in TS 38.331 [5] applicable + to the Control Resource Set identified by CORESET ID field. + If the field of CORESET ID is set to 0, + this field indicates a TCI-StateId for a TCI state of the first 64 TCI-states configured by tci-States-ToAddModList and tciStates-ToReleaseList in the PDSCH-Config in the active BWP. + If the field of CORESET ID is set to the other value than 0, + this field indicates a TCI-StateId configured by tci-StatesPDCCH-ToAddList and tciStatesPDCCH-ToReleaseList in the controlResourceSet identified by the indicated CORESET ID. + The length of the field is 7 bits + */ + if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId == 0) { + int tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index[target_ssb_beam_index], Mod_idP, UE_id); + + if( tci_state_id != -1) + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + else { + //identify the best beam within first 64 TCI States of PDSCH + //Config TCI-states-to-addModList + int flag = 0; + + for(i =0; ssb_index_sorted[i]!=0; i++) { + tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index_sorted[i], Mod_idP, UE_id) ; + + if(tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + flag = 1; + break; + } + } + + if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0; + } + } + } else { + int tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index[target_ssb_beam_index], Mod_idP, UE_id); + + if (tci_state_id !=-1) + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + else { + //identify the best beam within CORESET/PDCCH + ////Config TCI-states-to-addModList + int flag = 0; + + for(i =0; ssb_index_sorted[i]!=0; i++) { + tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index_sorted[i], Mod_idP, UE_id); + + if( tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + flag = 1; + break; + } + } + + if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0; + } + } + } + + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]->tci_PresentInDCI; + + //filling pdsch tci state activation deactivation mac ce structure fields + if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.is_scheduled = 1; + /* + Serving Cell ID: This field indicates the identity of the Serving Cell for which the MAC CE applies + Considering only PCell exists. Serving cell index of PCell is always 0, hence configuring 0 + */ + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.servingCellId = 0; + /* + BWP ID: This field indicates a DL BWP for which the MAC CE applies as the codepoint of the DCI bandwidth + part indicator field as specified in TS 38.212 + */ + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.bwpId = pdsch_bwp_id; + + /* + * TODO ssb_rsrp_sort() API yet to code to find 8 best beams, rrc configuration + * is required + */ + for(i = 0; i<8; i++) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i] = i; + } + + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.highestTciStateActivated = 8; + + for(i = 0, j =0; iUE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i]) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.codepoint[j] = i; + j++; + } + } + }//tci_presentInDCI + }//is-triggering_beam_switch +}//tci handling + + +uint8_t pickandreverse_bits(uint8_t *payload, uint16_t bitlen, uint8_t start_bit) { + uint8_t rev_bits = 0; + for (int i=0; i>((start_bit+i)%8))&0x01)<<(bitlen-i-1); + return rev_bits; +} + + +void evaluate_rsrp_report(NR_UE_info_t *UE_info, + NR_UE_sched_ctrl_t *sched_ctrl, + int UE_id, + uint8_t csi_report_id, + uint8_t *payload, + int *cumul_bits, + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type){ + + uint8_t cri_ssbri_bitlen = UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.cri_ssbri_bitlen; + uint16_t curr_payload; + + /*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report + * the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE + * From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set + * From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 + */ + + /** from 38.214 sec 5.2.1.4.2 + - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE is + not required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in + a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting + + - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE is not + required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in a + single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB + resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with + multiple simultaneous spatial domain receive filter + */ + + int idx = 0; //Since for SSB RSRP reporting in RRC can configure only one ssb resource set per one report config + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri = UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.nb_ssbri_cri; + + for (int csi_ssb_idx = 0; csi_ssb_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri ; csi_ssb_idx++) { + curr_payload = pickandreverse_bits(payload, cri_ssbri_bitlen, *cumul_bits); + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI[csi_ssb_idx] = + *(UE_info->csi_report_template[UE_id][csi_report_id].SSB_Index_list[cri_ssbri_bitlen>0?((curr_payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]); + else + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI[csi_ssb_idx] = + *(UE_info->csi_report_template[UE_id][csi_report_id].CSI_Index_list[cri_ssbri_bitlen>0?((curr_payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]); + + *cumul_bits += cri_ssbri_bitlen; + if(UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type == NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP) + LOG_D(MAC,"CSI-RS Resource Indicator = %d\n",sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI[csi_ssb_idx]); + else + LOG_D(MAC,"SSB Resource Indicator = %d\n",sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI[csi_ssb_idx]); + } + + curr_payload = pickandreverse_bits(payload, 7, *cumul_bits); + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP = curr_payload & 0x7f; + *cumul_bits += 7; + + for (int diff_rsrp_idx =0; diff_rsrp_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri - 1; diff_rsrp_idx++ ) { + curr_payload = pickandreverse_bits(payload, 4, *cumul_bits); + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx] = curr_payload & 0x0f; + *cumul_bits += 4; + } + UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report++; + int strongest_ssb_rsrp = get_measured_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP); + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + // including ssb rsrp in mac stats + stats->cumul_rsrp += strongest_ssb_rsrp; + stats->num_rsrp_meas++; + LOG_D(MAC,"rsrp_id = %d rsrp = %d\n", + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP, + strongest_ssb_rsrp); +} + + +void evaluate_cri_report(uint8_t *payload, + uint8_t cri_bitlen, + int cumul_bits, + NR_UE_sched_ctrl_t *sched_ctrl){ + + int idx = 0; // FIXME not sure about this index. Should it be the same as csi_report_id? + + uint8_t temp_cri = pickandreverse_bits(payload, cri_bitlen, cumul_bits); + sched_ctrl->CSI_report[idx].choice.cri_ri_li_pmi_cqi_report.cri = temp_cri; +} + +void evaluate_ri_report(uint8_t *payload, + uint8_t ri_bitlen, + NR_UE_sched_ctrl_t *sched_ctrl){ + + AssertFatal(1==0,"Evaluation of RI report not yet implemented\n"); +} + + +void evaluate_cqi_report(uint8_t *payload, + uint8_t cqi_bitlen, + int *cumul_bits, + NR_UE_sched_ctrl_t *sched_ctrl){ + + //TODO sub-band CQI report not yet implemented + int idx = 0; // FIXME not sure about this index. Should it be the same as csi_report_id? + + uint8_t temp_cqi = pickandreverse_bits(payload, 4, *cumul_bits); + sched_ctrl->CSI_report[idx].choice.cri_ri_li_pmi_cqi_report.wb_cqi_1tb = temp_cqi; + *cumul_bits += 4; + LOG_I(MAC,"Wide-band CQI for the first TB %d\n", temp_cqi); + if (cqi_bitlen > 4) { + temp_cqi = pickandreverse_bits(payload, 4, *cumul_bits); + sched_ctrl->CSI_report[idx].choice.cri_ri_li_pmi_cqi_report.wb_cqi_2tb = temp_cqi; + LOG_D(MAC,"Wide-band CQI for the second TB %d\n", temp_cqi); + } +} + +void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig, + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu, + frame_t frame, + slot_t slot, + int UE_id, + module_id_t Mod_idP) { + + /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */ + NR_ServingCellConfigCommon_t *scc = + RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; + const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + uint8_t *payload = uci_pdu->csi_part1.csi_part1_payload; + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type = NR_CSI_ReportConfig__reportQuantity_PR_NOTHING; + NR_UE_info_t *UE_info = &(RC.nrmac[Mod_idP]->UE_info); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + int cumul_bits = 0; + for (int csi_report_id = 0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++ ) { + UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = 0; + uint8_t cri_bitlen = 0; + uint8_t ri_bitlen = 0; + uint8_t cqi_bitlen = 0; + NR_CSI_ReportConfig_t *csirep = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + int period, offset; + csi_period_offset(csirep, NULL, &period, &offset); + // verify if report with current id has been scheduled for this frame and slot + if ((n_slots_frame*frame + slot - offset)%period == 0) { + reportQuantity_type = UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type; + LOG_D(MAC,"SFN/SF:%d/%d reportQuantity type = %d\n",frame,slot,reportQuantity_type); + switch(reportQuantity_type){ + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: + evaluate_rsrp_report(UE_info,sched_ctrl,UE_id,csi_report_id,payload,&cumul_bits,reportQuantity_type); + break; + case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP: + evaluate_rsrp_report(UE_info,sched_ctrl,UE_id,csi_report_id,payload,&cumul_bits,reportQuantity_type); + break; + case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI: + cri_bitlen = UE_info->csi_report_template[UE_id][csi_report_id].csi_meas_bitlen.cri_bitlen; + if(cri_bitlen) + evaluate_cri_report(payload,cri_bitlen,cumul_bits,sched_ctrl); + cumul_bits += cri_bitlen; + ri_bitlen = UE_info->csi_report_template[UE_id][csi_report_id].csi_meas_bitlen.ri_bitlen; + if(ri_bitlen) + evaluate_ri_report(payload,ri_bitlen,sched_ctrl); + cumul_bits += ri_bitlen; + //TODO add zero padding bits when needed + cqi_bitlen = UE_info->csi_report_template[UE_id][csi_report_id].csi_meas_bitlen.cqi_bitlen; + if(cqi_bitlen) + evaluate_cqi_report(payload,cqi_bitlen,&cumul_bits,sched_ctrl); + break; + default: + AssertFatal(1==0, "Invalid or not supported CSI measurement report\n"); + } + } + } +} + +static NR_UE_harq_t *find_harq(module_id_t mod_id, frame_t frame, sub_frame_t slot, int UE_id) +{ + /* In case of realtime problems: we can only identify a HARQ process by + * timing. If the HARQ process's feedback_frame/feedback_slot is not the one we + * expected, we assume that processing has been aborted and we need to + * skip this HARQ process, which is what happens in the loop below. + * Similarly, we might be "in advance", in which case we need to skip + * this result. */ + NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id]; + int8_t pid = sched_ctrl->feedback_dl_harq.head; + if (pid < 0) + return NULL; + NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; + /* old feedbacks we missed: mark for retransmission */ + while (harq->feedback_frame != frame + || (harq->feedback_frame == frame && harq->feedback_slot < slot)) { + LOG_W(NR_MAC, + "expected HARQ pid %d feedback at %d.%d, but is at %d.%d instead (HARQ feedback is in the past)\n", + pid, + harq->feedback_frame, + harq->feedback_slot, + frame, + slot); + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + handle_dl_harq(mod_id, UE_id, pid, 0); + pid = sched_ctrl->feedback_dl_harq.head; + if (pid < 0) + return NULL; + harq = &sched_ctrl->harq_processes[pid]; + } + /* feedbacks that we wait for in the future: don't do anything */ + if (harq->feedback_slot > slot) { + LOG_W(NR_MAC, + "expected HARQ pid %d feedback at %d.%d, but is at %d.%d instead (HARQ feedback is in the future)\n", + pid, + harq->feedback_frame, + harq->feedback_slot, + frame, + slot); + return NULL; + } + return harq; +} + +void handle_nr_uci_pucch_0_1(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) +{ + int UE_id = find_nr_UE_id(mod_id, uci_01->rnti); + if (UE_id < 0) { + LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); + return; + } + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + if (((uci_01->pduBitmap >> 1) & 0x01)) { + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { + const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; + const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; + NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); + if (!harq) + break; + DevAssert(harq->is_waiting); + const int8_t pid = sched_ctrl->feedback_dl_harq.head; + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + LOG_D(NR_MAC,"bit %d pid %d ack/nack %d\n",harq_bit,pid,harq_value); + handle_dl_harq(mod_id, UE_id, pid, harq_value == 0 && harq_confidence == 0); + if (harq_confidence == 1) UE_info->mac_stats[UE_id].pucch0_DTX++; + } + } + + // check scheduling request result, confidence_level == 0 is good + if (uci_01->pduBitmap & 0x1 && uci_01->sr->sr_indication && uci_01->sr->sr_confidence_level == 0 && uci_01->ul_cqi >= 148) { + // SR detected with SNR >= 10dB + sched_ctrl->SR |= true; + LOG_D(NR_MAC, "SR UE %04x ul_cqi %d\n", uci_01->rnti, uci_01->ul_cqi); + } + + // tpc (power control) only if we received AckNack or positive SR. For a + // negative SR, the UE won't have sent anything, and the SNR is not valid + if (((uci_01->pduBitmap >> 1) & 0x1) || sched_ctrl->SR) { + if ((uci_01->harq) && (uci_01->harq->harq_confidence_level==0)) sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_01->ul_cqi, 30); + else sched_ctrl->tpc1 = 3; + sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640; + } +} + +void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) +{ + int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); + if (UE_id < 0) { + LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); + return; + } + AssertFatal(RC.nrmac[mod_id]->UE_info.CellGroup[UE_id],"Cellgroup is null for UE %d/%x\n",UE_id,uci_234->rnti); + AssertFatal(RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig, "Cellgroup->spCellConfig is null for UE %d/%x\n",UE_id,uci_234->rnti); + AssertFatal(RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated, "Cellgroup->spCellConfig->spCellConfigDedicated is null for UE %d/%x\n",UE_id,uci_234->rnti); + if ( RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->csi_MeasConfig==NULL) return; + + NR_CSI_MeasConfig_t *csi_MeasConfig = RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + // tpc (power control) + sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, + uci_234->ul_cqi, + 30); + sched_ctrl->pucch_snrx10 = uci_234->ul_cqi * 5 - 640; + + if ((uci_234->pduBitmap >> 1) & 0x01) { + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { + const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; + NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); + if (!harq) + break; + DevAssert(harq->is_waiting); + const int8_t pid = sched_ctrl->feedback_dl_harq.head; + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); + } + } + if ((uci_234->pduBitmap >> 2) & 0x01) { + //API to parse the csi report and store it into sched_ctrl + extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE_id, mod_id); + //TCI handling function + tci_handling(mod_id, UE_id,frame, slot); + } + if ((uci_234->pduBitmap >> 3) & 0x01) { + //@TODO:Handle CSI Report 2 + } +} + + +// this function returns an index to NR_sched_pucch structure +// currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1 +// if the function returns -1 it was not possible to schedule acknack +// when current pucch is ready to be scheduled nr_fill_nfapi_pucch is called +int nr_acknack_scheduling(int mod_id, + int UE_id, + frame_t frame, + sub_frame_t slot, + int r_pucch, + int is_common) { + + const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots; + const int first_ul_slot_tdd = tdd->nrofDownlinkSlots + nr_slots_period * (slot / nr_slots_period); + const int first_ul_slot_period = tdd->nrofDownlinkSlots; + const int CC_id = 0; + NR_sched_pucch_t *csi_pucch; + + AssertFatal(slot < first_ul_slot_tdd + (tdd->nrofUplinkSymbols != 0), + "cannot handle multiple TDD periods (yet): slot %d first_ul_slot_tdd %d nrofUplinkSlots %ld\n", + slot, + first_ul_slot_tdd, + tdd->nrofUplinkSlots); + + /* for the moment, we consider: + * * only pucch_sched[0] holds HARQ (and SR) + * * we do not multiplex with CSI, which is always in pucch_sched[2] + * * SR uses format 0 and is allocated in the first UL (mixed) slot (and not + * later) + * * each UE has dedicated PUCCH Format 0 resources, and we use index 0! */ + NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id]; + NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0]; + LOG_D(NR_MAC,"pucch_acknak %d.%d Trying to allocate pucch, current DAI %d\n",frame,slot,pucch->dai_c); + pucch->r_pucch=r_pucch; + AssertFatal(pucch->csi_bits == 0, + "%s(): csi_bits %d in sched_pucch[0]\n", + __func__, + pucch->csi_bits); + /* if the currently allocated PUCCH of this UE is full, allocate it */ + if (pucch->dai_c == 2) { + /* advance the UL slot information in PUCCH by one so we won't schedule in + * the same slot again */ + const int f = pucch->frame; + const int s = pucch->ul_slot; + LOG_D(NR_MAC,"pucch_acknak : %d.%d DAI = 2 pucch currently in %d.%d, advancing by 1 slot\n",frame,slot,f,s); + nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id); + memset(pucch, 0, sizeof(*pucch)); + pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; + if(((s + 1)%nr_slots_period) == 0) + pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; + else + pucch->ul_slot = (s + 1) % n_slots_frame; + // we assume that only two indices over the array sched_pucch exist + csi_pucch = &sched_ctrl->sched_pucch[1]; + // skip the CSI PUCCH if it is present and if in the next frame/slot + // and if we don't multiplex + csi_pucch->r_pucch=-1; + if (csi_pucch->csi_bits > 0 + && csi_pucch->frame == pucch->frame + && csi_pucch->ul_slot == pucch->ul_slot + && !csi_pucch->simultaneous_harqcsi) { + nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); + memset(csi_pucch, 0, sizeof(*csi_pucch)); + pucch->frame = pucch->ul_slot == n_slots_frame - 1 ? (pucch->frame + 1) % 1024 : pucch->frame; + if(((pucch->ul_slot + 1)%nr_slots_period) == 0) + pucch->ul_slot = (pucch->ul_slot + 1 + first_ul_slot_period) % n_slots_frame; + else + pucch->ul_slot = (pucch->ul_slot + 1) % n_slots_frame; + } + } + + LOG_D(NR_MAC,"pucch_acknak 1. DL %d.%d, UL_ACK %d.%d, DAI_C %d\n",frame,slot,pucch->frame,pucch->ul_slot,pucch->dai_c); + + // this is hardcoded for now as ue specific only if we are not on the initialBWP (to be fixed to allow ue_Specific also on initialBWP + NR_CellGroupConfig_t *cg = RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]; + NR_BWP_UplinkDedicated_t *ubwpd=NULL; + + if (cg && + cg->spCellConfig && + cg->spCellConfig->spCellConfigDedicated && + cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) + ubwpd = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; + + NR_SearchSpace__searchSpaceType_PR ss_type = (is_common==0 && (sched_ctrl->active_bwp || ubwpd)) ? NR_SearchSpace__searchSpaceType_PR_ue_Specific: NR_SearchSpace__searchSpaceType_PR_common; + uint8_t pdsch_to_harq_feedback[8]; + int bwp_Id = 0; + if (sched_ctrl->active_ubwp) bwp_Id = sched_ctrl->active_ubwp->bwp_Id; + + int max_fb_time = 0; + get_pdsch_to_harq_feedback(mod_id, UE_id, bwp_Id, ss_type, &max_fb_time, pdsch_to_harq_feedback); + + LOG_D(NR_MAC,"pucch_acknak 1b. DL %d.%d, UL_ACK %d.%d, DAI_C %d\n",frame,slot,pucch->frame,pucch->ul_slot,pucch->dai_c); + /* there is a HARQ. Check whether we can use it for this ACKNACK */ + if (pucch->dai_c > 0) { + /* this UE already has a PUCCH occasion */ + // Find the right timing_indicator value. + int i = 0; + while (i < 8) { + int diff = pucch->ul_slot - slot; + if (diff<0) + diff += n_slots_frame; + if (pdsch_to_harq_feedback[i] == diff) + break; + ++i; + } + if (i >= 8) { + // we cannot reach this timing anymore, allocate and try again + const int f = pucch->frame; + const int s = pucch->ul_slot; + const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + LOG_D(NR_MAC,"pucch_acknak : %d.%d DAI > 0, cannot reach timing for pucch in %d.%d, advancing slot by 1 and trying again\n",frame,slot,f,s); + nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id); + memset(pucch, 0, sizeof(*pucch)); + pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; + if(((s + 1)%nr_slots_period) == 0) + pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; + else + pucch->ul_slot = (s + 1) % n_slots_frame; + return nr_acknack_scheduling(mod_id, UE_id, frame, slot, r_pucch,is_common); + } + + pucch->timing_indicator = i; + pucch->dai_c++; + // retain old resource indicator, and we are good + LOG_D(NR_MAC,"pucch_acknak : %d.%d. DAI > 0, pucch allocated for %d.%d (index %d)\n",frame,slot,pucch->frame,pucch->ul_slot,pucch->timing_indicator); + return 0; + } + + LOG_D(NR_MAC,"pucch_acknak : %d.%d DAI = 0, looking for new pucch occasion\n",frame,slot); + /* we need to find a new PUCCH occasion */ + + /*(Re)Inizialization of timing information*/ + if ((pucch->frame == 0 && pucch->ul_slot == 0) || + ((pucch->frame*n_slots_frame + pucch->ul_slot) < + (frame*n_slots_frame + slot))) { + AssertFatal(pucch->sr_flag + pucch->dai_c == 0, + "expected no SR/AckNack for UE %d in %4d.%2d, but has %d/%d for %4d.%2d\n", + UE_id, frame, slot, pucch->sr_flag, pucch->dai_c, pucch->frame, pucch->ul_slot); + pucch->frame = frame; + pucch->ul_slot = first_ul_slot_tdd; + } + + // Find the right timing_indicator value. + int ind_found = -1; + // while we are within the feedback limits + while ((n_slots_frame + pucch->ul_slot - slot) % n_slots_frame <= max_fb_time) { + int i = 0; + while (i < 8) { + LOG_D(NR_MAC,"pdsch_to_harq_feedback[%d] = %d (pucch->ul_slot %d - slot %d)\n", + i,pdsch_to_harq_feedback[i],pucch->ul_slot,slot); + int diff = pucch->ul_slot - slot; + if (diff<0) + diff += n_slots_frame; + if (pdsch_to_harq_feedback[i] == diff) { + ind_found = i; + break; + } + ++i; + } + if (ind_found!=-1) + break; + // advance to the next ul slot + const int f = pucch->frame; + const int s = pucch->ul_slot; + pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; + if(((s + 1)%nr_slots_period) == 0) + pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; + else + pucch->ul_slot = (s + 1) % n_slots_frame; + } + if (ind_found==-1) { + LOG_D(NR_MAC, + "%4d.%2d could not find pdsch_to_harq_feedback for UE %d: earliest " + "ack slot %d\n", + frame, + slot, + UE_id, + pucch->ul_slot); + return -1; + } + + // is there already CSI in this slot? + csi_pucch = &sched_ctrl->sched_pucch[1]; + if (csi_pucch && + csi_pucch->csi_bits > 0 && + csi_pucch->frame == pucch->frame && + csi_pucch->ul_slot == pucch->ul_slot) { + // skip the CSI PUCCH if it is present and if in the next frame/slot + // and if we don't multiplex + // FIXME currently we support at most 11 bits in pucch2 so skip also in that case + if(!csi_pucch->simultaneous_harqcsi + || ((csi_pucch->csi_bits + csi_pucch->dai_c) >= 11)) { + nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); + memset(csi_pucch, 0, sizeof(*csi_pucch)); + /* advance the UL slot information in PUCCH by one so we won't schedule in + * the same slot again */ + const int f = pucch->frame; + const int s = pucch->ul_slot; + memset(pucch, 0, sizeof(*pucch)); + pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; + if(((s + 1)%nr_slots_period) == 0) + pucch->ul_slot = (s + 1 + first_ul_slot_period) % n_slots_frame; + else + pucch->ul_slot = (s + 1) % n_slots_frame; + return nr_acknack_scheduling(mod_id, UE_id, frame, slot, r_pucch,is_common); + } + // multiplexing harq and csi in a pucch + else { + csi_pucch->timing_indicator = ind_found; + csi_pucch->dai_c++; + return 1; + } + } + + pucch->timing_indicator = ind_found; // index in the list of timing indicators + + LOG_D(NR_MAC,"pucch_acknak 2. DAI 0 DL %d.%d, UL_ACK %d.%d (index %d)\n",frame,slot,pucch->frame,pucch->ul_slot,pucch->timing_indicator); + + pucch->dai_c++; + pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources + pucch->r_pucch=r_pucch; + NR_PUCCH_Config_t *pucch_Config = NULL; + if (sched_ctrl->active_ubwp) { + pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup; + } else if (RC.nrmac[mod_id]->UE_info.CellGroup[UE_id] && + RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig && + RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated && + RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig && + RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + } + + NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ? + &sched_ctrl->active_ubwp->bwp_Common->genericParameters: + &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + int bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth,MAX_BWP_SIZE); + + /* verify that at that slot and symbol, resources are free. We only do this + * for initialCyclicShift 0 (we assume it always has that one), so other + * initialCyclicShifts can overlap with ICS 0!*/ + if (pucch_Config) { + const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[pucch->resource_indicator]; + DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0); + int second_hop_prb = resource->secondHopPRB!= NULL ? *resource->secondHopPRB : 0; + int nr_of_symbols = resource->format.choice.format0->nrofSymbols; + if (resource->format.choice.format0->initialCyclicShift == 0) { + uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE]; + for (int l=0; lformat.choice.format0->startingSymbolIndex + l); + int prb; + if (l==1 && second_hop_prb != 0) + prb = second_hop_prb; + else + prb = resource->startingPRB; + if ((vrb_map_UL[bwp_start+prb] & symb) != 0) + LOG_W(MAC, "symbol 0x%x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d.%d\n", symb, resource->startingPRB, pucch->frame, pucch->ul_slot); + vrb_map_UL[bwp_start+prb] |= symb; + } + } + } + return 0; +} + + +void nr_sr_reporting(int Mod_idP, frame_t SFN, sub_frame_t slot) +{ + gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP]; + if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) + return; + NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon; + const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + NR_UE_info_t *UE_info = &nrmac->UE_info; + NR_list_t *UE_list = &UE_info->list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + if (sched_ctrl->ul_failure==1) continue; + NR_PUCCH_Config_t *pucch_Config = NULL; + if (sched_ctrl->active_ubwp) { + pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup; + } else if (RC.nrmac[Mod_idP]->UE_info.CellGroup[UE_id] && + RC.nrmac[Mod_idP]->UE_info.CellGroup[UE_id]->spCellConfig && + RC.nrmac[Mod_idP]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated && + RC.nrmac[Mod_idP]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig && + RC.nrmac[Mod_idP]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP && + RC.nrmac[Mod_idP]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup) { + pucch_Config = RC.nrmac[Mod_idP]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; + } + else continue; + if (!pucch_Config->schedulingRequestResourceToAddModList) continue; + AssertFatal(pucch_Config->schedulingRequestResourceToAddModList->list.count>0,"NO SR configuration available"); + + for (int SR_resource_id =0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++) { + NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id]; + + int SR_period; int SR_offset; + + find_period_offest_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset); + // convert to int to avoid underflow of uint + int sfn_sf = SFN * n_slots_frame + slot; + LOG_D(NR_MAC,"SR_resource_id %d: SR_period %d, SR_offset %d\n",SR_resource_id,SR_period,SR_offset); + if ((sfn_sf - SR_offset) % SR_period != 0) + continue; + LOG_D(NR_MAC, "%4d.%2d Scheduling Request identified\n", SFN, slot); + NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource; + + int found = -1; + NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1 + int n_list = pucchresset->resourceList.list.count; + for (int i=0; iresourceList.list.array[i] == *PucchResourceId ) + found = i; + } + AssertFatal(found>-1,"SR resource not found among PUCCH resources"); + + /* loop through nFAPI PUCCH messages: if the UEs is in there in this slot + * with the resource_indicator, it means we already allocated that PUCCH + * resource for AckNack (e.g., the UE has been scheduled often), and we + * just need to add the SR_flag. Otherwise, just allocate in the internal + * PUCCH resource, and nr_schedule_pucch() will handle the rest */ + NR_PUCCH_Resource_t *pucch_res = pucch_Config->resourceToAddModList->list.array[found]; + /* for the moment, can only handle SR on PUCCH Format 0 */ + DevAssert(pucch_res->format.present == NR_PUCCH_Resource__format_PR_format0); + nfapi_nr_ul_tti_request_t *ul_tti_req = &nrmac->UL_tti_req_ahead[0][slot]; + bool nfapi_allocated = false; + for (int i = 0; i < ul_tti_req->n_pdus; ++i) { + if (ul_tti_req->pdus_list[i].pdu_type != NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE) + continue; + nfapi_nr_pucch_pdu_t *pdu = &ul_tti_req->pdus_list[i].pucch_pdu; + /* check that it is our PUCCH F0. Assuming there can be only one */ + if (pdu->rnti == UE_info->rnti[UE_id] + && pdu->format_type == 0 // does not use NR_PUCCH_Resource__format_PR_format0 + && pdu->initial_cyclic_shift == pucch_res->format.choice.format0->initialCyclicShift + && pdu->nr_of_symbols == pucch_res->format.choice.format0->nrofSymbols + && pdu->start_symbol_index == pucch_res->format.choice.format0->startingSymbolIndex) { + LOG_D(NR_MAC,"%4d.%2d adding SR_flag 1 to PUCCH nFAPI SR for RNTI %04x\n", SFN, slot, pdu->rnti); + pdu->sr_flag = 1; + nfapi_allocated = true; + break; + } + } + + if (nfapi_allocated) // break scheduling resource loop, continue next UE + break; + + /* we did not find it: check if current PUCCH is for the current slot, in + * which case we add the SR to it; otherwise, allocate SR separately */ + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[0]; + if (curr_pucch->frame == SFN && curr_pucch->ul_slot == slot) { + if (curr_pucch->resource_indicator != found) { + LOG_W(NR_MAC, "%4d.%2d expected PUCCH in this slot to have resource indicator of SR (%d), skipping SR\n", SFN, slot, found); + continue; + } + curr_pucch->sr_flag = true; + } else { + NR_sched_pucch_t sched_sr; + memset(&sched_sr, 0, sizeof(sched_sr)); + sched_sr.frame = SFN; + sched_sr.ul_slot = slot; + sched_sr.resource_indicator = found; + sched_sr.sr_flag = true; + nr_fill_nfapi_pucch(Mod_idP, SFN, slot, &sched_sr, UE_id); + } + } + } +} + diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 89c3fe69fe..c68b16b553 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -31,63 +31,202 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "executables/softmodem-common.h" -//#define ENABLE_MAC_PAYLOAD_DEBUG 1 +#include "common/utils/nr/nr_common.h" +#include +#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -void nr_process_mac_pdu( - module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - uint8_t *pduP, - uint16_t mac_pdu_len) +int get_dci_format(NR_UE_sched_ctrl_t *sched_ctrl) { + + const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; + int dci_format; + if (sched_ctrl->search_space) { + dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0; + } + else { + dci_format = NR_UL_DCI_FORMAT_0_0; + } + + return(dci_format); +} + +void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp) +{ + gNB_MAC_INST *nrmac = RC.nrmac[module_id]; + const int bwp_id = ubwp->bwp_Id; + if (nrmac->preferred_ul_tda[bwp_id]) + return; + + /* there is a mixed slot only when in TDD */ + NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon; + const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + const NR_TDD_UL_DL_Pattern_t *tdd = + scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + /* Uplink symbols are at the end of the slot */ + const int symb_ulMixed = tdd ? ((1 << tdd->nrofUplinkSymbols) - 1) << (14 - tdd->nrofUplinkSymbols) : 0; + + const struct NR_PUCCH_Config__resourceToAddModList *resList = ubwp->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList; + // for the moment, just block any symbol that might hold a PUCCH, regardless + // of the RB. This is a big simplification, as most RBs will NOT have a PUCCH + // in the respective symbols, but it simplifies scheduling + uint16_t symb_pucch = 0; + for (int i = 0; i < resList->list.count; ++i) { + const NR_PUCCH_Resource_t *resource = resList->list.array[i]; + int nrofSymbols = 0; + int startingSymbolIndex = 0; + switch (resource->format.present) { + case NR_PUCCH_Resource__format_PR_format0: + nrofSymbols = resource->format.choice.format0->nrofSymbols; + startingSymbolIndex = resource->format.choice.format0->startingSymbolIndex; + break; + case NR_PUCCH_Resource__format_PR_format1: + nrofSymbols = resource->format.choice.format1->nrofSymbols; + startingSymbolIndex = resource->format.choice.format1->startingSymbolIndex; + break; + case NR_PUCCH_Resource__format_PR_format2: + nrofSymbols = resource->format.choice.format2->nrofSymbols; + startingSymbolIndex = resource->format.choice.format2->startingSymbolIndex; + break; + case NR_PUCCH_Resource__format_PR_format3: + nrofSymbols = resource->format.choice.format3->nrofSymbols; + startingSymbolIndex = resource->format.choice.format3->startingSymbolIndex; + break; + case NR_PUCCH_Resource__format_PR_format4: + nrofSymbols = resource->format.choice.format4->nrofSymbols; + startingSymbolIndex = resource->format.choice.format4->startingSymbolIndex; + break; + default: + AssertFatal(0, "found NR_PUCCH format index %d\n", resource->format.present); + break; + } + symb_pucch |= ((1 << nrofSymbols) - 1) << startingSymbolIndex; + } + + /* check that TDA index 1 fits into UL slot and does not overlap with PUCCH */ + const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + const NR_PUSCH_TimeDomainResourceAllocation_t *tdaP_UL = tdaList->list.array[0]; + const int k2 = get_K2(scc, (NR_BWP_Uplink_t*)ubwp,0, mu); + int start, len; + SLIV2SL(tdaP_UL->startSymbolAndLength, &start, &len); + const uint16_t symb_tda = ((1 << len) - 1) << start; + // check whether PUCCH and TDA overlap: then, we cannot use it. Note that + // here we assume that the PUCCH is scheduled in every slot, and on all RBs + // (which is mostly not true, this is a simplification) + AssertFatal((symb_pucch & symb_tda) == 0, "TDA index 0 for UL overlaps with PUCCH\n"); + + // get largest time domain allocation (TDA) for UL slot and UL in mixed slot + int tdaMi = -1; + if(tdaList->list.count > 1) { + const NR_PUSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1]; + AssertFatal(k2 == get_K2(scc, (NR_BWP_Uplink_t*)ubwp, 1, mu), + "scheduler cannot handle different k2 for UL slot (%d) and UL Mixed slot (%ld)\n", + k2, + get_K2(scc, (NR_BWP_Uplink_t*)ubwp, 1, mu)); + SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len); + const uint16_t symb_tda_mi = ((1 << len) - 1) << start; + // check whether PUCCH and TDA overlap: then, we cannot use it. Also, check + // whether TDA is entirely within mixed slot, UL. Note that here we assume + // that the PUCCH is scheduled in every slot, and on all RBs (which is + // mostly not true, this is a simplification) + if ((symb_pucch & symb_tda_mi) == 0 && (symb_ulMixed & symb_tda_mi) == symb_tda_mi) { + tdaMi = 1; + } else { + LOG_E(NR_MAC, + "TDA index 1 UL overlaps with PUCCH or is not entirely in mixed slot (symb_pucch %x symb_ulMixed %x symb_tda_mi %x), won't schedule UL mixed slot\n", + symb_pucch, + symb_ulMixed, + symb_tda_mi); + } + } + const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; + const int n = slots_per_frame[*scc->ssbSubcarrierSpacing]; + nrmac->preferred_ul_tda[bwp_id] = malloc(n * sizeof(*nrmac->preferred_ul_tda[bwp_id])); + + const int nr_mix_slots = tdd ? tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0 : 0; + const int nr_slots_period = tdd ? tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots : n; + for (int slot = 0; slot < n; ++slot) { + const int sched_slot = (slot + k2) % n; + nrmac->preferred_ul_tda[bwp_id][slot] = -1; + if (!tdd || sched_slot % nr_slots_period >= tdd->nrofDownlinkSlots + nr_mix_slots) + nrmac->preferred_ul_tda[bwp_id][slot] = 0; + else if (tdd && nr_mix_slots && sched_slot % nr_slots_period == tdd->nrofDownlinkSlots) + nrmac->preferred_ul_tda[bwp_id][slot] = tdaMi; + LOG_D(MAC, "DL slot %d UL slot %d preferred_ul_tda %d\n", slot, sched_slot, nrmac->preferred_ul_tda[bwp_id][slot]); + } + + if (k2 < tdd->nrofUplinkSlots) + LOG_W(NR_MAC, + "k2 %d < tdd->nrofUplinkSlots %ld: not all UL slots can be scheduled\n", + k2, + tdd->nrofUplinkSlots); +} + +// For both UL-SCH except: +// - UL-SCH: fixed-size MAC CE(known by LCID) +// - UL-SCH: padding +// - UL-SCH: MSG3 48-bits +// |0|1|2|3|4|5|6|7| bit-wise +// |R|F| LCID | +// | L | +// |0|1|2|3|4|5|6|7| bit-wise +// |R|F| LCID | +// | L | +// | L | +// +// For: +// - UL-SCH: fixed-size MAC CE(known by LCID) +// - UL-SCH: padding, for single/multiple 1-oct padding CE(s) +// - UL-SCH: MSG3 48-bits +// |0|1|2|3|4|5|6|7| bit-wise +// |R|R| LCID | +// +// LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; +// L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; +// F: length of L is 0:8 or 1:16 bits wide +// R: Reserved bit, set to zero. + +int nr_process_mac_pdu(module_id_t module_idP, + int UE_id, + uint8_t CC_id, + frame_t frameP, + sub_frame_t slot, + uint8_t *pduP, + int pdu_len) { - // This function is adapting code from the old - // parse_header(...) and ue_send_sdu(...) functions of OAI LTE + uint8_t rx_lcid; + uint8_t done = 0; + uint16_t mac_ce_len; + uint16_t mac_subheader_len; + uint16_t mac_sdu_len; - uint8_t *pdu_ptr = pduP, rx_lcid, done = 0; - int pdu_len = mac_pdu_len; - uint16_t mac_ce_len, mac_subheader_len, mac_sdu_len; + NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + if ( pduP[0] != UL_SCH_LCID_PADDING ) + trace_NRpdu(DIRECTION_UPLINK, pduP, pdu_len, UE_id, WS_C_RNTI, UE_info->rnti[UE_id], frameP, 0, 0, 0); - // For both DL/UL-SCH - // Except: - // - UL/DL-SCH: fixed-size MAC CE(known by LCID) - // - UL/DL-SCH: padding - // - UL-SCH: MSG3 48-bits - // |0|1|2|3|4|5|6|7| bit-wise - // |R|F| LCID | - // | L | - // |0|1|2|3|4|5|6|7| bit-wise - // |R|F| LCID | - // | L | - // | L | - - // For both DL/UL-SCH - // For: - // - UL/DL-SCH: fixed-size MAC CE(known by LCID) - // - UL/DL-SCH: padding, for single/multiple 1-oct padding CE(s) - // - UL-SCH: MSG3 48-bits - // |0|1|2|3|4|5|6|7| bit-wise - // |R|R| LCID | - // LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; - // L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; - // F: lenght of L is 0:8 or 1:16 bits wide - // R: Reserved bit, set to zero. + #ifdef ENABLE_MAC_PAYLOAD_DEBUG + LOG_I(NR_MAC, "In %s: dumping MAC PDU in %d.%d:\n", __func__, frameP, slot); + log_dump(NR_MAC, pduP, pdu_len, LOG_DUMP_CHAR, "\n"); + #endif while (!done && pdu_len > 0){ mac_ce_len = 0; - mac_subheader_len = 1; // default to fixed-length subheader = 1-oct + mac_subheader_len = sizeof(NR_MAC_SUBHEADER_FIXED); mac_sdu_len = 0; - rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID; + rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; - LOG_D(MAC, "LCID received at gNB side: %d \n", rx_lcid); + LOG_D(NR_MAC, "In %s: received UL-SCH sub-PDU with LCID 0x%x in %d.%d (remaining PDU length %d)\n", __func__, rx_lcid, frameP, slot, pdu_len); + + unsigned char *ce_ptr; + int n_Lcg = 0; switch(rx_lcid){ // MAC CE /*#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID, pdu_len); + LOG_D(NR_MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID, pdu_len); #endif*/ case UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY: // 38.321 Ch6.1.3.20 @@ -96,46 +235,80 @@ void nr_process_mac_pdu( case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION: // 38.321 Ch6.1.3.7 break; - case UL_SCH_LCID_S_BSR: - //38.321 section 6.1.3.1 - //fixed length - mac_ce_len =1; - /* Extract short BSR value */ - break; + case UL_SCH_LCID_S_BSR: case UL_SCH_LCID_S_TRUNCATED_BSR: - //38.321 section 6.1.3.1 - //fixed length - mac_ce_len =1; - /* Extract short truncated BSR value */ - break; + //38.321 section 6.1.3.1 + //fixed length + mac_ce_len =1; + /* Extract short BSR value */ + ce_ptr = &pduP[mac_subheader_len]; + NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr; + sched_ctrl->estimated_ul_buffer = 0; + sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size]; + LOG_D(NR_MAC, + "SHORT BSR at %4d.%2d, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n", + frameP, + slot, + bsr_s->LcgID, + bsr_s->Buffer_size, + NR_SHORT_BSR_TABLE[bsr_s->Buffer_size], + sched_ctrl->estimated_ul_buffer); + break; case UL_SCH_LCID_L_BSR: - //38.321 section 6.1.3.1 - //variable length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - } - /* Extract long BSR value */ - break; - case UL_SCH_LCID_L_TRUNCATED_BSR: //38.321 section 6.1.3.1 //variable length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; } - /* Extract long truncated BSR value */ - break; + /* Extract long BSR value */ + ce_ptr = &pduP[mac_subheader_len]; + NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr; + sched_ctrl->estimated_ul_buffer = 0; + n_Lcg = bsr_l->LcgID7 + bsr_l->LcgID6 + bsr_l->LcgID5 + bsr_l->LcgID4 + + bsr_l->LcgID3 + bsr_l->LcgID2 + bsr_l->LcgID1 + bsr_l->LcgID0; + + LOG_D(NR_MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n", + bsr_l->LcgID7, bsr_l->LcgID6, bsr_l->LcgID5, bsr_l->LcgID4, + bsr_l->LcgID3, bsr_l->LcgID2, bsr_l->LcgID1, bsr_l->LcgID0); + + for (int n = 0; n < n_Lcg; n++){ + LOG_D(NR_MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d", + n, n_Lcg, pduP[mac_subheader_len + 1 + n], + NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]]); + sched_ctrl->estimated_ul_buffer += + NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]]; + LOG_D(NR_MAC, + "LONG BSR at %4d.%2d, %d/%d (n/n_Lcg), BS Index %d, BS value < %d, total %d\n", + frameP, + slot, + n, + n_Lcg, + pduP[mac_subheader_len + 1 + n], + NR_LONG_BSR_TABLE[pduP[mac_subheader_len + 1 + n]], + sched_ctrl->estimated_ul_buffer); + } + + break; case UL_SCH_LCID_C_RNTI: + + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; + if (ra->state >= WAIT_Msg3 && ra->rnti == UE_info->rnti[UE_id]) { + ra->crnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF); + ra->msg3_dcch_dtch = true; + LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x\n", ra->crnti); + break; + } + } + //38.321 section 6.1.3.2 //fixed length mac_ce_len = 2; @@ -147,15 +320,29 @@ void nr_process_mac_pdu( //fixed length mac_ce_len = 2; /* Extract SINGLE ENTRY PHR elements for PHR calculation */ + ce_ptr = &pduP[mac_subheader_len]; + NR_SINGLE_ENTRY_PHR_MAC_CE *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr; + /* Save the phr info */ + const int PH = phr->PH; + const int PCMAX = phr->PCMAX; + /* 38.133 Table10.1.17.1-1 */ + if (PH < 55) + sched_ctrl->ph = PH - 32; + else + sched_ctrl->ph = PH - 32 + (PH - 54); + /* 38.133 Table10.1.18.1-1 */ + sched_ctrl->pcmax = PCMAX - 29; + LOG_D(NR_MAC, "SINGLE ENTRY PHR R1 %d PH %d (%d dB) R2 %d PCMAX %d (%d dBm)\n", + phr->R1, PH, sched_ctrl->ph, phr->R2, PCMAX, sched_ctrl->pcmax); break; case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT: //38.321 section 6.1.3.9 // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; } /* Extract MULTI ENTRY PHR elements from single octet bitmap for PHR calculation */ @@ -164,10 +351,10 @@ void nr_process_mac_pdu( case UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT: //38.321 section 6.1.3.9 // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; } /* Extract MULTI ENTRY PHR elements from four octets bitmap for PHR calculation */ @@ -178,81 +365,252 @@ void nr_process_mac_pdu( // end of MAC PDU, can ignore the rest. break; - // MAC SDUs case UL_SCH_LCID_SRB1: - // todo - break; case UL_SCH_LCID_SRB2: - // todo - break; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8) + | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff); + } else { + mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + } + + rnti_t crnti = UE_info->rnti[UE_id]; + int UE_idx = UE_id; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; + if (ra->state >= WAIT_Msg3 && ra->rnti == UE_info->rnti[UE_id]) { + uint8_t *next_subpduP = pduP + mac_subheader_len + mac_sdu_len; + if ((pduP[mac_subheader_len+mac_sdu_len] & 0x3F) == UL_SCH_LCID_C_RNTI) { + crnti = ((next_subpduP[1]&0xFF)<<8)|(next_subpduP[2]&0xFF); + UE_idx = find_nr_UE_id(module_idP, crnti); + break; + } + } + } + + if (UE_info->CellGroup[UE_idx]) { + LOG_D(NR_MAC, "[UE %d] Frame %d : ULSCH -> UL-DCCH %d (gNB %d, %d bytes), rnti: 0x%04x \n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len, crnti); + mac_rlc_data_ind(module_idP, + crnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pduP + mac_subheader_len), + mac_sdu_len, + 1, + NULL); + } else { + AssertFatal(1==0,"[UE %d] Frame/Slot %d.%d : Received LCID %d which is not configured, dropping packet\n",UE_id,frameP,slot,rx_lcid); + } + break; case UL_SCH_LCID_SRB3: // todo break; - case UL_SCH_LCID_CCCH_MSG3: - // todo - break; + case UL_SCH_LCID_CCCH: - // todo - mac_subheader_len = 2; + case UL_SCH_LCID_CCCH1: + // fixed length + mac_subheader_len = 1; + + if ( rx_lcid == UL_SCH_LCID_CCCH1 ) { + // RRCResumeRequest1 message includes the full I-RNTI and has a size of 8 bytes + mac_sdu_len = 8; + + // Check if it is a valid CCCH1 message, we get all 00's messages very often + int i = 0; + for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) { + if(pduP[i] != 0) { + break; + } + } + if (i == (mac_subheader_len+mac_sdu_len)) { + LOG_D(NR_MAC, "%s() Invalid CCCH1 message!, pdu_len: %d\n", __func__, pdu_len); + done = 1; break; + } + } else { + // fixed length of 6 bytes + mac_sdu_len = 6; + } + + nr_mac_rrc_data_ind(module_idP, + CC_id, + frameP, + 0, + 0, + UE_info->rnti[UE_id], + CCCH, + pduP + mac_subheader_len, + mac_sdu_len, + 0); + break; case UL_SCH_LCID_DTCH: - // check if LCID is valid at current time. - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L1 & 0x7f) << 8) - | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L2 & 0xff); + // check if LCID is valid at current time. + if (((NR_MAC_SUBHEADER_SHORT *)pduP)->F) { + // mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L1 & 0x7f) << 8) + | ((uint16_t)((NR_MAC_SUBHEADER_LONG *)pduP)->L2 & 0xff); - } else { - mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - } + } else { + mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + } - LOG_D(MAC, "[UE %d] Frame %d : ULSCH -> UL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len); + LOG_D(NR_MAC, "In %s: [UE %d] %d.%d : ULSCH -> UL-%s %d (gNB %d, %d bytes)\n", + __func__, + module_idP, + frameP, + slot, + rx_lcid<4?"DCCH":"DTCH", + rx_lcid, + module_idP, + mac_sdu_len); + UE_info->mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len; - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); + mac_rlc_data_ind(module_idP, + UE_info->rnti[UE_id], + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *)(pduP + mac_subheader_len), + mac_sdu_len, + 1, + NULL); - for (i = 0; i < 32; i++) - LOG_T(MAC, "%x.", (pdu_ptr + mac_subheader_len)[i]); - - LOG_T(MAC, "\n"); - #endif - - if (IS_SOFTMODEM_NOS1){ - if (rx_lcid < NB_RB_MAX && rx_lcid >= UL_SCH_LCID_DTCH) { - - mac_rlc_data_ind(module_idP, - 0x1234, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pdu_ptr + mac_subheader_len), - mac_sdu_len, - 1, - NULL); - } else { - LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, module_idP); - } - } - - break; + /* Updated estimated buffer when receiving data */ + if (sched_ctrl->estimated_ul_buffer >= mac_sdu_len) + sched_ctrl->estimated_ul_buffer -= mac_sdu_len; + else + sched_ctrl->estimated_ul_buffer = 0; + break; default: - return; - break; + LOG_E(NR_MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid); + return -1; + break; } - pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); + + #ifdef ENABLE_MAC_PAYLOAD_DEBUG + if (rx_lcid < 45 || rx_lcid == 52 || rx_lcid == 63) { + LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, rx_lcid); + log_dump(NR_MAC, pduP, mac_subheader_len, LOG_DUMP_CHAR, "\n"); + LOG_I(NR_MAC, "In %s: dumping UL MAC SDU with length %d (LCID = 0x%02x):\n", __func__, mac_sdu_len, rx_lcid); + log_dump(NR_MAC, pduP + mac_subheader_len, mac_sdu_len, LOG_DUMP_CHAR, "\n"); + } else { + LOG_I(NR_MAC, "In %s: dumping UL MAC CE with length %d (LCID = 0x%02x):\n", __func__, mac_ce_len, rx_lcid); + log_dump(NR_MAC, pduP + mac_subheader_len + mac_sdu_len, mac_ce_len, LOG_DUMP_CHAR, "\n"); + } + #endif + + pduP += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); if (pdu_len < 0) { - LOG_E(MAC, "%s() residual mac pdu length < 0!, pdu_len: %d\n", __func__, pdu_len); - return; + LOG_E(NR_MAC, "In %s: residual UL MAC PDU in %d.%d with length < 0!, pdu_len %d \n", __func__, frameP, slot, pdu_len); + LOG_E(NR_MAC, "MAC PDU "); + for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes + printf("%02x ", pduP[i]); + printf("\n"); + return 0; } } + return 0; +} + +void abort_nr_ul_harq(module_id_t mod_id, int UE_id, int8_t harq_pid) +{ + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid]; + + harq->ndi ^= 1; + harq->round = 0; + UE_info->mac_stats[UE_id].ulsch_errors++; + add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid); + + /* the transmission failed: the UE won't send the data we expected initially, + * so retrieve to correctly schedule after next BSR */ + sched_ctrl->sched_ul_bytes -= harq->sched_pusch.tb_size; + if (sched_ctrl->sched_ul_bytes < 0) + sched_ctrl->sched_ul_bytes = 0; +} + +void handle_nr_ul_harq(const int CC_idP, + module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_crc_t *crc_pdu) +{ + gNB_MAC_INST *gNB_mac = RC.nrmac[mod_id]; + int UE_id = find_nr_UE_id(mod_id, crc_pdu->rnti); + if (UE_id < 0) { + for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { + NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; + if (ra->state >= WAIT_Msg3 && + ra->rnti == crc_pdu->rnti) + return; + } + LOG_E(NR_MAC, "%s(): unknown RNTI 0x%04x in PUSCH\n", __func__, crc_pdu->rnti); + return; + } + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + int8_t harq_pid = sched_ctrl->feedback_ul_harq.head; + while (crc_pdu->harq_id != harq_pid || harq_pid < 0) { + LOG_W(NR_MAC, + "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x (ignore this warning for RA)\n", + crc_pdu->harq_id, + harq_pid, + crc_pdu->rnti); + if (harq_pid < 0) + return; + + remove_front_nr_list(&sched_ctrl->feedback_ul_harq); + sched_ctrl->ul_harq_processes[harq_pid].is_waiting = false; + if(sched_ctrl->ul_harq_processes[harq_pid].round >= MAX_HARQ_ROUNDS - 1) { + abort_nr_ul_harq(mod_id, UE_id, harq_pid); + } else { + sched_ctrl->ul_harq_processes[harq_pid].round++; + add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid); + } + harq_pid = sched_ctrl->feedback_ul_harq.head; + } + remove_front_nr_list(&sched_ctrl->feedback_ul_harq); + NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid]; + DevAssert(harq->is_waiting); + harq->feedback_slot = -1; + harq->is_waiting = false; + if (!crc_pdu->tb_crc_status) { + harq->ndi ^= 1; + harq->round = 0; + LOG_D(NR_MAC, + "Ulharq id %d crc passed for RNTI %04x\n", + harq_pid, + crc_pdu->rnti); + add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid); + } else if (harq->round >= MAX_HARQ_ROUNDS - 1) { + abort_nr_ul_harq(mod_id, UE_id, harq_pid); + LOG_D(NR_MAC, + "RNTI %04x: Ulharq id %d crc failed in all rounds\n", + crc_pdu->rnti, + harq_pid); + } else { + harq->round++; + LOG_D(NR_MAC, + "Ulharq id %d crc failed for RNTI %04x\n", + harq_pid, + crc_pdu->rnti); + add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid); + } } /* @@ -266,21 +624,28 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, uint8_t *sduP, const uint16_t sdu_lenP, const uint16_t timing_advance, - const uint8_t ul_cqi){ - int current_rnti = 0, UE_id = -1, harq_pid = 0; - gNB_MAC_INST *gNB_mac = NULL; - NR_UE_list_t *UE_list = NULL; - NR_UE_sched_ctrl_t *UE_scheduling_control = NULL; + const uint8_t ul_cqi, + const uint16_t rssi){ - current_rnti = rntiP; - UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti); - gNB_mac = RC.nrmac[gnb_mod_idP]; - UE_list = &gNB_mac->UE_list; + gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; + NR_UE_info_t *UE_info = &gNB_mac->UE_info; + + const int current_rnti = rntiP; + const int UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti); + const int target_snrx10 = gNB_mac->pusch_target_snrx10; + const int pusch_failure_thres = gNB_mac->pusch_failure_thres; if (UE_id != -1) { - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); + NR_UE_sched_ctrl_t *UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + const int8_t harq_pid = UE_scheduling_control->feedback_ul_harq.head; - LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d\n", + if (sduP) + T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), + T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(harq_pid), + T_BUFFER(sduP, sdu_lenP)); + + UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP; + LOG_D(NR_MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d TA %d sduP %p, rssi %d\n", gnb_mod_idP, harq_pid, CC_idP, @@ -288,38 +653,1082 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, slotP, current_rnti, UE_id, - ul_cqi); + ul_cqi, + timing_advance, + sduP, + rssi); + + // if not missed detection (10dB threshold for now) + if (rssi>0) { + UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30); + if (timing_advance != 0xffff) + UE_scheduling_control->ta_update = timing_advance; + UE_scheduling_control->raw_rssi = rssi; + UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640; + LOG_D(NR_MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); + } + else{ + LOG_D(NR_MAC,"[UE %d] Detected DTX : increasing UE TX power\n",UE_id); + UE_scheduling_control->tpc0 = 3; + } #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_I(MAC, "Printing received UL MAC payload at gNB side: %d \n"); - for (int i = 0; i < sdu_lenP ; i++) { + + LOG_I(NR_MAC, "Printing received UL MAC payload at gNB side: %d \n"); + for (int i = 0; i < sdu_lenP ; i++) { //harq_process_ul_ue->a[i] = (unsigned char) rand(); //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); printf("%02x ",(unsigned char)sduP[i]); - } - printf("\n"); + } + printf("\n"); + #endif if (sduP != NULL){ - UE_scheduling_control->ta_update = timing_advance; - LOG_D(MAC, "Received PDU at MAC gNB \n"); - nr_process_mac_pdu(gnb_mod_idP, CC_idP, frameP, sduP, sdu_lenP); + LOG_D(NR_MAC, "Received PDU at MAC gNB \n"); + + UE_info->UE_sched_ctrl[UE_id].pusch_consecutive_dtx_cnt = 0; + const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size; + UE_scheduling_control->sched_ul_bytes -= tb_size; + if (UE_scheduling_control->sched_ul_bytes < 0) + UE_scheduling_control->sched_ul_bytes = 0; + + nr_process_mac_pdu(gnb_mod_idP, UE_id, CC_idP, frameP, slotP, sduP, sdu_lenP); } - } - else { - // random access pusch with TC-RNTI - if (sduP != NULL) { // if the CRC passed - for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { - if (UE_list->active[i] == TRUE) { - if (UE_list->tc_rnti[i] == current_rnti) { - // for now the only thing we are doing is set the UE as 5G connected - UE_list->fiveG_connected[i] = true; - LOG_I(MAC, "[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly and UE_id %d is now 5G connected\n", - gnb_mod_idP, current_rnti, i); + else { + NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid]; + /* reduce sched_ul_bytes when cur_harq->round == 3 */ + if (cur_harq->round == 3){ + const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size; + UE_scheduling_control->sched_ul_bytes -= tb_size; + if (UE_scheduling_control->sched_ul_bytes < 0) + UE_scheduling_control->sched_ul_bytes = 0; + } + if (ul_cqi <= 128) { + UE_info->UE_sched_ctrl[UE_id].pusch_consecutive_dtx_cnt++; + UE_info->mac_stats[UE_id].ulsch_DTX++; + } + if (UE_info->UE_sched_ctrl[UE_id].pusch_consecutive_dtx_cnt >= pusch_failure_thres) { + LOG_D(NR_MAC,"Detected UL Failure on PUSCH, stopping scheduling\n"); + UE_info->UE_sched_ctrl[UE_id].ul_failure = 1; + nr_mac_gNB_rrc_ul_failure(gnb_mod_idP,CC_idP,frameP,slotP,rntiP); + } + } + } else if(sduP) { + + bool no_sig = true; + for (int k = 0; k < sdu_lenP; k++) { + if(sduP[k]!=0) { + no_sig = false; + break; + } + } + + if(no_sig) { + LOG_W(NR_MAC, "No signal\n"); + } + + T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), + T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, + T_BUFFER(sduP, sdu_lenP)); + + /* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3) + * and check the corresponding UE's RNTI match, in which case we activate + * it. */ + for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { + NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; + if (ra->state != WAIT_Msg3) + continue; + + if(no_sig) { + LOG_W(NR_MAC, "Random Access %i failed at state %i (no signal)\n", i, ra->state); + nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + } else { + + // random access pusch with TC-RNTI + if (ra->rnti != current_rnti) { + LOG_W(NR_MAC, + "expected TC_RNTI %04x to match current RNTI %04x\n", + ra->rnti, + current_rnti); + + if( (frameP==ra->Msg3_frame) && (slotP==ra->Msg3_slot) ) { + LOG_W(NR_MAC, "Random Access %i failed at state %i (TC_RNTI %04x RNTI %04x)\n", i, ra->state,ra->rnti,current_rnti); + nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + } + + continue; + } + + int UE_id=-1; + + UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->CellGroup); + if (UE_id<0) { + LOG_W(NR_MAC, "Random Access %i discarded at state %i (TC_RNTI %04x RNTI %04x): max number of users achieved!\n", i, ra->state,ra->rnti,current_rnti); + nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + return; + } + + UE_info->UE_beam_index[UE_id] = ra->beam_id; + + // re-initialize ta update variables after RA procedure completion + UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP; + + LOG_D(NR_MAC, + "reset RA state information for RA-RNTI 0x%04x/index %d\n", + ra->rnti, + i); + + LOG_I(NR_MAC, + "[gNB %d][RAPROC] PUSCH with TC_RNTI 0x%04x received correctly, " + "adding UE MAC Context UE_id %d/RNTI 0x%04x\n", + gnb_mod_idP, + current_rnti, + UE_id, + ra->rnti); + + NR_UE_sched_ctrl_t *UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + + UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30); + if (timing_advance != 0xffff) + UE_scheduling_control->ta_update = timing_advance; + UE_scheduling_control->raw_rssi = rssi; + UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640; + LOG_D(NR_MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); + if(ra->cfra) { + + LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) CFRA procedure succeeded!\n", UE_id, ra->rnti); + nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + UE_info->active[UE_id] = true; + + } else { + + LOG_I(NR_MAC,"[RAPROC] RA-Msg3 received (sdu_lenP %d)\n",sdu_lenP); + LOG_D(NR_MAC,"[RAPROC] Received Msg3:\n"); + for (int k = 0; k < sdu_lenP; k++) { + LOG_D(NR_MAC,"(%i): 0x%x\n",k,sduP[k]); + } + + // UE Contention Resolution Identity + // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 + // First byte corresponds to R/LCID MAC sub-header + memcpy(ra->cont_res_id, &sduP[1], sizeof(uint8_t) * 6); + + if (nr_process_mac_pdu(gnb_mod_idP, UE_id, CC_idP, frameP, slotP, sduP, sdu_lenP) == 0) { + ra->state = Msg4; + ra->Msg4_frame = (frameP + 2) % 1024; + ra->Msg4_slot = 1; + + if (ra->msg3_dcch_dtch) { + // Check if the UE identified by C-RNTI still exists at the gNB + int UE_id_C = find_nr_UE_id(gnb_mod_idP, ra->crnti); + if (UE_id_C < 0) { + // The UE identified by C-RNTI no longer exists at the gNB + // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better solution may be implemented + mac_remove_nr_ue(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + return; + } else { + // The UE identified by C-RNTI still exists at the gNB + // Reset uplink failure flags/counters/timers at MAC and at RRC so gNB will resume again scheduling resources for this UE + UE_info->UE_sched_ctrl[UE_id_C].pusch_consecutive_dtx_cnt = 0; + UE_info->UE_sched_ctrl[UE_id_C].ul_failure = 0; + nr_mac_gNB_rrc_ul_failure_reset(gnb_mod_idP, frameP, slotP, ra->crnti); + } + } + LOG_I(NR_MAC, "Scheduling RA-Msg4 for TC_RNTI 0x%04x (state %d, frame %d, slot %d)\n", + (ra->msg3_dcch_dtch?ra->crnti:ra->rnti), ra->state, ra->Msg4_frame, ra->Msg4_slot); + } + else { + nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); } } + return; } } + } else { + for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { + NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; + if (ra->state != WAIT_Msg3) + continue; + + if( (frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot)) + continue; + + // for CFRA (NSA) do not schedule retransmission of msg3 + if (ra->cfra) { + LOG_W(NR_MAC, "Random Access %i failed at state %i (NSA msg3 reception failed)\n", i, ra->state); + nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + return; + } + + if (ra->msg3_round >= MAX_HARQ_ROUNDS - 1) { + LOG_W(NR_MAC, "Random Access %i failed at state %i (Reached msg3 max harq rounds)\n", i, ra->state); + nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + return; + } + + LOG_W(NR_MAC, "Random Access %i Msg3 CRC did not pass)\n", i); + ra->msg3_round++; + ra->state = Msg3_retransmission; + } } } +long get_K2(NR_ServingCellConfigCommon_t *scc,NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) { + DevAssert(scc); + const NR_PUSCH_TimeDomainResourceAllocation_t *tda_list = ubwp ? + ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]: + scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]; + if (tda_list->k2) + return *tda_list->k2; + else if (mu < 2) + return 1; + else if (mu == 2) + return 2; + else + return 3; +} + +bool nr_UE_is_to_be_scheduled(module_id_t mod_id, int CC_id, int UE_id, frame_t frame, sub_frame_t slot) +{ + const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; + const int n = slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int now = frame * n + slot; + + const struct gNB_MAC_INST_s *nrmac = RC.nrmac[mod_id]; + const NR_UE_sched_ctrl_t *sched_ctrl = &nrmac->UE_info.UE_sched_ctrl[UE_id]; + const int last_ul_sched = sched_ctrl->last_ul_frame * n + sched_ctrl->last_ul_slot; + + const int diff = (now - last_ul_sched + 1024 * n) % (1024 * n); + /* UE is to be scheduled if + * (1) we think the UE has more bytes awaiting than what we scheduled + * (2) there is a scheduling request + * (3) or we did not schedule it in more than 10 frames */ + const bool has_data = sched_ctrl->estimated_ul_buffer > sched_ctrl->sched_ul_bytes; + const bool high_inactivity = diff >= nrmac->ulsch_max_frame_inactivity * n; + LOG_D(NR_MAC, + "%4d.%2d UL inactivity %d slots has_data %d SR %d\n", + frame, + slot, + diff, + has_data, + sched_ctrl->SR); + return has_data || sched_ctrl->SR || high_inactivity; +} + +int next_list_entry_looped(NR_list_t *list, int UE_id) +{ + if (UE_id < 0) + return list->head; + return list->next[UE_id] < 0 ? list->head : list->next[UE_id]; +} + +bool allocate_ul_retransmission(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + uint8_t *rballoc_mask, + int *n_rb_sched, + int UE_id, + int harq_pid) +{ + const int CC_id = 0; + const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon; + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_sched_pusch_t *retInfo = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch; + NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id]; + NR_BWP_UplinkDedicated_t *ubwpd= cg ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP:NULL; + NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ? &sched_ctrl->active_ubwp->bwp_Common->genericParameters : &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + int rbStart = 0; // wrt BWP start + const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + + const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_bwp || ubwpd) ? 1 : 2; + const int tda = sched_ctrl->active_ubwp ? RC.nrmac[module_id]->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda); + LOG_D(NR_MAC,"num_dmrs_cdm_grps_no_data %d, tbs %d\n",num_dmrs_cdm_grps_no_data, retInfo->tb_size); + if (tda == retInfo->time_domain_allocation) { + /* Check the resource is enough for retransmission */ + while (rbStart < bwpSize && !rballoc_mask[rbStart]) + rbStart++; + if (rbStart + retInfo->rbSize > bwpSize) { + LOG_W(NR_MAC, "cannot allocate retransmission of UE %d/RNTI %04x: no resources (rbStart %d, retInfo->rbSize %d, bwpSize %d\n", UE_id, UE_info->rnti[UE_id], rbStart, retInfo->rbSize, bwpSize); + return false; + } + /* check whether we need to switch the TDA allocation since tha last + * (re-)transmission */ + NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static; + + int dci_format = get_dci_format(sched_ctrl); + + if (ps->time_domain_allocation != tda + || ps->dci_format != dci_format + || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data) + nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, ps); + LOG_D(NR_MAC, "%s(): retransmission keeping TDA %d and TBS %d\n", __func__, tda, retInfo->tb_size); + } else { + /* the retransmission will use a different time domain allocation, check + * that we have enough resources */ + while (rbStart < bwpSize && !rballoc_mask[rbStart]) + rbStart++; + int rbSize = 0; + while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize]) + rbSize++; + NR_pusch_semi_static_t temp_ps; + int dci_format = get_dci_format(sched_ctrl); + nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp,ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, &temp_ps); + uint32_t new_tbs; + uint16_t new_rbSize; + bool success = nr_find_nb_rb(retInfo->Qm, + retInfo->R, + temp_ps.nrOfSymbols, + temp_ps.N_PRB_DMRS * temp_ps.num_dmrs_symb, + retInfo->tb_size, + rbSize, + &new_tbs, + &new_rbSize); + if (!success || new_tbs != retInfo->tb_size) { + LOG_D(NR_MAC, "%s(): new TBsize %d of new TDA does not match old TBS %d\n", __func__, new_tbs, retInfo->tb_size); + return false; /* the maximum TBsize we might have is smaller than what we need */ + } + LOG_D(NR_MAC, "%s(): retransmission with TDA %d->%d and TBS %d -> %d\n", __func__, retInfo->time_domain_allocation, tda, retInfo->tb_size, new_tbs); + /* we can allocate it. Overwrite the time_domain_allocation, the number + * of RBs, and the new TB size. The rest is done below */ + retInfo->tb_size = new_tbs; + retInfo->rbSize = new_rbSize; + retInfo->time_domain_allocation = tda; + sched_ctrl->pusch_semi_static = temp_ps; + } + + /* Find free CCE */ + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(NR_MAC, "%4d.%2d no free CCE for retransmission UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]); + return false; + } + + /* frame/slot in sched_pusch has been set previously. In the following, we + * overwrite the information in the retransmission information before storing + * as the new scheduling instruction */ + retInfo->frame = sched_ctrl->sched_pusch.frame; + retInfo->slot = sched_ctrl->sched_pusch.slot; + /* Get previous PSUCH field info */ + sched_ctrl->sched_pusch = *retInfo; + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + + LOG_D(NR_MAC, + "%4d.%2d Allocate UL retransmission UE %d/RNTI %04x sched %4d.%2d (%d RBs)\n", + frame, + slot, + UE_id, + UE_info->rnti[UE_id], + sched_pusch->frame, + sched_pusch->slot, + sched_pusch->rbSize); + + sched_pusch->rbStart = rbStart; + /* no need to recompute the TBS, it will be the same */ + + /* Mark the corresponding RBs as used */ + n_rb_sched -= sched_pusch->rbSize; + for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) + rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0; + return true; +} + +void update_ul_ue_R_Qm(NR_sched_pusch_t *sched_pusch, const NR_pusch_semi_static_t *ps) +{ + const int mcs = sched_pusch->mcs; + sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table); + sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table); + + if (ps->pusch_Config && ps->pusch_Config->tp_pi2BPSK && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) { + sched_pusch->R >>= 1; + sched_pusch->Qm <<= 1; + } +} + +float ul_thr_ue[MAX_MOBILES_PER_GNB]; +uint32_t ul_pf_tbs[3][29]; // pre-computed, approximate TBS values for PF coefficient +void pf_ul(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + NR_list_t *UE_list, + int max_num_ue, + int n_rb_sched, + uint8_t *rballoc_mask) { + + const int CC_id = 0; + gNB_MAC_INST *nrmac = RC.nrmac[module_id]; + NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; + NR_UE_info_t *UE_info = &nrmac->UE_info; + const int min_rb = 5; + float coeff_ue[MAX_MOBILES_PER_GNB]; + // UEs that could be scheduled + int ue_array[MAX_MOBILES_PER_GNB]; + NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB }; + + /* Loop UE_list to calculate throughput and coeff */ + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + + if (UE_info->Msg4_ACKed[UE_id] != true) continue; + + LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %d\n",UE_id); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ? &sched_ctrl->active_ubwp->bwp_Common->genericParameters : &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + int rbStart = 0; // wrt BWP start + NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id]; + NR_BWP_UplinkDedicated_t *ubwpd= cg ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP : NULL; + + const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static; + + /* Calculate throughput */ + const float a = 0.0005f; // corresponds to 200ms window + const uint32_t b = UE_info->mac_stats[UE_id].ulsch_current_bytes; + ul_thr_ue[UE_id] = (1 - a) * ul_thr_ue[UE_id] + a * b; + + /* Check if retransmission is necessary */ + sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head; + LOG_D(NR_MAC,"pf_ul: UE %d harq_pid %d\n",UE_id,sched_pusch->ul_harq_pid); + if (sched_pusch->ul_harq_pid >= 0) { + /* Allocate retransmission*/ + bool r = allocate_ul_retransmission( + module_id, frame, slot, rballoc_mask, &n_rb_sched, UE_id, sched_pusch->ul_harq_pid); + if (!r) { + LOG_D(NR_MAC, "%4d.%2d UL retransmission UE RNTI %04x can NOT be allocated\n", frame, slot, UE_info->rnti[UE_id]); + continue; + } + else LOG_D(NR_MAC,"%4d.%2d UL Retransmission UE RNTI %04x to be allocated, max_num_ue %d\n",frame,slot,UE_info->rnti[UE_id],max_num_ue); + + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) + return; + continue; + } + + const int B = max(0, sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes); + /* preprocessor computed sched_frame/sched_slot */ + const bool do_sched = nr_UE_is_to_be_scheduled(module_id, 0, UE_id, sched_pusch->frame, sched_pusch->slot); + + LOG_D(NR_MAC,"pf_ul: do_sched UE %d => %s\n",UE_id,do_sched ? "yes" : "no"); + if (B == 0 && !do_sched) + continue; + + /* Schedule UE on SR or UL inactivity and no data (otherwise, will be scheduled + * based on data to transmit) */ + if (B == 0 && do_sched) { + /* if no data, pre-allocate 5RB */ + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(NR_MAC, "%4d.%2d no free CCE for UL DCI UE %04x (BSR 0)\n", frame, slot, UE_info->rnti[UE_id]); + continue; + } + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) + return; + + LOG_D(NR_MAC,"Looking for min_rb %d RBs, starting at %d\n", min_rb, rbStart); + while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++; + if (rbStart + min_rb >= bwpSize) { + LOG_W(NR_MAC, "cannot allocate continuous UL data for UE %d/RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d\n", + UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize); + return; + } + + /* Save PUSCH field */ + /* we want to avoid a lengthy deduction of DMRS and other parameters in + * every TTI if we can save it, so check whether dci_format, TDA, or + * num_dmrs_cdm_grps_no_data has changed and only then recompute */ + const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_ubwp || ubwpd) ? 1 : 2; + int dci_format = get_dci_format(sched_ctrl); + const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + if (ps->time_domain_allocation != tda + || ps->dci_format != dci_format + || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data) + nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, ps); + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + sched_pusch->mcs = 9; + update_ul_ue_R_Qm(sched_pusch, ps); + sched_pusch->rbStart = rbStart; + sched_pusch->rbSize = min_rb; + sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, + sched_pusch->R, + sched_pusch->rbSize, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->num_dmrs_symb, + 0, // nb_rb_oh + 0, + 1 /* NrOfLayers */) + >> 3; + + /* Mark the corresponding RBs as used */ + n_rb_sched -= sched_pusch->rbSize; + for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) + rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0; + + continue; + } + + /* Create UE_sched for UEs eligibale for new data transmission*/ + add_tail_nr_list(&UE_sched, UE_id); + + /* Calculate coefficient*/ + sched_pusch->mcs = 9; + const uint32_t tbs = ul_pf_tbs[ps->mcs_table][sched_pusch->mcs]; + coeff_ue[UE_id] = (float) tbs / ul_thr_ue[UE_id]; + LOG_D(NR_MAC,"b %d, ul_thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n", + b, UE_id, ul_thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]); + } + + + /* Loop UE_sched to find max coeff and allocate transmission */ + while (UE_sched.head >= 0 && max_num_ue> 0 && n_rb_sched > 0) { + /* Find max coeff */ + int *max = &UE_sched.head; /* Find max coeff: assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* Find max coeff: if the current one has larger coeff, save for later */ + if (coeff_ue[*p] > coeff_ue[*max]) + max = p; + p = &UE_sched.next[*p]; + } + /* Find max coeff: remove the max one: do not use remove_nr_list() since it + * goes through the whole list every time. Note that UE_sched.tail might + * not be set correctly anymore */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(NR_MAC, "%4d.%2d no free CCE for UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]); + continue; + } + else LOG_D(NR_MAC, "%4d.%2d free CCE for UL DCI UE %04x\n",frame,slot, UE_info->rnti[UE_id]); + + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) + return; + + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id]; + NR_BWP_UplinkDedicated_t *ubwpd= cg ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP:NULL; + NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ? &sched_ctrl->active_ubwp->bwp_Common->genericParameters : &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + int rbStart = sched_ctrl->active_ubwp ? NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE) : 0; + const uint16_t bwpSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static; + + while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++; + sched_pusch->rbStart = rbStart; + uint16_t max_rbSize = 1; + while (rbStart + max_rbSize < bwpSize && rballoc_mask[rbStart + max_rbSize]) + max_rbSize++; + + if (rbStart + min_rb >= bwpSize) { + LOG_W(NR_MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources (rbStart %d, min_rb %d, bwpSize %d\n", + UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize); + return; + } + else LOG_D(NR_MAC,"allocating UL data for UE %d/RNTI %04x (rbStsart %d, min_rb %d, bwpSize %d\n",UE_id, UE_info->rnti[UE_id],rbStart,min_rb,bwpSize); + + /* Save PUSCH field */ + /* we want to avoid a lengthy deduction of DMRS and other parameters in + * every TTI if we can save it, so check whether dci_format, TDA, or + * num_dmrs_cdm_grps_no_data has changed and only then recompute */ + const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_ubwp || ubwpd) ? 1 : 2; + int dci_format = get_dci_format(sched_ctrl); + const int tda = sched_ctrl->active_ubwp ? nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + if (ps->time_domain_allocation != tda + || ps->dci_format != dci_format + || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data) + nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, ubwpd, dci_format, tda, num_dmrs_cdm_grps_no_data, ps); + update_ul_ue_R_Qm(sched_pusch, ps); + + /* Calculate the current scheduling bytes and the necessary RBs */ + const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0); + uint16_t rbSize = 0; + uint32_t TBS = 0; + nr_find_nb_rb(sched_pusch->Qm, + sched_pusch->R, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->num_dmrs_symb, + B, + max_rbSize, + &TBS, + &rbSize); + sched_pusch->rbSize = rbSize; + sched_pusch->tb_size = TBS; + LOG_D(NR_MAC,"rbSize %d, TBS %d, est buf %d, sched_ul %d, B %d, CCE %d, num_dmrs_symb %d, N_PRB_DMRS %d\n", + rbSize, sched_pusch->tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, B,sched_ctrl->cce_index,ps->num_dmrs_symb,ps->N_PRB_DMRS); + + /* Mark the corresponding RBs as used */ + n_rb_sched -= sched_pusch->rbSize; + for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) + rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0; + } +} + +bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) +{ + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + NR_COMMON_channels_t *cc = nr_mac->common_channels; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + NR_UE_info_t *UE_info = &nr_mac->UE_info; + + if (UE_info->num_UEs == 0) + return false; + + const int CC_id = 0; + + /* Get the K2 for first UE to compute offset. The other UEs are guaranteed to + * have the same K2 (we don't support multiple/different K2s via different + * TDAs yet). If the TDA is negative, it means that there is no UL slot to + * schedule now (slot + k2 is not UL slot) */ + int UE_id = UE_info->list.head; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const int tda = sched_ctrl->active_ubwp ? nr_mac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0; + if (tda < 0) + return false; + int K2 = get_K2(scc, sched_ctrl->active_ubwp, tda, mu); + const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]); + const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; + + if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) + return false; + + bool is_mixed_slot = is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[sched_slot / 64], sched_slot) && + is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot); + + // FIXME: Avoid mixed slots for initialUplinkBWP + if (sched_ctrl->active_ubwp==NULL && is_mixed_slot) + return false; + + sched_ctrl->sched_pusch.slot = sched_slot; + sched_ctrl->sched_pusch.frame = sched_frame; + for (UE_id = UE_info->list.next[UE_id]; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + AssertFatal(K2 == get_K2(scc,sched_ctrl->active_ubwp, tda, mu), + "Different K2, %d(UE%d) != %ld(UE%d)\n", K2, 0, get_K2(scc,sched_ctrl->active_ubwp, tda, mu), UE_id); + sched_ctrl->sched_pusch.slot = sched_slot; + sched_ctrl->sched_pusch.frame = sched_frame; + } + + /* Change vrb_map_UL to rballoc_mask: check which symbols per RB (in + * vrb_map_UL) overlap with the "default" tda and exclude those RBs. + * Calculate largest contiguous RBs */ + uint16_t *vrb_map_UL = + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp ? + sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth: + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + const uint16_t bwpStart = NRRIV2PRBOFFSET(sched_ctrl->active_ubwp ? + sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth: + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = sched_ctrl->active_ubwp ? + sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList: + scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength; + int startSymbolIndex, nrOfSymbols; + SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); + const uint16_t symb = ((1 << nrOfSymbols) - 1) << startSymbolIndex; + + int st = 0, e = 0, len = 0; + for (int i = 0; i < bwpSize; i++) + if (RC.nrmac[module_id]->ulprbbl[i] == 1) vrb_map_UL[i]=symb; + + for (int i = 0; i < bwpSize; i++) { + while ((vrb_map_UL[bwpStart + i] & symb) != 0 && i < bwpSize) + i++; + st = i; + while ((vrb_map_UL[bwpStart + i] & symb) == 0 && i < bwpSize) + i++; + if (i - st > len) { + len = i - st; + e = i - 1; + } + } + st = e - len + 1; + + LOG_D(NR_MAC,"UL %d.%d : start_prb %d, end PRB %d\n",frame,slot,st,e); + + uint8_t rballoc_mask[bwpSize]; + + /* Calculate mask: if any RB in vrb_map_UL is blocked (1), the current RB will be 0 */ + for (int i = 0; i < bwpSize; i++) + rballoc_mask[i] = i >= st && i <= e; + + /* proportional fair scheduling algorithm */ + pf_ul(module_id, + frame, + slot, + &UE_info->list, + 2, + len, + rballoc_mask); + return true; +} + +nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(module_id_t module_id, int CC_id) +{ + /* in the PF algorithm, we have to use the TBsize to compute the coefficient. + * This would include the number of DMRS symbols, which in turn depends on + * the time domain allocation. In case we are in a mixed slot, we do not want + * to recalculate all these values, and therefore we provide a look-up table + * which should approximately(!) give us the TBsize. In particular, the + * number of symbols, the number of DMRS symbols, and the exact Qm and R, are + * not correct*/ + for (int mcsTableIdx = 0; mcsTableIdx < 3; ++mcsTableIdx) { + for (int mcs = 0; mcs < 29; ++mcs) { + if (mcs > 27 && mcsTableIdx == 1) + continue; + const uint8_t Qm = nr_get_Qm_dl(mcs, mcsTableIdx); + const uint16_t R = nr_get_code_rate_dl(mcs, mcsTableIdx); + /* note: we do not update R/Qm based on low MCS or pi2BPSK */ + ul_pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm, + R, + 1, /* rbSize */ + 10, /* hypothetical number of slots */ + 0, /* N_PRB_DMRS * N_DMRS_SLOT */ + 0 /* N_PRB_oh, 0 for initialBWP */, + 0 /* tb_scaling */, + 1 /* nrOfLayers */) + >> 3; + } + } + return nr_fr1_ulsch_preprocessor; +} + +void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) +{ + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + /* Uplink data ONLY can be scheduled when the current slot is downlink slot, + * because we have to schedule the DCI0 first before schedule uplink data */ + if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slot / 64], slot)) { + LOG_D(NR_MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot); + return; + } + bool do_sched = RC.nrmac[module_id]->pre_processor_ul(module_id, frame, slot); + if (!do_sched) + return; + + const int CC_id = 0; + nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[CC_id]; + ul_dci_req->SFN = frame; + ul_dci_req->Slot = slot; + /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each + * allocated PDCCH so we can easily allocate UE's DCIs independent of any + * CORESET order */ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {{0}}; + + NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon; + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + const NR_list_t *UE_list = &UE_info->list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + if (sched_ctrl->ul_failure == 1 && get_softmodem_params()->phy_test==0) continue; + + NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id]; + NR_BWP_UplinkDedicated_t *ubwpd= cg ? cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP:NULL; + UE_info->mac_stats[UE_id].ulsch_current_bytes = 0; + + /* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in + * every TTI are pre-populated by the preprocessor and used below */ + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + LOG_D(NR_MAC,"UE %x : sched_pusch->rbSize %d\n",UE_info->rnti[UE_id],sched_pusch->rbSize); + if (sched_pusch->rbSize <= 0) + continue; + + uint16_t rnti = UE_info->rnti[UE_id]; + sched_ctrl->SR = false; + + int8_t harq_id = sched_pusch->ul_harq_pid; + if (harq_id < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + harq_id = sched_ctrl->available_ul_harq.head; + AssertFatal(harq_id >= 0, + "no free HARQ process available for UE %d\n", + UE_id); + remove_front_nr_list(&sched_ctrl->available_ul_harq); + sched_pusch->ul_harq_pid = harq_id; + } else { + /* PP selected a specific HARQ process. Check whether it will be a new + * transmission or a retransmission, and remove from the corresponding + * list */ + if (sched_ctrl->ul_harq_processes[harq_id].round == 0) + remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); + else + remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id); + } + NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id]; + DevAssert(!cur_harq->is_waiting); + add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); + cur_harq->feedback_slot = sched_pusch->slot; + cur_harq->is_waiting = true; + + int rnti_types[2] = { NR_RNTI_C, 0 }; + + /* pre-computed PUSCH values that only change if time domain allocation, + * DCI format, or DMRS parameters change. Updated in the preprocessor + * through nr_set_pusch_semi_static() */ + NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static; + + /* Statistics */ + UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++; + if (cur_harq->round == 0) { + UE_info->mac_stats[UE_id].ulsch_total_bytes_scheduled += sched_pusch->tb_size; + /* Save information on MCS, TBS etc for the current initial transmission + * so we have access to it when retransmitting */ + cur_harq->sched_pusch = *sched_pusch; + /* save which time allocation has been used, to be used on + * retransmissions */ + cur_harq->sched_pusch.time_domain_allocation = ps->time_domain_allocation; + sched_ctrl->sched_ul_bytes += sched_pusch->tb_size; + } else { + LOG_D(NR_MAC, + "%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n", + frame, + slot, + rnti, + sched_pusch->frame, + sched_pusch->slot, + harq_id, + cur_harq->round, + cur_harq->ndi); + } + UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size; + sched_ctrl->last_ul_frame = sched_pusch->frame; + sched_ctrl->last_ul_slot = sched_pusch->slot; + + LOG_D(NR_MAC, + "ULSCH/PUSCH: %4d.%2d RNTI %04x UL sched %4d.%2d DCI L %d start %2d RBS %3d startSymbol %2d nb_symbol %2d dmrs_pos %x MCS %2d TBS %4d HARQ PID %2d round %d RV %d NDI %d est %6d sched %6d est BSR %6d TPC %d\n", + frame, + slot, + rnti, + sched_pusch->frame, + sched_pusch->slot, + sched_ctrl->aggregation_level, + sched_pusch->rbStart, + sched_pusch->rbSize, + ps->startSymbolIndex, + ps->nrOfSymbols, + ps->ul_dmrs_symb_pos, + sched_pusch->mcs, + sched_pusch->tb_size, + harq_id, + cur_harq->round, + nr_rv_round_map[cur_harq->round], + cur_harq->ndi, + sched_ctrl->estimated_ul_buffer, + sched_ctrl->sched_ul_bytes, + sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, + sched_ctrl->tpc0); + + + /* PUSCH in a later slot, but corresponding DCI now! */ + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_id]->UL_tti_req_ahead[0][sched_pusch->slot]; + AssertFatal(future_ul_tti_req->SFN == sched_pusch->frame + && future_ul_tti_req->Slot == sched_pusch->slot, + "%d.%d future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", + frame, slot, + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + sched_pusch->frame, + sched_pusch->slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; + memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + future_ul_tti_req->n_pdus += 1; + + LOG_D(NR_MAC, "%4d.%2d Scheduling UE specific PUSCH for sched %d.%d, ul_tto_req %d.%d\n", frame, slot, + sched_pusch->frame,sched_pusch->slot,future_ul_tti_req->SFN,future_ul_tti_req->Slot); + + pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + pusch_pdu->rnti = rnti; + pusch_pdu->handle = 0; //not yet used + + /* FAPI: BWP */ + NR_BWP_t *genericParameters = sched_ctrl->active_ubwp ? &sched_ctrl->active_ubwp->bwp_Common->genericParameters:&scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + pusch_pdu->bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + pusch_pdu->bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + pusch_pdu->subcarrier_spacing = genericParameters->subcarrierSpacing; + pusch_pdu->cyclic_prefix = 0; + + /* FAPI: PUSCH information always included */ + pusch_pdu->target_code_rate = sched_pusch->R; + pusch_pdu->qam_mod_order = sched_pusch->Qm; + pusch_pdu->mcs_index = sched_pusch->mcs; + pusch_pdu->mcs_table = ps->mcs_table; + pusch_pdu->transform_precoding = ps->transform_precoding; + if (ps->pusch_Config && ps->pusch_Config->dataScramblingIdentityPUSCH) + pusch_pdu->data_scrambling_id = *ps->pusch_Config->dataScramblingIdentityPUSCH; + else + pusch_pdu->data_scrambling_id = *scc->physCellId; + pusch_pdu->nrOfLayers = 1; + + /* FAPI: DMRS */ + pusch_pdu->ul_dmrs_symb_pos = ps->ul_dmrs_symb_pos; + pusch_pdu->dmrs_config_type = ps->dmrs_config_type; + if (pusch_pdu->transform_precoding) { // transform precoding disabled + long *scramblingid=NULL; + if (ps->NR_DMRS_UplinkConfig && pusch_pdu->scid == 0) + scramblingid = ps->NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; + else if (ps->NR_DMRS_UplinkConfig) + scramblingid = ps->NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; + if (scramblingid == NULL) + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + else + pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; + } + else { + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + if (ps->NR_DMRS_UplinkConfig && ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) + pusch_pdu->pusch_identity = *ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; + else if (ps->NR_DMRS_UplinkConfig) + pusch_pdu->pusch_identity = *scc->physCellId; + } + pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] + pusch_pdu->num_dmrs_cdm_grps_no_data = ps->num_dmrs_cdm_grps_no_data; + pusch_pdu->dmrs_ports = 1; + + /* FAPI: Pusch Allocation in frequency domain */ + pusch_pdu->resource_alloc = 1; //type 1 + pusch_pdu->rb_start = sched_pusch->rbStart; + pusch_pdu->rb_size = sched_pusch->rbSize; + pusch_pdu->vrb_to_prb_mapping = 0; + if (ps->pusch_Config==NULL || ps->pusch_Config->frequencyHopping==NULL) + pusch_pdu->frequency_hopping = 0; + else + pusch_pdu->frequency_hopping = 1; + + /* FAPI: Resource Allocation in time domain */ + pusch_pdu->start_symbol_index = ps->startSymbolIndex; + pusch_pdu->nr_of_symbols = ps->nrOfSymbols; + + /* PUSCH PDU */ + pusch_pdu->pusch_data.rv_index = nr_rv_round_map[cur_harq->round]; + pusch_pdu->pusch_data.harq_process_id = harq_id; + pusch_pdu->pusch_data.new_data_indicator = cur_harq->ndi; + pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size; + pusch_pdu->pusch_data.num_cb = 0; //CBG not supported + + LOG_D(NR_MAC,"PUSCH PDU : data_scrambling_identity %x, dmrs_scrambling_id %x\n",pusch_pdu->data_scrambling_id,pusch_pdu->ul_dmrs_scrambling_id); + /* TRANSFORM PRECODING --------------------------------------------------------*/ + + if (pusch_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled){ + + // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled + pusch_pdu->dfts_ofdm.low_papr_group_number = pusch_pdu->pusch_identity % 30; + + // V as specified in section 6.4.1.1.1.2 in 38.211 V = 0 if sequence hopping and group hopping are disabled + if ((ps->NR_DMRS_UplinkConfig==NULL) || ((ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping == NULL) && + (ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping == NULL))) + pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0; + else + AssertFatal(1==0,"SequenceGroupHopping or sequenceHopping are NOT Supported\n"); + + LOG_D(NR_MAC,"TRANSFORM PRECODING IS ENABLED. CDM groups: %d, U: %d MCS table: %d\n", pusch_pdu->num_dmrs_cdm_grps_no_data, pusch_pdu->dfts_ofdm.low_papr_group_number, ps->mcs_table); + } + + /*-----------------------------------------------------------------------------*/ + + /* PUSCH PTRS */ + if (ps->NR_DMRS_UplinkConfig && ps->NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { + bool valid_ptrs_setup = false; + pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); + valid_ptrs_setup = set_ul_ptrs_values(ps->NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup, + pusch_pdu->rb_size, pusch_pdu->mcs_index, pusch_pdu->mcs_table, + &pusch_pdu->pusch_ptrs.ptrs_freq_density,&pusch_pdu->pusch_ptrs.ptrs_time_density, + &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_pdu->pusch_ptrs.num_ptrs_ports, + &pusch_pdu->pusch_ptrs.ul_ptrs_power, pusch_pdu->nr_of_symbols); + if (valid_ptrs_setup==true) { + pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + } + } + else{ + pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + } + + /* look up the PDCCH PDU for this BWP and CORESET. If it does not exist, + * create it */ + const int bwpid = sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Id : 0; + NR_SearchSpace_t *ss = (sched_ctrl->active_bwp || ubwpd) ? sched_ctrl->search_space: RC.nrmac[module_id]->sched_ctrlCommon->search_space; + NR_ControlResourceSet_t *coreset = (sched_ctrl->active_bwp || ubwpd) ? sched_ctrl->coreset: RC.nrmac[module_id]->sched_ctrlCommon->coreset; + const int coresetid = coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = pdcch_pdu_bwp_coreset[bwpid][coresetid]; + if (!pdcch_pdu) { + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; + memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); + ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; + ul_dci_req->numPdus += 1; + nr_configure_pdcch(nr_mac, pdcch_pdu, ss, coreset, scc, genericParameters, NULL); + pdcch_pdu_bwp_coreset[bwpid][coresetid] = pdcch_pdu; + } + + LOG_D(NR_MAC,"Configuring ULDCI/PDCCH in %d.%d at CCE %d, rnti %x\n", frame,slot,sched_ctrl->cce_index,rnti); + + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci]; + pdcch_pdu->numDlDci++; + dci_pdu->RNTI = rnti; + if (coreset->pdcch_DMRS_ScramblingID && + ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { + dci_pdu->ScramblingId = *coreset->pdcch_DMRS_ScramblingID; + dci_pdu->ScramblingRNTI = rnti; + } else { + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + } + dci_pdu->AggregationLevel = sched_ctrl->aggregation_level; + dci_pdu->CceIndex = sched_ctrl->cce_index; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + + dci_pdu_rel15_t uldci_payload; + memset(&uldci_payload, 0, sizeof(uldci_payload)); + int n_ubwp=1; + if (cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList) + n_ubwp = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; + + config_uldci(sched_ctrl->active_ubwp, + ubwpd, + scc, + pusch_pdu, + &uldci_payload, + ps->dci_format, + ps->time_domain_allocation, + UE_info->UE_sched_ctrl[UE_id].tpc0, + n_ubwp, + bwpid); + fill_dci_pdu_rel15(scc, + cg, + dci_pdu, + &uldci_payload, + ps->dci_format, + rnti_types[0], + pusch_pdu->bwp_size, + bwpid); + + memset(sched_pusch, 0, sizeof(*sched_pusch)); + } +} diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 74c6841a3a..91221276b0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -31,30 +31,30 @@ #ifndef __LAYER2_NR_MAC_PROTO_H__ #define __LAYER2_NR_MAC_PROTO_H__ -#include "PHY/defs_gNB.h" - #include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h" #include "NR_TAG-Id.h" -#define MAX_ACK_BITS 2 //only format 0 is available for now - void set_cset_offset(uint16_t); void mac_top_init_gNB(void); void config_common(int Mod_idP, + int ssb_SubcarrierOffset, int pdsch_AntennaPorts, + int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc ); -int rrc_mac_config_req_gNB(module_id_t Mod_idP, - int ssb_SubcarrierOffset, +int rrc_mac_config_req_gNB(module_id_t Mod_idP, + int ssb_SubcarrierOffset, int pdsch_AntennaPorts, + int pusch_AntennaPorts, + int sib1_tda, NR_ServingCellConfigCommon_t *scc, - int nsa_flag, - uint32_t rnti, - NR_CellGroupConfig_t *secondaryCellGroup - ); + NR_BCCH_BCH_Message_t *mib, + int add_ue, + uint32_t rnti, + NR_CellGroupConfig_t *CellGroup); void clear_nr_nfapi_information(gNB_MAC_INST * gNB, int CC_idP, @@ -62,22 +62,39 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, sub_frame_t subframeP); void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame_txP, sub_frame_t slot_txP, frame_t frame_rxP, sub_frame_t slot_rxP); -int nr_generate_dlsch_pdu(module_id_t Mod_idP, - unsigned char *sdus_payload, - unsigned char *mac_pdu, - unsigned char num_sdus, - unsigned short *sdu_lengths, - unsigned char *sdu_lcids, - unsigned char drx_cmd, - unsigned char *ue_cont_res_id, - unsigned short post_padding); +/* \brief main DL scheduler function. Calls a preprocessor to decide on + * resource allocation, then "post-processes" resource allocation (nFAPI + * messages, statistics, HARQ handling, CEs, ... */ +void nr_schedule_ue_spec(module_id_t module_id, + frame_t frame, + sub_frame_t slot); -void nr_schedule_ue_spec(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); +uint32_t schedule_control_sib1(module_id_t module_id, + int CC_id, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + int time_domain_allocation, + int startSymbolIndex, + int nrOfSymbols, + uint16_t dlDmrsSymbPos, + uint8_t candidate_idx, + int num_total_bytes); -void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); +/* \brief default FR1 DL preprocessor init routine, returns preprocessor to call */ +nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(module_id_t module_id, int CC_id); + +void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); + +void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); + +/* \brief main UL scheduler function. Calls a preprocessor to decide on + * resource allocation, then "post-processes" resource allocation (nFAPI + * messages, statistics, HARQ handling, ... */ +void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot); + +/* \brief default FR1 UL preprocessor init routine, returns preprocessor to call */ +nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(module_id_t module_id, int CC_id); /////// Random Access MAC-PHY interface functions and primitives /////// @@ -94,15 +111,20 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); void nr_initiate_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, uint16_t preamble_index, uint8_t freq_index, uint8_t symbol, int16_t timing_offset); -void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP); +void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t *ra); int nr_allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, sub_frame_t slotP, int test_only); -void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc, +void nr_get_Msg3alloc(module_id_t module_id, + int CC_id, + NR_ServingCellConfigCommon_t *scc, NR_BWP_Uplink_t *ubwp, sub_frame_t current_subframe, frame_t current_frame, - NR_RA_t *ra); + NR_RA_t *ra, + int16_t *tdd_beam_association); + +void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); /* \brief Function in gNB to fill RAR pdu when requested by PHY. @param ra Instance of RA resources of gNB @@ -114,6 +136,15 @@ void nr_fill_rar(uint8_t Mod_idP, uint8_t * dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); +void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_ServingCellConfigCommon_t *scc, + int round, + int startSymbolAndLength, + rnti_t rnti, int scs, + int bwp_size, int bwp_start, + int mappingtype, int fh, + int msg3_first_rb, int msg3_nb_rb); + void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); @@ -121,53 +152,65 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs); /////// Phy test scheduler /////// +/* \brief preprocessor for phytest: schedules UE_id 0 with fixed MCS on all + * freq resources */ +void nr_preprocessor_phytest(module_id_t module_id, + frame_t frame, + sub_frame_t slot); +/* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a + * fixed set of resources */ +bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot); + void nr_schedule_css_dlsch_phytest(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); -int configure_fapi_dl_pdu(int Mod_id, - nfapi_nr_dl_tti_request_body_t *dl_req, - NR_sched_pucch *pucch_sched, - uint8_t *mcsIndex, - uint16_t *rbSize, - uint16_t *rbStart); +void handle_nr_uci_pucch_0_1(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01); +void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234); -void config_uldci(NR_BWP_Uplink_t *ubwp, - nfapi_nr_pusch_pdu_t *pusch_pdu, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + +void config_uldci(const NR_BWP_Uplink_t *ubwp, + const NR_BWP_UplinkDedicated_t *ubwpd, + const NR_ServingCellConfigCommon_t *scc, + const nfapi_nr_pusch_pdu_t *pusch_pdu, dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, int *rnti_types, + int dci_format, int time_domain_assignment, - int n_ubwp, int bwp_id); + uint8_t tpc, + int n_ubwp, + int bwp_id); -void configure_fapi_dl_Tx(module_id_t Mod_idP, - frame_t frameP, - sub_frame_t slotP, - nfapi_nr_dl_tti_request_body_t *dl_req, - nfapi_nr_pdu_t *tx_req, - int tbs_bytes, - int16_t pdu_index); +void nr_schedule_pucch(int Mod_idP, + frame_t frameP, + sub_frame_t slotP); -void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, - frame_t frameP, - sub_frame_t slotP, - NR_sched_pucch *pucch_sched, - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_config); +void nr_csirs_scheduling(int Mod_idP, + frame_t frame, + sub_frame_t slot, + int n_slots_frame); -void nr_schedule_uss_ulsch_phytest(int Mod_idP, - frame_t frameP, - sub_frame_t slotP); +void nr_csi_meas_reporting(int Mod_idP, + frame_t frameP, + sub_frame_t slotP); -void nr_update_pucch_scheduling(int Mod_idP, - int UE_id, - frame_t frameP, - sub_frame_t slotP, - int slots_per_tdd, - int *pucch_id); +int nr_acknack_scheduling(int Mod_idP, + int UE_id, + frame_t frameP, + sub_frame_t slotP, + int r_pucch, + int do_common); void get_pdsch_to_harq_feedback(int Mod_idP, int UE_id, + int bwp_id, NR_SearchSpace__searchSpaceType_PR ss_type, + int *max_fb_time, uint8_t *pdsch_to_harq_feedback); void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, @@ -190,47 +233,81 @@ int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space, */ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, - NR_ServingCellConfigCommon_t *scc, - NR_BWP_Uplink_t *bwp, + NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *CellGroup, + NR_BWP_Uplink_t *bwp, + NR_BWP_UplinkDedicated_t *bwpd, + uint16_t rnti, uint8_t pucch_resource, - uint16_t O_uci, + uint16_t O_csi, uint16_t O_ack, - uint8_t SR_flag); + uint8_t O_sr, + int r_pucch); void find_search_space(int ss_type, NR_BWP_Downlink_t *bwp, NR_SearchSpace_t *ss); -int nr_configure_pdcch(gNB_MAC_INST *nr_mac, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, - uint16_t rnti, - int ss_type, - NR_SearchSpace_t *ss, - NR_ServingCellConfigCommon_t *scc, - NR_BWP_Downlink_t *bwp); +void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, + NR_SearchSpace_t *ss, + NR_ControlResourceSet_t *coreset, + NR_ServingCellConfigCommon_t *scc, + NR_BWP_t *bwp, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); -void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *secondaryCellGroup, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, +void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, + const NR_CellGroupConfig_t *CellGroup, + nfapi_nr_dl_dci_pdu_t *pdcch_dci_pdu, dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, - int *rnti_types, + int dci_formats, + int rnti_types, int N_RB, int bwp_id); -void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, +void prepare_dci(const NR_CellGroupConfig_t *CellGroup, dci_pdu_rel15_t *dci_pdu_rel15, nr_dci_format_t format, int bwp_id); -void find_aggregation_candidates(uint8_t *aggregation_level, - uint8_t *nr_of_candidates, - NR_SearchSpace_t *ss); +/* find coreset within the search space */ +NR_ControlResourceSet_t *get_coreset(module_id_t module_idP, + NR_ServingCellConfigCommon_t *scc, + void *bwp, + NR_SearchSpace_t *ss, + NR_SearchSpace__searchSpaceType_PR ss_type); + +/* find a search space within a BWP */ +NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, + NR_BWP_DownlinkDedicated_t *bwp_Dedicated, + NR_SearchSpace__searchSpaceType_PR target_ss); + +long get_K2(NR_ServingCellConfigCommon_t *scc, NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu); + +void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc, + const NR_CellGroupConfig_t *secondaryCellGroup, + const NR_BWP_Downlink_t *bwp, + const NR_BWP_DownlinkDedicated_t *bwpd0, + int tda, + const long dci_format, + NR_pdsch_semi_static_t *ps); + +void nr_set_pusch_semi_static(const NR_ServingCellConfigCommon_t *scc, + const NR_BWP_Uplink_t *ubwp, + const NR_BWP_UplinkDedicated_t *ubwpd, + long dci_format, + int tda, + uint8_t num_dmrs_cdm_grps_no_data, + NR_pusch_semi_static_t *ps); + +uint8_t nr_get_tpc(int target, uint8_t cqi, int incr); int get_spf(nfapi_nr_config_request_scf_t *cfg); int to_absslot(nfapi_nr_config_request_scf_t *cfg,int frame,int slot); +int get_nrofHARQ_ProcessesForPDSCH(e_NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH n); + void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, int x_overhead, uint8_t numdmrscdmgroupnodata, @@ -247,20 +324,37 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); -void dump_nr_ue_list(NR_UE_list_t *listP, int ul_flag); +/* Functions to manage an NR_list_t */ +void dump_nr_list(NR_list_t *listP); +void create_nr_list(NR_list_t *listP, int len); +void destroy_nr_list(NR_list_t *list); +void add_nr_list(NR_list_t *listP, int id); +void remove_nr_list(NR_list_t *listP, int id); +void add_tail_nr_list(NR_list_t *listP, int id); +void add_front_nr_list(NR_list_t *listP, int id); +void remove_front_nr_list(NR_list_t *listP); int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP); -int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP); +int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP); + +int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup); + +void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti); + +void nr_mac_remove_ra_rnti(module_id_t mod_id, rnti_t rnti); int allocate_nr_CCEs(gNB_MAC_INST *nr_mac, - int bwp_id, - int coreset_id, + NR_BWP_Downlink_t *bwp, + NR_ControlResourceSet_t *coreset, int aggregation, - int search_space, // 0 common, 1 ue-specific - int UE_id, - int m - ); + uint16_t Y, + int m, + int nr_of_candidates); + +int nr_get_default_pucch_res(int pucch_ResourceCommon); + +void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP); int get_dlscs(nfapi_nr_config_request_t *cfg); @@ -268,8 +362,6 @@ int get_ulscs(nfapi_nr_config_request_t *cfg); int get_symbolsperslot(nfapi_nr_config_request_t *cfg); -int32_t get_nr_uldl_offset(int nr_bandP); - void config_nr_mib(int Mod_idP, int CC_idP, int p_gNBP, @@ -280,24 +372,24 @@ void config_nr_mib(int Mod_idP, int cellBarred, int intraFreqReselection); +int nr_write_ce_dlsch_pdu(module_id_t module_idP, + const NR_UE_sched_ctrl_t *ue_sched_ctl, + unsigned char *mac_pdu, + unsigned char drx_cmd, + unsigned char *ue_cont_res_id); -void nr_generate_Msg2(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP); +void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); -void nr_schedule_reception_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP); +void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); - -void nr_process_mac_pdu( - module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - uint8_t *pduP, - uint16_t mac_pdu_len); +void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra); int binomial(int n, int k); +bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot); + +void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart, int CC_id); + /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of gNB @@ -315,6 +407,45 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, const rnti_t rntiP, uint8_t * sduP, const uint16_t sdu_lenP, - const uint16_t timing_advance, const uint8_t ul_cqi); + const uint16_t timing_advance, + const uint8_t ul_cqi, + const uint16_t rssi); +void create_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl, + const NR_PDSCH_ServingCellConfig_t *pdsch); + +void handle_nr_ul_harq(const int CC_idP, + module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_crc_t *crc_pdu); + +int16_t ssb_index_from_prach(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + uint16_t preamble_index, + uint8_t freq_index, + uint8_t symbol); + +void find_SSB_and_RO_available(module_id_t module_idP); + +void set_dl_dmrs_ports(NR_pdsch_semi_static_t *ps); + +void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp); +void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp); + +bool find_free_CCE(module_id_t module_id, sub_frame_t slot, int UE_id); + +bool nr_find_nb_rb(uint16_t Qm, + uint16_t R, + uint16_t nb_symb_sch, + uint16_t nb_dmrs_prb, + uint32_t bytes, + uint16_t nb_rb_max, + uint32_t *tbs, + uint16_t *nb_rb); + +void nr_sr_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP); + +void dump_mac_stats(gNB_MAC_INST *gNB, char *output, int strlen, bool reset_rsrp); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 56e020838d..5e5de9a8e1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -34,7 +34,7 @@ #include "NR_MAC_COMMON/nr_mac_extern.h" #include "assertions.h" -#include "LAYER2/PDCP_v10.1.0/pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "RRC/NR/nr_rrc_defs.h" #include "common/utils/LOG/log.h" //#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" @@ -45,11 +45,98 @@ extern RAN_CONTEXT_t RC; +#define MACSTATSSTRLEN 16384 + +void *nrmac_stats_thread(void *arg) { + + gNB_MAC_INST *gNB = (gNB_MAC_INST *)arg; + + char output[MACSTATSSTRLEN]; + memset(output,0,MACSTATSSTRLEN); + FILE *fd=fopen("nrMAC_stats.log","w"); + AssertFatal(fd!=NULL,"Cannot open nrMAC_stats.log, error %s\n",strerror(errno)); + + while (oai_exit == 0) { + dump_mac_stats(gNB,output,MACSTATSSTRLEN,false); + fprintf(fd,"%s\n",output); + fflush(fd); + usleep(200000); + fseek(fd,0,SEEK_SET); + } + fclose(fd); + return NULL; +} + +void clear_mac_stats(gNB_MAC_INST *gNB) { + memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t)); +} + +void dump_mac_stats(gNB_MAC_INST *gNB, char *output, int strlen, bool reset_rsrp) +{ + NR_UE_info_t *UE_info = &gNB->UE_info; + int num = 1; + + int stroff=0; + if (UE_info->num_UEs == 0) return; + + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + + const NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0; + stroff+=sprintf(output+stroff,"UE ID %d RNTI %04x (%d/%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n", + UE_id, + UE_info->rnti[UE_id], + num++, + UE_info->num_UEs, + sched_ctrl->ph, + sched_ctrl->pcmax, + avg_rsrp, + stats->num_rsrp_meas); + + stroff+=sprintf(output+stroff,"UE %d: dlsch_rounds %"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS %d\n", + UE_id, + stats->dlsch_rounds[0], stats->dlsch_rounds[1], + stats->dlsch_rounds[2], stats->dlsch_rounds[3], + stats->dlsch_errors, + stats->pucch0_DTX, + sched_ctrl->dl_bler_stats.bler, + sched_ctrl->dl_bler_stats.mcs); + if (reset_rsrp) { + stats->num_rsrp_meas = 0; + stats->cumul_rsrp = 0; + } + stroff+=sprintf(output+stroff,"UE %d: dlsch_total_bytes %"PRIu64"\n", UE_id, stats->dlsch_total_bytes); + stroff+=sprintf(output+stroff,"UE %d: ulsch_rounds %"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64", ulsch_DTX %d, ulsch_errors %"PRIu64"\n", + UE_id, + stats->ulsch_rounds[0], stats->ulsch_rounds[1], + stats->ulsch_rounds[2], stats->ulsch_rounds[3], + stats->ulsch_DTX, + stats->ulsch_errors); + stroff+=sprintf(output+stroff, + "UE %d: ulsch_total_bytes_scheduled %"PRIu64", ulsch_total_bytes_received %"PRIu64"\n", + UE_id, + stats->ulsch_total_bytes_scheduled, stats->ulsch_total_bytes_rx); + for (int lc_id = 0; lc_id < 63; lc_id++) { + if (stats->lc_bytes_tx[lc_id] > 0) { + stroff+=sprintf(output+stroff, "UE %d: LCID %d: %"PRIu64" bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]); + LOG_D(NR_MAC, "UE %d: LCID %d: %"PRIu64" bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]); + } + if (stats->lc_bytes_rx[lc_id] > 0) { + stroff+=sprintf(output+stroff, "UE %d: LCID %d: %"PRIu64" bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]); + LOG_D(NR_MAC, "UE %d: LCID %d: %"PRIu64" bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]); + } + } + } + print_meas_log(&gNB->eNB_scheduler, "DL & UL scheduling timing stats", NULL, NULL, output+stroff); +} + + void mac_top_init_gNB(void) { module_id_t i; int list_el; - NR_UE_list_t *UE_list; + NR_UE_info_t *UE_info; gNB_MAC_INST *nrmac; LOG_I(MAC, "[MAIN] Init function start:nb_nr_macrlc_inst=%d\n",RC.nb_nr_macrlc_inst); @@ -81,6 +168,17 @@ void mac_top_init_gNB(void) RC.nrmac[i]->ul_handle = 0; + RC.nrmac[i]->first_MIB = true; + + if (get_softmodem_params()->phy_test) { + RC.nrmac[i]->pre_processor_dl = nr_preprocessor_phytest; + RC.nrmac[i]->pre_processor_ul = nr_ul_preprocessor_phytest; + } else { + RC.nrmac[i]->pre_processor_dl = nr_init_fr1_dlsch_preprocessor(i, 0); + RC.nrmac[i]->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(i, 0); + } + pthread_create(&RC.nrmac[i]->stats_thread,NULL,nrmac_stats_thread,(void*)RC.nrmac[i]); + }//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++) AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n"); @@ -88,12 +186,13 @@ void mac_top_init_gNB(void) // These should be out of here later pdcp_layer_init(); - if(IS_SOFTMODEM_NOS1) - nr_ip_over_LTE_DRB_preconfiguration(); + if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) + nr_DRB_preconfiguration(0x1234); rrc_init_nr_global_param(); - }else { + + } else { RC.nrmac = NULL; } @@ -103,26 +202,12 @@ void mac_top_init_gNB(void) nrmac = RC.nrmac[i]; nrmac->if_inst = NR_IF_Module_init(i); - UE_list = &nrmac->UE_list; - UE_list->num_UEs = 0; - UE_list->head = -1; - UE_list->head_ul = -1; - UE_list->avail = 0; - - for (list_el = 0; list_el < MAX_MOBILES_PER_GNB - 1; list_el++) { - UE_list->next[list_el] = list_el + 1; - UE_list->next_ul[list_el] = list_el + 1; - UE_list->active[list_el] = FALSE; - for (int list_harq = 0; list_harq < NR_MAX_NB_HARQ_PROCESSES; list_harq++) { - UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].round = 0; - UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].ndi = 0; - UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].is_waiting = 0; - } + UE_info = &nrmac->UE_info; + UE_info->num_UEs = 0; + create_nr_list(&UE_info->list, MAX_MOBILES_PER_GNB); + for (list_el = 0; list_el < MAX_MOBILES_PER_GNB; list_el++) { + UE_info->active[list_el] = false; } - - UE_list->next[list_el] = -1; - UE_list->next_ul[list_el] = -1; - UE_list->active[list_el] = FALSE; } srand48(0); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index f84e7a900c..45e0a5b52b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -68,21 +68,41 @@ #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" #include "NR_TAG.h" +#include + + /* Defs */ #define MAX_NUM_BWP 2 #define MAX_NUM_CORESET 2 #define MAX_NUM_CCE 90 +#define MAX_HARQ_ROUNDS 4 /*!\brief Maximum number of random access process */ #define NR_NB_RA_PROC_MAX 4 +#define MAX_NUM_OF_SSB 64 + +/*! \brief NR_list_t is a "list" (of users, HARQ processes, slices, ...). + * Especially useful in the scheduler and to keep "classes" of users. */ +typedef struct { + int head; + int *next; + int tail; + int len; +} NR_list_t; typedef enum { RA_IDLE = 0, Msg2 = 1, WAIT_Msg3 = 2, - Msg4 = 3, - WAIT_Msg4_ACK = 4 + Msg3_retransmission = 3, + Msg4 = 4, + WAIT_Msg4_ACK = 5 } RA_gNB_state_t; +typedef struct NR_preamble_ue { + uint8_t num_preambles; + uint8_t *preamble_list; +} NR_preamble_ue_t; + /*! \brief gNB template for the Random access information */ typedef struct { /// Flag to indicate this process is active @@ -125,6 +145,8 @@ typedef struct { uint8_t msg3_first_rb; /// Msg3 number of RB uint8_t msg3_nb_rb; + /// Msg3 BWP start + uint8_t msg3_bwp_start; /// Msg3 TPC command uint8_t msg3_TPC; /// Msg3 ULdelay command @@ -133,14 +155,26 @@ typedef struct { uint8_t msg3_cqireq; /// Round of Msg3 HARQ uint8_t msg3_round; - /// Msg3 pusch pdu - nfapi_nr_pusch_pdu_t pusch_pdu; + /// Flag to indicate if Msg3 carries a DCCH or DTCH message + bool msg3_dcch_dtch; /// TBS used for Msg4 int msg4_TBsize; /// MCS used for Msg4 int msg4_mcs; + /// MAC PDU length for Msg4 + int mac_pdu_length; /// RA search space NR_SearchSpace_t *ra_ss; + // Beam index + uint8_t beam_id; + /// CellGroup for UE that is to come (NSA is non-null, null for SA) + NR_CellGroupConfig_t *CellGroup; + /// Preambles for contention-free access + NR_preamble_ue_t preambles; + /// NSA: the UEs C-RNTI to use + rnti_t crnti; + /// CFRA flag + bool cfra; } NR_RA_t; /*! \brief gNB common channels */ @@ -167,16 +201,27 @@ typedef struct { uint32_t PCCH_alloc_pdu; /// Outgoing PCCH pdu for PHY PCCH_PDU PCCH_pdu; - /// Outgoing RAR pdu for PHY - RAR_PDU RAR_pdu; /// Template for RA computations NR_RA_t ra[NR_NB_RA_PROC_MAX]; /// VRB map for common channels - uint8_t vrb_map[100]; - /// VRB map for common channels and retransmissions by PHICH - uint8_t vrb_map_UL[100]; + uint16_t vrb_map[275]; + /// VRB map for common channels and PUSCH, dynamically allocated because + /// length depends on number of slots and RBs + uint16_t *vrb_map_UL; /// number of subframe allocation pattern available for MBSFN sync area uint8_t num_sf_allocation_pattern; + ///Number of active SSBs + uint8_t num_active_ssb; + //Total available prach occasions per configuration period + uint32_t total_prach_occasions_per_config_period; + //Total available prach occasions + uint32_t total_prach_occasions; + //Max Association period + uint8_t max_association_period; + //SSB index + uint8_t ssb_index[MAX_NUM_OF_SSB]; + //CB preambles for each SSB + uint8_t cb_preambles_per_ssb; } NR_COMMON_channels_t; @@ -208,8 +253,17 @@ typedef struct pdcchStateInd { uint8_t servingCellId; uint8_t coresetId; uint8_t tciStateId; + bool tci_present_inDCI; } pdcchStateInd_t; +typedef struct pucchSpatialRelation { + bool is_scheduled; + uint8_t servingCellId; + uint8_t bwpId; + uint8_t pucchResourceId; + bool s0tos7_actDeact[8]; +} pucchSpatialRelation_t; + typedef struct SPCSIReportingpucch { bool is_scheduled; uint8_t servingCellId; @@ -233,12 +287,14 @@ typedef struct pdschTciStatesActDeact { uint8_t bwpId; uint8_t highestTciStateActivated; bool tciStateActDeact[MAX_TCI_STATES]; + uint8_t codepoint[8]; } pdschTciStatesActDeact_t; typedef struct UE_info { sp_zp_csirs_t sp_zp_csi_rs; csi_rs_im_t csi_im; pdcchStateInd_t pdcch_state_ind; + pucchSpatialRelation_t pucch_spatial_relation; SPCSIReportingpucch_t SP_CSI_reporting_pucch; aperiodicCSI_triggerStateSelection_t aperi_CSI_trigger; pdschTciStatesActDeact_t pdsch_TCI_States_ActDeact; @@ -248,54 +304,368 @@ typedef struct UE_info { typedef struct NR_sched_pucch { int frame; int ul_slot; + bool sr_flag; + int csi_bits; + bool simultaneous_harqcsi; uint8_t dai_c; uint8_t timing_indicator; uint8_t resource_indicator; -} NR_sched_pucch; + int r_pucch; +} NR_sched_pucch_t; + +/* PUSCH semi-static configuration: as long as the TDA and DCI format remain + * the same over the same uBWP and search space, there is no need to + * recalculate all S/L, MCS table, or DMRS-related parameters over and over + * again. Hence, we store them in this struct for easy reference. */ +typedef struct NR_pusch_semi_static_t { + int dci_format; + int time_domain_allocation; + uint8_t num_dmrs_cdm_grps_no_data; + + int startSymbolIndex; + int nrOfSymbols; + + NR_PUSCH_Config_t *pusch_Config; + uint8_t transform_precoding; + uint8_t mcs_table; + + long mapping_type; + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; + uint16_t dmrs_config_type; + uint16_t ul_dmrs_symb_pos; + uint8_t num_dmrs_symb; + uint8_t N_PRB_DMRS; +} NR_pusch_semi_static_t; + +typedef struct NR_sched_pusch { + int frame; + int slot; + + /// RB allocation within active uBWP + uint16_t rbSize; + uint16_t rbStart; + + /// MCS + uint8_t mcs; + + /// TBS-related info + uint16_t R; + uint8_t Qm; + uint32_t tb_size; + + /// UL HARQ PID to use for this UE, or -1 for "any new" + int8_t ul_harq_pid; + + /// the Time Domain Allocation used for this transmission. Note that this is + /// only important for retransmissions; otherwise, the TDA in + /// NR_pusch_semi_static_t has precedence + int time_domain_allocation; +} NR_sched_pusch_t; + +/* PDSCH semi-static configuratio: as long as the TDA/DMRS/mcsTable remains the + * same, there is no need to recalculate all S/L or DMRS-related parameters + * over and over again. Hence, we store them in this struct for easy + * reference. */ +typedef struct NR_pdsch_semi_static { + int time_domain_allocation; + uint8_t numDmrsCdmGrpsNoData; + + int startSymbolIndex; + int nrOfSymbols; + uint8_t nrOfLayers; + uint8_t mcsTableIdx; + uint8_t dmrs_ports_id; + uint8_t N_PRB_DMRS; + uint8_t N_DMRS_SLOT; + uint16_t dl_dmrs_symb_pos; + nfapi_nr_dmrs_type_e dmrsConfigType; +} NR_pdsch_semi_static_t; + +typedef struct NR_sched_pdsch { + /// RB allocation within active BWP + uint16_t rbSize; + uint16_t rbStart; + + /// MCS-related infos + uint8_t mcs; + + /// TBS-related info + uint16_t R; + uint8_t Qm; + uint32_t tb_size; + + /// DL HARQ PID to use for this UE, or -1 for "any new" + int8_t dl_harq_pid; + + // pucch format allocation + uint8_t pucch_allocation; + + /// the Time Domain Allocation used for this transmission. Note that this is + /// only important for retransmissions; otherwise, the TDA in + /// NR_pdsch_semi_static_t has precedence + int time_domain_allocation; +} NR_sched_pdsch_t; typedef struct NR_UE_harq { - uint8_t is_waiting; + bool is_waiting; + uint8_t ndi; + uint8_t round; + uint16_t feedback_frame; + uint16_t feedback_slot; + + /* Transport block to be sent using this HARQ process, its size is in + * sched_pdsch */ + uint32_t tb[16384]; + uint32_t tb_size; + + /// sched_pdsch keeps information on MCS etc used for the initial transmission + NR_sched_pdsch_t sched_pdsch; +} NR_UE_harq_t; + +//! fixme : need to enhace for the multiple TB CQI report + +typedef struct NR_DL_bler_stats { + frame_t last_frame_slot; + float bler; + float rd2_bler; + uint8_t mcs; + uint64_t dlsch_rounds[8]; +} NR_DL_bler_stats_t; + +// +/*! As per spec 38.214 section 5.2.1.4.2 + * - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE shall report in + a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting. + * - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE shall report in a + single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB + resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with + multiple simultaneous spatial domain receive filter +*/ +#define MAX_NR_OF_REPORTED_RS 4 + +typedef enum NR_CSI_Report_Config { + CSI_Report_PR_cri_ri_li_pmi_cqi_report, + CSI_Report_PR_ssb_cri_report +} NR_CSI_Report_Config_PR; +struct CRI_RI_LI_PMI_CQI { + uint8_t cri; + uint8_t ri; + uint8_t li; + uint8_t pmi_x1; + uint8_t pmi_x2; + uint8_t wb_cqi_1tb; + uint8_t wb_cqi_2tb; +}; + +typedef struct CRI_SSB_RSRP { + uint8_t nr_ssbri_cri; + uint8_t CRI_SSBRI[MAX_NR_OF_REPORTED_RS]; + uint8_t RSRP; + uint8_t diff_RSRP[MAX_NR_OF_REPORTED_RS - 1]; +} CRI_SSB_RSRP_t; + +struct CSI_Report { + NR_CSI_Report_Config_PR present; + union Config_CSI_Report { + struct CRI_RI_LI_PMI_CQI cri_ri_li_pmi_cqi_report; + struct CRI_SSB_RSRP ssb_cri_report; + } choice; +}; + +#define MAX_SR_BITLEN 8 + +typedef struct { + uint8_t nb_ssbri_cri; + uint8_t cri_ssbri_bitlen; + uint8_t rsrp_bitlen; + uint8_t diff_rsrp_bitlen; +}L1_RSRP_bitlen_t; + +typedef struct{ + uint8_t cri_bitlen; + uint8_t ri_bitlen; + uint8_t li_bitlen; + uint8_t pmi_x1_bitlen; + uint8_t pmi_x2_bitlen; + uint8_t cqi_bitlen; +} CSI_Meas_bitlen_t; + +typedef struct nr_csi_report { + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; + long periodicity; + uint16_t offset; + long ** SSB_Index_list; + long ** CSI_Index_list; +// uint8_t nb_of_nzp_csi_report; + uint8_t nb_of_csi_ssb_report; + L1_RSRP_bitlen_t CSI_report_bitlen; + CSI_Meas_bitlen_t csi_meas_bitlen; +} nr_csi_report_t; + +/*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report + the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE + From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set + From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 + */ +#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16 + +typedef enum { + INACTIVE = 0, + ACTIVE_NOT_SCHED, + ACTIVE_SCHED +} NR_UL_harq_states_t; + +typedef struct NR_UE_ul_harq { + bool is_waiting; uint8_t ndi; uint8_t round; uint16_t feedback_slot; -} NR_UE_harq_t; + + /// sched_pusch keeps information on MCS etc used for the initial transmission + NR_sched_pusch_t sched_pusch; +} NR_UE_ul_harq_t; /*! \brief scheduling control information set through an API */ +#define MAX_CSI_REPORTS 48 typedef struct { - uint64_t dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch - uint64_t ulsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains ulsch - NR_sched_pucch *sched_pucch; - uint16_t ta_timer; + /// the currently active BWP in DL + NR_BWP_Downlink_t *active_bwp; + /// the currently active BWP in UL + NR_BWP_Uplink_t *active_ubwp; + /// CCE index and aggregation, should be coherent with cce_list + NR_SearchSpace_t *search_space; + NR_ControlResourceSet_t *coreset; + + /// CCE index and Aggr. Level are shared for PUSCH/PDSCH allocation decisions + /// corresponding to the sched_pusch/sched_pdsch structures below + int cce_index; + uint8_t aggregation_level; + /// maximum aggregation level for UE, can be used to select level + int maxL; + /// PUCCH scheduling information. Array of two: HARQ+SR in the first field, + /// CSI in second. This order is important for nr_acknack_scheduling()! + NR_sched_pucch_t sched_pucch[2]; + + /// PUSCH semi-static configuration: is not cleared across TTIs + NR_pusch_semi_static_t pusch_semi_static; + /// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI + NR_sched_pusch_t sched_pusch; + + /// uplink bytes that are currently scheduled + int sched_ul_bytes; + /// estimation of the UL buffer size + int estimated_ul_buffer; + + /// PHR info: power headroom level (dB) + int ph; + /// PHR info: nominal UE transmit power levels (dBm) + int pcmax; + + /// PDSCH semi-static configuration: is not cleared across TTIs + NR_pdsch_semi_static_t pdsch_semi_static; + /// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI + NR_sched_pdsch_t sched_pdsch; + /// For UL synchronization: store last UL scheduling grant + frame_t last_ul_frame; + sub_frame_t last_ul_slot; + + /// total amount of data awaiting for this UE + uint32_t num_total_bytes; + /// per-LC status data + mac_rlc_status_resp_t rlc_status[MAX_NUM_LCID]; + + /// Estimation of HARQ from BLER + NR_DL_bler_stats_t dl_bler_stats; + + int lcid_mask; + int lcid_to_schedule; + uint16_t ta_frame; int16_t ta_update; + bool ta_apply; + uint8_t tpc0; + uint8_t tpc1; + int raw_rssi; + int pusch_snrx10; + int pucch_snrx10; + uint16_t ul_rssi; uint8_t current_harq_pid; + int pusch_consecutive_dtx_cnt; + int pucch_consecutive_dtx_cnt; + int ul_failure; + struct CSI_Report CSI_report[MAX_CSI_REPORTS]; + bool SR; + + /// information about every HARQ process NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; - int dummy; + /// HARQ processes that are free + NR_list_t available_dl_harq; + /// HARQ processes that await feedback + NR_list_t feedback_dl_harq; + /// HARQ processes that await retransmission + NR_list_t retrans_dl_harq; + /// information about every UL HARQ process + NR_UE_ul_harq_t ul_harq_processes[NR_MAX_NB_HARQ_PROCESSES]; + /// UL HARQ processes that are free + NR_list_t available_ul_harq; + /// UL HARQ processes that await feedback + NR_list_t feedback_ul_harq; + /// UL HARQ processes that await retransmission + NR_list_t retrans_ul_harq; NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information } NR_UE_sched_ctrl_t; -typedef struct NR_preamble_ue { - uint8_t num_preambles; - uint8_t *preamble_list; -} NR_preamble_ue; +typedef struct { + boolean_t fiveG_connected; + uicc_t *uicc; +} NRUEcontext_t; + +typedef struct { + uint64_t lc_bytes_tx[64]; + uint64_t lc_bytes_rx[64]; + uint64_t dlsch_rounds[8]; + uint64_t dlsch_errors; + uint64_t dlsch_total_bytes; + int dlsch_current_bytes; + uint64_t ulsch_rounds[8]; + uint64_t ulsch_errors; + uint32_t ulsch_DTX; + uint64_t ulsch_total_bytes_scheduled; + uint64_t ulsch_total_bytes_rx; + int ulsch_current_bytes; + uint32_t pucch0_DTX; + int cumul_rsrp; + uint8_t num_rsrp_meas; +} NR_mac_stats_t; + /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ +#define MAX_CSI_REPORTCONFIG 48 typedef struct { - DLSCH_PDU DLSCH_pdu[4][MAX_MOBILES_PER_GNB]; /// scheduling control info + nr_csi_report_t csi_report_template[MAX_MOBILES_PER_GNB][MAX_CSI_REPORTCONFIG]; NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB]; - int next[MAX_MOBILES_PER_GNB]; - int head; - int next_ul[MAX_MOBILES_PER_GNB]; - int head_ul; - int avail; + NR_mac_stats_t mac_stats[MAX_MOBILES_PER_GNB]; + NR_list_t list; int num_UEs; - boolean_t active[MAX_MOBILES_PER_GNB]; - boolean_t fiveG_connected[MAX_MOBILES_PER_GNB]; + + bool active[MAX_MOBILES_PER_GNB]; rnti_t rnti[MAX_MOBILES_PER_GNB]; - rnti_t tc_rnti[MAX_MOBILES_PER_GNB]; - NR_preamble_ue preambles[MAX_MOBILES_PER_GNB]; - NR_CellGroupConfig_t *secondaryCellGroup[MAX_MOBILES_PER_GNB]; -} NR_UE_list_t; + NR_CellGroupConfig_t *CellGroup[MAX_MOBILES_PER_GNB]; + /// CCE indexing + int Y[MAX_MOBILES_PER_GNB][3][160]; + int m[MAX_MOBILES_PER_GNB]; + int num_pdcch_cand[MAX_MOBILES_PER_GNB][MAX_NUM_CORESET]; + // UE selected beam index + uint8_t UE_beam_index[MAX_MOBILES_PER_GNB]; + bool Msg4_ACKed[MAX_MOBILES_PER_GNB]; +} NR_UE_info_t; + +typedef void (*nr_pp_impl_dl)(module_id_t mod_id, + frame_t frame, + sub_frame_t slot); +typedef bool (*nr_pp_impl_ul)(module_id_t mod_id, + frame_t frame, + sub_frame_t slot); /*! \brief top level eNB MAC structure */ typedef struct gNB_MAC_INST_s { @@ -305,38 +675,53 @@ typedef struct gNB_MAC_INST_s { eth_params_t eth_params_s; /// Module module_id_t Mod_id; - /// frame counter - frame_t frame; - /// slot counter - int slot; /// timing advance group NR_TAG_t *tag; /// Pointer to IF module instance for PHY NR_IF_Module_t *if_inst; - /// TA command - int ta_command; - /// MAC CE flag indicating TA length - int ta_len; + pthread_t stats_thread; + /// Pusch target SNR + int pusch_target_snrx10; + /// Pucch target SNR + int pucch_target_snrx10; + /// PUCCH Failure threshold (compared to consecutive PUCCH DTX) + int pucch_failure_thres; + /// PUSCH Failure threshold (compared to consecutive PUSCH DTX) + int pusch_failure_thres; + /// Subcarrier Offset + int ssb_SubcarrierOffset; + /// SIB1 Time domain allocation + int sib1_tda; /// Common cell resources NR_COMMON_channels_t common_channels[NFAPI_CC_MAX]; /// current PDU index (BCH,DLSCH) uint16_t pdu_index[NFAPI_CC_MAX]; - + int num_ulprbbl; + int ulprbbl[275]; /// NFAPI Config Request Structure nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX]; /// NFAPI DL Config Request Structure nfapi_nr_dl_tti_request_t DL_req[NFAPI_CC_MAX]; - /// NFAPI UL TTI Request Structure (this is from the new SCF specs) - nfapi_nr_ul_tti_request_t UL_tti_req[NFAPI_CC_MAX]; + /// a PDCCH PDU groups DCIs per BWP and CORESET. The following structure + /// keeps pointers to PDCCH PDUs within DL_req so that we can easily track + /// PDCCH PDUs per CC/BWP/CORESET + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_idx[NFAPI_CC_MAX][MAX_NUM_BWP][MAX_NUM_CORESET]; + /// NFAPI UL TTI Request Structure, simple pointer into structure + /// UL_tti_req_ahead for current frame/slot + nfapi_nr_ul_tti_request_t *UL_tti_req[NFAPI_CC_MAX]; + /// NFAPI UL TTI Request Structure for future TTIs, dynamically allocated + /// because length depends on number of slots + nfapi_nr_ul_tti_request_t *UL_tti_req_ahead[NFAPI_CC_MAX]; /// NFAPI HI/DCI0 Config Request Structure nfapi_nr_ul_dci_request_t UL_dci_req[NFAPI_CC_MAX]; /// NFAPI DL PDU structure nfapi_nr_tx_data_request_t TX_req[NFAPI_CC_MAX]; - NR_UE_list_t UE_list; + NR_UE_info_t UE_info; /// UL handle uint32_t ul_handle; + //UE_info_t UE_info; // MAC function execution peformance profiler /// processing time of eNB scheduler @@ -361,6 +746,39 @@ typedef struct gNB_MAC_INST_s { time_stats_t schedule_pch; /// CCE lists int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE]; + /// list of allocated beams per period + int16_t *tdd_beam_association; + + /// bitmap of DLSCH slots, can hold up to 160 slots + uint64_t dlsch_slot_bitmap[3]; + /// Lookup for preferred time domain allocation for BWP, in DL, slots + /// dynamically allocated + int *preferred_dl_tda[MAX_NUM_BWP]; + /// bitmap of ULSCH slots, can hold up to 160 slots + uint64_t ulsch_slot_bitmap[3]; + /// Lookup for preferred time domain allocation for UL BWP, dynamically + /// allocated. The index refers to the DL slot, and the indicated TDA's k2 + /// points to the right UL slot + int *preferred_ul_tda[MAX_NUM_BWP]; + + /// maximum number of slots before a UE will be scheduled ULSCH automatically + uint32_t ulsch_max_frame_inactivity; + + /// DL preprocessor for differentiated scheduling + nr_pp_impl_dl pre_processor_dl; + /// UL preprocessor for differentiated scheduling + nr_pp_impl_ul pre_processor_ul; + + NR_UE_sched_ctrl_t *sched_ctrlCommon; + uint16_t cset0_bwp_start; + uint16_t cset0_bwp_size; + NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config[64]; + + bool first_MIB; + double dl_bler_target_upper; + double dl_bler_target_lower; + double dl_rd2_bler_threshold; + uint8_t dl_max_mcs; } gNB_MAC_INST; #endif /*__LAYER2_NR_MAC_GNB_H__ */ diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 3667af2698..cddb666bfd 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -57,10 +57,11 @@ #include "openair2/RRC/NAS/nas_config.h" #include "intertask_interface.h" #include "openair3/S1AP/s1ap_eNB.h" - +#include # include "gtpv1u_eNB_task.h" # include "gtpv1u.h" +#include #include "ENB_APP/enb_config.h" @@ -83,9 +84,94 @@ hash_table_t *pdcp_coll_p = NULL; static int mbms_socket = -1; #endif +uint32_t Pdcp_stats_tx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB]; +uint32_t Pdcp_stats_tx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_throughput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_tx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB]; +uint32_t Pdcp_stats_rx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_goodput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +uint32_t Pdcp_stats_rx_outoforder[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +int pdcp_pc5_sockfd; +struct sockaddr_in prose_ctrl_addr; +struct sockaddr_in prose_pdcp_addr; +struct sockaddr_in pdcp_sin; /* pdcp module parameters and related functions*/ static pdcp_params_t pdcp_params= {0,NULL}; +rnti_t pdcp_UE_UE_module_id_to_rnti[MAX_MOBILES_PER_ENB]; +rnti_t pdcp_eNB_UE_instance_to_rnti[MAX_MOBILES_PER_ENB]; // for noS1 mode +unsigned int pdcp_eNB_UE_instance_to_rnti_index; + +signed int pdcp_2_nas_irq; +pdcp_stats_t UE_pdcp_stats[MAX_MOBILES_PER_ENB]; +pdcp_stats_t eNB_pdcp_stats[NUMBER_OF_eNB_MAX]; + +static pdcp_mbms_t pdcp_mbms_array_ue[MAX_MOBILES_PER_ENB][LTE_maxServiceCount][LTE_maxSessionPerPMCH]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h +static pdcp_mbms_t pdcp_mbms_array_eNB[NUMBER_OF_eNB_MAX][LTE_maxServiceCount][LTE_maxSessionPerPMCH]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h +static sdu_size_t pdcp_input_sdu_remaining_size_to_read; +static sdu_size_t pdcp_output_header_bytes_to_write; +static sdu_size_t pdcp_output_sdu_bytes_to_write; +notifiedFIFO_t pdcp_sdu_list; + +pdcp_enb_t pdcp_enb[MAX_NUM_CCs]; + + +extern volatile int oai_exit; + +pthread_t pdcp_stats_thread_desc; + +void *pdcp_stats_thread(void *param) { + + FILE *fd; + int old_byte_cnt[MAX_MOBILES_PER_ENB][NB_RB_MAX],old_byte_cnt_rx[MAX_MOBILES_PER_ENB][NB_RB_MAX]; + for (int i=0;i0) { + fprintf(fd,"PDCP: CRNTI %x, DRB %d: tx_bytes %d, DL Throughput %e\n", + pdcp_enb[0].rnti[UE_id],drb_id, + Pdcp_stats_tx_bytes[0][UE_id][drb_id], + (double)((Pdcp_stats_tx_bytes[0][UE_id][drb_id]-old_byte_cnt[UE_id][drb_id])<<3)); + fprintf(fd," rx_bytes %d, UL Throughput %e\n", + Pdcp_stats_rx_bytes[0][UE_id][drb_id], + (double)((Pdcp_stats_rx_bytes[0][UE_id][drb_id]-old_byte_cnt_rx[UE_id][drb_id])<<3)); + old_byte_cnt[UE_id][drb_id]=Pdcp_stats_tx_bytes[0][UE_id][drb_id]; + old_byte_cnt_rx[UE_id][drb_id]=Pdcp_stats_rx_bytes[0][UE_id][drb_id]; + } + } + fclose(fd); + } + return(NULL); +} uint64_t get_pdcp_optmask(void) { return pdcp_params.optmask; @@ -358,16 +444,7 @@ boolean_t pdcp_data_req( LOG_D(PDCP, "pdcp data req on drb %ld, size %d, rnti %x, node_type %d \n", rb_idP, pdcp_pdu_size, ctxt_pP->rnti, RC.rrc ? RC.rrc[ctxt_pP->module_id]->node_type: -1); - // The check on nos1 is done only for the use case of LTE stack running over 5g-nr PHY. This should be changed - // before future merge of develop with develop-nr and instead of a check of IS_SOFTMODEM_NOS1, we should use a check - // with a new execution option capturing the nr-ip-over-LTE-stack use case. - ngran_node_t node_type; - if (IS_SOFTMODEM_NOS1) - node_type = ngran_gNB; - else - node_type = RC.rrc[ctxt_pP->module_id]->node_type; - - if (ctxt_pP->enb_flag == ENB_FLAG_YES && NODE_IS_DU(node_type)) { //RC.rrc[ctxt_pP->module_id]->node_type + if (ctxt_pP->enb_flag == ENB_FLAG_YES && NODE_IS_DU(RC.rrc[ctxt_pP->module_id]->node_type)) { LOG_E(PDCP, "Can't be DU, bad node type %d \n", RC.rrc[ctxt_pP->module_id]->node_type); ret=FALSE; } else { @@ -403,7 +480,7 @@ boolean_t pdcp_data_req( // DL transfer MessageDef *message_p; // Note: the acyual task must be TASK_PDCP_ENB, but this task is not created - message_p = itti_alloc_new_message (TASK_PDCP_ENB, F1AP_DL_RRC_MESSAGE); + message_p = itti_alloc_new_message (TASK_PDCP_ENB, 0, F1AP_DL_RRC_MESSAGE); F1AP_DL_RRC_MESSAGE (message_p).rrc_container = &pdcp_pdu_p->data[0] ; F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = pdcp_pdu_size; F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id = 0; @@ -476,7 +553,7 @@ boolean_t pdcp_data_req( break; } - //LOG_I(PDCP,"ueid %d lcid %d tx seq num %d\n", pdcp_uid, rb_idP+rb_offset, current_sn); + LOG_D(PDCP,"ueid %d lcid %d tx seq num %d\n", pdcp_uid, (int)(rb_idP+rb_offset), current_sn); Pdcp_stats_tx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++; Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++; Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP; @@ -939,14 +1016,14 @@ pdcp_data_ind( sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX); AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY"); memcpy(>pu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset); - message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ); + message_p = itti_alloc_new_message(TASK_PDCP_ENB, 0, GTPV1U_ENB_TUNNEL_DATA_REQ); AssertFatal(message_p != NULL, "OUT OF MEMORY"); GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer = gtpu_buffer_p; GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length = sdu_buffer_sizeP - payload_offset; GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset = GTPU_HEADER_OVERHEAD_MAX; GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti = ctxt_pP->rnti; GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id = rb_id + 4; - itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); + itti_send_msg_to_task(TASK_VARIABLE, INSTANCE_DEFAULT, message_p); packet_forwarded = TRUE; } } else { @@ -996,17 +1073,7 @@ pdcp_data_ind( * TODO: be sure of this */ if (NFAPI_MODE == NFAPI_UE_STUB_PNF ) { -#ifdef UESIM_EXPANSION - - if (UE_NAS_USE_TUN) { - pdcpHead->inst = ctxt_pP->module_id; - } else { - pdcpHead->inst = 0; - } - -#else pdcpHead->inst = ctxt_pP->module_id; -#endif } else { // nfapi_mode if (UE_NAS_USE_TUN) { pdcpHead->inst = ctxt_pP->module_id; @@ -1014,7 +1081,13 @@ pdcp_data_ind( pdcpHead->inst = 1; } } // nfapi_mode - } + } else { + if (UE_NAS_USE_TUN) { + pdcpHead->inst = ctxt_pP->module_id; + } else if (ENB_NAS_USE_TUN) { + pdcpHead->inst = 0; + } + } } else { pdcpHead->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB); pdcpHead->inst = ctxt_pP->module_id; @@ -1035,7 +1108,7 @@ pdcp_data_ind( pushNotifiedFIFO(&pdcp_sdu_list, new_sdu_p); /* Print octets of incoming data in hexadecimal form */ - LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n", + LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n", sdu_buffer_sizeP - payload_offset + (int)sizeof(pdcp_data_ind_header_t), sdu_buffer_sizeP - payload_offset); //util_print_hex_octets(PDCP, &new_sdu_p->data[sizeof (pdcp_data_ind_header_t)], sdu_buffer_sizeP - payload_offset); @@ -1158,11 +1231,11 @@ pdcp_run ( RRC_DCCH_DATA_REQ (msg_p).frame, 0, RRC_DCCH_DATA_REQ (msg_p).eNB_index); - LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %ld, muiP %d, confirmP %d, mode %d\n", + LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %ld, rb_id %ld, muiP %d, confirmP %d, mode %d\n", PROTOCOL_CTXT_ARGS(&ctxt), ITTI_MSG_NAME (msg_p), ITTI_MSG_ORIGIN_NAME(msg_p), - ITTI_MSG_INSTANCE (msg_p), + ITTI_MSG_DESTINATION_INSTANCE (msg_p), RRC_DCCH_DATA_REQ (msg_p).rb_id, RRC_DCCH_DATA_REQ (msg_p).muip, RRC_DCCH_DATA_REQ (msg_p).confirmp, @@ -1284,7 +1357,7 @@ pdcp_mbms_run ( // PROTOCOL_CTXT_ARGS(&ctxt), // ITTI_MSG_NAME (msg_p), // ITTI_MSG_ORIGIN_NAME(msg_p), -// ITTI_MSG_INSTANCE (msg_p), +// ITTI_MSG_DESTINATION_INSTANCE (msg_p), // RRC_DCCH_DATA_REQ (msg_p).rb_id, // RRC_DCCH_DATA_REQ (msg_p).muip, // RRC_DCCH_DATA_REQ (msg_p).confirmp, @@ -2117,8 +2190,7 @@ pdcp_config_set_security( } //----------------------------------------------------------------------------- -void -rrc_pdcp_config_req ( +void rrc_pdcp_config_req ( const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const uint32_t actionP, @@ -2287,7 +2359,7 @@ uint64_t pdcp_module_init( uint64_t pdcp_optmask ) { nas_getparams(); if(UE_NAS_USE_TUN) { - int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )?MAX_NUMBER_NETIF:1; + int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )? MAX_MOBILES_PER_ENB : 1; netlink_init_tun("ue",num_if); if (IS_SOFTMODEM_NOS1) nas_config(1, 1, 2, "ue"); @@ -2316,6 +2388,8 @@ uint64_t pdcp_module_init( uint64_t pdcp_optmask ) { LOG_E(PDCP, "ENB pdcp will not use tun interface\n"); } + pthread_create(&pdcp_stats_thread_desc,NULL,pdcp_stats_thread,NULL); + return pdcp_params.optmask ; } @@ -2353,101 +2427,6 @@ void pdcp_module_cleanup (void) { } -void nr_ip_over_LTE_DRB_preconfiguration(void){ - - // Addition for the use-case of 4G stack on top of 5G-NR. - // We need to configure pdcp and rlc instances without having an actual - // UE RRC Connection. In order to be able to test the NR PHY with some injected traffic - // on top of the LTE stack. - protocol_ctxt_t ctxt; - LTE_DRB_ToAddModList_t* DRB_configList=NULL; - DRB_configList = CALLOC(1, sizeof(LTE_DRB_ToAddModList_t)); - struct LTE_LogicalChannelConfig *DRB_lchan_config = NULL; - struct LTE_RLC_Config *DRB_rlc_config = NULL; - struct LTE_PDCP_Config *DRB_pdcp_config = NULL; - struct LTE_PDCP_Config__rlc_UM *PDCP_rlc_UM = NULL; - - struct LTE_DRB_ToAddMod *DRB_config = NULL; - struct LTE_LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters = NULL; - long *logicalchannelgroup_drb; - - - //Static preconfiguration of DRB - DRB_config = CALLOC(1, sizeof(*DRB_config)); - - DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long)); - // allowed value 5..15, value : x+4 - *(DRB_config->eps_BearerIdentity) = 1; //ue_context_pP->ue_context.e_rab[i].param.e_rab_id;//+ 4; // especial case generation - // DRB_config->drb_Identity = 1 + drb_identity_index + e_rab_done;// + i ;// (DRB_Identity_t) ue_context_pP->ue_context.e_rab[i].param.e_rab_id; - // 1 + drb_identiy_index; - DRB_config->drb_Identity = 1; - DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); - *(DRB_config->logicalChannelIdentity) = DRB_config->drb_Identity + 3; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2 - - DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config)); - DRB_config->rlc_Config = DRB_rlc_config; - - DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config)); - DRB_config->pdcp_Config = DRB_pdcp_config; - DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long)); - *DRB_pdcp_config->discardTimer = LTE_PDCP_Config__discardTimer_infinity; - DRB_pdcp_config->rlc_AM = NULL; - DRB_pdcp_config->rlc_UM = NULL; - - DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional; - DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35; - // PDCP - PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM)); - DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; - PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; - - DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed; - - DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); - DRB_config->logicalChannelConfig = DRB_lchan_config; - DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); - DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; - - DRB_ul_SpecificParameters->priority= 4; - - DRB_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8; - //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - DRB_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - - logicalchannelgroup_drb = CALLOC(1, sizeof(long)); - *logicalchannelgroup_drb = 1;//(i+1) % 3; - DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb; - - ASN_SEQUENCE_ADD(&DRB_configList->list,DRB_config); - - if (ENB_NAS_USE_TUN){ - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_YES, 0x1234, 0, 0,0); - } - else{ - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0); - } - - rrc_pdcp_config_asn1_req(&ctxt, - (LTE_SRB_ToAddModList_t *) NULL, - DRB_configList, - (LTE_DRB_ToReleaseList_t *) NULL, - 0xff, NULL, NULL, NULL - , (LTE_PMCH_InfoList_r9_t *) NULL, - &DRB_config->drb_Identity); - - rrc_rlc_config_asn1_req(&ctxt, - (LTE_SRB_ToAddModList_t*)NULL, - DRB_configList, - (LTE_DRB_ToReleaseList_t*)NULL - //#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - ,(LTE_PMCH_InfoList_r9_t *)NULL - , 0, 0 - //#endif - ); -} //----------------------------------------------------------------------------- void pdcp_layer_init(void) //----------------------------------------------------------------------------- diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h index de8a1b385b..9d9224d660 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h @@ -53,9 +53,6 @@ typedef rlc_op_status_t (*send_rlc_data_req_func_t)(const protocol_ctxt_t *cons typedef boolean_t (*pdcp_data_ind_func_t)( const protocol_ctxt_t *, const srb_flag_t, const MBMS_flag_t, const rb_id_t, const sdu_size_t, mem_block_t *,const uint32_t *const, const uint32_t *const); -/* maximum number of tun interfaces that will be created to emulates UEs */ -/* UEs beyond that will be multiplexed on the same tun */ -#define MAX_NUMBER_NETIF 16 #define ENB_NAS_USE_TUN_W_MBMS_BIT (1<< 10) #define PDCP_USE_NETLINK_BIT (1<< 11) @@ -70,9 +67,7 @@ typedef struct { } pdcp_params_t; -#ifndef PDCP_USE_NETLINK - #define PDCP_USE_NETLINK ( get_pdcp_optmask() & PDCP_USE_NETLINK_BIT) -#endif +#define PDCP_USE_NETLINK ( get_pdcp_optmask() & PDCP_USE_NETLINK_BIT) #define LINK_ENB_PDCP_TO_IP_DRIVER ( get_pdcp_optmask() & LINK_ENB_PDCP_TO_IP_DRIVER_BIT) #define LINK_ENB_PDCP_TO_GTPV1U ( get_pdcp_optmask() & LINK_ENB_PDCP_TO_GTPV1U_BIT) #define UE_NAS_USE_TUN ( get_pdcp_optmask() & UE_NAS_USE_TUN_BIT) @@ -94,34 +89,34 @@ extern int pdcp_instance_cnt; int init_pdcp_thread(void); void cleanup_pdcp_thread(void); -uint32_t Pdcp_stats_tx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB]; -uint32_t Pdcp_stats_tx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_throughput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_tx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB]; +extern uint32_t Pdcp_stats_tx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_throughput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_tx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB]; -uint32_t Pdcp_stats_rx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_goodput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; -uint32_t Pdcp_stats_rx_outoforder[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB]; +extern uint32_t Pdcp_stats_rx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_goodput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; +extern uint32_t Pdcp_stats_rx_outoforder[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX]; void pdcp_update_perioidical_stats(const protocol_ctxt_t *const ctxt_pP); @@ -141,7 +136,7 @@ typedef struct pdcp_enb_s { } pdcp_enb_t; -pdcp_enb_t pdcp_enb[MAX_NUM_CCs]; +extern pdcp_enb_t pdcp_enb[MAX_NUM_CCs]; typedef struct pdcp_stats_s { time_stats_t pdcp_run; @@ -245,17 +240,18 @@ typedef struct pdcp_mbms_s { * \note None * @ingroup _pdcp */ + boolean_t pdcp_data_req( protocol_ctxt_t *ctxt_pP, const srb_flag_t srb_flagP, const rb_id_t rb_id, const mui_t muiP, - const confirm_t confirmP, \ + const confirm_t confirmP, const sdu_size_t sdu_buffer_size, unsigned char *const sdu_buffer, const pdcp_transmission_mode_t mode, - const uint32_t *const sourceL2Id, - const uint32_t *const destinationL2Id + const uint32_t * sourceL2Id, + const uint32_t * destinationL2Id ); /*! \fn boolean_t pdcp_data_ind(const protocol_ctxt_t* const, srb_flag_t, MBMS_flag_t, rb_id_t, sdu_size_t, mem_block_t*, boolean_t) @@ -458,10 +454,10 @@ struct pdcp_netlink_element_s { //TTN for D2D (PC5S) #define PDCP_SOCKET_PORT_NO 9999 //temporary value #define PC5_SIGNALLING_PAYLOAD_SIZE 100 //should be updated with a correct value -int pdcp_pc5_sockfd; -struct sockaddr_in prose_ctrl_addr; -struct sockaddr_in prose_pdcp_addr; -struct sockaddr_in pdcp_sin; +extern int pdcp_pc5_sockfd; +extern struct sockaddr_in prose_ctrl_addr; +extern struct sockaddr_in prose_pdcp_addr; +extern struct sockaddr_in pdcp_sin; void pdcp_pc5_socket_init(void); typedef struct { @@ -503,28 +499,17 @@ typedef struct { #define REORDERING_WINDOW_SN_7BIT 64 #define REORDERING_WINDOW_SN_12BIT 2048 -signed int pdcp_2_nas_irq; -pdcp_stats_t UE_pdcp_stats[MAX_MOBILES_PER_ENB]; -pdcp_stats_t eNB_pdcp_stats[NUMBER_OF_eNB_MAX]; +extern pdcp_stats_t UE_pdcp_stats[MAX_MOBILES_PER_ENB]; +extern pdcp_stats_t eNB_pdcp_stats[NUMBER_OF_eNB_MAX]; // for UE code conly -rnti_t pdcp_UE_UE_module_id_to_rnti[MAX_MOBILES_PER_ENB]; -rnti_t pdcp_eNB_UE_instance_to_rnti[MAX_MOBILES_PER_ENB]; // for noS1 mode -unsigned int pdcp_eNB_UE_instance_to_rnti_index; +extern rnti_t pdcp_UE_UE_module_id_to_rnti[MAX_MOBILES_PER_ENB]; +extern rnti_t pdcp_eNB_UE_instance_to_rnti[MAX_MOBILES_PER_ENB]; // for noS1 mode +extern unsigned int pdcp_eNB_UE_instance_to_rnti_index; -pdcp_mbms_t pdcp_mbms_array_ue[MAX_MOBILES_PER_ENB][LTE_maxServiceCount][LTE_maxSessionPerPMCH]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h -pdcp_mbms_t pdcp_mbms_array_eNB[NUMBER_OF_eNB_MAX][LTE_maxServiceCount][LTE_maxSessionPerPMCH]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h -sdu_size_t pdcp_output_sdu_bytes_to_write; -sdu_size_t pdcp_output_header_bytes_to_write; -notifiedFIFO_t pdcp_sdu_list; -int pdcp_sent_a_sdu; -pdcp_data_req_header_t pdcp_input_header; -unsigned char pdcp_input_sdu_buffer[MAX_IP_PACKET_SIZE]; -sdu_size_t pdcp_input_index_header; -sdu_size_t pdcp_input_sdu_size_read; -sdu_size_t pdcp_input_sdu_remaining_size_to_read; +extern notifiedFIFO_t pdcp_sdu_list; #define PDCP_COLL_KEY_VALUE(mODULE_iD, rNTI, iS_eNB, rB_iD, iS_sRB) \ ((hash_key_t)mODULE_iD | \ diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_control_primitive.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_control_primitive.c index 0ef6893d08..c2736ddd84 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_control_primitive.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_control_primitive.c @@ -32,7 +32,6 @@ #include "rtos_header.h" #include "platform.h" #include "protocol_vars_extern.h" -#include "print.h" //----------------------------------------------------------------------------- #include "rlc.h" #include "pdcp.h" diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index c9a62d573b..05e77a935d 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -43,6 +43,7 @@ extern int otg_enabled; #include #include #include +#include #define rtf_put write #define rtf_get read @@ -78,20 +79,11 @@ extern int nas_sock_fd[MAX_MOBILES_PER_ENB]; extern int nas_sock_mbms_fd; -extern int mbms_rab_id; - - extern struct msghdr nas_msg_tx; extern struct msghdr nas_msg_rx; -#ifdef UESIM_EXPANSION - extern uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX]; -#endif - - - # include "gtpv1u_eNB_task.h" # include "gtpv1u_eNB_defs.h" @@ -119,8 +111,6 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) { * PDCP packet to pick the right socket below */ int rb_id = pdcpHead->rb_id; - int sizeToWrite= sizeof (pdcp_data_ind_header_t) + - pdcpHead->data_size; void * pdcpData=(void*)(pdcpHead+1); if (rb_id == 10) { //hardcoded for PC5-Signaling if( LOG_DEBUGFLAG(DEBUG_PDCP) ) { @@ -134,33 +124,34 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) { } else if (UE_NAS_USE_TUN) { //ret = write(nas_sock_fd[pdcpHead->inst], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite ); if(rb_id == mbms_rab_id){ - ret = write(nas_sock_mbms_fd, pdcpData,sizeToWrite ); + ret = write(nas_sock_mbms_fd, pdcpData, pdcpHead->data_size ); LOG_I(PDCP,"[PDCP_FIFOS] ret %d TRIED TO PUSH MBMS DATA TO rb_id %d handle %d sizeToWrite %d\n", - ret,rb_id,nas_sock_fd[pdcpHead->inst],sizeToWrite); + ret,rb_id,nas_sock_fd[pdcpHead->inst],pdcpHead->data_size); } else { if( LOG_DEBUGFLAG(DEBUG_PDCP) ) - log_dump(PDCP, pdcpData, sizeToWrite, LOG_DUMP_CHAR,"PDCP output to be sent to TUN interface: \n"); - ret = write(nas_sock_fd[pdcpHead->inst], pdcpData,sizeToWrite ); + log_dump(PDCP, pdcpData, pdcpHead->data_size, LOG_DUMP_CHAR,"PDCP output to be sent to TUN interface: \n"); + ret = write(nas_sock_fd[pdcpHead->inst], pdcpData,pdcpHead->data_size ); LOG_T(PDCP,"[UE PDCP_FIFOS] ret %d TRIED TO PUSH DATA TO rb_id %d handle %d sizeToWrite %d\n", - ret,rb_id,nas_sock_fd[pdcpHead->inst],sizeToWrite); + ret,rb_id,nas_sock_fd[pdcpHead->inst],pdcpHead->data_size); } } else if (ENB_NAS_USE_TUN) { if( LOG_DEBUGFLAG(DEBUG_PDCP) ) - log_dump(PDCP, pdcpData, sizeToWrite, LOG_DUMP_CHAR,"PDCP output to be sent to TUN interface: \n"); - ret = write(nas_sock_fd[0], pdcpData, sizeToWrite); - LOG_T(PDCP,"[NB PDCP_FIFOS] ret %d TRIED TO PUSH DATA TO rb_id %d handle %d sizeToWrite %d\n",ret,rb_id,nas_sock_fd[0],sizeToWrite); + log_dump(PDCP, pdcpData, pdcpHead->data_size, LOG_DUMP_CHAR,"PDCP output to be sent to TUN interface: \n"); + ret = write(nas_sock_fd[0], pdcpData, pdcpHead->data_size); + LOG_T(PDCP,"[NB PDCP_FIFOS] ret %d TRIED TO PUSH DATA TO rb_id %d handle %d sizeToWrite %d\n",ret,rb_id,nas_sock_fd[0],pdcpHead->data_size); } else if (PDCP_USE_NETLINK) { + int sizeToWrite= sizeof (pdcp_data_ind_header_t) + pdcpHead->data_size; memcpy(NLMSG_DATA(nas_nlh_tx), (uint8_t *) pdcpHead, sizeToWrite); nas_nlh_tx->nlmsg_len = sizeToWrite; ret = sendmsg(nas_sock_fd[0],&nas_msg_tx,0); } // PDCP_USE_NETLINK - - AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s), nas_sock_fd[0]: %d\n", errno, strerror(errno), nas_sock_fd[0]); + AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s), nas_sock_fd[0]: %d\n", errno, strerror(errno), nas_sock_fd[0]); + if( LOG_DEBUGFLAG(DEBUG_PDCP) ) - log_dump(PDCP, pdcpData, min(sizeToWrite,30) , LOG_DUMP_CHAR, + log_dump(PDCP, pdcpData, min(pdcpHead->data_size,30) , LOG_DUMP_CHAR, "Printing first bytes of PDCP SDU before removing it from the list: \n"); delNotifiedFIFO_elt (sdu_p); pdcp_nb_sdu_sent ++; @@ -202,6 +193,7 @@ int pdcp_fifo_flush_mbms_sdus(const protocol_ctxt_t *const ctxt_pP) { //} // PDCP_USE_NETLINK //AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s)\n", errno, strerror(errno)); + //AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s)\n", errno, strerror(errno)); delNotifiedFIFO_elt (sdu_p); pdcp_nb_sdu_sent ++; @@ -231,7 +223,11 @@ int pdcp_fifo_read_input_sdus_fromtun (const protocol_ctxt_t *const ctxt_pP) { key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag); h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p); } else { // => ENB_NAS_USE_TUN - ctxt.rnti=pdcp_eNB_UE_instance_to_rnti[0]; + /* Get the IP from a packet */ + struct ip *ip_pack = (struct ip *) nl_rx_buf; + /* Use last octet of destination IP to get index of UE */ + int ue_indx = ((ip_pack->ip_dst.s_addr >> 24) - 2) % MAX_MOBILES_PER_ENB; + ctxt.rnti=pdcp_eNB_UE_instance_to_rnti[ue_indx]; ctxt.enb_flag=ENB_FLAG_YES; ctxt.module_id=0; key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO); @@ -242,9 +238,9 @@ int pdcp_fifo_read_input_sdus_fromtun (const protocol_ctxt_t *const ctxt_pP) { ctxt.module_id, ctxt.rnti, ctxt.enb_flag); if (h_rc == HASH_TABLE_OK) { - LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %ld \n", + LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %ld: Received socket with length %d on Rab %ld \n", ctxt.frame, ctxt.instance, len, rab_id); - LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %04x][RB %ld]\n", + LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %ld][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %04x][RB %ld]\n", ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id, ctxt.rnti, rab_id); @@ -263,7 +259,7 @@ int pdcp_fifo_read_input_sdus_fromtun (const protocol_ctxt_t *const ctxt_pP) { ); } else { LOG_D(PDCP, - "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %04x][RB %ld] TUN NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n", + "[FRAME %5u][UE][IP][INSTANCE %ld][RB %ld][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %04x][RB %ld] TUN NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n", ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id, ctxt.rnti, rab_id, key); } @@ -310,9 +306,9 @@ int pdcp_fifo_read_input_mbms_sdus_fromtun (const protocol_ctxt_t *const ctxt_p ctxt.module_id, ctxt.rnti, ctxt.enb_flag); if (h_rc == HASH_TABLE_OK) { - LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %ld \n", + LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %ld: Received socket with length %d on Rab %ld \n", ctxt.frame, ctxt.instance, len, rab_id); - LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %04x][RB %ld]\n", + LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %ld][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %04x][RB %ld]\n", ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id, ctxt.rnti, rab_id); MSC_LOG_RX_MESSAGE((ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE, @@ -349,7 +345,7 @@ int pdcp_fifo_read_input_mbms_sdus_fromtun (const protocol_ctxt_t *const ctxt_p MSC_AS_TIME_ARGS(ctxt_pP), ctxt.instance, rab_id, rab_id, len); LOG_D(PDCP, - "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %04x][RB %ld] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n", + "[FRAME %5u][UE][IP][INSTANCE %ld][RB %ld][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %04x][RB %ld] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n", ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id, ctxt.rnti, rab_id, key); //if (!UE_NAS_USE_TUN) { @@ -382,7 +378,6 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const ctx protocol_ctxt_t ctxt; hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_rc; - module_id_t ue_id = 0; pdcp_t *pdcp_p = NULL; static unsigned char pdcp_read_state_g =0; rb_id_t rab_id = 0; @@ -476,38 +471,11 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const ctx } else { // rb_id =0, thus interpreated as broadcast and transported as multiple unicast // is a broadcast packet, we have to send this packet on all default RABS of all connected UEs //#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES - for (ue_id = 0; ue_id < NB_UE_INST; ue_id++) { - if (oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt_cpy.module_id][ue_id] != NOT_A_RNTI) { - ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt_cpy.module_id][ue_id]; - LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n", - ctxt.frame, - pdcp_read_header_g.inst, - pdcp_read_header_g.rb_id, - pdcp_read_header_g.data_size, - ctxt.module_id, - ctxt.rnti, - DEFAULT_RAB_ID); - pdcp_data_req ( - &ctxt, - SRB_FLAG_NO, - DEFAULT_RAB_ID, - RLC_MUI_UNDEFINED, - RLC_SDU_CONFIRM_NO, - pdcp_read_header_g.data_size, - (unsigned char *)NLMSG_DATA(nas_nlh_rx), - PDCP_TRANSMISSION_MODE_DATA - ,NULL, NULL - ); - } - } + // never finished code, dropped } } else { // ctxt.enb_flag => UE if (NFAPI_MODE == NFAPI_UE_STUB_PNF) { -#ifdef UESIM_EXPANSION - ctxt.module_id = inst_pdcp_list[pdcp_read_header_g.inst]; -#else ctxt.module_id = pdcp_read_header_g.inst; -#endif } else { ctxt.module_id = 0; } @@ -635,7 +603,7 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const ctxt_pP) //int optval; int bytes_received; sidelink_pc5s_element *sl_pc5s_msg_send = NULL; - pc5s_header_t *pc5s_header = NULL; + pc5s_header_t *pc5s_header = NULL; rb_id_t rab_id = 0; //TTN for D2D (PC5S) // receive a message from ProSe App @@ -736,6 +704,12 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const ctxt_pP) pc5s_header->rb_id, rab_id, pc5s_header->data_size); + /* pointers to pc5s_header fields possibly not aligned because pc5s_header points to a packed structure + * Using these possibly unaligned pointers in a function call may trigger alignment errors at run time and + * gcc, from v9, now warns about it. fix these warnings by using local variables + */ + uint32_t sourceL2Id = pc5s_header->sourceL2Id; + uint32_t destinationL2Id = pc5s_header->destinationL2Id; pdcp_data_req( &ctxt, SRB_FLAG_NO, @@ -745,9 +719,11 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const ctxt_pP) pc5s_header->data_size, (unsigned char *)receive_buf, PDCP_TRANSMISSION_MODE_DATA, - &pc5s_header->sourceL2Id, - &pc5s_header->destinationL2Id + &sourceL2Id, + &destinationL2Id ); + pc5s_header->sourceL2Id = sourceL2Id; + pc5s_header->destinationL2Id=destinationL2Id; } else { /* else of h_rc == HASH_TABLE_OK */ MSC_LOG_RX_DISCARDED_MESSAGE( (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE, @@ -791,6 +767,12 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const ctxt_pP) pc5s_header->rb_id, DEFAULT_RAB_ID, pc5s_header->data_size); + /* pointers to pc5s_header fields possibly not aligned because pc5s_header points to a packed structure + * Using these possibly unaligned pointers in a function call may trigger alignment errors at run time and + * gcc, from v9, now warns about it. fix these warnings by using local variables + */ + uint32_t sourceL2Id = pc5s_header->sourceL2Id; + uint32_t destinationL2Id = pc5s_header->destinationL2Id; pdcp_data_req ( &ctxt, SRB_FLAG_NO, @@ -800,9 +782,11 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const ctxt_pP) pc5s_header->data_size, (unsigned char *)receive_buf, PDCP_TRANSMISSION_MODE_DATA, - &pc5s_header->sourceL2Id, - &pc5s_header->destinationL2Id + &sourceL2Id, + &destinationL2Id ); + pc5s_header->sourceL2Id = sourceL2Id; + pc5s_header->destinationL2Id=destinationL2Id; } } /* end of !ctxt.enb_flag */ diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent.h b/openair2/LAYER2/PROTO_AGENT/proto_agent.h index 6898c9e447..32bf5aa13c 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent.h @@ -30,6 +30,8 @@ #define PROTO_AGENT_H_ #include "ENB_APP/enb_config.h" // for enb properties #include "proto_agent_common.h" +#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h" +#include "RRC/NR/nr_rrc_defs.h" void *proto_agent_receive(void *args); diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c index 6e343343cd..f19d7526fe 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c @@ -33,10 +33,9 @@ #include "PHY/phy_extern.h" #include "proto_agent_common.h" #include "common/utils/LOG/log.h" +#include "common/ran_context.h" -#include "RRC/LTE/rrc_extern.h" -#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" -#include "rrc_eNB_UE_context.h" +extern RAN_CONTEXT_t RC; /* * message primitives @@ -319,13 +318,15 @@ error: } int proto_agent_get_ack_result(mod_id_t mod_id, const void *params, Protocol__FlexsplitMessage **msg) { +/* code useless in this status: return 0 anyways rlc_op_status_t result = 0; - //printf("PROTO_AGENT: handling the data_req_ack message\n"); + printf("PROTO_AGENT: handling the data_req_ack message\n"); Protocol__FlexsplitMessage *input = (Protocol__FlexsplitMessage *)params; Protocol__FspRlcDataReqAck *data_ack = input->data_req_ack; result = data_ack->result; - //printf("PROTO_AGENT: ACK RESULT IS %u\n", result); + printf("PROTO_AGENT: ACK RESULT IS %u\n", result); ack_result = result; +*/ return 0; } @@ -362,28 +363,23 @@ int proto_agent_pdcp_data_req_process(mod_id_t mod_id, const void *params, Proto pdcp_pdu_size = rlc_data->fsp_pdu->fsp_pdu_data.len; pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__); - if (!pdcp_pdu_p) goto error; + if (!pdcp_pdu_p) { + LOG_E(PROTO_AGENT, "%s: an error occured\n", __FUNCTION__); + return -1; + } memcpy(pdcp_pdu_p->data, rlc_data->fsp_pdu->fsp_pdu_data.data, pdcp_pdu_size); - result = rlc_data_req(&ctxt_pP - ,srb_flagP - ,flag_MBMS - ,rb_idP - ,muiP - ,confirmP - ,pdcp_pdu_size - ,pdcp_pdu_p - ,NULL - ,NULL - ); + if (RC.nrrrc) { + LOG_D(PROTO_AGENT, "proto_agent received pdcp_data_req \n"); + // for (int i = 0; i < pdcp_pdu_size; i++) + // printf(" %2.2x", (unsigned char)pdcp_pdu_p->data[i]); + // printf("\n"); + du_rlc_data_req(&ctxt_pP, srb_flagP, flag_MBMS, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p); + result = 1; + } else { + result = rlc_data_req(&ctxt_pP, srb_flagP, flag_MBMS, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p, NULL, NULL); + } return result; -error: - - if (pdcp_pdu_p) - free_mem_block(pdcp_pdu_p, __func__); - - LOG_E(PROTO_AGENT, "%s: an error occured\n", __FUNCTION__); - return -1; } int proto_agent_destroy_pdcp_data_ind(Protocol__FlexsplitMessage *msg) { @@ -500,6 +496,13 @@ error: return -1; } +boolean_t pdcp_data_ind( + const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_id, + const sdu_size_t sdu_buffer_size, + mem_block_t *const sdu_buffer); int proto_agent_pdcp_data_ind_process(mod_id_t mod_id, const void *params, Protocol__FlexsplitMessage **msg) { boolean_t result = 0; @@ -522,6 +525,8 @@ int proto_agent_pdcp_data_ind_process(mod_id_t mod_id, const void *params, Proto ctxt_pP.rnti = ctxt->fsp_rnti; ctxt_pP.frame = ctxt->fsp_frame; ctxt_pP.subframe = ctxt->fsp_subframe; + ctxt_pP.configured = 1; + ctxt_pP.brOption = 0; ctxt_pP.eNB_index = ctxt->fsp_enb_index; srb_flagP = rlc_data->fsp_srb_flag; flag_MBMS = rlc_data->fsp_mbms_flag; @@ -535,7 +540,7 @@ int proto_agent_pdcp_data_ind_process(mod_id_t mod_id, const void *params, Proto // if (xid == 1) // pdcp_data_ind_wifi((const protocol_ctxt_t*) ctxt_pP, (const srb_flag_t) srb_flagP, (const MBMS_flag_t) flag_MBMS, (const rb_id_t) rb_idP, pdcp_pdu_size, pdcp_pdu_p); // else if (xid == 0) // FIXME: USE a preprocessed definition - LOG_D(PROTO_AGENT, "[inst %d] Received PDCP PDU with size %d for UE RNTI %x RB %ld, Calling pdcp_data_ind\n", ctxt_pP.instance, pdcp_pdu_size,ctxt_pP.rnti,rb_idP); + LOG_D(PROTO_AGENT, "[inst %ld] Received PDCP PDU with size %d for UE RNTI %x RB %ld, Calling pdcp_data_ind\n", ctxt_pP.instance, pdcp_pdu_size,ctxt_pP.rnti,rb_idP); result = pdcp_data_ind(&ctxt_pP, srb_flagP, flag_MBMS, diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h index c805b81543..8f553e05e1 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h @@ -62,7 +62,6 @@ typedef int (*proto_agent_message_destruction_callback)( ); -uint32_t ack_result; /********************************** * progRAN protocol messages helper diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c index 9a63427ed5..925c11c8f8 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c @@ -30,7 +30,7 @@ #include "common/utils/LOG/log.h" proto_agent_channel_t *proto_channel[NUMBER_OF_eNB_MAX][ENB_AGENT_MAX]; -proto_agent_channel_instance_t channel_instance; +static proto_agent_channel_instance_t channel_instance; int proto_agent_channel_id = 0; int proto_agent_register_channel(mod_id_t mod_id, proto_agent_channel_t *channel, proto_agent_id_t agent_id) { diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h index c6ab681819..57e2116a72 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h @@ -37,7 +37,6 @@ //----------------------------------------------------------------------------- # include "rlc_tm_entity.h" # include "mem_block.h" -//# include "rrm_config_structs.h" # include "rlc_tm_structs.h" //# include "rlc.h" # include "platform_types.h" diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c index 940740943e..05c3423f76 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c @@ -27,7 +27,6 @@ #include "rlc_um.h" #include "rlc_primitives.h" #include "list.h" -#include "rrm_config_structs.h" #include "LAYER2/MAC/mac_extern.h" #include "common/utils/LOG/log.h" diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c index fda84879be..cf77f9ec37 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c @@ -80,6 +80,8 @@ static int g_send_id_read_index[2]; static struct mac_data_ind g_tx_delayed_indications[MAX_TIME_DELAYED_PDU_DUE_TO_HARQ]; static struct mac_data_ind g_rx_delayed_indications[MAX_TIME_DELAYED_PDU_DUE_TO_HARQ]; +static rlc_um_entity_t um_tx; +static rlc_um_entity_t um_rx; static int8_t *g_sdus[] = {"En dépit de son volontarisme affiché, le premier ministre est de plus en plus décrié pour son incompétence. La tension politique et dans l'opinion publique est encore montée d'un cran au Japon, sur fond d'inquiétantes nouvelles, avec du plutonium détecté dans le sol autour de la centrale de Fukushima. Le premier ministre Naoto Kan a solennellement déclaré que son gouvernement était «en état d'alerte maximum». Tout en reconnaissant que la situation restait «imprévisible». Ce volontarisme affiché par le premier ministre - que Nicolas Sarkozy rencontrera demain lors d'une visite au Japon - ne l'a pas empêché d'être la cible de violentes critiques de la part de parlementaires sur sa gestion de la crise. Attaqué sur le manque de transparence, il a assuré qu'il rendait publiques toutes les informations en sa possession. Un député de l'opposition, Yosuke Isozaki, a aussi reproché à Naoto Kan de ne pas avoir ordonné l'évacuation des populations dans la zone comprise entre 20 et 30 km autour de la centrale. «Peut-il y avoir quelque chose de plus irresponsable que cela ?», a-t-il lancé. Pour l'heure, la zone d'évacuation est limitée à un rayon de 20 km, seul le confinement étant recommandé pour les 10 km suivants. Sur ce sujet, les autorités japonaises ont été fragilisées mardi par les déclarations de Greenpeace, affirmant que ses experts avaient détecté une radioactivité dangereuse à 40 km de la centrale. L'organisation écologiste a appelé à une extension de la zone d'évacuation, exhortant Tokyo à «cesser de privilégier la politique aux dépens de la science». L'Agence japonaise de sûreté nucléaire a balayé ces critiques.", diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.h index 6da464aa28..bfde1b31f3 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.h +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.h @@ -21,8 +21,6 @@ # ifndef __RLC_UM_TEST_H__ # define __RLC_UM_TEST_H__ -rlc_um_entity_t um_tx; -rlc_um_entity_t um_rx; void rlc_um_v9_3_0_test_windows_5(void); void rlc_um_v9_3_0_test_windows_10(void); diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_very_simple_test.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_very_simple_test.h index 598518f1c8..b762a4fdb4 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_very_simple_test.h +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_very_simple_test.h @@ -33,7 +33,6 @@ //----------------------------------------------------------------------------- # include "rlc_um_entity.h" # include "mem_block.h" -# include "rrm_config_structs.h" # include "rlc_um_structs.h" # include "rlc_um_constants.h" //----------------------------------------------------------------------------- diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c index 98c8c3e252..b9dcf0414b 100644 --- a/openair2/LAYER2/RLC/rlc.c +++ b/openair2/LAYER2/RLC/rlc.c @@ -36,6 +36,7 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "targets/COMMON/openairinterface5g_limits.h" #include "assertions.h" +#include #include "common/ran_context.h" extern RAN_CONTEXT_t RC; @@ -51,7 +52,27 @@ extern boolean_t pdcp_data_ind( #define DEBUG_RLC_PDCP_INTERFACE 1 //#define TRACE_RLC_PAYLOAD 1 #define DEBUG_RLC_DATA_REQ 1 +void (*rlc_rrc_data_conf)( + const protocol_ctxt_t *const ctxtP, + const rb_id_t rb_idP, + const mui_t muiP, + const rlc_tx_status_t statusP) __attribute__ ((aligned(32))); +void (*rlc_rrc_data_ind)( + const protocol_ctxt_t *const ctxtP, + const rb_id_t rb_idP, + const sdu_size_t sdu_sizeP, + const uint8_t *const sduP) __attribute__ ((aligned(32))); + +logical_chan_id_t rlc_mbms_rbid2lcid_ue [MAX_MOBILES_PER_ENB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */ +logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */ +rlc_mbms_id_t rlc_mbms_lcid2service_session_id_ue[MAX_MOBILES_PER_ENB][RLC_MAX_MBMS_LC]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h +rlc_mbms_id_t rlc_mbms_lcid2service_session_id_eNB[MAX_eNB][RLC_MAX_MBMS_LC]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h +hash_table_t *rlc_coll_p __attribute__ ((aligned(32))); + + +logical_chan_id_t rlc_mbms_rbid2lcid_ue [MAX_MOBILES_PER_ENB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */ +logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */ //----------------------------------------------------------------------------- void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP) //----------------------------------------------------------------------------- diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h index 27ca18ed7e..1e5b7947d7 100644 --- a/openair2/LAYER2/RLC/rlc.h +++ b/openair2/LAYER2/RLC/rlc.h @@ -133,17 +133,17 @@ typedef struct { #define RLC_MAX_MBMS_LC (LTE_maxSessionPerPMCH * LTE_maxServiceCount) #define RLC_MAX_LC ((max_val_LTE_DRB_Identity+1)* MAX_MOBILES_PER_ENB) -void (*rlc_rrc_data_ind)( +extern void (*rlc_rrc_data_ind)( const protocol_ctxt_t *const ctxtP, const rb_id_t rb_idP, const sdu_size_t sdu_sizeP, const uint8_t *const sduP) __attribute__ ((aligned(32))); -void (*rlc_rrc_data_conf)( +extern void (*rlc_rrc_data_conf)( const protocol_ctxt_t *const ctxtP, const rb_id_t rb_idP, const mui_t muiP, - const rlc_tx_status_t statusP); + const rlc_tx_status_t statusP) __attribute__ ((aligned(32))); typedef void (rrc_data_ind_cb_t)( const protocol_ctxt_t *const ctxtP, @@ -184,8 +184,8 @@ typedef struct rlc_mbms_id_s { //rlc_mbms_t rlc_mbms_array_ue[MAX_MOBILES_PER_ENB][maxServiceCount][maxSessionPerPMCH]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h //rlc_mbms_t rlc_mbms_array_eNB[NUMBER_OF_eNB_MAX][maxServiceCount][maxSessionPerPMCH]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h -rlc_mbms_id_t rlc_mbms_lcid2service_session_id_ue[MAX_MOBILES_PER_ENB][RLC_MAX_MBMS_LC]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h -rlc_mbms_id_t rlc_mbms_lcid2service_session_id_eNB[MAX_eNB][RLC_MAX_MBMS_LC]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h +extern rlc_mbms_id_t rlc_mbms_lcid2service_session_id_ue[MAX_MOBILES_PER_ENB][RLC_MAX_MBMS_LC]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h +extern rlc_mbms_id_t rlc_mbms_lcid2service_session_id_eNB[MAX_eNB][RLC_MAX_MBMS_LC]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h #define rlc_mbms_enb_get_lcid_by_rb_id(Enb_mOD,rB_iD) rlc_mbms_rbid2lcid_eNB[Enb_mOD][rB_iD] ; @@ -201,8 +201,8 @@ rlc_mbms_id_t rlc_mbms_lcid2service_session_id_eNB[MAX_eNB][RLC_MAX_MBMS_ rlc_mbms_rbid2lcid_ue[uE_mOD][rB_iD] = lOG_cH_iD; \ } while (0); -logical_chan_id_t rlc_mbms_rbid2lcid_ue [MAX_MOBILES_PER_ENB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */ -logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */ +extern logical_chan_id_t rlc_mbms_rbid2lcid_ue [MAX_MOBILES_PER_ENB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */ +extern logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */ #define RLC_COLL_KEY_VALUE(eNB_iD, rNTI, iS_eNB, rB_iD, iS_sRB) \ @@ -250,7 +250,7 @@ logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; (((hash_key_t)(sESSION_ID)) << 37) | \ (((hash_key_t)(0x0000000000000001)) << 63)) -hash_table_t *rlc_coll_p __attribute__ ((aligned(32))); +extern hash_table_t *rlc_coll_p __attribute__ ((aligned(32))); /*! \fn tbs_size_t mac_rlc_serialize_tb (char* bufferP, list_t transport_blocksP) * \brief Serialize a list of transport blocks coming from RLC in order to be processed by MAC. @@ -624,6 +624,14 @@ rlc_op_status_t rlc_stat_req ( */ int rlc_module_init(int enb_flag); +void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP); /** @} */ #define RLC_FG_COLOR_BLACK "\e[0;30m" diff --git a/openair2/LAYER2/nr_pdcp/asn1_utils.c b/openair2/LAYER2/nr_pdcp/asn1_utils.c new file mode 100644 index 0000000000..264a2815bb --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/asn1_utils.c @@ -0,0 +1,68 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "pdcp.h" + +int decode_t_reordering(int v) +{ + static int tab[36] = { + 0, 1, 2, 4, 5, 8, 10, 15, 20, 30, 40, 50, 60, 80, 100, 120, 140, 160, 180, + 200, 220, 240, 260, 280, 300, 500, 750, 1000, 1250, 1500, 1750, 2000, + 2250, 2500, 2750, 3000 + }; + + if (v < 0 || v > 35) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_sn_size_ul(long s) +{ + if (s == 0) return 12; + if (s == 1) return 18; + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); +} + +int decode_sn_size_dl(long s) +{ + if (s == 0) return 12; + if (s == 1) return 18; + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); +} + +int decode_discard_timer(long v) +{ + static int tab[16] = { + 10, 20, 30, 40, 50, 60, 75, 100, 150, 200, 250, 300, 500, 750, 1500, -1, + }; + + if (v < 0 || v > 15) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} diff --git a/common/utils/itti_analyzer/libui/ui_menu_bar.h b/openair2/LAYER2/nr_pdcp/asn1_utils.h similarity index 79% rename from common/utils/itti_analyzer/libui/ui_menu_bar.h rename to openair2/LAYER2/nr_pdcp/asn1_utils.h index 037dc5edca..d525bce287 100644 --- a/common/utils/itti_analyzer/libui/ui_menu_bar.h +++ b/openair2/LAYER2/nr_pdcp/asn1_utils.h @@ -19,15 +19,12 @@ * contact@openairinterface.org */ -#ifndef UI_MENU_BAR_H_ -#define UI_MENU_BAR_H_ +#ifndef _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_ +#define _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_ -void ui_set_sensitive_move_buttons(gboolean enable); +int decode_t_reordering(int v); +int decode_sn_size_ul(long s); +int decode_sn_size_dl(long s); +int decode_discard_timer(long v); -void ui_set_sensitive_save_message_buttons(gboolean enable); - -int ui_menu_bar_create(GtkWidget *vbox); - -int ui_toolbar_create(GtkWidget *vbox); - -#endif /* UI_MENU_BAR_H_ */ +#endif /* _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_ */ diff --git a/common/utils/itti_analyzer/libbuffers/file.h b/openair2/LAYER2/nr_pdcp/nr_pdcp.h similarity index 86% rename from common/utils/itti_analyzer/libbuffers/file.h rename to openair2/LAYER2/nr_pdcp/nr_pdcp.h index be0fa6ba2d..94939a0421 100644 --- a/common/utils/itti_analyzer/libbuffers/file.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp.h @@ -19,9 +19,12 @@ * contact@openairinterface.org */ -#ifndef FILE_H_ -#define FILE_H_ +#include -int file_read_dump(buffer_t **buffer, const char *filename); +#ifndef _NR_PDCP_H_ +#define _NR_PDCP_H_ -#endif /* FILE_H_ */ +void nr_pdcp_layer_init_ue(void); +void nr_DRB_preconfiguration(uint16_t crnti); + +#endif /* _NR_PDCP_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c new file mode 100644 index 0000000000..87b71894c7 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -0,0 +1,398 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_entity.h" + +#include +#include +#include + +#include "nr_pdcp_security_nea2.h" +#include "nr_pdcp_integrity_nia2.h" +#include "nr_pdcp_sdu.h" + +#include "LOG/log.h" + +static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, + char *_buffer, int size) +{ + unsigned char *buffer = (unsigned char *)_buffer; + nr_pdcp_sdu_t *sdu; + int rcvd_sn; + uint32_t rcvd_hfn; + uint32_t rcvd_count; + int header_size; + int integrity_size; + int rx_deliv_sn; + uint32_t rx_deliv_hfn; + + if (size < 1) { + LOG_E(PDCP, "bad PDU received (size = %d)\n", size); + return; + } + + if (entity->type != NR_PDCP_SRB && !(buffer[0] & 0x80)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (entity->sn_size == 12) { + rcvd_sn = ((buffer[0] & 0xf) << 8) | + buffer[1]; + header_size = 2; + } else { + rcvd_sn = ((buffer[0] & 0x3) << 16) | + (buffer[1] << 8) | + buffer[2]; + header_size = 3; + } + + /* SRBs always have MAC-I, even if integrity is not active */ + if (entity->has_integrity || entity->type == NR_PDCP_SRB) { + integrity_size = 4; + } else { + integrity_size = 0; + } + + if (size < header_size + integrity_size + 1) { + LOG_E(PDCP, "bad PDU received (size = %d)\n", size); + return; + } + + rx_deliv_sn = entity->rx_deliv & entity->sn_max; + rx_deliv_hfn = entity->rx_deliv >> entity->sn_size; + + if (rcvd_sn < rx_deliv_sn - entity->window_size) { + rcvd_hfn = rx_deliv_hfn + 1; + } else if (rcvd_sn >= rx_deliv_sn + entity->window_size) { + rcvd_hfn = rx_deliv_hfn - 1; + } else { + rcvd_hfn = rx_deliv_hfn; + } + + rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn; + + if (entity->has_ciphering) + entity->cipher(entity->security_context, + buffer+header_size, size-header_size, + entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); + + if (entity->has_integrity) { + unsigned char integrity[4]; + entity->integrity(entity->integrity_context, integrity, + buffer, size - integrity_size, + entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); + if (memcmp(integrity, buffer + size - integrity_size, 4) != 0) { + LOG_E(PDCP, "discard NR PDU, integrity failed\n"); +// return; + } + } + + if (rcvd_count < entity->rx_deliv + || nr_pdcp_sdu_in_list(entity->rx_list, rcvd_count)) { + LOG_D(PDCP, "discard NR PDU rcvd_count=%d\n", rcvd_count); + return; + } + + sdu = nr_pdcp_new_sdu(rcvd_count, + (char *)buffer + header_size, + size - header_size - integrity_size); + entity->rx_list = nr_pdcp_sdu_list_add(entity->rx_list, sdu); + entity->rx_size += size-header_size; + + if (rcvd_count >= entity->rx_next) { + entity->rx_next = rcvd_count + 1; + } + + /* TODO(?): out of order delivery */ + + if (rcvd_count == entity->rx_deliv) { + /* deliver all SDUs starting from rx_deliv up to discontinuity or end of list */ + uint32_t count = entity->rx_deliv; + while (entity->rx_list != NULL && count == entity->rx_list->count) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + count++; + } + entity->rx_deliv = count; + } + + if (entity->t_reordering_start != 0 && entity->rx_deliv >= entity->rx_reord) { + /* stop and reset t-Reordering */ + entity->t_reordering_start = 0; + } + + if (entity->t_reordering_start == 0 && entity->rx_deliv < entity->rx_next) { + entity->rx_reord = entity->rx_next; + entity->t_reordering_start = entity->t_current; + } +} + +static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity, + char *buffer, int size, int sdu_id) +{ + uint32_t count; + int sn; + int header_size; + int integrity_size; + char buf[size + 3 + 4]; + int dc_bit; + + count = entity->tx_next; + sn = entity->tx_next & entity->sn_max; + + /* D/C bit is only to be set for DRBs */ + if (entity->type == NR_PDCP_DRB_AM || entity->type == NR_PDCP_DRB_UM) { + dc_bit = 0x80; + } else { + dc_bit = 0; + } + + if (entity->sn_size == 12) { + buf[0] = dc_bit | ((sn >> 8) & 0xf); + buf[1] = sn & 0xff; + header_size = 2; + } else { + buf[0] = dc_bit | ((sn >> 16) & 0x3); + buf[1] = (sn >> 8) & 0xff; + buf[2] = sn & 0xff; + header_size = 3; + } + + /* SRBs always have MAC-I, even if integrity is not active */ + if (entity->has_integrity || entity->type == NR_PDCP_SRB) { + integrity_size = 4; + } else { + integrity_size = 0; + } + + memcpy(buf + header_size, buffer, size); + + if (entity->has_integrity) + entity->integrity(entity->integrity_context, + (unsigned char *)buf + header_size + size, + (unsigned char *)buf, header_size + size, + entity->rb_id, count, entity->is_gnb ? 1 : 0); + + // set MAC-I to 0 for SRBs with integrity not active + else if (integrity_size == 4) + memset(buf + header_size + size, 0, 4); + + if (entity->has_ciphering) + entity->cipher(entity->security_context, + (unsigned char *)buf + header_size, size + integrity_size, + entity->rb_id, count, entity->is_gnb ? 1 : 0); + + entity->tx_next++; + + entity->deliver_pdu(entity->deliver_pdu_data, entity, buf, + header_size + size + integrity_size, sdu_id); +} + +/* may be called several times, take care to clean previous settings */ +static void nr_pdcp_entity_set_security(nr_pdcp_entity_t *entity, + int integrity_algorithm, + char *integrity_key, + int ciphering_algorithm, + char *ciphering_key) +{ + if (integrity_algorithm != -1) + entity->integrity_algorithm = integrity_algorithm; + if (ciphering_algorithm != -1) + entity->ciphering_algorithm = ciphering_algorithm; + if (integrity_key != NULL) + memcpy(entity->integrity_key, integrity_key, 16); + if (ciphering_key != NULL) + memcpy(entity->ciphering_key, ciphering_key, 16); + + if (integrity_algorithm == 0) { + entity->has_integrity = 0; + if (entity->free_integrity != NULL) + entity->free_integrity(entity->integrity_context); + entity->free_integrity = NULL; + } + + if (integrity_algorithm != 0 && integrity_algorithm != -1) { + if (integrity_algorithm != 2) { + LOG_E(PDCP, "FATAL: only nia2 supported for the moment\n"); + exit(1); + } + entity->has_integrity = 1; + if (entity->free_integrity != NULL) + entity->free_integrity(entity->integrity_context); + entity->integrity_context = nr_pdcp_integrity_nia2_init(entity->integrity_key); + entity->integrity = nr_pdcp_integrity_nia2_integrity; + entity->free_integrity = nr_pdcp_integrity_nia2_free_integrity; + } + + if (ciphering_algorithm == 0) { + entity->has_ciphering = 0; + if (entity->free_security != NULL) + entity->free_security(entity->security_context); + entity->free_security = NULL; + } + + if (ciphering_algorithm != 0 && ciphering_algorithm != -1) { + if (ciphering_algorithm != 2) { + LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n"); + exit(1); + } + entity->has_ciphering = 1; + if (entity->free_security != NULL) + entity->free_security(entity->security_context); + entity->security_context = nr_pdcp_security_nea2_init(entity->ciphering_key); + entity->cipher = nr_pdcp_security_nea2_cipher; + entity->free_security = nr_pdcp_security_nea2_free_security; + } +} + +static void check_t_reordering(nr_pdcp_entity_t *entity) +{ + uint32_t count; + + /* if t_reordering is set to "infinity" (seen as -1) then do nothing */ + if (entity->t_reordering == -1) + return; + + if (entity->t_reordering_start == 0 + || entity->t_current <= entity->t_reordering_start + entity->t_reordering) + return; + + /* stop timer */ + entity->t_reordering_start = 0; + + /* deliver all SDUs with count < rx_reord */ + while (entity->rx_list != NULL && entity->rx_list->count < entity->rx_reord) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + } + + /* deliver all SDUs starting from rx_reord up to discontinuity or end of list */ + count = entity->rx_reord; + while (entity->rx_list != NULL && count == entity->rx_list->count) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + count++; + } + + entity->rx_deliv = count; + + if (entity->rx_deliv < entity->rx_next) { + entity->rx_reord = entity->rx_next; + entity->t_reordering_start = entity->t_current; + } +} + +void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now) +{ + entity->t_current = now; + + check_t_reordering(entity); +} + +void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity) +{ + nr_pdcp_sdu_t *cur = entity->rx_list; + while (cur != NULL) { + nr_pdcp_sdu_t *next = cur->next; + nr_pdcp_free_sdu(cur); + cur = next; + } + if (entity->free_security != NULL) + entity->free_security(entity->security_context); + if (entity->free_integrity != NULL) + entity->free_integrity(entity->integrity_context); + free(entity); +} + +nr_pdcp_entity_t *new_nr_pdcp_entity( + nr_pdcp_entity_type_t type, + int is_gnb, int rb_id, int pdusession_id,int has_sdap, + int has_sdapULheader, int has_sdapDLheader, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data, + int sn_size, + int t_reordering, + int discard_timer, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) +{ + nr_pdcp_entity_t *ret; + + ret = calloc(1, sizeof(nr_pdcp_entity_t)); + if (ret == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ret->type = type; + + ret->recv_pdu = nr_pdcp_entity_recv_pdu; + ret->recv_sdu = nr_pdcp_entity_recv_sdu; + ret->set_security = nr_pdcp_entity_set_security; + ret->set_time = nr_pdcp_entity_set_time; + + ret->delete = nr_pdcp_entity_delete; + + ret->deliver_sdu = deliver_sdu; + ret->deliver_sdu_data = deliver_sdu_data; + + ret->deliver_pdu = deliver_pdu; + ret->deliver_pdu_data = deliver_pdu_data; + + ret->rb_id = rb_id; + ret->pdusession_id = pdusession_id; + ret->has_sdap = has_sdap; + ret->has_sdapULheader = has_sdapULheader; + ret->has_sdapDLheader = has_sdapDLheader; + ret->sn_size = sn_size; + ret->t_reordering = t_reordering; + ret->discard_timer = discard_timer; + + ret->sn_max = (1 << sn_size) - 1; + ret->window_size = 1 << (sn_size - 1); + + ret->is_gnb = is_gnb; + + nr_pdcp_entity_set_security(ret, + integrity_algorithm, (char *)integrity_key, + ciphering_algorithm, (char *)ciphering_key); + + return ret; +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h new file mode 100644 index 0000000000..fbcc2b96cd --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -0,0 +1,139 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_PDCP_ENTITY_H_ +#define _NR_PDCP_ENTITY_H_ + +#include + +#include "nr_pdcp_sdu.h" + +typedef enum { + NR_PDCP_DRB_AM, + NR_PDCP_DRB_UM, + NR_PDCP_SRB +} nr_pdcp_entity_type_t; + +typedef struct nr_pdcp_entity_t { + nr_pdcp_entity_type_t type; + + /* functions provided by the PDCP module */ + void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size); + void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size, + int sdu_id); + void (*delete)(struct nr_pdcp_entity_t *entity); + + /* set_security: pass -1 to integrity_algorithm / ciphering_algorithm + * to keep the current algorithm + * pass NULL to integrity_key / ciphering_key + * to keep the current key + */ + void (*set_security)(struct nr_pdcp_entity_t *entity, + int integrity_algorithm, + char *integrity_key, + int ciphering_algorithm, + char *ciphering_key); + + void (*set_time)(struct nr_pdcp_entity_t *entity, uint64_t now); + + /* callbacks provided to the PDCP module */ + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size); + void *deliver_sdu_data; + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id); + void *deliver_pdu_data; + + /* configuration variables */ + int rb_id; + int pdusession_id; + int has_sdap; + int has_sdapULheader; + int has_sdapDLheader; + int sn_size; /* SN size, in bits */ + int t_reordering; /* unit: ms, -1 for infinity */ + int discard_timer; /* unit: ms, -1 for infinity */ + + int sn_max; /* (2^SN_size) - 1 */ + int window_size; /* 2^(SN_size - 1) */ + + /* state variables */ + uint32_t tx_next; + uint32_t rx_next; + uint32_t rx_deliv; + uint32_t rx_reord; + + /* set to the latest know time by the user of the module. Unit: ms */ + uint64_t t_current; + + /* timers (stores the ms of activation, 0 means not active) */ + int t_reordering_start; + + /* security */ + int has_ciphering; + int has_integrity; + int ciphering_algorithm; + int integrity_algorithm; + unsigned char ciphering_key[16]; + unsigned char integrity_key[16]; + void *security_context; + void (*cipher)(void *security_context, + unsigned char *buffer, int length, + int bearer, int count, int direction); + void (*free_security)(void *security_context); + void *integrity_context; + void (*integrity)(void *integrity_context, unsigned char *out, + unsigned char *buffer, int length, + int bearer, int count, int direction); + void (*free_integrity)(void *integrity_context); + /* security/integrity algorithms need to know uplink/downlink information + * which is reverse for gnb and ue, so we need to know if this + * pdcp entity is for a gnb or an ue + */ + int is_gnb; + + /* rx management */ + nr_pdcp_sdu_t *rx_list; + int rx_size; + int rx_maxsize; +} nr_pdcp_entity_t; + +nr_pdcp_entity_t *new_nr_pdcp_entity( + nr_pdcp_entity_type_t type, + int is_gnb, int rb_id, int pdusession_id,int has_sdap, + int has_sdapULheader,int has_sdapDLheader, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data, + int sn_size, + int t_reordering, + int discard_timer, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key); + +void nr_DRB_preconfiguration(uint16_t crnti); + +#endif /* _NR_PDCP_ENTITY_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c new file mode 100644 index 0000000000..86f0558611 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c @@ -0,0 +1,82 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_integrity_nia2.h" + +#include +#include +#include +#include + +void *nr_pdcp_integrity_nia2_init(unsigned char *integrity_key) +{ + CMAC_CTX *ctx; + + ctx = CMAC_CTX_new(); + if (ctx == NULL) abort(); + + CMAC_Init(ctx, integrity_key, 16, EVP_aes_128_cbc(), NULL); + + return ctx; +} + +static void compute_t(unsigned char *t, uint32_t count, int bearer, + int direction) +{ + t[0] = (count >> 24) & 255; + t[1] = (count >> 16) & 255; + t[2] = (count >> 8) & 255; + t[3] = (count ) & 255; + t[4] = ((bearer-1) << 3) | (direction << 2); + memset(&t[5], 0, 8-5); +} + +void nr_pdcp_integrity_nia2_integrity(void *integrity_context, + unsigned char *out, + unsigned char *buffer, int length, + int bearer, int count, int direction) +{ + CMAC_CTX *ctx = integrity_context; + unsigned char t[8]; + unsigned char mac[16]; + size_t maclen; + + /* see 33.401 B.2.3 for the input to 128-EIA2 + * (which is identical to 128-NIA2, see 33.501 D.3.1.3) */ + compute_t(t, count, bearer, direction); + + CMAC_Init(ctx, NULL, 0, NULL, NULL); + CMAC_Update(ctx, t, 8); + CMAC_Update(ctx, buffer, length); + CMAC_Final(ctx, mac, &maclen); + + /* AES CMAC (RFC 4493) outputs 128 bits but NR PDCP PDUs have a MAC-I of + * 32 bits (see 38.323 6.2). RFC 4493 2.1 says to truncate most significant + * bit first (so seems to say 33.401 B.2.3) + */ + memcpy(out, mac, 4); +} + +void nr_pdcp_integrity_nia2_free_integrity(void *integrity_context) +{ + CMAC_CTX *ctx = integrity_context; + CMAC_CTX_free(ctx); +} diff --git a/common/utils/itti_analyzer/libparser/struct_type.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h similarity index 68% rename from common/utils/itti_analyzer/libparser/struct_type.h rename to openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h index 29d4113b6f..9593a2825c 100644 --- a/common/utils/itti_analyzer/libparser/struct_type.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h @@ -19,17 +19,16 @@ * contact@openairinterface.org */ -#include "types.h" +#ifndef _NR_PDCP_INTEGRITY_NIA2_H_ +#define _NR_PDCP_INTEGRITY_NIA2_H_ -#ifndef STRUCT_TYPE_H_ -#define STRUCT_TYPE_H_ +void *nr_pdcp_integrity_nia2_init(unsigned char *integrity_key); -int struct_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); +void nr_pdcp_integrity_nia2_integrity(void *integrity_context, + unsigned char *out, + unsigned char *buffer, int length, + int bearer, int count, int direction); -int struct_type_hr_display(types_t *type, int indent); +void nr_pdcp_integrity_nia2_free_integrity(void *integrity_context); -int struct_type_file_print(types_t *type, int indent, FILE *file); - -#endif /* STRUCT_TYPE_H_ */ +#endif /* _NR_PDCP_INTEGRITY_NIA2_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c new file mode 100644 index 0000000000..298588f112 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -0,0 +1,1405 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include "asn1_utils.h" +#include "nr_pdcp_ue_manager.h" +#include "nr_pdcp_timer_thread.h" +#include "NR_RadioBearerConfig.h" +#include "NR_RLC-BearerConfig.h" +#include "NR_RLC-Config.h" +#include "NR_CellGroupConfig.h" +#include "openair2/RRC/NR/nr_rrc_proto.h" +#include + +/* from OAI */ +#include "pdcp.h" +#include "LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include +#include "openair2/SDAP/nr_sdap/nr_sdap_gnb.h" + +#define TODO do { \ + printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \ + exit(1); \ + } while (0) + +static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager; + +/* TODO: handle time a bit more properly */ +static uint64_t nr_pdcp_current_time; +static int nr_pdcp_current_time_last_frame; +static int nr_pdcp_current_time_last_subframe; + +/* necessary globals for OAI, not used internally */ +hash_table_t *pdcp_coll_p; +static uint64_t pdcp_optmask; + +ngran_node_t node_type = ngran_gNB; +uint8_t proto_agent_flag = 0; + +/****************************************************************************/ +/* rlc_data_req queue - begin */ +/****************************************************************************/ + + +#include + +/* NR PDCP and RLC both use "big locks". In some cases a thread may do + * lock(rlc) followed by lock(pdcp) (typically when running 'rx_sdu'). + * Another thread may first do lock(pdcp) and then lock(rlc) (typically + * the GTP module calls 'pdcp_data_req' that, in a previous implementation + * was indirectly calling 'rlc_data_req' which does lock(rlc)). + * To avoid the resulting deadlock it is enough to ensure that a call + * to lock(pdcp) will never be followed by a call to lock(rlc). So, + * here we chose to have a separate thread that deals with rlc_data_req, + * out of the PDCP lock. Other solutions may be possible. + * So instead of calling 'rlc_data_req' directly we have a queue and a + * separate thread emptying it. + */ + +typedef struct { + protocol_ctxt_t ctxt_pP; + srb_flag_t srb_flagP; + MBMS_flag_t MBMS_flagP; + rb_id_t rb_idP; + mui_t muiP; + confirm_t confirmP; + sdu_size_t sdu_sizeP; + mem_block_t *sdu_pP; +} rlc_data_req_queue_item; + +#define RLC_DATA_REQ_QUEUE_SIZE 10000 + +typedef struct { + rlc_data_req_queue_item q[RLC_DATA_REQ_QUEUE_SIZE]; + volatile int start; + volatile int length; + pthread_mutex_t m; + pthread_cond_t c; +} rlc_data_req_queue; + +static rlc_data_req_queue q; + +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +static void *rlc_data_req_thread(void *_) +{ + int i; + + pthread_setname_np(pthread_self(), "RLC queue"); + while (1) { + if (pthread_mutex_lock(&q.m) != 0) abort(); + while (q.length == 0) + if (pthread_cond_wait(&q.c, &q.m) != 0) abort(); + i = q.start; + if (pthread_mutex_unlock(&q.m) != 0) abort(); + + rlc_data_req(&q.q[i].ctxt_pP, + q.q[i].srb_flagP, + q.q[i].MBMS_flagP, + q.q[i].rb_idP, + q.q[i].muiP, + q.q[i].confirmP, + q.q[i].sdu_sizeP, + q.q[i].sdu_pP, + NULL, + NULL); + + if (pthread_mutex_lock(&q.m) != 0) abort(); + + q.length--; + q.start = (q.start + 1) % RLC_DATA_REQ_QUEUE_SIZE; + + if (pthread_cond_signal(&q.c) != 0) abort(); + if (pthread_mutex_unlock(&q.m) != 0) abort(); + } +} + +static void init_nr_rlc_data_req_queue(void) +{ + pthread_t t; + + pthread_mutex_init(&q.m, NULL); + pthread_cond_init(&q.c, NULL); + + if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP, + void *_unused1, void *_unused2) +{ + int i; + int logged = 0; + + if (pthread_mutex_lock(&q.m) != 0) abort(); + while (q.length == RLC_DATA_REQ_QUEUE_SIZE) { + if (!logged) { + logged = 1; + LOG_W(PDCP, "%s: rlc_data_req queue is full\n", __FUNCTION__); + } + if (pthread_cond_wait(&q.c, &q.m) != 0) abort(); + } + + i = (q.start + q.length) % RLC_DATA_REQ_QUEUE_SIZE; + q.length++; + + q.q[i].ctxt_pP = *ctxt_pP; + q.q[i].srb_flagP = srb_flagP; + q.q[i].MBMS_flagP = MBMS_flagP; + q.q[i].rb_idP = rb_idP; + q.q[i].muiP = muiP; + q.q[i].confirmP = confirmP; + q.q[i].sdu_sizeP = sdu_sizeP; + q.q[i].sdu_pP = sdu_pP; + + if (pthread_cond_signal(&q.c) != 0) abort(); + if (pthread_mutex_unlock(&q.m) != 0) abort(); +} + +void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP) +{ + enqueue_rlc_data_req(ctxt_pP, + srb_flagP, + MBMS_flagP, + rb_idP, muiP, + confirmP, + sdu_sizeP, + sdu_pP, + NULL, + NULL); +} + +/****************************************************************************/ +/* rlc_data_req queue - end */ +/****************************************************************************/ + +/****************************************************************************/ +/* pdcp_data_ind thread - begin */ +/****************************************************************************/ + +typedef struct { + protocol_ctxt_t ctxt_pP; + srb_flag_t srb_flagP; + MBMS_flag_t MBMS_flagP; + rb_id_t rb_id; + sdu_size_t sdu_buffer_size; + mem_block_t *sdu_buffer; +} pdcp_data_ind_queue_item; + +#define PDCP_DATA_IND_QUEUE_SIZE 10000 + +typedef struct { + pdcp_data_ind_queue_item q[PDCP_DATA_IND_QUEUE_SIZE]; + volatile int start; + volatile int length; + pthread_mutex_t m; + pthread_cond_t c; +} pdcp_data_ind_queue; + +static pdcp_data_ind_queue pq; + +static void do_pdcp_data_ind( + const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_id, + const sdu_size_t sdu_buffer_size, + mem_block_t *const sdu_buffer) +{ + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + int rnti = ctxt_pP->rnti; + + if (ctxt_pP->module_id != 0 || + //ctxt_pP->enb_flag != 1 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 || + ctxt_pP->configured != 1 || + ctxt_pP->brOption != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (ctxt_pP->enb_flag) + T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(rnti), + T_INT(rb_id), T_INT(sdu_buffer_size)); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + + if (srb_flagP == 1) { + if (rb_id < 1 || rb_id > 2) + rb = NULL; + else + rb = ue->srb[rb_id - 1]; + } else { + if (rb_id < 1 || rb_id > 5) + rb = NULL; + else + rb = ue->drb[rb_id - 1]; + } + + if (rb != NULL) { + rb->recv_pdu(rb, (char *)sdu_buffer->data, sdu_buffer_size); + } else { + LOG_E(PDCP, "%s:%d:%s: fatal: no RB found (rb_id %ld, srb_flag %d)\n", + __FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP); + exit(1); + } + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + free_mem_block(sdu_buffer, __FUNCTION__); +} + +static void *pdcp_data_ind_thread(void *_) +{ + int i; + + pthread_setname_np(pthread_self(), "PDCP data ind"); + while (1) { + if (pthread_mutex_lock(&pq.m) != 0) abort(); + while (pq.length == 0) + if (pthread_cond_wait(&pq.c, &pq.m) != 0) abort(); + i = pq.start; + if (pthread_mutex_unlock(&pq.m) != 0) abort(); + + do_pdcp_data_ind(&pq.q[i].ctxt_pP, + pq.q[i].srb_flagP, + pq.q[i].MBMS_flagP, + pq.q[i].rb_id, + pq.q[i].sdu_buffer_size, + pq.q[i].sdu_buffer); + + if (pthread_mutex_lock(&pq.m) != 0) abort(); + + pq.length--; + pq.start = (pq.start + 1) % PDCP_DATA_IND_QUEUE_SIZE; + + if (pthread_cond_signal(&pq.c) != 0) abort(); + if (pthread_mutex_unlock(&pq.m) != 0) abort(); + } +} + +static void init_nr_pdcp_data_ind_queue(void) +{ + pthread_t t; + + pthread_mutex_init(&pq.m, NULL); + pthread_cond_init(&pq.c, NULL); + + if (pthread_create(&t, NULL, pdcp_data_ind_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +static void enqueue_pdcp_data_ind( + const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_id, + const sdu_size_t sdu_buffer_size, + mem_block_t *const sdu_buffer) +{ + int i; + int logged = 0; + + if (pthread_mutex_lock(&pq.m) != 0) abort(); + while (pq.length == PDCP_DATA_IND_QUEUE_SIZE) { + if (!logged) { + logged = 1; + LOG_W(PDCP, "%s: pdcp_data_ind queue is full\n", __FUNCTION__); + } + if (pthread_cond_wait(&pq.c, &pq.m) != 0) abort(); + } + + i = (pq.start + pq.length) % PDCP_DATA_IND_QUEUE_SIZE; + pq.length++; + + pq.q[i].ctxt_pP = *ctxt_pP; + pq.q[i].srb_flagP = srb_flagP; + pq.q[i].MBMS_flagP = MBMS_flagP; + pq.q[i].rb_id = rb_id; + pq.q[i].sdu_buffer_size = sdu_buffer_size; + pq.q[i].sdu_buffer = sdu_buffer; + + if (pthread_cond_signal(&pq.c) != 0) abort(); + if (pthread_mutex_unlock(&pq.m) != 0) abort(); +} + +boolean_t pdcp_data_ind( + const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_id, + const sdu_size_t sdu_buffer_size, + mem_block_t *const sdu_buffer) +{ + enqueue_pdcp_data_ind(ctxt_pP, + srb_flagP, + MBMS_flagP, + rb_id, + sdu_buffer_size, + sdu_buffer); + return true; +} + +/****************************************************************************/ +/* pdcp_data_ind thread - end */ +/****************************************************************************/ + +/****************************************************************************/ +/* hacks to be cleaned up at some point - begin */ +/****************************************************************************/ + +#include "LAYER2/MAC/mac_extern.h" + +static void reblock_tun_socket(void) +{ + extern int nas_sock_fd[]; + int f; + + f = fcntl(nas_sock_fd[0], F_GETFL, 0); + f &= ~(O_NONBLOCK); + if (fcntl(nas_sock_fd[0], F_SETFL, f) == -1) { + LOG_E(PDCP, "reblock_tun_socket failed\n"); + exit(1); + } +} + +static void *enb_tun_read_thread(void *_) +{ + extern int nas_sock_fd[]; + char rx_buf[NL_MAX_PAYLOAD]; + int len; + int rnti; + protocol_ctxt_t ctxt; + + int rb_id = 1; + pthread_setname_np( pthread_self(),"enb_tun_read"); + + while (1) { + len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD); + if (len == -1) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + LOG_D(PDCP, "%s(): nas_sock_fd read returns len %d\n", __func__, len); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + if (rnti == -1) continue; + + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = rnti; + + pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, + RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf, + PDCP_TRANSMISSION_MODE_DATA, NULL, NULL); + } + + return NULL; +} + +static void *ue_tun_read_thread(void *_) +{ + extern int nas_sock_fd[]; + char rx_buf[NL_MAX_PAYLOAD]; + int len; + int rnti; + protocol_ctxt_t ctxt; + + int rb_id = 1; + pthread_setname_np( pthread_self(),"ue_tun_read"); + while (1) { + len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD); + if (len == -1) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + LOG_D(PDCP, "%s(): nas_sock_fd read returns len %d\n", __func__, len); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + if (rnti == -1) continue; + + ctxt.module_id = 0; + ctxt.enb_flag = 0; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = rnti; + + pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, + RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf, + PDCP_TRANSMISSION_MODE_DATA, NULL, NULL); + } + + return NULL; +} + +static void start_pdcp_tun_enb(void) +{ + pthread_t t; + + reblock_tun_socket(); + + if (pthread_create(&t, NULL, enb_tun_read_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +static void start_pdcp_tun_ue(void) +{ + pthread_t t; + + reblock_tun_socket(); + + if (pthread_create(&t, NULL, ue_tun_read_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/****************************************************************************/ +/* hacks to be cleaned up at some point - end */ +/****************************************************************************/ + +int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) +{ + return 0; +} + +void pdcp_layer_init(void) +{ + /* hack: be sure to initialize only once */ + static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + static int initialized = 0; + if (pthread_mutex_lock(&m) != 0) abort(); + if (initialized) { + if (pthread_mutex_unlock(&m) != 0) abort(); + return; + } + initialized = 1; + if (pthread_mutex_unlock(&m) != 0) abort(); + + nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1); + + if ((RC.nrrrc == NULL) || (!NODE_IS_CU(RC.nrrrc[0]->node_type))) { + init_nr_rlc_data_req_queue(); + } + + init_nr_pdcp_data_ind_queue(); + nr_pdcp_init_timer_thread(nr_pdcp_ue_manager); +} + +#include "nfapi/oai_integration/vendor_ext.h" +#include "targets/RT/USER/lte-softmodem.h" +#include "openair2/RRC/NAS/nas_config.h" + +uint64_t pdcp_module_init(uint64_t _pdcp_optmask) +{ + /* hack: be sure to initialize only once */ + static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + static int initialized = 0; + if (pthread_mutex_lock(&m) != 0) abort(); + if (initialized) { + abort(); + } + initialized = 1; + if (pthread_mutex_unlock(&m) != 0) abort(); + +#if 0 + pdcp_optmask = _pdcp_optmask; + return pdcp_optmask; +#endif + /* temporary enforce netlink when UE_NAS_USE_TUN is set, + this is while switching from noS1 as build option + to noS1 as config option */ + if ( _pdcp_optmask & UE_NAS_USE_TUN_BIT) { + pdcp_optmask = pdcp_optmask | PDCP_USE_NETLINK_BIT ; + } + + pdcp_optmask = pdcp_optmask | _pdcp_optmask ; + LOG_I(PDCP, "pdcp init,%s %s\n", + ((LINK_ENB_PDCP_TO_GTPV1U)?"usegtp":""), + ((PDCP_USE_NETLINK)?"usenetlink":"")); + + if (PDCP_USE_NETLINK) { + nas_getparams(); + + if(UE_NAS_USE_TUN) { + int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )? MAX_MOBILES_PER_ENB : 1; + netlink_init_tun("ue",num_if); + //Add --nr-ip-over-lte option check for next line + if (IS_SOFTMODEM_NOS1) + nas_config(1, 1, 2, "ue"); + LOG_I(PDCP, "UE pdcp will use tun interface\n"); + start_pdcp_tun_ue(); + } else if(ENB_NAS_USE_TUN) { + netlink_init_tun("enb",1); + nas_config(1, 1, 1, "enb"); + LOG_I(PDCP, "ENB pdcp will use tun interface\n"); + start_pdcp_tun_enb(); + } else { + LOG_I(PDCP, "pdcp will use kernel modules\n"); + abort(); + netlink_init(); + } + } + return pdcp_optmask ; +} + +static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, + char *buf, int size) +{ + extern int nas_sock_fd[]; + int len; + nr_pdcp_ue_t *ue = _ue; + MessageDef *message_p; + uint8_t *gtpu_buffer_p; + int rb_id; + int i; + + if(IS_SOFTMODEM_NOS1 || UE_NAS_USE_TUN){ + LOG_D(PDCP, "IP packet received, to be sent to TUN interface"); + + if(entity->has_sdapDLheader){ + size -= SDAP_HDR_LENGTH; + len = write(nas_sock_fd[0], &buf[SDAP_HDR_LENGTH], size); + } else { + len = write(nas_sock_fd[0], buf, size); + } + + if (len != size) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + } + + } + else{ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + + rb_found: + { + int offset=0; + if (entity->has_sdap == 1 && entity->has_sdapULheader == 1) offset = 1; // this is the offset of the SDAP header in bytes + + gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U, + size + GTPU_HEADER_OVERHEAD_MAX - offset); + AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY"); + memcpy(>pu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], buf+offset, size-offset); + message_p = itti_alloc_new_message(TASK_PDCP_ENB, 0, GTPV1U_GNB_TUNNEL_DATA_REQ); + AssertFatal(message_p != NULL, "OUT OF MEMORY"); + GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).buffer = gtpu_buffer_p; + GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).length = size-offset; + GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).offset = GTPU_HEADER_OVERHEAD_MAX; + GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).rnti = ue->rnti; + GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).pdusession_id = entity->pdusession_id; + if (offset==1) { + LOG_I(PDCP, "%s() (drb %d) SDAP header %2x\n",__func__, rb_id, buf[0]); + sdap_gnb_ul_header_handler(buf[0]); // Handler for the UL gNB SDAP Header + } + LOG_D(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size-offset); + itti_send_msg_to_task(TASK_VARIABLE, INSTANCE_DEFAULT, message_p); + } + } +} + +static void deliver_pdu_drb(void *_ue, nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id) +{ + nr_pdcp_ue_t *ue = _ue; + int rb_id; + protocol_ctxt_t ctxt; + int i; + mem_block_t *memblock; + + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = ue->rnti; + + memblock = get_free_mem_block(size, __FUNCTION__); + memcpy(memblock->data, buf, size); + + LOG_D(PDCP, "%s(): (srb %d) calling rlc_data_req size %d\n", __func__, rb_id, size); + //for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]); + //printf("\n"); + enqueue_rlc_data_req(&ctxt, 0, MBMS_FLAG_NO, rb_id, sdu_id, 0, size, memblock, NULL, NULL); +} + +static void deliver_sdu_srb(void *_ue, nr_pdcp_entity_t *entity, + char *buf, int size) +{ + nr_pdcp_ue_t *ue = _ue; + int srb_id; + int i; + + for (i = 0; i < sizeofArray(ue->srb) ; i++) { + if (entity == ue->srb[i]) { + srb_id = i+1; + goto srb_found; + } + } + + LOG_E(PDCP, "%s:%d:%s: fatal, no SRB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + + srb_found: + { + uint8_t *rrc_buffer_p = entity->is_gnb ? + itti_malloc(TASK_PDCP_ENB, TASK_RRC_GNB, size): + itti_malloc(TASK_PDCP_UE, TASK_RRC_NRUE, size); + MessageDef *message_p; + + AssertFatal(rrc_buffer_p != NULL, "OUT OF MEMORY"); + memcpy(rrc_buffer_p, buf, size); + message_p = entity->is_gnb ? + itti_alloc_new_message(TASK_PDCP_ENB, 0, NR_RRC_DCCH_DATA_IND): + itti_alloc_new_message(TASK_PDCP_UE, 0, NR_RRC_DCCH_DATA_IND); + + AssertFatal(message_p != NULL, "OUT OF MEMORY"); + NR_RRC_DCCH_DATA_IND(message_p).dcch_index = srb_id; + NR_RRC_DCCH_DATA_IND(message_p).sdu_p = rrc_buffer_p; + NR_RRC_DCCH_DATA_IND(message_p).sdu_size = size; + NR_RRC_DCCH_DATA_IND(message_p).rnti = ue->rnti; + + itti_send_msg_to_task(entity->is_gnb ? TASK_RRC_GNB : TASK_RRC_NRUE, 0, message_p); + } +} + +static void deliver_pdu_srb(void *_ue, nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id) +{ + nr_pdcp_ue_t *ue = _ue; + int srb_id; + protocol_ctxt_t ctxt; + int i; + mem_block_t *memblock; + + for (i = 0; i < sizeofArray(ue->srb) ; i++) { + if (entity == ue->srb[i]) { + srb_id = i+1; + goto srb_found; + } + } + + LOG_E(PDCP, "%s:%d:%s: fatal, no SRB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +srb_found: + + + LOG_D(PDCP, "%s(): (srb %d) calling rlc_data_req size %d\n", __func__, srb_id, size); + //for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]); + //printf("\n"); + if ((RC.nrrrc == NULL) || (!NODE_IS_CU(RC.nrrrc[0]->node_type))) { + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = ue->rnti; + + memblock = get_free_mem_block(size, __FUNCTION__); + memcpy(memblock->data, buf, size); + enqueue_rlc_data_req(&ctxt, 1, MBMS_FLAG_NO, srb_id, sdu_id, 0, size, memblock, NULL, NULL); + } + else { + MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_DL_RRC_MESSAGE); + F1AP_DL_RRC_MESSAGE (message_p).rrc_container = (uint8_t*)buf; + F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = size; + F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id = 0; + F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id = 0; + F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id = 0xFFFFFFFF; // unknown + F1AP_DL_RRC_MESSAGE (message_p).rnti = ue->rnti; + F1AP_DL_RRC_MESSAGE (message_p).srb_id = srb_id; + F1AP_DL_RRC_MESSAGE (message_p).execute_duplication = 1; + F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc = 0; + itti_send_msg_to_task (TASK_CU_F1, 0, message_p); + LOG_D(PDCP, "Send F1AP_DL_RRC_MESSAGE with ITTI\n"); + } +} + +void pdcp_run(const protocol_ctxt_t *const ctxt_pP) +{ + MessageDef *msg_p; + int result; + protocol_ctxt_t ctxt={.module_id=0, + .enb_flag=1, + .instance=0, + .rnti=0, + .frame=-1, + .subframe=-1, + .eNB_index=0, + .configured=true, + .brOption=false + }; + + + while (1) { + itti_poll_msg(ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p); + if (msg_p == NULL){ + break; + } + switch (ITTI_MSG_ID(msg_p)) { + case RRC_DCCH_DATA_REQ: + LOG_D(PDCP, "Received RRC_DCCH_DATA_REQ type at PDCP task \n"); + PROTOCOL_CTXT_SET_BY_MODULE_ID( + &ctxt, + RRC_DCCH_DATA_REQ(msg_p).module_id, + RRC_DCCH_DATA_REQ(msg_p).enb_flag, + RRC_DCCH_DATA_REQ(msg_p).rnti, + RRC_DCCH_DATA_REQ(msg_p).frame, + 0, + RRC_DCCH_DATA_REQ(msg_p).eNB_index); + result = pdcp_data_req(&ctxt, + SRB_FLAG_YES, + RRC_DCCH_DATA_REQ(msg_p).rb_id, + RRC_DCCH_DATA_REQ(msg_p).muip, + RRC_DCCH_DATA_REQ(msg_p).confirmp, + RRC_DCCH_DATA_REQ(msg_p).sdu_size, + RRC_DCCH_DATA_REQ(msg_p).sdu_p, + RRC_DCCH_DATA_REQ(msg_p).mode, + NULL, NULL); + + if (result != TRUE) + LOG_E(PDCP, "PDCP data request failed!\n"); + result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ(msg_p).sdu_p); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + break; + default: + LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p)); + break; + } + } +} + +static void add_srb(int is_gnb, int rnti, struct NR_SRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) +{ + nr_pdcp_entity_t *pdcp_srb; + nr_pdcp_ue_t *ue; + int t_Reordering=3000; + + int srb_id = s->srb_Identity; + if (s->pdcp_Config == NULL || + s->pdcp_Config->t_Reordering == NULL) t_Reordering = 3000; + else t_Reordering = decode_t_reordering(*s->pdcp_Config->t_Reordering); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + if (ue->srb[srb_id-1] != NULL) { + LOG_D(PDCP, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n", + __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + } else { + pdcp_srb = new_nr_pdcp_entity(NR_PDCP_SRB, is_gnb, srb_id, + 0, 0, 0, 0, // sdap parameters + deliver_sdu_srb, ue, deliver_pdu_srb, ue, + 12, t_Reordering, -1, + ciphering_algorithm, + integrity_algorithm, + ciphering_key, + integrity_key); + nr_pdcp_ue_add_srb_pdcp_entity(ue, srb_id, pdcp_srb); + + LOG_D(PDCP, "%s:%d:%s: added srb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + } + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); +} + +static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) +{ + nr_pdcp_entity_t *pdcp_drb; + nr_pdcp_ue_t *ue; + + int drb_id = s->drb_Identity; + int sn_size_ul = decode_sn_size_ul(*s->pdcp_Config->drb->pdcp_SN_SizeUL); + int sn_size_dl = decode_sn_size_dl(*s->pdcp_Config->drb->pdcp_SN_SizeDL); + int discard_timer = decode_discard_timer(*s->pdcp_Config->drb->discardTimer); + + int has_integrity; + int has_ciphering; + + /* if pdcp_Config->t_Reordering is not present, it means infinity (-1) */ + int t_reordering = -1; + if (s->pdcp_Config->t_Reordering != NULL) { + t_reordering = decode_t_reordering(*s->pdcp_Config->t_Reordering); + } + + if (s->pdcp_Config->drb != NULL + && s->pdcp_Config->drb->integrityProtection != NULL) + has_integrity = 1; + else + has_integrity = 0; + + if (s->pdcp_Config->ext1 != NULL + && s->pdcp_Config->ext1->cipheringDisabled != NULL) + has_ciphering = 0; + else + has_ciphering = 1; + + if ((!s->cnAssociation) || s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_NOTHING) { + LOG_E(PDCP,"%s:%d:%s: fatal, cnAssociation is missing or present is NR_DRB_ToAddMod__cnAssociation_PR_NOTHING\n",__FILE__,__LINE__,__FUNCTION__); + exit(-1); + } + + int pdusession_id; + int has_sdap = 0; + int has_sdapULheader=0; + int has_sdapDLheader=0; + if (s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity) + pdusession_id = s->cnAssociation->choice.eps_BearerIdentity; + else { + if (!s->cnAssociation->choice.sdap_Config) { + LOG_E(PDCP,"%s:%d:%s: fatal, sdap_Config is null",__FILE__,__LINE__,__FUNCTION__); + exit(-1); + } + pdusession_id = s->cnAssociation->choice.sdap_Config->pdu_Session; + has_sdap = 1; + has_sdapULheader = s->cnAssociation->choice.sdap_Config->sdap_HeaderUL == NR_SDAP_Config__sdap_HeaderUL_present ? 1 : 0; + has_sdapDLheader = s->cnAssociation->choice.sdap_Config->sdap_HeaderDL == NR_SDAP_Config__sdap_HeaderDL_present ? 1 : 0; + } + /* TODO(?): accept different UL and DL SN sizes? */ + if (sn_size_ul != sn_size_dl) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad SN sizes, must be same. ul=%d, dl=%d\n", + __FILE__, __LINE__, __FUNCTION__, sn_size_ul, sn_size_dl); + exit(1); + } + + if (drb_id != 1) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id); + exit(1); + } + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + if (ue->drb[drb_id-1] != NULL) { + LOG_W(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } else { + pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id,pdusession_id,has_sdap, + has_sdapULheader,has_sdapDLheader, + deliver_sdu_drb, ue, deliver_pdu_drb, ue, + sn_size_dl, t_reordering, discard_timer, + has_ciphering ? ciphering_algorithm : 0, + has_integrity ? integrity_algorithm : 0, + has_ciphering ? ciphering_key : NULL, + has_integrity ? integrity_key : NULL); + nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); + + LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); +} + +static void add_drb(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, + NR_RLC_Config_t *rlc_Config, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) +{ + switch (rlc_Config->present) { + case NR_RLC_Config_PR_am: + add_drb_am(is_gnb, rnti, s, ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); + break; + case NR_RLC_Config_PR_um_Bi_Directional: + //add_drb_um(rnti, s); + /* hack */ + add_drb_am(is_gnb, rnti, s, ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); + break; + default: + LOG_E(PDCP, "%s:%d:%s: fatal: unhandled DRB type\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + LOG_I(PDCP, "%s:%s:%d: added DRB for UE RNTI %x\n", __FILE__, __FUNCTION__, __LINE__, rnti); +} + +boolean_t nr_rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc, + uint8_t *const kUPint + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 + ,rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) + //struct NR_RLC_Config *rlc_Config) +{ + int rnti = ctxt_pP->rnti; + int i; + + if (//ctxt_pP->enb_flag != 1 || + ctxt_pP->module_id != 0 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 || + //ctxt_pP->configured != 2 || + //srb2add_list == NULL || + //drb2add_list != NULL || + //drb2release_list != NULL || + //security_modeP != 255 || + //kRRCenc != NULL || + //kRRCint != NULL || + //kUPenc != NULL || + pmch_InfoList_r9 != NULL /*|| + defaultDRB != NULL */) { + LOG_I(PDCP,"Releasing DRBs, oops\n"); + TODO; + } + + if (srb2add_list != NULL) { + for (i = 0; i < srb2add_list->list.count; i++) { + add_srb(ctxt_pP->enb_flag,rnti, srb2add_list->list.array[i], + security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, + kRRCenc, kRRCint); + } + } + + if (drb2add_list != NULL) { + for (i = 0; i < drb2add_list->list.count; i++) { + add_drb(ctxt_pP->enb_flag, rnti, drb2add_list->list.array[i], + rlc_bearer2add_list->list.array[i]->rlc_Config, + security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, + kUPenc, kUPint); + } + } + + /* update security */ + if (kRRCint != NULL) { + /* todo */ + } + + if (drb2release_list != NULL) { + // TODO + } + + free(kRRCenc); + free(kRRCint); + free(kUPenc); + free(kUPint); + + return 0; +} + +/* Dummy function due to dependency from LTE libraries */ +boolean_t rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + LTE_SRB_ToAddModList_t *const srb2add_list, + LTE_DRB_ToAddModList_t *const drb2add_list, + LTE_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 + ,rb_id_t *const defaultDRB) +{ + return 0; +} + +void nr_DRB_preconfiguration(uint16_t crnti) +{ + + NR_RadioBearerConfig_t *rbconfig = NULL; + struct NR_CellGroupConfig__rlc_BearerToAddModList *Rlc_Bearer_ToAdd_list = NULL; + protocol_ctxt_t ctxt; + //fill_default_rbconfig(rb_config, 5, 1); + rbconfig = calloc(1, sizeof(*rbconfig)); + + rbconfig->srb_ToAddModList = NULL; + rbconfig->srb3_ToRelease = NULL; + rbconfig->drb_ToAddModList = calloc(1,sizeof(*rbconfig->drb_ToAddModList)); + NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod)); + drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation)); + drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; + drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5; + drb_ToAddMod->drb_Identity = 1; + drb_ToAddMod->reestablishPDCP = NULL; + drb_ToAddMod->recoverPDCP = NULL; + drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); + drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); + drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); + *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity; + drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); + *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits; + drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); + *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len12bits; + drb_ToAddMod->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drb_ToAddMod->pdcp_Config->drb->headerCompression.choice.notUsed = 0; + + drb_ToAddMod->pdcp_Config->drb->integrityProtection=NULL; + drb_ToAddMod->pdcp_Config->drb->statusReportRequired=NULL; + drb_ToAddMod->pdcp_Config->drb->outOfOrderDelivery=NULL; + drb_ToAddMod->pdcp_Config->moreThanOneRLC = NULL; + + drb_ToAddMod->pdcp_Config->t_Reordering = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->t_Reordering)); + *drb_ToAddMod->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; + drb_ToAddMod->pdcp_Config->ext1 = NULL; + + ASN_SEQUENCE_ADD(&rbconfig->drb_ToAddModList->list,drb_ToAddMod); + + rbconfig->drb_ToReleaseList = NULL; + + rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig)); + rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig)); + rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; + rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL; + rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse)); + *rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); + } + + NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig)); + nr_rlc_bearer_init(RLC_BearerConfig,NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity); + nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional); + nr_rlc_bearer_init_ul_spec(RLC_BearerConfig->mac_LogicalChannelConfig); + + Rlc_Bearer_ToAdd_list = calloc(1,sizeof(*Rlc_Bearer_ToAdd_list)); + ASN_SEQUENCE_ADD(&Rlc_Bearer_ToAdd_list->list, RLC_BearerConfig); + + if (ENB_NAS_USE_TUN){ + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_YES, crnti, 0, 0, 0); + } + else{ + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, crnti, 0, 0,0); + } + + nr_rrc_pdcp_config_asn1_req( + &ctxt, + (NR_SRB_ToAddModList_t *) NULL, + rbconfig->drb_ToAddModList , + rbconfig->drb_ToReleaseList, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + Rlc_Bearer_ToAdd_list); + + nr_rrc_rlc_config_asn1_req (&ctxt, + (NR_SRB_ToAddModList_t *) NULL, + rbconfig->drb_ToAddModList, + rbconfig->drb_ToReleaseList, + (LTE_PMCH_InfoList_r9_t *) NULL, + Rlc_Bearer_ToAdd_list); + + LOG_D(PDCP, "%s:%d: done RRC PDCP/RLC ASN1 request for UE rnti %x\n", __FUNCTION__, __LINE__, ctxt.rnti); + +} + +uint64_t get_pdcp_optmask(void) +{ + return pdcp_optmask; +} + +boolean_t pdcp_remove_UE( + const protocol_ctxt_t *const ctxt_pP) +{ + int rnti = ctxt_pP->rnti; + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager, rnti); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + return 1; +} + +void pdcp_config_set_security( + const protocol_ctxt_t* const ctxt_pP, + pdcp_t *const pdcp_pP, + const rb_id_t rb_id, + const uint16_t lc_idP, + const uint8_t security_modeP, + uint8_t *const kRRCenc_pP, + uint8_t *const kRRCint_pP, + uint8_t *const kUPenc_pP) +{ + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + int rnti = ctxt_pP->rnti; + int integrity_algorithm; + int ciphering_algorithm; + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + + /* TODO: proper handling of DRBs, for the moment only SRBs are handled */ + + if (rb_id >= 1 && rb_id <= 2) { + rb = ue->srb[rb_id - 1]; + + if (rb == NULL) { + LOG_E(PDCP, "%s:%d:%s: no SRB found (rnti %d, rb_id %ld)\n", + __FILE__, __LINE__, __FUNCTION__, rnti, rb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return; + } + + integrity_algorithm = (security_modeP>>4) & 0xf; + ciphering_algorithm = security_modeP & 0x0f; + rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP, + ciphering_algorithm, (char *)kRRCenc_pP); + } else { + LOG_E(PDCP, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); +} + +static boolean_t pdcp_data_req_srb( + protocol_ctxt_t *ctxt_pP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer) +{ + LOG_D(PDCP, "%s() called, size %d\n", __func__, sdu_buffer_size); + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + int rnti = ctxt_pP->rnti; + + if (ctxt_pP->module_id != 0 || + //ctxt_pP->enb_flag != 1 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 /*|| + ctxt_pP->configured != 1 || + ctxt_pP->brOption != 0*/) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + + if (rb_id < 1 || rb_id > 2) + rb = NULL; + else + rb = ue->srb[rb_id - 1]; + + if (rb == NULL) { + LOG_E(PDCP, "%s:%d:%s: no SRB found (rnti %d, rb_id %ld)\n", + __FILE__, __LINE__, __FUNCTION__, rnti, rb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return 0; + } + + rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP); + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + return 1; +} + + +static boolean_t pdcp_data_req_drb( + protocol_ctxt_t *ctxt_pP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer) +{ + LOG_D(PDCP, "%s() called, size %d\n", __func__, sdu_buffer_size); + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + int rnti = ctxt_pP->rnti; + + if (ctxt_pP->module_id != 0 || + //ctxt_pP->enb_flag != 1 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 /*|| + ctxt_pP->configured != 1 || + ctxt_pP->brOption != 0*/) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + + if (rb_id < 1 || rb_id > 5) + rb = NULL; + else + rb = ue->drb[rb_id - 1]; + + if (rb == NULL) { + LOG_E(PDCP, "%s:%d:%s: no DRB found (rnti %d, rb_id %ld)\n", + __FILE__, __LINE__, __FUNCTION__, rnti, rb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return 0; + } + + rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP); + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + return 1; +} + +boolean_t pdcp_data_req( + protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode + ,const uint32_t *const sourceL2Id + ,const uint32_t *const destinationL2Id + ) +{ + if (srb_flagP) { + return pdcp_data_req_srb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size, sdu_buffer); + } + else{ + return pdcp_data_req_drb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size, sdu_buffer); + } +} + +void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind) +{ + /* nothing to do */ +} + +void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req) +{ + /* nothing to do */ +} + +//Dummy function needed due to LTE dependencies +void +pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){ + /* nothing to do */ +} + +void nr_pdcp_tick(int frame, int subframe) +{ + if (frame != nr_pdcp_current_time_last_frame || + subframe != nr_pdcp_current_time_last_subframe) { + nr_pdcp_current_time_last_frame = frame; + nr_pdcp_current_time_last_subframe = subframe; + nr_pdcp_current_time++; + nr_pdcp_wakeup_timer_thread(nr_pdcp_current_time); + } +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c new file mode 100644 index 0000000000..47d95156e3 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c @@ -0,0 +1,78 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_sdu.h" + +#include +#include + +nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size) +{ + nr_pdcp_sdu_t *ret = calloc(1, sizeof(nr_pdcp_sdu_t)); + if (ret == NULL) + exit(1); + ret->count = count; + ret->buffer = malloc(size); + if (ret->buffer == NULL) + exit(1); + memcpy(ret->buffer, buffer, size); + ret->size = size; + return ret; +} + +nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu) +{ + nr_pdcp_sdu_t head; + nr_pdcp_sdu_t *cur; + nr_pdcp_sdu_t *prev; + + head.next = l; + cur = l; + prev = &head; + + /* order is by 'count' */ + while (cur != NULL) { + /* check if 'sdu' is before 'cur' in the list */ + if (sdu->count < cur->count) + break; + prev = cur; + cur = cur->next; + } + prev->next = sdu; + sdu->next = cur; + return head.next; +} + +int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count) +{ + while (l != NULL) { + if (l->count == count) + return 1; + l = l->next; + } + return 0; +} + +void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu) +{ + free(sdu->buffer); + free(sdu); +} diff --git a/common/utils/itti_analyzer/libparser/enum_type.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h similarity index 67% rename from common/utils/itti_analyzer/libparser/enum_type.h rename to openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h index 4538829e78..3d4e50a4ce 100644 --- a/common/utils/itti_analyzer/libparser/enum_type.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h @@ -19,19 +19,21 @@ * contact@openairinterface.org */ -#include "types.h" +#ifndef _NR_PDCP_SDU_H_ +#define _NR_PDCP_SDU_H_ -#ifndef ENUM_TYPE_H_ -#define ENUM_TYPE_H_ +#include -char *enum_type_get_name_from_value(types_t *type, uint32_t value); +typedef struct nr_pdcp_sdu_t { + uint32_t count; + char *buffer; + int size; + struct nr_pdcp_sdu_t *next; +} nr_pdcp_sdu_t; -int enum_type_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); +nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size); +nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu); +int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count); +void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu); -int enum_type_file_print(types_t *type, int indent, FILE *file); - -int enum_type_hr_display(types_t *type, int indent); - -#endif /* ENUM_TYPE_H_ */ +#endif /* _NR_PDCP_SDU_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c new file mode 100644 index 0000000000..52afe95673 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c @@ -0,0 +1,74 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_security_nea2.h" + +#include +#include +#include +#include +#include + +#ifndef NETTLE_VERSION_MAJOR +/* hack: include bignum.h, not version.h because version.h does not exist + * in old versions and bignum.h includes version.h (as of today). + * May completely fail to work... maybe we should skip support of old + * versions of nettle. + */ +#include +#endif + +void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key) +{ + void *ctx = calloc(1, nettle_aes128.context_size); + if (ctx == NULL) exit(1); + +#if !defined(NETTLE_VERSION_MAJOR) || NETTLE_VERSION_MAJOR < 3 + nettle_aes128.set_encrypt_key(ctx, 16, ciphering_key); +#else + nettle_aes128.set_encrypt_key(ctx, ciphering_key); +#endif + + return ctx; +} + +void nr_pdcp_security_nea2_cipher(void *security_context, + unsigned char *buffer, int length, + int bearer, int count, int direction) +{ + unsigned char t[16]; + + t[0] = (count >> 24) & 255; + t[1] = (count >> 16) & 255; + t[2] = (count >> 8) & 255; + t[3] = (count ) & 255; + t[4] = ((bearer-1) << 3) | (direction << 2); + memset(&t[5], 0, 16-5); + + nettle_ctr_crypt(security_context, nettle_aes128.encrypt, + nettle_aes128.block_size, t, + length, buffer, buffer); +} + +void nr_pdcp_security_nea2_free_security(void *security_context) +{ + free(security_context); +} diff --git a/common/utils/itti_analyzer/libparser/array_type.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h similarity index 70% rename from common/utils/itti_analyzer/libparser/array_type.h rename to openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h index b336934dbb..c3667c93d4 100644 --- a/common/utils/itti_analyzer/libparser/array_type.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h @@ -19,17 +19,15 @@ * contact@openairinterface.org */ -#include "types.h" +#ifndef _NR_PDCP_SECURITY_NEA2_H_ +#define _NR_PDCP_SECURITY_NEA2_H_ -#ifndef ARRAY_TYPE_H_ -#define ARRAY_TYPE_H_ +void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key); -int array_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); +void nr_pdcp_security_nea2_cipher(void *security_context, + unsigned char *buffer, int length, + int bearer, int count, int direction); -int array_type_hr_display(types_t *type, int indent); +void nr_pdcp_security_nea2_free_security(void *security_context); -int array_type_file_print(types_t *type, int indent, FILE *file); - -#endif /* ARRAY_TYPE_H_ */ +#endif /* _NR_PDCP_SECURITY_NEA2_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c new file mode 100644 index 0000000000..36e9b16024 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c @@ -0,0 +1,87 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_timer_thread.h" + +#include +#include +#include + +#include "LOG/log.h" + +static pthread_mutex_t timer_thread_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t timer_thread_cond = PTHREAD_COND_INITIALIZER; +static volatile uint64_t timer_thread_curtime = 0; + +static void *nr_pdcp_timer_thread(void *_nr_pdcp_ue_manager) +{ + nr_pdcp_ue_manager_t *nr_pdcp_ue_manager = (nr_pdcp_ue_manager_t *)_nr_pdcp_ue_manager; + nr_pdcp_ue_t **ue_list; + int ue_count; + int i; + int j; + uint64_t curtime = 0; + + while (1) { + if (pthread_mutex_lock(&timer_thread_mutex) != 0) abort(); + while (curtime == timer_thread_curtime) + if (pthread_cond_wait(&timer_thread_cond, &timer_thread_mutex) != 0) abort(); + curtime = timer_thread_curtime; + if (pthread_mutex_unlock(&timer_thread_mutex) != 0) abort(); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue_list = nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager); + ue_count = nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager); + for (i = 0; i < ue_count; i++) { + for (j = 0; j < 2; j++) { + if (ue_list[i]->srb[j] != NULL) + ue_list[i]->srb[j]->set_time(ue_list[i]->srb[j], curtime); + } + for (j = 0; j < 5; j++) { + if (ue_list[i]->drb[j] != NULL) + ue_list[i]->drb[j]->set_time(ue_list[i]->drb[j], curtime); + } + } + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + } + + return NULL; +} + +void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager) +{ + pthread_t t; + + if (pthread_create(&t, NULL, nr_pdcp_timer_thread, nr_pdcp_ue_manager) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +void nr_pdcp_wakeup_timer_thread(uint64_t time) +{ + if (pthread_mutex_lock(&timer_thread_mutex)) abort(); + timer_thread_curtime = time; + if (pthread_cond_broadcast(&timer_thread_cond)) abort(); + if (pthread_mutex_unlock(&timer_thread_mutex)) abort(); +} diff --git a/common/utils/itti_analyzer/libui/ui_notif_dlg.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h similarity index 79% rename from common/utils/itti_analyzer/libui/ui_notif_dlg.h rename to openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h index 361ec81850..db8282f940 100644 --- a/common/utils/itti_analyzer/libui/ui_notif_dlg.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h @@ -19,13 +19,14 @@ * contact@openairinterface.org */ -#include +#ifndef _NR_PDCP_TIMER_THREAD_H_ +#define _NR_PDCP_TIMER_THREAD_H_ -#ifndef UI_NOTIF_DLG_H_ -#define UI_NOTIF_DLG_H_ +#include "nr_pdcp_ue_manager.h" -const char *gtk_get_respose_string (gint response); +#include -extern int ui_notification_dialog(GtkMessageType type, gboolean cancel, const char *title, const char *fmt, ...); +void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager); +void nr_pdcp_wakeup_timer_thread(uint64_t time); -#endif /* UI_NOTIF_DLG_H_ */ +#endif /* _NR_PDCP_TIMER_THREAD_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c new file mode 100644 index 0000000000..160c5ebb22 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c @@ -0,0 +1,212 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_ue_manager.h" + +#include +#include +#include + +#include "LOG/log.h" + +typedef struct { + pthread_mutex_t lock; + nr_pdcp_ue_t **ue_list; + int ue_count; + int enb_flag; +} nr_pdcp_ue_manager_internal_t; + +nr_pdcp_ue_manager_t *new_nr_pdcp_ue_manager(int enb_flag) +{ + nr_pdcp_ue_manager_internal_t *ret; + + ret = calloc(1, sizeof(nr_pdcp_ue_manager_internal_t)); + if (ret == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (pthread_mutex_init(&ret->lock, NULL)) abort(); + ret->enb_flag = enb_flag; + + return ret; +} + +int nr_pdcp_manager_get_enb_flag(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->enb_flag; +} + +void nr_pdcp_manager_lock(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (pthread_mutex_lock(&m->lock)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (pthread_mutex_unlock(&m->lock)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *_m, int rnti) +{ + /* TODO: optimze */ + nr_pdcp_ue_manager_internal_t *m = _m; + int i; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + return m->ue_list[i]; + + LOG_D(PDCP, "%s:%d:%s: new UE 0x%x\n", __FILE__, __LINE__, __FUNCTION__, rnti); + + m->ue_count++; + m->ue_list = realloc(m->ue_list, sizeof(nr_pdcp_ue_t *) * m->ue_count); + if (m->ue_list == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + m->ue_list[m->ue_count-1] = calloc(1, sizeof(nr_pdcp_ue_t)); + if (m->ue_list[m->ue_count-1] == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + m->ue_list[m->ue_count-1]->rnti = rnti; + + return m->ue_list[m->ue_count-1]; +} + +/* must be called with lock acquired */ +void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *_m, int rnti) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + nr_pdcp_ue_t *ue; + int i; + int j; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + break; + + if (i == m->ue_count) { + LOG_D(PDCP, "%s:%d:%s: warning: ue %d not found\n", + __FILE__, __LINE__, __FUNCTION__, + rnti); + return; + } + + ue = m->ue_list[i]; + + for (j = 0; j < 2; j++) + if (ue->srb[j] != NULL) + ue->srb[j]->delete(ue->srb[j]); + + for (j = 0; j < 5; j++) + if (ue->drb[j] != NULL) + ue->drb[j]->delete(ue->drb[j]); + + free(ue); + + m->ue_count--; + if (m->ue_count == 0) { + free(m->ue_list); + m->ue_list = NULL; + return; + } + + memmove(&m->ue_list[i], &m->ue_list[i+1], + (m->ue_count - i) * sizeof(nr_pdcp_ue_t *)); + m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(nr_pdcp_ue_t *)); + if (m->ue_list == NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +void nr_pdcp_ue_add_srb_pdcp_entity(nr_pdcp_ue_t *ue, int srb_id, nr_pdcp_entity_t *entity) +{ + if (srb_id < 1 || srb_id > 2) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + srb_id--; + + if (ue->srb[srb_id] != NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal, srb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->srb[srb_id] = entity; +} + +/* must be called with lock acquired */ +void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity_t *entity) +{ + if (drb_id < 1 || drb_id > 5) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + drb_id--; + + if (ue->drb[drb_id] != NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal, drb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->drb[drb_id] = entity; +} + +/* must be called with lock acquired */ +nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->ue_list; +} + +/* must be called with lock acquired */ +int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->ue_count; +} + +int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (m->ue_count == 0) + return -1; + return m->ue_list[0]->rnti; +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h new file mode 100644 index 0000000000..742e0e84be --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h @@ -0,0 +1,68 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_PDCP_UE_MANAGER_H_ +#define _NR_PDCP_UE_MANAGER_H_ + +#include "nr_pdcp_entity.h" + +typedef void nr_pdcp_ue_manager_t; + +typedef struct nr_pdcp_ue_t { + int rnti; + nr_pdcp_entity_t *srb[3]; + nr_pdcp_entity_t *drb[5]; +} nr_pdcp_ue_t; + +/***********************************************************************/ +/* manager functions */ +/***********************************************************************/ + +nr_pdcp_ue_manager_t *new_nr_pdcp_ue_manager(int enb_flag); + +int nr_pdcp_manager_get_enb_flag(nr_pdcp_ue_manager_t *m); + +void nr_pdcp_manager_lock(nr_pdcp_ue_manager_t *m); +void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m); + +nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti); +void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti); + +nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m); +int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m); + +/***********************************************************************/ +/* ue functions */ +/***********************************************************************/ + +void nr_pdcp_ue_add_srb_pdcp_entity(nr_pdcp_ue_t *ue, int srb_id, + nr_pdcp_entity_t *entity); +void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, + nr_pdcp_entity_t *entity); + +/***********************************************************************/ +/* hacks */ +/***********************************************************************/ + +/* returns -1 if no UE */ +int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *m); + +#endif /* _NR_PDCP_UE_MANAGER_H_ */ diff --git a/openair2/LAYER2/nr_rlc/asn1_utils.c b/openair2/LAYER2/nr_rlc/asn1_utils.c index 46f7d90da5..43d55af1ac 100644 --- a/openair2/LAYER2/nr_rlc/asn1_utils.c +++ b/openair2/LAYER2/nr_rlc/asn1_utils.c @@ -21,14 +21,14 @@ #include "rlc.h" -int decode_t_reordering(int v) +int decode_t_reassembly(int v) { - static int tab[32] = { - 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, - 90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 1600 + static int tab[31] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, + 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200 }; - if (v < 0 || v > 31) { + if (v < 0 || v > 30) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -72,11 +72,13 @@ int decode_t_poll_retransmit(int v) int decode_poll_pdu(int v) { - static int tab[8] = { - 4, 8, 16, 32, 64, 128, 256, -1 /* -1 means infinity */ + static int tab[24] = { + 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 6144, 8192, 12288, + 16384, 20480, 24576, 28672, 32768, 40960, 49152, 57344, 65536 + -1 /* -1 means infinity */ }; - if (v < 0 || v > 7) { + if (v < 0 || v > 23) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -86,12 +88,23 @@ int decode_poll_pdu(int v) int decode_poll_byte(int v) { - static int tab[15] = { - 25, 50, 75, 100, 125, 250, 375, 500, 750, 1000, 1250, 1500, 2000, 3000, + static int tab[44] = { + /* KB */ + 1024 * 1, 1024 * 2, 1024 * 5, 1024 * 8, 1024 * 10, + 1024 * 15, 1024 * 25, 1024 * 50, 1024 * 75, 1024 * 100, + 1024 * 125, 1024 * 250, 1024 * 375, 1024 * 500, 1024 * 750, + 1024 * 1000, 1024 * 1250, 1024 * 1500, 1024 * 2000, 1024 * 3000, + 1024 * 4000, 1024 * 4500, 1024 * 5000, 1024 * 5500, 1024 * 6000, + 1024 * 6500, 1024 * 7000, 1024 * 7500, + /* MB */ + 1024 * 1024 * 8, 1024 * 1024 * 9, 1024 * 1024 * 10, 1024 * 1024 * 11, + 1024 * 1024 * 12, 1024 * 1024 * 13, 1024 * 1024 * 14, 1024 * 1024 * 15, + 1024 * 1024 * 16, 1024 * 1024 * 17, 1024 * 1024 * 18, 1024 * 1024 * 20, + 1024 * 1024 * 25, 1024 * 1024 * 30, 1024 * 1024 * 40, -1 /* -1 means infinity */ }; - if (v < 0 || v > 14) { + if (v < 0 || v > 43) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -114,10 +127,24 @@ int decode_max_retx_threshold(int v) return tab[v]; } -int decode_sn_field_length(int v) +int decode_sn_field_length_um(int v) { static int tab[2] = { - 5, 10 + 6, 12 + }; + + if (v < 0 || v > 1) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_sn_field_length_am(int v) +{ + static int tab[2] = { + 12, 18 }; if (v < 0 || v > 1) { diff --git a/openair2/LAYER2/nr_rlc/asn1_utils.h b/openair2/LAYER2/nr_rlc/asn1_utils.h index 61394c9c69..6f010b02da 100644 --- a/openair2/LAYER2/nr_rlc/asn1_utils.h +++ b/openair2/LAYER2/nr_rlc/asn1_utils.h @@ -19,15 +19,16 @@ * contact@openairinterface.org */ -#ifndef _ASN1_UTILS_H_ -#define _ASN1_UTILS_H_ +#ifndef _OPENAIR2_LAYER2_NR_RLC_ASN1_UTILS_H_ +#define _OPENAIR2_LAYER2_NR_RLC_ASN1_UTILS_H_ -int decode_t_reordering(int v); +int decode_t_reassembly(int v); int decode_t_status_prohibit(int v); int decode_t_poll_retransmit(int v); int decode_poll_pdu(int v); int decode_poll_byte(int v); int decode_max_retx_threshold(int v); -int decode_sn_field_length(int v); +int decode_sn_field_length_um(int v); +int decode_sn_field_length_am(int v); -#endif /* _ASN1_UTILS_H_ */ +#endif /* _OPENAIR2_LAYER2_NR_RLC_ASN1_UTILS_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h index 5b12a90cfd..b9b638fe07 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h @@ -63,6 +63,8 @@ typedef struct nr_rlc_entity_t { void (*max_retx_reached)(void *max_retx_reached_data, struct nr_rlc_entity_t *entity); void *max_retx_reached_data; + /* buffer status computation */ + nr_rlc_entity_buffer_status_t bstatus; } nr_rlc_entity_t; nr_rlc_entity_t *new_nr_rlc_entity_am( diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 8f3d49d8c2..7224449bc6 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -28,6 +28,19 @@ #include "LOG/log.h" +/* for a given SDU/SDU segment, computes the corresponding PDU header size */ +static int compute_pdu_header_size(nr_rlc_entity_am_t *entity, + nr_rlc_sdu_segment_t *sdu) +{ + int header_size = 2; + /* one more byte if SN field length is 18 */ + if (entity->sn_field_length == 18) + header_size++; + /* two more bytes for SO if SDU segment is not the first */ + if (!sdu->is_first) header_size += 2; + return header_size; +} + /*************************************************************************/ /* PDU RX functions */ /*************************************************************************/ @@ -109,10 +122,15 @@ static void consider_retransmission(nr_rlc_entity_am_t *entity, * upper layers should deal with this condition, internally it's better * for the RLC code to keep going with this segment (we only remove * a segment that was ACKed) - */ + */ + LOG_D(RLC, "RLC segment to be added at the ReTx list \n"); nr_rlc_sdu_segment_list_append(&entity->retransmit_list, &entity->retransmit_end, cur); + + /* update buffer status */ + entity->common.bstatus.retx_size += compute_pdu_header_size(entity, cur) + + cur->size; } /* checks that all the bytes of the SDU sn have been received (but SDU @@ -217,7 +235,7 @@ static void reassemble_and_deliver(nr_rlc_entity_am_t *entity, int sn) bad_sdu = 1; } if (!bad_sdu && len > 0) { - memcpy(sdu + so, pdu->data, len); + memcpy(sdu + so, pdu->data + so - pdu->so, len); so += len; } free(pdu->data); @@ -350,6 +368,9 @@ static void process_received_ack(nr_rlc_entity_am_t *entity, int ack_sn) } /* remove from retransmit list */ prev->next = cur->next; + /* update buffer status */ + entity->common.bstatus.retx_size -= compute_pdu_header_size(entity, cur) + + cur->size; /* put the PDU in the ack list */ entity->ack_list = nr_rlc_sdu_segment_list_add(sn_compare_tx, entity, entity->ack_list, cur); @@ -649,7 +670,7 @@ control: control_decoder = decoder; control_e1 = e1; while (control_e1) { - nr_rlc_pdu_decoder_get_bits(&control_decoder, entity->sn_field_length); R(control_decoder); /* NACK_SN */ + nack_sn = nr_rlc_pdu_decoder_get_bits(&control_decoder, entity->sn_field_length); R(control_decoder); control_e1 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); control_e2 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); control_e3 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); @@ -659,17 +680,36 @@ control: } else { nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); } + /* check range and so_start/so_end consistency */ if (control_e2) { - nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); /* SOstart */ - nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); /* SOend */ + so_start = nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); + so_end = nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); + } else { + so_start = 0; + so_end = 0xffff; } if (control_e3) { - nr_rlc_pdu_decoder_get_bits(&control_decoder, 8); R(control_decoder); /* NACK range */ + range = nr_rlc_pdu_decoder_get_bits(&control_decoder, 8); R(control_decoder); + } else { + range = 1; + } + if (range < 1) { + LOG_E(RLC, "%s:%d:%s: error, bad 'range' in RLC NACK (sn %d)\n", + __FILE__, __LINE__, __FUNCTION__, nack_sn); + goto err; + } + /* so_start can be > so_end if more than one range; they don't refer + * to the same PDU then + */ + if (range == 1 && so_end < so_start) { + LOG_E(RLC, "%s:%d:%s: error, bad so start/end (sn %d)\n", + __FILE__, __LINE__, __FUNCTION__, nack_sn); + goto err; } } /* 38.322 5.3.3.3 says to stop t_poll_retransmit if a ACK or NACK is - * received for the SN 'poll_sn' + * received for the SN 'poll_sn' - check ACK case (NACK done below) */ if (sn_compare_tx(entity, entity->poll_sn, ack_sn) < 0) entity->t_poll_retransmit_start = 0; @@ -696,28 +736,22 @@ control: if (e2) { so_start = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder); so_end = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder); - if (so_end < so_start) { - LOG_W(RLC, "%s:%d:%s: warning, bad so start/end, NACK the whole PDU (sn %d)\n", - __FILE__, __LINE__, __FUNCTION__, nack_sn); - so_start = 0; - so_end = -1; - } - /* special value 0xffff indicates 'all bytes to the end' */ - if (so_end == 0xffff) - so_end = -1; } else { so_start = 0; - so_end = -1; + so_end = 0xffff; } if (e3) { range = nr_rlc_pdu_decoder_get_bits(&decoder, 8); R(decoder); } else { range = 1; } + /* special value 0xffff indicates 'all bytes to the end' */ + if (so_end == 0xffff) + so_end = -1; process_received_nack(entity, nack_sn, so_start, so_end, range, sn_set); /* 38.322 5.3.3.3 says to stop t_poll_retransmit if a ACK or NACK is - * received for the SN 'poll_sn' + * received for the SN 'poll_sn' - check NACK case (ACK done above) */ if (sn_compare_tx(entity, nack_sn, entity->poll_sn) <= 0 && sn_compare_tx(entity, entity->poll_sn, (nack_sn + range) % entity->sn_modulus) < 0) @@ -826,19 +860,6 @@ static int serialize_sdu(nr_rlc_entity_am_t *entity, return encoder.byte + sdu->size; } -/* for a given SDU/SDU segment, computes the corresponding PDU header size */ -static int compute_pdu_header_size(nr_rlc_entity_am_t *entity, - nr_rlc_sdu_segment_t *sdu) -{ - int header_size = 2; - /* one more byte if SN field length is 18 */ - if (entity->sn_field_length == 18) - header_size++; - /* two more bytes for SO if SDU segment is not the first */ - if (!sdu->is_first) header_size += 2; - return header_size; -} - /* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size' * bytes * - modifies SDU/SDU segment to become an SDU segment @@ -921,6 +942,7 @@ static missing_data_t next_missing(nr_rlc_entity_am_t *entity, */ ret.sn_start = entity->rx_next; ret.so_start = 0; + ret.next = cur; goto set_end_different_sdu; } } @@ -1283,7 +1305,7 @@ static int missing_size(nr_rlc_entity_am_t *entity, missing_data_t *m, missing_data_t m_nack; /* be careful to limit a range to 255 SNs, that is: cut if needed */ - sn_count = m->sn_end - m->sn_start; + sn_count = m->sn_end - m->sn_start + 1; if (sn_count < 0) sn_count += entity->sn_modulus; @@ -1411,8 +1433,12 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer, sdu->next = NULL; - /* segment if necessary */ pdu_size = pdu_header_size + sdu->size; + + /* update buffer status */ + entity->common.bstatus.retx_size -= pdu_size; + + /* segment if necessary */ if (pdu_size > size) { nr_rlc_sdu_segment_t *next_sdu; next_sdu = resegment(sdu, entity, size); @@ -1421,6 +1447,9 @@ static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer, entity->retransmit_list = next_sdu; if (entity->retransmit_end == NULL) entity->retransmit_end = entity->retransmit_list; + /* update buffer status */ + entity->common.bstatus.retx_size += compute_pdu_header_size(entity, next_sdu) + + next_sdu->size; } /* put SDU/SDU segment in the wait list */ @@ -1464,11 +1493,15 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) sdu->next = NULL; + pdu_size = pdu_header_size + sdu->size; + + /* update buffer status */ + entity->common.bstatus.tx_size -= pdu_size; + /* assign SN to SDU */ sdu->sdu->sn = entity->tx_next; /* segment if necessary */ - pdu_size = pdu_header_size + sdu->size; if (pdu_size > size) { nr_rlc_sdu_segment_t *next_sdu; next_sdu = resegment(sdu, entity, size); @@ -1477,6 +1510,9 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) entity->tx_list = next_sdu; if (entity->tx_end == NULL) entity->tx_end = entity->tx_list; + /* update buffer status */ + entity->common.bstatus.tx_size += compute_pdu_header_size(entity, next_sdu) + + next_sdu->size; } /* update tx_next if the SDU segment is the last */ @@ -1505,24 +1541,6 @@ static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size) return serialize_sdu(entity, sdu, buffer, size, p); } -/* Pretend to serialize all the SDUs in a list and return the size - * of all the PDUs it would produce, limited to 'maxsize'. - * Used for buffer status reporting. - */ -static int tx_list_size(nr_rlc_entity_am_t *entity, - nr_rlc_sdu_segment_t *l, int maxsize) -{ - int ret = 0; - - while (l != NULL) { - ret += compute_pdu_header_size(entity, l) + l->size; - l = l->next; - } - - if (ret > maxsize) ret = maxsize; - return ret; -} - nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status( nr_rlc_entity_t *_entity, int maxsize) { @@ -1534,8 +1552,8 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status( else ret.status_size = 0; - ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize); - ret.retx_size = tx_list_size(entity, entity->retransmit_list, maxsize); + ret.tx_size = entity->common.bstatus.tx_size; + ret.retx_size = entity->common.bstatus.retx_size; return ret; } @@ -1578,9 +1596,18 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity, exit(1); } + /* log SDUs rejected, at most once per second */ + if (entity->sdu_rejected != 0 + && entity->t_current > entity->t_log_buffer_full + 1000) { + LOG_E(RLC, "%s:%d:%s: warning: %d SDU rejected, SDU buffer full\n", + __FILE__, __LINE__, __FUNCTION__, + entity->sdu_rejected); + entity->sdu_rejected = 0; + entity->t_log_buffer_full = entity->t_current; + } + if (entity->tx_size + size > entity->tx_maxsize) { - LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n", - __FILE__, __LINE__, __FUNCTION__); + entity->sdu_rejected++; return; } @@ -1588,7 +1615,13 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity, sdu = nr_rlc_new_sdu(buffer, size, sdu_id); + LOG_D(RLC, "Created new RLC SDU and append it to the RLC list \n"); + nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu); + + /* update buffer status */ + entity->common.bstatus.tx_size += compute_pdu_header_size(entity, sdu) + + sdu->size; } /*************************************************************************/ @@ -1718,6 +1751,9 @@ static void check_t_reassembly(nr_rlc_entity_am_t *entity) sn = (sn + 1) % entity->sn_modulus; entity->rx_highest_status = sn; + /* trigger status report */ + entity->status_triggered = 1; + if (sn_compare_rx(entity, entity->rx_next_highest, (entity->rx_highest_status+1) % entity->sn_modulus) > 0 || (entity->rx_next_highest == @@ -1776,6 +1812,10 @@ void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id) entity->tx_end = NULL; } + /* update buffer status */ + entity->common.bstatus.tx_size -= compute_pdu_header_size(entity, cur) + + cur->size; + nr_rlc_free_sdu_segment(cur); } @@ -1799,6 +1839,9 @@ static void clear_entity(nr_rlc_entity_am_t *entity) entity->t_current = 0; + entity->t_log_buffer_full = 0; + entity->sdu_rejected = 0; + entity->t_poll_retransmit_start = 0; entity->t_reassembly_start = 0; entity->t_status_prohibit_start = 0; @@ -1828,6 +1871,9 @@ static void clear_entity(nr_rlc_entity_am_t *entity) entity->retransmit_end = NULL; entity->ack_list = NULL; + + entity->common.bstatus.tx_size = 0; + entity->common.bstatus.retx_size = 0; } void nr_rlc_entity_am_reestablishment(nr_rlc_entity_t *_entity) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h index 7a553a22a9..453fe87026 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h @@ -60,6 +60,10 @@ typedef struct { /* set to the latest know time by the user of the module. Unit: ms */ uint64_t t_current; + /* deal with logging of buffer full */ + uint64_t t_log_buffer_full; + int sdu_rejected; + /* timers (stores the TTI of activation, 0 means not active) */ uint64_t t_poll_retransmit_start; uint64_t t_reassembly_start; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c index 86a0697624..75408276d1 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c @@ -68,25 +68,15 @@ static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size) memcpy(buffer, sdu->sdu->data, sdu->size); entity->tx_size -= sdu->size; + + /* update buffer status */ + entity->common.bstatus.tx_size -= sdu->size; + nr_rlc_free_sdu_segment(sdu); return ret; } -static int tx_list_size(nr_rlc_entity_tm_t *entity, - nr_rlc_sdu_segment_t *l, int maxsize) -{ - int ret = 0; - - while (l != NULL) { - ret += l->size; - l = l->next; - } - - if (ret > maxsize) ret = maxsize; - return ret; -} - nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status( nr_rlc_entity_t *_entity, int maxsize) { @@ -94,7 +84,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status( nr_rlc_entity_buffer_status_t ret; ret.status_size = 0; - ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize); + ret.tx_size = entity->common.bstatus.tx_size; ret.retx_size = 0; return ret; @@ -136,6 +126,9 @@ void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity, sdu = nr_rlc_new_sdu(buffer, size, sdu_id); nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu); + + /* update buffer status */ + entity->common.bstatus.tx_size += sdu->size; } /*************************************************************************/ @@ -165,6 +158,8 @@ static void clear_entity(nr_rlc_entity_tm_t *entity) entity->tx_list = NULL; entity->tx_end = NULL; entity->tx_size = 0; + + entity->common.bstatus.tx_size = 0; } void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c index 4ef952667d..7336e8f9da 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c @@ -28,6 +28,20 @@ #include "LOG/log.h" +/* for a given SDU/SDU segment, computes the corresponding PDU header size */ +static int compute_pdu_header_size(nr_rlc_entity_um_t *entity, + nr_rlc_sdu_segment_t *sdu) +{ + int header_size = 1; + + /* if SN to be included then one more byte if SN field length is 12 */ + if (!(sdu->is_first && sdu->is_last) && entity->sn_field_length == 12) + header_size++; + /* two more bytes for SO if SDU segment is not the first */ + if (!sdu->is_first) header_size += 2; + return header_size; +} + /*************************************************************************/ /* PDU RX functions */ /*************************************************************************/ @@ -148,7 +162,7 @@ static void reassemble_and_deliver(nr_rlc_entity_um_t *entity, int sn) bad_sdu = 1; } if (!bad_sdu && len > 0) { - memcpy(sdu + so, pdu->data, len); + memcpy(sdu + so, pdu->data + so - pdu->so, len); so += len; } free(pdu->data); @@ -375,20 +389,6 @@ static int serialize_sdu(nr_rlc_entity_um_t *entity, return encoder.byte + sdu->size; } -/* for a given SDU/SDU segment, computes the corresponding PDU header size */ -static int compute_pdu_header_size(nr_rlc_entity_um_t *entity, - nr_rlc_sdu_segment_t *sdu) -{ - int header_size = 1; - - /* if SN to be included then one more byte if SN field length is 12 */ - if (!(sdu->is_first && sdu->is_last) && entity->sn_field_length == 12) - header_size++; - /* two more bytes for SO if SDU segment is not the first */ - if (!sdu->is_first) header_size += 2; - return header_size; -} - /* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size' * bytes * - modifies SDU/SDU segment to become an SDU segment @@ -462,8 +462,12 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size) /* assign SN to SDU */ sdu->sdu->sn = entity->tx_next; - /* segment if necessary */ pdu_size = pdu_header_size + sdu->size; + + /* update buffer status */ + entity->common.bstatus.tx_size -= pdu_size; + + /* segment if necessary */ if (pdu_size > size) { nr_rlc_sdu_segment_t *next_sdu; next_sdu = resegment(sdu, entity, size); @@ -474,6 +478,9 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size) entity->tx_list = next_sdu; if (entity->tx_end == NULL) entity->tx_end = entity->tx_list; + /* update buffer status */ + entity->common.bstatus.tx_size += compute_pdu_header_size(entity, next_sdu) + + next_sdu->size; } /* update tx_next if the SDU is an SDU segment and is the last */ @@ -488,24 +495,6 @@ static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size) return ret; } -/* Pretend to serialize all the SDUs in a list and return the size - * of all the PDUs it would produce, limited to 'maxsize'. - * Used for buffer status reporting. - */ -static int tx_list_size(nr_rlc_entity_um_t *entity, - nr_rlc_sdu_segment_t *l, int maxsize) -{ - int ret = 0; - - while (l != NULL) { - ret += compute_pdu_header_size(entity, l) + l->size; - l = l->next; - } - - if (ret > maxsize) ret = maxsize; - return ret; -} - nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status( nr_rlc_entity_t *_entity, int maxsize) { @@ -513,7 +502,7 @@ nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status( nr_rlc_entity_buffer_status_t ret; ret.status_size = 0; - ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize); + ret.tx_size = entity->common.bstatus.tx_size; ret.retx_size = 0; return ret; @@ -555,6 +544,10 @@ void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity, sdu = nr_rlc_new_sdu(buffer, size, sdu_id); nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu); + + /* update buffer status */ + entity->common.bstatus.tx_size += compute_pdu_header_size(entity, sdu) + + sdu->size; } /*************************************************************************/ @@ -650,6 +643,10 @@ void nr_rlc_entity_um_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id) entity->tx_end = NULL; } + /* update buffer status */ + entity->common.bstatus.tx_size -= compute_pdu_header_size(entity, cur) + + cur->size; + nr_rlc_free_sdu_segment(cur); } @@ -682,6 +679,8 @@ static void clear_entity(nr_rlc_entity_um_t *entity) entity->tx_list = NULL; entity->tx_end = NULL; entity->tx_size = 0; + + entity->common.bstatus.tx_size = 0; } void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index bbc4acbd56..046696d12f 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -27,19 +27,112 @@ #include "asn1_utils.h" #include "nr_rlc_ue_manager.h" #include "nr_rlc_entity.h" +#include "nr_rlc_oai_api.h" +#include "NR_RLC-BearerConfig.h" +#include "NR_DRB-ToAddMod.h" +#include "NR_DRB-ToAddModList.h" +#include "NR_SRB-ToAddModList.h" +#include "NR_DRB-ToReleaseList.h" +#include "NR_CellGroupConfig.h" +#include "NR_RLC-Config.h" +#include "common/ran_context.h" +#include "NR_UL-CCCH-Message.h" + +#include "openair2/F1AP/f1ap_du_rrc_message_transfer.h" + +#include "openair2/LAYER2/PROTO_AGENT/proto_agent.h" + +extern RAN_CONTEXT_t RC; #include +#include + static nr_rlc_ue_manager_t *nr_rlc_ue_manager; /* TODO: handle time a bit more properly */ -//#if 0 static uint64_t nr_rlc_current_time; static int nr_rlc_current_time_last_frame; static int nr_rlc_current_time_last_subframe; -//#endif -//#if 0 + +void nr_rlc_bearer_init(NR_RLC_BearerConfig_t *RLC_BearerConfig, NR_RLC_BearerConfig__servedRadioBearer_PR rb_type){ + + RLC_BearerConfig->servedRadioBearer = calloc(1, sizeof(*RLC_BearerConfig->servedRadioBearer)); + RLC_BearerConfig->reestablishRLC = calloc(1, sizeof(*RLC_BearerConfig->reestablishRLC)); + RLC_BearerConfig->rlc_Config = calloc(1, sizeof(*RLC_BearerConfig->rlc_Config)); + RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1, sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); + + *RLC_BearerConfig->reestablishRLC = NR_RLC_BearerConfig__reestablishRLC_true; + if(rb_type == NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity){ + RLC_BearerConfig->logicalChannelIdentity = 4; + RLC_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity; + RLC_BearerConfig->servedRadioBearer->choice.drb_Identity = 1; + } + else{ + RLC_BearerConfig->logicalChannelIdentity = 1; + RLC_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity; + RLC_BearerConfig->servedRadioBearer->choice.srb_Identity = 1; + } + +} + +void nr_rlc_bearer_init_ul_spec(struct NR_LogicalChannelConfig *mac_LogicalChannelConfig){ + + mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*mac_LogicalChannelConfig->ul_SpecificParameters)); + mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; + mac_LogicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + mac_LogicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + mac_LogicalChannelConfig->ul_SpecificParameters->allowedServingCells = NULL; + mac_LogicalChannelConfig->ul_SpecificParameters->allowedSCS_List = NULL; + mac_LogicalChannelConfig->ul_SpecificParameters->maxPUSCH_Duration = NULL; + mac_LogicalChannelConfig->ul_SpecificParameters->configuredGrantType1Allowed = NULL; + + mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup)); + *mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1; + mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = calloc(1,sizeof(*mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID)); + *mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = 0; + mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false; + mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false; + mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL; + +} + +void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr){ + + switch (rlc_config_pr){ + case NR_RLC_Config_PR_um_Bi_Directional: + // RLC UM Bi-directional Bearer configuration + rlc_Config->choice.um_Bi_Directional = calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional)); + rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength)); + *rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength)); + *rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + break; + case NR_RLC_Config_PR_am: + // RLC AM Bearer configuration + rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am)); + rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); + *rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; + rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; + rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64; + rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB500; + rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t32; + rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength)); + *rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; + rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15; + break; + default: + LOG_E (RLC, "Error in %s: RLC config type %d is not handled\n", __FUNCTION__, rlc_config_pr); + break; + } + + rlc_Config->present = rlc_config_pr; + +} + void mac_rlc_data_ind ( const module_id_t module_idP, const rnti_t rntiP, @@ -84,7 +177,7 @@ void mac_rlc_data_ind ( } else { LOG_E(RLC, "%s:%d:%s: fatal: no RB found (channel ID %d)\n", __FILE__, __LINE__, __FUNCTION__, channel_idP); - exit(1); + // exit(1); } nr_rlc_manager_unlock(nr_rlc_ue_manager); @@ -115,7 +208,10 @@ tbs_size_t mac_rlc_data_req( switch (channel_idP) { case 1 ... 3: rb = ue->srb[channel_idP - 1]; break; case 4 ... 8: rb = ue->drb[channel_idP - 4]; break; - default: rb = NULL; break; + default: + rb = NULL; + LOG_E(RLC, "In %s:%d:%s: data request for unknown RB with LCID 0x%02x !\n", __FILE__, __LINE__, __FUNCTION__, channel_idP); + break; } if (rb != NULL) { @@ -123,8 +219,6 @@ tbs_size_t mac_rlc_data_req( maxsize = tb_sizeP; ret = rb->generate_pdu(rb, buffer_pP, maxsize); } else { - LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB, channel_idP: %d\n", __FILE__, __LINE__, __FUNCTION__, channel_idP); - exit(1); ret = 0; } @@ -154,14 +248,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( mac_rlc_status_resp_t ret; nr_rlc_entity_t *rb; - /* TODO: handle time a bit more properly */ - if (nr_rlc_current_time_last_frame != frameP || - nr_rlc_current_time_last_subframe != subframeP) { - nr_rlc_current_time++; - nr_rlc_current_time_last_frame = frameP; - nr_rlc_current_time_last_subframe = subframeP; - } - nr_rlc_manager_lock(nr_rlc_ue_manager); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rntiP); @@ -178,11 +264,14 @@ mac_rlc_status_resp_t mac_rlc_status_ind( * reports '> 81338368' (table 6.1.3.1-2). Passing 100000000 is thus * more than enough. */ - buf_stat = rb->buffer_status(rb, 100000000); + // Fix me: temproary reduction meanwhile cpu cost of this computation is optimized + buf_stat = rb->buffer_status(rb, 1000*1000); ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; } else { + if (!(frameP%128)) //to suppress this warning message + LOG_W(RLC, "[%s] Radio Bearer (channel ID %d) is NULL for UE with rntiP %x\n", __FUNCTION__, channel_idP, rntiP); ret.bytes_in_buffer = 0; } @@ -195,7 +284,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( ret.head_sdu_is_segmented = 0; return ret; } -//#endif rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( const module_id_t module_idP, @@ -239,11 +327,15 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( * reports '> 81338368' (table 6.1.3.1-2). Passing 100000000 is thus * more than enough. */ - buf_stat = rb->buffer_status(rb, 100000000); + // Fixme : Laurent reduced size for CPU saving + // Fix me: temproary reduction meanwhile cpu cost of this computation is optimized + buf_stat = rb->buffer_status(rb, 1000*1000); ret = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; } else { + if (!(frameP%128)) //to suppress this warning message + LOG_W(RLC, "[%s] Radio Bearer (channel ID %d) is NULL for UE with rntiP %x\n", __FUNCTION__, channel_idP, rntiP); ret = 0; } @@ -252,9 +344,7 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( return ret; } -int oai_emulation; -//#if 0 rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const MBMS_flag_t MBMS_flagP, @@ -306,22 +396,27 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, return RLC_OP_STATUS_OK; } -//#endif -//#if 0 int rlc_module_init(int enb_flag) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static int inited = 0; + static int inited_ue = 0; if (pthread_mutex_lock(&lock)) abort(); - if (inited) { - LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + if (enb_flag == 1 && inited) { + LOG_E(RLC, "%s:%d:%s: fatal, inited already 1\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } - inited = 1; + if (enb_flag == 0 && inited_ue) { + LOG_E(RLC, "%s:%d:%s: fatal, inited_ue already 1\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (enb_flag == 1) inited = 1; + if (enb_flag == 0) inited_ue = 1; nr_rlc_ue_manager = new_nr_rlc_ue_manager(enb_flag); @@ -329,13 +424,10 @@ int rlc_module_init(int enb_flag) return 0; } -//#endif -//#if 0 void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP) { } -//#endif static void deliver_sdu(void *_ue, nr_rlc_entity_t *entity, char *buf, int size) { @@ -348,7 +440,7 @@ static void deliver_sdu(void *_ue, nr_rlc_entity_t *entity, char *buf, int size) int is_enb; /* is it SRB? */ - for (i = 0; i < 2; i++) { + for (i = 0; i < sizeofArray(ue->srb); i++) { if (entity == ue->srb[i]) { is_srb = 1; rb_id = i+1; @@ -357,7 +449,7 @@ static void deliver_sdu(void *_ue, nr_rlc_entity_t *entity, char *buf, int size) } /* maybe DRB? */ - for (i = 0; i < 5; i++) { + for (i = 0; i < sizeofArray(ue->drb) ; i++) { if (entity == ue->drb[i]) { is_srb = 0; rb_id = i+1; @@ -370,7 +462,7 @@ static void deliver_sdu(void *_ue, nr_rlc_entity_t *entity, char *buf, int size) exit(1); rb_found: - LOG_D(RLC, "%s:%d:%s: delivering SDU (rnti %d is_srb %d rb_id %d) size %d", + LOG_D(RLC, "%s:%d:%s: delivering SDU (rnti %d is_srb %d rb_id %d) size %d\n", __FILE__, __LINE__, __FUNCTION__, ue->rnti, is_srb, rb_id, size); memblock = get_free_mem_block(size, __func__); @@ -399,6 +491,27 @@ rb_found: T(T_ENB_RLC_UL, T_INT(0 /*ctxt_pP->module_id*/), T_INT(ue->rnti), T_INT(rb_id), T_INT(size)); + + const ngran_node_t type = RC.nrrrc[0 /*ctxt_pP->module_id*/]->node_type; + AssertFatal(type != ngran_eNB_CU && type != ngran_ng_eNB_CU && type != ngran_gNB_CU, + "Can't be CU, bad node type %d\n", type); + + // if (NODE_IS_DU(type) && is_srb == 0) { + // LOG_D(RLC, "call proto_agent_send_pdcp_data_ind() \n"); + // proto_agent_send_pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock); + // return; + // } + + if (NODE_IS_DU(type) && is_srb == 1) { + MessageDef *msg; + msg = itti_alloc_new_message(TASK_RLC_ENB, 0, F1AP_UL_RRC_MESSAGE); + F1AP_UL_RRC_MESSAGE(msg).rnti = ue->rnti; + F1AP_UL_RRC_MESSAGE(msg).srb_id = rb_id; + F1AP_UL_RRC_MESSAGE(msg).rrc_container = (unsigned char *)buf; + F1AP_UL_RRC_MESSAGE(msg).rrc_container_length = size; + itti_send_msg_to_task(TASK_DU_F1, ENB_MODULE_ID_TO_INSTANCE(0 /*ctxt_pP->module_id*/), msg); + return; + } } if (!pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock)) { @@ -499,7 +612,7 @@ static void max_retx_reached(void *_ue, nr_rlc_entity_t *entity) exit(1); rb_found: - LOG_D(RLC, "max RETX reached on %s %d\n", + LOG_E(RLC, "max RETX reached on %s %d\n", is_srb ? "SRB" : "DRB", rb_id); @@ -522,17 +635,17 @@ rb_found: #endif } -__attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s) +static void add_rlc_srb(int rnti, struct NR_SRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig) { nr_rlc_entity_t *nr_rlc_am; nr_rlc_ue_t *ue; - struct LTE_SRB_ToAddMod__rlc_Config *r = s->rlc_Config; - struct LTE_SRB_ToAddMod__logicalChannelConfig *l = s->logicalChannelConfig; + struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; int srb_id = s->srb_Identity; + int channel_id = rlc_BearerConfig->logicalChannelIdentity; int logical_channel_group; - //int t_reordering; int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -541,25 +654,21 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * int t_reassembly; int sn_field_length; + LOG_D(RLC,"Trying to add SRB %d\n",srb_id); if (srb_id != 1 && srb_id != 2) { LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n", - __FILE__, __LINE__, __FUNCTION__, srb_id); + __FILE__, __LINE__, __FUNCTION__, srb_id); exit(1); } - switch (l->present) { - case LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue: - logical_channel_group = *l->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup; - break; - case LTE_SRB_ToAddMod__logicalChannelConfig_PR_defaultValue: - /* default value from 36.331 9.2.1 */ - logical_channel_group = 0; - break; - default: - LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + if (channel_id != srb_id) { + LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n", + __FILE__, __LINE__, __FUNCTION__); exit(1); } + logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup; + /* TODO: accept other values? */ if (logical_channel_group != 0) { LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); @@ -567,31 +676,22 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * } switch (r->present) { - case LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue: { - struct LTE_RLC_Config__am *am; - if (r->choice.explicitValue.present != LTE_RLC_Config_PR_am) { - LOG_E(RLC, "%s:%d:%s: fatal error, must be RLC AM\n", - __FILE__, __LINE__, __FUNCTION__); - exit(1); - } - am = &r->choice.explicitValue.choice.am; - //t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); + case NR_RLC_Config_PR_am: { + struct NR_RLC_Config__am *am; + am = r->choice.am; + t_reassembly = decode_t_reassembly(am->dl_AM_RLC.t_Reassembly); t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte); max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold); + if (*am->dl_AM_RLC.sn_FieldLength != *am->ul_AM_RLC.sn_FieldLength) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + sn_field_length = decode_sn_field_length_am(*am->dl_AM_RLC.sn_FieldLength); break; } - case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue: - /* default values from 36.331 9.2.1 */ - //t_reordering = 35; - t_status_prohibit = 0; - t_poll_retransmit = 45; - poll_pdu = -1; - poll_byte = -1; - max_retx_threshold = 4; - break; default: LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); exit(1); @@ -600,8 +700,7 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * nr_rlc_manager_lock(nr_rlc_ue_manager); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); if (ue->srb[srb_id-1] != NULL) { - LOG_D(RLC, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n", - __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + LOG_W(RLC, "%s:%d:%s: SRB %d already exists for UE with RNTI 0x%x, do nothing\n", __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); } else { /* hack: hardcode values for NR */ t_poll_retransmit = 45; @@ -611,8 +710,8 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * poll_byte = -1; max_retx_threshold = 8; sn_field_length = 12; - nr_rlc_am = new_nr_rlc_entity_am(100000, - 100000, + nr_rlc_am = new_nr_rlc_entity_am(10000000, + 10000000, deliver_sdu, ue, successful_delivery, ue, max_retx_reached, ue, @@ -622,24 +721,22 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * sn_field_length); nr_rlc_ue_add_srb_rlc_entity(ue, srb_id, nr_rlc_am); - LOG_D(RLC, "%s:%d:%s: added srb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added srb %d to UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); } nr_rlc_manager_unlock(nr_rlc_ue_manager); } -static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig) { nr_rlc_entity_t *nr_rlc_am; nr_rlc_ue_t *ue; - struct LTE_RLC_Config *r = s->rlc_Config; - struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; int drb_id = s->drb_Identity; - int channel_id = *s->logicalChannelIdentity; + int channel_id = rlc_BearerConfig->logicalChannelIdentity; int logical_channel_group; - //int t_reordering; int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -665,19 +762,24 @@ static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) /* TODO: accept other values? */ if (logical_channel_group != 1) { LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); - exit(1); + //exit(1); } switch (r->present) { - case LTE_RLC_Config_PR_am: { - struct LTE_RLC_Config__am *am; - am = &r->choice.am; - //t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); + case NR_RLC_Config_PR_am: { + struct NR_RLC_Config__am *am; + am = r->choice.am; + t_reassembly = decode_t_reassembly(am->dl_AM_RLC.t_Reassembly); t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte); max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold); + if (*am->dl_AM_RLC.sn_FieldLength != *am->ul_AM_RLC.sn_FieldLength) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + sn_field_length = decode_sn_field_length_am(*am->dl_AM_RLC.sn_FieldLength); break; } default: @@ -688,19 +790,10 @@ static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) nr_rlc_manager_lock(nr_rlc_ue_manager); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); if (ue->drb[drb_id-1] != NULL) { - LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_W(RLC, "%s:%d:%s: DRB %d already exists for UE with RNTI %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - /* hack: hardcode values for NR */ - t_poll_retransmit = 45; - t_reassembly = 35; - t_status_prohibit = 0; - poll_pdu = -1; - poll_byte = -1; - max_retx_threshold = 8; - sn_field_length = 12; - nr_rlc_am = new_nr_rlc_entity_am(100000, - 100000, + nr_rlc_am = new_nr_rlc_entity_am(10000000, + 10000000, deliver_sdu, ue, successful_delivery, ue, max_retx_reached, ue, @@ -710,24 +803,22 @@ static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) sn_field_length); nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_am); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added drb %d to UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } nr_rlc_manager_unlock(nr_rlc_ue_manager); } -static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb_um(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig) { nr_rlc_entity_t *nr_rlc_um; nr_rlc_ue_t *ue; - struct LTE_RLC_Config *r = s->rlc_Config; - struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; int drb_id = s->drb_Identity; - int channel_id = *s->logicalChannelIdentity; + int channel_id = rlc_BearerConfig->logicalChannelIdentity; int logical_channel_group; - //int t_reordering; int sn_field_length; int t_reassembly; @@ -752,15 +843,15 @@ static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) } switch (r->present) { - case LTE_RLC_Config_PR_um_Bi_Directional: { - struct LTE_RLC_Config__um_Bi_Directional *um; - um = &r->choice.um_Bi_Directional; - //t_reordering = decode_t_reordering(um->dl_UM_RLC.t_Reordering); - if (um->dl_UM_RLC.sn_FieldLength != um->ul_UM_RLC.sn_FieldLength) { + case NR_RLC_Config_PR_um_Bi_Directional: { + struct NR_RLC_Config__um_Bi_Directional *um; + um = r->choice.um_Bi_Directional; + t_reassembly = decode_t_reassembly(um->dl_UM_RLC.t_Reassembly); + if (*um->dl_UM_RLC.sn_FieldLength != *um->ul_UM_RLC.sn_FieldLength) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } - sn_field_length = decode_sn_field_length(um->dl_UM_RLC.sn_FieldLength); + sn_field_length = decode_sn_field_length_um(*um->dl_UM_RLC.sn_FieldLength); break; } default: @@ -771,42 +862,38 @@ static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) nr_rlc_manager_lock(nr_rlc_ue_manager); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); if (ue->drb[drb_id-1] != NULL) { - LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_W(RLC, "DEBUG add_drb_um %s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - /* hack: hardcode values for NR */ - t_reassembly = 35; - sn_field_length = 6; - nr_rlc_um = new_nr_rlc_entity_um(1000000, - 1000000, + nr_rlc_um = new_nr_rlc_entity_um(100000000, + 100000000, deliver_sdu, ue, t_reassembly, sn_field_length); nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_um); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added drb %d to UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } nr_rlc_manager_unlock(nr_rlc_ue_manager); } -__attribute__ ((unused)) static void add_drb(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, struct NR_RLC_BearerConfig *rlc_BearerConfig) { - switch (s->rlc_Config->present) { - case LTE_RLC_Config_PR_am: - add_drb_am(rnti, s); + switch (rlc_BearerConfig->rlc_Config->present) { + case NR_RLC_Config_PR_am: + add_drb_am(rnti, s, rlc_BearerConfig); break; - case LTE_RLC_Config_PR_um_Bi_Directional: - add_drb_um(rnti, s); + case NR_RLC_Config_PR_um_Bi_Directional: + add_drb_um(rnti, s, rlc_BearerConfig); break; default: LOG_E(RLC, "%s:%d:%s: fatal: unhandled DRB type\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } + LOG_I(RLC, "%s:%s:%d: added DRB to UE with RNTI 0x%x\n", __FILE__, __FUNCTION__, __LINE__, rnti); } -//#if 0 +/* Dummy function due to dependency from LTE libraries */ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, const LTE_SRB_ToAddModList_t * const srb2add_listP, const LTE_DRB_ToAddModList_t * const drb2add_listP, @@ -814,14 +901,25 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, const uint32_t sourceL2Id, const uint32_t destinationL2Id) +{ + return 0; +} + +rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) { int rnti = ctxt_pP->rnti; int i; + int j; if (/*ctxt_pP->enb_flag != 1 ||*/ ctxt_pP->module_id != 0 /*|| ctxt_pP->instance != 0 || ctxt_pP->eNB_index != 0 || ctxt_pP->configured != 1 || ctxt_pP->brOption != 0 */) { - LOG_E(RLC, "%s: ctxt_pP not handled (%d %d %d %d %d %d)\n", __FUNCTION__, + LOG_E(RLC, "%s: ctxt_pP not handled (%d %d %ld %d %d %d)\n", __FUNCTION__, ctxt_pP->enb_flag , ctxt_pP->module_id, ctxt_pP->instance, ctxt_pP->eNB_index, ctxt_pP->configured, ctxt_pP->brOption); exit(1); @@ -834,26 +932,45 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP if (drb2release_listP != NULL) { LOG_E(RLC, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); - exit(1); + //exit(1); } if (srb2add_listP != NULL) { for (i = 0; i < srb2add_listP->list.count; i++) { - add_srb(rnti, srb2add_listP->list.array[i]); + if (rlc_bearer2add_list != NULL) { + for(j = 0; j < rlc_bearer2add_list->list.count; j++){ + if(rlc_bearer2add_list->list.array[j]->servedRadioBearer != NULL){ + if(rlc_bearer2add_list->list.array[j]->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity){ + if(srb2add_listP->list.array[i]->srb_Identity == rlc_bearer2add_list->list.array[j]->servedRadioBearer->choice.srb_Identity){ + add_rlc_srb(rnti, srb2add_listP->list.array[i], rlc_bearer2add_list->list.array[j]); + } + } + } + } + } + } } - if (drb2add_listP != NULL) { + if ((drb2add_listP != NULL) && (rlc_bearer2add_list != NULL)) { for (i = 0; i < drb2add_listP->list.count; i++) { - add_drb(rnti, drb2add_listP->list.array[i]); + if (rlc_bearer2add_list != NULL) { + for(j = 0; j < rlc_bearer2add_list->list.count; j++){ + if(rlc_bearer2add_list->list.array[j]->servedRadioBearer != NULL){ + if(rlc_bearer2add_list->list.array[j]->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity){ + if(drb2add_listP->list.array[i]->drb_Identity == rlc_bearer2add_list->list.array[j]->servedRadioBearer->choice.drb_Identity){ + add_drb(rnti, drb2add_listP->list.array[i], rlc_bearer2add_list->list.array[j]); + } + } + } + } + } } } return RLC_OP_STATUS_OK; } -//#endif -//#if 0 rlc_op_status_t rrc_rlc_config_req ( const protocol_ctxt_t* const ctxt_pP, const srb_flag_t srb_flagP, @@ -883,7 +1000,7 @@ rlc_op_status_t rrc_rlc_config_req ( exit(1); } nr_rlc_manager_lock(nr_rlc_ue_manager); - LOG_D(RLC, "%s:%d:%s: remove rb %ld (is_srb %d) for UE %d\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti); + LOG_D(RLC, "%s:%d:%s: remove rb %ld (is_srb %d) for UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ctxt_pP->rnti); if (srb_flagP) { if (ue->srb[rb_idP-1] != NULL) { @@ -912,16 +1029,12 @@ rlc_op_status_t rrc_rlc_config_req ( nr_rlc_manager_unlock(nr_rlc_ue_manager); return RLC_OP_STATUS_OK; } -//#endif -//#if 0 void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP) { /* nothing to do */ } -//#endif -//#if 0 rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) { LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, x->rnti); @@ -931,4 +1044,23 @@ rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) return RLC_OP_STATUS_OK; } -//#endif + +void nr_rlc_tick(int frame, int subframe) +{ + if (frame != nr_rlc_current_time_last_frame || + subframe != nr_rlc_current_time_last_subframe) { + nr_rlc_current_time_last_frame = frame; + nr_rlc_current_time_last_subframe = subframe; + nr_rlc_current_time++; + } +} + +/* This is a hack, to compile the gNB. + * TODO: remove it. The solution is to cleanup cmake_targets/CMakeLists.txt + */ +void rlc_tick(int a, int b) +{ + LOG_E(RLC, "%s:%d:%s: this code should not be reached\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); +} diff --git a/common/utils/itti_analyzer/libbuffers/socket.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h similarity index 56% rename from common/utils/itti_analyzer/libbuffers/socket.h rename to openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index 8c2be2243e..6b3c228163 100644 --- a/common/utils/itti_analyzer/libbuffers/socket.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -19,34 +19,31 @@ * contact@openairinterface.org */ -#include -#include +/*! \file nr_rlc_oai_api.h + * \brief Header file for nr_rlc_oai_api + * \author Guido Casati + * \date 2020 + * \email: guido.casati@iis.fraunhofe.de + * \version 1.0 + * @ingroup _rlc -#ifndef SOCKET_H_ -#define SOCKET_H_ + */ -typedef struct { - pthread_t thread; - int sd; - char *ip_address; - uint16_t port; +#include "NR_RLC-BearerConfig.h" +#include "NR_RLC-Config.h" +#include "NR_LogicalChannelIdentity.h" +#include "NR_RadioBearerConfig.h" +#include "NR_CellGroupConfig.h" +#include "openair2/RRC/NR/nr_rrc_proto.h" - /* The pipe used between main thread (running GTK) and the socket thread */ - int pipe_fd; +/* from OAI */ +#include "pdcp.h" - /* Time used to avoid refreshing UI every time a new signal is incoming */ - gint64 last_data_notification; - uint8_t nb_signals_since_last_update; +struct NR_RLC_Config; +struct NR_LogicalChannelConfig; - /* The last signals received which are not yet been updated in GUI */ - GList *signal_list; -} socket_data_t; +void nr_rlc_bearer_init(NR_RLC_BearerConfig_t *RLC_BearerConfig, NR_RLC_BearerConfig__servedRadioBearer_PR rb_type); -gboolean socket_abort_connection; +void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr); -int socket_connect_to_remote_host(const char *remote_ip, const uint16_t port, - int pipe_fd); - -int socket_disconnect_from_remote_host(void); - -#endif /* SOCKET_H_ */ +void nr_rlc_bearer_init_ul_spec(struct NR_LogicalChannelConfig *mac_LogicalChannelConfig); \ No newline at end of file diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c index 09f1e4f599..dc2baa1839 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c @@ -85,7 +85,7 @@ nr_rlc_ue_t *nr_rlc_manager_get_ue(nr_rlc_ue_manager_t *_m, int rnti) if (m->ue_list[i]->rnti == rnti) return m->ue_list[i]; - LOG_D(RLC, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti); + LOG_D(RLC, "%s:%d:%s: new UE with RNTI 0x%x\n", __FILE__, __LINE__, __FUNCTION__, rnti); m->ue_count++; m->ue_list = realloc(m->ue_list, sizeof(nr_rlc_ue_t *) * m->ue_count); @@ -117,7 +117,7 @@ void nr_rlc_manager_remove_ue(nr_rlc_ue_manager_t *_m, int rnti) break; if (i == m->ue_count) { - LOG_D(RLC, "%s:%d:%s: warning: ue %d not found\n", + LOG_W(RLC, "%s:%d:%s: warning: ue %d not found\n", __FILE__, __LINE__, __FUNCTION__, rnti); return; diff --git a/openair2/LAYER2/nr_rlc/tests/LOG/log.h b/openair2/LAYER2/nr_rlc/tests/LOG/log.h index 5c9fcd643c..8ebc7e1909 100644 --- a/openair2/LAYER2/nr_rlc/tests/LOG/log.h +++ b/openair2/LAYER2/nr_rlc/tests/LOG/log.h @@ -1,5 +1,5 @@ -#ifndef _LOG_H_ -#define _LOG_H_ +#ifndef _NR_RLC_TESTS_LOG_H_ +#define _NR_RLC_TESTS_LOG_H_ #include @@ -7,4 +7,4 @@ #define LOG_D(x, ...) printf(__VA_ARGS__) #define LOG_W(x, ...) printf(__VA_ARGS__) -#endif /* _LOG_H_ */ +#endif /* _NR_RLC_TESTS_LOG_H_ */ diff --git a/openair2/LAYER2/nr_rlc/tests/run_tests.sh b/openair2/LAYER2/nr_rlc/tests/run_tests.sh index ac22516064..7ca4798861 100755 --- a/openair2/LAYER2/nr_rlc/tests/run_tests.sh +++ b/openair2/LAYER2/nr_rlc/tests/run_tests.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_count=13 +test_count=17 for i in `seq $test_count` do diff --git a/openair2/LAYER2/nr_rlc/tests/test.c b/openair2/LAYER2/nr_rlc/tests/test.c index 742e79ca2c..bfde8b9fad 100644 --- a/openair2/LAYER2/nr_rlc/tests/test.c +++ b/openair2/LAYER2/nr_rlc/tests/test.c @@ -22,13 +22,13 @@ * create the UE RLC AM entity with given parameters * * GNB_UM - * create the eNB RLC UM entity with given parameters + * create the gNB RLC UM entity with given parameters * * UE_UM * create the UE RLC UM entity with given parameters * * GNB_TM - * create the eNB RLC TM entity with given parameters + * create the gNB RLC TM entity with given parameters * * UE_UM * create the UE RLC TM entity with given parameters @@ -39,7 +39,7 @@ * You must end your test definition with a line 'TIME, -1'. * * GNB_SDU - * send an SDU to eNB with id and size + * send an SDU to gNB with id and size * the SDU is [00 01 ... ff 01 ...] * (ie. start byte is 00 then we increment for each byte, loop if needed) * @@ -47,10 +47,10 @@ * same as GNB_SDU but the SDU is sent to the UE * * GNB_PDU <'size' bytes> - * send a custom PDU from eNB to UE (eNB does not see this PDU at all) + * send a custom PDU from gNB to UE (gNB does not see this PDU at all) * * UE_PDU <'size' bytes> - * send a custom PDU from UE to eNB (UE does not see this PDU at all) + * send a custom PDU from UE to gNB (UE does not see this PDU at all) * * GNB_PDU_SIZE * set 'gnb_pdu_size' @@ -70,7 +70,7 @@ * that the test must fail (ie. exit with non zero, crash not allowed) * * GNB_BUFFER_STATUS - * call buffer_status for eNB and print result + * call buffer_status for gNB and print result * * UE_BUFFER_STATUS * call buffer_status for UE and print result @@ -82,7 +82,7 @@ * discards given SDU * * RE_ESTABLISH - * re-establish both eNB and UE + * re-establish both gNB and UE */ enum action { @@ -368,7 +368,7 @@ int test_main(void) pos += 2; break; case RE_ESTABLISH: - printf("TEST: %d: re-establish eNB and UE\n", i); + printf("TEST: %d: re-establish gNB and UE\n", i); gnb->reestablishment(gnb); ue->reestablishment(ue); pos++; diff --git a/openair2/LAYER2/nr_rlc/tests/test14.h b/openair2/LAYER2/nr_rlc/tests/test14.h new file mode 100644 index 0000000000..9eb472b270 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/test14.h @@ -0,0 +1,46 @@ +/* + * am test (SN field size 18): + * test status reporting with missing packet + * at time 1, UE receives an SDU of 50 bytes + * at time 2, UE receives an SDU of 50 bytes + * at time 3, UE receives an SDU of 50 bytes + * at time 4, UE receives an SDU of 50 bytes + * transmission fails for first SDU, okay for the others + * then some time with transmission failing + * then at time 49, UE receives an SDU, transmission okay + * then at time 50, transmission failing again (we had a bug triggered by this) + * finally at time 55, transmission okay again to clear buffers + */ + +TIME, 1, + GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + GNB_RECV_FAILS, 1, + GNB_PDU_SIZE, 80, + UE_PDU_SIZE, 80, + UE_SDU, 0, 50, +TIME, 2, + GNB_RECV_FAILS, 0, + UE_SDU, 1, 50, +TIME, 3, + GNB_BUFFER_STATUS, + UE_SDU, 2, 50, +TIME, 4, + GNB_BUFFER_STATUS, + UE_SDU, 3, 50, +TIME, 5, + GNB_BUFFER_STATUS, + GNB_RECV_FAILS, 1, +TIME, 6, + GNB_BUFFER_STATUS, + UE_BUFFER_STATUS, +TIME, 49, + GNB_RECV_FAILS, 0, + UE_SDU, 4, 50, +TIME, 50, + GNB_RECV_FAILS, 1, + GNB_BUFFER_STATUS, + UE_BUFFER_STATUS, +TIME, 55, + GNB_RECV_FAILS, 0, +TIME, -1 diff --git a/openair2/LAYER2/nr_rlc/tests/test14.txt.gz b/openair2/LAYER2/nr_rlc/tests/test14.txt.gz new file mode 100644 index 0000000000..53616dae3d Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test14.txt.gz differ diff --git a/openair2/LAYER2/nr_rlc/tests/test15.h b/openair2/LAYER2/nr_rlc/tests/test15.h new file mode 100644 index 0000000000..8ce9f97896 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/test15.h @@ -0,0 +1,19 @@ +/* + * am test (SN field size 18): + * test "range" in NACK, generate a case where so_start > so_end + * (so so_start and so_end are not from the same PDU) + */ + +TIME, 1, + GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + GNB_PDU_SIZE, 40, + UE_PDU_SIZE, 80, + GNB_SDU, 0, 50, + GNB_SDU, 1, 50, + GNB_SDU, 2, 50, +TIME, 2, + UE_RECV_FAILS, 1, +TIME, 4, + UE_RECV_FAILS, 0, +TIME, -1 diff --git a/openair2/LAYER2/nr_rlc/tests/test15.txt.gz b/openair2/LAYER2/nr_rlc/tests/test15.txt.gz new file mode 100644 index 0000000000..2619436c2d Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test15.txt.gz differ diff --git a/openair2/LAYER2/nr_rlc/tests/test16.h b/openair2/LAYER2/nr_rlc/tests/test16.h new file mode 100644 index 0000000000..92f9923809 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/test16.h @@ -0,0 +1,19 @@ +/* + * am test (SN field size 18): + * there was a bug when we receive a full PDU after receiving only the + * beginning of it; the data was copied at the end but from the start of the + * full PDU instead of the correct offset. This test captures this case. + * Gnb sends the start of a PDU then the full PDU. That is the SDU is + * [00 .. 09]. First gnb sends [00 .. 08] then it sends [00 .. 09]. + */ + +TIME, 1, + GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + GNB_PDU_SIZE, 12, + UE_PDU_SIZE, 20, + GNB_PDU, 12, 0x90, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +TIME, 2, + GNB_PDU_SIZE, 20, + GNB_PDU, 13, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, +TIME, -1 diff --git a/openair2/LAYER2/nr_rlc/tests/test16.txt.gz b/openair2/LAYER2/nr_rlc/tests/test16.txt.gz new file mode 100644 index 0000000000..74b19724aa Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test16.txt.gz differ diff --git a/openair2/LAYER2/nr_rlc/tests/test17.h b/openair2/LAYER2/nr_rlc/tests/test17.h new file mode 100644 index 0000000000..3da9fcc6e5 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/test17.h @@ -0,0 +1,18 @@ +/* + * um test (SN field size 12): + * same problem as for test16, but we test by sending [00 .. 08] then + * [02 .. 09] (they overlap, the full SDU is [00 .. 09]), which probably + * never occurs in practice but triggers the bug. Doing as for test16 does + * not trigger the bug. + */ + +TIME, 1, + GNB_UM, 100000, 100000, 35, 12, + UE_UM, 100000, 100000, 35, 12, + GNB_PDU_SIZE, 8, + UE_PDU_SIZE, 20, + GNB_PDU, 11, 0x40, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +TIME, 2, + GNB_PDU_SIZE, 20, + GNB_PDU, 12, 0x80, 0x00, 0x00, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, +TIME, -1 diff --git a/openair2/LAYER2/nr_rlc/tests/test17.txt.gz b/openair2/LAYER2/nr_rlc/tests/test17.txt.gz new file mode 100644 index 0000000000..b30f671617 Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test17.txt.gz differ diff --git a/openair2/LAYER2/nr_rlc/tests/test8.txt.gz b/openair2/LAYER2/nr_rlc/tests/test8.txt.gz index d69e43acdc..c20d43c63b 100644 Binary files a/openair2/LAYER2/nr_rlc/tests/test8.txt.gz and b/openair2/LAYER2/nr_rlc/tests/test8.txt.gz differ diff --git a/openair2/LAYER2/nr_rlc/tests/test9.txt.gz b/openair2/LAYER2/nr_rlc/tests/test9.txt.gz index 6def9c20f8..27590b7d71 100644 Binary files a/openair2/LAYER2/nr_rlc/tests/test9.txt.gz and b/openair2/LAYER2/nr_rlc/tests/test9.txt.gz differ diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c index bbdc55e036..7ffdc75195 100644 --- a/openair2/LAYER2/openair2_proc.c +++ b/openair2/LAYER2/openair2_proc.c @@ -362,264 +362,5 @@ int dump_eNB_l2_stats(char *buffer, int length) { return len + 1 /* SR: for trailing \0 */; } -#ifdef PROC -int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length) { - int len = 0,fg,Overhead, Sign; - unsigned int i,j,k,kk; - unsigned int Mod_id = 0,CH_index; - unsigned int tx_pdcp_sdu; - unsigned int tx_pdcp_sdu_discarded; - unsigned int tx_retransmit_pdu_unblock; - unsigned int tx_retransmit_pdu_by_status; - unsigned int tx_retransmit_pdu; - unsigned int tx_data_pdu; - unsigned int tx_control_pdu; - unsigned int rx_sdu; - unsigned int rx_error_pdu; - unsigned int rx_data_pdu; - unsigned int rx_data_pdu_out_of_window; - unsigned int rx_control_pdu; - // if (mac_xface->is_cluster_head == 0) { - for (k=0; kIs_cluster_head[k] == 0) { -#ifndef PHY_EMUL_ONE_MACHINE - Mod_id=k-NB_CH_INST; - len+=sprintf(&buffer[len],"UE TTI: %d\n",Mac_rlc_xface->frame); - - for (CH_index = 0; CH_index>5, - UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_RX, - UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_RX_ERRORS); - - for(i=1; i>5, - Pdcp_stats_rx[k][CH_index][i], - Pdcp_stats_rx_rate[k][CH_index][i], - (10*Pdcp_stats_rx_rate[k][CH_index][i])>>5, - Sign*(10*Overhead)>>5); - int status = rlc_stat_req (k, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - &tx_pdcp_sdu, - &tx_pdcp_sdu_discarded, - &tx_retransmit_pdu_unblock, - &tx_retransmit_pdu_by_status, - &tx_retransmit_pdu, - &tx_data_pdu, - &tx_control_pdu, - &rx_sdu, - &rx_error_pdu, - &rx_data_pdu, - &rx_data_pdu_out_of_window, - &rx_control_pdu) ; - - if (status == RLC_OP_STATUS_OK) { - len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_SDU_TO_TX = %u\tNB_SDU_DISC %u\tNB_RX_SDU %u\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - tx_pdcp_sdu, - tx_pdcp_sdu_discarded, - rx_sdu); - len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_TB_TX_DATA = %u\tNB_TB_TX_CONTROL %u\tNB_TX_TB_RETRANS %u", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - tx_data_pdu, - tx_control_pdu, - tx_retransmit_pdu); - len+=sprintf(&buffer[len],"\tRLC LCHAN %d, NB_TX_TB_RETRANS_BY_STATUS = %u\tNB_TX_TB_RETRANS_PADD %u\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - tx_retransmit_pdu_by_status, - tx_retransmit_pdu_unblock); - len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_RX_DATA = %u\tNB_RX_TB_OUT_WIN %u\tNB_RX_TB_CORRUPT %u\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - rx_data_pdu, - rx_data_pdu_out_of_window, - rx_error_pdu); - } - - len+=sprintf(&buffer[len],"[MAC]: LCHAN %d, NB_TX_MAC = %d (%d bits/TTI, %d kbits/s), NB_RX_MAC = %d (%d errors)\n", - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_TX, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate, - (10*UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate)>>5, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX, - UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_ERRORS); - len+=sprintf(&buffer[len]," TX per TB: "); - - for(kk=0; kkIs_cluster_head[k] ==1) { - Mod_id=k; - len+=sprintf(&buffer[len], - "-------------------------------------------------------------------CH %d: TTI: %d------------------------------------------------------------------\n", - NODE_ID[Mod_id],Mac_rlc_xface->frame); - - for(i=1; i<=NB_CNX_CH; i++) { - if (CH_mac_inst[Mod_id].Dcch_lchan[i].Active==1) { - len+=sprintf(&buffer[len],"\nMR index %u: DL SINR (feedback) %d dB, CQI: %s\n\n", - i,//CH_rrc_inst[Mod_id].Info.UE_info[i].L2_id[0], - CH_mac_inst[Mod_id].Def_meas[i].Wideband_sinr, - print_cqi(CH_mac_inst[Mod_id].Def_meas[i].cqi)); - len+=sprintf(&buffer[len], - "[MAC] LCHAN %d (DCCH), NB_TX_MAC= %d (%d bits/TTI, %d kbits/s), NB_RX_MAC= %d (errors %d, sacch errors %d, sach errors %d, sach_missing %d)\n\n", - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.Lchan_id.Index, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_TX, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.output_rate, - (10*CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.output_rate)>>5, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_ERRORS, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACCH_ERRORS, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACH_ERRORS, - CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACH_MISSING); - - for(j=0; j>5, - Pdcp_stats_rx[k][i][j], - Pdcp_stats_rx_rate[k][i][j], - (10*Pdcp_stats_rx_rate[k][i][j])>>5, - Sign*(10*Overhead)>>5); - int status = rlc_stat_req (k, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - &tx_pdcp_sdu, - &tx_pdcp_sdu_discarded, - &tx_retransmit_pdu_unblock, - &tx_retransmit_pdu_by_status, - &tx_retransmit_pdu, - &tx_data_pdu, - &tx_control_pdu, - &rx_sdu, - &rx_error_pdu, - &rx_data_pdu, - &rx_data_pdu_out_of_window, - &rx_control_pdu) ; - /* - if (status == RLC_OP_STATUS_OK) { - len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_SDU_TO_TX = %d\tNB_SDU_DISC %d\tNB_RX_SDU %d\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - tx_pdcp_sdu, - tx_pdcp_sdu_discarded, - rx_sdu); - len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_TB_TX_DATA = %d\tNB_TB_TX_CONTROL %d\tNB_TX_TB_RETRANS %\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - tx_data_pdu, - tx_control_pdu, - tx_retransmit_pdu); - len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_TX_TB_RETRANS_BY_STATUS = %d\tNB_TX_TB_RETRANS_PADD %d\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - tx_retransmit_pdu_by_status, - tx_retransmit_pdu_unblock); - len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_RX_DATA = %d\tNB_RX_TB_OUT_WIN %d\tNB_RX_TB_CORRUPT %d\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - rx_data_pdu, - rx_data_pdu_out_of_window, - rx_error_pdu); - } - */ - len+=sprintf(&buffer[len], - "[MAC]LCHAN %d (CNX %u,RAB %u), NB_TX_MAC= %d (%d bits/TTI, %d kbit/s), NB_RX_MAC= %d (errors %d, sacch_errors %d, sach_errors %d, sach_missing %d)\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index, - i,j, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_TX, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate, - (10*CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate)>>5, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_ERRORS, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACCH_ERRORS, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACH_ERRORS, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACH_MISSING); - len+=sprintf(&buffer[len],"[MAC][SCHEDULER] TX Arrival Rate %d, TX Service Rate %d, RX Arrival rate %d, RX Service rate %d, NB_BW_REQ_RX %d\n\n", - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Arrival_rate, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Tx_rate, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Req_rate, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Rx_rate, - CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_BW_REQ_RX); - /* - len+=sprintf(&buffer[len]," TX per TB: "); - for(kk=0;kkrx_list; + int last_byte; + int new_last_byte; + int count; + + while (l != NULL) { + if (l->sn == sn) + break; + l = l->next; + } + /* nothing received, everything is missing, return 0 */ + if (l == NULL) + return 0; + + last_byte = -1; + count = 0; + while (l != NULL && l->sn == sn) { + if (l->so > last_byte + 1) + /* missing part detected */ + count++; + if (l->is_last) + /* end of PDU reached - no more missing part to add */ + return count; + new_last_byte = l->so + l->size - l->data_offset - 1; + if (new_last_byte > last_byte) + last_byte = new_last_byte; + l = l->next; + } + /* at this point: end of PDU not received, one more missing part */ + count++; + + return count; +} + +/* return size of nack reporting for sn, in bits */ +static int segment_nack_size(rlc_entity_am_t *entity, int sn) +{ + /* nack + e1 + e2 = 12 bits + * SOstart + SOend = 30 bits + */ + int count; + + count = count_nack_missing_parts(entity, sn); + + /* count_nack_missing_parts returns 0 when everything is missing + * in which case we don't have SOstart/SOend, so only 12 bits + */ + if (count == 0) + return 12; + + return count * (12 + 30); +} + static int status_size(rlc_entity_am_t *entity, int maxsize) { /* let's count bits */ @@ -912,11 +970,16 @@ static int status_size(rlc_entity_am_t *entity, int maxsize) return 0; } - /* each NACK adds 12 bits */ + /* add size of NACKs */ sn = entity->vr_r; - while (bits + 12 <= maxsize && sn_compare_rx(entity, sn, entity->vr_ms) < 0) { - if (!(rlc_am_segment_full(entity, sn))) - bits += 12; + while (sn_compare_rx(entity, sn, entity->vr_ms) < 0) { + if (!(rlc_am_segment_full(entity, sn))) { + int nack_size = segment_nack_size(entity, sn); + /* stop there if not enough room */ + if (bits + nack_size > maxsize) + break; + bits += nack_size; + } sn = (sn + 1) % 1024; } @@ -929,7 +992,8 @@ static int generate_status(rlc_entity_am_t *entity, char *buffer, int size) int bits = 15; /* minimum size is 15 (header+ack_sn+e1) */ int sn; rlc_pdu_encoder_t encoder; - int has_nack = 0; + rlc_pdu_encoder_t encoder_ack; + rlc_pdu_encoder_t previous_e1; int ack; rlc_pdu_encoder_init(&encoder, buffer, size); @@ -947,24 +1011,68 @@ static int generate_status(rlc_entity_am_t *entity, char *buffer, int size) rlc_pdu_encoder_put_bits(&encoder, 0, 3); /* CPT */ /* reserve room for ACK (it will be set after putting the NACKs) */ + encoder_ack = encoder; rlc_pdu_encoder_put_bits(&encoder, 0, 10); + /* put 0 for e1, will be set to 1 later in the code if needed */ + previous_e1 = encoder; + rlc_pdu_encoder_put_bits(&encoder, 0, 1); /* at this point, ACK is VR(R) */ ack = entity->vr_r; - /* each NACK adds 12 bits */ sn = entity->vr_r; - while (bits + 12 <= size && sn_compare_rx(entity, sn, entity->vr_ms) < 0) { + while (sn_compare_rx(entity, sn, entity->vr_ms) < 0) { if (!(rlc_am_segment_full(entity, sn))) { - /* put previous e1 (is 1) */ - rlc_pdu_encoder_put_bits(&encoder, 1, 1); - /* if previous was NACK, put previous e2 (0, we don't do 'so' thing) */ - if (has_nack) - rlc_pdu_encoder_put_bits(&encoder, 0, 1); - /* put NACKed sn */ - rlc_pdu_encoder_put_bits(&encoder, sn, 10); - has_nack = 1; - bits += 12; + rlc_rx_pdu_segment_t *l; + int i; + int count = count_nack_missing_parts(entity, sn); + int nack_bits = count == 0 ? 12 : count * (12 + 30); + int last_byte; + int new_last_byte; + int so_start; + int so_end; + /* if not enough room, stop putting NACKs */ + if (bits + nack_bits > size) + break; + /* set previous e1 to 1 */ + rlc_pdu_encoder_put_bits(&previous_e1, 1, 1); + + if (count == 0) { + /* simply NACK, no SOstart/SOend */ + rlc_pdu_encoder_put_bits(&encoder, sn, 10); /* nack */ + previous_e1 = encoder; + rlc_pdu_encoder_put_bits(&encoder, 0, 2); /* e1, e2 */ + } else { + /* count is not 0, so we have 'count' NACK+e1+e2+SOstart+SOend */ + l = entity->rx_list; + last_byte = -1; + while (l->sn != sn) l = l->next; + for (i = 0; i < count; i++) { + rlc_pdu_encoder_put_bits(&encoder, sn, 10); /* nack */ + previous_e1 = encoder; + /* all NACKs but the last have a following NACK, set e1 for them */ + rlc_pdu_encoder_put_bits(&encoder, i != count - 1, 1); /* e1 */ + rlc_pdu_encoder_put_bits(&encoder, 1, 1); /* e2 */ + /* look for the next segment with missing data before it */ + while (l != NULL && l->sn == sn && !(l->so > last_byte + 1)) { + new_last_byte = l->so + l->size - l->data_offset - 1; + if (new_last_byte > last_byte) + last_byte = new_last_byte; + l = l->next; + } + so_start = last_byte + 1; + if (l == NULL) + so_end = 0x7fff; + else + so_end = l->so - 1; + rlc_pdu_encoder_put_bits(&encoder, so_start, 15); + rlc_pdu_encoder_put_bits(&encoder, so_end, 15); + if (l != NULL) + last_byte = l->so + l->size - l->data_offset - 1; + } + } + + bits += nack_bits; } else { /* this sn is full and we put all NACKs before it, use it for ACK */ ack = (sn + 1) % 1024; @@ -972,24 +1080,10 @@ static int generate_status(rlc_entity_am_t *entity, char *buffer, int size) sn = (sn + 1) % 1024; } - /* go to highest full sn+1 for ACK, VR(MS) is the limit */ - while (sn_compare_rx(entity, sn, entity->vr_ms) < 0 && - rlc_am_segment_full(entity, sn)) { - ack = (sn + 1) % 1024; - sn = (sn + 1) % 1024; - } - - /* at this point, if last put was NACK then put 2 bits else put 1 bit */ - if (has_nack) - rlc_pdu_encoder_put_bits(&encoder, 0, 2); - else - rlc_pdu_encoder_put_bits(&encoder, 0, 1); - rlc_pdu_encoder_align(&encoder); /* let's put the ACK */ - buffer[0] |= ack >> 6; - buffer[1] |= (ack & 0x3f) << 2; + rlc_pdu_encoder_put_bits(&encoder_ack, ack, 10); /* reset the trigger */ entity->status_triggered = 0; diff --git a/openair2/LAYER2/rlc_v2/rlc_oai_api.c b/openair2/LAYER2/rlc_v2/rlc_oai_api.c index bd3eebe635..0cf4b85fa2 100644 --- a/openair2/LAYER2/rlc_v2/rlc_oai_api.c +++ b/openair2/LAYER2/rlc_v2/rlc_oai_api.c @@ -177,14 +177,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( mac_rlc_status_resp_t ret; rlc_entity_t *rb; - /* TODO: handle time a bit more properly */ - if (rlc_current_time_last_frame != frameP || - rlc_current_time_last_subframe != subframeP) { - rlc_current_time++; - rlc_current_time_last_frame = frameP; - rlc_current_time_last_subframe = subframeP; - } - rlc_manager_lock(rlc_ue_manager); ue = rlc_manager_get_ue(rlc_ue_manager, rntiP); @@ -244,14 +236,6 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( exit(1); } - /* TODO: handle time a bit more properly */ - if (rlc_current_time_last_frame != frameP || - rlc_current_time_last_subframe != subframeP) { - rlc_current_time++; - rlc_current_time_last_frame = frameP; - rlc_current_time_last_subframe = subframeP; - } - rlc_manager_lock(rlc_ue_manager); ue = rlc_manager_get_ue(rlc_ue_manager, rntiP); @@ -281,7 +265,6 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( return ret; } -int oai_emulation; rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, @@ -443,7 +426,7 @@ rb_found: "Can't be CU, bad node type %d\n", type); if (NODE_IS_DU(type) && is_srb == 1) { - MessageDef *msg = itti_alloc_new_message(TASK_RLC_ENB, F1AP_UL_RRC_MESSAGE); + MessageDef *msg = itti_alloc_new_message(TASK_RLC_ENB, 0, F1AP_UL_RRC_MESSAGE); F1AP_UL_RRC_MESSAGE(msg).rnti = ue->rnti; F1AP_UL_RRC_MESSAGE(msg).srb_id = rb_id; F1AP_UL_RRC_MESSAGE(msg).rrc_container = (unsigned char *)buf; @@ -506,7 +489,7 @@ rb_found: if (!is_enb) return; - msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION); + msg = itti_alloc_new_message(TASK_RLC_ENB, 0, RLC_SDU_INDICATION); RLC_SDU_INDICATION(msg).rnti = ue->rnti; RLC_SDU_INDICATION(msg).is_successful = 1; RLC_SDU_INDICATION(msg).srb_id = rb_id; @@ -559,7 +542,7 @@ rb_found: if (!is_enb) return; - msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION); + msg = itti_alloc_new_message(TASK_RLC_ENB, 0, RLC_SDU_INDICATION); RLC_SDU_INDICATION(msg).rnti = ue->rnti; RLC_SDU_INDICATION(msg).is_successful = 0; RLC_SDU_INDICATION(msg).srb_id = rb_id; @@ -658,8 +641,7 @@ static void add_srb(int rnti, int module_id, struct LTE_SRB_ToAddMod *s) poll_pdu, poll_byte, max_retx_threshold); rlc_ue_add_srb_rlc_entity(ue, srb_id, rlc_am); - LOG_D(RLC, "%s:%d:%s: added srb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added SRB %d to UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); } rlc_manager_unlock(rlc_ue_manager); } @@ -736,8 +718,7 @@ static void add_drb_am(int rnti, int module_id, struct LTE_DRB_ToAddMod *s) poll_pdu, poll_byte, max_retx_threshold); rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_am); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added DRB %d to UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } rlc_manager_unlock(rlc_ue_manager); } @@ -807,8 +788,7 @@ static void add_drb_um(int rnti, int module_id, struct LTE_DRB_ToAddMod *s) sn_field_length); rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_um); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added DRB %d to UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } rlc_manager_unlock(rlc_ue_manager); } @@ -853,7 +833,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP if (0 /*|| ctxt_pP->instance != 0 || ctxt_pP->eNB_index != 0 || ctxt_pP->configured != 1 || ctxt_pP->brOption != 0 */) { - LOG_E(RLC, "%s: ctxt_pP not handled (%d %d %d %d %d %d)\n", __FUNCTION__, + LOG_E(RLC, "%s: ctxt_pP not handled (%d %d %ld %d %d %d)\n", __FUNCTION__, ctxt_pP->enb_flag , ctxt_pP->module_id, ctxt_pP->instance, ctxt_pP->eNB_index, ctxt_pP->configured, ctxt_pP->brOption); exit(1); @@ -925,8 +905,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP ); rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_um); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, (int)drb_id, mbms_rnti); + LOG_D(RLC, "%s:%d:%s: added DRB %d to UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, (int)drb_id, mbms_rnti); } rlc_manager_unlock(rlc_ue_manager); @@ -1028,3 +1007,38 @@ rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) return RLC_OP_STATUS_OK; } + +void rlc_tick(int frame, int subframe) +{ + int expected_next_frame; + int expected_next_subframe; + + if (frame != rlc_current_time_last_frame || + subframe != rlc_current_time_last_subframe) { + /* warn if discontinuity in ticks */ + expected_next_subframe = (rlc_current_time_last_subframe + 1) % 10; + if (expected_next_subframe == 0) + expected_next_frame = (rlc_current_time_last_frame + 1) % 1024; + else + expected_next_frame = rlc_current_time_last_frame; + if (expected_next_frame != frame || expected_next_subframe != subframe) + LOG_W(RLC, "rlc_tick: discontinuity (expected %d.%d, got %d.%d)\n", + expected_next_frame, expected_next_subframe, + frame, subframe); + + rlc_current_time++; + rlc_current_time_last_frame = frame; + rlc_current_time_last_subframe = subframe; + } +} + +void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP){ + +} \ No newline at end of file diff --git a/openair2/LAYER2/rlc_v2/rlc_pdu.c b/openair2/LAYER2/rlc_v2/rlc_pdu.c index c55e2d9c3c..dc8fc8b094 100644 --- a/openair2/LAYER2/rlc_v2/rlc_pdu.c +++ b/openair2/LAYER2/rlc_v2/rlc_pdu.c @@ -233,9 +233,10 @@ static void put_bit(rlc_pdu_encoder_t *encoder, int bit) exit(1); } - encoder->buffer[encoder->byte] <<= 1; if (bit) - encoder->buffer[encoder->byte] |= 1; + encoder->buffer[encoder->byte] |= 1 << (7 - encoder->bit); + else + encoder->buffer[encoder->byte] &= ~(1 << (7 - encoder->bit)); encoder->bit++; if (encoder->bit == 8) { diff --git a/openair2/LAYER2/rlc_v2/tests/LOG/log.h b/openair2/LAYER2/rlc_v2/tests/LOG/log.h index 5c9fcd643c..89d85090b1 100644 --- a/openair2/LAYER2/rlc_v2/tests/LOG/log.h +++ b/openair2/LAYER2/rlc_v2/tests/LOG/log.h @@ -1,5 +1,5 @@ -#ifndef _LOG_H_ -#define _LOG_H_ +#ifndef _RLC_V2_TESTS_LOG_H_ +#define _RLC_V2_TESTS_LOG_H_ #include @@ -7,4 +7,4 @@ #define LOG_D(x, ...) printf(__VA_ARGS__) #define LOG_W(x, ...) printf(__VA_ARGS__) -#endif /* _LOG_H_ */ +#endif /* _RLC_V2_TESTS_LOG_H_ */ diff --git a/openair2/LAYER2/rlc_v2/tests/run_tests.sh b/openair2/LAYER2/rlc_v2/tests/run_tests.sh index 72feff0036..f3776157a3 100755 --- a/openair2/LAYER2/rlc_v2/tests/run_tests.sh +++ b/openair2/LAYER2/rlc_v2/tests/run_tests.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_count=45 +test_count=49 for i in `seq $test_count` do diff --git a/openair2/LAYER2/rlc_v2/tests/test11.txt.gz b/openair2/LAYER2/rlc_v2/tests/test11.txt.gz index ea435a6660..160916bb36 100644 Binary files a/openair2/LAYER2/rlc_v2/tests/test11.txt.gz and b/openair2/LAYER2/rlc_v2/tests/test11.txt.gz differ diff --git a/openair2/LAYER2/rlc_v2/tests/test12.txt.gz b/openair2/LAYER2/rlc_v2/tests/test12.txt.gz index 988d7ae644..a416cfdd2e 100644 Binary files a/openair2/LAYER2/rlc_v2/tests/test12.txt.gz and b/openair2/LAYER2/rlc_v2/tests/test12.txt.gz differ diff --git a/openair2/LAYER2/rlc_v2/tests/test46.h b/openair2/LAYER2/rlc_v2/tests/test46.h new file mode 100644 index 0000000000..b58c9dce64 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/test46.h @@ -0,0 +1,49 @@ +/* + * rlc am test ack/nack reporting with segmented SDUs + * eNB sends SDU in big PDU, not received + * eNB retx with smaller PDUs, not received except a few + * after some time, RX works again, UE should NACK with SOstart/SOend + * + * this test was written because in the past we didn't generate NACKs with + * SOstart/SOend, potentially leading to infinite retransmissions, even with + * good radio conditions (well, there will be max ReTX reached at some point). + * The scenario is as follows: + * the eNB transmits many many PDUs segments and asks for status + * report at some point (but before sending all the segments). The UE then + * generates a (wrong) NACK without SOstart/SOend, and then the eNB has to + * resend everything from start (all bytes of the PDU have been NACKed because + * there is no SOstart/SOend). Then the eNB will again ask for status report + * before sending everything and the process repeats all over again. + */ +TIME, 1, + ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, + UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, + UE_RECV_FAILS, 1, + ENB_RECV_FAILS, 1, + ENB_SDU, 0, 300, + ENB_PDU_SIZE, 500, + UE_PDU_SIZE, 1000, +TIME, 2, + ENB_PDU_SIZE, 7, +TIME, 50, + UE_RECV_FAILS, 0, +TIME, 51, + UE_RECV_FAILS, 1, +TIME, 60, + UE_RECV_FAILS, 0, +TIME, 61, + UE_RECV_FAILS, 1, +TIME, 70, + UE_RECV_FAILS, 0, +TIME, 71, + UE_RECV_FAILS, 1, +TIME, 80, + UE_RECV_FAILS, 0, +TIME, 81, + UE_RECV_FAILS, 1, +TIME, 140, + UE_RECV_FAILS, 0, + ENB_RECV_FAILS, 0, +TIME, 150, + ENB_PDU_SIZE, 200, +TIME, -1 diff --git a/openair2/LAYER2/rlc_v2/tests/test46.txt.gz b/openair2/LAYER2/rlc_v2/tests/test46.txt.gz new file mode 100644 index 0000000000..dd633ec032 Binary files /dev/null and b/openair2/LAYER2/rlc_v2/tests/test46.txt.gz differ diff --git a/openair2/LAYER2/rlc_v2/tests/test47.h b/openair2/LAYER2/rlc_v2/tests/test47.h new file mode 100644 index 0000000000..30cc6498da --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/test47.h @@ -0,0 +1,27 @@ +/* + * am: test function segment_nack_size, case "if (count == 0) return 12;" + * The eNB sends 5 PDUs, only first and last received by the UE. Then we + * ask for the UE's buffer status to trigger the case. + */ +TIME, 1, + ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, + UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, + ENB_RECV_FAILS, 1, + ENB_PDU_SIZE, 100, + UE_PDU_SIZE, 100, +TIME, 2, + ENB_SDU, 0, 10, +TIME, 3, + UE_RECV_FAILS, 1, + ENB_SDU, 1, 10, +TIME, 4, + ENB_SDU, 2, 10, +TIME, 5, + ENB_SDU, 3, 10, +TIME, 6, + UE_RECV_FAILS, 0, + ENB_RECV_FAILS, 0, + ENB_SDU, 4, 10, +TIME, 42, + UE_BUFFER_STATUS, +TIME, -1 diff --git a/openair2/LAYER2/rlc_v2/tests/test47.txt.gz b/openair2/LAYER2/rlc_v2/tests/test47.txt.gz new file mode 100644 index 0000000000..5404bd7936 Binary files /dev/null and b/openair2/LAYER2/rlc_v2/tests/test47.txt.gz differ diff --git a/openair2/LAYER2/rlc_v2/tests/test48.h b/openair2/LAYER2/rlc_v2/tests/test48.h new file mode 100644 index 0000000000..46c2c8ad33 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/test48.h @@ -0,0 +1,29 @@ +/* + * am: test case "if (bits + nack_size > maxsize)" in functions status_size + * and generate_status. + * The eNB sends 5 PDUs, only first and last received by the UE. Then we + * ask for the UE's buffer status to trigger the case. UE PDU size is + * limited to 6 to trigger the case. + */ +TIME, 1, + ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, + UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, + ENB_RECV_FAILS, 1, + ENB_PDU_SIZE, 100, + UE_PDU_SIZE, 6, +TIME, 2, + ENB_SDU, 0, 10, +TIME, 3, + UE_RECV_FAILS, 1, + ENB_SDU, 1, 10, +TIME, 4, + ENB_SDU, 2, 10, +TIME, 5, + ENB_SDU, 3, 10, +TIME, 6, + UE_RECV_FAILS, 0, + ENB_RECV_FAILS, 0, + ENB_SDU, 4, 10, +TIME, 42, + UE_BUFFER_STATUS, +TIME, -1 diff --git a/openair2/LAYER2/rlc_v2/tests/test48.txt.gz b/openair2/LAYER2/rlc_v2/tests/test48.txt.gz new file mode 100644 index 0000000000..c1797b73bb Binary files /dev/null and b/openair2/LAYER2/rlc_v2/tests/test48.txt.gz differ diff --git a/openair2/LAYER2/rlc_v2/tests/test49.h b/openair2/LAYER2/rlc_v2/tests/test49.h new file mode 100644 index 0000000000..edeec27403 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/test49.h @@ -0,0 +1,27 @@ +/* + * rlc am test ack/nack reporting with segmented SDUs + * + * 5 SDUs put into 6 PDUs, all PDUs received expect the 3rd. Then + * retransmission happens with smaller PDU size. + */ +TIME, 1, + ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, + UE_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, + ENB_SDU, 0, 60, + ENB_SDU, 1, 160, + ENB_SDU, 2, 130, + ENB_SDU, 3, 120, + ENB_SDU, 4, 100, + ENB_PDU_SIZE, 100, + UE_PDU_SIZE, 1000, +TIME, 3, + UE_RECV_FAILS, 1, +TIME, 4, + UE_RECV_FAILS, 0, +TIME, 7, + ENB_PDU_SIZE, 40, +TIME, 42, + UE_RECV_FAILS, 1, +TIME, 80, + UE_RECV_FAILS, 0, +TIME, -1 diff --git a/openair2/LAYER2/rlc_v2/tests/test49.txt.gz b/openair2/LAYER2/rlc_v2/tests/test49.txt.gz new file mode 100644 index 0000000000..752a1aedd5 Binary files /dev/null and b/openair2/LAYER2/rlc_v2/tests/test49.txt.gz differ diff --git a/openair2/LAYER2/rlc_v2/tests/test6.h b/openair2/LAYER2/rlc_v2/tests/test6.h index 2115c8a328..f778749729 100644 --- a/openair2/LAYER2/rlc_v2/tests/test6.h +++ b/openair2/LAYER2/rlc_v2/tests/test6.h @@ -5,9 +5,6 @@ * [1..600] is received but ACK/NACK not * eNB retx with still smaller PDUs [1..400] [401..600] [601..900] * all is received, ACKs/NACKs go through - * - * this test will fail if NACK mechanism uses SOstart/SOend - * (not implemented for the moment) */ TIME, 1, ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, diff --git a/openair2/LAYER2/rlc_v2/tests/test6.txt.gz b/openair2/LAYER2/rlc_v2/tests/test6.txt.gz index 54870821a6..345c149eec 100644 Binary files a/openair2/LAYER2/rlc_v2/tests/test6.txt.gz and b/openair2/LAYER2/rlc_v2/tests/test6.txt.gz differ diff --git a/openair2/LAYER2/rlc_v2/tests/test7.h b/openair2/LAYER2/rlc_v2/tests/test7.h index 081227a400..83e9083b10 100644 --- a/openair2/LAYER2/rlc_v2/tests/test7.h +++ b/openair2/LAYER2/rlc_v2/tests/test7.h @@ -6,9 +6,6 @@ * eNB retx with still smaller PDUs [1..400] [401..600] [601..900] * [401..600] received, ACK goes through * link clean, all goes through - * - * this test will fail if NACK mechanism uses SOstart/SOend - * (not implemented for the moment) */ TIME, 1, ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, diff --git a/openair2/LAYER2/rlc_v2/tests/test7.txt.gz b/openair2/LAYER2/rlc_v2/tests/test7.txt.gz index 9976a60507..48148755dc 100644 Binary files a/openair2/LAYER2/rlc_v2/tests/test7.txt.gz and b/openair2/LAYER2/rlc_v2/tests/test7.txt.gz differ diff --git a/openair2/LAYER2/rlc_v2/tests/test9.h b/openair2/LAYER2/rlc_v2/tests/test9.h index 88e23d94e9..2da9732012 100644 --- a/openair2/LAYER2/rlc_v2/tests/test9.h +++ b/openair2/LAYER2/rlc_v2/tests/test9.h @@ -11,9 +11,6 @@ * In the current RLC implementation, this is impossible. If we send [12..21] * it means [1..21] has been split and so we won't sent it later on. * Maybe with HARQ retransmissions in PHY/MAC in bad radio conditions? - * - * this test will fail if NACK mechanism uses SOstart/SOend - * (not implemented for the moment) */ TIME, 1, ENB_AM, 100000, 100000, 35, 0, 45, -1, -1, 4, diff --git a/openair2/LAYER2/rlc_v2/tests/test9.txt.gz b/openair2/LAYER2/rlc_v2/tests/test9.txt.gz index cc6d934e70..d3803062aa 100644 Binary files a/openair2/LAYER2/rlc_v2/tests/test9.txt.gz and b/openair2/LAYER2/rlc_v2/tests/test9.txt.gz differ diff --git a/openair2/M2AP/m2ap_MCE.c b/openair2/M2AP/m2ap_MCE.c index 096f3cabee..f163aa453a 100644 --- a/openair2/M2AP/m2ap_MCE.c +++ b/openair2/M2AP/m2ap_MCE.c @@ -105,7 +105,7 @@ void m2ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_associa DevAssert(sctp_new_association_resp != NULL); if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - LOG_W(M2AP, "Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", + LOG_W(M2AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", sctp_new_association_resp->sctp_state, instance, sctp_new_association_resp->ulp_cnx_id); @@ -233,7 +233,7 @@ int m2ap_MCE_init_sctp (m2ap_MCE_instance_t *instance_p, sctp_init_t *sctp_init = NULL; DevAssert(instance_p != NULL); DevAssert(local_ip_addr != NULL); - message = itti_alloc_new_message (TASK_M2AP_MCE, SCTP_INIT_MSG_MULTI_REQ); + message = itti_alloc_new_message (TASK_M2AP_MCE, 0, SCTP_INIT_MSG_MULTI_REQ); sctp_init = &message->ittiMsg.sctp_init_multi; sctp_init->port = mce_port_for_M2C; sctp_init->ppid = M2AP_SCTP_PPID; @@ -267,7 +267,7 @@ static void m2ap_MCE_register_MCE(m2ap_MCE_instance_t *instance_p, m2ap_MCE_data_t *m2ap_mce_data = NULL; DevAssert(instance_p != NULL); DevAssert(target_MCE_ip_address != NULL); - message = itti_alloc_new_message(TASK_M2AP_MCE, SCTP_NEW_ASSOCIATION_REQ_MULTI); + message = itti_alloc_new_message(TASK_M2AP_MCE, 0, SCTP_NEW_ASSOCIATION_REQ_MULTI); sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi; sctp_new_association_req->port = mce_port_for_M2C; sctp_new_association_req->ppid = M2AP_SCTP_PPID; @@ -312,7 +312,7 @@ void m2ap_MCE_handle_register_MCE(instance_t instance, DevCheck(new_instance->tac == m2ap_register_MCE->tac, new_instance->tac, m2ap_register_MCE->tac, 0); DevCheck(new_instance->mcc == m2ap_register_MCE->mcc, new_instance->mcc, m2ap_register_MCE->mcc, 0); DevCheck(new_instance->mnc == m2ap_register_MCE->mnc, new_instance->mnc, m2ap_register_MCE->mnc, 0); - M2AP_WARN("MCE[%d] already registered\n", instance); + M2AP_WARN("MCE[%ld] already registered\n", instance); } else { new_instance = calloc(1, sizeof(m2ap_MCE_instance_t)); DevAssert(new_instance != NULL); @@ -356,7 +356,7 @@ void m2ap_MCE_handle_register_MCE(instance_t instance, new_instance->mce_port_for_M2C = m2ap_register_MCE->mce_port_for_M2C; /* Add the new instance to the list of MCE (meaningfull in virtual mode) */ m2ap_MCE_insert_new_instance(new_instance); - M2AP_INFO("Registered new MCE[%d] and %s MCE id %u\n", + M2AP_INFO("Registered new MCE[%ld] and %s MCE id %u\n", instance, m2ap_register_MCE->cell_type == CELL_MACRO_ENB ? "macro" : "home", m2ap_register_MCE->MCE_id); @@ -367,7 +367,7 @@ void m2ap_MCE_handle_register_MCE(instance_t instance, return; } - M2AP_INFO("MCE[%d] MCE id %u acting as a listner (server)\n", + M2AP_INFO("MCE[%ld] MCE id %u acting as a listner (server)\n", instance, m2ap_register_MCE->MCE_id); } } @@ -394,7 +394,7 @@ void m2ap_MCE_handle_sctp_init_msg_multi_cnf( /* Trying to connect to the provided list of MCE ip address */ for (index = 0; index < instance->nb_m2; index++) { - M2AP_INFO("MCE[%d] MCE id %u acting as an initiator (client)\n", + M2AP_INFO("MCE[%ld] MCE id %u acting as an initiator (client)\n", instance_id, instance->MCE_id); m2ap_MCE_register_MCE(instance, &instance->target_mce_m2_ip_address[index], @@ -507,7 +507,7 @@ void MCE_task_send_sctp_init_req(instance_t enb_id, m2ap_mce_sctp_req_t * m2ap_m LOG_I(M2AP, "M2AP_SCTP_REQ(create socket)\n"); MessageDef *message_p = NULL; - message_p = itti_alloc_new_message (TASK_M2AP_MCE, SCTP_INIT_MSG); + message_p = itti_alloc_new_message (TASK_M2AP_MCE, 0, SCTP_INIT_MSG); // if( m2ap_mce_sctp_req == NULL ){ // message_p->ittiMsg.sctp_init.port = M2AP_PORT_NUMBER; @@ -558,7 +558,7 @@ void *m2ap_MCE_task(void *arg) { switch (ITTI_MSG_ID(received_msg)) { case MESSAGE_TEST: LOG_W(M2AP,"MCE Received MESSAGE_TEST Message\n"); - //MessageDef * message_p = itti_alloc_new_message(TASK_M2AP_MCE, MESSAGE_TEST); + //MessageDef * message_p = itti_alloc_new_message(TASK_M2AP_MCE, 0, MESSAGE_TEST); //itti_send_msg_to_task(TASK_M3AP, 1/*ctxt_pP->module_id*/, message_p); break; case TERMINATE_MESSAGE: @@ -567,29 +567,29 @@ void *m2ap_MCE_task(void *arg) { break; case M2AP_MCE_SCTP_REQ: - MCE_task_send_sctp_init_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MCE_task_send_sctp_init_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MCE_SCTP_REQ(received_msg)); break; case M2AP_SUBFRAME_PROCESS: - m2ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg)); + m2ap_check_timers(ITTI_MSG_DESTINATION_INSTANCE(received_msg)); break; case M2AP_REGISTER_MCE_REQ: LOG_I(M2AP,"MCE Received M2AP_REGISTER_MCE_REQ Message\n"); - m2ap_MCE_handle_register_MCE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_MCE_handle_register_MCE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_REGISTER_MCE_REQ(received_msg)); break; case M2AP_SETUP_RESP: LOG_I(M2AP,"MCE Received M2AP_SETUP_RESP Message\n"); - MCE_send_M2_SETUP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MCE_send_M2_SETUP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_SETUP_RESP(received_msg)); break; case M2AP_SETUP_FAILURE: LOG_I(M2AP,"MCE Received M2AP_SETUP_FAILURE Message\n"); - MCE_send_M2_SETUP_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MCE_send_M2_SETUP_FAILURE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_SETUP_FAILURE(received_msg)); break; @@ -644,41 +644,41 @@ void *m2ap_MCE_task(void *arg) { // case M2AP_HANDOVER_REQ: -// m2ap_MCE_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m2ap_MCE_handle_handover_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M2AP_HANDOVER_REQ(received_msg)); // break; // // case M2AP_HANDOVER_REQ_ACK: -// m2ap_MCE_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m2ap_MCE_handle_handover_req_ack(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M2AP_HANDOVER_REQ_ACK(received_msg)); // break; // // case M2AP_UE_CONTEXT_RELEASE: -// m2ap_MCE_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m2ap_MCE_ue_context_release(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M2AP_UE_CONTEXT_RELEASE(received_msg)); // break; // case SCTP_INIT_MSG_MULTI_CNF: LOG_D(M2AP,"MCE Received SCTP_INIT_MSG_MULTI_CNF Message\n"); - m2ap_MCE_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_MCE_handle_sctp_init_msg_multi_cnf(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_init_msg_multi_cnf); break; case SCTP_NEW_ASSOCIATION_RESP: LOG_D(M2AP,"MCE Received SCTP_NEW_ASSOCIATION_RESP Message\n"); - m2ap_MCE_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_MCE_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_NEW_ASSOCIATION_IND: LOG_D(M2AP,"MCE Received SCTP_NEW_ASSOCIATION Message\n"); - m2ap_MCE_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_MCE_handle_sctp_association_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_ind); break; case SCTP_DATA_IND: LOG_D(M2AP,"MCE Received SCTP_DATA_IND Message\n"); - m2ap_MCE_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_MCE_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; diff --git a/openair2/M2AP/m2ap_MCE_handler.c b/openair2/M2AP/m2ap_MCE_handler.c index 85e342f996..5a0e303218 100644 --- a/openair2/M2AP/m2ap_MCE_handler.c +++ b/openair2/M2AP/m2ap_MCE_handler.c @@ -113,7 +113,7 @@ int m2ap_MCE_handle_message(instance_t instance, uint32_t assoc_id, int32_t stre } /* Calling the right handler */ - LOG_I(M2AP, "Calling handler with instance %d\n",instance); + LOG_I(M2AP, "Calling handler with instance %ld\n",instance); ret = (*m2ap_MCE_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1]) (instance, assoc_id, stream, &pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu); diff --git a/openair2/M2AP/m2ap_MCE_interface_management.c b/openair2/M2AP/m2ap_MCE_interface_management.c index e162c9a5de..3b12f41cbe 100644 --- a/openair2/M2AP/m2ap_MCE_interface_management.c +++ b/openair2/M2AP/m2ap_MCE_interface_management.c @@ -179,7 +179,7 @@ int MCE_handle_MBMS_SESSION_START_RESPONSE(instance_t instance, int ENB_MBMS_M2AP_ID=-1; - MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE,M2AP_MBMS_SESSION_START_RESP); //TODO + MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE, 0,M2AP_MBMS_SESSION_START_RESP); //TODO LOG_D(M2AP, "M2AP: SessionStart-Resp: protocolIEs.list.count %d\n", in->protocolIEs.list.count); @@ -317,7 +317,7 @@ int MCE_handle_MBMS_SESSION_STOP_RESPONSE(instance_t instance, int ENB_MBMS_M2AP_ID=-1; - MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE,M2AP_MBMS_SESSION_STOP_RESP); //TODO + MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE, 0,M2AP_MBMS_SESSION_STOP_RESP); //TODO LOG_D(M2AP, "M2AP: SessionStop-Resp: protocolIEs.list.count %d\n", in->protocolIEs.list.count); @@ -616,7 +616,7 @@ int MCE_handle_MBMS_SCHEDULING_INFORMATION_RESPONSE(instance_t instance, //int ENB_MBMS_M2AP_ID=-1; - MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE,M2AP_MBMS_SCHEDULING_INFORMATION_RESP); //TODO + MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE, 0,M2AP_MBMS_SCHEDULING_INFORMATION_RESP); //TODO // LOG_D(M2AP, "M2AP: SessionStop-Resp: protocolIEs.list.count %d\n", // in->protocolIEs.list.count); @@ -720,7 +720,7 @@ int MCE_handle_M2_SETUP_REQUEST(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message(TASK_MCE_APP, M2AP_SETUP_REQ); + message_p = itti_alloc_new_message(TASK_MCE_APP, 0, M2AP_SETUP_REQ); /* assoc_id */ M2AP_SETUP_REQ(message_p).assoc_id = assoc_id; @@ -1193,7 +1193,7 @@ int MCE_handle_MCE_CONFIGURATION_UPDATE_FAILURE(instance_t instance, //M2AP_MCEConfigurationUpdateFailure_Ies_t *ie; - MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_MCE, M2AP_MCE_CONFIGURATION_UPDATE_FAILURE); + MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_MCE, 0, M2AP_MCE_CONFIGURATION_UPDATE_FAILURE); LOG_D(M2AP, "M2AP: MCEConfigurationUpdate-Failure: protocolIEs.list.count %d\n", in->protocolIEs.list.count); @@ -1258,7 +1258,7 @@ int MCE_handle_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_MCE, M2AP_MCE_CONFIGURATION_UPDATE_ACK); + message_p = itti_alloc_new_message (TASK_M2AP_MCE, 0, M2AP_MCE_CONFIGURATION_UPDATE_ACK); itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); @@ -1295,7 +1295,7 @@ int MCE_handle_ENB_CONFIGURATION_UPDATE(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_MCE, M2AP_MCE_CONFIGURATION_UPDATE_ACK); + message_p = itti_alloc_new_message (TASK_M2AP_MCE, 0, M2AP_MCE_CONFIGURATION_UPDATE_ACK); itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); @@ -1399,7 +1399,7 @@ int MCE_handle_MBMS_SERVICE_COUNTING_RESPONSE(instance_t instance, //int ENB_MBMS_M2AP_ID=-1; - MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE,M2AP_MBMS_SERVICE_COUNTING_RESP); //TODO + MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE, 0,M2AP_MBMS_SERVICE_COUNTING_RESP); //TODO LOG_D(M2AP, "M2AP: MbmsServiceCounting-Resp: protocolIEs.list.count %d\n", in->protocolIEs.list.count); diff --git a/openair2/M2AP/m2ap_eNB.c b/openair2/M2AP/m2ap_eNB.c index 39c769a43d..c72eda7d8c 100644 --- a/openair2/M2AP/m2ap_eNB.c +++ b/openair2/M2AP/m2ap_eNB.c @@ -136,7 +136,7 @@ void m2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa //dump_trees_m2(); if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - M2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", + M2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", sctp_new_association_resp->sctp_state, instance, sctp_new_association_resp->ulp_cnx_id); @@ -233,7 +233,7 @@ int m2ap_eNB_init_sctp (m2ap_eNB_instance_t *instance_p, sctp_init_t *sctp_init = NULL; DevAssert(instance_p != NULL); DevAssert(local_ip_addr != NULL); - message = itti_alloc_new_message (TASK_M2AP_ENB, SCTP_INIT_MSG_MULTI_REQ); + message = itti_alloc_new_message (TASK_M2AP_ENB, 0, SCTP_INIT_MSG_MULTI_REQ); sctp_init = &message->ittiMsg.sctp_init_multi; sctp_init->port = enb_port_for_M2C; sctp_init->ppid = M2AP_SCTP_PPID; @@ -267,7 +267,7 @@ static void m2ap_eNB_register_eNB(m2ap_eNB_instance_t *instance_p, m2ap_eNB_data_t *m2ap_enb_data = NULL; DevAssert(instance_p != NULL); DevAssert(target_eNB_ip_address != NULL); - message = itti_alloc_new_message(TASK_M2AP_ENB, SCTP_NEW_ASSOCIATION_REQ_MULTI); + message = itti_alloc_new_message(TASK_M2AP_ENB, 0, SCTP_NEW_ASSOCIATION_REQ_MULTI); sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi; sctp_new_association_req->port = enb_port_for_M2C; sctp_new_association_req->ppid = M2AP_SCTP_PPID; @@ -319,7 +319,7 @@ void m2ap_eNB_handle_register_eNB(instance_t instance, DevCheck(new_instance->tac == m2ap_register_eNB->tac, new_instance->tac, m2ap_register_eNB->tac, 0); DevCheck(new_instance->mcc == m2ap_register_eNB->mcc, new_instance->mcc, m2ap_register_eNB->mcc, 0); DevCheck(new_instance->mnc == m2ap_register_eNB->mnc, new_instance->mnc, m2ap_register_eNB->mnc, 0); - M2AP_WARN("eNB[%d] already registered\n", instance); + M2AP_WARN("eNB[%ld] already registered\n", instance); } else { @@ -376,7 +376,7 @@ void m2ap_eNB_handle_register_eNB(instance_t instance, /* Add the new instance to the list of eNB (meaningfull in virtual mode) */ m2ap_eNB_insert_new_instance(new_instance); - M2AP_INFO("Registered new eNB[%d] and %s eNB id %u\n", + M2AP_INFO("Registered new eNB[%ld] and %s eNB id %u\n", instance, m2ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home", m2ap_register_eNB->eNB_id); @@ -387,7 +387,7 @@ void m2ap_eNB_handle_register_eNB(instance_t instance, return; } - M2AP_INFO("eNB[%d] eNB id %u acting as a listner (server)\n", + M2AP_INFO("eNB[%ld] eNB id %u acting as a listner (server)\n", instance, m2ap_register_eNB->eNB_id); } } @@ -414,7 +414,7 @@ void m2ap_eNB_handle_sctp_init_msg_multi_cnf( /* Trying to connect to the provided list of eNB ip address */ for (index = 0; index < instance->nb_m2; index++) { - M2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n", + M2AP_INFO("eNB[%ld] eNB id %u acting as an initiator (client)\n", instance_id, instance->eNB_id); m2ap_eNB_register_eNB(instance, &instance->target_mce_m2_ip_address[index], @@ -527,7 +527,7 @@ void m2ap_eNB_handle_sctp_init_msg_multi_cnf( // LOG_I(M2AP, "M2AP_SCTP_REQ(create socket)\n"); // MessageDef *message_p = NULL; // -// message_p = itti_alloc_new_message (M2AP, SCTP_INIT_MSG); +// message_p = itti_alloc_new_message (M2AP, 0, SCTP_INIT_MSG); // message_p->ittiMsg.sctp_init.port = M2AP_PORT_NUMBER; // message_p->ittiMsg.sctp_init.ppid = M2AP_SCTP_PPID; // message_p->ittiMsg.sctp_init.ipv4 = 1; @@ -561,7 +561,7 @@ void *m2ap_eNB_task(void *arg) { switch (ITTI_MSG_ID(received_msg)) { case MESSAGE_TEST: LOG_D(M2AP,"eNB Received MESSAGE_TEST Message %s\n",itti_get_task_name(ITTI_MSG_ORIGIN_ID(received_msg))); - //MessageDef * message_p = itti_alloc_new_message(TASK_M2AP_ENB, MESSAGE_TEST); + //MessageDef * message_p = itti_alloc_new_message(TASK_M2AP_ENB, 0, MESSAGE_TEST); //itti_send_msg_to_task(TASK_M3AP, 1/*ctxt_pP->module_id*/, message_p); break; case TERMINATE_MESSAGE: @@ -570,104 +570,104 @@ void *m2ap_eNB_task(void *arg) { break; case M2AP_SUBFRAME_PROCESS: - m2ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg)); + m2ap_check_timers(ITTI_MSG_DESTINATION_INSTANCE(received_msg)); break; case M2AP_REGISTER_ENB_REQ: LOG_I(M2AP,"eNB Received M2AP_REGISTER_ENB_REQ Message\n"); - m2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_eNB_handle_register_eNB(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_REGISTER_ENB_REQ(received_msg)); break; case M2AP_MBMS_SCHEDULING_INFORMATION_RESP: LOG_I(M2AP,"eNB M2AP_MBMS_SCHEDULING_INFORMATION_RESP Message\n"); - eNB_send_MBMS_SCHEDULING_INFORMATION_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SCHEDULING_INFORMATION_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SCHEDULING_INFORMATION_RESP(received_msg)); break; case M2AP_MBMS_SESSION_START_RESP: LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_START_RESP Message\n"); - eNB_send_MBMS_SESSION_START_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SESSION_START_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SESSION_START_RESP(received_msg)); break; case M2AP_MBMS_SESSION_START_FAILURE: LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_START_FAILURE Message\n"); - eNB_send_MBMS_SESSION_START_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SESSION_START_FAILURE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SESSION_START_FAILURE(received_msg)); break; case M2AP_MBMS_SESSION_STOP_RESP: LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_STOP_RESP Message\n"); - eNB_send_MBMS_SESSION_STOP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SESSION_STOP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SESSION_STOP_RESP(received_msg)); break; case M2AP_ENB_CONFIGURATION_UPDATE: LOG_I(M2AP,"eNB M2AP_ENB_CONFIGURATION_UPDATE Message\n"); - eNB_send_eNB_CONFIGURATION_UPDATE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_eNB_CONFIGURATION_UPDATE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_ENB_CONFIGURATION_UPDATE(received_msg)); break; case M2AP_MCE_CONFIGURATION_UPDATE_ACK: LOG_I(M2AP,"eNB M2AP_MCE_CONFIGURATION_UPDATE_ACK Message\n"); - //eNB_send_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + //eNB_send_MCE_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M2AP_MCE_CONFIGURATION_UPDATE_ACK(received_msg)); break; case M2AP_MCE_CONFIGURATION_UPDATE_FAILURE: LOG_I(M2AP,"eNB M2AP_MCE_CONFIGURATION_UPDATE_FAILURE Message\n"); - //(ITTI_MESSAGE_GET_INSTANCE(received_msg), + //(ITTI_MSG_DESTINATION_INSTANCE(received_msg), //&M2AP_MCE_CONFIGURATION_UPDATE_FAILURE(received_msg)); break; case M2AP_MBMS_SESSION_UPDATE_RESP: LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_UPDATE_RESP Message\n"); - eNB_send_MBMS_SESSION_UPDATE_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SESSION_UPDATE_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SESSION_UPDATE_RESP(received_msg)); break; case M2AP_MBMS_SESSION_UPDATE_FAILURE: LOG_I(M2AP,"eNB M2AP_MBMS_SESSION_UPDATE_FAILURE Message\n"); - eNB_send_MBMS_SESSION_UPDATE_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SESSION_UPDATE_FAILURE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SESSION_UPDATE_FAILURE(received_msg)); break; case M2AP_MBMS_SERVICE_COUNTING_REPORT: LOG_I(M2AP,"eNB M2AP_MBMS_SERVICE_COUNTING_REPORT Message\n"); - eNB_send_MBMS_SERVICE_COUNTING_REPORT(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SERVICE_COUNTING_REPORT(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SERVICE_COUNTING_REPORT(received_msg)); break; case M2AP_MBMS_OVERLOAD_NOTIFICATION: LOG_I(M2AP,"eNB M2AP_MBMS_OVERLOAD_NOTIFICATION Message\n"); - eNB_send_MBMS_OVERLOAD_NOTIFICATION(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_OVERLOAD_NOTIFICATION(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_OVERLOAD_NOTIFICATION(received_msg)); break; case M2AP_MBMS_SERVICE_COUNTING_RESP: LOG_I(M2AP,"eNB M2AP_MBMS_SERVICE_COUNTING_RESP Message\n"); - eNB_send_MBMS_SERVICE_COUNTING_RESP(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SERVICE_COUNTING_RESP(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SERVICE_COUNTING_RESP(received_msg)); break; case M2AP_MBMS_SERVICE_COUNTING_FAILURE: LOG_I(M2AP,"eNB Message\n"); - eNB_send_MBMS_SERVICE_COUNTING_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + eNB_send_MBMS_SERVICE_COUNTING_FAILURE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M2AP_MBMS_SERVICE_COUNTING_FAILURE(received_msg)); break; case SCTP_INIT_MSG_MULTI_CNF: LOG_I(M2AP,"eNB Received SCTP_INIT_MSG_MULTI_CNF Message\n"); - m2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_init_msg_multi_cnf); break; case SCTP_NEW_ASSOCIATION_RESP: LOG_I(M2AP,"eNB Received SCTP_NEW_ASSOCIATION_RESP Message\n"); - m2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_eNB_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_NEW_ASSOCIATION_IND: LOG_I(M2AP,"eNB Received SCTP_NEW_ASSOCIATION Message\n"); - m2ap_eNB_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_eNB_handle_sctp_association_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_ind); break; case SCTP_DATA_IND: LOG_I(M2AP,"eNB Received SCTP_DATA_IND Message\n"); - m2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m2ap_eNB_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; diff --git a/openair2/M2AP/m2ap_eNB_handler.c b/openair2/M2AP/m2ap_eNB_handler.c index fe0059f0a5..9abc337408 100644 --- a/openair2/M2AP/m2ap_eNB_handler.c +++ b/openair2/M2AP/m2ap_eNB_handler.c @@ -113,7 +113,7 @@ int m2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stre } /* Calling the right handler */ - LOG_I(M2AP, "Calling handler with instance %d\n",instance); + LOG_I(M2AP, "Calling handler with instance %ld\n",instance); ret = (*m2ap_eNB_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1]) (instance, assoc_id, stream, &pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M2AP_M2AP_PDU, &pdu); diff --git a/openair2/M2AP/m2ap_eNB_interface_management.c b/openair2/M2AP/m2ap_eNB_interface_management.c index 9649d919c3..486e382e69 100644 --- a/openair2/M2AP/m2ap_eNB_interface_management.c +++ b/openair2/M2AP/m2ap_eNB_interface_management.c @@ -85,8 +85,8 @@ int eNB_handle_MBMS_SCHEDULING_INFORMATION(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SCHEDULING_INFORMATION); - //message_p2 = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SCHEDULING_INFORMATION); + message_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_MBMS_SCHEDULING_INFORMATION); + //message_p2 = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_MBMS_SCHEDULING_INFORMATION); @@ -292,7 +292,7 @@ int eNB_handle_MBMS_SESSION_START_REQUEST(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SESSION_START_REQ); + message_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_MBMS_SESSION_START_REQ); itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); @@ -463,7 +463,7 @@ int eNB_handle_MBMS_SESSION_STOP_REQUEST(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SESSION_STOP_REQ); + message_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_MBMS_SESSION_STOP_REQ); itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); @@ -749,8 +749,8 @@ int eNB_handle_M2_SETUP_RESPONSE(instance_t instance, //M2AP_Cells_to_be_Activated_List_Item_t *cell; int i,j; - MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_SETUP_RESP); - //MessageDef *msg_p2 = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_SETUP_RESP); + MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_SETUP_RESP); + //MessageDef *msg_p2 = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_SETUP_RESP); LOG_D(M2AP, "M2AP: M2Setup-Resp: protocolIEs.list.count %d\n", in->protocolIEs.list.count); @@ -856,7 +856,7 @@ int eNB_handle_M2_SETUP_FAILURE(instance_t instance, M2AP_M2SetupFailure_Ies_t *ie; - MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_SETUP_FAILURE); + MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_SETUP_FAILURE); LOG_D(M2AP, "M2AP: M2Setup-Failure: protocolIEs.list.count %d\n", in->protocolIEs.list.count); @@ -1062,7 +1062,7 @@ int eNB_handle_eNB_CONFIGURATION_UPDATE_FAILURE(instance_t instance, //M2AP_ENBConfigurationUpdateFailure_Ies_t *ie; - MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_ENB_CONFIGURATION_UPDATE_FAILURE); + MessageDef *msg_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_ENB_CONFIGURATION_UPDATE_FAILURE); LOG_D(M2AP, "M2AP: ENBConfigurationUpdate-Failure: protocolIEs.list.count %d\n", in->protocolIEs.list.count); @@ -1127,7 +1127,7 @@ int eNB_handle_eNB_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_ENB_CONFIGURATION_UPDATE_ACK); + message_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_ENB_CONFIGURATION_UPDATE_ACK); itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); @@ -1162,7 +1162,7 @@ int eNB_handle_MCE_CONFIGURATION_UPDATE(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MCE_CONFIGURATION_UPDATE); + message_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_MCE_CONFIGURATION_UPDATE); itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); @@ -1233,7 +1233,7 @@ int eNB_handle_MBMS_SESSION_UPDATE_REQUEST(instance_t instance, assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SESSION_UPDATE_REQ); + message_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_MBMS_SESSION_UPDATE_REQ); itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); @@ -1321,7 +1321,7 @@ int eNB_handle_MBMS_SERVICE_COUNTING_REQ(instance_t instance, - //message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SERVICE_COUNTING_REQ); + //message_p = itti_alloc_new_message (TASK_M2AP_ENB, 0, M2AP_MBMS_SERVICE_COUNTING_REQ); return 0; diff --git a/openair2/M2AP/m2ap_eNB_management_procedures.c b/openair2/M2AP/m2ap_eNB_management_procedures.c index b3ada92fa8..59d91afb74 100644 --- a/openair2/M2AP/m2ap_eNB_management_procedures.c +++ b/openair2/M2AP/m2ap_eNB_management_procedures.c @@ -116,7 +116,7 @@ void dump_trees_m2(void) m2ap_eNB_instance_t *zz; STAILQ_FOREACH(zz, &m2ap_eNB_internal_data.m2ap_eNB_instances_head, m2ap_eNB_entries) { -printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance); +printf("here comes the tree (instance %ld):\n---------------------------------------------\n", zz->instance); dump_tree_m2(zz->m2ap_enb_head.rbh_root); printf("---------------------------------------------\n"); } diff --git a/openair2/M2AP/m2ap_itti_messaging.c b/openair2/M2AP/m2ap_itti_messaging.c index b9cfd32901..e0dcc27175 100644 --- a/openair2/M2AP/m2ap_itti_messaging.c +++ b/openair2/M2AP/m2ap_itti_messaging.c @@ -36,7 +36,7 @@ void m2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uin MessageDef *message_p; sctp_data_req_t *sctp_data_req; - message_p = itti_alloc_new_message(TASK_M2AP_ENB, SCTP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_M2AP_ENB, 0, SCTP_DATA_REQ); sctp_data_req = &message_p->ittiMsg.sctp_data_req; @@ -56,7 +56,7 @@ void m2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t asso MessageDef *message_p = NULL; sctp_close_association_t *sctp_close_association_p = NULL; - message_p = itti_alloc_new_message(TASK_M2AP_ENB, SCTP_CLOSE_ASSOCIATION); + message_p = itti_alloc_new_message(TASK_M2AP_ENB, 0, SCTP_CLOSE_ASSOCIATION); sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; sctp_close_association_p->assoc_id = assoc_id; @@ -70,7 +70,7 @@ void m2ap_MCE_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uin MessageDef *message_p; sctp_data_req_t *sctp_data_req; - message_p = itti_alloc_new_message(TASK_M2AP_MCE, SCTP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_M2AP_MCE, 0, SCTP_DATA_REQ); sctp_data_req = &message_p->ittiMsg.sctp_data_req; @@ -88,7 +88,7 @@ void m2ap_MCE_itti_send_sctp_close_association(instance_t instance, int32_t asso MessageDef *message_p = NULL; sctp_close_association_t *sctp_close_association_p = NULL; - message_p = itti_alloc_new_message(TASK_M2AP_MCE, SCTP_CLOSE_ASSOCIATION); + message_p = itti_alloc_new_message(TASK_M2AP_MCE, 0, SCTP_CLOSE_ASSOCIATION); sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; sctp_close_association_p->assoc_id = assoc_id; diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c index 817c863f7b..4ac12ab5b4 100644 --- a/openair2/MCE_APP/mce_app.c +++ b/openair2/MCE_APP/mce_app.c @@ -54,7 +54,6 @@ # define X2AP_ENB_REGISTER_RETRY_DELAY 10 #include "openair1/PHY/INIT/phy_init.h" -extern unsigned char NB_MCE_INST; extern RAN_CONTEXT_t RC; @@ -78,7 +77,7 @@ static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, u { // M3AP registration /* note: there is an implicit relationship between the data structure and the message name */ - msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_REGISTER_MCE_REQ); + msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M3AP_REGISTER_MCE_REQ); //RCconfig_S1(msg_p, mce_id); //if (mce_id == 0) @@ -92,7 +91,7 @@ static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, u //if (NODE_IS_DU(node_type)) { // F1AP registration // // configure F1AP here for F1C // LOG_I(ENB_APP,"ngran_eNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); - // msg_p = itti_alloc_new_message (TASK_ENB_APP, F1AP_SETUP_REQ); + // msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, F1AP_SETUP_REQ); // RCconfig_DU_F1(msg_p, enb_id); // LOG_I(ENB_APP,"[eNB %d] eNB_app_register via F1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id)); @@ -101,7 +100,7 @@ static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, u //} //else { // S1AP registration // /* note: there is an implicit relationship between the data structure and the message name */ - // msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ); + // msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, S1AP_REGISTER_ENB_REQ); // RCconfig_S1(msg_p, enb_id); // if (enb_id == 0) RCconfig_gtpu(); @@ -128,7 +127,7 @@ static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, u // // for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) { // { -// msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ); +// msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, X2AP_REGISTER_ENB_REQ); // RCconfig_X2(msg_p, mce_id); // itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p); // register_mce_x2_pending++; @@ -148,7 +147,7 @@ static uint32_t MCE_app_register(ngran_node_t node_type,uint32_t mce_id_start, u // for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) { // { // // LOG_W(MCE_APP,"Register commes inside ...\n"); -// msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_REGISTER_MCE_REQ); +// msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M2AP_REGISTER_MCE_REQ); // //RCconfig_M2_MCE(msg_p, mce_id); // itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p); // // LOG_W(MCE_APP,"Register sent ...\n"); @@ -169,7 +168,7 @@ static uint32_t MCE_app_register_m3(uint32_t mce_id_start, uint32_t mce_id_end) for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) { { // LOG_W(MCE_APP,"Register commes inside ...\n"); - msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_REGISTER_MCE_REQ); + msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M3AP_REGISTER_MCE_REQ); RCconfig_M3(msg_p, mce_id); itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p); LOG_D(MCE_APP,"Register sent ...\n"); @@ -184,7 +183,7 @@ static uint32_t MCE_app_register_m3(uint32_t mce_id_start, uint32_t mce_id_end) //static uint32_t MCE_app_handle_m3ap_mbms_session_start_req(instance_t instance){ // //uint32_t mce_id=0; // // MessageDef *msg_p; -// // msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_MBMS_SESSION_START_RESP); +// // msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M3AP_MBMS_SESSION_START_RESP); // // itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // @@ -194,7 +193,7 @@ static uint32_t MCE_app_register_m3(uint32_t mce_id_start, uint32_t mce_id_end) static uint32_t MCE_app_handle_m3ap_mbms_session_stop_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_MBMS_SESSION_STOP_RESP); + msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M3AP_MBMS_SESSION_STOP_RESP); itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; @@ -203,7 +202,7 @@ static uint32_t MCE_app_handle_m3ap_mbms_session_stop_req(instance_t instance){ static uint32_t MCE_app_handle_m3ap_mbms_session_update_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_MBMS_SESSION_UPDATE_RESP); + msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M3AP_MBMS_SESSION_UPDATE_RESP); itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; @@ -216,7 +215,7 @@ static uint32_t MCE_app_handle_m2ap_setup_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_SETUP_RESP); + msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M2AP_SETUP_RESP); if(m2ap_setup_resp_local) memcpy(&M2AP_SETUP_RESP(msg_p),m2ap_setup_resp_local,sizeof(m2ap_setup_resp_t)); else @@ -230,7 +229,7 @@ static uint32_t MCE_app_handle_m2ap_setup_req(instance_t instance){ static uint32_t MCE_app_handle_m2ap_mbms_session_start_resp(instance_t instance){ MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MCE_APP, M3AP_MBMS_SESSION_START_RESP); + msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M3AP_MBMS_SESSION_START_RESP); itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; } @@ -243,7 +242,7 @@ static uint32_t MCE_app_send_m2ap_mbms_scheduling_information(instance_t instanc //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_MBMS_SCHEDULING_INFORMATION); + msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M2AP_MBMS_SCHEDULING_INFORMATION); if(m2ap_mbms_scheduling_information_local) memcpy(&M2AP_MBMS_SCHEDULING_INFORMATION(msg_p),m2ap_mbms_scheduling_information_local,sizeof(m2ap_mbms_scheduling_information_t)); else @@ -257,7 +256,7 @@ static uint32_t MCE_app_send_m2ap_session_start_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_MBMS_SESSION_START_REQ); + msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M2AP_MBMS_SESSION_START_REQ); itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; @@ -266,7 +265,7 @@ static uint32_t MCE_app_send_m2ap_session_start_req(instance_t instance){ // // //uint32_t mce_id=0; // MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_MBMS_SESSION_STOP_REQ); +// msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M2AP_MBMS_SESSION_STOP_REQ); // itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // return 0; @@ -275,7 +274,7 @@ static uint32_t MCE_app_send_m2ap_session_start_req(instance_t instance){ // // //uint32_t mce_id=0; // MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_MCE_CONFIGURATION_UPDATE); +// msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M2AP_MCE_CONFIGURATION_UPDATE); // itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // return 0; @@ -284,7 +283,7 @@ static uint32_t MCE_app_send_m2ap_session_start_req(instance_t instance){ // // //uint32_t mce_id=0; // MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_ENB_CONFIGURATION_UPDATE_ACK); +// msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M2AP_ENB_CONFIGURATION_UPDATE_ACK); // itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // return 0; @@ -293,7 +292,7 @@ static uint32_t MCE_app_send_m2ap_session_start_req(instance_t instance){ // // //uint32_t mce_id=0; // MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MCE_APP, M2AP_ENB_CONFIGURATION_UPDATE_FAILURE); +// msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, M2AP_ENB_CONFIGURATION_UPDATE_FAILURE); // itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // return 0; @@ -303,7 +302,7 @@ static uint32_t MCE_app_send_m2ap_session_start_req(instance_t instance){ // // //uint32_t mce_id=0; // MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MCE_APP, MESSAGE_TEST); +// msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, MESSAGE_TEST); // itti_send_msg_to_task (TASK_MME_APP, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // return 0; @@ -313,7 +312,7 @@ static uint32_t MCE_app_send_m2ap_session_start_req(instance_t instance){ // // //uint32_t mce_id=0; // MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MCE_APP, MESSAGE_TEST); +// msg_p = itti_alloc_new_message (TASK_MCE_APP, 0, MESSAGE_TEST); // itti_send_msg_to_task (TASK_M3AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // return 0; @@ -379,7 +378,7 @@ void *MCE_app_task(void *args_p) { do { // Wait for a message itti_receive_msg (TASK_MCE_APP, &msg_p); - instance = ITTI_MSG_INSTANCE (msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: @@ -397,7 +396,7 @@ void *MCE_app_task(void *args_p) { case M3AP_REGISTER_MCE_CNF: //AssertFatal(!NODE_IS_DU(RC.rrc[0]->node_type), "Should not have received S1AP_REGISTER_ENB_CNF\n"); - LOG_I(MCE_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_I(MCE_APP, "[MCE %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), M3AP_REGISTER_MCE_CNF(msg_p).nb_mme); DevAssert(register_mce_pending > 0); register_mce_pending--; @@ -412,7 +411,7 @@ void *MCE_app_task(void *args_p) { if (registered_mce == mce_nb) { /* If all MCE are registered, start L2L1 task */ // MessageDef *msg_init_p; - // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE); + // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, 0, INITIALIZE_MESSAGE); // itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); } else { LOG_W(MCE_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n", @@ -434,7 +433,7 @@ void *MCE_app_task(void *args_p) { case M3AP_MBMS_SESSION_START_REQ: LOG_I(MCE_APP, "Received M3AP_MBMS_SESSION_START_REQ message %s\n", ITTI_MSG_NAME (msg_p)); - //MCE_app_handle_m3ap_mbms_session_start_req(ITTI_MESSAGE_GET_INSTANCE(msg_p)); + //MCE_app_handle_m3ap_mbms_session_start_req(ITTI_MSG_DESTINATION_INSTANCE(msg_p)); if(m2ap_setup_req_local) if (timer_setup (2, 0, TASK_MCE_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL, &mce_scheduling_info_timer_id) < 0) { @@ -445,12 +444,12 @@ void *MCE_app_task(void *args_p) { case M3AP_MBMS_SESSION_STOP_REQ: LOG_I(MCE_APP, "Received M3AP_MBMS_SESSION_STOP_REQ message %s\n", ITTI_MSG_NAME (msg_p)); - MCE_app_handle_m3ap_mbms_session_stop_req(ITTI_MESSAGE_GET_INSTANCE(msg_p)); + MCE_app_handle_m3ap_mbms_session_stop_req(ITTI_MSG_DESTINATION_INSTANCE(msg_p)); break; case M3AP_MBMS_SESSION_UPDATE_REQ: LOG_I(MCE_APP, "Received M3AP_MBMS_SESSION_UPDATE_REQ message %s\n", ITTI_MSG_NAME (msg_p)); - MCE_app_handle_m3ap_mbms_session_update_req(ITTI_MESSAGE_GET_INSTANCE(msg_p)); + MCE_app_handle_m3ap_mbms_session_update_req(ITTI_MSG_DESTINATION_INSTANCE(msg_p)); break; @@ -479,7 +478,7 @@ void *MCE_app_task(void *args_p) { // /* If all MCE cells are registered, start L2L1 task */ // MessageDef *msg_init_p; - // //msg_init_p = itti_alloc_new_message (TASK_MCE_APP, INITIALIZE_MESSAGE); + // //msg_init_p = itti_alloc_new_message (TASK_MCE_APP, 0, INITIALIZE_MESSAGE); // //itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); // } else { @@ -503,7 +502,7 @@ void *MCE_app_task(void *args_p) { case M3AP_DEREGISTERED_MCE_IND: if (EPC_MODE_ENABLED) { - LOG_W(MCE_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_W(MCE_APP, "[MCE %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme); /* TODO handle recovering of registration */ } @@ -621,7 +620,7 @@ void *MCE_app_task(void *args_p) { m2ap_setup_req_local = (m2ap_setup_req_t*)calloc(1,sizeof(m2ap_setup_req_t)); if(m2ap_setup_req_local) memcpy(m2ap_setup_req_local,&M2AP_SETUP_REQ(msg_p),sizeof(m2ap_setup_req_t)); - MCE_app_handle_m2ap_setup_req(ITTI_MESSAGE_GET_INSTANCE(msg_p)); + MCE_app_handle_m2ap_setup_req(ITTI_MSG_DESTINATION_INSTANCE(msg_p)); //MCE_app_send_m2ap_mbms_scheduling_information(0); //if (timer_setup (2, 0, TASK_MCE_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, // NULL, &mce_scheduling_info_timer_id) < 0) { diff --git a/openair2/MCE_APP/mce_config.c b/openair2/MCE_APP/mce_config.c index 975f524ebd..439f2d2061 100644 --- a/openair2/MCE_APP/mce_config.c +++ b/openair2/MCE_APP/mce_config.c @@ -108,7 +108,7 @@ int RCconfig_MCE(void ) { if (address) { MessageDef *message; - AssertFatal((message = itti_alloc_new_message(TASK_MCE_APP, M2AP_MCE_SCTP_REQ))!=NULL,""); + AssertFatal((message = itti_alloc_new_message(TASK_MCE_APP, 0, M2AP_MCE_SCTP_REQ))!=NULL,""); //IPV4_STR_ADDR_TO_INT_NWBO ( address, M2AP_MCE_SCTP_REQ(message).mce_m2_ip_address, "BAD IP ADDRESS FORMAT FOR MCE M2_C !\n" ); M2AP_MCE_SCTP_REQ (message).mce_m2_ip_address.ipv6 = 0; M2AP_MCE_SCTP_REQ (message).mce_m2_ip_address.ipv4 = 1; diff --git a/openair2/NETWORK_DRIVER/LITE/device.c b/openair2/NETWORK_DRIVER/LITE/device.c index 854c3bcc99..59340784c1 100644 --- a/openair2/NETWORK_DRIVER/LITE/device.c +++ b/openair2/NETWORK_DRIVER/LITE/device.c @@ -316,7 +316,11 @@ void oai_nw_drv_change_rx_flags(struct net_device *dev, int flags) } //--------------------------------------------------------------------------- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +void oai_nw_drv_tx_timeout(struct net_device *dev, unsigned int txqueue) +#else void oai_nw_drv_tx_timeout(struct net_device *dev) +#endif { //--------------------------------------------------------------------------- // Transmitter timeout, serious problems. diff --git a/openair2/NETWORK_DRIVER/MESH/common.c b/openair2/NETWORK_DRIVER/MESH/common.c index c5b46440dc..c04acded3e 100644 --- a/openair2/NETWORK_DRIVER/MESH/common.c +++ b/openair2/NETWORK_DRIVER/MESH/common.c @@ -389,36 +389,19 @@ void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct class pdcph.sourceL2Id = 0; pdcph.destinationL2Id = 0; - - -#ifdef PDCP_USE_NETLINK bytes_wrote = nas_netlink_send((char *)&pdcph,NAS_PDCPH_SIZE); #ifdef NAS_DEBUG_SEND printk("[NAS] Wrote %d bytes (header for %d byte skb) to PDCP via netlink\n", bytes_wrote,skb->len); #endif -#else - bytes_wrote = rtf_put(NAS2PDCP_FIFO, &pdcph, NAS_PDCPH_SIZE); -#ifdef NAS_DEBUG_SEND - printk("[NAS] Wrote %d bytes (header for %d byte skb) to PDCP fifo\n", - bytes_wrote,skb->len); -#endif -#endif //PDCP_USE_NETLINK if (bytes_wrote != NAS_PDCPH_SIZE) { printk("NAS_COMMON_QOS_SEND: problem while writing PDCP's header (bytes wrote = %d )\n",bytes_wrote); printk("rb_id %ld, Wrote %d, Header Size %lu\n", pdcph.rb_id , bytes_wrote, NAS_PDCPH_SIZE); -#ifndef PDCP_USE_NETLINK - rtf_reset(NAS2PDCP_FIFO); -#endif //PDCP_USE_NETLINK return; } -#ifdef PDCP_USE_NETLINK bytes_wrote += nas_netlink_send((char *)skb->data,skb->len); -#else - bytes_wrote += rtf_put(NAS2PDCP_FIFO, skb->data, skb->len); -#endif //PDCP_USE_NETLINK if (bytes_wrote != skb->len+NAS_PDCPH_SIZE) { printk("NAS_COMMON_QOS_SEND: Inst %d, RB_ID %ld: problem while writing PDCP's data, bytes_wrote = %d, Data_len %d, PDCPH_SIZE %lu\n", @@ -427,9 +410,6 @@ void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct class bytes_wrote, skb->len, NAS_PDCPH_SIZE); // congestion -#ifndef PDCP_USE_NETLINK - rtf_reset(NAS2PDCP_FIFO); -#endif //PDCP_USE_NETLINK return; } @@ -449,69 +429,6 @@ void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct class #endif } -#ifndef PDCP_USE_NETLINK -//--------------------------------------------------------------------------- -void nas_COMMON_QOS_receive() -{ - //--------------------------------------------------------------------------- - uint8_t sapi; - struct pdcp_data_ind_header_s pdcph; - unsigned char data_buffer[2048]; - struct classifier_entity *rclass; - struct nas_priv *priv; - int bytes_read; - - // Start debug information -#ifdef NAS_DEBUG_RECEIVE - printk("NAS_COMMON_QOS_RECEIVE - begin \n"); -#endif - - // End debug information - - bytes_read = rtf_get(PDCP2PDCP_USE_RT_FIFO,&pdcph, NAS_PDCPH_SIZE); - - while (bytes_read>0) { - if (bytes_read != NAS_PDCPH_SIZE) { - printk("NAS_COMMON_QOS_RECEIVE: problem while reading PDCP header\n"); - return; - } - - priv=netdev_priv(nasdev[pdcph.inst]); - rclass = nas_COMMON_search_class_for_rb(pdcph.rb_id,priv); - - bytes_read+= rtf_get(PDCP2PDCP_USE_RT_FIFO, - data_buffer, - pdcph.data_size); - -#ifdef NAS_DEBUG_RECEIVE - printk("NAS_COMMON_QOS_RECEIVE - Got header for RB %d, Inst %d \n", - pdcph.rb_id, - pdcph.inst); -#endif - - if (rclass) { -#ifdef NAS_DEBUG_RECEIVE - printk("[NAS][COMMON] Found corresponding connection in classifier for RAB\n"); -#endif //NAS_DEBUG_RECEIVE - - nas_COMMON_receive(pdcph.data_size, - (void *)data_buffer, - pdcph.inst, - rclass, - pdcph.rb_id); - } - - bytes_read = rtf_get(PDCP2PDCP_USE_RT_FIFO, &pdcph, NAS_PDCPH_SIZE); - } - - - -#ifdef NAS_DEBUG_RECEIVE - printk("NAS_COMMON_QOS_RECEIVE - end \n"); -#endif -} - -#else void nas_COMMON_QOS_receive(struct nlmsghdr *nlh) { @@ -542,7 +459,6 @@ void nas_COMMON_QOS_receive(struct nlmsghdr *nlh) } } -#endif //PDCP_USE_NETLINK //--------------------------------------------------------------------------- struct cx_entity *nas_COMMON_search_cx(nasLocalConnectionRef_t lcr,struct nas_priv *priv) diff --git a/openair2/NETWORK_DRIVER/MESH/device.c b/openair2/NETWORK_DRIVER/MESH/device.c index 8b95e05cfc..f63408259c 100644 --- a/openair2/NETWORK_DRIVER/MESH/device.c +++ b/openair2/NETWORK_DRIVER/MESH/device.c @@ -53,10 +53,8 @@ struct net_device *nasdev[NB_INSTANCES_MAX]; -#ifdef PDCP_USE_NETLINK extern void nas_netlink_release(void); extern int nas_netlink_init(void); -#endif //int bytes_wrote; //int bytes_read; @@ -82,38 +80,6 @@ int find_inst(struct net_device *dev) //--------------------------------------------------------------------------- -#ifndef PDCP_USE_NETLINK -//void interrupt(void){ -void *nas_interrupt(void) -{ - //--------------------------------------------------------------------------- - uint8_t cxi; - - // struct nas_priv *priv=netdev_priv(dev_id); - // unsigned int flags; - - // priv->lock = SPIN_LOCK_UNLOCKED; - -#ifdef DEBUG_INTERRUPT - printk("INTERRUPT - begin\n"); -#endif - // spin_lock_irqsave(&priv->lock,flags); - cxi=0; - // mesh_GC_receive(); - // mesh_DC_receive(naspriv->cx+cxi); -#ifndef PDCP_USE_NETLINK - nas_COMMON_QOS_receive(); -#endif - // spin_unlock_irqrestore(&priv->lock,flags); -#ifdef DEBUG_INTERRUPT - printk("INTERRUPT: end\n"); -#endif - // return 0; - return NULL; -} -#endif //NETLINK - -//--------------------------------------------------------------------------- // Called by ifconfig when the device is activated by ifconfig int nas_open(struct net_device *dev) { @@ -121,15 +87,6 @@ int nas_open(struct net_device *dev) printk("OPEN: begin\n"); // MOD_INC_USE_COUNT; // Address has already been set at init -#ifndef PDCP_USE_NETLINK - - if (pdcp_2_nas_irq==-EBUSY) { - printk("OPEN: irq failure\n"); - return -EBUSY; - } - -#endif //PDCP_USE_NETLINK - /* netif_start_queue(dev); // @@ -297,7 +254,11 @@ int nas_change_mtu(struct net_device *dev, int mtu) } //--------------------------------------------------------------------------- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +void nas_tx_timeout(struct net_device *dev, unsigned int txqueue) +#else void nas_tx_timeout(struct net_device *dev) +#endif { //--------------------------------------------------------------------------- // Transmitter timeout, serious problems. @@ -324,7 +285,7 @@ static const struct net_device_ops nasmesh_netdev_ops = { .ndo_set_mac_address = NULL, .ndo_set_config = nas_set_config, .ndo_do_ioctl = nas_CTL_ioctl, -#if (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1797) +#if (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1797 && LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0)) .extended.ndo_change_mtu = nas_change_mtu, #else .ndo_change_mtu = nas_change_mtu, @@ -445,16 +406,6 @@ int init_module (void) printk("Starting NASMESH, number of IMEI paramters %d, IMEI %X%X\n",m_arg,nas_IMEI[0],nas_IMEI[1]); -#ifndef PDCP_USE_NETLINK - - if (pdcp_2_nas_irq == -EBUSY || pdcp_2_nas_irq == -EINVAL) { - printk("[NAS][INIT] No interrupt resource available\n"); - return -EBUSY; - } else - printk("[NAS][INIT]: Interrupt %d\n", pdcp_2_nas_irq); - -#endif //NETLINK - for (inst=0; instirq, NULL); - // End IRQ linux - - } - -#else // NETLINK - - - -#endif //NETLINK - for (inst=0; instlength); #endif ++cx->retry; -#ifdef PDCP_USE_NETLINK -#else - // bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); -#endif cx->countimer=gpriv->timer_establishment; if (bytes_wrote==p->length) { @@ -353,11 +349,6 @@ int nas_mesh_DC_send_cx_release_request(struct cx_entity *cx, p->length = NAS_TL_SIZE + sizeof(struct NASConnReleaseReq); p->nasUEDCPrimitive.conn_release_req.localConnectionRef = cx->lcr; p->nasUEDCPrimitive.conn_release_req.releaseCause = NAS_CX_RELEASE_UNDEF_CAUSE; -#ifdef PDCP_USE_NETLINK - -#else - // bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); -#endif if (bytes_wrote==p->length) { cx->state=NAS_IDLE; @@ -441,22 +432,12 @@ void nas_mesh_DC_send_sig_data_request(struct sk_buff *skb, p->nasUEDCPrimitive.data_transfer_req.localConnectionRef = cx->lcr; p->nasUEDCPrimitive.data_transfer_req.priority = 3; // TBD p->nasUEDCPrimitive.data_transfer_req.nasDataLength = (skb->len)+1; //adds category character -#ifdef PDCP_USE_NETLINK -#else - // bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); -#endif if (bytes_wrote!=p->length) { printk("NAS_MESH_DC_SEND_SIG: Header sent failure in DC-FIFO\n"); return; } -#ifdef PDCP_USE_NETLINK -#else - // bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], &data_type, 1); - // bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], skb->data, skb->len); -#endif - if (bytes_wrote != p->length + skb->len + 1) { printk("NAS_MESH_DC_SEND_SIG: Data sent failure in DC-FIFO\n"); return; @@ -511,22 +492,12 @@ void nas_mesh_DC_send_peer_sig_data_request(struct cx_entity *cx, uint8_t sig_ca p->nasUEDCPrimitive.data_transfer_req.localConnectionRef = cx->lcr; p->nasUEDCPrimitive.data_transfer_req.priority = 3; // TBD p->nasUEDCPrimitive.data_transfer_req.nasDataLength = (nas_length)+1; //adds category character -#ifdef PDCP_USE_NETLINK -#else - // bytes_wrote = rtf_put(cx->sap[NAS_DC_INPUT_SAPI], p, p->length); -#endif if (bytes_wrote!=p->length) { printk("NAS_MESH_DC_PEER_SEND_SIG: Header sent failure in DC-FIFO\n"); return; } -#ifdef PDCP_USE_NETLINK -#else - // bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], &data_type, 1); - // bytes_wrote += rtf_put(cx->sap[NAS_DC_INPUT_SAPI], (char *)nas_data, nas_length); -#endif - if (bytes_wrote != p->length + nas_length + 1) { printk("NAS_MESH_DC_PEER_SEND_SIG: Data sent failure in DC-FIFO\n"); return; @@ -665,9 +636,6 @@ void nas_mesh_DC_decode_sig_data_ind(struct cx_entity *cx, struct nas_ue_dc_elem } // End debug information -#ifndef PDCP_USE_NETLINK - // nas_COMMON_receive(p->length, p->nasUEDCPrimitive.data_transfer_ind.nasDataLength, cx->sap[NAS_DC_OUTPUT_SAPI]); -#endif #ifdef NAS_DEBUG_DC printk("NAS_MESH_DC_RECEIVE: DATA_TRANSFER_IND reception\n"); printk(" Local Connection reference %u\n",p->nasUEDCPrimitive.data_transfer_ind.localConnectionRef); @@ -842,20 +810,12 @@ int nas_mesh_DC_receive(struct cx_entity *cx,struct nas_priv *gpriv) } // End debug information -#ifdef PDCP_USE_NETLINK -#else - // bytes_read = rtf_get(cx->sap[NAS_DC_OUTPUT_SAPI] , gpriv->rbuffer, NAS_TL_SIZE); -#endif if (bytes_read>0) { struct nas_ue_dc_element *p; p= (struct nas_ue_dc_element *)(gpriv->rbuffer); //get the rest of the primitive -#ifdef PDCP_USE_NETLINK -#else - // bytes_read += rtf_get(cx->sap[NAS_DC_OUTPUT_SAPI], (uint8_t *)p+NAS_TL_SIZE, p->length-NAS_TL_SIZE); -#endif if (bytes_read!=p->length) { printk("NAS_MESH_DC_RECEIVE: Problem while reading primitive header\n"); @@ -886,6 +846,7 @@ int nas_mesh_DC_receive(struct cx_entity *cx,struct nas_priv *gpriv) switch (cx->state) { case NAS_CX_RELEASING_FAILURE: cx->retry=0; + /* fallthrough */ case NAS_CX_DCH: nas_mesh_DC_decode_cx_loss_ind(cx,p); // process message @@ -981,19 +942,11 @@ int nas_mesh_GC_receive(struct nas_priv *gpriv) #ifdef NAS_DEBUG_GC printk("NAS_MESH_GC_RECEIVE - begin \n"); #endif -#ifdef PDCP_USE_NETLINK -#else - // bytes_read = rtf_get(gpriv->sap[NAS_GC_SAPI], gpriv->rbuffer, NAS_TL_SIZE); -#endif if (bytes_read>0) { struct nas_ue_gc_element *p; p= (struct nas_ue_gc_element *)(gpriv->rbuffer); //get the rest of the primitive -#ifdef PDCP_USE_NETLINK -#else - // bytes_read += rtf_get(gpriv->sap[NAS_GC_SAPI], (uint8_t *)p+NAS_TL_SIZE, p->length-NAS_TL_SIZE); -#endif if (bytes_read!=p->length) { printk("NAS_MESH_GC_RECEIVE: Problem while reading primitive's header\n"); @@ -1003,10 +956,6 @@ int nas_mesh_GC_receive(struct nas_priv *gpriv) // start decoding message switch (p->type) { case INFO_BROADCAST_IND : -#ifdef PDCP_USE_NETLINK -#else - // bytes_read += rtf_get(gpriv->sap[NAS_GC_SAPI], (uint8_t *)p+p->length, p->nasUEGCPrimitive.broadcast_ind.nasDataLength); -#endif if (bytes_read!=p->length+p->nasUEGCPrimitive.broadcast_ind.nasDataLength) { printk("NAS_MESH_GC_RECEIVE: INFO_BROADCAST_IND reception, Problem while reading primitive's data\n"); return bytes_read; diff --git a/openair2/NETWORK_DRIVER/MESH/proto_extern.h b/openair2/NETWORK_DRIVER/MESH/proto_extern.h index ac92b2f8bd..332540f3b7 100644 --- a/openair2/NETWORK_DRIVER/MESH/proto_extern.h +++ b/openair2/NETWORK_DRIVER/MESH/proto_extern.h @@ -110,14 +110,6 @@ void nas_COMMON_del_send(struct sk_buff *skb, struct cx_entity *cx, struct classifier_entity *gc,int inst, struct nas_priv *gpriv); -#ifndef PDCP_USE_NETLINK -/** -\fn void nas_COMMON_QOS_receive() -\brief Retrieve PDU from PDCP for connection - */ -void nas_COMMON_QOS_receive(void); -#endif //PDCP_USE_NETLINK - /** \fn struct rb_entity *nas_COMMON_add_rb(struct cx_entity *cx, nasRadioBearerId_t rabi, nasQoSTrafficClass_t qos) \brief Add a radio-bearer descriptor @@ -168,7 +160,6 @@ struct classifier_entity */ void nas_COMMON_flush_rb(struct cx_entity *cx); -#ifdef PDCP_USE_NETLINK /** \fn int nas_netlink_send(unsigned char *data,unsigned int len) \brief Request the transfer of data by PDCP via netlink socket @@ -185,7 +176,6 @@ int nas_netlink_send(unsigned char *data,unsigned int len); */ void nas_COMMON_QOS_receive(struct nlmsghdr *nlh); -#endif //PDCP_USE_NETLINK //nasmesh.c /** @@ -305,13 +295,10 @@ void nas_tool_print_buffer(char * buffer,int length); void nas_print_rb_entity(struct rb_entity *rb); void nas_print_classifier(struct classifier_entity *gc); -#ifdef PDCP_USE_NETLINK // nas_netlink.c void nas_netlink_release(void); int nas_netlink_init(void); -#endif - /** @} */ #endif diff --git a/openair2/NETWORK_DRIVER/UE_IP/common.c b/openair2/NETWORK_DRIVER/UE_IP/common.c index 86e00ef674..05118a5f6b 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/common.c +++ b/openair2/NETWORK_DRIVER/UE_IP/common.c @@ -287,18 +287,6 @@ ue_ip_common_ip2wireless( printk("[UE_IP_DRV][%s] Dest %d.%d.%d.%d\n",__FUNCTION__, dst_addr[0],dst_addr[1],dst_addr[2],dst_addr[3]); } - // modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator start -#ifdef UESIM_EXPANSION - - if ((src_addr[3] - 2)> instP) { - pdcph.inst = src_addr[3] - 2; - printk("[UE_IP_DRV] change INST from %d to %d\n",instP, pdcph.inst); - instP = src_addr[3] - 2; - priv_p=netdev_priv(ue_ip_dev[instP]); - } - -#endif - // modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator end //get Ipv4 address and pass to PCDP header printk("[UE_IP_DRV] source Id: 0x%08x\n",pdcph.sourceL2Id ); printk("[UE_IP_DRV] destinationL2Id Id: 0x%08x\n",pdcph.destinationL2Id ); diff --git a/openair2/NETWORK_DRIVER/UE_IP/device.c b/openair2/NETWORK_DRIVER/UE_IP/device.c index 32f9442747..0ff9a73925 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/device.c +++ b/openair2/NETWORK_DRIVER/UE_IP/device.c @@ -302,7 +302,13 @@ void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP) { } //--------------------------------------------------------------------------- -void ue_ip_tx_timeout(struct net_device *dev_pP) { + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +void ue_ip_tx_timeout(struct net_device *dev_pP, unsigned int txqueue) +#else +void ue_ip_tx_timeout(struct net_device *dev_pP) +#endif +{ //--------------------------------------------------------------------------- // Transmitter timeout, serious problems. ue_ip_priv_t *priv_p = netdev_priv(dev_pP); diff --git a/openair2/NETWORK_DRIVER/UE_IP/local.h b/openair2/NETWORK_DRIVER/UE_IP/local.h index 5532de9573..46e44f0040 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/local.h +++ b/openair2/NETWORK_DRIVER/UE_IP/local.h @@ -55,10 +55,6 @@ #include "platform_types.h" #include "sap.h" -#ifndef MAKE_VERSION - #define MAKE_VERSION(a,b,c) ((a)*256+(b)*16+(c)) -#endif - typedef struct ue_ip_priv_s { int irq; int rx_flags; diff --git a/openair2/NETWORK_DRIVER/UE_IP/netlink.c b/openair2/NETWORK_DRIVER/UE_IP/netlink.c index 658ae19aba..b3829c51d1 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/netlink.c +++ b/openair2/NETWORK_DRIVER/UE_IP/netlink.c @@ -39,6 +39,7 @@ #include "local.h" #include "proto_extern.h" +MODULE_LICENSE("OAI"); #define OAI_IP_DRIVER_NETLINK_ID 31 #define NL_DEST_PID 1 diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index ec969c6741..cb5bef5ab0 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -30,171 +30,177 @@ * \warning */ -#include "openair1/PHY/defs_eNB.h" -#include "openair1/PHY/phy_extern.h" #include "openair1/SCHED_NR/fapi_nr_l1.h" #include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "common/ran_context.h" #include "executables/softmodem-common.h" +#include "nfapi/oai_integration/vendor_ext.h" #define MAX_IF_MODULES 100 +//#define UL_HARQ_PRINT -NR_IF_Module_t *if_inst[MAX_IF_MODULES]; -NR_Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; - +static NR_IF_Module_t *nr_if_inst[MAX_IF_MODULES]; +static NR_Sched_Rsp_t NR_Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind); extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); +extern int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); +extern int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); +extern int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); +extern int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); +extern int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); +extern int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); extern uint8_t nfapi_mode; extern uint16_t sf_ahead; extern uint16_t sl_ahead; void handle_nr_rach(NR_UL_IND_t *UL_info) { - if (UL_info->rach_ind.number_of_pdus>0) { - AssertFatal(UL_info->rach_ind.number_of_pdus==1,"More than 1 RACH pdu not supported\n"); - UL_info->rach_ind.number_of_pdus=0; - LOG_D(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); - - if (UL_info->rach_ind.pdu_list[0].num_preamble>0) - AssertFatal(UL_info->rach_ind.pdu_list[0].num_preamble==1, - "More than 1 preamble not supported\n"); - - nr_initiate_ra_proc(UL_info->module_id, - UL_info->CC_id, - UL_info->rach_ind.sfn, - UL_info->rach_ind.slot, - UL_info->rach_ind.pdu_list[0].preamble_list[0].preamble_index, - UL_info->rach_ind.pdu_list[0].freq_index, - UL_info->rach_ind.pdu_list[0].symbol_index, - UL_info->rach_ind.pdu_list[0].preamble_list[0].timing_advance); - + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->rach_ind.number_of_pdus>0) { + LOG_D(PHY,"UL_info->UL_info->rach_ind.number_of_pdus:%d SFN/Slot:%d.%d \n", UL_info->rach_ind.number_of_pdus, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); + oai_nfapi_nr_rach_indication(&UL_info->rach_ind); + UL_info->rach_ind.number_of_pdus = 0; + } + } + else{ + if (UL_info->rach_ind.number_of_pdus>0) { + LOG_D(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); + int npdus = UL_info->rach_ind.number_of_pdus; + for(int i = 0; i < npdus; i++) { + UL_info->rach_ind.number_of_pdus--; + if (UL_info->rach_ind.pdu_list[i].num_preamble>0) + AssertFatal(UL_info->rach_ind.pdu_list[i].num_preamble==1, + "More than 1 preamble not supported\n"); + + nr_initiate_ra_proc(UL_info->module_id, + UL_info->CC_id, + UL_info->rach_ind.sfn, + UL_info->rach_ind.slot, + UL_info->rach_ind.pdu_list[i].preamble_list[0].preamble_index, + UL_info->rach_ind.pdu_list[i].freq_index, + UL_info->rach_ind.pdu_list[i].symbol_index, + UL_info->rach_ind.pdu_list[i].preamble_list[0].timing_advance); + } + } } } -void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl) { - // TODO - int max_harq_rounds = 4; // TODO define macro - int num_ucis = UL_info->uci_ind.num_ucis; - nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; +void handle_nr_uci(NR_UL_IND_t *UL_info) +{ + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->uci_ind.num_ucis>0) { + LOG_D(PHY,"PNF Sending UL_info->num_ucis:%d PDU_type: %d, SFN/SF:%d.%d \n", UL_info->uci_ind.num_ucis, UL_info->uci_ind.uci_list[0].pdu_type ,UL_info->frame, UL_info->slot); + oai_nfapi_nr_uci_indication(&UL_info->uci_ind); + UL_info->uci_ind.num_ucis = 0; + } + } + else{ + const module_id_t mod_id = UL_info->module_id; + const frame_t frame = UL_info->frame; + const sub_frame_t slot = UL_info->slot; + int num_ucis = UL_info->uci_ind.num_ucis; + nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; + LOG_D(MAC,"handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); + for (int i = 0; i < num_ucis; i++) { + switch (uci_list[i].pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__); + break; - for (int i = 0; i < num_ucis; i++) { - switch (uci_list[i].pdu_type) { - case NFAPI_NR_UCI_PDCCH_PDU_TYPE: break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - if (get_softmodem_params()->phy_test == 0) { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; - // handle harq - int harq_idx_s = 0; - // iterate over received harq bits - for (int harq_bit = 0; harq_bit < uci_pdu->harq->num_harq; harq_bit++) { - // search for the right harq process - for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) { - if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { - if (uci_pdu->harq->harq_list[harq_bit].harq_value == 0) - sched_ctrl->harq_processes[harq_idx].round++; - if ((uci_pdu->harq->harq_list[harq_bit].harq_value == 1) || - (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds)) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - harq_idx_s = harq_idx + 1; - break; - } - // if gNB fails to receive a ACK/NACK - else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) && - (sched_ctrl->harq_processes[harq_idx].is_waiting)) { - sched_ctrl->harq_processes[harq_idx].round++; - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - } - } - } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; + handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); + break; } - break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; + handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); + break; + } + } + LOG_D(MAC, "UCI handled \n"); } } UL_info->uci_ind.num_ucis = 0; } - -void handle_nr_ulsch(NR_UL_IND_t *UL_info) { - if(nfapi_mode == 1) { +void handle_nr_ulsch(NR_UL_IND_t *UL_info) +{ + if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->crc_ind.number_crcs>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); - // oai_nfapi_crc_indication(&UL_info->crc_ind); - + LOG_D(PHY,"UL_info->UL_info->crc_ind.number_crcs:%d CRC_IND:SFN/Slot:%d.%d\n", UL_info->crc_ind.number_crcs, UL_info->crc_ind.sfn, UL_info->crc_ind.slot); + oai_nfapi_nr_crc_indication(&UL_info->crc_ind); UL_info->crc_ind.number_crcs = 0; } if (UL_info->rx_ind.number_of_pdus>0) { - //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); - // oai_nfapi_rx_ind(&UL_info->rx_ind); + LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/Slot:%d.%d \n", UL_info->rx_ind.number_of_pdus, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); + oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); UL_info->rx_ind.number_of_pdus = 0; } - } else { - - if (UL_info->rx_ind.number_of_pdus>0 && UL_info->crc_ind.number_crcs>0) { - for (int i=0; irx_ind.number_of_pdus; i++) { - for (int j=0; jcrc_ind.number_crcs; j++) { + } + else{ + if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { + for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { + for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { // find crc_indication j corresponding rx_indication i - LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].rx_ue_information.rnti:%04x UL_info->rx_ind.rx_indication_body.rx_pdu_list[%d].rx_ue_information.rnti:%04x\n", j, - UL_info->crc_ind.crc_list[j].rnti, i, UL_info->rx_ind.pdu_list[i].rnti); + const nfapi_nr_rx_data_pdu_t *rx = &UL_info->rx_ind.pdu_list[i]; + const nfapi_nr_crc_t *crc = &UL_info->crc_ind.crc_list[j]; + LOG_D(PHY, + "UL_info->crc_ind.pdu_list[%d].rnti:%04x " + "UL_info->rx_ind.pdu_list[%d].rnti:%04x\n", + j, + crc->rnti, + i, + rx->rnti); - if (UL_info->crc_ind.crc_list[j].rnti == - UL_info->rx_ind.pdu_list[i].rnti) { - LOG_D(PHY, "UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].crc_indication_rel8.crc_flag:%d\n", j, UL_info->crc_ind.crc_list[j].tb_crc_status); + if (crc->rnti != rx->rnti) + continue; - if (UL_info->crc_ind.crc_list[j].tb_crc_status == 1) { // CRC error indication - LOG_D(MAC,"Frame %d, Slot %d Calling rx_sdu (CRC error) \n",UL_info->frame,UL_info->slot); + LOG_D(MAC, + "%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n", + UL_info->frame, + UL_info->slot, + crc->tb_crc_status ? "error" : "ok", + crc->tb_crc_status); - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, //UL_info->frame, - UL_info->rx_ind.slot, //UL_info->slot, - UL_info->rx_ind.pdu_list[i].rnti, - (uint8_t *)NULL, - UL_info->rx_ind.pdu_list[i].pdu_length, - UL_info->rx_ind.pdu_list[i].timing_advance, - UL_info->rx_ind.pdu_list[i].ul_cqi); - } else { - LOG_D(MAC,"Frame %d, Slot %d Calling rx_sdu (CRC ok) \n",UL_info->frame,UL_info->slot); - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, //UL_info->frame, - UL_info->rx_ind.slot, //UL_info->slot, - UL_info->rx_ind.pdu_list[i].rnti, - UL_info->rx_ind.pdu_list[i].pdu, - UL_info->rx_ind.pdu_list[i].pdu_length, - UL_info->rx_ind.pdu_list[i].timing_advance, - UL_info->rx_ind.pdu_list[i].ul_cqi); - } - break; - } + /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ + nr_rx_sdu(UL_info->module_id, + UL_info->CC_id, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + rx->rnti, + crc->tb_crc_status ? NULL : rx->pdu, + rx->pdu_length, + rx->timing_advance, + rx->ul_cqi, + rx->rssi); + handle_nr_ul_harq(UL_info->CC_id, UL_info->module_id, UL_info->frame, UL_info->slot, crc); + break; } // for (j=0;jcrc_ind.number_crcs;j++) } // for (i=0;irx_ind.number_of_pdus;i++) - UL_info->crc_ind.number_crcs=0; + UL_info->crc_ind.number_crcs = 0; UL_info->rx_ind.number_of_pdus = 0; - } - else if (UL_info->rx_ind.number_of_pdus!=0 || UL_info->crc_ind.number_crcs!=0) { - LOG_E(PHY,"hoping not to have mis-match between CRC ind and RX ind - hopefully the missing message is coming shortly rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n", - UL_info->rx_ind.number_of_pdus, UL_info->rx_ind.sfn, UL_info->rx_ind.slot, - UL_info->crc_ind.number_crcs, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); + } else if (UL_info->rx_ind.number_of_pdus != 0 + || UL_info->crc_ind.number_crcs != 0) { + LOG_E(PHY, + "hoping not to have mis-match between CRC ind and RX ind - " + "hopefully the missing message is coming shortly " + "rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n", + UL_info->rx_ind.number_of_pdus, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + UL_info->crc_ind.number_crcs, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot); } } } @@ -206,16 +212,23 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { #endif module_id_t module_id = UL_info->module_id; int CC_id = UL_info->CC_id; - NR_Sched_Rsp_t *sched_info = &Sched_INFO[module_id][CC_id]; - NR_IF_Module_t *ifi = if_inst[module_id]; + NR_Sched_Rsp_t *sched_info = &NR_Sched_INFO[module_id][CC_id]; + NR_IF_Module_t *ifi = nr_if_inst[module_id]; gNB_MAC_INST *mac = RC.nrmac[module_id]; - LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rach_pdus:%d rx_ind:%d crcs:%d]\n", UL_info->frame,UL_info->slot, module_id,CC_id, UL_info->rach_ind.number_of_pdus, UL_info->rx_ind.number_of_pdus, UL_info->crc_ind.number_crcs); - if (nfapi_mode != 1) { + handle_nr_rach(UL_info); + + handle_nr_uci(UL_info); + // clear UL DCI prior to handling ULSCH + mac->UL_dci_req[CC_id].numPdus = 0; + handle_nr_ulsch(UL_info); + + if (NFAPI_MODE != NFAPI_MODE_PNF) { + if (ifi->CC_mask==0) { ifi->current_frame = UL_info->frame; ifi->current_slot = UL_info->slot; @@ -225,17 +238,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } ifi->CC_mask |= (1<frame,UL_info->slot); - handle_nr_rach(UL_info); - handle_nr_uci(UL_info, &mac->UE_list.UE_sched_ctrl[0]); - // clear HI prior to handling ULSCH - mac->UL_dci_req[CC_id].numPdus = 0; - handle_nr_ulsch(UL_info); - - if (nfapi_mode != 1) { if (ifi->CC_mask == ((1<config[CC_id]; int spf = get_spf(cfg); gNB_dlsch_ulsch_scheduler(module_id, - UL_info->frame, - UL_info->slot, (UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%spf); @@ -258,13 +259,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { sched_info->DL_req = &mac->DL_req[CC_id]; sched_info->UL_dci_req = &mac->UL_dci_req[CC_id]; - if ((mac->common_channels[CC_id].ServingCellConfigCommon->tdd_UL_DL_ConfigurationCommon==NULL) || - (is_nr_UL_slot(mac->common_channels[CC_id].ServingCellConfigCommon,UL_info->slot)>0)) { - //printf("NR_UL_indication: this is an UL slot. UL_info: frame %d, slot %d. UL_tti_req: frame %d, slot %d\n",UL_info->frame,UL_info->slot,mac->UL_tti_req[CC_id].SFN,mac->UL_tti_req[CC_id].Slot); - sched_info->UL_tti_req = &mac->UL_tti_req[CC_id]; - } - else - sched_info->UL_tti_req = NULL; + sched_info->UL_tti_req = mac->UL_tti_req[CC_id]; sched_info->TX_req = &mac->TX_req[CC_id]; #ifdef DUMP_FAPI @@ -291,17 +286,17 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { AssertFatal(Mod_id %d\n",Mod_id,MAX_IF_MODULES); LOG_I(PHY,"Installing callbacks for IF_Module - UL_indication\n"); - if (if_inst[Mod_id]==NULL) { - if_inst[Mod_id] = (NR_IF_Module_t*)malloc(sizeof(NR_IF_Module_t)); - memset((void*)if_inst[Mod_id],0,sizeof(NR_IF_Module_t)); + if (nr_if_inst[Mod_id]==NULL) { + nr_if_inst[Mod_id] = (NR_IF_Module_t*)malloc(sizeof(NR_IF_Module_t)); + memset((void*)nr_if_inst[Mod_id],0,sizeof(NR_IF_Module_t)); - LOG_I(MAC,"Allocating shared L1/L2 interface structure for instance %d @ %p\n",Mod_id,if_inst[Mod_id]); + LOG_I(MAC,"Allocating shared L1/L2 interface structure for instance %d @ %p\n",Mod_id,nr_if_inst[Mod_id]); - if_inst[Mod_id]->CC_mask=0; - if_inst[Mod_id]->NR_UL_indication = NR_UL_indication; - AssertFatal(pthread_mutex_init(&if_inst[Mod_id]->if_mutex,NULL)==0, - "allocation of if_inst[%d]->if_mutex fails\n",Mod_id); + nr_if_inst[Mod_id]->CC_mask=0; + nr_if_inst[Mod_id]->NR_UL_indication = NR_UL_indication; + AssertFatal(pthread_mutex_init(&nr_if_inst[Mod_id]->if_mutex,NULL)==0, + "allocation of nr_if_inst[%d]->if_mutex fails\n",Mod_id); } - return if_inst[Mod_id]; + return nr_if_inst[Mod_id]; } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index e63f93b028..66c7870f80 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -42,10 +42,16 @@ #define MAX_IF_MODULES 100 +const char *dl_indication_type[] = {"MIB", "SIB", "DLSCH", "DCI", "RAR"}; + static nr_ue_if_module_t *nr_ue_if_module_inst[MAX_IF_MODULES]; // L2 Abstraction Layer -int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t *pduP, unsigned int additional_bits, uint32_t ssb_index, uint32_t ssb_length, uint16_t cell_id){ +int handle_bcch_bch(module_id_t module_id, int cc_id, + unsigned int gNB_index, uint8_t *pduP, + unsigned int additional_bits, + uint32_t ssb_index, uint32_t ssb_length, + uint16_t ssb_start_subcarrier, uint16_t cell_id){ return nr_ue_decode_mib(module_id, cc_id, @@ -53,71 +59,74 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, ui additional_bits, ssb_length, // Lssb = 64 is not support ssb_index, - pduP, + pduP, + ssb_start_subcarrier, cell_id); } // L2 Abstraction Layer -int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, uint8_t *pduP, uint32_t pdu_len){ - - return 0; +int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len){ + return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, ack_nack, pduP, pdu_len); } + // L2 Abstraction Layer -int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, fapi_nr_dci_indication_pdu_t *dci){ +int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci){ - //printf("handle_dci: rnti %x,dci_type %d\n",rnti,dci_type); - return nr_ue_process_dci_indication_pdu(module_id, cc_id, gNB_index, dci); + return nr_ue_process_dci_indication_pdu(module_id, cc_id, gNB_index, frame, slot, dci); } -// L2 Abstraction Layer -int8_t handle_dlsch (module_id_t module_id, int cc_id, uint8_t gNB_index, fapi_nr_dci_indication_t *dci_ind, uint8_t *pduP, uint32_t pdu_len, frame_t frame, int slot, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ - LOG_D(MAC, "handle_dlsch at MAC layer \n"); - //if (IS_SOFTMODEM_NOS1 || IS_SOFTMODEM_RFSIM) - // sdu should be processed even when is S1 mode because data and timing advance updates are transmitted by the UE - nr_ue_send_sdu(module_id, cc_id, frame, slot, - pduP, - pdu_len, - gNB_index, - ul_time_alignment); +// L2 Abstraction Layer +// Note: sdu should always be processed because data and timing advance updates are transmitted by the UE +int8_t handle_dlsch(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ + + update_harq_status(dl_info->module_id, + dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid, + dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack); + if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack) + nr_ue_send_sdu(dl_info, ul_time_alignment, pdu_id); return 0; - /* - return nr_ue_process_dlsch(module_id, - cc_id, - gNB_index, - dci_ind, - pduP, - pdu_len); - */ } -int8_t handle_rar (nr_downlink_indication_t *dl_info){ +void update_harq_status(module_id_t module_id, uint8_t harq_pid, uint8_t ack_nack) { - LOG_D(MAC, "handling RAR at MAC layer \n"); - nr_process_rar (dl_info); - return 0; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid]; + if (current_harq->active) { + current_harq->ack = ack_nack; + current_harq->ack_received = true; + LOG_D(PHY,"Updating harq_status for harq_id %d,ack/nak %d\n",harq_pid,current_harq->ack); + } + else { + //shouldn't get here + LOG_E(MAC, "Trying to process acknack for an inactive harq process (%d)\n", harq_pid); + } } + int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ NR_UE_L2_STATE_t ret; module_id_t module_id = ul_info->module_id; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - // clean previous FAPI messages - mac->tx_request.number_of_pdus = 0; - mac->ul_config_request.number_pdus = 0; - mac->dl_config_request.number_pdus = 0; - // clean previous FAPI messages - - ret = nr_ue_scheduler(NULL, ul_info); - - if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && get_softmodem_params()->do_ra){ - nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx); + if (ul_info->ue_sched_mode == ONLY_PUSCH) { + ret = nr_ue_scheduler(NULL, ul_info); + return 0; } + else if (ul_info->ue_sched_mode == SCHED_ALL) + ret = nr_ue_scheduler(NULL, ul_info); + + NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon = mac->scc != NULL ? mac->scc->tdd_UL_DL_ConfigurationCommon : mac->scc_SIB->tdd_UL_DL_ConfigurationCommon; + + if (is_nr_UL_slot(tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type) && !get_softmodem_params()->phy_test) + nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->thread_id); + + if (is_nr_UL_slot(tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type)) + nr_ue_pucch_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->thread_id); switch(ret){ case UE_CONNECTION_OK: @@ -132,8 +141,6 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ break; } - mac->if_module->scheduled_response(&mac->scheduled_response); - return 0; } @@ -144,91 +151,70 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ module_id_t module_id = dl_info->module_id; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; - + if (!dl_info->dci_ind && !dl_info->rx_ind) { // UL indication to schedule DCI reception nr_ue_scheduler(dl_info, NULL); } else { // UL indication after reception of DCI or DL PDU - dl_config->number_pdus = 0; - ul_config->number_pdus = 0; - //hook up pointers - mac->scheduled_response.dl_config = dl_config; - mac->scheduled_response.ul_config = ul_config; - mac->scheduled_response.tx_request = &mac->tx_request; - mac->scheduled_response.module_id = dl_info->module_id; - mac->scheduled_response.CC_id = dl_info->cc_id; - mac->scheduled_response.frame = dl_info->frame; - mac->scheduled_response.slot = dl_info->slot; - if(dl_info->dci_ind != NULL){ LOG_D(MAC,"[L2][IF MODULE][DL INDICATION][DCI_IND]\n"); for(i=0; idci_ind->number_of_dcis; ++i){ LOG_D(MAC,">>>NR_IF_Module i=%d, dl_info->dci_ind->number_of_dcis=%d\n",i,dl_info->dci_ind->number_of_dcis); - - ret_mask |= (handle_dci(dl_info->module_id, + nr_scheduled_response_t scheduled_response; + int8_t ret = handle_dci(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - dl_info->dci_ind->dci_list+i)<< FAPI_NR_DCI_IND); + dl_info->frame, + dl_info->slot, + dl_info->dci_ind->dci_list+i); - AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is void!\n" ); - nr_ue_if_module_inst[module_id]->scheduled_response(&mac->scheduled_response); + ret_mask |= (ret << FAPI_NR_DCI_IND); + if (ret >= 0) { + AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is NULL!\n" ); + AssertFatal( nr_ue_if_module_inst[module_id]->scheduled_response != NULL, "scheduled_response is NULL!\n" ); + fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, dl_info->module_id, dl_info->cc_id, dl_info->frame, dl_info->slot, dl_info->thread_id); + nr_ue_if_module_inst[module_id]->scheduled_response(&scheduled_response); + } } } if(dl_info->rx_ind != NULL){ - LOG_D(MAC,"[L2][IF MODULE][DL INDICATION][RX_IND], Number of PDUs: %d \n", dl_info->rx_ind->number_pdus); - for(i=0; irx_ind->number_pdus; ++i){ + LOG_D(MAC, "In %s sending DL indication to MAC. 1 PDU type %s of %d total number of PDUs \n", + __FUNCTION__, + dl_indication_type[dl_info->rx_ind->rx_indication_body[i].pdu_type - 1], + dl_info->rx_ind->number_pdus); + switch(dl_info->rx_ind->rx_indication_body[i].pdu_type){ + case FAPI_NR_RX_PDU_TYPE_SSB: + mac->ssb_rsrp_dBm = (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.rsrp_dBm; + ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.additional_bits, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_index, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_length, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_start_subcarrier, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; - case FAPI_NR_RX_PDU_TYPE_MIB: - ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.additional_bits, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.ssb_index, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.ssb_length, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_MIB; - - LOG_D(MAC,"[L2][IF MODULE][DL INDICATION][RX_IND], MIB case Number of PDUs: %d \n", dl_info->rx_ind->number_pdus); - - break; - - case FAPI_NR_RX_PDU_TYPE_SIB: - - ret_mask |= (handle_bcch_dlsch(dl_info->module_id, - dl_info->cc_id, dl_info->gNB_index, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.sibs_mask, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->sib_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; - - break; - - case FAPI_NR_RX_PDU_TYPE_DLSCH: - - ret_mask |= (handle_dlsch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - dl_info->dci_ind, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu_length, - dl_info->frame, - dl_info->slot, - ul_time_alignment)) << FAPI_NR_RX_PDU_TYPE_DLSCH; - - LOG_D(MAC,"[L2][IF MODULE][DL INDICATION][RX_IND], DLSCH case Number of PDUs: %d \n", dl_info->rx_ind->number_pdus); - - break; - - case FAPI_NR_RX_PDU_TYPE_RAR: - - ret_mask |= (handle_rar(dl_info)) << FAPI_NR_RX_PDU_TYPE_RAR; - - break; - - default: - break; + break; + case FAPI_NR_RX_PDU_TYPE_SIB: + ret_mask |= (handle_bcch_dlsch(dl_info->module_id, + dl_info->cc_id, dl_info->gNB_index, + (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.ack_nack, + (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu, + (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; + break; + case FAPI_NR_RX_PDU_TYPE_DLSCH: + ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; + break; + case FAPI_NR_RX_PDU_TYPE_RAR: + ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_RAR; + break; + default: + break; } } } @@ -263,20 +249,16 @@ int nr_ue_if_module_kill(uint32_t module_id) { if (nr_ue_if_module_inst[module_id] != NULL){ free(nr_ue_if_module_inst[module_id]); - } + } return 0; } int nr_ue_dcireq(nr_dcireq_t *dcireq) { - - fapi_nr_dl_config_request_t *dl_config=&dcireq->dl_config_req; + + fapi_nr_dl_config_request_t *dl_config = &dcireq->dl_config_req; NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0); - - dl_config->sfn=UE_mac->dl_config_request.sfn; - dl_config->slot=UE_mac->dl_config_request.slot; - dl_config->number_pdus=0; - - //printf(" UE_mac->dl_config_request.slot %d VS dcireq->slot %d \n", UE_mac->dl_config_request.slot, dcireq->slot); + dl_config->sfn = UE_mac->dl_config_request.sfn; + dl_config->slot = UE_mac->dl_config_request.slot; LOG_D(PHY, "Entering UE DCI configuration frame %d slot %d \n", dcireq->frame, dcireq->slot); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index df2d78f0cb..1ba8238f1e 100755 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -39,6 +39,12 @@ typedef struct NR_UL_TIME_ALIGNMENT NR_UL_TIME_ALIGNMENT_t; +typedef enum { + ONLY_PUSCH, + NOT_PUSCH, + SCHED_ALL, +} NR_UE_SCHED_MODE_t; + typedef struct { /// module id module_id_t module_id; @@ -66,8 +72,8 @@ typedef struct { frame_t frame; /// slot int slot; - /// proc is needed to signal back decoded frame number to PHY. However, this is not really FAPI procedure and should be done differently - UE_nr_rxtx_proc_t * proc; + /// index of the current UE RX/TX thread + int thread_id; /// NR UE FAPI-like P7 message, direction: L1 to L2 /// data reception indication structure @@ -95,8 +101,14 @@ typedef struct { frame_t frame_tx; /// slot tx uint32_t slot_tx; + /// index of the current UE RX/TX thread + int thread_id; + /// dci reception indication structure fapi_nr_dci_indication_t *dci_ind; + + NR_UE_SCHED_MODE_t ue_sched_mode; + } nr_uplink_indication_t; // Downlink subframe P7 @@ -111,6 +123,8 @@ typedef struct { frame_t frame; /// slot int slot; + /// index of the current UE RX/TX thread + int thread_id; /// NR UE FAPI-like P7 message, direction: L2 to L1 /// downlink transmission configuration request structure @@ -216,15 +230,23 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq); \param ssb_index SSB index within 0 - (L_ssb-1) corresponding to 38.331 ch.13 parameter i \param ssb_length corresponding to L1 parameter L_ssb \param cell_id cell id */ -int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t *pduP, unsigned int additional_bits, uint32_t ssb_index, uint32_t ssb_length, uint16_t cell_id); +int handle_bcch_bch(module_id_t module_id, + int cc_id, + unsigned int gNB_index, + uint8_t *pduP, + unsigned int additional_bits, + uint32_t ssb_index, + uint32_t ssb_length, + uint16_t ssb_start_subcarrier, + uint16_t cell_id); // TODO check /**\brief handle BCCH-DL-SCH message from dl_indication \param pdu_len length(bytes) of pdu \param pduP pointer to pdu*/ -int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, uint8_t *pduP, uint32_t pdu_len); +int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len); -int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, fapi_nr_dci_indication_pdu_t *dci); +int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); #endif diff --git a/openair2/PHY_INTERFACE/IF_Module.c b/openair2/PHY_INTERFACE/IF_Module.c index d98c603d78..ed3c9a5b7d 100644 --- a/openair2/PHY_INTERFACE/IF_Module.c +++ b/openair2/PHY_INTERFACE/IF_Module.c @@ -7,8 +7,8 @@ #include "nfapi/oai_integration/vendor_ext.h" #define MAX_IF_MODULES 100 -IF_Module_t *if_inst[MAX_IF_MODULES]; -Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; +static IF_Module_t *if_inst[MAX_IF_MODULES]; +static Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); @@ -19,6 +19,8 @@ extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); extern uint16_t sf_ahead; extern UL_RCC_IND_t UL_RCC_INFO; +extern RAN_CONTEXT_t RC; + uint16_t frame_cnt=0; void handle_rach(UL_IND_t *UL_info) { int i; @@ -685,7 +687,7 @@ static void dump_dl(Sched_Rsp_t *d) { /* debug utility functions end */ /****************************************************************************/ -void UL_indication(UL_IND_t *UL_info, L1_rxtx_proc_t *proc) { +void UL_indication(UL_IND_t *UL_info, void *proc) { AssertFatal(UL_info!=NULL,"UL_INFO is null\n"); #ifdef DUMP_FAPI dump_ul(UL_info); diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h index 42a4459732..096979c4fd 100644 --- a/openair2/PHY_INTERFACE/IF_Module.h +++ b/openair2/PHY_INTERFACE/IF_Module.h @@ -37,7 +37,6 @@ #include //#include "openair1/PHY/LTE_TRANSPORT/transport_eNB.h" #include "nfapi_interface.h" -#include "platform_constants.h" #include "platform_types.h" #include @@ -135,64 +134,13 @@ typedef struct { uint8_t Mod_id; int CC_id; nfapi_config_request_t *cfg; -}PHY_Config_t; +} PHY_Config_t; #include -/// Context data structure for RX/TX portion of subframe processing -typedef struct { - /// Component Carrier index - uint8_t CC_id; - /// timestamp transmitted to HW - openair0_timestamp timestamp_tx; - openair0_timestamp timestamp_rx; - /// subframe to act upon for transmission - int subframe_tx; - /// subframe to act upon for reception - int subframe_rx; - /// frame to act upon for transmission - int frame_tx; - /// frame to act upon for reception - int frame_rx; - int frame_prach; - int subframe_prach; - int frame_prach_br; - int subframe_prach_br; - /// \brief Instance count for RXn-TXnp4 processing thread. - /// \internal This variable is protected by \ref mutex_rxtx. - int instance_cnt; - /// pthread structure for RXn-TXnp4 processing thread - pthread_t pthread; - /// pthread attributes for RXn-TXnp4 processing thread - pthread_attr_t attr; - /// condition variable for tx processing thread - pthread_cond_t cond; - /// mutex for RXn-TXnp4 processing thread - pthread_mutex_t mutex; - /// scheduling parameters for RXn-TXnp4 thread - struct sched_param sched_param_rxtx; - - /// \internal This variable is protected by \ref mutex_RUs. - int instance_cnt_RUs; - /// condition variable for tx processing thread - pthread_cond_t cond_RUs; - /// mutex for RXn-TXnp4 processing thread - pthread_mutex_t mutex_RUs; - tpool_t *threadPool; - int nbEncode; - int nbDecode; - notifiedFIFO_t *respEncode; - notifiedFIFO_t *respDecode; - pthread_mutex_t mutex_emulateRF; - int instance_cnt_emulateRF; - pthread_t pthread_emulateRF; - pthread_attr_t attr_emulateRF; - pthread_cond_t cond_emulateRF; - int first_rx; -} L1_rxtx_proc_t; typedef struct IF_Module_s{ //define the function pointer - void (*UL_indication)(UL_IND_t *UL_INFO, L1_rxtx_proc_t *proc); - void (*schedule_response)(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); + void (*UL_indication)(UL_IND_t *UL_INFO, void *proc); + void (*schedule_response)(Sched_Rsp_t *Sched_INFO, void *proc); void (*PHY_config_req)(PHY_Config_t* config_INFO); void (*PHY_config_update_sib2_req)(PHY_Config_t* config_INFO); @@ -203,24 +151,13 @@ typedef struct IF_Module_s{ pthread_mutex_t if_mutex; } IF_Module_t; -// These mutex is used for multiple UEs L2 FAPI simulator. -// Each UEs set these value in UL and UL_INFO is shared in all UE's thread. -typedef struct { - pthread_mutex_t rx_mutex; - pthread_mutex_t crc_mutex; - pthread_mutex_t sr_mutex; - pthread_mutex_t harq_mutex; - pthread_mutex_t cqi_mutex; - pthread_mutex_t rach_mutex; -} FILL_UL_INFO_MUTEX_t; - /*Initial */ IF_Module_t *IF_Module_init(int Mod_id); void IF_Module_kill(int Mod_id); /*Interface for uplink, transmitting the Preamble(list), ULSCH SDU, NAK, Tick (trigger scheduler) */ -void UL_indication(UL_IND_t *UL_INFO, L1_rxtx_proc_t *proc); +void UL_indication(UL_IND_t *UL_INFO, void *proc); /*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/ void Schedule_Response(Sched_Rsp_t *Sched_INFO); diff --git a/openair2/PHY_INTERFACE/UE_MAC_interface.h b/openair2/PHY_INTERFACE/UE_MAC_interface.h index 42e790d1e9..207c3293b4 100644 --- a/openair2/PHY_INTERFACE/UE_MAC_interface.h +++ b/openair2/PHY_INTERFACE/UE_MAC_interface.h @@ -68,64 +68,6 @@ typedef enum { } UE_MAC_Tx_ind_type_e; - -// *** UE_UL_Config.request related structures - - -typedef struct{ - //module_id_t module_idP; - //int CC_id; - //frame_t frameP; - uint8_t eNB_id; - //uint16_t rnti; - //sub_frame_t subframe_tx; - uint32_t SR_payload; //0 or 1 -}UE_MAC_ul_config_SR; - - - -typedef struct{ - //module_id_t module_idP; - //int CC_id; - //frame_t frameP; - uint8_t eNB_indexP; - //sub_frame_t subframeP; - - uint8_t ra_RACH_MaskIndex; - int8_t ra_PREAMBLE_RECEIVED_TARGET_POWER; - uint8_t ra_TDD_map_index; - uint16_t ra_RNTI; - uint8_t *Msg3; -}UE_MAC_ul_config_rach; - -typedef struct { - union { - UE_MAC_ul_config_rach ue_rach_config; - //UE_MAC_ul_config_ULSCH ue_ULSCH_pdu; - UE_MAC_ul_config_SR ue_SR_config; - }; -} UE_MAC_ul_config_request_list; - -typedef struct { - nfapi_tl_t tl; - uint16_t length_list; - UE_MAC_ul_config_request_list* ue_ul_config_list; -} UE_MAC_ul_config_request_body_t; - -typedef struct { - //nfapi_p7_message_header_t header; - uint16_t sfn_sf; - UE_MAC_ul_config_request_body_t ue_ul_config_request_body; //nfapi_dl_config_request_body_t -} UE_MAC_ul_config_request_t; - - - - - - - - - // *** UE_Tx.request related structures typedef struct { diff --git a/openair2/PHY_INTERFACE/mac_phy_primitives.c b/openair2/PHY_INTERFACE/mac_phy_primitives.c deleted file mode 100644 index 06e06d096d..0000000000 --- a/openair2/PHY_INTERFACE/mac_phy_primitives.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*________________________mac_phy_primitives.c________________________ - - Authors : Hicham Anouar, Raymond Knopp - Company : EURECOM - Emails : anouar@eurecom.fr, knopp@eurecom.fr -________________________________________________________________*/ - - -//#include "openair_extern.h" - -#ifdef MAC_CONTEXT -#include "LAYER2/MAC/defs.h" -#include "LAYER2/MAC/extern.h" -//#include "extern.h" -#include "defs.h" -#endif //MAC_CONTEXT - - -//#define DEBUG_UE_DECODE_SACH -//#define DEBUG_NODEB_DECODE_SACH - -#ifdef PHY_CONTEXT -#ifdef PHY_EMUL -#include "extern.h" -#include "SIMULATION/simulation_defs.h" -#else //PHY_EMUL -#include "MAC_INTERFACE/extern.h" -#endif //PHY_EMUL - -void clear_macphy_data_req(unsigned char Mod_id) -{ - //msg("CLEAR DATA_REQ\n"); - unsigned char i; - - Macphy_req_table[Mod_id].Macphy_req_cnt = 0; - - for (i=0; iTime_alloc==Phy2->Time_alloc && Phy1->Freq_alloc==Phy2->Freq_alloc)// && Phy1->Coding_fmt==Phy2->Coding_fmt && Phy1->Seq_index==Phy2->Seq_index) - return 1; - else - return 0; - -} -*/ - -MACPHY_DATA_REQ_TABLE_ENTRY* find_data_req_entry(unsigned char Mod_id,MACPHY_REQ_ENTRY_KEY *Search_key) -{ - - unsigned char i; - - //msg("[MAC_PHY]MAC_PHY_REQUEST_CNT=%d\n",Macphy_req_table.Macphy_req_cnt); - if (Macphy_req_table[Mod_id].Macphy_req_cnt > 0) { -#ifdef DEBUG_PHY - // msg("[MACPHY_FIND_REQ] SEARCH KEY=%d\n",Search_key->Key_type); -#endif //DEBUG_PHY - //msg("[MACPHY_FIND_REQ] SEARCH KEY=%d, NB_REQ_MAX=%d\n",Search_key->Key_type,NB_REQ_MAX); - - switch(Search_key->Key_type) { - case PDU_TYPE_KEY: - for(i=0; iKey.Pdu_type) && - (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) ) { - //msg("[MACPHY_FIND] MACPHY_req_table_entry=%p,idx=%d,Phy_resources %p", &Macphy_req_table.Macphy_req_table_entry[i],i,Macphy_req_table.Macphy_req_table_entry[i].Macphy_data_req.Phy_Resources_Entry); - return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); - } - } - - break; - /* - case LCHAN_KEY: - for(i=0;iKey.Lchan_id->Index) && - (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) ) - return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); - } - break; - - case PHY_RESOURCES_KEY: - for(i=0;iTime_alloc == - Search_key->Key.Phy_resources.Time_alloc ) - &&( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Freq_alloc == - Search_key->Key.Phy_resources.Freq_alloc ) - &&( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.CH_index == - Search_key->CH_index ) - && ( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Direction == RX)) - return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); - } - break; - */ - } - } - -#ifndef PHY_EMUL - // msg("[PHY][PHY_MAC] Frame %d : No data request\n",mac_xface->frame); -#endif //PHY_EMUL - - - return (MACPHY_DATA_REQ_TABLE_ENTRY*)0; - -} - - - - - - -void print_active_requests(unsigned char Mod_id) -{ - - int i; - msg("_________________________INST %d , FRAME %d ACTIVE_REQUESTS_________________\n",Mod_id,mac_xface->frame); - - for (i=0; iTime_alloc, - // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Freq_alloc); - //if(Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Pdu_type==RACH) - //msg("[RACH_REQ] Rach_pdu %p, Payload %p\n",Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Dir.Req_rx.Pdu.Rach_pdu, - // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Dir.Req_rx.Pdu.Rach_pdu->Rach_payload); - - } - } -} - - -/*___________________________________________________________________________________________________*/ -#define RCNT Macphy_req_table[Mod_id].Macphy_req_cnt - -MACPHY_DATA_REQ *new_macphy_data_req(unsigned char Mod_id) -{ - /*___________________________________________________________________________________________________*/ - unsigned char i; - - - - for (i=0; iframe,Mod_id,i); - // Macphy_req_table[Mod_id].Macphy_req_table_entry[i%NB_REQ_MAX].Macphy_data_req.Phy_resources=(PHY_RESOURCES*)malloc16(sizeof(PHY_RESOURCES)); - return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i%NB_REQ_MAX].Macphy_data_req); - } - } - - msg("[OPENAIR][MAC][ERROR] frame %d: No more DATA_REQ !!!!\n",mac_xface->frame); - - print_active_requests(Mod_id); - mac_xface->macphy_exit("new_macphy_data_req: no more DATA_REQ"); - //rt_sleep(nano2count(2000)); - - return((MACPHY_DATA_REQ*)0); -} - - -#endif //PHY_CONTEXT - -#ifdef MAC_CONTEXT -#include "LAYER2/MAC/extern.h" - -// Function called by PHY to indicate available data/measurements for MAC - -/*___________________________________________________________________________________________________*/ -void macphy_data_ind(unsigned char Mod_id,unsigned char Pdu_type,void *pdu,unsigned short rnti) -{ - /*___________________________________________________________________________________________________*/ - //msg("[OPENAIR][MACPHY] Calling mac_resp In\n"); - - int i; - - // if (Req_rx->crc_status[0]!= -1) { //CRC_STATUS - - // msg("[OPENAIR][MACPHY] Calling mac_indicate In\n"); - // Req_rx->Meas.UL_meas=&UL_meas[Mod_id]; - // Req_rx->Meas.DL_meas=&DL_meas[Mod_id]; - - switch (Pdu_type) { - case ULSCH: - - // msg("[OPENAIR][MACPHY] Received RACH, Sending to MAC\n"); - nodeb_decode_ulsch(Mod_id,(ULSCH_PDU *)pdu,rnti); - - break; - - case DLSCH: -#ifdef DEBUG_UE_DECODE_SACH - msg("[MAC][UE][MAC_PHY] TTI %d Inst %d\n",mac_xface->frame,Mod_id); -#endif - - // ue_decode_dlsch(Mod_id-NB_CH_INST, - // (DLSCH_PDU *)pdu,rnti); - - break; - - default: - break; - } - - // msg("Freeing Req %p\n",Macphy_data_req_table_entry); - // } - -} - - - - - -/*PHY_RESOURCES_TABLE_ENTRY *new_phy_resources() { - - - unsigned char i; - - //msg("[OPENAIR][PHY][MAC Interface] New Phy Resource, cnt %d\n",Phy_resources_table.Phy_resources_cnt); - - for (i=0;irx_ind.sfn_sf = frame << 4 | subframe; UL_INFO->rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG; UL_INFO->rx_ind.vendor_extension = ul_config_req->vendor_extension; @@ -101,7 +104,6 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id, UL_INFO->rx_ind.rx_indication_body.number_of_pdus++; UL_INFO->rx_ind.sfn_sf = frame << 4 | subframe; - pthread_mutex_unlock(&fill_ul_mutex.rx_mutex); } void fill_sr_indication_UE_MAC(int Mod_id, @@ -109,8 +111,6 @@ void fill_sr_indication_UE_MAC(int Mod_id, int subframe, UL_IND_t *UL_INFO, uint16_t rnti) { - pthread_mutex_lock(&fill_ul_mutex.sr_mutex); - nfapi_sr_indication_t *sr_ind = &UL_INFO->sr_ind; nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body; nfapi_sr_indication_pdu_t *pdu = &sr_ind_body->sr_pdu_list[sr_ind_body->number_of_srs]; @@ -139,7 +139,6 @@ void fill_sr_indication_UE_MAC(int Mod_id, // UL_INFO->rx_ind.rx_indication_body.number_of_pdus++; sr_ind_body->number_of_srs++; - pthread_mutex_unlock(&fill_ul_mutex.sr_mutex); } void fill_crc_indication_UE_MAC(int Mod_id, @@ -149,8 +148,6 @@ void fill_crc_indication_UE_MAC(int Mod_id, uint8_t crc_flag, int index, uint16_t rnti) { - pthread_mutex_lock(&fill_ul_mutex.crc_mutex); - nfapi_crc_indication_pdu_t *pdu = &UL_INFO->crc_ind.crc_indication_body .crc_pdu_list[UL_INFO->crc_ind.crc_indication_body.number_of_crcs]; @@ -174,8 +171,6 @@ void fill_crc_indication_UE_MAC(int Mod_id, __FUNCTION__, pdu->rx_ue_information.rnti, UL_INFO->crc_ind.crc_indication_body.number_of_crcs); - - pthread_mutex_unlock(&fill_ul_mutex.crc_mutex); } void fill_rach_indication_UE_MAC(int Mod_id, @@ -184,10 +179,6 @@ void fill_rach_indication_UE_MAC(int Mod_id, UL_IND_t *UL_INFO, uint8_t ra_PreambleIndex, uint16_t ra_RNTI) { - LOG_D(MAC, "fill_rach_indication_UE_MAC 1 \n"); - - pthread_mutex_lock(&fill_ul_mutex.rach_mutex); - UL_INFO->rach_ind.rach_indication_body.number_of_preambles = 1; UL_INFO->rach_ind.header.message_id = NFAPI_RACH_INDICATION; @@ -232,8 +223,6 @@ void fill_rach_indication_UE_MAC(int Mod_id, // should call it when we merge with that branch. oai_nfapi_rach_ind(&UL_INFO->rach_ind); free(UL_INFO->rach_ind.rach_indication_body.preamble_list); - - pthread_mutex_unlock(&fill_ul_mutex.rach_mutex); } void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, @@ -241,7 +230,6 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint8_t subframe, UL_IND_t *UL_INFO, uint16_t rnti) { - pthread_mutex_lock(&fill_ul_mutex.cqi_mutex); nfapi_cqi_indication_pdu_t *pdu = &UL_INFO->cqi_ind.cqi_indication_body .cqi_pdu_list[UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis]; @@ -275,7 +263,6 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, raw_pdu->pdu[0] = cqi << 4; UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis++; - pthread_mutex_unlock(&fill_ul_mutex.cqi_mutex); } void fill_ulsch_harq_indication_UE_MAC( @@ -285,8 +272,6 @@ void fill_ulsch_harq_indication_UE_MAC( UL_IND_t *UL_INFO, nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t rnti) { - pthread_mutex_lock(&fill_ul_mutex.harq_mutex); - nfapi_harq_indication_pdu_t *pdu = &UL_INFO->harq_ind.harq_indication_body.harq_pdu_list [UL_INFO->harq_ind.harq_indication_body.number_of_harqs]; @@ -318,7 +303,6 @@ void fill_ulsch_harq_indication_UE_MAC( } UL_INFO->harq_ind.harq_indication_body.number_of_harqs++; - pthread_mutex_unlock(&fill_ul_mutex.harq_mutex); } void fill_uci_harq_indication_UE_MAC(int Mod_id, @@ -327,8 +311,6 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id, UL_IND_t *UL_INFO, nfapi_ul_config_harq_information *harq_information, uint16_t rnti) { - pthread_mutex_lock(&fill_ul_mutex.harq_mutex); - nfapi_harq_indication_t *ind = &UL_INFO->harq_ind; nfapi_harq_indication_body_t *body = &ind->harq_indication_body; nfapi_harq_indication_pdu_t *pdu = @@ -410,7 +392,6 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id, LOG_D(PHY, "Incremented eNB->UL_INFO.harq_ind.number_of_harqs:%d\n", UL_INFO->harq_ind.harq_indication_body.number_of_harqs); - pthread_mutex_unlock(&fill_ul_mutex.harq_mutex); } void handle_nfapi_ul_pdu_UE_MAC(module_id_t Mod_id, diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.h b/openair2/PHY_INTERFACE/phy_stub_UE.h index 09356fc9f8..bdf8872371 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.h +++ b/openair2/PHY_INTERFACE/phy_stub_UE.h @@ -17,8 +17,6 @@ //#include "openair1/PHY/defs.h" //#include "openair1/PHY/LTE_TRANSPORT/defs.h" -// this mutex is used to set multiple UE's UL value in L2 FAPI simulator. -FILL_UL_INFO_MUTEX_t fill_ul_mutex; //below 2 difinitions move to phy_stub_UE.c to add initialization when difinition. extern UL_IND_t *UL_INFO; extern nfapi_tx_request_pdu_t* tx_request_pdu_list; @@ -28,16 +26,7 @@ extern nfapi_tx_request_pdu_t* tx_request_pdu_list; extern nfapi_dl_config_request_t* dl_config_req; extern nfapi_ul_config_request_t* ul_config_req; extern nfapi_hi_dci0_request_t* hi_dci0_req; - -int tx_req_num_elems; - -//below 2 difinitions move to lte-ue.c to add initialization when difinition. -//int next_ra_frame; -//module_id_t next_Mod_id; -eth_params_t stub_eth_params; - - - +extern int tx_req_num_elems; // This function should return all the sched_response config messages which concern a specific UE. Inside this // function we should somehow make the translation of config message's rnti to Mod_ID. diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c index 027a629992..a4239e857d 100644 --- a/openair2/RRC/LITE/rrc_common.c +++ b/openair2/RRC/LITE/rrc_common.c @@ -97,35 +97,6 @@ rrc_init_global_param( //----------------------------------------------------------------------------- { - //#ifdef USER_MODE - // Rrc_xface = (RRC_XFACE*)malloc16(sizeof(RRC_XFACE)); - //#endif //USRE_MODE - - // Rrc_xface->openair_rrc_top_init = openair_rrc_top_init; - // Rrc_xface->openair_rrc_eNB_init = openair_rrc_eNB_init; - // Rrc_xface->openair_rrc_UE_init = openair_rrc_ue_init; - // Rrc_xface->mac_rrc_data_ind = mac_rrc_data_ind; - //Rrc_xface->mac_rrc_data_req = mac_rrc_data_req; - // Rrc_xface->rrc_data_indP = (void *)rlcrrc_data_ind; - // Rrc_xface->rrc_rx_tx = rrc_rx_tx; - // Rrc_xface->mac_rrc_meas_ind = mac_rrc_meas_ind; - // Rrc_xface->get_rrc_status = get_rrc_status; - - //Rrc_xface->rrc_get_status = ... - - // Mac_rlc_xface->mac_out_of_sync_ind=mac_out_of_sync_ind; - -#ifndef NO_RRM - // Rrc_xface->fn_rrc=fn_rrc; -#endif - // LOG_D(RRC, "[RRC]INIT_GLOBAL_PARAM: Mac_rlc_xface %p, rrc_rlc_register %p,rlcrrc_data_ind%p\n",Mac_rlc_xface,Mac_rlc_xface->rrc_rlc_register_rrc,rlcrrc_data_ind); - /* - if((Mac_rlc_xface==NULL) || (Mac_rlc_xface->rrc_rlc_register_rrc==NULL) || - (rlcrrc_data_ind==NULL)) { - LOG_E(RRC,"Data structured is not initialized \n"); - return -1; - } - */ rrc_rlc_register_rrc (rrc_data_ind, NULL); //register with rlc DCCH_LCHAN_DESC.transport_block_size = 4; @@ -392,7 +363,7 @@ rrc_rx_tx( current_timestamp_ms, ctxt_pP->frame, estimated_distance); - LOG_D(LOCALIZE, " RRC status %d\n", ue_context_p->ue_context.Status); + LOG_D(LOCALIZE, " RRC status %d\n", ue_context_p->ue_context.StatusRrc); push_front(&RC.rrc[ctxt_pP->module_id]->loc_list, estimated_distance); RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms = current_timestamp_ms; diff --git a/openair2/RRC/LTE/L2_interface.c b/openair2/RRC/LTE/L2_interface.c index d9682b466f..0b767b8ad6 100644 --- a/openair2/RRC/LTE/L2_interface.c +++ b/openair2/RRC/LTE/L2_interface.c @@ -49,8 +49,6 @@ #include "intertask_interface.h" #include "flexran_agent_extern.h" -#undef C_RNTI // C_RNTI is used in F1AP generated code, prevent preprocessor replace -//#include "f1ap_du_rrc_message_transfer.h" #include "openair2/F1AP/f1ap_du_rrc_message_transfer.h" extern RAN_CONTEXT_t RC; @@ -316,8 +314,9 @@ mac_rrc_data_ind( UE_id, rntiP, sduP, - sdu_lenP - ); + sdu_lenP, + NULL, + 0); return(0); } @@ -349,12 +348,12 @@ mac_rrc_data_ind( ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ctxt.module_id],rntiP); if(ue_context_p) { - if (ue_context_p->ue_context.Status != RRC_RECONFIGURED) { - LOG_E(RRC,"[eNB %d] Received C-RNTI ,but UE %x status(%d) not RRC_RECONFIGURED\n",module_idP,rntiP,ue_context_p->ue_context.Status); + if (ue_context_p->ue_context.StatusRrc != RRC_RECONFIGURED) { + LOG_E(RRC,"[eNB %d] Received C-RNTI ,but UE %x status(%d) not RRC_RECONFIGURED\n",module_idP,rntiP,ue_context_p->ue_context.StatusRrc); return (-1); } rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt,ue_context_p,0); - ue_context_p->ue_context.Status = RRC_RECONFIGURED; + ue_context_p->ue_context.StatusRrc = RRC_RECONFIGURED; } } @@ -376,7 +375,7 @@ mac_eNB_get_rrc_status( ue_context_p = rrc_eNB_get_ue_context(RC.rrc[Mod_idP], rntiP); if (ue_context_p != NULL) { - return(ue_context_p->ue_context.Status); + return(ue_context_p->ue_context.StatusRrc); } else { return RRC_INACTIVE; } diff --git a/openair2/RRC/LTE/L2_interface_common.c b/openair2/RRC/LTE/L2_interface_common.c index fa332b5be1..f70cc68550 100644 --- a/openair2/RRC/LTE/L2_interface_common.c +++ b/openair2/RRC/LTE/L2_interface_common.c @@ -80,7 +80,7 @@ rrc_data_req( ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, sdu_sizeP); memcpy (message_buffer, buffer_pP, sdu_sizeP); - message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_RRC_ENB : TASK_RRC_UE, RRC_DCCH_DATA_REQ); + message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_RRC_ENB : TASK_RRC_UE, 0, RRC_DCCH_DATA_REQ); RRC_DCCH_DATA_REQ (message_p).frame = ctxt_pP->frame; RRC_DCCH_DATA_REQ (message_p).enb_flag = ctxt_pP->enb_flag; RRC_DCCH_DATA_REQ (message_p).rb_id = rb_idP; @@ -139,7 +139,7 @@ rrc_data_ind( uint8_t *message_buffer; message_buffer = itti_malloc (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, ctxt_pP->enb_flag ? TASK_RRC_ENB : TASK_RRC_UE, sdu_sizeP); memcpy (message_buffer, buffer_pP, sdu_sizeP); - message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, 0, RRC_DCCH_DATA_IND); RRC_DCCH_DATA_IND (message_p).frame = ctxt_pP->frame; RRC_DCCH_DATA_IND (message_p).dcch_index = DCCH_index; RRC_DCCH_DATA_IND (message_p).sdu_size = sdu_sizeP; diff --git a/openair2/RRC/LTE/L2_interface_ue.c b/openair2/RRC/LTE/L2_interface_ue.c index 8c55dbaeb5..5c1800cdd4 100644 --- a/openair2/RRC/LTE/L2_interface_ue.c +++ b/openair2/RRC/LTE/L2_interface_ue.c @@ -94,7 +94,7 @@ mac_rrc_data_req_ue( ccch_size = sdu_size; } - message_p = itti_alloc_new_message (TASK_RRC_UE, RRC_MAC_CCCH_DATA_REQ); + message_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_MAC_CCCH_DATA_REQ); RRC_MAC_CCCH_DATA_REQ (message_p).frame = frameP; RRC_MAC_CCCH_DATA_REQ (message_p).sdu_size = ccch_size; memset (RRC_MAC_CCCH_DATA_REQ (message_p).sdu, 0, CCCH_SDU_SIZE); @@ -155,7 +155,7 @@ mac_rrc_data_ind_ue( sdu_size = sdu_lenP; } - message_p = itti_alloc_new_message (TASK_MAC_UE, RRC_MAC_BCCH_MBMS_DATA_IND); + message_p = itti_alloc_new_message (TASK_MAC_UE, 0, RRC_MAC_BCCH_MBMS_DATA_IND); memset (RRC_MAC_BCCH_MBMS_DATA_IND (message_p).sdu, 0, BCCH_SDU_MBMS_SIZE); RRC_MAC_BCCH_MBMS_DATA_IND (message_p).frame = frameP; RRC_MAC_BCCH_MBMS_DATA_IND (message_p).sub_frame = sub_frameP; @@ -181,7 +181,7 @@ mac_rrc_data_ind_ue( sdu_size = sdu_lenP; } - message_p = itti_alloc_new_message (TASK_MAC_UE, RRC_MAC_BCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_MAC_UE, 0, RRC_MAC_BCCH_DATA_IND); memset (RRC_MAC_BCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE); RRC_MAC_BCCH_DATA_IND (message_p).frame = frameP; RRC_MAC_BCCH_DATA_IND (message_p).sub_frame = sub_frameP; @@ -213,7 +213,7 @@ mac_rrc_data_ind_ue( sdu_size = sdu_lenP; } - message_p = itti_alloc_new_message (TASK_MAC_UE, RRC_MAC_CCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_MAC_UE, 0, RRC_MAC_CCCH_DATA_IND); memset (RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); memcpy (RRC_MAC_CCCH_DATA_IND (message_p).sdu, sduP, sdu_size); RRC_MAC_CCCH_DATA_IND (message_p).frame = frameP; @@ -239,7 +239,7 @@ mac_rrc_data_ind_ue( sdu_size = msg_sdu_size; } - message_p = itti_alloc_new_message (TASK_MAC_UE, RRC_MAC_MCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_MAC_UE, 0, RRC_MAC_MCCH_DATA_IND); RRC_MAC_MCCH_DATA_IND (message_p).frame = frameP; RRC_MAC_MCCH_DATA_IND (message_p).sub_frame = sub_frameP; RRC_MAC_MCCH_DATA_IND (message_p).sdu_size = sdu_lenP; @@ -293,7 +293,7 @@ rrc_data_req_ue( ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, sdu_sizeP); memcpy (message_buffer, buffer_pP, sdu_sizeP); - message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_RRC_ENB : TASK_RRC_UE, RRC_DCCH_DATA_REQ); + message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_RRC_ENB : TASK_RRC_UE, 0, RRC_DCCH_DATA_REQ); RRC_DCCH_DATA_REQ (message_p).frame = ctxt_pP->frame; RRC_DCCH_DATA_REQ (message_p).enb_flag = ctxt_pP->enb_flag; RRC_DCCH_DATA_REQ (message_p).rb_id = rb_idP; @@ -332,7 +332,7 @@ rrc_data_ind_ue( uint8_t *message_buffer; message_buffer = itti_malloc (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, ctxt_pP->enb_flag ? TASK_RRC_ENB : TASK_RRC_UE, sdu_sizeP); memcpy (message_buffer, buffer_pP, sdu_sizeP); - message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, 0, RRC_DCCH_DATA_IND); RRC_DCCH_DATA_IND (message_p).frame = ctxt_pP->frame; RRC_DCCH_DATA_IND (message_p).dcch_index = DCCH_index; RRC_DCCH_DATA_IND (message_p).sdu_size = sdu_sizeP; @@ -350,7 +350,7 @@ void rrc_in_sync_ind(module_id_t Mod_idP, frame_t frameP, uint16_t eNB_index) { { MessageDef *message_p; //LOG_I(RRC,"sending a message to task_mac_ue\n"); - message_p = itti_alloc_new_message (TASK_MAC_UE, RRC_MAC_IN_SYNC_IND); + message_p = itti_alloc_new_message (TASK_MAC_UE, 0, RRC_MAC_IN_SYNC_IND); RRC_MAC_IN_SYNC_IND (message_p).frame = frameP; RRC_MAC_IN_SYNC_IND (message_p).enb_index = eNB_index; itti_send_msg_to_task (TASK_RRC_UE, UE_MODULE_ID_TO_INSTANCE(Mod_idP), message_p); @@ -370,7 +370,7 @@ void rrc_out_of_sync_ind(module_id_t Mod_idP, frame_t frameP, uint16_t eNB_index { MessageDef *message_p; - message_p = itti_alloc_new_message (TASK_MAC_UE, RRC_MAC_OUT_OF_SYNC_IND); + message_p = itti_alloc_new_message (TASK_MAC_UE, 0, RRC_MAC_OUT_OF_SYNC_IND); RRC_MAC_OUT_OF_SYNC_IND (message_p).frame = frameP; RRC_MAC_OUT_OF_SYNC_IND (message_p).enb_index = eNB_index; itti_send_msg_to_task (TASK_RRC_UE, UE_MODULE_ID_TO_INSTANCE(Mod_idP), message_p); @@ -396,7 +396,7 @@ int mac_ue_ccch_success_ind(module_id_t Mod_idP, uint8_t eNB_index) { //-------------------------------------------------------------------------------------------// { MessageDef *message_p; - message_p = itti_alloc_new_message (TASK_MAC_UE, RRC_MAC_CCCH_DATA_CNF); + message_p = itti_alloc_new_message (TASK_MAC_UE, 0, RRC_MAC_CCCH_DATA_CNF); RRC_MAC_CCCH_DATA_CNF (message_p).enb_index = eNB_index; itti_send_msg_to_task (TASK_RRC_UE, UE_MODULE_ID_TO_INSTANCE(Mod_idP), message_p); } diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 09e6245fec..ce26aeef87 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -99,6 +99,7 @@ #include "intertask_interface.h" +#include "NR_FreqBandList.h" #include "common/ran_context.h" @@ -2727,7 +2728,7 @@ do_RRCConnectionSetup( // assign_enum(&physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax, //SchedulingRequestConfig__setup__dsr_TransMax_n4); // assign_enum(&physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax = SchedulingRequestConfig__setup__dsr_TransMax_n4; - physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax = LTE_SchedulingRequestConfig__setup__dsr_TransMax_n4; + physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax = LTE_SchedulingRequestConfig__setup__dsr_TransMax_n64; rrcConnectionSetup->rrc_TransactionIdentifier = Transaction_id; rrcConnectionSetup->criticalExtensions.present = LTE_RRCConnectionSetup__criticalExtensions_PR_c1; rrcConnectionSetup->criticalExtensions.choice.c1.present = LTE_RRCConnectionSetup__criticalExtensions__c1_PR_rrcConnectionSetup_r8 ; @@ -3199,9 +3200,13 @@ uint8_t do_SecurityModeCommand( //------------------------------------------------------------------------------ uint8_t do_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, uint8_t *const buffer, - const uint8_t Transaction_id) + const uint8_t Transaction_id, + int16_t eutra_band, + uint32_t nr_band) //------------------------------------------------------------------------------ { + NR_FreqBandList_t *nsa_band_list; + NR_FreqBandInformation_t *nsa_band; LTE_DL_DCCH_Message_t dl_dcch_msg; LTE_RAT_Type_t rat=LTE_RAT_Type_eutra; asn_enc_rval_t enc_rval; @@ -3215,31 +3220,61 @@ uint8_t do_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list.count=0; ASN_SEQUENCE_ADD(&dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list, &rat); - - /* request NR configuration */ LTE_UECapabilityEnquiry_r8_IEs_t *r8 = &dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8; LTE_UECapabilityEnquiry_v8a0_IEs_t r8_a0; LTE_UECapabilityEnquiry_v1180_IEs_t r11_80; LTE_UECapabilityEnquiry_v1310_IEs_t r13_10; LTE_UECapabilityEnquiry_v1430_IEs_t r14_30; LTE_UECapabilityEnquiry_v1510_IEs_t r15_10; - - memset(&r8_a0, 0, sizeof(r8_a0)); - memset(&r11_80, 0, sizeof(r11_80)); - memset(&r13_10, 0, sizeof(r13_10)); - memset(&r14_30, 0, sizeof(r14_30)); - memset(&r15_10, 0, sizeof(r15_10)); - - r8->nonCriticalExtension = &r8_a0; - r8_a0.nonCriticalExtension = &r11_80; - r11_80.nonCriticalExtension = &r13_10; - r13_10.nonCriticalExtension = &r14_30; - r14_30.nonCriticalExtension = &r15_10; - - /* TODO: no hardcoded values here */ - OCTET_STRING_t req_freq; - unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 + + if (nr_band>0) { + + /* request NR configuration */ + + memset(&r8_a0, 0, sizeof(r8_a0)); + memset(&r11_80, 0, sizeof(r11_80)); + memset(&r13_10, 0, sizeof(r13_10)); + memset(&r14_30, 0, sizeof(r14_30)); + memset(&r15_10, 0, sizeof(r15_10)); + + r8->nonCriticalExtension = &r8_a0; + r8_a0.nonCriticalExtension = &r11_80; + r11_80.nonCriticalExtension = &r13_10; + r13_10.nonCriticalExtension = &r14_30; + r14_30.nonCriticalExtension = &r15_10; + + /* TODO: no hardcoded values here */ + + nsa_band_list = (NR_FreqBandList_t *)calloc(1, sizeof(NR_FreqBandList_t)); + + nsa_band = (NR_FreqBandInformation_t *) calloc(1,sizeof(NR_FreqBandInformation_t)); + nsa_band->present = NR_FreqBandInformation_PR_bandInformationEUTRA; + nsa_band->choice.bandInformationEUTRA = (NR_FreqBandInformationEUTRA_t *) calloc(1, sizeof(NR_FreqBandInformationEUTRA_t)); + nsa_band->choice.bandInformationEUTRA->bandEUTRA = eutra_band; + ASN_SEQUENCE_ADD(&nsa_band_list->list, nsa_band); + + nsa_band = (NR_FreqBandInformation_t *) calloc(1,sizeof(NR_FreqBandInformation_t)); + nsa_band->present = NR_FreqBandInformation_PR_bandInformationNR; + nsa_band->choice.bandInformationNR = (NR_FreqBandInformationNR_t *) calloc(1, sizeof(NR_FreqBandInformationNR_t)); + //if(nr_band > 0) + nsa_band->choice.bandInformationNR->bandNR = nr_band; + //else + // nsa_band->choice.bandInformationNR->bandNR = 78; + ASN_SEQUENCE_ADD(&nsa_band_list->list, nsa_band); + + //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 + unsigned char req_freq_buf[1024]; + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_FreqBandList, + NULL, + (void *)nsa_band_list, + req_freq_buf, + 1024); + + xer_fprint(stdout, &asn_DEF_NR_FreqBandList, (void *)nsa_band_list); + + + //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x08, 0x18 }; // bands 7 & nr260 //unsigned char req_freq_buf[13] = { 0x00, 0xc0, 0x18, 0x01, 0x01, 0x30, 0x4b, 0x04, 0x0e, 0x08, 0x24, 0x04, 0xd0 }; @@ -3247,14 +3282,16 @@ uint8_t do_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, //0x01, 0x60, 0x18, 0x05, 0x80, 0xc0, 0x04, 0x04, 0xc1, 0x2c, 0x10, 0x08, 0x20, 0x30, 0x40, 0xe0, 0x82, 0x40, 0x28, 0x80, 0x9a // }; - req_freq.buf = req_freq_buf; - req_freq.size = 5; + req_freq.buf = req_freq_buf; + req_freq.size = (enc_rval.encoded+7)/8; // req_freq.size = 21; - r15_10.requestedFreqBandsNR_MRDC_r15 = &req_freq; - if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - xer_fprint(stdout, &asn_DEF_LTE_DL_DCCH_Message, (void *)&dl_dcch_msg); + r15_10.requestedFreqBandsNR_MRDC_r15 = &req_freq; + // Add request for eutra-nr } +// if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_LTE_DL_DCCH_Message, (void *)&dl_dcch_msg); +// } enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_DL_DCCH_Message, NULL, @@ -3287,9 +3324,13 @@ uint8_t do_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, //------------------------------------------------------------------------------ uint8_t do_NR_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, uint8_t *const buffer, - const uint8_t Transaction_id) + const uint8_t Transaction_id, + int16_t eutra_band, + uint32_t nr_band) //------------------------------------------------------------------------------ { + NR_FreqBandList_t *nsa_band_list; + NR_FreqBandInformation_t *nsa_band; LTE_DL_DCCH_Message_t dl_dcch_msg; LTE_RAT_Type_t rat_nr=LTE_RAT_Type_nr; LTE_RAT_Type_t rat_eutra_nr=LTE_RAT_Type_eutra_nr; @@ -3329,8 +3370,32 @@ uint8_t do_NR_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, /* TODO: no hardcoded values here */ + nsa_band_list = (NR_FreqBandList_t *)calloc(1, sizeof(NR_FreqBandList_t)); + + nsa_band = (NR_FreqBandInformation_t *) calloc(1,sizeof(NR_FreqBandInformation_t)); + nsa_band->present = NR_FreqBandInformation_PR_bandInformationEUTRA; + nsa_band->choice.bandInformationEUTRA = (NR_FreqBandInformationEUTRA_t *) calloc(1, sizeof(NR_FreqBandInformationEUTRA_t)); + nsa_band->choice.bandInformationEUTRA->bandEUTRA = eutra_band; + ASN_SEQUENCE_ADD(&nsa_band_list->list, nsa_band); + + nsa_band = (NR_FreqBandInformation_t *) calloc(1,sizeof(NR_FreqBandInformation_t)); + nsa_band->present = NR_FreqBandInformation_PR_bandInformationNR; + nsa_band->choice.bandInformationNR = (NR_FreqBandInformationNR_t *) calloc(1, sizeof(NR_FreqBandInformationNR_t)); + if(nr_band > 0) + nsa_band->choice.bandInformationNR->bandNR = nr_band; + else + nsa_band->choice.bandInformationNR->bandNR = 78; + ASN_SEQUENCE_ADD(&nsa_band_list->list, nsa_band); + OCTET_STRING_t req_freq; - unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 + //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 + unsigned char req_freq_buf[100]; + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_FreqBandList, + NULL, + (void *)nsa_band_list, + req_freq_buf, + 1024); + //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x08, 0x18 }; // bands 7 & nr260 //unsigned char req_freq_buf[13] = { 0x00, 0xc0, 0x18, 0x01, 0x01, 0x30, 0x4b, 0x04, 0x0e, 0x08, 0x24, 0x04, 0xd0 }; @@ -3339,7 +3404,7 @@ uint8_t do_NR_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, // }; req_freq.buf = req_freq_buf; - req_freq.size = 5; + req_freq.size = (enc_rval.encoded+7)/8; // req_freq.size = 21; r15_10.requestedFreqBandsNR_MRDC_r15 = &req_freq; diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h index 640d18a61f..0d9fe65aeb 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.h @@ -359,15 +359,17 @@ uint8_t do_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, uint8_t *const buffer, - const uint8_t Transaction_id -); + const uint8_t Transaction_id, + int16_t eutra_band, + uint32_t nr_band); uint8_t do_NR_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, uint8_t *const buffer, - const uint8_t Transaction_id -); + const uint8_t Transaction_id, + int16_t eutra_band, + uint32_t nr_band); uint8_t do_SecurityModeCommand( const protocol_ctxt_t *const ctxt_pP, diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.h b/openair2/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.h index 6b56be1022..a862af7836 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.h +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.h @@ -28,7 +28,6 @@ * \email: raymond.knopp@eurecom.fr ,navid.nikaein@eurecom.fr, michele.paffetti@studio.unibo.it */ -#ifdef USER_MODE #include #include #include /* for atoi(3) */ @@ -36,9 +35,6 @@ #include /* for strerror(3) */ #include /* for EX_* exit codes */ #include /* for errno */ -#else -#include /* Needed by all modules */ -#endif #include #include /* for _ASN_DEFAULT_STACK_MAX */ diff --git a/openair2/RRC/LTE/MESSAGES/asn1_patch b/openair2/RRC/LTE/MESSAGES/asn1_patch deleted file mode 100644 index 8682f17895..0000000000 --- a/openair2/RRC/LTE/MESSAGES/asn1_patch +++ /dev/null @@ -1,522 +0,0 @@ -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/asn_codecs_prim.c patch_dir/asn_codecs_prim.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/asn_codecs_prim.c 2011-03-31 10:22:56.000000000 +0200 ---- patch_dir/asn_codecs_prim.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 4,10 **** - */ - #include - #include -- #include - - /* - * Decode an always-primitive type. ---- 4,9 ---- -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/asn_internal.h patch_dir/asn_internal.h -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/asn_internal.h 2011-03-31 10:22:57.000000000 +0200 ---- patch_dir/asn_internal.h 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 10,20 **** ---- 10,31 ---- - #define _ASN_INTERNAL_H_ - - #include "asn_application.h" /* Application-visible API */ -+ #ifndef USER_MODE -+ #include -+ #include -+ #include "rtai_mem.h" -+ #endif - - #ifndef __NO_ASSERT_H__ /* Include assert.h only for internal use. */ - #include /* for assert() macro */ - #endif - -+ #ifndef USER_MODE -+ #ifndef assert -+ #define assert(expr) ((expr) ? (void) 0 : printk("Assertion failed in %s:%d\n", __FILE__, __LINE__)) -+ #endif -+ #endif -+ - #ifdef __cplusplus - extern "C" { - #endif -*************** -*** 23,32 **** ---- 34,51 ---- - #define ASN1C_ENVIRONMENT_VERSION 922 /* Compile-time version */ - int get_asn1c_environment_version(void); /* Run-time version */ - -+ #ifdef USER_MODE - #define CALLOC(nmemb, size) calloc(nmemb, size) - #define MALLOC(size) malloc(size) - #define REALLOC(oldptr, size) realloc(oldptr, size) - #define FREEMEM(ptr) free(ptr) -+ #else -+ #define CALLOC(nmemb, size) rt_calloc(nmemb,size) -+ #define MALLOC(size) rt_malloc(size) -+ #define REALLOC(oldptr, size) rt_realloc(oldptr, size) -+ #define FREEMEM(ptr) rt_free(ptr); -+ #endif -+ - - /* - * A macro for debugging the ASN.1 internals. -*************** -*** 38,45 **** - #ifdef ASN_THREAD_SAFE - #define asn_debug_indent 0 - #else /* !ASN_THREAD_SAFE */ -! int asn_debug_indent; - #endif /* ASN_THREAD_SAFE */ - #define ASN_DEBUG(fmt, args...) do { \ - int adi = asn_debug_indent; \ - while(adi--) fprintf(stderr, " "); \ ---- 57,65 ---- - #ifdef ASN_THREAD_SAFE - #define asn_debug_indent 0 - #else /* !ASN_THREAD_SAFE */ -! extern int asn_debug_indent; - #endif /* ASN_THREAD_SAFE */ -+ #ifdef USER_MODE - #define ASN_DEBUG(fmt, args...) do { \ - int adi = asn_debug_indent; \ - while(adi--) fprintf(stderr, " "); \ -*************** -*** 47,52 **** ---- 67,81 ---- - fprintf(stderr, " (%s:%d)\n", \ - __FILE__, __LINE__); \ - } while(0) -+ #else -+ #define ASN_DEBUG(fmt, args...) do { \ -+ int adi = asn_debug_indent; \ -+ while(adi--) printk(" "); \ -+ printk(fmt, ##args); \ -+ printk(" (%s:%d)\n", \ -+ __FILE__, __LINE__); \ -+ } while(0) -+ #endif - #else /* !__GNUC__ */ - void ASN_DEBUG_f(const char *fmt, ...); - #define ASN_DEBUG ASN_DEBUG_f -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/asn_SET_OF.c patch_dir/asn_SET_OF.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/asn_SET_OF.c 2011-03-31 10:22:56.000000000 +0200 ---- patch_dir/asn_SET_OF.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 4,10 **** - */ - #include - #include -- #include - - /* - * Add another element into the set. ---- 4,9 ---- -*************** -*** 21,26 **** ---- 20,27 ---- - /* - * Make sure there's enough space to insert an element. - */ -+ ASN_DEBUG("SET ADD: count %d, size %d",as->count,as->size); -+ - if(as->count == as->size) { - int _newsize = as->size ? (as->size << 1) : 4; - void *_new_arr; -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/asn_system.h patch_dir/asn_system.h -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/asn_system.h 2011-03-31 10:22:57.000000000 +0200 ---- patch_dir/asn_system.h 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 13,25 **** - #include "config.h" - #endif - -! #include /* For snprintf(3) */ -! #include /* For *alloc(3) */ -! #include /* For memcpy(3) */ -! #include /* For size_t */ -! #include /* For LONG_MAX */ -! #include /* For va_start */ -! #include /* for offsetof and ptrdiff_t */ - - #ifdef WIN32 - ---- 13,39 ---- - #include "config.h" - #endif - -! #ifdef USER_MODE -! #include // For snprintf(3) -! #include // For *alloc(3) -! #include // For memcpy(3) -! #include // For size_t -! #include // For LONG_MAX -! #include // For va_start -! #include // for offsetof and ptrdiff_t -! #include // For errno -! #else -! typedef char FILE; -! #include -! #include // For snprintf -! #include // For sort -! #define qsort(base,num,size,cmp_func) sort(base,num,size,cmp_func,NULL) -! #include // For errno -! #ifndef errno -! extern int errno; -! #endif -! #include "bsearch.h" -! #endif - - #ifdef WIN32 - -*************** -*** 63,69 **** - #include - #else /* !defined(__vxworks) */ - -! #include /* C99 specifies this file */ - /* - * 1. Earlier FreeBSD version didn't have , - * but was present. ---- 77,85 ---- - #include - #else /* !defined(__vxworks) */ - -! #ifdef USER_MODE -! #include /*C99 specifies this file */ -! #endif - /* - * 1. Earlier FreeBSD version didn't have , - * but was present. -*************** -*** 81,91 **** - #define inline - #endif /* __GNUC__ */ - #else -! #include /* SUSv2+ and C99 specify this file, for uintXX_t */ - #endif /* defined(sun) */ - #endif - -! #include /* for ntohl() */ - #define sys_ntohl(foo) ntohl(foo) - - #endif /* defined(__vxworks) */ ---- 97,109 ---- - #define inline - #endif /* __GNUC__ */ - #else -! #ifdef USER_MODE -! #include /*SUSv2+ and C99 specify this file, for uintXX_t */ -! #endif - #endif /* defined(sun) */ - #endif - -! /*#include for ntohl() */ - #define sys_ntohl(foo) ntohl(foo) - - #endif /* defined(__vxworks) */ -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/ber_tlv_tag.c patch_dir/ber_tlv_tag.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/ber_tlv_tag.c 2011-03-31 10:22:56.000000000 +0200 ---- patch_dir/ber_tlv_tag.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 4,10 **** - */ - #include - #include -- #include - - ssize_t - ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) { ---- 4,9 ---- -*************** -*** 57,63 **** - return 0; /* Want more */ - } - -! - ssize_t - ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) { - char buf[sizeof("[APPLICATION ]") + 32]; ---- 56,62 ---- - return 0; /* Want more */ - } - -! #ifdef USER_MODE - ssize_t - ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) { - char buf[sizeof("[APPLICATION ]") + 32]; -*************** -*** 71,76 **** ---- 70,76 ---- - - return fwrite(buf, 1, ret, f); - } -+ #endif - - ssize_t - ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) { -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/constraints.c patch_dir/constraints.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/constraints.c 2011-03-31 10:22:57.000000000 +0200 ---- patch_dir/constraints.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 1,4 **** -! #include "asn_internal.h" - #include "constraints.h" - - int ---- 1,4 ---- -! #include - #include "constraints.h" - - int -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/constr_TYPE.c patch_dir/constr_TYPE.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/constr_TYPE.c 2011-03-31 10:22:56.000000000 +0200 ---- patch_dir/constr_TYPE.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 4,10 **** - */ - #include - #include -- #include - - /* - * Version of the ASN.1 infrastructure shipped with compiler. ---- 4,9 ---- -*************** -*** 29,34 **** ---- 28,34 ---- - return type_descriptor->outmost_tag(type_descriptor, struct_ptr, 0, 0); - } - -+ #ifdef USER_MODE - /* - * Print the target language's structure in human readable form. - */ -*************** -*** 75,77 **** ---- 75,78 ---- - fprintf(stderr, "\n"); - va_end(ap); - } -+ #endif -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/der_encoder.c patch_dir/der_encoder.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/der_encoder.c 2011-03-31 10:22:56.000000000 +0200 ---- patch_dir/der_encoder.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 3,9 **** - * Redistribution and modifications are permitted subject to BSD license. - */ - #include -- #include - - static ssize_t der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len, - asn_app_consume_bytes_f *cb, void *app_key, int constructed); ---- 3,8 ---- -*************** -*** 81,89 **** ---- 80,90 ---- - asn_app_consume_bytes_f *cb, - void *app_key) { - ber_tlv_tag_t *tags; /* Copy of tags stream */ -+ ber_tlv_tag_t tags_array[8]; - int tags_count; /* Number of tags */ - size_t overall_length; - ssize_t *lens; -+ ssize_t lens_array[8]; - int i; - - ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)", -*************** -*** 102,111 **** - * and initialize it appropriately. - */ - int stag_offset; -! tags = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t)); - if(!tags) { /* Can fail on !x86 */ -! errno = ENOMEM; -! return -1; - } - tags_count = sd->tags_count - + 1 /* EXPLICIT or IMPLICIT tag is given */ ---- 103,121 ---- - * and initialize it appropriately. - */ - int stag_offset; -! //tags = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t)); -! tags = &(tags_array[0]); -! if ((sd->tags_count + 1)>=8) { -! #ifdef USER_MODE -! printf("der_encoder.c: ERROR tags array too small. Increase size!\n"); -! exit(-1); -! #endif -! errno = ENOMEM; -! return -1; -! } - if(!tags) { /* Can fail on !x86 */ -! errno = ENOMEM; -! return -1; - } - tags_count = sd->tags_count - + 1 /* EXPLICIT or IMPLICIT tag is given */ -*************** -*** 124,135 **** - if(tags_count == 0) - return 0; - -! lens = (ssize_t *)alloca(tags_count * sizeof(lens[0])); - if(!lens) { -! errno = ENOMEM; -! return -1; - } -! - /* - * Array of tags is initialized. - * Now, compute the size of the TLV pairs, from right to left. ---- 134,154 ---- - if(tags_count == 0) - return 0; - -! //lens = (ssize_t *)alloca(tags_count * sizeof(lens[0])); -! lens = &(lens_array[0]); -! if (tags_count>=8) { -! #ifdef USER_MODE -! printf("der_encoder.c: ERROR lens array too small. Increase size!\n"); -! exit(-1); -! #endif -! errno = ENOMEM; -! return -1; -! } - if(!lens) { -! errno = ENOMEM; -! return -1; - } -! - /* - * Array of tags is initialized. - * Now, compute the size of the TLV pairs, from right to left. -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/INTEGER.c patch_dir/INTEGER.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/INTEGER.c 2011-03-31 10:22:56.000000000 +0200 ---- patch_dir/INTEGER.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 6,12 **** - #include - #include - #include /* Encoder and decoder of a primitive type */ -- #include - - /* - * INTEGER basic type description. ---- 6,11 ---- -*************** -*** 103,109 **** - static ssize_t - INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) { - asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; -! char scratch[32]; /* Enough for 64-bit integer */ - uint8_t *buf = st->buf; - uint8_t *buf_end = st->buf + st->size; - signed long accum; ---- 102,108 ---- - static ssize_t - INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) { - asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; -! char scratch[128]; - uint8_t *buf = st->buf; - uint8_t *buf_end = st->buf + st->size; - signed long accum; -*************** -*** 142,149 **** ---- 141,152 ---- - - el = INTEGER_map_value2enum(specs, accum); - if(el) { -+ scrsize = sizeof(scratch); -+ scr = scratch; -+ /* cannot use alloca in kernel - scrsize = el->enum_len + 32; - scr = (char *)alloca(scrsize); -+ */ - if(plainOrXER == 0) - ret = snprintf(scr, scrsize, - "%ld (%s)", accum, el->enum_name); -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/NativeEnumerated.c patch_dir/NativeEnumerated.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/NativeEnumerated.c 2011-03-31 10:22:57.000000000 +0200 ---- patch_dir/NativeEnumerated.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 46,51 **** ---- 46,52 ---- - asn_app_consume_bytes_f *cb, void *app_key) { - asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; - asn_enc_rval_t er; -+ char scratch[128]; - const long *native = (const long *)sptr; - const asn_INTEGER_enum_map_t *el; - -*************** -*** 57,63 **** - el = INTEGER_map_value2enum(specs, *native); - if(el) { - size_t srcsize = el->enum_len + 5; -! char *src = (char *)alloca(srcsize); - - er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name); - assert(er.encoded > 0 && (size_t)er.encoded < srcsize); ---- 58,64 ---- - el = INTEGER_map_value2enum(specs, *native); - if(el) { - size_t srcsize = el->enum_len + 5; -! char *src = (char *)scratch; //alloca(srcsize); - - er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name); - assert(er.encoded > 0 && (size_t)er.encoded < srcsize); -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/OCTET_STRING.c patch_dir/OCTET_STRING.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/OCTET_STRING.c 2011-03-31 10:22:55.000000000 +0200 ---- patch_dir/OCTET_STRING.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 6,12 **** - #include - #include - #include /* for .bits_unused member */ -- #include - - /* - * OCTET STRING basic type description. ---- 6,11 ---- -diff -cB /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/xer_encoder.c patch_dir/xer_encoder.c -*** /homes/kaltenbe/Devel/openair/openair_branches/openair_lte/openair2/RRC/LITE/MESSAGES/asn1c/asn1c/skeletons/xer_encoder.c 2011-04-11 18:03:26.000000000 +0200 ---- patch_dir/xer_encoder.c 2011-05-31 10:28:26.000000000 +0200 -*************** -*** 3,10 **** - * Redistribution and modifications are permitted subject to BSD license. - */ - #include -! #include -! #include - - /* - * The XER encoder of any type. May be invoked by the application. ---- 3,10 ---- - * Redistribution and modifications are permitted subject to BSD license. - */ - #include -! //#include -! //#include - - /* - * The XER encoder of any type. May be invoked by the application. -*************** -*** 41,46 **** ---- 41,47 ---- - * This is a helper function for xer_fprint, which directs all incoming data - * into the provided file descriptor. - */ -+ #ifdef USER_MODE - static int - xer__print2fp(const void *buffer, size_t size, void *app_key) { - FILE *stream = (FILE *)app_key; -*************** -*** 65,67 **** ---- 66,69 ---- - - return fflush(stream); - } -+ #endif diff --git a/openair2/RRC/LTE/defs_NB_IoT.h b/openair2/RRC/LTE/defs_NB_IoT.h index 06b150a673..3907d2321d 100644 --- a/openair2/RRC/LTE/defs_NB_IoT.h +++ b/openair2/RRC/LTE/defs_NB_IoT.h @@ -37,6 +37,9 @@ #include "COMMON/s1ap_messages_types.h" #include "COMMON/rrc_messages_types.h" +#if ITTI_SIM +#include "COMMON/itti_sim_messages_types.h" +#endif #include "collection/tree.h" #include "rrc_types_NB_IoT.h" @@ -145,7 +148,7 @@ typedef struct UE_RRC_INFO_NB_IoT_s { //Measurement Report not supported in NB-IoT #define PAYLOAD_SIZE_MAX 1024 -#define RRC_BUF_SIZE 255 +#define RRC_BUF_SIZE 8192 #define UNDEF_SECURITY_MODE 0xff #define NO_SECURITY_MODE 0x20 @@ -208,13 +211,13 @@ typedef struct RB_INFO_TABLE_ENTRY_NB_IoT_s { RB_INFO_NB_IoT Rb_info; uint8_t Active; uint32_t Next_check_frame; - uint8_t Status; + uint8_t status; } RB_INFO_TABLE_ENTRY_NB_IoT; typedef struct SRB_INFO_TABLE_ENTRY_NB_IoT_s { SRB_INFO_NB_IoT Srb_info; uint8_t Active; - uint8_t Status; + uint8_t status; uint32_t Next_check_frame; } SRB_INFO_TABLE_ENTRY_NB_IoT; @@ -266,7 +269,7 @@ typedef struct eNB_RRC_UE_NB_IoT_s { e_LTE_CipheringAlgorithm_r12 ciphering_algorithm; //Specs. TS 36.331 V14.1.0 pag 432 Change position of chipering enumerative w.r.t previous version e_LTE_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm; - uint8_t Status; + uint8_t status; rnti_t rnti; uint64_t random_ue_identity; diff --git a/openair2/RRC/LTE/plmn_data.h b/openair2/RRC/LTE/plmn_data.h index 97dc94343b..701bcaf764 100644 --- a/openair2/RRC/LTE/plmn_data.h +++ b/openair2/RRC/LTE/plmn_data.h @@ -2231,7 +2231,8 @@ static const plmn_data_t plmn_data[] = { /* 310 900 Mid-Rivers Communications Mid-Rivers Wireless Operational */ - {310, 910, "Verizon Wireless", "Verizon USA"} + {310, 910, "Verizon Wireless", "Verizon USA"}, + {0,0,"",""} /* 310 920 Get Mobile Inactive 310 930 Copper Valley Wireless Inactive diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index c5aa2bc0f8..4b862fa11d 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -330,7 +330,7 @@ void init_SL_preconfig(UE_RRC_INST *UE, const uint8_t eNB_index ) { preconfigpool->data_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12 = 0; // 40 ms SL Period preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.present = LTE_SubframeBitmapSL_r12_PR_bs40_r12; - preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf = CALLOC(1,5); + preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf = CALLOC(5,1); preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size = 5; preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = 0; // last 36 subframes for PSCCH @@ -338,7 +338,7 @@ void init_SL_preconfig(UE_RRC_INST *UE, const uint8_t eNB_index ) { preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[1] = 0xFF; preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[2] = 0xFF; preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[3] = 0xFF; - preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[5] = 0xFF; + preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[4] = 0xFF; preconfigpool->dataHoppingConfig_r12.hoppingParameter_r12 = 0; preconfigpool->dataHoppingConfig_r12.numSubbands_r12 = LTE_SL_HoppingConfigComm_r12__numSubbands_r12_ns1; preconfigpool->dataHoppingConfig_r12.rb_Offset_r12 = 0; @@ -393,15 +393,7 @@ char openair_rrc_ue_init( const module_id_t ue_mod_idP, const unsigned char eNB_ init_SI_UE(&ctxt,eNB_index); LOG_D(RRC,PROTOCOL_RRC_CTXT_FMT" INIT: phy_sync_2_ch_ind\n", PROTOCOL_RRC_CTXT_ARGS(&ctxt)); -#ifndef NO_RRM - send_msg(&S_rrc,msg_rrc_phy_synch_to_CH_ind(ctxt.module_id,eNB_index,UE_rrc_inst[ctxt.module_id].Mac_id)); -#endif -#ifndef NO_RRM - send_msg(&S_rrc,msg_rrc_phy_synch_to_CH_ind(ctxt.module_id,eNB_index,UE_rrc_inst[ctxt.module_id].Mac_id)); -#endif -#ifdef NO_RRM //init ch SRB0, SRB1 & BDTCH openair_rrc_on_ue(&ctxt); -#endif return 0; } @@ -492,7 +484,7 @@ rrc_t310_expiration( UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id, Rlc_info_um); UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Active = 0; - UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Status = IDLE; + UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].StatusSrb = IDLE; UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Next_check_frame = 0; } } else { // Restablishment procedure @@ -671,7 +663,7 @@ rrc_ue_establish_srb1( { // add descriptor from RRC PDU UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Active = 1; - UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Status = RADIO_CONFIG_OK;//RADIO CFG + UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].StatusSrb = RADIO_CONFIG_OK;//RADIO CFG UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Srb_info.Srb_id = 1; // copy default configuration for now // memcpy(&UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Srb_info.Lchan_desc[0],&DCCH_LCHAN_DESC,LCHAN_DESC_SIZE); @@ -695,7 +687,7 @@ rrc_ue_establish_srb2( { // add descriptor from RRC PDU UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Active = 1; - UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Status = RADIO_CONFIG_OK;//RADIO CFG + UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].StatusSrb = RADIO_CONFIG_OK;//RADIO CFG UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Srb_info.Srb_id = 2; // copy default configuration for now // memcpy(&UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Srb_info.Lchan_desc[0],&DCCH_LCHAN_DESC,LCHAN_DESC_SIZE); @@ -1796,7 +1788,7 @@ rrc_ue_process_rrcConnectionReconfiguration( for (list_count = 0; list_count < rrcConnectionReconfiguration_r8->dedicatedInfoNASList->list.count; list_count++) { pdu_length = rrcConnectionReconfiguration_r8->dedicatedInfoNASList->list.array[list_count]->size; pdu_buffer = rrcConnectionReconfiguration_r8->dedicatedInfoNASList->list.array[list_count]->buf; - msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_CONN_ESTABLI_CNF); + msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_CONN_ESTABLI_CNF); NAS_CONN_ESTABLI_CNF(msg_p).errCode = AS_SUCCESS; NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length = pdu_length; NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data = pdu_buffer; @@ -1811,7 +1803,7 @@ rrc_ue_process_rrcConnectionReconfiguration( MessageDef *message_ral_p = NULL; rrc_ral_connection_reestablishment_ind_t connection_reestablishment_ind; int i; - message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_CONNECTION_REESTABLISHMENT_IND); + message_ral_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_RAL_CONNECTION_REESTABLISHMENT_IND); memset(&connection_reestablishment_ind, 0, sizeof(rrc_ral_connection_reestablishment_ind_t)); // TO DO ral_si_ind.plmn_id = 0; connection_reestablishment_ind.ue_id = ctxt_pP->rnti; @@ -2007,7 +1999,7 @@ rrc_ue_decode_dcch( MessageDef *msg_p; pdu_length = dedicatedInfoType->choice.dedicatedInfoNAS.size; pdu_buffer = dedicatedInfoType->choice.dedicatedInfoNAS.buf; - msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_DOWNLINK_DATA_IND); + msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_DOWNLINK_DATA_IND); NAS_DOWNLINK_DATA_IND(msg_p).UEid = ctxt_pP->module_id; // TODO set the UEid to something else ? NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length = pdu_length; NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data = pdu_buffer; @@ -2073,7 +2065,7 @@ rrc_ue_decode_dcch( MessageDef *message_ral_p = NULL; rrc_ral_connection_reconfiguration_ho_ind_t connection_reconfiguration_ho_ind; int i; - message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_CONNECTION_RECONFIGURATION_HO_IND); + message_ral_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_RAL_CONNECTION_RECONFIGURATION_HO_IND); memset(&connection_reconfiguration_ho_ind, 0, sizeof(rrc_ral_connection_reconfiguration_ho_ind_t)); connection_reconfiguration_ho_ind.ue_id = ctxt_pP->module_id; @@ -2127,7 +2119,7 @@ rrc_ue_decode_dcch( MessageDef *message_ral_p = NULL; rrc_ral_connection_reconfiguration_ind_t connection_reconfiguration_ind; int i; - message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_CONNECTION_RECONFIGURATION_IND); + message_ral_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_RAL_CONNECTION_RECONFIGURATION_IND); memset(&connection_reconfiguration_ind, 0, sizeof(rrc_ral_connection_reconfiguration_ind_t)); connection_reconfiguration_ind.ue_id = ctxt_pP->module_id; @@ -2189,7 +2181,7 @@ rrc_ue_decode_dcch( break; case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionRelease: - msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_CONN_RELEASE_IND); + msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_CONN_RELEASE_IND); if ((dl_dcch_msg->message.choice.c1.choice.rrcConnectionRelease.criticalExtensions.present == LTE_RRCConnectionRelease__criticalExtensions_PR_c1) @@ -2201,7 +2193,7 @@ rrc_ue_decode_dcch( itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); #if ENABLE_RAL - msg_p = itti_alloc_new_message(TASK_RRC_UE, RRC_RAL_CONNECTION_RELEASE_IND); + msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, RRC_RAL_CONNECTION_RELEASE_IND); RRC_RAL_CONNECTION_RELEASE_IND(msg_p).ue_id = ctxt_pP->module_id; itti_send_msg_to_task(TASK_RAL_UE, ctxt_pP->instance, msg_p); #endif @@ -2249,9 +2241,6 @@ rrc_ue_decode_dcch( } } -#ifndef NO_RRM - send_msg(&S_rrc,msg_rrc_end_scan_req(ctxt_pP->module_id,eNB_indexP)); -#endif } const char siWindowLength[9][5] = {"1ms","2ms","5ms","10ms","15ms","20ms","40ms","80ms","ERR"}; @@ -2530,14 +2519,6 @@ int decode_BCCH_MBMS_DLSCH_Message( break; } }*/ - /*if ((rrc_get_sub_state(ctxt_pP->module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE) - #if defined(ENABLE_USE_MME) - && (UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL) - #endif - ) { - rrc_ue_generate_RRCConnectionRequest(ctxt_pP, 0); - rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_CONNECTING ); - }*/ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); return 0; } @@ -2837,7 +2818,7 @@ int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_in ) ) { MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_CELL_SELECTION_CNF); + msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_CELL_SELECTION_CNF); NAS_CELL_SELECTION_CNF (msg_p).errCode = AS_SUCCESS; NAS_CELL_SELECTION_CNF (msg_p).cellID = BIT_STRING_to_uint32(&sib1->cellAccessRelatedInfo.cellIdentity); NAS_CELL_SELECTION_CNF (msg_p).tac = BIT_STRING_to_uint16(&sib1->cellAccessRelatedInfo.trackingAreaCode); @@ -2853,7 +2834,7 @@ int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_in if (cell_valid == 0) { MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ); + msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, PHY_FIND_NEXT_CELL_REQ); itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n"); } @@ -2969,6 +2950,12 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIwindowsize = siWindowLength_int[sib1->si_WindowLength]; LOG_I( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n", ctxt_pP->module_id, eNB_index, ctxt_pP->module_id ); + /* pointers to SIperiod inthe Info struct points to a packed structure + * Using these possibly unaligned pointers in a function call may trigger alignment errors at run time and + * gcc, from v9, now warns about it. fix these warnings by removing the indirection on data + * Not sure if SiPeriod can be modified, reassign after function call for security + */ + uint16_t Aligned_SIperiod = UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod; rrc_mac_config_req_ue(ctxt_pP->module_id, 0, eNB_index, (LTE_RadioResourceConfigCommonSIB_t *)NULL, (struct LTE_PhysicalConfigDedicated *)NULL, @@ -2981,7 +2968,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]->tdd_Config, (LTE_MobilityControlInfo_t *) NULL, &UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIwindowsize, - &UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod, + &Aligned_SIperiod, NULL, NULL, NULL, @@ -2995,6 +2982,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, (struct LTE_NonMBSFN_SubframeConfig_r14 *)NULL, (LTE_MBSFN_AreaInfoList_r9_t *)NULL ); + UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod=Aligned_SIperiod; LOG_I(RRC,"Setting SIStatus bit 0 to 1\n"); UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus = 1; UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag; @@ -3036,7 +3024,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, ) { /* PLMN match, send a confirmation to NAS */ MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_CELL_SELECTION_CNF); + msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, NAS_CELL_SELECTION_CNF); NAS_CELL_SELECTION_CNF (msg_p).errCode = AS_SUCCESS; NAS_CELL_SELECTION_CNF (msg_p).cellID = BIT_STRING_to_uint32(&sib1->cellAccessRelatedInfo.cellIdentity); NAS_CELL_SELECTION_CNF (msg_p).tac = BIT_STRING_to_uint16(&sib1->cellAccessRelatedInfo.trackingAreaCode); @@ -3054,7 +3042,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, if (cell_valid == 0) { /* Cell can not be used, ask PHY to try the next one */ MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ); + msg_p = itti_alloc_new_message(TASK_RRC_UE, 0, PHY_FIND_NEXT_CELL_REQ); itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM " @@ -3672,7 +3660,7 @@ int decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index ) { { MessageDef *message_ral_p = NULL; rrc_ral_system_information_ind_t ral_si_ind; - message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_SYSTEM_INFORMATION_IND); + message_ral_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_RAL_SYSTEM_INFORMATION_IND); memset(&ral_si_ind, 0, sizeof(rrc_ral_system_information_ind_t)); ral_si_ind.plmn_id.MCCdigit2 = '0'; ral_si_ind.plmn_id.MCCdigit1 = '2'; @@ -4456,7 +4444,7 @@ void *rrc_ue_task( void *args_p ) { while(1) { // Wait for a message itti_receive_msg (TASK_RRC_UE, &msg_p); - instance = ITTI_MSG_INSTANCE (msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); ue_mod_id = UE_INSTANCE_TO_MODULE_ID(instance); switch (ITTI_MSG_ID(msg_p)) { @@ -4645,7 +4633,7 @@ void *rrc_ue_task( void *args_p ) { case RRC_STATE_IDLE: { /* Ask to layer 1 to find a cell matching the criterion */ MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_CELL_REQ); + message_p = itti_alloc_new_message(TASK_RRC_UE, 0, PHY_FIND_CELL_REQ); PHY_FIND_CELL_REQ (message_p).earfcn_start = 1; PHY_FIND_CELL_REQ (message_p).earfcn_end = 1; itti_send_msg_to_task(TASK_PHY_UE, UE_MODULE_ID_TO_INSTANCE(ue_mod_id), message_p); @@ -4748,7 +4736,7 @@ void *rrc_ue_task( void *args_p ) { if (rrc_get_sub_state(ue_mod_id) != RRC_SUB_STATE_IDLE_SEARCHING) { /* Ask to layer 1 to find a cell matching the criterion */ MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_CELL_REQ); + message_p = itti_alloc_new_message(TASK_RRC_UE, 0, PHY_FIND_CELL_REQ); rrc_set_sub_state (ue_mod_id, RRC_SUB_STATE_IDLE_SEARCHING); PHY_FIND_CELL_REQ (message_p).transaction_id = RRC_RAL_SCAN_REQ (msg_p).transaction_id; PHY_FIND_CELL_REQ (message_p).earfcn_start = 1; @@ -4780,7 +4768,7 @@ void *rrc_ue_task( void *args_p ) { case RRC_SUB_STATE_IDLE_SEARCHING: { MessageDef *message_p; int i; - message_p = itti_alloc_new_message(TASK_RRC_UE, RRC_RAL_SCAN_CONF); + message_p = itti_alloc_new_message(TASK_RRC_UE, 0, RRC_RAL_SCAN_CONF); RRC_RAL_SCAN_CONF (message_p).transaction_id = PHY_FIND_CELL_IND(msg_p).transaction_id; RRC_RAL_SCAN_CONF (message_p).num_scan_resp = PHY_FIND_CELL_IND(msg_p).cell_nb; @@ -4823,7 +4811,7 @@ void *rrc_ue_task( void *args_p ) { case PHY_MEAS_REPORT_IND: { LOG_D(RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_UE, RRC_RAL_MEASUREMENT_REPORT_IND); + message_p = itti_alloc_new_message(TASK_RRC_UE, 0, RRC_RAL_MEASUREMENT_REPORT_IND); memcpy(&RRC_RAL_MEASUREMENT_REPORT_IND (message_p).threshold, &PHY_MEAS_REPORT_IND(msg_p).threshold, sizeof(RRC_RAL_MEASUREMENT_REPORT_IND (message_p).threshold)); diff --git a/openair2/RRC/LTE/rrc_UE_ral.c b/openair2/RRC/LTE/rrc_UE_ral.c index d7ace8c242..1ebba43d8b 100644 --- a/openair2/RRC/LTE/rrc_UE_ral.c +++ b/openair2/RRC/LTE/rrc_UE_ral.c @@ -126,7 +126,7 @@ int rrc_ue_ral_handle_configure_threshold_request(unsigned int mod_idP, MessageD message_p = itti_alloc_new_message (TASK_RRC_UE, PHY_MEAS_THRESHOLD_REQ); PHY_MEAS_THRESHOLD_REQ(message_p).transaction_id = transaction_id; memcpy (&PHY_MEAS_THRESHOLD_REQ(message_p).cfg_param, (void *) link_cfg_param_p, sizeof(ral_link_cfg_param_t)); - itti_send_msg_to_task (TASK_PHY_UE, ITTI_MSG_INSTANCE(msg_pP), message_p); + itti_send_msg_to_task (TASK_PHY_UE, ITTI_MSG_DESTINATION_INSTANCE(msg_pP), message_p); break; default: @@ -147,7 +147,7 @@ int rrc_ue_ral_handle_configure_threshold_request(unsigned int mod_idP, MessageD message_p = itti_alloc_new_message (TASK_RRC_UE, PHY_MEAS_THRESHOLD_REQ); PHY_MEAS_THRESHOLD_REQ(message_p).transaction_id = transaction_id; memcpy (&PHY_MEAS_THRESHOLD_REQ(message_p).cfg_param, (void *) link_cfg_param_p, sizeof(ral_link_cfg_param_t)); - itti_send_msg_to_task (TASK_MAC_UE, ITTI_MSG_INSTANCE(msg_pP), message_p); + itti_send_msg_to_task (TASK_MAC_UE, ITTI_MSG_DESTINATION_INSTANCE(msg_pP), message_p); break; default: @@ -166,7 +166,7 @@ int rrc_ue_ral_handle_configure_threshold_request(unsigned int mod_idP, MessageD message_p = itti_alloc_new_message (TASK_RRC_UE, PHY_MEAS_THRESHOLD_REQ); PHY_MEAS_THRESHOLD_REQ(message_p).transaction_id = transaction_id; memcpy (&PHY_MEAS_THRESHOLD_REQ(message_p).cfg_param, (void *) link_cfg_param_p, sizeof(ral_link_cfg_param_t)); - itti_send_msg_to_task (TASK_PHY_UE, ITTI_MSG_INSTANCE(msg_pP), message_p); + itti_send_msg_to_task (TASK_PHY_UE, ITTI_MSG_DESTINATION_INSTANCE(msg_pP), message_p); break; case RAL_LINK_PARAM_LTE_AVAILABLE_BW: @@ -176,7 +176,7 @@ int rrc_ue_ral_handle_configure_threshold_request(unsigned int mod_idP, MessageD message_p = itti_alloc_new_message (TASK_RRC_UE, PHY_MEAS_THRESHOLD_REQ); PHY_MEAS_THRESHOLD_REQ(message_p).transaction_id = transaction_id; memcpy (&PHY_MEAS_THRESHOLD_REQ(message_p).cfg_param, (void *) link_cfg_param_p, sizeof(ral_link_cfg_param_t)); - itti_send_msg_to_task (TASK_MAC_UE, ITTI_MSG_INSTANCE(msg_pP), message_p); + itti_send_msg_to_task (TASK_MAC_UE, ITTI_MSG_DESTINATION_INSTANCE(msg_pP), message_p); break; case RAL_LINK_PARAM_LTE_MOBILE_NODE_CAPABILITIES: diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index c498e3c6fe..40aad67a06 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -67,6 +67,8 @@ #define MAX_NUM_NEIGH_CELLs 6 /* maximum neighbouring cells number */ +#define MAX_NUM_GNB_CELLs 1 /* maximum gNB cells number */ + #define UE_STATE_NOTIFICATION_INTERVAL 50 #define IPV4_ADDR "%u.%u.%u.%u" @@ -171,13 +173,6 @@ extern pthread_mutex_t slrb_mutex; //the thread function void *send_UE_status_notification(void *); - - -//#include "COMMON/openair_defs.h" -#ifndef USER_MODE - //#include -#endif - #include "LTE_SystemInformationBlockType1.h" #include "LTE_SystemInformation.h" #include "LTE_RRCConnectionReconfiguration.h" @@ -215,12 +210,6 @@ void *send_UE_status_notification(void *); #define NB_SIG_CNX_UE 2 //MAX_MANAGED_RG_PER_MOBILE #define NB_CNX_UE 2//MAX_MANAGED_RG_PER_MOBILE -#ifndef NO_RRM - #include "L3_rrc_interface.h" - #include "rrc_rrm_msg.h" - #include "rrc_rrm_interface.h" -#endif - #include "intertask_interface.h" @@ -271,7 +260,8 @@ typedef enum UE_STATE_e { RRC_RECONFIGURED, RRC_HO_EXECUTION, RRC_NR_NSA, - RRC_NR_NSA_RECONFIGURED + RRC_NR_NSA_RECONFIGURED, + RRC_NR_NSA_DELETED } UE_STATE_t; typedef enum HO_STATE_e { @@ -326,7 +316,7 @@ typedef enum SL_TRIGGER_e { #define MAX_MEAS_ID 6 #define PAYLOAD_SIZE_MAX 1024 -#define RRC_BUF_SIZE 255 +#define RRC_BUF_SIZE 8192 #define UNDEF_SECURITY_MODE 0xff #define NO_SECURITY_MODE 0x20 @@ -361,7 +351,7 @@ typedef struct UE_RRC_INFO_s { uint8_t SIwindowsize_MBMS; //!< Corresponds to the SIB1 si-WindowLength parameter. The unit is ms. Possible values are (final): 1,2,5,10,15,20,40 uint8_t handoverTarget; HO_STATE_t ho_state; - uint16_t SIperiod; //!< Corresponds to the SIB1 si-Periodicity parameter (multiplied by 10). Possible values are (final): 80,160,320,640,1280,2560,5120 + uint16_t SIperiod ; //!< Corresponds to the SIB1 si-Periodicity parameter (multiplied by 10). Possible values are (final): 80,160,320,640,1280,2560,5120 uint16_t SIperiod_MBMS; //!< Corresponds to the SIB1-MBMS si-Periodicity parameter (multiplied by 10). Possible values are (final): 80,160,320,640,1280,2560,5120 TODO unsigned short UE_index; uint32_t T300_active; @@ -516,13 +506,13 @@ typedef struct RB_INFO_TABLE_ENTRY_s { RB_INFO Rb_info; uint8_t Active; uint32_t Next_check_frame; - uint8_t Status; + uint8_t StatusRb; } RB_INFO_TABLE_ENTRY; typedef struct SRB_INFO_TABLE_ENTRY_s { SRB_INFO Srb_info; uint8_t Active; - uint8_t Status; + uint8_t StatusSrb; uint32_t Next_check_frame; } SRB_INFO_TABLE_ENTRY; @@ -545,6 +535,13 @@ typedef struct rrc_gummei_s { uint16_t mme_group_id; } rrc_gummei_t; +typedef struct { + uint16_t ciphering_algorithms; + uint16_t integrity_algorithms; + uint16_t sk_counter; + uint8_t kgNB[32]; +} lte_rrc_nr_security_t; + typedef struct eNB_RRC_UE_s { uint8_t primaryCC_id; LTE_SCellToAddMod_r10_t sCell_config[2]; @@ -553,7 +550,7 @@ typedef struct eNB_RRC_UE_s { LTE_DRB_ToAddModList_t *DRB_configList; LTE_DRB_ToAddModList_t *DRB_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER]; LTE_DRB_ToReleaseList_t *DRB_Release_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER]; - uint8_t DRB_active[8]; + uint8_t DRB_active[NB_RB_MAX -2]; struct LTE_PhysicalConfigDedicated *physicalConfigDedicated; struct LTE_SPS_Config *sps_Config; LTE_MeasObjectToAddMod_t *MeasObj[MAX_MEAS_OBJ]; @@ -589,8 +586,10 @@ typedef struct eNB_RRC_UE_s { LTE_CipheringAlgorithm_r12_t ciphering_algorithm; e_LTE_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm; - uint8_t Status; // RRC status, type enum UE_STATE_t + uint8_t StatusRrc; // RRC status, type enum UE_STATE_t rnti_t rnti; + int gnb_rnti; //RNTI of the UE at the gNB if in ENDC connection + int gnb_x2_assoc_id; uint64_t random_ue_identity; @@ -612,6 +611,9 @@ typedef struct eNB_RRC_UE_s { security_capabilities_t security_capabilities; + /* security capabilities and settings for an UE in ENDC mode */ + lte_rrc_nr_security_t nr_security; + int next_hop_chain_count; uint8_t next_security_key[SECURITY_KEY_LENGTH]; @@ -791,6 +793,15 @@ typedef struct eNB_RRC_INST_s { int num_neigh_cells_cc[MAX_NUM_CCs]; uint32_t neigh_cells_id[MAX_NUM_NEIGH_CELLs][MAX_NUM_CCs]; + // gNB cells connected to this eNB + int num_gnb_cells; + int num_gnb_cells_cc[MAX_NUM_GNB_CELLs]; + uint32_t gnb_cells_id[MAX_NUM_GNB_CELLs][MAX_NUM_CCs]; + + // Nr scc freq band and SSB absolute frequency + uint32_t nr_gnb_freq_band[MAX_NUM_GNB_CELLs][MAX_NUM_CCs]; + int nr_scg_ssb_freq; + // other RAN parameters int srb1_timer_poll_retransmit; int srb1_poll_pdu; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index b6062df2c4..9283b64ded 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -87,6 +87,7 @@ #include "pdcp.h" #include "gtpv1u_eNB_task.h" +#include #include "intertask_interface.h" @@ -103,13 +104,9 @@ static int is_en_dc_supported(LTE_UE_EUTRA_Capability_t *c); extern RAN_CONTEXT_t RC; -#ifdef PHY_EMUL - extern EMULATION_VARS *Emul_vars; -#endif extern eNB_MAC_INST *eNB_mac_inst; extern UE_MAC_INST *UE_mac_inst; -extern uint16_t two_tier_hexagonal_cellIds[7]; mui_t rrc_eNB_mui = 0; @@ -155,7 +152,6 @@ init_SI( LOG_D(RRC,"%s()\n\n\n\n",__FUNCTION__); if(configuration->radioresourceconfig[CC_id].mbms_dedicated_serving_cell == TRUE) { - LOG_I(RRC, "Configuring MIB FeMBMS (N_RB_DL %d)\n", (int)configuration->N_RB_DL[CC_id]); RC.rrc[ctxt_pP->module_id]->carrier[CC_id].MIB_FeMBMS = (uint8_t *) malloc16(4); @@ -333,7 +329,7 @@ init_SI( if (carrier->MBMS_flag > 0) { for (i = 0; i < carrier->sib2->mbsfn_SubframeConfigList->list.count; i++) { // SIB 2 - // LOG_D(RRC, "[eNB %d] mbsfn_SubframeConfigList.list.count = %ld\n", enb_mod_idP, RC.rrc[enb_mod_idP].sib2->mbsfn_SubframeConfigList->list.count); + // LOG_D(RRC, "[eNB %ld] mbsfn_SubframeConfigList.list.count = %ld\n", enb_mod_idP, RC.rrc[enb_mod_idP].sib2->mbsfn_SubframeConfigList->list.count); LOG_D(RRC, PROTOCOL_RRC_CTXT_FMT" SIB13 contents for MBSFN subframe allocation %d/%d(partial)\n", PROTOCOL_RRC_CTXT_ARGS(ctxt_pP), i, @@ -500,13 +496,17 @@ init_SI( RC.rrc[ctxt_pP->module_id]->carrier[CC_id].FeMBMS_flag, (carrier->sib1_MBMS==NULL?(LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL:(LTE_BCCH_DL_SCH_Message_MBMS_t *)carrier->sib1_MBMS),//(LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL, (LTE_SchedulingInfo_MBMS_r14_t *) NULL, - (carrier->sib1_MBMS==NULL?(struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL:(struct LTE_NonMBSFN_SubframeConfig_r14 *)carrier->sib1_MBMS->nonMBSFN_SubframeConfig_r14),//(struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, - (carrier->sib1_MBMS==NULL?(LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL:(LTE_SystemInformationBlockType1_MBMS_r14_t *)carrier->sib1_MBMS->systemInformationBlockType13_r14),//(LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (carrier->sib1_MBMS==NULL?(LTE_MBSFN_AreaInfoList_r9_t *) NULL:(LTE_MBSFN_AreaInfoList_r9_t *)&carrier->sib1_MBMS->systemInformationBlockType13_r14->mbsfn_AreaInfoList_r9)//(LTE_MBSFN_AreaInfoList_r9_t *) NULL - - ,(LTE_MBSFNAreaConfiguration_r9_t*) NULL - - ); + (carrier->sib1_MBMS==NULL + ? (struct LTE_NonMBSFN_SubframeConfig_r14 *)NULL + : (struct LTE_NonMBSFN_SubframeConfig_r14 *)carrier->sib1_MBMS->nonMBSFN_SubframeConfig_r14),//(struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, + (carrier->sib1_MBMS==NULL + ? (LTE_SystemInformationBlockType1_MBMS_r14_t *)NULL + : (LTE_SystemInformationBlockType1_MBMS_r14_t *)carrier->sib1_MBMS->systemInformationBlockType13_r14),//(LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, + (carrier->sib1_MBMS==NULL + ? (LTE_MBSFN_AreaInfoList_r9_t *)NULL + : (LTE_MBSFN_AreaInfoList_r9_t *)&carrier->sib1_MBMS->systemInformationBlockType13_r14->mbsfn_AreaInfoList_r9),//(LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *)NULL + ); } /* set flag to indicate that cell information is configured. This is required @@ -590,7 +590,7 @@ init_MCCH( (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, - (LTE_MBSFNAreaConfiguration_r9_t*) NULL + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); } @@ -993,6 +993,7 @@ void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag) { free_list = &eNB_MAC->UE_free_list; free_list->UE_free_ctrl[free_list->tail_freelist].rnti = rnti; free_list->UE_free_ctrl[free_list->tail_freelist].removeContextFlg = removeFlag; + free_list->UE_free_ctrl[free_list->tail_freelist].raFlag = 0; free_list->num_UEs++; eNB_MAC->UE_release_req.ue_release_request_body.ue_release_request_TLVs_list[eNB_MAC->UE_release_req.ue_release_request_body.number_of_TLVs].rnti = rnti; eNB_MAC->UE_release_req.ue_release_request_body.number_of_TLVs++; @@ -1040,59 +1041,59 @@ void release_UE_in_freeList(module_id_t mod_id) { for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { eNB_PHY = RC.eNB[mod_id][CC_id]; + int id; + // clean ULSCH entries for rnti + id = find_ulsch(rnti,eNB_PHY,eNB_MAC->UE_free_list.UE_free_ctrl[ue_num].raFlag ? SEARCH_EXIST_RA : SEARCH_EXIST); - int id; - - // clean ULSCH entries for rnti - id = find_ulsch(rnti,eNB_PHY,SEARCH_EXIST); if (id>=0) clean_eNb_ulsch(eNB_PHY->ulsch[id]); - // clean DLSCH entries for rnti - id = find_dlsch(rnti,eNB_PHY,SEARCH_EXIST); + // clean DLSCH entries for rnti + id = find_dlsch(rnti,eNB_PHY,eNB_MAC->UE_free_list.UE_free_ctrl[ue_num].raFlag ? SEARCH_EXIST_RA : SEARCH_EXIST); + if (id>=0) clean_eNb_dlsch(eNB_PHY->dlsch[id][0]); - // clean UCI entries for rnti - for (i=0; iuci_vars[i].rnti == rnti) { LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti); memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI)); } } - - /* - for (i=0; iulsch[i]; - if((ulsch != NULL) && (ulsch->rnti == rnti)) { - void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); - LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); - clean_eNb_ulsch(ulsch); - } + /* + for (i=0; iulsch[i]; - dlsch = eNB_PHY->dlsch[i][0]; + if((ulsch != NULL) && (ulsch->rnti == rnti)) { + void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); + LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); + clean_eNb_ulsch(ulsch); + } - if((dlsch != NULL) && (dlsch->rnti == rnti)) { - void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); - LOG_I(RRC, "clean_eNb_dlsch dlsch[%d] UE %x \n", i, rnti); - clean_eNb_dlsch(dlsch); - } - } + dlsch = eNB_PHY->dlsch[i][0]; - ulsch = eNB_PHY->ulsch[i]; + if((dlsch != NULL) && (dlsch->rnti == rnti)) { + void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); + LOG_I(RRC, "clean_eNb_dlsch dlsch[%d] UE %x \n", i, rnti); + clean_eNb_dlsch(dlsch); + } + } - if((ulsch != NULL) && (ulsch->rnti == rnti)) { - void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); - LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); - clean_eNb_ulsch(ulsch); - } + ulsch = eNB_PHY->ulsch[i]; - for (i=0; iuci_vars[i].rnti == rnti) { - LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti); - memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI)); - } - } - */ + if((ulsch != NULL) && (ulsch->rnti == rnti)) { + void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); + LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); + clean_eNb_ulsch(ulsch); + } + + for (i=0; iuci_vars[i].rnti == rnti) { + LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti); + memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI)); + } + } + */ if (flexran_agent_get_rrc_xface(mod_id)) { flexran_agent_get_rrc_xface(mod_id)->flexran_agent_notify_ue_state_change( @@ -1129,7 +1130,7 @@ void release_UE_in_freeList(module_id_t mod_id) { rrc_rlc_remove_ue(&ctxt); pdcp_remove_UE(&ctxt); } else { - MessageDef *m = itti_alloc_new_message(TASK_RRC_ENB, F1AP_UE_CONTEXT_RELEASE_CMD); + MessageDef *m = itti_alloc_new_message(TASK_RRC_ENB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); F1AP_UE_CONTEXT_RELEASE_CMD(m).rnti = rnti; F1AP_UE_CONTEXT_RELEASE_CMD(m).cause = F1AP_CAUSE_RADIO_NETWORK; F1AP_UE_CONTEXT_RELEASE_CMD(m).cause_value = 10; // 10 = F1AP_CauseRadioNetwork_normal_release @@ -1198,7 +1199,7 @@ rrc_eNB_process_RRCConnectionSetupComplete( LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, " "processing LTE_RRCConnectionSetupComplete from UE (SRB1 Active)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); ue_context_pP->ue_context.Srb1.Active = 1; - ue_context_pP->ue_context.Status = RRC_CONNECTED; + ue_context_pP->ue_context.StatusRrc = RRC_CONNECTED; ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity timer when UE goes into RRC_CONNECTED T(T_ENB_RRC_CONNECTION_SETUP_COMPLETE, T_INT(ctxt_pP->module_id), @@ -1279,10 +1280,14 @@ rrc_eNB_generate_UECapabilityEnquiry( uint8_t size; T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + int16_t eutra_band = RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0]; + uint32_t nr_band = RC.rrc[ctxt_pP->module_id]->nr_gnb_freq_band[0][0]; size = do_UECapabilityEnquiry( ctxt_pP, buffer, - rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id)); + rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id), + eutra_band, + nr_band); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate UECapabilityEnquiry (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), @@ -1325,10 +1330,14 @@ rrc_eNB_generate_NR_UECapabilityEnquiry( uint8_t size; T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + int16_t eutra_band = RC.rrc[ctxt_pP->module_id]->configuration.eutra_band[0]; + uint32_t nr_band = RC.rrc[ctxt_pP->module_id]->nr_gnb_freq_band[0][0]; size = do_NR_UECapabilityEnquiry( ctxt_pP, buffer, - rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id)); + rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id), + eutra_band, + nr_band); LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate NR UECapabilityEnquiry (bytes %d)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), @@ -1488,7 +1497,7 @@ rrc_eNB_generate_RRCConnectionReestablishment( (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, - (LTE_MBSFNAreaConfiguration_r9_t*) NULL + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); break; } @@ -1566,7 +1575,7 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete( int measurements_enabled; uint8_t next_xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id); int ret = 0; - ue_context_pP->ue_context.Status = RRC_CONNECTED; + ue_context_pP->ue_context.StatusRrc = RRC_CONNECTED; ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED ue_context_pP->ue_context.reestablishment_xid = next_xid; SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; @@ -2162,7 +2171,7 @@ void rrc_generate_SgNBReleaseRequest( //----------------------------------------------------------------------------- { MessageDef *msg; - msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_ENDC_SGNB_RELEASE_REQ); + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_RELEASE_REQ); memset(&(X2AP_ENDC_SGNB_RELEASE_REQ(msg)), 0, sizeof(x2ap_ENDC_sgnb_release_req_t)); // X2AP_ENDC_SGNB_RELEASE_REQ(msg).MeNB_ue_x2_id = ; // X2AP_ENDC_SGNB_RELEASE_REQ(msg).SgNB_ue_x2_id = ; @@ -2190,14 +2199,13 @@ rrc_eNB_generate_RRCConnectionRelease( uint8_t buffer[RRC_BUF_SIZE]; uint16_t size = 0; int release_num; - memset(buffer, 0, RRC_BUF_SIZE); T(T_ENB_RRC_CONNECTION_RELEASE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); #if 0 if(ue_context_pP != NULL) { - if(ue_context_pP->ue_context.Status == RRC_NR_NSA) { + if(ue_context_pP->ue_context.StatusRrc == RRC_NR_NSA) { //rrc_eNB_generate_SgNBReleaseRequest(ctxt_pP,ue_context_pP); } } @@ -2258,7 +2266,7 @@ rrc_eNB_generate_RRCConnectionRelease( pthread_mutex_unlock(&rrc_release_freelist); if (NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { - MessageDef *m = itti_alloc_new_message(TASK_RRC_ENB, F1AP_UE_CONTEXT_RELEASE_CMD); + MessageDef *m = itti_alloc_new_message(TASK_RRC_ENB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); F1AP_UE_CONTEXT_RELEASE_CMD(m).rnti = ctxt_pP->rnti; F1AP_UE_CONTEXT_RELEASE_CMD(m).cause = F1AP_CAUSE_RADIO_NETWORK; F1AP_UE_CONTEXT_RELEASE_CMD(m).cause_value = 10; // 10 = F1AP_CauseRadioNetwork_normal_release @@ -3100,7 +3108,7 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t LOG_W(RRC, "drx_Configuration parameter is NULL, cannot configure local UE parameters or CDRX is deactivated\n"); } else { /* Send DRX configuration to MAC task to configure timers of local UE context */ - message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_MAC_DRX_CONFIG_REQ); + message_p = itti_alloc_new_message(TASK_RRC_ENB, 0, RRC_MAC_DRX_CONFIG_REQ); RRC_MAC_DRX_CONFIG_REQ(message_p).rnti = rnti; RRC_MAC_DRX_CONFIG_REQ(message_p).drx_Configuration = mac_MainConfig->drx_Config; itti_send_msg_to_task(TASK_MAC_ENB, module_id, message_p); @@ -3281,11 +3289,15 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t MeasObj2->measObjectId = 2; MeasObj2->measObject.present = LTE_MeasObjectToAddMod__measObject_PR_measObjectNR_r15; - MeasObj2->measObject.choice.measObjectNR_r15.carrierFreq_r15 =641272; //634000; //(634000 = 3.51GHz) (640000 = 3.6GHz) (641272 = 3619.08MHz = 3600 + 30/1000*106*12/2) (642256 is for 3.6GHz and absoluteFrequencySSB = 642016) + MeasObj2->measObject.choice.measObjectNR_r15.carrierFreq_r15 = rrc_inst->nr_scg_ssb_freq; //641272; //634000; //(634000 = 3.51GHz) (640000 = 3.6GHz) (641272 = 3619.08MHz = 3600 + 30/1000*106*12/2) (642256 is for 3.6GHz and absoluteFrequencySSB = 642016) MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.periodicityAndOffset_r15.present = LTE_MTC_SSB_NR_r15__periodicityAndOffset_r15_PR_sf20_r15; MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.periodicityAndOffset_r15.choice.sf20_r15 = 0; MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.ssb_Duration_r15 = LTE_MTC_SSB_NR_r15__ssb_Duration_r15_sf4; - MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz30; + + if (rrc_inst->nr_scg_ssb_freq > 2016666) //FR2 + MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz120; + else + MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz30; MeasObj2->measObject.choice.measObjectNR_r15.quantityConfigSet_r15 = 1; MeasObj2->measObject.choice.measObjectNR_r15.ext1 = calloc(1, sizeof(struct LTE_MeasObjectNR_r15__ext1)); @@ -3296,7 +3308,11 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t if (MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15 == NULL) exit(1); MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->present = LTE_MeasObjectNR_r15__ext1__bandNR_r15_PR_setup; - MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 78; + if (rrc_inst->nr_scg_ssb_freq > 2016666) //FR2 + MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 261; + else + MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 78; + ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj2); } @@ -3424,6 +3440,7 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5); if (ue_context_pP->ue_context.does_nr) { + LOG_I(RRC,"Configuring measurement for NR cell\n"); ReportConfig_NR->reportConfigId = 7; ReportConfig_NR->reportConfig.present = LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigInterRAT; ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.triggerType.present = LTE_ReportConfigInterRAT__triggerType_PR_event; @@ -3593,20 +3610,17 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); - /* Refresh SRBs/DRBs */ rrc_pdcp_config_asn1_req(ctxt_pP, - *SRB_configList2, // NULL, - *DRB_configList, - NULL, - 0xff, // already configured during the securitymodecommand - NULL, - NULL, - NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - , (LTE_PMCH_InfoList_r9_t *) NULL -#endif - , NULL); + *SRB_configList2, // NULL, + *DRB_configList, + NULL, + 0xff, // already configured during the securitymodecommand + NULL, + NULL, + NULL + , (LTE_PMCH_InfoList_r9_t *) NULL + , NULL); /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { @@ -3614,12 +3628,10 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t *SRB_configList2, // NULL, *DRB_configList, NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) , (LTE_PMCH_InfoList_r9_t *) NULL, 0, 0 -#endif - ); + ); } free(Sparams); @@ -3867,7 +3879,7 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt LOG_W(RRC, "drx_Configuration parameter is NULL, cannot configure local UE parameters or CDRX is deactivated\n"); } else { /* Send DRX configuration to MAC task to configure timers of local UE context */ - message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_MAC_DRX_CONFIG_REQ); + message_p = itti_alloc_new_message(TASK_RRC_ENB, 0, RRC_MAC_DRX_CONFIG_REQ); RRC_MAC_DRX_CONFIG_REQ(message_p).rnti = rnti; RRC_MAC_DRX_CONFIG_REQ(message_p).drx_Configuration = mac_MainConfig->drx_Config; itti_send_msg_to_task(TASK_MAC_ENB, module_id, message_p); @@ -4011,7 +4023,6 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1; MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6; - //<<<<<<< HEAD MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB if (rrc_inst->carrier[0].sib1->tdd_Config!=NULL) { @@ -4411,69 +4422,11 @@ static int encode_CG_ConfigInfo( struct NR_RadioBearerConfig *rb_config = NULL; asn_enc_rval_t enc_rval; int RRC_OK = 1; - int index = 0; char temp_buff[ASN_MAX_ENCODE_SIZE]; - LTE_UE_CapabilityRAT_ContainerList_t *ue_cap_rat_container_list = NULL; - LTE_UE_CapabilityRAT_Container_t ue_cap_rat_container_MRDC; - LTE_UE_CapabilityRAT_Container_t ue_cap_rat_container_nr; + NR_UE_CapabilityRAT_ContainerList_t *ue_cap_rat_container_list = NULL; + NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container_MRDC = NULL; + NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container_nr = NULL; int RAT_Container_count = 0; - rb_config = calloc(1,sizeof(struct NR_RadioBearerConfig)); - AssertFatal(rb_config != NULL,"failed to allocate memory for rb_config"); - - if(ue_context_pP->ue_context.DRB_configList->list.count != 0) { - rb_config->drb_ToAddModList = calloc(1,sizeof(struct NR_DRB_ToAddModList )); - AssertFatal(rb_config->drb_ToAddModList != NULL,"failed to allocated memory for drbtoaddmodlist"); - rb_config->drb_ToAddModList->list.count = NUMBEROF_DRBS_TOBE_ADDED; - rb_config->drb_ToAddModList->list.array - = calloc(NUMBEROF_DRBS_TOBE_ADDED, sizeof(struct NR_DRB_ToAddMod *)); - AssertFatal( rb_config->drb_ToAddModList->list.array != NULL, - "falied to allocate memory for list.array"); - - for(index = 0; index < NUMBEROF_DRBS_TOBE_ADDED; index++) { - rb_config->drb_ToAddModList->list.array[index] - = calloc(1,sizeof(struct NR_DRB_ToAddMod)); - AssertFatal(rb_config->drb_ToAddModList->list.array[index] != NULL, - "failed to allocate memory for drb_toaddmod"); - rb_config->drb_ToAddModList->list.array[index]->drb_Identity - = ue_context_pP->ue_context.DRB_configList->list.array[index]->drb_Identity; - - if(ue_context_pP->ue_context.DRB_configList->list.array[index]->eps_BearerIdentity) { - rb_config->drb_ToAddModList->list.array[index]->cnAssociation - = calloc(1,sizeof(struct NR_DRB_ToAddMod__cnAssociation)); - AssertFatal(rb_config->drb_ToAddModList->list.array[index]->cnAssociation != NULL, - "failed to allocate memory cnAssociation"); - rb_config->drb_ToAddModList->list.array[index]->cnAssociation->present - = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; - rb_config->drb_ToAddModList->list.array[index]->cnAssociation->choice.eps_BearerIdentity - = *(ue_context_pP->ue_context.DRB_configList->list.array[index]->eps_BearerIdentity); - } - - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config = calloc(1,sizeof(struct NR_PDCP_Config)); - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb = calloc(1,sizeof(struct NR_PDCP_Config__drb)); - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->discardTimer = calloc(1,sizeof(long)); - *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->discardTimer - = *(ue_context_pP->ue_context.DRB_configList->list.array[index]->pdcp_Config->discardTimer); - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(long)); - *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeUL - = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(long)); - *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeDL - = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->headerCompression.present - = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->headerCompression.choice.notUsed = 0; - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->t_Reordering = calloc(1,sizeof(long)); - *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->t_Reordering - = NR_PDCP_Config__t_Reordering_ms0; - } - - rb_config->securityConfig = calloc(1,sizeof(struct NR_SecurityConfig )); - rb_config->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(struct NR_SecurityAlgorithmConfig)); - rb_config->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; - rb_config->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm = NULL; - rb_config->securityConfig->keyToUse = calloc(1,sizeof(long)); - *rb_config->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; - } cg_configinfo = calloc(1,sizeof(struct NR_CG_ConfigInfo)); AssertFatal(cg_configinfo != NULL,"failed to allocate memory for cg_configinfo"); @@ -4488,10 +4441,6 @@ static int encode_CG_ConfigInfo( = calloc(1,sizeof(struct NR_CG_ConfigInfo_IEs)); AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo != NULL, "failed to allocate memory for cg_configinfo_IEs"); - cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->ue_CapabilityInfo - = calloc(1,sizeof( OCTET_STRING_t)); - AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo-> - ue_CapabilityInfo != NULL, "failed to allocate memory for ue_capabilityinfo"); if(ue_context_pP->ue_context.UE_Capability_MRDC) { RAT_Container_count++; @@ -4499,8 +4448,10 @@ static int encode_CG_ConfigInfo( (void *)ue_context_pP->ue_context.UE_Capability_MRDC,temp_buff,ASN_MAX_ENCODE_SIZE); AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); - ue_cap_rat_container_MRDC.rat_Type = LTE_RAT_Type_eutra_nr; - OCTET_STRING_fromBuf(&ue_cap_rat_container_MRDC.ueCapabilityRAT_Container, + ue_cap_rat_container_MRDC = calloc(1, sizeof(*ue_cap_rat_container_MRDC)); + AssertFatal(ue_cap_rat_container_MRDC != NULL,"failed to allocate memory for ue_cap_rat_container_MRDC"); + ue_cap_rat_container_MRDC->rat_Type = NR_RAT_Type_eutra_nr; + OCTET_STRING_fromBuf(&ue_cap_rat_container_MRDC->ue_CapabilityRAT_Container, (const char *)temp_buff,(enc_rval.encoded+7)>>3); memset((void *)temp_buff,0,sizeof(temp_buff)); } @@ -4511,44 +4462,30 @@ static int encode_CG_ConfigInfo( (void *)ue_context_pP->ue_context.UE_Capability_nr,temp_buff,ASN_MAX_ENCODE_SIZE); AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); - ue_cap_rat_container_nr.rat_Type = LTE_RAT_Type_nr; - OCTET_STRING_fromBuf(&ue_cap_rat_container_nr.ueCapabilityRAT_Container, + ue_cap_rat_container_nr = calloc(1, sizeof(*ue_cap_rat_container_nr)); + AssertFatal(ue_cap_rat_container_nr != NULL,"failed to allocate memory for ue_cap_rat_container_nr"); + ue_cap_rat_container_nr->rat_Type = NR_RAT_Type_nr; + OCTET_STRING_fromBuf(&ue_cap_rat_container_nr->ue_CapabilityRAT_Container, (const char *)temp_buff,(enc_rval.encoded+7)>>3); memset((void *)temp_buff,0,sizeof(temp_buff)); } - ue_cap_rat_container_list = calloc(1,sizeof(LTE_UE_CapabilityRAT_ContainerList_t)); - ue_cap_rat_container_list->list.count = RAT_Container_count; - ue_cap_rat_container_list->list.size = RAT_Container_count * sizeof(LTE_UE_CapabilityRAT_Container_t); - ue_cap_rat_container_list->list.array = calloc(RAT_Container_count,sizeof(LTE_UE_CapabilityRAT_Container_t *)); - - if(ue_context_pP->ue_context.UE_Capability_MRDC) { - ue_cap_rat_container_list->list.array[0] = calloc(1,sizeof(LTE_UE_CapabilityRAT_Container_t)); - memcpy(ue_cap_rat_container_list->list.array[0],&ue_cap_rat_container_MRDC,sizeof(LTE_UE_CapabilityRAT_Container_t)); + if (RAT_Container_count) { + cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->ue_CapabilityInfo = calloc(1,sizeof( OCTET_STRING_t)); + AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo-> ue_CapabilityInfo != NULL, "failed to allocate memory for ue_capabilityinfo"); + ue_cap_rat_container_list = calloc(1,sizeof(NR_UE_CapabilityRAT_ContainerList_t)); + if (ue_cap_rat_container_MRDC != NULL) + ASN_SEQUENCE_ADD(&ue_cap_rat_container_list->list, ue_cap_rat_container_MRDC); + if (ue_cap_rat_container_nr != NULL) + ASN_SEQUENCE_ADD(&ue_cap_rat_container_list->list, ue_cap_rat_container_nr); + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList,NULL, + (void *)ue_cap_rat_container_list,temp_buff,ASN_MAX_ENCODE_SIZE); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + OCTET_STRING_fromBuf(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->ue_CapabilityInfo, + (const char *)temp_buff, (enc_rval.encoded+7)>>3); } - if(ue_context_pP->ue_context.UE_Capability_nr) { - ue_cap_rat_container_list->list.array[1] = calloc(1,sizeof(LTE_UE_CapabilityRAT_Container_t)); - memcpy(ue_cap_rat_container_list->list.array[1],&ue_cap_rat_container_nr,sizeof(LTE_UE_CapabilityRAT_Container_t)); - } - - //this xer_fprint logs can be enabled for additional debugging logs - //xer_fprint(stdout,&asn_DEF_LTE_UE_CapabilityRAT_ContainerList,ue_cap_rat_container_list); - enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_UE_CapabilityRAT_ContainerList,NULL, - (void *)ue_cap_rat_container_list,temp_buff,ASN_MAX_ENCODE_SIZE); - AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - OCTET_STRING_fromBuf(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->ue_CapabilityInfo, - (const char *)temp_buff, (enc_rval.encoded+7)>>3); - cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->mcg_RB_Config - = calloc(1,sizeof(OCTET_STRING_t)); - AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo-> - mcg_RB_Config != NULL, "failed to allocate memory for mcg_rb_config"); - enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig,NULL,(void *)rb_config,temp_buff,ASN_MAX_ENCODE_SIZE); - AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - OCTET_STRING_fromBuf(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->mcg_RB_Config, - (const char *)temp_buff, (enc_rval.encoded+7)>>3); // this xer_fprint can be enabled for additional debugging messages // xer_fprint(stdout,&asn_DEF_NR_CG_ConfigInfo,(void *)cg_configinfo); enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo,NULL,(void *)cg_configinfo, @@ -4558,7 +4495,7 @@ static int encode_CG_ConfigInfo( *enc_size = (enc_rval.encoded+7)/8; ASN_STRUCT_FREE(asn_DEF_NR_RadioBearerConfig,rb_config); ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo,cg_configinfo); - ASN_STRUCT_FREE(asn_DEF_LTE_UE_CapabilityRAT_ContainerList,ue_cap_rat_container_list); + ASN_STRUCT_FREE(asn_DEF_NR_UE_CapabilityRAT_ContainerList,ue_cap_rat_container_list); return RRC_OK; } //----------------------------------------------------------------------------- @@ -4643,22 +4580,37 @@ rrc_eNB_process_MeasurementReport( /* TODO: improve NR triggering */ if (measResults2->measId == 7) { - if ((ue_context_pP->ue_context.Status != RRC_NR_NSA) && (ue_context_pP->ue_context.Status != RRC_NR_NSA_RECONFIGURED)) { + if ((ue_context_pP->ue_context.StatusRrc != RRC_NR_NSA) && (ue_context_pP->ue_context.StatusRrc != RRC_NR_NSA_RECONFIGURED)) { MessageDef *msg; - ue_context_pP->ue_context.Status = RRC_NR_NSA; + ue_context_pP->ue_context.StatusRrc = RRC_NR_NSA; + ue_context_pP->ue_context.gnb_rnti = -1; // set when receiving X2AP_ENDC_SGNB_ADDITION_REQ_ACK + ue_context_pP->ue_context.gnb_x2_assoc_id = -1; // set when receiving X2AP_ENDC_SGNB_ADDITION_REQ_ACK if(is_en_dc_supported(ue_context_pP->ue_context.UE_Capability)) { + + AssertFatal(measResults2->measResultNeighCells!=NULL,"no measResultNeighCells, shouldn't happen!\n"); + AssertFatal(measResults2->measResultNeighCells->present==LTE_MeasResults__measResultNeighCells_PR_measResultNeighCellListNR_r15,"field is not LTE_MeasResults__measResultNeighCells_PR_measResultNeighCellListNR_r15"); /** to add gNB as Secondary node CG-ConfigInfo to be added as per 36.423 r15 **/ if(encode_CG_ConfigInfo(enc_buf,sizeof(enc_buf),ue_context_pP,&enc_size) == RRC_OK) LOG_I(RRC,"CG-ConfigInfo encoded successfully\n"); - msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_ENDC_SGNB_ADDITION_REQ); + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ); memset(&(X2AP_ENDC_SGNB_ADDITION_REQ(msg)), 0, sizeof(x2ap_ENDC_sgnb_addition_req_t)); + X2AP_ENDC_SGNB_ADDITION_REQ(msg).rnti = ctxt_pP->rnti; + + X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.encryption_algorithms = ue_context_pP->ue_context.nr_security.ciphering_algorithms; + X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.integrity_algorithms = ue_context_pP->ue_context.nr_security.integrity_algorithms; + + memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).kgnb, ue_context_pP->ue_context.nr_security.kgNB, 32); + memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer,enc_buf,enc_size); X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer_size = enc_size; + X2AP_ENDC_SGNB_ADDITION_REQ(msg).target_physCellId + //= measResults2->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]->pci_r15; = measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[0]->physCellId; + //For the moment we have a single E-RAB which will be the one to be added to the gNB //Not sure how to select bearers to be added if there are multiple. X2AP_ENDC_SGNB_ADDITION_REQ(msg).nb_e_rabs_tobeadded = 1; @@ -4666,7 +4618,7 @@ rrc_eNB_process_MeasurementReport( for (int e_rab=0; e_rab < X2AP_ENDC_SGNB_ADDITION_REQ(msg).nb_e_rabs_tobeadded; e_rab++) { X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id; X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].gtp_teid = ue_context_pP->ue_context.e_rab[e_rab].param.gtp_teid; - X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].drb_ID = ue_context_pP->ue_context.DRB_configList->list.array[e_rab]->drb_Identity; + X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].drb_ID = ue_context_pP->ue_context.DRB_configList->list.array[e_rab]->drb_Identity; memcpy(&X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].sgw_addr, &ue_context_pP->ue_context.e_rab[e_rab].param.sgw_addr, sizeof(transport_layer_addr_t)); @@ -4679,6 +4631,32 @@ rrc_eNB_process_MeasurementReport( return; } } + + if (!ue_context_pP->ue_context.measResults->measResultNeighCells) { + ue_context_pP->ue_context.measResults->measResultNeighCells = calloc(1,sizeof(*ue_context_pP->ue_context.measResults->measResultNeighCells)); + ue_context_pP->ue_context.measResults->measResultNeighCells->present = LTE_MeasResults__measResultNeighCells_PR_measResultNeighCellListNR_r15; + ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array = calloc(1, sizeof(*ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array)); + ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0] = calloc(1, sizeof(*ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0])); + ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.count = 1; + } + struct LTE_MeasResultCellNR_r15 *ueCtxtMeasResultCellNR_r15 = ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]; + const struct LTE_MeasResultCellNR_r15 *measNeighCellNR0 = measResults2->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]; + ueCtxtMeasResultCellNR_r15->pci_r15 = measNeighCellNR0->pci_r15; + if (!ueCtxtMeasResultCellNR_r15->measResultCell_r15.rsrpResult_r15) + ueCtxtMeasResultCellNR_r15->measResultCell_r15.rsrpResult_r15 = calloc(1, sizeof(*ueCtxtMeasResultCellNR_r15->measResultCell_r15.rsrpResult_r15)); + if (!ueCtxtMeasResultCellNR_r15->measResultCell_r15.rsrqResult_r15) + ueCtxtMeasResultCellNR_r15->measResultCell_r15.rsrqResult_r15 = calloc(1, sizeof(*ueCtxtMeasResultCellNR_r15->measResultCell_r15.rsrqResult_r15)); + *ueCtxtMeasResultCellNR_r15->measResultCell_r15.rsrpResult_r15 = *measNeighCellNR0->measResultCell_r15.rsrpResult_r15; + *ueCtxtMeasResultCellNR_r15->measResultCell_r15.rsrqResult_r15 = *measNeighCellNR0->measResultCell_r15.rsrqResult_r15; + if (measNeighCellNR0->measResultRS_IndexList_r15) { + if (!ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15) { + ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15 = calloc(1,sizeof(*ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15)); + ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15->list.array = calloc(1, sizeof(ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15->list.array)); + ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15->list.array[0] = calloc(1, sizeof(*ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15->list.array)); + ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15->list.count = 1; + } + ueCtxtMeasResultCellNR_r15->measResultRS_IndexList_r15->list.array[0]->ssb_Index_r15 = measNeighCellNR0->measResultRS_IndexList_r15->list.array[0]->ssb_Index_r15; + } } if (measResults2->measResultNeighCells == NULL) @@ -4740,15 +4718,15 @@ rrc_eNB_process_MeasurementReport( LOG_D(RRC, "A3 event is triggered...\n"); /* if the UE is not in handover mode, start handover procedure */ - if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) { + if (ue_context_pP->ue_context.StatusRrc != RRC_HO_EXECUTION) { MessageDef *msg; LOG_I(RRC, "Send HO preparation message at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe); /* HO info struct may not be needed anymore */ ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info))); - ue_context_pP->ue_context.Status = RRC_HO_EXECUTION; + ue_context_pP->ue_context.StatusRrc = RRC_HO_EXECUTION; ue_context_pP->ue_context.handover_info->state = HO_REQUEST; /* HO Preparation message */ - msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ); + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_HANDOVER_REQ); rrc_eNB_generate_HandoverPreparationInformation( ue_context_pP, X2AP_HANDOVER_REQ(msg).rrc_buffer, @@ -4877,7 +4855,7 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re RB_INSERT(rrc_ue_tree_s, &RC.rrc[mod_id]->rrc_ue_head, ue_context_target_p); LOG_D(RRC, "eNB %d: Created new UE context uid %u\n", mod_id, ue_context_target_p->local_uid); ue_context_target_p->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_target_p->ue_context.handover_info))); - //ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION; + //ue_context_target_p->ue_context.StatusRrc = RRC_HO_EXECUTION; //ue_context_target_p->ue_context.handover_info->state = HO_ACK; ue_context_target_p->ue_context.handover_info->x2_id = m->x2_id; ue_context_target_p->ue_context.handover_info->assoc_id = m->target_assoc_id; @@ -4952,7 +4930,7 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re } rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ(mod_id, ue_context_target_p); - ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION; + ue_context_target_p->ue_context.StatusRrc = RRC_HO_EXECUTION; ue_context_target_p->ue_context.handover_info->state = HO_ACK; } @@ -4997,13 +4975,14 @@ void rrc_eNB_handover_ue_context_release( //MessageDef *msg_release_p = NULL; MessageDef *msg_delete_tunnels_p = NULL; uint32_t eNB_ue_s1ap_id = ue_context_p->ue_context.eNB_ue_s1ap_id; - //msg_release_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE); + //msg_release_p = itti_alloc_new_message(TASK_RRC_ENB, 0, S1AP_UE_CONTEXT_RELEASE); //itti_send_msg_to_task(TASK_S1AP, ctxt_pP->module_id, msg_release_p); s1ap_ue_context_release(ctxt_pP->instance, ue_context_p->ue_context.eNB_ue_s1ap_id); //MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL,0, "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", eNB_ue_s1ap_id); - msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ); + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, 0, GTPV1U_ENB_DELETE_TUNNEL_REQ); memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0; for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) { GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] = @@ -5014,7 +4993,7 @@ void rrc_eNB_handover_ue_context_release( ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0; } - itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p); + itti_send_msg_to_task(TASK_VARIABLE, ctxt_pP->module_id, msg_delete_tunnels_p); struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = NULL; rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(RC.rrc[ctxt_pP->module_id], 0, eNB_ue_s1ap_id); @@ -5066,7 +5045,7 @@ flexran_rrc_eNB_trigger_handover (int mod_id, LOG_D(RRC, "Handover is triggered by FlexRAN controller...\n"); /* if the UE is not in handover mode, start handover procedure */ - if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) { + if (ue_context_pP->ue_context.StatusRrc != RRC_HO_EXECUTION) { MessageDef *msg; LOG_I(RRC, "Send HO preparation message at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe); /* Check memory leakage for handover info */ @@ -5074,10 +5053,10 @@ flexran_rrc_eNB_trigger_handover (int mod_id, //free(ue_context_pP->ue_context.handover_info); //} ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info))); - ue_context_pP->ue_context.Status = RRC_HO_EXECUTION; + ue_context_pP->ue_context.StatusRrc = RRC_HO_EXECUTION; ue_context_pP->ue_context.handover_info->state = HO_REQUEST; /* HO Preparation message */ - msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ); + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_HANDOVER_REQ); rrc_eNB_generate_HandoverPreparationInformation( ue_context_pP, X2AP_HANDOVER_REQ(msg).rrc_buffer, @@ -5135,7 +5114,7 @@ check_handovers( RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) { ctxt_pP->rnti = ue_context_p->ue_id_rnti; - if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info != NULL) { + if (ue_context_p->ue_context.StatusRrc == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info != NULL) { /* in the source, UE in HO_PREPARE mode */ if (ue_context_p->ue_context.handover_info->state == HO_PREPARE) { LOG_D(RRC, @@ -5164,7 +5143,7 @@ check_handovers( MessageDef *msg; // Configure target ue_context_p->ue_context.handover_info->state = HO_FORWARDING; - msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ_ACK); + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_HANDOVER_REQ_ACK); rrc_eNB_generate_HO_RRCConnectionReconfiguration(ctxt_pP, ue_context_p, X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, &X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size); rrc_eNB_configure_rbs_handover(ue_context_p,ctxt_pP); @@ -5186,7 +5165,7 @@ check_handovers( } } - if (ue_context_p->ue_context.Status == RRC_RECONFIGURED + if (ue_context_p->ue_context.StatusRrc == RRC_RECONFIGURED && ue_context_p->ue_context.handover_info != NULL && ue_context_p->ue_context.handover_info->forwarding_state == FORWARDING_NO_EMPTY ) { MessageDef *msg_p; @@ -5208,11 +5187,11 @@ check_handovers( GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).frame, 0, GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).eNB_index); - LOG_D(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %d, rb_id %ld, muiP %d, confirmP %d, mode %d\n", + LOG_D(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %ld, rb_id %ld, muiP %d, confirmP %d, mode %d\n", PROTOCOL_CTXT_ARGS(&ctxt), ITTI_MSG_NAME (msg_p), ITTI_MSG_ORIGIN_NAME(msg_p), - ITTI_MSG_INSTANCE (msg_p), + ITTI_MSG_DESTINATION_INSTANCE (msg_p), GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id, GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).muip, GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).confirmp, @@ -5252,7 +5231,7 @@ check_handovers( ue_context_p->ue_context.handover_info->forwarding_state = FORWARDING_EMPTY; } - if( ue_context_p->ue_context.Status == RRC_RECONFIGURED && + if( ue_context_p->ue_context.StatusRrc == RRC_RECONFIGURED && ue_context_p->ue_context.handover_info != NULL && ue_context_p->ue_context.handover_info->forwarding_state == FORWARDING_EMPTY && ue_context_p->ue_context.handover_info->endmark_state == ENDMARK_NO_EMPTY && @@ -5276,11 +5255,11 @@ check_handovers( GTPV1U_ENB_END_MARKER_IND (msg_p).frame, 0, GTPV1U_ENB_END_MARKER_IND (msg_p).eNB_index); - LOG_I(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %d, rb_id %ld, muiP %d, confirmP %d, mode %d\n", + LOG_I(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %ld, rb_id %ld, muiP %d, confirmP %d, mode %d\n", PROTOCOL_CTXT_ARGS(&ctxt), ITTI_MSG_NAME (msg_p), ITTI_MSG_ORIGIN_NAME(msg_p), - ITTI_MSG_INSTANCE (msg_p), + ITTI_MSG_DESTINATION_INSTANCE (msg_p), GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id, GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).muip, GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).confirmp, @@ -5755,7 +5734,7 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct //SchedulingRequestConfig__setup__dsr_TransMax_n4); // assign_enum(&physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax = SchedulingRequestConfig__setup__dsr_TransMax_n4; physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax = - LTE_SchedulingRequestConfig__setup__dsr_TransMax_n4; + LTE_SchedulingRequestConfig__setup__dsr_TransMax_n64; LOG_D(RRC, "handover_config [FRAME %05d][RRC_eNB][MOD %02d][][--- MAC_CONFIG_REQ (SRB1 UE %x) --->][MAC_eNB][MOD %02d][]\n", ctxt_pP->frame, ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ctxt_pP->module_id); @@ -5789,7 +5768,7 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, - (LTE_MBSFNAreaConfiguration_r9_t*) NULL + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); // Configure target eNB SRB2 /// SRB2 @@ -6134,7 +6113,6 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct mobilityInfo = CALLOC(1, sizeof(*mobilityInfo)); memset((void *)mobilityInfo, 0, sizeof(*mobilityInfo)); mobilityInfo->targetPhysCellId = RC.rrc[ctxt_pP->module_id]->carrier[0].physCellId; - //(PhysCellId_t) two_tier_hexagonal_cellIds[ue_context_pP->ue_context.handover_info->modid_t]; LOG_D(RRC, "[eNB %d] Frame %d: handover preparation: targetPhysCellId: %ld mod_id: %d ue: %x \n", ctxt_pP->module_id, ctxt_pP->frame, @@ -6341,20 +6319,17 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct ue_context_pP->ue_context.rnti, rrc_eNB_mui, size); - /* Refresh SRBs/DRBs */ rrc_pdcp_config_asn1_req(ctxt_pP, - *SRB_configList2, // NULL, - *DRB_configList, - NULL, - 0xff, // already configured during the securitymodecommand - NULL, - NULL, - NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - , (LTE_PMCH_InfoList_r9_t *) NULL -#endif - , NULL); + *SRB_configList2, // NULL, + *DRB_configList, + NULL, + 0xff, // already configured during the securitymodecommand + NULL, + NULL, + NULL + , (LTE_PMCH_InfoList_r9_t *) NULL + , NULL); /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { @@ -6362,12 +6337,10 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct *SRB_configList2, // NULL, *DRB_configList, NULL -#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) , (LTE_PMCH_InfoList_r9_t *) NULL, 0, 0 -#endif - ); + ); } free(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ); @@ -6413,6 +6386,7 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc NULL, NULL, (LTE_PMCH_InfoList_r9_t *) NULL, NULL); + if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { rrc_rlc_config_asn1_req(ctxt_pP, ue_context_p->ue_context.SRB_configList, @@ -6470,7 +6444,7 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, - (LTE_MBSFNAreaConfiguration_r9_t*) NULL + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); } @@ -6553,6 +6527,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( kUPenc, (LTE_PMCH_InfoList_r9_t *) NULL, NULL); + /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { rrc_rlc_config_asn1_req(ctxt_pP, @@ -6562,7 +6537,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (LTE_PMCH_InfoList_r9_t *) NULL, 0, 0 - ); + ); } /* Set the SRB active in UE context */ @@ -6602,10 +6577,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (int)DRB_configList->list.array[i]->drb_Identity, (int)*DRB_configList->list.array[i]->logicalChannelIdentity); /* For pre-ci tests */ - LOG_I(RRC, "[eNB %d] Frame %d : Logical Channel UL-DCCH, Received LTE_RRCConnectionReconfigurationComplete from UE %u, reconfiguring DRB %d/LCID %d\n", + LOG_I(RRC, "[eNB %d] Frame %d : Logical Channel UL-DCCH, Received LTE_RRCConnectionReconfigurationComplete, reconfiguring DRB %d/LCID %d\n", ctxt_pP->module_id, ctxt_pP->frame, - oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[ctxt_pP->module_id][ue_context_pP->local_uid], (int)DRB_configList->list.array[i]->drb_Identity, (int)*DRB_configList->list.array[i]->logicalChannelIdentity); @@ -6630,7 +6604,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( "[eNB %d] Config the oai%d to send/receive pkt on DRB %ld to/from the protocol stack\n", ctxt_pP->module_id, ctxt_pP->module_id, (long int)((ue_context_pP->local_uid * LTE_maxDRB) + DRB_configList->list.array[i]->drb_Identity)); - ue_module_id = oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[ctxt_pP->module_id][ue_context_pP->local_uid]; + ue_module_id = 0; // Was oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[ctxt_pP->module_id][ue_context_pP->local_uid]; rb_conf_ipv4(0, //add ue_module_id, //cx ctxt_pP->module_id, //inst @@ -6687,26 +6661,14 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, - (LTE_MBSFNAreaConfiguration_r9_t*) NULL + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); } } else { // remove LCHAN from MAC/PHY - if (ue_context_pP->ue_context.DRB_active[drb_id] == 1) { - // DRB has just been removed so remove RLC + PDCP for DRB - /* rrc_pdcp_config_req (ctxt_pP->module_id, frameP, 1, CONFIG_ACTION_REMOVE, - (ue_mod_idP * NB_RB_MAX) + DRB2LCHAN[i],UNDEF_SECURITY_MODE); - */ - if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { - rrc_rlc_config_req(ctxt_pP, - SRB_FLAG_NO, - MBMS_FLAG_NO, - CONFIG_ACTION_REMOVE, - DRB2LCHAN[i], - Rlc_info_um); - } + if (DRB_configList->list.array[i]->logicalChannelIdentity) { + DRB2LCHAN[i] = (uint8_t) * DRB_configList->list.array[i]->logicalChannelIdentity; } - ue_context_pP->ue_context.DRB_active[drb_id] = 0; LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ (DRB) ---> MAC_eNB\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); @@ -6747,7 +6709,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, - (LTE_MBSFNAreaConfiguration_r9_t*) NULL + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); } } // end else of if (ue_context_pP->ue_context.DRB_active[drb_id] == 0) @@ -6840,7 +6802,7 @@ rrc_eNB_generate_RRCConnectionSetup( case ngran_gNB_CU : // create an ITTI message /* TODO: F1 IDs ar missing in RRC */ - message_p = itti_alloc_new_message (TASK_RRC_ENB, F1AP_DL_RRC_MESSAGE); + message_p = itti_alloc_new_message (TASK_RRC_ENB, 0, F1AP_DL_RRC_MESSAGE); F1AP_DL_RRC_MESSAGE (message_p).rrc_container = (uint8_t *)ue_p->Srb0.Tx_buffer.Payload; F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = ue_p->Srb0.Tx_buffer.payload_size; F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id = 0; @@ -6910,7 +6872,7 @@ rrc_eNB_generate_RRCConnectionSetup( (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, (LTE_MBSFN_AreaInfoList_r9_t *) NULL, - (LTE_MBSFNAreaConfiguration_r9_t*) NULL + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); break; } @@ -6945,6 +6907,32 @@ rrc_eNB_generate_RRCConnectionSetup( } } +//----------------------------------------------------------------------------- +void rrc_eNB_process_reconfiguration_complete_endc(const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *const ue_context_p) +//----------------------------------------------------------------------------- +{ + MessageDef *msg_p; + + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_RECONF_COMPLETE); + + /* MeNB_ue_x2_id is unknown, set to 0. + * This is not correct but X2 id in the eNB is only 12 bits, + * so unfortunately we can't use rnti. + * To be corrected if needed. + * As of today, when stopping t_dc_prep we remove the UE + * from X2. To keep the id until the 'reconfiguration complete' message is received + * needs a rethink/rewrite of this logic. For simplicity, let's + * keep it as is. The only problem we can get is if/when we + * interoperate with a non-OAI gNB. The OAI gNB does not + * care about MeNB_ue_x2_id. + */ + X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).MeNB_ue_x2_id = 0; + X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).SgNB_ue_x2_id = ue_context_p->ue_context.gnb_rnti; + X2AP_ENDC_SGNB_RECONF_COMPLETE(msg_p).gnb_x2_assoc_id = ue_context_p->ue_context.gnb_x2_assoc_id; + itti_send_msg_to_task (TASK_X2AP, ctxt_pP->instance, msg_p); +} + void setup_ngran_CU(eNB_RRC_INST *rrc) { } @@ -7026,6 +7014,8 @@ char openair_rrc_eNB_configuration( openair_rrc_top_init_eNB(RC.rrc[ctxt.module_id]->carrier[CC_id].MBMS_flag,0); } + RC.rrc[ctxt.module_id]->nr_scg_ssb_freq = configuration->nr_scg_ssb_freq; + openair_rrc_on(&ctxt); /* @@ -7037,13 +7027,23 @@ char openair_rrc_eNB_configuration( LOG_W(RRC, "[inst %d] RRC->MCC/MSG->MCC %d/%d \n", ctxt.module_id, RC.rrc[ctxt.module_id]->mcc, rrc_configuration_req->mcc); */ if (NODE_IS_CU(RC.rrc[ctxt.module_id]->node_type)) - // msg_p = itti_alloc_new_message (TASK_ENB_APP, F1AP_SCTP_REQ); + // msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, F1AP_SCTP_REQ); // RCconfig_CU_F1(msg_p, enb_id); setup_ngran_CU(RC.rrc[ctxt.module_id]); return 0; } +static +void rrc_eNB_generate_RRCConnectionReestablishmentReject_unknown_UE(protocol_ctxt_t *const ctxt_pP, + const int CC_id) { + struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, ctxt_pP->rnti); + rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, + ue_context_p, + CC_id); + ue_context_p->ue_context.ul_failure_timer = 500; // 500 milliseconds to send the message and remove temporary entry +} + /*------------------------------------------------------------------------------*/ int rrc_eNB_decode_ccch( @@ -7122,12 +7122,14 @@ rrc_eNB_decode_ccch( uint16_t c_rnti = 0; if (rrcConnectionReestablishmentRequest->ue_Identity.physCellId != RC.rrc[ctxt_pP->module_id]->carrier[CC_id].physCellId) { + /* UE was moving from previous cell so quickly that RRCConnectionReestablishment for previous cell was recieved in this cell */ LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" LTE_RRCConnectionReestablishmentRequest ue_Identity.physCellId(%ld) is not equal to current physCellId(%d), let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), rrcConnectionReestablishmentRequest->ue_Identity.physCellId, RC.rrc[ctxt_pP->module_id]->carrier[CC_id].physCellId); - rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + rrc_eNB_generate_RRCConnectionReestablishmentReject_unknown_UE(ctxt_pP, + CC_id); break; } @@ -7140,10 +7142,12 @@ rrc_eNB_decode_ccch( if (rrcConnectionReestablishmentRequest->ue_Identity.c_RNTI.size == 0 || rrcConnectionReestablishmentRequest->ue_Identity.c_RNTI.size > 2) { + /* c_RNTI range error should not happen */ LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" LTE_RRCConnectionReestablishmentRequest c_RNTI range error, let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); - rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + rrc_eNB_generate_RRCConnectionReestablishmentReject_unknown_UE(ctxt_pP, + CC_id); break; } @@ -7155,7 +7159,8 @@ rrc_eNB_decode_ccch( LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" LTE_RRCConnectionReestablishmentRequest without UE context, let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); - rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + rrc_eNB_generate_RRCConnectionReestablishmentReject_unknown_UE(ctxt_pP, + CC_id); break; } @@ -7212,7 +7217,7 @@ rrc_eNB_decode_ccch( } //c-plane not end - if((ue_context_p->ue_context.Status != RRC_RECONFIGURED) && (ue_context_p->ue_context.reestablishment_cause == LTE_ReestablishmentCause_spare1)) { + if((ue_context_p->ue_context.StatusRrc != RRC_RECONFIGURED) && (ue_context_p->ue_context.reestablishment_cause == LTE_ReestablishmentCause_spare1)) { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" LTE_RRCConnectionReestablishmentRequest (UE %x c-plane is not end), let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),c_rnti); @@ -7222,9 +7227,11 @@ rrc_eNB_decode_ccch( if(ue_context_p->ue_context.ue_reestablishment_timer > 0) { LOG_E(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" RRRCConnectionReconfigurationComplete(Previous) don't receive, delete the Previous UE\n", - PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); - ue_context_p->ue_context.Status = RRC_RECONFIGURED; + PROTOCOL_RRC_CTXT_UE_FMT" RRRCConnectionReconfigurationComplete(Previous) don't receive, delete the Previous UE,\nprevious Status %d, new Status RRC_RECONFIGURED\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context_p->ue_context.StatusRrc + ); + ue_context_p->ue_context.StatusRrc = RRC_RECONFIGURED; protocol_ctxt_t ctxt_old_p; PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt_old_p, ctxt_pP->instance, @@ -7273,9 +7280,6 @@ rrc_eNB_decode_ccch( PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), rrcConnectionReestablishmentRequest->ue_Identity.physCellId, ue_context_p->ue_context.reestablishment_cause); -#ifndef NO_RRM - send_msg(&S_rrc, msg_rrc_MR_attach_ind(ctxt_pP->module_id, Mac_id)); -#else ue_context_p->ue_context.primaryCC_id = CC_id; //LG COMMENT Idx = (ue_mod_idP * NB_RB_MAX) + DCCH; Idx = DCCH; @@ -7329,7 +7333,6 @@ rrc_eNB_decode_ccch( ); } -#endif //NO_RRM } break; @@ -7401,7 +7404,7 @@ rrc_eNB_decode_ccch( if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { rrc_mac_remove_ue(ctxt_pP->module_id, ue_context_p->ue_context.rnti); } else { - MessageDef *m = itti_alloc_new_message(TASK_RRC_ENB, F1AP_UE_CONTEXT_RELEASE_CMD); + MessageDef *m = itti_alloc_new_message(TASK_RRC_ENB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); F1AP_UE_CONTEXT_RELEASE_CMD(m).rnti = ctxt_pP->rnti; F1AP_UE_CONTEXT_RELEASE_CMD(m).cause = F1AP_CAUSE_RADIO_NETWORK; F1AP_UE_CONTEXT_RELEASE_CMD(m).cause_value = 10; // 10 = F1AP_CauseRadioNetwork_normal_release @@ -7505,7 +7508,7 @@ rrc_eNB_decode_ccch( if (NODE_IS_MONOLITHIC(RC.rrc[ctxt_pP->module_id]->node_type)) rrc_mac_remove_ue(ctxt_pP->module_id,ctxt_pP->rnti); else if (NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { - MessageDef *m = itti_alloc_new_message(TASK_RRC_ENB, F1AP_UE_CONTEXT_RELEASE_CMD); + MessageDef *m = itti_alloc_new_message(TASK_RRC_ENB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); F1AP_UE_CONTEXT_RELEASE_CMD(m).rnti = ctxt_pP->rnti; F1AP_UE_CONTEXT_RELEASE_CMD(m).cause = F1AP_CAUSE_RADIO_NETWORK; F1AP_UE_CONTEXT_RELEASE_CMD(m).cause_value = 10; // 10 = F1AP_CauseRadioNetwork_normal_release @@ -7518,9 +7521,6 @@ rrc_eNB_decode_ccch( } } -#ifndef NO_RRM - send_msg(&S_rrc, msg_rrc_MR_attach_ind(ctxt_pP->module_id, Mac_id)); -#else ue_context_p->ue_context.primaryCC_id = CC_id; //LG COMMENT Idx = (ue_mod_idP * NB_RB_MAX) + DCCH; Idx = DCCH; @@ -7573,7 +7573,6 @@ rrc_eNB_decode_ccch( ); } -#endif //NO_RRM break; default: @@ -7593,42 +7592,239 @@ rrc_eNB_decode_ccch( return rval; } +#define NCE nonCriticalExtension + +static void +get_ue_Category( + LTE_UE_EUTRA_Capability_t *c, + long *catDL, + long *catUL +) +{ + if (c != NULL) { // v8.6 + *catDL=c->ue_Category; *catUL=c->ue_Category; + struct LTE_UE_EUTRA_Capability_v920_IEs *c92=c->NCE; + if (c92 != NULL) { // v9.2 + struct LTE_UE_EUTRA_Capability_v940_IEs *c94=c92->NCE; + if (c94 != NULL) { // v9.4 + struct LTE_UE_EUTRA_Capability_v1020_IEs *c102=c94->NCE; + if (c102 != NULL) { // v10.2 + if (c102->ue_Category_v1020) {*catDL=*c102->ue_Category_v1020;*catUL=*c102->ue_Category_v1020;} + struct LTE_UE_EUTRA_Capability_v1060_IEs *c106=c102->NCE; + if (c106 != NULL) { // v10.6 + struct LTE_UE_EUTRA_Capability_v1090_IEs *c109=c106->NCE; + if (c109 != NULL) { // v10.9 + struct LTE_UE_EUTRA_Capability_v1130_IEs *c113=c109->NCE; + if (c113 != NULL) { // v11.3 + struct LTE_UE_EUTRA_Capability_v1170_IEs *c117=c113->NCE; + if (c117 != NULL) { // v11.7 + if (c117->ue_Category_v1170) {*catDL=*c117->ue_Category_v1170; + struct LTE_UE_EUTRA_Capability_v1180_IEs *c118=c117->NCE; + if (c118 != NULL) { // v11.8 + struct LTE_UE_EUTRA_Capability_v11a0_IEs *c11a=c118->NCE; + if (c11a != NULL) { // v11.a + if (c11a->ue_Category_v11a0) {*catDL=*c11a->ue_Category_v11a0;*catUL=*c11a->ue_Category_v11a0;} + struct LTE_UE_EUTRA_Capability_v1250_IEs *c125=c11a->NCE; + if (c125 != NULL) { // v12.5 + if (c125->ue_CategoryDL_r12) *catDL=*c125->ue_CategoryDL_r12; + if (c125->ue_CategoryUL_r12) *catUL=*c125->ue_CategoryUL_r12; + struct LTE_UE_EUTRA_Capability_v1260_IEs *c126=c125->NCE; + if (c126 != NULL) { // v12.6 + if (c126->ue_CategoryDL_v1260) *catDL=*c126->ue_CategoryDL_v1260; + struct LTE_UE_EUTRA_Capability_v1270_IEs *c127=c126->NCE; + if (c127 != NULL) { // v12.7 + struct LTE_UE_EUTRA_Capability_v1280_IEs *c128=c127->NCE; + if (c128 != NULL) { // v12.8 + struct LTE_UE_EUTRA_Capability_v1310_IEs *c131=c128->NCE; + if (c131 != NULL) { // v13.1 + if (c131->ue_CategoryDL_v1310 && *c131->ue_CategoryDL_v1310 == 0) *catDL=17; + if (c131->ue_CategoryDL_v1310 && *c131->ue_CategoryDL_v1310 == 1) *catDL=-1; + if (c131->ue_CategoryUL_v1310 && *c131->ue_CategoryUL_v1310 == 0) *catUL=14; + if (c131->ue_CategoryUL_v1310 && *c131->ue_CategoryUL_v1310 == 1) *catUL=-1; + struct LTE_UE_EUTRA_Capability_v1320_IEs *c132=c131->NCE; + if (c132 != NULL) { //v13.2 + struct LTE_UE_EUTRA_Capability_v1330_IEs *c133=c132->NCE; + if (c133 != NULL) { // v13.3 + if (c133->ue_CategoryDL_v1330) *catDL=*c133->ue_CategoryDL_v1330; + struct LTE_UE_EUTRA_Capability_v1340_IEs *c134=c133->NCE; + if (c134 != NULL) { // v13.4 + if (c134->ue_CategoryUL_v1340) *catUL=*c134->ue_CategoryUL_v1340; + struct LTE_UE_EUTRA_Capability_v1350_IEs *c135=c134->NCE; + if (c135 != NULL) { // v13.5 + if (c135->ue_CategoryDL_v1350) *catDL=99; // Cat 1Bis + if (c135->ue_CategoryUL_v1350) *catUL=99; // Cat 1Bis + struct LTE_UE_EUTRA_Capability_v1360_IEs *c136=c135->NCE; + if (c136 != NULL) { // v13.6 + struct LTE_UE_EUTRA_Capability_v1430_IEs *c143=c136->NCE; + if (c143 != NULL) { // v14.3 + if (c143->ue_CategoryDL_v1430 && *c143->ue_CategoryDL_v1430 == LTE_UE_EUTRA_Capability_v1430_IEs__ue_CategoryDL_v1430_m2) *catDL=-2; + if (c143->ue_CategoryUL_v1430 && *c143->ue_CategoryUL_v1430 == LTE_UE_EUTRA_Capability_v1430_IEs__ue_CategoryDL_v1430_m2) *catUL=-2; + if (c143->ue_CategoryUL_v1430) *catUL=16+*c143->ue_CategoryUL_v1430; + if (c143->ue_CategoryUL_v1430b)*catUL=21; + struct LTE_UE_EUTRA_Capability_v1440_IEs *c144=c143->NCE; + if (c144 != NULL) { // v14.4 + struct LTE_UE_EUTRA_Capability_v1450_IEs *c145=c144->NCE; + if (c145 != NULL) { // v14.5 + if (c145->ue_CategoryDL_v1450) *catDL=*c145->ue_CategoryDL_v1450; + struct LTE_UE_EUTRA_Capability_v1460_IEs *c146=c145->NCE; + if (c146 != NULL) { // v14.6 + if (c146->ue_CategoryDL_v1460) *catDL=*c146->ue_CategoryDL_v1460; + struct LTE_UE_EUTRA_Capability_v1510_IEs *c151=c146->NCE; + if (c151 != NULL) { // v15.1 + struct LTE_UE_EUTRA_Capability_v1520_IEs *c152=c151->NCE; + if (c152 != NULL) { // v15.20 + struct LTE_UE_EUTRA_Capability_v1530_IEs *c153=c152->NCE; + if (c153 != NULL) { // v15.30 + if (c153->ue_CategoryDL_v1530) *catDL=*c153->ue_CategoryDL_v1530; + if (c153->ue_CategoryUL_v1530) *catUL=*c153->ue_CategoryUL_v1530; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} + +static int +is_ul_64QAM_supported( + LTE_UE_EUTRA_Capability_t *c +) //----------------------------------------------------------------------------- +{ + return c != NULL // R8 + && c->NCE != NULL // R92 + && c->NCE->NCE != NULL // R94 + && c->NCE->NCE->NCE != NULL // R102 + && c->NCE->NCE->NCE->NCE != NULL // R106 + && c->NCE->NCE->NCE->NCE->NCE != NULL // R109 + && c->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R113 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R117 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R118 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R11a + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R125 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250 != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250->supportedBandListEUTRA_v1250 != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250->supportedBandListEUTRA_v1250->list.array != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250->supportedBandListEUTRA_v1250->list.array[0]->ul_64QAM_r12 != NULL + && *c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250->supportedBandListEUTRA_v1250->list.array[0]->ul_64QAM_r12==LTE_SupportedBandEUTRA_v1250__ul_64QAM_r12_supported; +} + +static int +is_dl_256QAM_supported( + LTE_UE_EUTRA_Capability_t *c +) +//----------------------------------------------------------------------------- +{ + return c != NULL // R8 + && c->NCE != NULL // R92 + && c->NCE->NCE != NULL // R94 + && c->NCE->NCE->NCE != NULL // R102 + && c->NCE->NCE->NCE->NCE != NULL // R106 + && c->NCE->NCE->NCE->NCE->NCE != NULL // R109 + && c->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R113 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R117 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R118 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R11a + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R125 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250 != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250->supportedBandListEUTRA_v1250 != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250->supportedBandListEUTRA_v1250->list.array != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250->supportedBandListEUTRA_v1250->list.array[0]->dl_256QAM_r12 != NULL + && *c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1250->supportedBandListEUTRA_v1250->list.array[0]->dl_256QAM_r12==LTE_SupportedBandEUTRA_v1250__dl_256QAM_r12_supported; + +} +static int +is_ul_256QAM_supported( + LTE_UE_EUTRA_Capability_t *c +) +//----------------------------------------------------------------------------- +{ + return c != NULL // R8 + && c->NCE != NULL // R92 + && c->NCE->NCE != NULL // R94 + && c->NCE->NCE->NCE != NULL // R102 + && c->NCE->NCE->NCE->NCE != NULL // R106 + && c->NCE->NCE->NCE->NCE->NCE != NULL // R109 + && c->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R113 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R117 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R118 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R11a + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R125 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R126 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // 127 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // 128 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //131 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //132 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //133 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //134 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //135 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //136 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //143 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1430 != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1430->supportedBandCombination_v1430 != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1430->supportedBandCombination_v1430->list.array != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1430->supportedBandCombination_v1430->list.array[0]->bandParameterList_v1430 != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1430->supportedBandCombination_v1430->list.array[0]->bandParameterList_v1430->list.array != NULL + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1430->supportedBandCombination_v1430->list.array[0]->bandParameterList_v1430->list.array[0]->ul_256QAM_r14!=NULL + && *c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->rf_Parameters_v1430->supportedBandCombination_v1430->list.array[0]->bandParameterList_v1430->list.array[0]->ul_256QAM_r14==LTE_BandParameters_v1430__ul_256QAM_r14_supported; +} + static int is_en_dc_supported( LTE_UE_EUTRA_Capability_t *c ) //----------------------------------------------------------------------------- { - /* to be refined - check that the eNB is connected to a gNB, check that - * the bands supported by the UE include the band of the gNB + /* to be refined - check that the bands supported by the UE include + * the band of the gNB */ -#define NCE nonCriticalExtension - return c != NULL - && c->NCE != NULL - && c->NCE->NCE != NULL - && c->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL - && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL + return c != NULL // R8 + && c->NCE != NULL // R92 + && c->NCE->NCE != NULL // R94 + && c->NCE->NCE->NCE != NULL // R102 + && c->NCE->NCE->NCE->NCE != NULL // R106 + && c->NCE->NCE->NCE->NCE->NCE != NULL // R109 + && c->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R113 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R117 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R118 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R11a + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R125 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // R126 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // 127 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL // 128 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //131 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //132 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //133 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //134 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //135 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //136 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //143 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //144 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //145 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //146 + && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE != NULL //151 && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->irat_ParametersNR_r15 != NULL && c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->irat_ParametersNR_r15->en_DC_r15 != NULL && *c->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->NCE->irat_ParametersNR_r15->en_DC_r15 == @@ -7636,6 +7832,45 @@ is_en_dc_supported( #undef NCE } +int to_nr_rsrpq(long rsrpq_result,int nr_band) { + + switch(nr_band) { + case 1: // A + case 70: + case 74: + case 34: + case 38: + case 39: + case 40: + case 50: + case 51: + return((rsrpq_result*10)-1180); + case 66: // B + return((rsrpq_result*10)-1175); + case 77: // C + case 78: + case 79: + return((rsrpq_result*10)-1170); + case 28: // D + return((rsrpq_result*10)-1165); + case 2: + case 5: + case 7: + case 41: // E + return((rsrpq_result*10)-1160); + case 3: // G + case 8: + case 12: + case 20: + case 71: + return((rsrpq_result*10)-1150); + case 25: // H + return((rsrpq_result*10)-1145); + default: + AssertFatal(1==0,"Illegal NR band %d\n",nr_band); + } +} + //----------------------------------------------------------------------------- int rrc_eNB_decode_dcch( @@ -7760,7 +7995,7 @@ rrc_eNB_decode_dcch( int flexran_agent_handover = 0; if (EPC_MODE_ENABLED) { - if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) { + if (ue_context_p->ue_context.StatusRrc == RRC_RECONFIGURED) { dedicated_DRB = 1; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld)\n", @@ -7785,7 +8020,7 @@ rrc_eNB_decode_dcch( dedicated_DRB = 2; RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0; } - } else if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION) { + } else if (ue_context_p->ue_context.StatusRrc == RRC_HO_EXECUTION) { int16_t UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); if(UE_id == -1) { @@ -7799,7 +8034,7 @@ rrc_eNB_decode_dcch( RC.rrc[ctxt_pP->module_id]->Nb_ue++; dedicated_DRB = 3; RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0; - ue_context_p->ue_context.Status = RRC_RECONFIGURED; + ue_context_p->ue_context.StatusRrc = RRC_RECONFIGURED; if(ue_context_p->ue_context.handover_info) { ue_context_p->ue_context.handover_info->state = HO_CONFIGURED; @@ -7808,8 +8043,7 @@ rrc_eNB_decode_dcch( LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_HO_EXECUTION (xid %ld)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); - } - else if(ue_context_p->ue_context.Status == RRC_NR_NSA){ + } else if(ue_context_p->ue_context.StatusRrc == RRC_NR_NSA) { //Looking for a condition to trigger S1AP E-RAB-Modification-indication, based on the reception of RRCConnectionReconfigurationComplete //including NR specific elements. if(ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.criticalExtensions.choice.rrcConnectionReconfigurationComplete_r8. @@ -7827,9 +8061,12 @@ rrc_eNB_decode_dcch( if(ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.criticalExtensions.choice.rrcConnectionReconfigurationComplete_r8. nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension ->scg_ConfigResponseNR_r15!=NULL) { - ue_context_p->ue_context.Status = RRC_NR_NSA_RECONFIGURED; + dedicated_DRB = -1; /* put a value that does not run anything below */ + ue_context_p->ue_context.StatusRrc = RRC_NR_NSA_RECONFIGURED; /*Trigger E-RAB Modification Indication */ rrc_eNB_send_E_RAB_Modification_Indication(ctxt_pP, ue_context_p); + /* send reconfiguration complete to gNB */ + rrc_eNB_process_reconfiguration_complete_endc(ctxt_pP, ue_context_p); } } } @@ -7837,20 +8074,18 @@ rrc_eNB_decode_dcch( } } } - } - else { + } else { dedicated_DRB = 0; - ue_context_p->ue_context.Status = RRC_RECONFIGURED; + ue_context_p->ue_context.StatusRrc = RRC_RECONFIGURED; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (default DRB, xid %ld)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); } ue_context_p->ue_context.reestablishment_xid = -1; - } else { dedicated_DRB = 1; - ue_context_p->ue_context.Status = RRC_RECONFIGURED; + ue_context_p->ue_context.StatusRrc = RRC_RECONFIGURED; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); @@ -7889,9 +8124,10 @@ rrc_eNB_decode_dcch( xid = ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier; ue_context_p->ue_context.e_rab_release_command_flag = 0; //gtp tunnel delete - msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ); + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, 0, GTPV1U_ENB_DELETE_TUNNEL_REQ); memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0; for(i = 0; i < NB_RB_MAX; i++) { if(xid == ue_context_p->ue_context.e_rab[i].xid) { @@ -8204,7 +8440,7 @@ rrc_eNB_decode_dcch( ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability,ue_context_p->ue_context.UE_Capability_nr); ue_context_p->ue_context.UE_Capability_nr = 0; } - + LOG_I(RRC,"Received NR_UE_Capabilities\n"); dec_rval = uper_decode(NULL, &asn_DEF_NR_UE_NR_Capability, (void **)&ue_context_p->ue_context.UE_Capability_nr, @@ -8229,6 +8465,8 @@ rrc_eNB_decode_dcch( if (ul_dcch_msg->message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.array[i]->rat_Type == LTE_RAT_Type_eutra_nr) { + LOG_I(RRC,"Received UE_Capabilities_MRDC\n"); + if(ue_context_p->ue_context.UE_Capability_MRDC) { ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability,ue_context_p->ue_context.UE_Capability_MRDC); ue_context_p->ue_context.UE_Capability_MRDC = 0; @@ -8300,8 +8538,13 @@ rrc_eNB_decode_dcch( ue_context_p->ue_context.UE_Capability = 0; } - if (dec_rval.code == RC_OK) - ue_context_p->ue_context.does_nr = is_en_dc_supported(ue_context_p->ue_context.UE_Capability); + if (dec_rval.code == RC_OK) { + /* do NR only if at least one gNB connected */ + if (RC.rrc[ctxt_pP->module_id]->num_gnb_cells != 0) + ue_context_p->ue_context.does_nr = is_en_dc_supported(ue_context_p->ue_context.UE_Capability); + else + ue_context_p->ue_context.does_nr = 0; + } if (EPC_MODE_ENABLED) { rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP, @@ -8383,8 +8626,7 @@ rrc_eNB_decode_dcch( case LTE_UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10: T(T_ENB_RRC_MBMS_COUNTING_RESPONSE_R10, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); - LOG_E(RRC, "THINH [LTE_UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10]\n"); - + LOG_E(RRC, "THINH [LTE_UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10]\n"); break; case LTE_UL_DCCH_MessageType__c1_PR_interFreqRSTDMeasurementIndication_r10: @@ -8412,46 +8654,57 @@ rrc_eNB_decode_dcch( case LTE_UL_DCCH_MessageType__messageClassExtension_PR_c2: //SidelinkUEInformation if(ul_dcch_msg->message.choice.messageClassExtension.choice.c2.present == - LTE_UL_DCCH_MessageType__messageClassExtension__c2_PR_scgFailureInformationNR_r15){ + LTE_UL_DCCH_MessageType__messageClassExtension__c2_PR_scgFailureInformationNR_r15) { if (ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15. - criticalExtensions.present == LTE_SCGFailureInformationNR_r15__criticalExtensions_PR_c1){ + criticalExtensions.present == LTE_SCGFailureInformationNR_r15__criticalExtensions_PR_c1) { if (ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions. - choice.c1.present == LTE_SCGFailureInformationNR_r15__criticalExtensions__c1_PR_scgFailureInformationNR_r15){ + choice.c1.present == LTE_SCGFailureInformationNR_r15__criticalExtensions__c1_PR_scgFailureInformationNR_r15) { if (ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions. - choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15!=NULL) { + choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15!=NULL) { LOG_E(RRC, "Received NR scgFailureInformation from UE, failure type: %ld \n", - ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions. - choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15->failureType_r15); + ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions. + choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15->failureType_r15); xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)ul_dcch_msg); + + /* TODO: scg failure indication, what to do? Let's remove the UE for now. + * We could re-establish DRB? + * Also, the way to remove is to start ue_release_timer_rrc and + * send RRCConnectionRelease to the UE, maybe it's not good/correct. + */ + if (ue_context_p != NULL) { + ue_context_p->ue_context.ue_release_timer_thres_rrc = 100; + ue_context_p->ue_context.ue_release_timer_rrc = 1; + rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p); + } } } } - } - else if(ul_dcch_msg->message.choice.messageClassExtension.choice.c2.present == LTE_UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12){ + } else if(ul_dcch_msg->message.choice.messageClassExtension.choice.c2.present == LTE_UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12) { //case UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12: //SidelinkUEInformation LOG_I(RRC,"THINH [LTE_UL_DCCH_MessageType__messageClassExtension_PR_c2]\n"); LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, - "[MSG] RRC SidelinkUEInformation \n"); + "[MSG] RRC SidelinkUEInformation \n"); MSC_LOG_RX_MESSAGE( - MSC_RRC_ENB, - MSC_RRC_UE, - Rx_sdu, - sdu_sizeP, - MSC_AS_TIME_FMT" SidelinkUEInformation UE %x size %u", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_p->ue_context.rnti, - sdu_sizeP); - LOG_I(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " - "(SidelinkUEInformation) ---> RRC_eNB\n", - PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), - DCCH, + MSC_RRC_ENB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" SidelinkUEInformation UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, sdu_sizeP); + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(SidelinkUEInformation) ---> RRC_eNB\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); rrc_eNB_process_SidelinkUEInformation( ctxt_pP, ue_context_p, &ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.sidelinkUEInformation_r12); - } + } + break; default: @@ -8560,28 +8813,27 @@ void handle_f1_setup_req(f1ap_setup_req_t *f1_setup_req) { // prepare F1_SETUP_RESPONSE if (msg_p == NULL) { - msg_p = itti_alloc_new_message (TASK_CU_F1,F1AP_SETUP_RESP); + msg_p = itti_alloc_new_message (TASK_CU_F1, 0,F1AP_SETUP_RESP); } F1AP_SETUP_RESP (msg_p).gNB_CU_name = rrc->node_name; - F1AP_SETUP_RESP (msg_p).mcc[cu_cell_ind] = rrc->configuration.mcc[0]; - F1AP_SETUP_RESP (msg_p).mnc[cu_cell_ind] = rrc->configuration.mnc[0]; - F1AP_SETUP_RESP (msg_p).mnc_digit_length[cu_cell_ind] = rrc->configuration.mnc_digit_length[0]; - F1AP_SETUP_RESP (msg_p).nr_cellid[cu_cell_ind] = rrc->nr_cellid; - F1AP_SETUP_RESP (msg_p).nrpci[cu_cell_ind] = f1_setup_req->nr_pci[i]; + F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].mcc = rrc->configuration.mcc[0]; + F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].mnc = rrc->configuration.mnc[0]; + F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].mnc_digit_length = rrc->configuration.mnc_digit_length[0]; + F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].nr_cellid = rrc->nr_cellid; + F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].nrpci = f1_setup_req->nr_pci[i]; int num_SI= 0; - if (rrc->carrier[0].SIB23) { - F1AP_SETUP_RESP (msg_p).SI_container[cu_cell_ind][num_SI] = rrc->carrier[0].SIB23; - F1AP_SETUP_RESP (msg_p).SI_container_length[cu_cell_ind][num_SI] = rrc->carrier[0].sizeof_SIB23; - //printf("SI %d size %d: ", 0, F1AP_SETUP_RESP(msg_p).SI_container_length[j][num_SI]); - //for (int n = 0; n < F1AP_SETUP_RESP(msg_p).SI_container_length[j][num_SI]; n++) - // printf("%02x ", F1AP_SETUP_RESP(msg_p).SI_container[0][num_SI][n]); + F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].SI_container[2+num_SI] = rrc->carrier[0].SIB23; + F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].SI_container_length[2+num_SI] = rrc->carrier[0].sizeof_SIB23; + //printf("SI %d size %d: ", 0, F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].SI_container_length[2+num_SI]); + //for (int n = 0; n < F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].SI_container_length[2+num_SI]; n++) + // printf("%02x ", F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].SI_container[2+num_SI][n]); //printf("\n"); num_SI++; } - F1AP_SETUP_RESP (msg_p).num_SI[cu_cell_ind] = num_SI; + F1AP_SETUP_RESP (msg_p).cells_to_activate[cu_cell_ind].num_SI = num_SI; cu_cell_ind++; found_cell=1; F1AP_SETUP_RESP (msg_p).num_cells_to_activate = cu_cell_ind; @@ -8596,7 +8848,7 @@ void handle_f1_setup_req(f1ap_setup_req_t *f1_setup_req) { if (found_cell==0) { AssertFatal(1==0,"No cell found\n"); - /*msg_p = itti_alloc_new_message (TASK_CU_F1,F1AP_SETUP_FAILURE); + /*msg_p = itti_alloc_new_message (TASK_CU_F1, 0,F1AP_SETUP_FAILURE); F1AP_SETUP_RESP (msg_p).cause = rrc->node_name; F1AP_SETUP_RESP (msg_p).time_to_wait = rrc->node_id; F1AP_SETUP_RESP (msg_p).criticality_diagnostics = rrc->node_name;*/ @@ -8618,17 +8870,14 @@ void rrc_enb_init(void) { //----------------------------------------------------------------------------- void process_successful_rlc_sdu_indication(int instance, - int rnti, - int message_id) -{ + int rnti, + int message_id) { int release_num; int release_total; RRC_release_ctrl_t *release_ctrl; - /* Check if the message sent was RRC Connection Release. * If yes then continue the release process. */ - pthread_mutex_lock(&rrc_release_freelist); if (rrc_release_info.num_UEs > 0) { @@ -8670,14 +8919,11 @@ void process_successful_rlc_sdu_indication(int instance, } //----------------------------------------------------------------------------- -void process_unsuccessful_rlc_sdu_indication(int instance, int rnti) -{ +void process_unsuccessful_rlc_sdu_indication(int instance, int rnti) { int release_num; int release_total; RRC_release_ctrl_t *release_ctrl; - /* radio link failure detected by RLC layer, remove UE properly */ - pthread_mutex_lock(&rrc_release_freelist); /* first, check if the rnti is in the list rrc_release_info.RRC_release_ctrl */ @@ -8745,8 +8991,7 @@ void process_rlc_sdu_indication(int instance, int rnti, int is_successful, int srb_id, - int message_id) -{ + int message_id) { if (is_successful) process_successful_rlc_sdu_indication(instance, rnti, message_id); else @@ -8783,37 +9028,64 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { struct rrc_eNB_ue_context_s *ue_to_be_removed[NUMBER_OF_UE_MAX]; int removed_ue_count = 0; int cur_ue; -#ifdef LOCALIZATION - double estimated_distance = 0; - protocol_ctxt_t ctxt; -#endif MessageDef *msg; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX, VCD_FUNCTION_IN); if (RC.rrc[ENB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)]->configuration.enable_x2) { /* send a tick to x2ap */ - msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_SUBFRAME_PROCESS); + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_SUBFRAME_PROCESS); itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg); check_handovers(ctxt_pP); // counter, get the value and aggregate } // check for UL failure or for UE to be released + FILE *fd=NULL; + if ((ctxt_pP->frame&127) == 0 && ctxt_pP->subframe ==0) + fd=fopen("RRC_stats.log","w+"); + RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) { ctxt_pP->rnti = ue_context_p->ue_id_rnti; - if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe == 0)) { - if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { - LOG_I(RRC, "UE rnti %x: S-TMSI %x failure timer %d/8\n", - ue_context_p->ue_context.rnti, - ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, - ue_context_p->ue_context.ul_failure_timer); - } else { - LOG_I(RRC, "UE rnti %x failure timer %d/8\n", - ue_context_p->ue_context.rnti, - ue_context_p->ue_context.ul_failure_timer); + if ((ctxt_pP->frame&127) == 0 && ctxt_pP->subframe ==0) { + if (fd) { + if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { + fprintf(fd,"RRC UE rnti %x: S-TMSI %x failure timer %d/8\n", + ue_context_p->ue_context.rnti, + ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, + ue_context_p->ue_context.ul_failure_timer); + } else { + fprintf(fd,"RRC UE rnti %x failure timer %d/8\n", + ue_context_p->ue_context.rnti, + ue_context_p->ue_context.ul_failure_timer); + } + + if (ue_context_p->ue_context.UE_Capability) { + long catDL,catUL; + get_ue_Category(ue_context_p->ue_context.UE_Capability,&catDL,&catUL); + fprintf(fd,"RRC UE cap: CatDL %ld, CatUL %ld, 64QAM UL %s, 256 QAM DL %s, 256 QAM UL %s, ENDC %s,\n", + catDL,catUL, + is_ul_64QAM_supported(ue_context_p->ue_context.UE_Capability) == 1 ? "yes" : "no", + is_dl_256QAM_supported(ue_context_p->ue_context.UE_Capability) == 1 ? "yes" : "no", + is_ul_256QAM_supported(ue_context_p->ue_context.UE_Capability) == 1 ? "yes" : "no", + is_en_dc_supported(ue_context_p->ue_context.UE_Capability) == 1 ? "yes" : "no"); + } + if (ue_context_p->ue_context.measResults) { + fprintf(fd, "RRC PCell RSRP %ld, RSRQ %ld\n", ue_context_p->ue_context.measResults->measResultPCell.rsrpResult-140, + ue_context_p->ue_context.measResults->measResultPCell.rsrqResult/2 - 20); + if (ue_context_p->ue_context.measResults->measResultNeighCells && + ue_context_p->ue_context.measResults->measResultNeighCells->present == LTE_MeasResults__measResultNeighCells_PR_measResultNeighCellListNR_r15) { + + fprintf(fd,"NR_pci %ld\n",ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]->pci_r15); + if(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]->measResultCell_r15.rsrpResult_r15) + fprintf(fd,"NR_rsrp %f dB\n",to_nr_rsrpq(*ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]->measResultCell_r15.rsrpResult_r15,RC.rrc[ctxt_pP->module_id]->nr_gnb_freq_band[0][0])/10.0); + if (ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]->measResultCell_r15.rsrqResult_r15) + fprintf(fd,"NR_rsrq %f dB\n",to_nr_rsrpq(*ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]->measResultCell_r15.rsrqResult_r15,RC.rrc[ctxt_pP->module_id]->nr_gnb_freq_band[0][0])/10.0); + if (ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]->measResultRS_IndexList_r15) + fprintf(fd,"NR_ssb_index %ld\n",ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultNeighCellListNR_r15.list.array[0]->measResultRS_IndexList_r15->list.array[0]->ssb_Index_r15); + } + } } } - if (ue_context_p->ue_context.ul_failure_timer > 0) { ue_context_p->ue_context.ul_failure_timer++; @@ -8980,6 +9252,19 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { ue_to_be_removed[cur_ue]->ue_context.ue_reestablishment_timer = 0; } + /* remove UE from gNB if UE is in NSA mode */ + if (ue_to_be_removed[cur_ue]->ue_context.StatusRrc == RRC_NR_NSA || + ue_to_be_removed[cur_ue]->ue_context.StatusRrc == RRC_NR_NSA_RECONFIGURED) { + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_RELEASE_REQUEST); + X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).rnti = ue_to_be_removed[cur_ue]->ue_context.gnb_rnti; + X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).assoc_id = ue_to_be_removed[cur_ue]->ue_context.gnb_x2_assoc_id; + X2AP_ENDC_SGNB_RELEASE_REQUEST(message_p).cause = X2AP_CAUSE_RADIO_CONNECTION_WITH_UE_LOST; + itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, message_p); + /* set state to RRC_NR_NSA_DELETED to avoid sending X2AP_ENDC_SGNB_RELEASE_REQUEST again later */ + ue_to_be_removed[cur_ue]->ue_context.StatusRrc = RRC_NR_NSA_DELETED; + } + rrc_eNB_free_UE(ctxt_pP->module_id, ue_to_be_removed[cur_ue]); if (ue_to_be_removed[cur_ue]->ue_context.ul_failure_timer >= 20000) { @@ -8992,37 +9277,36 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { } } -#ifdef RRC_LOCALIZATION - /* for the localization, only primary CC_id might be relevant*/ - gettimeofday(&ts, NULL); - current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000; - ref_timestamp_ms = RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms; - RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) { - ctxt = *ctxt_pP; - ctxt.rnti = ue_context_p->ue_context.rnti; - estimated_distance = rrc_get_estimated_ue_distance(&ctxt, CC_id, RC.rrc[ctxt_pP->module_id]->loc_type); + if (fd!=NULL) fclose(fd); + - if ((current_timestamp_ms - ref_timestamp_ms > RC.rrc[ctxt_pP->module_id]->aggregation_period_ms) && - estimated_distance != -1) { - LOG_D(LOCALIZE, "RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n", - ctxt.rnti, - ctxt_pP->module_id, - current_timestamp_ms, - ctxt_pP->frame, - estimated_distance); - LOG_D(LOCALIZE, "RRC status %d\n", - ue_context_p->ue_context.Status); - push_front(&RC.rrc[ctxt_pP->module_id]->loc_list, estimated_distance); - RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms = current_timestamp_ms; - } // end if - } // end RB_FOREACH -#endif (void)ts; /* remove gcc warning "unused variable" */ (void)ref_timestamp_ms; /* remove gcc warning "unused variable" */ (void)current_timestamp_ms; /* remove gcc warning "unused variable" */ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX, VCD_FUNCTION_OUT); } +void rrc_eNB_process_ENDC_x2_setup_request(int mod_id, x2ap_ENDC_setup_req_t *m) { + if (RC.rrc[mod_id]->num_gnb_cells >= MAX_NUM_GNB_CELLs) { + LOG_E(RRC, "Error: number of gNB cells is exceeded\n"); + return; + } + + if (m->num_cc > MAX_NUM_CCs) { + LOG_E(RRC, "Error: number of gNB cells carriers is exceeded \n"); + return; + } + + RC.rrc[mod_id]->num_gnb_cells++; + RC.rrc[mod_id]->num_gnb_cells_cc[RC.rrc[mod_id]->num_gnb_cells-1] = m->num_cc; + + for (int i=0; inum_cc; i++) { + RC.rrc[mod_id]->gnb_cells_id[RC.rrc[mod_id]->num_gnb_cells-1][i] = m->Nid_cell[i]; + RC.rrc[mod_id]->nr_gnb_freq_band[RC.rrc[mod_id]->num_gnb_cells-1][i] = m->servedNrCell_band[i]; + } + +} + void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP, x2ap_ENDC_sgnb_addition_req_ACK_t *m) { NR_CG_Config_t *CG_Config = NULL; { @@ -9094,41 +9378,97 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP, unsigned char buffer[8192]; int size; ue_context = rrc_eNB_get_ue_context(RC.rrc[enb_mod_idP], m->rnti); - ue_context->ue_context.nb_of_modify_endc_e_rabs = m->nb_e_rabs_admitted_tobeadded; - int j=0; - while(j < m->nb_e_rabs_admitted_tobeadded) { - for (int e_rab_idx=0; e_rab_idxue_context.setup_e_rabs; e_rab_idx++) { - //Update ue_context information with gNB's address and new GTP tunnel ID - if( ue_context->ue_context.e_rab[e_rab_idx].param.e_rab_id == m->e_rabs_admitted_tobeadded[j].e_rab_id) { - memcpy(ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].buffer, - m->e_rabs_admitted_tobeadded[j].gnb_addr.buffer, - m->e_rabs_admitted_tobeadded[j].gnb_addr.length); - ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].length = m->e_rabs_admitted_tobeadded[j].gnb_addr.length; - ue_context->ue_context.gnb_gtp_endc_teid[e_rab_idx] = m->e_rabs_admitted_tobeadded[j].gtp_teid; - ue_context->ue_context.e_rab[e_rab_idx].status = E_RAB_STATUS_TOMODIFY; - break; + if (ue_context) { + ue_context->ue_context.nb_of_modify_endc_e_rabs = m->nb_e_rabs_admitted_tobeadded; + + ue_context->ue_context.gnb_rnti = m->SgNB_ue_x2_id; + ue_context->ue_context.gnb_x2_assoc_id = m->gnb_x2_assoc_id; + + int j=0; + + while(j < m->nb_e_rabs_admitted_tobeadded) { + for (int e_rab_idx=0; e_rab_idxue_context.setup_e_rabs; e_rab_idx++) { + //Update ue_context information with gNB's address and new GTP tunnel ID + if( ue_context->ue_context.e_rab[e_rab_idx].param.e_rab_id == m->e_rabs_admitted_tobeadded[j].e_rab_id) { + memcpy(ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].buffer, + m->e_rabs_admitted_tobeadded[j].gnb_addr.buffer, + m->e_rabs_admitted_tobeadded[j].gnb_addr.length); + ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].length = m->e_rabs_admitted_tobeadded[j].gnb_addr.length; + ue_context->ue_context.gnb_gtp_endc_teid[e_rab_idx] = m->e_rabs_admitted_tobeadded[j].gtp_teid; + ue_context->ue_context.e_rab[e_rab_idx].status = E_RAB_STATUS_TOMODIFY; + break; + } } + + j++; } - j++; + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + 0, + ENB_FLAG_YES, + m->rnti, + 0, 0); + size = rrc_eNB_generate_RRCConnectionReconfiguration_endc(&ctxt, ue_context, buffer, 8192, scg_CellGroupConfig, nr1_conf); + rrc_data_req(&ctxt, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + } else { + LOG_E(F1AP, "no ue_context for RNTI %x, acknowledging release\n", m->rnti); } - - PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, - 0, - ENB_FLAG_YES, - m->rnti, - 0, 0); - size = rrc_eNB_generate_RRCConnectionReconfiguration_endc(&ctxt, ue_context, buffer, 8192, scg_CellGroupConfig, nr1_conf); - rrc_data_req(&ctxt, - DCCH, - rrc_eNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); } +void rrc_eNB_process_ENDC_DC_prep_timeout(module_id_t module_id, x2ap_ENDC_dc_prep_timeout_t *m) +{ + rrc_eNB_ue_context_t *ue_context; + + ue_context = rrc_eNB_get_ue_context(RC.rrc[module_id], m->rnti); + if (ue_context == NULL) { + LOG_E(RRC, "receiving DC prep timeout for unknown UE rnti %d\n", m->rnti); + return; + } + + if (ue_context->ue_context.StatusRrc != RRC_NR_NSA) { + LOG_E(RRC, "receiving DC prep timeout for UE rnti %d not in state RRC_NR_NSA\n", m->rnti); + return; + } + + LOG_I(RRC, "DC prep timeout for UE rnti %d, put back to RRC_RECONFIGURED mode\n", m->rnti); + ue_context->ue_context.StatusRrc = RRC_RECONFIGURED; +} + +void rrc_eNB_process_ENDC_sgNB_release_required(module_id_t module_id, x2ap_ENDC_sgnb_release_required_t *m) +{ + rrc_eNB_ue_context_t *ue_context; + protocol_ctxt_t ctxt; + + ue_context = rrc_eNB_find_ue_context_from_gnb_rnti(RC.rrc[module_id], m->gnb_rnti); + if (ue_context == NULL) { + LOG_E(RRC, "receiving ENDC SgNB Release Required for unknown UE (with gNB's rnti %d)\n", m->gnb_rnti); + return; + } + + /* TODO: what to do? release the UE? if yes, how? Or re-establish bearers in LTE? + * Or something else? + * The following removes the UE, maybe it's not correct at all. + */ + ue_context->ue_context.ue_release_timer_thres_rrc = 100; + ue_context->ue_context.ue_release_timer_rrc = 1; + + ue_context->ue_context.StatusRrc = RRC_NR_NSA_DELETED; + + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + module_id, /* TODO: should be 'instance' */ + ENB_FLAG_YES, + ue_context->ue_context.rnti, + 0, 0); + + rrc_eNB_generate_RRCConnectionRelease(&ctxt, ue_context); +} //----------------------------------------------------------------------------- void *rrc_enb_process_itti_msg(void *notUsed) { @@ -9141,7 +9481,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { // Wait for a message itti_receive_msg(TASK_RRC_ENB, &msg_p); msg_name_p = ITTI_MSG_NAME(msg_p); - instance = ITTI_MSG_INSTANCE(msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p); /* RRC_SUBFRAME_PROCESS is sent every subframe, do not log it */ if (ITTI_MSG_ID(msg_p) != RRC_SUBFRAME_PROCESS) @@ -9154,7 +9494,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { break; case MESSAGE_TEST: - LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p); + LOG_I(RRC, "[eNB %ld] Received %s\n", instance, msg_name_p); break; /* Messages from MAC */ @@ -9165,7 +9505,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { RRC_MAC_CCCH_DATA_IND(msg_p).rnti, msg_p->ittiMsgHeader.lte_time.frame, msg_p->ittiMsgHeader.lte_time.slot); - LOG_I(RRC,"Decoding CCCH : inst %d, CC_id %d, ctxt %p, sib_info_p->Rx_buffer.payload_size %d\n", + LOG_I(RRC,"Decoding CCCH : inst %ld, CC_id %d, ctxt %p, sib_info_p->Rx_buffer.payload_size %d\n", instance, RRC_MAC_CCCH_DATA_IND(msg_p).CC_id, &ctxt, @@ -9223,13 +9563,13 @@ void *rrc_enb_process_itti_msg(void *notUsed) { break; case S1AP_PAGING_IND: - LOG_D(RRC, "[eNB %d] Received Paging message from S1AP: %s\n", instance, msg_name_p); + LOG_D(RRC, "[eNB %ld] Received Paging message from S1AP: %s\n", instance, msg_name_p); rrc_eNB_process_PAGING_IND(msg_p, msg_name_p, instance); break; case S1AP_E_RAB_SETUP_REQ: rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(msg_p, msg_name_p, instance); - LOG_D(RRC, "[eNB %d] Received the message %s\n", instance, msg_name_p); + LOG_D(RRC, "[eNB %ld] Received the message %s\n", instance, msg_name_p); break; case S1AP_E_RAB_MODIFY_REQ: @@ -9263,7 +9603,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { } case S1AP_PATH_SWITCH_REQ_ACK: - LOG_I(RRC, "[eNB %d] received path switch ack %s\n", instance, msg_name_p); + LOG_I(RRC, "[eNB %ld] received path switch ack %s\n", instance, msg_name_p); rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK(msg_p, msg_name_p, instance); break; @@ -9276,7 +9616,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { break; case X2AP_HANDOVER_REQ: - LOG_I(RRC, "[eNB %d] target eNB Receives X2 HO Req %s\n", instance, msg_name_p); + LOG_I(RRC, "[eNB %ld] target eNB Receives X2 HO Req %s\n", instance, msg_name_p); rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p)); break; @@ -9294,7 +9634,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { exit(1); } - LOG_I(RRC, "[eNB %d] source eNB receives the X2 HO ACK %s\n", instance, msg_name_p); + LOG_I(RRC, "[eNB %ld] source eNB receives the X2 HO ACK %s\n", instance, msg_name_p); DevAssert(ue_context_p != NULL); if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort(); @@ -9345,7 +9685,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { case X2AP_UE_CONTEXT_RELEASE: { struct rrc_eNB_ue_context_s *ue_context_p = NULL; ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], X2AP_UE_CONTEXT_RELEASE(msg_p).rnti); - LOG_I(RRC, "[eNB %d] source eNB receives the X2 UE CONTEXT RELEASE %s\n", instance, msg_name_p); + LOG_I(RRC, "[eNB %ld] source eNB receives the X2 UE CONTEXT RELEASE %s\n", instance, msg_name_p); DevAssert(ue_context_p != NULL); if (ue_context_p->ue_context.handover_info->state != HO_COMPLETE) abort(); @@ -9376,7 +9716,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { if (ue_context_p != NULL && ue_context_p->ue_context.handover_info != NULL) { - LOG_I(RRC, "[eNB %d] eNB receives X2 HANDOVER CANCEL for rnti %x, cause %s [%s]\n", + LOG_I(RRC, "[eNB %ld] eNB receives X2 HANDOVER CANCEL for rnti %x, cause %s [%s]\n", instance, X2AP_HANDOVER_CANCEL(msg_p).rnti, cause, @@ -9385,7 +9725,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { if (X2AP_HANDOVER_CANCEL(msg_p).cause == X2AP_T_RELOC_PREP_TIMEOUT) { /* for prep timeout, simply return to normal state */ /* TODO: be sure that it's correct to set Status to RRC_RECONFIGURED */ - ue_context_p->ue_context.Status = RRC_RECONFIGURED; + ue_context_p->ue_context.StatusRrc = RRC_RECONFIGURED; /* TODO: be sure free is enough here (check memory leaks) */ free(ue_context_p->ue_context.handover_info); ue_context_p->ue_context.handover_info = NULL; @@ -9401,21 +9741,35 @@ void *rrc_enb_process_itti_msg(void *notUsed) { else failure_cause = "UE not in handover"; - LOG_W(RRC, "[eNB %d] cannot process (%s) X2 HANDOVER CANCEL for rnti %x, cause %s, ignoring\n", + LOG_W(RRC, "[eNB %ld] cannot process (%s) X2 HANDOVER CANCEL for rnti %x, cause %s, ignoring\n", instance, failure_cause, X2AP_HANDOVER_CANCEL(msg_p).rnti, cause); } break; } + case X2AP_ENDC_SETUP_REQ: + rrc_eNB_process_ENDC_x2_setup_request(instance, &X2AP_ENDC_SETUP_REQ(msg_p)); + break; + case X2AP_ENDC_SGNB_ADDITION_REQ_ACK: { rrc_eNB_process_AdditionResponseInformation(ENB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg_p)); break; } + case X2AP_ENDC_DC_PREP_TIMEOUT: { + rrc_eNB_process_ENDC_DC_prep_timeout(ENB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_DC_PREP_TIMEOUT(msg_p)); + break; + } + + case X2AP_ENDC_SGNB_RELEASE_REQUIRED: { + rrc_eNB_process_ENDC_sgNB_release_required(ENB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_SGNB_RELEASE_REQUIRED(msg_p)); + break; + } + /* Messages from eNB app */ case RRC_CONFIGURATION_REQ: - LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p, &RRC_CONFIGURATION_REQ(msg_p)); + LOG_I(RRC, "[eNB %ld] Received %s : %p\n", instance, msg_name_p, &RRC_CONFIGURATION_REQ(msg_p)); openair_rrc_eNB_configuration(ENB_INSTANCE_TO_MODULE_ID(instance), &RRC_CONFIGURATION_REQ(msg_p)); break; @@ -9423,7 +9777,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { case F1AP_SETUP_REQ: AssertFatal(NODE_IS_CU(RC.rrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST, need call by CU!\n"); - LOG_I(RRC,"[eNB %d] Received %s : %p\n", instance, msg_name_p, &F1AP_SETUP_REQ(msg_p)); + LOG_I(RRC,"[eNB %ld] Received %s : %p\n", instance, msg_name_p, &F1AP_SETUP_REQ(msg_p)); handle_f1_setup_req(&F1AP_SETUP_REQ(msg_p)); break; @@ -9464,8 +9818,8 @@ void *rrc_enb_process_itti_msg(void *notUsed) { break; case M2AP_MCE_CONFIGURATION_UPDATE: - rrc_eNB_process_M2AP_MCE_CONFIGURATION_UPDATE(&ctxt,&M2AP_MCE_CONFIGURATION_UPDATE(msg_p)); - break; + rrc_eNB_process_M2AP_MCE_CONFIGURATION_UPDATE(&ctxt,&M2AP_MCE_CONFIGURATION_UPDATE(msg_p)); + break; case RLC_SDU_INDICATION: process_rlc_sdu_indication(instance, @@ -9476,7 +9830,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) { break; default: - LOG_E(RRC, "[eNB %d] Received unexpected message %s\n", instance, msg_name_p); + LOG_E(RRC, "[eNB %ld] Received unexpected message %s\n", instance, msg_name_p); break; } @@ -9509,7 +9863,7 @@ rrc_enb_task( //if (go_nr) rrc_go_nr(); } } - } +} /*------------------------------------------------------------------------------*/ void @@ -9850,7 +10204,7 @@ rrc_rx_tx( //----------------------------------------------------------------------------- { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_SUBFRAME_PROCESS); + message_p = itti_alloc_new_message(TASK_RRC_ENB, 0, RRC_SUBFRAME_PROCESS); RRC_SUBFRAME_PROCESS(message_p).ctxt = *ctxt_pP; RRC_SUBFRAME_PROCESS(message_p).CC_id = CC_id; itti_send_msg_to_task(TASK_RRC_ENB, ctxt_pP->module_id, message_p); diff --git a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c index 1025d46f62..a6af6a4163 100644 --- a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c +++ b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c @@ -40,6 +40,7 @@ # include "common/ran_context.h" +#include extern RAN_CONTEXT_t RC; @@ -92,7 +93,6 @@ rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( } } - //------------------------------------------------------------------------------ boolean_t gtpv_data_req( @@ -113,64 +113,151 @@ gtpv_data_req( return FALSE; } LOG_D(GTPU,"gtpv_data_req ue rnti %x sdu_sizeP %d rb id %ld", ctxt_pP->rnti, sdu_sizeP, rb_idP); - { - MessageDef *message_p; - // Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling). - uint8_t *message_buffer; - - if(task_id == TASK_DATA_FORWARDING){ - - LOG_I(GTPU,"gtpv_data_req task_id = TASK_DATA_FORWARDING\n"); - - message_buffer = itti_malloc (TASK_GTPV1_U, TASK_DATA_FORWARDING, sdu_sizeP); - - memcpy (message_buffer, buffer_pP, sdu_sizeP); - - message_p = itti_alloc_new_message (TASK_GTPV1_U, GTPV1U_ENB_DATA_FORWARDING_IND); - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).frame = ctxt_pP->frame; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).enb_flag = ctxt_pP->enb_flag; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rb_id = rb_idP; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).muip = muiP; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).confirmp = confirmP; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_size = sdu_sizeP; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_p = message_buffer; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).mode = modeP; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).module_id = ctxt_pP->module_id; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rnti = ctxt_pP->rnti; - GTPV1U_ENB_DATA_FORWARDING_IND (message_p).eNB_index = ctxt_pP->eNB_index; - - itti_send_msg_to_task (TASK_DATA_FORWARDING, ctxt_pP->instance, message_p); - return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. - }else if(task_id == TASK_END_MARKER){ - - LOG_I(GTPU,"gtpv_data_req task_id = TASK_END_MARKER\n"); - - message_buffer = itti_malloc (TASK_GTPV1_U, TASK_END_MARKER, sdu_sizeP); - - memcpy (message_buffer, buffer_pP, sdu_sizeP); - - message_p = itti_alloc_new_message (TASK_GTPV1_U, GTPV1U_ENB_END_MARKER_IND); - GTPV1U_ENB_END_MARKER_IND (message_p).frame = ctxt_pP->frame; - GTPV1U_ENB_END_MARKER_IND (message_p).enb_flag = ctxt_pP->enb_flag; - GTPV1U_ENB_END_MARKER_IND (message_p).rb_id = rb_idP; - GTPV1U_ENB_END_MARKER_IND (message_p).muip = muiP; - GTPV1U_ENB_END_MARKER_IND (message_p).confirmp = confirmP; - GTPV1U_ENB_END_MARKER_IND (message_p).sdu_size = sdu_sizeP; - GTPV1U_ENB_END_MARKER_IND (message_p).sdu_p = message_buffer; - GTPV1U_ENB_END_MARKER_IND (message_p).mode = modeP; - GTPV1U_ENB_END_MARKER_IND (message_p).module_id = ctxt_pP->module_id; - GTPV1U_ENB_END_MARKER_IND (message_p).rnti = ctxt_pP->rnti; - GTPV1U_ENB_END_MARKER_IND (message_p).eNB_index = ctxt_pP->eNB_index; - - itti_send_msg_to_task (TASK_END_MARKER, ctxt_pP->instance, message_p); - return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. - } + MessageDef *message_p; + // Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling). + uint8_t *message_buffer; + + if(task_id == TASK_DATA_FORWARDING){ + + LOG_I(GTPU,"gtpv_data_req task_id = TASK_DATA_FORWARDING\n"); + + message_buffer = itti_malloc (TASK_GTPV1_U, TASK_DATA_FORWARDING, sdu_sizeP); + + memcpy (message_buffer, buffer_pP, sdu_sizeP); + + message_p = itti_alloc_new_message (TASK_GTPV1_U, 0, GTPV1U_ENB_DATA_FORWARDING_IND); + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).frame = ctxt_pP->frame; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).enb_flag = ctxt_pP->enb_flag; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rb_id = rb_idP; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).muip = muiP; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).confirmp = confirmP; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_size = sdu_sizeP; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_p = message_buffer; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).mode = modeP; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).module_id = ctxt_pP->module_id; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rnti = ctxt_pP->rnti; + GTPV1U_ENB_DATA_FORWARDING_IND (message_p).eNB_index = ctxt_pP->eNB_index; + + itti_send_msg_to_task (TASK_DATA_FORWARDING, ctxt_pP->instance, message_p); + return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. + } else if (task_id == TASK_END_MARKER){ + + LOG_I(GTPU,"gtpv_data_req task_id = TASK_END_MARKER\n"); + + message_buffer = itti_malloc (TASK_GTPV1_U, TASK_END_MARKER, sdu_sizeP); + + memcpy (message_buffer, buffer_pP, sdu_sizeP); + + message_p = itti_alloc_new_message (TASK_GTPV1_U, 0, GTPV1U_ENB_END_MARKER_IND); + GTPV1U_ENB_END_MARKER_IND (message_p).frame = ctxt_pP->frame; + GTPV1U_ENB_END_MARKER_IND (message_p).enb_flag = ctxt_pP->enb_flag; + GTPV1U_ENB_END_MARKER_IND (message_p).rb_id = rb_idP; + GTPV1U_ENB_END_MARKER_IND (message_p).muip = muiP; + GTPV1U_ENB_END_MARKER_IND (message_p).confirmp = confirmP; + GTPV1U_ENB_END_MARKER_IND (message_p).sdu_size = sdu_sizeP; + GTPV1U_ENB_END_MARKER_IND (message_p).sdu_p = message_buffer; + GTPV1U_ENB_END_MARKER_IND (message_p).mode = modeP; + GTPV1U_ENB_END_MARKER_IND (message_p).module_id = ctxt_pP->module_id; + GTPV1U_ENB_END_MARKER_IND (message_p).rnti = ctxt_pP->rnti; + GTPV1U_ENB_END_MARKER_IND (message_p).eNB_index = ctxt_pP->eNB_index; + + itti_send_msg_to_task (TASK_END_MARKER, ctxt_pP->instance, message_p); + return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. } - return TRUE; - + LOG_E(RRC, "Impossible state\n"); + return FALSE; } -//#endif +boolean_t gtpv_data_req_new ( + protocol_ctxt_t *ctxt, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id) { + int task; + + if (sdu_buffer_sizeP==0) + task=TASK_END_MARKER; + else + task=TASK_DATA_FORWARDING; + + struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ctxt->module_id], ctxt->rnti); + if(ue_context_p == NULL || ue_context_p->ue_context.handover_info == NULL || + ue_context_p->ue_context.StatusRrc != RRC_HO_EXECUTION) { + LOG_E(RRC,"incoming GTP-U for X2 in non HO context\n"); + return false; + } + + /* in the source enb, UE in RRC_HO_EXECUTION mode */ + // We have 2*2=4 cases (data or end marker) * (from slave, from EPC) + if (ue_context_p->ue_context.handover_info->state == HO_COMPLETE) { + LOG_I(GTPU, "source receive END MARKER\n"); + /* set handover state */ + //ue_context_p->ue_context.handover_info->state = HO_END_MARKER; + MessageDef *msg; + // Configure end marker + msg = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_ENB_END_MARKER_REQ); + GTPV1U_ENB_END_MARKER_REQ(msg).buffer = itti_malloc(TASK_GTPV1_U, TASK_GTPV1_U, GTPU_HEADER_OVERHEAD_MAX + sdu_buffer_sizeP); + memcpy(>PV1U_ENB_END_MARKER_REQ(msg).buffer[GTPU_HEADER_OVERHEAD_MAX], sdu_buffer_pP, sdu_buffer_sizeP); + GTPV1U_ENB_END_MARKER_REQ(msg).length = sdu_buffer_sizeP; + GTPV1U_ENB_END_MARKER_REQ(msg).rnti = ctxt->rnti; + GTPV1U_ENB_END_MARKER_REQ(msg).rab_id = rb_idP; + GTPV1U_ENB_END_MARKER_REQ(msg).offset = GTPU_HEADER_OVERHEAD_MAX; + LOG_I(GTPU, "Send End Marker to GTPV1-U at frame %d and subframe %d \n", ctxt->frame,ctxt->subframe); + itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(ctxt->module_id), msg); + return NW_GTPV1U_OK; + } + + /* target enb */ + // We have 2*2=4 cases (data or end marker) * (from source, from EPC) + if (ue_context_p->ue_context.StatusRrc == RRC_RECONFIGURED) { + // It should come from remote eNB + // case end marker by EPC is not possible ? + if (task==TASK_END_MARKER) { + LOG_I(GTPU, "target end receive END MARKER\n"); + // We close the HO, nothing to send to remote ? + ue_context_p->ue_context.handover_info->state = HO_END_MARKER; + gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req; + memset(&delete_tunnel_req, 0, sizeof(delete_tunnel_req)); + delete_tunnel_req.rnti = ctxt->rnti; + gtpv1u_delete_x2u_tunnel(ctxt->module_id, &delete_tunnel_req, GTPV1U_TARGET_ENB); + return true; + } else { + /* data packet */ + LOG_I(GTPU, "Received a message data forwarding length %d\n", sdu_buffer_sizeP); + // Is it from remote ENB + // We have to push it to the UE ? + if(ue_context_p->ue_context.handover_info->state != HO_COMPLETE) { + int result = pdcp_data_req( + ctxt, + srb_flagP, + rb_idP, + muiP, // mui + confirmP, // confirm + sdu_buffer_sizeP, + sdu_buffer_pP, + modeP, + sourceL2Id, + destinationL2Id + ); + ue_context_p->ue_context.handover_info->forwarding_state = FORWARDING_NO_EMPTY; + return result; + } else { /* It is from from epc message */ + /* in the source enb, UE in RRC_HO_EXECUTION mode */ + // ????? + return true; + } + } + } + LOG_E(RRC,"This function should return before the end\n"); + return false; +} + void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ( module_id_t enb_mod_idP, @@ -181,20 +268,16 @@ void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ( LOG_W(RRC, "[eNB] In %s: invalid UE\n", __func__); return; } + gtpv1u_enb_delete_tunnel_req_t tmp={0}; - MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL, 0, - "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", - ue_context_pP->ue_context.eNB_ue_s1ap_id); - - MessageDef *msg = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ); - memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg))); - GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).rnti = ue_context_pP->ue_context.rnti; - GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).num_erab = ue_context_pP->ue_context.nb_of_e_rabs; + tmp.rnti = ue_context_pP->ue_context.rnti; + tmp.from_gnb = 0; + tmp.num_erab = ue_context_pP->ue_context.nb_of_e_rabs; for (int e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_e_rabs; e_rab++) { const rb_id_t gtp_ebi = ue_context_pP->ue_context.enb_gtp_ebi[e_rab]; - GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).eps_bearer_id[e_rab] = gtp_ebi; + tmp.eps_bearer_id[e_rab] = gtp_ebi; } - itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(enb_mod_idP), msg); + gtpv1u_delete_s1u_tunnel(enb_mod_idP,&tmp); } diff --git a/openair2/RRC/LTE/rrc_eNB_M2AP.c b/openair2/RRC/LTE/rrc_eNB_M2AP.c index 98a72895a0..a9c65eae1a 100644 --- a/openair2/RRC/LTE/rrc_eNB_M2AP.c +++ b/openair2/RRC/LTE/rrc_eNB_M2AP.c @@ -1520,7 +1520,7 @@ rrc_eNB_process_M2AP_MBMS_SCHEDULING_INFORMATION( rrc_M2AP_openair_rrc_top_init_MBMS(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].MBMS_flag); }*/ MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SCHEDULING_INFORMATION_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, M2AP_MBMS_SCHEDULING_INFORMATION_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); pthread_mutex_unlock(&RC.rrc[ctxt_pP->module_id]->cell_info_mutex); @@ -1560,7 +1560,7 @@ rrc_eNB_process_M2AP_MBMS_SESSION_START_REQ( pthread_mutex_unlock(&RC.rrc[ctxt_pP->module_id]->cell_info_mutex); MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SESSION_START_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, M2AP_MBMS_SESSION_START_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; @@ -1628,7 +1628,7 @@ void rrc_eNB_send_M2AP_MBMS_SCHEDULING_INFORMATION_RESP( ) { MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SCHEDULING_INFORMATION_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, M2AP_MBMS_SCHEDULING_INFORMATION_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->instance), msg_p); } @@ -1638,7 +1638,7 @@ void rrc_eNB_send_M2AP_MBMS_SESSION_START_RESP( ) { MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SESSION_START_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, M2AP_MBMS_SESSION_START_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->instance), msg_p); } @@ -1648,7 +1648,7 @@ void rrc_eNB_send_M2AP_MBMS_SESSION_STOP_RESP( ) { MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SESSION_STOP_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, M2AP_MBMS_SESSION_STOP_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->instance), msg_p); } @@ -1658,6 +1658,6 @@ void rrc_eNB_send_M2AP_MBMS_SESSION_UPDATE_RESP( ) { MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, M2AP_MBMS_SESSION_UPDATE_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, M2AP_MBMS_SESSION_UPDATE_RESP); itti_send_msg_to_task (TASK_M2AP_ENB, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->instance), msg_p); } diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index 9f92be366b..1cb575d1dd 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -48,11 +48,12 @@ #include "pdcp_primitives.h" #include "UTIL/OSA/osa_defs.h" -#include "msc.h" +#include #include "LTE_UERadioAccessCapabilityInformation.h" #include "gtpv1u_eNB_task.h" +#include #include "RRC/LTE/rrc_eNB_GTPV1U.h" #include "TLVDecoder.h" @@ -241,7 +242,7 @@ rrc_eNB_S1AP_get_ue_ids( if (s1ap_eNB_instance_p != NULL) { ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, eNB_ue_s1ap_id); // get s1ap_eNB_ue_context } else { - LOG_E(S1AP, "[eNB instance %d] Couldn't find the eNB S1AP context\n", + LOG_E(S1AP, "[eNB instance %ld] Couldn't find the eNB S1AP context\n", instance); return NULL; } @@ -588,7 +589,7 @@ rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP( int e_rab; int e_rabs_done = 0; int e_rabs_failed = 0; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_INITIAL_CONTEXT_SETUP_RESP); S1AP_INITIAL_CONTEXT_SETUP_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; for (e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_e_rabs; e_rab++) { @@ -648,7 +649,7 @@ rrc_eNB_send_S1AP_UPLINK_NAS( MessageDef *msg_p; pdu_length = dedicatedInfoType->choice.dedicatedInfoNAS.size; pdu_buffer = dedicatedInfoType->choice.dedicatedInfoNAS.buf; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UPLINK_NAS); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_UPLINK_NAS); S1AP_UPLINK_NAS (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; S1AP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length; S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer; @@ -700,7 +701,7 @@ void rrc_eNB_send_S1AP_UE_CAPABILITIES_IND( if (ret.encoded == -1) abort(); MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UE_CAPABILITIES_IND); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_UE_CAPABILITIES_IND); S1AP_UE_CAPABILITIES_IND (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; S1AP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.length = (ret.encoded+7)/8; S1AP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.buffer = buf2; @@ -724,7 +725,7 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( MessageDef *message_p = NULL; rrc_ue_s1ap_ids_t *rrc_ue_s1ap_ids_p = NULL; hashtable_rc_t h_rc; - message_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_NAS_FIRST_REQ); + message_p = itti_alloc_new_message(TASK_RRC_ENB, 0, S1AP_NAS_FIRST_REQ); memset(&message_p->ittiMsg.s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t)); ue_context_pP->ue_context.ue_initial_id = get_next_ue_initial_id(ctxt_pP->module_id); S1AP_NAS_FIRST_REQ(message_p).ue_initial_id = ue_context_pP->ue_context.ue_initial_id; @@ -782,21 +783,37 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei; if (r_mme->plmn_Identity != NULL) { - if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) { - /* Use first indicated PLMN MCC if it is defined */ - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[selected_plmn_identity]; + if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count == 3)) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = (*r_mme->plmn_Identity->mcc->list.array[0] & 0xf) * 100 + + (*r_mme->plmn_Identity->mcc->list.array[1] & 0xf) * 10 + + (*r_mme->plmn_Identity->mcc->list.array[2] & 0xf); LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n", ctxt_pP->module_id, S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc, ue_context_pP->ue_context.rnti); } - - if (r_mme->plmn_Identity->mnc.list.count > 0) { - /* Use first indicated PLMN MNC if it is defined */ - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[selected_plmn_identity]; - LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n", + if(r_mme->plmn_Identity->mnc.list.count == 3) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 100 + + (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf) * 10 + + (*r_mme->plmn_Identity->mnc.list.array[2] & 0xf); + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 3; + LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n", ctxt_pP->module_id, S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len, + ue_context_pP->ue_context.rnti); + } + else if(r_mme->plmn_Identity->mnc.list.count == 2) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 10 + + (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf); + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 2; + LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n", + ctxt_pP->module_id, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len, ue_context_pP->ue_context.rnti); } } else { // end if plmn_Identity != NULL @@ -853,7 +870,7 @@ rrc_eNB_process_S1AP_DOWNLINK_NAS( ue_initial_id = S1AP_DOWNLINK_NAS (msg_p).ue_initial_id; eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id; ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id); - LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d\n", + LOG_I(RRC, "[eNB %ld] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d\n", instance, msg_name, ue_initial_id, @@ -871,8 +888,8 @@ rrc_eNB_process_S1AP_DOWNLINK_NAS( eNB_ue_s1ap_id); /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ MessageDef *msg_fail_p; - LOG_W(RRC, "[eNB %d] In S1AP_DOWNLINK_NAS: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); - msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_NAS_NON_DELIVERY_IND); + LOG_W(RRC, "[eNB %ld] In S1AP_DOWNLINK_NAS: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_NAS_NON_DELIVERY_IND); S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.length = S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length; S1AP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.buffer = S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer; @@ -944,14 +961,14 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char ue_initial_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id; eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id; ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id); - LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", + LOG_I(RRC, "[eNB %ld] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_e_rabs); if (ue_context_p == NULL) { /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ MessageDef *msg_fail_p = NULL; - LOG_W(RRC, "[eNB %d] In S1AP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); - msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_INITIAL_CONTEXT_SETUP_FAIL); + LOG_W(RRC, "[eNB %ld] In S1AP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_INITIAL_CONTEXT_SETUP_FAIL); S1AP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; // TODO add failure cause when defined! itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p); @@ -1045,8 +1062,17 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char } } + ue_context_p->ue_context.nr_security.ciphering_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.encryption_algorithms; + ue_context_p->ue_context.nr_security.integrity_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.integrity_algorithms; + /* let's initialize sk_counter to 0 */ + ue_context_p->ue_context.nr_security.sk_counter = 0; + /* let's compute kgNB */ + derive_skgNB(ue_context_p->ue_context.kenb, + ue_context_p->ue_context.nr_security.sk_counter, + ue_context_p->ue_context.nr_security.kgNB); + // in case, send the S1SP initial context response if it is not sent with the attach complete message - if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) { + if (ue_context_p->ue_context.StatusRrc == RRC_RECONFIGURED) { LOG_I(RRC, "Sending rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", ue_context_p->ue_context.reestablishment_cause); //if(ue_context_p->ue_context.reestablishment_cause == ReestablishmentCause_spare1){} rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(&ctxt,ue_context_p); @@ -1057,7 +1083,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char (RC.rrc[ctxt.module_id]->node_type == ngran_ng_eNB_CU) || (RC.rrc[ctxt.module_id]->node_type == ngran_gNB_CU) ){ - message_p = itti_alloc_new_message (TASK_RRC_ENB, F1AP_UE_CONTEXT_SETUP_REQ); + message_p = itti_alloc_new_message (TASK_RRC_ENB, 0, F1AP_UE_CONTEXT_SETUP_REQ); F1AP_UE_CONTEXT_SETUP_REQ (message_p).rrc_container = ue_p->Srb0.Tx_buffer.Payload; F1AP_UE_CONTEXT_SETUP_REQ (message_p).rrc_container_length = ue_p->Srb0.Tx_buffer.payload_size; @@ -1088,8 +1114,8 @@ int rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(MessageDef *msg_p, const char if (ue_context_p == NULL) { /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ MessageDef *msg_fail_p; - LOG_W(RRC, "[eNB %d] In S1AP_UE_CTXT_MODIFICATION_REQ: unknown UE from eNB_ue_s1ap_id (%d)\n", instance, eNB_ue_s1ap_id); - msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_UE_CTXT_MODIFICATION_FAIL); + LOG_W(RRC, "[eNB %ld] In S1AP_UE_CTXT_MODIFICATION_REQ: unknown UE from eNB_ue_s1ap_id (%d)\n", instance, eNB_ue_s1ap_id); + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_UE_CTXT_MODIFICATION_FAIL); S1AP_UE_CTXT_MODIFICATION_FAIL (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; // TODO add failure cause when defined! itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p); @@ -1126,7 +1152,7 @@ int rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(MessageDef *msg_p, const char /* Send the response */ { MessageDef *msg_resp_p; - msg_resp_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CTXT_MODIFICATION_RESP); + msg_resp_p = itti_alloc_new_message(TASK_RRC_ENB, 0, S1AP_UE_CTXT_MODIFICATION_RESP); S1AP_UE_CTXT_MODIFICATION_RESP(msg_resp_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; itti_send_msg_to_task(TASK_S1AP, instance, msg_resp_p); } @@ -1144,10 +1170,10 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char * if (ue_context_p == NULL) { /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ MessageDef *msg_fail_p; - LOG_W(RRC, "[eNB %d] In S1AP_UE_CONTEXT_RELEASE_REQ: unknown UE from eNB_ue_s1ap_id (%d)\n", + LOG_W(RRC, "[eNB %ld] In S1AP_UE_CONTEXT_RELEASE_REQ: unknown UE from eNB_ue_s1ap_id (%d)\n", instance, eNB_ue_s1ap_id); - msg_fail_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_RESP); /* TODO change message ID. */ + msg_fail_p = itti_alloc_new_message(TASK_RRC_ENB, 0, S1AP_UE_CONTEXT_RELEASE_RESP); /* TODO change message ID. */ S1AP_UE_CONTEXT_RELEASE_RESP(msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; // TODO add failure cause when defined! itti_send_msg_to_task(TASK_S1AP, instance, msg_fail_p); @@ -1157,7 +1183,7 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char * /* Send the response */ { MessageDef *msg_resp_p; - msg_resp_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_RESP); + msg_resp_p = itti_alloc_new_message(TASK_RRC_ENB, 0, S1AP_UE_CONTEXT_RELEASE_RESP); S1AP_UE_CONTEXT_RELEASE_RESP(msg_resp_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; itti_send_msg_to_task(TASK_S1AP, instance, msg_resp_p); } @@ -1187,7 +1213,7 @@ rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ( "0 S1AP_UE_CONTEXT_RELEASE_REQ eNB_ue_s1ap_id 0x%06"PRIX32" ", ue_context_pP->ue_context.eNB_ue_s1ap_id); MessageDef *msg_context_release_req_p = NULL; - msg_context_release_req_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_REQ); + msg_context_release_req_p = itti_alloc_new_message(TASK_RRC_ENB, 0, S1AP_UE_CONTEXT_RELEASE_REQ); S1AP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; S1AP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).cause = causeP; S1AP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).cause_value = cause_valueP; @@ -1202,7 +1228,7 @@ void rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_CPLT( MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_S1AP_ENB, NULL, 0, "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ", eNB_ue_s1ap_id); - MessageDef *msg = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE); + MessageDef *msg = itti_alloc_new_message(TASK_RRC_ENB, 0, S1AP_UE_CONTEXT_RELEASE_COMPLETE); S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg).eNB_ue_s1ap_id = eNB_ue_s1ap_id; itti_send_msg_to_task(TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_mod_idP), msg); } @@ -1229,7 +1255,7 @@ rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND( if (ue_context_p == NULL) { /* Can not associate this message to an UE index */ MessageDef *msg_complete_p = NULL; - LOG_W(RRC, "[eNB %d] In S1AP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from eNB_ue_s1ap_id (%d)\n", + LOG_W(RRC, "[eNB %ld] In S1AP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from eNB_ue_s1ap_id (%d)\n", instance, eNB_ue_s1ap_id); MSC_LOG_EVENT(MSC_RRC_ENB, "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" context not found", @@ -1240,7 +1266,7 @@ rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND( 0, "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ", eNB_ue_s1ap_id); - msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE); + msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, 0, S1AP_UE_CONTEXT_RELEASE_COMPLETE); S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; itti_send_msg_to_task(TASK_S1AP, instance, msg_complete_p); rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(RC.rrc[instance], UE_INITIAL_ID_INVALID, eNB_ue_s1ap_id); @@ -1271,14 +1297,14 @@ int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name ue_initial_id = S1AP_E_RAB_SETUP_REQ (msg_p).ue_initial_id; eNB_ue_s1ap_id = S1AP_E_RAB_SETUP_REQ (msg_p).eNB_ue_s1ap_id; ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id); - LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", + LOG_I(RRC, "[eNB %ld] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_E_RAB_SETUP_REQ (msg_p).nb_e_rabs_tosetup); if (ue_context_p == NULL) { /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ MessageDef *msg_fail_p = NULL; - LOG_W(RRC, "[eNB %d] In S1AP_E_RAB_SETUP_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); - msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_SETUP_REQUEST_FAIL); + LOG_W(RRC, "[eNB %ld] In S1AP_E_RAB_SETUP_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_SETUP_REQUEST_FAIL); S1AP_E_RAB_SETUP_REQ (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; // TODO add failure cause when defined! itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p); @@ -1370,7 +1396,7 @@ int rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(const protocol_ctxt_t *const ctxt_pP, int e_rab; int e_rabs_done = 0; int e_rabs_failed = 0; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_SETUP_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_SETUP_RESP); S1AP_E_RAB_SETUP_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; for (e_rab = 0; e_rab < ue_context_pP->ue_context.setup_e_rabs ; e_rab++) { @@ -1446,15 +1472,15 @@ int rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_nam ue_initial_id = S1AP_E_RAB_MODIFY_REQ (msg_p).ue_initial_id; eNB_ue_s1ap_id = S1AP_E_RAB_MODIFY_REQ (msg_p).eNB_ue_s1ap_id; ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id); - LOG_D(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", + LOG_D(RRC, "[eNB %ld] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_E_RAB_MODIFY_REQ (msg_p).nb_e_rabs_tomodify); if (ue_context_p == NULL) { /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ - LOG_W(RRC, "[eNB %d] In S1AP_E_RAB_MODIFY_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); + LOG_W(RRC, "[eNB %ld] In S1AP_E_RAB_MODIFY_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); int nb_of_e_rabs_failed = 0; MessageDef *msg_fail_p = NULL; - msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP); + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_MODIFY_RESP); S1AP_E_RAB_MODIFY_RESP (msg_fail_p).eNB_ue_s1ap_id = S1AP_E_RAB_MODIFY_REQ (msg_p).eNB_ue_s1ap_id; S1AP_E_RAB_MODIFY_RESP (msg_fail_p).nb_of_e_rabs = 0; @@ -1567,7 +1593,7 @@ int rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_nam { int nb_of_e_rabs_failed = 0; MessageDef *msg_fail_p = NULL; - msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP); + msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_MODIFY_RESP); S1AP_E_RAB_MODIFY_RESP (msg_fail_p).eNB_ue_s1ap_id = S1AP_E_RAB_MODIFY_REQ (msg_p).eNB_ue_s1ap_id; // S1AP_E_RAB_MODIFY_RESP (msg_fail_p).e_rabs[S1AP_MAX_E_RAB]; S1AP_E_RAB_MODIFY_RESP (msg_fail_p).nb_of_e_rabs = 0; @@ -1597,7 +1623,7 @@ int rrc_eNB_send_S1AP_E_RAB_MODIFY_RESP(const protocol_ctxt_t *const ctxt_pP, int e_rab; int e_rabs_done = 0; int e_rabs_failed = 0; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_MODIFY_RESP); S1AP_E_RAB_MODIFY_RESP (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; for (e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_modify_e_rabs; e_rab++) { @@ -1748,9 +1774,10 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_release(&ctxt, ue_context_p, xid, S1AP_E_RAB_RELEASE_COMMAND (msg_p).nas_pdu.length, S1AP_E_RAB_RELEASE_COMMAND (msg_p).nas_pdu.buffer); } else { //gtp tunnel delete - msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ); + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, 0, GTPV1U_ENB_DELETE_TUNNEL_REQ); memset(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).from_gnb = 0; for(i = 0; i < NB_RB_MAX; i++) { if(xid == ue_context_p->ue_context.e_rab[i].xid) { @@ -1761,7 +1788,7 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms } } - itti_send_msg_to_task(TASK_GTPV1_U, instance, msg_delete_tunnels_p); + itti_send_msg_to_task(TASK_VARIABLE, instance, msg_delete_tunnels_p); //S1AP_E_RAB_RELEASE_RESPONSE rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(&ctxt, ue_context_p, xid); } @@ -1778,7 +1805,7 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms int rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, uint8_t xid) { int e_rabs_released = 0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_RELEASE_RESPONSE); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_RELEASE_RESPONSE); S1AP_E_RAB_RELEASE_RESPONSE (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; for (int i = 0; i < NB_RB_MAX; i++) { @@ -1821,7 +1848,7 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance uint32_t T; /* DRX cycle */ for (uint16_t tai_size = 0; tai_size < S1AP_PAGING_IND(msg_p).tai_size; tai_size++) { - LOG_D(RRC,"[eNB %d] In S1AP_PAGING_IND: MCC %d, MNC %d, TAC %d\n", instance, S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc, + LOG_D(RRC,"[eNB %ld] In S1AP_PAGING_IND: MCC %d, MNC %d, TAC %d\n", instance, S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc, S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mnc, S1AP_PAGING_IND(msg_p).tac[tai_size]); for (uint8_t j = 0; j < RC.rrc[instance]->configuration.num_plmn; j++) { @@ -1883,7 +1910,7 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance default: /* pcch_nB error */ - LOG_E(RRC, "[eNB %d] In S1AP_PAGING_IND: pcch_nB error (pcch_nB %d) \n", + LOG_E(RRC, "[eNB %ld] In S1AP_PAGING_IND: pcch_nB error (pcch_nB %d) \n", instance, pcch_nB); return (-1); } @@ -1919,12 +1946,12 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance if (UE_PF_PO[CC_id][i].enable_flag == TRUE) { //paging exist UE log - LOG_D(RRC,"[eNB %d] CC_id %d In S1AP_PAGING_IND: Update exist UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO); + LOG_D(RRC,"[eNB %ld] CC_id %d In S1AP_PAGING_IND: Update exist UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO); } else { /* set enable_flag */ UE_PF_PO[CC_id][i].enable_flag = TRUE; //paging new UE log - LOG_D(RRC,"[eNB %d] CC_id %d In S1AP_PAGING_IND: Insert a new UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO); + LOG_D(RRC,"[eNB %ld] CC_id %d In S1AP_PAGING_IND: Insert a new UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO); } break; @@ -1937,7 +1964,7 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance uint8_t *message_buffer; /* Transfer data to PDCP */ MessageDef *message_p; - message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_PCCH_DATA_REQ); + message_p = itti_alloc_new_message (TASK_RRC_ENB, 0, RRC_PCCH_DATA_REQ); /* Create message for PDCP (DLInformationTransfer_t) */ length = do_Paging (instance, buffer, @@ -1958,7 +1985,7 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance RRC_PCCH_DATA_REQ (message_p).rnti = P_RNTI; RRC_PCCH_DATA_REQ (message_p).ue_index = i; RRC_PCCH_DATA_REQ (message_p).CC_id = CC_id; - LOG_D(RRC, "[eNB %d] CC_id %d In S1AP_PAGING_IND: send encdoed buffer to PDCP buffer_size %d\n", instance, CC_id, length); + LOG_D(RRC, "[eNB %ld] CC_id %d In S1AP_PAGING_IND: send encdoed buffer to PDCP buffer_size %d\n", instance, CC_id, length); itti_send_msg_to_task (TASK_PDCP_ENB, instance, message_p); } } @@ -1980,7 +2007,7 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP, gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; uint8_t inde_list[ue_context_pP->ue_context.nb_of_e_rabs]; memset(inde_list, 0, ue_context_pP->ue_context.nb_of_e_rabs*sizeof(uint8_t)); - msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_PATH_SWITCH_REQ); ue_context_pP->ue_context.ue_initial_id = get_next_ue_initial_id (ctxt_pP->module_id); S1AP_PATH_SWITCH_REQ (msg_p).ue_initial_id = ue_context_pP->ue_context.ue_initial_id; rrc_ue_s1ap_ids_p = malloc(sizeof(*rrc_ue_s1ap_ids_p)); @@ -2083,7 +2110,7 @@ int rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ(instance_t instance, rrc_eNB_ue_contex } else { /* Save e RAB information for later */ { - LOG_I(RRC, "[eNB %d] rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ: rnti %u nb_of_e_rabs %d\n", + LOG_I(RRC, "[eNB %ld] rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ: rnti %u nb_of_e_rabs %d\n", instance, ue_context_target_p->ue_context.rnti, ue_context_target_p->ue_context.nb_of_e_rabs); int i; memset(&create_tunnel_req, 0, sizeof(create_tunnel_req)); @@ -2143,14 +2170,14 @@ int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, ue_initial_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_initial_id; eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id; ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id); - LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", + LOG_I(RRC, "[eNB %ld] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n", instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_E_RAB_SETUP_REQ (msg_p).nb_e_rabs_tosetup); if (ue_context_p == NULL) { /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */ //MessageDef *msg_fail_p = NULL; - LOG_W(RRC, "[eNB %d] In S1AP_PATH_SWITCH_REQ_ACK: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); - //msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ_ACK_FAIL); + LOG_W(RRC, "[eNB %ld] In S1AP_PATH_SWITCH_REQ_ACK: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id); + //msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_PATH_SWITCH_REQ_ACK_FAIL); //S1AP_PATH_SWITCH_REQ_ACK (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id; // TODO add failure cause when defined! //itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p); @@ -2241,7 +2268,7 @@ int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, int rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP) { MessageDef *msg_p = NULL; - msg_p = itti_alloc_new_message (TASK_RRC_ENB, X2AP_UE_CONTEXT_RELEASE); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, X2AP_UE_CONTEXT_RELEASE); X2AP_UE_CONTEXT_RELEASE (msg_p).rnti = ue_context_pP->ue_context.rnti; X2AP_UE_CONTEXT_RELEASE (msg_p).source_assoc_id = ue_context_pP->ue_context.handover_info->assoc_id; itti_send_msg_to_task (TASK_X2AP, ctxt_pP->instance, msg_p); @@ -2294,7 +2321,7 @@ int rrc_eNB_send_E_RAB_Modification_Indication(const protocol_ctxt_t *const ctxt uint8_t inde_list[ue_context_pP->ue_context.nb_of_e_rabs]; memset(inde_list, 0, ue_context_pP->ue_context.nb_of_e_rabs*sizeof(uint8_t)); - msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFICATION_IND); + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_MODIFICATION_IND); S1AP_E_RAB_MODIFICATION_IND (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id; diff --git a/openair2/RRC/LTE/rrc_eNB_UE_context.c b/openair2/RRC/LTE/rrc_eNB_UE_context.c index 197aedae51..2cc89adf15 100644 --- a/openair2/RRC/LTE/rrc_eNB_UE_context.c +++ b/openair2/RRC/LTE/rrc_eNB_UE_context.c @@ -173,6 +173,23 @@ rrc_eNB_get_ue_context( } +//------------------------------------------------------------------------------ +struct rrc_eNB_ue_context_s * +rrc_eNB_find_ue_context_from_gnb_rnti( + eNB_RRC_INST *rrc_instance_pP, + int gnb_rnti) +//------------------------------------------------------------------------------ +{ + struct rrc_eNB_ue_context_s *ue_context_p = NULL; + RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(rrc_instance_pP->rrc_ue_head)) { + if (ue_context_p->ue_context.gnb_rnti == gnb_rnti) { + return ue_context_p; + } + } + return NULL; +} + + //------------------------------------------------------------------------------ void rrc_eNB_remove_ue_context( const protocol_ctxt_t *const ctxt_pP, diff --git a/openair2/RRC/LTE/rrc_eNB_UE_context.h b/openair2/RRC/LTE/rrc_eNB_UE_context.h index e22f517d50..c6420ca936 100644 --- a/openair2/RRC/LTE/rrc_eNB_UE_context.h +++ b/openair2/RRC/LTE/rrc_eNB_UE_context.h @@ -73,6 +73,11 @@ rrc_eNB_get_ue_context( rnti_t rntiP ); +struct rrc_eNB_ue_context_s * +rrc_eNB_find_ue_context_from_gnb_rnti( + eNB_RRC_INST *rrc_instance_pP, + int gnb_rnti); + void rrc_eNB_remove_ue_context( const protocol_ctxt_t* const ctxt_pP, eNB_RRC_INST* rrc_instance_pP, diff --git a/openair2/RRC/LTE/rrc_eNB_ral.c b/openair2/RRC/LTE/rrc_eNB_ral.c index 4820e84dc0..9e1486f6d8 100644 --- a/openair2/RRC/LTE/rrc_eNB_ral.c +++ b/openair2/RRC/LTE/rrc_eNB_ral.c @@ -126,7 +126,7 @@ int rrc_enb_ral_handle_configure_threshold_request(unsigned int mod_idP, Message message_p = itti_alloc_new_message (TASK_RRC_ENB, PHY_MEAS_THRESHOLD_REQ); PHY_MEAS_THRESHOLD_REQ(message_p).transaction_id = transaction_id; memcpy (&PHY_MEAS_THRESHOLD_REQ(message_p).cfg_param, (void *) link_cfg_param_p, sizeof(ral_link_cfg_param_t)); - itti_send_msg_to_task (TASK_PHY_ENB, ITTI_MSG_INSTANCE(msg_pP), message_p); + itti_send_msg_to_task (TASK_PHY_ENB, ITTI_MSG_DESTINATION_INSTANCE(msg_pP), message_p); break; default: @@ -147,7 +147,7 @@ int rrc_enb_ral_handle_configure_threshold_request(unsigned int mod_idP, Message message_p = itti_alloc_new_message (TASK_RRC_ENB, PHY_MEAS_THRESHOLD_REQ); PHY_MEAS_THRESHOLD_REQ(message_p).transaction_id = transaction_id; memcpy (&PHY_MEAS_THRESHOLD_REQ(message_p).cfg_param, (void *) link_cfg_param_p, sizeof(ral_link_cfg_param_t)); - itti_send_msg_to_task (TASK_MAC_ENB, ITTI_MSG_INSTANCE(msg_pP), message_p); + itti_send_msg_to_task (TASK_MAC_ENB, ITTI_MSG_DESTINATION_INSTANCE(msg_pP), message_p); break; default: @@ -166,7 +166,7 @@ int rrc_enb_ral_handle_configure_threshold_request(unsigned int mod_idP, Message message_p = itti_alloc_new_message (TASK_RRC_ENB, PHY_MEAS_THRESHOLD_REQ); PHY_MEAS_THRESHOLD_REQ(message_p).transaction_id = transaction_id; memcpy (&PHY_MEAS_THRESHOLD_REQ(message_p).cfg_param, (void *) link_cfg_param_p, sizeof(ral_link_cfg_param_t)); - itti_send_msg_to_task (TASK_PHY_ENB, ITTI_MSG_INSTANCE(msg_pP), message_p); + itti_send_msg_to_task (TASK_PHY_ENB, ITTI_MSG_DESTINATION_INSTANCE(msg_pP), message_p); break; case RAL_LINK_PARAM_LTE_AVAILABLE_BW: @@ -176,7 +176,7 @@ int rrc_enb_ral_handle_configure_threshold_request(unsigned int mod_idP, Message message_p = itti_alloc_new_message (TASK_RRC_ENB, PHY_MEAS_THRESHOLD_REQ); PHY_MEAS_THRESHOLD_REQ(message_p).transaction_id = transaction_id; memcpy (&PHY_MEAS_THRESHOLD_REQ(message_p).cfg_param, (void *) link_cfg_param_p, sizeof(ral_link_cfg_param_t)); - itti_send_msg_to_task (TASK_MAC_ENB, ITTI_MSG_INSTANCE(msg_pP), message_p); + itti_send_msg_to_task (TASK_MAC_ENB, ITTI_MSG_DESTINATION_INSTANCE(msg_pP), message_p); break; case RAL_LINK_PARAM_LTE_MOBILE_NODE_CAPABILITIES: diff --git a/openair2/RRC/LTE/rrc_extern.h b/openair2/RRC/LTE/rrc_extern.h index 6564f38ade..7f7fd6579e 100644 --- a/openair2/RRC/LTE/rrc_extern.h +++ b/openair2/RRC/LTE/rrc_extern.h @@ -47,7 +47,6 @@ extern LTE_LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue; extern unsigned char NB_INST; extern unsigned char NB_eNB_INST; extern uint16_t NB_UE_INST; -extern unsigned short NODE_ID[1]; extern void* bigphys_malloc(int); diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 8f6baabcbf..c50ddf3189 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -360,6 +360,8 @@ void rrc_eNB_process_x2_setup_response(int mod_id, x2ap_setup_resp_t *m); void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m); +void rrc_eNB_process_ENDC_x2_setup_request(int mod_id, x2ap_ENDC_setup_req_t *m); + /**\brief Generate/decode the handover RRCConnectionReconfiguration at eNB \param module_idP Instance ID for eNB/CH \param frame Frame index diff --git a/openair2/RRC/LTE/rrc_rrm_interface.c b/openair2/RRC/LTE/rrc_rrm_interface.c deleted file mode 100644 index fe15dae46d..0000000000 --- a/openair2/RRC/LTE/rrc_rrm_interface.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! -******************************************************************************* - -\file rrm_sock.c - -\brief RRM (Radio Ressource Manager ) Socket: communication withe other medium: - - RRC , - - CMM , - - PUSU - -\author BURLOT Pascal - -\date 10/07/08 - - -\par Historique: - P.BURLOT 2009-01-20 - + send a message via fifo: - - sending header - - and data if any - -******************************************************************************* -*/ - -#ifndef RRC_RRM_FIFOS_XFACE - #include - #include - #include - #include - #include - - #include - #include - -#else - - #include - -#endif - -#include "rrc_rrm_interface.h" -#include "defs.h" -//! \brief Taille maximale de la charge utile -#define SIZE_MAX_PAYLOAD 2048 -//! \brief PID de l'espace utilisateur (Netlink mode) -//#define PID_USERSPACE 0xAA - - - - - -#ifndef RRC_RRM_FIFOS_XFACE - -/*! -******************************************************************************* -\brief This function opens a unix socket for the rrm communication -\return The return value is a socket handle -*/ -int open_socket( - sock_rrm_t *s, ///< socket descriptor - char *path_local, ///< local socket path if unix socket - char *path_dest, ///< host Socket path if unix socket - int rrm_inst ///< instance of the rrm entity -) { - /* Unix socket */ - int socket_fd ; - int len ; - - if ((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) { - perror("unix socket"); - return -1 ; - } - - memset(&(s->un_local_addr), 0, sizeof(struct sockaddr_un)); - s->un_local_addr.sun_family = AF_UNIX; - sprintf(s->un_local_addr.sun_path,"%s%d", path_local, rrm_inst ); - unlink(s->un_local_addr.sun_path); - msg("local %s\n",s->un_local_addr.sun_path); - len = strlen((s->un_local_addr).sun_path) + sizeof((s->un_local_addr).sun_family); - - if (bind(socket_fd, (struct sockaddr *)&(s->un_local_addr), len) == -1) { - perror("bind"); - return -1 ; - } - - memset(&(s->un_dest_addr), 0, sizeof(struct sockaddr_un)); - s->un_dest_addr.sun_family = AF_UNIX; - sprintf(s->un_dest_addr.sun_path,"%s%d", path_dest, rrm_inst ); - msg("Dest %s\n",s->un_dest_addr.sun_path); - s->s = socket_fd ; - return socket_fd ; -} -/*! -******************************************************************************* -\brief This function closes a RRM socket -\return none -*/ -void close_socket( - sock_rrm_t *sock ///< the socket handle -) { - shutdown(sock->s, SHUT_RDWR); - close(sock->s); -} - -/*! -******************************************************************************* -\brief This function send a buffer message to the unix socket -\return if OK then "0" is returned else "-1" -*/ -char BUFF[2048]; -int send_msg_sock( - sock_rrm_t *s, ///< socket descriptor - msg_t *smsg ///< the message to send -) { - /* Unix socket */ - int ret = 0 ; - // char *buf = NULL; - struct msghdr msghd ; - struct iovec iov; - int taille = sizeof(msg_head_t) ; - - if ( smsg == NULL ) { - return -1 ; - } - - if ( smsg->data != NULL ) { - taille += smsg->head.size ; - } - - //buf = RRM_MALLOC(char, taille); - //if (buf ==NULL) - //return -1 ; - memcpy( BUFF, &(smsg->head), sizeof(msg_head_t) ) ; - memcpy( BUFF+sizeof(msg_head_t), smsg->data, smsg->head.size ) ; - iov.iov_base = (void *)BUFF; - iov.iov_len = taille ; - msghd.msg_name = (void *)&(s->un_dest_addr); - msghd.msg_namelen = sizeof(s->un_dest_addr); - msghd.msg_iov = &iov; - msghd.msg_iovlen = 1; - msghd.msg_control = NULL ; - msghd.msg_controllen = 0 ; - - if ( sendmsg(s->s, &msghd, 0) < 0 ) { - ret = -1; - msg("socket %d, dest %s\n",s->s,s->un_dest_addr.sun_path); - perror("sendmsg:unix socket"); - } - - //RRM_FREE(buf) ; - //RRM_FREE(msg->data) ; - //RRM_FREE(msg) ; - return ret ; -} - -/*! -******************************************************************************* -\brief This function read a buffer from a unix socket -\return the function returns a message pointer. If the pointeur is NULL, a error - is happened. -*/ -char *recv_msg( - sock_rrm_t *s ///< socket descriptor -) { - /* Unix socket */ - char *buf = NULL; - char *smsg = NULL; - struct msghdr msghd ; - struct iovec iov; - int size_msg ; - msg_head_t *head ; - int ret ; - int taille = SIZE_MAX_PAYLOAD ; - buf = RRM_CALLOC( char,taille); - - if ( buf == NULL ) { - return NULL ; - } - - iov.iov_base = (void *)buf; - iov.iov_len = taille ; - msghd.msg_name = (void *)&(s->un_dest_addr); - msghd.msg_namelen = sizeof(s->un_dest_addr); - msghd.msg_iov = &iov; - msghd.msg_iovlen = 1; - msghd.msg_control = NULL ; - msghd.msg_controllen= 0 ; - ret = recvmsg(s->s, &msghd, 0 ) ; - - if ( ret <= 0 ) { - // non-blocking socket - // perror("PB recvmsg_un"); - RRM_FREE(buf); - return NULL ; - } - - if (msghd.msg_flags != 0 ) { - fprintf(stderr,"error recvmsg_un: 0x%02x\n", msghd.msg_flags) ; - RRM_FREE(buf); - return NULL ; - } - - head = (msg_head_t *) buf ; - size_msg = sizeof(msg_head_t) + head->size ; - smsg = RRM_CALLOC(char, size_msg ) ; - - if ( smsg != NULL ) { - memcpy( smsg, buf, size_msg ) ; - } - - RRM_FREE( buf ) ; - return smsg ; -} - -#else //XFACE - -int send_msg_fifo(int *s, msg_t *fmsg) { - int ret = 0, ret1; - int taille = sizeof(msg_head_t) ; - msg("write on fifos %d, msg %p\n",*s,fmsg); - - if ( fmsg == NULL ) { - return -1 ; - } - - // envoi le header - ret1 = rtf_put (*s,(char *) &(fmsg->head), taille); - - if(ret1 <0) { - msg("rtf_put H ERR %d\n",ret1); - rtf_reset(*s); - return ret1; - } - - ret=ret1; - - // envoi les datas si elles sont definis - if ( fmsg->data != NULL ) { - ret1 += rtf_put (*s,(char *) fmsg->data, fmsg->head.size); - - if(ret1 <0) { - msg("rtf_put D ERR %d\n",ret1); - rtf_reset(*s); - return ret1; - } - } - - ret+=ret1; - return ret; -} - -#endif //XFACE - -int send_msg(void *s, msg_t *smsg) { - send_msg_sock((sock_rrm_t *)s, smsg); -} diff --git a/openair2/RRC/LTE/rrm_2_rrc_msg.c b/openair2/RRC/LTE/rrm_2_rrc_msg.c deleted file mode 100644 index 84801a16be..0000000000 --- a/openair2/RRC/LTE/rrm_2_rrc_msg.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! -******************************************************************************* - -\file emul_interface.c - -\brief RRM interface emulation, it sends message to the RRM interface - - RRC -> RRM - - CMM -> RRM - -\author BURLOT Pascal - -\date 10/07/08 - - -\par Historique: - $Author$ $Date$ $Revision$ - $Id$ - $Log$ - -******************************************************************************* -*/ - -#include "defs.h" -#include "extern.h" - - - - -//#include "mac_lchan_interface.h" -//#include "openair_rrc_utils.h" -//#include "openair_rrc_main.h" -#ifdef PHY_EMUL - #include "SIMULATION/simulation_defs.h" - extern EMULATION_VARS *Emul_vars; - extern CH_MAC_INST *CH_mac_inst; - extern UE_MAC_INST *UE_mac_inst; -#endif - - - -/******************************************************************************/ -void fn_rrc (void) { - /******************************************************************************/ - msg_head_t *Header ; - char *Data; - L2_ID Mac_id; - - while(1) { - Header = (msg_head_t *) recv_msg(&S_rrc) ; - - if(Header==NULL) { - break; - } - - Data_to_read=Header->size; - - if (Data_to_read > 0 ) { - Data = (char *) (Header +1) ; - } - - msg("Got MSG of Type %d on Inst %d\n",Header->msg_type,Header->inst); - - switch ( Header->msg_type ) { - case RRM_INIT_CH_REQ: { - rrm_init_ch_req_t *p = (rrm_init_ch_req_t *) Data; - msg( "[RRM]>[RRC][Inst %d]:RRM_INIT_CH_REQ\n",Header->inst); - rrc_init_ch_req(Header->inst,p); - break; - } - - case RRCI_INIT_MR_REQ: { - rrci_init_mr_req_t *p = (rrci_init_mr_req_t *) Data; - msg( "[RRM]>[RRC][Inst %d]:RRCI_INIT_MR_REQ\n",Header->inst); - rrc_init_mr_req(Header->inst,p); - break; - } - - case RRM_RB_ESTABLISH_REQ: { - send_msg((void *)&S_rrc,msg_rrc_rb_establish_resp(Header->inst,Header->Trans_id)); - msg( "[RRM]>[RRC][Inst %d]:RRM_RB_ESTABLISH_REQ, size %d\n",Header->inst,sizeof(rrm_rb_establish_req_t)); - rrc_config_req(Header->inst,(void *)Data,Header->msg_type,Header->Trans_id); - break ; - } - - case RRM_RB_MODIFY_REQ: { - send_msg((void *)&S_rrc,msg_rrc_rb_modify_resp(Header->inst,Header->Trans_id)); - msg( "[RRM]>[RRC][Inst %d]:RRM_RB_MODIFY_REQ\n",Header->inst); - rrc_config_req(Header->inst,Data,Header->msg_type,Header->Trans_id); - } - - case RRM_RB_RELEASE_REQ: { - send_msg((void *)&S_rrc,msg_rrc_rb_release_resp(Header->inst,Header->Trans_id)); - msg( "[RRM]>[RRC][Inst %d]:RRM_RB_RELEASE_REQ\n",Header->inst); - rrc_config_req(Header->inst,Data,Header->msg_type,Header->Trans_id); - } - - case RRCI_CX_ESTABLISH_RESP: { - rrci_cx_establish_resp_t *p = (rrci_cx_establish_resp_t *) Data; - unsigned char i, CH_index = 0; - msg( "[RRCI]>[RRC][Inst %d]:RRCI_CX_ESTABLISH_RESP\n",Header->inst); - - for(i=0; iinst-NB_CH_INST].Info[i].CH_mac_id,&p->L2_id,sizeof(L2_ID))) { - CH_index=i; - break; - } - - if(i==NB_SIG_CNX_UE) { - msg("[RRC] FATAL: CH_INDEX NOT FOUND\n"); - return; - } - - UE_rrc_inst[Header->inst-NB_CH_INST].Srb2[CH_index].Srb_info.IP_addr_type=p->L3_info_t; - - if(p->L3_info_t == IPv4_ADDR) { - memcpy(&UE_rrc_inst[Header->inst-NB_CH_INST].Srb2[CH_index].Srb_info.IP_addr,p->L3_info,4); - } else { - memcpy(&UE_rrc_inst[Header->inst-NB_CH_INST].Srb2[CH_index].Srb_info.IP_addr,p->L3_info,16); - } - } - break ; - - case RRM_SENSING_MEAS_REQ: { - // rrm_sensing_meas_req_t *p = (rrm_sensing_meas_req_t *) sock_msg ; - send_msg((void *)&S_rrc,msg_rrc_sensing_meas_resp(Header->inst,Header->Trans_id)); - msg( "[RRM]>[RRC][Inst %d]:RRM_SENSING_MEAS_REQ\n",Header->inst); - // rrc_meas_req(header->inst,p,RRC_MEAS_ADD); - } - break ; - - case RRM_SENSING_MEAS_RESP: { - msg( "[RRM]>[RRC][Inst %d]:RRM_SENSING_MEAS_RESP\n",Header->inst); - //rrm_rrc_meas_resp(header->inst,header->Trans_id); - } - break ; - - case RRM_SCAN_ORD: - msg( "[RRM]>[RRC][Inst %d]:RRM_SCAN_ORD\n",Header->inst); - //memcpy(&CH_rrc_inst[0].Rrm_init_scan_req,(rrm_init_scan_req_t *) Data,sizeof(rrm_init_scan_req_t)); - //CH_rrc_inst[0].Last_scan_req=Rrc_xface->Frame_index; - ///send over air - break; - - case RRM_INIT_SCAN_REQ: - msg( "[RRM]>[RRC][Inst %d]:RRM_INIT_SCAN_REQ\n",Header->inst); - memcpy(&CH_rrc_inst[0].Rrm_init_scan_req,(rrm_init_scan_req_t *) Data,sizeof(rrm_init_scan_req_t)); - CH_rrc_inst[0].Last_scan_req=Rrc_xface->Frame_index; - ///send over air - break; - - case RRM_END_SCAN_REQ: - msg( "[RRM]>[RRC][Inst %d]:RRM_END_SCAN_REQ\n",Header->inst); - memcpy(&Mac_id.L2_id[0],Data,sizeof(L2_ID)); - unsigned char UE_index=Mac_id.L2_id[0]-NB_CH_MAX+1; - UE_rrc_inst[0].Srb2[UE_index].Srb_info.Tx_buffer.Payload[0]=100; - msg("SRB_ID %d\n",CH_rrc_inst[0].Srb2[UE_index].Srb_info.Srb_id); - Mac_rlc_xface->rrc_rlc_data_req(0,CH_rrc_inst[0].Srb2[UE_index].Srb_info.Srb_id,0,0,1,CH_rrc_inst[0].Srb2[UE_index].Srb_info.Tx_buffer.Payload); - //CH_rrc_inst[0].Last_scan_req=Rrc_xface->Frame_index; - ///send over air - break; - - default : - msg("[L3_xface]WARNING: msg unknown %d\n",Header->msg_type) ; - } - } -} diff --git a/openair2/RRC/NAS/nas_config.c b/openair2/RRC/NAS/nas_config.c index 2eb439b9e9..31ca8f9eb8 100644 --- a/openair2/RRC/NAS/nas_config.c +++ b/openair2/RRC/NAS/nas_config.c @@ -344,6 +344,24 @@ int nas_config(int interface_id, int thirdOctet, int fourthOctet, char *ifname) LOG_E(OIP,"Interface %s couldn't be configured (ip address %s, mask %s broadcast address %s)\n", interfaceName, ipAddress, netMask, broadcastAddress); + int res; + char command_line[500]; + res = sprintf(command_line, + "ip rule add from %s/32 table %d && " + "ip rule add to %s/32 table %d && " + "ip route add default dev %s%d table %d", + ipAddress, interface_id - 1 + 10000, + ipAddress, interface_id - 1 + 10000, + UE_NAS_USE_TUN ? "oaitun_ue" : "oip", + interface_id, interface_id - 1 + 10000); + + if (res < 0) { + LOG_E(OIP,"Could not create ip rule/route commands string\n"); + return res; + } + + background_system(command_line); + return returnValue; } diff --git a/openair2/RRC/NR/L2_nr_interface.c b/openair2/RRC/NR/L2_nr_interface.c index 0905f6d7de..d781cb7e9b 100644 --- a/openair2/RRC/NR/L2_nr_interface.c +++ b/openair2/RRC/NR/L2_nr_interface.c @@ -28,6 +28,7 @@ * \email: raymond.knopp@eurecom.fr, kroempa@gmail.com */ +#include #include "platform_types.h" #include "nr_rrc_defs.h" #include "nr_rrc_extern.h" @@ -35,83 +36,364 @@ #include "pdcp.h" #include "msc.h" #include "common/ran_context.h" +#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" +#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" #include "intertask_interface.h" #include "NR_MIB.h" #include "NR_BCCH-BCH-Message.h" +#include "rrc_gNB_UE_context.h" +#include +#include + extern RAN_CONTEXT_t RC; +int generate_pdcch_ConfigSIB1(NR_PDCCH_ConfigSIB1_t *pdcch_ConfigSIB1, + long ssbSubcarrierSpacing, + long subCarrierSpacingCommon, + channel_bandwidth_t min_channel_bw) { + + nr_ssb_and_cset_mux_pattern_type_t mux_pattern = 0; + + switch (ssbSubcarrierSpacing) { + + case NR_SubcarrierSpacing_kHz15: + if (subCarrierSpacingCommon == NR_SubcarrierSpacing_kHz15) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_1_NUM_INDEXES; + mux_pattern = table_38213_13_1_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else if (subCarrierSpacingCommon == NR_SubcarrierSpacing_kHz30) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_2_NUM_INDEXES; + mux_pattern = table_38213_13_2_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else { + AssertFatal(true,"Invalid subCarrierSpacingCommon\n"); + } + break; + + case NR_SubcarrierSpacing_kHz30: + if (subCarrierSpacingCommon == NR_SubcarrierSpacing_kHz15) { + + if ( (min_channel_bw == bw_5MHz) || (min_channel_bw == bw_10MHz) ) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_3_NUM_INDEXES; + mux_pattern = table_38213_13_3_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else if (min_channel_bw == bw_40MHz) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_5_NUM_INDEXES; + mux_pattern = table_38213_13_5_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else { + AssertFatal(true,"Invalid min_bandwidth\n"); + } + + } else if (subCarrierSpacingCommon == NR_SubcarrierSpacing_kHz30) { + + if ( (min_channel_bw == bw_5MHz) || (min_channel_bw == bw_10MHz) ) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_4_NUM_INDEXES; + mux_pattern = table_38213_13_4_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else if (min_channel_bw == bw_40MHz) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_6_NUM_INDEXES; + mux_pattern = table_38213_13_6_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else { + AssertFatal(true,"Invalid min_bandwidth\n"); + } + + } else { + AssertFatal(true,"Invalid subCarrierSpacingCommon\n"); + } + break; + + case NR_SubcarrierSpacing_kHz120: + if (subCarrierSpacingCommon == NR_SubcarrierSpacing_kHz60) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_7_NUM_INDEXES; + mux_pattern = table_38213_13_7_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else if (subCarrierSpacingCommon == NR_SubcarrierSpacing_kHz120) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_8_NUM_INDEXES; + mux_pattern = table_38213_13_8_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else { + AssertFatal(true,"Invalid subCarrierSpacingCommon\n"); + } + break; + + case NR_SubcarrierSpacing_kHz240: + if (subCarrierSpacingCommon == NR_SubcarrierSpacing_kHz60) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_9_NUM_INDEXES; + mux_pattern = table_38213_13_9_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else if (subCarrierSpacingCommon == NR_SubcarrierSpacing_kHz120) { + pdcch_ConfigSIB1->controlResourceSetZero = rand() % TABLE_38213_13_10_NUM_INDEXES; + mux_pattern = table_38213_13_10_c1[pdcch_ConfigSIB1->controlResourceSetZero]; + } else { + AssertFatal(true,"Invalid subCarrierSpacingCommon\n"); + } + break; + + default: + AssertFatal(true,"Invalid ssbSubcarrierSpacing\n"); + break; + } + + + frequency_range_t frequency_range = FR1; + if(ssbSubcarrierSpacing>=60) { + frequency_range = FR2; + } + + pdcch_ConfigSIB1->searchSpaceZero = 0; + if(mux_pattern == NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 && frequency_range == FR1){ + pdcch_ConfigSIB1->searchSpaceZero = rand() % TABLE_38213_13_11_NUM_INDEXES; + } + if(mux_pattern == NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 && frequency_range == FR2){ + pdcch_ConfigSIB1->searchSpaceZero = rand() % TABLE_38213_13_12_NUM_INDEXES; + } + + return 0; +} + +int +nr_rrc_mac_remove_ue(module_id_t mod_idP, + rnti_t rntiP){ + // todo + return 0; +} + +//------------------------------------------------------------------------------ +uint8_t +nr_rrc_data_req( + const protocol_ctxt_t *const ctxt_pP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_sizeP, + uint8_t *const buffer_pP, + const pdcp_transmission_mode_t modeP +) +//------------------------------------------------------------------------------ +{ + if(sdu_sizeP == 255) { + LOG_D(RRC,"sdu_sizeP == 255"); + return FALSE; + } + + MSC_LOG_TX_MESSAGE( + ctxt_pP->enb_flag ? MSC_RRC_GNB : MSC_RRC_UE, + ctxt_pP->enb_flag ? MSC_PDCP_ENB : MSC_PDCP_UE, + buffer_pP, + sdu_sizeP, + MSC_AS_TIME_FMT"RRC_DCCH_DATA_REQ UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ctxt_pP->rnti, + muiP, + sdu_sizeP); + MessageDef *message_p; + // Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling). + uint8_t *message_buffer; + message_buffer = itti_malloc ( + ctxt_pP->enb_flag ? TASK_RRC_GNB : TASK_RRC_UE, + ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, + sdu_sizeP); + memcpy (message_buffer, buffer_pP, sdu_sizeP); + message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_RRC_GNB : TASK_RRC_UE, 0, RRC_DCCH_DATA_REQ); + RRC_DCCH_DATA_REQ (message_p).frame = ctxt_pP->frame; + RRC_DCCH_DATA_REQ (message_p).enb_flag = ctxt_pP->enb_flag; + RRC_DCCH_DATA_REQ (message_p).rb_id = rb_idP; + RRC_DCCH_DATA_REQ (message_p).muip = muiP; + RRC_DCCH_DATA_REQ (message_p).confirmp = confirmP; + RRC_DCCH_DATA_REQ (message_p).sdu_size = sdu_sizeP; + RRC_DCCH_DATA_REQ (message_p).sdu_p = message_buffer; + //memcpy (NR_RRC_DCCH_DATA_REQ (message_p).sdu_p, buffer_pP, sdu_sizeP); + RRC_DCCH_DATA_REQ (message_p).mode = modeP; + RRC_DCCH_DATA_REQ (message_p).module_id = ctxt_pP->module_id; + RRC_DCCH_DATA_REQ (message_p).rnti = ctxt_pP->rnti; + RRC_DCCH_DATA_REQ (message_p).eNB_index = ctxt_pP->eNB_index; + itti_send_msg_to_task ( + ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, + ctxt_pP->instance, + message_p); + LOG_I(NR_RRC,"send RRC_DCCH_DATA_REQ to PDCP\n"); + + /* Hack: only trigger PDCP if in CU, otherwise it is triggered by RU threads + * Ideally, PDCP would not neet to be triggered like this but react to ITTI + * messages automatically */ + if (ctxt_pP->enb_flag && NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) + pdcp_run(ctxt_pP); + + return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. +} + int8_t mac_rrc_nr_data_req(const module_id_t Mod_idP, const int CC_id, const frame_t frameP, const rb_id_t Srb_id, + const rnti_t rnti, const uint8_t Nb_tb, uint8_t *const buffer_pP ){ - asn_enc_rval_t enc_rval; - uint8_t Sdu_size = 0; - uint8_t sfn_msb = (uint8_t)((frameP>>4)&0x3f); - #ifdef DEBUG_RRC LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%ld\n",Mod_idP,Srb_id); #endif - gNB_RRC_INST *rrc; - rrc_gNB_carrier_data_t *carrier; - NR_BCCH_BCH_Message_t *mib; - NR_SRB_INFO * srb_info; - char payload_size, *payload_pP; - - rrc = RC.nrrrc[Mod_idP]; - carrier = &rrc->carrier; - mib = &carrier->mib; - srb_info = &carrier->Srb0; + // MIBCH + if ((Srb_id & RAB_OFFSET) == MIBCH) { - /* MIBCH */ - if( (Srb_id & RAB_OFFSET ) == MIBCH) { - mib->message.choice.mib->systemFrameNumber.buf[0] = sfn_msb << 2; - enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_BCH_Message, - NULL, - (void *)mib, - carrier->MIB, - 24); - LOG_D(NR_RRC,"Encoded MIB for frame %d sfn_msb %d (%p), bits %lu\n",frameP,sfn_msb,carrier->MIB,enc_rval.encoded); - buffer_pP[0]=carrier->MIB[0]; - buffer_pP[1]=carrier->MIB[1]; - buffer_pP[2]=carrier->MIB[2]; - LOG_D(NR_RRC,"MIB PDU buffer_pP[0]=%x , buffer_pP[1]=%x, buffer_pP[2]=%x\n",buffer_pP[0],buffer_pP[1],buffer_pP[2]); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return(3); + asn_enc_rval_t enc_rval; + uint8_t sfn_msb = (uint8_t)((frameP>>4)&0x3f); + rrc_gNB_carrier_data_t *carrier = &RC.nrrrc[Mod_idP]->carrier; + NR_BCCH_BCH_Message_t *mib = &carrier->mib; + + // Currently we are getting the pdcch_ConfigSIB1 from the configuration file. + // Uncomment this function for a dynamic pdcch_ConfigSIB1. + //channel_bandwidth_t min_channel_bw = bw_10MHz; // Must be obtained based on TS 38.101-1 Table 5.3.5-1 + //generate_pdcch_ConfigSIB1(carrier->pdcch_ConfigSIB1, + // *carrier->servingcellconfigcommon->ssbSubcarrierSpacing, + // carrier->mib.message.choice.mib->subCarrierSpacingCommon, + // min_channel_bw); + + mib->message.choice.mib->pdcch_ConfigSIB1.controlResourceSetZero = carrier->pdcch_ConfigSIB1->controlResourceSetZero; + mib->message.choice.mib->pdcch_ConfigSIB1.searchSpaceZero = carrier->pdcch_ConfigSIB1->searchSpaceZero; + + mib->message.choice.mib->systemFrameNumber.buf[0] = sfn_msb << 2; + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_BCH_Message, + NULL, + (void *) mib, + carrier->MIB, + 24); + LOG_D(NR_RRC, "Encoded MIB for frame %d sfn_msb %d (%p), bits %lu\n", frameP, sfn_msb, carrier->MIB, + enc_rval.encoded); + buffer_pP[0] = carrier->MIB[0]; + buffer_pP[1] = carrier->MIB[1]; + buffer_pP[2] = carrier->MIB[2]; + LOG_D(NR_RRC, "MIB PDU buffer_pP[0]=%x , buffer_pP[1]=%x, buffer_pP[2]=%x\n", buffer_pP[0], buffer_pP[1], + buffer_pP[2]); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return (3); + } + + // TODO BCCH SIB1 SIBs + if ((Srb_id & RAB_OFFSET ) == BCCH) { + memcpy(&buffer_pP[0], + RC.nrrrc[Mod_idP]->carrier.SIB1, + RC.nrrrc[Mod_idP]->carrier.sizeof_SIB1); + + return RC.nrrrc[Mod_idP]->carrier.sizeof_SIB1; } - /* TODO BCCH SIB1 SIBs */ - - /* CCCH */ + // CCCH if( (Srb_id & RAB_OFFSET ) == CCCH) { - //struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[Mod_idP],rnti); - //if (ue_context_p == NULL) return(0); - //eNB_RRC_UE_t *ue_p = &ue_context_p->ue_context; - LOG_D(RRC,"[gNB %d] Frame %d CCCH request (Srb_id %ld)\n", Mod_idP, frameP, Srb_id); - // srb_info=&ue_p->Srb0; + char *payload_pP; + uint8_t Sdu_size = 0; + struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[Mod_idP], rnti); - payload_size = srb_info->Tx_buffer.payload_size; + LOG_D(NR_RRC,"[gNB %d] Frame %d CCCH request (Srb_id %ld)\n", Mod_idP, frameP, Srb_id); + + AssertFatal(ue_context_p!=NULL,"failed to get ue_context, rnti %x\n",rnti); + char payload_size = ue_context_p->ue_context.Srb0.Tx_buffer.payload_size; // check if data is there for MAC if (payload_size > 0) { - payload_pP = srb_info->Tx_buffer.Payload; - LOG_D(RRC,"[gNB %d] CCCH (%p) has %d bytes (dest: %p, src %p)\n", Mod_idP, srb_info, payload_size, buffer_pP, payload_pP); + payload_pP = ue_context_p->ue_context.Srb0.Tx_buffer.Payload; + LOG_D(NR_RRC,"[gNB %d] CCCH has %d bytes (dest: %p, src %p)\n", Mod_idP, payload_size, buffer_pP, payload_pP); // Fill buffer memcpy((void *)buffer_pP, (void*)payload_pP, payload_size); Sdu_size = payload_size; - srb_info->Tx_buffer.payload_size = 0; + ue_context_p->ue_context.Srb0.Tx_buffer.payload_size = 0; } return Sdu_size; } return(0); -} \ No newline at end of file +} + +int8_t nr_mac_rrc_data_ind(const module_id_t module_idP, + const int CC_id, + const frame_t frameP, + const sub_frame_t sub_frameP, + const int UE_id, + const rnti_t rntiP, + const rb_id_t srb_idP, + const uint8_t *sduP, + const sdu_size_t sdu_lenP, + const boolean_t brOption) { + + if (NODE_IS_DU(RC.nrrrc[module_idP]->node_type)) { + LOG_W(RRC,"[DU %d][RAPROC] Received SDU for CCCH on SRB %ld length %d for UE id %d RNTI %x \n", + module_idP, srb_idP, sdu_lenP, UE_id, rntiP); + + // Generate DUtoCURRCContainer + // call do_RRCSetup like full procedure and extract masterCellGroup + NR_CellGroupConfig_t cellGroupConfig; + NR_ServingCellConfigCommon_t *scc=RC.nrrrc[module_idP]->carrier.servingcellconfigcommon; + uint8_t sdu2[100]; + memset(&cellGroupConfig,0,sizeof(cellGroupConfig)); + fill_initial_cellGroupConfig(rntiP,&cellGroupConfig,scc,&RC.nrrrc[module_idP]->carrier); + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, + NULL, + (void *)&cellGroupConfig, + sdu2, + 100); + + int sdu2_len = (enc_rval.encoded+7)/8; + if (enc_rval.encoded == -1) { + LOG_E(F1AP,"Could not encoded cellGroupConfig, failed element %s\n",enc_rval.failed_type->name); + exit(-1); + } + /* do ITTI message */ + DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER( + module_idP, + CC_id, + UE_id, + rntiP, + sduP, + sdu_lenP, + (const int8_t*)sdu2, + sdu2_len + ); + return(0); + } + + protocol_ctxt_t ctxt; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, GNB_FLAG_YES, rntiP, frameP, sub_frameP,0); + + if((srb_idP & RAB_OFFSET) == CCCH) { + LOG_D(NR_RRC, "[gNB %d] Received SDU for CCCH on SRB %ld\n", module_idP, srb_idP); + ctxt.brOption = brOption; + if (sdu_lenP > 0) { + nr_rrc_gNB_decode_ccch(&ctxt, sduP, sdu_lenP, NULL, CC_id); + } + } + + return 0; +} + +void nr_mac_gNB_rrc_ul_failure(const module_id_t Mod_instP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t subframeP, + const rnti_t rntiP) { + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + ue_context_p = rrc_gNB_get_ue_context( + RC.nrrrc[Mod_instP], + rntiP); + + if (ue_context_p != NULL) { + LOG_D(RRC,"Frame %d, Subframe %d: UE %x UL failure, activating timer\n",frameP,subframeP,rntiP); + if(ue_context_p->ue_context.ul_failure_timer == 0) + ue_context_p->ue_context.ul_failure_timer=1; + } else { + LOG_D(RRC,"Frame %d, Subframe %d: UL failure: UE %x unknown \n",frameP,subframeP,rntiP); + } +} + +void nr_mac_gNB_rrc_ul_failure_reset(const module_id_t Mod_instP, + const frame_t frameP, + const sub_frame_t subframeP, + const rnti_t rntiP) { + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[Mod_instP], rntiP); + if (ue_context_p != NULL) { + LOG_W(RRC,"Frame %d, Subframe %d: UE %x UL failure reset, deactivating timer\n",frameP,subframeP,rntiP); + ue_context_p->ue_context.ul_failure_timer=0; + } else { + LOG_W(RRC,"Frame %d, Subframe %d: UL failure reset: UE %x unknown \n",frameP,subframeP,rntiP); + } +} diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c old mode 100644 new mode 100755 index c00b57d7aa..bdd1cf5261 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -41,8 +41,40 @@ #include #include "asn1_msg.h" +#include "../nr_rrc_proto.h" #include "RRC/NR/nr_rrc_extern.h" -#if defined(NR_Rel15) +#include "NR_DL-CCCH-Message.h" +#include "NR_UL-CCCH-Message.h" +#include "NR_DL-DCCH-Message.h" +#include "NR_RRCReject.h" +#include "NR_RejectWaitTime.h" +#include "NR_RRCSetup.h" +#include "NR_RRCSetup-IEs.h" +#include "NR_SRB-ToAddModList.h" +#include "NR_CellGroupConfig.h" +#include "NR_RLC-BearerConfig.h" +#include "NR_RLC-Config.h" +#include "NR_LogicalChannelConfig.h" +#include "NR_PDCP-Config.h" +#include "NR_MAC-CellGroupConfig.h" +#include "NR_SecurityModeCommand.h" +#include "NR_CipheringAlgorithm.h" +#include "NR_RRCReconfiguration-IEs.h" +#include "NR_DRB-ToAddMod.h" +#include "NR_DRB-ToAddModList.h" +#include "NR_SecurityConfig.h" +#include "NR_RRCReconfiguration-v1530-IEs.h" +#include "NR_UL-DCCH-Message.h" +#include "NR_SDAP-Config.h" +#include "NR_RRCReconfigurationComplete.h" +#include "NR_RRCReconfigurationComplete-IEs.h" +#include "NR_DLInformationTransfer.h" +#include "NR_RRCReestablishmentRequest.h" +#include "NR_UE-CapabilityRequestFilterNR.h" +#include "PHY/defs_nr_common.h" +#include "common/utils/nr/nr_common.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" +#if defined(NR_Rel16) #include "NR_SCS-SpecificCarrier.h" #include "NR_TDD-UL-DL-ConfigCommon.h" #include "NR_FrequencyInfoUL.h" @@ -103,18 +135,6 @@ #include "common/ran_context.h" -//#include "PHY/defs.h" -/*#ifndef USER_MODE -#define msg printk -#ifndef errno -int errno; -#endif -#else -# if !defined (msg) -# define msg printf -# endif -#endif*/ - //#define XER_PRINT typedef struct xer_sprint_string_s { @@ -200,8 +220,19 @@ uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) { mib->message.choice.mib->spare.bits_unused = 7; // This makes a spare of 1 bits mib->message.choice.mib->ssb_SubcarrierOffset = (carrier->ssb_SubcarrierOffset)&15; - mib->message.choice.mib->pdcch_ConfigSIB1.controlResourceSetZero = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero; - mib->message.choice.mib->pdcch_ConfigSIB1.searchSpaceZero = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero; + + /* + * The SIB1 will be sent in this allocation (Type0-PDCCH) : 38.213, 13-4 Table and 38.213 13-11 to 13-14 tables + * the reverse allocation is in nr_ue_decode_mib() + */ + if(rrc->carrier.pdcch_ConfigSIB1) { + mib->message.choice.mib->pdcch_ConfigSIB1.controlResourceSetZero = rrc->carrier.pdcch_ConfigSIB1->controlResourceSetZero; + mib->message.choice.mib->pdcch_ConfigSIB1.searchSpaceZero = rrc->carrier.pdcch_ConfigSIB1->searchSpaceZero; + } else { + mib->message.choice.mib->pdcch_ConfigSIB1.controlResourceSetZero = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero; + mib->message.choice.mib->pdcch_ConfigSIB1.searchSpaceZero = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero; + } + AssertFatal(scc->ssbSubcarrierSpacing != NULL, "scc->ssbSubcarrierSpacing is null\n"); switch (*scc->ssbSubcarrierSpacing) { case NR_SubcarrierSpacing_kHz15: @@ -265,86 +296,369 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, gNB_RrcConfigurationReq *configuration ) { asn_enc_rval_t enc_rval; - NR_BCCH_DL_SCH_Message_t *sib1_message ; - struct NR_SIB1 *sib1 ; - int i; - struct NR_PLMN_IdentityInfo nr_plmn_info; // TODO : Add support for more than one PLMN - //int num_plmn = configuration->num_plmn; - int num_plmn = 1; - struct NR_PLMN_Identity nr_plmn[num_plmn]; - NR_MCC_MNC_Digit_t nr_mcc_digit[num_plmn][3]; - NR_MCC_MNC_Digit_t nr_mnc_digit[num_plmn][3]; - // struct NR_UAC_BarringInfoSet nr_uac_BarringInfoSet; - sib1_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t)); - memset(sib1_message,0,sizeof(NR_BCCH_DL_SCH_Message_t)); + int num_plmn = 1; // int num_plmn = configuration->num_plmn; + struct NR_PLMN_Identity *nr_plmn = CALLOC(1, sizeof(struct NR_PLMN_Identity) * num_plmn); + NR_MCC_MNC_Digit_t (*nr_mcc_digit)[3] = (NR_MCC_MNC_Digit_t(*)[3])CALLOC(1, sizeof(NR_MCC_MNC_Digit_t)*num_plmn*3); + NR_MCC_MNC_Digit_t (*nr_mnc_digit)[3] = (NR_MCC_MNC_Digit_t(*)[3])CALLOC(1, sizeof(NR_MCC_MNC_Digit_t)*num_plmn*3);; + memset(nr_plmn,0,sizeof(struct NR_PLMN_Identity) * num_plmn); + memset(nr_mcc_digit,0,sizeof(NR_MCC_MNC_Digit_t)*num_plmn*3); + memset(nr_mnc_digit,0,sizeof(NR_MCC_MNC_Digit_t)*num_plmn*3); + + NR_BCCH_DL_SCH_Message_t *sib1_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t)); carrier->siblock1 = sib1_message; sib1_message->message.present = NR_BCCH_DL_SCH_MessageType_PR_c1; sib1_message->message.choice.c1 = CALLOC(1,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1)); - memset(sib1_message->message.choice.c1,0,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1)); sib1_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1; sib1_message->message.choice.c1->choice.systemInformationBlockType1 = CALLOC(1,sizeof(struct NR_SIB1)); - sib1 = sib1_message->message.choice.c1->choice.systemInformationBlockType1; - memset(sib1,0,sizeof(struct NR_SIB1)); - sib1->cellSelectionInfo = CALLOC(1,sizeof(struct NR_SIB1__cellSelectionInfo)); - memset(sib1->cellSelectionInfo,0,sizeof(struct NR_SIB1__cellSelectionInfo)); - sib1->cellSelectionInfo->q_RxLevMin = -50; - memset(&nr_plmn_info.plmn_IdentityList,0,sizeof(struct NR_PLMN_IdentityInfo__plmn_IdentityList)); - asn_set_empty(&nr_plmn_info.plmn_IdentityList.list); - memset(&nr_plmn_info,0,sizeof(struct NR_PLMN_IdentityInfo)); - memset(nr_plmn,0,num_plmn*sizeof(struct NR_PLMN_Identity)); - for (i = 0; i < num_plmn; ++i) { + struct NR_SIB1 *sib1 = sib1_message->message.choice.c1->choice.systemInformationBlockType1; + + // cellSelectionInfo + sib1->cellSelectionInfo = CALLOC(1,sizeof(struct NR_SIB1__cellSelectionInfo)); + sib1->cellSelectionInfo->q_RxLevMin = -65; + + // cellAccessRelatedInfo + struct NR_PLMN_IdentityInfo *nr_plmn_info=CALLOC(1,sizeof(struct NR_PLMN_IdentityInfo)); + asn_set_empty(&nr_plmn_info->plmn_IdentityList.list); + for (int i = 0; i < num_plmn; ++i) { nr_mcc_digit[i][0] = (configuration->mcc[i]/100)%10; nr_mcc_digit[i][1] = (configuration->mcc[i]/10)%10; nr_mcc_digit[i][2] = (configuration->mcc[i])%10; nr_plmn[i].mcc = CALLOC(1,sizeof(struct NR_MCC)); - memset(nr_plmn[i].mcc,0,sizeof(struct NR_MCC)); asn_set_empty(&nr_plmn[i].mcc->list); ASN_SEQUENCE_ADD(&nr_plmn[i].mcc->list, &nr_mcc_digit[i][0]); ASN_SEQUENCE_ADD(&nr_plmn[i].mcc->list, &nr_mcc_digit[i][1]); ASN_SEQUENCE_ADD(&nr_plmn[i].mcc->list, &nr_mcc_digit[i][2]); - nr_mnc_digit[i][0] = (configuration->mnc[i]/100)%10; + if(configuration->mnc_digit_length[i] == 3) nr_mnc_digit[i][0] = (configuration->mnc[i]/100)%10; nr_mnc_digit[i][1] = (configuration->mnc[i]/10)%10; nr_mnc_digit[i][2] = (configuration->mnc[i])%10; - memset(&nr_plmn[i].mnc,0,sizeof(NR_MNC_t)); nr_plmn[i].mnc.list.size=0; nr_plmn[i].mnc.list.count=0; - ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][0]); + if(configuration->mnc_digit_length[i] == 3) ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][0]); ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][1]); ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][2]); - ASN_SEQUENCE_ADD(&nr_plmn_info.plmn_IdentityList.list, &nr_plmn[i]); + ASN_SEQUENCE_ADD(&nr_plmn_info->plmn_IdentityList.list, &nr_plmn[i]); }//end plmn loop - nr_plmn_info.cellIdentity.buf = MALLOC(8); - memset(nr_plmn_info.cellIdentity.buf,0,8); - nr_plmn_info.cellIdentity.buf[0]= (configuration->cell_identity >> 20) & 0xff; - nr_plmn_info.cellIdentity.buf[1]= (configuration->cell_identity >> 12) & 0xff; - nr_plmn_info.cellIdentity.buf[2]= (configuration->cell_identity >> 4) & 0xff; - nr_plmn_info.cellIdentity.buf[3]= (configuration->cell_identity << 4) & 0xff; - nr_plmn_info.cellIdentity.size= 4; - nr_plmn_info.cellIdentity.bits_unused= 4; - nr_plmn_info.cellReservedForOperatorUse = 0; - memset(&sib1->cellAccessRelatedInfo,0,sizeof(NR_CellAccessRelatedInfo_t)); - ASN_SEQUENCE_ADD(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list, &nr_plmn_info); -#if 0 - sib1->uac_BarringInfo = CALLOC(1, sizeof(struct NR_SIB1__uac_BarringInfo)); - memset(sib1->uac_BarringInfo, 0, sizeof(struct NR_SIB1__uac_BarringInfo)); - nr_uac_BarringInfoSet.uac_BarringFactor = NR_UAC_BarringInfoSet__uac_BarringFactor_p95; - nr_uac_BarringInfoSet.uac_BarringTime = NR_UAC_BarringInfoSet__uac_BarringTime_s4; - nr_uac_BarringInfoSet.uac_BarringForAccessIdentity.buf = MALLOC(1); - memset(nr_uac_BarringInfoSet.uac_BarringForAccessIdentity.buf,0,1); - nr_uac_BarringInfoSet.uac_BarringForAccessIdentity.size = 1; - nr_uac_BarringInfoSet.uac_BarringForAccessIdentity.bits_unused = 1; - ASN_SEQUENCE_ADD(&sib1->uac_BarringInfo->uac_BarringInfoSetList, &nr_uac_BarringInfoSet); -#endif - //encode SIB1 to data + nr_plmn_info->cellIdentity.buf = CALLOC(1,5); + nr_plmn_info->cellIdentity.buf[0]= (configuration->cell_identity >> 28) & 0xff; + nr_plmn_info->cellIdentity.buf[1]= (configuration->cell_identity >> 20) & 0xff; + nr_plmn_info->cellIdentity.buf[2]= (configuration->cell_identity >> 12) & 0xff; + nr_plmn_info->cellIdentity.buf[3]= (configuration->cell_identity >> 4) & 0xff; + nr_plmn_info->cellIdentity.buf[4]= (configuration->cell_identity << 4) & 0xff; + nr_plmn_info->cellIdentity.size= 5; + nr_plmn_info->cellIdentity.bits_unused= 4; + nr_plmn_info->cellReservedForOperatorUse = NR_PLMN_IdentityInfo__cellReservedForOperatorUse_notReserved; + + nr_plmn_info->trackingAreaCode = CALLOC(1,sizeof(NR_TrackingAreaCode_t)); + nr_plmn_info->trackingAreaCode->buf = CALLOC(1,3); + nr_plmn_info->trackingAreaCode->buf[0] = ( ((uint32_t)configuration->tac) >> 16) & 0xff; + nr_plmn_info->trackingAreaCode->buf[1] = ( ((uint32_t)configuration->tac) >> 8) & 0xff; + nr_plmn_info->trackingAreaCode->buf[2] = ( ((uint32_t)configuration->tac) >> 0) & 0xff; + nr_plmn_info->trackingAreaCode->size = 3; + nr_plmn_info->trackingAreaCode->bits_unused = 0; + + ASN_SEQUENCE_ADD(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list, nr_plmn_info); + + // connEstFailureControl + // TODO: add connEstFailureControl + + //si-SchedulingInfo + /*sib1->si_SchedulingInfo = CALLOC(1,sizeof(struct NR_SI_SchedulingInfo)); + asn_set_empty(&sib1->si_SchedulingInfo->schedulingInfoList.list); + sib1->si_SchedulingInfo->si_WindowLength = NR_SI_SchedulingInfo__si_WindowLength_s40; + struct NR_SchedulingInfo *schedulingInfo = CALLOC(1,sizeof(struct NR_SchedulingInfo)); + schedulingInfo->si_BroadcastStatus = NR_SchedulingInfo__si_BroadcastStatus_broadcasting; + schedulingInfo->si_Periodicity = NR_SchedulingInfo__si_Periodicity_rf8; + asn_set_empty(&schedulingInfo->sib_MappingInfo.list); + + NR_SIB_TypeInfo_t *sib_type3 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); + sib_type3->type = NR_SIB_TypeInfo__type_sibType3; + sib_type3->valueTag = CALLOC(1,sizeof(sib_type3->valueTag)); + ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type3); + + NR_SIB_TypeInfo_t *sib_type5 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); + sib_type5->type = NR_SIB_TypeInfo__type_sibType5; + sib_type5->valueTag = CALLOC(1,sizeof(sib_type5->valueTag)); + ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type5); + + NR_SIB_TypeInfo_t *sib_type4 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); + sib_type4->type = NR_SIB_TypeInfo__type_sibType4; + sib_type4->valueTag = CALLOC(1,sizeof(sib_type4->valueTag)); + ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type4); + + NR_SIB_TypeInfo_t *sib_type2 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); + sib_type2->type = NR_SIB_TypeInfo__type_sibType2; + sib_type2->valueTag = CALLOC(1,sizeof(sib_type2->valueTag)); + ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type2); + + ASN_SEQUENCE_ADD(&sib1->si_SchedulingInfo->schedulingInfoList.list,schedulingInfo);*/ + + // servingCellConfigCommon + sib1->servingCellConfigCommon = CALLOC(1,sizeof(struct NR_ServingCellConfigCommonSIB)); + + asn_set_empty(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list); + asn_set_empty(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list); + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.genericParameters.subcarrierSpacing = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.genericParameters.cyclicPrefix = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.cyclicPrefix; + for(int i = 0; i< configuration->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count; i++) { + struct NR_NR_MultiBandInfo *nrMultiBandInfo = CALLOC(1,sizeof(struct NR_NR_MultiBandInfo)); + nrMultiBandInfo->freqBandIndicatorNR = configuration->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[i]; + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list,nrMultiBandInfo); + } + + int scs_scaling0 = 1<<(configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing); + int scs_scaling = scs_scaling0; + int scs_scaling2 = scs_scaling0; + if (configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) { + scs_scaling = scs_scaling0*3; + } + if (configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) { + scs_scaling = scs_scaling0>>2; + scs_scaling2 = scs_scaling0>>2; + } + uint32_t absolute_diff = (*configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - + configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); + + sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA = scs_scaling2 * (absolute_diff/(12*scs_scaling) - 10); + + LOG_I(NR_RRC,"SIB1 freq: absoluteFrequencySSB %ld, absoluteFrequencyPointA %ld\n", + *configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB, + configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); + LOG_I(NR_RRC,"SIB1 freq: absolute_diff %d, %d*(absolute_diff/(12*%d) - 10) %d\n", + absolute_diff,scs_scaling2,scs_scaling,(int)sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA); + + for(int i = 0; i< configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.count; i++) { + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list,configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[i]); + } + + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); + asn_set_empty(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list); + + NR_SearchSpace_t *ss1 = calloc(1,sizeof(*ss1)); + ss1->searchSpaceId = 1; + ss1->controlResourceSetId=calloc(1,sizeof(*ss1->controlResourceSetId)); + *ss1->controlResourceSetId=0; + ss1->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss1->monitoringSlotPeriodicityAndOffset)); + ss1->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; + ss1->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss1->monitoringSymbolsWithinSlot)); + ss1->monitoringSymbolsWithinSlot->buf = calloc(1,2); + // should be '1000 0000 0000 00'B (LSB first!), first symbol in slot, adjust if needed + ss1->monitoringSymbolsWithinSlot->buf[1] = 0; + ss1->monitoringSymbolsWithinSlot->buf[0] = (1<<7); + ss1->monitoringSymbolsWithinSlot->size = 2; + ss1->monitoringSymbolsWithinSlot->bits_unused = 2; + ss1->nrofCandidates = calloc(1,sizeof(*ss1->nrofCandidates)); + ss1->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss1->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + ss1->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; + ss1->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; + ss1->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; + ss1->searchSpaceType = calloc(1,sizeof(*ss1->searchSpaceType)); + ss1->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; + ss1->searchSpaceType->choice.common=calloc(1,sizeof(*ss1->searchSpaceType->choice.common)); + ss1->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss1->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list,ss1); + + NR_SearchSpace_t *ss5 = calloc(1,sizeof(*ss5)); + ss5->searchSpaceId = 5; + ss5->controlResourceSetId=calloc(1,sizeof(*ss5->controlResourceSetId)); + *ss5->controlResourceSetId=0; + ss5->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss5->monitoringSlotPeriodicityAndOffset)); + ss5->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5; + ss5->monitoringSlotPeriodicityAndOffset->choice.sl5 = 0; + ss5->duration = calloc(1,sizeof(*ss5->duration)); + *ss5->duration = 2; + ss5->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss5->monitoringSymbolsWithinSlot)); + ss5->monitoringSymbolsWithinSlot->buf = calloc(1,2); + // should be '1100 0000 0000 00'B (LSB first!), first two symols in slot, adjust if needed + ss5->monitoringSymbolsWithinSlot->buf[1] = 0; + ss5->monitoringSymbolsWithinSlot->buf[0] = (1<<7); + ss5->monitoringSymbolsWithinSlot->size = 2; + ss5->monitoringSymbolsWithinSlot->bits_unused = 2; + ss5->nrofCandidates = calloc(1,sizeof(*ss5->nrofCandidates)); + ss5->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss5->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + ss5->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; + ss5->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n2; + ss5->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n1; + ss5->searchSpaceType = calloc(1,sizeof(*ss5->searchSpaceType)); + ss5->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; + ss5->searchSpaceType->choice.common=calloc(1,sizeof(*ss5->searchSpaceType->choice.common)); + ss5->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss5->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list,ss5); + + NR_SearchSpace_t *ss7 = calloc(1,sizeof(*ss7)); + ss7->searchSpaceId = 7; + ss7->controlResourceSetId=calloc(1,sizeof(*ss7->controlResourceSetId)); + *ss7->controlResourceSetId=0; + ss7->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss7->monitoringSlotPeriodicityAndOffset)); + ss7->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; + ss7->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss7->monitoringSymbolsWithinSlot)); + ss7->monitoringSymbolsWithinSlot->buf = calloc(1,2); + // should be '1100 0000 0000 00'B (LSB first!), first two symols in slot, adjust if needed + ss7->monitoringSymbolsWithinSlot->buf[1] = 0; + ss7->monitoringSymbolsWithinSlot->buf[0] = (1<<7); + ss7->monitoringSymbolsWithinSlot->size = 2; + ss7->monitoringSymbolsWithinSlot->bits_unused = 2; + ss7->nrofCandidates = calloc(1,sizeof(*ss7->nrofCandidates)); + ss7->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss7->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + ss7->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; + ss7->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n2; + ss7->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n1; + ss7->searchSpaceType = calloc(1,sizeof(*ss7->searchSpaceType)); + ss7->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; + ss7->searchSpaceType->choice.common=calloc(1,sizeof(*ss7->searchSpaceType->choice.common)); + ss7->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss7->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list,ss7); + + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = calloc(1,sizeof(NR_SearchSpaceId_t)); + *sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = 0; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation = calloc(1,sizeof(NR_SearchSpaceId_t)); + *sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation = 7; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->pagingSearchSpace = calloc(1,sizeof(NR_SearchSpaceId_t)); + *sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->pagingSearchSpace = 5; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->ra_SearchSpace = calloc(1,sizeof(NR_SearchSpaceId_t)); + *sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->ra_SearchSpace = 1; + + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon; + sib1->servingCellConfigCommon->downlinkConfigCommon.bcch_Config.modificationPeriodCoeff = NR_BCCH_Config__modificationPeriodCoeff_n2; + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.defaultPagingCycle = NR_PagingCycle_rf256; + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.nAndPagingFrameOffset.present = NR_PCCH_Config__nAndPagingFrameOffset_PR_quarterT; + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.nAndPagingFrameOffset.choice.quarterT = 1; + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.ns = NR_PCCH_Config__ns_one; + + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO = calloc(1,sizeof(struct NR_PCCH_Config__firstPDCCH_MonitoringOccasionOfPO)); + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO->present = NR_PCCH_Config__firstPDCCH_MonitoringOccasionOfPO_PR_sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT; + + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO->choice.sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT = CALLOC(1,sizeof(struct NR_PCCH_Config__firstPDCCH_MonitoringOccasionOfPO__sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT)); + asn_set_empty(&sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO->choice.sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT->list); + + long *sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT = calloc(1,sizeof(long)); + *sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT = 0; + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO->choice.sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT->list,sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT); + + sib1->servingCellConfigCommon->uplinkConfigCommon = CALLOC(1,sizeof(struct NR_UplinkConfigCommonSIB)); + asn_set_empty(&sib1->servingCellConfigCommon->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list); + for(int i = 0; i< configuration->scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.count; i++) { + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list,configuration->scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[i]); + } + + sib1->servingCellConfigCommon->uplinkConfigCommon->frequencyInfoUL.p_Max = CALLOC(1,sizeof(NR_P_Max_t)); + *sib1->servingCellConfigCommon->uplinkConfigCommon->frequencyInfoUL.p_Max = 23; + + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.genericParameters = configuration->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon = configuration->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; + + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon = configuration->scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding = null; + + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon = configuration->scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon; + + sib1->servingCellConfigCommon->uplinkConfigCommon->timeAlignmentTimerCommon = NR_TimeAlignmentTimer_infinity; + + sib1->servingCellConfigCommon->n_TimingAdvanceOffset = configuration->scc->n_TimingAdvanceOffset; + + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup.buf = calloc(1, sizeof(uint8_t)); + uint8_t bitmap8,temp_bitmap=0; + switch (configuration->scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup = configuration->scc->ssb_PositionsInBurst->choice.shortBitmap; + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup = configuration->scc->ssb_PositionsInBurst->choice.mediumBitmap; + break; + /* + groupPresence: This field is present when maximum number of SS/PBCH blocks per half frame equals to 64 as defined in TS 38.213 [13], clause 4.1. + The first/leftmost bit corresponds to the SS/PBCH index 0-7, the second bit corresponds to SS/PBCH block 8-15, and so on. + Value 0 in the bitmap indicates that the SSBs according to inOneGroup are absent. Value 1 indicates that the SS/PBCH blocks are transmitted in accordance with inOneGroup. + inOneGroup: When maximum number of SS/PBCH blocks per half frame equals to 64 as defined in TS 38.213 [13], clause 4.1, all 8 bit are valid; + The first/ leftmost bit corresponds to the first SS/PBCH block index in the group (i.e., to SSB index 0, 8, and so on); the second bit corresponds to the second SS/PBCH block index in the group + (i.e., to SSB index 1, 9, and so on), and so on. Value 0 in the bitmap indicates that the corresponding SS/PBCH block is not transmitted while value 1 indicates that the corresponding SS/PBCH block is transmitted. + */ + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup.size = 1; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup.bits_unused = 0; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence = calloc(1, sizeof(BIT_STRING_t)); + memset(sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence, 0, sizeof(BIT_STRING_t)); + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->size = 1; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->bits_unused = 0; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->buf = calloc(1, sizeof(uint8_t)); + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->buf[0] = 0; + for (int i=0; i<8; i++){ + bitmap8 = configuration->scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]; + if (bitmap8!=0){ + if(temp_bitmap==0) + temp_bitmap = bitmap8; + else + AssertFatal(temp_bitmap==bitmap8,"For longBitmap the groups of 8 SSBs containing at least 1 transmitted SSB should be all the same\n"); + + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup.buf[0] = bitmap8; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->buf[0] |= 1<<(7-i); + } + } + break; + default: + AssertFatal(false,"ssb_PositionsInBurst not present\n"); + break; + } + + sib1->servingCellConfigCommon->ssb_PeriodicityServingCell = *configuration->scc->ssb_periodicityServingCell; + sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon = CALLOC(1,sizeof(struct NR_TDD_UL_DL_ConfigCommon)); + sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing = configuration->scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; + sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon->pattern1 = configuration->scc->tdd_UL_DL_ConfigurationCommon->pattern1; + sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon->pattern2 = configuration->scc->tdd_UL_DL_ConfigurationCommon->pattern2; + sib1->servingCellConfigCommon->ss_PBCH_BlockPower = configuration->scc->ss_PBCH_BlockPower; + + // ims-EmergencySupport + // TODO: add ims-EmergencySupport + + // eCallOverIMS-Support + // TODO: add eCallOverIMS-Support + + // ue-TimersAndConstants + sib1->ue_TimersAndConstants = CALLOC(1,sizeof(struct NR_UE_TimersAndConstants)); + sib1->ue_TimersAndConstants->t300 = NR_UE_TimersAndConstants__t300_ms400; + sib1->ue_TimersAndConstants->t301 = NR_UE_TimersAndConstants__t301_ms400; + sib1->ue_TimersAndConstants->t310 = NR_UE_TimersAndConstants__t310_ms2000; + sib1->ue_TimersAndConstants->n310 = NR_UE_TimersAndConstants__n310_n10; + sib1->ue_TimersAndConstants->t311 = NR_UE_TimersAndConstants__t311_ms3000; + sib1->ue_TimersAndConstants->n311 = NR_UE_TimersAndConstants__n311_n1; + sib1->ue_TimersAndConstants->t319 = NR_UE_TimersAndConstants__t319_ms400; + + // uac-BarringInfo + /*sib1->uac_BarringInfo = CALLOC(1, sizeof(struct NR_SIB1__uac_BarringInfo)); + NR_UAC_BarringInfoSet_t *nr_uac_BarringInfoSet = CALLOC(1, sizeof(NR_UAC_BarringInfoSet_t)); + asn_set_empty(&sib1->uac_BarringInfo->uac_BarringInfoSetList); + nr_uac_BarringInfoSet->uac_BarringFactor = NR_UAC_BarringInfoSet__uac_BarringFactor_p95; + nr_uac_BarringInfoSet->uac_BarringTime = NR_UAC_BarringInfoSet__uac_BarringTime_s4; + nr_uac_BarringInfoSet->uac_BarringForAccessIdentity.buf = CALLOC(1, 1); + nr_uac_BarringInfoSet->uac_BarringForAccessIdentity.size = 1; + nr_uac_BarringInfoSet->uac_BarringForAccessIdentity.bits_unused = 1; + ASN_SEQUENCE_ADD(&sib1->uac_BarringInfo->uac_BarringInfoSetList, nr_uac_BarringInfoSet);*/ + + // useFullResumeID + // TODO: add useFullResumeID + + // lateNonCriticalExtension + // TODO: add lateNonCriticalExtension + + // nonCriticalExtension + // TODO: add nonCriticalExtension + + xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1_message->message.choice.c1->choice.systemInformationBlockType1); + + if(carrier->SIB1 == NULL) carrier->SIB1=(uint8_t *) malloc16(NR_MAX_SIB_LENGTH/8); enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message, NULL, (void *)sib1_message, carrier->SIB1, - 100); + NR_MAX_SIB_LENGTH/8); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); @@ -355,6 +669,56 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, return((enc_rval.encoded+7)/8); } +uint8_t do_SIB23_NR(rrc_gNB_carrier_data_t *carrier, + gNB_RrcConfigurationReq *configuration) { + asn_enc_rval_t enc_rval; + SystemInformation_IEs__sib_TypeAndInfo__Member *sib2 = NULL; + SystemInformation_IEs__sib_TypeAndInfo__Member *sib3 = NULL; + + NR_BCCH_DL_SCH_Message_t *sib_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t)); + sib_message->message.present = NR_BCCH_DL_SCH_MessageType_PR_c1; + sib_message->message.choice.c1 = CALLOC(1,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1)); + sib_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation; + sib_message->message.choice.c1->choice.systemInformation = CALLOC(1,sizeof(struct NR_SystemInformation)); + + struct NR_SystemInformation *sib = sib_message->message.choice.c1->choice.systemInformation; + sib->criticalExtensions.present = NR_SystemInformation__criticalExtensions_PR_systemInformation; + sib->criticalExtensions.choice.systemInformation = CALLOC(1, sizeof(struct NR_SystemInformation_IEs)); + + struct NR_SystemInformation_IEs *ies = sib->criticalExtensions.choice.systemInformation; + sib2 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member)); + sib2->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2; + sib2->choice.sib2 = CALLOC(1, sizeof(struct NR_SIB2)); + sib2->choice.sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB1; + sib2->choice.sib2->cellReselectionServingFreqInfo.threshServingLowP = 2; // INTEGER (0..31) + sib2->choice.sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 2; // INTEGER (0..7) + sib2->choice.sib2->intraFreqCellReselectionInfo.q_RxLevMin = -50; // INTEGER (-70..-22) + sib2->choice.sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 2; // INTEGER (0..31) + sib2->choice.sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 2; // INTEGER (0..7) + sib2->choice.sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true; + ASN_SEQUENCE_ADD(&ies->sib_TypeAndInfo.list, sib2); + + sib3 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member)); + sib3->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3; + sib3->choice.sib3 = CALLOC(1, sizeof(struct NR_SIB3)); + ASN_SEQUENCE_ADD(&ies->sib_TypeAndInfo.list, sib3); + + //encode SIB to data + // carrier->SIB23 = (uint8_t *) malloc16(128); + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message, + NULL, + (void *)sib_message, + carrier->SIB23, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + if (enc_rval.encoded==-1) { + return(-1); + } + + return((enc_rval.encoded+7)/8); +} void do_RLC_BEARER(uint8_t Mod_id, int CC_id, @@ -578,3 +942,1397 @@ void do_SpCellConfig(gNB_RRC_INST *rrc, spconfig->reconfigurationWithSync = CALLOC(1,sizeof(struct NR_ReconfigurationWithSync)); } +//------------------------------------------------------------------------------ +uint8_t do_RRCReject(uint8_t Mod_id, + uint8_t *const buffer) +//------------------------------------------------------------------------------ +{ + asn_enc_rval_t enc_rval;; + NR_DL_CCCH_Message_t dl_ccch_msg; + NR_RRCReject_t *rrcReject; + NR_RejectWaitTime_t waitTime = 1; + + memset((void *)&dl_ccch_msg, 0, sizeof(NR_DL_CCCH_Message_t)); + dl_ccch_msg.message.present = NR_DL_CCCH_MessageType_PR_c1; + dl_ccch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_DL_CCCH_MessageType__c1)); + dl_ccch_msg.message.choice.c1->present = NR_RRCReject__criticalExtensions_PR_rrcReject; + + dl_ccch_msg.message.choice.c1->choice.rrcReject = CALLOC(1,sizeof(NR_RRCReject_t)); + rrcReject = dl_ccch_msg.message.choice.c1->choice.rrcReject; + + rrcReject->criticalExtensions.choice.rrcReject = CALLOC(1, sizeof(struct NR_RRCReject_IEs)); + rrcReject->criticalExtensions.choice.rrcReject->waitTime = CALLOC(1, sizeof(NR_RejectWaitTime_t)); + + rrcReject->criticalExtensions.present = NR_RRCReject__criticalExtensions_PR_rrcReject; + rrcReject->criticalExtensions.choice.rrcReject->waitTime = &waitTime; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_DL_CCCH_Message, (void *)&dl_ccch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_CCCH_Message, + NULL, + (void *)&dl_ccch_msg, + buffer, + 100); + + if(enc_rval.encoded == -1) { + LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + LOG_D(NR_RRC,"RRCReject Encoded %zd bits (%zd bytes)\n", + enc_rval.encoded,(enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); +} + +void fill_initial_SpCellConfig(rnti_t rnti, + NR_SpCellConfig_t *SpCellConfig, + NR_ServingCellConfigCommon_t *scc, + rrc_gNB_carrier_data_t *carrier) { + int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + SpCellConfig->servCellIndex = NULL; + SpCellConfig->reconfigurationWithSync = NULL; + SpCellConfig->rlmInSyncOutOfSyncThreshold = NULL; + SpCellConfig->rlf_TimersAndConstants = NULL; + SpCellConfig->spCellConfigDedicated = calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated)); + SpCellConfig->spCellConfigDedicated->uplinkConfig = calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated->uplinkConfig)); + NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1,sizeof(*initialUplinkBWP)); + SpCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP = initialUplinkBWP; + initialUplinkBWP->pucch_Config = calloc(1,sizeof(*initialUplinkBWP->pucch_Config)); + initialUplinkBWP->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup; + NR_PUCCH_Config_t *pucch_Config = calloc(1,sizeof(*pucch_Config)); + initialUplinkBWP->pucch_Config->choice.setup=pucch_Config; + pucch_Config->resourceSetToAddModList = calloc(1,sizeof(*pucch_Config->resourceSetToAddModList)); + pucch_Config->resourceSetToReleaseList = NULL; + NR_PUCCH_ResourceSet_t *pucchresset0=calloc(1,sizeof(*pucchresset0)); + pucchresset0->pucch_ResourceSetId = 0; + NR_PUCCH_ResourceId_t *pucchresset0id0=calloc(1,sizeof(*pucchresset0id0)); + *pucchresset0id0=0; + ASN_SEQUENCE_ADD(&pucchresset0->resourceList.list,pucchresset0id0); + pucchresset0->maxPayloadSize=NULL; + ASN_SEQUENCE_ADD(&pucch_Config->resourceSetToAddModList->list,pucchresset0); + + pucch_Config->resourceToAddModList = calloc(1,sizeof(*pucch_Config->resourceToAddModList)); + pucch_Config->resourceToReleaseList = NULL; + // configure one single PUCCH0 opportunity for initial connection procedure + // one symbol (13) + NR_PUCCH_Resource_t *pucchres0=calloc(1,sizeof(*pucchres0)); + pucchres0->pucch_ResourceId=0; + //pucchres0->startingPRB=0; + pucchres0->startingPRB=(8+rnti) % curr_bwp; + LOG_D(NR_RRC, "pucchres0->startPRB %ld rnti %d curr_bwp %d\n", pucchres0->startingPRB, rnti, curr_bwp); + pucchres0->intraSlotFrequencyHopping=NULL; + pucchres0->secondHopPRB=NULL; + pucchres0->format.present= NR_PUCCH_Resource__format_PR_format0; + pucchres0->format.choice.format0=calloc(1,sizeof(*pucchres0->format.choice.format0)); + pucchres0->format.choice.format0->initialCyclicShift=0; + pucchres0->format.choice.format0->nrofSymbols=1; + pucchres0->format.choice.format0->startingSymbolIndex=13; + ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres0); + initialUplinkBWP->pusch_Config = calloc(1,sizeof(*initialUplinkBWP->pusch_Config)); + initialUplinkBWP->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; + NR_PUSCH_Config_t *pusch_Config = calloc(1,sizeof(*pusch_Config)); + initialUplinkBWP->pusch_Config->choice.setup = pusch_Config; + pusch_Config->dataScramblingIdentityPUSCH = NULL; + pusch_Config->txConfig=calloc(1,sizeof(*pusch_Config->txConfig)); + *pusch_Config->txConfig= NR_PUSCH_Config__txConfig_codebook; + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA = NULL; + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + NR_DMRS_UplinkConfig->dmrs_Type = NULL; + NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NULL; /*calloc(1,sizeof(*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition)); + *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0;*/ + NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; + NR_DMRS_UplinkConfig->maxLength=NULL; + NR_DMRS_UplinkConfig->transformPrecodingDisabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingDisabled)); + NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0 = NULL; + NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1 = NULL; + NR_DMRS_UplinkConfig->transformPrecodingEnabled = NULL; + pusch_Config->pusch_PowerControl = calloc(1,sizeof(*pusch_Config->pusch_PowerControl)); + pusch_Config->pusch_PowerControl->tpc_Accumulation = NULL; + pusch_Config->pusch_PowerControl->msg3_Alpha = calloc(1,sizeof(*pusch_Config->pusch_PowerControl->msg3_Alpha)); + *pusch_Config->pusch_PowerControl->msg3_Alpha = NR_Alpha_alpha1; + pusch_Config->pusch_PowerControl->p0_NominalWithoutGrant = calloc(1,sizeof(*pusch_Config->pusch_PowerControl->p0_NominalWithoutGrant)); + *pusch_Config->pusch_PowerControl->p0_NominalWithoutGrant = -76; + pusch_Config->pusch_PowerControl->p0_AlphaSets = calloc(1,sizeof(*pusch_Config->pusch_PowerControl->p0_AlphaSets)); + NR_P0_PUSCH_AlphaSet_t *aset = calloc(1,sizeof(*aset)); + aset->p0_PUSCH_AlphaSetId=0; + aset->p0=calloc(1,sizeof(*aset->p0)); + *aset->p0 = 0; + aset->alpha=calloc(1,sizeof(*aset->alpha)); + *aset->alpha=NR_Alpha_alpha1; + ASN_SEQUENCE_ADD(&pusch_Config->pusch_PowerControl->p0_AlphaSets->list,aset); + pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList = calloc(1,sizeof(*pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList)); + NR_PUSCH_PathlossReferenceRS_t *plrefRS = calloc(1,sizeof(*plrefRS)); + plrefRS->pusch_PathlossReferenceRS_Id=0; + plrefRS->referenceSignal.present = NR_PathlossReferenceRS_Config_PR_ssb_Index; + plrefRS->referenceSignal.choice.ssb_Index = 0; + ASN_SEQUENCE_ADD(&pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList->list,plrefRS); + pusch_Config->pusch_PowerControl->pathlossReferenceRSToReleaseList = NULL; + pusch_Config->pusch_PowerControl->twoPUSCH_PC_AdjustmentStates = NULL; + pusch_Config->pusch_PowerControl->deltaMCS = NULL; + pusch_Config->pusch_PowerControl->sri_PUSCH_MappingToAddModList = calloc(1,sizeof(*pusch_Config->pusch_PowerControl->sri_PUSCH_MappingToAddModList)); + NR_SRI_PUSCH_PowerControl_t *sriPUSCHPC=calloc(1,sizeof(*sriPUSCHPC)); + sriPUSCHPC->sri_PUSCH_PowerControlId=0; + sriPUSCHPC->sri_PUSCH_PathlossReferenceRS_Id=0; + sriPUSCHPC->sri_P0_PUSCH_AlphaSetId=0; + sriPUSCHPC->sri_PUSCH_ClosedLoopIndex=NR_SRI_PUSCH_PowerControl__sri_PUSCH_ClosedLoopIndex_i0; + ASN_SEQUENCE_ADD(&pusch_Config->pusch_PowerControl->sri_PUSCH_MappingToAddModList->list,sriPUSCHPC); + pusch_Config->pusch_PowerControl->sri_PUSCH_MappingToReleaseList = NULL; + pusch_Config->frequencyHopping=NULL; + pusch_Config->frequencyHoppingOffsetLists=NULL; + pusch_Config->resourceAllocation = NR_PUSCH_Config__resourceAllocation_resourceAllocationType1; + pusch_Config->pusch_TimeDomainAllocationList = NULL; + pusch_Config->pusch_AggregationFactor=NULL; + pusch_Config->mcs_Table=NULL; + pusch_Config->mcs_TableTransformPrecoder=NULL; + pusch_Config->transformPrecoder= NULL; + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) { + pusch_Config->transformPrecoder=calloc(1,sizeof(*pusch_Config->transformPrecoder)); + *pusch_Config->transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; + } + pusch_Config->codebookSubset=calloc(1,sizeof(*pusch_Config->codebookSubset)); + *pusch_Config->codebookSubset = NR_PUSCH_Config__codebookSubset_nonCoherent; + pusch_Config->maxRank=calloc(1,sizeof(*pusch_Config->maxRank)); + *pusch_Config->maxRank= 1; + pusch_Config->rbg_Size=NULL; + pusch_Config->uci_OnPUSCH=NULL; + pusch_Config->tp_pi2BPSK=NULL; + + initialUplinkBWP->srs_Config = calloc(1,sizeof(*initialUplinkBWP->srs_Config)); + initialUplinkBWP->srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup; + NR_SRS_Config_t *srs_Config = calloc(1,sizeof(*srs_Config)); + initialUplinkBWP->srs_Config->choice.setup=srs_Config; + srs_Config->srs_ResourceSetToReleaseList=NULL; + srs_Config->srs_ResourceSetToAddModList=calloc(1,sizeof(*srs_Config->srs_ResourceSetToAddModList)); + NR_SRS_ResourceSet_t *srs_resset0=calloc(1,sizeof(*srs_resset0)); + srs_resset0->srs_ResourceSetId = 0; + srs_resset0->srs_ResourceIdList=calloc(1,sizeof(*srs_resset0->srs_ResourceIdList)); + NR_SRS_ResourceId_t *srs_resset0_id=calloc(1,sizeof(*srs_resset0_id)); + *srs_resset0_id=0; + ASN_SEQUENCE_ADD(&srs_resset0->srs_ResourceIdList->list,srs_resset0_id); + srs_Config->srs_ResourceToReleaseList=NULL; + srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_aperiodic; + srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic)); + srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1; + srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL; + srs_resset0->resourceType.choice.aperiodic->slotOffset= calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset)); + *srs_resset0->resourceType.choice.aperiodic->slotOffset=2; + srs_resset0->resourceType.choice.aperiodic->ext1=NULL; + srs_resset0->usage=NR_SRS_ResourceSet__usage_codebook; + srs_resset0->alpha = calloc(1,sizeof(*srs_resset0->alpha)); + *srs_resset0->alpha = NR_Alpha_alpha1; + srs_resset0->p0=calloc(1,sizeof(*srs_resset0->p0)); + *srs_resset0->p0=-80; + srs_resset0->pathlossReferenceRS=NULL; + srs_resset0->srs_PowerControlAdjustmentStates=NULL; + ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceSetToAddModList->list,srs_resset0); + srs_Config->srs_ResourceToReleaseList=NULL; + srs_Config->srs_ResourceToAddModList=calloc(1,sizeof(*srs_Config->srs_ResourceToAddModList)); + NR_SRS_Resource_t *srs_res0=calloc(1,sizeof(*srs_res0)); + srs_res0->srs_ResourceId=0; + srs_res0->nrofSRS_Ports=NR_SRS_Resource__nrofSRS_Ports_port1; + srs_res0->ptrs_PortIndex=NULL; + srs_res0->transmissionComb.present=NR_SRS_Resource__transmissionComb_PR_n2; + srs_res0->transmissionComb.choice.n2=calloc(1,sizeof(*srs_res0->transmissionComb.choice.n2)); + srs_res0->transmissionComb.choice.n2->combOffset_n2=0; + srs_res0->transmissionComb.choice.n2->cyclicShift_n2=0; + srs_res0->resourceMapping.startPosition=2; + srs_res0->resourceMapping.nrofSymbols=NR_SRS_Resource__resourceMapping__nrofSymbols_n1; + srs_res0->resourceMapping.repetitionFactor=NR_SRS_Resource__resourceMapping__repetitionFactor_n1; + srs_res0->freqDomainPosition=0; + srs_res0->freqDomainShift=0; + srs_res0->freqHopping.c_SRS = 0; + srs_res0->freqHopping.b_SRS=0; + srs_res0->freqHopping.b_hop=0; + srs_res0->groupOrSequenceHopping=NR_SRS_Resource__groupOrSequenceHopping_neither; + srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_aperiodic; + srs_res0->resourceType.choice.aperiodic=calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic)); + srs_res0->sequenceId=40; + srs_res0->spatialRelationInfo=calloc(1,sizeof(*srs_res0->spatialRelationInfo)); + srs_res0->spatialRelationInfo->servingCellId=NULL; + srs_res0->spatialRelationInfo->referenceSignal.present=NR_SRS_SpatialRelationInfo__referenceSignal_PR_csi_RS_Index; + srs_res0->spatialRelationInfo->referenceSignal.choice.csi_RS_Index=0; + ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceToAddModList->list,srs_res0); + + // configure Scheduling request + // 40 slot period + pucch_Config->schedulingRequestResourceToAddModList = calloc(1,sizeof(*pucch_Config->schedulingRequestResourceToAddModList)); + NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig = calloc(1,sizeof(*schedulingRequestResourceConfig)); + schedulingRequestResourceConfig->schedulingRequestResourceId = 1; + schedulingRequestResourceConfig->schedulingRequestID= 0; + schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset)); + schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40; + // note: make sure that there is no issue here. Later choose the RNTI accordingly. + // Here we would be limited to 3 UEs on this resource (1 1/2 Frames 30 kHz SCS, 5 ms TDD periodicity => slots 7,8,9). + // This should be a temporary resource until the first RRCReconfiguration gives new pucch resources. + // Check for above configuration and exit for now if it is not the case + AssertFatal(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing==NR_SubcarrierSpacing_kHz30, + "SCS != 30kHz\n"); + AssertFatal(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity==NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms5, + "TDD period != 5ms : %ld\n",scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); + + schedulingRequestResourceConfig->periodicityAndOffset->choice.sl40 = 8; + schedulingRequestResourceConfig->resource = calloc(1,sizeof(*schedulingRequestResourceConfig->resource)); + *schedulingRequestResourceConfig->resource = 0; + ASN_SEQUENCE_ADD(&pucch_Config->schedulingRequestResourceToAddModList->list,schedulingRequestResourceConfig); + + pucch_Config->dl_DataToUL_ACK = calloc(1,sizeof(*pucch_Config->dl_DataToUL_ACK)); + long *delay[8]; + for (int i=0;i<8;i++) { + delay[i] = calloc(1,sizeof(*delay[i])); + AssertFatal(carrier->minRXTXTIME >=2 && carrier->minRXTXTIME <7, + "check minRXTXTIME %d\n",carrier->minRXTXTIME); + *delay[i] = (i+carrier->minRXTXTIME); + ASN_SEQUENCE_ADD(&pucch_Config->dl_DataToUL_ACK->list,delay[i]); + } + + SpCellConfig->spCellConfigDedicated->initialDownlinkBWP = calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated->initialDownlinkBWP)); + NR_BWP_DownlinkDedicated_t *bwp_Dedicated = SpCellConfig->spCellConfigDedicated->initialDownlinkBWP; + bwp_Dedicated->pdcch_Config=calloc(1,sizeof(*bwp_Dedicated->pdcch_Config)); + bwp_Dedicated->pdcch_Config->present = NR_SetupRelease_PDCCH_Config_PR_setup; + bwp_Dedicated->pdcch_Config->choice.setup = calloc(1,sizeof(*bwp_Dedicated->pdcch_Config->choice.setup)); + + bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList = calloc(1,sizeof(*bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList)); + + bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList = calloc(1,sizeof(*bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList)); + + NR_ControlResourceSet_t *coreset = calloc(1,sizeof(*coreset)); + coreset->controlResourceSetId=1; + // frequency domain resources depends on BWP size + // options are 24, 48 or 96 + coreset->frequencyDomainResources.buf = calloc(1,6); + if (0) { + int curr_bwp = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + if (curr_bwp < 48) + coreset->frequencyDomainResources.buf[0] = 0xf0; + else + coreset->frequencyDomainResources.buf[0] = 0xff; + if (curr_bwp < 96) + coreset->frequencyDomainResources.buf[1] = 0; + else + coreset->frequencyDomainResources.buf[1] = 0xff; + } else { + coreset->frequencyDomainResources.buf[0] = 0xf0; + coreset->frequencyDomainResources.buf[1] = 0; + } + coreset->frequencyDomainResources.buf[2] = 0; + coreset->frequencyDomainResources.buf[3] = 0; + coreset->frequencyDomainResources.buf[4] = 0; + coreset->frequencyDomainResources.buf[5] = 0; + coreset->frequencyDomainResources.size = 6; + coreset->frequencyDomainResources.bits_unused = 3; + coreset->duration=1; + coreset->cce_REG_MappingType.present = NR_ControlResourceSet__cce_REG_MappingType_PR_nonInterleaved; + coreset->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; + + coreset->tci_StatesPDCCH_ToAddList=NULL; + coreset->tci_StatesPDCCH_ToReleaseList = NULL; + coreset->tci_PresentInDCI = NULL; + coreset->pdcch_DMRS_ScramblingID = NULL; + + ASN_SEQUENCE_ADD(&bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, + coreset); + + bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList = calloc(1,sizeof(*bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList)); + + NR_SearchSpace_t *ss2 = calloc(1,sizeof(*ss2)); + + ss2->searchSpaceId=2; + ss2->controlResourceSetId=calloc(1,sizeof(*ss2->controlResourceSetId)); + *ss2->controlResourceSetId=1; + ss2->monitoringSlotPeriodicityAndOffset=calloc(1,sizeof(*ss2->monitoringSlotPeriodicityAndOffset)); + ss2->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; + ss2->monitoringSlotPeriodicityAndOffset->choice.sl1=(NULL_t)0; + ss2->duration=NULL; + ss2->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss2->monitoringSymbolsWithinSlot)); + ss2->monitoringSymbolsWithinSlot->buf = calloc(1,2); + ss2->monitoringSymbolsWithinSlot->size = 2; + ss2->monitoringSymbolsWithinSlot->bits_unused = 2; + ss2->monitoringSymbolsWithinSlot->buf[0]=0x80; + ss2->monitoringSymbolsWithinSlot->buf[1]=0x0; + ss2->nrofCandidates=calloc(1,sizeof(*ss2->nrofCandidates)); + ss2->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss2->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n2; + ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + ss2->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; + ss2->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; + ss2->searchSpaceType=calloc(1,sizeof(*ss2->searchSpaceType)); + ss2->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + ss2->searchSpaceType->choice.ue_Specific = calloc(1,sizeof(*ss2->searchSpaceType->choice.ue_Specific)); + ss2->searchSpaceType->choice.ue_Specific->dci_Formats=NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_1_And_1_1; + + ASN_SEQUENCE_ADD(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, + ss2); + bwp_Dedicated->pdsch_Config=calloc(1,sizeof(*bwp_Dedicated->pdsch_Config)); + bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; + bwp_Dedicated->pdsch_Config->choice.setup = calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup)); + bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; + bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); + bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; + bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + + bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=NULL; + bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL; + + bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); + *bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1; + bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation = NR_PDSCH_Config__resourceAllocation_resourceAllocationType1; + bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; + bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling = calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling)); + bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize = + calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize)); + *bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize = NR_PDSCH_Config__prb_BundlingType__staticBundling__bundleSize_wideband; + + bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList)); + NR_TCI_State_t *tcic; + + tcic=calloc(1,sizeof(*tcic)); + tcic->tci_StateId=0; + tcic->qcl_Type1.cell=NULL; + tcic->qcl_Type1.bwp_Id=NULL; + tcic->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; + tcic->qcl_Type1.referenceSignal.choice.ssb = 0; + tcic->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeD; + + ASN_SEQUENCE_ADD(&bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcic); + + SpCellConfig->spCellConfigDedicated->tag_Id=0; + SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig=calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig)); + NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig = calloc(1,sizeof(*pdsch_servingcellconfig)); + SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->present = NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup; + SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig; + pdsch_servingcellconfig->codeBlockGroupTransmission = NULL; + pdsch_servingcellconfig->xOverhead = NULL; + pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = calloc(1, sizeof(*pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH)); + *pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16; + pdsch_servingcellconfig->pucch_Cell= NULL; + pdsch_servingcellconfig->ext1=calloc(1,sizeof(*pdsch_servingcellconfig->ext1)); + pdsch_servingcellconfig->ext1->maxMIMO_Layers = calloc(1,sizeof(*pdsch_servingcellconfig->ext1->maxMIMO_Layers)); + *pdsch_servingcellconfig->ext1->maxMIMO_Layers = 2; + +} + +void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGroupConfig_t *ue_context_mastercellGroup) { + + cellGroupConfig->cellGroupId = 0; + cellGroupConfig->rlc_BearerToReleaseList = NULL; + cellGroupConfig->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList)); + + // RLC Bearer Config + // TS38.331 9.2.1 Default SRB configurations + NR_RLC_BearerConfig_t *rlc_BearerConfig = NULL; + NR_RLC_Config_t *rlc_Config = NULL; + NR_LogicalChannelConfig_t *logicalChannelConfig = NULL; + long *logicalChannelGroup = NULL; + rlc_BearerConfig = calloc(1, sizeof(NR_RLC_BearerConfig_t)); + rlc_BearerConfig->logicalChannelIdentity = 2; + rlc_BearerConfig->servedRadioBearer = calloc(1, sizeof(*rlc_BearerConfig->servedRadioBearer)); + rlc_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity; + rlc_BearerConfig->servedRadioBearer->choice.srb_Identity = 2; + rlc_BearerConfig->reestablishRLC = NULL; + rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); + rlc_Config->present = NR_RLC_Config_PR_am; + rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am)); + rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength) = NR_SN_FieldLengthAM_size12; + rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms35; + rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms0; + rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength) = NR_SN_FieldLengthAM_size12; + rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; + rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_infinity; + rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_infinity; + rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t8; + rlc_BearerConfig->rlc_Config = rlc_Config; + logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t)); + logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters)); + logicalChannelConfig->ul_SpecificParameters->priority = 3; + logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5; + logicalChannelGroup = CALLOC(1, sizeof(long)); + *logicalChannelGroup = 0; + logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = logicalChannelGroup; + logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = CALLOC(1, sizeof(*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID)); + *logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = 0; + logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = 0; + logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = 0; + rlc_BearerConfig->mac_LogicalChannelConfig = logicalChannelConfig; + ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); + ASN_SEQUENCE_ADD(&ue_context_mastercellGroup->rlc_BearerToAddModList->list, rlc_BearerConfig); + + // DRB Configuration + NR_RLC_BearerConfig_t *rlc_BearerConfig_drb = NULL; + NR_RLC_Config_t *rlc_Config_drb = NULL; + NR_LogicalChannelConfig_t *logicalChannelConfig_drb = NULL; + long *logicalChannelGroup_drb = NULL; + rlc_BearerConfig_drb = calloc(1, sizeof(NR_RLC_BearerConfig_t)); + rlc_BearerConfig_drb->logicalChannelIdentity = 4; + rlc_BearerConfig_drb->servedRadioBearer = calloc(1, sizeof(*rlc_BearerConfig_drb->servedRadioBearer)); + rlc_BearerConfig_drb->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity; + rlc_BearerConfig_drb->servedRadioBearer->choice.drb_Identity = 1; + rlc_BearerConfig_drb->reestablishRLC = NULL; + rlc_Config_drb = calloc(1, sizeof(NR_RLC_Config_t)); + rlc_Config_drb->present = NR_RLC_Config_PR_am; + rlc_Config_drb->choice.am = calloc(1, sizeof(*rlc_Config_drb->choice.am)); + rlc_Config_drb->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config_drb->choice.am->dl_AM_RLC.sn_FieldLength) = NR_SN_FieldLengthAM_size18; + rlc_Config_drb->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms80; + rlc_Config_drb->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms10; + rlc_Config_drb->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config_drb->choice.am->ul_AM_RLC.sn_FieldLength) = NR_SN_FieldLengthAM_size18; + rlc_Config_drb->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms80; + rlc_Config_drb->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64; + rlc_Config_drb->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB125; + rlc_Config_drb->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t8; + rlc_BearerConfig_drb->rlc_Config = rlc_Config_drb; + logicalChannelConfig_drb = calloc(1, sizeof(NR_LogicalChannelConfig_t)); + logicalChannelConfig_drb->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig_drb->ul_SpecificParameters)); + logicalChannelConfig_drb->ul_SpecificParameters->priority = 13; + logicalChannelConfig_drb->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8; + logicalChannelConfig_drb->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms100; + logicalChannelGroup_drb = CALLOC(1, sizeof(long)); + *logicalChannelGroup_drb = 1; + logicalChannelConfig_drb->ul_SpecificParameters->logicalChannelGroup = logicalChannelGroup_drb; + logicalChannelConfig_drb->ul_SpecificParameters->schedulingRequestID = CALLOC(1, sizeof(*logicalChannelConfig_drb->ul_SpecificParameters->schedulingRequestID)); + *logicalChannelConfig_drb->ul_SpecificParameters->schedulingRequestID = 0; + logicalChannelConfig_drb->ul_SpecificParameters->logicalChannelSR_Mask = 0; + logicalChannelConfig_drb->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = 0; + rlc_BearerConfig_drb->mac_LogicalChannelConfig = logicalChannelConfig_drb; + ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig_drb); + ASN_SEQUENCE_ADD(&ue_context_mastercellGroup->rlc_BearerToAddModList->list, rlc_BearerConfig_drb); +} + +void fill_initial_cellGroupConfig(rnti_t rnti, + NR_CellGroupConfig_t *cellGroupConfig, + NR_ServingCellConfigCommon_t *scc, + rrc_gNB_carrier_data_t *carrier) { + + NR_RLC_BearerConfig_t *rlc_BearerConfig = NULL; + NR_RLC_Config_t *rlc_Config = NULL; + NR_LogicalChannelConfig_t *logicalChannelConfig = NULL; + NR_MAC_CellGroupConfig_t *mac_CellGroupConfig = NULL; + NR_PhysicalCellGroupConfig_t *physicalCellGroupConfig = NULL; + long *logicalChannelGroup = NULL; + + cellGroupConfig->cellGroupId = 0; + + /* Rlc Bearer Config */ + /* TS38.331 9.2.1 Default SRB configurations */ + cellGroupConfig->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList)); + rlc_BearerConfig = calloc(1, sizeof(NR_RLC_BearerConfig_t)); + rlc_BearerConfig->logicalChannelIdentity = 1; + rlc_BearerConfig->servedRadioBearer = calloc(1, sizeof(*rlc_BearerConfig->servedRadioBearer)); + rlc_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity; + rlc_BearerConfig->servedRadioBearer->choice.srb_Identity = 1; + rlc_BearerConfig->reestablishRLC = NULL; + rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); + rlc_Config->present = NR_RLC_Config_PR_am; + rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am)); + rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength) = NR_SN_FieldLengthAM_size12; + rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms35; + rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms0; + rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength) = NR_SN_FieldLengthAM_size12; + rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; + rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_infinity; + rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_infinity; + rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t8; + rlc_BearerConfig->rlc_Config = rlc_Config; + logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t)); + logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters)); + logicalChannelConfig->ul_SpecificParameters->priority = 1; + logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + logicalChannelGroup = CALLOC(1, sizeof(long)); + *logicalChannelGroup = 0; + logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = logicalChannelGroup; + logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = CALLOC(1, sizeof(*logicalChannelConfig->ul_SpecificParameters->schedulingRequestID)); + *logicalChannelConfig->ul_SpecificParameters->schedulingRequestID = 0; + logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = 0; + logicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = 0; + rlc_BearerConfig->mac_LogicalChannelConfig = logicalChannelConfig; + ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); + + cellGroupConfig->rlc_BearerToReleaseList = NULL; + + /* mac CellGroup Config */ + if (1) { + mac_CellGroupConfig = calloc(1, sizeof(*mac_CellGroupConfig)); + if (1) { + mac_CellGroupConfig->schedulingRequestConfig = calloc(1, sizeof(*mac_CellGroupConfig->schedulingRequestConfig)); + mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList = CALLOC(1,sizeof(*mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList)); + struct NR_SchedulingRequestToAddMod *schedulingrequestlist; + schedulingrequestlist = CALLOC(1,sizeof(*schedulingrequestlist)); + schedulingrequestlist->schedulingRequestId = 0; + schedulingrequestlist->sr_ProhibitTimer = CALLOC(1,sizeof(*schedulingrequestlist->sr_ProhibitTimer)); + *(schedulingrequestlist->sr_ProhibitTimer) = 0; + schedulingrequestlist->sr_TransMax = NR_SchedulingRequestToAddMod__sr_TransMax_n64; + ASN_SEQUENCE_ADD(&(mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList->list),schedulingrequestlist); + } + mac_CellGroupConfig->bsr_Config = calloc(1, sizeof(*mac_CellGroupConfig->bsr_Config)); + mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10; + mac_CellGroupConfig->bsr_Config->retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf80; + mac_CellGroupConfig->tag_Config = calloc(1, sizeof(*mac_CellGroupConfig->tag_Config)); + mac_CellGroupConfig->tag_Config->tag_ToReleaseList = NULL; + mac_CellGroupConfig->tag_Config->tag_ToAddModList = calloc(1,sizeof(*mac_CellGroupConfig->tag_Config->tag_ToAddModList)); + struct NR_TAG *tag=calloc(1,sizeof(*tag)); + tag->tag_Id = 0; + tag->timeAlignmentTimer = NR_TimeAlignmentTimer_infinity; + ASN_SEQUENCE_ADD(&mac_CellGroupConfig->tag_Config->tag_ToAddModList->list,tag); + mac_CellGroupConfig->phr_Config = calloc(1, sizeof(*mac_CellGroupConfig->phr_Config)); + mac_CellGroupConfig->phr_Config->present = NR_SetupRelease_PHR_Config_PR_setup; + mac_CellGroupConfig->phr_Config->choice.setup = calloc(1, sizeof(*mac_CellGroupConfig->phr_Config->choice.setup)); + mac_CellGroupConfig->phr_Config->choice.setup->phr_PeriodicTimer = NR_PHR_Config__phr_PeriodicTimer_sf10; + mac_CellGroupConfig->phr_Config->choice.setup->phr_ProhibitTimer = NR_PHR_Config__phr_ProhibitTimer_sf10; + mac_CellGroupConfig->phr_Config->choice.setup->phr_Tx_PowerFactorChange = NR_PHR_Config__phr_Tx_PowerFactorChange_dB1; + } + cellGroupConfig->mac_CellGroupConfig = mac_CellGroupConfig; + + physicalCellGroupConfig = calloc(1,sizeof(*physicalCellGroupConfig)); + physicalCellGroupConfig->p_NR_FR1 = calloc(1,sizeof(*physicalCellGroupConfig->p_NR_FR1)); + *physicalCellGroupConfig->p_NR_FR1 = 10; + physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook = NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic; + cellGroupConfig->physicalCellGroupConfig = physicalCellGroupConfig; + + cellGroupConfig->spCellConfig = calloc(1,sizeof(*cellGroupConfig->spCellConfig)); + + fill_initial_SpCellConfig(rnti,cellGroupConfig->spCellConfig,scc,carrier); + + cellGroupConfig->sCellToAddModList = NULL; + cellGroupConfig->sCellToReleaseList = NULL; +} + +//------------------------------------------------------------------------------ +uint8_t do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t *const buffer, + const uint8_t transaction_id, + OCTET_STRING_t *masterCellGroup_from_DU, + NR_ServingCellConfigCommon_t *scc, + rrc_gNB_carrier_data_t *carrier) +//------------------------------------------------------------------------------ +{ + asn_enc_rval_t enc_rval; + NR_DL_CCCH_Message_t dl_ccch_msg; + NR_RRCSetup_t *rrcSetup; + NR_RRCSetup_IEs_t *ie; + NR_SRB_ToAddMod_t *SRB1_config = NULL; + NR_PDCP_Config_t *pdcp_Config = NULL; + NR_CellGroupConfig_t *cellGroupConfig = NULL; + char masterCellGroup_buf[1000]; + + AssertFatal(ue_context_pP != NULL,"ue_context_p is null\n"); + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + NR_SRB_ToAddModList_t **SRB_configList = &ue_p->SRB_configList; + + + + memset((void *)&dl_ccch_msg, 0, sizeof(NR_DL_CCCH_Message_t)); + dl_ccch_msg.message.present = NR_DL_CCCH_MessageType_PR_c1; + dl_ccch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_DL_CCCH_MessageType__c1)); + dl_ccch_msg.message.choice.c1->present = NR_DL_CCCH_MessageType__c1_PR_rrcSetup; + dl_ccch_msg.message.choice.c1->choice.rrcSetup = calloc(1, sizeof(NR_RRCSetup_t)); + + rrcSetup = dl_ccch_msg.message.choice.c1->choice.rrcSetup; + rrcSetup->criticalExtensions.present = NR_RRCSetup__criticalExtensions_PR_rrcSetup; + rrcSetup->rrc_TransactionIdentifier = transaction_id; + rrcSetup->criticalExtensions.choice.rrcSetup = calloc(1, sizeof(NR_RRCSetup_IEs_t)); + ie = rrcSetup->criticalExtensions.choice.rrcSetup; + + /****************************** radioBearerConfig ******************************/ + + /* Configure SRB1 */ + if (*SRB_configList) { + free(*SRB_configList); + } + + *SRB_configList = calloc(1, sizeof(NR_SRB_ToAddModList_t)); + // SRB1 + /* TODO */ + SRB1_config = calloc(1, sizeof(NR_SRB_ToAddMod_t)); + SRB1_config->srb_Identity = 1; + // pdcp_Config->t_Reordering + SRB1_config->pdcp_Config = pdcp_Config; + ie->radioBearerConfig.srb_ToAddModList = *SRB_configList; + ASN_SEQUENCE_ADD(&(*SRB_configList)->list, SRB1_config); + + ie->radioBearerConfig.srb3_ToRelease = NULL; + ie->radioBearerConfig.drb_ToAddModList = NULL; + ie->radioBearerConfig.drb_ToReleaseList = NULL; + ie->radioBearerConfig.securityConfig = NULL; + + /****************************** masterCellGroup ******************************/ + /* TODO */ + if (masterCellGroup_from_DU) { + memcpy(&ie->masterCellGroup,masterCellGroup_from_DU,sizeof(*masterCellGroup_from_DU)); + // decode masterCellGroup OCTET_STRING received from DU and place in ue context + uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, //might be added prefix later + (void **)&cellGroupConfig, + (uint8_t *)masterCellGroup_from_DU->buf, + masterCellGroup_from_DU->size, 0, 0); + + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)cellGroupConfig); + } + else { + cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t)); + fill_initial_cellGroupConfig(ue_context_pP->ue_context.rnti,cellGroupConfig,scc,carrier); + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, + NULL, + (void *)cellGroupConfig, + masterCellGroup_buf, + 1000); + + if(enc_rval.encoded == -1) { + LOG_E(NR_RRC, "ASN1 message CellGroupConfig encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + if (OCTET_STRING_fromBuf(&ie->masterCellGroup, masterCellGroup_buf, (enc_rval.encoded+7)/8) == -1) { + LOG_E(NR_RRC, "fatal: OCTET_STRING_fromBuf failed\n"); + return -1; + } + } + + ue_p->masterCellGroup = cellGroupConfig; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_DL_CCCH_Message, (void *)&dl_ccch_msg); + } + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_CCCH_Message, + NULL, + (void *)&dl_ccch_msg, + buffer, + 1000); + + if(enc_rval.encoded == -1) { + LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + LOG_D(NR_RRC,"RRCSetup Encoded %zd bits (%zd bytes)\n", + enc_rval.encoded,(enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); +} + +uint8_t do_NR_SecurityModeCommand( + const protocol_ctxt_t *const ctxt_pP, + uint8_t *const buffer, + const uint8_t Transaction_id, + const uint8_t cipheringAlgorithm, + NR_IntegrityProtAlgorithm_t *integrityProtAlgorithm +) +//------------------------------------------------------------------------------ +{ + NR_DL_DCCH_Message_t dl_dcch_msg; + asn_enc_rval_t enc_rval; + memset(&dl_dcch_msg,0,sizeof(NR_DL_DCCH_Message_t)); + dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; + dl_dcch_msg.message.choice.c1=CALLOC(1,sizeof(struct NR_DL_DCCH_MessageType__c1)); + dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_securityModeCommand; + dl_dcch_msg.message.choice.c1->choice.securityModeCommand = CALLOC(1, sizeof(struct NR_SecurityModeCommand)); + dl_dcch_msg.message.choice.c1->choice.securityModeCommand->rrc_TransactionIdentifier = Transaction_id; + dl_dcch_msg.message.choice.c1->choice.securityModeCommand->criticalExtensions.present = NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand; + + dl_dcch_msg.message.choice.c1->choice.securityModeCommand->criticalExtensions.choice.securityModeCommand = + CALLOC(1, sizeof(struct NR_SecurityModeCommand_IEs)); + // the two following information could be based on the mod_id + dl_dcch_msg.message.choice.c1->choice.securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm + = (NR_CipheringAlgorithm_t)cipheringAlgorithm; + dl_dcch_msg.message.choice.c1->choice.securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm + = integrityProtAlgorithm; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, + NULL, + (void *)&dl_dcch_msg, + buffer, + 100); + + if(enc_rval.encoded == -1) { + LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + LOG_D(NR_RRC,"[gNB %d] securityModeCommand for UE %x Encoded %zd bits (%zd bytes)\n", + ctxt_pP->module_id, + ctxt_pP->rnti, + enc_rval.encoded, + (enc_rval.encoded+7)/8); + + if (enc_rval.encoded==-1) { + LOG_E(NR_RRC,"[gNB %d] ASN1 : securityModeCommand encoding failed for UE %x\n", + ctxt_pP->module_id, + ctxt_pP->rnti); + return(-1); + } + + // rrc_ue_process_ueCapabilityEnquiry(0,1000,&dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry,0); + // exit(-1); + return((enc_rval.encoded+7)/8); +} + +/*TODO*/ +//------------------------------------------------------------------------------ +uint8_t do_NR_SA_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, + uint8_t *const buffer, + const uint8_t Transaction_id) +//------------------------------------------------------------------------------ +{ + NR_UE_CapabilityRequestFilterNR_t *sa_band_filter; + NR_FreqBandList_t *sa_band_list; + NR_FreqBandInformation_t *sa_band_info; + NR_FreqBandInformationNR_t *sa_band_infoNR; + + NR_DL_DCCH_Message_t dl_dcch_msg; + NR_UE_CapabilityRAT_Request_t *ue_capabilityrat_request; + + asn_enc_rval_t enc_rval; + memset(&dl_dcch_msg,0,sizeof(NR_DL_DCCH_Message_t)); + dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; + dl_dcch_msg.message.choice.c1 = CALLOC(1,sizeof(struct NR_DL_DCCH_MessageType__c1)); + dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry; + dl_dcch_msg.message.choice.c1->choice.ueCapabilityEnquiry = CALLOC(1,sizeof(struct NR_UECapabilityEnquiry)); + dl_dcch_msg.message.choice.c1->choice.ueCapabilityEnquiry->rrc_TransactionIdentifier = Transaction_id; + dl_dcch_msg.message.choice.c1->choice.ueCapabilityEnquiry->criticalExtensions.present = NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry; + dl_dcch_msg.message.choice.c1->choice.ueCapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry = CALLOC(1,sizeof(struct NR_UECapabilityEnquiry_IEs)); + ue_capabilityrat_request = CALLOC(1,sizeof(NR_UE_CapabilityRAT_Request_t)); + memset(ue_capabilityrat_request,0,sizeof(NR_UE_CapabilityRAT_Request_t)); + ue_capabilityrat_request->rat_Type = NR_RAT_Type_nr; + + sa_band_infoNR = (NR_FreqBandInformationNR_t*)calloc(1,sizeof(NR_FreqBandInformationNR_t)); + sa_band_infoNR->bandNR = 78; + sa_band_info = (NR_FreqBandInformation_t*)calloc(1,sizeof(NR_FreqBandInformation_t)); + sa_band_info->present = NR_FreqBandInformation_PR_bandInformationNR; + sa_band_info->choice.bandInformationNR = sa_band_infoNR; + + sa_band_list = (NR_FreqBandList_t *)calloc(1, sizeof(NR_FreqBandList_t)); + ASN_SEQUENCE_ADD(&sa_band_list->list, sa_band_info); + + sa_band_filter = (NR_UE_CapabilityRequestFilterNR_t*)calloc(1,sizeof(NR_UE_CapabilityRequestFilterNR_t)); + sa_band_filter->frequencyBandListFilter = sa_band_list; + + OCTET_STRING_t req_freq; + unsigned char req_freq_buf[1024]; + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_CapabilityRequestFilterNR, + NULL, + (void *)sa_band_filter, + req_freq_buf, + 1024); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UE_CapabilityRequestFilterNR, (void *)sa_band_filter); + } + + req_freq.buf = req_freq_buf; + req_freq.size = (enc_rval.encoded+7)/8; + + ue_capabilityrat_request->capabilityRequestFilter = &req_freq; + + ASN_SEQUENCE_ADD(&dl_dcch_msg.message.choice.c1->choice.ueCapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry->ue_CapabilityRAT_RequestList.list, + ue_capabilityrat_request); + + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, + NULL, + (void *)&dl_dcch_msg, + buffer, + 100); + + if(enc_rval.encoded == -1) { + LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + LOG_D(NR_RRC,"[gNB %d] NR UECapabilityRequest for UE %x Encoded %zd bits (%zd bytes)\n", + ctxt_pP->module_id, + ctxt_pP->rnti, + enc_rval.encoded, + (enc_rval.encoded+7)/8); + + if (enc_rval.encoded==-1) { + LOG_E(NR_RRC,"[gNB %d] ASN1 : NR UECapabilityRequest encoding failed for UE %x\n", + ctxt_pP->module_id, + ctxt_pP->rnti); + return(-1); + } + + return((enc_rval.encoded+7)/8); +} + + +uint8_t do_NR_RRCRelease(uint8_t *buffer, + uint8_t Transaction_id) { + asn_enc_rval_t enc_rval; + NR_DL_DCCH_Message_t dl_dcch_msg; + NR_RRCRelease_t *rrcConnectionRelease; + memset(&dl_dcch_msg,0,sizeof(NR_DL_DCCH_Message_t)); + dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; + dl_dcch_msg.message.choice.c1=CALLOC(1,sizeof(struct NR_DL_DCCH_MessageType__c1)); + dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcRelease; + dl_dcch_msg.message.choice.c1->choice.rrcRelease = CALLOC(1, sizeof(NR_RRCRelease_t)); + rrcConnectionRelease = dl_dcch_msg.message.choice.c1->choice.rrcRelease; + // RRCConnectionRelease + rrcConnectionRelease->rrc_TransactionIdentifier = Transaction_id; + rrcConnectionRelease->criticalExtensions.present = NR_RRCRelease__criticalExtensions_PR_rrcRelease; + rrcConnectionRelease->criticalExtensions.choice.rrcRelease = CALLOC(1, sizeof(NR_RRCRelease_IEs_t)); + rrcConnectionRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq = + CALLOC(1, sizeof(struct NR_RRCRelease_IEs__deprioritisationReq)); + rrcConnectionRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationType = + NR_RRCRelease_IEs__deprioritisationReq__deprioritisationType_nr; + rrcConnectionRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationTimer = + NR_RRCRelease_IEs__deprioritisationReq__deprioritisationTimer_min10; + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, + NULL, + (void *)&dl_dcch_msg, + buffer, + RRC_BUF_SIZE); + if(enc_rval.encoded == -1) { + LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + return((enc_rval.encoded+7)/8); +} + +//------------------------------------------------------------------------------ +int16_t do_RRCReconfiguration( + const protocol_ctxt_t *const ctxt_pP, + uint8_t *buffer, + uint8_t Transaction_id, + NR_SRB_ToAddModList_t *SRB_configList, + NR_DRB_ToAddModList_t *DRB_configList, + NR_DRB_ToReleaseList_t *DRB_releaseList, + NR_SecurityConfig_t *security_config, + NR_SDAP_Config_t *sdap_config, + NR_MeasConfig_t *meas_config, + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList, + NR_MAC_CellGroupConfig_t *mac_CellGroupConfig, + NR_CellGroupConfig_t *cellGroupConfig) +//------------------------------------------------------------------------------ +{ + NR_DL_DCCH_Message_t dl_dcch_msg; + asn_enc_rval_t enc_rval; + NR_RRCReconfiguration_IEs_t *ie; + unsigned char masterCellGroup_buf[1000]; + + memset(&dl_dcch_msg, 0, sizeof(NR_DL_DCCH_Message_t)); + dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; + dl_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_DL_DCCH_MessageType__c1)); + dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + + dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration = calloc(1, sizeof(NR_RRCReconfiguration_t)); + dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->rrc_TransactionIdentifier = Transaction_id; + dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; + + /******************** Radio Bearer Config ********************/ + /* Configure Security */ + // security_config = CALLOC(1, sizeof(NR_SecurityConfig_t)); + // security_config->securityAlgorithmConfig = CALLOC(1, sizeof(*ie->radioBearerConfig->securityConfig->securityAlgorithmConfig)); + // security_config->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; + // security_config->securityAlgorithmConfig->integrityProtAlgorithm = NULL; + // security_config->keyToUse = CALLOC(1, sizeof(*ie->radioBearerConfig->securityConfig->keyToUse)); + // *security_config->keyToUse = NR_SecurityConfig__keyToUse_master; + + ie = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t)); + if (SRB_configList || DRB_configList) { + ie->radioBearerConfig = calloc(1, sizeof(NR_RadioBearerConfig_t)); + ie->radioBearerConfig->srb_ToAddModList = SRB_configList; + ie->radioBearerConfig->drb_ToAddModList = DRB_configList; + ie->radioBearerConfig->securityConfig = security_config; + ie->radioBearerConfig->srb3_ToRelease = NULL; + ie->radioBearerConfig->drb_ToReleaseList = DRB_releaseList; + } + /******************** Secondary Cell Group ********************/ + // rrc_gNB_carrier_data_t *carrier = &(gnb_rrc_inst->carrier); + // fill_default_secondaryCellGroup( carrier->servingcellconfigcommon, + // ue_context_pP->ue_context.secondaryCellGroup, + // 1, + // 1, + // carrier->pdsch_AntennaPorts, + // carrier->initial_csi_index[ue_context_p->local_uid + 1], + // ue_context_pP->local_uid); + + /******************** Meas Config ********************/ + // measConfig + ie->measConfig = meas_config; + // lateNonCriticalExtension + ie->lateNonCriticalExtension = NULL; + // nonCriticalExtension + + if (cellGroupConfig || dedicatedNAS_MessageList) { + ie->nonCriticalExtension = calloc(1, sizeof(NR_RRCReconfiguration_v1530_IEs_t)); + if (dedicatedNAS_MessageList) + ie->nonCriticalExtension->dedicatedNAS_MessageList = dedicatedNAS_MessageList; + } + + if(cellGroupConfig!=NULL){ + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, + NULL, + (void *)cellGroupConfig, + masterCellGroup_buf, + 1000); + if(enc_rval.encoded == -1) { + LOG_E(NR_RRC, "ASN1 message CellGroupConfig encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)cellGroupConfig); + ie->nonCriticalExtension->masterCellGroup = calloc(1,sizeof(OCTET_STRING_t)); + + ie->nonCriticalExtension->masterCellGroup->buf = masterCellGroup_buf; + ie->nonCriticalExtension->masterCellGroup->size = (enc_rval.encoded+7)/8; + } + + dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie; + + //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg); + //} + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, + NULL, + (void *)&dl_dcch_msg, + buffer, + 1000); + + if(enc_rval.encoded == -1) { + LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + LOG_D(NR_RRC,"[gNB %d] RRCReconfiguration for UE %x Encoded %zd bits (%zd bytes)\n", + ctxt_pP->module_id, + ctxt_pP->rnti, + enc_rval.encoded, + (enc_rval.encoded+7)/8); + + if (enc_rval.encoded == -1) { + LOG_E(NR_RRC,"[gNB %d] ASN1 : RRCReconfiguration encoding failed for UE %x\n", + ctxt_pP->module_id, + ctxt_pP->rnti); + return(-1); + } + + return((enc_rval.encoded+7)/8); +} + + +uint8_t do_RRCSetupRequest(uint8_t Mod_id, uint8_t *buffer,uint8_t *rv) { + asn_enc_rval_t enc_rval; + uint8_t buf[5],buf2=0; + NR_UL_CCCH_Message_t ul_ccch_msg; + NR_RRCSetupRequest_t *rrcSetupRequest; + memset((void *)&ul_ccch_msg,0,sizeof(NR_UL_CCCH_Message_t)); + ul_ccch_msg.message.present = NR_UL_CCCH_MessageType_PR_c1; + ul_ccch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_CCCH_MessageType__c1)); + ul_ccch_msg.message.choice.c1->present = NR_UL_CCCH_MessageType__c1_PR_rrcSetupRequest; + ul_ccch_msg.message.choice.c1->choice.rrcSetupRequest = CALLOC(1, sizeof(NR_RRCSetupRequest_t)); + rrcSetupRequest = ul_ccch_msg.message.choice.c1->choice.rrcSetupRequest; + + + if (1) { + rrcSetupRequest->rrcSetupRequest.ue_Identity.present = NR_InitialUE_Identity_PR_randomValue; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue.size = 5; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue.bits_unused = 1; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue.buf = buf; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue.buf[0] = rv[0]; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue.buf[1] = rv[1]; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue.buf[2] = rv[2]; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue.buf[3] = rv[3]; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue.buf[4] = rv[4]&0xfe; + } else { + rrcSetupRequest->rrcSetupRequest.ue_Identity.present = NR_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.ng_5G_S_TMSI_Part1.size = 1; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.ng_5G_S_TMSI_Part1.bits_unused = 0; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.ng_5G_S_TMSI_Part1.buf = buf; + rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.ng_5G_S_TMSI_Part1.buf[0] = 0x12; + } + + rrcSetupRequest->rrcSetupRequest.establishmentCause = NR_EstablishmentCause_mo_Signalling; //EstablishmentCause_mo_Data; + rrcSetupRequest->rrcSetupRequest.spare.buf = &buf2; + rrcSetupRequest->rrcSetupRequest.spare.size=1; + rrcSetupRequest->rrcSetupRequest.spare.bits_unused = 7; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_CCCH_Message, (void *)&ul_ccch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_CCCH_Message, + NULL, + (void *)&ul_ccch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(NR_RRC,"[UE] RRCSetupRequest Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); +} +//------------------------------------------------------------------------------ +uint8_t +do_NR_RRCReconfigurationComplete( + const protocol_ctxt_t *const ctxt_pP, + uint8_t *buffer, + const uint8_t Transaction_id +) +//------------------------------------------------------------------------------ +{ + asn_enc_rval_t enc_rval; + NR_UL_DCCH_Message_t ul_dcch_msg; + NR_RRCReconfigurationComplete_t *rrcReconfigurationComplete; + memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + ul_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_DCCH_MessageType__c1)); + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_rrcReconfigurationComplete; + ul_dcch_msg.message.choice.c1->choice.rrcReconfigurationComplete = CALLOC(1, sizeof(NR_RRCReconfigurationComplete_t)); + rrcReconfigurationComplete = ul_dcch_msg.message.choice.c1->choice.rrcReconfigurationComplete; + rrcReconfigurationComplete->rrc_TransactionIdentifier = Transaction_id; + rrcReconfigurationComplete->criticalExtensions.choice.rrcReconfigurationComplete = CALLOC(1, sizeof(NR_RRCReconfigurationComplete_IEs_t)); + rrcReconfigurationComplete->criticalExtensions.present = + NR_RRCReconfigurationComplete__criticalExtensions_PR_rrcReconfigurationComplete; + rrcReconfigurationComplete->criticalExtensions.choice.rrcReconfigurationComplete->nonCriticalExtension = NULL; + rrcReconfigurationComplete->criticalExtensions.choice.rrcReconfigurationComplete->lateNonCriticalExtension = NULL; + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, + NULL, + (void *)&ul_dcch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + LOG_I(NR_RRC,"rrcReconfigurationComplete Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); +} + +uint8_t do_RRCSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, uint8_t sel_plmn_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS){ + asn_enc_rval_t enc_rval; + + NR_UL_DCCH_Message_t ul_dcch_msg; + NR_RRCSetupComplete_t *RrcSetupComplete; + memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); + + uint8_t buf[6]; + + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + ul_dcch_msg.message.choice.c1 = CALLOC(1,sizeof(struct NR_UL_DCCH_MessageType__c1)); + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_rrcSetupComplete; + ul_dcch_msg.message.choice.c1->choice.rrcSetupComplete = CALLOC(1, sizeof(NR_RRCSetupComplete_t)); + RrcSetupComplete = ul_dcch_msg.message.choice.c1->choice.rrcSetupComplete; + RrcSetupComplete->rrc_TransactionIdentifier = Transaction_id; + RrcSetupComplete->criticalExtensions.present = NR_RRCSetupComplete__criticalExtensions_PR_rrcSetupComplete; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete = CALLOC(1, sizeof(NR_RRCSetupComplete_IEs_t)); + // RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->nonCriticalExtension = CALLOC(1, + // sizeof(*RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->nonCriticalExtension)); + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->selectedPLMN_Identity = sel_plmn_id; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->registeredAMF = NULL; + + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value = CALLOC(1, sizeof(struct NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value)); + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->present = NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size = 6; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf = buf; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[0] = 0x12; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[1] = 0x34; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[2] = 0x56; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[3] = 0x78; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[4] = 0x9A; + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[5] = 0xBC; + + memset(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,0,sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,dedicatedInfoNAS,dedicatedInfoNASLength); +if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); +} + +enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, + NULL, + (void *)&ul_dcch_msg, + buffer, + 100); +AssertFatal(enc_rval.encoded > 0,"ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name,enc_rval.encoded); +LOG_D(NR_RRC,"RRCSetupComplete Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + +return((enc_rval.encoded+7)/8); +} + +//------------------------------------------------------------------------------ +uint8_t +do_NR_DLInformationTransfer( + uint8_t Mod_id, + uint8_t **buffer, + uint8_t transaction_id, + uint32_t pdu_length, + uint8_t *pdu_buffer +) +//------------------------------------------------------------------------------ +{ + ssize_t encoded; + NR_DL_DCCH_Message_t dl_dcch_msg; + memset(&dl_dcch_msg, 0, sizeof(NR_DL_DCCH_Message_t)); + dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; + dl_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_DL_DCCH_MessageType__c1)); + dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer; + + dl_dcch_msg.message.choice.c1->choice.dlInformationTransfer = CALLOC(1, sizeof(NR_DLInformationTransfer_t)); + dl_dcch_msg.message.choice.c1->choice.dlInformationTransfer->rrc_TransactionIdentifier = transaction_id; + dl_dcch_msg.message.choice.c1->choice.dlInformationTransfer->criticalExtensions.present = + NR_DLInformationTransfer__criticalExtensions_PR_dlInformationTransfer; + + dl_dcch_msg.message.choice.c1->choice.dlInformationTransfer-> + criticalExtensions.choice.dlInformationTransfer = CALLOC(1, sizeof(NR_DLInformationTransfer_IEs_t)); + dl_dcch_msg.message.choice.c1->choice.dlInformationTransfer-> + criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); + dl_dcch_msg.message.choice.c1->choice.dlInformationTransfer-> + criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message->buf = pdu_buffer; + dl_dcch_msg.message.choice.c1->choice.dlInformationTransfer-> + criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message->size = pdu_length; + + encoded = uper_encode_to_new_buffer (&asn_DEF_NR_DL_DCCH_Message, NULL, (void *) &dl_dcch_msg, (void **)buffer); + AssertFatal(encoded > 0,"ASN1 message encoding failed (%s, %ld)!\n", + "DLInformationTransfer", encoded); + LOG_D(NR_RRC,"DLInformationTransfer Encoded %zd bytes\n", encoded); + //for (int i=0;ipresent = NR_UL_DCCH_MessageType__c1_PR_ulInformationTransfer; + ul_dcch_msg.message.choice.c1->choice.ulInformationTransfer = CALLOC(1,sizeof(struct NR_ULInformationTransfer)); + ul_dcch_msg.message.choice.c1->choice.ulInformationTransfer->criticalExtensions.present = NR_ULInformationTransfer__criticalExtensions_PR_ulInformationTransfer; + ul_dcch_msg.message.choice.c1->choice.ulInformationTransfer->criticalExtensions.choice.ulInformationTransfer = CALLOC(1,sizeof(struct NR_ULInformationTransfer_IEs)); + struct NR_ULInformationTransfer_IEs *ulInformationTransfer = ul_dcch_msg.message.choice.c1->choice.ulInformationTransfer->criticalExtensions.choice.ulInformationTransfer; + ulInformationTransfer->dedicatedNAS_Message = CALLOC(1,sizeof(NR_DedicatedNAS_Message_t)); + ulInformationTransfer->dedicatedNAS_Message->buf = pdu_buffer; + ulInformationTransfer->dedicatedNAS_Message->size = pdu_length; + ulInformationTransfer->lateNonCriticalExtension = NULL; + encoded = uper_encode_to_new_buffer (&asn_DEF_NR_UL_DCCH_Message, NULL, (void *) &ul_dcch_msg, (void **) buffer); + AssertFatal(encoded > 0,"ASN1 message encoding failed (%s, %ld)!\n", + "ULInformationTransfer",encoded); + LOG_D(NR_RRC,"ULInformationTransfer Encoded %zd bytes\n",encoded); + + return encoded; +} + +uint8_t do_RRCReestablishmentRequest(uint8_t Mod_id, uint8_t *buffer, uint16_t c_rnti) { + asn_enc_rval_t enc_rval; + NR_UL_CCCH_Message_t ul_ccch_msg; + NR_RRCReestablishmentRequest_t *rrcReestablishmentRequest; + uint8_t buf[2]; + + memset((void *)&ul_ccch_msg,0,sizeof(NR_UL_CCCH_Message_t)); + ul_ccch_msg.message.present = NR_UL_CCCH_MessageType_PR_c1; + ul_ccch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_CCCH_MessageType__c1)); + ul_ccch_msg.message.choice.c1->present = NR_UL_CCCH_MessageType__c1_PR_rrcReestablishmentRequest; + ul_ccch_msg.message.choice.c1->choice.rrcReestablishmentRequest = CALLOC(1, sizeof(NR_RRCReestablishmentRequest_t)); + + rrcReestablishmentRequest = ul_ccch_msg.message.choice.c1->choice.rrcReestablishmentRequest; + // test + rrcReestablishmentRequest->rrcReestablishmentRequest.reestablishmentCause = NR_ReestablishmentCause_reconfigurationFailure; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.c_RNTI = c_rnti; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.physCellId = 0; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf = buf; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[0] = 0x08; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[1] = 0x32; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.size = 2; + + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_CCCH_Message, (void *)&ul_ccch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_CCCH_Message, + NULL, + (void *)&ul_ccch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(NR_RRC,"[UE] RRCReestablishmentRequest Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); +} + +//------------------------------------------------------------------------------ +uint8_t +do_RRCReestablishment( +const protocol_ctxt_t *const ctxt_pP, +rrc_gNB_ue_context_t *const ue_context_pP, +int CC_id, +uint8_t *const buffer, +//const uint8_t transmission_mode, +const uint8_t Transaction_id, +NR_SRB_ToAddModList_t **SRB_configList +) { + asn_enc_rval_t enc_rval; + //long *logicalchannelgroup = NULL; + struct NR_SRB_ToAddMod *SRB1_config = NULL; + struct NR_SRB_ToAddMod *SRB2_config = NULL; + //gNB_RRC_INST *nrrrc = RC.nrrrc[ctxt_pP->module_id]; + NR_DL_DCCH_Message_t dl_dcch_msg; + NR_RRCReestablishment_t *rrcReestablishment = NULL; + int i = 0; + ue_context_pP->ue_context.reestablishment_xid = Transaction_id; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[Transaction_id]; + + if (*SRB_configList2) { + free(*SRB_configList2); + } + + *SRB_configList2 = CALLOC(1, sizeof(NR_SRB_ToAddModList_t)); + memset((void *)&dl_dcch_msg, 0, sizeof(NR_DL_DCCH_Message_t)); + dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; + dl_dcch_msg.message.choice.c1 = calloc(1,sizeof(struct NR_DL_DCCH_MessageType__c1)); + dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment; + dl_dcch_msg.message.choice.c1->choice.rrcReestablishment = CALLOC(1,sizeof(NR_RRCReestablishment_t)); + rrcReestablishment = dl_dcch_msg.message.choice.c1->choice.rrcReestablishment; + + // get old configuration of SRB2 + if (*SRB_configList != NULL) { + for (i = 0; (i < (*SRB_configList)->list.count) && (i < 3); i++) { + LOG_D(NR_RRC, "(*SRB_configList)->list.array[%d]->srb_Identity=%ld\n", + i, (*SRB_configList)->list.array[i]->srb_Identity); + + if ((*SRB_configList)->list.array[i]->srb_Identity == 2 ) { + SRB2_config = (*SRB_configList)->list.array[i]; + } else if ((*SRB_configList)->list.array[i]->srb_Identity == 1 ) { + SRB1_config = (*SRB_configList)->list.array[i]; + } + } + } + + if (SRB1_config == NULL) { + // default SRB1 configuration + LOG_W(NR_RRC,"SRB1 configuration does not exist in SRB configuration list, use default\n"); + /// SRB1 + SRB1_config = CALLOC(1, sizeof(*SRB1_config)); + SRB1_config->srb_Identity = 1; + } + + if (SRB2_config == NULL) { + LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); + } else { + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + } + + if (*SRB_configList) { + free(*SRB_configList); + } + + *SRB_configList = CALLOC(1, sizeof(LTE_SRB_ToAddModList_t)); + ASN_SEQUENCE_ADD(&(*SRB_configList)->list,SRB1_config); + + rrcReestablishment->rrc_TransactionIdentifier = Transaction_id; + rrcReestablishment->criticalExtensions.present = NR_RRCReestablishment__criticalExtensions_PR_rrcReestablishment; + rrcReestablishment->criticalExtensions.choice.rrcReestablishment = CALLOC(1,sizeof(NR_RRCReestablishment_IEs_t)); + + uint8_t KgNB_star[32] = { 0 }; + /** TODO + uint16_t pci = nrrrc->carrier[CC_id].physCellId; + uint32_t earfcn_dl = (uint32_t)freq_to_arfcn10(RC.mac[ctxt_pP->module_id]->common_channels[CC_id].eutra_band, + nrrrc->carrier[CC_id].dl_CarrierFreq); + bool is_rel8_only = true; + + if (earfcn_dl > 65535) { + is_rel8_only = false; + } + LOG_D(NR_RRC, "pci=%d, eutra_band=%d, downlink_frequency=%d, earfcn_dl=%u, is_rel8_only=%s\n", + pci, + RC.mac[ctxt_pP->module_id]->common_channels[CC_id].eutra_band, + nrrrc->carrier[CC_id].dl_CarrierFreq, + earfcn_dl, + is_rel8_only == true ? "true": "false"); + */ + + if (ue_context_pP->ue_context.nh_ncc >= 0) { + //TODO derive_keNB_star(ue_context_pP->ue_context.nh, pci, earfcn_dl, is_rel8_only, KgNB_star); + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount = ue_context_pP->ue_context.nh_ncc; + } else { // first HO + //TODO derive_keNB_star (ue_context_pP->ue_context.kgnb, pci, earfcn_dl, is_rel8_only, KgNB_star); + // LG: really 1 + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount = 0; + } + // copy KgNB_star to ue_context_pP->ue_context.kgnb + memcpy (ue_context_pP->ue_context.kgnb, KgNB_star, 32); + ue_context_pP->ue_context.kgnb_ncc = 0; + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->lateNonCriticalExtension = NULL; + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nonCriticalExtension = NULL; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, + NULL, + (void *)&dl_dcch_msg, + buffer, + 100); + + if(enc_rval.encoded == -1) { + LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + LOG_D(NR_RRC,"RRCReestablishment Encoded %u bits (%u bytes)\n", + (uint32_t)enc_rval.encoded, (uint32_t)(enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); + +} + +uint8_t +do_RRCReestablishmentComplete(uint8_t *buffer, int64_t rrc_TransactionIdentifier) { + asn_enc_rval_t enc_rval; + NR_UL_DCCH_Message_t ul_dcch_msg; + NR_RRCReestablishmentComplete_t *rrcReestablishmentComplete; + + memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + ul_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_DCCH_MessageType__c1)); + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_rrcReestablishmentComplete; + ul_dcch_msg.message.choice.c1->choice.rrcReestablishmentComplete = CALLOC(1, sizeof(NR_RRCReestablishmentComplete_t)); + + rrcReestablishmentComplete = ul_dcch_msg.message.choice.c1->choice.rrcReestablishmentComplete; + rrcReestablishmentComplete->rrc_TransactionIdentifier = rrc_TransactionIdentifier; + rrcReestablishmentComplete->criticalExtensions.present = NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete; + rrcReestablishmentComplete->criticalExtensions.choice.rrcReestablishmentComplete = CALLOC(1, sizeof(NR_RRCReestablishmentComplete_IEs_t)); + rrcReestablishmentComplete->criticalExtensions.choice.rrcReestablishmentComplete->lateNonCriticalExtension = NULL; + rrcReestablishmentComplete->criticalExtensions.choice.rrcReestablishmentComplete->nonCriticalExtension = NULL; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_CCCH_Message, (void *)&ul_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, + NULL, + (void *)&ul_dcch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(NR_RRC,"[UE] RRCReestablishmentComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); +} + diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 3f647cb887..7b38de2bb9 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -65,6 +65,9 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, gNB_RrcConfigurationReq *configuration ); +uint8_t do_SIB23_NR(rrc_gNB_carrier_data_t *carrier, + gNB_RrcConfigurationReq *configuration); + void do_RLC_BEARER(uint8_t Mod_id, int CC_id, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_BearerToAddModList, @@ -82,3 +85,100 @@ void do_PHYSICALCELLGROUP(uint8_t Mod_id, void do_SpCellConfig(gNB_RRC_INST *rrc, struct NR_SpCellConfig *spconfig); + +uint8_t do_RRCReject(uint8_t Mod_id, + uint8_t *const buffer); + +void fill_initial_SpCellConfig(rnti_t rnti, + NR_SpCellConfig_t *SpCellConfig, + NR_ServingCellConfigCommon_t *scc, + rrc_gNB_carrier_data_t *carrier); + +void fill_initial_cellGroupConfig(rnti_t rnti, + NR_CellGroupConfig_t *cellGroupConfig, + NR_ServingCellConfigCommon_t *scc, + rrc_gNB_carrier_data_t *carrier); + +void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGroupConfig_t *ue_context_mastercellGroup); + +uint8_t do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t *const buffer, + const uint8_t transaction_id, + OCTET_STRING_t *masterCellGroup_from_DU, + NR_ServingCellConfigCommon_t *scc, + rrc_gNB_carrier_data_t *carrier); + +uint8_t do_NR_SecurityModeCommand( + const protocol_ctxt_t *const ctxt_pP, + uint8_t *const buffer, + const uint8_t Transaction_id, + const uint8_t cipheringAlgorithm, + NR_IntegrityProtAlgorithm_t *integrityProtAlgorithm); + +uint8_t do_NR_SA_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, + uint8_t *const buffer, + const uint8_t Transaction_id); + +uint8_t do_NR_RRCRelease(uint8_t *buffer, + uint8_t Transaction_id); + +int16_t do_RRCReconfiguration( + const protocol_ctxt_t *const ctxt_pP, + uint8_t *buffer, + uint8_t Transaction_id, + NR_SRB_ToAddModList_t *SRB_configList, + NR_DRB_ToAddModList_t *DRB_configList, + NR_DRB_ToReleaseList_t *DRB_releaseList, + NR_SecurityConfig_t *security_config, + NR_SDAP_Config_t *sdap_config, + NR_MeasConfig_t *meas_config, + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList, + NR_MAC_CellGroupConfig_t *mac_CellGroupConfig, + NR_CellGroupConfig_t *cellGroupConfig); + +uint8_t do_RRCSetupComplete(uint8_t Mod_id, + uint8_t *buffer, + const uint8_t Transaction_id, + uint8_t sel_plmn_id, + const int dedicatedInfoNASLength, + const char *dedicatedInfoNAS); + +uint8_t do_RRCSetupRequest(uint8_t Mod_id, uint8_t *buffer,uint8_t *rv); + +uint8_t do_NR_RRCReconfigurationComplete( + const protocol_ctxt_t *const ctxt_pP, + uint8_t *buffer, + const uint8_t Transaction_id + ); + +uint8_t +do_NR_DLInformationTransfer( + uint8_t Mod_id, + uint8_t **buffer, + uint8_t transaction_id, + uint32_t pdu_length, + uint8_t *pdu_buffer +); + +uint8_t do_NR_ULInformationTransfer(uint8_t **buffer, + uint32_t pdu_length, + uint8_t *pdu_buffer); + +uint8_t do_RRCReestablishmentRequest(uint8_t Mod_id, uint8_t *buffer, uint16_t c_rnti); + +uint8_t +do_RRCReestablishment( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + int CC_id, + uint8_t *const buffer, + //const uint8_t transmission_mode, + const uint8_t Transaction_id, + NR_SRB_ToAddModList_t **SRB_configList +); + +uint8_t +do_RRCReestablishmentComplete( + uint8_t *buffer, + int64_t rrc_TransactionIdentifier); + diff --git a/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/extract_asn1_from_spce.pl b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/extract_asn1_from_spce.pl index 81193afd1d..bdcdef5939 100755 --- a/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/extract_asn1_from_spce.pl +++ b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/extract_asn1_from_spce.pl @@ -26,38 +26,52 @@ while () { syswrite OUTPUT_FILE,"END\n\n"; - while() { - if( m/NR-UE-Variables DEFINITIONS AUTOMATIC TAGS ::=/){ - - syswrite OUTPUT_FILE,"$_ \n"; - syswrite OUTPUT_FILE,"BEGIN\n\n"; + while() { + if( m/PC5-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::=/){ + syswrite OUTPUT_FILE,"$_ \n"; + syswrite OUTPUT_FILE,"BEGIN\n\n"; - # Get all the text delimited by -- ASN1START and -- ASN1STOP - extract_asn1(); + # Get all the text delimited by -- ASN1START and -- ASN1STOP + extract_asn1(); - syswrite OUTPUT_FILE,"END\n\n"; + syswrite OUTPUT_FILE,"END\n\n"; - while() { + while() { + if( m/NR-UE-Variables DEFINITIONS AUTOMATIC TAGS ::=/){ + syswrite OUTPUT_FILE,"$_ \n"; + syswrite OUTPUT_FILE,"BEGIN\n\n"; + + # Get all the text delimited by -- ASN1START and -- ASN1STOP + extract_asn1(); + syswrite OUTPUT_FILE,"END\n\n"; + while() { + if( m/NR-Sidelink-Preconf DEFINITIONS AUTOMATIC TAGS ::=/){ + syswrite OUTPUT_FILE,"$_ \n"; + syswrite OUTPUT_FILE,"BEGIN\n\n"; + + # Get all the text delimited by -- ASN1START and -- ASN1STOP + extract_asn1(); + + syswrite OUTPUT_FILE,"END\n\n"; + while() { if( m/NR-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::=/){ - - syswrite OUTPUT_FILE,"$_ \n"; - syswrite OUTPUT_FILE,"BEGIN\n\n"; + syswrite OUTPUT_FILE,"$_ \n"; + syswrite OUTPUT_FILE,"BEGIN\n\n"; - # Get all the text delimited by -- ASN1START and -- ASN1STOP - extract_asn1(); + # Get all the text delimited by -- ASN1START and -- ASN1STOP + extract_asn1(); - syswrite OUTPUT_FILE,"END\n\n"; - - } + syswrite OUTPUT_FILE,"END\n\n"; + } } - - } - } - + } + } + } + } + } + } close(OUTPUT_FILE); } - - } close(INPUT_FILE); diff --git a/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.1.0.asn1 b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.1.0.asn1 new file mode 100644 index 0000000000..353e3e398f --- /dev/null +++ b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.1.0.asn1 @@ -0,0 +1,12881 @@ +NR-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- TAG-BCCH-BCH-MESSAGE-START + +BCCH-BCH-Message ::= SEQUENCE { + message BCCH-BCH-MessageType +} + +BCCH-BCH-MessageType ::= CHOICE { + mib MIB, + messageClassExtension SEQUENCE {} +} + +-- TAG-BCCH-BCH-MESSAGE-STOP +-- TAG-BCCH-DL-SCH-MESSAGE-START + +BCCH-DL-SCH-Message ::= SEQUENCE { + message BCCH-DL-SCH-MessageType +} + +BCCH-DL-SCH-MessageType ::= CHOICE { + c1 CHOICE { + systemInformation SystemInformation, + systemInformationBlockType1 SIB1 + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-BCCH-DL-SCH-MESSAGE-STOP +-- TAG-DL-CCCH-MESSAGE-START + +DL-CCCH-Message ::= SEQUENCE { + message DL-CCCH-MessageType +} + +DL-CCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcReject RRCReject, + rrcSetup RRCSetup, + spare2 NULL, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-DL-CCCH-MESSAGE-STOP +-- TAG-DL-DCCH-MESSAGE-START + +DL-DCCH-Message ::= SEQUENCE { + message DL-DCCH-MessageType +} + +DL-DCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcReconfiguration RRCReconfiguration, + rrcResume RRCResume, + rrcRelease RRCRelease, + rrcReestablishment RRCReestablishment, + securityModeCommand SecurityModeCommand, + dlInformationTransfer DLInformationTransfer, + ueCapabilityEnquiry UECapabilityEnquiry, + counterCheck CounterCheck, + mobilityFromNRCommand MobilityFromNRCommand, + dlDedicatedMessageSegment-r16 DLDedicatedMessageSegment-r16, + ueInformationRequest-r16 UEInformationRequest-r16, + dlInformationTransferMRDC-r16 DLInformationTransferMRDC-r16, + loggedMeasurementConfiguration-r16 LoggedMeasurementConfiguration-r16, + spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-DL-DCCH-MESSAGE-STOP +-- TAG-PCCH-PCH-MESSAGE-START + +PCCH-Message ::= SEQUENCE { + message PCCH-MessageType +} + +PCCH-MessageType ::= CHOICE { + c1 CHOICE { + paging Paging, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-PCCH-PCH-MESSAGE-STOP +-- TAG-UL-CCCH-MESSAGE-START + + +UL-CCCH-Message ::= SEQUENCE { + message UL-CCCH-MessageType +} + +UL-CCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcSetupRequest RRCSetupRequest, + rrcResumeRequest RRCResumeRequest, + rrcReestablishmentRequest RRCReestablishmentRequest, + rrcSystemInfoRequest RRCSystemInfoRequest + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-UL-CCCH-MESSAGE-STOP +-- TAG-UL-CCCH1-MESSAGE-START + + +UL-CCCH1-Message ::= SEQUENCE { + message UL-CCCH1-MessageType +} + +UL-CCCH1-MessageType ::= CHOICE { + c1 CHOICE { + rrcResumeRequest1 RRCResumeRequest1, + spare3 NULL, + spare2 NULL, + spare1 NULL + + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-UL-CCCH1-MESSAGE-STOP +-- TAG-UL-DCCH-MESSAGE-START + +UL-DCCH-Message ::= SEQUENCE { + message UL-DCCH-MessageType +} + +UL-DCCH-MessageType ::= CHOICE { + c1 CHOICE { + measurementReport MeasurementReport, + rrcReconfigurationComplete RRCReconfigurationComplete, + rrcSetupComplete RRCSetupComplete, + rrcReestablishmentComplete RRCReestablishmentComplete, + rrcResumeComplete RRCResumeComplete, + securityModeComplete SecurityModeComplete, + securityModeFailure SecurityModeFailure, + ulInformationTransfer ULInformationTransfer, + locationMeasurementIndication LocationMeasurementIndication, + ueCapabilityInformation UECapabilityInformation, + counterCheckResponse CounterCheckResponse, + ueAssistanceInformation UEAssistanceInformation, + failureInformation FailureInformation, + ulInformationTransferMRDC ULInformationTransferMRDC, + scgFailureInformation SCGFailureInformation, + scgFailureInformationEUTRA SCGFailureInformationEUTRA + }, + messageClassExtension CHOICE { + c2 CHOICE { + ulDedicatedMessageSegment-r16 ULDedicatedMessageSegment-r16, + dedicatedSIBRequest-r16 DedicatedSIBRequest-r16, + mcgFailureInformation-r16 MCGFailureInformation-r16, + ueInformationResponse-r16 UEInformationResponse-r16, + sidelinkUEInformationNR-r16 SidelinkUEInformationNR-r16, + ulInformationTransferIRAT-r16 ULInformationTransferIRAT-r16, + iabOtherInformation-r16 IABOtherInformation-r16, + spare9 NULL, spare8 NULL, spare7 NULL, spare6 NULL, + spare5 NULL, spare4 NULL, spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtensionFuture-r16 SEQUENCE {} + } +} + +-- TAG-UL-DCCH-MESSAGE-STOP +-- TAG-COUNTERCHECK-START + + +CounterCheck ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + counterCheck CounterCheck-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CounterCheck-IEs ::= SEQUENCE { + drb-CountMSB-InfoList DRB-CountMSB-InfoList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +DRB-CountMSB-InfoList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-CountMSB-Info + +DRB-CountMSB-Info ::= SEQUENCE { + drb-Identity DRB-Identity, + countMSB-Uplink INTEGER(0..33554431), + countMSB-Downlink INTEGER(0..33554431) +} + +-- TAG-COUNTERCHECK-STOP +-- TAG-COUNTERCHECKRESPONSE-START + +CounterCheckResponse ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + counterCheckResponse CounterCheckResponse-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CounterCheckResponse-IEs ::= SEQUENCE { + drb-CountInfoList DRB-CountInfoList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL + +} + +DRB-CountInfoList ::= SEQUENCE (SIZE (0..maxDRB)) OF DRB-CountInfo + +DRB-CountInfo ::= SEQUENCE { + drb-Identity DRB-Identity, + count-Uplink INTEGER(0..4294967295), + count-Downlink INTEGER(0..4294967295) +} + +-- TAG-COUNTERCHECKRESPONSE-STOP +-- TAG-DEDICATEDSIBREQUEST-START + +DedicatedSIBRequest-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + dedicatedSIBRequest-r16 DedicatedSIBRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DedicatedSIBRequest-r16-IEs ::= SEQUENCE { + onDemandSIB-RequestList-r16 SEQUENCE { + + requestedSIB-List-r16 SEQUENCE (SIZE (1..maxOnDemandSIB-r16)) OF SIB-ReqInfo-r16 OPTIONAL, + requestedPosSIB-List-r16 SEQUENCE (SIZE (1..maxOnDemandPosSIB-r16)) OF PosSIB-ReqInfo-r16 OPTIONAL + } OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SIB-ReqInfo-r16 ::= ENUMERATED { sib12, sib13, sib14, spare5, spare4, spare3, spare2, spare1 } + +PosSIB-ReqInfo-r16 ::= SEQUENCE { + gnss-id-r16 GNSS-ID-r16 OPTIONAL, + sbas-id-r16 SBAS-ID-r16 OPTIONAL, + posSibType-r16 ENUMERATED { posSibType1-1, posSibType1-2, posSibType1-3, posSibType1-4, posSibType1-5, posSibType1-6, + posSibType1-7, posSibType1-8, posSibType2-1, posSibType2-2, posSibType2-3, posSibType2-4, + posSibType2-5, posSibType2-6, posSibType2-7, posSibType2-8, posSibType2-9, posSibType2-10, + posSibType2-11, posSibType2-12, posSibType2-13, posSibType2-14, posSibType2-15, + posSibType2-16, posSibType2-17, posSibType2-18, posSibType2-19, posSibType2-20, + posSibType2-21, posSibType2-22, posSibType2-23, posSibType3-1, posSibType4-1, + posSibType5-1, posSibType6-1, posSibType6-2, posSibType6-3,... } +} + +-- TAG-DEDICATEDSIBREQUEST-STOP +-- TAG-DLDEDICATEDMESSAGESEGMENT-START + + +DLDedicatedMessageSegment-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + dlDedicatedMessageSegment-r16 DLDedicatedMessageSegment-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLDedicatedMessageSegment-r16-IEs ::= SEQUENCE { + segmentNumber-r16 INTEGER(0..4), + rrc-MessageSegmentContainer-r16 OCTET STRING, + rrc-MessageSegmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLDEDICATEDMESSAGESEGMENT-STOP +-- TAG-DLINFORMATIONTRANSFER-START + +DLInformationTransfer ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + dlInformationTransfer DLInformationTransfer-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLInformationTransfer-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension DLInformationTransfer-v1610-IEs OPTIONAL +} + +DLInformationTransfer-v1610-IEs ::= SEQUENCE { + referenceTimeInfo-r16 ReferenceTimeInfo-r16 OPTIONAL, -- Need R + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLINFORMATIONTRANSFER-STOP +-- TAG-DLINFORMATIONTRANSFERMRDC-START + +DLInformationTransferMRDC-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + dlInformationTransferMRDC-r16 DLInformationTransferMRDC-r16-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLInformationTransferMRDC-r16-IEs::= SEQUENCE { + dl-DCCH-MessageNR-r16 OCTET STRING OPTIONAL, -- Need N + dl-DCCH-MessageEUTRA-r16 OCTET STRING OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLINFORMATIONTRANSFERMRDC-STOP +-- TAG-FAILUREINFORMATION-START + +FailureInformation ::= SEQUENCE { + criticalExtensions CHOICE { + failureInformation FailureInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +FailureInformation-IEs ::= SEQUENCE { + failureInfoRLC-Bearer FailureInfoRLC-Bearer OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension FailureInformation-v1610-IEs OPTIONAL +} + +FailureInfoRLC-Bearer ::= SEQUENCE { + cellGroupId CellGroupId, + logicalChannelIdentity LogicalChannelIdentity, + failureType ENUMERATED {rlc-failure, spare3, spare2, spare1} +} + +FailureInformation-v1610-IEs ::= SEQUENCE { + failureInfoDAPS-r16 FailureInfoDAPS-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureInfoDAPS-r16 ::= SEQUENCE { + failureType-r16 ENUMERATED {daps-failure, spare3, spare2, spare1} +} + +-- TAG-FAILUREINFORMATION-STOP +-- TAG-IABOTHERINFORMATION-START + +IABOtherInformation-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + iabOtherInformation-r16 IABOtherInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +IABOtherInformation-r16-IEs ::= SEQUENCE { + ip-InfoType CHOICE { + iab-IP-Request-r16 SEQUENCE { + iab-IPv4-AddressNumReq-r16 IAB-IPAddressNumReq-r16 OPTIONAL, + iab-IPv6-AddressReq-r16 CHOICE { + iab-IPv6-AddressNumReq-r16 IAB-IPAddressNumReq-r16, + iab-IPv6-AddressPrefixReq-r16 IAB-IPAddressPrefixReq-r16, + ... + } OPTIONAL + }, + iab-IP-Report-r16 SEQUENCE { + iab-IPv4-AddressReport-r16 IAB-IP-AddressAndTraffic-r16 OPTIONAL, + iab-IPv6-Report-r16 CHOICE { + iab-IPv6-AddressReport-r16 IAB-IP-AddressAndTraffic-r16, + iab-IPv6-PrefixReport-r16 IAB-IP-PrefixAndTraffic-r16, + ... + } OPTIONAL + }, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +IAB-IPAddressNumReq-r16 ::= SEQUENCE { + all-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + f1-C-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + f1-U-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + non-F1-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + ... +} + +IAB-IPAddressPrefixReq-r16 ::= SEQUENCE { + all-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + f1-C-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + f1-U-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + non-F1-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + ... +} + +IAB-IP-AddressAndTraffic-r16 ::= SEQUENCE { + all-Traffic-IAB-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + f1-C-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + f1-U-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + non-F1-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL +} + +IAB-IP-PrefixAndTraffic-r16 ::= SEQUENCE { + all-Traffic-IAB-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + f1-C-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + f1-U-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + non-F1-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL +} + +-- TAG-IABOTHERINFORMATION-STOP +-- TAG-LOCATIONMEASUREMENTINDICATION-START + +LocationMeasurementIndication ::= SEQUENCE { + criticalExtensions CHOICE { + locationMeasurementIndication LocationMeasurementIndication-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +LocationMeasurementIndication-IEs ::= SEQUENCE { + measurementIndication SetupRelease {LocationMeasurementInfo}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-LOCATIONMEASUREMENTINDICATION-STOP +-- TAG-LOGGEDMEASUREMENTCONFIGURATION-START + +LoggedMeasurementConfiguration-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + loggedMeasurementConfiguration-r16 LoggedMeasurementConfiguration-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +LoggedMeasurementConfiguration-r16-IEs ::= SEQUENCE { + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + absoluteTimeInfo-r16 AbsoluteTimeInfo-r16, + areaConfiguration-r16 AreaConfiguration-r16 OPTIONAL, --Need R + plmn-IdentityList-r16 PLMN-IdentityList2-r16 OPTIONAL, --Need R + bt-NameList-r16 SetupRelease {BT-NameList-r16} OPTIONAL, --Need M + wlan-NameList-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, --Need M + sensor-NameList-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, --Need M + loggingDuration-r16 LoggingDuration-r16, + reportType CHOICE { + periodical LoggedPeriodicalReportConfig-r16, + eventTriggered LoggedEventTriggerConfig-r16, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +LoggedPeriodicalReportConfig-r16 ::= SEQUENCE { + loggingInterval-r16 LoggingInterval-r16, + ... + } + +LoggedEventTriggerConfig-r16 ::= SEQUENCE { + eventType-r16 EventType-r16, + loggingInterval-r16 LoggingInterval-r16, + ... +} + +EventType-r16 ::= CHOICE { + outOfCoverage NULL, + eventL1 SEQUENCE { + l1-Threshold MeasTriggerQuantity, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + ... +} + +-- TAG-LOGGEDMEASUREMENTCONFIGURATION-STOP +-- TAG-MCGFAILUREINFORMATION-START + +MCGFailureInformation-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + mcgFailureInformation-r16 MCGFailureInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MCGFailureInformation-r16-IEs ::= SEQUENCE { + failureReportMCG-r16 FailureReportMCG-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportMCG-r16 ::= SEQUENCE { + failureType-r16 ENUMERATED {t310-Expiry, randomAccessProblem, rlc-MaxNumRetx, + t312-Expiry-r16, lbt-Failure-r16, beamFailureRecoveryFailure-r16, + bh-RLF-r16, spare1} OPTIONAL, + measResultFreqList-r16 MeasResultList2NR OPTIONAL, + measResultFreqListEUTRA-r16 MeasResultList2EUTRA OPTIONAL, + measResultSCG-r16 OCTET STRING (CONTAINING MeasResultSCG-Failure) OPTIONAL, + measResultSCG-EUTRA-r16 OCTET STRING OPTIONAL, + measResultFreqListUTRA-FDD-r16 MeasResultList2UTRA OPTIONAL, + ... +} + +MeasResultList2UTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2UTRA-FDD-r16 + +MeasResult2UTRA-FDD-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueUTRA-FDD-r16, + measResultNeighCellList-r16 MeasResultListUTRA-FDD-r16 +} + +MeasResultList2EUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2EUTRA-r16 + +-- TAG-MCGFAILUREINFORMATION-STOP +-- TAG-MEASUREMENTREPORT-START + +MeasurementReport ::= SEQUENCE { + criticalExtensions CHOICE { + measurementReport MeasurementReport-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementReport-IEs ::= SEQUENCE { + measResults MeasResults, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-MEASUREMENTREPORT-STOP +-- TAG-MIB-START + +MIB ::= SEQUENCE { + systemFrameNumber BIT STRING (SIZE (6)), + subCarrierSpacingCommon ENUMERATED {scs15or60, scs30or120}, + ssb-SubcarrierOffset INTEGER (0..15), + dmrs-TypeA-Position ENUMERATED {pos2, pos3}, + pdcch-ConfigSIB1 PDCCH-ConfigSIB1, + cellBarred ENUMERATED {barred, notBarred}, + intraFreqReselection ENUMERATED {allowed, notAllowed}, + spare BIT STRING (SIZE (1)) +} + +-- TAG-MIB-STOP +-- TAG-MOBILITYFROMNRCOMMAND-START + +MobilityFromNRCommand ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + mobilityFromNRCommand MobilityFromNRCommand-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MobilityFromNRCommand-IEs ::= SEQUENCE { + targetRAT-Type ENUMERATED { eutra, utra-fdd-v1610, spare2, spare1, ...}, + targetRAT-MessageContainer OCTET STRING, + nas-SecurityParamFromNR OCTET STRING OPTIONAL, -- Cond HO-ToEPCUTRAN + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension MobilityFromNRCommand-v1610-IEs OPTIONAL +} + +MobilityFromNRCommand-v1610-IEs ::= SEQUENCE { + voiceFallbackIndication-r16 ENUMERATED {true} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-MOBILITYFROMNRCOMMAND-STOP +-- TAG-PAGING-START + +Paging ::= SEQUENCE { + pagingRecordList PagingRecordList OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +PagingRecordList ::= SEQUENCE (SIZE(1..maxNrofPageRec)) OF PagingRecord + +PagingRecord ::= SEQUENCE { + ue-Identity PagingUE-Identity, + accessType ENUMERATED {non3GPP} OPTIONAL, -- Need N + ... +} + +PagingUE-Identity ::= CHOICE { + ng-5G-S-TMSI NG-5G-S-TMSI, + fullI-RNTI I-RNTI-Value, + ... +} + +-- TAG-PAGING-STOP +-- TAG-RRCREESTABLISHMENT-START + +RRCReestablishment ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReestablishment RRCReestablishment-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReestablishment-IEs ::= SEQUENCE { + nextHopChainingCount NextHopChainingCount, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCREESTABLISHMENT-STOP +-- TAG-RRCREESTABLISHMENTCOMPLETE-START + +RRCReestablishmentComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReestablishmentComplete RRCReestablishmentComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReestablishmentComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReestablishmentComplete-v1610-IEs OPTIONAL +} + +RRCReestablishmentComplete-v1610-IEs ::= SEQUENCE { + ueMeasurementsAvailable-r16 UEMeasurementsAvailable-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCREESTABLISHMENTCOMPLETE-STOP +-- TAG-RRCREESTABLISHMENTREQUEST-START + + +RRCReestablishmentRequest ::= SEQUENCE { + rrcReestablishmentRequest RRCReestablishmentRequest-IEs +} + +RRCReestablishmentRequest-IEs ::= SEQUENCE { + ue-Identity ReestabUE-Identity, + reestablishmentCause ReestablishmentCause, + spare BIT STRING (SIZE (1)) +} + +ReestabUE-Identity ::= SEQUENCE { + c-RNTI RNTI-Value, + physCellId PhysCellId, + shortMAC-I ShortMAC-I +} + +ReestablishmentCause ::= ENUMERATED {reconfigurationFailure, handoverFailure, otherFailure, spare1} + +-- TAG-RRCREESTABLISHMENTREQUEST-STOP +-- TAG-RRCRECONFIGURATION-START + +RRCReconfiguration ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfiguration RRCReconfiguration-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfiguration-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig OPTIONAL, -- Need M + secondaryCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Cond SCG + measConfig MeasConfig OPTIONAL, -- Need M + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReconfiguration-v1530-IEs OPTIONAL +} + +RRCReconfiguration-v1530-IEs ::= SEQUENCE { + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Need M + fullConfig ENUMERATED {true} OPTIONAL, -- Cond FullConfig + dedicatedNAS-MessageList SEQUENCE (SIZE(1..maxDRB)) OF DedicatedNAS-Message OPTIONAL, -- Cond nonHO + masterKeyUpdate MasterKeyUpdate OPTIONAL, -- Cond MasterKeyChange + dedicatedSIB1-Delivery OCTET STRING (CONTAINING SIB1) OPTIONAL, -- Need N + dedicatedSystemInformationDelivery OCTET STRING (CONTAINING SystemInformation) OPTIONAL, -- Need N + otherConfig OtherConfig OPTIONAL, -- Need M + nonCriticalExtension RRCReconfiguration-v1540-IEs OPTIONAL +} + +RRCReconfiguration-v1540-IEs ::= SEQUENCE { + otherConfig-v1540 OtherConfig-v1540 OPTIONAL, -- Need M + nonCriticalExtension RRCReconfiguration-v1560-IEs OPTIONAL +} + +RRCReconfiguration-v1560-IEs ::= SEQUENCE { + mrdc-SecondaryCellGroupConfig SetupRelease { MRDC-SecondaryCellGroupConfig } OPTIONAL, -- Need M + radioBearerConfig2 OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, -- Need M + sk-Counter SK-Counter OPTIONAL, -- Need N + nonCriticalExtension RRCReconfiguration-v1610-IEs OPTIONAL +} +RRCReconfiguration-v1610-IEs ::= SEQUENCE { + otherConfig-v1610 OtherConfig-v1610 OPTIONAL, -- Need M + bap-Config-r16 SetupRelease { BAP-Config-r16 } OPTIONAL, -- Need M + iab-IP-AddressConfigurationList-r16 IAB-IP-AddressConfigurationList-r16 OPTIONAL, -- Need M + conditionalReconfiguration-r16 ConditionalReconfiguration-r16 OPTIONAL, -- Need M + daps-SourceRelease-r16 ENUMERATED{true} OPTIONAL, -- Need N + t316-r16 SetupRelease {T316-r16} OPTIONAL, -- Need M + needForGapsConfigNR-r16 SetupRelease {NeedForGapsConfigNR-r16} OPTIONAL, -- Need M + onDemandSIB-Request-r16 SetupRelease { OnDemandSIB-Request-r16 } OPTIONAL, -- Need M + dedicatedPosSysInfoDelivery-r16 OCTET STRING (CONTAINING PosSystemInformation-r16-IEs) OPTIONAL, -- Need N + sl-ConfigDedicatedNR-r16 SetupRelease {SL-ConfigDedicatedNR-r16} OPTIONAL, -- Need M + sl-ConfigDedicatedEUTRA-Info-r16 SetupRelease {SL-ConfigDedicatedEUTRA-Info-r16} OPTIONAL, -- Need M + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +MRDC-SecondaryCellGroupConfig ::= SEQUENCE { + mrdc-ReleaseAndAdd ENUMERATED {true} OPTIONAL, -- Need N + mrdc-SecondaryCellGroup CHOICE { + nr-SCG OCTET STRING (CONTAINING RRCReconfiguration), + eutra-SCG OCTET STRING + } +} + +BAP-Config-r16 ::= SEQUENCE { + bap-Address-r16 BIT STRING (SIZE (10)) OPTIONAL, -- Need M + defaultUL-BAProutingID-r16 BAP-Routing-ID-r16 OPTIONAL, -- Need M + defaultUL-BH-RLC-Channel-r16 BH-RLC-ChannelID-r16 OPTIONAL, -- Need M + flowControlFeedbackType-r16 ENUMERATED {perBH-RLC-Channel, perRoutingID, both} OPTIONAL, -- Need R + ... +} + +MasterKeyUpdate ::= SEQUENCE { + keySetChangeIndicator BOOLEAN, + nextHopChainingCount NextHopChainingCount, + nas-Container OCTET STRING OPTIONAL, -- Cond securityNASC + ... +} + +OnDemandSIB-Request-r16 ::= SEQUENCE { + onDemandSIB-RequestProhibitTimer-r16 ENUMERATED {s0, s0dot5, s1, s2, s5, s10, s20, s30} +} + +T316-r16 ::= ENUMERATED {ms50, ms100, ms200, ms300, ms400, ms500, ms600, ms1000, ms1500, ms2000} + +IAB-IP-AddressConfigurationList-r16 ::= SEQUENCE { + iab-IP-AddressToAddModList-r16 SEQUENCE (SIZE(1..maxIAB-IP-Address-r16)) OF IAB-IP-AddressConfiguration-r16 OPTIONAL, -- Need N + iab-IP-AddressToReleaseList-r16 SEQUENCE (SIZE(1..maxIAB-IP-Address-r16)) OF IAB-IP-AddressIndex-r16 OPTIONAL, -- Need N + ... +} + +IAB-IP-AddressConfiguration-r16 ::= SEQUENCE { + iab-IP-AddressIndex-r16 IAB-IP-AddressIndex-r16, + iab-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, -- Need M + iab-IP-Usage-r16 IAB-IP-Usage-r16 OPTIONAL, -- Need M + iab-donor-DU-BAP-Address-r16 BIT STRING (SIZE(10)) OPTIONAL, -- Need M +... +} + +SL-ConfigDedicatedEUTRA-Info-r16 ::= SEQUENCE { + sl-ConfigDedicatedEUTRA-r16 OCTET STRING OPTIONAL, -- Need M + sl-TimeOffsetEUTRA-List-r16 SEQUENCE (SIZE (8)) OF SL-TimeOffsetEUTRA-r16 OPTIONAL -- Need M +} + +SL-TimeOffsetEUTRA-r16 ::= ENUMERATED {ms0, ms0dot25, ms0dot5, ms0dot625, ms0dot75, ms1, ms1dot25, ms1dot5, ms1dot75, + ms2, ms2dot5, ms3, ms4, ms5, ms6, ms8, ms10, ms20} + +-- TAG-RRCRECONFIGURATION-STOP +-- TAG-RRCRECONFIGURATIONCOMPLETE-START + +RRCReconfigurationComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationComplete RRCReconfigurationComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1530-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1530-IEs ::= SEQUENCE { + uplinkTxDirectCurrentList UplinkTxDirectCurrentList OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1560-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1560-IEs ::= SEQUENCE { + scg-Response CHOICE { + nr-SCG-Response OCTET STRING (CONTAINING RRCReconfigurationComplete), + eutra-SCG-Response OCTET STRING + } OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1610-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1610-IEs ::= SEQUENCE { + ueMeasurementsAvailable-r16 UEMeasurementsAvailable-r16 OPTIONAL, + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRECONFIGURATIONCOMPLETE-STOP +-- TAG-RRCREJECT-START + +RRCReject ::= SEQUENCE { + criticalExtensions CHOICE { + rrcReject RRCReject-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReject-IEs ::= SEQUENCE { + waitTime RejectWaitTime OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCREJECT-STOP +-- TAG-RRCRELEASE-START + +RRCRelease ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcRelease RRCRelease-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCRelease-IEs ::= SEQUENCE { + redirectedCarrierInfo RedirectedCarrierInfo OPTIONAL, -- Need N + cellReselectionPriorities CellReselectionPriorities OPTIONAL, -- Need R + suspendConfig SuspendConfig OPTIONAL, -- Need R + deprioritisationReq SEQUENCE { + deprioritisationType ENUMERATED {frequency, nr}, + deprioritisationTimer ENUMERATED {min5, min10, min15, min30} + } OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCRelease-v1540-IEs OPTIONAL +} + +RRCRelease-v1540-IEs ::= SEQUENCE { + waitTime RejectWaitTime OPTIONAL, -- Need N + nonCriticalExtension RRCRelease-v1610-IEs OPTIONAL +} + +RRCRelease-v1610-IEs ::= SEQUENCE { + voiceFallbackIndication-r16 ENUMERATED {true} OPTIONAL, -- Need N + measIdleConfig-r16 SetupRelease {MeasIdleConfigDedicated-r16} OPTIONAL, -- Need M + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +RedirectedCarrierInfo ::= CHOICE { + nr CarrierInfoNR, + eutra RedirectedCarrierInfo-EUTRA, + ... +} + +RedirectedCarrierInfo-EUTRA ::= SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cnType ENUMERATED {epc,fiveGC} OPTIONAL -- Need N +} + +CarrierInfoNR ::= SEQUENCE { + carrierFreq ARFCN-ValueNR, + ssbSubcarrierSpacing SubcarrierSpacing, + smtc SSB-MTC OPTIONAL, -- Need S + ... +} + +SuspendConfig ::= SEQUENCE { + fullI-RNTI I-RNTI-Value, + shortI-RNTI ShortI-RNTI-Value, + ran-PagingCycle PagingCycle, + ran-NotificationAreaInfo RAN-NotificationAreaInfo OPTIONAL, -- Need M + t380 PeriodicRNAU-TimerValue OPTIONAL, -- Need R + nextHopChainingCount NextHopChainingCount, + ... +} + + +PeriodicRNAU-TimerValue ::= ENUMERATED { min5, min10, min20, min30, min60, min120, min360, min720} + + +CellReselectionPriorities ::= SEQUENCE { + freqPriorityListEUTRA FreqPriorityListEUTRA OPTIONAL, -- Need M + freqPriorityListNR FreqPriorityListNR OPTIONAL, -- Need M + t320 ENUMERATED {min5, min10, min20, min30, min60, min120, min180, spare1} OPTIONAL, -- Need R + ... +} + +PagingCycle ::= ENUMERATED {rf32, rf64, rf128, rf256} + +FreqPriorityListEUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA + +FreqPriorityListNR ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityNR + +FreqPriorityEUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL -- Need R +} + +FreqPriorityNR ::= SEQUENCE { + carrierFreq ARFCN-ValueNR, + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL -- Need R +} + +RAN-NotificationAreaInfo ::= CHOICE { + cellList PLMN-RAN-AreaCellList, + ran-AreaConfigList PLMN-RAN-AreaConfigList, + ... +} + +PLMN-RAN-AreaCellList ::= SEQUENCE (SIZE (1.. maxPLMNIdentities)) OF PLMN-RAN-AreaCell + +PLMN-RAN-AreaCell ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, -- Need S + ran-AreaCells SEQUENCE (SIZE (1..32)) OF CellIdentity +} + +PLMN-RAN-AreaConfigList ::= SEQUENCE (SIZE (1..maxPLMNIdentities)) OF PLMN-RAN-AreaConfig + +PLMN-RAN-AreaConfig ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, -- Need S + ran-Area SEQUENCE (SIZE (1..16)) OF RAN-AreaConfig +} + +RAN-AreaConfig ::= SEQUENCE { + trackingAreaCode TrackingAreaCode, + ran-AreaCodeList SEQUENCE (SIZE (1..32)) OF RAN-AreaCode OPTIONAL -- Need R +} + +-- TAG-RRCRELEASE-STOP +-- TAG-RRCRESUME-START + +RRCResume ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcResume RRCResume-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCResume-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig OPTIONAL, -- Need M + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Need M + measConfig MeasConfig OPTIONAL, -- Need M + fullConfig ENUMERATED {true} OPTIONAL, -- Need N + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCResume-v1560-IEs OPTIONAL +} + +RRCResume-v1560-IEs ::= SEQUENCE { + radioBearerConfig2 OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, -- Need M + sk-Counter SK-Counter OPTIONAL, -- Need N + nonCriticalExtension RRCResume-v1610-IEs OPTIONAL +} + +RRCResume-v1610-IEs ::= SEQUENCE { + idleModeMeasurementReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + restoreMCG-SCells-r16 ENUMERATED {true} OPTIONAL, -- Need N + restoreSCG-r16 ENUMERATED {true} OPTIONAL, -- Need N + mrdc-SecondaryCellGroup-r16 CHOICE { + nr-SCG-r16 OCTET STRING (CONTAINING RRCReconfiguration), + eutra-SCG-r16 OCTET STRING + } OPTIONAL, -- Cond RestoreSCG + needForGapsConfigNR-r16 SetupRelease {NeedForGapsConfigNR-r16} OPTIONAL, -- Need M + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCRESUME-STOP +-- TAG-RRCRESUMECOMPLETE-START + +RRCResumeComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcResumeComplete RRCResumeComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCResumeComplete-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, + selectedPLMN-Identity INTEGER (1..maxPLMN) OPTIONAL, + uplinkTxDirectCurrentList UplinkTxDirectCurrentList OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCResumeComplete-v1610-IEs OPTIONAL +} + +RRCResumeComplete-v1610-IEs ::= SEQUENCE { + idleMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + measResultIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL, + measResultIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + scg-Response-r16 CHOICE { + nr-SCG-Response OCTET STRING (CONTAINING RRCReconfigurationComplete), + eutra-SCG-Response OCTET STRING + } OPTIONAL, + ueMeasurementsAvailable-r16 UEMeasurementsAvailable-r16 OPTIONAL, + mobilityHistoryAvail-r16 ENUMERATED {true} OPTIONAL, + mobilityState-r16 ENUMERATED {normal, medium, high, spare} OPTIONAL, + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCRESUMECOMPLETE-STOP +-- TAG-RRCRESUMEREQUEST-START + +RRCResumeRequest ::= SEQUENCE { + rrcResumeRequest RRCResumeRequest-IEs +} + +RRCResumeRequest-IEs ::= SEQUENCE { + resumeIdentity ShortI-RNTI-Value, + resumeMAC-I BIT STRING (SIZE (16)), + resumeCause ResumeCause, + spare BIT STRING (SIZE (1)) +} + +-- TAG-RRCRESUMEREQUEST-STOP +-- TAG-RRCRESUMEREQUEST1-START + +RRCResumeRequest1 ::= SEQUENCE { + rrcResumeRequest1 RRCResumeRequest1-IEs +} + +RRCResumeRequest1-IEs ::= SEQUENCE { + resumeIdentity I-RNTI-Value, + resumeMAC-I BIT STRING (SIZE (16)), + resumeCause ResumeCause, + spare BIT STRING (SIZE (1)) +} + +-- TAG-RRCRESUMEREQUEST1-STOP +-- TAG-RRCSETUP-START + +RRCSetup ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcSetup RRCSetup-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCSetup-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig, + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig), + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCSETUP-STOP +-- TAG-RRCSETUPCOMPLETE-START + +RRCSetupComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcSetupComplete RRCSetupComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCSetupComplete-IEs ::= SEQUENCE { + selectedPLMN-Identity INTEGER (1..maxPLMN), + registeredAMF RegisteredAMF OPTIONAL, + guami-Type ENUMERATED {native, mapped} OPTIONAL, + s-NSSAI-List SEQUENCE (SIZE (1..maxNrofS-NSSAI)) OF S-NSSAI OPTIONAL, + dedicatedNAS-Message DedicatedNAS-Message, + ng-5G-S-TMSI-Value CHOICE { + ng-5G-S-TMSI NG-5G-S-TMSI, + ng-5G-S-TMSI-Part2 BIT STRING (SIZE (9)) + } OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCSetupComplete-v1610-IEs OPTIONAL +} + +RRCSetupComplete-v1610-IEs ::= SEQUENCE { + iab-NodeIndication-r16 ENUMERATED {true} OPTIONAL, + idleMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + ueMeasurementsAvailable-r16 UEMeasurementsAvailable-r16 OPTIONAL, + mobilityHistoryAvail-r16 ENUMERATED {true} OPTIONAL, + mobilityState-r16 ENUMERATED {normal, medium, high, spare} OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +RegisteredAMF ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, + amf-Identifier AMF-Identifier +} + +-- TAG-RRCSETUPCOMPLETE-STOP +-- TAG-RRCSETUPREQUEST-START + +RRCSetupRequest ::= SEQUENCE { + rrcSetupRequest RRCSetupRequest-IEs +} + +RRCSetupRequest-IEs ::= SEQUENCE { + ue-Identity InitialUE-Identity, + establishmentCause EstablishmentCause, + spare BIT STRING (SIZE (1)) +} + +InitialUE-Identity ::= CHOICE { + ng-5G-S-TMSI-Part1 BIT STRING (SIZE (39)), + randomValue BIT STRING (SIZE (39)) +} + +EstablishmentCause ::= ENUMERATED { + emergency, highPriorityAccess, mt-Access, mo-Signalling, + mo-Data, mo-VoiceCall, mo-VideoCall, mo-SMS, mps-PriorityAccess, mcs-PriorityAccess, + spare6, spare5, spare4, spare3, spare2, spare1} + +-- TAG-RRCSETUPREQUEST-STOP +-- TAG-RRCSYSTEMINFOREQUEST-START + +RRCSystemInfoRequest ::= SEQUENCE { + criticalExtensions CHOICE { + rrcSystemInfoRequest RRCSystemInfoRequest-IEs, + criticalExtensionsFuture-r16 CHOICE { + rrcPosSystemInfoRequest-r16 RRC-PosSystemInfoRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } + } +} + +RRCSystemInfoRequest-IEs ::= SEQUENCE { + requested-SI-List BIT STRING (SIZE (maxSI-Message)), --32bits + spare BIT STRING (SIZE (12)) +} + +RRC-PosSystemInfoRequest-r16-IEs ::= SEQUENCE { + requestedPosSI-List BIT STRING (SIZE (maxSI-Message)), --32bits + spare BIT STRING (SIZE (11)) +} + +-- TAG-RRCSYSTEMINFOREQUEST-STOP +-- TAG-SCGFAILUREINFORMATION-START + +SCGFailureInformation ::= SEQUENCE { + criticalExtensions CHOICE { + scgFailureInformation SCGFailureInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCGFailureInformation-IEs ::= SEQUENCE { + failureReportSCG FailureReportSCG OPTIONAL, + nonCriticalExtension SCGFailureInformation-v1590-IEs OPTIONAL +} + +SCGFailureInformation-v1590-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportSCG ::= SEQUENCE { + failureType ENUMERATED { + t310-Expiry, randomAccessProblem, + rlc-MaxNumRetx, + synchReconfigFailureSCG, scg-ReconfigFailure, + srb3-IntegrityFailure, other-r16, spare1}, + measResultFreqList MeasResultFreqList OPTIONAL, + measResultSCG-Failure OCTET STRING (CONTAINING MeasResultSCG-Failure) OPTIONAL, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL, + failureType-v1610 ENUMERATED {scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, t312-Expiry-r16, bh-RLF-r16, + spare4, spare3, spare2, spare1} OPTIONAL + ]] +} + +MeasResultFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2NR + + +-- TAG-SCGFAILUREINFORMATION-STOP +-- TAG-SCGFAILUREINFORMATIONEUTRA-START + +SCGFailureInformationEUTRA ::= SEQUENCE { + criticalExtensions CHOICE { + scgFailureInformationEUTRA SCGFailureInformationEUTRA-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCGFailureInformationEUTRA-IEs ::= SEQUENCE { + failureReportSCG-EUTRA FailureReportSCG-EUTRA OPTIONAL, + nonCriticalExtension SCGFailureInformationEUTRA-v1590-IEs OPTIONAL +} + +SCGFailureInformationEUTRA-v1590-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportSCG-EUTRA ::= SEQUENCE { + failureType ENUMERATED { + t313-Expiry, randomAccessProblem, + rlc-MaxNumRetx, scg-ChangeFailure, + scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, spare}, + measResultFreqListMRDC MeasResultFreqListFailMRDC OPTIONAL, + measResultSCG-FailureMRDC OCTET STRING OPTIONAL, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL + ]] +} + +MeasResultFreqListFailMRDC ::= SEQUENCE (SIZE (1.. maxFreq)) OF MeasResult2EUTRA + +-- TAG-SCGFAILUREINFORMATIONEUTRA-STOP +-- TAG-SECURITYMODECOMMAND-START + +SecurityModeCommand ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeCommand SecurityModeCommand-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeCommand-IEs ::= SEQUENCE { + securityConfigSMC SecurityConfigSMC, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +SecurityConfigSMC ::= SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig, + ... +} + +-- TAG-SECURITYMODECOMMAND-STOP +-- TAG-SECURITYMODECOMPLETE-START + +SecurityModeComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeComplete SecurityModeComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-SECURITYMODECOMPLETE-STOP +-- TAG-SECURITYMODEFAILURE-START + +SecurityModeFailure ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeFailure SecurityModeFailure-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeFailure-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-SECURITYMODEFAILURE-STOP +-- TAG-SIB1-START + +SIB1 ::= SEQUENCE { + cellSelectionInfo SEQUENCE { + q-RxLevMin Q-RxLevMin, + q-RxLevMinOffset INTEGER (1..8) OPTIONAL, -- Need S + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + q-QualMinOffset INTEGER (1..8) OPTIONAL -- Need S + } OPTIONAL, -- Cond Standalone + cellAccessRelatedInfo CellAccessRelatedInfo, + connEstFailureControl ConnEstFailureControl OPTIONAL, -- Need R + si-SchedulingInfo SI-SchedulingInfo OPTIONAL, -- Need R + servingCellConfigCommon ServingCellConfigCommonSIB OPTIONAL, -- Need R + ims-EmergencySupport ENUMERATED {true} OPTIONAL, -- Need R + eCallOverIMS-Support ENUMERATED {true} OPTIONAL, -- Need R + ue-TimersAndConstants UE-TimersAndConstants OPTIONAL, -- Need R + uac-BarringInfo SEQUENCE { + uac-BarringForCommon UAC-BarringPerCatList OPTIONAL, -- Need S + uac-BarringPerPLMN-List UAC-BarringPerPLMN-List OPTIONAL, -- Need S + uac-BarringInfoSetList UAC-BarringInfoSetList, + uac-AccessCategory1-SelectionAssistanceInfo CHOICE { + plmnCommon UAC-AccessCategory1-SelectionAssistanceInfo, + individualPLMNList SEQUENCE (SIZE (2..maxPLMN)) OF UAC-AccessCategory1-SelectionAssistanceInfo + } OPTIONAL -- Need S + } OPTIONAL, -- Need R + useFullResumeID ENUMERATED {true} OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SIB1-v1610-IEs OPTIONAL +} + +SIB1-v1610-IEs ::= SEQUENCE { + idleModeMeasurementsEUTRA-r16 ENUMERATED{true} OPTIONAL, -- Need R + idleModeMeasurementsNR-r16 ENUMERATED{true} OPTIONAL, -- Need R + posSI-SchedulingInfo-r16 PosSI-SchedulingInfo-r16 OPTIONAL, -- Need R + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UAC-AccessCategory1-SelectionAssistanceInfo ::= ENUMERATED {a, b, c} + +-- TAG-SIB1-STOP +-- TAG-SIDELINKUEINFORMATIONNR-START + +SidelinkUEInformationNR-r16::= SEQUENCE { + criticalExtensions CHOICE { + sidelinkUEInformationNR-r16 SidelinkUEInformationNR-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SidelinkUEInformationNR-r16-IEs ::= SEQUENCE { + sl-RxInterestedFreqList-r16 SL-InterestedFreqList-r16 OPTIONAL, + sl-TxResourceReqList-r16 SL-TxResourceReqList-r16 OPTIONAL, + sl-FailureList-r16 SL-FailureList-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SL-InterestedFreqList-r16 ::= SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF INTEGER (1..maxNrofFreqSL-r16) + +SL-TxResourceReqList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-TxResourceReq-r16 + +SL-TxResourceReq-r16 ::= SEQUENCE { + sl-DestinationIdentity-r16 SL-DestinationIdentity-r16, + sl-CastType-r16 ENUMERATED {broadcast, groupcast, unicast, spare1}, + sl-RLC-ModeIndicationList-r16 SEQUENCE (SIZE (1.. maxNrofSLRB-r16)) OF SL-RLC-ModeIndication-r16 OPTIONAL, + sl-QoS-InfoList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIsPerDest-r16)) OF SL-QoS-Info-r16 OPTIONAL, + sl-TypeTxSyncList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-TypeTxSync-r16 OPTIONAL, + sl-TxInterestedFreqList-r16 SL-TxInterestedFreqList-r16 OPTIONAL, + sl-CapabilityInformationSidelink-r16 OCTET STRING OPTIONAL +} + +SL-TxInterestedFreqList-r16 ::= SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF INTEGER (1..maxNrofFreqSL-r16) + +SL-QoS-Info-r16 ::= SEQUENCE { + sl-QoS-FlowIdentity-r16 SL-QoS-FlowIdentity-r16, + sl-QoS-Profile-r16 SL-QoS-Profile-r16 OPTIONAL +} + +SL-RLC-ModeIndication-r16 ::= SEQUENCE { + sl-Mode-r16 CHOICE { + sl-AM-Mode-r16 NULL, + sl-UM-Mode-r16 NULL + }, + sl-QoS-InfoList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIsPerDest-r16)) OF SL-QoS-Info-r16 +} + +SL-FailureList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-Failure-r16 + +SL-Failure-r16 ::= SEQUENCE { + sl-DestinationIdentity-r16 SL-DestinationIdentity-r16, + sl-Failure-r16 ENUMERATED {rlf,configFailure, spare6, spare5, spare4, spare3, spare2, spare1} +} + +-- TAG-SIDELINKUEINFORMATIONNR-STOP +-- TAG-SYSTEMINFORMATION-START + +SystemInformation ::= SEQUENCE { + criticalExtensions CHOICE { + systemInformation SystemInformation-IEs, + criticalExtensionsFuture-r16 CHOICE { + posSystemInformation-r16 PosSystemInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } + } +} + +SystemInformation-IEs ::= SEQUENCE { + sib-TypeAndInfo SEQUENCE (SIZE (1..maxSIB)) OF CHOICE { + sib2 SIB2, + sib3 SIB3, + sib4 SIB4, + sib5 SIB5, + sib6 SIB6, + sib7 SIB7, + sib8 SIB8, + sib9 SIB9, + ..., + sib10-v1610 SIB10-r16, + sib11-v1610 SIB11-r16, + sib12-v1610 SIB12-r16, + sib13-v1610 SIB13-r16, + sib14-v1610 SIB14-r16 + }, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-SYSTEMINFORMATION-STOP +-- TAG-UEASSISTANCEINFORMATION-START + +UEAssistanceInformation ::= SEQUENCE { + criticalExtensions CHOICE { + ueAssistanceInformation UEAssistanceInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEAssistanceInformation-IEs ::= SEQUENCE { + delayBudgetReport DelayBudgetReport OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UEAssistanceInformation-v1540-IEs OPTIONAL +} + +DelayBudgetReport::= CHOICE { + type1 ENUMERATED { + msMinus1280, msMinus640, msMinus320, msMinus160,msMinus80, msMinus60, msMinus40, + msMinus20, ms0, ms20,ms40, ms60, ms80, ms160, ms320, ms640, ms1280}, + ... +} + +UEAssistanceInformation-v1540-IEs ::= SEQUENCE { + overheatingAssistance OverheatingAssistance OPTIONAL, + nonCriticalExtension UEAssistanceInformation-v1610-IEs OPTIONAL +} + +OverheatingAssistance ::= SEQUENCE { + reducedMaxCCs ReducedMaxCCs-r16 OPTIONAL, + reducedMaxBW-FR1 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxBW-FR2 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxMIMO-LayersFR1 SEQUENCE { + reducedMIMO-LayersFR1-DL MIMO-LayersDL, + reducedMIMO-LayersFR1-UL MIMO-LayersUL + } OPTIONAL, + reducedMaxMIMO-LayersFR2 SEQUENCE { + reducedMIMO-LayersFR2-DL MIMO-LayersDL, + reducedMIMO-LayersFR2-UL MIMO-LayersUL + } OPTIONAL +} + +ReducedAggregatedBandwidth ::= ENUMERATED {mhz0, mhz10, mhz20, mhz30, mhz40, mhz50, mhz60, mhz80, mhz100, mhz200, mhz300, mhz400} + +UEAssistanceInformation-v1610-IEs ::= SEQUENCE { + idc-Assistance-r16 IDC-Assistance-r16 OPTIONAL, + drx-Preference-r16 DRX-Preference-r16 OPTIONAL, + maxBW-Preference-r16 MaxBW-Preference-r16 OPTIONAL, + maxCC-Preference-r16 MaxCC-Preference-r16 OPTIONAL, + maxMIMO-LayerPreference-r16 MaxMIMO-LayerPreference-r16 OPTIONAL, + minSchedulingOffsetPreference-r16 MinSchedulingOffsetPreference-r16 OPTIONAL, + releasePreference-r16 ReleasePreference-r16 OPTIONAL, + sl-UE-AssistanceInformationNR-r16 SL-UE-AssistanceInformationNR-r16 OPTIONAL, + referenceTimeInfoPreference-r16 BOOLEAN OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +IDC-Assistance-r16 ::= SEQUENCE { + affectedCarrierFreqList-r16 AffectedCarrierFreqList-r16 OPTIONAL, + affectedCarrierFreqCombList-r16 AffectedCarrierFreqCombList-r16 OPTIONAL, + ... +} + +AffectedCarrierFreqList-r16 ::= SEQUENCE (SIZE (1.. maxFreqIDC-r16)) OF AffectedCarrierFreq-r16 + +AffectedCarrierFreq-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + interferenceDirection-r16 ENUMERATED {nr, other, both, spare} +} + +AffectedCarrierFreqCombList-r16 ::= SEQUENCE (SIZE (1..maxCombIDC-r16)) OF AffectedCarrierFreqComb-r16 + +AffectedCarrierFreqComb-r16 ::= SEQUENCE { + affectedCarrierFreqComb-r16 SEQUENCE (SIZE (2..maxNrofServingCells)) OF ARFCN-ValueNR OPTIONAL, + victimSystemType-r16 VictimSystemType-r16 +} + +VictimSystemType-r16 ::= SEQUENCE { + gps-r16 ENUMERATED {true} OPTIONAL, + glonass-r16 ENUMERATED {true} OPTIONAL, + bds-r16 ENUMERATED {true} OPTIONAL, + galileo-r16 ENUMERATED {true} OPTIONAL, + navIC-r16 ENUMERATED {true} OPTIONAL, + wlan-r16 ENUMERATED {true} OPTIONAL, + bluetooth-r16 ENUMERATED {true} OPTIONAL, + ... +} + +DRX-Preference-r16 ::= SEQUENCE { + preferredDRX-InactivityTimer-r16 ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1} OPTIONAL, + preferredDRX-LongCycle-r16 ENUMERATED { + ms10, ms20, ms32, ms40, ms60, ms64, ms70, ms80, ms128, ms160, ms256, ms320, ms512, + ms640, ms1024, ms1280, ms2048, ms2560, ms5120, ms10240, spare12, spare11, spare10, + spare9, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, + preferredDRX-ShortCycle-r16 ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, + preferredDRX-ShortCycleTimer-r16 INTEGER (1..16) OPTIONAL +} + +MaxBW-Preference-r16 ::= SEQUENCE { + reducedMaxBW-FR1-r16 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxBW-FR2-r16 ReducedMaxBW-FRx-r16 OPTIONAL +} + +MaxCC-Preference-r16 ::= SEQUENCE { + reducedMaxCCs-r16 ReducedMaxCCs-r16 OPTIONAL +} + +MaxMIMO-LayerPreference-r16 ::= SEQUENCE { + reducedMaxMIMO-LayersFR1-r16 SEQUENCE { + reducedMIMO-LayersFR1-DL-r16 INTEGER (1..8), + reducedMIMO-LayersFR1-UL-r16 INTEGER (1..4) + } OPTIONAL, + reducedMaxMIMO-LayersFR2-r16 SEQUENCE { + reducedMIMO-LayersFR2-DL-r16 INTEGER (1..8), + reducedMIMO-LayersFR2-UL-r16 INTEGER (1..4) + } OPTIONAL +} + +MinSchedulingOffsetPreference-r16 ::= SEQUENCE { + preferredK0-r16 SEQUENCE { + preferredK0-SCS-15kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK0-SCS-30kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK0-SCS-60kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL, + preferredK0-SCS-120kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL + } OPTIONAL, + preferredK2-r16 SEQUENCE { + preferredK2-SCS-15kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK2-SCS-30kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK2-SCS-60kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL, + preferredK2-SCS-120kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL + } OPTIONAL +} + +ReleasePreference-r16 ::= SEQUENCE { + preferredRRC-State-r16 ENUMERATED {idle, inactive, connected, outOfConnected} +} + +ReducedMaxBW-FRx-r16 ::= SEQUENCE { + reducedBW-DL-r16 ReducedAggregatedBandwidth, + reducedBW-UL-r16 ReducedAggregatedBandwidth +} + +ReducedMaxCCs-r16 ::= SEQUENCE { + reducedCCsDL-r16 INTEGER (0..31), + reducedCCsUL-r16 INTEGER (0..31) +} + +SL-UE-AssistanceInformationNR-r16 ::= SEQUENCE (SIZE (1..maxNrofTrafficPattern-r16)) OF SL-TrafficPatternInfo-r16 + +SL-TrafficPatternInfo-r16::= SEQUENCE { + trafficPeriodicity-r16 ENUMERATED {ms20,ms50, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}, + timingOffset-r16 INTEGER (0..10239), + messageSize-r16 BIT STRING (SIZE (8)), + sl-QoS-FlowIdentity-r16 SL-QoS-FlowIdentity-r16 +} + +-- TAG-UEASSISTANCEINFORMATION-STOP +-- TAG-UECAPABILITYENQUIRY-START + +UECapabilityEnquiry ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityEnquiry UECapabilityEnquiry-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityEnquiry-IEs ::= SEQUENCE { + ue-CapabilityRAT-RequestList UE-CapabilityRAT-RequestList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ue-CapabilityEnquiryExt OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL +} + +UECapabilityEnquiry-v1560-IEs ::= SEQUENCE { + capabilityRequestFilterCommon UE-CapabilityRequestFilterCommon OPTIONAL, -- Need N + nonCriticalExtension UECapabilityEnquiry-v1610-IEs OPTIONAL +} + +UECapabilityEnquiry-v1610-IEs ::= SEQUENCE { + rrc-SegAllowed-r16 ENUMERATED {enabled} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UECAPABILITYENQUIRY-STOP +-- TAG-UECAPABILITYINFORMATION-START + +UECapabilityInformation ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityInformation UECapabilityInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityInformation-IEs ::= SEQUENCE { + ue-CapabilityRAT-ContainerList UE-CapabilityRAT-ContainerList OPTIONAL, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-UECAPABILITYINFORMATION-STOP +-- TAG-UEINFORMATIONREQUEST-START + +UEInformationRequest-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueInformationRequest-r16 UEInformationRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEInformationRequest-r16-IEs ::= SEQUENCE { + idleModeMeasurementReq-r16 ENUMERATED{true} OPTIONAL, -- Need N + logMeasReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + connEstFailReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + ra-ReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + rlf-ReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + mobilityHistoryReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UEINFORMATIONREQUEST-STOP +-- TAG-UEINFORMATIONRESPONSE-START + +UEInformationResponse-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueInformationResponse-r16 UEInformationResponse-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEInformationResponse-r16-IEs ::= SEQUENCE { + measResultIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL, + measResultIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + logMeasReport-r16 LogMeasReport-r16 OPTIONAL, + connEstFailReport-r16 ConnEstFailReport-r16 OPTIONAL, + ra-ReportList-r16 RA-ReportList-r16 OPTIONAL, + rlf-Report-r16 RLF-Report-r16 OPTIONAL, + mobilityHistoryReport-r16 MobilityHistoryReport-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +LogMeasReport-r16 ::= SEQUENCE { + absoluteTimeStamp-r16 AbsoluteTimeInfo-r16, + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + logMeasInfoList-r16 LogMeasInfoList-r16, + logMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableBT-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableWLAN-r16 ENUMERATED {true} OPTIONAL, + ... +} + +LogMeasInfoList-r16 ::= SEQUENCE (SIZE (1..maxLogMeasReport-r16)) OF LogMeasInfo-r16 + +LogMeasInfo-r16 ::= SEQUENCE { + locationInfo-r16 LocationInfo-r16 OPTIONAL, + relativeTimeStamp-r16 INTEGER (0..7200), + servCellIdentity-r16 CGI-Info-Logging-r16 OPTIONAL, + measResultServingCell-r16 MeasResultServingCell-r16 OPTIONAL, + measResultNeighCells-r16 SEQUENCE { + measResultNeighCellListNR MeasResultListLogging2NR-r16 OPTIONAL, + measResultNeighCellListEUTRA MeasResultList2EUTRA-r16 OPTIONAL + }, + anyCellSelectionDetected-r16 ENUMERATED {true} OPTIONAL +} + +ConnEstFailReport-r16 ::= SEQUENCE { + measResultFailedCell-r16 MeasResultFailedCell-r16, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + measResultNeighCells-r16 SEQUENCE { + measResultNeighCellListNR MeasResultList2NR-r16 OPTIONAL, + measResultNeighCellListEUTRA MeasResultList2EUTRA-r16 OPTIONAL + }, + numberOfConnFail-r16 INTEGER (1..8), + perRAInfoList-r16 PerRAInfoList-r16, + timeSinceFailure-r16 TimeSinceFailure-r16, + ... +} + +MeasResultServingCell-r16 ::= SEQUENCE { + resultsSSB-Cell MeasQuantityResults, + resultsSSB SEQUENCE{ + best-ssb-Index SSB-Index, + best-ssb-Results MeasQuantityResults, + numberOfGoodSSB INTEGER (1..maxNrofSSBs-r16) + } OPTIONAL +} + +MeasResultFailedCell-r16 ::= SEQUENCE { + cgi-Info CGI-Info-Logging-r16, + measResult-r16 SEQUENCE { + cellResults-r16 SEQUENCE{ + resultsSSB-Cell-r16 MeasQuantityResults + }, + rsIndexResults-r16 SEQUENCE{ + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList + } + } +} + +RA-ReportList-r16 ::= SEQUENCE (SIZE (1..maxRAReport-r16)) OF RA-Report-r16 + +RA-Report-r16 ::= SEQUENCE { + cellId-r16 CGI-Info-Logging-r16, + ra-InformationCommon-r16 RA-InformationCommon-r16, + raPurpose-r16 ENUMERATED {accessRelated, beamFailureRecovery, reconfigurationWithSync, ulUnSynchronized, + schedulingRequestFailure, noPUCCHResourceAvailable, requestForOtherSI, + spare9, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1} +} + +RA-InformationCommon-r16 ::= SEQUENCE { + absoluteFrequencyPointA-r16 ARFCN-ValueNR, + locationAndBandwidth-r16 INTEGER (0..37949), + subcarrierSpacing-r16 SubcarrierSpacing, + msg1-FrequencyStart-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, + msg1-FrequencyStartCFRA-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, + msg1-SubcarrierSpacing-r16 SubcarrierSpacing OPTIONAL, + msg1-SubcarrierSpacingCFRA-r16 SubcarrierSpacing OPTIONAL, + msg1-FDM-r16 ENUMERATED {one, two, four, eight} OPTIONAL, + msg1-FDMCFRA-r16 ENUMERATED {one, two, four, eight} OPTIONAL, + perRAInfoList-r16 PerRAInfoList-r16 +} + +PerRAInfoList-r16 ::= SEQUENCE (SIZE (1..200)) OF PerRAInfo-r16 + +PerRAInfo-r16 ::= CHOICE { + perRASSBInfoList-r16 PerRASSBInfo-r16, + perRACSI-RSInfoList-r16 PerRACSI-RSInfo-r16 +} + +PerRASSBInfo-r16 ::= SEQUENCE { + ssb-Index-r16 SSB-Index, + numberOfPreamblesSentOnSSB-r16 INTEGER (1..200), + perRAAttemptInfoList-r16 PerRAAttemptInfoList-r16 +} + +PerRACSI-RSInfo-r16 ::= SEQUENCE { + csi-RS-Index-r16 CSI-RS-Index, + numberOfPreamblesSentOnCSI-RS-r16 INTEGER (1..200) +} + +PerRAAttemptInfoList-r16 ::= SEQUENCE (SIZE (1..200)) OF PerRAAttemptInfo-r16 + +PerRAAttemptInfo-r16 ::= SEQUENCE { + contentionDetected-r16 BOOLEAN OPTIONAL, + dlRSRPAboveThreshold-r16 BOOLEAN OPTIONAL, + ... +} + +RLF-Report-r16 ::= CHOICE { + nr-RLF-Report-r16 SEQUENCE { + measResultLastServCell-r16 MeasResultRLFNR-r16, + measResultNeighCells-r16 SEQUENCE { + measResultListNR-r16 MeasResultList2NR-r16 OPTIONAL, + measResultListEUTRA-r16 MeasResultList2EUTRA-r16 OPTIONAL + } OPTIONAL, + c-RNTI-r16 RNTI-Value, + previousPCellId-r16 CHOICE { + nrPreviousCell-r16 CGI-Info-Logging-r16, + eutraPreviousCell-r16 CGI-InfoEUTRALogging + } OPTIONAL, + failedPCellId-r16 CHOICE { + nrFailedPCellId-r16 CHOICE { + cellGlobalId-r16 CGI-Info-Logging-r16, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 PhysCellId, + carrierFreq-r16 ARFCN-ValueNR + } + }, + eutraFailedPCellId-r16 CHOICE { + cellGlobalId-r16 CGI-InfoEUTRALogging, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 EUTRA-PhysCellId, + carrierFreq-r16 ARFCN-ValueEUTRA + } + } + }, + reconnectCellId-r16 CHOICE { + nrReconnectCellId-r16 CGI-Info-Logging-r16, + eutraReconnectCellId-r16 CGI-InfoEUTRALogging + } OPTIONAL, + timeUntilReconnection-16 TimeUntilReconnection-16 OPTIONAL, + reestablishmentCellId-r16 CGI-Info-Logging-r16 OPTIONAL, + timeConnFailure-r16 INTEGER (0..1023) OPTIONAL, + timeSinceFailure-r16 TimeSinceFailure-r16, + connectionFailureType-r16 ENUMERATED {rlf, hof}, + rlf-Cause-r16 ENUMERATED {t310-Expiry, randomAccessProblem, rlc-MaxNumRetx, + beamFailureRecoveryFailure, lbtFailure-r16, + bh-rlfRecoveryFailure, spare2, spare1}, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + noSuitableCellFound-r16 ENUMERATED {true} OPTIONAL, + ra-InformationCommon-r16 RA-InformationCommon-r16 OPTIONAL + }, + eutra-RLF-Report-r16 SEQUENCE { + failedPCellId-EUTRA CGI-InfoEUTRALogging, + measResult-RLF-Report-EUTRA-r16 OCTET STRING + } +} + +MeasResultList2NR-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResult2NR-r16 +MeasResultList2EUTRA-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResult2EUTRA-r16 + +MeasResult2NR-r16 ::= SEQUENCE { + ssbFrequency-r16 ARFCN-ValueNR OPTIONAL, + refFreqCSI-RS-r16 ARFCN-ValueNR OPTIONAL, + measResultList-r16 MeasResultListNR +} + +MeasResultListLogging2NR-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResultListLoggingNR-r16 + +MeasResultLogging2NR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + measResultListLoggingNR-r16 MeasResultListLoggingNR-r16 +} + +MeasResultListLoggingNR-r16 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultLoggingNR-r16 + +MeasResultLoggingNR-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + resultsSSB-Cell-r16 MeasQuantityResults, + numberOfGoodSSB-r16 INTEGER (1..maxNrofSSBs-r16) OPTIONAL +} + +MeasResult2EUTRA-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueEUTRA, + measResultList-r16 MeasResultListEUTRA +} + +MeasResultRLFNR-r16 ::= SEQUENCE { + measResult-r16 SEQUENCE { + cellResults-r16 SEQUENCE{ + resultsSSB-Cell-r16 MeasQuantityResults OPTIONAL, + resultsCSI-RS-Cell-r16 MeasQuantityResults OPTIONAL + }, + rsIndexResults-r16 SEQUENCE{ + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList OPTIONAL, + ssbRLMConfigBitmap-r16 BIT STRING (SIZE (64)) OPTIONAL, + resultsCSI-RS-Indexes-r16 ResultsPerCSI-RS-IndexList OPTIONAL, + csi-rsRLMConfigBitmap-r16 BIT STRING (SIZE (96)) OPTIONAL + } OPTIONAL + } +} + +TimeSinceFailure-r16 ::= INTEGER (0..172800) + +MobilityHistoryReport-r16 ::= VisitedCellInfoList-r16 + +TimeUntilReconnection-16 ::= INTEGER (0..172800) + +-- TAG-UEINFORMATIONRESPONSE-STOP +-- TAG-ULDEDICATEDMESSAGESEGMENT-START + +ULDedicatedMessageSegment-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + ulDedicatedMessageSegment-r16 ULDedicatedMessageSegment-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULDedicatedMessageSegment-r16-IEs ::= SEQUENCE { + segmentNumber-r16 INTEGER (0..15), + rrc-MessageSegmentContainer-r16 OCTET STRING, + rrc-MessageSegmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULDEDICATEDMESSAGESEGMENT-STOP +-- TAG-ULINFORMATIONTRANSFER-START + +ULInformationTransfer ::= SEQUENCE { + criticalExtensions CHOICE { + ulInformationTransfer ULInformationTransfer-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransfer-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFER-STOP +-- TAG-ULINFORMATIONTRANSFERIRAT-START + +ULInformationTransferIRAT-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ulInformationTransferIRAT-r16 ULInformationTransferIRAT-r16-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransferIRAT-r16-IEs ::= SEQUENCE { + ul-DCCH-MessageEUTRA-r16 OCTET STRING OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFERIRAT-STOP +-- TAG-ULINFORMATIONTRANSFERMRDC-START + +ULInformationTransferMRDC ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ulInformationTransferMRDC ULInformationTransferMRDC-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransferMRDC-IEs::= SEQUENCE { + ul-DCCH-MessageNR OCTET STRING OPTIONAL, + ul-DCCH-MessageEUTRA OCTET STRING OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFERMRDC-STOP +-- TAG-SETUPRELEASE-START + +SetupRelease { ElementTypeParam } ::= CHOICE { + release NULL, + setup ElementTypeParam +} + +-- TAG-SETUPRELEASE-STOP +-- TAG-SIB2-START + +SIB2 ::= SEQUENCE { + cellReselectionInfoCommon SEQUENCE { + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need S + rangeToBestCell RangeToBestCell OPTIONAL, -- Need R + q-Hyst ENUMERATED { + dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10, + dB12, dB14, dB16, dB18, dB20, dB22, dB24}, + speedStateReselectionPars SEQUENCE { + mobilityStateParameters MobilityStateParameters, + q-HystSF SEQUENCE { + sf-Medium ENUMERATED {dB-6, dB-4, dB-2, dB0}, + sf-High ENUMERATED {dB-6, dB-4, dB-2, dB0} + } + } OPTIONAL, -- Need R + ... + }, + cellReselectionServingFreqInfo SEQUENCE { + s-NonIntraSearchP ReselectionThreshold OPTIONAL, -- Need S + s-NonIntraSearchQ ReselectionThresholdQ OPTIONAL, -- Need S + threshServingLowP ReselectionThreshold, + threshServingLowQ ReselectionThresholdQ OPTIONAL, -- Need R + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + ... + }, + intraFreqCellReselectionInfo SEQUENCE { + q-RxLevMin Q-RxLevMin, + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + s-IntraSearchP ReselectionThreshold, + s-IntraSearchQ ReselectionThresholdQ OPTIONAL, -- Need S + t-ReselectionNR T-Reselection, + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Need S + frequencyBandListSUL MultiFrequencyBandListNR-SIB OPTIONAL, -- Need R + p-Max P-Max OPTIONAL, -- Need S + smtc SSB-MTC OPTIONAL, -- Need S + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, -- Need R + ssb-ToMeasure SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell BOOLEAN, + ..., + [[ + t-ReselectionNR-SF SpeedStateScaleFactors OPTIONAL -- Need N + ]], + [[ + smtc2-LP-r16 SSB-MTC2-LP-r16 OPTIONAL, -- Need R + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum + ]] + }, + ..., + [[ + relaxedMeasurement-r16 SEQUENCE { + lowMobilityEvaluation-r16 SEQUENCE { + s-SearchDeltaP-r16 ENUMERATED { + dB3, dB6, dB9, dB12, dB15, + spare3, spare2, spare1}, + t-SearchDeltaP-r16 ENUMERATED { + s5, s10, s20, s30, s60, s120, s180, + s240, s300, spare7, spare6, spare5, + spare4, spare3, spare2, spare1} + } OPTIONAL, -- Need R + cellEdgeEvaluation-r16 SEQUENCE { + s-SearchThresholdP-r16 ReselectionThreshold, + s-SearchThresholdQ-r16 ReselectionThresholdQ OPTIONAL -- Need R + } OPTIONAL, -- Need R + combineRelaxedMeasCondition-r16 ENUMERATED {true} OPTIONAL, -- Need R + highPriorityMeasRelax-r16 ENUMERATED {true} OPTIONAL -- Need R + } OPTIONAL -- Need R + ]] +} + +RangeToBestCell ::= Q-OffsetRange + +-- TAG-SIB2-STOP +-- TAG-SIB3-START + +SIB3 ::= SEQUENCE { + intraFreqNeighCellList IntraFreqNeighCellList OPTIONAL, -- Need R + intraFreqBlackCellList IntraFreqBlackCellList OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + intraFreqNeighCellList-v1610 IntraFreqNeighCellList-v1610 OPTIONAL, -- Need R + intraFreqWhiteCellList-r16 IntraFreqWhiteCellList-r16 OPTIONAL, -- Cond SharedSpectrum2 + intraFreqCAG-CellList-r16 SEQUENCE (SIZE (1..maxPLMN)) OF IntraFreqCAG-CellPerPLMN-r16 OPTIONAL -- Need R + ]] +} + + +IntraFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo + +IntraFreqNeighCellList-v1610::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo-v1610 + +IntraFreqNeighCellInfo ::= SEQUENCE { + physCellId PhysCellId, + q-OffsetCell Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-RxLevMinOffsetCellSUL INTEGER (1..8) OPTIONAL, -- Need R + q-QualMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + ... +} + +IntraFreqNeighCellInfo-v1610 ::= SEQUENCE { + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum2 +} + +IntraFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PCI-Range + +IntraFreqWhiteCellList-r16 ::= SEQUENCE (SIZE (1..maxCellWhite)) OF PCI-Range + +IntraFreqCAG-CellPerPLMN-r16 ::= SEQUENCE { + plmn-IdentityIndex-r16 INTEGER (1..maxPLMN), + cag-CellList-r16 SEQUENCE (SIZE (1..maxCAG-Cell-r16)) OF PCI-Range +} + +-- TAG-SIB3-STOP +-- TAG-SIB4-START + +SIB4 ::= SEQUENCE { + interFreqCarrierFreqList InterFreqCarrierFreqList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + interFreqCarrierFreqList-v1610 InterFreqCarrierFreqList-v1610 OPTIONAL -- Need R +} + +InterFreqCarrierFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo + +InterFreqCarrierFreqList-v1610 ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo-v1610 + +InterFreqCarrierFreqInfo ::= SEQUENCE { + dl-CarrierFreq ARFCN-ValueNR, + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Cond Mandatory + frequencyBandListSUL MultiFrequencyBandListNR-SIB OPTIONAL, -- Need R + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need S + smtc SSB-MTC OPTIONAL, -- Need S + ssbSubcarrierSpacing SubcarrierSpacing, + ssb-ToMeasure SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell BOOLEAN, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, + q-RxLevMin Q-RxLevMin, + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + p-Max P-Max OPTIONAL, -- Need S + t-ReselectionNR T-Reselection, + t-ReselectionNR-SF SpeedStateScaleFactors OPTIONAL, -- Need S + threshX-HighP ReselectionThreshold, + threshX-LowP ReselectionThreshold, + threshX-Q SEQUENCE { + threshX-HighQ ReselectionThresholdQ, + threshX-LowQ ReselectionThresholdQ + } OPTIONAL, -- Cond RSRQ + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need R + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + q-OffsetFreq Q-OffsetRange DEFAULT dB0, + interFreqNeighCellList InterFreqNeighCellList OPTIONAL, -- Need R + interFreqBlackCellList InterFreqBlackCellList OPTIONAL, -- Need R + ... +} + +InterFreqCarrierFreqInfo-v1610 ::= SEQUENCE { + interFreqNeighCellList-v1610 InterFreqNeighCellList-v1610 OPTIONAL, -- Need R + smtc2-LP-r16 SSB-MTC2-LP-r16 OPTIONAL, -- Need R + interFreqWhiteCellList-r16 InterFreqWhiteCellList-r16 OPTIONAL, -- Cond SharedSpectrum2 + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + interFreqCAG-CellList-r16 SEQUENCE (SIZE (1..maxPLMN)) OF InterFreqCAG-CellList-r16 OPTIONAL -- Need R +} + +InterFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo + +InterFreqNeighCellList-v1610 ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo-v1610 + +InterFreqNeighCellInfo ::= SEQUENCE { + physCellId PhysCellId, + q-OffsetCell Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-RxLevMinOffsetCellSUL INTEGER (1..8) OPTIONAL, -- Need R + + ... +} + +InterFreqNeighCellInfo-v1610 ::= SEQUENCE { + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum2 +} + +InterFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PCI-Range + +InterFreqWhiteCellList-r16 ::= SEQUENCE (SIZE (1..maxCellWhite)) OF PCI-Range + +InterFreqCAG-CellList-r16 ::= SEQUENCE { + plmn-IdentityIndex-r16 INTEGER (1..maxPLMN), + cag-CellList-r16 SEQUENCE (SIZE (1..maxCAG-Cell-r16)) OF PCI-Range +} + +-- TAG-SIB4-STOP +-- TAG-SIB5-START + +SIB5 ::= SEQUENCE { + carrierFreqListEUTRA CarrierFreqListEUTRA OPTIONAL, -- Need R + t-ReselectionEUTRA T-Reselection, + t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need S + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + carrierFreqListEUTRA-v1610 CarrierFreqListEUTRA-v1610 OPTIONAL -- Need R + ]] +} + +CarrierFreqListEUTRA ::= SEQUENCE (SIZE (1..maxEUTRA-Carrier)) OF CarrierFreqEUTRA + +CarrierFreqListEUTRA-v1610 ::= SEQUENCE (SIZE (1..maxEUTRA-Carrier)) OF CarrierFreqEUTRA-v1610 + +CarrierFreqEUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + eutra-multiBandInfoList EUTRA-MultiBandInfoList OPTIONAL, -- Need R + eutra-FreqNeighCellList EUTRA-FreqNeighCellList OPTIONAL, -- Need R + eutra-BlackCellList EUTRA-FreqBlackCellList OPTIONAL, -- Need R + allowedMeasBandwidth EUTRA-AllowedMeasBandwidth, + presenceAntennaPort1 EUTRA-PresenceAntennaPort1, + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need R + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + threshX-High ReselectionThreshold, + threshX-Low ReselectionThreshold, + q-RxLevMin INTEGER (-70..-22), + q-QualMin INTEGER (-34..-3), + p-MaxEUTRA INTEGER (-30..33), + threshX-Q SEQUENCE { + threshX-HighQ ReselectionThresholdQ, + threshX-LowQ ReselectionThresholdQ + } OPTIONAL -- Cond RSRQ +} + +CarrierFreqEUTRA-v1610 ::= SEQUENCE { + highSpeedEUTRACarrier-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +EUTRA-FreqBlackCellList ::= SEQUENCE (SIZE (1..maxEUTRA-CellBlack)) OF EUTRA-PhysCellIdRange + +EUTRA-FreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellEUTRA)) OF EUTRA-FreqNeighCellInfo + +EUTRA-FreqNeighCellInfo ::= SEQUENCE { + physCellId EUTRA-PhysCellId, + dummy EUTRA-Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-QualMinOffsetCell INTEGER (1..8) OPTIONAL -- Need R +} + +-- TAG-SIB5-STOP +-- TAG-SIB6-START + +SIB6 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningType OCTET STRING (SIZE (2)), + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB6-STOP +-- TAG-SIB7-START + +SIB7 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment}, + warningMessageSegmentNumber INTEGER (0..63), + warningMessageSegment OCTET STRING, + dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1 + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB7-STOP +-- TAG-SIB8-START + +SIB8 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment}, + warningMessageSegmentNumber INTEGER (0..63), + warningMessageSegment OCTET STRING, + dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1 + warningAreaCoordinatesSegment OCTET STRING OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB8-STOP +-- TAG-SIB9-START + +SIB9 ::= SEQUENCE { + timeInfo SEQUENCE { + timeInfoUTC INTEGER (0..549755813887), + dayLightSavingTime BIT STRING (SIZE (2)) OPTIONAL, -- Need R + leapSeconds INTEGER (-127..128) OPTIONAL, -- Need R + localTimeOffset INTEGER (-63..64) OPTIONAL -- Need R + } OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + referenceTimeInfo-r16 ReferenceTimeInfo-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SIB9-STOP +-- TAG-SIB10-START + +SIB10-r16 ::= SEQUENCE { + hrnn-List-r16 HRNN-List-r16 OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +HRNN-List-r16 ::= SEQUENCE (SIZE (1..maxNPN-r16)) OF HRNN-r16 + +HRNN-r16 ::= SEQUENCE { + hrnn-r16 OCTET STRING (SIZE(1.. maxHRNN-Len-r16)) OPTIONAL -- Need R +} + +-- TAG-SIB10-STOP +-- TAG-SIB11-START + +SIB11-r16 ::= SEQUENCE { + measIdleConfigSIB-r16 MeasIdleConfigSIB-r16 OPTIONAL, -- Need S + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB11-STOP +-- TAG-SIB12-START + +SIB12-r16 ::= SEQUENCE { + segmentNumber-r16 INTEGER (0..63), + segmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + segmentContainer-r16 OCTET STRING +} + +SIB12-IEs-r16 ::= SEQUENCE { + sl-ConfigCommonNR-r16 SL-ConfigCommonNR-r16, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +SL-ConfigCommonNR-r16 ::= SEQUENCE { + sl-FreqInfoList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-FreqConfigCommon-r16 OPTIONAL, -- Need R + sl-UE-SelectedConfig-r16 SL-UE-SelectedConfig-r16 OPTIONAL, -- Need R + sl-NR-AnchorCarrierFreqList-r16 SL-NR-AnchorCarrierFreqList-r16 OPTIONAL, -- Need R + sl-EUTRA-AnchorCarrierFreqList-r16 SL-EUTRA-AnchorCarrierFreqList-r16 OPTIONAL, -- Need R + sl-RadioBearerConfigList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SL-RadioBearerConfig-r16 OPTIONAL, -- Need R + sl-RLC-BearerConfigList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfig-r16 OPTIONAL, -- Need R + sl-MeasConfigCommon-r16 SL-MeasConfigCommon-r16 OPTIONAL, -- Need R + sl-CSI-Acquisition-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + sl-OffsetDFN-r16 INTEGER (1..1000) OPTIONAL, -- Need R + t400-r16 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000} OPTIONAL, -- Need R + sl-MaxNumConsecutiveDTX-r16 ENUMERATED {n1, n2, n3, n4, n6, n8, n16, n32} OPTIONAL, -- Need R + sl-SSB-PriorityNR-r16 INTEGER (1..8) OPTIONAL -- Need R +} + +SL-NR-AnchorCarrierFreqList-r16 ::= SEQUENCE (SIZE (1..maxFreqSL-NR-r16)) OF ARFCN-ValueNR + +SL-EUTRA-AnchorCarrierFreqList-r16 ::= SEQUENCE (SIZE (1..maxFreqSL-EUTRA-r16)) OF ARFCN-ValueEUTRA + +-- TAG-SIB12-STOP +-- TAG-SIB13-START + +SIB13-r16 ::= SEQUENCE { + sl-V2X-ConfigCommon-r16 OCTET STRING, + sl-Bandwidth-r16 OCTET STRING, + tdd-Config-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB13-STOP +-- TAG-SIB14-START + +SIB14-r16 ::= SEQUENCE { + sl-V2X-ConfigCommonExt-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB14-STOP +-- TAG-POSSYSTEMINFORMATION-R16-IES-START + +PosSystemInformation-r16-IEs ::= SEQUENCE { + posSIB-TypeAndInfo-r16 SEQUENCE (SIZE (1..maxSIB)) OF CHOICE { + posSib1-1-r16 SIBpos-r16, + posSib1-2-r16 SIBpos-r16, + posSib1-3-r16 SIBpos-r16, + posSib1-4-r16 SIBpos-r16, + posSib1-5-r16 SIBpos-r16, + posSib1-6-r16 SIBpos-r16, + posSib1-7-r16 SIBpos-r16, + posSib1-8-r16 SIBpos-r16, + posSib2-1-r16 SIBpos-r16, + posSib2-2-r16 SIBpos-r16, + posSib2-3-r16 SIBpos-r16, + posSib2-4-r16 SIBpos-r16, + posSib2-5-r16 SIBpos-r16, + posSib2-6-r16 SIBpos-r16, + posSib2-7-r16 SIBpos-r16, + posSib2-8-r16 SIBpos-r16, + posSib2-9-r16 SIBpos-r16, + posSib2-10-r16 SIBpos-r16, + posSib2-11-r16 SIBpos-r16, + posSib2-12-r16 SIBpos-r16, + posSib2-13-r16 SIBpos-r16, + posSib2-14-r16 SIBpos-r16, + posSib2-15-r16 SIBpos-r16, + posSib2-16-r16 SIBpos-r16, + posSib2-17-r16 SIBpos-r16, + posSib2-18-r16 SIBpos-r16, + posSib2-19-r16 SIBpos-r16, + posSib2-20-r16 SIBpos-r16, + posSib2-21-r16 SIBpos-r16, + posSib2-22-r16 SIBpos-r16, + posSib2-23-r16 SIBpos-r16, + posSib3-1-r16 SIBpos-r16, + posSib4-1-r16 SIBpos-r16, + posSib5-1-r16 SIBpos-r16, + posSib6-1-r16 SIBpos-r16, + posSib6-2-r16 SIBpos-r16, + posSib6-3-r16 SIBpos-r16, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-POSSYSTEMINFORMATION-R16-IES-STOP +-- TAG-POSSI-SCHEDULINGINFO-START + +PosSI-SchedulingInfo-r16 ::= SEQUENCE { + posSchedulingInfoList-r16 SEQUENCE (SIZE (1..maxSI-Message)) OF PosSchedulingInfo-r16, + posSI-RequestConfig-r16 SI-RequestConfig OPTIONAL, -- Cond MSG-1 + posSI-RequestConfigSUL-r16 SI-RequestConfig OPTIONAL, -- Cond SUL-MSG-1 + ... +} + +PosSchedulingInfo-r16 ::= SEQUENCE { + offsetToSI-Used-r16 ENUMERATED {true} OPTIONAL, -- Need R + posSI-Periodicity-r16 ENUMERATED {rf8, rf16, rf32, rf64, rf128, rf256, rf512}, + posSI-BroadcastStatus-r16 ENUMERATED {broadcasting, notBroadcasting}, + posSIB-MappingInfo-r16 PosSIB-MappingInfo-r16, + ... +} + +PosSIB-MappingInfo-r16 ::= SEQUENCE (SIZE (1..maxSIB)) OF PosSIB-Type-r16 + +PosSIB-Type-r16 ::= SEQUENCE { + encrypted-r16 ENUMERATED { true } OPTIONAL, -- Need R + gnss-id-r16 GNSS-ID-r16 OPTIONAL, -- Need R + sbas-id-r16 SBAS-ID-r16 OPTIONAL, -- Need R + posSibType-r16 ENUMERATED { posSibType1-1, posSibType1-2, posSibType1-3, posSibType1-4, posSibType1-5, posSibType1-6, + posSibType1-7, posSibType1-8, posSibType2-1, posSibType2-2, posSibType2-3, posSibType2-4, + posSibType2-5, posSibType2-6, posSibType2-7, posSibType2-8, posSibType2-9, posSibType2-10, + posSibType2-11, posSibType2-12, posSibType2-13, posSibType2-14, posSibType2-15, + posSibType2-16, posSibType2-17, posSibType2-18, posSibType2-19, posSibType2-20, + posSibType2-21, posSibType2-22, posSibType2-23, posSibType3-1, posSibType4-1, + posSibType5-1,posSibType6-1, posSibType6-2, posSibType6-3,... }, + areaScope-r16 ENUMERATED {true} OPTIONAL -- Need S +} + +GNSS-ID-r16 ::= SEQUENCE { + gnss-id-r16 ENUMERATED{gps, sbas, qzss, galileo, glonass, bds, ...}, + ... +} + +SBAS-ID-r16 ::= SEQUENCE { + sbas-id-r16 ENUMERATED { waas, egnos, msas, gagan, ...}, + ... +} + +-- TAG-POSSI-SCHEDULINGINFO-STOP +-- TAG-SIPOS-START + +SIBpos-r16 ::= SEQUENCE { + assistanceDataSIB-Element-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIPOS-STOP +-- TAG-ADDITIONALSPECTRUMEMISSION-START + +AdditionalSpectrumEmission ::= INTEGER (0..7) + +-- TAG-ADDITIONALSPECTRUMEMISSION-STOP +-- TAG-ALPHA-START + +Alpha ::= ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} + +-- TAG-ALPHA-STOP +-- TAG-AMF-IDENTIFIER-START + +AMF-Identifier ::= BIT STRING (SIZE (24)) + +-- TAG-AMF-IDENTIFIER-STOP +-- TAG-ARFCN-VALUEEUTRA-START + +ARFCN-ValueEUTRA ::= INTEGER (0..maxEARFCN) + +-- TAG-ARFCN-VALUEEUTRA-STOP +-- TAG-ARFCN-VALUENR-START + +ARFCN-ValueNR ::= INTEGER (0..maxNARFCN) + +-- TAG-ARFCN-VALUENR-STOP +-- TAG-ARFCN-ValueUTRA-FDD-START + +ARFCN-ValueUTRA-FDD-r16 ::= INTEGER (0..16383) + +-- TAG-ARFCN-ValueUTRA-FDD-STOP +-- TAG-AVAILABILITYCOMBINATIONSPERCELL-START + +AvailabilityCombinationsPerCell-r16 ::= SEQUENCE { + availabilityCombinationsPerCellIndex-r16 AvailabilityCombinationsPerCellIndex-r16, + iab-DU-CellIdentity-r16 CellIdentity, + positionInDCI-AI-r16 INTEGER(0..maxAI-DCI-PayloadSize-r16-1) OPTIONAL, -- Need M + availabilityCombinations-r16 SEQUENCE (SIZE (1..maxNrofAvailabilityCombinationsPerSet-r16)) OF AvailabilityCombination-r16, + ... +} + +AvailabilityCombinationsPerCellIndex-r16 ::= INTEGER(0..maxNrofDUCells-r16) + +AvailabilityCombination-r16 ::= SEQUENCE { + availabilityCombinationId-r16 AvailabilityCombinationId-r16, + resourceAvailability-r16 SEQUENCE (SIZE (1..maxNrofResourceAvailabilityPerCombination-r16)) OF INTEGER (0..7) +} + +AvailabilityCombinationId-r16 ::= INTEGER (0..maxNrofAvailabilityCombinationsPerSet-r16-1) + +-- TAG-AVAILABILITYCOMBINATIONSPERCELL-STOP +-- TAG-AVAILABILITYINDICATOR-START + +AvailabilityIndicator-r16 ::= SEQUENCE { + ai-RNTI-r16 AI-RNTI-r16, + dci-PayloadSizeAI-r16 INTEGER (1..maxAI-DCI-PayloadSize-r16), + availableCombToAddModList-r16 SEQUENCE (SIZE(1..maxNrofDUCells-r16)) OF AvailabilityCombinationsPerCell-r16 OPTIONAL, -- Need N + availableCombToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofDUCells-r16)) OF AvailabilityCombinationsPerCellIndex-r16 OPTIONAL, -- Need N + ... +} + +AI-RNTI-r16 ::= RNTI-Value + +-- TAG-AVAILABILITYINDICATOR-STOP +-- TAG-BAPROUTINGID-START + +BAP-Routing-ID-r16::= SEQUENCE{ + bap-Address-r16 BIT STRING (SIZE (10)), + bap-PathId-r16 BIT STRING (SIZE (10)) +} + +-- TAG-BAPROUTINGID-STOP +-- TAG-BEAMFAILURERECOVERYCONFIG-START + +BeamFailureRecoveryConfig ::= SEQUENCE { + rootSequenceIndex-BFR INTEGER (0..137) OPTIONAL, -- Need M + rach-ConfigBFR RACH-ConfigGeneric OPTIONAL, -- Need M + rsrp-ThresholdSSB RSRP-Range OPTIONAL, -- Need M + candidateBeamRSList SEQUENCE (SIZE(1..maxNrofCandidateBeams)) OF PRACH-ResourceDedicatedBFR OPTIONAL, -- Need M + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, + four, eight, sixteen} OPTIONAL, -- Need M + ra-ssb-OccasionMaskIndex INTEGER (0..15) OPTIONAL, -- Need M + recoverySearchSpaceId SearchSpaceId OPTIONAL, -- Need R + ra-Prioritization RA-Prioritization OPTIONAL, -- Need R + beamFailureRecoveryTimer ENUMERATED {ms10, ms20, ms40, ms60, ms80, ms100, ms150, ms200} OPTIONAL, -- Need M + ..., + [[ + msg1-SubcarrierSpacing SubcarrierSpacing OPTIONAL -- Need M + ]], + [[ + ra-PrioritizationTwoStep-r16 RA-Prioritization OPTIONAL, -- Need R + candidateBeamRSListExt-v1610 SetupRelease{ CandidateBeamRSListExt-r16 } OPTIONAL -- Need M + ]] +} + +PRACH-ResourceDedicatedBFR ::= CHOICE { + ssb BFR-SSB-Resource, + csi-RS BFR-CSIRS-Resource +} + +BFR-SSB-Resource ::= SEQUENCE { + ssb SSB-Index, + ra-PreambleIndex INTEGER (0..63), + ... +} + +BFR-CSIRS-Resource ::= SEQUENCE { + csi-RS NZP-CSI-RS-ResourceId, + ra-OccasionList SEQUENCE (SIZE(1..maxRA-OccasionsPerCSIRS)) OF INTEGER (0..maxRA-Occasions-1) OPTIONAL, -- Need R + ra-PreambleIndex INTEGER (0..63) OPTIONAL, -- Need R + ... +} + +CandidateBeamRSListExt-r16::= SEQUENCE (SIZE(1.. maxNrofCandidateBeamsExt-r16)) OF PRACH-ResourceDedicatedBFR + +-- TAG-BEAMFAILURERECOVERYCONFIG-STOP +-- TAG-BEAMFAILURERECOVERYSCELLCONFIG-START + +BeamFailureRecoverySCellConfig-r16 ::= SEQUENCE { + rsrp-ThresholdBFR-r16 RSRP-Range OPTIONAL, -- Need M + candidateBeamRSSCellList-r16 SEQUENCE (SIZE(1..maxNrofCandidateBeams-r16)) OF CandidateBeamRS-r16 OPTIONAL, -- Need M + ... +} + +CandidateBeamRS-r16 ::= SEQUENCE { + candidateBeamConfig-r16 CHOICE { + ssb-r16 SSB-Index, + csi-RS-r16 NZP-CSI-RS-ResourceId + }, + servingCellId ServCellIndex OPTIONAL -- Need R +} + +-- TAG-BEAMFAILURERECOVERYSCELLCONFIG-STOP +-- TAG-BETAOFFSETS-START + +BetaOffsets ::= SEQUENCE { + betaOffsetACK-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetACK-Index2 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetACK-Index3 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part1-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part1-Index2 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part2-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part2-Index2 INTEGER(0..31) OPTIONAL -- Need S +} + +-- TAG-BETAOFFSETS-STOP +-- TAG-BH-RLCCHANNELCONFIG-START + +BH-RLC-ChannelConfig-r16::= SEQUENCE { + bh-LogicalChannelIdentity-r16 BH-LogicalChannelIdentity-r16 OPTIONAL, -- Cond LCH-SetupOnly + bh-RLC-ChannelID-r16 BH-RLC-ChannelID-r16, + reestablishRLC-r16 ENUMERATED {true} OPTIONAL, -- Need N + rlc-Config-r16 RLC-Config OPTIONAL, -- Cond LCH-Setup + mac-LogicalChannelConfig-r16 LogicalChannelConfig OPTIONAL, -- Cond LCH-Setup + ... +} + +-- TAG-BH-RLCCHANNELCONFIG-STOP +-- TAG-BH-LOGICALCHANNELIDENTITY-START + +BH-LogicalChannelIdentity-r16 ::= CHOICE { + bh-LogicalChannelIdentity-r16 LogicalChannelIdentity, + bh-LogicalChannelIdentityExt-r16 BH-LogicalChannelIdentity-Ext-r16 +} + +-- TAG-BH-LOGICALCHANNELIDENTITY-STOP +-- TAG-BH-LOGICALCHANNELIDENTITY-Ext-START + +BH-LogicalChannelIdentity-Ext-r16 ::= INTEGER (33.. maxLC-ID-Iab-r16) + +-- TAG-BH-LOGICALCHANNELIDENTITY-Ext-STOP +-- TAG-BHRLCCHANNELID-START + +BH-RLC-ChannelID-r16 ::= BIT STRING (SIZE (16)) + +-- TAG-BHRLCCHANNELID-STOP +-- TAG-BSR-CONFIG-START + +BSR-Config ::= SEQUENCE { + periodicBSR-Timer ENUMERATED { sf1, sf5, sf10, sf16, sf20, sf32, sf40, sf64, + sf80, sf128, sf160, sf320, sf640, sf1280, sf2560, infinity }, + retxBSR-Timer ENUMERATED { sf10, sf20, sf40, sf80, sf160, sf320, sf640, sf1280, sf2560, + sf5120, sf10240, spare5, spare4, spare3, spare2, spare1}, + logicalChannelSR-DelayTimer ENUMERATED { sf20, sf40, sf64, sf128, sf512, sf1024, sf2560, spare1} OPTIONAL, -- Need R + ... +} + +-- TAG-BSR-CONFIG-STOP +-- TAG-BWP-START + +BWP ::= SEQUENCE { + locationAndBandwidth INTEGER (0..37949), + subcarrierSpacing SubcarrierSpacing, + cyclicPrefix ENUMERATED { extended } OPTIONAL -- Need R +} + + +-- TAG-BWP-STOP +-- TAG-BWP-DOWNLINK-START + +BWP-Downlink ::= SEQUENCE { + bwp-Id BWP-Id, + bwp-Common BWP-DownlinkCommon OPTIONAL, -- Cond SetupOtherBWP + bwp-Dedicated BWP-DownlinkDedicated OPTIONAL, -- Cond SetupOtherBWP + ... +} + +-- TAG-BWP-DOWNLINK-STOP +-- TAG-BWP-DOWNLINKCOMMON-START + +BWP-DownlinkCommon ::= SEQUENCE { + genericParameters BWP, + pdcch-ConfigCommon SetupRelease { PDCCH-ConfigCommon } OPTIONAL, -- Need M + pdsch-ConfigCommon SetupRelease { PDSCH-ConfigCommon } OPTIONAL, -- Need M + ... +} + +-- TAG-BWP-DOWNLINKCOMMON-STOP +-- TAG-BWP-DOWNLINKDEDICATED-START + +BWP-DownlinkDedicated ::= SEQUENCE { + pdcch-Config SetupRelease { PDCCH-Config } OPTIONAL, -- Need M + pdsch-Config SetupRelease { PDSCH-Config } OPTIONAL, -- Need M + sps-Config SetupRelease { SPS-Config } OPTIONAL, -- Need M + radioLinkMonitoringConfig SetupRelease { RadioLinkMonitoringConfig } OPTIONAL, -- Need M + ..., + [[ + sps-ConfigToAddModList-r16 SPS-ConfigToAddModList-r16 OPTIONAL, -- Need N + sps-ConfigToReleaseList-r16 SPS-ConfigToReleaseList-r16 OPTIONAL, -- Need N + sps-ConfigDeactivationStateList-r16 SPS-ConfigDeactivationStateList-r16 OPTIONAL, -- Need R + beamFailureRecoverySCellConfig-r16 SetupRelease {BeamFailureRecoverySCellConfig-r16} OPTIONAL, -- Cond SCellOnly + sl-PDCCH-Config-r16 SetupRelease { PDCCH-Config } OPTIONAL, -- Need M + sl-V2X-PDCCH-Config-r16 SetupRelease { PDCCH-Config } OPTIONAL -- Need M + ]] +} + +SPS-ConfigToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-Config + +SPS-ConfigToReleaseList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-ConfigIndex-r16 + +SPS-ConfigDeactivationState-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-ConfigIndex-r16 + +SPS-ConfigDeactivationStateList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-DeactivationState)) OF SPS-ConfigDeactivationState-r16 + +-- TAG-BWP-DOWNLINKDEDICATED-STOP +-- TAG-BWP-ID-START + +BWP-Id ::= INTEGER (0..maxNrofBWPs) + +-- TAG-BWP-ID-STOP +-- TAG-BWP-UPLINK-START + +BWP-Uplink ::= SEQUENCE { + bwp-Id BWP-Id, + bwp-Common BWP-UplinkCommon OPTIONAL, -- Cond SetupOtherBWP + bwp-Dedicated BWP-UplinkDedicated OPTIONAL, -- Cond SetupOtherBWP + ... +} + +-- TAG-BWP-UPLINK-STOP +-- TAG-BWP-UPLINKCOMMON-START + +BWP-UplinkCommon ::= SEQUENCE { + genericParameters BWP, + rach-ConfigCommon SetupRelease { RACH-ConfigCommon } OPTIONAL, -- Need M + pusch-ConfigCommon SetupRelease { PUSCH-ConfigCommon } OPTIONAL, -- Need M + pucch-ConfigCommon SetupRelease { PUCCH-ConfigCommon } OPTIONAL, -- Need M + ..., + [[ + rach-ConfigCommonIAB-r16 SetupRelease { RACH-ConfigCommon } OPTIONAL, -- Need M + useInterlacePUCCH-PUSCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + msgA-ConfigCommon-r16 SetupRelease { MsgA-ConfigCommon-r16 } OPTIONAL -- Cond SpCellOnly2 + ]] +} + +-- TAG-BWP-UPLINKCOMMON-STOP +-- TAG-BWP-UPLINKDEDICATED-START + +BWP-UplinkDedicated ::= SEQUENCE { + pucch-Config SetupRelease { PUCCH-Config } OPTIONAL, -- Need M + pusch-Config SetupRelease { PUSCH-Config } OPTIONAL, -- Need M + configuredGrantConfig SetupRelease { ConfiguredGrantConfig } OPTIONAL, -- Need M + srs-Config SetupRelease { SRS-Config } OPTIONAL, -- Need M + beamFailureRecoveryConfig SetupRelease { BeamFailureRecoveryConfig } OPTIONAL, -- Cond SpCellOnly + ..., + [[ + sl-PUCCH-Config-r16 SetupRelease { PUCCH-Config } OPTIONAL, -- Need M + cp-ExtensionC2-r16 INTEGER (1..28) OPTIONAL, -- Need R + cp-ExtensionC3-r16 INTEGER (1..28) OPTIONAL, -- Need R + useInterlacePUCCH-PUSCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + pucch-ConfigurationList-r16 SetupRelease { PUCCH-ConfigurationList-r16 } OPTIONAL, -- Need M + lbt-FailureRecoveryConfig-r16 SetupRelease { LBT-FailureRecoveryConfig-r16 } OPTIONAL, -- Need M + configuredGrantConfigToAddModList-r16 ConfiguredGrantConfigToAddModList-r16 OPTIONAL, -- Need N + configuredGrantConfigToReleaseList-r16 ConfiguredGrantConfigToReleaseList-r16 OPTIONAL, -- Need N + configuredGrantConfigType2DeactivationStateList-r16 ConfiguredGrantConfigType2DeactivationStateList-r16 OPTIONAL -- Need R + ]] + +} + +ConfiguredGrantConfigToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfig + +ConfiguredGrantConfigToReleaseList-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfigIndex-r16 + +ConfiguredGrantConfigType2DeactivationState-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfigIndex-r16 + +ConfiguredGrantConfigType2DeactivationStateList-r16 ::= + SEQUENCE (SIZE (1..maxNrofCG-Type2DeactivationState)) OF ConfiguredGrantConfigType2DeactivationState-r16 + +-- TAG-BWP-UPLINKDEDICATED-STOP +-- TAG-CELLACCESSRELATEDINFO-START + +CellAccessRelatedInfo ::= SEQUENCE { + plmn-IdentityList PLMN-IdentityInfoList, + cellReservedForOtherUse ENUMERATED {true} OPTIONAL, -- Need R + ..., + [[ + cellReservedForFutureUse-r16 ENUMERATED {true} OPTIONAL, -- Need R + npn-IdentityInfoList-r16 NPN-IdentityInfoList-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-CELLACCESSRELATEDINFO-STOP +-- TAG-CELLACCESSRELATEDINFOEUTRA-5GC-START + +CellAccessRelatedInfo-EUTRA-5GC ::= SEQUENCE { + plmn-IdentityList-eutra-5gc PLMN-IdentityList-EUTRA-5GC, + trackingAreaCode-eutra-5gc TrackingAreaCode, + ranac-5gc RAN-AreaCode OPTIONAL, + cellIdentity-eutra-5gc CellIdentity-EUTRA-5GC +} + +PLMN-IdentityList-EUTRA-5GC::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity-EUTRA-5GC + +PLMN-Identity-EUTRA-5GC ::= CHOICE { + plmn-Identity-EUTRA-5GC PLMN-Identity, + plmn-index INTEGER (1..maxPLMN) +} + +CellIdentity-EUTRA-5GC ::= CHOICE { + cellIdentity-EUTRA BIT STRING (SIZE (28)), + cellId-index INTEGER (1..maxPLMN) +} + +-- TAG-CELLACCESSRELATEDINFOEUTRA-5GC-STOP +-- TAG-CELLACCESSRELATEDINFOEUTRA-EPC-START + +CellAccessRelatedInfo-EUTRA-EPC ::= SEQUENCE { + plmn-IdentityList-eutra-epc PLMN-IdentityList-EUTRA-EPC, + trackingAreaCode-eutra-epc BIT STRING (SIZE (16)), + cellIdentity-eutra-epc BIT STRING (SIZE (28)) +} + +PLMN-IdentityList-EUTRA-EPC::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity + +-- TAG-CELLACCESSRELATEDINFOEUTRA-EPC-STOP +-- TAG-CELLGROUPCONFIG-START + +-- Configuration of one Cell-Group: +CellGroupConfig ::= SEQUENCE { + cellGroupId CellGroupId, + rlc-BearerToAddModList SEQUENCE (SIZE(1..maxLC-ID)) OF RLC-BearerConfig OPTIONAL, -- Need N + rlc-BearerToReleaseList SEQUENCE (SIZE(1..maxLC-ID)) OF LogicalChannelIdentity OPTIONAL, -- Need N + mac-CellGroupConfig MAC-CellGroupConfig OPTIONAL, -- Need M + physicalCellGroupConfig PhysicalCellGroupConfig OPTIONAL, -- Need M + spCellConfig SpCellConfig OPTIONAL, -- Need M + sCellToAddModList SEQUENCE (SIZE (1..maxNrofSCells)) OF SCellConfig OPTIONAL, -- Need N + sCellToReleaseList SEQUENCE (SIZE (1..maxNrofSCells)) OF SCellIndex OPTIONAL, -- Need N + ..., + [[ + reportUplinkTxDirectCurrent ENUMERATED {true} OPTIONAL -- Cond BWP-Reconfig + ]], + [[ + bap-Address-r16 BIT STRING (SIZE (10)) OPTIONAL, -- Need M + bh-RLC-ChannelToAddModList-r16 SEQUENCE (SIZE(1..maxBH-RLC-ChannelID-r16)) OF BH-RLC-ChannelConfig-r16 OPTIONAL, -- Need N + bh-RLC-ChannelToReleaseList-r16 SEQUENCE (SIZE(1..maxBH-RLC-ChannelID-r16)) OF BH-RLC-ChannelID-r16 OPTIONAL, -- Need N + f1c-TransferPath-r16 ENUMERATED {lte, nr, both} OPTIONAL, -- Need M + simultaneousTCI-UpdateList1-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousTCI-UpdateList2-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousSpatial-UpdatedList1-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousSpatial-UpdatedList2-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + uplinkTxSwitchingOption-r16 ENUMERATED {switchedUL, dualUL} OPTIONAL -- Need R + ]] +} + +-- Serving cell specific MAC and PHY parameters for a SpCell: +SpCellConfig ::= SEQUENCE { + servCellIndex ServCellIndex OPTIONAL, -- Cond SCG + reconfigurationWithSync ReconfigurationWithSync OPTIONAL, -- Cond ReconfWithSync + rlf-TimersAndConstants SetupRelease { RLF-TimersAndConstants } OPTIONAL, -- Need M + rlmInSyncOutOfSyncThreshold ENUMERATED {n1} OPTIONAL, -- Need S + spCellConfigDedicated ServingCellConfig OPTIONAL, -- Need M + ... +} + +ReconfigurationWithSync ::= SEQUENCE { + spCellConfigCommon ServingCellConfigCommon OPTIONAL, -- Need M + newUE-Identity RNTI-Value, + t304 ENUMERATED {ms50, ms100, ms150, ms200, ms500, ms1000, ms2000, ms10000}, + rach-ConfigDedicated CHOICE { + uplink RACH-ConfigDedicated, + supplementaryUplink RACH-ConfigDedicated + } OPTIONAL, -- Need N + ..., + [[ + smtc SSB-MTC OPTIONAL -- Need S + ]], + [[ + daps-UplinkPowerConfig-r16 DAPS-UplinkPowerConfig-r16 OPTIONAL -- Need N + ]] +} + +DAPS-UplinkPowerConfig-r16 ::= SEQUENCE { + p-DAPS-Source-r16 P-Max, + p-DAPS-Target-r16 P-Max, + uplinkPowerSharingDAPS-Mode-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic } +} + +SCellConfig ::= SEQUENCE { + sCellIndex SCellIndex, + sCellConfigCommon ServingCellConfigCommon OPTIONAL, -- Cond SCellAdd + sCellConfigDedicated ServingCellConfig OPTIONAL, -- Cond SCellAddMod + ..., + [[ + smtc SSB-MTC OPTIONAL -- Need S + ]], + [[ + sCellState-r16 ENUMERATED {activated} OPTIONAL, -- Cond SCellAddSync + secondaryDRX-GroupConfig-r16 ENUMERATED {true} OPTIONAL -- Cond DRX-Config2 + ]]} + +-- TAG-CELLGROUPCONFIG-STOP +-- TAG-CELLGROUPID-START + +CellGroupId ::= INTEGER (0.. maxSecondaryCellGroups) + +-- TAG-CELLGROUPID-STOP +-- TAG-CELLIDENTITY-START + +CellIdentity ::= BIT STRING (SIZE (36)) + +-- TAG-CELLIDENTITY-STOP +-- TAG-CELLRESELECTIONPRIORITY-START + +CellReselectionPriority ::= INTEGER (0..7) + +-- TAG-CELLRESELECTIONPRIORITY-STOP +-- TAG-CELLRESELECTIONSUBPRIORITY-START + +CellReselectionSubPriority ::= ENUMERATED {oDot2, oDot4, oDot6, oDot8} + +-- TAG-CELLRESELECTIONSUBPRIORITY-STOP +-- TAG-CGI-INFOEUTRA-START + +CGI-InfoEUTRA ::= SEQUENCE { + cgi-info-EPC SEQUENCE { + cgi-info-EPC-legacy CellAccessRelatedInfo-EUTRA-EPC, + cgi-info-EPC-list SEQUENCE (SIZE (1..maxPLMN)) OF CellAccessRelatedInfo-EUTRA-EPC OPTIONAL + } OPTIONAL, + cgi-info-5GC SEQUENCE (SIZE (1..maxPLMN)) OF CellAccessRelatedInfo-EUTRA-5GC OPTIONAL, + freqBandIndicator FreqBandIndicatorEUTRA, + multiBandInfoList MultiBandInfoListEUTRA OPTIONAL, + freqBandIndicatorPriority ENUMERATED {true} OPTIONAL +} + +-- TAG-CGI-INFOEUTRA-STOP +-- TAG-CGI-INFOEUTRALOGGING-START + +CGI-InfoEUTRALogging ::= SEQUENCE { + plmn-Identity-eutra-5gc PLMN-Identity OPTIONAL, + trackingAreaCode-eutra-5gc TrackingAreaCode OPTIONAL, + cellIdentity-eutra-5gc BIT STRING (SIZE (28)) OPTIONAL, + plmn-Identity-eutra-epc PLMN-Identity OPTIONAL, + trackingAreaCode-eutra-epc BIT STRING (SIZE (16)) OPTIONAL, + cellIdentity-eutra-epc BIT STRING (SIZE (28)) OPTIONAL +} + +-- TAG-CGI-INFOEUTRALOGGING-STOP +-- TAG-CGI-INFO-NR-START + +CGI-InfoNR ::= SEQUENCE { + plmn-IdentityInfoList PLMN-IdentityInfoList OPTIONAL, + frequencyBandList MultiFrequencyBandListNR OPTIONAL, + noSIB1 SEQUENCE { + ssb-SubcarrierOffset INTEGER (0..15), + pdcch-ConfigSIB1 PDCCH-ConfigSIB1 + } OPTIONAL, + ..., + [[ + npn-IdentityInfoList-r16 NPN-IdentityInfoList-r16 OPTIONAL + ]] +} + +-- TAG-CGI-INFO-NR-STOP +-- TAG-CGI-INFO-LOGGING-START + +CGI-Info-Logging-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + cellIdentity-r16 CellIdentity, + trackingAreaCode-r16 TrackingAreaCode OPTIONAL +} + +-- TAG-CGI-INFO-LOGGING-STOP +-- TAG-CLI-RSSI-RANGE-START + +CLI-RSSI-Range-r16 ::= INTEGER(0..76) + +-- TAG-CLI-RSSI-RANGE-STOP +-- TAG-CODEBOOKCONFIG-START + +CodebookConfig ::= SEQUENCE { + codebookType CHOICE { + type1 SEQUENCE { + subType CHOICE { + typeI-SinglePanel SEQUENCE { + nrOfAntennaPorts CHOICE { + two SEQUENCE { + twoTX-CodebookSubsetRestriction BIT STRING (SIZE (6)) + }, + moreThanTwo SEQUENCE { + n1-n2 CHOICE { + two-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (8)), + two-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (64)), + four-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (16)), + three-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (96)), + six-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (24)), + four-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (128)), + eight-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (32)), + four-three-TypeI-SinglePanel-Restriction BIT STRING (SIZE (192)), + six-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (192)), + twelve-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (48)), + four-four-TypeI-SinglePanel-Restriction BIT STRING (SIZE (256)), + eight-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (256)), + sixteen-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (64)) + }, + typeI-SinglePanel-codebookSubsetRestriction-i2 BIT STRING (SIZE (16)) OPTIONAL -- Need R + } + }, + typeI-SinglePanel-ri-Restriction BIT STRING (SIZE (8)) + }, + typeI-MultiPanel SEQUENCE { + ng-n1-n2 CHOICE { + two-two-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (8)), + two-four-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (16)), + four-two-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (8)), + two-two-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (64)), + two-eight-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (32)), + four-four-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (16)), + two-four-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (128)), + four-two-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (64)) + }, + ri-Restriction BIT STRING (SIZE (4)) + } + }, + codebookMode INTEGER (1..2) + + }, + type2 SEQUENCE { + subType CHOICE { + typeII SEQUENCE { + n1-n2-codebookSubsetRestriction CHOICE { + two-one BIT STRING (SIZE (16)), + two-two BIT STRING (SIZE (43)), + four-one BIT STRING (SIZE (32)), + three-two BIT STRING (SIZE (59)), + six-one BIT STRING (SIZE (48)), + four-two BIT STRING (SIZE (75)), + eight-one BIT STRING (SIZE (64)), + four-three BIT STRING (SIZE (107)), + six-two BIT STRING (SIZE (107)), + twelve-one BIT STRING (SIZE (96)), + four-four BIT STRING (SIZE (139)), + eight-two BIT STRING (SIZE (139)), + sixteen-one BIT STRING (SIZE (128)) + }, + typeII-RI-Restriction BIT STRING (SIZE (2)) + }, + typeII-PortSelection SEQUENCE { + portSelectionSamplingSize ENUMERATED {n1, n2, n3, n4} OPTIONAL, -- Need R + typeII-PortSelectionRI-Restriction BIT STRING (SIZE (2)) + } + }, + phaseAlphabetSize ENUMERATED {n4, n8}, + subbandAmplitude BOOLEAN, + numberOfBeams ENUMERATED {two, three, four} + } + } +} + +CodebookConfig-r16 ::= SEQUENCE { + codebookType CHOICE { + type2 SEQUENCE { + subType CHOICE { + typeII-r16 SEQUENCE { + n1-n2-codebookSubsetRestriction-r16 CHOICE { + two-one BIT STRING (SIZE (16)), + two-two BIT STRING (SIZE (43)), + four-one BIT STRING (SIZE (32)), + three-two BIT STRING (SIZE (59)), + six-one BIT STRING (SIZE (48)), + four-two BIT STRING (SIZE (75)), + eight-one BIT STRING (SIZE (64)), + four-three BIT STRING (SIZE (107)), + six-two BIT STRING (SIZE (107)), + twelve-one BIT STRING (SIZE (96)), + four-four BIT STRING (SIZE (139)), + eight-two BIT STRING (SIZE (139)), + sixteen-one BIT STRING (SIZE (128)) + }, + typeII-RI-Restriction-r16 BIT STRING (SIZE(4)) + }, + typeII-PortSelection-r16 SEQUENCE { + portSelectionSamplingSize-r16 ENUMERATED {n1, n2, n3, n4}, + typeII-PortSelectionRI-Restriction-r16 BIT STRING (SIZE (4)) + } + }, + numberOfPMI-SubbandsPerCQI-Subband-r16 INTEGER (1..2), + paramCombination-r16 INTEGER (1..8) + } + } +} + +-- TAG-CODEBOOKCONFIG-STOP +-- TAG-COMMONLOCATIONINFO-START + +CommonLocationInfo-r16 ::= SEQUENCE { + gnss-TOD-msec-r16 OCTET STRING OPTIONAL, + locationTimestamp-r16 OCTET STRING OPTIONAL, + locationCoordinate-r16 OCTET STRING OPTIONAL, + locationError-r16 OCTET STRING OPTIONAL, + locationSource-r16 OCTET STRING OPTIONAL, + velocityEstimate-r16 OCTET STRING OPTIONAL +} + +-- TAG-COMMONLOCATIONINFO-STOP +-- TAG-CONDRECONFIGID-START + +CondReconfigId-r16 ::= INTEGER (1.. maxNrofCondCells-r16) + +-- TAG-CONDRECONFIGID-STOP +-- TAG-CONDRECONFIGTOADDMODLIST-START + +CondReconfigToAddModList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCondCells-r16)) OF CondReconfigToAddMod-r16 + +CondReconfigToAddMod-r16 ::= SEQUENCE { + condReconfigId-r16 CondReconfigId-r16, + condExecutionCond-r16 SEQUENCE (SIZE (1..2)) OF MeasId OPTIONAL, -- Cond condReconfigAdd + condRRCReconfig-r16 OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, -- Cond condReconfigAdd + ... +} + +-- TAG-CONDRECONFIGTOADDMODLIST-STOP +-- TAG-CONDITIONALRECONFIGURATION-START + +ConditionalReconfiguration-r16 ::= SEQUENCE { + attemptCondReconfig-r16 ENUMERATED {true} OPTIONAL, -- Cond PCell + condReconfigToRemoveList-r16 CondReconfigToRemoveList-r16 OPTIONAL, -- Need N + condReconfigToAddModList-r16 CondReconfigToAddModList-r16 OPTIONAL, -- Need N + ... +} + +CondReconfigToRemoveList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCondCells-r16)) OF CondReconfigId-r16 + +-- TAG-CONDITIONALRECONFIGURATION-STOP +-- TAG-CONFIGUREDGRANTCONFIG-START + +ConfiguredGrantConfig ::= SEQUENCE { + frequencyHopping ENUMERATED {intraSlot, interSlot} OPTIONAL, -- Need S + cg-DMRS-Configuration DMRS-UplinkConfig, + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoder ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + uci-OnPUSCH SetupRelease { CG-UCI-OnPUSCH } OPTIONAL, -- Need M + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch }, + rbg-Size ENUMERATED {config2} OPTIONAL, -- Need S + powerControlLoopToUse ENUMERATED {n0, n1}, + p0-PUSCH-Alpha P0-PUSCH-AlphaSetId, + transformPrecoder ENUMERATED {enabled, disabled} OPTIONAL, -- Need S + nrofHARQ-Processes INTEGER(1..16), + repK ENUMERATED {n1, n2, n4, n8}, + repK-RV ENUMERATED {s1-0231, s2-0303, s3-0000} OPTIONAL, -- Need R + periodicity ENUMERATED { + sym2, sym7, sym1x14, sym2x14, sym4x14, sym5x14, sym8x14, sym10x14, sym16x14, sym20x14, + sym32x14, sym40x14, sym64x14, sym80x14, sym128x14, sym160x14, sym256x14, sym320x14, sym512x14, + sym640x14, sym1024x14, sym1280x14, sym2560x14, sym5120x14, + sym6, sym1x12, sym2x12, sym4x12, sym5x12, sym8x12, sym10x12, sym16x12, sym20x12, sym32x12, + sym40x12, sym64x12, sym80x12, sym128x12, sym160x12, sym256x12, sym320x12, sym512x12, sym640x12, + sym1280x12, sym2560x12 + }, + configuredGrantTimer INTEGER (1..64) OPTIONAL, -- Need R + rrc-ConfiguredUplinkGrant SEQUENCE { + timeDomainOffset INTEGER (0..5119), + timeDomainAllocation INTEGER (0..15), + frequencyDomainAllocation BIT STRING (SIZE(18)), + antennaPort INTEGER (0..31), + dmrs-SeqInitialization INTEGER (0..1) OPTIONAL, -- Need R + precodingAndNumberOfLayers INTEGER (0..63), + srs-ResourceIndicator INTEGER (0..15) OPTIONAL, -- Need R + mcsAndTBS INTEGER (0..31), + frequencyHoppingOffset INTEGER (1.. maxNrofPhysicalResourceBlocks-1) OPTIONAL, -- Need R + pathlossReferenceIndex INTEGER (0..maxNrofPUSCH-PathlossReferenceRSs-1), + ..., + [[ + pusch-RepTypeIndicator-r16 ENUMERATED {pusch-RepTypeA,pusch-RepTypeB} OPTIONAL, -- Need M + frequencyHoppingPUSCH-RepTypeB-r16 ENUMERATED {interRepetition, interSlot} OPTIONAL, -- Cond RepTypeB + timeReferenceSFN-r16 ENUMERATED {sfn512} OPTIONAL -- Need S + ]] + } OPTIONAL, -- Need R + ..., + [[ + cg-RetransmissionTimer-r16 INTEGER (1..64) OPTIONAL, -- Need R + cg-minDFI-Delay-r16 ENUMERATED + {sym7, sym1x14, sym2x14, sym3x14, sym4x14, sym5x14, sym6x14, sym7x14, sym8x14, + sym9x14, sym10x14, sym11x14, sym12x14, sym13x14, sym14x14,sym15x14, sym16x14 + } OPTIONAL, -- Need R + cg-nrofPUSCH-InSlot-r16 INTEGER (1..7) OPTIONAL, -- Need R + cg-nrofSlots-r16 INTEGER (1..40) OPTIONAL, -- Need R + cg-StartingOffsets-r16 CG-StartingOffsets-r16 OPTIONAL, -- Need R + cg-UCI-Multiplexing ENUMERATED {enabled} OPTIONAL, -- Need R + cg-COT-SharingOffset-r16 INTEGER (1..39) OPTIONAL, -- Need R + betaOffsetCG-UCI-r16 INTEGER (0.. 31) OPTIONAL, -- Need R + cg-COT-SharingList-r16 SEQUENCE (SIZE (1..1709)) OF CG-COT-Sharing-r16 OPTIONAL, -- Need R + harq-ProcID-Offset-r16 INTEGER (0..15) OPTIONAL, -- Need M + harq-ProcID-Offset2-r16 INTEGER (0..15) OPTIONAL, -- Need M + configuredGrantConfigIndex-r16 ConfiguredGrantConfigIndex-r16 OPTIONAL, -- Cond CG-List + configuredGrantConfigIndexMAC-r16 ConfiguredGrantConfigIndexMAC-r16 OPTIONAL, -- Cond CG-List + periodicityExt-r16 INTEGER (1..5120) OPTIONAL, -- Need R + startingFromRV0-r16 ENUMERATED {on, off} OPTIONAL, -- Need R + phy-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL, -- Need R + autonomousTx-r16 ENUMERATED {enabled} OPTIONAL -- Cond LCH-BasedPrioritization + ]] + +} + +CG-UCI-OnPUSCH ::= CHOICE { + dynamic SEQUENCE (SIZE (1..4)) OF BetaOffsets, + semiStatic BetaOffsets +} + +CG-COT-Sharing-r16 ::= CHOICE { + noCOT-Sharing-r16 NULL, + cot-Sharing-r16 SEQUENCE { + duration-r16 INTEGER (1.. 39), + offset-r16 INTEGER (1.. 39), + channelAccessPriority-r16 INTEGER (1..4) + } +} + +CG-StartingOffsets-r16 ::= SEQUENCE { + cg-StartingFullBW-InsideCOT-r16 SEQUENCE (SIZE (1..7)) OF INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingFullBW-OutsideCOT-r16 SEQUENCE (SIZE (1..7)) OF INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingPartialBW-InsideCOT-r16 INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingPartialBW-OutsideCOT-r16 INTEGER (0..6) OPTIONAL -- Need R +} + +-- TAG-CONFIGUREDGRANTCONFIG-STOP +-- TAG-CONFIGUREDGRANTCONFIGINDEX-START + +ConfiguredGrantConfigIndex-r16 ::= INTEGER (0.. maxNrofConfiguredGrantConfig-r16-1) + +-- TAG-CONFIGUREDGRANTCONFIGINDEX-STOP +-- TAG-CONFIGUREDGRANTCONFIGINDEXMAC-START + +ConfiguredGrantConfigIndexMAC-r16 ::= INTEGER (0.. maxNrofConfiguredGrantConfigMAC-r16-1) + +-- TAG-CONFIGUREDGRANTCONFIGINDEXMAC-STOP +-- TAG-CONNESTFAILURECONTROL-START + +ConnEstFailureControl ::= SEQUENCE { + connEstFailCount ENUMERATED {n1, n2, n3, n4}, + connEstFailOffsetValidity ENUMERATED {s30, s60, s120, s240, s300, s420, s600, s900}, + connEstFailOffset INTEGER (0..15) OPTIONAL -- Need S +} + +-- TAG-CONNESTFAILURECONTROL-STOP +-- TAG-CONTROLRESOURCESET-START + +ControlResourceSet ::= SEQUENCE { + controlResourceSetId ControlResourceSetId, + + frequencyDomainResources BIT STRING (SIZE (45)), + duration INTEGER (1..maxCoReSetDuration), + cce-REG-MappingType CHOICE { + interleaved SEQUENCE { + reg-BundleSize ENUMERATED {n2, n3, n6}, + interleaverSize ENUMERATED {n2, n3, n6}, + shiftIndex INTEGER(0..maxNrofPhysicalResourceBlocks-1) OPTIONAL -- Need S + }, + nonInterleaved NULL + }, + precoderGranularity ENUMERATED {sameAsREG-bundle, allContiguousRBs}, + tci-StatesPDCCH-ToAddList SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL, -- Cond NotSIB1-initialBWP + tci-StatesPDCCH-ToReleaseList SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL, -- Cond NotSIB1-initialBWP + tci-PresentInDCI ENUMERATED {enabled} OPTIONAL, -- Need S + pdcch-DMRS-ScramblingID INTEGER (0..65535) OPTIONAL, -- Need S + ..., + [[ + rb-Offset-r16 INTEGER (0..5) OPTIONAL, -- Need S + tci-PresentForDCI-Format1-2-r16 INTEGER (1..3) OPTIONAL, -- Need S + coresetPoolIndex-r16 INTEGER (0..1) OPTIONAL, -- Need S + controlResourceSetId-v1610 ControlResourceSetId-v1610 OPTIONAL -- Need S + ]] +} + +-- TAG-CONTROLRESOURCESET-STOP +-- TAG-CONTROLRESOURCESETID-START + +ControlResourceSetId ::= INTEGER (0..maxNrofControlResourceSets-1) + +ControlResourceSetId-r16 ::= INTEGER (0..maxNrofControlResourceSets-1-r16) + +ControlResourceSetId-v1610 ::= INTEGER (maxNrofControlResourceSets..maxNrofControlResourceSets-1-r16) + +-- TAG-CONTROLRESOURCESETID-STOP +-- TAG-CONTROLRESOURCESETZERO-START + +ControlResourceSetZero ::= INTEGER (0..15) + +-- TAG-CONTROLRESOURCESETZERO-STOP +-- TAG-CrossCarrierSchedulingConfig-START + +CrossCarrierSchedulingConfig ::= SEQUENCE { + schedulingCellInfo CHOICE { + own SEQUENCE { -- Cross carrier scheduling: scheduling cell + cif-Presence BOOLEAN + }, + other SEQUENCE { -- Cross carrier scheduling: scheduled cell + schedulingCellId ServCellIndex, + cif-InSchedulingCell INTEGER (1..7) + } + }, + ..., + [[ + carrierIndicatorSize SEQUENCE { + carrierIndicatorSizeForDCI-Format1-2-r16 INTEGER (0..3), + carrierIndicatorSizeForDCI-Format0-2-r16 INTEGER (0..3) + } OPTIONAL -- Cond CIF-PRESENCE + ]] +} + +-- TAG-CrossCarrierSchedulingConfig-STOP +-- TAG-CSI-APERIODICTRIGGERSTATELIST-START + +CSI-AperiodicTriggerStateList ::= SEQUENCE (SIZE (1..maxNrOfCSI-AperiodicTriggers)) OF CSI-AperiodicTriggerState + +CSI-AperiodicTriggerState ::= SEQUENCE { + associatedReportConfigInfoList SEQUENCE (SIZE(1..maxNrofReportConfigPerAperiodicTrigger)) OF CSI-AssociatedReportConfigInfo, + ... +} + +CSI-AssociatedReportConfigInfo ::= SEQUENCE { + reportConfigId CSI-ReportConfigId, + resourcesForChannel CHOICE { + nzp-CSI-RS SEQUENCE { + resourceSet INTEGER (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig), + qcl-info SEQUENCE (SIZE(1..maxNrofAP-CSI-RS-ResourcesPerSet)) OF TCI-StateId + OPTIONAL -- Cond Aperiodic + }, + csi-SSB-ResourceSet INTEGER (1..maxNrofCSI-SSB-ResourceSetsPerConfig) + }, + csi-IM-ResourcesForInterference INTEGER(1..maxNrofCSI-IM-ResourceSetsPerConfig) + OPTIONAL, -- Cond CSI-IM-ForInterference + nzp-CSI-RS-ResourcesForInterference INTEGER (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig) + OPTIONAL, -- Cond NZP-CSI-RS-ForInterference + ... +} + +-- TAG-CSI-APERIODICTRIGGERSTATELIST-STOP +-- TAG-CSI-FREQUENCYOCCUPATION-START + +CSI-FrequencyOccupation ::= SEQUENCE { + startingRB INTEGER (0..maxNrofPhysicalResourceBlocks-1), + nrofRBs INTEGER (24..maxNrofPhysicalResourceBlocksPlus1), + ... +} + +-- TAG-CSI-FREQUENCYOCCUPATION-STOP +-- TAG-CSI-IM-RESOURCE-START + +CSI-IM-Resource ::= SEQUENCE { + csi-IM-ResourceId CSI-IM-ResourceId, + csi-IM-ResourceElementPattern CHOICE { + pattern0 SEQUENCE { + subcarrierLocation-p0 ENUMERATED { s0, s2, s4, s6, s8, s10 }, + symbolLocation-p0 INTEGER (0..12) + }, + pattern1 SEQUENCE { + subcarrierLocation-p1 ENUMERATED { s0, s4, s8 }, + symbolLocation-p1 INTEGER (0..13) + } + } OPTIONAL, -- Need M + freqBand CSI-FrequencyOccupation OPTIONAL, -- Need M + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, -- Cond PeriodicOrSemiPersistent + ... +} + +-- TAG-CSI-IM-RESOURCE-STOP +-- TAG-CSI-IM-RESOURCEID-START + +CSI-IM-ResourceId ::= INTEGER (0..maxNrofCSI-IM-Resources-1) + +-- TAG-CSI-IM-RESOURCEID-STOP +-- TAG-CSI-IM-RESOURCESET-START + +CSI-IM-ResourceSet ::= SEQUENCE { + csi-IM-ResourceSetId CSI-IM-ResourceSetId, + csi-IM-Resources SEQUENCE (SIZE(1..maxNrofCSI-IM-ResourcesPerSet)) OF CSI-IM-ResourceId, + ... +} +-- TAG-CSI-IM-RESOURCESET-STOP +-- TAG-CSI-IM-RESOURCESETID-START + +CSI-IM-ResourceSetId ::= INTEGER (0..maxNrofCSI-IM-ResourceSets-1) + +-- TAG-CSI-IM-RESOURCESETID-STOP +-- TAG-CSI-MEASCONFIG-START + +CSI-MeasConfig ::= SEQUENCE { + nzp-CSI-RS-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-Resources)) OF NZP-CSI-RS-Resource OPTIONAL, -- Need N + nzp-CSI-RS-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-Resources)) OF NZP-CSI-RS-ResourceId OPTIONAL, -- Need N + nzp-CSI-RS-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSets)) OF NZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + nzp-CSI-RS-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSets)) OF NZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + csi-IM-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofCSI-IM-Resources)) OF CSI-IM-Resource OPTIONAL, -- Need N + csi-IM-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-IM-Resources)) OF CSI-IM-ResourceId OPTIONAL, -- Need N + csi-IM-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSets)) OF CSI-IM-ResourceSet OPTIONAL, -- Need N + csi-IM-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSets)) OF CSI-IM-ResourceSetId OPTIONAL, -- Need N + csi-SSB-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSets)) OF CSI-SSB-ResourceSet OPTIONAL, -- Need N + csi-SSB-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSets)) OF CSI-SSB-ResourceSetId OPTIONAL, -- Need N + csi-ResourceConfigToAddModList SEQUENCE (SIZE (1..maxNrofCSI-ResourceConfigurations)) OF CSI-ResourceConfig + OPTIONAL, -- Need N + csi-ResourceConfigToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-ResourceConfigurations)) OF CSI-ResourceConfigId + OPTIONAL, -- Need N + csi-ReportConfigToAddModList SEQUENCE (SIZE (1..maxNrofCSI-ReportConfigurations)) OF CSI-ReportConfig OPTIONAL, -- Need N + csi-ReportConfigToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-ReportConfigurations)) OF CSI-ReportConfigId + OPTIONAL, -- Need N + reportTriggerSize INTEGER (0..6) OPTIONAL, -- Need M + aperiodicTriggerStateList SetupRelease { CSI-AperiodicTriggerStateList } OPTIONAL, -- Need M + semiPersistentOnPUSCH-TriggerStateList SetupRelease { CSI-SemiPersistentOnPUSCH-TriggerStateList } OPTIONAL, -- Need M + ..., + [[ + reportTriggerSizeForDCI-Format0-2-r16 INTEGER (0..6) OPTIONAL -- Need R + ]] +} + +-- TAG-CSI-MEASCONFIG-STOP +-- TAG-CSI-REPORTCONFIG-START + +CSI-ReportConfig ::= SEQUENCE { + reportConfigId CSI-ReportConfigId, + carrier ServCellIndex OPTIONAL, -- Need S + resourcesForChannelMeasurement CSI-ResourceConfigId, + csi-IM-ResourcesForInterference CSI-ResourceConfigId OPTIONAL, -- Need R + nzp-CSI-RS-ResourcesForInterference CSI-ResourceConfigId OPTIONAL, -- Need R + reportConfigType CHOICE { + periodic SEQUENCE { + reportSlotConfig CSI-ReportPeriodicityAndOffset, + pucch-CSI-ResourceList SEQUENCE (SIZE (1..maxNrofBWPs)) OF PUCCH-CSI-Resource + }, + semiPersistentOnPUCCH SEQUENCE { + reportSlotConfig CSI-ReportPeriodicityAndOffset, + pucch-CSI-ResourceList SEQUENCE (SIZE (1..maxNrofBWPs)) OF PUCCH-CSI-Resource + }, + semiPersistentOnPUSCH SEQUENCE { + reportSlotConfig ENUMERATED {sl5, sl10, sl20, sl40, sl80, sl160, sl320}, + reportSlotOffsetList SEQUENCE (SIZE (1.. maxNrofUL-Allocations)) OF INTEGER(0..32), + p0alpha P0-PUSCH-AlphaSetId + }, + aperiodic SEQUENCE { + reportSlotOffsetList SEQUENCE (SIZE (1..maxNrofUL-Allocations)) OF INTEGER(0..32) + } + }, + reportQuantity CHOICE { + none NULL, + cri-RI-PMI-CQI NULL, + cri-RI-i1 NULL, + cri-RI-i1-CQI SEQUENCE { + pdsch-BundleSizeForCSI ENUMERATED {n2, n4} OPTIONAL -- Need S + }, + cri-RI-CQI NULL, + cri-RSRP NULL, + ssb-Index-RSRP NULL, + cri-RI-LI-PMI-CQI NULL + }, + reportFreqConfiguration SEQUENCE { + cqi-FormatIndicator ENUMERATED { widebandCQI, subbandCQI } OPTIONAL, -- Need R + pmi-FormatIndicator ENUMERATED { widebandPMI, subbandPMI } OPTIONAL, -- Need R + csi-ReportingBand CHOICE { + subbands3 BIT STRING(SIZE(3)), + subbands4 BIT STRING(SIZE(4)), + subbands5 BIT STRING(SIZE(5)), + subbands6 BIT STRING(SIZE(6)), + subbands7 BIT STRING(SIZE(7)), + subbands8 BIT STRING(SIZE(8)), + subbands9 BIT STRING(SIZE(9)), + subbands10 BIT STRING(SIZE(10)), + subbands11 BIT STRING(SIZE(11)), + subbands12 BIT STRING(SIZE(12)), + subbands13 BIT STRING(SIZE(13)), + subbands14 BIT STRING(SIZE(14)), + subbands15 BIT STRING(SIZE(15)), + subbands16 BIT STRING(SIZE(16)), + subbands17 BIT STRING(SIZE(17)), + subbands18 BIT STRING(SIZE(18)), + ..., + subbands19-v1530 BIT STRING(SIZE(19)) + } OPTIONAL -- Need S + + } OPTIONAL, -- Need R + timeRestrictionForChannelMeasurements ENUMERATED {configured, notConfigured}, + timeRestrictionForInterferenceMeasurements ENUMERATED {configured, notConfigured}, + codebookConfig CodebookConfig OPTIONAL, -- Need R + dummy ENUMERATED {n1, n2} OPTIONAL, -- Need R + groupBasedBeamReporting CHOICE { + enabled NULL, + disabled SEQUENCE { + nrofReportedRS ENUMERATED {n1, n2, n3, n4} OPTIONAL -- Need S + } + }, + cqi-Table ENUMERATED {table1, table2, table3, spare1} OPTIONAL, -- Need R + subbandSize ENUMERATED {value1, value2}, + non-PMI-PortIndication SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourcesPerConfig)) OF PortIndexFor8Ranks OPTIONAL, -- Need R + ..., + [[ + semiPersistentOnPUSCH-v1530 SEQUENCE { + reportSlotConfig-v1530 ENUMERATED {sl4, sl8, sl16} + } OPTIONAL -- Need R + ]], + [[ + semiPersistentOnPUSCH-v1610 SEQUENCE { + reportSlotOffsetListForDCI-Format0-2-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) + OPTIONAL, -- Need R + reportSlotOffsetListForDCI-Format0-1-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) + OPTIONAL -- Need R + } OPTIONAL, -- Need R + aperiodic-v1610 SEQUENCE { + reportSlotOffsetListForDCI-Format0-2-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) + OPTIONAL, -- Need R + reportSlotOffsetListForDCI-Format0-1-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) + OPTIONAL -- Need R + } OPTIONAL, -- Need R + reportQuantity-r16 CHOICE { + cri-SINR-r16 NULL, + ssb-Index-SINR-r16 NULL + } OPTIONAL, -- Need R + codebookConfig-r16 CodebookConfig-r16 OPTIONAL -- Need R + ]] +} + +CSI-ReportPeriodicityAndOffset ::= CHOICE { + slots4 INTEGER(0..3), + slots5 INTEGER(0..4), + slots8 INTEGER(0..7), + slots10 INTEGER(0..9), + slots16 INTEGER(0..15), + slots20 INTEGER(0..19), + slots40 INTEGER(0..39), + slots80 INTEGER(0..79), + slots160 INTEGER(0..159), + slots320 INTEGER(0..319) +} + +PUCCH-CSI-Resource ::= SEQUENCE { + uplinkBandwidthPartId BWP-Id, + pucch-Resource PUCCH-ResourceId +} + +PortIndexFor8Ranks ::= CHOICE { + portIndex8 SEQUENCE{ + rank1-8 PortIndex8 OPTIONAL, -- Need R + rank2-8 SEQUENCE(SIZE(2)) OF PortIndex8 OPTIONAL, -- Need R + rank3-8 SEQUENCE(SIZE(3)) OF PortIndex8 OPTIONAL, -- Need R + rank4-8 SEQUENCE(SIZE(4)) OF PortIndex8 OPTIONAL, -- Need R + rank5-8 SEQUENCE(SIZE(5)) OF PortIndex8 OPTIONAL, -- Need R + rank6-8 SEQUENCE(SIZE(6)) OF PortIndex8 OPTIONAL, -- Need R + rank7-8 SEQUENCE(SIZE(7)) OF PortIndex8 OPTIONAL, -- Need R + rank8-8 SEQUENCE(SIZE(8)) OF PortIndex8 OPTIONAL -- Need R + }, + portIndex4 SEQUENCE{ + rank1-4 PortIndex4 OPTIONAL, -- Need R + rank2-4 SEQUENCE(SIZE(2)) OF PortIndex4 OPTIONAL, -- Need R + rank3-4 SEQUENCE(SIZE(3)) OF PortIndex4 OPTIONAL, -- Need R + rank4-4 SEQUENCE(SIZE(4)) OF PortIndex4 OPTIONAL -- Need R + }, + portIndex2 SEQUENCE{ + rank1-2 PortIndex2 OPTIONAL, -- Need R + rank2-2 SEQUENCE(SIZE(2)) OF PortIndex2 OPTIONAL -- Need R + }, + portIndex1 NULL +} + +PortIndex8::= INTEGER (0..7) +PortIndex4::= INTEGER (0..3) +PortIndex2::= INTEGER (0..1) + +-- TAG-CSI-REPORTCONFIG-STOP +-- TAG-CSI-REPORTCONFIGID-START + +CSI-ReportConfigId ::= INTEGER (0..maxNrofCSI-ReportConfigurations-1) + +-- TAG-CSI-REPORTCONFIGID-STOP +-- TAG-CSI-RESOURCECONFIG-START + +CSI-ResourceConfig ::= SEQUENCE { + csi-ResourceConfigId CSI-ResourceConfigId, + csi-RS-ResourceSetList CHOICE { + nzp-CSI-RS-SSB SEQUENCE { + nzp-CSI-RS-ResourceSetList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig)) OF NZP-CSI-RS-ResourceSetId OPTIONAL, -- Need R + csi-SSB-ResourceSetList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSetsPerConfig)) OF CSI-SSB-ResourceSetId OPTIONAL -- Need R + }, + csi-IM-ResourceSetList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSetsPerConfig)) OF CSI-IM-ResourceSetId + }, + + bwp-Id BWP-Id, + resourceType ENUMERATED { aperiodic, semiPersistent, periodic }, + ... +} + +-- TAG-CSI-RESOURCECONFIG-STOP +-- TAG-CSI-RESOURCECONFIGID-START + +CSI-ResourceConfigId ::= INTEGER (0..maxNrofCSI-ResourceConfigurations-1) + +-- TAG-CSI-RESOURCECONFIGID-STOP +-- TAG-CSI-RESOURCEPERIODICITYANDOFFSET-START + +CSI-ResourcePeriodicityAndOffset ::= CHOICE { + slots4 INTEGER (0..3), + slots5 INTEGER (0..4), + slots8 INTEGER (0..7), + slots10 INTEGER (0..9), + slots16 INTEGER (0..15), + slots20 INTEGER (0..19), + slots32 INTEGER (0..31), + slots40 INTEGER (0..39), + slots64 INTEGER (0..63), + slots80 INTEGER (0..79), + slots160 INTEGER (0..159), + slots320 INTEGER (0..319), + slots640 INTEGER (0..639) +} + +-- TAG-CSI-RESOURCEPERIODICITYANDOFFSET-STOP +-- TAG-CSI-RS-RESOURCECONFIGMOBILITY-START + +CSI-RS-ResourceConfigMobility ::= SEQUENCE { + subcarrierSpacing SubcarrierSpacing, + csi-RS-CellList-Mobility SEQUENCE (SIZE (1..maxNrofCSI-RS-CellsRRM)) OF CSI-RS-CellMobility, + ..., + [[ + refServCellIndex ServCellIndex OPTIONAL -- Need S + ]] + + +} + +CSI-RS-CellMobility ::= SEQUENCE { + cellId PhysCellId, + csi-rs-MeasurementBW SEQUENCE { + nrofPRBs ENUMERATED { size24, size48, size96, size192, size264}, + startPRB INTEGER(0..2169) + }, + density ENUMERATED {d1,d3} OPTIONAL, -- Need R + csi-rs-ResourceList-Mobility SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesRRM)) OF CSI-RS-Resource-Mobility +} + +CSI-RS-Resource-Mobility ::= SEQUENCE { + csi-RS-Index CSI-RS-Index, + slotConfig CHOICE { + ms4 INTEGER (0..31), + ms5 INTEGER (0..39), + ms10 INTEGER (0..79), + ms20 INTEGER (0..159), + ms40 INTEGER (0..319) + }, + associatedSSB SEQUENCE { + ssb-Index SSB-Index, + isQuasiColocated BOOLEAN + } OPTIONAL, -- Need R + frequencyDomainAllocation CHOICE { + row1 BIT STRING (SIZE (4)), + row2 BIT STRING (SIZE (12)) + }, + firstOFDMSymbolInTimeDomain INTEGER (0..13), + sequenceGenerationConfig INTEGER (0..1023), + ... +} + +CSI-RS-Index ::= INTEGER (0..maxNrofCSI-RS-ResourcesRRM-1) + +-- TAG-CSI-RS-RESOURCECONFIGMOBILITY-STOP +-- TAG-CSI-RS-RESOURCEMAPPING-START + +CSI-RS-ResourceMapping ::= SEQUENCE { + frequencyDomainAllocation CHOICE { + row1 BIT STRING (SIZE (4)), + row2 BIT STRING (SIZE (12)), + row4 BIT STRING (SIZE (3)), + other BIT STRING (SIZE (6)) + }, + nrofPorts ENUMERATED {p1,p2,p4,p8,p12,p16,p24,p32}, + firstOFDMSymbolInTimeDomain INTEGER (0..13), + firstOFDMSymbolInTimeDomain2 INTEGER (2..12) OPTIONAL, -- Need R + cdm-Type ENUMERATED {noCDM, fd-CDM2, cdm4-FD2-TD2, cdm8-FD2-TD4}, + density CHOICE { + dot5 ENUMERATED {evenPRBs, oddPRBs}, + one NULL, + three NULL, + spare NULL + }, + freqBand CSI-FrequencyOccupation, + ... +} + +-- TAG-CSI-RS-RESOURCEMAPPING-STOP +-- TAG-CSI-SEMIPERSISTENTONPUSCHTRIGGERSTATELIST-START + +CSI-SemiPersistentOnPUSCH-TriggerStateList ::= SEQUENCE(SIZE (1..maxNrOfSemiPersistentPUSCH-Triggers)) OF CSI-SemiPersistentOnPUSCH-TriggerState + +CSI-SemiPersistentOnPUSCH-TriggerState ::= SEQUENCE { + associatedReportConfigInfo CSI-ReportConfigId, + ... +} + +-- TAG-CSI-SEMIPERSISTENTONPUSCHTRIGGERSTATELIST-STOP +-- TAG-CSI-SSB-RESOURCESET-START + +CSI-SSB-ResourceSet ::= SEQUENCE { + csi-SSB-ResourceSetId CSI-SSB-ResourceSetId, + csi-SSB-ResourceList SEQUENCE (SIZE(1..maxNrofCSI-SSB-ResourcePerSet)) OF SSB-Index, + ... +} + +-- TAG-CSI-SSB-RESOURCESET-STOP +-- TAG-CSI-SSB-RESOURCESETID-START + +CSI-SSB-ResourceSetId ::= INTEGER (0..maxNrofCSI-SSB-ResourceSets-1) + +-- TAG-CSI-SSB-RESOURCESETID-STOP +-- TAG-DEDICATED-NAS-MESSAGE-START + +DedicatedNAS-Message ::= OCTET STRING + +-- TAG-DEDICATED-NAS-MESSAGE-STOP +-- TAG-DMRS-DOWNLINKCONFIG-START + +DMRS-DownlinkConfig ::= SEQUENCE { + dmrs-Type ENUMERATED {type2} OPTIONAL, -- Need S + dmrs-AdditionalPosition ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + maxLength ENUMERATED {len2} OPTIONAL, -- Need S + scramblingID0 INTEGER (0..65535) OPTIONAL, -- Need S + scramblingID1 INTEGER (0..65535) OPTIONAL, -- Need S + phaseTrackingRS SetupRelease { PTRS-DownlinkConfig } OPTIONAL, -- Need M + ..., + [[ + dmrs-Downlink-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + +} + +-- TAG-DMRS-DOWNLINKCONFIG-STOP +-- TAG-DMRS-UPLINKCONFIG-START + +DMRS-UplinkConfig ::= SEQUENCE { + dmrs-Type ENUMERATED {type2} OPTIONAL, -- Need S + dmrs-AdditionalPosition ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + phaseTrackingRS SetupRelease { PTRS-UplinkConfig } OPTIONAL, -- Need M + maxLength ENUMERATED {len2} OPTIONAL, -- Need S + transformPrecodingDisabled SEQUENCE { + scramblingID0 INTEGER (0..65535) OPTIONAL, -- Need S + scramblingID1 INTEGER (0..65535) OPTIONAL, -- Need S + ..., + [[ + dmrs-Uplink-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + } OPTIONAL, -- Need R + transformPrecodingEnabled SEQUENCE { + nPUSCH-Identity INTEGER(0..1007) OPTIONAL, -- Need S + sequenceGroupHopping ENUMERATED {disabled} OPTIONAL, -- Need S + sequenceHopping ENUMERATED {enabled} OPTIONAL, -- Need S + ..., + [[ + dmrs-UplinkTransformPrecoding-r16 SetupRelease {DMRS-UplinkTransformPrecoding-r16} OPTIONAL -- Need M + ]] + } OPTIONAL, -- Need R + ... +} + +DMRS-UplinkTransformPrecoding-r16 ::= SEQUENCE { + pi2BPSK-ScramblingID0 INTEGER(0..65535) OPTIONAL, -- Need S + pi2BPSK-ScramblingID1 INTEGER(0..65535) OPTIONAL -- Need S +} + +-- TAG-DMRS-UPLINKCONFIG-STOP +-- TAG-DOWNLINKCONFIGCOMMON-START + +DownlinkConfigCommon ::= SEQUENCE { + frequencyInfoDL FrequencyInfoDL OPTIONAL, -- Cond InterFreqHOAndServCellAdd + initialDownlinkBWP BWP-DownlinkCommon OPTIONAL, -- Cond ServCellAdd + ... +} + +-- TAG-DOWNLINKCONFIGCOMMON-STOP +-- TAG-DOWNLINKCONFIGCOMMONSIB-START + +DownlinkConfigCommonSIB ::= SEQUENCE { + frequencyInfoDL FrequencyInfoDL-SIB, + initialDownlinkBWP BWP-DownlinkCommon, + bcch-Config BCCH-Config, + pcch-Config PCCH-Config, + ... +} + + +BCCH-Config ::= SEQUENCE { + modificationPeriodCoeff ENUMERATED {n2, n4, n8, n16}, + ... +} + + +PCCH-Config ::= SEQUENCE { + defaultPagingCycle PagingCycle, + nAndPagingFrameOffset CHOICE { + oneT NULL, + halfT INTEGER (0..1), + quarterT INTEGER (0..3), + oneEighthT INTEGER (0..7), + oneSixteenthT INTEGER (0..15) + }, + ns ENUMERATED {four, two, one}, + firstPDCCH-MonitoringOccasionOfPO CHOICE { + sCS15KHZoneT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..139), + sCS30KHZoneT-SCS15KHZhalfT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..279), + sCS60KHZoneT-SCS30KHZhalfT-SCS15KHZquarterT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..559), + sCS120KHZoneT-SCS60KHZhalfT-SCS30KHZquarterT-SCS15KHZoneEighthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..1119), + sCS120KHZhalfT-SCS60KHZquarterT-SCS30KHZoneEighthT-SCS15KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..2239), + sCS120KHZquarterT-SCS60KHZoneEighthT-SCS30KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..4479), + sCS120KHZoneEighthT-SCS60KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..8959), + sCS120KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..17919) + } OPTIONAL, -- Need R + ..., + [[ + nrofPDCCH-MonitoringOccasionPerSSB-InPO-r16 INTEGER (2..4) OPTIONAL -- Cond SharedSpectrum2 + ]] +} + +-- TAG-DOWNLINKCONFIGCOMMONSIB-STOP +-- TAG-DOWNLINKPREEMPTION-START + +DownlinkPreemption ::= SEQUENCE { + int-RNTI RNTI-Value, + timeFrequencySet ENUMERATED {set0, set1}, + dci-PayloadSize INTEGER (0..maxINT-DCI-PayloadSize), + int-ConfigurationPerServingCell SEQUENCE (SIZE (1..maxNrofServingCells)) OF INT-ConfigurationPerServingCell, + ... +} + +INT-ConfigurationPerServingCell ::= SEQUENCE { + servingCellId ServCellIndex, + positionInDCI INTEGER (0..maxINT-DCI-PayloadSize-1) +} + +-- TAG-DOWNLINKPREEMPTION-STOP +-- TAG-DRB-IDENTITY-START + +DRB-Identity ::= INTEGER (1..32) + +-- TAG-DRB-IDENTITY-STOP +-- TAG-DRX-CONFIG-START + +DRX-Config ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + }, + drx-InactivityTimer ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1}, + drx-HARQ-RTT-TimerDL INTEGER (0..56), + drx-HARQ-RTT-TimerUL INTEGER (0..56), + drx-RetransmissionTimerDL ENUMERATED { + sl0, sl1, sl2, sl4, sl6, sl8, sl16, sl24, sl33, sl40, sl64, sl80, sl96, sl112, sl128, + sl160, sl320, spare15, spare14, spare13, spare12, spare11, spare10, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1}, + drx-RetransmissionTimerUL ENUMERATED { + sl0, sl1, sl2, sl4, sl6, sl8, sl16, sl24, sl33, sl40, sl64, sl80, sl96, sl112, sl128, + sl160, sl320, spare15, spare14, spare13, spare12, spare11, spare10, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-LongCycleStartOffset CHOICE { + ms10 INTEGER(0..9), + ms20 INTEGER(0..19), + ms32 INTEGER(0..31), + ms40 INTEGER(0..39), + ms60 INTEGER(0..59), + ms64 INTEGER(0..63), + ms70 INTEGER(0..69), + ms80 INTEGER(0..79), + ms128 INTEGER(0..127), + ms160 INTEGER(0..159), + ms256 INTEGER(0..255), + ms320 INTEGER(0..319), + ms512 INTEGER(0..511), + ms640 INTEGER(0..639), + ms1024 INTEGER(0..1023), + ms1280 INTEGER(0..1279), + ms2048 INTEGER(0..2047), + ms2560 INTEGER(0..2559), + ms5120 INTEGER(0..5119), + ms10240 INTEGER(0..10239) + }, + shortDRX SEQUENCE { + drx-ShortCycle ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-ShortCycleTimer INTEGER (1..16) + } OPTIONAL, -- Need R + drx-SlotOffset INTEGER (0..31) +} + +-- TAG-DRX-CONFIG-STOP +-- TAG-DRX-CONFIGSECONDARYGROUP-START + +DRX-ConfigSecondaryGroup ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + }, + drx-InactivityTimer ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1} +} + +-- TAG-DRX-CONFIGSECONDARYGROUP-STOP +-- TAG-FILTERCOEFFICIENT-START + +FilterCoefficient ::= ENUMERATED { fc0, fc1, fc2, fc3, fc4, fc5, fc6, fc7, fc8, fc9, fc11, fc13, fc15, fc17, fc19, spare1, ...} + +-- TAG-FILTERCOEFFICIENT-STOP +-- TAG-FREQBANDINDICATORNR-START + +FreqBandIndicatorNR ::= INTEGER (1..1024) + +-- TAG-FREQBANDINDICATORNR-STOP +-- TAG-FREQUENCYINFODL-START + +FrequencyInfoDL ::= SEQUENCE { + absoluteFrequencySSB ARFCN-ValueNR OPTIONAL, -- Cond SpCellAdd + frequencyBandList MultiFrequencyBandListNR, + absoluteFrequencyPointA ARFCN-ValueNR, + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + ... +} + +-- TAG-FREQUENCYINFODL-STOP +-- TAG-FREQUENCYINFODL-SIB-START + +FrequencyInfoDL-SIB ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR-SIB, + offsetToPointA INTEGER (0..2199), + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier +} + +-- TAG-FREQUENCYINFODL-SIB-STOP +-- TAG-FREQUENCYINFOUL-START + +FrequencyInfoUL ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR OPTIONAL, -- Cond FDD-OrSUL + absoluteFrequencyPointA ARFCN-ValueNR OPTIONAL, -- Cond FDD-OrSUL + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + additionalSpectrumEmission AdditionalSpectrumEmission OPTIONAL, -- Need S + p-Max P-Max OPTIONAL, -- Need S + frequencyShift7p5khz ENUMERATED {true} OPTIONAL, -- Cond FDD-TDD-OrSUL-Optional + ... +} + +-- TAG-FREQUENCYINFOUL-STOP +-- TAG-FREQUENCYINFOUL-SIB-START + +FrequencyInfoUL-SIB ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Cond FDD-OrSUL + absoluteFrequencyPointA ARFCN-ValueNR OPTIONAL, -- Cond FDD-OrSUL + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + p-Max P-Max OPTIONAL, -- Need S + frequencyShift7p5khz ENUMERATED {true} OPTIONAL, -- Cond FDD-TDD-OrSUL-Optional + ... +} + +-- TAG-FREQUENCYINFOUL-SIB-STOP +-- TAG-HIGHSPEEDCONFIG-START + +HighSpeedConfig-r16 ::= SEQUENCE { + highSpeedMeasFlag-r16 ENUMERATED {true} OPTIONAL, -- Need R + highSpeedDemodFlag-r16 ENUMERATED {true} OPTIONAL, -- Need R + ... +} + +-- TAG-HIGHSPEEDCONFIG-STOP +-- TAG-HYSTERESIS-START + +Hysteresis ::= INTEGER (0..30) + +-- TAG-HYSTERESIS-STOP +-- TAG-INVALIDSYMBOLPATTERN-START + +InvalidSymbolPattern-r16 ::= SEQUENCE { + symbols-r16 CHOICE { + oneSlot BIT STRING (SIZE (14)), + twoSlots BIT STRING (SIZE (28)) + }, + periodicityAndPattern-r16 CHOICE { + n2 BIT STRING (SIZE (2)), + n4 BIT STRING (SIZE (4)), + n5 BIT STRING (SIZE (5)), + n8 BIT STRING (SIZE (8)), + n10 BIT STRING (SIZE (10)), + n20 BIT STRING (SIZE (20)), + n40 BIT STRING (SIZE (40)) + } OPTIONAL, -- Need M + ... +} + +-- TAG-INVALIDSYMBOLPATTERN-STOP +-- TAG-I-RNTI-VALUE-START + +I-RNTI-Value ::= BIT STRING (SIZE(40)) + +-- TAG-I-RNTI-VALUE-STOP +-- TAG-LBT-FAILURERECOVERYCONFIG-START + +LBT-FailureRecoveryConfig-r16 ::= SEQUENCE { + lbt-FailureInstanceMaxCount-r16 ENUMERATED {n4, n8, n16, n32, n64, n128}, + lbt-FailureDetectionTimer-r16 ENUMERATED {ms10, ms20, ms40, ms80, ms160, ms320}, + ... +} + +-- TAG-LBT-FAILURERECOVERYCONFIG-STOP +-- TAG-LOCATIONINFO-START + +LocationInfo-r16 ::= SEQUENCE { + commonLocationInfo-r16 CommonLocationInfo-r16 OPTIONAL, + bt-LocationInfo-r16 LogMeasResultListBT-r16 OPTIONAL, + wlan-LocationInfo-r16 LogMeasResultListWLAN-r16 OPTIONAL, + sensor-LocationInfo-r16 Sensor-LocationInfo-r16 OPTIONAL, + ... +} + +-- TAG-LOCATIONINFO-STOP +-- TAG-LOCATIONMEASUREMENTINFO-START + +LocationMeasurementInfo ::= CHOICE { + eutra-RSTD EUTRA-RSTD-InfoList, + ..., + eutra-FineTimingDetection NULL, + nr-PRS-Measurement-r16 NR-PRS-MeasurementInfoList-r16 +} + +EUTRA-RSTD-InfoList ::= SEQUENCE (SIZE (1..maxInterRAT-RSTD-Freq)) OF EUTRA-RSTD-Info + +EUTRA-RSTD-Info ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + measPRS-Offset INTEGER (0..39), + ... +} + +NR-PRS-MeasurementInfoList-r16 ::= SEQUENCE (SIZE (1..maxFreqLayers)) OF NR-PRS-MeasurementInfo-r16 + +NR-PRS-MeasurementInfo-r16 ::= SEQUENCE { + dl-PRS-ARFCN-PointA-r16 ARFCN-ValueNR, + nr-MeasPRS-RepetitionAndOffset-r16 CHOICE { + ms20-r16 INTEGER (0..19), + ms40-r16 INTEGER (0..39), + ms80-r16 INTEGER (0..79), + ms160-r16 INTEGER (0..159), + ... + }, + nr-MeasPRS-length-r16 ENUMERATED {ms1dot5, ms3, ms3dot5, ms4, ms5dot5, ms6, spare2, spare1}, + ... +} + +-- TAG-LOCATIONMEASUREMENTINFO-STOP +-- TAG-LOGICALCHANNELCONFIG-START + +LogicalChannelConfig ::= SEQUENCE { + ul-SpecificParameters SEQUENCE { + priority INTEGER (1..16), + prioritisedBitRate ENUMERATED {kBps0, kBps8, kBps16, kBps32, kBps64, kBps128, kBps256, kBps512, + kBps1024, kBps2048, kBps4096, kBps8192, kBps16384, kBps32768, kBps65536, infinity}, + bucketSizeDuration ENUMERATED {ms5, ms10, ms20, ms50, ms100, ms150, ms300, ms500, ms1000, + spare7, spare6, spare5, spare4, spare3,spare2, spare1}, + allowedServingCells SEQUENCE (SIZE (1..maxNrofServingCells-1)) OF ServCellIndex + OPTIONAL, -- PDCP-CADuplication + allowedSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SubcarrierSpacing OPTIONAL, -- Need R + maxPUSCH-Duration ENUMERATED {ms0p02, ms0p04, ms0p0625, ms0p125, ms0p25, ms0p5, spare2, spare1} + OPTIONAL, -- Need R + configuredGrantType1Allowed ENUMERATED {true} OPTIONAL, -- Need R + logicalChannelGroup INTEGER (0..maxLCG-ID) OPTIONAL, -- Need R + schedulingRequestID SchedulingRequestId OPTIONAL, -- Need R + logicalChannelSR-Mask BOOLEAN, + logicalChannelSR-DelayTimerApplied BOOLEAN, + ..., + bitRateQueryProhibitTimer ENUMERATED {s0, s0dot4, s0dot8, s1dot6, s3, s6, s12, s30} OPTIONAL, -- Need R + [[ + allowedCG-List-r16 SEQUENCE (SIZE (0.. maxNrofConfiguredGrantConfigMAC-r16-1)) OF ConfiguredGrantConfigIndexMAC-r16 + OPTIONAL, -- Need S + allowedPHY-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL -- Need S + ]] + } OPTIONAL, -- Cond UL + ..., + [[ + channelAccessPriority-r16 INTEGER (1..4) OPTIONAL, -- Need R + bitRateMultiplier-r16 ENUMERATED {x40, x70, x100, x200} OPTIONAL -- Need R + ]] +} + +-- TAG-LOGICALCHANNELCONFIG-STOP +-- TAG-LOGICALCHANNELIDENTITY-START + +LogicalChannelIdentity ::= INTEGER (1..maxLC-ID) + +-- TAG-LOGICALCHANNELIDENTITY-STOP +-- TAG-MAC-CELLGROUPCONFIG-START + +MAC-CellGroupConfig ::= SEQUENCE { + drx-Config SetupRelease { DRX-Config } OPTIONAL, -- Need M + schedulingRequestConfig SchedulingRequestConfig OPTIONAL, -- Need M + bsr-Config BSR-Config OPTIONAL, -- Need M + tag-Config TAG-Config OPTIONAL, -- Need M + phr-Config SetupRelease { PHR-Config } OPTIONAL, -- Need M + skipUplinkTxDynamic BOOLEAN, + ..., + [[ + csi-Mask BOOLEAN OPTIONAL, -- Need M + dataInactivityTimer SetupRelease { DataInactivityTimer } OPTIONAL -- Cond MCG-Only + ]], + [[ + usePreBSR-r16 ENUMERATED {true} OPTIONAL, -- Need R + schedulingRequestID-LBT-SCell-r16 SchedulingRequestId OPTIONAL, -- Need M + lch-BasedPrioritization-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + schedulingRequestID-BFR-SCell-r16 SchedulingRequestId OPTIONAL, -- Need R + drx-ConfigSecondaryGroup-r16 SetupRelease { DRX-ConfigSecondaryGroup } OPTIONAL -- Need M + ]] +} + +DataInactivityTimer ::= ENUMERATED {s1, s2, s3, s5, s7, s10, s15, s20, s40, s50, s60, s80, s100, s120, s150, s180} + +-- TAG-MAC-CELLGROUPCONFIG-STOP +-- TAG-MEASCONFIG-START + +MeasConfig ::= SEQUENCE { + measObjectToRemoveList MeasObjectToRemoveList OPTIONAL, -- Need N + measObjectToAddModList MeasObjectToAddModList OPTIONAL, -- Need N + reportConfigToRemoveList ReportConfigToRemoveList OPTIONAL, -- Need N + reportConfigToAddModList ReportConfigToAddModList OPTIONAL, -- Need N + measIdToRemoveList MeasIdToRemoveList OPTIONAL, -- Need N + measIdToAddModList MeasIdToAddModList OPTIONAL, -- Need N + s-MeasureConfig CHOICE { + ssb-RSRP RSRP-Range, + csi-RSRP RSRP-Range + } OPTIONAL, -- Need M + quantityConfig QuantityConfig OPTIONAL, -- Need M + measGapConfig MeasGapConfig OPTIONAL, -- Need M + measGapSharingConfig MeasGapSharingConfig OPTIONAL, -- Need M + ..., + [[ + interFrequencyConfig-NoGap-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +MeasObjectToRemoveList ::= SEQUENCE (SIZE (1..maxNrofObjectId)) OF MeasObjectId + +MeasIdToRemoveList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF MeasId + +ReportConfigToRemoveList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigId + +-- TAG-MEASCONFIG-STOP +-- TAG-MEASGAPCONFIG-START + +MeasGapConfig ::= SEQUENCE { + gapFR2 SetupRelease { GapConfig } OPTIONAL, -- Need M + ..., + [[ + gapFR1 SetupRelease { GapConfig } OPTIONAL, -- Need M + gapUE SetupRelease { GapConfig } OPTIONAL -- Need M + ]] + +} + +GapConfig ::= SEQUENCE { + gapOffset INTEGER (0..159), + mgl ENUMERATED {ms1dot5, ms3, ms3dot5, ms4, ms5dot5, ms6}, + mgrp ENUMERATED {ms20, ms40, ms80, ms160}, + mgta ENUMERATED {ms0, ms0dot25, ms0dot5}, + ..., + [[ + refServCellIndicator ENUMERATED {pCell, pSCell, mcg-FR2} OPTIONAL -- Cond NEDCorNRDC + ]], + [[ + refFR2ServCellAsyncCA-r16 ServCellIndex OPTIONAL -- Cond AsyncCA + ]] + +} + +-- TAG-MEASGAPCONFIG-STOP +-- TAG-MEASGAPSHARINGCONFIG-START + +MeasGapSharingConfig ::= SEQUENCE { + gapSharingFR2 SetupRelease { MeasGapSharingScheme } OPTIONAL, -- Need M + ..., + [[ + gapSharingFR1 SetupRelease { MeasGapSharingScheme } OPTIONAL, --Need M + gapSharingUE SetupRelease { MeasGapSharingScheme } OPTIONAL --Need M + ]] + +} + +MeasGapSharingScheme::= ENUMERATED {scheme00, scheme01, scheme10, scheme11} + +-- TAG-MEASGAPSHARINGCONFIG-STOP +-- TAG-MEASID-START + +MeasId ::= INTEGER (1..maxNrofMeasId) + +-- TAG-MEASID-STOP +-- TAG-MEASIDLECONFIG-START + +MeasIdleConfigSIB-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, -- Need S + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, -- Need S + ... +} + +MeasIdleConfigDedicated-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, -- Need N + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, -- Need N + measIdleDuration-r16 ENUMERATED{sec10, sec30, sec60, sec120, sec180, sec240, sec300, spare}, + validityAreaList-r16 ValidityAreaList-r16 OPTIONAL, -- Need N + ... +} + +ValidityAreaList-r16 ::= SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF ValidityArea-r16 + +ValidityArea-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + validityCellList-r16 ValidityCellList OPTIONAL -- Need N +} + +ValidityCellList ::= SEQUENCE (SIZE (1.. maxCellMeasIdle-r16)) OF PCI-Range + +MeasIdleCarrierNR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + ssbSubcarrierSpacing-r16 SubcarrierSpacing, + frequencyBandList MultiFrequencyBandListNR OPTIONAL, -- Need R + measCellListNR-r16 CellListNR-r16 OPTIONAL, -- Need R + reportQuantities-r16 ENUMERATED {rsrp, rsrq, both}, + qualityThreshold-r16 SEQUENCE { + idleRSRP-Threshold-NR-r16 RSRP-Range OPTIONAL, -- Need R + idleRSRQ-Threshold-NR-r16 RSRQ-Range OPTIONAL -- Need R + } OPTIONAL, -- Need R + ssb-MeasConfig-r16 SEQUENCE { + nrofSS-BlocksToAverage-r16 INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation-r16 ThresholdNR OPTIONAL, -- Need S + smtc-r16 SSB-MTC OPTIONAL, -- Need S + ssb-ToMeasure-r16 SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell-r16 BOOLEAN, + ss-RSSI-Measurement-r16 SS-RSSI-Measurement OPTIONAL -- Need S + } OPTIONAL, -- Need S + beamMeasConfigIdle-r16 BeamMeasConfigIdle-NR-r16 OPTIONAL, -- Need R + ... +} + +MeasIdleCarrierEUTRA-r16 ::= SEQUENCE { + carrierFreqEUTRA-r16 ARFCN-ValueEUTRA, + allowedMeasBandwidth-r16 EUTRA-AllowedMeasBandwidth, + measCellListEUTRA-r16 CellListEUTRA-r16 OPTIONAL, -- Need R + reportQuantitiesEUTRA-r16 ENUMERATED {rsrp, rsrq, both}, + qualityThresholdEUTRA-r16 SEQUENCE { + idleRSRP-Threshold-EUTRA-r16 RSRP-RangeEUTRA OPTIONAL, -- Need R + idleRSRQ-Threshold-EUTRA-r16 RSRQ-RangeEUTRA-r16 OPTIONAL -- Need R + } OPTIONAL, -- Need S + ... +} + +CellListNR-r16 ::= SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF PCI-Range + +CellListEUTRA-r16 ::= SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF EUTRA-PhysCellIdRange + +BeamMeasConfigIdle-NR-r16 ::= SEQUENCE { + reportQuantityRS-Indexes-r16 ENUMERATED {rsrp, rsrq, both}, + maxNrofRS-IndexesToReport-r16 INTEGER (1.. maxNrofIndexesToReport), + includeBeamMeasurements-r16 BOOLEAN +} + +RSRQ-RangeEUTRA-r16 ::= INTEGER (-30..46) + +-- TAG-MEASIDLECONFIG-STOP +-- TAG-MEASIDTOADDMODLIST-START + +MeasIdToAddModList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF MeasIdToAddMod + +MeasIdToAddMod ::= SEQUENCE { + measId MeasId, + measObjectId MeasObjectId, + reportConfigId ReportConfigId +} + +-- TAG-MEASIDTOADDMODLIST-STOP +-- TAG-MEASOBJECTCLI-START + +MeasObjectCLI-r16 ::= SEQUENCE { + cli-ResourceConfig-r16 CLI-ResourceConfig-r16, + ... +} + +CLI-ResourceConfig-r16 ::= SEQUENCE { + srs-ResourceConfig-r16 SetupRelease { SRS-ResourceListConfigCLI-r16 } OPTIONAL, -- Need M + rssi-ResourceConfig-r16 SetupRelease { RSSI-ResourceListConfigCLI-r16 } OPTIONAL -- Need M +} + +SRS-ResourceListConfigCLI-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-SRS-Resources-r16)) OF SRS-ResourceConfigCLI-r16 + +RSSI-ResourceListConfigCLI-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-RSSI-Resources-r16)) OF RSSI-ResourceConfigCLI-r16 + +SRS-ResourceConfigCLI-r16 ::= SEQUENCE { + srs-Resource-r16 SRS-Resource, + srs-SCS-r16 SubcarrierSpacing, + ... +} + +RSSI-ResourceConfigCLI-r16 ::= SEQUENCE { + rssi-ResourceId-r16 RSSI-ResourceId-r16, + rssi-SCS-r16 SubcarrierSpacing, + startPRB-r16 INTEGER (0..2169), + nrofPRBs-r16 INTEGER (4..maxNrofPhysicalResourceBlocksPlus1), + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 INTEGER (1..14), + rssi-PeriodicityAndOffset-r16 RSSI-PeriodicityAndOffset-r16, + ... +} + +RSSI-ResourceId-r16 ::= INTEGER (0.. maxNrofCLI-RSSI-Resources-r16-1) + +RSSI-PeriodicityAndOffset-r16 ::= CHOICE { + sl10 INTEGER(0..9), + sl20 INTEGER(0..19), + sl40 INTEGER(0..39), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + s1640 INTEGER(0..639), + ... +} + +-- TAG-MEASOBJECTCLI-STOP +-- TAG-MEASOBJECTEUTRA-START + +MeasObjectEUTRA::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + allowedMeasBandwidth EUTRA-AllowedMeasBandwidth, + cellsToRemoveListEUTRAN EUTRA-CellIndexList OPTIONAL, -- Need N + cellsToAddModListEUTRAN SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-Cell OPTIONAL, -- Need N + blackCellsToRemoveListEUTRAN EUTRA-CellIndexList OPTIONAL, -- Need N + blackCellsToAddModListEUTRAN SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-BlackCell OPTIONAL, -- Need N + eutra-PresenceAntennaPort1 EUTRA-PresenceAntennaPort1, + eutra-Q-OffsetRange EUTRA-Q-OffsetRange OPTIONAL, -- Need R + widebandRSRQ-Meas BOOLEAN, + ... +} + +EUTRA-CellIndexList ::= SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-CellIndex + +EUTRA-CellIndex ::= INTEGER (1..maxCellMeasEUTRA) + + +EUTRA-Cell ::= SEQUENCE { + cellIndexEUTRA EUTRA-CellIndex, + physCellId EUTRA-PhysCellId, + cellIndividualOffset EUTRA-Q-OffsetRange +} + + +EUTRA-BlackCell ::= SEQUENCE { + cellIndexEUTRA EUTRA-CellIndex, + physCellIdRange EUTRA-PhysCellIdRange +} + +-- TAG-MEASOBJECTEUTRA-STOP +-- TAG-MEASOBJECTID-START + +MeasObjectId ::= INTEGER (1..maxNrofObjectId) + +-- TAG-MEASOBJECTID-STOP +-- TAG-MEASOBJECTNR-START + +MeasObjectNR ::= SEQUENCE { + ssbFrequency ARFCN-ValueNR OPTIONAL, -- Cond SSBorAssociatedSSB + ssbSubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond SSBorAssociatedSSB + smtc1 SSB-MTC OPTIONAL, -- Cond SSBorAssociatedSSB + smtc2 SSB-MTC2 OPTIONAL, -- Cond IntraFreqConnected + refFreqCSI-RS ARFCN-ValueNR OPTIONAL, -- Cond CSI-RS + referenceSignalConfig ReferenceSignalConfig, + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need R + absThreshCSI-RS-Consolidation ThresholdNR OPTIONAL, -- Need R + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need R + nrofCSI-RS-ResourcesToAverage INTEGER (2..maxNrofCSI-RS-ResourcesToAverage) OPTIONAL, -- Need R + quantityConfigIndex INTEGER (1..maxNrofQuantityConfig), + offsetMO Q-OffsetRangeList, + cellsToRemoveList PCI-List OPTIONAL, -- Need N + cellsToAddModList CellsToAddModList OPTIONAL, -- Need N + blackCellsToRemoveList PCI-RangeIndexList OPTIONAL, -- Need N + blackCellsToAddModList SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeElement OPTIONAL, -- Need N + whiteCellsToRemoveList PCI-RangeIndexList OPTIONAL, -- Need N + whiteCellsToAddModList SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeElement OPTIONAL, -- Need N + ..., + [[ + freqBandIndicatorNR FreqBandIndicatorNR OPTIONAL, -- Need R + measCycleSCell ENUMERATED {sf160, sf256, sf320, sf512, sf640, sf1024, sf1280} OPTIONAL -- Need R + ]], + [[ + + smtc3list-r16 SSB-MTC3List-r16 OPTIONAL, -- Need R + rmtc-Config-r16 SetupRelease {RMTC-Config-r16} OPTIONAL, -- Need M + t312-r16 SetupRelease { T312-r16 } OPTIONAL -- Need M + ]] +} + +SSB-MTC3List-r16::= SEQUENCE (SIZE(1..4)) OF SSB-MTC3-r16 + +T312-r16 ::= ENUMERATED { ms0, ms50, ms100, ms200, ms300, ms400, ms500, ms1000} + +ReferenceSignalConfig::= SEQUENCE { + ssb-ConfigMobility SSB-ConfigMobility OPTIONAL, -- Need M + csi-rs-ResourceConfigMobility SetupRelease { CSI-RS-ResourceConfigMobility } OPTIONAL -- Need M +} + +SSB-ConfigMobility::= SEQUENCE { + + ssb-ToMeasure SetupRelease { SSB-ToMeasure } OPTIONAL, -- Need M + deriveSSB-IndexFromCell BOOLEAN, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, -- Need M + ..., + [[ + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + ssb-PositionQCL-CellsToAddModList-r16 SSB-PositionQCL-CellsToAddModList-r16 OPTIONAL, -- Need N + ssb-PositionQCL-CellsToRemoveList-r16 PCI-List OPTIONAL -- Need N + ]] + +} + + +Q-OffsetRangeList ::= SEQUENCE { + rsrpOffsetSSB Q-OffsetRange DEFAULT dB0, + rsrqOffsetSSB Q-OffsetRange DEFAULT dB0, + sinrOffsetSSB Q-OffsetRange DEFAULT dB0, + rsrpOffsetCSI-RS Q-OffsetRange DEFAULT dB0, + rsrqOffsetCSI-RS Q-OffsetRange DEFAULT dB0, + sinrOffsetCSI-RS Q-OffsetRange DEFAULT dB0 +} + + +ThresholdNR ::= SEQUENCE{ + thresholdRSRP RSRP-Range OPTIONAL, -- Need R + thresholdRSRQ RSRQ-Range OPTIONAL, -- Need R + thresholdSINR SINR-Range OPTIONAL -- Need R +} + +CellsToAddModList ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF CellsToAddMod + +CellsToAddMod ::= SEQUENCE { + physCellId PhysCellId, + cellIndividualOffset Q-OffsetRangeList +} + +RMTC-Config-r16 ::= SEQUENCE { + rmtc-Periodicity-r16 ENUMERATED {ms40, ms80, ms160, ms320, ms640}, + rmtc-SubframeOffset-r16 INTEGER(0..639) OPTIONAL, -- Need M + measDurationSymbols-r16 ENUMERATED {sym1, sym14or12, sym28or24, sym42or36, sym70or60}, + rmtc-Frequency-r16 ARFCN-ValueNR, + ref-SCS-CP-r16 ENUMERATED {kHz15, kHz30, kHz60-NCP, kHz60-ECP}, + ... +} + +SSB-PositionQCL-CellsToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF SSB-PositionQCL-CellsToAddMod-r16 + +SSB-PositionQCL-CellsToAddMod-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 +} + +-- TAG-MEASOBJECTNR-STOP +-- TAG-MEASOBJECTNR-SL-START + +MeasObjectNR-SL-r16 ::= SEQUENCE { + tx-PoolMeasToRemoveList-r16 Tx-PoolMeasList-r16 OPTIONAL, -- Need N + tx-PoolMeasToAddModList-r16 Tx-PoolMeasList-r16 OPTIONAL -- Need N +} + +Tx-PoolMeasList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-PoolToMeasureNR-r16)) OF SL-ResourcePoolID-r16 + +-- TAG-MEASOBJECTNR-SL-STOP +-- TAG-MEASOBJECTTOADDMODLIST-START + +MeasObjectToAddModList ::= SEQUENCE (SIZE (1..maxNrofObjectId)) OF MeasObjectToAddMod + +MeasObjectToAddMod ::= SEQUENCE { + measObjectId MeasObjectId, + measObject CHOICE { + measObjectNR MeasObjectNR, + ..., + measObjectEUTRA MeasObjectEUTRA, + measObjectUTRA-FDD-r16 MeasObjectUTRA-FDD-r16, + measObjectNR-SL-r16 MeasObjectNR-SL-r16, + measObjectCLI-r16 MeasObjectCLI-r16 + } +} + +-- TAG-MEASOBJECTTOADDMODLIST-STOP +-- TAG-MEASOBJECTUTRA-FDD-START + +MeasObjectUTRA-FDD-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueUTRA-FDD-r16, + utra-FDD-Q-OffsetRange-r16 UTRA-FDD-Q-OffsetRange-r16 OPTIONAL, -- Need R + cellsToRemoveList-r16 UTRA-FDD-CellIndexList-r16 OPTIONAL, -- Need N + cellsToAddModList-r16 CellsToAddModListUTRA-FDD-r16 OPTIONAL, -- Need N + ... +} + +CellsToAddModListUTRA-FDD-r16 ::= SEQUENCE (SIZE (1..maxCellMeasUTRA-FDD-r16)) OF CellsToAddModUTRA-FDD-r16 + +CellsToAddModUTRA-FDD-r16 ::= SEQUENCE { + cellIndexUTRA-FDD-r16 UTRA-FDD-CellIndex-r16, + physCellId-r16 PhysCellIdUTRA-FDD-r16 +} + +UTRA-FDD-CellIndexList-r16 ::= SEQUENCE (SIZE (1..maxCellMeasUTRA-FDD-r16)) OF UTRA-FDD-CellIndex-r16 + +UTRA-FDD-CellIndex-r16 ::= INTEGER (1..maxCellMeasUTRA-FDD-r16) + +-- TAG-MEASOBJECTUTRA-FDD-STOP +-- TAG-MEASRESULTCELLLISTSFTD-NR-START + +MeasResultCellListSFTD-NR ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF MeasResultCellSFTD-NR + +MeasResultCellSFTD-NR ::= SEQUENCE { + physCellId PhysCellId, + sfn-OffsetResult INTEGER (0..1023), + frameBoundaryOffsetResult INTEGER (-30720..30719), + rsrp-Result RSRP-Range OPTIONAL +} + +-- TAG-MEASRESULTCELLLISTSFTD-NR-STOP +-- TAG-MEASRESULTCELLLISTSFTD-EUTRA-START + +MeasResultCellListSFTD-EUTRA ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF MeasResultSFTD-EUTRA + +MeasResultSFTD-EUTRA ::= SEQUENCE { + eutra-PhysCellId EUTRA-PhysCellId, + sfn-OffsetResult INTEGER (0..1023), + frameBoundaryOffsetResult INTEGER (-30720..30719), + rsrp-Result RSRP-Range OPTIONAL +} + +-- TAG-MEASRESULTCELLLISTSFTD-EUTRA-STOP +-- TAG-MEASRESULTS-START + +MeasResults ::= SEQUENCE { + measId MeasId, + measResultServingMOList MeasResultServMOList, + measResultNeighCells CHOICE { + measResultListNR MeasResultListNR, + ..., + measResultListEUTRA MeasResultListEUTRA, + measResultListUTRA-FDD-r16 MeasResultListUTRA-FDD-r16 + } OPTIONAL, + ..., + [[ + measResultServFreqListEUTRA-SCG MeasResultServFreqListEUTRA-SCG OPTIONAL, + measResultServFreqListNR-SCG MeasResultServFreqListNR-SCG OPTIONAL, + measResultSFTD-EUTRA MeasResultSFTD-EUTRA OPTIONAL, + measResultSFTD-NR MeasResultCellSFTD-NR OPTIONAL + ]], + [[ + measResultCellListSFTD-NR MeasResultCellListSFTD-NR OPTIONAL + ]], + [[ + measResultForRSSI-r16 MeasResultForRSSI-r16 OPTIONAL, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + ul-PDCP-DelayValueResultList-r16 UL-PDCP-DelayValueResultList-r16 OPTIONAL, + measResultsSL-r16 MeasResultsSL-r16 OPTIONAL, + measResultCLI-r16 MeasResultCLI-r16 OPTIONAL + ]] + + +} + +MeasResultServMOList ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF MeasResultServMO + +MeasResultServMO ::= SEQUENCE { + servCellId ServCellIndex, + measResultServingCell MeasResultNR, + measResultBestNeighCell MeasResultNR OPTIONAL, + ... +} + +MeasResultListNR ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultNR + +MeasResultNR ::= SEQUENCE { + physCellId PhysCellId OPTIONAL, + measResult SEQUENCE { + cellResults SEQUENCE{ + resultsSSB-Cell MeasQuantityResults OPTIONAL, + resultsCSI-RS-Cell MeasQuantityResults OPTIONAL + }, + rsIndexResults SEQUENCE{ + resultsSSB-Indexes ResultsPerSSB-IndexList OPTIONAL, + resultsCSI-RS-Indexes ResultsPerCSI-RS-IndexList OPTIONAL + } OPTIONAL + }, + ..., + [[ + cgi-Info CGI-InfoNR OPTIONAL + ]] +} + +MeasResultListEUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultEUTRA + +MeasResultEUTRA ::= SEQUENCE { + eutra-PhysCellId PhysCellId, + measResult MeasQuantityResultsEUTRA, + + cgi-Info CGI-InfoEUTRA OPTIONAL, + ... +} + +MultiBandInfoListEUTRA ::= SEQUENCE (SIZE (1..maxMultiBands)) OF FreqBandIndicatorEUTRA + +MeasQuantityResults ::= SEQUENCE { + rsrp RSRP-Range OPTIONAL, + rsrq RSRQ-Range OPTIONAL, + sinr SINR-Range OPTIONAL +} + +MeasQuantityResultsEUTRA ::= SEQUENCE { + rsrp RSRP-RangeEUTRA OPTIONAL, + rsrq RSRQ-RangeEUTRA OPTIONAL, + sinr SINR-RangeEUTRA OPTIONAL +} + +ResultsPerSSB-IndexList::= SEQUENCE (SIZE (1..maxNrofIndexesToReport2)) OF ResultsPerSSB-Index + +ResultsPerSSB-Index ::= SEQUENCE { + ssb-Index SSB-Index, + ssb-Results MeasQuantityResults OPTIONAL +} + +ResultsPerCSI-RS-IndexList::= SEQUENCE (SIZE (1..maxNrofIndexesToReport2)) OF ResultsPerCSI-RS-Index + +ResultsPerCSI-RS-Index ::= SEQUENCE { + csi-RS-Index CSI-RS-Index, + csi-RS-Results MeasQuantityResults OPTIONAL +} +MeasResultServFreqListEUTRA-SCG ::= SEQUENCE (SIZE (1..maxNrofServingCellsEUTRA)) OF MeasResult2EUTRA + +MeasResultServFreqListNR-SCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF MeasResult2NR + +MeasResultListUTRA-FDD-r16 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultUTRA-FDD-r16 + +MeasResultUTRA-FDD-r16 ::= SEQUENCE { + physCellId-r16 PhysCellIdUTRA-FDD-r16, + measResult-r16 SEQUENCE { + utra-FDD-RSCP-r16 INTEGER (-5..91) OPTIONAL, + utra-FDD-EcN0-r16 INTEGER (0..49) OPTIONAL + } +} + +MeasResultForRSSI-r16 ::= SEQUENCE { + rssi-Result-r16 ENUMERATED{ffs}, + channelOccupancy-r16 INTEGER (0..100) +} + +MeasResultCLI-r16 ::= SEQUENCE { + measResultListSRS-RSRP-r16 MeasResultListSRS-RSRP-r16 OPTIONAL, + measResultListCLI-RSSI-r16 MeasResultListCLI-RSSI-r16 OPTIONAL +} + +MeasResultListSRS-RSRP-r16 ::= SEQUENCE (SIZE (1.. maxCLI-Report-r16)) OF MeasResultSRS-RSRP-r16 + +MeasResultSRS-RSRP-r16 ::= SEQUENCE { + srs-ResourceId-r16 SRS-ResourceId, + srs-RSRP-Result-r16 SRS-RSRP-Range-r16 +} + +MeasResultListCLI-RSSI-r16 ::= SEQUENCE (SIZE (1.. maxCLI-Report-r16)) OF MeasResultCLI-RSSI-r16 + +MeasResultCLI-RSSI-r16 ::= SEQUENCE { + rssi-ResourceId-r16 RSSI-ResourceId-r16, + cli-RSSI-Result-r16 CLI-RSSI-Range-r16 +} + +UL-PDCP-DelayValueResultList-r16 ::= SEQUENCE (SIZE (1..maxDRB)) OF UL-PDCP-DelayValueResult-r16 + +UL-PDCP-DelayValueResult-r16 ::= SEQUENCE { + drb-Id-r16 DRB-Identity, + averageDelay-r16 INTEGER (0..10000), + ... +} + +-- TAG-MEASRESULTS-STOP +-- TAG-MEASRESULT2EUTRA-START + +MeasResult2EUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + measResultServingCell MeasResultEUTRA OPTIONAL, + measResultBestNeighCell MeasResultEUTRA OPTIONAL, + ... +} + +-- TAG-MEASRESULT2EUTRA-STOP +-- TAG-MEASRESULT2NR-START + +MeasResult2NR ::= SEQUENCE { + ssbFrequency ARFCN-ValueNR OPTIONAL, + refFreqCSI-RS ARFCN-ValueNR OPTIONAL, + measResultServingCell MeasResultNR OPTIONAL, + measResultNeighCellListNR MeasResultListNR OPTIONAL, + ... +} + +-- TAG-MEASRESULT2NR-STOP +-- TAG-MEASRESULTIDLEEUTRA-START + +MeasResultIdleEUTRA-r16 ::= SEQUENCE { + measResultsPerCarrierListIdleEUTRA-r16 SEQUENCE (SIZE (1.. maxFreqIdle-r16)) OF MeasResultsPerCarrierIdleEUTRA-r16, + ... +} + +MeasResultsPerCarrierIdleEUTRA-r16 ::= SEQUENCE { + carrierFreqEUTRA-r16 ARFCN-ValueEUTRA, + measResultsPerCellListIdleEUTRA-r16 SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF MeasResultsPerCellIdleEUTRA-r16, + ... +} + +MeasResultsPerCellIdleEUTRA-r16 ::= SEQUENCE { + eutra-PhysCellId-r16 EUTRA-PhysCellId, + measIdleResultEUTRA-r16 SEQUENCE { + rsrp-ResultEUTRA-r16 RSRP-RangeEUTRA OPTIONAL, + rsrq-ResultEUTRA-r16 RSRQ-RangeEUTRA-r16 OPTIONAL + }, + ... +} + +-- TAG-MEASRESULTIDLEEUTRA-STOP +-- TAG-MEASRESULTIDLENR-START + +MeasResultIdleNR-r16 ::= SEQUENCE { + measResultServingCell-r16 SEQUENCE { + rsrp-Result-r16 RSRP-Range OPTIONAL, + rsrq-Result-r16 RSRQ-Range OPTIONAL, + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList-r16 OPTIONAL + }, + measResultsPerCarrierListIdleNR-r16 SEQUENCE (SIZE (1.. maxFreqIdle-r16)) OF MeasResultsPerCarrierIdleNR-r16 OPTIONAL, + ... +} + +MeasResultsPerCarrierIdleNR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + measResultsPerCellListIdleNR-r16 SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF MeasResultsPerCellIdleNR-r16, + ... +} + +MeasResultsPerCellIdleNR-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + measIdleResultNR-r16 SEQUENCE { + rsrp-Result-r16 RSRP-Range OPTIONAL, + rsrq-Result-r16 RSRQ-Range OPTIONAL, + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList-r16 OPTIONAL + }, + ... +} + +ResultsPerSSB-IndexList-r16 ::= SEQUENCE (SIZE (1.. maxNrofIndexesToReport)) OF ResultsPerSSB-IndexIdle-r16 + +ResultsPerSSB-IndexIdle-r16 ::= SEQUENCE { + ssb-Index-r16 SSB-Index, + ssb-Results-r16 SEQUENCE { + ssb-RSRP-Result-r16 RSRP-Range OPTIONAL, + ssb-RSRQ-Result-r16 RSRQ-Range OPTIONAL + } OPTIONAL +} + +-- TAG-MEASRESULTIDLENR-STOP +-- TAG-MEASRESULTSCG-FAILURE-START + +MeasResultSCG-Failure ::= SEQUENCE { + measResultPerMOList MeasResultList2NR, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL + ]] +} + +MeasResultList2NR ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2NR + +-- TAG-MEASRESULTSCG-FAILURE-STOP +-- TAG-MEASRESULTSSL-START + +MeasResultsSL-r16 ::= SEQUENCE { + measResultsListSL-r16 CHOICE { + measResultNR-SL-r16 MeasResultNR-SL-r16, + ... + }, + ... +} + +MeasResultNR-SL-r16 ::= SEQUENCE { + measResultListCBR-NR-r16 SEQUENCE (SIZE (1.. maxNrofSL-PoolToMeasureNR-r16)) OF MeasResultCBR-NR-r16, + ... +} + +MeasResultCBR-NR-r16 ::= SEQUENCE { + sl-poolReportIdentity-r16 SL-ResourcePoolID-r16, + sl-CBR-ResultsNR-r16 SL-CBR-r16, + ... +} + +-- TAG-MEASRESULTSSL-STOP +-- TAG-MEASTRIGGERQUANTITYEUTRA-START + +MeasTriggerQuantityEUTRA::= CHOICE { + rsrp RSRP-RangeEUTRA, + rsrq RSRQ-RangeEUTRA, + sinr SINR-RangeEUTRA +} + +RSRP-RangeEUTRA ::= INTEGER (0..97) + +RSRQ-RangeEUTRA ::= INTEGER (0..34) + +SINR-RangeEUTRA ::= INTEGER (0..127) + +-- TAG-MEASTRIGGERQUANTITYEUTRA-STOP +-- TAG-MOBILITYSTATEPARAMETERS-START + +MobilityStateParameters ::= SEQUENCE{ + t-Evaluation ENUMERATED { + s30, s60, s120, s180, s240, spare3, spare2, spare1}, + t-HystNormal ENUMERATED { + s30, s60, s120, s180, s240, spare3, spare2, spare1}, + n-CellChangeMedium INTEGER (1..16), + n-CellChangeHigh INTEGER (1..16) +} + +-- TAG-MOBILITYSTATEPARAMETERS-STOP +-- TAG-MSGACONFIGCOMMON-START + +MsgA-ConfigCommon-r16 ::= SEQUENCE { + rach-ConfigCommonTwoStepRA-r16 RACH-ConfigCommonTwoStepRA-r16, + msgA-PUSCH-Config-r16 MsgA-PUSCH-Config-r16 OPTIONAL --Cond InitialBWPConfig +} +-- TAG-MSGACONFIGCOMMON-STOP +-- TAG-MSGA-PUSCH-CONFIG-START + +MsgA-PUSCH-Config-r16 ::= SEQUENCE { + msgA-PUSCH-ResourceGroupA-r16 MsgA-PUSCH-Resource-r16 OPTIONAL, -- Cond InitialBWPConfig + msgA-PUSCH-ResourceGroupB-r16 MsgA-PUSCH-Resource-r16 OPTIONAL, -- Cond GroupBConfigured + msgA-TransformPrecoder-r16 ENUMERATED {enabled, disabled} OPTIONAL, -- Need R + msgA-DataScramblingIndex-r16 INTEGER (0..1023) OPTIONAL, -- Need S + msgA-DeltaPreamble-r16 INTEGER (-1..6) OPTIONAL -- Need R +} + +MsgA-PUSCH-Resource-r16 ::= SEQUENCE { + msgA-MCS-r16 INTEGER (0..15), + nrofSlotsMsgA-PUSCH-r16 INTEGER (1..4), + nrofMsgA-PO-PerSlot-r16 ENUMERATED {one, two, three, six}, + msgA-PUSCH-TimeDomainOffset-r16 INTEGER (1..32), + msgA-PUSCH-TimeDomainAllocation-r16 INTEGER (1..maxNrofUL-Allocations) OPTIONAL, -- Need S + startSymbolAndLengthMsgA-PO-r16 INTEGER (0..127) OPTIONAL, -- Need S + mappingTypeMsgA-PUSCH-r16 ENUMERATED {typeA, typeB} OPTIONAL, -- Need S + guardPeriodMsgA-PUSCH-r16 INTEGER (0..3) OPTIONAL, -- Need R + guardBandMsgA-PUSCH-r16 INTEGER (0..1), + frequencyStartMsgA-PUSCH-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1), + nrofPRBs-PerMsgA-PO-r16 INTEGER (1..32), + nrofMsgA-PO-FDM-r16 ENUMERATED {one, two, four, eight}, + msgA-IntraSlotFrequencyHopping-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + msgA-HoppingBits-r16 BIT STRING (SIZE(2)) OPTIONAL, -- Need R + msgA-DMRS-Config-r16 MsgA-DMRS-Config-r16, + nrofDMRS-Sequences-r16 INTEGER (1..2), + msgA-Alpha-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, + alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need S + interlaceIndexFirstPO-MsgA-PUSCH-r16 INTEGER (1..10) OPTIONAL, -- Need R + nrofInterlacesPerMsgA-PO-r16 INTEGER (1..10) OPTIONAL, -- Need R + ... +} + +MsgA-DMRS-Config-r16 ::= SEQUENCE { + msgA-DMRS-AdditionalPosition-r16 ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + msgA-MaxLength-r16 ENUMERATED {len2} OPTIONAL, -- Need S + msgA-PUSCH-DMRS-CDM-Group-r16 INTEGER (0..1) OPTIONAL, -- Need S + msgA-PUSCH-NrofPorts-r16 INTEGER (0..1) OPTIONAL, -- Need S + msgA-ScramblingID0-r16 INTEGER (0..65536) OPTIONAL, -- Need S + msgA-ScramblingID1-r16 INTEGER (0..65536) OPTIONAL -- Need S +} + +-- TAG-MSGA-PUSCH-CONFIG-STOP +-- TAG-MULTIFREQUENCYBANDLISTNR-START + +MultiFrequencyBandListNR ::= SEQUENCE (SIZE (1..maxNrofMultiBands)) OF FreqBandIndicatorNR + +-- TAG-MULTIFREQUENCYBANDLISTNR-STOP +-- TAG-MULTIFREQUENCYBANDLISTNR-SIB-START + +MultiFrequencyBandListNR-SIB ::= SEQUENCE (SIZE (1.. maxNrofMultiBands)) OF NR-MultiBandInfo + +NR-MultiBandInfo ::= SEQUENCE { + freqBandIndicatorNR FreqBandIndicatorNR OPTIONAL, -- Cond OptULNotSIB2 + nr-NS-PmaxList NR-NS-PmaxList OPTIONAL -- Need S +} + +-- TAG-MULTIFREQUENCYBANDLISTNR-SIB-STOP +-- TAG-NeedForGapsConfigNR-START + +NeedForGapsConfigNR-r16 ::= SEQUENCE { + requestedTargetBandFilterNR-r16 SEQUENCE (SIZE (1..maxBands)) OF FreqBandIndicatorNR OPTIONAL -- Need R +} + +-- TAG-NeedForGapsConfigNR-STOP +-- TAG-NeedForGapsInfoNR-START + +NeedForGapsInfoNR-r16 ::= SEQUENCE { + intraFreq-needForGap-r16 NeedForGapsIntraFreqlist-r16, + interFreq-needForGap-r16 NeedForGapsBandlistNR-r16 +} + +NeedForGapsIntraFreqlist-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCells)) OF NeedForGapsIntraFreq-r16 + +NeedForGapsBandlistNR-r16 ::= SEQUENCE (SIZE (1..maxBands)) OF NeedForGapsNR-r16 + +NeedForGapsIntraFreq-r16 ::= SEQUENCE { + servCellId-r16 ServCellIndex, + gapIndicationIntra-r16 ENUMERATED {gap, no-gap} +} + +NeedForGapsNR-r16 ::= SEQUENCE { + bandNR-r16 FreqBandIndicatorNR, + gapIndication-r16 ENUMERATED {gap, no-gap} +} + +-- TAG-NeedForGapsInfoNR-STOP +-- TAG-NEXTHOPCHAININGCOUNT-START + +NextHopChainingCount ::= INTEGER (0..7) + +-- TAG-NEXTHOPCHAININGCOUNT-STOP +-- TAG-NG-5G-S-TMSI-START + +NG-5G-S-TMSI ::= BIT STRING (SIZE (48)) + +-- TAG-NG-5G-S-TMSI-STOP +-- TAG-NPN-IDENTITY-START + +NPN-Identity-r16 ::= CHOICE { + pni-npn-r16 SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + cag-IdentityList-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF CAG-IdentityInfo-r16 + }, + snpn-r16 SEQUENCE { + plmn-Identity PLMN-Identity, + nid-List-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF NID-r16 + } +} + +CAG-IdentityInfo-r16 ::= SEQUENCE { + cag-Identity-r16 BIT STRING (SIZE (32)), + manualCAGselectionAllowed-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +NID-r16 ::= BIT STRING (SIZE (44)) + +-- TAG-NPN-IDENTITY-STOP +-- TAG-NPN-IDENTITYINFOLIST-START + +NPN-IdentityInfoList-r16 ::= SEQUENCE (SIZE (1..maxNPN-r16)) OF NPN-IdentityInfo-r16 + + +NPN-IdentityInfo-r16 ::= SEQUENCE { + npn-IdentityList-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF NPN-Identity-r16, + trackingAreaCode-r16 TrackingAreaCode, + ranac-r16 RAN-AreaCode OPTIONAL, -- Need R + cellIdentity-r16 CellIdentity, + cellReservedForOperatorUse-r16 ENUMERATED {reserved, notReserved}, + iab-Support-r16 ENUMERATED {true} OPTIONAL, -- Need R + ... +} + +-- TAG-NPN-IDENTITYINFOLIST-STOP +-- TAG-NR-NS-PMAXLIST-START + +NR-NS-PmaxList ::= SEQUENCE (SIZE (1..maxNR-NS-Pmax)) OF NR-NS-PmaxValue + +NR-NS-PmaxValue ::= SEQUENCE { + additionalPmax P-Max OPTIONAL, -- Need N + additionalSpectrumEmission AdditionalSpectrumEmission +} + +-- TAG-NR-NS-PMAXLIST-STOP +-- TAG-NZP-CSI-RS-RESOURCE-START + +NZP-CSI-RS-Resource ::= SEQUENCE { + nzp-CSI-RS-ResourceId NZP-CSI-RS-ResourceId, + resourceMapping CSI-RS-ResourceMapping, + powerControlOffset INTEGER (-8..15), + powerControlOffsetSS ENUMERATED{db-3, db0, db3, db6} OPTIONAL, -- Need R + scramblingID ScramblingId, + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, -- Cond PeriodicOrSemiPersistent + qcl-InfoPeriodicCSI-RS TCI-StateId OPTIONAL, -- Cond Periodic + ... +} + +-- TAG-NZP-CSI-RS-RESOURCE-STOP +-- TAG-NZP-CSI-RS-RESOURCEID-START + +NZP-CSI-RS-ResourceId ::= INTEGER (0..maxNrofNZP-CSI-RS-Resources-1) + +-- TAG-NZP-CSI-RS-RESOURCEID-STOP +-- TAG-NZP-CSI-RS-RESOURCESET-START +NZP-CSI-RS-ResourceSet ::= SEQUENCE { + nzp-CSI-ResourceSetId NZP-CSI-RS-ResourceSetId, + nzp-CSI-RS-Resources SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourcesPerSet)) OF NZP-CSI-RS-ResourceId, + repetition ENUMERATED { on, off } OPTIONAL, -- Need S + aperiodicTriggeringOffset INTEGER(0..6) OPTIONAL, -- Need S + trs-Info ENUMERATED {true} OPTIONAL, -- Need R + ..., + [[ + aperiodicTriggeringOffset-r16 INTEGER(0..31) OPTIONAL -- Need S + ]] +} + +-- TAG-NZP-CSI-RS-RESOURCESET-STOP +-- TAG-NZP-CSI-RS-RESOURCESETID-START + +NZP-CSI-RS-ResourceSetId ::= INTEGER (0..maxNrofNZP-CSI-RS-ResourceSets-1) + +-- TAG-NZP-CSI-RS-RESOURCESETID-STOP +-- TAG-P-MAX-START + +P-Max ::= INTEGER (-30..33) + +-- TAG-P-MAX-STOP +-- TAG-PCI-LIST-START + +PCI-List ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF PhysCellId + +-- TAG-PCI-LIST-STOP +-- TAG-PCI-RANGE-START + +PCI-Range ::= SEQUENCE { + start PhysCellId, + range ENUMERATED {n4, n8, n12, n16, n24, n32, n48, n64, n84, + n96, n128, n168, n252, n504, n1008,spare1} OPTIONAL -- Need S +} + +-- TAG-PCI-RANGE-STOP +-- TAG-PCI-RANGEELEMENT-START + +PCI-RangeElement ::= SEQUENCE { + pci-RangeIndex PCI-RangeIndex, + pci-Range PCI-Range +} + +-- TAG-PCI-RANGEELEMENT-STOP +-- TAG-PCI-RANGEINDEX-START + +PCI-RangeIndex ::= INTEGER (1..maxNrofPCI-Ranges) + +-- TAG-PCI-RANGEINDEX-STOP +-- TAG-PCI-RANGEINDEXLIST-START + +PCI-RangeIndexList ::= SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeIndex + +-- TAG-PCI-RANGEINDEXLIST-STOP +-- TAG-PDCCH-CONFIG-START + +PDCCH-Config ::= SEQUENCE { + controlResourceSetToAddModList SEQUENCE(SIZE (1..3)) OF ControlResourceSet OPTIONAL, -- Need N + controlResourceSetToReleaseList SEQUENCE(SIZE (1..3)) OF ControlResourceSetId OPTIONAL, -- Need N + searchSpacesToAddModList SEQUENCE(SIZE (1..10)) OF SearchSpace OPTIONAL, -- Need N + searchSpacesToReleaseList SEQUENCE(SIZE (1..10)) OF SearchSpaceId OPTIONAL, -- Need N + downlinkPreemption SetupRelease { DownlinkPreemption } OPTIONAL, -- Need M + tpc-PUSCH SetupRelease { PUSCH-TPC-CommandConfig } OPTIONAL, -- Need M + tpc-PUCCH SetupRelease { PUCCH-TPC-CommandConfig } OPTIONAL, -- Need M + tpc-SRS SetupRelease { SRS-TPC-CommandConfig} OPTIONAL, -- Need M + ..., + [[ + controlResourceSetToAddModList2-r16 SEQUENCE (SIZE (1..2)) OF ControlResourceSet OPTIONAL, -- Need N + controlResourceSetToReleaseList-r16 SEQUENCE (SIZE (1..5)) OF ControlResourceSetId-r16 OPTIONAL, -- Need N + searchSpacesToAddModListExt-r16 SEQUENCE(SIZE (1..10)) OF SearchSpaceExt-r16 OPTIONAL, -- Need N + searchSpaceSwitchingTimer-r16 INTEGER (1..80) OPTIONAL, -- Need R + cellGroupsForSwitchingList-r16 SEQUENCE(SIZE (1..4)) OF CellGroupForSwitching-r16 OPTIONAL, -- Need R + uplinkCancellation-r16 SetupRelease { UplinkCancellation-r16 } OPTIONAL, -- Need M + monitoringCapabilityConfig-r16 ENUMERATED { r15monitoringcapability,r16monitoringcapability } OPTIONAL, -- Need M + searchSpaceSwitchingDelay-r16 INTEGER (10..52) OPTIONAL -- Need R + ]] +} + +CellGroupForSwitching-r16 ::= SEQUENCE(SIZE (1..16)) OF ServCellIndex + +-- TAG-PDCCH-CONFIG-STOP +-- TAG-PDCCH-CONFIGCOMMON-START + +PDCCH-ConfigCommon ::= SEQUENCE { + controlResourceSetZero ControlResourceSetZero OPTIONAL, -- Cond InitialBWP-Only + commonControlResourceSet ControlResourceSet OPTIONAL, -- Need R + searchSpaceZero SearchSpaceZero OPTIONAL, -- Cond InitialBWP-Only + commonSearchSpaceList SEQUENCE (SIZE(1..4)) OF SearchSpace OPTIONAL, -- Need R + searchSpaceSIB1 SearchSpaceId OPTIONAL, -- Need S + searchSpaceOtherSystemInformation SearchSpaceId OPTIONAL, -- Need S + pagingSearchSpace SearchSpaceId OPTIONAL, -- Need S + ra-SearchSpace SearchSpaceId OPTIONAL, -- Need S + ..., + [[ + firstPDCCH-MonitoringOccasionOfPO CHOICE { + sCS15KHZoneT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..139), + sCS30KHZoneT-SCS15KHZhalfT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..279), + sCS60KHZoneT-SCS30KHZhalfT-SCS15KHZquarterT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..559), + sCS120KHZoneT-SCS60KHZhalfT-SCS30KHZquarterT-SCS15KHZoneEighthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..1119), + sCS120KHZhalfT-SCS60KHZquarterT-SCS30KHZoneEighthT-SCS15KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..2239), + sCS120KHZquarterT-SCS60KHZoneEighthT-SCS30KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..4479), + sCS120KHZoneEighthT-SCS60KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..8959), + sCS120KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..17919) + } OPTIONAL, -- Cond OtherBWP + commonSearchSpaceListExt-r16 SEQUENCE (SIZE(1..4)) OF SearchSpaceExt-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-PDCCH-CONFIGCOMMON-STOP +-- TAG-PDCCH-CONFIGSIB1-START + +PDCCH-ConfigSIB1 ::= SEQUENCE { + controlResourceSetZero ControlResourceSetZero, + searchSpaceZero SearchSpaceZero +} + +-- TAG-PDCCH-CONFIGSIB1-STOP +-- TAG-PDCCH-SERVINGCELLCONFIG-START + +PDCCH-ServingCellConfig ::= SEQUENCE { + slotFormatIndicator SetupRelease { SlotFormatIndicator } OPTIONAL, -- Need M + ..., + [[ + availabilityIndicator-r16 SetupRelease {AvailabilityIndicator-r16} OPTIONAL, -- Need M + searchSpaceSwitchingTimer-r16 INTEGER (1..80) OPTIONAL -- Need R + ]] +} + +-- TAG-PDCCH-SERVINGCELLCONFIG-STOP +-- TAG-PDCP-CONFIG-START + +PDCP-Config ::= SEQUENCE { + drb SEQUENCE { + discardTimer ENUMERATED {ms10, ms20, ms30, ms40, ms50, ms60, ms75, ms100, ms150, ms200, + ms250, ms300, ms500, ms750, ms1500, infinity} OPTIONAL, -- Cond Setup + pdcp-SN-SizeUL ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + pdcp-SN-SizeDL ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + headerCompression CHOICE { + notUsed NULL, + rohc SEQUENCE { + maxCID INTEGER (1..16383) DEFAULT 15, + profiles SEQUENCE { + profile0x0001 BOOLEAN, + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0101 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + drb-ContinueROHC ENUMERATED { true } OPTIONAL -- Need N + }, + uplinkOnlyROHC SEQUENCE { + maxCID INTEGER (1..16383) DEFAULT 15, + profiles SEQUENCE { + profile0x0006 BOOLEAN + }, + drb-ContinueROHC ENUMERATED { true } OPTIONAL -- Need N + }, + ... + }, + integrityProtection ENUMERATED { enabled } OPTIONAL, -- Cond ConnectedTo5GC1 + statusReportRequired ENUMERATED { true } OPTIONAL, -- Cond Rlc-AM-UM + outOfOrderDelivery ENUMERATED { true } OPTIONAL -- Need R + } OPTIONAL, -- Cond DRB + moreThanOneRLC SEQUENCE { + primaryPath SEQUENCE { + cellGroup CellGroupId OPTIONAL, -- Need R + logicalChannel LogicalChannelIdentity OPTIONAL -- Need R + }, + ul-DataSplitThreshold UL-DataSplitThreshold OPTIONAL, -- Cond SplitBearer + pdcp-Duplication BOOLEAN OPTIONAL -- Need R + } OPTIONAL, -- Cond MoreThanOneRLC + + t-Reordering ENUMERATED { + ms0, ms1, ms2, ms4, ms5, ms8, ms10, ms15, ms20, ms30, ms40, + ms50, ms60, ms80, ms100, ms120, ms140, ms160, ms180, ms200, ms220, + ms240, ms260, ms280, ms300, ms500, ms750, ms1000, ms1250, + ms1500, ms1750, ms2000, ms2250, ms2500, ms2750, + ms3000, spare28, spare27, spare26, spare25, spare24, + spare23, spare22, spare21, spare20, + spare19, spare18, spare17, spare16, spare15, spare14, + spare13, spare12, spare11, spare10, spare09, + spare08, spare07, spare06, spare05, spare04, spare03, + spare02, spare01 } OPTIONAL, -- Need S + ..., + [[ + cipheringDisabled ENUMERATED {true} OPTIONAL -- Cond ConnectedTo5GC + ]], + [[ + discardTimerExt-r16 SetupRelease { DiscardTimerExt-r16 } OPTIONAL, -- Cond DRB2 + moreThanTwoRLC-DRB-r16 SEQUENCE { + splitSecondaryPath LogicalChannelIdentity OPTIONAL, -- Cond SplitBearer2 + duplicationState SEQUENCE (SIZE (3)) OF BOOLEAN OPTIONAL -- Need S + } OPTIONAL, -- Cond MoreThanTwoRLC-DRB + ethernetHeaderCompression-r16 SetupRelease { EthernetHeaderCompression-r16 } OPTIONAL -- Need M + ]] +} + +EthernetHeaderCompression-r16 ::= SEQUENCE { + ehc-Common SEQUENCE { + ehc-CID-Length ENUMERATED { bits7, bits15 }, + ... + }, + ehc-Downlink SEQUENCE { + drb-ContinueEHC-DL ENUMERATED { true } OPTIONAL, -- Need R + ... + } OPTIONAL, -- Need M + ehc-Uplink SEQUENCE { + maxCID-EHC-UL INTEGER (1..32767), + drb-ContinueEHC-UL ENUMERATED { true } OPTIONAL, -- Need R + ... + } OPTIONAL -- Need M +} + +UL-DataSplitThreshold ::= ENUMERATED { + b0, b100, b200, b400, b800, b1600, b3200, b6400, b12800, b25600, b51200, b102400, b204800, + b409600, b819200, b1228800, b1638400, b2457600, b3276800, b4096000, b4915200, b5734400, + b6553600, infinity, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1} + +DiscardTimerExt-r16 ::= ENUMERATED {ms0dot5, ms1, ms2, ms4, ms6, ms8, spare2, spare1} + +-- TAG-PDCP-CONFIG-STOP +-- TAG-PDSCH-CONFIG-START + +PDSCH-Config ::= SEQUENCE { + dataScramblingIdentityPDSCH INTEGER (0..1023) OPTIONAL, -- Need S + dmrs-DownlinkForPDSCH-MappingTypeA SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-DownlinkForPDSCH-MappingTypeB SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + + tci-StatesToAddModList SEQUENCE (SIZE(1..maxNrofTCI-States)) OF TCI-State OPTIONAL, -- Need N + tci-StatesToReleaseList SEQUENCE (SIZE(1..maxNrofTCI-States)) OF TCI-StateId OPTIONAL, -- Need N + vrb-ToPRB-Interleaver ENUMERATED {n2, n4} OPTIONAL, -- Need S + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch}, + pdsch-TimeDomainAllocationList SetupRelease { PDSCH-TimeDomainResourceAllocationList } OPTIONAL, -- Need M + pdsch-AggregationFactor ENUMERATED { n2, n4, n8 } OPTIONAL, -- Need S + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + rateMatchPatternGroup1 RateMatchPatternGroup OPTIONAL, -- Need R + rateMatchPatternGroup2 RateMatchPatternGroup OPTIONAL, -- Need R + + rbg-Size ENUMERATED {config1, config2}, + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + maxNrofCodeWordsScheduledByDCI ENUMERATED {n1, n2} OPTIONAL, -- Need R + + prb-BundlingType CHOICE { + staticBundling SEQUENCE { + bundleSize ENUMERATED { n4, wideband } OPTIONAL -- Need S + }, + dynamicBundling SEQUENCE { + bundleSizeSet1 ENUMERATED { n4, wideband, n2-wideband, n4-wideband } OPTIONAL, -- Need S + bundleSizeSet2 ENUMERATED { n4, wideband } OPTIONAL -- Need S + } + }, + zp-CSI-RS-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-Resources)) OF ZP-CSI-RS-Resource + OPTIONAL, -- Need N + zp-CSI-RS-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-Resources)) OF ZP-CSI-RS-ResourceId + OPTIONAL, -- Need N + aperiodic-ZP-CSI-RS-ResourceSetsToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + aperiodic-ZP-CSI-RS-ResourceSetsToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + sp-ZP-CSI-RS-ResourceSetsToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + sp-ZP-CSI-RS-ResourceSetsToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + p-ZP-CSI-RS-ResourceSet SetupRelease { ZP-CSI-RS-ResourceSet } + OPTIONAL, -- Need M + ..., + [[ + maxMIMO-Layers-r16 SetupRelease { MaxMIMO-LayersDL-r16 } OPTIONAL, -- Need M + minimumSchedulingOffsetK0-r16 SetupRelease { MinSchedulingOffsetK0-Values-r16 } OPTIONAL, -- Need M + + -- Start of the parameters for DCI format 1_2 introduced in V16.1.0 + antennaPortsFieldPresenceForDCI-Format1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + aperiodicZP-CSI-RS-ResourceSetsToAddModListForDCI-Format1-2-r16 SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + aperiodicZP-CSI-RS-ResourceSetsToReleaseListForDCI-Format1-2-r16 SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + dmrs-DownlinkForPDSCH-MappingTypeA-ForDCI-Format1-2-r16 SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-DownlinkForPDSCH-MappingTypeB-ForDCI-Format1-2-r16 SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-SequenceInitializationForDCI-Format1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + harq-ProcessNumberSizeForDCI-Format1-2-r16 INTEGER (0..4) OPTIONAL, -- Need R + mcs-TableForDCI-Format1-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + numberOfBitsForRV-ForDCI-Format1-2-r16 INTEGER (0..2) OPTIONAL, -- Need R + pdsch-TimeDomainAllocationListForDCI-Format1-2-r16 SetupRelease { PDSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + prb-BundlingTypeForDCI-Format1-2-r16 CHOICE { + staticBundling-r16 SEQUENCE { + bundleSize-r16 ENUMERATED { n4, wideband } OPTIONAL -- Need S + }, + dynamicBundling-r16 SEQUENCE { + bundleSizeSet1-r16 ENUMERATED { n4, wideband, n2-wideband, n4-wideband } OPTIONAL, -- Need S + bundleSizeSet2-r16 ENUMERATED { n4, wideband } OPTIONAL -- Need S + } + } OPTIONAL, -- Need R + priorityIndicatorForDCI-Format1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + rateMatchPatternGroup1ForDCI-Format1-2-r16 RateMatchPatternGroup OPTIONAL, -- Need R + rateMatchPatternGroup2ForDCI-Format1-2-r16 RateMatchPatternGroup OPTIONAL, -- Need R + resourceAllocationType1GranularityForDCI-Format1-2-r16 ENUMERATED {n2,n4,n8,n16} OPTIONAL, -- Need S + vrb-ToPRB-InterleaverForDCI-Format1-2-r16 ENUMERATED {n2, n4} OPTIONAL, -- Need S + referenceOfSLIVForDCI-Format1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + resourceAllocationForDCI-Format1-2-r16 ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch} + OPTIONAL, -- Need M + -- End of the parameters for DCI format 1_2 introduced in V16.1.0 + + priorityIndicatorForDCI-Format1-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + dataScramblingIdentityPDSCH2-r16 INTEGER (0..1023) OPTIONAL, -- Need R + pdsch-TimeDomainAllocationList-r16 SetupRelease { PDSCH-TimeDomainResourceAllocationList-r16 } OPTIONAL, -- Need M + repetitionSchemeConfig-r16 SetupRelease { RepetitionSchemeConfig-r16} OPTIONAL -- Need M + ]] +} + +RateMatchPatternGroup ::= SEQUENCE (SIZE (1..maxNrofRateMatchPatternsPerGroup)) OF CHOICE { + cellLevel RateMatchPatternId, + bwpLevel RateMatchPatternId +} + +MinSchedulingOffsetK0-Values-r16 ::= SEQUENCE (SIZE (1..maxNrOfMinSchedulingOffsetValues-r16)) OF INTEGER (0..maxK0-SchedulingOffset-r16) + +MaxMIMO-LayersDL-r16 ::= INTEGER (1..8) + +-- TAG-PDSCH-CONFIG-STOP +-- TAG-PDSCH-CONFIGCOMMON-START + +PDSCH-ConfigCommon ::= SEQUENCE { + pdsch-TimeDomainAllocationList PDSCH-TimeDomainResourceAllocationList OPTIONAL, -- Need R + ... +} + +-- TAG-PDSCH-CONFIGCOMMON-STOP +-- TAG-PDSCH-SERVINGCELLCONFIG-START + +PDSCH-ServingCellConfig ::= SEQUENCE { + codeBlockGroupTransmission SetupRelease { PDSCH-CodeBlockGroupTransmission } OPTIONAL, -- Need M + xOverhead ENUMERATED { xOh6, xOh12, xOh18 } OPTIONAL, -- Need S + nrofHARQ-ProcessesForPDSCH ENUMERATED {n2, n4, n6, n10, n12, n16} OPTIONAL, -- Need S + pucch-Cell ServCellIndex OPTIONAL, -- Cond SCellAddOnly + ..., + [[ + maxMIMO-Layers INTEGER (1..8) OPTIONAL, -- Need M + processingType2Enabled BOOLEAN OPTIONAL -- Need M + ]], + [[ + pdsch-CodeBlockGroupTransmissionList-r16 SetupRelease { PDSCH-CodeBlockGroupTransmissionList-r16 } OPTIONAL -- Need M + ]] +} + +PDSCH-CodeBlockGroupTransmission ::= SEQUENCE { + maxCodeBlockGroupsPerTransportBlock ENUMERATED {n2, n4, n6, n8}, + codeBlockGroupFlushIndicator BOOLEAN, + ... +} + +PDSCH-CodeBlockGroupTransmissionList-r16 ::= SEQUENCE (SIZE (1..2)) OF PDSCH-CodeBlockGroupTransmission + +-- TAG-PDSCH-SERVINGCELLCONFIG-STOP +-- TAG-PDSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-START + + +PDSCH-TimeDomainResourceAllocationList ::= SEQUENCE (SIZE(1..maxNrofDL-Allocations)) OF PDSCH-TimeDomainResourceAllocation + +PDSCH-TimeDomainResourceAllocation ::= SEQUENCE { + k0 INTEGER(0..32) OPTIONAL, -- Need S + mappingType ENUMERATED {typeA, typeB}, + startSymbolAndLength INTEGER (0..127) +} + +PDSCH-TimeDomainResourceAllocationList-r16 ::= SEQUENCE (SIZE(1..maxNrofDL-Allocations)) OF PDSCH-TimeDomainResourceAllocation-r16 + +PDSCH-TimeDomainResourceAllocation-r16 ::= SEQUENCE { + k0-r16 INTEGER(0..32) OPTIONAL, -- Need S + mappingType-r16 ENUMERATED {typeA, typeB}, + startSymbolAndLength-r16 INTEGER (0..127), + repetitionNumber-r16 ENUMERATED {n2, n3, n4, n5, n6, n7, n8, n16} OPTIONAL, -- Cond Formats1-0and1-1 + ... +} + +-- TAG-PDSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-STOP +-- TAG-PHR-CONFIG-START + +PHR-Config ::= SEQUENCE { + phr-PeriodicTimer ENUMERATED {sf10, sf20, sf50, sf100, sf200,sf500, sf1000, infinity}, + phr-ProhibitTimer ENUMERATED {sf0, sf10, sf20, sf50, sf100,sf200, sf500, sf1000}, + phr-Tx-PowerFactorChange ENUMERATED {dB1, dB3, dB6, infinity}, + multiplePHR BOOLEAN, + dummy BOOLEAN, + phr-Type2OtherCell BOOLEAN, + phr-ModeOtherCG ENUMERATED {real, virtual}, + ... +} + +-- TAG-PHR-CONFIG-STOP +-- TAG-PHYSCELLID-START + +PhysCellId ::= INTEGER (0..1007) + +-- TAG-PHYSCELLID-STOP +-- TAG-PHYSICALCELLGROUPCONFIG-START + +PhysicalCellGroupConfig ::= SEQUENCE { + harq-ACK-SpatialBundlingPUCCH ENUMERATED {true} OPTIONAL, -- Need S + harq-ACK-SpatialBundlingPUSCH ENUMERATED {true} OPTIONAL, -- Need S + p-NR-FR1 P-Max OPTIONAL, -- Need R + pdsch-HARQ-ACK-Codebook ENUMERATED {semiStatic, dynamic}, + tpc-SRS-RNTI RNTI-Value OPTIONAL, -- Need R + tpc-PUCCH-RNTI RNTI-Value OPTIONAL, -- Need R + tpc-PUSCH-RNTI RNTI-Value OPTIONAL, -- Need R + sp-CSI-RNTI RNTI-Value OPTIONAL, -- Need R + cs-RNTI SetupRelease { RNTI-Value } OPTIONAL, -- Need M + ..., + [[ + mcs-C-RNTI RNTI-Value OPTIONAL, -- Need R + p-UE-FR1 P-Max OPTIONAL -- Cond MCG-Only + ]], + [[ + xScale ENUMERATED {dB0, dB6, spare2, spare1} OPTIONAL -- Cond SCG-Only + ]], + [[ + pdcch-BlindDetection SetupRelease { PDCCH-BlindDetection } OPTIONAL -- Need M + ]], + [[ + dcp-Config-r16 SetupRelease { DCP-Config-r16 } OPTIONAL, -- Need M + harq-ACK-SpatialBundlingPUCCH-secondaryPUCCH-group-r16 ENUMERATED {true} OPTIONAL, -- Cond twoPUCCHgroup + harq-ACK-SpatialBundlingPUSCH-secondaryPUCCH-group-r16 ENUMERATED {true} OPTIONAL, -- Cond twoPUCCHgroup + pdsch-HARQ-ACK-Codebook-secondaryPUCCH-group-r16 ENUMERATED {semiStatic, dynamic} OPTIONAL, -- Cond twoPUCCHgroup + p-NR-FR2-r16 P-Max OPTIONAL, -- Need R + p-UE-FR2-r16 P-Max OPTIONAL, -- Cond MCG-Only + nrdc-PCmode-FR1-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, -- Cond MCG-Only + nrdc-PCmode-FR2-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, -- Cond MCG-Only + pdsch-HARQ-ACK-Codebook-r16 ENUMERATED {enhancedDynamic} OPTIONAL, -- Need R + nfi-TotalDAI-Included-r16 ENUMERATED {true} OPTIONAL, -- Need M + ul-TotalDAI-Included-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedback-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedbackNDI-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedbackCBG-r16 ENUMERATED {true} OPTIONAL, -- Need R + downlinkAssignmentIndexForDCI-Format0-2-r16 ENUMERATED { enabled } OPTIONAL, -- Need S + downlinkAssignmentIndexForDCI-Format1-2-r16 ENUMERATED {n1, n2, n4} OPTIONAL, -- Need S + pdsch-HARQ-ACK-CodebookList-r16 SetupRelease {PDSCH-HARQ-ACK-CodebookList-r16} OPTIONAL, -- Need M + ackNackFeedbackMode-r16 ENUMERATED {joint, separate} OPTIONAL, -- Need R + pdcch-BlindDetectionCA-CombIndicator-r16 SetupRelease { PDCCH-BlindDetectionCA-CombIndicator-r16 } OPTIONAL, -- Need M + pdcch-BlindDetection2-r16 SetupRelease { PDCCH-BlindDetection2-r16 } OPTIONAL, -- Need M + pdcch-BlindDetection3-r16 SetupRelease { PDCCH-BlindDetection3-r16 } OPTIONAL, -- Need M + bdFactorR-r16 ENUMERATED {n1} OPTIONAL -- Need R + ]] +} + +PDCCH-BlindDetection ::= INTEGER (1..15) + +DCP-Config-r16 ::= SEQUENCE { + ps-RNTI-r16 RNTI-Value, + ps-Offset-r16 INTEGER (1..120), + sizeDCI-2-6-r16 INTEGER (1..maxDCI-2-6-Size-r16), + ps-PositionDCI-2-6-r16 INTEGER (0..maxDCI-2-6-Size-1-r16), + ps-WakeUp-r16 ENUMERATED {true} OPTIONAL, -- Need S + ps-TransmitPeriodicL1-RSRP-r16 ENUMERATED {true} OPTIONAL, -- Need S + ps-TransmitOtherPeriodicCSI-r16 ENUMERATED {true} OPTIONAL -- Need S +} + +PDSCH-HARQ-ACK-CodebookList-r16 ::= SEQUENCE (SIZE (1..2)) OF ENUMERATED {semiStatic, dynamic} + +PDCCH-BlindDetectionCA-CombIndicator-r16 ::= SEQUENCE { + pdcch-BlindDetectionCA1-r16 INTEGER (1..15), + pdcch-BlindDetectionCA2-r16 INTEGER (1..15) +} + +PDCCH-BlindDetection2-r16 ::= INTEGER (1..15) + +PDCCH-BlindDetection3-r16 ::= INTEGER (1..15) + +-- TAG-PHYSICALCELLGROUPCONFIG-STOP +-- TAG-PLMN-IDENTITY-START + +PLMN-Identity ::= SEQUENCE { + mcc MCC OPTIONAL, -- Cond MCC + mnc MNC +} + +MCC ::= SEQUENCE (SIZE (3)) OF MCC-MNC-Digit + +MNC ::= SEQUENCE (SIZE (2..3)) OF MCC-MNC-Digit + +MCC-MNC-Digit ::= INTEGER (0..9) + + +-- TAG-PLMN-IDENTITY-STOP +-- TAG-PLMN-IDENTITYINFOLIST-START + +PLMN-IdentityInfoList ::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-IdentityInfo + +PLMN-IdentityInfo ::= SEQUENCE { + plmn-IdentityList SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity, + trackingAreaCode TrackingAreaCode OPTIONAL, -- Need R + ranac RAN-AreaCode OPTIONAL, -- Need R + cellIdentity CellIdentity, + cellReservedForOperatorUse ENUMERATED {reserved, notReserved}, + ..., + [[ + iab-Support-r16 ENUMERATED {true} OPTIONAL -- Need S + ]] +} +-- TAG-PLMN-IDENTITYINFOLIST-STOP +-- TAG-PLMNIDENTITYLIST2-START + +PLMN-IdentityList2-r16 ::= SEQUENCE (SIZE (1..16)) OF PLMN-Identity + +-- TAG-PLMNIDENTITYLIST2-STOP +-- TAG-PRB-ID-START + +PRB-Id ::= INTEGER (0..maxNrofPhysicalResourceBlocks-1) + +-- TAG-PRB-ID-STOP +-- TAG-PTRS-DOWNLINKCONFIG-START + +PTRS-DownlinkConfig ::= SEQUENCE { + frequencyDensity SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need S + timeDensity SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need S + epre-Ratio INTEGER (0..3) OPTIONAL, -- Need S + resourceElementOffset ENUMERATED { offset01, offset10, offset11 } OPTIONAL, -- Need S + ..., + [[ + maxNrofPorts-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + ]] + +} + +-- TAG-PTRS-DOWNLINKCONFIG-STOP +-- TAG-PTRS-UPLINKCONFIG-START + +PTRS-UplinkConfig ::= SEQUENCE { + transformPrecoderDisabled SEQUENCE { + frequencyDensity SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need S + timeDensity SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need S + maxNrofPorts ENUMERATED {n1, n2}, + resourceElementOffset ENUMERATED {offset01, offset10, offset11 } OPTIONAL, -- Need S + ptrs-Power ENUMERATED {p00, p01, p10, p11} + } OPTIONAL, -- Need R + transformPrecoderEnabled SEQUENCE { + sampleDensity SEQUENCE (SIZE (5)) OF INTEGER (1..276), + timeDensityTransformPrecoding ENUMERATED {d2} OPTIONAL -- Need S + } OPTIONAL, -- Need R + ... +} + +-- TAG-PTRS-UPLINKCONFIG-STOP +-- TAG-PUCCH-CONFIG-START + +PUCCH-Config ::= SEQUENCE { + resourceSetToAddModList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceSets)) OF PUCCH-ResourceSet OPTIONAL, -- Need N + resourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceSets)) OF PUCCH-ResourceSetId OPTIONAL, -- Need N + resourceToAddModList SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-Resource OPTIONAL, -- Need N + resourceToReleaseList SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-ResourceId OPTIONAL, -- Need N + format1 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format2 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format3 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format4 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + schedulingRequestResourceToAddModList SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceConfig + OPTIONAL, -- Need N + schedulingRequestResourceToReleaseList SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceId + OPTIONAL, -- Need N + multi-CSI-PUCCH-ResourceList SEQUENCE (SIZE (1..2)) OF PUCCH-ResourceId OPTIONAL, -- Need M + dl-DataToUL-ACK SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) OPTIONAL, -- Need M + spatialRelationInfoToAddModList SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos)) OF PUCCH-SpatialRelationInfo + OPTIONAL, -- Need N + spatialRelationInfoToReleaseList SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos)) OF PUCCH-SpatialRelationInfoId + OPTIONAL, -- Need N + pucch-PowerControl PUCCH-PowerControl OPTIONAL, -- Need M + ..., + [[ + resourceToAddModListExt-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-ResourceExt-r16 OPTIONAL, -- Need N + dl-DataToUL-ACK-r16 SetupRelease { DL-DataToUL-ACK-r16 } OPTIONAL, -- Need M + ul-AccessConfigListForDCI-Format-1-1-r16 SetupRelease { UL-AccessConfigListForDCI-Format1-1-r16 } OPTIONAL, -- Need M + subslotLengthForPUCCH-r16 CHOICE { + normalCP-r16 ENUMERATED {n2,n7}, + extendedCP-r16 ENUMERATED {n2,n6} + } OPTIONAL, -- Need R + dl-DataToUL-ACK-ForDCI-Format1-2-r16 SetupRelease { DL-DataToUL-ACK-ForDCI-Format1-2-r16} OPTIONAL, -- Need M + numberOfBitsForPUCCH-ResourceIndicatorForDCI-Format1-2-r16 INTEGER (0..3) OPTIONAL, -- Need R + dmrs-UplinkTransformPrecodingPUCCH-r16 ENUMERATED {enabled} OPTIONAL, -- Cond PI2-BPSK + spatialRelationInfoToAddModList2-r16 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfosDiff-r16)) OF PUCCH-SpatialRelationInfo + OPTIONAL, -- Need N + spatialRelationInfoToReleaseList2-r16 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfosDiff-r16)) OF PUCCH-SpatialRelationInfoId + OPTIONAL, -- Need N + spatialRelationInfoToAddModListExt-r16 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos-r16)) OF PUCCH-SpatialRelationInfoExt-r16 + OPTIONAL, -- Need N + spatialRelationInfoToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos-r16)) OF PUCCH-SpatialRelationInfoId-r16 OPTIONAL, -- Need N + resourceGroupToAddModList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceGroups-r16)) OF PUCCH-ResourceGroup-r16 + OPTIONAL, -- Need N + resourceGroupToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceGroups-r16)) OF PUCCH-ResourceGroupId-r16 + OPTIONAL, -- Need N + sps-PUCCH-AN-List-r16 SetupRelease { SPS-PUCCH-AN-List-r16 } OPTIONAL, -- Need M + schedulingRequestResourceToAddModList-v1610 SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceConfig-v1610 + OPTIONAL -- Need N + ]] +} + +PUCCH-FormatConfig ::= SEQUENCE { + interslotFrequencyHopping ENUMERATED {enabled} OPTIONAL, -- Need R + additionalDMRS ENUMERATED {true} OPTIONAL, -- Need R + maxCodeRate PUCCH-MaxCodeRate OPTIONAL, -- Need R + nrofSlots ENUMERATED {n2,n4,n8} OPTIONAL, -- Need S + pi2BPSK ENUMERATED {enabled} OPTIONAL, -- Need R + simultaneousHARQ-ACK-CSI ENUMERATED {true} OPTIONAL -- Need R +} + +PUCCH-MaxCodeRate ::= ENUMERATED {zeroDot08, zeroDot15, zeroDot25, zeroDot35, zeroDot45, zeroDot60, zeroDot80} + +-- A set with one or more PUCCH resources +PUCCH-ResourceSet ::= SEQUENCE { + pucch-ResourceSetId PUCCH-ResourceSetId, + resourceList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourcesPerSet)) OF PUCCH-ResourceId, + maxPayloadSize INTEGER (4..256) OPTIONAL -- Need R +} + +PUCCH-ResourceSetId ::= INTEGER (0..maxNrofPUCCH-ResourceSets-1) + +PUCCH-Resource ::= SEQUENCE { + pucch-ResourceId PUCCH-ResourceId, + startingPRB PRB-Id, + intraSlotFrequencyHopping ENUMERATED { enabled } OPTIONAL, -- Need R + secondHopPRB PRB-Id OPTIONAL, -- Need R + format CHOICE { + format0 PUCCH-format0, + format1 PUCCH-format1, + format2 PUCCH-format2, + format3 PUCCH-format3, + format4 PUCCH-format4 + } +} + +PUCCH-ResourceExt-r16 ::= SEQUENCE { + interlaceAllocation-r16 SEQUENCE { + rb-SetIndex INTEGER (0..4), + interlace0 CHOICE { + scs15 INTEGER (0..9), + scs30 INTEGER (0..4) + } + } OPTIONAL, --Need R + formatExt-v1610 CHOICE { + interlace1-v1610 INTEGER (0..9), + occ-v1610 SEQUENCE { + occ-Length-v1610 ENUMERATED {n2,n4} OPTIONAL, -- Need M + occ-Index-v1610 ENUMERATED {n0,n1,n2,n3} OPTIONAL -- Need M + } + } OPTIONAL, -- Need R + ... +} + +PUCCH-ResourceId ::= INTEGER (0..maxNrofPUCCH-Resources-1) + + +PUCCH-format0 ::= SEQUENCE { + initialCyclicShift INTEGER(0..11), + nrofSymbols INTEGER (1..2), + startingSymbolIndex INTEGER(0..13) +} + +PUCCH-format1 ::= SEQUENCE { + initialCyclicShift INTEGER(0..11), + nrofSymbols INTEGER (4..14), + startingSymbolIndex INTEGER(0..10), + timeDomainOCC INTEGER(0..6) +} + +PUCCH-format2 ::= SEQUENCE { + nrofPRBs INTEGER (1..16), + nrofSymbols INTEGER (1..2), + startingSymbolIndex INTEGER(0..13) +} + +PUCCH-format3 ::= SEQUENCE { + nrofPRBs INTEGER (1..16), + nrofSymbols INTEGER (4..14), + startingSymbolIndex INTEGER(0..10) +} + +PUCCH-format4 ::= SEQUENCE { + nrofSymbols INTEGER (4..14), + occ-Length ENUMERATED {n2,n4}, + occ-Index ENUMERATED {n0,n1,n2,n3}, + startingSymbolIndex INTEGER(0..10) +} + +PUCCH-ResourceGroup-r16 ::= SEQUENCE { + pucch-ResourceGroupId-r16 PUCCH-ResourceGroupId-r16, + resourcePerGroupList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourcesPerGroup-r16)) OF PUCCH-ResourceId +} + +PUCCH-ResourceGroupId-r16 ::= INTEGER (0..maxNrofPUCCH-ResourceGroups-1-r16) + +DL-DataToUL-ACK-r16 ::= SEQUENCE (SIZE (1..8)) OF INTEGER (-1..15) + +DL-DataToUL-ACK-ForDCI-Format1-2-r16 ::= SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) + +UL-AccessConfigListForDCI-Format1-1-r16 ::= SEQUENCE (SIZE (1..16)) OF INTEGER (0..15) + +-- TAG-PUCCH-CONFIG-STOP +-- TAG-PUCCH-CONFIGCOMMON-START + +PUCCH-ConfigCommon ::= SEQUENCE { + pucch-ResourceCommon INTEGER (0..15) OPTIONAL, -- Cond InitialBWP-Only + pucch-GroupHopping ENUMERATED { neither, enable, disable }, + hoppingId INTEGER (0..1023) OPTIONAL, -- Need R + p0-nominal INTEGER (-202..24) OPTIONAL, -- Need R + ... +} + +-- TAG-PUCCH-CONFIGCOMMON-STOP +-- TAG-PUCCH-CONFIGURATIONLIST-START + +PUCCH-ConfigurationList-r16 ::= SEQUENCE (SIZE (1..2)) OF PUCCH-Config + +-- TAG-PUCCH-CONFIGURATIONLIST-STOP +-- TAG-PUCCH-PATHLOSSREFERENCERS-ID-START + +PUCCH-PathlossReferenceRS-Id ::= INTEGER (0..maxNrofPUCCH-PathlossReferenceRSs-1) + +PUCCH-PathlossReferenceRS-Id-v1610 ::= INTEGER (maxNrofPUCCH-PathlossReferenceRSs..maxNrofPUCCH-PathlossReferenceRSs-1-r16) + +-- TAG-PUCCH-PATHLOSSREFERENCERS-ID-STOP +-- TAG-PUCCH-POWERCONTROL-START +PUCCH-PowerControl ::= SEQUENCE { + deltaF-PUCCH-f0 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f1 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f2 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f3 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f4 INTEGER (-16..15) OPTIONAL, -- Need R + p0-Set SEQUENCE (SIZE (1..maxNrofPUCCH-P0-PerSet)) OF P0-PUCCH OPTIONAL, -- Need M + pathlossReferenceRSs SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSs)) OF PUCCH-PathlossReferenceRS + OPTIONAL, -- Need M + twoPUCCH-PC-AdjustmentStates ENUMERATED {twoStates} OPTIONAL, -- Need S + ..., + [[ + pathlossReferenceRSs-v1610 SetupRelease { PathlossReferenceRSs-v1610 } OPTIONAL -- Need M + ]] +} + +P0-PUCCH ::= SEQUENCE { + p0-PUCCH-Id P0-PUCCH-Id, + p0-PUCCH-Value INTEGER (-16..15) +} + +P0-PUCCH-Id ::= INTEGER (1..8) + +PathlossReferenceRSs-v1610 ::= SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSsDiff-r16)) OF PUCCH-PathlossReferenceRS-r16 + +PUCCH-PathlossReferenceRS ::= SEQUENCE { + pucch-PathlossReferenceRS-Id PUCCH-PathlossReferenceRS-Id, + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + } +} + +PUCCH-PathlossReferenceRS-r16 ::= SEQUENCE { + pucch-PathlossReferenceRS-Id-r16 PUCCH-PathlossReferenceRS-Id-v1610, + referenceSignal-r16 CHOICE { + ssb-Index-r16 SSB-Index, + csi-RS-Index-r16 NZP-CSI-RS-ResourceId + } +} + +-- TAG-PUCCH-POWERCONTROL-STOP +-- TAG-PUCCH-SPATIALRELATIONINFO-START + +PUCCH-SpatialRelationInfo ::= SEQUENCE { + pucch-SpatialRelationInfoId PUCCH-SpatialRelationInfoId, + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId, + srs PUCCH-SRS + }, + pucch-PathlossReferenceRS-Id PUCCH-PathlossReferenceRS-Id, + p0-PUCCH-Id P0-PUCCH-Id, + closedLoopIndex ENUMERATED { i0, i1 } +} + +PUCCH-SpatialRelationInfoExt-r16 ::= SEQUENCE { + pucch-SpatialRelationInfoId-v1610 PUCCH-SpatialRelationInfoId-v1610 OPTIONAL, -- Cond SetupOnly + pucch-PathlossReferenceRS-Id-v1610 PUCCH-PathlossReferenceRS-Id-v1610 OPTIONAL, --Need R + ... +} + +PUCCH-SRS ::= SEQUENCE { + resource SRS-ResourceId, + uplinkBWP BWP-Id +} +-- TAG-PUCCH-SPATIALRELATIONINFO-STOP +-- TAG-PUCCH-SPATIALRELATIONINFO-START + +PUCCH-SpatialRelationInfoId ::= INTEGER (1..maxNrofSpatialRelationInfos) + +PUCCH-SpatialRelationInfoId-r16 ::= INTEGER (1..maxNrofSpatialRelationInfos-r16) + +PUCCH-SpatialRelationInfoId-v1610::= INTEGER (maxNrofSpatialRelationInfos-plus-1..maxNrofSpatialRelationInfos-r16) + +-- TAG-PUCCH-SPATIALRELATIONINFO-STOP +-- TAG-PUCCH-TPC-COMMANDCONFIG-START + +PUCCH-TPC-CommandConfig ::= SEQUENCE { + tpc-IndexPCell INTEGER (1..15) OPTIONAL, -- Cond PDCCH-OfSpcell + tpc-IndexPUCCH-SCell INTEGER (1..15) OPTIONAL, -- Cond PDCCH-ofSpCellOrPUCCH-SCell + ... +} + +-- TAG-PUCCH-TPC-COMMANDCONFIG-STOP +-- TAG-PUSCH-CONFIG-START + +PUSCH-Config ::= SEQUENCE { + dataScramblingIdentityPUSCH INTEGER (0..1023) OPTIONAL, -- Need S + txConfig ENUMERATED {codebook, nonCodebook} OPTIONAL, -- Need S + dmrs-UplinkForPUSCH-MappingTypeA SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + dmrs-UplinkForPUSCH-MappingTypeB SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + pusch-PowerControl PUSCH-PowerControl OPTIONAL, -- Need M + frequencyHopping ENUMERATED {intraSlot, interSlot} OPTIONAL, -- Need S + frequencyHoppingOffsetLists SEQUENCE (SIZE (1..4)) OF INTEGER (1.. maxNrofPhysicalResourceBlocks-1) + OPTIONAL, -- Need M + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch}, + pusch-TimeDomainAllocationList SetupRelease { PUSCH-TimeDomainResourceAllocationList } OPTIONAL, -- Need M + pusch-AggregationFactor ENUMERATED { n2, n4, n8 } OPTIONAL, -- Need S + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoder ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + transformPrecoder ENUMERATED {enabled, disabled} OPTIONAL, -- Need S + codebookSubset ENUMERATED {fullyAndPartialAndNonCoherent, partialAndNonCoherent,nonCoherent} + OPTIONAL, -- Cond codebookBased + maxRank INTEGER (1..4) OPTIONAL, -- Cond codebookBased + rbg-Size ENUMERATED { config2} OPTIONAL, -- Need S + uci-OnPUSCH SetupRelease { UCI-OnPUSCH} OPTIONAL, -- Need M + tp-pi2BPSK ENUMERATED {enabled} OPTIONAL, -- Need S + ..., + [[ + minimumSchedulingOffsetK2-r16 SetupRelease { MinSchedulingOffsetK2-Values-r16 } OPTIONAL, -- Need M + ul-AccessConfigListForDCI-Format0-1-r16 SetupRelease { UL-AccessConfigListForDCI-Format0-1-r16 } OPTIONAL, -- Need M + -- Start of the parameters for DCI format 0_2 introduced in V16.1.0 + harq-ProcessNumberSizeForDCI-Format0-2-r16 INTEGER (0..4) OPTIONAL, -- Need R + dmrs-SequenceInitializationForDCI-Format0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + numberOfBitsForRV-ForDCI-Format0-2-r16 INTEGER (0..2) OPTIONAL, -- Need R + antennaPortsFieldPresenceForDCI-Format0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + dmrs-UplinkForPUSCH-MappingTypeA-ForDCI-Format0-2-r16 SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + dmrs-UplinkForPUSCH-MappingTypeB-ForDCI-Format0-2-r16 SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + frequencyHoppingForDCI-Format0-2-r16 CHOICE { + pusch-RepTypeA ENUMERATED {intraSlot, interSlot}, + pusch-RepTypeB ENUMERATED {interRepetition, interSlot} + } OPTIONAL, -- Need S + frequencyHoppingOffsetListsForDCI-Format0-2-r16 SetupRelease { FrequencyHoppingOffsetListsForDCI-Format0-2-r16} OPTIONAL, -- Need M + codebookSubsetForDCI-Format0-2-r16 ENUMERATED {fullyAndPartialAndNonCoherent, partialAndNonCoherent,nonCoherent} + OPTIONAL, -- Cond codebookBased + invalidSymbolPatternIndicatorForDCI-Format0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + maxRankForDCI-Format0-2-r16 INTEGER (1..4) OPTIONAL, -- Cond codebookBased + mcs-TableForDCI-Format0-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoderForDCI-Format0-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + priorityIndicatorForDCI-Format0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + pusch-RepTypeIndicatorForDCI-Format0-2-r16 ENUMERATED { pusch-RepTypeA, pusch-RepTypeB} OPTIONAL, -- Need R + resourceAllocationForDCI-Format0-2-r16 ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch} + OPTIONAL, -- Need M + resourceAllocationType1GranularityForDCI-Format0-2-r16 ENUMERATED { n2,n4,n8,n16 } OPTIONAL, -- Need S + uci-OnPUSCH-ListForDCI-Format0-2-r16 SetupRelease { UCI-OnPUSCH-ListForDCI-Format0-2-r16} OPTIONAL, -- Need M + pusch-TimeDomainAllocationListForDCI-Format0-2-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + -- End of the parameters for DCI format 0_2 introduced in V16.1.0 + -- Start of the parameters for DCI format 0_1 introduced in V16.1.0 + pusch-TimeDomainAllocationListForDCI-Format0-1-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + invalidSymbolPatternIndicatorForDCI-Format0-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + priorityIndicatorForDCI-Format0-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + pusch-RepTypeIndicatorForDCI-Format0-1-r16 ENUMERATED { pusch-RepTypeA, pusch-RepTypeB} OPTIONAL, -- Need R + frequencyHoppingForDCI-Format0-1-r16 ENUMERATED {interRepetition, interSlot} OPTIONAL, -- Cond RepTypeB + uci-OnPUSCH-ListForDCI-Format0-1-r16 SetupRelease { UCI-OnPUSCH-ListForDCI-Format0-1-r16 } OPTIONAL, -- Need M + -- End of the parameters for DCI format 0_1 introduced in V16.1.0 + invalidSymbolPattern-r16 InvalidSymbolPattern-r16 OPTIONAL, -- Need S + pusch-PowerControl-v1610 SetupRelease {PUSCH-PowerControl-v1610} OPTIONAL, -- Need M + ul-FullPowerTransmission-r16 ENUMERATED {fullpower, fullpowerMode1, fullpoweMode2} OPTIONAL, -- Need R + pusch-TimeDomainAllocationListForMultiPUSCH-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + numberOfInvalidSymbolsForDL-UL-Switching-r16 INTEGER (1..4) OPTIONAL -- Cond RepTypeB2 + ]] +} + +UCI-OnPUSCH ::= SEQUENCE { + betaOffsets CHOICE { + dynamic SEQUENCE (SIZE (4)) OF BetaOffsets, + semiStatic BetaOffsets + } OPTIONAL, -- Need M + scaling ENUMERATED { f0p5, f0p65, f0p8, f1 } +} + +MinSchedulingOffsetK2-Values-r16 ::= SEQUENCE (SIZE (1..maxNrOfMinSchedulingOffsetValues-r16)) OF INTEGER (0..maxK2-SchedulingOffset-r16) + +UCI-OnPUSCH-ForDCI-Format0-2-r16 ::= SEQUENCE { + betaOffsetsForDCI-Format0-2-r16 CHOICE { + dynamicForDCI-Format0-2-r16 CHOICE { + oneBit-r16 SEQUENCE (SIZE (2)) OF BetaOffsets, + twoBits-r16 SEQUENCE (SIZE (4)) OF BetaOffsets + }, + semiStaticForDCI-Format0-2-r16 BetaOffsets + } OPTIONAL, -- Need M + scalingForDCI-Format0-2-r16 ENUMERATED { f0p5, f0p65, f0p8, f1 } +} + +FrequencyHoppingOffsetListsForDCI-Format0-2-r16 ::= SEQUENCE (SIZE (1..4)) OF INTEGER (1.. maxNrofPhysicalResourceBlocks-1) + +UCI-OnPUSCH-ListForDCI-Format0-2-r16 ::= SEQUENCE (SIZE (1..2)) OF UCI-OnPUSCH-ForDCI-Format0-2-r16 + +UCI-OnPUSCH-ListForDCI-Format0-1-r16 ::= SEQUENCE (SIZE (1..2)) OF UCI-OnPUSCH + +UL-AccessConfigListForDCI-Format0-1-r16 ::= SEQUENCE (SIZE (1..64)) OF INTEGER (0..63) + +-- TAG-PUSCH-CONFIG-STOP +-- TAG-PUSCH-CONFIGCOMMON-START + +PUSCH-ConfigCommon ::= SEQUENCE { + groupHoppingEnabledTransformPrecoding ENUMERATED {enabled} OPTIONAL, -- Need R + pusch-TimeDomainAllocationList PUSCH-TimeDomainResourceAllocationList OPTIONAL, -- Need R + msg3-DeltaPreamble INTEGER (-1..6) OPTIONAL, -- Need R + p0-NominalWithGrant INTEGER (-202..24) OPTIONAL, -- Need R + ... +} + +-- TAG-PUSCH-CONFIGCOMMON-STOP +-- TAG-PUSCH-POWERCONTROL-START + +PUSCH-PowerControl ::= SEQUENCE { + tpc-Accumulation ENUMERATED { disabled } OPTIONAL, -- Need S + msg3-Alpha Alpha OPTIONAL, -- Need S + p0-NominalWithoutGrant INTEGER (-202..24) OPTIONAL, -- Need M + p0-AlphaSets SEQUENCE (SIZE (1..maxNrofP0-PUSCH-AlphaSets)) OF P0-PUSCH-AlphaSet OPTIONAL, -- Need M + pathlossReferenceRSToAddModList SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSs)) OF PUSCH-PathlossReferenceRS + OPTIONAL, -- Need N + pathlossReferenceRSToReleaseList SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSs)) OF PUSCH-PathlossReferenceRS-Id + OPTIONAL, -- Need N + twoPUSCH-PC-AdjustmentStates ENUMERATED {twoStates} OPTIONAL, -- Need S + deltaMCS ENUMERATED {enabled} OPTIONAL, -- Need S + sri-PUSCH-MappingToAddModList SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF SRI-PUSCH-PowerControl + OPTIONAL, -- Need N + sri-PUSCH-MappingToReleaseList SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF SRI-PUSCH-PowerControlId + OPTIONAL -- Need N +} + +P0-PUSCH-AlphaSet ::= SEQUENCE { + p0-PUSCH-AlphaSetId P0-PUSCH-AlphaSetId, + p0 INTEGER (-16..15) OPTIONAL, -- Need S + alpha Alpha OPTIONAL -- Need S +} + +P0-PUSCH-AlphaSetId ::= INTEGER (0..maxNrofP0-PUSCH-AlphaSets-1) + +PUSCH-PathlossReferenceRS ::= SEQUENCE { + pusch-PathlossReferenceRS-Id PUSCH-PathlossReferenceRS-Id, + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + } +} + +PUSCH-PathlossReferenceRS-r16 ::= SEQUENCE { + pusch-PathlossReferenceRS-Id-r16 PUSCH-PathlossReferenceRS-Id-v1610, + referenceSignal-r16 CHOICE { + ssb-Index-r16 SSB-Index, + csi-RS-Index-r16 NZP-CSI-RS-ResourceId + } +} + +PUSCH-PathlossReferenceRS-Id ::= INTEGER (0..maxNrofPUSCH-PathlossReferenceRSs-1) + +PUSCH-PathlossReferenceRS-Id-v1610 ::= INTEGER (maxNrofPUSCH-PathlossReferenceRSs..maxNrofPUSCH-PathlossReferenceRSs-1-r16) + +SRI-PUSCH-PowerControl ::= SEQUENCE { + sri-PUSCH-PowerControlId SRI-PUSCH-PowerControlId, + sri-PUSCH-PathlossReferenceRS-Id PUSCH-PathlossReferenceRS-Id, + sri-P0-PUSCH-AlphaSetId P0-PUSCH-AlphaSetId, + sri-PUSCH-ClosedLoopIndex ENUMERATED { i0, i1 } +} + +SRI-PUSCH-PowerControlId ::= INTEGER (0..maxNrofSRI-PUSCH-Mappings-1) + +PUSCH-PowerControl-v1610 ::= SEQUENCE { + pathlossReferenceRSToAddModList2-r16 SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSsDiff-r16)) OF PUSCH-PathlossReferenceRS-r16 + OPTIONAL, -- Need N + pathlossReferenceRSToReleaseList2-r16 SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSsDiff-r16)) OF PUSCH-PathlossReferenceRS-Id-v1610 + OPTIONAL, -- Need N + p0-PUSCH-SetList-r16 SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF P0-PUSCH-Set-r16 OPTIONAL, -- Need R + olpc-ParameterSet SEQUENCE { + olpc-ParameterSetForDCI-Format0-1-r16 INTEGER (1..2) OPTIONAL, -- Need R + olpc-ParameterSetForDCI-Format0-2-r16 INTEGER (1..2) OPTIONAL -- Need R + } OPTIONAL, -- Need M + ... +} + +P0-PUSCH-Set-r16 ::= SEQUENCE { + p0-PUSCH-SetId-r16 P0-PUSCH-SetId-r16, + p0-List-r16 SEQUENCE (SIZE (1..maxNrofP0-PUSCH-Set-r16)) OF P0-PUSCH-r16 OPTIONAL, -- Need R + ... +} + +P0-PUSCH-SetId-r16 ::= INTEGER (0..maxNrofSRI-PUSCH-Mappings-1) + +P0-PUSCH-r16 ::= INTEGER (-16..15) + +-- TAG-PUSCH-POWERCONTROL-STOP +-- TAG-PUSCH-SERVINGCELLCONFIG-START + +PUSCH-ServingCellConfig ::= SEQUENCE { + codeBlockGroupTransmission SetupRelease { PUSCH-CodeBlockGroupTransmission } OPTIONAL, -- Need M + rateMatching ENUMERATED {limitedBufferRM} OPTIONAL, -- Need S + xOverhead ENUMERATED {xoh6, xoh12, xoh18} OPTIONAL, -- Need S + ..., + [[ + maxMIMO-Layers INTEGER (1..4) OPTIONAL, -- Need M + processingType2Enabled BOOLEAN OPTIONAL -- Need M + ]], + [[ + maxMIMO-LayersForDCI-Format0-2-r16 SetupRelease { MaxMIMO-LayersForDCI-Format0-2-r16} OPTIONAL -- Need M + ]] +} + +PUSCH-CodeBlockGroupTransmission ::= SEQUENCE { + maxCodeBlockGroupsPerTransportBlock ENUMERATED {n2, n4, n6, n8}, + ... +} + +MaxMIMO-LayersForDCI-Format0-2-r16 ::= INTEGER (1..4) + +-- TAG-PUSCH-SERVINGCELLCONFIG-STOP +-- TAG-PUSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-START + +PUSCH-TimeDomainResourceAllocationList ::= SEQUENCE (SIZE(1..maxNrofUL-Allocations)) OF PUSCH-TimeDomainResourceAllocation + +PUSCH-TimeDomainResourceAllocation ::= SEQUENCE { + k2 INTEGER(0..32) OPTIONAL, -- Need S + mappingType ENUMERATED {typeA, typeB}, + startSymbolAndLength INTEGER (0..127) +} + +PUSCH-TimeDomainResourceAllocationList-r16 ::= SEQUENCE (SIZE(1..maxNrofUL-Allocations-r16)) OF PUSCH-TimeDomainResourceAllocation-r16 + +PUSCH-TimeDomainResourceAllocation-r16 ::= SEQUENCE { + k2-r16 INTEGER(0..32) OPTIONAL, -- Need S + puschAllocationList-r16 SEQUENCE (SIZE(1..maxNrofMultiplePUSCHs-r16)) OF PUSCH-Allocation-r16, + ... +} + +PUSCH-Allocation-r16 ::= SEQUENCE { + mappingType-r16 ENUMERATED {typeA, typeB} OPTIONAL, -- Cond NotFormat01-02-Or-TypeA + startSymbolAndLength-r16 INTEGER (0..127) OPTIONAL, -- Cond NotFormat01-02-Or-TypeA + startSymbol-r16 INTEGER (0..13) OPTIONAL, -- Cond RepTypeB + length-r16 INTEGER (1..14) OPTIONAL, -- Cond RepTypeB + numberOfRepetitions-r16 ENUMERATED {n1, n2, n3, n4, n7, n8, n12, n16} OPTIONAL, -- Cond Format01-02 + ... +} + +-- TAG-PUSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-STOP +-- TAG-PUSCH-TPC-COMMANDCONFIG-START + +PUSCH-TPC-CommandConfig ::= SEQUENCE { + tpc-Index INTEGER (1..15) OPTIONAL, -- Cond SUL + tpc-IndexSUL INTEGER (1..15) OPTIONAL, -- Cond SUL-Only + targetCell ServCellIndex OPTIONAL, -- Need S + ... +} + +-- TAG-PUSCH-TPC-COMMANDCONFIG-STOP +-- TAG-Q-OFFSETRANGE-START + +Q-OffsetRange ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-Q-OFFSETRANGE-STOP +-- TAG-Q-QUALMIN-START + +Q-QualMin ::= INTEGER (-43..-12) + +-- TAG-Q-QUALMIN-STOP +-- TAG-Q-RXLEVMIN-START + +Q-RxLevMin ::= INTEGER (-70..-22) + +-- TAG-Q-RXLEVMIN-STOP +-- TAG-QUANTITYCONFIG-START + + +QuantityConfig ::= SEQUENCE { + quantityConfigNR-List SEQUENCE (SIZE (1..maxNrofQuantityConfig)) OF QuantityConfigNR OPTIONAL, -- Need M + ..., + [[ + quantityConfigEUTRA FilterConfig OPTIONAL -- Need M + ]], + [[ + quantityConfigUTRA-FDD-r16 QuantityConfigUTRA-FDD-r16 OPTIONAL, -- Need M + quantityConfigCLI-r16 FilterConfigCLI-r16 OPTIONAL -- Need M + ]] +} + +QuantityConfigNR::= SEQUENCE { + quantityConfigCell QuantityConfigRS, + quantityConfigRS-Index QuantityConfigRS OPTIONAL -- Need M +} + +QuantityConfigRS ::= SEQUENCE { + ssb-FilterConfig FilterConfig, + csi-RS-FilterConfig FilterConfig +} + +FilterConfig ::= SEQUENCE { + filterCoefficientRSRP FilterCoefficient DEFAULT fc4, + filterCoefficientRSRQ FilterCoefficient DEFAULT fc4, + filterCoefficientRS-SINR FilterCoefficient DEFAULT fc4 +} + +FilterConfigCLI-r16 ::= SEQUENCE { + filterCoefficientSRS-RSRP-r16 FilterCoefficient DEFAULT fc4, + filterCoefficientCLI-RSSI-r16 FilterCoefficient DEFAULT fc4 +} + +QuantityConfigUTRA-FDD-r16 ::= SEQUENCE { + filterCoefficientRSCP-r16 FilterCoefficient DEFAULT fc4, + filterCoefficientEcNO-r16 FilterCoefficient DEFAULT fc4 +} + +-- TAG-QUANTITYCONFIG-STOP +-- TAG-RACH-CONFIGCOMMON-START + +RACH-ConfigCommon ::= SEQUENCE { + rach-ConfigGeneric RACH-ConfigGeneric, + totalNumberOfRA-Preambles INTEGER (1..63) OPTIONAL, -- Need S + ssb-perRACH-OccasionAndCB-PreamblesPerSSB CHOICE { + oneEighth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneFourth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneHalf ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + one ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + two ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32}, + four INTEGER (1..16), + eight INTEGER (1..8), + sixteen INTEGER (1..4) + } OPTIONAL, -- Need M + + groupBconfigured SEQUENCE { + ra-Msg3SizeGroupA ENUMERATED {b56, b144, b208, b256, b282, b480, b640, + b800, b1000, b72, spare6, spare5,spare4, spare3, spare2, spare1}, + messagePowerOffsetGroupB ENUMERATED { minusinfinity, dB0, dB5, dB8, dB10, dB12, dB15, dB18}, + numberOfRA-PreamblesGroupA INTEGER (1..64) + } OPTIONAL, -- Need R + ra-ContentionResolutionTimer ENUMERATED { sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64}, + rsrp-ThresholdSSB RSRP-Range OPTIONAL, -- Need R + rsrp-ThresholdSSB-SUL RSRP-Range OPTIONAL, -- Cond SUL + prach-RootSequenceIndex CHOICE { + l839 INTEGER (0..837), + l139 INTEGER (0..137) + }, + msg1-SubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond L139 + restrictedSetConfig ENUMERATED {unrestrictedSet, restrictedSetTypeA, restrictedSetTypeB}, + msg3-transformPrecoder ENUMERATED {enabled} OPTIONAL, -- Need R + ..., + [[ + ra-PrioritizationForAccessIdentity SEQUENCE { + ra-Prioritization-r16 RA-Prioritization, + ra-PrioritizationForAI-r16 BIT STRING (SIZE (2)) + } OPTIONAL, -- Cond InitialBWP-Only + prach-RootSequenceIndex-r16 CHOICE { + l571 INTEGER (0..569), + l1151 INTEGER (0..1149) + } OPTIONAL -- Need R + ]] +} + +-- TAG-RACH-CONFIGCOMMON-STOP +-- TAG-RACH-CONFIGCOMMONTWOSTEPRA-START + +RACH-ConfigCommonTwoStepRA-r16 ::= SEQUENCE { + rach-ConfigGenericTwoStepRA-r16 RACH-ConfigGenericTwoStepRA-r16, + msgA-TotalNumberOfRA-Preambles-r16 INTEGER (1..63) OPTIONAL, -- Need S + msgA-SSB-PerRACH-OccasionAndCB-PreamblesPerSSB-r16 CHOICE { + oneEighth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneFourth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneHalf ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + one ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + two ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32}, + four INTEGER (1..16), + eight INTEGER (1..8), + sixteen INTEGER (1..4) + } OPTIONAL, -- Cond 2StepOnly + msgA-CB-PreamblesPerSSB-PerSharedRO-r16 INTEGER (1..60) OPTIONAL, -- Cond SharedRO + msgA-SSB-SharedRO-MaskIndex-r16 INTEGER (1..15) OPTIONAL, -- Need S + groupB-ConfiguredTwoStepRA-r16 GroupB-ConfiguredTwoStepRA-r16 OPTIONAL, -- Need S + msgA-PRACH-RootSequenceIndex-r16 CHOICE { + l839 INTEGER (0..837), + l139 INTEGER (0..137), + l571 INTEGER (0..569), + l1151 INTEGER (0..1149) + } OPTIONAL, -- Cond 2StepOnly + msgA-TransMax-r16 ENUMERATED {n1, n2, n4, n6, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Need R + msgA-RSRP-Threshold-r16 RSRP-Range OPTIONAL, -- Cond 2Step4Step + msgA-RSRP-ThresholdSSB-r16 RSRP-Range OPTIONAL, -- Need R + msgA-SubcarrierSpacing-r16 SubcarrierSpacing OPTIONAL, -- Cond 2StepOnlyL139 + msgA-RestrictedSetConfig-r16 ENUMERATED {unrestrictedSet, restrictedSetTypeA, + restrictedSetTypeB} OPTIONAL, -- Cond 2StepOnly + ra-PrioritizationForAccessIdentityTwoStep-r16 SEQUENCE { + ra-Prioritization-r16 RA-Prioritization, + ra-PrioritizationForAI-r16 BIT STRING (SIZE (2)) + } OPTIONAL, -- Cond InitialBWP-Only + ra-ContentionResolutionTimer-r16 ENUMERATED {sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64} OPTIONAL, -- Cond 2StepOnly + ... +} + +GroupB-ConfiguredTwoStepRA-r16 ::= SEQUENCE { + ra-MsgA-SizeGroupA ENUMERATED {b56, b144, b208, b256, b282, b480, b640, b800, + b1000, b72, spare6, spare5, spare4, spare3, spare2, spare1}, + messagePowerOffsetGroupB ENUMERATED {minusinfinity, dB0, dB5, dB8, dB10, dB12, dB15, dB18}, + numberofRA-PreamblesGroupA INTEGER (1..64) +} + +-- TAG-RACH-CONFIGCOMMONTWOSTEPRA-STOP +-- TAG-RACH-CONFIGDEDICATED-START + + +RACH-ConfigDedicated ::= SEQUENCE { + cfra CFRA OPTIONAL, -- Need S + ra-Prioritization RA-Prioritization OPTIONAL, -- Need N + ..., + [[ + ra-PrioritizationTwoStep-r16 RA-Prioritization OPTIONAL, -- Need N + cfra-TwoStep-r16 CFRA-TwoStep-r16 OPTIONAL -- Need S + ]] +} + +CFRA ::= SEQUENCE { + occasions SEQUENCE { + rach-ConfigGeneric RACH-ConfigGeneric, + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, four, eight, sixteen} + OPTIONAL -- Cond Mandatory + } OPTIONAL, -- Need S + resources CHOICE { + ssb SEQUENCE { + ssb-ResourceList SEQUENCE (SIZE(1..maxRA-SSB-Resources)) OF CFRA-SSB-Resource, + ra-ssb-OccasionMaskIndex INTEGER (0..15) + }, + csirs SEQUENCE { + csirs-ResourceList SEQUENCE (SIZE(1..maxRA-CSIRS-Resources)) OF CFRA-CSIRS-Resource, + rsrp-ThresholdCSI-RS RSRP-Range + } + }, + ..., + [[ + totalNumberOfRA-Preambles INTEGER (1..63) OPTIONAL -- Cond Occasions + ]] +} + +CFRA-TwoStep-r16 ::= SEQUENCE { + occasionsTwoStepRA-r16 SEQUENCE { + rach-ConfigGenericTwoStepRA-r16 RACH-ConfigGenericTwoStepRA-r16, + ssb-PerRACH-OccasionTwoStepRA-r16 ENUMERATED {oneEighth, oneFourth, oneHalf, one, + two, four, eight, sixteen} + } OPTIONAL, -- Need S + msgA-CFRA-PUSCH-r16 MsgA-PUSCH-Resource-r16, + msgA-TransMax-r16 ENUMERATED {n1, n2, n4, n6, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Need S + resourcesTwoStep-r16 SEQUENCE { + ssb-ResourceList SEQUENCE (SIZE(1..maxRA-SSB-Resources)) OF CFRA-SSB-Resource, + ra-ssb-OccasionMaskIndex INTEGER (0..15) + }, + ... +} + +CFRA-SSB-Resource ::= SEQUENCE { + ssb SSB-Index, + ra-PreambleIndex INTEGER (0..63), + ..., + [[ + msgA-PUSCH-resource-Index-r16 INTEGER (0..3071) OPTIONAL -- Cond 2StepCFRA + ]] + +} + +CFRA-CSIRS-Resource ::= SEQUENCE { + csi-RS CSI-RS-Index, + ra-OccasionList SEQUENCE (SIZE(1..maxRA-OccasionsPerCSIRS)) OF INTEGER (0..maxRA-Occasions-1), + ra-PreambleIndex INTEGER (0..63), + ... +} + +-- TAG-RACH-CONFIGDEDICATED-STOP +-- TAG-RACH-CONFIGGENERIC-START + +RACH-ConfigGeneric ::= SEQUENCE { + prach-ConfigurationIndex INTEGER (0..255), + msg1-FDM ENUMERATED {one, two, four, eight}, + msg1-FrequencyStart INTEGER (0..maxNrofPhysicalResourceBlocks-1), + zeroCorrelationZoneConfig INTEGER(0..15), + preambleReceivedTargetPower INTEGER (-202..-60), + preambleTransMax ENUMERATED {n3, n4, n5, n6, n7, n8, n10, n20, n50, n100, n200}, + powerRampingStep ENUMERATED {dB0, dB2, dB4, dB6}, + ra-ResponseWindow ENUMERATED {sl1, sl2, sl4, sl8, sl10, sl20, sl40, sl80}, + ..., + [[ + prach-ConfigurationPeriodScaling-IAB-r16 ENUMERATED {scf1,scf2,scf4,scf8,scf16,scf32,scf64} OPTIONAL, -- Need R + prach-ConfigurationFrameOffset-IAB-r16 INTEGER (0..63) OPTIONAL, -- Need R + prach-ConfigurationSOffset-IAB-r16 INTEGER (0..39) OPTIONAL, -- Need R + ra-ResponseWindow-v1610 ENUMERATED { sl60, sl160} OPTIONAL, -- Need R + prach-ConfigurationIndex-v1610 INTEGER (256..262) OPTIONAL -- Need R + ]] +} + +-- TAG-RACH-CONFIGGENERIC-STOP +-- TAG-RACH-CONFIGGENERICTWOSTEPRA-START + +RACH-ConfigGenericTwoStepRA-r16 ::= SEQUENCE { + msgA-PRACH-ConfigurationIndex-r16 INTEGER (0..262) OPTIONAL, -- Cond 2StepOnly + msgA-RO-FDM-r16 ENUMERATED {one, two, four, eight} OPTIONAL, -- Cond 2StepOnly + msgA-RO-FrequencyStart-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, -- Cond 2StepOnly + msgA-ZeroCorrelationZoneConfig-r16 INTEGER (0..15) OPTIONAL, -- Cond 2StepOnly + msgA-PreamblePowerRampingStep-r16 ENUMERATED {dB0, dB2, dB4, dB6} OPTIONAL, -- Cond 2StepOnlyNoCFRA + msgA-PreambleReceivedTargetPower-r16 INTEGER (-202..-60) OPTIONAL, -- Cond 2StepOnlyNoCFRA + msgB-ResponseWindow-r16 ENUMERATED {sl1, sl2, sl4, sl8, sl10, sl20, sl40, sl80, sl160, sl320} + OPTIONAL, -- Cond NoCFRA + preambleTransMax-r16 ENUMERATED {n3, n4, n5, n6, n7, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Cond 2StepOnlyNoCFRA + ... +} + +-- TAG-RACH-CONFIGGENERICTWOSTEPRA-STOP +-- TAG-RA-PRIORITIZATION-START + +RA-Prioritization ::= SEQUENCE { + powerRampingStepHighPriority ENUMERATED {dB0, dB2, dB4, dB6}, + scalingFactorBI ENUMERATED {zero, dot25, dot5, dot75} OPTIONAL, -- Need R + ... +} + +-- TAG-RA-PRIORITIZATION-STOP +-- TAG-RADIOBEARERCONFIG-START + +RadioBearerConfig ::= SEQUENCE { + srb-ToAddModList SRB-ToAddModList OPTIONAL, -- Cond HO-Conn + srb3-ToRelease ENUMERATED{true} OPTIONAL, -- Need N + drb-ToAddModList DRB-ToAddModList OPTIONAL, -- Cond HO-toNR + drb-ToReleaseList DRB-ToReleaseList OPTIONAL, -- Need N + securityConfig SecurityConfig OPTIONAL, -- Need M + ... +} + +SRB-ToAddModList ::= SEQUENCE (SIZE (1..2)) OF SRB-ToAddMod +SRB-ToAddMod ::= SEQUENCE { + srb-Identity SRB-Identity, + reestablishPDCP ENUMERATED{true} OPTIONAL, -- Need N + discardOnPDCP ENUMERATED{true} OPTIONAL, -- Need N + pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP + ... +} + +DRB-ToAddModList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-ToAddMod + +DRB-ToAddMod ::= SEQUENCE { + cnAssociation CHOICE { + eps-BearerIdentity INTEGER (0..15), + sdap-Config SDAP-Config + } OPTIONAL, -- Cond DRBSetup + drb-Identity DRB-Identity, + reestablishPDCP ENUMERATED{true} OPTIONAL, -- Need N + recoverPDCP ENUMERATED{true} OPTIONAL, -- Need N + pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP + ..., + [[ + daps-Config-r16 ENUMERATED{true} OPTIONAL --Need N + ]] +} +DRB-ToReleaseList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-Identity + +SecurityConfig ::= SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig OPTIONAL, -- Cond RBTermChange1 + keyToUse ENUMERATED{master, secondary} OPTIONAL, -- Cond RBTermChange + ... +} + +-- TAG-RADIOBEARERCONFIG-STOP +-- TAG-RADIOLINKMONITORINGCONFIG-START + +RadioLinkMonitoringConfig ::= SEQUENCE { + failureDetectionResourcesToAddModList SEQUENCE (SIZE(1..maxNrofFailureDetectionResources)) OF RadioLinkMonitoringRS + OPTIONAL, -- Need N + failureDetectionResourcesToReleaseList SEQUENCE (SIZE(1..maxNrofFailureDetectionResources)) OF RadioLinkMonitoringRS-Id + OPTIONAL, -- Need N + beamFailureInstanceMaxCount ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10} OPTIONAL, -- Need R + beamFailureDetectionTimer ENUMERATED {pbfd1, pbfd2, pbfd3, pbfd4, pbfd5, pbfd6, pbfd8, pbfd10} OPTIONAL, -- Need R + ... +} + +RadioLinkMonitoringRS ::= SEQUENCE { + radioLinkMonitoringRS-Id RadioLinkMonitoringRS-Id, + purpose ENUMERATED {beamFailure, rlf, both}, + detectionResource CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + }, + ... +} + +-- TAG-RADIOLINKMONITORINGCONFIG-STOP +-- TAG-RADIOLINKMONITORINGRS-ID-START + +RadioLinkMonitoringRS-Id ::= INTEGER (0..maxNrofFailureDetectionResources-1) + +-- TAG-RADIOLINKMONITORINGRS-ID-STOP +-- TAG-RAN-AREACODE-START + +RAN-AreaCode ::= INTEGER (0..255) + +-- TAG-RAN-AREACODE-STOP +-- TAG-RATEMATCHPATTERN-START + +RateMatchPattern ::= SEQUENCE { + rateMatchPatternId RateMatchPatternId, + + patternType CHOICE { + bitmaps SEQUENCE { + resourceBlocks BIT STRING (SIZE (275)), + symbolsInResourceBlock CHOICE { + oneSlot BIT STRING (SIZE (14)), + twoSlots BIT STRING (SIZE (28)) + }, + periodicityAndPattern CHOICE { + n2 BIT STRING (SIZE (2)), + n4 BIT STRING (SIZE (4)), + n5 BIT STRING (SIZE (5)), + n8 BIT STRING (SIZE (8)), + n10 BIT STRING (SIZE (10)), + n20 BIT STRING (SIZE (20)), + n40 BIT STRING (SIZE (40)) + } OPTIONAL, -- Need S + ... + }, + controlResourceSet ControlResourceSetId + }, + subcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond CellLevel + dummy ENUMERATED { dynamic, semiStatic }, + ..., + [[ + controlResourceSet-r16 ControlResourceSetId-r16 OPTIONAL -- Need R + ]] + +} + +-- TAG-RATEMATCHPATTERN-STOP +-- TAG-RATEMATCHPATTERNID-START + +RateMatchPatternId ::= INTEGER (0..maxNrofRateMatchPatterns-1) + +-- TAG-RATEMATCHPATTERNID-STOP +-- TAG-RATEMATCHPATTERNLTE-CRS-START + +RateMatchPatternLTE-CRS ::= SEQUENCE { + carrierFreqDL INTEGER (0..16383), + carrierBandwidthDL ENUMERATED {n6, n15, n25, n50, n75, n100, spare2, spare1}, + mbsfn-SubframeConfigList EUTRA-MBSFN-SubframeConfigList OPTIONAL, -- Need M + nrofCRS-Ports ENUMERATED {n1, n2, n4}, + v-Shift ENUMERATED {n0, n1, n2, n3, n4, n5} +} + +LTE-CRS-PatternList-r16 ::= SEQUENCE (SIZE (1..maxLTE-CRS-Patterns-r16)) OF RateMatchPatternLTE-CRS + +-- TAG-RATEMATCHPATTERNLTE-CRS-STOP +-- TAG-REFERENCETIMEINFO-START + +ReferenceTimeInfo-r16 ::= SEQUENCE { + time-r16 ReferenceTime-r16, + uncertainty-r16 INTEGER (0..32767) OPTIONAL, -- Need S + timeInfoType-r16 ENUMERATED {localClock} OPTIONAL, -- Need S + referenceSFN-r16 INTEGER (0..1023) OPTIONAL -- Cond RefTime +} + +ReferenceTime-r16 ::= SEQUENCE { + refDays-r16 INTEGER (0..72999), + refSeconds-r16 INTEGER (0..86399), + refMilliSeconds-r16 INTEGER (0..999), + refTenNanoSeconds-r16 INTEGER (0..99999) +} + +-- TAG-REFERENCETIMEINFO-STOP +-- TAG-REJECTWAITTIME-START + +RejectWaitTime ::= INTEGER (1..16) + +-- TAG-REJECTWAITTIME-STOP +-- TAG-REPETITIONSCHEMECONFIG-START + +RepetitionSchemeConfig-r16 ::= CHOICE { + fdm-TDM-r16 SetupRelease { FDM-TDM-r16 }, + slotBased-r16 SetupRelease { SlotBased-r16 } +} + +FDM-TDM-r16 ::= SEQUENCE { + repetitionScheme-r16 ENUMERATED {fdmSchemeA, fdmSchemeB,tdmSchemeA }, + startingSymbolOffsetK-r16 INTEGER (0..7) OPTIONAL -- Need R +} + +SlotBased-r16 ::= SEQUENCE { + tciMapping-r16 ENUMERATED {cyclicMapping, sequenticalMapping}, + sequenceOffsetforRV-r16 INTEGER (1..3) +} + +-- TAG-REPETITIONSCHEMECONFIG-STOP +-- TAG-REPORTCONFIGID-START + +ReportConfigId ::= INTEGER (1..maxReportConfigId) + +-- TAG-REPORTCONFIGID-STOP +-- TAG-REPORTCONFIGINTERRAT-START + +ReportConfigInterRAT ::= SEQUENCE { + reportType CHOICE { + periodical PeriodicalReportConfigInterRAT, + eventTriggered EventTriggerConfigInterRAT, + reportCGI ReportCGI-EUTRA, + ..., + reportSFTD ReportSFTD-EUTRA + } +} + +ReportCGI-EUTRA ::= SEQUENCE { + cellForWhichToReportCGI EUTRA-PhysCellId, + ..., + [[ + useAutonomousGaps-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] +} + +ReportSFTD-EUTRA ::= SEQUENCE { + reportSFTD-Meas BOOLEAN, + reportRSRP BOOLEAN, + ... +} + +EventTriggerConfigInterRAT ::= SEQUENCE { + eventId CHOICE { + eventB1 SEQUENCE { + b1-ThresholdEUTRA MeasTriggerQuantityEUTRA, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + ... + }, + eventB2 SEQUENCE { + b2-Threshold1 MeasTriggerQuantity, + b2-Threshold2EUTRA MeasTriggerQuantityEUTRA, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + ... + }, + ..., + [[ + eventB1-UTRA-FDD-r16 SEQUENCE { + b1-ThresholdUTRA-FDD-r16 MeasTriggerQuantityUTRA-FDD-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger, + ... + }, + eventB2-UTRA-FDD-r16 SEQUENCE { + b2-Threshold1-r16 MeasTriggerQuantity, + b2-Threshold2UTRA-FDD-r16 MeasTriggerQuantityUTRA-FDD-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger, + ... + } + ]] + }, + rsType NR-RS-Type, + + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + ..., + [[ + reportQuantityUTRA-FDD-r16 MeasReportQuantityUTRA-FDD-r16 OPTIONAL -- Need R + ]] + + +} + +PeriodicalReportConfigInterRAT ::= SEQUENCE { + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + ..., + [[ + reportQuantityUTRA-FDD-r16 MeasReportQuantityUTRA-FDD-r16 OPTIONAL -- Need R + ]] +} + +MeasTriggerQuantityUTRA-FDD-r16 ::= CHOICE{ + utra-FDD-RSCP-r16 INTEGER (-5..91), + utra-FDD-EcN0-r16 INTEGER (0..49) +} + +MeasReportQuantityUTRA-FDD-r16 ::= SEQUENCE { + cpich-RSCP BOOLEAN, + cpich-EcN0 BOOLEAN +} + +-- TAG-REPORTCONFIGINTERRAT-STOP +-- TAG-REPORTCONFIGNR-START + +ReportConfigNR ::= SEQUENCE { + reportType CHOICE { + periodical PeriodicalReportConfig, + eventTriggered EventTriggerConfig, + ..., + reportCGI ReportCGI, + reportSFTD ReportSFTD-NR, + condTriggerConfig-r16 CondTriggerConfig-r16, + cli-Periodical-r16 CLI-PeriodicalReportConfig-r16, + cli-EventTriggered-r16 CLI-EventTriggerConfig-r16 + } +} + +ReportCGI ::= SEQUENCE { + cellForWhichToReportCGI PhysCellId, + ..., + [[ + useAutonomousGaps-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] + +} + +ReportSFTD-NR ::= SEQUENCE { + reportSFTD-Meas BOOLEAN, + reportRSRP BOOLEAN, + ..., + [[ + reportSFTD-NeighMeas ENUMERATED {true} OPTIONAL, -- Need R + drx-SFTD-NeighMeas ENUMERATED {true} OPTIONAL, -- Need R + cellsForWhichToReportSFTD SEQUENCE (SIZE (1..maxCellSFTD)) OF PhysCellId OPTIONAL -- Need R + ]] +} + +CondTriggerConfig-r16 ::= SEQUENCE { + condEventId CHOICE { + condEventA3 SEQUENCE { + a3-Offset MeasTriggerQuantityOffset, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + condEventA5 SEQUENCE { + a5-Threshold1 MeasTriggerQuantity, + a5-Threshold2 MeasTriggerQuantity, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + ... + }, + rsType-r16 NR-RS-Type, + ... +} + +EventTriggerConfig::= SEQUENCE { + eventId CHOICE { + eventA1 SEQUENCE { + a1-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + eventA2 SEQUENCE { + a2-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + eventA3 SEQUENCE { + a3-Offset MeasTriggerQuantityOffset, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA4 SEQUENCE { + a4-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA5 SEQUENCE { + a5-Threshold1 MeasTriggerQuantity, + a5-Threshold2 MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA6 SEQUENCE { + a6-Offset MeasTriggerQuantityOffset, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + ... + }, + + rsType NR-RS-Type, + + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + + reportQuantityCell MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + + reportQuantityRS-Indexes MeasReportQuantity OPTIONAL, -- Need R + maxNrofRS-IndexesToReport INTEGER (1..maxNrofIndexesToReport) OPTIONAL, -- Need R + includeBeamMeasurements BOOLEAN, + reportAddNeighMeas ENUMERATED {setup} OPTIONAL, -- Need R + ..., + [[ + measRSSI-ReportConfig-r16 MeasRSSI-ReportConfig-r16 OPTIONAL, -- Need R + useT312-r16 BOOLEAN OPTIONAL, -- Need M + includeCommonLocationInfo-r16 ENUMERATED {true} OPTIONAL, -- Need R + includeBT-Meas-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + includeWLAN-Meas-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + includeSensor-Meas-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL -- Need M + ]] +} + +PeriodicalReportConfig ::= SEQUENCE { + rsType NR-RS-Type, + + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + + reportQuantityCell MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + + reportQuantityRS-Indexes MeasReportQuantity OPTIONAL, -- Need R + maxNrofRS-IndexesToReport INTEGER (1..maxNrofIndexesToReport) OPTIONAL, -- Need R + includeBeamMeasurements BOOLEAN, + useWhiteCellList BOOLEAN, + ..., + [[ + measRSSI-ReportConfig-r16 MeasRSSI-ReportConfig-r16 OPTIONAL, -- Need R + includeCommonLocationInfo-r16 ENUMERATED {true} OPTIONAL, -- Need R + includeBT-Meas-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + includeWLAN-Meas-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + includeSensor-Meas-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, -- Need M + ul-DelayValueConfig-r16 SetupRelease { UL-DelayValueConfig-r16 } OPTIONAL, -- Need M + reportAddNeighMeas-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] + +} + +NR-RS-Type ::= ENUMERATED {ssb, csi-rs} + +MeasTriggerQuantity ::= CHOICE { + rsrp RSRP-Range, + rsrq RSRQ-Range, + sinr SINR-Range +} + +MeasTriggerQuantityOffset ::= CHOICE { + rsrp INTEGER (-30..30), + rsrq INTEGER (-30..30), + sinr INTEGER (-30..30) +} + + +MeasReportQuantity ::= SEQUENCE { + rsrp BOOLEAN, + rsrq BOOLEAN, + sinr BOOLEAN +} + +MeasRSSI-ReportConfig-r16 ::= SEQUENCE { + channelOccupancyThreshold-r16 RSSI-Range-r16 OPTIONAL -- Need R +} + +CLI-EventTriggerConfig-r16 ::= SEQUENCE { + eventId-r16 CHOICE { + eventI1-r16 SEQUENCE { + i1-Threshold-r16 MeasTriggerQuantityCLI-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + ... + }, + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + maxReportCLI-r16 INTEGER (1..maxCLI-Report-r16), + ... +} + +CLI-PeriodicalReportConfig-r16 ::= SEQUENCE { + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantityCLI-r16 MeasReportQuantityCLI-r16, + maxReportCLI-r16 INTEGER (1..maxCLI-Report-r16), + ... +} + +MeasTriggerQuantityCLI-r16 ::= CHOICE { + srs-RSRP-r16 SRS-RSRP-Range-r16, + cli-RSSI-r16 CLI-RSSI-Range-r16 +} + +MeasReportQuantityCLI-r16 ::= ENUMERATED {srs-rsrp, cli-rssi} + +-- TAG-REPORTCONFIGNR-STOP +-- TAG-REPORTCONFIGNR-SL-START + +ReportConfigNR-SL-r16 ::= SEQUENCE { + reportType-r16 CHOICE { + periodical-r16 PeriodicalReportConfigNR-SL-r16, + eventTriggered-r16 EventTriggerConfigNR-SL-r16 + } +} + +EventTriggerConfigNR-SL-r16::= SEQUENCE { + eventId-r16 CHOICE { + eventC1 SEQUENCE { + c1-Threshold-r16 SL-CBR-r16, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + eventC2-r16 SEQUENCE { + c2-Threshold-r16 SL-CBR-r16, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + ... + }, + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity-r16 MeasReportQuantity-r16, + ... +} + +PeriodicalReportConfigNR-SL-r16 ::= SEQUENCE { + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity-r16 MeasReportQuantity-r16, + ... +} + +MeasReportQuantity-r16 ::= SEQUENCE { + cbr-r16 BOOLEAN, + ... +} + +-- TAG-REPORTCONFIGNR-SL-STOP +-- TAG-REPORTCONFIGTOADDMODLIST-START + +ReportConfigToAddModList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigToAddMod + +ReportConfigToAddMod ::= SEQUENCE { + reportConfigId ReportConfigId, + reportConfig CHOICE { + reportConfigNR ReportConfigNR, + ..., + reportConfigInterRAT ReportConfigInterRAT, + reportConfigNR-SL-r16 ReportConfigNR-SL-r16 + } +} + +-- TAG-REPORTCONFIGTOADDMODLIST-STOP +-- TAG-REPORTINTERVAL-START + +ReportInterval ::= ENUMERATED {ms120, ms240, ms480, ms640, ms1024, ms2048, ms5120, ms10240, ms20480, ms40960, + min1,min6, min12, min30 } + +-- TAG-REPORTINTERVAL-STOP +-- TAG-RESELECTIONTHRESHOLD-START + +ReselectionThreshold ::= INTEGER (0..31) + +-- TAG-RESELECTIONTHRESHOLD-STOP +-- TAG-RESELECTIONTHRESHOLDQ-START + +ReselectionThresholdQ ::= INTEGER (0..31) + +-- TAG-RESELECTIONTHRESHOLDQ-STOP +-- TAG-RESUMECAUSE-START + +ResumeCause ::= ENUMERATED {emergency, highPriorityAccess, mt-Access, mo-Signalling, + mo-Data, mo-VoiceCall, mo-VideoCall, mo-SMS, rna-Update, mps-PriorityAccess, + mcs-PriorityAccess, spare1, spare2, spare3, spare4, spare5 } + +-- TAG-RESUMECAUSE-STOP +-- TAG-RLC-BEARERCONFIG-START + +RLC-BearerConfig ::= SEQUENCE { + logicalChannelIdentity LogicalChannelIdentity, + servedRadioBearer CHOICE { + srb-Identity SRB-Identity, + drb-Identity DRB-Identity + } OPTIONAL, -- Cond LCH-SetupOnly + reestablishRLC ENUMERATED {true} OPTIONAL, -- Need N + rlc-Config RLC-Config OPTIONAL, -- Cond LCH-Setup + mac-LogicalChannelConfig LogicalChannelConfig OPTIONAL, -- Cond LCH-Setup + ..., + [[ + rlc-Config-v1610 RLC-Config-v1610 OPTIONAL -- Need R + ]] +} + +-- TAG-RLC-BEARERCONFIG-STOP +-- TAG-RLC-CONFIG-START + +RLC-Config ::= CHOICE { + am SEQUENCE { + ul-AM-RLC UL-AM-RLC, + dl-AM-RLC DL-AM-RLC + }, + um-Bi-Directional SEQUENCE { + ul-UM-RLC UL-UM-RLC, + dl-UM-RLC DL-UM-RLC + }, + um-Uni-Directional-UL SEQUENCE { + ul-UM-RLC UL-UM-RLC + }, + um-Uni-Directional-DL SEQUENCE { + dl-UM-RLC DL-UM-RLC + }, + ... +} + +UL-AM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthAM OPTIONAL, -- Cond Reestab + t-PollRetransmit T-PollRetransmit, + pollPDU PollPDU, + pollByte PollByte, + maxRetxThreshold ENUMERATED { t1, t2, t3, t4, t6, t8, t16, t32 } +} + +DL-AM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthAM OPTIONAL, -- Cond Reestab + t-Reassembly T-Reassembly, + t-StatusProhibit T-StatusProhibit +} + +UL-UM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthUM OPTIONAL -- Cond Reestab +} + +DL-UM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthUM OPTIONAL, -- Cond Reestab + t-Reassembly T-Reassembly +} + +T-PollRetransmit ::= ENUMERATED { + ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms105, + ms110, ms115, ms120, ms125, ms130, ms135, + ms140, ms145, ms150, ms155, ms160, ms165, + ms170, ms175, ms180, ms185, ms190, ms195, + ms200, ms205, ms210, ms215, ms220, ms225, + ms230, ms235, ms240, ms245, ms250, ms300, + ms350, ms400, ms450, ms500, ms800, ms1000, + ms2000, ms4000, ms1-v1610, ms2-v1610, ms3-v1610, + ms4-v1610, spare1} + + +PollPDU ::= ENUMERATED { + p4, p8, p16, p32, p64, p128, p256, p512, p1024, p2048, p4096, p6144, p8192, p12288, p16384,p20480, + p24576, p28672, p32768, p40960, p49152, p57344, p65536, infinity, spare8, spare7, spare6, spare5, spare4, + spare3, spare2, spare1} + +PollByte ::= ENUMERATED { + kB1, kB2, kB5, kB8, kB10, kB15, kB25, kB50, kB75, + kB100, kB125, kB250, kB375, kB500, kB750, kB1000, + kB1250, kB1500, kB2000, kB3000, kB4000, kB4500, + kB5000, kB5500, kB6000, kB6500, kB7000, kB7500, + mB8, mB9, mB10, mB11, mB12, mB13, mB14, mB15, + mB16, mB17, mB18, mB20, mB25, mB30, mB40, infinity, + spare20, spare19, spare18, spare17, spare16, + spare15, spare14, spare13, spare12, spare11, + spare10, spare9, spare8, spare7, spare6, spare5, + spare4, spare3, spare2, spare1} + +T-Reassembly ::= ENUMERATED { + ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms110, + ms120, ms130, ms140, ms150, ms160, ms170, + ms180, ms190, ms200, spare1} + +T-StatusProhibit ::= ENUMERATED { + ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms105, + ms110, ms115, ms120, ms125, ms130, ms135, + ms140, ms145, ms150, ms155, ms160, ms165, + ms170, ms175, ms180, ms185, ms190, ms195, + ms200, ms205, ms210, ms215, ms220, ms225, + ms230, ms235, ms240, ms245, ms250, ms300, + ms350, ms400, ms450, ms500, ms800, ms1000, + ms1200, ms1600, ms2000, ms2400, spare2, spare1} + +SN-FieldLengthUM ::= ENUMERATED {size6, size12} +SN-FieldLengthAM ::= ENUMERATED {size12, size18} + +RLC-Config-v1610 ::= SEQUENCE { + dl-AM-RLC-v1610 DL-AM-RLC-v1610 +} + +DL-AM-RLC-v1610 ::= SEQUENCE { + t-StatusProhibit-v1610 T-StatusProhibit-v1610 OPTIONAL, -- Need N + ... +} + +T-StatusProhibit-v1610 ::= ENUMERATED { ms1, ms2, ms3, ms4, spare4, spare3, spare2, spare1} + +-- TAG-RLC-CONFIG-STOP +-- TAG-RLF-TIMERSANDCONSTANTS-START + +RLF-TimersAndConstants ::= SEQUENCE { + t310 ENUMERATED {ms0, ms50, ms100, ms200, ms500, ms1000, ms2000, ms4000, ms6000}, + n310 ENUMERATED {n1, n2, n3, n4, n6, n8, n10, n20}, + n311 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10}, + ..., + [[ + t311 ENUMERATED {ms1000, ms3000, ms5000, ms10000, ms15000, ms20000, ms30000} + ]] +} + +-- TAG-RLF-TIMERSANDCONSTANTS-STOP +-- TAG-RNTI-VALUE-START + +RNTI-Value ::= INTEGER (0..65535) + +-- TAG-RNTI-VALUE-STOP +-- TAG-RSRP-RANGE-START + +RSRP-Range ::= INTEGER(0..127) + +-- TAG-RSRP-RANGE-STOP +-- TAG-RSRQ-RANGE-START + +RSRQ-Range ::= INTEGER(0..127) + +-- TAG-RSRQ-RANGE-STOP +-- TAG-RSSI-RANGE-START + +RSSI-Range-r16 ::= INTEGER(0..76) + +-- TAG-RSSI-RANGE-STOP +-- TAG-SCELLINDEX-START + +SCellIndex ::= INTEGER (1..31) + +-- TAG-SCELLINDEX-STOP +-- TAG-SCHEDULINGREQUESTCONFIG-START + +SchedulingRequestConfig ::= SEQUENCE { + schedulingRequestToAddModList SEQUENCE (SIZE (1..maxNrofSR-ConfigPerCellGroup)) OF SchedulingRequestToAddMod + OPTIONAL, -- Need N + schedulingRequestToReleaseList SEQUENCE (SIZE (1..maxNrofSR-ConfigPerCellGroup)) OF SchedulingRequestId + OPTIONAL -- Need N +} + +SchedulingRequestToAddMod ::= SEQUENCE { + schedulingRequestId SchedulingRequestId, + sr-ProhibitTimer ENUMERATED {ms1, ms2, ms4, ms8, ms16, ms32, ms64, ms128} OPTIONAL, -- Need S + sr-TransMax ENUMERATED { n4, n8, n16, n32, n64, spare3, spare2, spare1} +} + + + +-- TAG-SCHEDULINGREQUESTCONFIG-STOP +-- TAG-SCHEDULINGREQUESTID-START + +SchedulingRequestId ::= INTEGER (0..7) + +-- TAG-SCHEDULINGREQUESTID-STOP +-- TAG-SCHEDULINGREQUESTRESOURCECONFIG-START + +SchedulingRequestResourceConfig ::= SEQUENCE { + schedulingRequestResourceId SchedulingRequestResourceId, + schedulingRequestID SchedulingRequestId, + periodicityAndOffset CHOICE { + sym2 NULL, + sym6or7 NULL, + sl1 NULL, -- Recurs in every slot + sl2 INTEGER (0..1), + sl4 INTEGER (0..3), + sl5 INTEGER (0..4), + sl8 INTEGER (0..7), + sl10 INTEGER (0..9), + sl16 INTEGER (0..15), + sl20 INTEGER (0..19), + sl40 INTEGER (0..39), + sl80 INTEGER (0..79), + sl160 INTEGER (0..159), + sl320 INTEGER (0..319), + sl640 INTEGER (0..639) + } OPTIONAL, -- Need M + resource PUCCH-ResourceId OPTIONAL -- Need M +} + +SchedulingRequestResourceConfig-v1610 ::= SEQUENCE { + phy-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL, -- Need M + ... +} + +-- TAG-SCHEDULINGREQUESTRESOURCECONFIG-STOP +-- TAG-SCHEDULINGREQUESTRESOURCEID-START + +SchedulingRequestResourceId ::= INTEGER (1..maxNrofSR-Resources) + +-- TAG-SCHEDULINGREQUESTRESOURCEID-STOP +-- TAG-SCRAMBLINGID-START + +ScramblingId ::= INTEGER(0..1023) + +-- TAG-SCRAMBLINGID-STOP +-- TAG-SCS-SPECIFICCARRIER-START + +SCS-SpecificCarrier ::= SEQUENCE { + offsetToCarrier INTEGER (0..2199), + subcarrierSpacing SubcarrierSpacing, + carrierBandwidth INTEGER (1..maxNrofPhysicalResourceBlocks), + ..., + [[ + txDirectCurrentLocation INTEGER (0..4095) OPTIONAL -- Need S + ]] +} + +-- TAG-SCS-SPECIFICCARRIER-STOP +-- TAG-SDAP-CONFIG-START + +SDAP-Config ::= SEQUENCE { + pdu-Session PDU-SessionID, + sdap-HeaderDL ENUMERATED {present, absent}, + sdap-HeaderUL ENUMERATED {present, absent}, + defaultDRB BOOLEAN, + mappedQoS-FlowsToAdd SEQUENCE (SIZE (1..maxNrofQFIs)) OF QFI OPTIONAL, -- Need N + mappedQoS-FlowsToRelease SEQUENCE (SIZE (1..maxNrofQFIs)) OF QFI OPTIONAL, -- Need N + ... +} + +QFI ::= INTEGER (0..maxQFI) + +PDU-SessionID ::= INTEGER (0..255) + +-- TAG-SDAP-CONFIG-STOP +-- TAG-SEARCHSPACE-START + +SearchSpace ::= SEQUENCE { + searchSpaceId SearchSpaceId, + controlResourceSetId ControlResourceSetId OPTIONAL, -- Cond SetupOnly + monitoringSlotPeriodicityAndOffset CHOICE { + sl1 NULL, + sl2 INTEGER (0..1), + sl4 INTEGER (0..3), + sl5 INTEGER (0..4), + sl8 INTEGER (0..7), + sl10 INTEGER (0..9), + sl16 INTEGER (0..15), + sl20 INTEGER (0..19), + sl40 INTEGER (0..39), + sl80 INTEGER (0..79), + sl160 INTEGER (0..159), + sl320 INTEGER (0..319), + sl640 INTEGER (0..639), + sl1280 INTEGER (0..1279), + sl2560 INTEGER (0..2559) + } OPTIONAL, -- Cond Setup + duration INTEGER (2..2559) OPTIONAL, -- Need R + monitoringSymbolsWithinSlot BIT STRING (SIZE (14)) OPTIONAL, -- Cond Setup + nrofCandidates SEQUENCE { + aggregationLevel1 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel2 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel4 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel8 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel16 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8} + } OPTIONAL, -- Cond Setup + searchSpaceType CHOICE { + common SEQUENCE { + dci-Format0-0-AndFormat1-0 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-0 SEQUENCE { + nrofCandidates-SFI SEQUENCE { + aggregationLevel1 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-1 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-2 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-3 SEQUENCE { + dummy1 ENUMERATED {sl1, sl2, sl4, sl5, sl8, sl10, sl16, sl20} OPTIONAL, -- Cond Setup + dummy2 ENUMERATED {n1, n2}, + ... + } OPTIONAL -- Need R + }, + ue-Specific SEQUENCE { + dci-Formats ENUMERATED {formats0-0-And-1-0, formats0-1-And-1-1}, + ..., + [[ + dci-Formats-MT-r16 ENUMERATED {formats2-5} OPTIONAL, -- Need R + dci-FormatsSL-r16 ENUMERATED {formats0-0-And-1-0, formats0-1-And-1-1, formats3-0, formats3-1, + formats3-0-And-3-1} OPTIONAL, -- Need R + dci-FormatsExt-r16 ENUMERATED {formats0-2-And-1-2, formats0-1-And-1-1And-0-2-And-1-2} + OPTIONAL -- Need R + ]] + } + } OPTIONAL -- Cond Setup2 +} + +SearchSpaceExt-r16 ::= SEQUENCE { + controlResourceSetId-r16 ControlResourceSetId-r16 OPTIONAL, -- Cond SetupOnly2 + searchSpaceType-r16 SEQUENCE { + common-r16 SEQUENCE { + dci-Format2-4-r16 SEQUENCE { + nrofCandidates-CI-r16 SEQUENCE { + aggregationLevel1-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-5-r16 SEQUENCE { + nrofCandidates-IAB-r16 SEQUENCE { + aggregationLevel1-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-6-r16 SEQUENCE { + ... + } OPTIONAL, -- Need R + ... + } + } OPTIONAL, -- Cond Setup3 + searchSpaceGroupIdList-r16 SEQUENCE (SIZE (1.. 2)) OF INTEGER (0..1) OPTIONAL, -- Need R + freqMonitorLocations-r16 BIT STRING (SIZE (5)) OPTIONAL -- Need R +} + +-- TAG-SEARCHSPACE-STOP +-- TAG-SEARCHSPACEID-START + +SearchSpaceId ::= INTEGER (0..maxNrofSearchSpaces-1) + +-- TAG-SEARCHSPACEID-STOP +-- TAG-SEARCHSPACEZERO-START + +SearchSpaceZero ::= INTEGER (0..15) + +-- TAG-SEARCHSPACEZERO-STOP +-- TAG-SECURITYALGORITHMCONFIG-START + +SecurityAlgorithmConfig ::= SEQUENCE { + cipheringAlgorithm CipheringAlgorithm, + integrityProtAlgorithm IntegrityProtAlgorithm OPTIONAL, -- Need R + ... +} + +IntegrityProtAlgorithm ::= ENUMERATED { + nia0, nia1, nia2, nia3, spare4, spare3, + spare2, spare1, ...} + +CipheringAlgorithm ::= ENUMERATED { + nea0, nea1, nea2, nea3, spare4, spare3, + spare2, spare1, ...} + +-- TAG-SECURITYALGORITHMCONFIG-STOP +-- TAG-SEMISTATICCHANNELACCESSCONFIG-START + +SemiStaticChannelAccessConfig ::= SEQUENCE { + period ENUMERATED {ms1, ms2, ms2dot5, ms4, ms5, ms10} +} + +-- TAG-SEMISTATICCHANNELACCESSCONFIG-STOP +-- TAG-SENSORLOCATIONINFO-START + +Sensor-LocationInfo-r16 ::= SEQUENCE { + sensor-MeasurementInformation-r16 OCTET STRING OPTIONAL, + sensor-MotionInformation-r16 OCTET STRING OPTIONAL, + ... +} + +-- TAG-SENSORLOCATIONINFO-STOP +-- TAG-SERVCELLINDEX-START + +ServCellIndex ::= INTEGER (0..maxNrofServingCells-1) + +-- TAG-SERVCELLINDEX-STOP +-- TAG-SERVINGCELLCONFIG-START + +ServingCellConfig ::= SEQUENCE { + tdd-UL-DL-ConfigurationDedicated TDD-UL-DL-ConfigDedicated OPTIONAL, -- Cond TDD + initialDownlinkBWP BWP-DownlinkDedicated OPTIONAL, -- Need M + downlinkBWP-ToReleaseList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Id OPTIONAL, -- Need N + downlinkBWP-ToAddModList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Downlink OPTIONAL, -- Need N + firstActiveDownlinkBWP-Id BWP-Id OPTIONAL, -- Cond SyncAndCellAdd + bwp-InactivityTimer ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, + ms40,ms50, ms60, ms80,ms100, ms200,ms300, ms500, + ms750, ms1280, ms1920, ms2560, spare10, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, --Need R + defaultDownlinkBWP-Id BWP-Id OPTIONAL, -- Need S + uplinkConfig UplinkConfig OPTIONAL, -- Need M + supplementaryUplink UplinkConfig OPTIONAL, -- Need M + pdcch-ServingCellConfig SetupRelease { PDCCH-ServingCellConfig } OPTIONAL, -- Need M + pdsch-ServingCellConfig SetupRelease { PDSCH-ServingCellConfig } OPTIONAL, -- Need M + csi-MeasConfig SetupRelease { CSI-MeasConfig } OPTIONAL, -- Need M + sCellDeactivationTimer ENUMERATED {ms20, ms40, ms80, ms160, ms200, ms240, + ms320, ms400, ms480, ms520, ms640, ms720, + ms840, ms1280, spare2,spare1} OPTIONAL, -- Cond ServingCellWithoutPUCCH + crossCarrierSchedulingConfig CrossCarrierSchedulingConfig OPTIONAL, -- Need M + tag-Id TAG-Id, + dummy ENUMERATED {enabled} OPTIONAL, -- Need R + pathlossReferenceLinking ENUMERATED {spCell, sCell} OPTIONAL, -- Cond SCellOnly + servingCellMO MeasObjectId OPTIONAL, -- Cond MeasObject + ..., + [[ + lte-CRS-ToMatchAround SetupRelease { RateMatchPatternLTE-CRS } OPTIONAL, -- Need M + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + downlinkChannelBW-PerSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier OPTIONAL -- Need S + ]], + [[ + supplementaryUplinkRelease ENUMERATED {true} OPTIONAL, -- Need N + tdd-UL-DL-ConfigurationDedicated-iab-mt-r16 TDD-UL-DL-ConfigDedicated-IAB-MT-r16 OPTIONAL, -- Cond TDD_IAB + dormantBWP-Config-r16 SetupRelease { DormantBWP-Config-r16 } OPTIONAL, -- Need M + ca-SlotOffset-r16 CHOICE { + refSCS15kHz INTEGER (-2..2), + refSCS30KHz INTEGER (-5..5), + refSCS60KHz INTEGER (-10..10), + refSCS120KHz INTEGER (-20..20) + } OPTIONAL, -- Cond AsyncCA + channelAccessConfig-r16 SetupRelease { ChannelAccessConfig-r16 } OPTIONAL, -- Need M + intraCellGuardBandsUL-r16 IntraCellGuardBands-r16 OPTIONAL, -- Need S + intraCellGuardBandsDL-r16 IntraCellGuardBands-r16 OPTIONAL, -- Need S + csi-RS-ValidationWith-DCI-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + lte-CRS-PatternList1-r16 SetupRelease { LTE-CRS-PatternList-r16 } OPTIONAL, -- Need M + lte-CRS-PatternList2-r16 SetupRelease { LTE-CRS-PatternList-r16 } OPTIONAL, -- Need M + crs-RateMatch-PerCORESETPoolIndex-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableTwoDefaultTCIStates-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultTCIStatePerCoresetPoolIndex-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableBeamSwitchTiming-r16 ENUMERATED {true} OPTIONAL, -- Need R + cbg-TxDiffTBsProcessingType1-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + cbg-TxDiffTBsProcessingType2-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] +} + +UplinkConfig ::= SEQUENCE { + initialUplinkBWP BWP-UplinkDedicated OPTIONAL, -- Need M + uplinkBWP-ToReleaseList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Id OPTIONAL, -- Need N + uplinkBWP-ToAddModList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Uplink OPTIONAL, -- Need N + firstActiveUplinkBWP-Id BWP-Id OPTIONAL, -- Cond SyncAndCellAdd + pusch-ServingCellConfig SetupRelease { PUSCH-ServingCellConfig } OPTIONAL, -- Need M + carrierSwitching SetupRelease { SRS-CarrierSwitching } OPTIONAL, -- Need M + ..., + [[ + powerBoostPi2BPSK BOOLEAN OPTIONAL, -- Need M + uplinkChannelBW-PerSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier OPTIONAL -- Need S + ]], + [[ + enablePLRS-UpdateForPUSCH-SRS-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForPUSCH0-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForPUCCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForSRS-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + uplinkTxSwitching-r16 SetupRelease { UplinkTxSwitching-r16 } OPTIONAL -- Need M + ]] +} + +ChannelAccessConfig-r16 ::= SEQUENCE { + maxEnergyDetectionThreshold-r16 INTEGER(-85..-52), + energyDetectionThresholdOffset-r16 INTEGER (-20..-13), + ul-toDL-COT-SharingED-Threshold-r16 INTEGER (-85..-52) OPTIONAL, -- Need R + absenceOfAnyOtherTechnology-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +IntraCellGuardBands-r16 ::= SEQUENCE (SIZE (1..4)) OF GuardBand-r16 + +GuardBand-r16 ::= SEQUENCE { + startCRB-r16 INTEGER (0..274), + nrofCRBs-r16 INTEGER (0..15) +} + +DormancyGroupID-r16 ::= INTEGER (0..4) + +DormantBWP-Config-r16::= SEQUENCE { + dormantBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + withinActiveTimeConfig-r16 SetupRelease { WithinActiveTimeConfig-r16 } OPTIONAL, -- Need M + outsideActiveTimeConfig-r16 SetupRelease { OutsideActiveTimeConfig-r16 } OPTIONAL -- Need M +} + +WithinActiveTimeConfig-r16 ::= SEQUENCE { + firstWithinActiveTimeBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + dormancyGroupWithinActiveTime-r16 DormancyGroupID-r16 OPTIONAL -- Need R +} + +OutsideActiveTimeConfig-r16 ::= SEQUENCE { + firstOutsideActiveTimeBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + dormancyGroupOutsideActiveTime-r16 DormancyGroupID-r16 OPTIONAL -- Need R +} + +UplinkTxSwitching-r16 ::= SEQUENCE { + uplinkTxSwitchingPeriodLocation-r16 BOOLEAN, + uplinkTxSwitchingCarrier-r16 ENUMERATED {carrier1, carrier2} +} + +-- TAG-SERVINGCELLCONFIG-STOP +-- TAG-SERVINGCELLCONFIGCOMMON-START + +ServingCellConfigCommon ::= SEQUENCE { + physCellId PhysCellId OPTIONAL, -- Cond HOAndServCellAdd, + downlinkConfigCommon DownlinkConfigCommon OPTIONAL, -- Cond HOAndServCellAdd + uplinkConfigCommon UplinkConfigCommon OPTIONAL, -- Need M + supplementaryUplinkConfig UplinkConfigCommon OPTIONAL, -- Need S + n-TimingAdvanceOffset ENUMERATED { n0, n25600, n39936 } OPTIONAL, -- Need S + ssb-PositionsInBurst CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)) + } OPTIONAL, -- Cond AbsFreqSSB + ssb-periodicityServingCell ENUMERATED { ms5, ms10, ms20, ms40, ms80, ms160, spare2, spare1 } OPTIONAL, -- Need S + dmrs-TypeA-Position ENUMERATED {pos2, pos3}, + lte-CRS-ToMatchAround SetupRelease { RateMatchPatternLTE-CRS } OPTIONAL, -- Need M + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + ssbSubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond HOAndServCellWithSSB + tdd-UL-DL-ConfigurationCommon TDD-UL-DL-ConfigCommon OPTIONAL, -- Cond TDD + ss-PBCH-BlockPower INTEGER (-60..50), + ..., + [[ + channelAccessMode-r16 CHOICE { + dynamic NULL, + semiStatic SemiStaticChannelAccessConfig + } OPTIONAL, -- Cond SharedSpectrum + discoveryBurstWindowLength-r16 ENUMERATED {ms0dot5, ms1, ms2, ms3, ms4, ms5} OPTIONAL, -- Need M + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + highSpeedConfig-r16 HighSpeedConfig-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SERVINGCELLCONFIGCOMMON-STOP +-- TAG-SERVINGCELLCONFIGCOMMONSIB-START + +ServingCellConfigCommonSIB ::= SEQUENCE { + downlinkConfigCommon DownlinkConfigCommonSIB, + uplinkConfigCommon UplinkConfigCommonSIB OPTIONAL, -- Need R + supplementaryUplink UplinkConfigCommonSIB OPTIONAL, -- Need R + n-TimingAdvanceOffset ENUMERATED { n0, n25600, n39936 } OPTIONAL, -- Need S + ssb-PositionsInBurst SEQUENCE { + inOneGroup BIT STRING (SIZE (8)), + groupPresence BIT STRING (SIZE (8)) OPTIONAL -- Cond FR2-Only + }, + ssb-PeriodicityServingCell ENUMERATED {ms5, ms10, ms20, ms40, ms80, ms160}, + tdd-UL-DL-ConfigurationCommon TDD-UL-DL-ConfigCommon OPTIONAL, -- Cond TDD + ss-PBCH-BlockPower INTEGER (-60..50), + ..., + [[ + channelAccessMode-r16 CHOICE { + dynamic NULL, + semiStatic SemiStaticChannelAccessConfig + } OPTIONAL, -- Cond SharedSpectrum + discoveryBurstWindowLength-r16 ENUMERATED {ms0dot5, ms1, ms2, ms3, ms4, ms5} OPTIONAL, -- Need R + highSpeedConfig-r16 HighSpeedConfig-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SERVINGCELLCONFIGCOMMONSIB-STOP +-- TAG-SHORTI-RNTI-VALUE-START + +ShortI-RNTI-Value ::= BIT STRING (SIZE(24)) + +-- TAG-SHORTI-RNTI-VALUE-STOP +-- TAG-SHORTMAC-I-START + +ShortMAC-I ::= BIT STRING (SIZE (16)) + +-- TAG-SHORTMAC-I-STOP +-- TAG-SINR-RANGE-START + +SINR-Range ::= INTEGER(0..127) + +-- TAG-SINR-RANGE-STOP +-- TAG-SI-REQUESTCONFIG-START + +SI-RequestConfig::= SEQUENCE { + rach-OccasionsSI SEQUENCE { + rach-ConfigSI RACH-ConfigGeneric, + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, four, eight, sixteen} + } OPTIONAL, -- Need R + si-RequestPeriod ENUMERATED {one, two, four, six, eight, ten, twelve, sixteen} OPTIONAL, -- Need R + si-RequestResources SEQUENCE (SIZE (1..maxSI-Message)) OF SI-RequestResources +} + +SI-RequestResources ::= SEQUENCE { + ra-PreambleStartIndex INTEGER (0..63), + ra-AssociationPeriodIndex INTEGER (0..15) OPTIONAL, -- Need R + ra-ssb-OccasionMaskIndex INTEGER (0..15) OPTIONAL -- Need R +} + +-- TAG-SI-SCHEDULINGINFO-START + +SI-SchedulingInfo ::= SEQUENCE { + schedulingInfoList SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo, + si-WindowLength ENUMERATED {s5, s10, s20, s40, s80, s160, s320, s640, s1280}, + si-RequestConfig SI-RequestConfig OPTIONAL, -- Cond MSG-1 + si-RequestConfigSUL SI-RequestConfig OPTIONAL, -- Cond SUL-MSG-1 + systemInformationAreaID BIT STRING (SIZE (24)) OPTIONAL, -- Need R + ... +} + +SchedulingInfo ::= SEQUENCE { + si-BroadcastStatus ENUMERATED {broadcasting, notBroadcasting}, + si-Periodicity ENUMERATED {rf8, rf16, rf32, rf64, rf128, rf256, rf512}, + sib-MappingInfo SIB-Mapping +} + +SIB-Mapping ::= SEQUENCE (SIZE (1..maxSIB)) OF SIB-TypeInfo + +SIB-TypeInfo ::= SEQUENCE { + type ENUMERATED {sibType2, sibType3, sibType4, sibType5, sibType6, sibType7, sibType8, sibType9, + sibType10-v1610, sibType11-v1610, sibType12-v1610, sibType13-v1610, sibType14-v1610, + spare3, spare2, spare1,... }, + valueTag INTEGER (0..31) OPTIONAL, -- Cond SIB-TYPE + areaScope ENUMERATED {true} OPTIONAL -- Need S +} + +-- TAG-SI-SCHEDULINGINFO-STOP +-- TAG-SKCOUNTER-START + +SK-Counter ::= INTEGER (0..65535) + +-- TAG-SKCOUNTER-STOP +-- TAG-SLOTFORMATCOMBINATIONSPERCELL-START + +SlotFormatCombinationsPerCell ::= SEQUENCE { + servingCellId ServCellIndex, + subcarrierSpacing SubcarrierSpacing, + subcarrierSpacing2 SubcarrierSpacing OPTIONAL, -- Need R + slotFormatCombinations SEQUENCE (SIZE (1..maxNrofSlotFormatCombinationsPerSet)) OF SlotFormatCombination + OPTIONAL, -- Need M + positionInDCI INTEGER(0..maxSFI-DCI-PayloadSize-1) OPTIONAL, -- Need M + ..., + [[ + enableConfiguredUL-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + +} + +SlotFormatCombination ::= SEQUENCE { + slotFormatCombinationId SlotFormatCombinationId, + slotFormats SEQUENCE (SIZE (1..maxNrofSlotFormatsPerCombination)) OF INTEGER (0..255) +} + +SlotFormatCombinationId ::= INTEGER (0..maxNrofSlotFormatCombinationsPerSet-1) + +-- TAG-SLOTFORMATCOMBINATIONSPERCELL-STOP +-- TAG-SLOTFORMATINDICATOR-START + +SlotFormatIndicator ::= SEQUENCE { + sfi-RNTI RNTI-Value, + dci-PayloadSize INTEGER (1..maxSFI-DCI-PayloadSize), + slotFormatCombToAddModList SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF SlotFormatCombinationsPerCell + OPTIONAL, -- Need N + slotFormatCombToReleaseList SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL, -- Need N + ..., + [[ + availableRB-SetsToAddModList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF AvailableRB-SetsPerCell-r16 OPTIONAL, -- Need N + availableRB-SetsToRelease-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL, -- Need N + searchSpaceSwitchTriggerToAddModList-r16 SEQUENCE (SIZE(1..4)) OF SearchSpaceSwitchTrigger-r16 OPTIONAL, -- Need N + searchSpaceSwitchTriggerToReleaseList-r16 SEQUENCE (SIZE(1..4)) OF ServCellIndex OPTIONAL, -- Need N + co-DurationsPerCellToAddModList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF CO-DurationsPerCell-r16 OPTIONAL, -- Need N + co-DurationsPerCellToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL -- Need N + ]] +} + +CO-DurationsPerCell-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1), + subcarrierSpacing-r16 SubcarrierSpacing, + co-DurationList-r16 SEQUENCE (SIZE(1..64)) OF CO-Duration-r16 +} + +CO-Duration-r16 ::= INTEGER (0..1120) + +AvailableRB-SetsPerCell-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1) +} + +SearchSpaceSwitchTrigger-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1) +} + +-- TAG-SLOTFORMATINDICATOR-STOP +-- TAG-S-NSSAI-START + +S-NSSAI ::= CHOICE{ + sst BIT STRING (SIZE (8)), + sst-SD BIT STRING (SIZE (32)) +} + +-- TAG-S-NSSAI-STOP +-- TAG-SPEEDSTATESCALEFACTORS-START + +SpeedStateScaleFactors ::= SEQUENCE { + sf-Medium ENUMERATED {oDot25, oDot5, oDot75, lDot0}, + sf-High ENUMERATED {oDot25, oDot5, oDot75, lDot0} +} +-- TAG-SPEEDSTATESCALEFACTORS-STOP +-- TAG-SPS-CONFIG-START + +SPS-Config ::= SEQUENCE { + periodicity ENUMERATED {ms10, ms20, ms32, ms40, ms64, ms80, ms128, ms160, ms320, ms640, + spare6, spare5, spare4, spare3, spare2, spare1}, + nrofHARQ-Processes INTEGER (1..8), + n1PUCCH-AN PUCCH-ResourceId OPTIONAL, -- Need M + mcs-Table ENUMERATED {qam64LowSE} OPTIONAL, -- Need S + ..., + [[ + sps-ConfigIndex-r16 SPS-ConfigIndex-r16 OPTIONAL, -- Cond SPS-List + harq-ProcID-Offset-r16 INTEGER (0..15) OPTIONAL, -- Need R + periodicityExt-r16 INTEGER (1..5120) OPTIONAL, -- Need R + harq-CodebookID-r16 INTEGER (1..2) OPTIONAL, -- Need R + pdsch-AggregationFactor-r16 ENUMERATED {n1, n2, n4, n8 } OPTIONAL -- Need S + ]] +} + +-- TAG-SPS-CONFIG-STOP +-- TAG-SPS-CONFIGINDEX-START + +SPS-ConfigIndex-r16 ::= INTEGER (0.. maxNrofSPS-Config-r16-1) + +-- TAG-SPS-CONFIGINDEX-STOP +-- TAG-SPS-PUCCH-AN-START + +SPS-PUCCH-AN-r16 ::= SEQUENCE { + sps-PUCCH-AN-ResourceID-r16 PUCCH-ResourceId, + maxPayloadSize-r16 INTEGER (4..256) OPTIONAL -- Need R +} + +-- TAG-SPS-PUCCH-AN-STOP +-- TAG-SPS-PUCCH-AN-LIST-START + +SPS-PUCCH-AN-List-r16 ::= SEQUENCE (SIZE(1..4)) OF SPS-PUCCH-AN-r16 + +-- TAG-SPS-PUCCH-AN-LIST-STOP +-- TAG-SRB-IDENTITY-START + +SRB-Identity ::= INTEGER (1..3) + +-- TAG-SRB-IDENTITY-STOP +-- TAG-SRS-CARRIERSWITCHING-START + +SRS-CarrierSwitching ::= SEQUENCE { + srs-SwitchFromServCellIndex INTEGER (0..31) OPTIONAL, -- Need M + srs-SwitchFromCarrier ENUMERATED {sUL, nUL}, + srs-TPC-PDCCH-Group CHOICE { + typeA SEQUENCE (SIZE (1..32)) OF SRS-TPC-PDCCH-Config, + typeB SRS-TPC-PDCCH-Config + } OPTIONAL, -- Need M + monitoringCells SEQUENCE (SIZE (1..maxNrofServingCells)) OF ServCellIndex OPTIONAL, -- Need M + ... +} + +SRS-TPC-PDCCH-Config ::= SEQUENCE { + srs-CC-SetIndexlist SEQUENCE (SIZE(1..4)) OF SRS-CC-SetIndex OPTIONAL -- Need M +} + +SRS-CC-SetIndex ::= SEQUENCE { + cc-SetIndex INTEGER (0..3) OPTIONAL, -- Need M + cc-IndexInOneCC-Set INTEGER (0..7) OPTIONAL -- Need M +} + +-- TAG-SRS-CARRIERSWITCHING-STOP +-- TAG-SRS-CONFIG-START + +SRS-Config ::= SEQUENCE { + srs-ResourceSetToReleaseList SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSetId OPTIONAL, -- Need N + srs-ResourceSetToAddModList SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSet OPTIONAL, -- Need N + srs-ResourceToReleaseList SEQUENCE (SIZE(1..maxNrofSRS-Resources)) OF SRS-ResourceId OPTIONAL, -- Need N + srs-ResourceToAddModList SEQUENCE (SIZE(1..maxNrofSRS-Resources)) OF SRS-Resource OPTIONAL, -- Need N + tpc-Accumulation ENUMERATED {disabled} OPTIONAL, -- Need S + ..., + [[ + srs-RequestForDCI-Format1-2-r16 INTEGER (1..2) OPTIONAL, -- Need S + srs-RequestForDCI-Format0-2-r16 INTEGER (1..2) OPTIONAL, -- Need S + srs-ResourceSetToAddModListForDCI-Format0-2-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSet OPTIONAL, -- Need N + srs-ResourceSetToReleaseListForDCI-Format0-2-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSetId OPTIONAL,-- Need N + srs-PosResourceSetToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResourceSets-r16)) OF SRS-PosResourceSetId-r16 + OPTIONAL, -- Need N + srs-PosResourceSetToAddModList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResourceSets-r16)) OF SRS-PosResourceSet-r16 OPTIONAL,-- Need N + srs-PosResourceToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResources-r16)) OF SRS-PosResourceId-r16 OPTIONAL,-- Need N + srs-PosResourceToAddModList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResources-r16)) OF SRS-PosResource-r16 OPTIONAL -- Need N + ]] +} + +SRS-ResourceSet ::= SEQUENCE { + srs-ResourceSetId SRS-ResourceSetId, + srs-ResourceIdList SEQUENCE (SIZE(1..maxNrofSRS-ResourcesPerSet)) OF SRS-ResourceId OPTIONAL, -- Cond Setup + resourceType CHOICE { + aperiodic SEQUENCE { + aperiodicSRS-ResourceTrigger INTEGER (1..maxNrofSRS-TriggerStates-1), + csi-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + slotOffset INTEGER (1..32) OPTIONAL, -- Need S + ..., + [[ + aperiodicSRS-ResourceTriggerList SEQUENCE (SIZE(1..maxNrofSRS-TriggerStates-2)) + OF INTEGER (1..maxNrofSRS-TriggerStates-1) OPTIONAL -- Need M + ]] + }, + semi-persistent SEQUENCE { + associatedCSI-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + ... + }, + periodic SEQUENCE { + associatedCSI-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + ... + } + }, + usage ENUMERATED {beamManagement, codebook, nonCodebook, antennaSwitching}, + alpha Alpha OPTIONAL, -- Need S + p0 INTEGER (-202..24) OPTIONAL, -- Cond Setup + pathlossReferenceRS PathlossReferenceRS-Config OPTIONAL, -- Need M + srs-PowerControlAdjustmentStates ENUMERATED { sameAsFci2, separateClosedLoop} OPTIONAL, -- Need S + ..., + [[ + pathlossReferenceRSList-r16 SetupRelease { PathlossReferenceRSList-r16} OPTIONAL -- Need M + ]] +} + +PathlossReferenceRS-Config ::= CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId +} + +PathlossReferenceRSList-r16 ::= SEQUENCE (SIZE (1..maxNrofSRS-PathlossReferenceRS-r16)) OF PathlossReferenceRS-r16 + +PathlossReferenceRS-r16 ::= SEQUENCE { + srs-PathlossReferenceRS-Id-r16 SRS-PathlossReferenceRS-Id-r16, + pathlossReferenceRS-r16 PathlossReferenceRS-Config +} + +SRS-PathlossReferenceRS-Id-r16 ::= INTEGER (0..maxNrofSRS-PathlossReferenceRS-1-r16) + +SRS-PosResourceSet-r16 ::= SEQUENCE { + srs-PosResourceSetId-r16 SRS-PosResourceSetId-r16, + srs-PosResourceIdList-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourcesPerSet)) OF SRS-PosResourceId-r16 + OPTIONAL, -- Cond Setup + resourceType-r16 CHOICE { + aperiodic-r16 SEQUENCE { + aperiodicSRS-ResourceTriggerList-r16 SEQUENCE (SIZE(1..maxNrofSRS-TriggerStates-1)) + OF INTEGER (1..maxNrofSRS-TriggerStates-1) OPTIONAL, -- Need M + ... + }, + semi-persistent-r16 SEQUENCE { + ... + }, + periodic-r16 SEQUENCE { + ... + } + }, + alpha-r16 Alpha OPTIONAL, -- Need S + p0-r16 INTEGER (-202..24) OPTIONAL, -- Cond Setup + pathlossReferenceRS-Pos-r16 CHOICE { + ssb-IndexServing-r16 SSB-Index, + ssb-Ncell-r16 SSB-InfoNcell-r16, + dl-PRS-r16 DL-PRS-Info-r16 + } OPTIONAL, -- Need M + ... +} + +SRS-ResourceSetId ::= INTEGER (0..maxNrofSRS-ResourceSets-1) + +SRS-PosResourceSetId-r16 ::= INTEGER (0..maxNrofSRS-PosResourceSets-1-r16) + +SRS-Resource ::= SEQUENCE { + srs-ResourceId SRS-ResourceId, + nrofSRS-Ports ENUMERATED {port1, ports2, ports4}, + ptrs-PortIndex ENUMERATED {n0, n1 } OPTIONAL, -- Need R + transmissionComb CHOICE { + n2 SEQUENCE { + combOffset-n2 INTEGER (0..1), + cyclicShift-n2 INTEGER (0..7) + }, + n4 SEQUENCE { + combOffset-n4 INTEGER (0..3), + cyclicShift-n4 INTEGER (0..11) + } + }, + resourceMapping SEQUENCE { + startPosition INTEGER (0..5), + nrofSymbols ENUMERATED {n1, n2, n4}, + repetitionFactor ENUMERATED {n1, n2, n4} + }, + freqDomainPosition INTEGER (0..67), + freqDomainShift INTEGER (0..268), + freqHopping SEQUENCE { + c-SRS INTEGER (0..63), + b-SRS INTEGER (0..3), + b-hop INTEGER (0..3) + }, + groupOrSequenceHopping ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceType CHOICE { + aperiodic SEQUENCE { + ... + }, + semi-persistent SEQUENCE { + periodicityAndOffset-sp SRS-PeriodicityAndOffset, + ... + }, + periodic SEQUENCE { + periodicityAndOffset-p SRS-PeriodicityAndOffset, + ... + } + }, + sequenceId INTEGER (0..1023), + spatialRelationInfo SRS-SpatialRelationInfo OPTIONAL, -- Need R + ..., + [[ + resourceMapping-r16 SEQUENCE { + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 ENUMERATED {n1, n2, n4}, + repetitionFactor-r16 ENUMERATED {n1, n2, n4} + } OPTIONAL -- Need R + ]] + +} + +SRS-PosResource-r16::= SEQUENCE { + srs-PosResourceId-r16 SRS-PosResourceId-r16, + transmissionComb-r16 CHOICE { + n2-r16 SEQUENCE { + combOffset-n2-r16 INTEGER (0..1), + cyclicShift-n2-r16 INTEGER (0..7) + }, + n4-r16 SEQUENCE { + combOffset-n4-16 INTEGER (0..3), + cyclicShift-n4-r16 INTEGER (0..11) + }, + n8-r16 SEQUENCE { + combOffset-n8-r16 INTEGER (0..7), + cyclicShift-n8-r16 INTEGER (0..5) + }, + ... + }, + resourceMapping-r16 SEQUENCE { + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 ENUMERATED {n1, n2, n4, n8, n12} + }, + freqDomainShift-r16 INTEGER (0..268), + freqHopping-r16 SEQUENCE { + c-SRS-r16 INTEGER (0..63), + ... + }, + groupOrSequenceHopping-r16 ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceType-r16 CHOICE { + aperiodic-r16 SEQUENCE { + slotOffset-r16 INTEGER (1..32) OPTIONAL, -- Need S + ... + }, + semi-persistent-r16 SEQUENCE { + periodicityAndOffset-sp-r16 SRS-PeriodicityAndOffset-r16, + ... + }, + periodic-r16 SEQUENCE { + periodicityAndOffset-p-r16 SRS-PeriodicityAndOffset-r16, + ... + } + }, + sequenceId-r16 INTEGER (0..65535), + spatialRelationInfoPos-r16 SRS-SpatialRelationInfoPos-r16 OPTIONAL, -- Need R + ... +} + +SRS-SpatialRelationInfo ::= SEQUENCE { + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId, + srs SEQUENCE { + resourceId SRS-ResourceId, + uplinkBWP BWP-Id + } + } +} + +SRS-SpatialRelationInfoPos-r16 ::= CHOICE { + servingRS-r16 SEQUENCE { + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal-r16 CHOICE { + ssb-IndexServing-r16 SSB-Index, + csi-RS-IndexServing-r16 NZP-CSI-RS-ResourceId, + srs-SpatialRelation-r16 SEQUENCE { + resourceSelection-r16 CHOICE { + srs-ResourceId-r16 SRS-ResourceId, + srs-PosResourceId-r16 SRS-PosResourceId-r16 + }, + uplinkBWP-r16 BWP-Id + } + } + }, + ssb-Ncell-r16 SSB-InfoNcell-r16, + dl-PRS-r16 DL-PRS-Info-r16 +} + +SSB-Configuration-r16 ::= SEQUENCE { + ssb-Freq-r16 ARFCN-ValueNR, + halfFrameIndex-r16 ENUMERATED {zero, one}, + ssbSubcarrierSpacing-r16 SubcarrierSpacing, + ssb-Periodicity-r16 ENUMERATED { ms5, ms10, ms20, ms40, ms80, ms160, spare2,spare1 } OPTIONAL, -- Need S + sfn0-Offset-r16 SEQUENCE { + sfn-Offset-r16 INTEGER (0..1023), + integerSubframeOffset-r16 INTEGER (0..9) OPTIONAL -- Need R + } OPTIONAL, -- Need R + sfn-SSB-Offset-r16 INTEGER (0..15), + ss-PBCH-BlockPower-r16 INTEGER (-60..50) OPTIONAL -- Cond Pathloss +} + +SSB-InfoNcell-r16 ::= SEQUENCE { + physicalCellId-r16 PhysCellId, + ssb-IndexNcell-r16 SSB-Index OPTIONAL, -- Need S + ssb-Configuration-r16 SSB-Configuration-r16 OPTIONAL -- Need S +} + +DL-PRS-Info-r16 ::= SEQUENCE { + dl-PRS-ID-r16 INTEGER (0..255), + dl-PRS-ResourceSetId-r16 INTEGER (0..7), + dl-PRS-ResourceId-r16 INTEGER (0..63) OPTIONAL -- Need S +} + +SRS-ResourceId ::= INTEGER (0..maxNrofSRS-Resources-1) +SRS-PosResourceId-r16 ::= INTEGER (0..maxNrofSRS-PosResources-1-r16) + +SRS-PeriodicityAndOffset ::= CHOICE { + sl1 NULL, + sl2 INTEGER(0..1), + sl4 INTEGER(0..3), + sl5 INTEGER(0..4), + sl8 INTEGER(0..7), + sl10 INTEGER(0..9), + sl16 INTEGER(0..15), + sl20 INTEGER(0..19), + sl32 INTEGER(0..31), + sl40 INTEGER(0..39), + sl64 INTEGER(0..63), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + sl640 INTEGER(0..639), + sl1280 INTEGER(0..1279), + sl2560 INTEGER(0..2559) +} + +SRS-PeriodicityAndOffset-r16 ::= CHOICE { + sl1 NULL, + sl2 INTEGER(0..1), + sl4 INTEGER(0..3), + sl5 INTEGER(0..4), + sl8 INTEGER(0..7), + sl10 INTEGER(0..9), + sl16 INTEGER(0..15), + sl20 INTEGER(0..19), + sl32 INTEGER(0..31), + sl40 INTEGER(0..39), + sl64 INTEGER(0..63), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + sl640 INTEGER(0..639), + sl1280 INTEGER(0..1279), + sl2560 INTEGER(0..2559), + sl5120 INTEGER(0..5119), + sl10240 INTEGER(0..10239), + sl40960 INTEGER(0..40959), + sl81920 INTEGER(0..81919), + ... +} + +-- TAG-SRS-CONFIG-STOP +-- TAG-SRS-RSRP-RANGE-START + +SRS-RSRP-Range-r16 ::= INTEGER(0..98) + +-- TAG-SRS-RSRP-RANGE-STOP +-- TAG-SRS-TPC-COMMANDCONFIG-START + +SRS-TPC-CommandConfig ::= SEQUENCE { + startingBitOfFormat2-3 INTEGER (1..31) OPTIONAL, -- Need R + fieldTypeFormat2-3 INTEGER (0..1) OPTIONAL, -- Need R + ..., + [[ + startingBitOfFormat2-3SUL INTEGER (1..31) OPTIONAL -- Need R + ]] +} + +-- TAG-SRS-TPC-COMMANDCONFIG-STOP +-- TAG-SSB-INDEX-START + +SSB-Index ::= INTEGER (0..maxNrofSSBs-1) + +-- TAG-SSB-INDEX-STOP +-- TAG-SSB-MTC-START + +SSB-MTC ::= SEQUENCE { + periodicityAndOffset CHOICE { + sf5 INTEGER (0..4), + sf10 INTEGER (0..9), + sf20 INTEGER (0..19), + sf40 INTEGER (0..39), + sf80 INTEGER (0..79), + sf160 INTEGER (0..159) + }, + duration ENUMERATED { sf1, sf2, sf3, sf4, sf5 } +} + +SSB-MTC2 ::= SEQUENCE { + pci-List SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need M + periodicity ENUMERATED {sf5, sf10, sf20, sf40, sf80, spare3, spare2, spare1} +} + +SSB-MTC2-LP-r16 ::= SEQUENCE { + pci-List SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need R + periodicity ENUMERATED {sf10, sf20, sf40, sf80, sf160, spare3, spare2, spare1} +} + +SSB-MTC3-r16 ::= SEQUENCE { + periodicityAndOffset-r16 CHOICE { + sf5-r16 INTEGER (0..4), + sf10-r16 INTEGER (0..9), + sf20-r16 INTEGER (0..19), + sf40-r16 INTEGER (0..39), + sf80-r16 INTEGER (0..79), + sf160-r16 INTEGER (0..159), + sf320-r16 INTEGER (0..319), + sf640-r16 INTEGER (0..639), + sf1280-r16 INTEGER (0..1279) + }, + duration-r16 ENUMERATED {sf1, sf2, sf3, sf4, sf5}, + pci-List-r16 SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need M + ssb-ToMeasure-r16 SetupRelease { SSB-ToMeasure } OPTIONAL -- Need M +} + + +-- TAG-SSB-MTC-STOP +-- TAG-SSB-POSITIONQCL-RELATION-START + +SSB-PositionQCL-Relation-r16 ::= ENUMERATED {n1,n2,n4,n8} + +-- TAG-SSB-POSITIONQCL-RELATION-STOP +-- TAG-SSB-TOMEASURE-START + +SSB-ToMeasure ::= CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)) +} + +-- TAG-SSB-TOMEASURE-STOP +-- TAG-SS-RSSI-MEASUREMENT-START + +SS-RSSI-Measurement ::= SEQUENCE { + measurementSlots BIT STRING (SIZE (1..80)), + endSymbol INTEGER(0..3) +} + +-- TAG-SS-RSSI-MEASUREMENT-STOP +-- TAG-SUBCARRIERSPACING-START + +SubcarrierSpacing ::= ENUMERATED {kHz15, kHz30, kHz60, kHz120, kHz240, spare3, spare2, spare1} + +-- TAG-SUBCARRIERSPACING-STOP +-- TAG-TAG-CONFIG-START + +TAG-Config ::= SEQUENCE { + tag-ToReleaseList SEQUENCE (SIZE (1..maxNrofTAGs)) OF TAG-Id OPTIONAL, -- Need N + tag-ToAddModList SEQUENCE (SIZE (1..maxNrofTAGs)) OF TAG OPTIONAL -- Need N +} + +TAG ::= SEQUENCE { + tag-Id TAG-Id, + timeAlignmentTimer TimeAlignmentTimer, + ... +} + +TAG-Id ::= INTEGER (0..maxNrofTAGs-1) + +TimeAlignmentTimer ::= ENUMERATED {ms500, ms750, ms1280, ms1920, ms2560, ms5120, ms10240, infinity} + +-- TAG-TAG-CONFIG-STOP +-- TAG-TCI-STATE-START + +TCI-State ::= SEQUENCE { + tci-StateId TCI-StateId, + qcl-Type1 QCL-Info, + qcl-Type2 QCL-Info OPTIONAL, -- Need R + ... +} + +QCL-Info ::= SEQUENCE { + cell ServCellIndex OPTIONAL, -- Need R + bwp-Id BWP-Id OPTIONAL, -- Cond CSI-RS-Indicated + referenceSignal CHOICE { + csi-rs NZP-CSI-RS-ResourceId, + ssb SSB-Index + }, + qcl-Type ENUMERATED {typeA, typeB, typeC, typeD}, + ... +} + +-- TAG-TCI-STATE-STOP +-- TAG-TCI-STATEID-START + +TCI-StateId ::= INTEGER (0..maxNrofTCI-States-1) + +-- TAG-TCI-STATEID-STOP +-- TAG-TDD-UL-DL-CONFIGCOMMON-START + +TDD-UL-DL-ConfigCommon ::= SEQUENCE { + referenceSubcarrierSpacing SubcarrierSpacing, + pattern1 TDD-UL-DL-Pattern, + pattern2 TDD-UL-DL-Pattern OPTIONAL, -- Need R + ... +} + +TDD-UL-DL-Pattern ::= SEQUENCE { + dl-UL-TransmissionPeriodicity ENUMERATED {ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms5, ms10}, + nrofDownlinkSlots INTEGER (0..maxNrofSlots), + nrofDownlinkSymbols INTEGER (0..maxNrofSymbols-1), + nrofUplinkSlots INTEGER (0..maxNrofSlots), + nrofUplinkSymbols INTEGER (0..maxNrofSymbols-1), + ..., + [[ + dl-UL-TransmissionPeriodicity-v1530 ENUMERATED {ms3, ms4} OPTIONAL -- Need R + ]] +} + +-- TAG-TDD-UL-DL-CONFIGCOMMON-STOP +-- TAG-TDD-UL-DL-CONFIGDEDICATED-START + +TDD-UL-DL-ConfigDedicated ::= SEQUENCE { + slotSpecificConfigurationsToAddModList SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotConfig OPTIONAL, -- Need N + slotSpecificConfigurationsToReleaseList SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotIndex OPTIONAL, -- Need N + ... +} + +TDD-UL-DL-ConfigDedicated-IAB-MT-r16::= SEQUENCE { + slotSpecificConfigurationsToAddModList-IAB-MT-r16 SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotConfig-IAB-MT-r16 OPTIONAL, -- Need N + slotSpecificConfigurationsToReleaseList-IAB-MT-r16 SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotIndex OPTIONAL, -- Need N + ... +} + +TDD-UL-DL-SlotConfig ::= SEQUENCE { + slotIndex TDD-UL-DL-SlotIndex, + symbols CHOICE { + allDownlink NULL, + allUplink NULL, + explicit SEQUENCE { + nrofDownlinkSymbols INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need S + nrofUplinkSymbols INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need S + } + } +} + +TDD-UL-DL-SlotConfig-IAB-MT-r16::= SEQUENCE { + slotIndex-r16 TDD-UL-DL-SlotIndex, + symbols-IAB-MT-r16 CHOICE { + allDownlink-r16 NULL, + allUplink-r16 NULL, + explicit-r16 SEQUENCE { + nrofDownlinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need FFS + nrofUplinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need FFS + }, + explicit-IAB-MT-r16 SEQUENCE { + nrofDownlinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need FFS + nrofUplinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need FFS + } + } +} + +TDD-UL-DL-SlotIndex ::= INTEGER (0..maxNrofSlots-1) + +-- TAG-TDD-UL-DL-CONFIGDEDICATED-STOP +-- TAG-TRACKINGAREACODE-START + +TrackingAreaCode ::= BIT STRING (SIZE (24)) + +-- TAG-TRACKINGAREACODE-STOP +-- TAG-TRESELECTION-START + +T-Reselection ::= INTEGER (0..7) + +-- TAG-TRESELECTION-STOP +-- TAG-TIMETOTRIGGER-START + +TimeToTrigger ::= ENUMERATED { + ms0, ms40, ms64, ms80, ms100, ms128, ms160, ms256, + ms320, ms480, ms512, ms640, ms1024, ms1280, ms2560, + ms5120} + +-- TAG-TIMETOTRIGGER-STOP +-- TAG-UAC-BARRINGINFOSETINDEX-START + +UAC-BarringInfoSetIndex ::= INTEGER (1..maxBarringInfoSet) + +-- TAG-UAC-BARRINGINFOSETINDEX-STOP +-- TAG-UAC-BARRINGINFOSETLIST-START + +UAC-BarringInfoSetList ::= SEQUENCE (SIZE(1..maxBarringInfoSet)) OF UAC-BarringInfoSet + +UAC-BarringInfoSet ::= SEQUENCE { + uac-BarringFactor ENUMERATED {p00, p05, p10, p15, p20, p25, p30, p40, + p50, p60, p70, p75, p80, p85, p90, p95}, + uac-BarringTime ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512}, + uac-BarringForAccessIdentity BIT STRING (SIZE(7)) +} + +-- TAG-UAC-BARRINGINFOSETLIST-STOP +-- TAG-UAC-BARRINGPERCATLIST-START + +UAC-BarringPerCatList ::= SEQUENCE (SIZE (1..maxAccessCat-1)) OF UAC-BarringPerCat + +UAC-BarringPerCat ::= SEQUENCE { + accessCategory INTEGER (1..maxAccessCat-1), + uac-barringInfoSetIndex UAC-BarringInfoSetIndex +} + +-- TAG-UAC-BARRINGPERCATLIST-STOP +-- TAG-UAC-BARRINGPERPLMN-LIST-START + +UAC-BarringPerPLMN-List ::= SEQUENCE (SIZE (1.. maxPLMN)) OF UAC-BarringPerPLMN + +UAC-BarringPerPLMN ::= SEQUENCE { + plmn-IdentityIndex INTEGER (1..maxPLMN), + uac-ACBarringListType CHOICE{ + uac-ImplicitACBarringList SEQUENCE (SIZE(maxAccessCat-1)) OF UAC-BarringInfoSetIndex, + uac-ExplicitACBarringList UAC-BarringPerCatList + } OPTIONAL -- Need S +} + +-- TAG-UAC-BARRINGPERPLMN-LIST-STOP +-- TAG-UE-TIMERSANDCONSTANTS-START + +UE-TimersAndConstants ::= SEQUENCE { + t300 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + t301 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + t310 ENUMERATED {ms0, ms50, ms100, ms200, ms500, ms1000, ms2000}, + n310 ENUMERATED {n1, n2, n3, n4, n6, n8, n10, n20}, + t311 ENUMERATED {ms1000, ms3000, ms5000, ms10000, ms15000, ms20000, ms30000}, + n311 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10}, + t319 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + ... +} + +-- TAG-UE-TIMERSANDCONSTANTS-STOP +-- TAG-ULDELAYVALUECONFIG-START + +UL-DelayValueConfig-r16 ::= SEQUENCE { + delay-DRBlist SEQUENCE (SIZE(1..maxDRB)) OF DRB-Identity +} + +-- TAG-ULDELAYVALUECONFIG-STOP +-- TAG-UPLINKCANCELLATION-START + +UplinkCancellation-r16 ::= SEQUENCE { + ci-RNTI-r16 RNTI-Value, + dci-PayloadSizeForCI-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16), + ci-ConfigurationPerServingCell-r16 SEQUENCE (SIZE (1..maxNrofServingCells)) OF CI-ConfigurationPerServingCell-r16, + ... +} + +CI-ConfigurationPerServingCell-r16 ::= SEQUENCE { + servingCellId ServCellIndex, + positionInDCI-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16-1), + positionInDCI-ForSUL-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16-1) OPTIONAL, -- Cond SUL-Only + ci-PayloadSize-r16 ENUMERATED {n1, n2, n4, n5, n7, n8, n10, n14, n16, n20, n28, n32, n35, n42, n56, n112}, + timeFrequencyRegion-r16 SEQUENCE { + timeDurationForCI-r16 ENUMERATED {n2, n4, n7, n14} OPTIONAL, -- Cond SymbolPeriodicity + timeGranularityForCI-r16 ENUMERATED {n1, n2, n4, n7, n14, n28}, + frequencyRegionForCI-r16 INTEGER (0..37949), + deltaOffset-r16 INTEGER (0..2), + ... + }, + uplinkCancellationPriority-v1610 ENUMERATED {enabled} OPTIONAL -- Need S +} + +-- TAG-UPLINKCANCELLATION-STOP +-- TAG-UPLINKCONFIGCOMMON-START + +UplinkConfigCommon ::= SEQUENCE { + frequencyInfoUL FrequencyInfoUL OPTIONAL, -- Cond InterFreqHOAndServCellAdd + initialUplinkBWP BWP-UplinkCommon OPTIONAL, -- Cond ServCellAdd + dummy TimeAlignmentTimer +} + +-- TAG-UPLINKCONFIGCOMMON-STOP +-- TAG-UPLINKCONFIGCOMMONSIB-START + +UplinkConfigCommonSIB ::= SEQUENCE { + frequencyInfoUL FrequencyInfoUL-SIB, + initialUplinkBWP BWP-UplinkCommon, + timeAlignmentTimerCommon TimeAlignmentTimer +} + +-- TAG-UPLINKCONFIGCOMMONSIB-STOP +-- TAG-UPLINKTXDIRECTCURRENTLIST-START + +UplinkTxDirectCurrentList ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF UplinkTxDirectCurrentCell + +UplinkTxDirectCurrentCell ::= SEQUENCE { + servCellIndex ServCellIndex, + uplinkDirectCurrentBWP SEQUENCE (SIZE (1..maxNrofBWPs)) OF UplinkTxDirectCurrentBWP, + ..., + [[ + uplinkDirectCurrentBWP-SUL SEQUENCE (SIZE (1..maxNrofBWPs)) OF UplinkTxDirectCurrentBWP OPTIONAL + ]] +} + +UplinkTxDirectCurrentBWP ::= SEQUENCE { + bwp-Id BWP-Id, + shift7dot5kHz BOOLEAN, + txDirectCurrentLocation INTEGER (0..3301) +} + +-- TAG-UPLINKTXDIRECTCURRENTLIST-STOP +-- TAG-ZP-CSI-RS-RESOURCE-START + +ZP-CSI-RS-Resource ::= SEQUENCE { + zp-CSI-RS-ResourceId ZP-CSI-RS-ResourceId, + resourceMapping CSI-RS-ResourceMapping, + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, --Cond PeriodicOrSemiPersistent + ... +} + +ZP-CSI-RS-ResourceId ::= INTEGER (0..maxNrofZP-CSI-RS-Resources-1) + +-- TAG-ZP-CSI-RS-RESOURCE-STOP +-- TAG-ZP-CSI-RS-RESOURCESET-START + +ZP-CSI-RS-ResourceSet ::= SEQUENCE { + zp-CSI-RS-ResourceSetId ZP-CSI-RS-ResourceSetId, + zp-CSI-RS-ResourceIdList SEQUENCE (SIZE(1..maxNrofZP-CSI-RS-ResourcesPerSet)) OF ZP-CSI-RS-ResourceId, + ... +} + +-- TAG-ZP-CSI-RS-RESOURCESET-STOP +-- TAG-ZP-CSI-RS-RESOURCESETID-START + +ZP-CSI-RS-ResourceSetId ::= INTEGER (0..maxNrofZP-CSI-RS-ResourceSets-1) + +-- TAG-ZP-CSI-RS-RESOURCESETID-STOP +-- TAG-ACCESSSTRATUMRELEASE-START + +AccessStratumRelease ::= ENUMERATED { + rel15, rel16, spare6, spare5, spare4, spare3, spare2, spare1, ... } + +-- TAG-ACCESSSTRATUMRELEASE-STOP +-- TAG-BANDCOMBINATIONLIST-START + +BandCombinationList ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination + +BandCombinationList-v1540 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1540 + +BandCombinationList-v1550 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1550 + +BandCombinationList-v1560 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1560 + +BandCombinationList-v1570 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1570 + +BandCombinationList-v1580 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1580 + +BandCombinationList-v1590 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1590 + +BandCombinationList-v1610 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1610 + +BandCombinationList-UplinkTxSwitch-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-UplinkTxSwitch-r16 + +BandCombination ::= SEQUENCE { + bandList SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters, + featureSetCombination FeatureSetCombinationId, + ca-ParametersEUTRA CA-ParametersEUTRA OPTIONAL, + ca-ParametersNR CA-ParametersNR OPTIONAL, + mrdc-Parameters MRDC-Parameters OPTIONAL, + supportedBandwidthCombinationSet BIT STRING (SIZE (1..32)) OPTIONAL, + powerClass-v1530 ENUMERATED {pc2} OPTIONAL +} + +BandCombination-v1540::= SEQUENCE { + bandList-v1540 SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters-v1540, + ca-ParametersNR-v1540 CA-ParametersNR-v1540 OPTIONAL +} + +BandCombination-v1550 ::= SEQUENCE { + ca-ParametersNR-v1550 CA-ParametersNR-v1550 +} + +BandCombination-v1610 ::= SEQUENCE { + bandList-v1610 SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters-v1610 OPTIONAL, + ca-ParametersNR-v1610 CA-ParametersNR-v1610 OPTIONAL, + ca-ParametersNRDC-v1610 CA-ParametersNRDC-v1610 OPTIONAL, + powerClass-v1610 ENUMERATED {pc1dot5} OPTIONAL +} + +BandCombination-v1560::= SEQUENCE { + ne-DC-BC ENUMERATED {supported} OPTIONAL, + ca-ParametersNRDC CA-ParametersNRDC OPTIONAL, + ca-ParametersEUTRA-v1560 CA-ParametersEUTRA-v1560 OPTIONAL, + ca-ParametersNR-v1560 CA-ParametersNR-v1560 OPTIONAL +} + +BandCombination-v1570 ::= SEQUENCE { + ca-ParametersEUTRA-v1570 CA-ParametersEUTRA-v1570 +} + +BandCombination-v1580 ::= SEQUENCE { + mrdc-Parameters-v1580 MRDC-Parameters-v1580 +} + +BandCombination-v1590::= SEQUENCE { + supportedBandwidthCombinationSetIntraENDC BIT STRING (SIZE (1..32)) OPTIONAL, + mrdc-Parameters-v1590 MRDC-Parameters-v1590 +} + +BandCombination-UplinkTxSwitch-r16 ::= SEQUENCE { + bandCombination-r16 BandCombination, + bandCombination-v1540 BandCombination-v1540 OPTIONAL, + bandCombination-v1560 BandCombination-v1560 OPTIONAL, + bandCombination-v1570 BandCombination-v1570 OPTIONAL, + bandCombination-v1580 BandCombination-v1580 OPTIONAL, + bandCombination-v1590 BandCombination-v1590 OPTIONAL, + bandCombination-v1610 BandCombination-v1610 OPTIONAL, + supportedBandPairListNR-r16 SEQUENCE (SIZE (1..maxULTxSwitchingBandPairs)) OF ULTxSwitchingBandPair-r16, + uplinkTxSwitching-OptionSupport-r16 ENUMERATED {switchedUL, dualUL, both} OPTIONAL, + ... +} + +ULTxSwitchingBandPair-r16 ::= SEQUENCE { + bandIndexUL1-r16 INTEGER(1..maxSimultaneousBands), + bandIndexUL2-r16 INTEGER(1..maxSimultaneousBands), + uplinkTxSwitchingPeriod-r16 ENUMERATED {n35us, n140us, n210us}, + uplinkTxSwitching-DL-Interruption-r16 BIT STRING (SIZE(1..maxSimultaneousBands)) OPTIONAL +} + +BandParameters ::= CHOICE { + eutra SEQUENCE { + bandEUTRA FreqBandIndicatorEUTRA, + ca-BandwidthClassDL-EUTRA CA-BandwidthClassEUTRA OPTIONAL, + ca-BandwidthClassUL-EUTRA CA-BandwidthClassEUTRA OPTIONAL + }, + nr SEQUENCE { + bandNR FreqBandIndicatorNR, + ca-BandwidthClassDL-NR CA-BandwidthClassNR OPTIONAL, + ca-BandwidthClassUL-NR CA-BandwidthClassNR OPTIONAL + } +} + +BandParameters-v1540 ::= SEQUENCE { + srs-CarrierSwitch CHOICE { + nr SEQUENCE { + srs-SwitchingTimesListNR SEQUENCE (SIZE (1..maxSimultaneousBands)) OF SRS-SwitchingTimeNR + }, + eutra SEQUENCE { + srs-SwitchingTimesListEUTRA SEQUENCE (SIZE (1..maxSimultaneousBands)) OF SRS-SwitchingTimeEUTRA + } + } OPTIONAL, + srs-TxSwitch SEQUENCE { + supportedSRS-TxPortSwitch ENUMERATED {t1r2, t1r4, t2r4, t1r4-t2r4, t1r1, t2r2, t4r4, notSupported}, + txSwitchImpactToRx INTEGER (1..32) OPTIONAL, + txSwitchWithAnotherBand INTEGER (1..32) OPTIONAL + } OPTIONAL +} + +BandParameters-v1610 ::= SEQUENCE { + srs-TxSwitch-v1610 SEQUENCE { + supportedSRS-TxPortSwitch-v1610 ENUMERATED {t1r1-t1r2, t1r1-t1r2-t1r4, t1r1-t1r2-t2r2-t2r4, t1r1-t1r2-t2r2-t1r4-t2r4, + t1r1-t2r2, t1r1-t2r2-t4r4} + } OPTIONAL, + intraFreqDAPS-Parameters-r16 SEQUENCE { + intraFreqDiffSCS-DAPS-r16 ENUMERATED {supported} OPTIONAL, + intraFreqDAPS-r16 ENUMERATED {supported} OPTIONAL, + intraFreqAsyncDAPS-r16 ENUMERATED {supported} OPTIONAL, + intraFreqMultiUL-TransmissionDAPS-r16 ENUMERATED {supported} OPTIONAL, + intraFreqTwoTAGs-DAPS-r16 ENUMERATED {supported} OPTIONAL, + intraFreqSemiStaticPowerSharingDAPS-Mode1-r16 ENUMERATED {supported} OPTIONAL, + intraFreqSemiStaticPowerSharingDAPS-Mode2-r16 ENUMERATED {supported} OPTIONAL, + intraFreqDynamicPowersharingDAPS-r16 ENUMERATED {short, long} OPTIONAL + } OPTIONAL +} + +-- TAG-BANDCOMBINATIONLIST-STOP +-- TAG-BANDCOMBINATIONLISTSIDELINK-START + +BandCombinationListSidelink-r16 ::= SEQUENCE { + supportedBandCombinationListSidelink-r16 SupportedBandCombinationListSidelink-r16 OPTIONAL, + supportedBandCombinationListSidelinkEUTRA-r16 SupportedBandCombinationListSidelinkEUTRA-r16 OPTIONAL, + supportedBandCombinationListSidelinkEUTRA-NR-r16 SupportedBandCombinationListSidelinkEUTRA-NR-r16 OPTIONAL, + ... +} + +SupportedBandCombinationListSidelink-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationParametersSidelink-r16 + +BandCombinationParametersSidelink-r16 ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParametersSidelink-r16 + +BandParametersSidelink-r16 ::= SEQUENCE { + freqBandSidelink-r16 FreqBandIndicatorNR +} + +SupportedBandCombinationListSidelinkEUTRA-r16 ::= SEQUENCE { + bandCombinationListEUTRA1-r16 OCTET STRING OPTIONAL, + bandCombinationListEUTRA2-r16 OCTET STRING OPTIONAL +} + +SupportedBandCombinationListSidelinkEUTRA-NR-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationParametersSidelinkEUTRA-NR-r16 + +BandCombinationParametersSidelinkEUTRA-NR-r16 ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParametersSidelinkEUTRA-NR-r16 + +BandParametersSidelinkEUTRA-NR-r16 ::= CHOICE { + eutra SEQUENCE { + bandParametersSidelinkEUTRA1-r16 OCTET STRING OPTIONAL, + bandParametersSidelinkEUTRA2-r16 OCTET STRING OPTIONAL + }, + nr SEQUENCE { + bandParametersSidelinkNR-r16 BandParametersSidelink-r16 } + } + +-- TAG-BANDCOMBINATIONLISTSIDELINK-STOP +-- TAG-CA-BANDWIDTHCLASSEUTRA-START + +CA-BandwidthClassEUTRA ::= ENUMERATED {a, b, c, d, e, f, ...} + +-- TAG-CA-BANDWIDTHCLASSEUTRA-STOP +-- TAG-CA-BANDWIDTHCLASSNR-START + +CA-BandwidthClassNR ::= ENUMERATED {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, ...} + +-- TAG-CA-BANDWIDTHCLASSNR-STOP +-- TAG-CA-PARAMETERSEUTRA-START + +CA-ParametersEUTRA ::= SEQUENCE { + multipleTimingAdvance ENUMERATED {supported} OPTIONAL, + simultaneousRx-Tx ENUMERATED {supported} OPTIONAL, + supportedNAICS-2CRS-AP BIT STRING (SIZE (1..8)) OPTIONAL, + additionalRx-Tx-PerformanceReq ENUMERATED {supported} OPTIONAL, + ue-CA-PowerClass-N ENUMERATED {class2} OPTIONAL, + supportedBandwidthCombinationSetEUTRA-v1530 BIT STRING (SIZE (1..32)) OPTIONAL, + ... +} + +CA-ParametersEUTRA-v1560 ::= SEQUENCE { + fd-MIMO-TotalWeightedLayers INTEGER (2..128) OPTIONAL +} + +CA-ParametersEUTRA-v1570 ::= SEQUENCE { + dl-1024QAM-TotalWeightedLayers INTEGER (0..10) OPTIONAL +} + +-- TAG-CA-PARAMETERSEUTRA-STOP +-- TAG-CA-PARAMETERSNR-START + +CA-ParametersNR ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL, + parallelTxSRS-PUCCH-PUSCH ENUMERATED {supported} OPTIONAL, + parallelTxPRACH-SRS-PUCCH-PUSCH ENUMERATED {supported} OPTIONAL, + simultaneousRxTxInterBandCA ENUMERATED {supported} OPTIONAL, + simultaneousRxTxSUL ENUMERATED {supported} OPTIONAL, + diffNumerologyAcrossPUCCH-Group ENUMERATED {supported} OPTIONAL, + diffNumerologyWithinPUCCH-GroupSmallerSCS ENUMERATED {supported} OPTIONAL, + supportedNumberTAG ENUMERATED {n2, n3, n4} OPTIONAL, + ... +} + +CA-ParametersNR-v1540 ::= SEQUENCE { + simultaneousSRS-AssocCSI-RS-AllCC INTEGER (5..32) OPTIONAL, + csi-RS-IM-ReceptionForFeedbackPerBandComb SEQUENCE { + maxNumberSimultaneousNZP-CSI-RS-ActBWP-AllCC INTEGER (1..64) OPTIONAL, + totalNumberPortsSimultaneousNZP-CSI-RS-ActBWP-AllCC INTEGER (2..256) OPTIONAL + } OPTIONAL, + simultaneousCSI-ReportsAllCC INTEGER (5..32) OPTIONAL, + dualPA-Architecture ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1550 ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1560 ::= SEQUENCE { + diffNumerologyWithinPUCCH-GroupLargerSCS ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1610 ::= SEQUENCE { + -- R1 9-3: Parallel MsgA and SRS/PUCCH/PUSCH transmissions across CCs in inter-band CA + parallelTxMsgA-SRS-PUCCH-PUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 9-4: MsgA operation in a band combination including SUL + msgA-SUL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9c: Joint search space group switching across multiple cells + jointSearchSpaceGroupSwitchingAcrossCells-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-5: Half-duplex UE behaviour in TDD CA for same SCS + half-DuplexTDD-CA-SameSCS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-4: SCell dormancy within active time + scellDormancyWithinActiveTime-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-4a: SCell dormancy outside active time + scellDormancyOutsideActiveTime-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-6: Cross-carrier A-CSI RS triggering with different SCS + crossCarrierA-CSI-trigDiffSCS-r16 ENUMERATED {higherA-CSI-SCS,lowerA-CSI-SCS,both} OPTIONAL, + -- R1 18-6a: Default QCL assumption for cross-carrier A-CSI-RS triggering + defaultQCL-CrossCarrierA-CSI-Trig-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-7: CA with non-aligned frame boundaries for inter-band CA + interCA-NonAlignedFrame-r16 ENUMERATED {supported} OPTIONAL, + simul-SRS-Trans-InterBandCA-r16 INTEGER (1..2) OPTIONAL, + daps-Parameters-r16 SEQUENCE { + asyncDAPS-r16 ENUMERATED {supported} OPTIONAL, + interFreqDAPS-r16 ENUMERATED {supported} OPTIONAL, + interFreqDiffSCS-DAPS-r16 ENUMERATED {supported} OPTIONAL, + multiUL-TransmissionDAPS-r16 ENUMERATED {supported} OPTIONAL, + semiStaticPowerSharingDAPS-Mode1-r16 ENUMERATED {supported} OPTIONAL, + semiStaticPowerSharingDAPS-Mode2-r16 ENUMERATED {supported} OPTIONAL, + dynamicPowersharingDAPS-r16 ENUMERATED {short, long} OPTIONAL, + ul-TransCancellationDAPS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + codebookParametersPerBC-r16 CodebookParameters-v1610 OPTIONAL +} + +-- TAG-CA-PARAMETERSNR-STOP +-- TAG-CA-PARAMETERS-NRDC-START + +CA-ParametersNRDC ::= SEQUENCE { + ca-ParametersNR-ForDC CA-ParametersNR OPTIONAL, + ca-ParametersNR-ForDC-v1540 CA-ParametersNR-v1540 OPTIONAL, + ca-ParametersNR-ForDC-v1550 CA-ParametersNR-v1550 OPTIONAL, + ca-ParametersNR-ForDC-v1560 CA-ParametersNR-v1560 OPTIONAL, + featureSetCombinationDC FeatureSetCombinationId OPTIONAL +} + +CA-ParametersNRDC-v1610 ::= SEQUENCE { + -- R1 18-1: Semi-static power sharing mode1 between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-PwrSharingMode1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-1a: Semi-static power sharing mode 2 between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-PwrSharingMode2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-1b: Dynamic power sharing between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-DynamicPwrSharing-r16 ENUMERATED {short, long} OPTIONAL +} + +-- TAG-CA-PARAMETERS-NRDC-STOP +-- TAG-CARRIERAGGREGATIONVARIANT-START + +CarrierAggregationVariant ::= SEQUENCE { + fr1fdd-FR1TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR2TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL, + fr1tdd-FR2TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1tdd-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL +} + +-- TAG-CARRIERAGGREGATIONVARIANT-STOP +-- TAG-CODEBOOKPARAMETERS-START + +CodebookParameters ::= SEQUENCE { + type1 SEQUENCE { + singlePanel SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + modes ENUMERATED {mode1, mode1andMode2}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) + }, + multiPanel SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + modes ENUMERATED {mode1, mode2, both}, + nrofPanels ENUMERATED {n2, n4}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) + } OPTIONAL + }, + type2 SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + amplitudeSubsetRestriction ENUMERATED {supported} OPTIONAL + } OPTIONAL, + type2-PortSelection SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband} + } OPTIONAL +} + +CodebookParameters-v1610 ::= SEQUENCE { + supportedCSI-RS-ResourceListAlt-r16 SEQUENCE { + type1-SinglePanel-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type1-MultiPanel-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type2-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type2-PortSelection-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL + } OPTIONAL +} + +CodebookVariantsList-r16 ::= SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesAlt-r16)) OF SupportedCSI-RS-Resource + +SupportedCSI-RS-Resource ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p2, p4, p8, p12, p16, p24, p32}, + maxNumberResourcesPerBand INTEGER (1..64), + totalNumberTxPortsPerBand INTEGER (2..256) +} + +-- TAG-CODEBOOKPARAMETERS-STOP +-- TAG-FEATURESETCOMBINATION-START + +FeatureSetCombination ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF FeatureSetsPerBand + +FeatureSetsPerBand ::= SEQUENCE (SIZE (1..maxFeatureSetsPerBand)) OF FeatureSet + +FeatureSet ::= CHOICE { + eutra SEQUENCE { + downlinkSetEUTRA FeatureSetEUTRA-DownlinkId, + uplinkSetEUTRA FeatureSetEUTRA-UplinkId + }, + nr SEQUENCE { + downlinkSetNR FeatureSetDownlinkId, + uplinkSetNR FeatureSetUplinkId + } +} + +-- TAG-FEATURESETCOMBINATION-STOP +-- TAG-FEATURESETCOMBINATIONID-START + +FeatureSetCombinationId ::= INTEGER (0.. maxFeatureSetCombinations) + +-- TAG-FEATURESETCOMBINATIONID-STOP +-- TAG-FEATURESETDOWNLINK-START + +FeatureSetDownlink ::= SEQUENCE { + featureSetListPerDownlinkCC SEQUENCE (SIZE (1..maxNrofServingCells)) OF FeatureSetDownlinkPerCC-Id, + + intraBandFreqSeparationDL FreqSeparationClass OPTIONAL, + scalingFactor ENUMERATED {f0p4, f0p75, f0p8} OPTIONAL, + crossCarrierScheduling-OtherSCS ENUMERATED {supported} OPTIONAL, + scellWithoutSSB ENUMERATED {supported} OPTIONAL, + csi-RS-MeasSCellWithoutSSB ENUMERATED {supported} OPTIONAL, + dummy1 ENUMERATED {supported} OPTIONAL, + type1-3-CSS ENUMERATED {supported} OPTIONAL, + pdcch-MonitoringAnyOccasions ENUMERATED {withoutDCI-Gap, withDCI-Gap} OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + ue-SpecificUL-DL-Assignment ENUMERATED {supported} OPTIONAL, + searchSpaceSharingCA-DL ENUMERATED {supported} OPTIONAL, + timeDurationForQCL SEQUENCE { + scs-60kHz ENUMERATED {s7, s14, s28} OPTIONAL, + scs-120kHz ENUMERATED {s14, s28} OPTIONAL + } OPTIONAL, + pdsch-ProcessingType1-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + dummy3 DummyA OPTIONAL, + dummy4 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyB OPTIONAL, + dummy5 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyC OPTIONAL, + dummy6 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyD OPTIONAL, + dummy7 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyE OPTIONAL +} + +FeatureSetDownlink-v1540 ::= SEQUENCE { + oneFL-DMRS-TwoAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + additionalDMRS-DL-Alt ENUMERATED {supported} OPTIONAL, + twoFL-DMRS-TwoAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-ThreeAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + pdcch-MonitoringAnyOccasionsWithSpanGap SEQUENCE { + scs-15kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-30kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-60kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-120kHz ENUMERATED {set1, set2, set3} OPTIONAL + } OPTIONAL, + pdsch-SeparationWithGap ENUMERATED {supported} OPTIONAL, + pdsch-ProcessingType2 SEQUENCE { + scs-15kHz ProcessingParameters OPTIONAL, + scs-30kHz ProcessingParameters OPTIONAL, + scs-60kHz ProcessingParameters OPTIONAL + } OPTIONAL, + pdsch-ProcessingType2-Limited SEQUENCE { + differentTB-PerSlot-SCS-30kHz ENUMERATED {upto1, upto2, upto4, upto7} + } OPTIONAL, + dl-MCS-TableAlt-DynamicIndication ENUMERATED {supported} OPTIONAL +} + +FeatureSetDownlink-v15a0 ::= SEQUENCE { + supportedSRS-Resources SRS-Resources OPTIONAL +} + +FeatureSetDownlink-v1610 ::= SEQUENCE { + -- R1 22-4e/4f/4g/4h: CBG based reception for DL with unicast PDSCH(s) per slot per CC with UE processing time Capability 1 + cbgPDSCH-ProcessingType1-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {one-pdsch, upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {one-pdsch, upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {one-pdsch, upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {one-pdsch, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + + -- R1 22-3e/3f/3g/3h: CBG based reception for DL with unicast PDSCH(s) per slot per CC with UE processing time Capability 2 + cbgPDSCH-ProcessingType2-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {one-pdsch, upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {one-pdsch, upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {one-pdsch, upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {one-pdsch, upto2, upto4, upto7} OPTIONAL + } OPTIONAL +} + +DummyA ::= SEQUENCE { + maxNumberNZP-CSI-RS-PerCC INTEGER (1..32), + maxNumberPortsAcrossNZP-CSI-RS-PerCC ENUMERATED {p2, p4, p8, p12, p16, p24, p32, p40, p48, p56, p64, p72, p80, + p88, p96, p104, p112, p120, p128, p136, p144, p152, p160, p168, + p176, p184, p192, p200, p208, p216, p224, p232, p240, p248, p256}, + maxNumberCS-IM-PerCC ENUMERATED {n1, n2, n4, n8, n16, n32}, + maxNumberSimultaneousCSI-RS-ActBWP-AllCC ENUMERATED {n5, n6, n7, n8, n9, n10, n12, n14, n16, n18, n20, n22, n24, n26, + n28, n30, n32, n34, n36, n38, n40, n42, n44, n46, n48, n50, n52, + n54, n56, n58, n60, n62, n64}, + totalNumberPortsSimultaneousCSI-RS-ActBWP-AllCC ENUMERATED {p8, p12, p16, p24, p32, p40, p48, p56, p64, p72, p80, + p88, p96, p104, p112, p120, p128, p136, p144, p152, p160, p168, + p176, p184, p192, p200, p208, p216, p224, p232, p240, p248, p256} +} + +DummyB ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p2, p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + supportedCodebookMode ENUMERATED {mode1, mode1AndMode2}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyC ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p8, p16, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + supportedCodebookMode ENUMERATED {mode1, mode2, both}, + supportedNumberPanels ENUMERATED {n2, n4}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyD ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + amplitudeSubsetRestriction ENUMERATED {supported} OPTIONAL, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyE ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +-- TAG-FEATURESETDOWNLINK-STOP +-- TAG-FEATURESETDOWNLINKID-START + +FeatureSetDownlinkId ::= INTEGER (0..maxDownlinkFeatureSets) + +-- TAG-FEATURESETDOWNLINKID-STOP +-- TAG-FEATURESETDOWNLINKPERCC-START + +FeatureSetDownlinkPerCC ::= SEQUENCE { + supportedSubcarrierSpacingDL SubcarrierSpacing, + supportedBandwidthDL SupportedBandwidth, + channelBW-90mhz ENUMERATED {supported} OPTIONAL, + maxNumberMIMO-LayersPDSCH MIMO-LayersDL OPTIONAL, + supportedModulationOrderDL ModulationOrder OPTIONAL +} + +-- TAG-FEATURESETDOWNLINKPERCC-STOP +-- TAG-FEATURESETDOWNLINKPERCC-ID-START + +FeatureSetDownlinkPerCC-Id ::= INTEGER (1..maxPerCC-FeatureSets) + +-- TAG-FEATURESETDOWNLINKPERCC-ID-STOP +-- TAG-FEATURESETEUTRADOWNLINKID-START + +FeatureSetEUTRA-DownlinkId ::= INTEGER (0..maxEUTRA-DL-FeatureSets) + +-- TAG-FEATURESETEUTRADOWNLINKID-STOP +-- TAG-FEATURESETEUTRAUPLINKID-START + +FeatureSetEUTRA-UplinkId ::= INTEGER (0..maxEUTRA-UL-FeatureSets) + +-- TAG-FEATURESETEUTRAUPLINKID-STOP +-- TAG-FEATURESETS-START + +FeatureSets ::= SEQUENCE { + featureSetsDownlink SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink OPTIONAL, + featureSetsDownlinkPerCC SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetDownlinkPerCC OPTIONAL, + featureSetsUplink SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink OPTIONAL, + featureSetsUplinkPerCC SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetUplinkPerCC OPTIONAL, + ..., + [[ + featureSetsDownlink-v1540 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v1540 OPTIONAL, + featureSetsUplink-v1540 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1540 OPTIONAL, + featureSetsUplinkPerCC-v1540 SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetUplinkPerCC-v1540 OPTIONAL + ]], + [[ + featureSetsDownlink-v15a0 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v15a0 OPTIONAL + ]], + [[ + featureSetsDownlink-v1610 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v1610 OPTIONAL, + featureSetsUplink-v1610 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1610 OPTIONAL + ]] +} + +-- TAG-FEATURESETS-STOP +-- TAG-FEATURESETUPLINK-START + +FeatureSetUplink ::= SEQUENCE { + featureSetListPerUplinkCC SEQUENCE (SIZE (1.. maxNrofServingCells)) OF FeatureSetUplinkPerCC-Id, + scalingFactor ENUMERATED {f0p4, f0p75, f0p8} OPTIONAL, + crossCarrierScheduling-OtherSCS ENUMERATED {supported} OPTIONAL, + intraBandFreqSeparationUL FreqSeparationClass OPTIONAL, + searchSpaceSharingCA-UL ENUMERATED {supported} OPTIONAL, + dummy1 DummyI OPTIONAL, + supportedSRS-Resources SRS-Resources OPTIONAL, + twoPUCCH-Group ENUMERATED {supported} OPTIONAL, + dynamicSwitchSUL ENUMERATED {supported} OPTIONAL, + simultaneousTxSUL-NonSUL ENUMERATED {supported} OPTIONAL, + pusch-ProcessingType1-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + dummy2 DummyF OPTIONAL +} + +FeatureSetUplink-v1540 ::= SEQUENCE { + zeroSlotOffsetAperiodicSRS ENUMERATED {supported} OPTIONAL, + pa-PhaseDiscontinuityImpacts ENUMERATED {supported} OPTIONAL, + pusch-SeparationWithGap ENUMERATED {supported} OPTIONAL, + pusch-ProcessingType2 SEQUENCE { + scs-15kHz ProcessingParameters OPTIONAL, + scs-30kHz ProcessingParameters OPTIONAL, + scs-60kHz ProcessingParameters OPTIONAL + } OPTIONAL, + ul-MCS-TableAlt-DynamicIndication ENUMERATED {supported} OPTIONAL +} + +FeatureSetUplink-v1610 ::= SEQUENCE { + -- R1 11-5: PUsCH repetition Type B + pusch-RepetitionTypeB-r16 SEQUENCE { + maxNumberPUSCH-Tx-r16 ENUMERATED {n2, n3, n4, n7, n8, n12}, + hoppingScheme-r16 ENUMERATED {interSlotHopping, interRepetitionHopping, both} + } OPTIONAL, + -- R1 11-7: UL cancelation scheme for self-carrier + ul-CancellationSelfCarrier-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-7a: UL cancelation scheme for cross-carrier + ul-CancellationCrossCarrier-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-5c: The maximum number of SRS resources in one SRS resource set with usage set to 'codebook' for Mode 2 + ul-FullPwrMode2-MaxSRS-ResInSet ENUMERATED {n1, n2, n4} OPTIONAL, + + -- R1 22-4a/4b/4c/4d: CBG based transmission for UL with unicast PUSCH(s) per slot per CC with UE processing time Capability 1 + cbgPUSCH-ProcessingType1-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + + -- R1 22-3a/3b/3c/3d: CBG based transmission for UL with unicast PUSCH(s) per slot per CC with UE processing time Capability 2 + cbgPUSCH-ProcessingType2-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + supportedSRS-PosResources-r16 SRS-AllPosResources-r16 OPTIONAL +} + +SRS-AllPosResources-r16 ::= SEQUENCE { + srs-PosResources-r16 SRS-PosResources-r16, + srs-PosResourceAP-r16 SRS-PosResourceAP-r16 OPTIONAL, + srs-PosResourceSP-r16 SRS-PosResourceSP-r16 OPTIONAL +} + +SRS-PosResources-r16 ::= SEQUENCE { + maxNumberSRS-PosResourceSetPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n12, n16}, + maxNumberSRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberSRS-ResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14}, + maxNumberPeriodicSRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberPeriodicSRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-PosResourceAP-r16 ::= SEQUENCE { + maxNumberAP-SRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberAP-SRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-PosResourceSP-r16 ::= SEQUENCE { + maxNumberSP-SRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberSP-SRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-Resources ::= SEQUENCE { + maxNumberAperiodicSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberAperiodicSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberPeriodicSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberPeriodicSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberSemiPersistentSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberSemiPersistentSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberSRS-Ports-PerResource ENUMERATED {n1, n2, n4} +} + +DummyF ::= SEQUENCE { + maxNumberPeriodicCSI-ReportPerBWP INTEGER (1..4), + maxNumberAperiodicCSI-ReportPerBWP INTEGER (1..4), + maxNumberSemiPersistentCSI-ReportPerBWP INTEGER (0..4), + simultaneousCSI-ReportsAllCC INTEGER (5..32) +} + +-- TAG-FEATURESETUPLINK-STOP +-- TAG-FEATURESETUPLINKID-START + +FeatureSetUplinkId ::= INTEGER (0..maxUplinkFeatureSets) + +-- TAG-FEATURESETUPLINKID-STOP +-- TAG-FEATURESETUPLINKPERCC-START + +FeatureSetUplinkPerCC ::= SEQUENCE { + supportedSubcarrierSpacingUL SubcarrierSpacing, + supportedBandwidthUL SupportedBandwidth, + channelBW-90mhz ENUMERATED {supported} OPTIONAL, + mimo-CB-PUSCH SEQUENCE { + maxNumberMIMO-LayersCB-PUSCH MIMO-LayersUL OPTIONAL, + maxNumberSRS-ResourcePerSet INTEGER (1..2) + } OPTIONAL, + maxNumberMIMO-LayersNonCB-PUSCH MIMO-LayersUL OPTIONAL, + supportedModulationOrderUL ModulationOrder OPTIONAL +} +FeatureSetUplinkPerCC-v1540 ::= SEQUENCE { + mimo-NonCB-PUSCH SEQUENCE { + maxNumberSRS-ResourcePerSet INTEGER (1..4), + maxNumberSimultaneousSRS-ResourceTx INTEGER (1..4) + } OPTIONAL +} + +-- TAG-FEATURESETUPLINKPERCC-STOP +-- TAG-FEATURESETUPLINKPERCC-ID-START + +FeatureSetUplinkPerCC-Id ::= INTEGER (1..maxPerCC-FeatureSets) + +-- TAG-FEATURESETUPLINKPERCC-ID-STOP +-- TAG-FREQBANDINDICATOREUTRA-START + +FreqBandIndicatorEUTRA ::= INTEGER (1..maxBandsEUTRA) + +-- TAG-FREQBANDINDICATOREUTRA-STOP +-- TAG-FREQBANDLIST-START + +FreqBandList ::= SEQUENCE (SIZE (1..maxBandsMRDC)) OF FreqBandInformation + +FreqBandInformation ::= CHOICE { + bandInformationEUTRA FreqBandInformationEUTRA, + bandInformationNR FreqBandInformationNR +} + +FreqBandInformationEUTRA ::= SEQUENCE { + bandEUTRA FreqBandIndicatorEUTRA, + ca-BandwidthClassDL-EUTRA CA-BandwidthClassEUTRA OPTIONAL, -- Need N + ca-BandwidthClassUL-EUTRA CA-BandwidthClassEUTRA OPTIONAL -- Need N +} + +FreqBandInformationNR ::= SEQUENCE { + bandNR FreqBandIndicatorNR, + maxBandwidthRequestedDL AggregatedBandwidth OPTIONAL, -- Need N + maxBandwidthRequestedUL AggregatedBandwidth OPTIONAL, -- Need N + maxCarriersRequestedDL INTEGER (1..maxNrofServingCells) OPTIONAL, -- Need N + maxCarriersRequestedUL INTEGER (1..maxNrofServingCells) OPTIONAL -- Need N +} + +AggregatedBandwidth ::= ENUMERATED {mhz50, mhz100, mhz150, mhz200, mhz250, mhz300, mhz350, + mhz400, mhz450, mhz500, mhz550, mhz600, mhz650, mhz700, mhz750, mhz800} + +-- TAG-FREQBANDLIST-STOP +-- TAG-FREQSEPARATIONCLASS-START + +FreqSeparationClass ::= ENUMERATED {c1, c2, c3, ...} + +-- TAG-FREQSEPARATIONCLASS-STOP +-- TAG-HIGHSPEEDPARAMETERS-START + +HighSpeedParameters-r16 ::= SEQUENCE { + measurementEnhancement-r16 ENUMERATED {supported} OPTIONAL, + demodulationEnhancement-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-HIGHSPEEDPARAMETERS-STOP +-- TAG-IMS-PARAMETERS-START + +IMS-Parameters ::= SEQUENCE { + ims-ParametersCommon IMS-ParametersCommon OPTIONAL, + ims-ParametersFRX-Diff IMS-ParametersFRX-Diff OPTIONAL, + ... +} + +IMS-ParametersCommon ::= SEQUENCE { + voiceOverEUTRA-5GC ENUMERATED {supported} OPTIONAL, + ..., + [[ + voiceOverSCG-BearerEUTRA-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + voiceFallbackIndicationEPS-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +IMS-ParametersFRX-Diff ::= SEQUENCE { + voiceOverNR ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-IMS-PARAMETERS-STOP +-- TAG-INTERRAT-PARAMETERS-START + +InterRAT-Parameters ::= SEQUENCE { + eutra EUTRA-Parameters OPTIONAL, + ..., + [[ + utra-FDD-r16 UTRA-FDD-Parameters-r16 OPTIONAL + ]] + +} + +EUTRA-Parameters ::= SEQUENCE { + supportedBandListEUTRA SEQUENCE (SIZE (1..maxBandsEUTRA)) OF FreqBandIndicatorEUTRA, + eutra-ParametersCommon EUTRA-ParametersCommon OPTIONAL, + eutra-ParametersXDD-Diff EUTRA-ParametersXDD-Diff OPTIONAL, + ... +} + +EUTRA-ParametersCommon ::= SEQUENCE { + mfbi-EUTRA ENUMERATED {supported} OPTIONAL, + modifiedMPR-BehaviorEUTRA BIT STRING (SIZE (32)) OPTIONAL, + multiNS-Pmax-EUTRA ENUMERATED {supported} OPTIONAL, + rs-SINR-MeasEUTRA ENUMERATED {supported} OPTIONAL, + ..., + [[ + ne-DC ENUMERATED {supported} OPTIONAL + ]], + [[ + nr-HO-ToEN-DC-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +EUTRA-ParametersXDD-Diff ::= SEQUENCE { + rsrqMeasWidebandEUTRA ENUMERATED {supported} OPTIONAL, + ... +} + +UTRA-FDD-Parameters-r16 ::= SEQUENCE { + supportedBandListUTRA-FDD-r16 SEQUENCE (SIZE (1..maxBandsUTRA-FDD-r16)) OF SupportedBandUTRA-FDD-r16, + ... +} + +SupportedBandUTRA-FDD-r16 ::= ENUMERATED { + bandI, bandII, bandIII, bandIV, bandV, bandVI, + bandVII, bandVIII, bandIX, bandX, bandXI, + bandXII, bandXIII, bandXIV, bandXV, bandXVI, + bandXVII, bandXVIII, bandXIX, bandXX, + bandXXI, bandXXII, bandXXIII, bandXXIV, + bandXXV, bandXXVI, bandXXVII, bandXXVIII, + bandXXIX, bandXXX, bandXXXI, bandXXXII} + +-- TAG-INTERRAT-PARAMETERS-STOP +-- TAG-MAC-PARAMETERS-START + +MAC-Parameters ::= SEQUENCE { + mac-ParametersCommon MAC-ParametersCommon OPTIONAL, + mac-ParametersXDD-Diff MAC-ParametersXDD-Diff OPTIONAL +} + +MAC-Parameters-v1610 ::= SEQUENCE { + mac-ParametersFRX-Diff-r16 MAC-ParametersFRX-Diff-r16 OPTIONAL +} + +MAC-ParametersCommon ::= SEQUENCE { + lcp-Restriction ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + lch-ToSCellRestriction ENUMERATED {supported} OPTIONAL, + ..., + [[ + recommendedBitRate ENUMERATED {supported} OPTIONAL, + recommendedBitRateQuery ENUMERATED {supported} OPTIONAL + ]], + [[ + recommendedBitRateMultiplier-r16 ENUMERATED {supported} OPTIONAL, + secondaryDRX-Group ENUMERATED {supported} OPTIONAL, + preEmptiveBSR-r16 ENUMERATED {supported} OPTIONAL, + autonomousTransmission-r16 ENUMERATED {supported} OPTIONAL, + lch-PriorityBasedPrioritization-r16 ENUMERATED {supported} OPTIONAL, + lch-ToConfiguredGrantMapping-r16 ENUMERATED {supported} OPTIONAL, + lch-ToGrantPriorityRestriction-r16 ENUMERATED {supported} OPTIONAL, + singlePHR-P-r16 ENUMERATED {supported} OPTIONAL, + ul-LBT-FailureDetectionRecovery-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +MAC-ParametersFRX-Diff-r16 ::= SEQUENCE { + directMCG-SCellActivation-r16 ENUMERATED {supported} OPTIONAL, + directMCG-SCellActivationResume-r16 ENUMERATED {supported} OPTIONAL, + directSCG-SCellActivation-r16 ENUMERATED {supported} OPTIONAL, + directSCG-SCellActivationResume-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-1: DRX Adaptation + drx-Adaptation-r16 SEQUENCE { + licensedBand-r16 MinTimeGap-r16 OPTIONAL, + unlicensedBand-r16 MinTimeGap-r16 OPTIONAL + } OPTIONAL, + ... +} + +MAC-ParametersXDD-Diff ::= SEQUENCE { + skipUplinkTxDynamic ENUMERATED {supported} OPTIONAL, + logicalChannelSR-DelayTimer ENUMERATED {supported} OPTIONAL, + longDRX-Cycle ENUMERATED {supported} OPTIONAL, + shortDRX-Cycle ENUMERATED {supported} OPTIONAL, + multipleSR-Configurations ENUMERATED {supported} OPTIONAL, + multipleConfiguredGrants ENUMERATED {supported} OPTIONAL, + ... +} + +MinTimeGap-r16 ::= SEQUENCE { + scs-15kHz-r16 ENUMERATED {sl1, sl3} OPTIONAL, + scs-30kHz-r16 ENUMERATED {sl1, sl6} OPTIONAL, + scs-60kHz-r16 ENUMERATED {sl1, sl12} OPTIONAL, + scs-120kHz-r16 ENUMERATED {sl2, sl24} OPTIONAL +} + +-- TAG-MAC-PARAMETERS-STOP +-- TAG-MEASANDMOBPARAMETERS-START + +MeasAndMobParameters ::= SEQUENCE { + measAndMobParametersCommon MeasAndMobParametersCommon OPTIONAL, + measAndMobParametersXDD-Diff MeasAndMobParametersXDD-Diff OPTIONAL, + measAndMobParametersFRX-Diff MeasAndMobParametersFRX-Diff OPTIONAL +} + +MeasAndMobParametersCommon ::= SEQUENCE { + supportedGapPattern BIT STRING (SIZE (22)) OPTIONAL, + ssb-RLM ENUMERATED {supported} OPTIONAL, + ssb-AndCSI-RS-RLM ENUMERATED {supported} OPTIONAL, + ..., + [[ + eventB-MeasAndReport ENUMERATED {supported} OPTIONAL, + handoverFDD-TDD ENUMERATED {supported} OPTIONAL, + eutra-CGI-Reporting ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting ENUMERATED {supported} OPTIONAL + ]], + [[ + independentGapConfig ENUMERATED {supported} OPTIONAL, + periodicEUTRA-MeasAndReport ENUMERATED {supported} OPTIONAL, + handoverFR1-FR2 ENUMERATED {supported} OPTIONAL, + maxNumberCSI-RS-RRM-RS-SINR ENUMERATED {n4, n8, n16, n32, n64, n96} OPTIONAL + ]], + [[ + nr-CGI-Reporting-ENDC ENUMERATED {supported} OPTIONAL + ]], + [[ + eutra-CGI-Reporting-NEDC ENUMERATED {supported} OPTIONAL, + eutra-CGI-Reporting-NRDC ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NEDC ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NRDC ENUMERATED {supported} OPTIONAL + ]], + [[ + reportAddNeighMeasForPeriodic-r16 ENUMERATED {supported} OPTIONAL, + condHandoverParametersCommon-r16 SEQUENCE { + condHandoverFDD-TDD-r16 ENUMERATED {supported} OPTIONAL, + condHandoverFR1-FR2-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + nr-NeedForGap-Reporting-r16 ENUMERATED {supported} OPTIONAL, + supportedGapPattern-NRonly-r16 BIT STRING (SIZE (10)) OPTIONAL, + supportedGapPattern-NRonly-NEDC-r16 ENUMERATED {supported} OPTIONAL, + maxNumberCLI-RSSI-r16 ENUMERATED {n8, n16, n32, n64} OPTIONAL, + maxNumberCLI-SRS-RSRP-r16 ENUMERATED {n4, n8, n16, n32} OPTIONAL, + maxNumberPerSlotCLI-SRS-RSRP-r16 ENUMERATED {n2, n4, n8} OPTIONAL, + mfbi-IAB-r16 ENUMERATED {supported} OPTIONAL, + multipleNS-And-Pmax-IAB-r16 ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NPN-r16 ENUMERATED {supported} OPTIONAL, + idleInactiveEUTRA-MeasReport-r16 ENUMERATED {supported} OPTIONAL, + idleInactive-ValidityArea-r16 ENUMERATED {supported} OPTIONAL + ]] + +} + +MeasAndMobParametersXDD-Diff ::= SEQUENCE { + intraAndInterF-MeasAndReport ENUMERATED {supported} OPTIONAL, + eventA-MeasAndReport ENUMERATED {supported} OPTIONAL, + ..., + [[ + handoverInterF ENUMERATED {supported} OPTIONAL, + handoverLTE-EPC ENUMERATED {supported} OPTIONAL, + handoverLTE-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + sftd-MeasNR-Neigh ENUMERATED {supported} OPTIONAL, + sftd-MeasNR-Neigh-DRX ENUMERATED {supported} OPTIONAL + ]], + [[ + condHandoverParametersXDD-Diff-r16 SEQUENCE { + condHandover-r16 ENUMERATED {supported} OPTIONAL, + condHandoverFailure-r16 ENUMERATED {supported} OPTIONAL, + condHandoverTwoTriggerEvents-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + pcellT312-r16 ENUMERATED {supported} OPTIONAL, + handoverIntraF-IAB-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGaps-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGapsNEDC-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGapsNRDC-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-ENDC-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGapsNEDC-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGapsNRDC-r16 ENUMERATED {supported} OPTIONAL, + handoverUTRA-FDD-r16 ENUMERATED {supported} OPTIONAL + ]] + +} + +MeasAndMobParametersFRX-Diff ::= SEQUENCE { + ss-SINR-Meas ENUMERATED {supported} OPTIONAL, + csi-RSRP-AndRSRQ-MeasWithSSB ENUMERATED {supported} OPTIONAL, + csi-RSRP-AndRSRQ-MeasWithoutSSB ENUMERATED {supported} OPTIONAL, + csi-SINR-Meas ENUMERATED {supported} OPTIONAL, + csi-RS-RLM ENUMERATED {supported} OPTIONAL, + ..., + [[ + handoverInterF ENUMERATED {supported} OPTIONAL, + handoverLTE-EPC ENUMERATED {supported} OPTIONAL, + handoverLTE-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + maxNumberResource-CSI-RS-RLM ENUMERATED {n2, n4, n6, n8} OPTIONAL + ]], + [[ + simultaneousRxDataSSB-DiffNumerology ENUMERATED {supported} OPTIONAL + ]], + [[ + nr-AutonomousGaps-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-ENDC-r16 ENUMERATED {supported} OPTIONAL, + handoverUTRA-FDD-r16 ENUMERATED {supported} OPTIONAL, + cli-RSSI-Meas-r16 ENUMERATED {supported} OPTIONAL, + cli-SRS-RSRP-Meas-r16 ENUMERATED {supported} OPTIONAL, + condHandoverParametersFRX-Diff-r16 SEQUENCE { + condHandover-r16 ENUMERATED {supported} OPTIONAL, + condHandoverFailure-r16 ENUMERATED {supported} OPTIONAL, + condHandoverTwoTriggerEvents-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + pcellT312-r16 ENUMERATED {supported} OPTIONAL, + interFrequencyMeas-Nogap-r16 ENUMERATED {supported} OPTIONAL, + simultaneousRxDataSSB-DiffNumerology-Inter-r16 ENUMERATED {supported} OPTIONAL, + handoverIntraF-IAB-r16 ENUMERATED {supported} OPTIONAL, + idleInactiveNR-MeasReport-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-MEASANDMOBPARAMETERS-STOP +-- TAG-MEASANDMOBPARAMETERSMRDC-START + +MeasAndMobParametersMRDC ::= SEQUENCE { + measAndMobParametersMRDC-Common MeasAndMobParametersMRDC-Common OPTIONAL, + measAndMobParametersMRDC-XDD-Diff MeasAndMobParametersMRDC-XDD-Diff OPTIONAL, + measAndMobParametersMRDC-FRX-Diff MeasAndMobParametersMRDC-FRX-Diff OPTIONAL +} + +MeasAndMobParametersMRDC-v1560 ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff-v1560 MeasAndMobParametersMRDC-XDD-Diff-v1560 OPTIONAL +} + +MeasAndMobParametersMRDC-v1610 ::= SEQUENCE { + measAndMobParametersMRDC-Common-v1610 MeasAndMobParametersMRDC-Common-v1610 OPTIONAL, + measAndMobParametersMRDC-XDD-Diff-v1610 MeasAndMobParametersMRDC-XDD-Diff-v1610 OPTIONAL, + measAndMobParametersMRDC-FRX-Diff-v1610 MeasAndMobParametersMRDC-FRX-Diff-v1610 OPTIONAL, + interNR-MeasEUTRA-IAB-r16 ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-Common ::= SEQUENCE { + independentGapConfig ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-Common-v1610 ::= SEQUENCE { + condPSCellChangeParametersCommon-r16 SEQUENCE { + condPSCellChangeFDD-TDD-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChangeFR1-FR2-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL +} + +MeasAndMobParametersMRDC-XDD-Diff ::= SEQUENCE { + sftd-MeasPSCell ENUMERATED {supported} OPTIONAL, + sftd-MeasNR-Cell ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-XDD-Diff-v1560 ::= SEQUENCE { + sftd-MeasPSCell-NEDC ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-XDD-Diff-v1610 ::= SEQUENCE { + condPSCellChangeParametersXDD-Diff-r16 SEQUENCE { + condPSCellChange-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChangeTwoTriggerEvents-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + pscellT312-r16 ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-FRX-Diff ::= SEQUENCE { + simultaneousRxDataSSB-DiffNumerology ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-FRX-Diff-v1610 ::= SEQUENCE { + condPSCellChangeParametersFRX-Diff-r16 SEQUENCE { + condPSCellChange-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChangeTwoTriggerEvents-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + pscellT312-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-MEASANDMOBPARAMETERSMRDC-STOP +-- TAG-MIMO-LAYERS-START + +MIMO-LayersDL ::= ENUMERATED {twoLayers, fourLayers, eightLayers} + +MIMO-LayersUL ::= ENUMERATED {oneLayer, twoLayers, fourLayers} + +-- TAG-MIMO-LAYERS-STOP +-- TAG-MIMO-PARAMETERSPERBAND-START + +MIMO-ParametersPerBand ::= SEQUENCE { + tci-StatePDSCH SEQUENCE { + maxNumberConfiguredTCIstatesPerCC ENUMERATED {n4, n8, n16, n32, n64, n128} OPTIONAL, + maxNumberActiveTCI-PerBWP ENUMERATED {n1, n2, n4, n8} OPTIONAL + } OPTIONAL, + additionalActiveTCI-StatePDCCH ENUMERATED {supported} OPTIONAL, + pusch-TransCoherence ENUMERATED {nonCoherent, partialCoherent, fullCoherent} OPTIONAL, + beamCorrespondenceWithoutUL-BeamSweeping ENUMERATED {supported} OPTIONAL, + periodicBeamReport ENUMERATED {supported} OPTIONAL, + aperiodicBeamReport ENUMERATED {supported} OPTIONAL, + sp-BeamReportPUCCH ENUMERATED {supported} OPTIONAL, + sp-BeamReportPUSCH ENUMERATED {supported} OPTIONAL, + dummy1 DummyG OPTIONAL, + maxNumberRxBeam INTEGER (2..8) OPTIONAL, + maxNumberRxTxBeamSwitchDL SEQUENCE { + scs-15kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-30kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-60kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-120kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-240kHz ENUMERATED {n4, n7, n14} OPTIONAL + } OPTIONAL, + maxNumberNonGroupBeamReporting ENUMERATED {n1, n2, n4} OPTIONAL, + groupBeamReporting ENUMERATED {supported} OPTIONAL, + uplinkBeamManagement SEQUENCE { + maxNumberSRS-ResourcePerSet-BM ENUMERATED {n2, n4, n8, n16}, + maxNumberSRS-ResourceSet INTEGER (1..8) + } OPTIONAL, + maxNumberCSI-RS-BFD INTEGER (1..64) OPTIONAL, + maxNumberSSB-BFD INTEGER (1..64) OPTIONAL, + maxNumberCSI-RS-SSB-CBD INTEGER (1..256) OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + twoPortsPTRS-UL ENUMERATED {supported} OPTIONAL, + dummy5 SRS-Resources OPTIONAL, + dummy3 INTEGER (1..4) OPTIONAL, + beamReportTiming SEQUENCE { + scs-15kHz ENUMERATED {sym2, sym4, sym8} OPTIONAL, + scs-30kHz ENUMERATED {sym4, sym8, sym14, sym28} OPTIONAL, + scs-60kHz ENUMERATED {sym8, sym14, sym28} OPTIONAL, + scs-120kHz ENUMERATED {sym14, sym28, sym56} OPTIONAL + } OPTIONAL, + ptrs-DensityRecommendationSetDL SEQUENCE { + scs-15kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-30kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-60kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-120kHz PTRS-DensityRecommendationDL OPTIONAL + } OPTIONAL, + ptrs-DensityRecommendationSetUL SEQUENCE { + scs-15kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-30kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-60kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-120kHz PTRS-DensityRecommendationUL OPTIONAL + } OPTIONAL, + dummy4 DummyH OPTIONAL, + aperiodicTRS ENUMERATED {supported} OPTIONAL, + ..., + [[ + dummy6 ENUMERATED {true} OPTIONAL, + beamManagementSSB-CSI-RS BeamManagementSSB-CSI-RS OPTIONAL, + beamSwitchTiming SEQUENCE { + scs-60kHz ENUMERATED {sym14, sym28, sym48, sym224, sym336} OPTIONAL, + scs-120kHz ENUMERATED {sym14, sym28, sym48, sym224, sym336} OPTIONAL + } OPTIONAL, + codebookParameters CodebookParameters OPTIONAL, + csi-RS-IM-ReceptionForFeedback CSI-RS-IM-ReceptionForFeedback OPTIONAL, + csi-RS-ProcFrameworkForSRS CSI-RS-ProcFrameworkForSRS OPTIONAL, + csi-ReportFramework CSI-ReportFramework OPTIONAL, + csi-RS-ForTracking CSI-RS-ForTracking OPTIONAL, + srs-AssocCSI-RS SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource OPTIONAL, + spatialRelations SpatialRelations OPTIONAL + ]], + [[ + -- R1 16-2b-0: Support of default QCL assumption with two TCI states + defaultQCL-TwoTCI-r16 ENUMERATED {supported} OPTIONAL, + codebookParametersPerBand-r16 CodebookParameters-v1610 OPTIONAL + ]] + +} + +DummyG ::= SEQUENCE { + maxNumberSSB-CSI-RS-ResourceOneTx ENUMERATED {n8, n16, n32, n64}, + maxNumberSSB-CSI-RS-ResourceTwoTx ENUMERATED {n0, n4, n8, n16, n32, n64}, + supportedCSI-RS-Density ENUMERATED {one, three, oneAndThree} +} + +BeamManagementSSB-CSI-RS ::= SEQUENCE { + maxNumberSSB-CSI-RS-ResourceOneTx ENUMERATED {n0, n8, n16, n32, n64}, + maxNumberCSI-RS-Resource ENUMERATED {n0, n4, n8, n16, n32, n64}, + maxNumberCSI-RS-ResourceTwoTx ENUMERATED {n0, n4, n8, n16, n32, n64}, + supportedCSI-RS-Density ENUMERATED {one, three, oneAndThree} OPTIONAL, + maxNumberAperiodicCSI-RS-Resource ENUMERATED {n0, n1, n4, n8, n16, n32, n64} +} + +DummyH ::= SEQUENCE { + burstLength INTEGER (1..2), + maxSimultaneousResourceSetsPerCC INTEGER (1..8), + maxConfiguredResourceSetsPerCC INTEGER (1..64), + maxConfiguredResourceSetsAllCC INTEGER (1..128) +} + +CSI-RS-ForTracking ::= SEQUENCE { + maxBurstLength INTEGER (1..2), + maxSimultaneousResourceSetsPerCC INTEGER (1..8), + maxConfiguredResourceSetsPerCC INTEGER (1..64), + maxConfiguredResourceSetsAllCC INTEGER (1..256) +} + +CSI-RS-IM-ReceptionForFeedback ::= SEQUENCE { + maxConfigNumberNZP-CSI-RS-PerCC INTEGER (1..64), + maxConfigNumberPortsAcrossNZP-CSI-RS-PerCC INTEGER (2..256), + maxConfigNumberCSI-IM-PerCC ENUMERATED {n1, n2, n4, n8, n16, n32}, + maxNumberSimultaneousNZP-CSI-RS-PerCC INTEGER (1..64), + totalNumberPortsSimultaneousNZP-CSI-RS-PerCC INTEGER (2..256) +} + +CSI-RS-ProcFrameworkForSRS ::= SEQUENCE { + maxNumberPeriodicSRS-AssocCSI-RS-PerBWP INTEGER (1..4), + maxNumberAperiodicSRS-AssocCSI-RS-PerBWP INTEGER (1..4), + maxNumberSP-SRS-AssocCSI-RS-PerBWP INTEGER (0..4), + simultaneousSRS-AssocCSI-RS-PerCC INTEGER (1..8) +} + +CSI-ReportFramework ::= SEQUENCE { + maxNumberPeriodicCSI-PerBWP-ForCSI-Report INTEGER (1..4), + maxNumberAperiodicCSI-PerBWP-ForCSI-Report INTEGER (1..4), + maxNumberSemiPersistentCSI-PerBWP-ForCSI-Report INTEGER (0..4), + maxNumberPeriodicCSI-PerBWP-ForBeamReport INTEGER (1..4), + maxNumberAperiodicCSI-PerBWP-ForBeamReport INTEGER (1..4), + maxNumberAperiodicCSI-triggeringStatePerCC ENUMERATED {n3, n7, n15, n31, n63, n128}, + maxNumberSemiPersistentCSI-PerBWP-ForBeamReport INTEGER (0..4), + simultaneousCSI-ReportsPerCC INTEGER (1..8) +} + +PTRS-DensityRecommendationDL ::= SEQUENCE { + frequencyDensity1 INTEGER (1..276), + frequencyDensity2 INTEGER (1..276), + timeDensity1 INTEGER (0..29), + timeDensity2 INTEGER (0..29), + timeDensity3 INTEGER (0..29) +} + +PTRS-DensityRecommendationUL ::= SEQUENCE { + frequencyDensity1 INTEGER (1..276), + frequencyDensity2 INTEGER (1..276), + timeDensity1 INTEGER (0..29), + timeDensity2 INTEGER (0..29), + timeDensity3 INTEGER (0..29), + sampleDensity1 INTEGER (1..276), + sampleDensity2 INTEGER (1..276), + sampleDensity3 INTEGER (1..276), + sampleDensity4 INTEGER (1..276), + sampleDensity5 INTEGER (1..276) +} + +SpatialRelations ::= SEQUENCE { + maxNumberConfiguredSpatialRelations ENUMERATED {n4, n8, n16, n32, n64, n96}, + maxNumberActiveSpatialRelations ENUMERATED {n1, n2, n4, n8, n14}, + additionalActiveSpatialRelationPUCCH ENUMERATED {supported} OPTIONAL, + maxNumberDL-RS-QCL-TypeD ENUMERATED {n1, n2, n4, n8, n14} +} + +DummyI ::= SEQUENCE { + supportedSRS-TxPortSwitch ENUMERATED {t1r2, t1r4, t2r4, t1r4-t2r4, tr-equal}, + txSwitchImpactToRx ENUMERATED {true} OPTIONAL +} + +-- TAG-MIMO-PARAMETERSPERBAND-STOP +-- TAG-MODULATIONORDER-START + +ModulationOrder ::= ENUMERATED {bpsk-halfpi, bpsk, qpsk, qam16, qam64, qam256} + +-- TAG-MODULATIONORDER-STOP +-- TAG-MRDC-PARAMETERS-START + +MRDC-Parameters ::= SEQUENCE { + singleUL-Transmission ENUMERATED {supported} OPTIONAL, + dynamicPowerSharingENDC ENUMERATED {supported} OPTIONAL, + tdm-Pattern ENUMERATED {supported} OPTIONAL, + ul-SharingEUTRA-NR ENUMERATED {tdm, fdm, both} OPTIONAL, + ul-SwitchingTimeEUTRA-NR ENUMERATED {type1, type2} OPTIONAL, + simultaneousRxTxInterBandENDC ENUMERATED {supported} OPTIONAL, + asyncIntraBandENDC ENUMERATED {supported} OPTIONAL, + ..., + [[ + dualPA-Architecture ENUMERATED {supported} OPTIONAL, + intraBandENDC-Support ENUMERATED {non-contiguous, both} OPTIONAL, + ul-TimingAlignmentEUTRA-NR ENUMERATED {required} OPTIONAL + ]], + [[ + maxUplinkDutyCycle-interBandENDC-TDD-PC2-r16 SEQUENCE{ + eutra-TDD-Config0-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config1-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config2-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config3-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config4-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config5-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config6-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL + } OPTIONAL + ]] +} + +MRDC-Parameters-v1580 ::= SEQUENCE { + dynamicPowerSharingNEDC ENUMERATED {supported} OPTIONAL +} + +MRDC-Parameters-v1590 ::= SEQUENCE { + interBandContiguousMRDC ENUMERATED {supported} OPTIONAL +} + +-- TAG-MRDC-PARAMETERS-STOP +-- TAG-NRDC-PARAMETERS-START + +NRDC-Parameters ::= SEQUENCE { + measAndMobParametersNRDC MeasAndMobParametersMRDC OPTIONAL, + generalParametersNRDC GeneralParametersMRDC-XDD-Diff OPTIONAL, + fdd-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + dummy SEQUENCE {} OPTIONAL +} + +NRDC-Parameters-v1570 ::= SEQUENCE { + sfn-SyncNRDC ENUMERATED {supported} OPTIONAL +} + +NRDC-Parameters-v1610 ::= SEQUENCE { + measAndMobParametersNRDC-v1610 MeasAndMobParametersMRDC-v1610 OPTIONAL +} + + +-- TAG-NRDC-PARAMETERS-STOP +-- TAG-OLPC-SRS-POS-START + +OLPC-SRS-Pos-r16 ::= SEQUENCE { + olpc-SRS-PosBasedOnPRS-Serving-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-PosBasedOnSSB-Neigh-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-PosBasedOnPRS-Neigh-r16 ENUMERATED {supported} OPTIONAL, + maxNumberPathLossEstimatePerServing-r16 ENUMERATED {n1, n4, n8, n16} OPTIONAL +} + +--TAG-OLPC-SRS-POS-STOP +-- TAG-PDCP-PARAMETERS-START + +PDCP-Parameters ::= SEQUENCE { + supportedROHC-Profiles SEQUENCE { + profile0x0000 BOOLEAN, + profile0x0001 BOOLEAN, + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0101 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + maxNumberROHC-ContextSessions ENUMERATED {cs2, cs4, cs8, cs12, cs16, cs24, cs32, cs48, cs64, + cs128, cs256, cs512, cs1024, cs16384, spare2, spare1}, + uplinkOnlyROHC-Profiles ENUMERATED {supported} OPTIONAL, + continueROHC-Context ENUMERATED {supported} OPTIONAL, + outOfOrderDelivery ENUMERATED {supported} OPTIONAL, + shortSN ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationSRB ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationMCG-OrSCG-DRB ENUMERATED {supported} OPTIONAL, + ..., + [[ + drb-IAB-r16 ENUMERATED {supported} OPTIONAL, + non-DRB-IAB-r16 ENUMERATED {supported} OPTIONAL, + extendedDiscardTimer-r16 ENUMERATED {supported} OPTIONAL, + continueEHC-Context-r16 ENUMERATED {supported} OPTIONAL, + ehc-r16 ENUMERATED {supported} OPTIONAL, + maxNumberEHC-Contexts-r16 ENUMERATED {cs2, cs4, cs8, cs16, cs32, cs64, cs128, cs256, cs512, + cs1024, cs2048, cs4096, cs8192, cs16384, cs32768, cs65536} OPTIONAL, + jointEHC-ROHC-Config-r16 ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationMoreThanTwoRLC-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-PDCP-PARAMETERS-STOP +-- TAG-PDCP-PARAMETERSMRDC-START + +PDCP-ParametersMRDC ::= SEQUENCE { + pdcp-DuplicationSplitSRB ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationSplitDRB ENUMERATED {supported} OPTIONAL +} + +PDCP-ParametersMRDC-v1610 ::= SEQUENCE { + scg-DRB-NR-IAB-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-PDCP-PARAMETERSMRDC-STOP +-- TAG-PHY-PARAMETERS-START + +Phy-Parameters ::= SEQUENCE { + phy-ParametersCommon Phy-ParametersCommon OPTIONAL, + phy-ParametersXDD-Diff Phy-ParametersXDD-Diff OPTIONAL, + phy-ParametersFRX-Diff Phy-ParametersFRX-Diff OPTIONAL, + phy-ParametersFR1 Phy-ParametersFR1 OPTIONAL, + phy-ParametersFR2 Phy-ParametersFR2 OPTIONAL +} + +Phy-ParametersCommon ::= SEQUENCE { + csi-RS-CFRA-ForHO ENUMERATED {supported} OPTIONAL, + dynamicPRB-BundlingDL ENUMERATED {supported} OPTIONAL, + sp-CSI-ReportPUCCH ENUMERATED {supported} OPTIONAL, + sp-CSI-ReportPUSCH ENUMERATED {supported} OPTIONAL, + nzp-CSI-RS-IntefMgmt ENUMERATED {supported} OPTIONAL, + type2-SP-CSI-Feedback-LongPUCCH ENUMERATED {supported} OPTIONAL, + precoderGranularityCORESET ENUMERATED {supported} OPTIONAL, + dynamicHARQ-ACK-Codebook ENUMERATED {supported} OPTIONAL, + semiStaticHARQ-ACK-Codebook ENUMERATED {supported} OPTIONAL, + spatialBundlingHARQ-ACK ENUMERATED {supported} OPTIONAL, + dynamicBetaOffsetInd-HARQ-ACK-CSI ENUMERATED {supported} OPTIONAL, + pucch-Repetition-F1-3-4 ENUMERATED {supported} OPTIONAL, + ra-Type0-PUSCH ENUMERATED {supported} OPTIONAL, + dynamicSwitchRA-Type0-1-PDSCH ENUMERATED {supported} OPTIONAL, + dynamicSwitchRA-Type0-1-PUSCH ENUMERATED {supported} OPTIONAL, + pdsch-MappingTypeA ENUMERATED {supported} OPTIONAL, + pdsch-MappingTypeB ENUMERATED {supported} OPTIONAL, + interleavingVRB-ToPRB-PDSCH ENUMERATED {supported} OPTIONAL, + interSlotFreqHopping-PUSCH ENUMERATED {supported} OPTIONAL, + type1-PUSCH-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + type2-PUSCH-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + pusch-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + pdsch-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + downlinkSPS ENUMERATED {supported} OPTIONAL, + configuredUL-GrantType1 ENUMERATED {supported} OPTIONAL, + configuredUL-GrantType2 ENUMERATED {supported} OPTIONAL, + pre-EmptIndication-DL ENUMERATED {supported} OPTIONAL, + cbg-TransIndication-DL ENUMERATED {supported} OPTIONAL, + cbg-TransIndication-UL ENUMERATED {supported} OPTIONAL, + cbg-FlushIndication-DL ENUMERATED {supported} OPTIONAL, + dynamicHARQ-ACK-CodeB-CBG-Retx-DL ENUMERATED {supported} OPTIONAL, + rateMatchingResrcSetSemi-Static ENUMERATED {supported} OPTIONAL, + rateMatchingResrcSetDynamic ENUMERATED {supported} OPTIONAL, + bwp-SwitchingDelay ENUMERATED {type1, type2} OPTIONAL, + ..., + [[ + dummy ENUMERATED {supported} OPTIONAL + ]], + [[ + maxNumberSearchSpaces ENUMERATED {n10} OPTIONAL, + rateMatchingCtrlResrcSetDynamic ENUMERATED {supported} OPTIONAL, + maxLayersMIMO-Indication ENUMERATED {supported} OPTIONAL + ]], + [[ + spCellPlacement CarrierAggregationVariant OPTIONAL + ]], + [[ + -- R1 9-1: Basic channel structure and procedure of 2-step RACH + twoStepRACH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-1: Monitoring DCI format 1_2 and DCI format 0_2 + dci-Format1-2And0-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-1a: Monitoring both DCI format 0_1/1_1 and DCI format 0_2/1_2 in the same search space + monitoringDCI-SameSearchSpace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-10: Type 2 configured grant release by DCI format 0_1 + type2-CG-ReleaseDCI-0-1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-11: Type 2 configured grant release by DCI format 0_2 + type2-CG-ReleaseDCI-0-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-3: SPS release by DCI format 1_1 + sps-ReleaseDCI-1-1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-3a: SPS release by DCI format 1_2 + sps-ReleaseDCI-1-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-8: CSI trigger states containing non-active BWP + csi-TriggerStateNon-ActiveBWP-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-2: Support up to 4 SMTCs configured for an IAB node MT per frequency location, including IAB-specific SMTC window periodicities + seperateSMTC-InterIAB-Support-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-3: Support RACH configuration separately from the RACH configuration for UE access, including new IAB-specific offset and scaling factors + seperateRACH-IAB-Support-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-5a: Support semi-static configuration/indication of UL-Flexible-DL slot formats for IAB-MT resources + ul-flexibleDL-SlotFormatSemiStatic-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-5b: Support dynamic indication of UL-Flexible-DL slot formats for IAB-MT resources + ul-flexibleDL-SlotFormatDynamics-IAB-r16 ENUMERATED {supported} OPTIONAL, + dft-S-OFDM-WaveformUL-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-6: Support DCI Format 2_5 based indication of soft resource availability to an IAB node + dci-25-AI-RNTI-Support-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-7: Support T_delta reception. + t-DeltaReceptionSupport-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-8: Support of Desired guard symbol reporting and provided guard symbok reception. + guardSymbolReportReception-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-8 HARQ-ACK codebook type and spatial bundling per PUCCH group + harqACK-CB-SpatialBundlingPUCCH-Group-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-2: Cross Slot Scheduling + crossSlotScheduling-r16 SEQUENCE { + licensedBand-r16 ENUMERATED {supported} OPTIONAL, + unlicensedBand-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + maxNumberSRS-PosPathLossEstimateAllServingCells-r16 ENUMERATED {n1, n4, n8, n16} OPTIONAL, + maxNumberSRS-PosSpatialRelationsAllServingCells-r16 ENUMERATED {n0, n1, n2, n4, n8, n16} OPTIONAL, + extendedCG-Periodicities-r16 ENUMERATED {supported} OPTIONAL, + extendedSPS-Periodicities-r16 ENUMERATED {supported} OPTIONAL, + codebookVariantsList-r16 CodebookVariantsList-r16 OPTIONAL + ]] +} + +Phy-ParametersXDD-Diff ::= SEQUENCE { + dynamicSFI ENUMERATED {supported} OPTIONAL, + twoPUCCH-F0-2-ConsecSymbols ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUSCH ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUCCH ENUMERATED {supported} OPTIONAL, + ..., + [[ + dl-SchedulingOffset-PDSCH-TypeA ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeB ENUMERATED {supported} OPTIONAL, + ul-SchedulingOffset ENUMERATED {supported} OPTIONAL + ]] +} + +Phy-ParametersFRX-Diff ::= SEQUENCE { + dynamicSFI ENUMERATED {supported} OPTIONAL, + dummy1 BIT STRING (SIZE (2)) OPTIONAL, + twoFL-DMRS BIT STRING (SIZE (2)) OPTIONAL, + dummy2 BIT STRING (SIZE (2)) OPTIONAL, + dummy3 BIT STRING (SIZE (2)) OPTIONAL, + supportedDMRS-TypeDL ENUMERATED {type1, type1And2} OPTIONAL, + supportedDMRS-TypeUL ENUMERATED {type1, type1And2} OPTIONAL, + semiOpenLoopCSI ENUMERATED {supported} OPTIONAL, + csi-ReportWithoutPMI ENUMERATED {supported} OPTIONAL, + csi-ReportWithoutCQI ENUMERATED {supported} OPTIONAL, + onePortsPTRS BIT STRING (SIZE (2)) OPTIONAL, + twoPUCCH-F0-2-ConsecSymbols ENUMERATED {supported} OPTIONAL, + pucch-F2-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F3-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F4-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F0-2WithoutFH ENUMERATED {notSupported} OPTIONAL, + pucch-F1-3-4WithoutFH ENUMERATED {notSupported} OPTIONAL, + mux-SR-HARQ-ACK-CSI-PUCCH-MultiPerSlot ENUMERATED {supported} OPTIONAL, + uci-CodeBlockSegmentation ENUMERATED {supported} OPTIONAL, + onePUCCH-LongAndShortFormat ENUMERATED {supported} OPTIONAL, + twoPUCCH-AnyOthersInSlot ENUMERATED {supported} OPTIONAL, + intraSlotFreqHopping-PUSCH ENUMERATED {supported} OPTIONAL, + pusch-LBRM ENUMERATED {supported} OPTIONAL, + pdcch-BlindDetectionCA INTEGER (4..16) OPTIONAL, + tpc-PUSCH-RNTI ENUMERATED {supported} OPTIONAL, + tpc-PUCCH-RNTI ENUMERATED {supported} OPTIONAL, + tpc-SRS-RNTI ENUMERATED {supported} OPTIONAL, + absoluteTPC-Command ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUSCH ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUCCH ENUMERATED {supported} OPTIONAL, + pusch-HalfPi-BPSK ENUMERATED {supported} OPTIONAL, + pucch-F3-4-HalfPi-BPSK ENUMERATED {supported} OPTIONAL, + almostContiguousCP-OFDM-UL ENUMERATED {supported} OPTIONAL, + sp-CSI-RS ENUMERATED {supported} OPTIONAL, + sp-CSI-IM ENUMERATED {supported} OPTIONAL, + tdd-MultiDL-UL-SwitchPerSlot ENUMERATED {supported} OPTIONAL, + multipleCORESET ENUMERATED {supported} OPTIONAL, + ..., + [[ + csi-RS-IM-ReceptionForFeedback CSI-RS-IM-ReceptionForFeedback OPTIONAL, + csi-RS-ProcFrameworkForSRS CSI-RS-ProcFrameworkForSRS OPTIONAL, + csi-ReportFramework CSI-ReportFramework OPTIONAL, + mux-SR-HARQ-ACK-CSI-PUCCH-OncePerSlot SEQUENCE { + sameSymbol ENUMERATED {supported} OPTIONAL, + diffSymbol ENUMERATED {supported} OPTIONAL + } OPTIONAL, + mux-SR-HARQ-ACK-PUCCH ENUMERATED {supported} OPTIONAL, + mux-MultipleGroupCtrlCH-Overlap ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeA ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeB ENUMERATED {supported} OPTIONAL, + ul-SchedulingOffset ENUMERATED {supported} OPTIONAL, + dl-64QAM-MCS-TableAlt ENUMERATED {supported} OPTIONAL, + ul-64QAM-MCS-TableAlt ENUMERATED {supported} OPTIONAL, + cqi-TableAlt ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-TwoAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL, + twoFL-DMRS-TwoAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-ThreeAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL + ]], + [[ + pdcch-BlindDetectionNRDC SEQUENCE { + pdcch-BlindDetectionMCG-UE INTEGER (1..15), + pdcch-BlindDetectionSCG-UE INTEGER (1..15) + } OPTIONAL, + mux-HARQ-ACK-PUSCH-DiffSymbol ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R1 11-1b: Type 1 HARQ-ACK codebook support for relative TDRA for DL + type1-HARQ-ACK-Codebook-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-8: Enhanced UL power control scheme + enhancedPowerControl-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1b-1: TCI state activation across multiple CCs + simultaneousTCI-ActMultipleCC-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1b-2: Spatial relation update across multiple CCs + simultaneousSpatialRelationMultipleCC-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1c: Support of default spatial relation and pathloss reference RS for dedicated-PUCCH/SRS and PUSCH + defaultSpatialRelationPathlossRS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1d: Support of spatial relation update for AP-SRS via MAC CE + spatialRelationUpdateAP-SRS-r16 ENUMERATED {supported} OPTIONAL, + cli-RSSI-FDM-DL-r16 ENUMERATED {supported} OPTIONAL, + cli-SRS-RSRP-FDM-DL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-3: Maximum MIMO Layer Adaptation + maxLayersMIMO-Adaptation-r16 ENUMERATED {supported} OPTIONAL + ]] + +} + +Phy-ParametersFR1 ::= SEQUENCE { + pdcch-MonitoringSingleOccasion ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL, + pdsch-256QAM-FR1 ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR1-PerSymbol ENUMERATED {n10, n20} OPTIONAL, + ..., + [[ + pdsch-RE-MappingFR1-PerSlot ENUMERATED {n16, n32, n48, n64, n80, n96, n112, n128, + n144, n160, n176, n192, n208, n224, n240, n256} OPTIONAL + ]] +} + +Phy-ParametersFR2 ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR2-PerSymbol ENUMERATED {n6, n20} OPTIONAL, + ..., + [[ + pCell-FR2 ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR2-PerSlot ENUMERATED {n16, n32, n48, n64, n80, n96, n112, n128, + n144, n160, n176, n192, n208, n224, n240, n256} OPTIONAL + ]] +} + +-- TAG-PHY-PARAMETERS-STOP +-- TAG-PHY-PARAMETERSMRDC-START + +Phy-ParametersMRDC ::= SEQUENCE { + naics-Capability-List SEQUENCE (SIZE (1..maxNrofNAICS-Entries)) OF NAICS-Capability-Entry OPTIONAL, + ..., + [[ + spCellPlacement CarrierAggregationVariant OPTIONAL + ]] +} + +NAICS-Capability-Entry ::= SEQUENCE { + numberOfNAICS-CapableCC INTEGER(1..5), + numberOfAggregatedPRB ENUMERATED {n50, n75, n100, n125, n150, n175, n200, n225, + n250, n275, n300, n350, n400, n450, n500, spare}, + ... +} + +-- TAG-PHY-PARAMETERSMRDC-STOP +-- TAG-POWSAV-PARAMETERS-START + +PowSav-Parameters-r16 ::= SEQUENCE { + powSav-ParametersCommon-r16 PowSav-ParametersCommon-r16 OPTIONAL, + powSav-ParametersFRX-Diff-r16 PowSav-ParametersFRX-Diff-r16 OPTIONAL, + ... +} + +PowSav-ParametersCommon-r16 ::= SEQUENCE { + drx-Preference-r16 ENUMERATED {supported} OPTIONAL, + maxCC-Preference-r16 ENUMERATED {supported} OPTIONAL, + releasePreference-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-4a: UE assistance information + minSchedulingOffsetPreference-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +PowSav-ParametersFRX-Diff-r16 ::= SEQUENCE { + maxBW-Preference-r16 ENUMERATED {supported} OPTIONAL, + maxMIMO-LayerPreference-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-POWSAV-PARAMETERS-STOP +-- TAG-PROCESSINGPARAMETERS-START + +ProcessingParameters ::= SEQUENCE { + fallback ENUMERATED {sc, cap1-only}, + differentTB-PerSlot SEQUENCE { + upto1 NumberOfCarriers OPTIONAL, + upto2 NumberOfCarriers OPTIONAL, + upto4 NumberOfCarriers OPTIONAL, + upto7 NumberOfCarriers OPTIONAL + } OPTIONAL +} + +NumberOfCarriers ::= INTEGER (1..16) + +-- TAG-PROCESSINGPARAMETERS-STOP +-- TAG-RAT-TYPE-START + +RAT-Type ::= ENUMERATED {nr, eutra-nr, eutra, utra-fdd-v1610, ...} + +-- TAG-RAT-TYPE-STOP +-- TAG-RF-PARAMETERS-START + +RF-Parameters ::= SEQUENCE { + supportedBandListNR SEQUENCE (SIZE (1..maxBands)) OF BandNR, + supportedBandCombinationList BandCombinationList OPTIONAL, + appliedFreqBandListFilter FreqBandList OPTIONAL, + ..., + [[ + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL, + srs-SwitchingTimeRequested ENUMERATED {true} OPTIONAL + ]], + [[ + supportedBandCombinationList-v1550 BandCombinationList-v1550 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationListSidelink-r16 BandCombinationListSidelink-r16 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-r16 BandCombinationList-UplinkTxSwitch-r16 OPTIONAL + ]] +} + +BandNR ::= SEQUENCE { + bandNR FreqBandIndicatorNR, + modifiedMPR-Behaviour BIT STRING (SIZE (8)) OPTIONAL, + mimo-ParametersPerBand MIMO-ParametersPerBand OPTIONAL, + extendedCP ENUMERATED {supported} OPTIONAL, + multipleTCI ENUMERATED {supported} OPTIONAL, + bwp-WithoutRestriction ENUMERATED {supported} OPTIONAL, + bwp-SameNumerology ENUMERATED {upto2, upto4} OPTIONAL, + bwp-DiffNumerology ENUMERATED {upto4} OPTIONAL, + crossCarrierScheduling-SameSCS ENUMERATED {supported} OPTIONAL, + pdsch-256QAM-FR2 ENUMERATED {supported} OPTIONAL, + pusch-256QAM ENUMERATED {supported} OPTIONAL, + ue-PowerClass ENUMERATED {pc1, pc2, pc3, pc4} OPTIONAL, + rateMatchingLTE-CRS ENUMERATED {supported} OPTIONAL, + channelBWs-DL CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (10)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (3)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (3)) OPTIONAL + } + } OPTIONAL, + channelBWs-UL CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (10)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (3)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (3)) OPTIONAL + } + } OPTIONAL, + ..., + [[ + maxUplinkDutyCycle-PC2-FR1 ENUMERATED {n60, n70, n80, n90, n100} OPTIONAL + ]], + [[ + pucch-SpatialRelInfoMAC-CE ENUMERATED {supported} OPTIONAL, + powerBoosting-pi2BPSK ENUMERATED {supported} OPTIONAL + ]], + [[ + maxUplinkDutyCycle-FR2 ENUMERATED {n15, n20, n25, n30, n40, n50, n60, n70, n80, n90, n100} OPTIONAL + ]], + [[ + channelBWs-DL-v1590 CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (16)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (8)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (8)) OPTIONAL + } + } OPTIONAL, + channelBWs-UL-v1590 CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (16)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (8)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (8)) OPTIONAL + } + } OPTIONAL + ]], + [[ + asymmetricBandwidthCombinationSet BIT STRING (SIZE (1..32)) OPTIONAL + ]], + [[ + -- R1 10: NR-unlicensed + unlicensedParametersPerBand-r16 UnlicensedParametersPerBand-r16 OPTIONAL, + -- R1 11-7b: Independent cancellation of the overlapping PUSCHs in an intra-band UL CA + cancelOverlappingPUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-1: Multiple LTE-CRS rate matching patterns + multipleRateMatchingEUTRA-CRS-r16 SEQUENCE { + maxNumberPatterns-r16 INTEGER (2..6), + maxNumberNon-OverlapPatterns-r16 INTEGER (1..3) + } OPTIONAL, + -- R1 14-1a: Two LTE-CRS overlapping rate matching patterns within a part of NR carrier using 15 kHz overlapping with a LTE carrier + overlapRateMatchingEUTRA-CRS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-2: PDSCH Type B mapping of length 9 and 10 OFDM symbols + pdsch-MappingTypeB-Alt-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-3: One slot periodic TRS configuration for FR1 + oneShotPeriodicTRS-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-Pos-r16 OLPC-SRS-Pos-r16 OPTIONAL, + spatialRelationsSRS-Pos-r16 SpatialRelationsSRS-Pos-r16 OPTIONAL, + simul-SRS-Trans-IntraBandCA-r16 INTEGER (1..2) OPTIONAL, + channelBW-DL-IAB-r16 CHOICE { + fr1-100mhz SEQUENCE { + scs-15kHz ENUMERATED {supported} OPTIONAL, + scs-30kHz ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL + }, + fr2-200mhz SEQUENCE { + scs-60kHz ENUMERATED {supported} OPTIONAL, + scs-120kHz ENUMERATED {supported} OPTIONAL + } + } OPTIONAL, + channelBW-UL-IAB-r16 CHOICE { + fr1-100mhz SEQUENCE { + scs-15kHz ENUMERATED {supported} OPTIONAL, + scs-30kHz ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL + }, + fr2-200mhz SEQUENCE { + scs-60kHz ENUMERATED {supported} OPTIONAL, + scs-120kHz ENUMERATED {supported} OPTIONAL + } + } OPTIONAL, + rasterShift7dot5-IAB-r16 ENUMERATED {supported} OPTIONAL, + ue-PowerClass-v1610 ENUMERATED {pc1dot5} OPTIONAL + ]] +} + +-- TAG-RF-PARAMETERS-STOP +-- TAG-RF-PARAMETERSMRDC-START + +RF-ParametersMRDC ::= SEQUENCE { + supportedBandCombinationList BandCombinationList OPTIONAL, + appliedFreqBandListFilter FreqBandList OPTIONAL, + ..., + [[ + srs-SwitchingTimeRequested ENUMERATED {true} OPTIONAL, + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1550 BandCombinationList-v1550 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL, + supportedBandCombinationListNEDC-Only BandCombinationList OPTIONAL + ]], + [[ + supportedBandCombinationList-v1570 BandCombinationList-v1570 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1580 BandCombinationList-v1580 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1590 BandCombinationList-v1590 OPTIONAL + ]], + [[ + supportedBandCombinationListNEDC-Only-v15a0 SEQUENCE { + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL, + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL, + supportedBandCombinationList-v1570 BandCombinationList-v1570 OPTIONAL, + supportedBandCombinationList-v1580 BandCombinationList-v1580 OPTIONAL, + supportedBandCombinationList-v1590 BandCombinationList-v1590 OPTIONAL + } OPTIONAL + ]], + [[ + supportedBandCombinationList-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationListNEDC-Only-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-r16 BandCombinationList-UplinkTxSwitch-r16 OPTIONAL + ]] +} + +-- TAG-RF-PARAMETERSMRDC-STOP +-- TAG-RLC-PARAMETERS-START + +RLC-Parameters ::= SEQUENCE { + am-WithShortSN ENUMERATED {supported} OPTIONAL, + um-WithShortSN ENUMERATED {supported} OPTIONAL, + um-WithLongSN ENUMERATED {supported} OPTIONAL, + ..., + [[ + extendedT-PollRetransmit-r16 ENUMERATED {supported} OPTIONAL, + extendedT-StatusProhibit-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-RLC-PARAMETERS-STOP +-- TAG-SDAP-PARAMETERS-START + +SDAP-Parameters ::= SEQUENCE { + as-ReflectiveQoS ENUMERATED {true} OPTIONAL, + ..., + [[ + sdap-QOS-IAB-r16 ENUMERATED {supported} OPTIONAL, + sdapHeaderIAB-r16 ENUMERATED {supported} OPTIONAL + ]] + +} + +-- TAG-SDAP-PARAMETERS-STOP +-- TAG-SIDELINKPARAMETERS-START + +SidelinkParameters-r16 ::= SEQUENCE { + sidelinkParametersNR-r16 SidelinkParametersNR-r16 OPTIONAL, + sidelinkParametersEUTRA-r16 SidelinkParametersEUTRA-r16 OPTIONAL +} + +SidelinkParametersNR-r16 ::= SEQUENCE { + rlc-ParametersSidelink-r16 RLC-ParametersSidelink-r16 OPTIONAL, + mac-ParametersSidelink-r16 MAC-ParametersSidelink-r16 OPTIONAL, + fdd-Add-UE-Sidelink-Capabilities-r16 UE-SidelinkCapabilityAddXDD-Mode-r16 OPTIONAL, + tdd-Add-UE-Sidelink-Capabilities-r16 UE-SidelinkCapabilityAddXDD-Mode-r16 OPTIONAL, + ... +} + +SidelinkParametersEUTRA-r16 ::= SEQUENCE { + sl-ParametersEUTRA1-r16 OCTET STRING OPTIONAL, + sl-ParametersEUTRA2-r16 OCTET STRING OPTIONAL, + sl-ParametersEUTRA3-r16 OCTET STRING OPTIONAL, + supportedBandListSidelinkEUTRA-r16 SEQUENCE (SIZE (1..maxBandsEUTRA)) OF BandSidelinkEUTRA-r16 OPTIONAL, + ... +} + +RLC-ParametersSidelink-r16 ::= SEQUENCE { + am-WithLongSN-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + um-WithLongSN-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +MAC-ParametersSidelink-r16 ::= SEQUENCE { + mac-ParametersSidelinkCommon-r16 MAC-ParametersSidelinkCommon-r16 OPTIONAL, + mac-ParametersSidelinkXDD-Diff-r16 MAC-ParametersSidelinkXDD-Diff-r16 OPTIONAL, + ... +} + +UE-SidelinkCapabilityAddXDD-Mode-r16 ::= SEQUENCE { + mac-ParametersSidelinkXDD-Diff-r16 MAC-ParametersSidelinkXDD-Diff-r16 OPTIONAL +} + +MAC-ParametersSidelinkCommon-r16 ::= SEQUENCE { + lcp-RestrictionSidelink-r16 ENUMERATED {supported} OPTIONAL, + multipleConfiguredGrantsSidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +MAC-ParametersSidelinkXDD-Diff-r16 ::= SEQUENCE { + multipleSR-ConfigurationsSidelink-r16 ENUMERATED {supported} OPTIONAL, + logicalChannelSR-DelayTimerSidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +BandSidelinkEUTRA-r16 ::= SEQUENCE { + freqBandSidelinkEUTRA-r16 FreqBandIndicatorEUTRA, + -- R1 15-7: Transmitting LTE sidelink mode 3 scheduled by NR Uu + gnb-ScheduledMode3SidelinkEUTRA-r16 SEQUENCE { + gnb-ScheduledMode3DelaySidelinkEUTRA-r16 ENUMERATED {ms0, ms0dot25, ms0dot5, ms0dot625, ms0dot75, ms1, + ms1dot25, ms1dot5, ms1dot75, ms2, ms2dot5, ms3, ms4, + ms5, ms6, ms8, ms10, ms20} + } OPTIONAL, + -- R1 15-9: Transmitting LTE sidelink mode 4 configured by NR Uu + gnb-ScheduledMode4SidelinkEUTRA-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-SIDELINKPARAMETERS-STOP +-- TAG-SON-PARAMETERS-START + +SON-Parameters-r16 ::= SEQUENCE { + rach-Report-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-SON-PARAMETERS-STOP +-- TAG-SPATIALRELATIONSSRS-POS-START + +SpatialRelationsSRS-Pos-r16 ::= SEQUENCE { + spatialRelation-SRS-PosBasedOnSSB-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnCSI-RS-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnPRS-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnSRS-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnSSB-Neigh-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnPRS-Neigh-r16 ENUMERATED {supported} OPTIONAL +} + +--TAG-SPATIALRELATIONSSRS-POS-STOP +-- TAG-SRS-SWITCHINGTIMENR-START + +SRS-SwitchingTimeNR ::= SEQUENCE { + switchingTimeDL ENUMERATED {n0us, n30us, n100us, n140us, n200us, n300us, n500us, n900us} OPTIONAL, + switchingTimeUL ENUMERATED {n0us, n30us, n100us, n140us, n200us, n300us, n500us, n900us} OPTIONAL +} + +-- TAG-SRS-SWITCHINGTIMENR-STOP +-- TAG-SRS-SWITCHINGTIMEEUTRA-START + +SRS-SwitchingTimeEUTRA ::= SEQUENCE { + switchingTimeDL ENUMERATED {n0, n0dot5, n1, n1dot5, n2, n2dot5, n3, n3dot5, n4, n4dot5, n5, n5dot5, n6, n6dot5, n7} + OPTIONAL, + switchingTimeUL ENUMERATED {n0, n0dot5, n1, n1dot5, n2, n2dot5, n3, n3dot5, n4, n4dot5, n5, n5dot5, n6, n6dot5, n7} + OPTIONAL +} +-- TAG-SRS-SWITCHINGTIMEEUTRA-STOP +-- TAG-SUPPORTEDBANDWIDTH-START + +SupportedBandwidth ::= CHOICE { + fr1 ENUMERATED {mhz5, mhz10, mhz15, mhz20, mhz25, mhz30, mhz40, mhz50, mhz60, mhz80, mhz100}, + fr2 ENUMERATED {mhz50, mhz100, mhz200, mhz400} +} + +-- TAG-SUPPORTEDBANDWIDTH-STOP +-- TAG-UE-BASEDPERFMEAS-PARAMETERS-START + +UE-BasedPerfMeas-Parameters-r16 ::= SEQUENCE { + barometerMeasReport-r16 ENUMERATED {supported} OPTIONAL, + immMeasBT-r16 ENUMERATED {supported} OPTIONAL, + immMeasWLAN-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasBT-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasurements-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasWLAN-r16 ENUMERATED {supported} OPTIONAL, + orientationMeasReport-r16 ENUMERATED {supported} OPTIONAL, + speedMeasReport-r16 ENUMERATED {supported} OPTIONAL, + gnss-Location-r16 ENUMERATED {supported} OPTIONAL, + ulPDCP-Delay-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-UE-BASEDPERFMEAS-PARAMETERS-STOP +-- TAG-UE-CAPABILITYRAT-CONTAINERLIST-START + +UE-CapabilityRAT-ContainerList ::= SEQUENCE (SIZE (0..maxRAT-CapabilityContainers)) OF UE-CapabilityRAT-Container + +UE-CapabilityRAT-Container ::= SEQUENCE { + rat-Type RAT-Type, + ue-CapabilityRAT-Container OCTET STRING +} + +-- TAG-UE-CAPABILITYRAT-CONTAINERLIST-STOP +-- TAG-UE-CAPABILITYRAT-REQUESTLIST-START + +UE-CapabilityRAT-RequestList ::= SEQUENCE (SIZE (1..maxRAT-CapabilityContainers)) OF UE-CapabilityRAT-Request + +UE-CapabilityRAT-Request ::= SEQUENCE { + rat-Type RAT-Type, + capabilityRequestFilter OCTET STRING OPTIONAL, -- Need N + ... +} + +-- TAG-UE-CAPABILITYRAT-REQUESTLIST-STOP +-- TAG-UE-CAPABILITYREQUESTFILTERCOMMON-START + +UE-CapabilityRequestFilterCommon ::= SEQUENCE { + mrdc-Request SEQUENCE { + omitEN-DC ENUMERATED {true} OPTIONAL, -- Need N + includeNR-DC ENUMERATED {true} OPTIONAL, -- Need N + includeNE-DC ENUMERATED {true} OPTIONAL -- Need N + } OPTIONAL, -- Need N + ..., + [[ + codebookTypeRequest-r16 SEQUENCE { + type1-SinglePanel-r16 ENUMERATED {true} OPTIONAL, -- Need N + type1-MultiPanel-r16 ENUMERATED {true} OPTIONAL, -- Need N + type2-r16 ENUMERATED {true} OPTIONAL, -- Need N + type2-PortSelection-r16 ENUMERATED {true} OPTIONAL -- Need N + } OPTIONAL, -- Need N + uplinkTxSwitchRequest-r16 ENUMERATED {true} OPTIONAL -- Need N + ]] +} + +-- TAG-UE-CAPABILITYREQUESTFILTERCOMMON-STOP +-- TAG-UE-CAPABILITYREQUESTFILTERNR-START + +UE-CapabilityRequestFilterNR ::= SEQUENCE { + frequencyBandListFilter FreqBandList OPTIONAL, -- Need N + nonCriticalExtension UE-CapabilityRequestFilterNR-v1540 OPTIONAL +} + +UE-CapabilityRequestFilterNR-v1540 ::= SEQUENCE { + srs-SwitchingTimeRequest ENUMERATED {true} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UE-CAPABILITYREQUESTFILTERNR-STOP +-- TAG-UE-MRDC-CAPABILITY-START + +UE-MRDC-Capability ::= SEQUENCE { + measAndMobParametersMRDC MeasAndMobParametersMRDC OPTIONAL, + phy-ParametersMRDC-v1530 Phy-ParametersMRDC OPTIONAL, + rf-ParametersMRDC RF-ParametersMRDC, + generalParametersMRDC GeneralParametersMRDC-XDD-Diff OPTIONAL, + fdd-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + featureSetCombinations SEQUENCE (SIZE (1..maxFeatureSetCombinations)) OF FeatureSetCombination OPTIONAL, + pdcp-ParametersMRDC-v1530 PDCP-ParametersMRDC OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UE-MRDC-Capability-v1560 OPTIONAL +} + +UE-MRDC-Capability-v1560 ::= SEQUENCE { + receivedFilters OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL, + measAndMobParametersMRDC-v1560 MeasAndMobParametersMRDC-v1560 OPTIONAL, + fdd-Add-UE-MRDC-Capabilities-v1560 UE-MRDC-CapabilityAddXDD-Mode-v1560 OPTIONAL, + tdd-Add-UE-MRDC-Capabilities-v1560 UE-MRDC-CapabilityAddXDD-Mode-v1560 OPTIONAL, + nonCriticalExtension UE-MRDC-Capability-v1610 OPTIONAL +} + +UE-MRDC-Capability-v1610 ::= SEQUENCE { + measAndMobParametersMRDC-v1610 MeasAndMobParametersMRDC-v1610 OPTIONAL, + generalParametersMRDC-v1610 GeneralParametersMRDC-v1610 OPTIONAL, + pdcp-ParametersMRDC-v1610 PDCP-ParametersMRDC-v1610 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-MRDC-CapabilityAddXDD-Mode ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff MeasAndMobParametersMRDC-XDD-Diff OPTIONAL, + generalParametersMRDC-XDD-Diff GeneralParametersMRDC-XDD-Diff OPTIONAL +} + +UE-MRDC-CapabilityAddXDD-Mode-v1560 ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff-v1560 MeasAndMobParametersMRDC-XDD-Diff-v1560 OPTIONAL +} + +UE-MRDC-CapabilityAddFRX-Mode ::= SEQUENCE { + measAndMobParametersMRDC-FRX-Diff MeasAndMobParametersMRDC-FRX-Diff +} + + +GeneralParametersMRDC-XDD-Diff ::= SEQUENCE { + splitSRB-WithOneUL-Path ENUMERATED {supported} OPTIONAL, + splitDRB-withUL-Both-MCG-SCG ENUMERATED {supported} OPTIONAL, + srb3 ENUMERATED {supported} OPTIONAL, + v2x-EUTRA ENUMERATED {supported} OPTIONAL, + ... +} + +GeneralParametersMRDC-v1610 ::= SEQUENCE { + f1c-OverEUTRA-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-UE-MRDC-CAPABILITY-STOP +-- TAG-UE-NR-CAPABILITY-START + +UE-NR-Capability ::= SEQUENCE { + accessStratumRelease AccessStratumRelease, + pdcp-Parameters PDCP-Parameters, + rlc-Parameters RLC-Parameters OPTIONAL, + mac-Parameters MAC-Parameters OPTIONAL, + phy-Parameters Phy-Parameters, + rf-Parameters RF-Parameters, + measAndMobParameters MeasAndMobParameters OPTIONAL, + fdd-Add-UE-NR-Capabilities UE-NR-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-NR-Capabilities UE-NR-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + featureSets FeatureSets OPTIONAL, + featureSetCombinations SEQUENCE (SIZE (1..maxFeatureSetCombinations)) OF FeatureSetCombination OPTIONAL, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1530 OPTIONAL +} + +UE-NR-Capability-v1530 ::= SEQUENCE { + fdd-Add-UE-NR-Capabilities-v1530 UE-NR-CapabilityAddXDD-Mode-v1530 OPTIONAL, + tdd-Add-UE-NR-Capabilities-v1530 UE-NR-CapabilityAddXDD-Mode-v1530 OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + interRAT-Parameters InterRAT-Parameters OPTIONAL, + inactiveState ENUMERATED {supported} OPTIONAL, + delayBudgetReporting ENUMERATED {supported} OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1540 OPTIONAL +} + +UE-NR-Capability-v1540 ::= SEQUENCE { + sdap-Parameters SDAP-Parameters OPTIONAL, + overheatingInd ENUMERATED {supported} OPTIONAL, + ims-Parameters IMS-Parameters OPTIONAL, + fr1-Add-UE-NR-Capabilities-v1540 UE-NR-CapabilityAddFRX-Mode-v1540 OPTIONAL, + fr2-Add-UE-NR-Capabilities-v1540 UE-NR-CapabilityAddFRX-Mode-v1540 OPTIONAL, + fr1-fr2-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1550 OPTIONAL +} + +UE-NR-Capability-v1550 ::= SEQUENCE { + reducedCP-Latency ENUMERATED {supported} OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1560 OPTIONAL +} + +UE-NR-Capability-v1560 ::= SEQUENCE { + nrdc-Parameters NRDC-Parameters OPTIONAL, + receivedFilters OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1570 OPTIONAL +} + +UE-NR-Capability-v1570 ::= SEQUENCE { + nrdc-Parameters-v1570 NRDC-Parameters-v1570 OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1610 OPTIONAL +} + +UE-NR-Capability-v1610 ::= SEQUENCE { + inDeviceCoexInd-r16 ENUMERATED {supported} OPTIONAL, + dl-DedicatedMessageSegmentation-r16 ENUMERATED {supported} OPTIONAL, + nrdc-Parameters-v1610 NRDC-Parameters-v1610 OPTIONAL, + powSav-Parameters-r16 PowSav-Parameters-r16 OPTIONAL, + fr1-Add-UE-NR-Capabilities-v1610 UE-NR-CapabilityAddFRX-Mode-v1610 OPTIONAL, + fr2-Add-UE-NR-Capabilities-v1610 UE-NR-CapabilityAddFRX-Mode-v1610 OPTIONAL, + bh-RLF-Indication-r16 ENUMERATED {supported} OPTIONAL, + directSN-AdditionFirstRRC-IAB-r16 ENUMERATED {supported} OPTIONAL, + bap-Parameters-r16 BAP-Parameters-r16 OPTIONAL, + referenceTimeProvision-r16 ENUMERATED {supported} OPTIONAL, + sidelinkParameters-r16 SidelinkParameters-r16 OPTIONAL, + highSpeedParameters-r16 HighSpeedParameters-r16 OPTIONAL, + mac-Parameters-v1610 MAC-Parameters-v1610 OPTIONAL, + mcgRLF-RecoveryViaSCG-r16 ENUMERATED {supported} OPTIONAL, + resumeWithStoredMCG-SCells-r16 ENUMERATED {supported} OPTIONAL, + resumeWithStoredSCG-r16 ENUMERATED {supported} OPTIONAL, + resumeWithSCG-Config-r16 ENUMERATED {supported} OPTIONAL, + ue-BasedPerfMeas-Parameters-r16 UE-BasedPerfMeas-Parameters-r16 OPTIONAL, + son-Parameters-r16 SON-Parameters-r16 OPTIONAL, + onDemandSIB-Connected-r16 ENUMERATED {supported} OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-NR-CapabilityAddXDD-Mode ::= SEQUENCE { + phy-ParametersXDD-Diff Phy-ParametersXDD-Diff OPTIONAL, + mac-ParametersXDD-Diff MAC-ParametersXDD-Diff OPTIONAL, + measAndMobParametersXDD-Diff MeasAndMobParametersXDD-Diff OPTIONAL +} + +UE-NR-CapabilityAddXDD-Mode-v1530 ::= SEQUENCE { + eutra-ParametersXDD-Diff EUTRA-ParametersXDD-Diff +} + +UE-NR-CapabilityAddFRX-Mode ::= SEQUENCE { + phy-ParametersFRX-Diff Phy-ParametersFRX-Diff OPTIONAL, + measAndMobParametersFRX-Diff MeasAndMobParametersFRX-Diff OPTIONAL +} + +UE-NR-CapabilityAddFRX-Mode-v1540 ::= SEQUENCE { + ims-ParametersFRX-Diff IMS-ParametersFRX-Diff OPTIONAL +} + +UE-NR-CapabilityAddFRX-Mode-v1610 ::= SEQUENCE { + powSav-ParametersFRX-Diff-r16 PowSav-ParametersFRX-Diff-r16 OPTIONAL, + mac-ParametersFRX-Diff-r16 MAC-ParametersFRX-Diff-r16 OPTIONAL +} + +BAP-Parameters-r16 ::= SEQUENCE { + flowControlBH-RLC-ChannelBased-r16 ENUMERATED {supported} OPTIONAL, + flowControlRouting-ID-Based-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-UE-NR-CAPABILITY-STOP +-- TAG-UNLICENSEDPARAMETERSPERBAND-START + +UnlicensedParametersPerBand-r16 ::= SEQUENCE { + -- R1 10-2g: SSB-based BFD/CBD for dynamic channel access mode + ssb-BFD-CBD-dynamicChannelAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2h: SSB-based BFD/CBD for semi-static channel access mode + ssb-BFD-CBD-semi-staticChannelAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2i: CSI-RS-based BFD/CBD for NR-U + csi-RS-BFD-CBD-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-10: RSSI and channel occupancy measurement and reporting + rssi-ChannelOccupancyReporting-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-11:SRS starting position at any OFDM symbol in a slot + srs-StartAnyOFDM-Symbol-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-20: Support search space set configuration with freqMonitorLocation-r16 + searchSpaceFreqMonitorLocation-r16 INTEGER (1..5) OPTIONAL, + -- R1 10-20a: Support coreset configuration with rb-Offset + coreset-RB-Offset-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-23:CGI reading on unlicensed cell for ANR functionality + cgi-Acquisition-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-25: Enable configured UL transmissions when DCI 2_0 is configured but not detected + configuredUL-Tx-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-8: Type B PDSCH length {3, 5, 6, 8, 9, 10, 11, 12, 13} without DMRS shift due to CRS collision + typeB-PDSCH-length-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9: Search space set group switching with explicit DCI 2_0 bit field trigger or with implicit PDCCH decoding with DCI 2_0 monitoring + searchSpaceSetGroupSwitchingwithDCI-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9b: Search space set group switching with implicit PDCCH decoding without DCI 2_0 monitoring FFS:per band or per UE + searchSpaceSetGroupSwitchingwithoutDCI-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9d: Support Search space set group switching capability 2 + searchSpaceSetGroupSwitchingcapability2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-14: Non-numerical PDSCH to HARQ-ACK timing + non-numericalPDSCH-HARQ-timing-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-15: Enhanced dynamic HARQ codebook + enhancedDynamicHARQ-codebook-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-16: One-shot HARQ ACK feedback + oneShotHARQ-feedback-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-17: Multi-PUSCH UL grant + multiPUSCH-UL-grant-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-26: CSI-RS based RLM for NR-U + csi-RS-RLM-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-26a: CSI-RS based RRM for NR-U + vcsi-RS-RRM-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-3: PRB interlace mapping for PUSCH + pusch-PRB-interlace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-3a: PRB interlace mapping for PUCCH + pucch-F0-F1-PRB-Interlace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-12: OCC for PRB interlace mapping for PF2 and PF3 + occ-PRB-PF2-PF3-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-13a: Extended CP range of more than one symbol for CG-PUSCH + extCP-rangeCG-PUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-18: Configured grant with retransmission in CG resources + configuredGrantWithReTx-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-24: CG-UCI multiplexing with HARQ ACK + mux-CG-UCI-HARQ-ACK-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-28: Configured grant with Rel-16 enhanced resource configuration + cg-resourceConfig-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-UNLICENSEDPARAMETERSPERBAND-STOP +-- TAG-ABSOLUTETIMEINFO-START + +AbsoluteTimeInfo-r16 ::= BIT STRING (SIZE (48)) + +-- TAG-ABSOLUTETIMEINFO-STOP +-- TAG-AREACONFIGURATION-START + +AreaConfiguration-r16 ::= SEQUENCE { + areaConfig-r16 AreaConfig-r16, + interFreqTargetList-r16 SEQUENCE(SIZE (1..maxFreq)) OF InterFreqTargetInfo-r16 OPTIONAL -- Need R +} + +AreaConfig-r16 ::= CHOICE { + cellGlobalIdList-r16 CellGlobalIdList-r16, + trackingAreaCodeList-r16 TrackingAreaCodeList-r16, + trackingAreaIdentityList-r16 TrackingAreaIdentityList-r16 +} + +InterFreqTargetInfo-r16 ::= SEQUENCE { + dl-CarrierFreq ARFCN-ValueNR, + cellList SEQUENCE (SIZE (1..32)) OF PhysCellId OPTIONAL +} + +CellGlobalIdList-r16 ::= SEQUENCE (SIZE (1..32)) OF CGI-Info-Logging-r16 + +TrackingAreaCodeList-r16 ::= SEQUENCE (SIZE (1..8)) OF TrackingAreaCode + +TrackingAreaIdentityList-r16 ::= SEQUENCE (SIZE (1..8)) OF TrackingAreaIdentity-r16 + +TrackingAreaIdentity-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + trackingAreaCode-r16 TrackingAreaCode +} + +-- TAG-AREACONFIGURATION-STOP +-- TAG-BTNAMELIST-START + +BT-NameList-r16 ::= SEQUENCE (SIZE (1..maxBT-Name-r16)) OF BT-Name-r16 + +BT-Name-r16 ::= OCTET STRING (SIZE (1..248)) + +-- TAG-BTNAMELIST-STOP +-- TAG-EUTRA-ALLOWEDMEASBANDWIDTH-START + +EUTRA-AllowedMeasBandwidth ::= ENUMERATED {mbw6, mbw15, mbw25, mbw50, mbw75, mbw100} + +-- TAG-EUTRA-ALLOWEDMEASBANDWIDTH-STOP +-- TAG-EUTRA-MBSFN-SUBFRAMECONFIGLIST-START + +EUTRA-MBSFN-SubframeConfigList ::= SEQUENCE (SIZE (1..maxMBSFN-Allocations)) OF EUTRA-MBSFN-SubframeConfig + +EUTRA-MBSFN-SubframeConfig ::= SEQUENCE { + radioframeAllocationPeriod ENUMERATED {n1, n2, n4, n8, n16, n32}, + radioframeAllocationOffset INTEGER (0..7), + subframeAllocation1 CHOICE { + oneFrame BIT STRING (SIZE(6)), + fourFrames BIT STRING (SIZE(24)) + }, + subframeAllocation2 CHOICE { + oneFrame BIT STRING (SIZE(2)), + fourFrames BIT STRING (SIZE(8)) + } OPTIONAL, -- Need R + ... +} + +-- TAG-EUTRA-MBSFN-SUBFRAMECONFIGLIST-STOP +-- TAG-EUTRA-MULTIBANDINFOLIST-START + +EUTRA-MultiBandInfoList ::= SEQUENCE (SIZE (1..maxMultiBands)) OF EUTRA-MultiBandInfo + +EUTRA-MultiBandInfo ::= SEQUENCE { + eutra-FreqBandIndicator FreqBandIndicatorEUTRA, + eutra-NS-PmaxList EUTRA-NS-PmaxList OPTIONAL -- Need R +} + +-- TAG-EUTRA-MULTIBANDINFOLIST-STOP +-- TAG-EUTRA-NS-PMAXLIST-START + +EUTRA-NS-PmaxList ::= SEQUENCE (SIZE (1..maxEUTRA-NS-Pmax)) OF EUTRA-NS-PmaxValue + +EUTRA-NS-PmaxValue ::= SEQUENCE { + additionalPmax INTEGER (-30..33) OPTIONAL, -- Need R + additionalSpectrumEmission INTEGER (1..288) OPTIONAL -- Need R +} + +-- TAG-EUTRA-NS-PMAXLIST-STOP +-- TAG-EUTRA-PHYSCELLID-START + +EUTRA-PhysCellId ::= INTEGER (0..503) + +-- TAG-EUTRA-PHYSCELLID-STOP +-- TAG-EUTRA-PHYSCELLIDRANGE-START + +EUTRA-PhysCellIdRange ::= SEQUENCE { + start EUTRA-PhysCellId, + range ENUMERATED {n4, n8, n12, n16, n24, n32, n48, n64, n84, n96, + n128, n168, n252, n504, spare2, spare1} OPTIONAL -- Need N +} + +-- TAG-EUTRA-PHYSCELLIDRANGE-STOP +-- TAG-EUTRA-PRESENCEANTENNAPORT1-START + +EUTRA-PresenceAntennaPort1 ::= BOOLEAN + +-- TAG-EUTRA-PRESENCEANTENNAPORT1-STOP +-- TAG-EUTRA-Q-OFFSETRANGE-START + +EUTRA-Q-OffsetRange ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-EUTRA-Q-OFFSETRANGE-STOP +-- TAG-IABIPADDRESS-START + +IAB-IP-Address-r16 ::= CHOICE { + iPv4-Address-r16 BIT STRING (SIZE(32)), + iPv6-Address-r16 BIT STRING (SIZE(128)), + iPv6-Prefix-r16 BIT STRING (SIZE(64)), + ... +} + +-- TAG-IABIPADDRESS-STOP +-- TAG-IABIPADDRESSINDEX-START + +IAB-IP-AddressIndex-r16 ::= INTEGER (1..maxIAB-IP-Address-r16) + +-- TAG-IABIPADDRESSINDEX-STOP +-- TAG-IAB-IP-USAGE-START + +IAB-IP-Usage-r16 ::= ENUMERATED {f1-c, f1-U, non-F1, spare} + +-- TAG-IAB-IP-USAGE-STOP +-- TAG-LOGGINGDURATION-START + +LoggingDuration-r16 ::= ENUMERATED { + min10, min20, min40, min60, min90, min120, spare2, spare1} + +-- TAG-LOGGINGDURATION-STOP +-- TAG-LOGGINGINTERVAL-START + +LoggingInterval-r16 ::= ENUMERATED { + ms320, ms640, ms1280, ms2560, ms5120, ms10240, ms20480, + ms30720, ms40960, ms61440 , infinity} + +-- TAG-LOGGINGINTERVAL-STOP +-- TAG-LOGMEASRESULTLISTBT-START + +LogMeasResultListBT-r16 ::= SEQUENCE (SIZE (1..maxBT-IdReport-r16)) OF LogMeasResultBT-r16 + +LogMeasResultBT-r16 ::= SEQUENCE { + bt-Addr-r16 BIT STRING (SIZE (48)), + rssi-BT-r16 INTEGER (-128..127) OPTIONAL, + ... +} + +-- TAG-LOGMEASRESULTLISTBT-STOP +-- TAG-LOGMEASRESULTLISTWLAN-START + +LogMeasResultListWLAN-r16 ::= SEQUENCE (SIZE (1..maxWLAN-Id-Report-r16)) OF LogMeasResultWLAN-r16 + +LogMeasResultWLAN-r16 ::= SEQUENCE { + wlan-Identifiers-r16 WLAN-Identifiers-r16, + rssiWLAN-r16 WLAN-RSSI-Range-r16 OPTIONAL, + rtt-WLAN-r16 WLAN-RTT-r16 OPTIONAL, + ... +} + +WLAN-Identifiers-r16 ::= SEQUENCE { + ssid-r16 OCTET STRING (SIZE (1..32)) OPTIONAL, + bssid-r16 OCTET STRING (SIZE (6)) OPTIONAL, + hessid-r16 OCTET STRING (SIZE (6)) OPTIONAL, + ... +} + +WLAN-RSSI-Range-r16 ::= INTEGER(0..141) + +WLAN-RTT-r16 ::= SEQUENCE { + rttValue-r16 INTEGER (0..16777215), + rttUnits-r16 ENUMERATED { + microseconds, + hundredsofnanoseconds, + tensofnanoseconds, + nanoseconds, + tenthsofnanoseconds, +... }, + rttAccuracy-r16 INTEGER (0..255) OPTIONAL, + ... +} + +-- TAG-OTHERCONFIG-START + +OtherConfig ::= SEQUENCE { + delayBudgetReportingConfig CHOICE{ + release NULL, + setup SEQUENCE{ + delayBudgetReportingProhibitTimer ENUMERATED {s0, s0dot4, s0dot8, s1dot6, s3, s6, s12, s30} + } + } OPTIONAL -- Need M +} + +OtherConfig-v1540 ::= SEQUENCE { + overheatingAssistanceConfig SetupRelease {OverheatingAssistanceConfig} OPTIONAL, -- Need M + ... +} +CandidateServingFreqListNR-r16 ::= SEQUENCE (SIZE (1..maxFreqIDC-r16)) OF ARFCN-ValueNR + +OtherConfig-v1610 ::= SEQUENCE { + idc-AssistanceConfig-r16 SetupRelease {IDC-AssistanceConfig-r16} OPTIONAL, -- Need M + drx-PreferenceConfig-r16 SetupRelease {DRX-PreferenceConfig-r16} OPTIONAL, -- Need M + maxBW-PreferenceConfig-r16 SetupRelease {MaxBW-PreferenceConfig-r16} OPTIONAL, -- Need M + maxCC-PreferenceConfig-r16 SetupRelease {MaxCC-PreferenceConfig-r16} OPTIONAL, -- Need M + maxMIMO-LayerPreferenceConfig-r16 SetupRelease {MaxMIMO-LayerPreferenceConfig-r16} OPTIONAL, -- Need M + minSchedulingOffsetPreferenceConfig-r16 SetupRelease {MinSchedulingOffsetPreferenceConfig-r16} OPTIONAL, -- Need M + releasePreferenceConfig-r16 SetupRelease {ReleasePreferenceConfig-r16} OPTIONAL, -- Need M + referenceTimePreferenceReporting-r16 ENUMERATED {true} OPTIONAL, -- Need R + btNameList-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + wlanNameList-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + sensorNameList-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, -- Need M + obtainCommonLocation-r16 ENUMERATED {true} OPTIONAL, -- Need R + sl-AssistanceConfigNR-r16 ENUMERATED{true} OPTIONAL -- Need R +} + +OverheatingAssistanceConfig ::= SEQUENCE { + overheatingIndicationProhibitTimer ENUMERATED {s0, s0dot5, s1, s2, s5, s10, s20, s30, + s60, s90, s120, s300, s600, spare3, spare2, spare1} +} + +IDC-AssistanceConfig-r16 ::= SEQUENCE { + candidateServingFreqListNR-r16 CandidateServingFreqListNR-r16 OPTIONAL, -- Need R + ... +} + +DRX-PreferenceConfig-r16 ::= SEQUENCE { + drx-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxBW-PreferenceConfig-r16 ::= SEQUENCE { + maxBW-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxCC-PreferenceConfig-r16 ::= SEQUENCE { + maxCC-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxMIMO-LayerPreferenceConfig-r16 ::= SEQUENCE { + maxMIMO-LayerPreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MinSchedulingOffsetPreferenceConfig-r16 ::= SEQUENCE { + minSchedulingOffsetPreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +ReleasePreferenceConfig-r16 ::= SEQUENCE { + releasePreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, infinity, spare1}, + connectedReporting ENUMERATED {true} OPTIONAL -- Need R +} + +-- TAG-OTHERCONFIG-STOP +-- TAG-PHYSCELLIDUTRA-FDD-START + +PhysCellIdUTRA-FDD-r16 ::= INTEGER (0..511) + +-- TAG-PHYSCELLIDUTRA-FDD-STOP +-- TAG-RRC-TRANSACTIONIDENTIFIER-START + +RRC-TransactionIdentifier ::= INTEGER (0..3) + +-- TAG-RRC-TRANSACTIONIDENTIFIER-STOP +-- TAG-SENSORNAMELIST-START + +Sensor-NameList-r16 ::= SEQUENCE { + measUncomBarPre-r16 ENUMERATED {true} OPTIONAL, -- Need R + measUeSpeed ENUMERATED {true} OPTIONAL, -- Need R + measUeOrientation ENUMERATED {true} OPTIONAL -- Need R +} + +-- TAG-SENSORNAMELIST-STOP +-- TAG-TRACEREFERENCE-START + +TraceReference-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + traceId-r16 OCTET STRING (SIZE (3)) +} + +-- TAG-TRACEREFERENCE-STOP +-- TAG-UEMeasurementsAvailable-START + +UEMeasurementsAvailable-r16 ::= SEQUENCE { + logMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableBT-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableWLAN-r16 ENUMERATED {true} OPTIONAL, + connEstFailInfoAvailable-r16 ENUMERATED {true} OPTIONAL, + rlf-InfoAvailable-r16 ENUMERATED {true} OPTIONAL, + ... +} + +-- TAG-UEMeasurementsAvailable-STOP +-- TAG-UTRA-FDD-Q-OFFSETRANGE-START + +UTRA-FDD-Q-OffsetRange-r16 ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-UTRA-FDD-Q-OFFSETRANGE-STOP +-- TAG-VISITEDCELLINFOLIST-START + +VisitedCellInfoList-r16 ::= SEQUENCE (SIZE (1..maxCellHistory-r16)) OF VisitedCellInfo-r16 + +VisitedCellInfo-r16 ::= SEQUENCE { + visitedCellId-r16 CHOICE { + nr-CellId-r16 CHOICE { + cgi-Info CGI-Info-Logging-r16, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 PhysCellId, + carrierFreq-r16 ARFCN-ValueNR + } + }, + eutra-CellId-r16 CHOICE { + cellGlobalId-r16 CGI-InfoEUTRA, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 EUTRA-PhysCellId, + carrierFreq-r16 ARFCN-ValueEUTRA + } + } + } OPTIONAL, + timeSpent-r16 INTEGER (0..4095), + ... +} + +-- TAG-VISITEDCELLINFOLIST-STOP +-- TAG-WLANNAMELIST-START + +WLAN-NameList-r16 ::= SEQUENCE (SIZE (1..maxWLAN-Name-r16)) OF WLAN-Name-r16 + +WLAN-Name-r16 ::= OCTET STRING (SIZE (1..32)) + +-- TAG-SL-BWP-CONFIG-START + +SL-BWP-Config-r16 ::= SEQUENCE { + sl-BWP-Id BWP-Id, + sl-BWP-Generic-r16 SL-BWP-Generic-r16 OPTIONAL, -- Need M + sl-BWP-PoolConfig-r16 SL-BWP-PoolConfig-r16 OPTIONAL, -- Need M + ... +} + +SL-BWP-Generic-r16 ::= SEQUENCE { + sl-BWP-r16 BWP OPTIONAL, -- Need M + sl-LengthSymbols-r16 ENUMERATED {sym7, sym8, sym9, sym10, sym11, sym12, sym13, sym14} OPTIONAL, -- Need M + sl-StartSymbol-r16 ENUMERATED {sym0, sym1, sym2, sym3, sym4, sym5, sym6, sym7} OPTIONAL, -- Need M + sl-PSBCH-Config-r16 SetupRelease {SL-PSBCH-Config-r16} OPTIONAL, -- Need M + sl-TxDirectCurrentLocation-r16 INTEGER (0..3301) OPTIONAL, -- Need M + ... +} + +-- TAG-SL-BWP-CONFIG-STOP +-- TAG-SL-BWP-CONFIGCOMMON-START + +SL-BWP-ConfigCommon-r16 ::= SEQUENCE { + sl-BWP-Generic-r16 SL-BWP-Generic-r16 OPTIONAL, -- Need R + sl-BWP-PoolConfigCommon-r16 SL-BWP-PoolConfigCommon-r16 OPTIONAL, -- Need R + ... +} + +-- TAG-SL-BWP-CONFIGCOMMON-STOP +-- TAG-SL-BWP-POOLCONFIG-START + +SL-BWP-PoolConfig-r16 ::= SEQUENCE { + sl-RxPool-r16 SEQUENCE (SIZE (1..maxNrofRXPool-r16)) OF SL-ResourcePool-r16 OPTIONAL, -- Cond HO + sl-TxPoolSelectedNormal-r16 SL-TxPoolDedicated-r16 OPTIONAL, -- Need M + sl-TxPoolScheduling-r16 SL-TxPoolDedicated-r16 OPTIONAL, -- Need N + sl-TxPoolExceptional-r16 SL-ResourcePoolConfig-r16 OPTIONAL -- Need M +} + +SL-TxPoolDedicated-r16 ::= SEQUENCE { + sl-PoolToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolID-r16 OPTIONAL, -- Need N + sl-PoolToAddModList-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolConfig-r16 OPTIONAL -- Need N +} + +SL-ResourcePoolConfig-r16 ::= SEQUENCE { + sl-ResourcePoolID-r16 SL-ResourcePoolID-r16, + sl-ResourcePool-r16 SL-ResourcePool-r16 OPTIONAL -- Need M +} + +SL-ResourcePoolID-r16 ::= INTEGER (1..maxNrofPoolID-r16) + +-- TAG-SL-BWP-POOLCONFIG-STOP +-- TAG-SL-BWP-POOLCONFIGCOMMON-START + +SL-BWP-PoolConfigCommon-r16 ::= SEQUENCE { + sl-RxPool-r16 SEQUENCE (SIZE (1..maxNrofRXPool-r16)) OF SL-ResourcePool-r16 OPTIONAL, -- Need R + sl-TxPoolSelectedNormal-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolConfig-r16 OPTIONAL, -- Need R + sl-TxPoolExceptional-r16 SL-ResourcePoolConfig-r16 OPTIONAL -- Need R +} + +-- TAG-SL-BWP-POOLCONFIGCOMMON-STOP +-- TAG-SL-CBR-PRIORITYTXCONFIGLIST-START + +SL-CBR-PriorityTxConfigList-r16 ::= SEQUENCE (SIZE (1..8)) OF SL-PriorityTxConfigIndex-r16 + +SL-PriorityTxConfigIndex-r16 ::= SEQUENCE { + sl-PriorityThreshold-r16 INTEGER (1..8) OPTIONAL, -- Need M + sl-DefaultTxConfigIndex-r16 INTEGER (0..maxCBR-Level-1-r16) OPTIONAL, -- Need M + sl-CBR-ConfigIndex-r16 INTEGER (0..maxCBR-Config-1-r16) OPTIONAL, -- Need M + sl-Tx-ConfigIndexList-r16 SEQUENCE (SIZE (1.. maxCBR-Level-r16)) OF SL-TxConfigIndex-r16 OPTIONAL -- Need M +} + +SL-TxConfigIndex-r16 ::= INTEGER (0..maxTxConfig-1-r16) + +-- TAG-SL-CBR-PRIORITYTXCONFIGLIST-STOP +-- TAG-SL-CBR-COMMONTXCONFIGLIST-START + +SL-CBR-CommonTxConfigList-r16 ::= SEQUENCE { + sl-CBR-RangeConfigList-r16 SEQUENCE (SIZE (1..maxCBR-Config-r16)) OF SL-CBR-LevelsConfig-r16 OPTIONAL, -- Need M + sl-CBR-PSSCH-TxConfigList-r16 SEQUENCE (SIZE (1.. maxTxConfig-r16)) OF SL-CBR-PSSCH-TxConfig-r16 OPTIONAL -- Need M +} + +SL-CBR-LevelsConfig-r16 ::= SEQUENCE (SIZE (1..maxCBR-Level-r16)) OF SL-CBR-r16 + +SL-CBR-PSSCH-TxConfig-r16 ::= SEQUENCE { + sl-CR-Limit-r16 INTEGER(0..10000) OPTIONAL, -- Need M + sl-TxParameters-r16 SL-PSSCH-TxParameters-r16 OPTIONAL -- Need M +} + +SL-CBR-r16 ::= INTEGER (0..100) + +-- TAG-SL-CBR-COMMONTXCONFIGLIST-STOP +-- TAG-SL-CONFIGDEDICATEDNR-START + +SL-ConfigDedicatedNR-r16 ::= SEQUENCE { + sl-PHY-MAC-RLC-Config-r16 SL-PHY-MAC-RLC-Config-r16 OPTIONAL, -- Need M + sl-RadioBearerToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SLRB-Uu-ConfigIndex-r16 OPTIONAL, -- Need N + sl-RadioBearerToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SL-RadioBearerConfig-r16 OPTIONAL, -- Need N + sl-MeasConfigInfoToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-DestinationIndex-r16 OPTIONAL, -- Need N + sl-MeasConfigInfoToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-MeasConfigInfo-r16 OPTIONAL, -- Need M + t400-r16 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000} OPTIONAL, -- Need M + ... +} + +SL-DestinationIndex-r16 ::= INTEGER (0..maxNrofSL-Dest-1-r16) + +SL-PHY-MAC-RLC-Config-r16::= SEQUENCE { + sl-ScheduledConfig-r16 SetupRelease { SL-ScheduledConfig-r16 } OPTIONAL, -- Need M + sl-UE-SelectedConfig-r16 SetupRelease { SL-UE-SelectedConfig-r16 } OPTIONAL, -- Need M + sl-FreqInfoToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-Freq-Id-r16 OPTIONAL, -- Need N + sl-FreqInfoToAddModList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-FreqConfig-r16 OPTIONAL, -- Need N + sl-RLC-BearerToReleaseList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfigIndex-r16 OPTIONAL, -- Need N + sl-RLC-BearerToAddModList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfig-r16 OPTIONAL, -- Need N + sl-MaxNumConsecutiveDTX-r16 ENUMERATED {n1, n2, n3, n4, n6, n8, n16, n32} OPTIONAL, -- Need M + sl-CSI-Acquisition-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + sl-CSI-SchedulingRequestId-r16 SetupRelease {SchedulingRequestId} OPTIONAL, -- Need M + sl-SSB-PriorityNR-r16 INTEGER (1..8) OPTIONAL, -- Need R + networkControlledSyncTx-r16 ENUMERATED {on, off} OPTIONAL -- Need M +} + +-- TAG-SL-CONFIGDEDICATEDNR-STOP +-- TAG-SL-CONFIGUREDGRANTCONFIG-START + +SL-ConfiguredGrantConfig-r16 ::= SEQUENCE { + sl-ConfigIndexCG-r16 SL-ConfigIndexCG-r16, + sl-PeriodCG-r16 SL-PeriodCG-r16 OPTIONAL, -- Need M + sl-NrOfHARQ-Processes-r16 INTEGER (1..16) OPTIONAL, -- Need M + sl-HARQ-ProcID-offset-r16 INTEGER (1..16) OPTIONAL, -- Need M + sl-CG-MaxTransNumList-r16 SL-CG-MaxTransNumList-r16 OPTIONAL, -- Need M + rrc-ConfiguredSidelinkGrant SEQUENCE { + sl-TimeResourceCG-Type1-r16 INTEGER (0..496) OPTIONAL, -- Need M + sl-StartSubchannelCG-Type1-r16 INTEGER (0..26) OPTIONAL, -- Need M + sl-FreqResourceCG-Type1-r16 INTEGER (0..6929) OPTIONAL, -- Need M + sl-TimeOffsetCG-Type1-r16 INTEGER (0..7999) OPTIONAL, -- Need R + sl-N1PUCCH-AN-r16 PUCCH-ResourceId OPTIONAL, -- Need M + sl-PSFCH-ToPUCCH-CG-Type1-r16 INTEGER (0..15) OPTIONAL -- Need M + } OPTIONAL, -- Need M + ... +} + +SL-ConfigIndexCG-r16 ::= INTEGER (1..maxNrofCG-SL-r16) + +SL-CG-MaxTransNumList-r16 ::= SEQUENCE (SIZE (1..8)) OF SL-CG-MaxTransNum-r16 + +SL-CG-MaxTransNum-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-MaxTransNum-r16 INTEGER (1..32) +} + +SL-PeriodCG-r16 ::= CHOICE{ + sl-PeriodCG1-r16 ENUMERATED {ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}, + sl-PeriodCG2-r16 INTEGER (1..99) +} + +-- TAG-SL-CONFIGUREDGRANTCONFIG-STOP +-- TAG-SL-DESTINATIONIDENTITY-START + +SL-DestinationIdentity-r16 ::= BIT STRING (SIZE (24)) + +-- TAG-SL-DESTINATIONIDENTITY-STOP +-- TAG-SL-FREQCONFIG-START + +SL-FreqConfig-r16 ::= SEQUENCE { + sl-Freq-Id-r16 SL-Freq-Id-r16, + sl-SCS-SpecificCarrierList-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + sl-AbsoluteFrequencyPointA-r16 ARFCN-ValueNR OPTIONAL, -- Need M + sl-AbsoluteFrequencySSB-r16 ARFCN-ValueNR OPTIONAL, -- Need R + frequencyShift7p5khzSL-r16 ENUMERATED {true} OPTIONAL, -- Cond V2X-SL-Shared + valueN-r16 INTEGER (-1..1), + sl-BWP-ToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF BWP-Id OPTIONAL, -- Need N + sl-BWP-ToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF SL-BWP-Config-r16 OPTIONAL, -- Need N + sl-SyncConfigList-r16 SL-SyncConfigList-r16 OPTIONAL, -- Need M + sl-SyncPriority-r16 ENUMERATED {gnss, gnbEnb} OPTIONAL -- Need M +} + +SL-Freq-Id-r16 ::= INTEGER (1.. maxNrofFreqSL-r16) + +-- TAG-SL-FREQCONFIG-STOP +-- TAG-SL-FREQCONFIGCOMMON-START + +SL-FreqConfigCommon-r16 ::= SEQUENCE { + sl-SCS-SpecificCarrierList-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + sl-AbsoluteFrequencyPointA-r16 ARFCN-ValueNR, + sl-AbsoluteFrequencySSB-r16 ARFCN-ValueNR OPTIONAL, -- Need R + frequencyShift7p5khzSL-r16 ENUMERATED {true} OPTIONAL, -- Cond V2X-SL-Shared + valueN-r16 INTEGER (-1..1), + sl-BWP-List-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF SL-BWP-ConfigCommon-r16 OPTIONAL, -- Need R + sl-SyncPriority-r16 ENUMERATED {gnss, gnbEnb} OPTIONAL, -- Need R + sl-NbAsSync-r16 BOOLEAN OPTIONAL, -- Need R + sl-SyncConfigList-r16 SL-SyncConfigList-r16 OPTIONAL, -- Need R + ... +} +-- TAG-SL-FREQCONFIGCOMMON-STOP +-- TAG-SL-LOGICALCHANNELCONFIG-START + +SL-LogicalChannelConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-PrioritisedBitRate-r16 ENUMERATED {kBps0, kBps8, kBps16, kBps32, kBps64, kBps128, kBps256, kBps512, + kBps1024, kBps2048, kBps4096, kBps8192, kBps16384, kBps32768, kBps65536, infinity}, + sl-BucketSizeDuration-r16 ENUMERATED {ms5, ms10, ms20, ms50, ms100, ms150, ms300, ms500, ms1000, + spare7, spare6, spare5, spare4, spare3,spare2, spare1}, + sl-ConfiguredGrantType1Allowed-r16 ENUMERATED {true} OPTIONAL, -- Need R + sl-HARQ-FeedbackEnabled-r16 ENUMERATED {enabled, disabled } OPTIONAL, -- Need R + sl-AllowedCG-List-r16 SEQUENCE (SIZE (0.. maxNrofCG-SL-r16-1)) OF SL-ConfigIndexCG-r16 + OPTIONAL, -- Need R + sl-AllowedSCS-List-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SubcarrierSpacing OPTIONAL, -- Need R + sl-MaxPUSCH-Duration-r16 ENUMERATED {ms0p02, ms0p04, ms0p0625, ms0p125, ms0p25, ms0p5, spare2, spare1} + OPTIONAL, -- Need R + sl-LogicalChannelGroup-r16 INTEGER (0..maxLCG-ID) OPTIONAL, -- Need R + sl-SchedulingRequestId-r16 SchedulingRequestId OPTIONAL, -- Need R + sl-LogicalChannelSR-DelayTimerApplied-r16 BOOLEAN OPTIONAL, -- Need R + ... +} +-- TAG-SL-LOGICALCHANNELCONFIG-STOP +-- TAG-SL-MEASCONFIGCOMMON-START + +SL-MeasConfigCommon-r16 ::= SEQUENCE { + sl-MeasObjectListCommon-r16 SL-MeasObjectList-r16 OPTIONAL, -- Need R + sl-ReportConfigListCommon-r16 SL-ReportConfigList-r16 OPTIONAL, -- Need R + sl-MeasIdListCommon-r16 SL-MeasIdList-r16 OPTIONAL, -- Need R + sl-QuantityConfigCommon-r16 SL-QuantityConfig-r16 OPTIONAL, -- Need R + ... +} + +-- TAG-SL-MEASCONFIGCOMMON-STOP +-- TAG-SL-MEASCONFIGINFO-START + +SL-MeasConfigInfo-r16 ::= SEQUENCE { + sl-DestinationIndex-r16 SL-DestinationIndex-r16, + sl-MeasConfig-r16 SL-MeasConfig-r16, + ... +} + +SL-MeasConfig-r16 ::= SEQUENCE { + sl-MeasObjectToRemoveList-r16 SL-MeasObjectToRemoveList-r16 OPTIONAL, -- Need N + sl-MeasObjectToAddModList-r16 SL-MeasObjectList-r16 OPTIONAL, -- Need N + sl-ReportConfigToRemoveList-r16 SL-ReportConfigToRemoveList-r16 OPTIONAL, -- Need N + sl-ReportConfigToAddModList-r16 SL-ReportConfigList-r16 OPTIONAL, -- Need N + sl-MeasIdToRemoveList-r16 SL-MeasIdToRemoveList-r16 OPTIONAL, -- Need N + sl-MeasIdToAddModList-r16 SL-MeasIdList-r16 OPTIONAL, -- Need N + sl-QuantityConfig-r16 SL-QuantityConfig-r16 OPTIONAL, -- Need M + ... +} + +SL-MeasObjectToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ObjectId-r16)) OF SL-MeasObjectId-r16 + +SL-ReportConfigToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ReportConfigId-r16)) OF SL-ReportConfigId-r16 + +SL-MeasIdToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF SL-MeasId-r16 + +-- TAG-SL-MEASCONFIGINFO-STOP +-- TAG-SL-MEASIDLIST-START + +SL-MeasIdList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF SL-MeasIdInfo-r16 + +SL-MeasIdInfo-r16 ::= SEQUENCE { + sl-MeasId-r16 SL-MeasId-r16, + sl-MeasObjectId-r16 SL-MeasObjectId-r16, + sl-ReportConfigId-r16 SL-ReportConfigId-r16, + ... +} + +SL-MeasId-r16 ::= INTEGER (1..maxNrofSL-MeasId-r16) + +-- TAG-SL-MEASIDLIST-STOP +-- TAG-SL-MEASOBJECTLIST-START + +SL-MeasObjectList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ObjectId-r16)) OF SL-MeasObjectInfo-r16 + +SL-MeasObjectInfo-r16 ::= SEQUENCE { + sl-MeasObjectId-r16 SL-MeasObjectId-r16, + sl-MeasObject-r16 SL-MeasObject-r16, + ... +} + +SL-MeasObjectId-r16 ::= INTEGER (1..maxNrofSL-ObjectId-r16) + +SL-MeasObject-r16 ::= SEQUENCE { + frequencyInfoSL-r16 ARFCN-ValueNR, + ... +} + +-- TAG-SL-MEASOBJECTLIST-STOP +-- TAG-SL-PDCP-CONFIG-START + +SL-PDCP-Config-r16 ::= SEQUENCE { + sl-DiscardTimer-r16 ENUMERATED {ms3, ms10, ms20, ms25, ms30, ms40, ms50, ms60, ms75, ms100, ms150, ms200, + ms250, ms300, ms500, ms750, ms1500, infinity} OPTIONAL, -- Cond Setup + sl-PDCP-SN-Size-r16 ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + sl-OutOfOrderDelivery ENUMERATED { true } OPTIONAL, -- Need R + ... +} + +-- TAG-SL-PDCP-CONFIG-STOP +-- TAG-SL-PSBCH-CONFIG-START + +SL-PSBCH-Config-r16 ::= SEQUENCE { + dl-P0-PSBCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + dl-Alpha-PSBCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need M + ... +} + +-- TAG-SL-PSBCH-CONFIG-STOP +-- TAG-SL-PSSCH-TXCONFIGLIST-START + +SL-PSSCH-TxConfigList-r16 ::= SEQUENCE (SIZE (1..maxPSSCH-TxConfig-r16)) OF SL-PSSCH-TxConfig-r16 + +SL-PSSCH-TxConfig-r16 ::= SEQUENCE { + sl-TypeTxSync-r16 SL-TypeTxSync-r16 OPTIONAL, -- Need R + sl-ThresUE-Speed-r16 ENUMERATED {kmph60, kmph80, kmph100, kmph120, + kmph140, kmph160, kmph180, kmph200}, + sl-ParametersAboveThres-r16 SL-PSSCH-TxParameters-r16, + sl-ParametersBelowThres-r16 SL-PSSCH-TxParameters-r16, + ... +} + + +SL-PSSCH-TxParameters-r16 ::= SEQUENCE { + sl-MinMCS-PSSCH-r16 INTEGER (0..27), + sl-MaxMCS-PSSCH-r16 INTEGER (0..31), + sl-MinSubChannelNumPSSCH-r16 INTEGER (1..27), + sl-MaxSubchannelNumPSSCH-r16 INTEGER (1..27), + sl-MaxTxTransNumPSSCH-r16 INTEGER (1..32), + sl-MaxTxPower-r16 SL-TxPower-r16 OPTIONAL -- Cond CBR +} + +-- TAG-SL-PSSCH-TXCONFIGLIST-STOP +-- TAG-SL-QOS-FLOWIDENTITY-START + +SL-QoS-FlowIdentity-r16 ::= INTEGER (1..maxNrofSL-QFIs-r16) + +-- TAG-SL-QOS-FLOWIDENTITY-STOP +-- TAG-SL-QOS-PROFILE-START + +SL-QoS-Profile-r16 ::= SEQUENCE { + sl-PQI-r16 SL-PQI-r16 OPTIONAL, -- Need R + sl-GFBR-r16 INTEGER (0..4000000000) OPTIONAL, -- Need R + sl-MFBR-r16 INTEGER (0..4000000000) OPTIONAL, -- Need R + sl-Range-r16 INTEGER (1..1000) OPTIONAL, -- Need R + ... +} + +SL-PQI-r16 ::= CHOICE { + sl-StandardizedPQI-r16 INTEGER (0..255), + sl-Non-StandardizedPQI-r16 SEQUENCE { + sl-ResourceType-r16 ENUMERATED {gbr, non-GBR, delayCriticalGBR, spare1} OPTIONAL, -- Need R + sl-PriorityLevel-r16 INTEGER (1..8) OPTIONAL, -- Need R + sl-PacketDelayBudget-r16 INTEGER (0..1023) OPTIONAL, -- Need R + sl-PacketErrorRate-r16 INTEGER (0..9) OPTIONAL, -- Need R + sl-AveragingWindow-r16 INTEGER (0..4095) OPTIONAL, -- Need R + sl-MaxDataBurstVolume-r16 INTEGER (0..4095) OPTIONAL, -- Need R + ... + } +} + +-- TAG-SL-QOS-PROFILE-STOP +-- TAG-SL-QUANTITYCONFIG-START + +SL-QuantityConfig-r16 ::= SEQUENCE { + sl-FilterCoefficientDMRS-r16 FilterCoefficient DEFAULT fc4, + ... +} + +-- TAG-SL-QuantityConfig-STOP +-- TAG-SL-RADIOBEARERCONFIG-START + +SL-RadioBearerConfig-r16 ::= SEQUENCE { + slrb-Uu-ConfigIndex-r16 SLRB-Uu-ConfigIndex-r16, + sl-SDAP-Config-r16 SL-SDAP-Config-r16 OPTIONAL, -- Cond SLRBSetup + sl-PDCP-Config-r16 SL-PDCP-Config-r16 OPTIONAL, -- Cond SLRBSetup + sl-TransRange-r16 ENUMERATED {m20, m50, m80, m100, m120, m150, m180, m200, m220, m250, m270, m300, m350, m370, + m400, m420, m450, m480, m500, m550, m600, m700, m1000, spare9, spare8, spare7, spare6, + spare5, spare4, spare3, spare2, spare1} OPTIONAL, -- Need R + ... +} + +-- TAG-SL-RADIOBEARERCONFIG-STOP +-- TAG-SL-REPORTCONFIGLIST-START + +SL-ReportConfigList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ReportConfigId-r16)) OF SL-ReportConfigInfo-r16 + +SL-ReportConfigInfo-r16 ::= SEQUENCE { + sl-ReportConfigId-r16 SL-ReportConfigId-r16, + sl-ReportConfig-r16 SL-ReportConfig-r16, + ... +} + +SL-ReportConfigId-r16 ::= INTEGER (1..maxNrofSL-ReportConfigId-r16) + +SL-ReportConfig-r16 ::= SEQUENCE { + sl-ReportType-r16 CHOICE { + sl-Periodical-r16 SL-PeriodicalReportConfig-r16, + sl-EventTriggered-r16 SL-EventTriggerConfig-r16, + ... + }, + ... +} + +SL-PeriodicalReportConfig-r16 ::= SEQUENCE { + sl-ReportInterval-r16 ReportInterval, + sl-ReportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + sl-ReportQuantity-r16 SL-MeasReportQuantity-r16, + sl-RS-Type-r16 SL-RS-Type-r16, + ... +} + +SL-EventTriggerConfig-r16 ::= SEQUENCE { + sl-EventId-r16 CHOICE { + eventS1-r16 SEQUENCE { + s1-Threshold-r16 SL-MeasTriggerQuantity-r16, + sl-ReportOnLeave-r16 BOOLEAN, + sl-Hysteresis-r16 Hysteresis, + sl-TimeToTrigger-r16 TimeToTrigger, + ... + }, + eventS2-r16 SEQUENCE { + s2-Threshold-r16 SL-MeasTriggerQuantity-r16, + sl-ReportOnLeave-r16 BOOLEAN, + sl-Hysteresis-r16 Hysteresis, + sl-TimeToTrigger-r16 TimeToTrigger, + ... + }, + ... + }, + sl-ReportInterval-r16 ReportInterval, + sl-ReportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + sl-ReportQuantity-r16 SL-MeasReportQuantity-r16, + sl-RS-Type-r16 SL-RS-Type-r16, + ... +} + +SL-MeasReportQuantity-r16 ::= CHOICE { + sl-RSRP-r16 RSRP-Range, + ... +} + +SL-MeasTriggerQuantity-r16 ::= CHOICE { + sl-RSRP-r16 RSRP-Range, + ... +} + +SL-RS-Type-r16 ::= ENUMERATED {dmrs, spare3, spare2, spare1} + +-- TAG-SL-REPORTCONFIGLIST-STOP +-- TAG-SL-RESOURCEPOOL-START + +SL-ResourcePool-r16 ::= SEQUENCE { + sl-PSCCH-Config-r16 SetupRelease { SL-PSCCH-Config-r16 } OPTIONAL, -- Need M + sl-PSSCH-Config-r16 SetupRelease { SL-PSSCH-Config-r16 } OPTIONAL, -- Need M + sl-PSFCH-Config-r16 SetupRelease { SL-PSFCH-Config-r16 } OPTIONAL, -- Need M + sl-SyncAllowed-r16 SL-SyncAllowed-r16 OPTIONAL, -- Need M + sl-SubchannelSize-r16 ENUMERATED {n10, n12, n15, n20, n25, n50, n75, n100} OPTIONAL, -- Need M + sl-TimeResource-r16 INTEGER (10..160) OPTIONAL, -- Need M + sl-StartRB-Subchannel-r16 INTEGER (0..265) OPTIONAL, -- Need M + sl-NumSubchannel-r16 INTEGER (1..27) OPTIONAL, -- Need M + sl-Additional-MCS-Table-r16 ENUMERATED {qam256, qam64LowSE, qam256-qam64LowSE } OPTIONAL, -- Need M + sl-ThreshS-RSSI-CBR-r16 INTEGER (0..45) OPTIONAL, -- Need M + sl-TimeWindowSizeCBR-r16 ENUMERATED {ms100, slot100} OPTIONAL, -- Need M + sl-TimeWindowSizeCR-r16 ENUMERATED {ms1000, slot1000} OPTIONAL, -- Need M + sl-PTRS-Config-r16 SL-PTRS-Config-r16 OPTIONAL, -- Need M + sl-UE-SelectedConfigRP-r16 SL-UE-SelectedConfigRP-r16 OPTIONAL, -- Need M + sl-RxParametersNcell-r16 SEQUENCE { + sl-TDD-Configuration-r16 TDD-UL-DL-ConfigCommon OPTIONAL, -- Need M + sl-SyncConfigIndex-r16 INTEGER (0..15) + } OPTIONAL, -- Need M + sl-ZoneConfigMCR-List-r16 SEQUENCE (SIZE (16)) OF SL-ZoneConfigMCR-r16 OPTIONAL, -- Need M + sl-FilterCoefficient-r16 FilterCoefficient OPTIONAL, -- Need M + sl-RB-Number-r16 INTEGER (10..275) OPTIONAL, -- Need M + sl-PreemptionEnable-r16 ENUMERATED {enabled, pl1, pl2, pl3, pl4, pl5, pl6, pl7, pl8} OPTIONAL, -- Need R + sl-PriorityThreshold-UL-URLLC-r16 INTEGER (1..9) OPTIONAL, -- Need M + sl-PriorityThreshold-r16 INTEGER (1..9) OPTIONAL, -- Need M + sl-X-Overhead-r16 ENUMERATED {n0,n3, n6, n9} OPTIONAL, -- Need M + sl-PowerControl-r16 SL-PowerControl-r16 OPTIONAL, -- Need M + sl-TxPercentageList-r16 SL-TxPercentageList-r16 OPTIONAL, -- Need M + sl-MinMaxMCS-List-r16 SL-MinMaxMCS-List-r16 OPTIONAL, -- Need M +... +} + +SL-ZoneConfigMCR-r16 ::= SEQUENCE { + sl-ZoneConfigMCR-Index-r16 INTEGER (0..15), + sl-TransRange-r16 ENUMERATED {m20, m50, m80, m100, m120, m150, m180, m200, m220, m250, m270, m300, m350, + m370, m400, m420, m450, m480, m500, m550, m600, m700, m1000, spare8, spare7, + spare6, spare5, spare4, spare3, spare2, spare1} OPTIONAL, -- Need M + sl-ZoneConfig-r16 SL-ZoneConfig-r16 OPTIONAL, -- Need M +... +} + +SL-SyncAllowed-r16 ::= SEQUENCE { + gnss-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R + gnbEnb-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R + ue-Sync-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +SL-PSCCH-Config-r16 ::= SEQUENCE { + sl-TimeResourcePSCCH-r16 ENUMERATED {n2, n3} OPTIONAL, -- Need M + sl-FreqResourcePSCCH-r16 ENUMERATED {n10,n12, n15, n20, n25} OPTIONAL, -- Need M + sl-DMRS-ScrambleID-r16 INTEGER (0..65535) OPTIONAL, -- Need M + sl-NumReservedBits-r16 INTEGER (2..4) OPTIONAL, -- Need M + ... +} + +SL-PSSCH-Config-r16 ::= SEQUENCE { + sl-PSSCH-DMRS-TimePatternList-r16 SEQUENCE (SIZE (1..3)) OF INTEGER (2..4) OPTIONAL, -- Need M + sl-BetaOffsets2ndSCI-r16 SEQUENCE (SIZE (4)) OF SL-BetaOffsets-r16 OPTIONAL, -- Need M + sl-Scaling-r16 ENUMERATED {f0p5, f0p65, f0p8, f1} OPTIONAL, -- Need M + ... +} + +SL-PSFCH-Config-r16 ::= SEQUENCE { + sl-PSFCH-Period-r16 ENUMERATED {sl0, sl1, sl2, sl4} OPTIONAL, -- Need M + sl-PSFCH-RB-Set-r16 BIT STRING (SIZE (10..275)) OPTIONAL, -- Need M + sl-NumMuxCS-Pair-r16 ENUMERATED {n1, n2, n3, n6} OPTIONAL, -- Need M + sl-MinTimeGapPSFCH-r16 ENUMERATED {sl2, sl3} OPTIONAL, -- Need M + sl-PSFCH-HopID-r16 INTEGER (0..1023) OPTIONAL, -- Need M + sl-PSFCH-CandidateResourceType-r16 ENUMERATED {startSubCH, allocSubCH} OPTIONAL, -- Need M + ... +} +SL-PTRS-Config-r16 ::= SEQUENCE { + sl-PTRS-FreqDensity-r16 SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need M + sl-PTRS-TimeDensity-r16 SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need M + sl-PTRS-RE-Offset-r16 ENUMERATED {offset01, offset10, offset11} OPTIONAL, -- Need M + ... +} + +SL-UE-SelectedConfigRP-r16 ::= SEQUENCE { + sl-CBR-PriorityTxConfigList-r16 SL-CBR-PriorityTxConfigList-r16 OPTIONAL, -- Need M + sl-ThresPSSCH-RSRP-List-r16 SL-ThresPSSCH-RSRP-List-r16 OPTIONAL, -- Need M + sl-MultiReserveResource-r16 ENUMERATED {enabled} OPTIONAL, -- Need M + sl-MaxNumPerReserve-r16 ENUMERATED {n2, n3} OPTIONAL, -- Need M + sl-SensingWindow-r16 ENUMERATED {ms100, ms1100} OPTIONAL, -- Need M + sl-SelectionWindowList-r16 SL-SelectionWindowList-r16 OPTIONAL, -- Need M + sl-ResourceReservePeriodList-r16 SEQUENCE (SIZE (1..16)) OF SL-ResourceReservePeriod-r16 OPTIONAL, -- Need M + sl-RS-ForSensing-r16 ENUMERATED {pscch, pssch}, + ... +} + +SL-ResourceReservePeriod-r16 ::= CHOICE { + sl-ResourceReservePeriod1-r16 ENUMERATED {ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}, + sl-ResourceReservePeriod2-r16 INTEGER (1..99) +} + +SL-SelectionWindowList-r16 ::= SEQUENCE (SIZE (8)) OF SL-SelectionWindowConfig-r16 + +SL-SelectionWindowConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-SelectionWindow-r16 ENUMERATED {n1, n5, n10, n20} +} + +SL-TxPercentageList-r16 ::= SEQUENCE (SIZE (8)) OF SL-TxPercentageConfig-r16 + +SL-TxPercentageConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-TxPercentage-r16 ENUMERATED {p20, p35, p50} +} + +SL-MinMaxMCS-List-r16 ::= SEQUENCE (SIZE (1..3)) OF SL-MinMaxMCS-Config-r16 + +SL-MinMaxMCS-Config-r16 ::= SEQUENCE { + sl-MCS-Table-r16 ENUMERATED {qam64, qam256, qam64LowSE}, + sl-MinMCS-PSSCH-r16 INTEGER (0..27), + sl-MaxMCS-PSSCH-r16 INTEGER (0..31) +} + +SL-BetaOffsets-r16 ::= INTEGER (0..31) + +SL-PowerControl-r16 ::= SEQUENCE { + sl-MaxTransPower-r16 INTEGER (-30..33), + sl-Alpha-PSSCH-PSCCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need M + dl-Alpha-PSSCH-PSCCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need M + sl-P0-PSSCH-PSCCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + dl-P0-PSSCH-PSCCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + dl-Alpha-PSFCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need M + dl-P0-PSFCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + ... +} + +-- TAG-SL-RESOURCEPOOL-STOP +-- TAG-SL-RLC-BEARERCONFIG-START + +SL-RLC-BearerConfig-r16 ::= SEQUENCE { + sl-RLC-BearerConfigIndex-r16 SL-RLC-BearerConfigIndex-r16, + sl-ServedRadioBearer-r16 SLRB-Uu-ConfigIndex-r16 OPTIONAL, -- Cond LCH-SetupOnly + sl-RLC-Config-r16 SL-RLC-Config-r16 OPTIONAL, -- Cond LCH-Setup + sl-MAC-LogicalChannelConfig-r16 SL-LogicalChannelConfig-r16 OPTIONAL, -- Cond LCH-Setup + ... +} + +-- TAG-SL-RLC-BEARERCONFIG-STOP +-- TAG-SL-RLC-BEARERCONFIGINDEX-START + +SL-RLC-BearerConfigIndex-r16 ::= INTEGER (1..maxSL-LCID-r16) + +-- TAG-RLC-BEARERCONFIGINDEX-STOP +-- TAG-SL-RLC-CONFIG-START + +SL-RLC-Config-r16 ::= CHOICE { + sl-AM-RLC-r16 SEQUENCE { + sl-SN-FieldLengthAM-r16 SN-FieldLengthAM OPTIONAL, -- Cond SLRBSetup + sl-T-PollRetransmit-r16 T-PollRetransmit, + sl-PollPDU-r16 PollPDU, + sl-PollByte-r16 PollByte, + sl-MaxRetxThreshold-r16 ENUMERATED { t1, t2, t3, t4, t6, t8, t16, t32 }, + ... + }, + sl-UM-RLC-r16 SEQUENCE { + sl-SN-FieldLengthUM-r16 SN-FieldLengthUM OPTIONAL, -- Cond SLRBSetup + ... + }, + ... +} + +-- TAG-SL-RLC-CONFIG-STOP +-- TAG-SL-SCHEDULEDCONFIG-START + +SL-ScheduledConfig-r16 ::= SEQUENCE { + sl-RNTI-r16 RNTI-Value, + mac-MainConfigSL-r16 MAC-MainConfigSL-r16 OPTIONAL, -- Need M + sl-Timing-Config-r16 SL-TimingConfig-r16 OPTIONAL, -- Need M + sl-CS-RNTI-r16 RNTI-Value OPTIONAL, -- Need M + sl-PSFCH-ToPUCCH-r16 SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) OPTIONAL, -- Need M + sl-ConfiguredGrantConfigList-r16 SL-ConfiguredGrantConfigList-r16 OPTIONAL, -- Need M + ... +} + +MAC-MainConfigSL-r16 ::= SEQUENCE { + sl-BSR-Config-r16 BSR-Config OPTIONAL, -- Need M + ul-PrioritizationThres-r16 INTEGER (1..16) OPTIONAL, -- Need M + sl-PrioritizationThres-r16 INTEGER (1..8) OPTIONAL, -- Need M + ... + +} + +SL-TimingConfig-r16 ::= SEQUENCE { + sl-DCI-ToSL-Trans-r16 ENUMERATED{ffs} OPTIONAL, -- Need M + ... +} + +SL-ConfiguredGrantConfigList-r16 ::= SEQUENCE { + sl-ConfiguredGrantConfigToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofCG-SL-r16)) OF SL-ConfigIndexCG-r16 OPTIONAL, -- Need N + sl-ConfiguredGrantConfigToAddModList-r16 SEQUENCE (SIZE (1..maxNrofCG-SL-r16)) OF SL-ConfiguredGrantConfig-r16 OPTIONAL -- Need N +} + +-- TAG-SL-SCHEDULEDCONFIG-STOP +-- TAG-SL-SDAP-CONFIG-START + +SL-SDAP-Config-r16 ::= SEQUENCE { + sl-SDAP-Header-r16 ENUMERATED {present, absent}, + sl-DefaultRB-r16 BOOLEAN, + sl-MappedQoS-Flows-r16 CHOICE { + sl-MappedQoS-FlowsList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-Profile-r16, + sl-MappedQoS-FlowsListDedicated-r16 SL-MappedQoS-FlowsListDedicated-r16 + } OPTIONAL, -- Need M + sl-CastType-r16 ENUMERATED {broadcast, groupcast, unicast, spare1} OPTIONAL, -- Need M + ... +} + +SL-MappedQoS-FlowsListDedicated-r16 ::= SEQUENCE { + sl-MappedQoS-FlowsToAddList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-FlowIdentity-r16 OPTIONAL, -- Need N + sl-MappedQoS-FlowsToReleaseList-16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-FlowIdentity-r16 OPTIONAL -- Need N +} + +-- TAG-SL-SDAP-CONFIG-STOP +-- TAG-SL-SYNCCONFIG-START + +SL-SyncConfigList-r16 ::= SEQUENCE (SIZE (1..maxSL-SyncConfig-r16)) OF SL-SyncConfig-r16 + +SL-SyncConfig-r16 ::= SEQUENCE { + sl-SyncRefMinHyst-r16 ENUMERATED {dB0, dB3, dB6, dB9, dB12} OPTIONAL, -- Need R + sl-SyncRefDiffHyst-r16 ENUMERATED {dB0, dB3, dB6, dB9, dB12, dBinf} OPTIONAL, -- Need R + sl-filterCoefficient-r16 FilterCoefficient OPTIONAL, -- Need R + sl-SSB-TimeAllocation1-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSB-TimeAllocation2-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSB-TimeAllocation3-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSID-r16 INTEGER (0..671) OPTIONAL, -- Need R + txParameters-r16 SEQUENCE { + syncTxThreshIC-r16 SL-RSRP-Range-r16 OPTIONAL, -- Need R + syncTxThreshOoC-r16 SL-RSRP-Range-r16 OPTIONAL, -- Need R + syncInfoReserved-r16 BIT STRING (SIZE (2)) OPTIONAL -- Need R + }, + gnss-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R +... +} + +SL-RSRP-Range-r16 ::= INTEGER (0..13) + +SL-SSB-TimeAllocation-r16 ::= SEQUENCE { + sl-NumSSB-WithinPeriod-r16 ENUMERATED {n1, n2, n4, n5, n16, n32, n64} OPTIONAL, -- Need R + sl-TimeOffsetSSB-r16 INTEGER (0..1279) OPTIONAL, -- Need R + sl-TimeInterval-r16 INTEGER (0..639) OPTIONAL -- Need R +} + +-- TAG-SL-SYNCCONFIG-STOP +-- TAG-SL-THRESPSSCH-RSRP-LIST-START + +SL-ThresPSSCH-RSRP-List-r16 ::= SEQUENCE (SIZE (64)) OF SL-ThresPSSCH-RSRP-r16 + +SL-ThresPSSCH-RSRP-r16 ::= INTEGER (0..66) + +-- TAG-SL-THRESPSSCH-RSRP-LIST-STOP +-- TAG-SL-TXPOWER-START + +SL-TxPower-r16 ::= CHOICE{ + minusinfinity-r16 NULL, + txPower-r16 INTEGER (-30..33) +} + +-- TAG-SL-TXPOWER-STOP +-- TAG-SL-TYPETXSYNC-START + +SL-TypeTxSync-r16 ::= ENUMERATED {gnss, gnbEnb, ue} + +-- TAG-SL-TYPETXSYNC-STOP +-- TAG-SL-UE-SELECTEDCONFIG-START + +SL-UE-SelectedConfig-r16 ::= SEQUENCE { + sl-PSSCH-TxConfigList-r16 SL-PSSCH-TxConfigList-r16 OPTIONAL, -- Need R + sl-ProbResourceKeep-r16 ENUMERATED {v0, v0dot2, v0dot4, v0dot6, v0dot8} OPTIONAL, -- Need R + sl-ReselectAfter-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n7, n8, n9} OPTIONAL, -- Need R + sl-CBR-CommonTxConfigList-r16 SL-CBR-CommonTxConfigList-r16 OPTIONAL, -- Need R + ul-PrioritizationThres-r16 INTEGER (1..16) OPTIONAL, -- Need R + sl-PrioritizationThres-r16 INTEGER (1..8) OPTIONAL, -- Need R + ... +} + +-- TAG-SL-UE-SELECTEDCONFIG-STOP +-- TAG-SL-ZONECONFIG-START + +SL-ZoneConfig-r16 ::= SEQUENCE { + sl-ZoneLength-r16 ENUMERATED { m5, m10, m20, m30, m40, m50, spare2, spare1}, + ... +} + +-- TAG-SL-ZONECONFIG-STOP +-- TAG-SLRB-UU-CONFIGINDEX-START + +SLRB-Uu-ConfigIndex-r16 ::= INTEGER (1..maxNrofSLRB-r16) + +-- TAG-SLRB-UU-CONFIGINDEX-STOP +-- TAG-MULTIPLICITY-AND-TYPE-CONSTRAINT-DEFINITIONS-START + +maxAI-DCI-PayloadSize-r16 INTEGER ::= 128 --Maximum size of the DCI payload scrambled with ai-RNTI +maxAI-DCI-PayloadSize-r16-1 INTEGER ::= 127 --Maximum size of the DCI payload scrambled with ai-RNTI minus 1 +maxBandComb INTEGER ::= 65536 -- Maximum number of DL band combinations +maxBandsUTRA-FDD-r16 INTEGER ::= 64 -- Maximum number of bands listed in UTRA-FDD UE caps +maxBH-RLC-ChannelID-r16 INTEGER ::= 65536 -- Maximum value of BH RLC Channel ID +maxBT-IdReport-r16 INTEGER ::= 32 -- Maximum number of Bluetooth IDs to report +maxBT-Name-r16 INTEGER ::= 4 -- Maximum number of Bluetooth name +maxCAG-Cell-r16 INTEGER ::= 16 -- Maximum number of NR CAG cell ranges in SIB3, SIB4 +maxCBR-Config-r16 INTEGER ::= 8 -- Maximum number of CBR range configurations for sidelink communication + -- congestion control +maxCBR-Config-1-r16 INTEGER ::= 7 -- Maximum number of CBR range configurations for sidelink communication + -- congestion control minus 1 +maxCBR-Level-r16 INTEGER ::= 16 -- Maximum nuber of CBR levels +maxCBR-Level-1-r16 INTEGER ::= 15 -- Maximum number of CBR levels minus 1 +maxCellBlack INTEGER ::= 16 -- Maximum number of NR blacklisted cell ranges in SIB3, SIB4 +maxCellHistory-r16 INTEGER ::= 16 -- Maximum number of visited cells reported +maxCellInter INTEGER ::= 16 -- Maximum number of inter-Freq cells listed in SIB4 +maxCellIntra INTEGER ::= 16 -- Maximum number of intra-Freq cells listed in SIB3 +maxCellMeasEUTRA INTEGER ::= 32 -- Maximum number of cells in E-UTRAN +maxCellMeasIdle-r16 INTEGER ::= 8 -- Maximum number of cells per carrier for idle/inactive measurements +maxCellMeasUTRA-FDD-r16 INTEGER ::= 32 -- Maximum number of cells in FDD UTRAN +maxCellWhite INTEGER ::= 16 -- Maximum number of NR whitelisted cell ranges in SIB3, SIB4 +maxEARFCN INTEGER ::= 262143 -- Maximum value of E-UTRA carrier frequency +maxEUTRA-CellBlack INTEGER ::= 16 -- Maximum number of E-UTRA blacklisted physical cell identity ranges + -- in SIB5 +maxEUTRA-NS-Pmax INTEGER ::= 8 -- Maximum number of NS and P-Max values per band +maxLogMeasReport-r16 INTEGER ::= 520 -- Maximum number of entries for logged measurements +maxMultiBands INTEGER ::= 8 -- Maximum number of additional frequency bands that a cell belongs to +maxNARFCN INTEGER ::= 3279165 -- Maximum value of NR carrier frequency +maxNR-NS-Pmax INTEGER ::= 8 -- Maximum number of NS and P-Max values per band +maxFreqIdle-r16 INTEGER ::= 8 -- Maximum number of carrier frequencies for idle/inactive measurements +maxNrofServingCells INTEGER ::= 32 -- Max number of serving cells (SpCells + SCells) +maxNrofServingCells-1 INTEGER ::= 31 -- Max number of serving cells (SpCell + SCells) per cell group +maxNrofAggregatedCellsPerCellGroup INTEGER ::= 16 +maxNrofDUCells-r16 INTEGER ::= 512 -- Max number of cells configured on the collocated IAB-DU +maxNrofAssociatedDUCellsPerMT-r16 INTEGER ::= 65535 +maxNrofAvailabilityCombinationsPerSet-r16 INTEGER ::= 512 -- Max number of AvailabilityCombinationId used in the DCI format 2_5 +maxNrofAvailabilityCombinationsPerSet-r16-1 INTEGER ::= 511 -- Max number of AvailabilityCombinationId used in the DCI format 2_5 minus 1 +maxNrofSCells INTEGER ::= 31 -- Max number of secondary serving cells per cell group +maxNrofCellMeas INTEGER ::= 32 -- Maximum number of entries in each of the cell lists in a measurement object +maxNrofCG-SL-r16 INTEGER ::= 8 -- Max number of sidelink configured grant +maxNrofCG-SL-r16-1 INTEGER ::= 7 -- Max number of sidelink configured grant minus 1 +maxNrofSS-BlocksToAverage INTEGER ::= 16 -- Max number for the (max) number of SS blocks to average to determine cell measurement +maxNrofCondCells-r16 INTEGER ::= 8 -- Max number of conditional candidate SpCells +maxNrofCSI-RS-ResourcesToAverage INTEGER ::= 16 -- Max number for the (max) number of CSI-RS to average to determine cell measurement +maxNrofDL-Allocations INTEGER ::= 16 -- Maximum number of PDSCH time domain resource allocations +maxNrofSR-ConfigPerCellGroup INTEGER ::= 8 -- Maximum number of SR configurations per cell group +maxLCG-ID INTEGER ::= 7 -- Maximum value of LCG ID +maxLC-ID INTEGER ::= 32 -- Maximum value of Logical Channel ID +maxLC-ID-Iab-r16 INTEGER ::= 65536 -- Maximum value of BH Logical Channel ID extension +maxLTE-CRS-Patterns-r16 INTEGER ::= 3 -- Maximum number of additional LTE CRS rate matching patterns +maxNrofTAGs INTEGER ::= 4 -- Maximum number of Timing Advance Groups +maxNrofTAGs-1 INTEGER ::= 3 -- Maximum number of Timing Advance Groups minus 1 +maxNrofBWPs INTEGER ::= 4 -- Maximum number of BWPs per serving cell +maxNrofCombIDC INTEGER ::= 128 -- Maximum number of reported MR-DC combinations for IDC +maxNrofSymbols-1 INTEGER ::= 13 -- Maximum index identifying a symbol within a slot (14 symbols, indexed from 0..13) +maxNrofSlots INTEGER ::= 320 -- Maximum number of slots in a 10 ms period +maxNrofSlots-1 INTEGER ::= 319 -- Maximum number of slots in a 10 ms period minus 1 +maxNrofPhysicalResourceBlocks INTEGER ::= 275 -- Maximum number of PRBs +maxNrofPhysicalResourceBlocks-1 INTEGER ::= 274 -- Maximum number of PRBs minus 1 +maxNrofPhysicalResourceBlocksPlus1 INTEGER ::= 276 -- Maximum number of PRBs plus 1 +maxNrofControlResourceSets INTEGER ::= 12 -- Max number of CoReSets configurable on a serving cell +maxNrofControlResourceSets-1 INTEGER ::= 11 -- Max number of CoReSets configurable on a serving cell minus 1 +maxNrofControlResourceSets-1-r16 INTEGER ::= 15 -- Max number of CoReSets configurable on a serving cell extended in minus 1 +maxNrofCoresetPools-r16 INTEGER ::= 2 -- Maximum number of CORESET pools +maxCoReSetDuration INTEGER ::= 3 -- Max number of OFDM symbols in a control resource set +maxNrofSearchSpaces-1 INTEGER ::= 39 -- Max number of Search Spaces minus 1 +maxSFI-DCI-PayloadSize INTEGER ::= 128 -- Max number payload of a DCI scrambled with SFI-RNTI +maxSFI-DCI-PayloadSize-1 INTEGER ::= 127 -- Max number payload of a DCI scrambled with SFI-RNTI minus 1 +maxIAB-IP-Address-r16 INTEGER ::= 32 -- Max number of assigned IP addresses +maxINT-DCI-PayloadSize INTEGER ::= 126 -- Max number payload of a DCI scrambled with INT-RNTI +maxINT-DCI-PayloadSize-1 INTEGER ::= 125 -- Max number payload of a DCI scrambled with INT-RNTI minus 1 +maxNrofRateMatchPatterns INTEGER ::= 4 -- Max number of rate matching patterns that may be configured +maxNrofRateMatchPatterns-1 INTEGER ::= 3 -- Max number of rate matching patterns that may be configured minus 1 +maxNrofRateMatchPatternsPerGroup INTEGER ::= 8 -- Max number of rate matching patterns that may be configured in one group +maxNrofCSI-ReportConfigurations INTEGER ::= 48 -- Maximum number of report configurations +maxNrofCSI-ReportConfigurations-1 INTEGER ::= 47 -- Maximum number of report configurations minus 1 +maxNrofCSI-ResourceConfigurations INTEGER ::= 112 -- Maximum number of resource configurations +maxNrofCSI-ResourceConfigurations-1 INTEGER ::= 111 -- Maximum number of resource configurations minus 1 +maxNrofAP-CSI-RS-ResourcesPerSet INTEGER ::= 16 +maxNrOfCSI-AperiodicTriggers INTEGER ::= 128 -- Maximum number of triggers for aperiodic CSI reporting +maxNrofReportConfigPerAperiodicTrigger INTEGER ::= 16 -- Maximum number of report configurations per trigger state for aperiodic reporting +maxNrofNZP-CSI-RS-Resources INTEGER ::= 192 -- Maximum number of Non-Zero-Power (NZP) CSI-RS resources +maxNrofNZP-CSI-RS-Resources-1 INTEGER ::= 191 -- Maximum number of Non-Zero-Power (NZP) CSI-RS resources minus 1 +maxNrofNZP-CSI-RS-ResourcesPerSet INTEGER ::= 64 -- Maximum number of NZP CSI-RS resources per resource set +maxNrofNZP-CSI-RS-ResourceSets INTEGER ::= 64 -- Maximum number of NZP CSI-RS resources per cell +maxNrofNZP-CSI-RS-ResourceSets-1 INTEGER ::= 63 -- Maximum number of NZP CSI-RS resources per cell minus 1 +maxNrofNZP-CSI-RS-ResourceSetsPerConfig INTEGER ::= 16 -- Maximum number of resource sets per resource configuration +maxNrofNZP-CSI-RS-ResourcesPerConfig INTEGER ::= 128 -- Maximum number of resources per resource configuration +maxNrofZP-CSI-RS-Resources INTEGER ::= 32 -- Maximum number of Zero-Power (ZP) CSI-RS resources +maxNrofZP-CSI-RS-Resources-1 INTEGER ::= 31 -- Maximum number of Zero-Power (ZP) CSI-RS resources minus 1 +maxNrofZP-CSI-RS-ResourceSets-1 INTEGER ::= 15 +maxNrofZP-CSI-RS-ResourcesPerSet INTEGER ::= 16 +maxNrofZP-CSI-RS-ResourceSets INTEGER ::= 16 +maxNrofCSI-IM-Resources INTEGER ::= 32 -- Maximum number of CSI-IM resources. See CSI-IM-ResourceMax in 38.214. +maxNrofCSI-IM-Resources-1 INTEGER ::= 31 -- Maximum number of CSI-IM resources minus 1. See CSI-IM-ResourceMax in 38.214. +maxNrofCSI-IM-ResourcesPerSet INTEGER ::= 8 -- Maximum number of CSI-IM resources per set. See CSI-IM-ResourcePerSetMax in 38.214 +maxNrofCSI-IM-ResourceSets INTEGER ::= 64 -- Maximum number of NZP CSI-IM resources per cell +maxNrofCSI-IM-ResourceSets-1 INTEGER ::= 63 -- Maximum number of NZP CSI-IM resources per cell minus 1 +maxNrofCSI-IM-ResourceSetsPerConfig INTEGER ::= 16 -- Maximum number of CSI IM resource sets per resource configuration +maxNrofCSI-SSB-ResourcePerSet INTEGER ::= 64 -- Maximum number of SSB resources in a resource set +maxNrofCSI-SSB-ResourceSets INTEGER ::= 64 -- Maximum number of CSI SSB resource sets per cell +maxNrofCSI-SSB-ResourceSets-1 INTEGER ::= 63 -- Maximum number of CSI SSB resource sets per cell minus 1 +maxNrofCSI-SSB-ResourceSetsPerConfig INTEGER ::= 1 -- Maximum number of CSI SSB resource sets per resource configuration +maxNrofFailureDetectionResources INTEGER ::= 10 -- Maximum number of failure detection resources +maxNrofFailureDetectionResources-1 INTEGER ::= 9 -- Maximum number of failure detection resources minus 1 +maxNrofFreqSL-r16 INTEGER ::= 8 -- Maximum number of carrier frequncy for for NR sidelink communication +maxNrofSL-BWPs-r16 INTEGER ::= 4 -- Maximum number of BWP for for NR sidelink communication +maxFreqSL-EUTRA-r16 INTEGER ::= 8 -- Maximum number of EUTRA anchor carrier frequncy for NR sidelink communication +maxNrofSL-MeasId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement identity (RSRP) per destination +maxNrofSL-ObjectId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement objects (RSRP) per destination +maxNrofSL-ReportConfigId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement reporting configuration(RSRP) per destination +maxNrofSL-PoolToMeasureNR-r16 INTEGER ::= 8 -- Maximum number of resoure pool for NR sidelink measurement to measure for + -- each measurement object (for CBR) +maxFreqSL-NR-r16 INTEGER ::= 8 -- Maximum number of NR anchor carrier frequncy for NR sidelink communication +maxNrofSL-QFIs-r16 INTEGER ::= 2048 -- Maximum number of QoS flow for NR sidelink communication per UE +maxNrofSL-QFIsPerDest-r16 INTEGER ::= 64 -- Maximum number of QoS flow per destination for NR sidelink communication +maxNrofObjectId INTEGER ::= 64 -- Maximum number of measurement objects +maxNrofPageRec INTEGER ::= 32 -- Maximum number of page records +maxNrofPCI-Ranges INTEGER ::= 8 -- Maximum number of PCI ranges +maxPLMN INTEGER ::= 12 -- Maximum number of PLMNs broadcast and reported by UE at establisghment +maxNrofCSI-RS-ResourcesRRM INTEGER ::= 96 -- Maximum number of CSI-RS resources for an RRM measurement object +maxNrofCSI-RS-ResourcesRRM-1 INTEGER ::= 95 -- Maximum number of CSI-RS resources for an RRM measurement object minus 1 +maxNrofMeasId INTEGER ::= 64 -- Maximum number of configured measurements +maxNrofQuantityConfig INTEGER ::= 2 -- Maximum number of quantity configurations +maxNrofCSI-RS-CellsRRM INTEGER ::= 96 -- Maximum number of cells with CSI-RS resources for an RRM measurement object +maxNrofSL-Dest-r16 INTEGER ::= 32 -- Maximum number of destination for NR sidelink communication +maxNrofSL-Dest-1-r16 INTEGER ::= 31 -- Highest index of destination for NR sidelink communication +maxNrofSLRB-r16 INTEGER ::= 512 -- Maximum number of radio bearer for NR sidelink communication per UE +maxSL-LCID-r16 INTEGER ::= 512 -- Maximum number of RLC bearer for NR sidelink communication per UE +maxSL-SyncConfig-r16 INTEGER ::= 16 -- Maximum number of sidelink Sync configurations +maxNrofRXPool-r16 INTEGER ::= 16 -- Maximum number of Rx resource poolfor NR sidelink communication +maxNrofTXPool-r16 INTEGER ::= 8 -- Maximum number of Tx resourcepoolfor NR sidelink communication +maxNrofPoolID-r16 INTEGER ::= 16 -- Maximum index of resource pool for NR sidelink communication +maxNrofSRS-PathlossReferenceRS-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for SRS power control. +maxNrofSRS-PathlossReferenceRS-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for SRS power control-1. +maxNrofSRS-ResourceSets INTEGER ::= 16 -- Maximum number of SRS resource sets in a BWP. +maxNrofSRS-ResourceSets-1 INTEGER ::= 15 -- Maximum number of SRS resource sets in a BWP minus 1. +maxNrofSRS-PosResourceSets-r16 INTEGER ::= 16 -- Maximum number of SRS Positioning resource sets in a BWP. +maxNrofSRS-PosResourceSets-1-r16 INTEGER ::= 15 -- Maximum number of SRS Positioning resource sets in a BWP minus 1. +maxNrofSRS-Resources INTEGER ::= 64 -- Maximum number of SRS resources. +maxNrofSRS-Resources-1 INTEGER ::= 63 -- Maximum number of SRS resources in an SRS resource set minus 1. +maxNrofSRS-PosResources-r16 INTEGER ::= 64 -- Maximum number of SRS Positioning resources. +maxNrofSRS-PosResources-1-r16 INTEGER ::= 63 -- Maximum number of SRS Positioning resources in an SRS Positioning + -- resource set minus 1. +maxNrofSRS-ResourcesPerSet INTEGER ::= 16 -- Maximum number of SRS resources in an SRS resource set +maxNrofSRS-TriggerStates-1 INTEGER ::= 3 -- Maximum number of SRS trigger states minus 1, i.e., the largest code point. +maxNrofSRS-TriggerStates-2 INTEGER ::= 2 -- Maximum number of SRS trigger states minus 2. +maxRAT-CapabilityContainers INTEGER ::= 8 -- Maximum number of interworking RAT containers (incl NR and MRDC) +maxSimultaneousBands INTEGER ::= 32 -- Maximum number of simultaneously aggregated bands +maxULTxSwitchingBandPairs INTEGER ::= 32 -- Maximum number of band pairs supporting dynamic UL Tx switching in a band combination +maxNrofSlotFormatCombinationsPerSet INTEGER ::= 512 -- Maximum number of Slot Format Combinations in a SF-Set. +maxNrofSlotFormatCombinationsPerSet-1 INTEGER ::= 511 -- Maximum number of Slot Format Combinations in a SF-Set minus 1. +maxNrofTrafficPattern-r16 INTEGER ::= 8 -- Maximum number of Traffic Pattern for NR sidelink communication. +maxNrofPUCCH-Resources INTEGER ::= 128 +maxNrofPUCCH-Resources-1 INTEGER ::= 127 +maxNrofPUCCH-ResourceSets INTEGER ::= 4 -- Maximum number of PUCCH Resource Sets +maxNrofPUCCH-ResourceSets-1 INTEGER ::= 3 -- Maximum number of PUCCH Resource Sets minus 1. +maxNrofPUCCH-ResourcesPerSet INTEGER ::= 32 -- Maximum number of PUCCH Resources per PUCCH-ResourceSet +maxNrofPUCCH-P0-PerSet INTEGER ::= 8 -- Maximum number of P0-pucch present in a p0-pucch set +maxNrofPUCCH-PathlossReferenceRSs INTEGER ::= 4 -- Maximum number of RSs used as pathloss reference for PUCCH power control. +maxNrofPUCCH-PathlossReferenceRSs-1 INTEGER ::= 3 -- Maximum number of RSs used as pathloss reference for PUCCH power control minus 1. +maxNrofPUCCH-PathlossReferenceRSs-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for PUCCH power control extended. +maxNrofPUCCH-PathlossReferenceRSs-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for PUCCH power control + -- minus 1 extended. +maxNrofPUCCH-PathlossReferenceRSsDiff-r16 INTEGER ::= 60 -- Difference between the extended maximum and the non-extended maximum +maxNrofPUCCH-ResourceGroups-r16 INTEGER ::= 4 -- Maximum number of PUCCH resources groups. +maxNrofPUCCH-ResourcesPerGroup-r16 INTEGER ::= 128 -- Maximum number of PUCCH resources in a PUCCH group. +maxNrofMultiplePUSCHs-r16 INTEGER ::= 8 -- Maximum number of multiple PUSCHs in PUSCH TDRA list +maxNrofP0-PUSCH-AlphaSets INTEGER ::= 30 -- Maximum number of P0-pusch-alpha-sets (see 38,213, clause 7.1) +maxNrofP0-PUSCH-AlphaSets-1 INTEGER ::= 29 -- Maximum number of P0-pusch-alpha-sets minus 1 (see 38,213, clause 7.1) +maxNrofPUSCH-PathlossReferenceRSs INTEGER ::= 4 -- Maximum number of RSs used as pathloss reference for PUSCH power control. +maxNrofPUSCH-PathlossReferenceRSs-1 INTEGER ::= 3 -- Maximum number of RSs used as pathloss reference for PUSCH power control minus 1. +maxNrofPUSCH-PathlossReferenceRSs-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for PUSCH power control extended +maxNrofPUSCH-PathlossReferenceRSs-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for PUSCH power control minus 1 +maxNrofPUSCH-PathlossReferenceRSsDiff-r16 INTEGER ::= 60 -- Difference between maxNrofPUSCH-PathlossReferenceRSs-r16 and + -- maxNrofPUSCH-PathlossReferenceRSs +maxNrofNAICS-Entries INTEGER ::= 8 -- Maximum number of supported NAICS capability set +maxBands INTEGER ::= 1024 -- Maximum number of supported bands in UE capability. +maxBandsMRDC INTEGER ::= 1280 +maxBandsEUTRA INTEGER ::= 256 +maxCellReport INTEGER ::= 8 +maxDRB INTEGER ::= 29 -- Maximum number of DRBs (that can be added in DRB-ToAddModLIst). +maxFreq INTEGER ::= 8 -- Max number of frequencies. +maxFreqLayers INTEGER ::= 4 -- Max number of frequency layers. +maxFreqIDC-r16 INTEGER ::= 128 -- Max number of frequencies for IDC indication. +maxCombIDC-r16 INTEGER ::= 128 -- Max number of reported UL CA for IDC indication. +maxFreqIDC-MRDC INTEGER ::= 32 -- Maximum number of candidate NR frequencies for MR-DC IDC indication +maxNrofCandidateBeams INTEGER ::= 16 -- Max number of PRACH-ResourceDedicatedBFR that in BFR config. +maxNrofCandidateBeams-r16 INTEGER ::= 64 -- Max number of candidate beam resources in BFR config. +maxNrofCandidateBeamsExt-r16 INTEGER ::= 48 -- Max number of PRACH-ResourceDedicatedBFR in the CandidateBeamRSListExt +maxNrofPCIsPerSMTC INTEGER ::= 64 -- Maximun number of PCIs per SMTC. +maxNrofQFIs INTEGER ::= 64 +maxNrofResourceAvailabilityPerCombination-r16 INTEGER ::= 256 +maxNrOfSemiPersistentPUSCH-Triggers INTEGER ::= 64 -- Maximum number of triggers for semi persistent reporting on PUSCH +maxNrofSR-Resources INTEGER ::= 8 -- Maximum number of SR resources per BWP in a cell. +maxNrofSlotFormatsPerCombination INTEGER ::= 256 +maxNrofSpatialRelationInfos INTEGER ::= 8 +maxNrofSpatialRelationInfos-plus-1 INTEGER ::= 9 +maxNrofSpatialRelationInfos-r16 INTEGER ::= 64 +maxNrofSpatialRelationInfosDiff-r16 INTEGER ::= 56 -- Difference between maxNrofSpatialRelationInfos-r16 and maxNrofSpatialRelationInfos +maxNrofIndexesToReport INTEGER ::= 32 +maxNrofIndexesToReport2 INTEGER ::= 64 +maxNrofSSBs-r16 INTEGER ::= 64 -- Maximum number of SSB resources in a resource set. +maxNrofSSBs-1 INTEGER ::= 63 -- Maximum number of SSB resources in a resource set minus 1. +maxNrofS-NSSAI INTEGER ::= 8 -- Maximum number of S-NSSAI. +maxNrofTCI-StatesPDCCH INTEGER ::= 64 +maxNrofTCI-States INTEGER ::= 128 -- Maximum number of TCI states. +maxNrofTCI-States-1 INTEGER ::= 127 -- Maximum number of TCI states minus 1. +maxNrofUL-Allocations INTEGER ::= 16 -- Maximum number of PUSCH time domain resource allocations. +maxQFI INTEGER ::= 63 +maxRA-CSIRS-Resources INTEGER ::= 96 +maxRA-OccasionsPerCSIRS INTEGER ::= 64 -- Maximum number of RA occasions for one CSI-RS +maxRA-Occasions-1 INTEGER ::= 511 -- Maximum number of RA occasions in the system +maxRA-SSB-Resources INTEGER ::= 64 +maxSCSs INTEGER ::= 5 +maxSecondaryCellGroups INTEGER ::= 3 +maxNrofServingCellsEUTRA INTEGER ::= 32 +maxMBSFN-Allocations INTEGER ::= 8 +maxNrofMultiBands INTEGER ::= 8 +maxCellSFTD INTEGER ::= 3 -- Maximum number of cells for SFTD reporting +maxReportConfigId INTEGER ::= 64 +maxNrofCodebooks INTEGER ::= 16 -- Maximum number of codebooks suppoted by the UE +maxNrofCSI-RS-Resources INTEGER ::= 7 -- Maximum number of codebook resources supported by the UE +maxNrofCSI-RS-ResourcesAlt-r16 INTEGER ::= 512 -- Maximum number of alternative codebook resources supported by the UE +maxNrofCSI-RS-ResourcesAlt-1-r16 INTEGER ::= 511 -- Maximum number of alternative codebook resources supported by the UE minus 1 +maxNrofSRI-PUSCH-Mappings INTEGER ::= 16 +maxNrofSRI-PUSCH-Mappings-1 INTEGER ::= 15 +maxSIB INTEGER::= 32 -- Maximum number of SIBs +maxSI-Message INTEGER::= 32 -- Maximum number of SI messages +maxPO-perPF INTEGER ::= 4 -- Maximum number of paging occasion per paging frame +maxAccessCat-1 INTEGER ::= 63 -- Maximum number of Access Categories minus 1 +maxBarringInfoSet INTEGER ::= 8 -- Maximum number of Access Categories +maxCellEUTRA INTEGER ::= 8 -- Maximum number of E-UTRA cells in SIB list +maxEUTRA-Carrier INTEGER ::= 8 -- Maximum number of E-UTRA carriers in SIB list +maxPLMNIdentities INTEGER ::= 8 -- Maximum number of PLMN identites in RAN area configurations +maxDownlinkFeatureSets INTEGER ::= 1024 -- (for NR DL) Total number of FeatureSets (size of the pool) +maxUplinkFeatureSets INTEGER ::= 1024 -- (for NR UL) Total number of FeatureSets (size of the pool) +maxEUTRA-DL-FeatureSets INTEGER ::= 256 -- (for E-UTRA) Total number of FeatureSets (size of the pool) +maxEUTRA-UL-FeatureSets INTEGER ::= 256 -- (for E-UTRA) Total number of FeatureSets (size of the pool) +maxFeatureSetsPerBand INTEGER ::= 128 -- (for NR) The number of feature sets associated with one band. +maxPerCC-FeatureSets INTEGER ::= 1024 -- (for NR) Total number of CC-specific FeatureSets (size of the pool) +maxFeatureSetCombinations INTEGER ::= 1024 -- (for MR-DC/NR)Total number of Feature set combinations (size of the pool) +maxInterRAT-RSTD-Freq INTEGER ::= 3 +maxHRNN-Len-r16 INTEGER ::= 48 -- Maximum length of HRNNs +maxNPN-r16 INTEGER ::= 12 -- Maximum number of NPNs broadcast and reported by UE at establishment +maxNrOfMinSchedulingOffsetValues-r16 INTEGER ::= 2 -- Maximum number of min. scheduling offset (K0/K2) configurations +maxK0-SchedulingOffset-r16 INTEGER ::= 16 -- Maximum number of slots configured as min. scheduling offset (K0) +maxK2-SchedulingOffset-r16 INTEGER ::= 16 -- Maximum number of slots configured as min. scheduling offset (K2) +maxDCI-2-6-Size-r16 INTEGER ::= 140 -- Maximum size of DCI format 2-6 +maxDCI-2-6-Size-1-r16 INTEGER ::= 139 -- Maximum DCI format 2-6 size minus 1 +maxNrofUL-Allocations-r16 INTEGER ::= 64 -- Maximum number of PUSCH time domain resource allocations +maxNrofP0-PUSCH-Set-r16 INTEGER ::= 2 -- Maximum number of P0 PUSCH set(s) +maxOnDemandSIB-r16 INTEGER ::= 8 -- Maximum number of SIB(s) that can be requested on-demand +maxOnDemandPosSIB-r16 INTEGER ::= 32 -- Maximum number of posSIB(s) that can be requested on-demand +maxCI-DCI-PayloadSize-r16 INTEGER ::= 126 -- Maximum number of the DCI size for CI +maxCI-DCI-PayloadSize-r16-1 INTEGER ::= 125 -- Maximum number of the DCI size for CI minus 1 +maxWLAN-Id-Report-r16 INTEGER ::= 32 -- Maximum number of WLAN IDs to report +maxWLAN-Name-r16 INTEGER ::= 4 -- Maximum number of WLAN name +maxRAReport-r16 INTEGER ::= 8 -- Maximum number of RA procedures information to be included in the RA report +maxTxConfig-r16 INTEGER ::= 64 -- Maximum number of sidelink transmission parameters configurations +maxTxConfig-1-r16 INTEGER ::= 63 -- Maximum number of sidelink transmission parameters configurations minus 1 +maxPSSCH-TxConfig-r16 INTEGER ::= 16 -- Maximum number of PSSCH TX configurations +maxNrofCLI-RSSI-Resources-r16 INTEGER ::= 64 -- Maximum number of CLI-RSSI resources for UE +maxNrofCLI-RSSI-Resources-r16-1 INTEGER ::= 63 -- Maximum number of CLI-RSSI resources for UE minus 1 +maxNrofCLI-SRS-Resources-r16 INTEGER ::= 32 -- Maximum number of SRS resources for CLI measurement for UE +maxCLI-Report-r16 INTEGER ::= 8 +maxNrofConfiguredGrantConfig-r16 INTEGER ::= 12 -- Maximum number of configured grant configurations per BWP +maxNrofConfiguredGrantConfig-r16-1 INTEGER ::= 11 -- Maximum number of configured grant configurations per BWP minus 1 +maxNrofCG-Type2DeactivationState INTEGER ::= 16 -- Maximum number of deactivation state for type 2 configured grants per BWP +maxNrofConfiguredGrantConfigMAC-r16 INTEGER ::= 32 -- Maximum number of configured grant configurations per MAC entity +maxNrofConfiguredGrantConfigMAC-r16-1 INTEGER ::= 31 -- Maximum number of configured grant configurations per MAC entity minus 1 +maxNrofSPS-Config-r16 INTEGER ::= 8 -- Maximum number of SPS configurations per BWP +maxNrofSPS-Config-r16-1 INTEGER ::= 7 -- Maximum number of SPS configurations per BWP minus 1 +maxNrofSPS-DeactivationState INTEGER ::= 16 -- Maximum number of deactivation state for SPS per BWP +maxNrofDormancyGroups INTEGER ::= 5 -- +maxNrofPUCCH-ResourceGroups-1-r16 INTEGER ::= 3 -- +maxNrofServingCellsTCI-r16 INTEGER ::= 32 -- Maximum number of serving cells in simultaneousTCI-UpdateList + +-- TAG-MULTIPLICITY-AND-TYPE-CONSTRAINT-DEFINITIONS-STOP + +END + +-- NR-UE-VARIABLES-START + +NR-UE-Variables DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + ARFCN-ValueNR, + CellIdentity, + EUTRA-PhysCellId, + MeasId, + MeasIdToAddModList, + MeasIdleCarrierEUTRA-r16, + MeasIdleCarrierNR-r16, + MeasResultIdleEUTRA-r16, + MeasResultIdleNR-r16, + MeasObjectToAddModList, + PhysCellId, + RNTI-Value, + ReportConfigToAddModList, + RSRP-Range, + SL-MeasId-r16, + SL-MeasIdList-r16, + SL-MeasObjectList-r16, + SL-ReportConfigList-r16, + SL-QuantityConfig-r16, + Tx-PoolMeasList-r16, + QuantityConfig, + maxNrofCellMeas, + maxNrofMeasId, + maxFreqIdle-r16, + PhysCellIdUTRA-FDD-r16, + ValidityAreaList-r16, + CondReconfigToAddModList-r16, + ConnEstFailReport-r16, + LoggingDuration-r16, + LoggingInterval-r16, + LogMeasInfoList-r16, + LogMeasInfo-r16, + RA-Report-r16, + RLF-Report-r16, + TraceReference-r16, + WLAN-Identifiers-r16, + WLAN-NameList-r16, + BT-NameList-r16, + PLMN-Identity, + maxPLMN, + RA-ReportList-r16, + VisitedCellInfoList-r16, + AbsoluteTimeInfo-r16, + LoggedEventTriggerConfig-r16, + LoggedPeriodicalReportConfig-r16, + Sensor-NameList-r16, + PLMN-IdentityList2-r16, + AreaConfiguration-r16, + maxNrofSL-MeasId-r16, + maxNrofFreqSL-r16, + maxNrofCLI-RSSI-Resources-r16, + maxNrofCLI-SRS-Resources-r16, + RSSI-ResourceId-r16, + SRS-ResourceId +FROM NR-RRC-Definitions; + +-- NR-UE-VARIABLES-STOP + +-- TAG-VARCONDITIONALRECONFIG-START + +VarConditionalReconfig ::= SEQUENCE { + condReconfigList CondReconfigToAddModList-r16 OPTIONAL +} + + +-- TAG-VARCONDITIONALRECONFIG-STOP +-- TAG-VARCONNESTFAILREPORT-START + +VarConnEstFailReport-r16 ::= SEQUENCE { + connEstFailReport-r16 ConnEstFailReport-r16, + plmn-Identity-r16 PLMN-Identity +} + +-- TAG-VARCONNESTFAILREPORT-STOP +-- TAG-VARLOGMEASCONFIG-START + +VarLogMeasConfig-r16-IEs ::= SEQUENCE { + areaConfiguration-r16 AreaConfiguration-r16 OPTIONAL, + bt-NameList-r16 BT-NameList-r16 OPTIONAL, + wlan-NameList-r16 WLAN-NameList-r16 OPTIONAL, + sensor-NameList-r16 Sensor-NameList-r16 OPTIONAL, + loggingDuration-r16 LoggingDuration-r16, + reportType CHOICE { + periodical LoggedPeriodicalReportConfig-r16, + eventTriggered LoggedEventTriggerConfig-r16 + } +} +-- TAG-VARLOGMEASCONFIG-STOP +-- TAG-VARLOGMEAREPORT-START + +VarLogMeasReport-r16 ::= SEQUENCE { + absoluteTimeStamp-r16 AbsoluteTimeInfo-r16, + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + logMeasInfoList-r16 LogMeasInfoList-r16, + plmn-IdentityList-r16 PLMN-IdentityList2-r16 +} + +-- TAG-VARLOGMEAREPORT-STOP +-- TAG-VARMEASCONFIG-START + +VarMeasConfig ::= SEQUENCE { + -- Measurement identities + measIdList MeasIdToAddModList OPTIONAL, + -- Measurement objects + measObjectList MeasObjectToAddModList OPTIONAL, + -- Reporting configurations + reportConfigList ReportConfigToAddModList OPTIONAL, + -- Other parameters + quantityConfig QuantityConfig OPTIONAL, + + s-MeasureConfig CHOICE { + ssb-RSRP RSRP-Range, + csi-RSRP RSRP-Range + } OPTIONAL + +} + +-- TAG-VARMEASCONFIG-STOP +-- TAG-VARMEASCONFIGSL-START + +VarMeasConfigSL-r16 ::= SEQUENCE { + -- NR sidelink measurement identities + sl-MeasIdList-r16 SL-MeasIdList-r16 OPTIONAL, + -- NR sidelink measurement objects + sl-MeasObjectList-r16 SL-MeasObjectList-r16 OPTIONAL, + -- NR sidelink reporting configurations + sl-reportConfigList-r16 SL-ReportConfigList-r16 OPTIONAL, + -- Other parameters + sl-QuantityConfig-r16 SL-QuantityConfig-r16 OPTIONAL +} + +-- TAG-VARMEASCONFIGSL-STOP +-- TAG-VARMEASIDLECONFIG-START + +VarMeasIdleConfig-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, + measIdleDuration-r16 ENUMERATED {sec10, sec30, sec60, sec120, sec180, sec240, sec300, spare}, + validityAreaList-r16 ValidityAreaList-r16 OPTIONAL +} + +-- TAG-VARMEASIDLECONFIG-STOP +-- TAG-VARMEASIDLEREPORT-START + +VarMeasIdleReport-r16 ::= SEQUENCE { + measReportIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + measReportIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL +} + +-- TAG-VARMEASIDLEREPORT-STOP +-- TAG-VARMEASREPORTLIST-START + +VarMeasReportList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF VarMeasReport + +VarMeasReport ::= SEQUENCE { + -- List of measurement that have been triggered + measId MeasId, + cellsTriggeredList CellsTriggeredList OPTIONAL, + numberOfReportsSent INTEGER, + cli-TriggeredList-r16 CLI-TriggeredList-r16 OPTIONAL, + tx-PoolMeasToAddModListNR-r16 Tx-PoolMeasList-r16 OPTIONAL +} + +CellsTriggeredList ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF CHOICE { + physCellId PhysCellId, + physCellIdEUTRA EUTRA-PhysCellId, + physCellIdUTRA-FDD-r16 PhysCellIdUTRA-FDD-r16 + } + +CLI-TriggeredList-r16 ::= CHOICE { + srs-RSRP-TriggeredList-r16 SRS-RSRP-TriggeredList-r16, + cli-RSSI-TriggeredList-r16 CLI-RSSI-TriggeredList-r16 + } + +SRS-RSRP-TriggeredList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-SRS-Resources-r16)) OF SRS-ResourceId + +CLI-RSSI-TriggeredList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-RSSI-Resources-r16)) OF RSSI-ResourceId-r16 + +-- TAG-VARMEASREPORTLIST-STOP +-- TAG-VARMEASREPORTLISTSL-START + +VarMeasReportListSL-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF VarMeasReportSL-r16 + +VarMeasReportSL-r16 ::= SEQUENCE { + -- List of NR sidelink measurement that have been triggered + sl-MeasId-r16 SL-MeasId-r16, + sl-FrequencyTriggeredList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF ARFCN-ValueNR OPTIONAL, + sl-NumberOfReportsSent-r16 INTEGER +} + +-- TAG-VARMEASREPORTLISTSL-STOP +-- TAG-VARMOBILITYHISTORYREPORT-START + +VarMobilityHistoryReport-r16 ::= VisitedCellInfoList-r16 + +-- TAG-VARMOBILITYHISTORYREPORT-STOP +-- TAG-VARPENDINGRNA-UPDATE-START + +VarPendingRNA-Update ::= SEQUENCE { + pendingRNA-Update BOOLEAN OPTIONAL +} + +-- TAG-VARPENDINGRNA-UPDATE-STOP +-- TAG-VARRA-REPORT-START + +VarRA-Report-r16 ::= SEQUENCE { + ra-ReportList-r16 RA-ReportList-r16, + plmn-IdentityList-r16 PLMN-IdentityList-r16 +} + +PLMN-IdentityList-r16 ::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity + +-- TAG-VARRA-REPORT-STOP +-- TAG-VARRESUMEMAC-INPUT-START + +VarResumeMAC-Input ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellIdentity CellIdentity, + source-c-RNTI RNTI-Value + +} + +-- TAG-VARRESUMEMAC-INPUT-STOP +-- TAG-VARRLF-REPORT-START + +VarRLF-Report-r16 ::= SEQUENCE { + rlf-Report-r16 RLF-Report-r16, + plmn-IdentityList-r16 PLMN-IdentityList-r16 +} + +-- TAG-VARRLF-REPORT-STOP +-- TAG-VARSHORTMAC-INPUT-START + +VarShortMAC-Input ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellIdentity CellIdentity, + source-c-RNTI RNTI-Value +} + +-- TAG-VARSHORTMAC-INPUT-STOP + +END + +-- TAG-NR-INTER-NODE-DEFINITIONS-START + +NR-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + ARFCN-ValueNR, + ARFCN-ValueEUTRA, + CellIdentity, + CGI-InfoEUTRA, + CGI-InfoNR, + CSI-RS-Index, + CSI-RS-CellMobility, + DRX-Config, + EUTRA-PhysCellId, + FreqBandIndicatorNR, + GapConfig, + maxBandComb, + maxBands, + maxCellSFTD, + maxFeatureSetsPerBand, + maxFreqIDC-MRDC, + maxNrofCombIDC, + maxNrofSCells, + maxNrofServingCells, + maxNrofServingCells-1, + maxNrofServingCellsEUTRA, + maxNrofIndexesToReport, + maxSimultaneousBands, + MeasQuantityResults, + MeasResultCellListSFTD-EUTRA, + MeasResultCellListSFTD-NR, + MeasResultList2NR, + MeasResultSCG-Failure, + MeasResultServFreqListEUTRA-SCG, + NeedForGapsInfoNR-r16, + OverheatingAssistance, + P-Max, + PhysCellId, + RadioBearerConfig, + RAN-NotificationAreaInfo, + RRCReconfiguration, + ServCellIndex, + SetupRelease, + SSB-Index, + SSB-MTC, + SSB-ToMeasure, + SS-RSSI-Measurement, + ShortMAC-I, + SubcarrierSpacing, + UEAssistanceInformation, + UE-CapabilityRAT-ContainerList, + maxNrofCLI-RSSI-Resources-r16, + maxNrofCLI-SRS-Resources-r16, + RSSI-ResourceId-r16, + SidelinkUEInformationNR-r16, + SRS-ResourceId +FROM NR-RRC-Definitions; + +-- TAG-NR-INTER-NODE-DEFINITIONS-STOP + +-- TAG-HANDOVER-COMMAND-START + +HandoverCommand ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverCommand HandoverCommand-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverCommand-IEs ::= SEQUENCE { + handoverCommandMessage OCTET STRING (CONTAINING RRCReconfiguration), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-HANDOVER-COMMAND-STOP +-- TAG-HANDOVER-PREPARATION-INFORMATION-START + +HandoverPreparationInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverPreparationInformation HandoverPreparationInformation-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverPreparationInformation-IEs ::= SEQUENCE { + ue-CapabilityRAT-List UE-CapabilityRAT-ContainerList, + sourceConfig AS-Config OPTIONAL, -- Cond HO + rrm-Config RRM-Config OPTIONAL, + as-Context AS-Context OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +AS-Config ::= SEQUENCE { + rrcReconfiguration OCTET STRING (CONTAINING RRCReconfiguration), + ..., + [[ + sourceRB-SN-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + sourceSCG-NR-Config OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + sourceSCG-EUTRA-Config OCTET STRING OPTIONAL + ]], + [[ + sourceSCG-Configured ENUMERATED {true} OPTIONAL + ]] + +} + +AS-Context ::= SEQUENCE { + reestablishmentInfo ReestablishmentInfo OPTIONAL, + configRestrictInfo ConfigRestrictInfoSCG OPTIONAL, + ..., + [[ ran-NotificationAreaInfo RAN-NotificationAreaInfo OPTIONAL + ]], + [[ ueAssistanceInformation OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL -- Cond HO2 + ]], + [[ + selectedBandCombinationSN BandCombinationInfoSN OPTIONAL + ]], + [[ + configRestrictInfoDAPS-r16 ConfigRestrictInfoDAPS-r16 OPTIONAL, + sidelinkUEInformationNR-r16 OCTET STRING OPTIONAL, + sidelinkUEInformationEUTRA-r16 OCTET STRING OPTIONAL, + ueAssistanceInformationEUTRA-r16 OCTET STRING OPTIONAL, + ueAssistanceInformationSCG-r16 OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL, -- Cond HO2 + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL + ]] +} + +ConfigRestrictInfoDAPS-r16 ::= SEQUENCE { + powerCoordination-r16 SEQUENCE { + p-DAPS-Source-r16 P-Max, + p-DAPS-Target-r16 P-Max, + uplinkPowerSharingDAPS-Mode-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic } + } OPTIONAL +} + +ReestablishmentInfo ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellShortMAC-I ShortMAC-I, + additionalReestabInfoList ReestabNCellInfoList OPTIONAL +} + +ReestabNCellInfoList ::= SEQUENCE ( SIZE (1..maxCellPrep) ) OF ReestabNCellInfo + +ReestabNCellInfo::= SEQUENCE{ + cellIdentity CellIdentity, + key-gNodeB-Star BIT STRING (SIZE (256)), + shortMAC-I ShortMAC-I +} + +RRM-Config ::= SEQUENCE { + ue-InactiveTime ENUMERATED { + s1, s2, s3, s5, s7, s10, s15, s20, + s25, s30, s40, s50, min1, min1s20, min1s40, + min2, min2s30, min3, min3s30, min4, min5, min6, + min7, min8, min9, min10, min12, min14, min17, min20, + min24, min28, min33, min38, min44, min50, hr1, + hr1min30, hr2, hr2min30, hr3, hr3min30, hr4, hr5, hr6, + hr8, hr10, hr13, hr16, hr20, day1, day1hr12, day2, + day2hr12, day3, day4, day5, day7, day10, day14, day19, + day24, day30, dayMoreThan30} OPTIONAL, + candidateCellInfoList MeasResultList2NR OPTIONAL, + ..., + [[ + candidateCellInfoListSN-EUTRA MeasResultServFreqListEUTRA-SCG OPTIONAL + ]] +} + +-- TAG-HANDOVER-PREPARATION-INFORMATION-STOP +-- TAG-CG-CONFIG-START + +CG-Config ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + cg-Config CG-Config-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +CG-Config-IEs ::= SEQUENCE { + scg-CellGroupConfig OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + scg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + configRestrictModReq ConfigRestrictModReqSCG OPTIONAL, + drx-InfoSCG DRX-Info OPTIONAL, + candidateCellInfoListSN OCTET STRING (CONTAINING MeasResultList2NR) OPTIONAL, + measConfigSN MeasConfigSN OPTIONAL, + selectedBandCombination BandCombinationInfoSN OPTIONAL, + fr-InfoListSCG FR-InfoList OPTIONAL, + candidateServingFreqListNR CandidateServingFreqListNR OPTIONAL, + nonCriticalExtension CG-Config-v1540-IEs OPTIONAL +} + +CG-Config-v1540-IEs ::= SEQUENCE { + pSCellFrequency ARFCN-ValueNR OPTIONAL, + reportCGI-RequestNR SEQUENCE { + requestedCellInfo SEQUENCE { + ssbFrequency ARFCN-ValueNR, + cellForWhichToReportCGI PhysCellId + } OPTIONAL + } OPTIONAL, + ph-InfoSCG PH-TypeListSCG OPTIONAL, + nonCriticalExtension CG-Config-v1560-IEs OPTIONAL +} + +CG-Config-v1560-IEs ::= SEQUENCE { + pSCellFrequencyEUTRA ARFCN-ValueEUTRA OPTIONAL, + scg-CellGroupConfigEUTRA OCTET STRING OPTIONAL, + candidateCellInfoListSN-EUTRA OCTET STRING OPTIONAL, + candidateServingFreqListEUTRA CandidateServingFreqListEUTRA OPTIONAL, + needForGaps ENUMERATED {true} OPTIONAL, + drx-ConfigSCG DRX-Config OPTIONAL, + reportCGI-RequestEUTRA SEQUENCE { + requestedCellInfoEUTRA SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cellForWhichToReportCGI-EUTRA EUTRA-PhysCellId + } OPTIONAL + } OPTIONAL, + nonCriticalExtension CG-Config-v1590-IEs OPTIONAL +} + +CG-Config-v1590-IEs ::= SEQUENCE { + scellFrequenciesSN-NR SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueNR OPTIONAL, + scellFrequenciesSN-EUTRA SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueEUTRA OPTIONAL, + nonCriticalExtension CG-Config-v1610-IEs OPTIONAL +} + +CG-Config-v1610-IEs ::= SEQUENCE { + drx-InfoSCG2 DRX-Info2 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +PH-TypeListSCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF PH-InfoSCG + +PH-InfoSCG ::= SEQUENCE { + servCellIndex ServCellIndex, + ph-Uplink PH-UplinkCarrierSCG, + ph-SupplementaryUplink PH-UplinkCarrierSCG OPTIONAL, + ... +} + +PH-UplinkCarrierSCG ::= SEQUENCE{ + ph-Type1or3 ENUMERATED {type1, type3}, + ... +} + +MeasConfigSN ::= SEQUENCE { + measuredFrequenciesSN SEQUENCE (SIZE (1..maxMeasFreqsSN)) OF NR-FreqInfo OPTIONAL, + ... +} + +NR-FreqInfo ::= SEQUENCE { + measuredFrequency ARFCN-ValueNR OPTIONAL, + ... +} + +ConfigRestrictModReqSCG ::= SEQUENCE { + requestedBC-MRDC BandCombinationInfoSN OPTIONAL, + requestedP-MaxFR1 P-Max OPTIONAL, + ..., + [[ + requestedPDCCH-BlindDetectionSCG INTEGER (1..15) OPTIONAL, + requestedP-MaxEUTRA P-Max OPTIONAL + ]], + [[ + requestedP-MaxFR2-r16 P-Max OPTIONAL, + requestedMaxInterFreqMeasIdSCG-r16 INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + requestedMaxIntraFreqMeasIdSCG-r16 INTEGER(1..maxMeasIdentitiesMN) OPTIONAL + ]] +} + +BandCombinationIndex ::= INTEGER (1..maxBandComb) + +BandCombinationInfoSN ::= SEQUENCE { + bandCombinationIndex BandCombinationIndex, + requestedFeatureSets FeatureSetEntryIndex +} + +FR-InfoList ::= SEQUENCE (SIZE (1..maxNrofServingCells-1)) OF FR-Info + +FR-Info ::= SEQUENCE { + servCellIndex ServCellIndex, + fr-Type ENUMERATED {fr1, fr2} +} + +CandidateServingFreqListNR ::= SEQUENCE (SIZE (1.. maxFreqIDC-MRDC)) OF ARFCN-ValueNR + +CandidateServingFreqListEUTRA ::= SEQUENCE (SIZE (1.. maxFreqIDC-MRDC)) OF ARFCN-ValueEUTRA + +-- TAG-CG-CONFIG-STOP +-- TAG-CG-CONFIG-INFO-START + +CG-ConfigInfo ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + cg-ConfigInfo CG-ConfigInfo-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +CG-ConfigInfo-IEs ::= SEQUENCE { + ue-CapabilityInfo OCTET STRING (CONTAINING UE-CapabilityRAT-ContainerList) OPTIONAL,-- Cond SN-AddMod + candidateCellInfoListMN MeasResultList2NR OPTIONAL, + candidateCellInfoListSN OCTET STRING (CONTAINING MeasResultList2NR) OPTIONAL, + measResultCellListSFTD-NR MeasResultCellListSFTD-NR OPTIONAL, + scgFailureInfo SEQUENCE { + failureType ENUMERATED { t310-Expiry, randomAccessProblem, + rlc-MaxNumRetx, synchReconfigFailure-SCG, + scg-reconfigFailure, + srb3-IntegrityFailure}, + measResultSCG OCTET STRING (CONTAINING MeasResultSCG-Failure) + } OPTIONAL, + configRestrictInfo ConfigRestrictInfoSCG OPTIONAL, + drx-InfoMCG DRX-Info OPTIONAL, + measConfigMN MeasConfigMN OPTIONAL, + sourceConfigSCG OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + scg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + mcg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + mrdc-AssistanceInfo MRDC-AssistanceInfo OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1540-IEs OPTIONAL +} + +CG-ConfigInfo-v1540-IEs ::= SEQUENCE { + ph-InfoMCG PH-TypeListMCG OPTIONAL, + measResultReportCGI SEQUENCE { + ssbFrequency ARFCN-ValueNR, + cellForWhichToReportCGI PhysCellId, + cgi-Info CGI-InfoNR + } OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1560-IEs OPTIONAL +} + +CG-ConfigInfo-v1560-IEs ::= SEQUENCE { + candidateCellInfoListMN-EUTRA OCTET STRING OPTIONAL, + candidateCellInfoListSN-EUTRA OCTET STRING OPTIONAL, + sourceConfigSCG-EUTRA OCTET STRING OPTIONAL, + scgFailureInfoEUTRA SEQUENCE { + failureTypeEUTRA ENUMERATED { t313-Expiry, randomAccessProblem, + rlc-MaxNumRetx, scg-ChangeFailure}, + measResultSCG-EUTRA OCTET STRING + } OPTIONAL, + drx-ConfigMCG DRX-Config OPTIONAL, + measResultReportCGI-EUTRA SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cellForWhichToReportCGI-EUTRA EUTRA-PhysCellId, + cgi-InfoEUTRA CGI-InfoEUTRA + } OPTIONAL, + measResultCellListSFTD-EUTRA MeasResultCellListSFTD-EUTRA OPTIONAL, + fr-InfoListMCG FR-InfoList OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1570-IEs OPTIONAL +} + +CG-ConfigInfo-v1570-IEs ::= SEQUENCE { + sftdFrequencyList-NR SFTD-FrequencyList-NR OPTIONAL, + sftdFrequencyList-EUTRA SFTD-FrequencyList-EUTRA OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1590-IEs OPTIONAL +} + +CG-ConfigInfo-v1590-IEs ::= SEQUENCE { + servFrequenciesMN-NR SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueNR OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1610-IEs OPTIONAL +} + +CG-ConfigInfo-v1610-IEs ::= SEQUENCE { + drx-InfoMCG2 DRX-Info2 OPTIONAL, + alignedDRX-Indication ENUMERATED {true} OPTIONAL, + scgFailureInfo-r16 SEQUENCE { + failureType-r16 ENUMERATED { scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, bh-RLF-r16, + spare4, spare3, spare2, spare1}, + measResultSCG-r16 OCTET STRING (CONTAINING MeasResultSCG-Failure) + } OPTIONAL, + scgFailureInfoEUTRA-r16 SEQUENCE { + failureTypeEUTRA-r16 ENUMERATED { scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, bh-RLF-r16, + spare4, spare3, spare2, spare1}, + measResultSCG-EUTRA-r16 OCTET STRING + } OPTIONAL, + sidelinkUEInformationNR-r16 OCTET STRING (CONTAINING SidelinkUEInformationNR-r16) OPTIONAL, + sidelinkUEInformationEUTRA-r16 OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} +SFTD-FrequencyList-NR ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF ARFCN-ValueNR + +SFTD-FrequencyList-EUTRA ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF ARFCN-ValueEUTRA + +ConfigRestrictInfoSCG ::= SEQUENCE { + allowedBC-ListMRDC BandCombinationInfoList OPTIONAL, + powerCoordination-FR1 SEQUENCE { + p-maxNR-FR1 P-Max OPTIONAL, + p-maxEUTRA P-Max OPTIONAL, + p-maxUE-FR1 P-Max OPTIONAL + } OPTIONAL, + servCellIndexRangeSCG SEQUENCE { + lowBound ServCellIndex, + upBound ServCellIndex + } OPTIONAL, -- Cond SN-AddMod + maxMeasFreqsSCG INTEGER(1..maxMeasFreqsMN) OPTIONAL, + dummy INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + ..., + [[ + selectedBandEntriesMNList SEQUENCE (SIZE (1..maxBandComb)) OF SelectedBandEntriesMN OPTIONAL, + pdcch-BlindDetectionSCG INTEGER (1..15) OPTIONAL, + maxNumberROHC-ContextSessionsSN INTEGER(0.. 16384) OPTIONAL + ]], + [[ + maxIntraFreqMeasIdentitiesSCG INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + maxInterFreqMeasIdentitiesSCG INTEGER(1..maxMeasIdentitiesMN) OPTIONAL + ]], + [[ + p-maxNR-FR1-MCG-r16 P-Max OPTIONAL, + powerCoordination-FR2-r16 SEQUENCE { + p-maxNR-FR2-MCG-r16 P-Max OPTIONAL, + p-maxNR-FR2-SCG-r16 P-Max OPTIONAL, + p-maxUE-FR2-r16 P-Max OPTIONAL + } OPTIONAL, + nrdc-PC-mode-FR1-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, + nrdc-PC-mode-FR2-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, + maxMeasSRS-ResourceSCG-r16 INTEGER(0..maxNrofCLI-SRS-Resources-r16) OPTIONAL, + maxMeasCLI-ResourceSCG-r16 INTEGER(0..maxNrofCLI-RSSI-Resources-r16) OPTIONAL, + maxNumberEHC-ContextsSN-r16 INTEGER(0..65536) OPTIONAL, + allowedReducedConfigForOverheating-r16 OverheatingAssistance OPTIONAL + ]] +} + +SelectedBandEntriesMN ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandEntryIndex + +BandEntryIndex ::= INTEGER (0.. maxNrofServingCells) + +PH-TypeListMCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF PH-InfoMCG + +PH-InfoMCG ::= SEQUENCE { + servCellIndex ServCellIndex, + ph-Uplink PH-UplinkCarrierMCG, + ph-SupplementaryUplink PH-UplinkCarrierMCG OPTIONAL, + ... +} + +PH-UplinkCarrierMCG ::= SEQUENCE{ + ph-Type1or3 ENUMERATED {type1, type3}, + ... +} + +BandCombinationInfoList ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationInfo + +BandCombinationInfo ::= SEQUENCE { + bandCombinationIndex BandCombinationIndex, + allowedFeatureSetsList SEQUENCE (SIZE (1..maxFeatureSetsPerBand)) OF FeatureSetEntryIndex +} + +FeatureSetEntryIndex ::= INTEGER (1.. maxFeatureSetsPerBand) + +DRX-Info ::= SEQUENCE { + drx-LongCycleStartOffset CHOICE { + ms10 INTEGER(0..9), + ms20 INTEGER(0..19), + ms32 INTEGER(0..31), + ms40 INTEGER(0..39), + ms60 INTEGER(0..59), + ms64 INTEGER(0..63), + ms70 INTEGER(0..69), + ms80 INTEGER(0..79), + ms128 INTEGER(0..127), + ms160 INTEGER(0..159), + ms256 INTEGER(0..255), + ms320 INTEGER(0..319), + ms512 INTEGER(0..511), + ms640 INTEGER(0..639), + ms1024 INTEGER(0..1023), + ms1280 INTEGER(0..1279), + ms2048 INTEGER(0..2047), + ms2560 INTEGER(0..2559), + ms5120 INTEGER(0..5119), + ms10240 INTEGER(0..10239) + }, + shortDRX SEQUENCE { + drx-ShortCycle ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-ShortCycleTimer INTEGER (1..16) + } OPTIONAL +} + +DRX-Info2 ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + } +} + +MeasConfigMN ::= SEQUENCE { + measuredFrequenciesMN SEQUENCE (SIZE (1..maxMeasFreqsMN)) OF NR-FreqInfo OPTIONAL, + measGapConfig SetupRelease { GapConfig } OPTIONAL, + gapPurpose ENUMERATED {perUE, perFR1} OPTIONAL, + ..., + [[ measGapConfigFR2 SetupRelease { GapConfig } OPTIONAL + ]] + +} + +MRDC-AssistanceInfo ::= SEQUENCE { + affectedCarrierFreqCombInfoListMRDC SEQUENCE (SIZE (1..maxNrofCombIDC)) OF AffectedCarrierFreqCombInfoMRDC, + ..., + [[ + overheatingAssistanceSCG-r16 OCTET STRING (CONTAINING OverheatingAssistance) OPTIONAL + ]] +} + +AffectedCarrierFreqCombInfoMRDC ::= SEQUENCE { + victimSystemType VictimSystemType, + interferenceDirectionMRDC ENUMERATED {eutra-nr, nr, other, utra-nr-other, nr-other, spare3, spare2, spare1}, + affectedCarrierFreqCombMRDC SEQUENCE { + affectedCarrierFreqCombEUTRA AffectedCarrierFreqCombEUTRA OPTIONAL, + affectedCarrierFreqCombNR AffectedCarrierFreqCombNR + } OPTIONAL +} + +VictimSystemType ::= SEQUENCE { + gps ENUMERATED {true} OPTIONAL, + glonass ENUMERATED {true} OPTIONAL, + bds ENUMERATED {true} OPTIONAL, + galileo ENUMERATED {true} OPTIONAL, + wlan ENUMERATED {true} OPTIONAL, + bluetooth ENUMERATED {true} OPTIONAL +} + +AffectedCarrierFreqCombEUTRA ::= SEQUENCE (SIZE (1..maxNrofServingCellsEUTRA)) OF ARFCN-ValueEUTRA + +AffectedCarrierFreqCombNR ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF ARFCN-ValueNR + +-- TAG-CG-CONFIG-INFO-STOP +-- TAG-MEASUREMENT-TIMING-CONFIGURATION-START + +MeasurementTimingConfiguration ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + measTimingConf MeasurementTimingConfiguration-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementTimingConfiguration-IEs ::= SEQUENCE { + measTiming MeasTimingList OPTIONAL, + nonCriticalExtension MeasurementTimingConfiguration-v1550-IEs OPTIONAL +} + +MeasurementTimingConfiguration-v1550-IEs ::= SEQUENCE { + campOnFirstSSB BOOLEAN, + psCellOnlyOnFirstSSB BOOLEAN, + nonCriticalExtension MeasurementTimingConfiguration-v1610-IEs OPTIONAL +} + +MeasurementTimingConfiguration-v1610-IEs ::= SEQUENCE { + csi-RS-Config-r16 SEQUENCE { + csi-RS-SubcarrierSpacing-r16 SubcarrierSpacing, + csi-RS-CellMobility-r16 CSI-RS-CellMobility, + refSSBFreq-r16 ARFCN-ValueNR + }, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +MeasTimingList ::= SEQUENCE (SIZE (1..maxMeasFreqsMN)) OF MeasTiming + +MeasTiming ::= SEQUENCE { + frequencyAndTiming SEQUENCE { + carrierFreq ARFCN-ValueNR, + ssbSubcarrierSpacing SubcarrierSpacing, + ssb-MeasurementTimingConfiguration SSB-MTC, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL + } OPTIONAL, +..., + [[ + ssb-ToMeasure SSB-ToMeasure OPTIONAL, + physCellId PhysCellId OPTIONAL + ]] +} + +-- TAG-MEASUREMENT-TIMING-CONFIGURATION-STOP +-- TAG-UE-RADIO-PAGING-INFORMATION-START + +UERadioPagingInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioPagingInformation UERadioPagingInformation-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioPagingInformation-IEs ::= SEQUENCE { + supportedBandListNRForPaging SEQUENCE (SIZE (1..maxBands)) OF FreqBandIndicatorNR OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +-- TAG-UE-RADIO-PAGING-INFORMATION-STOP +-- TAG-UE-RADIO-ACCESS-CAPABILITY-INFORMATION-START + +UERadioAccessCapabilityInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioAccessCapabilityInformation UERadioAccessCapabilityInformation-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioAccessCapabilityInformation-IEs ::= SEQUENCE { + ue-RadioAccessCapabilityInfo OCTET STRING (CONTAINING UE-CapabilityRAT-ContainerList), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UE-RADIO-ACCESS-CAPABILITY-INFORMATION-STOP +-- TAG-NR-MULTIPLICITY-AND-CONSTRAINTS-START + +maxMeasFreqsMN INTEGER ::= 32 -- Maximum number of MN-configured measurement frequencies +maxMeasFreqsSN INTEGER ::= 32 -- Maximum number of SN-configured measurement frequencies +maxMeasIdentitiesMN INTEGER ::= 62 -- Maximum number of measurement identities that a UE can be configured with +maxCellPrep INTEGER ::= 32 -- Maximum number of cells prepared for handover + +-- TAG-NR-MULTIPLICITY-AND-CONSTRAINTS-STOP + +-- TAG-NR-INTER-NODE-DEFINITIONS-END-START + +END + +-- TAG-NR-INTER-NODE-DEFINITIONS-END-STOP diff --git a/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1 b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1 new file mode 100644 index 0000000000..80112fa2ff --- /dev/null +++ b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1 @@ -0,0 +1,14304 @@ +NR-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- TAG-BCCH-BCH-MESSAGE-START + +BCCH-BCH-Message ::= SEQUENCE { + message BCCH-BCH-MessageType +} + +BCCH-BCH-MessageType ::= CHOICE { + mib MIB, + messageClassExtension SEQUENCE {} +} + +-- TAG-BCCH-BCH-MESSAGE-STOP +-- TAG-BCCH-DL-SCH-MESSAGE-START + +BCCH-DL-SCH-Message ::= SEQUENCE { + message BCCH-DL-SCH-MessageType +} + +BCCH-DL-SCH-MessageType ::= CHOICE { + c1 CHOICE { + systemInformation SystemInformation, + systemInformationBlockType1 SIB1 + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-BCCH-DL-SCH-MESSAGE-STOP +-- TAG-DL-CCCH-MESSAGE-START + +DL-CCCH-Message ::= SEQUENCE { + message DL-CCCH-MessageType +} + +DL-CCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcReject RRCReject, + rrcSetup RRCSetup, + spare2 NULL, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-DL-CCCH-MESSAGE-STOP +-- TAG-DL-DCCH-MESSAGE-START + +DL-DCCH-Message ::= SEQUENCE { + message DL-DCCH-MessageType +} + +DL-DCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcReconfiguration RRCReconfiguration, + rrcResume RRCResume, + rrcRelease RRCRelease, + rrcReestablishment RRCReestablishment, + securityModeCommand SecurityModeCommand, + dlInformationTransfer DLInformationTransfer, + ueCapabilityEnquiry UECapabilityEnquiry, + counterCheck CounterCheck, + mobilityFromNRCommand MobilityFromNRCommand, + dlDedicatedMessageSegment-r16 DLDedicatedMessageSegment-r16, + ueInformationRequest-r16 UEInformationRequest-r16, + dlInformationTransferMRDC-r16 DLInformationTransferMRDC-r16, + loggedMeasurementConfiguration-r16 LoggedMeasurementConfiguration-r16, + spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-DL-DCCH-MESSAGE-STOP +-- TAG-PCCH-PCH-MESSAGE-START + +PCCH-Message ::= SEQUENCE { + message PCCH-MessageType +} + +PCCH-MessageType ::= CHOICE { + c1 CHOICE { + paging Paging, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-PCCH-PCH-MESSAGE-STOP +-- TAG-UL-CCCH-MESSAGE-START + + +UL-CCCH-Message ::= SEQUENCE { + message UL-CCCH-MessageType +} + +UL-CCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcSetupRequest RRCSetupRequest, + rrcResumeRequest RRCResumeRequest, + rrcReestablishmentRequest RRCReestablishmentRequest, + rrcSystemInfoRequest RRCSystemInfoRequest + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-UL-CCCH-MESSAGE-STOP +-- TAG-UL-CCCH1-MESSAGE-START + + +UL-CCCH1-Message ::= SEQUENCE { + message UL-CCCH1-MessageType +} + +UL-CCCH1-MessageType ::= CHOICE { + c1 CHOICE { + rrcResumeRequest1 RRCResumeRequest1, + spare3 NULL, + spare2 NULL, + spare1 NULL + + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-UL-CCCH1-MESSAGE-STOP +-- TAG-UL-DCCH-MESSAGE-START + +UL-DCCH-Message ::= SEQUENCE { + message UL-DCCH-MessageType +} + +UL-DCCH-MessageType ::= CHOICE { + c1 CHOICE { + measurementReport MeasurementReport, + rrcReconfigurationComplete RRCReconfigurationComplete, + rrcSetupComplete RRCSetupComplete, + rrcReestablishmentComplete RRCReestablishmentComplete, + rrcResumeComplete RRCResumeComplete, + securityModeComplete SecurityModeComplete, + securityModeFailure SecurityModeFailure, + ulInformationTransfer ULInformationTransfer, + locationMeasurementIndication LocationMeasurementIndication, + ueCapabilityInformation UECapabilityInformation, + counterCheckResponse CounterCheckResponse, + ueAssistanceInformation UEAssistanceInformation, + failureInformation FailureInformation, + ulInformationTransferMRDC ULInformationTransferMRDC, + scgFailureInformation SCGFailureInformation, + scgFailureInformationEUTRA SCGFailureInformationEUTRA + }, + messageClassExtension CHOICE { + c2 CHOICE { + ulDedicatedMessageSegment-r16 ULDedicatedMessageSegment-r16, + dedicatedSIBRequest-r16 DedicatedSIBRequest-r16, + mcgFailureInformation-r16 MCGFailureInformation-r16, + ueInformationResponse-r16 UEInformationResponse-r16, + sidelinkUEInformationNR-r16 SidelinkUEInformationNR-r16, + ulInformationTransferIRAT-r16 ULInformationTransferIRAT-r16, + iabOtherInformation-r16 IABOtherInformation-r16, + spare9 NULL, spare8 NULL, spare7 NULL, spare6 NULL, + spare5 NULL, spare4 NULL, spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtensionFuture-r16 SEQUENCE {} + } +} + +-- TAG-UL-DCCH-MESSAGE-STOP +-- TAG-COUNTERCHECK-START + + +CounterCheck ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + counterCheck CounterCheck-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CounterCheck-IEs ::= SEQUENCE { + drb-CountMSB-InfoList DRB-CountMSB-InfoList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +DRB-CountMSB-InfoList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-CountMSB-Info + +DRB-CountMSB-Info ::= SEQUENCE { + drb-Identity DRB-Identity, + countMSB-Uplink INTEGER(0..33554431), + countMSB-Downlink INTEGER(0..33554431) +} + +-- TAG-COUNTERCHECK-STOP +-- TAG-COUNTERCHECKRESPONSE-START + +CounterCheckResponse ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + counterCheckResponse CounterCheckResponse-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CounterCheckResponse-IEs ::= SEQUENCE { + drb-CountInfoList DRB-CountInfoList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL + +} + +DRB-CountInfoList ::= SEQUENCE (SIZE (0..maxDRB)) OF DRB-CountInfo + +DRB-CountInfo ::= SEQUENCE { + drb-Identity DRB-Identity, + count-Uplink INTEGER(0..4294967295), + count-Downlink INTEGER(0..4294967295) +} + +-- TAG-COUNTERCHECKRESPONSE-STOP +-- TAG-DEDICATEDSIBREQUEST-START + +DedicatedSIBRequest-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + dedicatedSIBRequest-r16 DedicatedSIBRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DedicatedSIBRequest-r16-IEs ::= SEQUENCE { + onDemandSIB-RequestList-r16 SEQUENCE { + + requestedSIB-List-r16 SEQUENCE (SIZE (1..maxOnDemandSIB-r16)) OF SIB-ReqInfo-r16 OPTIONAL, + requestedPosSIB-List-r16 SEQUENCE (SIZE (1..maxOnDemandPosSIB-r16)) OF PosSIB-ReqInfo-r16 OPTIONAL + } OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SIB-ReqInfo-r16 ::= ENUMERATED { sib12, sib13, sib14, spare5, spare4, spare3, spare2, spare1 } + +PosSIB-ReqInfo-r16 ::= SEQUENCE { + gnss-id-r16 GNSS-ID-r16 OPTIONAL, + sbas-id-r16 SBAS-ID-r16 OPTIONAL, + posSibType-r16 ENUMERATED { posSibType1-1, posSibType1-2, posSibType1-3, posSibType1-4, posSibType1-5, posSibType1-6, + posSibType1-7, posSibType1-8, posSibType2-1, posSibType2-2, posSibType2-3, posSibType2-4, + posSibType2-5, posSibType2-6, posSibType2-7, posSibType2-8, posSibType2-9, posSibType2-10, + posSibType2-11, posSibType2-12, posSibType2-13, posSibType2-14, posSibType2-15, + posSibType2-16, posSibType2-17, posSibType2-18, posSibType2-19, posSibType2-20, + posSibType2-21, posSibType2-22, posSibType2-23, posSibType3-1, posSibType4-1, + posSibType5-1, posSibType6-1, posSibType6-2, posSibType6-3,... } +} + +-- TAG-DEDICATEDSIBREQUEST-STOP +-- TAG-DLDEDICATEDMESSAGESEGMENT-START + + +DLDedicatedMessageSegment-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + dlDedicatedMessageSegment-r16 DLDedicatedMessageSegment-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLDedicatedMessageSegment-r16-IEs ::= SEQUENCE { + segmentNumber-r16 INTEGER(0..4), + rrc-MessageSegmentContainer-r16 OCTET STRING, + rrc-MessageSegmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLDEDICATEDMESSAGESEGMENT-STOP +-- TAG-DLINFORMATIONTRANSFER-START + +DLInformationTransfer ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + dlInformationTransfer DLInformationTransfer-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLInformationTransfer-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension DLInformationTransfer-v1610-IEs OPTIONAL +} + +DLInformationTransfer-v1610-IEs ::= SEQUENCE { + referenceTimeInfo-r16 ReferenceTimeInfo-r16 OPTIONAL, -- Need R + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLINFORMATIONTRANSFER-STOP +-- TAG-DLINFORMATIONTRANSFERMRDC-START + +DLInformationTransferMRDC-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + dlInformationTransferMRDC-r16 DLInformationTransferMRDC-r16-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLInformationTransferMRDC-r16-IEs::= SEQUENCE { + dl-DCCH-MessageNR-r16 OCTET STRING OPTIONAL, -- Need N + dl-DCCH-MessageEUTRA-r16 OCTET STRING OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLINFORMATIONTRANSFERMRDC-STOP +-- TAG-FAILUREINFORMATION-START + +FailureInformation ::= SEQUENCE { + criticalExtensions CHOICE { + failureInformation FailureInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +FailureInformation-IEs ::= SEQUENCE { + failureInfoRLC-Bearer FailureInfoRLC-Bearer OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension FailureInformation-v1610-IEs OPTIONAL +} + +FailureInfoRLC-Bearer ::= SEQUENCE { + cellGroupId CellGroupId, + logicalChannelIdentity LogicalChannelIdentity, + failureType ENUMERATED {rlc-failure, spare3, spare2, spare1} +} + +FailureInformation-v1610-IEs ::= SEQUENCE { + failureInfoDAPS-r16 FailureInfoDAPS-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureInfoDAPS-r16 ::= SEQUENCE { + failureType-r16 ENUMERATED {daps-failure, spare3, spare2, spare1} +} + +-- TAG-FAILUREINFORMATION-STOP +-- TAG-IABOTHERINFORMATION-START + +IABOtherInformation-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + iabOtherInformation-r16 IABOtherInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +IABOtherInformation-r16-IEs ::= SEQUENCE { + ip-InfoType-r16 CHOICE { + iab-IP-Request-r16 SEQUENCE { + iab-IPv4-AddressNumReq-r16 IAB-IP-AddressNumReq-r16 OPTIONAL, + iab-IPv6-AddressReq-r16 CHOICE { + iab-IPv6-AddressNumReq-r16 IAB-IP-AddressNumReq-r16, + iab-IPv6-AddressPrefixReq-r16 IAB-IP-AddressPrefixReq-r16, + ... + } OPTIONAL + }, + iab-IP-Report-r16 SEQUENCE { + iab-IPv4-AddressReport-r16 IAB-IP-AddressAndTraffic-r16 OPTIONAL, + iab-IPv6-Report-r16 CHOICE { + iab-IPv6-AddressReport-r16 IAB-IP-AddressAndTraffic-r16, + iab-IPv6-PrefixReport-r16 IAB-IP-PrefixAndTraffic-r16, + ... + } OPTIONAL + }, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +IAB-IP-AddressNumReq-r16 ::= SEQUENCE { + all-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + f1-C-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + f1-U-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + non-F1-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + ... +} + +IAB-IP-AddressPrefixReq-r16 ::= SEQUENCE { + all-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + f1-C-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + f1-U-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + non-F1-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + ... +} + +IAB-IP-AddressAndTraffic-r16 ::= SEQUENCE { + all-Traffic-IAB-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + f1-C-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + f1-U-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + non-F1-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL +} + +IAB-IP-PrefixAndTraffic-r16 ::= SEQUENCE { + all-Traffic-IAB-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + f1-C-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + f1-U-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + non-F1-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL +} + +-- TAG-IABOTHERINFORMATION-STOP +-- TAG-LOCATIONMEASUREMENTINDICATION-START + +LocationMeasurementIndication ::= SEQUENCE { + criticalExtensions CHOICE { + locationMeasurementIndication LocationMeasurementIndication-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +LocationMeasurementIndication-IEs ::= SEQUENCE { + measurementIndication SetupRelease {LocationMeasurementInfo}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-LOCATIONMEASUREMENTINDICATION-STOP +-- TAG-LOGGEDMEASUREMENTCONFIGURATION-START + +LoggedMeasurementConfiguration-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + loggedMeasurementConfiguration-r16 LoggedMeasurementConfiguration-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +LoggedMeasurementConfiguration-r16-IEs ::= SEQUENCE { + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + absoluteTimeInfo-r16 AbsoluteTimeInfo-r16, + areaConfiguration-r16 AreaConfiguration-r16 OPTIONAL, --Need R + plmn-IdentityList-r16 PLMN-IdentityList2-r16 OPTIONAL, --Need R + bt-NameList-r16 SetupRelease {BT-NameList-r16} OPTIONAL, --Need M + wlan-NameList-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, --Need M + sensor-NameList-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, --Need M + loggingDuration-r16 LoggingDuration-r16, + reportType CHOICE { + periodical LoggedPeriodicalReportConfig-r16, + eventTriggered LoggedEventTriggerConfig-r16, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +LoggedPeriodicalReportConfig-r16 ::= SEQUENCE { + loggingInterval-r16 LoggingInterval-r16, + ... + } + +LoggedEventTriggerConfig-r16 ::= SEQUENCE { + eventType-r16 EventType-r16, + loggingInterval-r16 LoggingInterval-r16, + ... +} + +EventType-r16 ::= CHOICE { + outOfCoverage NULL, + eventL1 SEQUENCE { + l1-Threshold MeasTriggerQuantity, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + ... +} + +-- TAG-LOGGEDMEASUREMENTCONFIGURATION-STOP +-- TAG-MCGFAILUREINFORMATION-START + +MCGFailureInformation-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + mcgFailureInformation-r16 MCGFailureInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MCGFailureInformation-r16-IEs ::= SEQUENCE { + failureReportMCG-r16 FailureReportMCG-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportMCG-r16 ::= SEQUENCE { + failureType-r16 ENUMERATED {t310-Expiry, randomAccessProblem, rlc-MaxNumRetx, + t312-Expiry-r16, lbt-Failure-r16, beamFailureRecoveryFailure-r16, + bh-RLF-r16, spare1} OPTIONAL, + measResultFreqList-r16 MeasResultList2NR OPTIONAL, + measResultFreqListEUTRA-r16 MeasResultList2EUTRA OPTIONAL, + measResultSCG-r16 OCTET STRING (CONTAINING MeasResultSCG-Failure) OPTIONAL, + measResultSCG-EUTRA-r16 OCTET STRING OPTIONAL, + measResultFreqListUTRA-FDD-r16 MeasResultList2UTRA OPTIONAL, + ... +} + +MeasResultList2UTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2UTRA-FDD-r16 + +MeasResult2UTRA-FDD-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueUTRA-FDD-r16, + measResultNeighCellList-r16 MeasResultListUTRA-FDD-r16 +} + +MeasResultList2EUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2EUTRA-r16 + +-- TAG-MCGFAILUREINFORMATION-STOP +-- TAG-MEASUREMENTREPORT-START + +MeasurementReport ::= SEQUENCE { + criticalExtensions CHOICE { + measurementReport MeasurementReport-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementReport-IEs ::= SEQUENCE { + measResults MeasResults, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-MEASUREMENTREPORT-STOP +-- TAG-MIB-START + +MIB ::= SEQUENCE { + systemFrameNumber BIT STRING (SIZE (6)), + subCarrierSpacingCommon ENUMERATED {scs15or60, scs30or120}, + ssb-SubcarrierOffset INTEGER (0..15), + dmrs-TypeA-Position ENUMERATED {pos2, pos3}, + pdcch-ConfigSIB1 PDCCH-ConfigSIB1, + cellBarred ENUMERATED {barred, notBarred}, + intraFreqReselection ENUMERATED {allowed, notAllowed}, + spare BIT STRING (SIZE (1)) +} + +-- TAG-MIB-STOP +-- TAG-MOBILITYFROMNRCOMMAND-START + +MobilityFromNRCommand ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + mobilityFromNRCommand MobilityFromNRCommand-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MobilityFromNRCommand-IEs ::= SEQUENCE { + targetRAT-Type ENUMERATED { eutra, utra-fdd-v1610, spare2, spare1, ...}, + targetRAT-MessageContainer OCTET STRING, + nas-SecurityParamFromNR OCTET STRING OPTIONAL, -- Cond HO-ToEPCUTRAN + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension MobilityFromNRCommand-v1610-IEs OPTIONAL +} + +MobilityFromNRCommand-v1610-IEs ::= SEQUENCE { + voiceFallbackIndication-r16 ENUMERATED {true} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-MOBILITYFROMNRCOMMAND-STOP +-- TAG-PAGING-START + +Paging ::= SEQUENCE { + pagingRecordList PagingRecordList OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +PagingRecordList ::= SEQUENCE (SIZE(1..maxNrofPageRec)) OF PagingRecord + +PagingRecord ::= SEQUENCE { + ue-Identity PagingUE-Identity, + accessType ENUMERATED {non3GPP} OPTIONAL, -- Need N + ... +} + +PagingUE-Identity ::= CHOICE { + ng-5G-S-TMSI NG-5G-S-TMSI, + fullI-RNTI I-RNTI-Value, + ... +} + +-- TAG-PAGING-STOP +-- TAG-RRCREESTABLISHMENT-START + +RRCReestablishment ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReestablishment RRCReestablishment-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReestablishment-IEs ::= SEQUENCE { + nextHopChainingCount NextHopChainingCount, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCREESTABLISHMENT-STOP +-- TAG-RRCREESTABLISHMENTCOMPLETE-START + +RRCReestablishmentComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReestablishmentComplete RRCReestablishmentComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReestablishmentComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReestablishmentComplete-v1610-IEs OPTIONAL +} + +RRCReestablishmentComplete-v1610-IEs ::= SEQUENCE { + ue-MeasurementsAvailable-r16 UE-MeasurementsAvailable-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCREESTABLISHMENTCOMPLETE-STOP +-- TAG-RRCREESTABLISHMENTREQUEST-START + + +RRCReestablishmentRequest ::= SEQUENCE { + rrcReestablishmentRequest RRCReestablishmentRequest-IEs +} + +RRCReestablishmentRequest-IEs ::= SEQUENCE { + ue-Identity ReestabUE-Identity, + reestablishmentCause ReestablishmentCause, + spare BIT STRING (SIZE (1)) +} + +ReestabUE-Identity ::= SEQUENCE { + c-RNTI RNTI-Value, + physCellId PhysCellId, + shortMAC-I ShortMAC-I +} + +ReestablishmentCause ::= ENUMERATED {reconfigurationFailure, handoverFailure, otherFailure, spare1} + +-- TAG-RRCREESTABLISHMENTREQUEST-STOP +-- TAG-RRCRECONFIGURATION-START + +RRCReconfiguration ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfiguration RRCReconfiguration-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfiguration-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig OPTIONAL, -- Need M + secondaryCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Cond SCG + measConfig MeasConfig OPTIONAL, -- Need M + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReconfiguration-v1530-IEs OPTIONAL +} + +RRCReconfiguration-v1530-IEs ::= SEQUENCE { + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Need M + fullConfig ENUMERATED {true} OPTIONAL, -- Cond FullConfig + dedicatedNAS-MessageList SEQUENCE (SIZE(1..maxDRB)) OF DedicatedNAS-Message OPTIONAL, -- Cond nonHO + masterKeyUpdate MasterKeyUpdate OPTIONAL, -- Cond MasterKeyChange + dedicatedSIB1-Delivery OCTET STRING (CONTAINING SIB1) OPTIONAL, -- Need N + dedicatedSystemInformationDelivery OCTET STRING (CONTAINING SystemInformation) OPTIONAL, -- Need N + otherConfig OtherConfig OPTIONAL, -- Need M + nonCriticalExtension RRCReconfiguration-v1540-IEs OPTIONAL +} + +RRCReconfiguration-v1540-IEs ::= SEQUENCE { + otherConfig-v1540 OtherConfig-v1540 OPTIONAL, -- Need M + nonCriticalExtension RRCReconfiguration-v1560-IEs OPTIONAL +} + +RRCReconfiguration-v1560-IEs ::= SEQUENCE { + mrdc-SecondaryCellGroupConfig SetupRelease { MRDC-SecondaryCellGroupConfig } OPTIONAL, -- Need M + radioBearerConfig2 OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, -- Need M + sk-Counter SK-Counter OPTIONAL, -- Need N + nonCriticalExtension RRCReconfiguration-v1610-IEs OPTIONAL +} +RRCReconfiguration-v1610-IEs ::= SEQUENCE { + otherConfig-v1610 OtherConfig-v1610 OPTIONAL, -- Need M + bap-Config-r16 SetupRelease { BAP-Config-r16 } OPTIONAL, -- Need M + iab-IP-AddressConfigurationList-r16 IAB-IP-AddressConfigurationList-r16 OPTIONAL, -- Need M + conditionalReconfiguration-r16 ConditionalReconfiguration-r16 OPTIONAL, -- Need M + daps-SourceRelease-r16 ENUMERATED{true} OPTIONAL, -- Need N + t316-r16 SetupRelease {T316-r16} OPTIONAL, -- Need M + needForGapsConfigNR-r16 SetupRelease {NeedForGapsConfigNR-r16} OPTIONAL, -- Need M + onDemandSIB-Request-r16 SetupRelease { OnDemandSIB-Request-r16 } OPTIONAL, -- Need M + dedicatedPosSysInfoDelivery-r16 OCTET STRING (CONTAINING PosSystemInformation-r16-IEs) OPTIONAL, -- Need N + sl-ConfigDedicatedNR-r16 SetupRelease {SL-ConfigDedicatedNR-r16} OPTIONAL, -- Need M + sl-ConfigDedicatedEUTRA-Info-r16 SetupRelease {SL-ConfigDedicatedEUTRA-Info-r16} OPTIONAL, -- Need M + targetCellSMTC-SCG-r16 SSB-MTC OPTIONAL, -- Need S + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +MRDC-SecondaryCellGroupConfig ::= SEQUENCE { + mrdc-ReleaseAndAdd ENUMERATED {true} OPTIONAL, -- Need N + mrdc-SecondaryCellGroup CHOICE { + nr-SCG OCTET STRING (CONTAINING RRCReconfiguration), + eutra-SCG OCTET STRING + } +} + +BAP-Config-r16 ::= SEQUENCE { + bap-Address-r16 BIT STRING (SIZE (10)) OPTIONAL, -- Need M + defaultUL-BAP-RoutingID-r16 BAP-RoutingID-r16 OPTIONAL, -- Need M + defaultUL-BH-RLC-Channel-r16 BH-RLC-ChannelID-r16 OPTIONAL, -- Need M + flowControlFeedbackType-r16 ENUMERATED {perBH-RLC-Channel, perRoutingID, both} OPTIONAL, -- Need R + ... +} + +MasterKeyUpdate ::= SEQUENCE { + keySetChangeIndicator BOOLEAN, + nextHopChainingCount NextHopChainingCount, + nas-Container OCTET STRING OPTIONAL, -- Cond securityNASC + ... +} + +OnDemandSIB-Request-r16 ::= SEQUENCE { + onDemandSIB-RequestProhibitTimer-r16 ENUMERATED {s0, s0dot5, s1, s2, s5, s10, s20, s30} +} + +T316-r16 ::= ENUMERATED {ms50, ms100, ms200, ms300, ms400, ms500, ms600, ms1000, ms1500, ms2000} + +IAB-IP-AddressConfigurationList-r16 ::= SEQUENCE { + iab-IP-AddressToAddModList-r16 SEQUENCE (SIZE(1..maxIAB-IP-Address-r16)) OF IAB-IP-AddressConfiguration-r16 OPTIONAL, -- Need N + iab-IP-AddressToReleaseList-r16 SEQUENCE (SIZE(1..maxIAB-IP-Address-r16)) OF IAB-IP-AddressIndex-r16 OPTIONAL, -- Need N + ... +} + +IAB-IP-AddressConfiguration-r16 ::= SEQUENCE { + iab-IP-AddressIndex-r16 IAB-IP-AddressIndex-r16, + iab-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, -- Need M + iab-IP-Usage-r16 IAB-IP-Usage-r16 OPTIONAL, -- Need M + iab-donor-DU-BAP-Address-r16 BIT STRING (SIZE(10)) OPTIONAL, -- Need M +... +} + +SL-ConfigDedicatedEUTRA-Info-r16 ::= SEQUENCE { + sl-ConfigDedicatedEUTRA-r16 OCTET STRING OPTIONAL, -- Need M + sl-TimeOffsetEUTRA-List-r16 SEQUENCE (SIZE (8)) OF SL-TimeOffsetEUTRA-r16 OPTIONAL -- Need M +} + +SL-TimeOffsetEUTRA-r16 ::= ENUMERATED {ms0, ms0dot25, ms0dot5, ms0dot625, ms0dot75, ms1, ms1dot25, ms1dot5, ms1dot75, + ms2, ms2dot5, ms3, ms4, ms5, ms6, ms8, ms10, ms20} + +-- TAG-RRCRECONFIGURATION-STOP +-- TAG-RRCRECONFIGURATIONCOMPLETE-START + +RRCReconfigurationComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationComplete RRCReconfigurationComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1530-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1530-IEs ::= SEQUENCE { + uplinkTxDirectCurrentList UplinkTxDirectCurrentList OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1560-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1560-IEs ::= SEQUENCE { + scg-Response CHOICE { + nr-SCG-Response OCTET STRING (CONTAINING RRCReconfigurationComplete), + eutra-SCG-Response OCTET STRING + } OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1610-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1610-IEs ::= SEQUENCE { + ue-MeasurementsAvailable-r16 UE-MeasurementsAvailable-r16 OPTIONAL, + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1640-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1640-IEs ::= SEQUENCE { + uplinkTxDirectCurrentTwoCarrierList-r16 UplinkTxDirectCurrentTwoCarrierList-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRECONFIGURATIONCOMPLETE-STOP +-- TAG-RRCREJECT-START + +RRCReject ::= SEQUENCE { + criticalExtensions CHOICE { + rrcReject RRCReject-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReject-IEs ::= SEQUENCE { + waitTime RejectWaitTime OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCREJECT-STOP +-- TAG-RRCRELEASE-START + +RRCRelease ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcRelease RRCRelease-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCRelease-IEs ::= SEQUENCE { + redirectedCarrierInfo RedirectedCarrierInfo OPTIONAL, -- Need N + cellReselectionPriorities CellReselectionPriorities OPTIONAL, -- Need R + suspendConfig SuspendConfig OPTIONAL, -- Need R + deprioritisationReq SEQUENCE { + deprioritisationType ENUMERATED {frequency, nr}, + deprioritisationTimer ENUMERATED {min5, min10, min15, min30} + } OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCRelease-v1540-IEs OPTIONAL +} + +RRCRelease-v1540-IEs ::= SEQUENCE { + waitTime RejectWaitTime OPTIONAL, -- Need N + nonCriticalExtension RRCRelease-v1610-IEs OPTIONAL +} + +RRCRelease-v1610-IEs ::= SEQUENCE { + voiceFallbackIndication-r16 ENUMERATED {true} OPTIONAL, -- Need N + measIdleConfig-r16 SetupRelease {MeasIdleConfigDedicated-r16} OPTIONAL, -- Need M + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +RedirectedCarrierInfo ::= CHOICE { + nr CarrierInfoNR, + eutra RedirectedCarrierInfo-EUTRA, + ... +} + +RedirectedCarrierInfo-EUTRA ::= SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cnType ENUMERATED {epc,fiveGC} OPTIONAL -- Need N +} + +CarrierInfoNR ::= SEQUENCE { + carrierFreq ARFCN-ValueNR, + ssbSubcarrierSpacing SubcarrierSpacing, + smtc SSB-MTC OPTIONAL, -- Need S + ... +} + +SuspendConfig ::= SEQUENCE { + fullI-RNTI I-RNTI-Value, + shortI-RNTI ShortI-RNTI-Value, + ran-PagingCycle PagingCycle, + ran-NotificationAreaInfo RAN-NotificationAreaInfo OPTIONAL, -- Need M + t380 PeriodicRNAU-TimerValue OPTIONAL, -- Need R + nextHopChainingCount NextHopChainingCount, + ... +} + +PeriodicRNAU-TimerValue ::= ENUMERATED { min5, min10, min20, min30, min60, min120, min360, min720} + + +CellReselectionPriorities ::= SEQUENCE { + freqPriorityListEUTRA FreqPriorityListEUTRA OPTIONAL, -- Need M + freqPriorityListNR FreqPriorityListNR OPTIONAL, -- Need M + t320 ENUMERATED {min5, min10, min20, min30, min60, min120, min180, spare1} OPTIONAL, -- Need R + ... +} + +PagingCycle ::= ENUMERATED {rf32, rf64, rf128, rf256} + +FreqPriorityListEUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA + +FreqPriorityListNR ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityNR + +FreqPriorityEUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL -- Need R +} + +FreqPriorityNR ::= SEQUENCE { + carrierFreq ARFCN-ValueNR, + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL -- Need R +} + +RAN-NotificationAreaInfo ::= CHOICE { + cellList PLMN-RAN-AreaCellList, + ran-AreaConfigList PLMN-RAN-AreaConfigList, + ... +} + +PLMN-RAN-AreaCellList ::= SEQUENCE (SIZE (1.. maxPLMNIdentities)) OF PLMN-RAN-AreaCell + +PLMN-RAN-AreaCell ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, -- Need S + ran-AreaCells SEQUENCE (SIZE (1..32)) OF CellIdentity +} + +PLMN-RAN-AreaConfigList ::= SEQUENCE (SIZE (1..maxPLMNIdentities)) OF PLMN-RAN-AreaConfig + +PLMN-RAN-AreaConfig ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, -- Need S + ran-Area SEQUENCE (SIZE (1..16)) OF RAN-AreaConfig +} + +RAN-AreaConfig ::= SEQUENCE { + trackingAreaCode TrackingAreaCode, + ran-AreaCodeList SEQUENCE (SIZE (1..32)) OF RAN-AreaCode OPTIONAL -- Need R +} + +-- TAG-RRCRELEASE-STOP +-- TAG-RRCRESUME-START + +RRCResume ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcResume RRCResume-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCResume-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig OPTIONAL, -- Need M + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Need M + measConfig MeasConfig OPTIONAL, -- Need M + fullConfig ENUMERATED {true} OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCResume-v1560-IEs OPTIONAL +} + +RRCResume-v1560-IEs ::= SEQUENCE { + radioBearerConfig2 OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, -- Need M + sk-Counter SK-Counter OPTIONAL, -- Need N + nonCriticalExtension RRCResume-v1610-IEs OPTIONAL +} + +RRCResume-v1610-IEs ::= SEQUENCE { + idleModeMeasurementReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + restoreMCG-SCells-r16 ENUMERATED {true} OPTIONAL, -- Need N + restoreSCG-r16 ENUMERATED {true} OPTIONAL, -- Need N + mrdc-SecondaryCellGroup-r16 CHOICE { + nr-SCG-r16 OCTET STRING (CONTAINING RRCReconfiguration), + eutra-SCG-r16 OCTET STRING + } OPTIONAL, -- Cond RestoreSCG + needForGapsConfigNR-r16 SetupRelease {NeedForGapsConfigNR-r16} OPTIONAL, -- Need M + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCRESUME-STOP +-- TAG-RRCRESUMECOMPLETE-START + +RRCResumeComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcResumeComplete RRCResumeComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCResumeComplete-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, + selectedPLMN-Identity INTEGER (1..maxPLMN) OPTIONAL, + uplinkTxDirectCurrentList UplinkTxDirectCurrentList OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCResumeComplete-v1610-IEs OPTIONAL +} + +RRCResumeComplete-v1610-IEs ::= SEQUENCE { + idleMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + measResultIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL, + measResultIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + scg-Response-r16 CHOICE { + nr-SCG-Response OCTET STRING (CONTAINING RRCReconfigurationComplete), + eutra-SCG-Response OCTET STRING + } OPTIONAL, + ue-MeasurementsAvailable-r16 UE-MeasurementsAvailable-r16 OPTIONAL, + mobilityHistoryAvail-r16 ENUMERATED {true} OPTIONAL, + mobilityState-r16 ENUMERATED {normal, medium, high, spare} OPTIONAL, + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL, + nonCriticalExtension RRCResumeComplete-v1640-IEs OPTIONAL +} + +RRCResumeComplete-v1640-IEs ::= SEQUENCE { + uplinkTxDirectCurrentTwoCarrierList-r16 UplinkTxDirectCurrentTwoCarrierList-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRESUMECOMPLETE-STOP +-- TAG-RRCRESUMEREQUEST-START + +RRCResumeRequest ::= SEQUENCE { + rrcResumeRequest RRCResumeRequest-IEs +} + +RRCResumeRequest-IEs ::= SEQUENCE { + resumeIdentity ShortI-RNTI-Value, + resumeMAC-I BIT STRING (SIZE (16)), + resumeCause ResumeCause, + spare BIT STRING (SIZE (1)) +} + +-- TAG-RRCRESUMEREQUEST-STOP +-- TAG-RRCRESUMEREQUEST1-START + +RRCResumeRequest1 ::= SEQUENCE { + rrcResumeRequest1 RRCResumeRequest1-IEs +} + +RRCResumeRequest1-IEs ::= SEQUENCE { + resumeIdentity I-RNTI-Value, + resumeMAC-I BIT STRING (SIZE (16)), + resumeCause ResumeCause, + spare BIT STRING (SIZE (1)) +} + +-- TAG-RRCRESUMEREQUEST1-STOP +-- TAG-RRCSETUP-START + +RRCSetup ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcSetup RRCSetup-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCSetup-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig, + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig), + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCSETUP-STOP +-- TAG-RRCSETUPCOMPLETE-START + +RRCSetupComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcSetupComplete RRCSetupComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCSetupComplete-IEs ::= SEQUENCE { + selectedPLMN-Identity INTEGER (1..maxPLMN), + registeredAMF RegisteredAMF OPTIONAL, + guami-Type ENUMERATED {native, mapped} OPTIONAL, + s-NSSAI-List SEQUENCE (SIZE (1..maxNrofS-NSSAI)) OF S-NSSAI OPTIONAL, + dedicatedNAS-Message DedicatedNAS-Message, + ng-5G-S-TMSI-Value CHOICE { + ng-5G-S-TMSI NG-5G-S-TMSI, + ng-5G-S-TMSI-Part2 BIT STRING (SIZE (9)) + } OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCSetupComplete-v1610-IEs OPTIONAL +} + +RRCSetupComplete-v1610-IEs ::= SEQUENCE { + iab-NodeIndication-r16 ENUMERATED {true} OPTIONAL, + idleMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + ue-MeasurementsAvailable-r16 UE-MeasurementsAvailable-r16 OPTIONAL, + mobilityHistoryAvail-r16 ENUMERATED {true} OPTIONAL, + mobilityState-r16 ENUMERATED {normal, medium, high, spare} OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +RegisteredAMF ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, + amf-Identifier AMF-Identifier +} + +-- TAG-RRCSETUPCOMPLETE-STOP +-- TAG-RRCSETUPREQUEST-START + +RRCSetupRequest ::= SEQUENCE { + rrcSetupRequest RRCSetupRequest-IEs +} + +RRCSetupRequest-IEs ::= SEQUENCE { + ue-Identity InitialUE-Identity, + establishmentCause EstablishmentCause, + spare BIT STRING (SIZE (1)) +} + +InitialUE-Identity ::= CHOICE { + ng-5G-S-TMSI-Part1 BIT STRING (SIZE (39)), + randomValue BIT STRING (SIZE (39)) +} + +EstablishmentCause ::= ENUMERATED { + emergency, highPriorityAccess, mt-Access, mo-Signalling, + mo-Data, mo-VoiceCall, mo-VideoCall, mo-SMS, mps-PriorityAccess, mcs-PriorityAccess, + spare6, spare5, spare4, spare3, spare2, spare1} + +-- TAG-RRCSETUPREQUEST-STOP +-- TAG-RRCSYSTEMINFOREQUEST-START + +RRCSystemInfoRequest ::= SEQUENCE { + criticalExtensions CHOICE { + rrcSystemInfoRequest RRCSystemInfoRequest-IEs, + criticalExtensionsFuture-r16 CHOICE { + rrcPosSystemInfoRequest-r16 RRC-PosSystemInfoRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } + } +} + +RRCSystemInfoRequest-IEs ::= SEQUENCE { + requested-SI-List BIT STRING (SIZE (maxSI-Message)), --32bits + spare BIT STRING (SIZE (12)) +} + +RRC-PosSystemInfoRequest-r16-IEs ::= SEQUENCE { + requestedPosSI-List BIT STRING (SIZE (maxSI-Message)), --32bits + spare BIT STRING (SIZE (11)) +} + +-- TAG-RRCSYSTEMINFOREQUEST-STOP +-- TAG-SCGFAILUREINFORMATION-START + +SCGFailureInformation ::= SEQUENCE { + criticalExtensions CHOICE { + scgFailureInformation SCGFailureInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCGFailureInformation-IEs ::= SEQUENCE { + failureReportSCG FailureReportSCG OPTIONAL, + nonCriticalExtension SCGFailureInformation-v1590-IEs OPTIONAL +} + +SCGFailureInformation-v1590-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportSCG ::= SEQUENCE { + failureType ENUMERATED { + t310-Expiry, randomAccessProblem, + rlc-MaxNumRetx, + synchReconfigFailureSCG, scg-ReconfigFailure, + srb3-IntegrityFailure, other-r16, spare1}, + measResultFreqList MeasResultFreqList OPTIONAL, + measResultSCG-Failure OCTET STRING (CONTAINING MeasResultSCG-Failure) OPTIONAL, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL, + failureType-v1610 ENUMERATED {scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, bh-RLF-r16, spare4, spare3, spare2, spare1} OPTIONAL + ]] +} + +MeasResultFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2NR + + +-- TAG-SCGFAILUREINFORMATION-STOP +-- TAG-SCGFAILUREINFORMATIONEUTRA-START + +SCGFailureInformationEUTRA ::= SEQUENCE { + criticalExtensions CHOICE { + scgFailureInformationEUTRA SCGFailureInformationEUTRA-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCGFailureInformationEUTRA-IEs ::= SEQUENCE { + failureReportSCG-EUTRA FailureReportSCG-EUTRA OPTIONAL, + nonCriticalExtension SCGFailureInformationEUTRA-v1590-IEs OPTIONAL +} + +SCGFailureInformationEUTRA-v1590-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportSCG-EUTRA ::= SEQUENCE { + failureType ENUMERATED { + t313-Expiry, randomAccessProblem,rlc-MaxNumRetx, + scg-ChangeFailure,scg-lbtFailure-r16, + beamFailureRecoveryFailure-r16, t312-Expiry-r16, spare}, + measResultFreqListMRDC MeasResultFreqListFailMRDC OPTIONAL, + measResultSCG-FailureMRDC OCTET STRING OPTIONAL, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL + ]] +} + +MeasResultFreqListFailMRDC ::= SEQUENCE (SIZE (1.. maxFreq)) OF MeasResult2EUTRA + +-- TAG-SCGFAILUREINFORMATIONEUTRA-STOP +-- TAG-SECURITYMODECOMMAND-START + +SecurityModeCommand ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeCommand SecurityModeCommand-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeCommand-IEs ::= SEQUENCE { + securityConfigSMC SecurityConfigSMC, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +SecurityConfigSMC ::= SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig, + ... +} + +-- TAG-SECURITYMODECOMMAND-STOP +-- TAG-SECURITYMODECOMPLETE-START + +SecurityModeComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeComplete SecurityModeComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-SECURITYMODECOMPLETE-STOP +-- TAG-SECURITYMODEFAILURE-START + +SecurityModeFailure ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeFailure SecurityModeFailure-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeFailure-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-SECURITYMODEFAILURE-STOP +-- TAG-SIB1-START + +SIB1 ::= SEQUENCE { + cellSelectionInfo SEQUENCE { + q-RxLevMin Q-RxLevMin, + q-RxLevMinOffset INTEGER (1..8) OPTIONAL, -- Need S + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + q-QualMinOffset INTEGER (1..8) OPTIONAL -- Need S + } OPTIONAL, -- Cond Standalone + cellAccessRelatedInfo CellAccessRelatedInfo, + connEstFailureControl ConnEstFailureControl OPTIONAL, -- Need R + si-SchedulingInfo SI-SchedulingInfo OPTIONAL, -- Need R + servingCellConfigCommon ServingCellConfigCommonSIB OPTIONAL, -- Need R + ims-EmergencySupport ENUMERATED {true} OPTIONAL, -- Need R + eCallOverIMS-Support ENUMERATED {true} OPTIONAL, -- Need R + ue-TimersAndConstants UE-TimersAndConstants OPTIONAL, -- Need R + uac-BarringInfo SEQUENCE { + uac-BarringForCommon UAC-BarringPerCatList OPTIONAL, -- Need S + uac-BarringPerPLMN-List UAC-BarringPerPLMN-List OPTIONAL, -- Need S + uac-BarringInfoSetList UAC-BarringInfoSetList, + uac-AccessCategory1-SelectionAssistanceInfo CHOICE { + plmnCommon UAC-AccessCategory1-SelectionAssistanceInfo, + individualPLMNList SEQUENCE (SIZE (2..maxPLMN)) OF UAC-AccessCategory1-SelectionAssistanceInfo + } OPTIONAL -- Need S + } OPTIONAL, -- Need R + useFullResumeID ENUMERATED {true} OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SIB1-v1610-IEs OPTIONAL +} + +SIB1-v1610-IEs ::= SEQUENCE { + idleModeMeasurementsEUTRA-r16 ENUMERATED{true} OPTIONAL, -- Need R + idleModeMeasurementsNR-r16 ENUMERATED{true} OPTIONAL, -- Need R + posSI-SchedulingInfo-r16 PosSI-SchedulingInfo-r16 OPTIONAL, -- Need R + nonCriticalExtension SIB1-v1630-IEs OPTIONAL +} + +SIB1-v1630-IEs ::= SEQUENCE { + uac-BarringInfo-v1630 SEQUENCE { + uac-AC1-SelectAssistInfo-r16 SEQUENCE (SIZE (2..maxPLMN)) OF UAC-AC1-SelectAssistInfo-r16 + } OPTIONAL, -- Need R + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UAC-AccessCategory1-SelectionAssistanceInfo ::= ENUMERATED {a, b, c} + +UAC-AC1-SelectAssistInfo-r16 ::= ENUMERATED {a, b, c, notConfigured} + +-- TAG-SIB1-STOP +-- TAG-SIDELINKUEINFORMATIONNR-START + +SidelinkUEInformationNR-r16::= SEQUENCE { + criticalExtensions CHOICE { + sidelinkUEInformationNR-r16 SidelinkUEInformationNR-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SidelinkUEInformationNR-r16-IEs ::= SEQUENCE { + sl-RxInterestedFreqList-r16 SL-InterestedFreqList-r16 OPTIONAL, + sl-TxResourceReqList-r16 SL-TxResourceReqList-r16 OPTIONAL, + sl-FailureList-r16 SL-FailureList-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SL-InterestedFreqList-r16 ::= SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF INTEGER (1..maxNrofFreqSL-r16) + +SL-TxResourceReqList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-TxResourceReq-r16 + +SL-TxResourceReq-r16 ::= SEQUENCE { + sl-DestinationIdentity-r16 SL-DestinationIdentity-r16, + sl-CastType-r16 ENUMERATED {broadcast, groupcast, unicast, spare1}, + sl-RLC-ModeIndicationList-r16 SEQUENCE (SIZE (1.. maxNrofSLRB-r16)) OF SL-RLC-ModeIndication-r16 OPTIONAL, + sl-QoS-InfoList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIsPerDest-r16)) OF SL-QoS-Info-r16 OPTIONAL, + sl-TypeTxSyncList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-TypeTxSync-r16 OPTIONAL, + sl-TxInterestedFreqList-r16 SL-TxInterestedFreqList-r16 OPTIONAL, + sl-CapabilityInformationSidelink-r16 OCTET STRING OPTIONAL +} + +SL-TxInterestedFreqList-r16 ::= SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF INTEGER (1..maxNrofFreqSL-r16) + +SL-QoS-Info-r16 ::= SEQUENCE { + sl-QoS-FlowIdentity-r16 SL-QoS-FlowIdentity-r16, + sl-QoS-Profile-r16 SL-QoS-Profile-r16 OPTIONAL +} + +SL-RLC-ModeIndication-r16 ::= SEQUENCE { + sl-Mode-r16 CHOICE { + sl-AM-Mode-r16 NULL, + sl-UM-Mode-r16 NULL + }, + sl-QoS-InfoList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIsPerDest-r16)) OF SL-QoS-Info-r16 +} + +SL-FailureList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-Failure-r16 + +SL-Failure-r16 ::= SEQUENCE { + sl-DestinationIdentity-r16 SL-DestinationIdentity-r16, + sl-Failure-r16 ENUMERATED {rlf,configFailure, spare6, spare5, spare4, spare3, spare2, spare1} +} + +-- TAG-SIDELINKUEINFORMATIONNR-STOP +-- TAG-SYSTEMINFORMATION-START + +SystemInformation ::= SEQUENCE { + criticalExtensions CHOICE { + systemInformation SystemInformation-IEs, + criticalExtensionsFuture-r16 CHOICE { + posSystemInformation-r16 PosSystemInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } + } +} + +SystemInformation-IEs ::= SEQUENCE { + sib-TypeAndInfo SEQUENCE (SIZE (1..maxSIB)) OF CHOICE { + sib2 SIB2, + sib3 SIB3, + sib4 SIB4, + sib5 SIB5, + sib6 SIB6, + sib7 SIB7, + sib8 SIB8, + sib9 SIB9, + ..., + sib10-v1610 SIB10-r16, + sib11-v1610 SIB11-r16, + sib12-v1610 SIB12-r16, + sib13-v1610 SIB13-r16, + sib14-v1610 SIB14-r16 + }, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-SYSTEMINFORMATION-STOP +-- TAG-UEASSISTANCEINFORMATION-START + +UEAssistanceInformation ::= SEQUENCE { + criticalExtensions CHOICE { + ueAssistanceInformation UEAssistanceInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEAssistanceInformation-IEs ::= SEQUENCE { + delayBudgetReport DelayBudgetReport OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UEAssistanceInformation-v1540-IEs OPTIONAL +} + +DelayBudgetReport::= CHOICE { + type1 ENUMERATED { + msMinus1280, msMinus640, msMinus320, msMinus160,msMinus80, msMinus60, msMinus40, + msMinus20, ms0, ms20,ms40, ms60, ms80, ms160, ms320, ms640, ms1280}, + ... +} + +UEAssistanceInformation-v1540-IEs ::= SEQUENCE { + overheatingAssistance OverheatingAssistance OPTIONAL, + nonCriticalExtension UEAssistanceInformation-v1610-IEs OPTIONAL +} + +OverheatingAssistance ::= SEQUENCE { + reducedMaxCCs ReducedMaxCCs-r16 OPTIONAL, + reducedMaxBW-FR1 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxBW-FR2 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxMIMO-LayersFR1 SEQUENCE { + reducedMIMO-LayersFR1-DL MIMO-LayersDL, + reducedMIMO-LayersFR1-UL MIMO-LayersUL + } OPTIONAL, + reducedMaxMIMO-LayersFR2 SEQUENCE { + reducedMIMO-LayersFR2-DL MIMO-LayersDL, + reducedMIMO-LayersFR2-UL MIMO-LayersUL + } OPTIONAL +} + +ReducedAggregatedBandwidth ::= ENUMERATED {mhz0, mhz10, mhz20, mhz30, mhz40, mhz50, mhz60, mhz80, mhz100, mhz200, mhz300, mhz400} + +UEAssistanceInformation-v1610-IEs ::= SEQUENCE { + idc-Assistance-r16 IDC-Assistance-r16 OPTIONAL, + drx-Preference-r16 DRX-Preference-r16 OPTIONAL, + maxBW-Preference-r16 MaxBW-Preference-r16 OPTIONAL, + maxCC-Preference-r16 MaxCC-Preference-r16 OPTIONAL, + maxMIMO-LayerPreference-r16 MaxMIMO-LayerPreference-r16 OPTIONAL, + minSchedulingOffsetPreference-r16 MinSchedulingOffsetPreference-r16 OPTIONAL, + releasePreference-r16 ReleasePreference-r16 OPTIONAL, + sl-UE-AssistanceInformationNR-r16 SL-UE-AssistanceInformationNR-r16 OPTIONAL, + referenceTimeInfoPreference-r16 BOOLEAN OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +IDC-Assistance-r16 ::= SEQUENCE { + affectedCarrierFreqList-r16 AffectedCarrierFreqList-r16 OPTIONAL, + affectedCarrierFreqCombList-r16 AffectedCarrierFreqCombList-r16 OPTIONAL, + ... +} + +AffectedCarrierFreqList-r16 ::= SEQUENCE (SIZE (1.. maxFreqIDC-r16)) OF AffectedCarrierFreq-r16 + +AffectedCarrierFreq-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + interferenceDirection-r16 ENUMERATED {nr, other, both, spare} +} + +AffectedCarrierFreqCombList-r16 ::= SEQUENCE (SIZE (1..maxCombIDC-r16)) OF AffectedCarrierFreqComb-r16 + +AffectedCarrierFreqComb-r16 ::= SEQUENCE { + affectedCarrierFreqComb-r16 SEQUENCE (SIZE (2..maxNrofServingCells)) OF ARFCN-ValueNR OPTIONAL, + victimSystemType-r16 VictimSystemType-r16 +} + +VictimSystemType-r16 ::= SEQUENCE { + gps-r16 ENUMERATED {true} OPTIONAL, + glonass-r16 ENUMERATED {true} OPTIONAL, + bds-r16 ENUMERATED {true} OPTIONAL, + galileo-r16 ENUMERATED {true} OPTIONAL, + navIC-r16 ENUMERATED {true} OPTIONAL, + wlan-r16 ENUMERATED {true} OPTIONAL, + bluetooth-r16 ENUMERATED {true} OPTIONAL, + ... +} + +DRX-Preference-r16 ::= SEQUENCE { + preferredDRX-InactivityTimer-r16 ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1} OPTIONAL, + preferredDRX-LongCycle-r16 ENUMERATED { + ms10, ms20, ms32, ms40, ms60, ms64, ms70, ms80, ms128, ms160, ms256, ms320, ms512, + ms640, ms1024, ms1280, ms2048, ms2560, ms5120, ms10240, spare12, spare11, spare10, + spare9, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, + preferredDRX-ShortCycle-r16 ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, + preferredDRX-ShortCycleTimer-r16 INTEGER (1..16) OPTIONAL +} + +MaxBW-Preference-r16 ::= SEQUENCE { + reducedMaxBW-FR1-r16 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxBW-FR2-r16 ReducedMaxBW-FRx-r16 OPTIONAL +} + +MaxCC-Preference-r16 ::= SEQUENCE { + reducedMaxCCs-r16 ReducedMaxCCs-r16 OPTIONAL +} + +MaxMIMO-LayerPreference-r16 ::= SEQUENCE { + reducedMaxMIMO-LayersFR1-r16 SEQUENCE { + reducedMIMO-LayersFR1-DL-r16 INTEGER (1..8), + reducedMIMO-LayersFR1-UL-r16 INTEGER (1..4) + } OPTIONAL, + reducedMaxMIMO-LayersFR2-r16 SEQUENCE { + reducedMIMO-LayersFR2-DL-r16 INTEGER (1..8), + reducedMIMO-LayersFR2-UL-r16 INTEGER (1..4) + } OPTIONAL +} + +MinSchedulingOffsetPreference-r16 ::= SEQUENCE { + preferredK0-r16 SEQUENCE { + preferredK0-SCS-15kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK0-SCS-30kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK0-SCS-60kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL, + preferredK0-SCS-120kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL + } OPTIONAL, + preferredK2-r16 SEQUENCE { + preferredK2-SCS-15kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK2-SCS-30kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK2-SCS-60kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL, + preferredK2-SCS-120kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL + } OPTIONAL +} + +ReleasePreference-r16 ::= SEQUENCE { + preferredRRC-State-r16 ENUMERATED {idle, inactive, connected, outOfConnected} +} + +ReducedMaxBW-FRx-r16 ::= SEQUENCE { + reducedBW-DL-r16 ReducedAggregatedBandwidth, + reducedBW-UL-r16 ReducedAggregatedBandwidth +} + +ReducedMaxCCs-r16 ::= SEQUENCE { + reducedCCsDL-r16 INTEGER (0..31), + reducedCCsUL-r16 INTEGER (0..31) +} + +SL-UE-AssistanceInformationNR-r16 ::= SEQUENCE (SIZE (1..maxNrofTrafficPattern-r16)) OF SL-TrafficPatternInfo-r16 + +SL-TrafficPatternInfo-r16::= SEQUENCE { + trafficPeriodicity-r16 ENUMERATED {ms20, ms50, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}, + timingOffset-r16 INTEGER (0..10239), + messageSize-r16 BIT STRING (SIZE (8)), + sl-QoS-FlowIdentity-r16 SL-QoS-FlowIdentity-r16 +} + +-- TAG-UEASSISTANCEINFORMATION-STOP +-- TAG-UECAPABILITYENQUIRY-START + +UECapabilityEnquiry ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityEnquiry UECapabilityEnquiry-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityEnquiry-IEs ::= SEQUENCE { + ue-CapabilityRAT-RequestList UE-CapabilityRAT-RequestList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ue-CapabilityEnquiryExt OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL +} + +UECapabilityEnquiry-v1560-IEs ::= SEQUENCE { + capabilityRequestFilterCommon UE-CapabilityRequestFilterCommon OPTIONAL, -- Need N + nonCriticalExtension UECapabilityEnquiry-v1610-IEs OPTIONAL +} + +UECapabilityEnquiry-v1610-IEs ::= SEQUENCE { + rrc-SegAllowed-r16 ENUMERATED {enabled} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UECAPABILITYENQUIRY-STOP +-- TAG-UECAPABILITYINFORMATION-START + +UECapabilityInformation ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityInformation UECapabilityInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityInformation-IEs ::= SEQUENCE { + ue-CapabilityRAT-ContainerList UE-CapabilityRAT-ContainerList OPTIONAL, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-UECAPABILITYINFORMATION-STOP +-- TAG-UEINFORMATIONREQUEST-START + +UEInformationRequest-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueInformationRequest-r16 UEInformationRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEInformationRequest-r16-IEs ::= SEQUENCE { + idleModeMeasurementReq-r16 ENUMERATED{true} OPTIONAL, -- Need N + logMeasReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + connEstFailReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + ra-ReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + rlf-ReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + mobilityHistoryReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UEINFORMATIONREQUEST-STOP +-- TAG-UEINFORMATIONRESPONSE-START + +UEInformationResponse-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueInformationResponse-r16 UEInformationResponse-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEInformationResponse-r16-IEs ::= SEQUENCE { + measResultIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL, + measResultIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + logMeasReport-r16 LogMeasReport-r16 OPTIONAL, + connEstFailReport-r16 ConnEstFailReport-r16 OPTIONAL, + ra-ReportList-r16 RA-ReportList-r16 OPTIONAL, + rlf-Report-r16 RLF-Report-r16 OPTIONAL, + mobilityHistoryReport-r16 MobilityHistoryReport-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +LogMeasReport-r16 ::= SEQUENCE { + absoluteTimeStamp-r16 AbsoluteTimeInfo-r16, + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + logMeasInfoList-r16 LogMeasInfoList-r16, + logMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableBT-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableWLAN-r16 ENUMERATED {true} OPTIONAL, + ... +} + +LogMeasInfoList-r16 ::= SEQUENCE (SIZE (1..maxLogMeasReport-r16)) OF LogMeasInfo-r16 + +LogMeasInfo-r16 ::= SEQUENCE { + locationInfo-r16 LocationInfo-r16 OPTIONAL, + relativeTimeStamp-r16 INTEGER (0..7200), + servCellIdentity-r16 CGI-Info-Logging-r16 OPTIONAL, + measResultServingCell-r16 MeasResultServingCell-r16 OPTIONAL, + measResultNeighCells-r16 SEQUENCE { + measResultNeighCellListNR MeasResultListLogging2NR-r16 OPTIONAL, + measResultNeighCellListEUTRA MeasResultList2EUTRA-r16 OPTIONAL + }, + anyCellSelectionDetected-r16 ENUMERATED {true} OPTIONAL, + ... +} + +ConnEstFailReport-r16 ::= SEQUENCE { + measResultFailedCell-r16 MeasResultFailedCell-r16, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + measResultNeighCells-r16 SEQUENCE { + measResultNeighCellListNR MeasResultList2NR-r16 OPTIONAL, + measResultNeighCellListEUTRA MeasResultList2EUTRA-r16 OPTIONAL + }, + numberOfConnFail-r16 INTEGER (1..8), + perRAInfoList-r16 PerRAInfoList-r16, + timeSinceFailure-r16 TimeSinceFailure-r16, + ... +} + +MeasResultServingCell-r16 ::= SEQUENCE { + resultsSSB-Cell MeasQuantityResults, + resultsSSB SEQUENCE{ + best-ssb-Index SSB-Index, + best-ssb-Results MeasQuantityResults, + numberOfGoodSSB INTEGER (1..maxNrofSSBs-r16) + } OPTIONAL +} + +MeasResultFailedCell-r16 ::= SEQUENCE { + cgi-Info CGI-Info-Logging-r16, + measResult-r16 SEQUENCE { + cellResults-r16 SEQUENCE{ + resultsSSB-Cell-r16 MeasQuantityResults + }, + rsIndexResults-r16 SEQUENCE{ + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList + } + } +} + +RA-ReportList-r16 ::= SEQUENCE (SIZE (1..maxRAReport-r16)) OF RA-Report-r16 + +RA-Report-r16 ::= SEQUENCE { + cellId-r16 CHOICE { + cellGlobalId-r16 CGI-Info-Logging-r16, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 PhysCellId, + carrierFreq-r16 ARFCN-ValueNR + } + }, + ra-InformationCommon-r16 RA-InformationCommon-r16 OPTIONAL, + raPurpose-r16 ENUMERATED {accessRelated, beamFailureRecovery, reconfigurationWithSync, ulUnSynchronized, + schedulingRequestFailure, noPUCCHResourceAvailable, requestForOtherSI, + spare9, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1}, + ... +} + +RA-InformationCommon-r16 ::= SEQUENCE { + absoluteFrequencyPointA-r16 ARFCN-ValueNR, + locationAndBandwidth-r16 INTEGER (0..37949), + subcarrierSpacing-r16 SubcarrierSpacing, + msg1-FrequencyStart-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, + msg1-FrequencyStartCFRA-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, + msg1-SubcarrierSpacing-r16 SubcarrierSpacing OPTIONAL, + msg1-SubcarrierSpacingCFRA-r16 SubcarrierSpacing OPTIONAL, + msg1-FDM-r16 ENUMERATED {one, two, four, eight} OPTIONAL, + msg1-FDMCFRA-r16 ENUMERATED {one, two, four, eight} OPTIONAL, + perRAInfoList-r16 PerRAInfoList-r16, + ... +} + +PerRAInfoList-r16 ::= SEQUENCE (SIZE (1..200)) OF PerRAInfo-r16 + +PerRAInfo-r16 ::= CHOICE { + perRASSBInfoList-r16 PerRASSBInfo-r16, + perRACSI-RSInfoList-r16 PerRACSI-RSInfo-r16 +} + +PerRASSBInfo-r16 ::= SEQUENCE { + ssb-Index-r16 SSB-Index, + numberOfPreamblesSentOnSSB-r16 INTEGER (1..200), + perRAAttemptInfoList-r16 PerRAAttemptInfoList-r16 +} + +PerRACSI-RSInfo-r16 ::= SEQUENCE { + csi-RS-Index-r16 CSI-RS-Index, + numberOfPreamblesSentOnCSI-RS-r16 INTEGER (1..200) +} + +PerRAAttemptInfoList-r16 ::= SEQUENCE (SIZE (1..200)) OF PerRAAttemptInfo-r16 + +PerRAAttemptInfo-r16 ::= SEQUENCE { + contentionDetected-r16 BOOLEAN OPTIONAL, + dlRSRPAboveThreshold-r16 BOOLEAN OPTIONAL, + ... +} + +RLF-Report-r16 ::= CHOICE { + nr-RLF-Report-r16 SEQUENCE { + measResultLastServCell-r16 MeasResultRLFNR-r16, + measResultNeighCells-r16 SEQUENCE { + measResultListNR-r16 MeasResultList2NR-r16 OPTIONAL, + measResultListEUTRA-r16 MeasResultList2EUTRA-r16 OPTIONAL + } OPTIONAL, + c-RNTI-r16 RNTI-Value, + previousPCellId-r16 CHOICE { + nrPreviousCell-r16 CGI-Info-Logging-r16, + eutraPreviousCell-r16 CGI-InfoEUTRALogging + } OPTIONAL, + failedPCellId-r16 CHOICE { + nrFailedPCellId-r16 CHOICE { + cellGlobalId-r16 CGI-Info-Logging-r16, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 PhysCellId, + carrierFreq-r16 ARFCN-ValueNR + } + }, + eutraFailedPCellId-r16 CHOICE { + cellGlobalId-r16 CGI-InfoEUTRALogging, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 EUTRA-PhysCellId, + carrierFreq-r16 ARFCN-ValueEUTRA + } + } + }, + reconnectCellId-r16 CHOICE { + nrReconnectCellId-r16 CGI-Info-Logging-r16, + eutraReconnectCellId-r16 CGI-InfoEUTRALogging + } OPTIONAL, + timeUntilReconnection-16 TimeUntilReconnection-16 OPTIONAL, + reestablishmentCellId-r16 CGI-Info-Logging-r16 OPTIONAL, + timeConnFailure-r16 INTEGER (0..1023) OPTIONAL, + timeSinceFailure-r16 TimeSinceFailure-r16, + connectionFailureType-r16 ENUMERATED {rlf, hof}, + rlf-Cause-r16 ENUMERATED {t310-Expiry, randomAccessProblem, rlc-MaxNumRetx, + beamFailureRecoveryFailure, lbtFailure-r16, + bh-rlfRecoveryFailure, spare2, spare1}, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + noSuitableCellFound-r16 ENUMERATED {true} OPTIONAL, + ra-InformationCommon-r16 RA-InformationCommon-r16 OPTIONAL, + ... + }, + eutra-RLF-Report-r16 SEQUENCE { + failedPCellId-EUTRA CGI-InfoEUTRALogging, + measResult-RLF-Report-EUTRA-r16 OCTET STRING, + ... + } +} + +MeasResultList2NR-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResult2NR-r16 +MeasResultList2EUTRA-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResult2EUTRA-r16 + +MeasResult2NR-r16 ::= SEQUENCE { + ssbFrequency-r16 ARFCN-ValueNR OPTIONAL, + refFreqCSI-RS-r16 ARFCN-ValueNR OPTIONAL, + measResultList-r16 MeasResultListNR +} + +MeasResultListLogging2NR-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResultLogging2NR-r16 + +MeasResultLogging2NR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + measResultListLoggingNR-r16 MeasResultListLoggingNR-r16 +} + +MeasResultListLoggingNR-r16 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultLoggingNR-r16 + +MeasResultLoggingNR-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + resultsSSB-Cell-r16 MeasQuantityResults, + numberOfGoodSSB-r16 INTEGER (1..maxNrofSSBs-r16) OPTIONAL +} + +MeasResult2EUTRA-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueEUTRA, + measResultList-r16 MeasResultListEUTRA +} + +MeasResultRLFNR-r16 ::= SEQUENCE { + measResult-r16 SEQUENCE { + cellResults-r16 SEQUENCE{ + resultsSSB-Cell-r16 MeasQuantityResults OPTIONAL, + resultsCSI-RS-Cell-r16 MeasQuantityResults OPTIONAL + }, + rsIndexResults-r16 SEQUENCE{ + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList OPTIONAL, + ssbRLMConfigBitmap-r16 BIT STRING (SIZE (64)) OPTIONAL, + resultsCSI-RS-Indexes-r16 ResultsPerCSI-RS-IndexList OPTIONAL, + csi-rsRLMConfigBitmap-r16 BIT STRING (SIZE (96)) OPTIONAL + } OPTIONAL + } +} + +TimeSinceFailure-r16 ::= INTEGER (0..172800) + +MobilityHistoryReport-r16 ::= VisitedCellInfoList-r16 + +TimeUntilReconnection-16 ::= INTEGER (0..172800) + +-- TAG-UEINFORMATIONRESPONSE-STOP +-- TAG-ULDEDICATEDMESSAGESEGMENT-START + +ULDedicatedMessageSegment-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + ulDedicatedMessageSegment-r16 ULDedicatedMessageSegment-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULDedicatedMessageSegment-r16-IEs ::= SEQUENCE { + segmentNumber-r16 INTEGER (0..15), + rrc-MessageSegmentContainer-r16 OCTET STRING, + rrc-MessageSegmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULDEDICATEDMESSAGESEGMENT-STOP +-- TAG-ULINFORMATIONTRANSFER-START + +ULInformationTransfer ::= SEQUENCE { + criticalExtensions CHOICE { + ulInformationTransfer ULInformationTransfer-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransfer-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFER-STOP +-- TAG-ULINFORMATIONTRANSFERIRAT-START + +ULInformationTransferIRAT-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ulInformationTransferIRAT-r16 ULInformationTransferIRAT-r16-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransferIRAT-r16-IEs ::= SEQUENCE { + ul-DCCH-MessageEUTRA-r16 OCTET STRING OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFERIRAT-STOP +-- TAG-ULINFORMATIONTRANSFERMRDC-START + +ULInformationTransferMRDC ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ulInformationTransferMRDC ULInformationTransferMRDC-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransferMRDC-IEs::= SEQUENCE { + ul-DCCH-MessageNR OCTET STRING OPTIONAL, + ul-DCCH-MessageEUTRA OCTET STRING OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFERMRDC-STOP +-- TAG-SETUPRELEASE-START + +SetupRelease { ElementTypeParam } ::= CHOICE { + release NULL, + setup ElementTypeParam +} + +-- TAG-SETUPRELEASE-STOP +-- TAG-SIB2-START + +SIB2 ::= SEQUENCE { + cellReselectionInfoCommon SEQUENCE { + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need S + rangeToBestCell RangeToBestCell OPTIONAL, -- Need R + q-Hyst ENUMERATED { + dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10, + dB12, dB14, dB16, dB18, dB20, dB22, dB24}, + speedStateReselectionPars SEQUENCE { + mobilityStateParameters MobilityStateParameters, + q-HystSF SEQUENCE { + sf-Medium ENUMERATED {dB-6, dB-4, dB-2, dB0}, + sf-High ENUMERATED {dB-6, dB-4, dB-2, dB0} + } + } OPTIONAL, -- Need R + ... + }, + cellReselectionServingFreqInfo SEQUENCE { + s-NonIntraSearchP ReselectionThreshold OPTIONAL, -- Need S + s-NonIntraSearchQ ReselectionThresholdQ OPTIONAL, -- Need S + threshServingLowP ReselectionThreshold, + threshServingLowQ ReselectionThresholdQ OPTIONAL, -- Need R + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + ... + }, + intraFreqCellReselectionInfo SEQUENCE { + q-RxLevMin Q-RxLevMin, + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + s-IntraSearchP ReselectionThreshold, + s-IntraSearchQ ReselectionThresholdQ OPTIONAL, -- Need S + t-ReselectionNR T-Reselection, + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Need S + frequencyBandListSUL MultiFrequencyBandListNR-SIB OPTIONAL, -- Need R + p-Max P-Max OPTIONAL, -- Need S + smtc SSB-MTC OPTIONAL, -- Need S + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, -- Need R + ssb-ToMeasure SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell BOOLEAN, + ..., + [[ + t-ReselectionNR-SF SpeedStateScaleFactors OPTIONAL -- Need N + ]], + [[ + smtc2-LP-r16 SSB-MTC2-LP-r16 OPTIONAL, -- Need R + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum + ]] + }, + ..., + [[ + relaxedMeasurement-r16 SEQUENCE { + lowMobilityEvaluation-r16 SEQUENCE { + s-SearchDeltaP-r16 ENUMERATED { + dB3, dB6, dB9, dB12, dB15, + spare3, spare2, spare1}, + t-SearchDeltaP-r16 ENUMERATED { + s5, s10, s20, s30, s60, s120, s180, + s240, s300, spare7, spare6, spare5, + spare4, spare3, spare2, spare1} + } OPTIONAL, -- Need R + cellEdgeEvaluation-r16 SEQUENCE { + s-SearchThresholdP-r16 ReselectionThreshold, + s-SearchThresholdQ-r16 ReselectionThresholdQ OPTIONAL -- Need R + } OPTIONAL, -- Need R + combineRelaxedMeasCondition-r16 ENUMERATED {true} OPTIONAL, -- Need R + highPriorityMeasRelax-r16 ENUMERATED {true} OPTIONAL -- Need R + } OPTIONAL -- Need R + ]] +} + +RangeToBestCell ::= Q-OffsetRange + +-- TAG-SIB2-STOP +-- TAG-SIB3-START + +SIB3 ::= SEQUENCE { + intraFreqNeighCellList IntraFreqNeighCellList OPTIONAL, -- Need R + intraFreqBlackCellList IntraFreqBlackCellList OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + intraFreqNeighCellList-v1610 IntraFreqNeighCellList-v1610 OPTIONAL, -- Need R + intraFreqWhiteCellList-r16 IntraFreqWhiteCellList-r16 OPTIONAL, -- Cond SharedSpectrum2 + intraFreqCAG-CellList-r16 SEQUENCE (SIZE (1..maxPLMN)) OF IntraFreqCAG-CellListPerPLMN-r16 OPTIONAL -- Need R + ]] +} + + +IntraFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo + +IntraFreqNeighCellList-v1610::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo-v1610 + +IntraFreqNeighCellInfo ::= SEQUENCE { + physCellId PhysCellId, + q-OffsetCell Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-RxLevMinOffsetCellSUL INTEGER (1..8) OPTIONAL, -- Need R + q-QualMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + ... +} + +IntraFreqNeighCellInfo-v1610 ::= SEQUENCE { + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum2 +} + +IntraFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PCI-Range + +IntraFreqWhiteCellList-r16 ::= SEQUENCE (SIZE (1..maxCellWhite)) OF PCI-Range + +IntraFreqCAG-CellListPerPLMN-r16 ::= SEQUENCE { + plmn-IdentityIndex-r16 INTEGER (1..maxPLMN), + cag-CellList-r16 SEQUENCE (SIZE (1..maxCAG-Cell-r16)) OF PCI-Range +} + +-- TAG-SIB3-STOP +-- TAG-SIB4-START + +SIB4 ::= SEQUENCE { + interFreqCarrierFreqList InterFreqCarrierFreqList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + interFreqCarrierFreqList-v1610 InterFreqCarrierFreqList-v1610 OPTIONAL -- Need R + ]] +} + +InterFreqCarrierFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo + +InterFreqCarrierFreqList-v1610 ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo-v1610 + +InterFreqCarrierFreqInfo ::= SEQUENCE { + dl-CarrierFreq ARFCN-ValueNR, + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Cond Mandatory + frequencyBandListSUL MultiFrequencyBandListNR-SIB OPTIONAL, -- Need R + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need S + smtc SSB-MTC OPTIONAL, -- Need S + ssbSubcarrierSpacing SubcarrierSpacing, + ssb-ToMeasure SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell BOOLEAN, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, + q-RxLevMin Q-RxLevMin, + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + p-Max P-Max OPTIONAL, -- Need S + t-ReselectionNR T-Reselection, + t-ReselectionNR-SF SpeedStateScaleFactors OPTIONAL, -- Need S + threshX-HighP ReselectionThreshold, + threshX-LowP ReselectionThreshold, + threshX-Q SEQUENCE { + threshX-HighQ ReselectionThresholdQ, + threshX-LowQ ReselectionThresholdQ + } OPTIONAL, -- Cond RSRQ + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need R + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + q-OffsetFreq Q-OffsetRange DEFAULT dB0, + interFreqNeighCellList InterFreqNeighCellList OPTIONAL, -- Need R + interFreqBlackCellList InterFreqBlackCellList OPTIONAL, -- Need R + ... +} + +InterFreqCarrierFreqInfo-v1610 ::= SEQUENCE { + interFreqNeighCellList-v1610 InterFreqNeighCellList-v1610 OPTIONAL, -- Need R + smtc2-LP-r16 SSB-MTC2-LP-r16 OPTIONAL, -- Need R + interFreqWhiteCellList-r16 InterFreqWhiteCellList-r16 OPTIONAL, -- Cond SharedSpectrum2 + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + interFreqCAG-CellList-r16 SEQUENCE (SIZE (1..maxPLMN)) OF InterFreqCAG-CellListPerPLMN-r16 OPTIONAL -- Need R +} + +InterFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo + +InterFreqNeighCellList-v1610 ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo-v1610 + +InterFreqNeighCellInfo ::= SEQUENCE { + physCellId PhysCellId, + q-OffsetCell Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-RxLevMinOffsetCellSUL INTEGER (1..8) OPTIONAL, -- Need R + q-QualMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + ... +} + +InterFreqNeighCellInfo-v1610 ::= SEQUENCE { + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum2 +} + +InterFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PCI-Range + +InterFreqWhiteCellList-r16 ::= SEQUENCE (SIZE (1..maxCellWhite)) OF PCI-Range + +InterFreqCAG-CellListPerPLMN-r16 ::= SEQUENCE { + plmn-IdentityIndex-r16 INTEGER (1..maxPLMN), + cag-CellList-r16 SEQUENCE (SIZE (1..maxCAG-Cell-r16)) OF PCI-Range +} + +-- TAG-SIB4-STOP +-- TAG-SIB5-START + +SIB5 ::= SEQUENCE { + carrierFreqListEUTRA CarrierFreqListEUTRA OPTIONAL, -- Need R + t-ReselectionEUTRA T-Reselection, + t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need S + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + carrierFreqListEUTRA-v1610 CarrierFreqListEUTRA-v1610 OPTIONAL -- Need R + ]] +} + +CarrierFreqListEUTRA ::= SEQUENCE (SIZE (1..maxEUTRA-Carrier)) OF CarrierFreqEUTRA + +CarrierFreqListEUTRA-v1610 ::= SEQUENCE (SIZE (1..maxEUTRA-Carrier)) OF CarrierFreqEUTRA-v1610 + +CarrierFreqEUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + eutra-multiBandInfoList EUTRA-MultiBandInfoList OPTIONAL, -- Need R + eutra-FreqNeighCellList EUTRA-FreqNeighCellList OPTIONAL, -- Need R + eutra-BlackCellList EUTRA-FreqBlackCellList OPTIONAL, -- Need R + allowedMeasBandwidth EUTRA-AllowedMeasBandwidth, + presenceAntennaPort1 EUTRA-PresenceAntennaPort1, + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need R + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + threshX-High ReselectionThreshold, + threshX-Low ReselectionThreshold, + q-RxLevMin INTEGER (-70..-22), + q-QualMin INTEGER (-34..-3), + p-MaxEUTRA INTEGER (-30..33), + threshX-Q SEQUENCE { + threshX-HighQ ReselectionThresholdQ, + threshX-LowQ ReselectionThresholdQ + } OPTIONAL -- Cond RSRQ +} + +CarrierFreqEUTRA-v1610 ::= SEQUENCE { + highSpeedEUTRACarrier-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +EUTRA-FreqBlackCellList ::= SEQUENCE (SIZE (1..maxEUTRA-CellBlack)) OF EUTRA-PhysCellIdRange + +EUTRA-FreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellEUTRA)) OF EUTRA-FreqNeighCellInfo + +EUTRA-FreqNeighCellInfo ::= SEQUENCE { + physCellId EUTRA-PhysCellId, + dummy EUTRA-Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-QualMinOffsetCell INTEGER (1..8) OPTIONAL -- Need R +} + +-- TAG-SIB5-STOP +-- TAG-SIB6-START + +SIB6 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningType OCTET STRING (SIZE (2)), + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB6-STOP +-- TAG-SIB7-START + +SIB7 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment}, + warningMessageSegmentNumber INTEGER (0..63), + warningMessageSegment OCTET STRING, + dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1 + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB7-STOP +-- TAG-SIB8-START + +SIB8 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment}, + warningMessageSegmentNumber INTEGER (0..63), + warningMessageSegment OCTET STRING, + dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1 + warningAreaCoordinatesSegment OCTET STRING OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB8-STOP +-- TAG-SIB9-START + +SIB9 ::= SEQUENCE { + timeInfo SEQUENCE { + timeInfoUTC INTEGER (0..549755813887), + dayLightSavingTime BIT STRING (SIZE (2)) OPTIONAL, -- Need R + leapSeconds INTEGER (-127..128) OPTIONAL, -- Need R + localTimeOffset INTEGER (-63..64) OPTIONAL -- Need R + } OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + referenceTimeInfo-r16 ReferenceTimeInfo-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SIB9-STOP +-- TAG-SIB10-START + +SIB10-r16 ::= SEQUENCE { + hrnn-List-r16 HRNN-List-r16 OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +HRNN-List-r16 ::= SEQUENCE (SIZE (1..maxNPN-r16)) OF HRNN-r16 + +HRNN-r16 ::= SEQUENCE { + hrnn-r16 OCTET STRING (SIZE(1.. maxHRNN-Len-r16)) OPTIONAL -- Need R +} + +-- TAG-SIB10-STOP +-- TAG-SIB11-START + +SIB11-r16 ::= SEQUENCE { + measIdleConfigSIB-r16 MeasIdleConfigSIB-r16 OPTIONAL, -- Need S + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB11-STOP +-- TAG-SIB12-START + +SIB12-r16 ::= SEQUENCE { + segmentNumber-r16 INTEGER (0..63), + segmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + segmentContainer-r16 OCTET STRING +} + +SIB12-IEs-r16 ::= SEQUENCE { + sl-ConfigCommonNR-r16 SL-ConfigCommonNR-r16, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +SL-ConfigCommonNR-r16 ::= SEQUENCE { + sl-FreqInfoList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-FreqConfigCommon-r16 OPTIONAL, -- Need R + sl-UE-SelectedConfig-r16 SL-UE-SelectedConfig-r16 OPTIONAL, -- Need R + sl-NR-AnchorCarrierFreqList-r16 SL-NR-AnchorCarrierFreqList-r16 OPTIONAL, -- Need R + sl-EUTRA-AnchorCarrierFreqList-r16 SL-EUTRA-AnchorCarrierFreqList-r16 OPTIONAL, -- Need R + sl-RadioBearerConfigList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SL-RadioBearerConfig-r16 OPTIONAL, -- Need R + sl-RLC-BearerConfigList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfig-r16 OPTIONAL, -- Need R + sl-MeasConfigCommon-r16 SL-MeasConfigCommon-r16 OPTIONAL, -- Need R + sl-CSI-Acquisition-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + sl-OffsetDFN-r16 INTEGER (1..1000) OPTIONAL, -- Need R + t400-r16 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000} OPTIONAL, -- Need R + sl-MaxNumConsecutiveDTX-r16 ENUMERATED {n1, n2, n3, n4, n6, n8, n16, n32} OPTIONAL, -- Need R + sl-SSB-PriorityNR-r16 INTEGER (1..8) OPTIONAL -- Need R +} + +SL-NR-AnchorCarrierFreqList-r16 ::= SEQUENCE (SIZE (1..maxFreqSL-NR-r16)) OF ARFCN-ValueNR + +SL-EUTRA-AnchorCarrierFreqList-r16 ::= SEQUENCE (SIZE (1..maxFreqSL-EUTRA-r16)) OF ARFCN-ValueEUTRA + +-- TAG-SIB12-STOP +-- TAG-SIB13-START + +SIB13-r16 ::= SEQUENCE { + sl-V2X-ConfigCommon-r16 OCTET STRING, + dummy OCTET STRING, + tdd-Config-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB13-STOP +-- TAG-SIB14-START + +SIB14-r16 ::= SEQUENCE { + sl-V2X-ConfigCommonExt-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB14-STOP +-- TAG-POSSYSTEMINFORMATION-R16-IES-START + +PosSystemInformation-r16-IEs ::= SEQUENCE { + posSIB-TypeAndInfo-r16 SEQUENCE (SIZE (1..maxSIB)) OF CHOICE { + posSib1-1-r16 SIBpos-r16, + posSib1-2-r16 SIBpos-r16, + posSib1-3-r16 SIBpos-r16, + posSib1-4-r16 SIBpos-r16, + posSib1-5-r16 SIBpos-r16, + posSib1-6-r16 SIBpos-r16, + posSib1-7-r16 SIBpos-r16, + posSib1-8-r16 SIBpos-r16, + posSib2-1-r16 SIBpos-r16, + posSib2-2-r16 SIBpos-r16, + posSib2-3-r16 SIBpos-r16, + posSib2-4-r16 SIBpos-r16, + posSib2-5-r16 SIBpos-r16, + posSib2-6-r16 SIBpos-r16, + posSib2-7-r16 SIBpos-r16, + posSib2-8-r16 SIBpos-r16, + posSib2-9-r16 SIBpos-r16, + posSib2-10-r16 SIBpos-r16, + posSib2-11-r16 SIBpos-r16, + posSib2-12-r16 SIBpos-r16, + posSib2-13-r16 SIBpos-r16, + posSib2-14-r16 SIBpos-r16, + posSib2-15-r16 SIBpos-r16, + posSib2-16-r16 SIBpos-r16, + posSib2-17-r16 SIBpos-r16, + posSib2-18-r16 SIBpos-r16, + posSib2-19-r16 SIBpos-r16, + posSib2-20-r16 SIBpos-r16, + posSib2-21-r16 SIBpos-r16, + posSib2-22-r16 SIBpos-r16, + posSib2-23-r16 SIBpos-r16, + posSib3-1-r16 SIBpos-r16, + posSib4-1-r16 SIBpos-r16, + posSib5-1-r16 SIBpos-r16, + posSib6-1-r16 SIBpos-r16, + posSib6-2-r16 SIBpos-r16, + posSib6-3-r16 SIBpos-r16, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-POSSYSTEMINFORMATION-R16-IES-STOP +-- TAG-POSSI-SCHEDULINGINFO-START + +PosSI-SchedulingInfo-r16 ::= SEQUENCE { + posSchedulingInfoList-r16 SEQUENCE (SIZE (1..maxSI-Message)) OF PosSchedulingInfo-r16, + posSI-RequestConfig-r16 SI-RequestConfig OPTIONAL, -- Cond MSG-1 + posSI-RequestConfigSUL-r16 SI-RequestConfig OPTIONAL, -- Cond SUL-MSG-1 + ... +} + +PosSchedulingInfo-r16 ::= SEQUENCE { + offsetToSI-Used-r16 ENUMERATED {true} OPTIONAL, -- Need R + posSI-Periodicity-r16 ENUMERATED {rf8, rf16, rf32, rf64, rf128, rf256, rf512}, + posSI-BroadcastStatus-r16 ENUMERATED {broadcasting, notBroadcasting}, + posSIB-MappingInfo-r16 PosSIB-MappingInfo-r16, + ... +} + +PosSIB-MappingInfo-r16 ::= SEQUENCE (SIZE (1..maxSIB)) OF PosSIB-Type-r16 + +PosSIB-Type-r16 ::= SEQUENCE { + encrypted-r16 ENUMERATED { true } OPTIONAL, -- Need R + gnss-id-r16 GNSS-ID-r16 OPTIONAL, -- Need R + sbas-id-r16 SBAS-ID-r16 OPTIONAL, -- Need R + posSibType-r16 ENUMERATED { posSibType1-1, posSibType1-2, posSibType1-3, posSibType1-4, posSibType1-5, posSibType1-6, + posSibType1-7, posSibType1-8, posSibType2-1, posSibType2-2, posSibType2-3, posSibType2-4, + posSibType2-5, posSibType2-6, posSibType2-7, posSibType2-8, posSibType2-9, posSibType2-10, + posSibType2-11, posSibType2-12, posSibType2-13, posSibType2-14, posSibType2-15, + posSibType2-16, posSibType2-17, posSibType2-18, posSibType2-19, posSibType2-20, + posSibType2-21, posSibType2-22, posSibType2-23, posSibType3-1, posSibType4-1, + posSibType5-1,posSibType6-1, posSibType6-2, posSibType6-3,... }, + areaScope-r16 ENUMERATED {true} OPTIONAL -- Need S +} + +GNSS-ID-r16 ::= SEQUENCE { + gnss-id-r16 ENUMERATED{gps, sbas, qzss, galileo, glonass, bds, ...}, + ... +} + +SBAS-ID-r16 ::= SEQUENCE { + sbas-id-r16 ENUMERATED { waas, egnos, msas, gagan, ...}, + ... +} + +-- TAG-POSSI-SCHEDULINGINFO-STOP +-- TAG-SIPOS-START + +SIBpos-r16 ::= SEQUENCE { + assistanceDataSIB-Element-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIPOS-STOP +-- TAG-ADDITIONALSPECTRUMEMISSION-START + +AdditionalSpectrumEmission ::= INTEGER (0..7) + +-- TAG-ADDITIONALSPECTRUMEMISSION-STOP +-- TAG-ALPHA-START + +Alpha ::= ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} + +-- TAG-ALPHA-STOP +-- TAG-AMF-IDENTIFIER-START + +AMF-Identifier ::= BIT STRING (SIZE (24)) + +-- TAG-AMF-IDENTIFIER-STOP +-- TAG-ARFCN-VALUEEUTRA-START + +ARFCN-ValueEUTRA ::= INTEGER (0..maxEARFCN) + +-- TAG-ARFCN-VALUEEUTRA-STOP +-- TAG-ARFCN-VALUENR-START + +ARFCN-ValueNR ::= INTEGER (0..maxNARFCN) + +-- TAG-ARFCN-VALUENR-STOP +-- TAG-ARFCN-ValueUTRA-FDD-START + +ARFCN-ValueUTRA-FDD-r16 ::= INTEGER (0..16383) + +-- TAG-ARFCN-ValueUTRA-FDD-STOP +-- TAG-AVAILABILITYCOMBINATIONSPERCELL-START + +AvailabilityCombinationsPerCell-r16 ::= SEQUENCE { + availabilityCombinationsPerCellIndex-r16 AvailabilityCombinationsPerCellIndex-r16, + iab-DU-CellIdentity-r16 CellIdentity, + positionInDCI-AI-r16 INTEGER(0..maxAI-DCI-PayloadSize-r16-1) OPTIONAL, -- Need M + availabilityCombinations-r16 SEQUENCE (SIZE (1..maxNrofAvailabilityCombinationsPerSet-r16)) OF AvailabilityCombination-r16, + ... +} + +AvailabilityCombinationsPerCellIndex-r16 ::= INTEGER(0..maxNrofDUCells-r16) + +AvailabilityCombination-r16 ::= SEQUENCE { + availabilityCombinationId-r16 AvailabilityCombinationId-r16, + resourceAvailability-r16 SEQUENCE (SIZE (1..maxNrofResourceAvailabilityPerCombination-r16)) OF INTEGER (0..7) +} + +AvailabilityCombinationId-r16 ::= INTEGER (0..maxNrofAvailabilityCombinationsPerSet-r16-1) + +-- TAG-AVAILABILITYCOMBINATIONSPERCELL-STOP +-- TAG-AVAILABILITYINDICATOR-START + +AvailabilityIndicator-r16 ::= SEQUENCE { + ai-RNTI-r16 AI-RNTI-r16, + dci-PayloadSizeAI-r16 INTEGER (1..maxAI-DCI-PayloadSize-r16), + availableCombToAddModList-r16 SEQUENCE (SIZE(1..maxNrofDUCells-r16)) OF AvailabilityCombinationsPerCell-r16 OPTIONAL, -- Need N + availableCombToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofDUCells-r16)) OF AvailabilityCombinationsPerCellIndex-r16 OPTIONAL, -- Need N + ... +} + +AI-RNTI-r16 ::= RNTI-Value + +-- TAG-AVAILABILITYINDICATOR-STOP +-- TAG-BAPROUTINGID-START + +BAP-RoutingID-r16::= SEQUENCE{ + bap-Address-r16 BIT STRING (SIZE (10)), + bap-PathId-r16 BIT STRING (SIZE (10)) +} + +-- TAG-BAPROUTINGID-STOP +-- TAG-BEAMFAILURERECOVERYCONFIG-START + +BeamFailureRecoveryConfig ::= SEQUENCE { + rootSequenceIndex-BFR INTEGER (0..137) OPTIONAL, -- Need M + rach-ConfigBFR RACH-ConfigGeneric OPTIONAL, -- Need M + rsrp-ThresholdSSB RSRP-Range OPTIONAL, -- Need M + candidateBeamRSList SEQUENCE (SIZE(1..maxNrofCandidateBeams)) OF PRACH-ResourceDedicatedBFR OPTIONAL, -- Need M + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, + four, eight, sixteen} OPTIONAL, -- Need M + ra-ssb-OccasionMaskIndex INTEGER (0..15) OPTIONAL, -- Need M + recoverySearchSpaceId SearchSpaceId OPTIONAL, -- Need R + ra-Prioritization RA-Prioritization OPTIONAL, -- Need R + beamFailureRecoveryTimer ENUMERATED {ms10, ms20, ms40, ms60, ms80, ms100, ms150, ms200} OPTIONAL, -- Need M + ..., + [[ + msg1-SubcarrierSpacing SubcarrierSpacing OPTIONAL -- Need M + ]], + [[ + ra-PrioritizationTwoStep-r16 RA-Prioritization OPTIONAL, -- Need R + candidateBeamRSListExt-v1610 SetupRelease{ CandidateBeamRSListExt-r16 } OPTIONAL -- Need M + ]], + [[ + spCell-BFR-CBRA-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +PRACH-ResourceDedicatedBFR ::= CHOICE { + ssb BFR-SSB-Resource, + csi-RS BFR-CSIRS-Resource +} + +BFR-SSB-Resource ::= SEQUENCE { + ssb SSB-Index, + ra-PreambleIndex INTEGER (0..63), + ... +} + +BFR-CSIRS-Resource ::= SEQUENCE { + csi-RS NZP-CSI-RS-ResourceId, + ra-OccasionList SEQUENCE (SIZE(1..maxRA-OccasionsPerCSIRS)) OF INTEGER (0..maxRA-Occasions-1) OPTIONAL, -- Need R + ra-PreambleIndex INTEGER (0..63) OPTIONAL, -- Need R + ... +} + +CandidateBeamRSListExt-r16::= SEQUENCE (SIZE(1.. maxNrofCandidateBeamsExt-r16)) OF PRACH-ResourceDedicatedBFR + +-- TAG-BEAMFAILURERECOVERYCONFIG-STOP +-- TAG-BEAMFAILURERECOVERYSCELLCONFIG-START + +BeamFailureRecoverySCellConfig-r16 ::= SEQUENCE { + rsrp-ThresholdBFR-r16 RSRP-Range OPTIONAL, -- Need M + candidateBeamRSSCellList-r16 SEQUENCE (SIZE(1..maxNrofCandidateBeams-r16)) OF CandidateBeamRS-r16 OPTIONAL, -- Need M + ... +} + +CandidateBeamRS-r16 ::= SEQUENCE { + candidateBeamConfig-r16 CHOICE { + ssb-r16 SSB-Index, + csi-RS-r16 NZP-CSI-RS-ResourceId + }, + servingCellId ServCellIndex OPTIONAL -- Need R +} + +-- TAG-BEAMFAILURERECOVERYSCELLCONFIG-STOP +-- TAG-BETAOFFSETS-START + +BetaOffsets ::= SEQUENCE { + betaOffsetACK-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetACK-Index2 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetACK-Index3 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part1-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part1-Index2 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part2-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part2-Index2 INTEGER(0..31) OPTIONAL -- Need S +} + +-- TAG-BETAOFFSETS-STOP +-- TAG-BHLOGICALCHANNELIDENTITY-START + +BH-LogicalChannelIdentity-r16 ::= CHOICE { + bh-LogicalChannelIdentity-r16 LogicalChannelIdentity, + bh-LogicalChannelIdentityExt-r16 BH-LogicalChannelIdentity-Ext-r16 +} + +-- TAG-BHLOGICALCHANNELIDENTITY-STOP +-- TAG-BHLOGICALCHANNELIDENTITYEXT-START + +BH-LogicalChannelIdentity-Ext-r16 ::= INTEGER (320.. maxLC-ID-Iab-r16) + +-- TAG-BHLOGICALCHANNELIDENTITYEXT-STOP +-- TAG-BHRLCCHANNELCONFIG-START + +BH-RLC-ChannelConfig-r16::= SEQUENCE { + bh-LogicalChannelIdentity-r16 BH-LogicalChannelIdentity-r16 OPTIONAL, -- Cond LCH-SetupOnly + bh-RLC-ChannelID-r16 BH-RLC-ChannelID-r16, + reestablishRLC-r16 ENUMERATED {true} OPTIONAL, -- Need N + rlc-Config-r16 RLC-Config OPTIONAL, -- Cond LCH-Setup + mac-LogicalChannelConfig-r16 LogicalChannelConfig OPTIONAL, -- Cond LCH-Setup + ... +} + +-- TAG-BHRLCCHANNELCONFIG-STOP +-- TAG-BHRLCCHANNELID-START + +BH-RLC-ChannelID-r16 ::= BIT STRING (SIZE (16)) + +-- TAG-BHRLCCHANNELID-STOP +-- TAG-BSR-CONFIG-START + +BSR-Config ::= SEQUENCE { + periodicBSR-Timer ENUMERATED { sf1, sf5, sf10, sf16, sf20, sf32, sf40, sf64, + sf80, sf128, sf160, sf320, sf640, sf1280, sf2560, infinity }, + retxBSR-Timer ENUMERATED { sf10, sf20, sf40, sf80, sf160, sf320, sf640, sf1280, sf2560, + sf5120, sf10240, spare5, spare4, spare3, spare2, spare1}, + logicalChannelSR-DelayTimer ENUMERATED { sf20, sf40, sf64, sf128, sf512, sf1024, sf2560, spare1} OPTIONAL, -- Need R + ... +} + +-- TAG-BSR-CONFIG-STOP +-- TAG-BWP-START + +BWP ::= SEQUENCE { + locationAndBandwidth INTEGER (0..37949), + subcarrierSpacing SubcarrierSpacing, + cyclicPrefix ENUMERATED { extended } OPTIONAL -- Need R +} + +-- TAG-BWP-STOP +-- TAG-BWP-DOWNLINK-START + +BWP-Downlink ::= SEQUENCE { + bwp-Id BWP-Id, + bwp-Common BWP-DownlinkCommon OPTIONAL, -- Cond SetupOtherBWP + bwp-Dedicated BWP-DownlinkDedicated OPTIONAL, -- Cond SetupOtherBWP + ... +} + +-- TAG-BWP-DOWNLINK-STOP +-- TAG-BWP-DOWNLINKCOMMON-START + +BWP-DownlinkCommon ::= SEQUENCE { + genericParameters BWP, + pdcch-ConfigCommon SetupRelease { PDCCH-ConfigCommon } OPTIONAL, -- Need M + pdsch-ConfigCommon SetupRelease { PDSCH-ConfigCommon } OPTIONAL, -- Need M + ... +} + +-- TAG-BWP-DOWNLINKCOMMON-STOP +-- TAG-BWP-DOWNLINKDEDICATED-START + +BWP-DownlinkDedicated ::= SEQUENCE { + pdcch-Config SetupRelease { PDCCH-Config } OPTIONAL, -- Need M + pdsch-Config SetupRelease { PDSCH-Config } OPTIONAL, -- Need M + sps-Config SetupRelease { SPS-Config } OPTIONAL, -- Need M + radioLinkMonitoringConfig SetupRelease { RadioLinkMonitoringConfig } OPTIONAL, -- Need M + ..., + [[ + sps-ConfigToAddModList-r16 SPS-ConfigToAddModList-r16 OPTIONAL, -- Need N + sps-ConfigToReleaseList-r16 SPS-ConfigToReleaseList-r16 OPTIONAL, -- Need N + sps-ConfigDeactivationStateList-r16 SPS-ConfigDeactivationStateList-r16 OPTIONAL, -- Need R + beamFailureRecoverySCellConfig-r16 SetupRelease {BeamFailureRecoverySCellConfig-r16} OPTIONAL, -- Cond SCellOnly + sl-PDCCH-Config-r16 SetupRelease { PDCCH-Config } OPTIONAL, -- Need M + sl-V2X-PDCCH-Config-r16 SetupRelease { PDCCH-Config } OPTIONAL -- Need M + ]] +} + +SPS-ConfigToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-Config + +SPS-ConfigToReleaseList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-ConfigIndex-r16 + +SPS-ConfigDeactivationState-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-ConfigIndex-r16 + +SPS-ConfigDeactivationStateList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-DeactivationState)) OF SPS-ConfigDeactivationState-r16 + +-- TAG-BWP-DOWNLINKDEDICATED-STOP +-- TAG-BWP-ID-START + +BWP-Id ::= INTEGER (0..maxNrofBWPs) + +-- TAG-BWP-ID-STOP +-- TAG-BWP-UPLINK-START + +BWP-Uplink ::= SEQUENCE { + bwp-Id BWP-Id, + bwp-Common BWP-UplinkCommon OPTIONAL, -- Cond SetupOtherBWP + bwp-Dedicated BWP-UplinkDedicated OPTIONAL, -- Cond SetupOtherBWP + ... +} + +-- TAG-BWP-UPLINK-STOP +-- TAG-BWP-UPLINKCOMMON-START + +BWP-UplinkCommon ::= SEQUENCE { + genericParameters BWP, + rach-ConfigCommon SetupRelease { RACH-ConfigCommon } OPTIONAL, -- Need M + pusch-ConfigCommon SetupRelease { PUSCH-ConfigCommon } OPTIONAL, -- Need M + pucch-ConfigCommon SetupRelease { PUCCH-ConfigCommon } OPTIONAL, -- Need M + ..., + [[ + rach-ConfigCommonIAB-r16 SetupRelease { RACH-ConfigCommon } OPTIONAL, -- Need M + useInterlacePUCCH-PUSCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + msgA-ConfigCommon-r16 SetupRelease { MsgA-ConfigCommon-r16 } OPTIONAL -- Cond SpCellOnly2 + ]] +} + +-- TAG-BWP-UPLINKCOMMON-STOP +-- TAG-BWP-UPLINKDEDICATED-START + +BWP-UplinkDedicated ::= SEQUENCE { + pucch-Config SetupRelease { PUCCH-Config } OPTIONAL, -- Need M + pusch-Config SetupRelease { PUSCH-Config } OPTIONAL, -- Need M + configuredGrantConfig SetupRelease { ConfiguredGrantConfig } OPTIONAL, -- Need M + srs-Config SetupRelease { SRS-Config } OPTIONAL, -- Need M + beamFailureRecoveryConfig SetupRelease { BeamFailureRecoveryConfig } OPTIONAL, -- Cond SpCellOnly + ..., + [[ + sl-PUCCH-Config-r16 SetupRelease { PUCCH-Config } OPTIONAL, -- Need M + cp-ExtensionC2-r16 INTEGER (1..28) OPTIONAL, -- Need R + cp-ExtensionC3-r16 INTEGER (1..28) OPTIONAL, -- Need R + useInterlacePUCCH-PUSCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + pucch-ConfigurationList-r16 SetupRelease { PUCCH-ConfigurationList-r16 } OPTIONAL, -- Need M + lbt-FailureRecoveryConfig-r16 SetupRelease { LBT-FailureRecoveryConfig-r16 } OPTIONAL, -- Need M + configuredGrantConfigToAddModList-r16 ConfiguredGrantConfigToAddModList-r16 OPTIONAL, -- Need N + configuredGrantConfigToReleaseList-r16 ConfiguredGrantConfigToReleaseList-r16 OPTIONAL, -- Need N + configuredGrantConfigType2DeactivationStateList-r16 ConfiguredGrantConfigType2DeactivationStateList-r16 OPTIONAL -- Need R + ]] + +} + +ConfiguredGrantConfigToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfig + +ConfiguredGrantConfigToReleaseList-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfigIndex-r16 + +ConfiguredGrantConfigType2DeactivationState-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfigIndex-r16 + +ConfiguredGrantConfigType2DeactivationStateList-r16 ::= + SEQUENCE (SIZE (1..maxNrofCG-Type2DeactivationState)) OF ConfiguredGrantConfigType2DeactivationState-r16 + +-- TAG-BWP-UPLINKDEDICATED-STOP +-- TAG-CELLACCESSRELATEDINFO-START + +CellAccessRelatedInfo ::= SEQUENCE { + plmn-IdentityList PLMN-IdentityInfoList, + cellReservedForOtherUse ENUMERATED {true} OPTIONAL, -- Need R + ..., + [[ + cellReservedForFutureUse-r16 ENUMERATED {true} OPTIONAL, -- Need R + npn-IdentityInfoList-r16 NPN-IdentityInfoList-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-CELLACCESSRELATEDINFO-STOP +-- TAG-CELLACCESSRELATEDINFOEUTRA-5GC-START + +CellAccessRelatedInfo-EUTRA-5GC ::= SEQUENCE { + plmn-IdentityList-eutra-5gc PLMN-IdentityList-EUTRA-5GC, + trackingAreaCode-eutra-5gc TrackingAreaCode, + ranac-5gc RAN-AreaCode OPTIONAL, + cellIdentity-eutra-5gc CellIdentity-EUTRA-5GC +} + +PLMN-IdentityList-EUTRA-5GC::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity-EUTRA-5GC + +PLMN-Identity-EUTRA-5GC ::= CHOICE { + plmn-Identity-EUTRA-5GC PLMN-Identity, + plmn-index INTEGER (1..maxPLMN) +} + +CellIdentity-EUTRA-5GC ::= CHOICE { + cellIdentity-EUTRA BIT STRING (SIZE (28)), + cellId-index INTEGER (1..maxPLMN) +} + +-- TAG-CELLACCESSRELATEDINFOEUTRA-5GC-STOP +-- TAG-CELLACCESSRELATEDINFOEUTRA-EPC-START + +CellAccessRelatedInfo-EUTRA-EPC ::= SEQUENCE { + plmn-IdentityList-eutra-epc PLMN-IdentityList-EUTRA-EPC, + trackingAreaCode-eutra-epc BIT STRING (SIZE (16)), + cellIdentity-eutra-epc BIT STRING (SIZE (28)) +} + +PLMN-IdentityList-EUTRA-EPC::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity + +-- TAG-CELLACCESSRELATEDINFOEUTRA-EPC-STOP +-- TAG-CELLGROUPCONFIG-START + +-- Configuration of one Cell-Group: +CellGroupConfig ::= SEQUENCE { + cellGroupId CellGroupId, + rlc-BearerToAddModList SEQUENCE (SIZE(1..maxLC-ID)) OF RLC-BearerConfig OPTIONAL, -- Need N + rlc-BearerToReleaseList SEQUENCE (SIZE(1..maxLC-ID)) OF LogicalChannelIdentity OPTIONAL, -- Need N + mac-CellGroupConfig MAC-CellGroupConfig OPTIONAL, -- Need M + physicalCellGroupConfig PhysicalCellGroupConfig OPTIONAL, -- Need M + spCellConfig SpCellConfig OPTIONAL, -- Need M + sCellToAddModList SEQUENCE (SIZE (1..maxNrofSCells)) OF SCellConfig OPTIONAL, -- Need N + sCellToReleaseList SEQUENCE (SIZE (1..maxNrofSCells)) OF SCellIndex OPTIONAL, -- Need N + ..., + [[ + reportUplinkTxDirectCurrent ENUMERATED {true} OPTIONAL -- Cond BWP-Reconfig + ]], + [[ + bap-Address-r16 BIT STRING (SIZE (10)) OPTIONAL, -- Need M + bh-RLC-ChannelToAddModList-r16 SEQUENCE (SIZE(1..maxBH-RLC-ChannelID-r16)) OF BH-RLC-ChannelConfig-r16 OPTIONAL, -- Need N + bh-RLC-ChannelToReleaseList-r16 SEQUENCE (SIZE(1..maxBH-RLC-ChannelID-r16)) OF BH-RLC-ChannelID-r16 OPTIONAL, -- Need N + f1c-TransferPath-r16 ENUMERATED {lte, nr, both} OPTIONAL, -- Need M + simultaneousTCI-UpdateList1-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousTCI-UpdateList2-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousSpatial-UpdatedList1-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousSpatial-UpdatedList2-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + uplinkTxSwitchingOption-r16 ENUMERATED {switchedUL, dualUL} OPTIONAL, -- Need R + uplinkTxSwitchingPowerBoosting-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]], + [[ + reportUplinkTxDirectCurrentTwoCarrier-r16 ENUMERATED {true} OPTIONAL -- Need N + ]] +} + +-- Serving cell specific MAC and PHY parameters for a SpCell: +SpCellConfig ::= SEQUENCE { + servCellIndex ServCellIndex OPTIONAL, -- Cond SCG + reconfigurationWithSync ReconfigurationWithSync OPTIONAL, -- Cond ReconfWithSync + rlf-TimersAndConstants SetupRelease { RLF-TimersAndConstants } OPTIONAL, -- Need M + rlmInSyncOutOfSyncThreshold ENUMERATED {n1} OPTIONAL, -- Need S + spCellConfigDedicated ServingCellConfig OPTIONAL, -- Need M + ... +} + +ReconfigurationWithSync ::= SEQUENCE { + spCellConfigCommon ServingCellConfigCommon OPTIONAL, -- Need M + newUE-Identity RNTI-Value, + t304 ENUMERATED {ms50, ms100, ms150, ms200, ms500, ms1000, ms2000, ms10000}, + rach-ConfigDedicated CHOICE { + uplink RACH-ConfigDedicated, + supplementaryUplink RACH-ConfigDedicated + } OPTIONAL, -- Need N + ..., + [[ + smtc SSB-MTC OPTIONAL -- Need S + ]], + [[ + daps-UplinkPowerConfig-r16 DAPS-UplinkPowerConfig-r16 OPTIONAL -- Need N + ]] +} + +DAPS-UplinkPowerConfig-r16 ::= SEQUENCE { + p-DAPS-Source-r16 P-Max, + p-DAPS-Target-r16 P-Max, + uplinkPowerSharingDAPS-Mode-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic } +} + +SCellConfig ::= SEQUENCE { + sCellIndex SCellIndex, + sCellConfigCommon ServingCellConfigCommon OPTIONAL, -- Cond SCellAdd + sCellConfigDedicated ServingCellConfig OPTIONAL, -- Cond SCellAddMod + ..., + [[ + smtc SSB-MTC OPTIONAL -- Need S + ]], + [[ + sCellState-r16 ENUMERATED {activated} OPTIONAL, -- Cond SCellAddSync + secondaryDRX-GroupConfig-r16 ENUMERATED {true} OPTIONAL -- Cond DRX-Config2 + ]]} + +-- TAG-CELLGROUPCONFIG-STOP +-- TAG-CELLGROUPID-START + +CellGroupId ::= INTEGER (0.. maxSecondaryCellGroups) + +-- TAG-CELLGROUPID-STOP +-- TAG-CELLIDENTITY-START + +CellIdentity ::= BIT STRING (SIZE (36)) + +-- TAG-CELLIDENTITY-STOP +-- TAG-CELLRESELECTIONPRIORITY-START + +CellReselectionPriority ::= INTEGER (0..7) + +-- TAG-CELLRESELECTIONPRIORITY-STOP +-- TAG-CELLRESELECTIONSUBPRIORITY-START + +CellReselectionSubPriority ::= ENUMERATED {oDot2, oDot4, oDot6, oDot8} + +-- TAG-CELLRESELECTIONSUBPRIORITY-STOP +-- TAG-CGI-INFOEUTRA-START + +CGI-InfoEUTRA ::= SEQUENCE { + cgi-info-EPC SEQUENCE { + cgi-info-EPC-legacy CellAccessRelatedInfo-EUTRA-EPC, + cgi-info-EPC-list SEQUENCE (SIZE (1..maxPLMN)) OF CellAccessRelatedInfo-EUTRA-EPC OPTIONAL + } OPTIONAL, + cgi-info-5GC SEQUENCE (SIZE (1..maxPLMN)) OF CellAccessRelatedInfo-EUTRA-5GC OPTIONAL, + freqBandIndicator FreqBandIndicatorEUTRA, + multiBandInfoList MultiBandInfoListEUTRA OPTIONAL, + freqBandIndicatorPriority ENUMERATED {true} OPTIONAL +} + +-- TAG-CGI-INFOEUTRA-STOP +-- TAG-CGI-INFOEUTRALOGGING-START + +CGI-InfoEUTRALogging ::= SEQUENCE { + plmn-Identity-eutra-5gc PLMN-Identity OPTIONAL, + trackingAreaCode-eutra-5gc TrackingAreaCode OPTIONAL, + cellIdentity-eutra-5gc BIT STRING (SIZE (28)) OPTIONAL, + plmn-Identity-eutra-epc PLMN-Identity OPTIONAL, + trackingAreaCode-eutra-epc BIT STRING (SIZE (16)) OPTIONAL, + cellIdentity-eutra-epc BIT STRING (SIZE (28)) OPTIONAL +} + +-- TAG-CGI-INFOEUTRALOGGING-STOP +-- TAG-CGI-INFO-NR-START + +CGI-InfoNR ::= SEQUENCE { + plmn-IdentityInfoList PLMN-IdentityInfoList OPTIONAL, + frequencyBandList MultiFrequencyBandListNR OPTIONAL, + noSIB1 SEQUENCE { + ssb-SubcarrierOffset INTEGER (0..15), + pdcch-ConfigSIB1 PDCCH-ConfigSIB1 + } OPTIONAL, + ..., + [[ + npn-IdentityInfoList-r16 NPN-IdentityInfoList-r16 OPTIONAL + ]] +} + +-- TAG-CGI-INFO-NR-STOP +-- TAG-CGI-INFO-LOGGING-START + +CGI-Info-Logging-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + cellIdentity-r16 CellIdentity, + trackingAreaCode-r16 TrackingAreaCode OPTIONAL +} + +-- TAG-CGI-INFO-LOGGING-STOP +-- TAG-CLI-RSSI-RANGE-START + +CLI-RSSI-Range-r16 ::= INTEGER(0..76) + +-- TAG-CLI-RSSI-RANGE-STOP +-- TAG-CODEBOOKCONFIG-START + +CodebookConfig ::= SEQUENCE { + codebookType CHOICE { + type1 SEQUENCE { + subType CHOICE { + typeI-SinglePanel SEQUENCE { + nrOfAntennaPorts CHOICE { + two SEQUENCE { + twoTX-CodebookSubsetRestriction BIT STRING (SIZE (6)) + }, + moreThanTwo SEQUENCE { + n1-n2 CHOICE { + two-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (8)), + two-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (64)), + four-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (16)), + three-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (96)), + six-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (24)), + four-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (128)), + eight-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (32)), + four-three-TypeI-SinglePanel-Restriction BIT STRING (SIZE (192)), + six-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (192)), + twelve-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (48)), + four-four-TypeI-SinglePanel-Restriction BIT STRING (SIZE (256)), + eight-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (256)), + sixteen-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (64)) + }, + typeI-SinglePanel-codebookSubsetRestriction-i2 BIT STRING (SIZE (16)) OPTIONAL -- Need R + } + }, + typeI-SinglePanel-ri-Restriction BIT STRING (SIZE (8)) + }, + typeI-MultiPanel SEQUENCE { + ng-n1-n2 CHOICE { + two-two-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (8)), + two-four-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (16)), + four-two-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (8)), + two-two-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (64)), + two-eight-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (32)), + four-four-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (16)), + two-four-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (128)), + four-two-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (64)) + }, + ri-Restriction BIT STRING (SIZE (4)) + } + }, + codebookMode INTEGER (1..2) + + }, + type2 SEQUENCE { + subType CHOICE { + typeII SEQUENCE { + n1-n2-codebookSubsetRestriction CHOICE { + two-one BIT STRING (SIZE (16)), + two-two BIT STRING (SIZE (43)), + four-one BIT STRING (SIZE (32)), + three-two BIT STRING (SIZE (59)), + six-one BIT STRING (SIZE (48)), + four-two BIT STRING (SIZE (75)), + eight-one BIT STRING (SIZE (64)), + four-three BIT STRING (SIZE (107)), + six-two BIT STRING (SIZE (107)), + twelve-one BIT STRING (SIZE (96)), + four-four BIT STRING (SIZE (139)), + eight-two BIT STRING (SIZE (139)), + sixteen-one BIT STRING (SIZE (128)) + }, + typeII-RI-Restriction BIT STRING (SIZE (2)) + }, + typeII-PortSelection SEQUENCE { + portSelectionSamplingSize ENUMERATED {n1, n2, n3, n4} OPTIONAL, -- Need R + typeII-PortSelectionRI-Restriction BIT STRING (SIZE (2)) + } + }, + phaseAlphabetSize ENUMERATED {n4, n8}, + subbandAmplitude BOOLEAN, + numberOfBeams ENUMERATED {two, three, four} + } + } +} + +CodebookConfig-r16 ::= SEQUENCE { + codebookType CHOICE { + type2 SEQUENCE { + subType CHOICE { + typeII-r16 SEQUENCE { + n1-n2-codebookSubsetRestriction-r16 CHOICE { + two-one BIT STRING (SIZE (16)), + two-two BIT STRING (SIZE (43)), + four-one BIT STRING (SIZE (32)), + three-two BIT STRING (SIZE (59)), + six-one BIT STRING (SIZE (48)), + four-two BIT STRING (SIZE (75)), + eight-one BIT STRING (SIZE (64)), + four-three BIT STRING (SIZE (107)), + six-two BIT STRING (SIZE (107)), + twelve-one BIT STRING (SIZE (96)), + four-four BIT STRING (SIZE (139)), + eight-two BIT STRING (SIZE (139)), + sixteen-one BIT STRING (SIZE (128)) + }, + typeII-RI-Restriction-r16 BIT STRING (SIZE(4)) + }, + typeII-PortSelection-r16 SEQUENCE { + portSelectionSamplingSize-r16 ENUMERATED {n1, n2, n3, n4}, + typeII-PortSelectionRI-Restriction-r16 BIT STRING (SIZE (4)) + } + }, + numberOfPMI-SubbandsPerCQI-Subband-r16 INTEGER (1..2), + paramCombination-r16 INTEGER (1..8) + } + } +} + +-- TAG-CODEBOOKCONFIG-STOP +-- TAG-COMMONLOCATIONINFO-START + +CommonLocationInfo-r16 ::= SEQUENCE { + gnss-TOD-msec-r16 OCTET STRING OPTIONAL, + locationTimestamp-r16 OCTET STRING OPTIONAL, + locationCoordinate-r16 OCTET STRING OPTIONAL, + locationError-r16 OCTET STRING OPTIONAL, + locationSource-r16 OCTET STRING OPTIONAL, + velocityEstimate-r16 OCTET STRING OPTIONAL +} + +-- TAG-COMMONLOCATIONINFO-STOP +-- TAG-CONDRECONFIGID-START + +CondReconfigId-r16 ::= INTEGER (1.. maxNrofCondCells-r16) + +-- TAG-CONDRECONFIGID-STOP +-- TAG-CONDRECONFIGTOADDMODLIST-START + +CondReconfigToAddModList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCondCells-r16)) OF CondReconfigToAddMod-r16 + +CondReconfigToAddMod-r16 ::= SEQUENCE { + condReconfigId-r16 CondReconfigId-r16, + condExecutionCond-r16 SEQUENCE (SIZE (1..2)) OF MeasId OPTIONAL, -- Cond condReconfigAdd + condRRCReconfig-r16 OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, -- Cond condReconfigAdd + ... +} + +-- TAG-CONDRECONFIGTOADDMODLIST-STOP +-- TAG-CONDITIONALRECONFIGURATION-START + +ConditionalReconfiguration-r16 ::= SEQUENCE { + attemptCondReconfig-r16 ENUMERATED {true} OPTIONAL, -- Cond CHO + condReconfigToRemoveList-r16 CondReconfigToRemoveList-r16 OPTIONAL, -- Need N + condReconfigToAddModList-r16 CondReconfigToAddModList-r16 OPTIONAL, -- Need N + ... +} + +CondReconfigToRemoveList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCondCells-r16)) OF CondReconfigId-r16 + +-- TAG-CONDITIONALRECONFIGURATION-STOP +-- TAG-CONFIGUREDGRANTCONFIG-START + +ConfiguredGrantConfig ::= SEQUENCE { + frequencyHopping ENUMERATED {intraSlot, interSlot} OPTIONAL, -- Need S + cg-DMRS-Configuration DMRS-UplinkConfig, + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoder ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + uci-OnPUSCH SetupRelease { CG-UCI-OnPUSCH } OPTIONAL, -- Need M + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch }, + rbg-Size ENUMERATED {config2} OPTIONAL, -- Need S + powerControlLoopToUse ENUMERATED {n0, n1}, + p0-PUSCH-Alpha P0-PUSCH-AlphaSetId, + transformPrecoder ENUMERATED {enabled, disabled} OPTIONAL, -- Need S + nrofHARQ-Processes INTEGER(1..16), + repK ENUMERATED {n1, n2, n4, n8}, + repK-RV ENUMERATED {s1-0231, s2-0303, s3-0000} OPTIONAL, -- Need R + periodicity ENUMERATED { + sym2, sym7, sym1x14, sym2x14, sym4x14, sym5x14, sym8x14, sym10x14, sym16x14, sym20x14, + sym32x14, sym40x14, sym64x14, sym80x14, sym128x14, sym160x14, sym256x14, sym320x14, sym512x14, + sym640x14, sym1024x14, sym1280x14, sym2560x14, sym5120x14, + sym6, sym1x12, sym2x12, sym4x12, sym5x12, sym8x12, sym10x12, sym16x12, sym20x12, sym32x12, + sym40x12, sym64x12, sym80x12, sym128x12, sym160x12, sym256x12, sym320x12, sym512x12, sym640x12, + sym1280x12, sym2560x12 + }, + configuredGrantTimer INTEGER (1..64) OPTIONAL, -- Need R + rrc-ConfiguredUplinkGrant SEQUENCE { + timeDomainOffset INTEGER (0..5119), + timeDomainAllocation INTEGER (0..15), + frequencyDomainAllocation BIT STRING (SIZE(18)), + antennaPort INTEGER (0..31), + dmrs-SeqInitialization INTEGER (0..1) OPTIONAL, -- Need R + precodingAndNumberOfLayers INTEGER (0..63), + srs-ResourceIndicator INTEGER (0..15) OPTIONAL, -- Need R + mcsAndTBS INTEGER (0..31), + frequencyHoppingOffset INTEGER (1.. maxNrofPhysicalResourceBlocks-1) OPTIONAL, -- Need R + pathlossReferenceIndex INTEGER (0..maxNrofPUSCH-PathlossReferenceRSs-1), + ..., + [[ + pusch-RepTypeIndicator-r16 ENUMERATED {pusch-RepTypeA,pusch-RepTypeB} OPTIONAL, -- Need M + frequencyHoppingPUSCH-RepTypeB-r16 ENUMERATED {interRepetition, interSlot} OPTIONAL, -- Cond RepTypeB + timeReferenceSFN-r16 ENUMERATED {sfn512} OPTIONAL -- Need S + ]] + } OPTIONAL, -- Need R + ..., + [[ + cg-RetransmissionTimer-r16 INTEGER (1..64) OPTIONAL, -- Need R + cg-minDFI-Delay-r16 ENUMERATED + {sym7, sym1x14, sym2x14, sym3x14, sym4x14, sym5x14, sym6x14, sym7x14, sym8x14, + sym9x14, sym10x14, sym11x14, sym12x14, sym13x14, sym14x14,sym15x14, sym16x14 + } OPTIONAL, -- Need R + cg-nrofPUSCH-InSlot-r16 INTEGER (1..7) OPTIONAL, -- Need R + cg-nrofSlots-r16 INTEGER (1..40) OPTIONAL, -- Need R + cg-StartingOffsets-r16 CG-StartingOffsets-r16 OPTIONAL, -- Need R + cg-UCI-Multiplexing-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + cg-COT-SharingOffset-r16 INTEGER (1..39) OPTIONAL, -- Need R + betaOffsetCG-UCI-r16 INTEGER (0..31) OPTIONAL, -- Need R + cg-COT-SharingList-r16 SEQUENCE (SIZE (1..1709)) OF CG-COT-Sharing-r16 OPTIONAL, -- Need R + harq-ProcID-Offset-r16 INTEGER (0..15) OPTIONAL, -- Need M + harq-ProcID-Offset2-r16 INTEGER (0..15) OPTIONAL, -- Need M + configuredGrantConfigIndex-r16 ConfiguredGrantConfigIndex-r16 OPTIONAL, -- Cond CG-List + configuredGrantConfigIndexMAC-r16 ConfiguredGrantConfigIndexMAC-r16 OPTIONAL, -- Cond CG-IndexMAC + periodicityExt-r16 INTEGER (1..5120) OPTIONAL, -- Need R + startingFromRV0-r16 ENUMERATED {on, off} OPTIONAL, -- Need R + phy-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL, -- Need R + autonomousTx-r16 ENUMERATED {enabled} OPTIONAL -- Cond LCH-BasedPrioritization + ]] + +} + +CG-UCI-OnPUSCH ::= CHOICE { + dynamic SEQUENCE (SIZE (1..4)) OF BetaOffsets, + semiStatic BetaOffsets +} + +CG-COT-Sharing-r16 ::= CHOICE { + noCOT-Sharing-r16 NULL, + cot-Sharing-r16 SEQUENCE { + duration-r16 INTEGER (1..39), + offset-r16 INTEGER (1..39), + channelAccessPriority-r16 INTEGER (1..4) + } +} + +CG-StartingOffsets-r16 ::= SEQUENCE { + cg-StartingFullBW-InsideCOT-r16 SEQUENCE (SIZE (1..7)) OF INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingFullBW-OutsideCOT-r16 SEQUENCE (SIZE (1..7)) OF INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingPartialBW-InsideCOT-r16 INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingPartialBW-OutsideCOT-r16 INTEGER (0..6) OPTIONAL -- Need R +} + +-- TAG-CONFIGUREDGRANTCONFIG-STOP +-- TAG-CONFIGUREDGRANTCONFIGINDEX-START + +ConfiguredGrantConfigIndex-r16 ::= INTEGER (0.. maxNrofConfiguredGrantConfig-r16-1) + +-- TAG-CONFIGUREDGRANTCONFIGINDEX-STOP +-- TAG-CONFIGUREDGRANTCONFIGINDEXMAC-START + +ConfiguredGrantConfigIndexMAC-r16 ::= INTEGER (0.. maxNrofConfiguredGrantConfigMAC-r16-1) + +-- TAG-CONFIGUREDGRANTCONFIGINDEXMAC-STOP +-- TAG-CONNESTFAILURECONTROL-START + +ConnEstFailureControl ::= SEQUENCE { + connEstFailCount ENUMERATED {n1, n2, n3, n4}, + connEstFailOffsetValidity ENUMERATED {s30, s60, s120, s240, s300, s420, s600, s900}, + connEstFailOffset INTEGER (0..15) OPTIONAL -- Need S +} + +-- TAG-CONNESTFAILURECONTROL-STOP +-- TAG-CONTROLRESOURCESET-START + +ControlResourceSet ::= SEQUENCE { + controlResourceSetId ControlResourceSetId, + + frequencyDomainResources BIT STRING (SIZE (45)), + duration INTEGER (1..maxCoReSetDuration), + cce-REG-MappingType CHOICE { + interleaved SEQUENCE { + reg-BundleSize ENUMERATED {n2, n3, n6}, + interleaverSize ENUMERATED {n2, n3, n6}, + shiftIndex INTEGER(0..maxNrofPhysicalResourceBlocks-1) OPTIONAL -- Need S + }, + nonInterleaved NULL + }, + precoderGranularity ENUMERATED {sameAsREG-bundle, allContiguousRBs}, + tci-StatesPDCCH-ToAddList SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL, -- Cond NotSIB1-initialBWP + tci-StatesPDCCH-ToReleaseList SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL, -- Cond NotSIB1-initialBWP + tci-PresentInDCI ENUMERATED {enabled} OPTIONAL, -- Need S + pdcch-DMRS-ScramblingID INTEGER (0..65535) OPTIONAL, -- Need S + ..., + [[ + rb-Offset-r16 INTEGER (0..5) OPTIONAL, -- Need S + tci-PresentDCI-1-2-r16 INTEGER (1..3) OPTIONAL, -- Need S + coresetPoolIndex-r16 INTEGER (0..1) OPTIONAL, -- Need S + controlResourceSetId-v1610 ControlResourceSetId-v1610 OPTIONAL -- Need S + ]] +} + +-- TAG-CONTROLRESOURCESET-STOP +-- TAG-CONTROLRESOURCESETID-START + +ControlResourceSetId ::= INTEGER (0..maxNrofControlResourceSets-1) + +ControlResourceSetId-r16 ::= INTEGER (0..maxNrofControlResourceSets-1-r16) + +ControlResourceSetId-v1610 ::= INTEGER (maxNrofControlResourceSets..maxNrofControlResourceSets-1-r16) + +-- TAG-CONTROLRESOURCESETID-STOP +-- TAG-CONTROLRESOURCESETZERO-START + +ControlResourceSetZero ::= INTEGER (0..15) + +-- TAG-CONTROLRESOURCESETZERO-STOP +-- TAG-CROSSCARRIERSCHEDULINGCONFIG-START + +CrossCarrierSchedulingConfig ::= SEQUENCE { + schedulingCellInfo CHOICE { + own SEQUENCE { -- Cross carrier scheduling: scheduling cell + cif-Presence BOOLEAN + }, + other SEQUENCE { -- Cross carrier scheduling: scheduled cell + schedulingCellId ServCellIndex, + cif-InSchedulingCell INTEGER (1..7) + } + }, + ..., + [[ + carrierIndicatorSize-r16 SEQUENCE { + carrierIndicatorSizeDCI-1-2-r16 INTEGER (0..3), + carrierIndicatorSizeDCI-0-2-r16 INTEGER (0..3) + } OPTIONAL, -- Cond CIF-PRESENCE + enableDefaultBeamForCCS-r16 ENUMERATED {enabled} OPTIONAL -- Need S + ]] +} + +-- TAG-CROSSCARRIERSCHEDULINGCONFIG-STOP +-- TAG-CSI-APERIODICTRIGGERSTATELIST-START + +CSI-AperiodicTriggerStateList ::= SEQUENCE (SIZE (1..maxNrOfCSI-AperiodicTriggers)) OF CSI-AperiodicTriggerState + +CSI-AperiodicTriggerState ::= SEQUENCE { + associatedReportConfigInfoList SEQUENCE (SIZE(1..maxNrofReportConfigPerAperiodicTrigger)) OF CSI-AssociatedReportConfigInfo, + ... +} + +CSI-AssociatedReportConfigInfo ::= SEQUENCE { + reportConfigId CSI-ReportConfigId, + resourcesForChannel CHOICE { + nzp-CSI-RS SEQUENCE { + resourceSet INTEGER (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig), + qcl-info SEQUENCE (SIZE(1..maxNrofAP-CSI-RS-ResourcesPerSet)) OF TCI-StateId + OPTIONAL -- Cond Aperiodic + }, + csi-SSB-ResourceSet INTEGER (1..maxNrofCSI-SSB-ResourceSetsPerConfig) + }, + csi-IM-ResourcesForInterference INTEGER(1..maxNrofCSI-IM-ResourceSetsPerConfig) OPTIONAL, -- Cond CSI-IM-ForInterference + nzp-CSI-RS-ResourcesForInterference INTEGER (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig) OPTIONAL, -- Cond NZP-CSI-RS-ForInterference + ... +} + +-- TAG-CSI-APERIODICTRIGGERSTATELIST-STOP +-- TAG-CSI-FREQUENCYOCCUPATION-START + +CSI-FrequencyOccupation ::= SEQUENCE { + startingRB INTEGER (0..maxNrofPhysicalResourceBlocks-1), + nrofRBs INTEGER (24..maxNrofPhysicalResourceBlocksPlus1), + ... +} + +-- TAG-CSI-FREQUENCYOCCUPATION-STOP +-- TAG-CSI-IM-RESOURCE-START + +CSI-IM-Resource ::= SEQUENCE { + csi-IM-ResourceId CSI-IM-ResourceId, + csi-IM-ResourceElementPattern CHOICE { + pattern0 SEQUENCE { + subcarrierLocation-p0 ENUMERATED { s0, s2, s4, s6, s8, s10 }, + symbolLocation-p0 INTEGER (0..12) + }, + pattern1 SEQUENCE { + subcarrierLocation-p1 ENUMERATED { s0, s4, s8 }, + symbolLocation-p1 INTEGER (0..13) + } + } OPTIONAL, -- Need M + freqBand CSI-FrequencyOccupation OPTIONAL, -- Need M + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, -- Cond PeriodicOrSemiPersistent + ... +} + +-- TAG-CSI-IM-RESOURCE-STOP +-- TAG-CSI-IM-RESOURCEID-START + +CSI-IM-ResourceId ::= INTEGER (0..maxNrofCSI-IM-Resources-1) + +-- TAG-CSI-IM-RESOURCEID-STOP +-- TAG-CSI-IM-RESOURCESET-START + +CSI-IM-ResourceSet ::= SEQUENCE { + csi-IM-ResourceSetId CSI-IM-ResourceSetId, + csi-IM-Resources SEQUENCE (SIZE(1..maxNrofCSI-IM-ResourcesPerSet)) OF CSI-IM-ResourceId, + ... +} +-- TAG-CSI-IM-RESOURCESET-STOP +-- TAG-CSI-IM-RESOURCESETID-START + +CSI-IM-ResourceSetId ::= INTEGER (0..maxNrofCSI-IM-ResourceSets-1) + +-- TAG-CSI-IM-RESOURCESETID-STOP +-- TAG-CSI-MEASCONFIG-START + +CSI-MeasConfig ::= SEQUENCE { + nzp-CSI-RS-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-Resources)) OF NZP-CSI-RS-Resource OPTIONAL, -- Need N + nzp-CSI-RS-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-Resources)) OF NZP-CSI-RS-ResourceId OPTIONAL, -- Need N + nzp-CSI-RS-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSets)) OF NZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + nzp-CSI-RS-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSets)) OF NZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + csi-IM-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofCSI-IM-Resources)) OF CSI-IM-Resource OPTIONAL, -- Need N + csi-IM-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-IM-Resources)) OF CSI-IM-ResourceId OPTIONAL, -- Need N + csi-IM-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSets)) OF CSI-IM-ResourceSet OPTIONAL, -- Need N + csi-IM-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSets)) OF CSI-IM-ResourceSetId OPTIONAL, -- Need N + csi-SSB-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSets)) OF CSI-SSB-ResourceSet OPTIONAL, -- Need N + csi-SSB-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSets)) OF CSI-SSB-ResourceSetId OPTIONAL, -- Need N + csi-ResourceConfigToAddModList SEQUENCE (SIZE (1..maxNrofCSI-ResourceConfigurations)) OF CSI-ResourceConfig + OPTIONAL, -- Need N + csi-ResourceConfigToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-ResourceConfigurations)) OF CSI-ResourceConfigId + OPTIONAL, -- Need N + csi-ReportConfigToAddModList SEQUENCE (SIZE (1..maxNrofCSI-ReportConfigurations)) OF CSI-ReportConfig OPTIONAL, -- Need N + csi-ReportConfigToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-ReportConfigurations)) OF CSI-ReportConfigId + OPTIONAL, -- Need N + reportTriggerSize INTEGER (0..6) OPTIONAL, -- Need M + aperiodicTriggerStateList SetupRelease { CSI-AperiodicTriggerStateList } OPTIONAL, -- Need M + semiPersistentOnPUSCH-TriggerStateList SetupRelease { CSI-SemiPersistentOnPUSCH-TriggerStateList } OPTIONAL, -- Need M + ..., + [[ + reportTriggerSizeDCI-0-2-r16 INTEGER (0..6) OPTIONAL -- Need R + ]] +} + +-- TAG-CSI-MEASCONFIG-STOP +-- TAG-CSI-REPORTCONFIG-START + +CSI-ReportConfig ::= SEQUENCE { + reportConfigId CSI-ReportConfigId, + carrier ServCellIndex OPTIONAL, -- Need S + resourcesForChannelMeasurement CSI-ResourceConfigId, + csi-IM-ResourcesForInterference CSI-ResourceConfigId OPTIONAL, -- Need R + nzp-CSI-RS-ResourcesForInterference CSI-ResourceConfigId OPTIONAL, -- Need R + reportConfigType CHOICE { + periodic SEQUENCE { + reportSlotConfig CSI-ReportPeriodicityAndOffset, + pucch-CSI-ResourceList SEQUENCE (SIZE (1..maxNrofBWPs)) OF PUCCH-CSI-Resource + }, + semiPersistentOnPUCCH SEQUENCE { + reportSlotConfig CSI-ReportPeriodicityAndOffset, + pucch-CSI-ResourceList SEQUENCE (SIZE (1..maxNrofBWPs)) OF PUCCH-CSI-Resource + }, + semiPersistentOnPUSCH SEQUENCE { + reportSlotConfig ENUMERATED {sl5, sl10, sl20, sl40, sl80, sl160, sl320}, + reportSlotOffsetList SEQUENCE (SIZE (1.. maxNrofUL-Allocations)) OF INTEGER(0..32), + p0alpha P0-PUSCH-AlphaSetId + }, + aperiodic SEQUENCE { + reportSlotOffsetList SEQUENCE (SIZE (1..maxNrofUL-Allocations)) OF INTEGER(0..32) + } + }, + reportQuantity CHOICE { + none NULL, + cri-RI-PMI-CQI NULL, + cri-RI-i1 NULL, + cri-RI-i1-CQI SEQUENCE { + pdsch-BundleSizeForCSI ENUMERATED {n2, n4} OPTIONAL -- Need S + }, + cri-RI-CQI NULL, + cri-RSRP NULL, + ssb-Index-RSRP NULL, + cri-RI-LI-PMI-CQI NULL + }, + reportFreqConfiguration SEQUENCE { + cqi-FormatIndicator ENUMERATED { widebandCQI, subbandCQI } OPTIONAL, -- Need R + pmi-FormatIndicator ENUMERATED { widebandPMI, subbandPMI } OPTIONAL, -- Need R + csi-ReportingBand CHOICE { + subbands3 BIT STRING(SIZE(3)), + subbands4 BIT STRING(SIZE(4)), + subbands5 BIT STRING(SIZE(5)), + subbands6 BIT STRING(SIZE(6)), + subbands7 BIT STRING(SIZE(7)), + subbands8 BIT STRING(SIZE(8)), + subbands9 BIT STRING(SIZE(9)), + subbands10 BIT STRING(SIZE(10)), + subbands11 BIT STRING(SIZE(11)), + subbands12 BIT STRING(SIZE(12)), + subbands13 BIT STRING(SIZE(13)), + subbands14 BIT STRING(SIZE(14)), + subbands15 BIT STRING(SIZE(15)), + subbands16 BIT STRING(SIZE(16)), + subbands17 BIT STRING(SIZE(17)), + subbands18 BIT STRING(SIZE(18)), + ..., + subbands19-v1530 BIT STRING(SIZE(19)) + } OPTIONAL -- Need S + + } OPTIONAL, -- Need R + timeRestrictionForChannelMeasurements ENUMERATED {configured, notConfigured}, + timeRestrictionForInterferenceMeasurements ENUMERATED {configured, notConfigured}, + codebookConfig CodebookConfig OPTIONAL, -- Need R + dummy ENUMERATED {n1, n2} OPTIONAL, -- Need R + groupBasedBeamReporting CHOICE { + enabled NULL, + disabled SEQUENCE { + nrofReportedRS ENUMERATED {n1, n2, n3, n4} OPTIONAL -- Need S + } + }, + cqi-Table ENUMERATED {table1, table2, table3, spare1} OPTIONAL, -- Need R + subbandSize ENUMERATED {value1, value2}, + non-PMI-PortIndication SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourcesPerConfig)) OF PortIndexFor8Ranks OPTIONAL, -- Need R + ..., + [[ + semiPersistentOnPUSCH-v1530 SEQUENCE { + reportSlotConfig-v1530 ENUMERATED {sl4, sl8, sl16} + } OPTIONAL -- Need R + ]], + [[ + semiPersistentOnPUSCH-v1610 SEQUENCE { + reportSlotOffsetListDCI-0-2-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) OPTIONAL, -- Need R + reportSlotOffsetListDCI-0-1-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) OPTIONAL -- Need R + } OPTIONAL, -- Need R + aperiodic-v1610 SEQUENCE { + reportSlotOffsetListDCI-0-2-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) OPTIONAL, -- Need R + reportSlotOffsetListDCI-0-1-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) OPTIONAL -- Need R + } OPTIONAL, -- Need R + reportQuantity-r16 CHOICE { + cri-SINR-r16 NULL, + ssb-Index-SINR-r16 NULL + } OPTIONAL, -- Need R + codebookConfig-r16 CodebookConfig-r16 OPTIONAL -- Need R + ]] +} + +CSI-ReportPeriodicityAndOffset ::= CHOICE { + slots4 INTEGER(0..3), + slots5 INTEGER(0..4), + slots8 INTEGER(0..7), + slots10 INTEGER(0..9), + slots16 INTEGER(0..15), + slots20 INTEGER(0..19), + slots40 INTEGER(0..39), + slots80 INTEGER(0..79), + slots160 INTEGER(0..159), + slots320 INTEGER(0..319) +} + +PUCCH-CSI-Resource ::= SEQUENCE { + uplinkBandwidthPartId BWP-Id, + pucch-Resource PUCCH-ResourceId +} + +PortIndexFor8Ranks ::= CHOICE { + portIndex8 SEQUENCE{ + rank1-8 PortIndex8 OPTIONAL, -- Need R + rank2-8 SEQUENCE(SIZE(2)) OF PortIndex8 OPTIONAL, -- Need R + rank3-8 SEQUENCE(SIZE(3)) OF PortIndex8 OPTIONAL, -- Need R + rank4-8 SEQUENCE(SIZE(4)) OF PortIndex8 OPTIONAL, -- Need R + rank5-8 SEQUENCE(SIZE(5)) OF PortIndex8 OPTIONAL, -- Need R + rank6-8 SEQUENCE(SIZE(6)) OF PortIndex8 OPTIONAL, -- Need R + rank7-8 SEQUENCE(SIZE(7)) OF PortIndex8 OPTIONAL, -- Need R + rank8-8 SEQUENCE(SIZE(8)) OF PortIndex8 OPTIONAL -- Need R + }, + portIndex4 SEQUENCE{ + rank1-4 PortIndex4 OPTIONAL, -- Need R + rank2-4 SEQUENCE(SIZE(2)) OF PortIndex4 OPTIONAL, -- Need R + rank3-4 SEQUENCE(SIZE(3)) OF PortIndex4 OPTIONAL, -- Need R + rank4-4 SEQUENCE(SIZE(4)) OF PortIndex4 OPTIONAL -- Need R + }, + portIndex2 SEQUENCE{ + rank1-2 PortIndex2 OPTIONAL, -- Need R + rank2-2 SEQUENCE(SIZE(2)) OF PortIndex2 OPTIONAL -- Need R + }, + portIndex1 NULL +} + +PortIndex8::= INTEGER (0..7) +PortIndex4::= INTEGER (0..3) +PortIndex2::= INTEGER (0..1) + +-- TAG-CSI-REPORTCONFIG-STOP +-- TAG-CSI-REPORTCONFIGID-START + +CSI-ReportConfigId ::= INTEGER (0..maxNrofCSI-ReportConfigurations-1) + +-- TAG-CSI-REPORTCONFIGID-STOP +-- TAG-CSI-RESOURCECONFIG-START + +CSI-ResourceConfig ::= SEQUENCE { + csi-ResourceConfigId CSI-ResourceConfigId, + csi-RS-ResourceSetList CHOICE { + nzp-CSI-RS-SSB SEQUENCE { + nzp-CSI-RS-ResourceSetList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig)) OF NZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need R + csi-SSB-ResourceSetList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSetsPerConfig)) OF CSI-SSB-ResourceSetId OPTIONAL -- Need R + }, + csi-IM-ResourceSetList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSetsPerConfig)) OF CSI-IM-ResourceSetId + }, + + bwp-Id BWP-Id, + resourceType ENUMERATED { aperiodic, semiPersistent, periodic }, + ... +} + +-- TAG-CSI-RESOURCECONFIG-STOP +-- TAG-CSI-RESOURCECONFIGID-START + +CSI-ResourceConfigId ::= INTEGER (0..maxNrofCSI-ResourceConfigurations-1) + +-- TAG-CSI-RESOURCECONFIGID-STOP +-- TAG-CSI-RESOURCEPERIODICITYANDOFFSET-START + +CSI-ResourcePeriodicityAndOffset ::= CHOICE { + slots4 INTEGER (0..3), + slots5 INTEGER (0..4), + slots8 INTEGER (0..7), + slots10 INTEGER (0..9), + slots16 INTEGER (0..15), + slots20 INTEGER (0..19), + slots32 INTEGER (0..31), + slots40 INTEGER (0..39), + slots64 INTEGER (0..63), + slots80 INTEGER (0..79), + slots160 INTEGER (0..159), + slots320 INTEGER (0..319), + slots640 INTEGER (0..639) +} + +-- TAG-CSI-RESOURCEPERIODICITYANDOFFSET-STOP +-- TAG-CSI-RS-RESOURCECONFIGMOBILITY-START + +CSI-RS-ResourceConfigMobility ::= SEQUENCE { + subcarrierSpacing SubcarrierSpacing, + csi-RS-CellList-Mobility SEQUENCE (SIZE (1..maxNrofCSI-RS-CellsRRM)) OF CSI-RS-CellMobility, + ..., + [[ + refServCellIndex ServCellIndex OPTIONAL -- Need S + ]] + + +} + +CSI-RS-CellMobility ::= SEQUENCE { + cellId PhysCellId, + csi-rs-MeasurementBW SEQUENCE { + nrofPRBs ENUMERATED { size24, size48, size96, size192, size264}, + startPRB INTEGER(0..2169) + }, + density ENUMERATED {d1,d3} OPTIONAL, -- Need R + csi-rs-ResourceList-Mobility SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesRRM)) OF CSI-RS-Resource-Mobility +} + +CSI-RS-Resource-Mobility ::= SEQUENCE { + csi-RS-Index CSI-RS-Index, + slotConfig CHOICE { + ms4 INTEGER (0..31), + ms5 INTEGER (0..39), + ms10 INTEGER (0..79), + ms20 INTEGER (0..159), + ms40 INTEGER (0..319) + }, + associatedSSB SEQUENCE { + ssb-Index SSB-Index, + isQuasiColocated BOOLEAN + } OPTIONAL, -- Need R + frequencyDomainAllocation CHOICE { + row1 BIT STRING (SIZE (4)), + row2 BIT STRING (SIZE (12)) + }, + firstOFDMSymbolInTimeDomain INTEGER (0..13), + sequenceGenerationConfig INTEGER (0..1023), + ... +} + +CSI-RS-Index ::= INTEGER (0..maxNrofCSI-RS-ResourcesRRM-1) + +-- TAG-CSI-RS-RESOURCECONFIGMOBILITY-STOP +-- TAG-CSI-RS-RESOURCEMAPPING-START + +CSI-RS-ResourceMapping ::= SEQUENCE { + frequencyDomainAllocation CHOICE { + row1 BIT STRING (SIZE (4)), + row2 BIT STRING (SIZE (12)), + row4 BIT STRING (SIZE (3)), + other BIT STRING (SIZE (6)) + }, + nrofPorts ENUMERATED {p1,p2,p4,p8,p12,p16,p24,p32}, + firstOFDMSymbolInTimeDomain INTEGER (0..13), + firstOFDMSymbolInTimeDomain2 INTEGER (2..12) OPTIONAL, -- Need R + cdm-Type ENUMERATED {noCDM, fd-CDM2, cdm4-FD2-TD2, cdm8-FD2-TD4}, + density CHOICE { + dot5 ENUMERATED {evenPRBs, oddPRBs}, + one NULL, + three NULL, + spare NULL + }, + freqBand CSI-FrequencyOccupation, + ... +} + +-- TAG-CSI-RS-RESOURCEMAPPING-STOP +-- TAG-CSI-SEMIPERSISTENTONPUSCHTRIGGERSTATELIST-START + +CSI-SemiPersistentOnPUSCH-TriggerStateList ::= SEQUENCE(SIZE (1..maxNrOfSemiPersistentPUSCH-Triggers)) OF CSI-SemiPersistentOnPUSCH-TriggerState + +CSI-SemiPersistentOnPUSCH-TriggerState ::= SEQUENCE { + associatedReportConfigInfo CSI-ReportConfigId, + ... +} + +-- TAG-CSI-SEMIPERSISTENTONPUSCHTRIGGERSTATELIST-STOP +-- TAG-CSI-SSB-RESOURCESET-START + +CSI-SSB-ResourceSet ::= SEQUENCE { + csi-SSB-ResourceSetId CSI-SSB-ResourceSetId, + csi-SSB-ResourceList SEQUENCE (SIZE(1..maxNrofCSI-SSB-ResourcePerSet)) OF SSB-Index, + ... +} + +-- TAG-CSI-SSB-RESOURCESET-STOP +-- TAG-CSI-SSB-RESOURCESETID-START + +CSI-SSB-ResourceSetId ::= INTEGER (0..maxNrofCSI-SSB-ResourceSets-1) + +-- TAG-CSI-SSB-RESOURCESETID-STOP +-- TAG-DEDICATED-NAS-MESSAGE-START + +DedicatedNAS-Message ::= OCTET STRING + +-- TAG-DEDICATED-NAS-MESSAGE-STOP +-- TAG-DMRS-DOWNLINKCONFIG-START + +DMRS-DownlinkConfig ::= SEQUENCE { + dmrs-Type ENUMERATED {type2} OPTIONAL, -- Need S + dmrs-AdditionalPosition ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + maxLength ENUMERATED {len2} OPTIONAL, -- Need S + scramblingID0 INTEGER (0..65535) OPTIONAL, -- Need S + scramblingID1 INTEGER (0..65535) OPTIONAL, -- Need S + phaseTrackingRS SetupRelease { PTRS-DownlinkConfig } OPTIONAL, -- Need M + ..., + [[ + dmrs-Downlink-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + +} + +-- TAG-DMRS-DOWNLINKCONFIG-STOP +-- TAG-DMRS-UPLINKCONFIG-START + +DMRS-UplinkConfig ::= SEQUENCE { + dmrs-Type ENUMERATED {type2} OPTIONAL, -- Need S + dmrs-AdditionalPosition ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + phaseTrackingRS SetupRelease { PTRS-UplinkConfig } OPTIONAL, -- Need M + maxLength ENUMERATED {len2} OPTIONAL, -- Need S + transformPrecodingDisabled SEQUENCE { + scramblingID0 INTEGER (0..65535) OPTIONAL, -- Need S + scramblingID1 INTEGER (0..65535) OPTIONAL, -- Need S + ..., + [[ + dmrs-Uplink-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + } OPTIONAL, -- Need R + transformPrecodingEnabled SEQUENCE { + nPUSCH-Identity INTEGER(0..1007) OPTIONAL, -- Need S + sequenceGroupHopping ENUMERATED {disabled} OPTIONAL, -- Need S + sequenceHopping ENUMERATED {enabled} OPTIONAL, -- Need S + ..., + [[ + dmrs-UplinkTransformPrecoding-r16 SetupRelease {DMRS-UplinkTransformPrecoding-r16} OPTIONAL -- Need M + ]] + } OPTIONAL, -- Need R + ... +} + +DMRS-UplinkTransformPrecoding-r16 ::= SEQUENCE { + pi2BPSK-ScramblingID0 INTEGER(0..65535) OPTIONAL, -- Need S + pi2BPSK-ScramblingID1 INTEGER(0..65535) OPTIONAL -- Need S +} + +-- TAG-DMRS-UPLINKCONFIG-STOP +-- TAG-DOWNLINKCONFIGCOMMON-START + +DownlinkConfigCommon ::= SEQUENCE { + frequencyInfoDL FrequencyInfoDL OPTIONAL, -- Cond InterFreqHOAndServCellAdd + initialDownlinkBWP BWP-DownlinkCommon OPTIONAL, -- Cond ServCellAdd + ... +} + +-- TAG-DOWNLINKCONFIGCOMMON-STOP +-- TAG-DOWNLINKCONFIGCOMMONSIB-START + +DownlinkConfigCommonSIB ::= SEQUENCE { + frequencyInfoDL FrequencyInfoDL-SIB, + initialDownlinkBWP BWP-DownlinkCommon, + bcch-Config BCCH-Config, + pcch-Config PCCH-Config, + ... +} + + +BCCH-Config ::= SEQUENCE { + modificationPeriodCoeff ENUMERATED {n2, n4, n8, n16}, + ... +} + + +PCCH-Config ::= SEQUENCE { + defaultPagingCycle PagingCycle, + nAndPagingFrameOffset CHOICE { + oneT NULL, + halfT INTEGER (0..1), + quarterT INTEGER (0..3), + oneEighthT INTEGER (0..7), + oneSixteenthT INTEGER (0..15) + }, + ns ENUMERATED {four, two, one}, + firstPDCCH-MonitoringOccasionOfPO CHOICE { + sCS15KHZoneT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..139), + sCS30KHZoneT-SCS15KHZhalfT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..279), + sCS60KHZoneT-SCS30KHZhalfT-SCS15KHZquarterT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..559), + sCS120KHZoneT-SCS60KHZhalfT-SCS30KHZquarterT-SCS15KHZoneEighthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..1119), + sCS120KHZhalfT-SCS60KHZquarterT-SCS30KHZoneEighthT-SCS15KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..2239), + sCS120KHZquarterT-SCS60KHZoneEighthT-SCS30KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..4479), + sCS120KHZoneEighthT-SCS60KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..8959), + sCS120KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..17919) + } OPTIONAL, -- Need R + ..., + [[ + nrofPDCCH-MonitoringOccasionPerSSB-InPO-r16 INTEGER (2..4) OPTIONAL -- Cond SharedSpectrum2 + ]] +} + +-- TAG-DOWNLINKCONFIGCOMMONSIB-STOP +-- TAG-DOWNLINKPREEMPTION-START + +DownlinkPreemption ::= SEQUENCE { + int-RNTI RNTI-Value, + timeFrequencySet ENUMERATED {set0, set1}, + dci-PayloadSize INTEGER (0..maxINT-DCI-PayloadSize), + int-ConfigurationPerServingCell SEQUENCE (SIZE (1..maxNrofServingCells)) OF INT-ConfigurationPerServingCell, + ... +} + +INT-ConfigurationPerServingCell ::= SEQUENCE { + servingCellId ServCellIndex, + positionInDCI INTEGER (0..maxINT-DCI-PayloadSize-1) +} + +-- TAG-DOWNLINKPREEMPTION-STOP +-- TAG-DRB-IDENTITY-START + +DRB-Identity ::= INTEGER (1..32) + +-- TAG-DRB-IDENTITY-STOP +-- TAG-DRX-CONFIG-START + +DRX-Config ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + }, + drx-InactivityTimer ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1}, + drx-HARQ-RTT-TimerDL INTEGER (0..56), + drx-HARQ-RTT-TimerUL INTEGER (0..56), + drx-RetransmissionTimerDL ENUMERATED { + sl0, sl1, sl2, sl4, sl6, sl8, sl16, sl24, sl33, sl40, sl64, sl80, sl96, sl112, sl128, + sl160, sl320, spare15, spare14, spare13, spare12, spare11, spare10, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1}, + drx-RetransmissionTimerUL ENUMERATED { + sl0, sl1, sl2, sl4, sl6, sl8, sl16, sl24, sl33, sl40, sl64, sl80, sl96, sl112, sl128, + sl160, sl320, spare15, spare14, spare13, spare12, spare11, spare10, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-LongCycleStartOffset CHOICE { + ms10 INTEGER(0..9), + ms20 INTEGER(0..19), + ms32 INTEGER(0..31), + ms40 INTEGER(0..39), + ms60 INTEGER(0..59), + ms64 INTEGER(0..63), + ms70 INTEGER(0..69), + ms80 INTEGER(0..79), + ms128 INTEGER(0..127), + ms160 INTEGER(0..159), + ms256 INTEGER(0..255), + ms320 INTEGER(0..319), + ms512 INTEGER(0..511), + ms640 INTEGER(0..639), + ms1024 INTEGER(0..1023), + ms1280 INTEGER(0..1279), + ms2048 INTEGER(0..2047), + ms2560 INTEGER(0..2559), + ms5120 INTEGER(0..5119), + ms10240 INTEGER(0..10239) + }, + shortDRX SEQUENCE { + drx-ShortCycle ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-ShortCycleTimer INTEGER (1..16) + } OPTIONAL, -- Need R + drx-SlotOffset INTEGER (0..31) +} + +-- TAG-DRX-CONFIG-STOP +-- TAG-DRX-CONFIGSECONDARYGROUP-START + +DRX-ConfigSecondaryGroup ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + }, + drx-InactivityTimer ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1} +} + +-- TAG-DRX-CONFIGSECONDARYGROUP-STOP +-- TAG-FILTERCOEFFICIENT-START + +FilterCoefficient ::= ENUMERATED { fc0, fc1, fc2, fc3, fc4, fc5, fc6, fc7, fc8, fc9, fc11, fc13, fc15, fc17, fc19, spare1, ...} + +-- TAG-FILTERCOEFFICIENT-STOP +-- TAG-FREQBANDINDICATORNR-START + +FreqBandIndicatorNR ::= INTEGER (1..1024) + +-- TAG-FREQBANDINDICATORNR-STOP +-- TAG-FREQUENCYINFODL-START + +FrequencyInfoDL ::= SEQUENCE { + absoluteFrequencySSB ARFCN-ValueNR OPTIONAL, -- Cond SpCellAdd + frequencyBandList MultiFrequencyBandListNR, + absoluteFrequencyPointA ARFCN-ValueNR, + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + ... +} + +-- TAG-FREQUENCYINFODL-STOP +-- TAG-FREQUENCYINFODL-SIB-START + +FrequencyInfoDL-SIB ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR-SIB, + offsetToPointA INTEGER (0..2199), + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier +} + +-- TAG-FREQUENCYINFODL-SIB-STOP +-- TAG-FREQUENCYINFOUL-START + +FrequencyInfoUL ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR OPTIONAL, -- Cond FDD-OrSUL + absoluteFrequencyPointA ARFCN-ValueNR OPTIONAL, -- Cond FDD-OrSUL + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + additionalSpectrumEmission AdditionalSpectrumEmission OPTIONAL, -- Need S + p-Max P-Max OPTIONAL, -- Need S + frequencyShift7p5khz ENUMERATED {true} OPTIONAL, -- Cond FDD-TDD-OrSUL-Optional + ... +} + +-- TAG-FREQUENCYINFOUL-STOP +-- TAG-FREQUENCYINFOUL-SIB-START + +FrequencyInfoUL-SIB ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Cond FDD-OrSUL + absoluteFrequencyPointA ARFCN-ValueNR OPTIONAL, -- Cond FDD-OrSUL + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + p-Max P-Max OPTIONAL, -- Need S + frequencyShift7p5khz ENUMERATED {true} OPTIONAL, -- Cond FDD-TDD-OrSUL-Optional + ... +} + +-- TAG-FREQUENCYINFOUL-SIB-STOP +-- TAG-HIGHSPEEDCONFIG-START + +HighSpeedConfig-r16 ::= SEQUENCE { + highSpeedMeasFlag-r16 ENUMERATED {true} OPTIONAL, -- Need R + highSpeedDemodFlag-r16 ENUMERATED {true} OPTIONAL, -- Need R + ... +} + +-- TAG-HIGHSPEEDCONFIG-STOP +-- TAG-HYSTERESIS-START + +Hysteresis ::= INTEGER (0..30) + +-- TAG-HYSTERESIS-STOP +-- TAG-INVALIDSYMBOLPATTERN-START + +InvalidSymbolPattern-r16 ::= SEQUENCE { + symbols-r16 CHOICE { + oneSlot BIT STRING (SIZE (14)), + twoSlots BIT STRING (SIZE (28)) + }, + periodicityAndPattern-r16 CHOICE { + n2 BIT STRING (SIZE (2)), + n4 BIT STRING (SIZE (4)), + n5 BIT STRING (SIZE (5)), + n8 BIT STRING (SIZE (8)), + n10 BIT STRING (SIZE (10)), + n20 BIT STRING (SIZE (20)), + n40 BIT STRING (SIZE (40)) + } OPTIONAL, -- Need M + ... +} + +-- TAG-INVALIDSYMBOLPATTERN-STOP +-- TAG-I-RNTI-VALUE-START + +I-RNTI-Value ::= BIT STRING (SIZE(40)) + +-- TAG-I-RNTI-VALUE-STOP +-- TAG-LBT-FAILURERECOVERYCONFIG-START + +LBT-FailureRecoveryConfig-r16 ::= SEQUENCE { + lbt-FailureInstanceMaxCount-r16 ENUMERATED {n4, n8, n16, n32, n64, n128}, + lbt-FailureDetectionTimer-r16 ENUMERATED {ms10, ms20, ms40, ms80, ms160, ms320}, + ... +} + +-- TAG-LBT-FAILURERECOVERYCONFIG-STOP +-- TAG-LOCATIONINFO-START + +LocationInfo-r16 ::= SEQUENCE { + commonLocationInfo-r16 CommonLocationInfo-r16 OPTIONAL, + bt-LocationInfo-r16 LogMeasResultListBT-r16 OPTIONAL, + wlan-LocationInfo-r16 LogMeasResultListWLAN-r16 OPTIONAL, + sensor-LocationInfo-r16 Sensor-LocationInfo-r16 OPTIONAL, + ... +} + +-- TAG-LOCATIONINFO-STOP +-- TAG-LOCATIONMEASUREMENTINFO-START + +LocationMeasurementInfo ::= CHOICE { + eutra-RSTD EUTRA-RSTD-InfoList, + ..., + eutra-FineTimingDetection NULL, + nr-PRS-Measurement-r16 NR-PRS-MeasurementInfoList-r16 +} + +EUTRA-RSTD-InfoList ::= SEQUENCE (SIZE (1..maxInterRAT-RSTD-Freq)) OF EUTRA-RSTD-Info + +EUTRA-RSTD-Info ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + measPRS-Offset INTEGER (0..39), + ... +} + +NR-PRS-MeasurementInfoList-r16 ::= SEQUENCE (SIZE (1..maxFreqLayers)) OF NR-PRS-MeasurementInfo-r16 + +NR-PRS-MeasurementInfo-r16 ::= SEQUENCE { + dl-PRS-PointA-r16 ARFCN-ValueNR, + nr-MeasPRS-RepetitionAndOffset-r16 CHOICE { + ms20-r16 INTEGER (0..19), + ms40-r16 INTEGER (0..39), + ms80-r16 INTEGER (0..79), + ms160-r16 INTEGER (0..159), + ... + }, + nr-MeasPRS-length-r16 ENUMERATED {ms1dot5, ms3, ms3dot5, ms4, ms5dot5, ms6, ms10, ms20}, + ... +} + +-- TAG-LOCATIONMEASUREMENTINFO-STOP +-- TAG-LOGICALCHANNELCONFIG-START + +LogicalChannelConfig ::= SEQUENCE { + ul-SpecificParameters SEQUENCE { + priority INTEGER (1..16), + prioritisedBitRate ENUMERATED {kBps0, kBps8, kBps16, kBps32, kBps64, kBps128, kBps256, kBps512, + kBps1024, kBps2048, kBps4096, kBps8192, kBps16384, kBps32768, kBps65536, infinity}, + bucketSizeDuration ENUMERATED {ms5, ms10, ms20, ms50, ms100, ms150, ms300, ms500, ms1000, + spare7, spare6, spare5, spare4, spare3,spare2, spare1}, + allowedServingCells SEQUENCE (SIZE (1..maxNrofServingCells-1)) OF ServCellIndex + OPTIONAL, -- Cond PDCP-CADuplication + allowedSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SubcarrierSpacing OPTIONAL, -- Need R + maxPUSCH-Duration ENUMERATED {ms0p02, ms0p04, ms0p0625, ms0p125, ms0p25, ms0p5, spare2, spare1} + OPTIONAL, -- Need R + configuredGrantType1Allowed ENUMERATED {true} OPTIONAL, -- Need R + logicalChannelGroup INTEGER (0..maxLCG-ID) OPTIONAL, -- Need R + schedulingRequestID SchedulingRequestId OPTIONAL, -- Need R + logicalChannelSR-Mask BOOLEAN, + logicalChannelSR-DelayTimerApplied BOOLEAN, + ..., + bitRateQueryProhibitTimer ENUMERATED {s0, s0dot4, s0dot8, s1dot6, s3, s6, s12, s30} OPTIONAL, -- Need R + [[ + allowedCG-List-r16 SEQUENCE (SIZE (0.. maxNrofConfiguredGrantConfigMAC-r16-1)) OF ConfiguredGrantConfigIndexMAC-r16 + OPTIONAL, -- Need S + allowedPHY-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL -- Need S + ]] + } OPTIONAL, -- Cond UL + ..., + [[ + channelAccessPriority-r16 INTEGER (1..4) OPTIONAL, -- Need R + bitRateMultiplier-r16 ENUMERATED {x40, x70, x100, x200} OPTIONAL -- Need R + ]] +} + +-- TAG-LOGICALCHANNELCONFIG-STOP +-- TAG-LOGICALCHANNELIDENTITY-START + +LogicalChannelIdentity ::= INTEGER (1..maxLC-ID) + +-- TAG-LOGICALCHANNELIDENTITY-STOP +-- TAG-MAC-CELLGROUPCONFIG-START + +MAC-CellGroupConfig ::= SEQUENCE { + drx-Config SetupRelease { DRX-Config } OPTIONAL, -- Need M + schedulingRequestConfig SchedulingRequestConfig OPTIONAL, -- Need M + bsr-Config BSR-Config OPTIONAL, -- Need M + tag-Config TAG-Config OPTIONAL, -- Need M + phr-Config SetupRelease { PHR-Config } OPTIONAL, -- Need M + skipUplinkTxDynamic BOOLEAN, + ..., + [[ + csi-Mask BOOLEAN OPTIONAL, -- Need M + dataInactivityTimer SetupRelease { DataInactivityTimer } OPTIONAL -- Cond MCG-Only + ]], + [[ + usePreBSR-r16 ENUMERATED {true} OPTIONAL, -- Need R + schedulingRequestID-LBT-SCell-r16 SchedulingRequestId OPTIONAL, -- Need R + lch-BasedPrioritization-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + schedulingRequestID-BFR-SCell-r16 SchedulingRequestId OPTIONAL, -- Need R + drx-ConfigSecondaryGroup-r16 SetupRelease { DRX-ConfigSecondaryGroup } OPTIONAL -- Need M + ]], + [[ + enhancedSkipUplinkTxDynamic-r16 ENUMERATED {true} OPTIONAL, -- Need R + enhancedSkipUplinkTxConfigured-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +DataInactivityTimer ::= ENUMERATED {s1, s2, s3, s5, s7, s10, s15, s20, s40, s50, s60, s80, s100, s120, s150, s180} + +-- TAG-MAC-CELLGROUPCONFIG-STOP +-- TAG-MEASCONFIG-START + +MeasConfig ::= SEQUENCE { + measObjectToRemoveList MeasObjectToRemoveList OPTIONAL, -- Need N + measObjectToAddModList MeasObjectToAddModList OPTIONAL, -- Need N + reportConfigToRemoveList ReportConfigToRemoveList OPTIONAL, -- Need N + reportConfigToAddModList ReportConfigToAddModList OPTIONAL, -- Need N + measIdToRemoveList MeasIdToRemoveList OPTIONAL, -- Need N + measIdToAddModList MeasIdToAddModList OPTIONAL, -- Need N + s-MeasureConfig CHOICE { + ssb-RSRP RSRP-Range, + csi-RSRP RSRP-Range + } OPTIONAL, -- Need M + quantityConfig QuantityConfig OPTIONAL, -- Need M + measGapConfig MeasGapConfig OPTIONAL, -- Need M + measGapSharingConfig MeasGapSharingConfig OPTIONAL, -- Need M + ..., + [[ + interFrequencyConfig-NoGap-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +MeasObjectToRemoveList ::= SEQUENCE (SIZE (1..maxNrofObjectId)) OF MeasObjectId + +MeasIdToRemoveList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF MeasId + +ReportConfigToRemoveList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigId + +-- TAG-MEASCONFIG-STOP +-- TAG-MEASGAPCONFIG-START + +MeasGapConfig ::= SEQUENCE { + gapFR2 SetupRelease { GapConfig } OPTIONAL, -- Need M + ..., + [[ + gapFR1 SetupRelease { GapConfig } OPTIONAL, -- Need M + gapUE SetupRelease { GapConfig } OPTIONAL -- Need M + ]] + +} + +GapConfig ::= SEQUENCE { + gapOffset INTEGER (0..159), + mgl ENUMERATED {ms1dot5, ms3, ms3dot5, ms4, ms5dot5, ms6}, + mgrp ENUMERATED {ms20, ms40, ms80, ms160}, + mgta ENUMERATED {ms0, ms0dot25, ms0dot5}, + ..., + [[ + refServCellIndicator ENUMERATED {pCell, pSCell, mcg-FR2} OPTIONAL -- Cond NEDCorNRDC + ]], + [[ + refFR2ServCellAsyncCA-r16 ServCellIndex OPTIONAL, -- Cond AsyncCA + mgl-r16 ENUMERATED {ms10, ms20} OPTIONAL -- Cond PRS + ]] +} + +-- TAG-MEASGAPCONFIG-STOP +-- TAG-MEASGAPSHARINGCONFIG-START + +MeasGapSharingConfig ::= SEQUENCE { + gapSharingFR2 SetupRelease { MeasGapSharingScheme } OPTIONAL, -- Need M + ..., + [[ + gapSharingFR1 SetupRelease { MeasGapSharingScheme } OPTIONAL, --Need M + gapSharingUE SetupRelease { MeasGapSharingScheme } OPTIONAL --Need M + ]] +} + +MeasGapSharingScheme::= ENUMERATED {scheme00, scheme01, scheme10, scheme11} + +-- TAG-MEASGAPSHARINGCONFIG-STOP +-- TAG-MEASID-START + +MeasId ::= INTEGER (1..maxNrofMeasId) + +-- TAG-MEASID-STOP +-- TAG-MEASIDLECONFIG-START + +MeasIdleConfigSIB-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, -- Need S + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, -- Need S + ... +} + +MeasIdleConfigDedicated-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, -- Need N + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, -- Need N + measIdleDuration-r16 ENUMERATED{sec10, sec30, sec60, sec120, sec180, sec240, sec300, spare}, + validityAreaList-r16 ValidityAreaList-r16 OPTIONAL, -- Need N + ... +} + +ValidityAreaList-r16 ::= SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF ValidityArea-r16 + +ValidityArea-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + validityCellList-r16 ValidityCellList OPTIONAL -- Need N +} + +ValidityCellList ::= SEQUENCE (SIZE (1.. maxCellMeasIdle-r16)) OF PCI-Range + +MeasIdleCarrierNR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + ssbSubcarrierSpacing-r16 SubcarrierSpacing, + frequencyBandList MultiFrequencyBandListNR OPTIONAL, -- Need R + measCellListNR-r16 CellListNR-r16 OPTIONAL, -- Need R + reportQuantities-r16 ENUMERATED {rsrp, rsrq, both}, + qualityThreshold-r16 SEQUENCE { + idleRSRP-Threshold-NR-r16 RSRP-Range OPTIONAL, -- Need R + idleRSRQ-Threshold-NR-r16 RSRQ-Range OPTIONAL -- Need R + } OPTIONAL, -- Need R + ssb-MeasConfig-r16 SEQUENCE { + nrofSS-BlocksToAverage-r16 INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation-r16 ThresholdNR OPTIONAL, -- Need S + smtc-r16 SSB-MTC OPTIONAL, -- Need S + ssb-ToMeasure-r16 SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell-r16 BOOLEAN, + ss-RSSI-Measurement-r16 SS-RSSI-Measurement OPTIONAL -- Need S + } OPTIONAL, -- Need S + beamMeasConfigIdle-r16 BeamMeasConfigIdle-NR-r16 OPTIONAL, -- Need R + ... +} + +MeasIdleCarrierEUTRA-r16 ::= SEQUENCE { + carrierFreqEUTRA-r16 ARFCN-ValueEUTRA, + allowedMeasBandwidth-r16 EUTRA-AllowedMeasBandwidth, + measCellListEUTRA-r16 CellListEUTRA-r16 OPTIONAL, -- Need R + reportQuantitiesEUTRA-r16 ENUMERATED {rsrp, rsrq, both}, + qualityThresholdEUTRA-r16 SEQUENCE { + idleRSRP-Threshold-EUTRA-r16 RSRP-RangeEUTRA OPTIONAL, -- Need R + idleRSRQ-Threshold-EUTRA-r16 RSRQ-RangeEUTRA-r16 OPTIONAL -- Need R + } OPTIONAL, -- Need S + ... +} + +CellListNR-r16 ::= SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF PCI-Range + +CellListEUTRA-r16 ::= SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF EUTRA-PhysCellIdRange + +BeamMeasConfigIdle-NR-r16 ::= SEQUENCE { + reportQuantityRS-Indexes-r16 ENUMERATED {rsrp, rsrq, both}, + maxNrofRS-IndexesToReport-r16 INTEGER (1.. maxNrofIndexesToReport), + includeBeamMeasurements-r16 BOOLEAN +} + +RSRQ-RangeEUTRA-r16 ::= INTEGER (-30..46) + +-- TAG-MEASIDLECONFIG-STOP +-- TAG-MEASIDTOADDMODLIST-START + +MeasIdToAddModList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF MeasIdToAddMod + +MeasIdToAddMod ::= SEQUENCE { + measId MeasId, + measObjectId MeasObjectId, + reportConfigId ReportConfigId +} + +-- TAG-MEASIDTOADDMODLIST-STOP +-- TAG-MEASOBJECTCLI-START + +MeasObjectCLI-r16 ::= SEQUENCE { + cli-ResourceConfig-r16 CLI-ResourceConfig-r16, + ... +} + +CLI-ResourceConfig-r16 ::= SEQUENCE { + srs-ResourceConfig-r16 SetupRelease { SRS-ResourceListConfigCLI-r16 } OPTIONAL, -- Need M + rssi-ResourceConfig-r16 SetupRelease { RSSI-ResourceListConfigCLI-r16 } OPTIONAL -- Need M +} + +SRS-ResourceListConfigCLI-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-SRS-Resources-r16)) OF SRS-ResourceConfigCLI-r16 + +RSSI-ResourceListConfigCLI-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-RSSI-Resources-r16)) OF RSSI-ResourceConfigCLI-r16 + +SRS-ResourceConfigCLI-r16 ::= SEQUENCE { + srs-Resource-r16 SRS-Resource, + srs-SCS-r16 SubcarrierSpacing, + refServCellIndex-r16 ServCellIndex OPTIONAL, -- Need S + refBWP-r16 BWP-Id, + ... +} + +RSSI-ResourceConfigCLI-r16 ::= SEQUENCE { + rssi-ResourceId-r16 RSSI-ResourceId-r16, + rssi-SCS-r16 SubcarrierSpacing, + startPRB-r16 INTEGER (0..2169), + nrofPRBs-r16 INTEGER (4..maxNrofPhysicalResourceBlocksPlus1), + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 INTEGER (1..14), + rssi-PeriodicityAndOffset-r16 RSSI-PeriodicityAndOffset-r16, + refServCellIndex-r16 ServCellIndex OPTIONAL, -- Need S + ... +} + +RSSI-ResourceId-r16 ::= INTEGER (0.. maxNrofCLI-RSSI-Resources-r16-1) + +RSSI-PeriodicityAndOffset-r16 ::= CHOICE { + sl10 INTEGER(0..9), + sl20 INTEGER(0..19), + sl40 INTEGER(0..39), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + s1640 INTEGER(0..639), + ... +} + +-- TAG-MEASOBJECTCLI-STOP +-- TAG-MEASOBJECTEUTRA-START + +MeasObjectEUTRA::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + allowedMeasBandwidth EUTRA-AllowedMeasBandwidth, + cellsToRemoveListEUTRAN EUTRA-CellIndexList OPTIONAL, -- Need N + cellsToAddModListEUTRAN SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-Cell OPTIONAL, -- Need N + blackCellsToRemoveListEUTRAN EUTRA-CellIndexList OPTIONAL, -- Need N + blackCellsToAddModListEUTRAN SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-BlackCell OPTIONAL, -- Need N + eutra-PresenceAntennaPort1 EUTRA-PresenceAntennaPort1, + eutra-Q-OffsetRange EUTRA-Q-OffsetRange OPTIONAL, -- Need R + widebandRSRQ-Meas BOOLEAN, + ... +} + +EUTRA-CellIndexList ::= SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-CellIndex + +EUTRA-CellIndex ::= INTEGER (1..maxCellMeasEUTRA) + + +EUTRA-Cell ::= SEQUENCE { + cellIndexEUTRA EUTRA-CellIndex, + physCellId EUTRA-PhysCellId, + cellIndividualOffset EUTRA-Q-OffsetRange +} + + +EUTRA-BlackCell ::= SEQUENCE { + cellIndexEUTRA EUTRA-CellIndex, + physCellIdRange EUTRA-PhysCellIdRange +} + +-- TAG-MEASOBJECTEUTRA-STOP +-- TAG-MEASOBJECTID-START + +MeasObjectId ::= INTEGER (1..maxNrofObjectId) + +-- TAG-MEASOBJECTID-STOP +-- TAG-MEASOBJECTNR-START + +MeasObjectNR ::= SEQUENCE { + ssbFrequency ARFCN-ValueNR OPTIONAL, -- Cond SSBorAssociatedSSB + ssbSubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond SSBorAssociatedSSB + smtc1 SSB-MTC OPTIONAL, -- Cond SSBorAssociatedSSB + smtc2 SSB-MTC2 OPTIONAL, -- Cond IntraFreqConnected + refFreqCSI-RS ARFCN-ValueNR OPTIONAL, -- Cond CSI-RS + referenceSignalConfig ReferenceSignalConfig, + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need R + absThreshCSI-RS-Consolidation ThresholdNR OPTIONAL, -- Need R + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need R + nrofCSI-RS-ResourcesToAverage INTEGER (2..maxNrofCSI-RS-ResourcesToAverage) OPTIONAL, -- Need R + quantityConfigIndex INTEGER (1..maxNrofQuantityConfig), + offsetMO Q-OffsetRangeList, + cellsToRemoveList PCI-List OPTIONAL, -- Need N + cellsToAddModList CellsToAddModList OPTIONAL, -- Need N + blackCellsToRemoveList PCI-RangeIndexList OPTIONAL, -- Need N + blackCellsToAddModList SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeElement OPTIONAL, -- Need N + whiteCellsToRemoveList PCI-RangeIndexList OPTIONAL, -- Need N + whiteCellsToAddModList SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeElement OPTIONAL, -- Need N + ..., + [[ + freqBandIndicatorNR FreqBandIndicatorNR OPTIONAL, -- Need R + measCycleSCell ENUMERATED {sf160, sf256, sf320, sf512, sf640, sf1024, sf1280} OPTIONAL -- Need R + ]], + [[ + smtc3list-r16 SSB-MTC3List-r16 OPTIONAL, -- Need R + rmtc-Config-r16 SetupRelease {RMTC-Config-r16} OPTIONAL, -- Need M + t312-r16 SetupRelease { T312-r16 } OPTIONAL -- Need M + ]] +} + +SSB-MTC3List-r16::= SEQUENCE (SIZE(1..4)) OF SSB-MTC3-r16 + +T312-r16 ::= ENUMERATED { ms0, ms50, ms100, ms200, ms300, ms400, ms500, ms1000} + +ReferenceSignalConfig::= SEQUENCE { + ssb-ConfigMobility SSB-ConfigMobility OPTIONAL, -- Need M + csi-rs-ResourceConfigMobility SetupRelease { CSI-RS-ResourceConfigMobility } OPTIONAL -- Need M +} + +SSB-ConfigMobility::= SEQUENCE { + ssb-ToMeasure SetupRelease { SSB-ToMeasure } OPTIONAL, -- Need M + deriveSSB-IndexFromCell BOOLEAN, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, -- Need M + ..., + [[ + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + ssb-PositionQCL-CellsToAddModList-r16 SSB-PositionQCL-CellsToAddModList-r16 OPTIONAL, -- Need N + ssb-PositionQCL-CellsToRemoveList-r16 PCI-List OPTIONAL -- Need N + ]] +} + +Q-OffsetRangeList ::= SEQUENCE { + rsrpOffsetSSB Q-OffsetRange DEFAULT dB0, + rsrqOffsetSSB Q-OffsetRange DEFAULT dB0, + sinrOffsetSSB Q-OffsetRange DEFAULT dB0, + rsrpOffsetCSI-RS Q-OffsetRange DEFAULT dB0, + rsrqOffsetCSI-RS Q-OffsetRange DEFAULT dB0, + sinrOffsetCSI-RS Q-OffsetRange DEFAULT dB0 +} + + +ThresholdNR ::= SEQUENCE{ + thresholdRSRP RSRP-Range OPTIONAL, -- Need R + thresholdRSRQ RSRQ-Range OPTIONAL, -- Need R + thresholdSINR SINR-Range OPTIONAL -- Need R +} + +CellsToAddModList ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF CellsToAddMod + +CellsToAddMod ::= SEQUENCE { + physCellId PhysCellId, + cellIndividualOffset Q-OffsetRangeList +} + +RMTC-Config-r16 ::= SEQUENCE { + rmtc-Periodicity-r16 ENUMERATED {ms40, ms80, ms160, ms320, ms640}, + rmtc-SubframeOffset-r16 INTEGER(0..639) OPTIONAL, -- Need M + measDurationSymbols-r16 ENUMERATED {sym1, sym14or12, sym28or24, sym42or36, sym70or60}, + rmtc-Frequency-r16 ARFCN-ValueNR, + ref-SCS-CP-r16 ENUMERATED {kHz15, kHz30, kHz60-NCP, kHz60-ECP}, + ... +} + +SSB-PositionQCL-CellsToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF SSB-PositionQCL-CellsToAddMod-r16 + +SSB-PositionQCL-CellsToAddMod-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 +} + +-- TAG-MEASOBJECTNR-STOP +-- TAG-MEASOBJECTNR-SL-START + +MeasObjectNR-SL-r16 ::= SEQUENCE { + tx-PoolMeasToRemoveList-r16 Tx-PoolMeasList-r16 OPTIONAL, -- Need N + tx-PoolMeasToAddModList-r16 Tx-PoolMeasList-r16 OPTIONAL -- Need N +} + +Tx-PoolMeasList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-PoolToMeasureNR-r16)) OF SL-ResourcePoolID-r16 + +-- TAG-MEASOBJECTNR-SL-STOP +-- TAG-MEASOBJECTTOADDMODLIST-START + +MeasObjectToAddModList ::= SEQUENCE (SIZE (1..maxNrofObjectId)) OF MeasObjectToAddMod + +MeasObjectToAddMod ::= SEQUENCE { + measObjectId MeasObjectId, + measObject CHOICE { + measObjectNR MeasObjectNR, + ..., + measObjectEUTRA MeasObjectEUTRA, + measObjectUTRA-FDD-r16 MeasObjectUTRA-FDD-r16, + measObjectNR-SL-r16 MeasObjectNR-SL-r16, + measObjectCLI-r16 MeasObjectCLI-r16 + } +} + +-- TAG-MEASOBJECTTOADDMODLIST-STOP +-- TAG-MEASOBJECTUTRA-FDD-START + +MeasObjectUTRA-FDD-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueUTRA-FDD-r16, + utra-FDD-Q-OffsetRange-r16 UTRA-FDD-Q-OffsetRange-r16 OPTIONAL, -- Need R + cellsToRemoveList-r16 UTRA-FDD-CellIndexList-r16 OPTIONAL, -- Need N + cellsToAddModList-r16 CellsToAddModListUTRA-FDD-r16 OPTIONAL, -- Need N + ... +} + +CellsToAddModListUTRA-FDD-r16 ::= SEQUENCE (SIZE (1..maxCellMeasUTRA-FDD-r16)) OF CellsToAddModUTRA-FDD-r16 + +CellsToAddModUTRA-FDD-r16 ::= SEQUENCE { + cellIndexUTRA-FDD-r16 UTRA-FDD-CellIndex-r16, + physCellId-r16 PhysCellIdUTRA-FDD-r16 +} + +UTRA-FDD-CellIndexList-r16 ::= SEQUENCE (SIZE (1..maxCellMeasUTRA-FDD-r16)) OF UTRA-FDD-CellIndex-r16 + +UTRA-FDD-CellIndex-r16 ::= INTEGER (1..maxCellMeasUTRA-FDD-r16) + +-- TAG-MEASOBJECTUTRA-FDD-STOP +-- TAG-MEASRESULTCELLLISTSFTD-NR-START + +MeasResultCellListSFTD-NR ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF MeasResultCellSFTD-NR + +MeasResultCellSFTD-NR ::= SEQUENCE { + physCellId PhysCellId, + sfn-OffsetResult INTEGER (0..1023), + frameBoundaryOffsetResult INTEGER (-30720..30719), + rsrp-Result RSRP-Range OPTIONAL +} + +-- TAG-MEASRESULTCELLLISTSFTD-NR-STOP +-- TAG-MEASRESULTCELLLISTSFTD-EUTRA-START + +MeasResultCellListSFTD-EUTRA ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF MeasResultSFTD-EUTRA + +MeasResultSFTD-EUTRA ::= SEQUENCE { + eutra-PhysCellId EUTRA-PhysCellId, + sfn-OffsetResult INTEGER (0..1023), + frameBoundaryOffsetResult INTEGER (-30720..30719), + rsrp-Result RSRP-Range OPTIONAL +} + +-- TAG-MEASRESULTCELLLISTSFTD-EUTRA-STOP +-- TAG-MEASRESULTS-START + +MeasResults ::= SEQUENCE { + measId MeasId, + measResultServingMOList MeasResultServMOList, + measResultNeighCells CHOICE { + measResultListNR MeasResultListNR, + ..., + measResultListEUTRA MeasResultListEUTRA, + measResultListUTRA-FDD-r16 MeasResultListUTRA-FDD-r16 + } OPTIONAL, + ..., + [[ + measResultServFreqListEUTRA-SCG MeasResultServFreqListEUTRA-SCG OPTIONAL, + measResultServFreqListNR-SCG MeasResultServFreqListNR-SCG OPTIONAL, + measResultSFTD-EUTRA MeasResultSFTD-EUTRA OPTIONAL, + measResultSFTD-NR MeasResultCellSFTD-NR OPTIONAL + ]], + [[ + measResultCellListSFTD-NR MeasResultCellListSFTD-NR OPTIONAL + ]], + [[ + measResultForRSSI-r16 MeasResultForRSSI-r16 OPTIONAL, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + ul-PDCP-DelayValueResultList-r16 UL-PDCP-DelayValueResultList-r16 OPTIONAL, + measResultsSL-r16 MeasResultsSL-r16 OPTIONAL, + measResultCLI-r16 MeasResultCLI-r16 OPTIONAL + ]] + + +} + +MeasResultServMOList ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF MeasResultServMO + +MeasResultServMO ::= SEQUENCE { + servCellId ServCellIndex, + measResultServingCell MeasResultNR, + measResultBestNeighCell MeasResultNR OPTIONAL, + ... +} + +MeasResultListNR ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultNR + +MeasResultNR ::= SEQUENCE { + physCellId PhysCellId OPTIONAL, + measResult SEQUENCE { + cellResults SEQUENCE{ + resultsSSB-Cell MeasQuantityResults OPTIONAL, + resultsCSI-RS-Cell MeasQuantityResults OPTIONAL + }, + rsIndexResults SEQUENCE{ + resultsSSB-Indexes ResultsPerSSB-IndexList OPTIONAL, + resultsCSI-RS-Indexes ResultsPerCSI-RS-IndexList OPTIONAL + } OPTIONAL + }, + ..., + [[ + cgi-Info CGI-InfoNR OPTIONAL + ]] +} + +MeasResultListEUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultEUTRA + +MeasResultEUTRA ::= SEQUENCE { + eutra-PhysCellId PhysCellId, + measResult MeasQuantityResultsEUTRA, + + cgi-Info CGI-InfoEUTRA OPTIONAL, + ... +} + +MultiBandInfoListEUTRA ::= SEQUENCE (SIZE (1..maxMultiBands)) OF FreqBandIndicatorEUTRA + +MeasQuantityResults ::= SEQUENCE { + rsrp RSRP-Range OPTIONAL, + rsrq RSRQ-Range OPTIONAL, + sinr SINR-Range OPTIONAL +} + +MeasQuantityResultsEUTRA ::= SEQUENCE { + rsrp RSRP-RangeEUTRA OPTIONAL, + rsrq RSRQ-RangeEUTRA OPTIONAL, + sinr SINR-RangeEUTRA OPTIONAL +} + +ResultsPerSSB-IndexList::= SEQUENCE (SIZE (1..maxNrofIndexesToReport2)) OF ResultsPerSSB-Index + +ResultsPerSSB-Index ::= SEQUENCE { + ssb-Index SSB-Index, + ssb-Results MeasQuantityResults OPTIONAL +} + +ResultsPerCSI-RS-IndexList::= SEQUENCE (SIZE (1..maxNrofIndexesToReport2)) OF ResultsPerCSI-RS-Index + +ResultsPerCSI-RS-Index ::= SEQUENCE { + csi-RS-Index CSI-RS-Index, + csi-RS-Results MeasQuantityResults OPTIONAL +} +MeasResultServFreqListEUTRA-SCG ::= SEQUENCE (SIZE (1..maxNrofServingCellsEUTRA)) OF MeasResult2EUTRA + +MeasResultServFreqListNR-SCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF MeasResult2NR + +MeasResultListUTRA-FDD-r16 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultUTRA-FDD-r16 + +MeasResultUTRA-FDD-r16 ::= SEQUENCE { + physCellId-r16 PhysCellIdUTRA-FDD-r16, + measResult-r16 SEQUENCE { + utra-FDD-RSCP-r16 INTEGER (-5..91) OPTIONAL, + utra-FDD-EcN0-r16 INTEGER (0..49) OPTIONAL + } +} + +MeasResultForRSSI-r16 ::= SEQUENCE { + rssi-Result-r16 RSSI-Range-r16, + channelOccupancy-r16 INTEGER (0..100) +} + +MeasResultCLI-r16 ::= SEQUENCE { + measResultListSRS-RSRP-r16 MeasResultListSRS-RSRP-r16 OPTIONAL, + measResultListCLI-RSSI-r16 MeasResultListCLI-RSSI-r16 OPTIONAL +} + +MeasResultListSRS-RSRP-r16 ::= SEQUENCE (SIZE (1.. maxCLI-Report-r16)) OF MeasResultSRS-RSRP-r16 + +MeasResultSRS-RSRP-r16 ::= SEQUENCE { + srs-ResourceId-r16 SRS-ResourceId, + srs-RSRP-Result-r16 SRS-RSRP-Range-r16 +} + +MeasResultListCLI-RSSI-r16 ::= SEQUENCE (SIZE (1.. maxCLI-Report-r16)) OF MeasResultCLI-RSSI-r16 + +MeasResultCLI-RSSI-r16 ::= SEQUENCE { + rssi-ResourceId-r16 RSSI-ResourceId-r16, + cli-RSSI-Result-r16 CLI-RSSI-Range-r16 +} + +UL-PDCP-DelayValueResultList-r16 ::= SEQUENCE (SIZE (1..maxDRB)) OF UL-PDCP-DelayValueResult-r16 + +UL-PDCP-DelayValueResult-r16 ::= SEQUENCE { + drb-Id-r16 DRB-Identity, + averageDelay-r16 INTEGER (0..10000), + ... +} + +-- TAG-MEASRESULTS-STOP +-- TAG-MEASRESULT2EUTRA-START + +MeasResult2EUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + measResultServingCell MeasResultEUTRA OPTIONAL, + measResultBestNeighCell MeasResultEUTRA OPTIONAL, + ... +} + +-- TAG-MEASRESULT2EUTRA-STOP +-- TAG-MEASRESULT2NR-START + +MeasResult2NR ::= SEQUENCE { + ssbFrequency ARFCN-ValueNR OPTIONAL, + refFreqCSI-RS ARFCN-ValueNR OPTIONAL, + measResultServingCell MeasResultNR OPTIONAL, + measResultNeighCellListNR MeasResultListNR OPTIONAL, + ... +} + +-- TAG-MEASRESULT2NR-STOP +-- TAG-MEASRESULTIDLEEUTRA-START + +MeasResultIdleEUTRA-r16 ::= SEQUENCE { + measResultsPerCarrierListIdleEUTRA-r16 SEQUENCE (SIZE (1.. maxFreqIdle-r16)) OF MeasResultsPerCarrierIdleEUTRA-r16, + ... +} + +MeasResultsPerCarrierIdleEUTRA-r16 ::= SEQUENCE { + carrierFreqEUTRA-r16 ARFCN-ValueEUTRA, + measResultsPerCellListIdleEUTRA-r16 SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF MeasResultsPerCellIdleEUTRA-r16, + ... +} + +MeasResultsPerCellIdleEUTRA-r16 ::= SEQUENCE { + eutra-PhysCellId-r16 EUTRA-PhysCellId, + measIdleResultEUTRA-r16 SEQUENCE { + rsrp-ResultEUTRA-r16 RSRP-RangeEUTRA OPTIONAL, + rsrq-ResultEUTRA-r16 RSRQ-RangeEUTRA-r16 OPTIONAL + }, + ... +} + +-- TAG-MEASRESULTIDLEEUTRA-STOP +-- TAG-MEASRESULTIDLENR-START + +MeasResultIdleNR-r16 ::= SEQUENCE { + measResultServingCell-r16 SEQUENCE { + rsrp-Result-r16 RSRP-Range OPTIONAL, + rsrq-Result-r16 RSRQ-Range OPTIONAL, + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList-r16 OPTIONAL + }, + measResultsPerCarrierListIdleNR-r16 SEQUENCE (SIZE (1.. maxFreqIdle-r16)) OF MeasResultsPerCarrierIdleNR-r16 OPTIONAL, + ... +} + +MeasResultsPerCarrierIdleNR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + measResultsPerCellListIdleNR-r16 SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF MeasResultsPerCellIdleNR-r16, + ... +} + +MeasResultsPerCellIdleNR-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + measIdleResultNR-r16 SEQUENCE { + rsrp-Result-r16 RSRP-Range OPTIONAL, + rsrq-Result-r16 RSRQ-Range OPTIONAL, + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList-r16 OPTIONAL + }, + ... +} + +ResultsPerSSB-IndexList-r16 ::= SEQUENCE (SIZE (1.. maxNrofIndexesToReport)) OF ResultsPerSSB-IndexIdle-r16 + +ResultsPerSSB-IndexIdle-r16 ::= SEQUENCE { + ssb-Index-r16 SSB-Index, + ssb-Results-r16 SEQUENCE { + ssb-RSRP-Result-r16 RSRP-Range OPTIONAL, + ssb-RSRQ-Result-r16 RSRQ-Range OPTIONAL + } OPTIONAL +} + +-- TAG-MEASRESULTIDLENR-STOP +-- TAG-MEASRESULTSCG-FAILURE-START + +MeasResultSCG-Failure ::= SEQUENCE { + measResultPerMOList MeasResultList2NR, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL + ]] +} + +MeasResultList2NR ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2NR + +-- TAG-MEASRESULTSCG-FAILURE-STOP +-- TAG-MEASRESULTSSL-START + +MeasResultsSL-r16 ::= SEQUENCE { + measResultsListSL-r16 CHOICE { + measResultNR-SL-r16 MeasResultNR-SL-r16, + ... + }, + ... +} + +MeasResultNR-SL-r16 ::= SEQUENCE { + measResultListCBR-NR-r16 SEQUENCE (SIZE (1.. maxNrofSL-PoolToMeasureNR-r16)) OF MeasResultCBR-NR-r16, + ... +} + +MeasResultCBR-NR-r16 ::= SEQUENCE { + sl-poolReportIdentity-r16 SL-ResourcePoolID-r16, + sl-CBR-ResultsNR-r16 SL-CBR-r16, + ... +} + +-- TAG-MEASRESULTSSL-STOP +-- TAG-MEASTRIGGERQUANTITYEUTRA-START + +MeasTriggerQuantityEUTRA::= CHOICE { + rsrp RSRP-RangeEUTRA, + rsrq RSRQ-RangeEUTRA, + sinr SINR-RangeEUTRA +} + +RSRP-RangeEUTRA ::= INTEGER (0..97) + +RSRQ-RangeEUTRA ::= INTEGER (0..34) + +SINR-RangeEUTRA ::= INTEGER (0..127) + +-- TAG-MEASTRIGGERQUANTITYEUTRA-STOP +-- TAG-MOBILITYSTATEPARAMETERS-START + +MobilityStateParameters ::= SEQUENCE{ + t-Evaluation ENUMERATED { + s30, s60, s120, s180, s240, spare3, spare2, spare1}, + t-HystNormal ENUMERATED { + s30, s60, s120, s180, s240, spare3, spare2, spare1}, + n-CellChangeMedium INTEGER (1..16), + n-CellChangeHigh INTEGER (1..16) +} + +-- TAG-MOBILITYSTATEPARAMETERS-STOP +-- TAG-MSGACONFIGCOMMON-START + +MsgA-ConfigCommon-r16 ::= SEQUENCE { + rach-ConfigCommonTwoStepRA-r16 RACH-ConfigCommonTwoStepRA-r16, + msgA-PUSCH-Config-r16 MsgA-PUSCH-Config-r16 OPTIONAL --Cond InitialBWPConfig +} +-- TAG-MSGACONFIGCOMMON-STOP +-- TAG-MSGA-PUSCH-CONFIG-START + +MsgA-PUSCH-Config-r16 ::= SEQUENCE { + msgA-PUSCH-ResourceGroupA-r16 MsgA-PUSCH-Resource-r16 OPTIONAL, -- Cond InitialBWPConfig + msgA-PUSCH-ResourceGroupB-r16 MsgA-PUSCH-Resource-r16 OPTIONAL, -- Cond GroupBConfigured + msgA-TransformPrecoder-r16 ENUMERATED {enabled, disabled} OPTIONAL, -- Need R + msgA-DataScramblingIndex-r16 INTEGER (0..1023) OPTIONAL, -- Need S + msgA-DeltaPreamble-r16 INTEGER (-1..6) OPTIONAL -- Need R +} + +MsgA-PUSCH-Resource-r16 ::= SEQUENCE { + msgA-MCS-r16 INTEGER (0..15), + nrofSlotsMsgA-PUSCH-r16 INTEGER (1..4), + nrofMsgA-PO-PerSlot-r16 ENUMERATED {one, two, three, six}, + msgA-PUSCH-TimeDomainOffset-r16 INTEGER (1..32), + msgA-PUSCH-TimeDomainAllocation-r16 INTEGER (1..maxNrofUL-Allocations) OPTIONAL, -- Need S + startSymbolAndLengthMsgA-PO-r16 INTEGER (0..127) OPTIONAL, -- Need S + mappingTypeMsgA-PUSCH-r16 ENUMERATED {typeA, typeB} OPTIONAL, -- Need S + guardPeriodMsgA-PUSCH-r16 INTEGER (0..3) OPTIONAL, -- Need R + guardBandMsgA-PUSCH-r16 INTEGER (0..1), + frequencyStartMsgA-PUSCH-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1), + nrofPRBs-PerMsgA-PO-r16 INTEGER (1..32), + nrofMsgA-PO-FDM-r16 ENUMERATED {one, two, four, eight}, + msgA-IntraSlotFrequencyHopping-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + msgA-HoppingBits-r16 BIT STRING (SIZE(2)) OPTIONAL, -- Cond FreqHopConfigured + msgA-DMRS-Config-r16 MsgA-DMRS-Config-r16, + nrofDMRS-Sequences-r16 INTEGER (1..2), + msgA-Alpha-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, + alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need S + interlaceIndexFirstPO-MsgA-PUSCH-r16 INTEGER (1..10) OPTIONAL, -- Need R + nrofInterlacesPerMsgA-PO-r16 INTEGER (1..10) OPTIONAL, -- Need R + ... +} + +MsgA-DMRS-Config-r16 ::= SEQUENCE { + msgA-DMRS-AdditionalPosition-r16 ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + msgA-MaxLength-r16 ENUMERATED {len2} OPTIONAL, -- Need S + msgA-PUSCH-DMRS-CDM-Group-r16 INTEGER (0..1) OPTIONAL, -- Need S + msgA-PUSCH-NrofPorts-r16 INTEGER (0..1) OPTIONAL, -- Need S + msgA-ScramblingID0-r16 INTEGER (0..65535) OPTIONAL, -- Need S + msgA-ScramblingID1-r16 INTEGER (0..65535) OPTIONAL -- Need S +} + +-- TAG-MSGA-PUSCH-CONFIG-STOP +-- TAG-MULTIFREQUENCYBANDLISTNR-START + +MultiFrequencyBandListNR ::= SEQUENCE (SIZE (1..maxNrofMultiBands)) OF FreqBandIndicatorNR + +-- TAG-MULTIFREQUENCYBANDLISTNR-STOP +-- TAG-MULTIFREQUENCYBANDLISTNR-SIB-START + +MultiFrequencyBandListNR-SIB ::= SEQUENCE (SIZE (1.. maxNrofMultiBands)) OF NR-MultiBandInfo + +NR-MultiBandInfo ::= SEQUENCE { + freqBandIndicatorNR FreqBandIndicatorNR OPTIONAL, -- Cond OptULNotSIB2 + nr-NS-PmaxList NR-NS-PmaxList OPTIONAL -- Need S +} + +-- TAG-MULTIFREQUENCYBANDLISTNR-SIB-STOP +-- TAG-NeedForGapsConfigNR-START + +NeedForGapsConfigNR-r16 ::= SEQUENCE { + requestedTargetBandFilterNR-r16 SEQUENCE (SIZE (1..maxBands)) OF FreqBandIndicatorNR OPTIONAL -- Need R +} + +-- TAG-NeedForGapsConfigNR-STOP +-- TAG-NeedForGapsInfoNR-START + +NeedForGapsInfoNR-r16 ::= SEQUENCE { + intraFreq-needForGap-r16 NeedForGapsIntraFreqlist-r16, + interFreq-needForGap-r16 NeedForGapsBandlistNR-r16 +} + +NeedForGapsIntraFreqlist-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCells)) OF NeedForGapsIntraFreq-r16 + +NeedForGapsBandlistNR-r16 ::= SEQUENCE (SIZE (1..maxBands)) OF NeedForGapsNR-r16 + +NeedForGapsIntraFreq-r16 ::= SEQUENCE { + servCellId-r16 ServCellIndex, + gapIndicationIntra-r16 ENUMERATED {gap, no-gap} +} + +NeedForGapsNR-r16 ::= SEQUENCE { + bandNR-r16 FreqBandIndicatorNR, + gapIndication-r16 ENUMERATED {gap, no-gap} +} + +-- TAG-NeedForGapsInfoNR-STOP +-- TAG-NEXTHOPCHAININGCOUNT-START + +NextHopChainingCount ::= INTEGER (0..7) + +-- TAG-NEXTHOPCHAININGCOUNT-STOP +-- TAG-NG-5G-S-TMSI-START + +NG-5G-S-TMSI ::= BIT STRING (SIZE (48)) + +-- TAG-NG-5G-S-TMSI-STOP +-- TAG-NPN-IDENTITY-START + +NPN-Identity-r16 ::= CHOICE { + pni-npn-r16 SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + cag-IdentityList-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF CAG-IdentityInfo-r16 + }, + snpn-r16 SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + nid-List-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF NID-r16 + } +} + +CAG-IdentityInfo-r16 ::= SEQUENCE { + cag-Identity-r16 BIT STRING (SIZE (32)), + manualCAGselectionAllowed-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +NID-r16 ::= BIT STRING (SIZE (44)) + +-- TAG-NPN-IDENTITY-STOP +-- TAG-NPN-IDENTITYINFOLIST-START + +NPN-IdentityInfoList-r16 ::= SEQUENCE (SIZE (1..maxNPN-r16)) OF NPN-IdentityInfo-r16 + + +NPN-IdentityInfo-r16 ::= SEQUENCE { + npn-IdentityList-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF NPN-Identity-r16, + trackingAreaCode-r16 TrackingAreaCode, + ranac-r16 RAN-AreaCode OPTIONAL, -- Need R + cellIdentity-r16 CellIdentity, + cellReservedForOperatorUse-r16 ENUMERATED {reserved, notReserved}, + iab-Support-r16 ENUMERATED {true} OPTIONAL, -- Need S + ... +} + +-- TAG-NPN-IDENTITYINFOLIST-STOP +-- TAG-NR-NS-PMAXLIST-START + +NR-NS-PmaxList ::= SEQUENCE (SIZE (1..maxNR-NS-Pmax)) OF NR-NS-PmaxValue + +NR-NS-PmaxValue ::= SEQUENCE { + additionalPmax P-Max OPTIONAL, -- Need N + additionalSpectrumEmission AdditionalSpectrumEmission +} + +-- TAG-NR-NS-PMAXLIST-STOP +-- TAG-NZP-CSI-RS-RESOURCE-START + +NZP-CSI-RS-Resource ::= SEQUENCE { + nzp-CSI-RS-ResourceId NZP-CSI-RS-ResourceId, + resourceMapping CSI-RS-ResourceMapping, + powerControlOffset INTEGER (-8..15), + powerControlOffsetSS ENUMERATED{db-3, db0, db3, db6} OPTIONAL, -- Need R + scramblingID ScramblingId, + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, -- Cond PeriodicOrSemiPersistent + qcl-InfoPeriodicCSI-RS TCI-StateId OPTIONAL, -- Cond Periodic + ... +} + +-- TAG-NZP-CSI-RS-RESOURCE-STOP +-- TAG-NZP-CSI-RS-RESOURCEID-START + +NZP-CSI-RS-ResourceId ::= INTEGER (0..maxNrofNZP-CSI-RS-Resources-1) + +-- TAG-NZP-CSI-RS-RESOURCEID-STOP +-- TAG-NZP-CSI-RS-RESOURCESET-START +NZP-CSI-RS-ResourceSet ::= SEQUENCE { + nzp-CSI-ResourceSetId NZP-CSI-RS-ResourceSetId, + nzp-CSI-RS-Resources SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourcesPerSet)) OF NZP-CSI-RS-ResourceId, + repetition ENUMERATED { on, off } OPTIONAL, -- Need S + aperiodicTriggeringOffset INTEGER(0..6) OPTIONAL, -- Need S + trs-Info ENUMERATED {true} OPTIONAL, -- Need R + ..., + [[ + aperiodicTriggeringOffset-r16 INTEGER(0..31) OPTIONAL -- Need S + ]] +} + +-- TAG-NZP-CSI-RS-RESOURCESET-STOP +-- TAG-NZP-CSI-RS-RESOURCESETID-START + +NZP-CSI-RS-ResourceSetId ::= INTEGER (0..maxNrofNZP-CSI-RS-ResourceSets-1) + +-- TAG-NZP-CSI-RS-RESOURCESETID-STOP +-- TAG-P-MAX-START + +P-Max ::= INTEGER (-30..33) + +-- TAG-P-MAX-STOP +-- TAG-PCI-LIST-START + +PCI-List ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF PhysCellId + +-- TAG-PCI-LIST-STOP +-- TAG-PCI-RANGE-START + +PCI-Range ::= SEQUENCE { + start PhysCellId, + range ENUMERATED {n4, n8, n12, n16, n24, n32, n48, n64, n84, + n96, n128, n168, n252, n504, n1008,spare1} OPTIONAL -- Need S +} + +-- TAG-PCI-RANGE-STOP +-- TAG-PCI-RANGEELEMENT-START + +PCI-RangeElement ::= SEQUENCE { + pci-RangeIndex PCI-RangeIndex, + pci-Range PCI-Range +} + +-- TAG-PCI-RANGEELEMENT-STOP +-- TAG-PCI-RANGEINDEX-START + +PCI-RangeIndex ::= INTEGER (1..maxNrofPCI-Ranges) + +-- TAG-PCI-RANGEINDEX-STOP +-- TAG-PCI-RANGEINDEXLIST-START + +PCI-RangeIndexList ::= SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeIndex + +-- TAG-PCI-RANGEINDEXLIST-STOP +-- TAG-PDCCH-CONFIG-START + +PDCCH-Config ::= SEQUENCE { + controlResourceSetToAddModList SEQUENCE(SIZE (1..3)) OF ControlResourceSet OPTIONAL, -- Need N + controlResourceSetToReleaseList SEQUENCE(SIZE (1..3)) OF ControlResourceSetId OPTIONAL, -- Need N + searchSpacesToAddModList SEQUENCE(SIZE (1..10)) OF SearchSpace OPTIONAL, -- Need N + searchSpacesToReleaseList SEQUENCE(SIZE (1..10)) OF SearchSpaceId OPTIONAL, -- Need N + downlinkPreemption SetupRelease { DownlinkPreemption } OPTIONAL, -- Need M + tpc-PUSCH SetupRelease { PUSCH-TPC-CommandConfig } OPTIONAL, -- Need M + tpc-PUCCH SetupRelease { PUCCH-TPC-CommandConfig } OPTIONAL, -- Need M + tpc-SRS SetupRelease { SRS-TPC-CommandConfig} OPTIONAL, -- Need M + ..., + [[ + controlResourceSetToAddModListSizeExt-v1610 SEQUENCE (SIZE (1..2)) OF ControlResourceSet OPTIONAL, -- Need N + controlResourceSetToReleaseListSizeExt-r16 SEQUENCE (SIZE (1..5)) OF ControlResourceSetId-r16 OPTIONAL, -- Need N + searchSpacesToAddModListExt-r16 SEQUENCE(SIZE (1..10)) OF SearchSpaceExt-r16 OPTIONAL, -- Need N + uplinkCancellation-r16 SetupRelease { UplinkCancellation-r16 } OPTIONAL, -- Need M + monitoringCapabilityConfig-r16 ENUMERATED { r15monitoringcapability,r16monitoringcapability } OPTIONAL, -- Need M + searchSpaceSwitchConfig-r16 SearchSpaceSwitchConfig-r16 OPTIONAL -- Need R + ]] +} + +SearchSpaceSwitchConfig-r16 ::= SEQUENCE { + cellGroupsForSwitchList-r16 SEQUENCE(SIZE (1..4)) OF CellGroupForSwitch-r16 OPTIONAL, -- Need R + searchSpaceSwitchDelay-r16 INTEGER (10..52) OPTIONAL -- Need R +} + +CellGroupForSwitch-r16 ::= SEQUENCE(SIZE (1..16)) OF ServCellIndex + +-- TAG-PDCCH-CONFIG-STOP +-- TAG-PDCCH-CONFIGCOMMON-START + +PDCCH-ConfigCommon ::= SEQUENCE { + controlResourceSetZero ControlResourceSetZero OPTIONAL, -- Cond InitialBWP-Only + commonControlResourceSet ControlResourceSet OPTIONAL, -- Need R + searchSpaceZero SearchSpaceZero OPTIONAL, -- Cond InitialBWP-Only + commonSearchSpaceList SEQUENCE (SIZE(1..4)) OF SearchSpace OPTIONAL, -- Need R + searchSpaceSIB1 SearchSpaceId OPTIONAL, -- Need S + searchSpaceOtherSystemInformation SearchSpaceId OPTIONAL, -- Need S + pagingSearchSpace SearchSpaceId OPTIONAL, -- Need S + ra-SearchSpace SearchSpaceId OPTIONAL, -- Need S + ..., + [[ + firstPDCCH-MonitoringOccasionOfPO CHOICE { + sCS15KHZoneT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..139), + sCS30KHZoneT-SCS15KHZhalfT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..279), + sCS60KHZoneT-SCS30KHZhalfT-SCS15KHZquarterT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..559), + sCS120KHZoneT-SCS60KHZhalfT-SCS30KHZquarterT-SCS15KHZoneEighthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..1119), + sCS120KHZhalfT-SCS60KHZquarterT-SCS30KHZoneEighthT-SCS15KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..2239), + sCS120KHZquarterT-SCS60KHZoneEighthT-SCS30KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..4479), + sCS120KHZoneEighthT-SCS60KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..8959), + sCS120KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..17919) + } OPTIONAL -- Cond OtherBWP + ]], + [[ + commonSearchSpaceListExt-r16 SEQUENCE (SIZE(1..4)) OF SearchSpaceExt-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-PDCCH-CONFIGCOMMON-STOP +-- TAG-PDCCH-CONFIGSIB1-START + +PDCCH-ConfigSIB1 ::= SEQUENCE { + controlResourceSetZero ControlResourceSetZero, + searchSpaceZero SearchSpaceZero +} + +-- TAG-PDCCH-CONFIGSIB1-STOP +-- TAG-PDCCH-SERVINGCELLCONFIG-START + +PDCCH-ServingCellConfig ::= SEQUENCE { + slotFormatIndicator SetupRelease { SlotFormatIndicator } OPTIONAL, -- Need M + ..., + [[ + availabilityIndicator-r16 SetupRelease {AvailabilityIndicator-r16} OPTIONAL, -- Need M + searchSpaceSwitchTimer-r16 INTEGER (1..80) OPTIONAL -- Need R + ]] +} + +-- TAG-PDCCH-SERVINGCELLCONFIG-STOP +-- TAG-PDCP-CONFIG-START + +PDCP-Config ::= SEQUENCE { + drb SEQUENCE { + discardTimer ENUMERATED {ms10, ms20, ms30, ms40, ms50, ms60, ms75, ms100, ms150, ms200, + ms250, ms300, ms500, ms750, ms1500, infinity} OPTIONAL, -- Cond Setup + pdcp-SN-SizeUL ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + pdcp-SN-SizeDL ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + headerCompression CHOICE { + notUsed NULL, + rohc SEQUENCE { + maxCID INTEGER (1..16383) DEFAULT 15, + profiles SEQUENCE { + profile0x0001 BOOLEAN, + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0101 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + drb-ContinueROHC ENUMERATED { true } OPTIONAL -- Need N + }, + uplinkOnlyROHC SEQUENCE { + maxCID INTEGER (1..16383) DEFAULT 15, + profiles SEQUENCE { + profile0x0006 BOOLEAN + }, + drb-ContinueROHC ENUMERATED { true } OPTIONAL -- Need N + }, + ... + }, + integrityProtection ENUMERATED { enabled } OPTIONAL, -- Cond ConnectedTo5GC1 + statusReportRequired ENUMERATED { true } OPTIONAL, -- Cond Rlc-AM-UM + outOfOrderDelivery ENUMERATED { true } OPTIONAL -- Need R + } OPTIONAL, -- Cond DRB + moreThanOneRLC SEQUENCE { + primaryPath SEQUENCE { + cellGroup CellGroupId OPTIONAL, -- Need R + logicalChannel LogicalChannelIdentity OPTIONAL -- Need R + }, + ul-DataSplitThreshold UL-DataSplitThreshold OPTIONAL, -- Cond SplitBearer + pdcp-Duplication BOOLEAN OPTIONAL -- Need R + } OPTIONAL, -- Cond MoreThanOneRLC + + t-Reordering ENUMERATED { + ms0, ms1, ms2, ms4, ms5, ms8, ms10, ms15, ms20, ms30, ms40, + ms50, ms60, ms80, ms100, ms120, ms140, ms160, ms180, ms200, ms220, + ms240, ms260, ms280, ms300, ms500, ms750, ms1000, ms1250, + ms1500, ms1750, ms2000, ms2250, ms2500, ms2750, + ms3000, spare28, spare27, spare26, spare25, spare24, + spare23, spare22, spare21, spare20, + spare19, spare18, spare17, spare16, spare15, spare14, + spare13, spare12, spare11, spare10, spare09, + spare08, spare07, spare06, spare05, spare04, spare03, + spare02, spare01 } OPTIONAL, -- Need S + ..., + [[ + cipheringDisabled ENUMERATED {true} OPTIONAL -- Cond ConnectedTo5GC + ]], + [[ + discardTimerExt-r16 SetupRelease { DiscardTimerExt-r16 } OPTIONAL, -- Cond DRB2 + moreThanTwoRLC-DRB-r16 SEQUENCE { + splitSecondaryPath-r16 LogicalChannelIdentity OPTIONAL, -- Cond SplitBearer2 + duplicationState-r16 SEQUENCE (SIZE (3)) OF BOOLEAN OPTIONAL -- Need S + } OPTIONAL, -- Cond MoreThanTwoRLC-DRB + ethernetHeaderCompression-r16 SetupRelease { EthernetHeaderCompression-r16 } OPTIONAL -- Need M + ]] +} + +EthernetHeaderCompression-r16 ::= SEQUENCE { + ehc-Common-r16 SEQUENCE { + ehc-CID-Length-r16 ENUMERATED { bits7, bits15 }, + ... + }, + ehc-Downlink-r16 SEQUENCE { + drb-ContinueEHC-DL-r16 ENUMERATED { true } OPTIONAL, -- Need R + ... + } OPTIONAL, -- Need M + ehc-Uplink-r16 SEQUENCE { + maxCID-EHC-UL-r16 INTEGER (1..32767), + drb-ContinueEHC-UL-r16 ENUMERATED { true } OPTIONAL, -- Need R + ... + } OPTIONAL -- Need M +} + +UL-DataSplitThreshold ::= ENUMERATED { + b0, b100, b200, b400, b800, b1600, b3200, b6400, b12800, b25600, b51200, b102400, b204800, + b409600, b819200, b1228800, b1638400, b2457600, b3276800, b4096000, b4915200, b5734400, + b6553600, infinity, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1} + +DiscardTimerExt-r16 ::= ENUMERATED {ms0dot5, ms1, ms2, ms4, ms6, ms8, spare2, spare1} + +-- TAG-PDCP-CONFIG-STOP +-- TAG-PDSCH-CONFIG-START + +PDSCH-Config ::= SEQUENCE { + dataScramblingIdentityPDSCH INTEGER (0..1023) OPTIONAL, -- Need S + dmrs-DownlinkForPDSCH-MappingTypeA SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-DownlinkForPDSCH-MappingTypeB SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + + tci-StatesToAddModList SEQUENCE (SIZE(1..maxNrofTCI-States)) OF TCI-State OPTIONAL, -- Need N + tci-StatesToReleaseList SEQUENCE (SIZE(1..maxNrofTCI-States)) OF TCI-StateId OPTIONAL, -- Need N + vrb-ToPRB-Interleaver ENUMERATED {n2, n4} OPTIONAL, -- Need S + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch}, + pdsch-TimeDomainAllocationList SetupRelease { PDSCH-TimeDomainResourceAllocationList } OPTIONAL, -- Need M + pdsch-AggregationFactor ENUMERATED { n2, n4, n8 } OPTIONAL, -- Need S + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + rateMatchPatternGroup1 RateMatchPatternGroup OPTIONAL, -- Need R + rateMatchPatternGroup2 RateMatchPatternGroup OPTIONAL, -- Need R + + rbg-Size ENUMERATED {config1, config2}, + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + maxNrofCodeWordsScheduledByDCI ENUMERATED {n1, n2} OPTIONAL, -- Need R + + prb-BundlingType CHOICE { + staticBundling SEQUENCE { + bundleSize ENUMERATED { n4, wideband } OPTIONAL -- Need S + }, + dynamicBundling SEQUENCE { + bundleSizeSet1 ENUMERATED { n4, wideband, n2-wideband, n4-wideband } OPTIONAL, -- Need S + bundleSizeSet2 ENUMERATED { n4, wideband } OPTIONAL -- Need S + } + }, + zp-CSI-RS-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-Resources)) OF ZP-CSI-RS-Resource + OPTIONAL, -- Need N + zp-CSI-RS-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-Resources)) OF ZP-CSI-RS-ResourceId + OPTIONAL, -- Need N + aperiodic-ZP-CSI-RS-ResourceSetsToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + aperiodic-ZP-CSI-RS-ResourceSetsToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + sp-ZP-CSI-RS-ResourceSetsToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + sp-ZP-CSI-RS-ResourceSetsToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + p-ZP-CSI-RS-ResourceSet SetupRelease { ZP-CSI-RS-ResourceSet } + OPTIONAL, -- Need M + ..., + [[ + maxMIMO-Layers-r16 SetupRelease { MaxMIMO-LayersDL-r16 } OPTIONAL, -- Need M + minimumSchedulingOffsetK0-r16 SetupRelease { MinSchedulingOffsetK0-Values-r16 } OPTIONAL, -- Need M + + -- Start of the parameters for DCI format 1_2 introduced in V16.1.0 + antennaPortsFieldPresenceDCI-1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + aperiodicZP-CSI-RS-ResourceSetsToAddModListDCI-1-2-r16 SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + aperiodicZP-CSI-RS-ResourceSetsToReleaseListDCI-1-2-r16 SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + dmrs-DownlinkForPDSCH-MappingTypeA-DCI-1-2-r16 SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-DownlinkForPDSCH-MappingTypeB-DCI-1-2-r16 SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-SequenceInitializationDCI-1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + harq-ProcessNumberSizeDCI-1-2-r16 INTEGER (0..4) OPTIONAL, -- Need R + mcs-TableDCI-1-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + numberOfBitsForRV-DCI-1-2-r16 INTEGER (0..2) OPTIONAL, -- Need R + pdsch-TimeDomainAllocationListDCI-1-2-r16 SetupRelease { PDSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + prb-BundlingTypeDCI-1-2-r16 CHOICE { + staticBundling-r16 SEQUENCE { + bundleSize-r16 ENUMERATED { n4, wideband } OPTIONAL -- Need S + }, + dynamicBundling-r16 SEQUENCE { + bundleSizeSet1-r16 ENUMERATED { n4, wideband, n2-wideband, n4-wideband } OPTIONAL, -- Need S + bundleSizeSet2-r16 ENUMERATED { n4, wideband } OPTIONAL -- Need S + } + } OPTIONAL, -- Need R + priorityIndicatorDCI-1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + rateMatchPatternGroup1DCI-1-2-r16 RateMatchPatternGroup OPTIONAL, -- Need R + rateMatchPatternGroup2DCI-1-2-r16 RateMatchPatternGroup OPTIONAL, -- Need R + resourceAllocationType1GranularityDCI-1-2-r16 ENUMERATED {n2,n4,n8,n16} OPTIONAL, -- Need S + vrb-ToPRB-InterleaverDCI-1-2-r16 ENUMERATED {n2, n4} OPTIONAL, -- Need S + referenceOfSLIVDCI-1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + resourceAllocationDCI-1-2-r16 ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch} + OPTIONAL, -- Need M + -- End of the parameters for DCI format 1_2 introduced in V16.1.0 + + priorityIndicatorDCI-1-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + dataScramblingIdentityPDSCH2-r16 INTEGER (0..1023) OPTIONAL, -- Need R + pdsch-TimeDomainAllocationList-r16 SetupRelease { PDSCH-TimeDomainResourceAllocationList-r16 } OPTIONAL, -- Need M + repetitionSchemeConfig-r16 SetupRelease { RepetitionSchemeConfig-r16} OPTIONAL -- Need M + ]], + [[ + repetitionSchemeConfig-v1630 SetupRelease { RepetitionSchemeConfig-v1630} OPTIONAL -- Need M + ]] +} + +RateMatchPatternGroup ::= SEQUENCE (SIZE (1..maxNrofRateMatchPatternsPerGroup)) OF CHOICE { + cellLevel RateMatchPatternId, + bwpLevel RateMatchPatternId +} + +MinSchedulingOffsetK0-Values-r16 ::= SEQUENCE (SIZE (1..maxNrOfMinSchedulingOffsetValues-r16)) OF INTEGER (0..maxK0-SchedulingOffset-r16) + +MaxMIMO-LayersDL-r16 ::= INTEGER (1..8) + +-- TAG-PDSCH-CONFIG-STOP +-- TAG-PDSCH-CONFIGCOMMON-START + +PDSCH-ConfigCommon ::= SEQUENCE { + pdsch-TimeDomainAllocationList PDSCH-TimeDomainResourceAllocationList OPTIONAL, -- Need R + ... +} + +-- TAG-PDSCH-CONFIGCOMMON-STOP +-- TAG-PDSCH-SERVINGCELLCONFIG-START + +PDSCH-ServingCellConfig ::= SEQUENCE { + codeBlockGroupTransmission SetupRelease { PDSCH-CodeBlockGroupTransmission } OPTIONAL, -- Need M + xOverhead ENUMERATED { xOh6, xOh12, xOh18 } OPTIONAL, -- Need S + nrofHARQ-ProcessesForPDSCH ENUMERATED {n2, n4, n6, n10, n12, n16} OPTIONAL, -- Need S + pucch-Cell ServCellIndex OPTIONAL, -- Cond SCellAddOnly + ..., + [[ + maxMIMO-Layers INTEGER (1..8) OPTIONAL, -- Need M + processingType2Enabled BOOLEAN OPTIONAL -- Need M + ]], + [[ + pdsch-CodeBlockGroupTransmissionList-r16 SetupRelease { PDSCH-CodeBlockGroupTransmissionList-r16 } OPTIONAL -- Need M + ]] +} + +PDSCH-CodeBlockGroupTransmission ::= SEQUENCE { + maxCodeBlockGroupsPerTransportBlock ENUMERATED {n2, n4, n6, n8}, + codeBlockGroupFlushIndicator BOOLEAN, + ... +} + +PDSCH-CodeBlockGroupTransmissionList-r16 ::= SEQUENCE (SIZE (1..2)) OF PDSCH-CodeBlockGroupTransmission + +-- TAG-PDSCH-SERVINGCELLCONFIG-STOP +-- TAG-PDSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-START + + +PDSCH-TimeDomainResourceAllocationList ::= SEQUENCE (SIZE(1..maxNrofDL-Allocations)) OF PDSCH-TimeDomainResourceAllocation + +PDSCH-TimeDomainResourceAllocation ::= SEQUENCE { + k0 INTEGER(0..32) OPTIONAL, -- Need S + mappingType ENUMERATED {typeA, typeB}, + startSymbolAndLength INTEGER (0..127) +} + +PDSCH-TimeDomainResourceAllocationList-r16 ::= SEQUENCE (SIZE(1..maxNrofDL-Allocations)) OF PDSCH-TimeDomainResourceAllocation-r16 + +PDSCH-TimeDomainResourceAllocation-r16 ::= SEQUENCE { + k0-r16 INTEGER(0..32) OPTIONAL, -- Need S + mappingType-r16 ENUMERATED {typeA, typeB}, + startSymbolAndLength-r16 INTEGER (0..127), + repetitionNumber-r16 ENUMERATED {n2, n3, n4, n5, n6, n7, n8, n16} OPTIONAL, -- Cond Formats1-0and1-1 + ... +} + +-- TAG-PDSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-STOP +-- TAG-PHR-CONFIG-START + +PHR-Config ::= SEQUENCE { + phr-PeriodicTimer ENUMERATED {sf10, sf20, sf50, sf100, sf200,sf500, sf1000, infinity}, + phr-ProhibitTimer ENUMERATED {sf0, sf10, sf20, sf50, sf100,sf200, sf500, sf1000}, + phr-Tx-PowerFactorChange ENUMERATED {dB1, dB3, dB6, infinity}, + multiplePHR BOOLEAN, + dummy BOOLEAN, + phr-Type2OtherCell BOOLEAN, + phr-ModeOtherCG ENUMERATED {real, virtual}, + ..., + [[ + mpe-Reporting-FR2-r16 SetupRelease { MPE-Config-FR2-r16 } OPTIONAL -- Need M + ]] +} + +MPE-Config-FR2-r16 ::= SEQUENCE { + mpe-ProhibitTimer-r16 ENUMERATED {sf0, sf10, sf20, sf50, sf100, sf200, sf500, sf1000}, + mpe-Threshold-r16 ENUMERATED {dB3, dB6, dB9, dB12} +} + +-- TAG-PHR-CONFIG-STOP +-- TAG-PHYSCELLID-START + +PhysCellId ::= INTEGER (0..1007) + +-- TAG-PHYSCELLID-STOP +-- TAG-PHYSICALCELLGROUPCONFIG-START + +PhysicalCellGroupConfig ::= SEQUENCE { + harq-ACK-SpatialBundlingPUCCH ENUMERATED {true} OPTIONAL, -- Need S + harq-ACK-SpatialBundlingPUSCH ENUMERATED {true} OPTIONAL, -- Need S + p-NR-FR1 P-Max OPTIONAL, -- Need R + pdsch-HARQ-ACK-Codebook ENUMERATED {semiStatic, dynamic}, + tpc-SRS-RNTI RNTI-Value OPTIONAL, -- Need R + tpc-PUCCH-RNTI RNTI-Value OPTIONAL, -- Need R + tpc-PUSCH-RNTI RNTI-Value OPTIONAL, -- Need R + sp-CSI-RNTI RNTI-Value OPTIONAL, -- Need R + cs-RNTI SetupRelease { RNTI-Value } OPTIONAL, -- Need M + ..., + [[ + mcs-C-RNTI RNTI-Value OPTIONAL, -- Need R + p-UE-FR1 P-Max OPTIONAL -- Cond MCG-Only + ]], + [[ + xScale ENUMERATED {dB0, dB6, spare2, spare1} OPTIONAL -- Cond SCG-Only + ]], + [[ + pdcch-BlindDetection SetupRelease { PDCCH-BlindDetection } OPTIONAL -- Need M + ]], + [[ + dcp-Config-r16 SetupRelease { DCP-Config-r16 } OPTIONAL, -- Need M + harq-ACK-SpatialBundlingPUCCH-secondaryPUCCHgroup-r16 ENUMERATED {enabled, disabled} OPTIONAL, -- Cond twoPUCCHgroup + harq-ACK-SpatialBundlingPUSCH-secondaryPUCCHgroup-r16 ENUMERATED {enabled, disabled} OPTIONAL, -- Cond twoPUCCHgroup + pdsch-HARQ-ACK-Codebook-secondaryPUCCHgroup-r16 ENUMERATED {semiStatic, dynamic} OPTIONAL, -- Cond twoPUCCHgroup + p-NR-FR2-r16 P-Max OPTIONAL, -- Need R + p-UE-FR2-r16 P-Max OPTIONAL, -- Cond MCG-Only + nrdc-PCmode-FR1-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, -- Cond MCG-Only + nrdc-PCmode-FR2-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, -- Cond MCG-Only + pdsch-HARQ-ACK-Codebook-r16 ENUMERATED {enhancedDynamic} OPTIONAL, -- Need R + nfi-TotalDAI-Included-r16 ENUMERATED {true} OPTIONAL, -- Need R + ul-TotalDAI-Included-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedback-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedbackNDI-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedbackCBG-r16 ENUMERATED {true} OPTIONAL, -- Need R + downlinkAssignmentIndexDCI-0-2-r16 ENUMERATED { enabled } OPTIONAL, -- Need S + downlinkAssignmentIndexDCI-1-2-r16 ENUMERATED {n1, n2, n4} OPTIONAL, -- Need S + pdsch-HARQ-ACK-CodebookList-r16 SetupRelease {PDSCH-HARQ-ACK-CodebookList-r16} OPTIONAL, -- Need M + ackNackFeedbackMode-r16 ENUMERATED {joint, separate} OPTIONAL, -- Need R + pdcch-BlindDetectionCA-CombIndicator-r16 SetupRelease { PDCCH-BlindDetectionCA-CombIndicator-r16 } OPTIONAL, -- Need M + pdcch-BlindDetection2-r16 SetupRelease { PDCCH-BlindDetection2-r16 } OPTIONAL, -- Need M + pdcch-BlindDetection3-r16 SetupRelease { PDCCH-BlindDetection3-r16 } OPTIONAL, -- Need M + bdFactorR-r16 ENUMERATED {n1} OPTIONAL -- Need R + ]] +} + +PDCCH-BlindDetection ::= INTEGER (1..15) + +DCP-Config-r16 ::= SEQUENCE { + ps-RNTI-r16 RNTI-Value, + ps-Offset-r16 INTEGER (1..120), + sizeDCI-2-6-r16 INTEGER (1..maxDCI-2-6-Size-r16), + ps-PositionDCI-2-6-r16 INTEGER (0..maxDCI-2-6-Size-1-r16), + ps-WakeUp-r16 ENUMERATED {true} OPTIONAL, -- Need S + ps-TransmitPeriodicL1-RSRP-r16 ENUMERATED {true} OPTIONAL, -- Need S + ps-TransmitOtherPeriodicCSI-r16 ENUMERATED {true} OPTIONAL -- Need S +} + +PDSCH-HARQ-ACK-CodebookList-r16 ::= SEQUENCE (SIZE (1..2)) OF ENUMERATED {semiStatic, dynamic} + +PDCCH-BlindDetectionCA-CombIndicator-r16 ::= SEQUENCE { + pdcch-BlindDetectionCA1-r16 INTEGER (1..15), + pdcch-BlindDetectionCA2-r16 INTEGER (1..15) +} + +PDCCH-BlindDetection2-r16 ::= INTEGER (1..15) + +PDCCH-BlindDetection3-r16 ::= INTEGER (1..15) + +-- TAG-PHYSICALCELLGROUPCONFIG-STOP +-- TAG-PLMN-IDENTITY-START + +PLMN-Identity ::= SEQUENCE { + mcc MCC OPTIONAL, -- Cond MCC + mnc MNC +} + +MCC ::= SEQUENCE (SIZE (3)) OF MCC-MNC-Digit + +MNC ::= SEQUENCE (SIZE (2..3)) OF MCC-MNC-Digit + +MCC-MNC-Digit ::= INTEGER (0..9) + +-- TAG-PLMN-IDENTITY-STOP +-- TAG-PLMN-IDENTITYINFOLIST-START + +PLMN-IdentityInfoList ::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-IdentityInfo + +PLMN-IdentityInfo ::= SEQUENCE { + plmn-IdentityList SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity, + trackingAreaCode TrackingAreaCode OPTIONAL, -- Need R + ranac RAN-AreaCode OPTIONAL, -- Need R + cellIdentity CellIdentity, + cellReservedForOperatorUse ENUMERATED {reserved, notReserved}, + ..., + [[ + iab-Support-r16 ENUMERATED {true} OPTIONAL -- Need S + ]] +} +-- TAG-PLMN-IDENTITYINFOLIST-STOP +-- TAG-PLMNIDENTITYLIST2-START + +PLMN-IdentityList2-r16 ::= SEQUENCE (SIZE (1..16)) OF PLMN-Identity + +-- TAG-PLMNIDENTITYLIST2-STOP +-- TAG-PRB-ID-START + +PRB-Id ::= INTEGER (0..maxNrofPhysicalResourceBlocks-1) + +-- TAG-PRB-ID-STOP +-- TAG-PTRS-DOWNLINKCONFIG-START + +PTRS-DownlinkConfig ::= SEQUENCE { + frequencyDensity SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need S + timeDensity SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need S + epre-Ratio INTEGER (0..3) OPTIONAL, -- Need S + resourceElementOffset ENUMERATED { offset01, offset10, offset11 } OPTIONAL, -- Need S + ..., + [[ + maxNrofPorts-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + ]] + +} + +-- TAG-PTRS-DOWNLINKCONFIG-STOP +-- TAG-PTRS-UPLINKCONFIG-START + +PTRS-UplinkConfig ::= SEQUENCE { + transformPrecoderDisabled SEQUENCE { + frequencyDensity SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need S + timeDensity SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need S + maxNrofPorts ENUMERATED {n1, n2}, + resourceElementOffset ENUMERATED {offset01, offset10, offset11 } OPTIONAL, -- Need S + ptrs-Power ENUMERATED {p00, p01, p10, p11} + } OPTIONAL, -- Need R + transformPrecoderEnabled SEQUENCE { + sampleDensity SEQUENCE (SIZE (5)) OF INTEGER (1..276), + timeDensityTransformPrecoding ENUMERATED {d2} OPTIONAL -- Need S + } OPTIONAL, -- Need R + ... +} + +-- TAG-PTRS-UPLINKCONFIG-STOP +-- TAG-PUCCH-CONFIG-START + +PUCCH-Config ::= SEQUENCE { + resourceSetToAddModList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceSets)) OF PUCCH-ResourceSet OPTIONAL, -- Need N + resourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceSets)) OF PUCCH-ResourceSetId OPTIONAL, -- Need N + resourceToAddModList SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-Resource OPTIONAL, -- Need N + resourceToReleaseList SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-ResourceId OPTIONAL, -- Need N + format1 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format2 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format3 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format4 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + schedulingRequestResourceToAddModList SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceConfig + OPTIONAL, -- Need N + schedulingRequestResourceToReleaseList SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceId + OPTIONAL, -- Need N + multi-CSI-PUCCH-ResourceList SEQUENCE (SIZE (1..2)) OF PUCCH-ResourceId OPTIONAL, -- Need M + dl-DataToUL-ACK SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) OPTIONAL, -- Need M + spatialRelationInfoToAddModList SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos)) OF PUCCH-SpatialRelationInfo + OPTIONAL, -- Need N + spatialRelationInfoToReleaseList SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos)) OF PUCCH-SpatialRelationInfoId + OPTIONAL, -- Need N + pucch-PowerControl PUCCH-PowerControl OPTIONAL, -- Need M + ..., + [[ + resourceToAddModListExt-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-ResourceExt-r16 OPTIONAL, -- Need N + dl-DataToUL-ACK-r16 SetupRelease { DL-DataToUL-ACK-r16 } OPTIONAL, -- Need M + ul-AccessConfigListDCI-1-1-r16 SetupRelease { UL-AccessConfigListDCI-1-1-r16 } OPTIONAL, -- Need M + subslotLengthForPUCCH-r16 CHOICE { + normalCP-r16 ENUMERATED {n2,n7}, + extendedCP-r16 ENUMERATED {n2,n6} + } OPTIONAL, -- Need R + dl-DataToUL-ACK-DCI-1-2-r16 SetupRelease { DL-DataToUL-ACK-DCI-1-2-r16} OPTIONAL, -- Need M + numberOfBitsForPUCCH-ResourceIndicatorDCI-1-2-r16 INTEGER (0..3) OPTIONAL, -- Need R + dmrs-UplinkTransformPrecodingPUCCH-r16 ENUMERATED {enabled} OPTIONAL, -- Cond PI2-BPSK + spatialRelationInfoToAddModListSizeExt-v1610 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfosDiff-r16)) OF PUCCH-SpatialRelationInfo + OPTIONAL, -- Need N + spatialRelationInfoToReleaseListSizeExt-v1610 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfosDiff-r16)) OF PUCCH-SpatialRelationInfoId + OPTIONAL, -- Need N + spatialRelationInfoToAddModListExt-v1610 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos-r16)) OF PUCCH-SpatialRelationInfoExt-r16 + OPTIONAL, -- Need N + spatialRelationInfoToReleaseListExt-v1610 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos-r16)) OF + PUCCH-SpatialRelationInfoId-r16 OPTIONAL, -- Need N + resourceGroupToAddModList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceGroups-r16)) OF PUCCH-ResourceGroup-r16 + OPTIONAL, -- Need N + resourceGroupToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceGroups-r16)) OF PUCCH-ResourceGroupId-r16 + OPTIONAL, -- Need N + sps-PUCCH-AN-List-r16 SetupRelease { SPS-PUCCH-AN-List-r16 } OPTIONAL, -- Need M + schedulingRequestResourceToAddModListExt-v1610 SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceConfigExt-v1610 + OPTIONAL -- Need N + ]] +} + +PUCCH-FormatConfig ::= SEQUENCE { + interslotFrequencyHopping ENUMERATED {enabled} OPTIONAL, -- Need R + additionalDMRS ENUMERATED {true} OPTIONAL, -- Need R + maxCodeRate PUCCH-MaxCodeRate OPTIONAL, -- Need R + nrofSlots ENUMERATED {n2,n4,n8} OPTIONAL, -- Need S + pi2BPSK ENUMERATED {enabled} OPTIONAL, -- Need R + simultaneousHARQ-ACK-CSI ENUMERATED {true} OPTIONAL -- Need R +} + +PUCCH-MaxCodeRate ::= ENUMERATED {zeroDot08, zeroDot15, zeroDot25, zeroDot35, zeroDot45, zeroDot60, zeroDot80} + +-- A set with one or more PUCCH resources +PUCCH-ResourceSet ::= SEQUENCE { + pucch-ResourceSetId PUCCH-ResourceSetId, + resourceList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourcesPerSet)) OF PUCCH-ResourceId, + maxPayloadSize INTEGER (4..256) OPTIONAL -- Need R +} + +PUCCH-ResourceSetId ::= INTEGER (0..maxNrofPUCCH-ResourceSets-1) + +PUCCH-Resource ::= SEQUENCE { + pucch-ResourceId PUCCH-ResourceId, + startingPRB PRB-Id, + intraSlotFrequencyHopping ENUMERATED { enabled } OPTIONAL, -- Need R + secondHopPRB PRB-Id OPTIONAL, -- Need R + format CHOICE { + format0 PUCCH-format0, + format1 PUCCH-format1, + format2 PUCCH-format2, + format3 PUCCH-format3, + format4 PUCCH-format4 + } +} + +PUCCH-ResourceExt-r16 ::= SEQUENCE { + interlaceAllocation-r16 SEQUENCE { + rb-SetIndex INTEGER (0..4), + interlace0 CHOICE { + scs15 INTEGER (0..9), + scs30 INTEGER (0..4) + } + } OPTIONAL, --Need R + formatExt-v1610 CHOICE { + interlace1-v1610 INTEGER (0..9), + occ-v1610 SEQUENCE { + occ-Length-v1610 ENUMERATED {n2,n4} OPTIONAL, -- Need M + occ-Index-v1610 ENUMERATED {n0,n1,n2,n3} OPTIONAL -- Need M + } + } OPTIONAL, -- Need R + ... +} + +PUCCH-ResourceId ::= INTEGER (0..maxNrofPUCCH-Resources-1) + + +PUCCH-format0 ::= SEQUENCE { + initialCyclicShift INTEGER(0..11), + nrofSymbols INTEGER (1..2), + startingSymbolIndex INTEGER(0..13) +} + +PUCCH-format1 ::= SEQUENCE { + initialCyclicShift INTEGER(0..11), + nrofSymbols INTEGER (4..14), + startingSymbolIndex INTEGER(0..10), + timeDomainOCC INTEGER(0..6) +} + +PUCCH-format2 ::= SEQUENCE { + nrofPRBs INTEGER (1..16), + nrofSymbols INTEGER (1..2), + startingSymbolIndex INTEGER(0..13) +} + +PUCCH-format3 ::= SEQUENCE { + nrofPRBs INTEGER (1..16), + nrofSymbols INTEGER (4..14), + startingSymbolIndex INTEGER(0..10) +} + +PUCCH-format4 ::= SEQUENCE { + nrofSymbols INTEGER (4..14), + occ-Length ENUMERATED {n2,n4}, + occ-Index ENUMERATED {n0,n1,n2,n3}, + startingSymbolIndex INTEGER(0..10) +} + +PUCCH-ResourceGroup-r16 ::= SEQUENCE { + pucch-ResourceGroupId-r16 PUCCH-ResourceGroupId-r16, + resourcePerGroupList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourcesPerGroup-r16)) OF PUCCH-ResourceId +} + +PUCCH-ResourceGroupId-r16 ::= INTEGER (0..maxNrofPUCCH-ResourceGroups-1-r16) + +DL-DataToUL-ACK-r16 ::= SEQUENCE (SIZE (1..8)) OF INTEGER (-1..15) + +DL-DataToUL-ACK-DCI-1-2-r16 ::= SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) + +UL-AccessConfigListDCI-1-1-r16 ::= SEQUENCE (SIZE (1..16)) OF INTEGER (0..15) + +-- TAG-PUCCH-CONFIG-STOP +-- TAG-PUCCH-CONFIGCOMMON-START + +PUCCH-ConfigCommon ::= SEQUENCE { + pucch-ResourceCommon INTEGER (0..15) OPTIONAL, -- Cond InitialBWP-Only + pucch-GroupHopping ENUMERATED { neither, enable, disable }, + hoppingId INTEGER (0..1023) OPTIONAL, -- Need R + p0-nominal INTEGER (-202..24) OPTIONAL, -- Need R + ... +} + +-- TAG-PUCCH-CONFIGCOMMON-STOP +-- TAG-PUCCH-CONFIGURATIONLIST-START + +PUCCH-ConfigurationList-r16 ::= SEQUENCE (SIZE (1..2)) OF PUCCH-Config + +-- TAG-PUCCH-CONFIGURATIONLIST-STOP +-- TAG-PUCCH-PATHLOSSREFERENCERS-ID-START + +PUCCH-PathlossReferenceRS-Id ::= INTEGER (0..maxNrofPUCCH-PathlossReferenceRSs-1) + +PUCCH-PathlossReferenceRS-Id-v1610 ::= INTEGER (maxNrofPUCCH-PathlossReferenceRSs..maxNrofPUCCH-PathlossReferenceRSs-1-r16) + +-- TAG-PUCCH-PATHLOSSREFERENCERS-ID-STOP +-- TAG-PUCCH-POWERCONTROL-START +PUCCH-PowerControl ::= SEQUENCE { + deltaF-PUCCH-f0 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f1 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f2 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f3 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f4 INTEGER (-16..15) OPTIONAL, -- Need R + p0-Set SEQUENCE (SIZE (1..maxNrofPUCCH-P0-PerSet)) OF P0-PUCCH OPTIONAL, -- Need M + pathlossReferenceRSs SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSs)) OF PUCCH-PathlossReferenceRS + OPTIONAL, -- Need M + twoPUCCH-PC-AdjustmentStates ENUMERATED {twoStates} OPTIONAL, -- Need S + ..., + [[ + pathlossReferenceRSs-v1610 SetupRelease { PathlossReferenceRSs-v1610 } OPTIONAL -- Need M + ]] +} + +P0-PUCCH ::= SEQUENCE { + p0-PUCCH-Id P0-PUCCH-Id, + p0-PUCCH-Value INTEGER (-16..15) +} + +P0-PUCCH-Id ::= INTEGER (1..8) + +PathlossReferenceRSs-v1610 ::= SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSsDiff-r16)) OF PUCCH-PathlossReferenceRS-r16 + +PUCCH-PathlossReferenceRS ::= SEQUENCE { + pucch-PathlossReferenceRS-Id PUCCH-PathlossReferenceRS-Id, + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + } +} + +PUCCH-PathlossReferenceRS-r16 ::= SEQUENCE { + pucch-PathlossReferenceRS-Id-r16 PUCCH-PathlossReferenceRS-Id-v1610, + referenceSignal-r16 CHOICE { + ssb-Index-r16 SSB-Index, + csi-RS-Index-r16 NZP-CSI-RS-ResourceId + } +} + +-- TAG-PUCCH-POWERCONTROL-STOP +-- TAG-PUCCH-SPATIALRELATIONINFO-START + +PUCCH-SpatialRelationInfo ::= SEQUENCE { + pucch-SpatialRelationInfoId PUCCH-SpatialRelationInfoId, + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId, + srs PUCCH-SRS + }, + pucch-PathlossReferenceRS-Id PUCCH-PathlossReferenceRS-Id, + p0-PUCCH-Id P0-PUCCH-Id, + closedLoopIndex ENUMERATED { i0, i1 } +} + +PUCCH-SpatialRelationInfoExt-r16 ::= SEQUENCE { + pucch-SpatialRelationInfoId-v1610 PUCCH-SpatialRelationInfoId-v1610 OPTIONAL, -- Cond SetupOnly + pucch-PathlossReferenceRS-Id-v1610 PUCCH-PathlossReferenceRS-Id-v1610 OPTIONAL, --Need R + ... +} + +PUCCH-SRS ::= SEQUENCE { + resource SRS-ResourceId, + uplinkBWP BWP-Id +} +-- TAG-PUCCH-SPATIALRELATIONINFO-STOP +-- TAG-PUCCH-SPATIALRELATIONINFO-START + +PUCCH-SpatialRelationInfoId ::= INTEGER (1..maxNrofSpatialRelationInfos) + +PUCCH-SpatialRelationInfoId-r16 ::= INTEGER (1..maxNrofSpatialRelationInfos-r16) + +PUCCH-SpatialRelationInfoId-v1610::= INTEGER (maxNrofSpatialRelationInfos-plus-1..maxNrofSpatialRelationInfos-r16) + +-- TAG-PUCCH-SPATIALRELATIONINFO-STOP +-- TAG-PUCCH-TPC-COMMANDCONFIG-START + +PUCCH-TPC-CommandConfig ::= SEQUENCE { + tpc-IndexPCell INTEGER (1..15) OPTIONAL, -- Cond PDCCH-OfSpcell + tpc-IndexPUCCH-SCell INTEGER (1..15) OPTIONAL, -- Cond PDCCH-ofSpCellOrPUCCH-SCell + ... +} + +-- TAG-PUCCH-TPC-COMMANDCONFIG-STOP +-- TAG-PUSCH-CONFIG-START + +PUSCH-Config ::= SEQUENCE { + dataScramblingIdentityPUSCH INTEGER (0..1023) OPTIONAL, -- Need S + txConfig ENUMERATED {codebook, nonCodebook} OPTIONAL, -- Need S + dmrs-UplinkForPUSCH-MappingTypeA SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + dmrs-UplinkForPUSCH-MappingTypeB SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + pusch-PowerControl PUSCH-PowerControl OPTIONAL, -- Need M + frequencyHopping ENUMERATED {intraSlot, interSlot} OPTIONAL, -- Need S + frequencyHoppingOffsetLists SEQUENCE (SIZE (1..4)) OF INTEGER (1.. maxNrofPhysicalResourceBlocks-1) + OPTIONAL, -- Need M + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch}, + pusch-TimeDomainAllocationList SetupRelease { PUSCH-TimeDomainResourceAllocationList } OPTIONAL, -- Need M + pusch-AggregationFactor ENUMERATED { n2, n4, n8 } OPTIONAL, -- Need S + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoder ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + transformPrecoder ENUMERATED {enabled, disabled} OPTIONAL, -- Need S + codebookSubset ENUMERATED {fullyAndPartialAndNonCoherent, partialAndNonCoherent,nonCoherent} + OPTIONAL, -- Cond codebookBased + maxRank INTEGER (1..4) OPTIONAL, -- Cond codebookBased + rbg-Size ENUMERATED { config2} OPTIONAL, -- Need S + uci-OnPUSCH SetupRelease { UCI-OnPUSCH} OPTIONAL, -- Need M + tp-pi2BPSK ENUMERATED {enabled} OPTIONAL, -- Need S + ..., + [[ + minimumSchedulingOffsetK2-r16 SetupRelease { MinSchedulingOffsetK2-Values-r16 } OPTIONAL, -- Need M + ul-AccessConfigListDCI-0-1-r16 SetupRelease { UL-AccessConfigListDCI-0-1-r16 } OPTIONAL, -- Need M + -- Start of the parameters for DCI format 0_2 introduced in V16.1.0 + harq-ProcessNumberSizeDCI-0-2-r16 INTEGER (0..4) OPTIONAL, -- Need R + dmrs-SequenceInitializationDCI-0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + numberOfBitsForRV-DCI-0-2-r16 INTEGER (0..2) OPTIONAL, -- Need R + antennaPortsFieldPresenceDCI-0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + dmrs-UplinkForPUSCH-MappingTypeA-DCI-0-2-r16 SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + dmrs-UplinkForPUSCH-MappingTypeB-DCI-0-2-r16 SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + frequencyHoppingDCI-0-2-r16 CHOICE { + pusch-RepTypeA ENUMERATED {intraSlot, interSlot}, + pusch-RepTypeB ENUMERATED {interRepetition, interSlot} + } OPTIONAL, -- Need S + frequencyHoppingOffsetListsDCI-0-2-r16 SetupRelease { FrequencyHoppingOffsetListsDCI-0-2-r16} OPTIONAL, -- Need M + codebookSubsetDCI-0-2-r16 ENUMERATED {fullyAndPartialAndNonCoherent, partialAndNonCoherent,nonCoherent} + OPTIONAL, -- Cond codebookBased + invalidSymbolPatternIndicatorDCI-0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + maxRankDCI-0-2-r16 INTEGER (1..4) OPTIONAL, -- Cond codebookBased + mcs-TableDCI-0-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoderDCI-0-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + priorityIndicatorDCI-0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + pusch-RepTypeIndicatorDCI-0-2-r16 ENUMERATED { pusch-RepTypeA, pusch-RepTypeB} OPTIONAL, -- Need R + resourceAllocationDCI-0-2-r16 ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch} + OPTIONAL, -- Need M + resourceAllocationType1GranularityDCI-0-2-r16 ENUMERATED { n2,n4,n8,n16 } OPTIONAL, -- Need S + uci-OnPUSCH-ListDCI-0-2-r16 SetupRelease { UCI-OnPUSCH-ListDCI-0-2-r16} OPTIONAL, -- Need M + pusch-TimeDomainAllocationListDCI-0-2-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + -- End of the parameters for DCI format 0_2 introduced in V16.1.0 + -- Start of the parameters for DCI format 0_1 introduced in V16.1.0 + pusch-TimeDomainAllocationListDCI-0-1-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + invalidSymbolPatternIndicatorDCI-0-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + priorityIndicatorDCI-0-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + pusch-RepTypeIndicatorDCI-0-1-r16 ENUMERATED { pusch-RepTypeA, pusch-RepTypeB} OPTIONAL, -- Need R + frequencyHoppingDCI-0-1-r16 ENUMERATED {interRepetition, interSlot} OPTIONAL, -- Cond RepTypeB + uci-OnPUSCH-ListDCI-0-1-r16 SetupRelease { UCI-OnPUSCH-ListDCI-0-1-r16 } OPTIONAL, -- Need M + -- End of the parameters for DCI format 0_1 introduced in V16.1.0 + invalidSymbolPattern-r16 InvalidSymbolPattern-r16 OPTIONAL, -- Need S + pusch-PowerControl-v1610 SetupRelease {PUSCH-PowerControl-v1610} OPTIONAL, -- Need M + ul-FullPowerTransmission-r16 ENUMERATED {fullpower, fullpowerMode1, fullpowerMode2} OPTIONAL, -- Need R + pusch-TimeDomainAllocationListForMultiPUSCH-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + numberOfInvalidSymbolsForDL-UL-Switching-r16 INTEGER (1..4) OPTIONAL -- Cond RepTypeB2 + ]] +} + +UCI-OnPUSCH ::= SEQUENCE { + betaOffsets CHOICE { + dynamic SEQUENCE (SIZE (4)) OF BetaOffsets, + semiStatic BetaOffsets + } OPTIONAL, -- Need M + scaling ENUMERATED { f0p5, f0p65, f0p8, f1 } +} + +MinSchedulingOffsetK2-Values-r16 ::= SEQUENCE (SIZE (1..maxNrOfMinSchedulingOffsetValues-r16)) OF INTEGER (0..maxK2-SchedulingOffset-r16) + +UCI-OnPUSCH-DCI-0-2-r16 ::= SEQUENCE { + betaOffsetsDCI-0-2-r16 CHOICE { + dynamicDCI-0-2-r16 CHOICE { + oneBit-r16 SEQUENCE (SIZE (2)) OF BetaOffsets, + twoBits-r16 SEQUENCE (SIZE (4)) OF BetaOffsets + }, + semiStaticDCI-0-2-r16 BetaOffsets + } OPTIONAL, -- Need M + scalingDCI-0-2-r16 ENUMERATED { f0p5, f0p65, f0p8, f1 } +} + +FrequencyHoppingOffsetListsDCI-0-2-r16 ::= SEQUENCE (SIZE (1..4)) OF INTEGER (1.. maxNrofPhysicalResourceBlocks-1) + +UCI-OnPUSCH-ListDCI-0-2-r16 ::= SEQUENCE (SIZE (1..2)) OF UCI-OnPUSCH-DCI-0-2-r16 + +UCI-OnPUSCH-ListDCI-0-1-r16 ::= SEQUENCE (SIZE (1..2)) OF UCI-OnPUSCH + +UL-AccessConfigListDCI-0-1-r16 ::= SEQUENCE (SIZE (1..64)) OF INTEGER (0..63) + +-- TAG-PUSCH-CONFIG-STOP +-- TAG-PUSCH-CONFIGCOMMON-START + +PUSCH-ConfigCommon ::= SEQUENCE { + groupHoppingEnabledTransformPrecoding ENUMERATED {enabled} OPTIONAL, -- Need R + pusch-TimeDomainAllocationList PUSCH-TimeDomainResourceAllocationList OPTIONAL, -- Need R + msg3-DeltaPreamble INTEGER (-1..6) OPTIONAL, -- Need R + p0-NominalWithGrant INTEGER (-202..24) OPTIONAL, -- Need R + ... +} + +-- TAG-PUSCH-CONFIGCOMMON-STOP +-- TAG-PUSCH-POWERCONTROL-START + +PUSCH-PowerControl ::= SEQUENCE { + tpc-Accumulation ENUMERATED { disabled } OPTIONAL, -- Need S + msg3-Alpha Alpha OPTIONAL, -- Need S + p0-NominalWithoutGrant INTEGER (-202..24) OPTIONAL, -- Need M + p0-AlphaSets SEQUENCE (SIZE (1..maxNrofP0-PUSCH-AlphaSets)) OF P0-PUSCH-AlphaSet OPTIONAL, -- Need M + pathlossReferenceRSToAddModList SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSs)) OF PUSCH-PathlossReferenceRS + OPTIONAL, -- Need N + pathlossReferenceRSToReleaseList SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSs)) OF PUSCH-PathlossReferenceRS-Id + OPTIONAL, -- Need N + twoPUSCH-PC-AdjustmentStates ENUMERATED {twoStates} OPTIONAL, -- Need S + deltaMCS ENUMERATED {enabled} OPTIONAL, -- Need S + sri-PUSCH-MappingToAddModList SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF SRI-PUSCH-PowerControl + OPTIONAL, -- Need N + sri-PUSCH-MappingToReleaseList SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF SRI-PUSCH-PowerControlId + OPTIONAL -- Need N +} + +P0-PUSCH-AlphaSet ::= SEQUENCE { + p0-PUSCH-AlphaSetId P0-PUSCH-AlphaSetId, + p0 INTEGER (-16..15) OPTIONAL, -- Need S + alpha Alpha OPTIONAL -- Need S +} + +P0-PUSCH-AlphaSetId ::= INTEGER (0..maxNrofP0-PUSCH-AlphaSets-1) + +PUSCH-PathlossReferenceRS ::= SEQUENCE { + pusch-PathlossReferenceRS-Id PUSCH-PathlossReferenceRS-Id, + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + } +} + +PUSCH-PathlossReferenceRS-r16 ::= SEQUENCE { + pusch-PathlossReferenceRS-Id-r16 PUSCH-PathlossReferenceRS-Id-v1610, + referenceSignal-r16 CHOICE { + ssb-Index-r16 SSB-Index, + csi-RS-Index-r16 NZP-CSI-RS-ResourceId + } +} + +PUSCH-PathlossReferenceRS-Id ::= INTEGER (0..maxNrofPUSCH-PathlossReferenceRSs-1) + +PUSCH-PathlossReferenceRS-Id-v1610 ::= INTEGER (maxNrofPUSCH-PathlossReferenceRSs..maxNrofPUSCH-PathlossReferenceRSs-1-r16) + +SRI-PUSCH-PowerControl ::= SEQUENCE { + sri-PUSCH-PowerControlId SRI-PUSCH-PowerControlId, + sri-PUSCH-PathlossReferenceRS-Id PUSCH-PathlossReferenceRS-Id, + sri-P0-PUSCH-AlphaSetId P0-PUSCH-AlphaSetId, + sri-PUSCH-ClosedLoopIndex ENUMERATED { i0, i1 } +} + +SRI-PUSCH-PowerControlId ::= INTEGER (0..maxNrofSRI-PUSCH-Mappings-1) + +PUSCH-PowerControl-v1610 ::= SEQUENCE { + pathlossReferenceRSToAddModListSizeExt-v1610 SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSsDiff-r16)) OF PUSCH-PathlossReferenceRS-r16 + OPTIONAL, -- Need N + pathlossReferenceRSToReleaseListSizeExt-v1610 SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSsDiff-r16)) OF PUSCH-PathlossReferenceRS-Id-v1610 + OPTIONAL, -- Need N + p0-PUSCH-SetList-r16 SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF P0-PUSCH-Set-r16 OPTIONAL, -- Need R + olpc-ParameterSet SEQUENCE { + olpc-ParameterSetDCI-0-1-r16 INTEGER (1..2) OPTIONAL, -- Need R + olpc-ParameterSetDCI-0-2-r16 INTEGER (1..2) OPTIONAL -- Need R + } OPTIONAL, -- Need M + ... +} + +P0-PUSCH-Set-r16 ::= SEQUENCE { + p0-PUSCH-SetId-r16 P0-PUSCH-SetId-r16, + p0-List-r16 SEQUENCE (SIZE (1..maxNrofP0-PUSCH-Set-r16)) OF P0-PUSCH-r16 OPTIONAL, -- Need R + ... +} + +P0-PUSCH-SetId-r16 ::= INTEGER (0..maxNrofSRI-PUSCH-Mappings-1) + +P0-PUSCH-r16 ::= INTEGER (-16..15) + +-- TAG-PUSCH-POWERCONTROL-STOP +-- TAG-PUSCH-SERVINGCELLCONFIG-START + +PUSCH-ServingCellConfig ::= SEQUENCE { + codeBlockGroupTransmission SetupRelease { PUSCH-CodeBlockGroupTransmission } OPTIONAL, -- Need M + rateMatching ENUMERATED {limitedBufferRM} OPTIONAL, -- Need S + xOverhead ENUMERATED {xoh6, xoh12, xoh18} OPTIONAL, -- Need S + ..., + [[ + maxMIMO-Layers INTEGER (1..4) OPTIONAL, -- Need M + processingType2Enabled BOOLEAN OPTIONAL -- Need M + ]], + [[ + maxMIMO-LayersDCI-0-2-r16 SetupRelease { MaxMIMO-LayersDCI-0-2-r16} OPTIONAL -- Need M + ]] +} + +PUSCH-CodeBlockGroupTransmission ::= SEQUENCE { + maxCodeBlockGroupsPerTransportBlock ENUMERATED {n2, n4, n6, n8}, + ... +} + +MaxMIMO-LayersDCI-0-2-r16 ::= INTEGER (1..4) + +-- TAG-PUSCH-SERVINGCELLCONFIG-STOP +-- TAG-PUSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-START + +PUSCH-TimeDomainResourceAllocationList ::= SEQUENCE (SIZE(1..maxNrofUL-Allocations)) OF PUSCH-TimeDomainResourceAllocation + +PUSCH-TimeDomainResourceAllocation ::= SEQUENCE { + k2 INTEGER(0..32) OPTIONAL, -- Need S + mappingType ENUMERATED {typeA, typeB}, + startSymbolAndLength INTEGER (0..127) +} + +PUSCH-TimeDomainResourceAllocationList-r16 ::= SEQUENCE (SIZE(1..maxNrofUL-Allocations-r16)) OF PUSCH-TimeDomainResourceAllocation-r16 + +PUSCH-TimeDomainResourceAllocation-r16 ::= SEQUENCE { + k2-r16 INTEGER(0..32) OPTIONAL, -- Need S + puschAllocationList-r16 SEQUENCE (SIZE(1..maxNrofMultiplePUSCHs-r16)) OF PUSCH-Allocation-r16, +... +} + +PUSCH-Allocation-r16 ::= SEQUENCE { + mappingType-r16 ENUMERATED {typeA, typeB} OPTIONAL, -- Cond NotFormat01-02-Or-TypeA + startSymbolAndLength-r16 INTEGER (0..127) OPTIONAL, -- Cond NotFormat01-02-Or-TypeA + startSymbol-r16 INTEGER (0..13) OPTIONAL, -- Cond RepTypeB + length-r16 INTEGER (1..14) OPTIONAL, -- Cond RepTypeB + numberOfRepetitions-r16 ENUMERATED {n1, n2, n3, n4, n7, n8, n12, n16} OPTIONAL, -- Cond Format01-02 + ... +} + +-- TAG-PUSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-STOP +-- TAG-PUSCH-TPC-COMMANDCONFIG-START + +PUSCH-TPC-CommandConfig ::= SEQUENCE { + tpc-Index INTEGER (1..15) OPTIONAL, -- Cond SUL + tpc-IndexSUL INTEGER (1..15) OPTIONAL, -- Cond SUL-Only + targetCell ServCellIndex OPTIONAL, -- Need S + ... +} + +-- TAG-PUSCH-TPC-COMMANDCONFIG-STOP +-- TAG-Q-OFFSETRANGE-START + +Q-OffsetRange ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-Q-OFFSETRANGE-STOP +-- TAG-Q-QUALMIN-START + +Q-QualMin ::= INTEGER (-43..-12) + +-- TAG-Q-QUALMIN-STOP +-- TAG-Q-RXLEVMIN-START + +Q-RxLevMin ::= INTEGER (-70..-22) + +-- TAG-Q-RXLEVMIN-STOP +-- TAG-QUANTITYCONFIG-START + + +QuantityConfig ::= SEQUENCE { + quantityConfigNR-List SEQUENCE (SIZE (1..maxNrofQuantityConfig)) OF QuantityConfigNR OPTIONAL, -- Need M + ..., + [[ + quantityConfigEUTRA FilterConfig OPTIONAL -- Need M + ]], + [[ + quantityConfigUTRA-FDD-r16 QuantityConfigUTRA-FDD-r16 OPTIONAL, -- Need M + quantityConfigCLI-r16 FilterConfigCLI-r16 OPTIONAL -- Need M + ]] +} + +QuantityConfigNR::= SEQUENCE { + quantityConfigCell QuantityConfigRS, + quantityConfigRS-Index QuantityConfigRS OPTIONAL -- Need M +} + +QuantityConfigRS ::= SEQUENCE { + ssb-FilterConfig FilterConfig, + csi-RS-FilterConfig FilterConfig +} + +FilterConfig ::= SEQUENCE { + filterCoefficientRSRP FilterCoefficient DEFAULT fc4, + filterCoefficientRSRQ FilterCoefficient DEFAULT fc4, + filterCoefficientRS-SINR FilterCoefficient DEFAULT fc4 +} + +FilterConfigCLI-r16 ::= SEQUENCE { + filterCoefficientSRS-RSRP-r16 FilterCoefficient DEFAULT fc4, + filterCoefficientCLI-RSSI-r16 FilterCoefficient DEFAULT fc4 +} + +QuantityConfigUTRA-FDD-r16 ::= SEQUENCE { + filterCoefficientRSCP-r16 FilterCoefficient DEFAULT fc4, + filterCoefficientEcNO-r16 FilterCoefficient DEFAULT fc4 +} + +-- TAG-QUANTITYCONFIG-STOP +-- TAG-RACH-CONFIGCOMMON-START + +RACH-ConfigCommon ::= SEQUENCE { + rach-ConfigGeneric RACH-ConfigGeneric, + totalNumberOfRA-Preambles INTEGER (1..63) OPTIONAL, -- Need S + ssb-perRACH-OccasionAndCB-PreamblesPerSSB CHOICE { + oneEighth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneFourth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneHalf ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + one ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + two ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32}, + four INTEGER (1..16), + eight INTEGER (1..8), + sixteen INTEGER (1..4) + } OPTIONAL, -- Need M + + groupBconfigured SEQUENCE { + ra-Msg3SizeGroupA ENUMERATED {b56, b144, b208, b256, b282, b480, b640, + b800, b1000, b72, spare6, spare5,spare4, spare3, spare2, spare1}, + messagePowerOffsetGroupB ENUMERATED { minusinfinity, dB0, dB5, dB8, dB10, dB12, dB15, dB18}, + numberOfRA-PreamblesGroupA INTEGER (1..64) + } OPTIONAL, -- Need R + ra-ContentionResolutionTimer ENUMERATED { sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64}, + rsrp-ThresholdSSB RSRP-Range OPTIONAL, -- Need R + rsrp-ThresholdSSB-SUL RSRP-Range OPTIONAL, -- Cond SUL + prach-RootSequenceIndex CHOICE { + l839 INTEGER (0..837), + l139 INTEGER (0..137) + }, + msg1-SubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond L139 + restrictedSetConfig ENUMERATED {unrestrictedSet, restrictedSetTypeA, restrictedSetTypeB}, + msg3-transformPrecoder ENUMERATED {enabled} OPTIONAL, -- Need R + ..., + [[ + ra-PrioritizationForAccessIdentity-r16 SEQUENCE { + ra-Prioritization-r16 RA-Prioritization, + ra-PrioritizationForAI-r16 BIT STRING (SIZE (2)) + } OPTIONAL, -- Cond InitialBWP-Only + prach-RootSequenceIndex-r16 CHOICE { + l571 INTEGER (0..569), + l1151 INTEGER (0..1149) + } OPTIONAL -- Need R + ]] +} + +-- TAG-RACH-CONFIGCOMMON-STOP +-- TAG-RACH-CONFIGCOMMONTWOSTEPRA-START + +RACH-ConfigCommonTwoStepRA-r16 ::= SEQUENCE { + rach-ConfigGenericTwoStepRA-r16 RACH-ConfigGenericTwoStepRA-r16, + msgA-TotalNumberOfRA-Preambles-r16 INTEGER (1..63) OPTIONAL, -- Need S + msgA-SSB-PerRACH-OccasionAndCB-PreamblesPerSSB-r16 CHOICE { + oneEighth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneFourth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneHalf ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + one ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + two ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32}, + four INTEGER (1..16), + eight INTEGER (1..8), + sixteen INTEGER (1..4) + } OPTIONAL, -- Cond 2StepOnly + msgA-CB-PreamblesPerSSB-PerSharedRO-r16 INTEGER (1..60) OPTIONAL, -- Cond SharedRO + msgA-SSB-SharedRO-MaskIndex-r16 INTEGER (1..15) OPTIONAL, -- Need S + groupB-ConfiguredTwoStepRA-r16 GroupB-ConfiguredTwoStepRA-r16 OPTIONAL, -- Need S + msgA-PRACH-RootSequenceIndex-r16 CHOICE { + l839 INTEGER (0..837), + l139 INTEGER (0..137), + l571 INTEGER (0..569), + l1151 INTEGER (0..1149) + } OPTIONAL, -- Cond 2StepOnly + msgA-TransMax-r16 ENUMERATED {n1, n2, n4, n6, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Need R + msgA-RSRP-Threshold-r16 RSRP-Range OPTIONAL, -- Cond 2Step4Step + msgA-RSRP-ThresholdSSB-r16 RSRP-Range OPTIONAL, -- Need R + msgA-SubcarrierSpacing-r16 SubcarrierSpacing OPTIONAL, -- Cond 2StepOnlyL139 + msgA-RestrictedSetConfig-r16 ENUMERATED {unrestrictedSet, restrictedSetTypeA, + restrictedSetTypeB} OPTIONAL, -- Cond 2StepOnly + ra-PrioritizationForAccessIdentityTwoStep-r16 SEQUENCE { + ra-Prioritization-r16 RA-Prioritization, + ra-PrioritizationForAI-r16 BIT STRING (SIZE (2)) + } OPTIONAL, -- Cond InitialBWP-Only + ra-ContentionResolutionTimer-r16 ENUMERATED {sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64} OPTIONAL, -- Cond 2StepOnly + ... +} + +GroupB-ConfiguredTwoStepRA-r16 ::= SEQUENCE { + ra-MsgA-SizeGroupA ENUMERATED {b56, b144, b208, b256, b282, b480, b640, b800, + b1000, b72, spare6, spare5, spare4, spare3, spare2, spare1}, + messagePowerOffsetGroupB ENUMERATED {minusinfinity, dB0, dB5, dB8, dB10, dB12, dB15, dB18}, + numberOfRA-PreamblesGroupA INTEGER (1..64) +} + +-- TAG-RACH-CONFIGCOMMONTWOSTEPRA-STOP +-- TAG-RACH-CONFIGDEDICATED-START + + +RACH-ConfigDedicated ::= SEQUENCE { + cfra CFRA OPTIONAL, -- Need S + ra-Prioritization RA-Prioritization OPTIONAL, -- Need N + ..., + [[ + ra-PrioritizationTwoStep-r16 RA-Prioritization OPTIONAL, -- Need N + cfra-TwoStep-r16 CFRA-TwoStep-r16 OPTIONAL -- Need S + ]] +} + +CFRA ::= SEQUENCE { + occasions SEQUENCE { + rach-ConfigGeneric RACH-ConfigGeneric, + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, four, eight, sixteen} + OPTIONAL -- Cond Mandatory + } OPTIONAL, -- Need S + resources CHOICE { + ssb SEQUENCE { + ssb-ResourceList SEQUENCE (SIZE(1..maxRA-SSB-Resources)) OF CFRA-SSB-Resource, + ra-ssb-OccasionMaskIndex INTEGER (0..15) + }, + csirs SEQUENCE { + csirs-ResourceList SEQUENCE (SIZE(1..maxRA-CSIRS-Resources)) OF CFRA-CSIRS-Resource, + rsrp-ThresholdCSI-RS RSRP-Range + } + }, + ..., + [[ + totalNumberOfRA-Preambles INTEGER (1..63) OPTIONAL -- Cond Occasions + ]] +} + +CFRA-TwoStep-r16 ::= SEQUENCE { + occasionsTwoStepRA-r16 SEQUENCE { + rach-ConfigGenericTwoStepRA-r16 RACH-ConfigGenericTwoStepRA-r16, + ssb-PerRACH-OccasionTwoStepRA-r16 ENUMERATED {oneEighth, oneFourth, oneHalf, one, + two, four, eight, sixteen} + } OPTIONAL, -- Need S + msgA-CFRA-PUSCH-r16 MsgA-PUSCH-Resource-r16, + msgA-TransMax-r16 ENUMERATED {n1, n2, n4, n6, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Need S + resourcesTwoStep-r16 SEQUENCE { + ssb-ResourceList SEQUENCE (SIZE(1..maxRA-SSB-Resources)) OF CFRA-SSB-Resource, + ra-ssb-OccasionMaskIndex INTEGER (0..15) + }, + ... +} + +CFRA-SSB-Resource ::= SEQUENCE { + ssb SSB-Index, + ra-PreambleIndex INTEGER (0..63), + ..., + [[ + msgA-PUSCH-Resource-Index-r16 INTEGER (0..3071) OPTIONAL -- Cond 2StepCFRA + ]] + +} + +CFRA-CSIRS-Resource ::= SEQUENCE { + csi-RS CSI-RS-Index, + ra-OccasionList SEQUENCE (SIZE(1..maxRA-OccasionsPerCSIRS)) OF INTEGER (0..maxRA-Occasions-1), + ra-PreambleIndex INTEGER (0..63), + ... +} + +-- TAG-RACH-CONFIGDEDICATED-STOP +-- TAG-RACH-CONFIGGENERIC-START + +RACH-ConfigGeneric ::= SEQUENCE { + prach-ConfigurationIndex INTEGER (0..255), + msg1-FDM ENUMERATED {one, two, four, eight}, + msg1-FrequencyStart INTEGER (0..maxNrofPhysicalResourceBlocks-1), + zeroCorrelationZoneConfig INTEGER(0..15), + preambleReceivedTargetPower INTEGER (-202..-60), + preambleTransMax ENUMERATED {n3, n4, n5, n6, n7, n8, n10, n20, n50, n100, n200}, + powerRampingStep ENUMERATED {dB0, dB2, dB4, dB6}, + ra-ResponseWindow ENUMERATED {sl1, sl2, sl4, sl8, sl10, sl20, sl40, sl80}, + ..., + [[ + prach-ConfigurationPeriodScaling-IAB-r16 ENUMERATED {scf1,scf2,scf4,scf8,scf16,scf32,scf64} OPTIONAL, -- Need R + prach-ConfigurationFrameOffset-IAB-r16 INTEGER (0..63) OPTIONAL, -- Need R + prach-ConfigurationSOffset-IAB-r16 INTEGER (0..39) OPTIONAL, -- Need R + ra-ResponseWindow-v1610 ENUMERATED { sl60, sl160} OPTIONAL, -- Need R + prach-ConfigurationIndex-v1610 INTEGER (256..262) OPTIONAL -- Need R + ]] +} + +-- TAG-RACH-CONFIGGENERIC-STOP +-- TAG-RACH-CONFIGGENERICTWOSTEPRA-START + +RACH-ConfigGenericTwoStepRA-r16 ::= SEQUENCE { + msgA-PRACH-ConfigurationIndex-r16 INTEGER (0..262) OPTIONAL, -- Cond 2StepOnly + msgA-RO-FDM-r16 ENUMERATED {one, two, four, eight} OPTIONAL, -- Cond 2StepOnly + msgA-RO-FrequencyStart-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, -- Cond 2StepOnly + msgA-ZeroCorrelationZoneConfig-r16 INTEGER (0..15) OPTIONAL, -- Cond 2StepOnly + msgA-PreamblePowerRampingStep-r16 ENUMERATED {dB0, dB2, dB4, dB6} OPTIONAL, -- Cond 2StepOnlyNoCFRA + msgA-PreambleReceivedTargetPower-r16 INTEGER (-202..-60) OPTIONAL, -- Cond 2StepOnlyNoCFRA + msgB-ResponseWindow-r16 ENUMERATED {sl1, sl2, sl4, sl8, sl10, sl20, sl40, sl80, sl160, sl320} + OPTIONAL, -- Cond NoCFRA + preambleTransMax-r16 ENUMERATED {n3, n4, n5, n6, n7, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Cond 2StepOnlyNoCFRA + ... +} + +-- TAG-RACH-CONFIGGENERICTWOSTEPRA-STOP +-- TAG-RA-PRIORITIZATION-START + +RA-Prioritization ::= SEQUENCE { + powerRampingStepHighPriority ENUMERATED {dB0, dB2, dB4, dB6}, + scalingFactorBI ENUMERATED {zero, dot25, dot5, dot75} OPTIONAL, -- Need R + ... +} + +-- TAG-RA-PRIORITIZATION-STOP +-- TAG-RADIOBEARERCONFIG-START + +RadioBearerConfig ::= SEQUENCE { + srb-ToAddModList SRB-ToAddModList OPTIONAL, -- Cond HO-Conn + srb3-ToRelease ENUMERATED{true} OPTIONAL, -- Need N + drb-ToAddModList DRB-ToAddModList OPTIONAL, -- Cond HO-toNR + drb-ToReleaseList DRB-ToReleaseList OPTIONAL, -- Need N + securityConfig SecurityConfig OPTIONAL, -- Need M + ... +} + +SRB-ToAddModList ::= SEQUENCE (SIZE (1..2)) OF SRB-ToAddMod +SRB-ToAddMod ::= SEQUENCE { + srb-Identity SRB-Identity, + reestablishPDCP ENUMERATED{true} OPTIONAL, -- Need N + discardOnPDCP ENUMERATED{true} OPTIONAL, -- Need N + pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP + ... +} + +DRB-ToAddModList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-ToAddMod + +DRB-ToAddMod ::= SEQUENCE { + cnAssociation CHOICE { + eps-BearerIdentity INTEGER (0..15), + sdap-Config SDAP-Config + } OPTIONAL, -- Cond DRBSetup + drb-Identity DRB-Identity, + reestablishPDCP ENUMERATED{true} OPTIONAL, -- Need N + recoverPDCP ENUMERATED{true} OPTIONAL, -- Need N + pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP + ..., + [[ + daps-Config-r16 ENUMERATED{true} OPTIONAL -- Cond DAPS + ]] +} +DRB-ToReleaseList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-Identity + +SecurityConfig ::= SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig OPTIONAL, -- Cond RBTermChange1 + keyToUse ENUMERATED{master, secondary} OPTIONAL, -- Cond RBTermChange + ... +} + +-- TAG-RADIOBEARERCONFIG-STOP +-- TAG-RADIOLINKMONITORINGCONFIG-START + +RadioLinkMonitoringConfig ::= SEQUENCE { + failureDetectionResourcesToAddModList SEQUENCE (SIZE(1..maxNrofFailureDetectionResources)) OF RadioLinkMonitoringRS + OPTIONAL, -- Need N + failureDetectionResourcesToReleaseList SEQUENCE (SIZE(1..maxNrofFailureDetectionResources)) OF RadioLinkMonitoringRS-Id + OPTIONAL, -- Need N + beamFailureInstanceMaxCount ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10} OPTIONAL, -- Need R + beamFailureDetectionTimer ENUMERATED {pbfd1, pbfd2, pbfd3, pbfd4, pbfd5, pbfd6, pbfd8, pbfd10} OPTIONAL, -- Need R + ... +} + +RadioLinkMonitoringRS ::= SEQUENCE { + radioLinkMonitoringRS-Id RadioLinkMonitoringRS-Id, + purpose ENUMERATED {beamFailure, rlf, both}, + detectionResource CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + }, + ... +} + +-- TAG-RADIOLINKMONITORINGCONFIG-STOP +-- TAG-RADIOLINKMONITORINGRS-ID-START + +RadioLinkMonitoringRS-Id ::= INTEGER (0..maxNrofFailureDetectionResources-1) + +-- TAG-RADIOLINKMONITORINGRS-ID-STOP +-- TAG-RAN-AREACODE-START + +RAN-AreaCode ::= INTEGER (0..255) + +-- TAG-RAN-AREACODE-STOP +-- TAG-RATEMATCHPATTERN-START + +RateMatchPattern ::= SEQUENCE { + rateMatchPatternId RateMatchPatternId, + + patternType CHOICE { + bitmaps SEQUENCE { + resourceBlocks BIT STRING (SIZE (275)), + symbolsInResourceBlock CHOICE { + oneSlot BIT STRING (SIZE (14)), + twoSlots BIT STRING (SIZE (28)) + }, + periodicityAndPattern CHOICE { + n2 BIT STRING (SIZE (2)), + n4 BIT STRING (SIZE (4)), + n5 BIT STRING (SIZE (5)), + n8 BIT STRING (SIZE (8)), + n10 BIT STRING (SIZE (10)), + n20 BIT STRING (SIZE (20)), + n40 BIT STRING (SIZE (40)) + } OPTIONAL, -- Need S + ... + }, + controlResourceSet ControlResourceSetId + }, + subcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond CellLevel + dummy ENUMERATED { dynamic, semiStatic }, + ..., + [[ + controlResourceSet-r16 ControlResourceSetId-r16 OPTIONAL -- Need R + ]] + +} + +-- TAG-RATEMATCHPATTERN-STOP +-- TAG-RATEMATCHPATTERNID-START + +RateMatchPatternId ::= INTEGER (0..maxNrofRateMatchPatterns-1) + +-- TAG-RATEMATCHPATTERNID-STOP +-- TAG-RATEMATCHPATTERNLTE-CRS-START + +RateMatchPatternLTE-CRS ::= SEQUENCE { + carrierFreqDL INTEGER (0..16383), + carrierBandwidthDL ENUMERATED {n6, n15, n25, n50, n75, n100, spare2, spare1}, + mbsfn-SubframeConfigList EUTRA-MBSFN-SubframeConfigList OPTIONAL, -- Need M + nrofCRS-Ports ENUMERATED {n1, n2, n4}, + v-Shift ENUMERATED {n0, n1, n2, n3, n4, n5} +} + +LTE-CRS-PatternList-r16 ::= SEQUENCE (SIZE (1..maxLTE-CRS-Patterns-r16)) OF RateMatchPatternLTE-CRS + +-- TAG-RATEMATCHPATTERNLTE-CRS-STOP +-- TAG-REFERENCETIMEINFO-START + +ReferenceTimeInfo-r16 ::= SEQUENCE { + time-r16 ReferenceTime-r16, + uncertainty-r16 INTEGER (0..32767) OPTIONAL, -- Need S + timeInfoType-r16 ENUMERATED {localClock} OPTIONAL, -- Need S + referenceSFN-r16 INTEGER (0..1023) OPTIONAL -- Cond RefTime +} + +ReferenceTime-r16 ::= SEQUENCE { + refDays-r16 INTEGER (0..72999), + refSeconds-r16 INTEGER (0..86399), + refMilliSeconds-r16 INTEGER (0..999), + refTenNanoSeconds-r16 INTEGER (0..99999) +} + +-- TAG-REFERENCETIMEINFO-STOP +-- TAG-REJECTWAITTIME-START + +RejectWaitTime ::= INTEGER (1..16) + +-- TAG-REJECTWAITTIME-STOP +-- TAG-REPETITIONSCHEMECONFIG-START + +RepetitionSchemeConfig-r16 ::= CHOICE { + fdm-TDM-r16 SetupRelease { FDM-TDM-r16 }, + slotBased-r16 SetupRelease { SlotBased-r16 } +} + +RepetitionSchemeConfig-v1630 ::= SEQUENCE { + slotBased-v1630 SetupRelease { SlotBased-v1630 } +} + +FDM-TDM-r16 ::= SEQUENCE { + repetitionScheme-r16 ENUMERATED {fdmSchemeA, fdmSchemeB,tdmSchemeA }, + startingSymbolOffsetK-r16 INTEGER (0..7) OPTIONAL -- Need R +} + +SlotBased-r16 ::= SEQUENCE { + tciMapping-r16 ENUMERATED {cyclicMapping, sequentialMapping}, + sequenceOffsetForRV-r16 INTEGER (1..3) +} + +SlotBased-v1630 ::= SEQUENCE { + tciMapping-r16 ENUMERATED {cyclicMapping, sequentialMapping}, + sequenceOffsetForRV-r16 INTEGER (0) +} + +-- TAG-REPETITIONSCHEMECONFIG-STOP +-- TAG-REPORTCONFIGID-START + +ReportConfigId ::= INTEGER (1..maxReportConfigId) + +-- TAG-REPORTCONFIGID-STOP +-- TAG-REPORTCONFIGINTERRAT-START + +ReportConfigInterRAT ::= SEQUENCE { + reportType CHOICE { + periodical PeriodicalReportConfigInterRAT, + eventTriggered EventTriggerConfigInterRAT, + reportCGI ReportCGI-EUTRA, + ..., + reportSFTD ReportSFTD-EUTRA + } +} + +ReportCGI-EUTRA ::= SEQUENCE { + cellForWhichToReportCGI EUTRA-PhysCellId, + ..., + [[ + useAutonomousGaps-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] +} + +ReportSFTD-EUTRA ::= SEQUENCE { + reportSFTD-Meas BOOLEAN, + reportRSRP BOOLEAN, + ... +} + +EventTriggerConfigInterRAT ::= SEQUENCE { + eventId CHOICE { + eventB1 SEQUENCE { + b1-ThresholdEUTRA MeasTriggerQuantityEUTRA, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + ... + }, + eventB2 SEQUENCE { + b2-Threshold1 MeasTriggerQuantity, + b2-Threshold2EUTRA MeasTriggerQuantityEUTRA, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + ... + }, + ..., + [[ + eventB1-UTRA-FDD-r16 SEQUENCE { + b1-ThresholdUTRA-FDD-r16 MeasTriggerQuantityUTRA-FDD-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger, + ... + }, + eventB2-UTRA-FDD-r16 SEQUENCE { + b2-Threshold1-r16 MeasTriggerQuantity, + b2-Threshold2UTRA-FDD-r16 MeasTriggerQuantityUTRA-FDD-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger, + ... + } + ]] + }, + rsType NR-RS-Type, + + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + ..., + [[ + reportQuantityUTRA-FDD-r16 MeasReportQuantityUTRA-FDD-r16 OPTIONAL -- Need R + ]] + + +} + +PeriodicalReportConfigInterRAT ::= SEQUENCE { + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + ..., + [[ + reportQuantityUTRA-FDD-r16 MeasReportQuantityUTRA-FDD-r16 OPTIONAL -- Need R + ]] +} + +MeasTriggerQuantityUTRA-FDD-r16 ::= CHOICE{ + utra-FDD-RSCP-r16 INTEGER (-5..91), + utra-FDD-EcN0-r16 INTEGER (0..49) +} + +MeasReportQuantityUTRA-FDD-r16 ::= SEQUENCE { + cpich-RSCP BOOLEAN, + cpich-EcN0 BOOLEAN +} + +-- TAG-REPORTCONFIGINTERRAT-STOP +-- TAG-REPORTCONFIGNR-START + +ReportConfigNR ::= SEQUENCE { + reportType CHOICE { + periodical PeriodicalReportConfig, + eventTriggered EventTriggerConfig, + ..., + reportCGI ReportCGI, + reportSFTD ReportSFTD-NR, + condTriggerConfig-r16 CondTriggerConfig-r16, + cli-Periodical-r16 CLI-PeriodicalReportConfig-r16, + cli-EventTriggered-r16 CLI-EventTriggerConfig-r16 + } +} + +ReportCGI ::= SEQUENCE { + cellForWhichToReportCGI PhysCellId, + ..., + [[ + useAutonomousGaps-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] + +} + +ReportSFTD-NR ::= SEQUENCE { + reportSFTD-Meas BOOLEAN, + reportRSRP BOOLEAN, + ..., + [[ + reportSFTD-NeighMeas ENUMERATED {true} OPTIONAL, -- Need R + drx-SFTD-NeighMeas ENUMERATED {true} OPTIONAL, -- Need R + cellsForWhichToReportSFTD SEQUENCE (SIZE (1..maxCellSFTD)) OF PhysCellId OPTIONAL -- Need R + ]] +} + +CondTriggerConfig-r16 ::= SEQUENCE { + condEventId CHOICE { + condEventA3 SEQUENCE { + a3-Offset MeasTriggerQuantityOffset, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + condEventA5 SEQUENCE { + a5-Threshold1 MeasTriggerQuantity, + a5-Threshold2 MeasTriggerQuantity, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + ... + }, + rsType-r16 NR-RS-Type, + ... +} + +EventTriggerConfig::= SEQUENCE { + eventId CHOICE { + eventA1 SEQUENCE { + a1-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + eventA2 SEQUENCE { + a2-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + eventA3 SEQUENCE { + a3-Offset MeasTriggerQuantityOffset, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA4 SEQUENCE { + a4-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA5 SEQUENCE { + a5-Threshold1 MeasTriggerQuantity, + a5-Threshold2 MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA6 SEQUENCE { + a6-Offset MeasTriggerQuantityOffset, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + ... + }, + rsType NR-RS-Type, + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantityCell MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + reportQuantityRS-Indexes MeasReportQuantity OPTIONAL, -- Need R + maxNrofRS-IndexesToReport INTEGER (1..maxNrofIndexesToReport) OPTIONAL, -- Need R + includeBeamMeasurements BOOLEAN, + reportAddNeighMeas ENUMERATED {setup} OPTIONAL, -- Need R + ..., + [[ + measRSSI-ReportConfig-r16 MeasRSSI-ReportConfig-r16 OPTIONAL, -- Need R + useT312-r16 BOOLEAN OPTIONAL, -- Need M + includeCommonLocationInfo-r16 ENUMERATED {true} OPTIONAL, -- Need R + includeBT-Meas-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + includeWLAN-Meas-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + includeSensor-Meas-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL -- Need M + ]] +} + +PeriodicalReportConfig ::= SEQUENCE { + rsType NR-RS-Type, + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantityCell MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + reportQuantityRS-Indexes MeasReportQuantity OPTIONAL, -- Need R + maxNrofRS-IndexesToReport INTEGER (1..maxNrofIndexesToReport) OPTIONAL, -- Need R + includeBeamMeasurements BOOLEAN, + useWhiteCellList BOOLEAN, + ..., + [[ + measRSSI-ReportConfig-r16 MeasRSSI-ReportConfig-r16 OPTIONAL, -- Need R + includeCommonLocationInfo-r16 ENUMERATED {true} OPTIONAL, -- Need R + includeBT-Meas-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + includeWLAN-Meas-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + includeSensor-Meas-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, -- Need M + ul-DelayValueConfig-r16 SetupRelease { UL-DelayValueConfig-r16 } OPTIONAL, -- Need M + reportAddNeighMeas-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] +} + +NR-RS-Type ::= ENUMERATED {ssb, csi-rs} + +MeasTriggerQuantity ::= CHOICE { + rsrp RSRP-Range, + rsrq RSRQ-Range, + sinr SINR-Range +} + +MeasTriggerQuantityOffset ::= CHOICE { + rsrp INTEGER (-30..30), + rsrq INTEGER (-30..30), + sinr INTEGER (-30..30) +} + + +MeasReportQuantity ::= SEQUENCE { + rsrp BOOLEAN, + rsrq BOOLEAN, + sinr BOOLEAN +} + +MeasRSSI-ReportConfig-r16 ::= SEQUENCE { + channelOccupancyThreshold-r16 RSSI-Range-r16 OPTIONAL -- Need R +} + +CLI-EventTriggerConfig-r16 ::= SEQUENCE { + eventId-r16 CHOICE { + eventI1-r16 SEQUENCE { + i1-Threshold-r16 MeasTriggerQuantityCLI-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + ... + }, + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + maxReportCLI-r16 INTEGER (1..maxCLI-Report-r16), + ... +} + +CLI-PeriodicalReportConfig-r16 ::= SEQUENCE { + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantityCLI-r16 MeasReportQuantityCLI-r16, + maxReportCLI-r16 INTEGER (1..maxCLI-Report-r16), + ... +} + +MeasTriggerQuantityCLI-r16 ::= CHOICE { + srs-RSRP-r16 SRS-RSRP-Range-r16, + cli-RSSI-r16 CLI-RSSI-Range-r16 +} + +MeasReportQuantityCLI-r16 ::= ENUMERATED {srs-rsrp, cli-rssi} + +-- TAG-REPORTCONFIGNR-STOP +-- TAG-REPORTCONFIGNR-SL-START + +ReportConfigNR-SL-r16 ::= SEQUENCE { + reportType-r16 CHOICE { + periodical-r16 PeriodicalReportConfigNR-SL-r16, + eventTriggered-r16 EventTriggerConfigNR-SL-r16 + } +} + +EventTriggerConfigNR-SL-r16::= SEQUENCE { + eventId-r16 CHOICE { + eventC1 SEQUENCE { + c1-Threshold-r16 SL-CBR-r16, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + eventC2-r16 SEQUENCE { + c2-Threshold-r16 SL-CBR-r16, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + ... + }, + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity-r16 MeasReportQuantity-r16, + ... +} + +PeriodicalReportConfigNR-SL-r16 ::= SEQUENCE { + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity-r16 MeasReportQuantity-r16, + ... +} + +MeasReportQuantity-r16 ::= SEQUENCE { + cbr-r16 BOOLEAN, + ... +} + +-- TAG-REPORTCONFIGNR-SL-STOP +-- TAG-REPORTCONFIGTOADDMODLIST-START + +ReportConfigToAddModList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigToAddMod + +ReportConfigToAddMod ::= SEQUENCE { + reportConfigId ReportConfigId, + reportConfig CHOICE { + reportConfigNR ReportConfigNR, + ..., + reportConfigInterRAT ReportConfigInterRAT, + reportConfigNR-SL-r16 ReportConfigNR-SL-r16 + } +} + +-- TAG-REPORTCONFIGTOADDMODLIST-STOP +-- TAG-REPORTINTERVAL-START + +ReportInterval ::= ENUMERATED {ms120, ms240, ms480, ms640, ms1024, ms2048, ms5120, ms10240, ms20480, ms40960, + min1,min6, min12, min30 } + +-- TAG-REPORTINTERVAL-STOP +-- TAG-RESELECTIONTHRESHOLD-START + +ReselectionThreshold ::= INTEGER (0..31) + +-- TAG-RESELECTIONTHRESHOLD-STOP +-- TAG-RESELECTIONTHRESHOLDQ-START + +ReselectionThresholdQ ::= INTEGER (0..31) + +-- TAG-RESELECTIONTHRESHOLDQ-STOP +-- TAG-RESUMECAUSE-START + +ResumeCause ::= ENUMERATED {emergency, highPriorityAccess, mt-Access, mo-Signalling, + mo-Data, mo-VoiceCall, mo-VideoCall, mo-SMS, rna-Update, mps-PriorityAccess, + mcs-PriorityAccess, spare1, spare2, spare3, spare4, spare5 } + +-- TAG-RESUMECAUSE-STOP +-- TAG-RLC-BEARERCONFIG-START + +RLC-BearerConfig ::= SEQUENCE { + logicalChannelIdentity LogicalChannelIdentity, + servedRadioBearer CHOICE { + srb-Identity SRB-Identity, + drb-Identity DRB-Identity + } OPTIONAL, -- Cond LCH-SetupOnly + reestablishRLC ENUMERATED {true} OPTIONAL, -- Need N + rlc-Config RLC-Config OPTIONAL, -- Cond LCH-Setup + mac-LogicalChannelConfig LogicalChannelConfig OPTIONAL, -- Cond LCH-Setup + ..., + [[ + rlc-Config-v1610 RLC-Config-v1610 OPTIONAL -- Need R + ]] +} + +-- TAG-RLC-BEARERCONFIG-STOP +-- TAG-RLC-CONFIG-START + +RLC-Config ::= CHOICE { + am SEQUENCE { + ul-AM-RLC UL-AM-RLC, + dl-AM-RLC DL-AM-RLC + }, + um-Bi-Directional SEQUENCE { + ul-UM-RLC UL-UM-RLC, + dl-UM-RLC DL-UM-RLC + }, + um-Uni-Directional-UL SEQUENCE { + ul-UM-RLC UL-UM-RLC + }, + um-Uni-Directional-DL SEQUENCE { + dl-UM-RLC DL-UM-RLC + }, + ... +} + +UL-AM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthAM OPTIONAL, -- Cond Reestab + t-PollRetransmit T-PollRetransmit, + pollPDU PollPDU, + pollByte PollByte, + maxRetxThreshold ENUMERATED { t1, t2, t3, t4, t6, t8, t16, t32 } +} + +DL-AM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthAM OPTIONAL, -- Cond Reestab + t-Reassembly T-Reassembly, + t-StatusProhibit T-StatusProhibit +} + +UL-UM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthUM OPTIONAL -- Cond Reestab +} + +DL-UM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthUM OPTIONAL, -- Cond Reestab + t-Reassembly T-Reassembly +} + +T-PollRetransmit ::= ENUMERATED { + ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms105, + ms110, ms115, ms120, ms125, ms130, ms135, + ms140, ms145, ms150, ms155, ms160, ms165, + ms170, ms175, ms180, ms185, ms190, ms195, + ms200, ms205, ms210, ms215, ms220, ms225, + ms230, ms235, ms240, ms245, ms250, ms300, + ms350, ms400, ms450, ms500, ms800, ms1000, + ms2000, ms4000, ms1-v1610, ms2-v1610, ms3-v1610, + ms4-v1610, spare1} + + +PollPDU ::= ENUMERATED { + p4, p8, p16, p32, p64, p128, p256, p512, p1024, p2048, p4096, p6144, p8192, p12288, p16384,p20480, + p24576, p28672, p32768, p40960, p49152, p57344, p65536, infinity, spare8, spare7, spare6, spare5, spare4, + spare3, spare2, spare1} + +PollByte ::= ENUMERATED { + kB1, kB2, kB5, kB8, kB10, kB15, kB25, kB50, kB75, + kB100, kB125, kB250, kB375, kB500, kB750, kB1000, + kB1250, kB1500, kB2000, kB3000, kB4000, kB4500, + kB5000, kB5500, kB6000, kB6500, kB7000, kB7500, + mB8, mB9, mB10, mB11, mB12, mB13, mB14, mB15, + mB16, mB17, mB18, mB20, mB25, mB30, mB40, infinity, + spare20, spare19, spare18, spare17, spare16, + spare15, spare14, spare13, spare12, spare11, + spare10, spare9, spare8, spare7, spare6, spare5, + spare4, spare3, spare2, spare1} + +T-Reassembly ::= ENUMERATED { + ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms110, + ms120, ms130, ms140, ms150, ms160, ms170, + ms180, ms190, ms200, spare1} + +T-StatusProhibit ::= ENUMERATED { + ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms105, + ms110, ms115, ms120, ms125, ms130, ms135, + ms140, ms145, ms150, ms155, ms160, ms165, + ms170, ms175, ms180, ms185, ms190, ms195, + ms200, ms205, ms210, ms215, ms220, ms225, + ms230, ms235, ms240, ms245, ms250, ms300, + ms350, ms400, ms450, ms500, ms800, ms1000, + ms1200, ms1600, ms2000, ms2400, spare2, spare1} + +SN-FieldLengthUM ::= ENUMERATED {size6, size12} +SN-FieldLengthAM ::= ENUMERATED {size12, size18} + +RLC-Config-v1610 ::= SEQUENCE { + dl-AM-RLC-v1610 DL-AM-RLC-v1610 +} + +DL-AM-RLC-v1610 ::= SEQUENCE { + t-StatusProhibit-v1610 T-StatusProhibit-v1610 OPTIONAL, -- Need N + ... +} + +T-StatusProhibit-v1610 ::= ENUMERATED { ms1, ms2, ms3, ms4, spare4, spare3, spare2, spare1} + +-- TAG-RLC-CONFIG-STOP +-- TAG-RLF-TIMERSANDCONSTANTS-START + +RLF-TimersAndConstants ::= SEQUENCE { + t310 ENUMERATED {ms0, ms50, ms100, ms200, ms500, ms1000, ms2000, ms4000, ms6000}, + n310 ENUMERATED {n1, n2, n3, n4, n6, n8, n10, n20}, + n311 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10}, + ..., + [[ + t311 ENUMERATED {ms1000, ms3000, ms5000, ms10000, ms15000, ms20000, ms30000} + ]] +} + +-- TAG-RLF-TIMERSANDCONSTANTS-STOP +-- TAG-RNTI-VALUE-START + +RNTI-Value ::= INTEGER (0..65535) + +-- TAG-RNTI-VALUE-STOP +-- TAG-RSRP-RANGE-START + +RSRP-Range ::= INTEGER(0..127) + +-- TAG-RSRP-RANGE-STOP +-- TAG-RSRQ-RANGE-START + +RSRQ-Range ::= INTEGER(0..127) + +-- TAG-RSRQ-RANGE-STOP +-- TAG-RSSI-RANGE-START + +RSSI-Range-r16 ::= INTEGER(0..76) + +-- TAG-RSSI-RANGE-STOP +-- TAG-SCELLINDEX-START + +SCellIndex ::= INTEGER (1..31) + +-- TAG-SCELLINDEX-STOP +-- TAG-SCHEDULINGREQUESTCONFIG-START + +SchedulingRequestConfig ::= SEQUENCE { + schedulingRequestToAddModList SEQUENCE (SIZE (1..maxNrofSR-ConfigPerCellGroup)) OF SchedulingRequestToAddMod + OPTIONAL, -- Need N + schedulingRequestToReleaseList SEQUENCE (SIZE (1..maxNrofSR-ConfigPerCellGroup)) OF SchedulingRequestId + OPTIONAL -- Need N +} + +SchedulingRequestToAddMod ::= SEQUENCE { + schedulingRequestId SchedulingRequestId, + sr-ProhibitTimer ENUMERATED {ms1, ms2, ms4, ms8, ms16, ms32, ms64, ms128} OPTIONAL, -- Need S + sr-TransMax ENUMERATED { n4, n8, n16, n32, n64, spare3, spare2, spare1} +} + + + +-- TAG-SCHEDULINGREQUESTCONFIG-STOP +-- TAG-SCHEDULINGREQUESTID-START + +SchedulingRequestId ::= INTEGER (0..7) + +-- TAG-SCHEDULINGREQUESTID-STOP +-- TAG-SCHEDULINGREQUESTRESOURCECONFIG-START + +SchedulingRequestResourceConfig ::= SEQUENCE { + schedulingRequestResourceId SchedulingRequestResourceId, + schedulingRequestID SchedulingRequestId, + periodicityAndOffset CHOICE { + sym2 NULL, + sym6or7 NULL, + sl1 NULL, -- Recurs in every slot + sl2 INTEGER (0..1), + sl4 INTEGER (0..3), + sl5 INTEGER (0..4), + sl8 INTEGER (0..7), + sl10 INTEGER (0..9), + sl16 INTEGER (0..15), + sl20 INTEGER (0..19), + sl40 INTEGER (0..39), + sl80 INTEGER (0..79), + sl160 INTEGER (0..159), + sl320 INTEGER (0..319), + sl640 INTEGER (0..639) + } OPTIONAL, -- Need M + resource PUCCH-ResourceId OPTIONAL -- Need M +} + +SchedulingRequestResourceConfigExt-v1610 ::= SEQUENCE { + phy-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL, -- Need M + ... +} + +-- TAG-SCHEDULINGREQUESTRESOURCECONFIG-STOP +-- TAG-SCHEDULINGREQUESTRESOURCEID-START + +SchedulingRequestResourceId ::= INTEGER (1..maxNrofSR-Resources) + +-- TAG-SCHEDULINGREQUESTRESOURCEID-STOP +-- TAG-SCRAMBLINGID-START + +ScramblingId ::= INTEGER(0..1023) + +-- TAG-SCRAMBLINGID-STOP +-- TAG-SCS-SPECIFICCARRIER-START + +SCS-SpecificCarrier ::= SEQUENCE { + offsetToCarrier INTEGER (0..2199), + subcarrierSpacing SubcarrierSpacing, + carrierBandwidth INTEGER (1..maxNrofPhysicalResourceBlocks), + ..., + [[ + txDirectCurrentLocation INTEGER (0..4095) OPTIONAL -- Need S + ]] +} + +-- TAG-SCS-SPECIFICCARRIER-STOP +-- TAG-SDAP-CONFIG-START + +SDAP-Config ::= SEQUENCE { + pdu-Session PDU-SessionID, + sdap-HeaderDL ENUMERATED {present, absent}, + sdap-HeaderUL ENUMERATED {present, absent}, + defaultDRB BOOLEAN, + mappedQoS-FlowsToAdd SEQUENCE (SIZE (1..maxNrofQFIs)) OF QFI OPTIONAL, -- Need N + mappedQoS-FlowsToRelease SEQUENCE (SIZE (1..maxNrofQFIs)) OF QFI OPTIONAL, -- Need N + ... +} + +QFI ::= INTEGER (0..maxQFI) + +PDU-SessionID ::= INTEGER (0..255) + +-- TAG-SDAP-CONFIG-STOP +-- TAG-SEARCHSPACE-START + +SearchSpace ::= SEQUENCE { + searchSpaceId SearchSpaceId, + controlResourceSetId ControlResourceSetId OPTIONAL, -- Cond SetupOnly + monitoringSlotPeriodicityAndOffset CHOICE { + sl1 NULL, + sl2 INTEGER (0..1), + sl4 INTEGER (0..3), + sl5 INTEGER (0..4), + sl8 INTEGER (0..7), + sl10 INTEGER (0..9), + sl16 INTEGER (0..15), + sl20 INTEGER (0..19), + sl40 INTEGER (0..39), + sl80 INTEGER (0..79), + sl160 INTEGER (0..159), + sl320 INTEGER (0..319), + sl640 INTEGER (0..639), + sl1280 INTEGER (0..1279), + sl2560 INTEGER (0..2559) + } OPTIONAL, -- Cond Setup + duration INTEGER (2..2559) OPTIONAL, -- Need R + monitoringSymbolsWithinSlot BIT STRING (SIZE (14)) OPTIONAL, -- Cond Setup + nrofCandidates SEQUENCE { + aggregationLevel1 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel2 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel4 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel8 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel16 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8} + } OPTIONAL, -- Cond Setup + searchSpaceType CHOICE { + common SEQUENCE { + dci-Format0-0-AndFormat1-0 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-0 SEQUENCE { + nrofCandidates-SFI SEQUENCE { + aggregationLevel1 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-1 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-2 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-3 SEQUENCE { + dummy1 ENUMERATED {sl1, sl2, sl4, sl5, sl8, sl10, sl16, sl20} OPTIONAL, -- Cond Setup + dummy2 ENUMERATED {n1, n2}, + ... + } OPTIONAL -- Need R + }, + ue-Specific SEQUENCE { + dci-Formats ENUMERATED {formats0-0-And-1-0, formats0-1-And-1-1}, + ..., + [[ + dci-Formats-MT-r16 ENUMERATED {formats2-5} OPTIONAL, -- Need R + dci-FormatsSL-r16 ENUMERATED {formats0-0-And-1-0, formats0-1-And-1-1, formats3-0, formats3-1, + formats3-0-And-3-1} OPTIONAL, -- Need R + dci-FormatsExt-r16 ENUMERATED {formats0-2-And-1-2, formats0-1-And-1-1And-0-2-And-1-2} + OPTIONAL -- Need R + ]] + } + } OPTIONAL -- Cond Setup2 +} + +SearchSpaceExt-r16 ::= SEQUENCE { + controlResourceSetId-r16 ControlResourceSetId-r16 OPTIONAL, -- Cond SetupOnly2 + searchSpaceType-r16 SEQUENCE { + common-r16 SEQUENCE { + dci-Format2-4-r16 SEQUENCE { + nrofCandidates-CI-r16 SEQUENCE { + aggregationLevel1-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-5-r16 SEQUENCE { + nrofCandidates-IAB-r16 SEQUENCE { + aggregationLevel1-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-6-r16 SEQUENCE { + ... + } OPTIONAL, -- Need R + ... + } + } OPTIONAL, -- Cond Setup3 + searchSpaceGroupIdList-r16 SEQUENCE (SIZE (1.. 2)) OF INTEGER (0..1) OPTIONAL, -- Need R + freqMonitorLocations-r16 BIT STRING (SIZE (5)) OPTIONAL -- Need R +} + +-- TAG-SEARCHSPACE-STOP +-- TAG-SEARCHSPACEID-START + +SearchSpaceId ::= INTEGER (0..maxNrofSearchSpaces-1) + +-- TAG-SEARCHSPACEID-STOP +-- TAG-SEARCHSPACEZERO-START + +SearchSpaceZero ::= INTEGER (0..15) + +-- TAG-SEARCHSPACEZERO-STOP +-- TAG-SECURITYALGORITHMCONFIG-START + +SecurityAlgorithmConfig ::= SEQUENCE { + cipheringAlgorithm CipheringAlgorithm, + integrityProtAlgorithm IntegrityProtAlgorithm OPTIONAL, -- Need R + ... +} + +IntegrityProtAlgorithm ::= ENUMERATED { + nia0, nia1, nia2, nia3, spare4, spare3, + spare2, spare1, ...} + +CipheringAlgorithm ::= ENUMERATED { + nea0, nea1, nea2, nea3, spare4, spare3, + spare2, spare1, ...} + +-- TAG-SECURITYALGORITHMCONFIG-STOP +-- TAG-SEMISTATICCHANNELACCESSCONFIG-START + +SemiStaticChannelAccessConfig-r16 ::= SEQUENCE { + period ENUMERATED {ms1, ms2, ms2dot5, ms4, ms5, ms10} +} + +-- TAG-SEMISTATICCHANNELACCESSCONFIG-STOP +-- TAG-SENSORLOCATIONINFO-START + +Sensor-LocationInfo-r16 ::= SEQUENCE { + sensor-MeasurementInformation-r16 OCTET STRING OPTIONAL, + sensor-MotionInformation-r16 OCTET STRING OPTIONAL, + ... +} + +-- TAG-SENSORLOCATIONINFO-STOP +-- TAG-SERVCELLINDEX-START + +ServCellIndex ::= INTEGER (0..maxNrofServingCells-1) + +-- TAG-SERVCELLINDEX-STOP +-- TAG-SERVINGCELLCONFIG-START + +ServingCellConfig ::= SEQUENCE { + tdd-UL-DL-ConfigurationDedicated TDD-UL-DL-ConfigDedicated OPTIONAL, -- Cond TDD + initialDownlinkBWP BWP-DownlinkDedicated OPTIONAL, -- Need M + downlinkBWP-ToReleaseList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Id OPTIONAL, -- Need N + downlinkBWP-ToAddModList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Downlink OPTIONAL, -- Need N + firstActiveDownlinkBWP-Id BWP-Id OPTIONAL, -- Cond SyncAndCellAdd + bwp-InactivityTimer ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, + ms40,ms50, ms60, ms80,ms100, ms200,ms300, ms500, + ms750, ms1280, ms1920, ms2560, spare10, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, --Need R + defaultDownlinkBWP-Id BWP-Id OPTIONAL, -- Need S + uplinkConfig UplinkConfig OPTIONAL, -- Need M + supplementaryUplink UplinkConfig OPTIONAL, -- Need M + pdcch-ServingCellConfig SetupRelease { PDCCH-ServingCellConfig } OPTIONAL, -- Need M + pdsch-ServingCellConfig SetupRelease { PDSCH-ServingCellConfig } OPTIONAL, -- Need M + csi-MeasConfig SetupRelease { CSI-MeasConfig } OPTIONAL, -- Need M + sCellDeactivationTimer ENUMERATED {ms20, ms40, ms80, ms160, ms200, ms240, + ms320, ms400, ms480, ms520, ms640, ms720, + ms840, ms1280, spare2,spare1} OPTIONAL, -- Cond ServingCellWithoutPUCCH + crossCarrierSchedulingConfig CrossCarrierSchedulingConfig OPTIONAL, -- Need M + tag-Id TAG-Id, + dummy1 ENUMERATED {enabled} OPTIONAL, -- Need R + pathlossReferenceLinking ENUMERATED {spCell, sCell} OPTIONAL, -- Cond SCellOnly + servingCellMO MeasObjectId OPTIONAL, -- Cond MeasObject + ..., + [[ + lte-CRS-ToMatchAround SetupRelease { RateMatchPatternLTE-CRS } OPTIONAL, -- Need M + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + downlinkChannelBW-PerSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier OPTIONAL -- Need S + ]], + [[ + supplementaryUplinkRelease-r16 ENUMERATED {true} OPTIONAL, -- Need N + tdd-UL-DL-ConfigurationDedicated-IAB-MT-r16 TDD-UL-DL-ConfigDedicated-IAB-MT-r16 OPTIONAL, -- Cond TDD_IAB + dormantBWP-Config-r16 SetupRelease { DormantBWP-Config-r16 } OPTIONAL, -- Need M + ca-SlotOffset-r16 CHOICE { + refSCS15kHz INTEGER (-2..2), + refSCS30KHz INTEGER (-5..5), + refSCS60KHz INTEGER (-10..10), + refSCS120KHz INTEGER (-20..20) + } OPTIONAL, -- Cond AsyncCA + dummy2 SetupRelease { DummyJ } OPTIONAL, -- Need M + intraCellGuardBandsDL-List-r16 SEQUENCE (SIZE (1..maxSCSs)) OF IntraCellGuardBandsPerSCS-r16 OPTIONAL, -- Need S + intraCellGuardBandsUL-List-r16 SEQUENCE (SIZE (1..maxSCSs)) OF IntraCellGuardBandsPerSCS-r16 OPTIONAL, -- Need S + csi-RS-ValidationWithDCI-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + lte-CRS-PatternList1-r16 SetupRelease { LTE-CRS-PatternList-r16 } OPTIONAL, -- Need M + lte-CRS-PatternList2-r16 SetupRelease { LTE-CRS-PatternList-r16 } OPTIONAL, -- Need M + crs-RateMatch-PerCORESETPoolIndex-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableTwoDefaultTCI-States-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultTCI-StatePerCoresetPoolIndex-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableBeamSwitchTiming-r16 ENUMERATED {true} OPTIONAL, -- Need R + cbg-TxDiffTBsProcessingType1-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + cbg-TxDiffTBsProcessingType2-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]], + [[ + directionalCollisionHandling-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + channelAccessConfig-r16 SetupRelease { ChannelAccessConfig-r16 } OPTIONAL -- Need M + ]] +} + +UplinkConfig ::= SEQUENCE { + initialUplinkBWP BWP-UplinkDedicated OPTIONAL, -- Need M + uplinkBWP-ToReleaseList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Id OPTIONAL, -- Need N + uplinkBWP-ToAddModList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Uplink OPTIONAL, -- Need N + firstActiveUplinkBWP-Id BWP-Id OPTIONAL, -- Cond SyncAndCellAdd + pusch-ServingCellConfig SetupRelease { PUSCH-ServingCellConfig } OPTIONAL, -- Need M + carrierSwitching SetupRelease { SRS-CarrierSwitching } OPTIONAL, -- Need M + ..., + [[ + powerBoostPi2BPSK BOOLEAN OPTIONAL, -- Need M + uplinkChannelBW-PerSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier OPTIONAL -- Need S + ]], + [[ + enablePL-RS-UpdateForPUSCH-SRS-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForPUSCH0-0-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForPUCCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForSRS-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + uplinkTxSwitching-r16 SetupRelease { UplinkTxSwitching-r16 } OPTIONAL, -- Need M + mpr-PowerBoost-FR2-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +DummyJ ::= SEQUENCE { + maxEnergyDetectionThreshold-r16 INTEGER(-85..-52), + energyDetectionThresholdOffset-r16 INTEGER (-20..-13), + ul-toDL-COT-SharingED-Threshold-r16 INTEGER (-85..-52) OPTIONAL, -- Need R + absenceOfAnyOtherTechnology-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +ChannelAccessConfig-r16 ::= SEQUENCE { + energyDetectionConfig-r16 CHOICE { + maxEnergyDetectionThreshold-r16 INTEGER (-85..-52), + energyDetectionThresholdOffset-r16 INTEGER (-13..20) + } OPTIONAL, -- Need R + ul-toDL-COT-SharingED-Threshold-r16 INTEGER (-85..-52) OPTIONAL, -- Need R + absenceOfAnyOtherTechnology-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +IntraCellGuardBandsPerSCS-r16 ::= SEQUENCE { + guardBandSCS-r16 SubcarrierSpacing, + intraCellGuardBands-r16 SEQUENCE (SIZE (1..4)) OF GuardBand-r16 +} + +GuardBand-r16 ::= SEQUENCE { + startCRB-r16 INTEGER (0..274), + nrofCRBs-r16 INTEGER (0..15) +} + +DormancyGroupID-r16 ::= INTEGER (0..4) + +DormantBWP-Config-r16::= SEQUENCE { + dormantBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + withinActiveTimeConfig-r16 SetupRelease { WithinActiveTimeConfig-r16 } OPTIONAL, -- Need M + outsideActiveTimeConfig-r16 SetupRelease { OutsideActiveTimeConfig-r16 } OPTIONAL -- Need M +} + +WithinActiveTimeConfig-r16 ::= SEQUENCE { + firstWithinActiveTimeBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + dormancyGroupWithinActiveTime-r16 DormancyGroupID-r16 OPTIONAL -- Need R +} + +OutsideActiveTimeConfig-r16 ::= SEQUENCE { + firstOutsideActiveTimeBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + dormancyGroupOutsideActiveTime-r16 DormancyGroupID-r16 OPTIONAL -- Need R +} + +UplinkTxSwitching-r16 ::= SEQUENCE { + uplinkTxSwitchingPeriodLocation-r16 BOOLEAN, + uplinkTxSwitchingCarrier-r16 ENUMERATED {carrier1, carrier2} +} + +-- TAG-SERVINGCELLCONFIG-STOP +-- TAG-SERVINGCELLCONFIGCOMMON-START + +ServingCellConfigCommon ::= SEQUENCE { + physCellId PhysCellId OPTIONAL, -- Cond HOAndServCellAdd, + downlinkConfigCommon DownlinkConfigCommon OPTIONAL, -- Cond HOAndServCellAdd + uplinkConfigCommon UplinkConfigCommon OPTIONAL, -- Need M + supplementaryUplinkConfig UplinkConfigCommon OPTIONAL, -- Need S + n-TimingAdvanceOffset ENUMERATED { n0, n25600, n39936 } OPTIONAL, -- Need S + ssb-PositionsInBurst CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)) + } OPTIONAL, -- Cond AbsFreqSSB + ssb-periodicityServingCell ENUMERATED { ms5, ms10, ms20, ms40, ms80, ms160, spare2, spare1 } OPTIONAL, -- Need S + dmrs-TypeA-Position ENUMERATED {pos2, pos3}, + lte-CRS-ToMatchAround SetupRelease { RateMatchPatternLTE-CRS } OPTIONAL, -- Need M + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + ssbSubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond HOAndServCellWithSSB + tdd-UL-DL-ConfigurationCommon TDD-UL-DL-ConfigCommon OPTIONAL, -- Cond TDD + ss-PBCH-BlockPower INTEGER (-60..50), + ..., + [[ + channelAccessMode-r16 CHOICE { + dynamic NULL, + semiStatic SemiStaticChannelAccessConfig-r16 + } OPTIONAL, -- Cond SharedSpectrum + discoveryBurstWindowLength-r16 ENUMERATED {ms0dot5, ms1, ms2, ms3, ms4, ms5} OPTIONAL, -- Need R + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + highSpeedConfig-r16 HighSpeedConfig-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SERVINGCELLCONFIGCOMMON-STOP +-- TAG-SERVINGCELLCONFIGCOMMONSIB-START + +ServingCellConfigCommonSIB ::= SEQUENCE { + downlinkConfigCommon DownlinkConfigCommonSIB, + uplinkConfigCommon UplinkConfigCommonSIB OPTIONAL, -- Need R + supplementaryUplink UplinkConfigCommonSIB OPTIONAL, -- Need R + n-TimingAdvanceOffset ENUMERATED { n0, n25600, n39936 } OPTIONAL, -- Need S + ssb-PositionsInBurst SEQUENCE { + inOneGroup BIT STRING (SIZE (8)), + groupPresence BIT STRING (SIZE (8)) OPTIONAL -- Cond FR2-Only + }, + ssb-PeriodicityServingCell ENUMERATED {ms5, ms10, ms20, ms40, ms80, ms160}, + tdd-UL-DL-ConfigurationCommon TDD-UL-DL-ConfigCommon OPTIONAL, -- Cond TDD + ss-PBCH-BlockPower INTEGER (-60..50), + ..., + [[ + channelAccessMode-r16 CHOICE { + dynamic NULL, + semiStatic SemiStaticChannelAccessConfig-r16 + } OPTIONAL, -- Cond SharedSpectrum + discoveryBurstWindowLength-r16 ENUMERATED {ms0dot5, ms1, ms2, ms3, ms4, ms5} OPTIONAL, -- Need R + highSpeedConfig-r16 HighSpeedConfig-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SERVINGCELLCONFIGCOMMONSIB-STOP +-- TAG-SHORTI-RNTI-VALUE-START + +ShortI-RNTI-Value ::= BIT STRING (SIZE(24)) + +-- TAG-SHORTI-RNTI-VALUE-STOP +-- TAG-SHORTMAC-I-START + +ShortMAC-I ::= BIT STRING (SIZE (16)) + +-- TAG-SHORTMAC-I-STOP +-- TAG-SINR-RANGE-START + +SINR-Range ::= INTEGER(0..127) + +-- TAG-SINR-RANGE-STOP +-- TAG-SI-REQUESTCONFIG-START + +SI-RequestConfig::= SEQUENCE { + rach-OccasionsSI SEQUENCE { + rach-ConfigSI RACH-ConfigGeneric, + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, four, eight, sixteen} + } OPTIONAL, -- Need R + si-RequestPeriod ENUMERATED {one, two, four, six, eight, ten, twelve, sixteen} OPTIONAL, -- Need R + si-RequestResources SEQUENCE (SIZE (1..maxSI-Message)) OF SI-RequestResources +} + +SI-RequestResources ::= SEQUENCE { + ra-PreambleStartIndex INTEGER (0..63), + ra-AssociationPeriodIndex INTEGER (0..15) OPTIONAL, -- Need R + ra-ssb-OccasionMaskIndex INTEGER (0..15) OPTIONAL -- Need R +} + +-- TAG-SI-SCHEDULINGINFO-START + +SI-SchedulingInfo ::= SEQUENCE { + schedulingInfoList SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo, + si-WindowLength ENUMERATED {s5, s10, s20, s40, s80, s160, s320, s640, s1280}, + si-RequestConfig SI-RequestConfig OPTIONAL, -- Cond MSG-1 + si-RequestConfigSUL SI-RequestConfig OPTIONAL, -- Cond SUL-MSG-1 + systemInformationAreaID BIT STRING (SIZE (24)) OPTIONAL, -- Need R + ... +} + +SchedulingInfo ::= SEQUENCE { + si-BroadcastStatus ENUMERATED {broadcasting, notBroadcasting}, + si-Periodicity ENUMERATED {rf8, rf16, rf32, rf64, rf128, rf256, rf512}, + sib-MappingInfo SIB-Mapping +} + +SIB-Mapping ::= SEQUENCE (SIZE (1..maxSIB)) OF SIB-TypeInfo + +SIB-TypeInfo ::= SEQUENCE { + type ENUMERATED {sibType2, sibType3, sibType4, sibType5, sibType6, sibType7, sibType8, sibType9, + sibType10-v1610, sibType11-v1610, sibType12-v1610, sibType13-v1610, sibType14-v1610, + spare3, spare2, spare1,... }, + valueTag INTEGER (0..31) OPTIONAL, -- Cond SIB-TYPE + areaScope ENUMERATED {true} OPTIONAL -- Need S +} + +-- TAG-SI-SCHEDULINGINFO-STOP +-- TAG-SKCOUNTER-START + +SK-Counter ::= INTEGER (0..65535) + +-- TAG-SKCOUNTER-STOP +-- TAG-SLOTFORMATCOMBINATIONSPERCELL-START + +SlotFormatCombinationsPerCell ::= SEQUENCE { + servingCellId ServCellIndex, + subcarrierSpacing SubcarrierSpacing, + subcarrierSpacing2 SubcarrierSpacing OPTIONAL, -- Need R + slotFormatCombinations SEQUENCE (SIZE (1..maxNrofSlotFormatCombinationsPerSet)) OF SlotFormatCombination + OPTIONAL, -- Need M + positionInDCI INTEGER(0..maxSFI-DCI-PayloadSize-1) OPTIONAL, -- Need M + ..., + [[ + enableConfiguredUL-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + +} + +SlotFormatCombination ::= SEQUENCE { + slotFormatCombinationId SlotFormatCombinationId, + slotFormats SEQUENCE (SIZE (1..maxNrofSlotFormatsPerCombination)) OF INTEGER (0..255) +} + +SlotFormatCombinationId ::= INTEGER (0..maxNrofSlotFormatCombinationsPerSet-1) + +-- TAG-SLOTFORMATCOMBINATIONSPERCELL-STOP +-- TAG-SLOTFORMATINDICATOR-START + +SlotFormatIndicator ::= SEQUENCE { + sfi-RNTI RNTI-Value, + dci-PayloadSize INTEGER (1..maxSFI-DCI-PayloadSize), + slotFormatCombToAddModList SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF SlotFormatCombinationsPerCell + OPTIONAL, -- Need N + slotFormatCombToReleaseList SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL, -- Need N + ..., + [[ + availableRB-SetsToAddModList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF AvailableRB-SetsPerCell-r16 OPTIONAL, -- Need N + availableRB-SetsToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL, -- Need N + switchTriggerToAddModList-r16 SEQUENCE (SIZE(1..4)) OF SearchSpaceSwitchTrigger-r16 OPTIONAL, -- Need N + switchTriggerToReleaseList-r16 SEQUENCE (SIZE(1..4)) OF ServCellIndex OPTIONAL, -- Need N + co-DurationsPerCellToAddModList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF CO-DurationsPerCell-r16 OPTIONAL, -- Need N + co-DurationsPerCellToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL -- Need N + ]] +} + +CO-DurationsPerCell-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1), + subcarrierSpacing-r16 SubcarrierSpacing, + co-DurationList-r16 SEQUENCE (SIZE(1..64)) OF CO-Duration-r16 +} + +CO-Duration-r16 ::= INTEGER (0..1120) + +AvailableRB-SetsPerCell-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1) +} + +SearchSpaceSwitchTrigger-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1) +} + +-- TAG-SLOTFORMATINDICATOR-STOP +-- TAG-S-NSSAI-START + +S-NSSAI ::= CHOICE{ + sst BIT STRING (SIZE (8)), + sst-SD BIT STRING (SIZE (32)) +} + +-- TAG-S-NSSAI-STOP +-- TAG-SPEEDSTATESCALEFACTORS-START + +SpeedStateScaleFactors ::= SEQUENCE { + sf-Medium ENUMERATED {oDot25, oDot5, oDot75, lDot0}, + sf-High ENUMERATED {oDot25, oDot5, oDot75, lDot0} +} +-- TAG-SPEEDSTATESCALEFACTORS-STOP +-- TAG-SPS-CONFIG-START + +SPS-Config ::= SEQUENCE { + periodicity ENUMERATED {ms10, ms20, ms32, ms40, ms64, ms80, ms128, ms160, ms320, ms640, + spare6, spare5, spare4, spare3, spare2, spare1}, + nrofHARQ-Processes INTEGER (1..8), + n1PUCCH-AN PUCCH-ResourceId OPTIONAL, -- Need M + mcs-Table ENUMERATED {qam64LowSE} OPTIONAL, -- Need S + ..., + [[ + sps-ConfigIndex-r16 SPS-ConfigIndex-r16 OPTIONAL, -- Cond SPS-List + harq-ProcID-Offset-r16 INTEGER (0..15) OPTIONAL, -- Need R + periodicityExt-r16 INTEGER (1..5120) OPTIONAL, -- Need R + harq-CodebookID-r16 INTEGER (1..2) OPTIONAL, -- Need R + pdsch-AggregationFactor-r16 ENUMERATED {n1, n2, n4, n8 } OPTIONAL -- Need S + ]] +} + +-- TAG-SPS-CONFIG-STOP +-- TAG-SPS-CONFIGINDEX-START + +SPS-ConfigIndex-r16 ::= INTEGER (0.. maxNrofSPS-Config-r16-1) + +-- TAG-SPS-CONFIGINDEX-STOP +-- TAG-SPS-PUCCH-AN-START + +SPS-PUCCH-AN-r16 ::= SEQUENCE { + sps-PUCCH-AN-ResourceID-r16 PUCCH-ResourceId, + maxPayloadSize-r16 INTEGER (4..256) OPTIONAL -- Need R +} + +-- TAG-SPS-PUCCH-AN-STOP +-- TAG-SPS-PUCCH-AN-LIST-START + +SPS-PUCCH-AN-List-r16 ::= SEQUENCE (SIZE(1..4)) OF SPS-PUCCH-AN-r16 + +-- TAG-SPS-PUCCH-AN-LIST-STOP +-- TAG-SRB-IDENTITY-START + +SRB-Identity ::= INTEGER (1..3) + +-- TAG-SRB-IDENTITY-STOP +-- TAG-SRS-CARRIERSWITCHING-START + +SRS-CarrierSwitching ::= SEQUENCE { + srs-SwitchFromServCellIndex INTEGER (0..31) OPTIONAL, -- Need M + srs-SwitchFromCarrier ENUMERATED {sUL, nUL}, + srs-TPC-PDCCH-Group CHOICE { + typeA SEQUENCE (SIZE (1..32)) OF SRS-TPC-PDCCH-Config, + typeB SRS-TPC-PDCCH-Config + } OPTIONAL, -- Need M + monitoringCells SEQUENCE (SIZE (1..maxNrofServingCells)) OF ServCellIndex OPTIONAL, -- Need M + ... +} + +SRS-TPC-PDCCH-Config ::= SEQUENCE { + srs-CC-SetIndexlist SEQUENCE (SIZE(1..4)) OF SRS-CC-SetIndex OPTIONAL -- Need M +} + +SRS-CC-SetIndex ::= SEQUENCE { + cc-SetIndex INTEGER (0..3) OPTIONAL, -- Need M + cc-IndexInOneCC-Set INTEGER (0..7) OPTIONAL -- Need M +} + +-- TAG-SRS-CARRIERSWITCHING-STOP +-- TAG-SRS-CONFIG-START + +SRS-Config ::= SEQUENCE { + srs-ResourceSetToReleaseList SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSetId OPTIONAL, -- Need N + srs-ResourceSetToAddModList SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSet OPTIONAL, -- Need N + srs-ResourceToReleaseList SEQUENCE (SIZE(1..maxNrofSRS-Resources)) OF SRS-ResourceId OPTIONAL, -- Need N + srs-ResourceToAddModList SEQUENCE (SIZE(1..maxNrofSRS-Resources)) OF SRS-Resource OPTIONAL, -- Need N + tpc-Accumulation ENUMERATED {disabled} OPTIONAL, -- Need S + ..., + [[ + srs-RequestDCI-1-2-r16 INTEGER (1..2) OPTIONAL, -- Need S + srs-RequestDCI-0-2-r16 INTEGER (1..2) OPTIONAL, -- Need S + srs-ResourceSetToAddModListDCI-0-2-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSet OPTIONAL, -- Need N + srs-ResourceSetToReleaseListDCI-0-2-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSetId OPTIONAL, -- Need N + srs-PosResourceSetToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResourceSets-r16)) OF SRS-PosResourceSetId-r16 + OPTIONAL, -- Need N + srs-PosResourceSetToAddModList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResourceSets-r16)) OF SRS-PosResourceSet-r16 OPTIONAL,-- Need N + srs-PosResourceToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResources-r16)) OF SRS-PosResourceId-r16 OPTIONAL,-- Need N + srs-PosResourceToAddModList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResources-r16)) OF SRS-PosResource-r16 OPTIONAL -- Need N + ]] +} + +SRS-ResourceSet ::= SEQUENCE { + srs-ResourceSetId SRS-ResourceSetId, + srs-ResourceIdList SEQUENCE (SIZE(1..maxNrofSRS-ResourcesPerSet)) OF SRS-ResourceId OPTIONAL, -- Cond Setup + resourceType CHOICE { + aperiodic SEQUENCE { + aperiodicSRS-ResourceTrigger INTEGER (1..maxNrofSRS-TriggerStates-1), + csi-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + slotOffset INTEGER (1..32) OPTIONAL, -- Need S + ..., + [[ + aperiodicSRS-ResourceTriggerList SEQUENCE (SIZE(1..maxNrofSRS-TriggerStates-2)) + OF INTEGER (1..maxNrofSRS-TriggerStates-1) OPTIONAL -- Need M + ]] + }, + semi-persistent SEQUENCE { + associatedCSI-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + ... + }, + periodic SEQUENCE { + associatedCSI-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + ... + } + }, + usage ENUMERATED {beamManagement, codebook, nonCodebook, antennaSwitching}, + alpha Alpha OPTIONAL, -- Need S + p0 INTEGER (-202..24) OPTIONAL, -- Cond Setup + pathlossReferenceRS PathlossReferenceRS-Config OPTIONAL, -- Need M + srs-PowerControlAdjustmentStates ENUMERATED { sameAsFci2, separateClosedLoop} OPTIONAL, -- Need S + ..., + [[ + pathlossReferenceRSList-r16 SetupRelease { PathlossReferenceRSList-r16} OPTIONAL -- Need M + ]] +} + +PathlossReferenceRS-Config ::= CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId +} + +PathlossReferenceRSList-r16 ::= SEQUENCE (SIZE (1..maxNrofSRS-PathlossReferenceRS-r16)) OF PathlossReferenceRS-r16 + +PathlossReferenceRS-r16 ::= SEQUENCE { + srs-PathlossReferenceRS-Id-r16 SRS-PathlossReferenceRS-Id-r16, + pathlossReferenceRS-r16 PathlossReferenceRS-Config +} + +SRS-PathlossReferenceRS-Id-r16 ::= INTEGER (0..maxNrofSRS-PathlossReferenceRS-1-r16) + +SRS-PosResourceSet-r16 ::= SEQUENCE { + srs-PosResourceSetId-r16 SRS-PosResourceSetId-r16, + srs-PosResourceIdList-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourcesPerSet)) OF SRS-PosResourceId-r16 + OPTIONAL, -- Cond Setup + resourceType-r16 CHOICE { + aperiodic-r16 SEQUENCE { + aperiodicSRS-ResourceTriggerList-r16 SEQUENCE (SIZE(1..maxNrofSRS-TriggerStates-1)) + OF INTEGER (1..maxNrofSRS-TriggerStates-1) OPTIONAL, -- Need M + ... + }, + semi-persistent-r16 SEQUENCE { + ... + }, + periodic-r16 SEQUENCE { + ... + } + }, + alpha-r16 Alpha OPTIONAL, -- Need S + p0-r16 INTEGER (-202..24) OPTIONAL, -- Cond Setup + pathlossReferenceRS-Pos-r16 CHOICE { + ssb-IndexServing-r16 SSB-Index, + ssb-Ncell-r16 SSB-InfoNcell-r16, + dl-PRS-r16 DL-PRS-Info-r16 + } OPTIONAL, -- Need M + ... +} + +SRS-ResourceSetId ::= INTEGER (0..maxNrofSRS-ResourceSets-1) + +SRS-PosResourceSetId-r16 ::= INTEGER (0..maxNrofSRS-PosResourceSets-1-r16) + +SRS-Resource ::= SEQUENCE { + srs-ResourceId SRS-ResourceId, + nrofSRS-Ports ENUMERATED {port1, ports2, ports4}, + ptrs-PortIndex ENUMERATED {n0, n1 } OPTIONAL, -- Need R + transmissionComb CHOICE { + n2 SEQUENCE { + combOffset-n2 INTEGER (0..1), + cyclicShift-n2 INTEGER (0..7) + }, + n4 SEQUENCE { + combOffset-n4 INTEGER (0..3), + cyclicShift-n4 INTEGER (0..11) + } + }, + resourceMapping SEQUENCE { + startPosition INTEGER (0..5), + nrofSymbols ENUMERATED {n1, n2, n4}, + repetitionFactor ENUMERATED {n1, n2, n4} + }, + freqDomainPosition INTEGER (0..67), + freqDomainShift INTEGER (0..268), + freqHopping SEQUENCE { + c-SRS INTEGER (0..63), + b-SRS INTEGER (0..3), + b-hop INTEGER (0..3) + }, + groupOrSequenceHopping ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceType CHOICE { + aperiodic SEQUENCE { + ... + }, + semi-persistent SEQUENCE { + periodicityAndOffset-sp SRS-PeriodicityAndOffset, + ... + }, + periodic SEQUENCE { + periodicityAndOffset-p SRS-PeriodicityAndOffset, + ... + } + }, + sequenceId INTEGER (0..1023), + spatialRelationInfo SRS-SpatialRelationInfo OPTIONAL, -- Need R + ..., + [[ + resourceMapping-r16 SEQUENCE { + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 ENUMERATED {n1, n2, n4}, + repetitionFactor-r16 ENUMERATED {n1, n2, n4} + } OPTIONAL -- Need R + ]] + +} + +SRS-PosResource-r16::= SEQUENCE { + srs-PosResourceId-r16 SRS-PosResourceId-r16, + transmissionComb-r16 CHOICE { + n2-r16 SEQUENCE { + combOffset-n2-r16 INTEGER (0..1), + cyclicShift-n2-r16 INTEGER (0..7) + }, + n4-r16 SEQUENCE { + combOffset-n4-16 INTEGER (0..3), + cyclicShift-n4-r16 INTEGER (0..11) + }, + n8-r16 SEQUENCE { + combOffset-n8-r16 INTEGER (0..7), + cyclicShift-n8-r16 INTEGER (0..5) + }, + ... + }, + resourceMapping-r16 SEQUENCE { + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 ENUMERATED {n1, n2, n4, n8, n12} + }, + freqDomainShift-r16 INTEGER (0..268), + freqHopping-r16 SEQUENCE { + c-SRS-r16 INTEGER (0..63), + ... + }, + groupOrSequenceHopping-r16 ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceType-r16 CHOICE { + aperiodic-r16 SEQUENCE { + slotOffset-r16 INTEGER (1..32) OPTIONAL, -- Need S + ... + }, + semi-persistent-r16 SEQUENCE { + periodicityAndOffset-sp-r16 SRS-PeriodicityAndOffset-r16, + ... + }, + periodic-r16 SEQUENCE { + periodicityAndOffset-p-r16 SRS-PeriodicityAndOffset-r16, + ... + } + }, + sequenceId-r16 INTEGER (0..65535), + spatialRelationInfoPos-r16 SRS-SpatialRelationInfoPos-r16 OPTIONAL, -- Need R + ... +} + +SRS-SpatialRelationInfo ::= SEQUENCE { + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId, + srs SEQUENCE { + resourceId SRS-ResourceId, + uplinkBWP BWP-Id + } + } +} + +SRS-SpatialRelationInfoPos-r16 ::= CHOICE { + servingRS-r16 SEQUENCE { + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal-r16 CHOICE { + ssb-IndexServing-r16 SSB-Index, + csi-RS-IndexServing-r16 NZP-CSI-RS-ResourceId, + srs-SpatialRelation-r16 SEQUENCE { + resourceSelection-r16 CHOICE { + srs-ResourceId-r16 SRS-ResourceId, + srs-PosResourceId-r16 SRS-PosResourceId-r16 + }, + uplinkBWP-r16 BWP-Id + } + } + }, + ssb-Ncell-r16 SSB-InfoNcell-r16, + dl-PRS-r16 DL-PRS-Info-r16 +} + +SSB-Configuration-r16 ::= SEQUENCE { + ssb-Freq-r16 ARFCN-ValueNR, + halfFrameIndex-r16 ENUMERATED {zero, one}, + ssbSubcarrierSpacing-r16 SubcarrierSpacing, + ssb-Periodicity-r16 ENUMERATED { ms5, ms10, ms20, ms40, ms80, ms160, spare2,spare1 } OPTIONAL, -- Need S + sfn0-Offset-r16 SEQUENCE { + sfn-Offset-r16 INTEGER (0..1023), + integerSubframeOffset-r16 INTEGER (0..9) OPTIONAL -- Need R + } OPTIONAL, -- Need R + sfn-SSB-Offset-r16 INTEGER (0..15), + ss-PBCH-BlockPower-r16 INTEGER (-60..50) OPTIONAL -- Cond Pathloss +} + +SSB-InfoNcell-r16 ::= SEQUENCE { + physicalCellId-r16 PhysCellId, + ssb-IndexNcell-r16 SSB-Index OPTIONAL, -- Need S + ssb-Configuration-r16 SSB-Configuration-r16 OPTIONAL -- Need S +} + +DL-PRS-Info-r16 ::= SEQUENCE { + dl-PRS-ID-r16 INTEGER (0..255), + dl-PRS-ResourceSetId-r16 INTEGER (0..7), + dl-PRS-ResourceId-r16 INTEGER (0..63) OPTIONAL -- Need S +} + +SRS-ResourceId ::= INTEGER (0..maxNrofSRS-Resources-1) +SRS-PosResourceId-r16 ::= INTEGER (0..maxNrofSRS-PosResources-1-r16) + +SRS-PeriodicityAndOffset ::= CHOICE { + sl1 NULL, + sl2 INTEGER(0..1), + sl4 INTEGER(0..3), + sl5 INTEGER(0..4), + sl8 INTEGER(0..7), + sl10 INTEGER(0..9), + sl16 INTEGER(0..15), + sl20 INTEGER(0..19), + sl32 INTEGER(0..31), + sl40 INTEGER(0..39), + sl64 INTEGER(0..63), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + sl640 INTEGER(0..639), + sl1280 INTEGER(0..1279), + sl2560 INTEGER(0..2559) +} + +SRS-PeriodicityAndOffset-r16 ::= CHOICE { + sl1 NULL, + sl2 INTEGER(0..1), + sl4 INTEGER(0..3), + sl5 INTEGER(0..4), + sl8 INTEGER(0..7), + sl10 INTEGER(0..9), + sl16 INTEGER(0..15), + sl20 INTEGER(0..19), + sl32 INTEGER(0..31), + sl40 INTEGER(0..39), + sl64 INTEGER(0..63), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + sl640 INTEGER(0..639), + sl1280 INTEGER(0..1279), + sl2560 INTEGER(0..2559), + sl5120 INTEGER(0..5119), + sl10240 INTEGER(0..10239), + sl40960 INTEGER(0..40959), + sl81920 INTEGER(0..81919), + ... +} + +-- TAG-SRS-CONFIG-STOP +-- TAG-SRS-RSRP-RANGE-START + +SRS-RSRP-Range-r16 ::= INTEGER(0..98) + +-- TAG-SRS-RSRP-RANGE-STOP +-- TAG-SRS-TPC-COMMANDCONFIG-START + +SRS-TPC-CommandConfig ::= SEQUENCE { + startingBitOfFormat2-3 INTEGER (1..31) OPTIONAL, -- Need R + fieldTypeFormat2-3 INTEGER (0..1) OPTIONAL, -- Need R + ..., + [[ + startingBitOfFormat2-3SUL INTEGER (1..31) OPTIONAL -- Need R + ]] +} + +-- TAG-SRS-TPC-COMMANDCONFIG-STOP +-- TAG-SSB-INDEX-START + +SSB-Index ::= INTEGER (0..maxNrofSSBs-1) + +-- TAG-SSB-INDEX-STOP +-- TAG-SSB-MTC-START + +SSB-MTC ::= SEQUENCE { + periodicityAndOffset CHOICE { + sf5 INTEGER (0..4), + sf10 INTEGER (0..9), + sf20 INTEGER (0..19), + sf40 INTEGER (0..39), + sf80 INTEGER (0..79), + sf160 INTEGER (0..159) + }, + duration ENUMERATED { sf1, sf2, sf3, sf4, sf5 } +} + +SSB-MTC2 ::= SEQUENCE { + pci-List SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need M + periodicity ENUMERATED {sf5, sf10, sf20, sf40, sf80, spare3, spare2, spare1} +} + +SSB-MTC2-LP-r16 ::= SEQUENCE { + pci-List SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need R + periodicity ENUMERATED {sf10, sf20, sf40, sf80, sf160, spare3, spare2, spare1} +} + +SSB-MTC3-r16 ::= SEQUENCE { + periodicityAndOffset-r16 CHOICE { + sf5-r16 INTEGER (0..4), + sf10-r16 INTEGER (0..9), + sf20-r16 INTEGER (0..19), + sf40-r16 INTEGER (0..39), + sf80-r16 INTEGER (0..79), + sf160-r16 INTEGER (0..159), + sf320-r16 INTEGER (0..319), + sf640-r16 INTEGER (0..639), + sf1280-r16 INTEGER (0..1279) + }, + duration-r16 ENUMERATED {sf1, sf2, sf3, sf4, sf5}, + pci-List-r16 SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need M + ssb-ToMeasure-r16 SetupRelease { SSB-ToMeasure } OPTIONAL -- Need M +} + + +-- TAG-SSB-MTC-STOP +-- TAG-SSB-POSITIONQCL-RELATION-START + +SSB-PositionQCL-Relation-r16 ::= ENUMERATED {n1,n2,n4,n8} + +-- TAG-SSB-POSITIONQCL-RELATION-STOP +-- TAG-SSB-TOMEASURE-START + +SSB-ToMeasure ::= CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)) +} + +-- TAG-SSB-TOMEASURE-STOP +-- TAG-SS-RSSI-MEASUREMENT-START + +SS-RSSI-Measurement ::= SEQUENCE { + measurementSlots BIT STRING (SIZE (1..80)), + endSymbol INTEGER(0..3) +} + +-- TAG-SS-RSSI-MEASUREMENT-STOP +-- TAG-SUBCARRIERSPACING-START + +SubcarrierSpacing ::= ENUMERATED {kHz15, kHz30, kHz60, kHz120, kHz240, spare3, spare2, spare1} + +-- TAG-SUBCARRIERSPACING-STOP +-- TAG-TAG-CONFIG-START + +TAG-Config ::= SEQUENCE { + tag-ToReleaseList SEQUENCE (SIZE (1..maxNrofTAGs)) OF TAG-Id OPTIONAL, -- Need N + tag-ToAddModList SEQUENCE (SIZE (1..maxNrofTAGs)) OF TAG OPTIONAL -- Need N +} + +TAG ::= SEQUENCE { + tag-Id TAG-Id, + timeAlignmentTimer TimeAlignmentTimer, + ... +} + +TAG-Id ::= INTEGER (0..maxNrofTAGs-1) + +TimeAlignmentTimer ::= ENUMERATED {ms500, ms750, ms1280, ms1920, ms2560, ms5120, ms10240, infinity} + +-- TAG-TAG-CONFIG-STOP +-- TAG-TCI-STATE-START + +TCI-State ::= SEQUENCE { + tci-StateId TCI-StateId, + qcl-Type1 QCL-Info, + qcl-Type2 QCL-Info OPTIONAL, -- Need R + ... +} + +QCL-Info ::= SEQUENCE { + cell ServCellIndex OPTIONAL, -- Need R + bwp-Id BWP-Id OPTIONAL, -- Cond CSI-RS-Indicated + referenceSignal CHOICE { + csi-rs NZP-CSI-RS-ResourceId, + ssb SSB-Index + }, + qcl-Type ENUMERATED {typeA, typeB, typeC, typeD}, + ... +} + +-- TAG-TCI-STATE-STOP +-- TAG-TCI-STATEID-START + +TCI-StateId ::= INTEGER (0..maxNrofTCI-States-1) + +-- TAG-TCI-STATEID-STOP +-- TAG-TDD-UL-DL-CONFIGCOMMON-START + +TDD-UL-DL-ConfigCommon ::= SEQUENCE { + referenceSubcarrierSpacing SubcarrierSpacing, + pattern1 TDD-UL-DL-Pattern, + pattern2 TDD-UL-DL-Pattern OPTIONAL, -- Need R + ... +} + +TDD-UL-DL-Pattern ::= SEQUENCE { + dl-UL-TransmissionPeriodicity ENUMERATED {ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms5, ms10}, + nrofDownlinkSlots INTEGER (0..maxNrofSlots), + nrofDownlinkSymbols INTEGER (0..maxNrofSymbols-1), + nrofUplinkSlots INTEGER (0..maxNrofSlots), + nrofUplinkSymbols INTEGER (0..maxNrofSymbols-1), + ..., + [[ + dl-UL-TransmissionPeriodicity-v1530 ENUMERATED {ms3, ms4} OPTIONAL -- Need R + ]] +} + +-- TAG-TDD-UL-DL-CONFIGCOMMON-STOP +-- TAG-TDD-UL-DL-CONFIGDEDICATED-START + +TDD-UL-DL-ConfigDedicated ::= SEQUENCE { + slotSpecificConfigurationsToAddModList SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotConfig OPTIONAL, -- Need N + slotSpecificConfigurationsToReleaseList SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotIndex OPTIONAL, -- Need N + ... +} + +TDD-UL-DL-ConfigDedicated-IAB-MT-r16::= SEQUENCE { + slotSpecificConfigurationsToAddModList-IAB-MT-r16 SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotConfig-IAB-MT-r16 OPTIONAL, -- Need N + slotSpecificConfigurationsToReleaseList-IAB-MT-r16 SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotIndex OPTIONAL, -- Need N + ... +} + +TDD-UL-DL-SlotConfig ::= SEQUENCE { + slotIndex TDD-UL-DL-SlotIndex, + symbols CHOICE { + allDownlink NULL, + allUplink NULL, + explicit SEQUENCE { + nrofDownlinkSymbols INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need S + nrofUplinkSymbols INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need S + } + } +} + +TDD-UL-DL-SlotConfig-IAB-MT-r16::= SEQUENCE { + slotIndex-r16 TDD-UL-DL-SlotIndex, + symbols-IAB-MT-r16 CHOICE { + allDownlink-r16 NULL, + allUplink-r16 NULL, + explicit-r16 SEQUENCE { + nrofDownlinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need S + nrofUplinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need S + }, + explicit-IAB-MT-r16 SEQUENCE { + nrofDownlinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need S + nrofUplinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need S + } + } +} + +TDD-UL-DL-SlotIndex ::= INTEGER (0..maxNrofSlots-1) + +-- TAG-TDD-UL-DL-CONFIGDEDICATED-STOP +-- TAG-TRACKINGAREACODE-START + +TrackingAreaCode ::= BIT STRING (SIZE (24)) + +-- TAG-TRACKINGAREACODE-STOP +-- TAG-TRESELECTION-START + +T-Reselection ::= INTEGER (0..7) + +-- TAG-TRESELECTION-STOP +-- TAG-TIMETOTRIGGER-START + +TimeToTrigger ::= ENUMERATED { + ms0, ms40, ms64, ms80, ms100, ms128, ms160, ms256, + ms320, ms480, ms512, ms640, ms1024, ms1280, ms2560, + ms5120} + +-- TAG-TIMETOTRIGGER-STOP +-- TAG-UAC-BARRINGINFOSETINDEX-START + +UAC-BarringInfoSetIndex ::= INTEGER (1..maxBarringInfoSet) + +-- TAG-UAC-BARRINGINFOSETINDEX-STOP +-- TAG-UAC-BARRINGINFOSETLIST-START + +UAC-BarringInfoSetList ::= SEQUENCE (SIZE(1..maxBarringInfoSet)) OF UAC-BarringInfoSet + +UAC-BarringInfoSet ::= SEQUENCE { + uac-BarringFactor ENUMERATED {p00, p05, p10, p15, p20, p25, p30, p40, + p50, p60, p70, p75, p80, p85, p90, p95}, + uac-BarringTime ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512}, + uac-BarringForAccessIdentity BIT STRING (SIZE(7)) +} + +-- TAG-UAC-BARRINGINFOSETLIST-STOP +-- TAG-UAC-BARRINGPERCATLIST-START + +UAC-BarringPerCatList ::= SEQUENCE (SIZE (1..maxAccessCat-1)) OF UAC-BarringPerCat + +UAC-BarringPerCat ::= SEQUENCE { + accessCategory INTEGER (1..maxAccessCat-1), + uac-barringInfoSetIndex UAC-BarringInfoSetIndex +} + +-- TAG-UAC-BARRINGPERCATLIST-STOP +-- TAG-UAC-BARRINGPERPLMN-LIST-START + +UAC-BarringPerPLMN-List ::= SEQUENCE (SIZE (1.. maxPLMN)) OF UAC-BarringPerPLMN + +UAC-BarringPerPLMN ::= SEQUENCE { + plmn-IdentityIndex INTEGER (1..maxPLMN), + uac-ACBarringListType CHOICE{ + uac-ImplicitACBarringList SEQUENCE (SIZE(maxAccessCat-1)) OF UAC-BarringInfoSetIndex, + uac-ExplicitACBarringList UAC-BarringPerCatList + } OPTIONAL -- Need S +} + +-- TAG-UAC-BARRINGPERPLMN-LIST-STOP +-- TAG-UE-TIMERSANDCONSTANTS-START + +UE-TimersAndConstants ::= SEQUENCE { + t300 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + t301 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + t310 ENUMERATED {ms0, ms50, ms100, ms200, ms500, ms1000, ms2000}, + n310 ENUMERATED {n1, n2, n3, n4, n6, n8, n10, n20}, + t311 ENUMERATED {ms1000, ms3000, ms5000, ms10000, ms15000, ms20000, ms30000}, + n311 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10}, + t319 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + ... +} + +-- TAG-UE-TIMERSANDCONSTANTS-STOP +-- TAG-ULDELAYVALUECONFIG-START + +UL-DelayValueConfig-r16 ::= SEQUENCE { + delay-DRBlist SEQUENCE (SIZE(1..maxDRB)) OF DRB-Identity +} + +-- TAG-ULDELAYVALUECONFIG-STOP +-- TAG-UPLINKCANCELLATION-START + +UplinkCancellation-r16 ::= SEQUENCE { + ci-RNTI-r16 RNTI-Value, + dci-PayloadSizeForCI-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16), + ci-ConfigurationPerServingCell-r16 SEQUENCE (SIZE (1..maxNrofServingCells)) OF CI-ConfigurationPerServingCell-r16, + ... +} + +CI-ConfigurationPerServingCell-r16 ::= SEQUENCE { + servingCellId ServCellIndex, + positionInDCI-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16-1), + positionInDCI-ForSUL-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16-1) OPTIONAL, -- Cond SUL-Only + ci-PayloadSize-r16 ENUMERATED {n1, n2, n4, n5, n7, n8, n10, n14, n16, n20, n28, n32, n35, n42, n56, n112}, + timeFrequencyRegion-r16 SEQUENCE { + timeDurationForCI-r16 ENUMERATED {n2, n4, n7, n14} OPTIONAL, -- Cond SymbolPeriodicity + timeGranularityForCI-r16 ENUMERATED {n1, n2, n4, n7, n14, n28}, + frequencyRegionForCI-r16 INTEGER (0..37949), + deltaOffset-r16 INTEGER (0..2), + ... + }, + uplinkCancellationPriority-v1610 ENUMERATED {enabled} OPTIONAL -- Need S +} + +-- TAG-UPLINKCANCELLATION-STOP +-- TAG-UPLINKCONFIGCOMMON-START + +UplinkConfigCommon ::= SEQUENCE { + frequencyInfoUL FrequencyInfoUL OPTIONAL, -- Cond InterFreqHOAndServCellAdd + initialUplinkBWP BWP-UplinkCommon OPTIONAL, -- Cond ServCellAdd + dummy TimeAlignmentTimer +} + +-- TAG-UPLINKCONFIGCOMMON-STOP +-- TAG-UPLINKCONFIGCOMMONSIB-START + +UplinkConfigCommonSIB ::= SEQUENCE { + frequencyInfoUL FrequencyInfoUL-SIB, + initialUplinkBWP BWP-UplinkCommon, + timeAlignmentTimerCommon TimeAlignmentTimer +} + +-- TAG-UPLINKCONFIGCOMMONSIB-STOP +-- TAG-UPLINKTXDIRECTCURRENTLIST-START + +UplinkTxDirectCurrentList ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF UplinkTxDirectCurrentCell + +UplinkTxDirectCurrentCell ::= SEQUENCE { + servCellIndex ServCellIndex, + uplinkDirectCurrentBWP SEQUENCE (SIZE (1..maxNrofBWPs)) OF UplinkTxDirectCurrentBWP, + ..., + [[ + uplinkDirectCurrentBWP-SUL SEQUENCE (SIZE (1..maxNrofBWPs)) OF UplinkTxDirectCurrentBWP OPTIONAL + ]] +} + +UplinkTxDirectCurrentBWP ::= SEQUENCE { + bwp-Id BWP-Id, + shift7dot5kHz BOOLEAN, + txDirectCurrentLocation INTEGER (0..3301) +} + +-- TAG-UPLINKTXDIRECTCURRENTLIST-STOP +-- TAG-UPLINKTXDIRECTCURRENTTWOCARRIERLIST-START + +UplinkTxDirectCurrentTwoCarrierList-r16 ::= SEQUENCE (SIZE (1..maxNrofTxDC-TwoCarrier-r16)) OF UplinkTxDirectCurrentTwoCarrier-r16 + +UplinkTxDirectCurrentTwoCarrier-r16 ::= SEQUENCE { + carrierOneInfo-r16 UplinkTxDirectCurrentCarrierInfo-r16, + carrierTwoInfo-r16 UplinkTxDirectCurrentCarrierInfo-r16, + singlePA-TxDirectCurrent-r16 UplinkTxDirectCurrentTwoCarrierInfo-r16, + secondPA-TxDirectCurrent-r16 UplinkTxDirectCurrentTwoCarrierInfo-r16 OPTIONAL +} + +UplinkTxDirectCurrentCarrierInfo-r16 ::= SEQUENCE { + servCellIndex-r16 ServCellIndex, + servCellInfo-r16 CHOICE { + bwp-Id-r16 BWP-Id, + deactivatedCarrier-r16 ENUMERATED {deactivated} + } +} + +UplinkTxDirectCurrentTwoCarrierInfo-r16 ::= SEQUENCE { + referenceCarrierIndex-r16 ServCellIndex, + shift7dot5kHz-r16 BOOLEAN, + txDirectCurrentLocation-r16 INTEGER (0..3301) +} + +-- TAG-UPLINKTXDIRECTCURRENTTWOCARRIERLIST-STOP +-- TAG-ZP-CSI-RS-RESOURCE-START + +ZP-CSI-RS-Resource ::= SEQUENCE { + zp-CSI-RS-ResourceId ZP-CSI-RS-ResourceId, + resourceMapping CSI-RS-ResourceMapping, + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, --Cond PeriodicOrSemiPersistent + ... +} + +ZP-CSI-RS-ResourceId ::= INTEGER (0..maxNrofZP-CSI-RS-Resources-1) + +-- TAG-ZP-CSI-RS-RESOURCE-STOP +-- TAG-ZP-CSI-RS-RESOURCESET-START + +ZP-CSI-RS-ResourceSet ::= SEQUENCE { + zp-CSI-RS-ResourceSetId ZP-CSI-RS-ResourceSetId, + zp-CSI-RS-ResourceIdList SEQUENCE (SIZE(1..maxNrofZP-CSI-RS-ResourcesPerSet)) OF ZP-CSI-RS-ResourceId, + ... +} + +-- TAG-ZP-CSI-RS-RESOURCESET-STOP +-- TAG-ZP-CSI-RS-RESOURCESETID-START + +ZP-CSI-RS-ResourceSetId ::= INTEGER (0..maxNrofZP-CSI-RS-ResourceSets-1) + +-- TAG-ZP-CSI-RS-RESOURCESETID-STOP +-- TAG-ACCESSSTRATUMRELEASE-START + +AccessStratumRelease ::= ENUMERATED { + rel15, rel16, spare6, spare5, spare4, spare3, spare2, spare1, ... } + +-- TAG-ACCESSSTRATUMRELEASE-STOP +-- TAG-BANDCOMBINATIONLIST-START + +BandCombinationList ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination + +BandCombinationList-v1540 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1540 + +BandCombinationList-v1550 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1550 + +BandCombinationList-v1560 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1560 + +BandCombinationList-v1570 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1570 + +BandCombinationList-v1580 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1580 + +BandCombinationList-v1590 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1590 + +BandCombinationList-v1610 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1610 + +BandCombinationList-v1630 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1630 + +BandCombinationList-v1640 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1640 + +BandCombinationList-UplinkTxSwitch-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-UplinkTxSwitch-r16 + +BandCombinationList-UplinkTxSwitch-v1630 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-UplinkTxSwitch-v1630 + +BandCombinationList-UplinkTxSwitch-v1640 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-UplinkTxSwitch-v1640 + +BandCombination ::= SEQUENCE { + bandList SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters, + featureSetCombination FeatureSetCombinationId, + ca-ParametersEUTRA CA-ParametersEUTRA OPTIONAL, + ca-ParametersNR CA-ParametersNR OPTIONAL, + mrdc-Parameters MRDC-Parameters OPTIONAL, + supportedBandwidthCombinationSet BIT STRING (SIZE (1..32)) OPTIONAL, + powerClass-v1530 ENUMERATED {pc2} OPTIONAL +} + +BandCombination-v1540::= SEQUENCE { + bandList-v1540 SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters-v1540, + ca-ParametersNR-v1540 CA-ParametersNR-v1540 OPTIONAL +} + +BandCombination-v1550 ::= SEQUENCE { + ca-ParametersNR-v1550 CA-ParametersNR-v1550 +} +BandCombination-v1560::= SEQUENCE { + ne-DC-BC ENUMERATED {supported} OPTIONAL, + ca-ParametersNRDC CA-ParametersNRDC OPTIONAL, + ca-ParametersEUTRA-v1560 CA-ParametersEUTRA-v1560 OPTIONAL, + ca-ParametersNR-v1560 CA-ParametersNR-v1560 OPTIONAL +} + +BandCombination-v1570 ::= SEQUENCE { + ca-ParametersEUTRA-v1570 CA-ParametersEUTRA-v1570 +} + +BandCombination-v1580 ::= SEQUENCE { + mrdc-Parameters-v1580 MRDC-Parameters-v1580 +} + +BandCombination-v1590::= SEQUENCE { + supportedBandwidthCombinationSetIntraENDC BIT STRING (SIZE (1..32)) OPTIONAL, + mrdc-Parameters-v1590 MRDC-Parameters-v1590 +} + +BandCombination-v1610 ::= SEQUENCE { + bandList-v1610 SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters-v1610 OPTIONAL, + ca-ParametersNR-v1610 CA-ParametersNR-v1610 OPTIONAL, + ca-ParametersNRDC-v1610 CA-ParametersNRDC-v1610 OPTIONAL, + powerClass-v1610 ENUMERATED {pc1dot5} OPTIONAL, + powerClassNRPart-r16 ENUMERATED {pc1, pc2, pc3, pc5} OPTIONAL, + featureSetCombinationDAPS-r16 FeatureSetCombinationId OPTIONAL, + mrdc-Parameters-v1620 MRDC-Parameters-v1620 OPTIONAL +} + +BandCombination-v1630 ::= SEQUENCE { + ca-ParametersNR-v1630 CA-ParametersNR-v1630 OPTIONAL, + ca-ParametersNRDC-v1630 CA-ParametersNRDC-v1630 OPTIONAL, + mrdc-Parameters-v1630 MRDC-Parameters-v1630 OPTIONAL, + supportedTxBandCombListPerBC-Sidelink-r16 BIT STRING (SIZE (1..maxBandComb)) OPTIONAL, + supportedRxBandCombListPerBC-Sidelink-r16 BIT STRING (SIZE (1..maxBandComb)) OPTIONAL, + scalingFactorTxSidelink-r16 SEQUENCE (SIZE (1..maxBandComb)) OF ScalingFactorSidelink-r16 OPTIONAL, + scalingFactorRxSidelink-r16 SEQUENCE (SIZE (1..maxBandComb)) OF ScalingFactorSidelink-r16 OPTIONAL +} + +BandCombination-v1640 ::= SEQUENCE { + ca-ParametersNR-v1640 CA-ParametersNR-v1640 OPTIONAL, + ca-ParametersNRDC-v1640 CA-ParametersNRDC-v1640 OPTIONAL +} + +BandCombination-UplinkTxSwitch-r16 ::= SEQUENCE { + bandCombination-r16 BandCombination, + bandCombination-v1540 BandCombination-v1540 OPTIONAL, + bandCombination-v1560 BandCombination-v1560 OPTIONAL, + bandCombination-v1570 BandCombination-v1570 OPTIONAL, + bandCombination-v1580 BandCombination-v1580 OPTIONAL, + bandCombination-v1590 BandCombination-v1590 OPTIONAL, + bandCombination-v1610 BandCombination-v1610 OPTIONAL, + supportedBandPairListNR-r16 SEQUENCE (SIZE (1..maxULTxSwitchingBandPairs)) OF ULTxSwitchingBandPair-r16, + uplinkTxSwitching-OptionSupport-r16 ENUMERATED {switchedUL, dualUL, both} OPTIONAL, + uplinkTxSwitching-PowerBoosting-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +BandCombination-UplinkTxSwitch-v1630 ::= SEQUENCE { + bandCombination-v1630 BandCombination-v1630 OPTIONAL +} + +BandCombination-UplinkTxSwitch-v1640 ::= SEQUENCE { + bandCombination-v1640 BandCombination-v1640 OPTIONAL +} + +ULTxSwitchingBandPair-r16 ::= SEQUENCE { + bandIndexUL1-r16 INTEGER(1..maxSimultaneousBands), + bandIndexUL2-r16 INTEGER(1..maxSimultaneousBands), + uplinkTxSwitchingPeriod-r16 ENUMERATED {n35us, n140us, n210us}, + uplinkTxSwitching-DL-Interruption-r16 BIT STRING (SIZE(1..maxSimultaneousBands)) OPTIONAL +} + +BandParameters ::= CHOICE { + eutra SEQUENCE { + bandEUTRA FreqBandIndicatorEUTRA, + ca-BandwidthClassDL-EUTRA CA-BandwidthClassEUTRA OPTIONAL, + ca-BandwidthClassUL-EUTRA CA-BandwidthClassEUTRA OPTIONAL + }, + nr SEQUENCE { + bandNR FreqBandIndicatorNR, + ca-BandwidthClassDL-NR CA-BandwidthClassNR OPTIONAL, + ca-BandwidthClassUL-NR CA-BandwidthClassNR OPTIONAL + } +} + +BandParameters-v1540 ::= SEQUENCE { + srs-CarrierSwitch CHOICE { + nr SEQUENCE { + srs-SwitchingTimesListNR SEQUENCE (SIZE (1..maxSimultaneousBands)) OF SRS-SwitchingTimeNR + }, + eutra SEQUENCE { + srs-SwitchingTimesListEUTRA SEQUENCE (SIZE (1..maxSimultaneousBands)) OF SRS-SwitchingTimeEUTRA + } + } OPTIONAL, + srs-TxSwitch SEQUENCE { + supportedSRS-TxPortSwitch ENUMERATED {t1r2, t1r4, t2r4, t1r4-t2r4, t1r1, t2r2, t4r4, notSupported}, + txSwitchImpactToRx INTEGER (1..32) OPTIONAL, + txSwitchWithAnotherBand INTEGER (1..32) OPTIONAL + } OPTIONAL +} + +BandParameters-v1610 ::= SEQUENCE { + srs-TxSwitch-v1610 SEQUENCE { + supportedSRS-TxPortSwitch-v1610 ENUMERATED {t1r1-t1r2, t1r1-t1r2-t1r4, t1r1-t1r2-t2r2-t2r4, t1r1-t1r2-t2r2-t1r4-t2r4, + t1r1-t2r2, t1r1-t2r2-t4r4} + } OPTIONAL +} + +ScalingFactorSidelink-r16 ::= ENUMERATED {f0p4, f0p75, f0p8, f1} + +-- TAG-BANDCOMBINATIONLIST-STOP +-- TAG-BANDCOMBINATIONLISTSIDELINKEUTRANR-START + +BandCombinationListSidelinkEUTRA-NR-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationParametersSidelinkEUTRA-NR-r16 + +BandCombinationListSidelinkEUTRA-NR-v1630 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationParametersSidelinkEUTRA-NR-v1630 + +BandCombinationParametersSidelinkEUTRA-NR-r16 ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParametersSidelinkEUTRA-NR-r16 + +BandCombinationParametersSidelinkEUTRA-NR-v1630 ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParametersSidelinkEUTRA-NR-v1630 + +BandParametersSidelinkEUTRA-NR-r16 ::= CHOICE { + eutra SEQUENCE { + bandParametersSidelinkEUTRA1-r16 OCTET STRING OPTIONAL, + bandParametersSidelinkEUTRA2-r16 OCTET STRING OPTIONAL + }, + nr SEQUENCE { + bandParametersSidelinkNR-r16 BandParametersSidelink-r16 + } +} + +BandParametersSidelinkEUTRA-NR-v1630 ::= CHOICE { + eutra NULL, + nr SEQUENCE { + tx-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + rx-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + sl-CrossCarrierScheduling-r16 ENUMERATED {supported} OPTIONAL + } +} + +BandParametersSidelink-r16 ::= SEQUENCE { + freqBandSidelink-r16 FreqBandIndicatorNR +} + +-- TAG-BANDCOMBINATIONLISTSIDELINKEUTRANR-STOP +-- TAG-CA-BANDWIDTHCLASSEUTRA-START + +CA-BandwidthClassEUTRA ::= ENUMERATED {a, b, c, d, e, f, ...} + +-- TAG-CA-BANDWIDTHCLASSEUTRA-STOP +-- TAG-CA-BANDWIDTHCLASSNR-START + +CA-BandwidthClassNR ::= ENUMERATED {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, ...} + +-- TAG-CA-BANDWIDTHCLASSNR-STOP +-- TAG-CA-PARAMETERSEUTRA-START + +CA-ParametersEUTRA ::= SEQUENCE { + multipleTimingAdvance ENUMERATED {supported} OPTIONAL, + simultaneousRx-Tx ENUMERATED {supported} OPTIONAL, + supportedNAICS-2CRS-AP BIT STRING (SIZE (1..8)) OPTIONAL, + additionalRx-Tx-PerformanceReq ENUMERATED {supported} OPTIONAL, + ue-CA-PowerClass-N ENUMERATED {class2} OPTIONAL, + supportedBandwidthCombinationSetEUTRA-v1530 BIT STRING (SIZE (1..32)) OPTIONAL, + ... +} + +CA-ParametersEUTRA-v1560 ::= SEQUENCE { + fd-MIMO-TotalWeightedLayers INTEGER (2..128) OPTIONAL +} + +CA-ParametersEUTRA-v1570 ::= SEQUENCE { + dl-1024QAM-TotalWeightedLayers INTEGER (0..10) OPTIONAL +} + +-- TAG-CA-PARAMETERSEUTRA-STOP +-- TAG-CA-PARAMETERSNR-START + +CA-ParametersNR ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL, + parallelTxSRS-PUCCH-PUSCH ENUMERATED {supported} OPTIONAL, + parallelTxPRACH-SRS-PUCCH-PUSCH ENUMERATED {supported} OPTIONAL, + simultaneousRxTxInterBandCA ENUMERATED {supported} OPTIONAL, + simultaneousRxTxSUL ENUMERATED {supported} OPTIONAL, + diffNumerologyAcrossPUCCH-Group ENUMERATED {supported} OPTIONAL, + diffNumerologyWithinPUCCH-GroupSmallerSCS ENUMERATED {supported} OPTIONAL, + supportedNumberTAG ENUMERATED {n2, n3, n4} OPTIONAL, + ... +} + +CA-ParametersNR-v1540 ::= SEQUENCE { + simultaneousSRS-AssocCSI-RS-AllCC INTEGER (5..32) OPTIONAL, + csi-RS-IM-ReceptionForFeedbackPerBandComb SEQUENCE { + maxNumberSimultaneousNZP-CSI-RS-ActBWP-AllCC INTEGER (1..64) OPTIONAL, + totalNumberPortsSimultaneousNZP-CSI-RS-ActBWP-AllCC INTEGER (2..256) OPTIONAL + } OPTIONAL, + simultaneousCSI-ReportsAllCC INTEGER (5..32) OPTIONAL, + dualPA-Architecture ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1550 ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1560 ::= SEQUENCE { + diffNumerologyWithinPUCCH-GroupLargerSCS ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1610 ::= SEQUENCE { + -- R1 9-3: Parallel MsgA and SRS/PUCCH/PUSCH transmissions across CCs in inter-band CA + parallelTxMsgA-SRS-PUCCH-PUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 9-4: MsgA operation in a band combination including SUL + msgA-SUL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9c: Joint search space group switching across multiple cells + jointSearchSpaceGroupSwitchingAcrossCells-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-5: Half-duplex UE behaviour in TDD CA for same SCS + half-DuplexTDD-CA-SameSCS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-4: SCell dormancy within active time + scellDormancyWithinActiveTime-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-4a: SCell dormancy outside active time + scellDormancyOutsideActiveTime-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-6: Cross-carrier A-CSI RS triggering with different SCS + crossCarrierA-CSI-trigDiffSCS-r16 ENUMERATED {higherA-CSI-SCS,lowerA-CSI-SCS,both} OPTIONAL, + -- R1 18-6a: Default QCL assumption for cross-carrier A-CSI-RS triggering + defaultQCL-CrossCarrierA-CSI-Trig-r16 ENUMERATED {diffOnly, both} OPTIONAL, + -- R1 18-7: CA with non-aligned frame boundaries for inter-band CA + interCA-NonAlignedFrame-r16 ENUMERATED {supported} OPTIONAL, + simul-SRS-Trans-BC-r16 ENUMERATED {n2} OPTIONAL, + interFreqDAPS-r16 SEQUENCE { + interFreqAsyncDAPS-r16 ENUMERATED {supported} OPTIONAL, + interFreqDiffSCS-DAPS-r16 ENUMERATED {supported} OPTIONAL, + interFreqMultiUL-TransmissionDAPS-r16 ENUMERATED {supported} OPTIONAL, + interFreqSemiStaticPowerSharingDAPS-Mode1-r16 ENUMERATED {supported} OPTIONAL, + interFreqSemiStaticPowerSharingDAPS-Mode2-r16 ENUMERATED {supported} OPTIONAL, + interFreqDynamicPowerSharingDAPS-r16 ENUMERATED {short, long} OPTIONAL, + interFreqUL-TransCancellationDAPS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + codebookParametersPerBC-r16 CodebookParameters-v1610 OPTIONAL, + -- R1 16-2a-10 Value of R for BD/CCE + blindDetectFactor-r16 INTEGER (1..2) OPTIONAL, + -- R1 11-2a: Capability on the number of CCs for monitoring a maximum number of BDs and non-overlapped CCEs per span when configured + -- with DL CA with Rel-16 PDCCH monitoring capability on all the serving cells + pdcch-MonitoringCA-r16 SEQUENCE { + maxNumberOfMonitoringCC-r16 INTEGER (2..16), + supportedSpanArrangement-r16 ENUMERATED {alignedOnly, alignedAndNonAligned} + } OPTIONAL, + -- R1 11-2c: Number of carriers for CCE/BD scaling with DL CA with mix of Rel. 16 and Rel. 15 PDCCH monitoring capabilities on + -- different carriers + pdcch-BlindDetectionCA-Mixed-r16 SEQUENCE { + pdcch-BlindDetectionCA1-r16 INTEGER (1..15), + pdcch-BlindDetectionCA2-r16 INTEGER (1..15), + supportedSpanArrangement-r16 ENUMERATED {alignedOnly, alignedAndNonAligned} + } OPTIONAL, + -- R1 11-2d: Capability on the number of CCs for monitoring a maximum number of BDs and non-overlapped CCEs per span for MCG and for + -- SCG when configured for NR-DC operation with Rel-16 PDCCH monitoring capability on all the serving cells + pdcch-BlindDetectionMCG-UE-r16 INTEGER (1..14) OPTIONAL, + pdcch-BlindDetectionSCG-UE-r16 INTEGER (1..14) OPTIONAL, + -- R1 11-2e: Number of carriers for CCE/BD scaling for MCG and for SCG when configured for NR-DC operation with mix of Rel. 16 and + -- Rel. 15 PDCCH monitoring capabilities on different carriers + pdcch-BlindDetectionMCG-UE-Mixed-r16 SEQUENCE { + pdcch-BlindDetectionMCG-UE1-r16 INTEGER (0..15), + pdcch-BlindDetectionMCG-UE2-r16 INTEGER (0..15) + } OPTIONAL, + pdcch-BlindDetectionSCG-UE-Mixed-r16 SEQUENCE { + pdcch-BlindDetectionSCG-UE1-r16 INTEGER (0..15), + pdcch-BlindDetectionSCG-UE2-r16 INTEGER (0..15) + } OPTIONAL, + -- R1 18-5 cross-carrier scheduling with different SCS in DL CA + crossCarrierSchedulingDL-DiffSCS-r16 ENUMERATED {low-to-high, high-to-low, both} OPTIONAL, + -- R1 18-5a Default QCL assumption for cross-carrier scheduling + crossCarrierSchedulingDefaultQCL-r16 ENUMERATED {diff-only, both} OPTIONAL, + -- R1 18-5b cross-carrier scheduling with different SCS in UL CA + crossCarrierSchedulingUL-DiffSCS-r16 ENUMERATED {low-to-high, high-to-low, both} OPTIONAL, + -- R1 13.19a Simultaneous positioning SRS and MIMO SRS transmission for a given BC + simul-SRS-MIMO-Trans-BC-r16 ENUMERATED {n2} OPTIONAL, + -- R1 16-3a, 16-3a-1, 16-3b, 16-3b-1: New Individual Codebook + codebookParametersAdditionPerBC-r16 CodebookParametersAdditionPerBC-r16 OPTIONAL, + -- R1 16-8: Mixed codebook + codebookComboParametersAdditionPerBC-r16 CodebookComboParametersAdditionPerBC-r16 OPTIONAL +} + +CA-ParametersNR-v1630 ::= SEQUENCE { + -- R1 22-5b: Simultaneous transmission of SRS for antenna switching and SRS for CB/NCB /BM for inter-band UL CA + -- R1 22-5d: Simultaneous transmission of SRS for antenna switching for inter-band UL CA + simulTX-SRS-AntSwitchingInterBandUL-CA-r16 SimulSRS-ForAntennaSwitching-r16 OPTIONAL, + -- R4 8-5: supported beam management type for inter-band CA + beamManagementType-r16 ENUMERATED {ibm, cbm} OPTIONAL, + -- R4 7-3a: UL frequency separation class with aggregate BW and Gap BW + intraBandFreqSeparationUL-AggBW-GapBW-r16 ENUMERATED {classI, classII, classIII} OPTIONAL, + -- RAN 89: Case B in case of Inter-band CA with non-aligned frame boundaries + interCA-NonAlignedFrame-B-r16 ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1640 ::= SEQUENCE { + -- R4 7-5: Support of reporting UL Tx DC locations for uplink intra-band CA. + uplinkTxDC-TwoCarrierReport-r16 ENUMERATED {supported} OPTIONAL, + -- RAN 22-6: Support of up to 3 different numerologies in the same NR PUCCH group for NR part of EN-DC, NGEN-DC, NE-DC and NR-CA + -- where UE is not configured with two NR PUCCH groups + maxUpTo3Diff-NumerologiesConfigSinglePUCCH-grp-r16 PUCCH-Grp-CarrierTypes-r16 OPTIONAL, + -- RAN 22-6a: Support of up to 4 different numerologies in the same NR PUCCH group for NR part of EN-DC, NGEN-DC, NE-DC and NR-CA + -- where UE is not configured with two NR PUCCH groups + maxUpTo4Diff-NumerologiesConfigSinglePUCCH-grp-r16 PUCCH-Grp-CarrierTypes-r16 OPTIONAL, + -- RAN 22-7: Support two PUCCH groups for NR-CA with 3 or more bands with at least two carrier types + twoPUCCH-Grp-ConfigurationsList-r16 SEQUENCE (SIZE (1..maxTwoPUCCH-Grp-ConfigList-r16)) OF TwoPUCCH-Grp-Configurations-r16 OPTIONAL, + -- R1 22-7a: Different numerology across NR PUCCH groups + diffNumerologyAcrossPUCCH-Group-CarrierTypes-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-7b: Different numerologies across NR carriers within the same NR PUCCH group, with PUCCH on a carrier of smaller SCS + diffNumerologyWithinPUCCH-GroupSmallerSCS-CarrierTypes-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-7c: Different numerologies across NR carriers within the same NR PUCCH group, with PUCCH on a carrier of larger SCS + diffNumerologyWithinPUCCH-GroupLargerSCS-CarrierTypes-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-2f: add the replicated FGs of 11-2a/c with restriction for non-aligned span case + -- with DL CA with Rel-16 PDCCH monitoring capability on all the serving cells + pdcch-MonitoringCA-NonAlignedSpan-r16 INTEGER (2..16) OPTIONAL, + -- R1 11-2g: add the replicated FGs of 11-2a/c with restriction for non-aligned span case + pdcch-BlindDetectionCA-Mixed-NonAlignedSpan-r16 SEQUENCE { + pdcch-BlindDetectionCA1-r16 INTEGER (1..15), + pdcch-BlindDetectionCA2-r16 INTEGER (1..15) + } OPTIONAL +} + +SimulSRS-ForAntennaSwitching-r16 ::= SEQUENCE { + supportSRS-xTyR-xLessThanY-r16 ENUMERATED {supported} OPTIONAL, + supportSRS-xTyR-xEqualToY-r16 ENUMERATED {supported} OPTIONAL, + supportSRS-AntennaSwitching-r16 ENUMERATED {supported} OPTIONAL +} + +TwoPUCCH-Grp-Configurations-r16 ::= SEQUENCE { + pucch-PrimaryGroupMapping-r16 TwoPUCCH-Grp-ConfigParams-r16, + pucch-SecondaryGroupMapping-r16 TwoPUCCH-Grp-ConfigParams-r16 +} + +TwoPUCCH-Grp-ConfigParams-r16 ::= SEQUENCE { + pucch-GroupMapping-r16 PUCCH-Grp-CarrierTypes-r16, + pucch-TX-r16 PUCCH-Grp-CarrierTypes-r16 +} + +PUCCH-Grp-CarrierTypes-r16 ::= SEQUENCE { + fr1-NonSharedTDD-r16 ENUMERATED {supported} OPTIONAL, + fr1-SharedTDD-r16 ENUMERATED {supported} OPTIONAL, + fr1-NonSharedFDD-r16 ENUMERATED {supported} OPTIONAL, + fr2-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-CA-PARAMETERSNR-STOP +-- TAG-CA-PARAMETERS-NRDC-START + +CA-ParametersNRDC ::= SEQUENCE { + ca-ParametersNR-ForDC CA-ParametersNR OPTIONAL, + ca-ParametersNR-ForDC-v1540 CA-ParametersNR-v1540 OPTIONAL, + ca-ParametersNR-ForDC-v1550 CA-ParametersNR-v1550 OPTIONAL, + ca-ParametersNR-ForDC-v1560 CA-ParametersNR-v1560 OPTIONAL, + featureSetCombinationDC FeatureSetCombinationId OPTIONAL +} + +CA-ParametersNRDC-v1610 ::= SEQUENCE { + -- R1 18-1: Semi-static power sharing mode1 between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-PwrSharingMode1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-1a: Semi-static power sharing mode 2 between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-PwrSharingMode2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-1b: Dynamic power sharing between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-DynamicPwrSharing-r16 ENUMERATED {short, long} OPTIONAL, + asyncNRDC-r16 ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNRDC-v1630 ::= SEQUENCE { + ca-ParametersNR-ForDC-v1610 CA-ParametersNR-v1610 OPTIONAL, + ca-ParametersNR-ForDC-v1630 CA-ParametersNR-v1630 OPTIONAL +} + +CA-ParametersNRDC-v1640 ::= SEQUENCE { + ca-ParametersNR-ForDC-v1640 CA-ParametersNR-v1640 OPTIONAL +} + +-- TAG-CA-PARAMETERS-NRDC-STOP +-- TAG-CARRIERAGGREGATIONVARIANT-START + +CarrierAggregationVariant ::= SEQUENCE { + fr1fdd-FR1TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR2TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL, + fr1tdd-FR2TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1tdd-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL +} + +-- TAG-CARRIERAGGREGATIONVARIANT-STOP +-- TAG-CODEBOOKPARAMETERS-START + +CodebookParameters ::= SEQUENCE { + type1 SEQUENCE { + singlePanel SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + modes ENUMERATED {mode1, mode1andMode2}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) + }, + multiPanel SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + modes ENUMERATED {mode1, mode2, both}, + nrofPanels ENUMERATED {n2, n4}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) + } OPTIONAL + }, + type2 SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + amplitudeSubsetRestriction ENUMERATED {supported} OPTIONAL + } OPTIONAL, + type2-PortSelection SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband} + } OPTIONAL +} + +CodebookParameters-v1610 ::= SEQUENCE { + supportedCSI-RS-ResourceListAlt-r16 SEQUENCE { + type1-SinglePanel-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type1-MultiPanel-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type2-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type2-PortSelection-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL + } OPTIONAL +} + +CodebookParametersAddition-r16 ::= SEQUENCE { + etype2-r16 SEQUENCE { + -- R1 16-3a Regular eType 2 R=1 + etype2R1-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF + INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + }, + -- R1 16-3a-1 Regular eType 2 R=2 + etype2R2-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF + INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + -- R1 16-3a-2: Support of parameter combinations 7-8 + paramComb7-8-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-3a-3: Support of rank 3,4 + rank3-4-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-3a-4: CBSR with soft amplitude restriction + amplitudeSubsetRestriction-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + etype2-PS-r16 SEQUENCE { + -- R1 16-3b Regular eType 2 R=1 PortSelection + etype2R1-PortSelection-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF + INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + }, + -- R1 16-3b-1 Regular eType 2 R=2 PortSelection + etype2R2-PortSelection-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF + INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + -- R1 16-3b-2: Support of rank 3,4 + rank3-4-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL +} + +CodebookComboParametersAddition-r16 ::= SEQUENCE { + -- R1 16-8 Mixed codebook types + type1SP-Type2-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-Type2PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-eType2R1-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-eType2R2-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-eType2R1PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-eType2R2PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-Type2-Type2PS-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-Type2-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-Type2PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-eType2R1-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-eType2R2-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-eType2R1PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-eType2R2PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-Type2-Type2PS-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL +} + +CodebookParametersAdditionPerBC-r16::= SEQUENCE { + -- R1 16-3a Regular eType 2 R=1 + etype2R1-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + -- R1 16-3a-1 Regular eType 2 R=2 + etype2R2-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + -- R1 16-3b Regular eType 2 R=1 PortSelection + etype2R1-PortSelection-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + -- R1 16-3b-1 Regular eType 2 R=2 PortSelection + etype2R2-PortSelection-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL +} + +CodebookComboParametersAdditionPerBC-r16::= SEQUENCE { + -- R1 16-8 Mixed codebook types + type1SP-Type2-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-Type2PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-eType2R1-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-eType2R2-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-eType2R1PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-eType2R2PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-Type2-Type2PS-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-Type2-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-Type2PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-eType2R1-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-eType2R2-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-eType2R1PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-eType2R2PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-Type2-Type2PS-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL +} + +CodebookVariantsList-r16 ::= SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesAlt-r16)) OF SupportedCSI-RS-Resource + +SupportedCSI-RS-Resource ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p2, p4, p8, p12, p16, p24, p32}, + maxNumberResourcesPerBand INTEGER (1..64), + totalNumberTxPortsPerBand INTEGER (2..256) +} + +-- TAG-CODEBOOKPARAMETERS-STOP +-- TAG-FEATURESETCOMBINATION-START + +FeatureSetCombination ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF FeatureSetsPerBand + +FeatureSetsPerBand ::= SEQUENCE (SIZE (1..maxFeatureSetsPerBand)) OF FeatureSet + +FeatureSet ::= CHOICE { + eutra SEQUENCE { + downlinkSetEUTRA FeatureSetEUTRA-DownlinkId, + uplinkSetEUTRA FeatureSetEUTRA-UplinkId + }, + nr SEQUENCE { + downlinkSetNR FeatureSetDownlinkId, + uplinkSetNR FeatureSetUplinkId + } +} + +-- TAG-FEATURESETCOMBINATION-STOP +-- TAG-FEATURESETCOMBINATIONID-START + +FeatureSetCombinationId ::= INTEGER (0.. maxFeatureSetCombinations) + +-- TAG-FEATURESETCOMBINATIONID-STOP +-- TAG-FEATURESETDOWNLINK-START + +FeatureSetDownlink ::= SEQUENCE { + featureSetListPerDownlinkCC SEQUENCE (SIZE (1..maxNrofServingCells)) OF FeatureSetDownlinkPerCC-Id, + + intraBandFreqSeparationDL FreqSeparationClass OPTIONAL, + scalingFactor ENUMERATED {f0p4, f0p75, f0p8} OPTIONAL, + dummy8 ENUMERATED {supported} OPTIONAL, + scellWithoutSSB ENUMERATED {supported} OPTIONAL, + csi-RS-MeasSCellWithoutSSB ENUMERATED {supported} OPTIONAL, + dummy1 ENUMERATED {supported} OPTIONAL, + type1-3-CSS ENUMERATED {supported} OPTIONAL, + pdcch-MonitoringAnyOccasions ENUMERATED {withoutDCI-Gap, withDCI-Gap} OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + ue-SpecificUL-DL-Assignment ENUMERATED {supported} OPTIONAL, + searchSpaceSharingCA-DL ENUMERATED {supported} OPTIONAL, + timeDurationForQCL SEQUENCE { + scs-60kHz ENUMERATED {s7, s14, s28} OPTIONAL, + scs-120kHz ENUMERATED {s14, s28} OPTIONAL + } OPTIONAL, + pdsch-ProcessingType1-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + dummy3 DummyA OPTIONAL, + dummy4 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyB OPTIONAL, + dummy5 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyC OPTIONAL, + dummy6 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyD OPTIONAL, + dummy7 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyE OPTIONAL +} + +FeatureSetDownlink-v1540 ::= SEQUENCE { + oneFL-DMRS-TwoAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + additionalDMRS-DL-Alt ENUMERATED {supported} OPTIONAL, + twoFL-DMRS-TwoAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-ThreeAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + pdcch-MonitoringAnyOccasionsWithSpanGap SEQUENCE { + scs-15kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-30kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-60kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-120kHz ENUMERATED {set1, set2, set3} OPTIONAL + } OPTIONAL, + pdsch-SeparationWithGap ENUMERATED {supported} OPTIONAL, + pdsch-ProcessingType2 SEQUENCE { + scs-15kHz ProcessingParameters OPTIONAL, + scs-30kHz ProcessingParameters OPTIONAL, + scs-60kHz ProcessingParameters OPTIONAL + } OPTIONAL, + pdsch-ProcessingType2-Limited SEQUENCE { + differentTB-PerSlot-SCS-30kHz ENUMERATED {upto1, upto2, upto4, upto7} + } OPTIONAL, + dl-MCS-TableAlt-DynamicIndication ENUMERATED {supported} OPTIONAL +} + +FeatureSetDownlink-v15a0 ::= SEQUENCE { + supportedSRS-Resources SRS-Resources OPTIONAL +} + +FeatureSetDownlink-v1610 ::= SEQUENCE { + -- R1 22-4e/4f/4g/4h: CBG based reception for DL with unicast PDSCH(s) per slot per CC with UE processing time Capability 1 + cbgPDSCH-ProcessingType1-DifferentTB-PerSlot-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-30kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-60kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-120kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + + -- R1 22-3e/3f/3g/3h: CBG based reception for DL with unicast PDSCH(s) per slot per CC with UE processing time Capability 2 + cbgPDSCH-ProcessingType2-DifferentTB-PerSlot-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-30kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-60kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-120kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + intraFreqDAPS-r16 SEQUENCE { + intraFreqDiffSCS-DAPS-r16 ENUMERATED {supported} OPTIONAL, + intraFreqAsyncDAPS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + intraBandFreqSeparationDL-v1620 FreqSeparationClassDL-v1620 OPTIONAL, + intraBandFreqSeparationDL-Only-r16 FreqSeparationClassDL-Only-r16 OPTIONAL, + + -- R1 11-2: Rel-16 PDCCH monitoring capability + pdcch-Monitoring-r16 SEQUENCE { + pdsch-ProcessingType1-r16 SEQUENCE { + scs-15kHz-r16 PDCCH-MonitoringOccasions-r16 OPTIONAL, + scs-30kHz-r16 PDCCH-MonitoringOccasions-r16 OPTIONAL + } OPTIONAL, + pdsch-ProcessingType2-r16 SEQUENCE { + scs-15kHz-r16 PDCCH-MonitoringOccasions-r16 OPTIONAL, + scs-30kHz-r16 PDCCH-MonitoringOccasions-r16 OPTIONAL + } OPTIONAL + } OPTIONAL, + + -- R1 11-2b: Mix of Rel. 16 PDCCH monitoring capability and Rel. 15 PDCCH monitoring capability on different carriers + pdcch-MonitoringMixed-r16 ENUMERATED {supported} OPTIONAL, + + -- R1 18-5c: Processing up to X unicast DCI scheduling for DL per scheduled CC + crossCarrierSchedulingProcessing-DiffSCS-r16 SEQUENCE { + scs-15kHz-120kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-15kHz-60kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-30kHz-120kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-15kHz-30kHz-r16 ENUMERATED {n2} OPTIONAL, + scs-30kHz-60kHz-r16 ENUMERATED {n2} OPTIONAL, + scs-60kHz-120kHz-r16 ENUMERATED {n2} OPTIONAL + } OPTIONAL, + + -- R1 16-2b-1: Support of single-DCI based SDM scheme + singleDCI-SDM-scheme-r16 ENUMERATED {supported} OPTIONAL +} + +PDCCH-MonitoringOccasions-r16 ::= SEQUENCE { + period7span3-r16 ENUMERATED {supported} OPTIONAL, + period4span3-r16 ENUMERATED {supported} OPTIONAL, + period2span2-r16 ENUMERATED {supported} OPTIONAL +} + +DummyA ::= SEQUENCE { + maxNumberNZP-CSI-RS-PerCC INTEGER (1..32), + maxNumberPortsAcrossNZP-CSI-RS-PerCC ENUMERATED {p2, p4, p8, p12, p16, p24, p32, p40, p48, p56, p64, p72, p80, + p88, p96, p104, p112, p120, p128, p136, p144, p152, p160, p168, + p176, p184, p192, p200, p208, p216, p224, p232, p240, p248, p256}, + maxNumberCS-IM-PerCC ENUMERATED {n1, n2, n4, n8, n16, n32}, + maxNumberSimultaneousCSI-RS-ActBWP-AllCC ENUMERATED {n5, n6, n7, n8, n9, n10, n12, n14, n16, n18, n20, n22, n24, n26, + n28, n30, n32, n34, n36, n38, n40, n42, n44, n46, n48, n50, n52, + n54, n56, n58, n60, n62, n64}, + totalNumberPortsSimultaneousCSI-RS-ActBWP-AllCC ENUMERATED {p8, p12, p16, p24, p32, p40, p48, p56, p64, p72, p80, + p88, p96, p104, p112, p120, p128, p136, p144, p152, p160, p168, + p176, p184, p192, p200, p208, p216, p224, p232, p240, p248, p256} +} + +DummyB ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p2, p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + supportedCodebookMode ENUMERATED {mode1, mode1AndMode2}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyC ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p8, p16, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + supportedCodebookMode ENUMERATED {mode1, mode2, both}, + supportedNumberPanels ENUMERATED {n2, n4}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyD ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + amplitudeSubsetRestriction ENUMERATED {supported} OPTIONAL, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyE ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +-- TAG-FEATURESETDOWNLINK-STOP +-- TAG-FEATURESETDOWNLINKID-START + +FeatureSetDownlinkId ::= INTEGER (0..maxDownlinkFeatureSets) + +-- TAG-FEATURESETDOWNLINKID-STOP +-- TAG-FEATURESETDOWNLINKPERCC-START + +FeatureSetDownlinkPerCC ::= SEQUENCE { + supportedSubcarrierSpacingDL SubcarrierSpacing, + supportedBandwidthDL SupportedBandwidth, + channelBW-90mhz ENUMERATED {supported} OPTIONAL, + maxNumberMIMO-LayersPDSCH MIMO-LayersDL OPTIONAL, + supportedModulationOrderDL ModulationOrder OPTIONAL +} + +FeatureSetDownlinkPerCC-v1620 ::= SEQUENCE { + -- R1 16-2a: Mulit-DCI based multi-TRP + multiDCI-MultiTRP-r16 MultiDCI-MultiTRP-r16 OPTIONAL, + -- R1 16-2b-3: Support of single-DCI based FDMSchemeB + supportFDM-SchemeB-r16 ENUMERATED {supported} OPTIONAL +} + +MultiDCI-MultiTRP-r16 ::= SEQUENCE { + maxNumberCORESET-r16 ENUMERATED {n2, n3, n4, n5}, + maxNumberCORESETPerPoolIndex-r16 INTEGER (1..3), + maxNumberUnicastPDSCH-PerPool-r16 ENUMERATED {n1, n2, n3, n4, n7} +} + +-- TAG-FEATURESETDOWNLINKPERCC-STOP +-- TAG-FEATURESETDOWNLINKPERCC-ID-START + +FeatureSetDownlinkPerCC-Id ::= INTEGER (1..maxPerCC-FeatureSets) + +-- TAG-FEATURESETDOWNLINKPERCC-ID-STOP +-- TAG-FEATURESETEUTRADOWNLINKID-START + +FeatureSetEUTRA-DownlinkId ::= INTEGER (0..maxEUTRA-DL-FeatureSets) + +-- TAG-FEATURESETEUTRADOWNLINKID-STOP +-- TAG-FEATURESETEUTRAUPLINKID-START + +FeatureSetEUTRA-UplinkId ::= INTEGER (0..maxEUTRA-UL-FeatureSets) + +-- TAG-FEATURESETEUTRAUPLINKID-STOP +-- TAG-FEATURESETS-START + +FeatureSets ::= SEQUENCE { + featureSetsDownlink SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink OPTIONAL, + featureSetsDownlinkPerCC SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetDownlinkPerCC OPTIONAL, + featureSetsUplink SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink OPTIONAL, + featureSetsUplinkPerCC SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetUplinkPerCC OPTIONAL, + ..., + [[ + featureSetsDownlink-v1540 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v1540 OPTIONAL, + featureSetsUplink-v1540 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1540 OPTIONAL, + featureSetsUplinkPerCC-v1540 SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetUplinkPerCC-v1540 OPTIONAL + ]], + [[ + featureSetsDownlink-v15a0 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v15a0 OPTIONAL + ]], + [[ + featureSetsDownlink-v1610 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v1610 OPTIONAL, + featureSetsUplink-v1610 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1610 OPTIONAL, + featureSetDownlinkPerCC-v1620 SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetDownlinkPerCC-v1620 OPTIONAL + ]], + [[ + featureSetsUplink-v1630 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1630 OPTIONAL + ]], + [[ + featureSetsUplink-v1640 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1640 OPTIONAL + ]] +} + +-- TAG-FEATURESETS-STOP +-- TAG-FEATURESETUPLINK-START + +FeatureSetUplink ::= SEQUENCE { + featureSetListPerUplinkCC SEQUENCE (SIZE (1.. maxNrofServingCells)) OF FeatureSetUplinkPerCC-Id, + scalingFactor ENUMERATED {f0p4, f0p75, f0p8} OPTIONAL, + dummy3 ENUMERATED {supported} OPTIONAL, + intraBandFreqSeparationUL FreqSeparationClass OPTIONAL, + searchSpaceSharingCA-UL ENUMERATED {supported} OPTIONAL, + dummy1 DummyI OPTIONAL, + supportedSRS-Resources SRS-Resources OPTIONAL, + twoPUCCH-Group ENUMERATED {supported} OPTIONAL, + dynamicSwitchSUL ENUMERATED {supported} OPTIONAL, + simultaneousTxSUL-NonSUL ENUMERATED {supported} OPTIONAL, + pusch-ProcessingType1-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + dummy2 DummyF OPTIONAL +} + +FeatureSetUplink-v1540 ::= SEQUENCE { + zeroSlotOffsetAperiodicSRS ENUMERATED {supported} OPTIONAL, + pa-PhaseDiscontinuityImpacts ENUMERATED {supported} OPTIONAL, + pusch-SeparationWithGap ENUMERATED {supported} OPTIONAL, + pusch-ProcessingType2 SEQUENCE { + scs-15kHz ProcessingParameters OPTIONAL, + scs-30kHz ProcessingParameters OPTIONAL, + scs-60kHz ProcessingParameters OPTIONAL + } OPTIONAL, + ul-MCS-TableAlt-DynamicIndication ENUMERATED {supported} OPTIONAL +} + +FeatureSetUplink-v1610 ::= SEQUENCE { + -- R1 11-5: PUsCH repetition Type B + pusch-RepetitionTypeB-r16 SEQUENCE { + maxNumberPUSCH-Tx-r16 ENUMERATED {n2, n3, n4, n7, n8, n12}, + hoppingScheme-r16 ENUMERATED {interSlotHopping, interRepetitionHopping, both} + } OPTIONAL, + -- R1 11-7: UL cancelation scheme for self-carrier + ul-CancellationSelfCarrier-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-7a: UL cancelation scheme for cross-carrier + ul-CancellationCrossCarrier-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-5c: The maximum number of SRS resources in one SRS resource set with usage set to 'codebook' for Mode 2 + ul-FullPwrMode2-MaxSRS-ResInSet-r16 ENUMERATED {n1, n2, n4} OPTIONAL, + + -- R1 22-4a/4b/4c/4d: CBG based transmission for UL with unicast PUSCH(s) per slot per CC with UE processing time Capability 1 + cbgPUSCH-ProcessingType1-DifferentTB-PerSlot-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-30kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-60kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-120kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + + -- R1 22-3a/3b/3c/3d: CBG based transmission for UL with unicast PUSCH(s) per slot per CC with UE processing time Capability 2 + cbgPUSCH-ProcessingType2-DifferentTB-PerSlot-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-30kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-60kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-120kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + supportedSRS-PosResources-r16 SRS-AllPosResources-r16 OPTIONAL, + intraFreqDAPS-UL-r16 SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL, + intraFreqTwoTAGs-DAPS-r16 ENUMERATED {supported} OPTIONAL, + dummy1 ENUMERATED {supported} OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + dummy3 ENUMERATED {short, long} OPTIONAL + } OPTIONAL, + intraBandFreqSeparationUL-v1620 FreqSeparationClassUL-v1620 OPTIONAL, + + -- R1 11-3: More than one PUCCH for HARQ-ACK transmission within a slot + multiPUCCH-r16 SEQUENCE { + sub-SlotConfig-NCP-r16 ENUMERATED {set1, set2} OPTIONAL, + sub-SlotConfig-ECP-r16 ENUMERATED {set1, set2} OPTIONAL + } OPTIONAL, + -- R1 11-3c: 2 PUCCH of format 0 or 2 for a single 7*2-symbol subslot based HARQ-ACK codebook + twoPUCCH-Type1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-3d: 2 PUCCH of format 0 or 2 for a single 2*7-symbol subslot based HARQ-ACK codebook + twoPUCCH-Type2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-3e: 1 PUCCH format 0 or 2 and 1 PUCCH format 1, 3 or 4 in the same subslot for a single 2*7-symbol HARQ-ACK codebooks + twoPUCCH-Type3-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-3f: 2 PUCCH transmissions in the same subslot for a single 2*7-symbol HARQ-ACK codebooks which are not covered by 11-3d and + -- 11-3e + twoPUCCH-Type4-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-3g: SR/HARQ-ACK multiplexing once per subslot using a PUCCH (or HARQ-ACK piggybacked on a PUSCH) when SR/HARQ-ACK + -- are supposed to be sent with different starting symbols in a subslot + mux-SR-HARQ-ACK-r16 ENUMERATED {supported} OPTIONAL, + dummy1 ENUMERATED {supported} OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + -- R1 11-4c: 2 PUCCH of format 0 or 2 for two HARQ-ACK codebooks with one 7*2-symbol sub-slot based HARQ-ACK codebook + twoPUCCH-Type5-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4d: 2 PUCCH of format 0 or 2 in consecutive symbols for two HARQ-ACK codebooks with one 2*7-symbol sub-slot based HARQ-ACK + -- codebook + twoPUCCH-Type6-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4e: 2 PUCCH of format 0 or 2 for two subslot based HARQ-ACK codebooks + twoPUCCH-Type7-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4f: 1 PUCCH format 0 or 2 and 1 PUCCH format 1, 3 or 4 in the same subslot for HARQ-ACK codebooks with one 2*7-symbol + -- subslot based HARQ-ACK codebook + twoPUCCH-Type8-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4g: 1 PUCCH format 0 or 2 and 1 PUCCH format 1, 3 or 4 in the same subslot for two subslot based HARQ-ACK codebooks + twoPUCCH-Type9-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4h: 2 PUCCH transmissions in the same subslot for two HARQ-ACK codebooks with one 2*7-symbol subslot which are not covered + -- by 11-4c and 11-4e + twoPUCCH-Type10-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4i: 2 PUCCH transmissions in the same subslot for two subslot based HARQ-ACK codebooks which are not covered by 11-4d and + -- 11-4f + twoPUCCH-Type11-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-1: UL intra-UE multiplexing/prioritization of overlapping channel/signals with two priority levels in physical layer + ul-IntraUE-Mux-r16 SEQUENCE { + pusch-PreparationLowPriority-r16 ENUMERATED {sym0, sym1, sym2}, + pusch-PreparationHighPriority-r16 ENUMERATED {sym0, sym1, sym2} + } OPTIONAL, + -- R1 16-5a: Supported UL full power transmission mode of fullpower + ul-FullPwrMode-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-5d: Processing up to X unicast DCI scheduling for UL per scheduled CC + crossCarrierSchedulingProcessing-DiffSCS-r16 SEQUENCE { + scs-15kHz-120kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-15kHz-60kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-30kHz-120kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-15kHz-30kHz-r16 ENUMERATED {n2} OPTIONAL, + scs-30kHz-60kHz-r16 ENUMERATED {n2} OPTIONAL, + scs-60kHz-120kHz-r16 ENUMERATED {n2} OPTIONAL + } OPTIONAL, + -- R1 16-5b: Supported UL full power transmission mode of fullpowerMode1 + ul-FullPwrMode1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-5c-2: Ports configuration for Mode 2 + ul-FullPwrMode2-SRSConfig-diffNumSRSPorts-r16 ENUMERATED {p1-2, p1-4, p1-2-4} OPTIONAL, + -- R1 16-5c-3: TPMI group for Mode 2 + ul-FullPwrMode2-TPMIGroup-r16 SEQUENCE { + twoPorts-r16 BIT STRING(SIZE(2)) OPTIONAL, + fourPortsNonCoherent-r16 ENUMERATED{g0, g1, g2, g3} OPTIONAL, + fourPortsPartialCoherent-r16 ENUMERATED{g0, g1, g2, g3, g4, g5, g6} OPTIONAL + } OPTIONAL +} + +FeatureSetUplink-v1630 ::= SEQUENCE { + -- R1 22-8: For SRS for CB PUSCH and antenna switching on FR1 with symbol level offset for aperiodic SRS transmission + offsetSRS-CB-PUSCH-Ant-Switch-fr1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-8a: PDCCH monitoring on any span of up to 3 consecutive OFDM symbols of a slot and constrained timeline for SRS for CB + -- PUSCH and antenna switching on FR1 + offsetSRS-CB-PUSCH-PDCCH-MonitorSingleOcc-fr1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-8b: For type 1 CSS with dedicated RRC configuration, type 3 CSS, and UE-SS, monitoring occasion can be any OFDM symbol(s) + -- of a slot for Case 2 and constrained timeline for SRS for CB PUSCH and antenna switching on FR1 + offsetSRS-CB-PUSCH-PDCCH-MonitorAnyOccWithoutGap-fr1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-8c: For type 1 CSS with dedicated RRC configuration, type 3 CSS, and UE-SS, monitoring occasion can be any OFDM symbol(s) + -- of a slot for Case 2 with a DCI gap and constrained timeline for SRS for CB PUSCH and antenna switching on FR1 + offsetSRS-CB-PUSCH-PDCCH-MonitorAnyOccWithGap-fr1-r16 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + -- R1 22-9: Cancellation of PUCCH, PUSCH or PRACH with a DCI scheduling a PDSCH or CSI-RS or a DCI format 2_0 for SFI + partialCancellationPUCCH-PUSCH-PRACH-TX-r16 ENUMERATED {supported} OPTIONAL +} + +FeatureSetUplink-v1640 ::= SEQUENCE { + -- R1 11-4: Two HARQ-ACK codebooks with up to one sub-slot based HARQ-ACK codebook (i.e. slot-based + slot-based, or slot-based + + -- sub-slot based) simultaneously constructed for supporting HARQ-ACK codebooks with different priorities at a UE + twoHARQ-ACK-Codebook-type1-r16 SubSlot-Config-r16 OPTIONAL, + -- R1 11-4a: Two sub-slot based HARQ-ACK codebooks simultaneously constructed for supporting HARQ-ACK codebooks with different + -- priorities at a UE + twoHARQ-ACK-Codebook-type2-r16 SubSlot-Config-r16 OPTIONAL, + -- R1 22-8d: All PDCCH monitoring occasion can be any OFDM symbol(s) of a slot for Case 2 with a span gap and constrained timeline + -- for SRS for CB PUSCH and antenna switching on FR1 + offsetSRS-CB-PUSCH-PDCCH-MonitorAnyOccWithSpanGap-fr1-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {set1, set2, set3} OPTIONAL, + scs-30kHz-r16 ENUMERATED {set1, set2, set3} OPTIONAL, + scs-60kHz-r16 ENUMERATED {set1, set2, set3} OPTIONAL + } OPTIONAL +} + +SubSlot-Config-r16 ::= SEQUENCE { + sub-SlotConfig-NCP-r16 ENUMERATED {n4,n5,n6,n7} OPTIONAL, + sub-SlotConfig-ECP-r16 ENUMERATED {n4,n5,n6} OPTIONAL +} + +SRS-AllPosResources-r16 ::= SEQUENCE { + srs-PosResources-r16 SRS-PosResources-r16, + srs-PosResourceAP-r16 SRS-PosResourceAP-r16 OPTIONAL, + srs-PosResourceSP-r16 SRS-PosResourceSP-r16 OPTIONAL +} + +SRS-PosResources-r16 ::= SEQUENCE { + maxNumberSRS-PosResourceSetPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n12, n16}, + maxNumberSRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberSRS-ResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14}, + maxNumberPeriodicSRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberPeriodicSRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-PosResourceAP-r16 ::= SEQUENCE { + maxNumberAP-SRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberAP-SRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-PosResourceSP-r16 ::= SEQUENCE { + maxNumberSP-SRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberSP-SRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-Resources ::= SEQUENCE { + maxNumberAperiodicSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberAperiodicSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberPeriodicSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberPeriodicSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberSemiPersistentSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberSemiPersistentSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberSRS-Ports-PerResource ENUMERATED {n1, n2, n4} +} + +DummyF ::= SEQUENCE { + maxNumberPeriodicCSI-ReportPerBWP INTEGER (1..4), + maxNumberAperiodicCSI-ReportPerBWP INTEGER (1..4), + maxNumberSemiPersistentCSI-ReportPerBWP INTEGER (0..4), + simultaneousCSI-ReportsAllCC INTEGER (5..32) +} + +-- TAG-FEATURESETUPLINK-STOP +-- TAG-FEATURESETUPLINKID-START + +FeatureSetUplinkId ::= INTEGER (0..maxUplinkFeatureSets) + +-- TAG-FEATURESETUPLINKID-STOP +-- TAG-FEATURESETUPLINKPERCC-START + +FeatureSetUplinkPerCC ::= SEQUENCE { + supportedSubcarrierSpacingUL SubcarrierSpacing, + supportedBandwidthUL SupportedBandwidth, + channelBW-90mhz ENUMERATED {supported} OPTIONAL, + mimo-CB-PUSCH SEQUENCE { + maxNumberMIMO-LayersCB-PUSCH MIMO-LayersUL OPTIONAL, + maxNumberSRS-ResourcePerSet INTEGER (1..2) + } OPTIONAL, + maxNumberMIMO-LayersNonCB-PUSCH MIMO-LayersUL OPTIONAL, + supportedModulationOrderUL ModulationOrder OPTIONAL +} +FeatureSetUplinkPerCC-v1540 ::= SEQUENCE { + mimo-NonCB-PUSCH SEQUENCE { + maxNumberSRS-ResourcePerSet INTEGER (1..4), + maxNumberSimultaneousSRS-ResourceTx INTEGER (1..4) + } OPTIONAL +} + +-- TAG-FEATURESETUPLINKPERCC-STOP +-- TAG-FEATURESETUPLINKPERCC-ID-START + +FeatureSetUplinkPerCC-Id ::= INTEGER (1..maxPerCC-FeatureSets) + +-- TAG-FEATURESETUPLINKPERCC-ID-STOP +-- TAG-FREQBANDINDICATOREUTRA-START + +FreqBandIndicatorEUTRA ::= INTEGER (1..maxBandsEUTRA) + +-- TAG-FREQBANDINDICATOREUTRA-STOP +-- TAG-FREQBANDLIST-START + +FreqBandList ::= SEQUENCE (SIZE (1..maxBandsMRDC)) OF FreqBandInformation + +FreqBandInformation ::= CHOICE { + bandInformationEUTRA FreqBandInformationEUTRA, + bandInformationNR FreqBandInformationNR +} + +FreqBandInformationEUTRA ::= SEQUENCE { + bandEUTRA FreqBandIndicatorEUTRA, + ca-BandwidthClassDL-EUTRA CA-BandwidthClassEUTRA OPTIONAL, -- Need N + ca-BandwidthClassUL-EUTRA CA-BandwidthClassEUTRA OPTIONAL -- Need N +} + +FreqBandInformationNR ::= SEQUENCE { + bandNR FreqBandIndicatorNR, + maxBandwidthRequestedDL AggregatedBandwidth OPTIONAL, -- Need N + maxBandwidthRequestedUL AggregatedBandwidth OPTIONAL, -- Need N + maxCarriersRequestedDL INTEGER (1..maxNrofServingCells) OPTIONAL, -- Need N + maxCarriersRequestedUL INTEGER (1..maxNrofServingCells) OPTIONAL -- Need N +} + +AggregatedBandwidth ::= ENUMERATED {mhz50, mhz100, mhz150, mhz200, mhz250, mhz300, mhz350, + mhz400, mhz450, mhz500, mhz550, mhz600, mhz650, mhz700, mhz750, mhz800} + +-- TAG-FREQBANDLIST-STOP +-- TAG-FREQSEPARATIONCLASS-START + +FreqSeparationClass ::= ENUMERATED { mhz800, mhz1200, mhz1400, ...} + +FreqSeparationClassDL-v1620 ::= ENUMERATED {mhz1000, mhz1600, mhz1800, mhz2000, mhz2200, mhz2400} + +FreqSeparationClassUL-v1620 ::= ENUMERATED {mhz1000} + +-- TAG-FREQSEPARATIONCLASS-STOP +-- TAG-FREQSEPARATIONCLASSDL-Only-START + +FreqSeparationClassDL-Only-r16 ::= ENUMERATED {mhz200, mhz400, mhz600, mhz800, mhz1000, mhz1200} + +-- TAG-FREQSEPARATIONCLASSDL-Only-STOP +-- TAG-HIGHSPEEDPARAMETERS-START + +HighSpeedParameters-r16 ::= SEQUENCE { + measurementEnhancement-r16 ENUMERATED {supported} OPTIONAL, + demodulationEnhancement-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-HIGHSPEEDPARAMETERS-STOP +-- TAG-IMS-PARAMETERS-START + +IMS-Parameters ::= SEQUENCE { + ims-ParametersCommon IMS-ParametersCommon OPTIONAL, + ims-ParametersFRX-Diff IMS-ParametersFRX-Diff OPTIONAL, + ... +} + +IMS-ParametersCommon ::= SEQUENCE { + voiceOverEUTRA-5GC ENUMERATED {supported} OPTIONAL, + ..., + [[ + voiceOverSCG-BearerEUTRA-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + voiceFallbackIndicationEPS-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +IMS-ParametersFRX-Diff ::= SEQUENCE { + voiceOverNR ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-IMS-PARAMETERS-STOP +-- TAG-INTERRAT-PARAMETERS-START + +InterRAT-Parameters ::= SEQUENCE { + eutra EUTRA-Parameters OPTIONAL, + ..., + [[ + utra-FDD-r16 UTRA-FDD-Parameters-r16 OPTIONAL + ]] + +} + +EUTRA-Parameters ::= SEQUENCE { + supportedBandListEUTRA SEQUENCE (SIZE (1..maxBandsEUTRA)) OF FreqBandIndicatorEUTRA, + eutra-ParametersCommon EUTRA-ParametersCommon OPTIONAL, + eutra-ParametersXDD-Diff EUTRA-ParametersXDD-Diff OPTIONAL, + ... +} + +EUTRA-ParametersCommon ::= SEQUENCE { + mfbi-EUTRA ENUMERATED {supported} OPTIONAL, + modifiedMPR-BehaviorEUTRA BIT STRING (SIZE (32)) OPTIONAL, + multiNS-Pmax-EUTRA ENUMERATED {supported} OPTIONAL, + rs-SINR-MeasEUTRA ENUMERATED {supported} OPTIONAL, + ..., + [[ + ne-DC ENUMERATED {supported} OPTIONAL + ]], + [[ + nr-HO-ToEN-DC-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +EUTRA-ParametersXDD-Diff ::= SEQUENCE { + rsrqMeasWidebandEUTRA ENUMERATED {supported} OPTIONAL, + ... +} + +UTRA-FDD-Parameters-r16 ::= SEQUENCE { + supportedBandListUTRA-FDD-r16 SEQUENCE (SIZE (1..maxBandsUTRA-FDD-r16)) OF SupportedBandUTRA-FDD-r16, + ... +} + +SupportedBandUTRA-FDD-r16 ::= ENUMERATED { + bandI, bandII, bandIII, bandIV, bandV, bandVI, + bandVII, bandVIII, bandIX, bandX, bandXI, + bandXII, bandXIII, bandXIV, bandXV, bandXVI, + bandXVII, bandXVIII, bandXIX, bandXX, + bandXXI, bandXXII, bandXXIII, bandXXIV, + bandXXV, bandXXVI, bandXXVII, bandXXVIII, + bandXXIX, bandXXX, bandXXXI, bandXXXII} + +-- TAG-INTERRAT-PARAMETERS-STOP +-- TAG-MAC-PARAMETERS-START + +MAC-Parameters ::= SEQUENCE { + mac-ParametersCommon MAC-ParametersCommon OPTIONAL, + mac-ParametersXDD-Diff MAC-ParametersXDD-Diff OPTIONAL +} + +MAC-Parameters-v1610 ::= SEQUENCE { + mac-ParametersFRX-Diff-r16 MAC-ParametersFRX-Diff-r16 OPTIONAL +} + +MAC-ParametersCommon ::= SEQUENCE { + lcp-Restriction ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + lch-ToSCellRestriction ENUMERATED {supported} OPTIONAL, + ..., + [[ + recommendedBitRate ENUMERATED {supported} OPTIONAL, + recommendedBitRateQuery ENUMERATED {supported} OPTIONAL + ]], + [[ + recommendedBitRateMultiplier-r16 ENUMERATED {supported} OPTIONAL, + preEmptiveBSR-r16 ENUMERATED {supported} OPTIONAL, + autonomousTransmission-r16 ENUMERATED {supported} OPTIONAL, + lch-PriorityBasedPrioritization-r16 ENUMERATED {supported} OPTIONAL, + lch-ToConfiguredGrantMapping-r16 ENUMERATED {supported} OPTIONAL, + lch-ToGrantPriorityRestriction-r16 ENUMERATED {supported} OPTIONAL, + singlePHR-P-r16 ENUMERATED {supported} OPTIONAL, + ul-LBT-FailureDetectionRecovery-r16 ENUMERATED {supported} OPTIONAL, + -- R4 8-1: MPE + tdd-MPE-P-MPR-Reporting-r16 ENUMERATED {supported} OPTIONAL, + lcid-ExtensionIAB-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + spCell-BFR-CBRA-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +MAC-ParametersFRX-Diff-r16 ::= SEQUENCE { + directMCG-SCellActivation-r16 ENUMERATED {supported} OPTIONAL, + directMCG-SCellActivationResume-r16 ENUMERATED {supported} OPTIONAL, + directSCG-SCellActivation-r16 ENUMERATED {supported} OPTIONAL, + directSCG-SCellActivationResume-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-1: DRX Adaptation + drx-Adaptation-r16 SEQUENCE { + non-SharedSpectrumChAccess-r16 MinTimeGap-r16 OPTIONAL, + sharedSpectrumChAccess-r16 MinTimeGap-r16 OPTIONAL + } OPTIONAL, + ... +} + +MAC-ParametersXDD-Diff ::= SEQUENCE { + skipUplinkTxDynamic ENUMERATED {supported} OPTIONAL, + logicalChannelSR-DelayTimer ENUMERATED {supported} OPTIONAL, + longDRX-Cycle ENUMERATED {supported} OPTIONAL, + shortDRX-Cycle ENUMERATED {supported} OPTIONAL, + multipleSR-Configurations ENUMERATED {supported} OPTIONAL, + multipleConfiguredGrants ENUMERATED {supported} OPTIONAL, + ..., + [[ + secondaryDRX-Group-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + enhancedSkipUplinkTxDynamic-r16 ENUMERATED {supported} OPTIONAL, + enhancedSkipUplinkTxConfigured-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +MinTimeGap-r16 ::= SEQUENCE { + scs-15kHz-r16 ENUMERATED {sl1, sl3} OPTIONAL, + scs-30kHz-r16 ENUMERATED {sl1, sl6} OPTIONAL, + scs-60kHz-r16 ENUMERATED {sl1, sl12} OPTIONAL, + scs-120kHz-r16 ENUMERATED {sl2, sl24} OPTIONAL +} + +-- TAG-MAC-PARAMETERS-STOP +-- TAG-MEASANDMOBPARAMETERS-START + +MeasAndMobParameters ::= SEQUENCE { + measAndMobParametersCommon MeasAndMobParametersCommon OPTIONAL, + measAndMobParametersXDD-Diff MeasAndMobParametersXDD-Diff OPTIONAL, + measAndMobParametersFRX-Diff MeasAndMobParametersFRX-Diff OPTIONAL +} + +MeasAndMobParametersCommon ::= SEQUENCE { + supportedGapPattern BIT STRING (SIZE (22)) OPTIONAL, + ssb-RLM ENUMERATED {supported} OPTIONAL, + ssb-AndCSI-RS-RLM ENUMERATED {supported} OPTIONAL, + ..., + [[ + eventB-MeasAndReport ENUMERATED {supported} OPTIONAL, + handoverFDD-TDD ENUMERATED {supported} OPTIONAL, + eutra-CGI-Reporting ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting ENUMERATED {supported} OPTIONAL + ]], + [[ + independentGapConfig ENUMERATED {supported} OPTIONAL, + periodicEUTRA-MeasAndReport ENUMERATED {supported} OPTIONAL, + handoverFR1-FR2 ENUMERATED {supported} OPTIONAL, + maxNumberCSI-RS-RRM-RS-SINR ENUMERATED {n4, n8, n16, n32, n64, n96} OPTIONAL + ]], + [[ + nr-CGI-Reporting-ENDC ENUMERATED {supported} OPTIONAL + ]], + [[ + eutra-CGI-Reporting-NEDC ENUMERATED {supported} OPTIONAL, + eutra-CGI-Reporting-NRDC ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NEDC ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NRDC ENUMERATED {supported} OPTIONAL + ]], + [[ + reportAddNeighMeasForPeriodic-r16 ENUMERATED {supported} OPTIONAL, + condHandoverParametersCommon-r16 SEQUENCE { + condHandoverFDD-TDD-r16 ENUMERATED {supported} OPTIONAL, + condHandoverFR1-FR2-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + nr-NeedForGap-Reporting-r16 ENUMERATED {supported} OPTIONAL, + supportedGapPattern-NRonly-r16 BIT STRING (SIZE (10)) OPTIONAL, + supportedGapPattern-NRonly-NEDC-r16 ENUMERATED {supported} OPTIONAL, + maxNumberCLI-RSSI-r16 ENUMERATED {n8, n16, n32, n64} OPTIONAL, + maxNumberCLI-SRS-RSRP-r16 ENUMERATED {n4, n8, n16, n32} OPTIONAL, + maxNumberPerSlotCLI-SRS-RSRP-r16 ENUMERATED {n2, n4, n8} OPTIONAL, + mfbi-IAB-r16 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NPN-r16 ENUMERATED {supported} OPTIONAL, + idleInactiveEUTRA-MeasReport-r16 ENUMERATED {supported} OPTIONAL, + idleInactive-ValidityArea-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGaps-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGaps-NEDC-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGaps-NRDC-r16 ENUMERATED {supported} OPTIONAL, + pcellT312-r16 ENUMERATED {supported} OPTIONAL, + supportedGapPattern-r16 BIT STRING (SIZE (2)) OPTIONAL + ]] +} + +MeasAndMobParametersXDD-Diff ::= SEQUENCE { + intraAndInterF-MeasAndReport ENUMERATED {supported} OPTIONAL, + eventA-MeasAndReport ENUMERATED {supported} OPTIONAL, + ..., + [[ + handoverInterF ENUMERATED {supported} OPTIONAL, + handoverLTE-EPC ENUMERATED {supported} OPTIONAL, + handoverLTE-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + sftd-MeasNR-Neigh ENUMERATED {supported} OPTIONAL, + sftd-MeasNR-Neigh-DRX ENUMERATED {supported} OPTIONAL + ]], + [[ + dummy ENUMERATED {supported} OPTIONAL + ]] +} + +MeasAndMobParametersFRX-Diff ::= SEQUENCE { + ss-SINR-Meas ENUMERATED {supported} OPTIONAL, + csi-RSRP-AndRSRQ-MeasWithSSB ENUMERATED {supported} OPTIONAL, + csi-RSRP-AndRSRQ-MeasWithoutSSB ENUMERATED {supported} OPTIONAL, + csi-SINR-Meas ENUMERATED {supported} OPTIONAL, + csi-RS-RLM ENUMERATED {supported} OPTIONAL, + ..., + [[ + handoverInterF ENUMERATED {supported} OPTIONAL, + handoverLTE-EPC ENUMERATED {supported} OPTIONAL, + handoverLTE-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + maxNumberResource-CSI-RS-RLM ENUMERATED {n2, n4, n6, n8} OPTIONAL + ]], + [[ + simultaneousRxDataSSB-DiffNumerology ENUMERATED {supported} OPTIONAL + ]], + [[ + nr-AutonomousGaps-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-ENDC-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-NEDC-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-NRDC-r16 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + cli-RSSI-Meas-r16 ENUMERATED {supported} OPTIONAL, + cli-SRS-RSRP-Meas-r16 ENUMERATED {supported} OPTIONAL, + interFrequencyMeas-NoGap-r16 ENUMERATED {supported} OPTIONAL, + simultaneousRxDataSSB-DiffNumerology-Inter-r16 ENUMERATED {supported} OPTIONAL, + idleInactiveNR-MeasReport-r16 ENUMERATED {supported} OPTIONAL, + -- R4 6-2: Support of beam level Early Measurement Reporting + idleInactiveNR-MeasBeamReport-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + increasedNumberofCSIRSPerMO-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-MEASANDMOBPARAMETERS-STOP +-- TAG-MEASANDMOBPARAMETERSMRDC-START + +MeasAndMobParametersMRDC ::= SEQUENCE { + measAndMobParametersMRDC-Common MeasAndMobParametersMRDC-Common OPTIONAL, + measAndMobParametersMRDC-XDD-Diff MeasAndMobParametersMRDC-XDD-Diff OPTIONAL, + measAndMobParametersMRDC-FRX-Diff MeasAndMobParametersMRDC-FRX-Diff OPTIONAL +} + +MeasAndMobParametersMRDC-v1560 ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff-v1560 MeasAndMobParametersMRDC-XDD-Diff-v1560 OPTIONAL +} + +MeasAndMobParametersMRDC-v1610 ::= SEQUENCE { + measAndMobParametersMRDC-Common-v1610 MeasAndMobParametersMRDC-Common-v1610 OPTIONAL, + interNR-MeasEUTRA-IAB-r16 ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-Common ::= SEQUENCE { + independentGapConfig ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-Common-v1610 ::= SEQUENCE { + condPSCellChangeParametersCommon-r16 SEQUENCE { + condPSCellChangeFDD-TDD-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChangeFR1-FR2-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + pscellT312-r16 ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-XDD-Diff ::= SEQUENCE { + sftd-MeasPSCell ENUMERATED {supported} OPTIONAL, + sftd-MeasNR-Cell ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-XDD-Diff-v1560 ::= SEQUENCE { + sftd-MeasPSCell-NEDC ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-FRX-Diff ::= SEQUENCE { + simultaneousRxDataSSB-DiffNumerology ENUMERATED {supported} OPTIONAL +} + +-- TAG-MEASANDMOBPARAMETERSMRDC-STOP +-- TAG-MIMO-LAYERS-START + +MIMO-LayersDL ::= ENUMERATED {twoLayers, fourLayers, eightLayers} + +MIMO-LayersUL ::= ENUMERATED {oneLayer, twoLayers, fourLayers} + +-- TAG-MIMO-LAYERS-STOP +-- TAG-MIMO-PARAMETERSPERBAND-START + +MIMO-ParametersPerBand ::= SEQUENCE { + tci-StatePDSCH SEQUENCE { + maxNumberConfiguredTCIstatesPerCC ENUMERATED {n4, n8, n16, n32, n64, n128} OPTIONAL, + maxNumberActiveTCI-PerBWP ENUMERATED {n1, n2, n4, n8} OPTIONAL + } OPTIONAL, + additionalActiveTCI-StatePDCCH ENUMERATED {supported} OPTIONAL, + pusch-TransCoherence ENUMERATED {nonCoherent, partialCoherent, fullCoherent} OPTIONAL, + beamCorrespondenceWithoutUL-BeamSweeping ENUMERATED {supported} OPTIONAL, + periodicBeamReport ENUMERATED {supported} OPTIONAL, + aperiodicBeamReport ENUMERATED {supported} OPTIONAL, + sp-BeamReportPUCCH ENUMERATED {supported} OPTIONAL, + sp-BeamReportPUSCH ENUMERATED {supported} OPTIONAL, + dummy1 DummyG OPTIONAL, + maxNumberRxBeam INTEGER (2..8) OPTIONAL, + maxNumberRxTxBeamSwitchDL SEQUENCE { + scs-15kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-30kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-60kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-120kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-240kHz ENUMERATED {n4, n7, n14} OPTIONAL + } OPTIONAL, + maxNumberNonGroupBeamReporting ENUMERATED {n1, n2, n4} OPTIONAL, + groupBeamReporting ENUMERATED {supported} OPTIONAL, + uplinkBeamManagement SEQUENCE { + maxNumberSRS-ResourcePerSet-BM ENUMERATED {n2, n4, n8, n16}, + maxNumberSRS-ResourceSet INTEGER (1..8) + } OPTIONAL, + maxNumberCSI-RS-BFD INTEGER (1..64) OPTIONAL, + maxNumberSSB-BFD INTEGER (1..64) OPTIONAL, + maxNumberCSI-RS-SSB-CBD INTEGER (1..256) OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + twoPortsPTRS-UL ENUMERATED {supported} OPTIONAL, + dummy5 SRS-Resources OPTIONAL, + dummy3 INTEGER (1..4) OPTIONAL, + beamReportTiming SEQUENCE { + scs-15kHz ENUMERATED {sym2, sym4, sym8} OPTIONAL, + scs-30kHz ENUMERATED {sym4, sym8, sym14, sym28} OPTIONAL, + scs-60kHz ENUMERATED {sym8, sym14, sym28} OPTIONAL, + scs-120kHz ENUMERATED {sym14, sym28, sym56} OPTIONAL + } OPTIONAL, + ptrs-DensityRecommendationSetDL SEQUENCE { + scs-15kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-30kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-60kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-120kHz PTRS-DensityRecommendationDL OPTIONAL + } OPTIONAL, + ptrs-DensityRecommendationSetUL SEQUENCE { + scs-15kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-30kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-60kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-120kHz PTRS-DensityRecommendationUL OPTIONAL + } OPTIONAL, + dummy4 DummyH OPTIONAL, + aperiodicTRS ENUMERATED {supported} OPTIONAL, + ..., + [[ + dummy6 ENUMERATED {true} OPTIONAL, + beamManagementSSB-CSI-RS BeamManagementSSB-CSI-RS OPTIONAL, + beamSwitchTiming SEQUENCE { + scs-60kHz ENUMERATED {sym14, sym28, sym48, sym224, sym336} OPTIONAL, + scs-120kHz ENUMERATED {sym14, sym28, sym48, sym224, sym336} OPTIONAL + } OPTIONAL, + codebookParameters CodebookParameters OPTIONAL, + csi-RS-IM-ReceptionForFeedback CSI-RS-IM-ReceptionForFeedback OPTIONAL, + csi-RS-ProcFrameworkForSRS CSI-RS-ProcFrameworkForSRS OPTIONAL, + csi-ReportFramework CSI-ReportFramework OPTIONAL, + csi-RS-ForTracking CSI-RS-ForTracking OPTIONAL, + srs-AssocCSI-RS SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource OPTIONAL, + spatialRelations SpatialRelations OPTIONAL + ]], + [[ + -- R1 16-2b-0: Support of default QCL assumption with two TCI states + defaultQCL-TwoTCI-r16 ENUMERATED {supported} OPTIONAL, + codebookParametersPerBand-r16 CodebookParameters-v1610 OPTIONAL, + -- R1 16-1b-3: Support of PUCCH resource groups per BWP for simultaneous spatial relation update + simul-SpatialRelationUpdatePUCCHResGroup-r16 ENUMERATED {supported} OPTIONAL, + + -- R1 16-1f: Maximum number of SCells configured for SCell beam failure recovery simultaneously + maxNumberSCellBFR-r16 ENUMERATED {n1,n2,n4,n8} OPTIONAL, + + -- R1 16-2c: Supports simultaneous reception with different Type-D for FR2 only + simultaneousReceptionDiffTypeD-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1a-1: SSB/CSI-RS for L1-SINR measurement + ssb-csirs-SINR-measurement-r16 SEQUENCE { + maxNumberSSB-CSIRS-OneTx-CMR-r16 ENUMERATED {n8, n16, n32, n64}, + maxNumberCSI-IM-NZP-IMR-res-r16 ENUMERATED {n8, n16, n32, n64}, + maxNumberCSIRS-2Tx-res-r16 ENUMERATED {n0, n4, n8, n16, n32, n64}, + maxNumberSSB-CSIRS-res-r16 ENUMERATED {n8, n16, n32, n64, n128}, + maxNumberCSI-IM-NZP-IMR-res-mem-r16 ENUMERATED {n8, n16, n32, n64, n128}, + supportedCSI-RS-Density-CMR-r16 ENUMERATED {one, three, oneAndThree}, + maxNumberAperiodicCSI-RS-Res-r16 ENUMERATED {n2, n4, n8, n16, n32, n64}, + supportedSINR-meas-r16 ENUMERATED {ssbWithCSI-IM, ssbWithNZP-IMR, csirsWithNZP-IMR, csi-RSWithoutIMR} OPTIONAL + } OPTIONAL, + -- R1 16-1a-2: Non-group based L1-SINR reporting + nonGroupSINR-reporting-r16 ENUMERATED {n1, n2, n4} OPTIONAL, + -- R1 16-1a-3: Non-group based L1-SINR reporting + groupSINR-reporting-r16 ENUMERATED {supported} OPTIONAL, + + multiDCI-multiTRP-Parameters-r16 SEQUENCE { + -- R1 16-2a-0: Overlapping PDSCHs in time and fully overlapping in frequency and time + overlapPDSCHsFullyFreqTime-r16 INTEGER (1..2) OPTIONAL, + -- R1 16-2a-1: Overlapping PDSCHs in time and partially overlapping in frequency and time + overlapPDSCHsInTimePartiallyFreq-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2a-2: Out of order operation for DL + outOfOrderOperationDL-r16 SEQUENCE { + supportPDCCH-ToPDSCH-r16 ENUMERATED {supported} OPTIONAL, + supportPDSCH-ToHARQ-ACK-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- R1 16-2a-3: Out of order operation for UL + outOfOrderOperationUL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2a-5: Separate CRS rate matching + separateCRS-RateMatching-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2a-6: Default QCL enhancement for multi-DCI based multi-TRP + defaultQCL-PerCORESETPoolIndex-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2a-7: Maximum number of activated TCI states + maxNumberActivatedTCI-States-r16 SEQUENCE { + maxNumberPerCORESET-Pool-r16 ENUMERATED {n1, n2, n4, n8}, + maxTotalNumberAcrossCORESET-Pool-r16 ENUMERATED {n2, n4, n8, n16} + } OPTIONAL + } OPTIONAL, + singleDCI-SDM-scheme-Parameters-r16 SEQUENCE { + -- R1 16-2b-1b: Single-DCI based SDM scheme - Support of new DMRS port entry + supportNewDMRS-Port-r16 ENUMERATED {n0, n2, n3} OPTIONAL, + -- R1 16-2b-1a: Support of s-port DL PTRS + supportTwoPortDL-PTRS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- R1 16-2b-2: Support of single-DCI based FDMSchemeA + supportFDM-SchemeA-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2b-3a: Single-DCI based FDMSchemeB CW soft combining + supportCodeWordSoftCombining-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2b-4: Single-DCI based TDMSchemeA + supportTDM-SchemeA-r16 ENUMERATED {kb3, kb5, kb10, kb20, noRestriction} OPTIONAL, + -- R1 16-2b-5: Single-DCI based inter-slot TDM + supportInter-slotTDM-r16 SEQUENCE { + supportRepNumPDSCH-TDRA-r16 ENUMERATED {n2, n3, n4, n5, n6, n7, n8, n16}, + maxTBS-Size-r16 ENUMERATED {kb3, kb5, kb10, kb20, noRestriction}, + maxNumberTCI-states-r16 INTEGER (1..2) + } OPTIONAL, + -- R1 16-4: Low PAPR DMRS for PDSCH + lowPAPR-DMRS-PDSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-6a: Low PAPR DMRS for PUSCH without transform precoding + lowPAPR-DMRS-PUSCHwithoutPrecoding-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-6b: Low PAPR DMRS for PUCCH + lowPAPR-DMRS-PUCCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-6c: Low PAPR DMRS for PUSCH with transform precoding & pi/2 BPSK + lowPAPR-DMRS-PUSCHwithPrecoding-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-7: Extension of the maximum number of configured aperiodic CSI report settings + csi-ReportFrameworkExt-r16 CSI-ReportFrameworkExt-r16 OPTIONAL, + -- R1 16-3a, 16-3a-1, 16-3b, 16-3b-1, 16-8: Individual new codebook types + codebookParametersAddition-r16 CodebookParametersAddition-r16 OPTIONAL, + -- R1 16-8: Mixed codebook types + codebookComboParametersAddition-r16 CodebookComboParametersAddition-r16 OPTIONAL, + -- R4 8-2: SSB based beam correspondence + beamCorrespondenceSSB-based-r16 ENUMERATED {supported} OPTIONAL, + -- R4 8-3: CSI-RS based beam correspondence + beamCorrespondenceCSI-RS-based-r16 ENUMERATED {supported} OPTIONAL, + beamSwitchTiming-r16 SEQUENCE { + scs-60kHz-r16 ENUMERATED {sym224, sym336} OPTIONAL, + scs-120kHz-r16 ENUMERATED {sym224, sym336} OPTIONAL + } OPTIONAL + ]], + [[ + -- R1 16-1a-4: Semi-persistent L1-SINR report on PUCCH + semi-PersistentL1-SINR-Report-PUCCH-r16 SEQUENCE { + supportReportFormat1-2OFDM-syms-r16 ENUMERATED {supported} OPTIONAL, + supportReportFormat4-14OFDM-syms-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- R1 16-1a-5: Semi-persistent L1-SINR report on PUSCH + semi-PersistentL1-SINR-Report-PUSCH-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R1 16-1h: Support of 64 configured PUCCH spatial relations + spatialRelations-v1640 SEQUENCE { + maxNumberConfiguredSpatialRelations-v1640 ENUMERATED {n96, n128, n160, n192, n224, n256, n288, n320} + } OPTIONAL, + -- R1 16-1i: Support of 64 configured candidate beam RSs for BFR + support64CandidateBeamRS-BFR-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +DummyG ::= SEQUENCE { + maxNumberSSB-CSI-RS-ResourceOneTx ENUMERATED {n8, n16, n32, n64}, + maxNumberSSB-CSI-RS-ResourceTwoTx ENUMERATED {n0, n4, n8, n16, n32, n64}, + supportedCSI-RS-Density ENUMERATED {one, three, oneAndThree} +} + +BeamManagementSSB-CSI-RS ::= SEQUENCE { + maxNumberSSB-CSI-RS-ResourceOneTx ENUMERATED {n0, n8, n16, n32, n64}, + maxNumberCSI-RS-Resource ENUMERATED {n0, n4, n8, n16, n32, n64}, + maxNumberCSI-RS-ResourceTwoTx ENUMERATED {n0, n4, n8, n16, n32, n64}, + supportedCSI-RS-Density ENUMERATED {one, three, oneAndThree} OPTIONAL, + maxNumberAperiodicCSI-RS-Resource ENUMERATED {n0, n1, n4, n8, n16, n32, n64} +} + +DummyH ::= SEQUENCE { + burstLength INTEGER (1..2), + maxSimultaneousResourceSetsPerCC INTEGER (1..8), + maxConfiguredResourceSetsPerCC INTEGER (1..64), + maxConfiguredResourceSetsAllCC INTEGER (1..128) +} + +CSI-RS-ForTracking ::= SEQUENCE { + maxBurstLength INTEGER (1..2), + maxSimultaneousResourceSetsPerCC INTEGER (1..8), + maxConfiguredResourceSetsPerCC INTEGER (1..64), + maxConfiguredResourceSetsAllCC INTEGER (1..256) +} + +CSI-RS-IM-ReceptionForFeedback ::= SEQUENCE { + maxConfigNumberNZP-CSI-RS-PerCC INTEGER (1..64), + maxConfigNumberPortsAcrossNZP-CSI-RS-PerCC INTEGER (2..256), + maxConfigNumberCSI-IM-PerCC ENUMERATED {n1, n2, n4, n8, n16, n32}, + maxNumberSimultaneousNZP-CSI-RS-PerCC INTEGER (1..64), + totalNumberPortsSimultaneousNZP-CSI-RS-PerCC INTEGER (2..256) +} + +CSI-RS-ProcFrameworkForSRS ::= SEQUENCE { + maxNumberPeriodicSRS-AssocCSI-RS-PerBWP INTEGER (1..4), + maxNumberAperiodicSRS-AssocCSI-RS-PerBWP INTEGER (1..4), + maxNumberSP-SRS-AssocCSI-RS-PerBWP INTEGER (0..4), + simultaneousSRS-AssocCSI-RS-PerCC INTEGER (1..8) +} + +CSI-ReportFramework ::= SEQUENCE { + maxNumberPeriodicCSI-PerBWP-ForCSI-Report INTEGER (1..4), + maxNumberAperiodicCSI-PerBWP-ForCSI-Report INTEGER (1..4), + maxNumberSemiPersistentCSI-PerBWP-ForCSI-Report INTEGER (0..4), + maxNumberPeriodicCSI-PerBWP-ForBeamReport INTEGER (1..4), + maxNumberAperiodicCSI-PerBWP-ForBeamReport INTEGER (1..4), + maxNumberAperiodicCSI-triggeringStatePerCC ENUMERATED {n3, n7, n15, n31, n63, n128}, + maxNumberSemiPersistentCSI-PerBWP-ForBeamReport INTEGER (0..4), + simultaneousCSI-ReportsPerCC INTEGER (1..8) +} + +CSI-ReportFrameworkExt-r16 ::= SEQUENCE { + maxNumberAperiodicCSI-PerBWP-ForCSI-ReportExt-r16 INTEGER (5..8) +} + +PTRS-DensityRecommendationDL ::= SEQUENCE { + frequencyDensity1 INTEGER (1..276), + frequencyDensity2 INTEGER (1..276), + timeDensity1 INTEGER (0..29), + timeDensity2 INTEGER (0..29), + timeDensity3 INTEGER (0..29) +} + +PTRS-DensityRecommendationUL ::= SEQUENCE { + frequencyDensity1 INTEGER (1..276), + frequencyDensity2 INTEGER (1..276), + timeDensity1 INTEGER (0..29), + timeDensity2 INTEGER (0..29), + timeDensity3 INTEGER (0..29), + sampleDensity1 INTEGER (1..276), + sampleDensity2 INTEGER (1..276), + sampleDensity3 INTEGER (1..276), + sampleDensity4 INTEGER (1..276), + sampleDensity5 INTEGER (1..276) +} + +SpatialRelations ::= SEQUENCE { + maxNumberConfiguredSpatialRelations ENUMERATED {n4, n8, n16, n32, n64, n96}, + maxNumberActiveSpatialRelations ENUMERATED {n1, n2, n4, n8, n14}, + additionalActiveSpatialRelationPUCCH ENUMERATED {supported} OPTIONAL, + maxNumberDL-RS-QCL-TypeD ENUMERATED {n1, n2, n4, n8, n14} +} + +DummyI ::= SEQUENCE { + supportedSRS-TxPortSwitch ENUMERATED {t1r2, t1r4, t2r4, t1r4-t2r4, tr-equal}, + txSwitchImpactToRx ENUMERATED {true} OPTIONAL +} + +-- TAG-MIMO-PARAMETERSPERBAND-STOP +-- TAG-MODULATIONORDER-START + +ModulationOrder ::= ENUMERATED {bpsk-halfpi, bpsk, qpsk, qam16, qam64, qam256} + +-- TAG-MODULATIONORDER-STOP +-- TAG-MRDC-PARAMETERS-START + +MRDC-Parameters ::= SEQUENCE { + singleUL-Transmission ENUMERATED {supported} OPTIONAL, + dynamicPowerSharingENDC ENUMERATED {supported} OPTIONAL, + tdm-Pattern ENUMERATED {supported} OPTIONAL, + ul-SharingEUTRA-NR ENUMERATED {tdm, fdm, both} OPTIONAL, + ul-SwitchingTimeEUTRA-NR ENUMERATED {type1, type2} OPTIONAL, + simultaneousRxTxInterBandENDC ENUMERATED {supported} OPTIONAL, + asyncIntraBandENDC ENUMERATED {supported} OPTIONAL, + ..., + [[ + dualPA-Architecture ENUMERATED {supported} OPTIONAL, + intraBandENDC-Support ENUMERATED {non-contiguous, both} OPTIONAL, + ul-TimingAlignmentEUTRA-NR ENUMERATED {required} OPTIONAL + ]] +} + +MRDC-Parameters-v1580 ::= SEQUENCE { + dynamicPowerSharingNEDC ENUMERATED {supported} OPTIONAL +} + +MRDC-Parameters-v1590 ::= SEQUENCE { + interBandContiguousMRDC ENUMERATED {supported} OPTIONAL +} + +MRDC-Parameters-v1620 ::= SEQUENCE { + maxUplinkDutyCycle-interBandENDC-TDD-PC2-r16 SEQUENCE{ + eutra-TDD-Config0-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config1-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config2-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config3-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config4-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config5-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config6-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL + } OPTIONAL, + -- R1 18-2 Single UL TX operation for TDD PCell in EN-DC + tdm-restrictionTDD-endc-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-2a Single UL TX operation for FDD PCell in EN-DC + tdm-restrictionFDD-endc-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-2b Support of HARQ-offset for SUO case1 in EN-DC with LTE TDD PCell for type 1 UE + singleUL-HARQ-offsetTDD-PCell-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-3 Dual Tx transmission for EN-DC with FDD PCell(TDM pattern for dual Tx UE) + tdm-restrictionDualTX-FDD-endc-r16 ENUMERATED {supported} OPTIONAL +} + +MRDC-Parameters-v1630 ::= SEQUENCE { + -- R4 2-20 Maximum uplink duty cycle for FDD+TDD EN-DC power class 2 + maxUplinkDutyCycle-interBandENDC-FDD-TDD-PC2-r16 SEQUENCE { + maxUplinkDutyCycle-FDD-TDD-EN-DC1-r16 ENUMERATED {n30, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + maxUplinkDutyCycle-FDD-TDD-EN-DC2-r16 ENUMERATED {n30, n40, n50, n60, n70, n80, n90, n100} OPTIONAL + } OPTIONAL, + + -- R4 2-19 FDD-FDD or TDD-TDD inter-band MR-DC with overlapping or partially overlapping DL spectrum + interBandMRDC-WithOverlapDL-Bands-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-MRDC-PARAMETERS-STOP +-- TAG-NRDC-PARAMETERS-START + +NRDC-Parameters ::= SEQUENCE { + measAndMobParametersNRDC MeasAndMobParametersMRDC OPTIONAL, + generalParametersNRDC GeneralParametersMRDC-XDD-Diff OPTIONAL, + fdd-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + dummy2 OCTET STRING OPTIONAL, + dummy SEQUENCE {} OPTIONAL +} + +NRDC-Parameters-v1570 ::= SEQUENCE { + sfn-SyncNRDC ENUMERATED {supported} OPTIONAL +} + +NRDC-Parameters-v15c0 ::= SEQUENCE { + pdcp-DuplicationSplitSRB ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationSplitDRB ENUMERATED {supported} OPTIONAL +} + +NRDC-Parameters-v1610 ::= SEQUENCE { + measAndMobParametersNRDC-v1610 MeasAndMobParametersMRDC-v1610 OPTIONAL +} + + +-- TAG-NRDC-PARAMETERS-STOP +-- TAG-OLPC-SRS-POS-START + +OLPC-SRS-Pos-r16 ::= SEQUENCE { + olpc-SRS-PosBasedOnPRS-Serving-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-PosBasedOnSSB-Neigh-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-PosBasedOnPRS-Neigh-r16 ENUMERATED {supported} OPTIONAL, + maxNumberPathLossEstimatePerServing-r16 ENUMERATED {n1, n4, n8, n16} OPTIONAL +} + +--TAG-OLPC-SRS-POS-STOP +-- TAG-PDCP-PARAMETERS-START + +PDCP-Parameters ::= SEQUENCE { + supportedROHC-Profiles SEQUENCE { + profile0x0000 BOOLEAN, + profile0x0001 BOOLEAN, + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0101 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + maxNumberROHC-ContextSessions ENUMERATED {cs2, cs4, cs8, cs12, cs16, cs24, cs32, cs48, cs64, + cs128, cs256, cs512, cs1024, cs16384, spare2, spare1}, + uplinkOnlyROHC-Profiles ENUMERATED {supported} OPTIONAL, + continueROHC-Context ENUMERATED {supported} OPTIONAL, + outOfOrderDelivery ENUMERATED {supported} OPTIONAL, + shortSN ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationSRB ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationMCG-OrSCG-DRB ENUMERATED {supported} OPTIONAL, + ..., + [[ + drb-IAB-r16 ENUMERATED {supported} OPTIONAL, + non-DRB-IAB-r16 ENUMERATED {supported} OPTIONAL, + extendedDiscardTimer-r16 ENUMERATED {supported} OPTIONAL, + continueEHC-Context-r16 ENUMERATED {supported} OPTIONAL, + ehc-r16 ENUMERATED {supported} OPTIONAL, + maxNumberEHC-Contexts-r16 ENUMERATED {cs2, cs4, cs8, cs16, cs32, cs64, cs128, cs256, cs512, + cs1024, cs2048, cs4096, cs8192, cs16384, cs32768, cs65536} OPTIONAL, + jointEHC-ROHC-Config-r16 ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationMoreThanTwoRLC-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-PDCP-PARAMETERS-STOP +-- TAG-PDCP-PARAMETERSMRDC-START + +PDCP-ParametersMRDC ::= SEQUENCE { + pdcp-DuplicationSplitSRB ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationSplitDRB ENUMERATED {supported} OPTIONAL +} + +PDCP-ParametersMRDC-v1610 ::= SEQUENCE { + scg-DRB-NR-IAB-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-PDCP-PARAMETERSMRDC-STOP +-- TAG-PHY-PARAMETERS-START + +Phy-Parameters ::= SEQUENCE { + phy-ParametersCommon Phy-ParametersCommon OPTIONAL, + phy-ParametersXDD-Diff Phy-ParametersXDD-Diff OPTIONAL, + phy-ParametersFRX-Diff Phy-ParametersFRX-Diff OPTIONAL, + phy-ParametersFR1 Phy-ParametersFR1 OPTIONAL, + phy-ParametersFR2 Phy-ParametersFR2 OPTIONAL +} + +Phy-ParametersCommon ::= SEQUENCE { + csi-RS-CFRA-ForHO ENUMERATED {supported} OPTIONAL, + dynamicPRB-BundlingDL ENUMERATED {supported} OPTIONAL, + sp-CSI-ReportPUCCH ENUMERATED {supported} OPTIONAL, + sp-CSI-ReportPUSCH ENUMERATED {supported} OPTIONAL, + nzp-CSI-RS-IntefMgmt ENUMERATED {supported} OPTIONAL, + type2-SP-CSI-Feedback-LongPUCCH ENUMERATED {supported} OPTIONAL, + precoderGranularityCORESET ENUMERATED {supported} OPTIONAL, + dynamicHARQ-ACK-Codebook ENUMERATED {supported} OPTIONAL, + semiStaticHARQ-ACK-Codebook ENUMERATED {supported} OPTIONAL, + spatialBundlingHARQ-ACK ENUMERATED {supported} OPTIONAL, + dynamicBetaOffsetInd-HARQ-ACK-CSI ENUMERATED {supported} OPTIONAL, + pucch-Repetition-F1-3-4 ENUMERATED {supported} OPTIONAL, + ra-Type0-PUSCH ENUMERATED {supported} OPTIONAL, + dynamicSwitchRA-Type0-1-PDSCH ENUMERATED {supported} OPTIONAL, + dynamicSwitchRA-Type0-1-PUSCH ENUMERATED {supported} OPTIONAL, + pdsch-MappingTypeA ENUMERATED {supported} OPTIONAL, + pdsch-MappingTypeB ENUMERATED {supported} OPTIONAL, + interleavingVRB-ToPRB-PDSCH ENUMERATED {supported} OPTIONAL, + interSlotFreqHopping-PUSCH ENUMERATED {supported} OPTIONAL, + type1-PUSCH-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + type2-PUSCH-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + pusch-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + pdsch-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + downlinkSPS ENUMERATED {supported} OPTIONAL, + configuredUL-GrantType1 ENUMERATED {supported} OPTIONAL, + configuredUL-GrantType2 ENUMERATED {supported} OPTIONAL, + pre-EmptIndication-DL ENUMERATED {supported} OPTIONAL, + cbg-TransIndication-DL ENUMERATED {supported} OPTIONAL, + cbg-TransIndication-UL ENUMERATED {supported} OPTIONAL, + cbg-FlushIndication-DL ENUMERATED {supported} OPTIONAL, + dynamicHARQ-ACK-CodeB-CBG-Retx-DL ENUMERATED {supported} OPTIONAL, + rateMatchingResrcSetSemi-Static ENUMERATED {supported} OPTIONAL, + rateMatchingResrcSetDynamic ENUMERATED {supported} OPTIONAL, + bwp-SwitchingDelay ENUMERATED {type1, type2} OPTIONAL, + ..., + [[ + dummy ENUMERATED {supported} OPTIONAL + ]], + [[ + maxNumberSearchSpaces ENUMERATED {n10} OPTIONAL, + rateMatchingCtrlResrcSetDynamic ENUMERATED {supported} OPTIONAL, + maxLayersMIMO-Indication ENUMERATED {supported} OPTIONAL + ]], + [[ + spCellPlacement CarrierAggregationVariant OPTIONAL + ]], + [[ + -- R1 9-1: Basic channel structure and procedure of 2-step RACH + twoStepRACH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-1: Monitoring DCI format 1_2 and DCI format 0_2 + dci-Format1-2And0-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-1a: Monitoring both DCI format 0_1/1_1 and DCI format 0_2/1_2 in the same search space + monitoringDCI-SameSearchSpace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-10: Type 2 configured grant release by DCI format 0_1 + type2-CG-ReleaseDCI-0-1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-11: Type 2 configured grant release by DCI format 0_2 + type2-CG-ReleaseDCI-0-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-3: SPS release by DCI format 1_1 + sps-ReleaseDCI-1-1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-3a: SPS release by DCI format 1_2 + sps-ReleaseDCI-1-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-8: CSI trigger states containing non-active BWP + csi-TriggerStateNon-ActiveBWP-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-2: Support up to 4 SMTCs configured for an IAB node MT per frequency location, including IAB-specific SMTC window periodicities + seperateSMTC-InterIAB-Support-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-3: Support RACH configuration separately from the RACH configuration for UE access, including new IAB-specific offset and scaling factors + seperateRACH-IAB-Support-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-5a: Support semi-static configuration/indication of UL-Flexible-DL slot formats for IAB-MT resources + ul-flexibleDL-SlotFormatSemiStatic-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-5b: Support dynamic indication of UL-Flexible-DL slot formats for IAB-MT resources + ul-flexibleDL-SlotFormatDynamics-IAB-r16 ENUMERATED {supported} OPTIONAL, + dft-S-OFDM-WaveformUL-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-6: Support DCI Format 2_5 based indication of soft resource availability to an IAB node + dci-25-AI-RNTI-Support-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-7: Support T_delta reception. + t-DeltaReceptionSupport-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-8: Support of Desired guard symbol reporting and provided guard symbok reception. + guardSymbolReportReception-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-8 HARQ-ACK codebook type and spatial bundling per PUCCH group + harqACK-CB-SpatialBundlingPUCCH-Group-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-2: Cross Slot Scheduling + crossSlotScheduling-r16 SEQUENCE { + non-SharedSpectrumChAccess-r16 ENUMERATED {supported} OPTIONAL, + sharedSpectrumChAccess-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + maxNumberSRS-PosPathLossEstimateAllServingCells-r16 ENUMERATED {n1, n4, n8, n16} OPTIONAL, + extendedCG-Periodicities-r16 ENUMERATED {supported} OPTIONAL, + extendedSPS-Periodicities-r16 ENUMERATED {supported} OPTIONAL, + codebookVariantsList-r16 CodebookVariantsList-r16 OPTIONAL, + -- R1 11-6: PUSCH repetition Type A + pusch-RepetitionTypeA-r16 SEQUENCE { + sharedSpectrumChAccess-r16 ENUMERATED {supported} OPTIONAL, + non-SharedSpectrumChAccess-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- R1 11-4b: DL priority indication in DCI with mixed DCI formats + dci-DL-PriorityIndicator-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-1a: UL priority indication in DCI with mixed DCI formats + dci-UL-PriorityIndicator-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1e: Maximum number of configured pathloss reference RSs for PUSCH/PUCCH/SRS by RRC for MAC-CE based pathloss reference RS update + maxNumberPathlossRS-Update-r16 ENUMERATED {n4, n8, n16, n32, n64} OPTIONAL, + + -- R1 18-9: Usage of the PDSCH starting time for HARQ-ACK type 2 codebook + type2-HARQ-ACK-Codebook-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1g-1: Resources for beam management, pathloss measurement, BFD, RLM and new beam identification across frequency ranges + maxTotalResourcesForAcrossFreqRanges-r16 SEQUENCE { + maxNumberResWithinSlotAcrossCC-AcrossFR-r16 ENUMERATED {n2, n4, n8, n12, n16, n32, n64, n128} OPTIONAL, + maxNumberResAcrossCC-AcrossFR-r16 ENUMERATED {n2, n4, n8, n12, n16, n32, n40, n48, n64, n72, n80, n96, n128, n256} + OPTIONAL + } OPTIONAL, + -- R1 16-2a-4: HARQ-ACK for multi-DCI based multi-TRP - separate + harqACK-separateMultiDCI-MultiTRP-r16 SEQUENCE { + maxNumberLongPUCCHs-r16 ENUMERATED {longAndLong, longAndShort, shortAndShort} OPTIONAL + } OPTIONAL, + -- R1 16-2a-4: HARQ-ACK for multi-DCI based multi-TRP - joint + harqACK-jointMultiDCI-MultiTRP-r16 ENUMERATED {supported} OPTIONAL, + -- R4 9-1: BWP switching on multiple CCs RRM requirements + bwp-SwitchingMultiCCs-r16 CHOICE { + type1-r16 ENUMERATED {us100, us200}, + type2-r16 ENUMERATED {us200, us400, us800, us1000} + } OPTIONAL + ]], + [[ + targetSMTC-SCG-r16 ENUMERATED {supported} OPTIONAL, + supportRepetitionZeroOffsetRV-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-12: in-order CBG-based re-transmission + cbg-TransInOrderPUSCH-UL-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R4 6-3: Dormant BWP switching on multiple CCs RRM requirements + bwp-SwitchingMultiDormancyCCs-r16 CHOICE { + type1-r16 ENUMERATED {us100, us200}, + type2-r16 ENUMERATED {us200, us400, us800, us1000} + } OPTIONAL, + -- R1 16-2a-8: Indicates that retransmission scheduled by a different CORESETPoolIndex for multi-DCI multi-TRP is not supported. + supportRetx-Diff-CoresetPool-Multi-DCI-TRP-r16 ENUMERATED {notSupported} OPTIONAL, + -- R1 22-10: Support of pdcch-MonitoringAnyOccasionsWithSpanGap in case of cross-carrier scheduling with different SCSs + pdcch-MonitoringAnyOccasionsWithSpanGapCrossCarrierSch-r16 ENUMERATED {mode2, mode3} OPTIONAL + ]] +} + +Phy-ParametersXDD-Diff ::= SEQUENCE { + dynamicSFI ENUMERATED {supported} OPTIONAL, + twoPUCCH-F0-2-ConsecSymbols ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUSCH ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUCCH ENUMERATED {supported} OPTIONAL, + ..., + [[ + dl-SchedulingOffset-PDSCH-TypeA ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeB ENUMERATED {supported} OPTIONAL, + ul-SchedulingOffset ENUMERATED {supported} OPTIONAL + ]] +} + +Phy-ParametersFRX-Diff ::= SEQUENCE { + dynamicSFI ENUMERATED {supported} OPTIONAL, + dummy1 BIT STRING (SIZE (2)) OPTIONAL, + twoFL-DMRS BIT STRING (SIZE (2)) OPTIONAL, + dummy2 BIT STRING (SIZE (2)) OPTIONAL, + dummy3 BIT STRING (SIZE (2)) OPTIONAL, + supportedDMRS-TypeDL ENUMERATED {type1, type1And2} OPTIONAL, + supportedDMRS-TypeUL ENUMERATED {type1, type1And2} OPTIONAL, + semiOpenLoopCSI ENUMERATED {supported} OPTIONAL, + csi-ReportWithoutPMI ENUMERATED {supported} OPTIONAL, + csi-ReportWithoutCQI ENUMERATED {supported} OPTIONAL, + onePortsPTRS BIT STRING (SIZE (2)) OPTIONAL, + twoPUCCH-F0-2-ConsecSymbols ENUMERATED {supported} OPTIONAL, + pucch-F2-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F3-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F4-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F0-2WithoutFH ENUMERATED {notSupported} OPTIONAL, + pucch-F1-3-4WithoutFH ENUMERATED {notSupported} OPTIONAL, + mux-SR-HARQ-ACK-CSI-PUCCH-MultiPerSlot ENUMERATED {supported} OPTIONAL, + uci-CodeBlockSegmentation ENUMERATED {supported} OPTIONAL, + onePUCCH-LongAndShortFormat ENUMERATED {supported} OPTIONAL, + twoPUCCH-AnyOthersInSlot ENUMERATED {supported} OPTIONAL, + intraSlotFreqHopping-PUSCH ENUMERATED {supported} OPTIONAL, + pusch-LBRM ENUMERATED {supported} OPTIONAL, + pdcch-BlindDetectionCA INTEGER (4..16) OPTIONAL, + tpc-PUSCH-RNTI ENUMERATED {supported} OPTIONAL, + tpc-PUCCH-RNTI ENUMERATED {supported} OPTIONAL, + tpc-SRS-RNTI ENUMERATED {supported} OPTIONAL, + absoluteTPC-Command ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUSCH ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUCCH ENUMERATED {supported} OPTIONAL, + pusch-HalfPi-BPSK ENUMERATED {supported} OPTIONAL, + pucch-F3-4-HalfPi-BPSK ENUMERATED {supported} OPTIONAL, + almostContiguousCP-OFDM-UL ENUMERATED {supported} OPTIONAL, + sp-CSI-RS ENUMERATED {supported} OPTIONAL, + sp-CSI-IM ENUMERATED {supported} OPTIONAL, + tdd-MultiDL-UL-SwitchPerSlot ENUMERATED {supported} OPTIONAL, + multipleCORESET ENUMERATED {supported} OPTIONAL, + ..., + [[ + csi-RS-IM-ReceptionForFeedback CSI-RS-IM-ReceptionForFeedback OPTIONAL, + csi-RS-ProcFrameworkForSRS CSI-RS-ProcFrameworkForSRS OPTIONAL, + csi-ReportFramework CSI-ReportFramework OPTIONAL, + mux-SR-HARQ-ACK-CSI-PUCCH-OncePerSlot SEQUENCE { + sameSymbol ENUMERATED {supported} OPTIONAL, + diffSymbol ENUMERATED {supported} OPTIONAL + } OPTIONAL, + mux-SR-HARQ-ACK-PUCCH ENUMERATED {supported} OPTIONAL, + mux-MultipleGroupCtrlCH-Overlap ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeA ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeB ENUMERATED {supported} OPTIONAL, + ul-SchedulingOffset ENUMERATED {supported} OPTIONAL, + dl-64QAM-MCS-TableAlt ENUMERATED {supported} OPTIONAL, + ul-64QAM-MCS-TableAlt ENUMERATED {supported} OPTIONAL, + cqi-TableAlt ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-TwoAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL, + twoFL-DMRS-TwoAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-ThreeAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL + ]], + [[ + pdcch-BlindDetectionNRDC SEQUENCE { + pdcch-BlindDetectionMCG-UE INTEGER (1..15), + pdcch-BlindDetectionSCG-UE INTEGER (1..15) + } OPTIONAL, + mux-HARQ-ACK-PUSCH-DiffSymbol ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R1 11-1b: Type 1 HARQ-ACK codebook support for relative TDRA for DL + type1-HARQ-ACK-Codebook-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-8: Enhanced UL power control scheme + enhancedPowerControl-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1b-1: TCI state activation across multiple CCs + simultaneousTCI-ActMultipleCC-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1b-2: Spatial relation update across multiple CCs + simultaneousSpatialRelationMultipleCC-r16 ENUMERATED {supported} OPTIONAL, + cli-RSSI-FDM-DL-r16 ENUMERATED {supported} OPTIONAL, + cli-SRS-RSRP-FDM-DL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-3: Maximum MIMO Layer Adaptation + maxLayersMIMO-Adaptation-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-5: Configuration of aggregation factor per SPS configuration + aggregationFactorSPS-DL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1g: Resources for beam management, pathloss measurement, BFD, RLM and new beam identification + maxTotalResourcesForOneFreqRange-r16 SEQUENCE { + maxNumberResWithinSlotAcrossCC-OneFR-r16 ENUMERATED {n2, n4, n8, n12, n16, n32, n64, n128} OPTIONAL, + maxNumberResAcrossCC-OneFR-r16 ENUMERATED {n2, n4, n8, n12, n16, n32, n40, n48, n64, n72, n80, n96, n128, n256} + OPTIONAL + } OPTIONAL, + -- R1 16-7: Extension of the maximum number of configured aperiodic CSI report settings + csi-ReportFrameworkExt-r16 CSI-ReportFrameworkExt-r16 OPTIONAL + ]], + [[ + twoTCI-Act-servingCellInCC-List-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +Phy-ParametersFR1 ::= SEQUENCE { + pdcch-MonitoringSingleOccasion ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL, + pdsch-256QAM-FR1 ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR1-PerSymbol ENUMERATED {n10, n20} OPTIONAL, + ..., + [[ + pdsch-RE-MappingFR1-PerSlot ENUMERATED {n16, n32, n48, n64, n80, n96, n112, n128, + n144, n160, n176, n192, n208, n224, n240, n256} OPTIONAL + ]] +} + +Phy-ParametersFR2 ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR2-PerSymbol ENUMERATED {n6, n20} OPTIONAL, + ..., + [[ + pCell-FR2 ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR2-PerSlot ENUMERATED {n16, n32, n48, n64, n80, n96, n112, n128, + n144, n160, n176, n192, n208, n224, n240, n256} OPTIONAL + ]], + [[ + -- R1 16-1c: Support of default spatial relation and pathloss reference RS for dedicated-PUCCH/SRS and PUSCH + defaultSpatialRelationPathlossRS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1d: Support of spatial relation update for AP-SRS via MAC CE + spatialRelationUpdateAP-SRS-r16 ENUMERATED {supported} OPTIONAL, + maxNumberSRS-PosSpatialRelationsAllServingCells-r16 ENUMERATED {n0, n1, n2, n4, n8, n16} OPTIONAL + ]] +} + +-- TAG-PHY-PARAMETERS-STOP +-- TAG-PHY-PARAMETERSMRDC-START + +Phy-ParametersMRDC ::= SEQUENCE { + naics-Capability-List SEQUENCE (SIZE (1..maxNrofNAICS-Entries)) OF NAICS-Capability-Entry OPTIONAL, + ..., + [[ + spCellPlacement CarrierAggregationVariant OPTIONAL + ]], + [[ + -- R1 18-3b: Semi-statically configured LTE UL transmissions in all UL subframes not limited to tdm-pattern in case of TDD PCell + tdd-PCellUL-TX-AllUL-Subframe-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-3a: Semi-statically configured LTE UL transmissions in all UL subframes not limited to tdm-pattern in case of FDD PCell + fdd-PCellUL-TX-AllUL-Subframe-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +NAICS-Capability-Entry ::= SEQUENCE { + numberOfNAICS-CapableCC INTEGER(1..5), + numberOfAggregatedPRB ENUMERATED {n50, n75, n100, n125, n150, n175, n200, n225, + n250, n275, n300, n350, n400, n450, n500, spare}, + ... +} + +-- TAG-PHY-PARAMETERSMRDC-STOP +-- TAG-PHY-PARAMETERSSHAREDSPECTRUMCHACCESS-START + +Phy-ParametersSharedSpectrumChAccess-r16 ::= SEQUENCE { + -- 10-32 (1-2): SS block based SINR measurement (SS-SINR) for unlicensed spectrum + ss-SINR-Meas-r16 ENUMERATED {supported} OPTIONAL, + -- 10-33 (2-32a): Semi-persistent CSI report on PUCCH for unlicensed spectrum + sp-CSI-ReportPUCCH-r16 ENUMERATED {supported} OPTIONAL, + -- 10-33a (2-32b): Semi-persistent CSI report on PUSCH for unlicensed spectrum + sp-CSI-ReportPUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- 10-34 (3-6): Dynamic SFI monitoring for unlicensed spectrum + dynamicSFI-r16 ENUMERATED {supported} OPTIONAL, + -- 10-35c (4-19c): SR/HARQ-ACK/CSI multiplexing once per slot using a PUCCH (or HARQ-ACK/CSI piggybacked on a PUSCH) when SR/HARQ- + -- ACK/CSI are supposed to be sent with different starting symbols in a slot for unlicensed spectrum + -- 10-35 (4-19): SR/HARQ-ACK/CSI multiplexing once per slot using a PUCCH (or HARQ-ACK/CSI piggybacked on a PUSCH) when SR/HARQ- + -- ACK/CSI are supposed to be sent with the same starting symbol on the PUCCH resources in a slot for unlicensed spectrum + mux-SR-HARQ-ACK-CSI-PUCCH-OncePerSlot-r16 SEQUENCE { + sameSymbol-r16 ENUMERATED {supported} OPTIONAL, + diffSymbol-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- 10-35a (4-19a): Overlapping PUCCH resources have different starting symbols in a slot for unlicensed spectrum + mux-SR-HARQ-ACK-PUCCH-r16 ENUMERATED {supported} OPTIONAL, + -- 10-35b (4-19b): SR/HARQ-ACK/CSI multiplexing more than once per slot using a PUCCH (or HARQ-ACK/CSI piggybacked on a PUSCH) when + -- SR/HARQ ACK/CSI are supposed to be sent with the same or different starting symbol in a slot for unlicensed spectrum + mux-SR-HARQ-ACK-CSI-PUCCH-MultiPerSlot-r16 ENUMERATED {supported} OPTIONAL, + -- 10-36 (4-28): HARQ-ACK multiplexing on PUSCH with different PUCCH/PUSCH starting OFDM symbols for unlicensed spectrum + mux-HARQ-ACK-PUSCH-DiffSymbol-r16 ENUMERATED {supported} OPTIONAL, + -- 10-37 (4-23): Repetitions for PUCCH format 1, 3, and 4 over multiple slots with K = 2, 4, 8 for unlicensed spectrum + pucch-Repetition-F1-3-4-r16 ENUMERATED {supported} OPTIONAL, + -- 10-38 (5-14): Type 1 configured PUSCH repetitions over multiple slots for unlicensed spectrum + type1-PUSCH-RepetitionMultiSlots-r16 ENUMERATED {supported} OPTIONAL, + -- 10-39 (5-16): Type 2 configured PUSCH repetitions over multiple slots for unlicensed spectrum + type2-PUSCH-RepetitionMultiSlots-r16 ENUMERATED {supported} OPTIONAL, + -- 10-40 (5-17): PUSCH repetitions over multiple slots for unlicensed spectrum + pusch-RepetitionMultiSlots-r16 ENUMERATED {supported} OPTIONAL, + -- 10-40a (5-17a): PDSCH repetitions over multiple slots for unlicensed spectrum + pdsch-RepetitionMultiSlots-r16 ENUMERATED {supported} OPTIONAL, + -- 10-41 (5-18): DL SPS + downlinkSPS-r16 ENUMERATED {supported} OPTIONAL, + -- 10-42 (5-19): Type 1 Configured UL grant + configuredUL-GrantType1-r16 ENUMERATED {supported} OPTIONAL, + -- 10-43 (5-20): Type 2 Configured UL grant + configuredUL-GrantType2-r16 ENUMERATED {supported} OPTIONAL, + -- 10-44 (5-21): Pre-emption indication for DL + pre-EmptIndication-DL-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-PHY-PARAMETERSSHAREDSPECTRUMCHACCESS-STOP +-- TAG-POWSAV-PARAMETERS-START + +PowSav-Parameters-r16 ::= SEQUENCE { + powSav-ParametersCommon-r16 PowSav-ParametersCommon-r16 OPTIONAL, + powSav-ParametersFRX-Diff-r16 PowSav-ParametersFRX-Diff-r16 OPTIONAL, + ... +} + +PowSav-ParametersCommon-r16 ::= SEQUENCE { + drx-Preference-r16 ENUMERATED {supported} OPTIONAL, + maxCC-Preference-r16 ENUMERATED {supported} OPTIONAL, + releasePreference-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-4a: UE assistance information + minSchedulingOffsetPreference-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +PowSav-ParametersFRX-Diff-r16 ::= SEQUENCE { + maxBW-Preference-r16 ENUMERATED {supported} OPTIONAL, + maxMIMO-LayerPreference-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-POWSAV-PARAMETERS-STOP +-- TAG-PROCESSINGPARAMETERS-START + +ProcessingParameters ::= SEQUENCE { + fallback ENUMERATED {sc, cap1-only}, + differentTB-PerSlot SEQUENCE { + upto1 NumberOfCarriers OPTIONAL, + upto2 NumberOfCarriers OPTIONAL, + upto4 NumberOfCarriers OPTIONAL, + upto7 NumberOfCarriers OPTIONAL + } OPTIONAL +} + +NumberOfCarriers ::= INTEGER (1..16) + +-- TAG-PROCESSINGPARAMETERS-STOP +-- TAG-RAT-TYPE-START + +RAT-Type ::= ENUMERATED {nr, eutra-nr, eutra, utra-fdd-v1610, ...} + +-- TAG-RAT-TYPE-STOP +-- TAG-RF-PARAMETERS-START + +RF-Parameters ::= SEQUENCE { + supportedBandListNR SEQUENCE (SIZE (1..maxBands)) OF BandNR, + supportedBandCombinationList BandCombinationList OPTIONAL, + appliedFreqBandListFilter FreqBandList OPTIONAL, + ..., + [[ + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL, + srs-SwitchingTimeRequested ENUMERATED {true} OPTIONAL + ]], + [[ + supportedBandCombinationList-v1550 BandCombinationList-v1550 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationListSidelinkEUTRA-NR-r16 BandCombinationListSidelinkEUTRA-NR-r16 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-r16 BandCombinationList-UplinkTxSwitch-r16 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1630 BandCombinationList-v1630 OPTIONAL, + supportedBandCombinationListSidelinkEUTRA-NR-v1630 BandCombinationListSidelinkEUTRA-NR-v1630 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-v1630 BandCombinationList-UplinkTxSwitch-v1630 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1640 BandCombinationList-v1640 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-v1640 BandCombinationList-UplinkTxSwitch-v1640 OPTIONAL + ]] + +} + +BandNR ::= SEQUENCE { + bandNR FreqBandIndicatorNR, + modifiedMPR-Behaviour BIT STRING (SIZE (8)) OPTIONAL, + mimo-ParametersPerBand MIMO-ParametersPerBand OPTIONAL, + extendedCP ENUMERATED {supported} OPTIONAL, + multipleTCI ENUMERATED {supported} OPTIONAL, + bwp-WithoutRestriction ENUMERATED {supported} OPTIONAL, + bwp-SameNumerology ENUMERATED {upto2, upto4} OPTIONAL, + bwp-DiffNumerology ENUMERATED {upto4} OPTIONAL, + crossCarrierScheduling-SameSCS ENUMERATED {supported} OPTIONAL, + pdsch-256QAM-FR2 ENUMERATED {supported} OPTIONAL, + pusch-256QAM ENUMERATED {supported} OPTIONAL, + ue-PowerClass ENUMERATED {pc1, pc2, pc3, pc4} OPTIONAL, + rateMatchingLTE-CRS ENUMERATED {supported} OPTIONAL, + channelBWs-DL CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (10)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (3)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (3)) OPTIONAL + } + } OPTIONAL, + channelBWs-UL CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (10)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (3)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (3)) OPTIONAL + } + } OPTIONAL, + ..., + [[ + maxUplinkDutyCycle-PC2-FR1 ENUMERATED {n60, n70, n80, n90, n100} OPTIONAL + ]], + [[ + pucch-SpatialRelInfoMAC-CE ENUMERATED {supported} OPTIONAL, + powerBoosting-pi2BPSK ENUMERATED {supported} OPTIONAL + ]], + [[ + maxUplinkDutyCycle-FR2 ENUMERATED {n15, n20, n25, n30, n40, n50, n60, n70, n80, n90, n100} OPTIONAL + ]], + [[ + channelBWs-DL-v1590 CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (16)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (8)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (8)) OPTIONAL + } + } OPTIONAL, + channelBWs-UL-v1590 CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (16)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (8)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (8)) OPTIONAL + } + } OPTIONAL + ]], + [[ + asymmetricBandwidthCombinationSet BIT STRING (SIZE (1..32)) OPTIONAL + ]], + [[ + -- R1 10: NR-unlicensed + sharedSpectrumChAccessParamsPerBand-r16 SharedSpectrumChAccessParamsPerBand-r16 OPTIONAL, + -- R1 11-7b: Independent cancellation of the overlapping PUSCHs in an intra-band UL CA + cancelOverlappingPUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-1: Multiple LTE-CRS rate matching patterns + multipleRateMatchingEUTRA-CRS-r16 SEQUENCE { + maxNumberPatterns-r16 INTEGER (2..6), + maxNumberNon-OverlapPatterns-r16 INTEGER (1..3) + } OPTIONAL, + -- R1 14-1a: Two LTE-CRS overlapping rate matching patterns within a part of NR carrier using 15 kHz overlapping with a LTE carrier + overlapRateMatchingEUTRA-CRS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-2: PDSCH Type B mapping of length 9 and 10 OFDM symbols + pdsch-MappingTypeB-Alt-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-3: One slot periodic TRS configuration for FR1 + oneSlotPeriodicTRS-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-Pos-r16 OLPC-SRS-Pos-r16 OPTIONAL, + spatialRelationsSRS-Pos-r16 SpatialRelationsSRS-Pos-r16 OPTIONAL, + simulSRS-MIMO-TransWithinBand-r16 ENUMERATED {n2} OPTIONAL, + channelBW-DL-IAB-r16 CHOICE { + fr1-100mhz SEQUENCE { + scs-15kHz ENUMERATED {supported} OPTIONAL, + scs-30kHz ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL + }, + fr2-200mhz SEQUENCE { + scs-60kHz ENUMERATED {supported} OPTIONAL, + scs-120kHz ENUMERATED {supported} OPTIONAL + } + } OPTIONAL, + channelBW-UL-IAB-r16 CHOICE { + fr1-100mhz SEQUENCE { + scs-15kHz ENUMERATED {supported} OPTIONAL, + scs-30kHz ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL + }, + fr2-200mhz SEQUENCE { + scs-60kHz ENUMERATED {supported} OPTIONAL, + scs-120kHz ENUMERATED {supported} OPTIONAL + } + } OPTIONAL, + rasterShift7dot5-IAB-r16 ENUMERATED {supported} OPTIONAL, + ue-PowerClass-v1610 ENUMERATED {pc1dot5} OPTIONAL, + condHandover-r16 ENUMERATED {supported} OPTIONAL, + condHandoverFailure-r16 ENUMERATED {supported} OPTIONAL, + condHandoverTwoTriggerEvents-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChange-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChangeTwoTriggerEvents-r16 ENUMERATED {supported} OPTIONAL, + mpr-PowerBoost-FR2-r16 ENUMERATED {supported} OPTIONAL, + + -- R1 11-9: Multiple active configured grant configurations for a BWP of a serving cell + activeConfiguredGrant-r16 SEQUENCE { + maxNumberConfigsPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n12}, + maxNumberConfigsAllCC-r16 INTEGER (2..32) + } OPTIONAL, + -- R1 11-9a: Joint release in a DCI for two or more configured grant Type 2 configurations for a given BWP of a serving cell + jointReleaseConfiguredGrantType2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-2: Multiple SPS configurations + sps-r16 SEQUENCE { + maxNumberConfigsPerBWP-r16 INTEGER (1..8), + maxNumberConfigsAllCC-r16 INTEGER (2..32) + } OPTIONAL, + -- R1 12-2a: Joint release in a DCI for two or more SPS configurations for a given BWP of a serving cell + jointReleaseSPS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 13-19: Simultaneous positioning SRS and MIMO SRS transmission within a band across multiple CCs + simulSRS-TransWithinBand-r16 ENUMERATED {n2} OPTIONAL, + trs-AdditionalBandwidth-r16 ENUMERATED {trs-AddBW-Set1, trs-AddBW-Set2} OPTIONAL, + handoverIntraF-IAB-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R1 22-5a: Simultaneous transmission of SRS for antenna switching and SRS for CB/NCB /BM for intra-band UL CA + -- R1 22-5c: Simultaneous transmission of SRS for antenna switching and SRS for antenna switching for intra-band UL CA + simulTX-SRS-AntSwitchingIntraBandUL-CA-r16 SimulSRS-ForAntennaSwitching-r16 OPTIONAL, + -- R1 10: NR-unlicensed + sharedSpectrumChAccessParamsPerBand-v1630 SharedSpectrumChAccessParamsPerBand-v1630 OPTIONAL + ]], + [[ + handoverUTRA-FDD-r16 ENUMERATED {supported} OPTIONAL, + -- R4 7-4: Report the shorter transient capability supported by the UE: 2, 4 or 7us + enhancedUL-TransientPeriod-r16 ENUMERATED {us2, us4, us7} OPTIONAL, + sharedSpectrumChAccessParamsPerBand-v1640 SharedSpectrumChAccessParamsPerBand-v1640 OPTIONAL + ]] +} + +-- TAG-RF-PARAMETERS-STOP +-- TAG-RF-PARAMETERSMRDC-START + +RF-ParametersMRDC ::= SEQUENCE { + supportedBandCombinationList BandCombinationList OPTIONAL, + appliedFreqBandListFilter FreqBandList OPTIONAL, + ..., + [[ + srs-SwitchingTimeRequested ENUMERATED {true} OPTIONAL, + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1550 BandCombinationList-v1550 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL, + supportedBandCombinationListNEDC-Only BandCombinationList OPTIONAL + ]], + [[ + supportedBandCombinationList-v1570 BandCombinationList-v1570 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1580 BandCombinationList-v1580 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1590 BandCombinationList-v1590 OPTIONAL + ]], + [[ + supportedBandCombinationListNEDC-Only-v15a0 SEQUENCE { + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL, + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL, + supportedBandCombinationList-v1570 BandCombinationList-v1570 OPTIONAL, + supportedBandCombinationList-v1580 BandCombinationList-v1580 OPTIONAL, + supportedBandCombinationList-v1590 BandCombinationList-v1590 OPTIONAL + } OPTIONAL + ]], + [[ + supportedBandCombinationList-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationListNEDC-Only-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-r16 BandCombinationList-UplinkTxSwitch-r16 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1630 BandCombinationList-v1630 OPTIONAL, + supportedBandCombinationListNEDC-Only-v1630 BandCombinationList-v1630 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-v1630 BandCombinationList-UplinkTxSwitch-v1630 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1640 BandCombinationList-v1640 OPTIONAL, + supportedBandCombinationListNEDC-Only-v1640 BandCombinationList-v1640 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-v1640 BandCombinationList-UplinkTxSwitch-v1640 OPTIONAL + ]] +} + +-- TAG-RF-PARAMETERSMRDC-STOP +-- TAG-RLC-PARAMETERS-START + +RLC-Parameters ::= SEQUENCE { + am-WithShortSN ENUMERATED {supported} OPTIONAL, + um-WithShortSN ENUMERATED {supported} OPTIONAL, + um-WithLongSN ENUMERATED {supported} OPTIONAL, + ..., + [[ + extendedT-PollRetransmit-r16 ENUMERATED {supported} OPTIONAL, + extendedT-StatusProhibit-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-RLC-PARAMETERS-STOP +-- TAG-SDAP-PARAMETERS-START + +SDAP-Parameters ::= SEQUENCE { + as-ReflectiveQoS ENUMERATED {true} OPTIONAL, + ..., + [[ + sdap-QOS-IAB-r16 ENUMERATED {supported} OPTIONAL, + sdapHeaderIAB-r16 ENUMERATED {supported} OPTIONAL + ]] + +} + +-- TAG-SDAP-PARAMETERS-STOP +-- TAG-SIDELINKPARAMETERS-START + +SidelinkParameters-r16 ::= SEQUENCE { + sidelinkParametersNR-r16 SidelinkParametersNR-r16 OPTIONAL, + sidelinkParametersEUTRA-r16 SidelinkParametersEUTRA-r16 OPTIONAL +} + +SidelinkParametersNR-r16 ::= SEQUENCE { + rlc-ParametersSidelink-r16 RLC-ParametersSidelink-r16 OPTIONAL, + mac-ParametersSidelink-r16 MAC-ParametersSidelink-r16 OPTIONAL, + fdd-Add-UE-Sidelink-Capabilities-r16 UE-SidelinkCapabilityAddXDD-Mode-r16 OPTIONAL, + tdd-Add-UE-Sidelink-Capabilities-r16 UE-SidelinkCapabilityAddXDD-Mode-r16 OPTIONAL, + supportedBandListSidelink-r16 SEQUENCE (SIZE (1..maxBands)) OF BandSidelink-r16 OPTIONAL, + ... +} + +SidelinkParametersEUTRA-r16 ::= SEQUENCE { + sl-ParametersEUTRA1-r16 OCTET STRING OPTIONAL, + sl-ParametersEUTRA2-r16 OCTET STRING OPTIONAL, + sl-ParametersEUTRA3-r16 OCTET STRING OPTIONAL, + supportedBandListSidelinkEUTRA-r16 SEQUENCE (SIZE (1..maxBandsEUTRA)) OF BandSidelinkEUTRA-r16 OPTIONAL, + ... +} + +RLC-ParametersSidelink-r16 ::= SEQUENCE { + am-WithLongSN-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + um-WithLongSN-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +MAC-ParametersSidelink-r16 ::= SEQUENCE { + mac-ParametersSidelinkCommon-r16 MAC-ParametersSidelinkCommon-r16 OPTIONAL, + mac-ParametersSidelinkXDD-Diff-r16 MAC-ParametersSidelinkXDD-Diff-r16 OPTIONAL, + ... +} + +UE-SidelinkCapabilityAddXDD-Mode-r16 ::= SEQUENCE { + mac-ParametersSidelinkXDD-Diff-r16 MAC-ParametersSidelinkXDD-Diff-r16 OPTIONAL +} + +MAC-ParametersSidelinkCommon-r16 ::= SEQUENCE { + lcp-RestrictionSidelink-r16 ENUMERATED {supported} OPTIONAL, + multipleConfiguredGrantsSidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +MAC-ParametersSidelinkXDD-Diff-r16 ::= SEQUENCE { + multipleSR-ConfigurationsSidelink-r16 ENUMERATED {supported} OPTIONAL, + logicalChannelSR-DelayTimerSidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +BandSidelinkEUTRA-r16 ::= SEQUENCE { + freqBandSidelinkEUTRA-r16 FreqBandIndicatorEUTRA, + -- R1 15-7: Transmitting LTE sidelink mode 3 scheduled by NR Uu + gnb-ScheduledMode3SidelinkEUTRA-r16 SEQUENCE { + gnb-ScheduledMode3DelaySidelinkEUTRA-r16 ENUMERATED {ms0, ms0dot25, ms0dot5, ms0dot625, ms0dot75, ms1, + ms1dot25, ms1dot5, ms1dot75, ms2, ms2dot5, ms3, ms4, + ms5, ms6, ms8, ms10, ms20} + } OPTIONAL, + -- R1 15-9: Transmitting LTE sidelink mode 4 configured by NR Uu + gnb-ScheduledMode4SidelinkEUTRA-r16 ENUMERATED {supported} OPTIONAL +} + +BandSidelink-r16 ::= SEQUENCE { + freqBandSidelink-r16 FreqBandIndicatorNR, + --15-1 + sl-Reception-r16 SEQUENCE { + harq-RxProcessSidelink-r16 ENUMERATED {n16, n24, n32, n48, n64}, + pscch-RxSidelink-r16 ENUMERATED {value1, value2}, + scs-CP-PatternRxSidelink-r16 CHOICE { + fr1-r16 SEQUENCE { + scs-15kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + }, + fr2-r16 SEQUENCE { + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-120kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + } + } OPTIONAL, + extendedCP-RxSidelink-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-2 + sl-TransmissionMode1-r16 SEQUENCE { + harq-TxProcessModeOneSidelink-r16 ENUMERATED {n8, n16}, + scs-CP-PatternTxSidelinkModeOne-r16 CHOICE { + fr1-r16 SEQUENCE { + scs-15kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + }, + fr2-r16 SEQUENCE { + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-120kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + } + }, + extendedCP-TxSidelink-r16 ENUMERATED {supported} OPTIONAL, + harq-ReportOnPUCCH-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-4 + sync-Sidelink-r16 SEQUENCE { + gNB-Sync-r16 ENUMERATED {supported} OPTIONAL, + gNB-GNSS-UE-SyncWithPriorityOnGNB-ENB-r16 ENUMERATED {supported} OPTIONAL, + gNB-GNSS-UE-SyncWithPriorityOnGNSS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-10 + sl-Tx-256QAM-r16 ENUMERATED {supported} OPTIONAL, + --15-11 + psfch-FormatZeroSidelink-r16 SEQUENCE { + psfch-RxNumber ENUMERATED {n5, n15, n25, n32, n35, n45, n50, n64}, + psfch-TxNumber ENUMERATED {n4, n8, n16} + } OPTIONAL, + --15-12 + lowSE-64QAM-MCS-TableSidelink-r16 ENUMERATED {supported} OPTIONAL, + --15-15 + enb-sync-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + ..., + [[ + --15-3 + sl-TransmissionMode2-r16 SEQUENCE { + harq-TxProcessModeTwoSidelink-r16 ENUMERATED {n8, n16}, + scs-CP-PatternTxSidelinkModeTwo-r16 ENUMERATED {supported} OPTIONAL, + dl-openLoopPC-Sidelink-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-5 + congestionControlSidelink-r16 SEQUENCE { + cbr-ReportSidelink-r16 ENUMERATED {supported} OPTIONAL, + cbr-CR-TimeLimitSidelink-r16 ENUMERATED {time1, time2} + } OPTIONAL, + --15-22 + fewerSymbolSlotSidelink-r16 ENUMERATED {supported} OPTIONAL, + --15-23 + sl-openLoopPC-RSRP-ReportSidelink-r16 ENUMERATED {supported} OPTIONAL, + --13-1 + sl-Rx-256QAM-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-SIDELINKPARAMETERS-STOP +-- TAG-SON-PARAMETERS-START + +SON-Parameters-r16 ::= SEQUENCE { + rach-Report-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-SON-PARAMETERS-STOP +-- TAG-SPATIALRELATIONSSRS-POS-START + +SpatialRelationsSRS-Pos-r16 ::= SEQUENCE { + spatialRelation-SRS-PosBasedOnSSB-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnCSI-RS-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnPRS-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnSRS-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnSSB-Neigh-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnPRS-Neigh-r16 ENUMERATED {supported} OPTIONAL +} + +--TAG-SPATIALRELATIONSSRS-POS-STOP +-- TAG-SRS-SWITCHINGTIMENR-START + +SRS-SwitchingTimeNR ::= SEQUENCE { + switchingTimeDL ENUMERATED {n0us, n30us, n100us, n140us, n200us, n300us, n500us, n900us} OPTIONAL, + switchingTimeUL ENUMERATED {n0us, n30us, n100us, n140us, n200us, n300us, n500us, n900us} OPTIONAL +} + +-- TAG-SRS-SWITCHINGTIMENR-STOP +-- TAG-SRS-SWITCHINGTIMEEUTRA-START + +SRS-SwitchingTimeEUTRA ::= SEQUENCE { + switchingTimeDL ENUMERATED {n0, n0dot5, n1, n1dot5, n2, n2dot5, n3, n3dot5, n4, n4dot5, n5, n5dot5, n6, n6dot5, n7} + OPTIONAL, + switchingTimeUL ENUMERATED {n0, n0dot5, n1, n1dot5, n2, n2dot5, n3, n3dot5, n4, n4dot5, n5, n5dot5, n6, n6dot5, n7} + OPTIONAL +} +-- TAG-SRS-SWITCHINGTIMEEUTRA-STOP +-- TAG-SUPPORTEDBANDWIDTH-START + +SupportedBandwidth ::= CHOICE { + fr1 ENUMERATED {mhz5, mhz10, mhz15, mhz20, mhz25, mhz30, mhz40, mhz50, mhz60, mhz80, mhz100}, + fr2 ENUMERATED {mhz50, mhz100, mhz200, mhz400} +} + +-- TAG-SUPPORTEDBANDWIDTH-STOP +-- TAG-UE-BASEDPERFMEAS-PARAMETERS-START + +UE-BasedPerfMeas-Parameters-r16 ::= SEQUENCE { + barometerMeasReport-r16 ENUMERATED {supported} OPTIONAL, + immMeasBT-r16 ENUMERATED {supported} OPTIONAL, + immMeasWLAN-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasBT-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasurements-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasWLAN-r16 ENUMERATED {supported} OPTIONAL, + orientationMeasReport-r16 ENUMERATED {supported} OPTIONAL, + speedMeasReport-r16 ENUMERATED {supported} OPTIONAL, + gnss-Location-r16 ENUMERATED {supported} OPTIONAL, + ulPDCP-Delay-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-UE-BASEDPERFMEAS-PARAMETERS-STOP +-- TAG-UE-CAPABILITYRAT-CONTAINERLIST-START + +UE-CapabilityRAT-ContainerList ::= SEQUENCE (SIZE (0..maxRAT-CapabilityContainers)) OF UE-CapabilityRAT-Container + +UE-CapabilityRAT-Container ::= SEQUENCE { + rat-Type RAT-Type, + ue-CapabilityRAT-Container OCTET STRING +} + +-- TAG-UE-CAPABILITYRAT-CONTAINERLIST-STOP +-- TAG-UE-CAPABILITYRAT-REQUESTLIST-START + +UE-CapabilityRAT-RequestList ::= SEQUENCE (SIZE (1..maxRAT-CapabilityContainers)) OF UE-CapabilityRAT-Request + +UE-CapabilityRAT-Request ::= SEQUENCE { + rat-Type RAT-Type, + capabilityRequestFilter OCTET STRING OPTIONAL, -- Need N + ... +} + +-- TAG-UE-CAPABILITYRAT-REQUESTLIST-STOP +-- TAG-UE-CAPABILITYREQUESTFILTERCOMMON-START + +UE-CapabilityRequestFilterCommon ::= SEQUENCE { + mrdc-Request SEQUENCE { + omitEN-DC ENUMERATED {true} OPTIONAL, -- Need N + includeNR-DC ENUMERATED {true} OPTIONAL, -- Need N + includeNE-DC ENUMERATED {true} OPTIONAL -- Need N + } OPTIONAL, -- Need N + ..., + [[ + codebookTypeRequest-r16 SEQUENCE { + type1-SinglePanel-r16 ENUMERATED {true} OPTIONAL, -- Need N + type1-MultiPanel-r16 ENUMERATED {true} OPTIONAL, -- Need N + type2-r16 ENUMERATED {true} OPTIONAL, -- Need N + type2-PortSelection-r16 ENUMERATED {true} OPTIONAL -- Need N + } OPTIONAL, -- Need N + uplinkTxSwitchRequest-r16 ENUMERATED {true} OPTIONAL -- Need N + ]] +} + +-- TAG-UE-CAPABILITYREQUESTFILTERCOMMON-STOP +-- TAG-UE-CAPABILITYREQUESTFILTERNR-START + +UE-CapabilityRequestFilterNR ::= SEQUENCE { + frequencyBandListFilter FreqBandList OPTIONAL, -- Need N + nonCriticalExtension UE-CapabilityRequestFilterNR-v1540 OPTIONAL +} + +UE-CapabilityRequestFilterNR-v1540 ::= SEQUENCE { + srs-SwitchingTimeRequest ENUMERATED {true} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UE-CAPABILITYREQUESTFILTERNR-STOP +-- TAG-UE-MRDC-CAPABILITY-START + +UE-MRDC-Capability ::= SEQUENCE { + measAndMobParametersMRDC MeasAndMobParametersMRDC OPTIONAL, + phy-ParametersMRDC-v1530 Phy-ParametersMRDC OPTIONAL, + rf-ParametersMRDC RF-ParametersMRDC, + generalParametersMRDC GeneralParametersMRDC-XDD-Diff OPTIONAL, + fdd-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + featureSetCombinations SEQUENCE (SIZE (1..maxFeatureSetCombinations)) OF FeatureSetCombination OPTIONAL, + pdcp-ParametersMRDC-v1530 PDCP-ParametersMRDC OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UE-MRDC-Capability-v1560 OPTIONAL +} + +UE-MRDC-Capability-v1560 ::= SEQUENCE { + receivedFilters OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL, + measAndMobParametersMRDC-v1560 MeasAndMobParametersMRDC-v1560 OPTIONAL, + fdd-Add-UE-MRDC-Capabilities-v1560 UE-MRDC-CapabilityAddXDD-Mode-v1560 OPTIONAL, + tdd-Add-UE-MRDC-Capabilities-v1560 UE-MRDC-CapabilityAddXDD-Mode-v1560 OPTIONAL, + nonCriticalExtension UE-MRDC-Capability-v1610 OPTIONAL +} + +UE-MRDC-Capability-v1610 ::= SEQUENCE { + measAndMobParametersMRDC-v1610 MeasAndMobParametersMRDC-v1610 OPTIONAL, + generalParametersMRDC-v1610 GeneralParametersMRDC-v1610 OPTIONAL, + pdcp-ParametersMRDC-v1610 PDCP-ParametersMRDC-v1610 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-MRDC-CapabilityAddXDD-Mode ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff MeasAndMobParametersMRDC-XDD-Diff OPTIONAL, + generalParametersMRDC-XDD-Diff GeneralParametersMRDC-XDD-Diff OPTIONAL +} + +UE-MRDC-CapabilityAddXDD-Mode-v1560 ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff-v1560 MeasAndMobParametersMRDC-XDD-Diff-v1560 OPTIONAL +} + +UE-MRDC-CapabilityAddFRX-Mode ::= SEQUENCE { + measAndMobParametersMRDC-FRX-Diff MeasAndMobParametersMRDC-FRX-Diff +} + + +GeneralParametersMRDC-XDD-Diff ::= SEQUENCE { + splitSRB-WithOneUL-Path ENUMERATED {supported} OPTIONAL, + splitDRB-withUL-Both-MCG-SCG ENUMERATED {supported} OPTIONAL, + srb3 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + ... +} + +GeneralParametersMRDC-v1610 ::= SEQUENCE { + f1c-OverEUTRA-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-UE-MRDC-CAPABILITY-STOP +-- TAG-UE-NR-CAPABILITY-START + +UE-NR-Capability ::= SEQUENCE { + accessStratumRelease AccessStratumRelease, + pdcp-Parameters PDCP-Parameters, + rlc-Parameters RLC-Parameters OPTIONAL, + mac-Parameters MAC-Parameters OPTIONAL, + phy-Parameters Phy-Parameters, + rf-Parameters RF-Parameters, + measAndMobParameters MeasAndMobParameters OPTIONAL, + fdd-Add-UE-NR-Capabilities UE-NR-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-NR-Capabilities UE-NR-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + featureSets FeatureSets OPTIONAL, + featureSetCombinations SEQUENCE (SIZE (1..maxFeatureSetCombinations)) OF FeatureSetCombination OPTIONAL, + lateNonCriticalExtension OCTET STRING (CONTAINING UE-NR-Capability-v15c0) OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1530 OPTIONAL +} + +-- Regular non-critical extensions: +UE-NR-Capability-v1530 ::= SEQUENCE { + fdd-Add-UE-NR-Capabilities-v1530 UE-NR-CapabilityAddXDD-Mode-v1530 OPTIONAL, + tdd-Add-UE-NR-Capabilities-v1530 UE-NR-CapabilityAddXDD-Mode-v1530 OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + interRAT-Parameters InterRAT-Parameters OPTIONAL, + inactiveState ENUMERATED {supported} OPTIONAL, + delayBudgetReporting ENUMERATED {supported} OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1540 OPTIONAL +} + +UE-NR-Capability-v1540 ::= SEQUENCE { + sdap-Parameters SDAP-Parameters OPTIONAL, + overheatingInd ENUMERATED {supported} OPTIONAL, + ims-Parameters IMS-Parameters OPTIONAL, + fr1-Add-UE-NR-Capabilities-v1540 UE-NR-CapabilityAddFRX-Mode-v1540 OPTIONAL, + fr2-Add-UE-NR-Capabilities-v1540 UE-NR-CapabilityAddFRX-Mode-v1540 OPTIONAL, + fr1-fr2-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1550 OPTIONAL +} + +UE-NR-Capability-v1550 ::= SEQUENCE { + reducedCP-Latency ENUMERATED {supported} OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1560 OPTIONAL +} + +UE-NR-Capability-v1560 ::= SEQUENCE { + nrdc-Parameters NRDC-Parameters OPTIONAL, + receivedFilters OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1570 OPTIONAL +} + +UE-NR-Capability-v1570 ::= SEQUENCE { + nrdc-Parameters-v1570 NRDC-Parameters-v1570 OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1610 OPTIONAL +} + +-- Late non-critical extensions: +UE-NR-Capability-v15c0 ::= SEQUENCE { + nrdc-Parameters-v15c0 NRDC-Parameters-v15c0 OPTIONAL, + partialFR2-FallbackRX-Req ENUMERATED {true} OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- Regular non-critical extensions: +UE-NR-Capability-v1610 ::= SEQUENCE { + inDeviceCoexInd-r16 ENUMERATED {supported} OPTIONAL, + dl-DedicatedMessageSegmentation-r16 ENUMERATED {supported} OPTIONAL, + nrdc-Parameters-v1610 NRDC-Parameters-v1610 OPTIONAL, + powSav-Parameters-r16 PowSav-Parameters-r16 OPTIONAL, + fr1-Add-UE-NR-Capabilities-v1610 UE-NR-CapabilityAddFRX-Mode-v1610 OPTIONAL, + fr2-Add-UE-NR-Capabilities-v1610 UE-NR-CapabilityAddFRX-Mode-v1610 OPTIONAL, + bh-RLF-Indication-r16 ENUMERATED {supported} OPTIONAL, + directSN-AdditionFirstRRC-IAB-r16 ENUMERATED {supported} OPTIONAL, + bap-Parameters-r16 BAP-Parameters-r16 OPTIONAL, + referenceTimeProvision-r16 ENUMERATED {supported} OPTIONAL, + sidelinkParameters-r16 SidelinkParameters-r16 OPTIONAL, + highSpeedParameters-r16 HighSpeedParameters-r16 OPTIONAL, + mac-Parameters-v1610 MAC-Parameters-v1610 OPTIONAL, + mcgRLF-RecoveryViaSCG-r16 ENUMERATED {supported} OPTIONAL, + resumeWithStoredMCG-SCells-r16 ENUMERATED {supported} OPTIONAL, + resumeWithStoredSCG-r16 ENUMERATED {supported} OPTIONAL, + resumeWithSCG-Config-r16 ENUMERATED {supported} OPTIONAL, + ue-BasedPerfMeas-Parameters-r16 UE-BasedPerfMeas-Parameters-r16 OPTIONAL, + son-Parameters-r16 SON-Parameters-r16 OPTIONAL, + onDemandSIB-Connected-r16 ENUMERATED {supported} OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1640 OPTIONAL +} + +UE-NR-Capability-v1640 ::= SEQUENCE { + redirectAtResumeByNAS-r16 ENUMERATED {supported} OPTIONAL, + phy-ParametersSharedSpectrumChAccess-r16 Phy-ParametersSharedSpectrumChAccess-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-NR-CapabilityAddXDD-Mode ::= SEQUENCE { + phy-ParametersXDD-Diff Phy-ParametersXDD-Diff OPTIONAL, + mac-ParametersXDD-Diff MAC-ParametersXDD-Diff OPTIONAL, + measAndMobParametersXDD-Diff MeasAndMobParametersXDD-Diff OPTIONAL +} + +UE-NR-CapabilityAddXDD-Mode-v1530 ::= SEQUENCE { + eutra-ParametersXDD-Diff EUTRA-ParametersXDD-Diff +} + +UE-NR-CapabilityAddFRX-Mode ::= SEQUENCE { + phy-ParametersFRX-Diff Phy-ParametersFRX-Diff OPTIONAL, + measAndMobParametersFRX-Diff MeasAndMobParametersFRX-Diff OPTIONAL +} + +UE-NR-CapabilityAddFRX-Mode-v1540 ::= SEQUENCE { + ims-ParametersFRX-Diff IMS-ParametersFRX-Diff OPTIONAL +} + +UE-NR-CapabilityAddFRX-Mode-v1610 ::= SEQUENCE { + powSav-ParametersFRX-Diff-r16 PowSav-ParametersFRX-Diff-r16 OPTIONAL, + mac-ParametersFRX-Diff-r16 MAC-ParametersFRX-Diff-r16 OPTIONAL +} + +BAP-Parameters-r16 ::= SEQUENCE { + flowControlBH-RLC-ChannelBased-r16 ENUMERATED {supported} OPTIONAL, + flowControlRouting-ID-Based-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-UE-NR-CAPABILITY-STOP +-- TAG-SHAREDSPECTRUMCHACCESSPARAMSPERBAND-START + +SharedSpectrumChAccessParamsPerBand-r16 ::= SEQUENCE { + + -- R1 10-1: UL channel access for dynamic channel access mode + ul-DynamicChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-1a: UL channel access for semi-static channel access mode + ul-Semi-StaticChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2: SSB-based RRM for dynamic channel access mode + ssb-RRM-DynamicChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2a: SSB-based RRM for semi-static channel access mode + ssb-RRM-Semi-StaticChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2b: MIB reading on unlicensed cell + mib-Acquisition-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2c: SSB-based RLM for dynamic channel access mode + ssb-RLM-DynamicChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2d: SSB-based RLM for semi-static channel access mode + ssb-RLM-Semi-StaticChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2e: SIB1 reception on unlicensed cell + sib1-Acquisition-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2f: Support monitoring of extended RAR window + extRA-ResponseWindow-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2g: SSB-based BFD/CBD for dynamic channel access mode + ssb-BFD-CBD-dynamicChannelAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2h: SSB-based BFD/CBD for semi-static channel access mode + ssb-BFD-CBD-semi-staticChannelAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2i: CSI-RS-based BFD/CBD for NR-U + csi-RS-BFD-CBD-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-7: UL channel access for 10 MHz SCell + ul-ChannelBW-SCell-10mhz-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-10: RSSI and channel occupancy measurement and reporting + rssi-ChannelOccupancyReporting-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-11:SRS starting position at any OFDM symbol in a slot + srs-StartAnyOFDM-Symbol-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-20: Support search space set configuration with freqMonitorLocation-r16 + searchSpaceFreqMonitorLocation-r16 INTEGER (1..5) OPTIONAL, + -- R1 10-20a: Support coreset configuration with rb-Offset + coreset-RB-Offset-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-23:CGI reading on unlicensed cell for ANR functionality + cgi-Acquisition-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-25: Enable configured UL transmissions when DCI 2_0 is configured but not detected + configuredUL-Tx-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-27: Wideband PRACH + prach-Wideband-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-29: Support available RB set indicator field in DCI 2_0 + dci-AvailableRB-Set-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-30: Support channel occupancy duration indicator field in DCI 2_0 + dci-ChOccupancyDuration-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-8: Type B PDSCH length {3, 5, 6, 8, 9, 10, 11, 12, 13} without DMRS shift due to CRS collision + typeB-PDSCH-length-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9: Search space set group switching with explicit DCI 2_0 bit field trigger or with implicit PDCCH decoding with DCI 2_0 monitoring + searchSpaceSetGroupSwitchingwithDCI-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9b: Search space set group switching with implicit PDCCH decoding without DCI 2_0 monitoring FFS:per band or per UE + searchSpaceSetGroupSwitchingwithoutDCI-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9d: Support Search space set group switching capability 2 + searchSpaceSetGroupSwitchingcapability2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-14: Non-numerical PDSCH to HARQ-ACK timing + non-numericalPDSCH-HARQ-timing-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-15: Enhanced dynamic HARQ codebook + enhancedDynamicHARQ-codebook-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-16: One-shot HARQ ACK feedback + oneShotHARQ-feedback-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-17: Multi-PUSCH UL grant + multiPUSCH-UL-grant-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-26: CSI-RS based RLM for NR-U + csi-RS-RLM-r16 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + -- R1 10-31: Support of P/SP-CSI-RS reception with CSI-RS-ValidationWith-DCI-r16 configured + periodicAndSemi-PersistentCSI-RS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-3: PRB interlace mapping for PUSCH + pusch-PRB-interlace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-3a: PRB interlace mapping for PUCCH + pucch-F0-F1-PRB-Interlace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-12: OCC for PRB interlace mapping for PF2 and PF3 + occ-PRB-PF2-PF3-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-13a: Extended CP range of more than one symbol for CG-PUSCH + extCP-rangeCG-PUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-18: Configured grant with retransmission in CG resources + configuredGrantWithReTx-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-21a: Support using ED threshold given by gNB for UL to DL COT sharing + ed-Threshold-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-21b: Support UL to DL COT sharing + ul-DL-COT-Sharing-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-24: CG-UCI multiplexing with HARQ ACK + mux-CG-UCI-HARQ-ACK-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-28: Configured grant with Rel-16 enhanced resource configuration + cg-resourceConfig-r16 ENUMERATED {supported} OPTIONAL +} + +SharedSpectrumChAccessParamsPerBand-v1630 ::= SEQUENCE { + -- R4 4-1: DL reception in intra-carrier guardband + dl-ReceptionIntraCellGuardband-r16 ENUMERATED {supported} OPTIONAL, + -- R4 4-2: DL reception when gNB does not transmit on all RB sets of a carrier as a result of LBT + dl-ReceptionLBT-subsetRB-r16 ENUMERATED {supported} OPTIONAL +} + +SharedSpectrumChAccessParamsPerBand-v1640 ::= SEQUENCE { + -- 10-26b(1-4): CSI-RS based RRM measurement with associated SS-block + csi-RSRP-AndRSRQ-MeasWithSSB-r16 ENUMERATED {supported} OPTIONAL, + -- 10-26c(1-5): CSI-RS based RRM measurement without associated SS-block + csi-RSRP-AndRSRQ-MeasWithoutSSB-r16 ENUMERATED {supported} OPTIONAL, + -- 10-26d(1-6): CSI-RS based RS-SINR measurement + csi-SINR-Meas-r16 ENUMERATED {supported} OPTIONAL, + -- 10-26e(1-8): RLM based on a mix of SS block and CSI-RS signals within active BWP + ssb-AndCSI-RS-RLM-r16 ENUMERATED {supported} OPTIONAL, + -- 10-26f(1-9): CSI-RS based contention free RA for HO + csi-RS-CFRA-ForHO-r16 ENUMERATED {supported} OPTIONAL +} +-- TAG-SHAREDSPECTRUMCHACCESSPARAMSPERBAND-STOP +-- TAG-ABSOLUTETIMEINFO-START + +AbsoluteTimeInfo-r16 ::= BIT STRING (SIZE (48)) + +-- TAG-ABSOLUTETIMEINFO-STOP +-- TAG-AREACONFIGURATION-START + +AreaConfiguration-r16 ::= SEQUENCE { + areaConfig-r16 AreaConfig-r16, + interFreqTargetList-r16 SEQUENCE(SIZE (1..maxFreq)) OF InterFreqTargetInfo-r16 OPTIONAL -- Need R +} + +AreaConfig-r16 ::= CHOICE { + cellGlobalIdList-r16 CellGlobalIdList-r16, + trackingAreaCodeList-r16 TrackingAreaCodeList-r16, + trackingAreaIdentityList-r16 TrackingAreaIdentityList-r16 +} + +InterFreqTargetInfo-r16 ::= SEQUENCE { + dl-CarrierFreq ARFCN-ValueNR, + cellList SEQUENCE (SIZE (1..32)) OF PhysCellId OPTIONAL +} + +CellGlobalIdList-r16 ::= SEQUENCE (SIZE (1..32)) OF CGI-Info-Logging-r16 + +TrackingAreaCodeList-r16 ::= SEQUENCE (SIZE (1..8)) OF TrackingAreaCode + +TrackingAreaIdentityList-r16 ::= SEQUENCE (SIZE (1..8)) OF TrackingAreaIdentity-r16 + +TrackingAreaIdentity-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + trackingAreaCode-r16 TrackingAreaCode +} + +-- TAG-AREACONFIGURATION-STOP +-- TAG-BTNAMELIST-START + +BT-NameList-r16 ::= SEQUENCE (SIZE (1..maxBT-Name-r16)) OF BT-Name-r16 + +BT-Name-r16 ::= OCTET STRING (SIZE (1..248)) + +-- TAG-BTNAMELIST-STOP +-- TAG-EUTRA-ALLOWEDMEASBANDWIDTH-START + +EUTRA-AllowedMeasBandwidth ::= ENUMERATED {mbw6, mbw15, mbw25, mbw50, mbw75, mbw100} + +-- TAG-EUTRA-ALLOWEDMEASBANDWIDTH-STOP +-- TAG-EUTRA-MBSFN-SUBFRAMECONFIGLIST-START + +EUTRA-MBSFN-SubframeConfigList ::= SEQUENCE (SIZE (1..maxMBSFN-Allocations)) OF EUTRA-MBSFN-SubframeConfig + +EUTRA-MBSFN-SubframeConfig ::= SEQUENCE { + radioframeAllocationPeriod ENUMERATED {n1, n2, n4, n8, n16, n32}, + radioframeAllocationOffset INTEGER (0..7), + subframeAllocation1 CHOICE { + oneFrame BIT STRING (SIZE(6)), + fourFrames BIT STRING (SIZE(24)) + }, + subframeAllocation2 CHOICE { + oneFrame BIT STRING (SIZE(2)), + fourFrames BIT STRING (SIZE(8)) + } OPTIONAL, -- Need R + ... +} + +-- TAG-EUTRA-MBSFN-SUBFRAMECONFIGLIST-STOP +-- TAG-EUTRA-MULTIBANDINFOLIST-START + +EUTRA-MultiBandInfoList ::= SEQUENCE (SIZE (1..maxMultiBands)) OF EUTRA-MultiBandInfo + +EUTRA-MultiBandInfo ::= SEQUENCE { + eutra-FreqBandIndicator FreqBandIndicatorEUTRA, + eutra-NS-PmaxList EUTRA-NS-PmaxList OPTIONAL -- Need R +} + +-- TAG-EUTRA-MULTIBANDINFOLIST-STOP +-- TAG-EUTRA-NS-PMAXLIST-START + +EUTRA-NS-PmaxList ::= SEQUENCE (SIZE (1..maxEUTRA-NS-Pmax)) OF EUTRA-NS-PmaxValue + +EUTRA-NS-PmaxValue ::= SEQUENCE { + additionalPmax INTEGER (-30..33) OPTIONAL, -- Need R + additionalSpectrumEmission INTEGER (1..288) OPTIONAL -- Need R +} + +-- TAG-EUTRA-NS-PMAXLIST-STOP +-- TAG-EUTRA-PHYSCELLID-START + +EUTRA-PhysCellId ::= INTEGER (0..503) + +-- TAG-EUTRA-PHYSCELLID-STOP +-- TAG-EUTRA-PHYSCELLIDRANGE-START + +EUTRA-PhysCellIdRange ::= SEQUENCE { + start EUTRA-PhysCellId, + range ENUMERATED {n4, n8, n12, n16, n24, n32, n48, n64, n84, n96, + n128, n168, n252, n504, spare2, spare1} OPTIONAL -- Need N +} + +-- TAG-EUTRA-PHYSCELLIDRANGE-STOP +-- TAG-EUTRA-PRESENCEANTENNAPORT1-START + +EUTRA-PresenceAntennaPort1 ::= BOOLEAN + +-- TAG-EUTRA-PRESENCEANTENNAPORT1-STOP +-- TAG-EUTRA-Q-OFFSETRANGE-START + +EUTRA-Q-OffsetRange ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-EUTRA-Q-OFFSETRANGE-STOP +-- TAG-IABIPADDRESS-START + +IAB-IP-Address-r16 ::= CHOICE { + iPv4-Address-r16 BIT STRING (SIZE(32)), + iPv6-Address-r16 BIT STRING (SIZE(128)), + iPv6-Prefix-r16 BIT STRING (SIZE(64)), + ... +} + +-- TAG-IABIPADDRESS-STOP +-- TAG-IABIPADDRESSINDEX-START + +IAB-IP-AddressIndex-r16 ::= INTEGER (1..maxIAB-IP-Address-r16) + +-- TAG-IABIPADDRESSINDEX-STOP +-- TAG-IAB-IP-USAGE-START + +IAB-IP-Usage-r16 ::= ENUMERATED {f1-C, f1-U, non-F1, spare} + +-- TAG-IAB-IP-USAGE-STOP +-- TAG-LOGGINGDURATION-START + +LoggingDuration-r16 ::= ENUMERATED { + min10, min20, min40, min60, min90, min120, spare2, spare1} + +-- TAG-LOGGINGDURATION-STOP +-- TAG-LOGGINGINTERVAL-START + +LoggingInterval-r16 ::= ENUMERATED { + ms320, ms640, ms1280, ms2560, ms5120, ms10240, ms20480, + ms30720, ms40960, ms61440 , infinity} + +-- TAG-LOGGINGINTERVAL-STOP +-- TAG-LOGMEASRESULTLISTBT-START + +LogMeasResultListBT-r16 ::= SEQUENCE (SIZE (1..maxBT-IdReport-r16)) OF LogMeasResultBT-r16 + +LogMeasResultBT-r16 ::= SEQUENCE { + bt-Addr-r16 BIT STRING (SIZE (48)), + rssi-BT-r16 INTEGER (-128..127) OPTIONAL, + ... +} + +-- TAG-LOGMEASRESULTLISTBT-STOP +-- TAG-LOGMEASRESULTLISTWLAN-START + +LogMeasResultListWLAN-r16 ::= SEQUENCE (SIZE (1..maxWLAN-Id-Report-r16)) OF LogMeasResultWLAN-r16 + +LogMeasResultWLAN-r16 ::= SEQUENCE { + wlan-Identifiers-r16 WLAN-Identifiers-r16, + rssiWLAN-r16 WLAN-RSSI-Range-r16 OPTIONAL, + rtt-WLAN-r16 WLAN-RTT-r16 OPTIONAL, + ... +} + +WLAN-Identifiers-r16 ::= SEQUENCE { + ssid-r16 OCTET STRING (SIZE (1..32)) OPTIONAL, + bssid-r16 OCTET STRING (SIZE (6)) OPTIONAL, + hessid-r16 OCTET STRING (SIZE (6)) OPTIONAL, + ... +} + +WLAN-RSSI-Range-r16 ::= INTEGER(0..141) + +WLAN-RTT-r16 ::= SEQUENCE { + rttValue-r16 INTEGER (0..16777215), + rttUnits-r16 ENUMERATED { + microseconds, + hundredsofnanoseconds, + tensofnanoseconds, + nanoseconds, + tenthsofnanoseconds, + ...}, + rttAccuracy-r16 INTEGER (0..255) OPTIONAL, + ... +} + +-- TAG-OTHERCONFIG-START + +OtherConfig ::= SEQUENCE { + delayBudgetReportingConfig CHOICE{ + release NULL, + setup SEQUENCE{ + delayBudgetReportingProhibitTimer ENUMERATED {s0, s0dot4, s0dot8, s1dot6, s3, s6, s12, s30} + } + } OPTIONAL -- Need M +} + +OtherConfig-v1540 ::= SEQUENCE { + overheatingAssistanceConfig SetupRelease {OverheatingAssistanceConfig} OPTIONAL, -- Need M + ... +} +CandidateServingFreqListNR-r16 ::= SEQUENCE (SIZE (1..maxFreqIDC-r16)) OF ARFCN-ValueNR + +OtherConfig-v1610 ::= SEQUENCE { + idc-AssistanceConfig-r16 SetupRelease {IDC-AssistanceConfig-r16} OPTIONAL, -- Need M + drx-PreferenceConfig-r16 SetupRelease {DRX-PreferenceConfig-r16} OPTIONAL, -- Need M + maxBW-PreferenceConfig-r16 SetupRelease {MaxBW-PreferenceConfig-r16} OPTIONAL, -- Need M + maxCC-PreferenceConfig-r16 SetupRelease {MaxCC-PreferenceConfig-r16} OPTIONAL, -- Need M + maxMIMO-LayerPreferenceConfig-r16 SetupRelease {MaxMIMO-LayerPreferenceConfig-r16} OPTIONAL, -- Need M + minSchedulingOffsetPreferenceConfig-r16 SetupRelease {MinSchedulingOffsetPreferenceConfig-r16} OPTIONAL, -- Need M + releasePreferenceConfig-r16 SetupRelease {ReleasePreferenceConfig-r16} OPTIONAL, -- Need M + referenceTimePreferenceReporting-r16 ENUMERATED {true} OPTIONAL, -- Need R + btNameList-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + wlanNameList-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + sensorNameList-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, -- Need M + obtainCommonLocation-r16 ENUMERATED {true} OPTIONAL, -- Need R + sl-AssistanceConfigNR-r16 ENUMERATED{true} OPTIONAL -- Need R +} + +OverheatingAssistanceConfig ::= SEQUENCE { + overheatingIndicationProhibitTimer ENUMERATED {s0, s0dot5, s1, s2, s5, s10, s20, s30, + s60, s90, s120, s300, s600, spare3, spare2, spare1} +} + +IDC-AssistanceConfig-r16 ::= SEQUENCE { + candidateServingFreqListNR-r16 CandidateServingFreqListNR-r16 OPTIONAL, -- Need R + ... +} + +DRX-PreferenceConfig-r16 ::= SEQUENCE { + drx-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxBW-PreferenceConfig-r16 ::= SEQUENCE { + maxBW-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxCC-PreferenceConfig-r16 ::= SEQUENCE { + maxCC-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxMIMO-LayerPreferenceConfig-r16 ::= SEQUENCE { + maxMIMO-LayerPreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MinSchedulingOffsetPreferenceConfig-r16 ::= SEQUENCE { + minSchedulingOffsetPreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +ReleasePreferenceConfig-r16 ::= SEQUENCE { + releasePreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, infinity, spare1}, + connectedReporting ENUMERATED {true} OPTIONAL -- Need R +} + +-- TAG-OTHERCONFIG-STOP +-- TAG-PHYSCELLIDUTRA-FDD-START + +PhysCellIdUTRA-FDD-r16 ::= INTEGER (0..511) + +-- TAG-PHYSCELLIDUTRA-FDD-STOP +-- TAG-RRC-TRANSACTIONIDENTIFIER-START + +RRC-TransactionIdentifier ::= INTEGER (0..3) + +-- TAG-RRC-TRANSACTIONIDENTIFIER-STOP +-- TAG-SENSORNAMELIST-START + +Sensor-NameList-r16 ::= SEQUENCE { + measUncomBarPre-r16 ENUMERATED {true} OPTIONAL, -- Need R + measUeSpeed ENUMERATED {true} OPTIONAL, -- Need R + measUeOrientation ENUMERATED {true} OPTIONAL -- Need R +} + +-- TAG-SENSORNAMELIST-STOP +-- TAG-TRACEREFERENCE-START + +TraceReference-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + traceId-r16 OCTET STRING (SIZE (3)) +} + +-- TAG-TRACEREFERENCE-STOP +-- TAG-UE-MeasurementsAvailable-START + +UE-MeasurementsAvailable-r16 ::= SEQUENCE { + logMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableBT-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableWLAN-r16 ENUMERATED {true} OPTIONAL, + connEstFailInfoAvailable-r16 ENUMERATED {true} OPTIONAL, + rlf-InfoAvailable-r16 ENUMERATED {true} OPTIONAL, + ... +} + +-- TAG-UE-MeasurementsAvailable-STOP +-- TAG-UTRA-FDD-Q-OFFSETRANGE-START + +UTRA-FDD-Q-OffsetRange-r16 ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-UTRA-FDD-Q-OFFSETRANGE-STOP +-- TAG-VISITEDCELLINFOLIST-START + +VisitedCellInfoList-r16 ::= SEQUENCE (SIZE (1..maxCellHistory-r16)) OF VisitedCellInfo-r16 + +VisitedCellInfo-r16 ::= SEQUENCE { + visitedCellId-r16 CHOICE { + nr-CellId-r16 CHOICE { + cgi-Info CGI-Info-Logging-r16, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 PhysCellId, + carrierFreq-r16 ARFCN-ValueNR + } + }, + eutra-CellId-r16 CHOICE { + cellGlobalId-r16 CGI-InfoEUTRA, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 EUTRA-PhysCellId, + carrierFreq-r16 ARFCN-ValueEUTRA + } + } + } OPTIONAL, + timeSpent-r16 INTEGER (0..4095), + ... +} + +-- TAG-VISITEDCELLINFOLIST-STOP +-- TAG-WLANNAMELIST-START + +WLAN-NameList-r16 ::= SEQUENCE (SIZE (1..maxWLAN-Name-r16)) OF WLAN-Name-r16 + +WLAN-Name-r16 ::= OCTET STRING (SIZE (1..32)) + +-- TAG-SL-BWP-CONFIG-START + +SL-BWP-Config-r16 ::= SEQUENCE { + sl-BWP-Id BWP-Id, + sl-BWP-Generic-r16 SL-BWP-Generic-r16 OPTIONAL, -- Need M + sl-BWP-PoolConfig-r16 SL-BWP-PoolConfig-r16 OPTIONAL, -- Need M + ... +} + +SL-BWP-Generic-r16 ::= SEQUENCE { + sl-BWP-r16 BWP OPTIONAL, -- Need M + sl-LengthSymbols-r16 ENUMERATED {sym7, sym8, sym9, sym10, sym11, sym12, sym13, sym14} OPTIONAL, -- Need M + sl-StartSymbol-r16 ENUMERATED {sym0, sym1, sym2, sym3, sym4, sym5, sym6, sym7} OPTIONAL, -- Need M + sl-PSBCH-Config-r16 SetupRelease {SL-PSBCH-Config-r16} OPTIONAL, -- Need M + sl-TxDirectCurrentLocation-r16 INTEGER (0..3301) OPTIONAL, -- Need M + ... +} + +-- TAG-SL-BWP-CONFIG-STOP +-- TAG-SL-BWP-CONFIGCOMMON-START + +SL-BWP-ConfigCommon-r16 ::= SEQUENCE { + sl-BWP-Generic-r16 SL-BWP-Generic-r16 OPTIONAL, -- Need R + sl-BWP-PoolConfigCommon-r16 SL-BWP-PoolConfigCommon-r16 OPTIONAL, -- Need R + ... +} + +-- TAG-SL-BWP-CONFIGCOMMON-STOP +-- TAG-SL-BWP-POOLCONFIG-START + +SL-BWP-PoolConfig-r16 ::= SEQUENCE { + sl-RxPool-r16 SEQUENCE (SIZE (1..maxNrofRXPool-r16)) OF SL-ResourcePool-r16 OPTIONAL, -- Cond HO + sl-TxPoolSelectedNormal-r16 SL-TxPoolDedicated-r16 OPTIONAL, -- Need M + sl-TxPoolScheduling-r16 SL-TxPoolDedicated-r16 OPTIONAL, -- Need N + sl-TxPoolExceptional-r16 SL-ResourcePoolConfig-r16 OPTIONAL -- Need M +} + +SL-TxPoolDedicated-r16 ::= SEQUENCE { + sl-PoolToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolID-r16 OPTIONAL, -- Need N + sl-PoolToAddModList-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolConfig-r16 OPTIONAL -- Need N +} + +SL-ResourcePoolConfig-r16 ::= SEQUENCE { + sl-ResourcePoolID-r16 SL-ResourcePoolID-r16, + sl-ResourcePool-r16 SL-ResourcePool-r16 OPTIONAL -- Need M +} + +SL-ResourcePoolID-r16 ::= INTEGER (1..maxNrofPoolID-r16) + +-- TAG-SL-BWP-POOLCONFIG-STOP +-- TAG-SL-BWP-POOLCONFIGCOMMON-START + +SL-BWP-PoolConfigCommon-r16 ::= SEQUENCE { + sl-RxPool-r16 SEQUENCE (SIZE (1..maxNrofRXPool-r16)) OF SL-ResourcePool-r16 OPTIONAL, -- Need R + sl-TxPoolSelectedNormal-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolConfig-r16 OPTIONAL, -- Need R + sl-TxPoolExceptional-r16 SL-ResourcePoolConfig-r16 OPTIONAL -- Need R +} + +-- TAG-SL-BWP-POOLCONFIGCOMMON-STOP +-- TAG-SL-CBR-PRIORITYTXCONFIGLIST-START + +SL-CBR-PriorityTxConfigList-r16 ::= SEQUENCE (SIZE (1..8)) OF SL-PriorityTxConfigIndex-r16 + +SL-PriorityTxConfigIndex-r16 ::= SEQUENCE { + sl-PriorityThreshold-r16 INTEGER (1..8) OPTIONAL, -- Need M + sl-DefaultTxConfigIndex-r16 INTEGER (0..maxCBR-Level-1-r16) OPTIONAL, -- Need M + sl-CBR-ConfigIndex-r16 INTEGER (0..maxCBR-Config-1-r16) OPTIONAL, -- Need M + sl-Tx-ConfigIndexList-r16 SEQUENCE (SIZE (1.. maxCBR-Level-r16)) OF SL-TxConfigIndex-r16 OPTIONAL -- Need M +} + +SL-TxConfigIndex-r16 ::= INTEGER (0..maxTxConfig-1-r16) + +-- TAG-SL-CBR-PRIORITYTXCONFIGLIST-STOP +-- TAG-SL-CBR-COMMONTXCONFIGLIST-START + +SL-CBR-CommonTxConfigList-r16 ::= SEQUENCE { + sl-CBR-RangeConfigList-r16 SEQUENCE (SIZE (1..maxCBR-Config-r16)) OF SL-CBR-LevelsConfig-r16 OPTIONAL, -- Need M + sl-CBR-PSSCH-TxConfigList-r16 SEQUENCE (SIZE (1.. maxTxConfig-r16)) OF SL-CBR-PSSCH-TxConfig-r16 OPTIONAL -- Need M +} + +SL-CBR-LevelsConfig-r16 ::= SEQUENCE (SIZE (1..maxCBR-Level-r16)) OF SL-CBR-r16 + +SL-CBR-PSSCH-TxConfig-r16 ::= SEQUENCE { + sl-CR-Limit-r16 INTEGER(0..10000) OPTIONAL, -- Need M + sl-TxParameters-r16 SL-PSSCH-TxParameters-r16 OPTIONAL -- Need M +} + +SL-CBR-r16 ::= INTEGER (0..100) + +-- TAG-SL-CBR-COMMONTXCONFIGLIST-STOP +-- TAG-SL-CONFIGDEDICATEDNR-START + +SL-ConfigDedicatedNR-r16 ::= SEQUENCE { + sl-PHY-MAC-RLC-Config-r16 SL-PHY-MAC-RLC-Config-r16 OPTIONAL, -- Need M + sl-RadioBearerToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SLRB-Uu-ConfigIndex-r16 OPTIONAL, -- Need N + sl-RadioBearerToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SL-RadioBearerConfig-r16 OPTIONAL, -- Need N + sl-MeasConfigInfoToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-DestinationIndex-r16 OPTIONAL, -- Need N + sl-MeasConfigInfoToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-MeasConfigInfo-r16 OPTIONAL, -- Need M + t400-r16 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000} OPTIONAL, -- Need M + ... +} + +SL-DestinationIndex-r16 ::= INTEGER (0..maxNrofSL-Dest-1-r16) + +SL-PHY-MAC-RLC-Config-r16::= SEQUENCE { + sl-ScheduledConfig-r16 SetupRelease { SL-ScheduledConfig-r16 } OPTIONAL, -- Need M + sl-UE-SelectedConfig-r16 SetupRelease { SL-UE-SelectedConfig-r16 } OPTIONAL, -- Need M + sl-FreqInfoToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-Freq-Id-r16 OPTIONAL, -- Need N + sl-FreqInfoToAddModList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-FreqConfig-r16 OPTIONAL, -- Need N + sl-RLC-BearerToReleaseList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfigIndex-r16 OPTIONAL, -- Need N + sl-RLC-BearerToAddModList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfig-r16 OPTIONAL, -- Need N + sl-MaxNumConsecutiveDTX-r16 ENUMERATED {n1, n2, n3, n4, n6, n8, n16, n32} OPTIONAL, -- Need M + sl-CSI-Acquisition-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + sl-CSI-SchedulingRequestId-r16 SetupRelease {SchedulingRequestId} OPTIONAL, -- Need M + sl-SSB-PriorityNR-r16 INTEGER (1..8) OPTIONAL, -- Need R + networkControlledSyncTx-r16 ENUMERATED {on, off} OPTIONAL -- Need M +} + +-- TAG-SL-CONFIGDEDICATEDNR-STOP +-- TAG-SL-CONFIGUREDGRANTCONFIG-START + +SL-ConfiguredGrantConfig-r16 ::= SEQUENCE { + sl-ConfigIndexCG-r16 SL-ConfigIndexCG-r16, + sl-PeriodCG-r16 SL-PeriodCG-r16 OPTIONAL, -- Need M + sl-NrOfHARQ-Processes-r16 INTEGER (1..16) OPTIONAL, -- Need M + sl-HARQ-ProcID-offset-r16 INTEGER (0..15) OPTIONAL, -- Need M + sl-CG-MaxTransNumList-r16 SL-CG-MaxTransNumList-r16 OPTIONAL, -- Need M + rrc-ConfiguredSidelinkGrant-r16 SEQUENCE { + sl-TimeResourceCG-Type1-r16 INTEGER (0..496) OPTIONAL, -- Need M + sl-StartSubchannelCG-Type1-r16 INTEGER (0..26) OPTIONAL, -- Need M + sl-FreqResourceCG-Type1-r16 INTEGER (0..6929) OPTIONAL, -- Need M + sl-TimeOffsetCG-Type1-r16 INTEGER (0..7999) OPTIONAL, -- Need R + sl-N1PUCCH-AN-r16 PUCCH-ResourceId OPTIONAL, -- Need M + sl-PSFCH-ToPUCCH-CG-Type1-r16 INTEGER (0..15) OPTIONAL, -- Need M + sl-ResourcePoolID-r16 SL-ResourcePoolID-r16 OPTIONAL, -- Need M + sl-TimeReferenceSFN-Type1-r16 ENUMERATED {sfn512} OPTIONAL -- Need S + } OPTIONAL, -- Need M + ... +} + +SL-ConfigIndexCG-r16 ::= INTEGER (0..maxNrofCG-SL-r16-1) + +SL-CG-MaxTransNumList-r16 ::= SEQUENCE (SIZE (1..8)) OF SL-CG-MaxTransNum-r16 + +SL-CG-MaxTransNum-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-MaxTransNum-r16 INTEGER (1..32) +} + +SL-PeriodCG-r16 ::= CHOICE{ + sl-PeriodCG1-r16 ENUMERATED {ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000, spare6, + spare5, spare4, spare3, spare2, spare1}, + sl-PeriodCG2-r16 INTEGER (1..99) +} + +-- TAG-SL-CONFIGUREDGRANTCONFIG-STOP +-- TAG-SL-DESTINATIONIDENTITY-START + +SL-DestinationIdentity-r16 ::= BIT STRING (SIZE (24)) + +-- TAG-SL-DESTINATIONIDENTITY-STOP +-- TAG-SL-FREQCONFIG-START + +SL-FreqConfig-r16 ::= SEQUENCE { + sl-Freq-Id-r16 SL-Freq-Id-r16, + sl-SCS-SpecificCarrierList-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + sl-AbsoluteFrequencyPointA-r16 ARFCN-ValueNR OPTIONAL, -- Need M + sl-AbsoluteFrequencySSB-r16 ARFCN-ValueNR OPTIONAL, -- Need R + frequencyShift7p5khzSL-r16 ENUMERATED {true} OPTIONAL, -- Cond V2X-SL-Shared + valueN-r16 INTEGER (-1..1), + sl-BWP-ToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF BWP-Id OPTIONAL, -- Need N + sl-BWP-ToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF SL-BWP-Config-r16 OPTIONAL, -- Need N + sl-SyncConfigList-r16 SL-SyncConfigList-r16 OPTIONAL, -- Need M + sl-SyncPriority-r16 ENUMERATED {gnss, gnbEnb} OPTIONAL -- Need M +} + +SL-Freq-Id-r16 ::= INTEGER (1.. maxNrofFreqSL-r16) + +-- TAG-SL-FREQCONFIG-STOP +-- TAG-SL-FREQCONFIGCOMMON-START + +SL-FreqConfigCommon-r16 ::= SEQUENCE { + sl-SCS-SpecificCarrierList-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + sl-AbsoluteFrequencyPointA-r16 ARFCN-ValueNR, + sl-AbsoluteFrequencySSB-r16 ARFCN-ValueNR OPTIONAL, -- Need R + frequencyShift7p5khzSL-r16 ENUMERATED {true} OPTIONAL, -- Cond V2X-SL-Shared + valueN-r16 INTEGER (-1..1), + sl-BWP-List-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF SL-BWP-ConfigCommon-r16 OPTIONAL, -- Need R + sl-SyncPriority-r16 ENUMERATED {gnss, gnbEnb} OPTIONAL, -- Need R + sl-NbAsSync-r16 BOOLEAN OPTIONAL, -- Need R + sl-SyncConfigList-r16 SL-SyncConfigList-r16 OPTIONAL, -- Need R + ... +} +-- TAG-SL-FREQCONFIGCOMMON-STOP +-- TAG-SL-LOGICALCHANNELCONFIG-START + +SL-LogicalChannelConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-PrioritisedBitRate-r16 ENUMERATED {kBps0, kBps8, kBps16, kBps32, kBps64, kBps128, kBps256, kBps512, + kBps1024, kBps2048, kBps4096, kBps8192, kBps16384, kBps32768, kBps65536, infinity}, + sl-BucketSizeDuration-r16 ENUMERATED {ms5, ms10, ms20, ms50, ms100, ms150, ms300, ms500, ms1000, + spare7, spare6, spare5, spare4, spare3,spare2, spare1}, + sl-ConfiguredGrantType1Allowed-r16 ENUMERATED {true} OPTIONAL, -- Need R + sl-HARQ-FeedbackEnabled-r16 ENUMERATED {enabled, disabled } OPTIONAL, -- Need R + sl-AllowedCG-List-r16 SEQUENCE (SIZE (0.. maxNrofCG-SL-r16-1)) OF SL-ConfigIndexCG-r16 + OPTIONAL, -- Need R + sl-AllowedSCS-List-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SubcarrierSpacing OPTIONAL, -- Need R + sl-MaxPUSCH-Duration-r16 ENUMERATED {ms0p02, ms0p04, ms0p0625, ms0p125, ms0p25, ms0p5, spare2, spare1} + OPTIONAL, -- Need R + sl-LogicalChannelGroup-r16 INTEGER (0..maxLCG-ID) OPTIONAL, -- Need R + sl-SchedulingRequestId-r16 SchedulingRequestId OPTIONAL, -- Need R + sl-LogicalChannelSR-DelayTimerApplied-r16 BOOLEAN OPTIONAL, -- Need R + ... +} +-- TAG-SL-LOGICALCHANNELCONFIG-STOP +-- TAG-SL-MEASCONFIGCOMMON-START + +SL-MeasConfigCommon-r16 ::= SEQUENCE { + sl-MeasObjectListCommon-r16 SL-MeasObjectList-r16 OPTIONAL, -- Need R + sl-ReportConfigListCommon-r16 SL-ReportConfigList-r16 OPTIONAL, -- Need R + sl-MeasIdListCommon-r16 SL-MeasIdList-r16 OPTIONAL, -- Need R + sl-QuantityConfigCommon-r16 SL-QuantityConfig-r16 OPTIONAL, -- Need R + ... +} + +-- TAG-SL-MEASCONFIGCOMMON-STOP +-- TAG-SL-MEASCONFIGINFO-START + +SL-MeasConfigInfo-r16 ::= SEQUENCE { + sl-DestinationIndex-r16 SL-DestinationIndex-r16, + sl-MeasConfig-r16 SL-MeasConfig-r16, + ... +} + +SL-MeasConfig-r16 ::= SEQUENCE { + sl-MeasObjectToRemoveList-r16 SL-MeasObjectToRemoveList-r16 OPTIONAL, -- Need N + sl-MeasObjectToAddModList-r16 SL-MeasObjectList-r16 OPTIONAL, -- Need N + sl-ReportConfigToRemoveList-r16 SL-ReportConfigToRemoveList-r16 OPTIONAL, -- Need N + sl-ReportConfigToAddModList-r16 SL-ReportConfigList-r16 OPTIONAL, -- Need N + sl-MeasIdToRemoveList-r16 SL-MeasIdToRemoveList-r16 OPTIONAL, -- Need N + sl-MeasIdToAddModList-r16 SL-MeasIdList-r16 OPTIONAL, -- Need N + sl-QuantityConfig-r16 SL-QuantityConfig-r16 OPTIONAL, -- Need M + ... +} + +SL-MeasObjectToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ObjectId-r16)) OF SL-MeasObjectId-r16 + +SL-ReportConfigToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ReportConfigId-r16)) OF SL-ReportConfigId-r16 + +SL-MeasIdToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF SL-MeasId-r16 + +-- TAG-SL-MEASCONFIGINFO-STOP +-- TAG-SL-MEASIDLIST-START + +SL-MeasIdList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF SL-MeasIdInfo-r16 + +SL-MeasIdInfo-r16 ::= SEQUENCE { + sl-MeasId-r16 SL-MeasId-r16, + sl-MeasObjectId-r16 SL-MeasObjectId-r16, + sl-ReportConfigId-r16 SL-ReportConfigId-r16, + ... +} + +SL-MeasId-r16 ::= INTEGER (1..maxNrofSL-MeasId-r16) + +-- TAG-SL-MEASIDLIST-STOP +-- TAG-SL-MEASOBJECTLIST-START + +SL-MeasObjectList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ObjectId-r16)) OF SL-MeasObjectInfo-r16 + +SL-MeasObjectInfo-r16 ::= SEQUENCE { + sl-MeasObjectId-r16 SL-MeasObjectId-r16, + sl-MeasObject-r16 SL-MeasObject-r16, + ... +} + +SL-MeasObjectId-r16 ::= INTEGER (1..maxNrofSL-ObjectId-r16) + +SL-MeasObject-r16 ::= SEQUENCE { + frequencyInfoSL-r16 ARFCN-ValueNR, + ... +} + +-- TAG-SL-MEASOBJECTLIST-STOP +-- TAG-SL-PDCP-CONFIG-START + +SL-PDCP-Config-r16 ::= SEQUENCE { + sl-DiscardTimer-r16 ENUMERATED {ms3, ms10, ms20, ms25, ms30, ms40, ms50, ms60, ms75, ms100, ms150, ms200, + ms250, ms300, ms500, ms750, ms1500, infinity} OPTIONAL, -- Cond Setup + sl-PDCP-SN-Size-r16 ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + sl-OutOfOrderDelivery ENUMERATED { true } OPTIONAL, -- Need R + ... +} + +-- TAG-SL-PDCP-CONFIG-STOP +-- TAG-SL-PSBCH-CONFIG-START + +SL-PSBCH-Config-r16 ::= SEQUENCE { + dl-P0-PSBCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + dl-Alpha-PSBCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need M + ... +} + +-- TAG-SL-PSBCH-CONFIG-STOP +-- TAG-SL-PSSCH-TXCONFIGLIST-START + +SL-PSSCH-TxConfigList-r16 ::= SEQUENCE (SIZE (1..maxPSSCH-TxConfig-r16)) OF SL-PSSCH-TxConfig-r16 + +SL-PSSCH-TxConfig-r16 ::= SEQUENCE { + sl-TypeTxSync-r16 SL-TypeTxSync-r16 OPTIONAL, -- Need R + sl-ThresUE-Speed-r16 ENUMERATED {kmph60, kmph80, kmph100, kmph120, + kmph140, kmph160, kmph180, kmph200}, + sl-ParametersAboveThres-r16 SL-PSSCH-TxParameters-r16, + sl-ParametersBelowThres-r16 SL-PSSCH-TxParameters-r16, + ... +} + + +SL-PSSCH-TxParameters-r16 ::= SEQUENCE { + sl-MinMCS-PSSCH-r16 INTEGER (0..27), + sl-MaxMCS-PSSCH-r16 INTEGER (0..31), + sl-MinSubChannelNumPSSCH-r16 INTEGER (1..27), + sl-MaxSubchannelNumPSSCH-r16 INTEGER (1..27), + sl-MaxTxTransNumPSSCH-r16 INTEGER (1..32), + sl-MaxTxPower-r16 SL-TxPower-r16 OPTIONAL -- Cond CBR +} + +-- TAG-SL-PSSCH-TXCONFIGLIST-STOP +-- TAG-SL-QOS-FLOWIDENTITY-START + +SL-QoS-FlowIdentity-r16 ::= INTEGER (1..maxNrofSL-QFIs-r16) + +-- TAG-SL-QOS-FLOWIDENTITY-STOP +-- TAG-SL-QOS-PROFILE-START + +SL-QoS-Profile-r16 ::= SEQUENCE { + sl-PQI-r16 SL-PQI-r16 OPTIONAL, -- Need R + sl-GFBR-r16 INTEGER (0..4000000000) OPTIONAL, -- Need R + sl-MFBR-r16 INTEGER (0..4000000000) OPTIONAL, -- Need R + sl-Range-r16 INTEGER (1..1000) OPTIONAL, -- Need R + ... +} + +SL-PQI-r16 ::= CHOICE { + sl-StandardizedPQI-r16 INTEGER (0..255), + sl-Non-StandardizedPQI-r16 SEQUENCE { + sl-ResourceType-r16 ENUMERATED {gbr, non-GBR, delayCriticalGBR, spare1} OPTIONAL, -- Need R + sl-PriorityLevel-r16 INTEGER (1..8) OPTIONAL, -- Need R + sl-PacketDelayBudget-r16 INTEGER (0..1023) OPTIONAL, -- Need R + sl-PacketErrorRate-r16 INTEGER (0..9) OPTIONAL, -- Need R + sl-AveragingWindow-r16 INTEGER (0..4095) OPTIONAL, -- Need R + sl-MaxDataBurstVolume-r16 INTEGER (0..4095) OPTIONAL, -- Need R + ... + } +} + +-- TAG-SL-QOS-PROFILE-STOP +-- TAG-SL-QUANTITYCONFIG-START + +SL-QuantityConfig-r16 ::= SEQUENCE { + sl-FilterCoefficientDMRS-r16 FilterCoefficient DEFAULT fc4, + ... +} + +-- TAG-SL-QuantityConfig-STOP +-- TAG-SL-RADIOBEARERCONFIG-START + +SL-RadioBearerConfig-r16 ::= SEQUENCE { + slrb-Uu-ConfigIndex-r16 SLRB-Uu-ConfigIndex-r16, + sl-SDAP-Config-r16 SL-SDAP-Config-r16 OPTIONAL, -- Cond SLRBSetup + sl-PDCP-Config-r16 SL-PDCP-Config-r16 OPTIONAL, -- Cond SLRBSetup + sl-TransRange-r16 ENUMERATED {m20, m50, m80, m100, m120, m150, m180, m200, m220, m250, m270, m300, m350, m370, + m400, m420, m450, m480, m500, m550, m600, m700, m1000, spare9, spare8, spare7, spare6, + spare5, spare4, spare3, spare2, spare1} OPTIONAL, -- Need R + ... +} + +-- TAG-SL-RADIOBEARERCONFIG-STOP +-- TAG-SL-REPORTCONFIGLIST-START + +SL-ReportConfigList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ReportConfigId-r16)) OF SL-ReportConfigInfo-r16 + +SL-ReportConfigInfo-r16 ::= SEQUENCE { + sl-ReportConfigId-r16 SL-ReportConfigId-r16, + sl-ReportConfig-r16 SL-ReportConfig-r16, + ... +} + +SL-ReportConfigId-r16 ::= INTEGER (1..maxNrofSL-ReportConfigId-r16) + +SL-ReportConfig-r16 ::= SEQUENCE { + sl-ReportType-r16 CHOICE { + sl-Periodical-r16 SL-PeriodicalReportConfig-r16, + sl-EventTriggered-r16 SL-EventTriggerConfig-r16, + ... + }, + ... +} + +SL-PeriodicalReportConfig-r16 ::= SEQUENCE { + sl-ReportInterval-r16 ReportInterval, + sl-ReportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + sl-ReportQuantity-r16 SL-MeasReportQuantity-r16, + sl-RS-Type-r16 SL-RS-Type-r16, + ... +} + +SL-EventTriggerConfig-r16 ::= SEQUENCE { + sl-EventId-r16 CHOICE { + eventS1-r16 SEQUENCE { + s1-Threshold-r16 SL-MeasTriggerQuantity-r16, + sl-ReportOnLeave-r16 BOOLEAN, + sl-Hysteresis-r16 Hysteresis, + sl-TimeToTrigger-r16 TimeToTrigger, + ... + }, + eventS2-r16 SEQUENCE { + s2-Threshold-r16 SL-MeasTriggerQuantity-r16, + sl-ReportOnLeave-r16 BOOLEAN, + sl-Hysteresis-r16 Hysteresis, + sl-TimeToTrigger-r16 TimeToTrigger, + ... + }, + ... + }, + sl-ReportInterval-r16 ReportInterval, + sl-ReportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + sl-ReportQuantity-r16 SL-MeasReportQuantity-r16, + sl-RS-Type-r16 SL-RS-Type-r16, + ... +} + +SL-MeasReportQuantity-r16 ::= CHOICE { + sl-RSRP-r16 BOOLEAN, + ... +} + +SL-MeasTriggerQuantity-r16 ::= CHOICE { + sl-RSRP-r16 RSRP-Range, + ... +} + +SL-RS-Type-r16 ::= ENUMERATED {dmrs, spare3, spare2, spare1} + +-- TAG-SL-REPORTCONFIGLIST-STOP +-- TAG-SL-RESOURCEPOOL-START + +SL-ResourcePool-r16 ::= SEQUENCE { + sl-PSCCH-Config-r16 SetupRelease { SL-PSCCH-Config-r16 } OPTIONAL, -- Need M + sl-PSSCH-Config-r16 SetupRelease { SL-PSSCH-Config-r16 } OPTIONAL, -- Need M + sl-PSFCH-Config-r16 SetupRelease { SL-PSFCH-Config-r16 } OPTIONAL, -- Need M + sl-SyncAllowed-r16 SL-SyncAllowed-r16 OPTIONAL, -- Need M + sl-SubchannelSize-r16 ENUMERATED {n10, n12, n15, n20, n25, n50, n75, n100} OPTIONAL, -- Need M + dummy INTEGER (10..160) OPTIONAL, -- Need M + sl-StartRB-Subchannel-r16 INTEGER (0..265) OPTIONAL, -- Need M + sl-NumSubchannel-r16 INTEGER (1..27) OPTIONAL, -- Need M + sl-Additional-MCS-Table-r16 ENUMERATED {qam256, qam64LowSE, qam256-qam64LowSE } OPTIONAL, -- Need M + sl-ThreshS-RSSI-CBR-r16 INTEGER (0..45) OPTIONAL, -- Need M + sl-TimeWindowSizeCBR-r16 ENUMERATED {ms100, slot100} OPTIONAL, -- Need M + sl-TimeWindowSizeCR-r16 ENUMERATED {ms1000, slot1000} OPTIONAL, -- Need M + sl-PTRS-Config-r16 SL-PTRS-Config-r16 OPTIONAL, -- Need M + sl-UE-SelectedConfigRP-r16 SL-UE-SelectedConfigRP-r16 OPTIONAL, -- Need M + sl-RxParametersNcell-r16 SEQUENCE { + sl-TDD-Configuration-r16 TDD-UL-DL-ConfigCommon OPTIONAL, -- Need M + sl-SyncConfigIndex-r16 INTEGER (0..15) + } OPTIONAL, -- Need M + sl-ZoneConfigMCR-List-r16 SEQUENCE (SIZE (16)) OF SL-ZoneConfigMCR-r16 OPTIONAL, -- Need M + sl-FilterCoefficient-r16 FilterCoefficient OPTIONAL, -- Need M + sl-RB-Number-r16 INTEGER (10..275) OPTIONAL, -- Need M + sl-PreemptionEnable-r16 ENUMERATED {enabled, pl1, pl2, pl3, pl4, pl5, pl6, pl7, pl8} OPTIONAL, -- Need R + sl-PriorityThreshold-UL-URLLC-r16 INTEGER (1..9) OPTIONAL, -- Need M + sl-PriorityThreshold-r16 INTEGER (1..9) OPTIONAL, -- Need M + sl-X-Overhead-r16 ENUMERATED {n0,n3, n6, n9} OPTIONAL, -- Need S + sl-PowerControl-r16 SL-PowerControl-r16 OPTIONAL, -- Need M + sl-TxPercentageList-r16 SL-TxPercentageList-r16 OPTIONAL, -- Need M + sl-MinMaxMCS-List-r16 SL-MinMaxMCS-List-r16 OPTIONAL, -- Need M + ..., + [[ + sl-TimeResource-r16 BIT STRING (SIZE (10..160)) OPTIONAL -- Need M + ]] +} + +SL-ZoneConfigMCR-r16 ::= SEQUENCE { + sl-ZoneConfigMCR-Index-r16 INTEGER (0..15), + sl-TransRange-r16 ENUMERATED {m20, m50, m80, m100, m120, m150, m180, m200, m220, m250, m270, m300, m350, + m370, m400, m420, m450, m480, m500, m550, m600, m700, m1000, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1} + OPTIONAL, -- Need M + sl-ZoneConfig-r16 SL-ZoneConfig-r16 OPTIONAL, -- Need M + ... +} + +SL-SyncAllowed-r16 ::= SEQUENCE { + gnss-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R + gnbEnb-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R + ue-Sync-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +SL-PSCCH-Config-r16 ::= SEQUENCE { + sl-TimeResourcePSCCH-r16 ENUMERATED {n2, n3} OPTIONAL, -- Need M + sl-FreqResourcePSCCH-r16 ENUMERATED {n10,n12, n15, n20, n25} OPTIONAL, -- Need M + sl-DMRS-ScrambleID-r16 INTEGER (0..65535) OPTIONAL, -- Need M + sl-NumReservedBits-r16 INTEGER (2..4) OPTIONAL, -- Need M + ... +} + +SL-PSSCH-Config-r16 ::= SEQUENCE { + sl-PSSCH-DMRS-TimePatternList-r16 SEQUENCE (SIZE (1..3)) OF INTEGER (2..4) OPTIONAL, -- Need M + sl-BetaOffsets2ndSCI-r16 SEQUENCE (SIZE (4)) OF SL-BetaOffsets-r16 OPTIONAL, -- Need M + sl-Scaling-r16 ENUMERATED {f0p5, f0p65, f0p8, f1} OPTIONAL, -- Need M + ... +} + +SL-PSFCH-Config-r16 ::= SEQUENCE { + sl-PSFCH-Period-r16 ENUMERATED {sl0, sl1, sl2, sl4} OPTIONAL, -- Need M + sl-PSFCH-RB-Set-r16 BIT STRING (SIZE (10..275)) OPTIONAL, -- Need M + sl-NumMuxCS-Pair-r16 ENUMERATED {n1, n2, n3, n6} OPTIONAL, -- Need M + sl-MinTimeGapPSFCH-r16 ENUMERATED {sl2, sl3} OPTIONAL, -- Need M + sl-PSFCH-HopID-r16 INTEGER (0..1023) OPTIONAL, -- Need M + sl-PSFCH-CandidateResourceType-r16 ENUMERATED {startSubCH, allocSubCH} OPTIONAL, -- Need M + ... +} +SL-PTRS-Config-r16 ::= SEQUENCE { + sl-PTRS-FreqDensity-r16 SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need M + sl-PTRS-TimeDensity-r16 SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need M + sl-PTRS-RE-Offset-r16 ENUMERATED {offset01, offset10, offset11} OPTIONAL, -- Need M + ... +} + +SL-UE-SelectedConfigRP-r16 ::= SEQUENCE { + sl-CBR-PriorityTxConfigList-r16 SL-CBR-PriorityTxConfigList-r16 OPTIONAL, -- Need M + sl-Thres-RSRP-List-r16 SL-Thres-RSRP-List-r16 OPTIONAL, -- Need M + sl-MultiReserveResource-r16 ENUMERATED {enabled} OPTIONAL, -- Need M + sl-MaxNumPerReserve-r16 ENUMERATED {n2, n3} OPTIONAL, -- Need M + sl-SensingWindow-r16 ENUMERATED {ms100, ms1100} OPTIONAL, -- Need M + sl-SelectionWindowList-r16 SL-SelectionWindowList-r16 OPTIONAL, -- Need M + sl-ResourceReservePeriodList-r16 SEQUENCE (SIZE (1..16)) OF SL-ResourceReservePeriod-r16 OPTIONAL, -- Need M + sl-RS-ForSensing-r16 ENUMERATED {pscch, pssch}, + ... +} + +SL-ResourceReservePeriod-r16 ::= CHOICE { + sl-ResourceReservePeriod1-r16 ENUMERATED {ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}, + sl-ResourceReservePeriod2-r16 INTEGER (1..99) +} + +SL-SelectionWindowList-r16 ::= SEQUENCE (SIZE (8)) OF SL-SelectionWindowConfig-r16 + +SL-SelectionWindowConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-SelectionWindow-r16 ENUMERATED {n1, n5, n10, n20} +} + +SL-TxPercentageList-r16 ::= SEQUENCE (SIZE (8)) OF SL-TxPercentageConfig-r16 + +SL-TxPercentageConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-TxPercentage-r16 ENUMERATED {p20, p35, p50} +} + +SL-MinMaxMCS-List-r16 ::= SEQUENCE (SIZE (1..3)) OF SL-MinMaxMCS-Config-r16 + +SL-MinMaxMCS-Config-r16 ::= SEQUENCE { + sl-MCS-Table-r16 ENUMERATED {qam64, qam256, qam64LowSE}, + sl-MinMCS-PSSCH-r16 INTEGER (0..27), + sl-MaxMCS-PSSCH-r16 INTEGER (0..31) +} + +SL-BetaOffsets-r16 ::= INTEGER (0..31) + +SL-PowerControl-r16 ::= SEQUENCE { + sl-MaxTransPower-r16 INTEGER (-30..33), + sl-Alpha-PSSCH-PSCCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need M + dl-Alpha-PSSCH-PSCCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need S + sl-P0-PSSCH-PSCCH-r16 INTEGER (-16..15) OPTIONAL, -- Need S + dl-P0-PSSCH-PSCCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + dl-Alpha-PSFCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need S + dl-P0-PSFCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + ... +} + +-- TAG-SL-RESOURCEPOOL-STOP +-- TAG-SL-RLC-BEARERCONFIG-START + +SL-RLC-BearerConfig-r16 ::= SEQUENCE { + sl-RLC-BearerConfigIndex-r16 SL-RLC-BearerConfigIndex-r16, + sl-ServedRadioBearer-r16 SLRB-Uu-ConfigIndex-r16 OPTIONAL, -- Cond LCH-SetupOnly + sl-RLC-Config-r16 SL-RLC-Config-r16 OPTIONAL, -- Cond LCH-Setup + sl-MAC-LogicalChannelConfig-r16 SL-LogicalChannelConfig-r16 OPTIONAL, -- Cond LCH-Setup + ... +} + +-- TAG-SL-RLC-BEARERCONFIG-STOP +-- TAG-SL-RLC-BEARERCONFIGINDEX-START + +SL-RLC-BearerConfigIndex-r16 ::= INTEGER (1..maxSL-LCID-r16) + +-- TAG-RLC-BEARERCONFIGINDEX-STOP +-- TAG-SL-RLC-CONFIG-START + +SL-RLC-Config-r16 ::= CHOICE { + sl-AM-RLC-r16 SEQUENCE { + sl-SN-FieldLengthAM-r16 SN-FieldLengthAM OPTIONAL, -- Cond SLRBSetup + sl-T-PollRetransmit-r16 T-PollRetransmit, + sl-PollPDU-r16 PollPDU, + sl-PollByte-r16 PollByte, + sl-MaxRetxThreshold-r16 ENUMERATED { t1, t2, t3, t4, t6, t8, t16, t32 }, + ... + }, + sl-UM-RLC-r16 SEQUENCE { + sl-SN-FieldLengthUM-r16 SN-FieldLengthUM OPTIONAL, -- Cond SLRBSetup + ... + }, + ... +} + +-- TAG-SL-RLC-CONFIG-STOP +-- TAG-SL-SCHEDULEDCONFIG-START + +SL-ScheduledConfig-r16 ::= SEQUENCE { + sl-RNTI-r16 RNTI-Value, + mac-MainConfigSL-r16 MAC-MainConfigSL-r16 OPTIONAL, -- Need M + sl-CS-RNTI-r16 RNTI-Value OPTIONAL, -- Need M + sl-PSFCH-ToPUCCH-r16 SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) OPTIONAL, -- Need M + sl-ConfiguredGrantConfigList-r16 SL-ConfiguredGrantConfigList-r16 OPTIONAL, -- Need M + ..., + [[ + sl-DCI-ToSL-Trans-r16 SEQUENCE (SIZE (1..8)) OF INTEGER (1..32) OPTIONAL -- Need M + ]] +} + +MAC-MainConfigSL-r16 ::= SEQUENCE { + sl-BSR-Config-r16 BSR-Config OPTIONAL, -- Need M + ul-PrioritizationThres-r16 INTEGER (1..16) OPTIONAL, -- Need M + sl-PrioritizationThres-r16 INTEGER (1..8) OPTIONAL, -- Need M + ... +} + +SL-ConfiguredGrantConfigList-r16 ::= SEQUENCE { + sl-ConfiguredGrantConfigToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofCG-SL-r16)) OF SL-ConfigIndexCG-r16 OPTIONAL, -- Need N + sl-ConfiguredGrantConfigToAddModList-r16 SEQUENCE (SIZE (1..maxNrofCG-SL-r16)) OF SL-ConfiguredGrantConfig-r16 OPTIONAL -- Need N +} + +-- TAG-SL-SCHEDULEDCONFIG-STOP +-- TAG-SL-SDAP-CONFIG-START + +SL-SDAP-Config-r16 ::= SEQUENCE { + sl-SDAP-Header-r16 ENUMERATED {present, absent}, + sl-DefaultRB-r16 BOOLEAN, + sl-MappedQoS-Flows-r16 CHOICE { + sl-MappedQoS-FlowsList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-Profile-r16, + sl-MappedQoS-FlowsListDedicated-r16 SL-MappedQoS-FlowsListDedicated-r16 + } OPTIONAL, -- Need M + sl-CastType-r16 ENUMERATED {broadcast, groupcast, unicast, spare1} OPTIONAL, -- Need M + ... +} + +SL-MappedQoS-FlowsListDedicated-r16 ::= SEQUENCE { + sl-MappedQoS-FlowsToAddList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-FlowIdentity-r16 OPTIONAL, -- Need N + sl-MappedQoS-FlowsToReleaseList-16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-FlowIdentity-r16 OPTIONAL -- Need N +} + +-- TAG-SL-SDAP-CONFIG-STOP +-- TAG-SL-SYNCCONFIG-START + +SL-SyncConfigList-r16 ::= SEQUENCE (SIZE (1..maxSL-SyncConfig-r16)) OF SL-SyncConfig-r16 + +SL-SyncConfig-r16 ::= SEQUENCE { + sl-SyncRefMinHyst-r16 ENUMERATED {dB0, dB3, dB6, dB9, dB12} OPTIONAL, -- Need R + sl-SyncRefDiffHyst-r16 ENUMERATED {dB0, dB3, dB6, dB9, dB12, dBinf} OPTIONAL, -- Need R + sl-filterCoefficient-r16 FilterCoefficient OPTIONAL, -- Need R + sl-SSB-TimeAllocation1-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSB-TimeAllocation2-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSB-TimeAllocation3-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSID-r16 INTEGER (0..671) OPTIONAL, -- Need R + txParameters-r16 SEQUENCE { + syncTxThreshIC-r16 SL-RSRP-Range-r16 OPTIONAL, -- Need R + syncTxThreshOoC-r16 SL-RSRP-Range-r16 OPTIONAL, -- Need R + syncInfoReserved-r16 BIT STRING (SIZE (2)) OPTIONAL -- Need R + }, + gnss-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R + ... +} + +SL-RSRP-Range-r16 ::= INTEGER (0..13) + +SL-SSB-TimeAllocation-r16 ::= SEQUENCE { + sl-NumSSB-WithinPeriod-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64} OPTIONAL, -- Need R + sl-TimeOffsetSSB-r16 INTEGER (0..1279) OPTIONAL, -- Need R + sl-TimeInterval-r16 INTEGER (0..639) OPTIONAL -- Need R +} + +-- TAG-SL-SYNCCONFIG-STOP +-- TAG-SL-THRES-RSRP-LIST-START + +SL-Thres-RSRP-List-r16 ::= SEQUENCE (SIZE (64)) OF SL-Thres-RSRP-r16 + +SL-Thres-RSRP-r16 ::= INTEGER (0..66) + +-- TAG-SL-THRES-RSRP-LIST-STOP +-- TAG-SL-TXPOWER-START + +SL-TxPower-r16 ::= CHOICE{ + minusinfinity-r16 NULL, + txPower-r16 INTEGER (-30..33) +} + +-- TAG-SL-TXPOWER-STOP +-- TAG-SL-TYPETXSYNC-START + +SL-TypeTxSync-r16 ::= ENUMERATED {gnss, gnbEnb, ue} + +-- TAG-SL-TYPETXSYNC-STOP +-- TAG-SL-UE-SELECTEDCONFIG-START + +SL-UE-SelectedConfig-r16 ::= SEQUENCE { + sl-PSSCH-TxConfigList-r16 SL-PSSCH-TxConfigList-r16 OPTIONAL, -- Need R + sl-ProbResourceKeep-r16 ENUMERATED {v0, v0dot2, v0dot4, v0dot6, v0dot8} OPTIONAL, -- Need R + sl-ReselectAfter-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n7, n8, n9} OPTIONAL, -- Need R + sl-CBR-CommonTxConfigList-r16 SL-CBR-CommonTxConfigList-r16 OPTIONAL, -- Need R + ul-PrioritizationThres-r16 INTEGER (1..16) OPTIONAL, -- Need R + sl-PrioritizationThres-r16 INTEGER (1..8) OPTIONAL, -- Need R + ... +} + +-- TAG-SL-UE-SELECTEDCONFIG-STOP +-- TAG-SL-ZONECONFIG-START + +SL-ZoneConfig-r16 ::= SEQUENCE { + sl-ZoneLength-r16 ENUMERATED { m5, m10, m20, m30, m40, m50, spare2, spare1}, + ... +} + +-- TAG-SL-ZONECONFIG-STOP +-- TAG-SLRB-UU-CONFIGINDEX-START + +SLRB-Uu-ConfigIndex-r16 ::= INTEGER (1..maxNrofSLRB-r16) + +-- TAG-SLRB-UU-CONFIGINDEX-STOP +-- TAG-MULTIPLICITY-AND-TYPE-CONSTRAINT-DEFINITIONS-START + +maxAI-DCI-PayloadSize-r16 INTEGER ::= 128 --Maximum size of the DCI payload scrambled with ai-RNTI +maxAI-DCI-PayloadSize-r16-1 INTEGER ::= 127 --Maximum size of the DCI payload scrambled with ai-RNTI minus 1 +maxBandComb INTEGER ::= 65536 -- Maximum number of DL band combinations +maxBandsUTRA-FDD-r16 INTEGER ::= 64 -- Maximum number of bands listed in UTRA-FDD UE caps +maxBH-RLC-ChannelID-r16 INTEGER ::= 65536 -- Maximum value of BH RLC Channel ID +maxBT-IdReport-r16 INTEGER ::= 32 -- Maximum number of Bluetooth IDs to report +maxBT-Name-r16 INTEGER ::= 4 -- Maximum number of Bluetooth name +maxCAG-Cell-r16 INTEGER ::= 16 -- Maximum number of NR CAG cell ranges in SIB3, SIB4 +maxTwoPUCCH-Grp-ConfigList-r16 INTEGER ::= 32 -- Maximum number of supported configuration(s) of {primary PUCCH group + -- config, secondary PUCCH group config} +maxCBR-Config-r16 INTEGER ::= 8 -- Maximum number of CBR range configurations for sidelink communication + -- congestion control +maxCBR-Config-1-r16 INTEGER ::= 7 -- Maximum number of CBR range configurations for sidelink communication + -- congestion control minus 1 +maxCBR-Level-r16 INTEGER ::= 16 -- Maximum nuber of CBR levels +maxCBR-Level-1-r16 INTEGER ::= 15 -- Maximum number of CBR levels minus 1 +maxCellBlack INTEGER ::= 16 -- Maximum number of NR blacklisted cell ranges in SIB3, SIB4 +maxCellHistory-r16 INTEGER ::= 16 -- Maximum number of visited cells reported +maxCellInter INTEGER ::= 16 -- Maximum number of inter-Freq cells listed in SIB4 +maxCellIntra INTEGER ::= 16 -- Maximum number of intra-Freq cells listed in SIB3 +maxCellMeasEUTRA INTEGER ::= 32 -- Maximum number of cells in E-UTRAN +maxCellMeasIdle-r16 INTEGER ::= 8 -- Maximum number of cells per carrier for idle/inactive measurements +maxCellMeasUTRA-FDD-r16 INTEGER ::= 32 -- Maximum number of cells in FDD UTRAN +maxCellWhite INTEGER ::= 16 -- Maximum number of NR whitelisted cell ranges in SIB3, SIB4 +maxEARFCN INTEGER ::= 262143 -- Maximum value of E-UTRA carrier frequency +maxEUTRA-CellBlack INTEGER ::= 16 -- Maximum number of E-UTRA blacklisted physical cell identity ranges + -- in SIB5 +maxEUTRA-NS-Pmax INTEGER ::= 8 -- Maximum number of NS and P-Max values per band +maxLogMeasReport-r16 INTEGER ::= 520 -- Maximum number of entries for logged measurements +maxMultiBands INTEGER ::= 8 -- Maximum number of additional frequency bands that a cell belongs to +maxNARFCN INTEGER ::= 3279165 -- Maximum value of NR carrier frequency +maxNR-NS-Pmax INTEGER ::= 8 -- Maximum number of NS and P-Max values per band +maxFreqIdle-r16 INTEGER ::= 8 -- Maximum number of carrier frequencies for idle/inactive measurements +maxNrofServingCells INTEGER ::= 32 -- Max number of serving cells (SpCells + SCells) +maxNrofServingCells-1 INTEGER ::= 31 -- Max number of serving cells (SpCell + SCells) per cell group +maxNrofAggregatedCellsPerCellGroup INTEGER ::= 16 +maxNrofDUCells-r16 INTEGER ::= 512 -- Max number of cells configured on the collocated IAB-DU +maxNrofAssociatedDUCellsPerMT-r16 INTEGER ::= 65535 +maxNrofAvailabilityCombinationsPerSet-r16 INTEGER ::= 512 -- Max number of AvailabilityCombinationId used in the DCI format 2_5 +maxNrofAvailabilityCombinationsPerSet-r16-1 INTEGER ::= 511 -- Max number of AvailabilityCombinationId used in the DCI format 2_5 minus 1 +maxNrofSCells INTEGER ::= 31 -- Max number of secondary serving cells per cell group +maxNrofCellMeas INTEGER ::= 32 -- Maximum number of entries in each of the cell lists in a measurement object +maxNrofCG-SL-r16 INTEGER ::= 8 -- Max number of sidelink configured grant +maxNrofCG-SL-r16-1 INTEGER ::= 7 -- Max number of sidelink configured grant minus 1 +maxNrofSS-BlocksToAverage INTEGER ::= 16 -- Max number for the (max) number of SS blocks to average to determine cell measurement +maxNrofCondCells-r16 INTEGER ::= 8 -- Max number of conditional candidate SpCells +maxNrofCSI-RS-ResourcesToAverage INTEGER ::= 16 -- Max number for the (max) number of CSI-RS to average to determine cell measurement +maxNrofDL-Allocations INTEGER ::= 16 -- Maximum number of PDSCH time domain resource allocations +maxNrofSR-ConfigPerCellGroup INTEGER ::= 8 -- Maximum number of SR configurations per cell group +maxLCG-ID INTEGER ::= 7 -- Maximum value of LCG ID +maxLC-ID INTEGER ::= 32 -- Maximum value of Logical Channel ID +maxLC-ID-Iab-r16 INTEGER ::= 65855 -- Maximum value of BH Logical Channel ID extension +maxLTE-CRS-Patterns-r16 INTEGER ::= 3 -- Maximum number of additional LTE CRS rate matching patterns +maxNrofTAGs INTEGER ::= 4 -- Maximum number of Timing Advance Groups +maxNrofTAGs-1 INTEGER ::= 3 -- Maximum number of Timing Advance Groups minus 1 +maxNrofBWPs INTEGER ::= 4 -- Maximum number of BWPs per serving cell +maxNrofCombIDC INTEGER ::= 128 -- Maximum number of reported MR-DC combinations for IDC +maxNrofSymbols-1 INTEGER ::= 13 -- Maximum index identifying a symbol within a slot (14 symbols, indexed from 0..13) +maxNrofSlots INTEGER ::= 320 -- Maximum number of slots in a 10 ms period +maxNrofSlots-1 INTEGER ::= 319 -- Maximum number of slots in a 10 ms period minus 1 +maxNrofPhysicalResourceBlocks INTEGER ::= 275 -- Maximum number of PRBs +maxNrofPhysicalResourceBlocks-1 INTEGER ::= 274 -- Maximum number of PRBs minus 1 +maxNrofPhysicalResourceBlocksPlus1 INTEGER ::= 276 -- Maximum number of PRBs plus 1 +maxNrofControlResourceSets INTEGER ::= 12 -- Max number of CoReSets configurable on a serving cell +maxNrofControlResourceSets-1 INTEGER ::= 11 -- Max number of CoReSets configurable on a serving cell minus 1 +maxNrofControlResourceSets-1-r16 INTEGER ::= 15 -- Max number of CoReSets configurable on a serving cell extended in minus 1 +maxNrofCoresetPools-r16 INTEGER ::= 2 -- Maximum number of CORESET pools +maxCoReSetDuration INTEGER ::= 3 -- Max number of OFDM symbols in a control resource set +maxNrofSearchSpaces-1 INTEGER ::= 39 -- Max number of Search Spaces minus 1 +maxSFI-DCI-PayloadSize INTEGER ::= 128 -- Max number payload of a DCI scrambled with SFI-RNTI +maxSFI-DCI-PayloadSize-1 INTEGER ::= 127 -- Max number payload of a DCI scrambled with SFI-RNTI minus 1 +maxIAB-IP-Address-r16 INTEGER ::= 32 -- Max number of assigned IP addresses +maxINT-DCI-PayloadSize INTEGER ::= 126 -- Max number payload of a DCI scrambled with INT-RNTI +maxINT-DCI-PayloadSize-1 INTEGER ::= 125 -- Max number payload of a DCI scrambled with INT-RNTI minus 1 +maxNrofRateMatchPatterns INTEGER ::= 4 -- Max number of rate matching patterns that may be configured +maxNrofRateMatchPatterns-1 INTEGER ::= 3 -- Max number of rate matching patterns that may be configured minus 1 +maxNrofRateMatchPatternsPerGroup INTEGER ::= 8 -- Max number of rate matching patterns that may be configured in one group +maxNrofCSI-ReportConfigurations INTEGER ::= 48 -- Maximum number of report configurations +maxNrofCSI-ReportConfigurations-1 INTEGER ::= 47 -- Maximum number of report configurations minus 1 +maxNrofCSI-ResourceConfigurations INTEGER ::= 112 -- Maximum number of resource configurations +maxNrofCSI-ResourceConfigurations-1 INTEGER ::= 111 -- Maximum number of resource configurations minus 1 +maxNrofAP-CSI-RS-ResourcesPerSet INTEGER ::= 16 +maxNrOfCSI-AperiodicTriggers INTEGER ::= 128 -- Maximum number of triggers for aperiodic CSI reporting +maxNrofReportConfigPerAperiodicTrigger INTEGER ::= 16 -- Maximum number of report configurations per trigger state for aperiodic reporting +maxNrofNZP-CSI-RS-Resources INTEGER ::= 192 -- Maximum number of Non-Zero-Power (NZP) CSI-RS resources +maxNrofNZP-CSI-RS-Resources-1 INTEGER ::= 191 -- Maximum number of Non-Zero-Power (NZP) CSI-RS resources minus 1 +maxNrofNZP-CSI-RS-ResourcesPerSet INTEGER ::= 64 -- Maximum number of NZP CSI-RS resources per resource set +maxNrofNZP-CSI-RS-ResourceSets INTEGER ::= 64 -- Maximum number of NZP CSI-RS resources per cell +maxNrofNZP-CSI-RS-ResourceSets-1 INTEGER ::= 63 -- Maximum number of NZP CSI-RS resources per cell minus 1 +maxNrofNZP-CSI-RS-ResourceSetsPerConfig INTEGER ::= 16 -- Maximum number of resource sets per resource configuration +maxNrofNZP-CSI-RS-ResourcesPerConfig INTEGER ::= 128 -- Maximum number of resources per resource configuration +maxNrofZP-CSI-RS-Resources INTEGER ::= 32 -- Maximum number of Zero-Power (ZP) CSI-RS resources +maxNrofZP-CSI-RS-Resources-1 INTEGER ::= 31 -- Maximum number of Zero-Power (ZP) CSI-RS resources minus 1 +maxNrofZP-CSI-RS-ResourceSets-1 INTEGER ::= 15 +maxNrofZP-CSI-RS-ResourcesPerSet INTEGER ::= 16 +maxNrofZP-CSI-RS-ResourceSets INTEGER ::= 16 +maxNrofCSI-IM-Resources INTEGER ::= 32 -- Maximum number of CSI-IM resources. See CSI-IM-ResourceMax in 38.214. +maxNrofCSI-IM-Resources-1 INTEGER ::= 31 -- Maximum number of CSI-IM resources minus 1. See CSI-IM-ResourceMax in 38.214. +maxNrofCSI-IM-ResourcesPerSet INTEGER ::= 8 -- Maximum number of CSI-IM resources per set. See CSI-IM-ResourcePerSetMax in 38.214 +maxNrofCSI-IM-ResourceSets INTEGER ::= 64 -- Maximum number of NZP CSI-IM resources per cell +maxNrofCSI-IM-ResourceSets-1 INTEGER ::= 63 -- Maximum number of NZP CSI-IM resources per cell minus 1 +maxNrofCSI-IM-ResourceSetsPerConfig INTEGER ::= 16 -- Maximum number of CSI IM resource sets per resource configuration +maxNrofCSI-SSB-ResourcePerSet INTEGER ::= 64 -- Maximum number of SSB resources in a resource set +maxNrofCSI-SSB-ResourceSets INTEGER ::= 64 -- Maximum number of CSI SSB resource sets per cell +maxNrofCSI-SSB-ResourceSets-1 INTEGER ::= 63 -- Maximum number of CSI SSB resource sets per cell minus 1 +maxNrofCSI-SSB-ResourceSetsPerConfig INTEGER ::= 1 -- Maximum number of CSI SSB resource sets per resource configuration +maxNrofFailureDetectionResources INTEGER ::= 10 -- Maximum number of failure detection resources +maxNrofFailureDetectionResources-1 INTEGER ::= 9 -- Maximum number of failure detection resources minus 1 +maxNrofFreqSL-r16 INTEGER ::= 8 -- Maximum number of carrier frequncy for for NR sidelink communication +maxNrofSL-BWPs-r16 INTEGER ::= 4 -- Maximum number of BWP for for NR sidelink communication +maxFreqSL-EUTRA-r16 INTEGER ::= 8 -- Maximum number of EUTRA anchor carrier frequncy for NR sidelink communication +maxNrofSL-MeasId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement identity (RSRP) per destination +maxNrofSL-ObjectId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement objects (RSRP) per destination +maxNrofSL-ReportConfigId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement reporting configuration(RSRP) per destination +maxNrofSL-PoolToMeasureNR-r16 INTEGER ::= 8 -- Maximum number of resoure pool for NR sidelink measurement to measure for + -- each measurement object (for CBR) +maxFreqSL-NR-r16 INTEGER ::= 8 -- Maximum number of NR anchor carrier frequncy for NR sidelink communication +maxNrofSL-QFIs-r16 INTEGER ::= 2048 -- Maximum number of QoS flow for NR sidelink communication per UE +maxNrofSL-QFIsPerDest-r16 INTEGER ::= 64 -- Maximum number of QoS flow per destination for NR sidelink communication +maxNrofObjectId INTEGER ::= 64 -- Maximum number of measurement objects +maxNrofPageRec INTEGER ::= 32 -- Maximum number of page records +maxNrofPCI-Ranges INTEGER ::= 8 -- Maximum number of PCI ranges +maxPLMN INTEGER ::= 12 -- Maximum number of PLMNs broadcast and reported by UE at establisghment +maxNrofCSI-RS-ResourcesRRM INTEGER ::= 96 -- Maximum number of CSI-RS resources per cell for an RRM measurement object +maxNrofCSI-RS-ResourcesRRM-1 INTEGER ::= 95 -- Maximum number of CSI-RS resources per cell for an RRM measurement object minus 1 +maxNrofMeasId INTEGER ::= 64 -- Maximum number of configured measurements +maxNrofQuantityConfig INTEGER ::= 2 -- Maximum number of quantity configurations +maxNrofCSI-RS-CellsRRM INTEGER ::= 96 -- Maximum number of cells with CSI-RS resources for an RRM measurement object +maxNrofSL-Dest-r16 INTEGER ::= 32 -- Maximum number of destination for NR sidelink communication +maxNrofSL-Dest-1-r16 INTEGER ::= 31 -- Highest index of destination for NR sidelink communication +maxNrofSLRB-r16 INTEGER ::= 512 -- Maximum number of radio bearer for NR sidelink communication per UE +maxSL-LCID-r16 INTEGER ::= 512 -- Maximum number of RLC bearer for NR sidelink communication per UE +maxSL-SyncConfig-r16 INTEGER ::= 16 -- Maximum number of sidelink Sync configurations +maxNrofRXPool-r16 INTEGER ::= 16 -- Maximum number of Rx resource poolfor NR sidelink communication +maxNrofTXPool-r16 INTEGER ::= 8 -- Maximum number of Tx resourcepoolfor NR sidelink communication +maxNrofPoolID-r16 INTEGER ::= 16 -- Maximum index of resource pool for NR sidelink communication +maxNrofSRS-PathlossReferenceRS-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for SRS power control. +maxNrofSRS-PathlossReferenceRS-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for SRS power control-1. +maxNrofSRS-ResourceSets INTEGER ::= 16 -- Maximum number of SRS resource sets in a BWP. +maxNrofSRS-ResourceSets-1 INTEGER ::= 15 -- Maximum number of SRS resource sets in a BWP minus 1. +maxNrofSRS-PosResourceSets-r16 INTEGER ::= 16 -- Maximum number of SRS Positioning resource sets in a BWP. +maxNrofSRS-PosResourceSets-1-r16 INTEGER ::= 15 -- Maximum number of SRS Positioning resource sets in a BWP minus 1. +maxNrofSRS-Resources INTEGER ::= 64 -- Maximum number of SRS resources. +maxNrofSRS-Resources-1 INTEGER ::= 63 -- Maximum number of SRS resources minus 1. +maxNrofSRS-PosResources-r16 INTEGER ::= 64 -- Maximum number of SRS Positioning resources. +maxNrofSRS-PosResources-1-r16 INTEGER ::= 63 -- Maximum number of SRS Positioning resources in an SRS Positioning + -- resource set minus 1. +maxNrofSRS-ResourcesPerSet INTEGER ::= 16 -- Maximum number of SRS resources in an SRS resource set +maxNrofSRS-TriggerStates-1 INTEGER ::= 3 -- Maximum number of SRS trigger states minus 1, i.e., the largest code point. +maxNrofSRS-TriggerStates-2 INTEGER ::= 2 -- Maximum number of SRS trigger states minus 2. +maxRAT-CapabilityContainers INTEGER ::= 8 -- Maximum number of interworking RAT containers (incl NR and MRDC) +maxSimultaneousBands INTEGER ::= 32 -- Maximum number of simultaneously aggregated bands +maxULTxSwitchingBandPairs INTEGER ::= 32 -- Maximum number of band pairs supporting dynamic UL Tx switching in a band combination +maxNrofSlotFormatCombinationsPerSet INTEGER ::= 512 -- Maximum number of Slot Format Combinations in a SF-Set. +maxNrofSlotFormatCombinationsPerSet-1 INTEGER ::= 511 -- Maximum number of Slot Format Combinations in a SF-Set minus 1. +maxNrofTrafficPattern-r16 INTEGER ::= 8 -- Maximum number of Traffic Pattern for NR sidelink communication. +maxNrofPUCCH-Resources INTEGER ::= 128 +maxNrofPUCCH-Resources-1 INTEGER ::= 127 +maxNrofPUCCH-ResourceSets INTEGER ::= 4 -- Maximum number of PUCCH Resource Sets +maxNrofPUCCH-ResourceSets-1 INTEGER ::= 3 -- Maximum number of PUCCH Resource Sets minus 1. +maxNrofPUCCH-ResourcesPerSet INTEGER ::= 32 -- Maximum number of PUCCH Resources per PUCCH-ResourceSet +maxNrofPUCCH-P0-PerSet INTEGER ::= 8 -- Maximum number of P0-pucch present in a p0-pucch set +maxNrofPUCCH-PathlossReferenceRSs INTEGER ::= 4 -- Maximum number of RSs used as pathloss reference for PUCCH power control. +maxNrofPUCCH-PathlossReferenceRSs-1 INTEGER ::= 3 -- Maximum number of RSs used as pathloss reference for PUCCH power control minus 1. +maxNrofPUCCH-PathlossReferenceRSs-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for PUCCH power control extended. +maxNrofPUCCH-PathlossReferenceRSs-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for PUCCH power control + -- minus 1 extended. +maxNrofPUCCH-PathlossReferenceRSsDiff-r16 INTEGER ::= 60 -- Difference between the extended maximum and the non-extended maximum +maxNrofPUCCH-ResourceGroups-r16 INTEGER ::= 4 -- Maximum number of PUCCH resources groups. +maxNrofPUCCH-ResourcesPerGroup-r16 INTEGER ::= 128 -- Maximum number of PUCCH resources in a PUCCH group. +maxNrofMultiplePUSCHs-r16 INTEGER ::= 8 -- Maximum number of multiple PUSCHs in PUSCH TDRA list +maxNrofP0-PUSCH-AlphaSets INTEGER ::= 30 -- Maximum number of P0-pusch-alpha-sets (see 38,213, clause 7.1) +maxNrofP0-PUSCH-AlphaSets-1 INTEGER ::= 29 -- Maximum number of P0-pusch-alpha-sets minus 1 (see 38,213, clause 7.1) +maxNrofPUSCH-PathlossReferenceRSs INTEGER ::= 4 -- Maximum number of RSs used as pathloss reference for PUSCH power control. +maxNrofPUSCH-PathlossReferenceRSs-1 INTEGER ::= 3 -- Maximum number of RSs used as pathloss reference for PUSCH power control minus 1. +maxNrofPUSCH-PathlossReferenceRSs-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for PUSCH power control extended +maxNrofPUSCH-PathlossReferenceRSs-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for PUSCH power control minus 1 +maxNrofPUSCH-PathlossReferenceRSsDiff-r16 INTEGER ::= 60 -- Difference between maxNrofPUSCH-PathlossReferenceRSs-r16 and + -- maxNrofPUSCH-PathlossReferenceRSs +maxNrofNAICS-Entries INTEGER ::= 8 -- Maximum number of supported NAICS capability set +maxBands INTEGER ::= 1024 -- Maximum number of supported bands in UE capability. +maxBandsMRDC INTEGER ::= 1280 +maxBandsEUTRA INTEGER ::= 256 +maxCellReport INTEGER ::= 8 +maxDRB INTEGER ::= 29 -- Maximum number of DRBs (that can be added in DRB-ToAddModLIst). +maxFreq INTEGER ::= 8 -- Max number of frequencies. +maxFreqLayers INTEGER ::= 4 -- Max number of frequency layers. +maxFreqIDC-r16 INTEGER ::= 128 -- Max number of frequencies for IDC indication. +maxCombIDC-r16 INTEGER ::= 128 -- Max number of reported UL CA for IDC indication. +maxFreqIDC-MRDC INTEGER ::= 32 -- Maximum number of candidate NR frequencies for MR-DC IDC indication +maxNrofCandidateBeams INTEGER ::= 16 -- Max number of PRACH-ResourceDedicatedBFR that in BFR config. +maxNrofCandidateBeams-r16 INTEGER ::= 64 -- Max number of candidate beam resources in BFR config. +maxNrofCandidateBeamsExt-r16 INTEGER ::= 48 -- Max number of PRACH-ResourceDedicatedBFR in the CandidateBeamRSListExt +maxNrofPCIsPerSMTC INTEGER ::= 64 -- Maximun number of PCIs per SMTC. +maxNrofQFIs INTEGER ::= 64 +maxNrofResourceAvailabilityPerCombination-r16 INTEGER ::= 256 +maxNrOfSemiPersistentPUSCH-Triggers INTEGER ::= 64 -- Maximum number of triggers for semi persistent reporting on PUSCH +maxNrofSR-Resources INTEGER ::= 8 -- Maximum number of SR resources per BWP in a cell. +maxNrofSlotFormatsPerCombination INTEGER ::= 256 +maxNrofSpatialRelationInfos INTEGER ::= 8 +maxNrofSpatialRelationInfos-plus-1 INTEGER ::= 9 +maxNrofSpatialRelationInfos-r16 INTEGER ::= 64 +maxNrofSpatialRelationInfosDiff-r16 INTEGER ::= 56 -- Difference between maxNrofSpatialRelationInfos-r16 and maxNrofSpatialRelationInfos +maxNrofIndexesToReport INTEGER ::= 32 +maxNrofIndexesToReport2 INTEGER ::= 64 +maxNrofSSBs-r16 INTEGER ::= 64 -- Maximum number of SSB resources in a resource set. +maxNrofSSBs-1 INTEGER ::= 63 -- Maximum number of SSB resources in a resource set minus 1. +maxNrofS-NSSAI INTEGER ::= 8 -- Maximum number of S-NSSAI. +maxNrofTCI-StatesPDCCH INTEGER ::= 64 +maxNrofTCI-States INTEGER ::= 128 -- Maximum number of TCI states. +maxNrofTCI-States-1 INTEGER ::= 127 -- Maximum number of TCI states minus 1. +maxNrofUL-Allocations INTEGER ::= 16 -- Maximum number of PUSCH time domain resource allocations. +maxQFI INTEGER ::= 63 +maxRA-CSIRS-Resources INTEGER ::= 96 +maxRA-OccasionsPerCSIRS INTEGER ::= 64 -- Maximum number of RA occasions for one CSI-RS +maxRA-Occasions-1 INTEGER ::= 511 -- Maximum number of RA occasions in the system +maxRA-SSB-Resources INTEGER ::= 64 +maxSCSs INTEGER ::= 5 +maxSecondaryCellGroups INTEGER ::= 3 +maxNrofServingCellsEUTRA INTEGER ::= 32 +maxMBSFN-Allocations INTEGER ::= 8 +maxNrofMultiBands INTEGER ::= 8 +maxCellSFTD INTEGER ::= 3 -- Maximum number of cells for SFTD reporting +maxReportConfigId INTEGER ::= 64 +maxNrofCodebooks INTEGER ::= 16 -- Maximum number of codebooks suppoted by the UE +maxNrofCSI-RS-ResourcesExt-r16 INTEGER ::= 16 -- Maximum number of codebook resources supported by the UE for eType2/Codebook combo +maxNrofCSI-RS-Resources INTEGER ::= 7 -- Maximum number of codebook resources supported by the UE +maxNrofCSI-RS-ResourcesAlt-r16 INTEGER ::= 512 -- Maximum number of alternative codebook resources supported by the UE +maxNrofCSI-RS-ResourcesAlt-1-r16 INTEGER ::= 511 -- Maximum number of alternative codebook resources supported by the UE minus 1 +maxNrofSRI-PUSCH-Mappings INTEGER ::= 16 +maxNrofSRI-PUSCH-Mappings-1 INTEGER ::= 15 +maxSIB INTEGER::= 32 -- Maximum number of SIBs +maxSI-Message INTEGER::= 32 -- Maximum number of SI messages +maxPO-perPF INTEGER ::= 4 -- Maximum number of paging occasion per paging frame +maxAccessCat-1 INTEGER ::= 63 -- Maximum number of Access Categories minus 1 +maxBarringInfoSet INTEGER ::= 8 -- Maximum number of Access Categories +maxCellEUTRA INTEGER ::= 8 -- Maximum number of E-UTRA cells in SIB list +maxEUTRA-Carrier INTEGER ::= 8 -- Maximum number of E-UTRA carriers in SIB list +maxPLMNIdentities INTEGER ::= 8 -- Maximum number of PLMN identites in RAN area configurations +maxDownlinkFeatureSets INTEGER ::= 1024 -- (for NR DL) Total number of FeatureSets (size of the pool) +maxUplinkFeatureSets INTEGER ::= 1024 -- (for NR UL) Total number of FeatureSets (size of the pool) +maxEUTRA-DL-FeatureSets INTEGER ::= 256 -- (for E-UTRA) Total number of FeatureSets (size of the pool) +maxEUTRA-UL-FeatureSets INTEGER ::= 256 -- (for E-UTRA) Total number of FeatureSets (size of the pool) +maxFeatureSetsPerBand INTEGER ::= 128 -- (for NR) The number of feature sets associated with one band. +maxPerCC-FeatureSets INTEGER ::= 1024 -- (for NR) Total number of CC-specific FeatureSets (size of the pool) +maxFeatureSetCombinations INTEGER ::= 1024 -- (for MR-DC/NR)Total number of Feature set combinations (size of the pool) +maxInterRAT-RSTD-Freq INTEGER ::= 3 +maxHRNN-Len-r16 INTEGER ::= 48 -- Maximum length of HRNNs +maxNPN-r16 INTEGER ::= 12 -- Maximum number of NPNs broadcast and reported by UE at establishment +maxNrOfMinSchedulingOffsetValues-r16 INTEGER ::= 2 -- Maximum number of min. scheduling offset (K0/K2) configurations +maxK0-SchedulingOffset-r16 INTEGER ::= 16 -- Maximum number of slots configured as min. scheduling offset (K0) +maxK2-SchedulingOffset-r16 INTEGER ::= 16 -- Maximum number of slots configured as min. scheduling offset (K2) +maxDCI-2-6-Size-r16 INTEGER ::= 140 -- Maximum size of DCI format 2-6 +maxDCI-2-6-Size-1-r16 INTEGER ::= 139 -- Maximum DCI format 2-6 size minus 1 +maxNrofUL-Allocations-r16 INTEGER ::= 64 -- Maximum number of PUSCH time domain resource allocations +maxNrofP0-PUSCH-Set-r16 INTEGER ::= 2 -- Maximum number of P0 PUSCH set(s) +maxOnDemandSIB-r16 INTEGER ::= 8 -- Maximum number of SIB(s) that can be requested on-demand +maxOnDemandPosSIB-r16 INTEGER ::= 32 -- Maximum number of posSIB(s) that can be requested on-demand +maxCI-DCI-PayloadSize-r16 INTEGER ::= 126 -- Maximum number of the DCI size for CI +maxCI-DCI-PayloadSize-r16-1 INTEGER ::= 125 -- Maximum number of the DCI size for CI minus 1 +maxWLAN-Id-Report-r16 INTEGER ::= 32 -- Maximum number of WLAN IDs to report +maxWLAN-Name-r16 INTEGER ::= 4 -- Maximum number of WLAN name +maxRAReport-r16 INTEGER ::= 8 -- Maximum number of RA procedures information to be included in the RA report +maxTxConfig-r16 INTEGER ::= 64 -- Maximum number of sidelink transmission parameters configurations +maxTxConfig-1-r16 INTEGER ::= 63 -- Maximum number of sidelink transmission parameters configurations minus 1 +maxPSSCH-TxConfig-r16 INTEGER ::= 16 -- Maximum number of PSSCH TX configurations +maxNrofCLI-RSSI-Resources-r16 INTEGER ::= 64 -- Maximum number of CLI-RSSI resources for UE +maxNrofCLI-RSSI-Resources-r16-1 INTEGER ::= 63 -- Maximum number of CLI-RSSI resources for UE minus 1 +maxNrofCLI-SRS-Resources-r16 INTEGER ::= 32 -- Maximum number of SRS resources for CLI measurement for UE +maxCLI-Report-r16 INTEGER ::= 8 +maxNrofConfiguredGrantConfig-r16 INTEGER ::= 12 -- Maximum number of configured grant configurations per BWP +maxNrofConfiguredGrantConfig-r16-1 INTEGER ::= 11 -- Maximum number of configured grant configurations per BWP minus 1 +maxNrofCG-Type2DeactivationState INTEGER ::= 16 -- Maximum number of deactivation state for type 2 configured grants per BWP +maxNrofConfiguredGrantConfigMAC-r16 INTEGER ::= 32 -- Maximum number of configured grant configurations per MAC entity +maxNrofConfiguredGrantConfigMAC-r16-1 INTEGER ::= 31 -- Maximum number of configured grant configurations per MAC entity minus 1 +maxNrofSPS-Config-r16 INTEGER ::= 8 -- Maximum number of SPS configurations per BWP +maxNrofSPS-Config-r16-1 INTEGER ::= 7 -- Maximum number of SPS configurations per BWP minus 1 +maxNrofSPS-DeactivationState INTEGER ::= 16 -- Maximum number of deactivation state for SPS per BWP +maxNrofDormancyGroups INTEGER ::= 5 -- +maxNrofPUCCH-ResourceGroups-1-r16 INTEGER ::= 3 -- +maxNrofServingCellsTCI-r16 INTEGER ::= 32 -- Maximum number of serving cells in simultaneousTCI-UpdateList +maxNrofTxDC-TwoCarrier-r16 INTEGER ::= 64 -- Maximum number of UL Tx DC locations reported by the UE for 2CC uplink CA + +-- TAG-MULTIPLICITY-AND-TYPE-CONSTRAINT-DEFINITIONS-STOP + +END + +-- TAG-PC5-RRC-DEFINITIONS-START + +PC5-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + SetupRelease, + RRC-TransactionIdentifier, + SN-FieldLengthAM, + SN-FieldLengthUM, + LogicalChannelIdentity, + maxNrofSLRB-r16, + maxNrofSL-QFIs-r16, + maxNrofSL-QFIsPerDest-r16, + RSRP-Range, + SL-MeasConfig-r16, + SL-MeasId-r16, + FreqBandList, + FreqBandIndicatorNR, + maxSimultaneousBands, + maxBandComb, + maxBands, + BandParametersSidelink-r16, + RLC-ParametersSidelink-r16 + + +FROM NR-RRC-Definitions; + +-- TAG-PC5-RRC-DEFINITIONS-STOP + + +-- TAG-SBCCH-SL-BCH-MESSAGE-START + +SBCCH-SL-BCH-Message ::= SEQUENCE { + message SBCCH-SL-BCH-MessageType +} + +SBCCH-SL-BCH-MessageType::= CHOICE { + c1 CHOICE { + masterInformationBlockSidelink MasterInformationBlockSidelink, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-SBCCH-SL-BCH-MESSAGE-STOP +-- TAG-SCCH-MESSAGE-START + +SCCH-Message ::= SEQUENCE { + message SCCH-MessageType +} + +SCCH-MessageType ::= CHOICE { + c1 CHOICE { + measurementReportSidelink MeasurementReportSidelink, + rrcReconfigurationSidelink RRCReconfigurationSidelink, + rrcReconfigurationCompleteSidelink RRCReconfigurationCompleteSidelink, + rrcReconfigurationFailureSidelink RRCReconfigurationFailureSidelink, + ueCapabilityEnquirySidelink UECapabilityEnquirySidelink, + ueCapabilityInformationSidelink UECapabilityInformationSidelink, + spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-SCCH-MESSAGE-STOP +-- TAG-MASTERINFORMATIONBLOCKSIDELINK-START + +MasterInformationBlockSidelink ::= SEQUENCE { + sl-TDD-Config-r16 BIT STRING (SIZE (12)), + inCoverage-r16 BOOLEAN, + directFrameNumber-r16 BIT STRING (SIZE (10)), + slotIndex-r16 BIT STRING (SIZE (7)), + reservedBits-r16 BIT STRING (SIZE (2)) +} + +-- TAG-MASTERINFORMATIONBLOCKSIDELINK-STOP +-- TAG-MEASUREMENTREPORTSIDELINK-START + +MeasurementReportSidelink ::= SEQUENCE { + criticalExtensions CHOICE { + measurementReportSidelink-r16 MeasurementReportSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementReportSidelink-IEs-r16 ::= SEQUENCE { + sl-measResults-r16 SL-MeasResults-r16, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +SL-MeasResults-r16 ::= SEQUENCE { + sl-MeasId-r16 SL-MeasId-r16, + sl-MeasResult-r16 SL-MeasResult-r16, + ... +} + +SL-MeasResult-r16 ::= SEQUENCE { + sl-ResultDMRS-r16 SL-MeasQuantityResult-r16 OPTIONAL, + ... +} + +SL-MeasQuantityResult-r16 ::= SEQUENCE { + sl-RSRP-r16 RSRP-Range OPTIONAL, + ... +} + +-- TAG-MEASUREMENTREPORTSIDELINK-STOP +-- TAG-RRCRECONFIGURATIONSIDELINK-START + +RRCReconfigurationSidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationSidelink-r16 RRCReconfigurationSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationSidelink-IEs-r16 ::= SEQUENCE { + slrb-ConfigToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SLRB-Config-r16 OPTIONAL, -- Need N + slrb-ConfigToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SLRB-PC5-ConfigIndex-r16 OPTIONAL, -- Need N + sl-MeasConfig-r16 SetupRelease {SL-MeasConfig-r16} OPTIONAL, -- Need M + sl-CSI-RS-Config-r16 SetupRelease {SL-CSI-RS-Config-r16} OPTIONAL, -- Need M + sl-ResetConfig-r16 ENUMERATED {true} OPTIONAL, -- Need N + sl-LatencyBoundCSI-Report-r16 INTEGER (3..160) OPTIONAL, -- Need M + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SLRB-Config-r16::= SEQUENCE { + slrb-PC5-ConfigIndex-r16 SLRB-PC5-ConfigIndex-r16, + sl-SDAP-ConfigPC5-r16 SL-SDAP-ConfigPC5-r16 OPTIONAL, -- Need M + sl-PDCP-ConfigPC5-r16 SL-PDCP-ConfigPC5-r16 OPTIONAL, -- Need M + sl-RLC-ConfigPC5-r16 SL-RLC-ConfigPC5-r16 OPTIONAL, -- Need M + sl-MAC-LogicalChannelConfigPC5-r16 SL-LogicalChannelConfigPC5-r16 OPTIONAL, -- Need M + ... +} + +SLRB-PC5-ConfigIndex-r16 ::= INTEGER (1..maxNrofSLRB-r16) + +SL-SDAP-ConfigPC5-r16 ::= SEQUENCE { + sl-MappedQoS-FlowsToAddList-r16 SEQUENCE (SIZE (1.. maxNrofSL-QFIsPerDest-r16)) OF SL-PQFI-r16 OPTIONAL, -- Need N + sl-MappedQoS-FlowsToReleaseList-r16 SEQUENCE (SIZE (1.. maxNrofSL-QFIsPerDest-r16)) OF SL-PQFI-r16 OPTIONAL, -- Need N + sl-SDAP-Header-r16 ENUMERATED {present, absent}, + ... +} + +SL-PDCP-ConfigPC5-r16 ::= SEQUENCE { + sl-PDCP-SN-Size-r16 ENUMERATED {len12bits, len18bits} OPTIONAL, -- Need M + sl-OutOfOrderDelivery-r16 ENUMERATED { true } OPTIONAL, -- Need R + ... +} + +SL-RLC-ConfigPC5-r16 ::= CHOICE { + sl-AM-RLC-r16 SEQUENCE { + sl-SN-FieldLengthAM-r16 SN-FieldLengthAM OPTIONAL, -- Need M + ... + }, + sl-UM-Bi-Directional-RLC-r16 SEQUENCE { + sl-SN-FieldLengthUM-r16 SN-FieldLengthUM OPTIONAL, -- Need M + ... + }, + sl-UM-Uni-Directional-RLC-r16 SEQUENCE { + sl-SN-FieldLengthUM-r16 SN-FieldLengthUM OPTIONAL, -- Need M + ... + } +} + +SL-LogicalChannelConfigPC5-r16 ::= SEQUENCE { + sl-LogicalChannelIdentity-r16 LogicalChannelIdentity, + ... +} + +SL-PQFI-r16 ::= INTEGER (1..64) + +SL-CSI-RS-Config-r16 ::= SEQUENCE { + sl-CSI-RS-FreqAllocation-r16 CHOICE { + sl-OneAntennaPort-r16 BIT STRING (SIZE (12)), + sl-TwoAntennaPort-r16 BIT STRING (SIZE (6)) + } OPTIONAL, -- Need M + sl-CSI-RS-FirstSymbol-r16 INTEGER (3..12) OPTIONAL, -- Need M + ... +} + +-- TAG-RRCRECONFIGURATIONSIDELINK-STOP +-- TAG-RRCRECONFIGURATIONCOMPLETESIDELINK-START + +RRCReconfigurationCompleteSidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationCompleteSidelink-r16 RRCReconfigurationCompleteSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationCompleteSidelink-IEs-r16 ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRECONFIGURATIONCOMPLETESIDELINK-STOP +-- TAG-RRCRECONFIGURATIONFAILURESIDELINK-START + +RRCReconfigurationFailureSidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationFailureSidelink-r16 RRCReconfigurationFailureSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationFailureSidelink-IEs-r16 ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRECONFIGURATIONFAILURESIDELINK-STOP +-- TAG-UECAPABILITYENQUIRYSIDELINK-START + +UECapabilityEnquirySidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityEnquirySidelink-r16 UECapabilityEnquirySidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityEnquirySidelink-IEs-r16 ::= SEQUENCE { + frequencyBandListFilterSidelink-r16 FreqBandList OPTIONAL, -- Need N + ue-CapabilityInformationSidelink-r16 OCTET STRING OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-UECAPABILITYENQUIRYSIDELINK-STOP +-- TAG-UECAPABILITYINFORMATIONSIDELINK-START + +UECapabilityInformationSidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityInformationSidelink-r16 UECapabilityInformationSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityInformationSidelink-IEs-r16 ::= SEQUENCE { + accessStratumReleaseSidelink-r16 AccessStratumReleaseSidelink-r16, + pdcp-ParametersSidelink-r16 PDCP-ParametersSidelink-r16 OPTIONAL, + rlc-ParametersSidelink-r16 RLC-ParametersSidelink-r16 OPTIONAL, + supportedBandCombinationListSidelinkNR-r16 BandCombinationListSidelinkNR-r16 OPTIONAL, + supportedBandListSidelink-r16 SEQUENCE (SIZE (1..maxBands)) OF BandSidelinkPC5-r16 OPTIONAL, + appliedFreqBandListFilter-r16 FreqBandList OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +AccessStratumReleaseSidelink-r16 ::= ENUMERATED { rel16, spare7, spare6, spare5, spare4, spare3, spare2, spare1, ... } + +PDCP-ParametersSidelink-r16 ::= SEQUENCE { + outOfOrderDeliverySidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +BandCombinationListSidelinkNR-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationParametersSidelinkNR-r16 + +BandCombinationParametersSidelinkNR-r16 ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParametersSidelink-r16 + +BandSidelinkPC5-r16 ::= SEQUENCE { + freqBandSidelink-r16 FreqBandIndicatorNR, + --15-1 + sl-Reception-r16 SEQUENCE { + harq-RxProcessSidelink-r16 ENUMERATED {n16, n24, n32, n64}, + pscch-RxSidelink-r16 ENUMERATED {value1, value2}, + scs-CP-PatternRxSidelink-r16 CHOICE { + fr1-r16 SEQUENCE { + scs-15kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + }, + fr2-r16 SEQUENCE { + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-120kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + } + } OPTIONAL, + extendedCP-RxSidelink-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-10 + sl-Tx-256QAM-r16 ENUMERATED {supported} OPTIONAL, + --15-12 + lowSE-64QAM-MCS-TableSidelink-r16 ENUMERATED {supported} OPTIONAL, + ..., + [[ + --15-14 + csi-ReportSidelink-r16 SEQUENCE { + csi-RS-PortsSidelink-r16 ENUMERATED {p1, p2} + } OPTIONAL, + --15-19 + rankTwoReception-r16 ENUMERATED {supported} OPTIONAL, + --15-23 + sl-openLoopPC-RSRP-ReportSidelink-r16 ENUMERATED {supported} OPTIONAL, + --13-1 + sl-Rx-256QAM-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-UECAPABILITYINFORMATIONSIDELINK-STOP + +END + +-- NR-UE-VARIABLES-START +NR-UE-Variables DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + ARFCN-ValueNR, + CellIdentity, + EUTRA-PhysCellId, + MeasId, + MeasIdToAddModList, + MeasIdleCarrierEUTRA-r16, + MeasIdleCarrierNR-r16, + MeasResultIdleEUTRA-r16, + MeasResultIdleNR-r16, + MeasObjectToAddModList, + PhysCellId, + RNTI-Value, + ReportConfigToAddModList, + RSRP-Range, + SL-MeasId-r16, + SL-MeasIdList-r16, + SL-MeasObjectList-r16, + SL-ReportConfigList-r16, + SL-QuantityConfig-r16, + Tx-PoolMeasList-r16, + QuantityConfig, + maxNrofCellMeas, + maxNrofMeasId, + maxFreqIdle-r16, + PhysCellIdUTRA-FDD-r16, + ValidityAreaList-r16, + CondReconfigToAddModList-r16, + ConnEstFailReport-r16, + LoggingDuration-r16, + LoggingInterval-r16, + LogMeasInfoList-r16, + LogMeasInfo-r16, + RA-Report-r16, + RLF-Report-r16, + TraceReference-r16, + WLAN-Identifiers-r16, + WLAN-NameList-r16, + BT-NameList-r16, + PLMN-Identity, + maxPLMN, + RA-ReportList-r16, + VisitedCellInfoList-r16, + AbsoluteTimeInfo-r16, + LoggedEventTriggerConfig-r16, + LoggedPeriodicalReportConfig-r16, + Sensor-NameList-r16, + PLMN-IdentityList2-r16, + AreaConfiguration-r16, + maxNrofSL-MeasId-r16, + maxNrofFreqSL-r16, + maxNrofCLI-RSSI-Resources-r16, + maxNrofCLI-SRS-Resources-r16, + RSSI-ResourceId-r16, + SRS-ResourceId +FROM NR-RRC-Definitions; + +-- NR-UE-VARIABLES-STOP +-- TAG-VARCONDITIONALRECONFIG-START + +VarConditionalReconfig ::= SEQUENCE { + condReconfigList CondReconfigToAddModList-r16 OPTIONAL +} + + +-- TAG-VARCONDITIONALRECONFIG-STOP +-- TAG-VARCONNESTFAILREPORT-START + +VarConnEstFailReport-r16 ::= SEQUENCE { + connEstFailReport-r16 ConnEstFailReport-r16, + plmn-Identity-r16 PLMN-Identity +} + +-- TAG-VARCONNESTFAILREPORT-STOP +-- TAG-VARLOGMEASCONFIG-START + +VarLogMeasConfig-r16-IEs ::= SEQUENCE { + areaConfiguration-r16 AreaConfiguration-r16 OPTIONAL, + bt-NameList-r16 BT-NameList-r16 OPTIONAL, + wlan-NameList-r16 WLAN-NameList-r16 OPTIONAL, + sensor-NameList-r16 Sensor-NameList-r16 OPTIONAL, + loggingDuration-r16 LoggingDuration-r16, + reportType CHOICE { + periodical LoggedPeriodicalReportConfig-r16, + eventTriggered LoggedEventTriggerConfig-r16 + } +} +-- TAG-VARLOGMEASCONFIG-STOP +-- TAG-VARLOGMEASREPORT-START + +VarLogMeasReport-r16 ::= SEQUENCE { + absoluteTimeInfo-r16 AbsoluteTimeInfo-r16, + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + logMeasInfoList-r16 LogMeasInfoList-r16, + plmn-IdentityList-r16 PLMN-IdentityList2-r16 +} + +-- TAG-VARLOGMEASREPORT-STOP +-- TAG-VARMEASCONFIG-START + +VarMeasConfig ::= SEQUENCE { + -- Measurement identities + measIdList MeasIdToAddModList OPTIONAL, + -- Measurement objects + measObjectList MeasObjectToAddModList OPTIONAL, + -- Reporting configurations + reportConfigList ReportConfigToAddModList OPTIONAL, + -- Other parameters + quantityConfig QuantityConfig OPTIONAL, + s-MeasureConfig CHOICE { + ssb-RSRP RSRP-Range, + csi-RSRP RSRP-Range + } OPTIONAL + +} + +-- TAG-VARMEASCONFIG-STOP +-- TAG-VARMEASCONFIGSL-START + +VarMeasConfigSL-r16 ::= SEQUENCE { + -- NR sidelink measurement identities + sl-MeasIdList-r16 SL-MeasIdList-r16 OPTIONAL, + -- NR sidelink measurement objects + sl-MeasObjectList-r16 SL-MeasObjectList-r16 OPTIONAL, + -- NR sidelink reporting configurations + sl-reportConfigList-r16 SL-ReportConfigList-r16 OPTIONAL, + -- Other parameters + sl-QuantityConfig-r16 SL-QuantityConfig-r16 OPTIONAL +} + +-- TAG-VARMEASCONFIGSL-STOP +-- TAG-VARMEASIDLECONFIG-START + +VarMeasIdleConfig-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, + measIdleDuration-r16 ENUMERATED {sec10, sec30, sec60, sec120, sec180, sec240, sec300, spare}, + validityAreaList-r16 ValidityAreaList-r16 OPTIONAL +} + +-- TAG-VARMEASIDLECONFIG-STOP +-- TAG-VARMEASIDLEREPORT-START + +VarMeasIdleReport-r16 ::= SEQUENCE { + measReportIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + measReportIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL +} + +-- TAG-VARMEASIDLEREPORT-STOP +-- TAG-VARMEASREPORTLIST-START + +VarMeasReportList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF VarMeasReport + +VarMeasReport ::= SEQUENCE { + -- List of measurement that have been triggered + measId MeasId, + cellsTriggeredList CellsTriggeredList OPTIONAL, + numberOfReportsSent INTEGER, + cli-TriggeredList-r16 CLI-TriggeredList-r16 OPTIONAL, + tx-PoolMeasToAddModListNR-r16 Tx-PoolMeasList-r16 OPTIONAL +} + +CellsTriggeredList ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF CHOICE { + physCellId PhysCellId, + physCellIdEUTRA EUTRA-PhysCellId, + physCellIdUTRA-FDD-r16 PhysCellIdUTRA-FDD-r16 + } + +CLI-TriggeredList-r16 ::= CHOICE { + srs-RSRP-TriggeredList-r16 SRS-RSRP-TriggeredList-r16, + cli-RSSI-TriggeredList-r16 CLI-RSSI-TriggeredList-r16 + } + +SRS-RSRP-TriggeredList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-SRS-Resources-r16)) OF SRS-ResourceId + +CLI-RSSI-TriggeredList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-RSSI-Resources-r16)) OF RSSI-ResourceId-r16 + +-- TAG-VARMEASREPORTLIST-STOP +-- TAG-VARMEASREPORTLISTSL-START + +VarMeasReportListSL-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF VarMeasReportSL-r16 + +VarMeasReportSL-r16 ::= SEQUENCE { + -- List of NR sidelink measurement that have been triggered + sl-MeasId-r16 SL-MeasId-r16, + sl-FrequencyTriggeredList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF ARFCN-ValueNR OPTIONAL, + sl-NumberOfReportsSent-r16 INTEGER +} + +-- TAG-VARMEASREPORTLISTSL-STOP +-- TAG-VARMOBILITYHISTORYREPORT-START + +VarMobilityHistoryReport-r16 ::= VisitedCellInfoList-r16 + +-- TAG-VARMOBILITYHISTORYREPORT-STOP +-- TAG-VARPENDINGRNA-UPDATE-START + +VarPendingRNA-Update ::= SEQUENCE { + pendingRNA-Update BOOLEAN OPTIONAL +} + +-- TAG-VARPENDINGRNA-UPDATE-STOP +-- TAG-VARRA-REPORT-START + +VarRA-Report-r16 ::= SEQUENCE { + ra-ReportList-r16 RA-ReportList-r16, + plmn-IdentityList-r16 PLMN-IdentityList-r16 +} + +PLMN-IdentityList-r16 ::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity + +-- TAG-VARRA-REPORT-STOP +-- TAG-VARRESUMEMAC-INPUT-START + +VarResumeMAC-Input ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellIdentity CellIdentity, + source-c-RNTI RNTI-Value + +} + +-- TAG-VARRESUMEMAC-INPUT-STOP +-- TAG-VARRLF-REPORT-START + +VarRLF-Report-r16 ::= SEQUENCE { + rlf-Report-r16 RLF-Report-r16, + plmn-IdentityList-r16 PLMN-IdentityList2-r16 +} + +-- TAG-VARRLF-REPORT-STOP +-- TAG-VARSHORTMAC-INPUT-START + +VarShortMAC-Input ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellIdentity CellIdentity, + source-c-RNTI RNTI-Value +} + +-- TAG-VARSHORTMAC-INPUT-STOP + +END + +-- TAG-NR-SIDELINK-PRECONF-DEFINITIONS-START + +NR-Sidelink-Preconf DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + SL-CBR-CommonTxConfigList-r16, + SL-FreqConfigCommon-r16, + SL-RadioBearerConfig-r16, + SL-RLC-BearerConfig-r16, + SL-EUTRA-AnchorCarrierFreqList-r16, + SL-NR-AnchorCarrierFreqList-r16, + SL-MeasConfigCommon-r16, + SL-UE-SelectedConfig-r16, + TDD-UL-DL-ConfigCommon, + maxNrofFreqSL-r16, + maxNrofSLRB-r16, + maxSL-LCID-r16 +FROM NR-RRC-Definitions; + +-- TAG-NR-SIDELINK-PRECONF-DEFINITIONS-STOP + +-- TAG-SL-PRECONFIGURATIONNR-START + +SL-PreconfigurationNR-r16 ::= SEQUENCE { + sidelinkPreconfigNR-r16 SidelinkPreconfigNR-r16, + ... +} + +SidelinkPreconfigNR-r16 ::= SEQUENCE { + sl-PreconfigFreqInfoList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-FreqConfigCommon-r16 OPTIONAL, + sl-PreconfigNR-AnchorCarrierFreqList-r16 SL-NR-AnchorCarrierFreqList-r16 OPTIONAL, + sl-PreconfigEUTRA-AnchorCarrierFreqList-r16 SL-EUTRA-AnchorCarrierFreqList-r16 OPTIONAL, + sl-RadioBearerPreConfigList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SL-RadioBearerConfig-r16 OPTIONAL, + sl-RLC-BearerPreConfigList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfig-r16 OPTIONAL, + sl-MeasPreConfig-r16 SL-MeasConfigCommon-r16 OPTIONAL, + sl-OffsetDFN-r16 INTEGER (1..1000) OPTIONAL, + t400-r16 ENUMERATED{ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000} OPTIONAL, + sl-MaxNumConsecutiveDTX-r16 ENUMERATED {n1, n2, n3, n4, n6, n8, n16, n32} OPTIONAL, + sl-SSB-PriorityNR-r16 INTEGER (1..8) OPTIONAL, + sl-PreconfigGeneral-r16 SL-PreconfigGeneral-r16 OPTIONAL, + sl-UE-SelectedPreConfig-r16 SL-UE-SelectedConfig-r16 OPTIONAL, + sl-CSI-Acquisition-r16 ENUMERATED {enabled} OPTIONAL, + sl-RoHC-Profiles-r16 SL-RoHC-Profiles-r16 OPTIONAL, + sl-MaxCID-r16 INTEGER (1..16383) DEFAULT 15, + ... +} + +SL-PreconfigGeneral-r16 ::= SEQUENCE { + sl-TDD-Configuration-r16 TDD-UL-DL-ConfigCommon OPTIONAL, + reservedBits-r16 BIT STRING (SIZE (2)) OPTIONAL, + ... +} + +SL-RoHC-Profiles-r16 ::= SEQUENCE { + profile0x0001-r16 BOOLEAN, + profile0x0002-r16 BOOLEAN, + profile0x0003-r16 BOOLEAN, + profile0x0004-r16 BOOLEAN, + profile0x0006-r16 BOOLEAN, + profile0x0101-r16 BOOLEAN, + profile0x0102-r16 BOOLEAN, + profile0x0103-r16 BOOLEAN, + profile0x0104-r16 BOOLEAN +} + +-- TAG-SL-PRECONFIGURATIONNR-STOP + +END + +-- TAG-NR-INTER-NODE-DEFINITIONS-START +NR-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + ARFCN-ValueNR, + ARFCN-ValueEUTRA, + CellIdentity, + CGI-InfoEUTRA, + CGI-InfoNR, + CSI-RS-Index, + CSI-RS-CellMobility, + DRX-Config, + EUTRA-PhysCellId, + FeatureSetDownlinkPerCC-Id, + FeatureSetUplinkPerCC-Id, + FreqBandIndicatorNR, + GapConfig, + maxBandComb, + maxBands, + maxCellSFTD, + maxFeatureSetsPerBand, + maxFreqIDC-MRDC, + maxNrofCombIDC, + maxNrofPhysicalResourceBlocks, + maxNrofSCells, + maxNrofServingCells, + maxNrofServingCells-1, + maxNrofServingCellsEUTRA, + maxNrofIndexesToReport, + maxSimultaneousBands, + MeasQuantityResults, + MeasResultCellListSFTD-EUTRA, + MeasResultCellListSFTD-NR, + MeasResultList2NR, + MeasResultSCG-Failure, + MeasResultServFreqListEUTRA-SCG, + NeedForGapsInfoNR-r16, + OverheatingAssistance, + P-Max, + PhysCellId, + RadioBearerConfig, + RAN-NotificationAreaInfo, + RRCReconfiguration, + ServCellIndex, + SetupRelease, + SSB-Index, + SSB-MTC, + SSB-ToMeasure, + SS-RSSI-Measurement, + ShortMAC-I, + SubcarrierSpacing, + UEAssistanceInformation, + UE-CapabilityRAT-ContainerList, + maxNrofCLI-RSSI-Resources-r16, + maxNrofCLI-SRS-Resources-r16, + RSSI-ResourceId-r16, + SidelinkUEInformationNR-r16, + SRS-ResourceId +FROM NR-RRC-Definitions; + +-- TAG-NR-INTER-NODE-DEFINITIONS-STOP +-- TAG-HANDOVER-COMMAND-START + +HandoverCommand ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverCommand HandoverCommand-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverCommand-IEs ::= SEQUENCE { + handoverCommandMessage OCTET STRING (CONTAINING RRCReconfiguration), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-HANDOVER-COMMAND-STOP +-- TAG-HANDOVER-PREPARATION-INFORMATION-START + +HandoverPreparationInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverPreparationInformation HandoverPreparationInformation-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverPreparationInformation-IEs ::= SEQUENCE { + ue-CapabilityRAT-List UE-CapabilityRAT-ContainerList, + sourceConfig AS-Config OPTIONAL, -- Cond HO + rrm-Config RRM-Config OPTIONAL, + as-Context AS-Context OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +AS-Config ::= SEQUENCE { + rrcReconfiguration OCTET STRING (CONTAINING RRCReconfiguration), + ..., + [[ + sourceRB-SN-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + sourceSCG-NR-Config OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + sourceSCG-EUTRA-Config OCTET STRING OPTIONAL + ]], + [[ + sourceSCG-Configured ENUMERATED {true} OPTIONAL + ]] + +} + +AS-Context ::= SEQUENCE { + reestablishmentInfo ReestablishmentInfo OPTIONAL, + configRestrictInfo ConfigRestrictInfoSCG OPTIONAL, + ..., + [[ ran-NotificationAreaInfo RAN-NotificationAreaInfo OPTIONAL + ]], + [[ ueAssistanceInformation OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL -- Cond HO2 + ]], + [[ + selectedBandCombinationSN BandCombinationInfoSN OPTIONAL + ]], + [[ + configRestrictInfoDAPS-r16 ConfigRestrictInfoDAPS-r16 OPTIONAL, + sidelinkUEInformationNR-r16 OCTET STRING OPTIONAL, + sidelinkUEInformationEUTRA-r16 OCTET STRING OPTIONAL, + ueAssistanceInformationEUTRA-r16 OCTET STRING OPTIONAL, + ueAssistanceInformationSCG-r16 OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL, -- Cond HO2 + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL + ]], + [[ + configRestrictInfoDAPS-v1640 ConfigRestrictInfoDAPS-v1640 OPTIONAL + ]] +} + +ConfigRestrictInfoDAPS-r16 ::= SEQUENCE { + powerCoordination-r16 SEQUENCE { + p-DAPS-Source-r16 P-Max, + p-DAPS-Target-r16 P-Max, + uplinkPowerSharingDAPS-Mode-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic } + } OPTIONAL +} + +ConfigRestrictInfoDAPS-v1640 ::= SEQUENCE { + sourceFeatureSetPerDownlinkCC-r16 FeatureSetDownlinkPerCC-Id, + sourceFeatureSetPerUplinkCC-r16 FeatureSetUplinkPerCC-Id +} + +ReestablishmentInfo ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellShortMAC-I ShortMAC-I, + additionalReestabInfoList ReestabNCellInfoList OPTIONAL +} + +ReestabNCellInfoList ::= SEQUENCE ( SIZE (1..maxCellPrep) ) OF ReestabNCellInfo + +ReestabNCellInfo::= SEQUENCE{ + cellIdentity CellIdentity, + key-gNodeB-Star BIT STRING (SIZE (256)), + shortMAC-I ShortMAC-I +} + +RRM-Config ::= SEQUENCE { + ue-InactiveTime ENUMERATED { + s1, s2, s3, s5, s7, s10, s15, s20, + s25, s30, s40, s50, min1, min1s20, min1s40, + min2, min2s30, min3, min3s30, min4, min5, min6, + min7, min8, min9, min10, min12, min14, min17, min20, + min24, min28, min33, min38, min44, min50, hr1, + hr1min30, hr2, hr2min30, hr3, hr3min30, hr4, hr5, hr6, + hr8, hr10, hr13, hr16, hr20, day1, day1hr12, day2, + day2hr12, day3, day4, day5, day7, day10, day14, day19, + day24, day30, dayMoreThan30} OPTIONAL, + candidateCellInfoList MeasResultList2NR OPTIONAL, + ..., + [[ + candidateCellInfoListSN-EUTRA MeasResultServFreqListEUTRA-SCG OPTIONAL + ]] +} + +-- TAG-HANDOVER-PREPARATION-INFORMATION-STOP +-- TAG-CG-CONFIG-START + +CG-Config ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + cg-Config CG-Config-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +CG-Config-IEs ::= SEQUENCE { + scg-CellGroupConfig OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + scg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + configRestrictModReq ConfigRestrictModReqSCG OPTIONAL, + drx-InfoSCG DRX-Info OPTIONAL, + candidateCellInfoListSN OCTET STRING (CONTAINING MeasResultList2NR) OPTIONAL, + measConfigSN MeasConfigSN OPTIONAL, + selectedBandCombination BandCombinationInfoSN OPTIONAL, + fr-InfoListSCG FR-InfoList OPTIONAL, + candidateServingFreqListNR CandidateServingFreqListNR OPTIONAL, + nonCriticalExtension CG-Config-v1540-IEs OPTIONAL +} + +CG-Config-v1540-IEs ::= SEQUENCE { + pSCellFrequency ARFCN-ValueNR OPTIONAL, + reportCGI-RequestNR SEQUENCE { + requestedCellInfo SEQUENCE { + ssbFrequency ARFCN-ValueNR, + cellForWhichToReportCGI PhysCellId + } OPTIONAL + } OPTIONAL, + ph-InfoSCG PH-TypeListSCG OPTIONAL, + nonCriticalExtension CG-Config-v1560-IEs OPTIONAL +} + +CG-Config-v1560-IEs ::= SEQUENCE { + pSCellFrequencyEUTRA ARFCN-ValueEUTRA OPTIONAL, + scg-CellGroupConfigEUTRA OCTET STRING OPTIONAL, + candidateCellInfoListSN-EUTRA OCTET STRING OPTIONAL, + candidateServingFreqListEUTRA CandidateServingFreqListEUTRA OPTIONAL, + needForGaps ENUMERATED {true} OPTIONAL, + drx-ConfigSCG DRX-Config OPTIONAL, + reportCGI-RequestEUTRA SEQUENCE { + requestedCellInfoEUTRA SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cellForWhichToReportCGI-EUTRA EUTRA-PhysCellId + } OPTIONAL + } OPTIONAL, + nonCriticalExtension CG-Config-v1590-IEs OPTIONAL +} + +CG-Config-v1590-IEs ::= SEQUENCE { + scellFrequenciesSN-NR SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueNR OPTIONAL, + scellFrequenciesSN-EUTRA SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueEUTRA OPTIONAL, + nonCriticalExtension CG-Config-v1610-IEs OPTIONAL +} + +CG-Config-v1610-IEs ::= SEQUENCE { + drx-InfoSCG2 DRX-Info2 OPTIONAL, + nonCriticalExtension CG-Config-v1620-IEs OPTIONAL +} + +CG-Config-v1620-IEs ::= SEQUENCE { + ueAssistanceInformationSCG-r16 OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL, + nonCriticalExtension CG-Config-v1630-IEs OPTIONAL +} + +CG-Config-v1630-IEs ::= SEQUENCE { + selectedToffset-r16 T-Offset-r16 OPTIONAL, + nonCriticalExtension CG-Config-v1640-IEs OPTIONAL +} + +CG-Config-v1640-IEs ::= SEQUENCE { + servCellInfoListSCG-NR-r16 ServCellInfoListSCG-NR-r16 OPTIONAL, + servCellInfoListSCG-EUTRA-r16 ServCellInfoListSCG-EUTRA-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +ServCellInfoListSCG-NR-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCells)) OF ServCellInfoXCG-NR-r16 + +ServCellInfoXCG-NR-r16 ::= SEQUENCE { + dl-FreqInfo-NR-r16 FrequencyConfig-NR-r16 OPTIONAL, + ul-FreqInfo-NR-r16 FrequencyConfig-NR-r16 OPTIONAL, -- Cond FDD + ... +} + +FrequencyConfig-NR-r16 ::= SEQUENCE { + freqBandIndicatorNR-r16 FreqBandIndicatorNR, + carrierCenterFreq-NR-r16 ARFCN-ValueNR, + carrierBandwidth-NR-r16 INTEGER (1..maxNrofPhysicalResourceBlocks), + subcarrierSpacing-NR-r16 SubcarrierSpacing +} + +ServCellInfoListSCG-EUTRA-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCellsEUTRA)) OF ServCellInfoXCG-EUTRA-r16 + +ServCellInfoXCG-EUTRA-r16 ::= SEQUENCE { + dl-CarrierFreq-EUTRA-r16 ARFCN-ValueEUTRA OPTIONAL, + ul-CarrierFreq-EUTRA-r16 ARFCN-ValueEUTRA OPTIONAL, -- Cond FDD + transmissionBandwidth-EUTRA-r16 TransmissionBandwidth-EUTRA-r16 OPTIONAL, + ... +} + +TransmissionBandwidth-EUTRA-r16 ::= ENUMERATED {rb6, rb15, rb25, rb50, rb75, rb100} + +PH-TypeListSCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF PH-InfoSCG + +PH-InfoSCG ::= SEQUENCE { + servCellIndex ServCellIndex, + ph-Uplink PH-UplinkCarrierSCG, + ph-SupplementaryUplink PH-UplinkCarrierSCG OPTIONAL, + ... +} + +PH-UplinkCarrierSCG ::= SEQUENCE{ + ph-Type1or3 ENUMERATED {type1, type3}, + ... +} + +MeasConfigSN ::= SEQUENCE { + measuredFrequenciesSN SEQUENCE (SIZE (1..maxMeasFreqsSN)) OF NR-FreqInfo OPTIONAL, + ... +} + +NR-FreqInfo ::= SEQUENCE { + measuredFrequency ARFCN-ValueNR OPTIONAL, + ... +} + +ConfigRestrictModReqSCG ::= SEQUENCE { + requestedBC-MRDC BandCombinationInfoSN OPTIONAL, + requestedP-MaxFR1 P-Max OPTIONAL, + ..., + [[ + requestedPDCCH-BlindDetectionSCG INTEGER (1..15) OPTIONAL, + requestedP-MaxEUTRA P-Max OPTIONAL + ]], + [[ + requestedP-MaxFR2-r16 P-Max OPTIONAL, + requestedMaxInterFreqMeasIdSCG-r16 INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + requestedMaxIntraFreqMeasIdSCG-r16 INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + requestedToffset-r16 T-Offset-r16 OPTIONAL + ]] +} + +BandCombinationIndex ::= INTEGER (1..maxBandComb) + +BandCombinationInfoSN ::= SEQUENCE { + bandCombinationIndex BandCombinationIndex, + requestedFeatureSets FeatureSetEntryIndex +} + +FR-InfoList ::= SEQUENCE (SIZE (1..maxNrofServingCells-1)) OF FR-Info + +FR-Info ::= SEQUENCE { + servCellIndex ServCellIndex, + fr-Type ENUMERATED {fr1, fr2} +} + +CandidateServingFreqListNR ::= SEQUENCE (SIZE (1.. maxFreqIDC-MRDC)) OF ARFCN-ValueNR + +CandidateServingFreqListEUTRA ::= SEQUENCE (SIZE (1.. maxFreqIDC-MRDC)) OF ARFCN-ValueEUTRA + +T-Offset-r16 ::= ENUMERATED {ms0dot5, ms0dot75, ms1, ms1dot5, ms2, ms2dot5, ms3, spare1} + +-- TAG-CG-CONFIG-STOP +-- TAG-CG-CONFIG-INFO-START + +CG-ConfigInfo ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + cg-ConfigInfo CG-ConfigInfo-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +CG-ConfigInfo-IEs ::= SEQUENCE { + ue-CapabilityInfo OCTET STRING (CONTAINING UE-CapabilityRAT-ContainerList) OPTIONAL,-- Cond SN-AddMod + candidateCellInfoListMN MeasResultList2NR OPTIONAL, + candidateCellInfoListSN OCTET STRING (CONTAINING MeasResultList2NR) OPTIONAL, + measResultCellListSFTD-NR MeasResultCellListSFTD-NR OPTIONAL, + scgFailureInfo SEQUENCE { + failureType ENUMERATED { t310-Expiry, randomAccessProblem, + rlc-MaxNumRetx, synchReconfigFailure-SCG, + scg-reconfigFailure, + srb3-IntegrityFailure}, + measResultSCG OCTET STRING (CONTAINING MeasResultSCG-Failure) + } OPTIONAL, + configRestrictInfo ConfigRestrictInfoSCG OPTIONAL, + drx-InfoMCG DRX-Info OPTIONAL, + measConfigMN MeasConfigMN OPTIONAL, + sourceConfigSCG OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + scg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + mcg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + mrdc-AssistanceInfo MRDC-AssistanceInfo OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1540-IEs OPTIONAL +} + +CG-ConfigInfo-v1540-IEs ::= SEQUENCE { + ph-InfoMCG PH-TypeListMCG OPTIONAL, + measResultReportCGI SEQUENCE { + ssbFrequency ARFCN-ValueNR, + cellForWhichToReportCGI PhysCellId, + cgi-Info CGI-InfoNR + } OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1560-IEs OPTIONAL +} + +CG-ConfigInfo-v1560-IEs ::= SEQUENCE { + candidateCellInfoListMN-EUTRA OCTET STRING OPTIONAL, + candidateCellInfoListSN-EUTRA OCTET STRING OPTIONAL, + sourceConfigSCG-EUTRA OCTET STRING OPTIONAL, + scgFailureInfoEUTRA SEQUENCE { + failureTypeEUTRA ENUMERATED { t313-Expiry, randomAccessProblem, + rlc-MaxNumRetx, scg-ChangeFailure}, + measResultSCG-EUTRA OCTET STRING + } OPTIONAL, + drx-ConfigMCG DRX-Config OPTIONAL, + measResultReportCGI-EUTRA SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cellForWhichToReportCGI-EUTRA EUTRA-PhysCellId, + cgi-InfoEUTRA CGI-InfoEUTRA + } OPTIONAL, + measResultCellListSFTD-EUTRA MeasResultCellListSFTD-EUTRA OPTIONAL, + fr-InfoListMCG FR-InfoList OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1570-IEs OPTIONAL +} + +CG-ConfigInfo-v1570-IEs ::= SEQUENCE { + sftdFrequencyList-NR SFTD-FrequencyList-NR OPTIONAL, + sftdFrequencyList-EUTRA SFTD-FrequencyList-EUTRA OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1590-IEs OPTIONAL +} + +CG-ConfigInfo-v1590-IEs ::= SEQUENCE { + servFrequenciesMN-NR SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueNR OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1610-IEs OPTIONAL +} + +CG-ConfigInfo-v1610-IEs ::= SEQUENCE { + drx-InfoMCG2 DRX-Info2 OPTIONAL, + alignedDRX-Indication ENUMERATED {true} OPTIONAL, + scgFailureInfo-r16 SEQUENCE { + failureType-r16 ENUMERATED { scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, bh-RLF-r16, + spare4, spare3, spare2, spare1}, + measResultSCG-r16 OCTET STRING (CONTAINING MeasResultSCG-Failure) + } OPTIONAL, + scgFailureInfoEUTRA-r16 SEQUENCE { + failureTypeEUTRA-r16 ENUMERATED { scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, spare5, + spare4, spare3, spare2, spare1}, + measResultSCG-EUTRA-r16 OCTET STRING + } OPTIONAL, + sidelinkUEInformationNR-r16 OCTET STRING (CONTAINING SidelinkUEInformationNR-r16) OPTIONAL, + sidelinkUEInformationEUTRA-r16 OCTET STRING OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1620-IEs OPTIONAL +} + +CG-ConfigInfo-v1620-IEs ::= SEQUENCE { + ueAssistanceInformationSourceSCG-r16 OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1640-IEs OPTIONAL +} + +CG-ConfigInfo-v1640-IEs ::= SEQUENCE { + servCellInfoListMCG-NR-r16 ServCellInfoListMCG-NR-r16 OPTIONAL, + servCellInfoListMCG-EUTRA-r16 ServCellInfoListMCG-EUTRA-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +ServCellInfoListMCG-NR-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCells)) OF ServCellInfoXCG-NR-r16 + +ServCellInfoListMCG-EUTRA-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCellsEUTRA)) OF ServCellInfoXCG-EUTRA-r16 + +SFTD-FrequencyList-NR ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF ARFCN-ValueNR + +SFTD-FrequencyList-EUTRA ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF ARFCN-ValueEUTRA + +ConfigRestrictInfoSCG ::= SEQUENCE { + allowedBC-ListMRDC BandCombinationInfoList OPTIONAL, + powerCoordination-FR1 SEQUENCE { + p-maxNR-FR1 P-Max OPTIONAL, + p-maxEUTRA P-Max OPTIONAL, + p-maxUE-FR1 P-Max OPTIONAL + } OPTIONAL, + servCellIndexRangeSCG SEQUENCE { + lowBound ServCellIndex, + upBound ServCellIndex + } OPTIONAL, -- Cond SN-AddMod + maxMeasFreqsSCG INTEGER(1..maxMeasFreqsMN) OPTIONAL, + dummy INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + ..., + [[ + selectedBandEntriesMNList SEQUENCE (SIZE (1..maxBandComb)) OF SelectedBandEntriesMN OPTIONAL, + pdcch-BlindDetectionSCG INTEGER (1..15) OPTIONAL, + maxNumberROHC-ContextSessionsSN INTEGER(0.. 16384) OPTIONAL + ]], + [[ + maxIntraFreqMeasIdentitiesSCG INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + maxInterFreqMeasIdentitiesSCG INTEGER(1..maxMeasIdentitiesMN) OPTIONAL + ]], + [[ + p-maxNR-FR1-MCG-r16 P-Max OPTIONAL, + powerCoordination-FR2-r16 SEQUENCE { + p-maxNR-FR2-MCG-r16 P-Max OPTIONAL, + p-maxNR-FR2-SCG-r16 P-Max OPTIONAL, + p-maxUE-FR2-r16 P-Max OPTIONAL + } OPTIONAL, + nrdc-PC-mode-FR1-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, + nrdc-PC-mode-FR2-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, + maxMeasSRS-ResourceSCG-r16 INTEGER(0..maxNrofCLI-SRS-Resources-r16) OPTIONAL, + maxMeasCLI-ResourceSCG-r16 INTEGER(0..maxNrofCLI-RSSI-Resources-r16) OPTIONAL, + maxNumberEHC-ContextsSN-r16 INTEGER(0..65536) OPTIONAL, + allowedReducedConfigForOverheating-r16 OverheatingAssistance OPTIONAL, + maxToffset-r16 T-Offset-r16 OPTIONAL + ]] +} + +SelectedBandEntriesMN ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandEntryIndex + +BandEntryIndex ::= INTEGER (0.. maxNrofServingCells) + +PH-TypeListMCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF PH-InfoMCG + +PH-InfoMCG ::= SEQUENCE { + servCellIndex ServCellIndex, + ph-Uplink PH-UplinkCarrierMCG, + ph-SupplementaryUplink PH-UplinkCarrierMCG OPTIONAL, + ... +} + +PH-UplinkCarrierMCG ::= SEQUENCE{ + ph-Type1or3 ENUMERATED {type1, type3}, + ... +} + +BandCombinationInfoList ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationInfo + +BandCombinationInfo ::= SEQUENCE { + bandCombinationIndex BandCombinationIndex, + allowedFeatureSetsList SEQUENCE (SIZE (1..maxFeatureSetsPerBand)) OF FeatureSetEntryIndex +} + +FeatureSetEntryIndex ::= INTEGER (1.. maxFeatureSetsPerBand) + +DRX-Info ::= SEQUENCE { + drx-LongCycleStartOffset CHOICE { + ms10 INTEGER(0..9), + ms20 INTEGER(0..19), + ms32 INTEGER(0..31), + ms40 INTEGER(0..39), + ms60 INTEGER(0..59), + ms64 INTEGER(0..63), + ms70 INTEGER(0..69), + ms80 INTEGER(0..79), + ms128 INTEGER(0..127), + ms160 INTEGER(0..159), + ms256 INTEGER(0..255), + ms320 INTEGER(0..319), + ms512 INTEGER(0..511), + ms640 INTEGER(0..639), + ms1024 INTEGER(0..1023), + ms1280 INTEGER(0..1279), + ms2048 INTEGER(0..2047), + ms2560 INTEGER(0..2559), + ms5120 INTEGER(0..5119), + ms10240 INTEGER(0..10239) + }, + shortDRX SEQUENCE { + drx-ShortCycle ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-ShortCycleTimer INTEGER (1..16) + } OPTIONAL +} + +DRX-Info2 ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + } +} + +MeasConfigMN ::= SEQUENCE { + measuredFrequenciesMN SEQUENCE (SIZE (1..maxMeasFreqsMN)) OF NR-FreqInfo OPTIONAL, + measGapConfig SetupRelease { GapConfig } OPTIONAL, + gapPurpose ENUMERATED {perUE, perFR1} OPTIONAL, + ..., + [[ + measGapConfigFR2 SetupRelease { GapConfig } OPTIONAL + ]] + +} + +MRDC-AssistanceInfo ::= SEQUENCE { + affectedCarrierFreqCombInfoListMRDC SEQUENCE (SIZE (1..maxNrofCombIDC)) OF AffectedCarrierFreqCombInfoMRDC, + ..., + [[ + overheatingAssistanceSCG-r16 OCTET STRING (CONTAINING OverheatingAssistance) OPTIONAL + ]] +} + +AffectedCarrierFreqCombInfoMRDC ::= SEQUENCE { + victimSystemType VictimSystemType, + interferenceDirectionMRDC ENUMERATED {eutra-nr, nr, other, utra-nr-other, nr-other, spare3, spare2, spare1}, + affectedCarrierFreqCombMRDC SEQUENCE { + affectedCarrierFreqCombEUTRA AffectedCarrierFreqCombEUTRA OPTIONAL, + affectedCarrierFreqCombNR AffectedCarrierFreqCombNR + } OPTIONAL +} + +VictimSystemType ::= SEQUENCE { + gps ENUMERATED {true} OPTIONAL, + glonass ENUMERATED {true} OPTIONAL, + bds ENUMERATED {true} OPTIONAL, + galileo ENUMERATED {true} OPTIONAL, + wlan ENUMERATED {true} OPTIONAL, + bluetooth ENUMERATED {true} OPTIONAL +} + +AffectedCarrierFreqCombEUTRA ::= SEQUENCE (SIZE (1..maxNrofServingCellsEUTRA)) OF ARFCN-ValueEUTRA + +AffectedCarrierFreqCombNR ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF ARFCN-ValueNR + +-- TAG-CG-CONFIG-INFO-STOP +-- TAG-MEASUREMENT-TIMING-CONFIGURATION-START + +MeasurementTimingConfiguration ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + measTimingConf MeasurementTimingConfiguration-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementTimingConfiguration-IEs ::= SEQUENCE { + measTiming MeasTimingList OPTIONAL, + nonCriticalExtension MeasurementTimingConfiguration-v1550-IEs OPTIONAL +} + +MeasurementTimingConfiguration-v1550-IEs ::= SEQUENCE { + campOnFirstSSB BOOLEAN, + psCellOnlyOnFirstSSB BOOLEAN, + nonCriticalExtension MeasurementTimingConfiguration-v1610-IEs OPTIONAL +} + +MeasurementTimingConfiguration-v1610-IEs ::= SEQUENCE { + csi-RS-Config-r16 SEQUENCE { + csi-RS-SubcarrierSpacing-r16 SubcarrierSpacing, + csi-RS-CellMobility-r16 CSI-RS-CellMobility, + refSSBFreq-r16 ARFCN-ValueNR + }, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +MeasTimingList ::= SEQUENCE (SIZE (1..maxMeasFreqsMN)) OF MeasTiming + +MeasTiming ::= SEQUENCE { + frequencyAndTiming SEQUENCE { + carrierFreq ARFCN-ValueNR, + ssbSubcarrierSpacing SubcarrierSpacing, + ssb-MeasurementTimingConfiguration SSB-MTC, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL + } OPTIONAL, + ..., + [[ + ssb-ToMeasure SSB-ToMeasure OPTIONAL, + physCellId PhysCellId OPTIONAL + ]] +} + +-- TAG-MEASUREMENT-TIMING-CONFIGURATION-STOP +-- TAG-UE-RADIO-PAGING-INFORMATION-START + +UERadioPagingInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioPagingInformation UERadioPagingInformation-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioPagingInformation-IEs ::= SEQUENCE { + supportedBandListNRForPaging SEQUENCE (SIZE (1..maxBands)) OF FreqBandIndicatorNR OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +-- TAG-UE-RADIO-PAGING-INFORMATION-STOP +-- TAG-UE-RADIO-ACCESS-CAPABILITY-INFORMATION-START + +UERadioAccessCapabilityInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioAccessCapabilityInformation UERadioAccessCapabilityInformation-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioAccessCapabilityInformation-IEs ::= SEQUENCE { + ue-RadioAccessCapabilityInfo OCTET STRING (CONTAINING UE-CapabilityRAT-ContainerList), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UE-RADIO-ACCESS-CAPABILITY-INFORMATION-STOP +-- TAG-NR-MULTIPLICITY-AND-CONSTRAINTS-START + +maxMeasFreqsMN INTEGER ::= 32 -- Maximum number of MN-configured measurement frequencies +maxMeasFreqsSN INTEGER ::= 32 -- Maximum number of SN-configured measurement frequencies +maxMeasIdentitiesMN INTEGER ::= 62 -- Maximum number of measurement identities that a UE can be configured with +maxCellPrep INTEGER ::= 32 -- Maximum number of cells prepared for handover + +-- TAG-NR-MULTIPLICITY-AND-CONSTRAINTS-STOP +-- TAG-NR-INTER-NODE-DEFINITIONS-END-START + +END + +-- TAG-NR-INTER-NODE-DEFINITIONS-END-STOP diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index dedd4cf839..6b7f9a21b9 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -29,96 +29,79 @@ */ #include "nr_rrc_config.h" +#include "common/utils/nr/nr_common.h" -void rrc_config_rlc_bearer(uint8_t Mod_id, - int CC_id, - rlc_bearer_config_t *rlc_config - ){ - rlc_config->LogicalChannelIdentity[CC_id] = 0; - rlc_config->servedRadioBearer_present[CC_id] = 0; - rlc_config->srb_Identity[CC_id] = 0; - rlc_config->drb_Identity[CC_id] = 0; - rlc_config->reestablishRLC[CC_id] = 0; - rlc_config->rlc_Config_present[CC_id] = 0; - rlc_config->ul_AM_sn_FieldLength[CC_id] = 0; - rlc_config->t_PollRetransmit[CC_id] = 0; - rlc_config->pollPDU[CC_id] = 0; - rlc_config->pollByte[CC_id] = 0; - rlc_config->maxRetxThreshold[CC_id] = 0; - rlc_config->dl_AM_sn_FieldLength[CC_id] = 0; - rlc_config->dl_AM_t_Reassembly[CC_id] = 0; - rlc_config->t_StatusProhibit[CC_id] = 0; - rlc_config->ul_UM_sn_FieldLength[CC_id] = 0; - rlc_config->dl_UM_sn_FieldLength[CC_id] = 0; - rlc_config->dl_UM_t_Reassembly[CC_id] = 0; - rlc_config->priority[CC_id] = 0; - rlc_config->prioritisedBitRate[CC_id] = 0; - rlc_config->bucketSizeDuration[CC_id] = 0; - rlc_config->allowedServingCells[CC_id] = 0; - rlc_config->subcarrierspacing[CC_id] = 0; - rlc_config->maxPUSCH_Duration[CC_id] = 0; - rlc_config->configuredGrantType1Allowed[CC_id] = 0; - rlc_config->logicalChannelGroup[CC_id] = 0; - rlc_config->schedulingRequestID[CC_id] = 0; - rlc_config->logicalChannelSR_Mask[CC_id] = 0; - rlc_config->logicalChannelSR_DelayTimerApplied[CC_id] = 0; +void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc){ + + lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); + + // setting default TDA for DL with + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); + timedomainresourceallocation->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation->startSymbolAndLength = get_SLIV(1,13); // basic slot configuration starting in symbol 1 til the end of the slot + ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, + timedomainresourceallocation); + + if(frame_type==TDD) { + // TDD + if(scc->tdd_UL_DL_ConfigurationCommon) { + int dl_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; + if(dl_symb > 1) { + timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); + timedomainresourceallocation->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation->startSymbolAndLength = get_SLIV(1,dl_symb-1); // mixed slot configuration starting in symbol 1 til the end of the dl allocation + ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, + timedomainresourceallocation); + } + } + } } -void rrc_config_mac_cellgroup(uint8_t Mod_id, - int CC_id, - mac_cellgroup_t *mac_cellgroup_config - ){ - mac_cellgroup_config->DRX_Config_PR[CC_id] = 0; - mac_cellgroup_config->drx_onDurationTimer_PR[CC_id] = 0; - mac_cellgroup_config->subMilliSeconds[CC_id] = 0; - mac_cellgroup_config->milliSeconds[CC_id] = 0; - mac_cellgroup_config->drx_InactivityTimer[CC_id] = 0; - mac_cellgroup_config->drx_HARQ_RTT_TimerDL[CC_id] = 0; - mac_cellgroup_config->drx_HARQ_RTT_TimerUL[CC_id] = 0; - mac_cellgroup_config->drx_RetransmissionTimerDL[CC_id] = 0; - mac_cellgroup_config->drx_RetransmissionTimerUL[CC_id] = 0; - mac_cellgroup_config->drx_LongCycleStartOffset_PR[CC_id] = 0; - mac_cellgroup_config->drx_LongCycleStartOffset[CC_id] = 0; - mac_cellgroup_config->drx_ShortCycle[CC_id] = 0; - mac_cellgroup_config->drx_ShortCycleTimer[CC_id] = 0; - mac_cellgroup_config->drx_SlotOffset[CC_id] = 0; - mac_cellgroup_config->schedulingRequestId[CC_id] = 0; - mac_cellgroup_config->sr_ProhibitTimer[CC_id] = 0; - mac_cellgroup_config->sr_TransMax[CC_id] = 0; - mac_cellgroup_config->periodicBSR_Timer[CC_id] = 0; - mac_cellgroup_config->retxBSR_Timer[CC_id] = 0; - mac_cellgroup_config->logicalChannelSR_DelayTimer[CC_id] = 0; - mac_cellgroup_config->tag_Id[CC_id] = 0; - mac_cellgroup_config->timeAlignmentTimer[CC_id] = 0; - mac_cellgroup_config->PHR_Config_PR[CC_id] = 0; - mac_cellgroup_config->phr_PeriodicTimer[CC_id] = 0; - mac_cellgroup_config->phr_ProhibitTimer[CC_id] = 0; - mac_cellgroup_config->phr_Tx_PowerFactorChange[CC_id] = 0; - mac_cellgroup_config->multiplePHR[CC_id] = 0; - mac_cellgroup_config->phr_Type2SpCell[CC_id] = 0; - mac_cellgroup_config->phr_Type2OtherCell[CC_id] = 0; - mac_cellgroup_config->phr_ModeOtherCG[CC_id] = 0; - mac_cellgroup_config->skipUplinkTxDynamic[CC_id] = 0; + +void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay){ + + //TODO change to accomodate for SRS + + int temp_min_delay = 6; // k2 = 2 or 3 won'r work as well as higher values + int k2 = (min_fb_delayuplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); + + struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); + pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation->k2 = k2; + pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0,13); // basic slot configuration starting in symbol 0 til the last but one symbol + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); + + if(frame_type==TDD) { + // TDD + if(scc->tdd_UL_DL_ConfigurationCommon) { + int ul_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; + pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); + pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation->k2 = k2; + pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); + + // for msg3 in the mixed slot + int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); + int nb_slots_per_period = ((1<k2 = CALLOC(1,sizeof(long)); + *pusch_timedomainresourceallocation_msg3->k2 = nb_slots_per_period - DELTA[mu]; + if(*pusch_timedomainresourceallocation_msg3->k2 < min_fb_delay) + *pusch_timedomainresourceallocation_msg3->k2 += nb_slots_per_period; + AssertFatal(*pusch_timedomainresourceallocation_msg3->k2<33,"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", + *pusch_timedomainresourceallocation_msg3->k2); + pusch_timedomainresourceallocation_msg3->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(14-ul_symb,ul_symb-1); // starting in fist ul symbol til the last but one + ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3); + } + } + } -void rrc_config_physicalcellgroup(uint8_t Mod_id, - int CC_id, - physicalcellgroup_t *physicalcellgroup_config - ){ - physicalcellgroup_config->harq_ACK_SpatialBundlingPUCCH[CC_id] = 0; - physicalcellgroup_config->harq_ACK_SpatialBundlingPUSCH[CC_id] = 0; - physicalcellgroup_config->p_NR[CC_id] = 0; - physicalcellgroup_config->pdsch_HARQ_ACK_Codebook[CC_id] = 0; - physicalcellgroup_config->tpc_SRS_RNTI[CC_id] = 0; - physicalcellgroup_config->tpc_PUCCH_RNTI[CC_id] = 0; - physicalcellgroup_config->tpc_PUSCH_RNTI[CC_id] = 0; - physicalcellgroup_config->sp_CSI_RNTI[CC_id] = 0; - physicalcellgroup_config->RNTI_Value[CC_id] = 0; -} - -void rrc_config_rachdedicated(uint8_t Mod_id, - int CC_id, - physicalcellgroup_t *physicalcellgroup_config - ){ - -} diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index e19d94b341..192fee754e 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -111,29 +111,8 @@ typedef struct physicalcellgroup_s{ long RNTI_Value[MAX_NUM_CCs]; }physicalcellgroup_t; -typedef struct rach_dedicated_s{ - - -}rach_dedicated_t; +void nr_rrc_config_dl_tda(NR_ServingCellConfigCommon_t *scc); +void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay); -void rrc_config_servingcellconfigcommon(uint8_t Mod_id, - int CC_id, - gNB_RrcConfigurationReq *common_configuration - ); - -void rrc_config_rlc_bearer(uint8_t Mod_id, - int CC_id, - rlc_bearer_config_t *rlc_config - ); - -void rrc_config_mac_cellgroup(uint8_t Mod_id, - int CC_id, - mac_cellgroup_t *mac_cellgroup_config - ); - -void rrc_config_physicalcellgroup(uint8_t Mod_id, - int CC_id, - physicalcellgroup_t *physicalcellgroup_config - ); #endif diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index eeb16c3087..d71393bc2d 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -54,6 +54,7 @@ #include "NR_BCCH-BCH-Message.h" #include "NR_PLMN-IdentityInfo.h" #include "NR_MCC-MNC-Digit.h" +#include "NR_NG-5G-S-TMSI.h" //#include "MCCH-Message.h" //#include "MBSFNAreaConfiguration-r9.h" //#include "SCellToAddMod-r10.h" @@ -65,6 +66,7 @@ #include "NR_CellGroupConfig.h" #include "NR_ServingCellConfigCommon.h" #include "NR_EstablishmentCause.h" +#include "NR_SIB1.h" //------------------- #include "intertask_interface.h" @@ -89,10 +91,10 @@ typedef struct nr_uid_linear_allocator_s { #define PROTOCOL_NR_RRC_CTXT_UE_FMT PROTOCOL_CTXT_FMT -#define PROTOCOL_NR_RRC_CTXT_UE_ARGS(CTXT_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp) +#define PROTOCOL_NR_RRC_CTXT_UE_ARGS(CTXT_Pp) PROTOCOL_NR_CTXT_ARGS(CTXT_Pp) #define PROTOCOL_NR_RRC_CTXT_FMT PROTOCOL_CTXT_FMT -#define PROTOCOL_NR_RRC_CTXT_ARGS(CTXT_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp) +#define PROTOCOL_NR_RRC_CTXT_ARGS(CTXT_Pp) PROTOCOL_NR_CTXT_ARGS(CTXT_Pp) #define NR_UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! @@ -126,7 +128,7 @@ typedef enum UE_STATE_NR_e { #define MAX_MEAS_ID 6 #define PAYLOAD_SIZE_MAX 1024 -#define RRC_BUF_SIZE 255 +#define RRC_BUF_SIZE 8192 #define UNDEF_SECURITY_MODE 0xff #define NO_SECURITY_MODE 0x20 @@ -149,7 +151,7 @@ typedef struct UE_RRC_INFO_NR_s { uint32_t SIStatus; uint32_t SIcnt; uint8_t MCCHStatus[8]; // MAX_MBSFN_AREA - uint8_t SIwindowsize; //!< Corresponds to the SIB1 si-WindowLength parameter. The unit is ms. Possible values are (final): 1,2,5,10,15,20,40 + uint16_t SIwindowsize; //!< Corresponds to the SIB1 si-WindowLength parameter. The unit is ms. Possible values are (final): 1,2,5,10,15,20,40 uint8_t handoverTarget; //HO_STATE_t ho_state; uint16_t @@ -168,8 +170,9 @@ typedef struct UE_RRC_INFO_NR_s { typedef struct UE_S_TMSI_NR_s { boolean_t presence; - mme_code_t mme_code; - m_tmsi_t m_tmsi; + uint16_t amf_set_id; + uint8_t amf_pointer; + uint32_t fiveg_tmsi; } __attribute__ ((__packed__)) NR_UE_S_TMSI; @@ -236,16 +239,42 @@ typedef struct RB_INFO_TABLE_ENTRY_NR_s { NR_RB_INFO Rb_info; uint8_t Active; uint32_t Next_check_frame; - uint8_t Status; + uint8_t status; } NR_RB_INFO_TABLE_ENTRY; typedef struct SRB_INFO_TABLE_ENTRY_NR_s { NR_SRB_INFO Srb_info; uint8_t Active; - uint8_t Status; + uint8_t status; uint32_t Next_check_frame; } NR_SRB_INFO_TABLE_ENTRY; +typedef struct nr_rrc_guami_s { + uint16_t mcc; + uint16_t mnc; + uint8_t mnc_len; + uint8_t amf_region_id; + uint16_t amf_set_id; + uint8_t amf_pointer; +} nr_rrc_guami_t; + +typedef enum pdu_session_satus_e { + PDU_SESSION_STATUS_NEW, + PDU_SESSION_STATUS_DONE, + PDU_SESSION_STATUS_ESTABLISHED, + PDU_SESSION_STATUS_REESTABLISHED, // after HO + PDU_SESSION_STATUS_TOMODIFY, // ENDC NSA + PDU_SESSION_STATUS_FAILED, + PDU_SESSION_STATUS_TORELEASE // to release DRB between eNB and UE +} pdu_session_status_t; + +typedef struct pdu_session_param_s { + pdusession_t param; + uint8_t status; + uint8_t xid; // transaction_id + ngap_Cause_t cause; + uint8_t cause_value; +} __attribute__ ((__packed__)) pdu_session_param_t; typedef struct gNB_RRC_UE_s { uint8_t primaryCC_id; @@ -267,72 +296,94 @@ typedef struct gNB_RRC_UE_s { NR_UE_NR_Capability_t* UE_Capability_nr; + int UE_Capability_size; NR_UE_MRDC_Capability_t* UE_Capability_MRDC; + int UE_MRDC_Capability_size; NR_CellGroupConfig_t *secondaryCellGroup; + NR_CellGroupConfig_t *masterCellGroup; NR_RRCReconfiguration_t *reconfig; NR_RadioBearerConfig_t *rb_config; ImsiMobileIdentity_t imsi; -#if defined(ENABLE_SECURITY) - /* KeNB as derived from KASME received from EPC */ - uint8_t kenb[32]; - int8_t kenb_ncc; + /* KgNB as derived from KASME received from EPC */ + uint8_t kgnb[32]; + int8_t kgnb_ncc; uint8_t nh[32]; int8_t nh_ncc; -#endif + /* Used integrity/ciphering algorithms */ NR_CipheringAlgorithm_t ciphering_algorithm; e_NR_IntegrityProtAlgorithm integrity_algorithm; - uint8_t Status; + uint8_t StatusRrc; rnti_t rnti; uint64_t random_ue_identity; - /* Information from UE RRC ConnectionRequest */ - UE_S_TMSI Initialue_identity_s_TMSI; + /* Information from UE RRC Setup Request */ + NR_UE_S_TMSI Initialue_identity_5g_s_TMSI; + uint64_t ng_5G_S_TMSI_Part1; + uint16_t ng_5G_S_TMSI_Part2; NR_EstablishmentCause_t establishment_cause; /* Information from UE RRC ConnectionReestablishmentRequest */ - NR_ReestablishmentCause_t reestablishment_cause; + NR_ReestablishmentCause_t reestablishment_cause; /* UE id for initial connection to S1AP */ uint16_t ue_initial_id; /* Information from S1AP initial_context_setup_req */ uint32_t gNB_ue_s1ap_id :24; + uint32_t gNB_ue_ngap_id; + uint64_t amf_ue_ngap_id:40; + nr_rrc_guami_t ue_guami; - security_capabilities_t security_capabilities; + ngap_security_capabilities_t security_capabilities; /* Total number of e_rab already setup in the list */ uint8_t setup_e_rabs; /* Number of e_rab to be setup in the list */ uint8_t nb_of_e_rabs; + /* Total number of pdu session already setup in the list */ + uint8_t setup_pdu_sessions; + /* Number of pdu session to be setup in the list */ + uint8_t nb_of_pdusessions; /* Number of e_rab to be modified in the list */ uint8_t nb_of_modify_e_rabs; uint8_t nb_of_failed_e_rabs; e_rab_param_t modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; /* list of e_rab to be setup by RRC layers */ + /* list of pdu session to be setup by RRC layers */ e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; + pdu_session_param_t pduSession[NR_NB_RB_MAX];//[NGAP_MAX_PDU_SESSION]; //release e_rabs uint8_t nb_release_of_e_rabs; e_rab_failed_t e_rabs_release_failed[S1AP_MAX_E_RAB]; + uint8_t nb_release_of_pdusessions; + pdusession_failed_t pdusessions_release_failed[NGAP_MAX_PDUSESSION]; // LG: For GTPV1 TUNNELS uint32_t gnb_gtp_teid[S1AP_MAX_E_RAB]; transport_layer_addr_t gnb_gtp_addrs[S1AP_MAX_E_RAB]; rb_id_t gnb_gtp_ebi[S1AP_MAX_E_RAB]; + rb_id_t gnb_gtp_psi[S1AP_MAX_E_RAB]; uint32_t ul_failure_timer; uint32_t ue_release_timer; uint32_t ue_release_timer_thres; uint32_t ue_release_timer_s1; uint32_t ue_release_timer_thres_s1; + uint32_t ue_release_timer_ng; + uint32_t ue_release_timer_thres_ng; uint32_t ue_release_timer_rrc; uint32_t ue_release_timer_thres_rrc; uint32_t ue_reestablishment_timer; uint32_t ue_reestablishment_timer_thres; uint8_t e_rab_release_command_flag; + uint8_t pdu_session_release_command_flag; + uint8_t established_pdu_sessions_flag; + uint32_t ue_rrc_inactivity_timer; + int8_t reestablishment_xid; //------------------------------------------------------------------------------// NR_CellGroupId_t cellGroupId; struct NR_SpCellConfig *spCellConfig; @@ -343,6 +394,10 @@ typedef struct gNB_RRC_UE_s { struct NR_MAC_CellGroupConfig *mac_CellGroupConfig; struct NR_PhysicalCellGroupConfig *physicalCellGroupConfig; + /* Nas Pdu */ + uint8_t nas_pdu_flag; + ngap_nas_pdu_t nas_pdu; + } gNB_RRC_UE_t; typedef uid_t ue_uid_t; @@ -373,27 +428,60 @@ typedef struct { uint8_t *SIB1; uint8_t sizeof_SIB1; + uint8_t *SIB23; + uint8_t sizeof_SIB23; + uint8_t *ServingCellConfigCommon; uint8_t sizeof_servingcellconfigcommon; + int physCellId; + NR_BCCH_BCH_Message_t mib; - int ssb_SubcarrierOffset; + NR_BCCH_BCH_Message_t *mib_DU; + NR_BCCH_DL_SCH_Message_t *siblock1_DU; + NR_SIB1_t *sib1; + NR_SIB2_t *sib2; + NR_SIB3_t *sib3; + NR_BCCH_DL_SCH_Message_t systemInformation; // SIB23 + int ssb_SubcarrierOffset; + int sib1_tda; int pdsch_AntennaPorts; + int pusch_AntennaPorts; + int minRXTXTIME; + int do_CSIRS; NR_BCCH_DL_SCH_Message_t *siblock1; NR_ServingCellConfigCommon_t *servingcellconfigcommon; + NR_PDCCH_ConfigSIB1_t *pdcch_ConfigSIB1; NR_CellGroupConfig_t *secondaryCellGroup[MAX_NR_RRC_UE_CONTEXTS]; NR_SRB_INFO SI; NR_SRB_INFO Srb0; int initial_csi_index[MAX_NR_RRC_UE_CONTEXTS]; + int p_gNB; } rrc_gNB_carrier_data_t; //--------------------------------------------------- +typedef struct { + /* nea0 = 0, nea1 = 1, ... */ + int ciphering_algorithms[4]; + int ciphering_algorithms_count; + + /* nia0 = 0, nia1 = 1, ... */ + int integrity_algorithms[4]; + int integrity_algorithms_count; + + /* flags to enable/disable ciphering and integrity for DRBs */ + int do_drb_ciphering; + int do_drb_integrity; +} nr_security_configuration_t; //---NR---(completely change)--------------------- typedef struct gNB_RRC_INST_s { + ngran_node_t node_type; + uint32_t node_id; + char *node_name; int module_id; eth_params_t eth_params_s; rrc_gNB_carrier_data_t carrier; @@ -402,6 +490,14 @@ typedef struct gNB_RRC_INST_s { int Nb_ue; hash_table_t *initial_id2_s1ap_ids; // key is content is rrc_ue_s1ap_ids_t hash_table_t *s1ap_id2_s1ap_ids ; // key is content is rrc_ue_s1ap_ids_t + hash_table_t *initial_id2_ngap_ids; + hash_table_t *ngap_id2_ngap_ids ; + + /// NR cell id + uint64_t nr_cellid; + + // RRC configuration + gNB_RrcConfigurationReq configuration; // other PLMN parameters /// Mobile country code @@ -419,10 +515,15 @@ typedef struct gNB_RRC_INST_s { int srb1_timer_reordering; int srb1_timer_status_prohibit; int srs_enable[MAX_NUM_CCs]; + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; + int cell_info_configured; + pthread_mutex_t cell_info_mutex; + // security configuration (preferred algorithms) + nr_security_configuration_t security; } gNB_RRC_INST; - #include "nr_rrc_proto.h" //should be put here otherwise compilation error #endif diff --git a/openair2/RRC/NR/nr_rrc_extern.h b/openair2/RRC/NR/nr_rrc_extern.h index 04e0392236..3b08a24027 100644 --- a/openair2/RRC/NR/nr_rrc_extern.h +++ b/openair2/RRC/NR/nr_rrc_extern.h @@ -47,7 +47,6 @@ extern NR_LogicalChannelConfig_t NR_SRB3_logicalChannelConfig_defaultValue; extern unsigned char NB_INST; extern unsigned char NB_eNB_INST; extern uint16_t NB_UE_INST; -extern unsigned short NODE_ID[1]; extern void* bigphys_malloc(int); diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 317282c814..22109c3029 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -39,6 +39,7 @@ #include "LTE_UE-CapabilityRAT-ContainerList.h" #include "NR_CG-Config.h" #include "NR_CG-ConfigInfo.h" +#include "NR_SecurityConfig.h" int rrc_init_nr_global_param(void); @@ -50,6 +51,7 @@ int8_t mac_rrc_nr_data_req(const module_id_t Mod_idP, const int CC_id, const frame_t frameP, const rb_id_t Srb_id, + const rnti_t rnti, const uint8_t Nb_tb, uint8_t *const buffer_pP ); @@ -65,35 +67,143 @@ void rrc_gNB_generate_SgNBAdditionRequestAcknowledge( struct rrc_gNB_ue_context_s *rrc_gNB_allocate_new_UE_context(gNB_RRC_INST *rrc_instance_pP); -void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t * cg_config_info); +void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t * cg_config_info); void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m); +void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); + void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, - NR_CellGroupConfig_t *secondaryCellGroup, - int scg_id, - int servCellIndex, - int n_physical_antenna_ports, - int initial_csi_index); + NR_ServingCellConfig_t *servingcellconfigdedicated, + NR_CellGroupConfig_t *secondaryCellGroup, + int scg_id, + int servCellIndex, + int dl_antenna_ports, + int minRXTXTIMEpdsch, + int do_csirs, + int initial_csi_index, + int uid); + +void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_CSI_MeasConfig_t *csi_MeasConfig, int dl_antenna_ports, int do_csirs); void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, - NR_RRCReconfiguration_IEs_t *reconfig, - NR_CellGroupConfig_t *secondaryCellGroup, - int n_physical_antenna_ports, - int initial_csi_index); + NR_ServingCellConfig_t *servingcellconfigdedicated, + NR_RRCReconfiguration_IEs_t *reconfig, + NR_CellGroupConfig_t *secondaryCellGroup, + int dl_antenna_ports, + int minRXTXTIMEpdsch, + int do_csirs, + int initial_csi_index, + int uid); -void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig); +void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig, + int eps_bearer_id, int rb_id, + e_NR_CipheringAlgorithm ciphering_algorithm, + e_NR_SecurityConfig__keyToUse key_to_use); int generate_CG_Config(gNB_RRC_INST *rrc, NR_CG_Config_t *cg_Config, NR_RRCReconfiguration_t *reconfig, NR_RadioBearerConfig_t *rbconfig); +void apply_macrlc_config(gNB_RRC_INST *rrc, + rrc_gNB_ue_context_t *const ue_context_pP, + const protocol_ctxt_t *const ctxt_pP ); + +void apply_pdcp_config(rrc_gNB_ue_context_t *const ue_context_pP, + const protocol_ctxt_t *const ctxt_pP ); + +void +rrc_gNB_generate_RRCSetup( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + OCTET_STRING_t *masterCellGroup_from_DU, + NR_ServingCellConfigCommon_t *scc, + const int CC_id); + int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m); +void +rrc_gNB_generate_SecurityModeCommand( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP +); +uint8_t +rrc_gNB_get_next_transaction_identifier( + module_id_t gnb_mod_idP +); + +void +rrc_gNB_generate_UECapabilityEnquiry( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP +); + +void +rrc_gNB_generate_RRCRelease( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP +); /**\brief RRC eNB task. \param void *args_p Pointer on arguments to start the task. */ void *rrc_gnb_task(void *args_p); +/* Trigger RRC periodic processing. To be called once per ms. */ +void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe); + +/**\ Function to set or overwrite PTRS DL RRC parameters. + \ *bwp Pointer to dedicated RC config structure + \ *ptrsNrb Pointer to K_ptrs N_RB related parameters + \ *ptrsMcs Pointer to L_ptrs MCS related parameters + \ *epre_Ratio Pointer to ep_ratio + \ *reOffset Pointer to RE Offset Value */ +void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset); + +uint8_t +nr_rrc_data_req( + const protocol_ctxt_t *const ctxt_pP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_size, + uint8_t *const buffer_pP, + const pdcp_transmission_mode_t modeP +); + +int +nr_rrc_mac_remove_ue(module_id_t mod_idP, + rnti_t rntiP); + +int8_t nr_mac_rrc_data_ind( + const module_id_t module_idP, + const int CC_id, + const frame_t frameP, + const sub_frame_t sub_frameP, + const int UE_id, + const rnti_t rntiP, + const rb_id_t srb_idP, + const uint8_t *sduP, + const sdu_size_t sdu_lenP, + const boolean_t brOption +); + +int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, + const uint8_t *buffer, + int buffer_length, + OCTET_STRING_t *du_to_cu_rrc_container, + const int CC_id); + +void +rrc_gNB_generate_dedicatedRRCReconfiguration_release( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid, + uint32_t nas_length, + uint8_t *nas_buffer); + +void +rrc_gNB_generate_dedicatedRRCReconfiguration( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP); diff --git a/openair2/RRC/NR/nr_rrc_types.h b/openair2/RRC/NR/nr_rrc_types.h index 02495591a9..61f90e3572 100644 --- a/openair2/RRC/NR/nr_rrc_types.h +++ b/openair2/RRC/NR/nr_rrc_types.h @@ -32,11 +32,11 @@ #define RRC_TYPES_NR_H_ typedef enum Rrc_State_NR_e { - RRC_STATE_INACTIVE_NR=0, - RRC_STATE_IDLE_NR, + RRC_STATE_IDLE_NR=0, + RRC_STATE_INACTIVE_NR, RRC_STATE_CONNECTED_NR, - RRC_STATE_FIRST_NR = RRC_STATE_INACTIVE_NR, + RRC_STATE_FIRST_NR = RRC_STATE_IDLE_NR, RRC_STATE_LAST_NR = RRC_STATE_CONNECTED_NR, } Rrc_State_NR_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c old mode 100644 new mode 100755 index 1f341cfdf9..7f7353f9af --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -51,6 +51,11 @@ #include "NR_MeasResults.h" #include "LTE_UECapabilityInformation.h" #include "LTE_UL-DCCH-Message.h" +#include "NR_UL-CCCH-Message.h" +#include "NR_RRCSetupRequest-IEs.h" +#include "NR_RRCSetupComplete-IEs.h" +#include "NR_RRCReestablishmentRequest-IEs.h" +#include "NR_MIB.h" #include "rlc.h" #include "rrc_eNB_UE_context.h" @@ -65,14 +70,14 @@ #include "OCG.h" #include "OCG_extern.h" -#if defined(ENABLE_SECURITY) - #include "UTIL/OSA/osa_defs.h" -#endif +#include "UTIL/OSA/osa_defs.h" #include "rrc_eNB_S1AP.h" +#include "rrc_gNB_NGAP.h" + #include "rrc_eNB_GTPV1U.h" - +#include "nr_pdcp/nr_pdcp_entity.h" #include "pdcp.h" #include "gtpv1u_eNB_task.h" @@ -82,13 +87,40 @@ #include "executables/softmodem-common.h" #include +#include + +#include "BIT_STRING.h" +#include "assertions.h" //#define XER_PRINT - extern RAN_CONTEXT_t RC; +extern boolean_t nr_rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc, + uint8_t *const kUPint + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 + ,rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +static inline uint64_t bitStr_to_uint64(BIT_STRING_t *asn); + mui_t rrc_gNB_mui = 0; +uint8_t first_rrcreconfiguration = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// @@ -104,93 +136,46 @@ void openair_nr_rrc_on(const protocol_ctxt_t *const ctxt_pP) { ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// -void rrc_gNB_process_SgNBAdditionRequest( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP -) { - rrc_gNB_generate_SgNBAdditionRequestAcknowledge(ctxt_pP,ue_context_pP); -} - -void rrc_gNB_generate_SgNBAdditionRequestAcknowledge( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP) { - //uint8_t size; - //uint8_t buffer[100]; - //int CC_id = ue_context_pP->ue_context.primaryCC_id; - //OCTET_STRING_t *secondaryCellGroup; - NR_CellGroupConfig_t *cellGroupconfig; - struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_BearerToAddModList; - struct NR_MAC_CellGroupConfig *mac_CellGroupConfig; - struct NR_PhysicalCellGroupConfig *physicalCellGroupConfig; - struct NR_SpCellConfig *spCellConfig; - //struct NR_CellGroupConfig__sCellToAddModList *sCellToAddModList; - cellGroupconfig = CALLOC(1,sizeof(NR_CellGroupConfig_t)); - cellGroupconfig->rlc_BearerToAddModList = CALLOC(1,sizeof(struct NR_CellGroupConfig__rlc_BearerToAddModList)); - cellGroupconfig->mac_CellGroupConfig = CALLOC(1,sizeof(struct NR_MAC_CellGroupConfig)); - cellGroupconfig->physicalCellGroupConfig = CALLOC(1,sizeof(struct NR_PhysicalCellGroupConfig)); - cellGroupconfig->spCellConfig = CALLOC(1,sizeof(struct NR_SpCellConfig)); - //cellGroupconfig->sCellToAddModList = CALLOC(1,sizeof(struct NR_CellGroupConfig__sCellToAddModList)); - rlc_BearerToAddModList = cellGroupconfig->rlc_BearerToAddModList; - mac_CellGroupConfig = cellGroupconfig->mac_CellGroupConfig; - physicalCellGroupConfig = cellGroupconfig->physicalCellGroupConfig; - spCellConfig = cellGroupconfig->spCellConfig; - //sCellToAddModList = cellGroupconfig->sCellToAddModList; - rlc_bearer_config_t *rlc_config; - rlc_config = CALLOC(1,sizeof(rlc_bearer_config_t)); - //Fill rlc_bearer config value - rrc_config_rlc_bearer(ctxt_pP->module_id, - ue_context_pP->ue_context.primaryCC_id, - rlc_config - ); - //Fill rlc_bearer config to structure - do_RLC_BEARER(ctxt_pP->module_id, - ue_context_pP->ue_context.primaryCC_id, - rlc_BearerToAddModList, - rlc_config); - mac_cellgroup_t *mac_cellgroup_config; - mac_cellgroup_config = CALLOC(1,sizeof(mac_cellgroup_t)); - //Fill mac_cellgroup_config config value - rrc_config_mac_cellgroup(ctxt_pP->module_id, - ue_context_pP->ue_context.primaryCC_id, - mac_cellgroup_config - ); - //Fill mac_cellgroup config to structure - do_MAC_CELLGROUP(ctxt_pP->module_id, - ue_context_pP->ue_context.primaryCC_id, - mac_CellGroupConfig, - mac_cellgroup_config); - physicalcellgroup_t *physicalcellgroup_config; - physicalcellgroup_config = CALLOC(1,sizeof(physicalcellgroup_t)); - //Fill physicalcellgroup_config config value - rrc_config_physicalcellgroup(ctxt_pP->module_id, - ue_context_pP->ue_context.primaryCC_id, - physicalcellgroup_config - ); - //Fill physicalcellgroup config to structure - do_PHYSICALCELLGROUP(ctxt_pP->module_id, - ue_context_pP->ue_context.primaryCC_id, - physicalCellGroupConfig, - physicalcellgroup_config); - do_SpCellConfig(RC.nrrrc[ctxt_pP->module_id], - spCellConfig); -} - -///---------------------------------------------------------------------------------------------------------------/// -///---------------------------------------------------------------------------------------------------------------/// - -static void init_NR_SI(gNB_RRC_INST *rrc) { +static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration) { LOG_D(RRC,"%s()\n\n\n\n",__FUNCTION__); - rrc->carrier.MIB = (uint8_t *) malloc16(4); - rrc->carrier.sizeof_MIB = do_MIB_NR(rrc,0); + if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) { + rrc->carrier.MIB = (uint8_t *) malloc16(4); + rrc->carrier.sizeof_MIB = do_MIB_NR(rrc,0); + } + + if((get_softmodem_params()->sa) && ( (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)))) { + rrc->carrier.sizeof_SIB1 = do_SIB1_NR(&rrc->carrier,configuration); + } + + if (!NODE_IS_DU(rrc->node_type)) { + rrc->carrier.SIB23 = (uint8_t *) malloc16(100); + AssertFatal(rrc->carrier.SIB23 != NULL, "cannot allocate memory for SIB"); + rrc->carrier.sizeof_SIB23 = do_SIB23_NR(&rrc->carrier, configuration); + LOG_I(NR_RRC,"do_SIB23_NR, size %d \n ", rrc->carrier.sizeof_SIB23); + AssertFatal(rrc->carrier.sizeof_SIB23 != 255,"FATAL, RC.nrrrc[mod].carrier[CC_id].sizeof_SIB23 == 255"); + } + LOG_I(NR_RRC,"Done init_NR_SI\n"); - rrc_mac_config_req_gNB(rrc->module_id, - rrc->carrier.ssb_SubcarrierOffset, - rrc->carrier.pdsch_AntennaPorts, - (NR_ServingCellConfigCommon_t *)rrc->carrier.servingcellconfigcommon, - 0, - 0, // WIP hardcoded rnti - (NR_CellGroupConfig_t *)NULL - ); + + if (NODE_IS_MONOLITHIC(rrc->node_type)){ + rrc_mac_config_req_gNB(rrc->module_id, + rrc->carrier.ssb_SubcarrierOffset, + rrc->carrier.pdsch_AntennaPorts, + rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, + (NR_ServingCellConfigCommon_t *)rrc->carrier.servingcellconfigcommon, + &rrc->carrier.mib, + 0, + 0, // WIP hardcoded rnti + (NR_CellGroupConfig_t *)NULL + ); + } + + /* set flag to indicate that cell information is configured. This is required + * in DU to trigger F1AP_SETUP procedure */ + pthread_mutex_lock(&rrc->cell_info_mutex); + rrc->cell_info_configured=1; + pthread_mutex_unlock(&rrc->cell_info_mutex); if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { // This is for phytest only, emulate first X2 message if uecap.raw file is present @@ -237,13 +222,16 @@ static void init_NR_SI(gNB_RRC_INST *rrc) { parse_CG_ConfigInfo(rrc,CG_ConfigInfo,NULL); } else { struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_allocate_new_UE_context(rrc); + ue_context_p->ue_context.spCellConfig = calloc(1, sizeof(struct NR_SpCellConfig)); + ue_context_p->ue_context.spCellConfig->spCellConfigDedicated = configuration->scd; LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p); - rrc_add_nsa_user(rrc,ue_context_p,NULL); + if (!NODE_IS_CU(RC.nrrrc[0]->node_type)) { + rrc_add_nsa_user(rrc,ue_context_p,NULL); + } } } } - char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration) { protocol_ctxt_t ctxt; gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP]; @@ -262,12 +250,21 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu RB_INIT(&rrc->rrc_ue_head); rrc->initial_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL); rrc->s1ap_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL); + rrc->initial_id2_ngap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL); + rrc->ngap_id2_ngap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL); rrc->carrier.servingcellconfigcommon = configuration->scc; rrc->carrier.ssb_SubcarrierOffset = configuration->ssb_SubcarrierOffset; rrc->carrier.pdsch_AntennaPorts = configuration->pdsch_AntennaPorts; - /// System Information INIT + rrc->carrier.pusch_AntennaPorts = configuration->pusch_AntennaPorts; + rrc->carrier.minRXTXTIME = configuration->minRXTXTIME; + rrc->carrier.sib1_tda = configuration->sib1_tda; + rrc->carrier.do_CSIRS = configuration->do_CSIRS; + nr_rrc_config_ul_tda(configuration->scc,configuration->minRXTXTIME); + /// System Information INIT + pthread_mutex_init(&rrc->cell_info_mutex,NULL); + rrc->cell_info_configured = 0; LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" Checking release \n",PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt)); - init_NR_SI(rrc); + init_NR_SI(rrc, configuration); rrc_init_nr_global_param(); openair_nr_rrc_on(&ctxt); return 0; @@ -297,6 +294,2793 @@ void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x parse_CG_ConfigInfo(rrc,cg_configinfo,m); } + +//----------------------------------------------------------------------------- +uint8_t +rrc_gNB_get_next_transaction_identifier( + module_id_t gnb_mod_idP +) +//----------------------------------------------------------------------------- +{ + static uint8_t nr_rrc_transaction_identifier[NUMBER_OF_gNB_MAX]; + nr_rrc_transaction_identifier[gnb_mod_idP] = (nr_rrc_transaction_identifier[gnb_mod_idP] + 1) % NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; + LOG_T(NR_RRC, "generated xid is %d\n", nr_rrc_transaction_identifier[gnb_mod_idP]); + return nr_rrc_transaction_identifier[gnb_mod_idP]; +} + +void apply_macrlc_config(gNB_RRC_INST *rrc, + rrc_gNB_ue_context_t *const ue_context_pP, + const protocol_ctxt_t *const ctxt_pP ) { + + rrc_mac_config_req_gNB(rrc->module_id, + rrc->carrier.ssb_SubcarrierOffset, + rrc->carrier.pdsch_AntennaPorts, + rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, + NULL, + NULL, + 0, + ue_context_pP->ue_context.rnti, + get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup : (NR_CellGroupConfig_t *)NULL); + + nr_rrc_rlc_config_asn1_req(ctxt_pP, + ue_context_pP->ue_context.SRB_configList, + NULL, + NULL, + NULL, + get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL); + +} + +void apply_pdcp_config(rrc_gNB_ue_context_t *const ue_context_pP, + const protocol_ctxt_t *const ctxt_pP ) { + + nr_rrc_pdcp_config_asn1_req(ctxt_pP, + ue_context_pP->ue_context.SRB_configList, + NULL, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL); + +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_RRCSetup( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + OCTET_STRING_t *masterCellGroup_from_DU, + NR_ServingCellConfigCommon_t *scc, + const int CC_id +) +//----------------------------------------------------------------------------- +{ + LOG_D(NR_RRC, "rrc_gNB_generate_RRCSetup \n"); + MessageDef *message_p; + + // T(T_GNB_RRC_SETUP, + // T_INT(ctxt_pP->module_id), + // T_INT(ctxt_pP->frame), + // T_INT(ctxt_pP->subframe), + // T_INT(ctxt_pP->rnti)); + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + ue_p->Srb0.Tx_buffer.payload_size = do_RRCSetup(ue_context_pP, + (uint8_t *) ue_p->Srb0.Tx_buffer.Payload, + rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id), + masterCellGroup_from_DU, + scc,&rrc->carrier); + + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, + (char *)(ue_p->Srb0.Tx_buffer.Payload), + ue_p->Srb0.Tx_buffer.payload_size, + "[MSG] RRC Setup\n"); + + switch (rrc->node_type) { + case ngran_gNB_CU: + // create an ITTI message + /* TODO: F1 IDs ar missing in RRC */ + nr_rrc_pdcp_config_asn1_req(ctxt_pP, + ue_context_pP->ue_context.SRB_configList, + NULL, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_DL_RRC_MESSAGE); + F1AP_DL_RRC_MESSAGE (message_p).rrc_container = (uint8_t *)ue_p->Srb0.Tx_buffer.Payload; + F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = ue_p->Srb0.Tx_buffer.payload_size; + F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id = 0; + F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id = 0; + F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id = 0xFFFFFFFF; // unknown + F1AP_DL_RRC_MESSAGE (message_p).rnti = ue_p->rnti; + F1AP_DL_RRC_MESSAGE (message_p).srb_id = CCCH; + F1AP_DL_RRC_MESSAGE (message_p).execute_duplication = 1; + F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc = 0; + itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p); + LOG_D(NR_RRC, "Send F1AP_DL_RRC_MESSAGE with ITTI\n"); + + break; + + case ngran_gNB_DU: + // nothing to do for DU + AssertFatal(1==0,"nothing to do for DU\n"); + break; + + case ngran_gNB: + { + // rrc_mac_config_req_gNB + +#ifdef ITTI_SIM + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_p->Srb0.Tx_buffer.payload_size); + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, + ue_p->Srb0.Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_CCCH_DATA_IND); + GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_gNB --- MAC_CONFIG_REQ (SRB1) ---> MAC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + ue_p->Srb0.Tx_buffer.Header, // LG WARNING + ue_p->Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" RRCSetup UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + ue_p->Srb0.Tx_buffer.payload_size); + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_p->Srb0.Tx_buffer.payload_size); + // activate release timer, if RRCSetupComplete not received after 100 frames, remove UE + ue_context_pP->ue_context.ue_release_timer = 1; + // remove UE after 10 frames after RRCConnectionRelease is triggered + ue_context_pP->ue_context.ue_release_timer_thres = 1000; + /* init timers */ + // ue_context_pP->ue_context.ue_rrc_inactivity_timer = 0; + + // configure MAC + + apply_macrlc_config(rrc,ue_context_pP,ctxt_pP); + + apply_pdcp_config(ue_context_pP,ctxt_pP); +#endif + } + break; + + default: + LOG_W(NR_RRC, "Unknown node type %d\n", rrc->node_type); + break; + } +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest( + const protocol_ctxt_t *const ctxt_pP, + const int CC_id +) +//----------------------------------------------------------------------------- +{ + LOG_I(NR_RRC, "generate RRCSetup for RRCReestablishmentRequest \n"); + rrc_gNB_ue_context_t *ue_context_pP = NULL; + gNB_RRC_INST *rrc_instance_p = RC.nrrrc[ctxt_pP->module_id]; + NR_ServingCellConfigCommon_t *scc=rrc_instance_p->carrier.servingcellconfigcommon; + + ue_context_pP = rrc_gNB_get_next_free_ue_context(ctxt_pP, rrc_instance_p, 0); + + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + ue_p->Srb0.Tx_buffer.payload_size = do_RRCSetup(ue_context_pP, + (uint8_t *) ue_p->Srb0.Tx_buffer.Payload, + rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id), + NULL, + scc,&rrc_instance_p->carrier); + + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, + (char *)(ue_p->Srb0.Tx_buffer.Payload), + ue_p->Srb0.Tx_buffer.payload_size, + "[MSG] RRC Setup\n"); + + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_gNB --- MAC_CONFIG_REQ (SRB1) ---> MAC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + rrc_mac_config_req_gNB(rrc_instance_p->module_id, + rrc_instance_p->carrier.ssb_SubcarrierOffset, + rrc_instance_p->carrier.pdsch_AntennaPorts, + rrc_instance_p->carrier.pusch_AntennaPorts, + rrc_instance_p->carrier.sib1_tda, + (NR_ServingCellConfigCommon_t *)rrc_instance_p->carrier.servingcellconfigcommon, + &rrc_instance_p->carrier.mib, + 0, + ue_context_pP->ue_context.rnti, + (NR_CellGroupConfig_t *)NULL + ); + + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + ue_p->Srb0.Tx_buffer.Header, // LG WARNING + ue_p->Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" RRCSetup UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + ue_p->Srb0.Tx_buffer.payload_size); + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_p->Srb0.Tx_buffer.payload_size); + // activate release timer, if RRCSetupComplete not received after 100 frames, remove UE + ue_context_pP->ue_context.ue_release_timer = 1; + // remove UE after 10 frames after RRCConnectionRelease is triggered + ue_context_pP->ue_context.ue_release_timer_thres = 1000; + /* init timers */ + // ue_context_pP->ue_context.ue_rrc_inactivity_timer = 0; +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, + ue_p->Srb0.Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_CCCH_DATA_IND); + GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#endif +} + +void +rrc_gNB_generate_RRCReject( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + const int CC_id +) +//----------------------------------------------------------------------------- +{ + LOG_I(NR_RRC, "rrc_gNB_generate_RRCReject \n"); + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + MessageDef *message_p; + + ue_p->Srb0.Tx_buffer.payload_size = do_RRCReject(ctxt_pP->module_id, + (uint8_t *)ue_p->Srb0.Tx_buffer.Payload); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, + (char *)(ue_p->Srb0.Tx_buffer.Payload), + ue_p->Srb0.Tx_buffer.payload_size, + "[MSG] RRCReject \n"); + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, + MSC_RRC_UE, + ue_p->Srb0.Tx_buffer.Header, + ue_p->Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" NR_RRCReject UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP == NULL ? -1 : ue_context_pP->ue_context.rnti, + ue_p->Srb0.Tx_buffer.payload_size); + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating NR_RRCReject (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_p->Srb0.Tx_buffer.payload_size); + + switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { + case ngran_gNB_CU: + // create an ITTI message + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_DL_RRC_MESSAGE); + F1AP_DL_RRC_MESSAGE (message_p).rrc_container = (uint8_t *)ue_p->Srb0.Tx_buffer.Payload; + F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = ue_p->Srb0.Tx_buffer.payload_size; + F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id = 0; + F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id = 0; + F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id = 0xFFFFFFFF; // unknown + F1AP_DL_RRC_MESSAGE (message_p).rnti = ue_p->rnti; + F1AP_DL_RRC_MESSAGE (message_p).srb_id = CCCH; + F1AP_DL_RRC_MESSAGE (message_p).execute_duplication = 1; + F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc = 0; + itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p); + LOG_D(NR_RRC, "Send F1AP_DL_RRC_MESSAGE with ITTI\n"); + break; + + case ngran_gNB_DU: + // nothing to do for DU + AssertFatal(1==0,"nothing to do for DU\n"); + break; + + case ngran_gNB: + { +#ifdef ITTI_SIM + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, + ue_p->Srb0.Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_CCCH_DATA_IND); + GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#endif + // rrc_mac_config_req_gNB + } + break; + + default : + LOG_W(NR_RRC, "Unknown node type %d\n", RC.nrrrc[ctxt_pP->module_id]->node_type); + } +} + +//----------------------------------------------------------------------------- +/* +* Process the rrc setup complete message from UE (SRB1 Active) +*/ +void +rrc_gNB_process_RRCSetupComplete( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + NR_RRCSetupComplete_IEs_t *rrcSetupComplete +) +//----------------------------------------------------------------------------- +{ + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, " "processing NR_RRCSetupComplete from UE (SRB1 Active)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + ue_context_pP->ue_context.Srb1.Active = 1; + ue_context_pP->ue_context.Srb1.Srb_info.Srb_id = 1; + ue_context_pP->ue_context.StatusRrc = NR_RRC_CONNECTED; + + if (AMF_MODE_ENABLED) { + rrc_gNB_send_NGAP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcSetupComplete); + } else { + rrc_gNB_generate_SecurityModeCommand(ctxt_pP, ue_context_pP); + } +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_defaultRRCReconfiguration( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP +) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + /*NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; + NR_DRB_ToAddModList_t **DRB_configList = NULL; + NR_DRB_ToAddModList_t **DRB_configList2 = NULL; + NR_SRB_ToAddMod_t *SRB2_config = NULL; + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_SDAP_Config_t *sdap_config = NULL;*/ + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList + *dedicatedNAS_MessageList = NULL; + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; + + uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + + /******************** Radio Bearer Config ********************/ + /* Configure SRB2 */ + /*SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; + if (*SRB_configList2) { + free(*SRB_configList2); + } + *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); + memset(*SRB_configList2, 0, sizeof(**SRB_configList2)); + SRB2_config = CALLOC(1, sizeof(*SRB2_config)); + SRB2_config->srb_Identity = 2; + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config);*/ + + /* Configure DRB */ + /*DRB_configList = &ue_context_pP->ue_context.DRB_configList; + if (*DRB_configList) { + free(*DRB_configList); + } + *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); + memset(*DRB_configList, 0, sizeof(**DRB_configList)); + + DRB_configList2 = &ue_context_pP->ue_context.DRB_configList2[xid]; + if (*DRB_configList2) { + free(*DRB_configList2); + } + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); + + DRB_config = CALLOC(1, sizeof(*DRB_config)); + DRB_config->drb_Identity = 1; + DRB_config->cnAssociation = CALLOC(1, sizeof(*DRB_config->cnAssociation)); + DRB_config->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + // TODO sdap_Config + sdap_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); + memset(sdap_config, 0, sizeof(NR_SDAP_Config_t)); + DRB_config->cnAssociation->choice.sdap_Config = sdap_config; + // TODO pdcp_Config + DRB_config->reestablishPDCP = NULL; + DRB_config->recoverPDCP = NULL; + DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config)); + DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb)); + DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer)); + *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; + DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL)); + *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL)); + *DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; + DRB_config->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + DRB_config->pdcp_Config->drb->headerCompression.choice.notUsed = 0; + + DRB_config->pdcp_Config->drb->integrityProtection = NULL; + DRB_config->pdcp_Config->drb->statusReportRequired = NULL; + DRB_config->pdcp_Config->drb->outOfOrderDelivery = NULL; + DRB_config->pdcp_Config->moreThanOneRLC = NULL; + + DRB_config->pdcp_Config->t_Reordering = calloc(1, sizeof(*DRB_config->pdcp_Config->t_Reordering)); + *DRB_config->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; + DRB_config->pdcp_Config->ext1 = NULL; + + ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config); + ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config);*/ + + dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + + /* Add all NAS PDUs to the list */ + for (int i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { + dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); + memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedNAS_Message, + (char *)ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer, + ue_context_pP->ue_context.pduSession[i].param.nas_pdu.length); + ASN_SEQUENCE_ADD(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); + } + + ue_context_pP->ue_context.pduSession[i].status = PDU_SESSION_STATUS_DONE; + LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", + i, ue_context_pP->ue_context.pduSession[i].status, "PDU_SESSION_STATUS_DONE"); + } + + if (ue_context_pP->ue_context.nas_pdu_flag == 1) { + dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); + memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedNAS_Message, + (char *)ue_context_pP->ue_context.nas_pdu.buffer, + ue_context_pP->ue_context.nas_pdu.length); + ASN_SEQUENCE_ADD(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); + } + + /* If list is empty free the list and reset the address */ + if (dedicatedNAS_MessageList->list.count == 0) { + free(dedicatedNAS_MessageList); + dedicatedNAS_MessageList = NULL; + } + + memset(buffer, 0, RRC_BUF_SIZE); + size = do_RRCReconfiguration(ctxt_pP, buffer, + xid, + NULL, //*SRB_configList2, + NULL, //*DRB_configList, + NULL, + NULL, + NULL, + NULL, + dedicatedNAS_MessageList, + NULL, + NULL); + + free(ue_context_pP->ue_context.nas_pdu.buffer); + + LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)buffer, size, "[MSG] RRC Reconfiguration\n"); + + /* Free all NAS PDUs */ + for (int i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { + free(ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer); + ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer = NULL; + } + } + + LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE id %x)\n", + ctxt_pP->module_id, + ctxt_pP->frame, + size, + ue_context_pP->ue_context.rnti); + switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { + case ngran_gNB_CU: + nr_rrc_data_req(ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + // rrc_pdcp_config_asn1_req + + break; + + case ngran_gNB_DU: + // nothing to do for DU + AssertFatal(1==0,"nothing to do for DU\n"); + break; + + case ngran_gNB: + { +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + LOG_D(NR_RRC, "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, + ctxt_pP->module_id, + size, + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + ctxt_pP->module_id, + DCCH); + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" NR_RRCReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); + nr_rrc_data_req(ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + // rrc_pdcp_config_asn1_req +#endif + // rrc_rlc_config_asn1_req + } + break; + + default : + LOG_W(NR_RRC, "Unknown node type %d\n", RC.nrrrc[ctxt_pP->module_id]->node_type); + } +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_dedicatedRRCReconfiguration( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP +) +//----------------------------------------------------------------------------- +{ + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_SRB_ToAddMod_t *SRB2_config = NULL; + NR_SDAP_Config_t *sdap_config = NULL; + NR_DRB_ToAddModList_t **DRB_configList = NULL; + NR_DRB_ToAddModList_t **DRB_configList2 = NULL; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList + *dedicatedNAS_MessageList = NULL; + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + int qos_flow_index = 0; + NR_QFI_t qfi = 0; + int pdu_sessions_done = 0; + int i; + NR_CellGroupConfig_t *cellGroupConfig; + + uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + + /* Configure SRB2 */ + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; + if (*SRB_configList2 == NULL) { + *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); + memset(*SRB_configList2, 0, sizeof(**SRB_configList2)); + SRB2_config = CALLOC(1, sizeof(*SRB2_config)); + SRB2_config->srb_Identity = 2; + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); + } + + DRB_configList = &ue_context_pP->ue_context.DRB_configList; + if (*DRB_configList) { + free(*DRB_configList); + } + *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); + memset(*DRB_configList, 0, sizeof(**DRB_configList)); + + DRB_configList2 = &ue_context_pP->ue_context.DRB_configList2[xid]; + if (*DRB_configList2) { + free(*DRB_configList2); + } + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); + + dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + + for (i = 0; i < ue_context_pP->ue_context.setup_pdu_sessions; i++) { + if (pdu_sessions_done >= ue_context_pP->ue_context.nb_of_pdusessions) { + break; + } + + if (ue_context_pP->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE) { + continue; + } + + DRB_config = CALLOC(1, sizeof(*DRB_config)); + DRB_config->drb_Identity = i+1; + DRB_config->cnAssociation = CALLOC(1, sizeof(*DRB_config->cnAssociation)); + DRB_config->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + // sdap_Config + sdap_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); + memset(sdap_config, 0, sizeof(NR_SDAP_Config_t)); + sdap_config->pdu_Session = ue_context_pP->ue_context.pduSession[i].param.pdusession_id; + sdap_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; + sdap_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; + sdap_config->defaultDRB = TRUE; + sdap_config->mappedQoS_FlowsToAdd = calloc(1, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd)); + memset(sdap_config->mappedQoS_FlowsToAdd, 0, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd)); + + for (qos_flow_index = 0; qos_flow_index < ue_context_pP->ue_context.pduSession[i].param.nb_qos; qos_flow_index++) { + qfi = ue_context_pP->ue_context.pduSession[i].param.qos[qos_flow_index].qfi; + ASN_SEQUENCE_ADD(&sdap_config->mappedQoS_FlowsToAdd->list, &qfi); + } + sdap_config->mappedQoS_FlowsToRelease = NULL; + DRB_config->cnAssociation->choice.sdap_Config = sdap_config; + + // pdcp_Config + DRB_config->reestablishPDCP = NULL; + DRB_config->recoverPDCP = NULL; + DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config)); + DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb)); + DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer)); + *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; + DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL)); + *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL)); + *DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; + DRB_config->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + DRB_config->pdcp_Config->drb->headerCompression.choice.notUsed = 0; + + DRB_config->pdcp_Config->drb->integrityProtection = NULL; + DRB_config->pdcp_Config->drb->statusReportRequired = NULL; + DRB_config->pdcp_Config->drb->outOfOrderDelivery = NULL; + DRB_config->pdcp_Config->moreThanOneRLC = NULL; + + DRB_config->pdcp_Config->t_Reordering = calloc(1, sizeof(*DRB_config->pdcp_Config->t_Reordering)); + *DRB_config->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; + DRB_config->pdcp_Config->ext1 = NULL; + + if (rrc->security.do_drb_integrity) { + DRB_config->pdcp_Config->drb->integrityProtection = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->integrityProtection)); + *DRB_config->pdcp_Config->drb->integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled; + } + + if (!rrc->security.do_drb_ciphering) { + DRB_config->pdcp_Config->ext1 = calloc(1, sizeof(*DRB_config->pdcp_Config->ext1)); + DRB_config->pdcp_Config->ext1->cipheringDisabled = calloc(1, sizeof(*DRB_config->pdcp_Config->ext1->cipheringDisabled)); + *DRB_config->pdcp_Config->ext1->cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true; + } + + // Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping + for (qos_flow_index = 0; qos_flow_index < ue_context_pP->ue_context.pduSession[i].param.nb_qos; qos_flow_index++) { + switch (ue_context_pP->ue_context.pduSession[i].param.qos[qos_flow_index].fiveQI) { + case 1: //100ms + case 2: //150ms + case 3: //50ms + case 4: //300ms + case 5: //100ms + case 6: //300ms + case 7: //100ms + case 8: //300ms + case 9: //300ms Video (Buffered Streaming)TCP-based (e.g., www, e-mail, chat, ftp, p2p file sharing, progressive video, etc.) + // TODO + break; + + default: + LOG_E(NR_RRC,"not supported 5qi %lu\n", ue_context_pP->ue_context.pduSession[i].param.qos[qos_flow_index].fiveQI); + ue_context_pP->ue_context.pduSession[i].status = PDU_SESSION_STATUS_FAILED; + ue_context_pP->ue_context.pduSession[i].xid = xid; + pdu_sessions_done++; + free(DRB_config); + continue; + } + } + + ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config); + ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); + + ue_context_pP->ue_context.pduSession[i].status = PDU_SESSION_STATUS_DONE; + ue_context_pP->ue_context.pduSession[i].xid = xid; + + if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { + dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); + memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedNAS_Message, + (char *)ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer, + ue_context_pP->ue_context.pduSession[i].param.nas_pdu.length); + ASN_SEQUENCE_ADD(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); + + LOG_I(NR_RRC,"add NAS info with size %d (pdusession id %d)\n",ue_context_pP->ue_context.pduSession[i].param.nas_pdu.length, i); + } else { + // TODO + LOG_E(NR_RRC,"no NAS info (pdusession id %d)\n", i); + } + } + + /* If list is empty free the list and reset the address */ + if (dedicatedNAS_MessageList->list.count == 0) { + free(dedicatedNAS_MessageList); + dedicatedNAS_MessageList = NULL; + } + + memset(buffer, 0, RRC_BUF_SIZE); + cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t)); + fill_mastercellGroupConfig(cellGroupConfig, ue_context_pP->ue_context.masterCellGroup); + size = do_RRCReconfiguration(ctxt_pP, buffer, + xid, + *SRB_configList2, + *DRB_configList, + NULL, + NULL, + NULL, + NULL, + dedicatedNAS_MessageList, + NULL, + cellGroupConfig); + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n"); + + /* Free all NAS PDUs */ + for (i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer); + ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer = NULL; + } + } + + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCReconfiguration (bytes %d, UE RNTI %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + LOG_D(NR_RRC, + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_gNB_mui, ctxt_pP->module_id, DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" dedicated RRCReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); + +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB_SIM, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + nr_rrc_data_req( + ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_dedicatedRRCReconfiguration_release( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid, + uint32_t nas_length, + uint8_t *nas_buffer) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[RRC_BUF_SIZE]; + int i; + uint16_t size = 0; + NR_DRB_ToReleaseList_t **DRB_Release_configList2 = NULL; + NR_DRB_Identity_t *DRB_release; + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList + *dedicatedNAS_MessageList = NULL; + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; + + DRB_Release_configList2 = &ue_context_pP->ue_context.DRB_Release_configList2[xid]; + if (*DRB_Release_configList2) { + free(*DRB_Release_configList2); + } + + *DRB_Release_configList2 = CALLOC(1, sizeof(**DRB_Release_configList2)); + for(i = 0; i < NB_RB_MAX; i++) { + if((ue_context_pP->ue_context.pduSession[i].status == PDU_SESSION_STATUS_TORELEASE) && ue_context_pP->ue_context.pduSession[i].xid == xid) { + DRB_release = CALLOC(1, sizeof(NR_DRB_Identity_t)); + *DRB_release = i+1; + ASN_SEQUENCE_ADD(&(*DRB_Release_configList2)->list, DRB_release); + } + } + + /* If list is empty free the list and reset the address */ + if (nas_length > 0) { + dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); + memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedNAS_Message, + (char *)nas_buffer, + nas_length); + ASN_SEQUENCE_ADD(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); + LOG_I(NR_RRC,"add NAS info with size %d\n", nas_length); + } else { + LOG_W(NR_RRC,"dedlicated NAS list is empty\n"); + } + + memset(buffer, 0, RRC_BUF_SIZE); + size = do_RRCReconfiguration(ctxt_pP, buffer, xid, + NULL, + NULL, + *DRB_Release_configList2, + NULL, + NULL, + NULL, + dedicatedNAS_MessageList, + NULL, + NULL); + + ue_context_pP->ue_context.pdu_session_release_command_flag = 1; + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, + "[MSG] RRC Reconfiguration\n"); + + /* Free all NAS PDUs */ + if (nas_length > 0) { + /* Free the NAS PDU buffer and invalidate it */ + free(nas_buffer); + } + + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE RNTI %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + LOG_D(NR_RRC, + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_gNB_mui, ctxt_pP->module_id, DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" dedicated NR_RRCReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + nr_rrc_data_req( + ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif +} + +//----------------------------------------------------------------------------- +/* +* Process the RRC Reconfiguration Complete from the UE +*/ +void +rrc_gNB_process_RRCReconfigurationComplete( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t xid +) +{ + int drb_id; + uint8_t *kRRCenc = NULL; + uint8_t *kRRCint = NULL; + uint8_t *kUPenc = NULL; + uint8_t *kUPint = NULL; + NR_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList2[xid]; + NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid]; + NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid]; + NR_DRB_Identity_t *drb_id_p = NULL; +// uint8_t nr_DRB2LCHAN[8]; + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + + ue_context_pP->ue_context.ue_reestablishment_timer = 0; + + /* Derive the keys from kgnb */ + if (DRB_configList != NULL) { + nr_derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm, + ue_context_pP->ue_context.kgnb, + &kUPenc); + nr_derive_key_up_int(ue_context_pP->ue_context.integrity_algorithm, + ue_context_pP->ue_context.kgnb, + &kUPint); + } + + nr_derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm, + ue_context_pP->ue_context.kgnb, + &kRRCenc); + nr_derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm, + ue_context_pP->ue_context.kgnb, + &kRRCint); + /* Refresh SRBs/DRBs */ + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, MSC_PDCP_ENB, NULL, 0, MSC_AS_TIME_FMT" CONFIG_REQ UE %x DRB (security unchanged)", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti); + +#ifndef ITTI_SIM + LOG_D(NR_RRC,"Configuring PDCP DRBs/SRBs for UE %x\n",ue_context_pP->ue_context.rnti); + + nr_rrc_pdcp_config_asn1_req(ctxt_pP, + SRB_configList, // NULL, + DRB_configList, + DRB_Release_configList2, + (ue_context_pP->ue_context.integrity_algorithm << 4) + | ue_context_pP->ue_context.ciphering_algorithm, + kRRCenc, + kRRCint, + kUPenc, + kUPint, + NULL, + NULL, + get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL); + /* Refresh SRBs/DRBs */ + + if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { + rrc_mac_config_req_gNB(rrc->module_id, + rrc->carrier.ssb_SubcarrierOffset, + rrc->carrier.pdsch_AntennaPorts, + rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, + NULL, + NULL, + 0, + ue_context_pP->ue_context.rnti, + ue_context_pP->ue_context.masterCellGroup + ); + LOG_D(NR_RRC,"Configuring RLC DRBs/SRBs for UE %x\n",ue_context_pP->ue_context.rnti); + nr_rrc_rlc_config_asn1_req(ctxt_pP, + SRB_configList, // NULL, + DRB_configList, + DRB_Release_configList2, + NULL, + get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL); + } +#endif + + /* Set the SRB active in UE context */ + if (SRB_configList != NULL) { + for (int i = 0; (i < SRB_configList->list.count) && (i < 3); i++) { + if (SRB_configList->list.array[i]->srb_Identity == 1) { + ue_context_pP->ue_context.Srb1.Active = 1; + ue_context_pP->ue_context.Srb1.Srb_info.Srb_id = 1; + } else if (SRB_configList->list.array[i]->srb_Identity == 2) { + ue_context_pP->ue_context.Srb2.Active = 1; + ue_context_pP->ue_context.Srb2.Srb_info.Srb_id = 2; + LOG_I(NR_RRC,"[gNB %d] Frame %d CC %d : SRB2 is now active\n", + ctxt_pP->module_id, + ctxt_pP->frame, + ue_context_pP->ue_context.primaryCC_id); + } else { + LOG_W(NR_RRC,"[gNB %d] Frame %d CC %d : invalide SRB identity %ld\n", + ctxt_pP->module_id, + ctxt_pP->frame, + ue_context_pP->ue_context.primaryCC_id, + SRB_configList->list.array[i]->srb_Identity); + } + } + + free(SRB_configList); + ue_context_pP->ue_context.SRB_configList2[xid] = NULL; + } + + /* Loop through DRBs and establish if necessary */ + if (DRB_configList != NULL) { + for (int i = 0; i < DRB_configList->list.count; i++) { + if (DRB_configList->list.array[i]) { + drb_id = (int)DRB_configList->list.array[i]->drb_Identity; + LOG_I(NR_RRC, "[gNB %d] Frame %d : Logical Channel UL-DCCH, Received NR_RRCReconfigurationComplete from UE rnti %x, reconfiguring DRB %d\n", + ctxt_pP->module_id, + ctxt_pP->frame, + ctxt_pP->rnti, + (int)DRB_configList->list.array[i]->drb_Identity); + //(int)*DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel); + + if (ue_context_pP->ue_context.DRB_active[drb_id] == 0) { + ue_context_pP->ue_context.DRB_active[drb_id] = 1; + LOG_D(NR_RRC, "[gNB %d] Frame %d: Establish RLC UM Bidirectional, DRB %d Active\n", + ctxt_pP->module_id, ctxt_pP->frame, (int)DRB_configList->list.array[i]->drb_Identity); + + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_gNB --- MAC_CONFIG_REQ (DRB) ---> MAC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + //if (DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel) { + // nr_DRB2LCHAN[i] = (uint8_t) * DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel; + //} + + // rrc_mac_config_req_eNB + } else { // remove LCHAN from MAC/PHY + if (ue_context_pP->ue_context.DRB_active[drb_id] == 1) { + /* TODO : It may be needed if gNB goes into full stack working. */ + // DRB has just been removed so remove RLC + PDCP for DRB + /* rrc_pdcp_config_req (ctxt_pP->module_id, frameP, 1, CONFIG_ACTION_REMOVE, + (ue_mod_idP * NB_RB_MAX) + DRB2LCHAN[i],UNDEF_SECURITY_MODE); + */ + /*rrc_rlc_config_req(ctxt_pP, + SRB_FLAG_NO, + MBMS_FLAG_NO, + CONFIG_ACTION_REMOVE, + nr_DRB2LCHAN[i], + Rlc_info_um);*/ + } + + ue_context_pP->ue_context.DRB_active[drb_id] = 0; + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ (DRB) ---> MAC_eNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + // rrc_mac_config_req_eNB + + } // end else of if (ue_context_pP->ue_context.DRB_active[drb_id] == 0) + } // end if (DRB_configList->list.array[i]) + } // end for (int i = 0; i < DRB_configList->list.count; i++) + + free(DRB_configList); + ue_context_pP->ue_context.DRB_configList2[xid] = NULL; + } // end if DRB_configList != NULL + + if(DRB_Release_configList2 != NULL) { + for (int i = 0; i < DRB_Release_configList2->list.count; i++) { + if (DRB_Release_configList2->list.array[i]) { + drb_id_p = DRB_Release_configList2->list.array[i]; + drb_id = *drb_id_p; + + if (ue_context_pP->ue_context.DRB_active[drb_id] == 1) { + ue_context_pP->ue_context.DRB_active[drb_id] = 0; + } + } + } + + free(DRB_Release_configList2); + ue_context_pP->ue_context.DRB_Release_configList2[xid] = NULL; + } +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_RRCReestablishment( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + const int CC_id) +//----------------------------------------------------------------------------- +{ + // int UE_id = -1; + //NR_LogicalChannelConfig_t *SRB1_logicalChannelConfig = NULL; + NR_SRB_ToAddModList_t **SRB_configList; + // NR_SRB_ToAddMod_t *SRB1_config = NULL; + //rrc_gNB_carrier_data_t *carrier = NULL; + gNB_RRC_UE_t *ue_context = NULL; + module_id_t module_id = ctxt_pP->module_id; + // uint16_t rnti = ctxt_pP->rnti; + + SRB_configList = &(ue_context_pP->ue_context.SRB_configList); + //carrier = &(RC.nrrrc[ctxt_pP->module_id]->carrier); + ue_context = &(ue_context_pP->ue_context); + ue_context->Srb0.Tx_buffer.payload_size = do_RRCReestablishment(ctxt_pP, + ue_context_pP, + CC_id, + (uint8_t *) ue_context->Srb0.Tx_buffer.Payload, + //(uint8_t) carrier->p_gNB, // at this point we do not have the UE capability information, so it can only be TM1 or TM2 + rrc_gNB_get_next_transaction_identifier(module_id), + SRB_configList + //&(ue_context->physicalConfigDedicated) + ); + + /* Configure SRB1 for UE */ + if (*SRB_configList != NULL) { + for (int cnt = 0; cnt < (*SRB_configList)->list.count; cnt++) { + if ((*SRB_configList)->list.array[cnt]->srb_Identity == 1) { + // SRB1_config = (*SRB_configList)->list.array[cnt]; + } + + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_gNB --- MAC_CONFIG_REQ (SRB1) ---> MAC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + // rrc_mac_config_req_eNB + } + } // if (*SRB_configList != NULL) + + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, + MSC_RRC_UE, + ue_context->Srb0.Tx_buffer.Header, + ue_context->Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" NR_RRCReestablishment UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context->rnti, + ue_context->Srb0.Tx_buffer.payload_size); + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context->Srb0.Tx_buffer.payload_size); +#if(0) + /* TODO : It may be needed if gNB goes into full stack working. */ + UE_id = find_nr_UE_id(module_id, rnti); + if (UE_id != -1) { + /* Activate reject timer, if RRCComplete not received after 10 frames, reject UE */ + RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1; + /* Reject UE after 10 frames, LTE_RRCConnectionReestablishmentReject is triggered */ + RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 100; + } else { + LOG_E(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Generating NR_RRCReestablishment without UE_id(MAC) rnti %x\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + rnti); + } +#endif +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, ue_context->Srb0.Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t *) ue_context->Srb0.Tx_buffer.Payload, ue_context->Srb0.Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = ue_context->Srb0.Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#endif + +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_process_RRCConnectionReestablishmentComplete( + const protocol_ctxt_t *const ctxt_pP, + const rnti_t reestablish_rnti, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t xid +) +//----------------------------------------------------------------------------- +{ + LOG_I(NR_RRC, + PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, processing NR_RRCConnectionReestablishmentComplete from UE (SRB1 Active)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + + NR_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList; + NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + NR_DRB_ToAddModList_t **DRB_configList2 = NULL; + NR_SRB_ToAddMod_t *SRB2_config = NULL; + NR_DRB_ToAddMod_t *DRB_config = NULL; + //NR_SDAP_Config_t *sdap_config = NULL; + int i = 0; + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + + uint8_t next_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + int ret = 0; + ue_context_pP->ue_context.StatusRrc = NR_RRC_CONNECTED; + ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED + ue_context_pP->ue_context.reestablishment_xid = next_xid; + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; + + // get old configuration of SRB2 + if (*SRB_configList2 != NULL) { + if((*SRB_configList2)->list.count!=0) { + LOG_D(NR_RRC, "SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p", + SRB_configList2, (*SRB_configList2)->list.count, (*SRB_configList2)->list.array[0]); + } + + for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { + if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ) { + LOG_D(NR_RRC, "get SRB2_config from (ue_context_pP->ue_context.SRB_configList2[%d])\n", xid); + SRB2_config = (*SRB_configList2)->list.array[i]; + break; + } + } + } + + // SRB2_config = CALLOC(1, sizeof(*SRB2_config)); + // SRB2_config->srb_Identity = 2; + + SRB_configList2 = &(ue_context_pP->ue_context.SRB_configList2[next_xid]); + DRB_configList2 = &(ue_context_pP->ue_context.DRB_configList2[next_xid]); + + if (*SRB_configList2) { + free(*SRB_configList2); + LOG_D(NR_RRC, "free(ue_context_pP->ue_context.SRB_configList2[%d])\n", next_xid); + } + + *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); + + if (SRB2_config != NULL) { + // Add SRB2 to SRB configuration list + ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList\n", + SRB2_config->srb_Identity); + LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList2[%d]\n", + SRB2_config->srb_Identity, next_xid); + } else { + // SRB configuration list only contains SRB1. + LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); + } + + if (*DRB_configList2) { + free(*DRB_configList2); + LOG_D(NR_RRC, "free(ue_context_pP->ue_context.DRB_configList2[%d])\n", next_xid); + } + + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + + if (DRB_configList != NULL) { + LOG_D(NR_RRC, "get DRB_config from (ue_context_pP->ue_context.DRB_configList)\n"); + + for (i = 0; (i < DRB_configList->list.count) && (i < 3); i++) { + DRB_config = DRB_configList->list.array[i]; + // Add DRB to DRB configuration list, for LTE_RRCConnectionReconfigurationComplete + ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); + } + } + + ue_context_pP->ue_context.Srb1.Active = 1; + //ue_context_pP->ue_context.Srb2.Srb_info.Srb_id = 2; + + if (AMF_MODE_ENABLED) { + hashtable_rc_t h_rc; + int j; + rrc_ue_ngap_ids_t *rrc_ue_ngap_ids_p = NULL; + uint16_t ue_initial_id = ue_context_pP->ue_context.ue_initial_id; + uint32_t gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + gNB_RRC_INST *rrc_instance_p = RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)]; + + if (gNB_ue_ngap_id > 0) { + h_rc = hashtable_get(rrc_instance_p->ngap_id2_ngap_ids, (hash_key_t)gNB_ue_ngap_id, (void **)&rrc_ue_ngap_ids_p); + + if (h_rc == HASH_TABLE_OK) { + rrc_ue_ngap_ids_p->ue_rnti = ctxt_pP->rnti; + } + } + + if (ue_initial_id != 0) { + h_rc = hashtable_get(rrc_instance_p->initial_id2_ngap_ids, (hash_key_t)ue_initial_id, (void **)&rrc_ue_ngap_ids_p); + + if (h_rc == HASH_TABLE_OK) { + rrc_ue_ngap_ids_p->ue_rnti = ctxt_pP->rnti; + } + } + + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req; + /* Save e RAB information for later */ + memset(&create_tunnel_req, 0, sizeof(create_tunnel_req)); + + for ( j = 0, i = 0; i < NB_RB_MAX; i++) { + if (ue_context_pP->ue_context.pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED || ue_context_pP->ue_context.pduSession[i].status == PDU_SESSION_STATUS_DONE) { + create_tunnel_req.pdusession_id[j] = ue_context_pP->ue_context.pduSession[i].param.pdusession_id; + create_tunnel_req.incoming_rb_id[j] = i+1; + create_tunnel_req.upf_NGu_teid[j] = ue_context_pP->ue_context.pduSession[i].param.gtp_teid; + memcpy(create_tunnel_req.upf_addr[j].buffer, + ue_context_pP->ue_context.pduSession[i].param.upf_addr.buffer, + sizeof(uint8_t)*20); + create_tunnel_req.upf_addr[j].length = ue_context_pP->ue_context.pduSession[i].param.upf_addr.length; + j++; + } + } + + create_tunnel_req.rnti = ctxt_pP->rnti; // warning put zero above + create_tunnel_req.num_tunnels = j; + ret = gtpv1u_update_ngu_tunnel( + ctxt_pP->instance, + &create_tunnel_req, + reestablish_rnti); + + if ( ret != 0 ) { + LOG_E(NR_RRC,"gtpv1u_update_ngu_tunnel failed,start to release UE %x\n",reestablish_rnti); + + // update s1u tunnel failed,reset rnti? + if (gNB_ue_ngap_id > 0) { + h_rc = hashtable_get(rrc_instance_p->ngap_id2_ngap_ids, (hash_key_t)gNB_ue_ngap_id, (void **)&rrc_ue_ngap_ids_p); + + if (h_rc == HASH_TABLE_OK ) { + rrc_ue_ngap_ids_p->ue_rnti = reestablish_rnti; + } + } + + if (ue_initial_id != 0) { + h_rc = hashtable_get(rrc_instance_p->initial_id2_ngap_ids, (hash_key_t)ue_initial_id, (void **)&rrc_ue_ngap_ids_p); + + if (h_rc == HASH_TABLE_OK ) { + rrc_ue_ngap_ids_p->ue_rnti = reestablish_rnti; + } + } + + ue_context_pP->ue_context.ue_release_timer_s1 = 1; + ue_context_pP->ue_context.ue_release_timer_thres_s1 = 100; + ue_context_pP->ue_context.ue_release_timer = 0; + ue_context_pP->ue_context.ue_reestablishment_timer = 0; + ue_context_pP->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ + ue_context_pP->ue_context.ul_failure_timer = 0; + return; + } + } /* AMF_MODE_ENABLED */ + + /* Update RNTI in ue_context */ + ue_context_pP->ue_id_rnti = ctxt_pP->rnti; // here ue_id_rnti is just a key, may be something else + ue_context_pP->ue_context.rnti = ctxt_pP->rnti; + + if (AMF_MODE_ENABLED) { + uint8_t send_security_mode_command = FALSE; + nr_rrc_pdcp_config_security( + ctxt_pP, + ue_context_pP, + send_security_mode_command ? 0 : 1); + LOG_D(NR_RRC, "set security successfully \n"); + } + + /* Add all NAS PDUs to the list */ + for (i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + + /* TODO parameters yet to process ... */ + /* TODO should test if pdu session are Ok before! */ + ue_context_pP->ue_context.pduSession[i].status = PDU_SESSION_STATUS_DONE; + ue_context_pP->ue_context.pduSession[i].xid = xid; + LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", + i, ue_context_pP->ue_context.pduSession[i].status, "PDU_SESSION_STATUS_DONE"); + } + + memset(buffer, 0, RRC_BUF_SIZE); + + size = do_RRCReconfiguration(ctxt_pP, buffer, + xid, + *SRB_configList2, + DRB_configList, + NULL, + NULL, + NULL, + NULL, // MeasObj_list, + NULL, + NULL, + NULL); + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, + "[MSG] RRC Reconfiguration\n"); + + /* Free all NAS PDUs */ + for (i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer); + ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer = NULL; + } + } + + if(size==65535) { + LOG_E(NR_RRC,"RRC decode err!!! do_RRCReconfiguration\n"); + return; + } else { + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCConnectionReconfiguration (bytes %d, UE id %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + LOG_D(NR_RRC, + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_gNB_mui, ctxt_pP->module_id, DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" LTE_RRCConnectionReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + nr_rrc_data_req( + ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif + } +} +//----------------------------------------------------------------------------- + +/*------------------------------------------------------------------------------*/ +int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, + const uint8_t *buffer, + int buffer_length, + OCTET_STRING_t *du_to_cu_rrc_container, + const int CC_id) +{ + module_id_t Idx; + asn_dec_rval_t dec_rval; + NR_UL_CCCH_Message_t *ul_ccch_msg = NULL; + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + gNB_RRC_INST *gnb_rrc_inst = RC.nrrrc[ctxt_pP->module_id]; + NR_RRCSetupRequest_IEs_t *rrcSetupRequest = NULL; + NR_RRCReestablishmentRequest_IEs_t rrcReestablishmentRequest; + uint64_t random_value = 0; + int i; + + dec_rval = uper_decode( NULL, + &asn_DEF_NR_UL_CCCH_Message, + (void **)&ul_ccch_msg, + (uint8_t *) buffer, + 100, + 0, + 0); + + if (dec_rval.consumed == 0) { + /* TODO */ + LOG_E(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" FATAL Error in receiving CCCH\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + return -1; + } + + if (ul_ccch_msg->message.present == NR_UL_CCCH_MessageType_PR_c1) { + switch (ul_ccch_msg->message.choice.c1->present) { + case NR_UL_CCCH_MessageType__c1_PR_NOTHING: + /* TODO */ + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_FMT" Received PR_NOTHING on UL-CCCH-Message\n", + PROTOCOL_NR_RRC_CTXT_ARGS(ctxt_pP)); + break; + + case NR_UL_CCCH_MessageType__c1_PR_rrcSetupRequest: + LOG_D(NR_RRC, "Received RRCSetupRequest on UL-CCCH-Message (UE rnti %x)\n", ctxt_pP->rnti); + ue_context_p = rrc_gNB_get_ue_context(gnb_rrc_inst, ctxt_pP->rnti); + if (ue_context_p != NULL) { + rrc_gNB_free_mem_UE_context(ctxt_pP, ue_context_p); + MSC_LOG_RX_DISCARDED_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + dec_rval.consumed, + MSC_AS_TIME_FMT" NR_RRCSetupRequest UE %x size %u (UE already in context)", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + dec_rval.consumed); + } else { + rrcSetupRequest = &ul_ccch_msg->message.choice.c1->choice.rrcSetupRequest->rrcSetupRequest; + if (NR_InitialUE_Identity_PR_randomValue == rrcSetupRequest->ue_Identity.present) { + /* randomValue BIT STRING (SIZE (39)) */ + if (rrcSetupRequest->ue_Identity.choice.randomValue.size != 5) { // 39-bit random value + LOG_E(NR_RRC, "wrong InitialUE-Identity randomValue size, expected 5, provided %lu", + (long unsigned int)rrcSetupRequest->ue_Identity.choice.randomValue.size); + return -1; + } + + memcpy(((uint8_t *) & random_value) + 3, + rrcSetupRequest->ue_Identity.choice.randomValue.buf, + rrcSetupRequest->ue_Identity.choice.randomValue.size); + + /* if there is already a registered UE (with another RNTI) with this random_value, + * the current one must be removed from MAC/PHY (zombie UE) + */ + if ((ue_context_p = rrc_gNB_ue_context_random_exist(RC.nrrrc[ctxt_pP->module_id], random_value))) { + LOG_W(NR_RRC, "new UE rnti %x (coming with random value) is already there as UE %x, removing %x from MAC/PHY\n", + ctxt_pP->rnti, ue_context_p->ue_context.rnti, ue_context_p->ue_context.rnti); + ue_context_p->ue_context.ul_failure_timer = 20000; + } + + ue_context_p = rrc_gNB_get_next_free_ue_context(ctxt_pP, RC.nrrrc[ctxt_pP->module_id], random_value); + ue_context_p->ue_context.Srb0.Srb_id = 0; + ue_context_p->ue_context.Srb0.Active = 1; + memcpy(ue_context_p->ue_context.Srb0.Rx_buffer.Payload, + buffer, + buffer_length); + ue_context_p->ue_context.Srb0.Rx_buffer.payload_size = buffer_length; + } else if (NR_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1 == rrcSetupRequest->ue_Identity.present) { + /* TODO */ + /* <5G-S-TMSI> = <5G-TMSI> 48-bit */ + /* ng-5G-S-TMSI-Part1 BIT STRING (SIZE (39)) */ + if (rrcSetupRequest->ue_Identity.choice.ng_5G_S_TMSI_Part1.size != 5) { + LOG_E(NR_RRC, "wrong ng_5G_S_TMSI_Part1 size, expected 5, provided %lu \n", + (long unsigned int)rrcSetupRequest->ue_Identity.choice.ng_5G_S_TMSI_Part1.size); + return -1; + } + + uint64_t s_tmsi_part1 = bitStr_to_uint64(&rrcSetupRequest->ue_Identity.choice.ng_5G_S_TMSI_Part1); + + // memcpy(((uint8_t *) & random_value) + 3, + // rrcSetupRequest->ue_Identity.choice.ng_5G_S_TMSI_Part1.buf, + // rrcSetupRequest->ue_Identity.choice.ng_5G_S_TMSI_Part1.size); + + if ((ue_context_p = rrc_gNB_ue_context_5g_s_tmsi_exist(RC.nrrrc[ctxt_pP->module_id], s_tmsi_part1))) { + LOG_I(NR_RRC, " 5G-S-TMSI-Part1 exists, ue_context_p %p, old rnti %x => %x\n",ue_context_p, ue_context_p->ue_context.rnti, ctxt_pP->rnti); + + nr_rrc_mac_remove_ue(ctxt_pP->module_id, ue_context_p->ue_context.rnti); + + /* replace rnti in the context */ + /* for that, remove the context from the RB tree */ + RB_REMOVE(rrc_nr_ue_tree_s, &RC.nrrrc[ctxt_pP->module_id]->rrc_ue_head, ue_context_p); + /* and insert again, after changing rnti everywhere it has to be changed */ + ue_context_p->ue_id_rnti = ctxt_pP->rnti; + ue_context_p->ue_context.rnti = ctxt_pP->rnti; + RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[ctxt_pP->module_id]->rrc_ue_head, ue_context_p); + /* reset timers */ + ue_context_p->ue_context.ul_failure_timer = 0; + ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 0; + ue_context_p->ue_context.ue_release_timer_s1 = 0; + ue_context_p->ue_context.ue_release_timer_rrc = 0; + } else { + LOG_I(NR_RRC, " 5G-S-TMSI-Part1 doesn't exist, setting ng_5G_S_TMSI_Part1 to %p => %ld\n", + ue_context_p, s_tmsi_part1); + + ue_context_p = rrc_gNB_get_next_free_ue_context(ctxt_pP, RC.nrrrc[ctxt_pP->module_id], s_tmsi_part1); + + if (ue_context_p == NULL) { + LOG_E(RRC, "%s:%d:%s: rrc_gNB_get_next_free_ue_context returned NULL\n", __FILE__, __LINE__, __FUNCTION__); + } + + if (ue_context_p != NULL) { + ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence = TRUE; + ue_context_p->ue_context.ng_5G_S_TMSI_Part1 = s_tmsi_part1; + } + } + } else { + /* TODO */ + memcpy(((uint8_t *) & random_value) + 3, + rrcSetupRequest->ue_Identity.choice.randomValue.buf, + rrcSetupRequest->ue_Identity.choice.randomValue.size); + + rrc_gNB_get_next_free_ue_context(ctxt_pP, RC.nrrrc[ctxt_pP->module_id], random_value); + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRCSetupRequest without random UE identity or S-TMSI not supported, let's reject the UE\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_gNB_generate_RRCReject(ctxt_pP, + rrc_gNB_get_ue_context(gnb_rrc_inst, ctxt_pP->rnti), + CC_id); + break; + } + + ue_context_p->ue_context.establishment_cause = rrcSetupRequest->establishmentCause; + + rrc_gNB_generate_RRCSetup(ctxt_pP, + rrc_gNB_get_ue_context(gnb_rrc_inst, ctxt_pP->rnti), + du_to_cu_rrc_container, + gnb_rrc_inst->carrier.servingcellconfigcommon, + CC_id); + } + break; + + case NR_UL_CCCH_MessageType__c1_PR_rrcResumeRequest: + LOG_I(NR_RRC, "receive rrcResumeRequest message \n"); + break; + + case NR_UL_CCCH_MessageType__c1_PR_rrcReestablishmentRequest: + LOG_I(NR_RRC, "receive rrcReestablishmentRequest message \n"); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)(buffer), buffer_length, + "[MSG] RRC Reestablishment Request\n"); + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT"MAC_gNB--- MAC_DATA_IND (rrcReestablishmentRequest on SRB0) --> RRC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + rrcReestablishmentRequest = ul_ccch_msg->message.choice.c1->choice.rrcReestablishmentRequest->rrcReestablishmentRequest; + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest cause %s\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ((rrcReestablishmentRequest.reestablishmentCause == NR_ReestablishmentCause_otherFailure) ? "Other Failure" : + (rrcReestablishmentRequest.reestablishmentCause == NR_ReestablishmentCause_handoverFailure) ? "Handover Failure" : + "reconfigurationFailure")); + { + uint16_t c_rnti = 0; + if (rrcReestablishmentRequest.ue_Identity.physCellId != RC.nrrrc[ctxt_pP->module_id]->carrier.physCellId) { + /* UE was moving from previous cell so quickly that RRCReestablishment for previous cell was recieved in this cell */ + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest ue_Identity.physCellId(%ld) is not equal to current physCellId(%d), fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + rrcReestablishmentRequest.ue_Identity.physCellId, + RC.nrrrc[ctxt_pP->module_id]->carrier.physCellId); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } + + LOG_D(NR_RRC, "physCellId is %ld\n", rrcReestablishmentRequest.ue_Identity.physCellId); + + for (i = 0; i < rrcReestablishmentRequest.ue_Identity.shortMAC_I.size; i++) { + LOG_D(NR_RRC, "rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[%d] = %x\n", + i, rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[i]); + } + + if (rrcReestablishmentRequest.ue_Identity.c_RNTI < 0 || + rrcReestablishmentRequest.ue_Identity.c_RNTI > 65535) { + /* c_RNTI range error should not happen */ + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest c_RNTI range error, fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } + + c_rnti = rrcReestablishmentRequest.ue_Identity.c_RNTI; + LOG_I(NR_RRC, "c_rnti is %x\n", c_rnti); + ue_context_p = rrc_gNB_get_ue_context(gnb_rrc_inst, c_rnti); + + if (ue_context_p == NULL) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest without UE context, fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } +#if(0) + /* TODO : It may be needed if gNB goes into full stack working. */ + int UE_id = find_nr_UE_id(ctxt_pP->module_id, c_rnti); + + if(UE_id == -1) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest without UE_id(MAC) rnti %x, fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),c_rnti); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } + + //previous rnti + rnti_t previous_rnti = 0; + + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { + if (reestablish_rnti_map[i][1] == c_rnti) { + previous_rnti = reestablish_rnti_map[i][0]; + break; + } + } + + if(previous_rnti != 0) { + UE_id = find_nr_UE_id(ctxt_pP->module_id, previous_rnti); + + if(UE_id == -1) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRCReestablishmentRequest without UE_id(MAC) previous rnti %x, fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),previous_rnti); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } + } +#endif + //c-plane not end + if((ue_context_p->ue_context.StatusRrc != NR_RRC_RECONFIGURED) && (ue_context_p->ue_context.reestablishment_cause == NR_ReestablishmentCause_spare1)) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest (UE %x c-plane is not end), RRC establishment failed \n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),c_rnti); + /* TODO RRC Release ? */ + break; + } + + if(ue_context_p->ue_context.ue_reestablishment_timer > 0) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRRCReconfigurationComplete(Previous) don't receive, delete the Previous UE,\nprevious Status %d, new Status NR_RRC_RECONFIGURED\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context_p->ue_context.StatusRrc + ); + ue_context_p->ue_context.StatusRrc = NR_RRC_RECONFIGURED; + protocol_ctxt_t ctxt_old_p; + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt_old_p, + ctxt_pP->instance, + GNB_FLAG_YES, + c_rnti, + ctxt_pP->frame, + ctxt_pP->subframe); + rrc_gNB_process_RRCReconfigurationComplete(&ctxt_old_p, + ue_context_p, + ue_context_p->ue_context.reestablishment_xid); + + for (uint8_t pdusessionid = 0; pdusessionid < ue_context_p->ue_context.nb_of_pdusessions; pdusessionid++) { + if (ue_context_p->ue_context.pduSession[pdusessionid].status == PDU_SESSION_STATUS_DONE) { + ue_context_p->ue_context.pduSession[pdusessionid].status = PDU_SESSION_STATUS_ESTABLISHED; + } else { + ue_context_p->ue_context.pduSession[pdusessionid].status = PDU_SESSION_STATUS_FAILED; + } + } + } + + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" UE context: %p\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context_p); + /* reset timers */ + ue_context_p->ue_context.ul_failure_timer = 0; + ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 0; + // ue_context_p->ue_context.ue_release_timer_s1 = 0; + ue_context_p->ue_context.ue_release_timer_rrc = 0; + ue_context_p->ue_context.reestablishment_xid = -1; + + // insert C-RNTI to map + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { + if (reestablish_rnti_map[i][0] == 0) { + reestablish_rnti_map[i][0] = ctxt_pP->rnti; + reestablish_rnti_map[i][1] = c_rnti; + LOG_D(NR_RRC, "reestablish_rnti_map[%d] [0] %x, [1] %x\n", + i, reestablish_rnti_map[i][0], reestablish_rnti_map[i][1]); + break; + } + } + + ue_context_p->ue_context.reestablishment_cause = rrcReestablishmentRequest.reestablishmentCause; + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Accept reestablishment request from UE physCellId %ld cause %ld\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + rrcReestablishmentRequest.ue_Identity.physCellId, + ue_context_p->ue_context.reestablishment_cause); + + ue_context_p->ue_context.primaryCC_id = CC_id; + //LG COMMENT Idx = (ue_mod_idP * NB_RB_MAX) + DCCH; + Idx = DCCH; + // SRB1 + ue_context_p->ue_context.Srb1.Active = 1; + ue_context_p->ue_context.Srb1.Srb_info.Srb_id = Idx; + memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + // SRB2: set it to go through SRB1 with id 1 (DCCH) + ue_context_p->ue_context.Srb2.Active = 1; + ue_context_p->ue_context.Srb2.Srb_info.Srb_id = Idx; + memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + + rrc_gNB_generate_RRCReestablishment(ctxt_pP, ue_context_p, CC_id); + + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT"CALLING RLC CONFIG SRB1 (rbid %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + Idx); + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, + MSC_PDCP_GNB, + NULL, + 0, + MSC_AS_TIME_FMT" CONFIG_REQ UE %x SRB", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti); + // nr_rrc_pdcp_config_asn1_req(ctxt_pP, + // ue_context_p->ue_context.SRB_configList, + // NULL, + // NULL, + // 0xff, + // NULL, + // NULL, + // NULL, + // NULL, + // NULL, + // NULL, + // NULL); + + // if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { + // nr_rrc_rlc_config_asn1_req(ctxt_pP, + // ue_context_p->ue_context.SRB_configList, + // NULL, + // NULL, + // NULL, + // NULL); + // } + } + break; + + case NR_UL_CCCH_MessageType__c1_PR_rrcSystemInfoRequest: + LOG_I(NR_RRC, "receive rrcSystemInfoRequest message \n"); + /* TODO */ + break; + + default: + LOG_E(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Unknown message\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + break; + } + } + return 0; +} + +/*! \fn uint64_t bitStr_to_uint64(BIT_STRING_t *) + *\brief This function extract at most a 64 bits value from a BIT_STRING_t object, the exact bits number depend on the BIT_STRING_t contents. + *\param[in] pointer to the BIT_STRING_t object. + *\return the extracted value. + */ +static inline uint64_t bitStr_to_uint64(BIT_STRING_t *asn) { + uint64_t result = 0; + int index; + int shift; + + DevCheck ((asn->size > 0) && (asn->size <= 8), asn->size, 0, 0); + + shift = ((asn->size - 1) * 8) - asn->bits_unused; + for (index = 0; index < (asn->size - 1); index++) { + result |= (uint64_t)asn->buf[index] << shift; + shift -= 8; + } + + result |= asn->buf[index] >> asn->bits_unused; + + return result; +} + +//----------------------------------------------------------------------------- +int +rrc_gNB_decode_dcch( + const protocol_ctxt_t *const ctxt_pP, + const rb_id_t Srb_id, + const uint8_t *const Rx_sdu, + const sdu_size_t sdu_sizeP +) +//----------------------------------------------------------------------------- +{ + asn_dec_rval_t dec_rval; + NR_UL_DCCH_Message_t *ul_dcch_msg = NULL; + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + MessageDef *msg_delete_tunnels_p = NULL; + uint8_t xid; + + int i; + + if ((Srb_id != 1) && (Srb_id != 2)) { + LOG_E(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Received message on SRB%ld, should not have ...\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + Srb_id); + } else { + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Received message on SRB%ld\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + Srb_id); + } + + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Decoding UL-DCCH Message\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + //for (int i=0;imodule_id], + ctxt_pP->rnti); + + if (ul_dcch_msg->message.present == NR_UL_DCCH_MessageType_PR_c1) { + switch (ul_dcch_msg->message.choice.c1->present) { + case NR_UL_DCCH_MessageType__c1_PR_NOTHING: + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_FMT" Received PR_NOTHING on UL-DCCH-Message\n", + PROTOCOL_NR_RRC_CTXT_ARGS(ctxt_pP)); + break; + + case NR_UL_DCCH_MessageType__c1_PR_rrcReconfigurationComplete: + LOG_I(NR_RRC, "Receive RRC Reconfiguration Complete message UE %x\n", ctxt_pP->rnti); + if(!ue_context_p) { + LOG_E(NR_RRC, "Processing NR_RRCReconfigurationComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti); + break; + } + + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)(Rx_sdu), sdu_sizeP, + "[MSG] RRC Connection Reconfiguration Complete\n"); + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" NR_RRCReconfigurationComplete UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + sdu_sizeP); + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(RRCReconfigurationComplete) ---> RRC_gNB]\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); + + if (ul_dcch_msg->message.choice.c1->present == NR_UL_DCCH_MessageType__c1_PR_rrcReconfigurationComplete) { + if (ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->criticalExtensions.present == + NR_RRCReconfigurationComplete__criticalExtensions_PR_rrcReconfigurationComplete) + rrc_gNB_process_RRCReconfigurationComplete( + ctxt_pP, + ue_context_p, + ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier); + } + + if (AMF_MODE_ENABLED) { + if(ue_context_p->ue_context.pdu_session_release_command_flag == 1) { + xid = ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier; + ue_context_p->ue_context.pdu_session_release_command_flag = 0; + //gtp tunnel delete + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_GNB, 0, GTPV1U_GNB_DELETE_TUNNEL_REQ); + memset(>PV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + + for(i = 0; i < NB_RB_MAX; i++) { + if(xid == ue_context_p->ue_context.pduSession[i].xid) { + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).pdusession_id[GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_pdusession++] = + ue_context_p->ue_context.gnb_gtp_psi[i]; + ue_context_p->ue_context.gnb_gtp_teid[i] = 0; + memset(&ue_context_p->ue_context.gnb_gtp_addrs[i], 0, sizeof(ue_context_p->ue_context.gnb_gtp_addrs[i])); + ue_context_p->ue_context.gnb_gtp_psi[i] = 0; + } + } + + itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->instance, msg_delete_tunnels_p); + //NGAP_PDUSESSION_RELEASE_RESPONSE + rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(ctxt_pP, ue_context_p, xid); + } else if (ue_context_p->ue_context.established_pdu_sessions_flag != 1) { + if (ue_context_p->ue_context.setup_pdu_sessions > 0) { + rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(ctxt_pP, + ue_context_p, + ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier); + } + } + } + if (first_rrcreconfiguration == 0){ + first_rrcreconfiguration = 1; + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + } + + break; + + case NR_UL_DCCH_MessageType__c1_PR_rrcSetupComplete: + if(!ue_context_p) { + LOG_I(NR_RRC, "Processing NR_RRCSetupComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti); + break; + } + + LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, + "[MSG] RRC SetupComplete\n"); + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" NR_RRCSetupComplete UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + sdu_sizeP); + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(RRCSetupComplete) ---> RRC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); + + if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.present == + NR_RRCSetupComplete__criticalExtensions_PR_rrcSetupComplete) { + if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice. + rrcSetupComplete->ng_5G_S_TMSI_Value != NULL) { + if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice. + rrcSetupComplete->ng_5G_S_TMSI_Value->present == NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI_Part2) { + // ng-5G-S-TMSI-Part2 BIT STRING (SIZE (9)) + if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice. + rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2.size != 2) { + LOG_E(NR_RRC, "wrong ng_5G_S_TMSI_Part2 size, expected 2, provided %lu", + (long unsigned int)ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete-> + criticalExtensions.choice.rrcSetupComplete-> + ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2.size); + return -1; + } + + if (ue_context_p->ue_context.ng_5G_S_TMSI_Part1 != 0) { + ue_context_p->ue_context.ng_5G_S_TMSI_Part2 = + BIT_STRING_to_uint16(&ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete-> + criticalExtensions.choice.rrcSetupComplete-> + ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2); + } + + /* TODO */ + } else if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice. + rrcSetupComplete->ng_5G_S_TMSI_Value->present == NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI) { + // NG-5G-S-TMSI ::= BIT STRING (SIZE (48)) + if (ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice. + rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size != 6) { + LOG_E(NR_RRC, "wrong ng_5G_S_TMSI size, expected 6, provided %lu", + (long unsigned int)ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete-> + criticalExtensions.choice.rrcSetupComplete-> + ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size); + return -1; + } + + uint64_t fiveg_s_TMSI = bitStr_to_uint64(&ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete-> + criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI); + LOG_I(NR_RRC, "Received rrcSetupComplete, 5g_s_TMSI: 0x%lX, amf_set_id: 0x%lX(%ld), amf_pointer: 0x%lX(%ld), 5g TMSI: 0x%X \n", + fiveg_s_TMSI, fiveg_s_TMSI >> 38, fiveg_s_TMSI >> 38, + (fiveg_s_TMSI >> 32) & 0x3F, (fiveg_s_TMSI >> 32) & 0x3F, + (uint32_t)fiveg_s_TMSI); + if (ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence == TRUE) { + ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.amf_set_id = fiveg_s_TMSI >> 38; + ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.amf_pointer = (fiveg_s_TMSI >> 32) & 0x3F; + ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.fiveg_tmsi = (uint32_t)fiveg_s_TMSI; + } + } + } + + rrc_gNB_process_RRCSetupComplete( + ctxt_pP, + ue_context_p, + ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.rrcSetupComplete); + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" UE State = NR_RRC_CONNECTED \n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + } + + ue_context_p->ue_context.ue_release_timer = 0; + break; + + case NR_UL_DCCH_MessageType__c1_PR_ulInformationTransfer: + LOG_I(NR_RRC,"Recived RRC GNB UL Information Transfer \n"); + if(!ue_context_p) { + LOG_I(NR_RRC, "Processing ulInformationTransfer UE %x, ue_context_p is NULL\n", ctxt_pP->rnti); + break; + } + + LOG_D(NR_RRC,"[MSG] RRC UL Information Transfer \n"); + LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, + "[MSG] RRC UL Information Transfer \n"); + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" ulInformationTransfer UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + sdu_sizeP); + + if (AMF_MODE_ENABLED == 1) { + rrc_gNB_send_NGAP_UPLINK_NAS(ctxt_pP, + ue_context_p, + ul_dcch_msg); + } + break; + + case NR_UL_DCCH_MessageType__c1_PR_securityModeComplete: + // to avoid segmentation fault + if(!ue_context_p) { + LOG_I(NR_RRC, "Processing securityModeComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti); + break; + } + + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" received securityModeComplete on UL-DCCH %d from UE\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH); + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(securityModeComplete) ---> RRC_eNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg); + } + + /* configure ciphering */ + nr_rrc_pdcp_config_security(ctxt_pP, ue_context_p, 1); + + rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); + //rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); + break; + case NR_UL_DCCH_MessageType__c1_PR_securityModeFailure: + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, + "[MSG] NR RRC Security Mode Failure\n"); + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" securityModeFailure UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + sdu_sizeP); + LOG_W(NR_RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(securityModeFailure) ---> RRC_gNB\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg); + } + + rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); + break; + + case NR_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation: + if(!ue_context_p) { + LOG_I(NR_RRC, "Processing ueCapabilityInformation UE %x, ue_context_p is NULL\n", ctxt_pP->rnti); + break; + } + + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, + "[MSG] NR_RRC UECapablility Information\n"); + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" ueCapabilityInformation UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + sdu_sizeP); + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" received ueCapabilityInformation on UL-DCCH %d from UE\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH); + LOG_D(RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(UECapabilityInformation) ---> RRC_eNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)ul_dcch_msg); + } + LOG_I(NR_RRC, "got UE capabilities for UE %x\n", ctxt_pP->rnti); + int eutra_index = -1; + + if( ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.present == + NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation ) { + for(i = 0;i < ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.count; i++){ + if(ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == + NR_RAT_Type_nr){ + if(ue_context_p->ue_context.UE_Capability_nr){ + ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability,ue_context_p->ue_context.UE_Capability_nr); + ue_context_p->ue_context.UE_Capability_nr = 0; + } + + dec_rval = uper_decode(NULL, + &asn_DEF_NR_UE_NR_Capability, + (void**)&ue_context_p->ue_context.UE_Capability_nr, + ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.buf, + ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size, + 0,0); + if(LOG_DEBUGFLAG(DEBUG_ASN1)){ + xer_fprint(stdout,&asn_DEF_NR_UE_NR_Capability,ue_context_p->ue_context.UE_Capability_nr); + } + + if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)){ + LOG_E(NR_RRC,PROTOCOL_NR_RRC_CTXT_UE_FMT" Failed to decode nr UE capabilities (%zu bytes)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),dec_rval.consumed); + ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability,ue_context_p->ue_context.UE_Capability_nr); + ue_context_p->ue_context.UE_Capability_nr = 0; + } + + ue_context_p->ue_context.UE_Capability_size = + ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size; + if(eutra_index != -1){ + LOG_E(NR_RRC,"fatal: more than 1 eutra capability\n"); + exit(1); + } + eutra_index = i; + } + + if(ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == + NR_RAT_Type_eutra_nr){ + if(ue_context_p->ue_context.UE_Capability_MRDC){ + ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability,ue_context_p->ue_context.UE_Capability_MRDC); + ue_context_p->ue_context.UE_Capability_MRDC = 0; + } + dec_rval = uper_decode(NULL, + &asn_DEF_NR_UE_MRDC_Capability, + (void**)&ue_context_p->ue_context.UE_Capability_MRDC, + ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.buf, + ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size, + 0,0); + + if(LOG_DEBUGFLAG(DEBUG_ASN1)){ + xer_fprint(stdout,&asn_DEF_NR_UE_MRDC_Capability,ue_context_p->ue_context.UE_Capability_MRDC); + } + + if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)){ + LOG_E(NR_RRC,PROTOCOL_NR_RRC_CTXT_FMT" Failed to decode nr UE capabilities (%zu bytes)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),dec_rval.consumed); + ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability,ue_context_p->ue_context.UE_Capability_MRDC); + ue_context_p->ue_context.UE_Capability_MRDC = 0; + } + ue_context_p->ue_context.UE_MRDC_Capability_size = + ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size; + } + + if(ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == + NR_RAT_Type_eutra){ + //TODO + } + } + + if(eutra_index == -1) + break; + } + if (AMF_MODE_ENABLED == 1) { + rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(ctxt_pP, + ue_context_p, + ul_dcch_msg); + } + + if (ue_context_p->ue_context.established_pdu_sessions_flag == 1) { + rrc_gNB_generate_dedicatedRRCReconfiguration(ctxt_pP, ue_context_p); + } else { + rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); + } + + break; + + case NR_UL_DCCH_MessageType__c1_PR_rrcReestablishmentComplete: + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, + "[MSG] NR_RRC Connection Reestablishment Complete\n"); + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" NR_RRCConnectionReestablishmentComplete UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + sdu_sizeP); + LOG_I(NR_RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(rrcConnectionReestablishmentComplete) ---> RRC_gNB\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); + { + rnti_t reestablish_rnti = 0; + + // select C-RNTI from map + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { + if (reestablish_rnti_map[i][0] == ctxt_pP->rnti) { + reestablish_rnti = reestablish_rnti_map[i][1]; + ue_context_p = rrc_gNB_get_ue_context( + RC.nrrrc[ctxt_pP->module_id], + reestablish_rnti); + // clear currentC-RNTI from map + reestablish_rnti_map[i][0] = 0; + reestablish_rnti_map[i][1] = 0; + LOG_D(NR_RRC, "reestablish_rnti_map[%d] [0] %x, [1] %x\n", + i, reestablish_rnti_map[i][0], reestablish_rnti_map[i][1]); + break; + } + } + + if (!ue_context_p) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCConnectionReestablishmentComplete without UE context, falt\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + break; + } + +#if(0) + /* TODO : It may be needed if gNB goes into full stack working. */ + //clear + int UE_id = find_nr_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); + + if(UE_id == -1) { + LOG_E(NR_RRC, + PROTOCOL_RRC_CTXT_UE_FMT" NR_RRCConnectionReestablishmentComplete without UE_id(MAC) rnti %x, fault\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ctxt_pP->rnti); + break; + } + + RC.nrmac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; +#endif + ue_context_p->ue_context.reestablishment_xid = -1; + + if (ul_dcch_msg->message.choice.c1->choice.rrcReestablishmentComplete->criticalExtensions.present == + NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete) { + rrc_gNB_process_RRCConnectionReestablishmentComplete(ctxt_pP, reestablish_rnti, ue_context_p, + ul_dcch_msg->message.choice.c1->choice.rrcReestablishmentComplete->rrc_TransactionIdentifier); + + } + + //ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 1; + // remove UE after 100 frames after LTE_RRCConnectionReestablishmentRelease is triggered + ue_context_p->ue_context.ue_reestablishment_timer_thres = 1000; + } + break; + default: + break; + } + } + return 0; +} + +void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *f1_setup_req) { + LOG_I(NR_RRC,"Received F1 Setup Request from gNB_DU %llu (%s)\n",(unsigned long long int)f1_setup_req->gNB_DU_id,f1_setup_req->gNB_DU_name); + int cu_cell_ind = 0; + MessageDef *msg_p = NULL,*msg_p2=NULL; + + for (int i = 0; i < f1_setup_req->num_cells_available; i++) { + int found_cell=0; + for (int j=0; jconfiguration.mcc[0] == f1_setup_req->mcc[i] && + rrc->configuration.mnc[0] == f1_setup_req->mnc[i] && + rrc->nr_cellid == f1_setup_req->nr_cellid[i]) { + // check that CU rrc instance corresponds to mcc/mnc/cgi (normally cgi should be enough, but just in case) + rrc->carrier.MIB = malloc(f1_setup_req->mib_length[i]); + rrc->carrier.sizeof_MIB = f1_setup_req->mib_length[i]; + LOG_W(NR_RRC, "instance %d mib length %d\n", i, f1_setup_req->mib_length[i]); + LOG_W(NR_RRC, "instance %d sib1 length %d\n", i, f1_setup_req->sib1_length[i]); + memcpy((void *)rrc->carrier.MIB,f1_setup_req->mib[i],f1_setup_req->mib_length[i]); + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_BCCH_BCH_Message, + (void **)&rrc->carrier.mib_DU, + f1_setup_req->mib[i], + f1_setup_req->mib_length[i]); + AssertFatal(dec_rval.code == RC_OK, + "[gNB_DU %"PRIu8"] Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits)\n", + j, + dec_rval.consumed ); + NR_BCCH_BCH_Message_t *mib = &rrc->carrier.mib; + NR_BCCH_BCH_Message_t *mib_DU = rrc->carrier.mib_DU; + mib->message.present = NR_BCCH_BCH_MessageType_PR_mib; + mib->message.choice.mib = CALLOC(1,sizeof(struct NR_MIB)); + memset(mib->message.choice.mib,0,sizeof(struct NR_MIB)); + memcpy(mib->message.choice.mib, mib_DU->message.choice.mib, sizeof(struct NR_MIB)); + + rrc->carrier.SIB1 = malloc(f1_setup_req->sib1_length[i]); + rrc->carrier.sizeof_SIB1 = f1_setup_req->sib1_length[i]; + memcpy((void *)rrc->carrier.SIB1,f1_setup_req->sib1[i],f1_setup_req->sib1_length[i]); + dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_BCCH_DL_SCH_Message, + (void **)&rrc->carrier.siblock1_DU, + f1_setup_req->sib1[i], + f1_setup_req->sib1_length[i]); + AssertFatal(dec_rval.code == RC_OK, + "[gNB_DU %"PRIu8"] Failed to decode NR_BCCH_DLSCH_MESSAGE (%zu bits)\n", + j, + dec_rval.consumed ); + + // Parse message and extract SystemInformationBlockType1 field + NR_BCCH_DL_SCH_Message_t *bcch_message = rrc->carrier.siblock1_DU; + AssertFatal(bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1, + "bcch_message->message.present != NR_BCCH_DL_SCH_MessageType_PR_c1\n"); + AssertFatal(bcch_message->message.choice.c1->present == NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1, + "bcch_message->message.choice.c1->present != NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1\n"); + rrc->carrier.sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; + rrc->carrier.physCellId = f1_setup_req->nr_pci[i]; + if (cu_cell_ind == 0) { + // prepare F1_SETUP_RESPONSE + GNB_CU_CONFIGURATION_UPDATE + if (msg_p == NULL) { + msg_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_SETUP_RESP); + } + if (msg_p2 == NULL) { + msg_p2 = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE); + } + + F1AP_SETUP_RESP (msg_p).gNB_CU_name = rrc->node_name; + F1AP_SETUP_RESP (msg_p).num_cells_to_activate = 0; + + } + + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).gNB_CU_name = rrc->node_name; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).cells_to_activate[cu_cell_ind].mcc = rrc->configuration.mcc[0]; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).cells_to_activate[cu_cell_ind].mnc = rrc->configuration.mnc[0]; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).cells_to_activate[cu_cell_ind].mnc_digit_length = rrc->configuration.mnc_digit_length[0]; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).cells_to_activate[cu_cell_ind].nr_cellid = rrc->nr_cellid; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).cells_to_activate[cu_cell_ind].nrpci = f1_setup_req->nr_pci[i]; + int num_SI= 0; + + if (rrc->carrier.SIB23) { + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).cells_to_activate[cu_cell_ind].SI_container[2] = rrc->carrier.SIB23; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).cells_to_activate[cu_cell_ind].SI_container_length[2] = rrc->carrier.sizeof_SIB23; + num_SI++; + } + + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).cells_to_activate[cu_cell_ind].num_SI = num_SI; + cu_cell_ind++; + found_cell=1; + F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p2).num_cells_to_activate = cu_cell_ind; + // send + break; + } else {// setup_req mcc/mnc match rrc internal list element + LOG_W(NR_RRC,"[Inst %d] No matching MCC/MNC: rrc->mcc/f1_setup_req->mcc %d/%d rrc->mnc/f1_setup_req->mnc %d/%d rrc->nr_cellid/f1_setup_req->nr_cellid %ld/%ld \n", + j, rrc->configuration.mcc[0], f1_setup_req->mcc[i], + rrc->configuration.mnc[0], f1_setup_req->mnc[i], + rrc->nr_cellid, f1_setup_req->nr_cellid[i]); + } + }// for (int j=0;jnum_cells_available;i++) +} + +void rrc_gNB_process_release_request(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_release_request_t *m) +{ + gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP]; + rrc_remove_nsa_user(rrc, m->rnti); +} + +void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC_dc_overall_timeout_t *m) +{ + gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP]; + rrc_remove_nsa_user(rrc, m->rnti); +} + +unsigned int mask_flip(unsigned int x) { + return((((x>>8) + (x<<8))&0xffff)>>6); +} + +unsigned int get_dl_bw_mask(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { + + + int common_band = *rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + int common_scs = rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + for (int i=0;irf_Parameters.supportedBandListNR.list.count;i++) { + NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[i]; + if (bandNRinfo->bandNR == common_band) { + if (common_band < 257) { // FR1 + switch (common_scs) { + case NR_SubcarrierSpacing_kHz15 : + if (bandNRinfo->channelBWs_DL && + bandNRinfo->channelBWs_DL->choice.fr1 && + bandNRinfo->channelBWs_DL->choice.fr1->scs_15kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_DL->choice.fr1->scs_15kHz->buf)); + break; + case NR_SubcarrierSpacing_kHz30 : + if (bandNRinfo->channelBWs_DL && + bandNRinfo->channelBWs_DL->choice.fr1 && + bandNRinfo->channelBWs_DL->choice.fr1->scs_30kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_DL->choice.fr1->scs_30kHz->buf)); + break; + case NR_SubcarrierSpacing_kHz60 : + if (bandNRinfo->channelBWs_DL && + bandNRinfo->channelBWs_DL->choice.fr1 && + bandNRinfo->channelBWs_DL->choice.fr1->scs_60kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_DL->choice.fr1->scs_60kHz->buf)); + break; + } + } + else { + switch (common_scs) { + case NR_SubcarrierSpacing_kHz60 : + if (bandNRinfo->channelBWs_DL && + bandNRinfo->channelBWs_DL->choice.fr2 && + bandNRinfo->channelBWs_DL->choice.fr2->scs_60kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_DL->choice.fr2->scs_60kHz->buf)); + break; + case NR_SubcarrierSpacing_kHz120 : + if (bandNRinfo->channelBWs_DL && + bandNRinfo->channelBWs_DL->choice.fr2 && + bandNRinfo->channelBWs_DL->choice.fr2->scs_120kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_DL->choice.fr2->scs_120kHz->buf)); + break; + } + } + } + } + return(0); +} + +unsigned int get_ul_bw_mask(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { + + + int common_band = *rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]; + int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + for (int i=0;irf_Parameters.supportedBandListNR.list.count;i++) { + NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[i]; + if (bandNRinfo->bandNR == common_band) { + if (common_band < 257) { // FR1 + switch (common_scs) { + case NR_SubcarrierSpacing_kHz15 : + if (bandNRinfo->channelBWs_UL && + bandNRinfo->channelBWs_UL->choice.fr1 && + bandNRinfo->channelBWs_UL->choice.fr1->scs_15kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_UL->choice.fr1->scs_15kHz->buf)); + break; + case NR_SubcarrierSpacing_kHz30 : + if (bandNRinfo->channelBWs_UL && + bandNRinfo->channelBWs_UL->choice.fr1 && + bandNRinfo->channelBWs_UL->choice.fr1->scs_30kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_UL->choice.fr1->scs_30kHz->buf)); + break; + case NR_SubcarrierSpacing_kHz60 : + if (bandNRinfo->channelBWs_UL && + bandNRinfo->channelBWs_UL->choice.fr1 && + bandNRinfo->channelBWs_UL->choice.fr1->scs_60kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_UL->choice.fr1->scs_60kHz->buf)); + break; + } + } + else { + switch (common_scs) { + case NR_SubcarrierSpacing_kHz60 : + if (bandNRinfo->channelBWs_UL && + bandNRinfo->channelBWs_UL->choice.fr2 && + bandNRinfo->channelBWs_UL->choice.fr2->scs_60kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_UL->choice.fr2->scs_60kHz->buf)); + break; + case NR_SubcarrierSpacing_kHz120 : + if (bandNRinfo->channelBWs_UL && + bandNRinfo->channelBWs_UL->choice.fr2 && + bandNRinfo->channelBWs_UL->choice.fr2->scs_120kHz) + return(mask_flip((unsigned int)*(uint16_t*)bandNRinfo->channelBWs_UL->choice.fr2->scs_120kHz->buf)); + break; + } + } + } + } + return(0); +} + +int is_dl_256QAM_supported(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { + int common_band = *rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + int common_scs = rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + if (common_band>256) { + for (int i=0;irf_Parameters.supportedBandListNR.list.count;i++) { + NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[i]; + if (bandNRinfo->bandNR == common_band && !bandNRinfo->pdsch_256QAM_FR2) return (0); + } + } + else if (cap->phy_Parameters.phy_ParametersFR1 && !cap->phy_Parameters.phy_ParametersFR1->pdsch_256QAM_FR1) return(0); + + // check featureSet + NR_FeatureSets_t *fs=cap->featureSets; + if (fs) { + // go through DL feature sets and look for one with current SCS + for (int i=0;ifeatureSetsDownlinkPerCC->list.count;i++) { + if (fs->featureSetsDownlinkPerCC->list.array[i]->supportedSubcarrierSpacingDL == common_scs && + fs->featureSetsDownlinkPerCC->list.array[i]->supportedModulationOrderDL && + *fs->featureSetsDownlinkPerCC->list.array[i]->supportedModulationOrderDL == NR_ModulationOrder_qam256) return(1); + } + } + return(0); +} + +int is_ul_256QAM_supported(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { + int common_band = *rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]; + int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + for (int i=0;irf_Parameters.supportedBandListNR.list.count;i++) { + NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[i]; + if (bandNRinfo->bandNR == common_band && !bandNRinfo->pusch_256QAM) return (0); + } + + // check featureSet + NR_FeatureSets_t *fs=cap->featureSets; + if (fs) { + // go through UL feature sets and look for one with current SCS + for (int i=0;ifeatureSetsUplinkPerCC->list.count;i++) { + if (fs->featureSetsUplinkPerCC->list.array[i]->supportedSubcarrierSpacingUL == common_scs && + fs->featureSetsUplinkPerCC->list.array[i]->supportedModulationOrderUL && + *fs->featureSetsUplinkPerCC->list.array[i]->supportedModulationOrderUL == NR_ModulationOrder_qam256) return(1); + } + } + return(0); +} + +int get_ul_mimo_layersCB(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { + int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + // check featureSet + NR_FeatureSets_t *fs=cap->featureSets; + if (fs) { + // go through UL feature sets and look for one with current SCS + for (int i=0;ifeatureSetsUplinkPerCC->list.count;i++) { + if (fs->featureSetsUplinkPerCC->list.array[i]->supportedSubcarrierSpacingUL == common_scs && + fs->featureSetsUplinkPerCC->list.array[i]->mimo_CB_PUSCH && + fs->featureSetsUplinkPerCC->list.array[i]->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH) + return(1<<*fs->featureSetsUplinkPerCC->list.array[i]->mimo_CB_PUSCH->maxNumberMIMO_LayersCB_PUSCH); + } + } + return(1); +} + +int get_ul_mimo_layers(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { + int common_scs = rrc->carrier.servingcellconfigcommon->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + // check featureSet + NR_FeatureSets_t *fs=cap->featureSets; + if (fs) { + // go through UL feature sets and look for one with current SCS + for (int i=0;ifeatureSetsUplinkPerCC->list.count;i++) { + if (fs->featureSetsUplinkPerCC->list.array[i]->supportedSubcarrierSpacingUL == common_scs && + fs->featureSetsUplinkPerCC->list.array[i]->maxNumberMIMO_LayersNonCB_PUSCH) + return(1<<*fs->featureSetsUplinkPerCC->list.array[i]->maxNumberMIMO_LayersNonCB_PUSCH); + } + } + return(1); +} + +int get_dl_mimo_layers(gNB_RRC_INST *rrc,NR_UE_NR_Capability_t *cap) { + int common_scs = rrc->carrier.servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + // check featureSet + NR_FeatureSets_t *fs=cap->featureSets; + if (fs) { + // go through UL feature sets and look for one with current SCS + for (int i=0;ifeatureSetsDownlinkPerCC->list.count;i++) { + if (fs->featureSetsUplinkPerCC->list.array[i]->supportedSubcarrierSpacingUL == common_scs && + fs->featureSetsDownlinkPerCC->list.array[i]->maxNumberMIMO_LayersPDSCH) + return(2<<*fs->featureSetsDownlinkPerCC->list.array[i]->maxNumberMIMO_LayersPDSCH); + } + } + return(1); +} +void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { + + MessageDef *msg; + rrc_gNB_ue_context_t *ue_context_p = NULL; + FILE *fd=NULL;//fopen("nrRRCstats.log","w"); + RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &(RC.nrrrc[ctxt_pP->module_id]->rrc_ue_head)) { + ctxt_pP->rnti = ue_context_p->ue_id_rnti; + + if (fd) { + if (ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence == TRUE) { + fprintf(fd,"NR RRC UE rnti %x: S-TMSI %x failure timer %d/8\n", + ue_context_p->ue_id_rnti, + ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.fiveg_tmsi, + ue_context_p->ue_context.ul_failure_timer); + } else { + fprintf(fd,"NR RRC UE rnti %x failure timer %d/8\n", + ue_context_p->ue_id_rnti, + ue_context_p->ue_context.ul_failure_timer); + } + + if (ue_context_p->ue_context.UE_Capability_nr) { + fprintf(fd,"NR RRC UE cap: BW DL %x. BW UL %x, 256 QAM DL %s, 256 QAM UL %s, DL MIMO Layers %d UL MIMO Layers (CB) %d UL MIMO Layers (nonCB) %d\n", + get_dl_bw_mask(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr), + get_ul_bw_mask(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr), + is_dl_256QAM_supported(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr) == 1 ? "yes" : "no", + is_ul_256QAM_supported(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr) == 1 ? "yes" : "no", + get_dl_mimo_layers(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr), + get_ul_mimo_layersCB(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr), + get_ul_mimo_layers(RC.nrrrc[0],ue_context_p->ue_context.UE_Capability_nr)); + } + } + if (ue_context_p->ue_context.ul_failure_timer > 0) { + ue_context_p->ue_context.ul_failure_timer++; + + if (ue_context_p->ue_context.ul_failure_timer >= 20000) { + // remove UE after 20 seconds after MAC (or else) has indicated UL failure + LOG_I(RRC, "Removing UE %x instance, because of uplink failure timer timeout\n", + ue_context_p->ue_context.rnti); + if(ue_context_p->ue_context.StatusRrc >= NR_RRC_CONNECTED){ + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ( + ctxt_pP->module_id, + ue_context_p, + NGAP_CAUSE_RADIO_NETWORK, + NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST); + } + + // Remove here the MAC and RRC context when RRC is not connected or gNB is not connected to CN5G + if(ue_context_p->ue_context.StatusRrc < NR_RRC_CONNECTED || ue_context_p->ue_context.gNB_ue_ngap_id == 0) { + mac_remove_nr_ue(ctxt_pP->module_id, ctxt_pP->rnti); + rrc_rlc_remove_ue(ctxt_pP); + pdcp_remove_UE(ctxt_pP); + + /* remove RRC UE Context */ + ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[ctxt_pP->module_id], ctxt_pP->rnti); + if (ue_context_p) { + rrc_gNB_remove_ue_context(ctxt_pP, RC.nrrrc[ctxt_pP->module_id], ue_context_p); + LOG_I(NR_RRC, "remove UE %x \n", ctxt_pP->rnti); + } + } + + break; // break RB_FOREACH + } + } + + if (ue_context_p->ue_context.ue_release_timer_rrc > 0) { + ue_context_p->ue_context.ue_release_timer_rrc++; + + if (ue_context_p->ue_context.ue_release_timer_rrc >= ue_context_p->ue_context.ue_release_timer_thres_rrc) { + LOG_I(NR_RRC, "Removing UE %x instance after UE_CONTEXT_RELEASE_Complete (ue_release_timer_rrc timeout)\n", + ue_context_p->ue_context.rnti); + ue_context_p->ue_context.ue_release_timer_rrc = 0; + + mac_remove_nr_ue(ctxt_pP->module_id, ctxt_pP->rnti); + rrc_rlc_remove_ue(ctxt_pP); + pdcp_remove_UE(ctxt_pP); + + /* remove RRC UE Context */ + ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[ctxt_pP->module_id], ctxt_pP->rnti); + if (ue_context_p) { + rrc_gNB_remove_ue_context(ctxt_pP, RC.nrrrc[ctxt_pP->module_id], ue_context_p); + LOG_I(NR_RRC, "remove UE %x \n", ctxt_pP->rnti); + } + + break; // break RB_FOREACH + } + } + } + + if (fd) fclose(fd); + + /* send a tick to x2ap */ + if (is_x2ap_enabled()){ + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_SUBFRAME_PROCESS); + itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg); + } +} + ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// void *rrc_gnb_task(void *args_p) { @@ -306,7 +3090,16 @@ void *rrc_gnb_task(void *args_p) { int result; //SRB_INFO *srb_info_p; //int CC_id; - //protocol_ctxt_t ctxt; + protocol_ctxt_t ctxt={.module_id=0, + .enb_flag=1, + .instance=0, + .rnti=0, + .frame=-1, + .subframe=-1, + .eNB_index=0, + .configured=true, + .brOption=false + }; itti_mark_task_ready(TASK_RRC_GNB); LOG_I(NR_RRC,"Entering main loop of NR_RRC message task\n"); @@ -314,84 +3107,114 @@ void *rrc_gnb_task(void *args_p) { // Wait for a message itti_receive_msg(TASK_RRC_GNB, &msg_p); msg_name_p = ITTI_MSG_NAME(msg_p); - instance = ITTI_MSG_INSTANCE(msg_p); - LOG_I(NR_RRC,"Received message %s\n",msg_name_p); + instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p); + + /* RRC_SUBFRAME_PROCESS is sent every subframe, do not log it */ + if (ITTI_MSG_ID(msg_p) != RRC_SUBFRAME_PROCESS) + LOG_I(NR_RRC,"Received message %s\n",msg_name_p); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: - LOG_W(RRC, " *** Exiting NR_RRC thread\n"); + LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n"); itti_exit_task(); break; case MESSAGE_TEST: - LOG_I(RRC, "[gNB %d] Received %s\n", instance, msg_name_p); + LOG_I(NR_RRC, "[gNB %ld] Received %s\n", instance, msg_name_p); + break; + + case RRC_SUBFRAME_PROCESS: + nr_rrc_subframe_process(&RRC_SUBFRAME_PROCESS(msg_p).ctxt, RRC_SUBFRAME_PROCESS(msg_p).CC_id); break; /* Messages from MAC */ + case NR_RRC_MAC_CCCH_DATA_IND: + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).gnb_index, + GNB_FLAG_YES, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).rnti, + msg_p->ittiMsgHeader.lte_time.frame, + msg_p->ittiMsgHeader.lte_time.slot); + LOG_I(NR_RRC,"Decoding CCCH : ue %d, inst %ld, CC_id %d, ctxt %p, sib_info_p->Rx_buffer.payload_size %d\n", + ctxt.rnti, + instance, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).CC_id, + &ctxt, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size); + + if (NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size >= CCCH_SDU_SIZE) { + LOG_I(NR_RRC, "CCCH message has size %d > %d\n", + NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size,CCCH_SDU_SIZE); + break; + } + + nr_rrc_gNB_decode_ccch(&ctxt, + (uint8_t *)NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).du_to_cu_rrc_container, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).CC_id); + + if (NR_RRC_MAC_CCCH_DATA_IND(msg_p).du_to_cu_rrc_container) { + free(NR_RRC_MAC_CCCH_DATA_IND(msg_p).du_to_cu_rrc_container->buf); + free(NR_RRC_MAC_CCCH_DATA_IND(msg_p).du_to_cu_rrc_container); + } + + break; /* Messages from PDCP */ + case NR_RRC_DCCH_DATA_IND: + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + instance, + GNB_FLAG_YES, + NR_RRC_DCCH_DATA_IND(msg_p).rnti, + msg_p->ittiMsgHeader.lte_time.frame, + msg_p->ittiMsgHeader.lte_time.slot); + LOG_D(NR_RRC,"Decoding DCCH : ue %d, inst %ld, ctxt %p, size %d\n", + ctxt.rnti, + instance, + &ctxt, + NR_RRC_DCCH_DATA_IND(msg_p).sdu_size); + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Received on DCCH %d %s\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(&ctxt), + NR_RRC_DCCH_DATA_IND(msg_p).dcch_index, + msg_name_p); + rrc_gNB_decode_dcch(&ctxt, + NR_RRC_DCCH_DATA_IND(msg_p).dcch_index, + NR_RRC_DCCH_DATA_IND(msg_p).sdu_p, + NR_RRC_DCCH_DATA_IND(msg_p).sdu_size); + result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), NR_RRC_DCCH_DATA_IND(msg_p).sdu_p); - /* - #if defined(ENABLE_USE_MME) + break; - // Messages from S1AP - case S1AP_DOWNLINK_NAS: - rrc_eNB_process_S1AP_DOWNLINK_NAS(msg_p, msg_name_p, instance, &rrc_gNB_mui); - break; + case NGAP_DOWNLINK_NAS: + rrc_gNB_process_NGAP_DOWNLINK_NAS(msg_p, msg_name_p, instance, &rrc_gNB_mui); + break; - case S1AP_INITIAL_CONTEXT_SETUP_REQ: - rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p, msg_name_p, instance); - break; + case NGAP_PDUSESSION_SETUP_REQ: + rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(msg_p, msg_name_p, instance); + break; - case S1AP_UE_CTXT_MODIFICATION_REQ: - rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(msg_p, msg_name_p, instance); - break; + case NGAP_PDUSESSION_RELEASE_COMMAND: + rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(msg_p, msg_name_p, instance); + break; - case S1AP_PAGING_IND: - LOG_D(RRC, "[eNB %d] Received Paging message from S1AP: %s\n", instance, msg_name_p); - rrc_eNB_process_PAGING_IND(msg_p, msg_name_p, instance); - break; + case GTPV1U_GNB_DELETE_TUNNEL_RESP: + break; - case S1AP_E_RAB_SETUP_REQ: - rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(msg_p, msg_name_p, instance); - LOG_D(RRC, "[eNB %d] Received the message %s\n", instance, msg_name_p); - break; - - case S1AP_E_RAB_MODIFY_REQ: - rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(msg_p, msg_name_p, instance); - break; - - case S1AP_E_RAB_RELEASE_COMMAND: - rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(msg_p, msg_name_p, instance); - break; - - case S1AP_UE_CONTEXT_RELEASE_REQ: - rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ(msg_p, msg_name_p, instance); - break; - - case S1AP_UE_CONTEXT_RELEASE_COMMAND: - rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND(msg_p, msg_name_p, instance); - break; - - case GTPV1U_ENB_DELETE_TUNNEL_RESP: - ///Nothing to do. Apparently everything is done in S1AP processing - //LOG_I(RRC, "[eNB %d] Received message %s, not processed because procedure not synched\n", - //instance, msg_name_p); - if (rrc_eNB_get_ue_context(RC.nrrrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti) - && rrc_eNB_get_ue_context(RC.nrrrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc > 0) { - rrc_eNB_get_ue_context(RC.nrrrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc = - rrc_eNB_get_ue_context(RC.nrrrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_thres_rrc; - } - break; - - #endif - */ /* Messages from gNB app */ case NRRRC_CONFIGURATION_REQ: - LOG_I(NR_RRC, "[gNB %d] Received %s : %p\n", instance, msg_name_p,&NRRRC_CONFIGURATION_REQ(msg_p)); + LOG_I(NR_RRC, "[gNB %ld] Received %s : %p\n", instance, msg_name_p,&NRRRC_CONFIGURATION_REQ(msg_p)); openair_rrc_gNB_configuration(GNB_INSTANCE_TO_MODULE_ID(instance), &NRRRC_CONFIGURATION_REQ(msg_p)); break; + /* Messages from F1AP task */ + case F1AP_SETUP_REQ: + AssertFatal(NODE_IS_CU(RC.nrrrc[instance]->node_type), + "should not receive F1AP_SETUP_REQUEST, need call by CU!\n"); + LOG_I(NR_RRC,"[gNB %ld] Received %s : %p\n", instance, msg_name_p, &F1AP_SETUP_REQ(msg_p)); + rrc_gNB_process_f1_setup_req(&F1AP_SETUP_REQ(msg_p)); + break; + /* Messages from X2AP */ case X2AP_ENDC_SGNB_ADDITION_REQ: LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n"); @@ -402,8 +3225,34 @@ void *rrc_gnb_task(void *args_p) { LOG_I(NR_RRC, "Handling of reconfiguration complete message at RRC gNB is pending \n"); break; + case NGAP_INITIAL_CONTEXT_SETUP_REQ: + rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p, msg_name_p, instance); + break; + + case X2AP_ENDC_SGNB_RELEASE_REQUEST: + LOG_I(NR_RRC, "Received ENDC sgNB release request from X2AP \n"); + rrc_gNB_process_release_request(GNB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_SGNB_RELEASE_REQUEST(msg_p)); + break; + + case X2AP_ENDC_DC_OVERALL_TIMEOUT: + rrc_gNB_process_dc_overall_timeout(GNB_INSTANCE_TO_MODULE_ID(instance), &X2AP_ENDC_DC_OVERALL_TIMEOUT(msg_p)); + break; + + /* Messages from GTP */ + case GTPV1U_ENB_DELETE_TUNNEL_RESP: + /* nothing to do? */ + break; + + case NGAP_UE_CONTEXT_RELEASE_REQ: + rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ(msg_p, msg_name_p, instance); + break; + + case NGAP_UE_CONTEXT_RELEASE_COMMAND: + rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p, msg_name_p, instance); + break; + default: - LOG_E(NR_RRC, "[gNB %d] Received unexpected message %s\n", instance, msg_name_p); + LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); break; } @@ -413,3 +3262,261 @@ void *rrc_gnb_task(void *args_p) { } } +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_SecurityModeCommand( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP +) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[100]; + uint8_t size; + + T(T_ENB_RRC_SECURITY_MODE_COMMAND, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), + T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + NR_IntegrityProtAlgorithm_t integrity_algorithm = (NR_IntegrityProtAlgorithm_t)ue_context_pP->ue_context.integrity_algorithm; + size = do_NR_SecurityModeCommand( + ctxt_pP, + buffer, + rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id), + ue_context_pP->ue_context.ciphering_algorithm, + &integrity_algorithm); + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Security Mode Command\n"); + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate SecurityModeCommand (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + size); + + switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { + case ngran_gNB_CU: + // create an ITTI message + memcpy(ue_context_pP->ue_context.Srb1.Srb_info.Tx_buffer.Payload, buffer, size); + ue_context_pP->ue_context.Srb1.Srb_info.Tx_buffer.payload_size = size; + + LOG_I(NR_RRC,"calling rrc_data_req :securityModeCommand\n"); + nr_rrc_data_req(ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + break; + + case ngran_gNB_DU: + // nothing to do for DU + AssertFatal(1==0,"nothing to do for DU\n"); + break; + + case ngran_gNB: + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (securityModeCommand to UE MUI %d) --->[PDCP][RB %02d]\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + size, + rrc_gNB_mui, + DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" securityModeCommand UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM,size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + LOG_D(NR_RRC,"calling rrc_data_req :securityModeCommand\n"); + nr_rrc_data_req(ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif + break; + + default : + LOG_W(NR_RRC, "Unknown node type %d\n", RC.nrrrc[ctxt_pP->module_id]->node_type); + } +} + +void +rrc_gNB_generate_UECapabilityEnquiry( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP +) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[100]; + uint8_t size; + + T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), + T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + size = do_NR_SA_UECapabilityEnquiry( + ctxt_pP, + buffer, + rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id)); + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate NR UECapabilityEnquiry (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + size); + switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { + case ngran_gNB_CU: + nr_rrc_data_req( + ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + break; + + case ngran_gNB_DU: + // nothing to do for DU + AssertFatal(1==0,"nothing to do for DU\n"); + break; + + case ngran_gNB: + // rrc_mac_config_req_gNB + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (NR UECapabilityEnquiry MUI %d) --->[PDCP][RB %02d]\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + size, + rrc_gNB_mui, + DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" rrcNRUECapabilityEnquiry UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + nr_rrc_data_req(ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif + break; + + default : + LOG_W(NR_RRC, "Unknown node type %d\n", RC.nrrrc[ctxt_pP->module_id]->node_type); + } +} + +//----------------------------------------------------------------------------- +/* +* Generate the RRC Connection Release to UE. +* If received, UE should switch to RRC_IDLE mode. +*/ +void +rrc_gNB_generate_RRCRelease( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP +) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size = 0; + + memset(buffer, 0, RRC_BUF_SIZE); + + size = do_NR_RRCRelease(buffer,rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id)); + ue_context_pP->ue_context.ue_reestablishment_timer = 0; + ue_context_pP->ue_context.ue_release_timer = 0; + ue_context_pP->ue_context.ul_failure_timer = 0; + ue_context_pP->ue_context.ue_release_timer_rrc = 0; + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCRelease (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + size); + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (rrcRelease MUI %d) --->[PDCP][RB %u]\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + size, + rrc_gNB_mui, + DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" NR_RRCRelease UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); + +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + if (NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { + uint8_t *message_buffer = itti_malloc (TASK_RRC_GNB, TASK_CU_F1, size); + memcpy (message_buffer, buffer, size); + MessageDef *m = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); + F1AP_UE_CONTEXT_RELEASE_CMD(m).rnti = ctxt_pP->rnti; + F1AP_UE_CONTEXT_RELEASE_CMD(m).cause = F1AP_CAUSE_RADIO_NETWORK; + F1AP_UE_CONTEXT_RELEASE_CMD(m).cause_value = 10; // 10 = F1AP_CauseRadioNetwork_normal_release + F1AP_UE_CONTEXT_RELEASE_CMD(m).rrc_container = message_buffer; + F1AP_UE_CONTEXT_RELEASE_CMD(m).rrc_container_length = size; + itti_send_msg_to_task(TASK_CU_F1, ctxt_pP->module_id, m); + } else { + nr_rrc_data_req(ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + + rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(ctxt_pP->instance, ue_context_pP->ue_context.gNB_ue_ngap_id); + ue_context_pP->ue_context.ue_release_timer_rrc = 1; + } +#endif +} +void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe) +{ + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_RRC_GNB, 0, RRC_SUBFRAME_PROCESS); + RRC_SUBFRAME_PROCESS(message_p).ctxt = *ctxt; + RRC_SUBFRAME_PROCESS(message_p).CC_id = CC_id; + itti_send_msg_to_task(TASK_RRC_GNB, ctxt->module_id, message_p); +} diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.c b/openair2/RRC/NR/rrc_gNB_GTPV1U.c index 9ab1bbf43a..293f9e8b9f 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.c +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.c @@ -92,3 +92,52 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( return -1; } } + +int +nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +) { + rnti_t rnti; + int i; + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + + if (create_tunnel_resp_pP) { + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" RX CREATE_TUNNEL_RESP num tunnels %u \n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + create_tunnel_resp_pP->num_tunnels); + rnti = create_tunnel_resp_pP->rnti; + ue_context_p = rrc_gNB_get_ue_context( + RC.nrrrc[ctxt_pP->module_id], + ctxt_pP->rnti); + + for (i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) { + ue_context_p->ue_context.gnb_gtp_teid[inde_list[i]] = create_tunnel_resp_pP->gnb_NGu_teid[i]; + ue_context_p->ue_context.gnb_gtp_addrs[inde_list[i]] = create_tunnel_resp_pP->gnb_addr; + ue_context_p->ue_context.gnb_gtp_psi[inde_list[i]] = create_tunnel_resp_pP->pdusession_id[i]; + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, msg index %u, id %u, gtp addr len %d \n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + create_tunnel_resp_pP->gnb_NGu_teid[i], + ue_context_p->ue_context.gnb_gtp_teid[inde_list[i]], + inde_list[i], + i, + create_tunnel_resp_pP->pdusession_id[i], + create_tunnel_resp_pP->gnb_addr.length); + } + + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_GTPU_GNB, + NULL,0, + MSC_AS_TIME_FMT" CREATE_TUNNEL_RESP RNTI %"PRIx16" ntuns %u psid %u enb-s1u teid %u", + 0,0,rnti, + create_tunnel_resp_pP->num_tunnels, + ue_context_p->ue_context.gnb_gtp_psi[0], + ue_context_p->ue_context.gnb_gtp_teid[0]); + (void)rnti; /* avoid gcc warning "set but not used" */ + return 0; + } else { + return -1; + } +} diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.h b/openair2/RRC/NR/rrc_gNB_GTPV1U.h index caff825a7a..748bd98789 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.h +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.h @@ -37,3 +37,12 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, uint8_t *inde_list ); + +int +nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +); + +#endif diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c new file mode 100644 index 0000000000..60ee99a172 --- /dev/null +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -0,0 +1,1509 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file rrc_gNB_NGAP.h + * \brief rrc NGAP procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#include "rrc_gNB_NGAP.h" +#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" +#include "rrc_eNB_S1AP.h" +#include "gnb_config.h" +#include "common/ran_context.h" +#include "gtpv1u.h" + +#include "asn1_conversions.h" +#include "intertask_interface.h" +#include "pdcp.h" +#include "pdcp_primitives.h" + +#include "msc.h" + +#include "gtpv1u_eNB_task.h" +#include "gtpv1u_gNB_task.h" +#include "RRC/LTE/rrc_eNB_GTPV1U.h" +#include "RRC/NR/rrc_gNB_GTPV1U.h" + +#include "S1AP_NAS-PDU.h" +#include "executables/softmodem-common.h" +#include "UTIL/OSA/osa_defs.h" +#include "ngap_gNB_defs.h" +#include "ngap_gNB_ue_context.h" +#include "ngap_gNB_management_procedures.h" +#include "NR_ULInformationTransfer.h" +#include "RRC/NR/MESSAGES/asn1_msg.h" +#include "NR_UERadioAccessCapabilityInformation.h" +#include "NR_UE-CapabilityRAT-ContainerList.h" +#include "NGAP_Cause.h" +#include "NGAP_CauseRadioNetwork.h" +#include "f1ap_messages_types.h" + +extern RAN_CONTEXT_t RC; + +/* Value to indicate an invalid UE initial id */ +static const uint16_t UE_INITIAL_ID_INVALID = 0; + +/* Masks for NGAP Encryption algorithms, NEA0 is always supported (not coded) */ +static const uint16_t NGAP_ENCRYPTION_NEA1_MASK = 0x8000; +static const uint16_t NGAP_ENCRYPTION_NEA2_MASK = 0x4000; +static const uint16_t NGAP_ENCRYPTION_NEA3_MASK = 0x2000; + +/* Masks for NGAP Integrity algorithms, NIA0 is always supported (not coded) */ +static const uint16_t NGAP_INTEGRITY_NIA1_MASK = 0x8000; +static const uint16_t NGAP_INTEGRITY_NIA2_MASK = 0x4000; +static const uint16_t NGAP_INTEGRITY_NIA3_MASK = 0x2000; + +#define INTEGRITY_ALGORITHM_NONE NR_IntegrityProtAlgorithm_nia0 + +/*! \fn uint16_t get_next_ue_initial_id(uint8_t mod_id) + *\brief provide an UE initial ID for NGAP initial communication. + *\param mod_id Instance ID of gNB. + *\return the UE initial ID. + */ +//------------------------------------------------------------------------------ +static uint16_t +get_next_ue_initial_id( + const module_id_t mod_id +) +//------------------------------------------------------------------------------ +{ + static uint16_t ue_initial_id[NUMBER_OF_gNB_MAX]; + ue_initial_id[mod_id]++; + + /* Never use UE_INITIAL_ID_INVALID this is the invalid id! */ + if (ue_initial_id[mod_id] == UE_INITIAL_ID_INVALID) { + ue_initial_id[mod_id]++; + } + + return ue_initial_id[mod_id]; +} + +//------------------------------------------------------------------------------ +/* +* Get the UE NG struct containing hashtables NG_id/UE_id. +* Is also used to set the NG_id of the UE, depending on inputs. +*/ +struct rrc_ue_ngap_ids_s * +rrc_gNB_NGAP_get_ue_ids( + gNB_RRC_INST *const rrc_instance_pP, + const uint16_t ue_initial_id, + const uint32_t gNB_ue_ngap_idP +) +//------------------------------------------------------------------------------ +{ + rrc_ue_ngap_ids_t *result = NULL; + rrc_ue_ngap_ids_t *result2 = NULL; + /*****************************/ + instance_t instance = 0; + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + ngap_gNB_ue_context_t *ue_desc_p = NULL; + rrc_gNB_ue_context_t *ue_context_p = NULL; + /*****************************/ + hashtable_rc_t h_rc; + + if (ue_initial_id != UE_INITIAL_ID_INVALID) { + h_rc = hashtable_get(rrc_instance_pP->initial_id2_ngap_ids, (hash_key_t)ue_initial_id, (void **)&result); + + if (h_rc == HASH_TABLE_OK) { + if (gNB_ue_ngap_idP > 0) { + h_rc = hashtable_get(rrc_instance_pP->ngap_id2_ngap_ids, (hash_key_t)gNB_ue_ngap_idP, (void **)&result2); + + if (h_rc != HASH_TABLE_OK) { // this case is equivalent to associate gNB_ue_ngap_idP and ue_initial_id + result2 = malloc(sizeof(*result2)); + + if (NULL != result2) { + *result2 = *result; + result2->gNB_ue_ngap_id = gNB_ue_ngap_idP; + result->gNB_ue_ngap_id = gNB_ue_ngap_idP; + h_rc = hashtable_insert(rrc_instance_pP->ngap_id2_ngap_ids, (hash_key_t)gNB_ue_ngap_idP, result2); + + if (h_rc != HASH_TABLE_OK) { + LOG_E(NGAP, "[gNB %ld] Error while hashtable_insert in ngap_id2_ngap_ids gNB_ue_ngap_idP %"PRIu32"\n", + rrc_instance_pP - RC.nrrrc[0], + gNB_ue_ngap_idP); + } + } + } else { // here we should check that the association was done correctly + if ((result->ue_initial_id != result2->ue_initial_id) || (result->gNB_ue_ngap_id != result2->gNB_ue_ngap_id)) { + LOG_E(NGAP, "[gNB %ld] Error while hashtable_get, two rrc_ue_ngap_ids_t that should be equal, are not:\n \ + ue_initial_id 1 = %"PRIu16",\n \ + ue_initial_id 2 = %"PRIu16",\n \ + gNB_ue_ngap_idP 1 = %"PRIu32",\n \ + gNB_ue_ngap_idP 2 = %"PRIu32"\n", + rrc_instance_pP - RC.nrrrc[0], + result->ue_initial_id, + result2->ue_initial_id, + result->gNB_ue_ngap_id, + result2->gNB_ue_ngap_id); + // Still return *result + } + } + } // end if if (gNB_ue_ngap_idP > 0) + } else { // end if (h_rc == HASH_TABLE_OK) + LOG_E(NGAP, "[gNB %ld] In hashtable_get, couldn't find in initial_id2_ngap_ids ue_initial_id %"PRIu16"\n", + rrc_instance_pP - RC.nrrrc[0], + ue_initial_id); + return NULL; + /* + * At the moment this is written, this case shouldn't (cannot) happen and is equivalent to an error. + * One could try to find the struct instance based on ngap_id2_ngap_ids and gNB_ue_ngap_idP (if > 0), + * but this behavior is not expected at the moment. + */ + } // end else (h_rc != HASH_TABLE_OK) + } else { // end if (ue_initial_id != UE_INITIAL_ID_INVALID) + if (gNB_ue_ngap_idP > 0) { + h_rc = hashtable_get(rrc_instance_pP->ngap_id2_ngap_ids, (hash_key_t)gNB_ue_ngap_idP, (void **)&result); + + if (h_rc != HASH_TABLE_OK) { + /* + * This case is uncommon, but can happen when: + * -> if the first NAS message was a Detach Request (non exhaustiv), the UE RRC context exist + * but is not associated with gNB_ue_ngap_id + * -> ... (?) + */ + LOG_E(NGAP, "[gNB %ld] In hashtable_get, couldn't find in ngap_id2_ngap_ids gNB_ue_ngap_idP %"PRIu32", trying to find it through NGAP context\n", + rrc_instance_pP - RC.nrrrc[0], + gNB_ue_ngap_idP); + instance = GNB_MODULE_ID_TO_INSTANCE(rrc_instance_pP - RC.nrrrc[0]); // get gNB instance + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); // get ngap_gNB_instance + + if (ngap_gNB_instance_p != NULL) { + ue_desc_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, gNB_ue_ngap_idP); // get s1ap_eNB_ue_context + } else { + LOG_E(NGAP, "[gNB instance %ld] Couldn't find the gNB NGAP context\n", + instance); + return NULL; + } + + if (ue_desc_p != NULL) { + struct ngap_gNB_ue_context_s *ngap_ue_context_p = NULL; + + if ((ngap_ue_context_p = RB_REMOVE(ngap_ue_map, &ngap_gNB_instance_p->ngap_ue_head, ue_desc_p)) != NULL) { + LOG_E(NR_RRC, "Removed UE context gNB_ue_ngap_id %u\n", ngap_ue_context_p->gNB_ue_ngap_id); + ngap_gNB_free_ue_context(ngap_ue_context_p); + } else { + LOG_E(NR_RRC, "Removing UE context gNB_ue_ngap_id %u: did not find context\n",ue_desc_p->gNB_ue_ngap_id); + } + + return NULL; //skip the operation below to avoid loop + result = rrc_gNB_NGAP_get_ue_ids(rrc_instance_pP, ue_desc_p->ue_initial_id, gNB_ue_ngap_idP); + + if (ue_desc_p->ue_initial_id != UE_INITIAL_ID_INVALID) { + result = rrc_gNB_NGAP_get_ue_ids(rrc_instance_pP, ue_desc_p->ue_initial_id, gNB_ue_ngap_idP); + + if (result != NULL) { + ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)], result->ue_rnti); + + if ((ue_context_p != NULL) && (ue_context_p->ue_context.gNB_ue_ngap_id == 0)) { + ue_context_p->ue_context.gNB_ue_ngap_id = gNB_ue_ngap_idP; + } else { + LOG_E(NR_RRC, "[gNB %ld] Incoherence between RRC context and NGAP context (%d != %d) for UE RNTI %d or UE RRC context doesn't exist\n", + rrc_instance_pP - RC.nrrrc[0], + (ue_context_p==NULL)?99999:ue_context_p->ue_context.gNB_ue_ngap_id, + gNB_ue_ngap_idP, + result->ue_rnti); + } + } + } else { + LOG_E(NGAP, "[gNB %ld] NGAP context found but ue_initial_id is invalid (0)\n", rrc_instance_pP - RC.nrrrc[0]); + return NULL; + } + } else { + LOG_E(NGAP, "[gNB %ld] In hashtable_get, couldn't find in ngap_id2_ngap_ids gNB_ue_ngap_idP %"PRIu32", because ue_initial_id is invalid in NGAP context\n", + rrc_instance_pP - RC.nrrrc[0], + gNB_ue_ngap_idP); + return NULL; + } + } // end if (h_rc != HASH_TABLE_OK) + } // end if (gNB_ue_ngap_idP > 0) + } // end else (ue_initial_id == UE_INITIAL_ID_INVALID) + + return result; +} + +//------------------------------------------------------------------------------ +static struct rrc_gNB_ue_context_s * +rrc_gNB_get_ue_context_from_ngap_ids( + const instance_t instanceP, + const uint16_t ue_initial_idP, + const uint32_t gNB_ue_ngap_idP +) +//------------------------------------------------------------------------------ +{ + rrc_ue_ngap_ids_t *temp = NULL; + temp = rrc_gNB_NGAP_get_ue_ids(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instanceP)], ue_initial_idP, gNB_ue_ngap_idP); + + if (temp != NULL) { + return rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instanceP)], temp->ue_rnti); + } + + return NULL; +} + +/*! \fn void process_gNB_security_key (const protocol_ctxt_t* const ctxt_pP, eNB_RRC_UE_t * const ue_context_pP, uint8_t *security_key) + *\brief save security key. + *\param ctxt_pP Running context. + *\param ue_context_pP UE context. + *\param security_key_pP The security key received from NGAP. + */ +//------------------------------------------------------------------------------ +void process_gNB_security_key ( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t *security_key_pP +) +//------------------------------------------------------------------------------ +{ + char ascii_buffer[65]; + uint8_t i; + /* Saves the security key */ + memcpy (ue_context_pP->ue_context.kgnb, security_key_pP, SECURITY_KEY_LENGTH); + memset (ue_context_pP->ue_context.nh, 0, SECURITY_KEY_LENGTH); + ue_context_pP->ue_context.nh_ncc = -1; + + for (i = 0; i < 32; i++) { + sprintf(&ascii_buffer[2 * i], "%02X", ue_context_pP->ue_context.kgnb[i]); + } + + ascii_buffer[2 * i] = '\0'; + LOG_I(NR_RRC, "[gNB %d][UE %x] Saved security key %s\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ascii_buffer); +} + +//------------------------------------------------------------------------------ +void +nr_rrc_pdcp_config_security( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + const uint8_t enable_ciphering +) +//------------------------------------------------------------------------------ +{ + NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; + (void)SRB_configList; + uint8_t *kRRCenc = NULL; + uint8_t *kRRCint = NULL; + uint8_t *kUPenc = NULL; + static int print_keys= 1; + + /* Derive the keys from kgnb */ + if (SRB_configList != NULL) { + nr_derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm, + ue_context_pP->ue_context.kgnb, + &kUPenc); + } + + nr_derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm, + ue_context_pP->ue_context.kgnb, + &kRRCenc); + nr_derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm, + ue_context_pP->ue_context.kgnb, + &kRRCint); + if (!IS_SOFTMODEM_IQPLAYER) { + SET_LOG_DUMP(DEBUG_SECURITY) ; + } + + + if ( LOG_DUMPFLAG( DEBUG_SECURITY ) ) { + if (print_keys == 1 ) { + print_keys =0; + LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, ue_context_pP->ue_context.kgnb, 32,"\nKgNB:" ); + LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, kRRCenc, 16,"\nKRRCenc:" ); + LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, kRRCint, 16,"\nKRRCint:" ); + } + } + + pdcp_config_set_security( + ctxt_pP, + NULL, /* pdcp_pP not used anymore in NR */ + DCCH, + DCCH+2, + enable_ciphering ? + ue_context_pP->ue_context.ciphering_algorithm + | (ue_context_pP->ue_context.integrity_algorithm << 4) + : 0 + | (ue_context_pP->ue_context.integrity_algorithm << 4), + kRRCenc, + kRRCint, + kUPenc); +} + +//------------------------------------------------------------------------------ +/* +* Initial UE NAS message on S1AP. +*/ +void +rrc_gNB_send_NGAP_NAS_FIRST_REQ( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + NR_RRCSetupComplete_IEs_t *rrcSetupComplete +) +//------------------------------------------------------------------------------ +{ + // gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + MessageDef *message_p = NULL; + rrc_ue_ngap_ids_t *rrc_ue_ngap_ids_p = NULL; + hashtable_rc_t h_rc; + + message_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_NAS_FIRST_REQ); + memset(&message_p->ittiMsg.ngap_nas_first_req, 0, sizeof(ngap_nas_first_req_t)); + ue_context_pP->ue_context.ue_initial_id = get_next_ue_initial_id(ctxt_pP->module_id); + NGAP_NAS_FIRST_REQ(message_p).ue_initial_id = ue_context_pP->ue_context.ue_initial_id; + rrc_ue_ngap_ids_p = malloc(sizeof(rrc_ue_ngap_ids_t)); + rrc_ue_ngap_ids_p->ue_initial_id = ue_context_pP->ue_context.ue_initial_id; + rrc_ue_ngap_ids_p->gNB_ue_ngap_id = UE_INITIAL_ID_INVALID; + rrc_ue_ngap_ids_p->ue_rnti = ctxt_pP->rnti; + + h_rc = hashtable_insert(RC.nrrrc[ctxt_pP->module_id]->initial_id2_ngap_ids, + (hash_key_t)ue_context_pP->ue_context.ue_initial_id, + rrc_ue_ngap_ids_p); + + if (h_rc != HASH_TABLE_OK) { + LOG_E(NGAP, "[gNB %d] Error while hashtable_insert in initial_id2_ngap_ids ue_initial_id %u\n", + ctxt_pP->module_id, + ue_context_pP->ue_context.ue_initial_id); + } + + /* Assume that cause is coded in the same way in RRC and NGap, just check that the value is in NGap range */ + AssertFatal(ue_context_pP->ue_context.establishment_cause < NGAP_RRC_CAUSE_LAST, + "Establishment cause invalid (%jd/%d) for gNB %d!", + ue_context_pP->ue_context.establishment_cause, + NGAP_RRC_CAUSE_LAST, + ctxt_pP->module_id); + NGAP_NAS_FIRST_REQ(message_p).establishment_cause = ue_context_pP->ue_context.establishment_cause; + + /* Forward NAS message */ + NGAP_NAS_FIRST_REQ(message_p).nas_pdu.buffer = rrcSetupComplete->dedicatedNAS_Message.buf; + NGAP_NAS_FIRST_REQ(message_p).nas_pdu.length = rrcSetupComplete->dedicatedNAS_Message.size; + // extract_imsi(NGAP_NAS_FIRST_REQ (message_p).nas_pdu.buffer, + // NGAP_NAS_FIRST_REQ (message_p).nas_pdu.length, + // ue_context_pP); + + /* Fill UE identities with available information */ + NGAP_NAS_FIRST_REQ(message_p).ue_identity.presenceMask = NGAP_UE_IDENTITIES_NONE; + /* Fill s-TMSI */ + NGAP_NAS_FIRST_REQ(message_p).ue_identity.s_tmsi.amf_set_id = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.amf_set_id; + NGAP_NAS_FIRST_REQ(message_p).ue_identity.s_tmsi.amf_pointer = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.amf_pointer; + NGAP_NAS_FIRST_REQ(message_p).ue_identity.s_tmsi.m_tmsi = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.fiveg_tmsi; + + /* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */ + int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1; + NGAP_NAS_FIRST_REQ(message_p).selected_plmn_identity = selected_plmn_identity; + + if (rrcSetupComplete->registeredAMF != NULL) { + NR_RegisteredAMF_t *r_amf = rrcSetupComplete->registeredAMF; + NGAP_NAS_FIRST_REQ(message_p).ue_identity.presenceMask |= NGAP_UE_IDENTITIES_guami; + + if (r_amf->plmn_Identity != NULL) { + if ((r_amf->plmn_Identity->mcc != NULL) && (r_amf->plmn_Identity->mcc->list.count > 0)) { + /* Use first indicated PLMN MCC if it is defined */ + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mcc = *r_amf->plmn_Identity->mcc->list.array[selected_plmn_identity]; + LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n", + ctxt_pP->module_id, + NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.mcc, + ue_context_pP->ue_context.rnti); + } + + if (r_amf->plmn_Identity->mnc.list.count > 0) { + /* Use first indicated PLMN MNC if it is defined */ + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mnc = *r_amf->plmn_Identity->mnc.list.array[selected_plmn_identity]; + LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n", + ctxt_pP->module_id, + NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.mnc, + ue_context_pP->ue_context.rnti); + } + } else { + /* TODO */ + } + + /* amf_Identifier */ + uint32_t amf_Id = BIT_STRING_to_uint32(&r_amf->amf_Identifier); + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_region_id = amf_Id >> 16; + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_set_id = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.amf_set_id; + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_pointer = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.amf_pointer; + + ue_context_pP->ue_context.ue_guami.mcc = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mcc; + ue_context_pP->ue_context.ue_guami.mnc = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mnc; + ue_context_pP->ue_context.ue_guami.mnc_len = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mnc_len; + ue_context_pP->ue_context.ue_guami.amf_region_id = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_region_id; + ue_context_pP->ue_context.ue_guami.amf_set_id = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_set_id; + ue_context_pP->ue_context.ue_guami.amf_pointer = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_pointer; + + MSC_LOG_TX_MESSAGE(MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)&message_p->ittiMsg.ngap_nas_first_req, + sizeof(ngap_nas_first_req_t), + MSC_AS_TIME_FMT" NGAP_NAS_FIRST_REQ gNB %u UE %x", + MSC_AS_TIME_ARGS(ctxt_pP), + ctxt_pP->module_id, + ctxt_pP->rnti); + LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUAMI amf_set_id %u amf_region_id %u ue %x\n", + ctxt_pP->module_id, + NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.amf_set_id, + NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.amf_region_id, + ue_context_pP->ue_context.rnti); + } + + itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, message_p); +} + +//------------------------------------------------------------------------------ +int +rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +) +//------------------------------------------------------------------------------ +{ + uint16_t ue_initial_id; + uint32_t gNB_ue_ngap_id; + rrc_gNB_ue_context_t *ue_context_p = NULL; + protocol_ctxt_t ctxt; + uint8_t pdu_sessions_done = 0; + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req; + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp; + uint8_t inde_list[NR_NB_RB_MAX - 3]= {0}; + int ret = 0; + + ue_initial_id = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_initial_id; + gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).gNB_ue_ngap_id; + + ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id); + LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u \n", + instance, msg_name, ue_initial_id, gNB_ue_ngap_id); + + if (ue_context_p == NULL) { + /* Can not associate this message to an UE index, send a failure to NGAP and discard it! */ + MessageDef *msg_fail_p = NULL; + LOG_W(NR_RRC, "[gNB %ld] In NGAP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id); + msg_fail_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_INITIAL_CONTEXT_SETUP_FAIL); + NGAP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; + // TODO add failure cause when defined! + itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p); + return (-1); + } else { + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).gNB_ue_ngap_id; + ue_context_p->ue_context.amf_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).amf_ue_ngap_id; + ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nas_pdu_flag; + + uint8_t nb_pdusessions_tosetup = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_pdusessions; + if (nb_pdusessions_tosetup != 0) { + memset(&create_tunnel_req, 0, sizeof(gtpv1u_gnb_create_tunnel_req_t)); + for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { + if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE) + continue; + ue_context_p->ue_context.pduSession[i].status = PDU_SESSION_STATUS_NEW; + ue_context_p->ue_context.pduSession[i].param = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done]; + create_tunnel_req.pdusession_id[pdu_sessions_done] = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done].pdusession_id; + create_tunnel_req.incoming_rb_id[pdu_sessions_done] = i+1; + create_tunnel_req.upf_NGu_teid[pdu_sessions_done] = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done].gtp_teid; + create_tunnel_req.upf_addr[pdu_sessions_done].length = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done].upf_addr.length; + memcpy(create_tunnel_req.upf_addr[pdu_sessions_done].buffer, + NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done].upf_addr.buffer, + sizeof(uint8_t)*20); + LOG_I(NR_RRC, "PDUSESSION SETUP: local index %d teid %u, pdusession id %d \n", + i, + create_tunnel_req.upf_NGu_teid[pdu_sessions_done], + create_tunnel_req.pdusession_id[pdu_sessions_done]); + inde_list[pdu_sessions_done] = i; + pdu_sessions_done++; + + if(pdu_sessions_done >= nb_pdusessions_tosetup) { + break; + } + } + + ue_context_p->ue_context.nb_of_pdusessions = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_pdusessions; + create_tunnel_req.rnti = ue_context_p->ue_context.rnti; + create_tunnel_req.num_tunnels = pdu_sessions_done; + + ret = gtpv1u_create_ngu_tunnel( + instance, + &create_tunnel_req, + &create_tunnel_resp); + if (ret != 0) { + LOG_E(NR_RRC,"rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti); + ue_context_p->ue_context.ue_release_timer_ng = 1; + ue_context_p->ue_context.ue_release_timer_thres_ng = 100; + ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 0; + ue_context_p->ue_context.ul_failure_timer = 20000; + ue_context_p->ue_context.ul_failure_timer = 0; + return (0); + } + + nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + &ctxt, + &create_tunnel_resp, + &inde_list[0]); + ue_context_p->ue_context.setup_pdu_sessions += nb_pdusessions_tosetup; + ue_context_p->ue_context.established_pdu_sessions_flag = 1; + } + + /* NAS PDU */ + if (NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu_flag == 1) { + ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu_flag; + ue_context_p->ue_context.nas_pdu.length = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.length; + ue_context_p->ue_context.nas_pdu.buffer = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.buffer; + } + + /* security */ + rrc_gNB_process_security(&ctxt, ue_context_p, &(NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_capabilities)); + process_gNB_security_key ( + &ctxt, + ue_context_p, + NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_key); + + /* configure only integrity, ciphering comes after receiving SecurityModeComplete */ + nr_rrc_pdcp_config_security(&ctxt, ue_context_p, 0); + + rrc_gNB_generate_SecurityModeCommand (&ctxt, ue_context_p); + + // in case, send the S1SP initial context response if it is not sent with the attach complete message + if (ue_context_p->ue_context.StatusRrc == NR_RRC_RECONFIGURED) { + LOG_I(NR_RRC, "Sending rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", ue_context_p->ue_context.reestablishment_cause); + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(&ctxt,ue_context_p); + } + + return 0; + } +} + +//------------------------------------------------------------------------------ +void +rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP +) +//------------------------------------------------------------------------------ +{ + MessageDef *msg_p = NULL; + int pdusession; + int pdu_sessions_done = 0; + int pdu_sessions_failed = 0; + int qos_flow_index = 0; + msg_p = itti_alloc_new_message (TASK_RRC_ENB, 0, NGAP_INITIAL_CONTEXT_SETUP_RESP); + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + + for (pdusession = 0; pdusession < ue_context_pP->ue_context.nb_of_pdusessions; pdusession++) { + if (ue_context_pP->ue_context.pduSession[pdusession].status == PDU_SESSION_STATUS_DONE) { + pdu_sessions_done++; + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions[pdusession].pdusession_id = ue_context_pP->ue_context.pduSession[pdusession].param.pdusession_id; + // TODO add other information from S1-U when it will be integrated + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions[pdusession].gtp_teid = ue_context_pP->ue_context.gnb_gtp_teid[pdusession]; + memcpy(NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions[pdusession].gNB_addr.buffer , ue_context_pP->ue_context.gnb_gtp_addrs[pdusession].buffer, 20); + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions[pdusession].gNB_addr.length = 4; + ue_context_pP->ue_context.pduSession[pdusession].status = PDU_SESSION_STATUS_ESTABLISHED; + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions[pdusession].nb_of_qos_flow = ue_context_pP->ue_context.pduSession[pdusession].param.nb_qos; + for (qos_flow_index = 0; qos_flow_index < ue_context_pP->ue_context.pduSession[pdusession].param.nb_qos; qos_flow_index++) { + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions[pdusession].associated_qos_flows[qos_flow_index].qfi = + ue_context_pP->ue_context.pduSession[pdusession].param.qos[qos_flow_index].qfi; + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions[pdusession].associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; + } + } else { + pdu_sessions_failed++; + ue_context_pP->ue_context.pduSession[pdusession].status = PDU_SESSION_STATUS_FAILED; + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions_failed[pdusession].pdusession_id = ue_context_pP->ue_context.pduSession[pdusession].param.pdusession_id; + // TODO add cause when it will be integrated + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions_failed[pdusession].cause = NGAP_Cause_PR_radioNetwork; + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).pdusessions_failed[pdusession].cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID; + } + } + + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_S1AP_ENB, + (const char *)&NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p), + sizeof(ngap_initial_context_setup_resp_t), + MSC_AS_TIME_FMT" INITIAL_CONTEXT_SETUP_RESP UE %X eNB_ue_s1ap_id %u e_rabs:%u succ %u fail", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_id_rnti, + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).gNB_ue_ngap_id, + pdu_sessions_done, pdu_sessions_failed); + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_pdusessions = pdu_sessions_done; + NGAP_INITIAL_CONTEXT_SETUP_RESP (msg_p).nb_of_pdusessions_failed = pdu_sessions_failed; + itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p); +} + +static NR_CipheringAlgorithm_t rrc_gNB_select_ciphering( + const protocol_ctxt_t *const ctxt_pP, + uint16_t algorithms) +{ + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + int i; + /* preset nea0 as fallback */ + int ret = 0; + + /* Select ciphering algorithm based on gNB configuration file and + * UE's supported algorithms. + * We take the first from the list that is supported by the UE. + * The ordering of the list comes from the configuration file. + */ + for (i = 0; i < rrc->security.ciphering_algorithms_count; i++) { + int nea_mask[4] = { + 0, + NGAP_ENCRYPTION_NEA1_MASK, + NGAP_ENCRYPTION_NEA2_MASK, + NGAP_ENCRYPTION_NEA3_MASK + }; + if (rrc->security.ciphering_algorithms[i] == 0) { + /* nea0 */ + break; + } + if (algorithms & nea_mask[rrc->security.ciphering_algorithms[i]]) { + ret = rrc->security.ciphering_algorithms[i]; + break; + } + } + + LOG_I(RRC, "selecting ciphering algorithm %d\n", ret); + + return ret; +} + +static e_NR_IntegrityProtAlgorithm rrc_gNB_select_integrity( + const protocol_ctxt_t *const ctxt_pP, + uint16_t algorithms) +{ + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + int i; + /* preset nia0 as fallback */ + int ret = 0; + + /* Select integrity algorithm based on gNB configuration file and + * UE's supported algorithms. + * We take the first from the list that is supported by the UE. + * The ordering of the list comes from the configuration file. + */ + for (i = 0; i < rrc->security.integrity_algorithms_count; i++) { + int nia_mask[4] = { + 0, + NGAP_INTEGRITY_NIA1_MASK, + NGAP_INTEGRITY_NIA2_MASK, + NGAP_INTEGRITY_NIA3_MASK + }; + if (rrc->security.integrity_algorithms[i] == 0) { + /* nia0 */ + break; + } + if (algorithms & nia_mask[rrc->security.integrity_algorithms[i]]) { + ret = rrc->security.integrity_algorithms[i]; + break; + } + } + + LOG_I(RRC, "selecting integrity algorithm %d\n", ret); + + return ret; +} + +int +rrc_gNB_process_security( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + ngap_security_capabilities_t *security_capabilities_pP +) { + boolean_t changed = FALSE; + NR_CipheringAlgorithm_t cipheringAlgorithm; + e_NR_IntegrityProtAlgorithm integrityProtAlgorithm; + /* Save security parameters */ + ue_context_pP->ue_context.security_capabilities = *security_capabilities_pP; + // translation + LOG_D(NR_RRC, + "[gNB %d] NAS security_capabilities.encryption_algorithms %u AS ciphering_algorithm %lu NAS security_capabilities.integrity_algorithms %u AS integrity_algorithm %u\n", + ctxt_pP->module_id, + ue_context_pP->ue_context.security_capabilities.nRencryption_algorithms, + (unsigned long)ue_context_pP->ue_context.ciphering_algorithm, + ue_context_pP->ue_context.security_capabilities.nRintegrity_algorithms, + ue_context_pP->ue_context.integrity_algorithm); + /* Select relevant algorithms */ + cipheringAlgorithm = rrc_gNB_select_ciphering(ctxt_pP, ue_context_pP->ue_context.security_capabilities.nRencryption_algorithms); + + if (ue_context_pP->ue_context.ciphering_algorithm != cipheringAlgorithm) { + ue_context_pP->ue_context.ciphering_algorithm = cipheringAlgorithm; + changed = TRUE; + } + + integrityProtAlgorithm = rrc_gNB_select_integrity(ctxt_pP, ue_context_pP->ue_context.security_capabilities.nRintegrity_algorithms); + + if (ue_context_pP->ue_context.integrity_algorithm != integrityProtAlgorithm) { + ue_context_pP->ue_context.integrity_algorithm = integrityProtAlgorithm; + changed = TRUE; + } + + LOG_I (NR_RRC, "[gNB %d][UE %x] Selected security algorithms (%p): %lx, %x, %s\n", + ctxt_pP->module_id, + ue_context_pP->ue_context.rnti, + security_capabilities_pP, + (unsigned long)cipheringAlgorithm, + integrityProtAlgorithm, + changed ? "changed" : "same"); + return changed; +} + +//------------------------------------------------------------------------------ +int +rrc_gNB_process_NGAP_DOWNLINK_NAS( + MessageDef *msg_p, + const char *msg_name, + instance_t instance, + mui_t *rrc_gNB_mui +) +//------------------------------------------------------------------------------ +{ + uint16_t ue_initial_id; + uint32_t gNB_ue_ngap_id; + uint32_t length; + uint8_t *buffer; + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + protocol_ctxt_t ctxt; + memset(&ctxt, 0, sizeof(protocol_ctxt_t)); + ue_initial_id = NGAP_DOWNLINK_NAS (msg_p).ue_initial_id; + gNB_ue_ngap_id = NGAP_DOWNLINK_NAS (msg_p).gNB_ue_ngap_id; + ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id); + LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u\n", + instance, + msg_name, + ue_initial_id, + gNB_ue_ngap_id); + + if (ue_context_p == NULL) { + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_NGAP_GNB, + NULL, + 0, + MSC_AS_TIME_FMT" DOWNLINK-NAS UE initial id %u gNB_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + ue_initial_id, + gNB_ue_ngap_id); + /* Can not associate this message to an UE index, send a failure to NGAP and discard it! */ + MessageDef *msg_fail_p; + LOG_W(NR_RRC, "[gNB %ld] In NGAP_DOWNLINK_NAS: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id); + msg_fail_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_NAS_NON_DELIVERY_IND); + NGAP_NAS_NON_DELIVERY_IND (msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; + NGAP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.length = NGAP_DOWNLINK_NAS (msg_p).nas_pdu.length; + NGAP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.buffer = NGAP_DOWNLINK_NAS (msg_p).nas_pdu.buffer; + // TODO add failure cause when defined! + MSC_LOG_TX_MESSAGE( + MSC_RRC_ENB, + MSC_NGAP_GNB, + (const char *)NULL, + 0, + MSC_AS_TIME_FMT" NGAP_NAS_NON_DELIVERY_IND UE initial id %u gNB_ue_ngap_id %u (ue ctxt !found)", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + ue_initial_id, + gNB_ue_ngap_id); + itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p); + return (-1); + } else { + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + + /* Is it the first income from NGAP ? */ + if (ue_context_p->ue_context.gNB_ue_ngap_id == 0) { + ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_DOWNLINK_NAS (msg_p).gNB_ue_ngap_id; + } + + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_NGAP_GNB, + (const char *)NULL, + 0, + MSC_AS_TIME_FMT" DOWNLINK-NAS UE initial id %u gNB_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + ue_initial_id, + NGAP_DOWNLINK_NAS (msg_p).gNB_ue_ngap_id); + /* Create message for PDCP (DLInformationTransfer_t) */ + length = do_NR_DLInformationTransfer ( + instance, + &buffer, + rrc_gNB_get_next_transaction_identifier (instance), + NGAP_DOWNLINK_NAS (msg_p).nas_pdu.length, + NGAP_DOWNLINK_NAS (msg_p).nas_pdu.buffer); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, buffer, length, "[MSG] RRC DL Information Transfer\n"); + /* + * switch UL or DL NAS message without RRC piggybacked to SRB2 if active. + */ + switch (RC.nrrrc[ctxt.module_id]->node_type) { + case ngran_gNB_CU: + /* Transfer data to PDCP */ + nr_rrc_data_req ( + &ctxt, + ue_context_p->ue_context.Srb2.Active == 1 ? ue_context_p->ue_context.Srb2.Srb_info.Srb_id : ue_context_p->ue_context.Srb1.Srb_info.Srb_id, + (*rrc_gNB_mui)++, + SDU_CONFIRM_NO, + length, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + break; + + case ngran_gNB_DU: + // nothing to do for DU + AssertFatal(1==0,"nothing to do for DU\n"); + break; + + case ngran_gNB: + { + // rrc_mac_config_req_gNB +#ifdef ITTI_SIM + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, length); + memcpy (message_buffer, buffer, length); + MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = length; + itti_send_msg_to_task (TASK_RRC_UE_SIM, instance, message_p); + LOG_I(NR_RRC, "Send DL NAS message \n"); +#else + /* Transfer data to PDCP */ + nr_rrc_data_req ( + &ctxt, + ue_context_p->ue_context.Srb2.Active == 1 ? ue_context_p->ue_context.Srb2.Srb_info.Srb_id : ue_context_p->ue_context.Srb1.Srb_info.Srb_id, + (*rrc_gNB_mui)++, + SDU_CONFIRM_NO, + length, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif + } + break; + + default : + LOG_W(NR_RRC, "Unknown node type %d\n", RC.nrrrc[ctxt.module_id]->node_type); + } + return (0); + } +} + +//------------------------------------------------------------------------------ +void +rrc_gNB_send_NGAP_UPLINK_NAS( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + NR_UL_DCCH_Message_t *const ul_dcch_msg +) +//------------------------------------------------------------------------------ +{ + uint32_t pdu_length; + uint8_t *pdu_buffer; + MessageDef *msg_p; + NR_ULInformationTransfer_t *ulInformationTransfer = ul_dcch_msg->message.choice.c1->choice.ulInformationTransfer; + + if (ulInformationTransfer->criticalExtensions.present == NR_ULInformationTransfer__criticalExtensions_PR_ulInformationTransfer) { + pdu_length = ulInformationTransfer->criticalExtensions.choice.ulInformationTransfer->dedicatedNAS_Message->size; + pdu_buffer = ulInformationTransfer->criticalExtensions.choice.ulInformationTransfer->dedicatedNAS_Message->buf; + msg_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_UPLINK_NAS); + NGAP_UPLINK_NAS (msg_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + NGAP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length; + NGAP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer; + // extract_imsi(NGAP_UPLINK_NAS (msg_p).nas_pdu.buffer, + // NGAP_UPLINK_NAS (msg_p).nas_pdu.length, + // ue_context_pP); + itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p); + LOG_I(NR_RRC,"Send RRC GNB UL Information Transfer \n"); + } +} + +//------------------------------------------------------------------------------ +void +rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid +) +//------------------------------------------------------------------------------ +{ + MessageDef *msg_p; + int pdu_sessions_done = 0; + int pdu_sessions_failed = 0; + int pdusession; + int qos_flow_index; + + msg_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_RESP); + NGAP_PDUSESSION_SETUP_RESP(msg_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + + for (pdusession = 0; pdusession < ue_context_pP->ue_context.setup_pdu_sessions; pdusession++) { + // if (xid == ue_context_pP->ue_context.pdusession[pdusession].xid) { + if (ue_context_pP->ue_context.pduSession[pdusession].status == PDU_SESSION_STATUS_DONE) { + NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].pdusession_id = ue_context_pP->ue_context.pduSession[pdusession].param.pdusession_id; + // NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].pdusession_id = 1; + NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].nb_of_qos_flow = ue_context_pP->ue_context.pduSession[pdusession].param.nb_qos; + NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].gtp_teid = ue_context_pP->ue_context.gnb_gtp_teid[pdusession]; + NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].gNB_addr.pdu_session_type = PDUSessionType_ipv4; + NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].gNB_addr.length = ue_context_pP->ue_context.gnb_gtp_addrs[pdusession].length; + memcpy(NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].gNB_addr.buffer, + ue_context_pP->ue_context.gnb_gtp_addrs[pdusession].buffer, sizeof(uint8_t)*20); + for (qos_flow_index = 0; qos_flow_index < NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].nb_of_qos_flow; qos_flow_index++) { + NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].associated_qos_flows[qos_flow_index].qfi = + ue_context_pP->ue_context.pduSession[pdusession].param.qos[qos_flow_index].qfi; + NGAP_PDUSESSION_SETUP_RESP(msg_p).pdusessions[pdusession].associated_qos_flows[qos_flow_index].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL; + } + + ue_context_pP->ue_context.pduSession[pdusession].status = PDU_SESSION_STATUS_ESTABLISHED; + LOG_I (NR_RRC,"gnb_gtp_addr (msg index %d, pdu_sessions index %d, status %d, xid %d): nb_of_pdusessions %d, pdusession_id %d, teid: %u, addr: %d.%d.%d.%d \n ", + pdu_sessions_done, pdusession, ue_context_pP->ue_context.pduSession[pdusession].status, xid, + ue_context_pP->ue_context.nb_of_pdusessions, + NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].pdusession_id, + NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gtp_teid, + NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gNB_addr.buffer[0], + NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gNB_addr.buffer[1], + NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gNB_addr.buffer[2], + NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions[pdu_sessions_done].gNB_addr.buffer[3]); + pdu_sessions_done++; + } else if ((ue_context_pP->ue_context.pduSession[pdusession].status == PDU_SESSION_STATUS_NEW) || + (ue_context_pP->ue_context.pduSession[pdusession].status == PDU_SESSION_STATUS_ESTABLISHED)) { + LOG_D (NR_RRC,"PDU-SESSION is NEW or already ESTABLISHED\n"); + } else { /* to be improved */ + ue_context_pP->ue_context.pduSession[pdusession].status = PDU_SESSION_STATUS_FAILED; + NGAP_PDUSESSION_SETUP_RESP (msg_p).pdusessions_failed[pdu_sessions_failed].pdusession_id = ue_context_pP->ue_context.pduSession[pdusession].param.pdusession_id; + pdu_sessions_failed++; + // TODO add cause when it will be integrated + } + NGAP_PDUSESSION_SETUP_RESP(msg_p).nb_of_pdusessions = pdu_sessions_done; + NGAP_PDUSESSION_SETUP_RESP(msg_p).nb_of_pdusessions_failed = pdu_sessions_failed; + // } else { + // LOG_D(NR_RRC,"xid does not corresponds (context pdu_sessions index %d, status %d, xid %d/%d) \n ", + // pdusession, ue_context_pP->ue_context.pdusession[pdusession].status, xid, ue_context_pP->ue_context.pdusession[pdusession].xid); + // } + } + + if ((pdu_sessions_done > 0) ) { + LOG_I(NR_RRC,"NGAP_PDUSESSION_SETUP_RESP: sending the message: nb_of_pdusessions %d, total pdu_sessions %d, index %d\n", + ue_context_pP->ue_context.nb_of_pdusessions, ue_context_pP->ue_context.setup_pdu_sessions, pdusession); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_NGAP_GNB, + (const char *)&NGAP_PDUSESSION_SETUP_RESP (msg_p), + sizeof(ngap_pdusession_setup_resp_t), + MSC_AS_TIME_FMT" PDUSESSION_SETUP_RESP UE %X gNB_ue_ngap_id %u pdu_sessions:%u succ %u fail", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_id_rnti, + NGAP_PDUSESSION_SETUP_RESP (msg_p).gNB_ue_ngap_id, + pdu_sessions_done, pdu_sessions_failed); + itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p); + } + + for(int i = 0; i < NB_RB_MAX; i++) { + ue_context_pP->ue_context.pduSession[i].xid = -1; + } + + return; +} + +//------------------------------------------------------------------------------ +int +rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +) +//------------------------------------------------------------------------------ +{ + uint16_t ue_initial_id; + uint32_t gNB_ue_ngap_id; + rrc_gNB_ue_context_t *ue_context_p = NULL; + protocol_ctxt_t ctxt; + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req; + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp; + uint8_t pdu_sessions_done; + uint8_t inde_list[NR_NB_RB_MAX - 3]= {0}; + int ret = 0; + + ue_initial_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).ue_initial_id; + gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; + ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id); + LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u \n", + instance, msg_name, ue_initial_id, gNB_ue_ngap_id); + + if (ue_context_p == NULL) { + MessageDef *msg_fail_p = NULL; + LOG_W(NR_RRC, "[gNB %ld] In NGAP_PDUSESSION_SETUP_REQ: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id); + msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_REQUEST_FAIL); + NGAP_PDUSESSION_SETUP_REQ(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; + // TODO add failure cause when defined! + itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p); + return (-1); + } else { + memset(&create_tunnel_req, 0, sizeof(gtpv1u_gnb_create_tunnel_req_t)); + uint8_t nb_pdusessions_tosetup = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup; + pdu_sessions_done = 0; + + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { + if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE) + continue; + ue_context_p->ue_context.pduSession[i].status = PDU_SESSION_STATUS_NEW; + ue_context_p->ue_context.pduSession[i].param = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done]; + create_tunnel_req.pdusession_id[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].pdusession_id; + create_tunnel_req.incoming_rb_id[pdu_sessions_done]= i+1; + create_tunnel_req.upf_NGu_teid[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].gtp_teid; + memcpy(create_tunnel_req.upf_addr[pdu_sessions_done].buffer, + NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.buffer, + sizeof(uint8_t)*20); + create_tunnel_req.upf_addr[pdu_sessions_done].length = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.length; + LOG_I(NR_RRC,"NGAP PDUSESSION SETUP REQ: local index %d teid %u, pdusession id %d \n", + i, + create_tunnel_req.upf_NGu_teid[pdu_sessions_done], + create_tunnel_req.pdusession_id[pdu_sessions_done]); + inde_list[pdu_sessions_done] = i; + pdu_sessions_done++; + + if(pdu_sessions_done >= nb_pdusessions_tosetup) { + break; + } + } + + ue_context_p->ue_context.nb_of_pdusessions = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup; + ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; + ue_context_p->ue_context.amf_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).amf_ue_ngap_id; + create_tunnel_req.rnti = ue_context_p->ue_context.rnti; + create_tunnel_req.num_tunnels = pdu_sessions_done; + + ret = gtpv1u_create_ngu_tunnel( + instance, + &create_tunnel_req, + &create_tunnel_resp); + if (ret != 0) { + LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti); + ue_context_p->ue_context.ue_release_timer_ng = 1; + ue_context_p->ue_context.ue_release_timer_thres_ng = 100; + ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 0; + ue_context_p->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ + // rrc_gNB_free_UE(ctxt.module_id,ue_context_p); + ue_context_p->ue_context.ul_failure_timer = 0; + return (0); + } + nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + &ctxt, + &create_tunnel_resp, + &inde_list[0]); + ue_context_p->ue_context.setup_pdu_sessions += nb_pdusessions_tosetup; + + // TEST + // ue_context_p->ue_context.pdusession[0].status = PDU_SESSION_STATUS_DONE; + // rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(&ctxt, ue_context_p, 0); + rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p); + return(0); + } +} + +void +rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ( + const module_id_t gnb_mod_idP, + const rrc_gNB_ue_context_t *const ue_context_pP, + const ngap_Cause_t causeP, + const long cause_valueP) +//------------------------------------------------------------------------------ +{ + if (ue_context_pP == NULL) { + LOG_E(RRC, "[gNB] In NGAP_UE_CONTEXT_RELEASE_REQ: invalid UE\n"); + } else { + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, + MSC_NGAP_GNB, + NULL, + 0, + "0 NGAP_UE_CONTEXT_RELEASE_REQ gNB_ue_ngap_id 0x%06"PRIX32" ", + ue_context_pP->ue_context.gNB_ue_ngap_id); + MessageDef *msg_context_release_req_p = NULL; + msg_context_release_req_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_REQ); + NGAP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + NGAP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).cause = causeP; + NGAP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).cause_value = cause_valueP; + NGAP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).nb_of_pdusessions = ue_context_pP->ue_context.setup_pdu_sessions; + for (int pdusession = 0; pdusession < ue_context_pP->ue_context.setup_pdu_sessions; pdusession++) { + NGAP_UE_CONTEXT_RELEASE_REQ(msg_context_release_req_p).pdusessions[pdusession].pdusession_id = ue_context_pP->ue_context.pduSession[pdusession].param.pdusession_id; + } + itti_send_msg_to_task(TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_mod_idP), msg_context_release_req_p); + } +} +/*------------------------------------------------------------------------------*/ +int +rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ ( + MessageDef *msg_p, + const char *msg_name, + instance_t instance) +{ + uint32_t gNB_ue_ngap_id; + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + gNB_ue_ngap_id = NGAP_UE_CONTEXT_RELEASE_REQ(msg_p).gNB_ue_ngap_id; + ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, UE_INITIAL_ID_INVALID, gNB_ue_ngap_id); + + if (ue_context_p == NULL) { + /* Can not associate this message to an UE index, send a failure to ngAP and discard it! */ + MessageDef *msg_fail_p; + LOG_W(RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_REQ: unknown UE from gNB_ue_ngap_id (%u)\n", + instance, + gNB_ue_ngap_id); + msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_RESP); /* TODO change message ID. */ + NGAP_UE_CONTEXT_RELEASE_RESP(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; + // TODO add failure cause when defined! + itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p); + return (-1); + } else { + /* TODO release context. */ + /* Send the response */ + { + MessageDef *msg_resp_p; + msg_resp_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_RESP); + NGAP_UE_CONTEXT_RELEASE_RESP(msg_resp_p).gNB_ue_ngap_id = gNB_ue_ngap_id; + itti_send_msg_to_task(TASK_NGAP, instance, msg_resp_p); + } + return (0); + } +} + +//----------------------------------------------------------------------------- +/* +* Process the NG command NGAP_UE_CONTEXT_RELEASE_COMMAND, sent by AMF. +* The gNB should remove all pdu session, NG context, and other context of the UE. +*/ +int +rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND( + MessageDef *msg_p, + const char *msg_name, + instance_t instance) { + //----------------------------------------------------------------------------- + uint32_t gNB_ue_ngap_id = 0; + protocol_ctxt_t ctxt; + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + struct rrc_ue_ngap_ids_s *rrc_ue_ngap_ids = NULL; + gNB_ue_ngap_id = NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; + ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, UE_INITIAL_ID_INVALID, gNB_ue_ngap_id); + + if (ue_context_p == NULL) { + /* Can not associate this message to an UE index */ + MessageDef *msg_complete_p = NULL; + LOG_W(NR_RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from gNB_ue_ngap_id (%u)\n", + instance, + gNB_ue_ngap_id); + MSC_LOG_EVENT(MSC_RRC_GNB, "0 NGAP_UE_CONTEXT_RELEASE_COMPLETE gNB_ue_ngap_id 0x%06"PRIX32" context not found", + gNB_ue_ngap_id); + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, + MSC_NGAP_GNB, + NULL, + 0, + "0 NGAP_UE_CONTEXT_RELEASE_COMPLETE gNB_ue_ngap_id 0x%06"PRIX32" ", + gNB_ue_ngap_id); + msg_complete_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE); + NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).gNB_ue_ngap_id = gNB_ue_ngap_id; + itti_send_msg_to_task(TASK_NGAP, instance, msg_complete_p); + rrc_ue_ngap_ids = rrc_gNB_NGAP_get_ue_ids(RC.nrrrc[instance], UE_INITIAL_ID_INVALID, gNB_ue_ngap_id); + + if (rrc_ue_ngap_ids != NULL) { + rrc_gNB_NGAP_remove_ue_ids(RC.nrrrc[instance], rrc_ue_ngap_ids); + } + + return -1; + } else { + ue_context_p->ue_context.ue_release_timer_ng = 0; + ue_context_p->ue_context.ue_release_timer_thres_rrc = 1000; + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + ctxt.eNB_index = 0; + rrc_gNB_generate_RRCRelease(&ctxt, ue_context_p); + return 0; + } +} + +void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE( + instance_t instance, + uint32_t gNB_ue_ngap_id) { + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, MSC_NGAP_GNB, NULL, 0, + "0 NGAP_UE_CONTEXT_RELEASE_COMPLETE gNB_ue_ngap_id 0x%06"PRIX32" ", + gNB_ue_ngap_id); + MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_COMPLETE); + NGAP_UE_CONTEXT_RELEASE_COMPLETE(msg).gNB_ue_ngap_id = gNB_ue_ngap_id; + itti_send_msg_to_task(TASK_NGAP, instance, msg); +} + +//------------------------------------------------------------------------------ +/* +* Remove UE ids (ue_initial_id and ng_id) from hashtables. +*/ +void +rrc_gNB_NGAP_remove_ue_ids( + gNB_RRC_INST *const rrc_instance_pP, + struct rrc_ue_ngap_ids_s *const ue_ids_pP +) +//------------------------------------------------------------------------------ +{ + hashtable_rc_t h_rc; + + if (rrc_instance_pP == NULL) { + LOG_E(NR_RRC, "Bad NR RRC instance\n"); + return; + } + + if (ue_ids_pP == NULL) { + LOG_E(NR_RRC, "Trying to free a NULL NGAP UE IDs\n"); + return; + } + + const uint16_t ue_initial_id = ue_ids_pP->ue_initial_id; + const uint32_t gNB_ue_ngap_id = ue_ids_pP->gNB_ue_ngap_id; + + if (gNB_ue_ngap_id > 0) { + h_rc = hashtable_remove(rrc_instance_pP->ngap_id2_ngap_ids, (hash_key_t)gNB_ue_ngap_id); + + if (h_rc != HASH_TABLE_OK) { + LOG_W(NR_RRC, "NGAP Did not find entry in hashtable ngap_id2_ngap_ids for gNB_ue_ngap_id %u\n", gNB_ue_ngap_id); + } else { + LOG_W(NR_RRC, "NGAP removed entry in hashtable ngap_id2_ngap_ids for gNB_ue_ngap_id %u\n", gNB_ue_ngap_id); + } + } + + if (ue_initial_id != UE_INITIAL_ID_INVALID) { + h_rc = hashtable_remove(rrc_instance_pP->initial_id2_ngap_ids, (hash_key_t)ue_initial_id); + + if (h_rc != HASH_TABLE_OK) { + LOG_W(NR_RRC, "NGAP Did not find entry in hashtable initial_id2_ngap_ids for ue_initial_id %u\n", ue_initial_id); + } else { + LOG_W(NR_RRC, "NGAP removed entry in hashtable initial_id2_ngap_ids for ue_initial_id %u\n", ue_initial_id); + } + } +} +void +rrc_gNB_send_NGAP_UE_CAPABILITIES_IND( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + NR_UL_DCCH_Message_t *const ul_dcch_msg +) +//------------------------------------------------------------------------------ +{ + NR_UE_CapabilityRAT_ContainerList_t *ueCapabilityRATContainerList = ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList; + /* 4096 is arbitrary, should be big enough */ + unsigned char buf[4096]; + unsigned char *buf2; + NR_UERadioAccessCapabilityInformation_t rac; + + if (ueCapabilityRATContainerList->list.count == 0) { + LOG_W(RRC, "[gNB %d][UE %x] bad UE capabilities\n", ctxt_pP->module_id, ue_context_pP->ue_context.rnti); + } + + asn_enc_rval_t ret = uper_encode_to_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, NULL, ueCapabilityRATContainerList, buf, 4096); + + if (ret.encoded == -1) abort(); + + memset(&rac, 0, sizeof(NR_UERadioAccessCapabilityInformation_t)); + rac.criticalExtensions.present = NR_UERadioAccessCapabilityInformation__criticalExtensions_PR_c1; + rac.criticalExtensions.choice.c1 = calloc(1,sizeof(*rac.criticalExtensions.choice.c1)); + rac.criticalExtensions.choice.c1->present = NR_UERadioAccessCapabilityInformation__criticalExtensions__c1_PR_ueRadioAccessCapabilityInformation; + rac.criticalExtensions.choice.c1->choice.ueRadioAccessCapabilityInformation = calloc(1,sizeof(NR_UERadioAccessCapabilityInformation_IEs_t)); + rac.criticalExtensions.choice.c1->choice.ueRadioAccessCapabilityInformation->ue_RadioAccessCapabilityInfo.buf = buf; + rac.criticalExtensions.choice.c1->choice.ueRadioAccessCapabilityInformation->ue_RadioAccessCapabilityInfo.size = (ret.encoded+7)/8; + rac.criticalExtensions.choice.c1->choice.ueRadioAccessCapabilityInformation->nonCriticalExtension = NULL; + /* 8192 is arbitrary, should be big enough */ + buf2 = malloc16(8192); + + if (buf2 == NULL) abort(); + + ret = uper_encode_to_buffer(&asn_DEF_NR_UERadioAccessCapabilityInformation, NULL, &rac, buf2, 8192); + + if (ret.encoded == -1) abort(); + + MessageDef *msg_p; + msg_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_UE_CAPABILITIES_IND); + NGAP_UE_CAPABILITIES_IND (msg_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + NGAP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.length = (ret.encoded+7)/8; + NGAP_UE_CAPABILITIES_IND (msg_p).ue_radio_cap.buffer = buf2; + itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p); + LOG_I(NR_RRC,"Send message to ngap: NGAP_UE_CAPABILITIES_IND\n"); +} + +//------------------------------------------------------------------------------ +void +rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid +) +//------------------------------------------------------------------------------ +{ + int pdu_sessions_released = 0; + MessageDef *msg_p; + msg_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_RELEASE_RESPONSE); + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + + for (int i = 0; i < NB_RB_MAX; i++) { + if (xid == ue_context_pP->ue_context.pduSession[i].xid) { + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).pdusession_release[pdu_sessions_released].pdusession_id = + ue_context_pP->ue_context.pduSession[i].param.pdusession_id; + pdu_sessions_released++; + //clear + memset(&ue_context_pP->ue_context.pduSession[i], 0, sizeof(pdu_session_param_t)); + } + } + + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).nb_of_pdusessions_released = pdu_sessions_released; + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).nb_of_pdusessions_failed = ue_context_pP->ue_context.nb_release_of_pdusessions; + memcpy(&(NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).pdusessions_failed[0]), &ue_context_pP->ue_context.pdusessions_release_failed[0], + sizeof(pdusession_failed_t)*ue_context_pP->ue_context.nb_release_of_pdusessions); + ue_context_pP->ue_context.setup_pdu_sessions -= pdu_sessions_released; + LOG_I(NR_RRC,"NGAP PDUSESSION RELEASE RESPONSE: GNB_UE_NGAP_ID %u release_pdu_sessions %d setup_pdu_sessions %d \n", + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).gNB_ue_ngap_id, + pdu_sessions_released, ue_context_pP->ue_context.setup_pdu_sessions); + itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p); + + //clear xid + for(int i = 0; i < NB_RB_MAX; i++) { + ue_context_pP->ue_context.pduSession[i].xid = -1; + } + + //clear release pdusessions + ue_context_pP->ue_context.nb_release_of_pdusessions = 0; + memset(&ue_context_pP->ue_context.pdusessions_release_failed[0], 0, sizeof(pdusession_failed_t)*NGAP_MAX_PDUSESSION); +} + +//------------------------------------------------------------------------------ +int +rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +) +//------------------------------------------------------------------------------ +{ + uint32_t gNB_ue_ngap_id; + rrc_gNB_ue_context_t *ue_context_p = NULL; + protocol_ctxt_t ctxt; + pdusession_release_t pdusession_release_params[NGAP_MAX_PDUSESSION]; + uint8_t nb_pdusessions_torelease; + MessageDef *msg_delete_tunnels_p = NULL; + uint8_t xid; + int i, pdusession; + uint8_t b_existed,is_existed; + uint8_t pdusession_release_drb = 0; + + memcpy(&pdusession_release_params[0], &(NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).pdusession_release_params[0]), + sizeof(pdusession_release_t)*NGAP_MAX_PDUSESSION); + gNB_ue_ngap_id = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; + nb_pdusessions_torelease = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).nb_pdusessions_torelease; + if (nb_pdusessions_torelease > NGAP_MAX_PDUSESSION) { + return -1; + } + ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, UE_INITIAL_ID_INVALID, gNB_ue_ngap_id); + LOG_I(NR_RRC, "[gNB %ld] Received %s: gNB_ue_ngap_id %u \n", instance, msg_name, gNB_ue_ngap_id); + + if (ue_context_p != NULL) { + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + xid = rrc_gNB_get_next_transaction_identifier(ctxt.module_id); + LOG_I(NR_RRC,"PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %u release_pdusessions %d \n", + NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).amf_ue_ngap_id&0x000000FFFFFFFFFF, gNB_ue_ngap_id, nb_pdusessions_torelease); + + for (pdusession = 0; pdusession < nb_pdusessions_torelease; pdusession++) { + b_existed = 0; + is_existed = 0; + + for (i = pdusession-1; i >= 0; i--) { + if (pdusession_release_params[pdusession].pdusession_id == pdusession_release_params[i].pdusession_id) { + is_existed = 1; + break; + } + } + + if(is_existed == 1) { + // pdusession_id is existed + continue; + } + + for (i = 0; i < NR_NB_RB_MAX; i++) { + if (pdusession_release_params[pdusession].pdusession_id == ue_context_p->ue_context.pduSession[i].param.pdusession_id) { + b_existed = 1; + break; + } + } + + if(b_existed == 0) { + // no pdusession_id + LOG_I(NR_RRC, "no pdusession_id \n"); + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].pdusession_id = pdusession_release_params[pdusession].pdusession_id; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause = NGAP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause_value = 30; + ue_context_p->ue_context.nb_release_of_pdusessions++; + } else { + if(ue_context_p->ue_context.pduSession[i].status == PDU_SESSION_STATUS_FAILED) { + ue_context_p->ue_context.pduSession[i].xid = xid; + continue; + } else if(ue_context_p->ue_context.pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED) { + LOG_I(NR_RRC, "RELEASE pdusession %d \n", ue_context_p->ue_context.pduSession[i].param.pdusession_id); + ue_context_p->ue_context.pduSession[i].status = PDU_SESSION_STATUS_TORELEASE; + ue_context_p->ue_context.pduSession[i].xid = xid; + pdusession_release_drb++; + } else { + // pdusession_id status NG + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].pdusession_id = pdusession_release_params[pdusession].pdusession_id; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause = NGAP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause_value = 0; + ue_context_p->ue_context.nb_release_of_pdusessions++; + } + } + } + + if(pdusession_release_drb > 0) { + //TODO RRCReconfiguration To UE + LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n"); + rrc_gNB_generate_dedicatedRRCReconfiguration_release(&ctxt, ue_context_p, xid, NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).nas_pdu.length, NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).nas_pdu.buffer); + } else { + //gtp tunnel delete + LOG_I(NR_RRC, "gtp tunnel delete \n"); + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_GNB, 0, GTPV1U_GNB_DELETE_TUNNEL_REQ); + memset(>PV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + + for(i = 0; i < NB_RB_MAX; i++) { + if(xid == ue_context_p->ue_context.pduSession[i].xid) { + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).pdusession_id[GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_pdusession++] = ue_context_p->ue_context.gnb_gtp_psi[i]; + ue_context_p->ue_context.gnb_gtp_teid[i] = 0; + memset(&ue_context_p->ue_context.gnb_gtp_addrs[i], 0, sizeof(ue_context_p->ue_context.gnb_gtp_addrs[i])); + ue_context_p->ue_context.gnb_gtp_psi[i] = 0; + } + } + + itti_send_msg_to_task(TASK_GTPV1_U, instance, msg_delete_tunnels_p); + //NGAP_PDUSESSION_RELEASE_RESPONSE + rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(&ctxt, ue_context_p, xid); + LOG_I(NR_RRC, "Send PDU Session Release Response \n"); + } + } else { + LOG_E(NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %u Error ue_context_p NULL \n", + NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).amf_ue_ngap_id&0x000000FFFFFFFFFF, NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id); + return -1; + } + + return 0; +} + +void nr_rrc_rx_tx(void) { + // check timers + + // check if UEs are lost, to remove them from upper layers + + // + +} + diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h new file mode 100644 index 0000000000..8779d62ff6 --- /dev/null +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -0,0 +1,170 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file rrc_gNB_NGAP.h + * \brief rrc NGAP procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#ifndef RRC_GNB_NGAP_H_ +#define RRC_GNB_NGAP_H_ + +#include "rrc_gNB_UE_context.h" +#include "nr_rrc_defs.h" +#include "nr_rrc_extern.h" + +#include "NR_RRCSetupComplete-IEs.h" +#include "NR_RegisteredAMF.h" +#include "NR_UL-DCCH-Message.h" + +typedef struct rrc_ue_ngap_ids_s { + /* Tree related data */ + RB_ENTRY(rrc_ue_ngap_ids_s) entries; + + // keys + uint16_t ue_initial_id; + uint32_t gNB_ue_ngap_id; + + // value + rnti_t ue_rnti; +} rrc_ue_ngap_ids_t; + +void +rrc_gNB_send_NGAP_NAS_FIRST_REQ( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + NR_RRCSetupComplete_IEs_t *rrcSetupComplete +); + +int +rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +); + +void +rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP +); + +int +rrc_gNB_process_security( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + ngap_security_capabilities_t *security_capabilities_pP +); + +int +rrc_gNB_process_NGAP_DOWNLINK_NAS( + MessageDef *msg_p, + const char *msg_name, + instance_t instance, + mui_t *rrc_gNB_mui +); + +void +rrc_gNB_send_NGAP_UPLINK_NAS( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + NR_UL_DCCH_Message_t *const ul_dcch_msg +); + +void +rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid +); + +int +rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +); + +void +rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ( + const module_id_t gnb_mod_idP, + const rrc_gNB_ue_context_t *const ue_context_pP, + const ngap_Cause_t causeP, + const long cause_valueP +); + +int +rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ ( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +); + +int +rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +); + +void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE( + instance_t instance, + uint32_t gNB_ue_ngap_id); + +void +rrc_gNB_NGAP_remove_ue_ids( + gNB_RRC_INST *const rrc_instance_pP, + struct rrc_ue_ngap_ids_s *const ue_ids_pP +); + +void +rrc_gNB_send_NGAP_UE_CAPABILITIES_IND( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + NR_UL_DCCH_Message_t *const ul_dcch_msg +); + +int +rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +); + +void +rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid +); + +void +nr_rrc_pdcp_config_security( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + const uint8_t send_security_mode_command +); + +#endif diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index b5fb50f509..ad8bd01470 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -135,10 +135,11 @@ rrc_gNB_allocate_new_UE_context( for(int i = 0; i < NB_RB_MAX; i++) { new_p->ue_context.e_rab[i].xid = -1; + new_p->ue_context.pduSession[i].xid = -1; new_p->ue_context.modify_e_rab[i].xid = -1; } - LOG_I(NR_RRC,"Returning new UE context at %p\n",new_p); + LOG_D(NR_RRC,"Returning new UE context at %p\n",new_p); return(new_p); } @@ -189,7 +190,7 @@ void rrc_gNB_free_mem_UE_context( //------------------------------------------------------------------------------ void rrc_gNB_remove_ue_context( - const protocol_ctxt_t *const ctxt_pP, + const protocol_ctxt_t *const ctxt_pP, gNB_RRC_INST *rrc_instance_pP, struct rrc_gNB_ue_context_s *ue_context_pP) //------------------------------------------------------------------------------ @@ -220,4 +221,82 @@ void rrc_gNB_remove_ue_context( PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); } +//----------------------------------------------------------------------------- +// return the ue context if there is already an UE with ue_identityP, NULL otherwise +struct rrc_gNB_ue_context_s * +rrc_gNB_ue_context_random_exist( + gNB_RRC_INST *rrc_instance_pP, + const uint64_t ue_identityP +) +//----------------------------------------------------------------------------- +{ + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head) { + if (ue_context_p->ue_context.random_ue_identity == ue_identityP) + return ue_context_p; + } + return NULL; +} +//----------------------------------------------------------------------------- +// return the ue context if there is already an UE with the same S-TMSI, NULL otherwise +struct rrc_gNB_ue_context_s * +rrc_gNB_ue_context_5g_s_tmsi_exist( + gNB_RRC_INST *rrc_instance_pP, + const uint64_t s_TMSI +) +//----------------------------------------------------------------------------- +{ + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head) { + LOG_I(NR_RRC,"checking for UE 5G S-TMSI %ld: rnti %d \n", + s_TMSI, ue_context_p->ue_context.rnti); + + if (ue_context_p->ue_context.ng_5G_S_TMSI_Part1 == s_TMSI) { + return ue_context_p; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// return a new ue context structure if ue_identityP, ctxt_pP->rnti not found in collection +struct rrc_gNB_ue_context_s * +rrc_gNB_get_next_free_ue_context( + const protocol_ctxt_t *const ctxt_pP, + gNB_RRC_INST *rrc_instance_pP, + const uint64_t ue_identityP +) +//----------------------------------------------------------------------------- +{ + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + ue_context_p = rrc_gNB_get_ue_context(rrc_instance_pP, ctxt_pP->rnti); + + if (ue_context_p == NULL) { + ue_context_p = rrc_gNB_allocate_new_UE_context(rrc_instance_pP); + + if (ue_context_p == NULL) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" Cannot create new UE context, no memory\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + return NULL; + } + + ue_context_p->ue_id_rnti = ctxt_pP->rnti; // here ue_id_rnti is just a key, may be something else + ue_context_p->ue_context.rnti = ctxt_pP->rnti; // yes duplicate, 1 may be removed + ue_context_p->ue_context.random_ue_identity = ue_identityP; + RB_INSERT(rrc_nr_ue_tree_s, &rrc_instance_pP->rrc_ue_head, ue_context_p); + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" Created new UE context uid %u\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context_p->local_uid); + return ue_context_p; + } else { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" Cannot create new UE context, already exist\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + return NULL; + } + + return(ue_context_p); +} diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.h b/openair2/RRC/NR/rrc_gNB_UE_context.h index d703c4c34c..73bd93e737 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.h +++ b/openair2/RRC/NR/rrc_gNB_UE_context.h @@ -73,10 +73,34 @@ rrc_gNB_get_ue_context( rnti_t rntiP ); +void rrc_gNB_free_mem_UE_context( + const protocol_ctxt_t *const ctxt_pP, + struct rrc_gNB_ue_context_s *const ue_context_pP +); + void rrc_gNB_remove_ue_context( const protocol_ctxt_t* const ctxt_pP, gNB_RRC_INST* rrc_instance_pP, struct rrc_gNB_ue_context_s* ue_context_pP ); +struct rrc_gNB_ue_context_s * +rrc_gNB_ue_context_random_exist( + gNB_RRC_INST *rrc_instance_pP, + const uint64_t ue_identityP +); + +struct rrc_gNB_ue_context_s * +rrc_gNB_ue_context_5g_s_tmsi_exist( + gNB_RRC_INST *rrc_instance_pP, + const uint64_t s_TMSI +); + +struct rrc_gNB_ue_context_s * +rrc_gNB_get_next_free_ue_context( + const protocol_ctxt_t *const ctxt_pP, + gNB_RRC_INST *rrc_instance_pP, + const uint64_t ue_identityP +); + #endif diff --git a/openair2/RRC/NR/rrc_gNB_internode.c b/openair2/RRC/NR/rrc_gNB_internode.c index cacff5cf5c..c4cd41c5b4 100644 --- a/openair2/RRC/NR/rrc_gNB_internode.c +++ b/openair2/RRC/NR/rrc_gNB_internode.c @@ -37,6 +37,7 @@ #include "NR_UE-CapabilityRAT-ContainerList.h" #include "LTE_UE-CapabilityRAT-ContainerList.h" #include "NR_CG-Config.h" +#include "executables/softmodem-common.h" int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m) { if (CG_ConfigInfo->criticalExtensions.present == NR_CG_ConfigInfo__criticalExtensions_PR_c1) { @@ -46,10 +47,10 @@ int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2 if (cg_ConfigInfo->ue_CapabilityInfo) { // Decode UE-CapabilityRAT-ContainerList - LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList=NULL; - UE_CapabilityRAT_ContainerList = calloc(1,sizeof(LTE_UE_CapabilityRAT_ContainerList_t)); + NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList=NULL; + UE_CapabilityRAT_ContainerList = calloc(1,sizeof(NR_UE_CapabilityRAT_ContainerList_t)); asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_LTE_UE_CapabilityRAT_ContainerList, + &asn_DEF_NR_UE_CapabilityRAT_ContainerList, (void **)&UE_CapabilityRAT_ContainerList, cg_ConfigInfo->ue_CapabilityInfo->buf, cg_ConfigInfo->ue_CapabilityInfo->size, 0, 0); @@ -95,33 +96,48 @@ int generate_CG_Config(gNB_RRC_INST *rrc, (const char *)buffer, (enc_rval.encoded+7)>>3); total_size = (enc_rval.encoded+7)>>3; - LOG_I(RRC,"Dumping NR_RRCReconfiguration message (%jd bytes)\n",(enc_rval.encoded+7)>>3); - for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { - printf("%02x",((uint8_t *)buffer)[i]); + FILE *fd; // file to be generated for nr-ue + if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0 || get_softmodem_params()->sa == 1) { + // This is for phytest only, emulate first X2 message if uecap.raw file is present + LOG_I(RRC,"Dumping NR_RRCReconfiguration message (%jd bytes)\n",(enc_rval.encoded+7)>>3); + for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { + printf("%02x",((uint8_t *)buffer)[i]); + } + printf("\n"); + fd = fopen("reconfig.raw","w"); + if (fd != NULL) { + fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); + fclose(fd); + } } - - printf("\n"); - FILE *fd = fopen("reconfig.raw","w"); - fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); - fclose(fd); + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig, NULL, (void *)rbconfig, buffer, 1024); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); + enc_rval.failed_type->name, enc_rval.encoded); cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config = calloc(1,sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config, - (const char *)buffer, - (enc_rval.encoded+7)>>3); - LOG_I(RRC,"Dumping scg_RB_Config message (%jd bytes)\n",(enc_rval.encoded+7)>>3); + (const char *)buffer, + (enc_rval.encoded+7)>>3); - for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { - printf("%02x",((uint8_t *)buffer)[i]); + + + if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0 || get_softmodem_params()->sa == 1) { + + LOG_I(RRC,"Dumping scg_RB_Config message (%jd bytes)\n",(enc_rval.encoded+7)>>3); + for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { + printf("%02x",((uint8_t *)buffer)[i]); + } + + printf("\n"); + fd = fopen("rbconfig.raw","w"); + if (fd != NULL) { + fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); + fclose(fd); + } } - - printf("\n"); - fd = fopen("rbconfig.raw","w"); - fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); - fclose(fd); + total_size = total_size + ((enc_rval.encoded+7)>>3); return(total_size); } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 22e31aa48a..3311779235 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -27,8 +27,6 @@ * \company Eurecom * \email: raymond.knopp@eurecom.fr */ -#ifndef RRC_GNB_NSA_C -#define RRC_GNB_NSA_C #include "nr_rrc_defs.h" #include "NR_RRCReconfiguration.h" @@ -36,12 +34,36 @@ //#include "NR_UE-CapabilityRAT-ContainerList.h" #include "LTE_UE-CapabilityRAT-ContainerList.h" #include "NR_CG-Config.h" +//#include "NR_SRB-ToAddModList.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/RRC/LTE/rrc_eNB_GTPV1U.h" #include "executables/softmodem-common.h" #include +#include +#include "UTIL/OSA/osa_defs.h" -void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) { +extern boolean_t nr_rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc, + uint8_t *const kUPint + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 + ,rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) { struct rrc_gNB_ue_context_s *ue_context_p = NULL; OCTET_STRING_t *ueCapabilityRAT_Container_nr=NULL; @@ -53,8 +75,8 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, LTE_UE_CapabilityRAT_Container AssertFatal((list_size=UE_CapabilityRAT_ContainerList->list.count) >= 2, "UE_CapabilityRAT_ContainerList->list.size %d < 2\n",UE_CapabilityRAT_ContainerList->list.count); for (int i=0; ilist.array[i]->rat_Type == LTE_RAT_Type_nr) ueCapabilityRAT_Container_nr = &UE_CapabilityRAT_ContainerList->list.array[i]->ueCapabilityRAT_Container; - else if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == LTE_RAT_Type_eutra_nr) ueCapabilityRAT_Container_MRDC = &UE_CapabilityRAT_ContainerList->list.array[i]->ueCapabilityRAT_Container; + if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == NR_RAT_Type_nr) ueCapabilityRAT_Container_nr = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container; + else if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == NR_RAT_Type_eutra_nr) ueCapabilityRAT_Container_MRDC = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container; } // decode and store capabilities @@ -94,28 +116,14 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, LTE_UE_CapabilityRAT_Container // dump ue_capabilities - if ( LOG_DEBUGFLAG(DEBUG_ASN1 && ueCapabilityRAT_Container_nr != NULL) ) { + if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_nr != NULL ) { xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, ue_context_p->ue_context.UE_Capability_nr); } - if ( LOG_DEBUGFLAG(DEBUG_ASN1 && ueCapabilityRAT_Container_MRDC != NULL) ) { + if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_MRDC != NULL ) { xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, ue_context_p->ue_context.UE_Capability_MRDC); } - if(cg_config_info && cg_config_info->mcg_RB_Config) { - asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_NR_RadioBearerConfig, - (void **)&ue_context_p->ue_context.rb_config, - cg_config_info->mcg_RB_Config->buf, - cg_config_info->mcg_RB_Config->size, 0, 0); - - if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"[InterNode] Failed to decode mcg_rb_config (%zu bits), size of OCTET_STRING %lu\n", - dec_rval.consumed, cg_config_info->mcg_RB_Config->size); - } - } - - xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)ue_context_p->ue_context.rb_config); rrc_add_nsa_user(rrc,ue_context_p, m); } @@ -127,10 +135,13 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ // generate nr-Config-r15 containers for LTE RRC : inside message for X2 EN-DC (CG-Config Message from 38.331) rrc_gNB_carrier_data_t *carrier=&rrc->carrier; MessageDef *msg; - msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); gtpv1u_enb_create_tunnel_req_t create_tunnel_req; gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; - protocol_ctxt_t ctxt; + protocol_ctxt_t ctxt={0}; + unsigned char *kUPenc = NULL; + unsigned char *kUPint = NULL; + int i; // NR RRCReconfiguration AssertFatal(rrc->Nb_ue < MAX_NR_RRC_UE_CONTEXTS,"cannot add another UE\n"); ue_context_p->ue_context.reconfig = calloc(1,sizeof(NR_RRCReconfiguration_t)); @@ -140,16 +151,111 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ ue_context_p->ue_context.reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; NR_RRCReconfiguration_IEs_t *reconfig_ies=calloc(1,sizeof(NR_RRCReconfiguration_IEs_t)); ue_context_p->ue_context.reconfig->criticalExtensions.choice.rrcReconfiguration = reconfig_ies; - carrier->initial_csi_index[rrc->Nb_ue] = 0; - if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1){ - ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t)); - fill_default_rbconfig(ue_context_p->ue_context.rb_config); + carrier->initial_csi_index[ue_context_p->local_uid + 1] = 0; + ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t)); + if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1 || get_softmodem_params()->sa == 1){ + fill_default_rbconfig(ue_context_p->ue_context.rb_config, + 5 /* EPS bearer ID */, + 1 /* drb ID */, + NR_CipheringAlgorithm_nea0, + NR_SecurityConfig__keyToUse_master); + } else { + /* TODO: handle more than one bearer */ + if (m == NULL) { + LOG_E(RRC, "fatal: m==NULL\n"); + exit(1); + } + if (m->nb_e_rabs_tobeadded != 1) { + LOG_E(RRC, "fatal: m->nb_e_rabs_tobeadded = %d, should be 1\n", m->nb_e_rabs_tobeadded); + exit(1); + } + + /* store security key and security capabilities */ + memcpy(ue_context_p->ue_context.kgnb, m->kgnb, 32); + ue_context_p->ue_context.security_capabilities.nRencryption_algorithms = m->security_capabilities.encryption_algorithms; + ue_context_p->ue_context.security_capabilities.nRintegrity_algorithms = m->security_capabilities.integrity_algorithms; + + /* Select ciphering algorithm based on gNB configuration file and + * UE's supported algorithms. + * We take the first from the list that is supported by the UE. + * The ordering of the list comes from the configuration file. + */ + /* preset nea0 as fallback */ + ue_context_p->ue_context.ciphering_algorithm = 0; + for (i = 0; i < rrc->security.ciphering_algorithms_count; i++) { + int nea_mask[4] = { + 0, + 0x8000, /* nea1 */ + 0x4000, /* nea2 */ + 0x2000 /* nea3 */ + }; + if (rrc->security.ciphering_algorithms[i] == 0) { + /* nea0 already preselected */ + break; + } + if (ue_context_p->ue_context.security_capabilities.nRencryption_algorithms & nea_mask[rrc->security.ciphering_algorithms[i]]) { + ue_context_p->ue_context.ciphering_algorithm = rrc->security.ciphering_algorithms[i]; + break; + } + } + + LOG_I(RRC, "selecting ciphering algorithm %d\n", (int)ue_context_p->ue_context.ciphering_algorithm); + + /* integrity: no integrity protection for DRB in ENDC mode + * as written in 38.331: "If UE is connected to E-UTRA/EPC, this field + * indicates the integrity protection algorithm to be used for SRBs + * configured with NR PDCP, as specified in TS 33.501" + * So nothing for DRB. Plus a test with a COTS UE revealed that it + * did not apply integrity on the DRB. + */ + ue_context_p->ue_context.integrity_algorithm = 0; + + LOG_I(RRC, "selecting integrity algorithm %d\n", ue_context_p->ue_context.integrity_algorithm); + + /* derive UP security key */ + nr_derive_key_up_enc(ue_context_p->ue_context.ciphering_algorithm, + ue_context_p->ue_context.kgnb, + &kUPenc); + nr_derive_key_up_int(ue_context_p->ue_context.integrity_algorithm, + ue_context_p->ue_context.kgnb, + &kUPint); + + e_NR_CipheringAlgorithm cipher_algo; + switch (ue_context_p->ue_context.ciphering_algorithm) { + case 0: cipher_algo = NR_CipheringAlgorithm_nea0; break; + case 1: cipher_algo = NR_CipheringAlgorithm_nea1; break; + case 2: cipher_algo = NR_CipheringAlgorithm_nea2; break; + case 3: cipher_algo = NR_CipheringAlgorithm_nea3; break; + default: LOG_E(RRC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); + } + + fill_default_rbconfig(ue_context_p->ue_context.rb_config, + m->e_rabs_tobeadded[0].e_rab_id, + m->e_rabs_tobeadded[0].drb_ID, + cipher_algo, + NR_SecurityConfig__keyToUse_secondary); } - fill_default_reconfig(carrier->servingcellconfigcommon, + if (ue_context_p->ue_context.spCellConfig) { + fill_default_reconfig(carrier->servingcellconfigcommon, + ue_context_p->ue_context.spCellConfig->spCellConfigDedicated, reconfig_ies, ue_context_p->ue_context.secondaryCellGroup, carrier->pdsch_AntennaPorts, - carrier->initial_csi_index[rrc->Nb_ue]); + carrier->minRXTXTIME, + carrier->do_CSIRS, + carrier->initial_csi_index[ue_context_p->local_uid + 1], + ue_context_p->local_uid); + } else { + fill_default_reconfig(carrier->servingcellconfigcommon, + NULL, + reconfig_ies, + ue_context_p->ue_context.secondaryCellGroup, + carrier->pdsch_AntennaPorts, + carrier->minRXTXTIME, + carrier->do_CSIRS, + carrier->initial_csi_index[ue_context_p->local_uid + 1], + ue_context_p->local_uid); + } ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity; NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config)); memset((void *)CG_Config,0,sizeof(*CG_Config)); @@ -162,7 +268,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ if (m->nb_e_rabs_tobeadded>0) { for (int i=0; inb_e_rabs_tobeadded; i++) { - // Add the new E-RABs at the corresponding rrc ue context of the gNB + // Add the new E-RABs at the corresponding rrc ue context of the gNB ue_context_p->ue_context.e_rab[i].param.e_rab_id = m->e_rabs_tobeadded[i].e_rab_id; ue_context_p->ue_context.e_rab[i].param.gtp_teid = m->e_rabs_tobeadded[i].gtp_teid; memcpy(&ue_context_p->ue_context.e_rab[i].param.sgw_addr, &m->e_rabs_tobeadded[i].sgw_addr, sizeof(transport_layer_addr_t)); @@ -222,27 +328,112 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ } } else LOG_W(RRC, "No E-RAB to be added received from SgNB Addition Request message \n"); + + X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).MeNB_ue_x2_id = m->ue_x2_id; + X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).SgNB_ue_x2_id = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity; + //X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size + // Send to X2 entity to transport to MeNB + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config, + NULL, + (void *)CG_Config, + X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer, + 1024); + X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3; + itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding + } else if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) { + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, ue_context_p->ue_id_rnti, 0, 0,rrc->module_id); } - //X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size - // Send to X2 entity to transport to MeNB - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config, - NULL, - (void *)CG_Config, - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer, - 1024); - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3; - itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding rrc->Nb_ue++; // configure MAC and RLC - rrc_mac_config_req_gNB(rrc->module_id, - rrc->carrier.ssb_SubcarrierOffset, - rrc->carrier.pdsch_AntennaPorts, - NULL, - 1, // add_ue flag - ue_context_p->ue_id_rnti, - ue_context_p->ue_context.secondaryCellGroup); + if (NODE_IS_DU(rrc->node_type)) { + rrc_mac_config_req_gNB(rrc->module_id, + rrc->carrier.ssb_SubcarrierOffset, + rrc->carrier.pdsch_AntennaPorts, + rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, + rrc->carrier.servingcellconfigcommon, + &rrc->carrier.mib, + 1, // add_ue flag + ue_context_p->ue_id_rnti, + ue_context_p->ue_context.secondaryCellGroup); + } else { + rrc_mac_config_req_gNB(rrc->module_id, + rrc->carrier.ssb_SubcarrierOffset, + rrc->carrier.pdsch_AntennaPorts, + rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, + NULL, + NULL, + 1, // add_ue flag + ue_context_p->ue_id_rnti, + ue_context_p->ue_context.secondaryCellGroup); + } + + if(m == NULL){ + LOG_W(RRC, "Calling RRC PDCP/RLC ASN1 request functions for protocol context %p with module_id %d, rnti %x, frame %d, subframe %d eNB_index %d \n", &ctxt, + ctxt.module_id, + ctxt.rnti, + ctxt.frame, + ctxt.subframe, + ctxt.eNB_index); + } + + nr_rrc_pdcp_config_asn1_req(&ctxt, + get_softmodem_params()->sa ? ue_context_p->ue_context.rb_config->srb_ToAddModList : (NR_SRB_ToAddModList_t *) NULL, + ue_context_p->ue_context.rb_config->drb_ToAddModList , + ue_context_p->ue_context.rb_config->drb_ToReleaseList, + (ue_context_p->ue_context.integrity_algorithm << 4) | ue_context_p->ue_context.ciphering_algorithm, + NULL, /* kRRCenc - unused */ + NULL, /* kRRCint - unused */ + kUPenc, /* kUPenc */ + kUPint, /* kUPint */ + NULL, + NULL, + ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList); + + nr_rrc_rlc_config_asn1_req (&ctxt, + get_softmodem_params()->sa ? ue_context_p->ue_context.rb_config->srb_ToAddModList : (NR_SRB_ToAddModList_t *) NULL, + ue_context_p->ue_context.rb_config->drb_ToAddModList, + ue_context_p->ue_context.rb_config->drb_ToReleaseList, + (LTE_PMCH_InfoList_r9_t *) NULL, + ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList); + + LOG_D(RRC, "%s:%d: done RRC PDCP/RLC ASN1 request for UE rnti %x\n", __FUNCTION__, __LINE__, ctxt.rnti); + } +void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) { + protocol_ctxt_t ctxt; + rrc_gNB_ue_context_t *ue_context; + int e_rab; -#endif + LOG_D(RRC, "calling rrc_remove_nsa_user rnti %d\n", rnti); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, rnti, 0, 0, rrc->module_id); + + ue_context = rrc_gNB_get_ue_context(rrc, rnti); + if (ue_context == NULL) { + LOG_W(RRC, "rrc_remove_nsa_user: rnti %d not found\n", rnti); + return; + } + + pdcp_remove_UE(&ctxt); + + rrc_rlc_remove_ue(&ctxt); + + mac_remove_nr_ue(rrc->module_id, rnti); + gtpv1u_enb_delete_tunnel_req_t tmp={0}; + tmp.rnti=rnti; + tmp.from_gnb=1; + LOG_D(RRC, "ue_context->ue_context.nb_of_e_rabs %d will be deleted for rnti %d\n", ue_context->ue_context.nb_of_e_rabs, rnti); + for (e_rab = 0; e_rab < ue_context->ue_context.nb_of_e_rabs; e_rab++) { + tmp.eps_bearer_id[tmp.num_erab++]= ue_context->ue_context.gnb_gtp_ebi[e_rab]; + // erase data + ue_context->ue_context.gnb_gtp_teid[e_rab] = 0; + memset(&ue_context->ue_context.gnb_gtp_addrs[e_rab], 0, sizeof(ue_context->ue_context.gnb_gtp_addrs[e_rab])); + ue_context->ue_context.gnb_gtp_ebi[e_rab] = 0; + } + gtpv1u_delete_s1u_tunnel(rrc->module_id, &tmp); + /* remove context */ + rrc_gNB_remove_ue_context(&ctxt, rrc, ue_context); +} diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 6ea6f3b3b3..30604cd015 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -31,6 +31,7 @@ #define RRC_GNB_NSA_C #include "NR_ServingCellConfigCommon.h" +#include "NR_ServingCellConfig.h" #include "NR_RRCReconfiguration.h" #include "NR_RRCReconfiguration-IEs.h" #include "NR_CellGroupConfig.h" @@ -43,64 +44,69 @@ #include "common/utils/nr/nr_common.h" #include "SIMULATION/TOOLS/sim.h" #include "executables/softmodem-common.h" +#include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #define false 0 #define true 1 - void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, + NR_ServingCellConfig_t *servingcellconfigdedicated, NR_CellGroupConfig_t *secondaryCellGroup, int scg_id, int servCellIndex, - int n_physical_antenna_ports, - int initial_csi_index) { + int dl_antenna_ports, + int minRXTXTIME, + int do_csirs, + int initial_csi_index, + int uid) { AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n"); AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n"); + + uint64_t bitmap=0; + switch (servingcellconfigcommon->ssb_PositionsInBurst->present) { + case 1 : + bitmap = ((uint64_t) servingcellconfigcommon->ssb_PositionsInBurst->choice.shortBitmap.buf[0])<<56; + break; + case 2 : + bitmap = ((uint64_t) servingcellconfigcommon->ssb_PositionsInBurst->choice.mediumBitmap.buf[0])<<56; + break; + case 3 : + for (int i=0; i<8; i++) { + bitmap |= (((uint64_t) servingcellconfigcommon->ssb_PositionsInBurst->choice.longBitmap.buf[i])<<((7-i)*8)); + } + break; + default: + AssertFatal(1==0,"SSB bitmap size value %d undefined (allowed values 1,2,3) \n", servingcellconfigcommon->ssb_PositionsInBurst->present); + } + memset(secondaryCellGroup,0,sizeof(NR_CellGroupConfig_t)); secondaryCellGroup->cellGroupId = scg_id; NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig)); - RLC_BearerConfig->logicalChannelIdentity = 4; - RLC_BearerConfig->servedRadioBearer = calloc(1,sizeof(*RLC_BearerConfig->servedRadioBearer)); - RLC_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity; - RLC_BearerConfig->servedRadioBearer->choice.drb_Identity=1; - RLC_BearerConfig->reestablishRLC=calloc(1,sizeof(*RLC_BearerConfig->reestablishRLC)); - *RLC_BearerConfig->reestablishRLC=NR_RLC_BearerConfig__reestablishRLC_true; - RLC_BearerConfig->rlc_Config=calloc(1,sizeof(*RLC_BearerConfig->rlc_Config)); - RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_am; - RLC_BearerConfig->rlc_Config->choice.am = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am)); - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB500; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t32; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15; - RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters)); - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedServingCells = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedSCS_List = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->maxPUSCH_Duration = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->configuredGrantType1Allowed = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup)); - *RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL; + nr_rlc_bearer_init(RLC_BearerConfig, NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity); + if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) + nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional); + else + nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am); + nr_rlc_bearer_init_ul_spec(RLC_BearerConfig->mac_LogicalChannelConfig); + secondaryCellGroup->rlc_BearerToAddModList = calloc(1,sizeof(*secondaryCellGroup->rlc_BearerToAddModList)); ASN_SEQUENCE_ADD(&secondaryCellGroup->rlc_BearerToAddModList->list, RLC_BearerConfig); + secondaryCellGroup->mac_CellGroupConfig=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig)); secondaryCellGroup->mac_CellGroupConfig->drx_Config = NULL; - secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig = NULL; + secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig = calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig)); + secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList = calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList)); + NR_SchedulingRequestToAddMod_t *SchedulingRequestConf = calloc(1,sizeof(*SchedulingRequestConf)); + SchedulingRequestConf->schedulingRequestId = 0; //Could be changed + SchedulingRequestConf->sr_ProhibitTimer = calloc(1,sizeof(*SchedulingRequestConf->sr_ProhibitTimer)); + *SchedulingRequestConf->sr_ProhibitTimer = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms16; + SchedulingRequestConf->sr_TransMax = NR_SchedulingRequestToAddMod__sr_TransMax_n32; + ASN_SEQUENCE_ADD(&secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList->list,SchedulingRequestConf); + secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToReleaseList = NULL; + secondaryCellGroup->mac_CellGroupConfig->bsr_Config=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->bsr_Config)); - secondaryCellGroup->mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf80; - secondaryCellGroup->mac_CellGroupConfig->bsr_Config->retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf320; + secondaryCellGroup->mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10; + secondaryCellGroup->mac_CellGroupConfig->bsr_Config->retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf160; secondaryCellGroup->mac_CellGroupConfig->tag_Config=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->tag_Config)); secondaryCellGroup->mac_CellGroupConfig->tag_Config->tag_ToReleaseList = NULL; secondaryCellGroup->mac_CellGroupConfig->tag_Config->tag_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->tag_Config->tag_ToAddModList)); @@ -141,36 +147,52 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->reconfigurationWithSync->t304=NR_ReconfigurationWithSync__t304_ms2000; secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated = NULL; secondaryCellGroup->spCellConfig->reconfigurationWithSync->ext1 = NULL; - /* contention free ra */ - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated = calloc(1,sizeof(struct NR_ReconfigurationWithSync__rach_ConfigDedicated)); - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->present= NR_ReconfigurationWithSync__rach_ConfigDedicated_PR_uplink; - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink= calloc(1,sizeof(struct NR_RACH_ConfigDedicated)); - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra= calloc(1,sizeof(struct NR_CFRA)); - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->ra_Prioritization= NULL; - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions= calloc(1,sizeof(struct NR_CFRA__occasions)); - memcpy(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->rach_ConfigGeneric, - &servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric, sizeof(NR_RACH_ConfigGeneric_t)); - //secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= calloc(1,sizeof(long)); - //*secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion = NR_CFRA__occasions__ssb_perRACH_Occasion_one; - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= NULL; - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb; - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb = calloc(1,sizeof(struct NR_CFRA__resources__ssb)); - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0; - struct NR_CFRA_SSB_Resource *ssbElem = calloc(1,sizeof(struct NR_CFRA_SSB_Resource)); - ssbElem->ssb = 0; - ssbElem->ra_PreambleIndex= 63; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem); - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->ext1 = NULL; + + // For 2-step contention-free random access procedure + if(get_softmodem_params()->sa == 0) { + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated = calloc(1,sizeof(struct NR_ReconfigurationWithSync__rach_ConfigDedicated)); + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->present= NR_ReconfigurationWithSync__rach_ConfigDedicated_PR_uplink; + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink= calloc(1,sizeof(struct NR_RACH_ConfigDedicated)); + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra= calloc(1,sizeof(struct NR_CFRA)); + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->ra_Prioritization= NULL; + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions= calloc(1,sizeof(struct NR_CFRA__occasions)); + memcpy(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->rach_ConfigGeneric, + &servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric, sizeof(NR_RACH_ConfigGeneric_t)); + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= calloc(1,sizeof(long)); + *secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion = NR_CFRA__occasions__ssb_perRACH_Occasion_one; + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb; + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb = calloc(1,sizeof(struct NR_CFRA__resources__ssb)); + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0; + + int n_ssb = 0; + struct NR_CFRA_SSB_Resource *ssbElem[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ + ssbElem[n_ssb] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource)); + ssbElem[n_ssb]->ssb = i; + ssbElem[n_ssb]->ra_PreambleIndex = 63 - (uid % 64); + ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[n_ssb]); + n_ssb++; + } + } + + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->ext1 = NULL; + } + secondaryCellGroup->spCellConfig->rlf_TimersAndConstants = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants)); secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->present = NR_SetupRelease_RLF_TimersAndConstants_PR_setup; secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup)); - secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->t310 = NR_RLF_TimersAndConstants__t310_ms2000; - secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->n310 = NR_RLF_TimersAndConstants__n310_n10; + secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->t310 = NR_RLF_TimersAndConstants__t310_ms4000; + secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->n310 = NR_RLF_TimersAndConstants__n310_n20; secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->n311 = NR_RLF_TimersAndConstants__n311_n1; secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1 = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1)); - secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1->t311_v1530 = NR_RLF_TimersAndConstants__ext1__t311_v1530_ms30000; + secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1->t311 = NR_RLF_TimersAndConstants__ext1__t311_ms30000; secondaryCellGroup->spCellConfig->rlmInSyncOutOfSyncThreshold = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated)); + if (servingcellconfigdedicated) { + secondaryCellGroup->spCellConfig->spCellConfigDedicated = servingcellconfigdedicated; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated)); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->tdd_UL_DL_ConfigurationDedicated = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP)); secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdcch_Config=NULL; @@ -193,9 +215,29 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0; -#if 0 + secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList)); + int n_ssb = 0; + NR_TCI_State_t *tcic[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ + tcic[i]=calloc(1,sizeof(*tcic[i])); + tcic[i]->tci_StateId=n_ssb; + tcic[i]->qcl_Type1.cell=NULL; + tcic[i]->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcic[i]->qcl_Type1.bwp_Id)); + *tcic[i]->qcl_Type1.bwp_Id=1; + tcic[i]->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; + tcic[i]->qcl_Type1.referenceSignal.choice.ssb = i; + tcic[i]->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; + ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcic[i]); + n_ssb++; + } + } + + +#if 0 + NR_TCI_State_t*tci0=calloc(1,sizeof(*tci0)); tci0->tci_StateId=0; tci0->qcl_Type1.cell=NULL; @@ -276,85 +318,6 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco tci7->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci7); - NR_TCI_State_t*tci8=calloc(1,sizeof(*tci8)); - tci8->tci_StateId=8; - tci8->qcl_Type1.cell=NULL; - tci8->qcl_Type1.bwp_Id=calloc(1,sizeof(*tci8->qcl_Type1.bwp_Id)); - *tci8->qcl_Type1.bwp_Id=1; - tci8->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tci8->qcl_Type1.referenceSignal.choice.ssb = 0; - tci8->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci8); - - NR_TCI_State_t*tci9=calloc(1,sizeof(*tci9)); - tci9->tci_StateId=9; - tci9->qcl_Type1.cell=NULL; - tci9->qcl_Type1.bwp_Id=calloc(1,sizeof(*tci9->qcl_Type1.bwp_Id)); - *tci9->qcl_Type1.bwp_Id=1; - tci9->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tci9->qcl_Type1.referenceSignal.choice.ssb = 1; - tci9->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci9); - - NR_TCI_State_t*tci10=calloc(1,sizeof(*tci10)); - tci10->tci_StateId=10; - tci10->qcl_Type1.cell=NULL; - tci10->qcl_Type1.bwp_Id=calloc(1,sizeof(*tci10->qcl_Type1.bwp_Id)); - *tci10->qcl_Type1.bwp_Id=1; - tci10->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tci10->qcl_Type1.referenceSignal.choice.ssb = 2; - tci10->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci10); - - NR_TCI_State_t*tci11=calloc(1,sizeof(*tci11)); - tci11->tci_StateId=11; - tci11->qcl_Type1.cell=NULL; - tci11->qcl_Type1.bwp_Id=calloc(1,sizeof(*tci11->qcl_Type1.bwp_Id)); - *tci11->qcl_Type1.bwp_Id=1; - tci11->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tci11->qcl_Type1.referenceSignal.choice.ssb = 3; - tci11->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci11); - - NR_TCI_State_t*tci12=calloc(1,sizeof(*tci12)); - tci12->tci_StateId=12; - tci12->qcl_Type1.cell=NULL; - tci12->qcl_Type1.bwp_Id=calloc(1,sizeof(*tci12->qcl_Type1.bwp_Id)); - *tci12->qcl_Type1.bwp_Id=1; - tci12->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tci12->qcl_Type1.referenceSignal.choice.ssb = 4; - tci12->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci12); - - NR_TCI_State_t*tci13=calloc(1,sizeof(*tci13)); - tci13->tci_StateId=13; - tci13->qcl_Type1.cell=NULL; - tci13->qcl_Type1.bwp_Id=calloc(1,sizeof(*tci13->qcl_Type1.bwp_Id)); - *tci13->qcl_Type1.bwp_Id=1; - tci13->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tci13->qcl_Type1.referenceSignal.choice.ssb = 5; - tci13->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci13); - - NR_TCI_State_t*tci14=calloc(1,sizeof(*tci14)); - tci14->tci_StateId=14; - tci14->qcl_Type1.cell=NULL; - tci14->qcl_Type1.bwp_Id=calloc(1,sizeof(*tci14->qcl_Type1.bwp_Id)); - *tci14->qcl_Type1.bwp_Id=1; - tci14->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tci14->qcl_Type1.referenceSignal.choice.ssb = 6; - tci14->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci14); - - NR_TCI_State_t*tci15=calloc(1,sizeof(*tci15)); - tci15->tci_StateId=15; - tci15->qcl_Type1.cell=NULL; - tci15->qcl_Type1.bwp_Id=calloc(1,sizeof(*tci15->qcl_Type1.bwp_Id)); - *tci15->qcl_Type1.bwp_Id=1; - tci15->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tci15->qcl_Type1.referenceSignal.choice.ssb = 7; - tci15->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tci15); #endif secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToReleaseList=NULL; @@ -367,7 +330,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table=NULL; + if (!get_softmodem_params()->use_256qam_table) { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table=NULL; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table)); + *secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256; + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; @@ -399,9 +367,15 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco #endif secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList= NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); + + NR_BWP_Downlink_t *bwp = NULL; + if (servingcellconfigdedicated) { + bwp=servingcellconfigdedicated->downlinkBWP_ToAddModList->list.array[0]; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); - NR_BWP_Downlink_t *bwp=calloc(1,sizeof(*bwp)); + bwp=calloc(1,sizeof(*bwp)); + } bwp->bwp_Id=1; bwp->bwp_Common=calloc(1,sizeof(*bwp->bwp_Common)); // copy common BWP size from initial BWP except for bandwdith @@ -417,12 +391,21 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->controlResourceSetZero=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet)); + int curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + NR_ControlResourceSet_t *coreset = calloc(1,sizeof(*coreset)); coreset->controlResourceSetId=1; - // frequencyDomainResources '11111111 11111111 00000000 00000000 00000000 00000'B, + // frequency domain resources depends on BWP size + // options are 24, 48 or 96 coreset->frequencyDomainResources.buf = calloc(1,6); - coreset->frequencyDomainResources.buf[0] = 0xff; - coreset->frequencyDomainResources.buf[1] = 0xff; + if (curr_bwp < 48) + coreset->frequencyDomainResources.buf[0] = 0xf0; + else + coreset->frequencyDomainResources.buf[0] = 0xff; + if (curr_bwp < 96) + coreset->frequencyDomainResources.buf[1] = 0; + else + coreset->frequencyDomainResources.buf[1] = 0xff; coreset->frequencyDomainResources.buf[2] = 0; coreset->frequencyDomainResources.buf[3] = 0; coreset->frequencyDomainResources.buf[4] = 0; @@ -434,11 +417,13 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco coreset->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; coreset->tci_StatesPDCCH_ToAddList=calloc(1,sizeof(*coreset->tci_StatesPDCCH_ToAddList)); - NR_TCI_StateId_t *tci[8]; - for (int i=0;i<8;i++) { - tci[i]=calloc(1,sizeof(*tci[i])); - *tci[i] = i; - ASN_SEQUENCE_ADD(&coreset->tci_StatesPDCCH_ToAddList->list,tci[i]); + NR_TCI_StateId_t *tci[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ + tci[i]=calloc(1,sizeof(*tci[i])); + *tci[i] = i; + ASN_SEQUENCE_ADD(&coreset->tci_StatesPDCCH_ToAddList->list,tci[i]); + } } coreset->tci_StatesPDCCH_ToReleaseList = NULL; coreset->tci_PresentInDCI = NULL; @@ -476,9 +461,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ss->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); ASN_SEQUENCE_ADD(&bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list,ss); - bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=NULL; + if(get_softmodem_params()->sa) { + bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1)); + *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=0; + } bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->pagingSearchSpace=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)); @@ -495,17 +483,18 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_PDSCH_TimeDomainResourceAllocation_t *pdschi; for (int i=0;idownlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) { pdschi= calloc(1,sizeof(*pdschi)); - AssertFatal(servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0!=NULL,"element %d is null\n",i); - - pdschi->k0 = calloc(1,sizeof(*pdschi->k0)); - *pdschi->k0 = *servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0; + if(servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0){ + pdschi->k0 = calloc(1,sizeof(*pdschi->k0)); + *pdschi->k0 = *servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0; + } pdschi->mappingType = servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType; pdschi->startSymbolAndLength = servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength; ASN_SEQUENCE_ADD(&bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,pdschi); } - bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated)); - + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated)); + } bwp->bwp_Dedicated->pdcch_Config=calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config)); bwp->bwp_Dedicated->pdcch_Config->present = NR_SetupRelease_PDCCH_Config_PR_setup; bwp->bwp_Dedicated->pdcch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup)); @@ -534,7 +523,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ss2->nrofCandidates=calloc(1,sizeof(*ss2->nrofCandidates)); ss2->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; ss2->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; + if (curr_bwp < 48) + ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + else if (curr_bwp < 96) + ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; + else + ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; ss2->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; ss2->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; ss2->searchSpaceType=calloc(1,sizeof(*ss2->searchSpaceType)); @@ -548,189 +542,50 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToReleaseList = NULL; - bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config)); + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config)); bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup)); - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + } + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=NULL; + if (dl_antenna_ports > 1)// for MIMO, we use DMRS Config Type 2 + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type)); + else + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID0=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID1=NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL; - + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL; + } bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=NULL; -#if 0 bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList)); - NR_TCI_State_t*tcid0=calloc(1,sizeof(*tcid0)); - tcid0->tci_StateId=0; - tcid0->qcl_Type1.cell=NULL; - tcid0->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid0->qcl_Type1.bwp_Id)); - *tcid0->qcl_Type1.bwp_Id=1; - tcid0->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid0->qcl_Type1.referenceSignal.choice.csi_rs = 2; - tcid0->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid0); + n_ssb = 0; + NR_TCI_State_t *tcid[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ + tcid[i]=calloc(1,sizeof(*tcid[i])); + tcid[i]->tci_StateId=n_ssb; + tcid[i]->qcl_Type1.cell=NULL; + tcid[i]->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid[i]->qcl_Type1.bwp_Id)); + *tcid[i]->qcl_Type1.bwp_Id=1; + tcid[i]->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; + tcid[i]->qcl_Type1.referenceSignal.choice.ssb = i; + tcid[i]->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; + ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid[i]); + n_ssb++; + } + } - NR_TCI_State_t*tcid1=calloc(1,sizeof(*tcid1)); - tcid1->tci_StateId=0; - tcid1->qcl_Type1.cell=NULL; - tcid1->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid1->qcl_Type1.bwp_Id)); - *tcid1->qcl_Type1.bwp_Id=1; - tcid1->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid1->qcl_Type1.referenceSignal.choice.csi_rs = 6; - tcid1->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid1); - - NR_TCI_State_t*tcid2=calloc(1,sizeof(*tcid2)); - tcid2->tci_StateId=2; - tcid2->qcl_Type1.cell=NULL; - tcid2->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid2->qcl_Type1.bwp_Id)); - *tcid2->qcl_Type1.bwp_Id=1; - tcid2->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid2->qcl_Type1.referenceSignal.choice.csi_rs = 10; - tcid2->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid2); - - NR_TCI_State_t*tcid3=calloc(1,sizeof(*tcid3)); - tcid3->tci_StateId=3; - tcid3->qcl_Type1.cell=NULL; - tcid3->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid3->qcl_Type1.bwp_Id)); - *tcid3->qcl_Type1.bwp_Id=1; - tcid3->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid3->qcl_Type1.referenceSignal.choice.csi_rs = 14; - tcid3->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid3); - - NR_TCI_State_t*tcid4=calloc(1,sizeof(*tcid4)); - tcid4->tci_StateId=4; - tcid4->qcl_Type1.cell=NULL; - tcid4->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid4->qcl_Type1.bwp_Id)); - *tcid4->qcl_Type1.bwp_Id=1; - tcid4->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid4->qcl_Type1.referenceSignal.choice.csi_rs = 18; - tcid4->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid4); - - NR_TCI_State_t*tcid5=calloc(1,sizeof(*tcid5)); - tcid5->tci_StateId=5; - tcid5->qcl_Type1.cell=NULL; - tcid5->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid5->qcl_Type1.bwp_Id)); - *tcid5->qcl_Type1.bwp_Id=1; - tcid5->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid5->qcl_Type1.referenceSignal.choice.csi_rs = 22; - tcid5->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid5); - - NR_TCI_State_t*tcid6=calloc(1,sizeof(*tcid6)); - tcid6->tci_StateId=6; - tcid6->qcl_Type1.cell=NULL; - tcid6->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid6->qcl_Type1.bwp_Id)); - *tcid6->qcl_Type1.bwp_Id=1; - tcid6->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid6->qcl_Type1.referenceSignal.choice.csi_rs = 26; - tcid6->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid6); - - NR_TCI_State_t*tcid7=calloc(1,sizeof(*tcid7)); - tcid7->tci_StateId=7; - tcid7->qcl_Type1.cell=NULL; - tcid7->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid7->qcl_Type1.bwp_Id)); - *tcid7->qcl_Type1.bwp_Id=1; - tcid7->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid7->qcl_Type1.referenceSignal.choice.csi_rs = 30; - tcid7->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid7); - - NR_TCI_State_t*tcid8=calloc(1,sizeof(*tcid8)); - tcid8->tci_StateId=8; - tcid8->qcl_Type1.cell=NULL; - tcid8->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid8->qcl_Type1.bwp_Id)); - *tcid8->qcl_Type1.bwp_Id=1; - tcid8->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tcid8->qcl_Type1.referenceSignal.choice.ssb = 0; - tcid8->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid8); - - NR_TCI_State_t*tcid9=calloc(1,sizeof(*tcid9)); - tcid9->tci_StateId=9; - tcid9->qcl_Type1.cell=NULL; - tcid9->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid9->qcl_Type1.bwp_Id)); - *tcid9->qcl_Type1.bwp_Id=1; - tcid9->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tcid9->qcl_Type1.referenceSignal.choice.ssb = 1; - tcid9->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid9); - - NR_TCI_State_t*tcid10=calloc(1,sizeof(*tcid10)); - tcid10->tci_StateId=10; - tcid10->qcl_Type1.cell=NULL; - tcid10->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid10->qcl_Type1.bwp_Id)); - *tcid10->qcl_Type1.bwp_Id=1; - tcid10->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tcid10->qcl_Type1.referenceSignal.choice.ssb = 2; - tcid10->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid10); - - NR_TCI_State_t*tcid11=calloc(1,sizeof(*tcid11)); - tcid11->tci_StateId=11; - tcid11->qcl_Type1.cell=NULL; - tcid11->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid11->qcl_Type1.bwp_Id)); - *tcid11->qcl_Type1.bwp_Id=1; - tcid11->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tcid11->qcl_Type1.referenceSignal.choice.ssb = 3; - tcid11->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid11); - - NR_TCI_State_t*tcid12=calloc(1,sizeof(*tcid12)); - tcid12->tci_StateId=12; - tcid12->qcl_Type1.cell=NULL; - tcid12->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid12->qcl_Type1.bwp_Id)); - *tcid12->qcl_Type1.bwp_Id=1; - tcid12->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tcid12->qcl_Type1.referenceSignal.choice.ssb = 4; - tcid12->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid12); - - NR_TCI_State_t*tcid13=calloc(1,sizeof(*tcid13)); - tcid13->tci_StateId=13; - tcid13->qcl_Type1.cell=NULL; - tcid13->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid13->qcl_Type1.bwp_Id)); - *tcid13->qcl_Type1.bwp_Id=1; - tcid13->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tcid13->qcl_Type1.referenceSignal.choice.ssb = 5; - tcid13->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid13); - - NR_TCI_State_t*tcid14=calloc(1,sizeof(*tcid14)); - tcid14->tci_StateId=14; - tcid14->qcl_Type1.cell=NULL; - tcid14->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid14->qcl_Type1.bwp_Id)); - *tcid14->qcl_Type1.bwp_Id=1; - tcid14->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tcid14->qcl_Type1.referenceSignal.choice.ssb = 6; - tcid14->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid14); - - NR_TCI_State_t*tcid15=calloc(1,sizeof(*tcid15)); - tcid15->tci_StateId=15; - tcid15->qcl_Type1.cell=NULL; - tcid15->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid15->qcl_Type1.bwp_Id)); - *tcid15->qcl_Type1.bwp_Id=1; - tcid15->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_ssb; - tcid15->qcl_Type1.referenceSignal.choice.ssb = 7; - tcid15->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeC; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid15); -#endif bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToReleaseList=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->vrb_ToPRB_Interleaver=NULL; @@ -742,7 +597,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL; + if (!get_softmodem_params()->use_256qam_table) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL; + } else { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table)); + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256; + } bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI)); *bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1; bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; @@ -768,7 +628,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL; + if (!get_softmodem_params()->use_256qam_table) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL; + } else { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table)); + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256; + } bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI)); *bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1; bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; @@ -799,8 +664,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco *bwp->bwp_Dedicated->radioLinkMonitoringConfig->choice.setup->beamFailureDetectionTimer = NR_RadioLinkMonitoringConfig__beamFailureDetectionTimer_pbfd2; #endif - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list,bwp); - + if (!servingcellconfigdedicated) { + ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list,bwp); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id=1; @@ -808,26 +674,38 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = 1; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig)); + + if (!servingcellconfigdedicated) { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig)); + } NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1,sizeof(*initialUplinkBWP)); secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP = initialUplinkBWP; initialUplinkBWP->pucch_Config = NULL; initialUplinkBWP->pusch_Config = calloc(1,sizeof(*initialUplinkBWP->pusch_Config)); initialUplinkBWP->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; - NR_PUSCH_Config_t *pusch_Config = calloc(1,sizeof(*pusch_Config)); + NR_PUSCH_Config_t *pusch_Config = NULL; + if (servingcellconfigdedicated) { + pusch_Config = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup; + } else { + pusch_Config = calloc(1,sizeof(*pusch_Config)); + } initialUplinkBWP->pusch_Config->choice.setup = pusch_Config; pusch_Config->txConfig=calloc(1,sizeof(*pusch_Config->txConfig)); *pusch_Config->txConfig= NR_PUSCH_Config__txConfig_codebook; pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA = NULL; - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + if (!servingcellconfigdedicated) { + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + } NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; NR_DMRS_UplinkConfig->dmrs_Type = NULL; NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = calloc(1,sizeof(*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition)); *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0; - NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; + if (!servingcellconfigdedicated) { + NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; + } NR_DMRS_UplinkConfig->maxLength=NULL; NR_DMRS_UplinkConfig->transformPrecodingDisabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingDisabled)); NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0 = NULL; @@ -846,12 +724,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco aset->alpha=calloc(1,sizeof(*aset->alpha)); *aset->alpha=NR_Alpha_alpha1; ASN_SEQUENCE_ADD(&pusch_Config->pusch_PowerControl->p0_AlphaSets->list,aset); - pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList = calloc(1,sizeof(*pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList)); - NR_PUSCH_PathlossReferenceRS_t *pl = calloc(1,sizeof(*pl)); - pl->pusch_PathlossReferenceRS_Id=0; - pl->referenceSignal.present = NR_PUSCH_PathlossReferenceRS__referenceSignal_PR_csi_RS_Index; - pl->referenceSignal.choice.csi_RS_Index=0; - ASN_SEQUENCE_ADD(&pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList->list,pl); + pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList = NULL; pusch_Config->pusch_PowerControl->pathlossReferenceRSToReleaseList = NULL; pusch_Config->pusch_PowerControl->twoPUSCH_PC_AdjustmentStates = NULL; pusch_Config->pusch_PowerControl->deltaMCS = NULL; @@ -864,8 +737,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pusch_Config->pusch_AggregationFactor=NULL; pusch_Config->mcs_Table=NULL; pusch_Config->mcs_TableTransformPrecoder=NULL; - pusch_Config->transformPrecoder=calloc(1,sizeof(*pusch_Config->transformPrecoder)); - *pusch_Config->transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; + pusch_Config->transformPrecoder= NULL; + /* if msg3_transformprecoding is set in conf file - pusch config should not disable it */ + if (servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) { + pusch_Config->transformPrecoder=calloc(1,sizeof(*pusch_Config->transformPrecoder)); + *pusch_Config->transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; + } pusch_Config->codebookSubset=calloc(1,sizeof(*pusch_Config->codebookSubset)); *pusch_Config->codebookSubset = NR_PUSCH_Config__codebookSubset_nonCoherent; pusch_Config->maxRank=calloc(1,sizeof(*pusch_Config->maxRank)); @@ -874,6 +751,39 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pusch_Config->uci_OnPUSCH=NULL; pusch_Config->tp_pi2BPSK=NULL; + /*------------------------------TRANSFORM PRECODING- -----------------------------------------------------------------------*/ + + uint8_t transform_precoding = NR_PUSCH_Config__transformPrecoder_disabled; + + // TBD: configure this from .conf file, Dedicated params cannot yet be configured in .conf file. + // Enable this to test transform precoding enabled from dedicated config. + /*if (pusch_Config->transformPrecoder == NULL) + pusch_Config->transformPrecoder=calloc(1,sizeof(*pusch_Config->transformPrecoder)); + + *pusch_Config->transformPrecoder = NR_PUSCH_Config__transformPrecoder_enabled; */ + // END ------- + + if (pusch_Config->transformPrecoder == NULL) { + if (servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder != NULL) + transform_precoding = NR_PUSCH_Config__transformPrecoder_enabled; + } + else + transform_precoding = *pusch_Config->transformPrecoder; + + + if (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled ) { + /* Enable DMRS uplink config for transform precoding enabled */ + NR_DMRS_UplinkConfig->transformPrecodingEnabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingEnabled)); + NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity = NULL; + NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping = NULL; + NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping = NULL; + NR_DMRS_UplinkConfig->transformPrecodingEnabled->ext1 = NULL; + + LOG_I(RRC,"TRANSFORM PRECODING ENABLED......\n"); + + } + /*----------------------------------------------------------------------------------------------------------------------------*/ + initialUplinkBWP->srs_Config = calloc(1,sizeof(*initialUplinkBWP->srs_Config)); initialUplinkBWP->srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup; NR_SRS_Config_t *srs_Config = calloc(1,sizeof(*srs_Config)); @@ -931,8 +841,13 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceToAddModList->list,srs_res0); secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList)); - NR_BWP_Uplink_t *ubwp = calloc(1,sizeof(*ubwp)); + NR_BWP_Uplink_t *ubwp = NULL; + if (servingcellconfigdedicated) { + ubwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList)); + ubwp = calloc(1,sizeof(*ubwp)); + } ubwp->bwp_Id=1; ubwp->bwp_Common = calloc(1,sizeof(*ubwp->bwp_Common)); // copy bwp_Common from Initial UL BWP except for bandwidth @@ -945,7 +860,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ubwp->bwp_Common->pusch_ConfigCommon = servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; ubwp->bwp_Common->pucch_ConfigCommon = servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon; - ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated)); + if (!servingcellconfigdedicated) { + ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated)); + } ubwp->bwp_Dedicated->pucch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pucch_Config)); ubwp->bwp_Dedicated->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup; NR_PUCCH_Config_t *pucch_Config = calloc(1,sizeof(*pucch_Config)); @@ -956,23 +873,17 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_PUCCH_ResourceSet_t *pucchresset1=calloc(1,sizeof(*pucchresset1)); pucchresset0->pucch_ResourceSetId = 0; NR_PUCCH_ResourceId_t *pucchresset0id0=calloc(1,sizeof(*pucchresset0id0)); - NR_PUCCH_ResourceId_t *pucchresset0id1=calloc(1,sizeof(*pucchresset0id1)); *pucchresset0id0=1; ASN_SEQUENCE_ADD(&pucchresset0->resourceList.list,pucchresset0id0); - *pucchresset0id1=2; - ASN_SEQUENCE_ADD(&pucchresset0->resourceList.list,pucchresset0id1); - pucchresset0->maxPayloadMinus1=NULL; + pucchresset0->maxPayloadSize=NULL; ASN_SEQUENCE_ADD(&pucch_Config->resourceSetToAddModList->list,pucchresset0); pucchresset1->pucch_ResourceSetId = 1; NR_PUCCH_ResourceId_t *pucchresset1id0=calloc(1,sizeof(*pucchresset1id0)); - NR_PUCCH_ResourceId_t *pucchresset1id1=calloc(1,sizeof(*pucchresset1id1)); - *pucchresset1id0=3; + *pucchresset1id0=2; ASN_SEQUENCE_ADD(&pucchresset1->resourceList.list,pucchresset1id0); - *pucchresset1id1=4; - ASN_SEQUENCE_ADD(&pucchresset1->resourceList.list,pucchresset1id1); - pucchresset1->maxPayloadMinus1=NULL; + pucchresset1->maxPayloadSize=NULL; ASN_SEQUENCE_ADD(&pucch_Config->resourceSetToAddModList->list,pucchresset1); pucch_Config->resourceToAddModList = calloc(1,sizeof(*pucch_Config->resourceToAddModList)); @@ -981,8 +892,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_PUCCH_Resource_t *pucchres1=calloc(1,sizeof(*pucchres1)); NR_PUCCH_Resource_t *pucchres2=calloc(1,sizeof(*pucchres2)); NR_PUCCH_Resource_t *pucchres3=calloc(1,sizeof(*pucchres3)); + pucchres0->pucch_ResourceId=1; - pucchres0->startingPRB=48; + pucchres0->startingPRB= (8 + uid) % curr_bwp; pucchres0->intraSlotFrequencyHopping=NULL; pucchres0->secondHopPRB=NULL; pucchres0->format.present= NR_PUCCH_Resource__format_PR_format0; @@ -992,39 +904,17 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pucchres0->format.choice.format0->startingSymbolIndex=13; ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres0); - pucchres1->pucch_ResourceId=2; - pucchres1->startingPRB=48; - pucchres1->intraSlotFrequencyHopping=NULL; - pucchres1->secondHopPRB=NULL; - pucchres1->format.present= NR_PUCCH_Resource__format_PR_format0; - pucchres1->format.choice.format0=calloc(1,sizeof(*pucchres1->format.choice.format0)); - pucchres1->format.choice.format0->initialCyclicShift=0; - pucchres1->format.choice.format0->nrofSymbols=1; - pucchres1->format.choice.format0->startingSymbolIndex=12; - ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres1); - - pucchres2->pucch_ResourceId=3; - pucchres2->startingPRB=40; + pucchres2->pucch_ResourceId=2; + pucchres2->startingPRB=0; pucchres2->intraSlotFrequencyHopping=NULL; pucchres2->secondHopPRB=NULL; pucchres2->format.present= NR_PUCCH_Resource__format_PR_format2; pucchres2->format.choice.format2=calloc(1,sizeof(*pucchres2->format.choice.format2)); - pucchres2->format.choice.format2->nrofPRBs=16; + pucchres2->format.choice.format2->nrofPRBs=8; pucchres2->format.choice.format2->nrofSymbols=1; pucchres2->format.choice.format2->startingSymbolIndex=13; ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres2); - pucchres3->pucch_ResourceId=4; - pucchres3->startingPRB=40; - pucchres3->intraSlotFrequencyHopping=NULL; - pucchres3->secondHopPRB=NULL; - pucchres3->format.present= NR_PUCCH_Resource__format_PR_format2; - pucchres3->format.choice.format2=calloc(1,sizeof(*pucchres3->format.choice.format2)); - pucchres3->format.choice.format2->nrofPRBs=16; - pucchres3->format.choice.format2->nrofSymbols=1; - pucchres3->format.choice.format2->startingSymbolIndex=12; - ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres3); - pucch_Config->format2=calloc(1,sizeof(*pucch_Config->format2)); pucch_Config->format2->present=NR_SetupRelease_PUCCH_FormatConfig_PR_setup; NR_PUCCH_FormatConfig_t *pucchfmt2 = calloc(1,sizeof(*pucchfmt2)); @@ -1032,26 +922,45 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pucchfmt2->interslotFrequencyHopping=NULL; pucchfmt2->additionalDMRS=NULL; pucchfmt2->maxCodeRate=calloc(1,sizeof(*pucchfmt2->maxCodeRate)); - *pucchfmt2->maxCodeRate=NR_PUCCH_MaxCodeRate_zeroDot15; + *pucchfmt2->maxCodeRate=NR_PUCCH_MaxCodeRate_zeroDot35; pucchfmt2->nrofSlots=NULL; pucchfmt2->pi2BPSK=NULL; - pucchfmt2->simultaneousHARQ_ACK_CSI=NULL; - pucch_Config->schedulingRequestResourceToAddModList=NULL; + pucchfmt2->simultaneousHARQ_ACK_CSI=calloc(1,sizeof(*pucchfmt2->simultaneousHARQ_ACK_CSI)); + *pucchfmt2->simultaneousHARQ_ACK_CSI=NR_PUCCH_FormatConfig__simultaneousHARQ_ACK_CSI_true; + + // for scheduling requestresource + pucch_Config->schedulingRequestResourceToAddModList = calloc(1,sizeof(*pucch_Config->schedulingRequestResourceToAddModList)); + NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig = calloc(1,sizeof(*schedulingRequestResourceConfig)); + schedulingRequestResourceConfig->schedulingRequestResourceId = 1; + schedulingRequestResourceConfig->schedulingRequestID = 0; + schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset)); + schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10; + schedulingRequestResourceConfig->periodicityAndOffset->choice.sl10 = 7; + schedulingRequestResourceConfig->resource = calloc(1,sizeof(*schedulingRequestResourceConfig->resource)); + *schedulingRequestResourceConfig->resource = 1; + ASN_SEQUENCE_ADD(&pucch_Config->schedulingRequestResourceToAddModList->list,schedulingRequestResourceConfig); + pucch_Config->schedulingRequestResourceToReleaseList=NULL; pucch_Config->multi_CSI_PUCCH_ResourceList=NULL; pucch_Config->dl_DataToUL_ACK = calloc(1,sizeof(*pucch_Config->dl_DataToUL_ACK)); long *delay[8]; for (int i=0;i<8;i++) { delay[i] = calloc(1,sizeof(*delay[i])); - *delay[i] = (i<6) ? (i+2) : 0; + *delay[i] = i+minRXTXTIME; ASN_SEQUENCE_ADD(&pucch_Config->dl_DataToUL_ACK->list,delay[i]); } pucch_Config->spatialRelationInfoToAddModList = calloc(1,sizeof(*pucch_Config->spatialRelationInfoToAddModList)); NR_PUCCH_SpatialRelationInfo_t *pucchspatial = calloc(1,sizeof(*pucchspatial)); pucchspatial->pucch_SpatialRelationInfoId = 1; pucchspatial->servingCellId = NULL; - pucchspatial->referenceSignal.present = NR_PUCCH_SpatialRelationInfo__referenceSignal_PR_csi_RS_Index; - pucchspatial->referenceSignal.choice.csi_RS_Index = 0; + if(do_csirs) { + pucchspatial->referenceSignal.present = NR_PUCCH_SpatialRelationInfo__referenceSignal_PR_csi_RS_Index; + pucchspatial->referenceSignal.choice.csi_RS_Index = 0; + } + else { + pucchspatial->referenceSignal.present = NR_PUCCH_SpatialRelationInfo__referenceSignal_PR_ssb_Index; + pucchspatial->referenceSignal.choice.ssb_Index = 0; + } pucchspatial->pucch_PathlossReferenceRS_Id = 0; pucchspatial->p0_PUCCH_Id = 1; pucchspatial->closedLoopIndex = NR_PUCCH_SpatialRelationInfo__closedLoopIndex_i0; @@ -1073,18 +982,14 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco p00->p0_PUCCH_Id=1; p00->p0_PUCCH_Value = 0; ASN_SEQUENCE_ADD(&pucch_Config->pucch_PowerControl->p0_Set->list,p00); - pucch_Config->pucch_PowerControl->pathlossReferenceRSs = calloc(1,sizeof(*pucch_Config->pucch_PowerControl->pathlossReferenceRSs)); - NR_PUCCH_PathlossReferenceRS_t *pucchPLRef=calloc(1,sizeof(*pucchPLRef)); - pucchPLRef->pucch_PathlossReferenceRS_Id=0; - pucchPLRef->referenceSignal.present = NR_PUCCH_PathlossReferenceRS__referenceSignal_PR_csi_RS_Index; - pucchPLRef->referenceSignal.choice.csi_RS_Index=0; - ASN_SEQUENCE_ADD(&pucch_Config->pucch_PowerControl->pathlossReferenceRSs->list,pucchPLRef); - - // copy pusch_Config from dedicated initialBWP - ubwp->bwp_Dedicated->pusch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pusch_Config)); - ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; - ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config; + pucch_Config->pucch_PowerControl->pathlossReferenceRSs = NULL; + if (!servingcellconfigdedicated) { + // copy pusch_Config from dedicated initialBWP + ubwp->bwp_Dedicated->pusch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pusch_Config)); + ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; + ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config; + } ubwp->bwp_Dedicated->configuredGrantConfig = NULL; ubwp->bwp_Dedicated->srs_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->srs_Config)); ubwp->bwp_Dedicated->srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup; @@ -1092,7 +997,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ubwp->bwp_Dedicated->beamFailureRecoveryConfig = NULL; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); + if (!servingcellconfigdedicated) { + ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = 1; @@ -1121,7 +1028,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig; pdsch_servingcellconfig->codeBlockGroupTransmission = NULL; pdsch_servingcellconfig->xOverhead = NULL; - pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NULL; + pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = calloc(1, sizeof(*pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH)); + *pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16; pdsch_servingcellconfig->pucch_Cell= NULL; pdsch_servingcellconfig->ext1=calloc(1,sizeof(*pdsch_servingcellconfig->ext1)); pdsch_servingcellconfig->ext1->maxMIMO_Layers = calloc(1,sizeof(*pdsch_servingcellconfig->ext1->maxMIMO_Layers)); @@ -1129,899 +1037,339 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pdsch_servingcellconfig->ext1->processingType2Enabled = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig=NULL; - //secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig)); - //secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; - + secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig)); + secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->present = NR_SetupRelease_CSI_MeasConfig_PR_setup; NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1,sizeof(*csi_MeasConfig)); -// secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; - csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)); + secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig; - NR_NZP_CSI_RS_Resource_t *nzpres0 = calloc(1,sizeof(*nzpres0)); - nzpres0->nzp_CSI_RS_ResourceId=0; - nzpres0->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other; - nzpres0->resourceMapping.frequencyDomainAllocation.choice.other.buf = calloc(1,1); - nzpres0->resourceMapping.frequencyDomainAllocation.choice.other.size = 1; - nzpres0->resourceMapping.frequencyDomainAllocation.choice.other.bits_unused = 2; - nzpres0->resourceMapping.frequencyDomainAllocation.choice.other.buf[0]=1<<2; - nzpres0->resourceMapping.nrofPorts = (n_physical_antenna_ports==1)? NR_CSI_RS_ResourceMapping__nrofPorts_p1 : NR_CSI_RS_ResourceMapping__nrofPorts_p2; - nzpres0->resourceMapping.firstOFDMSymbolInTimeDomain=7; - nzpres0->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres0->resourceMapping.cdm_Type = (n_physical_antenna_ports==1)? NR_CSI_RS_ResourceMapping__cdm_Type_noCDM : NR_CSI_RS_ResourceMapping__cdm_Type_fd_CDM2; - nzpres0->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_one; - nzpres0->resourceMapping.density.choice.one=(NULL_t)0; - nzpres0->resourceMapping.freqBand.startingRB=0; - nzpres0->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres0->powerControlOffset=13; - nzpres0->powerControlOffsetSS=NULL; - nzpres0->scramblingID=40; - nzpres0->periodicityAndOffset = calloc(1,sizeof(*nzpres0->periodicityAndOffset)); - nzpres0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; - nzpres0->periodicityAndOffset->choice.slots320 = 2; - nzpres0->qcl_InfoPeriodicCSI_RS=NULL; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres0); - - if (n_physical_antenna_ports > 1) { - NR_NZP_CSI_RS_Resource_t *nzpres2 = calloc(1,sizeof(*nzpres2)); - nzpres2->nzp_CSI_RS_ResourceId=2; - nzpres2->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres2->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres2->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres2->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres2->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=1; - nzpres2->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres2->resourceMapping.firstOFDMSymbolInTimeDomain=4; - nzpres2->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres2->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres2->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres2->resourceMapping.density.choice.three=(NULL_t)0; - nzpres2->resourceMapping.freqBand.startingRB=0; - nzpres2->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres2->powerControlOffset=0; - nzpres2->powerControlOffsetSS=calloc(1,sizeof(*nzpres2->powerControlOffsetSS)); - *nzpres2->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres2->scramblingID=40; - nzpres2->periodicityAndOffset = calloc(1,sizeof(*nzpres2->periodicityAndOffset)); - nzpres2->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres2->periodicityAndOffset->choice.slots160 = 25; - nzpres2->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres2->qcl_InfoPeriodicCSI_RS)); - *nzpres2->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres2); - - - NR_NZP_CSI_RS_Resource_t *nzpres3 = calloc(1,sizeof(*nzpres3)); - nzpres3->nzp_CSI_RS_ResourceId=3; - nzpres3->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres3->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres3->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres3->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres3->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=1; - nzpres3->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres3->resourceMapping.firstOFDMSymbolInTimeDomain=8; - nzpres3->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres3->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres3->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres3->resourceMapping.density.choice.three=(NULL_t)0; - nzpres3->resourceMapping.freqBand.startingRB=0; - nzpres3->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres3->powerControlOffset=0; - nzpres3->powerControlOffsetSS=calloc(1,sizeof(*nzpres3->powerControlOffsetSS)); - *nzpres3->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres3->scramblingID=40; - nzpres3->periodicityAndOffset = calloc(1,sizeof(*nzpres3->periodicityAndOffset)); - nzpres3->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres3->periodicityAndOffset->choice.slots160 = 25; - nzpres3->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres3->qcl_InfoPeriodicCSI_RS)); - *nzpres3->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres3); + if (do_csirs && dl_antenna_ports > 1) { + csi_MeasConfig->csi_IM_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceToAddModList)); + NR_CSI_IM_Resource_t *imres0 = calloc(1,sizeof(*imres0)); + imres0->csi_IM_ResourceId = 0; + imres0->csi_IM_ResourceElementPattern = calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern)); + imres0->csi_IM_ResourceElementPattern->present = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1; + imres0->csi_IM_ResourceElementPattern->choice.pattern1 = calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern->choice.pattern1)); + imres0->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1 = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern__pattern1__subcarrierLocation_p1_s4; + imres0->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1 = 6; + imres0->freqBand = calloc(1,sizeof(*imres0->freqBand)); + imres0->freqBand->startingRB = 0; + imres0->freqBand->nrofRBs = 108; + imres0->periodicityAndOffset = calloc(1,sizeof(*imres0->periodicityAndOffset)); + imres0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; + imres0->periodicityAndOffset->choice.slots320 = 0; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceToAddModList->list,imres0); + csi_MeasConfig->csi_IM_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceSetToAddModList)); + NR_CSI_IM_ResourceSet_t *imset0 = calloc(1,sizeof(*imset0)); + imset0->csi_IM_ResourceSetId = 0; + NR_CSI_IM_ResourceId_t *res0 = calloc(1,sizeof(*res0)); + *res0 = 0; + ASN_SEQUENCE_ADD(&imset0->csi_IM_Resources,res0); + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceSetToAddModList->list,imset0); } - if (n_physical_antenna_ports > 3) { - NR_NZP_CSI_RS_Resource_t *nzpres4 = calloc(1,sizeof(*nzpres4)); - nzpres4->nzp_CSI_RS_ResourceId=4; - nzpres4->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres4->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres4->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres4->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres4->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=1; - nzpres4->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres4->resourceMapping.firstOFDMSymbolInTimeDomain=4; - nzpres4->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres4->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres4->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres4->resourceMapping.density.choice.three=(NULL_t)0; - nzpres4->resourceMapping.freqBand.startingRB=0; - nzpres4->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres4->powerControlOffset=0; - nzpres4->powerControlOffsetSS=calloc(1,sizeof(*nzpres4->powerControlOffsetSS)); - *nzpres4->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres4->scramblingID=40; - nzpres4->periodicityAndOffset = calloc(1,sizeof(*nzpres4->periodicityAndOffset)); - nzpres4->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres4->periodicityAndOffset->choice.slots160 = 26; - nzpres4->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres4->qcl_InfoPeriodicCSI_RS)); - *nzpres4->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres4); - - NR_NZP_CSI_RS_Resource_t *nzpres5 = calloc(1,sizeof(*nzpres5)); - nzpres5->nzp_CSI_RS_ResourceId=5; - nzpres5->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres5->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres5->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres5->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres5->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=1; - nzpres5->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres5->resourceMapping.firstOFDMSymbolInTimeDomain=8; - nzpres5->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres5->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres5->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres5->resourceMapping.density.choice.three=(NULL_t)0; - nzpres5->resourceMapping.freqBand.startingRB=0; - nzpres5->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres5->powerControlOffset=0; - nzpres5->powerControlOffsetSS=calloc(1,sizeof(*nzpres5->powerControlOffsetSS)); - *nzpres5->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres5->scramblingID=40; - nzpres5->periodicityAndOffset = calloc(1,sizeof(*nzpres5->periodicityAndOffset)); - nzpres5->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres5->periodicityAndOffset->choice.slots160 = 26; - nzpres5->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres5->qcl_InfoPeriodicCSI_RS)); - *nzpres5->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres5); - } - if (n_physical_antenna_ports > 7) { - NR_NZP_CSI_RS_Resource_t *nzpres6 = calloc(1,sizeof(*nzpres6)); - nzpres6->nzp_CSI_RS_ResourceId=6; - nzpres6->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres6->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres6->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres6->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres6->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=4; - nzpres6->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres6->resourceMapping.firstOFDMSymbolInTimeDomain=4; - nzpres6->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres6->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres6->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres6->resourceMapping.density.choice.three=(NULL_t)0; - nzpres6->resourceMapping.freqBand.startingRB=0; - nzpres6->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres6->powerControlOffset=0; - nzpres6->powerControlOffsetSS=calloc(1,sizeof(*nzpres6->powerControlOffsetSS)); - *nzpres6->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres6->scramblingID=40; - nzpres6->periodicityAndOffset = calloc(1,sizeof(*nzpres6->periodicityAndOffset)); - nzpres6->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres6->periodicityAndOffset->choice.slots160 = 25; - nzpres6->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres6->qcl_InfoPeriodicCSI_RS)); - *nzpres6->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres6); - - NR_NZP_CSI_RS_Resource_t *nzpres7 = calloc(1,sizeof(*nzpres7)); - nzpres7->nzp_CSI_RS_ResourceId=7; - nzpres7->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres7->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres7->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres7->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres7->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=4; - nzpres7->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres7->resourceMapping.firstOFDMSymbolInTimeDomain=8; - nzpres7->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres7->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres7->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres7->resourceMapping.density.choice.three=(NULL_t)0; - nzpres7->resourceMapping.freqBand.startingRB=0; - nzpres7->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres7->powerControlOffset=0; - nzpres7->powerControlOffsetSS=calloc(1,sizeof(*nzpres7->powerControlOffsetSS)); - *nzpres7->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres7->scramblingID=40; - nzpres7->periodicityAndOffset = calloc(1,sizeof(*nzpres7->periodicityAndOffset)); - nzpres7->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres7->periodicityAndOffset->choice.slots160 = 25; - nzpres7->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres7->qcl_InfoPeriodicCSI_RS)); - *nzpres7->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres7); - NR_NZP_CSI_RS_Resource_t *nzpres8 = calloc(1,sizeof(*nzpres8)); - nzpres8->nzp_CSI_RS_ResourceId=8; - nzpres8->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres8->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres8->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres8->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres8->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=4; - nzpres8->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres8->resourceMapping.firstOFDMSymbolInTimeDomain=4; - nzpres8->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres8->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres8->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres8->resourceMapping.density.choice.three=(NULL_t)0; - nzpres8->resourceMapping.freqBand.startingRB=0; - nzpres8->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres8->powerControlOffset=0; - nzpres8->powerControlOffsetSS=calloc(1,sizeof(*nzpres8->powerControlOffsetSS)); - *nzpres8->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres8->scramblingID=40; - nzpres8->periodicityAndOffset = calloc(1,sizeof(*nzpres8->periodicityAndOffset)); - nzpres8->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres8->periodicityAndOffset->choice.slots160 = 26; - nzpres8->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres8->qcl_InfoPeriodicCSI_RS)); - *nzpres8->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres8); - - NR_NZP_CSI_RS_Resource_t *nzpres9 = calloc(1,sizeof(*nzpres9)); - nzpres9->nzp_CSI_RS_ResourceId=9; - nzpres9->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres9->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres9->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres9->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres9->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=4; - nzpres9->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres9->resourceMapping.firstOFDMSymbolInTimeDomain=8; - nzpres9->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres9->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres9->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres9->resourceMapping.density.choice.three=(NULL_t)0; - nzpres9->resourceMapping.freqBand.startingRB=0; - nzpres9->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres9->powerControlOffset=0; - nzpres9->powerControlOffsetSS=calloc(1,sizeof(*nzpres9->powerControlOffsetSS)); - *nzpres9->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres9->scramblingID=40; - nzpres9->periodicityAndOffset = calloc(1,sizeof(*nzpres9->periodicityAndOffset)); - nzpres9->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres9->periodicityAndOffset->choice.slots160 = 26; - nzpres9->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres9->qcl_InfoPeriodicCSI_RS)); - *nzpres9->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres9); - } - if (n_physical_antenna_ports > 15) { - NR_NZP_CSI_RS_Resource_t *nzpres10 = calloc(1,sizeof(*nzpres10)); - nzpres10->nzp_CSI_RS_ResourceId=10; - nzpres10->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres10->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres10->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres10->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres10->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=2; - nzpres10->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres10->resourceMapping.firstOFDMSymbolInTimeDomain=4; - nzpres10->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres10->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres10->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres10->resourceMapping.density.choice.three=(NULL_t)0; - nzpres10->resourceMapping.freqBand.startingRB=0; - nzpres10->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres10->powerControlOffset=0; - nzpres10->powerControlOffsetSS=calloc(1,sizeof(*nzpres10->powerControlOffsetSS)); - *nzpres10->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres10->scramblingID=40; - nzpres10->periodicityAndOffset = calloc(1,sizeof(*nzpres10->periodicityAndOffset)); - nzpres10->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres10->periodicityAndOffset->choice.slots160 = 25; - nzpres10->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres10->qcl_InfoPeriodicCSI_RS)); - *nzpres10->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres10); - - NR_NZP_CSI_RS_Resource_t *nzpres11 = calloc(1,sizeof(*nzpres11)); - nzpres11->nzp_CSI_RS_ResourceId=11; - nzpres11->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres11->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres11->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres11->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres11->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=2; - nzpres11->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres11->resourceMapping.firstOFDMSymbolInTimeDomain=8; - nzpres11->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres11->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres11->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres11->resourceMapping.density.choice.three=(NULL_t)0; - nzpres11->resourceMapping.freqBand.startingRB=0; - nzpres11->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres11->powerControlOffset=0; - nzpres11->powerControlOffsetSS=calloc(1,sizeof(*nzpres11->powerControlOffsetSS)); - *nzpres11->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres11->scramblingID=40; - nzpres11->periodicityAndOffset = calloc(1,sizeof(*nzpres11->periodicityAndOffset)); - nzpres11->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres11->periodicityAndOffset->choice.slots160 = 25; - nzpres11->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres11->qcl_InfoPeriodicCSI_RS)); - *nzpres11->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres11); - NR_NZP_CSI_RS_Resource_t *nzpres12 = calloc(1,sizeof(*nzpres12)); - nzpres12->nzp_CSI_RS_ResourceId=12; - nzpres12->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres12->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres12->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres12->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres12->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=2; - nzpres12->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres12->resourceMapping.firstOFDMSymbolInTimeDomain=4; - nzpres12->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres12->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres12->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres12->resourceMapping.density.choice.three=(NULL_t)0; - nzpres12->resourceMapping.freqBand.startingRB=0; - nzpres12->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres12->powerControlOffset=0; - nzpres12->powerControlOffsetSS=calloc(1,sizeof(*nzpres12->powerControlOffsetSS)); - *nzpres12->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres12->scramblingID=40; - nzpres12->periodicityAndOffset = calloc(1,sizeof(*nzpres12->periodicityAndOffset)); - nzpres12->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres12->periodicityAndOffset->choice.slots160 = 26; - nzpres12->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres12->qcl_InfoPeriodicCSI_RS)); - *nzpres12->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres12); - - NR_NZP_CSI_RS_Resource_t *nzpres13 = calloc(1,sizeof(*nzpres13)); - nzpres13->nzp_CSI_RS_ResourceId=13; - nzpres13->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres13->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres13->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres13->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres13->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=2; - nzpres13->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres13->resourceMapping.firstOFDMSymbolInTimeDomain=8; - nzpres13->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres13->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres13->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres13->resourceMapping.density.choice.three=(NULL_t)0; - nzpres13->resourceMapping.freqBand.startingRB=0; - nzpres13->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres13->powerControlOffset=0; - nzpres13->powerControlOffsetSS=calloc(1,sizeof(*nzpres13->powerControlOffsetSS)); - *nzpres13->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres13->scramblingID=40; - nzpres13->periodicityAndOffset = calloc(1,sizeof(*nzpres13->periodicityAndOffset)); - nzpres13->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres13->periodicityAndOffset->choice.slots160 = 26; - nzpres13->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres13->qcl_InfoPeriodicCSI_RS)); - *nzpres13->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres13); - NR_NZP_CSI_RS_Resource_t *nzpres14 = calloc(1,sizeof(*nzpres14)); - nzpres14->nzp_CSI_RS_ResourceId=14; - nzpres14->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres14->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres14->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres14->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres14->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=8; - nzpres14->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres14->resourceMapping.firstOFDMSymbolInTimeDomain=4; - nzpres14->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres14->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres14->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres14->resourceMapping.density.choice.three=(NULL_t)0; - nzpres14->resourceMapping.freqBand.startingRB=0; - nzpres14->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres14->powerControlOffset=0; - nzpres14->powerControlOffsetSS=calloc(1,sizeof(*nzpres14->powerControlOffsetSS)); - *nzpres14->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres14->scramblingID=40; - nzpres14->periodicityAndOffset = calloc(1,sizeof(*nzpres14->periodicityAndOffset)); - nzpres14->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres14->periodicityAndOffset->choice.slots160 = 25; - nzpres14->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres14->qcl_InfoPeriodicCSI_RS)); - *nzpres14->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres14); - - NR_NZP_CSI_RS_Resource_t *nzpres15 = calloc(1,sizeof(*nzpres15)); - nzpres15->nzp_CSI_RS_ResourceId=15; - nzpres15->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres15->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres15->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres15->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres15->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=8; - nzpres15->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres15->resourceMapping.firstOFDMSymbolInTimeDomain=8; - nzpres15->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres15->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres15->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres15->resourceMapping.density.choice.three=(NULL_t)0; - nzpres15->resourceMapping.freqBand.startingRB=0; - nzpres15->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres15->powerControlOffset=0; - nzpres15->powerControlOffsetSS=calloc(1,sizeof(*nzpres15->powerControlOffsetSS)); - *nzpres15->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres15->scramblingID=40; - nzpres15->periodicityAndOffset = calloc(1,sizeof(*nzpres15->periodicityAndOffset)); - nzpres15->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres15->periodicityAndOffset->choice.slots160 = 25; - nzpres15->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres15->qcl_InfoPeriodicCSI_RS)); - *nzpres15->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres15); - NR_NZP_CSI_RS_Resource_t *nzpres16 = calloc(1,sizeof(*nzpres16)); - nzpres16->nzp_CSI_RS_ResourceId=16; - nzpres16->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres16->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres16->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres16->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres16->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=8; - nzpres16->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres16->resourceMapping.firstOFDMSymbolInTimeDomain=5; - nzpres16->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres16->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres16->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres16->resourceMapping.density.choice.three=(NULL_t)0; - nzpres16->resourceMapping.freqBand.startingRB=0; - nzpres16->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres16->powerControlOffset=0; - nzpres16->powerControlOffsetSS=calloc(1,sizeof(*nzpres16->powerControlOffsetSS)); - *nzpres16->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres16->scramblingID=40; - nzpres16->periodicityAndOffset = calloc(1,sizeof(*nzpres16->periodicityAndOffset)); - nzpres16->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres16->periodicityAndOffset->choice.slots160 = 26; - nzpres16->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres16->qcl_InfoPeriodicCSI_RS)); - *nzpres16->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres16); - - NR_NZP_CSI_RS_Resource_t *nzpres17 = calloc(1,sizeof(*nzpres17)); - nzpres17->nzp_CSI_RS_ResourceId=9; - nzpres17->resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1; - nzpres17->resourceMapping.frequencyDomainAllocation.choice.row1.buf = calloc(1,1); - nzpres17->resourceMapping.frequencyDomainAllocation.choice.row1.size = 1; - nzpres17->resourceMapping.frequencyDomainAllocation.choice.row1.bits_unused = 4; - nzpres17->resourceMapping.frequencyDomainAllocation.choice.row1.buf[0]=8; - nzpres17->resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; - nzpres17->resourceMapping.firstOFDMSymbolInTimeDomain=9; - nzpres17->resourceMapping.firstOFDMSymbolInTimeDomain2=NULL; - nzpres17->resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; - nzpres17->resourceMapping.density.present=NR_CSI_RS_ResourceMapping__density_PR_three; - nzpres17->resourceMapping.density.choice.three=(NULL_t)0; - nzpres17->resourceMapping.freqBand.startingRB=0; - nzpres17->resourceMapping.freqBand.nrofRBs= servingcellconfigcommon->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - nzpres17->powerControlOffset=0; - nzpres17->powerControlOffsetSS=calloc(1,sizeof(*nzpres17->powerControlOffsetSS)); - *nzpres17->powerControlOffsetSS=NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; - nzpres17->scramblingID=40; - nzpres17->periodicityAndOffset = calloc(1,sizeof(*nzpres17->periodicityAndOffset)); - nzpres17->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots160; - nzpres17->periodicityAndOffset->choice.slots160 = 26; - nzpres17->qcl_InfoPeriodicCSI_RS=calloc(1,sizeof(*nzpres17->qcl_InfoPeriodicCSI_RS)); - *nzpres17->qcl_InfoPeriodicCSI_RS=8; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpres17); + else { + csi_MeasConfig->csi_IM_ResourceToAddModList = NULL; + csi_MeasConfig->csi_IM_ResourceSetToAddModList = NULL; } - if (n_physical_antenna_ports > 16) AssertFatal(1==0,"Fill in for more than 16 antenna elements\n"); - - csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList)); - csi_MeasConfig->nzp_CSI_RS_ResourceSetToReleaseList = NULL; - NR_NZP_CSI_RS_ResourceSet_t *nzpresset0=calloc(1,sizeof(*nzpresset0)); - nzpresset0->nzp_CSI_ResourceSetId=0; - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset00=calloc(1,sizeof(*nzpresset00)); - *nzpresset00=0; - ASN_SEQUENCE_ADD(&nzpresset0->nzp_CSI_RS_Resources.list,nzpresset00); - nzpresset0->repetition=NULL; - nzpresset0->aperiodicTriggeringOffset=NULL; - nzpresset0->trs_Info=NULL; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpresset0); - if (n_physical_antenna_ports > 1) { - NR_NZP_CSI_RS_ResourceSet_t *nzpresset3=calloc(1,sizeof(*nzpresset3)); - nzpresset3->nzp_CSI_ResourceSetId=3; - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset30=calloc(1,sizeof(*nzpresset30)); - *nzpresset30=2; - ASN_SEQUENCE_ADD(&nzpresset3->nzp_CSI_RS_Resources.list,nzpresset30); - if (n_physical_antenna_ports > 3) { - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset31=calloc(1,sizeof(*nzpresset31)); - *nzpresset31=3; - ASN_SEQUENCE_ADD(&nzpresset3->nzp_CSI_RS_Resources.list,nzpresset31); - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset32=calloc(1,sizeof(*nzpresset32)); - *nzpresset32=4; - ASN_SEQUENCE_ADD(&nzpresset3->nzp_CSI_RS_Resources.list,nzpresset32); - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset33=calloc(1,sizeof(*nzpresset33)); - *nzpresset33=5; - ASN_SEQUENCE_ADD(&nzpresset3->nzp_CSI_RS_Resources.list,nzpresset33); - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpresset3); - } - nzpresset3->repetition=calloc(1,sizeof(*nzpresset3->repetition)); - *nzpresset3->repetition=NR_NZP_CSI_RS_ResourceSet__repetition_off; - nzpresset3->aperiodicTriggeringOffset=NULL; - nzpresset3->trs_Info=calloc(1,sizeof(*nzpresset3->trs_Info)); - *nzpresset3->trs_Info=NR_NZP_CSI_RS_ResourceSet__trs_Info_true; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpresset3); - } - - if (n_physical_antenna_ports > 7) { - NR_NZP_CSI_RS_ResourceSet_t *nzpresset4=calloc(1,sizeof(*nzpresset4)); - nzpresset4->nzp_CSI_ResourceSetId=4; - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset40=calloc(1,sizeof(*nzpresset40)); - *nzpresset40=6; - ASN_SEQUENCE_ADD(&nzpresset4->nzp_CSI_RS_Resources.list,nzpresset40); - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset41=calloc(1,sizeof(*nzpresset41)); - *nzpresset41=7; - ASN_SEQUENCE_ADD(&nzpresset4->nzp_CSI_RS_Resources.list,nzpresset41); - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset42=calloc(1,sizeof(*nzpresset42)); - *nzpresset42=8; - ASN_SEQUENCE_ADD(&nzpresset4->nzp_CSI_RS_Resources.list,nzpresset42); - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset43=calloc(1,sizeof(*nzpresset43)); - *nzpresset43=9; - ASN_SEQUENCE_ADD(&nzpresset4->nzp_CSI_RS_Resources.list,nzpresset43); - nzpresset4->repetition=calloc(1,sizeof(*nzpresset4->repetition)); - *nzpresset4->repetition=NR_NZP_CSI_RS_ResourceSet__repetition_off; - nzpresset4->aperiodicTriggeringOffset=NULL; - nzpresset4->trs_Info=calloc(1,sizeof(*nzpresset4->trs_Info)); - *nzpresset4->trs_Info=NR_NZP_CSI_RS_ResourceSet__trs_Info_true; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpresset4); - } - if (n_physical_antenna_ports > 15) { - NR_NZP_CSI_RS_ResourceSet_t *nzpresset5=calloc(1,sizeof(*nzpresset5)); - nzpresset5->nzp_CSI_ResourceSetId=5; - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset50=calloc(1,sizeof(*nzpresset50)); - *nzpresset50=10; - ASN_SEQUENCE_ADD(&nzpresset5->nzp_CSI_RS_Resources.list,nzpresset50); - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset51=calloc(1,sizeof(*nzpresset51)); - *nzpresset51=11; - ASN_SEQUENCE_ADD(&nzpresset5->nzp_CSI_RS_Resources.list,nzpresset51); - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset52=calloc(1,sizeof(*nzpresset52)); - *nzpresset52=12; - ASN_SEQUENCE_ADD(&nzpresset5->nzp_CSI_RS_Resources.list,nzpresset52); - NR_NZP_CSI_RS_ResourceSetId_t *nzpresset53=calloc(1,sizeof(*nzpresset53)); - *nzpresset53=13; - ASN_SEQUENCE_ADD(&nzpresset5->nzp_CSI_RS_Resources.list,nzpresset53); - nzpresset5->repetition=calloc(1,sizeof(*nzpresset5->repetition)); - *nzpresset5->repetition=NR_NZP_CSI_RS_ResourceSet__repetition_off; - nzpresset5->aperiodicTriggeringOffset=NULL; - nzpresset5->trs_Info=calloc(1,sizeof(*nzpresset5->trs_Info)); - *nzpresset5->trs_Info=NR_NZP_CSI_RS_ResourceSet__trs_Info_true; - ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpresset5); - } - - csi_MeasConfig->csi_IM_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceToAddModList)); csi_MeasConfig->csi_IM_ResourceToReleaseList = NULL; - NR_CSI_IM_Resource_t *imres0 = calloc(1,sizeof(*imres0)); - imres0->csi_IM_ResourceId=0; - imres0->csi_IM_ResourceElementPattern=calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern)); - imres0->csi_IM_ResourceElementPattern->present = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1 ; - imres0->csi_IM_ResourceElementPattern->choice.pattern1=calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern->choice.pattern1)); - imres0->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1 = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern__pattern1__subcarrierLocation_p1_s4; - imres0->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1=7; - imres0->freqBand=calloc(1,sizeof(*imres0->freqBand)); - imres0->freqBand->startingRB=0; - imres0->freqBand->nrofRBs=106; - imres0->periodicityAndOffset=calloc(1,sizeof(*imres0->periodicityAndOffset)); - imres0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; - imres0->periodicityAndOffset->choice.slots320 = 2; - ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceToAddModList->list,imres0); - csi_MeasConfig->csi_IM_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceSetToAddModList)); + csi_MeasConfig->csi_IM_ResourceSetToAddModList = NULL; csi_MeasConfig->csi_IM_ResourceSetToReleaseList = NULL; - NR_CSI_IM_ResourceSet_t *imresset0 = calloc(1,sizeof(*imresset0)); - imresset0->csi_IM_ResourceSetId=0; - NR_CSI_IM_ResourceId_t *imresset00=calloc(1,sizeof(*imresset00)); - *imresset00=0; - ASN_SEQUENCE_ADD(&imresset0->csi_IM_Resources.list,imresset00); - ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceSetToAddModList->list,imresset0); - + + if (do_csirs) { + csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList)); + NR_NZP_CSI_RS_ResourceSet_t *nzpcsirs0 = calloc(1,sizeof(*nzpcsirs0)); + nzpcsirs0->nzp_CSI_ResourceSetId = 0; + NR_NZP_CSI_RS_ResourceId_t *nzpid0 = calloc(1,sizeof(*nzpid0)); + *nzpid0 = 0; + ASN_SEQUENCE_ADD(&nzpcsirs0->nzp_CSI_RS_Resources,nzpid0); + nzpcsirs0->repetition = NULL; + nzpcsirs0->aperiodicTriggeringOffset = NULL; + nzpcsirs0->trs_Info = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpcsirs0); + } + else + csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList = NULL; + + csi_MeasConfig->nzp_CSI_RS_ResourceSetToReleaseList = NULL; + + config_csirs(servingcellconfigcommon, csi_MeasConfig,dl_antenna_ports,do_csirs); + csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList)); csi_MeasConfig->csi_SSB_ResourceSetToReleaseList = NULL; + NR_CSI_SSB_ResourceSet_t *ssbresset0 = calloc(1,sizeof(*ssbresset0)); - ssbresset0->csi_SSB_ResourceSetId=0; - NR_SSB_Index_t *ssbresset00=calloc(1,sizeof(*ssbresset00)); - *ssbresset00=0; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset00); - if (n_physical_antenna_ports > 1) { - NR_SSB_Index_t *ssbresset01=calloc(1,sizeof(*ssbresset01)); - *ssbresset01=1; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset01); - } - if (n_physical_antenna_ports > 3) { - NR_SSB_Index_t *ssbresset02=calloc(1,sizeof(*ssbresset02)); - *ssbresset02=2; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset02); - NR_SSB_Index_t *ssbresset03=calloc(1,sizeof(*ssbresset03)); - *ssbresset03=3; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset03); - } - if (n_physical_antenna_ports > 7) { - NR_SSB_Index_t *ssbresset04=calloc(1,sizeof(*ssbresset04)); - *ssbresset04=4; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset04); - NR_SSB_Index_t *ssbresset05=calloc(1,sizeof(*ssbresset05)); - *ssbresset05=5; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset05); - NR_SSB_Index_t *ssbresset06=calloc(1,sizeof(*ssbresset06)); - *ssbresset06=6; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset06); - NR_SSB_Index_t *ssbresset07=calloc(1,sizeof(*ssbresset07)); - *ssbresset07=7; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset07); + ssbresset0->csi_SSB_ResourceSetId=0; + + NR_SSB_Index_t *ssbresset[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ + ssbresset[i]=calloc(1,sizeof(*ssbresset[i])); + *ssbresset[i] = i; + ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset[i]); + } } ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list,ssbresset0); csi_MeasConfig->csi_ResourceConfigToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_ResourceConfigToAddModList)); - csi_MeasConfig->csi_ResourceConfigToReleaseList = NULL; - NR_CSI_ResourceConfig_t *csires0 = calloc(1,sizeof(*csires0)); - csires0->csi_ResourceConfigId=0; - csires0->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires00 = calloc(1,sizeof(*csires00)); - *csires00 = 0; - ASN_SEQUENCE_ADD(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires00); - csires0->bwp_Id = 1; - csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires0); - NR_CSI_ResourceConfig_t *csires11 = calloc(1,sizeof(*csires11)); - csires11->csi_ResourceConfigId=11; - csires11->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_csi_IM_ResourceSetList; - csires11->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList = calloc(1,sizeof(*csires11->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList)); - NR_NZP_CSI_RS_ResourceSetId_t *csires110 = calloc(1,sizeof(*csires110)); - *csires110 = 0; - ASN_SEQUENCE_ADD(&csires11->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list,csires110); - csires11->bwp_Id = 1; - csires11->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires11); + if (do_csirs) { + csi_MeasConfig->csi_ResourceConfigToReleaseList = NULL; + NR_CSI_ResourceConfig_t *csires0 = calloc(1,sizeof(*csires0)); + csires0->csi_ResourceConfigId=0; + csires0->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; + csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); + csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); + NR_NZP_CSI_RS_ResourceSetId_t *nzp0 = calloc(1,sizeof(*nzp0)); + *nzp0 = 0; + ASN_SEQUENCE_ADD(&csires0->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,nzp0); + csires0->bwp_Id = 1; + csires0->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires0); + } - NR_CSI_ResourceConfig_t *csires10 = calloc(1,sizeof(*csires10)); - csires10->csi_ResourceConfigId=10; - csires10->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires10->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires10->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires10->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires10->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires10->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires100 = calloc(1,sizeof(*csires100)); - *csires100 = 0; - ASN_SEQUENCE_ADD(&csires10->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires100); - csires10->bwp_Id = 1; - csires10->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires10); + NR_CSI_ResourceConfig_t *csires1 = calloc(1,sizeof(*csires1)); + csires1->csi_ResourceConfigId=1; + csires1->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; + csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); + csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = calloc(1,sizeof(*csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList)); + NR_CSI_SSB_ResourceSetId_t *ssbres00 = calloc(1,sizeof(*ssbres00)); + *ssbres00 = 0; + ASN_SEQUENCE_ADD(&csires1->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list,ssbres00); + csires1->bwp_Id = 1; + csires1->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires1); - NR_CSI_ResourceConfig_t *csires2 = calloc(1,sizeof(*csires2)); - csires2->csi_ResourceConfigId=2; - csires2->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires2->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires2->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires2->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires2->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires2->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires20 = calloc(1,sizeof(*csires20)); - *csires20 = 0; - ASN_SEQUENCE_ADD(&csires2->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires20); - csires2->bwp_Id = 1; - csires2->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires2); + if (do_csirs && dl_antenna_ports > 1) { + NR_CSI_ResourceConfig_t *csires2 = calloc(1,sizeof(*csires2)); + csires2->csi_ResourceConfigId=2; + csires2->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_csi_IM_ResourceSetList; + csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList = calloc(1,sizeof(*csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList)); + NR_CSI_IM_ResourceSetId_t *csiim00 = calloc(1,sizeof(*csiim00)); + *csiim00 = 0; + ASN_SEQUENCE_ADD(&csires2->csi_RS_ResourceSetList.choice.csi_IM_ResourceSetList->list,csiim00); + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires2); + } - NR_CSI_ResourceConfig_t *csires3 = calloc(1,sizeof(*csires3)); - csires3->csi_ResourceConfigId=3; - csires3->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires3->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires3->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires3->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires3->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires3->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires30 = calloc(1,sizeof(*csires30)); - *csires30 = 0; - ASN_SEQUENCE_ADD(&csires3->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires30); - csires3->bwp_Id = 1; - csires3->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires3); - - NR_CSI_ResourceConfig_t *csires4 = calloc(1,sizeof(*csires4)); - csires4->csi_ResourceConfigId=4; - csires4->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires4->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires4->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires4->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires4->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires4->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires40 = calloc(1,sizeof(*csires40)); - *csires40 = 0; - ASN_SEQUENCE_ADD(&csires4->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires40); - csires4->bwp_Id = 1; - csires4->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires4); - - NR_CSI_ResourceConfig_t *csires5 = calloc(1,sizeof(*csires5)); - csires5->csi_ResourceConfigId=5; - csires5->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires5->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires5->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires5->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires5->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires5->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires50 = calloc(1,sizeof(*csires50)); - *csires50 = 0; - ASN_SEQUENCE_ADD(&csires5->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires50); - csires5->bwp_Id = 1; - csires5->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires5); - - NR_CSI_ResourceConfig_t *csires6 = calloc(1,sizeof(*csires6)); - csires6->csi_ResourceConfigId=6; - csires6->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires6->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires6->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires6->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires6->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires6->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires60 = calloc(1,sizeof(*csires60)); - *csires60 = 0; - ASN_SEQUENCE_ADD(&csires6->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires60); - csires6->bwp_Id = 1; - csires6->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires6); - - NR_CSI_ResourceConfig_t *csires7 = calloc(1,sizeof(*csires7)); - csires7->csi_ResourceConfigId=7; - csires7->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires7->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires7->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires7->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires7->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires7->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires70 = calloc(1,sizeof(*csires70)); - *csires70 = 0; - ASN_SEQUENCE_ADD(&csires7->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires70); - csires7->bwp_Id = 1; - csires7->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires7); - - NR_CSI_ResourceConfig_t *csires8 = calloc(1,sizeof(*csires8)); - csires8->csi_ResourceConfigId=8; - csires8->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires8->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires8->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires8->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires8->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires8->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires80 = calloc(1,sizeof(*csires80)); - *csires80 = 0; - ASN_SEQUENCE_ADD(&csires8->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires80); - csires8->bwp_Id = 1; - csires8->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires8); - - NR_CSI_ResourceConfig_t *csires9 = calloc(1,sizeof(*csires9)); - csires9->csi_ResourceConfigId=9; - csires9->csi_RS_ResourceSetList.present = NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB; - csires9->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB = calloc(1,sizeof(*csires9->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB)); - csires9->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList = calloc(1,sizeof(*csires9->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)); - csires9->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList = NULL; - NR_NZP_CSI_RS_ResourceSetId_t *csires90 = calloc(1,sizeof(*csires90)); - *csires90 = 0; - ASN_SEQUENCE_ADD(&csires9->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list,csires90); - csires9->bwp_Id = 1; - csires9->resourceType = NR_CSI_ResourceConfig__resourceType_periodic; - //ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ResourceConfigToAddModList->list,csires9); + NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1,sizeof(*pucchcsires1)); + pucchcsires1->uplinkBandwidthPartId=1; + pucchcsires1->pucch_Resource=2; csi_MeasConfig->csi_ReportConfigToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_ReportConfigToAddModList)); csi_MeasConfig->csi_ReportConfigToReleaseList = NULL; - NR_CSI_ReportConfig_t *csirep0 = calloc(1,sizeof(*csirep0)); - csirep0->reportConfigId=0; - csirep0->carrier=NULL; - csirep0->resourcesForChannelMeasurement=0; - csirep0->csi_IM_ResourcesForInterference=calloc(1,sizeof(*csirep0->csi_IM_ResourcesForInterference)); - *csirep0->csi_IM_ResourcesForInterference=11; - csirep0->nzp_CSI_RS_ResourcesForInterference=NULL; - csirep0->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; - csirep0->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep0->reportConfigType.choice.periodic)); - csirep0->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; - csirep0->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 9; - - NR_PUCCH_CSI_Resource_t *pucchcsires0 = calloc(1,sizeof(*pucchcsires0)); - pucchcsires0->uplinkBandwidthPartId=1; - pucchcsires0->pucch_Resource=11; - ASN_SEQUENCE_ADD(&csirep0->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires0); - csirep0->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI; - csirep0->reportQuantity.choice.cri_RI_PMI_CQI = (NULL_t)0; - csirep0->reportFreqConfiguration = calloc(1,sizeof(*csirep0->reportFreqConfiguration)); - csirep0->reportFreqConfiguration->cqi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI; - csirep0->reportFreqConfiguration->pmi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__pmi_FormatIndicator_widebandPMI; - csirep0->reportFreqConfiguration->csi_ReportingBand=calloc(1,sizeof(*csirep0->reportFreqConfiguration->csi_ReportingBand)); - - - AssertFatal(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id>0,"firstActiveDownlinkBWP_Id %d\n",(int)*secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id); - int NPRB = NRRIV2BW(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[*secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id-1]->bwp_Common->genericParameters.locationAndBandwidth,275); - int sbsize = get_subband_size(NPRB,0); - int numsb = NPRB/sbsize; - if (NPRB%sbsize == 0) numsb++; - csirep0->reportFreqConfiguration->csi_ReportingBand->present= NR_CSI_ReportConfig__reportFreqConfiguration__csi_ReportingBand_PR_NOTHING+(numsb-2); - csirep0->reportFreqConfiguration->csi_ReportingBand->choice.subbands18.size=numsb/8; - if ((numsb&7) > 0) csirep0->reportFreqConfiguration->csi_ReportingBand->choice.subbands18.size++; - csirep0->reportFreqConfiguration->csi_ReportingBand->choice.subbands18.bits_unused = (8-(numsb&7))&7; - csirep0->reportFreqConfiguration->csi_ReportingBand->choice.subbands18.buf=malloc(csirep0->reportFreqConfiguration->csi_ReportingBand->choice.subbands18.size); - for (int i=0;ireportFreqConfiguration->csi_ReportingBand->choice.subbands18.size;i++) - csirep0->reportFreqConfiguration->csi_ReportingBand->choice.subbands18.buf[i]=0xff; - csirep0->reportFreqConfiguration->csi_ReportingBand->choice.subbands18.buf[csirep0->reportFreqConfiguration->csi_ReportingBand->choice.subbands18.size-1]&=~((1<reportFreqConfiguration->csi_ReportingBand->choice.subbands18.bits_unused)-1); - - csirep0->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; - csirep0->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; - csirep0->codebookConfig=calloc(1,sizeof(*csirep0->codebookConfig)); - csirep0->codebookConfig->codebookType.present = NR_CodebookConfig__codebookType_PR_type1; - csirep0->codebookConfig->codebookType.choice.type1 = calloc(1,sizeof(*csirep0->codebookConfig->codebookType.choice.type1)); - csirep0->codebookConfig->codebookType.choice.type1->subType.present = NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel; - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel=calloc(1,sizeof(*csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel)); - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present=NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two; - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two= - calloc(1,sizeof(*csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two)); - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.size=1; - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.bits_unused=2; - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.buf=malloc(1); - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.buf[0]=0xfc; - //'111111'B - - - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.size=1; - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.bits_unused=0; - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf=malloc(1); - csirep0->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]=0xc0; //'00000011'B - - csirep0->codebookConfig->codebookType.choice.type1->codebookMode=1; - csirep0->dummy = NULL; - csirep0->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; - csirep0->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep0->groupBasedBeamReporting.choice.disabled)); - csirep0->groupBasedBeamReporting.choice.disabled->nrofReportedRS = NULL; - csirep0->cqi_Table = calloc(1,sizeof(*csirep0->cqi_Table)); - *csirep0->cqi_Table = NR_CSI_ReportConfig__cqi_Table_table1; - csirep0->subbandSize = NR_CSI_ReportConfig__subbandSize_value1; - csirep0->non_PMI_PortIndication = NULL; - csirep0->ext1 = NULL; - - ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep0); - - NR_CSI_ReportConfig_t *csirep1 = calloc(1,sizeof(*csirep1)); - csirep1->reportConfigId=2; - csirep1->carrier=NULL; - csirep1->resourcesForChannelMeasurement=initial_csi_index; - csirep1->csi_IM_ResourcesForInterference=NULL; - csirep1->nzp_CSI_RS_ResourcesForInterference=NULL; - csirep1->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; - csirep1->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep1->reportConfigType.choice.periodic)); - csirep1->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; - csirep1->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 49; - NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1,sizeof(*pucchcsires1)); - pucchcsires1->uplinkBandwidthPartId=1; - pucchcsires1->pucch_Resource=12; - ASN_SEQUENCE_ADD(&csirep1->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); - csirep1->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP; - csirep1->reportQuantity.choice.ssb_Index_RSRP=(NULL_t)0; - csirep1->reportFreqConfiguration = calloc(1,sizeof(*csirep1->reportFreqConfiguration)); - csirep1->reportFreqConfiguration->cqi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI; - csirep1->reportFreqConfiguration->pmi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__pmi_FormatIndicator_widebandPMI; - csirep1->reportFreqConfiguration->csi_ReportingBand=NULL; - csirep1->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; - csirep1->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; - csirep1->codebookConfig=calloc(1,sizeof(*csirep1->codebookConfig)); - csirep1->codebookConfig->codebookType.present = NR_CodebookConfig__codebookType_PR_type1; - csirep1->codebookConfig->codebookType.choice.type1 = calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1)); - csirep1->codebookConfig->codebookType.choice.type1->subType.present=NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel; - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel=calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel)); - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present=NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two; - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two= - calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two)); - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.size=1; - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.bits_unused=2; - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.buf=malloc(1); - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.buf[0]=0xfc; - //'111111'B - - - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.size=1; - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.bits_unused=0; - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf=malloc(1); - csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]=0xc0; //'00000011'B - - csirep1->codebookConfig->codebookType.choice.type1->codebookMode=1; - csirep1->dummy = NULL; - csirep1->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; - csirep1->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep1->groupBasedBeamReporting.choice.disabled)); - csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); - *csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n2; - // this corresponds to: - //if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE is not required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting. - - csirep1->cqi_Table = calloc(1,sizeof(*csirep1->cqi_Table)); - *csirep1->cqi_Table = NR_CSI_ReportConfig__cqi_Table_table1; - csirep1->subbandSize = NR_CSI_ReportConfig__subbandSize_value1; - csirep1->non_PMI_PortIndication = NULL; - csirep1->ext1 = NULL; - - ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep1); + if (do_csirs && dl_antenna_ports > 1) { + NR_CSI_ReportConfig_t *csirep1 = calloc(1,sizeof(*csirep1)); + csirep1->reportConfigId=0; + csirep1->carrier=NULL; + csirep1->resourcesForChannelMeasurement=0; + csirep1->csi_IM_ResourcesForInterference=calloc(1,sizeof(*csirep1->csi_IM_ResourcesForInterference)); + *csirep1->csi_IM_ResourcesForInterference=2; + csirep1->nzp_CSI_RS_ResourcesForInterference=NULL; + csirep1->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; + csirep1->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep1->reportConfigType.choice.periodic)); + csirep1->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; + csirep1->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 9 + (20 * uid) % 320; + ASN_SEQUENCE_ADD(&csirep1->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); + csirep1->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI; + csirep1->reportQuantity.choice.cri_RI_PMI_CQI=(NULL_t)0; + csirep1->reportFreqConfiguration = calloc(1,sizeof(*csirep1->reportFreqConfiguration)); + csirep1->reportFreqConfiguration->cqi_FormatIndicator = calloc(1,sizeof(*csirep1->reportFreqConfiguration->cqi_FormatIndicator)); + *csirep1->reportFreqConfiguration->cqi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI; + csirep1->reportFreqConfiguration->pmi_FormatIndicator = calloc(1,sizeof(*csirep1->reportFreqConfiguration->pmi_FormatIndicator)); + *csirep1->reportFreqConfiguration->pmi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__pmi_FormatIndicator_widebandPMI; + csirep1->reportFreqConfiguration->csi_ReportingBand = calloc(1,sizeof(*csirep1->reportFreqConfiguration->csi_ReportingBand)); + csirep1->reportFreqConfiguration->csi_ReportingBand->present = NR_CSI_ReportConfig__reportFreqConfiguration__csi_ReportingBand_PR_subbands7; + csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.size=1; + csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.bits_unused=1; + csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.buf=malloc(1); + csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.buf[0]=254; + csirep1->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; + csirep1->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; + csirep1->codebookConfig=calloc(1,sizeof(*csirep1->codebookConfig)); + csirep1->codebookConfig->codebookType.present = NR_CodebookConfig__codebookType_PR_type1; + csirep1->codebookConfig->codebookType.choice.type1 = calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1)); + csirep1->codebookConfig->codebookType.choice.type1->subType.present=NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel=calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel)); + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present= + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two= + calloc(1,sizeof(*csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two)); + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.size=1; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.bits_unused=2; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.buf=malloc(1); + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.choice.two->twoTX_CodebookSubsetRestriction.buf[0]=0xfc; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.size=1; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.bits_unused=0; + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf=malloc(1); + csirep1->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]=0x03; + csirep1->codebookConfig->codebookType.choice.type1->codebookMode=1; + csirep1->dummy = NULL; + csirep1->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; + csirep1->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep1->groupBasedBeamReporting.choice.disabled)); + //csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); + //*csirep1->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; + csirep1->cqi_Table = calloc(1,sizeof(*csirep1->cqi_Table)); + *csirep1->cqi_Table = NR_CSI_ReportConfig__cqi_Table_table1; + csirep1->subbandSize = NR_CSI_ReportConfig__subbandSize_value2; + csirep1->non_PMI_PortIndication = NULL; + csirep1->ext1 = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep1); + } + if (do_csirs) { + NR_CSI_ReportConfig_t *csirep2 = calloc(1,sizeof(*csirep2)); + csirep2->reportConfigId=1; + csirep2->carrier=NULL; + csirep2->resourcesForChannelMeasurement=0; + csirep2->csi_IM_ResourcesForInterference=NULL; + csirep2->nzp_CSI_RS_ResourcesForInterference=NULL; + csirep2->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; + csirep2->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep2->reportConfigType.choice.periodic)); + csirep2->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; + csirep2->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 29 + (20 * uid) % 320; + ASN_SEQUENCE_ADD(&csirep2->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); + csirep2->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP; + csirep2->reportQuantity.choice.cri_RSRP=(NULL_t)0; + csirep2->reportFreqConfiguration = calloc(1,sizeof(*csirep2->reportFreqConfiguration)); + csirep2->reportFreqConfiguration->cqi_FormatIndicator = NULL; + csirep2->reportFreqConfiguration->pmi_FormatIndicator=NULL; + csirep2->reportFreqConfiguration->csi_ReportingBand=NULL; + csirep2->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; + csirep2->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; + csirep2->codebookConfig=NULL; + csirep2->dummy = NULL; + csirep2->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; + csirep2->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled)); + csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); + *csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; + csirep2->cqi_Table = NULL; + csirep2->subbandSize = NR_CSI_ReportConfig__subbandSize_value1; + csirep2->non_PMI_PortIndication = NULL; + csirep2->ext1 = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep2); + } + else{ + NR_CSI_ReportConfig_t *csirep2 = calloc(1,sizeof(*csirep2)); + csirep2->reportConfigId=1; + csirep2->carrier=NULL; + csirep2->resourcesForChannelMeasurement=1; + csirep2->csi_IM_ResourcesForInterference=NULL; + csirep2->nzp_CSI_RS_ResourcesForInterference=NULL; + csirep2->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; + csirep2->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep2->reportConfigType.choice.periodic)); + csirep2->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320; + csirep2->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 29 + (20 * uid) % 320; + ASN_SEQUENCE_ADD(&csirep2->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list,pucchcsires1); + csirep2->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP; + csirep2->reportQuantity.choice.ssb_Index_RSRP=(NULL_t)0; + csirep2->reportFreqConfiguration = calloc(1,sizeof(*csirep2->reportFreqConfiguration)); + csirep2->reportFreqConfiguration->cqi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI; + csirep2->reportFreqConfiguration->pmi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__pmi_FormatIndicator_widebandPMI; + csirep2->reportFreqConfiguration->csi_ReportingBand=NULL; + csirep2->timeRestrictionForChannelMeasurements= NR_CSI_ReportConfig__timeRestrictionForChannelMeasurements_configured; + csirep2->timeRestrictionForInterferenceMeasurements=NR_CSI_ReportConfig__timeRestrictionForInterferenceMeasurements_configured; + csirep2->codebookConfig= NULL; + csirep2->dummy = NULL; + csirep2->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; + csirep2->groupBasedBeamReporting.choice.disabled=calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled)); + csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS = calloc(1,sizeof(*csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS)); + *csirep2->groupBasedBeamReporting.choice.disabled->nrofReportedRS=NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1; + csirep2->cqi_Table = calloc(1,sizeof(*csirep2->cqi_Table)); + *csirep2->cqi_Table = NR_CSI_ReportConfig__cqi_Table_table1; + csirep2->subbandSize = NR_CSI_ReportConfig__subbandSize_value1; + csirep2->non_PMI_PortIndication = NULL; + csirep2->ext1 = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_ReportConfigToAddModList->list,csirep2); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->sCellDeactivationTimer=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->tag_Id=0; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->dummy=NULL; + secondaryCellGroup->spCellConfig->spCellConfigDedicated->dummy1=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->pathlossReferenceLinking=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->servingCellMO=NULL; } + + +void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_CSI_MeasConfig_t *csi_MeasConfig, int dl_antenna_ports, int do_csirs) { + + if (do_csirs) { + csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)); + NR_NZP_CSI_RS_Resource_t *nzpcsi0 = calloc(1,sizeof(*nzpcsi0)); + nzpcsi0->nzp_CSI_RS_ResourceId = 0; + NR_CSI_RS_ResourceMapping_t resourceMapping; + switch (dl_antenna_ports) { + case 1: + resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2; + resourceMapping.frequencyDomainAllocation.choice.row2.buf = calloc(2, sizeof(uint8_t)); + resourceMapping.frequencyDomainAllocation.choice.row2.size = 2; + resourceMapping.frequencyDomainAllocation.choice.row2.bits_unused = 4; + resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]=0; + resourceMapping.frequencyDomainAllocation.choice.row2.buf[1]=16; + resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p1; + resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_noCDM; + break; + case 2: + resourceMapping.frequencyDomainAllocation.present = NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other; + resourceMapping.frequencyDomainAllocation.choice.row2.buf = calloc(2, sizeof(uint8_t)); + resourceMapping.frequencyDomainAllocation.choice.row2.size = 1; + resourceMapping.frequencyDomainAllocation.choice.row2.bits_unused = 2; + resourceMapping.frequencyDomainAllocation.choice.row2.buf[0]=4; + resourceMapping.nrofPorts = NR_CSI_RS_ResourceMapping__nrofPorts_p2; + resourceMapping.cdm_Type = NR_CSI_RS_ResourceMapping__cdm_Type_fd_CDM2; + break; + default: + AssertFatal(1==0,"Number of ports not yet supported\n"); + } + resourceMapping.firstOFDMSymbolInTimeDomain = 6; + resourceMapping.firstOFDMSymbolInTimeDomain2 = NULL; + resourceMapping.density.present = NR_CSI_RS_ResourceMapping__density_PR_one; + resourceMapping.density.choice.one = (NULL_t)0; + resourceMapping.freqBand.startingRB = 0; + resourceMapping.freqBand.nrofRBs = 108; + nzpcsi0->resourceMapping = resourceMapping; + nzpcsi0->powerControlOffset = 0; + nzpcsi0->powerControlOffsetSS=calloc(1,sizeof(*nzpcsi0->powerControlOffsetSS)); + *nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; + nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId; + nzpcsi0->periodicityAndOffset = calloc(1,sizeof(*nzpcsi0->periodicityAndOffset)); + nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320; + nzpcsi0->periodicityAndOffset->choice.slots320 = 0; + nzpcsi0->qcl_InfoPeriodicCSI_RS = NULL; + ASN_SEQUENCE_ADD(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpcsi0); + } + else + csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = NULL; +} + + void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, + NR_ServingCellConfig_t *servingcellconfigdedicated, NR_RRCReconfiguration_IEs_t *reconfig, NR_CellGroupConfig_t *secondaryCellGroup, - int n_physical_antenna_ports, - int initial_csi_index) { + int dl_antenna_ports, + int minRXTXTIME, + int do_csirs, + int initial_csi_index, + int uid) { AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n"); AssertFatal(reconfig!=NULL,"reconfig is null\n"); AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n"); // radioBearerConfig reconfig->radioBearerConfig=NULL; // secondaryCellGroup - fill_default_secondaryCellGroup(servingcellconfigcommon,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index); + fill_default_secondaryCellGroup(servingcellconfigcommon, + servingcellconfigdedicated, + secondaryCellGroup, + 1, + 1, + dl_antenna_ports, + minRXTXTIME, + do_csirs, + initial_csi_index, + uid); + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); char scg_buffer[1024]; @@ -2039,7 +1387,10 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon reconfig->nonCriticalExtension = NULL; } -void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { +void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig, + int eps_bearer_id, int rb_id, + e_NR_CipheringAlgorithm ciphering_algorithm, + e_NR_SecurityConfig__keyToUse key_to_use) { rbconfig->srb_ToAddModList = NULL; rbconfig->srb3_ToRelease = NULL; @@ -2047,14 +1398,14 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod)); drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation)); drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; - drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity=5; - drb_ToAddMod->drb_Identity = 1; + drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= eps_bearer_id; + drb_ToAddMod->drb_Identity = rb_id; drb_ToAddMod->reestablishPDCP = NULL; drb_ToAddMod->recoverPDCP = NULL; drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); - *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30; + *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); @@ -2077,12 +1428,44 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig)); rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig)); - rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; + rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = ciphering_algorithm; rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL; rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse)); - *rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; + *rbconfig->securityConfig->keyToUse = key_to_use; - xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); +// xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); } +/* Function to set or overwrite PTRS DL RRC parameters */ +void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset) +{ + int i=0; + /* check for memory allocation */ + if(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS == NULL) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup= calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = calloc(1,sizeof(long)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = calloc(1,sizeof(long)); + /* Fill the given values */ + for(i = 0; i < 2; i++) { + ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list,&ptrsNrb[i]); + } + for(i = 0; i < 3; i++) { + ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list,&ptrsMcs[i]); + } + }// if memory exist then over write the old values + else { + for(i = 0; i < 2; i++) { + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] = ptrsNrb[i]; + } + for(i = 0; i < 3; i++) { + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] = ptrsMcs[i]; + } + } + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = *epre_Ratio; + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = *reOffset; +} #endif diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 08976522b0..5c9293dcf9 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -33,6 +33,7 @@ #include "rrc_defs.h" #include "rrc_proto.h" #include "assertions.h" +#include "rrc_vars.h" typedef uint32_t channel_t; @@ -41,30 +42,145 @@ nr_mac_rrc_data_ind_ue( const module_id_t module_id, const int CC_id, const uint8_t gNB_index, + const frame_t frame, + const sub_frame_t sub_frame, + const rnti_t rnti, const channel_t channel, const uint8_t* pduP, const sdu_size_t pdu_len){ + sdu_size_t sdu_size = 0; switch(channel){ - case NR_BCCH_BCH: - AssertFatal( nr_rrc_ue_decode_NR_BCCH_BCH_Message( module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-BCH error!\n"); - break; - default: - break; + case NR_BCCH_BCH: + AssertFatal( nr_rrc_ue_decode_NR_BCCH_BCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-BCH error!\n"); + break; + + case NR_BCCH_DL_SCH: + if (pdu_len>0) { + LOG_T(NR_RRC, "[UE %d] Received SDU for NR-BCCH-DL-SCH on SRB %u from gNB %d\n", module_id, channel & RAB_OFFSET, + gNB_index); + + MessageDef *message_p; + int msg_sdu_size = BCCH_SDU_SIZE; + + if (pdu_len > msg_sdu_size) { + LOG_E(NR_RRC, "SDU larger than NR-BCCH-DL-SCH SDU buffer size (%d, %d)", sdu_size, msg_sdu_size); + sdu_size = msg_sdu_size; + } else { + sdu_size = pdu_len; + } + + message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_BCCH_DATA_IND); + memset(NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE); + memcpy(NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, pduP, sdu_size); + NR_RRC_MAC_BCCH_DATA_IND (message_p).frame = frame; //frameP + NR_RRC_MAC_BCCH_DATA_IND (message_p).sub_frame = sub_frame; //sub_frameP + NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = sdu_size; + NR_RRC_MAC_BCCH_DATA_IND (message_p).gnb_index = gNB_index; + itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p); + } + break; + + case CCCH: + if (pdu_len>0) { + LOG_T(NR_RRC,"[UE %d] Received SDU for CCCH on SRB %u from gNB %d\n",module_id,channel & RAB_OFFSET,gNB_index); + + MessageDef *message_p; + int msg_sdu_size = CCCH_SDU_SIZE; + + if (pdu_len > msg_sdu_size) { + LOG_E(NR_RRC, "SDU larger than CCCH SDU buffer size (%d, %d)", sdu_size, msg_sdu_size); + sdu_size = msg_sdu_size; + } else { + sdu_size = pdu_len; + } + + message_p = itti_alloc_new_message (TASK_MAC_UE, 0, NR_RRC_MAC_CCCH_DATA_IND); + memset (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); + memcpy (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, pduP, sdu_size); + NR_RRC_MAC_CCCH_DATA_IND (message_p).frame = frame; //frameP + NR_RRC_MAC_CCCH_DATA_IND (message_p).sub_frame = sub_frame; //sub_frameP + NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu_size = sdu_size; + NR_RRC_MAC_CCCH_DATA_IND (message_p).gnb_index = gNB_index; + NR_RRC_MAC_CCCH_DATA_IND (message_p).rnti = rnti; //rntiP + itti_send_msg_to_task (TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE( module_id ), message_p); + } + break; + + default: + break; } - return(0); - } -int8_t mac_rrc_nr_data_req_ue(const module_id_t Mod_idP, +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, const int CC_id, + const uint8_t gNB_id, const frame_t frameP, const rb_id_t Srb_id, - uint8_t *const buffer_pP ){ + uint8_t *buffer_pP){ - // todo + switch(Srb_id){ + + case CCCH: + + // TODO: Enable timer T300 + //NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_active = 1; + //NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_cnt = 0; + + LOG_D(NR_RRC, "nr_mac_rrc_data_req_ue: Payload size = %i\n", NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size); + memcpy(buffer_pP, (uint8_t*)NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.Payload, NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size); + for(int i = 0; iframe; + RRC_DCCH_DATA_REQ (message_p).enb_flag = ctxt_pP->enb_flag; + RRC_DCCH_DATA_REQ (message_p).rb_id = rb_idP; + RRC_DCCH_DATA_REQ (message_p).muip = muiP; + RRC_DCCH_DATA_REQ (message_p).confirmp = confirmP; + RRC_DCCH_DATA_REQ (message_p).sdu_size = sdu_sizeP; + RRC_DCCH_DATA_REQ (message_p).sdu_p = message_buffer; + RRC_DCCH_DATA_REQ (message_p).mode = modeP; + RRC_DCCH_DATA_REQ (message_p).module_id = ctxt_pP->module_id; + RRC_DCCH_DATA_REQ (message_p).rnti = ctxt_pP->rnti; + RRC_DCCH_DATA_REQ (message_p).eNB_index = ctxt_pP->eNB_index; + itti_send_msg_to_task ( + TASK_PDCP_UE, + ctxt_pP->instance, + message_p); + return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. + +} diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c old mode 100755 new mode 100644 index 44215df218..61f757ed53 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -33,10 +33,17 @@ #define RRC_UE #define RRC_UE_C -#include "NR_DL-DCCH-Message.h" //asn_DEF_NR_DL_DCCH_Message -#include "NR_BCCH-BCH-Message.h" //asn_DEF_NR_BCCH_BCH_Message -#include "NR_CellGroupConfig.h" //asn_DEF_NR_CellGroupConfig -#include "NR_BWP-Downlink.h" //asn_DEF_NR_BWP_Downlink +#include "asn1_conversions.h" + +#include "NR_DL-DCCH-Message.h" //asn_DEF_NR_DL_DCCH_Message +#include "NR_DL-CCCH-Message.h" //asn_DEF_NR_DL_CCCH_Message +#include "NR_BCCH-BCH-Message.h" //asn_DEF_NR_BCCH_BCH_Message +#include "NR_BCCH-DL-SCH-Message.h" //asn_DEF_NR_BCCH_DL_SCH_Message +#include "NR_CellGroupConfig.h" //asn_DEF_NR_CellGroupConfig +#include "NR_BWP-Downlink.h" //asn_DEF_NR_BWP_Downlink +#include "NR_RRCReconfiguration.h" +#include "NR_MeasConfig.h" +#include "NR_UL-DCCH-Message.h" #include "rrc_list.h" #include "rrc_defs.h" @@ -44,51 +51,193 @@ #include "rrc_vars.h" #include "LAYER2/NR_MAC_UE/mac_proto.h" -#include "executables/softmodem-common.h" +#include "intertask_interface.h" +#include "executables/softmodem-common.h" +#include "plmn_data.h" +#include "pdcp.h" +#include "UTIL/OSA/osa_defs.h" +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#ifndef CELLULAR + #include "RRC/NR/MESSAGES/asn1_msg.h" +#endif + +#include "RRC/NAS/nas_config.h" +#include "RRC/NAS/rb_config.h" +#include "SIMULATION/TOOLS/sim.h" // for taus +#include + +#include "nr_nas_msg_sim.h" + +NR_UE_RRC_INST_t *NR_UE_rrc_inst; +/* NAS Attach request with IMSI */ +static const char nr_nas_attach_req_imsi[] = { + 0x07, 0x41, + /* EPS Mobile identity = IMSI */ + 0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87, + 0xF9, + /* End of EPS Mobile Identity */ + 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03, + 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, + 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, + 0x01, 0x27, 0x11, +}; + +extern void pdcp_config_set_security( + const protocol_ctxt_t *const ctxt_pP, + pdcp_t *const pdcp_pP, + const rb_id_t rb_idP, + const uint16_t lc_idP, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc +); + +void +nr_rrc_ue_process_ueCapabilityEnquiry( + const protocol_ctxt_t *const ctxt_pP, + NR_UECapabilityEnquiry_t *UECapabilityEnquiry, + uint8_t gNB_index +); + +void +nr_sa_rrc_ue_process_radioBearerConfig( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t gNB_index, + NR_RadioBearerConfig_t *const radioBearerConfig +); + +uint8_t do_NR_RRCReconfigurationComplete( + const protocol_ctxt_t *const ctxt_pP, + uint8_t *buffer, + const uint8_t Transaction_id + ); + +void rrc_ue_generate_RRCReestablishmentRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ); + +void +nr_rrc_ue_generate_rrcReestablishmentComplete( + const protocol_ctxt_t *const ctxt_pP, + NR_RRCReestablishment_t *rrcReestablishment, + uint8_t gNB_index +); + +mui_t nr_rrc_mui=0; + +static Rrc_State_NR_t nr_rrc_get_state (module_id_t ue_mod_idP) { + return NR_UE_rrc_inst[ue_mod_idP].nrRrcState; +} + + +static Rrc_Sub_State_NR_t nr_rrc_get_sub_state (module_id_t ue_mod_idP) { + return NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState; +} + +static int nr_rrc_set_state (module_id_t ue_mod_idP, Rrc_State_NR_t state) { + AssertFatal ((RRC_STATE_FIRST_NR <= state) && (state <= RRC_STATE_LAST_NR), + "Invalid state %d!\n", state); + + if (NR_UE_rrc_inst[ue_mod_idP].nrRrcState != state) { + NR_UE_rrc_inst[ue_mod_idP].nrRrcState = state; + return (1); + } + + return (0); +} + +static int nr_rrc_set_sub_state( module_id_t ue_mod_idP, Rrc_Sub_State_NR_t subState ) { + if (AMF_MODE_ENABLED) { + switch (NR_UE_rrc_inst[ue_mod_idP].nrRrcState) { + case RRC_STATE_INACTIVE_NR: + AssertFatal ((RRC_SUB_STATE_INACTIVE_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_INACTIVE_LAST_NR), + "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); + break; + + case RRC_STATE_IDLE_NR: + AssertFatal ((RRC_SUB_STATE_IDLE_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_IDLE_LAST_NR), + "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); + break; + + case RRC_STATE_CONNECTED_NR: + AssertFatal ((RRC_SUB_STATE_CONNECTED_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_CONNECTED_LAST_NR), + "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); + break; + } + } + + if (NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState != subState) { + NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState = subState; + return (1); + } + + return (0); +} + +extern boolean_t nr_rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc, + uint8_t *const kUPint + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 + ,rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); // from LTE-RRC DL-DCCH RRCConnectionReconfiguration nr-secondary-cell-group-config (encoded) -int8_t nr_rrc_ue_decode_secondary_cellgroup_config( - const uint8_t *buffer, - const uint32_t size ){ +int8_t nr_rrc_ue_decode_secondary_cellgroup_config(const module_id_t module_id, + const uint8_t *buffer, + const uint32_t size){ - NR_CellGroupConfig_t *cell_group_config = NULL; - uint32_t i; + NR_CellGroupConfig_t *cell_group_config = NULL; + uint32_t i; - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cell_group_config, - (uint8_t *)buffer, - size ); + asn_dec_rval_t dec_rval = uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, + (void **)&cell_group_config, + (uint8_t *)buffer, + size, 0, 0); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - printf("NR_CellGroupConfig decode error\n"); - for (i=0; icell_group_config == NULL){ - NR_UE_rrc_inst->cell_group_config = cell_group_config; - nr_rrc_ue_process_scg_config(cell_group_config); - }else{ - nr_rrc_ue_process_scg_config(cell_group_config); - SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)cell_group_config, 0); - } + if(NR_UE_rrc_inst[module_id].scell_group_config == NULL){ + NR_UE_rrc_inst[module_id].scell_group_config = cell_group_config; + nr_rrc_ue_process_scg_config(module_id,cell_group_config); + }else{ + nr_rrc_ue_process_scg_config(module_id,cell_group_config); + SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)cell_group_config, 0); + } - //nr_rrc_mac_config_req_ue( 0,0,0,NULL, cell_group_config->mac_CellGroupConfig, cell_group_config->physicalCellGroupConfig, cell_group_config->spCellConfig ); - - return 0; + return 0; } int8_t nr_rrc_ue_process_RadioBearerConfig(NR_RadioBearerConfig_t *RadioBearerConfig){ - - xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)RadioBearerConfig); + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *) RadioBearerConfig); + } // Configure PDCP return 0; @@ -96,67 +245,72 @@ int8_t nr_rrc_ue_process_RadioBearerConfig(NR_RadioBearerConfig_t *RadioBearerCo // from LTE-RRC DL-DCCH RRCConnectionReconfiguration nr-secondary-cell-group-config (decoded) // RRCReconfiguration -int8_t nr_rrc_ue_process_rrcReconfiguration(NR_RRCReconfiguration_t *rrcReconfiguration){ +int8_t nr_rrc_ue_process_rrcReconfiguration(const module_id_t module_id, NR_RRCReconfiguration_t *rrcReconfiguration){ - switch(rrcReconfiguration->criticalExtensions.present){ - case NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration: - if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig != NULL){ - if(NR_UE_rrc_inst->radio_bearer_config == NULL){ - NR_UE_rrc_inst->radio_bearer_config = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig; - }else{ - nr_rrc_ue_process_RadioBearerConfig(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig); - } - } + switch(rrcReconfiguration->criticalExtensions.present){ + case NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration: + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig != NULL){ + if(NR_UE_rrc_inst[module_id].radio_bearer_config == NULL){ + NR_UE_rrc_inst[module_id].radio_bearer_config = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig; + }else{ + nr_rrc_ue_process_RadioBearerConfig(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig); + } + } + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup != NULL){ - if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup != NULL){ - NR_CellGroupConfig_t *cellGroupConfig = NULL; - uper_decode(NULL, - &asn_DEF_NR_CellGroupConfig, //might be added prefix later - (void **)&cellGroupConfig, - (uint8_t *)rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->buf, - rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->size, 0, 0); + if(get_softmodem_params()->sa) { - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)cellGroupConfig); + NR_CellGroupConfig_t *cellGroupConfig = NULL; + uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, //might be added prefix later + (void **)&cellGroupConfig, + (uint8_t *)rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->buf, + rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->size, 0, 0); - if(NR_UE_rrc_inst->cell_group_config == NULL){ - // first time receive the configuration, just use the memory allocated from uper_decoder. TODO this is not good implementation, need to maintain RRC_INST own structure every time. - NR_UE_rrc_inst->cell_group_config = cellGroupConfig; - nr_rrc_ue_process_scg_config(cellGroupConfig); - }else{ - // after first time, update it and free the memory after. - SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)NR_UE_rrc_inst->cell_group_config, 0); - NR_UE_rrc_inst->cell_group_config = cellGroupConfig; - nr_rrc_ue_process_scg_config(cellGroupConfig); - } - - } + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); + } - if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig != NULL){ - if(NR_UE_rrc_inst->meas_config == NULL){ - NR_UE_rrc_inst->meas_config = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig; - }else{ - // if some element need to be updated - nr_rrc_ue_process_meas_config(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig); - } - - } + if(NR_UE_rrc_inst[module_id].cell_group_config == NULL){ + // first time receive the configuration, just use the memory allocated from uper_decoder. TODO this is not good implementation, need to maintain RRC_INST own structure every time. + NR_UE_rrc_inst[module_id].cell_group_config = cellGroupConfig; + nr_rrc_ue_process_scg_config(module_id,cellGroupConfig); + }else{ + // after first time, update it and free the memory after. + SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)NR_UE_rrc_inst[module_id].cell_group_config, 0); + NR_UE_rrc_inst[module_id].cell_group_config = cellGroupConfig; + nr_rrc_ue_process_scg_config(module_id,cellGroupConfig); + } + } + else + nr_rrc_ue_decode_secondary_cellgroup_config(module_id, + rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->buf, + rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->size); + } + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig != NULL){ + if(NR_UE_rrc_inst[module_id].meas_config == NULL){ + NR_UE_rrc_inst[module_id].meas_config = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig; + }else{ + // if some element need to be updated + nr_rrc_ue_process_meas_config(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig); + } + } + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->lateNonCriticalExtension != NULL){ + // unuse now + } + if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension != NULL){ + // unuse now + } + break; + + case NR_RRCReconfiguration__criticalExtensions_PR_NOTHING: + case NR_RRCReconfiguration__criticalExtensions_PR_criticalExtensionsFuture: + default: + break; + } + //nr_rrc_mac_config_req_ue(); - if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->lateNonCriticalExtension != NULL){ - // unuse now - } - - if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension != NULL){ - // unuse now - } - break; - case NR_RRCReconfiguration__criticalExtensions_PR_NOTHING: - case NR_RRCReconfiguration__criticalExtensions_PR_criticalExtensionsFuture: - default: - break; - } - //nr_rrc_mac_config_req_ue(); - - return 0; + return 0; } @@ -166,90 +320,89 @@ int8_t nr_rrc_ue_process_meas_config(NR_MeasConfig_t *meas_config){ return 0; } -int8_t nr_rrc_ue_process_scg_config(NR_CellGroupConfig_t *cell_group_config){ - int i; - if(NR_UE_rrc_inst->cell_group_config==NULL){ - // initial list - if(cell_group_config->spCellConfig != NULL){ - if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ - if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList != NULL){ - for(i=0; ispCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; ++i){ - RRC_LIST_MOD_ADD(NR_UE_rrc_inst->BWP_Downlink_list, cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i], bwp_Id); - } - } - } - } - }else{ - // maintain list - if(cell_group_config->spCellConfig != NULL){ - if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ - // process element of list to be add by RRC message - if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList != NULL){ - for(i=0; ispCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; ++i){ - RRC_LIST_MOD_ADD(NR_UE_rrc_inst->BWP_Downlink_list, cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i], bwp_Id); - } - } - - - // process element of list to be release by RRC message - if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList != NULL){ - for(i=0; ispCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList->list.count; ++i){ - NR_BWP_Downlink_t *freeP = NULL; - RRC_LIST_MOD_REL(NR_UE_rrc_inst->BWP_Downlink_list, bwp_Id, *cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList->list.array[i], freeP); - if(freeP != NULL){ - SEQUENCE_free(&asn_DEF_NR_BWP_Downlink, (void *)freeP, 0); - } - } - } - } +int8_t nr_rrc_ue_process_scg_config(const module_id_t module_id, NR_CellGroupConfig_t *cell_group_config){ + int i; + if(cell_group_config==NULL){ + // initial list + if(cell_group_config->spCellConfig != NULL){ + if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ + if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList != NULL){ + for(i=0; ispCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; ++i){ + RRC_LIST_MOD_ADD(NR_UE_rrc_inst[module_id].BWP_Downlink_list, cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i], bwp_Id); + } + } + } + } + }else{ + // maintain list + if(cell_group_config->spCellConfig != NULL){ + if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ + // process element of list to be add by RRC message + if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList != NULL){ + for(i=0; ispCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; ++i){ + RRC_LIST_MOD_ADD(NR_UE_rrc_inst[module_id].BWP_Downlink_list, cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i], bwp_Id); + } } - } - return 0; + // process element of list to be release by RRC message + if(cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList != NULL){ + for(i=0; ispCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList->list.count; ++i){ + NR_BWP_Downlink_t *freeP = NULL; + RRC_LIST_MOD_REL(NR_UE_rrc_inst[module_id].BWP_Downlink_list, bwp_Id, *cell_group_config->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList->list.array[i], freeP); + if(freeP != NULL){ + SEQUENCE_free(&asn_DEF_NR_BWP_Downlink, (void *)freeP, 0); + } + } + } + } + } + } + + return 0; } - - void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, void *message,int msg_len) { - + module_id_t module_id=0; // TODO switch (nsa_message_type) { case nr_SecondaryCellGroupConfig_r15: { - NR_RRCReconfiguration_t *RRCReconfiguration=NULL; - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, - &asn_DEF_NR_RRCReconfiguration, - (void **)&RRCReconfiguration, - (uint8_t *)message, - msg_len); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(RRC,"NR_RRCReconfiguration decode error\n"); - // free the memory - SEQUENCE_free( &asn_DEF_NR_RRCReconfiguration, RRCReconfiguration, 1 ); - return; - } - nr_rrc_ue_process_rrcReconfiguration(RRCReconfiguration); - } + NR_RRCReconfiguration_t *RRCReconfiguration=NULL; + asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + &asn_DEF_NR_RRCReconfiguration, + (void **)&RRCReconfiguration, + (uint8_t *)message, + msg_len); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E(RRC,"NR_RRCReconfiguration decode error\n"); + // free the memory + SEQUENCE_free( &asn_DEF_NR_RRCReconfiguration, RRCReconfiguration, 1 ); + return; + } + nr_rrc_ue_process_rrcReconfiguration(module_id,RRCReconfiguration); + } break; + case nr_RadioBearerConfigX_r15: { - NR_RadioBearerConfig_t *RadioBearerConfig=NULL; - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, - &asn_DEF_NR_RadioBearerConfig, - (void **)&RadioBearerConfig, - (uint8_t *)message, - msg_len); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(RRC,"NR_RadioBearerConfig decode error\n"); - // free the memory - SEQUENCE_free( &asn_DEF_NR_RadioBearerConfig, RadioBearerConfig, 1 ); - return; - } - nr_rrc_ue_process_RadioBearerConfig(RadioBearerConfig); + NR_RadioBearerConfig_t *RadioBearerConfig=NULL; + asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + &asn_DEF_NR_RadioBearerConfig, + (void **)&RadioBearerConfig, + (uint8_t *)message, + msg_len); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E(RRC,"NR_RadioBearerConfig decode error\n"); + // free the memory + SEQUENCE_free( &asn_DEF_NR_RadioBearerConfig, RadioBearerConfig, 1 ); + return; + } + nr_rrc_ue_process_RadioBearerConfig(RadioBearerConfig); } break; + default: AssertFatal(1==0,"Unknown message %d\n",nsa_message_type); break; @@ -258,104 +411,118 @@ void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, } NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char* rrc_config_path){ + int nr_ue; + if(NB_NR_UE_INST > 0){ + NR_UE_rrc_inst = (NR_UE_RRC_INST_t *)malloc(NB_NR_UE_INST * sizeof(NR_UE_RRC_INST_t)); + memset(NR_UE_rrc_inst, 0, NB_NR_UE_INST * sizeof(NR_UE_RRC_INST_t)); + for(nr_ue=0;nr_ue 0){ - NR_UE_rrc_inst = (NR_UE_RRC_INST_t *)malloc(NB_NR_UE_INST * sizeof(NR_UE_RRC_INST_t)); - memset(NR_UE_rrc_inst, 0, NB_NR_UE_INST * sizeof(NR_UE_RRC_INST_t)); + // TODO: Put the appropriate list of SIBs + NR_UE_rrc_inst[nr_ue].requested_SI_List.buf = CALLOC(1,4); + NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[0] = SIB2 | SIB3 | SIB5; // SIB2 - SIB9 + NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[1] = 0; // SIB10 - SIB17 + NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[2] = 0; // SIB18 - SIB25 + NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[3] = 0; // SIB26 - SIB32 + NR_UE_rrc_inst[nr_ue].requested_SI_List.size= 4; + NR_UE_rrc_inst[nr_ue].requested_SI_List.bits_unused= 0; - // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. + NR_UE_rrc_inst[nr_ue].ra_trigger = RA_NOT_RUNNING; - // init RRC lists - RRC_LIST_INIT(NR_UE_rrc_inst->RLC_Bearer_Config_list, NR_maxLC_ID); - RRC_LIST_INIT(NR_UE_rrc_inst->SchedulingRequest_list, NR_maxNrofSR_ConfigPerCellGroup); - RRC_LIST_INIT(NR_UE_rrc_inst->TAG_list, NR_maxNrofTAGs); - RRC_LIST_INIT(NR_UE_rrc_inst->TDD_UL_DL_SlotConfig_list, NR_maxNrofSlots); - RRC_LIST_INIT(NR_UE_rrc_inst->BWP_Downlink_list, NR_maxNrofBWPs); - RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[0], 3); // for init-dl-bwp - RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[1], 3); // for dl-bwp id=0 - RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[2], 3); // for dl-bwp id=1 - RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[3], 3); // for dl-bwp id=2 - RRC_LIST_INIT(NR_UE_rrc_inst->ControlResourceSet_list[4], 3); // for dl-bwp id=3 - RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[0], 10); - RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[1], 10); - RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[2], 10); - RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[3], 10); - RRC_LIST_INIT(NR_UE_rrc_inst->SearchSpace_list[4], 10); - RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[0], NR_maxNrofAggregatedCellsPerCellGroup); - RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[1], NR_maxNrofAggregatedCellsPerCellGroup); - RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[2], NR_maxNrofAggregatedCellsPerCellGroup); - RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[3], NR_maxNrofAggregatedCellsPerCellGroup); - RRC_LIST_INIT(NR_UE_rrc_inst->SlotFormatCombinationsPerCell_list[4], NR_maxNrofAggregatedCellsPerCellGroup); - RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[0], NR_maxNrofTCI_States); - RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[1], NR_maxNrofTCI_States); - RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[2], NR_maxNrofTCI_States); - RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[3], NR_maxNrofTCI_States); - RRC_LIST_INIT(NR_UE_rrc_inst->TCI_State_list[4], NR_maxNrofTCI_States); - RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[0], NR_maxNrofRateMatchPatterns); - RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[1], NR_maxNrofRateMatchPatterns); - RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[2], NR_maxNrofRateMatchPatterns); - RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[3], NR_maxNrofRateMatchPatterns); - RRC_LIST_INIT(NR_UE_rrc_inst->RateMatchPattern_list[4], NR_maxNrofRateMatchPatterns); - RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[0], NR_maxNrofZP_CSI_RS_Resources); - RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[1], NR_maxNrofZP_CSI_RS_Resources); - RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[2], NR_maxNrofZP_CSI_RS_Resources); - RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[3], NR_maxNrofZP_CSI_RS_Resources); - RRC_LIST_INIT(NR_UE_rrc_inst->ZP_CSI_RS_Resource_list[4], NR_maxNrofZP_CSI_RS_Resources); - RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[0], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[1], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[2], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[3], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->Aperidic_ZP_CSI_RS_ResourceSet_list[4], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[0], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[1], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[2], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[3], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->SP_ZP_CSI_RS_ResourceSet_list[4], NR_maxNrofZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->NZP_CSI_RS_Resource_list, NR_maxNrofNZP_CSI_RS_Resources); - RRC_LIST_INIT(NR_UE_rrc_inst->NZP_CSI_RS_ResourceSet_list, NR_maxNrofNZP_CSI_RS_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->CSI_IM_Resource_list, NR_maxNrofCSI_IM_Resources); - RRC_LIST_INIT(NR_UE_rrc_inst->CSI_IM_ResourceSet_list, NR_maxNrofCSI_IM_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->CSI_SSB_ResourceSet_list, NR_maxNrofCSI_SSB_ResourceSets); - RRC_LIST_INIT(NR_UE_rrc_inst->CSI_ResourceConfig_list, NR_maxNrofCSI_ResourceConfigurations); - RRC_LIST_INIT(NR_UE_rrc_inst->CSI_ReportConfig_list, NR_maxNrofCSI_ReportConfigurations); - - if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra==1) { - // read in files for RRCReconfiguration and RBconfig - FILE *fd; - char filename[1024]; - if (rrc_config_path) - sprintf(filename,"%s/reconfig.raw",rrc_config_path); - else - sprintf(filename,"reconfig.raw"); - fd = fopen(filename,"r"); - char buffer[1024]; - AssertFatal(fd, - "cannot read file %s: errno %d, %s\n", - filename, - errno, - strerror(errno)); - int msg_len=fread(buffer,1,1024,fd); - fclose(fd); - process_nsa_message(NR_UE_rrc_inst, nr_SecondaryCellGroupConfig_r15, buffer,msg_len); - if (rrc_config_path) - sprintf(filename,"%s/rbconfig.raw",rrc_config_path); - else - sprintf(filename,"rbconfig.raw"); - fd = fopen(filename,"r"); - AssertFatal(fd, - "cannot read file %s: errno %d, %s\n", - filename, - errno, - strerror(errno)); - msg_len=fread(buffer,1,1024,fd); - fclose(fd); - process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, buffer,msg_len); - } - }else{ - NR_UE_rrc_inst = NULL; + // init RRC lists + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RLC_Bearer_Config_list, NR_maxLC_ID); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SchedulingRequest_list, NR_maxNrofSR_ConfigPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TAG_list, NR_maxNrofTAGs); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TDD_UL_DL_SlotConfig_list, NR_maxNrofSlots); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].BWP_Downlink_list, NR_maxNrofBWPs); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[0], 3); // for init-dl-bwp + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[1], 3); // for dl-bwp id=0 + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[2], 3); // for dl-bwp id=1 + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[3], 3); // for dl-bwp id=2 + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ControlResourceSet_list[4], 3); // for dl-bwp id=3 + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[0], 10); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[1], 10); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[2], 10); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[3], 10); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SearchSpace_list[4], 10); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[0], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[1], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[2], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[3], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SlotFormatCombinationsPerCell_list[4], NR_maxNrofAggregatedCellsPerCellGroup); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[0], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[1], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[2], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[3], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].TCI_State_list[4], NR_maxNrofTCI_States); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[0], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[1], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[2], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[3], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RateMatchPattern_list[4], NR_maxNrofRateMatchPatterns); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[0], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[1], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[2], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[3], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].ZP_CSI_RS_Resource_list[4], NR_maxNrofZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[0], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[1], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[2], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[3], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].Aperidic_ZP_CSI_RS_ResourceSet_list[4], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[0], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[1], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[2], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[3], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SP_ZP_CSI_RS_ResourceSet_list[4], NR_maxNrofZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].NZP_CSI_RS_Resource_list, NR_maxNrofNZP_CSI_RS_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].NZP_CSI_RS_ResourceSet_list, NR_maxNrofNZP_CSI_RS_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_IM_Resource_list, NR_maxNrofCSI_IM_Resources); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_IM_ResourceSet_list, NR_maxNrofCSI_IM_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_SSB_ResourceSet_list, NR_maxNrofCSI_SSB_ResourceSets); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_ResourceConfig_list, NR_maxNrofCSI_ResourceConfigurations); + RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_ReportConfig_list, NR_maxNrofCSI_ReportConfigurations); } - return NR_UE_rrc_inst; + if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra==1) { + // read in files for RRCReconfiguration and RBconfig + FILE *fd; + char filename[1024]; + if (rrc_config_path) + sprintf(filename,"%s/reconfig.raw",rrc_config_path); + else + sprintf(filename,"reconfig.raw"); + fd = fopen(filename,"r"); + char buffer[1024]; + AssertFatal(fd, + "cannot read file %s: errno %d, %s\n", + filename, + errno, + strerror(errno)); + int msg_len=fread(buffer,1,1024,fd); + fclose(fd); + process_nsa_message(NR_UE_rrc_inst, nr_SecondaryCellGroupConfig_r15, buffer,msg_len); + if (rrc_config_path) + sprintf(filename,"%s/rbconfig.raw",rrc_config_path); + else + sprintf(filename,"rbconfig.raw"); + fd = fopen(filename,"r"); + AssertFatal(fd, + "cannot read file %s: errno %d, %s\n", + filename, + errno, + strerror(errno)); + msg_len=fread(buffer,1,1024,fd); + fclose(fd); + process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, buffer,msg_len); + } + } + else{ + NR_UE_rrc_inst = NULL; + } + + return NR_UE_rrc_inst; } @@ -390,120 +557,2222 @@ int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message( const uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len ){ - int i; + NR_BCCH_BCH_Message_t *bcch_message = NULL; - NR_MIB_t *mib = NR_UE_rrc_inst->mib; - if(mib != NULL){ - SEQUENCE_free( &asn_DEF_NR_BCCH_BCH_Message, (void *)mib, 1 ); - } + if (NR_UE_rrc_inst[module_id].mib != NULL) + SEQUENCE_free( &asn_DEF_NR_BCCH_BCH_Message, (void *)bcch_message, 1 ); + else LOG_I(NR_RRC,"Configuring MAC for first MIB reception\n"); - - for(i=0; imessage.choice.mib; + SEQUENCE_free( &asn_DEF_NR_MIB, (void *)NR_UE_rrc_inst[module_id].mib, 1 ); + NR_UE_rrc_inst[module_id].mib = bcch_message->message.choice.mib; //memcpy( (void *)mib, // (void *)&bcch_message->message.choice.mib, // sizeof(NR_MIB_t) ); + + nr_rrc_mac_config_req_ue( 0, 0, 0, NR_UE_rrc_inst[module_id].mib, NULL, NULL, NULL); + } + + return 0; +} + +const char siWindowLength[10][5] = {"5s", "10s", "20s", "40s", "80s", "160s", "320s", "640s", "1280s","ERR"};// {"1ms","2ms","5ms","10ms","15ms","20ms","40ms","80ms","ERR"}; +const short siWindowLength_int[9] = {5,10,20,40,80,160,320,640,1280};//{1,2,5,10,15,20,40,80}; + +const char SIBType[12][6] = {"SIB3","SIB4","SIB5","SIB6","SIB7","SIB8","SIB9","SIB10","SIB11","SIB12","SIB13","Spare"}; +const char SIBPeriod[8][6] = {"rf8","rf16","rf32","rf64","rf128","rf256","rf512","ERR"}; +int siPeriod_int[7] = {80,160,320,640,1280,2560,5120}; + +const char *nr_SIBreserved( long value ) { + if (value < 0 || value > 1) + return "ERR"; + + if (value) + return "notReserved"; + + return "reserved"; +} + +void nr_dump_sib2( NR_SIB2_t *sib2 ){ +//cellReselectionInfoCommon + //nrofSS_BlocksToAverage + if( sib2->cellReselectionInfoCommon.nrofSS_BlocksToAverage) + LOG_I( RRC, "cellReselectionInfoCommon.nrofSS_BlocksToAverage : %ld\n", + *sib2->cellReselectionInfoCommon.nrofSS_BlocksToAverage ); + else + LOG_I( RRC, "cellReselectionInfoCommon->nrofSS_BlocksToAverage : not defined\n" ); + + //absThreshSS_BlocksConsolidation + if( sib2->cellReselectionInfoCommon.absThreshSS_BlocksConsolidation){ + LOG_I( RRC, "absThreshSS_BlocksConsolidation.thresholdRSRP : %ld\n", + *sib2->cellReselectionInfoCommon.absThreshSS_BlocksConsolidation->thresholdRSRP ); + LOG_I( RRC, "absThreshSS_BlocksConsolidation.thresholdRSRQ : %ld\n", + *sib2->cellReselectionInfoCommon.absThreshSS_BlocksConsolidation->thresholdRSRQ ); + LOG_I( RRC, "absThreshSS_BlocksConsolidation.thresholdSINR : %ld\n", + *sib2->cellReselectionInfoCommon.absThreshSS_BlocksConsolidation->thresholdSINR ); + } else + LOG_I( RRC, "cellReselectionInfoCommon->absThreshSS_BlocksConsolidation : not defined\n" ); + + //q_Hyst + LOG_I( RRC, "cellReselectionInfoCommon.q_Hyst : %ld\n", + sib2->cellReselectionInfoCommon.q_Hyst ); + + //speedStateReselectionPars + if( sib2->cellReselectionInfoCommon.speedStateReselectionPars){ + LOG_I( RRC, "speedStateReselectionPars->mobilityStateParameters.t_Evaluation : %ld\n", + sib2->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.t_Evaluation); + LOG_I( RRC, "speedStateReselectionPars->mobilityStateParameters.t_HystNormal : %ld\n", + sib2->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.t_HystNormal); + LOG_I( RRC, "speedStateReselectionPars->mobilityStateParameters.n_CellChangeMedium : %ld\n", + sib2->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.n_CellChangeMedium); + LOG_I( RRC, "speedStateReselectionPars->mobilityStateParameters.n_CellChangeHigh : %ld\n", + sib2->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.n_CellChangeHigh); + LOG_I( RRC, "speedStateReselectionPars->q_HystSF.sf_Medium : %ld\n", + sib2->cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_Medium); + LOG_I( RRC, "speedStateReselectionPars->q_HystSF.sf_High : %ld\n", + sib2->cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_High); + } else + LOG_I( RRC, "cellReselectionInfoCommon->speedStateReselectionPars : not defined\n" ); + +//cellReselectionServingFreqInfo + if( sib2->cellReselectionServingFreqInfo.s_NonIntraSearchP) + LOG_I( RRC, "cellReselectionServingFreqInfo.s_NonIntraSearchP : %ld\n", + *sib2->cellReselectionServingFreqInfo.s_NonIntraSearchP ); + else + LOG_I( RRC, "cellReselectionServingFreqInfo->s_NonIntraSearchP : not defined\n" ); + + if( sib2->cellReselectionServingFreqInfo.s_NonIntraSearchQ) + LOG_I( RRC, "cellReselectionServingFreqInfo.s_NonIntraSearchQ : %ld\n", + *sib2->cellReselectionServingFreqInfo.s_NonIntraSearchQ ); + else + LOG_I( RRC, "cellReselectionServingFreqInfo->s_NonIntraSearchQ : not defined\n" ); + + LOG_I( RRC, "cellReselectionServingFreqInfo.threshServingLowP : %ld\n", + sib2->cellReselectionServingFreqInfo.threshServingLowP ); + + if( sib2->cellReselectionServingFreqInfo.threshServingLowQ) + LOG_I( RRC, "cellReselectionServingFreqInfo.threshServingLowQ : %ld\n", + *sib2->cellReselectionServingFreqInfo.threshServingLowQ ); + else + LOG_I( RRC, "cellReselectionServingFreqInfo->threshServingLowQ : not defined\n" ); + + LOG_I( RRC, "cellReselectionServingFreqInfo.cellReselectionPriority : %ld\n", + sib2->cellReselectionServingFreqInfo.cellReselectionPriority ); + if( sib2->cellReselectionServingFreqInfo.cellReselectionSubPriority) + LOG_I( RRC, "cellReselectionServingFreqInfo.cellReselectionSubPriority : %ld\n", + *sib2->cellReselectionServingFreqInfo.cellReselectionSubPriority ); + else + LOG_I( RRC, "cellReselectionServingFreqInfo->cellReselectionSubPriority : not defined\n" ); + +//intraFreqCellReselectionInfo + LOG_I( RRC, "intraFreqCellReselectionInfo.q_RxLevMin : %ld\n", + sib2->intraFreqCellReselectionInfo.q_RxLevMin ); + + if( sib2->intraFreqCellReselectionInfo.q_RxLevMinSUL) + LOG_I( RRC, "intraFreqCellReselectionInfo.q_RxLevMinSUL : %ld\n", + *sib2->intraFreqCellReselectionInfo.q_RxLevMinSUL ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->q_RxLevMinSUL : not defined\n" ); + + if( sib2->intraFreqCellReselectionInfo.q_QualMin) + LOG_I( RRC, "intraFreqCellReselectionInfo.q_QualMin : %ld\n", + *sib2->intraFreqCellReselectionInfo.q_QualMin ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->q_QualMin : not defined\n" ); + + LOG_I( RRC, "intraFreqCellReselectionInfo.s_IntraSearchP : %ld\n", + sib2->intraFreqCellReselectionInfo.s_IntraSearchP ); + + if( sib2->intraFreqCellReselectionInfo.s_IntraSearchQ) + LOG_I( RRC, "intraFreqCellReselectionInfo.s_IntraSearchQ : %ld\n", + *sib2->intraFreqCellReselectionInfo.s_IntraSearchQ ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->s_IntraSearchQ : not defined\n" ); + + LOG_I( RRC, "intraFreqCellReselectionInfo.t_ReselectionNR : %ld\n", + sib2->intraFreqCellReselectionInfo.t_ReselectionNR ); + + if( sib2->intraFreqCellReselectionInfo.frequencyBandList) + LOG_I( RRC, "intraFreqCellReselectionInfo.frequencyBandList : %p\n", + sib2->intraFreqCellReselectionInfo.frequencyBandList ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->frequencyBandList : not defined\n" ); + + if( sib2->intraFreqCellReselectionInfo.frequencyBandListSUL) + LOG_I( RRC, "intraFreqCellReselectionInfo.frequencyBandListSUL : %p\n", + sib2->intraFreqCellReselectionInfo.frequencyBandListSUL ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->frequencyBandListSUL : not defined\n" ); + + if( sib2->intraFreqCellReselectionInfo.p_Max) + LOG_I( RRC, "intraFreqCellReselectionInfo.p_Max : %ld\n", + *sib2->intraFreqCellReselectionInfo.p_Max ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->p_Max : not defined\n" ); + + if( sib2->intraFreqCellReselectionInfo.smtc) + LOG_I( RRC, "intraFreqCellReselectionInfo.smtc : %p\n", + sib2->intraFreqCellReselectionInfo.smtc ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->smtc : not defined\n" ); + + if( sib2->intraFreqCellReselectionInfo.ss_RSSI_Measurement) + LOG_I( RRC, "intraFreqCellReselectionInfo.ss_RSSI_Measurement : %p\n", + sib2->intraFreqCellReselectionInfo.ss_RSSI_Measurement ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->ss_RSSI_Measurement : not defined\n" ); + + if( sib2->intraFreqCellReselectionInfo.ssb_ToMeasure) + LOG_I( RRC, "intraFreqCellReselectionInfo.ssb_ToMeasure : %p\n", + sib2->intraFreqCellReselectionInfo.ssb_ToMeasure ); + else + LOG_I( RRC, "intraFreqCellReselectionInfo->ssb_ToMeasure : not defined\n" ); + + LOG_I( RRC, "intraFreqCellReselectionInfo.deriveSSB_IndexFromCell : %d\n", + sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell ); + +} + +void nr_dump_sib3( NR_SIB3_t *sib3 ) { +//intraFreqNeighCellList + if( sib3->intraFreqNeighCellList){ + LOG_I( RRC, "intraFreqNeighCellList : %p\n", + sib3->intraFreqNeighCellList ); + const int n = sib3->intraFreqNeighCellList->list.count; + for (int i = 0; i < n; ++i){ + LOG_I( RRC, "intraFreqNeighCellList->physCellId : %ld\n", + sib3->intraFreqNeighCellList->list.array[i]->physCellId ); + LOG_I( RRC, "intraFreqNeighCellList->q_OffsetCell : %ld\n", + sib3->intraFreqNeighCellList->list.array[i]->q_OffsetCell ); + + if( sib3->intraFreqNeighCellList->list.array[i]->q_RxLevMinOffsetCell) + LOG_I( RRC, "intraFreqNeighCellList->q_RxLevMinOffsetCell : %ld\n", + *sib3->intraFreqNeighCellList->list.array[i]->q_RxLevMinOffsetCell ); + else + LOG_I( RRC, "intraFreqNeighCellList->q_RxLevMinOffsetCell : not defined\n" ); - nr_rrc_mac_config_req_ue( 0, 0, 0, mib, NULL); + if( sib3->intraFreqNeighCellList->list.array[i]->q_RxLevMinOffsetCellSUL) + LOG_I( RRC, "intraFreqNeighCellList->q_RxLevMinOffsetCellSUL : %ld\n", + *sib3->intraFreqNeighCellList->list.array[i]->q_RxLevMinOffsetCellSUL ); + else + LOG_I( RRC, "intraFreqNeighCellList->q_RxLevMinOffsetCellSUL : not defined\n" ); + + if( sib3->intraFreqNeighCellList->list.array[i]->q_QualMinOffsetCell) + LOG_I( RRC, "intraFreqNeighCellList->q_QualMinOffsetCell : %ld\n", + *sib3->intraFreqNeighCellList->list.array[i]->q_QualMinOffsetCell ); + else + LOG_I( RRC, "intraFreqNeighCellList->q_QualMinOffsetCell : not defined\n" ); } - - return 0; + } else{ + LOG_I( RRC, "intraFreqCellReselectionInfo : not defined\n" ); + } + +//intraFreqBlackCellList + if( sib3->intraFreqBlackCellList){ + LOG_I( RRC, "intraFreqBlackCellList : %p\n", + sib3->intraFreqBlackCellList ); + const int n = sib3->intraFreqBlackCellList->list.count; + for (int i = 0; i < n; ++i){ + LOG_I( RRC, "intraFreqBlackCellList->start : %ld\n", + sib3->intraFreqBlackCellList->list.array[i]->start ); + + if( sib3->intraFreqBlackCellList->list.array[i]->range) + LOG_I( RRC, "intraFreqBlackCellList->range : %ld\n", + *sib3->intraFreqBlackCellList->list.array[i]->range ); + else + LOG_I( RRC, "intraFreqBlackCellList->range : not defined\n" ); + } + } else{ + LOG_I( RRC, "intraFreqBlackCellList : not defined\n" ); + } + +//lateNonCriticalExtension + if( sib3->lateNonCriticalExtension) + LOG_I( RRC, "lateNonCriticalExtension : %p\n", + sib3->lateNonCriticalExtension ); + else + LOG_I( RRC, "lateNonCriticalExtension : not defined\n" ); } +int nr_decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ) { + NR_SystemInformation_t **si = &NR_UE_rrc_inst[ctxt_pP->module_id].si[gNB_index]; + int new_sib = 0; + NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN ); -// from NR SRB3 -int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message( - const module_id_t module_id, - const uint8_t gNB_index, - const uint8_t *bufferP, - const uint32_t buffer_len ){ - // uper_decode by nr R15 rrc_connection_reconfiguration - - int32_t i; - NR_DL_DCCH_Message_t *nr_dl_dcch_msg = NULL; + // Dump contents + if ((*si)->criticalExtensions.present == NR_SystemInformation__criticalExtensions_PR_systemInformation || + (*si)->criticalExtensions.present == NR_SystemInformation__criticalExtensions_PR_criticalExtensionsFuture_r16) { + LOG_D( RRC, "[UE] (*si)->criticalExtensions.choice.NR_SystemInformation_t->sib_TypeAndInfo.list.count %d\n", + (*si)->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count ); + } else { + LOG_D( RRC, "[UE] Unknown criticalExtension version (not Rel16)\n" ); + return -1; + } - asn_dec_rval_t dec_rval = uper_decode( NULL, - &asn_DEF_NR_DL_DCCH_Message, - (void**)&nr_dl_dcch_msg, - (uint8_t *)bufferP, - buffer_len, 0, 0); + for (int i=0; i<(*si)->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count; i++) { + SystemInformation_IEs__sib_TypeAndInfo__Member *typeandinfo; + typeandinfo = (*si)->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.array[i]; - if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { + switch(typeandinfo->present) { + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&2) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=2; + //new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib2[gNB_index], &typeandinfo->choice.sib2, sizeof(NR_SIB2_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB2 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + nr_dump_sib2( NR_UE_rrc_inst[ctxt_pP->module_id].sib2[gNB_index] ); + LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB2 params gNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n", + ctxt_pP->frame, ctxt_pP->module_id, gNB_index, ctxt_pP->module_id ); + //TODO rrc_mac_config_req_ue - for (i=0; imodule_id].MBMS_flag < 3) // see -Q option + if (AMF_MODE_ENABLED) { + nr_rrc_ue_generate_RRCSetupRequest( ctxt_pP->module_id, gNB_index ); + } - printf("\n"); - // free the memory - SEQUENCE_free( &asn_DEF_NR_DL_DCCH_Message, (void *)nr_dl_dcch_msg, 1 ); - return -1; - } - - if(nr_dl_dcch_msg != NULL){ - switch(nr_dl_dcch_msg->message.present){ - case NR_DL_DCCH_MessageType_PR_c1: - - switch(nr_dl_dcch_msg->message.choice.c1->present){ - case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: - nr_rrc_ue_process_rrcReconfiguration(nr_dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration); - break; - - case NR_DL_DCCH_MessageType__c1_PR_NOTHING: - case NR_DL_DCCH_MessageType__c1_PR_rrcResume: - case NR_DL_DCCH_MessageType__c1_PR_rrcRelease: - case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: - case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: - case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: - case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry: - case NR_DL_DCCH_MessageType__c1_PR_counterCheck: - case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand: - case NR_DL_DCCH_MessageType__c1_PR_spare7: - case NR_DL_DCCH_MessageType__c1_PR_spare6: - case NR_DL_DCCH_MessageType__c1_PR_spare5: - case NR_DL_DCCH_MessageType__c1_PR_spare4: - case NR_DL_DCCH_MessageType__c1_PR_spare3: - case NR_DL_DCCH_MessageType__c1_PR_spare2: - case NR_DL_DCCH_MessageType__c1_PR_spare1: - default: - // not supported or unused - break; - } - break; - case NR_DL_DCCH_MessageType_PR_NOTHING: - case NR_DL_DCCH_MessageType_PR_messageClassExtension: - default: - // not supported or unused - break; + if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State == NR_RRC_IDLE) { + LOG_I( RRC, "[UE %d] Received SIB1/SIB2/SIB3 Switching to RRC_SI_RECEIVED\n", ctxt_pP->module_id ); + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State = NR_RRC_SI_RECEIVED; +#if ENABLE_RAL + /* TODO { + MessageDef *message_ral_p = NULL; + rrc_ral_system_information_ind_t ral_si_ind; + message_ral_p = itti_alloc_new_message (TASK_RRC_UE, 0, RRC_RAL_SYSTEM_INFORMATION_IND); + memset(&ral_si_ind, 0, sizeof(rrc_ral_system_information_ind_t)); + ral_si_ind.plmn_id.MCCdigit2 = '0'; + ral_si_ind.plmn_id.MCCdigit1 = '2'; + ral_si_ind.plmn_id.MNCdigit3 = '0'; + ral_si_ind.plmn_id.MCCdigit3 = '8'; + ral_si_ind.plmn_id.MNCdigit2 = '9'; + ral_si_ind.plmn_id.MNCdigit1 = '9'; + ral_si_ind.cell_id = 1; + ral_si_ind.dbm = 0; + //ral_si_ind.dbm = fifo_dump_emos_UE.PHY_measurements->rx_rssi_dBm[gNB_index]; + // TO DO + ral_si_ind.sinr = 0; + //ral_si_ind.sinr = fifo_dump_emos_UE.PHY_measurements->subband_cqi_dB[gNB_index][phy_vars_ue->lte_frame_parms.nb_antennas_rx][0]; + // TO DO + ral_si_ind.link_data_rate = 0; + memcpy (&message_ral_p->ittiMsg, (void *) &ral_si_ind, sizeof(rrc_ral_system_information_ind_t)); +#warning "ue_mod_idP ? for instance ?" + itti_send_msg_to_task (TASK_RAL_UE, UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), message_ral_p); + }*/ +#endif + } } - - // release memory allocation - SEQUENCE_free( &asn_DEF_NR_DL_DCCH_Message, (void *)nr_dl_dcch_msg, 1 ); - }else{ - // log.. + + break; // case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2 + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&4) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=4; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib3[gNB_index], &typeandinfo->choice.sib3, sizeof(LTE_SystemInformationBlockType3_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB3 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + nr_dump_sib3( NR_UE_rrc_inst[ctxt_pP->module_id].sib3[gNB_index] ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib4: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&8) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=8; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib4[gNB_index], typeandinfo->choice.sib4, sizeof(NR_SIB4_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB4 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib5: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&16) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=16; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib5[gNB_index], typeandinfo->choice.sib5, sizeof(NR_SIB5_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB5 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + //dump_sib5(NR_UE_rrc_inst[ctxt_pP->module_id].sib5[gNB_index]); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib6: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&32) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=32; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib6[gNB_index], typeandinfo->choice.sib6, sizeof(NR_SIB6_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB6 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib7: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&64) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=64; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib7[gNB_index], typeandinfo->choice.sib7, sizeof(NR_SIB7_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB7 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib8: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&128) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=128; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib8[gNB_index], typeandinfo->choice.sib8, sizeof(NR_SIB8_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB8 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib9: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&256) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=256; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib9[gNB_index], typeandinfo->choice.sib9, sizeof(NR_SIB9_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB9 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib10_v1610: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&512) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=512; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib10[gNB_index], typeandinfo->choice.sib10_v1610, sizeof(NR_SIB10_r16_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB10 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib11_v1610: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1024) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=1024; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib11[gNB_index], typeandinfo->choice.sib11_v1610, sizeof(NR_SIB11_r16_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB11 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib12_v1610: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&2048) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=2048; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib12[gNB_index], typeandinfo->choice.sib12_v1610, sizeof(NR_SIB12_r16_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB12 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib13_v1610: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&4096) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=4096; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib13[gNB_index], typeandinfo->choice.sib13_v1610, sizeof(NR_SIB13_r16_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB13 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + //dump_sib13( NR_UE_rrc_inst[ctxt_pP->module_id].sib13[gNB_index] ); + // adding here function to store necessary parameters for using in decode_MCCH_Message + maybe transfer to PHY layer + LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB13 params gNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n", + ctxt_pP->frame, ctxt_pP->module_id, gNB_index, ctxt_pP->module_id); + // TODO rrc_mac_config_req_ue + } + break; + + case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib14_v1610: + if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&8192) == 0) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus|=8192; + new_sib=1; + memcpy( NR_UE_rrc_inst[ctxt_pP->module_id].sib12[gNB_index], typeandinfo->choice.sib14_v1610, sizeof(NR_SIB14_r16_t) ); + LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB14 from gNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, gNB_index ); + } + + break; + + default: + break; + } + if (new_sib == 1) { + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt++; + if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count) + nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE ); + + LOG_I(NR_RRC,"SIStatus %x, SIcnt %d/%d\n", + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus, + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt, + sib1->si_SchedulingInfo->schedulingInfoList.list.count); + } + } + + //if (new_sib == 1) { + // NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt++; + + // if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->schedulingInfoList.list.count) + // rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE ); + + // LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n", + // NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus, + // NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt, + // sib1->schedulingInfoList.list.count); + //} + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_OUT); + return 0; +} + +int8_t check_requested_SI_List(module_id_t module_id, BIT_STRING_t requested_SI_List, NR_SIB1_t sib1) { + + if(sib1.si_SchedulingInfo) { + + bool SIB_to_request[32] = {}; + + LOG_D(RRC, "SIBs broadcasting: "); + for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { + printf("SIB%li ", sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type + 2); + } + printf("\n"); + + LOG_D(RRC, "SIBs needed by UE: "); + for(int j = 0; j < 8*requested_SI_List.size; j++) { + if( ((requested_SI_List.buf[j/8]>>(j%8))&1) == 1) { + + printf("SIB%i ", j + 2); + + SIB_to_request[j] = true; + for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { + if(sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type == j) { + SIB_to_request[j] = false; + break; + } + } + + } + } + printf("\n"); + + LOG_D(RRC, "SIBs to request by UE: "); + bool do_ra = false; + for(int j = 0; j < 8*requested_SI_List.size; j++) { + if(SIB_to_request[j]) { + printf("SIB%i ", j + 2); + do_ra = true; + } + } + printf("\n"); + + if(do_ra) { + + NR_UE_rrc_inst[module_id].ra_trigger = REQUEST_FOR_OTHER_SI; + get_softmodem_params()->do_ra = 1; + + if(sib1.si_SchedulingInfo->si_RequestConfig) { + LOG_D(RRC, "Trigger contention-free RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger); + } else { + LOG_D(RRC, "Trigger contention-based RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger); + } + } - return 0; + } + return 0; +} + +int8_t nr_rrc_ue_generate_ra_msg(module_id_t module_id, uint8_t gNB_index) { + + switch(NR_UE_rrc_inst[module_id].ra_trigger){ + case INITIAL_ACCESS_FROM_RRC_IDLE: + // After SIB1 is received, prepare RRCConnectionRequest + nr_rrc_ue_generate_RRCSetupRequest(module_id,gNB_index); + break; + case RRC_CONNECTION_REESTABLISHMENT: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case DURING_HANDOVER: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case NON_SYNCHRONISED: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case TRANSITION_FROM_RRC_INACTIVE: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case TO_ESTABLISH_TA: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case REQUEST_FOR_OTHER_SI: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case BEAM_FAILURE_RECOVERY: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + default: + AssertFatal(1==0, "Invalid ra_trigger value!\n"); + break; + } + + return 0; +} + +int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id_t module_id, + const uint8_t gNB_index, + uint8_t *const Sdu, + const uint8_t Sdu_len, + const uint8_t rsrq, + const uint8_t rsrp) { + + NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; + NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN ); + + if (((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 1) && sib1->si_SchedulingInfo &&// SIB1 received + (NR_UE_rrc_inst[module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count)) { + // to prevent memory bloating + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); + return 0; + } + + nr_rrc_set_sub_state( module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR ); + + asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + &asn_DEF_NR_BCCH_DL_SCH_Message, + (void **)&bcch_message, + (const void *)Sdu, + Sdu_len ); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message ); + } + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E( NR_RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", + module_id, + dec_rval.consumed ); + log_dump(NR_RRC, Sdu, Sdu_len, LOG_DUMP_CHAR," Received bytes:\n" ); + // free the memory + SEQUENCE_free( &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message, 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); + return -1; + } + + if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) { + switch (bcch_message->message.choice.c1->present) { + case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1: + if ((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 0) { + NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; + if(sib1 != NULL){ + SEQUENCE_free(&asn_DEF_NR_SIB1, (void *)sib1, 1 ); + } + NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus|=1; + sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; + if (*(int64_t*)sib1 != 1) { + NR_UE_rrc_inst[module_id].sib1[gNB_index] = sib1; + if( g_log->log_component[NR_RRC].level >= OAILOG_DEBUG ) { + xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) NR_UE_rrc_inst[module_id].sib1[gNB_index]); + } + LOG_I(NR_RRC, "SIB1 decoded\n"); + + /// dump_SIB1(); + // FIXME: improve condition for the RA trigger + // Check for on-demand not broadcasted SI + check_requested_SI_List(module_id, NR_UE_rrc_inst[module_id].requested_SI_List, *sib1); + if( nr_rrc_get_state(module_id) <= RRC_STATE_IDLE_NR ) { + NR_UE_rrc_inst[module_id].ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE; + LOG_D(PHY,"Setting state to NR_RRC_SI_RECEIVED\n"); + nr_rrc_set_state (module_id, NR_RRC_SI_RECEIVED); + } + // take ServingCellConfigCommon and configure L1/L2 + NR_UE_rrc_inst[module_id].servingCellConfigCommonSIB = sib1->servingCellConfigCommon; + nr_rrc_mac_config_req_ue(module_id,0,0,NULL,sib1->servingCellConfigCommon,NULL,NULL); + nr_rrc_ue_generate_ra_msg(module_id,gNB_index); + } else { + LOG_E(NR_RRC, "SIB1 not decoded\n"); + } + } + break; + + case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: + if ((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 1) { + LOG_W(NR_RRC, "Decoding SI not implemented yet\n"); + // TODO: Decode SI + /* + // SIB1 with schedulingInfoList is available + NR_SystemInformation_t *si = NR_UE_rrc_inst[module_id].si[gNB_index]; + + memcpy( si, + bcch_message->message.choice.c1->choice.systemInformation, + sizeof(NR_SystemInformation_t) ); + LOG_I(NR_RRC, "[UE %"PRIu8"] Decoding SI\n", module_id); + nr_decode_SI( ctxt_pP, gNB_index ); + + if (nfapi_mode == 3) + UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1; + */ + } + break; + + case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: + default: + break; + } + } + + if (nr_rrc_get_sub_state(module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) { + //if ( (NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL) || (!AMF_MODE_ENABLED)) { + nr_rrc_ue_generate_RRCSetupRequest(module_id, 0); + nr_rrc_set_sub_state( module_id, RRC_SUB_STATE_IDLE_CONNECTING ); + //} + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); + return 0; +} + +//----------------------------------------------------------------------------- +void +nr_rrc_ue_process_masterCellGroup( + const protocol_ctxt_t *const ctxt_pP, + uint8_t gNB_index, + OCTET_STRING_t *masterCellGroup +) +//----------------------------------------------------------------------------- +{ + NR_CellGroupConfig_t *cellGroupConfig=NULL; + uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, //might be added prefix later + (void **)&cellGroupConfig, + (uint8_t *)masterCellGroup->buf, + masterCellGroup->size, 0, 0); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); + } + + if( cellGroupConfig->spCellConfig != NULL && cellGroupConfig->spCellConfig->reconfigurationWithSync != NULL){ + //TODO (perform Reconfiguration with sync according to 5.3.5.5.2) + //TODO (resume all suspended radio bearers and resume SCG transmission for all radio bearers, if suspended) + // NSA procedures + } + + if(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config == NULL){ + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config = calloc(1,sizeof(NR_CellGroupConfig_t)); + } + + if( cellGroupConfig->rlc_BearerToReleaseList != NULL){ + //TODO (perform RLC bearer release as specified in 5.3.5.5.3) + } + + if( cellGroupConfig->rlc_BearerToAddModList != NULL){ + //TODO (perform the RLC bearer addition/modification as specified in 5.3.5.5.4) + if(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList != NULL){ + free(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList); + } + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList = calloc(1, sizeof(struct NR_CellGroupConfig__rlc_BearerToAddModList)); + memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList,cellGroupConfig->rlc_BearerToAddModList, + sizeof(struct NR_CellGroupConfig__rlc_BearerToAddModList)); + } + + if( cellGroupConfig->mac_CellGroupConfig != NULL){ + //TODO (configure the MAC entity of this cell group as specified in 5.3.5.5.5) + LOG_I(RRC, "Received mac_CellGroupConfig from gNB\n"); + if(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->mac_CellGroupConfig != NULL){ + LOG_E(RRC, "UE RRC instance already contains mac CellGroupConfig which will be overwritten\n"); + free(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->mac_CellGroupConfig); + } + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->mac_CellGroupConfig = malloc(sizeof(struct NR_MAC_CellGroupConfig)); + memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->mac_CellGroupConfig,cellGroupConfig->mac_CellGroupConfig, + sizeof(struct NR_MAC_CellGroupConfig)); + } + + if( cellGroupConfig->sCellToReleaseList != NULL){ + //TODO (perform SCell release as specified in 5.3.5.5.8) + } + + if( cellGroupConfig->spCellConfig != NULL){ + if (NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config && + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->spCellConfig) { + memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->spCellConfig,cellGroupConfig->spCellConfig, + sizeof(struct NR_SpCellConfig)); + } else { + if (NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config) + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->spCellConfig = cellGroupConfig->spCellConfig; + else + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config = cellGroupConfig; + } + LOG_D(RRC,"Sending CellGroupConfig to MAC\n"); + nr_rrc_mac_config_req_ue(ctxt_pP->module_id,0,0,NULL,NULL,cellGroupConfig,NULL); + //TODO (configure the SpCell as specified in 5.3.5.5.7) + } + + if( cellGroupConfig->sCellToAddModList != NULL){ + //TODO (perform SCell addition/modification as specified in 5.3.5.5.9) + } + + if( cellGroupConfig->ext2->bh_RLC_ChannelToReleaseList_r16 != NULL){ + //TODO (perform the BH RLC channel addition/modification as specified in 5.3.5.5.11) + } + + if( cellGroupConfig->ext2->bh_RLC_ChannelToAddModList_r16 != NULL){ + //TODO (perform the BH RLC channel addition/modification as specified in 5.3.5.5.11) + } +} + +/*--------------------------------------------------*/ +static void rrc_ue_generate_RRCSetupComplete( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t gNB_index, + const uint8_t Transaction_id, + uint8_t sel_plmn_id){ + + uint8_t buffer[100]; + uint8_t size; + const char *nas_msg; + int nas_msg_length; + NR_UE_MAC_INST_t *mac = get_mac_inst(0); + + if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->csi_MeasConfig) + AssertFatal(1==0,"2 > csi_MeasConfig is not null\n"); + + if (AMF_MODE_ENABLED) { +#if defined(ITTI_SIM) + as_nas_info_t initialNasMsg; + generateRegistrationRequest(&initialNasMsg, ctxt_pP->module_id); + nas_msg = (char*)initialNasMsg.data; + nas_msg_length = initialNasMsg.length; +#else + if (get_softmodem_params()->sa) { + as_nas_info_t initialNasMsg; + generateRegistrationRequest(&initialNasMsg, ctxt_pP->module_id); + nas_msg = (char*)initialNasMsg.data; + nas_msg_length = initialNasMsg.length; + } else { + nas_msg = (char *) NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data; + nas_msg_length = NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.length; + } +#endif + } else { + nas_msg = nr_nas_attach_req_imsi; + nas_msg_length = sizeof(nr_nas_attach_req_imsi); + } + size = do_RRCSetupComplete(ctxt_pP->module_id,buffer,Transaction_id,sel_plmn_id,nas_msg_length,nas_msg); + LOG_I(NR_RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCSetupComplete (bytes%d, gNB %d)\n", + ctxt_pP->module_id,ctxt_pP->frame, size, gNB_index); + LOG_D(NR_RRC, + "[FRAME %05d][RRC_UE][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCSetupComplete to gNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n", + ctxt_pP->frame, ctxt_pP->module_id+NB_RN_INST, size, gNB_index, nr_rrc_mui, ctxt_pP->module_id+NB_eNB_INST, DCCH); + + //for (int i=0;irnti; + rrc_data_req_ue(ctxt_pP, + DCCH, + nr_rrc_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE, TASK_RRC_GNB_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_NRUE, 0, UE_RRC_DCCH_DATA_IND); + UE_RRC_DCCH_DATA_IND (message_p).rbid = 1; + UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + UE_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); +#endif +} + +int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB_INFO *const Srb_info, const uint8_t gNB_index ){ + + NR_DL_CCCH_Message_t *dl_ccch_msg=NULL; + asn_dec_rval_t dec_rval; + int rval=0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_IN); + LOG_D(RRC,"[NR UE%d] Decoding DL-CCCH message (%d bytes), State %d\n",ctxt_pP->module_id,Srb_info->Rx_buffer.payload_size, + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State); + dec_rval = uper_decode(NULL, + &asn_DEF_NR_DL_CCCH_Message, + (void **)&dl_ccch_msg, + (uint8_t *)Srb_info->Rx_buffer.Payload, + Srb_info->Rx_buffer.payload_size,0,0); + +// if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout,&asn_DEF_NR_DL_CCCH_Message,(void *)dl_ccch_msg); +// } + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed==0)) { + LOG_E(RRC,"[UE %d] Frame %d : Failed to decode DL-CCCH-Message (%zu bytes)\n",ctxt_pP->module_id,ctxt_pP->frame,dec_rval.consumed); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT); + return -1; + } + + if (dl_ccch_msg->message.present == NR_DL_CCCH_MessageType_PR_c1) { + if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus > 0) { + switch (dl_ccch_msg->message.choice.c1->present) { + case NR_DL_CCCH_MessageType__c1_PR_NOTHING: + LOG_I(NR_RRC, "[UE%d] Frame %d : Received PR_NOTHING on DL-CCCH-Message\n", + ctxt_pP->module_id, + ctxt_pP->frame); + rval = 0; + break; + + case NR_DL_CCCH_MessageType__c1_PR_rrcReject: + LOG_I(NR_RRC, + "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCReject \n", + ctxt_pP->module_id, + ctxt_pP->frame); + rval = 0; + break; + + case NR_DL_CCCH_MessageType__c1_PR_rrcSetup: + LOG_I(NR_RRC, + "[UE%d][RAPROC] Frame %d : Logical Channel DL-CCCH (SRB0), Received NR_RRCSetup RNTI %x\n", + ctxt_pP->module_id, + ctxt_pP->frame, + ctxt_pP->rnti); + + // Get configuration + // Release T300 timer + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T300_active = 0; + + nr_rrc_ue_process_masterCellGroup( + ctxt_pP, + gNB_index, + &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup); + nr_sa_rrc_ue_process_radioBearerConfig( + ctxt_pP, + gNB_index, + &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); + nr_rrc_set_state (ctxt_pP->module_id, RRC_STATE_CONNECTED); + nr_rrc_set_sub_state (ctxt_pP->module_id, RRC_SUB_STATE_CONNECTED); + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].rnti = ctxt_pP->rnti; + rrc_ue_generate_RRCSetupComplete( + ctxt_pP, + gNB_index, + dl_ccch_msg->message.choice.c1->choice.rrcSetup->rrc_TransactionIdentifier, + NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); + rval = 0; + break; + + default: + LOG_E(NR_RRC, "[UE%d] Frame %d : Unknown message\n", + ctxt_pP->module_id, + ctxt_pP->frame); + rval = -1; + break; + } + } + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT); + return rval; + } + + // from NR SRB3 + int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message( + const module_id_t module_id, + const uint8_t gNB_index, + const uint8_t *bufferP, + const uint32_t buffer_len ){ + // uper_decode by nr R15 rrc_connection_reconfiguration + + int32_t i; + NR_DL_DCCH_Message_t *nr_dl_dcch_msg = NULL; + MessageDef *msg_p; + + asn_dec_rval_t dec_rval = uper_decode( NULL, + &asn_DEF_NR_DL_DCCH_Message, + (void**)&nr_dl_dcch_msg, + (uint8_t *)bufferP, + buffer_len, 0, 0); + + if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { + for (i=0; imessage.present){ + case NR_DL_DCCH_MessageType_PR_c1: + switch(nr_dl_dcch_msg->message.choice.c1->present){ + case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: + nr_rrc_ue_process_rrcReconfiguration(module_id,nr_dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration); + break; + + case NR_DL_DCCH_MessageType__c1_PR_NOTHING: + case NR_DL_DCCH_MessageType__c1_PR_rrcResume: + case NR_DL_DCCH_MessageType__c1_PR_rrcRelease: + msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CONN_RELEASE_IND); + if((nr_dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.present == NR_RRCRelease__criticalExtensions_PR_rrcRelease) && + (nr_dl_dcch_msg->message.choice.c1->present == NR_DL_DCCH_MessageType__c1_PR_rrcRelease)){ + nr_dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationTimer = + NR_RRCRelease_IEs__deprioritisationReq__deprioritisationTimer_min5; + nr_dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationType = + NR_RRCRelease_IEs__deprioritisationReq__deprioritisationType_frequency; + } + itti_send_msg_to_task(TASK_RRC_NRUE,module_id,msg_p); + break; + + case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: + case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: + case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: + case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry: + case NR_DL_DCCH_MessageType__c1_PR_counterCheck: + case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand: + case NR_DL_DCCH_MessageType__c1_PR_dlDedicatedMessageSegment_r16: + case NR_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r16: + case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransferMRDC_r16: + case NR_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r16: + case NR_DL_DCCH_MessageType__c1_PR_spare3: + case NR_DL_DCCH_MessageType__c1_PR_spare2: + case NR_DL_DCCH_MessageType__c1_PR_spare1: + default: + // not supported or unused + break; + } + break; + case NR_DL_DCCH_MessageType_PR_NOTHING: + case NR_DL_DCCH_MessageType_PR_messageClassExtension: + default: + // not supported or unused + break; + } + + // release memory allocation + SEQUENCE_free( &asn_DEF_NR_DL_DCCH_Message, (void *)nr_dl_dcch_msg, 1 ); + }else{ + // log.. + } + + return 0; + } + + + //----------------------------------------------------------------------------- + void + nr_rrc_ue_process_securityModeCommand( + const protocol_ctxt_t *const ctxt_pP, + NR_SecurityModeCommand_t *const securityModeCommand, + const uint8_t gNB_index + ) + //----------------------------------------------------------------------------- + { + asn_enc_rval_t enc_rval; + NR_UL_DCCH_Message_t ul_dcch_msg; + uint8_t buffer[200]; + int i, securityMode; + LOG_I(NR_RRC,"[UE %d] SFN/SF %d/%d: Receiving from SRB1 (DL-DCCH), Processing securityModeCommand (eNB %d)\n", + ctxt_pP->module_id,ctxt_pP->frame, ctxt_pP->subframe, gNB_index); + + switch (securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm) { + case NR_CipheringAlgorithm_nea0: + LOG_I(NR_RRC,"[UE %d] Security algorithm is set to nea0\n", + ctxt_pP->module_id); + securityMode= NR_CipheringAlgorithm_nea0; + break; + + case NR_CipheringAlgorithm_nea1: + LOG_I(NR_RRC,"[UE %d] Security algorithm is set to nea1\n",ctxt_pP->module_id); + securityMode= NR_CipheringAlgorithm_nea1; + break; + + case NR_CipheringAlgorithm_nea2: + LOG_I(NR_RRC,"[UE %d] Security algorithm is set to nea2\n", + ctxt_pP->module_id); + securityMode = NR_CipheringAlgorithm_nea2; + break; + + default: + LOG_I(NR_RRC,"[UE %d] Security algorithm is set to none\n",ctxt_pP->module_id); + securityMode = NR_CipheringAlgorithm_spare1; + break; + } + NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm = + securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm; + + if (securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm != NULL) + { + switch (*securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm) { + case NR_IntegrityProtAlgorithm_nia1: + LOG_I(NR_RRC,"[UE %d] Integrity protection algorithm is set to nia1\n",ctxt_pP->module_id); + securityMode |= 1 << 5; + break; + + case NR_IntegrityProtAlgorithm_nia2: + LOG_I(NR_RRC,"[UE %d] Integrity protection algorithm is set to nia2\n",ctxt_pP->module_id); + securityMode |= 1 << 6; + break; + + default: + LOG_I(NR_RRC,"[UE %d] Integrity protection algorithm is set to none\n",ctxt_pP->module_id); + securityMode |= 0x70 ; + break; + } + + NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm = + *securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm; + + } + + LOG_D(NR_RRC,"[UE %d] security mode is %x \n",ctxt_pP->module_id, securityMode); + memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); + //memset((void *)&SecurityModeCommand,0,sizeof(SecurityModeCommand_t)); + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + ul_dcch_msg.message.choice.c1 = calloc(1, sizeof(*ul_dcch_msg.message.choice.c1)); + + if (securityMode >= NO_SECURITY_MODE) { + LOG_I(NR_RRC, "rrc_ue_process_securityModeCommand, security mode complete case \n"); + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; + } else { + LOG_I(NR_RRC, "rrc_ue_process_securityModeCommand, security mode failure case \n"); + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeFailure; + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; + } + + uint8_t *kRRCenc = NULL; + uint8_t *kUPenc = NULL; + uint8_t *kRRCint = NULL; + nr_derive_key_up_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm, + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, + &kUPenc); + nr_derive_key_rrc_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm, + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, + &kRRCenc); + nr_derive_key_rrc_int(NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm, + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, + &kRRCint); + LOG_I(NR_RRC, "driving kRRCenc, kRRCint and kUPenc from KgNB=" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x\n", + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[0], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[1], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[2], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[3], + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[4], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[5], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[6], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[7], + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[8], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[9], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[10], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[11], + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[12], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[13], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[14], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[15], + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[16], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[17], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[18], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[19], + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[20], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[21], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[22], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[23], + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[24], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[25], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[26], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[27], + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[28], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[29], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[30], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[31]); + + if (securityMode != 0xff) { + pdcp_config_set_security(ctxt_pP, NULL, DCCH, DCCH+2, + NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm + | (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4), + kRRCenc, kRRCint, kUPenc); + } else { + LOG_I(NR_RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x", securityMode); + } + + if (securityModeCommand->criticalExtensions.present == NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand) { + ul_dcch_msg.message.choice.c1->choice.securityModeComplete = CALLOC(1, sizeof(NR_SecurityModeComplete_t)); + ul_dcch_msg.message.choice.c1->choice.securityModeComplete->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier; + ul_dcch_msg.message.choice.c1->choice.securityModeComplete->criticalExtensions.present = NR_SecurityModeComplete__criticalExtensions_PR_securityModeComplete; + ul_dcch_msg.message.choice.c1->choice.securityModeComplete->criticalExtensions.choice.securityModeComplete = CALLOC(1, sizeof(NR_SecurityModeComplete_IEs_t)); + ul_dcch_msg.message.choice.c1->choice.securityModeComplete->criticalExtensions.choice.securityModeComplete->nonCriticalExtension =NULL; + LOG_I(NR_RRC,"[UE %d] SFN/SF %d/%d: Receiving from SRB1 (DL-DCCH), encoding securityModeComplete (gNB %d), rrc_TransactionIdentifier: %ld\n", + ctxt_pP->module_id,ctxt_pP->frame, ctxt_pP->subframe, gNB_index, securityModeCommand->rrc_TransactionIdentifier); + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, + NULL, + (void *)&ul_dcch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + log_dump(MAC, buffer, 16, LOG_DUMP_CHAR, "securityModeComplete payload: "); + LOG_D(NR_RRC, "securityModeComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8); + + for (i = 0; i < (enc_rval.encoded + 7) / 8; i++) { + LOG_T(NR_RRC, "%02x.", buffer[i]); + } + + LOG_T(NR_RRC, "\n"); + #ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM, + (enc_rval.encoded + 7) / 8); + memcpy (message_buffer, buffer, (enc_rval.encoded + 7) / 8); + + message_p = itti_alloc_new_message (TASK_RRC_NRUE, 0, UE_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = (enc_rval.encoded + 7) / 8; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); + #else + rrc_data_req_ue (ctxt_pP, + DCCH, + nr_rrc_mui++, + SDU_CONFIRM_NO, + (enc_rval.encoded + 7) / 8, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + #endif + } else + LOG_W(NR_RRC,"securityModeCommand->criticalExtensions.present (%d) != NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand\n", + securityModeCommand->criticalExtensions.present); + } + + //----------------------------------------------------------------------------- + void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) { + uint8_t i=0,rv[6]; + + if(get_softmodem_params()->sa) { + AMF_MODE_ENABLED = 1; + } + if(NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size ==0) { + // Get RRCConnectionRequest, fill random for now + // Generate random byte stream for contention resolution + for (i=0; i<6; i++) { + #ifdef SMBV + // if SMBV is configured the contention resolution needs to be fix for the connection procedure to succeed + rv[i]=i; + #else + rv[i]=taus()&0xff; + #endif + LOG_T(NR_RRC,"%x.",rv[i]); + } + + LOG_T(NR_RRC,"\n"); + NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size = + do_RRCSetupRequest( + module_id, + (uint8_t *)NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.Payload, + rv); + LOG_I(NR_RRC,"[UE %d] : Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, gNB %d)\n", + module_id, NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index); + + for (i=0; idrb_Identity); + + if(!AMF_MODE_ENABLED) { + ip_addr_offset3 = 0; + ip_addr_offset4 = 1; + LOG_I(OIP, "[UE %d] trying to bring up the OAI interface %d, IP X.Y.%d.%d\n", ue_mod_idP, ip_addr_offset3+ue_mod_idP, + ip_addr_offset3+ue_mod_idP+1, ip_addr_offset4+ue_mod_idP+1); + oip_ifup = nas_config(ip_addr_offset3+ue_mod_idP+1, // interface_id + UE_NAS_USE_TUN?1:(ip_addr_offset3+ue_mod_idP+1), // third_octet + ip_addr_offset4+ue_mod_idP+1, // fourth_octet + "oip"); // interface suffix (when using kernel module) + + if (oip_ifup == 0 && (!UE_NAS_USE_TUN)) { // interface is up --> send a config the DRB + LOG_I(OIP, "[UE %d] Config the ue net interface %d to send/receive pkt on DRB %ld to/from the protocol stack\n", + ue_mod_idP, + ip_addr_offset3+ue_mod_idP, + (long int)((gNB_index * NR_maxDRB) + DRB_config->drb_Identity)); + rb_conf_ipv4(0,//add + ue_mod_idP,//cx align with the UE index + ip_addr_offset3+ue_mod_idP,//inst num_enb+ue_index + (gNB_index * NR_maxDRB) + DRB_config->drb_Identity,//rb + 0,//dscp + ipv4_address(ip_addr_offset3+ue_mod_idP+1, ip_addr_offset4+ue_mod_idP+1),//saddr + ipv4_address(ip_addr_offset3+ue_mod_idP+1, gNB_index+1));//daddr + LOG_D(NR_RRC,"[UE %d] State = Attached (gNB %d)\n",ue_mod_idP,gNB_index); + } + } + + return(0); + } + + //----------------------------------------------------------------------------- + void + nr_rrc_ue_process_measConfig( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t gNB_index, + NR_MeasConfig_t *const measConfig + ) + //----------------------------------------------------------------------------- + { + int i; + long ind; + NR_MeasObjectToAddMod_t *measObj = NULL; + NR_ReportConfigToAddMod_t *reportConfig = NULL; + + if (measConfig->measObjectToRemoveList != NULL) { + for (i = 0; i < measConfig->measObjectToRemoveList->list.count; i++) { + ind = *measConfig->measObjectToRemoveList->list.array[i]; + free(NR_UE_rrc_inst[ctxt_pP->module_id].MeasObj[gNB_index][ind-1]); + } + } + + if (measConfig->measObjectToAddModList != NULL) { + LOG_I(NR_RRC, "Measurement Object List is present\n"); + for (i = 0; i < measConfig->measObjectToAddModList->list.count; i++) { + measObj = measConfig->measObjectToAddModList->list.array[i]; + ind = measConfig->measObjectToAddModList->list.array[i]->measObjectId; + + if (NR_UE_rrc_inst[ctxt_pP->module_id].MeasObj[gNB_index][ind-1]) { + LOG_D(NR_RRC, "Modifying measurement object %ld\n",ind); + memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].MeasObj[gNB_index][ind-1], + (char *)measObj, + sizeof(NR_MeasObjectToAddMod_t)); + } else { + LOG_I(NR_RRC, "Adding measurement object %ld\n", ind); + + if (measObj->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { + NR_UE_rrc_inst[ctxt_pP->module_id].MeasObj[gNB_index][ind-1]=measObj; + } + } + } + + LOG_I(NR_RRC, "call rrc_mac_config_req \n"); + // rrc_mac_config_req_ue + } + + if (measConfig->reportConfigToRemoveList != NULL) { + for (i = 0; i < measConfig->reportConfigToRemoveList->list.count; i++) { + ind = *measConfig->reportConfigToRemoveList->list.array[i]; + free(NR_UE_rrc_inst[ctxt_pP->module_id].ReportConfig[gNB_index][ind-1]); + } + } + + if (measConfig->reportConfigToAddModList != NULL) { + LOG_I(NR_RRC,"Report Configuration List is present\n"); + for (i = 0; i < measConfig->reportConfigToAddModList->list.count; i++) { + ind = measConfig->reportConfigToAddModList->list.array[i]->reportConfigId; + reportConfig = measConfig->reportConfigToAddModList->list.array[i]; + + if (NR_UE_rrc_inst[ctxt_pP->module_id].ReportConfig[gNB_index][ind-1]) { + LOG_I(NR_RRC, "Modifying Report Configuration %ld\n", ind-1); + memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].ReportConfig[gNB_index][ind-1], + (char *)measConfig->reportConfigToAddModList->list.array[i], + sizeof(NR_ReportConfigToAddMod_t)); + } else { + LOG_D(NR_RRC,"Adding Report Configuration %ld %p \n", ind-1, measConfig->reportConfigToAddModList->list.array[i]); + if (reportConfig->reportConfig.present == NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) { + NR_UE_rrc_inst[ctxt_pP->module_id].ReportConfig[gNB_index][ind-1] = measConfig->reportConfigToAddModList->list.array[i]; + } + } + } + } + + if (measConfig->measIdToRemoveList != NULL) { + for (i = 0; i < measConfig->measIdToRemoveList->list.count; i++) { + ind = *measConfig->measIdToRemoveList->list.array[i]; + free(NR_UE_rrc_inst[ctxt_pP->module_id].MeasId[gNB_index][ind-1]); + } + } + + if (measConfig->measIdToAddModList != NULL) { + for (i = 0; i < measConfig->measIdToAddModList->list.count; i++) { + ind = measConfig->measIdToAddModList->list.array[i]->measId; + + if (NR_UE_rrc_inst[ctxt_pP->module_id].MeasId[gNB_index][ind-1]) { + LOG_D(NR_RRC, "Modifying Measurement ID %ld\n",ind-1); + memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].MeasId[gNB_index][ind-1], + (char *)measConfig->measIdToAddModList->list.array[i], + sizeof(NR_MeasIdToAddMod_t)); + } else { + LOG_D(NR_RRC, "Adding Measurement ID %ld %p\n", ind-1, measConfig->measIdToAddModList->list.array[i]); + NR_UE_rrc_inst[ctxt_pP->module_id].MeasId[gNB_index][ind-1] = measConfig->measIdToAddModList->list.array[i]; + } + } + } + + if (measConfig->quantityConfig != NULL) { + if (NR_UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[gNB_index]) { + LOG_D(NR_RRC,"Modifying Quantity Configuration \n"); + memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[gNB_index], + (char *)measConfig->quantityConfig, + sizeof(NR_QuantityConfig_t)); + } else { + LOG_D(NR_RRC, "Adding Quantity configuration\n"); + NR_UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[gNB_index] = measConfig->quantityConfig; + } + } + + if (measConfig->measGapConfig != NULL) { + if (NR_UE_rrc_inst[ctxt_pP->module_id].measGapConfig[gNB_index]) { + memcpy((char *)NR_UE_rrc_inst[ctxt_pP->module_id].measGapConfig[gNB_index], + (char *)measConfig->measGapConfig, + sizeof(NR_MeasGapConfig_t)); + } else { + NR_UE_rrc_inst[ctxt_pP->module_id].measGapConfig[gNB_index] = measConfig->measGapConfig; + } + } + + if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_ssb_RSRP) { + NR_UE_rrc_inst[ctxt_pP->module_id].s_measure = measConfig->s_MeasureConfig->choice.ssb_RSRP; + } else if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_csi_RSRP) { + NR_UE_rrc_inst[ctxt_pP->module_id].s_measure = measConfig->s_MeasureConfig->choice.csi_RSRP; + } + } + + //----------------------------------------------------------------------------- + void + nr_sa_rrc_ue_process_radioBearerConfig( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t gNB_index, + NR_RadioBearerConfig_t *const radioBearerConfig + ) + //----------------------------------------------------------------------------- + { + long SRB_id, DRB_id; + int i, cnt; + + if( radioBearerConfig->srb3_ToRelease != NULL){ + if( *radioBearerConfig->srb3_ToRelease == TRUE){ + //TODO (release the PDCP entity and the srb-Identity of the SRB3.) + } + } + + if (radioBearerConfig->srb_ToAddModList != NULL) { + if (radioBearerConfig->securityConfig != NULL) { + if (*radioBearerConfig->securityConfig->keyToUse == NR_SecurityConfig__keyToUse_master) { + NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm = radioBearerConfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm; + NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm = *radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm; + } + } + + uint8_t *kRRCenc = NULL; + uint8_t *kRRCint = NULL; + nr_derive_key_rrc_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm, + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kRRCenc); + nr_derive_key_rrc_int(NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm, + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kRRCint); + + // Refresh SRBs + nr_rrc_pdcp_config_asn1_req(ctxt_pP, + radioBearerConfig->srb_ToAddModList, + NULL, + NULL, + NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm | + (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4), + kRRCenc, + kRRCint, + NULL, + NULL, + NULL, + NULL, + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList); + // Refresh SRBs + nr_rrc_rlc_config_asn1_req(ctxt_pP, + radioBearerConfig->srb_ToAddModList, + NULL, + NULL, + NULL, + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList + ); + + for (cnt = 0; cnt < radioBearerConfig->srb_ToAddModList->list.count; cnt++) { + SRB_id = radioBearerConfig->srb_ToAddModList->list.array[cnt]->srb_Identity; + LOG_D(NR_RRC,"[UE %d]: Frame %d SRB config cnt %d (SRB%ld)\n", ctxt_pP->module_id, ctxt_pP->frame, cnt, SRB_id); + if (SRB_id == 1) { + if (NR_UE_rrc_inst[ctxt_pP->module_id].SRB1_config[gNB_index]) { + memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].SRB1_config[gNB_index], + radioBearerConfig->srb_ToAddModList->list.array[cnt], + sizeof(NR_SRB_ToAddMod_t)); + } else { + NR_UE_rrc_inst[ctxt_pP->module_id].SRB1_config[gNB_index] = radioBearerConfig->srb_ToAddModList->list.array[cnt]; + nr_rrc_ue_establish_srb1(ctxt_pP->module_id, + ctxt_pP->frame, + gNB_index, + radioBearerConfig->srb_ToAddModList->list.array[cnt]); + + LOG_I(NR_RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB1 gNB %d) --->][MAC_UE][MOD %02d][]\n", + ctxt_pP->frame, ctxt_pP->module_id, gNB_index, ctxt_pP->module_id); + nr_rrc_mac_config_req_ue_logicalChannelBearer(ctxt_pP->module_id,0,gNB_index,1,true); //todo handle mac_LogicalChannelConfig + // rrc_mac_config_req_ue + } + } else { + if (NR_UE_rrc_inst[ctxt_pP->module_id].SRB2_config[gNB_index]) { + memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].SRB2_config[gNB_index], + radioBearerConfig->srb_ToAddModList->list.array[cnt], sizeof(NR_SRB_ToAddMod_t)); + } else { + NR_UE_rrc_inst[ctxt_pP->module_id].SRB2_config[gNB_index] = radioBearerConfig->srb_ToAddModList->list.array[cnt]; + nr_rrc_ue_establish_srb2(ctxt_pP->module_id, + ctxt_pP->frame, + gNB_index, + radioBearerConfig->srb_ToAddModList->list.array[cnt]); + + LOG_I(NR_RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SRB2 gNB %d) --->][MAC_UE][MOD %02d][]\n", + ctxt_pP->frame, ctxt_pP->module_id, gNB_index, ctxt_pP->module_id); + nr_rrc_mac_config_req_ue_logicalChannelBearer(ctxt_pP->module_id,0,gNB_index,2,true); //todo handle mac_LogicalChannelConfig + // rrc_mac_config_req_ue + } + } // srb2 + } + } // srb_ToAddModList + + // Establish DRBs if present + if (radioBearerConfig->drb_ToAddModList != NULL) { + if ((NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB == NULL) && + (radioBearerConfig->drb_ToAddModList->list.count >= 1)) { + NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB = malloc(sizeof(rb_id_t)); + *NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB = radioBearerConfig->drb_ToAddModList->list.array[0]->drb_Identity; + } + + for (cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) { + DRB_id = radioBearerConfig->drb_ToAddModList->list.array[cnt]->drb_Identity; + if (NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]) { + memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1], + radioBearerConfig->drb_ToAddModList->list.array[cnt], sizeof(NR_DRB_ToAddMod_t)); + } else { + //LOG_D(NR_RRC, "Adding DRB %ld %p\n", DRB_id-1, radioBearerConfig->drb_ToAddModList->list.array[cnt]); + NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1] = radioBearerConfig->drb_ToAddModList->list.array[cnt]; + int j; + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list = NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList; + if (rlc_bearer2add_list != NULL) { + for(j = 0; j < rlc_bearer2add_list->list.count; j++){ + if(rlc_bearer2add_list->list.array[j]->servedRadioBearer != NULL){ + if(rlc_bearer2add_list->list.array[j]->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity){ + if(DRB_id == rlc_bearer2add_list->list.array[j]->servedRadioBearer->choice.drb_Identity){ + LOG_I(NR_RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (DRB lcid %ld gNB %d) --->][MAC_UE][MOD %02d][]\n", + ctxt_pP->frame, ctxt_pP->module_id, rlc_bearer2add_list->list.array[j]->logicalChannelIdentity, 0, ctxt_pP->module_id); + nr_rrc_mac_config_req_ue_logicalChannelBearer(ctxt_pP->module_id,0,0,rlc_bearer2add_list->list.array[j]->logicalChannelIdentity,true); //todo handle mac_LogicalChannelConfig + } + } + } + } + } + } + } + + uint8_t *kUPenc = NULL; + uint8_t *kUPint = NULL; + + nr_derive_key_up_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm, + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kUPenc); + nr_derive_key_up_int(NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm, + NR_UE_rrc_inst[ctxt_pP->module_id].kgnb, &kUPint); + + MSC_LOG_TX_MESSAGE( + MSC_RRC_UE, + MSC_PDCP_UE, + NULL, + 0, + MSC_AS_TIME_FMT" CONFIG_REQ UE %x DRB (security %X)", + MSC_AS_TIME_ARGS(ctxt_pP), + ctxt_pP->rnti, + NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm | + (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4)); + + // Refresh DRBs + nr_rrc_pdcp_config_asn1_req(ctxt_pP, + NULL, + radioBearerConfig->drb_ToAddModList, + NULL, + 0, + NULL, + NULL, + kUPenc, + kUPint, + NULL, + NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB, + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList); + // Refresh DRBs + nr_rrc_rlc_config_asn1_req(ctxt_pP, + NULL, + radioBearerConfig->drb_ToAddModList, + NULL, + NULL, + NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToAddModList + ); + } // drb_ToAddModList // + + if (radioBearerConfig->drb_ToReleaseList != NULL) { + for (i = 0; i < radioBearerConfig->drb_ToReleaseList->list.count; i++) { + DRB_id = *radioBearerConfig->drb_ToReleaseList->list.array[i]; + free(NR_UE_rrc_inst[ctxt_pP->module_id].DRB_config[gNB_index][DRB_id-1]); + } + } + + if (NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList != NULL) { + for (i = 0; i < NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList->list.count; i++) { + NR_LogicalChannelIdentity_t lcid = *NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config->rlc_BearerToReleaseList->list.array[i]; + LOG_I(NR_RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (RB lcid %ld gNB %d release) --->][MAC_UE][MOD %02d][]\n", + ctxt_pP->frame, ctxt_pP->module_id, lcid, 0, ctxt_pP->module_id); + nr_rrc_mac_config_req_ue_logicalChannelBearer(ctxt_pP->module_id,0,0,lcid,false); //todo handle mac_LogicalChannelConfig + } + } + + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State = NR_RRC_CONNECTED; + LOG_I(NR_RRC,"[UE %d] State = NR_RRC_CONNECTED (gNB %d)\n", ctxt_pP->module_id, gNB_index); + } + + //----------------------------------------------------------------------------- + void + rrc_ue_process_rrcReconfiguration( + const protocol_ctxt_t *const ctxt_pP, + NR_RRCReconfiguration_t *rrcReconfiguration, + uint8_t gNB_index + ) + //----------------------------------------------------------------------------- + { + LOG_I(NR_RRC, "[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing RRCReconfiguration (gNB %d)\n", + ctxt_pP->module_id, ctxt_pP->frame, gNB_index); + + NR_RRCReconfiguration_IEs_t *ie = NULL; + + if (rrcReconfiguration->criticalExtensions.present + == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration) { + ie = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration; + if (ie->measConfig != NULL) { + LOG_I(NR_RRC, "Measurement Configuration is present\n"); + // nr_rrc_ue_process_measConfig(ctxt_pP, gNB_index, ie->measConfig); + } + + if(ie->nonCriticalExtension->masterCellGroup!=NULL) { + nr_rrc_ue_process_masterCellGroup( + ctxt_pP, + gNB_index, + ie->nonCriticalExtension->masterCellGroup); + } + + if (ie->radioBearerConfig != NULL) { + LOG_I(NR_RRC, "radio Bearer Configuration is present\n"); + nr_sa_rrc_ue_process_radioBearerConfig(ctxt_pP, gNB_index, ie->radioBearerConfig); + } + + /* Check if there is dedicated NAS information to forward to NAS */ + if (ie->nonCriticalExtension->dedicatedNAS_MessageList != NULL) { + int list_count; + uint32_t pdu_length; + uint8_t *pdu_buffer; + MessageDef *msg_p; + + for (list_count = 0; list_count < ie->nonCriticalExtension->dedicatedNAS_MessageList->list.count; list_count++) { + pdu_length = ie->nonCriticalExtension->dedicatedNAS_MessageList->list.array[list_count]->size; + pdu_buffer = ie->nonCriticalExtension->dedicatedNAS_MessageList->list.array[list_count]->buf; + msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CONN_ESTABLI_CNF); + NAS_CONN_ESTABLI_CNF(msg_p).errCode = AS_SUCCESS; + NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length = pdu_length; + NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data = pdu_buffer; + itti_send_msg_to_task(TASK_NAS_NRUE, ctxt_pP->instance, msg_p); + } + + free (ie->nonCriticalExtension->dedicatedNAS_MessageList); + } + } + } + + //----------------------------------------------------------------------------- + void nr_rrc_ue_generate_RRCReconfigurationComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, const uint8_t Transaction_id ) { + uint8_t buffer[32], size; + size = do_NR_RRCReconfigurationComplete(ctxt_pP, buffer, Transaction_id); + LOG_I(NR_RRC,PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel UL-DCCH (SRB1), Generating RRCReconfigurationComplete (bytes %d, gNB_index %d)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size, gNB_index); + LOG_D(RLC, + "[FRAME %05d][RRC_UE][INST %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCReconfigurationComplete to gNB %d MUI %d) --->][PDCP][INST %02d][RB %02d]\n", + ctxt_pP->frame, + UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), + size, + gNB_index, + nr_rrc_mui, + UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), + DCCH); + #ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM,size); + memcpy (message_buffer, buffer, size); + + message_p = itti_alloc_new_message (TASK_RRC_NRUE, 0, UE_RRC_DCCH_DATA_IND); + UE_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + UE_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); + + #else + rrc_data_req_ue ( + ctxt_pP, + DCCH, + nr_rrc_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + #endif + + } + + // from NR SRB1 + //----------------------------------------------------------------------------- + int + nr_rrc_ue_decode_dcch( + const protocol_ctxt_t *const ctxt_pP, + const srb_id_t Srb_id, + const uint8_t *const Buffer, + const uint8_t gNB_indexP + ) + //----------------------------------------------------------------------------- + { + asn_dec_rval_t dec_rval; + NR_DL_DCCH_Message_t *dl_dcch_msg = NULL; + MessageDef *msg_p; + + if (Srb_id != 1) { + LOG_E(NR_RRC,"[UE %d] Frame %d: Received message on DL-DCCH (SRB%ld), should not have ...\n", + ctxt_pP->module_id, ctxt_pP->frame, Srb_id); + } else { + LOG_D(NR_RRC, "Received message on SRB%ld\n", Srb_id); + } + + LOG_D(NR_RRC, "Decoding DL-DCCH Message\n"); + dec_rval = uper_decode( NULL, + &asn_DEF_NR_DL_DCCH_Message, + (void **)&dl_dcch_msg, + Buffer, + RRC_BUF_SIZE, + 0, + 0); + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E(NR_RRC, "Failed to decode DL-DCCH (%zu bytes)\n", dec_rval.consumed); + return -1; + } + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message,(void *)dl_dcch_msg); + } + + if (dl_dcch_msg->message.present == NR_DL_DCCH_MessageType_PR_c1) { + switch (dl_dcch_msg->message.choice.c1->present) { + case NR_DL_DCCH_MessageType__c1_PR_NOTHING: + LOG_I(NR_RRC, "Received PR_NOTHING on DL-DCCH-Message\n"); + break; + + case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: + { + rrc_ue_process_rrcReconfiguration(ctxt_pP, + dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration, + gNB_indexP); + nr_rrc_ue_generate_RRCReconfigurationComplete(ctxt_pP, + gNB_indexP, + dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration->rrc_TransactionIdentifier); + break; + } + + case NR_DL_DCCH_MessageType__c1_PR_rrcResume: + case NR_DL_DCCH_MessageType__c1_PR_rrcRelease: + LOG_I(NR_RRC, "[UE %d] Received RRC Release (gNB %d)\n", + ctxt_pP->module_id, gNB_indexP); + + msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CONN_RELEASE_IND); + + if((dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.present == NR_RRCRelease__criticalExtensions_PR_rrcRelease) && + (dl_dcch_msg->message.choice.c1->present == NR_DL_DCCH_MessageType__c1_PR_rrcRelease)){ + dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationTimer = + NR_RRCRelease_IEs__deprioritisationReq__deprioritisationTimer_min5; + dl_dcch_msg->message.choice.c1->choice.rrcRelease->criticalExtensions.choice.rrcRelease->deprioritisationReq->deprioritisationType = + NR_RRCRelease_IEs__deprioritisationReq__deprioritisationType_frequency; + } + + itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); + break; + case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry: + LOG_I(NR_RRC, "[UE %d] Received Capability Enquiry (gNB %d)\n", ctxt_pP->module_id,gNB_indexP); + nr_rrc_ue_process_ueCapabilityEnquiry( + ctxt_pP, + dl_dcch_msg->message.choice.c1->choice.ueCapabilityEnquiry, + gNB_indexP); + break; + case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: + LOG_I(NR_RRC, + "[UE%d] Frame %d : Logical Channel DL-DCCH (SRB1), Received RRCReestablishment\n", + ctxt_pP->module_id, + ctxt_pP->frame); + nr_rrc_ue_generate_rrcReestablishmentComplete( + ctxt_pP, + dl_dcch_msg->message.choice.c1->choice.rrcReestablishment, + gNB_indexP); + break; + case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: + { + NR_DLInformationTransfer_t *dlInformationTransfer = dl_dcch_msg->message.choice.c1->choice.dlInformationTransfer; + + if (dlInformationTransfer->criticalExtensions.present + == NR_DLInformationTransfer__criticalExtensions_PR_dlInformationTransfer) { + /* This message hold a dedicated info NAS payload, forward it to NAS */ + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = + dlInformationTransfer->criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message; + + MessageDef *msg_p; + msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_DOWNLINK_DATA_IND); + NAS_DOWNLINK_DATA_IND(msg_p).UEid = ctxt_pP->module_id; // TODO set the UEid to something else ? + NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length = dedicatedNAS_Message->size; + NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data = dedicatedNAS_Message->buf; + itti_send_msg_to_task(TASK_NAS_NRUE, ctxt_pP->instance, msg_p); + } + } + + break; + case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand: + case NR_DL_DCCH_MessageType__c1_PR_dlDedicatedMessageSegment_r16: + case NR_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r16: + case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransferMRDC_r16: + case NR_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r16: + case NR_DL_DCCH_MessageType__c1_PR_spare3: + case NR_DL_DCCH_MessageType__c1_PR_spare2: + case NR_DL_DCCH_MessageType__c1_PR_spare1: + case NR_DL_DCCH_MessageType__c1_PR_counterCheck: + break; + case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: + LOG_I(NR_RRC, "[UE %d] Received securityModeCommand (gNB %d)\n", + ctxt_pP->module_id, gNB_indexP); + nr_rrc_ue_process_securityModeCommand( + ctxt_pP, + dl_dcch_msg->message.choice.c1->choice.securityModeCommand, + gNB_indexP); + + break; + } + } + return 0; + } + + //----------------------------------------------------------------------------- + void *rrc_nrue_task( void *args_p ) { + MessageDef *msg_p; + instance_t instance; + unsigned int ue_mod_id; + int result; + NR_SRB_INFO *srb_info_p; + protocol_ctxt_t ctxt; + itti_mark_task_ready (TASK_RRC_NRUE); + + while(1) { + // Wait for a message + itti_receive_msg (TASK_RRC_NRUE, &msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); + ue_mod_id = UE_INSTANCE_TO_MODULE_ID(instance); + + switch (ITTI_MSG_ID(msg_p)) { + case TERMINATE_MESSAGE: + LOG_W(NR_RRC, " *** Exiting RRC thread\n"); + itti_exit_task (); + break; + + case MESSAGE_TEST: + LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); + break; + + case NR_RRC_MAC_BCCH_DATA_IND: + LOG_D(NR_RRC, "[UE %d] Received %s: frameP %d, gNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), + NR_RRC_MAC_BCCH_DATA_IND (msg_p).frame, NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NOT_A_RNTI, NR_RRC_MAC_BCCH_DATA_IND (msg_p).frame, 0,NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index); + nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message (ctxt.module_id, + NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index, + NR_RRC_MAC_BCCH_DATA_IND (msg_p).sdu, + NR_RRC_MAC_BCCH_DATA_IND (msg_p).sdu_size, + NR_RRC_MAC_BCCH_DATA_IND (msg_p).rsrq, + NR_RRC_MAC_BCCH_DATA_IND (msg_p).rsrp); + break; + + case NR_RRC_MAC_CCCH_DATA_IND: + LOG_D(NR_RRC, "[UE %d] RNTI %x Received %s: frameP %d, gNB %d\n", + ue_mod_id, + NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, + ITTI_MSG_NAME (msg_p), + NR_RRC_MAC_CCCH_DATA_IND (msg_p).frame, + NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); + srb_info_p = &NR_UE_rrc_inst[ue_mod_id].Srb0[NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index]; + memcpy (srb_info_p->Rx_buffer.Payload, NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu, + NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size); + srb_info_p->Rx_buffer.payload_size = NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size; + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, NR_RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0); + // PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, NR_RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0, NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); + nr_rrc_ue_decode_ccch (&ctxt, + srb_info_p, + NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); + break; + + /* PDCP messages */ + case NR_RRC_DCCH_DATA_IND: + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, NR_RRC_DCCH_DATA_IND (msg_p).module_id, GNB_FLAG_NO, NR_RRC_DCCH_DATA_IND (msg_p).rnti, NR_RRC_DCCH_DATA_IND (msg_p).frame, 0,NR_RRC_DCCH_DATA_IND (msg_p).gNB_index); + LOG_D(NR_RRC, "[UE %d] Received %s: frameP %d, DCCH %d, gNB %d\n", + NR_RRC_DCCH_DATA_IND (msg_p).module_id, + ITTI_MSG_NAME (msg_p), + NR_RRC_DCCH_DATA_IND (msg_p).frame, + NR_RRC_DCCH_DATA_IND (msg_p).dcch_index, + NR_RRC_DCCH_DATA_IND (msg_p).gNB_index); + LOG_D(NR_RRC, PROTOCOL_RRC_CTXT_UE_FMT"Received %s DCCH %d, gNB %d\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(&ctxt), + ITTI_MSG_NAME (msg_p), + NR_RRC_DCCH_DATA_IND (msg_p).dcch_index, + NR_RRC_DCCH_DATA_IND (msg_p).gNB_index); + nr_rrc_ue_decode_dcch ( + &ctxt, + NR_RRC_DCCH_DATA_IND (msg_p).dcch_index, + NR_RRC_DCCH_DATA_IND (msg_p).sdu_p, + NR_RRC_DCCH_DATA_IND (msg_p).gNB_index); + break; + + case NAS_KENB_REFRESH_REQ: + memcpy((void *)NR_UE_rrc_inst[ue_mod_id].kgnb, (void *)NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(NR_UE_rrc_inst[ue_mod_id].kgnb)); + LOG_D(RRC, "[UE %d] Received %s: refreshed RRC::KgNB = " + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x\n", + ue_mod_id, ITTI_MSG_NAME (msg_p), + NR_UE_rrc_inst[ue_mod_id].kgnb[0], NR_UE_rrc_inst[ue_mod_id].kgnb[1], NR_UE_rrc_inst[ue_mod_id].kgnb[2], NR_UE_rrc_inst[ue_mod_id].kgnb[3], + NR_UE_rrc_inst[ue_mod_id].kgnb[4], NR_UE_rrc_inst[ue_mod_id].kgnb[5], NR_UE_rrc_inst[ue_mod_id].kgnb[6], NR_UE_rrc_inst[ue_mod_id].kgnb[7], + NR_UE_rrc_inst[ue_mod_id].kgnb[8], NR_UE_rrc_inst[ue_mod_id].kgnb[9], NR_UE_rrc_inst[ue_mod_id].kgnb[10], NR_UE_rrc_inst[ue_mod_id].kgnb[11], + NR_UE_rrc_inst[ue_mod_id].kgnb[12], NR_UE_rrc_inst[ue_mod_id].kgnb[13], NR_UE_rrc_inst[ue_mod_id].kgnb[14], NR_UE_rrc_inst[ue_mod_id].kgnb[15], + NR_UE_rrc_inst[ue_mod_id].kgnb[16], NR_UE_rrc_inst[ue_mod_id].kgnb[17], NR_UE_rrc_inst[ue_mod_id].kgnb[18], NR_UE_rrc_inst[ue_mod_id].kgnb[19], + NR_UE_rrc_inst[ue_mod_id].kgnb[20], NR_UE_rrc_inst[ue_mod_id].kgnb[21], NR_UE_rrc_inst[ue_mod_id].kgnb[22], NR_UE_rrc_inst[ue_mod_id].kgnb[23], + NR_UE_rrc_inst[ue_mod_id].kgnb[24], NR_UE_rrc_inst[ue_mod_id].kgnb[25], NR_UE_rrc_inst[ue_mod_id].kgnb[26], NR_UE_rrc_inst[ue_mod_id].kgnb[27], + NR_UE_rrc_inst[ue_mod_id].kgnb[28], NR_UE_rrc_inst[ue_mod_id].kgnb[29], NR_UE_rrc_inst[ue_mod_id].kgnb[30], NR_UE_rrc_inst[ue_mod_id].kgnb[31]); + break; + + case NAS_UPLINK_DATA_REQ: { + uint32_t length; + uint8_t *buffer; + LOG_I(NR_RRC, "[UE %d] Received %s: UEid %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NAS_UPLINK_DATA_REQ (msg_p).UEid); + /* Create message for PDCP (ULInformationTransfer_t) */ + length = do_NR_ULInformationTransfer(&buffer, NAS_UPLINK_DATA_REQ (msg_p).nasMsg.length, NAS_UPLINK_DATA_REQ (msg_p).nasMsg.data); + /* Transfer data to PDCP */ + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_UE_rrc_inst[ue_mod_id].Info[0].rnti, 0, 0,0); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM,length); + memcpy (message_buffer, buffer, length); + + message_p = itti_alloc_new_message (TASK_RRC_NRUE, 0, UE_RRC_DCCH_DATA_IND); + if(NR_UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL) + UE_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + else + UE_RRC_DCCH_DATA_IND (message_p).rbid = DCCH1; + UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + UE_RRC_DCCH_DATA_IND (message_p).size = length; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt.instance, message_p); + +#else + // check if SRB2 is created, if yes request data_req on DCCH1 (SRB2) + if(NR_UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL) { + rrc_data_req_ue (&ctxt, + DCCH, + nr_rrc_mui++, + SDU_CONFIRM_NO, + length, buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + } else { + rrc_data_req_ue (&ctxt, + DCCH1, + nr_rrc_mui++, + SDU_CONFIRM_NO, + length, buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + } +#endif + break; + } + + default: + LOG_E(NR_RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); + break; + } + LOG_D(NR_RRC, "[UE %d] RRC Status %d\n", ue_mod_id, nr_rrc_get_state(ue_mod_id)); + result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + msg_p = NULL; + } +} +void nr_rrc_ue_process_sidelink_radioResourceConfig( + module_id_t Mod_idP, + uint8_t gNB_index, + NR_SetupRelease_SL_ConfigDedicatedNR_r16_t *sl_ConfigDedicatedNR +) +{ + //process sl_CommConfig, configure MAC/PHY for transmitting SL communication (RRC_CONNECTED) + if (sl_ConfigDedicatedNR != NULL) { + switch (sl_ConfigDedicatedNR->present){ + case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_setup: + //TODO + break; + case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_release: + break; + case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_NOTHING: + break; + default: + break; + } + } +} + +//----------------------------------------------------------------------------- +void +nr_rrc_ue_process_ueCapabilityEnquiry( + const protocol_ctxt_t *const ctxt_pP, + NR_UECapabilityEnquiry_t *UECapabilityEnquiry, + uint8_t gNB_index +) +//----------------------------------------------------------------------------- +{ + asn_enc_rval_t enc_rval; + NR_UL_DCCH_Message_t ul_dcch_msg; + NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container; + uint8_t buffer[200]; + int i; + LOG_I(NR_RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing UECapabilityEnquiry (gNB %d)\n", + ctxt_pP->module_id, + ctxt_pP->frame, + gNB_index); + memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); + memset((void *)&ue_CapabilityRAT_Container,0,sizeof(NR_UE_CapabilityRAT_Container_t)); + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + ul_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_DCCH_MessageType__c1)); + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation; + ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation = CALLOC(1, sizeof(struct NR_UECapabilityInformation)); + ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->rrc_TransactionIdentifier = UECapabilityEnquiry->rrc_TransactionIdentifier; + ue_CapabilityRAT_Container.rat_Type = NR_RAT_Type_nr; + NR_UE_NR_Capability_t* UE_Capability_nr; + UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t)); + NR_BandNR_t *nr_bandnr; + nr_bandnr = CALLOC(1,sizeof(NR_BandNR_t)); + nr_bandnr->bandNR = 1; + ASN_SEQUENCE_ADD( + &UE_Capability_nr->rf_Parameters.supportedBandListNR.list, + nr_bandnr); + OAI_NR_UECapability_t *UECap; + UECap = CALLOC(1,sizeof(OAI_NR_UECapability_t)); + UECap->UE_NR_Capability = UE_Capability_nr; + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout,&asn_DEF_NR_UE_NR_Capability,(void *)UE_Capability_nr); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability, + NULL, + (void *)UE_Capability_nr, + &UECap->sdu[0], + MAX_UE_NR_CAPABILITY_SIZE); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + UECap->sdu_size = (enc_rval.encoded + 7) / 8; + LOG_I(PHY, "[RRC]UE NR Capability encoded, %d bytes (%zd bits)\n", + UECap->sdu_size, enc_rval.encoded + 7); + + NR_UE_rrc_inst[ctxt_pP->module_id].UECap = UECap; + NR_UE_rrc_inst[ctxt_pP->module_id].UECapability = UECap->sdu; + NR_UE_rrc_inst[ctxt_pP->module_id].UECapability_size = UECap->sdu_size; + OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ue_CapabilityRAT_Container, + (const char *)NR_UE_rrc_inst[ctxt_pP->module_id].UECapability, + NR_UE_rrc_inst[ctxt_pP->module_id].UECapability_size); + // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf = UE_rrc_inst[ue_mod_idP].UECapability; + // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size; + AssertFatal(UECapabilityEnquiry->criticalExtensions.present == NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry, + "UECapabilityEnquiry->criticalExtensions.present (%d) != UECapabilityEnquiry__criticalExtensions_PR_c1 (%d)\n", + UECapabilityEnquiry->criticalExtensions.present,NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry); + + ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.present = NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation; + ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation = CALLOC(1, sizeof(struct NR_UECapabilityInformation_IEs)); + ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList = CALLOC(1, sizeof(struct NR_UE_CapabilityRAT_ContainerList)); + ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list.count = 0; + + for (i=0; icriticalExtensions.choice.ueCapabilityEnquiry->ue_CapabilityRAT_RequestList.list.count; i++) { + if (UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry->ue_CapabilityRAT_RequestList.list.array[i]->rat_Type + == NR_RAT_Type_nr) { + ASN_SEQUENCE_ADD( + &ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList->list, + &ue_CapabilityRAT_Container); + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *) &ul_dcch_msg, buffer, 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + + LOG_I(RRC,"UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM, + (enc_rval.encoded + 7) / 8); + memcpy (message_buffer, buffer, (enc_rval.encoded + 7) / 8); + + message_p = itti_alloc_new_message (TASK_RRC_NRUE, 0, UE_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = (enc_rval.encoded + 7) / 8; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); +#else + rrc_data_req_ue ( + ctxt_pP, + DCCH, + nr_rrc_mui++, + SDU_CONFIRM_NO, + (enc_rval.encoded + 7) / 8, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif + } + } +} + +//----------------------------------------------------------------------------- +void rrc_ue_generate_RRCReestablishmentRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ) +{ + NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size = + do_RRCReestablishmentRequest( + ctxt_pP->module_id, + (uint8_t *)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload, 1); + LOG_I(NR_RRC,"[UE %d] : Frame %d, Logical Channel UL-CCCH (SRB0), Generating RRCReestablishmentRequest (bytes %d, gNB %d)\n", + ctxt_pP->module_id, ctxt_pP->frame, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index); + + for (int i=0; imodule_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) { + LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload[i]); + } + + LOG_T(NR_RRC,"\n"); + +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM, + NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t*)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload, + NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_NRUE, 0, UE_RRC_CCCH_DATA_IND); + UE_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; + UE_RRC_CCCH_DATA_IND (message_p).size = NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); +#endif +} + +void +nr_rrc_ue_generate_rrcReestablishmentComplete( + const protocol_ctxt_t *const ctxt_pP, + NR_RRCReestablishment_t *rrcReestablishment, + uint8_t gNB_index +) +//----------------------------------------------------------------------------- +{ + uint32_t length; + uint8_t buffer[100]; + length = do_RRCReestablishmentComplete(buffer, rrcReestablishment->rrc_TransactionIdentifier); + LOG_I(NR_RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes%d, gNB %d)\n", + ctxt_pP->module_id,ctxt_pP->frame, length, gNB_index); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM,length); + memcpy (message_buffer, buffer, length); + + message_p = itti_alloc_new_message (TASK_RRC_NRUE, 0, UE_RRC_DCCH_DATA_IND); + UE_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + UE_RRC_DCCH_DATA_IND (message_p).size = length; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); + +#endif } diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 6481fb0cea..b79cbb4bae 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -39,7 +39,6 @@ #include "platform_types.h" -#include "NR_MAC_UE/mac.h" #include "NR_MAC_COMMON/nr_mac.h" #include "rrc_list.h" #include "NR_asn_constant.h" @@ -51,10 +50,18 @@ #include "NR_asn_constant.h" #include "NR_SchedulingRequestToAddMod.h" #include "NR_MIB.h" +#include "NR_SIB1.h" #include "NR_BCCH-BCH-Message.h" #include "NR_DL-DCCH-Message.h" +#include "../NR/nr_rrc_defs.h" #define NB_NR_UE_INST 1 +#define NB_CNX_UE 2//MAX_MANAGED_RG_PER_MOBILE +#define NB_SIG_CNX_UE 2 //MAX_MANAGED_RG_PER_MOBILE + +#define MAX_MEAS_OBJ 6 +#define MAX_MEAS_CONFIG 6 +#define MAX_MEAS_ID 6 typedef uint32_t channel_t; @@ -63,14 +70,96 @@ typedef enum { nr_RadioBearerConfigX_r15=1 } nsa_message_t; +#define MAX_UE_NR_CAPABILITY_SIZE 255 +typedef struct OAI_NR_UECapability_s { + uint8_t sdu[MAX_UE_NR_CAPABILITY_SIZE]; + uint8_t sdu_size; + NR_UE_NR_Capability_t *UE_NR_Capability; +} OAI_NR_UECapability_t; + +typedef enum requested_SI_List_e { + SIB2 = 1, + SIB3 = 2, + SIB4 = 4, + SIB5 = 8, + SIB6 = 16, + SIB7 = 32, + SIB8 = 64, + SIB9 = 128 +} requested_SI_List_t; + +// 3GPP TS 38.300 Section 9.2.6 +typedef enum RA_trigger_e { + RA_NOT_RUNNING, + INITIAL_ACCESS_FROM_RRC_IDLE, + RRC_CONNECTION_REESTABLISHMENT, + DURING_HANDOVER, + NON_SYNCHRONISED, + TRANSITION_FROM_RRC_INACTIVE, + TO_ESTABLISH_TA, + REQUEST_FOR_OTHER_SI, + BEAM_FAILURE_RECOVERY, +} RA_trigger_t; + typedef struct NR_UE_RRC_INST_s { NR_MeasConfig_t *meas_config; NR_CellGroupConfig_t *cell_group_config; + NR_ServingCellConfigCommonSIB_t *servingCellConfigCommonSIB; + NR_CellGroupConfig_t *scell_group_config; NR_RadioBearerConfig_t *radio_bearer_config; - + + NR_MeasObjectToAddMod_t *MeasObj[NB_CNX_UE][MAX_MEAS_OBJ]; + NR_ReportConfigToAddMod_t *ReportConfig[NB_CNX_UE][MAX_MEAS_CONFIG]; + NR_QuantityConfig_t *QuantityConfig[NB_CNX_UE]; + NR_MeasIdToAddMod_t *MeasId[NB_CNX_UE][MAX_MEAS_ID]; + NR_MeasGapConfig_t *measGapConfig[NB_CNX_UE]; + NR_RSRP_Range_t s_measure; + NR_SRB_ToAddMod_t *SRB1_config[NB_CNX_UE]; + NR_SRB_ToAddMod_t *SRB2_config[NB_CNX_UE]; + NR_DRB_ToAddMod_t *DRB_config[NB_CNX_UE][8]; + rb_id_t *defaultDRB; // remember the ID of the default DRB + + NR_SRB_INFO Srb0[NB_SIG_CNX_UE]; + NR_SRB_INFO_TABLE_ENTRY Srb1[NB_CNX_UE]; + NR_SRB_INFO_TABLE_ENTRY Srb2[NB_CNX_UE]; + + uint8_t MBMS_flag; + OAI_NR_UECapability_t *UECap; + uint8_t *UECapability; + uint8_t UECapability_size; + + RA_trigger_t ra_trigger; + BIT_STRING_t requested_SI_List; + + NR_SystemInformation_t *si[NB_CNX_UE]; + NR_SIB1_t *sib1[NB_CNX_UE]; + NR_SIB2_t *sib2[NB_CNX_UE]; + NR_SIB3_t *sib3[NB_CNX_UE]; + NR_SIB4_t *sib4[NB_CNX_UE]; + NR_SIB5_t *sib5[NB_CNX_UE]; + NR_SIB6_t *sib6[NB_CNX_UE]; + NR_SIB7_t *sib7[NB_CNX_UE]; + NR_SIB8_t *sib8[NB_CNX_UE]; + NR_SIB9_t *sib9[NB_CNX_UE]; + NR_SIB10_r16_t *sib10[NB_CNX_UE]; + NR_SIB11_r16_t *sib11[NB_CNX_UE]; + NR_SIB12_r16_t *sib12[NB_CNX_UE]; + NR_SIB13_r16_t *sib13[NB_CNX_UE]; + NR_SIB14_r16_t *sib14[NB_CNX_UE]; + plmn_t plmnID; + + NR_UE_RRC_INFO Info[NB_SIG_CNX_UE]; + NR_MIB_t *mib; - + + /* KeNB as computed from parameters within USIM card */ + uint8_t kgnb[32]; + /* Used integrity/ciphering algorithms */ + //RRC_LIST_TYPE(NR_SecurityAlgorithmConfig_t, NR_SecurityAlgorithmConfig) SecurityAlgorithmConfig_list; + NR_CipheringAlgorithm_t cipheringAlgorithm; + e_NR_IntegrityProtAlgorithm integrityProtAlgorithm; + // lists // CellGroupConfig.rlc-BearerToAddModList RRC_LIST_TYPE(NR_RLC_BearerConfig_t, NR_maxLC_ID) RLC_Bearer_Config_list; @@ -118,7 +207,11 @@ typedef struct NR_UE_RRC_INST_s { RRC_LIST_TYPE(NR_CSI_ResourceConfig_t, NR_maxNrofCSI_ResourceConfigurations) CSI_ResourceConfig_list; // CellGroupConfig.spCellConfig.spCellConfigDedicated RRC_LIST_TYPE(NR_CSI_ReportConfig_t, NR_maxNrofCSI_ReportConfigurations) CSI_ReportConfig_list; - + + long selected_plmn_identity; + Rrc_State_NR_t nrRrcState; + Rrc_Sub_State_NR_t nrRrcSubState; + as_nas_info_t initialNasMsg; } NR_UE_RRC_INST_t; #endif diff --git a/openair2/RRC/NR_UE/rrc_list.h b/openair2/RRC/NR_UE/rrc_list.h index 32a452e4a2..20a0adad56 100644 --- a/openair2/RRC/NR_UE/rrc_list.h +++ b/openair2/RRC/NR_UE/rrc_list.h @@ -111,4 +111,4 @@ #define RRC_LIST_ENTRY(list, i) \ list.entries[i] -#endif \ No newline at end of file +#endif diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 7bc7e4b90c..534da0112b 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -59,12 +59,12 @@ NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char*); \param size length of buffer*/ //TODO check to use which one //int8_t nr_rrc_ue_decode_rrcReconfiguration(const uint8_t *buffer, const uint32_t size); -int8_t nr_rrc_ue_decode_secondary_cellgroup_config(const uint8_t *buffer, const uint32_t size); +int8_t nr_rrc_ue_decode_secondary_cellgroup_config(const module_id_t module_id, const uint8_t *buffer, const uint32_t size); /**\brief Process NR RRC connection reconfiguration via SRB3 \param rrcReconfiguration decoded rrc connection reconfiguration*/ -int8_t nr_rrc_ue_process_rrcReconfiguration(NR_RRCReconfiguration_t *rrcReconfiguration); +int8_t nr_rrc_ue_process_rrcReconfiguration(const module_id_t module_id, NR_RRCReconfiguration_t *rrcReconfiguration); /**\prief Process measurement config from NR RRC connection reconfiguration message \param meas_config measurement configuration*/ @@ -73,7 +73,7 @@ int8_t nr_rrc_ue_process_meas_config(NR_MeasConfig_t *meas_config); /**\prief Process secondary cell group config from NR RRC connection reconfiguration message or EN-DC primitives \param cell_group_config secondary cell group configuration*/ //TODO check EN-DC function call flow. -int8_t nr_rrc_ue_process_scg_config(NR_CellGroupConfig_t *cell_group_config); +int8_t nr_rrc_ue_process_scg_config(const module_id_t module_id, NR_CellGroupConfig_t *cell_group_config); /**\prief Process radio bearer config from NR RRC connection reconfiguration message \param radio_bearer_config radio bearer configuration*/ @@ -86,6 +86,15 @@ int8_t nr_rrc_ue_process_radio_bearer_config(NR_RadioBearerConfig_t *radio_beare \param sdu_len length of buffer*/ int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message(const module_id_t module_id, const uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len); +/**\brief decode NR BCCH-DLSCH (SI) messages + \param module_idP module id + \param gNB_index gNB index + \param sduP pointer to buffer of ASN message BCCH-DLSCH + \param sdu_len length of buffer + \param rsrq RSRQ + \param rsrp RSRP*/ +int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(const module_id_t module_id, const uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len, const uint8_t rsrq, const uint8_t rsrp); + /**\brief Decode NR DCCH from gNB, sent from lower layer through SRB3 \param module_id module id \param gNB_index gNB index @@ -100,19 +109,38 @@ int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message(const module_id_t module_id, const ui \param channel indicator for channel of the pdu \param pduP pointer to pdu \param pdu_len data length of pdu*/ -int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const channel_t channel, const uint8_t* pduP, const sdu_size_t pdu_len); +int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, + const int CC_id, + const uint8_t gNB_index, + const frame_t frame, + const sub_frame_t sub_frame, + const rnti_t rnti, + const channel_t channel, + const uint8_t* pduP, + const sdu_size_t pdu_len); /**\brief \param module_id module id \param CC_id component carrier id + \param gNB_index gNB index \param frame_t frameP \param rb_id_t SRB id \param buffer_pP pointer to buffer*/ -int8_t mac_rrc_nr_data_req_ue(const module_id_t Mod_idP, +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, const int CC_id, + const uint8_t gNB_id, const frame_t frameP, const rb_id_t Srb_id, - uint8_t *const buffer_pP); + uint8_t *buffer_pP); + +/**\brief RRC UE task. + \param void *args_p Pointer on arguments to start the task. */ +void *rrc_nrue_task(void *args_p); + +/**\brief RRC UE generate RRCSetupRequest message. + \param module_id module id + \param gNB_index gNB index */ +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index); /** @}*/ #endif diff --git a/openair2/RRC/NR_UE/rrc_vars.h b/openair2/RRC/NR_UE/rrc_vars.h index 5c74e5b5a8..30c74debdd 100644 --- a/openair2/RRC/NR_UE/rrc_vars.h +++ b/openair2/RRC/NR_UE/rrc_vars.h @@ -36,6 +36,6 @@ #include "rrc_defs.h" -NR_UE_RRC_INST_t *NR_UE_rrc_inst; +extern NR_UE_RRC_INST_t *NR_UE_rrc_inst; #endif diff --git a/openair2/SDAP/nr_sdap/nr_sdap_gnb.c b/openair2/SDAP/nr_sdap/nr_sdap_gnb.c new file mode 100644 index 0000000000..5f0a2640e9 --- /dev/null +++ b/openair2/SDAP/nr_sdap/nr_sdap_gnb.c @@ -0,0 +1,87 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_sdap_gnb.h" +#include + +boolean_t sdap_gnb_data_req(protocol_ctxt_t *ctxt_p, + const srb_flag_t srb_flag, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t pt_mode, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id + ) { + if(sdu_buffer == NULL) { + LOG_E(PDCP, "%s:%d:%s: SDAP Layer gNB - NULL sdu_buffer \n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if(sdu_buffer_size == 0) { + LOG_E(PDCP, "%s:%d:%s: SDAP Layer gNB - NULL or 0 sdu_buffer_size \n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + uint8_t *sdap_buf = (uint8_t *)malloc(sdu_buffer_size+SDAP_HDR_LENGTH); + nr_sdap_dl_hdr_t sdap_hdr; + sdap_hdr.RDI = 0; // SDAP_Hardcoded - + sdap_hdr.RQI = 0; // SDAP_Hardcoded - Should get this info from DL_PDU_SESSION_INFORMATION + sdap_hdr.QFI = 1; // SDAP_Hardcoded - Should get this info from DL_PDU_SESSION_INFORMATION + memcpy(&sdap_buf[0], &sdap_hdr, 1); + memcpy(&sdap_buf[1], sdu_buffer, sdu_buffer_size); + rb_id_t sdap_drb_id = rb_id; // SDAP_Hardcoded - Should get this info from QFI to DRB mapping table + boolean_t ret = pdcp_data_req(ctxt_p, + srb_flag, + sdap_drb_id, + mui, + confirm, + sdu_buffer_size+1, + sdap_buf, + pt_mode, + sourceL2Id, + destinationL2Id); + + if(!ret) { + LOG_E(PDCP, "%s:%d:%s: SDAP Layer gNB - PDCP DL refused PDU\n", __FILE__, __LINE__, __FUNCTION__); + free(sdap_buf); + return 0; + } + + free(sdap_buf); + return 1; +} + +void sdap_gnb_ul_header_handler(char sdap_gnb_ul_hdr) { + nr_sdap_ul_hdr_t *sdap_hdr_ul = (nr_sdap_ul_hdr_t *)&sdap_gnb_ul_hdr; + + switch (sdap_hdr_ul->DC) { + case SDAP_HDR_UL_DATA_PDU: + LOG_I(PDCP, "%s:%d:%s: SDAP Layer gNB - UL Received SDAP Data PDU\n", __FILE__, __LINE__, __FUNCTION__); + break; + + case SDAP_HDR_UL_CTRL_PDU: + LOG_I(PDCP, "%s:%d:%s: SDAP Layer gNB - Received SDAP Control PDU\n", __FILE__, __LINE__, __FUNCTION__); + break; + } +} \ No newline at end of file diff --git a/openair2/SDAP/nr_sdap/nr_sdap_gnb.h b/openair2/SDAP/nr_sdap/nr_sdap_gnb.h new file mode 100644 index 0000000000..243aa89010 --- /dev/null +++ b/openair2/SDAP/nr_sdap/nr_sdap_gnb.h @@ -0,0 +1,61 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_SDAP_GNB_ +#define _NR_SDAP_GNB_ + +#include "openair2/COMMON/platform_types.h" +#include "common/utils/LOG/log.h" + +#define SDAP_BITMASK_DC (0x80) +#define SDAP_BITMASK_R (0x40) +#define SDAP_BITMASK_QFI (0x3F) +#define SDAP_HDR_UL_DATA_PDU (1) +#define SDAP_HDR_UL_CTRL_PDU (0) +#define SDAP_HDR_LENGTH (1) + +typedef struct nr_sdap_dl_hdr_s { + uint8_t QFI:6; + uint8_t RQI:1; + uint8_t RDI:1; +} __attribute__((packed)) nr_sdap_dl_hdr_t; + +typedef struct nr_sdap_ul_hdr_s { + uint8_t QFI:6; + uint8_t R:1; + uint8_t DC:1; +} __attribute__((packed)) nr_sdap_ul_hdr_t; + +boolean_t sdap_gnb_data_req(protocol_ctxt_t *ctxt_p, + const srb_flag_t srb_flag, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t pt_mode, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id + ); + +void sdap_gnb_ul_header_handler(char sdap_gnb_ul_hdr); + +#endif \ No newline at end of file diff --git a/common/utils/itti_analyzer/libui/ui_notebook.h b/openair2/SDAP/nr_sdap/sdap_gNB.c similarity index 79% rename from common/utils/itti_analyzer/libui/ui_notebook.h rename to openair2/SDAP/nr_sdap/sdap_gNB.c index 6f87856e84..ad84e4c273 100644 --- a/common/utils/itti_analyzer/libui/ui_notebook.h +++ b/openair2/SDAP/nr_sdap/sdap_gNB.c @@ -19,13 +19,12 @@ * contact@openairinterface.org */ -#ifndef UI_NOTEBOOK_H_ -#define UI_NOTEBOOK_H_ +/*! \file sdap_gNB.c + * \brief sdap tasks for gNB + * \author Konstantinos Alexandris , Cedric Roux , Navid Nikaein + * \date 2018 + * \version 1.0 + */ +#define SDAP_GNB +#define SDAP_GNB_C -void ui_notebook_terminal_clear(void); - -int ui_notebook_create(GtkWidget *vbox); - -void ui_notebook_terminal_append_data(gchar *text, gint length); - -#endif /* UI_NOTEBOOK_H_ */ diff --git a/openair2/SIMULATION/NR_RRC/itti_sim.c b/openair2/SIMULATION/NR_RRC/itti_sim.c new file mode 100644 index 0000000000..67a03d8b06 --- /dev/null +++ b/openair2/SIMULATION/NR_RRC/itti_sim.c @@ -0,0 +1,669 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file itti_sim.c + * \brief simulator for itti message from node to UE + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + + +#include + + +#include "T.h" + +#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all +#include + +#include "msc.h" + +#include "common/ran_context.h" + +#include "common/config/config_userapi.h" +#include "common/utils/load_module_shlib.h" +#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "PHY/phy_vars.h" +#include "SCHED/sched_common_vars.h" +#include "LAYER2/MAC/mac_vars.h" +#include "RRC/LTE/rrc_vars.h" +#include "gnb_config.h" +#include "SIMULATION/TOOLS/sim.h" + +#ifdef SMBV +#include "PHY/TOOLS/smbv.h" +unsigned short config_frames[4] = {2,9,11,13}; +#endif + +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" +#include "UTIL/OPT/opt.h" + +#include "intertask_interface.h" + + +#include "system.h" +#include +#include "PHY/TOOLS/phy_scope_interface.h" +#include "PHY/TOOLS/nr_phy_scope.h" +#include "stats.h" +#include "nr-softmodem.h" +#include "executables/softmodem-common.h" +#include "executables/thread-common.h" +#include "NB_IoT_interface.h" +#include "x2ap_eNB.h" +#include "ngap_gNB.h" +#include "RRC/NR_UE/rrc_proto.h" +#include "RRC/NR_UE/rrc_vars.h" +#include "openair3/NAS/UE/nas_ue_task.h" +#include +#include +#if ITTI_SIM +#include "nr_nas_msg_sim.h" +#endif + +pthread_cond_t nfapi_sync_cond; +pthread_mutex_t nfapi_sync_mutex; +int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex + +uint32_t timing_advance = 0; +uint64_t num_missed_slots=0; + +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} + +nrUE_params_t nrUE_params; +nrUE_params_t *get_nrUE_params(void) { + return &nrUE_params; +} + +void processSlotTX(void *arg) {} + +THREAD_STRUCT thread_struct; +pthread_cond_t sync_cond; +pthread_mutex_t sync_mutex; +int sync_var=-1; //!< protected by mutex \ref sync_mutex. +int config_sync_var=-1; + +openair0_config_t openair0_cfg[MAX_CARDS]; + +//volatile int start_gNB = 0; +volatile int oai_exit = 0; + +//static int wait_for_sync = 0; + +unsigned int mmapped_dma=0; +int single_thread_flag=1; + +int8_t threequarter_fs=0; + +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + +//Temp fix for inexistent NR upper layer +unsigned char NB_gNB_INST = 1; + + +int UE_scan = 1; +int UE_scan_carrier = 0; +runmode_t mode = normal_txrx; +static double snr_dB=20; + +FILE *input_fd=NULL; + +int chain_offset=0; + + +uint8_t dci_Format = 0; +uint8_t agregation_Level =0xFF; + +uint8_t nb_antenna_tx = 1; +uint8_t nb_antenna_rx = 1; + +char ref[128] = "internal"; +char channels[128] = "0"; + +int otg_enabled; + +extern void *udp_eNB_task(void *args_p); + +int transmission_mode=1; +int emulate_rf = 0; +int numerology = 0; + + +double cpuf; + +extern char uecap_xer[1024]; +char uecap_xer_in=0; + +/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed + * this is very hackish - find a proper solution + */ +uint8_t abstraction_flag=0; + +/* forward declarations */ +void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); + +/*---------------------BMC: timespec helpers -----------------------------*/ + +struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; +struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + +struct timespec clock_difftime(struct timespec start, struct timespec end) { + struct timespec temp; + + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + + return temp; +} + + + +#define KNRM "\x1B[0m" +#define KRED "\x1B[31m" +#define KGRN "\x1B[32m" +#define KBLU "\x1B[34m" +#define RESET "\033[0m" + + +void exit_function(const char *file, const char *function, const int line, const char *s) { + int ru_id; + + if (s != NULL) { + printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); + } + + oai_exit = 1; + + if (RC.ru == NULL) + exit(-1); // likely init not completed, prevent crash or hang, exit now... + + for (ru_id=0; ru_idrfdevice.trx_end_func) { + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + } + + if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) { + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + } + } + + sleep(1); //allow lte-softmodem threads to exit first + exit(1); +} + +void wait_gNBs(void) { + int i; + int waiting=1; + + while (waiting==1) { + printf("Waiting for gNB L1 instances to all get configured ... sleeping 50ms (nb_nr_sL1_inst %d)\n",RC.nb_nr_L1_inst); + usleep(50*1000); + waiting=0; + + for (i=0; iconfigured==0) { + waiting=1; + break; + } + } + } + + printf("gNB L1 are configured\n"); +} + +void wait_RUs(void) { + LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask); + // wait for all RUs to be configured over fronthaul + pthread_mutex_lock(&RC.ru_mutex); + + while (RC.ru_mask>0) { + pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex); + printf("RC.ru_mask:%02lx\n", RC.ru_mask); + } + + pthread_mutex_unlock(&RC.ru_mutex); + LOG_I(PHY,"RUs configured\n"); +} + + +int stop_L1L2(module_id_t gnb_id) { + return 0; +} + +int restart_L1L2(module_id_t gnb_id) { + return 0; +} + +int create_gNB_tasks(uint32_t gnb_nb) { + LOG_D(GNB_APP, "%s(gnb_nb:%d)\n", __FUNCTION__, gnb_nb); + itti_wait_ready(1); + + + if (gnb_nb > 0) { + if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0){ + LOG_E(SCTP, "Create task for SCTP failed\n"); + return -1; + } + if (is_x2ap_enabled()) { + if(itti_create_task(TASK_X2AP, x2ap_task, NULL) < 0){ + LOG_E(X2AP, "Create task for X2AP failed\n"); + } + } + else { + LOG_I(X2AP, "X2AP is disabled.\n"); + } + } + + if (AMF_MODE_ENABLED && (get_softmodem_params()->phy_test==0 && get_softmodem_params()->do_ra==0 && get_softmodem_params()->sa==0)) { + if (gnb_nb > 0) { + if (itti_create_task (TASK_NGAP, ngap_gNB_task, NULL) < 0) { + LOG_E(S1AP, "Create task for NGAP failed\n"); + return -1; + } + + + if(!emulate_rf){ + if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) { + LOG_E(UDP_, "Create task for UDP failed\n"); + return -1; + } + } + + if (itti_create_task (TASK_GTPV1_U, &nr_gtpv1u_gNB_task, NULL) < 0) { + LOG_E(GTPU, "Create task for GTPV1U failed\n"); + return -1; + } + } + } + + + if (gnb_nb > 0) { + if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { + LOG_E(GNB_APP, "Create task for gNB APP failed\n"); + return -1; + } + LOG_I(NR_RRC,"Creating NR RRC gNB Task\n"); + + if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) { + LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n"); + return -1; + } + } + + return 0; +} + + +static void get_options(void) { + + + paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ; + + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + get_common_options(SOFTMODEM_GNB_BIT ); + config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); + + + + + if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) { + memset((void *)&RC,0,sizeof(RC)); + /* Read RC configuration file */ + NRRCConfig(); + NB_gNB_INST = RC.nb_nr_inst; + NB_RU = RC.nb_RU; + printf("Configuration: nb_rrc_inst %d, nb_nr_L1_inst %d, nb_ru %hhu\n",NB_gNB_INST,RC.nb_nr_L1_inst,NB_RU); + } + +} + + +void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], + NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) +{ + for (int CC_id=0; CC_idssb_config.scs_common.value = 1; + config[CC_id]->cell_config.frame_duplex_type.value = 1; //FDD + config[CC_id]->carrier_config.dl_grid_size[1].value = 106; + config[CC_id]->carrier_config.ul_grid_size[1].value = 106; + config[CC_id]->cell_config.phy_cell_id.value = 0; + } +} + +/* + * helper function to terminate a certain ITTI task + */ +void terminate_task(task_id_t task_id, module_id_t mod_id) { + LOG_I(GNB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id); + MessageDef *msg; + msg = itti_alloc_new_message (ENB_APP, 0, TERMINATE_MESSAGE); + itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); +} + +//extern void free_transport(PHY_VARS_gNB *); +extern void nr_phy_free_RU(RU_t *); + +void init_pdcp(void) { + //if (!NODE_IS_DU(RC.rrc[0]->node_type)) { + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + + if (IS_SOFTMODEM_NOS1) { + printf("IS_SOFTMODEM_NOS1 option enabled \n"); + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; + } + + pdcp_module_init(pdcp_initmask); + + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); +} + + +int create_tasks_nrue(uint32_t ue_nb) { + LOG_D(ENB_APP, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb); + itti_wait_ready(1); + + if (ue_nb > 0) { + printf("create TASK_RRC_NRUE\n"); + if (itti_create_task (TASK_RRC_NRUE, rrc_nrue_task, NULL) < 0) { + LOG_E(NR_RRC, "Create task for RRC UE failed\n"); + return -1; + } + + LOG_D(NR_RRC,"create TASK_NAS_NRUE\n"); + if (itti_create_task (TASK_NAS_NRUE, nas_nrue_task, NULL) < 0) { + LOG_E(NR_RRC, "Create task for NAS UE failed\n"); + return -1; + } + } + + + itti_wait_ready(0); + return 0; +} + + +void *itti_sim_ue_rrc_task( void *args_p) { + MessageDef *msg_p, *message_p; + instance_t instance; + unsigned int ue_mod_id; + int result; + itti_mark_task_ready (TASK_RRC_UE_SIM); + + while(1) { + // Wait for a message + itti_receive_msg (TASK_RRC_UE_SIM, &msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); + ue_mod_id = UE_INSTANCE_TO_MODULE_ID(instance); + + switch (ITTI_MSG_ID(msg_p)) { + case TERMINATE_MESSAGE: + LOG_W(NR_RRC, " *** Exiting RRC thread\n"); + itti_exit_task (); + break; + + case MESSAGE_TEST: + LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); + break; + case GNB_RRC_BCCH_DATA_IND: + message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, NR_RRC_MAC_BCCH_DATA_IND); + memset (NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE); + NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = GNB_RRC_BCCH_DATA_IND(msg_p).size; + memcpy (NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, GNB_RRC_BCCH_DATA_IND(msg_p).sdu, GNB_RRC_BCCH_DATA_IND(msg_p).size); + itti_send_msg_to_task (TASK_RRC_NRUE, instance, message_p); + break; + case GNB_RRC_CCCH_DATA_IND: + message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, NR_RRC_MAC_CCCH_DATA_IND); + printf("receive GNB_RRC_CCCH_DATA_IND\n"); + memset (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); + memcpy (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, GNB_RRC_CCCH_DATA_IND(msg_p).sdu, GNB_RRC_CCCH_DATA_IND(msg_p).size); + NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu_size = GNB_RRC_CCCH_DATA_IND(msg_p).size; + itti_send_msg_to_task (TASK_RRC_NRUE, instance, message_p); + break; + case GNB_RRC_DCCH_DATA_IND: + printf("receive GNB_RRC_DCCH_DATA_IND\n"); + message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, NR_RRC_DCCH_DATA_IND); + NR_RRC_DCCH_DATA_IND (message_p).dcch_index = GNB_RRC_DCCH_DATA_IND(msg_p).rbid; + NR_RRC_DCCH_DATA_IND (message_p).sdu_size = GNB_RRC_DCCH_DATA_IND(msg_p).size; + NR_RRC_DCCH_DATA_IND (message_p).sdu_p = GNB_RRC_DCCH_DATA_IND(msg_p).sdu; + itti_send_msg_to_task (TASK_RRC_NRUE, instance, message_p); + break; + default: + LOG_E(NR_RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); + break; + } + + result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + msg_p = NULL; + } +} + + +void *itti_sim_gnb_rrc_task( void *args_p) { + MessageDef *msg_p, *message_p; + instance_t instance; + unsigned int ue_mod_id; + int result; + itti_mark_task_ready (TASK_RRC_GNB_SIM); + + while(1) { + // Wait for a message + itti_receive_msg (TASK_RRC_GNB_SIM, &msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); + ue_mod_id = UE_INSTANCE_TO_MODULE_ID(instance); + + switch (ITTI_MSG_ID(msg_p)) { + case TERMINATE_MESSAGE: + LOG_W(NR_RRC, " *** Exiting RRC thread\n"); + itti_exit_task (); + break; + + case MESSAGE_TEST: + LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); + break; + case UE_RRC_CCCH_DATA_IND: + message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, 0, NR_RRC_MAC_CCCH_DATA_IND); + NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu_size = UE_RRC_CCCH_DATA_IND(msg_p).size; + memset (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); + memcpy (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, UE_RRC_CCCH_DATA_IND(msg_p).sdu, UE_RRC_CCCH_DATA_IND(msg_p).size); + itti_send_msg_to_task (TASK_RRC_GNB, instance, message_p); + break; + case UE_RRC_DCCH_DATA_IND: + message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, 0, NR_RRC_DCCH_DATA_IND); + NR_RRC_DCCH_DATA_IND (message_p).sdu_size = UE_RRC_DCCH_DATA_IND(msg_p).size; + NR_RRC_DCCH_DATA_IND (message_p).dcch_index = UE_RRC_DCCH_DATA_IND(msg_p).rbid; + NR_RRC_DCCH_DATA_IND (message_p).sdu_p = UE_RRC_DCCH_DATA_IND(msg_p).sdu; + itti_send_msg_to_task (TASK_RRC_GNB, instance, message_p); + break; + + default: + LOG_E(NR_RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); + break; + } + + result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + msg_p = NULL; + } +} + + +int main( int argc, char **argv ) +{ + start_background_system(); + + ///static configuration for NR at the moment + if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + set_softmodem_sighandler(); +#ifdef DEBUG_CONSOLE + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); +#endif + + logInit(); + //configure_linux(); + printf("Reading in command-line options\n"); + get_options (); + + if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) { + fprintf(stderr,"Getting configuration failed\n"); + exit(-1); + } + + AMF_MODE_ENABLED = !IS_SOFTMODEM_NOS1; +// AMF_MODE_ENABLED = 0; + NGAP_CONF_MODE = !IS_SOFTMODEM_NOS1; //!get_softmodem_params()->phy_test; + +#if T_TRACER + T_Config_Init(); +#endif + //randominit (0); + set_taus_seed (0); + printf("configuring for RAU/RRU\n"); + + if (opp_enabled ==1) { + reset_opp_meas(); + } + + cpuf=get_cpu_freq_GHz(); + itti_init(TASK_MAX, tasks_info); + // initialize mscgen log after ITTI + MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX); + + + init_opt(); + + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + + if(IS_SOFTMODEM_NOS1) + init_pdcp(); + + if (RC.nb_nr_inst > 0) { + nr_read_config_and_init(); + // don't create if node doesn't connect to RRC/S1/GTP + AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n"); + for (int gnb_id = 0; gnb_id < RC.nb_nr_inst; gnb_id++) { + MessageDef *msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, NRRRC_CONFIGURATION_REQ); + NRRRC_CONFIGURATION_REQ(msg_p) = RC.nrrrc[gnb_id]->configuration; + itti_send_msg_to_task (TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p); + } + } else { + printf("No ITTI, Initializing L1\n"); + return 0; + } + + if(itti_create_task (TASK_RRC_GNB_SIM, itti_sim_gnb_rrc_task, NULL) < 0){ + printf("cannot create ITTI tasks\n"); + exit(-1); // need a softer mode + } + + openair_rrc_top_init_ue_nr("./"); + + if (create_tasks_nrue(1) < 0) { + printf("cannot create ITTI tasks\n"); + exit(-1); // need a softer mode + } + + if(itti_create_task (TASK_RRC_UE_SIM, itti_sim_ue_rrc_task, NULL) < 0){ + printf("cannot create ITTI tasks\n"); + exit(-1); // need a softer mode + } + + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + + printf("Sending sync to all threads\n"); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + // wait for end of program + printf("TYPE TO TERMINATE\n"); + + usleep(100000); + protocol_ctxt_t ctxt; + struct rrc_gNB_ue_context_s *ue_context_p = NULL; + + + ue_context_p = rrc_gNB_allocate_new_UE_context(RC.nrrrc[0]); + + if(ue_context_p == NULL){ + printf("ue_context_p == NULL"); + } + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + 0, + ENB_FLAG_YES, + 0, + 0, + 0); + NR_UE_rrc_inst[ctxt.module_id].Info[0].State = RRC_SI_RECEIVED; + + nr_rrc_ue_generate_RRCSetupRequest(ctxt.module_id, 0); + + printf("Entering ITTI signals handler\n"); + itti_wait_tasks_end(); + printf("Returned from ITTI signal handler\n"); + oai_exit=1; + printf("oai_exit=%d\n",oai_exit); + + printf("stopping MODEM threads\n"); + + + /* release memory used by the RU/gNB threads (incomplete), after all + * threads have been stopped (they partially use the same memory) */ + + pthread_cond_destroy(&sync_cond); + pthread_mutex_destroy(&sync_mutex); + + logClean(); + printf("Bye.\n"); + return 0; +} + + + diff --git a/openair2/UTIL/OCG/OCG.h b/openair2/UTIL/OCG/OCG.h index 34190f7d15..58cc7184e7 100644 --- a/openair2/UTIL/OCG/OCG.h +++ b/openair2/UTIL/OCG/OCG.h @@ -667,7 +667,6 @@ typedef struct { unsigned char omv_enabled; // openair mobility visulizer unsigned char opp_enabled; // openair performance profiler unsigned char oeh_enabled; // openair event handler, with CLI this could provide a remote event management - char *itti_dump_file; unsigned char vcd_enabled; char *vcd_file; unsigned char eMBMS_active_state; @@ -717,12 +716,6 @@ typedef struct { */ unsigned char slot_isr; int slot_sfd; - rnti_t eNB_ue_module_id_to_rnti[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX];/*!< \brief used by eNB, this array can be filled: - by local virtualization: set directly by UE, or by remote UEs: TODO add signalisation on ethernet emulation link from UE to eNB*/ - - module_id_t eNB_ue_local_uid_to_ue_module_id[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX];/*!< \brief used by eNB, this array can be filled: - by local virtualization: set directly by UE, or by remote UEs: TODO add signalisation on ethernet emulation link from UE to eNB*/ - } Info; /* @}*/ diff --git a/openair2/UTIL/OMG/makefile_old b/openair2/UTIL/OMG/makefile_old deleted file mode 100644 index 7bc551cb03..0000000000 --- a/openair2/UTIL/OMG/makefile_old +++ /dev/null @@ -1,123 +0,0 @@ -include $(OPENAIR_TARGETS)/Makefile.common -ifdef TEST_OMG - -CC= gcc - -OBJstatic = OMG.c common.c static.c -OBJrwp = OMG.c common.c job.c rwp.c -OBJrwalk = OMG.c common.c job.c rwalk.c -OBJtrace = OMG.c common.c job.c trace.c mobility_parser.c hashtable.c -OBJsumo = OMG.c common.c sumo.c client_traci_OMG.c socket_traci_OMG.c storage_traci_OMG.c id_manager.c - -OBJ = OMG.c common.c static.c job.c rwp.c rwalk.c trace.c sumo.c mobility_parser.c hashtable.c client_traci_OMG.c socket_traci_OMG.c storage_traci_OMG.c id_manager.c - -CFLAGS += -m32 -DTEST_OMG - -.PHONY: help staticOMG rwpOMG clean - -help: - @echo ' "make staticOMG" to compile the STATIC version' - @echo ' "make rwpOMG" to compile the RWP version' - @echo ' "make rwalkOMG" to compile the RWALK version' - @echo ' "make traceOMG" to compile the TRACE version' - @echo ' "make sumoOMG" to compile the SUMO version' - @echo ' "make clean" to remove the generated files and restore the original distribution' - @echo ' "make OMG" to compile the complete version' - - -staticOMG: ${OBJstatic} - ${CC} ${OBJstatic} -o staticOMG $(CFLAGS) - - -rwpOMG: ${OBJrwp} - ${CC} ${OBJrwp} -lm -o rwpOMG $(CFLAGS) - @#-lm: used to link to math lib - -traceOMG:${OBJtrace} - ${CC} ${OBJtrace} -lm -o traceOMG $(CFLAGS) - -rwalkOMG: ${OBJrwalk} - ${CC} ${OBJrwalk} -lm -o rwalkOMG $(CFLAGS) - -sumoOMG: ${OBJsumo} - ${CC} ${OBJsumo} -lm -o rwalkOMG $(CFLAGS) - -OMG: ${OBJ} - ${CC} ${OBJ} -lm -o OMG $(CFLAGS) - -clean: - @echo "Cleaning" - @rm OMG - @#rm rwpOMG - @#rm rwalkOMG - @#rm traceOMG - @#rm staticOMG - @#rm OMG - -else - -TOP_DIR = ../.. -OPENAIR1_TOP = ../.. -OPENAIR2_TOP = ../../../openair2 -OPENAIR3_TOP = ../../../openair3 -OPENAIR3 = $(OPENAIR3_DIR) - -CFLAGS += -DPHYSIM -DNODE_RG -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TX=2 -DMAX_MODULES=1 -I/usr/include/X11 #-Wno-packed-bitfield-compat - - -CFLAGS += -DOPENAIR_LTE -DOPENAIR2 #-DOFDMA_ULSCH -DIFFT_FPGA -DIFFT_FPGA_UE - -#CFLAGS += -DXFORMS - -ifdef DEBUG_PHY -CFLAGS += -DDEBUG_PHY -endif - -ifdef PDCP_USE_NETLINK -CFLAGS += -DPDCP_USE_NETLINK -DLINUX -DDEBUG_CONTROL -endif - -include $(OPENAIR1_DIR)/PHY/Makefile.inc -include $(OPENAIR1_DIR)/SCHED/Makefile.inc -include $(OPENAIR2_DIR)/LAYER2/Makefile.inc -include $(OPENAIR1_DIR)/SIMULATION/ETH_TRANSPORT/Makefile.inc - -SIMULATION_OBJS = $(TOP_DIR)/SIMULATION/TOOLS/gauss.o -SIMULATION_OBJS += $(TOP_DIR)/SIMULATION/TOOLS/random_channel.o -SIMULATION_OBJS += $(TOP_DIR)/SIMULATION/TOOLS/rangen_double.o -SIMULATION_OBJS += $(TOP_DIR)/SIMULATION/TOOLS/taus.o -SIMULATION_OBJS += $(TOP_DIR)/SIMULATION/TOOLS/multipath_channel.o -SIMULATION_OBJS += $(TOP_DIR)/SIMULATION/RF/rf.o -SIMULATION_OBJS += $(TOP_DIR)/SIMULATION/RF/adc.o -SIMULATION_OBJS += $(TOP_DIR)/SIMULATION/RF/dac.o - -OBJ = $(PHY_OBJS) $(SIMULATION_OBJS) $(ETHERNET_TRANSPORT_OBJS) $(TOOLS_OBJS) $(SCHED_OBJS) $(STATS_OBJS) - -all: physim - - -$(OBJ) : %.o : %.c - $(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) -DPHY_CONTEXT=1 -I$(TOP_DIR) $(L2_incl) -o $@ $< - -$(L2_OBJS) : %.o : %.c - $(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) -DMAC_CONTEXT=1 -DPHY_CONTEXT=1 -I$(TOP_DIR) $(L2_incl) -o $@ $< - -physim : $(OBJ) $(L2_OBJS) OMG.c common.c static.c job.c rwp.c rwalk.c hashtable.c mobility_parser.c trace.c -I$(TOP_DIR) $(L2_incl) -o physim $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(L2_OBJS) -lm -lforms -L/usr/local/lib -lforms -lX11 -L/usr/X11R6/lib -lXpm -lblas -lpthread - -clean: - rm -f physim - rm -f $(OBJ) - rm -f $(L2_OBJS) - rm -f *.o - rm -f *.exe* - -cleanl1: - rm -f physim - rm -f $(OBJ) - rm -f *.o - rm -f *.exe -cleanl2: - rm -f $(L2_OBJS) - -endif - diff --git a/openair2/UTIL/OPT/README.txt b/openair2/UTIL/OPT/README.txt index 2ac68f83fd..13ec727fd5 100644 --- a/openair2/UTIL/OPT/README.txt +++ b/openair2/UTIL/OPT/README.txt @@ -1,13 +1,14 @@ -How to configure wireshark for dissecting LTE protocols: +How to configure wireshark for dissecting LTE/NR protocols: - start the wireshark as a sudoers - goto analyze->enabled prototols - => enable mac_lte_udp and rlc_lte_udp + => enable mac_xxx_udp and rlc_xxx_udp (xxx is lte or nr) - goto edit/preferences and expand Protocols - select UDP and check "try heuristic sub-dissectors first" - - select MAC-LTE, and check all the options (checkboxes), and set the "which layer info to show in info column" to "MAC info" - - select RLC-LTE, and check all the options except the "May see RLC headers only", and + - select MAC-LTE (or MAC-NR), and check all the options (checkboxes), and set the "which layer info to show in info column" to "MAC info" + - select RLC-LTE (or NR), and check all the options except the "May see RLC headers only", and set the "call PDCP dissector for DRB PDUs" to "12-bit SN". Optionally you may select the sequence analysis for RLC AM/UM. + - select PDCP-LTE (or NR) How to use - start eNB or UE with option --opt.type wireshark diff --git a/openair2/UTIL/OPT/mac_pcap.h b/openair2/UTIL/OPT/mac_pcap.h index 3141d17d59..c443ceb1fb 100644 --- a/openair2/UTIL/OPT/mac_pcap.h +++ b/openair2/UTIL/OPT/mac_pcap.h @@ -6,6 +6,7 @@ #include #define MAC_LTE_DLT 147 +#define DLT_IPV4 228 /********************************************************/ /* Definitions and descriptions come from: http://wiki.wireshark.org/Development/LibpcapFileFormat */ @@ -29,20 +30,4 @@ typedef struct pcaprec_hdr_s { unsigned int orig_len; /* actual length of packet */ } pcaprec_hdr_t; -/* Context information for every MAC PDU that will be logged */ -typedef struct MAC_Context_Info_t { - unsigned short radioType; - unsigned char direction; - unsigned char rntiType; - unsigned short rnti; - unsigned short ueid; - unsigned char isRetx; - unsigned char crcStatusOK; - - unsigned short sysFrameNumber; - unsigned short subFrameNumber; - - unsigned int subframesSinceCaptureStart; -} MAC_Context_Info_t; - #endif diff --git a/openair2/UTIL/OPT/opt.h b/openair2/UTIL/OPT/opt.h index 6861e09cb1..ae6a3eb2a6 100644 --- a/openair2/UTIL/OPT/opt.h +++ b/openair2/UTIL/OPT/opt.h @@ -59,7 +59,8 @@ typedef uint16_t guint16; typedef uint32_t guint32; typedef guint8 gboolean; -#include "packet-mac-lte.h" +#include + #include "mac_pcap.h" /* OPT parameters definitions */ @@ -73,7 +74,7 @@ typedef guint8 gboolean; /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*---------------------------------------------------------------------------------------------------------------------------------------------*/ #define OPT_PARAMS_DESC { \ - {"type" , CONFIG_HLP_TYPEMON, 0, strptr:&in_type, defstrval:"none", TYPE_STRING, 0}, \ + {"type" , CONFIG_HLP_TYPEMON, 0, strptr:(char**)&in_type, defstrval:"none", TYPE_STRING, 0}, \ {"ip" , CONFIG_HLP_L2MONIP, 0, strptr:(char**)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, 0}, \ {"path" , CONFIG_HLP_L2MONPATH, 0, strptr:(char**)&in_path,defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, 0}, \ } @@ -107,9 +108,10 @@ typedef enum radio_type_e { */ extern int opt_enabled; -#define trace_pdu(x...) if (opt_enabled) trace_pdu_implementation(x) +#define trace_pdu(x...) if (opt_enabled) trace_pdu_implementation(0, x) +#define trace_NRpdu(x...) if (opt_enabled) trace_pdu_implementation(1, x) -void trace_pdu_implementation(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size, +void trace_pdu_implementation(int nr, int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size, int ueid, int rntiType, int rnti, uint16_t sysFrame, uint8_t subframe, int oob_event, int oob_event_value); diff --git a/openair2/UTIL/OPT/packet-mac-lte.h b/openair2/UTIL/OPT/packet-mac-lte.h deleted file mode 100644 index 2d36e02df4..0000000000 --- a/openair2/UTIL/OPT/packet-mac-lte.h +++ /dev/null @@ -1,382 +0,0 @@ -/* packet-mac-lte.h - * - * Martin Mathieson - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - * This header file may also be distributed under - * the terms of the BSD Licence as follows: - * - * Copyright (C) 2009 Martin Mathieson. All rights reserved. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - - /* - this is wireshark, commit: commit eda834b6e29c36e05a63a6056afa98390ff79357 - Date: Wed Aug 22 14:36:20 2018 +0200 - modified to be used in OpenAir to create the LTE MAC/RLC encapsulated in UDP as per Wireshark feature - */ - -#ifndef __UTIL_OPT_PACKET_MAC_LTE__H__ -#define __UTIL_OPT_PACKET_MAC_LTE__H__ - -#include "ws_symbol_export.h" - -/** data structure to hold time values with nanosecond resolution*/ -typedef struct { - time_t secs; - int nsecs; -} nstime_t; - - -/* radioType */ -#define FDD_RADIO 1 -#define TDD_RADIO 2 - -/* Direction */ -#define DIRECTION_UPLINK 0 -#define DIRECTION_DOWNLINK 1 - -/* rntiType */ -#define WS_NO_RNTI 0 -#define WS_P_RNTI 1 -#define WS_RA_RNTI 2 -#define WS_C_RNTI 3 -#define WS_SI_RNTI 4 -#define WS_SPS_RNTI 5 -#define WS_M_RNTI 6 -#define WS_SL_BCH_RNTI 7 -#define WS_SL_RNTI 8 -#define WS_SC_RNTI 9 -#define WS_G_RNTI 10 - -typedef enum mac_lte_oob_event { - ltemac_send_preamble, - ltemac_send_sr, - ltemac_sr_failure -} mac_lte_oob_event; - -typedef enum mac_lte_dl_retx { - dl_retx_no, - dl_retx_yes, - dl_retx_unknown -} mac_lte_dl_retx; - -typedef enum mac_lte_crc_status { - crc_fail = 0, - crc_success = 1, - crc_high_code_rate = 2, - crc_pdsch_lost = 3, - crc_duplicate_nonzero_rv = 4, - crc_false_dci = 5 -} mac_lte_crc_status; - -/* N.B. for SCellIndex-r13 extends to 31 */ -typedef enum mac_lte_carrier_id { - carrier_id_primary, - carrier_id_secondary_1, - carrier_id_secondary_2, - carrier_id_secondary_3, - carrier_id_secondary_4, - carrier_id_secondary_5, - carrier_id_secondary_6, - carrier_id_secondary_7 -} mac_lte_carrier_id; - -typedef enum mac_lte_ce_mode { - no_ce_mode = 0, - ce_mode_a = 1, - ce_mode_b = 2 -} mac_lte_ce_mode; - -typedef enum mac_lte_nb_mode { - no_nb_mode = 0, - nb_mode = 1 -} mac_lte_nb_mode; - -/* Context info attached to each LTE MAC frame */ -typedef struct mac_lte_info -{ - /* Needed for decode */ - guint8 radioType; - guint8 direction; - guint8 rntiType; - - /* Extra info to display */ - guint16 rnti; - guint16 ueid; - - /* Timing info */ - guint16 sysframeNumber; - guint16 subframeNumber; - - /* Optional field. More interesting for TDD (FDD is always -4 subframeNumber) */ - gboolean subframeNumberOfGrantPresent; - guint16 subframeNumberOfGrant; - - /* Flag set only if doing PHY-level data test - i.e. there may not be a - well-formed MAC PDU so just show as raw data */ - gboolean isPredefinedData; - - /* Length of DL PDU or UL grant size in bytes */ - guint16 length; - - /* 0=newTx, 1=first-retx, etc */ - guint8 reTxCount; - guint8 isPHICHNACK; /* FALSE=PDCCH retx grant, TRUE=PHICH NACK */ - - /* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set */ - gboolean isExtendedBSRSizes; - - /* UL only. Indicates if the R10 simultaneousPUCCH-PUSCH parameter is set for PCell */ - gboolean isSimultPUCCHPUSCHPCell; - - /* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set for PSCell */ - gboolean isSimultPUCCHPUSCHPSCell; - - /* Status of CRC check. For UE it is DL only. For eNodeB it is UL - only. For an analyzer, it is present for both DL and UL. */ - gboolean crcStatusValid; - mac_lte_crc_status crcStatus; - - /* Carrier ID */ - mac_lte_carrier_id carrierId; - - /* DL only. Is this known to be a retransmission? */ - mac_lte_dl_retx dl_retx; - - /* DL only. CE mode to be used for RAR decoding */ - mac_lte_ce_mode ceMode; - - /* DL and UL. NB-IoT mode of the UE */ - mac_lte_nb_mode nbMode; - - /* UL only, for now used for CE mode A RAR decoding */ - guint8 nUlRb; - - /* More Physical layer info (see direction above for which side of union to use) */ - union { - struct mac_lte_ul_phy_info - { - guint8 present; /* Remaining UL fields are present and should be displayed */ - guint8 modulation_type; - guint8 tbs_index; - guint8 resource_block_length; - guint8 resource_block_start; - guint8 harq_id; - gboolean ndi; - } ul_info; - struct mac_lte_dl_phy_info - { - guint8 present; /* Remaining DL fields are present and should be displayed */ - guint8 dci_format; - guint8 resource_allocation_type; - guint8 aggregation_level; - guint8 mcs_index; - guint8 redundancy_version_index; - guint8 resource_block_length; - guint8 harq_id; - gboolean ndi; - guint8 transport_block; /* 0..1 */ - } dl_info; - } detailed_phy_info; - - /* Relating to out-of-band events */ - /* N.B. dissector will only look to these fields if length is 0... */ - mac_lte_oob_event oob_event; - guint8 rapid; - guint8 rach_attempt_number; - #define MAX_SRs 20 - guint16 number_of_srs; - guint16 oob_ueid[MAX_SRs]; - guint16 oob_rnti[MAX_SRs]; -} mac_lte_info; - - -typedef struct mac_lte_tap_info { - /* Info from context */ - guint16 rnti; - guint16 ueid; - guint8 rntiType; - guint8 isPredefinedData; - gboolean crcStatusValid; - mac_lte_crc_status crcStatus; - guint8 direction; - - guint8 isPHYRetx; - guint16 ueInTTI; - - nstime_t mac_lte_time; - - /* Number of bytes (which part is used depends upon context settings) */ - guint32 single_number_of_bytes; - guint32 bytes_for_lcid[11]; - guint32 sdus_for_lcid[11]; - guint8 number_of_rars; - guint8 number_of_paging_ids; - - /* Number of padding bytes includes padding subheaders and trailing padding */ - guint16 padding_bytes; - guint16 raw_length; -} mac_lte_tap_info; - - - -/*****************************************************************/ -/* UDP framing format */ -/* ----------------------- */ -/* Several people have asked about dissecting MAC by framing */ -/* PDUs over IP. A suggested format over UDP has been created */ -/* and implemented by this dissector, using the definitions */ -/* below. A link to an example program showing you how to encode */ -/* these headers and send LTE MAC PDUs on a UDP socket is */ -/* provided at https://wiki.wireshark.org/MAC-LTE */ -/* */ -/* A heuristic dissector (enabled by a preference) will */ -/* recognise a signature at the beginning of these frames. */ -/*****************************************************************/ - - -/* Signature. Rather than try to define a port for this, or make the - port number a preference, frames will start with this string (with no - terminating NULL */ -#define MAC_LTE_START_STRING "mac-lte" - -/* Fixed fields. This is followed by the following 3 mandatory fields: - - radioType (1 byte) - - direction (1 byte) - - rntiType (1 byte) - (where the allowed values are defined above */ - -/* Optional fields. Attaching this info to frames will allow you - to show you display/filter/plot/add-custom-columns on these fields, so should - be added if available. - The format is to have the tag, followed by the value (there is no length field, - it's implicit from the tag) */ - -#define MAC_LTE_RNTI_TAG 0x02 -/* 2 bytes, network order */ - -#define MAC_LTE_UEID_TAG 0x03 -/* 2 bytes, network order */ - -#define MAC_LTE_FRAME_SUBFRAME_TAG 0x04 -/* 2 bytes, network order, SFN is stored in 12 MSB and SF in 4 LSB */ - -#define MAC_LTE_PREDEFINED_DATA_TAG 0x05 -/* 1 byte */ - -#define MAC_LTE_RETX_TAG 0x06 -/* 1 byte */ - -#define MAC_LTE_CRC_STATUS_TAG 0x07 -/* 1 byte */ - -#define MAC_LTE_EXT_BSR_SIZES_TAG 0x08 -/* 0 byte */ - -#define MAC_LTE_SEND_PREAMBLE_TAG 0x09 -/* 2 bytes, RAPID value (1 byte) followed by RACH attempt number (1 byte) */ - -#define MAC_LTE_CARRIER_ID_TAG 0x0A -/* 1 byte */ - -#define MAC_LTE_PHY_TAG 0x0B -/* variable length, length (1 byte) then depending on direction - in UL: modulation type (1 byte), TBS index (1 byte), RB length (1 byte), - RB start (1 byte), HARQ id (1 byte), NDI (1 byte) - in DL: DCI format (1 byte), resource allocation type (1 byte), aggregation level (1 byte), - MCS index (1 byte), redundancy version (1 byte), resource block length (1 byte), - HARQ id (1 byte), NDI (1 byte), TB (1 byte), DL reTx (1 byte) */ - -#define MAC_LTE_SIMULT_PUCCH_PUSCH_PCELL_TAG 0x0C -/* 0 byte */ - -#define MAC_LTE_SIMULT_PUCCH_PUSCH_PSCELL_TAG 0x0D -/* 0 byte */ - -#define MAC_LTE_CE_MODE_TAG 0x0E -/* 1 byte containing mac_lte_ce_mode enum value */ - -#define MAC_LTE_NB_MODE_TAG 0x0F -/* 1 byte containing mac_lte_nb_mode enum value */ - -#define MAC_LTE_N_UL_RB_TAG 0x10 -/* 1 byte containing the number of UL resource blocks: 6, 15, 25, 50, 75 or 100 */ - -#define MAC_LTE_SR_TAG 0x11 -/* 2 bytes for the number of items, followed by that number of ueid, rnti (2 bytes each) */ - - -/* MAC PDU. Following this tag comes the actual MAC PDU (there is no length, the PDU - continues until the end of the frame) */ -#define MAC_LTE_PAYLOAD_TAG 0x01 - - -/* Type to store parameters for configuring LCID->RLC channel settings for DRB */ -/* Some are optional, and may not be seen (e.g. on reestablishment) */ -typedef struct drb_mapping_t -{ - guint16 ueid; /* Mandatory */ - guint8 drbid; /* Mandatory */ - gboolean lcid_present; - guint8 lcid; /* Part of LogicalChannelConfig - optional */ - gboolean rlcMode_present; - guint8 rlcMode; /* Part of RLC config - optional */ - gboolean rlc_ul_ext_li_field; /* Part of RLC config - optional */ - gboolean rlc_dl_ext_li_field; /* Part of RLC config - optional */ - gboolean rlc_ul_ext_am_sn; /* Part of RLC config - optional */ - gboolean rlc_dl_ext_am_sn; /* Part of RLC config - optional */ - gboolean um_sn_length_present; - guint8 um_sn_length; /* Part of RLC config - optional */ - gboolean ul_priority_present; - guint8 ul_priority; /* Part of LogicalChannelConfig - optional */ - gboolean pdcp_sn_size_present; - guint8 pdcp_sn_size; /* Part of pdcp-Config - optional */ -} drb_mapping_t; - - - -/* Dedicated DRX config. Used to verify that a sensible config is given. - Also, beginning to configure MAC with this config and (optionally) show - DRX config and state (cycles/timers) attached to each UL/DL PDU! */ -typedef struct drx_config_t { - gboolean configured; - guint32 frameNum; - guint32 previousFrameNum; - - guint32 onDurationTimer; - guint32 inactivityTimer; - guint32 retransmissionTimer; - guint32 longCycle; - guint32 cycleOffset; - /* Optional Short cycle */ - gboolean shortCycleConfigured; - guint32 shortCycle; - guint32 shortCycleTimer; -} drx_config_t; - -/* RRC can indicate whether simultaneous PUCCH/PUSCH is used */ -typedef enum { - SIMULT_PUCCH_PUSCH_PCELL = 0, - SIMULT_PUCCH_PUSCH_PSCELL -} simult_pucch_pusch_cell_type; -/* - * Editor modelines - http://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 4 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=4 tabstop=8 expandtab: - * :indentSize=4:tabSize=8:noTabs=true: - */ - -#endif diff --git a/openair2/UTIL/OPT/packet-rohc.h b/openair2/UTIL/OPT/packet-rohc.h new file mode 100644 index 0000000000..c6c807f687 --- /dev/null +++ b/openair2/UTIL/OPT/packet-rohc.h @@ -0,0 +1,72 @@ +/* packet-rohc.h + * Routines for RObust Header Compression (ROHC) dissection. + * + * Copyright 2011, Anders Broman + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Ref: + * http://www.ietf.org/rfc/rfc3095.txt RObust Header Compression (ROHC): Framework and four profiles: RTP, UDP, ESP, and uncompressed + * http://datatracker.ietf.org/doc/rfc4815/ RObust Header Compression (ROHC): Corrections and Clarifications to RFC 3095 + * http://datatracker.ietf.org/doc/rfc5225/ RObust Header Compression Version 2 (ROHCv2): Profiles for RTP, UDP, IP, ESP and UDP-Lite + */ + +#ifndef PACKET_ROHC_H +#define PACKET_ROHC_H + +#define MAX_CID 15 + + /* ROHC Profiles */ +#define ROHC_PROFILE_UNCOMPRESSED 0 +#define ROHC_PROFILE_RTP 1 +#define ROHC_PROFILE_UDP 2 +#define ROHC_PROFILE_IP 4 +#define ROHC_PROFILE_UNKNOWN 0xFFFF + +enum rohc_mode +{ + MODE_NOT_SET = 0, + UNIDIRECTIONAL = 1, + OPTIMISTIC_BIDIRECTIONAL = 2, + RELIABLE_BIDIRECTIONAL = 3 +}; + +enum rohc_d_mode +{ + NO_CONTEXT = 1, + STATIC_CONTEXT = 2, + FULL_CONTEXT = 3 +}; +typedef struct rohc_info +{ + gboolean rohc_compression; + guint8 rohc_ip_version; + gboolean cid_inclusion_info; + gboolean large_cid_present; + enum rohc_mode mode; + gboolean rnd; + gboolean udp_checksum_present; + guint16 profile; + proto_item *last_created_item; +} rohc_info; + + +typedef struct rohc_context +{ + guint8 rohc_ip_version[MAX_CID+1]; + gboolean large_cid_present[MAX_CID+1]; + enum rohc_mode mode[MAX_CID+1]; + enum rohc_d_mode d_mode[MAX_CID+1]; + gboolean rnd[MAX_CID+1]; + gboolean udp_checkum_present[MAX_CID+1]; + guint16 profile[MAX_CID+1]; + gboolean rohc_context_init[MAX_CID+1]; + gint ir_frame_number[MAX_CID+1]; /* The frame number of the last IR packet seen */ + +} rohc_context; + +#endif /* PACKET_ROHC_H */ diff --git a/openair2/UTIL/OPT/probe.c b/openair2/UTIL/OPT/probe.c index 8c6a74e042..e64f7724c6 100644 --- a/openair2/UTIL/OPT/probe.c +++ b/openair2/UTIL/OPT/probe.c @@ -90,6 +90,7 @@ what about the implementation #include #include +#include #include "common/config/config_userapi.h" #include "opt.h" #include "common/utils/system.h" @@ -99,8 +100,6 @@ int opt_enabled=0; //static unsigned char g_PDUBuffer[1600]; //static unsigned int g_PDUOffset; -static char in_ip[128]={0}; -static char in_path[128]={0}; FILE *file_fd = NULL; pcap_hdr_t file_header = { 0xa1b2c3d4, /* magic number */ @@ -108,10 +107,14 @@ pcap_hdr_t file_header = { 0, /* timezone */ 0, /* sigfigs - apparently all tools do this */ 65535, /* snaplen - this should be long enough */ - MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */ + DLT_IPV4 + //MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */ }; trace_mode_t opt_type = OPT_NONE; +static char *in_type=NULL; +static char *in_path=NULL; +static char *in_ip=NULL; static unsigned int subframesSinceCaptureStart; static int g_socksd = -1;/* UDP socket used for sending frames */ @@ -125,14 +128,80 @@ typedef struct { opt_listener_t opt_listener; -static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType, - guint16 rnti, guint16 ueid, guint16 sysframeNumber, - guint8 isPredefinedData, guint8 retx, guint8 crcStatus, - guint8 oob_event, guint8 oob_event_value, - uint8_t *pdu_buffer, unsigned int pdu_buffer_size); +unsigned short checksum(unsigned short *ptr, int length) { + int sum = 0; + u_short answer = 0; + unsigned short *w = ptr; + int nleft = length; -static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context, - const unsigned char *PDU, unsigned int length); + while(nleft > 1) { + sum += *w++; + nleft -= 2; + } + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + answer = ~sum; + return(answer); +} + +/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */ +static int PCAP_WritePDU(const uint8_t *PDU, + unsigned int length) { + pcaprec_hdr_t packet_header; + // IPv4 header + typedef struct ip_hdr { + unsigned char ip_verlen; // 4-bit IPv4 version 4-bit header length (in 32-bit words) + unsigned char ip_tos; // IP type of service + unsigned short ip_totallength; // Total length + unsigned short ip_id; // Unique identifier + unsigned short ip_offset; // Fragment offset field + unsigned char ip_ttl; // Time to live + unsigned char ip_protocol; // Protocol(TCP,UDP etc) + unsigned short ip_checksum; // IP checksum + unsigned int ip_srcaddr; // Source address + unsigned int ip_destaddr; // Source address + } IPV4_HDR; + // Define the UDP header + typedef struct udp_hdr { + unsigned short src_portno; // Source port no. + unsigned short dst_portno; // Dest. port no. + unsigned short udp_length; // Udp packet length + unsigned short udp_checksum; // Udp checksum (optional) + } UDP_HDR; + IPV4_HDR IPheader= {0}; + IPheader.ip_verlen = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(uint32_t)); + IPheader.ip_totallength = htons(sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length); + IPheader.ip_ttl = 8; // Time-to-live is eight + IPheader.ip_protocol = IPPROTO_UDP; + IPheader.ip_srcaddr = inet_addr(in_ip); + IPheader.ip_destaddr = inet_addr(in_ip); + IPheader.ip_checksum = checksum((unsigned short *)&IPheader, sizeof(IPV4_HDR)); + // Initialize the UDP header + UDP_HDR UDPheader; + UDPheader.src_portno = htons( PACKET_MAC_LTE_DEFAULT_UDP_PORT); + UDPheader.dst_portno = htons( PACKET_MAC_LTE_DEFAULT_UDP_PORT); + UDPheader.udp_length = htons(sizeof(UDP_HDR) + length); + UDPheader.udp_checksum = 0; + /****************************************************************/ + /* PCAP Header */ + /* TODO: Timestamp might want to be relative to a more sensible + base time... */ + struct timeval tv; + gettimeofday(&tv, NULL); + packet_header.ts_sec = tv.tv_sec; + packet_header.ts_usec = tv.tv_usec; + packet_header.incl_len =sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length; + packet_header.orig_len =sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length; + /***************************************************************/ + /* Now write everything to the file */ + fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd); + fwrite(&IPheader, sizeof(IPV4_HDR), 1, file_fd); + fwrite(&UDPheader, sizeof(UDP_HDR), 1, file_fd); + fwrite(PDU, 1, length, file_fd); + fflush(file_fd); + return length; +} static void *opt_listener_thread(void *arg) { ssize_t ret; @@ -198,7 +267,6 @@ int opt_create_listener_socket(char *ip_address, uint16_t port) { } threadCreate(&opt_listener.thread, opt_listener_thread, NULL, "flexran", -1, OAI_PRIORITY_RT_LOW); - return 0; } @@ -214,7 +282,7 @@ int opt_create_listener_socket(char *ip_address, uint16_t port) { */ /* Add framing header to MAC PDU and send. */ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType, - guint16 rnti, guint16 ueid, guint16 sfnSf, + guint16 rnti, guint16 ueid, guint16 frame, guint16 subframe, guint8 isPredefinedData, guint8 retx, guint8 crcStatus, guint8 oob_event, guint8 oob_event_value, uint8_t *pdu_buffer, unsigned int pdu_buffer_size) { @@ -243,9 +311,9 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType, tmp16 = htons(ueid); memcpy(frameBuffer+frameOffset, &tmp16, 2); frameOffset += 2; - /* Subframe number */ + /* Subframe number */ frameBuffer[frameOffset++] = MAC_LTE_FRAME_SUBFRAME_TAG; - tmp16 = htons(sfnSf); // frame counter : this will give an expert info as wireshark expects SF and not F + tmp16 = htons((frame<<4)+subframe); // frame counter : this will give an expert info as wireshark expects SF and not F memcpy(frameBuffer+frameOffset, &tmp16, 2); frameOffset += 2; frameBuffer[frameOffset++] = MAC_LTE_CRC_STATUS_TAG; @@ -321,137 +389,157 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType, frameOffset += pdu_buffer_size; } - /* Send out the data over the UDP socket */ - bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0, - (const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr)); + if ( opt_type == OPT_WIRESHARK ) + /* Send out the data over the UDP socket */ + bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0, + (const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr)); + else + bytesSent = PCAP_WritePDU(frameBuffer, frameOffset); if (bytesSent != frameOffset) { - LOG_W(OPT, "sendto() failed (not a thread-safe func)- expected %d bytes, got %ld (errno=%d)\n", + LOG_W(OPT, "trace_pdu expected %d bytes, got %ld (errno=%d)\n", frameOffset, bytesSent, errno); //exit(1); } } -/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */ -static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context, - const uint8_t *PDU, - unsigned int length) -{ - pcaprec_hdr_t packet_header; - uint8_t context_header[256]; - int offset = 0; - unsigned short tmp16; - /*****************************************************************/ - /* Context information (same as written by UDP heuristic clients */ - context_header[offset++] = context->radioType; - context_header[offset++] = context->direction; - context_header[offset++] = context->rntiType; +static void SendFrameNR(guint8 radioType, guint8 direction, guint8 rntiType, + guint16 rnti, guint16 ueid, guint16 frame, guint16 subframe, + guint8 isPredefinedData, guint8 retx, guint8 crcStatus, + guint8 oob_event, guint8 oob_event_value, + uint8_t *pdu_buffer, unsigned int pdu_buffer_size) { + unsigned char frameBuffer[9000]; + unsigned int frameOffset; + ssize_t bytesSent; + frameOffset = 0; + uint16_t tmp16; + memcpy(frameBuffer+frameOffset, MAC_NR_START_STRING, + strlen(MAC_NR_START_STRING)); + frameOffset += strlen(MAC_NR_START_STRING); + /******************************************************************************/ + /* Now write out fixed fields (the mandatory elements of struct mac_lte_info) */ + frameBuffer[frameOffset++] = radioType; + frameBuffer[frameOffset++] = direction; + frameBuffer[frameOffset++] = rntiType; + /*************************************/ + /* Now optional fields */ /* RNTI */ - context_header[offset++] = MAC_LTE_RNTI_TAG; - tmp16 = htons(context->rnti); - memcpy(context_header+offset, &tmp16, 2); - offset += 2; + frameBuffer[frameOffset++] = MAC_NR_RNTI_TAG; + tmp16 = htons(rnti); + memcpy(frameBuffer+frameOffset, &tmp16, 2); + frameOffset += 2; /* UEId */ - context_header[offset++] = MAC_LTE_UEID_TAG; - tmp16 = htons(context->ueid); - memcpy(context_header+offset, &tmp16, 2); - offset += 2; + frameBuffer[frameOffset++] = MAC_NR_UEID_TAG; + tmp16 = htons(ueid); + memcpy(frameBuffer+frameOffset, &tmp16, 2); + frameOffset += 2; /* Subframe number */ - context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG; - tmp16 = htons(context->subFrameNumber); - memcpy(context_header+offset, &tmp16, 2); - offset += 2; - /* CRC Status */ - context_header[offset++] = MAC_LTE_CRC_STATUS_TAG; - context_header[offset++] = context->crcStatusOK; - /* Data tag immediately preceding PDU */ - context_header[offset++] = MAC_LTE_PAYLOAD_TAG; - /****************************************************************/ - /* PCAP Header */ - /* TODO: Timestamp might want to be relative to a more sensible - base time... */ - packet_header.ts_sec = context->subframesSinceCaptureStart / 1000; - packet_header.ts_usec = (context->subframesSinceCaptureStart % 1000) * 1000; - packet_header.incl_len = offset + length; - packet_header.orig_len = offset + length; - /***************************************************************/ - /* Now write everything to the file */ - fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd); - fwrite(context_header, 1, offset, file_fd); - fwrite(PDU, 1, length, file_fd); - return 1; + frameBuffer[frameOffset++] = MAC_NR_FRAME_SLOT_TAG; + tmp16 = htons(frame); // frame counter : this will give an expert info as wireshark expects SF and not F + memcpy(frameBuffer+frameOffset, &tmp16, 2); + frameOffset += 2; + tmp16 = htons(subframe); // frame counter : this will give an expert info as wireshark expects SF and not F + memcpy(frameBuffer+frameOffset, &tmp16, 2); + frameOffset += 2; + if (direction == 0 ) { //ulink + frameBuffer[frameOffset++] = MAC_NR_PHR_TYPE2_OTHERCELL_TAG; + frameBuffer[frameOffset++] = 0; + } + + /***************************************/ + /* Now write the MAC PDU */ + frameBuffer[frameOffset++] = MAC_NR_PAYLOAD_TAG; + + /* Append actual PDU */ + //memcpy(frameBuffer+frameOffset, g_PDUBuffer, g_PDUOffset); + //frameOffset += g_PDUOffset; + if (pdu_buffer != NULL) { + memcpy(frameBuffer+frameOffset, (void *)pdu_buffer, pdu_buffer_size); + frameOffset += pdu_buffer_size; + } + + if ( opt_type == OPT_WIRESHARK ) + /* Send out the data over the UDP socket */ + bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0, + (const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr)); + else + bytesSent = PCAP_WritePDU(frameBuffer, frameOffset); + + if (bytesSent != frameOffset) { + LOG_W(OPT, "trace_pdu expected %d bytes, got %ld (errno=%d)\n", + frameOffset, bytesSent, errno); + //exit(1); + } } #include extern RAN_CONTEXT_t RC; #include /* Remote serveraddress (where Wireshark is running) */ -void trace_pdu_implementation(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size, +void trace_pdu_implementation(int nr, int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size, int ueid, int rntiType, int rnti, uint16_t sysFrameNumber, uint8_t subFrameNumber, int oob_event, int oob_event_value) { - MAC_Context_Info_t pdu_context; int radioType=FDD_RADIO; LOG_D(OPT,"sending packet to wireshark: direction=%s, size: %d, ueid: %d, rnti: %x, frame/sf: %d.%d\n", direction?"DL":"UL", pdu_buffer_size, ueid, rnti, sysFrameNumber,subFrameNumber); - if (RC.eNB && RC.eNB[0][0]!=NULL) - radioType=RC.eNB[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO; - else if (PHY_vars_UE_g && PHY_vars_UE_g[0][0] != NULL) - radioType=PHY_vars_UE_g[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO; - else { - LOG_E(OPT,"not a eNB neither a UE!!! \n"); - return; + if (nr) { + radioType=TDD_RADIO; + } else { + if (RC.eNB && RC.eNB[0][0]!=NULL) + radioType=RC.eNB[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO; + else if (PHY_vars_UE_g && PHY_vars_UE_g[0][0] != NULL) + radioType=PHY_vars_UE_g[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO; + else { + LOG_E(OPT,"not a 4G eNB neither a 4G UE!!! \n"); + } } switch (opt_type) { case OPT_WIRESHARK : - if (g_socksd == -1) { + if (g_socksd == -1) return; - } - SendFrame( radioType, - (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK, - rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber, - 1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus - oob_event,oob_event_value, - pdu_buffer, pdu_buffer_size); break; case OPT_PCAP: - if (file_fd == NULL) { + if (file_fd == NULL) return; - } - pdu_context.radioType = radioType; - pdu_context.direction = (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK - : DIRECTION_UPLINK; - pdu_context.rntiType = rntiType; - pdu_context.rnti = rnti; - pdu_context.ueid = ueid; - pdu_context.isRetx = 0; - pdu_context.crcStatusOK =1; - pdu_context.sysFrameNumber = sysFrameNumber; - pdu_context.subFrameNumber = subFrameNumber; - pdu_context.subframesSinceCaptureStart = subframesSinceCaptureStart++; - MAC_LTE_PCAP_WritePDU( &pdu_context, pdu_buffer, pdu_buffer_size); break; case OPT_TSHARK: default: + return; break; } + + if (nr) + SendFrameNR( radioType, + (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK, + rntiType, rnti, ueid, sysFrameNumber, subFrameNumber, + 1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus + oob_event,oob_event_value, + pdu_buffer, pdu_buffer_size); + else + SendFrame( radioType, + (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK, + rntiType, rnti, ueid, sysFrameNumber, subFrameNumber, + 1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus + oob_event,oob_event_value, + pdu_buffer, pdu_buffer_size); } + /*---------------------------------------------------*/ -int init_opt(void) -{ - char *in_type=NULL; +int init_opt(void) { + in_type=malloc(200); + in_ip=malloc(200); + in_path=malloc(200); paramdef_t opt_params[] = OPT_PARAMS_DESC ; checkedparam_t opt_checkParams[] = OPTPARAMS_CHECK_DESC; - uint16_t in_port=0; config_set_checkfunctions(opt_params, opt_checkParams, sizeof(opt_params)/sizeof(paramdef_t)); config_get( opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX); - subframesSinceCaptureStart = 0; int tmptype = config_get_processedint( &(opt_params[OPTTYPE_IDX])); @@ -462,25 +550,21 @@ int init_opt(void) } else if (tmptype == OPT_PCAP && strlen(in_path) > 0) { opt_type = OPT_PCAP; opt_enabled=1; - LOG_I(OPT,"Enabling OPT for PCAP with the following file %s \n",in_path); } else if (tmptype == OPT_WIRESHARK && strlen(in_ip) > 0) { opt_enabled=1; opt_type = OPT_WIRESHARK; - LOG_I(OPT,"Enabling OPT for wireshark for local interface %s\n",in_ip); } else { LOG_E(OPT,"Invalid OPT configuration\n"); config_printhelp(opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX); } - in_port = PACKET_MAC_LTE_DEFAULT_UDP_PORT; - // trace_mode switch (opt_type) { case OPT_WIRESHARK: - + LOG_I(OPT,"mode Wireshark: ip %s port %d\n", in_ip, PACKET_MAC_LTE_DEFAULT_UDP_PORT); /* Create local server socket only if using localhost address */ - if (strcmp(in_ip, "127.0.0.1") == 0) { - opt_create_listener_socket(in_ip, in_port); + if (strncmp(in_ip, "127.0.0.1", 4) == 0) { + opt_create_listener_socket(in_ip, PACKET_MAC_LTE_DEFAULT_UDP_PORT); } g_socksd = socket(AF_INET, SOCK_DGRAM, 0); @@ -493,11 +577,12 @@ int init_opt(void) /* Get remote IP address from the function argument */ g_serv_addr.sin_family = AF_INET; - g_serv_addr.sin_port = htons(in_port); + g_serv_addr.sin_port = htons(PACKET_MAC_LTE_DEFAULT_UDP_PORT); g_serv_addr.sin_addr.s_addr = inet_addr(in_ip); break; case OPT_PCAP: + LOG_I(OPT,"mode PCAB : path is %s \n",in_path); file_fd = fopen(in_path, "w"); if (file_fd == NULL) { @@ -516,19 +601,9 @@ int init_opt(void) default: opt_type = OPT_NONE; - LOG_W(OPT, "supported Option\n"); + LOG_E(OPT,"Unsupported or unknown mode %d \n", opt_type); break; } - - if ( opt_type == OPT_WIRESHARK ) - LOG_E(OPT,"mode Wireshark: ip %s port %d\n", in_ip, in_port); - else if (opt_type == OPT_PCAP) - LOG_E(OPT,"mode PCAB : path is %s \n",in_path); - else - LOG_E(OPT,"Unsupported or unknown mode %d \n", opt_type); - - // mac_info = (mac_info*)malloc16(sizeof(mac_lte_info)); - // memset(mac_info, 0, sizeof(mac_lte_info)+pdu_buffer_size + 8); return (1); } diff --git a/openair2/UTIL/OPT/wireshark_headers.h b/openair2/UTIL/OPT/wireshark_headers.h new file mode 100644 index 0000000000..27d8753ffe --- /dev/null +++ b/openair2/UTIL/OPT/wireshark_headers.h @@ -0,0 +1,895 @@ +/* packet-mac-lte.h + * + * Martin Mathieson + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * Copyright (C) 2009 Martin Mathieson. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + + /* + this is wireshark, commit: commit eda834b6e29c36e05a63a6056afa98390ff79357 + Date: Wed Aug 22 14:36:20 2018 +0200 + modified to be used in OpenAir to create the LTE MAC/RLC encapsulated in UDP as per Wireshark feature + */ + +#ifndef __UTIL_OPT_PACKET_MAC_LTE__H__ +#define __UTIL_OPT_PACKET_MAC_LTE__H__ + +/** data structure to hold time values with nanosecond resolution*/ +typedef struct { + time_t secs; + int nsecs; +} nstime_t; + + +/* radioType */ +#define FDD_RADIO 1 +#define TDD_RADIO 2 + +/* Direction */ +#define DIRECTION_UPLINK 0 +#define DIRECTION_DOWNLINK 1 + +/* rntiType */ +#define WS_NO_RNTI 0 +#define WS_P_RNTI 1 +#define WS_RA_RNTI 2 +#define WS_C_RNTI 3 +#define WS_SI_RNTI 4 +#define WS_SPS_RNTI 5 +#define WS_M_RNTI 6 +#define WS_SL_BCH_RNTI 7 +#define WS_SL_RNTI 8 +#define WS_SC_RNTI 9 +#define WS_G_RNTI 10 + +#define WS_CS_RNTI 5 + +typedef enum mac_lte_oob_event { + ltemac_send_preamble, + ltemac_send_sr, + ltemac_sr_failure +} mac_lte_oob_event; + +typedef enum mac_lte_dl_retx { + dl_retx_no, + dl_retx_yes, + dl_retx_unknown +} mac_lte_dl_retx; + +typedef enum mac_lte_crc_status { + crc_fail = 0, + crc_success = 1, + crc_high_code_rate = 2, + crc_pdsch_lost = 3, + crc_duplicate_nonzero_rv = 4, + crc_false_dci = 5 +} mac_lte_crc_status; + +/* N.B. for SCellIndex-r13 extends to 31 */ +typedef enum mac_lte_carrier_id { + carrier_id_primary, + carrier_id_secondary_1, + carrier_id_secondary_2, + carrier_id_secondary_3, + carrier_id_secondary_4, + carrier_id_secondary_5, + carrier_id_secondary_6, + carrier_id_secondary_7 +} mac_lte_carrier_id; + +typedef enum mac_lte_ce_mode { + no_ce_mode = 0, + ce_mode_a = 1, + ce_mode_b = 2 +} mac_lte_ce_mode; + +typedef enum mac_lte_nb_mode { + no_nb_mode = 0, + nb_mode = 1 +} mac_lte_nb_mode; + +/* Context info attached to each LTE MAC frame */ +typedef struct mac_lte_info +{ + /* Needed for decode */ + guint8 radioType; + guint8 direction; + guint8 rntiType; + + /* Extra info to display */ + guint16 rnti; + guint16 ueid; + + /* Timing info */ + guint16 sysframeNumber; + guint16 subframeNumber; + gboolean sfnSfInfoPresent; + + /* Optional field. More interesting for TDD (FDD is always -4 subframeNumber) */ + gboolean subframeNumberOfGrantPresent; + guint16 subframeNumberOfGrant; + + /* Flag set only if doing PHY-level data test - i.e. there may not be a + well-formed MAC PDU so just show as raw data */ + gboolean isPredefinedData; + + /* Length of DL PDU or UL grant size in bytes */ + guint16 length; + + /* 0=newTx, 1=first-retx, etc */ + guint8 reTxCount; + guint8 isPHICHNACK; /* FALSE=PDCCH retx grant, TRUE=PHICH NACK */ + + /* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set */ + gboolean isExtendedBSRSizes; + + /* UL only. Indicates if the R10 simultaneousPUCCH-PUSCH parameter is set for PCell */ + gboolean isSimultPUCCHPUSCHPCell; + + /* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set for PSCell */ + gboolean isSimultPUCCHPUSCHPSCell; + + /* Status of CRC check. For UE it is DL only. For eNodeB it is UL + only. For an analyzer, it is present for both DL and UL. */ + gboolean crcStatusValid; + mac_lte_crc_status crcStatus; + + /* Carrier ID */ + mac_lte_carrier_id carrierId; + + /* DL only. Is this known to be a retransmission? */ + mac_lte_dl_retx dl_retx; + + /* DL only. CE mode to be used for RAR decoding */ + mac_lte_ce_mode ceMode; + + /* DL and UL. NB-IoT mode of the UE */ + mac_lte_nb_mode nbMode; + + /* UL only, for now used for CE mode A RAR decoding */ + guint8 nUlRb; + + /* More Physical layer info (see direction above for which side of union to use) */ + union { + struct mac_lte_ul_phy_info + { + guint8 present; /* Remaining UL fields are present and should be displayed */ + guint8 modulation_type; + guint8 tbs_index; + guint8 resource_block_length; + guint8 resource_block_start; + guint8 harq_id; + gboolean ndi; + } ul_info; + struct mac_lte_dl_phy_info + { + guint8 present; /* Remaining DL fields are present and should be displayed */ + guint8 dci_format; + guint8 resource_allocation_type; + guint8 aggregation_level; + guint8 mcs_index; + guint8 redundancy_version_index; + guint8 resource_block_length; + guint8 harq_id; + gboolean ndi; + guint8 transport_block; /* 0..1 */ + } dl_info; + } detailed_phy_info; + + /* Relating to out-of-band events */ + /* N.B. dissector will only look to these fields if length is 0... */ + mac_lte_oob_event oob_event; + guint8 rapid; + guint8 rach_attempt_number; + #define MAX_SRs 20 + guint16 number_of_srs; + guint16 oob_ueid[MAX_SRs]; + guint16 oob_rnti[MAX_SRs]; +} mac_lte_info; + + /* 0 to 10 and 32 to 38 */ +#define MAC_LTE_DATA_LCID_COUNT_MAX 18 +#define MAC_LTE_START_STRING "mac-lte" + +/* Fixed fields. This is followed by the following 3 mandatory fields: + - radioType (1 byte) + - direction (1 byte) + - rntiType (1 byte) + (where the allowed values are defined above */ + +/* Optional fields. Attaching this info to frames will allow you + to show you display/filter/plot/add-custom-columns on these fields, so should + be added if available. + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag) */ + +#define MAC_LTE_RNTI_TAG 0x02 +/* 2 bytes, network order */ + +#define MAC_LTE_UEID_TAG 0x03 +/* 2 bytes, network order */ + +#define MAC_LTE_FRAME_SUBFRAME_TAG 0x04 +/* 2 bytes, network order, SFN is stored in 12 MSB and SF in 4 LSB */ + +#define MAC_LTE_PREDEFINED_DATA_TAG 0x05 +/* 1 byte */ + +#define MAC_LTE_RETX_TAG 0x06 +/* 1 byte */ + +#define MAC_LTE_CRC_STATUS_TAG 0x07 +/* 1 byte */ + +#define MAC_LTE_EXT_BSR_SIZES_TAG 0x08 +/* 0 byte */ + +#define MAC_LTE_SEND_PREAMBLE_TAG 0x09 +/* 2 bytes, RAPID value (1 byte) followed by RACH attempt number (1 byte) */ + +#define MAC_LTE_CARRIER_ID_TAG 0x0A +/* 1 byte */ + +#define MAC_LTE_PHY_TAG 0x0B +/* variable length, length (1 byte) then depending on direction + in UL: modulation type (1 byte), TBS index (1 byte), RB length (1 byte), + RB start (1 byte), HARQ id (1 byte), NDI (1 byte) + in DL: DCI format (1 byte), resource allocation type (1 byte), aggregation level (1 byte), + MCS index (1 byte), redundancy version (1 byte), resource block length (1 byte), + HARQ id (1 byte), NDI (1 byte), TB (1 byte), DL reTx (1 byte) */ + +#define MAC_LTE_SIMULT_PUCCH_PUSCH_PCELL_TAG 0x0C +/* 0 byte */ + +#define MAC_LTE_SIMULT_PUCCH_PUSCH_PSCELL_TAG 0x0D +/* 0 byte */ + +#define MAC_LTE_CE_MODE_TAG 0x0E +/* 1 byte containing mac_lte_ce_mode enum value */ + +#define MAC_LTE_NB_MODE_TAG 0x0F +/* 1 byte containing mac_lte_nb_mode enum value */ + +#define MAC_LTE_N_UL_RB_TAG 0x10 +/* 1 byte containing the number of UL resource blocks: 6, 15, 25, 50, 75 or 100 */ + +#define MAC_LTE_SR_TAG 0x11 +/* 2 bytes for the number of items, followed by that number of ueid, rnti (2 bytes each) */ + + +/* MAC PDU. Following this tag comes the actual MAC PDU (there is no length, the PDU + continues until the end of the frame) */ +#define MAC_LTE_PAYLOAD_TAG 0x01 + +/* rlcMode */ +#define RLC_TM_MODE 1 +#define RLC_UM_MODE 2 +#define RLC_AM_MODE 4 +#define RLC_PREDEF 8 + +/* priority ? */ + +/* channelType */ +#define CHANNEL_TYPE_CCCH 1 +#define CHANNEL_TYPE_BCCH_BCH 2 +#define CHANNEL_TYPE_PCCH 3 +#define CHANNEL_TYPE_SRB 4 +#define CHANNEL_TYPE_DRB 5 +#define CHANNEL_TYPE_BCCH_DL_SCH 6 +#define CHANNEL_TYPE_MCCH 7 +#define CHANNEL_TYPE_MTCH 8 + +/* sequenceNumberLength */ +#define UM_SN_LENGTH_5_BITS 5 +#define UM_SN_LENGTH_10_BITS 10 +#define AM_SN_LENGTH_10_BITS 10 +#define AM_SN_LENGTH_16_BITS 16 + + +typedef enum rlc_lte_nb_mode { + rlc_no_nb_mode = 0, + rlc_nb_mode = 1 +} rlc_lte_nb_mode; + + +/* Info attached to each LTE RLC frame */ +typedef struct rlc_lte_info +{ + guint8 rlcMode; + guint8 direction; + guint8 priority; + guint8 sequenceNumberLength; + guint16 ueid; + guint16 channelType; + guint16 channelId; /* for SRB: 1=SRB1, 2=SRB2, 3=SRB1bis; for DRB: DRB ID */ + guint16 pduLength; + gboolean extendedLiField; + rlc_lte_nb_mode nbMode; +} rlc_lte_info; + + +typedef struct rlc_lte_tap_info { + /* Info from context */ + guint8 rlcMode; + guint8 direction; + guint8 priority; + guint16 ueid; + guint16 channelType; + guint16 channelId; + guint16 pduLength; + guint8 sequenceNumberLength; + + nstime_t rlc_lte_time; + guint8 loggedInMACFrame; + guint16 sequenceNumber; + guint8 isResegmented; + guint8 isControlPDU; + guint16 ACKNo; + #define MAX_NACKs 128 + guint16 noOfNACKs; + guint16 NACKs[MAX_NACKs]; + + guint16 missingSNs; +} rlc_lte_tap_info; + + +/* Signature. Rather than try to define a port for this, or make the + port number a preference, frames will start with this string (with no + terminating NULL */ +#define RLC_LTE_START_STRING "rlc-lte" + +/* Fixed field. This is followed by the following 1 mandatory field: + - rlcMode (1 byte) + (where the allowed values are defined above */ + +/* Conditional field. This field is mandatory in case of RLC Unacknowledged mode. + In case of RLC Acknowledged mode, the field is optional (assume 10 bits by default). + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag). The allowed values are defined above. */ + +#define RLC_LTE_SN_LENGTH_TAG 0x02 +/* 1 byte */ + +/* Optional fields. Attaching this info to frames will allow you + to show you display/filter/plot/add-custom-columns on these fields, so should + be added if available. + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag) */ + +#define RLC_LTE_DIRECTION_TAG 0x03 +/* 1 byte */ + +#define RLC_LTE_PRIORITY_TAG 0x04 +/* 1 byte */ + +#define RLC_LTE_UEID_TAG 0x05 +/* 2 bytes, network order */ + +#define RLC_LTE_CHANNEL_TYPE_TAG 0x06 +/* 2 bytes, network order */ + +#define RLC_LTE_CHANNEL_ID_TAG 0x07 +/* 2 bytes, network order */ + +#define RLC_LTE_EXT_LI_FIELD_TAG 0x08 +/* 0 byte, tag presence indicates that AM DRB PDU is using an extended LI field of 15 bits */ + +#define RLC_LTE_NB_MODE_TAG 0x09 +/* 1 byte containing rlc_lte_nb_mode enum value */ + +/* RLC PDU. Following this tag comes the actual RLC PDU (there is no length, the PDU + continues until the end of the frame) */ +#define RLC_LTE_PAYLOAD_TAG 0x01 + +enum pdcp_plane +{ + SIGNALING_PLANE = 1, + USER_PLANE = 2 +}; + +typedef enum LogicalChannelType +{ + Channel_DCCH=1, + Channel_BCCH=2, + Channel_CCCH=3, + Channel_PCCH=4, + Channel_DCCH_NB=5, + Channel_BCCH_NB=6, + Channel_CCCH_NB=7, + Channel_PCCH_NB=8 +} LogicalChannelType; + +typedef enum +{ + BCH_TRANSPORT=1, + DLSCH_TRANSPORT=2 +} BCCHTransportType; + +#define PDCP_SN_LENGTH_5_BITS 5 +#define PDCP_SN_LENGTH_7_BITS 7 +#define PDCP_SN_LENGTH_12_BITS 12 +#define PDCP_SN_LENGTH_15_BITS 15 +#define PDCP_SN_LENGTH_18_BITS 18 + +enum lte_security_integrity_algorithm_e { eia0, eia1, eia2, eia3 }; +enum lte_security_ciphering_algorithm_e { eea0, eea1, eea2, eea3 }; + +typedef struct pdcp_lte_security_info_t +{ + guint32 configuration_frame; + gboolean seen_next_ul_pdu; /* i.e. have we seen SecurityModeResponse */ + enum lte_security_integrity_algorithm_e integrity; + enum lte_security_ciphering_algorithm_e ciphering; + + /* Store previous settings so can revert if get SecurityModeFailure */ + guint32 previous_configuration_frame; + enum lte_security_integrity_algorithm_e previous_integrity; + enum lte_security_ciphering_algorithm_e previous_ciphering; +} pdcp_lte_security_info_t; + + +/***********************************************************************/ +/* UDP framing format */ +/* ----------------------- */ +/* Several people have asked about dissecting PDCP by framing */ +/* PDUs over IP. A suggested format over UDP has been defined */ +/* and implemented by this dissector, using the definitions */ +/* below. A link to an example program showing you how to encode */ +/* these headers and send LTE PDCP PDUs on a UDP socket is */ +/* provided at https://gitlab.com/wireshark/wireshark/-/wikis/PDCP-LTE */ +/* */ +/* A heuristic dissecter (enabled by a preference) will */ +/* recognise a signature at the beginning of these frames. */ +/* Until someone is using this format, suggestions for changes */ +/* are welcome. */ +/***********************************************************************/ + + +/* Signature. Rather than try to define a port for this, or make the + port number a preference, frames will start with this string (with no + terminating NULL */ +#define PDCP_LTE_START_STRING "pdcp-lte" + +/* Fixed fields. This is followed by the following 3 mandatory fields: + - no_header_pdu (1 byte) + - plane (1 byte) + - rohc_compression ( byte) + (where the allowed values are defined above) */ + +/* Conditional field. This field is mandatory in case of User Plane PDCP PDU. + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag). The allowed values are defined above. */ + +#define PDCP_LTE_SEQNUM_LENGTH_TAG 0x02 +/* 1 byte */ + +/* Optional fields. Attaching this info to frames will allow you + to show you display/filter/plot/add-custom-columns on these fields, so should + be added if available. + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag) */ + +#define PDCP_LTE_DIRECTION_TAG 0x03 +/* 1 byte */ + +#define PDCP_LTE_LOG_CHAN_TYPE_TAG 0x04 +/* 1 byte */ + +#define PDCP_LTE_BCCH_TRANSPORT_TYPE_TAG 0x05 +/* 1 byte */ + +#define PDCP_LTE_ROHC_IP_VERSION_TAG 0x06 +/* 2 bytes, network order */ + +#define PDCP_LTE_ROHC_CID_INC_INFO_TAG 0x07 +/* 1 byte */ + +#define PDCP_LTE_ROHC_LARGE_CID_PRES_TAG 0x08 +/* 1 byte */ + +#define PDCP_LTE_ROHC_MODE_TAG 0x09 +/* 1 byte */ + +#define PDCP_LTE_ROHC_RND_TAG 0x0A +/* 1 byte */ + +#define PDCP_LTE_ROHC_UDP_CHECKSUM_PRES_TAG 0x0B +/* 1 byte */ + +#define PDCP_LTE_ROHC_PROFILE_TAG 0x0C +/* 2 bytes, network order */ + +#define PDCP_LTE_CHANNEL_ID_TAG 0x0D +/* 2 bytes, network order */ + +#define PDCP_LTE_UEID_TAG 0x0E +/* 2 bytes, network order */ + +/* PDCP PDU. Following this tag comes the actual PDCP PDU (there is no length, the PDU + continues until the end of the frame) */ +#define PDCP_LTE_PAYLOAD_TAG 0x01 + + + +/* Called by RRC, or other configuration protocols */ + +/* Function to configure ciphering & integrity algorithms */ +void set_pdcp_lte_security_algorithms(guint16 ueid, pdcp_lte_security_info_t *security_info); + +/* Function to indicate securityModeCommand did not complete */ +void set_pdcp_lte_security_algorithms_failed(guint16 ueid); + + +/* Called by external dissectors */ +void set_pdcp_lte_rrc_ciphering_key(guint16 ueid, const char *key); +void set_pdcp_lte_rrc_integrity_key(guint16 ueid, const char *key); +void set_pdcp_lte_up_ciphering_key(guint16 ueid, const char *key); + + + +/* Context info attached to each NR MAC frame */ +typedef struct mac_nr_info +{ + /* Needed for decode */ + guint8 radioType; + guint8 direction; + guint8 rntiType; + + /* Extra info to display */ + guint16 rnti; + guint16 ueid; + guint8 harqid; + + /* Will these be included in the ME PHR report? */ + guint8 phr_type2_othercell; + + /* Timing info */ + gboolean sfnSlotInfoPresent; + guint16 sysframeNumber; + guint16 slotNumber; + + /* Length of DL PDU or UL grant size in bytes */ + guint16 length; + +} mac_nr_info; + + +/*****************************************************************/ +/* UDP framing format */ +/* ----------------------- */ +/* Several people have asked about dissecting MAC by framing */ +/* PDUs over IP. A suggested format over UDP has been created */ +/* and implemented by this dissector, using the definitions */ +/* below. */ +/* */ +/* A heuristic dissector (enabled by a preference) will */ +/* recognise a signature at the beginning of these frames. */ +/*****************************************************************/ + + +/* Signature. Rather than try to define a port for this, or make the + port number a preference, frames will start with this string (with no + terminating NULL */ +#define MAC_NR_START_STRING "mac-nr" + +/* Fixed fields. This is followed by the following 3 mandatory fields: + - radioType (1 byte) + - direction (1 byte) + - rntiType (1 byte) + (where the allowed values are defined above */ + +/* Optional fields. Attaching this info to frames will allow you + to show you display/filter/plot/add-custom-columns on these fields, so should + be added if available. + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag) */ + +#define MAC_NR_RNTI_TAG 0x02 +/* 2 bytes, network order */ + +#define MAC_NR_UEID_TAG 0x03 +/* 2 bytes, network order */ + +#define MAC_NR_FRAME_SUBFRAME_TAG 0x04 +/* 2 bytes, deprecated, do not use it */ + +#define MAC_NR_PHR_TYPE2_OTHERCELL_TAG 0x05 +/* 1 byte, TRUE/FALSE */ + +#define MAC_NR_HARQID 0x06 +/* 1 byte */ + +#define MAC_NR_FRAME_SLOT_TAG 0x07 +/* 4 bytes, network order, SFN is stored in the 2 first bytes and slot number in the 2 last bytes */ + +/* MAC PDU. Following this tag comes the actual MAC PDU (there is no length, the PDU + continues until the end of the frame) */ +#define MAC_NR_PAYLOAD_TAG 0x01 + + +/* Type to store parameters for configuring LCID->RLC channel settings for DRB */ +/* Some are optional, and may not be seen (e.g. on reestablishment) */ +typedef struct nr_drb_mac_rlc_mapping_t +{ + gboolean active; + guint16 ueid; /* Mandatory */ + guint8 drbid; /* Mandatory */ + + gboolean lcid_present; + guint8 lcid; /* Part of LogicalChannelConfig - optional */ + gboolean rlcMode_present; + guint8 rlcMode; /* Part of RLC config - optional */ + + guint8 tempDirection; /* So know direction of next SN length... */ + + gboolean rlcUlSnLength_present; + guint8 rlcUlSnLength; /* Part of RLC config - optional */ + gboolean rlcDlSnLength_present; + guint8 rlcDlSnLength; /* Part of RLC config - optional */ +} nr_drb_mac_rlc_mapping_t; + +/* rlcMode */ +#define RLC_TM_MODE 1 +#define RLC_UM_MODE 2 +#define RLC_AM_MODE 4 + +/* bearerType */ +#define BEARER_TYPE_CCCH 1 +#define BEARER_TYPE_BCCH_BCH 2 +#define BEARER_TYPE_PCCH 3 +#define BEARER_TYPE_SRB 4 +#define BEARER_TYPE_DRB 5 +#define BEARER_TYPE_BCCH_DL_SCH 6 + +/* sequenceNumberLength */ +#define TM_SN_LENGTH_0_BITS 0 +#define UM_SN_LENGTH_6_BITS 6 +#define UM_SN_LENGTH_12_BITS 12 +#define AM_SN_LENGTH_12_BITS 12 +#define AM_SN_LENGTH_18_BITS 18 + +/* Info attached to each NR RLC frame */ +typedef struct rlc_nr_info +{ + guint8 rlcMode; + guint8 direction; + guint8 sequenceNumberLength; + guint8 bearerType; + guint8 bearerId; + guint16 ueid; + guint16 pduLength; +} rlc_nr_info; + +typedef struct nr_drb_rlc_pdcp_mapping_t +{ + gboolean active; + guint16 ueid; /* Mandatory */ + guint8 drbid; /* Mandatory */ + + gboolean pdcpUlSnLength_present; + guint8 pdcpUlSnLength; /* Part of PDCP config - optional */ + gboolean pdcpDlSnLength_present; + guint8 pdcpDlSnLength; /* Part of PDCP config - optional */ + gboolean pdcpUlSdap; + gboolean pdcpDlSdap; + gboolean pdcpIntegrityProtection; + gboolean pdcpCipheringDisabled; + +} nr_drb_rlc_pdcp_mapping_t; + +/* TODO: could probably merge this struct with above */ +typedef struct pdcp_ue_parameters { + guint32 id; + guint8 pdcp_sn_bits_ul; + guint8 pdcp_sn_bits_dl; + gboolean pdcp_sdap_ul; + gboolean pdcp_sdap_dl; + gboolean pdcp_integrity; + gboolean pdcp_ciphering_disabled; +} pdcp_bearer_parameters; + +/*****************************************************************/ +/* UDP framing format */ +/* ----------------------- */ +/* Several people have asked about dissecting RLC by framing */ +/* PDUs over IP. A suggested format over UDP has been defined */ +/* and implemented by this dissector, using the definitions */ +/* below. */ +/* */ +/* A heuristic dissector (enabled by a preference) will */ +/* recognise a signature at the beginning of these frames. */ +/*****************************************************************/ + + +/* Signature. Rather than try to define a port for this, or make the + port number a preference, frames will start with this string (with no + terminating NULL */ +#define RLC_NR_START_STRING "rlc-nr" + +/* Fixed field. This is followed by the following 2 mandatory field: + - rlcMode (1 byte) + - sequenceNumberLength (1 byte) + (where the allowed values are defined above) */ + +/* Optional fields. Attaching this info to frames will allow you + to show you display/filter/plot/add-custom-columns on these fields, so should + be added if available. + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag) */ + +#define RLC_NR_DIRECTION_TAG 0x02 +/* 1 byte */ + +#define RLC_NR_UEID_TAG 0x03 +/* 2 bytes, network order */ + +#define RLC_NR_BEARER_TYPE_TAG 0x04 +/* 1 byte */ + +#define RLC_NR_BEARER_ID_TAG 0x05 +/* 1 byte */ + +/* RLC PDU. Following this tag comes the actual RLC PDU (there is no length, the PDU + continues until the end of the frame) */ +#define RLC_NR_PAYLOAD_TAG 0x01 + +enum pdcp_nr_plane +{ + NR_SIGNALING_PLANE = 1, + NR_USER_PLANE = 2 +}; + +typedef enum NRBearerType +{ + Bearer_DCCH=1, + Bearer_BCCH_BCH=2, + Bearer_BCCH_DL_SCH=3, + Bearer_CCCH=4, + Bearer_PCCH=5, +} NRBearerType; + + +#define PDCP_NR_SN_LENGTH_12_BITS 12 +#define PDCP_NR_SN_LENGTH_18_BITS 18 + +#define PDCP_NR_UL_SDAP_HEADER_PRESENT 0x01 +#define PDCP_NR_DL_SDAP_HEADER_PRESENT 0x02 + +enum nr_security_integrity_algorithm_e { nia0, nia1, nia2, nia3 }; +enum nr_security_ciphering_algorithm_e { nea0, nea1, nea2, nea3, nea_disabled=999}; + +typedef struct pdcp_nr_security_info_t +{ + guint32 configuration_frame; + gboolean seen_next_ul_pdu; /* i.e. have we seen SecurityModeResponse */ + enum nr_security_integrity_algorithm_e integrity; + enum nr_security_ciphering_algorithm_e ciphering; + + /* Store previous settings so can revert if get SecurityModeFailure */ + guint32 previous_configuration_frame; + enum nr_security_integrity_algorithm_e previous_integrity; + enum nr_security_ciphering_algorithm_e previous_ciphering; +} pdcp_nr_security_info_t; + + +/*****************************************************************/ +/* UDP framing format */ +/* ----------------------- */ +/* Several people have asked about dissecting PDCP by framing */ +/* PDUs over IP. A suggested format over UDP has been defined */ +/* and implemented by this dissector, using the definitions */ +/* below. */ +/* */ +/* A heuristic dissector (enabled by a preference) will */ +/* recognise a signature at the beginning of these frames. */ +/* Until someone is using this format, suggestions for changes */ +/* are welcome. */ +/*****************************************************************/ + + +/* Signature. Rather than try to define a port for this, or make the + port number a preference, frames will start with this string (with no + terminating NULL */ +#define PDCP_NR_START_STRING "pdcp-nr" + +/* Fixed fields: + - plane (1 byte) */ + +/* Conditional field. This field is mandatory in case of User Plane PDCP PDU. + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag). The allowed values are defined above. */ + +#define PDCP_NR_SEQNUM_LENGTH_TAG 0x02 +/* 1 byte */ + +/* Optional fields. Attaching this info should be added if available. + The format is to have the tag, followed by the value (there is no length field, + it's implicit from the tag) */ + +#define PDCP_NR_DIRECTION_TAG 0x03 +/* 1 byte */ + +#define PDCP_NR_BEARER_TYPE_TAG 0x04 +/* 1 byte */ + +#define PDCP_NR_BEARER_ID_TAG 0x05 +/* 1 byte */ + +#define PDCP_NR_UEID_TAG 0x06 +/* 2 bytes, network order */ + +#define PDCP_NR_ROHC_COMPRESSION_TAG 0x07 +/* 0 byte */ + +/* N.B. The following ROHC values only have significance if rohc_compression + is in use for the current channel */ + +#define PDCP_NR_ROHC_IP_VERSION_TAG 0x08 +/* 1 byte */ + +#define PDCP_NR_ROHC_CID_INC_INFO_TAG 0x09 +/* 0 byte */ + +#define PDCP_NR_ROHC_LARGE_CID_PRES_TAG 0x0A +/* 0 byte */ + +#define PDCP_NR_ROHC_MODE_TAG 0x0B +/* 1 byte */ + +#define PDCP_NR_ROHC_RND_TAG 0x0C +/* 0 byte */ + +#define PDCP_NR_ROHC_UDP_CHECKSUM_PRES_TAG 0x0D +/* 0 byte */ + +#define PDCP_NR_ROHC_PROFILE_TAG 0x0E +/* 2 bytes, network order */ + +#define PDCP_NR_MACI_PRES_TAG 0x0F +/* 0 byte */ + +#define PDCP_NR_SDAP_HEADER_TAG 0x10 +/* 1 byte, bitmask with PDCP_NR_UL_SDAP_HEADER_PRESENT and/or PDCP_NR_DL_SDAP_HEADER_PRESENT */ + +#define PDCP_NR_CIPHER_DISABLED_TAG 0x11 +/* 0 byte */ + +/* PDCP PDU. Following this tag comes the actual PDCP PDU (there is no length, the PDU + continues until the end of the frame) */ +#define PDCP_NR_PAYLOAD_TAG 0x01 + + +/* Called by RRC, or other configuration protocols */ + +/* Function to configure ciphering & integrity algorithms */ +void set_pdcp_nr_security_algorithms(guint16 ueid, pdcp_nr_security_info_t *security_info); + +/* Function to indicate securityModeCommand did not complete */ +void set_pdcp_nr_security_algorithms_failed(guint16 ueid); + + +/* Called by external dissectors */ +void set_pdcp_nr_rrc_ciphering_key(guint16 ueid, const char *key); +void set_pdcp_nr_rrc_integrity_key(guint16 ueid, const char *key); +void set_pdcp_nr_up_ciphering_key(guint16 ueid, const char *key); +void set_pdcp_nr_up_integrity_key(guint16 ueid, const char *key); + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ +#endif diff --git a/openair2/UTIL/OSA/osa_defs.h b/openair2/UTIL/OSA/osa_defs.h index 3df350541f..e845315922 100644 --- a/openair2/UTIL/OSA/osa_defs.h +++ b/openair2/UTIL/OSA/osa_defs.h @@ -48,13 +48,18 @@ typedef enum { NAS_INT_ALG = 0x02, RRC_ENC_ALG = 0x03, RRC_INT_ALG = 0x04, - UP_ENC_ALG = 0x05 + UP_ENC_ALG = 0x05, + UP_INT_ALG = 0x06 } algorithm_type_dist_t; //int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB); +int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB); + int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, const uint8_t key[32], uint8_t **out); +int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, + const uint8_t key[32], uint8_t **out); //#define derive_key_nas_enc(aLGiD, kEY, kNAS) derive_key(NAS_ENC_ALG, aLGiD, kEY, kNAS) @@ -72,6 +77,19 @@ int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, #define derive_key_up_int(aLGiD, kEY, kNAS) \ derive_key(UP_INT_ALG, aLGiD, kEY, kNAS) +// 5G SA +#define nr_derive_key_rrc_enc(aLGiD, kEY, kRRC) \ + nr_derive_key(RRC_ENC_ALG, aLGiD, kEY, kRRC) + +#define nr_derive_key_rrc_int(aLGiD, kEY, kRRC) \ + nr_derive_key(RRC_INT_ALG, aLGiD, kEY, kRRC) + +#define nr_derive_key_up_enc(aLGiD, kEY, kUP) \ + nr_derive_key(UP_ENC_ALG, aLGiD, kEY, kUP) + +#define nr_derive_key_up_int(aLGiD, kEY, kUP) \ + nr_derive_key(UP_INT_ALG, aLGiD, kEY, kUP) + typedef struct { uint8_t *key; uint32_t key_length; diff --git a/openair2/UTIL/OSA/osa_internal.h b/openair2/UTIL/OSA/osa_internal.h index 1f5aab5df8..f4a70c7e95 100644 --- a/openair2/UTIL/OSA/osa_internal.h +++ b/openair2/UTIL/OSA/osa_internal.h @@ -36,6 +36,8 @@ #define FC_ALG_KEY_DER (0x15) #define FC_KASME_TO_CK (0x16) +#define NR_FC_ALG_KEY_DER (0x69) + #ifndef hton_int32 # define hton_int32(x) \ (((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | \ diff --git a/openair2/UTIL/OSA/osa_key_deriver.c b/openair2/UTIL/OSA/osa_key_deriver.c index 237592bd17..c02b999490 100644 --- a/openair2/UTIL/OSA/osa_key_deriver.c +++ b/openair2/UTIL/OSA/osa_key_deriver.c @@ -97,6 +97,36 @@ int derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, return 0; } + +int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, + const uint8_t key[32], uint8_t **out) +{ + uint8_t string[7]; + + /* FC */ + string[0] = NR_FC_ALG_KEY_DER; + + /* P0 = algorithm type distinguisher */ + string[1] = (uint8_t)(alg_type & 0xFF); + + /* L0 = length(P0) = 1 */ + string[2] = 0x00; + string[3] = 0x01; + + /* P1 */ + string[4] = alg_id; + + /* L1 = length(P1) = 1 */ + string[5] = 0x00; + string[6] = 0x01; + + kdf(string, 7, key, 32, out, 32); + // in NR, we use the last 16 bytes, ignoring the first 16 ones + memcpy(*out, *out+16, 16); + + return 0; +} + /* int derive_keNB(const uint8_t key[32], const uint32_t nas_count, uint8_t **keNB) { @@ -131,3 +161,27 @@ int derive_keNB(const uint8_t key[32], const uint32_t nas_count, uint8_t **keNB) return 0; } */ + +int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB) +{ + uint8_t *out; + uint8_t s[5]; + + /* FC is 0x1c (see 3gpp 33.401 annex A.15) */ + s[0] = 0x1c; + + /* put sk_counter */ + s[1] = (sk_counter >> 8) & 0xff; + s[2] = sk_counter & 0xff; + + /* put length of sk_counter (2) */ + s[3] = 0x00; + s[4] = 0x02; + + kdf(s, 5, keNB, 32, &out, 32); + + memcpy(skgNB, out, 32); + free(out); + + return 0; +} diff --git a/openair2/UTIL/OTG/otg_defs.h b/openair2/UTIL/OTG/otg_defs.h index 6c9944014f..af0260587f 100644 --- a/openair2/UTIL/OTG/otg_defs.h +++ b/openair2/UTIL/OTG/otg_defs.h @@ -34,13 +34,8 @@ # define __OTG_DEFS_H__ /* \brief To define the NUMBER_OF_eNB_MAX and MAX_MOBILES_PER_ENB */ -#if STANDALONE==1 - #include "openairinterface5g_limits.h" -#else - // impl_defs_top.h includes openairinterface5g_limits.h - #include "PHY/impl_defs_top.h" -#endif - +#include "openairinterface5g_limits.h" +#include #include "otg_config.h" /** diff --git a/openair2/UTIL/OTG/otg_kpi.c b/openair2/UTIL/OTG/otg_kpi.c index ac2fff89fe..c55aecf239 100644 --- a/openair2/UTIL/OTG/otg_kpi.c +++ b/openair2/UTIL/OTG/otg_kpi.c @@ -37,8 +37,8 @@ unsigned int start_log_GP=0; unsigned int start_log_GP_bg=0; unsigned int start_log_jitter=0; -#include"otg_kpi.h" -#include"otg_externs.h" +#include "otg_kpi.h" +#include "otg_externs.h" extern unsigned char NB_eNB_INST; extern uint16_t NB_UE_INST; diff --git a/openair2/UTIL/OTG/otg_rx_socket.h b/openair2/UTIL/OTG/otg_rx_socket.h index e7062aaf58..b0c6d1b364 100644 --- a/openair2/UTIL/OTG/otg_rx_socket.h +++ b/openair2/UTIL/OTG/otg_rx_socket.h @@ -32,7 +32,7 @@ #ifndef __OTG_RX_SOCKET_H__ #define __OTG_RX_SOCKET_H__ -#include"otg.h" +#include "otg.h" //-----------------------begin func proto------------------- diff --git a/openair2/UTIL/OTG/otg_tx_socket.c b/openair2/UTIL/OTG/otg_tx_socket.c index 073b9b6ddd..070e44f361 100644 --- a/openair2/UTIL/OTG/otg_tx_socket.c +++ b/openair2/UTIL/OTG/otg_tx_socket.c @@ -30,7 +30,7 @@ * \warning */ -#include"otg_tx_socket.h" +#include "otg_tx_socket.h" #include "otg_vars.h" diff --git a/openair2/UTIL/OTG/otg_tx_socket.h b/openair2/UTIL/OTG/otg_tx_socket.h index 17568244fa..1d2345c242 100644 --- a/openair2/UTIL/OTG/otg_tx_socket.h +++ b/openair2/UTIL/OTG/otg_tx_socket.h @@ -37,8 +37,8 @@ #include #include #include -#include"otg.h" -#include"otg_tx.h" +#include "otg.h" +#include "otg_tx.h" //-----------------------begin func proto------------------- diff --git a/openair2/UTIL/TRACE/fifo_printf.c b/openair2/UTIL/TRACE/fifo_printf.c deleted file mode 100644 index 2dc4da0637..0000000000 --- a/openair2/UTIL/TRACE/fifo_printf.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/* - * fifo_printf.c - * ------------------- - * AUTHOR : Lionel GAUTHIER - * COMPANY : EURECOM - * EMAIL : Lionel.Gauthier@eurecom.fr - * - */ -#include "rtos_header.h" -#include "platform.h" -#include "protocol_vars_extern.h" - -#include -#include -#include - - -#include "fifo_printf.h" - -#ifndef FIFO_PRINTF -//----------------------------------------------------------------------------- -int fifo_printf_null (const char *fmt, ...) -{ - return 0; -} -#else -static uint8_t fifo_printed_l1[FIFO_PRINTF_MAX_STRING_SIZE]; -static uint8_t fifo_printed_l2[FIFO_PRINTF_MAX_STRING_SIZE]; -//----------------------------------------------------------------------------- -void -fifo_printf_init (void) -{ - //----------------------------------------------------------------------------- - printk ("[TRACE] INIT\n"); - rtf_create (FIFO_PRINTF_L1_NO, FIFO_PRINTF_SIZE); - rtf_create (FIFO_PRINTF_L2_NO, FIFO_PRINTF_SIZE); -} - -//----------------------------------------------------------------------------- -void -fifo_printf_clean_up (void) -{ - //----------------------------------------------------------------------------- - rtf_destroy (FIFO_PRINTF_L1_NO); - rtf_destroy (FIFO_PRINTF_L2_NO); -} - -//----------------------------------------------------------------------------- -int -fifo_printf (const char *fmt, ...) -{ - //----------------------------------------------------------------------------- - int i; - va_list args; - - va_start (args, fmt); - - if (pthread_self () == &task_l1l) { - i = vsprintf (fifo_printed_l1, fmt, args); - va_end (args); - - /* perhaps we should discard old data instead */ - if (i > FIFO_PRINTF_MAX_STRING_SIZE) { - rt_printk ("[WCDMA] FIFO_PRINTF WROTE OUTSIDE ITS MEMORY BOUNDARY : ERRORS WILL OCCUR\n"); - } - - if (i <= 0) { - return 0; - } - - rtf_put (FIFO_PRINTF_L1_NO, fifo_printed_l1, i); - - return i; - } - - if (pthread_self () == &task_l2) { - i = vsprintf (fifo_printed_l2, fmt, args); - va_end (args); - - /* perhaps we should discard old data instead */ - if (i > FIFO_PRINTF_MAX_STRING_SIZE) { - rt_printk ("[WCDMA] FIFO_PRINTF WROTE OUTSIDE ITS MEMORY BOUNDARY : ERRORS WILL OCCUR\n"); - } - - if (i <= 0) { - return 0; - } - - rtf_put (FIFO_PRINTF_L2_NO, fifo_printed_l2, i); - - return i; - } - - return 0; -} -#endif diff --git a/openair2/UTIL/TRACE/fifo_printf.h b/openair2/UTIL/TRACE/fifo_printf.h deleted file mode 100644 index ce2702b19a..0000000000 --- a/openair2/UTIL/TRACE/fifo_printf.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*************************************************************************** - fifo_printf.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - ***************************************************************************/ -#ifndef __FIFO_PRINTF_H__ -# define __FIFO_PRINTF_H__ -# define FIFO_PRINTF_MAX_STRING_SIZE 500 -# define FIFO_PRINTF_L1_NO 63 -# define FIFO_PRINTF_L2_NO 62 -# define FIFO_PRINTF_SIZE 65536 -#endif diff --git a/openair2/UTIL/TRACE/print.h b/openair2/UTIL/TRACE/print.h deleted file mode 100644 index 72c43f20d4..0000000000 --- a/openair2/UTIL/TRACE/print.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*************************************************************************** - print.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - ***************************************************************************/ -#ifndef __PRINT_H__ -# define __PRINT_H__ -# define msg printf -#endif diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index bd77272747..38e6149ccd 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -115,10 +115,13 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa if (x2ap_enb_data_p != NULL) { /* some sanity check - to be refined at some point */ if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n"); - // Allow for a gracious exit when we kill first the gNB, then the eNB - //abort(); - return; + X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED?\n"); + if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN){ + RB_REMOVE(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data_p); + return; + } + + exit(1); } x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams; @@ -132,8 +135,20 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa DevAssert(x2ap_enb_data_p != NULL); dump_trees(); + /* gNB: exit if connection to eNB failed - to be modified if needed. + * We may want to try to connect over and over again until we succeed + * but the modifications to the code to get this behavior are complex. + * Exit on error is a simple solution that can be caught by a script + * for example. + */ + if (instance_p->cell_type == CELL_MACRO_GNB + && sctp_new_association_resp->sctp_state == SCTP_STATE_UNREACHABLE) { + X2AP_ERROR("association with eNB failed, is it running? If no, run it first. If yes, check IP addresses in your configuration file.\n"); + exit(1); + } + if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - X2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", + X2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", sctp_new_association_resp->sctp_state, instance, sctp_new_association_resp->ulp_cnx_id); @@ -159,7 +174,7 @@ static void x2ap_eNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind) { x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_enb_data_p; - printf("x2ap_eNB_handle_sctp_association_ind at 1 (called for instance %d)\n", instance); + printf("x2ap_eNB_handle_sctp_association_ind at 1 (called for instance %ld)\n", instance); dump_trees(); DevAssert(sctp_new_association_ind != NULL); instance_p = x2ap_eNB_get_instance(instance); @@ -207,7 +222,7 @@ int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p, sctp_init_t *sctp_init = NULL; DevAssert(instance_p != NULL); DevAssert(local_ip_addr != NULL); - message = itti_alloc_new_message (TASK_X2AP, SCTP_INIT_MSG_MULTI_REQ); + message = itti_alloc_new_message (TASK_X2AP, 0, SCTP_INIT_MSG_MULTI_REQ); sctp_init = &message->ittiMsg.sctp_init_multi; sctp_init->port = enb_port_for_X2C; sctp_init->ppid = X2AP_SCTP_PPID; @@ -241,7 +256,7 @@ static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_enb_data = NULL; DevAssert(instance_p != NULL); DevAssert(target_eNB_ip_address != NULL); - message = itti_alloc_new_message(TASK_X2AP, SCTP_NEW_ASSOCIATION_REQ_MULTI); + message = itti_alloc_new_message(TASK_X2AP, 0, SCTP_NEW_ASSOCIATION_REQ_MULTI); sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi; sctp_new_association_req->port = enb_port_for_X2C; sctp_new_association_req->ppid = X2AP_SCTP_PPID; @@ -286,7 +301,7 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, DevCheck(new_instance->tac == x2ap_register_eNB->tac, new_instance->tac, x2ap_register_eNB->tac, 0); DevCheck(new_instance->mcc == x2ap_register_eNB->mcc, new_instance->mcc, x2ap_register_eNB->mcc, 0); DevCheck(new_instance->mnc == x2ap_register_eNB->mnc, new_instance->mnc, x2ap_register_eNB->mnc, 0); - X2AP_WARN("eNB[%d] already registered\n", instance); + X2AP_WARN("eNB[%ld] already registered\n", instance); } else { new_instance = calloc(1, sizeof(x2ap_eNB_instance_t)); DevAssert(new_instance != NULL); @@ -305,17 +320,26 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, x2ap_id_manager_init(&new_instance->id_manager); x2ap_timers_init(&new_instance->timers, x2ap_register_eNB->t_reloc_prep, - x2ap_register_eNB->tx2_reloc_overall); + x2ap_register_eNB->tx2_reloc_overall, + x2ap_register_eNB->t_dc_prep, + x2ap_register_eNB->t_dc_overall); for (int i = 0; i< x2ap_register_eNB->num_cc; i++) { - new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i]; - new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i]; + if(new_instance->cell_type == CELL_MACRO_GNB){ + new_instance->nr_band[i] = x2ap_register_eNB->nr_band[i]; + new_instance->tdd_nRARFCN[i] = x2ap_register_eNB->nrARFCN[i]; + } + else{ + new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i]; + new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i]; + new_instance->fdd_earfcn_DL[i] = x2ap_register_eNB->fdd_earfcn_DL[i]; + new_instance->fdd_earfcn_UL[i] = x2ap_register_eNB->fdd_earfcn_UL[i]; + } + new_instance->uplink_frequency_offset[i] = x2ap_register_eNB->uplink_frequency_offset[i]; new_instance->Nid_cell[i] = x2ap_register_eNB->Nid_cell[i]; new_instance->N_RB_DL[i] = x2ap_register_eNB->N_RB_DL[i]; new_instance->frame_type[i] = x2ap_register_eNB->frame_type[i]; - new_instance->fdd_earfcn_DL[i] = x2ap_register_eNB->fdd_earfcn_DL[i]; - new_instance->fdd_earfcn_UL[i] = x2ap_register_eNB->fdd_earfcn_UL[i]; } DevCheck(x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS, @@ -330,7 +354,7 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, new_instance->enb_port_for_X2C = x2ap_register_eNB->enb_port_for_X2C; /* Add the new instance to the list of eNB (meaningfull in virtual mode) */ x2ap_eNB_insert_new_instance(new_instance); - X2AP_INFO("Registered new eNB[%d] and %s eNB id %u\n", + X2AP_INFO("Registered new eNB[%ld] and %s eNB id %u\n", instance, x2ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home", x2ap_register_eNB->eNB_id); @@ -341,7 +365,7 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, return; } - X2AP_INFO("eNB[%d] eNB id %u acting as a listner (server)\n", + X2AP_INFO("eNB[%ld] eNB id %u acting as a listner (server)\n", instance, x2ap_register_eNB->eNB_id); } } @@ -368,7 +392,7 @@ void x2ap_eNB_handle_sctp_init_msg_multi_cnf( /* Trying to connect to the provided list of eNB ip address */ for (index = 0; index < instance->nb_x2; index++) { - X2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n", + X2AP_INFO("eNB[%ld] eNB id %u acting as an initiator (client)\n", instance_id, instance->eNB_id); x2ap_eNB_register_eNB(instance, &instance->target_enb_x2_ip_address[index], @@ -476,7 +500,10 @@ void x2ap_eNB_handle_sgNB_add_req(instance_t instance, } /* id_source is ue_id, id_target is unknown yet */ x2ap_set_ids(id_manager, ue_id, x2ap_ENDC_sgnb_addition_req->rnti, ue_id, -1); - x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_PREPARE); + x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_ENB_PREPARE); + x2ap_set_dc_prep_timer(id_manager, ue_id, + x2ap_timer_get_tti(&instance_p->timers)); + x2ap_id_set_target(id_manager, ue_id, x2ap_eNB_data); x2ap_eNB_generate_ENDC_x2_SgNB_addition_request(instance_p, x2ap_ENDC_sgnb_addition_req, x2ap_eNB_data, ue_id); @@ -498,9 +525,6 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance, x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *target; int ue_id; - /*int source_assoc_id = x2ap_ENDC_sgnb_addition_req_ACK->source_assoc_id; - int id_source; - int id_target;*/ instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); @@ -514,22 +538,15 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance, X2AP_ERROR("could not allocate a new X2AP UE ID\n"); exit(1); } - /* id_source is ue_id, id_target is unknown yet */ - x2ap_set_ids(id_manager, ue_id, x2ap_ENDC_sgnb_addition_req_ACK->rnti, ue_id, - x2ap_ENDC_sgnb_addition_req_ACK->MeNB_ue_x2_id); - x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_SOURCE_OVERALL); - - - /*target = x2ap_get_eNB(NULL, source_assoc_id, 0); - DevAssert(target != NULL);*/ - - // rnti is a new information, save it - - /*ue_id = x2ap_handover_req_ack->x2_id_target; - id_source = x2ap_id_get_id_source(&instance_p->id_manager, ue_id); - id_target = ue_id; - x2ap_set_ids(&instance_p->id_manager, ue_id, x2ap_handover_req_ack->rnti, id_source, id_target);*/ - + /* id_Source is MeNB_ue_x2_id, id_target is rnti (rnti is SgNB_ue_x2_id) */ + x2ap_set_ids(id_manager, ue_id, + x2ap_ENDC_sgnb_addition_req_ACK->SgNB_ue_x2_id, + x2ap_ENDC_sgnb_addition_req_ACK->MeNB_ue_x2_id, + x2ap_ENDC_sgnb_addition_req_ACK->SgNB_ue_x2_id); + x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_GNB_OVERALL); + x2ap_set_dc_overall_timer(id_manager, ue_id, + x2ap_timer_get_tti(&instance_p->timers)); + x2ap_id_set_target(id_manager, ue_id, target); x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK(instance_p, target, x2ap_ENDC_sgnb_addition_req_ACK, ue_id); @@ -540,27 +557,24 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance, * @param : IN instance, IN x2ap_reconf_complete **/ static -void x2ap_eNB_trigger_sgnb_reconfiguration_complete(instance_t instance, - x2ap_ENDC_reconf_complete_t *x2ap_reconf_complete) +void x2ap_eNB_trigger_sgnb_reconfiguration_complete(instance_t instance, + x2ap_ENDC_reconf_complete_t *x2ap_reconf_complete) { - x2ap_eNB_instance_t *instance_p = NULL; - x2ap_eNB_data_t *target = NULL; - int id_source = -1; - int id_target = -1; - LTE_PhysCellId_t target_pci; - + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *target; + int id_source; + int id_target; + instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); DevAssert(x2ap_reconf_complete != NULL); - - target_pci = x2ap_reconf_complete->target_physCellId; - target = x2ap_is_eNB_pci_in_list(target_pci); + + target = x2ap_get_eNB(NULL,x2ap_reconf_complete->gnb_x2_assoc_id, 0); DevAssert(target != NULL); - + id_source = x2ap_reconf_complete->MeNB_ue_x2_id; id_target = x2ap_reconf_complete->SgNB_ue_x2_id; x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(instance_p, target, id_source, id_target); - } @@ -589,6 +603,34 @@ void x2ap_eNB_ue_context_release(instance_t instance, x2ap_release_id(&instance_p->id_manager, ue_id); } +static +void x2ap_eNB_handle_sgNB_release_request(instance_t instance, + x2ap_ENDC_sgnb_release_request_t *x2ap_release_req) +{ + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *target; + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + DevAssert(x2ap_release_req != NULL); + + if (x2ap_release_req->rnti == -1 || + x2ap_release_req->assoc_id == -1) { + X2AP_WARN("x2ap_eNB_handle_sgNB_release_request: bad rnti or assoc_id, do not send release request to gNB\n"); + return; + } + + target = x2ap_get_eNB(NULL, x2ap_release_req->assoc_id, 0); + DevAssert(target != NULL); + + /* id_source is not used by oai's gNB so it's not big deal. For + * interoperability with other gNBs things may need to be refined. + */ + x2ap_eNB_generate_ENDC_x2_SgNB_release_request(instance_p, target, + 0, x2ap_release_req->rnti, + x2ap_release_req->cause); +} + void *x2ap_task(void *arg) { MessageDef *received_msg = NULL; int result; @@ -606,61 +648,67 @@ void *x2ap_task(void *arg) { break; case X2AP_SUBFRAME_PROCESS: - x2ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg)); + x2ap_check_timers(ITTI_MSG_DESTINATION_INSTANCE(received_msg)); break; case X2AP_REGISTER_ENB_REQ: - x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_handle_register_eNB(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &X2AP_REGISTER_ENB_REQ(received_msg)); break; case X2AP_HANDOVER_REQ: - x2ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_handle_handover_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &X2AP_HANDOVER_REQ(received_msg)); break; case X2AP_HANDOVER_REQ_ACK: - x2ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_handle_handover_req_ack(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &X2AP_HANDOVER_REQ_ACK(received_msg)); break; case X2AP_UE_CONTEXT_RELEASE: - x2ap_eNB_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_ue_context_release(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &X2AP_UE_CONTEXT_RELEASE(received_msg)); break; case X2AP_ENDC_SGNB_ADDITION_REQ: - x2ap_eNB_handle_sgNB_add_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_handle_sgNB_add_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &X2AP_ENDC_SGNB_ADDITION_REQ(received_msg)); break; case X2AP_ENDC_SGNB_ADDITION_REQ_ACK: - x2ap_gNB_trigger_sgNB_add_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_gNB_trigger_sgNB_add_req_ack(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &X2AP_ENDC_SGNB_ADDITION_REQ_ACK(received_msg)); LOG_I(X2AP, "Received elements for X2AP_ENDC_SGNB_ADDITION_REQ_ACK \n"); break; - case X2AP_ENDC_SGNB_RECONF_COMPLETE: - x2ap_eNB_trigger_sgnb_reconfiguration_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg), - &X2AP_ENDC_SGNB_RECONF_COMPLETE(received_msg)); - break; + case X2AP_ENDC_SGNB_RECONF_COMPLETE: + x2ap_eNB_trigger_sgnb_reconfiguration_complete(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &X2AP_ENDC_SGNB_RECONF_COMPLETE(received_msg)); + break; + + case X2AP_ENDC_SGNB_RELEASE_REQUEST: + x2ap_eNB_handle_sgNB_release_request(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &X2AP_ENDC_SGNB_RELEASE_REQUEST(received_msg)); + break; + case SCTP_INIT_MSG_MULTI_CNF: - x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_init_msg_multi_cnf); break; case SCTP_NEW_ASSOCIATION_RESP: - x2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_NEW_ASSOCIATION_IND: - x2ap_eNB_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_handle_sctp_association_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_ind); break; case SCTP_DATA_IND: - x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + x2ap_eNB_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c index 3762bc06dc..6d7897bf14 100644 --- a/openair2/X2AP/x2ap_eNB_decoder.c +++ b/openair2/X2AP/x2ap_eNB_decoder.c @@ -69,6 +69,14 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu) X2AP_INFO("X2AP_ProcedureCode_id_sgNBReconfigurationCompletion message!\n"); break; + case X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease: + X2AP_INFO("X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease message!\n"); + break; + + case X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease: + X2AP_INFO("X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease message!\n"); + break; + default: X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage.procedureCode); @@ -103,6 +111,10 @@ static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu) X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n"); break; + case X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease: + X2AP_INFO("meNBinitiatedSgNBRelease successful outcome!\n"); + break; + default: X2AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n", (int)pdu->choice.successfulOutcome.procedureCode); diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h index 6ab62ebf98..063302d03a 100644 --- a/openair2/X2AP/x2ap_eNB_defs.h +++ b/openair2/X2AP/x2ap_eNB_defs.h @@ -119,6 +119,8 @@ typedef struct x2ap_eNB_data_s { /* Nid cells */ uint32_t Nid_cell[MAX_NUM_CCs]; int num_cc; + /*Frequency band of NR neighbor cell supporting ENDC NSA */ + uint32_t servedNrCell_band[MAX_NUM_CCs]; /* Only meaningfull in virtual mode */ struct x2ap_eNB_instance_s *x2ap_eNB_instance; @@ -177,6 +179,7 @@ typedef struct x2ap_eNB_instance_s { uint32_t specialSubframe[MAX_NUM_CCs]; //#ifdef Rel15 + int32_t nr_band[MAX_NUM_CCs]; uint32_t tdd_nRARFCN[MAX_NUM_CCs]; int16_t nr_SCS[MAX_NUM_CCs]; //#endif diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c index a96fa14f48..7c3a89e7f4 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.c +++ b/openair2/X2AP/x2ap_eNB_generate_messages.c @@ -39,7 +39,6 @@ #include "x2ap_ids.h" #include "x2ap_eNB_itti_messaging.h" -#include "X2AP_SupportedSULFreqBandItem.h" #include "msc.h" #include "assertions.h" @@ -1236,7 +1235,6 @@ int x2ap_gNB_generate_ENDC_x2_setup_request( X2AP_En_gNB_ENDCX2SetupReqIEs_t *ie_GNB_ENDC; X2AP_PLMN_Identity_t *plmn; ServedNRcellsENDCX2ManagementList__Member *servedCellMember; - X2AP_SupportedSULFreqBandItem_t *SULFreqBandItem; uint8_t *buffer; uint32_t len; @@ -1284,8 +1282,8 @@ MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length ie_GNB_ENDC->value.present = X2AP_En_gNB_ENDCX2SetupReqIEs__value_PR_ServedNRcellsENDCX2ManagementList; { - for (int i = 0; inum_cc; i++){ - servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)calloc(1,sizeof(ServedNRcellsENDCX2ManagementList__Member)); + for (int i = 0; inum_cc; i++){ + servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)calloc(1,sizeof(ServedNRcellsENDCX2ManagementList__Member)); { servedCellMember->servedNRCellInfo.nrpCI = instance_p->Nid_cell[i]; @@ -1299,60 +1297,66 @@ MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length NR_FIVEGS_TAC_ID_TO_BIT_STRING(instance_p->tac, servedCellMember->servedNRCellInfo.fiveGS_TAC); X2AP_INFO("TAC: %d -> %02x%02x%02x\n", instance_p->tac, - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t)); { MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn); ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.broadcastPLMNs.list, plmn); } - - if (instance_p->frame_type[i] == TDD) { + if (instance_p->frame_type[i] == TDD) { X2AP_FreqBandNrItem_t *freq_band; servedCellMember->servedNRCellInfo.nrModeInfo.present = X2AP_ServedNRCell_Information__nrModeInfo_PR_tdd; - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.nRARFCN = 0; //instance_p->tdd_nRARFCN[i]; + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.nRARFCN = instance_p->tdd_nRARFCN[i]; /* addition of Frequency Band List */ freq_band = calloc(1, sizeof(X2AP_FreqBandNrItem_t)); if (freq_band == NULL) exit(1); - freq_band->freqBandIndicatorNr = 1; /* TODO: put correct value */ - - SULFreqBandItem = calloc(1, sizeof(X2AP_SupportedSULFreqBandItem_t)); - SULFreqBandItem->freqBandIndicatorNr=80; /* TODO: put correct value */ - ASN_SEQUENCE_ADD(&freq_band->supportedSULBandList.list, SULFreqBandItem); + freq_band->freqBandIndicatorNr = instance_p->nr_band[i]; ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr, freq_band); switch (instance_p->N_RB_DL[i]) { - case 50: - //This is not correct. Just to be able to test X2 only using an eNB instead of gNB - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb51; + case 24: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb24; + break; + case 32: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb32; + break; + case 66: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb66; + break; + case 93 : + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb93; + break; + case 106: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb106; + break; + case 121: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb121; + break; + case 217: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb217; + break; + case 273: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb273; + break; + /*More cases to be added */ + default: + AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL"); break; - case 93 : - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb93; - break; - case 106: - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb106; - break; - case 121: - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb121; - break; - /*More cases to be added */ - default: - AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL"); - break; - } - } + } + } else { AssertFatal(0,"ENDC_X2Setuprequest not supported for FDD!"); } - /*Don't know where to extract the value of measurementTimingConfiguration from. Set it to 0 for now */ - INT8_TO_OCTET_STRING(0, &servedCellMember->servedNRCellInfo.measurementTimingConfiguration); + /*Don't know where to extract the value of measurementTimingConfiguration from. Set it to 0 for now */ + INT8_TO_OCTET_STRING(0, &servedCellMember->servedNRCellInfo.measurementTimingConfiguration); } ASN_SEQUENCE_ADD(&ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list, servedCellMember); - } } + } ASN_SEQUENCE_ADD(&ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_en_gNB.list, ie_GNB_ENDC); @@ -1438,7 +1442,7 @@ int x2ap_eNB_generate_ENDC_x2_setup_response( } if (instance_p->frame_type[i] == FDD) { - servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD; servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i]; servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i]; switch (instance_p->N_RB_DL[i]) { @@ -1472,12 +1476,98 @@ int x2ap_eNB_generate_ENDC_x2_setup_response( } } else { - AssertFatal(0,"X2Setupresponse not supported for TDD!"); + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_tDD; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.eARFCN = instance_p->fdd_earfcn_DL[i]; + + switch (instance_p->subframeAssignment[i]) { + case 0: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa0; + break; + case 1: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa1; + break; + case 2: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa2; + break; + case 3: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa3; + break; + case 4: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa4; + break; + case 5: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa5; + break; + case 6: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa6; + break; + default: + AssertFatal(0,"Failed: Check value for subframeAssignment"); + break; + } + switch (instance_p->specialSubframe[i]) { + case 0: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp0; + break; + case 1: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp1; + break; + case 2: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp2; + break; + case 3: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp3; + break; + case 4: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp4; + break; + case 5: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp5; + break; + case 6: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp6; + break; + case 7: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp7; + break; + case 8: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp8; + break; + default: + AssertFatal(0,"Failed: Check value for subframeAssignment"); + break; + } + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.cyclicPrefixDL=X2AP_CyclicPrefixDL_normal; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.cyclicPrefixUL=X2AP_CyclicPrefixUL_normal; + + switch (instance_p->N_RB_DL[i]) { + case 6: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6; + break; + case 15: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15; + break; + case 25: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25; + break; + case 50: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50; + break; + case 75: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75; + break; + case 100: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100; + break; + default: + AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL"); + break; + } } } - ASN_SEQUENCE_ADD(&ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list, servedCellMember); + ASN_SEQUENCE_ADD(&ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list, servedCellMember); } - } + } ASN_SEQUENCE_ADD(&ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_eNB.list, ie_ENB_ENDC); @@ -1588,7 +1678,7 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_addition_request( for (int i=0;iid = X2AP_ProtocolIE_ID_id_E_RABs_ToBeAdded_SgNBAddReq_Item; - e_RABS_ToBeAdded_SgNBAddReq_ItemIEs->criticality = X2AP_Criticality_ignore; + e_RABS_ToBeAdded_SgNBAddReq_ItemIEs->criticality = X2AP_Criticality_reject; e_RABS_ToBeAdded_SgNBAddReq_ItemIEs->value.present = X2AP_E_RABs_ToBeAdded_SgNBAddReq_ItemIEs__value_PR_E_RABs_ToBeAdded_SgNBAddReq_Item; e_RABS_ToBeAdded_SgNBAddReq_Item = &e_RABS_ToBeAdded_SgNBAddReq_ItemIEs->value.choice.E_RABs_ToBeAdded_SgNBAddReq_Item; { @@ -1668,8 +1758,6 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in uint32_t len; int ret = 0; - int MeNB_UE_X2AP_id = x2ap_sgnb_addition_req_ACK->MeNB_ue_x2_id; - int SgNB_UE_X2AP_id = ue_id; int e_rabs_admitted_tobeadded = x2ap_sgnb_addition_req_ACK->nb_e_rabs_admitted_tobeadded; long int pDCPatSgNB = X2AP_EN_DC_ResourceConfiguration__pDCPatSgNB_present; long int mCGresources = X2AP_EN_DC_ResourceConfiguration__mCGresources_not_present; @@ -1694,7 +1782,7 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; ie->criticality= X2AP_Criticality_reject; ie->value.present = X2AP_SgNBAdditionRequestAcknowledge_IEs__value_PR_UE_X2AP_ID; - ie->value.choice.UE_X2AP_ID = MeNB_UE_X2AP_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id); + ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_source(&instance_p->id_manager, ue_id); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); // SgNB_UE_X2AP_id @@ -1702,7 +1790,7 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID; ie->criticality= X2AP_Criticality_reject; ie->value.present = X2AP_SgNBAdditionRequestAcknowledge_IEs__value_PR_SgNB_UE_X2AP_ID; - ie->value.choice.UE_X2AP_ID = SgNB_UE_X2AP_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id); + ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_target(&instance_p->id_manager, ue_id); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ie = (X2AP_SgNBAdditionRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBAdditionRequestAcknowledge_IEs_t)); @@ -1792,7 +1880,7 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete( ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; ie->criticality= X2AP_Criticality_reject; ie->value.present = X2AP_SgNBReconfigurationComplete_IEs__value_PR_UE_X2AP_ID; - ie->value.choice.UE_X2AP_ID = ue_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id); + ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_source(&instance_p->id_manager, ue_id); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ie = (X2AP_SgNBReconfigurationComplete_IEs_t *)calloc(1, sizeof(X2AP_SgNBReconfigurationComplete_IEs_t)); @@ -1821,3 +1909,226 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete( return ret; } + +int x2ap_eNB_generate_ENDC_x2_SgNB_release_request( + x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int x2_id_source, int x2_id_target, x2ap_cause_t cause) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_SgNBReleaseRequest_t *out; + X2AP_SgNBReleaseRequest_IEs_t *ie; + + uint8_t *buffer; + uint32_t len; + int ret = 0; + + DevAssert(instance_p != NULL); + DevAssert(x2ap_eNB_data_p != NULL); + + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease; + pdu.choice.initiatingMessage.criticality = X2AP_Criticality_ignore; + pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_SgNBReleaseRequest; + out = &pdu.choice.initiatingMessage.value.choice.SgNBReleaseRequest; + + ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; + ie->criticality= X2AP_Criticality_reject; + ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_UE_X2AP_ID; + ie->value.choice.UE_X2AP_ID = x2_id_source; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2_id_target != -1) { + ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID; + ie->criticality= X2AP_Criticality_reject; + ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_SgNB_UE_X2AP_ID; + ie->value.choice.SgNB_UE_X2AP_ID = x2_id_target; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_Cause; + ie->criticality= X2AP_Criticality_ignore; + ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_Cause; + switch (cause) { + case X2AP_CAUSE_T_DC_PREP_TIMEOUT: + ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork; + ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_tDCprep_expiry; + break; + case X2AP_CAUSE_RADIO_CONNECTION_WITH_UE_LOST: + ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork; + ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_radio_connection_with_UE_lost; + break; + default: + X2AP_ERROR("%s: unhandled cause %d\n", __FUNCTION__, cause); + exit(1); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode ENDC X2 SgNB_release_request message\n"); + return -1; + } + + x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0); + + return ret; +} + +int x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge( + x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int menb_ue_x2ap_id, int sgnb_ue_x2ap_id) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_SgNBReleaseRequestAcknowledge_t *out; + X2AP_SgNBReleaseRequestAcknowledge_IEs_t *ie; + + uint8_t *buffer; + uint32_t len; + int ret = 0; + + DevAssert(instance_p != NULL); + DevAssert(x2ap_eNB_data_p != NULL); + + x2ap_eNB_data_p->state = X2AP_ENB_STATE_WAITING; + + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease; + pdu.choice.successfulOutcome.criticality = X2AP_Criticality_ignore; + pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_SgNBReleaseRequestAcknowledge; + out = &pdu.choice.successfulOutcome.value.choice.SgNBReleaseRequestAcknowledge; + + ie = (X2AP_SgNBReleaseRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequestAcknowledge_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; + ie->criticality= X2AP_Criticality_ignore; + ie->value.present = X2AP_SgNBReleaseRequestAcknowledge_IEs__value_PR_UE_X2AP_ID; + ie->value.choice.UE_X2AP_ID = menb_ue_x2ap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + ie = (X2AP_SgNBReleaseRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequestAcknowledge_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID; + ie->criticality= X2AP_Criticality_ignore; + ie->value.present = X2AP_SgNBReleaseRequestAcknowledge_IEs__value_PR_SgNB_UE_X2AP_ID; + ie->value.choice.SgNB_UE_X2AP_ID = sgnb_ue_x2ap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode ENDC X2 SgNB Release Request Acknowledge\n"); + return -1; + } + + x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0); + + return ret; +} + +int x2ap_eNB_generate_ENDC_x2_SgNB_release_required( + x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int x2_id_source, int x2_id_target, x2ap_cause_t cause) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_SgNBReleaseRequired_t *out; + X2AP_SgNBReleaseRequired_IEs_t *ie; + + uint8_t *buffer; + uint32_t len; + int ret = 0; + + DevAssert(instance_p != NULL); + DevAssert(x2ap_eNB_data_p != NULL); + + /* Prepare the X2AP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease; + pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_SgNBReleaseRequired; + out = &pdu.choice.initiatingMessage.value.choice.SgNBReleaseRequired; + + ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; + ie->criticality= X2AP_Criticality_reject; + ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_UE_X2AP_ID; + ie->value.choice.UE_X2AP_ID = x2_id_source; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID; + ie->criticality= X2AP_Criticality_reject; + ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_SgNB_UE_X2AP_ID; + ie->value.choice.SgNB_UE_X2AP_ID = x2_id_target; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_Cause; + ie->criticality= X2AP_Criticality_ignore; + ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_Cause; + switch (cause) { + case X2AP_CAUSE_T_DC_OVERALL_TIMEOUT: + ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork; + ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_tDCoverall_expiry; + break; + default: + X2AP_ERROR("%s: unhandled cause %d\n", __FUNCTION__, cause); + exit(1); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode ENDC X2 SgNB_release_request message\n"); + return -1; + } + + x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0); + + return ret; +} + +int x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm( + x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int menb_ue_x2ap_id, int sgnb_ue_x2ap_id) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_SgNBReleaseConfirm_t *out; + X2AP_SgNBReleaseConfirm_IEs_t *ie; + + uint8_t *buffer; + uint32_t len; + int ret = 0; + + DevAssert(instance_p != NULL); + DevAssert(x2ap_eNB_data_p != NULL); + + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease; + pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject; + pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_SgNBReleaseConfirm; + out = &pdu.choice.successfulOutcome.value.choice.SgNBReleaseConfirm; + + ie = (X2AP_SgNBReleaseConfirm_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseConfirm_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; + ie->criticality= X2AP_Criticality_ignore; + ie->value.present = X2AP_SgNBReleaseConfirm_IEs__value_PR_UE_X2AP_ID; + ie->value.choice.UE_X2AP_ID = menb_ue_x2ap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + ie = (X2AP_SgNBReleaseConfirm_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseConfirm_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID; + ie->criticality= X2AP_Criticality_ignore; + ie->value.present = X2AP_SgNBReleaseConfirm_IEs__value_PR_SgNB_UE_X2AP_ID; + ie->value.choice.SgNB_UE_X2AP_ID = sgnb_ue_x2ap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode ENDC X2 SgNB Release Request Acknowledge\n"); + return -1; + } + + x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0); + + return ret; +} diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.h b/openair2/X2AP/x2ap_eNB_generate_messages.h index 3dfccc0e52..a920020b81 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.h +++ b/openair2/X2AP/x2ap_eNB_generate_messages.h @@ -77,4 +77,16 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete( x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, int ue_id, int SgNB_ue_id); +int x2ap_eNB_generate_ENDC_x2_SgNB_release_request(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int x2_id_source, int x2_id_target, x2ap_cause_t cause); + +int x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int menb_ue_x2ap_id, int sgnb_ue_x2ap_id); + +int x2ap_eNB_generate_ENDC_x2_SgNB_release_required(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int x2_id_source, int x2_id_target, x2ap_cause_t cause); + +int x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + int menb_ue_x2ap_id, int sgnb_ue_x2ap_id); + #endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */ diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index 1c6c98cd81..f71229f066 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -44,6 +44,7 @@ #include "msc.h" #include "assertions.h" #include "conversions.h" +#include "X2AP_FreqBandNrItem.h" static int x2ap_eNB_handle_x2_setup_request (instance_t instance, @@ -56,6 +57,17 @@ int x2ap_eNB_handle_x2_setup_response (instance_t instance, uint32_t stream, X2AP_X2AP_PDU_t *pdu); static +int x2ap_eNB_handle_x2_reset_request (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); +static +int x2ap_eNB_handle_x2_reset_response (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + +static int x2ap_eNB_handle_x2_setup_failure (instance_t instance, uint32_t assoc_id, uint32_t stream, @@ -132,6 +144,29 @@ int x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete (instance_t instance, uint32_t stream, X2AP_X2AP_PDU_t *pdu); +static +int x2ap_gNB_handle_ENDC_sGNB_release_request(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + +static +int x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + +static +int x2ap_gNB_handle_ENDC_sGNB_release_required(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + +static +int x2ap_gNB_handle_ENDC_sGNB_release_confirm(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); /* Handlers matrix. Only eNB related procedure present here. Placement of callback functions according to X2AP_ProcedureCode.h */ x2ap_message_decoded_callback x2ap_messages_callback[][3] = { @@ -142,7 +177,7 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = { { 0, 0, 0 }, /* snStatusTransfer */ { x2ap_eNB_handle_ue_context_release, 0, 0 }, /* uEContextRelease */ { x2ap_eNB_handle_x2_setup_request, x2ap_eNB_handle_x2_setup_response, x2ap_eNB_handle_x2_setup_failure }, /* x2Setup */ - { 0, 0, 0 }, /* reset */ + { x2ap_eNB_handle_x2_reset_request, x2ap_eNB_handle_x2_reset_response, 0 }, /* reset */ { 0, 0, 0 }, /* eNBConfigurationUpdate */ { 0, 0, 0 }, /* resourceStatusReportingInitiation */ { 0, 0, 0 }, /* resourceStatusReporting */ @@ -166,8 +201,9 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = { { x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete, 0, 0 }, /*X2AP_ProcedureCode_id_sgNBReconfigurationCompletion*/ { 0, 0, 0 }, { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, + { x2ap_gNB_handle_ENDC_sGNB_release_request, x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge, 0 }, /* meNBinitiatedSgNBRelease */ + { x2ap_gNB_handle_ENDC_sGNB_release_required, x2ap_gNB_handle_ENDC_sGNB_release_confirm, 0 }, /* sgNBinitiatedSgNBRelease */ + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, @@ -205,7 +241,7 @@ void x2ap_handle_x2_setup_message(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data if (instance_p->x2_target_enb_associated_nb == 0) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_X2AP, X2AP_DEREGISTERED_ENB_IND); + message_p = itti_alloc_new_message(TASK_X2AP, 0, X2AP_DEREGISTERED_ENB_IND); X2AP_DEREGISTERED_ENB_IND(message_p).nb_x2 = 0; itti_send_msg_to_task(TASK_ENB_APP, instance_p->instance, message_p); } @@ -225,7 +261,7 @@ void x2ap_handle_x2_setup_message(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data if (instance_p->x2_target_enb_pending_nb == 0) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_X2AP, X2AP_REGISTER_ENB_CNF); + message_p = itti_alloc_new_message(TASK_X2AP, 0, X2AP_REGISTER_ENB_CNF); X2AP_REGISTER_ENB_CNF(message_p).nb_x2 = instance_p->x2_target_enb_associated_nb; itti_send_msg_to_task(TASK_ENB_APP, instance_p->instance, message_p); } @@ -455,7 +491,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, return -1; } - msg = itti_alloc_new_message(TASK_X2AP, X2AP_SETUP_REQ); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_SETUP_REQ); X2AP_SETUP_REQ(msg).num_cc = ie->value.choice.ServedCells.list.count; @@ -476,6 +512,164 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data); } +const char *X2AP_ResetRequest_str[2]={"X2AP_ResetRequest_IEs__value_PR_Cause","X2AP_ResetRequest_IEs__value_PR_InterfaceInstanceIndication"}; +const char *X2AP_case_str_radio[50]={"X2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons", + "X2AP_CauseRadioNetwork_time_critical_handover", + "X2AP_CauseRadioNetwork_resource_optimisation_handover", + "X2AP_CauseRadioNetwork_reduce_load_in_serving_cell", + "X2AP_CauseRadioNetwork_partial_handover", + "X2AP_CauseRadioNetwork_unknown_new_eNB_UE_X2AP_ID", + "X2AP_CauseRadioNetwork_unknown_old_eNB_UE_X2AP_ID", + "X2AP_CauseRadioNetwork_unknown_pair_of_UE_X2AP_ID", + "X2AP_CauseRadioNetwork_ho_target_not_allowed", + "X2AP_CauseRadioNetwork_tx2relocoverall_expiry", + "X2AP_CauseRadioNetwork_trelocprep_expiry", + "X2AP_CauseRadioNetwork_cell_not_available", + "X2AP_CauseRadioNetwork_no_radio_resources_available_in_target_cell", + "X2AP_CauseRadioNetwork_invalid_MME_GroupID", + "X2AP_CauseRadioNetwork_unknown_MME_Code", + "X2AP_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported", + "X2AP_CauseRadioNetwork_reportCharacteristicsEmpty", + "X2AP_CauseRadioNetwork_noReportPeriodicity", + "X2AP_CauseRadioNetwork_existingMeasurementID", + "X2AP_CauseRadioNetwork_unknown_eNB_Measurement_ID", + "X2AP_CauseRadioNetwork_measurement_temporarily_not_available", + "X2AP_CauseRadioNetwork_unspecified", + "X2AP_CauseRadioNetwork_load_balancing", + "X2AP_CauseRadioNetwork_handover_optimisation", + "X2AP_CauseRadioNetwork_value_out_of_allowed_range", + "X2AP_CauseRadioNetwork_multiple_E_RAB_ID_instances", + "X2AP_CauseRadioNetwork_switch_off_ongoing", + "X2AP_CauseRadioNetwork_not_supported_QCI_value", + "X2AP_CauseRadioNetwork_measurement_not_supported_for_the_object", + "X2AP_CauseRadioNetwork_tDCoverall_expiry", + "X2AP_CauseRadioNetwork_tDCprep_expiry", + "X2AP_CauseRadioNetwork_action_desirable_for_radio_reasons", + "X2AP_CauseRadioNetwork_reduce_load", + "X2AP_CauseRadioNetwork_resource_optimisation", + "X2AP_CauseRadioNetwork_time_critical_action", + "X2AP_CauseRadioNetwork_target_not_allowed", + "X2AP_CauseRadioNetwork_no_radio_resources_available", + "X2AP_CauseRadioNetwork_invalid_QoS_combination", + "X2AP_CauseRadioNetwork_encryption_algorithms_not_supported", + "X2AP_CauseRadioNetwork_procedure_cancelled", + "X2AP_CauseRadioNetwork_rRM_purpose", + "X2AP_CauseRadioNetwork_improve_user_bit_rate", + "X2AP_CauseRadioNetwork_user_inactivity", + "X2AP_CauseRadioNetwork_radio_connection_with_UE_lost", + "X2AP_CauseRadioNetwork_bearer_option_not_supported", + "X2AP_CauseRadioNetwork_mCG_Mobility", + "X2AP_CauseRadioNetwork_sCG_Mobility", + "X2AP_CauseRadioNetwork_count_reaches_max_value", + "X2AP_CauseRadioNetwork_unknown_old_en_gNB_UE_X2AP_ID", + "X2AP_CauseRadioNetwork_pDCP_Overload"}; + +const char *X2AP_cause_str_radio[2]={"X2AP_CauseTransport_transport_resource_unavailable", + "X2AP_CauseTransport_unspecified"}; +const char *X2AP_cause_str_protocol[7]={" X2AP_CauseProtocol_transfer_syntax_error", + "X2AP_CauseProtocol_abstract_syntax_error_reject", + "X2AP_CauseProtocol_abstract_syntax_error_ignore_and_notify", + "X2AP_CauseProtocol_message_not_compatible_with_receiver_state", + "X2AP_CauseProtocol_semantic_error", + "X2AP_CauseProtocol_unspecified", + "X2AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message"}; +const char *X2AP_cause_str_misc[5]={"X2AP_CauseMisc_control_processing_overload", + "X2AP_CauseMisc_hardware_failure", + "X2AP_CauseMisc_om_intervention", + "X2AP_CauseMisc_not_enough_user_plane_processing_resources", + "X2AP_CauseMisc_unspecified"}; + + +int +x2ap_eNB_handle_x2_reset_response(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + + return (0); +} + + +int +x2ap_eNB_handle_x2_reset_request(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + + X2AP_ResetRequest_t *ResetRequest; + X2AP_ResetRequest_IEs_t *ie; + + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; + uint32_t eNB_id = 0; + + DevAssert (pdu != NULL); + ResetRequest = &pdu->choice.initiatingMessage.value.choice.ResetRequest; + + X2AP_DEBUG("Received a new X2 reset request\n"); + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_ResetRequest_IEs_t, ie, ResetRequest, + X2AP_ProtocolIE_ID_id_Cause, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } else { + AssertFatal(ie->value.present <= X2AP_ResetRequest_IEs__value_PR_InterfaceInstanceIndication && ie->value.present > 0, + "Cause value %d, is impossible\n",ie->value.present); + LOG_I(X2AP,"Received X2AP Reset Request with Cause Type %s\n",X2AP_ResetRequest_str[ie->value.present-1]); + } + + X2AP_DEBUG("Adding eNB to the list of associated eNBs\n"); + + if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) { + /* + * eNB has not been found in list of associated eNB, + * * * * Add it to the tail of list and initialize data + */ + if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) { + /* + * ?? + */ + return -1; + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + x2ap_eNB_data->eNB_id = eNB_id; + } + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + /* + * eNB has been found in list, consider the x2 setup request as a reset connection, + * * * * reseting any previous UE state if sctp association is != than the previous one + */ + if (x2ap_eNB_data->assoc_id != assoc_id) { + /* + * ??: Send an overload cause... + */ + X2AP_ERROR("Reset Request: eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, x2ap_eNB_data->assoc_id, assoc_id); + + return -1; + } + /* + * TODO: call the reset procedure + */ + } + + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_RESET_REQ); + + X2AP_RESET_REQ(msg).cause = ie->value.present; + + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + + return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data); +} + static int x2ap_eNB_handle_x2_setup_response(instance_t instance, @@ -511,6 +705,14 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, return -1; } + if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) || + (x2ap_eNB_data->state == X2AP_ENB_STATE_READY)) + + { + X2AP_ERROR("Received Unexpexted X2 Setup Response Message\n"); + return -1; + } + X2AP_DEBUG("Received a new X2 setup response\n"); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse, @@ -573,7 +775,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, return -1; } - msg = itti_alloc_new_message(TASK_X2AP, X2AP_SETUP_RESP); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_SETUP_RESP); X2AP_SETUP_RESP(msg).num_cc = ie->value.choice.ServedCells.list.count; @@ -637,6 +839,14 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, return -1; } + if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) || + (x2ap_eNB_data->state == X2AP_ENB_STATE_READY)) + + { + X2AP_ERROR("Received Unexpexted X2 Setup Failure Message\n"); + return -1; + } + X2AP_DEBUG("Received a new X2 setup failure\n"); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupFailure_IEs_t, ie, x2SetupFailure, @@ -649,9 +859,11 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, // need a FSM to handle all cases if ((ie->value.choice.Cause.present == X2AP_Cause_PR_misc) && (ie->value.choice.Cause.choice.misc == X2AP_CauseMisc_unspecified)) { - X2AP_WARN("Received X2 setup failure for eNB ... eNB is not ready\n"); + X2AP_ERROR("Received X2 setup failure for eNB ... eNB is not ready\n"); + exit(1); } else { X2AP_ERROR("Received x2 setup failure for eNB... please check your parameters\n"); + exit(1); } x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING; @@ -699,12 +911,13 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); - msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_HANDOVER_REQ); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true); if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -725,7 +938,11 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, //measResultListEUTRA.list.array[ncell_index]->physCellId; X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, X2AP_ProtocolIE_ID_id_GUMMEI_ID, true); - + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return -1; + } TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, X2AP_HANDOVER_REQ(msg).ue_gummei.mcc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len); OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code); @@ -736,6 +953,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -840,13 +1058,14 @@ int x2ap_eNB_handle_handover_response (instance_t instance, instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); - msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ_ACK); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_HANDOVER_REQ_ACK); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck, X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true); if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -857,6 +1076,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -887,6 +1107,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n", __FILE__, __LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; }else{ if (ie->value.choice.E_RABs_Admitted_List.list.count > 0) { @@ -934,6 +1155,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck, X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return -1; + } + X2AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer; if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s */) @@ -980,13 +1207,14 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); - msg = itti_alloc_new_message(TASK_X2AP, X2AP_UE_CONTEXT_RELEASE); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_UE_CONTEXT_RELEASE); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_UEContextRelease_IEs_t, ie, x2UEContextRelease, X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true); if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -997,6 +1225,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -1125,7 +1354,7 @@ int x2ap_eNB_handle_handover_cancel (instance_t instance, exit(1); } - msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_CANCEL); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_HANDOVER_CANCEL); X2AP_HANDOVER_CANCEL(msg).rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id); X2AP_HANDOVER_CANCEL(msg).cause = cause; @@ -1174,7 +1403,7 @@ int x2ap_eNB_handle_senb_addition_request (instance_t instance, instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); - msg = itti_alloc_new_message(TASK_X2AP, X2AP_SENB_ADDITION_REQ); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_SENB_ADDITION_REQ); /*MeNB_UE_X2AP_ID */ X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SeNBAdditionRequest_IEs_t, ie, x2SeNBAdditionRequest, @@ -1354,13 +1583,13 @@ x2ap_eNB_handle_ENDC_x2_setup_request(instance_t instance, ServedNRcellsENDCX2ManagementList__Member *servedCellMember; x2ap_eNB_instance_t *instance_p; + MessageDef *msg; x2ap_eNB_data_t *x2ap_eNB_data; uint32_t gNB_id = 0; x2ap_eNB_data = NULL; DevAssert (pdu != NULL); x2_ENDC_SetupRequest = &pdu->choice.initiatingMessage.value.choice.ENDCX2SetupRequest; - /* * We received a new valid X2 Setup Request on a stream != 0. * * * * This should not happen -> reject eNB x2 setup request. @@ -1385,103 +1614,110 @@ x2ap_eNB_handle_ENDC_x2_setup_request(instance_t instance, X2AP_ProtocolIE_ID_id_InitiatingNodeType_EndcX2Setup, true); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_ENDC_SETUP_REQ); if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); return -1; } else { if (ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_en_gNB.list.count > 0) { + for (int i=0; ivalue.choice.InitiatingNodeType_EndcX2Setup.choice.init_en_gNB.list.count;i++) { + ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqIEs_t*) ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list.array[i]; + if (ie_GNB_ENDC == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } - for (int i=0; ivalue.choice.InitiatingNodeType_EndcX2Setup.choice.init_en_gNB.list.count;i++) { + else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_Globalen_gNB_ID) { + if (ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID.size!= 28) { + //TODO: handle case were size != 28 -> notify ? reject ? + } + OCTET_STRING_TO_INT32(&ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID,gNB_id); + X2AP_DEBUG("gNB id: %07x\n", gNB_id); - ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqIEs_t*) ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list.array[i]; - if (ie_GNB_ENDC == NULL ) { - X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); - return -1; - } + X2AP_DEBUG("Adding gNB to the list of associated gNBs\n"); + if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (gNB_id)) == NULL) { + /* + * eNB has not been found in list of associated eNB, + * * * * Add it to the tail of list and initialize data + */ + if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) { + /* + * ?? + */ + return -1; + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + x2ap_eNB_data->eNB_id = gNB_id; + } + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + /* + * eNB has been found in list, consider the x2 setup request as a reset connection, + * * * * reseting any previous UE state if sctp association is != than the previous one + */ + if (x2ap_eNB_data->assoc_id != assoc_id) { + /* + * ??: Send an overload cause... + */ + X2AP_ERROR("Rejecting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", gNB_id, x2ap_eNB_data->assoc_id, assoc_id); - else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_Globalen_gNB_ID) { - if (ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID.size!= 28) { - //TODO: handle case were size != 28 -> notify ? reject ? - } - OCTET_STRING_TO_INT32(&ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID,gNB_id); - X2AP_DEBUG("gNB id: %07x\n", gNB_id); + // Here we should be calling an ENDC specific setup_failure function instead + x2ap_eNB_generate_x2_setup_failure (instance, + assoc_id, + X2AP_Cause_PR_protocol, + X2AP_CauseProtocol_unspecified, + -1); + return -1; + } + /* + * * TODO: call the reset procedure + */ + } + } + else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_ServedNRcellsENDCX2ManagementList){ + if (ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count > 0) { + x2ap_eNB_data->num_cc = ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count; + X2AP_ENDC_SETUP_REQ(msg).num_cc = x2ap_eNB_data->num_cc; + for (int i=0; ivalue.choice.ServedNRcellsENDCX2ManagementList.list.count;i++) { + servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.array[i]; + x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedNRCellInfo.nrpCI; + X2AP_ENDC_SETUP_REQ(msg).Nid_cell[i] = x2ap_eNB_data->Nid_cell[i]; + //servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0] + if (servedCellMember->servedNRCellInfo.fiveGS_TAC != NULL) { + X2AP_INFO("TAC: %02x%02x%02x\n", + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); + } else { + X2AP_INFO("TAC: (NULL)\n"); + } - X2AP_DEBUG("Adding gNB to the list of associated gNBs\n"); - if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (gNB_id)) == NULL) { - /* - * eNB has not been found in list of associated eNB, - * * * * Add it to the tail of list and initialize data - */ - if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) { - /* - * ?? - */ - return -1; - } else { - x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; - x2ap_eNB_data->eNB_id = gNB_id; - } - } else { - x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; - - /* - * eNB has been found in list, consider the x2 setup request as a reset connection, - * * * * reseting any previous UE state if sctp association is != than the previous one - */ - if (x2ap_eNB_data->assoc_id != assoc_id) { - /* - * ??: Send an overload cause... - */ - X2AP_ERROR("Rejecting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", gNB_id, x2ap_eNB_data->assoc_id, assoc_id); - - // Panos: Here we should be calling an ENDC specific setup_failure function instead - x2ap_eNB_generate_x2_setup_failure (instance, - assoc_id, - X2AP_Cause_PR_protocol, - X2AP_CauseProtocol_unspecified, - -1); - return -1; - } - /* - * * TODO: call the reset procedure - */ - } - } - else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_ServedNRcellsENDCX2ManagementList){ - if (ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count > 0) { - x2ap_eNB_data->num_cc = ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count; - for (int i=0; ivalue.choice.ServedNRcellsENDCX2ManagementList.list.count;i++) { - servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.array[i]; - x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedNRCellInfo.nrpCI; - //servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0] - if (servedCellMember->servedNRCellInfo.fiveGS_TAC != NULL) { - X2AP_INFO("TAC: %02x%02x%02x\n", - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); - } else { - X2AP_INFO("TAC: (NULL)\n"); - } - - X2AP_INFO("PLMN: %02x%02x%02x\n", - servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0], - servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[1], - servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[2]); - } - } - } - } + X2AP_INFO("PLMN: %02x%02x%02x\n", + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0], + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[1], + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[2]); + if(servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr.list.count > 0){ + X2AP_FreqBandNrItem_t *FreqBandItem = servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr.list.array[0]; + x2ap_eNB_data->servedNrCell_band[i] = FreqBandItem->freqBandIndicatorNr; + X2AP_ENDC_SETUP_REQ(msg).servedNrCell_band[i] = x2ap_eNB_data->servedNrCell_band[i]; + } + } + } + } + } } else { - X2AP_ERROR("%s %d: init_eNB list is empty \n",__FILE__,__LINE__); - return -1; + X2AP_ERROR("%s %d: init_eNB list is empty \n",__FILE__,__LINE__); + return -1; } } instance_p = x2ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + return x2ap_eNB_generate_ENDC_x2_setup_response(instance_p, x2ap_eNB_data); } @@ -1641,8 +1877,6 @@ int x2ap_gNB_handle_ENDC_sGNB_addition_request (instance_t instance, uint32_t stream, X2AP_X2AP_PDU_t *pdu) { - - X2AP_SgNBAdditionRequest_t *x2SgNBAdditionRequest; X2AP_SgNBAdditionRequest_IEs_t *ie; @@ -1673,7 +1907,7 @@ int x2ap_gNB_handle_ENDC_sGNB_addition_request (instance_t instance, DevAssert(instance_p != NULL); //Allocate an ITTI X2AP_SGNB_ADDITION_REQ message instead - msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_ADDITION_REQ); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_ENDC_SGNB_ADDITION_REQ); /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */ X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBAdditionRequest_IEs_t, ie, x2SgNBAdditionRequest, @@ -1821,7 +2055,9 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance, DevAssert(instance_p != NULL); //Allocate an ITTI X2AP_SGNB_ADDITION_REQ message instead - msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); + + X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).gnb_x2_assoc_id = assoc_id; /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */ X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBAdditionRequestAcknowledge_IEs_t, ie, x2SgNBAdditionRequest_ack, @@ -1923,6 +2159,9 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance, itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + /* remove UE from x2, DC preparation is over */ + x2ap_release_id(&instance_p->id_manager, ue_id); + return 0; } @@ -1930,78 +2169,289 @@ static int x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete (instance_t instance, uint32_t assoc_id, uint32_t stream, - X2AP_X2AP_PDU_t *pdu) { + X2AP_X2AP_PDU_t *pdu) +{ + X2AP_SgNBReconfigurationComplete_t *x2SgNBReconfigurationComplete; + X2AP_SgNBReconfigurationComplete_IEs_t *ie; - X2AP_SgNBReconfigurationComplete_t *x2SgNBReconfigurationComplete; - X2AP_SgNBReconfigurationComplete_IEs_t *ie; + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; - x2ap_eNB_instance_t *instance_p; - x2ap_eNB_data_t *x2ap_eNB_data; - MessageDef *msg; + int id_target; + int ue_id; - DevAssert (pdu != NULL); - x2SgNBReconfigurationComplete = &pdu->choice.initiatingMessage.value.choice.SgNBReconfigurationComplete; + DevAssert (pdu != NULL); + x2SgNBReconfigurationComplete = &pdu->choice.initiatingMessage.value.choice.SgNBReconfigurationComplete; - /*if (stream == 0) { - X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n"); - // TODO: send a x2 failure response - return 0; - }*/ + /*if (stream == 0) { + X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n"); + // TODO: send a x2 failure response + return 0; + }*/ - X2AP_DEBUG ("Received X2 SgNB Reconfiguration complete message\n"); + X2AP_DEBUG ("Received X2 SgNB Reconfiguration complete message\n"); - x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); - DevAssert(x2ap_eNB_data != NULL); + x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); + DevAssert(x2ap_eNB_data != NULL); - X2AP_INFO("X2AP Association id: %d \n",assoc_id); + X2AP_INFO("X2AP Association id: %d \n",assoc_id); - instance_p = x2ap_eNB_get_instance(instance); - DevAssert(instance_p != NULL); + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); - //Allocate an ITTI X2AP_sGNB_reconfiguration_complete message - msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RECONF_COMPLETE); + //Allocate an ITTI X2AP_sGNB_reconfiguration_complete message + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_ENDC_SGNB_RECONF_COMPLETE); - /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */ - X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete, - X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true); - if (ie == NULL ) { - X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); - return -1; - } + /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete, + X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } - X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).MeNB_ue_x2_id = ie->value.choice.UE_X2AP_ID; + X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).MeNB_ue_x2_id = ie->value.choice.UE_X2AP_ID; - /* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */ - X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete, - X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true); - if (ie == NULL ) { - X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); - return -1; - } + /* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete, + X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } - X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).SgNB_ue_x2_id = ie->value.choice.SgNB_UE_X2AP_ID; + id_target = ie->value.choice.SgNB_UE_X2AP_ID; + X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).SgNB_ue_x2_id = id_target; + ue_id = x2ap_find_id_from_id_target(&instance_p->id_manager, id_target); + if (ue_id == -1) { + X2AP_WARN("incorrect/unknown X2AP IDs for UE (SgNB_UE_X2AP_ID %d), ignoring sGNB reconfiguration complete\n", + id_target); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return 0; + } - X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete, - X2AP_ProtocolIE_ID_id_ResponseInformationSgNBReconfComp, true); - if (ie == NULL ) { - X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); - return -1; - } + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete, + X2AP_ProtocolIE_ID_id_ResponseInformationSgNBReconfComp, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } - if(ie->value.choice.ResponseInformationSgNBReconfComp.present == X2AP_ResponseInformationSgNBReconfComp_PR_success_SgNBReconfComp){ - X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).reconf_response = X2AP_RECONF_RESPONSE_SUCCESS; - } - else { - X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).reconf_response = X2AP_RECONF_RESPONSE_REJECT; - } + if (ie->value.choice.ResponseInformationSgNBReconfComp.present != X2AP_ResponseInformationSgNBReconfComp_PR_success_SgNBReconfComp){ + X2AP_ERROR("%s %d: fatal: unsuccessfulSgNB Reconfiguration Complete\n",__FILE__,__LINE__); + exit(1); + } - itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg); + x2ap_release_id(&instance_p->id_manager, ue_id); + itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg); - return 0; + return 0; } +static +int x2ap_gNB_handle_ENDC_sGNB_release_request(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + /* the logic in this function is the following: when receiving a release + * request, the UE may exist in X2. Or not. If it's not in X2, it can + * nevertheless be in RRC. + * The release request message may contain the gNB id. Or not. It's better + * to look for the UE using the gNB rather than the eNB id. So if we have + * the gNB id we use it. If not, we use the eNB id. + */ + X2AP_SgNBReleaseRequest_t *req; + X2AP_SgNBReleaseRequest_IEs_t *ie; + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; + int id_source; + int id_target; + int rnti; + int ue_id; + + DevAssert (pdu != NULL); + req = &pdu->choice.initiatingMessage.value.choice.SgNBReleaseRequest; + + /*if (stream == 0) { + X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n"); + // TODO: send a x2 failure response + return 0; + }*/ + + X2AP_DEBUG ("Received X2 SgNB Release Request message\n"); + + x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); + DevAssert(x2ap_eNB_data != NULL); + + X2AP_INFO("X2AP Association id: %d \n",assoc_id); + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + + /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequest_IEs_t, ie, req, + X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + id_source = ie->value.choice.UE_X2AP_ID; + + /* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequest_IEs_t, ie, req, + X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, false); + if (ie != NULL) + id_target = ie->value.choice.SgNB_UE_X2AP_ID; + else + id_target = -1; + + /* find ue_id, preferably from id_target if id_target is known */ + ue_id = -1; + if (id_target != -1) + ue_id = x2ap_find_id_from_id_target(&instance_p->id_manager, id_target); + if (ue_id == -1) + ue_id = x2ap_find_id_from_id_source(&instance_p->id_manager, id_source); + + if (ue_id == -1) { + X2AP_WARN("%s %d: no UE found for id_source %d id_target %d\n", + __FILE__, __LINE__, id_source, id_target); + } + + /* the UE may not exist in X2 anymore but exist in RRC + * in which case its rnti is simply the id_target + */ + if (ue_id != -1) { + rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id); + + /* remove ue_id */ + x2ap_release_id(&instance_p->id_manager, ue_id); + } else { + rnti = id_target; + } + + if (rnti != -1) { + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_ENDC_SGNB_RELEASE_REQUEST); + + X2AP_ENDC_SGNB_RELEASE_REQUEST(msg).rnti = rnti; + + itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg); + } + + /* this call should maybe not be here, we should check that the + * SgNB Release Request message has been executed properly + */ + x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge(instance_p, x2ap_eNB_data, + id_source, + rnti != -1 ? rnti : 0); + + return 0; +} + +static +int x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + /* nothing to do - may change at some point */ + X2AP_INFO("received release request acknowledge\n"); + return 0; +} + +static +int x2ap_gNB_handle_ENDC_sGNB_release_required(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + /* the logic in this function is the following: when receiving a release + * required we don't care about the UE in X2. We simply send a message + * to RRC with the SgNB id (which is SgNB's RNTI). RRC will look for the + * UE using this RNTI and deal with it. In the meanwhile the X2 layer + * immediately replies with "release confirm" no matter what happens + * in RRC. + */ + X2AP_SgNBReleaseRequired_t *req; + X2AP_SgNBReleaseRequired_IEs_t *ie; + + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; + + int id_source; + int id_target; + int gnb_rnti; + + DevAssert (pdu != NULL); + req = &pdu->choice.initiatingMessage.value.choice.SgNBReleaseRequired; + + /*if (stream == 0) { + X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n"); + // TODO: send a x2 failure response + return 0; + }*/ + + X2AP_DEBUG ("Received X2 SgNB Release Required message\n"); + + x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); + DevAssert(x2ap_eNB_data != NULL); + + X2AP_INFO("X2AP Association id: %d \n",assoc_id); + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + + /* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequired_IEs_t, ie, req, + X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + id_source = ie->value.choice.UE_X2AP_ID; + + /* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequired_IEs_t, ie, req, + X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + id_target = ie->value.choice.SgNB_UE_X2AP_ID; + + gnb_rnti = id_target; + + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_ENDC_SGNB_RELEASE_REQUIRED); + X2AP_ENDC_SGNB_RELEASE_REQUIRED(msg).gnb_rnti = gnb_rnti; + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + + /* this call should maybe not be here, we should check that the + * SgNB Release Required message has been executed properly + */ + x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm(instance_p, x2ap_eNB_data, + id_source, id_target); + + return 0; +} + +static +int x2ap_gNB_handle_ENDC_sGNB_release_confirm(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + /* nothing to do - may change at some point */ + X2AP_INFO("received release confirm\n"); + return 0; +} diff --git a/openair2/X2AP/x2ap_eNB_itti_messaging.c b/openair2/X2AP/x2ap_eNB_itti_messaging.c index 7573d9be89..26e26ba411 100644 --- a/openair2/X2AP/x2ap_eNB_itti_messaging.c +++ b/openair2/X2AP/x2ap_eNB_itti_messaging.c @@ -36,7 +36,7 @@ void x2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uin MessageDef *message_p; sctp_data_req_t *sctp_data_req; - message_p = itti_alloc_new_message(TASK_X2AP, SCTP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_X2AP, 0, SCTP_DATA_REQ); sctp_data_req = &message_p->ittiMsg.sctp_data_req; @@ -54,7 +54,7 @@ void x2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t asso MessageDef *message_p = NULL; sctp_close_association_t *sctp_close_association_p = NULL; - message_p = itti_alloc_new_message(TASK_X2AP, SCTP_CLOSE_ASSOCIATION); + message_p = itti_alloc_new_message(TASK_X2AP, 0, SCTP_CLOSE_ASSOCIATION); sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; sctp_close_association_p->assoc_id = assoc_id; diff --git a/openair2/X2AP/x2ap_eNB_management_procedures.c b/openair2/X2AP/x2ap_eNB_management_procedures.c index 469a76a261..a0cc0d1124 100644 --- a/openair2/X2AP/x2ap_eNB_management_procedures.c +++ b/openair2/X2AP/x2ap_eNB_management_procedures.c @@ -116,7 +116,7 @@ void dump_trees(void) x2ap_eNB_instance_t *zz; STAILQ_FOREACH(zz, &x2ap_eNB_internal_data.x2ap_eNB_instances_head, x2ap_eNB_entries) { -printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance); +printf("here comes the tree (instance %ld):\n---------------------------------------------\n", zz->instance); dump_tree(zz->x2ap_enb_head.rbh_root); printf("---------------------------------------------\n"); } diff --git a/openair2/X2AP/x2ap_ids.c b/openair2/X2AP/x2ap_ids.c index 02f1bbfc0e..0750ba5bc9 100644 --- a/openair2/X2AP/x2ap_ids.c +++ b/openair2/X2AP/x2ap_ids.c @@ -70,6 +70,16 @@ int x2ap_find_id_from_id_source(x2ap_id_manager *m, int id_source) return -1; } +int x2ap_find_id_from_id_target(x2ap_id_manager *m, int id_target) +{ + int i; + for (i = 0; i < X2AP_MAX_IDS; i++) + if (m->ids[i].rnti != -1 && + m->ids[i].id_target == id_target) + return i; + return -1; +} + int x2ap_find_id_from_rnti(x2ap_id_manager *m, int rnti) { int i; @@ -107,6 +117,16 @@ void x2ap_set_reloc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time) m->ids[ue_id].tx2_reloc_overall_start = time; } +void x2ap_set_dc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time) +{ + m->ids[ue_id].t_dc_prep_start = time; +} + +void x2ap_set_dc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time) +{ + m->ids[ue_id].t_dc_overall_start = time; +} + int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id) { return m->ids[ue_id].id_source; diff --git a/openair2/X2AP/x2ap_ids.h b/openair2/X2AP/x2ap_ids.h index f2670f3612..26d97f73c8 100644 --- a/openair2/X2AP/x2ap_ids.h +++ b/openair2/X2AP/x2ap_ids.h @@ -38,7 +38,8 @@ typedef enum { X2ID_STATE_SOURCE_PREPARE, X2ID_STATE_SOURCE_OVERALL, X2ID_STATE_TARGET, - X2ID_STATE_NSA_PREPARE, + X2ID_STATE_NSA_ENB_PREPARE, + X2ID_STATE_NSA_GNB_OVERALL, } x2id_state_t; typedef struct { @@ -55,6 +56,8 @@ typedef struct { /* timers */ uint64_t t_reloc_prep_start; uint64_t tx2_reloc_overall_start; + uint64_t t_dc_prep_start; + uint64_t t_dc_overall_start; } x2ap_id; typedef struct { @@ -66,6 +69,7 @@ int x2ap_allocate_new_id(x2ap_id_manager *m); void x2ap_release_id(x2ap_id_manager *m, int id); int x2ap_find_id(x2ap_id_manager *, int id_source, int id_target); int x2ap_find_id_from_id_source(x2ap_id_manager *, int id_source); +int x2ap_find_id_from_id_target(x2ap_id_manager *, int id_source); int x2ap_find_id_from_rnti(x2ap_id_manager *, int rnti); void x2ap_set_ids(x2ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target); void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state); @@ -73,6 +77,8 @@ void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state); void x2ap_id_set_target(x2ap_id_manager *m, int ue_id, void *target); void x2ap_set_reloc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time); void x2ap_set_reloc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time); +void x2ap_set_dc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time); +void x2ap_set_dc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time); int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id); int x2ap_id_get_id_target(x2ap_id_manager *m, int ue_id); int x2ap_id_get_rnti(x2ap_id_manager *m, int ue_id); diff --git a/openair2/X2AP/x2ap_timers.c b/openair2/X2AP/x2ap_timers.c index a0a7b61ad7..98674de51b 100644 --- a/openair2/X2AP/x2ap_timers.c +++ b/openair2/X2AP/x2ap_timers.c @@ -28,11 +28,17 @@ #include "x2ap_eNB_management_procedures.h" #include "x2ap_eNB_generate_messages.h" -void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall) +void x2ap_timers_init(x2ap_timers_t *t, + int t_reloc_prep, + int tx2_reloc_overall, + int t_dc_prep, + int t_dc_overall) { t->tti = 0; t->t_reloc_prep = t_reloc_prep; t->tx2_reloc_overall = tx2_reloc_overall; + t->t_dc_prep = t_dc_prep; + t->t_dc_overall = t_dc_overall; } void x2ap_check_timers(instance_t instance) @@ -59,14 +65,17 @@ void x2ap_check_timers(instance_t instance) for (i = 0; i < X2AP_MAX_IDS; i++) { if (m->ids[i].rnti == -1) continue; - x2_ongoing++; + + if (m->ids[i].state == X2ID_STATE_SOURCE_PREPARE || + m->ids[i].state == X2ID_STATE_SOURCE_OVERALL) + x2_ongoing++; if (m->ids[i].state == X2ID_STATE_SOURCE_PREPARE && t->tti > m->ids[i].t_reloc_prep_start + t->t_reloc_prep) { LOG_I(X2AP, "X2 timeout reloc prep\n"); /* t_reloc_prep timed out */ cause = X2AP_T_RELOC_PREP_TIMEOUT; - goto timeout; + goto lte_handover_timeout; } if (m->ids[i].state == X2ID_STATE_SOURCE_OVERALL && @@ -74,19 +83,68 @@ void x2ap_check_timers(instance_t instance) LOG_I(X2AP, "X2 timeout reloc overall\n"); /* tx2_reloc_overall timed out */ cause = X2AP_TX2_RELOC_OVERALL_TIMEOUT; - goto timeout; + goto lte_handover_timeout; + } + + if (m->ids[i].state == X2ID_STATE_NSA_ENB_PREPARE && + t->tti > m->ids[i].t_dc_prep_start + t->t_dc_prep) { + int id_source; + int id_target; + + LOG_I(X2AP, "X2 timeout DC prep\n"); + /* t_dc_prep timed out */ + target = x2ap_id_get_target(m, i); + id_source = x2ap_id_get_id_source(m, i); + id_target = x2ap_id_get_id_target(m, i); + x2ap_eNB_generate_ENDC_x2_SgNB_release_request(instance_p, target, + id_source, id_target, + X2AP_CAUSE_T_DC_PREP_TIMEOUT); + + /* inform RRC of timeout */ + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_ENDC_DC_PREP_TIMEOUT); + X2AP_ENDC_DC_PREP_TIMEOUT(msg).rnti = x2ap_id_get_rnti(m, i); + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + + /* remove UE from X2AP */ + x2ap_release_id(m, i); + + continue; + } + + if (m->ids[i].state == X2ID_STATE_NSA_GNB_OVERALL && + t->tti > m->ids[i].t_dc_overall_start + t->t_dc_overall) { + int id_source; + int id_target; + + LOG_I(X2AP, "X2 timeout DC overall\n"); + /* t_dc_overall timed out */ + target = x2ap_id_get_target(m, i); + id_source = x2ap_id_get_id_source(m, i); + id_target = x2ap_id_get_id_target(m, i); + x2ap_eNB_generate_ENDC_x2_SgNB_release_required(instance_p, target, + id_source, id_target, X2AP_CAUSE_T_DC_OVERALL_TIMEOUT); + + /* inform RRC of timeout */ + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_ENDC_DC_OVERALL_TIMEOUT); + X2AP_ENDC_DC_OVERALL_TIMEOUT(msg).rnti = x2ap_id_get_rnti(m, i); + itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg); + + /* remove UE from X2AP */ + x2ap_release_id(m, i); + + continue; } /* no timeout -> check next UE */ continue; -timeout: +lte_handover_timeout: /* inform target about timeout */ target = x2ap_id_get_target(m, i); x2ap_eNB_generate_x2_handover_cancel(instance_p, target, i, cause); /* inform RRC of cancellation */ - msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_CANCEL); + msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_HANDOVER_CANCEL); X2AP_HANDOVER_CANCEL(msg).rnti = x2ap_id_get_rnti(m, i); X2AP_HANDOVER_CANCEL(msg).cause = cause; itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); diff --git a/openair2/X2AP/x2ap_timers.h b/openair2/X2AP/x2ap_timers.h index d4579422d5..f32b73e87b 100644 --- a/openair2/X2AP/x2ap_timers.h +++ b/openair2/X2AP/x2ap_timers.h @@ -36,9 +36,15 @@ typedef struct { /* timer values (unit: TTI, ie. millisecond when in realtime) */ int t_reloc_prep; int tx2_reloc_overall; + int t_dc_prep; + int t_dc_overall; } x2ap_timers_t; -void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall); +void x2ap_timers_init(x2ap_timers_t *t, + int t_reloc_prep, + int tx2_reloc_overall, + int t_dc_prep, + int t_dc_overall); void x2ap_check_timers(instance_t instance); uint64_t x2ap_timer_get_tti(x2ap_timers_t *t); diff --git a/openair3/COMMON/messages_types.h b/openair3/COMMON/messages_types.h index f91881bf11..f8fd464288 100644 --- a/openair3/COMMON/messages_types.h +++ b/openair3/COMMON/messages_types.h @@ -39,6 +39,7 @@ #include "udp_messages_types.h" #include "mme_app_messages_types.h" #include "m2ap_messages_types.h" +#include "ngap_messages_types.h" #endif /* MESSAGES_TYPES_H_ */ diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c index f095cce67d..0fe2741d7b 100644 --- a/openair3/GTPV1-U/gtpv1u_eNB.c +++ b/openair3/GTPV1-U/gtpv1u_eNB.c @@ -51,6 +51,7 @@ #include "gtpv1u_eNB_defs.h" #include "gtpv1u_eNB_task.h" #include "rrc_eNB_GTPV1U.h" +#include #undef GTP_DUMP_SOCKET @@ -135,7 +136,7 @@ static int gtpv1u_eNB_send_init_udp(const Gtpv1uS1Req *req) { // Create and alloc new message MessageDef *message_p; struct in_addr addr= {0}; - message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_INIT); + message_p = itti_alloc_new_message(TASK_GTPV1_U, 0, UDP_INIT); if (message_p == NULL) { return -1; @@ -184,7 +185,7 @@ NwGtpv1uRcT gtpv1u_eNB_send_udp_msg( // Create and alloc new message MessageDef *message_p = NULL; udp_data_req_t *udp_data_req_p = NULL; - message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_GTPV1_U, 0, UDP_DATA_REQ); if (message_p) { #if defined(LOG_GTPU) && LOG_GTPU > 0 @@ -280,12 +281,12 @@ NwGtpv1uRcT gtpv1u_eNB_process_stack_req( (ue_context_p->ue_context.handover_info->state < HO_FORWARDING_COMPLETE)) { if(msgType == NW_GTP_END_MARKER) { /* in the source enb, UE in RRC_HO_EXECUTION mode */ - if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info->state == HO_COMPLETE) { + if (ue_context_p->ue_context.StatusRrc == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info->state == HO_COMPLETE) { /* set handover state */ //ue_context_p->ue_context.handover_info->state = HO_END_MARKER; MessageDef *msg; // Configure end marker - msg = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_END_MARKER_REQ); + msg = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_ENB_END_MARKER_REQ); GTPV1U_ENB_END_MARKER_REQ(msg).buffer = itti_malloc(TASK_GTPV1_U, TASK_GTPV1_U, GTPU_HEADER_OVERHEAD_MAX + buffer_len); memcpy(>PV1U_ENB_END_MARKER_REQ(msg).buffer[GTPU_HEADER_OVERHEAD_MAX], buffer, buffer_len); GTPV1U_ENB_END_MARKER_REQ(msg).length = buffer_len; @@ -298,17 +299,17 @@ NwGtpv1uRcT gtpv1u_eNB_process_stack_req( } } - if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION || ue_context_p->ue_context.Status == RRC_RECONFIGURED) { + if (ue_context_p->ue_context.StatusRrc == RRC_HO_EXECUTION || ue_context_p->ue_context.StatusRrc == RRC_RECONFIGURED) { int msgsrc = gtpv1u_eNB_get_msgsource(ue_context_p, teid); LOG_D(GTPU,"UE INFO.ueStatus %d, handover state %d, forwarding state %d, from %s. message type %s\n", - ue_context_p->ue_context.Status, + ue_context_p->ue_context.StatusRrc, ue_context_p->ue_context.handover_info->state, ue_context_p->ue_context.handover_info->forwarding_state, msgsrc == GTPV1U_MSG_FROM_SOURCE_ENB?"Source eNB":"EPC", msgsrc != GTPV1U_MSG_FROM_SOURCE_ENB? "UDP DATA" : msgType == NW_GTP_END_MARKER?"END MARKER":"DATA FORWARDING"); - /* target enb */ + /* target enb */ if(msgType == NW_GTP_END_MARKER) { LOG_I(GTPU, "target end receive END MARKER\n"); ue_context_p->ue_context.handover_info->state = HO_END_MARKER; @@ -358,7 +359,7 @@ NwGtpv1uRcT gtpv1u_eNB_process_stack_req( if (ue_context_p->ue_context.handover_info->state == HO_COMPLETE) { MessageDef *msg; // Configure target - msg = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_DATA_FORWARDING_REQ); + msg = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_ENB_DATA_FORWARDING_REQ); GTPV1U_ENB_DATA_FORWARDING_REQ(msg).buffer = itti_malloc(TASK_GTPV1_U, TASK_GTPV1_U, GTPU_HEADER_OVERHEAD_MAX + buffer_len); memcpy(>PV1U_ENB_DATA_FORWARDING_REQ(msg).buffer[GTPU_HEADER_OVERHEAD_MAX], buffer, buffer_len); GTPV1U_ENB_DATA_FORWARDING_REQ(msg).length = buffer_len; @@ -1122,7 +1123,7 @@ int gtpv1u_delete_s1u_tunnel( hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; teid_t teid_eNB = 0; int erab_index = 0; - message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_DELETE_TUNNEL_RESP); + message_p = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_ENB_DELETE_TUNNEL_RESP); GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti = req_pP->rnti; GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status = 0; hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti, (void **)>pv1u_ue_data_p); @@ -1184,7 +1185,10 @@ int gtpv1u_delete_s1u_tunnel( "0 GTPV1U_ENB_DELETE_TUNNEL_RESP rnti %x teid %x", GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti, teid_eNB); - return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p); + if (req_pP->from_gnb) + return itti_send_msg_to_task(TASK_RRC_GNB, instanceP, message_p); + else + return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p); } @@ -1208,7 +1212,7 @@ int gtpv1u_eNB_init(void) { //gtpv1u_data_g.udp_data; RC.gtpv1u_data_g->seq_num = 0; RC.gtpv1u_data_g->restart_counter = 0; - + RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up = 0; /* Initializing GTPv1-U stack */ if ((rc = nwGtpv1uInitialize(&RC.gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) { LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc); @@ -1286,7 +1290,7 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) { itti_receive_msg(TASK_GTPV1_U, &received_message_p); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN); DevAssert(received_message_p != NULL); - instance = ITTI_MSG_INSTANCE(received_message_p); + instance = ITTI_MSG_DESTINATION_INSTANCE(received_message_p); //msg_name_p = ITTI_MSG_NAME(received_message_p); switch (ITTI_MSG_ID(received_message_p)) { @@ -1494,15 +1498,15 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) { stack_req.apiInfo.sendtoInfo.teid = tenb_x2u_teid; stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr;// target enb ip rc = nwGtpv1uGpduMsgNew( - RC.gtpv1u_data_g->gtpv1u_stack, - tenb_x2u_teid, - NW_FALSE, - RC.gtpv1u_data_g->seq_num++, - data_req_p->buffer, - data_req_p->length, - data_req_p->offset, - &(stack_req.apiInfo.sendtoInfo.hMsg)); - + RC.gtpv1u_data_g->gtpv1u_stack, + tenb_x2u_teid, + NW_FALSE, + RC.gtpv1u_data_g->seq_num++, + data_req_p->buffer, + data_req_p->length, + data_req_p->offset, + &(stack_req.apiInfo.sendtoInfo.hMsg)); + if (rc != NW_GTPV1U_OK) { LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc); MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u", @@ -1512,7 +1516,7 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) { pMsg = (NwGtpv1uMsgT *) stack_req.apiInfo.sendtoInfo.hMsg; pMsg->msgType = NW_GTP_END_MARKER; rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req); - + if (rc != NW_GTPV1U_OK) { LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc); MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u", @@ -1532,11 +1536,11 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) { rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack, stack_req.apiInfo.sendtoInfo.hMsg); - + if (rc != NW_GTPV1U_OK) { LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc); } - + gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req; memset(&delete_tunnel_req, 0, sizeof(delete_tunnel_req)); delete_tunnel_req.rnti = data_req_p->rnti; @@ -1544,7 +1548,7 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) { } } } - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT); } break; diff --git a/openair3/GTPV1-U/gtpv1u_eNB_defs.h b/openair3/GTPV1-U/gtpv1u_eNB_defs.h index 79d9a1dcdd..fb317e4ca6 100644 --- a/openair3/GTPV1-U/gtpv1u_eNB_defs.h +++ b/openair3/GTPV1-U/gtpv1u_eNB_defs.h @@ -111,14 +111,6 @@ typedef struct gtpv1u_data_s { uint16_t seq_num; uint8_t restart_counter; -#ifdef GTPU_IN_KERNEL - char *interface_name; - int interface_index; - - struct iovec *malloc_ring; - void *sock_mmap_ring[16]; - int sock_desc[16]; // indexed by marking -#endif } gtpv1u_data_t; int diff --git a/openair3/GTPV1-U/gtpv1u_gNB.c b/openair3/GTPV1-U/gtpv1u_gNB.c index f13bf13794..d3f26aeff1 100644 --- a/openair3/GTPV1-U/gtpv1u_gNB.c +++ b/openair3/GTPV1-U/gtpv1u_gNB.c @@ -38,6 +38,7 @@ #include "NwGtpv1uPrivate.h" #include "NwLog.h" #include "gtpv1u_eNB_defs.h" +#include "gtpv1u_gNB_defs.h" #include "gtpv1_u_messages_types.h" #include "udp_eNB_task.h" #include "common/utils/LOG/log.h" @@ -45,13 +46,15 @@ #include "COMMON/platform_constants.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/ran_context.h" -#include "gtpv1u_eNB_defs.h" #include "gtpv1u_eNB_task.h" #include "gtpv1u_gNB_task.h" #include "rrc_eNB_GTPV1U.h" #undef GTP_DUMP_SOCKET +#undef GTPV1U_BEARER_OFFSET +#define GTPV1U_BEARER_OFFSET 1 + extern unsigned char NB_eNB_INST; extern RAN_CONTEXT_t RC; @@ -309,3 +312,707 @@ void *gtpv1u_gNB_task(void *args) { return NULL; } +/* Callback called when a gtpv1u message arrived on UDP interface */ +NwGtpv1uRcT nr_gtpv1u_gNB_process_stack_req( + NwGtpv1uUlpHandleT hUlp, + NwGtpv1uUlpApiT *pUlpApi) { + boolean_t result = FALSE; + teid_t teid = 0; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + nr_gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL; + protocol_ctxt_t ctxt; + NwGtpv1uRcT rc; + + switch(pUlpApi->apiType) { + /* Here there are two type of messages handled: + * - T-PDU + * - END-MARKER + */ + case NW_GTPV1U_ULP_API_RECV_TPDU: { + uint8_t buffer[4096]; + uint32_t buffer_len; + //uint16_t msgType = NW_GTP_GPDU; + //NwGtpv1uMsgT *pMsg = NULL; + /* Nw-gptv1u stack has processed a PDU. we can schedule it to PDCP + * for transmission. + */ + teid = pUlpApi->apiInfo.recvMsgInfo.teid; + //pMsg = (NwGtpv1uMsgT *) pUlpApi->apiInfo.recvMsgInfo.hMsg; + //msgType = pMsg->msgType; + + if (NW_GTPV1U_OK != nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg, + buffer, &buffer_len)) { + LOG_E(GTPU, "Error while retrieving T-PDU"); + } + + itti_free(TASK_UDP, ((NwGtpv1uMsgT *)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBuf); +#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0 + gtpv1u_eNB_write_dump_socket(buffer,buffer_len); +#endif + rc = nwGtpv1uMsgDelete(RC.nr_gtpv1u_data_g->gtpv1u_stack, + pUlpApi->apiInfo.recvMsgInfo.hMsg); + + if (rc != NW_GTPV1U_OK) { + LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc); + } + + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->teid_mapping, teid, (void **)>pv1u_teid_data_p); + + if (hash_rc == HASH_TABLE_OK) { +// #if defined(LOG_GTPU) && LOG_GTPU > 0 + LOG_D(GTPU, "Received T-PDU from gtpv1u stack teid %u size %d -> gnb module id %u ue module id %u pdu session id %u\n", + teid, + buffer_len, + gtpv1u_teid_data_p->gnb_id, + gtpv1u_teid_data_p->ue_id, + gtpv1u_teid_data_p->pdu_session_id); +// #endif + //warning "LG eps bearer mapping to DRB id to do (offset -4)" + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gtpv1u_teid_data_p->gnb_id, GNB_FLAG_YES, gtpv1u_teid_data_p->ue_id, 0, 0,gtpv1u_teid_data_p->gnb_id); + // MSC_LOG_TX_MESSAGE( + // MSC_GTPU_ENB, + // MSC_PDCP_ENB, + // NULL,0, + // MSC_AS_TIME_FMT" DATA-REQ rb %u size %u", + // 0,0, + // (gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4, + // buffer_len); + + result = pdcp_data_req( + &ctxt, + SRB_FLAG_NO, + 1, + 0, // mui + SDU_CONFIRM_NO, // confirm + buffer_len, + buffer, + PDCP_TRANSMISSION_MODE_DATA,NULL, NULL + ); + + if ( result == FALSE ) { + if (ctxt.configured == FALSE ) + LOG_W(GTPU, "gNB node PDCP data request failed, cause: [UE:%x]RB is not configured!\n", ctxt.rnti) ; + else + LOG_W(GTPU, "PDCP data request failed\n"); + + return NW_GTPV1U_FAILURE; + } + } else { + LOG_W(GTPU, "Received T-PDU from gtpv1u stack teid %u unknown size %u", teid, buffer_len); + } + } + break; + + default: { + LOG_E(GTPU, "Received undefined UlpApi (%02x) from gtpv1u stack!\n", + pUlpApi->apiType); + } + } // end of switch + + return NW_GTPV1U_OK; +} + +int nr_gtpv1u_gNB_init(void) { + NwGtpv1uRcT rc = NW_GTPV1U_FAILURE; + NwGtpv1uUlpEntityT ulp; + NwGtpv1uUdpEntityT udp; + NwGtpv1uLogMgrEntityT log; + NwGtpv1uTimerMgrEntityT tmr; + // enb_properties_p = enb_config_get()->properties[0]; + RC.nr_gtpv1u_data_g = (nr_gtpv1u_data_t *)calloc(sizeof(nr_gtpv1u_data_t),1); + LOG_I(GTPU, "Initializing GTPU stack %p\n",&RC.nr_gtpv1u_data_g); + + /* Initialize UE hashtable */ + RC.nr_gtpv1u_data_g->ue_mapping = hashtable_create (32, NULL, NULL); + AssertFatal(RC.nr_gtpv1u_data_g->ue_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create returned %p\n", RC.gtpv1u_data_g->ue_mapping); + RC.nr_gtpv1u_data_g->teid_mapping = hashtable_create (256, NULL, NULL); + AssertFatal(RC.nr_gtpv1u_data_g->teid_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create\n"); + // RC.gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up = enb_properties_p->enb_ipv4_address_for_S1U; + //gtpv1u_data_g.udp_data; + RC.nr_gtpv1u_data_g->seq_num = 0; + RC.nr_gtpv1u_data_g->restart_counter = 0; + + /* Initializing GTPv1-U stack */ + if ((rc = nwGtpv1uInitialize(&RC.nr_gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) { + LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc); + return -1; + } + + if ((rc = nwGtpv1uSetLogLevel(RC.nr_gtpv1u_data_g->gtpv1u_stack, + NW_LOG_LEVEL_DEBG)) != NW_GTPV1U_OK) { + LOG_E(GTPU, "Failed to setup loglevel for stack %x\n", rc); + return -1; + } + + /* Set the ULP API callback. Called once message have been processed by the + * nw-gtpv1u stack. + */ + ulp.ulpReqCallback = nr_gtpv1u_gNB_process_stack_req; + memset((void *)&(ulp.hUlp), 0, sizeof(NwGtpv1uUlpHandleT)); + + if ((rc = nwGtpv1uSetUlpEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) { + LOG_E(GTPU, "nwGtpv1uSetUlpEntity: %x", rc); + return -1; + } + + /* nw-gtpv1u stack requires an udp callback to send data over UDP. + * We provide a wrapper to UDP task. + */ + udp.udpDataReqCallback = gtpv1u_eNB_send_udp_msg; + memset((void *)&(udp.hUdp), 0, sizeof(NwGtpv1uUdpHandleT)); + + if ((rc = nwGtpv1uSetUdpEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &udp)) != NW_GTPV1U_OK) { + LOG_E(GTPU, "nwGtpv1uSetUdpEntity: %x", rc); + return -1; + } + + log.logReqCallback = gtpv1u_eNB_log_request; + memset((void *)&(log.logMgrHandle), 0, sizeof(NwGtpv1uLogMgrHandleT)); + + if ((rc = nwGtpv1uSetLogMgrEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &log)) != NW_GTPV1U_OK) { + LOG_E(GTPU, "nwGtpv1uSetLogMgrEntity: %x", rc); + return -1; + } + + /* Timer interface is more complicated as both wrappers doesn't send a message + * to the timer task but call the timer API functions start/stop timer. + */ + tmr.tmrMgrHandle = 0; + tmr.tmrStartCallback = gtpv1u_start_timer_wrapper; + tmr.tmrStopCallback = gtpv1u_stop_timer_wrapper; + + if ((rc = nwGtpv1uSetTimerMgrEntity(RC.nr_gtpv1u_data_g->gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) { + LOG_E(GTPU, "nwGtpv1uSetTimerMgrEntity: %x", rc); + return -1; + } + +#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0 + + if ((ret = gtpv1u_eNB_create_dump_socket()) < 0) { + return -1; + } + +#endif + LOG_D(GTPU, "Initializing GTPV1U interface for eNB: DONE\n"); + return 0; +} + +//----------------------------------------------------------------------------- +int +gtpv1u_create_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP) +{ + /* Create a new nw-gtpv1-u stack req using API */ + NwGtpv1uUlpApiT stack_req; + NwGtpv1uRcT rc = NW_GTPV1U_FAILURE; + /* Local tunnel end-point identifier */ + teid_t ngu_teid = 0; + nr_gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; + //MessageDef *message_p = NULL; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + int i; + pdusessionid_t pdusession_id = 0; + // int ipv4_addr = 0; + int ip_offset = 0; + in_addr_t in_addr; + int addrs_length_in_bytes= 0; + int loop_counter = 0; + int ret = 0; + MSC_LOG_RX_MESSAGE( + MSC_GTPU_GNB, + MSC_RRC_GNB, + NULL,0, + MSC_AS_TIME_FMT" CREATE_TUNNEL_REQ RNTI %"PRIx16" inst %u ntuns %u psid %u upf-ngu teid %u", + 0,0,create_tunnel_req_pP->rnti, instanceP, + create_tunnel_req_pP->num_tunnels, create_tunnel_req_pP->pdusession_id[0], + create_tunnel_req_pP->upf_NGu_teid[0]); + create_tunnel_resp_pP->rnti = create_tunnel_req_pP->rnti; + create_tunnel_resp_pP->status = 0; + create_tunnel_resp_pP->num_tunnels = 0; + + for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) { + ip_offset = 0; + loop_counter = 0; + pdusession_id = create_tunnel_req_pP->pdusession_id[i]; + LOG_D(GTPU, "Rx GTPV1U_GNB_CREATE_TUNNEL_REQ ue rnti %x pdu session id %u\n", + create_tunnel_req_pP->rnti, pdusession_id); + memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT)); + stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT; + + do { + ngu_teid = gtpv1u_new_teid(); + LOG_D(GTPU, "gtpv1u_create_ngu_tunnel() 0x%x %u(dec)\n", ngu_teid, ngu_teid); + stack_req.apiInfo.createTunnelEndPointInfo.teid = ngu_teid; + stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession = 0; + stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0; + rc = nwGtpv1uProcessUlpReq(RC.nr_gtpv1u_data_g->gtpv1u_stack, &stack_req); + LOG_D(GTPU, ".\n"); + loop_counter++; + } while (rc != NW_GTPV1U_OK && loop_counter < 10); + + if ( rc != NW_GTPV1U_OK && loop_counter == 10 ) { + LOG_E(GTPU,"NwGtpv1uCreateTunnelEndPoint failed 10 times,start next loop\n"); + ret = -1; + continue; + } + + //----------------------- + // PDCP->GTPV1U mapping + //----------------------- + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, (void **)>pv1u_ue_data_p); + + if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_OK)) { + if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { + gtpv1u_ue_data_p = calloc (1, sizeof(gtpv1u_ue_data_t)); + hash_rc = hashtable_insert(RC.nr_gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p); + AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable"); + } + + gtpv1u_ue_data_p->ue_id = create_tunnel_req_pP->rnti; + gtpv1u_ue_data_p->instance_id = 0; // TO DO + memcpy(&create_tunnel_resp_pP->gnb_addr.buffer, + &RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up, + sizeof (in_addr_t)); + + LOG_I(GTPU,"Configured GTPu address : %x\n",RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up); + create_tunnel_resp_pP->gnb_addr.length = sizeof (in_addr_t); + addrs_length_in_bytes = create_tunnel_req_pP->upf_addr[i].length / 8; + AssertFatal((addrs_length_in_bytes == 4) || + (addrs_length_in_bytes == 16) || + (addrs_length_in_bytes == 20), + "Bad transport layer address length %d (bits) %d (bytes)", + create_tunnel_req_pP->upf_addr[i].length, addrs_length_in_bytes); + + if ((addrs_length_in_bytes == 4) || + (addrs_length_in_bytes == 20)) { + in_addr = *((in_addr_t *)create_tunnel_req_pP->upf_addr[i].buffer); + ip_offset = 4; + gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].upf_ip_addr = in_addr; + } + + if ((addrs_length_in_bytes == 16) || + (addrs_length_in_bytes == 20)) { + memcpy(gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].upf_ip6_addr.s6_addr, + &create_tunnel_req_pP->upf_addr[i].buffer[ip_offset], + 16); + } + + gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].state = BEARER_IN_CONFIG; + gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_gNB = ngu_teid; + gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_gNB_stack_session = stack_req.apiInfo.createTunnelEndPointInfo.hStackSession; + gtpv1u_ue_data_p->bearers[pdusession_id - GTPV1U_BEARER_OFFSET].teid_upf = create_tunnel_req_pP->upf_NGu_teid[i]; + gtpv1u_ue_data_p->num_bearers++; + create_tunnel_resp_pP->gnb_NGu_teid[i] = ngu_teid; + + LOG_I(GTPU,"Copied to create_tunnel_resp tunnel: index %d target gNB ip %d.%d.%d.%d length %d gtp teid %u\n", + i, + create_tunnel_resp_pP->gnb_addr.buffer[0], + create_tunnel_resp_pP->gnb_addr.buffer[1], + create_tunnel_resp_pP->gnb_addr.buffer[2], + create_tunnel_resp_pP->gnb_addr.buffer[3], + create_tunnel_resp_pP->gnb_addr.length, + create_tunnel_resp_pP->gnb_NGu_teid[i]); + } else { + create_tunnel_resp_pP->gnb_NGu_teid[i] = 0; + create_tunnel_resp_pP->status = 0xFF; + } + + create_tunnel_resp_pP->pdusession_id[i] = pdusession_id; + create_tunnel_resp_pP->num_tunnels += 1; + //----------------------- + // GTPV1U->PDCP mapping + //----------------------- + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid, (void **)>pv1u_teid_data_p); + + if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { + gtpv1u_teid_data_p = calloc (1, sizeof(nr_gtpv1u_teid_data_t)); + gtpv1u_teid_data_p->gnb_id = 0; // TO DO + gtpv1u_teid_data_p->ue_id = create_tunnel_req_pP->rnti; + gtpv1u_teid_data_p->pdu_session_id = pdusession_id; + hash_rc = hashtable_insert(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid, gtpv1u_teid_data_p); + AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable"); + } else { + create_tunnel_resp_pP->gnb_NGu_teid[i] = 0; + create_tunnel_resp_pP->status = 0xFF; + } + } + + MSC_LOG_TX_MESSAGE( + MSC_GTPU_GNB, + MSC_RRC_GNB, + NULL,0, + "0 GTPV1U_GNB_CREATE_TUNNEL_RESP rnti %x teid %x", + create_tunnel_resp_pP->rnti, + ngu_teid); + LOG_D(GTPU, "Tx GTPV1U_GNB_CREATE_TUNNEL_RESP ue rnti %x status %d\n", + create_tunnel_req_pP->rnti, + create_tunnel_resp_pP->status); + //return 0; + return ret; +} + +int gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +) { + /* Local tunnel end-point identifier */ + teid_t ngu_teid = 0; + nr_gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_new_p = NULL; + //MessageDef *message_p = NULL; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + int i,j; + uint8_t bearers_num = 0,bearers_total = 0; + //----------------------- + // PDCP->GTPV1U mapping + //----------------------- + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, prior_rnti, (void **)>pv1u_ue_data_p); + + if(hash_rc != HASH_TABLE_OK) { + LOG_E(GTPU,"Error get ue_mapping(rnti=%x) from GTPV1U hashtable error\n", prior_rnti); + return -1; + } + + gtpv1u_ue_data_new_p = calloc (1, sizeof(nr_gtpv1u_ue_data_t)); + memcpy(gtpv1u_ue_data_new_p,gtpv1u_ue_data_p,sizeof(nr_gtpv1u_ue_data_t)); + gtpv1u_ue_data_new_p->ue_id = create_tunnel_req_pP->rnti; + hash_rc = hashtable_insert(RC.nr_gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p); + + //AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable"); + if ( hash_rc != HASH_TABLE_OK ) { + LOG_E(GTPU,"Failed to insert ue_mapping(rnti=%x) in GTPV1U hashtable\n",create_tunnel_req_pP->rnti); + return -1; + } else { + LOG_I(GTPU, "inserting ue_mapping(rnti=%x) in GTPV1U hashtable\n", + create_tunnel_req_pP->rnti); + } + + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->ue_mapping, prior_rnti); + LOG_I(GTPU, "hashtable_remove ue_mapping(rnti=%x) in GTPV1U hashtable\n", + prior_rnti); + //----------------------- + // GTPV1U->PDCP mapping + //----------------------- + bearers_total =gtpv1u_ue_data_new_p->num_bearers; + + for(j = 0; jbearers[j].state != BEARER_IN_CONFIG) + continue; + + bearers_num++; + + for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) { + if(j == (create_tunnel_req_pP->pdusession_id[i]-GTPV1U_BEARER_OFFSET)) + break; + } + + if(i < create_tunnel_req_pP->num_tunnels) { + ngu_teid = gtpv1u_ue_data_new_p->bearers[j].teid_gNB; + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid, (void **)>pv1u_teid_data_p); + + if (hash_rc == HASH_TABLE_OK) { + gtpv1u_teid_data_p->ue_id = create_tunnel_req_pP->rnti; + gtpv1u_teid_data_p->pdu_session_id = create_tunnel_req_pP->pdusession_id[i]; + LOG_I(GTPU, "updata teid_mapping te_id %u (prior_rnti %x rnti %x) in GTPV1U hashtable\n", + ngu_teid,prior_rnti,create_tunnel_req_pP->rnti); + } else { + LOG_W(GTPU, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", ngu_teid); + } + } else { + ngu_teid = gtpv1u_ue_data_new_p->bearers[j].teid_gNB; + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid); + + if (hash_rc != HASH_TABLE_OK) { + LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", prior_rnti, ngu_teid); + } + + gtpv1u_ue_data_new_p->bearers[j].state = BEARER_DOWN; + gtpv1u_ue_data_new_p->num_bearers--; + LOG_I(GTPU, "delete teid_mapping te_id %u (rnti%x) bearer_id %d in GTPV1U hashtable\n", + ngu_teid,prior_rnti,j+GTPV1U_BEARER_OFFSET);; + } + + if(bearers_num > bearers_total) + break; + } + + return 0; +} + +//----------------------------------------------------------------------------- +int gtpv1u_delete_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_delete_tunnel_req_t *const req_pP) { + NwGtpv1uUlpApiT stack_req; + NwGtpv1uRcT rc = NW_GTPV1U_FAILURE; + MessageDef *message_p = NULL; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + teid_t teid_gNB = 0; + int pdusession_index = 0; + message_p = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_GNB_DELETE_TUNNEL_RESP); + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti = req_pP->rnti; + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status = 0; + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, req_pP->rnti, (void **)>pv1u_ue_data_p); + + if (hash_rc == HASH_TABLE_OK) { + for (pdusession_index = 0; pdusession_index < req_pP->num_pdusession; pdusession_index++) { + teid_gNB = gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB; + LOG_D(GTPU, "Rx GTPV1U_ENB_DELETE_TUNNEL user rnti %x eNB S1U teid %u eps bearer id %u\n", + req_pP->rnti, teid_gNB, req_pP->pdusession_id[pdusession_index]); + { + memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT)); + stack_req.apiType = NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT; + LOG_D(GTPU, "gtpv1u_delete_ngu_tunnel pdusession %u %u\n", + req_pP->pdusession_id[pdusession_index], + teid_gNB); + stack_req.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle = + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB_stack_session; + rc = nwGtpv1uProcessUlpReq(RC.nr_gtpv1u_data_g->gtpv1u_stack, &stack_req); + LOG_D(GTPU, ".\n"); + } + + if (rc != NW_GTPV1U_OK) { + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status |= 0xFF; + LOG_E(GTPU, "NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT failed"); + } + + //----------------------- + // PDCP->GTPV1U mapping + //----------------------- + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].state = BEARER_DOWN; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB = 0; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_upf = 0; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].upf_ip_addr = 0; + gtpv1u_ue_data_p->num_bearers -= 1; + + if (gtpv1u_ue_data_p->num_bearers == 0) { + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->ue_mapping, req_pP->rnti); + LOG_D(GTPU, "Removed user rnti %x,no more bearers configured\n", req_pP->rnti); + } + + //----------------------- + // GTPV1U->PDCP mapping + //----------------------- + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->teid_mapping, teid_gNB); + + if (hash_rc != HASH_TABLE_OK) { + LOG_D(GTPU, "Removed user rnti %x , gNB NGU teid %u not found\n", req_pP->rnti, teid_gNB); + } + } + }// else silently do nothing + + LOG_D(GTPU, "Tx GTPV1U_GNB_DELETE_TUNNEL_RESP user rnti %x gNB NGU teid %u status %u\n", + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti, + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).gnb_NGu_teid, + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status); + MSC_LOG_TX_MESSAGE( + MSC_GTPU_GNB, + MSC_RRC_GNB, + NULL,0, + "0 GTPV1U_GNB_DELETE_TUNNEL_RESP rnti %x teid %x", + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti, + teid_gNB); + return itti_send_msg_to_task(TASK_RRC_GNB, instanceP, message_p); +} + +//----------------------------------------------------------------------------- +static int gtpv1u_gNB_send_init_udp(const Gtpv1uNGReq *req) { + // Create and alloc new message + MessageDef *message_p; + struct in_addr addr= {0}; + message_p = itti_alloc_new_message(TASK_GTPV1_U, 0, UDP_INIT); + + if (message_p == NULL) { + return -1; + } + + UDP_INIT(message_p).port = req->gnb_port_for_NGu_up; + addr.s_addr = req->gnb_ip_address_for_NGu_up; + UDP_INIT(message_p).address = inet_ntoa(addr); + LOG_I(GTPU, "Tx UDP_INIT IP addr %s (%x)\n", UDP_INIT(message_p).address,UDP_INIT(message_p).port); + MSC_LOG_EVENT( + MSC_GTPU_ENB, + "0 UDP bind %s:%u", + UDP_INIT(message_p).address, + UDP_INIT(message_p).port); + return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p); +} + +static int gtpv1u_ng_req( + const instance_t instanceP, + const Gtpv1uNGReq *const req) { + memcpy(&RC.nr_gtpv1u_data_g->gnb_ip_address_for_NGu_up, + &req->gnb_ip_address_for_NGu_up, + sizeof (req->gnb_ip_address_for_NGu_up)); + gtpv1u_gNB_send_init_udp(req); + return 0; +} + +static int gtpv1u_gnb_tunnel_data_req(gtpv1u_gnb_tunnel_data_req_t *gnb_tunnel_data_req) { + gtpv1u_gnb_tunnel_data_req_t *data_req_p = NULL; + NwGtpv1uUlpApiT stack_req; + NwGtpv1uRcT rc = NW_GTPV1U_FAILURE; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; + teid_t gnb_ngu_teid = 0; + teid_t upf_ngu_teid = 0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN); + data_req_p = gnb_tunnel_data_req; + + memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT)); + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void **)>pv1u_ue_data_p); + + if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { + LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti); + } else { + if ((data_req_p->pdusession_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->pdusession_id < max_val_NR_DRB_Identity)) { + gnb_ngu_teid = gtpv1u_ue_data_p->bearers[data_req_p->pdusession_id - GTPV1U_BEARER_OFFSET].teid_gNB; + upf_ngu_teid = gtpv1u_ue_data_p->bearers[data_req_p->pdusession_id - GTPV1U_BEARER_OFFSET].teid_upf; + stack_req.apiType = NW_GTPV1U_ULP_API_SEND_TPDU; + stack_req.apiInfo.sendtoInfo.teid = upf_ngu_teid; + stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->pdusession_id - GTPV1U_BEARER_OFFSET].upf_ip_addr; + rc = nwGtpv1uGpduMsgNew( + RC.nr_gtpv1u_data_g->gtpv1u_stack, + upf_ngu_teid, + NW_FALSE, + RC.nr_gtpv1u_data_g->seq_num++, + data_req_p->buffer, + data_req_p->length, + data_req_p->offset, + &(stack_req.apiInfo.sendtoInfo.hMsg)); + + if (rc != NW_GTPV1U_OK) { + LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc); + MSC_LOG_EVENT(MSC_GTPU_GNB,"0 Failed send G-PDU ltid %u rtid %u size %u", + gnb_ngu_teid,upf_ngu_teid,data_req_p->length); + (void)gnb_ngu_teid; /* avoid gcc warning "set but not used" */ + } else { + rc = nwGtpv1uProcessUlpReq(RC.nr_gtpv1u_data_g->gtpv1u_stack, &stack_req); + + if (rc != NW_GTPV1U_OK) { + LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc); + MSC_LOG_EVENT(MSC_GTPU_GNB,"0 Failed send G-PDU ltid %u rtid %u size %u", + gnb_ngu_teid,upf_ngu_teid,data_req_p->length); + } else { + MSC_LOG_TX_MESSAGE( + MSC_GTPU_GNB, + MSC_GTPU_SGW, + NULL, + 0, + MSC_AS_TIME_FMT" G-PDU ltid %u rtid %u size %u", + 0,0, + gnb_ngu_teid, + upf_ngu_teid, + data_req_p->length); + } + + rc = nwGtpv1uMsgDelete(RC.nr_gtpv1u_data_g->gtpv1u_stack, + stack_req.apiInfo.sendtoInfo.hMsg); + + if (rc != NW_GTPV1U_OK) { + LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc); + } + } + } + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT); + /* Buffer still needed, do not free it */ + //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer); + + return 0; +} + +//----------------------------------------------------------------------------- +void *gtpv1u_gNB_process_itti_msg(void *notUsed) { + /* Trying to fetch a message from the message queue. + * If the queue is empty, this function will block till a + * message is sent to the task. + */ + instance_t instance; + MessageDef *received_message_p = NULL; + int rc = 0; + itti_receive_msg(TASK_GTPV1_U, &received_message_p); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN); + DevAssert(received_message_p != NULL); + instance = received_message_p->ittiMsgHeader.originInstance; + + switch (ITTI_MSG_ID(received_message_p)) { + case GTPV1U_GNB_NG_REQ: + gtpv1u_ng_req(instance, &received_message_p->ittiMsg.gtpv1uNGReq); + break; + + case GTPV1U_GNB_DELETE_TUNNEL_REQ: + gtpv1u_delete_ngu_tunnel(instance, &received_message_p->ittiMsg.NRGtpv1uDeleteTunnelReq); + break; + + // DATA COMING FROM UDP + case UDP_DATA_IND: { + udp_data_ind_t *udp_data_ind_p; + udp_data_ind_p = &received_message_p->ittiMsg.udp_data_ind; + nwGtpv1uProcessUdpReq(RC.nr_gtpv1u_data_g->gtpv1u_stack, + udp_data_ind_p->buffer, + udp_data_ind_p->buffer_length, + udp_data_ind_p->peer_port, + udp_data_ind_p->peer_address); + } + break; + + // DATA TO BE SENT TO UDP + case GTPV1U_GNB_TUNNEL_DATA_REQ: + LOG_I(GTPU, "Received message %s\n", ITTI_MSG_NAME(received_message_p)); + gtpv1u_gnb_tunnel_data_req(>PV1U_GNB_TUNNEL_DATA_REQ(received_message_p)); + break; + + case TERMINATE_MESSAGE: { + if (RC.nr_gtpv1u_data_g->ue_mapping != NULL) { + hashtable_destroy (&(RC.nr_gtpv1u_data_g->ue_mapping)); + } + + if (RC.nr_gtpv1u_data_g->teid_mapping != NULL) { + hashtable_destroy (&(RC.nr_gtpv1u_data_g->teid_mapping)); + } + + LOG_W(GTPU, " *** Exiting GTPU thread\n"); + itti_exit_task(); + } + break; + + case TIMER_HAS_EXPIRED: + nwGtpv1uProcessTimeout(&received_message_p->ittiMsg.timer_has_expired.arg); + break; + + default: { + LOG_E(GTPU, "Unkwnon message ID %d:%s\n", + ITTI_MSG_ID(received_message_p), + ITTI_MSG_NAME(received_message_p)); + } + break; + } + + rc = itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p); + AssertFatal(rc == EXIT_SUCCESS, "Failed to free memory (%d)!\n", rc); + received_message_p = NULL; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_OUT); + return NULL; +} + +void *nr_gtpv1u_gNB_task(void *args) { + int rc = 0; + rc = nr_gtpv1u_gNB_init(); + AssertFatal(rc == 0, "gtpv1u_gNB_init Failed"); + itti_mark_task_ready(TASK_GTPV1_U); + MSC_START_USE(); + + while(1) { + (void) gtpv1u_gNB_process_itti_msg (NULL); + } + + return NULL; +} diff --git a/openair3/GTPV1-U/gtpv1u_gNB_defs.h b/openair3/GTPV1-U/gtpv1u_gNB_defs.h new file mode 100644 index 0000000000..d4356aa3cf --- /dev/null +++ b/openair3/GTPV1-U/gtpv1u_gNB_defs.h @@ -0,0 +1,108 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file gtpv1u_gNB_defs.h + * \brief + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#include "hashtable.h" +#include "NR_asn_constant.h" + +#ifndef GTPV1U_GNB_DEFS_H_ +#define GTPV1U_GNB_DEFS_H_ + +#include "NwGtpv1u.h" + +#define GTPV1U_UDP_PORT (2152) + +#define NR_GTPV1U_MAX_BEARERS_ID (max_val_NR_DRB_Identity - 3) + +#define GTPV1U_SOURCE_GNB (0) +#define GTPV1U_TARGET_GNB (1) +#define GTPV1U_MSG_FROM_SOURCE_GNB (0) +#define GTPV1U_MSG_FROM_UPF (1) + + +typedef struct nr_gtpv1u_teid_data_s { + /* UE identifier for oaisim stack */ + module_id_t gnb_id; + rnti_t ue_id; + pdusessionid_t pdu_session_id; +} nr_gtpv1u_teid_data_t; + + +typedef struct nr_gtpv1u_bearer_s { + /* TEID used in dl and ul */ + teid_t teid_gNB; ///< gNB TEID + uintptr_t teid_gNB_stack_session; ///< gNB TEID + teid_t teid_upf; ///< Remote TEID + in_addr_t upf_ip_addr; + struct in6_addr upf_ip6_addr; + teid_t teid_tgNB; + in_addr_t tgnb_ip_addr; ///< target gNB ipv4 + struct in6_addr tgnb_ip6_addr; ///< target gNB ipv6 + tcp_udp_port_t port; + //NwGtpv1uStackSessionHandleT stack_session; + bearer_state_t state; +} nr_gtpv1u_bearer_t; + +typedef struct nr_gtpv1u_ue_data_s { + /* UE identifier for oaisim stack */ + rnti_t ue_id; + + /* Unique identifier used between PDCP and GTP-U to distinguish UEs */ + uint32_t instance_id; + int num_bearers; + /* Bearer related data. + * Note that the first LCID available for data is 3 and we fixed the maximum + * number of e-rab per UE to be (32 [id range]), max RB is 11. The real rb id will 3 + rab_id (3..32). + */ + nr_gtpv1u_bearer_t bearers[NR_GTPV1U_MAX_BEARERS_ID]; + + //RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node; +} nr_gtpv1u_ue_data_t; + +typedef struct nr_gtpv1u_data_s { + /* nwgtpv1u stack internal data */ + NwGtpv1uStackHandleT gtpv1u_stack; + + /* RB tree of UEs */ + hash_table_t *ue_mapping; // PDCP->GTPV1U + hash_table_t *teid_mapping; // GTPV1U -> PDCP + + //RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head; + /* Local IP address to use */ + in_addr_t gnb_ip_address_for_NGu_up; + /* UDP internal data */ + //udp_data_t udp_data; + + uint16_t seq_num; + uint8_t restart_counter; + +} nr_gtpv1u_data_t; + + +#endif /* GTPV1U_GNB_DEFS_H_ */ diff --git a/openair3/GTPV1-U/gtpv1u_gNB_task.h b/openair3/GTPV1-U/gtpv1u_gNB_task.h index 42fae7a714..fcfaa90304 100644 --- a/openair3/GTPV1-U/gtpv1u_gNB_task.h +++ b/openair3/GTPV1-U/gtpv1u_gNB_task.h @@ -32,6 +32,20 @@ int gtpv1u_gNB_init(void); void *gtpv1u_gNB_task(void *args); +void *nr_gtpv1u_gNB_task(void *args); + +int +gtpv1u_create_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP); + +int +gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +); #endif /* GTPV1U_GNB_TASK_H_ */ diff --git a/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c b/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c index 0c7663921b..0d962cad7d 100644 --- a/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c +++ b/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c @@ -59,6 +59,7 @@ extern "C" { #endif +//#define LOG_GTPU 1 /*--------------------------------------------------------------------------* * P R I V A T E F U N C T I O N S * *--------------------------------------------------------------------------*/ @@ -900,7 +901,7 @@ nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle, case NW_GTP_END_MARKER: #if defined(LOG_GTPU) && LOG_GTPU > 0 for(int i =1; i<= udpDataLen; i++){ - printf("%02x ", udpData[i-1]); + printf("%02x ", (uint8_t)udpData[i-1]); if(i % 20 == 0)printf("\n"); } #endif diff --git a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniLogMgrEntity.h b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniLogMgrEntity.h index 8f2908e52a..18b60aa611 100644 --- a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniLogMgrEntity.h +++ b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniLogMgrEntity.h @@ -16,13 +16,13 @@ #include "NwEvt.h" #include "NwLog.h" +#ifndef __NW_MINI_LOG_MGR_H__ +#define __NW_MINI_LOG_MGR_H__ + #ifndef NW_ASSERT #define NW_ASSERT assert #endif -#ifndef __NW_MINI_LOG_MGR_H__ -#define __NW_MINI_LOG_MGR_H__ - extern uint32_t g_log_level; diff --git a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniTmrMgrEntity.h b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniTmrMgrEntity.h index b17228c9cf..a1f16ff89b 100644 --- a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniTmrMgrEntity.h +++ b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniTmrMgrEntity.h @@ -17,13 +17,13 @@ #include "NwEvt.h" #include "NwLog.h" +#ifndef __NW_MINI_TMR_MGR_H__ +#define __NW_MINI_TMR_MGR_H__ + #ifndef NW_ASSERT #define NW_ASSERT assert #endif -#ifndef __NW_MINI_TMR_MGR_H__ -#define __NW_MINI_TMR_MGR_H__ - typedef struct { NwEventT ev; void* timeoutArg; diff --git a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniUdpEntity.h b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniUdpEntity.h index 2e19ebbb8e..568c5b0796 100644 --- a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniUdpEntity.h +++ b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniUdpEntity.h @@ -17,13 +17,13 @@ #include "NwEvt.h" #include "NwLog.h" +#ifndef __NW_MINI_UDP_ENTITY_H__ +#define __NW_MINI_UDP_ENTITY_H__ + #ifndef NW_ASSERT #define NW_ASSERT assert #endif -#ifndef __NW_MINI_UDP_ENTITY_H__ -#define __NW_MINI_UDP_ENTITY_H__ - typedef struct { uint32_t hSocket; NwEventT ev; diff --git a/openair3/M3AP/m3ap_MCE.c b/openair3/M3AP/m3ap_MCE.c index dec9b96897..9362c8fcb6 100644 --- a/openair3/M3AP/m3ap_MCE.c +++ b/openair3/M3AP/m3ap_MCE.c @@ -136,7 +136,7 @@ void m3ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_associa //dump_trees_m3(); if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - M3AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", + M3AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", sctp_new_association_resp->sctp_state, instance, sctp_new_association_resp->ulp_cnx_id); @@ -229,7 +229,7 @@ int m3ap_MCE_init_sctp (m3ap_MCE_instance_t *instance_p, sctp_init_t *sctp_init = NULL; DevAssert(instance_p != NULL); DevAssert(local_ip_addr != NULL); - message = itti_alloc_new_message (TASK_M3AP_MCE, SCTP_INIT_MSG_MULTI_REQ); + message = itti_alloc_new_message (TASK_M3AP_MCE, 0, SCTP_INIT_MSG_MULTI_REQ); sctp_init = &message->ittiMsg.sctp_init_multi; sctp_init->port = mce_port_for_M3C; sctp_init->ppid = M3AP_SCTP_PPID; @@ -263,7 +263,7 @@ static void m3ap_MCE_register_MCE(m3ap_MCE_instance_t *instance_p, m3ap_MCE_data_t *m3ap_mce_data = NULL; DevAssert(instance_p != NULL); DevAssert(target_MCE_ip_address != NULL); - message = itti_alloc_new_message(TASK_M3AP_MCE, SCTP_NEW_ASSOCIATION_REQ_MULTI); + message = itti_alloc_new_message(TASK_M3AP_MCE, 0, SCTP_NEW_ASSOCIATION_REQ_MULTI); sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi; sctp_new_association_req->port = mce_port_for_M3C; sctp_new_association_req->ppid = M3AP_SCTP_PPID; @@ -313,7 +313,7 @@ void m3ap_MCE_handle_register_MCE(instance_t instance, DevCheck(new_instance->tac == m3ap_register_MCE->tac, new_instance->tac, m3ap_register_MCE->tac, 0); DevCheck(new_instance->mcc == m3ap_register_MCE->mcc, new_instance->mcc, m3ap_register_MCE->mcc, 0); DevCheck(new_instance->mnc == m3ap_register_MCE->mnc, new_instance->mnc, m3ap_register_MCE->mnc, 0); - M3AP_WARN("MCE[%d] already registered\n", instance); + M3AP_WARN("MCE[%ld] already registered\n", instance); } else { new_instance = calloc(1, sizeof(m3ap_MCE_instance_t)); DevAssert(new_instance != NULL); @@ -357,7 +357,7 @@ void m3ap_MCE_handle_register_MCE(instance_t instance, new_instance->mce_port_for_M3C = m3ap_register_MCE->mme_port_for_M3C; /* Add the new instance to the list of MCE (meaningfull in virtual mode) */ m3ap_MCE_insert_new_instance(new_instance); - M3AP_INFO("Registered new MCE[%d] and %s MCE id %u\n", + M3AP_INFO("Registered new MCE[%ld] and %s MCE id %u\n", instance, m3ap_register_MCE->cell_type == CELL_MACRO_ENB ? "macro" : "home", m3ap_register_MCE->MCE_id); @@ -370,7 +370,7 @@ void m3ap_MCE_handle_register_MCE(instance_t instance, return; } - M3AP_INFO("MCE[%d] MCE id %u acting as a listner (server)\n", + M3AP_INFO("MCE[%ld] MCE id %u acting as a listner (server)\n", instance, m3ap_register_MCE->MCE_id); } } @@ -397,7 +397,7 @@ void m3ap_MCE_handle_sctp_init_msg_multi_cnf( /* Trying to connect to the provided list of MCE ip address */ for (index = 0; index < instance->nb_m3; index++) { - M3AP_INFO("MCE[%d] MCE id %u acting as an initiator (client)\n", + M3AP_INFO("MCE[%ld] MCE id %u acting as an initiator (client)\n", instance_id, instance->MCE_id); m3ap_MCE_register_MCE(instance, &instance->target_mme_m3_ip_address[index], @@ -537,7 +537,7 @@ void *m3ap_MCE_task(void *arg) { switch (ITTI_MSG_ID(received_msg)) { case MESSAGE_TEST: // LOG_W(M3AP,"MCE Received Test Message ... TODO\n"); -// //MessageDef * message_p = itti_alloc_new_message(TASK_M3AP, MESSAGE_TEST); +// //MessageDef * message_p = itti_alloc_new_message(TASK_M3AP, 0, MESSAGE_TEST); // //itti_send_msg_to_task(TASK_M2AP_ENB, 1/*ctxt_pP->module_id*/, message_p); // // asn_dec_rval_t dec_ret; @@ -577,78 +577,78 @@ void *m3ap_MCE_task(void *arg) { break; case M3AP_SUBFRAME_PROCESS: - m3ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg)); + m3ap_check_timers(ITTI_MSG_DESTINATION_INSTANCE(received_msg)); break; case M3AP_REGISTER_MCE_REQ: LOG_I(M3AP,"MCE Received M3AP_REGISTER_MCE_REQ Message\n"); - m3ap_MCE_handle_register_MCE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MCE_handle_register_MCE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M3AP_REGISTER_MCE_REQ(received_msg)); break; case M3AP_MBMS_SESSION_START_RESP: LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_START_RESP Message\n"); - MCE_send_MBMS_SESSION_START_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MCE_send_MBMS_SESSION_START_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M3AP_MBMS_SESSION_START_RESP(received_msg)); break; case M3AP_MBMS_SESSION_STOP_RESP: LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_STOP_RESP Message\n"); - MCE_send_MBMS_SESSION_STOP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MCE_send_MBMS_SESSION_STOP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M3AP_MBMS_SESSION_START_RESP(received_msg)); break; case M3AP_MBMS_SESSION_UPDATE_RESP: LOG_I(M3AP,"MCE M3AP_MBMS_SESSION_UPDATE_RESP Message\n"); - //MCE_send_MBMS_SESSION_UPDATE_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + //MCE_send_MBMS_SESSION_UPDATE_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), //&M3AP_MBMS_SESSION_START_RESP(received_msg)); break; // case M3AP_HANDOVER_REQ: -// m3ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m3ap_eNB_handle_handover_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_HANDOVER_REQ(received_msg)); // break; // // case M3AP_HANDOVER_REQ_ACK: -// m3ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m3ap_eNB_handle_handover_req_ack(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_HANDOVER_REQ_ACK(received_msg)); // break; // // case M3AP_UE_CONTEXT_RELEASE: -// m3ap_eNB_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m3ap_eNB_ue_context_release(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_UE_CONTEXT_RELEASE(received_msg)); // break; // case SCTP_INIT_MSG_MULTI_CNF: LOG_D(M3AP,"MCE Received SCTP_INIT_MSG_MULTI_CNF Message\n"); - m3ap_MCE_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MCE_handle_sctp_init_msg_multi_cnf(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_init_msg_multi_cnf); break; case SCTP_NEW_ASSOCIATION_RESP: LOG_D(M3AP,"MCE Received SCTP_NEW_ASSOCIATION_RESP Message\n"); - m3ap_MCE_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MCE_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_NEW_ASSOCIATION_IND: LOG_D(M3AP,"MCE Received SCTP_NEW_ASSOCIATION Message\n"); - m3ap_MCE_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MCE_handle_sctp_association_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_ind); break; case SCTP_DATA_IND: LOG_D(M3AP,"MCE Received SCTP_DATA_IND Message\n"); - m3ap_MCE_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MCE_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; diff --git a/openair3/M3AP/m3ap_MCE_handler.c b/openair3/M3AP/m3ap_MCE_handler.c index e733af28db..21d10d1b04 100644 --- a/openair3/M3AP/m3ap_MCE_handler.c +++ b/openair3/M3AP/m3ap_MCE_handler.c @@ -108,7 +108,7 @@ int m3ap_MCE_handle_message(instance_t instance, uint32_t assoc_id, int32_t stre } /* Calling the right handler */ - LOG_I(M3AP, "Calling handler with instance %d\n",instance); + LOG_I(M3AP, "Calling handler with instance %ld\n",instance); ret = (*m3ap_MCE_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1]) (instance, assoc_id, stream, &pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu); diff --git a/openair3/M3AP/m3ap_MCE_interface_management.c b/openair3/M3AP/m3ap_MCE_interface_management.c index 2694846526..fb54579258 100644 --- a/openair3/M3AP/m3ap_MCE_interface_management.c +++ b/openair3/M3AP/m3ap_MCE_interface_management.c @@ -74,7 +74,7 @@ int MCE_handle_MBMS_SESSION_START_REQUEST(instance_t instance, // // container = &pdu->choice.initiatingMessage.value.choice.SessionStartRequest; - message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_START_REQ); + message_p = itti_alloc_new_message(TASK_M3AP_MCE, 0, M3AP_MBMS_SESSION_START_REQ); // // /* M3 Setup Request == Non UE-related procedure -> stream 0 */ @@ -248,7 +248,7 @@ int MCE_handle_MBMS_SESSION_STOP_REQUEST(instance_t instance, //MCE_send_MBMS_SESSION_STOP_RESPONSE(instance,assoc_id); //}else //MCE_send_MBMS_SESSION_STOP_FAILURE(instance,assoc_id); - message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_STOP_REQ); + message_p = itti_alloc_new_message(TASK_M3AP_MCE, 0, M3AP_MBMS_SESSION_STOP_REQ); // // /* M3 Setup Request == Non UE-related procedure -> stream 0 */ @@ -361,7 +361,7 @@ int MCE_handle_MBMS_SESSION_UPDATE_REQUEST(instance_t instance, //MCE_send_MBMS_SESSION_STOP_RESPONSE(instance,assoc_id); //}else //MCE_send_MBMS_SESSION_STOP_FAILURE(instance,assoc_id); - message_p = itti_alloc_new_message(TASK_M3AP_MCE, M3AP_MBMS_SESSION_UPDATE_REQ); + message_p = itti_alloc_new_message(TASK_M3AP_MCE, 0, M3AP_MBMS_SESSION_UPDATE_REQ); // // /* M3 Setup Request == Non UE-related procedure -> stream 0 */ @@ -711,7 +711,7 @@ int MCE_handle_M3_SETUP_RESPONSE(instance_t instance, //int num_cells_to_activate = 0; //M3AP_Cells_to_be_Activated_List_Item_t *cell; - MessageDef *msg_p = itti_alloc_new_message (TASK_M3AP_MCE, M3AP_SETUP_RESP); + MessageDef *msg_p = itti_alloc_new_message (TASK_M3AP_MCE, 0, M3AP_SETUP_RESP); // LOG_D(M3AP, "M3AP: M3Setup-Resp: protocolIEs.list.count %d\n", // in->protocolIEs.list.count); diff --git a/openair3/M3AP/m3ap_MCE_management_procedures.c b/openair3/M3AP/m3ap_MCE_management_procedures.c index 32901ca869..065d4b9616 100644 --- a/openair3/M3AP/m3ap_MCE_management_procedures.c +++ b/openair3/M3AP/m3ap_MCE_management_procedures.c @@ -116,7 +116,7 @@ void dump_trees_m3(void) m3ap_MCE_instance_t *zz; STAILQ_FOREACH(zz, &m3ap_MCE_internal_data.m3ap_MCE_instances_head, m3ap_MCE_entries) { -printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance); +printf("here comes the tree (instance %ld):\n---------------------------------------------\n", zz->instance); dump_tree_m3(zz->m3ap_mce_head.rbh_root); printf("---------------------------------------------\n"); } diff --git a/openair3/M3AP/m3ap_MME.c b/openair3/M3AP/m3ap_MME.c index fbfe6e1327..4d73caff23 100644 --- a/openair3/M3AP/m3ap_MME.c +++ b/openair3/M3AP/m3ap_MME.c @@ -105,7 +105,7 @@ void m3ap_MME_handle_sctp_association_resp(instance_t instance, sctp_new_associa DevAssert(sctp_new_association_resp != NULL); if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - LOG_W(M3AP, "Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", + LOG_W(M3AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", sctp_new_association_resp->sctp_state, instance, sctp_new_association_resp->ulp_cnx_id); @@ -233,7 +233,7 @@ int m3ap_MME_init_sctp (m3ap_MME_instance_t *instance_p, sctp_init_t *sctp_init = NULL; DevAssert(instance_p != NULL); DevAssert(local_ip_addr != NULL); - message = itti_alloc_new_message (TASK_M3AP_MME, SCTP_INIT_MSG_MULTI_REQ); + message = itti_alloc_new_message (TASK_M3AP_MME, 0, SCTP_INIT_MSG_MULTI_REQ); sctp_init = &message->ittiMsg.sctp_init_multi; sctp_init->port = mme_port_for_M3C; sctp_init->ppid = M3AP_SCTP_PPID; @@ -267,7 +267,7 @@ static void m3ap_MME_register_MME(m3ap_MME_instance_t *instance_p, // m3ap_MME_data_t *m3ap_mme_data = NULL; // DevAssert(instance_p != NULL); // DevAssert(target_MME_ip_address != NULL); - // message = itti_alloc_new_message(TASK_M3AP_MME, SCTP_NEW_ASSOCIATION_REQ_MULTI); + // message = itti_alloc_new_message(TASK_M3AP_MME, 0, SCTP_NEW_ASSOCIATION_REQ_MULTI); // sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi; // sctp_new_association_req->port = mme_port_for_M3C; // sctp_new_association_req->ppid = M3AP_SCTP_PPID; @@ -394,7 +394,7 @@ void m3ap_MME_handle_sctp_init_msg_multi_cnf( /* Trying to connect to the provided list of MME ip address */ for (index = 0; index < instance->nb_m3; index++) { - M3AP_INFO("MME[%d] MME id %u acting as an initiator (client)\n", + M3AP_INFO("MME[%ld] MME id %u acting as an initiator (client)\n", instance_id, instance->MME_id); m3ap_MME_register_MME(instance, &instance->target_mme_m3_ip_address[index], @@ -506,7 +506,7 @@ void MME_task_send_sctp_init_req(instance_t enb_id, m3ap_mme_sctp_req_t * m3ap_m MessageDef *message_p = NULL; - message_p = itti_alloc_new_message (TASK_M3AP_MME, SCTP_INIT_MSG); + message_p = itti_alloc_new_message (TASK_M3AP_MME, 0, SCTP_INIT_MSG); if(m3ap_mme_sctp_req==NULL) { LOG_I(M3AP, "M3AP_SCTP_REQ(create socket)\n"); message_p->ittiMsg.sctp_init.port = M3AP_PORT_NUMBER; @@ -555,7 +555,7 @@ void *m3ap_MME_task(void *arg) { switch (ITTI_MSG_ID(received_msg)) { case MESSAGE_TEST: LOG_W(M3AP,"MME Received MESSAGE_TEST Message\n"); - //MessageDef * message_p = itti_alloc_new_message(TASK_M3AP_MME, MESSAGE_TEST); + //MessageDef * message_p = itti_alloc_new_message(TASK_M3AP_MME, 0, MESSAGE_TEST); //itti_send_msg_to_task(TASK_M3AP, 1/*ctxt_pP->module_id*/, message_p); break; case TERMINATE_MESSAGE: @@ -564,31 +564,31 @@ void *m3ap_MME_task(void *arg) { break; // case M3AP_SUBFRAME_PROCESS: -// m3ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg)); +// m3ap_check_timers(ITTI_MSG_DESTINATION_INSTANCE(received_msg)); // break; // // case M3AP_REGISTER_MME_REQ: // LOG_W(M3AP,"MME Received M3AP_REGISTER_MME_REQ Message\n"); -// m3ap_MME_handle_register_MME(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m3ap_MME_handle_register_MME(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_REGISTER_MME_REQ(received_msg)); // break; // case M3AP_MME_SCTP_REQ: - MME_task_send_sctp_init_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MME_task_send_sctp_init_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M3AP_MME_SCTP_REQ(received_msg)); break; case M3AP_SETUP_RESP: LOG_I(M3AP,"MME Received M3AP_SETUP_RESP Message\n"); - MME_send_M3_SETUP_RESPONSE(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MME_send_M3_SETUP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M3AP_SETUP_RESP(received_msg)); break; // break; // // case M3AP_SETUP_FAILURE: // LOG_W(M3AP,"MME Received M3AP_SETUP_FAILURE Message\n"); -// MME_send_M2_SETUP_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// MME_send_M2_SETUP_FAILURE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_SETUP_FAILURE(received_msg)); // break; // @@ -599,83 +599,83 @@ void *m3ap_MME_task(void *arg) { // case M3AP_MBMS_SESSION_START_REQ: LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_START_REQ Message\n"); - MME_send_MBMS_SESSION_START_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MME_send_MBMS_SESSION_START_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M3AP_MBMS_SESSION_START_REQ(received_msg)); break; // case M3AP_MBMS_SESSION_STOP_REQ: LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_STOP_REQ Message\n"); - MME_send_MBMS_SESSION_STOP_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg), + MME_send_MBMS_SESSION_STOP_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &M3AP_MBMS_SESSION_STOP_REQ(received_msg)); break; // case M3AP_MBMS_SESSION_UPDATE_REQ: LOG_I(M3AP,"MME Received M3AP_MBMS_SESSION_UPDATE_REQ Message\n"); - // MME_send_MBMS_SESSION_UPDATE_REQUEST(ITTI_MESSAGE_GET_INSTANCE(received_msg), + // MME_send_MBMS_SESSION_UPDATE_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_MBMS_SESSION_UPDATE_REQ(received_msg)); break; // // case M3AP_RESET: // LOG_W(M3AP,"MME Received M3AP_RESET Message\n"); -// MME_send_RESET(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// MME_send_RESET(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_RESET(received_msg)); // break; // // case M3AP_ENB_CONFIGURATION_UPDATE_ACK: // LOG_W(M3AP,"MME Received M3AP_ENB_CONFIGURATION_UPDATE_ACK Message\n"); -// MME_send_ENB_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// MME_send_ENB_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_ENB_CONFIGURATION_UPDATE_ACK(received_msg)); // break; // // case M3AP_ENB_CONFIGURATION_UPDATE_FAILURE: // LOG_W(M3AP,"MME Received M3AP_ENB_CONFIGURATION_UPDATE_FAILURE Message\n"); -// MME_send_ENB_CONFIGURATION_UPDATE_FAILURE(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// MME_send_ENB_CONFIGURATION_UPDATE_FAILURE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_ENB_CONFIGURATION_UPDATE_FAILURE(received_msg))// break; // // // case M3AP_MME_CONFIGURATION_UPDATE: // LOG_W(M3AP,"MME Received M3AP_MME_CONFIGURATION_UPDATE Message\n"); -// MME_send_MME_CONFIGURATION_UPDATE(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// MME_send_MME_CONFIGURATION_UPDATE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_MME_CONFIGURATION_UPDATE(received_msg)); // break; // // case M3AP_HANDOVER_REQ: -// m3ap_MME_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m3ap_MME_handle_handover_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_HANDOVER_REQ(received_msg)); // break; // // case M3AP_HANDOVER_REQ_ACK: -// m3ap_MME_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m3ap_MME_handle_handover_req_ack(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_HANDOVER_REQ_ACK(received_msg)); // break; // // case M3AP_UE_CONTEXT_RELEASE: -// m3ap_MME_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg), +// m3ap_MME_ue_context_release(ITTI_MSG_DESTINATION_INSTANCE(received_msg), // &M3AP_UE_CONTEXT_RELEASE(received_msg)); // break; // case SCTP_INIT_MSG_MULTI_CNF: LOG_E(M3AP,"MME Received SCTP_INIT_MSG_MULTI_CNF Message ... shoudn't be happening ... it doesn't at leaast with M2AP_MCEC\n"); - m3ap_MME_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MME_handle_sctp_init_msg_multi_cnf(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_init_msg_multi_cnf); break; case SCTP_NEW_ASSOCIATION_RESP: LOG_D(M3AP,"MME Received SCTP_NEW_ASSOCIATION_RESP Message\n"); - m3ap_MME_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MME_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_NEW_ASSOCIATION_IND: LOG_D(M3AP,"MME Received SCTP_NEW_ASSOCIATION Message\n"); - m3ap_MME_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MME_handle_sctp_association_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_ind); break; case SCTP_DATA_IND: LOG_D(M3AP,"MME Received SCTP_DATA_IND Message\n"); - m3ap_MME_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + m3ap_MME_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; diff --git a/openair3/M3AP/m3ap_MME_handler.c b/openair3/M3AP/m3ap_MME_handler.c index 9af8cbe14f..688e3937e1 100644 --- a/openair3/M3AP/m3ap_MME_handler.c +++ b/openair3/M3AP/m3ap_MME_handler.c @@ -108,7 +108,7 @@ int m3ap_MME_handle_message(instance_t instance, uint32_t assoc_id, int32_t stre } /* Calling the right handler */ - LOG_I(M3AP, "Calling handler with instance %d\n",instance); + LOG_I(M3AP, "Calling handler with instance %ld\n",instance); ret = (*m3ap_MME_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1]) (instance, assoc_id, stream, &pdu); ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_M3AP_M3AP_PDU, &pdu); diff --git a/openair3/M3AP/m3ap_MME_interface_management.c b/openair3/M3AP/m3ap_MME_interface_management.c index e5cb03cf26..ccdfa4fc5e 100644 --- a/openair3/M3AP/m3ap_MME_interface_management.c +++ b/openair3/M3AP/m3ap_MME_interface_management.c @@ -265,7 +265,7 @@ int MME_handle_MBMS_SESSION_START_RESPONSE(instance_t instance, int MCE_MBMS_M3AP_ID=-1; - MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_START_RESP); //TODO + MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME, 0,M3AP_MBMS_SESSION_START_RESP); //TODO LOG_D(M3AP, "M3AP: SessionStart-Resp: protocolIEs.list.count %d\n", in->protocolIEs.list.count); @@ -403,7 +403,7 @@ int MME_handle_MBMS_SESSION_STOP_RESPONSE(instance_t instance, int MCE_MBMS_M3AP_ID=-1; - MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_STOP_RESP); //TODO + MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME, 0,M3AP_MBMS_SESSION_STOP_RESP); //TODO LOG_D(M3AP, "M3AP: MBMSSessionStop-Resp: protocolIEs.list.count %d\n", in->protocolIEs.list.count); @@ -522,7 +522,7 @@ int MME_handle_M3_SETUP_REQUEST(instance_t instance, // assoc_id, stream); // } // - message_p = itti_alloc_new_message(TASK_M3AP_MME, M3AP_SETUP_REQ); + message_p = itti_alloc_new_message(TASK_M3AP_MME, 0, M3AP_SETUP_REQ); //printf("M3AP_SETUP_REQ(message_p).assoc_id %d\n",M3AP_SETUP_REQ(message_p).assoc_id); // // /* assoc_id */ @@ -1055,7 +1055,7 @@ int MME_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, int MCE_MBMS_M3AP_ID=-1; - MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME,M3AP_MBMS_SESSION_UPDATE_RESP); //TODO + MessageDef *msg_g = itti_alloc_new_message(TASK_M3AP_MME, 0,M3AP_MBMS_SESSION_UPDATE_RESP); //TODO LOG_D(M3AP, "M3AP: SessionUpdate-Resp: protocolIEs.list.count %d\n", in->protocolIEs.list.count); diff --git a/openair3/M3AP/m3ap_MME_management_procedures.c b/openair3/M3AP/m3ap_MME_management_procedures.c index 11d2924249..151aba04e4 100644 --- a/openair3/M3AP/m3ap_MME_management_procedures.c +++ b/openair3/M3AP/m3ap_MME_management_procedures.c @@ -116,7 +116,7 @@ void dump_mme_trees_m2(void) m3ap_MME_instance_t *zz; STAILQ_FOREACH(zz, &m3ap_MME_internal_data.m3ap_MME_instances_head, m3ap_MME_entries) { -printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance); +printf("here comes the tree (instance %ld):\n---------------------------------------------\n", zz->instance); dump_mme_tree_m2(zz->m3ap_mme_head.rbh_root); printf("---------------------------------------------\n"); } diff --git a/openair3/M3AP/m3ap_itti_messaging.c b/openair3/M3AP/m3ap_itti_messaging.c index b906747640..42e689343f 100644 --- a/openair3/M3AP/m3ap_itti_messaging.c +++ b/openair3/M3AP/m3ap_itti_messaging.c @@ -36,7 +36,7 @@ void m3ap_MCE_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uin MessageDef *message_p; sctp_data_req_t *sctp_data_req; - message_p = itti_alloc_new_message(TASK_M3AP_MCE, SCTP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_M3AP_MCE, 0, SCTP_DATA_REQ); sctp_data_req = &message_p->ittiMsg.sctp_data_req; @@ -56,7 +56,7 @@ void m3ap_MCE_itti_send_sctp_close_association(instance_t instance, int32_t asso MessageDef *message_p = NULL; sctp_close_association_t *sctp_close_association_p = NULL; - message_p = itti_alloc_new_message(TASK_M3AP_MCE, SCTP_CLOSE_ASSOCIATION); + message_p = itti_alloc_new_message(TASK_M3AP_MCE, 0, SCTP_CLOSE_ASSOCIATION); sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; sctp_close_association_p->assoc_id = assoc_id; @@ -70,7 +70,7 @@ void m3ap_MME_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uin MessageDef *message_p; sctp_data_req_t *sctp_data_req; - message_p = itti_alloc_new_message(TASK_M3AP_MME, SCTP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_M3AP_MME, 0, SCTP_DATA_REQ); sctp_data_req = &message_p->ittiMsg.sctp_data_req; @@ -88,7 +88,7 @@ void m3ap_MME_itti_send_sctp_close_association(instance_t instance, int32_t asso MessageDef *message_p = NULL; sctp_close_association_t *sctp_close_association_p = NULL; - message_p = itti_alloc_new_message(TASK_M3AP_MME, SCTP_CLOSE_ASSOCIATION); + message_p = itti_alloc_new_message(TASK_M3AP_MME, 0, SCTP_CLOSE_ASSOCIATION); sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; sctp_close_association_p->assoc_id = assoc_id; diff --git a/openair3/MME_APP/mme_app.c b/openair3/MME_APP/mme_app.c index 534aec8b34..57f1b4c9d2 100644 --- a/openair3/MME_APP/mme_app.c +++ b/openair3/MME_APP/mme_app.c @@ -54,7 +54,6 @@ # define X2AP_ENB_REGISTER_RETRY_DELAY 10 #include "openair1/PHY/INIT/phy_init.h" -extern unsigned char NB_MCE_INST; extern RAN_CONTEXT_t RC; @@ -76,7 +75,7 @@ extern RAN_CONTEXT_t RC; // { // // M3AP registration // /* note: there is an implicit relationship between the data structure and the message name */ -// msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_REGISTER_MCE_REQ); +// msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M3AP_REGISTER_MCE_REQ); // //RCconfig_S1(msg_p, mce_id); // // //if (mce_id == 0) @@ -90,7 +89,7 @@ extern RAN_CONTEXT_t RC; // //if (NODE_IS_DU(node_type)) { // F1AP registration // // // configure F1AP here for F1C // // LOG_I(ENB_APP,"ngran_eNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); -// // msg_p = itti_alloc_new_message (TASK_ENB_APP, F1AP_SETUP_REQ); +// // msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, F1AP_SETUP_REQ); // // RCconfig_DU_F1(msg_p, enb_id); // // // LOG_I(ENB_APP,"[eNB %d] eNB_app_register via F1AP for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id)); @@ -99,7 +98,7 @@ extern RAN_CONTEXT_t RC; // //} // //else { // S1AP registration // // /* note: there is an implicit relationship between the data structure and the message name */ -// // msg_p = itti_alloc_new_message (TASK_ENB_APP, S1AP_REGISTER_ENB_REQ); +// // msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, S1AP_REGISTER_ENB_REQ); // // RCconfig_S1(msg_p, enb_id); // // // if (enb_id == 0) RCconfig_gtpu(); @@ -126,7 +125,7 @@ extern RAN_CONTEXT_t RC; // // for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) { // { -// msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ); +// msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, X2AP_REGISTER_ENB_REQ); // RCconfig_X2(msg_p, mce_id); // itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p); // register_mce_x2_pending++; @@ -146,7 +145,7 @@ extern RAN_CONTEXT_t RC; // for (mce_id = mce_id_start; (mce_id < mce_id_end) ; mce_id++) { // { // // LOG_W(MME_APP,"Register commes inside ...\n"); -// msg_p = itti_alloc_new_message (TASK_MME_APP, M2AP_REGISTER_MCE_REQ); +// msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M2AP_REGISTER_MCE_REQ); // //RCconfig_M2_MCE(msg_p, mce_id); // itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(mce_id), msg_p); // // LOG_W(MME_APP,"Register sent ...\n"); @@ -163,7 +162,7 @@ static uint32_t MME_app_handle_m3ap_setup_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_SETUP_RESP); + msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M3AP_SETUP_RESP); itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; @@ -187,7 +186,7 @@ static uint32_t MME_app_handle_m3ap_session_start_resp(instance_t instance){ // // uint32_t mce_id=0; // MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MME_APP, M2AP_MBMS_SCHEDULING_INFORMATION); +// msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M2AP_MBMS_SCHEDULING_INFORMATION); // itti_send_msg_to_task (TASK_M2AP_MCE, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // return 0; @@ -197,7 +196,7 @@ static uint32_t MME_app_send_m3ap_session_start_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_START_REQ); + msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M3AP_MBMS_SESSION_START_REQ); itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; @@ -206,7 +205,7 @@ static uint32_t MME_app_send_m3ap_session_start_req(instance_t instance){ // // //uint32_t mce_id=0; // MessageDef *msg_p; -// msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_STOP_REQ); +// msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M3AP_MBMS_SESSION_STOP_REQ); // itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); // // return 0; @@ -215,7 +214,7 @@ static uint32_t MME_app_send_m3ap_session_update_req(instance_t instance){ //uint32_t mce_id=0; MessageDef *msg_p; - msg_p = itti_alloc_new_message (TASK_MME_APP, M3AP_MBMS_SESSION_UPDATE_REQ); + msg_p = itti_alloc_new_message (TASK_MME_APP, 0, M3AP_MBMS_SESSION_UPDATE_REQ); itti_send_msg_to_task (TASK_M3AP_MME, ENB_MODULE_ID_TO_INSTANCE(instance), msg_p); return 0; @@ -263,7 +262,7 @@ void *MME_app_task(void *args_p) { do { // Wait for a message itti_receive_msg (TASK_MME_APP, &msg_p); - instance = ITTI_MSG_INSTANCE (msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: @@ -297,7 +296,7 @@ void *MME_app_task(void *args_p) { // if (registered_mce == mce_nb) { // /* If all MCE are registered, start L2L1 task */ // // MessageDef *msg_init_p; - // // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE); + // // msg_init_p = itti_alloc_new_message (TASK_ENB_APP, 0, INITIALIZE_MESSAGE); // // itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); // } else { // LOG_W(MME_APP, " %d MCE not associated with a MME, retrying registration in %d seconds ...\n", @@ -341,7 +340,7 @@ void *MME_app_task(void *args_p) { // /* If all MCE cells are registered, start L2L1 task */ // MessageDef *msg_init_p; - // //msg_init_p = itti_alloc_new_message (TASK_MME_APP, INITIALIZE_MESSAGE); + // //msg_init_p = itti_alloc_new_message (TASK_MME_APP, 0, INITIALIZE_MESSAGE); // //itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p); // } else { @@ -365,7 +364,7 @@ void *MME_app_task(void *args_p) { case M3AP_DEREGISTERED_MCE_IND: //M3AP_DEREGISTERED_MCE_IND debería if (EPC_MODE_ENABLED) { - LOG_W(MME_APP, "[MCE %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), + LOG_W(MME_APP, "[MCE %ld] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), M3AP_DEREGISTERED_MCE_IND(msg_p).nb_mme); /* TODO handle recovering of registration */ } diff --git a/openair3/MME_APP/mme_config.c b/openair3/MME_APP/mme_config.c index 04dba67567..3b4074f553 100644 --- a/openair3/MME_APP/mme_config.c +++ b/openair3/MME_APP/mme_config.c @@ -94,7 +94,7 @@ int RCconfig_MME(void ) { if (address) { MessageDef *message; - AssertFatal((message = itti_alloc_new_message(TASK_MME_APP, M3AP_MME_SCTP_REQ))!=NULL,""); + AssertFatal((message = itti_alloc_new_message(TASK_MME_APP, 0, M3AP_MME_SCTP_REQ))!=NULL,""); M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv6 = 0; M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv4 = 1; strcpy( M3AP_MME_SCTP_REQ (message).mme_m3_ip_address.ipv4_address, address); diff --git a/openair3/NAS/COMMON/API/NETWORK/as_message.c b/openair3/NAS/COMMON/API/NETWORK/as_message.c index fd3f15cb4c..4a2da21594 100644 --- a/openair3/NAS/COMMON/API/NETWORK/as_message.c +++ b/openair3/NAS/COMMON/API/NETWORK/as_message.c @@ -81,7 +81,12 @@ int as_message_decode(const char* buffer, as_message_t* msg, int length) LOG_FUNC_IN; int bytes; - Byte_t** data = NULL; + /* pointers to msg fields possibly not aligned because msg points to a packed structure + * Using these possibly unaligned pointers in a function call may trigger alignment errors at run time and + * gcc, from v9, now warns about it. fix these warnings by removing the indirection on data + * (in fact i don't understand this code data seems to be useless...) + */ + Byte_t *data = NULL; /* Get the message type */ msg->msgID = *(uint16_t*)(buffer); @@ -91,49 +96,49 @@ int as_message_decode(const char* buffer, as_message_t* msg, int length) case AS_NAS_ESTABLISH_REQ: /* NAS signalling connection establish request */ bytes += sizeof(nas_establish_req_t) - sizeof(Byte_t*); - data = &msg->msg.nas_establish_req.initialNasMsg.data; + data = msg->msg.nas_establish_req.initialNasMsg.data; break; case AS_NAS_ESTABLISH_IND: /* NAS signalling connection establishment indication */ bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*); - data = &msg->msg.nas_establish_ind.initialNasMsg.data; + data = msg->msg.nas_establish_ind.initialNasMsg.data; break; case AS_NAS_ESTABLISH_RSP: /* NAS signalling connection establishment response */ bytes += sizeof(nas_establish_rsp_t) - sizeof(Byte_t*); - data = &msg->msg.nas_establish_rsp.nasMsg.data; + data = msg->msg.nas_establish_rsp.nasMsg.data; break; case AS_NAS_ESTABLISH_CNF: /* NAS signalling connection establishment confirm */ bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*); - data = &msg->msg.nas_establish_cnf.nasMsg.data; + data = msg->msg.nas_establish_cnf.nasMsg.data; break; case AS_UL_INFO_TRANSFER_REQ: /* Uplink L3 data transfer request */ bytes += sizeof(ul_info_transfer_req_t) - sizeof(Byte_t*); - data = &msg->msg.ul_info_transfer_req.nasMsg.data; + data = msg->msg.ul_info_transfer_req.nasMsg.data; break; case AS_UL_INFO_TRANSFER_IND: /* Uplink L3 data transfer indication */ bytes += sizeof(ul_info_transfer_ind_t) - sizeof(Byte_t*); - data = &msg->msg.ul_info_transfer_ind.nasMsg.data; + data = msg->msg.ul_info_transfer_ind.nasMsg.data; break; case AS_DL_INFO_TRANSFER_REQ: /* Downlink L3 data transfer request */ bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*); - data = &msg->msg.dl_info_transfer_req.nasMsg.data; + data = msg->msg.dl_info_transfer_req.nasMsg.data; break; case AS_DL_INFO_TRANSFER_IND: /* Downlink L3 data transfer indication */ bytes += sizeof(dl_info_transfer_ind_t) - sizeof(Byte_t*); - data = &msg->msg.dl_info_transfer_ind.nasMsg.data; + data = msg->msg.dl_info_transfer_ind.nasMsg.data; break; case AS_BROADCAST_INFO_IND: @@ -166,7 +171,8 @@ int as_message_decode(const char* buffer, as_message_t* msg, int length) if (bytes > 0) { if (data) { /* Set the pointer to dedicated NAS information */ - *data = (Byte_t*)(buffer + bytes); + /* wasn't data already computed above for specific cases here we override ?? */ + data = (Byte_t *)buffer + bytes; } /* Decode the message */ @@ -201,8 +207,10 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) LOG_FUNC_IN; int bytes = sizeof(msg->msgID); - as_nas_info_t* nas_msg = NULL; - + as_nas_info_t nas_msg; + Byte_t *dataptr=NULL; + uint32_t len=0; + switch (msg->msgID) { case AS_BROADCAST_INFO_IND: /* Broadcast information */ @@ -237,25 +245,30 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) case AS_NAS_ESTABLISH_REQ: /* NAS signalling connection establish request */ bytes += sizeof(nas_establish_req_t) - sizeof(Byte_t*); - nas_msg = &msg->msg.nas_establish_req.initialNasMsg; + nas_msg = msg->msg.nas_establish_req.initialNasMsg; break; case AS_NAS_ESTABLISH_IND: /* NAS signalling connection establish indication */ bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*); - nas_msg = &msg->msg.nas_establish_ind.initialNasMsg; + nas_msg = msg->msg.nas_establish_ind.initialNasMsg; + dataptr=(Byte_t *)&(msg->msg.nas_establish_ind.initialNasMsg.data); + len=msg->msg.nas_establish_ind.initialNasMsg.length; break; case AS_NAS_ESTABLISH_RSP: /* NAS signalling connection establish response */ bytes += sizeof(nas_establish_rsp_t) - sizeof(Byte_t*); - nas_msg = &msg->msg.nas_establish_rsp.nasMsg; + nas_msg = msg->msg.nas_establish_rsp.nasMsg; + break; case AS_NAS_ESTABLISH_CNF: /* NAS signalling connection establish confirm */ bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*); - nas_msg = &msg->msg.nas_establish_cnf.nasMsg; + nas_msg = msg->msg.nas_establish_cnf.nasMsg; + dataptr=(Byte_t *)&(msg->msg.nas_establish_cnf.nasMsg.data); + len=msg->msg.nas_establish_ind.initialNasMsg.length; break; case AS_NAS_RELEASE_REQ: @@ -271,7 +284,7 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) case AS_UL_INFO_TRANSFER_REQ: /* Uplink L3 data transfer request */ bytes += sizeof(ul_info_transfer_req_t) - sizeof(Byte_t*); - nas_msg = &msg->msg.ul_info_transfer_req.nasMsg; + nas_msg = msg->msg.ul_info_transfer_req.nasMsg; break; case AS_UL_INFO_TRANSFER_CNF: @@ -282,13 +295,13 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) case AS_UL_INFO_TRANSFER_IND: /* Uplink L3 data transfer indication */ bytes += sizeof(ul_info_transfer_ind_t) - sizeof(Byte_t*); - nas_msg = &msg->msg.ul_info_transfer_ind.nasMsg; + nas_msg = msg->msg.ul_info_transfer_ind.nasMsg; break; case AS_DL_INFO_TRANSFER_REQ: /* Downlink L3 data transfer */ bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*); - nas_msg = &msg->msg.dl_info_transfer_req.nasMsg; + nas_msg = msg->msg.dl_info_transfer_req.nasMsg; break; case AS_DL_INFO_TRANSFER_CNF: @@ -299,7 +312,8 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) case AS_DL_INFO_TRANSFER_IND: /* Downlink L3 data transfer indication */ bytes += sizeof(dl_info_transfer_ind_t) - sizeof(Byte_t*); - nas_msg = &msg->msg.dl_info_transfer_ind.nasMsg; + nas_msg = msg->msg.dl_info_transfer_ind.nasMsg; + break; case AS_RAB_ESTABLISH_REQ: @@ -343,14 +357,14 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) /* Encode the AS message */ memcpy(buffer, (unsigned char*)msg, bytes); - if ( nas_msg && (nas_msg->length > 0) ) { + if ( (dataptr!=NULL) && (len > 0) ) { /* Copy the NAS message */ - memcpy(buffer + bytes, nas_msg->data, nas_msg->length); - bytes += nas_msg->length; + memcpy(buffer + bytes, nas_msg.data, nas_msg.length); + bytes += len; /* Release NAS message memory */ - free(nas_msg->data); - nas_msg->length = 0; - nas_msg->data = NULL; + free(nas_msg.data); + len=0; + dataptr = NULL; } LOG_FUNC_RETURN (bytes); diff --git a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c index 8ac43cf7b1..637d930226 100644 --- a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c +++ b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c @@ -190,7 +190,6 @@ int decode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint default: errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI; LOG_TRACE(WARNING, "DECODE_UNEXPECTED_IEI %x (4 bits)", ieiDecoded); - AssertFatal(0, " "); return TLV_DECODE_UNEXPECTED_IEI; } } diff --git a/openair3/NAS/COMMON/EMM/MSG/CsServiceNotification.h b/openair3/NAS/COMMON/EMM/MSG/CsServiceNotification.h index c173d3b729..4bed349327 100644 --- a/openair3/NAS/COMMON/EMM/MSG/CsServiceNotification.h +++ b/openair3/NAS/COMMON/EMM/MSG/CsServiceNotification.h @@ -26,7 +26,7 @@ #include "ProtocolDiscriminator.h" #include "SecurityHeaderType.h" #include "MessageType.h" -#include "PagingIdentity.h" +#include "NasPagingIdentity.h" #include "Cli.h" #include "SsCode.h" #include "LcsIndicator.h" diff --git a/common/utils/itti_analyzer/libparser/file_type.c b/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c similarity index 57% rename from common/utils/itti_analyzer/libparser/file_type.c rename to openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c index 04d66b7a08..5e1ff25151 100644 --- a/common/utils/itti_analyzer/libparser/file_type.c +++ b/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c @@ -19,35 +19,38 @@ * contact@openairinterface.org */ +/*! \file FGSAuthenticationResponse.c + +\brief authentication response procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + #include #include -#include #include +#include -#define G_LOG_DOMAIN ("PARSER") +#include "nas_log.h" -#include "file_type.h" +#include "FGSAuthenticationResponse.h" -int file_type_file_print(types_t *type, int indent, FILE *file) + +int encode_fgs_authentication_response(fgs_authentication_response_msg *authentication_response, uint8_t *buffer, uint32_t len) { - if (type == NULL) - return -1; - INDENTED(file, indent, fprintf(file, "\n")); - INDENTED(file, indent+4, fprintf(file, "Id .........: %d\n", type->id)); - INDENTED(file, indent+4, fprintf(file, "Name .......: %s\n", type->name)); - INDENTED(file, indent, fprintf(file, "\n")); + int encoded = 0; + int encode_result = 0; - return 0; + + if ((encode_result = + encode_authentication_response_parameter(&authentication_response->authenticationresponseparameter, + AUTHENTICATION_RESPONSE_PARAMETER_IEI, buffer + encoded, len - encoded)) < 0) //Return in case of error + return encode_result; + else + encoded += encode_result; + + return encoded; } -int file_type_hr_display(types_t *type, int indent) -{ - if (type == NULL) - return -1; - INDENTED(stdout, indent, printf("\n")); - INDENTED(stdout, indent+4, printf("Id .........: %d\n", type->id)); - INDENTED(stdout, indent+4, printf("Name .......: %s\n", type->name)); - INDENTED(stdout, indent, printf("\n")); - - return 0; -} diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h b/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h new file mode 100644 index 0000000000..0acee3382f --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h @@ -0,0 +1,66 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSAuthenticationResponse.h + +\brief authentication response procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "ExtendedProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "SpareHalfOctet.h" +#include "MessageType.h" +#include "AuthenticationResponseParameter.h" + +#ifndef FGS_AUTHENTICATION_RESPONSE_H_ +#define FGS_AUTHENTICATION_RESPONSE_H_ + +#define AUTHENTICATION_RESPONSE_PARAMETER_IEI 0x2d + +/* + * Message name: Identity response + * Description: This message is sent by the UE to the AMF to provide the requested identity. See table 8.2.22.1. + * Significance: dual + * Direction: UE to AMF + */ + +typedef struct fgs_authentication_response_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + SecurityHeaderType securityheadertype:4; + SpareHalfOctet sparehalfoctet:4; + MessageType messagetype; + AuthenticationResponseParameter authenticationresponseparameter; +} fgs_authentication_response_msg; + +int encode_fgs_authentication_response(fgs_authentication_response_msg *authentication_response, uint8_t *buffer, uint32_t len); + +#endif /* ! defined(FGS_AUTHENTICATION_RESPONSE_H_) */ + + diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c b/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c new file mode 100644 index 0000000000..4f8f6dd321 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c @@ -0,0 +1,56 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSIdentityResponse.c + +\brief identity response procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include +#include + +#include "nas_log.h" + +#include "FGSIdentityResponse.h" + + +int encode_identiy_response(fgs_identiy_response_msg *fgs_identity_reps, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + int encode_result = 0; + + if ((encode_result = + encode_5gs_mobile_identity(&fgs_identity_reps->fgsmobileidentity, 0, buffer + + encoded, len - encoded)) < 0) //Return in case of error + return encode_result; + else + encoded += encode_result; + + return encoded; +} + + diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h b/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h new file mode 100644 index 0000000000..431293e03e --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSIdentityResponse.h + +\brief identity response procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "ExtendedProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "SpareHalfOctet.h" +#include "FGSMobileIdentity.h" +#include "MessageType.h" + +#ifndef FGS_IDENTITY_RESPONSE_H_ +#define FGS_IDENTITY_RESPONSE_H_ + +/* + * Message name: Identity response + * Description: This message is sent by the UE to the AMF to provide the requested identity. See table 8.2.22.1. + * Significance: dual + * Direction: UE to AMF + */ + +typedef struct fgs_identiy_response_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + SecurityHeaderType securityheadertype:4; + SpareHalfOctet sparehalfoctet:4; + MessageType messagetype; + FGSMobileIdentity fgsmobileidentity; + +} fgs_identiy_response_msg; + +int encode_identiy_response(fgs_identiy_response_msg *fgs_identity_reps, uint8_t *buffer, uint32_t len); + +#endif /* ! defined(FGS_IDENTITY_RESPONSE_H_) */ + + diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c b/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c new file mode 100644 index 0000000000..e0be56145f --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c @@ -0,0 +1,66 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSNASSecurityModeComplete.c + +\brief security mode complete procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include +#include + +#include "nas_log.h" + +#include "FGSNASSecurityModeComplete.h" +#include "FGSMobileIdentity.h" +#include "FGCNasMessageContainer.h" + +int encode_fgs_security_mode_complete(fgs_security_mode_complete_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + int encode_result = 0; + + if ((encode_result = + encode_5gs_mobile_identity(&fgs_security_mode_comp->fgsmobileidentity, 0x77, buffer + + encoded, len - encoded)) < 0) { //Return in case of error + return encode_result; + } else { + encoded += encode_result; + if ((encode_result = + encode_fgc_nas_message_container(&fgs_security_mode_comp->fgsnasmessagecontainer, 0x71, buffer + + encoded, len - encoded)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } + } + + return encoded; +} + + + diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h b/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h new file mode 100644 index 0000000000..702dca3dc5 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSNASSecurityModeComplete.h + +\brief security mode complete procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "ExtendedProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "SpareHalfOctet.h" +#include "FGSMobileIdentity.h" +#include "MessageType.h" +#include "FGCNasMessageContainer.h" + +#ifndef FGS_NAS_SECURITY_MODE_COMPLETE_H_ +#define FGS_NAS_SECURITY_MODE_COMPLETE_H_ + +/* + * Message name: security mode complete + * Description: This message is sent by the UE to the AMF in response to a SECURITY MODE COMMAND message. See table 8.2.26.1.1. + * Significance: dual + * Direction: UE to AMF + */ + +typedef struct fgs_security_mode_complete_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + SecurityHeaderType securityheadertype:4; + SpareHalfOctet sparehalfoctet:4; + MessageType messagetype; + FGSMobileIdentity fgsmobileidentity; + FGCNasMessageContainer fgsnasmessagecontainer; +} fgs_security_mode_complete_msg; + +int encode_fgs_security_mode_complete(fgs_security_mode_complete_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len); + +#endif /* ! defined(FGS_NAS_SECURITY_MODE_COMPLETE_H_) */ + diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c b/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c new file mode 100644 index 0000000000..d94df434b2 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c @@ -0,0 +1,150 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSUplinkNasTransport.c + +\brief uplink nas transport procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include +#include +#include + +#include "FGSUplinkNasTransport.h" +#include "TLVEncoder.h" + +int encode_fgs_payload_container(FGSPayloadContainer *paycontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + uint32_t encoded = 0; + int encode_result; + + if (iei > 0) { + *buffer = iei; + encoded++; + } + + encoded += 2; + + if ((encode_result = encode_octet_string(&paycontainer->payloadcontainercontents, buffer + encoded, len - encoded)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } + if(iei > 0){ + *(uint16_t*) (buffer+1) = htons(encoded - 3); + } else { + *(uint16_t*) (buffer) = htons(encoded - 2); + } + + return encoded; +} + +int encode_nssai(OctetString *nssai, uint8_t iei, uint8_t *buffer) +{ + uint32_t encoded = 0; + int encode_result; + + if (iei > 0) { + *buffer = iei; + encoded++; + } + + *(buffer + encoded) = nssai->length; + encoded++; + + + if ((encode_result = encode_octet_string(nssai, buffer + encoded, nssai->length)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } + + return encoded; +} + +int encode_dnn(OctetString *dnn, uint8_t iei, uint8_t *buffer) +{ + uint32_t encoded = 0; + int encode_result; + + if (iei > 0) { + *buffer = iei; + encoded++; + } + + *(buffer + encoded) = dnn->length; + encoded++; + + if ((encode_result = encode_octet_string(dnn, buffer + encoded, dnn->length)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } + + return encoded; +} + +int encode_fgs_uplink_nas_transport(fgs_uplink_nas_transport_msg *fgs_up_nas_transport, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + int encode_result = 0; + + *(buffer + encoded) = (fgs_up_nas_transport->payloadcontainertype.iei << 4) | (fgs_up_nas_transport->payloadcontainertype.type &0xf); + encoded++; + + if ((encode_result = encode_fgs_payload_container(&fgs_up_nas_transport->fgspayloadcontainer, + 0, buffer +encoded, len - encoded)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } + + *(buffer + encoded) = 0x12; + encoded++; + + IES_ENCODE_U8(buffer, encoded, fgs_up_nas_transport->pdusessionid); + + // set request type + *(buffer + encoded) = (0x8<<4)|(fgs_up_nas_transport->requesttype &0x7); + encoded++; + + if ((encode_result = encode_nssai(&fgs_up_nas_transport->snssai, 0x22, buffer +encoded)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } + + if ((encode_result = encode_dnn(&fgs_up_nas_transport->dnn, 0x25, buffer +encoded)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } + + return encoded; +} + + diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h b/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h new file mode 100644 index 0000000000..5fabcea173 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h @@ -0,0 +1,77 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSUplinkNasTransport.h + +\brief uplink nas transport procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "ExtendedProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "SpareHalfOctet.h" +#include "MessageType.h" + +#ifndef FGS_UPLINK_NAS_TRANSPORT_H_ +#define FGS_UPLINK_NAS_TRANSPORT_H_ + +/* + * Message name: uplink nas transpaort + * Description: The UL NAS TRANSPORT message transports message payload and associated information to the AMF. See table 8.2.10.1.1. + * Significance: dual + * Direction: UE to network + */ + +typedef struct PayloadContainerType_tag{ + uint8_t iei:4; + uint8_t type:4; +}PayloadContainerType; +typedef struct FGSPayloadContainer_tag { + OctetString payloadcontainercontents; +} FGSPayloadContainer; + +typedef struct fgs_uplink_nas_transport_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + SecurityHeaderType securityheadertype:4; + SpareHalfOctet sparehalfoctet:4; + MessageType messagetype; + PayloadContainerType payloadcontainertype; + FGSPayloadContainer fgspayloadcontainer; + /* Optional fields */ + uint16_t pdusessionid; + uint8_t requesttype; + OctetString snssai; + OctetString dnn; +} fgs_uplink_nas_transport_msg; + +int encode_fgs_uplink_nas_transport(fgs_uplink_nas_transport_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len); + +#endif /* ! defined(FGS_UPLINK_NAS_TRANSPORT_H_) */ + + diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c new file mode 100644 index 0000000000..d8fde7e2cc --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c @@ -0,0 +1,70 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file RegistrationAccept.c + +\brief 5GS registration accept procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "RegistrationAccept.h" +#include "assertions.h" + +int decode_registration_accept(registration_accept_msg *registration_accept, uint8_t *buffer, uint32_t len) +{ + uint32_t decoded = 0; + int decoded_result = 0; + + /* Decoding mandatory fields */ + if ((decoded_result = decode_fgs_registration_result(®istration_accept->fgsregistrationresult, 0, *(buffer + decoded), len - decoded)) < 0) + return decoded_result; + + decoded += decoded_result; + + // todo ,Decoding optional fields + return decoded; +} + +int encode_registration_accept(registration_accept_msg *registration_accept, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + + LOG_FUNC_IN; + + + *(buffer + encoded) = encode_fgs_registration_result(®istration_accept->fgsregistrationresult); + encoded = encoded + 2; + + // todo ,Encoding optional fields + LOG_FUNC_RETURN(encoded); +} + diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h new file mode 100644 index 0000000000..08daec2646 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h @@ -0,0 +1,66 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file RegistrationAccept.h + +\brief 5GS registration accept procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + + +#include "ExtendedProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "SpareHalfOctet.h" +#include "MessageType.h" +#include "FGSRegistrationResult.h" + +#ifndef REGISTRATION_ACCEPT_H_ +#define REGISTRATION_ACCEPT_H_ + +/* + * Message name: Registration accept + * Description: The REGISTRATION ACCEPT message is sent by the AMF to the UE. See table 8.2.7.1.1. + * Significance: dual + * Direction: network to UE + */ + +typedef struct registration_accept_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + SecurityHeaderType securityheadertype:4; + SpareHalfOctet sparehalfoctet:4; + MessageType messagetype; + FGSRegistrationResult fgsregistrationresult; +} registration_accept_msg; + +int decode_registration_accept(registration_accept_msg *registrationaccept, uint8_t *buffer, uint32_t len); + +int encode_registration_accept(registration_accept_msg *registrationaccept, uint8_t *buffer, uint32_t len); + +#endif /* ! defined(REGISTRATION_ACCEPT_H_) */ + diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.c b/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.c new file mode 100644 index 0000000000..668e665351 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.c @@ -0,0 +1,61 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "RegistrationComplete.h" +#include "SORTransparentContainer.h" + +int decode_registration_complete(registration_complete_msg *registration_complete, uint8_t *buffer, uint32_t len) +{ + uint32_t decoded = 0; + int decoded_result = 0; + + /* Decoding mandatory fields */ + if ((decoded_result = decode_sor_transparent_container(®istration_complete->sortransparentcontainer, 0, buffer + decoded, len - decoded)) < 0) + return decoded_result; + else + decoded += decoded_result; + + return decoded; +} + +int encode_registration_complete(registration_complete_msg *registration_complete, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + int encode_result = 0; + + if ((encode_result = + encode_sor_transparent_container(®istration_complete->sortransparentcontainer, 0, + buffer + encoded, len - encoded)) < 0) //Return in case of error + return encode_result; + else + encoded += encode_result; + + return encoded; +} + diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h b/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h new file mode 100644 index 0000000000..0fbf2abde1 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h @@ -0,0 +1,62 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file RegistrationRequest.h + +\brief registration request procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "ExtendedProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "SpareHalfOctet.h" +#include "MessageType.h" +#include "SORTransparentContainer.h" + +#ifndef REGISTRATION_COMPLETE_H_ +#define REGISTRATION_COMPLETE_H_ + + +typedef struct registration_complete_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + SecurityHeaderType securityheadertype:4; + SpareHalfOctet sparehalfoctet:4; + MessageType messagetype; + + /* Optional fields */ + SORTransparentContainer sortransparentcontainer; +} registration_complete_msg; + + +int decode_registration_complete(registration_complete_msg *registrationcomplete, uint8_t *buffer, uint32_t len); + +int encode_registration_complete(registration_complete_msg *registrationcomplete, uint8_t *buffer, uint32_t len); + +#endif /* ! defined(REGISTRATION_COMPLETE_H_) */ + diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c b/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c new file mode 100644 index 0000000000..3d177c396a --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c @@ -0,0 +1,114 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file RegistrationRequest.c + * \brief registration request procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + +#include +#include +#include +#include + +#include "nas_log.h" + +#include "RegistrationRequest.h" + +int decode_registration_request(registration_request_msg *registration_request, uint8_t *buffer, uint32_t len) +{ + uint32_t decoded = 0; + int decoded_result = 0; + + LOG_FUNC_IN; + LOG_TRACE(INFO, "EMM - registration_request len = %d", + len); + + /* Decoding mandatory fields */ + if ((decoded_result = decode_5gs_registration_type(®istration_request->fgsregistrationtype, 0, *(buffer + decoded) & 0x0f, len - decoded)) < 0) { + // return decoded_result; + LOG_FUNC_RETURN(decoded_result); + } + + if ((decoded_result = decode_u8_nas_key_set_identifier(®istration_request->naskeysetidentifier, 0, *(buffer + decoded) >> 4, len - decoded)) < 0) { + // return decoded_result; + LOG_FUNC_RETURN(decoded_result); + } + + decoded++; + + if ((decoded_result = decode_5gs_mobile_identity(®istration_request->fgsmobileidentity, 0, buffer + decoded, len - decoded)) < 0) { + // return decoded_result; + LOG_FUNC_RETURN(decoded_result); + } else + decoded += decoded_result; + + + // TODO, Decoding optional fields + + return decoded; +} + +int encode_registration_request(registration_request_msg *registration_request, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + int encode_result = 0; + + *(buffer + encoded) = ((encode_u8_nas_key_set_identifier(®istration_request->naskeysetidentifier) & 0x0f) << 4) | (encode_5gs_registration_type(®istration_request->fgsregistrationtype) & 0x0f); + encoded++; + + if ((encode_result = + encode_5gs_mobile_identity(®istration_request->fgsmobileidentity, 0, buffer + + encoded, len - encoded)) < 0) //Return in case of error + return encode_result; + else + encoded += encode_result; + + if ((registration_request->presencemask & REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT) + == REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT) { + if ((encode_result = encode_5gmm_capability(®istration_request->fgmmcapability, + REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI, buffer + encoded, len - + encoded)) < 0) + // Return in case of error + return encode_result; + else + encoded += encode_result; + } + + if ((registration_request->presencemask & REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT) + == REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT) { + if ((encode_result = encode_nrue_security_capability(®istration_request->nruesecuritycapability, + REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI, buffer + encoded, len - + encoded)) < 0) + // Return in case of error + return encode_result; + else + encoded += encode_result; + } + + + // TODO, Encoding optional fields + return encoded; +} + diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.h b/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.h new file mode 100644 index 0000000000..ce534bfff9 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.h @@ -0,0 +1,125 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file RegistrationRequest.h + * \brief registration request procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + + +#include +#include +#include + +#include "ExtendedProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "SpareHalfOctet.h" +#include "FGSMobileIdentity.h" +#include "NasKeySetIdentifier.h" +#include "FGSRegistrationType.h" +#include "MessageType.h" +#include "FGMMCapability.h" +#include "NrUESecurityCapability.h" + +#ifndef REGISTRATION_REQUEST_H_ +#define REGISTRATION_REQUEST_H_ + + +# define REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEYSET_PRESENT (1<<0) +# define REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT (1<<1) +# define REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT (1<<2) +# define REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT (1<<3) +# define REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT (1<<4) +# define REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_PRESENT (1<<5) +# define REGISTRATION_REQUEST_UPLINK_DATA_STATUS_PRESENT (1<<6) +# define REGISTRATION_REQUEST_PDU_SESSION_STATUS_PRESENT (1<<7) +# define REGISTRATION_REQUEST_MICO_INDICATION_PRESENT (1<<8) +# define REGISTRATION_REQUEST_UE_STATUS_PRESENT (1<<9) +# define REGISTRATION_REQUEST_ADDITIONAL_GUTI_PRESENT (1<<10) +# define REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT (1<<11) +# define REGISTRATION_REQUEST_UE_USAGE_SETTING_PRESENT (1<<12) +# define REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_PRESENT (1<<13) +# define REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_PRESENT (1<<14) +# define REGISTRATION_REQUEST_LADN_INDICATION_PRESENT (1<<15) +# define REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_PRESENT (1<<16) +# define REGISTRATION_REQUEST_PAYLOAD_CONTAINER_PRESENT (1<<17) +# define REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_PRESENT (1<<18) +# define REGISTRATION_REQUEST_5GS_UPDATE_TYPE_PRESENT (1<<19) +# define REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT (1<<20) +# define REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT (1<<21) + +typedef enum registration_request_iei_tag { + REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEYSET_IEI = 0xC0, /* 0xC- = 192- */ + REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI = 0x10, /* 0x10 = 16 */ + REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI = 0x2E, /* 0x2E = 46 */ + REGISTRATION_REQUEST_REQUESTED_NSSAI_IEI = 0x2F, /* 0x2F = 47 */ + REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_IEI = 0x52, /* 0x52 = 82 */ + REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_IEI = 0x17, /* 0x17 = 23 */ + REGISTRATION_REQUEST_UPLINK_DATA_STATUS_IEI = 0x40, /* 0x40 = 64 */ + REGISTRATION_REQUEST_PDU_SESSION_STATUS_IEI = 0x50, /* 0x50 = 80 */ + REGISTRATION_REQUEST_MICO_INDICATION_IEI = 0xB0, /* 0xB- = 176- */ + REGISTRATION_REQUEST_UE_STATUS_IEI = 0x2B, /* 0x2B = 43 */ + REGISTRATION_REQUEST_ADDITIONAL_GUTI_IEI = 0x77, /* 0x77 = 119 */ + REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_IEI = 0x25, /* 0x25 = 37 */ + REGISTRATION_REQUEST_UE_USAGE_SETTING_IEI = 0x18, /* 0x18 = 24 */ + REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_IEI = 0x51, /* 0x51 = 81 */ + REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_IEI = 0x70, /* 0x70 = 112 */ + REGISTRATION_REQUEST_LADN_INDICATION_IEI = 0x74, /* 0x74 = 116 */ + REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_IEI = 0x80, /* 0x80 = 128 */ + REGISTRATION_REQUEST_PAYLOAD_CONTAINER_IEI = 0x7B, /* 0x7B = 123 */ + REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_IEI = 0x90, /* 0x90 = 144 */ + REGISTRATION_REQUEST_5GS_UPDATE_TYPE_IEI = 0x53, /* 0x53 = 83 */ + REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_IEI = 0x71, /* 0x71 = 113 */ + REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_IEI = 0x60 /* 0x60 = 96 */ +} registration_request_iei; + +/* + * Message name: Registration request + * Description: This message is sent by the UE to the AMF. See TS24.501 table 8.2.6.1.1. + * Significance: dual + * Direction: UE to network + */ + +typedef struct registration_request_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + SecurityHeaderType securityheadertype:4; + SpareHalfOctet sparehalfoctet:4; + MessageType messagetype; + FGSRegistrationType fgsregistrationtype; + NasKeySetIdentifier naskeysetidentifier; + FGSMobileIdentity fgsmobileidentity; + + /* Optional fields */ + uint32_t presencemask; + FGMMCapability fgmmcapability; + NrUESecurityCapability nruesecuritycapability; +} registration_request_msg; + +int decode_registration_request(registration_request_msg *registrationrequest, uint8_t *buffer, uint32_t len); + +int encode_registration_request(registration_request_msg *registrationrequest, uint8_t *buffer, uint32_t len); + +#endif /* ! defined(REGISTRATION_REQUEST_H_) */ + diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c new file mode 100644 index 0000000000..1c9198b720 --- /dev/null +++ b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c @@ -0,0 +1,63 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PduSessionEstablishRequest.c + +\brief pdu session establishment request procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "PduSessionEstablishRequest.h" + + +int encode_pdu_session_establishment_request(pdu_session_establishment_request_msg *pdusessionestablishrequest, uint8_t *buffer) +{ + int encoded = 0; + + + *(buffer + encoded) = pdusessionestablishrequest->protocoldiscriminator; + encoded++; + *(buffer + encoded) = pdusessionestablishrequest->pdusessionid; + encoded++; + *(buffer + encoded) = pdusessionestablishrequest->pti; + encoded++; + *(buffer + encoded) = pdusessionestablishrequest->pdusessionestblishmsgtype; + encoded++; + + IES_ENCODE_U16(buffer, encoded, pdusessionestablishrequest->maxdatarate); + *(buffer + encoded) = pdusessionestablishrequest->pdusessiontype; + encoded++; + + return encoded; +} + + diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h new file mode 100644 index 0000000000..e2742ebc38 --- /dev/null +++ b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PduSessionEstablishRequest.h + +\brief pdu session establishment request procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "ExtendedProtocolDiscriminator.h" +#include "MessageType.h" + +#ifndef PDU_SESSION_ESTABLISHMENT_REQUEST_H_ +#define PDU_SESSION_ESTABLISHMENT_REQUEST_H_ + + +/* + * Message name: pdu session establishment request + * Description: The PDU SESSION ESTABLISHMENT REQUEST message is sent by the UE to the SMF to initiate establishment of a PDU session. See table 8.3.1.1.1. + * Significance: dual + * Direction: UE to network + */ + +typedef struct pdu_session_establishment_request_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + uint8_t pdusessionid; + uint8_t pti; + MessageType pdusessionestblishmsgtype; + uint16_t maxdatarate; + uint8_t pdusessiontype; + /* Optional fields */ +} pdu_session_establishment_request_msg; + + +int encode_pdu_session_establishment_request(pdu_session_establishment_request_msg *pdusessionestablishrequest, uint8_t *buffer); + +#endif /* ! defined(PDU_SESSION_ESTABLISHMENT_REQUEST_H_) */ + + diff --git a/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.c b/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.c new file mode 100644 index 0000000000..e3b4bd021a --- /dev/null +++ b/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.c @@ -0,0 +1,50 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + + +/*! \file ExtendedProtocolDiscriminator.c + +\brief Extended protocol discriminator for registration request procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "ExtendedProtocolDiscriminator.h" + +int encode_ex_protocol_discriminator(ExtendedProtocolDiscriminator *exprotocoldiscriminator, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + return 0; +} + +int decode_ex_protocol_discriminator(ExtendedProtocolDiscriminator *exprotocoldiscriminator, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + return 0; +} + diff --git a/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.h b/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.h new file mode 100644 index 0000000000..3bf1f6ec8f --- /dev/null +++ b/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.h @@ -0,0 +1,48 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + + +/*! \file ExtendedProtocolDiscriminator.h + +\brief Extended protocol discriminator for registration request procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "OctetString.h" + +#ifndef EXTENDED_PROTOCOL_DISCRIMINATOR_H_ +#define EXTENDED_PROTOCOL_DISCRIMINATOR_H_ + +typedef uint8_t ExtendedProtocolDiscriminator; + +int encode_ex_protocol_discriminator(ExtendedProtocolDiscriminator *exprotocoldiscriminator, uint8_t iei, uint8_t *buffer, uint32_t len); + +int decode_ex_protocol_discriminator(ExtendedProtocolDiscriminator *exprotocoldiscriminator, uint8_t iei, uint8_t *buffer, uint32_t len); + +#endif /* EXTENDED PROTOCOL DISCRIMINATOR_H_ */ + diff --git a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c b/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c new file mode 100644 index 0000000000..874f61e7b3 --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c @@ -0,0 +1,98 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGCNasMessageContainer.c + +\brief security mode complete procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "FGCNasMessageContainer.h" + +int decode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + int decoded = 0; + uint8_t ielen = 0; + int decode_result; + + if (iei > 0) { + CHECK_IEI_DECODER(iei, *buffer); + decoded++; + } + + ielen = *(buffer + decoded); + decoded += 2; + CHECK_LENGTH_DECODER(len - decoded, ielen); + + if ((decode_result = decode_octet_string(&nasmessagecontainer->nasmessagecontainercontents, ielen, buffer + decoded, len - decoded)) < 0) + return decode_result; + else + decoded += decode_result; + + return decoded; +} +int encode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + uint32_t encoded = 0; + int encode_result; + /* Checking IEI and pointer */ + CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, FGC_NAS_MESSAGE_CONTAINER_MINIMUM_LENGTH, len); + + if (iei > 0) { + *buffer = iei; + encoded++; + } + + encoded += 2; + + if ((encode_result = encode_octet_string(&nasmessagecontainer->nasmessagecontainercontents, buffer + encoded, len - encoded)) < 0) { + return encode_result; + } else { + *(uint16_t*) (buffer+1) = htons(encoded + encode_result - 3); + encoded += encode_result; + } + + return encoded; +} + +void dump_fgc_nas_message_container_xml(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei) +{ + printf("\n"); + + if (iei > 0) + /* Don't display IEI if = 0 */ + printf(" 0x%X\n", iei); + + printf("%s", dump_octet_string_xml(&nasmessagecontainer->nasmessagecontainercontents)); + printf("\n"); +} + + diff --git a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h b/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h new file mode 100644 index 0000000000..19a1679b7e --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h @@ -0,0 +1,54 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGCNasMessageContainer.h + +\brief security mode complete procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "OctetString.h" + +#ifndef FGC_NAS_MESSAGE_CONTAINER_H_ +#define FGC_NAS_MESSAGE_CONTAINER_H_ + +#define FGC_NAS_MESSAGE_CONTAINER_MINIMUM_LENGTH 4 +#define FGC_NAS_MESSAGE_CONTAINER_MAXIMUM_LENGTH 65535 + +typedef struct FGCNasMessageContainer_tag { + OctetString nasmessagecontainercontents; +} FGCNasMessageContainer; + +int encode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len); + +int decode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len); + +void dump_fgc_nas_message_container_xml(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei); + +#endif /* FGC NAS MESSAGE CONTAINER_H_ */ + diff --git a/openair3/NAS/COMMON/IES/FGMMCapability.c b/openair3/NAS/COMMON/IES/FGMMCapability.c new file mode 100644 index 0000000000..ce156e63bf --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGMMCapability.c @@ -0,0 +1,54 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGMMCapability.c + * \brief 5GS Mobile Identity for registration request procedures + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "FGMMCapability.h" + + + +int encode_5gmm_capability(FGMMCapability *fgmmcapability, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + if(iei){ + *buffer = fgmmcapability->iei; + encoded++; + *(buffer+encoded) = fgmmcapability->length; + encoded++; + *(buffer+encoded) = fgmmcapability->value; + encoded++; + } + return encoded; +} + diff --git a/openair2/LAYER2/NR_MAC_UE/mac.h b/openair3/NAS/COMMON/IES/FGMMCapability.h similarity index 67% rename from openair2/LAYER2/NR_MAC_UE/mac.h rename to openair3/NAS/COMMON/IES/FGMMCapability.h index 9418511adf..d427896338 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac.h +++ b/openair3/NAS/COMMON/IES/FGMMCapability.h @@ -19,30 +19,33 @@ * contact@openairinterface.org */ -/* \file mac.h - * \brief MAC data structures, constant, and function prototype - * \author R. Knopp, K.H. HSU - * \date 2018 +/*! \file FGMMCapability.h + * \brief 5GS Mobile Capability for registration request procedures + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 * \version 0.1 - * \company Eurecom / NTUST - * \email: knopp@eurecom.fr, kai-hsiang.hsu@eurecom.fr - * \note - * \warning */ -#ifndef __LAYER2_NR_UE_MAC_DEFS_H__ -#define __LAYER2_NR_UE_MAC_DEFS_H__ #include #include -#include +#include -/*!\brief UE layer 2 status */ -typedef enum { - UE_CONNECTION_OK = 0, - UE_CONNECTION_LOST, - UE_PHY_RESYNCH, - UE_PHY_HO_PRACH -} NR_UE_L2_STATE_t; +#include "OctetString.h" + +#ifndef FGMM_CAPABILITY_H_ +#define FGMM_CAPABILITY_H_ + + +typedef struct { + uint8_t iei; + uint8_t length; + uint8_t value; +} FGMMCapability; + + +int encode_5gmm_capability(FGMMCapability *fgmmcapability, uint8_t iei, uint8_t *buffer, uint32_t len); + +#endif /* FGMM_CAPABILITY_H_ */ -#endif /*__LAYER2_NR_UE_MAC_DEFS_H__ */ diff --git a/openair3/NAS/COMMON/IES/FGSMobileIdentity.c b/openair3/NAS/COMMON/IES/FGSMobileIdentity.c new file mode 100644 index 0000000000..5f920105f9 --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGSMobileIdentity.c @@ -0,0 +1,246 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSMobileIdentity.c + * \brief 5GS Mobile Identity for registration request procedures + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + + +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "FGSMobileIdentity.h" + +static int decode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer); + +static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer); +static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_t *buffer); +static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer); + +int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + int decoded_rc = TLV_DECODE_VALUE_DOESNT_MATCH; + int decoded = 0; + uint8_t ielen = 0; + + if (iei > 0) { + CHECK_IEI_DECODER(iei, *buffer); + decoded++; + } + + ielen = *(buffer + decoded); + decoded++; + CHECK_LENGTH_DECODER(len - decoded, ielen); + + uint8_t typeofidentity = *(buffer + decoded) & 0x7; + + if (typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI) { + decoded_rc = decode_guti_5gs_mobile_identity(&fgsmobileidentity->guti, + buffer + decoded); + } + + if (decoded_rc < 0) { + return decoded_rc; + } + + return (decoded + decoded_rc); +} + +int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + int encoded_rc = TLV_ENCODE_VALUE_DOESNT_MATCH; + uint32_t encoded = 0; + + if (iei > 0) { + *buffer = iei; + encoded++; + } + + encoded = encoded + 2; + + if (fgsmobileidentity->guti.typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI) { + encoded_rc = encode_guti_5gs_mobile_identity(&fgsmobileidentity->guti, + buffer + encoded); + } + + if (fgsmobileidentity->suci.typeofidentity == FGS_MOBILE_IDENTITY_SUCI) { + encoded_rc = encode_suci_5gs_mobile_identity(&fgsmobileidentity->suci, + buffer + encoded); + } + + if (fgsmobileidentity->imeisv.typeofidentity == FGS_MOBILE_IDENTITY_IMEISV) { + encoded_rc = encode_imeisv_5gs_mobile_identity(&fgsmobileidentity->imeisv, + buffer + encoded); + } + + if (encoded_rc < 0) { + return encoded_rc; + } + + if(iei > 0){ + *(uint16_t*) (buffer+1) = htons(encoded + encoded_rc - 3); + } else { + *(uint16_t*) buffer = htons(encoded + encoded_rc - 2); + } + + return (encoded + encoded_rc); +} + +static int decode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer) +{ + int decoded = 0; + uint16_t temp; + guti->spare = (*(buffer + decoded) >> 4) & 0xf; + + /* + * For the 5G-GUTI, bits 5 to 8 of octet 3 are coded as "1111" + */ + if (guti->spare != 0xf) { + return (TLV_ENCODE_VALUE_DOESNT_MATCH); + } + + + guti->oddeven = (*(buffer + decoded) >> 3) & 0x1; + + /* + * For the 5G-GUTI, bits 4 of octet 3 are coded as "0" + */ + if (guti->oddeven != 0) { + return (TLV_ENCODE_VALUE_DOESNT_MATCH); + } + guti->typeofidentity = *(buffer + decoded) & 0x7; + + if (guti->typeofidentity != FGS_MOBILE_IDENTITY_5G_GUTI) { + return (TLV_ENCODE_VALUE_DOESNT_MATCH); + } + + decoded++; + guti->mccdigit2 = (*(buffer + decoded) >> 4) & 0xf; + guti->mccdigit1 = *(buffer + decoded) & 0xf; + decoded++; + guti->mncdigit3 = (*(buffer + decoded) >> 4) & 0xf; + guti->mccdigit3 = *(buffer + decoded) & 0xf; + decoded++; + guti->mncdigit2 = (*(buffer + decoded) >> 4) & 0xf; + guti->mncdigit1 = *(buffer + decoded) & 0xf; + decoded++; + + + guti->amfregionid = *(buffer+decoded); + decoded++; + IES_DECODE_U16(buffer, decoded, temp); + guti->amfsetid = temp>>3; + guti->amfpointer = temp&0x3f; + + IES_DECODE_U32(buffer, decoded, guti->tmsi); + return decoded; +} + + +static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer) +{ + uint32_t encoded = 0; + uint16_t temp; + *(buffer + encoded) = 0xf0 | ((guti->oddeven & 0x1) << 3) | + (guti->typeofidentity & 0x7); + encoded++; + *(buffer + encoded) = 0x00 | ((guti->mccdigit2 & 0xf) << 4) | + (guti->mccdigit1 & 0xf); + encoded++; + *(buffer + encoded) = 0x00 | ((guti->mncdigit3 & 0xf) << 4) | + (guti->mccdigit3 & 0xf); + encoded++; + *(buffer + encoded) = 0x00 | ((guti->mncdigit2 & 0xf) << 4) | + (guti->mncdigit1 & 0xf); + encoded++; + + *(buffer + encoded) = guti->amfregionid; + encoded++; + + temp = 0x00 | ((guti->amfsetid) << 6) | (guti->amfpointer & 0x3f); + + IES_ENCODE_U16(buffer, encoded, temp); + IES_ENCODE_U32(buffer, encoded, guti->tmsi); + return encoded; +} + + +static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_t *buffer) +{ + uint32_t encoded = 0; + *(buffer + encoded) = (suci->supiformat << 4) | (suci->typeofidentity); + encoded++; + *(buffer + encoded) = ((suci->mccdigit2 & 0xf) << 4) | + (suci->mccdigit1 & 0xf); + encoded++; + *(buffer + encoded) = ((suci->mncdigit3 & 0xf) << 4) | + (suci->mccdigit3 & 0xf); + encoded++; + *(buffer + encoded) = ((suci->mncdigit2 & 0xf) << 4) | + (suci->mncdigit1 & 0xf); + encoded++; + + *(buffer + encoded) = ((suci->routingindicatordigit2 & 0xf) << 4) | + (suci->routingindicatordigit1 & 0xf); + encoded++; + + *(buffer + encoded) = ((suci->routingindicatordigit4 & 0xf) << 4) | + (suci->routingindicatordigit3 & 0xf); + encoded++; + + *(buffer + encoded) = 0x00 | (suci->protectionschemeId & 0xf); + encoded++; + + *(buffer + encoded) = suci->homenetworkpki; + encoded++; + + char *ptr=suci->schemeoutput; + while ( ptr < suci->schemeoutput+strlen(suci->schemeoutput) ) { + buffer[encoded]=((*(ptr+1)-'0')<<4) | (*(ptr) -'0'); + encoded++; + ptr+=2; + } + + if (strlen(suci->schemeoutput)%2 == 1) + buffer[encoded++]=((*(ptr-1)-'0')) | 0xF0; + return encoded; +} + +static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer) +{ + uint32_t encoded = 0; + *(buffer + encoded) = 0x00 | (imeisv->digit1 << 4) | (imeisv->oddeven << 3) | (imeisv->typeofidentity); + encoded++; + + *(buffer + encoded) = 0x00 | (imeisv->digitp1 << 4) | (imeisv->digitp); + encoded++; + + return encoded; +} + diff --git a/openair3/NAS/COMMON/IES/FGSMobileIdentity.h b/openair3/NAS/COMMON/IES/FGSMobileIdentity.h new file mode 100644 index 0000000000..7968bc3300 --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGSMobileIdentity.h @@ -0,0 +1,135 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSMobileIdentity.h + * \brief 5GS Mobile Identity for registration request procedures + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + + +#include +#include +#include + +#include "OctetString.h" + +#ifndef FGS_MOBILE_IDENTITY_H_ +#define FGS_MOBILE_IDENTITY_H_ + + +typedef struct { + uint8_t spare:5; + uint8_t typeofidentity:3; +} NoIdentity5GSMobileIdentity_t; + +typedef struct { + uint8_t spare1:1; + uint8_t supiformat:3; + uint8_t spare2:1; + uint8_t typeofidentity:3; + uint8_t mccdigit2:4; + uint8_t mccdigit1:4; + uint8_t mncdigit3:4; + uint8_t mccdigit3:4; + uint8_t mncdigit2:4; + uint8_t mncdigit1:4; + uint8_t routingindicatordigit2:4; + uint8_t routingindicatordigit1:4; + uint8_t routingindicatordigit4:4; + uint8_t routingindicatordigit3:4; + uint8_t spare3:1; + uint8_t spare4:1; + uint8_t spare5:1; + uint8_t spare6:1; + uint8_t protectionschemeId:4; + uint8_t homenetworkpki; + char schemeoutput[32]; +} Suci5GSMobileIdentity_t; + +typedef struct { + uint8_t spare:4; + uint8_t oddeven:1; + uint8_t typeofidentity:3; + uint8_t mccdigit2:4; + uint8_t mccdigit1:4; + uint8_t mncdigit3:4; + uint8_t mccdigit3:4; + uint8_t mncdigit2:4; + uint8_t mncdigit1:4; + uint8_t amfregionid; + uint16_t amfsetid:10; + uint16_t amfpointer:6; + uint32_t tmsi; +} Guti5GSMobileIdentity_t; + + +typedef struct { + uint8_t digit1:4; + uint8_t oddeven:1; + uint8_t typeofidentity:3; + uint8_t digitp1:4; + uint8_t digitp:4; +} Imei5GSMobileIdentity_t; + +typedef Imei5GSMobileIdentity_t Imeisv5GSMobileIdentity_t; + + +typedef struct { + uint8_t digit1:4; + uint8_t spare:1; + uint8_t typeofidentity:3; + uint16_t amfsetid:10; + uint16_t amfpointer:6; + uint32_t tmsi; +} Stmsi5GSMobileIdentity_t; + +typedef struct { + uint8_t spare:5; + uint8_t typeofidentity:3; + uint8_t macaddr; +} Macaddr5GSMobileIdentity_t; + +typedef union FGSMobileIdentity_tag { +#define FGS_MOBILE_IDENTITY_NOIDENTITY 0b000 +#define FGS_MOBILE_IDENTITY_SUCI 0b001 +#define FGS_MOBILE_IDENTITY_5G_GUTI 0b010 +#define FGS_MOBILE_IDENTITY_IMEI 0b011 +#define FGS_MOBILE_IDENTITY_5GS_TMSI 0b100 +#define FGS_MOBILE_IDENTITY_IMEISV 0b101 +#define FGS_MOBILE_IDENTITY_MAC_ADDR 0b110 + NoIdentity5GSMobileIdentity_t noidentity; + Suci5GSMobileIdentity_t suci; + Guti5GSMobileIdentity_t guti; + Imei5GSMobileIdentity_t imei; + Stmsi5GSMobileIdentity_t stmsi; + Imeisv5GSMobileIdentity_t imeisv; + Macaddr5GSMobileIdentity_t macaddress; +} FGSMobileIdentity; + +int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len); + +int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len); + +#endif /* FGS MOBILE IDENTITY_H_ */ + diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationResult.c b/openair3/NAS/COMMON/IES/FGSRegistrationResult.c new file mode 100644 index 0000000000..e580b14409 --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGSRegistrationResult.c @@ -0,0 +1,62 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSRegistrationResult.c + +\brief 5GS Registration result for registration request procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "FGSRegistrationResult.h" + + +int decode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult, uint8_t iei, uint16_t value, uint32_t len) +{ + int decoded = 0; + uint16_t *buffer = &value; + fgsregistrationresult->registrationresult = *buffer & 0x7; + fgsregistrationresult->smsallowed = *buffer & 0x8; + decoded = decoded+2; + return decoded; +} + +uint16_t encode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult) +{ + uint16_t bufferReturn; + uint16_t *buffer = &bufferReturn; + uint8_t encoded = 0; + *(buffer + encoded) = 0x00 | (fgsregistrationresult->smsallowed & 0x8) | + (fgsregistrationresult->registrationresult & 0x7); + encoded= encoded+2; + + return bufferReturn; +} + diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationResult.h b/openair3/NAS/COMMON/IES/FGSRegistrationResult.h new file mode 100644 index 0000000000..0a2dedc2e5 --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGSRegistrationResult.h @@ -0,0 +1,59 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSRegistrationResult.h + +\brief 5GS Registration result for registration request procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include + +#include "OctetString.h" + + + +#ifndef FGS_REGISTRATION_RESULT_H_ +#define FGS_REGISTRATION_RESULT_H_ +#define FGS_REGISTRATION_RESULT_3GPP 0b001 +#define FGS_REGISTRATION_RESULT_NON_3GPP 0b010 +#define FGS_REGISTRATION_RESULT_3GPP_AND_NON_3GPP 0b011 + +typedef struct { + uint8_t iei; + uint8_t resultlength; + uint8_t spare:4; + uint8_t smsallowed:1; + uint8_t registrationresult:3; +} FGSRegistrationResult; + + +uint16_t encode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult); + +int decode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult, uint8_t iei, uint16_t value, uint32_t len); + +#endif /* FGS REGISTRATION RESULT_H_*/ + diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationType.c b/openair3/NAS/COMMON/IES/FGSRegistrationType.c new file mode 100644 index 0000000000..7f1c3ae667 --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGSRegistrationType.c @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSRegistrationType.c + * \brief 5GS Registration Type for registration request procedures + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "FGSRegistrationType.h" + +int decode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype, uint8_t iei, uint8_t value, uint32_t len) +{ + int decoded = 0; + uint8_t *buffer = &value; + if (iei > 0) { + CHECK_IEI_DECODER((*buffer & 0xf0), iei); + } + + *fgsregistrationtype = *buffer & 0x7; + decoded++; + + return decoded; +} + +int encode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype) +{ + uint8_t bufferReturn; + uint8_t *buffer = &bufferReturn; + uint8_t encoded = 0; + uint8_t iei = 0; + *(buffer + encoded) = 0x00 | (iei & 0xf0) | 0x8| + (*fgsregistrationtype & 0x7); + encoded++; + + return bufferReturn; +} + diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationType.h b/openair3/NAS/COMMON/IES/FGSRegistrationType.h new file mode 100644 index 0000000000..a548d45d93 --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGSRegistrationType.h @@ -0,0 +1,55 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file FGSRegistrationType.h + * \brief 5GS Registration Type for registration request procedures + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ +#include +#include +#include + +#include "OctetString.h" + +#ifndef FGS_REGISTRATION_TYPE_H_ +#define FGS_REGISTRATION_TYPE_H_ + +#define FGS_REGISTRATION_TYPE_MINIMUM_LENGTH 1 +#define FGS_REGISTRATION_TYPE_MAXIMUM_LENGTH 1 + +typedef uint8_t FGSRegistrationType; + + +#define INITIAL_REGISTRATION 0b001 +#define MOBILITY_REGISTRATION_UPDATING 0b010 +#define PERIODIC_REGISTRATION_UPDATING 0b011 +#define EMERGENCY_REGISTRATION 0b100 + +int encode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype); + +int decode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype, uint8_t iei, uint8_t value, uint32_t len); + + +#endif /* FGS_REGISTRATION_TYPE_H_*/ + diff --git a/common/utils/itti_analyzer/libresolver/resolvers.h b/openair3/NAS/COMMON/IES/NasPagingIdentity.h similarity index 64% rename from common/utils/itti_analyzer/libresolver/resolvers.h rename to openair3/NAS/COMMON/IES/NasPagingIdentity.h index 17e16462b4..3e03128006 100644 --- a/common/utils/itti_analyzer/libresolver/resolvers.h +++ b/openair3/NAS/COMMON/IES/NasPagingIdentity.h @@ -19,27 +19,25 @@ * contact@openairinterface.org */ -#ifndef RESOLVERS_H_ -#define RESOLVERS_H_ +#include +#include +#include -int resolve_typedefs(types_t **head); +#include "OctetString.h" -int resolve_struct(types_t **head); +#ifndef NASPAGING_IDENTITY_H_ +#define NASPAGING_IDENTITY_H_ -int resolve_pointer_type(types_t **head); +#define PAGING_IDENTITY_MINIMUM_LENGTH 2 +#define PAGING_IDENTITY_MAXIMUM_LENGTH 2 -int resolve_field(types_t **head); +typedef uint8_t PagingIdentity; -int resolve_array(types_t **head); +int encode_paging_identity(PagingIdentity *pagingidentity, uint8_t iei, uint8_t *buffer, uint32_t len); -int resolve_reference(types_t **head); +void dump_paging_identity_xml(PagingIdentity *pagingidentity, uint8_t iei); -int resolve_union(types_t **head); +int decode_paging_identity(PagingIdentity *pagingidentity, uint8_t iei, uint8_t *buffer, uint32_t len); -int resolve_file(types_t **head); +#endif /* PAGING IDENTITY_H_ */ -int resolve_function(types_t **head); - -int search_file(types_t *head, types_t **found, int id); - -#endif /* RESOLVERS_H_ */ diff --git a/openair3/NAS/COMMON/IES/NrUESecurityCapability.c b/openair3/NAS/COMMON/IES/NrUESecurityCapability.c new file mode 100644 index 0000000000..6c0ff7e7c7 --- /dev/null +++ b/openair3/NAS/COMMON/IES/NrUESecurityCapability.c @@ -0,0 +1,63 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file NrUESecurityCapability.c + * \brief 5GS UE Security Capability for registration request procedures + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + + +#include +#include +#include + + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "NrUESecurityCapability.h" + + + +int encode_nrue_security_capability(NrUESecurityCapability *nruesecuritycapability, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + if(iei){ + *buffer = nruesecuritycapability->iei; + encoded++; + *(buffer+encoded) = nruesecuritycapability->length; + encoded++; + *(buffer+encoded) = nruesecuritycapability->fg_EA; + encoded++; + *(buffer+encoded) = nruesecuritycapability->fg_IA; + encoded++; + *(buffer+encoded) = nruesecuritycapability->EEA; + encoded++; + *(buffer+encoded) = nruesecuritycapability->EIA; + encoded++; + if((nruesecuritycapability->length - 4) > 0) + encoded = encoded + nruesecuritycapability->length - 4; + } + return encoded; +} + diff --git a/openair3/NAS/COMMON/IES/NrUESecurityCapability.h b/openair3/NAS/COMMON/IES/NrUESecurityCapability.h new file mode 100644 index 0000000000..10aa0cf0ea --- /dev/null +++ b/openair3/NAS/COMMON/IES/NrUESecurityCapability.h @@ -0,0 +1,53 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file NrUESecurityCapability.h + * \brief 5GS UE Security Capability for registration request procedures + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + +#include +#include +#include + +#include "OctetString.h" + +#ifndef NRUE_SECURITY_CAPABILITY_H_ +#define NRUE_SECURITY_CAPABILITY_H_ + + +typedef struct { + uint8_t iei; + uint8_t length; + uint8_t fg_EA; + uint8_t fg_IA; + uint8_t EEA; + uint8_t EIA; +} NrUESecurityCapability; + + +int encode_nrue_security_capability(NrUESecurityCapability *nruesecuritycapability, uint8_t iei, uint8_t *buffer, uint32_t len); + +#endif /* NRUE_SECURITY_CAPABILITY_H_ */ + diff --git a/openair3/NAS/COMMON/IES/SORTransparentContainer.c b/openair3/NAS/COMMON/IES/SORTransparentContainer.c new file mode 100644 index 0000000000..3ab2a14c3d --- /dev/null +++ b/openair3/NAS/COMMON/IES/SORTransparentContainer.c @@ -0,0 +1,103 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include + +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "SORTransparentContainer.h" +#include "nas_log.h" + +//#define NAS_DEBUG 1 + +int decode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + int decoded = 0; + int decode_result; + uint16_t ielen; + + LOG_FUNC_IN; + + if (iei > 0) { + CHECK_IEI_DECODER(iei, *buffer); + decoded++; + } + + DECODE_LENGTH_U16(buffer + decoded, ielen, decoded); + + CHECK_LENGTH_DECODER(len - decoded, ielen); + + + if ((decode_result = decode_octet_string(&sortransparentcontainer->sortransparentcontainercontents, ielen, buffer + decoded, len - decoded)) < 0) { + LOG_FUNC_RETURN(decode_result); + } else { + decoded += decode_result; + } + +#if defined (NAS_DEBUG) + dump_sor_transparent_container_xml(sortransparentcontainer, iei); +#endif + LOG_FUNC_RETURN(decoded); +} + +int encode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + uint8_t *lenPtr; + uint32_t encoded = 0; + int32_t encode_result; + /* Checking IEI and pointer */ + CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, SOR_TRANSPARENT_CONTAINER_MINIMUM_LENGTH, len); +#if defined (NAS_DEBUG) + dump_sor_transparent_container_xml(sortransparentcontainer, iei); +#endif + + if (iei > 0) { + *buffer = iei; + encoded++; + } + + lenPtr = (buffer + encoded); + + //encoded += 2; + //if ((encode_result = encode_octet_string(&sortransparentcontainer->sortransparentcontainercontents, buffer + sizeof(uint16_t), len - sizeof(uint16_t))) < 0) + if ((encode_result = encode_octet_string(&sortransparentcontainer->sortransparentcontainercontents, lenPtr + sizeof(uint16_t), len - sizeof(uint16_t))) < 0) + return encode_result; + else + encoded += encode_result; + + ENCODE_U16(lenPtr, encode_result, encoded); + return encoded; +} + +void dump_sor_transparent_container_xml(SORTransparentContainer *sortransparentcontainer, uint8_t iei) +{ + printf("\n"); + + if (iei > 0) + /* Don't display IEI if = 0 */ + printf(" 0x%X\n", iei); + + printf("%s", dump_octet_string_xml(&sortransparentcontainer->sortransparentcontainercontents)); + printf("\n"); +} + diff --git a/common/utils/memory_pools.h b/openair3/NAS/COMMON/IES/SORTransparentContainer.h similarity index 55% rename from common/utils/memory_pools.h rename to openair3/NAS/COMMON/IES/SORTransparentContainer.h index 1c1997f7f2..587419b1f9 100644 --- a/common/utils/memory_pools.h +++ b/openair3/NAS/COMMON/IES/SORTransparentContainer.h @@ -19,24 +19,27 @@ * contact@openairinterface.org */ -#ifndef MEMORY_POOLS_H_ -#define MEMORY_POOLS_H_ - +#include +#include #include -typedef void * memory_pools_handle_t; -typedef void * memory_pool_item_handle_t; +#include "OctetString.h" -memory_pools_handle_t memory_pools_create (uint32_t pools_number); +#ifndef SOR_TRANSPARENT_CONTAINER_H_ +#define SOR_TRANSPARENT_CONTAINER_H_ -char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle); +#define SOR_TRANSPARENT_CONTAINER_MINIMUM_LENGTH 2 // [length]+[length] +#define SOR_TRANSPARENT_CONTAINER_MAXIMUM_LENGTH 65538 // [IEI]+[length]+[length]+[ESM msg] -int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size); +typedef struct SORTransparentContainer_tag { + OctetString sortransparentcontainercontents; +} SORTransparentContainer; -memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint16_t info_0, uint16_t info_1); +int encode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, uint8_t iei, uint8_t *buffer, uint32_t len); -int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint16_t info_0); +int decode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, uint8_t iei, uint8_t *buffer, uint32_t len); -void memory_pools_set_info (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, int index, uint16_t info); +void dump_sor_transparent_container_xml(SORTransparentContainer *sortransparentcontainer, uint8_t iei); + +#endif /* ESM MESSAGE CONTAINER_H_ */ -#endif /* MEMORY_POOLS_H_ */ diff --git a/common/utils/itti_analyzer/libparser/xml_parse.h b/openair3/NAS/COMMON/IES/SpareHalfOctet.c similarity index 64% rename from common/utils/itti_analyzer/libparser/xml_parse.h rename to openair3/NAS/COMMON/IES/SpareHalfOctet.c index f9624bc06b..60c45e07c2 100644 --- a/common/utils/itti_analyzer/libparser/xml_parse.h +++ b/openair3/NAS/COMMON/IES/SpareHalfOctet.c @@ -19,25 +19,32 @@ * contact@openairinterface.org */ -#include "rc.h" -#include "types.h" -#ifndef XML_PARSE_H_ -#define XML_PARSE_H_ +/*! \file SpareHalfOctet.c -extern void *xml_raw_data; -extern uint32_t xml_raw_data_size; +\brief registration request procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ -extern types_t *root; +#include +#include +#include -int xml_parse_file(const char *filename); -int xml_parse_buffer(char *xml_buffer, const int size); +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "SpareHalfOctet.h" -int dissect_signal(buffer_t *buffer, ui_set_signal_text_cb_t ui_set_signal_text_cb, - gpointer user_data); +int decode_spare_half_octet(SpareHalfOctet *sparehalfoctet, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + return 0; +} -int dissect_signal_header(buffer_t *buffer, ui_set_signal_text_cb_t ui_set_signal_text_cb, - gpointer cb_user_data); +int encode_spare_half_octet(SpareHalfOctet *sparehalfoctet, uint8_t iei, uint8_t *buffer, uint32_t len) +{ + return 0; +} -#endif /* XML_PARSE_H_ */ diff --git a/common/utils/itti_analyzer/libui/ui_notifications.h b/openair3/NAS/COMMON/IES/SpareHalfOctet.h similarity index 60% rename from common/utils/itti_analyzer/libui/ui_notifications.h rename to openair3/NAS/COMMON/IES/SpareHalfOctet.h index 33ef0ff5c0..fbf410d4f8 100644 --- a/common/utils/itti_analyzer/libui/ui_notifications.h +++ b/openair3/NAS/COMMON/IES/SpareHalfOctet.h @@ -19,29 +19,33 @@ * contact@openairinterface.org */ -#ifndef UI_NOTIFICATIONS_H_ -#define UI_NOTIFICATIONS_H_ -typedef void (*message_write_callback_t) (const gpointer buffer, const gchar *signal_name); +/*! \file SpareHalfOctet.h -int ui_disable_connect_button(void); +\brief registration request procedures for gNB +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ -int ui_enable_connect_button(void); +#include +#include +#include -int ui_messages_read(char *filename); +#include "OctetString.h" -int ui_messages_open_file_chooser(void); +#ifndef SPARE_HALF_OCTET_H_ +#define SPARE_HALF_OCTET_H_ -int ui_messages_save_file_chooser(gboolean filtered); +#define SPARE_HALF_OCTET_MINIMUM_LENGTH 1 +#define SPARE_HALF_OCTET_MAXIMUM_LENGTH 1 -int ui_filters_open_file_chooser(void); +typedef uint8_t SpareHalfOctet; -int ui_filters_save_file_chooser(void); +int encode_spare_half_octet(SpareHalfOctet *sparehalfoctet, uint8_t iei, uint8_t *buffer, uint32_t len); -void ui_progressbar_window_destroy(void); +int decode_spare_half_octet(SpareHalfOctet *sparehalfoctet, uint8_t iei, uint8_t *buffer, uint32_t len); -int ui_progress_bar_set_fraction(double fraction); +#endif /* SPARE HALF OCTET_H_ */ -int ui_progress_bar_terminate(void); - -#endif /* UI_NOTIFICATIONS_H_ */ diff --git a/openair3/NAS/COMMON/IES/SupportedCodecList.c b/openair3/NAS/COMMON/IES/SupportedCodecList.c index 3a69eee366..15a2fecaa0 100644 --- a/openair3/NAS/COMMON/IES/SupportedCodecList.c +++ b/openair3/NAS/COMMON/IES/SupportedCodecList.c @@ -43,13 +43,17 @@ int decode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t CHECK_LENGTH_DECODER(len - decoded, ielen); supportedcodeclist->systemidentification = *(buffer + decoded); decoded++; + ielen--; supportedcodeclist->lengthofbitmap = *(buffer + decoded); decoded++; + ielen--; //IES_DECODE_U16(supportedcodeclist->codecbitmap, *(buffer + decoded)); IES_DECODE_U16(buffer, decoded, supportedcodeclist->codecbitmap); + ielen=ielen -2; #if defined (NAS_DEBUG) dump_supported_codec_list_xml(supportedcodeclist, iei); #endif + decoded = decoded + ielen; return decoded; } int encode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t iei, uint8_t *buffer, uint32_t len) diff --git a/openair3/NAS/COMMON/NR_NAS_defs.h b/openair3/NAS/COMMON/NR_NAS_defs.h new file mode 100644 index 0000000000..54ac8c037e --- /dev/null +++ b/openair3/NAS/COMMON/NR_NAS_defs.h @@ -0,0 +1,392 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#ifndef NR_NAS_DEFS_H +#define NR_NAS_DEFS_H + +#include +#include +#include + +/* TS 24.007 possible L3 formats: + Table 11.1: Formats of information elements + Format Meaning IEI present LI present Value part present + T Type only yes no no + V Value only no no yes + TV Type and Value yes no yes + LV Length and Value no yes yes + TLV Type, Length and Value yes yes yes + LV-E Length and Value no yes yes + TLV-E Type, Length and Value yes yes yes +*/ + +/* Map task id to printable name. */ +typedef struct { + int id; + char text[256]; +} text_info_t; + +static inline const char * idToText(const text_info_t* table, int size, int id) { + for(int i=0; i TS 24.007 +typedef enum { + SGSsessionmanagementmessages=0x2e, //LTEbox: 0xC0 ??? + SGSmobilitymanagementmessages=0x7e, +} Extendedprotocoldiscriminator_t; + +#define FOREACH_TYPE(TYPE_DEF) \ + TYPE_DEF( Registrationrequest,0x41 )\ +TYPE_DEF( Registrationaccept,0x42 )\ +TYPE_DEF( Registrationcomplete,0x43 )\ +TYPE_DEF( Registrationreject,0x44 )\ +TYPE_DEF( DeregistrationrequestUEoriginating,0x45 )\ +TYPE_DEF( DeregistrationacceptUEoriginating,0x46 )\ +TYPE_DEF( DeregistrationrequestUEterminated,0x47 )\ +TYPE_DEF( DeregistrationacceptUEterminated,0x48 )\ +TYPE_DEF( Servicerequest,0x4c )\ +TYPE_DEF( Servicereject,0x4d )\ +TYPE_DEF( Serviceaccept,0x4e )\ +TYPE_DEF( Controlplaneservicerequest,0x4f )\ +TYPE_DEF( Networkslicespecificauthenticationcommand,0x50 )\ +TYPE_DEF( Networkslicespecificauthenticationcomplete,0x51 )\ +TYPE_DEF( Networkslicespecificauthenticationresult,0x52 )\ +TYPE_DEF( Configurationupdatecommand,0x54 )\ +TYPE_DEF( Configurationupdatecomplete,0x55 )\ +TYPE_DEF( Authenticationrequest,0x56 )\ +TYPE_DEF( Authenticationresponse,0x57 )\ +TYPE_DEF( Authenticationreject,0x58 )\ +TYPE_DEF( Authenticationfailure,0x59 )\ +TYPE_DEF( Authenticationresult,0x5a )\ +TYPE_DEF( Identityrequest,0x5b )\ +TYPE_DEF( Identityresponse,0x5c )\ +TYPE_DEF( Securitymodecommand,0x5d )\ +TYPE_DEF( Securitymodecomplete,0x5e )\ +TYPE_DEF( Securitymodereject,0x5f )\ +TYPE_DEF( SGMMstatus,0x64 )\ +TYPE_DEF( Notification,0x65 )\ +TYPE_DEF( Notificationresponse,0x66 )\ +TYPE_DEF( ULNAStransport,0x67 )\ +TYPE_DEF( DLNAStransport,0x68 )\ +TYPE_DEF( PDUsessionestablishmentrequest,0xc1 )\ +TYPE_DEF( PDUsessionestablishmentaccept,0xc2 )\ +TYPE_DEF( PDUsessionestablishmentreject,0xc3 )\ +TYPE_DEF( PDUsessionauthenticationcommand,0xc5 )\ +TYPE_DEF( PDUsessionauthenticationcomplete,0xc6 )\ +TYPE_DEF( PDUsessionauthenticationresult,0xc7 )\ +TYPE_DEF( PDUsessionmodificationrequest,0xc9 )\ +TYPE_DEF( PDUsessionmodificationreject,0xca )\ +TYPE_DEF( PDUsessionmodificationcommand,0xcb )\ +TYPE_DEF( PDUsessionmodificationcomplete,0xcc )\ +TYPE_DEF( PDUsessionmodificationcommandreject,0xcd )\ +TYPE_DEF( PDUsessionreleaserequest,0xd1 )\ +TYPE_DEF( PDUsessionreleasereject,0xd2 )\ +TYPE_DEF( PDUsessionreleasecommand,0xd3 )\ +TYPE_DEF( PDUsessionreleasecomplete,0xd4 )\ +TYPE_DEF( SGSMstatus,0xd6 )\ + +static const text_info_t message_text_info[] = { + FOREACH_TYPE(TO_TEXT) +}; + +//! Tasks id of each task +typedef enum { + FOREACH_TYPE(TO_ENUM) +} SGSmobilitymanagementmessages_t; + +// TS 24.501 +typedef enum { + notsecurityprotected=0, + Integrityprotected=1, + Integrityprotectedandciphered=2, + Integrityprotectedwithnew5GNASsecuritycontext=3, + Integrityprotectedandcipheredwithnew5GNASsecuritycontext=4, +} Security_header_t; + +typedef enum { + SUCI=1, + SGGUTI, + IMEI, + SGSTMSI, + IMEISV, + MACaddress, + EUI64, +} identitytype_t; + + +// table 9.11.3.2.1 +#define FOREACH_CAUSE(CAUSE_DEF) \ + CAUSE_DEF(Illegal_UE,0x3 )\ + CAUSE_DEF(PEI_not_accepted,0x5 )\ + CAUSE_DEF(Illegal_ME,0x6 )\ + CAUSE_DEF(SGS_services_not_allowed,0x7 )\ + CAUSE_DEF(UE_identity_cannot_be_derived_by_the_network,0x9 )\ + CAUSE_DEF(Implicitly_de_registered,0x0a )\ + CAUSE_DEF(PLMN_not_allowed,0x0b )\ + CAUSE_DEF(Tracking_area_not_allowed,0x0c )\ + CAUSE_DEF(Roaming_not_allowed_in_this_tracking_area,0x0d )\ + CAUSE_DEF(No_suitable_cells_in_tracking_area,0x0f )\ + CAUSE_DEF(MAC_failure,0x14 )\ + CAUSE_DEF(Synch_failure,0x15 )\ + CAUSE_DEF(Congestion,0x16 )\ + CAUSE_DEF(UE_security_capabilities_mismatch,0x17 )\ + CAUSE_DEF(Security_mode_rejected_unspecified,0x18 )\ + CAUSE_DEF(Non_5G_authentication_unacceptable,0x1a )\ + CAUSE_DEF(N1_mode_not_allowed,0x1b )\ + CAUSE_DEF(Restricted_service_area,0x1c )\ + CAUSE_DEF(Redirection_to_EPC_required,0x1f )\ + CAUSE_DEF(LADN_not_available,0x2b )\ + CAUSE_DEF(No_network_slices_available,0x3e )\ + CAUSE_DEF(Maximum_number_of_PDU_sessions_reached,0x41 )\ + CAUSE_DEF(Insufficient_resources_for_specific_slice_and_DNN,0x43 )\ + CAUSE_DEF(Insufficient_resources_for_specific_slice,0x45 )\ + CAUSE_DEF(ngKSI_already_in_use,0x47 )\ + CAUSE_DEF(Non_3GPP_access_to_5GCN_not_allowed,0x48 )\ + CAUSE_DEF(Serving_network_not_authorized,0x49 )\ + CAUSE_DEF(Temporarily_not_authorized_for_this_SNPN,0x4A )\ + CAUSE_DEF(Permanently_not_authorized_for_this_SNPN,0x4b )\ + CAUSE_DEF(Not_authorized_for_this_CAG_or_authorized_for_CAG_cells_only,0x4c )\ + CAUSE_DEF(Wireline_access_area_not_allowed,0x4d )\ + CAUSE_DEF(Payload_was_not_forwarded,0x5a )\ + CAUSE_DEF(DNN_not_supported_or_not_subscribed_in_the_slice,0x5b )\ + CAUSE_DEF(Insufficient_user_plane_resources_for_the_PDU_session,0x5c )\ + CAUSE_DEF(Semantically_incorrect_message,0x5f )\ + CAUSE_DEF(Invalid_mandatory_information,0x60 )\ + CAUSE_DEF(Message_type_non_existent_or_not_implemented,0x61 )\ + CAUSE_DEF(Message_type_not_compatible_with_the_protocol_state,0x62 )\ + CAUSE_DEF(Information_element_non_existent_or_not_implemented,0x63 )\ + CAUSE_DEF(Conditional_IE_error,0x64 )\ + CAUSE_DEF(Message_not_compatible_with_the_protocol_state,0x65 )\ + CAUSE_DEF(Protocol_error_unspecified,0x67 ) + +/* Map task id to printable name. */ + +#define CAUSE_TEXT(LabEl, nUmID) {nUmID, #LabEl}, + +static const text_info_t cause_text_info[] = { + FOREACH_CAUSE(TO_TEXT) +}; + +#define CAUSE_ENUM(LabEl, nUmID ) LabEl = nUmID, +//! Tasks id of each task +typedef enum { + FOREACH_CAUSE(TO_ENUM) +} cause_id_t; + +//_table_9.11.4.2.1:_5GSM_cause_information_element +#define FOREACH_CAUSE_SECU(CAUSE_SECU_DEF) \ + CAUSE_SECU_DEF(Security_Operator_determined_barring,0x08 )\ + CAUSE_SECU_DEF(Security_Insufficient_resources,0x1a )\ + CAUSE_SECU_DEF(Security_Missing_or_unknown_DNN,0x1b )\ + CAUSE_SECU_DEF(Security_Unknown_PDU_session_type,0x1c )\ + CAUSE_SECU_DEF(Security_User_authentication_or_authorization_failed,0x1d )\ + CAUSE_SECU_DEF(Security_Request_rejected_unspecified,0x1f )\ + CAUSE_SECU_DEF(Security_Service_option_not_supported,0x20 )\ + CAUSE_SECU_DEF(Security_Requested_service_option_not_subscribed,0x21 )\ + CAUSE_SECU_DEF(Security_Service_option_temporarily_out_of_order,0x22 )\ + CAUSE_SECU_DEF(Security_PTI_already_in_use,0x23 )\ + CAUSE_SECU_DEF(Security_Regular_deactivation,0x24 )\ + CAUSE_SECU_DEF(Security_Network_failure,0x26 )\ + CAUSE_SECU_DEF(Security_Reactivation_requested,0x27 )\ + CAUSE_SECU_DEF(Security_Semantic_error_in_the_TFT_operation,0x29 )\ + CAUSE_SECU_DEF(Security_Syntactical_error_in_the_TFT_operation,0x2a )\ + CAUSE_SECU_DEF(Security_Invalid_PDU_session_identity,0x2b )\ + CAUSE_SECU_DEF(Security_Semantic_errors_in_packet_filter,0x2c )\ + CAUSE_SECU_DEF(Security_Syntactical_error_in_packet_filter,0x2d )\ + CAUSE_SECU_DEF(Security_Out_of_LADN_service_area,0x2e )\ + CAUSE_SECU_DEF(Security_PTI_mismatch,0x2f )\ + CAUSE_SECU_DEF(Security_PDU_session_type_IPv4_only_allowed,0x32 )\ + CAUSE_SECU_DEF(Security_PDU_session_type_IPv6_only_allowed,0x33 )\ + CAUSE_SECU_DEF(Security_PDU_session_does_not_exist,0x36 )\ + CAUSE_SECU_DEF(Security_PDU_session_type_IPv4v6_only_allowed,0x39 )\ + CAUSE_SECU_DEF(Security_PDU_session_type_Unstructured_only_allowed,0x3a )\ + CAUSE_SECU_DEF(Security_PDU_session_type_Ethernet_only_allowed,0x3d )\ + CAUSE_SECU_DEF(Security_Insufficient_resources_for_specific_slice_and_DNN,0x43 )\ + CAUSE_SECU_DEF(Security_Not_supported_SSC_mode,0x44 )\ + CAUSE_SECU_DEF(Security_Insufficient_resources_for_specific_slice,0x45 )\ + CAUSE_SECU_DEF(Security_Missing_or_unknown_DNN_in_a_slice,0x46 )\ + CAUSE_SECU_DEF(Security_Invalid_PTI_value,0x51 )\ + CAUSE_SECU_DEF(Security_Maximum_data_rate_per_UE_for_user_plane_integrity_protection_is_too_low,0x52 )\ + CAUSE_SECU_DEF(Security_Semantic_error_in_the_QoS_operation,0x53 )\ + CAUSE_SECU_DEF(Security_Syntactical_error_in_the_QoS_operation,0x54 )\ + CAUSE_SECU_DEF(Security_Invalid_mapped_EPS_bearer_identity,0x55 )\ + CAUSE_SECU_DEF(Security_Semantically_incorrect_message,0x5f )\ + CAUSE_SECU_DEF(Security_Invalid_mandatory_information,0x60 )\ + CAUSE_SECU_DEF(Security_Message_type_non_existent_or_not_implemented,0x61 )\ + CAUSE_SECU_DEF(Security_Message_type_not_compatible_with_the_protocol_state,0x62 )\ + CAUSE_SECU_DEF(Security_Information_element_non_existent_or_not_implemented,0x63 )\ + CAUSE_SECU_DEF(Security_Conditional_IE_error,0x64 )\ + CAUSE_SECU_DEF(Security_Message_not_compatible_with_the_protocol_state,0x65 )\ + CAUSE_SECU_DEF(Security_Protocol_error_unspecified,0x6f ) + +static const text_info_t cause_secu_text_info[] = { + FOREACH_CAUSE_SECU(TO_TEXT) +}; + +//! Tasks id of each task +typedef enum { + FOREACH_CAUSE_SECU(TO_ENUM) +} cause_secu_id_t; + +// IEI (information element identifier) are spread in each message definition +#define IEI_RAND 0x21 +#define IEI_AUTN 0x20 +#define IEI_EAP 0x78 +#define IEI_AuthenticationResponse 0x2d + +//TS 24.501 sub layer states for UE +// for network side, only 5GMMderegistered, 5GMMderegistered_initiated, 5GMMregistered, 5GMMservice_request_initiated are valid +typedef enum { + SGMMnull, + SGMMderegistered, + SGMMderegistered_initiated, + SGMMregistered, + SGMMregistered_initiated, + SGMMservice_request_initiated, +} SGMM_UE_states; + +typedef struct { + Extendedprotocoldiscriminator_t epd:8; + Security_header_t sh:8; + SGSmobilitymanagementmessages_t mt:8; +} SGScommonHeader_t; + +typedef struct { + Extendedprotocoldiscriminator_t epd:8; + Security_header_t sh:8; + SGSmobilitymanagementmessages_t mt:8; + identitytype_t it:8; +} Identityrequest_t; + +// the message continues with the identity value, depending on identity type, see TS 14.501, 9.11.3.4 +typedef struct __attribute__((packed)) { + Extendedprotocoldiscriminator_t epd:8; + Security_header_t sh:8; + SGSmobilitymanagementmessages_t mt:8; + uint16_t len; +} +Identityresponse_t; + +typedef struct __attribute__((packed)) { + Identityresponse_t common; + identitytype_t mi:8; + unsigned int supiFormat:4; + unsigned int identityType:4; + unsigned int mcc1:4; + unsigned int mcc2:4; + unsigned int mcc3:4; + unsigned int mnc3:4; + unsigned int mnc1:4; + unsigned int mnc2:4; + unsigned int routing1:4; + unsigned int routing2:4; + unsigned int routing3:4; + unsigned int routing4:4; + unsigned int protectScheme:4; + unsigned int spare:4; + uint8_t hplmnId; +} +IdentityresponseIMSI_t; + +typedef struct __attribute__((packed)) { + Extendedprotocoldiscriminator_t epd:8; + Security_header_t sh:8; + SGSmobilitymanagementmessages_t mt:8; + unsigned int ngKSI:4; + unsigned int spare:4; + unsigned int ABBALen:8; + unsigned int ABBA:16; + uint8_t ieiRAND; + uint8_t RAND[16]; + uint8_t ieiAUTN; + uint8_t AUTNlen; + uint8_t AUTN[16]; +} +authenticationrequestHeader_t; + +typedef struct __attribute__((packed)) { + Extendedprotocoldiscriminator_t epd:8; + Security_header_t sh:8; + SGSmobilitymanagementmessages_t mt:8; + uint8_t iei; + uint8_t RESlen; + uint8_t RES[16]; +} authenticationresponse_t; + +//AUTHENTICATION RESULT + +typedef struct __attribute__((packed)) { + Extendedprotocoldiscriminator_t epd:8; + Security_header_t sh:8; + SGSmobilitymanagementmessages_t mt:8; + + unsigned int selectedNASsecurityalgorithms; + unsigned int ngKSI:4; //ngKSI NAS key set identifier 9.11.3.32 + unsigned int spare:4; + // LV 3-9 bytes Replayed UE security capabilities UE security capability 9.11.3.54 + + /* optional + TV (E-, 1 byte) Oprional IMEISV request IMEISV request 9.11.3.28 + TV (57, 2 bytes ) Selected EPS NAS security algorithms EPS NAS security algorithms 9.11.3.25 + TLV (36, 3 bytes) Additional 5G security information Additional 5G security information 9.11.3.12 + TLV-E (78,, 7-1503 bytes) EAP message EAP message 9.11.2.2 + TLV (38, 4-n)ABBA ABBA 9.11.3.10 + TLV (19, 4-7) Replayed S1 UE security capabilities S1 UE security capability 9.11.3.48A + */ + +} securityModeCommand_t; + +typedef struct { + uicc_t *uicc; +} nr_user_nas_t; + +#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed") +#define myCalloc(var, type) type * var=(type*)calloc(sizeof(type),1); +#define arrayCpy(tO, FroM) STATIC_ASSERT(sizeof(tO) == sizeof(FroM)) ; memcpy(tO, FroM, sizeof(tO)) +int resToresStar(uint8_t *msg, uicc_t* uicc); + +int identityResponse(void **msg, nr_user_nas_t *UE); +int authenticationResponse(void **msg, nr_user_nas_t *UE); +void UEprocessNAS(void *msg,nr_user_nas_t *UE); +void SGSabortUE(void *msg, NRUEcontext_t *UE) ; +void SGSregistrationReq(void *msg, NRUEcontext_t *UE); +void SGSderegistrationUEReq(void *msg, NRUEcontext_t *UE); +void SGSauthenticationResp(void *msg, NRUEcontext_t *UE); +void SGSidentityResp(void *msg, NRUEcontext_t *UE); +void SGSsecurityModeComplete(void *msg, NRUEcontext_t *UE); +void SGSregistrationComplete(void *msg, NRUEcontext_t *UE); +void processNAS(void *msg, NRUEcontext_t *UE); +int identityRequest(void **msg, NRUEcontext_t *UE); +int authenticationRequest(void **msg, NRUEcontext_t *UE); +int securityModeCommand(void **msg, NRUEcontext_t *UE); +void servingNetworkName(uint8_t *msg, char * imsiStr, int nmc_size); + +#endif diff --git a/openair3/NAS/COMMON/milenage.h b/openair3/NAS/COMMON/milenage.h new file mode 100644 index 0000000000..c5762a0d69 --- /dev/null +++ b/openair3/NAS/COMMON/milenage.h @@ -0,0 +1,355 @@ +/* + Adaptatipn of SW from hereafter license + Author: laurent.thomas@open-cells.com + The OpenAirInterface project uses this copy under the terms of BSD + license. +*/ +/* + 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) + Copyright (c) 2006-2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + Alternatively, this software may be distributed under the terms of BSD + license. + + See README and COPYING for more details. + + This file implements an example authentication algorithm defined for 3GPP + AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow + EAP-AKA to be tested properly with real USIM cards. + + This implementations assumes that the r1..r5 and c1..c5 constants defined in + TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00, + c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to + be AES (Rijndael). +*/ + +#ifndef MILENAGE_H +#define MILENAGE_H +#include + + +#define u8 uint8_t +/** + milenage_f1 - Milenage f1 and f1* algorithms + @opc: OPc = 128-bit value derived from OP and K + @k: K = 128-bit subscriber key + @_rand: RAND = 128-bit random challenge + @sqn: SQN = 48-bit sequence number + @amf: AMF = 16-bit authentication management field + @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL + @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL + Returns: true on success, false on failure +*/ + +void aes_128_encrypt_block(const u8* key, const u8* in, u8* out) { + AES_KEY k; + u8 tmp[16]; + AES_set_encrypt_key(key, 128, &k); + AES_encrypt(in, tmp, &k); + memcpy(out, tmp, sizeof(tmp)); +} +static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, + const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) { + u8 tmp1[16], tmp2[16], tmp3[16]; + int i; + + /* tmp1 = TEMP = E_K(RAND XOR OP_C) */ + for (i = 0; i < 16; i++) + tmp1[i] = _rand[i] ^ opc[i]; + + aes_128_encrypt_block(k, tmp1, tmp1); + AES_KEY kTab; + uint8_t cyphered[16]; + AES_set_encrypt_key(k, 128, &kTab); + AES_encrypt(tmp1, cyphered, &kTab); + /* tmp2 = IN1 = SQN || AMF || SQN || AMF */ + memcpy(tmp2, sqn, 6); + memcpy(tmp2 + 6, amf, 2); + memcpy(tmp2 + 8, tmp2, 8); + + /* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */ + + /* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */ + for (i = 0; i < 16; i++) + tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i]; + + /* XOR with TEMP = E_K(RAND XOR OP_C) */ + for (i = 0; i < 16; i++) + tmp3[i] ^= tmp1[i]; + + /* XOR with c1 (= ..00, i.e., NOP) */ + /* f1 || f1* = E_K(tmp3) XOR OP_c */ + aes_128_encrypt_block(k, tmp3, tmp1); + + for (i = 0; i < 16; i++) + tmp1[i] ^= opc[i]; + + if (mac_a) + memcpy(mac_a, tmp1, 8); /* f1 */ + + if (mac_s) + memcpy(mac_s, tmp1 + 8, 8); /* f1* */ + + return true; +} + + +/** + milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms + @opc: OPc = 128-bit value derived from OP and K + @k: K = 128-bit subscriber key + @_rand: RAND = 128-bit random challenge + @res: Buffer for RES = 64-bit signed response (f2), or %NULL + @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL + @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL + @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL + @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL + Returns: true on success, false on failure +*/ +static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, + u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) { + u8 tmp1[16], tmp2[16], tmp3[16]; + int i; + + /* tmp2 = TEMP = E_K(RAND XOR OP_C) */ + for (i = 0; i < 16; i++) + tmp1[i] = _rand[i] ^ opc[i]; + + aes_128_encrypt_block(k, tmp1, tmp2); + + /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */ + /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */ + /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */ + /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */ + + /* f2 and f5 */ + /* rotate by r2 (= 0, i.e., NOP) */ + for (i = 0; i < 16; i++) + tmp1[i] = tmp2[i] ^ opc[i]; + + tmp1[15] ^= 1; /* XOR c2 (= ..01) */ + /* f5 || f2 = E_K(tmp1) XOR OP_c */ + aes_128_encrypt_block(k, tmp1, tmp3); + + for (i = 0; i < 16; i++) + tmp3[i] ^= opc[i]; + + if (res) + memcpy(res, tmp3 + 8, 8); /* f2 */ + + if (ak) + memcpy(ak, tmp3, 6); /* f5 */ + + /* f3 */ + if (ck) { + /* rotate by r3 = 0x20 = 4 bytes */ + for (i = 0; i < 16; i++) + tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i]; + + tmp1[15] ^= 2; /* XOR c3 (= ..02) */ + aes_128_encrypt_block(k, tmp1, ck); + + for (i = 0; i < 16; i++) + ck[i] ^= opc[i]; + } + + /* f4 */ + if (ik) { + /* rotate by r4 = 0x40 = 8 bytes */ + for (i = 0; i < 16; i++) + tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i]; + + tmp1[15] ^= 4; /* XOR c4 (= ..04) */ + aes_128_encrypt_block(k, tmp1, ik); + + for (i = 0; i < 16; i++) + ik[i] ^= opc[i]; + } + + /* f5* */ + if (akstar) { + /* rotate by r5 = 0x60 = 12 bytes */ + for (i = 0; i < 16; i++) + tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i]; + + tmp1[15] ^= 8; /* XOR c5 (= ..08) */ + aes_128_encrypt_block(k, tmp1, tmp1); + + for (i = 0; i < 6; i++) + akstar[i] = tmp1[i] ^ opc[i]; + } + + return true; +} + + +/** + milenage_generate - Generate AKA AUTN,IK,CK,RES + @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) + @amf: AMF = 16-bit authentication management field + @k: K = 128-bit subscriber key + @sqn: SQN = 48-bit sequence number + @_rand: RAND = 128-bit random challenge + @autn: Buffer for AUTN = 128-bit authentication token + @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL + @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL + @res: Buffer for RES = 64-bit signed response (f2), or %NULL + @res_len: Max length for res; set to used length or 0 on failure +*/ +static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, + const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, + u8 *ck, u8 *res) { + int i; + u8 mac_a[8], ak[6]; + + if (!milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) || + !milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) + return false; + + /* AUTN = (SQN ^ AK) || AMF || MAC */ + for (i = 0; i < 6; i++) + autn[i] = sqn[i] ^ ak[i]; + + memcpy(autn + 6, amf, 2); + memcpy(autn + 8, mac_a, 8); + return true; +} + + +/** + milenage_auts - Milenage AUTS validation + @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) + @k: K = 128-bit subscriber key + @_rand: RAND = 128-bit random challenge + @auts: AUTS = 112-bit authentication token from client + @sqn: Buffer for SQN = 48-bit sequence number + Returns: 0 = success (sqn filled), -1 on failure +*/ +#define p(a) printf("%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", (int)((a)[0]), (int)((a)[1]), (int)((a)[2]), (int)((a)[3]),(int)((a)[4]), (int)((a)[5])); +// valid code but put in comment as it is not used right now +#if 0 +static bool milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, + u8 *sqn) { + u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ + u8 ak[6], mac_s[8]; + int i; + + if (!milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) + return false; + + for (i = 0; i < 6; i++) + sqn[i] = auts[i] ^ ak[i]; + + //p(sqn); + if (!milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) || + memcmp(mac_s, auts + 6, 8) != 0) + return false; + + return true; +} + + +/** + gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet + @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) + @k: K = 128-bit subscriber key + @_rand: RAND = 128-bit random challenge + @sres: Buffer for SRES = 32-bit SRES + @kc: Buffer for Kc = 64-bit Kc + Returns: 0 on success, -1 on failure +*/ +static bool gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) { + u8 res[8], ck[16], ik[16]; + int i; + + if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL)) + return false; + + for (i = 0; i < 8; i++) + kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8]; + +#ifdef GSM_MILENAGE_ALT_SRES + memcpy(sres, res, 4); +#else /* GSM_MILENAGE_ALT_SRES */ + + for (i = 0; i < 4; i++) + sres[i] = res[i] ^ res[i + 4]; + +#endif /* GSM_MILENAGE_ALT_SRES */ + return true; +} + + +/** + milenage_generate - Generate AKA AUTN,IK,CK,RES + @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) + @k: K = 128-bit subscriber key + @sqn: SQN = 48-bit sequence number + @_rand: RAND = 128-bit random challenge + @autn: AUTN = 128-bit authentication token + @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL + @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL + @res: Buffer for RES = 64-bit signed response (f2), or %NULL + @res_len: Variable that will be set to RES length + @auts: 112-bit buffer for AUTS + Returns: 0 on success, -1 on failure, or -2 on synchronization failure +*/ +static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, + const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, + u8 *auts) { + int i; + u8 mac_a[8], ak[6], rx_sqn[6]; + const u8 *amf; + + if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) + return -1; + + *res_len = 8; + + /* AUTN = (SQN ^ AK) || AMF || MAC */ + for (i = 0; i < 6; i++) + rx_sqn[i] = autn[i] ^ ak[i]; + + if (memcmp(rx_sqn, sqn, 6) <= 0) { + u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ + + if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) + return -1; + + for (i = 0; i < 6; i++) + auts[i] = sqn[i] ^ ak[i]; + + if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6)) + return -1; + + return -2; + } + + amf = autn + 6; + + if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL)) + return -1; + + if (memcmp(mac_a, autn + 8, 8) != 0) { + printf( "Milenage: MAC mismatch\n"); + return -1; + } + + return 0; +} + +static void milenage_opc_gen(const u8 *k, const u8 *op, u8 *opc) { + int i; + /* Encrypt OP using K */ + aes_128_encrypt_block(k, op, opc); + + /* XOR the resulting Ek(OP) with OP */ + for (i = 0; i < 16; i++) + opc[i] = opc[i] ^ op[i]; +} +#endif +#endif diff --git a/openair3/NAS/COMMON/nr_common.c b/openair3/NAS/COMMON/nr_common.c new file mode 100644 index 0000000000..736d75f6cc --- /dev/null +++ b/openair3/NAS/COMMON/nr_common.c @@ -0,0 +1,66 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include + +void servingNetworkName(uint8_t *msg, char * imsiStr, int nmc_size) { + //SNN-network-identifier in TS 24.501 + // TS 24.501: If the MNC of the serving PLMN has two digits, then a zero is added at the beginning. + const char *format="5G:mnc000.mcc000.3gppnetwork.org"; + memcpy(msg,format, strlen(format)); + + if (nmc_size == 2) + memcpy(msg+7, imsiStr+3, 2); + else + memcpy(msg+6, imsiStr+3, 3); + + memcpy(msg+13, imsiStr, 3); +} + +int resToresStar(uint8_t *msg, uicc_t* uicc) { + // TS 33.220 annex B.2 => FC=0x6B in TS 33.501 annex A.4 + //input S to KDF + uint8_t S[128]= {0}; + S[0]=0x6B; + uint8_t *ptr=S+1; + servingNetworkName(ptr, uicc->imsiStr, uicc->nmc_size); + *(uint16_t *)(ptr+strlen((char *)ptr))=htons(strlen((char *)ptr)); + ptr+=strlen((char *)ptr)+sizeof(uint16_t); + // add rand + memcpy(ptr, uicc->rand, sizeof(uicc->rand) ) ; + *(uint16_t *)(ptr+sizeof(uicc->rand))=htons(sizeof(uicc->rand)); + ptr+=sizeof(uicc->rand)+sizeof(uint16_t); + // add res + memcpy(ptr, uicc->milenage_res, sizeof(uicc->milenage_res) ) ; + *(uint16_t *)(ptr+sizeof(uicc->milenage_res))=htons(sizeof(uicc->milenage_res)); + ptr+=sizeof(uicc->milenage_res)+sizeof(uint16_t); + // S is done + uint8_t ckik[sizeof(uicc->ck) +sizeof(uicc->ik)]; + memcpy(ckik, uicc->ck, sizeof(uicc->ck)); + memcpy(ckik+sizeof(uicc->ck),uicc->ik, sizeof(uicc->ik)); + uint8_t out[32]; + kdf(S, ptr-S, ckik, 32, out, sizeof(out)); + memcpy(msg, out+16, 16); + return 16; +} diff --git a/openair3/NAS/NR_UE/.gitkeep b/openair3/NAS/NR_UE/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c new file mode 100644 index 0000000000..ad2f2c7c3c --- /dev/null +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -0,0 +1,993 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file nr_nas_msg_sim.c + * \brief simulator for nr nas message + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + + +#include // memset +#include // malloc, free + +#include "nas_log.h" +#include "TLVDecoder.h" +#include "TLVEncoder.h" +#include "nr_nas_msg_sim.h" +#include "aka_functions.h" +#include "secu_defs.h" +#include "PduSessionEstablishRequest.h" +#include "intertask_interface.h" +#include "openair2/RRC/NAS/nas_config.h" +#include +#include +#include + +uint8_t *registration_request_buf; +uint32_t registration_request_len; +extern char *baseNetAddress; +extern uint16_t NB_UE_INST; +static ue_sa_security_key_t ** ue_security_key; + +static int nas_protected_security_header_encode( + char *buffer, + const fgs_nas_message_security_header_t *header, + int length) +{ + LOG_FUNC_IN; + + int size = 0; + + /* Encode the protocol discriminator) */ + ENCODE_U8(buffer, header->protocol_discriminator, size); + + /* Encode the security header type */ + ENCODE_U8(buffer+size, (header->security_header_type & 0xf), size); + + /* Encode the message authentication code */ + ENCODE_U32(buffer+size, header->message_authentication_code, size); + /* Encode the sequence number */ + ENCODE_U8(buffer+size, header->sequence_number, size); + + LOG_FUNC_RETURN (size); +} + +static int _nas_mm_msg_encode_header(const mm_msg_header_t *header, + uint8_t *buffer, uint32_t len) { + int size = 0; + + /* Check the buffer length */ + if (len < sizeof(mm_msg_header_t)) { + return (TLV_ENCODE_BUFFER_TOO_SHORT); + } + + /* Check the protocol discriminator */ + if (header->ex_protocol_discriminator != FGS_MOBILITY_MANAGEMENT_MESSAGE) { + LOG_TRACE(ERROR, "ESM-MSG - Unexpected extened protocol discriminator: 0x%x", + header->ex_protocol_discriminator); + return (TLV_ENCODE_PROTOCOL_NOT_SUPPORTED); + } + + /* Encode the extendedprotocol discriminator */ + ENCODE_U8(buffer + size, header->ex_protocol_discriminator, size); + /* Encode the security header type */ + ENCODE_U8(buffer + size, (header->security_header_type & 0xf), size); + /* Encode the message type */ + ENCODE_U8(buffer + size, header->message_type, size); + return (size); +} + + +int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) { + LOG_FUNC_IN; + int header_result; + int encode_result; + uint8_t msg_type = mm_msg->header.message_type; + + + /* First encode the EMM message header */ + header_result = _nas_mm_msg_encode_header(&mm_msg->header, buffer, len); + + if (header_result < 0) { + LOG_TRACE(ERROR, "EMM-MSG - Failed to encode EMM message header " + "(%d)", header_result); + LOG_FUNC_RETURN(header_result); + } + + buffer += header_result; + len -= header_result; + + switch(msg_type) { + case REGISTRATION_REQUEST: + encode_result = encode_registration_request(&mm_msg->registration_request, buffer, len); + break; + case FGS_IDENTITY_RESPONSE: + encode_result = encode_identiy_response(&mm_msg->fgs_identity_response, buffer, len); + break; + case FGS_AUTHENTICATION_RESPONSE: + encode_result = encode_fgs_authentication_response(&mm_msg->fgs_auth_response, buffer, len); + break; + case FGS_SECURITY_MODE_COMPLETE: + encode_result = encode_fgs_security_mode_complete(&mm_msg->fgs_security_mode_complete, buffer, len); + break; + case FGS_UPLINK_NAS_TRANSPORT: + encode_result = encode_fgs_uplink_nas_transport(&mm_msg->uplink_nas_transport, buffer, len); + break; + default: + LOG_TRACE(ERROR, "EMM-MSG - Unexpected message type: 0x%x", + mm_msg->header.message_type); + encode_result = TLV_ENCODE_WRONG_MESSAGE_TYPE; + break; + /* TODO: Handle not standard layer 3 messages: SERVICE_REQUEST */ + } + + if (encode_result < 0) { + LOG_TRACE(ERROR, "EMM-MSG - Failed to encode L3 EMM message 0x%x " + "(%d)", mm_msg->header.message_type, encode_result); + } + + if (encode_result < 0) + LOG_FUNC_RETURN (encode_result); + + LOG_FUNC_RETURN (header_result + encode_result); +} + +void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, uicc_t* uicc) { + uint8_t S[100]={0}; + S[0] = 0x6B; + servingNetworkName (S+1, uicc->imsiStr, uicc->nmc_size); + int netNamesize = strlen((char*)S+1); + S[1 + netNamesize] = (netNamesize & 0xff00) >> 8; + S[2 + netNamesize] = (netNamesize & 0x00ff); + for (int i = 0; i < 16; i++) + S[3 + netNamesize + i] = rand[i]; + S[19 + netNamesize] = 0x00; + S[20 + netNamesize] = 0x10; + for (int i = 0; i < 8; i++) + S[21 + netNamesize + i] = input[i]; + S[29 + netNamesize] = 0x00; + S[30 + netNamesize] = 0x08; + + uint8_t plmn[3] = { 0x02, 0xf8, 0x39 }; + uint8_t oldS[100]; + oldS[0] = 0x6B; + memcpy(&oldS[1], plmn, 3); + oldS[4] = 0x00; + oldS[5] = 0x03; + for (int i = 0; i < 16; i++) + oldS[6 + i] = rand[i]; + oldS[22] = 0x00; + oldS[23] = 0x10; + for (int i = 0; i < 8; i++) + oldS[24 + i] = input[i]; + oldS[32] = 0x00; + oldS[33] = 0x08; + + + uint8_t key[32]; + memcpy(&key[0], ck, 16); + memcpy(&key[16], ik, 16); //KEY + uint8_t out[32]; + kdf(key, 32, S, 31 + netNamesize, out, 32); + for (int i = 0; i < 16; i++) + output[i] = out[16 + i]; +} + +void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], uicc_t *uicc) { + uint8_t S[100]={0}; + uint8_t key[32]; + + memcpy(&key[0], ck, 16); + memcpy(&key[16], ik, 16); //KEY + S[0] = 0x6A; + servingNetworkName (S+1, uicc->imsiStr, uicc->nmc_size); + int netNamesize = strlen((char*)S+1); + S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); + S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); + for (int i = 0; i < 6; i++) { + S[3 + netNamesize + i] = sqn[i]; + } + S[9 + netNamesize] = 0x00; + S[10 + netNamesize] = 0x06; + kdf(key, 32, S, 11 + netNamesize, kausf, 32); +} + +void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], uicc_t *uicc) { + uint8_t S[100]={0}; + S[0] = 0x6C; //FC + servingNetworkName (S+1, uicc->imsiStr, uicc->nmc_size); + int netNamesize = strlen((char*)S+1); + S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); + S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); + kdf(kausf, 32, S, 3 + netNamesize, kseaf, 32); +} + +void derive_kamf(uint8_t *kseaf, uint8_t *kamf, uint16_t abba, uicc_t* uicc) { + int imsiLen = strlen(uicc->imsiStr); + uint8_t S[100]; + S[0] = 0x6D; //FC = 0x6D + memcpy(&S[1], uicc->imsiStr, imsiLen ); + S[1 + imsiLen] = (uint8_t)((imsiLen & 0xff00) >> 8); + S[2 + imsiLen] = (uint8_t)(imsiLen & 0x00ff); + S[3 + imsiLen] = abba & 0x00ff; + S[4 + imsiLen] = (abba & 0xff00) >> 8; + S[5 + imsiLen] = 0x00; + S[6 + imsiLen] = 0x02; + kdf(kseaf, 32, S, 7 + imsiLen, kamf, 32); +} + +//------------------------------------------------------------------------------ +void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], uint8_t *knas_int) { + uint8_t S[20]; + uint8_t out[32] = { 0 }; + S[0] = 0x69; //FC + S[1] = (uint8_t)(nas_alg_type & 0xFF); + S[2] = 0x00; + S[3] = 0x01; + S[4] = nas_alg_id; + S[5] = 0x00; + S[6] = 0x01; + kdf(kamf, 32, S, 7, out, 32); + for (int i = 0; i < 16; i++) + knas_int[i] = out[16 + i]; +} + +void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb){ + /* Compute the KDF input parameter + * S = FC(0x6E) || UL NAS Count || 0x00 0x04 || 0x01 || 0x00 0x01 + */ + uint8_t input[32]; + // uint16_t length = 4; + // int offset = 0; + uint8_t out[32] = { 0 }; + + LOG_TRACE(INFO, "%s with count= %d", __FUNCTION__, count); + memset(input, 0, 32); + input[0] = 0x6E; + // P0 + input[1] = count >> 24; + input[2] = (uint8_t)(count >> 16); + input[3] = (uint8_t)(count >> 8); + input[4] = (uint8_t)count; + // L0 + input[5] = 0; + input[6] = 4; + // P1 + input[7] = 0x01; + // L1 + input[8] = 0; + input[9] = 1; + + kdf(kamf, 32, input, 10, out, 32); + for (int i = 0; i < 32; i++) + kgnb[i] = out[i]; + printf("kgnb : "); + for(int pp=0;pp<32;pp++) + printf("%02x ",kgnb[pp]); + printf("\n"); +} + +void derive_ue_keys(int Mod_id, uint8_t *buf, uicc_t *uicc) { + uint8_t ak[6]; + uint8_t sqn[6]; + + AssertFatal (Mod_id < NB_UE_INST, "Failed, Mod_id %d is over NB_UE_INST!\n", Mod_id); + if(ue_security_key[Mod_id]){ + // clear old key + memset(ue_security_key[Mod_id],0,sizeof(ue_sa_security_key_t)); + }else{ + // Allocate new memory + ue_security_key[Mod_id]=(ue_sa_security_key_t *)calloc(1,sizeof(ue_sa_security_key_t)); + } + uint8_t *kausf = ue_security_key[Mod_id]->kausf; + uint8_t *kseaf = ue_security_key[Mod_id]->kseaf; + uint8_t *kamf = ue_security_key[Mod_id]->kamf; + uint8_t *knas_int = ue_security_key[Mod_id]->knas_int; + uint8_t *output = ue_security_key[Mod_id]->res; + uint8_t *rand = ue_security_key[Mod_id]->rand; + uint8_t *kgnb = ue_security_key[Mod_id]->kgnb; + + // get RAND for authentication request + for(int index = 0; index < 16;index++){ + rand[index] = buf[8+index]; + } + + uint8_t resTemp[16]; + uint8_t ck[16], ik[16]; + f2345(uicc->key, rand, resTemp, ck, ik, ak, uicc->opc); + + transferRES(ck, ik, resTemp, rand, output, uicc); + + for(int index = 0; index < 6; index++){ + sqn[index] = buf[26+index]; + } + + derive_kausf(ck, ik, sqn, kausf, uicc); + derive_kseaf(kausf, kseaf, uicc); + derive_kamf(kseaf, kamf, 0x0000, uicc); + derive_knas(0x02, 2, kamf, knas_int); + derive_kgnb(kamf,0,kgnb); + + printf("kausf:"); + for(int i = 0; i < 32; i++){ + printf("%x ", kausf[i]); + } + printf("\n"); + + printf("kseaf:"); + for(int i = 0; i < 32; i++){ + printf("%x ", kseaf[i]); + } + + printf("\n"); + + printf("kamf:"); + for(int i = 0; i < 32; i++){ + printf("%x ", kamf[i]); + } + printf("\n"); + + printf("knas_int:\n"); + for(int i = 0; i < 16; i++){ + printf("%x ", knas_int[i]); + } + printf("\n"); +} + +void generateRegistrationRequest(as_nas_info_t *initialNasMsg, int Mod_id) { + int size = sizeof(mm_msg_header_t); + fgs_nas_message_t nas_msg={0}; + MM_msg *mm_msg; + uicc_t * uicc=checkUicc(Mod_id); + + mm_msg = &nas_msg.plain.mm_msg; + // set header + mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_msg->header.security_header_type = PLAIN_5GS_MSG; + mm_msg->header.message_type = REGISTRATION_REQUEST; + + + // set registration request + mm_msg->registration_request.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + size += 1; + mm_msg->registration_request.securityheadertype = PLAIN_5GS_MSG; + size += 1; + mm_msg->registration_request.messagetype = REGISTRATION_REQUEST; + size += 1; + mm_msg->registration_request.fgsregistrationtype = INITIAL_REGISTRATION; + mm_msg->registration_request.naskeysetidentifier.naskeysetidentifier = 1; + size += 1; + if(0){ + mm_msg->registration_request.fgsmobileidentity.guti.typeofidentity = FGS_MOBILE_IDENTITY_5G_GUTI; + mm_msg->registration_request.fgsmobileidentity.guti.amfregionid = 0xca; + mm_msg->registration_request.fgsmobileidentity.guti.amfpointer = 0; + mm_msg->registration_request.fgsmobileidentity.guti.amfsetid = 1016; + mm_msg->registration_request.fgsmobileidentity.guti.tmsi = 10; + mm_msg->registration_request.fgsmobileidentity.guti.mncdigit1 = + uicc->nmc_size==2 ? uicc->imsiStr[3]-'0' : uicc->imsiStr[4]-'0'; + mm_msg->registration_request.fgsmobileidentity.guti.mncdigit2 = + uicc->nmc_size==2 ? uicc->imsiStr[4]-'0' : uicc->imsiStr[5]-'0'; + mm_msg->registration_request.fgsmobileidentity.guti.mncdigit3 = + uicc->nmc_size==2 ? 0xf : uicc->imsiStr[3]-'0'; + mm_msg->registration_request.fgsmobileidentity.guti.mccdigit1 = uicc->imsiStr[0]-'0'; + mm_msg->registration_request.fgsmobileidentity.guti.mccdigit2 = uicc->imsiStr[1]-'0'; + mm_msg->registration_request.fgsmobileidentity.guti.mccdigit3 = uicc->imsiStr[2]-'0'; + + size += 13; + + } else { + mm_msg->registration_request.fgsmobileidentity.suci.typeofidentity = FGS_MOBILE_IDENTITY_SUCI; + mm_msg->registration_request.fgsmobileidentity.suci.mncdigit1 = + uicc->nmc_size==2 ? uicc->imsiStr[3]-'0' : uicc->imsiStr[4]-'0'; + mm_msg->registration_request.fgsmobileidentity.suci.mncdigit2 = + uicc->nmc_size==2 ? uicc->imsiStr[4]-'0' : uicc->imsiStr[5]-'0'; + mm_msg->registration_request.fgsmobileidentity.suci.mncdigit3 = + uicc->nmc_size==2 ? 0xf : uicc->imsiStr[3]-'0'; + mm_msg->registration_request.fgsmobileidentity.suci.mccdigit1 = uicc->imsiStr[0]-'0'; + mm_msg->registration_request.fgsmobileidentity.suci.mccdigit2 = uicc->imsiStr[1]-'0'; + mm_msg->registration_request.fgsmobileidentity.suci.mccdigit3 = uicc->imsiStr[2]-'0'; + memcpy(mm_msg->registration_request.fgsmobileidentity.suci.schemeoutput, uicc->imsiStr+3+uicc->nmc_size, strlen(uicc->imsiStr) - (3+uicc->nmc_size)); + size += sizeof(Suci5GSMobileIdentity_t); + } + + mm_msg->registration_request.presencemask |= REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT; + mm_msg->registration_request.fgmmcapability.iei = REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI; + mm_msg->registration_request.fgmmcapability.length = 1; + mm_msg->registration_request.fgmmcapability.value = 0x7; + size += 3; + + mm_msg->registration_request.presencemask |= REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT; + mm_msg->registration_request.nruesecuritycapability.iei = REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI; + mm_msg->registration_request.nruesecuritycapability.length = 8; + mm_msg->registration_request.nruesecuritycapability.fg_EA = 0x80; + mm_msg->registration_request.nruesecuritycapability.fg_IA = 0x20; + mm_msg->registration_request.nruesecuritycapability.EEA = 0; + mm_msg->registration_request.nruesecuritycapability.EIA = 0; + size += 10; + + // encode the message + initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); + registration_request_buf = initialNasMsg->data; + + initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size); + registration_request_len = initialNasMsg->length; + +} + +void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype, uicc_t* uicc) { + int size = sizeof(mm_msg_header_t); + fgs_nas_message_t nas_msg; + memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); + MM_msg *mm_msg; + + mm_msg = &nas_msg.plain.mm_msg; + // set header + mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_msg->header.security_header_type = PLAIN_5GS_MSG; + mm_msg->header.message_type = FGS_IDENTITY_RESPONSE; + + + // set identity response + mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + size += 1; + mm_msg->fgs_identity_response.securityheadertype = PLAIN_5GS_MSG; + size += 1; + mm_msg->fgs_identity_response.messagetype = FGS_IDENTITY_RESPONSE; + size += 1; + if(identitytype == FGS_MOBILE_IDENTITY_SUCI){ + mm_msg->fgs_identity_response.fgsmobileidentity.suci.typeofidentity = FGS_MOBILE_IDENTITY_SUCI; + mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit1 = + uicc->nmc_size==2 ? uicc->imsiStr[3]-'0' : uicc->imsiStr[4]-'0'; + mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit2 = + uicc->nmc_size==2 ? uicc->imsiStr[4]-'0' : uicc->imsiStr[5]-'0'; + mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit3 = + uicc->nmc_size==2? 0xF : uicc->imsiStr[3]-'0'; + mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit1 = uicc->imsiStr[0]-'0'; + mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit2 = uicc->imsiStr[1]-'0'; + mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit3 = uicc->imsiStr[2]-'0'; + memcpy(mm_msg->registration_request.fgsmobileidentity.suci.schemeoutput, uicc->imsiStr+3+uicc->nmc_size, strlen(uicc->imsiStr) - (3+uicc->nmc_size)); + size += sizeof(Suci5GSMobileIdentity_t); + } + + // encode the message + initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); + + initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size); + +} + +static void generateAuthenticationResp(int Mod_id,as_nas_info_t *initialNasMsg, uint8_t *buf, uicc_t *uicc){ + + derive_ue_keys(Mod_id,buf,uicc); + OctetString res; + res.length = 16; + res.value = calloc(1,16); + memcpy(res.value,ue_security_key[Mod_id]->res,16); + + int size = sizeof(mm_msg_header_t); + fgs_nas_message_t nas_msg; + memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); + MM_msg *mm_msg; + + mm_msg = &nas_msg.plain.mm_msg; + // set header + mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_msg->header.security_header_type = PLAIN_5GS_MSG; + mm_msg->header.message_type = FGS_AUTHENTICATION_RESPONSE; + + // set authentication response + mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + size += 1; + mm_msg->fgs_identity_response.securityheadertype = PLAIN_5GS_MSG; + size += 1; + mm_msg->fgs_identity_response.messagetype = FGS_AUTHENTICATION_RESPONSE; + size += 1; + + //set response parameter + mm_msg->fgs_auth_response.authenticationresponseparameter.res = res; + size += 18; + // encode the message + initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); + + initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size); +} + +int nas_itti_kgnb_refresh_req(const uint8_t kgnb[32], int instance) { + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_KENB_REFRESH_REQ); + memcpy(NAS_KENB_REFRESH_REQ(message_p).kenb, kgnb, sizeof(NAS_KENB_REFRESH_REQ(message_p).kenb)); + return itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); +} + +static void generateSecurityModeComplete(int Mod_id,as_nas_info_t *initialNasMsg) +{ + int size = sizeof(mm_msg_header_t); + fgs_nas_message_t nas_msg; + memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); + + MM_msg *mm_msg; + nas_stream_cipher_t stream_cipher; + uint8_t mac[4]; + // set security protected header + nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; + size += 7; + + mm_msg = &nas_msg.security_protected.plain.mm_msg; + + // set header + mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_msg->header.security_header_type = PLAIN_5GS_MSG; + mm_msg->header.message_type = FGS_SECURITY_MODE_COMPLETE; + + // set security mode complete + mm_msg->fgs_security_mode_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + size += 1; + mm_msg->fgs_security_mode_complete.securityheadertype = PLAIN_5GS_MSG; + size += 1; + mm_msg->fgs_security_mode_complete.messagetype = FGS_SECURITY_MODE_COMPLETE; + size += 1; + + mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.typeofidentity = FGS_MOBILE_IDENTITY_IMEISV; + mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digit1 = 1; + mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digitp1 = 1; + mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digitp = 1; + mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.oddeven = 0; + size += 5; + + mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.value = registration_request_buf; + mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.length = registration_request_len; + size += (registration_request_len + 2); + + // encode the message + initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); + + int security_header_len = nas_protected_security_header_encode((char*)(initialNasMsg->data),&(nas_msg.header), size); + + initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len); + + stream_cipher.key = ue_security_key[Mod_id]->knas_int; + stream_cipher.key_length = 16; + stream_cipher.count = 0; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); + /* length in bits */ + stream_cipher.blength = (initialNasMsg->length - 6) << 3; + + // only for Type of integrity protection algorithm: 128-5G-IA2 (2) + nas_stream_encrypt_eia2( + &stream_cipher, + mac); + + printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); + for(int i = 0; i < 4; i++){ + initialNasMsg->data[2+i] = mac[i]; + } +} + +static void generateRegistrationComplete(int Mod_id, as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) { + //wait send RRCReconfigurationComplete and InitialContextSetupResponse + sleep(1); + int length = 0; + int size = 0; + fgs_nas_message_t nas_msg; + nas_stream_cipher_t stream_cipher; + uint8_t mac[4]; + memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); + fgs_nas_message_security_protected_t *sp_msg; + + sp_msg = &nas_msg.security_protected; + // set header + sp_msg->header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp_msg->header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp_msg->header.message_authentication_code = 0; + sp_msg->header.sequence_number = 1; + length = 7; + sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + length += 1; + sp_msg->plain.mm_msg.registration_complete.securityheadertype = PLAIN_5GS_MSG; + sp_msg->plain.mm_msg.registration_complete.sparehalfoctet = 0; + length += 1; + sp_msg->plain.mm_msg.registration_complete.messagetype = REGISTRATION_COMPLETE; + length += 1; + + if(sortransparentcontainer) { + length += sortransparentcontainer->sortransparentcontainercontents.length; + } + + // encode the message + initialNasMsg->data = (Byte_t *)malloc(length * sizeof(Byte_t)); + + /* Encode the first octet of the header (extended protocol discriminator) */ + ENCODE_U8(initialNasMsg->data + size, sp_msg->header.protocol_discriminator, size); + + /* Encode the security header type */ + ENCODE_U8(initialNasMsg->data + size, sp_msg->header.security_header_type, size); + + /* Encode the message authentication code */ + ENCODE_U32(initialNasMsg->data + size, sp_msg->header.message_authentication_code, size); + + /* Encode the sequence number */ + ENCODE_U8(initialNasMsg->data + size, sp_msg->header.sequence_number, size); + + + /* Encode the extended protocol discriminator */ + ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator, size); + + /* Encode the security header type */ + ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.securityheadertype, size); + + /* Encode the message type */ + ENCODE_U8(initialNasMsg->data + size, sp_msg->plain.mm_msg.registration_complete.messagetype, size); + + if(sortransparentcontainer) { + encode_registration_complete(&sp_msg->plain.mm_msg.registration_complete, initialNasMsg->data + size, length - size); + } + + initialNasMsg->length = length; + stream_cipher.key = ue_security_key[Mod_id]->knas_int; + stream_cipher.key_length = 16; + stream_cipher.count = 1; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); + /* length in bits */ + stream_cipher.blength = (initialNasMsg->length - 6) << 3; + + // only for Type of integrity protection algorithm: 128-5G-IA2 (2) + nas_stream_encrypt_eia2( + &stream_cipher, + mac); + + printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); + for(int i = 0; i < 4; i++){ + initialNasMsg->data[2+i] = mac[i]; + } +} + +void decodeDownlinkNASTransport(as_nas_info_t *initialNasMsg, uint8_t * pdu_buffer){ + uint8_t msg_type = *(pdu_buffer + 16); + if(msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC){ + sprintf(baseNetAddress, "%d.%d", *(pdu_buffer + 39),*(pdu_buffer + 40)); + int third_octet = *(pdu_buffer + 41); + int fourth_octet = *(pdu_buffer + 42); + LOG_I(NAS, "Received PDU Session Establishment Accept\n"); + nas_config(1,third_octet,fourth_octet,"ue"); + } else { + LOG_E(NAS, "Received unexpected message in DLinformationTransfer %d\n", msg_type); + } +} + +static void generatePduSessionEstablishRequest(int Mod_id, uicc_t * uicc, as_nas_info_t *initialNasMsg){ + //wait send RegistrationComplete + usleep(100*150); + int size = 0; + fgs_nas_message_t nas_msg={0}; + + // setup pdu session establishment request + uint16_t req_length = 7; + uint8_t *req_buffer = malloc(req_length); + pdu_session_establishment_request_msg pdu_session_establish; + pdu_session_establish.protocoldiscriminator = FGS_SESSION_MANAGEMENT_MESSAGE; + pdu_session_establish.pdusessionid = 10; + pdu_session_establish.pti = 1; + pdu_session_establish.pdusessionestblishmsgtype = FGS_PDU_SESSION_ESTABLISHMENT_REQ; + pdu_session_establish.maxdatarate = 0xffff; + pdu_session_establish.pdusessiontype = 0x91; + encode_pdu_session_establishment_request(&pdu_session_establish, req_buffer); + + + + MM_msg *mm_msg; + nas_stream_cipher_t stream_cipher; + uint8_t mac[4]; + nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; + size += 7; + + mm_msg = &nas_msg.security_protected.plain.mm_msg; + + // set header + mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_msg->header.security_header_type = PLAIN_5GS_MSG; + mm_msg->header.message_type = FGS_UPLINK_NAS_TRANSPORT; + + // set uplink nas transport + mm_msg->uplink_nas_transport.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + size += 1; + mm_msg->uplink_nas_transport.securityheadertype = PLAIN_5GS_MSG; + size += 1; + mm_msg->uplink_nas_transport.messagetype = FGS_UPLINK_NAS_TRANSPORT; + size += 1; + + mm_msg->uplink_nas_transport.payloadcontainertype.iei = 0; + mm_msg->uplink_nas_transport.payloadcontainertype.type = 1; + size += 1; + mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.length = req_length; + mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.value = req_buffer; + size += (2+req_length); + mm_msg->uplink_nas_transport.pdusessionid = 10; + mm_msg->uplink_nas_transport.requesttype = 1; + size += 3; + mm_msg->uplink_nas_transport.snssai.length = 4; + //Fixme: it seems there are a lot of memory errors in this: this value was on the stack, + // but pushed in a itti message to another thread + // this kind of error seems in many places in 5G NAS + mm_msg->uplink_nas_transport.snssai.value=calloc(1,4); + mm_msg->uplink_nas_transport.snssai.value[0] = uicc->nssai_sst; + mm_msg->uplink_nas_transport.snssai.value[1] = (uicc->nssai_sd>>16)&0xFF; + mm_msg->uplink_nas_transport.snssai.value[2] = (uicc->nssai_sd>>8)&0xFF; + mm_msg->uplink_nas_transport.snssai.value[3] = (uicc->nssai_sd)&0xFF; + size += (1+1+4); + int dnnSize=strlen(uicc->dnnStr); + mm_msg->uplink_nas_transport.dnn.value=calloc(1,dnnSize+1); + mm_msg->uplink_nas_transport.dnn.length = dnnSize + 1; + mm_msg->uplink_nas_transport.dnn.value[0] = dnnSize + 1; + memcpy(mm_msg->uplink_nas_transport.dnn.value+1,uicc->dnnStr, dnnSize); + size += (1+1+dnnSize+1); + + // encode the message + initialNasMsg->data = (Byte_t *)malloc(size * sizeof(Byte_t)); + int security_header_len = nas_protected_security_header_encode((char*)(initialNasMsg->data),&(nas_msg.header), size); + + initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len); + + stream_cipher.key = ue_security_key[Mod_id]->knas_int; + stream_cipher.key_length = 16; + stream_cipher.count = 0; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); + /* length in bits */ + stream_cipher.blength = (initialNasMsg->length - 6) << 3; + + // only for Type of integrity protection algorithm: 128-5G-IA2 (2) + nas_stream_encrypt_eia2( + &stream_cipher, + mac); + + printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); + for(int i = 0; i < 4; i++){ + initialNasMsg->data[2+i] = mac[i]; + } +} + + +void *nas_nrue_task(void *args_p) +{ + MessageDef *msg_p; + instance_t instance; + unsigned int Mod_id; + int result; + uint8_t msg_type = 0; + uint8_t *pdu_buffer = NULL; + + + ue_security_key=(ue_sa_security_key_t **)calloc(1,sizeof(ue_sa_security_key_t*)*NB_UE_INST); + itti_mark_task_ready (TASK_NAS_NRUE); + MSC_START_USE(); + + while(1) { + // Wait for a message or an event + itti_receive_msg (TASK_NAS_NRUE, &msg_p); + + if (msg_p != NULL) { + instance = msg_p->ittiMsgHeader.originInstance; + Mod_id = instance ; + uicc_t *uicc=checkUicc(Mod_id); + + if (instance == INSTANCE_DEFAULT) { + printf("%s:%d: FATAL: instance is INSTANCE_DEFAULT, should not happen.\n", + __FILE__, __LINE__); + exit_fun("exit... \n"); + } + + switch (ITTI_MSG_ID(msg_p)) { + case INITIALIZE_MESSAGE: + LOG_I(NAS, "[UE %d] Received %s\n", Mod_id, ITTI_MSG_NAME (msg_p)); + + break; + + case TERMINATE_MESSAGE: + itti_exit_task (); + break; + + case MESSAGE_TEST: + LOG_I(NAS, "[UE %d] Received %s\n", Mod_id, ITTI_MSG_NAME (msg_p)); + break; + + case NAS_CELL_SELECTION_CNF: + LOG_I(NAS, "[UE %d] Received %s: errCode %u, cellID %u, tac %u\n", Mod_id, ITTI_MSG_NAME (msg_p), + NAS_CELL_SELECTION_CNF (msg_p).errCode, NAS_CELL_SELECTION_CNF (msg_p).cellID, NAS_CELL_SELECTION_CNF (msg_p).tac); + // as_stmsi_t s_tmsi={0, 0}; + // as_nas_info_t nas_info; + // plmn_t plmnID={0, 0, 0, 0}; + // generateRegistrationRequest(&nas_info); + // nr_nas_itti_nas_establish_req(0, AS_TYPE_ORIGINATING_SIGNAL, s_tmsi, plmnID, nas_info.data, nas_info.length, 0); + break; + + case NAS_CELL_SELECTION_IND: + LOG_I(NAS, "[UE %d] Received %s: cellID %u, tac %u\n", Mod_id, ITTI_MSG_NAME (msg_p), + NAS_CELL_SELECTION_IND (msg_p).cellID, NAS_CELL_SELECTION_IND (msg_p).tac); + + /* TODO not processed by NAS currently */ + break; + + case NAS_PAGING_IND: + LOG_I(NAS, "[UE %d] Received %s: cause %u\n", Mod_id, ITTI_MSG_NAME (msg_p), + NAS_PAGING_IND (msg_p).cause); + + /* TODO not processed by NAS currently */ + break; + + case NAS_CONN_ESTABLI_CNF: + { + LOG_I(NAS, "[UE %d] Received %s: errCode %u, length %u\n", Mod_id, ITTI_MSG_NAME (msg_p), + NAS_CONN_ESTABLI_CNF (msg_p).errCode, NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.length); + + pdu_buffer = NAS_CONN_ESTABLI_CNF (msg_p).nasMsg.data; + if((pdu_buffer + 1) != NULL){ + if (*(pdu_buffer + 1) > 0 ) { + if((pdu_buffer + 9) != NULL){ + msg_type = *(pdu_buffer + 9); + } else { + LOG_W(NAS, "[UE] Received invalid downlink message\n"); + break; + } + } else { + if((pdu_buffer + 2) != NULL){ + msg_type = *(pdu_buffer + 2); + } else { + LOG_W(NAS, "[UE] Received invalid downlink message\n"); + break; + } + } + } + if(msg_type == REGISTRATION_ACCEPT){ + LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n"); + + as_nas_info_t initialNasMsg; + memset(&initialNasMsg, 0, sizeof(as_nas_info_t)); + generateRegistrationComplete(Mod_id,&initialNasMsg, NULL); + if(initialNasMsg.length > 0){ + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); + NAS_UPLINK_DATA_REQ(message_p).UEid = Mod_id; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length; + itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); + LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); + } + + as_nas_info_t pduEstablishMsg; + memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t)); + generatePduSessionEstablishRequest(Mod_id, uicc, &pduEstablishMsg); + if(pduEstablishMsg.length > 0){ + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); + NAS_UPLINK_DATA_REQ(message_p).UEid = Mod_id; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)pduEstablishMsg.data; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = pduEstablishMsg.length; + itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); + LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); + } + } + else if((pdu_buffer + 16) != NULL){ + msg_type = *(pdu_buffer + 16); + if(msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC){ + if(baseNetAddress==NULL) { + baseNetAddress = calloc(1,8); + } + sprintf(baseNetAddress, "%d.%d", *(pdu_buffer + 39),*(pdu_buffer + 40)); + int third_octet = *(pdu_buffer + 41); + int fourth_octet = *(pdu_buffer + 42); + LOG_I(NAS, "Received PDU Session Establishment Accept\n"); + nas_config(1,third_octet,fourth_octet,"ue"); + } + } + + break; + } + + case NAS_CONN_RELEASE_IND: + LOG_I(NAS, "[UE %d] Received %s: cause %u\n", Mod_id, ITTI_MSG_NAME (msg_p), + NAS_CONN_RELEASE_IND (msg_p).cause); + + break; + + case NAS_UPLINK_DATA_CNF: + LOG_I(NAS, "[UE %d] Received %s: UEid %u, errCode %u\n", Mod_id, ITTI_MSG_NAME (msg_p), + NAS_UPLINK_DATA_CNF (msg_p).UEid, NAS_UPLINK_DATA_CNF (msg_p).errCode); + + break; + + case NAS_DOWNLINK_DATA_IND: + { + LOG_I(NAS, "[UE %d] Received %s: UEid %u, length %u , buffer %p\n", Mod_id, + ITTI_MSG_NAME (msg_p), + Mod_id, + NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length, + NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data); + as_nas_info_t initialNasMsg={0}; + + pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data; + if((pdu_buffer + 1) != NULL){ + if (*(pdu_buffer + 1) > 0 ) { + msg_type = *(pdu_buffer + 9); + } else { + msg_type = *(pdu_buffer + 2); + } + } + if((pdu_buffer + 2) == NULL){ + LOG_W(NAS, "[UE] Received invalid downlink message\n"); + return 0; + } + + switch(msg_type){ + case FGS_IDENTITY_REQUEST: + generateIdentityResponse(&initialNasMsg,*(pdu_buffer+3), uicc); + break; + case FGS_AUTHENTICATION_REQUEST: + generateAuthenticationResp(Mod_id,&initialNasMsg, pdu_buffer, uicc); + break; + case FGS_SECURITY_MODE_COMMAND: + nas_itti_kgnb_refresh_req(ue_security_key[Mod_id]->kgnb, instance); + generateSecurityModeComplete(Mod_id,&initialNasMsg); + break; + case FGS_DOWNLINK_NAS_TRANSPORT: + decodeDownlinkNASTransport(&initialNasMsg, pdu_buffer); + break; + + default: + LOG_W(NR_RRC,"unknow message type %d\n",msg_type); + break; + } + + if(initialNasMsg.length > 0){ + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); + NAS_UPLINK_DATA_REQ(message_p).UEid = Mod_id; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length; + itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); + LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message\n"); + } + + break; + } + + default: + LOG_E(NAS, "[UE %d] Received unexpected message %s\n", Mod_id, ITTI_MSG_NAME (msg_p)); + break; + } + + result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + msg_p = NULL; + } + } + + return NULL; +} diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.h b/openair3/NAS/NR_UE/nr_nas_msg_sim.h new file mode 100644 index 0000000000..1b59366037 --- /dev/null +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.h @@ -0,0 +1,135 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file nr_nas_msg_sim.h + * \brief simulator for nr nas message + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + + + +#ifndef __NR_NAS_MSG_SIM_H__ +#define __NR_NAS_MSG_SIM_H__ + +#include "RegistrationRequest.h" +#include "FGSIdentityResponse.h" +#include "FGSAuthenticationResponse.h" +#include "FGSNASSecurityModeComplete.h" +#include "RegistrationComplete.h" +#include "as_message.h" +#include "FGSUplinkNasTransport.h" + +#define PLAIN_5GS_MSG 0b0000 +#define INTEGRITY_PROTECTED 0b0001 +#define INTEGRITY_PROTECTED_AND_CIPHERED 0b0010 +#define INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX 0b0011 // only for SECURITY MODE COMMAND +#define INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX 0b0100 // only for SECURITY MODE COMPLETE + +#define REGISTRATION_REQUEST 0b01000001 /* 65 = 0x41 */ +#define REGISTRATION_ACCEPT 0b01000010 /* 66 = 0x42 */ +#define REGISTRATION_COMPLETE 0b01000011 /* 67 = 0x43 */ +#define FGS_AUTHENTICATION_REQUEST 0b01010110 /* 86 = 0x56 */ +#define FGS_AUTHENTICATION_RESPONSE 0b01010111 /* 87 = 0x57 */ +#define FGS_IDENTITY_REQUEST 0b01011011 /* 91 = 0x5b */ +#define FGS_IDENTITY_RESPONSE 0b01011100 /* 92 = 0x5c */ +#define FGS_SECURITY_MODE_COMMAND 0b01011101 /* 93 = 0x5d */ +#define FGS_SECURITY_MODE_COMPLETE 0b01011110 /* 94 = 0x5e */ +#define FGS_UPLINK_NAS_TRANSPORT 0b01100111 /* 103= 0x67 */ +#define FGS_DOWNLINK_NAS_TRANSPORT 0b01101000 /* 104= 0x68 */ + +// message type for 5GS session management +#define FGS_PDU_SESSION_ESTABLISHMENT_REQ 0b11000001 /* 193= 0xc1 */ +#define FGS_PDU_SESSION_ESTABLISHMENT_ACC 0b11000010 /* 194= 0xc2 */ + +#define INITIAL_REGISTRATION 0b001 + +/* Security Key for SA UE */ +typedef struct { + uint8_t kausf[32]; + uint8_t kseaf[32]; + uint8_t kamf[32]; + uint8_t knas_int[16]; + uint8_t res[16]; + uint8_t rand[16]; + uint8_t kgnb[32]; +} ue_sa_security_key_t; + +typedef enum fgs_protocol_discriminator_e { + /* Protocol discriminator identifier for 5GS Mobility Management */ + FGS_MOBILITY_MANAGEMENT_MESSAGE = 0x7E, + + /* Protocol discriminator identifier for 5GS Session Management */ + FGS_SESSION_MANAGEMENT_MESSAGE = 0x2E, +} fgs_protocol_discriminator_t; + + +typedef struct { + uint8_t ex_protocol_discriminator; + uint8_t security_header_type; + uint8_t message_type; +} mm_msg_header_t; + +/* Structure of security protected header */ +typedef struct { + fgs_protocol_discriminator_t protocol_discriminator; + uint8_t security_header_type; + uint32_t message_authentication_code; + uint8_t sequence_number; +} fgs_nas_message_security_header_t; + +typedef union { + mm_msg_header_t header; + registration_request_msg registration_request; + fgs_identiy_response_msg fgs_identity_response; + fgs_authentication_response_msg fgs_auth_response; + fgs_security_mode_complete_msg fgs_security_mode_complete; + registration_complete_msg registration_complete; + fgs_uplink_nas_transport_msg uplink_nas_transport; +} MM_msg; + + + +typedef struct { + MM_msg mm_msg; /* 5GS Mobility Management messages */ +} fgs_nas_message_plain_t; + +typedef struct { + fgs_nas_message_security_header_t header; + fgs_nas_message_plain_t plain; +} fgs_nas_message_security_protected_t; + + +typedef union { + fgs_nas_message_security_header_t header; + fgs_nas_message_security_protected_t security_protected; + fgs_nas_message_plain_t plain; +} fgs_nas_message_t; + +void generateRegistrationRequest(as_nas_info_t *initialNasMsg, int Mod_id); +void *nas_nrue_task(void *args_p); + +#endif /* __NR_NAS_MSG_SIM_H__*/ + + + diff --git a/openair3/NAS/NR_UE/ue_process_nas.c b/openair3/NAS/NR_UE/ue_process_nas.c new file mode 100644 index 0000000000..a89a07218e --- /dev/null +++ b/openair3/NAS/NR_UE/ue_process_nas.c @@ -0,0 +1,178 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include +#include + + +void SGSabortNet(void *msg, nr_user_nas_t *UE) { +} + +void ue_nas_schedule(void) { +} + +/* + *Message reception + */ + +void SGSauthenticationReq(void *msg, nr_user_nas_t *UE) { + authenticationrequestHeader_t *amsg=(authenticationrequestHeader_t *) msg; + arrayCpy(UE->uicc->rand,amsg->RAND); + arrayCpy(UE->uicc->autn,amsg->AUTN); + // AUTHENTICATION REQUEST message that contains a valid ngKSI, SQN and MAC is received + // TBD verify ngKSI (we set it as '2', see gNB code) + // SQN and MAC are tested in auth resp processing + ue_nas_schedule(); +} + +void SGSidentityReq(void *msg, nr_user_nas_t *UE) { + Identityrequest_t *idmsg=(Identityrequest_t *) msg; + + if (idmsg->it == SUCI ) { + LOG_I(NAS,"Received Identity request, scheduling answer\n"); + ue_nas_schedule(); + } else + LOG_E(NAS,"Not developped: identity request for %d\n", idmsg->it); +} + +void SGSsecurityModeCommand(void *msg, nr_user_nas_t *UE) { +} + + +void UEprocessNAS(void *msg,nr_user_nas_t *UE) { + SGScommonHeader_t *header=(SGScommonHeader_t *) msg; + + if ( header->sh > 4 ) + SGSabortNet(msg, UE); + else { + switch (header->epd) { + case SGSmobilitymanagementmessages: + LOG_I(NAS,"Received message: %s\n", idStr(message_text_info, header->mt)); + + switch (header->mt) { + case Authenticationrequest: + SGSauthenticationReq(msg, UE); + break; + + case Identityrequest: + SGSidentityReq(msg, UE); + break; + + case Securitymodecommand: + SGSsecurityModeCommand(msg, UE); + break; + + default: + SGSabortNet(msg, UE); + } + + break; + + case SGSsessionmanagementmessages: + SGSabortNet(msg, UE); + break; + + default: + SGSabortNet(msg, UE); + } + } +} + +/* + * Messages emission + */ + +int identityResponse(void **msg, nr_user_nas_t *UE) { + if (UE->uicc == NULL) + // config file section hardcoded as "uicc", nevertheless it opens to manage several UEs or a multi SIM UE + UE->uicc=init_uicc("uicc"); + + // TS 24.501 9.11.3.4 + int imsiL=strlen(UE->uicc->imsiStr); + int msinL=imsiL-3-UE->uicc->nmc_size; + int respSize=sizeof(IdentityresponseIMSI_t) + (msinL+1)/2; + IdentityresponseIMSI_t *resp=(IdentityresponseIMSI_t *) calloc(respSize,1); + resp->common.epd=SGSmobilitymanagementmessages; + resp->common.sh=0; + resp->common.mt=Identityresponse; + resp->common.len=htons(respSize-sizeof(Identityresponse_t)); + resp->mi=SUCI; + resp->mcc1=UE->uicc->imsiStr[0]-'0'; + resp->mcc2=UE->uicc->imsiStr[1]-'0'; + resp->mcc3=UE->uicc->imsiStr[2]-'0'; + resp->mnc1=UE->uicc->imsiStr[3]-'0'; + resp->mnc2=UE->uicc->imsiStr[4]-'0'; + resp->mnc3=UE->uicc->nmc_size==2? 0xF : UE->uicc->imsiStr[3]-'0'; + // TBD: routing to fill (FF ?) + char *out=(char *)(resp+1); + char *ptr=UE->uicc->imsiStr + 3 + UE->uicc->nmc_size; + + while ( ptr < UE->uicc->imsiStr+strlen(UE->uicc->imsiStr) ) { + *out=((*(ptr+1)-'0')<<4) | (*(ptr) -'0'); + out++; + ptr+=2; + } + + if (msinL%2 == 1) + *out=((*(ptr-1)-'0')) | 0xF0; + + *msg=resp; + return respSize; +} + +int authenticationResponse(void **msg,nr_user_nas_t *UE) { + if (UE->uicc == NULL) + // config file section hardcoded as "uicc", nevertheless it opens to manage several UEs or a multi SIM UE + UE->uicc=init_uicc("uicc"); + + myCalloc(resp, authenticationresponse_t); + resp->epd=SGSmobilitymanagementmessages; + resp->sh=0; + resp->mt=Authenticationresponse; + resp->iei=IEI_AuthenticationResponse; + resp->RESlen=sizeof(resp->RES); // always 16 see TS 24.501 Table 8.2.2.1.1 + // Verify the AUTN + // a full implementation need to test several SQN + // as the last 5bits can be any value + // and the value can also be greater and accepted (if it is in the accepted window) + uint8_t AUTN[16]; + uicc_milenage_generate(AUTN, UE->uicc); + + if ( memcmp(UE->uicc->autn, AUTN, sizeof(AUTN)) == 0 ) { + // prepare and send good answer + resToresStar(resp->RES,UE->uicc); + } else { + // prepare and send autn is not compatible with our data + abort(); + } + + *msg=resp; + return sizeof(authenticationresponse_t); +} + +int securityModeComplete(void **msg, nr_user_nas_t *UE) { + return -1; +} + +int registrationComplete(void **msg, nr_user_nas_t *UE) { + return -1; +} diff --git a/openair3/NAS/TOOLS/ue_sim_ci.conf b/openair3/NAS/TOOLS/ue_sim_ci.conf new file mode 100644 index 0000000000..5d95c9ba3f --- /dev/null +++ b/openair3/NAS/TOOLS/ue_sim_ci.conf @@ -0,0 +1,45 @@ +# List of known PLMNS +PLMN: { + PLMN0: { + FULLNAME="OpenAirInterface"; + SHORTNAME="OAICN"; + MNC="96"; + MCC="208"; + }; +}; + +UE0: +{ + USER: { + IMEI="356113022094149"; + MANUFACTURER="OAI"; + MODEL="LTE SoftModem"; + PIN="0000"; + }; + + SIM: { + MSIN="0100001111"; + USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; + OPC="e734f8734007d6c5ce7a0508809e7e9c"; + MSISDN="33611123456"; + }; + + # Home PLMN Selector with Access Technology + HPLMN= "20896"; + + # User controlled PLMN Selector with Access Technology + UCPLMN_LIST = (); + + # Operator PLMN List + OPLMN_LIST = ("20896"); + + # Operator controlled PLMN Selector with Access Technology + OCPLMN_LIST = (); + + # Forbidden plmns + FPLMN_LIST = (); + + # Equivalent home plmns + EHPLMN_LIST = (); + +}; diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.c b/openair3/NAS/UE/EMM/SAP/emm_as.c index 99a3763dea..6b226be380 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_as.c +++ b/openair3/NAS/UE/EMM/SAP/emm_as.c @@ -136,17 +136,25 @@ static int _emm_as_encrypt( static int _emm_as_send(const nas_user_t *user, const emm_as_t *msg); -static int _emm_as_security_res(const emm_data_t *emm_data, const emm_as_security_t *, - ul_info_transfer_req_t *); -static int _emm_as_establish_req(const emm_data_t *emm_data, const emm_as_establish_t *, - nas_establish_req_t *); + + static int _emm_as_cell_info_req(const emm_as_cell_info_t *, cell_info_req_t *); - -static int _emm_as_data_req(const emm_data_t *emm_data, const emm_as_data_t *msg, ul_info_transfer_req_t *); -static int _emm_as_status_ind(const emm_data_t *emm_data, const emm_as_status_t *, ul_info_transfer_req_t *); -static int _emm_as_release_req(const emm_as_release_t *, nas_release_req_t *); +/* prototyping of the following function modified: the last parameter turned to a void pointer + * instead of a ponter to the union field of the as_msg packed structure. This is to avoid new warnings introduced + * from gcc V9 which warns when accessing fields in a packed structure which may result in an alignment problem + * at run time. Modifications allow gcc to know at compile time that it cannot assume any alignment for those pointers. + * On X86 this is not fatal, as at run time the problem can be fixed (but it's better for perf to avoid). On other + * processor as Arm i think it can end in seg fault + */ +static int _emm_as_security_res(const emm_data_t *emm_data, const emm_as_security_t *, + void *ul_info_transfer_req_unaligned); +static int _emm_as_establish_req(const emm_data_t *emm_data, const emm_as_establish_t *, + void *nas_establish_req_unaligned); +static int _emm_as_data_req(const emm_data_t *emm_data, const emm_as_data_t *msg, void *ul_info_transfer_req_unaligned); +static int _emm_as_status_ind(const emm_data_t *emm_data, const emm_as_status_t *, void *ul_info_transfer_req_unaligned); +static int _emm_as_release_req(const emm_as_release_t *, void *nas_release_req_unaligned); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -443,14 +451,14 @@ static int _emm_as_data_ind(nas_user_t *user, const emm_as_data_t *msg, int *emm EPS_MOBILITY_MANAGEMENT_MESSAGE) { /* Process EMM data */ rc = _emm_as_recv(user, plain_msg, bytes, emm_cause); + free(plain_msg); } else if (header.protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) { const OctetString data = {bytes, (uint8_t *)plain_msg}; /* Foward ESM data to EPS session management */ rc = lowerlayer_data_ind(user, &data); + free(plain_msg); } - - free(plain_msg); } } else { /* Process successfull lower layer transfer indication */ @@ -938,32 +946,32 @@ static int _emm_as_send(const nas_user_t *user, const emm_as_t *msg) case _EMMAS_DATA_REQ: as_msg.msgID = _emm_as_data_req(user->emm_data, &msg->u.data, - &as_msg.msg.ul_info_transfer_req); + (void *)(&as_msg.msg.ul_info_transfer_req)); break; case _EMMAS_STATUS_IND: as_msg.msgID = _emm_as_status_ind(user->emm_data, &msg->u.status, - &as_msg.msg.ul_info_transfer_req); + (void *)(&as_msg.msg.ul_info_transfer_req)); break; case _EMMAS_RELEASE_REQ: as_msg.msgID = _emm_as_release_req( &msg->u.release, - &as_msg.msg.nas_release_req); + (void *)(&as_msg.msg.nas_release_req)); break; case _EMMAS_SECURITY_RES: as_msg.msgID = _emm_as_security_res(user->emm_data, &msg->u.security, - &as_msg.msg.ul_info_transfer_req); + (void *)(&as_msg.msg.ul_info_transfer_req)); break; case _EMMAS_ESTABLISH_REQ: as_msg.msgID = _emm_as_establish_req(user->emm_data, &msg->u.establish, - &as_msg.msg.nas_establish_req); + (void *)(&as_msg.msg.nas_establish_req)); break; @@ -1069,10 +1077,10 @@ static int _emm_as_send(const nas_user_t *user, const emm_as_t *msg) ** ** ***************************************************************************/ static int _emm_as_data_req(const emm_data_t *emm_data, const emm_as_data_t *msg, - ul_info_transfer_req_t *as_msg) + void *ul_info_transfer_req_unaligned) { LOG_FUNC_IN; - + ul_info_transfer_req_t *as_msg = (ul_info_transfer_req_t *)ul_info_transfer_req_unaligned; int size = 0; int is_encoded = FALSE; @@ -1165,12 +1173,12 @@ static int _emm_as_data_req(const emm_data_t *emm_data, const emm_as_data_t *msg ** ** ***************************************************************************/ static int _emm_as_status_ind(const emm_data_t *emm_data, const emm_as_status_t *msg, - ul_info_transfer_req_t *as_msg) + void *ul_info_transfer_req_unaligned) { LOG_FUNC_IN; int size = 0; - + ul_info_transfer_req_t *as_msg = (ul_info_transfer_req_t *)ul_info_transfer_req_unaligned; LOG_TRACE(INFO, "EMMAS-SAP - Send AS status indication (cause=%d)", msg->emm_cause); @@ -1239,12 +1247,12 @@ static int _emm_as_status_ind(const emm_data_t *emm_data, const emm_as_status_t ** ** ***************************************************************************/ static int _emm_as_release_req(const emm_as_release_t *msg, - nas_release_req_t *as_msg) + void *nas_release_req_unaligned) { LOG_FUNC_IN; LOG_TRACE(INFO, "EMMAS-SAP - Send AS release request"); - + nas_release_req_t *as_msg = (nas_release_req_t *)nas_release_req_unaligned; /* Setup the AS message */ if (msg->guti) { as_msg->s_tmsi.MMEcode = msg->guti->gummei.MMEcode; @@ -1279,10 +1287,10 @@ static int _emm_as_release_req(const emm_as_release_t *msg, ** ** ***************************************************************************/ static int _emm_as_security_res(const emm_data_t *emm_data, const emm_as_security_t *msg, - ul_info_transfer_req_t *as_msg) + void *ul_info_transfer_req_unaligned) { LOG_FUNC_IN; - + ul_info_transfer_req_t *as_msg=(ul_info_transfer_req_t *)ul_info_transfer_req_unaligned; int size = 0; LOG_TRACE(INFO, "EMMAS-SAP - Send AS security response"); @@ -1373,12 +1381,12 @@ static int _emm_as_security_res(const emm_data_t *emm_data, const emm_as_securit ** ** ***************************************************************************/ static int _emm_as_establish_req(const emm_data_t *emm_data, const emm_as_establish_t *msg, - nas_establish_req_t *as_msg) + void *nas_establish_req_unaligned) { LOG_FUNC_IN; int size = 0; - + nas_establish_req_t *as_msg = (nas_establish_req_t *)nas_establish_req_unaligned; LOG_TRACE(INFO, "EMMAS-SAP - Send AS connection establish request"); nas_message_t nas_msg; diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c index 67bfaf784e..b27270fadc 100644 --- a/openair3/NAS/UE/EMM/SecurityModeControl.c +++ b/openair3/NAS/UE/EMM/SecurityModeControl.c @@ -296,16 +296,16 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, else { /* Setup EMM cause code */ emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED; - - /* Release security mode control internal data */ - if (security_data->kenb.value) { - free(security_data->kenb.value); - security_data->kenb.value = NULL; - security_data->kenb.length = 0; - } } } + /* Release security mode control internal data */ + if (security_data->kenb.value) { + free(security_data->kenb.value); + security_data->kenb.value = NULL; + security_data->kenb.length = 0; + } + /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); diff --git a/openair3/NAS/UE/ESM/esm_ebr_context.c b/openair3/NAS/UE/ESM/esm_ebr_context.c index cd493dd09e..0c79fa3e3a 100644 --- a/openair3/NAS/UE/ESM/esm_ebr_context.c +++ b/openair3/NAS/UE/ESM/esm_ebr_context.c @@ -55,10 +55,6 @@ Description Defines functions used to handle EPS bearer contexts. #include #include #include -#ifdef UESIM_EXPANSION - #include "openairinterface5g_limits.h" - extern uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX]; -#endif /****************************************************************************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/ @@ -200,7 +196,7 @@ int esm_ebr_context_create( char *tmp = NULL; char ipv4_addr[INET_ADDRSTRLEN]; //char ipv6_addr[INET6_ADDRSTRLEN]; - char *netmask = NULL; + int netmask = 32; char broadcast[INET_ADDRSTRLEN]; struct in_addr in_addr; char command_line[500]; @@ -227,7 +223,7 @@ int esm_ebr_context_create( strcpy(ipv4_addr, tmp); if (IN_CLASSA(ntohl(in_addr.s_addr))) { - netmask = "255.0.0.0"; + netmask = 8; in_addr.s_addr = pdn->ip_addr[0] << 24 | ((255 << 16) & 0x00FF0000) | ((255 << 8) & 0x0000FF00) | @@ -239,7 +235,7 @@ int esm_ebr_context_create( // in_addr.s_addr); strcpy(broadcast, tmp); } else if (IN_CLASSB(ntohl(in_addr.s_addr))) { - netmask = "255.255.0.0"; + netmask = 16; in_addr.s_addr = pdn->ip_addr[0] << 24 | ((pdn->ip_addr[1] << 16) & 0x00FF0000) | ((255 << 8) & 0x0000FF00) | @@ -251,7 +247,7 @@ int esm_ebr_context_create( // in_addr.s_addr); strcpy(broadcast, tmp); } else if (IN_CLASSC(ntohl(in_addr.s_addr))) { - netmask = "255.255.255.0"; + netmask = 24; in_addr.s_addr = pdn->ip_addr[0] << 24 | ((pdn->ip_addr[1] << 16) & 0x00FF0000) | ((pdn->ip_addr[2] << 8) & 0x0000FF00) | @@ -263,56 +259,23 @@ int esm_ebr_context_create( // in_addr.s_addr); strcpy(broadcast, tmp); } else { - netmask = "255.255.255.255"; + netmask = 32; strcpy(broadcast, ipv4_addr); } - if(NFAPI_MODE==NFAPI_UE_STUB_PNF) { - // this is for L2 FAPI simulator. - // change for multiple UE's like 256UEs. - // if it's made too many tables , OS may crush so we use one table. - if(PDCP_USE_NETLINK) { -#ifdef UESIM_EXPANSION - uint16_t inst_nic = (pdn->ip_addr[3] & 0x000000FF) - 2; - res = sprintf(command_line, - "ifconfig %s%d %s netmask %s broadcast %s up && " - "ip rule add from %s/24 table %d && " - "ip rule add to %s/24 table %d && " - "ip route add default dev %s%d table %d", - UE_NAS_USE_TUN?"oaitun_ue":"oip", - inst_nic + 1, ipv4_addr, netmask, broadcast, - ipv4_addr, 201, - ipv4_addr, 201, - UE_NAS_USE_TUN?"oaitun_ue":"oip", - inst_nic + 1, 201); - inst_pdcp_list[inst_nic] = ueid; -#else - res = sprintf(command_line, - "ifconfig %s%d %s netmask %s broadcast %s up && " - "ip rule add from %s/32 table %d && " - "ip rule add to %s/32 table %d && " - "ip route add default dev %s%d table %d", - UE_NAS_USE_TUN?"oaitun_ue":"oip", - ueid + 1, ipv4_addr, netmask, broadcast, - ipv4_addr, ueid + 201, - ipv4_addr, ueid + 201, - UE_NAS_USE_TUN?"oaitun_ue":"oip", - ueid + 1, ueid + 201); -#endif - } // PDCP_USE_NETLINK - } else { - res = sprintf(command_line, - "ifconfig %s%d %s netmask %s broadcast %s up && " - "ip rule add from %s/32 table %d && " - "ip rule add to %s/32 table %d && " - "ip route add default dev %s%d table %d", - UE_NAS_USE_TUN?"oaitun_ue":"oip", - ueid + 1, ipv4_addr, netmask, broadcast, - ipv4_addr, ueid + 201, - ipv4_addr, ueid + 201, - UE_NAS_USE_TUN?"oaitun_ue":"oip", - ueid + 1, ueid + 201); - } + res = sprintf(command_line, + "ip address add %s/%d broadcast %s dev %s%d && " + "ip link set %s%d up && " + "ip rule add from %s/32 table %d && " + "ip rule add to %s/32 table %d && " + "ip route add default dev %s%d table %d", + ipv4_addr, netmask, broadcast, + UE_NAS_USE_TUN ? "oaitun_ue" : "oip", ueid + 1, + UE_NAS_USE_TUN ? "oaitun_ue" : "oip", ueid + 1, + ipv4_addr, ueid + 10000, + ipv4_addr, ueid + 10000, + UE_NAS_USE_TUN ? "oaitun_ue" : "oip", + ueid + 1, ueid + 10000); if ( res<0 ) { LOG_TRACE(WARNING, "ESM-PROC - Failed to system command string"); diff --git a/openair3/NAS/UE/nas_itti_messaging.c b/openair3/NAS/UE/nas_itti_messaging.c index 885ebbdd81..8016e0d791 100644 --- a/openair3/NAS/UE/nas_itti_messaging.c +++ b/openair3/NAS/UE/nas_itti_messaging.c @@ -102,7 +102,7 @@ extern unsigned char NB_eNB_INST; int nas_itti_kenb_refresh_req(const Byte_t kenb[32], int user_id) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_UE, NAS_KENB_REFRESH_REQ); + message_p = itti_alloc_new_message(TASK_NAS_UE, 0, NAS_KENB_REFRESH_REQ); memcpy(NAS_KENB_REFRESH_REQ(message_p).kenb, kenb, sizeof(NAS_KENB_REFRESH_REQ(message_p).kenb)); MSC_LOG_TX_MESSAGE( MSC_NAS_UE, @@ -130,7 +130,7 @@ int nas_itti_kenb_refresh_req(const Byte_t kenb[32], int user_id) { int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat, int user_id) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_UE, NAS_CELL_SELECTION_REQ); + message_p = itti_alloc_new_message(TASK_NAS_UE, 0, NAS_CELL_SELECTION_REQ); NAS_CELL_SELECTION_REQ(message_p).plmnID = plmnID; NAS_CELL_SELECTION_REQ(message_p).rat = rat; MSC_LOG_TX_MESSAGE( @@ -145,7 +145,7 @@ int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat, int user_id) { int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data, uint32_t length, int user_id) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_UE, NAS_CONN_ESTABLI_REQ); + message_p = itti_alloc_new_message(TASK_NAS_UE, 0, NAS_CONN_ESTABLI_REQ); NAS_CONN_ESTABLI_REQ(message_p).cause = cause; NAS_CONN_ESTABLI_REQ(message_p).type = type; NAS_CONN_ESTABLI_REQ(message_p).s_tmsi = s_tmsi; @@ -165,7 +165,7 @@ int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t int nas_itti_ul_data_req(const uint32_t ue_id, void *const data, const uint32_t length, int user_id) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_UE, NAS_UPLINK_DATA_REQ); + message_p = itti_alloc_new_message(TASK_NAS_UE, 0, NAS_UPLINK_DATA_REQ); NAS_UPLINK_DATA_REQ(message_p).UEid = ue_id; NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = data; NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = length; @@ -174,7 +174,7 @@ int nas_itti_ul_data_req(const uint32_t ue_id, void *const data, const uint32_t int nas_itti_rab_establish_rsp(const as_stmsi_t s_tmsi, const as_rab_id_t rabID, const nas_error_code_t errCode, int user_id) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_UE, NAS_RAB_ESTABLI_RSP); + message_p = itti_alloc_new_message(TASK_NAS_UE, 0, NAS_RAB_ESTABLI_RSP); NAS_RAB_ESTABLI_RSP(message_p).s_tmsi = s_tmsi; NAS_RAB_ESTABLI_RSP(message_p).rabID = rabID; NAS_RAB_ESTABLI_RSP(message_p).errCode = errCode; diff --git a/openair3/NAS/UE/nas_network.c b/openair3/NAS/UE/nas_network.c index f8abba4900..f6b291bb7b 100644 --- a/openair3/NAS/UE/nas_network.c +++ b/openair3/NAS/UE/nas_network.c @@ -141,11 +141,11 @@ int nas_network_process_data(nas_user_t *user, int msg_id, const void *data) case AS_CELL_INFO_CNF: { /* Received cell information confirm */ - const cell_info_cnf_t *info = &msg->msg.cell_info_cnf; - int cell_found = (info->errCode == AS_SUCCESS); - rc = nas_proc_cell_info(user, cell_found, info->tac, - info->cellID, info->rat, - info->rsrp, info->rsrq); + /* remove using pointers to fiels of the packed structure msg as it + * triggers warnings with gcc version 9 */ + const cell_info_cnf_t info = msg->msg.cell_info_cnf; + int cell_found = (info.errCode == AS_SUCCESS); + rc = nas_proc_cell_info(user, cell_found, info.tac, info.cellID, info.rat, info.rsrp, info.rsrq); break; } @@ -157,12 +157,12 @@ int nas_network_process_data(nas_user_t *user, int msg_id, const void *data) case AS_NAS_ESTABLISH_CNF: { /* Received NAS signalling connection establishment confirm */ - const nas_establish_cnf_t *confirm = &msg->msg.nas_establish_cnf; + const nas_establish_cnf_t confirm = msg->msg.nas_establish_cnf; - if ( (confirm->errCode == AS_SUCCESS) || - (confirm->errCode == AS_TERMINATED_NAS) ) { - rc = nas_proc_establish_cnf(user, confirm->nasMsg.data, - confirm->nasMsg.length); + if ( (confirm.errCode == AS_SUCCESS) || + (confirm.errCode == AS_TERMINATED_NAS) ) { + rc = nas_proc_establish_cnf(user, confirm.nasMsg.data, + confirm.nasMsg.length); } else { LOG_TRACE(WARNING, "NET-MAIN - " "Initial NAS message not delivered"); @@ -191,10 +191,10 @@ int nas_network_process_data(nas_user_t *user, int msg_id, const void *data) break; case AS_DL_INFO_TRANSFER_IND: { - const dl_info_transfer_ind_t *info = &msg->msg.dl_info_transfer_ind; + const dl_info_transfer_ind_t info = msg->msg.dl_info_transfer_ind; /* Received downlink data transfer indication */ - rc = nas_proc_dl_transfer_ind(user, info->nasMsg.data, - info->nasMsg.length); + rc = nas_proc_dl_transfer_ind(user, info.nasMsg.data, + info.nasMsg.length); break; } diff --git a/openair3/NAS/UE/nas_parser.c b/openair3/NAS/UE/nas_parser.c index beba47f64a..94c61b654c 100644 --- a/openair3/NAS/UE/nas_parser.c +++ b/openair3/NAS/UE/nas_parser.c @@ -86,10 +86,7 @@ static parser_command_line_t nasParserCommandLine = { "-trace", "", "Logging trace level\t\t", NAS_PARSER_DEFAULT_TRACE_LEVEL }, - { - "-uhost", "", "User app layer's hostname\t", - NAS_PARSER_DEFAULT_USER_HOSTNAME - }, + {"-uhost", "", "User app layer's hostname\t", "NULL"}, { "-nhost", "", "Network layer's hostname\t", NAS_PARSER_DEFAULT_NETWORK_HOSTNAME diff --git a/openair3/NAS/UE/nas_parser.h b/openair3/NAS/UE/nas_parser.h index 0924654e3f..1c97dbdaf1 100644 --- a/openair3/NAS/UE/nas_parser.h +++ b/openair3/NAS/UE/nas_parser.h @@ -55,7 +55,7 @@ Description NAS command line parser #define NAS_PARSER_DEFAULT_UE_ID "1" /* User application layer default hostname */ -#define NAS_PARSER_DEFAULT_USER_HOSTNAME "localhost" +#define NAS_PARSER_DEFAULT_USER_HOSTNAME NULL /* User application layer default port number */ #define NAS_PARSER_DEFAULT_USER_PORT_NUMBER "10000" diff --git a/openair3/NAS/UE/nas_ue_task.c b/openair3/NAS/UE/nas_ue_task.c index d712a7b7f0..be887623bb 100644 --- a/openair3/NAS/UE/nas_ue_task.c +++ b/openair3/NAS/UE/nas_ue_task.c @@ -33,6 +33,7 @@ # include "memory.h" #include "nas_user.h" +#include // FIXME make command line option for NAS_UE_AUTOSTART # define NAS_UE_AUTOSTART 1 @@ -136,7 +137,7 @@ void *nas_ue_task(void *args_p) for (instance = NB_eNB_INST; instance < (NB_eNB_INST + NB_UE_INST); instance++) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_UE, DEACTIVATE_MESSAGE); + message_p = itti_alloc_new_message(TASK_NAS_UE, 0, DEACTIVATE_MESSAGE); itti_send_msg_to_task(TASK_L2L1, instance, message_p); } @@ -145,7 +146,7 @@ void *nas_ue_task(void *args_p) itti_receive_msg (TASK_NAS_UE, &msg_p); if (msg_p != NULL) { - instance = ITTI_MSG_INSTANCE (msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); Mod_id = instance - NB_eNB_INST; if (instance == INSTANCE_DEFAULT) { printf("%s:%d: FATAL: instance is INSTANCE_DEFAULT, should not happen.\n", diff --git a/openair3/NAS/gNB/network_process_nas.c b/openair3/NAS/gNB/network_process_nas.c new file mode 100644 index 0000000000..ce8897730b --- /dev/null +++ b/openair3/NAS/gNB/network_process_nas.c @@ -0,0 +1,214 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ +#include + +void SGSabortUE(void *msg, NRUEcontext_t *UE) { +} +void nas_schedule(void) { +} +/* + *Message reception + */ + +void SGSregistrationReq(void *msg, NRUEcontext_t *UE) { +} + +void SGSderegistrationUEReq(void *msg, NRUEcontext_t *UE) { +} + +void SGSidentityResp(void *msg, NRUEcontext_t *UE) { + // use the UE SUPI to load the USIM + IdentityresponseIMSI_t *resp=(IdentityresponseIMSI_t *)msg; + char configName[100]={0}; + char * ptr= stpcpy(configName,"uicc"); + *ptr++=resp->mcc1+'0'; + *ptr++=resp->mcc2+'0'; + *ptr++=resp->mcc3+'0'; + *ptr++=resp->mnc1+'0'; + *ptr++=resp->mnc2+'0'; + if ( resp->mnc3 != 0xF ) + *ptr++=resp->mnc3 +'0'; + int respSize=ntohs(resp->common.len); + int msinByteSize=respSize-sizeof(IdentityresponseIMSI_t); + uint8_t * msin=(uint8_t *) (resp+1); + for(int i=3 ; i> 4) ; + *ptr++=(msin[i] & 0xf) +'0'; + if (digit1 != 0xf) + *ptr++=digit1 +'0'; + } + *ptr=0; + if (UE->uicc == NULL) + // config file section hardcoded as "uicc", nevertheless it opens to manage several UEs or a multi SIM UE + UE->uicc=init_uicc(configName); + //We schedule Authentication request + nas_schedule(); +} + +void SGSauthenticationResp(void *msg, NRUEcontext_t *UE) { + // Let's check the answer + authenticationresponse_t* resp=(authenticationresponse_t*) msg; + uint8_t resStarLocal[16]; + resToresStar(resStarLocal,UE->uicc); + if ( memcmp(resStarLocal, resp->RES, sizeof(resStarLocal)) == 0 ) { + LOG_I(NAS,"UE answer to authentication resquest is correct\n"); + // we will send securityModeCommand + nas_schedule(); + } else { + LOG_E(NAS,"UE authentication response not good\n"); + // To be implemented ? + } +} + +void SGSsecurityModeComplete(void *msg, NRUEcontext_t *UE) { + +} + +void SGSregistrationComplete(void *msg, NRUEcontext_t *UE) { +} + +void processNAS(void *msg, NRUEcontext_t *UE) { + SGScommonHeader_t *header=(SGScommonHeader_t *) msg; + + if ( header->sh > 4 ) + SGSabortUE(msg, UE); + else { + switch (header->epd) { + case SGSmobilitymanagementmessages: + LOG_I(NAS,"Received message: %s\n", idStr(message_text_info, header->mt)); + + switch (header->mt) { + case Registrationrequest: + SGSregistrationReq(msg, UE); + break; + + case DeregistrationrequestUEoriginating: + SGSderegistrationUEReq(msg, UE); + break; + + case Authenticationresponse: + SGSauthenticationResp(msg, UE); + break; + + case Identityresponse: + SGSidentityResp(msg, UE); + break; + + case Securitymodecomplete: + SGSsecurityModeComplete(msg, UE); + break; + + case Registrationcomplete: + SGSregistrationComplete(msg, UE); + break; + + default: + SGSabortUE(msg, UE); + } + + break; + + case SGSsessionmanagementmessages: + SGSabortUE(msg, UE); + break; + + default: + SGSabortUE(msg, UE); + } + } +} + +/* + * Messages emission + */ + +int identityRequest(void **msg, NRUEcontext_t *UE) { + myCalloc(req, Identityrequest_t); + req->epd=SGSmobilitymanagementmessages; + req->sh=0; + req->mt=Identityrequest; + req->it=SUCI; + *msg=req; + return sizeof(Identityrequest_t); +} + +int authenticationRequest(void **msg, NRUEcontext_t *UE) { + + myCalloc(req, authenticationrequestHeader_t); + req->epd=SGSmobilitymanagementmessages; + req->sh=0; + req->mt=Authenticationrequest; + // native security context => bit 4 to 0 + // probably from TS 33.501, table A-8.1 + // N-NAS-int-alg (Native NAS integrity) + /* + N-NAS-enc-alg 0x01 + N-NAS-int-alg 0x02 + N-RRC-enc-alg 0x03 + N-RRC-int-alg 0x04 + N-UP-enc-alg 0x05 + N-UP-int-alg 0x06 + */ + req->ngKSI=2; + // TS 33.501, Annex A.7.1: Initial set of security features defined for 5GS. + req->ABBALen=2; + req->ABBA=0; + //rand (TV) + req->ieiRAND=IEI_RAND; + FILE *h=fopen("/dev/random","r"); + + if ( sizeof(req->RAND) != fread(req->RAND,1,sizeof(req->RAND),h) ) + LOG_E(NAS, "can't read /dev/random\n"); + + fclose(h); + memcpy(UE->uicc->rand, req->RAND, sizeof(UE->uicc->rand)); + // challenge/AUTN (TLV) + req->ieiAUTN=IEI_AUTN; + req->AUTNlen=sizeof(req->AUTN); + uicc_milenage_generate( req->AUTN, UE->uicc); + // EAP message (TLV-E) + // not developped + *msg=req; + return sizeof(authenticationrequestHeader_t); +} + +int securityModeCommand(void **msg, NRUEcontext_t *UE) { + *msg=NULL; + myCalloc(req, securityModeCommand_t); + req->epd=SGSmobilitymanagementmessages; + req->sh=0; + req->mt=Securitymodecommand; + + // integrity algo from 5G-IA0 (null algo) to 5G-IA7 in first 4 bits + unsigned int ia=0; + // cyphering algo from 5G-EA0 (null algo) to 5G-IA7 in MSB 4 bits + unsigned int ea=0; + // trace from commercial: 5G-IA0 (0) 128-5G-IA2 (2) + req->selectedNASsecurityalgorithms= ea<<4 | ia; + + // KSI: N-NAS-int-alg 0x02 + req->ngKSI=2; + + *msg=req; + return 0; +} diff --git a/openair3/NGAP/MESSAGES/ASN1/ASN1_files/ngap-15.8.0.asn1 b/openair3/NGAP/MESSAGES/ASN1/ASN1_files/ngap-15.8.0.asn1 new file mode 100644 index 0000000000..b808ed3ada --- /dev/null +++ b/openair3/NGAP/MESSAGES/ASN1/ASN1_files/ngap-15.8.0.asn1 @@ -0,0 +1,6886 @@ +-- ASN1START +-- ************************************************************** +-- +-- Elementary Procedure definitions +-- +-- ************************************************************** + +NGAP-PDU-Descriptions { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-Access (22) modules (3) ngap (1) version1 (1) ngap-PDU-Descriptions (0)} + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + + Criticality, + ProcedureCode +FROM NGAP-CommonDataTypes + + AMFConfigurationUpdate, + AMFConfigurationUpdateAcknowledge, + AMFConfigurationUpdateFailure, + AMFStatusIndication, + CellTrafficTrace, + DeactivateTrace, + DownlinkNASTransport, + DownlinkNonUEAssociatedNRPPaTransport, + DownlinkRANConfigurationTransfer, + DownlinkRANStatusTransfer, + DownlinkUEAssociatedNRPPaTransport, + ErrorIndication, + HandoverCancel, + HandoverCancelAcknowledge, + HandoverCommand, + HandoverFailure, + HandoverNotify, + HandoverPreparationFailure, + HandoverRequest, + HandoverRequestAcknowledge, + HandoverRequired, + InitialContextSetupFailure, + InitialContextSetupRequest, + InitialContextSetupResponse, + InitialUEMessage, + LocationReport, + LocationReportingControl, + LocationReportingFailureIndication, + NASNonDeliveryIndication, + NGReset, + NGResetAcknowledge, + NGSetupFailure, + NGSetupRequest, + NGSetupResponse, + OverloadStart, + OverloadStop, + Paging, + PathSwitchRequest, + PathSwitchRequestAcknowledge, + PathSwitchRequestFailure, + PDUSessionResourceModifyConfirm, + PDUSessionResourceModifyIndication, + PDUSessionResourceModifyRequest, + PDUSessionResourceModifyResponse, + PDUSessionResourceNotify, + PDUSessionResourceReleaseCommand, + PDUSessionResourceReleaseResponse, + PDUSessionResourceSetupRequest, + PDUSessionResourceSetupResponse, + PrivateMessage, + PWSCancelRequest, + PWSCancelResponse, + PWSFailureIndication, + PWSRestartIndication, + RANConfigurationUpdate, + RANConfigurationUpdateAcknowledge, + RANConfigurationUpdateFailure, + RerouteNASRequest, + RRCInactiveTransitionReport, + SecondaryRATDataUsageReport, + TraceFailureIndication, + TraceStart, + UEContextModificationFailure, + UEContextModificationRequest, + UEContextModificationResponse, + UEContextReleaseCommand, + UEContextReleaseComplete, + UEContextReleaseRequest, + UERadioCapabilityCheckRequest, + UERadioCapabilityCheckResponse, + UERadioCapabilityInfoIndication, + UETNLABindingReleaseRequest, + UplinkNASTransport, + UplinkNonUEAssociatedNRPPaTransport, + UplinkRANConfigurationTransfer, + UplinkRANStatusTransfer, + UplinkUEAssociatedNRPPaTransport, + WriteReplaceWarningRequest, + WriteReplaceWarningResponse +FROM NGAP-PDU-Contents + + id-AMFConfigurationUpdate, + id-AMFStatusIndication, + id-CellTrafficTrace, + id-DeactivateTrace, + id-DownlinkNASTransport, + id-DownlinkNonUEAssociatedNRPPaTransport, + id-DownlinkRANConfigurationTransfer, + id-DownlinkRANStatusTransfer, + id-DownlinkUEAssociatedNRPPaTransport, + id-ErrorIndication, + id-HandoverCancel, + id-HandoverNotification, + id-HandoverPreparation, + id-HandoverResourceAllocation, + id-InitialContextSetup, + id-InitialUEMessage, + id-LocationReport, + id-LocationReportingControl, + id-LocationReportingFailureIndication, + id-NASNonDeliveryIndication, + id-NGReset, + id-NGSetup, + id-OverloadStart, + id-OverloadStop, + id-Paging, + id-PathSwitchRequest, + id-PDUSessionResourceModify, + id-PDUSessionResourceModifyIndication, + id-PDUSessionResourceNotify, + id-PDUSessionResourceRelease, + id-PDUSessionResourceSetup, + id-PrivateMessage, + id-PWSCancel, + id-PWSFailureIndication, + id-PWSRestartIndication, + id-RANConfigurationUpdate, + id-RerouteNASRequest, + id-RRCInactiveTransitionReport, + id-SecondaryRATDataUsageReport, + id-TraceFailureIndication, + id-TraceStart, + id-UEContextModification, + id-UEContextRelease, + id-UEContextReleaseRequest, + id-UERadioCapabilityCheck, + id-UERadioCapabilityInfoIndication, + id-UETNLABindingRelease, + id-UplinkNASTransport, + id-UplinkNonUEAssociatedNRPPaTransport, + id-UplinkRANConfigurationTransfer, + id-UplinkRANStatusTransfer, + id-UplinkUEAssociatedNRPPaTransport, + id-WriteReplaceWarning +FROM NGAP-Constants; + +-- ************************************************************** +-- +-- Interface Elementary Procedure Class +-- +-- ************************************************************** + +NGAP-ELEMENTARY-PROCEDURE ::= CLASS { + &InitiatingMessage , + &SuccessfulOutcome OPTIONAL, + &UnsuccessfulOutcome OPTIONAL, + &procedureCode ProcedureCode UNIQUE, + &criticality Criticality DEFAULT ignore +} + +WITH SYNTAX { + INITIATING MESSAGE &InitiatingMessage + [SUCCESSFUL OUTCOME &SuccessfulOutcome] + [UNSUCCESSFUL OUTCOME &UnsuccessfulOutcome] + PROCEDURE CODE &procedureCode + [CRITICALITY &criticality] +} + +-- ************************************************************** +-- +-- Interface PDU Definition +-- +-- ************************************************************** + +NGAP-PDU ::= CHOICE { + initiatingMessage InitiatingMessage, + successfulOutcome SuccessfulOutcome, + unsuccessfulOutcome UnsuccessfulOutcome, + ... +} + +InitiatingMessage ::= SEQUENCE { + procedureCode NGAP-ELEMENTARY-PROCEDURE.&procedureCode ({NGAP-ELEMENTARY-PROCEDURES}), + criticality NGAP-ELEMENTARY-PROCEDURE.&criticality ({NGAP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value NGAP-ELEMENTARY-PROCEDURE.&InitiatingMessage ({NGAP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +SuccessfulOutcome ::= SEQUENCE { + procedureCode NGAP-ELEMENTARY-PROCEDURE.&procedureCode ({NGAP-ELEMENTARY-PROCEDURES}), + criticality NGAP-ELEMENTARY-PROCEDURE.&criticality ({NGAP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value NGAP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome ({NGAP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +UnsuccessfulOutcome ::= SEQUENCE { + procedureCode NGAP-ELEMENTARY-PROCEDURE.&procedureCode ({NGAP-ELEMENTARY-PROCEDURES}), + criticality NGAP-ELEMENTARY-PROCEDURE.&criticality ({NGAP-ELEMENTARY-PROCEDURES}{@procedureCode}), + value NGAP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome ({NGAP-ELEMENTARY-PROCEDURES}{@procedureCode}) +} + +-- ************************************************************** +-- +-- Interface Elementary Procedure List +-- +-- ************************************************************** + +NGAP-ELEMENTARY-PROCEDURES NGAP-ELEMENTARY-PROCEDURE ::= { + NGAP-ELEMENTARY-PROCEDURES-CLASS-1 | + NGAP-ELEMENTARY-PROCEDURES-CLASS-2, + ... +} + +NGAP-ELEMENTARY-PROCEDURES-CLASS-1 NGAP-ELEMENTARY-PROCEDURE ::= { + aMFConfigurationUpdate | + handoverCancel | + handoverPreparation | + handoverResourceAllocation | + initialContextSetup | + nGReset | + nGSetup | + pathSwitchRequest | + pDUSessionResourceModify | + pDUSessionResourceModifyIndication | + pDUSessionResourceRelease | + pDUSessionResourceSetup | + pWSCancel | + rANConfigurationUpdate | + uEContextModification | + uEContextRelease | + uERadioCapabilityCheck | + writeReplaceWarning +} + +NGAP-ELEMENTARY-PROCEDURES-CLASS-2 NGAP-ELEMENTARY-PROCEDURE ::= { + aMFStatusIndication | + cellTrafficTrace | + deactivateTrace | + downlinkNASTransport | + downlinkNonUEAssociatedNRPPaTransport | + downlinkRANConfigurationTransfer | + downlinkRANStatusTransfer | + downlinkUEAssociatedNRPPaTransport | + errorIndication | + handoverNotification | + initialUEMessage | + locationReport | + locationReportingControl | + locationReportingFailureIndication | + nASNonDeliveryIndication | + overloadStart | + overloadStop | + paging | + pDUSessionResourceNotify | + privateMessage | + pWSFailureIndication | + pWSRestartIndication | + rerouteNASRequest | + rRCInactiveTransitionReport | + secondaryRATDataUsageReport | + traceFailureIndication | + traceStart | + uEContextReleaseRequest | + uERadioCapabilityInfoIndication | + uETNLABindingRelease | + uplinkNASTransport | + uplinkNonUEAssociatedNRPPaTransport | + uplinkRANConfigurationTransfer | + uplinkRANStatusTransfer | + uplinkUEAssociatedNRPPaTransport +} + +-- ************************************************************** +-- +-- Interface Elementary Procedures +-- +-- ************************************************************** + +aMFConfigurationUpdate NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE AMFConfigurationUpdate + SUCCESSFUL OUTCOME AMFConfigurationUpdateAcknowledge + UNSUCCESSFUL OUTCOME AMFConfigurationUpdateFailure + PROCEDURE CODE id-AMFConfigurationUpdate + CRITICALITY reject +} + +aMFStatusIndication NGAP-ELEMENTARY-PROCEDURE ::={ + INITIATING MESSAGE AMFStatusIndication + PROCEDURE CODE id-AMFStatusIndication + CRITICALITY ignore +} + +cellTrafficTrace NGAP-ELEMENTARY-PROCEDURE ::={ + INITIATING MESSAGE CellTrafficTrace + PROCEDURE CODE id-CellTrafficTrace + CRITICALITY ignore +} + +deactivateTrace NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DeactivateTrace + PROCEDURE CODE id-DeactivateTrace + CRITICALITY ignore +} + +downlinkNASTransport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DownlinkNASTransport + PROCEDURE CODE id-DownlinkNASTransport + CRITICALITY ignore +} + +downlinkNonUEAssociatedNRPPaTransport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DownlinkNonUEAssociatedNRPPaTransport + PROCEDURE CODE id-DownlinkNonUEAssociatedNRPPaTransport + CRITICALITY ignore +} + +downlinkRANConfigurationTransfer NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DownlinkRANConfigurationTransfer + PROCEDURE CODE id-DownlinkRANConfigurationTransfer + CRITICALITY ignore +} + +downlinkRANStatusTransfer NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DownlinkRANStatusTransfer + PROCEDURE CODE id-DownlinkRANStatusTransfer + CRITICALITY ignore +} + +downlinkUEAssociatedNRPPaTransport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE DownlinkUEAssociatedNRPPaTransport + PROCEDURE CODE id-DownlinkUEAssociatedNRPPaTransport + CRITICALITY ignore +} + +errorIndication NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE ErrorIndication + PROCEDURE CODE id-ErrorIndication + CRITICALITY ignore +} + +handoverCancel NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE HandoverCancel + SUCCESSFUL OUTCOME HandoverCancelAcknowledge + PROCEDURE CODE id-HandoverCancel + CRITICALITY reject +} + +handoverNotification NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE HandoverNotify + PROCEDURE CODE id-HandoverNotification + CRITICALITY ignore +} + +handoverPreparation NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE HandoverRequired + SUCCESSFUL OUTCOME HandoverCommand + UNSUCCESSFUL OUTCOME HandoverPreparationFailure + PROCEDURE CODE id-HandoverPreparation + CRITICALITY reject +} + +handoverResourceAllocation NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE HandoverRequest + SUCCESSFUL OUTCOME HandoverRequestAcknowledge + UNSUCCESSFUL OUTCOME HandoverFailure + PROCEDURE CODE id-HandoverResourceAllocation + CRITICALITY reject +} + +initialContextSetup NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE InitialContextSetupRequest + SUCCESSFUL OUTCOME InitialContextSetupResponse + UNSUCCESSFUL OUTCOME InitialContextSetupFailure + PROCEDURE CODE id-InitialContextSetup + CRITICALITY reject +} + +initialUEMessage NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE InitialUEMessage + PROCEDURE CODE id-InitialUEMessage + CRITICALITY ignore +} + +locationReport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE LocationReport + PROCEDURE CODE id-LocationReport + CRITICALITY ignore +} + +locationReportingControl NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE LocationReportingControl + PROCEDURE CODE id-LocationReportingControl + CRITICALITY ignore +} + +locationReportingFailureIndication NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE LocationReportingFailureIndication + PROCEDURE CODE id-LocationReportingFailureIndication + CRITICALITY ignore +} + +nASNonDeliveryIndication NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE NASNonDeliveryIndication + PROCEDURE CODE id-NASNonDeliveryIndication + CRITICALITY ignore +} + +nGReset NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE NGReset + SUCCESSFUL OUTCOME NGResetAcknowledge + PROCEDURE CODE id-NGReset + CRITICALITY reject +} + +nGSetup NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE NGSetupRequest + SUCCESSFUL OUTCOME NGSetupResponse + UNSUCCESSFUL OUTCOME NGSetupFailure + PROCEDURE CODE id-NGSetup + CRITICALITY reject +} + +overloadStart NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE OverloadStart + PROCEDURE CODE id-OverloadStart + CRITICALITY ignore +} + +overloadStop NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE OverloadStop + PROCEDURE CODE id-OverloadStop + CRITICALITY reject +} + +paging NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE Paging + PROCEDURE CODE id-Paging + CRITICALITY ignore +} + +pathSwitchRequest NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PathSwitchRequest + SUCCESSFUL OUTCOME PathSwitchRequestAcknowledge + UNSUCCESSFUL OUTCOME PathSwitchRequestFailure + PROCEDURE CODE id-PathSwitchRequest + CRITICALITY reject +} + +pDUSessionResourceModify NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PDUSessionResourceModifyRequest + SUCCESSFUL OUTCOME PDUSessionResourceModifyResponse + PROCEDURE CODE id-PDUSessionResourceModify + CRITICALITY reject +} + +pDUSessionResourceModifyIndication NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PDUSessionResourceModifyIndication + SUCCESSFUL OUTCOME PDUSessionResourceModifyConfirm + PROCEDURE CODE id-PDUSessionResourceModifyIndication + CRITICALITY reject +} + +pDUSessionResourceNotify NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PDUSessionResourceNotify + PROCEDURE CODE id-PDUSessionResourceNotify + CRITICALITY ignore +} + +pDUSessionResourceRelease NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PDUSessionResourceReleaseCommand + SUCCESSFUL OUTCOME PDUSessionResourceReleaseResponse + PROCEDURE CODE id-PDUSessionResourceRelease + CRITICALITY reject +} + +pDUSessionResourceSetup NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PDUSessionResourceSetupRequest + SUCCESSFUL OUTCOME PDUSessionResourceSetupResponse + PROCEDURE CODE id-PDUSessionResourceSetup + CRITICALITY reject +} + +privateMessage NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PrivateMessage + PROCEDURE CODE id-PrivateMessage + CRITICALITY ignore +} + +pWSCancel NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSCancelRequest + SUCCESSFUL OUTCOME PWSCancelResponse + PROCEDURE CODE id-PWSCancel + CRITICALITY reject +} + +pWSFailureIndication NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSFailureIndication + PROCEDURE CODE id-PWSFailureIndication + CRITICALITY ignore +} + +pWSRestartIndication NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE PWSRestartIndication + PROCEDURE CODE id-PWSRestartIndication + CRITICALITY ignore +} + +rANConfigurationUpdate NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RANConfigurationUpdate + SUCCESSFUL OUTCOME RANConfigurationUpdateAcknowledge + UNSUCCESSFUL OUTCOME RANConfigurationUpdateFailure + PROCEDURE CODE id-RANConfigurationUpdate + CRITICALITY reject +} + +rerouteNASRequest NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RerouteNASRequest + PROCEDURE CODE id-RerouteNASRequest + CRITICALITY reject +} + +rRCInactiveTransitionReport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE RRCInactiveTransitionReport + PROCEDURE CODE id-RRCInactiveTransitionReport + CRITICALITY ignore +} + +secondaryRATDataUsageReport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE SecondaryRATDataUsageReport + PROCEDURE CODE id-SecondaryRATDataUsageReport + CRITICALITY ignore +} + +traceFailureIndication NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE TraceFailureIndication + PROCEDURE CODE id-TraceFailureIndication + CRITICALITY ignore +} + +traceStart NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE TraceStart + PROCEDURE CODE id-TraceStart + CRITICALITY ignore +} + +uEContextModification NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextModificationRequest + SUCCESSFUL OUTCOME UEContextModificationResponse + UNSUCCESSFUL OUTCOME UEContextModificationFailure + PROCEDURE CODE id-UEContextModification + CRITICALITY reject +} + +uEContextRelease NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextReleaseCommand + SUCCESSFUL OUTCOME UEContextReleaseComplete + PROCEDURE CODE id-UEContextRelease + CRITICALITY reject +} + +uEContextReleaseRequest NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UEContextReleaseRequest + PROCEDURE CODE id-UEContextReleaseRequest + CRITICALITY ignore +} + +uERadioCapabilityCheck NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UERadioCapabilityCheckRequest + SUCCESSFUL OUTCOME UERadioCapabilityCheckResponse + PROCEDURE CODE id-UERadioCapabilityCheck + CRITICALITY reject +} + +uERadioCapabilityInfoIndication NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UERadioCapabilityInfoIndication + PROCEDURE CODE id-UERadioCapabilityInfoIndication + CRITICALITY ignore +} + +uETNLABindingRelease NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UETNLABindingReleaseRequest + PROCEDURE CODE id-UETNLABindingRelease + CRITICALITY ignore +} + +uplinkNASTransport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UplinkNASTransport + PROCEDURE CODE id-UplinkNASTransport + CRITICALITY ignore +} + +uplinkNonUEAssociatedNRPPaTransport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UplinkNonUEAssociatedNRPPaTransport + PROCEDURE CODE id-UplinkNonUEAssociatedNRPPaTransport + CRITICALITY ignore +} + +uplinkRANConfigurationTransfer NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UplinkRANConfigurationTransfer + PROCEDURE CODE id-UplinkRANConfigurationTransfer + CRITICALITY ignore +} + +uplinkRANStatusTransfer NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UplinkRANStatusTransfer + PROCEDURE CODE id-UplinkRANStatusTransfer + CRITICALITY ignore +} + +uplinkUEAssociatedNRPPaTransport NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE UplinkUEAssociatedNRPPaTransport + PROCEDURE CODE id-UplinkUEAssociatedNRPPaTransport + CRITICALITY ignore +} + +writeReplaceWarning NGAP-ELEMENTARY-PROCEDURE ::= { + INITIATING MESSAGE WriteReplaceWarningRequest + SUCCESSFUL OUTCOME WriteReplaceWarningResponse + PROCEDURE CODE id-WriteReplaceWarning + CRITICALITY reject +} + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- PDU definitions for NGAP. +-- +-- ************************************************************** + +NGAP-PDU-Contents { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-Access (22) modules (3) ngap (1) version1 (1) ngap-PDU-Contents (1) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + + AllowedNSSAI, + AMFName, + AMFSetID, + AMF-TNLAssociationSetupList, + AMF-TNLAssociationToAddList, + AMF-TNLAssociationToRemoveList, + AMF-TNLAssociationToUpdateList, + AMF-UE-NGAP-ID, + AssistanceDataForPaging, + BroadcastCancelledAreaList, + BroadcastCompletedAreaList, + CancelAllWarningMessages, + Cause, + CellIDListForRestart, + CNAssistedRANTuning, + ConcurrentWarningMessageInd, + CoreNetworkAssistanceInformationForInactive, + CPTransportLayerInformation, + CriticalityDiagnostics, + DataCodingScheme, + DirectForwardingPathAvailability, + EmergencyAreaIDListForRestart, + EmergencyFallbackIndicator, + EN-DCSONConfigurationTransfer, + EUTRA-CGI, + FiveG-S-TMSI, + GlobalRANNodeID, + GUAMI, + HandoverFlag, + HandoverType, + IMSVoiceSupportIndicator, + IndexToRFSP, + InfoOnRecommendedCellsAndRANNodesForPaging, + LocationReportingRequestType, + MaskedIMEISV, + MessageIdentifier, + MobilityRestrictionList, + NAS-PDU, + NASSecurityParametersFromNGRAN, + NewSecurityContextInd, + NGRAN-CGI, + NGRAN-TNLAssociationToRemoveList, + NGRANTraceID, + NR-CGI, + NRPPa-PDU, + NumberOfBroadcastsRequested, + OverloadResponse, + OverloadStartNSSAIList, + PagingDRX, + PagingOrigin, + PagingPriority, + PDUSessionAggregateMaximumBitRate, + PDUSessionResourceAdmittedList, + PDUSessionResourceFailedToModifyListModCfm, + PDUSessionResourceFailedToModifyListModRes, + PDUSessionResourceFailedToSetupListCxtFail, + PDUSessionResourceFailedToSetupListCxtRes, + PDUSessionResourceFailedToSetupListHOAck, + PDUSessionResourceFailedToSetupListPSReq, + PDUSessionResourceFailedToSetupListSURes, + PDUSessionResourceHandoverList, + PDUSessionResourceListCxtRelCpl, + PDUSessionResourceListCxtRelReq, + PDUSessionResourceListHORqd, + PDUSessionResourceModifyListModCfm, + PDUSessionResourceModifyListModInd, + PDUSessionResourceModifyListModReq, + PDUSessionResourceModifyListModRes, + PDUSessionResourceNotifyList, + PDUSessionResourceReleasedListNot, + PDUSessionResourceReleasedListPSAck, + PDUSessionResourceReleasedListPSFail, + PDUSessionResourceReleasedListRelRes, + PDUSessionResourceSecondaryRATUsageList, + PDUSessionResourceSetupListCxtReq, + PDUSessionResourceSetupListCxtRes, + PDUSessionResourceSetupListHOReq, + PDUSessionResourceSetupListSUReq, + PDUSessionResourceSetupListSURes, + PDUSessionResourceSwitchedList, + PDUSessionResourceToBeSwitchedDLList, + PDUSessionResourceToReleaseListHOCmd, + PDUSessionResourceToReleaseListRelCmd, + PLMNIdentity, + PLMNSupportList, + PWSFailedCellIDList, + RANNodeName, + RANPagingPriority, + RANStatusTransfer-TransparentContainer, + RAN-UE-NGAP-ID, + RedirectionVoiceFallback, + RelativeAMFCapacity, + RepetitionPeriod, + ResetType, + RoutingID, + RRCEstablishmentCause, + RRCInactiveTransitionReportRequest, + RRCState, + SecurityContext, + SecurityKey, + SerialNumber, + ServedGUAMIList, + SliceSupportList, + S-NSSAI, + SONConfigurationTransfer, + SourceToTarget-TransparentContainer, + SourceToTarget-AMFInformationReroute, + SupportedTAList, + TAIListForPaging, + TAIListForRestart, + TargetID, + TargetToSource-TransparentContainer, + TimeToWait, + TNLAssociationList, + TraceActivation, + TrafficLoadReductionIndication, + TransportLayerAddress, + UEAggregateMaximumBitRate, + UE-associatedLogicalNG-connectionList, + UEContextRequest, + UE-NGAP-IDs, + UEPagingIdentity, + UEPresenceInAreaOfInterestList, + UERadioCapability, + UERadioCapabilityForPaging, + UERetentionInformation, + UESecurityCapabilities, + UnavailableGUAMIList, + UserLocationInformation, + WarningAreaCoordinates, + WarningAreaList, + WarningMessageContents, + WarningSecurityInfo, + WarningType + +FROM NGAP-IEs + + PrivateIE-Container{}, + ProtocolExtensionContainer{}, + ProtocolIE-Container{}, + ProtocolIE-ContainerList{}, + ProtocolIE-ContainerPair{}, + ProtocolIE-SingleContainer{}, + NGAP-PRIVATE-IES, + NGAP-PROTOCOL-EXTENSION, + NGAP-PROTOCOL-IES, + NGAP-PROTOCOL-IES-PAIR +FROM NGAP-Containers + + id-AllowedNSSAI, + id-AMFName, + id-AMFOverloadResponse, + id-AMFSetID, + id-AMF-TNLAssociationFailedToSetupList, + id-AMF-TNLAssociationSetupList, + id-AMF-TNLAssociationToAddList, + id-AMF-TNLAssociationToRemoveList, + id-AMF-TNLAssociationToUpdateList, + id-AMFTrafficLoadReductionIndication, + id-AMF-UE-NGAP-ID, + id-AssistanceDataForPaging, + id-BroadcastCancelledAreaList, + id-BroadcastCompletedAreaList, + id-CancelAllWarningMessages, + id-Cause, + id-CellIDListForRestart, + id-CNAssistedRANTuning, + id-ConcurrentWarningMessageInd, + id-CoreNetworkAssistanceInformationForInactive, + id-CriticalityDiagnostics, + id-DataCodingScheme, + id-DefaultPagingDRX, + id-DirectForwardingPathAvailability, + id-EmergencyAreaIDListForRestart, + id-EmergencyFallbackIndicator, + id-ENDC-SONConfigurationTransferDL, + id-ENDC-SONConfigurationTransferUL, + id-EUTRA-CGI, + id-FiveG-S-TMSI, + id-GlobalRANNodeID, + id-GUAMI, + id-HandoverFlag, + id-HandoverType, + id-IMSVoiceSupportIndicator, + id-IndexToRFSP, + id-InfoOnRecommendedCellsAndRANNodesForPaging, + id-LocationReportingRequestType, + id-MaskedIMEISV, + id-MessageIdentifier, + id-MobilityRestrictionList, + id-NAS-PDU, + id-NASC, + id-NASSecurityParametersFromNGRAN, + id-NewAMF-UE-NGAP-ID, + id-NewGUAMI, + id-NewSecurityContextInd, + id-NGAP-Message, + id-NGRAN-CGI, + id-NGRAN-TNLAssociationToRemoveList, + id-NGRANTraceID, + id-NR-CGI, + id-NRPPa-PDU, + id-NumberOfBroadcastsRequested, + id-OldAMF, + id-OverloadStartNSSAIList, + id-PagingDRX, + id-PagingOrigin, + id-PagingPriority, + id-PDUSessionResourceAdmittedList, + id-PDUSessionResourceFailedToModifyListModCfm, + id-PDUSessionResourceFailedToModifyListModRes, + id-PDUSessionResourceFailedToSetupListCxtFail, + id-PDUSessionResourceFailedToSetupListCxtRes, + id-PDUSessionResourceFailedToSetupListHOAck, + id-PDUSessionResourceFailedToSetupListPSReq, + id-PDUSessionResourceFailedToSetupListSURes, + id-PDUSessionResourceHandoverList, + id-PDUSessionResourceListCxtRelCpl, + id-PDUSessionResourceListCxtRelReq, + id-PDUSessionResourceListHORqd, + id-PDUSessionResourceModifyListModCfm, + id-PDUSessionResourceModifyListModInd, + id-PDUSessionResourceModifyListModReq, + id-PDUSessionResourceModifyListModRes, + id-PDUSessionResourceNotifyList, + id-PDUSessionResourceReleasedListNot, + id-PDUSessionResourceReleasedListPSAck, + id-PDUSessionResourceReleasedListPSFail, + id-PDUSessionResourceReleasedListRelRes, + id-PDUSessionResourceSecondaryRATUsageList, + id-PDUSessionResourceSetupListCxtReq, + id-PDUSessionResourceSetupListCxtRes, + id-PDUSessionResourceSetupListHOReq, + id-PDUSessionResourceSetupListSUReq, + id-PDUSessionResourceSetupListSURes, + id-PDUSessionResourceSwitchedList, + id-PDUSessionResourceToBeSwitchedDLList, + id-PDUSessionResourceToReleaseListHOCmd, + id-PDUSessionResourceToReleaseListRelCmd, + id-PLMNSupportList, + id-PWSFailedCellIDList, + id-RANNodeName, + id-RANPagingPriority, + id-RANStatusTransfer-TransparentContainer, + id-RAN-UE-NGAP-ID, + id-RedirectionVoiceFallback, + id-RelativeAMFCapacity, + id-RepetitionPeriod, + id-ResetType, + id-RoutingID, + id-RRCEstablishmentCause, + id-RRCInactiveTransitionReportRequest, + id-RRCState, + id-SecurityContext, + id-SecurityKey, + id-SelectedPLMNIdentity, + id-SerialNumber, + id-ServedGUAMIList, + id-SliceSupportList, + id-SONConfigurationTransferDL, + id-SONConfigurationTransferUL, + id-SourceAMF-UE-NGAP-ID, + id-SourceToTarget-TransparentContainer, + id-SourceToTarget-AMFInformationReroute, + id-SupportedTAList, + id-TAIListForPaging, + id-TAIListForRestart, + id-TargetID, + id-TargetToSource-TransparentContainer, + id-TimeToWait, + id-TraceActivation, + id-TraceCollectionEntityIPAddress, + id-UEAggregateMaximumBitRate, + id-UE-associatedLogicalNG-connectionList, + id-UEContextRequest, + id-UE-NGAP-IDs, + id-UEPagingIdentity, + id-UEPresenceInAreaOfInterestList, + id-UERadioCapability, + id-UERadioCapabilityForPaging, + id-UERetentionInformation, + id-UESecurityCapabilities, + id-UnavailableGUAMIList, + id-UserLocationInformation, + id-WarningAreaCoordinates, + id-WarningAreaList, + id-WarningMessageContents, + id-WarningSecurityInfo, + id-WarningType + +FROM NGAP-Constants; + +-- ************************************************************** +-- +-- PDU SESSION MANAGEMENT ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PDU Session Resource Setup Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE SETUP REQUEST +-- +-- ************************************************************** + +PDUSessionResourceSetupRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceSetupRequestIEs} }, + ... +} + +PDUSessionResourceSetupRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RANPagingPriority CRITICALITY ignore TYPE RANPagingPriority PRESENCE optional }| + { ID id-NAS-PDU CRITICALITY reject TYPE NAS-PDU PRESENCE optional }| + { ID id-PDUSessionResourceSetupListSUReq CRITICALITY reject TYPE PDUSessionResourceSetupListSUReq PRESENCE mandatory }| + { ID id-UEAggregateMaximumBitRate CRITICALITY ignore TYPE UEAggregateMaximumBitRate PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE SETUP RESPONSE +-- +-- ************************************************************** + +PDUSessionResourceSetupResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceSetupResponseIEs} }, + ... +} + +PDUSessionResourceSetupResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceSetupListSURes CRITICALITY ignore TYPE PDUSessionResourceSetupListSURes PRESENCE optional }| + { ID id-PDUSessionResourceFailedToSetupListSURes CRITICALITY ignore TYPE PDUSessionResourceFailedToSetupListSURes PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- PDU Session Resource Release Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE RELEASE COMMAND +-- +-- ************************************************************** + +PDUSessionResourceReleaseCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceReleaseCommandIEs} }, + ... +} + +PDUSessionResourceReleaseCommandIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RANPagingPriority CRITICALITY ignore TYPE RANPagingPriority PRESENCE optional }| + { ID id-NAS-PDU CRITICALITY ignore TYPE NAS-PDU PRESENCE optional }| + { ID id-PDUSessionResourceToReleaseListRelCmd CRITICALITY reject TYPE PDUSessionResourceToReleaseListRelCmd PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE RELEASE RESPONSE +-- +-- ************************************************************** + +PDUSessionResourceReleaseResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceReleaseResponseIEs} }, + ... +} + +PDUSessionResourceReleaseResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceReleasedListRelRes CRITICALITY ignore TYPE PDUSessionResourceReleasedListRelRes PRESENCE mandatory }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PDU Session Resource Modify Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE MODIFY REQUEST +-- +-- ************************************************************** + +PDUSessionResourceModifyRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceModifyRequestIEs} }, + ... +} + +PDUSessionResourceModifyRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RANPagingPriority CRITICALITY ignore TYPE RANPagingPriority PRESENCE optional }| + { ID id-PDUSessionResourceModifyListModReq CRITICALITY reject TYPE PDUSessionResourceModifyListModReq PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE MODIFY RESPONSE +-- +-- ************************************************************** + +PDUSessionResourceModifyResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceModifyResponseIEs} }, + ... +} + +PDUSessionResourceModifyResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceModifyListModRes CRITICALITY ignore TYPE PDUSessionResourceModifyListModRes PRESENCE optional }| + { ID id-PDUSessionResourceFailedToModifyListModRes CRITICALITY ignore TYPE PDUSessionResourceFailedToModifyListModRes PRESENCE optional }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- PDU Session Resource Notify Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE NOTIFY +-- +-- ************************************************************** + +PDUSessionResourceNotify ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceNotifyIEs} }, + ... +} + +PDUSessionResourceNotifyIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceNotifyList CRITICALITY reject TYPE PDUSessionResourceNotifyList PRESENCE optional }| + { ID id-PDUSessionResourceReleasedListNot CRITICALITY ignore TYPE PDUSessionResourceReleasedListNot PRESENCE optional }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- PDU Session Resource Modify Indication Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE MODIFY INDICATION +-- +-- ************************************************************** + +PDUSessionResourceModifyIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceModifyIndicationIEs} }, + ... +} + +PDUSessionResourceModifyIndicationIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceModifyListModInd CRITICALITY reject TYPE PDUSessionResourceModifyListModInd PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PDU SESSION RESOURCE MODIFY CONFIRM +-- +-- ************************************************************** + +PDUSessionResourceModifyConfirm ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceModifyConfirmIEs} }, + ... +} + +PDUSessionResourceModifyConfirmIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceModifyListModCfm CRITICALITY ignore TYPE PDUSessionResourceModifyListModCfm PRESENCE optional }| + { ID id-PDUSessionResourceFailedToModifyListModCfm CRITICALITY ignore TYPE PDUSessionResourceFailedToModifyListModCfm PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MANAGEMENT ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Initial Context Setup Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- INITIAL CONTEXT SETUP REQUEST +-- +-- ************************************************************** + +InitialContextSetupRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {InitialContextSetupRequestIEs} }, + ... +} + +InitialContextSetupRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-OldAMF CRITICALITY reject TYPE AMFName PRESENCE optional }| + { ID id-UEAggregateMaximumBitRate CRITICALITY reject TYPE UEAggregateMaximumBitRate PRESENCE conditional }| + { ID id-CoreNetworkAssistanceInformationForInactive CRITICALITY ignore TYPE CoreNetworkAssistanceInformationForInactive PRESENCE optional }| + { ID id-GUAMI CRITICALITY reject TYPE GUAMI PRESENCE mandatory }| + { ID id-PDUSessionResourceSetupListCxtReq CRITICALITY reject TYPE PDUSessionResourceSetupListCxtReq PRESENCE optional }| + { ID id-AllowedNSSAI CRITICALITY reject TYPE AllowedNSSAI PRESENCE mandatory }| + { ID id-UESecurityCapabilities CRITICALITY reject TYPE UESecurityCapabilities PRESENCE mandatory }| + { ID id-SecurityKey CRITICALITY reject TYPE SecurityKey PRESENCE mandatory }| + { ID id-TraceActivation CRITICALITY ignore TYPE TraceActivation PRESENCE optional }| + { ID id-MobilityRestrictionList CRITICALITY ignore TYPE MobilityRestrictionList PRESENCE optional }| + { ID id-UERadioCapability CRITICALITY ignore TYPE UERadioCapability PRESENCE optional }| + { ID id-IndexToRFSP CRITICALITY ignore TYPE IndexToRFSP PRESENCE optional }| + { ID id-MaskedIMEISV CRITICALITY ignore TYPE MaskedIMEISV PRESENCE optional }| + { ID id-NAS-PDU CRITICALITY ignore TYPE NAS-PDU PRESENCE optional }| + { ID id-EmergencyFallbackIndicator CRITICALITY reject TYPE EmergencyFallbackIndicator PRESENCE optional }| + { ID id-RRCInactiveTransitionReportRequest CRITICALITY ignore TYPE RRCInactiveTransitionReportRequest PRESENCE optional }| + { ID id-UERadioCapabilityForPaging CRITICALITY ignore TYPE UERadioCapabilityForPaging PRESENCE optional }| + { ID id-RedirectionVoiceFallback CRITICALITY ignore TYPE RedirectionVoiceFallback PRESENCE optional }| + { ID id-LocationReportingRequestType CRITICALITY ignore TYPE LocationReportingRequestType PRESENCE optional }| + { ID id-CNAssistedRANTuning CRITICALITY ignore TYPE CNAssistedRANTuning PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- INITIAL CONTEXT SETUP RESPONSE +-- +-- ************************************************************** + +InitialContextSetupResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {InitialContextSetupResponseIEs} }, + ... +} + +InitialContextSetupResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceSetupListCxtRes CRITICALITY ignore TYPE PDUSessionResourceSetupListCxtRes PRESENCE optional }| + { ID id-PDUSessionResourceFailedToSetupListCxtRes CRITICALITY ignore TYPE PDUSessionResourceFailedToSetupListCxtRes PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- INITIAL CONTEXT SETUP FAILURE +-- +-- ************************************************************** + +InitialContextSetupFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {InitialContextSetupFailureIEs} }, + ... +} + +InitialContextSetupFailureIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceFailedToSetupListCxtFail CRITICALITY ignore TYPE PDUSessionResourceFailedToSetupListCxtFail PRESENCE optional }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE Context Release Request Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT RELEASE REQUEST +-- +-- ************************************************************** + +UEContextReleaseRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UEContextReleaseRequest-IEs} }, + ... +} + +UEContextReleaseRequest-IEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceListCxtRelReq CRITICALITY reject TYPE PDUSessionResourceListCxtRelReq PRESENCE optional }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE Context Release Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT RELEASE COMMAND +-- +-- ************************************************************** + +UEContextReleaseCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UEContextReleaseCommand-IEs} }, + ... +} + +UEContextReleaseCommand-IEs NGAP-PROTOCOL-IES ::= { + { ID id-UE-NGAP-IDs CRITICALITY reject TYPE UE-NGAP-IDs PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT RELEASE COMPLETE +-- +-- ************************************************************** + +UEContextReleaseComplete ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UEContextReleaseComplete-IEs} }, + ... +} + +UEContextReleaseComplete-IEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE optional }| + { ID id-InfoOnRecommendedCellsAndRANNodesForPaging CRITICALITY ignore TYPE InfoOnRecommendedCellsAndRANNodesForPaging PRESENCE optional }| + { ID id-PDUSessionResourceListCxtRelCpl CRITICALITY reject TYPE PDUSessionResourceListCxtRelCpl PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE Context Modification Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION REQUEST +-- +-- ************************************************************** + +UEContextModificationRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UEContextModificationRequestIEs} }, + ... +} + +UEContextModificationRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RANPagingPriority CRITICALITY ignore TYPE RANPagingPriority PRESENCE optional }| + { ID id-SecurityKey CRITICALITY reject TYPE SecurityKey PRESENCE optional }| + { ID id-IndexToRFSP CRITICALITY ignore TYPE IndexToRFSP PRESENCE optional }| + { ID id-UEAggregateMaximumBitRate CRITICALITY ignore TYPE UEAggregateMaximumBitRate PRESENCE optional }| + { ID id-UESecurityCapabilities CRITICALITY reject TYPE UESecurityCapabilities PRESENCE optional }| + { ID id-CoreNetworkAssistanceInformationForInactive CRITICALITY ignore TYPE CoreNetworkAssistanceInformationForInactive PRESENCE optional }| + { ID id-EmergencyFallbackIndicator CRITICALITY reject TYPE EmergencyFallbackIndicator PRESENCE optional }| + { ID id-NewAMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE optional }| + { ID id-RRCInactiveTransitionReportRequest CRITICALITY ignore TYPE RRCInactiveTransitionReportRequest PRESENCE optional }| + { ID id-NewGUAMI CRITICALITY reject TYPE GUAMI PRESENCE optional }| + { ID id-CNAssistedRANTuning CRITICALITY ignore TYPE CNAssistedRANTuning PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION RESPONSE +-- +-- ************************************************************** + +UEContextModificationResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UEContextModificationResponseIEs} }, + ... +} + +UEContextModificationResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RRCState CRITICALITY ignore TYPE RRCState PRESENCE optional }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE CONTEXT MODIFICATION FAILURE +-- +-- ************************************************************** + +UEContextModificationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UEContextModificationFailureIEs} }, + ... +} + +UEContextModificationFailureIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- RRC INACTIVE TRANSITION REPORT +-- +-- ************************************************************** + +RRCInactiveTransitionReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {RRCInactiveTransitionReportIEs} }, + ... +} + +RRCInactiveTransitionReportIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RRCState CRITICALITY ignore TYPE RRCState PRESENCE mandatory }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE MOBILITY MANAGEMENT ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Handover Preparation Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- HANDOVER REQUIRED +-- +-- ************************************************************** + +HandoverRequired ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {HandoverRequiredIEs} }, + ... +} + +HandoverRequiredIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-HandoverType CRITICALITY reject TYPE HandoverType PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TargetID CRITICALITY reject TYPE TargetID PRESENCE mandatory }| + { ID id-DirectForwardingPathAvailability CRITICALITY ignore TYPE DirectForwardingPathAvailability PRESENCE optional }| + { ID id-PDUSessionResourceListHORqd CRITICALITY reject TYPE PDUSessionResourceListHORqd PRESENCE mandatory }| + { ID id-SourceToTarget-TransparentContainer CRITICALITY reject TYPE SourceToTarget-TransparentContainer PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- HANDOVER COMMAND +-- +-- ************************************************************** + +HandoverCommand ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {HandoverCommandIEs} }, + ... +} + +HandoverCommandIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-HandoverType CRITICALITY reject TYPE HandoverType PRESENCE mandatory }| + { ID id-NASSecurityParametersFromNGRAN CRITICALITY reject TYPE NASSecurityParametersFromNGRAN PRESENCE conditional }| + -- This IE shall be present if HandoverType IE is set to value "5GStoEPPS" -- + { ID id-PDUSessionResourceHandoverList CRITICALITY ignore TYPE PDUSessionResourceHandoverList PRESENCE optional }| + { ID id-PDUSessionResourceToReleaseListHOCmd CRITICALITY ignore TYPE PDUSessionResourceToReleaseListHOCmd PRESENCE optional }| + { ID id-TargetToSource-TransparentContainer CRITICALITY reject TYPE TargetToSource-TransparentContainer PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- HANDOVER PREPARATION FAILURE +-- +-- ************************************************************** + +HandoverPreparationFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {HandoverPreparationFailureIEs} }, + ... +} + +HandoverPreparationFailureIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Handover Resource Allocation Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- HANDOVER REQUEST +-- +-- ************************************************************** + +HandoverRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {HandoverRequestIEs} }, + ... +} + +HandoverRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-HandoverType CRITICALITY reject TYPE HandoverType PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-UEAggregateMaximumBitRate CRITICALITY reject TYPE UEAggregateMaximumBitRate PRESENCE mandatory }| + { ID id-CoreNetworkAssistanceInformationForInactive CRITICALITY ignore TYPE CoreNetworkAssistanceInformationForInactive PRESENCE optional }| + { ID id-UESecurityCapabilities CRITICALITY reject TYPE UESecurityCapabilities PRESENCE mandatory }| + { ID id-SecurityContext CRITICALITY reject TYPE SecurityContext PRESENCE mandatory }| + { ID id-NewSecurityContextInd CRITICALITY reject TYPE NewSecurityContextInd PRESENCE optional }| + { ID id-NASC CRITICALITY reject TYPE NAS-PDU PRESENCE optional }| + { ID id-PDUSessionResourceSetupListHOReq CRITICALITY reject TYPE PDUSessionResourceSetupListHOReq PRESENCE mandatory }| + { ID id-AllowedNSSAI CRITICALITY reject TYPE AllowedNSSAI PRESENCE mandatory }| + { ID id-TraceActivation CRITICALITY ignore TYPE TraceActivation PRESENCE optional }| + { ID id-MaskedIMEISV CRITICALITY ignore TYPE MaskedIMEISV PRESENCE optional }| + { ID id-SourceToTarget-TransparentContainer CRITICALITY reject TYPE SourceToTarget-TransparentContainer PRESENCE mandatory }| + { ID id-MobilityRestrictionList CRITICALITY ignore TYPE MobilityRestrictionList PRESENCE optional }| + { ID id-LocationReportingRequestType CRITICALITY ignore TYPE LocationReportingRequestType PRESENCE optional }| + { ID id-RRCInactiveTransitionReportRequest CRITICALITY ignore TYPE RRCInactiveTransitionReportRequest PRESENCE optional }| + { ID id-GUAMI CRITICALITY reject TYPE GUAMI PRESENCE mandatory }| + { ID id-RedirectionVoiceFallback CRITICALITY ignore TYPE RedirectionVoiceFallback PRESENCE optional }| + { ID id-CNAssistedRANTuning CRITICALITY ignore TYPE CNAssistedRANTuning PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- HANDOVER REQUEST ACKNOWLEDGE +-- +-- ************************************************************** + +HandoverRequestAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {HandoverRequestAcknowledgeIEs} }, + ... +} + +HandoverRequestAcknowledgeIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceAdmittedList CRITICALITY ignore TYPE PDUSessionResourceAdmittedList PRESENCE mandatory }| + { ID id-PDUSessionResourceFailedToSetupListHOAck CRITICALITY ignore TYPE PDUSessionResourceFailedToSetupListHOAck PRESENCE optional }| + { ID id-TargetToSource-TransparentContainer CRITICALITY reject TYPE TargetToSource-TransparentContainer PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- HANDOVER FAILURE +-- +-- ************************************************************** + +HandoverFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { HandoverFailureIEs} }, + ... +} + +HandoverFailureIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Handover Notification Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- HANDOVER NOTIFY +-- +-- ************************************************************** + +HandoverNotify ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { HandoverNotifyIEs} }, + ... +} + +HandoverNotifyIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- Path Switch Request Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PATH SWITCH REQUEST +-- +-- ************************************************************** + +PathSwitchRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PathSwitchRequestIEs} }, + ... +} + +PathSwitchRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-SourceAMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE mandatory }| + { ID id-UESecurityCapabilities CRITICALITY ignore TYPE UESecurityCapabilities PRESENCE mandatory }| + { ID id-PDUSessionResourceToBeSwitchedDLList CRITICALITY reject TYPE PDUSessionResourceToBeSwitchedDLList PRESENCE mandatory }| + { ID id-PDUSessionResourceFailedToSetupListPSReq CRITICALITY ignore TYPE PDUSessionResourceFailedToSetupListPSReq PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- PATH SWITCH REQUEST ACKNOWLEDGE +-- +-- ************************************************************** + +PathSwitchRequestAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PathSwitchRequestAcknowledgeIEs} }, + ... +} + +PathSwitchRequestAcknowledgeIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-UESecurityCapabilities CRITICALITY reject TYPE UESecurityCapabilities PRESENCE optional }| + { ID id-SecurityContext CRITICALITY reject TYPE SecurityContext PRESENCE mandatory }| + { ID id-NewSecurityContextInd CRITICALITY reject TYPE NewSecurityContextInd PRESENCE optional }| + { ID id-PDUSessionResourceSwitchedList CRITICALITY ignore TYPE PDUSessionResourceSwitchedList PRESENCE mandatory }| + { ID id-PDUSessionResourceReleasedListPSAck CRITICALITY ignore TYPE PDUSessionResourceReleasedListPSAck PRESENCE optional }| + { ID id-AllowedNSSAI CRITICALITY reject TYPE AllowedNSSAI PRESENCE mandatory }| + { ID id-CoreNetworkAssistanceInformationForInactive CRITICALITY ignore TYPE CoreNetworkAssistanceInformationForInactive PRESENCE optional }| + { ID id-RRCInactiveTransitionReportRequest CRITICALITY ignore TYPE RRCInactiveTransitionReportRequest PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-RedirectionVoiceFallback CRITICALITY ignore TYPE RedirectionVoiceFallback PRESENCE optional }| + { ID id-CNAssistedRANTuning CRITICALITY ignore TYPE CNAssistedRANTuning PRESENCE optional }, + ... +} + + +-- ************************************************************** +-- +-- PATH SWITCH REQUEST FAILURE +-- +-- ************************************************************** + +PathSwitchRequestFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { PathSwitchRequestFailureIEs} }, + ... +} + +PathSwitchRequestFailureIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceReleasedListPSFail CRITICALITY ignore TYPE PDUSessionResourceReleasedListPSFail PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Handover Cancellation Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- HANDOVER CANCEL +-- +-- ************************************************************** + +HandoverCancel ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { HandoverCancelIEs} }, + ... +} + +HandoverCancelIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- HANDOVER CANCEL ACKNOWLEDGE +-- +-- ************************************************************** + +HandoverCancelAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { { HandoverCancelAcknowledgeIEs} }, + ... +} + +HandoverCancelAcknowledgeIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Uplink RAN Status Transfer Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UPLINK RAN STATUS TRANSFER +-- +-- ************************************************************** + +UplinkRANStatusTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UplinkRANStatusTransferIEs} }, + ... +} + +UplinkRANStatusTransferIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RANStatusTransfer-TransparentContainer CRITICALITY reject TYPE RANStatusTransfer-TransparentContainer PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- Downlink RAN Status Transfer Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- DOWNLINK RAN STATUS TRANSFER +-- +-- ************************************************************** + +DownlinkRANStatusTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {DownlinkRANStatusTransferIEs} }, + ... +} + +DownlinkRANStatusTransferIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RANStatusTransfer-TransparentContainer CRITICALITY reject TYPE RANStatusTransfer-TransparentContainer PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- PAGING ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PAGING +-- +-- ************************************************************** + +Paging ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PagingIEs} }, + ... +} + +PagingIEs NGAP-PROTOCOL-IES ::= { + { ID id-UEPagingIdentity CRITICALITY ignore TYPE UEPagingIdentity PRESENCE mandatory }| + { ID id-PagingDRX CRITICALITY ignore TYPE PagingDRX PRESENCE optional }| + { ID id-TAIListForPaging CRITICALITY ignore TYPE TAIListForPaging PRESENCE mandatory }| + { ID id-PagingPriority CRITICALITY ignore TYPE PagingPriority PRESENCE optional }| + { ID id-UERadioCapabilityForPaging CRITICALITY ignore TYPE UERadioCapabilityForPaging PRESENCE optional }| + { ID id-PagingOrigin CRITICALITY ignore TYPE PagingOrigin PRESENCE optional }| + { ID id-AssistanceDataForPaging CRITICALITY ignore TYPE AssistanceDataForPaging PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- NAS TRANSPORT ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- INITIAL UE MESSAGE +-- +-- ************************************************************** + +InitialUEMessage ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {InitialUEMessage-IEs} }, + ... +} + +InitialUEMessage-IEs NGAP-PROTOCOL-IES ::= { + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-NAS-PDU CRITICALITY reject TYPE NAS-PDU PRESENCE mandatory }| + { ID id-UserLocationInformation CRITICALITY reject TYPE UserLocationInformation PRESENCE mandatory }| + { ID id-RRCEstablishmentCause CRITICALITY ignore TYPE RRCEstablishmentCause PRESENCE mandatory }| + { ID id-FiveG-S-TMSI CRITICALITY reject TYPE FiveG-S-TMSI PRESENCE optional }| + { ID id-AMFSetID CRITICALITY ignore TYPE AMFSetID PRESENCE optional }| + { ID id-UEContextRequest CRITICALITY ignore TYPE UEContextRequest PRESENCE optional }| + { ID id-AllowedNSSAI CRITICALITY reject TYPE AllowedNSSAI PRESENCE optional }| + { ID id-SourceToTarget-AMFInformationReroute CRITICALITY ignore TYPE SourceToTarget-AMFInformationReroute PRESENCE optional }| + { ID id-SelectedPLMNIdentity CRITICALITY ignore TYPE PLMNIdentity PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- DOWNLINK NAS TRANSPORT +-- +-- ************************************************************** + +DownlinkNASTransport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {DownlinkNASTransport-IEs} }, + ... +} + +DownlinkNASTransport-IEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-OldAMF CRITICALITY reject TYPE AMFName PRESENCE optional }| + { ID id-RANPagingPriority CRITICALITY ignore TYPE RANPagingPriority PRESENCE optional }| + { ID id-NAS-PDU CRITICALITY reject TYPE NAS-PDU PRESENCE mandatory }| + { ID id-MobilityRestrictionList CRITICALITY ignore TYPE MobilityRestrictionList PRESENCE optional }| + { ID id-IndexToRFSP CRITICALITY ignore TYPE IndexToRFSP PRESENCE optional }| + { ID id-UEAggregateMaximumBitRate CRITICALITY ignore TYPE UEAggregateMaximumBitRate PRESENCE optional }| + { ID id-AllowedNSSAI CRITICALITY reject TYPE AllowedNSSAI PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UPLINK NAS TRANSPORT +-- +-- ************************************************************** + +UplinkNASTransport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UplinkNASTransport-IEs} }, + ... +} + +UplinkNASTransport-IEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-NAS-PDU CRITICALITY reject TYPE NAS-PDU PRESENCE mandatory }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- NAS NON DELIVERY INDICATION +-- +-- ************************************************************** + +NASNonDeliveryIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {NASNonDeliveryIndication-IEs} }, + ... +} + +NASNonDeliveryIndication-IEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-NAS-PDU CRITICALITY ignore TYPE NAS-PDU PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- REROUTE NAS REQUEST +-- +-- ************************************************************** + +RerouteNASRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {RerouteNASRequest-IEs} }, + ... +} + +RerouteNASRequest-IEs NGAP-PROTOCOL-IES ::= { + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE optional }| + { ID id-NGAP-Message CRITICALITY reject TYPE OCTET STRING PRESENCE mandatory }| + { ID id-AMFSetID CRITICALITY reject TYPE AMFSetID PRESENCE mandatory }| + { ID id-AllowedNSSAI CRITICALITY reject TYPE AllowedNSSAI PRESENCE optional }| + { ID id-SourceToTarget-AMFInformationReroute CRITICALITY ignore TYPE SourceToTarget-AMFInformationReroute PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- INTERFACE MANAGEMENT ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- NG Setup Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- NG SETUP REQUEST +-- +-- ************************************************************** + +NGSetupRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {NGSetupRequestIEs} }, + ... +} + +NGSetupRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-GlobalRANNodeID CRITICALITY reject TYPE GlobalRANNodeID PRESENCE mandatory }| + { ID id-RANNodeName CRITICALITY ignore TYPE RANNodeName PRESENCE optional}| + { ID id-SupportedTAList CRITICALITY reject TYPE SupportedTAList PRESENCE mandatory }| + { ID id-DefaultPagingDRX CRITICALITY ignore TYPE PagingDRX PRESENCE mandatory }| + { ID id-UERetentionInformation CRITICALITY ignore TYPE UERetentionInformation PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- NG SETUP RESPONSE +-- +-- ************************************************************** + +NGSetupResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {NGSetupResponseIEs} }, + ... +} + +NGSetupResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMFName CRITICALITY reject TYPE AMFName PRESENCE mandatory }| + { ID id-ServedGUAMIList CRITICALITY reject TYPE ServedGUAMIList PRESENCE mandatory }| + { ID id-RelativeAMFCapacity CRITICALITY ignore TYPE RelativeAMFCapacity PRESENCE mandatory }| + { ID id-PLMNSupportList CRITICALITY reject TYPE PLMNSupportList PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }| + { ID id-UERetentionInformation CRITICALITY ignore TYPE UERetentionInformation PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- NG SETUP FAILURE +-- +-- ************************************************************** + +NGSetupFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {NGSetupFailureIEs} }, + ... +} + +NGSetupFailureIEs NGAP-PROTOCOL-IES ::= { + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- RAN Configuration Update Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- RAN CONFIGURATION UPDATE +-- +-- ************************************************************** + +RANConfigurationUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {RANConfigurationUpdateIEs} }, + ... +} + +RANConfigurationUpdateIEs NGAP-PROTOCOL-IES ::= { + { ID id-RANNodeName CRITICALITY ignore TYPE RANNodeName PRESENCE optional }| + { ID id-SupportedTAList CRITICALITY reject TYPE SupportedTAList PRESENCE optional }| + { ID id-DefaultPagingDRX CRITICALITY ignore TYPE PagingDRX PRESENCE optional }| + { ID id-GlobalRANNodeID CRITICALITY ignore TYPE GlobalRANNodeID PRESENCE optional }| + { ID id-NGRAN-TNLAssociationToRemoveList CRITICALITY reject TYPE NGRAN-TNLAssociationToRemoveList PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- RAN CONFIGURATION UPDATE ACKNOWLEDGE +-- +-- ************************************************************** + +RANConfigurationUpdateAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {RANConfigurationUpdateAcknowledgeIEs} }, + ... +} + +RANConfigurationUpdateAcknowledgeIEs NGAP-PROTOCOL-IES ::= { + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- RAN CONFIGURATION UPDATE FAILURE +-- +-- ************************************************************** + +RANConfigurationUpdateFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {RANConfigurationUpdateFailureIEs} }, + ... +} + +RANConfigurationUpdateFailureIEs NGAP-PROTOCOL-IES ::= { + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, +... +} + +-- ************************************************************** +-- +-- AMF Configuration Update Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- AMF CONFIGURATION UPDATE +-- +-- ************************************************************** + +AMFConfigurationUpdate ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {AMFConfigurationUpdateIEs} }, + ... +} + +AMFConfigurationUpdateIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMFName CRITICALITY reject TYPE AMFName PRESENCE optional }| + { ID id-ServedGUAMIList CRITICALITY reject TYPE ServedGUAMIList PRESENCE optional }| + { ID id-RelativeAMFCapacity CRITICALITY ignore TYPE RelativeAMFCapacity PRESENCE optional }| + { ID id-PLMNSupportList CRITICALITY reject TYPE PLMNSupportList PRESENCE optional }| + { ID id-AMF-TNLAssociationToAddList CRITICALITY ignore TYPE AMF-TNLAssociationToAddList PRESENCE optional }| + { ID id-AMF-TNLAssociationToRemoveList CRITICALITY ignore TYPE AMF-TNLAssociationToRemoveList PRESENCE optional }| + { ID id-AMF-TNLAssociationToUpdateList CRITICALITY ignore TYPE AMF-TNLAssociationToUpdateList PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- AMF CONFIGURATION UPDATE ACKNOWLEDGE +-- +-- ************************************************************** + +AMFConfigurationUpdateAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {AMFConfigurationUpdateAcknowledgeIEs} }, + ... +} + +AMFConfigurationUpdateAcknowledgeIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-TNLAssociationSetupList CRITICALITY ignore TYPE AMF-TNLAssociationSetupList PRESENCE optional }| + { ID id-AMF-TNLAssociationFailedToSetupList CRITICALITY ignore TYPE TNLAssociationList PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- AMF CONFIGURATION UPDATE FAILURE +-- +-- ************************************************************** + +AMFConfigurationUpdateFailure ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {AMFConfigurationUpdateFailureIEs} }, + ... +} + +AMFConfigurationUpdateFailureIEs NGAP-PROTOCOL-IES ::= { + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-TimeToWait CRITICALITY ignore TYPE TimeToWait PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- AMF Status Indication Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- AMF STATUS INDICATION +-- +-- ************************************************************** + +AMFStatusIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {AMFStatusIndicationIEs} }, + ... +} + +AMFStatusIndicationIEs NGAP-PROTOCOL-IES ::= { + { ID id-UnavailableGUAMIList CRITICALITY reject TYPE UnavailableGUAMIList PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- NG Reset Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- NG RESET +-- +-- ************************************************************** + +NGReset ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {NGResetIEs} }, + ... +} + +NGResetIEs NGAP-PROTOCOL-IES ::= { + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }| + { ID id-ResetType CRITICALITY reject TYPE ResetType PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- NG RESET ACKNOWLEDGE +-- +-- ************************************************************** + +NGResetAcknowledge ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {NGResetAcknowledgeIEs} }, + ... +} + +NGResetAcknowledgeIEs NGAP-PROTOCOL-IES ::= { + { ID id-UE-associatedLogicalNG-connectionList CRITICALITY ignore TYPE UE-associatedLogicalNG-connectionList PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- Error Indication Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- ERROR INDICATION +-- +-- ************************************************************** + +ErrorIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {ErrorIndicationIEs} }, + ... +} + +ErrorIndicationIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE optional }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE optional }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- OVERLOAD START +-- +-- ************************************************************** + +OverloadStart ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {OverloadStartIEs} }, + ... +} + +OverloadStartIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMFOverloadResponse CRITICALITY reject TYPE OverloadResponse PRESENCE optional }| + { ID id-AMFTrafficLoadReductionIndication CRITICALITY ignore TYPE TrafficLoadReductionIndication PRESENCE optional }| + { ID id-OverloadStartNSSAIList CRITICALITY ignore TYPE OverloadStartNSSAIList PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- OVERLOAD STOP +-- +-- ************************************************************** + +OverloadStop ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {OverloadStopIEs} }, + ... +} + +OverloadStopIEs NGAP-PROTOCOL-IES ::= { + ... +} + +-- ************************************************************** +-- +-- CONFIGURATION TRANSFER ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UPLINK RAN CONFIGURATION TRANSFER +-- +-- ************************************************************** + +UplinkRANConfigurationTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UplinkRANConfigurationTransferIEs} }, + ... +} + +UplinkRANConfigurationTransferIEs NGAP-PROTOCOL-IES ::= { + { ID id-SONConfigurationTransferUL CRITICALITY ignore TYPE SONConfigurationTransfer PRESENCE optional }| + { ID id-ENDC-SONConfigurationTransferUL CRITICALITY ignore TYPE EN-DCSONConfigurationTransfer PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- DOWNLINK RAN CONFIGURATION TRANSFER +-- +-- ************************************************************** + +DownlinkRANConfigurationTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {DownlinkRANConfigurationTransferIEs} }, + ... +} + +DownlinkRANConfigurationTransferIEs NGAP-PROTOCOL-IES ::= { + { ID id-SONConfigurationTransferDL CRITICALITY ignore TYPE SONConfigurationTransfer PRESENCE optional }| + { ID id-ENDC-SONConfigurationTransferDL CRITICALITY ignore TYPE EN-DCSONConfigurationTransfer PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- WARNING MESSAGE TRANSMISSION ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- Write-Replace Warning Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- WRITE-REPLACE WARNING REQUEST +-- +-- ************************************************************** + +WriteReplaceWarningRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {WriteReplaceWarningRequestIEs} }, + ... +} + +WriteReplaceWarningRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-MessageIdentifier CRITICALITY reject TYPE MessageIdentifier PRESENCE mandatory }| + { ID id-SerialNumber CRITICALITY reject TYPE SerialNumber PRESENCE mandatory }| + { ID id-WarningAreaList CRITICALITY ignore TYPE WarningAreaList PRESENCE optional }| + { ID id-RepetitionPeriod CRITICALITY reject TYPE RepetitionPeriod PRESENCE mandatory }| + { ID id-NumberOfBroadcastsRequested CRITICALITY reject TYPE NumberOfBroadcastsRequested PRESENCE mandatory }| + { ID id-WarningType CRITICALITY ignore TYPE WarningType PRESENCE optional }| + { ID id-WarningSecurityInfo CRITICALITY ignore TYPE WarningSecurityInfo PRESENCE optional }| + { ID id-DataCodingScheme CRITICALITY ignore TYPE DataCodingScheme PRESENCE optional }| + { ID id-WarningMessageContents CRITICALITY ignore TYPE WarningMessageContents PRESENCE optional }| + { ID id-ConcurrentWarningMessageInd CRITICALITY reject TYPE ConcurrentWarningMessageInd PRESENCE optional }| + { ID id-WarningAreaCoordinates CRITICALITY ignore TYPE WarningAreaCoordinates PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- WRITE-REPLACE WARNING RESPONSE +-- +-- ************************************************************** + +WriteReplaceWarningResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {WriteReplaceWarningResponseIEs} }, + ... +} + +WriteReplaceWarningResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-MessageIdentifier CRITICALITY reject TYPE MessageIdentifier PRESENCE mandatory }| + { ID id-SerialNumber CRITICALITY reject TYPE SerialNumber PRESENCE mandatory }| + { ID id-BroadcastCompletedAreaList CRITICALITY ignore TYPE BroadcastCompletedAreaList PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PWS Cancel Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS CANCEL REQUEST +-- +-- ************************************************************** + +PWSCancelRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PWSCancelRequestIEs} }, + ... +} + +PWSCancelRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-MessageIdentifier CRITICALITY reject TYPE MessageIdentifier PRESENCE mandatory }| + { ID id-SerialNumber CRITICALITY reject TYPE SerialNumber PRESENCE mandatory }| + { ID id-WarningAreaList CRITICALITY ignore TYPE WarningAreaList PRESENCE optional }| + { ID id-CancelAllWarningMessages CRITICALITY reject TYPE CancelAllWarningMessages PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PWS CANCEL RESPONSE +-- +-- ************************************************************** + +PWSCancelResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PWSCancelResponseIEs} }, + ... +} + +PWSCancelResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-MessageIdentifier CRITICALITY reject TYPE MessageIdentifier PRESENCE mandatory }| + { ID id-SerialNumber CRITICALITY reject TYPE SerialNumber PRESENCE mandatory }| + { ID id-BroadcastCancelledAreaList CRITICALITY ignore TYPE BroadcastCancelledAreaList PRESENCE optional }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PWS Restart Indication Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS RESTART INDICATION +-- +-- ************************************************************** + +PWSRestartIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PWSRestartIndicationIEs} }, + ... +} + +PWSRestartIndicationIEs NGAP-PROTOCOL-IES ::= { + { ID id-CellIDListForRestart CRITICALITY reject TYPE CellIDListForRestart PRESENCE mandatory }| + { ID id-GlobalRANNodeID CRITICALITY reject TYPE GlobalRANNodeID PRESENCE mandatory }| + { ID id-TAIListForRestart CRITICALITY reject TYPE TAIListForRestart PRESENCE mandatory }| + { ID id-EmergencyAreaIDListForRestart CRITICALITY reject TYPE EmergencyAreaIDListForRestart PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PWS Failure Indication Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PWS FAILURE INDICATION +-- +-- ************************************************************** + +PWSFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PWSFailureIndicationIEs} }, + ... +} + +PWSFailureIndicationIEs NGAP-PROTOCOL-IES ::= { + { ID id-PWSFailedCellIDList CRITICALITY reject TYPE PWSFailedCellIDList PRESENCE mandatory }| + { ID id-GlobalRANNodeID CRITICALITY reject TYPE GlobalRANNodeID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- NRPPA TRANSPORT ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- DOWNLINK UE ASSOCIATED NRPPA TRANSPORT +-- +-- ************************************************************** + +DownlinkUEAssociatedNRPPaTransport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {DownlinkUEAssociatedNRPPaTransportIEs} }, + ... +} + +DownlinkUEAssociatedNRPPaTransportIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RoutingID CRITICALITY reject TYPE RoutingID PRESENCE mandatory }| + { ID id-NRPPa-PDU CRITICALITY reject TYPE NRPPa-PDU PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UPLINK UE ASSOCIATED NRPPA TRANSPORT +-- +-- ************************************************************** + +UplinkUEAssociatedNRPPaTransport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UplinkUEAssociatedNRPPaTransportIEs} }, + ... +} + +UplinkUEAssociatedNRPPaTransportIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RoutingID CRITICALITY reject TYPE RoutingID PRESENCE mandatory }| + { ID id-NRPPa-PDU CRITICALITY reject TYPE NRPPa-PDU PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- DOWNLINK NON UE ASSOCIATED NRPPA TRANSPORT +-- +-- ************************************************************** + +DownlinkNonUEAssociatedNRPPaTransport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {DownlinkNonUEAssociatedNRPPaTransportIEs} }, + ... +} + +DownlinkNonUEAssociatedNRPPaTransportIEs NGAP-PROTOCOL-IES ::= { + { ID id-RoutingID CRITICALITY reject TYPE RoutingID PRESENCE mandatory }| + { ID id-NRPPa-PDU CRITICALITY reject TYPE NRPPa-PDU PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UPLINK NON UE ASSOCIATED NRPPA TRANSPORT +-- +-- ************************************************************** + +UplinkNonUEAssociatedNRPPaTransport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UplinkNonUEAssociatedNRPPaTransportIEs} }, + ... +} + +UplinkNonUEAssociatedNRPPaTransportIEs NGAP-PROTOCOL-IES ::= { + { ID id-RoutingID CRITICALITY reject TYPE RoutingID PRESENCE mandatory }| + { ID id-NRPPa-PDU CRITICALITY reject TYPE NRPPa-PDU PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- TRACE ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- TRACE START +-- +-- ************************************************************** + +TraceStart ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {TraceStartIEs} }, + ... +} + +TraceStartIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-TraceActivation CRITICALITY ignore TYPE TraceActivation PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- TRACE FAILURE INDICATION +-- +-- ************************************************************** + +TraceFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {TraceFailureIndicationIEs} }, + ... +} + +TraceFailureIndicationIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-NGRANTraceID CRITICALITY ignore TYPE NGRANTraceID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- DEACTIVATE TRACE +-- +-- ************************************************************** + +DeactivateTrace ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {DeactivateTraceIEs} }, + ... +} + +DeactivateTraceIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-NGRANTraceID CRITICALITY ignore TYPE NGRANTraceID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- CELL TRAFFIC TRACE +-- +-- ************************************************************** + +CellTrafficTrace ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {CellTrafficTraceIEs} }, + ... +} + +CellTrafficTraceIEs NGAP-PROTOCOL-IES ::= { + {ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + {ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + {ID id-NGRANTraceID CRITICALITY ignore TYPE NGRANTraceID PRESENCE mandatory }| + {ID id-NGRAN-CGI CRITICALITY ignore TYPE NGRAN-CGI PRESENCE mandatory }| + {ID id-TraceCollectionEntityIPAddress CRITICALITY ignore TYPE TransportLayerAddress PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- LOCATION REPORTING ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- LOCATION REPORTING CONTROL +-- +-- ************************************************************** + +LocationReportingControl ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {LocationReportingControlIEs} }, + ... +} + +LocationReportingControlIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-LocationReportingRequestType CRITICALITY ignore TYPE LocationReportingRequestType PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- LOCATION REPORTING FAILURE INDICATION +-- +-- ************************************************************** + +LocationReportingFailureIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {LocationReportingFailureIndicationIEs} }, + ... +} + +LocationReportingFailureIndicationIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- LOCATION REPORT +-- +-- ************************************************************** + +LocationReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {LocationReportIEs} }, + ... +} + +LocationReportIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE mandatory }| + { ID id-UEPresenceInAreaOfInterestList CRITICALITY ignore TYPE UEPresenceInAreaOfInterestList PRESENCE optional }| + { ID id-LocationReportingRequestType CRITICALITY ignore TYPE LocationReportingRequestType PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE TNLA BINDING ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE TNLA BINDING RELEASE REQUEST +-- +-- ************************************************************** + +UETNLABindingReleaseRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UETNLABindingReleaseRequestIEs} }, + ... +} + +UETNLABindingReleaseRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }, + ... +} + +-- ************************************************************** +-- +-- UE RADIO CAPABILITY MANAGEMENT ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE RADIO CAPABILITY INFO INDICATION +-- +-- ************************************************************** + +UERadioCapabilityInfoIndication ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UERadioCapabilityInfoIndicationIEs} }, + ... +} + +UERadioCapabilityInfoIndicationIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-UERadioCapability CRITICALITY ignore TYPE UERadioCapability PRESENCE mandatory }| + { ID id-UERadioCapabilityForPaging CRITICALITY ignore TYPE UERadioCapabilityForPaging PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE Radio Capability Check Elementary Procedure +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- UE RADIO CAPABILITY CHECK REQUEST +-- +-- ************************************************************** + +UERadioCapabilityCheckRequest ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UERadioCapabilityCheckRequestIEs} }, + ... +} + +UERadioCapabilityCheckRequestIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY reject TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY reject TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-UERadioCapability CRITICALITY ignore TYPE UERadioCapability PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- UE RADIO CAPABILITY CHECK RESPONSE +-- +-- ************************************************************** + +UERadioCapabilityCheckResponse ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {UERadioCapabilityCheckResponseIEs} }, + ... +} + +UERadioCapabilityCheckResponseIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-IMSVoiceSupportIndicator CRITICALITY reject TYPE IMSVoiceSupportIndicator PRESENCE mandatory }| + { ID id-CriticalityDiagnostics CRITICALITY ignore TYPE CriticalityDiagnostics PRESENCE optional }, + ... +} + +-- ************************************************************** +-- +-- PRIVATE MESSAGE ELEMENTARY PROCEDURE +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- PRIVATE MESSAGE +-- +-- ************************************************************** + +PrivateMessage ::= SEQUENCE { + privateIEs PrivateIE-Container { { PrivateMessageIEs } }, + ... +} + +PrivateMessageIEs NGAP-PRIVATE-IES ::= { + ... +} + + +-- ************************************************************** +-- +-- DATA USAGE REPORTING ELEMENTARY PROCEDURES +-- +-- ************************************************************** + +-- ************************************************************** +-- +-- SECONDARY RAT DATA USAGE REPORT +-- +-- ************************************************************** + +SecondaryRATDataUsageReport ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {SecondaryRATDataUsageReportIEs} }, + ... +} + +SecondaryRATDataUsageReportIEs NGAP-PROTOCOL-IES ::= { + { ID id-AMF-UE-NGAP-ID CRITICALITY ignore TYPE AMF-UE-NGAP-ID PRESENCE mandatory }| + { ID id-RAN-UE-NGAP-ID CRITICALITY ignore TYPE RAN-UE-NGAP-ID PRESENCE mandatory }| + { ID id-PDUSessionResourceSecondaryRATUsageList CRITICALITY ignore TYPE PDUSessionResourceSecondaryRATUsageList PRESENCE mandatory }| + { ID id-HandoverFlag CRITICALITY ignore TYPE HandoverFlag PRESENCE optional }| + { ID id-UserLocationInformation CRITICALITY ignore TYPE UserLocationInformation PRESENCE optional }, + ... +} + + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- Information Element Definitions +-- +-- ************************************************************** + +NGAP-IEs { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-Access (22) modules (3) ngap (1) version1 (1) ngap-IEs (2) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + + id-AdditionalDLForwardingUPTNLInformation, + id-AdditionalULForwardingUPTNLInformation, + id-AdditionalDLQosFlowPerTNLInformation, + id-AdditionalDLUPTNLInformationForHOList, + id-AdditionalNGU-UP-TNLInformation, + id-AdditionalUL-NGU-UP-TNLInformation, + id-Cause, + id-CNTypeRestrictionsForEquivalent, + id-CNTypeRestrictionsForServing, + id-CommonNetworkInstance, + id-DataForwardingNotPossible, + id-DL-NGU-UP-TNLInformation, + id-EndpointIPAddressAndPort, + id-LastEUTRAN-PLMNIdentity, + id-LocationReportingAdditionalInfo, + id-MaximumIntegrityProtectedDataRate-DL, + id-NetworkInstance, + id-OldAssociatedQosFlowList-ULendmarkerexpected, + id-PDUSessionAggregateMaximumBitRate, + id-PDUSessionResourceFailedToSetupListCxtFail, + id-PDUSessionResourceReleaseResponseTransfer, + id-PDUSessionType, + id-PSCellInformation, + id-QosFlowAddOrModifyRequestList, + id-QosFlowSetupRequestList, + id-QosFlowToReleaseList, + id-SCTP-TLAs, + id-SecondaryRATUsageInformation, + id-SecurityIndication, + id-SecurityResult, + id-S-NSSAI, + id-TNLAssociationTransportLayerAddressNGRAN, + id-UL-NGU-UP-TNLInformation, + id-UL-NGU-UP-TNLModifyList, + id-ULForwarding, + id-ULForwardingUP-TNLInformation, + maxnoofAllowedAreas, + maxnoofAllowedS-NSSAIs, + maxnoofBPLMNs, + maxnoofCellIDforWarning, + maxnoofCellinAoI, + maxnoofCellinEAI, + maxnoofCellsingNB, + maxnoofCellsinngeNB, + maxnoofCellinTAI, + maxnoofCellsinUEHistoryInfo, + maxnoofCellsUEMovingTrajectory, + maxnoofDRBs, + maxnoofEmergencyAreaID, + maxnoofEAIforRestart, + maxnoofEPLMNs, + maxnoofEPLMNsPlusOne, + maxnoofE-RABs, + maxnoofErrors, + maxnoofForbTACs, + maxnoofMultiConnectivity, + maxnoofMultiConnectivityMinusOne, + maxnoofNGConnectionsToReset, + maxnoofPDUSessions, + maxnoofPLMNs, + maxnoofQosFlows, + maxnoofRANNodeinAoI, + maxnoofRecommendedCells, + maxnoofRecommendedRANNodes, + maxnoofAoI, + maxnoofServedGUAMIs, + maxnoofSliceItems, + maxnoofTACs, + maxnoofTAIforInactive, + maxnoofTAIforPaging, + maxnoofTAIforRestart, + maxnoofTAIforWarning, + maxnoofTAIinAoI, + maxnoofTimePeriods, + maxnoofTNLAssociations, + maxnoofXnExtTLAs, + maxnoofXnGTP-TLAs, + maxnoofXnTLAs + +FROM NGAP-Constants + + Criticality, + ProcedureCode, + ProtocolIE-ID, + TriggeringMessage +FROM NGAP-CommonDataTypes + + ProtocolExtensionContainer{}, + ProtocolIE-Container{}, + NGAP-PROTOCOL-EXTENSION, + ProtocolIE-SingleContainer{}, + NGAP-PROTOCOL-IES +FROM NGAP-Containers; + +-- A + +AdditionalDLUPTNLInformationForHOList ::= SEQUENCE (SIZE(1..maxnoofMultiConnectivityMinusOne)) OF AdditionalDLUPTNLInformationForHOItem + +AdditionalDLUPTNLInformationForHOItem ::= SEQUENCE { + additionalDL-NGU-UP-TNLInformation UPTransportLayerInformation, + additionalQosFlowSetupResponseList QosFlowListWithDataForwarding, + additionalDLForwardingUPTNLInformation UPTransportLayerInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { AdditionalDLUPTNLInformationForHOItem-ExtIEs} } OPTIONAL, + ... +} + +AdditionalDLUPTNLInformationForHOItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AdditionalQosFlowInformation ::= ENUMERATED { + more-likely, + ... +} + +AllocationAndRetentionPriority ::= SEQUENCE { + priorityLevelARP PriorityLevelARP, + pre-emptionCapability Pre-emptionCapability, + pre-emptionVulnerability Pre-emptionVulnerability, + iE-Extensions ProtocolExtensionContainer { {AllocationAndRetentionPriority-ExtIEs} } OPTIONAL, + ... +} + +AllocationAndRetentionPriority-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AllowedNSSAI ::= SEQUENCE (SIZE(1..maxnoofAllowedS-NSSAIs)) OF AllowedNSSAI-Item + +AllowedNSSAI-Item ::= SEQUENCE { + s-NSSAI S-NSSAI, + iE-Extensions ProtocolExtensionContainer { {AllowedNSSAI-Item-ExtIEs} } OPTIONAL, + ... +} + +AllowedNSSAI-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AllowedTACs ::= SEQUENCE (SIZE(1..maxnoofAllowedAreas)) OF TAC + +AMFName ::= PrintableString (SIZE(1..150, ...)) + +AMFPagingTarget ::= CHOICE { + globalRANNodeID GlobalRANNodeID, + tAI TAI, + choice-Extensions ProtocolIE-SingleContainer { {AMFPagingTarget-ExtIEs} } +} + +AMFPagingTarget-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +AMFPointer ::= BIT STRING (SIZE(6)) + +AMFRegionID ::= BIT STRING (SIZE(8)) + +AMFSetID ::= BIT STRING (SIZE(10)) + +AMF-TNLAssociationSetupList ::= SEQUENCE (SIZE(1..maxnoofTNLAssociations)) OF AMF-TNLAssociationSetupItem + +AMF-TNLAssociationSetupItem ::= SEQUENCE { + aMF-TNLAssociationAddress CPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { {AMF-TNLAssociationSetupItem-ExtIEs} } OPTIONAL, + ... +} + +AMF-TNLAssociationSetupItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AMF-TNLAssociationToAddList ::= SEQUENCE (SIZE(1..maxnoofTNLAssociations)) OF AMF-TNLAssociationToAddItem + +AMF-TNLAssociationToAddItem ::= SEQUENCE { + aMF-TNLAssociationAddress CPTransportLayerInformation, + tNLAssociationUsage TNLAssociationUsage OPTIONAL, + tNLAddressWeightFactor TNLAddressWeightFactor, + iE-Extensions ProtocolExtensionContainer { {AMF-TNLAssociationToAddItem-ExtIEs} } OPTIONAL, + ... +} + +AMF-TNLAssociationToAddItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AMF-TNLAssociationToRemoveList ::= SEQUENCE (SIZE(1..maxnoofTNLAssociations)) OF AMF-TNLAssociationToRemoveItem + +AMF-TNLAssociationToRemoveItem ::= SEQUENCE { + aMF-TNLAssociationAddress CPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { {AMF-TNLAssociationToRemoveItem-ExtIEs} } OPTIONAL, + ... +} + +AMF-TNLAssociationToRemoveItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + {ID id-TNLAssociationTransportLayerAddressNGRAN CRITICALITY reject EXTENSION CPTransportLayerInformation PRESENCE optional}, + ... +} + +AMF-TNLAssociationToUpdateList ::= SEQUENCE (SIZE(1..maxnoofTNLAssociations)) OF AMF-TNLAssociationToUpdateItem + +AMF-TNLAssociationToUpdateItem ::= SEQUENCE { + aMF-TNLAssociationAddress CPTransportLayerInformation, + tNLAssociationUsage TNLAssociationUsage OPTIONAL, + tNLAddressWeightFactor TNLAddressWeightFactor OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {AMF-TNLAssociationToUpdateItem-ExtIEs} } OPTIONAL, + ... +} + +AMF-TNLAssociationToUpdateItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AMF-UE-NGAP-ID ::= INTEGER (0..1099511627775) + +AreaOfInterest ::= SEQUENCE { + areaOfInterestTAIList AreaOfInterestTAIList OPTIONAL, + areaOfInterestCellList AreaOfInterestCellList OPTIONAL, + areaOfInterestRANNodeList AreaOfInterestRANNodeList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {AreaOfInterest-ExtIEs} } OPTIONAL, + ... +} + +AreaOfInterest-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AreaOfInterestCellList ::= SEQUENCE (SIZE(1..maxnoofCellinAoI)) OF AreaOfInterestCellItem + +AreaOfInterestCellItem ::= SEQUENCE { + nGRAN-CGI NGRAN-CGI, + iE-Extensions ProtocolExtensionContainer { {AreaOfInterestCellItem-ExtIEs} } OPTIONAL, + ... +} + +AreaOfInterestCellItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AreaOfInterestList ::= SEQUENCE (SIZE(1..maxnoofAoI)) OF AreaOfInterestItem + +AreaOfInterestItem ::= SEQUENCE { + areaOfInterest AreaOfInterest, + locationReportingReferenceID LocationReportingReferenceID, + iE-Extensions ProtocolExtensionContainer { {AreaOfInterestItem-ExtIEs} } OPTIONAL, + ... +} + +AreaOfInterestItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AreaOfInterestRANNodeList ::= SEQUENCE (SIZE(1..maxnoofRANNodeinAoI)) OF AreaOfInterestRANNodeItem + +AreaOfInterestRANNodeItem ::= SEQUENCE { + globalRANNodeID GlobalRANNodeID, + iE-Extensions ProtocolExtensionContainer { {AreaOfInterestRANNodeItem-ExtIEs} } OPTIONAL, + ... +} + +AreaOfInterestRANNodeItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AreaOfInterestTAIList ::= SEQUENCE (SIZE(1..maxnoofTAIinAoI)) OF AreaOfInterestTAIItem + +AreaOfInterestTAIItem ::= SEQUENCE { + tAI TAI, + iE-Extensions ProtocolExtensionContainer { {AreaOfInterestTAIItem-ExtIEs} } OPTIONAL, + ... +} + +AreaOfInterestTAIItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AssistanceDataForPaging ::= SEQUENCE { + assistanceDataForRecommendedCells AssistanceDataForRecommendedCells OPTIONAL, + pagingAttemptInformation PagingAttemptInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {AssistanceDataForPaging-ExtIEs} } OPTIONAL, + ... +} + +AssistanceDataForPaging-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AssistanceDataForRecommendedCells ::= SEQUENCE { + recommendedCellsForPaging RecommendedCellsForPaging, + iE-Extensions ProtocolExtensionContainer { {AssistanceDataForRecommendedCells-ExtIEs} } OPTIONAL, + ... +} + +AssistanceDataForRecommendedCells-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AssociatedQosFlowList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF AssociatedQosFlowItem + +AssociatedQosFlowItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + qosFlowMappingIndication ENUMERATED {ul, dl, ...} OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {AssociatedQosFlowItem-ExtIEs} } OPTIONAL, + ... +} + +AssociatedQosFlowItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +AveragingWindow ::= INTEGER (0..4095, ...) + +-- B + +BitRate ::= INTEGER (0..4000000000000, ...) + +BroadcastCancelledAreaList ::= CHOICE { + cellIDCancelledEUTRA CellIDCancelledEUTRA, + tAICancelledEUTRA TAICancelledEUTRA, + emergencyAreaIDCancelledEUTRA EmergencyAreaIDCancelledEUTRA, + cellIDCancelledNR CellIDCancelledNR, + tAICancelledNR TAICancelledNR, + emergencyAreaIDCancelledNR EmergencyAreaIDCancelledNR, + choice-Extensions ProtocolIE-SingleContainer { {BroadcastCancelledAreaList-ExtIEs} } +} + +BroadcastCancelledAreaList-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +BroadcastCompletedAreaList ::= CHOICE { + cellIDBroadcastEUTRA CellIDBroadcastEUTRA, + tAIBroadcastEUTRA TAIBroadcastEUTRA, + emergencyAreaIDBroadcastEUTRA EmergencyAreaIDBroadcastEUTRA, + cellIDBroadcastNR CellIDBroadcastNR, + tAIBroadcastNR TAIBroadcastNR, + emergencyAreaIDBroadcastNR EmergencyAreaIDBroadcastNR, + choice-Extensions ProtocolIE-SingleContainer { {BroadcastCompletedAreaList-ExtIEs} } +} + +BroadcastCompletedAreaList-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +BroadcastPLMNList ::= SEQUENCE (SIZE(1..maxnoofBPLMNs)) OF BroadcastPLMNItem + +BroadcastPLMNItem ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + tAISliceSupportList SliceSupportList, + iE-Extensions ProtocolExtensionContainer { {BroadcastPLMNItem-ExtIEs} } OPTIONAL, + ... +} + +BroadcastPLMNItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- C + +CancelAllWarningMessages ::= ENUMERATED { + true, + ... +} + +CancelledCellsInEAI-EUTRA ::= SEQUENCE (SIZE(1..maxnoofCellinEAI)) OF CancelledCellsInEAI-EUTRA-Item + +CancelledCellsInEAI-EUTRA-Item ::= SEQUENCE { + eUTRA-CGI EUTRA-CGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { {CancelledCellsInEAI-EUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +CancelledCellsInEAI-EUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CancelledCellsInEAI-NR ::= SEQUENCE (SIZE(1..maxnoofCellinEAI)) OF CancelledCellsInEAI-NR-Item + +CancelledCellsInEAI-NR-Item ::= SEQUENCE { + nR-CGI NR-CGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { {CancelledCellsInEAI-NR-Item-ExtIEs} } OPTIONAL, + ... +} + +CancelledCellsInEAI-NR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CancelledCellsInTAI-EUTRA ::= SEQUENCE (SIZE(1..maxnoofCellinTAI)) OF CancelledCellsInTAI-EUTRA-Item + +CancelledCellsInTAI-EUTRA-Item ::= SEQUENCE { + eUTRA-CGI EUTRA-CGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { {CancelledCellsInTAI-EUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +CancelledCellsInTAI-EUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CancelledCellsInTAI-NR ::= SEQUENCE (SIZE(1..maxnoofCellinTAI)) OF CancelledCellsInTAI-NR-Item + +CancelledCellsInTAI-NR-Item ::= SEQUENCE{ + nR-CGI NR-CGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { {CancelledCellsInTAI-NR-Item-ExtIEs} } OPTIONAL, + ... +} + +CancelledCellsInTAI-NR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +Cause ::= CHOICE { + radioNetwork CauseRadioNetwork, + transport CauseTransport, + nas CauseNas, + protocol CauseProtocol, + misc CauseMisc, + choice-Extensions ProtocolIE-SingleContainer { {Cause-ExtIEs} } +} + +Cause-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +CauseMisc ::= ENUMERATED { + control-processing-overload, + not-enough-user-plane-processing-resources, + hardware-failure, + om-intervention, + unknown-PLMN, + unspecified, + ... +} + +CauseNas ::= ENUMERATED { + normal-release, + authentication-failure, + deregister, + unspecified, + ... +} + +CauseProtocol ::= ENUMERATED { + transfer-syntax-error, + abstract-syntax-error-reject, + abstract-syntax-error-ignore-and-notify, + message-not-compatible-with-receiver-state, + semantic-error, + abstract-syntax-error-falsely-constructed-message, + unspecified, + ... +} + +CauseRadioNetwork ::= ENUMERATED { + unspecified, + txnrelocoverall-expiry, + successful-handover, + release-due-to-ngran-generated-reason, + release-due-to-5gc-generated-reason, + handover-cancelled, + partial-handover, + ho-failure-in-target-5GC-ngran-node-or-target-system, + ho-target-not-allowed, + tngrelocoverall-expiry, + tngrelocprep-expiry, + cell-not-available, + unknown-targetID, + no-radio-resources-available-in-target-cell, + unknown-local-UE-NGAP-ID, + inconsistent-remote-UE-NGAP-ID, + handover-desirable-for-radio-reason, + time-critical-handover, + resource-optimisation-handover, + reduce-load-in-serving-cell, + user-inactivity, + radio-connection-with-ue-lost, + radio-resources-not-available, + invalid-qos-combination, + failure-in-radio-interface-procedure, + interaction-with-other-procedure, + unknown-PDU-session-ID, + unkown-qos-flow-ID, + multiple-PDU-session-ID-instances, + multiple-qos-flow-ID-instances, + encryption-and-or-integrity-protection-algorithms-not-supported, + ng-intra-system-handover-triggered, + ng-inter-system-handover-triggered, + xn-handover-triggered, + not-supported-5QI-value, + ue-context-transfer, + ims-voice-eps-fallback-or-rat-fallback-triggered, + up-integrity-protection-not-possible, + up-confidentiality-protection-not-possible, + slice-not-supported, + ue-in-rrc-inactive-state-not-reachable, + redirection, + resources-not-available-for-the-slice, + ue-max-integrity-protected-data-rate-reason, + release-due-to-cn-detected-mobility, + ..., + n26-interface-not-available, + release-due-to-pre-emption, + multiple-location-reporting-reference-ID-instances +} + +CauseTransport ::= ENUMERATED { + transport-resource-unavailable, + unspecified, + ... +} + +CellIDBroadcastEUTRA ::= SEQUENCE (SIZE(1..maxnoofCellIDforWarning)) OF CellIDBroadcastEUTRA-Item + +CellIDBroadcastEUTRA-Item ::= SEQUENCE { + eUTRA-CGI EUTRA-CGI, + iE-Extensions ProtocolExtensionContainer { {CellIDBroadcastEUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +CellIDBroadcastEUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CellIDBroadcastNR ::= SEQUENCE (SIZE(1..maxnoofCellIDforWarning)) OF CellIDBroadcastNR-Item + +CellIDBroadcastNR-Item ::= SEQUENCE { + nR-CGI NR-CGI, + iE-Extensions ProtocolExtensionContainer { {CellIDBroadcastNR-Item-ExtIEs} } OPTIONAL, + ... +} + +CellIDBroadcastNR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CellIDCancelledEUTRA ::= SEQUENCE (SIZE(1..maxnoofCellIDforWarning)) OF CellIDCancelledEUTRA-Item + +CellIDCancelledEUTRA-Item ::= SEQUENCE { + eUTRA-CGI EUTRA-CGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { {CellIDCancelledEUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +CellIDCancelledEUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CellIDCancelledNR ::= SEQUENCE (SIZE(1..maxnoofCellIDforWarning)) OF CellIDCancelledNR-Item + +CellIDCancelledNR-Item ::= SEQUENCE { + nR-CGI NR-CGI, + numberOfBroadcasts NumberOfBroadcasts, + iE-Extensions ProtocolExtensionContainer { {CellIDCancelledNR-Item-ExtIEs} } OPTIONAL, + ... +} + +CellIDCancelledNR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CellIDListForRestart ::= CHOICE { + eUTRA-CGIListforRestart EUTRA-CGIList, + nR-CGIListforRestart NR-CGIList, + choice-Extensions ProtocolIE-SingleContainer { {CellIDListForRestart-ExtIEs} } +} + +CellIDListForRestart-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +CellSize ::= ENUMERATED {verysmall, small, medium, large, ...} + + +CellType ::= SEQUENCE { + cellSize CellSize, + iE-Extensions ProtocolExtensionContainer { {CellType-ExtIEs} } OPTIONAL, + ... +} + +CellType-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CNAssistedRANTuning ::= SEQUENCE { + expectedUEBehaviour ExpectedUEBehaviour OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {CNAssistedRANTuning-ExtIEs} } OPTIONAL, + ... +} + +CNAssistedRANTuning-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CNTypeRestrictionsForEquivalent ::= SEQUENCE (SIZE(1..maxnoofEPLMNs)) OF CNTypeRestrictionsForEquivalentItem + +CNTypeRestrictionsForEquivalentItem ::= SEQUENCE { + plmnIdentity PLMNIdentity, + cn-Type ENUMERATED {epc-forbidden, fiveGC-forbidden, ...}, + iE-Extensions ProtocolExtensionContainer { {CNTypeRestrictionsForEquivalentItem-ExtIEs} } OPTIONAL, + ... +} + +CNTypeRestrictionsForEquivalentItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::={ + ... +} + +CNTypeRestrictionsForServing ::= ENUMERATED { + epc-forbidden, + ... +} + +CommonNetworkInstance ::= OCTET STRING + +CompletedCellsInEAI-EUTRA ::= SEQUENCE (SIZE(1..maxnoofCellinEAI)) OF CompletedCellsInEAI-EUTRA-Item + +CompletedCellsInEAI-EUTRA-Item ::= SEQUENCE { + eUTRA-CGI EUTRA-CGI, + iE-Extensions ProtocolExtensionContainer { {CompletedCellsInEAI-EUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +CompletedCellsInEAI-EUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CompletedCellsInEAI-NR ::= SEQUENCE (SIZE(1..maxnoofCellinEAI)) OF CompletedCellsInEAI-NR-Item + +CompletedCellsInEAI-NR-Item ::= SEQUENCE { + nR-CGI NR-CGI, + iE-Extensions ProtocolExtensionContainer { {CompletedCellsInEAI-NR-Item-ExtIEs} } OPTIONAL, + ... +} + +CompletedCellsInEAI-NR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CompletedCellsInTAI-EUTRA ::= SEQUENCE (SIZE(1..maxnoofCellinTAI)) OF CompletedCellsInTAI-EUTRA-Item + +CompletedCellsInTAI-EUTRA-Item ::= SEQUENCE{ + eUTRA-CGI EUTRA-CGI, + iE-Extensions ProtocolExtensionContainer { {CompletedCellsInTAI-EUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +CompletedCellsInTAI-EUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CompletedCellsInTAI-NR ::= SEQUENCE (SIZE(1..maxnoofCellinTAI)) OF CompletedCellsInTAI-NR-Item + +CompletedCellsInTAI-NR-Item ::= SEQUENCE{ + nR-CGI NR-CGI, + iE-Extensions ProtocolExtensionContainer { {CompletedCellsInTAI-NR-Item-ExtIEs} } OPTIONAL, + ... +} + +CompletedCellsInTAI-NR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +ConcurrentWarningMessageInd ::= ENUMERATED { + true, + ... +} + +ConfidentialityProtectionIndication ::= ENUMERATED { + required, + preferred, + not-needed, + ... +} + +ConfidentialityProtectionResult ::= ENUMERATED { + performed, + not-performed, + ... +} + +CoreNetworkAssistanceInformationForInactive ::= SEQUENCE { + uEIdentityIndexValue UEIdentityIndexValue, + uESpecificDRX PagingDRX OPTIONAL, + periodicRegistrationUpdateTimer PeriodicRegistrationUpdateTimer, + mICOModeIndication MICOModeIndication OPTIONAL, + tAIListForInactive TAIListForInactive, + expectedUEBehaviour ExpectedUEBehaviour OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {CoreNetworkAssistanceInformationForInactive-ExtIEs} } OPTIONAL, + ... +} + +CoreNetworkAssistanceInformationForInactive-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +COUNTValueForPDCP-SN12 ::= SEQUENCE { + pDCP-SN12 INTEGER (0..4095), + hFN-PDCP-SN12 INTEGER (0..1048575), + iE-Extensions ProtocolExtensionContainer { {COUNTValueForPDCP-SN12-ExtIEs} } OPTIONAL, + ... +} + +COUNTValueForPDCP-SN12-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +COUNTValueForPDCP-SN18 ::= SEQUENCE { + pDCP-SN18 INTEGER (0..262143), + hFN-PDCP-SN18 INTEGER (0..16383), + iE-Extensions ProtocolExtensionContainer { {COUNTValueForPDCP-SN18-ExtIEs} } OPTIONAL, + ... +} + +COUNTValueForPDCP-SN18-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CPTransportLayerInformation ::= CHOICE { + endpointIPAddress TransportLayerAddress, + choice-Extensions ProtocolIE-SingleContainer { {CPTransportLayerInformation-ExtIEs} } +} + +CPTransportLayerInformation-ExtIEs NGAP-PROTOCOL-IES ::= { + { ID id-EndpointIPAddressAndPort CRITICALITY reject TYPE EndpointIPAddressAndPort PRESENCE mandatory}, + ... +} + +CriticalityDiagnostics ::= SEQUENCE { + procedureCode ProcedureCode OPTIONAL, + triggeringMessage TriggeringMessage OPTIONAL, + procedureCriticality Criticality OPTIONAL, + iEsCriticalityDiagnostics CriticalityDiagnostics-IE-List OPTIONAL, + iE-Extensions ProtocolExtensionContainer {{CriticalityDiagnostics-ExtIEs}} OPTIONAL, + ... +} + +CriticalityDiagnostics-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +CriticalityDiagnostics-IE-List ::= SEQUENCE (SIZE(1..maxnoofErrors)) OF CriticalityDiagnostics-IE-Item + +CriticalityDiagnostics-IE-Item ::= SEQUENCE { + iECriticality Criticality, + iE-ID ProtocolIE-ID, + typeOfError TypeOfError, + iE-Extensions ProtocolExtensionContainer {{CriticalityDiagnostics-IE-Item-ExtIEs}} OPTIONAL, + ... +} + +CriticalityDiagnostics-IE-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- D + +DataCodingScheme ::= BIT STRING (SIZE(8)) + +DataForwardingAccepted ::= ENUMERATED { + data-forwarding-accepted, + ... +} + +DataForwardingNotPossible ::= ENUMERATED { + data-forwarding-not-possible, + ... +} + +DataForwardingResponseDRBList ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF DataForwardingResponseDRBItem + +DataForwardingResponseDRBItem ::= SEQUENCE { + dRB-ID DRB-ID, + dLForwardingUP-TNLInformation UPTransportLayerInformation OPTIONAL, + uLForwardingUP-TNLInformation UPTransportLayerInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer {{DataForwardingResponseDRBItem-ExtIEs}} OPTIONAL, + ... +} + +DataForwardingResponseDRBItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +DelayCritical ::= ENUMERATED { + delay-critical, + non-delay-critical, + ... +} + +DLForwarding ::= ENUMERATED { + dl-forwarding-proposed, + ... +} + +DL-NGU-TNLInformationReused ::= ENUMERATED { + true, + ... +} + +DirectForwardingPathAvailability ::= ENUMERATED { + direct-path-available, + ... +} + +DRB-ID ::= INTEGER (1..32, ...) + +DRBsSubjectToStatusTransferList ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF DRBsSubjectToStatusTransferItem + +DRBsSubjectToStatusTransferItem ::= SEQUENCE { + dRB-ID DRB-ID, + dRBStatusUL DRBStatusUL, + dRBStatusDL DRBStatusDL, + iE-Extension ProtocolExtensionContainer { {DRBsSubjectToStatusTransferItem-ExtIEs} } OPTIONAL, + ... +} + +DRBsSubjectToStatusTransferItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-OldAssociatedQosFlowList-ULendmarkerexpected CRITICALITY reject EXTENSION AssociatedQosFlowList PRESENCE optional }, + ... +} + +DRBStatusDL ::= CHOICE { + dRBStatusDL12 DRBStatusDL12, + dRBStatusDL18 DRBStatusDL18, + choice-Extensions ProtocolIE-SingleContainer { {DRBStatusDL-ExtIEs} } +} + +DRBStatusDL-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +DRBStatusDL12 ::= SEQUENCE { + dL-COUNTValue COUNTValueForPDCP-SN12, + iE-Extension ProtocolExtensionContainer { {DRBStatusDL12-ExtIEs} } OPTIONAL, + ... +} + +DRBStatusDL12-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBStatusDL18 ::= SEQUENCE { + dL-COUNTValue COUNTValueForPDCP-SN18, + iE-Extension ProtocolExtensionContainer { {DRBStatusDL18-ExtIEs} } OPTIONAL, + ... +} + +DRBStatusDL18-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBStatusUL ::= CHOICE { + dRBStatusUL12 DRBStatusUL12, + dRBStatusUL18 DRBStatusUL18, + choice-Extensions ProtocolIE-SingleContainer { {DRBStatusUL-ExtIEs} } +} + +DRBStatusUL-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +DRBStatusUL12 ::= SEQUENCE { + uL-COUNTValue COUNTValueForPDCP-SN12, + receiveStatusOfUL-PDCP-SDUs BIT STRING (SIZE(1..2048)) OPTIONAL, + iE-Extension ProtocolExtensionContainer { {DRBStatusUL12-ExtIEs} } OPTIONAL, + ... +} + +DRBStatusUL12-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBStatusUL18 ::= SEQUENCE { + uL-COUNTValue COUNTValueForPDCP-SN18, + receiveStatusOfUL-PDCP-SDUs BIT STRING (SIZE(1..131072)) OPTIONAL, + iE-Extension ProtocolExtensionContainer { {DRBStatusUL18-ExtIEs} } OPTIONAL, + ... +} + +DRBStatusUL18-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +DRBsToQosFlowsMappingList ::= SEQUENCE (SIZE(1..maxnoofDRBs)) OF DRBsToQosFlowsMappingItem + +DRBsToQosFlowsMappingItem ::= SEQUENCE { + dRB-ID DRB-ID, + associatedQosFlowList AssociatedQosFlowList, + iE-Extensions ProtocolExtensionContainer { {DRBsToQosFlowsMappingItem-ExtIEs} } OPTIONAL, + ... +} + +DRBsToQosFlowsMappingItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +Dynamic5QIDescriptor ::= SEQUENCE { + priorityLevelQos PriorityLevelQos, + packetDelayBudget PacketDelayBudget, + packetErrorRate PacketErrorRate, + fiveQI FiveQI OPTIONAL, + delayCritical DelayCritical OPTIONAL, +-- The above IE shall be present in case of GBR QoS flow + averagingWindow AveragingWindow OPTIONAL, +-- The above IE shall be present in case of GBR QoS flow + maximumDataBurstVolume MaximumDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {Dynamic5QIDescriptor-ExtIEs} } OPTIONAL, + ... +} + +Dynamic5QIDescriptor-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- E + +EmergencyAreaID ::= OCTET STRING (SIZE(3)) + +EmergencyAreaIDBroadcastEUTRA ::= SEQUENCE (SIZE(1..maxnoofEmergencyAreaID)) OF EmergencyAreaIDBroadcastEUTRA-Item + +EmergencyAreaIDBroadcastEUTRA-Item ::= SEQUENCE { + emergencyAreaID EmergencyAreaID, + completedCellsInEAI-EUTRA CompletedCellsInEAI-EUTRA, + iE-Extensions ProtocolExtensionContainer { {EmergencyAreaIDBroadcastEUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +EmergencyAreaIDBroadcastEUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +EmergencyAreaIDBroadcastNR ::= SEQUENCE (SIZE(1..maxnoofEmergencyAreaID)) OF EmergencyAreaIDBroadcastNR-Item + +EmergencyAreaIDBroadcastNR-Item ::= SEQUENCE { + emergencyAreaID EmergencyAreaID, + completedCellsInEAI-NR CompletedCellsInEAI-NR, + iE-Extensions ProtocolExtensionContainer { {EmergencyAreaIDBroadcastNR-Item-ExtIEs} } OPTIONAL, + ... +} + +EmergencyAreaIDBroadcastNR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +EmergencyAreaIDCancelledEUTRA ::= SEQUENCE (SIZE(1..maxnoofEmergencyAreaID)) OF EmergencyAreaIDCancelledEUTRA-Item + +EmergencyAreaIDCancelledEUTRA-Item ::= SEQUENCE { + emergencyAreaID EmergencyAreaID, + cancelledCellsInEAI-EUTRA CancelledCellsInEAI-EUTRA, + iE-Extensions ProtocolExtensionContainer { {EmergencyAreaIDCancelledEUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +EmergencyAreaIDCancelledEUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +EmergencyAreaIDCancelledNR ::= SEQUENCE (SIZE(1..maxnoofEmergencyAreaID)) OF EmergencyAreaIDCancelledNR-Item + +EmergencyAreaIDCancelledNR-Item ::= SEQUENCE { + emergencyAreaID EmergencyAreaID, + cancelledCellsInEAI-NR CancelledCellsInEAI-NR, + iE-Extensions ProtocolExtensionContainer { {EmergencyAreaIDCancelledNR-Item-ExtIEs} } OPTIONAL, + ... +} + +EmergencyAreaIDCancelledNR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +EmergencyAreaIDList ::= SEQUENCE (SIZE(1..maxnoofEmergencyAreaID)) OF EmergencyAreaID + +EmergencyAreaIDListForRestart ::= SEQUENCE (SIZE(1..maxnoofEAIforRestart)) OF EmergencyAreaID + +EmergencyFallbackIndicator ::= SEQUENCE { + emergencyFallbackRequestIndicator EmergencyFallbackRequestIndicator, + emergencyServiceTargetCN EmergencyServiceTargetCN OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {EmergencyFallbackIndicator-ExtIEs} } OPTIONAL, + ... +} + +EmergencyFallbackIndicator-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +EmergencyFallbackRequestIndicator ::= ENUMERATED { + emergency-fallback-requested, + ... +} + +EmergencyServiceTargetCN ::= ENUMERATED { + fiveGC, + epc, + ... +} + +EN-DCSONConfigurationTransfer ::= OCTET STRING + +EndpointIPAddressAndPort ::=SEQUENCE { + endpointIPAddress TransportLayerAddress, + portNumber PortNumber, + iE-Extensions ProtocolExtensionContainer { { EndpointIPAddressAndPort-ExtIEs} } OPTIONAL +} + +EndpointIPAddressAndPort-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +EquivalentPLMNs ::= SEQUENCE (SIZE(1..maxnoofEPLMNs)) OF PLMNIdentity + +EPS-TAC ::= OCTET STRING (SIZE(2)) + +EPS-TAI ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + ePS-TAC EPS-TAC, + iE-Extensions ProtocolExtensionContainer { {EPS-TAI-ExtIEs} } OPTIONAL, + ... +} + +EPS-TAI-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +E-RAB-ID ::= INTEGER (0..15, ...) + +E-RABInformationList ::= SEQUENCE (SIZE(1..maxnoofE-RABs)) OF E-RABInformationItem + +E-RABInformationItem ::= SEQUENCE { + e-RAB-ID E-RAB-ID, + dLForwarding DLForwarding OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {E-RABInformationItem-ExtIEs} } OPTIONAL, + ... +} + +E-RABInformationItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +EUTRACellIdentity ::= BIT STRING (SIZE(28)) + +EUTRA-CGI ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + eUTRACellIdentity EUTRACellIdentity, + iE-Extensions ProtocolExtensionContainer { {EUTRA-CGI-ExtIEs} } OPTIONAL, + ... +} + +EUTRA-CGI-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +EUTRA-CGIList ::= SEQUENCE (SIZE(1..maxnoofCellsinngeNB)) OF EUTRA-CGI + +EUTRA-CGIListForWarning ::= SEQUENCE (SIZE(1..maxnoofCellIDforWarning)) OF EUTRA-CGI + +EUTRAencryptionAlgorithms ::= BIT STRING (SIZE(16, ...)) + +EUTRAintegrityProtectionAlgorithms ::= BIT STRING (SIZE(16, ...)) + +EventType ::= ENUMERATED { + direct, + change-of-serve-cell, + ue-presence-in-area-of-interest, + stop-change-of-serve-cell, + stop-ue-presence-in-area-of-interest, + cancel-location-reporting-for-the-ue, + ... +} + +ExpectedActivityPeriod ::= INTEGER (1..30|40|50|60|80|100|120|150|180|181, ...) + +ExpectedHOInterval ::= ENUMERATED { + sec15, sec30, sec60, sec90, sec120, sec180, long-time, + ... +} + +ExpectedIdlePeriod ::= INTEGER (1..30|40|50|60|80|100|120|150|180|181, ...) + +ExpectedUEActivityBehaviour ::= SEQUENCE { + expectedActivityPeriod ExpectedActivityPeriod OPTIONAL, + expectedIdlePeriod ExpectedIdlePeriod OPTIONAL, + sourceOfUEActivityBehaviourInformation SourceOfUEActivityBehaviourInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {ExpectedUEActivityBehaviour-ExtIEs} } OPTIONAL, + ... +} + +ExpectedUEActivityBehaviour-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +ExpectedUEBehaviour ::= SEQUENCE { + expectedUEActivityBehaviour ExpectedUEActivityBehaviour OPTIONAL, + expectedHOInterval ExpectedHOInterval OPTIONAL, + expectedUEMobility ExpectedUEMobility OPTIONAL, + expectedUEMovingTrajectory ExpectedUEMovingTrajectory OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {ExpectedUEBehaviour-ExtIEs} } OPTIONAL, + ... +} + +ExpectedUEBehaviour-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +ExpectedUEMobility ::= ENUMERATED { + stationary, + mobile, + ... +} + +ExpectedUEMovingTrajectory ::= SEQUENCE (SIZE(1..maxnoofCellsUEMovingTrajectory)) OF ExpectedUEMovingTrajectoryItem + +ExpectedUEMovingTrajectoryItem ::= SEQUENCE { + nGRAN-CGI NGRAN-CGI, + timeStayedInCell INTEGER (0..4095) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {ExpectedUEMovingTrajectoryItem-ExtIEs} } OPTIONAL, + ... +} + +ExpectedUEMovingTrajectoryItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- F + +FiveG-S-TMSI ::= SEQUENCE { + aMFSetID AMFSetID, + aMFPointer AMFPointer, + fiveG-TMSI FiveG-TMSI, + iE-Extensions ProtocolExtensionContainer { {FiveG-S-TMSI-ExtIEs} } OPTIONAL, + ... +} + +FiveG-S-TMSI-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +FiveG-TMSI ::= OCTET STRING (SIZE(4)) + +FiveQI ::= INTEGER (0..255, ...) + +ForbiddenAreaInformation ::= SEQUENCE (SIZE(1.. maxnoofEPLMNsPlusOne)) OF ForbiddenAreaInformation-Item + +ForbiddenAreaInformation-Item ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + forbiddenTACs ForbiddenTACs, + iE-Extensions ProtocolExtensionContainer { {ForbiddenAreaInformation-Item-ExtIEs} } OPTIONAL, + ... +} + +ForbiddenAreaInformation-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +ForbiddenTACs ::= SEQUENCE (SIZE(1..maxnoofForbTACs)) OF TAC + +-- G + +GBR-QosInformation ::= SEQUENCE { + maximumFlowBitRateDL BitRate, + maximumFlowBitRateUL BitRate, + guaranteedFlowBitRateDL BitRate, + guaranteedFlowBitRateUL BitRate, + notificationControl NotificationControl OPTIONAL, + maximumPacketLossRateDL PacketLossRate OPTIONAL, + maximumPacketLossRateUL PacketLossRate OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {GBR-QosInformation-ExtIEs} } OPTIONAL, + ... +} + +GBR-QosInformation-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ...} + +GlobalGNB-ID ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + gNB-ID GNB-ID, + iE-Extensions ProtocolExtensionContainer { {GlobalGNB-ID-ExtIEs} } OPTIONAL, + ... +} + +GlobalGNB-ID-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +GlobalN3IWF-ID ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + n3IWF-ID N3IWF-ID, + iE-Extensions ProtocolExtensionContainer { {GlobalN3IWF-ID-ExtIEs} } OPTIONAL, + ... +} + +GlobalN3IWF-ID-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +GlobalNgENB-ID ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + ngENB-ID NgENB-ID, + iE-Extensions ProtocolExtensionContainer { {GlobalNgENB-ID-ExtIEs} } OPTIONAL, + ... +} + +GlobalNgENB-ID-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +GlobalRANNodeID ::= CHOICE { + globalGNB-ID GlobalGNB-ID, + globalNgENB-ID GlobalNgENB-ID, + globalN3IWF-ID GlobalN3IWF-ID, + choice-Extensions ProtocolIE-SingleContainer { {GlobalRANNodeID-ExtIEs} } +} + +GlobalRANNodeID-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +GNB-ID ::= CHOICE { + gNB-ID BIT STRING (SIZE(22..32)), + choice-Extensions ProtocolIE-SingleContainer { {GNB-ID-ExtIEs} } +} + +GNB-ID-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +GTP-TEID ::= OCTET STRING (SIZE(4)) + +GTPTunnel ::= SEQUENCE { + transportLayerAddress TransportLayerAddress, + gTP-TEID GTP-TEID, + iE-Extensions ProtocolExtensionContainer { {GTPTunnel-ExtIEs} } OPTIONAL, + ... +} + +GTPTunnel-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +GUAMI ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + aMFRegionID AMFRegionID, + aMFSetID AMFSetID, + aMFPointer AMFPointer, + iE-Extensions ProtocolExtensionContainer { {GUAMI-ExtIEs} } OPTIONAL, + ... +} + +GUAMI-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + + +-- H + +HandoverCommandTransfer ::= SEQUENCE { + dLForwardingUP-TNLInformation UPTransportLayerInformation OPTIONAL, + qosFlowToBeForwardedList QosFlowToBeForwardedList OPTIONAL, + dataForwardingResponseDRBList DataForwardingResponseDRBList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {HandoverCommandTransfer-ExtIEs} } OPTIONAL, + ... +} + +HandoverCommandTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalDLForwardingUPTNLInformation CRITICALITY ignore EXTENSION QosFlowPerTNLInformationList PRESENCE optional}| + { ID id-ULForwardingUP-TNLInformation CRITICALITY reject EXTENSION UPTransportLayerInformation PRESENCE optional}| + { ID id-AdditionalULForwardingUPTNLInformation CRITICALITY reject EXTENSION UPTransportLayerInformationList PRESENCE optional}, + ... +} + +HandoverFlag ::= ENUMERATED { + handover-preparation, + ... +} + +HandoverPreparationUnsuccessfulTransfer ::= SEQUENCE { + cause Cause, + iE-Extensions ProtocolExtensionContainer { {HandoverPreparationUnsuccessfulTransfer-ExtIEs} } OPTIONAL, + ... +} + +HandoverPreparationUnsuccessfulTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +HandoverRequestAcknowledgeTransfer ::= SEQUENCE { + dL-NGU-UP-TNLInformation UPTransportLayerInformation, + dLForwardingUP-TNLInformation UPTransportLayerInformation OPTIONAL, + securityResult SecurityResult OPTIONAL, + qosFlowSetupResponseList QosFlowListWithDataForwarding, + qosFlowFailedToSetupList QosFlowListWithCause OPTIONAL, + dataForwardingResponseDRBList DataForwardingResponseDRBList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {HandoverRequestAcknowledgeTransfer-ExtIEs} } OPTIONAL, + ... +} + +HandoverRequestAcknowledgeTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalDLUPTNLInformationForHOList CRITICALITY ignore EXTENSION AdditionalDLUPTNLInformationForHOList PRESENCE optional }| + { ID id-ULForwardingUP-TNLInformation CRITICALITY reject EXTENSION UPTransportLayerInformation PRESENCE optional}| + { ID id-AdditionalULForwardingUPTNLInformation CRITICALITY reject EXTENSION UPTransportLayerInformationList PRESENCE optional}, + ... +} + +HandoverRequiredTransfer ::= SEQUENCE { + directForwardingPathAvailability DirectForwardingPathAvailability OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {HandoverRequiredTransfer-ExtIEs} } OPTIONAL, + ... +} + +HandoverRequiredTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +HandoverResourceAllocationUnsuccessfulTransfer ::= SEQUENCE { + cause Cause, + criticalityDiagnostics CriticalityDiagnostics OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {HandoverResourceAllocationUnsuccessfulTransfer-ExtIEs} } OPTIONAL, + ... +} + +HandoverResourceAllocationUnsuccessfulTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +HandoverType ::= ENUMERATED { + intra5gs, + fivegs-to-eps, + eps-to-5gs, + ... +} + +-- I + +IMSVoiceSupportIndicator ::= ENUMERATED { + supported, + not-supported, + ... +} + +IndexToRFSP ::= INTEGER (1..256, ...) + +InfoOnRecommendedCellsAndRANNodesForPaging ::= SEQUENCE { + recommendedCellsForPaging RecommendedCellsForPaging, + recommendRANNodesForPaging RecommendedRANNodesForPaging, + iE-Extensions ProtocolExtensionContainer { {InfoOnRecommendedCellsAndRANNodesForPaging-ExtIEs} } OPTIONAL, + ... +} + +InfoOnRecommendedCellsAndRANNodesForPaging-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + + +IntegrityProtectionIndication ::= ENUMERATED { + required, + preferred, + not-needed, + ... +} + +IntegrityProtectionResult ::= ENUMERATED { + performed, + not-performed, + ... +} + +IntendedNumberOfPagingAttempts ::= INTEGER (1..16, ...) + +InterfacesToTrace ::= BIT STRING (SIZE(8)) + +-- J +-- K +-- L + +LastVisitedCellInformation ::= CHOICE { + nGRANCell LastVisitedNGRANCellInformation, + eUTRANCell LastVisitedEUTRANCellInformation, + uTRANCell LastVisitedUTRANCellInformation, + gERANCell LastVisitedGERANCellInformation, + choice-Extensions ProtocolIE-SingleContainer { {LastVisitedCellInformation-ExtIEs} } +} + +LastVisitedCellInformation-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +LastVisitedCellItem ::= SEQUENCE { + lastVisitedCellInformation LastVisitedCellInformation, + iE-Extensions ProtocolExtensionContainer { {LastVisitedCellItem-ExtIEs} } OPTIONAL, + ... +} + +LastVisitedCellItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +LastVisitedEUTRANCellInformation ::= OCTET STRING + +LastVisitedGERANCellInformation ::= OCTET STRING + +LastVisitedNGRANCellInformation::= SEQUENCE { + globalCellID NGRAN-CGI, + cellType CellType, + timeUEStayedInCell TimeUEStayedInCell, + timeUEStayedInCellEnhancedGranularity TimeUEStayedInCellEnhancedGranularity OPTIONAL, + hOCauseValue Cause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {LastVisitedNGRANCellInformation-ExtIEs} } OPTIONAL, + ... +} + +LastVisitedNGRANCellInformation-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +LastVisitedUTRANCellInformation ::= OCTET STRING + +LocationReportingAdditionalInfo ::= ENUMERATED { + includePSCell, + ... +} + +LocationReportingReferenceID ::= INTEGER (1..64, ...) + +LocationReportingRequestType ::= SEQUENCE { + eventType EventType, + reportArea ReportArea, + areaOfInterestList AreaOfInterestList OPTIONAL, + locationReportingReferenceIDToBeCancelled LocationReportingReferenceID OPTIONAL, +-- The above IE shall be present if the event type is set to ¡°stop reporting UE presence in the area of interest¡± + iE-Extensions ProtocolExtensionContainer { {LocationReportingRequestType-ExtIEs} } OPTIONAL, + ... +} + +LocationReportingRequestType-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-LocationReportingAdditionalInfo CRITICALITY ignore EXTENSION LocationReportingAdditionalInfo PRESENCE optional }, + ... +} + +-- M + +MaskedIMEISV ::= BIT STRING (SIZE(64)) + +MaximumDataBurstVolume ::= INTEGER (0..4095, ...) + +MessageIdentifier ::= BIT STRING (SIZE(16)) + +MaximumIntegrityProtectedDataRate ::= ENUMERATED { + bitrate64kbs, + maximum-UE-rate, + ... +} + +MICOModeIndication ::= ENUMERATED { + true, + ... +} + +MobilityRestrictionList ::= SEQUENCE { + servingPLMN PLMNIdentity, + equivalentPLMNs EquivalentPLMNs OPTIONAL, + rATRestrictions RATRestrictions OPTIONAL, + forbiddenAreaInformation ForbiddenAreaInformation OPTIONAL, + serviceAreaInformation ServiceAreaInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {MobilityRestrictionList-ExtIEs} } OPTIONAL, + ... +} + +MobilityRestrictionList-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-LastEUTRAN-PLMNIdentity CRITICALITY ignore EXTENSION PLMNIdentity PRESENCE optional }| + { ID id-CNTypeRestrictionsForServing CRITICALITY ignore EXTENSION CNTypeRestrictionsForServing PRESENCE optional}| + { ID id-CNTypeRestrictionsForEquivalent CRITICALITY ignore EXTENSION CNTypeRestrictionsForEquivalent PRESENCE optional}, + ... +} + + +-- N + +N3IWF-ID ::= CHOICE { + n3IWF-ID BIT STRING (SIZE(16)), + choice-Extensions ProtocolIE-SingleContainer { {N3IWF-ID-ExtIEs} } +} + +N3IWF-ID-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +NAS-PDU ::= OCTET STRING + +NASSecurityParametersFromNGRAN ::= OCTET STRING + +NetworkInstance ::= INTEGER (1..256, ...) + +NewSecurityContextInd ::= ENUMERATED { + true, + ... +} + +NextHopChainingCount ::= INTEGER (0..7) + +NextPagingAreaScope ::= ENUMERATED { + same, + changed, + ... +} + +NgENB-ID ::= CHOICE { + macroNgENB-ID BIT STRING (SIZE(20)), + shortMacroNgENB-ID BIT STRING (SIZE(18)), + longMacroNgENB-ID BIT STRING (SIZE(21)), + choice-Extensions ProtocolIE-SingleContainer { {NgENB-ID-ExtIEs} } +} + +NgENB-ID-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +NGRAN-CGI ::= CHOICE { + nR-CGI NR-CGI, + eUTRA-CGI EUTRA-CGI, + choice-Extensions ProtocolIE-SingleContainer { {NGRAN-CGI-ExtIEs} } +} + +NGRAN-CGI-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +NGRAN-TNLAssociationToRemoveList ::= SEQUENCE (SIZE(1..maxnoofTNLAssociations)) OF NGRAN-TNLAssociationToRemoveItem + +NGRAN-TNLAssociationToRemoveItem::= SEQUENCE { + tNLAssociationTransportLayerAddress CPTransportLayerInformation, + tNLAssociationTransportLayerAddressAMF CPTransportLayerInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { NGRAN-TNLAssociationToRemoveItem-ExtIEs} } OPTIONAL +} + +NGRAN-TNLAssociationToRemoveItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +NGRANTraceID ::= OCTET STRING (SIZE(8)) + +NonDynamic5QIDescriptor ::= SEQUENCE { + fiveQI FiveQI, + priorityLevelQos PriorityLevelQos OPTIONAL, + averagingWindow AveragingWindow OPTIONAL, + maximumDataBurstVolume MaximumDataBurstVolume OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {NonDynamic5QIDescriptor-ExtIEs} } OPTIONAL, + ... +} + +NonDynamic5QIDescriptor-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +NotAllowedTACs ::= SEQUENCE (SIZE(1..maxnoofAllowedAreas)) OF TAC + +NotificationCause ::= ENUMERATED { + fulfilled, + not-fulfilled, + ... +} + +NotificationControl ::= ENUMERATED { + notification-requested, + ... +} + +NRCellIdentity ::= BIT STRING (SIZE(36)) + +NR-CGI ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + nRCellIdentity NRCellIdentity, + iE-Extensions ProtocolExtensionContainer { {NR-CGI-ExtIEs} } OPTIONAL, + ... +} + +NR-CGI-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +NR-CGIList ::= SEQUENCE (SIZE(1..maxnoofCellsingNB)) OF NR-CGI + +NR-CGIListForWarning ::= SEQUENCE (SIZE(1..maxnoofCellIDforWarning)) OF NR-CGI + +NRencryptionAlgorithms ::= BIT STRING (SIZE(16, ...)) + +NRintegrityProtectionAlgorithms ::= BIT STRING (SIZE(16, ...)) + +NRPPa-PDU ::= OCTET STRING + +NumberOfBroadcasts ::= INTEGER (0..65535) + +NumberOfBroadcastsRequested ::= INTEGER (0..65535) + +-- O + +OverloadAction ::= ENUMERATED { + reject-non-emergency-mo-dt, + reject-rrc-cr-signalling, + permit-emergency-sessions-and-mobile-terminated-services-only, + permit-high-priority-sessions-and-mobile-terminated-services-only, + ... +} + +OverloadResponse ::= CHOICE { + overloadAction OverloadAction, + choice-Extensions ProtocolIE-SingleContainer { {OverloadResponse-ExtIEs} } +} + +OverloadResponse-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +OverloadStartNSSAIList ::= SEQUENCE (SIZE (1..maxnoofSliceItems)) OF OverloadStartNSSAIItem + +OverloadStartNSSAIItem ::= SEQUENCE { + sliceOverloadList SliceOverloadList, + sliceOverloadResponse OverloadResponse OPTIONAL, + sliceTrafficLoadReductionIndication TrafficLoadReductionIndication OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {OverloadStartNSSAIItem-ExtIEs} } OPTIONAL, + ... +} + +OverloadStartNSSAIItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- P + +PacketDelayBudget ::= INTEGER (0..1023, ...) + +PacketErrorRate ::= SEQUENCE { + pERScalar INTEGER (0..9, ...), + pERExponent INTEGER (0..9, ...), + iE-Extensions ProtocolExtensionContainer { {PacketErrorRate-ExtIEs} } OPTIONAL, + ... +} + +PacketErrorRate-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PacketLossRate ::= INTEGER (0..1000, ...) + +PagingAttemptInformation ::= SEQUENCE { + pagingAttemptCount PagingAttemptCount, + intendedNumberOfPagingAttempts IntendedNumberOfPagingAttempts, + nextPagingAreaScope NextPagingAreaScope OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PagingAttemptInformation-ExtIEs} } OPTIONAL, + ... +} + +PagingAttemptInformation-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PagingAttemptCount ::= INTEGER (1..16, ...) + +PagingDRX ::= ENUMERATED { + v32, + v64, + v128, + v256, + ... +} + +PagingOrigin ::= ENUMERATED { + non-3gpp, + ... +} + +PagingPriority ::= ENUMERATED { + priolevel1, + priolevel2, + priolevel3, + priolevel4, + priolevel5, + priolevel6, + priolevel7, + priolevel8, + ... +} + +PathSwitchRequestAcknowledgeTransfer ::= SEQUENCE { + uL-NGU-UP-TNLInformation UPTransportLayerInformation OPTIONAL, + securityIndication SecurityIndication OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PathSwitchRequestAcknowledgeTransfer-ExtIEs} } OPTIONAL, + ... +} + +PathSwitchRequestAcknowledgeTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalNGU-UP-TNLInformation CRITICALITY ignore EXTENSION UPTransportLayerInformationPairList PRESENCE optional }, + ... +} + +PathSwitchRequestSetupFailedTransfer ::= SEQUENCE { + cause Cause, + iE-Extensions ProtocolExtensionContainer { {PathSwitchRequestSetupFailedTransfer-ExtIEs} } OPTIONAL, + ... +} + +PathSwitchRequestSetupFailedTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PathSwitchRequestTransfer ::= SEQUENCE { + dL-NGU-UP-TNLInformation UPTransportLayerInformation, + dL-NGU-TNLInformationReused DL-NGU-TNLInformationReused OPTIONAL, + userPlaneSecurityInformation UserPlaneSecurityInformation OPTIONAL, + qosFlowAcceptedList QosFlowAcceptedList, + iE-Extensions ProtocolExtensionContainer { {PathSwitchRequestTransfer-ExtIEs} } OPTIONAL, + ... +} + +PathSwitchRequestTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalDLQosFlowPerTNLInformation CRITICALITY ignore EXTENSION QosFlowPerTNLInformationList PRESENCE optional }, + ... +} + +PathSwitchRequestUnsuccessfulTransfer ::= SEQUENCE { + cause Cause, + iE-Extensions ProtocolExtensionContainer { {PathSwitchRequestUnsuccessfulTransfer-ExtIEs} } OPTIONAL, + ... +} + +PathSwitchRequestUnsuccessfulTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionAggregateMaximumBitRate ::= SEQUENCE { + pDUSessionAggregateMaximumBitRateDL BitRate, + pDUSessionAggregateMaximumBitRateUL BitRate, + iE-Extensions ProtocolExtensionContainer { {PDUSessionAggregateMaximumBitRate-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionAggregateMaximumBitRate-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionID ::= INTEGER (0..255) + +PDUSessionResourceAdmittedList ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceAdmittedItem + +PDUSessionResourceAdmittedItem ::= SEQUENCE { + pDUSessionID PDUSessionID, + handoverRequestAcknowledgeTransfer OCTET STRING (CONTAINING HandoverRequestAcknowledgeTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceAdmittedItem-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceAdmittedItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceFailedToModifyListModCfm ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceFailedToModifyItemModCfm + +PDUSessionResourceFailedToModifyItemModCfm ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceModifyIndicationUnsuccessfulTransfer OCTET STRING (CONTAINING PDUSessionResourceModifyIndicationUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceFailedToModifyItemModCfm-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceFailedToModifyItemModCfm-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceFailedToModifyListModRes ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceFailedToModifyItemModRes + +PDUSessionResourceFailedToModifyItemModRes ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceModifyUnsuccessfulTransfer OCTET STRING (CONTAINING PDUSessionResourceModifyUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceFailedToModifyItemModRes-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceFailedToModifyItemModRes-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceFailedToSetupListCxtFail ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceFailedToSetupItemCxtFail + +PDUSessionResourceFailedToSetupItemCxtFail ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceSetupUnsuccessfulTransfer OCTET STRING (CONTAINING PDUSessionResourceSetupUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceFailedToSetupItemCxtFail-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceFailedToSetupItemCxtFail-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceFailedToSetupListCxtRes ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceFailedToSetupItemCxtRes + +PDUSessionResourceFailedToSetupItemCxtRes ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceSetupUnsuccessfulTransfer OCTET STRING (CONTAINING PDUSessionResourceSetupUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceFailedToSetupItemCxtRes-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceFailedToSetupItemCxtRes-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceFailedToSetupListHOAck ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceFailedToSetupItemHOAck + +PDUSessionResourceFailedToSetupItemHOAck ::= SEQUENCE { + pDUSessionID PDUSessionID, + handoverResourceAllocationUnsuccessfulTransfer OCTET STRING (CONTAINING HandoverResourceAllocationUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceFailedToSetupItemHOAck-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceFailedToSetupItemHOAck-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceFailedToSetupListPSReq ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceFailedToSetupItemPSReq + +PDUSessionResourceFailedToSetupItemPSReq ::= SEQUENCE { + pDUSessionID PDUSessionID, + pathSwitchRequestSetupFailedTransfer OCTET STRING (CONTAINING PathSwitchRequestSetupFailedTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceFailedToSetupItemPSReq-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceFailedToSetupItemPSReq-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceFailedToSetupListSURes ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceFailedToSetupItemSURes + +PDUSessionResourceFailedToSetupItemSURes ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceSetupUnsuccessfulTransfer OCTET STRING (CONTAINING PDUSessionResourceSetupUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceFailedToSetupItemSURes-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceFailedToSetupItemSURes-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceHandoverList ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceHandoverItem + +PDUSessionResourceHandoverItem ::= SEQUENCE { + pDUSessionID PDUSessionID, + handoverCommandTransfer OCTET STRING (CONTAINING HandoverCommandTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceHandoverItem-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceHandoverItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceInformationList ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceInformationItem + +PDUSessionResourceInformationItem ::= SEQUENCE { + pDUSessionID PDUSessionID, + qosFlowInformationList QosFlowInformationList, + dRBsToQosFlowsMappingList DRBsToQosFlowsMappingList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceInformationItem-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceInformationItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceListCxtRelCpl ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceItemCxtRelCpl + +PDUSessionResourceItemCxtRelCpl ::= SEQUENCE { + pDUSessionID PDUSessionID, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceItemCxtRelCpl-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceItemCxtRelCpl-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-PDUSessionResourceReleaseResponseTransfer CRITICALITY ignore EXTENSION OCTET STRING (CONTAINING PDUSessionResourceReleaseResponseTransfer) PRESENCE optional }, + ... +} + +PDUSessionResourceListCxtRelReq ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceItemCxtRelReq + +PDUSessionResourceItemCxtRelReq ::= SEQUENCE { + pDUSessionID PDUSessionID, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceItemCxtRelReq-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceItemCxtRelReq-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceListHORqd ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceItemHORqd + +PDUSessionResourceItemHORqd ::= SEQUENCE { + pDUSessionID PDUSessionID, + handoverRequiredTransfer OCTET STRING (CONTAINING HandoverRequiredTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceItemHORqd-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceItemHORqd-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceModifyConfirmTransfer ::= SEQUENCE { + qosFlowModifyConfirmList QosFlowModifyConfirmList, + uLNGU-UP-TNLInformation UPTransportLayerInformation, + additionalNG-UUPTNLInformation UPTransportLayerInformationPairList OPTIONAL, + qosFlowFailedToModifyList QosFlowListWithCause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyConfirmTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyConfirmTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceModifyIndicationUnsuccessfulTransfer ::= SEQUENCE { + cause Cause, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyIndicationUnsuccessfulTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyIndicationUnsuccessfulTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceModifyRequestTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceModifyRequestTransferIEs} }, + ... +} + +PDUSessionResourceModifyRequestTransferIEs NGAP-PROTOCOL-IES ::= { + { ID id-PDUSessionAggregateMaximumBitRate CRITICALITY reject TYPE PDUSessionAggregateMaximumBitRate PRESENCE optional }| + { ID id-UL-NGU-UP-TNLModifyList CRITICALITY reject TYPE UL-NGU-UP-TNLModifyList PRESENCE optional }| + { ID id-NetworkInstance CRITICALITY reject TYPE NetworkInstance PRESENCE optional }| + { ID id-QosFlowAddOrModifyRequestList CRITICALITY reject TYPE QosFlowAddOrModifyRequestList PRESENCE optional }| + { ID id-QosFlowToReleaseList CRITICALITY reject TYPE QosFlowListWithCause PRESENCE optional }| + { ID id-AdditionalUL-NGU-UP-TNLInformation CRITICALITY reject TYPE UPTransportLayerInformationList PRESENCE optional }| + { ID id-CommonNetworkInstance CRITICALITY ignore TYPE CommonNetworkInstance PRESENCE optional }, + ... +} + +PDUSessionResourceModifyResponseTransfer ::= SEQUENCE { + dL-NGU-UP-TNLInformation UPTransportLayerInformation OPTIONAL, + uL-NGU-UP-TNLInformation UPTransportLayerInformation OPTIONAL, + qosFlowAddOrModifyResponseList QosFlowAddOrModifyResponseList OPTIONAL, + additionalDLQosFlowPerTNLInformation QosFlowPerTNLInformationList OPTIONAL, + qosFlowFailedToAddOrModifyList QosFlowListWithCause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyResponseTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyResponseTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-AdditionalNGU-UP-TNLInformation CRITICALITY ignore EXTENSION UPTransportLayerInformationPairList PRESENCE optional }, + ... +} + +PDUSessionResourceModifyIndicationTransfer ::= SEQUENCE { + dLQosFlowPerTNLInformation QosFlowPerTNLInformation, + additionalDLQosFlowPerTNLInformation QosFlowPerTNLInformationList OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyIndicationTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyIndicationTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-SecondaryRATUsageInformation CRITICALITY ignore EXTENSION SecondaryRATUsageInformation PRESENCE optional }| + { ID id-SecurityResult CRITICALITY ignore EXTENSION SecurityResult PRESENCE optional }, + ... +} + +PDUSessionResourceModifyListModCfm ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceModifyItemModCfm + +PDUSessionResourceModifyItemModCfm ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceModifyConfirmTransfer OCTET STRING (CONTAINING PDUSessionResourceModifyConfirmTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyItemModCfm-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyItemModCfm-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceModifyListModInd ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceModifyItemModInd + +PDUSessionResourceModifyItemModInd ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceModifyIndicationTransfer OCTET STRING (CONTAINING PDUSessionResourceModifyIndicationTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyItemModInd-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyItemModInd-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceModifyListModReq ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceModifyItemModReq + +PDUSessionResourceModifyItemModReq ::= SEQUENCE { + pDUSessionID PDUSessionID, + nAS-PDU NAS-PDU OPTIONAL, + pDUSessionResourceModifyRequestTransfer OCTET STRING (CONTAINING PDUSessionResourceModifyRequestTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyItemModReq-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyItemModReq-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + {ID id-S-NSSAI CRITICALITY reject EXTENSION S-NSSAI PRESENCE optional }, + ... +} + +PDUSessionResourceModifyListModRes ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceModifyItemModRes + +PDUSessionResourceModifyItemModRes ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceModifyResponseTransfer OCTET STRING (CONTAINING PDUSessionResourceModifyResponseTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyItemModRes-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyItemModRes-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceModifyUnsuccessfulTransfer ::= SEQUENCE { + cause Cause, + criticalityDiagnostics CriticalityDiagnostics OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceModifyUnsuccessfulTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceModifyUnsuccessfulTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceNotifyList ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceNotifyItem + +PDUSessionResourceNotifyItem ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceNotifyTransfer OCTET STRING (CONTAINING PDUSessionResourceNotifyTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceNotifyItem-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceNotifyItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceNotifyReleasedTransfer ::= SEQUENCE { + cause Cause, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceNotifyReleasedTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceNotifyReleasedTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-SecondaryRATUsageInformation CRITICALITY ignore EXTENSION SecondaryRATUsageInformation PRESENCE optional }, + ... +} + +PDUSessionResourceNotifyTransfer ::= SEQUENCE { + qosFlowNotifyList QosFlowNotifyList OPTIONAL, + qosFlowReleasedList QosFlowListWithCause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceNotifyTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceNotifyTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-SecondaryRATUsageInformation CRITICALITY ignore EXTENSION SecondaryRATUsageInformation PRESENCE optional }, + ... +} + +PDUSessionResourceReleaseCommandTransfer ::= SEQUENCE { + cause Cause, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceReleaseCommandTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceReleaseCommandTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceReleasedListNot ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceReleasedItemNot + +PDUSessionResourceReleasedItemNot ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceNotifyReleasedTransfer OCTET STRING (CONTAINING PDUSessionResourceNotifyReleasedTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceReleasedItemNot-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceReleasedItemNot-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceReleasedListPSAck ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceReleasedItemPSAck + +PDUSessionResourceReleasedItemPSAck ::= SEQUENCE { + pDUSessionID PDUSessionID, + pathSwitchRequestUnsuccessfulTransfer OCTET STRING (CONTAINING PathSwitchRequestUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceReleasedItemPSAck-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceReleasedItemPSAck-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceReleasedListPSFail ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceReleasedItemPSFail + +PDUSessionResourceReleasedItemPSFail ::= SEQUENCE { + pDUSessionID PDUSessionID, + pathSwitchRequestUnsuccessfulTransfer OCTET STRING (CONTAINING PathSwitchRequestUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceReleasedItemPSFail-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceReleasedItemPSFail-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceReleasedListRelRes ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceReleasedItemRelRes + +PDUSessionResourceReleasedItemRelRes ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceReleaseResponseTransfer OCTET STRING (CONTAINING PDUSessionResourceReleaseResponseTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceReleasedItemRelRes-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceReleasedItemRelRes-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceReleaseResponseTransfer ::= SEQUENCE { + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceReleaseResponseTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceReleaseResponseTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-SecondaryRATUsageInformation CRITICALITY ignore EXTENSION SecondaryRATUsageInformation PRESENCE optional }, + ... +} + +PDUSessionResourceSecondaryRATUsageList ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceSecondaryRATUsageItem + +PDUSessionResourceSecondaryRATUsageItem ::= SEQUENCE { + pDUSessionID PDUSessionID, + secondaryRATDataUsageReportTransfer OCTET STRING (CONTAINING SecondaryRATDataUsageReportTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceSecondaryRATUsageItem-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSecondaryRATUsageItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceSetupListCxtReq ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceSetupItemCxtReq + +PDUSessionResourceSetupItemCxtReq ::= SEQUENCE { + pDUSessionID PDUSessionID, + nAS-PDU NAS-PDU OPTIONAL, + s-NSSAI S-NSSAI, + pDUSessionResourceSetupRequestTransfer OCTET STRING (CONTAINING PDUSessionResourceSetupRequestTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceSetupItemCxtReq-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSetupItemCxtReq-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceSetupListCxtRes ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceSetupItemCxtRes + +PDUSessionResourceSetupItemCxtRes ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceSetupResponseTransfer OCTET STRING (CONTAINING PDUSessionResourceSetupResponseTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceSetupItemCxtRes-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSetupItemCxtRes-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceSetupListHOReq ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceSetupItemHOReq + +PDUSessionResourceSetupItemHOReq ::= SEQUENCE { + pDUSessionID PDUSessionID, + s-NSSAI S-NSSAI, + handoverRequestTransfer OCTET STRING (CONTAINING PDUSessionResourceSetupRequestTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceSetupItemHOReq-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSetupItemHOReq-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceSetupListSUReq ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceSetupItemSUReq + +PDUSessionResourceSetupItemSUReq ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionNAS-PDU NAS-PDU OPTIONAL, + s-NSSAI S-NSSAI, + pDUSessionResourceSetupRequestTransfer OCTET STRING (CONTAINING PDUSessionResourceSetupRequestTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceSetupItemSUReq-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSetupItemSUReq-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceSetupListSURes ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceSetupItemSURes + +PDUSessionResourceSetupItemSURes ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceSetupResponseTransfer OCTET STRING (CONTAINING PDUSessionResourceSetupResponseTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceSetupItemSURes-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSetupItemSURes-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceSetupRequestTransfer ::= SEQUENCE { + protocolIEs ProtocolIE-Container { {PDUSessionResourceSetupRequestTransferIEs} }, + ... +} + +PDUSessionResourceSetupRequestTransferIEs NGAP-PROTOCOL-IES ::= { + { ID id-PDUSessionAggregateMaximumBitRate CRITICALITY reject TYPE PDUSessionAggregateMaximumBitRate PRESENCE optional }| + { ID id-UL-NGU-UP-TNLInformation CRITICALITY reject TYPE UPTransportLayerInformation PRESENCE mandatory }| + { ID id-AdditionalUL-NGU-UP-TNLInformation CRITICALITY reject TYPE UPTransportLayerInformationList PRESENCE optional }| + { ID id-DataForwardingNotPossible CRITICALITY reject TYPE DataForwardingNotPossible PRESENCE optional }| + { ID id-PDUSessionType CRITICALITY reject TYPE PDUSessionType PRESENCE mandatory }| + { ID id-SecurityIndication CRITICALITY reject TYPE SecurityIndication PRESENCE optional }| + { ID id-NetworkInstance CRITICALITY reject TYPE NetworkInstance PRESENCE optional }| + { ID id-QosFlowSetupRequestList CRITICALITY reject TYPE QosFlowSetupRequestList PRESENCE mandatory }| + { ID id-CommonNetworkInstance CRITICALITY ignore TYPE CommonNetworkInstance PRESENCE optional }, + ... +} + +PDUSessionResourceSetupResponseTransfer ::= SEQUENCE { + dLQosFlowPerTNLInformation QosFlowPerTNLInformation, + additionalDLQosFlowPerTNLInformation QosFlowPerTNLInformationList OPTIONAL, + securityResult SecurityResult OPTIONAL, + qosFlowFailedToSetupList QosFlowListWithCause OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceSetupResponseTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSetupResponseTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceSetupUnsuccessfulTransfer ::= SEQUENCE { + cause Cause, + criticalityDiagnostics CriticalityDiagnostics OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceSetupUnsuccessfulTransfer-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSetupUnsuccessfulTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceSwitchedList ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceSwitchedItem + +PDUSessionResourceSwitchedItem ::= SEQUENCE { + pDUSessionID PDUSessionID, + pathSwitchRequestAcknowledgeTransfer OCTET STRING (CONTAINING PathSwitchRequestAcknowledgeTransfer), + iE-Extensions ProtocolExtensionContainer { { PDUSessionResourceSwitchedItem-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceSwitchedItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceToBeSwitchedDLList ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceToBeSwitchedDLItem + +PDUSessionResourceToBeSwitchedDLItem ::= SEQUENCE { + pDUSessionID PDUSessionID, + pathSwitchRequestTransfer OCTET STRING (CONTAINING PathSwitchRequestTransfer), + iE-Extensions ProtocolExtensionContainer { { PDUSessionResourceToBeSwitchedDLItem-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceToBeSwitchedDLItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceToReleaseListHOCmd ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceToReleaseItemHOCmd + +PDUSessionResourceToReleaseItemHOCmd ::= SEQUENCE { + pDUSessionID PDUSessionID, + handoverPreparationUnsuccessfulTransfer OCTET STRING (CONTAINING HandoverPreparationUnsuccessfulTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceToReleaseItemHOCmd-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceToReleaseItemHOCmd-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PDUSessionResourceToReleaseListRelCmd ::= SEQUENCE (SIZE(1..maxnoofPDUSessions)) OF PDUSessionResourceToReleaseItemRelCmd + +PDUSessionResourceToReleaseItemRelCmd ::= SEQUENCE { + pDUSessionID PDUSessionID, + pDUSessionResourceReleaseCommandTransfer OCTET STRING (CONTAINING PDUSessionResourceReleaseCommandTransfer), + iE-Extensions ProtocolExtensionContainer { {PDUSessionResourceToReleaseItemRelCmd-ExtIEs} } OPTIONAL, + ... +} + +PDUSessionResourceToReleaseItemRelCmd-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} +PDUSessionType ::= ENUMERATED { + ipv4, + ipv6, + ipv4v6, + ethernet, + unstructured, + ... +} + +PDUSessionUsageReport ::= SEQUENCE { + rATType ENUMERATED {nr, eutra, ...}, + pDUSessionTimedReportList VolumeTimedReportList, + iE-Extensions ProtocolExtensionContainer { {PDUSessionUsageReport-ExtIEs} } OPTIONAL, +... +} + +PDUSessionUsageReport-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PeriodicRegistrationUpdateTimer ::= BIT STRING (SIZE(8)) + +PLMNIdentity ::= OCTET STRING (SIZE(3)) + +PLMNSupportList ::= SEQUENCE (SIZE(1..maxnoofPLMNs)) OF PLMNSupportItem + +PLMNSupportItem ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + sliceSupportList SliceSupportList, + iE-Extensions ProtocolExtensionContainer { {PLMNSupportItem-ExtIEs} } OPTIONAL, + ... +} + +PLMNSupportItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +PortNumber ::= OCTET STRING (SIZE(2)) + +Pre-emptionCapability ::= ENUMERATED { + shall-not-trigger-pre-emption, + may-trigger-pre-emption, + ... +} + +Pre-emptionVulnerability ::= ENUMERATED { + not-pre-emptable, + pre-emptable, + ... +} + +PriorityLevelARP ::= INTEGER (1..15) + +PriorityLevelQos ::= INTEGER (1..127, ...) + +PWSFailedCellIDList ::= CHOICE { + eUTRA-CGI-PWSFailedList EUTRA-CGIList, + nR-CGI-PWSFailedList NR-CGIList, + choice-Extensions ProtocolIE-SingleContainer { {PWSFailedCellIDList-ExtIEs} } +} + +PWSFailedCellIDList-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +-- Q + +QosCharacteristics ::= CHOICE { + nonDynamic5QI NonDynamic5QIDescriptor, + dynamic5QI Dynamic5QIDescriptor, + choice-Extensions ProtocolIE-SingleContainer { {QosCharacteristics-ExtIEs} } +} + +QosCharacteristics-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +QosFlowAcceptedList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowAcceptedItem + +QosFlowAcceptedItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + iE-Extensions ProtocolExtensionContainer { {QosFlowAcceptedItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowAcceptedItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowAddOrModifyRequestList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowAddOrModifyRequestItem + +QosFlowAddOrModifyRequestItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + qosFlowLevelQosParameters QosFlowLevelQosParameters OPTIONAL, + e-RAB-ID E-RAB-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {QosFlowAddOrModifyRequestItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowAddOrModifyRequestItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowAddOrModifyResponseList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowAddOrModifyResponseItem + +QosFlowAddOrModifyResponseItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + iE-Extensions ProtocolExtensionContainer { {QosFlowAddOrModifyResponseItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowAddOrModifyResponseItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowIdentifier ::= INTEGER (0..63, ...) + +QosFlowInformationList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowInformationItem + +QosFlowInformationItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + dLForwarding DLForwarding OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {QosFlowInformationItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowInformationItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + {ID id-ULForwarding CRITICALITY reject EXTENSION ULForwarding PRESENCE optional}, + ... +} + +QosFlowLevelQosParameters ::= SEQUENCE { + qosCharacteristics QosCharacteristics, + allocationAndRetentionPriority AllocationAndRetentionPriority, + gBR-QosInformation GBR-QosInformation OPTIONAL, + reflectiveQosAttribute ReflectiveQosAttribute OPTIONAL, + additionalQosFlowInformation AdditionalQosFlowInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {QosFlowLevelQosParameters-ExtIEs} } OPTIONAL, + ... +} + +QosFlowLevelQosParameters-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowListWithCause ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowWithCauseItem + +QosFlowWithCauseItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + cause Cause, + iE-Extensions ProtocolExtensionContainer { {QosFlowWithCauseItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowWithCauseItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowModifyConfirmList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowModifyConfirmItem + +QosFlowModifyConfirmItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + iE-Extensions ProtocolExtensionContainer { {QosFlowModifyConfirmItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowModifyConfirmItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowNotifyList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowNotifyItem + +QosFlowNotifyItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + notificationCause NotificationCause, + iE-Extensions ProtocolExtensionContainer { {QosFlowNotifyItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowNotifyItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowPerTNLInformation ::= SEQUENCE { + uPTransportLayerInformation UPTransportLayerInformation, + associatedQosFlowList AssociatedQosFlowList, + iE-Extensions ProtocolExtensionContainer { { QosFlowPerTNLInformation-ExtIEs} } OPTIONAL, + ... +} + +QosFlowPerTNLInformation-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowPerTNLInformationList ::= SEQUENCE (SIZE(1..maxnoofMultiConnectivityMinusOne)) OF QosFlowPerTNLInformationItem + +QosFlowPerTNLInformationItem ::= SEQUENCE { + qosFlowPerTNLInformation QosFlowPerTNLInformation, + iE-Extensions ProtocolExtensionContainer { { QosFlowPerTNLInformationItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowPerTNLInformationItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowSetupRequestList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowSetupRequestItem + +QosFlowSetupRequestItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + qosFlowLevelQosParameters QosFlowLevelQosParameters, + e-RAB-ID E-RAB-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {QosFlowSetupRequestItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowSetupRequestItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowListWithDataForwarding ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowItemWithDataForwarding + +QosFlowItemWithDataForwarding ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + dataForwardingAccepted DataForwardingAccepted OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {QosFlowItemWithDataForwarding-ExtIEs} } OPTIONAL, + ... +} + +QosFlowItemWithDataForwarding-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowSetupResponseListSURes ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowSetupResponseItemSURes + +QosFlowSetupResponseItemSURes ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + iE-Extensions ProtocolExtensionContainer { {QosFlowSetupResponseItemSURes-ExtIEs} } OPTIONAL, + ... +} + +QosFlowSetupResponseItemSURes-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QosFlowToBeForwardedList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QosFlowToBeForwardedItem + +QosFlowToBeForwardedItem ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + iE-Extensions ProtocolExtensionContainer { {QosFlowToBeForwardedItem-ExtIEs} } OPTIONAL, + ... +} + +QosFlowToBeForwardedItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +QoSFlowsUsageReportList ::= SEQUENCE (SIZE(1..maxnoofQosFlows)) OF QoSFlowsUsageReport-Item + +QoSFlowsUsageReport-Item ::= SEQUENCE { + qosFlowIdentifier QosFlowIdentifier, + rATType ENUMERATED {nr, eutra, ...}, + qoSFlowsTimedReportList VolumeTimedReportList, + iE-Extensions ProtocolExtensionContainer { {QoSFlowsUsageReport-Item-ExtIEs} } OPTIONAL, +... +} + +QoSFlowsUsageReport-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- R + +RANNodeName ::= PrintableString (SIZE(1..150, ...)) + +RANPagingPriority ::= INTEGER (1..256) + +RANStatusTransfer-TransparentContainer ::= SEQUENCE { + dRBsSubjectToStatusTransferList DRBsSubjectToStatusTransferList, + iE-Extensions ProtocolExtensionContainer { {RANStatusTransfer-TransparentContainer-ExtIEs} } OPTIONAL, + ... +} + +RANStatusTransfer-TransparentContainer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +RAN-UE-NGAP-ID ::= INTEGER (0..4294967295) + +RATRestrictions ::= SEQUENCE (SIZE(1..maxnoofEPLMNsPlusOne)) OF RATRestrictions-Item + +RATRestrictions-Item ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + rATRestrictionInformation RATRestrictionInformation, + iE-Extensions ProtocolExtensionContainer { {RATRestrictions-Item-ExtIEs} } OPTIONAL, + ... +} + +RATRestrictions-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +RATRestrictionInformation ::= BIT STRING (SIZE(8, ...)) + +RecommendedCellsForPaging ::= SEQUENCE { + recommendedCellList RecommendedCellList, + iE-Extensions ProtocolExtensionContainer { {RecommendedCellsForPaging-ExtIEs} } OPTIONAL, + ... +} + +RecommendedCellsForPaging-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +RecommendedCellList ::= SEQUENCE (SIZE(1..maxnoofRecommendedCells)) OF RecommendedCellItem + +RecommendedCellItem ::= SEQUENCE { + nGRAN-CGI NGRAN-CGI, + timeStayedInCell INTEGER (0..4095) OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {RecommendedCellItem-ExtIEs} } OPTIONAL, + ... +} + +RecommendedCellItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +RecommendedRANNodesForPaging ::= SEQUENCE { + recommendedRANNodeList RecommendedRANNodeList, + iE-Extensions ProtocolExtensionContainer { {RecommendedRANNodesForPaging-ExtIEs} } OPTIONAL, + ... +} + +RecommendedRANNodesForPaging-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +RecommendedRANNodeList::= SEQUENCE (SIZE(1..maxnoofRecommendedRANNodes)) OF RecommendedRANNodeItem + +RecommendedRANNodeItem ::= SEQUENCE { + aMFPagingTarget AMFPagingTarget, + iE-Extensions ProtocolExtensionContainer { {RecommendedRANNodeItem-ExtIEs} } OPTIONAL, + ... +} + +RecommendedRANNodeItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +RedirectionVoiceFallback ::= ENUMERATED { + possible, + not-possible, + ... +} + +ReflectiveQosAttribute ::= ENUMERATED { + subject-to, + ... +} + +ReferenceID ::= INTEGER (1..64, ...) + +RelativeAMFCapacity ::= INTEGER (0..255) + +ReportArea ::= ENUMERATED { + cell, + ... +} + +RepetitionPeriod ::= INTEGER (0..131071) + +ResetAll ::= ENUMERATED { + reset-all, + ... +} + +ResetType ::= CHOICE { + nG-Interface ResetAll, + partOfNG-Interface UE-associatedLogicalNG-connectionList, + choice-Extensions ProtocolIE-SingleContainer { {ResetType-ExtIEs} } +} + +ResetType-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +RoutingID ::= OCTET STRING + +RRCContainer ::= OCTET STRING + +RRCEstablishmentCause ::= ENUMERATED { + emergency, + highPriorityAccess, + mt-Access, + mo-Signalling, + mo-Data, + mo-VoiceCall, + mo-VideoCall, + mo-SMS, + mps-PriorityAccess, + mcs-PriorityAccess, + ..., + notAvailable +} + +RRCInactiveTransitionReportRequest ::= ENUMERATED { + subsequent-state-transition-report, + single-rrc-connected-state-report, + cancel-report, + ... +} + +RRCState ::= ENUMERATED { + inactive, + connected, + ... +} + +-- S + +SCTP-TLAs ::= SEQUENCE (SIZE(1..maxnoofXnTLAs)) OF TransportLayerAddress + +SD ::= OCTET STRING (SIZE(3)) + +SecondaryRATUsageInformation ::= SEQUENCE { + pDUSessionUsageReport PDUSessionUsageReport OPTIONAL, + qosFlowsUsageReportList QoSFlowsUsageReportList OPTIONAL, + iE-Extension ProtocolExtensionContainer { {SecondaryRATUsageInformation-ExtIEs} } OPTIONAL, + ... +} + +SecondaryRATUsageInformation-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SecondaryRATDataUsageReportTransfer ::= SEQUENCE { + secondaryRATUsageInformation SecondaryRATUsageInformation OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {SecondaryRATDataUsageReportTransfer-ExtIEs} } OPTIONAL, + ... +} + +SecondaryRATDataUsageReportTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SecurityContext ::= SEQUENCE { + nextHopChainingCount NextHopChainingCount, + nextHopNH SecurityKey, + iE-Extensions ProtocolExtensionContainer { {SecurityContext-ExtIEs} } OPTIONAL, + ... +} + +SecurityContext-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SecurityIndication ::= SEQUENCE { + integrityProtectionIndication IntegrityProtectionIndication, + confidentialityProtectionIndication ConfidentialityProtectionIndication, + maximumIntegrityProtectedDataRate-UL MaximumIntegrityProtectedDataRate OPTIONAL, +-- The above IE shall be present if integrity protection is required or preferred + iE-Extensions ProtocolExtensionContainer { {SecurityIndication-ExtIEs} } OPTIONAL, + ... +} + +SecurityIndication-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-MaximumIntegrityProtectedDataRate-DL CRITICALITY ignore EXTENSION MaximumIntegrityProtectedDataRate PRESENCE optional }, + ... +} + +SecurityKey ::= BIT STRING (SIZE(256)) + +SecurityResult ::= SEQUENCE { + integrityProtectionResult IntegrityProtectionResult, + confidentialityProtectionResult ConfidentialityProtectionResult, + iE-Extensions ProtocolExtensionContainer { {SecurityResult-ExtIEs} } OPTIONAL, + ... +} + +SecurityResult-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SerialNumber ::= BIT STRING (SIZE(16)) + +ServedGUAMIList ::= SEQUENCE (SIZE(1..maxnoofServedGUAMIs)) OF ServedGUAMIItem + +ServedGUAMIItem ::= SEQUENCE { + gUAMI GUAMI, + backupAMFName AMFName OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {ServedGUAMIItem-ExtIEs} } OPTIONAL, + ... +} + +ServedGUAMIItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +ServiceAreaInformation ::= SEQUENCE (SIZE(1.. maxnoofEPLMNsPlusOne)) OF ServiceAreaInformation-Item + +ServiceAreaInformation-Item ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + allowedTACs AllowedTACs OPTIONAL, + notAllowedTACs NotAllowedTACs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {ServiceAreaInformation-Item-ExtIEs} } OPTIONAL, + ... +} + +ServiceAreaInformation-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + + +SliceOverloadList ::= SEQUENCE (SIZE(1..maxnoofSliceItems)) OF SliceOverloadItem + +SliceOverloadItem ::= SEQUENCE { + s-NSSAI S-NSSAI, + iE-Extensions ProtocolExtensionContainer { {SliceOverloadItem-ExtIEs} } OPTIONAL, + ... +} + +SliceOverloadItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SliceSupportList ::= SEQUENCE (SIZE(1..maxnoofSliceItems)) OF SliceSupportItem + +SliceSupportItem ::= SEQUENCE { + s-NSSAI S-NSSAI, + iE-Extensions ProtocolExtensionContainer { {SliceSupportItem-ExtIEs} } OPTIONAL, + ... +} + +SliceSupportItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +S-NSSAI ::= SEQUENCE { + sST SST, + sD SD OPTIONAL, + iE-Extensions ProtocolExtensionContainer { { S-NSSAI-ExtIEs} } OPTIONAL, + ... +} + +S-NSSAI-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SONConfigurationTransfer ::= SEQUENCE { + targetRANNodeID TargetRANNodeID, + sourceRANNodeID SourceRANNodeID, + sONInformation SONInformation, + xnTNLConfigurationInfo XnTNLConfigurationInfo OPTIONAL, +-- The above IE shall be present if the SON Information IE contains the SON Information Request IE set to ¡°Xn TNL Configuration Info¡± + iE-Extensions ProtocolExtensionContainer { {SONConfigurationTransfer-ExtIEs} } OPTIONAL, + ... +} + +SONConfigurationTransfer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SONInformation ::= CHOICE { + sONInformationRequest SONInformationRequest, + sONInformationReply SONInformationReply, + choice-Extensions ProtocolIE-SingleContainer { {SONInformation-ExtIEs} } +} + +SONInformation-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +SONInformationReply ::= SEQUENCE { + xnTNLConfigurationInfo XnTNLConfigurationInfo OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {SONInformationReply-ExtIEs} } OPTIONAL, + ... +} + +SONInformationReply-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SONInformationRequest ::= ENUMERATED { + xn-TNL-configuration-info, + ... +} + +SourceNGRANNode-ToTargetNGRANNode-TransparentContainer ::= SEQUENCE { + rRCContainer RRCContainer, + pDUSessionResourceInformationList PDUSessionResourceInformationList OPTIONAL, + e-RABInformationList E-RABInformationList OPTIONAL, + targetCell-ID NGRAN-CGI, + indexToRFSP IndexToRFSP OPTIONAL, + uEHistoryInformation UEHistoryInformation, + iE-Extensions ProtocolExtensionContainer { {SourceNGRANNode-ToTargetNGRANNode-TransparentContainer-ExtIEs} } OPTIONAL, + ... +} + +SourceNGRANNode-ToTargetNGRANNode-TransparentContainer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SourceOfUEActivityBehaviourInformation ::= ENUMERATED { + subscription-information, + statistics, + ... +} + +SourceRANNodeID ::= SEQUENCE { + globalRANNodeID GlobalRANNodeID, + selectedTAI TAI, + iE-Extensions ProtocolExtensionContainer { {SourceRANNodeID-ExtIEs} } OPTIONAL, + ... +} + +SourceRANNodeID-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +SourceToTarget-TransparentContainer ::= OCTET STRING +-- This IE includes a transparent container from the source RAN node to the target RAN node. +-- The octets of the OCTET STRING are encoded according to the specifications of the target system. + +SourceToTarget-AMFInformationReroute ::= SEQUENCE { +configuredNSSAI ConfiguredNSSAI OPTIONAL, +rejectedNSSAIinPLMN RejectedNSSAIinPLMN OPTIONAL, +rejectedNSSAIinTA RejectedNSSAIinTA OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {SourceToTarget-AMFInformationReroute-ExtIEs} } OPTIONAL, + ... +} + +SourceToTarget-AMFInformationReroute-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- This IE includes information from the source Core node to the target Core node for reroute information provide by NSSF. +-- The octets of the OCTET STRING are encoded according to the specifications of the Core network. + + +ConfiguredNSSAI ::= OCTET STRING (SIZE(128)) + +RejectedNSSAIinPLMN ::= OCTET STRING (SIZE(32)) + +RejectedNSSAIinTA ::= OCTET STRING (SIZE(32)) + +SST ::= OCTET STRING (SIZE(1)) + +SupportedTAList ::= SEQUENCE (SIZE(1..maxnoofTACs)) OF SupportedTAItem + +SupportedTAItem ::= SEQUENCE { + tAC TAC, + broadcastPLMNList BroadcastPLMNList, + iE-Extensions ProtocolExtensionContainer { {SupportedTAItem-ExtIEs} } OPTIONAL, + ... +} + +SupportedTAItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- T + +TAC ::= OCTET STRING (SIZE(3)) + +TAI ::= SEQUENCE { + pLMNIdentity PLMNIdentity, + tAC TAC, + iE-Extensions ProtocolExtensionContainer { {TAI-ExtIEs} } OPTIONAL, + ... +} + +TAI-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TAIBroadcastEUTRA ::= SEQUENCE (SIZE(1..maxnoofTAIforWarning)) OF TAIBroadcastEUTRA-Item + +TAIBroadcastEUTRA-Item ::= SEQUENCE { + tAI TAI, + completedCellsInTAI-EUTRA CompletedCellsInTAI-EUTRA, + iE-Extensions ProtocolExtensionContainer { {TAIBroadcastEUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +TAIBroadcastEUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TAIBroadcastNR ::= SEQUENCE (SIZE(1..maxnoofTAIforWarning)) OF TAIBroadcastNR-Item + +TAIBroadcastNR-Item ::= SEQUENCE { + tAI TAI, + completedCellsInTAI-NR CompletedCellsInTAI-NR, + iE-Extensions ProtocolExtensionContainer { {TAIBroadcastNR-Item-ExtIEs} } OPTIONAL, + ... +} + +TAIBroadcastNR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TAICancelledEUTRA ::= SEQUENCE (SIZE(1..maxnoofTAIforWarning)) OF TAICancelledEUTRA-Item + +TAICancelledEUTRA-Item ::= SEQUENCE { + tAI TAI, + cancelledCellsInTAI-EUTRA CancelledCellsInTAI-EUTRA, + iE-Extensions ProtocolExtensionContainer { {TAICancelledEUTRA-Item-ExtIEs} } OPTIONAL, + ... +} + +TAICancelledEUTRA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TAICancelledNR ::= SEQUENCE (SIZE(1..maxnoofTAIforWarning)) OF TAICancelledNR-Item + +TAICancelledNR-Item ::= SEQUENCE { + tAI TAI, + cancelledCellsInTAI-NR CancelledCellsInTAI-NR, + iE-Extensions ProtocolExtensionContainer { {TAICancelledNR-Item-ExtIEs} } OPTIONAL, + ... +} + +TAICancelledNR-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TAIListForInactive ::= SEQUENCE (SIZE(1..maxnoofTAIforInactive)) OF TAIListForInactiveItem + +TAIListForInactiveItem ::= SEQUENCE { + tAI TAI, + iE-Extensions ProtocolExtensionContainer { {TAIListForInactiveItem-ExtIEs} } OPTIONAL, + ... +} + +TAIListForInactiveItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TAIListForPaging ::= SEQUENCE (SIZE(1..maxnoofTAIforPaging)) OF TAIListForPagingItem + +TAIListForPagingItem ::= SEQUENCE { + tAI TAI, + iE-Extensions ProtocolExtensionContainer { {TAIListForPagingItem-ExtIEs} } OPTIONAL, + ... +} + +TAIListForPagingItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TAIListForRestart ::= SEQUENCE (SIZE(1..maxnoofTAIforRestart)) OF TAI + +TAIListForWarning ::= SEQUENCE (SIZE(1..maxnoofTAIforWarning)) OF TAI + +TargeteNB-ID ::= SEQUENCE { + globalENB-ID GlobalNgENB-ID, + selected-EPS-TAI EPS-TAI, + iE-Extensions ProtocolExtensionContainer { {TargeteNB-ID-ExtIEs} } OPTIONAL, + ... +} + +TargeteNB-ID-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TargetID ::= CHOICE { + targetRANNodeID TargetRANNodeID, + targeteNB-ID TargeteNB-ID, + choice-Extensions ProtocolIE-SingleContainer { {TargetID-ExtIEs} } +} + +TargetID-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +TargetNGRANNode-ToSourceNGRANNode-TransparentContainer ::= SEQUENCE { + rRCContainer RRCContainer, + iE-Extensions ProtocolExtensionContainer { {TargetNGRANNode-ToSourceNGRANNode-TransparentContainer-ExtIEs} } OPTIONAL, + ... +} + +TargetNGRANNode-ToSourceNGRANNode-TransparentContainer-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TargetRANNodeID ::= SEQUENCE { + globalRANNodeID GlobalRANNodeID, + selectedTAI TAI, + iE-Extensions ProtocolExtensionContainer { {TargetRANNodeID-ExtIEs} } OPTIONAL, + ... +} + +TargetRANNodeID-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TargetToSource-TransparentContainer ::= OCTET STRING +-- This IE includes a transparent container from the target RAN node to the source RAN node. +-- The octets of the OCTET STRING are encoded according to the specifications of the target system. + +TimerApproachForGUAMIRemoval ::= ENUMERATED { + apply-timer, + ... +} + +TimeStamp ::= OCTET STRING (SIZE(4)) + +TimeToWait ::= ENUMERATED {v1s, v2s, v5s, v10s, v20s, v60s, ...} + +TimeUEStayedInCell ::= INTEGER (0..4095) + +TimeUEStayedInCellEnhancedGranularity ::= INTEGER (0..40950) + +TNLAddressWeightFactor ::= INTEGER (0..255) + +TNLAssociationList ::= SEQUENCE (SIZE(1..maxnoofTNLAssociations)) OF TNLAssociationItem + +TNLAssociationItem ::= SEQUENCE { + tNLAssociationAddress CPTransportLayerInformation, + cause Cause, + iE-Extensions ProtocolExtensionContainer { {TNLAssociationItem-ExtIEs} } OPTIONAL, + ... +} + +TNLAssociationItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TNLAssociationUsage ::= ENUMERATED { + ue, + non-ue, + both, + ... +} + +TraceActivation ::= SEQUENCE { + nGRANTraceID NGRANTraceID, + interfacesToTrace InterfacesToTrace, + traceDepth TraceDepth, + traceCollectionEntityIPAddress TransportLayerAddress, + iE-Extensions ProtocolExtensionContainer { {TraceActivation-ExtIEs} } OPTIONAL, + ... +} + +TraceActivation-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +TraceDepth ::= ENUMERATED { + minimum, + medium, + maximum, + minimumWithoutVendorSpecificExtension, + mediumWithoutVendorSpecificExtension, + maximumWithoutVendorSpecificExtension, + ... +} + +TrafficLoadReductionIndication ::= INTEGER (1..99) + +TransportLayerAddress ::= BIT STRING (SIZE(1..160, ...)) + +TypeOfError ::= ENUMERATED { + not-understood, + missing, + ... +} + +-- U + +UEAggregateMaximumBitRate ::= SEQUENCE { + uEAggregateMaximumBitRateDL BitRate, + uEAggregateMaximumBitRateUL BitRate, + iE-Extensions ProtocolExtensionContainer { {UEAggregateMaximumBitRate-ExtIEs} } OPTIONAL, + ... +} + +UEAggregateMaximumBitRate-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +UE-associatedLogicalNG-connectionList ::= SEQUENCE (SIZE(1..maxnoofNGConnectionsToReset)) OF UE-associatedLogicalNG-connectionItem + +UE-associatedLogicalNG-connectionItem ::= SEQUENCE { + aMF-UE-NGAP-ID AMF-UE-NGAP-ID OPTIONAL, + rAN-UE-NGAP-ID RAN-UE-NGAP-ID OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {UE-associatedLogicalNG-connectionItem-ExtIEs} } OPTIONAL, + ... +} + +UE-associatedLogicalNG-connectionItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ...} + +UEContextRequest ::= ENUMERATED {requested, ...} + +UEHistoryInformation ::= SEQUENCE (SIZE(1..maxnoofCellsinUEHistoryInfo)) OF LastVisitedCellItem + +UEIdentityIndexValue ::= CHOICE { + indexLength10 BIT STRING (SIZE(10)), + choice-Extensions ProtocolIE-SingleContainer { {UEIdentityIndexValue-ExtIEs} } +} + +UEIdentityIndexValue-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +UE-NGAP-IDs ::= CHOICE { + uE-NGAP-ID-pair UE-NGAP-ID-pair, + aMF-UE-NGAP-ID AMF-UE-NGAP-ID, + choice-Extensions ProtocolIE-SingleContainer { {UE-NGAP-IDs-ExtIEs} } +} + +UE-NGAP-IDs-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +UE-NGAP-ID-pair ::= SEQUENCE{ + aMF-UE-NGAP-ID AMF-UE-NGAP-ID, + rAN-UE-NGAP-ID RAN-UE-NGAP-ID, + iE-Extensions ProtocolExtensionContainer { {UE-NGAP-ID-pair-ExtIEs} } OPTIONAL, + ... +} + +UE-NGAP-ID-pair-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +UEPagingIdentity ::= CHOICE { + fiveG-S-TMSI FiveG-S-TMSI, + choice-Extensions ProtocolIE-SingleContainer { {UEPagingIdentity-ExtIEs} } + } + +UEPagingIdentity-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +UEPresence ::= ENUMERATED {in, out, unknown, ...} + +UEPresenceInAreaOfInterestList ::= SEQUENCE (SIZE(1..maxnoofAoI)) OF UEPresenceInAreaOfInterestItem + +UEPresenceInAreaOfInterestItem ::= SEQUENCE { + locationReportingReferenceID LocationReportingReferenceID, + uEPresence UEPresence, + iE-Extensions ProtocolExtensionContainer { {UEPresenceInAreaOfInterestItem-ExtIEs} } OPTIONAL, + ... +} + +UEPresenceInAreaOfInterestItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +UERadioCapability ::= OCTET STRING + +UERadioCapabilityForPaging ::= SEQUENCE { + uERadioCapabilityForPagingOfNR UERadioCapabilityForPagingOfNR OPTIONAL, + uERadioCapabilityForPagingOfEUTRA UERadioCapabilityForPagingOfEUTRA OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {UERadioCapabilityForPaging-ExtIEs} } OPTIONAL, + ... +} + +UERadioCapabilityForPaging-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +UERadioCapabilityForPagingOfNR ::= OCTET STRING + +UERadioCapabilityForPagingOfEUTRA ::= OCTET STRING + +UERetentionInformation ::= ENUMERATED { + ues-retained, + ... +} + +UESecurityCapabilities ::= SEQUENCE { + nRencryptionAlgorithms NRencryptionAlgorithms, + nRintegrityProtectionAlgorithms NRintegrityProtectionAlgorithms, + eUTRAencryptionAlgorithms EUTRAencryptionAlgorithms, + eUTRAintegrityProtectionAlgorithms EUTRAintegrityProtectionAlgorithms, + + iE-Extensions ProtocolExtensionContainer { {UESecurityCapabilities-ExtIEs} } OPTIONAL, + ... +} + +UESecurityCapabilities-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +UL-NGU-UP-TNLModifyList ::= SEQUENCE (SIZE(1..maxnoofMultiConnectivity)) OF UL-NGU-UP-TNLModifyItem + +UL-NGU-UP-TNLModifyItem ::= SEQUENCE { + uL-NGU-UP-TNLInformation UPTransportLayerInformation, + dL-NGU-UP-TNLInformation UPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { {UL-NGU-UP-TNLModifyItem-ExtIEs} } OPTIONAL, + ... +} + +UL-NGU-UP-TNLModifyItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +UnavailableGUAMIList ::= SEQUENCE (SIZE(1..maxnoofServedGUAMIs)) OF UnavailableGUAMIItem + +UnavailableGUAMIItem ::= SEQUENCE { + gUAMI GUAMI, + timerApproachForGUAMIRemoval TimerApproachForGUAMIRemoval OPTIONAL, + backupAMFName AMFName OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {UnavailableGUAMIItem-ExtIEs} } OPTIONAL, + ... +} + +UnavailableGUAMIItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +ULForwarding ::= ENUMERATED { + ul-forwarding-proposed, + ... +} + +UPTransportLayerInformation ::= CHOICE { + gTPTunnel GTPTunnel, + choice-Extensions ProtocolIE-SingleContainer { {UPTransportLayerInformation-ExtIEs} } +} + +UPTransportLayerInformation-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +UPTransportLayerInformationList ::= SEQUENCE (SIZE(1..maxnoofMultiConnectivityMinusOne)) OF UPTransportLayerInformationItem + +UPTransportLayerInformationItem ::= SEQUENCE { + nGU-UP-TNLInformation UPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { {UPTransportLayerInformationItem-ExtIEs} } OPTIONAL, + ... +} + +UPTransportLayerInformationItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + + +UPTransportLayerInformationPairList ::= SEQUENCE (SIZE(1..maxnoofMultiConnectivityMinusOne)) OF UPTransportLayerInformationPairItem + +UPTransportLayerInformationPairItem ::= SEQUENCE { + uL-NGU-UP-TNLInformation UPTransportLayerInformation, + dL-NGU-UP-TNLInformation UPTransportLayerInformation, + iE-Extensions ProtocolExtensionContainer { {UPTransportLayerInformationPairItem-ExtIEs} } OPTIONAL, + ... +} + +UPTransportLayerInformationPairItem-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +UserLocationInformation ::= CHOICE { + userLocationInformationEUTRA UserLocationInformationEUTRA, + userLocationInformationNR UserLocationInformationNR, + userLocationInformationN3IWF UserLocationInformationN3IWF, + choice-Extensions ProtocolIE-SingleContainer { {UserLocationInformation-ExtIEs} } +} + +UserLocationInformation-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +UserLocationInformationEUTRA ::= SEQUENCE { + eUTRA-CGI EUTRA-CGI, + tAI TAI, + timeStamp TimeStamp OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {UserLocationInformationEUTRA-ExtIEs} } OPTIONAL, + ... +} + +UserLocationInformationEUTRA-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-PSCellInformation CRITICALITY ignore EXTENSION NGRAN-CGI PRESENCE optional}, + ... +} + +UserLocationInformationN3IWF ::= SEQUENCE { + iPAddress TransportLayerAddress, + portNumber PortNumber, + iE-Extensions ProtocolExtensionContainer { {UserLocationInformationN3IWF-ExtIEs} } OPTIONAL, + ... +} + +UserLocationInformationN3IWF-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +UserLocationInformationNR ::= SEQUENCE { + nR-CGI NR-CGI, + tAI TAI, + timeStamp TimeStamp OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {UserLocationInformationNR-ExtIEs} } OPTIONAL, + ... +} + +UserLocationInformationNR-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-PSCellInformation CRITICALITY ignore EXTENSION NGRAN-CGI PRESENCE optional}, + ... +} + +UserPlaneSecurityInformation ::= SEQUENCE { + securityResult SecurityResult, + securityIndication SecurityIndication, + iE-Extensions ProtocolExtensionContainer { {UserPlaneSecurityInformation-ExtIEs} } OPTIONAL, + ... +} + +UserPlaneSecurityInformation-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- V + +VolumeTimedReportList ::= SEQUENCE (SIZE(1..maxnoofTimePeriods)) OF VolumeTimedReport-Item + +VolumeTimedReport-Item ::= SEQUENCE { + startTimeStamp OCTET STRING (SIZE(4)), + endTimeStamp OCTET STRING (SIZE(4)), + usageCountUL INTEGER (0..18446744073709551615), + usageCountDL INTEGER (0..18446744073709551615), + iE-Extensions ProtocolExtensionContainer { {VolumeTimedReport-Item-ExtIEs} } OPTIONAL, +... +} + +VolumeTimedReport-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- W + +WarningAreaCoordinates ::= OCTET STRING (SIZE(1..1024)) + +WarningAreaList ::= CHOICE { + eUTRA-CGIListForWarning EUTRA-CGIListForWarning, + nR-CGIListForWarning NR-CGIListForWarning, + tAIListForWarning TAIListForWarning, + emergencyAreaIDList EmergencyAreaIDList, + choice-Extensions ProtocolIE-SingleContainer { {WarningAreaList-ExtIEs} } +} + +WarningAreaList-ExtIEs NGAP-PROTOCOL-IES ::= { + ... +} + +WarningMessageContents ::= OCTET STRING (SIZE(1..9600)) + +WarningSecurityInfo ::= OCTET STRING (SIZE(50)) + +WarningType ::= OCTET STRING (SIZE(2)) + +-- X + +XnExtTLAs ::= SEQUENCE (SIZE(1..maxnoofXnExtTLAs)) OF XnExtTLA-Item + +XnExtTLA-Item ::= SEQUENCE { + iPsecTLA TransportLayerAddress OPTIONAL, + gTP-TLAs XnGTP-TLAs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {XnExtTLA-Item-ExtIEs} } OPTIONAL, + ... +} + +XnExtTLA-Item-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + { ID id-SCTP-TLAs CRITICALITY ignore EXTENSION SCTP-TLAs PRESENCE optional }, + ... +} + +XnGTP-TLAs ::= SEQUENCE (SIZE(1..maxnoofXnGTP-TLAs)) OF TransportLayerAddress + +XnTLAs ::= SEQUENCE (SIZE(1..maxnoofXnTLAs)) OF TransportLayerAddress + +XnTNLConfigurationInfo ::= SEQUENCE { + xnTransportLayerAddresses XnTLAs, + xnExtendedTransportLayerAddresses XnExtTLAs OPTIONAL, + iE-Extensions ProtocolExtensionContainer { {XnTNLConfigurationInfo-ExtIEs} } OPTIONAL, + ... +} + +XnTNLConfigurationInfo-ExtIEs NGAP-PROTOCOL-EXTENSION ::= { + ... +} + +-- Y +-- Z + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- Common definitions +-- +-- ************************************************************** + +NGAP-CommonDataTypes { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-Access (22) modules (3) ngap (1) version1 (1) ngap-CommonDataTypes (3) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +Criticality ::= ENUMERATED { reject, ignore, notify } + +Presence ::= ENUMERATED { optional, conditional, mandatory } + +PrivateIE-ID ::= CHOICE { + local INTEGER (0..65535), + global OBJECT IDENTIFIER +} + +ProcedureCode ::= INTEGER (0..255) + +ProtocolExtensionID ::= INTEGER (0..65535) + +ProtocolIE-ID ::= INTEGER (0..65535) + +TriggeringMessage ::= ENUMERATED { initiating-message, successful-outcome, unsuccessfull-outcome } + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- Constant definitions +-- +-- ************************************************************** + +NGAP-Constants { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-Access (22) modules (3) ngap (1) version1 (1) ngap-Constants (4) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + + ProcedureCode, + ProtocolIE-ID +FROM NGAP-CommonDataTypes; + + +-- ************************************************************** +-- +-- Elementary Procedures +-- +-- ************************************************************** + +id-AMFConfigurationUpdate ProcedureCode ::= 0 +id-AMFStatusIndication ProcedureCode ::= 1 +id-CellTrafficTrace ProcedureCode ::= 2 +id-DeactivateTrace ProcedureCode ::= 3 +id-DownlinkNASTransport ProcedureCode ::= 4 +id-DownlinkNonUEAssociatedNRPPaTransport ProcedureCode ::= 5 +id-DownlinkRANConfigurationTransfer ProcedureCode ::= 6 +id-DownlinkRANStatusTransfer ProcedureCode ::= 7 +id-DownlinkUEAssociatedNRPPaTransport ProcedureCode ::= 8 +id-ErrorIndication ProcedureCode ::= 9 +id-HandoverCancel ProcedureCode ::= 10 +id-HandoverNotification ProcedureCode ::= 11 +id-HandoverPreparation ProcedureCode ::= 12 +id-HandoverResourceAllocation ProcedureCode ::= 13 +id-InitialContextSetup ProcedureCode ::= 14 +id-InitialUEMessage ProcedureCode ::= 15 +id-LocationReportingControl ProcedureCode ::= 16 +id-LocationReportingFailureIndication ProcedureCode ::= 17 +id-LocationReport ProcedureCode ::= 18 +id-NASNonDeliveryIndication ProcedureCode ::= 19 +id-NGReset ProcedureCode ::= 20 +id-NGSetup ProcedureCode ::= 21 +id-OverloadStart ProcedureCode ::= 22 +id-OverloadStop ProcedureCode ::= 23 +id-Paging ProcedureCode ::= 24 +id-PathSwitchRequest ProcedureCode ::= 25 +id-PDUSessionResourceModify ProcedureCode ::= 26 +id-PDUSessionResourceModifyIndication ProcedureCode ::= 27 +id-PDUSessionResourceRelease ProcedureCode ::= 28 +id-PDUSessionResourceSetup ProcedureCode ::= 29 +id-PDUSessionResourceNotify ProcedureCode ::= 30 +id-PrivateMessage ProcedureCode ::= 31 +id-PWSCancel ProcedureCode ::= 32 +id-PWSFailureIndication ProcedureCode ::= 33 +id-PWSRestartIndication ProcedureCode ::= 34 +id-RANConfigurationUpdate ProcedureCode ::= 35 +id-RerouteNASRequest ProcedureCode ::= 36 +id-RRCInactiveTransitionReport ProcedureCode ::= 37 +id-TraceFailureIndication ProcedureCode ::= 38 +id-TraceStart ProcedureCode ::= 39 +id-UEContextModification ProcedureCode ::= 40 +id-UEContextRelease ProcedureCode ::= 41 +id-UEContextReleaseRequest ProcedureCode ::= 42 +id-UERadioCapabilityCheck ProcedureCode ::= 43 +id-UERadioCapabilityInfoIndication ProcedureCode ::= 44 +id-UETNLABindingRelease ProcedureCode ::= 45 +id-UplinkNASTransport ProcedureCode ::= 46 +id-UplinkNonUEAssociatedNRPPaTransport ProcedureCode ::= 47 +id-UplinkRANConfigurationTransfer ProcedureCode ::= 48 +id-UplinkRANStatusTransfer ProcedureCode ::= 49 +id-UplinkUEAssociatedNRPPaTransport ProcedureCode ::= 50 +id-WriteReplaceWarning ProcedureCode ::= 51 +id-SecondaryRATDataUsageReport ProcedureCode ::= 52 + +-- ************************************************************** +-- +-- Extension constants +-- +-- ************************************************************** + +maxPrivateIEs INTEGER ::= 65535 +maxProtocolExtensions INTEGER ::= 65535 +maxProtocolIEs INTEGER ::= 65535 + +-- ************************************************************** +-- +-- Lists +-- +-- ************************************************************** + + maxnoofAllowedAreas INTEGER ::= 16 + maxnoofAllowedS-NSSAIs INTEGER ::= 8 + maxnoofBPLMNs INTEGER ::= 12 + maxnoofCellIDforWarning INTEGER ::= 65535 + maxnoofCellinAoI INTEGER ::= 256 + maxnoofCellinEAI INTEGER ::= 65535 + maxnoofCellinTAI INTEGER ::= 65535 + maxnoofCellsingNB INTEGER ::= 16384 + maxnoofCellsinngeNB INTEGER ::= 256 + maxnoofCellsinUEHistoryInfo INTEGER ::= 16 + maxnoofCellsUEMovingTrajectory INTEGER ::= 16 + maxnoofDRBs INTEGER ::= 32 + maxnoofEmergencyAreaID INTEGER ::= 65535 + maxnoofEAIforRestart INTEGER ::= 256 + maxnoofEPLMNs INTEGER ::= 15 + maxnoofEPLMNsPlusOne INTEGER ::= 16 + maxnoofE-RABs INTEGER ::= 256 + maxnoofErrors INTEGER ::= 256 + maxnoofForbTACs INTEGER ::= 4096 + maxnoofMultiConnectivity INTEGER ::= 4 + maxnoofMultiConnectivityMinusOne INTEGER ::= 3 + maxnoofNGConnectionsToReset INTEGER ::= 65536 + maxnoofPDUSessions INTEGER ::= 256 + maxnoofPLMNs INTEGER ::= 12 + maxnoofQosFlows INTEGER ::= 64 + maxnoofRANNodeinAoI INTEGER ::= 64 + maxnoofRecommendedCells INTEGER ::= 16 + maxnoofRecommendedRANNodes INTEGER ::= 16 + maxnoofAoI INTEGER ::= 64 + maxnoofServedGUAMIs INTEGER ::= 256 + maxnoofSliceItems INTEGER ::= 1024 + maxnoofTACs INTEGER ::= 256 + maxnoofTAIforInactive INTEGER ::= 16 + maxnoofTAIforPaging INTEGER ::= 16 + maxnoofTAIforRestart INTEGER ::= 2048 + maxnoofTAIforWarning INTEGER ::= 65535 + maxnoofTAIinAoI INTEGER ::= 16 + maxnoofTimePeriods INTEGER ::= 2 + maxnoofTNLAssociations INTEGER ::= 32 + maxnoofXnExtTLAs INTEGER ::= 16 + maxnoofXnGTP-TLAs INTEGER ::= 16 + maxnoofXnTLAs INTEGER ::= 2 + +-- ************************************************************** +-- +-- IEs +-- +-- ************************************************************** + + id-AllowedNSSAI ProtocolIE-ID ::= 0 + id-AMFName ProtocolIE-ID ::= 1 + id-AMFOverloadResponse ProtocolIE-ID ::= 2 + id-AMFSetID ProtocolIE-ID ::= 3 + id-AMF-TNLAssociationFailedToSetupList ProtocolIE-ID ::= 4 + id-AMF-TNLAssociationSetupList ProtocolIE-ID ::= 5 + id-AMF-TNLAssociationToAddList ProtocolIE-ID ::= 6 + id-AMF-TNLAssociationToRemoveList ProtocolIE-ID ::= 7 + id-AMF-TNLAssociationToUpdateList ProtocolIE-ID ::= 8 + id-AMFTrafficLoadReductionIndication ProtocolIE-ID ::= 9 + id-AMF-UE-NGAP-ID ProtocolIE-ID ::= 10 + id-AssistanceDataForPaging ProtocolIE-ID ::= 11 + id-BroadcastCancelledAreaList ProtocolIE-ID ::= 12 + id-BroadcastCompletedAreaList ProtocolIE-ID ::= 13 + id-CancelAllWarningMessages ProtocolIE-ID ::= 14 + id-Cause ProtocolIE-ID ::= 15 + id-CellIDListForRestart ProtocolIE-ID ::= 16 + id-ConcurrentWarningMessageInd ProtocolIE-ID ::= 17 + id-CoreNetworkAssistanceInformationForInactive ProtocolIE-ID ::= 18 + id-CriticalityDiagnostics ProtocolIE-ID ::= 19 + id-DataCodingScheme ProtocolIE-ID ::= 20 + id-DefaultPagingDRX ProtocolIE-ID ::= 21 + id-DirectForwardingPathAvailability ProtocolIE-ID ::= 22 + id-EmergencyAreaIDListForRestart ProtocolIE-ID ::= 23 + id-EmergencyFallbackIndicator ProtocolIE-ID ::= 24 + id-EUTRA-CGI ProtocolIE-ID ::= 25 + id-FiveG-S-TMSI ProtocolIE-ID ::= 26 + id-GlobalRANNodeID ProtocolIE-ID ::= 27 + id-GUAMI ProtocolIE-ID ::= 28 + id-HandoverType ProtocolIE-ID ::= 29 + id-IMSVoiceSupportIndicator ProtocolIE-ID ::= 30 + id-IndexToRFSP ProtocolIE-ID ::= 31 + id-InfoOnRecommendedCellsAndRANNodesForPaging ProtocolIE-ID ::= 32 + id-LocationReportingRequestType ProtocolIE-ID ::= 33 + id-MaskedIMEISV ProtocolIE-ID ::= 34 + id-MessageIdentifier ProtocolIE-ID ::= 35 + id-MobilityRestrictionList ProtocolIE-ID ::= 36 + id-NASC ProtocolIE-ID ::= 37 + id-NAS-PDU ProtocolIE-ID ::= 38 + id-NASSecurityParametersFromNGRAN ProtocolIE-ID ::= 39 + id-NewAMF-UE-NGAP-ID ProtocolIE-ID ::= 40 + id-NewSecurityContextInd ProtocolIE-ID ::= 41 + id-NGAP-Message ProtocolIE-ID ::= 42 + id-NGRAN-CGI ProtocolIE-ID ::= 43 + id-NGRANTraceID ProtocolIE-ID ::= 44 + id-NR-CGI ProtocolIE-ID ::= 45 + id-NRPPa-PDU ProtocolIE-ID ::= 46 + id-NumberOfBroadcastsRequested ProtocolIE-ID ::= 47 + id-OldAMF ProtocolIE-ID ::= 48 + id-OverloadStartNSSAIList ProtocolIE-ID ::= 49 + id-PagingDRX ProtocolIE-ID ::= 50 + id-PagingOrigin ProtocolIE-ID ::= 51 + id-PagingPriority ProtocolIE-ID ::= 52 + id-PDUSessionResourceAdmittedList ProtocolIE-ID ::= 53 + id-PDUSessionResourceFailedToModifyListModRes ProtocolIE-ID ::= 54 + id-PDUSessionResourceFailedToSetupListCxtRes ProtocolIE-ID ::= 55 + id-PDUSessionResourceFailedToSetupListHOAck ProtocolIE-ID ::= 56 + id-PDUSessionResourceFailedToSetupListPSReq ProtocolIE-ID ::= 57 + id-PDUSessionResourceFailedToSetupListSURes ProtocolIE-ID ::= 58 + id-PDUSessionResourceHandoverList ProtocolIE-ID ::= 59 + id-PDUSessionResourceListCxtRelCpl ProtocolIE-ID ::= 60 + id-PDUSessionResourceListHORqd ProtocolIE-ID ::= 61 + id-PDUSessionResourceModifyListModCfm ProtocolIE-ID ::= 62 + id-PDUSessionResourceModifyListModInd ProtocolIE-ID ::= 63 + id-PDUSessionResourceModifyListModReq ProtocolIE-ID ::= 64 + id-PDUSessionResourceModifyListModRes ProtocolIE-ID ::= 65 + id-PDUSessionResourceNotifyList ProtocolIE-ID ::= 66 + id-PDUSessionResourceReleasedListNot ProtocolIE-ID ::= 67 + id-PDUSessionResourceReleasedListPSAck ProtocolIE-ID ::= 68 + id-PDUSessionResourceReleasedListPSFail ProtocolIE-ID ::= 69 + id-PDUSessionResourceReleasedListRelRes ProtocolIE-ID ::= 70 + id-PDUSessionResourceSetupListCxtReq ProtocolIE-ID ::= 71 + id-PDUSessionResourceSetupListCxtRes ProtocolIE-ID ::= 72 + id-PDUSessionResourceSetupListHOReq ProtocolIE-ID ::= 73 + id-PDUSessionResourceSetupListSUReq ProtocolIE-ID ::= 74 + id-PDUSessionResourceSetupListSURes ProtocolIE-ID ::= 75 + id-PDUSessionResourceToBeSwitchedDLList ProtocolIE-ID ::= 76 + id-PDUSessionResourceSwitchedList ProtocolIE-ID ::= 77 + id-PDUSessionResourceToReleaseListHOCmd ProtocolIE-ID ::= 78 + id-PDUSessionResourceToReleaseListRelCmd ProtocolIE-ID ::= 79 + id-PLMNSupportList ProtocolIE-ID ::= 80 + id-PWSFailedCellIDList ProtocolIE-ID ::= 81 + id-RANNodeName ProtocolIE-ID ::= 82 + id-RANPagingPriority ProtocolIE-ID ::= 83 + id-RANStatusTransfer-TransparentContainer ProtocolIE-ID ::= 84 + id-RAN-UE-NGAP-ID ProtocolIE-ID ::= 85 + id-RelativeAMFCapacity ProtocolIE-ID ::= 86 + id-RepetitionPeriod ProtocolIE-ID ::= 87 + id-ResetType ProtocolIE-ID ::= 88 + id-RoutingID ProtocolIE-ID ::= 89 + id-RRCEstablishmentCause ProtocolIE-ID ::= 90 + id-RRCInactiveTransitionReportRequest ProtocolIE-ID ::= 91 + id-RRCState ProtocolIE-ID ::= 92 + id-SecurityContext ProtocolIE-ID ::= 93 + id-SecurityKey ProtocolIE-ID ::= 94 + id-SerialNumber ProtocolIE-ID ::= 95 + id-ServedGUAMIList ProtocolIE-ID ::= 96 + id-SliceSupportList ProtocolIE-ID ::= 97 + id-SONConfigurationTransferDL ProtocolIE-ID ::= 98 + id-SONConfigurationTransferUL ProtocolIE-ID ::= 99 + id-SourceAMF-UE-NGAP-ID ProtocolIE-ID ::= 100 + id-SourceToTarget-TransparentContainer ProtocolIE-ID ::= 101 + id-SupportedTAList ProtocolIE-ID ::= 102 + id-TAIListForPaging ProtocolIE-ID ::= 103 + id-TAIListForRestart ProtocolIE-ID ::= 104 + id-TargetID ProtocolIE-ID ::= 105 + id-TargetToSource-TransparentContainer ProtocolIE-ID ::= 106 + id-TimeToWait ProtocolIE-ID ::= 107 + id-TraceActivation ProtocolIE-ID ::= 108 + id-TraceCollectionEntityIPAddress ProtocolIE-ID ::= 109 + id-UEAggregateMaximumBitRate ProtocolIE-ID ::= 110 + id-UE-associatedLogicalNG-connectionList ProtocolIE-ID ::= 111 + id-UEContextRequest ProtocolIE-ID ::= 112 + id-UE-NGAP-IDs ProtocolIE-ID ::= 114 + id-UEPagingIdentity ProtocolIE-ID ::= 115 + id-UEPresenceInAreaOfInterestList ProtocolIE-ID ::= 116 + id-UERadioCapability ProtocolIE-ID ::= 117 + id-UERadioCapabilityForPaging ProtocolIE-ID ::= 118 + id-UESecurityCapabilities ProtocolIE-ID ::= 119 + id-UnavailableGUAMIList ProtocolIE-ID ::= 120 + id-UserLocationInformation ProtocolIE-ID ::= 121 + id-WarningAreaList ProtocolIE-ID ::= 122 + id-WarningMessageContents ProtocolIE-ID ::= 123 + id-WarningSecurityInfo ProtocolIE-ID ::= 124 + id-WarningType ProtocolIE-ID ::= 125 + id-AdditionalUL-NGU-UP-TNLInformation ProtocolIE-ID ::= 126 + id-DataForwardingNotPossible ProtocolIE-ID ::= 127 + id-DL-NGU-UP-TNLInformation ProtocolIE-ID ::= 128 + id-NetworkInstance ProtocolIE-ID ::= 129 + id-PDUSessionAggregateMaximumBitRate ProtocolIE-ID ::= 130 + id-PDUSessionResourceFailedToModifyListModCfm ProtocolIE-ID ::= 131 + id-PDUSessionResourceFailedToSetupListCxtFail ProtocolIE-ID ::= 132 + id-PDUSessionResourceListCxtRelReq ProtocolIE-ID ::= 133 + id-PDUSessionType ProtocolIE-ID ::= 134 + id-QosFlowAddOrModifyRequestList ProtocolIE-ID ::= 135 + id-QosFlowSetupRequestList ProtocolIE-ID ::= 136 + id-QosFlowToReleaseList ProtocolIE-ID ::= 137 + id-SecurityIndication ProtocolIE-ID ::= 138 + id-UL-NGU-UP-TNLInformation ProtocolIE-ID ::= 139 + id-UL-NGU-UP-TNLModifyList ProtocolIE-ID ::= 140 + id-WarningAreaCoordinates ProtocolIE-ID ::= 141 + id-PDUSessionResourceSecondaryRATUsageList ProtocolIE-ID ::= 142 + id-HandoverFlag ProtocolIE-ID ::= 143 + id-SecondaryRATUsageInformation ProtocolIE-ID ::= 144 + id-PDUSessionResourceReleaseResponseTransfer ProtocolIE-ID ::= 145 + id-RedirectionVoiceFallback ProtocolIE-ID ::= 146 + id-UERetentionInformation ProtocolIE-ID ::= 147 + id-S-NSSAI ProtocolIE-ID ::= 148 + id-PSCellInformation ProtocolIE-ID ::= 149 + id-LastEUTRAN-PLMNIdentity ProtocolIE-ID ::= 150 + id-MaximumIntegrityProtectedDataRate-DL ProtocolIE-ID ::= 151 + id-AdditionalDLForwardingUPTNLInformation ProtocolIE-ID ::= 152 + id-AdditionalDLUPTNLInformationForHOList ProtocolIE-ID ::= 153 + id-AdditionalNGU-UP-TNLInformation ProtocolIE-ID ::= 154 + id-AdditionalDLQosFlowPerTNLInformation ProtocolIE-ID ::= 155 + id-SecurityResult ProtocolIE-ID ::= 156 + id-ENDC-SONConfigurationTransferDL ProtocolIE-ID ::= 157 + id-ENDC-SONConfigurationTransferUL ProtocolIE-ID ::= 158 + id-OldAssociatedQosFlowList-ULendmarkerexpected ProtocolIE-ID ::= 159 + id-CNTypeRestrictionsForEquivalent ProtocolIE-ID ::= 160 + id-CNTypeRestrictionsForServing ProtocolIE-ID ::= 161 + id-NewGUAMI ProtocolIE-ID ::= 162 + id-ULForwarding ProtocolIE-ID ::= 163 + id-ULForwardingUP-TNLInformation ProtocolIE-ID ::= 164 + id-CNAssistedRANTuning ProtocolIE-ID ::= 165 + id-CommonNetworkInstance ProtocolIE-ID ::= 166 + id-NGRAN-TNLAssociationToRemoveList ProtocolIE-ID ::= 167 + id-TNLAssociationTransportLayerAddressNGRAN ProtocolIE-ID ::= 168 + id-EndpointIPAddressAndPort ProtocolIE-ID ::= 169 + id-LocationReportingAdditionalInfo ProtocolIE-ID ::= 170 + id-SourceToTarget-AMFInformationReroute ProtocolIE-ID ::= 171 + id-AdditionalULForwardingUPTNLInformation ProtocolIE-ID ::= 172 + id-SCTP-TLAs ProtocolIE-ID ::= 173 + id-SelectedPLMNIdentity ProtocolIE-ID ::= 174 + + +END +-- ASN1STOP + +-- ASN1START +-- ************************************************************** +-- +-- Container definitions +-- +-- ************************************************************** + +NGAP-Containers { +itu-t (0) identified-organization (4) etsi (0) mobileDomain (0) +ngran-Access (22) modules (3) ngap (1) version1 (1) ngap-Containers (5) } + +DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- ************************************************************** +-- +-- IE parameter types from other modules. +-- +-- ************************************************************** + +IMPORTS + + Criticality, + Presence, + PrivateIE-ID, + ProtocolExtensionID, + ProtocolIE-ID +FROM NGAP-CommonDataTypes + + maxPrivateIEs, + maxProtocolExtensions, + maxProtocolIEs +FROM NGAP-Constants; + +-- ************************************************************** +-- +-- Class Definition for Protocol IEs +-- +-- ************************************************************** + +NGAP-PROTOCOL-IES ::= CLASS { + &id ProtocolIE-ID UNIQUE, + &criticality Criticality, + &Value, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + TYPE &Value + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Protocol IEs +-- +-- ************************************************************** + +NGAP-PROTOCOL-IES-PAIR ::= CLASS { + &id ProtocolIE-ID UNIQUE, + &firstCriticality Criticality, + &FirstValue, + &secondCriticality Criticality, + &SecondValue, + &presence Presence +} +WITH SYNTAX { + ID &id + FIRST CRITICALITY &firstCriticality + FIRST TYPE &FirstValue + SECOND CRITICALITY &secondCriticality + SECOND TYPE &SecondValue + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Protocol Extensions +-- +-- ************************************************************** + +NGAP-PROTOCOL-EXTENSION ::= CLASS { + &id ProtocolExtensionID UNIQUE, + &criticality Criticality, + &Extension, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + EXTENSION &Extension + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Class Definition for Private IEs +-- +-- ************************************************************** + +NGAP-PRIVATE-IES ::= CLASS { + &id PrivateIE-ID, + &criticality Criticality, + &Value, + &presence Presence +} +WITH SYNTAX { + ID &id + CRITICALITY &criticality + TYPE &Value + PRESENCE &presence +} + +-- ************************************************************** +-- +-- Container for Protocol IEs +-- +-- ************************************************************** + +ProtocolIE-Container {NGAP-PROTOCOL-IES : IEsSetParam} ::= + SEQUENCE (SIZE (0..maxProtocolIEs)) OF + ProtocolIE-Field {{IEsSetParam}} + +ProtocolIE-SingleContainer {NGAP-PROTOCOL-IES : IEsSetParam} ::= + ProtocolIE-Field {{IEsSetParam}} + +ProtocolIE-Field {NGAP-PROTOCOL-IES : IEsSetParam} ::= SEQUENCE { + id NGAP-PROTOCOL-IES.&id ({IEsSetParam}), + criticality NGAP-PROTOCOL-IES.&criticality ({IEsSetParam}{@id}), + value NGAP-PROTOCOL-IES.&Value ({IEsSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container for Protocol IE Pairs +-- +-- ************************************************************** + +ProtocolIE-ContainerPair {NGAP-PROTOCOL-IES-PAIR : IEsSetParam} ::= + SEQUENCE (SIZE (0..maxProtocolIEs)) OF + ProtocolIE-FieldPair {{IEsSetParam}} + +ProtocolIE-FieldPair {NGAP-PROTOCOL-IES-PAIR : IEsSetParam} ::= SEQUENCE { + id NGAP-PROTOCOL-IES-PAIR.&id ({IEsSetParam}), + firstCriticality NGAP-PROTOCOL-IES-PAIR.&firstCriticality ({IEsSetParam}{@id}), + firstValue NGAP-PROTOCOL-IES-PAIR.&FirstValue ({IEsSetParam}{@id}), + secondCriticality NGAP-PROTOCOL-IES-PAIR.&secondCriticality ({IEsSetParam}{@id}), + secondValue NGAP-PROTOCOL-IES-PAIR.&SecondValue ({IEsSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container Lists for Protocol IE Containers +-- +-- ************************************************************** + +ProtocolIE-ContainerList {INTEGER : lowerBound, INTEGER : upperBound, NGAP-PROTOCOL-IES : IEsSetParam} ::= + SEQUENCE (SIZE (lowerBound..upperBound)) OF + ProtocolIE-SingleContainer {{IEsSetParam}} + +ProtocolIE-ContainerPairList {INTEGER : lowerBound, INTEGER : upperBound, NGAP-PROTOCOL-IES-PAIR : IEsSetParam} ::= + SEQUENCE (SIZE (lowerBound..upperBound)) OF + ProtocolIE-ContainerPair {{IEsSetParam}} + +-- ************************************************************** +-- +-- Container for Protocol Extensions +-- +-- ************************************************************** + +ProtocolExtensionContainer {NGAP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= + SEQUENCE (SIZE (1..maxProtocolExtensions)) OF + ProtocolExtensionField {{ExtensionSetParam}} + +ProtocolExtensionField {NGAP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= SEQUENCE { + id NGAP-PROTOCOL-EXTENSION.&id ({ExtensionSetParam}), + criticality NGAP-PROTOCOL-EXTENSION.&criticality ({ExtensionSetParam}{@id}), + extensionValue NGAP-PROTOCOL-EXTENSION.&Extension ({ExtensionSetParam}{@id}) +} + +-- ************************************************************** +-- +-- Container for Private IEs +-- +-- ************************************************************** + +PrivateIE-Container {NGAP-PRIVATE-IES : IEsSetParam } ::= + SEQUENCE (SIZE (1..maxPrivateIEs)) OF + PrivateIE-Field {{IEsSetParam}} + +PrivateIE-Field {NGAP-PRIVATE-IES : IEsSetParam} ::= SEQUENCE { + id NGAP-PRIVATE-IES.&id ({IEsSetParam}), + criticality NGAP-PRIVATE-IES.&criticality ({IEsSetParam}{@id}), + value NGAP-PRIVATE-IES.&Value ({IEsSetParam}{@id}) +} + +END +-- ASN1STOP \ No newline at end of file diff --git a/common/utils/itti_analyzer/libparser/field_type.h b/openair3/NGAP/ngap_common.c similarity index 70% rename from common/utils/itti_analyzer/libparser/field_type.h rename to openair3/NGAP/ngap_common.c index 329e90c3be..53b04e09eb 100644 --- a/common/utils/itti_analyzer/libparser/field_type.h +++ b/openair3/NGAP/ngap_common.c @@ -19,17 +19,23 @@ * contact@openairinterface.org */ -#include "types.h" +/*! \file ngap_common.c + * \brief ngap procedures for both gNB and AMF + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ -#ifndef FIELD_TYPE_H_ -#define FIELD_TYPE_H_ +#include -int field_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); +#include "ngap_common.h" +#include "NGAP_NGAP-PDU.h" -int field_type_file_print(types_t *type, int indent, FILE *file); -int field_type_hr_display(types_t *type, int indent); +int asn1_xer_print = 0; -#endif /* FIELD_TYPE_H_ */ + +void ngap_handle_criticality(NGAP_Criticality_t criticality) +{ +} diff --git a/openair3/NGAP/ngap_common.h b/openair3/NGAP/ngap_common.h new file mode 100644 index 0000000000..283dd2bffa --- /dev/null +++ b/openair3/NGAP/ngap_common.h @@ -0,0 +1,166 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_common.h + * \brief ngap procedures for both gNB and AMF + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ + +/** @defgroup _ngap_impl_ NGAP Layer Reference Implementation + * @ingroup _ref_implementation_ + * @{ + */ + + +#if HAVE_CONFIG_H_ +# include "config.h" +#endif + +#ifndef NGAP_COMMON_H_ +#define NGAP_COMMON_H_ + + +#include "common/utils/LOG/log.h" +/* replace ASN_DEBUG defined in asn_internal.h by oai tracing system + Would be cleaner to modify asn_internal.h but it seems to come + from non oai source, with BSD license, so prefer to do that here.. +*/ +#ifdef ASN_DEBUG +# undef ASN_DEBUG +#endif +#define ASN_DEBUG( x... ) LOG_I(ASN, x) + +#include "NGAP_ProtocolIE-Field.h" +#include "NGAP_NGAP-PDU.h" +#include "NGAP_InitiatingMessage.h" +#include "NGAP_SuccessfulOutcome.h" +#include "NGAP_UnsuccessfulOutcome.h" +#include "NGAP_ProtocolIE-Field.h" +#include "NGAP_ProtocolIE-FieldPair.h" +#include "NGAP_ProtocolIE-ContainerPair.h" +#include "NGAP_ProtocolExtensionField.h" +#include "NGAP_ProtocolExtensionContainer.h" +#include "NGAP_asn_constant.h" +#include "NGAP_SupportedTAItem.h" +#include "NGAP_ServedGUAMIItem.h" +#include "NGAP_BroadcastPLMNItem.h" +#include "NGAP_SliceSupportItem.h" +#include "NGAP_PLMNSupportItem.h" +#include "NGAP_PDUSessionResourceSetupResponseTransfer.h" +#include "NGAP_PDUSessionResourceSetupUnsuccessfulTransfer.h" +#include "NGAP_PDUSessionResourceSetupItemCxtRes.h" +#include "NGAP_PDUSessionResourceFailedToSetupItemCxtRes.h" +#include "NGAP_PDUSessionResourceSetupItemSUReq.h" +#include "NGAP_PDUSessionResourceSetupItemSURes.h" +#include "NGAP_PDUSessionResourceFailedToSetupItemSURes.h" +#include "NGAP_AssociatedQosFlowItem.h" +#include "NGAP_PDUSessionResourceSetupRequestTransfer.h" +#include "NGAP_PDUSessionResourceSetupItemCxtReq.h" +#include "NGAP_QosFlowSetupRequestItem.h" +#include "NGAP_AllowedNSSAI-Item.h" +#include "NGAP_PDUSessionResourceModifyItemModRes.h" +#include "NGAP_PDUSessionResourceFailedToModifyItemModRes.h" +#include "NGAP_PDUSessionResourceModifyUnsuccessfulTransfer.h" +#include "NGAP_PDUSessionResourceReleasedItemRelRes.h" +#include "NGAP_PDUSessionResourceToReleaseItemRelCmd.h" +#include "NGAP_PDUSessionResourceModifyItemModReq.h" +#include "NGAP_PDUSessionResourceModifyRequestTransfer.h" +#include "NGAP_QosFlowAddOrModifyRequestItem.h" +#include "NGAP_TAIListForPagingItem.h" +#include "NGAP_GNB-ID.h" +#include "NGAP_GlobalGNB-ID.h" +#include "NGAP_GTPTunnel.h" +#include "NGAP_UE-NGAP-ID-pair.h" +#include "NGAP_UserLocationInformationNR.h" + +/* Checking version of ASN1C compiler */ +#if (ASN1C_ENVIRONMENT_VERSION < ASN1C_MINIMUM_VERSION) +# error "You are compiling ngap with the wrong version of ASN1C" +#endif + +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (!FALSE) +#endif + +#define NGAP_UE_ID_FMT "0x%06"PRIX32 + +extern int asn_debug; +extern int asn1_xer_print; + +#if defined(ENB_MODE) +# include "common/utils/LOG/log.h" +# include "ngap_gNB_default_values.h" +# define NGAP_ERROR(x, args...) LOG_E(NGAP, x, ##args) +# define NGAP_WARN(x, args...) LOG_W(NGAP, x, ##args) +# define NGAP_TRAF(x, args...) LOG_I(NGAP, x, ##args) +# define NGAP_INFO(x, args...) LOG_I(NGAP, x, ##args) +# define NGAP_DEBUG(x, args...) LOG_I(NGAP, x, ##args) +#else +# include "amf_default_values.h" +# define NGAP_ERROR(x, args...) do { fprintf(stdout, "[NGAP][E]"x, ##args); } while(0) +# define NGAP_WARN(x, args...) do { fprintf(stdout, "[NGAP][W]"x, ##args); } while(0) +# define NGAP_TRAF(x, args...) do { fprintf(stdout, "[NGAP][T]"x, ##args); } while(0) +# define NGAP_INFO(x, args...) do { fprintf(stdout, "[NGAP][I]"x, ##args); } while(0) +# define NGAP_DEBUG(x, args...) do { fprintf(stdout, "[NGAP][D]"x, ##args); } while(0) +#endif + + +#define NGAP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ + do {\ + IE_TYPE **ptr; \ + ie = NULL; \ + for (ptr = container->protocolIEs.list.array; \ + ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \ + ptr++) { \ + if((*ptr)->id == IE_ID) { \ + ie = *ptr; \ + break; \ + } \ + } \ + if (ie == NULL ) { \ + if (mandatory) {\ + NGAP_ERROR("NGAP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL (searching for ie: %ld)\n",__FILE__,__LINE__, IE_ID);\ + abort();\ + }\ + else NGAP_INFO("NGAP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL (searching for ie: %ld)\n",__FILE__,__LINE__, IE_ID);\ + } \ + } while(0) +/** \brief Function callback prototype. + **/ +typedef int (*ngap_message_decoded_callback)( + uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu +); + +/** \brief Handle criticality + \param criticality Criticality of the IE + @returns void + **/ +void ngap_handle_criticality(NGAP_Criticality_t criticality); + +#endif /* NGAP_COMMON_H_ */ diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c new file mode 100644 index 0000000000..a5dfc88b35 --- /dev/null +++ b/openair3/NGAP/ngap_gNB.c @@ -0,0 +1,540 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB.c + * \brief NGAP gNB task + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \version 1.0 + * @ingroup _ngap + */ + + +#include +#include +#include +#include +#include + +#include "tree.h" +#include "queue.h" + +#include "intertask_interface.h" + +#include "ngap_gNB_default_values.h" + +#include "ngap_common.h" + +#include "ngap_gNB_defs.h" +#include "ngap_gNB.h" +#include "ngap_gNB_encoder.h" +#include "ngap_gNB_handlers.h" +#include "ngap_gNB_nnsf.h" + +#include "ngap_gNB_nas_procedures.h" +#include "ngap_gNB_management_procedures.h" +#include "ngap_gNB_context_management_procedures.h" + +#include "ngap_gNB_itti_messaging.h" + +#include "ngap_gNB_ue_context.h" // test, to be removed +#include "msc.h" + +#include "assertions.h" +#include "conversions.h" +#if defined(TEST_S1C_AMF) + #include "oaisim_amf_test_s1c.h" +#endif + +ngap_gNB_config_t ngap_config; + +static int ngap_gNB_generate_ng_setup_request( + ngap_gNB_instance_t *instance_p, ngap_gNB_amf_data_t *ngap_amf_data_p); + +void ngap_gNB_handle_register_gNB(instance_t instance, ngap_register_gnb_req_t *ngap_register_gNB); + +void ngap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); + +uint32_t ngap_generate_gNB_id(void) { + char *out; + char hostname[50]; + int ret; + uint32_t gNB_id; + /* Retrieve the host name */ + ret = gethostname(hostname, sizeof(hostname)); + DevAssert(ret == 0); + out = crypt(hostname, "eurecom"); + DevAssert(out != NULL); + gNB_id = ((out[0] << 24) | (out[1] << 16) | (out[2] << 8) | out[3]); + return gNB_id; +} + +static void ngap_gNB_register_amf(ngap_gNB_instance_t *instance_p, + net_ip_address_t *amf_ip_address, + net_ip_address_t *local_ip_addr, + uint16_t in_streams, + uint16_t out_streams, + uint8_t broadcast_plmn_num, + uint8_t broadcast_plmn_index[PLMN_LIST_MAX_SIZE]) { + MessageDef *message_p = NULL; + sctp_new_association_req_t *sctp_new_association_req_p = NULL; + ngap_gNB_amf_data_t *ngap_amf_data_p = NULL; + + DevAssert(instance_p != NULL); + DevAssert(amf_ip_address != NULL); + message_p = itti_alloc_new_message(TASK_NGAP, 0, SCTP_NEW_ASSOCIATION_REQ); + sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; + sctp_new_association_req_p->port = NGAP_PORT_NUMBER; + sctp_new_association_req_p->ppid = NGAP_SCTP_PPID; + sctp_new_association_req_p->in_streams = in_streams; + sctp_new_association_req_p->out_streams = out_streams; + memcpy(&sctp_new_association_req_p->remote_address, + amf_ip_address, + sizeof(*amf_ip_address)); + memcpy(&sctp_new_association_req_p->local_address, + local_ip_addr, + sizeof(*local_ip_addr)); + NGAP_INFO("[gNB %ld] check the amf registration state\n",instance_p->instance); + + /* Create new AMF descriptor */ + ngap_amf_data_p = calloc(1, sizeof(*ngap_amf_data_p)); + DevAssert(ngap_amf_data_p != NULL); + ngap_amf_data_p->cnx_id = ngap_gNB_fetch_add_global_cnx_id(); + sctp_new_association_req_p->ulp_cnx_id = ngap_amf_data_p->cnx_id; + ngap_amf_data_p->assoc_id = -1; + ngap_amf_data_p->broadcast_plmn_num = broadcast_plmn_num; + memcpy(&ngap_amf_data_p->amf_s1_ip, + amf_ip_address, + sizeof(*amf_ip_address)); + for (int i = 0; i < broadcast_plmn_num; ++i) + ngap_amf_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; + + ngap_amf_data_p->ngap_gNB_instance = instance_p; + STAILQ_INIT(&ngap_amf_data_p->served_guami); + /* Insert the new descriptor in list of known AMF + * but not yet associated. + */ + RB_INSERT(ngap_amf_map, &instance_p->ngap_amf_head, ngap_amf_data_p); + ngap_amf_data_p->state = NGAP_GNB_STATE_DISCONNECTED; + instance_p->ngap_amf_nb ++; + instance_p->ngap_amf_pending_nb ++; + + itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); +} + +void ngap_gNB_handle_register_gNB(instance_t instance, ngap_register_gnb_req_t *ngap_register_gNB) { + ngap_gNB_instance_t *new_instance; + uint8_t index; + DevAssert(ngap_register_gNB != NULL); + /* Look if the provided instance already exists */ + new_instance = ngap_gNB_get_instance(instance); + + if (new_instance != NULL) { + /* Checks if it is a retry on the same gNB */ + DevCheck(new_instance->gNB_id == ngap_register_gNB->gNB_id, new_instance->gNB_id, ngap_register_gNB->gNB_id, 0); + DevCheck(new_instance->cell_type == ngap_register_gNB->cell_type, new_instance->cell_type, ngap_register_gNB->cell_type, 0); + DevCheck(new_instance->num_plmn == ngap_register_gNB->num_plmn, new_instance->num_plmn, ngap_register_gNB->num_plmn, 0); + DevCheck(new_instance->tac == ngap_register_gNB->tac, new_instance->tac, ngap_register_gNB->tac, 0); + + for (int i = 0; i < new_instance->num_plmn; i++) { + DevCheck(new_instance->mcc[i] == ngap_register_gNB->mcc[i], new_instance->mcc[i], ngap_register_gNB->mcc[i], 0); + DevCheck(new_instance->mnc[i] == ngap_register_gNB->mnc[i], new_instance->mnc[i], ngap_register_gNB->mnc[i], 0); + DevCheck(new_instance->mnc_digit_length[i] == ngap_register_gNB->mnc_digit_length[i], new_instance->mnc_digit_length[i], ngap_register_gNB->mnc_digit_length[i], 0); + } + + DevCheck(new_instance->default_drx == ngap_register_gNB->default_drx, new_instance->default_drx, ngap_register_gNB->default_drx, 0); + } else { + new_instance = calloc(1, sizeof(ngap_gNB_instance_t)); + DevAssert(new_instance != NULL); + RB_INIT(&new_instance->ngap_ue_head); + RB_INIT(&new_instance->ngap_amf_head); + /* Copy usefull parameters */ + new_instance->instance = instance; + new_instance->gNB_name = ngap_register_gNB->gNB_name; + new_instance->gNB_id = ngap_register_gNB->gNB_id; + new_instance->cell_type = ngap_register_gNB->cell_type; + new_instance->tac = ngap_register_gNB->tac; + + memcpy(&new_instance->gNB_ng_ip, + &ngap_register_gNB->gnb_ip_address, + sizeof(ngap_register_gNB->gnb_ip_address)); + + for (int i = 0; i < ngap_register_gNB->num_plmn; i++) { + new_instance->mcc[i] = ngap_register_gNB->mcc[i]; + new_instance->mnc[i] = ngap_register_gNB->mnc[i]; + new_instance->mnc_digit_length[i] = ngap_register_gNB->mnc_digit_length[i]; + + new_instance->num_nssai[i] = ngap_register_gNB->num_nssai[i]; + } + + new_instance->num_plmn = ngap_register_gNB->num_plmn; + new_instance->default_drx = ngap_register_gNB->default_drx; + + memcpy(new_instance->s_nssai, ngap_register_gNB->s_nssai, sizeof(ngap_register_gNB->s_nssai)); + + /* Add the new instance to the list of gNB (meaningfull in virtual mode) */ + ngap_gNB_insert_new_instance(new_instance); + NGAP_INFO("Registered new gNB[%ld] and %s gNB id %u\n", + instance, + ngap_register_gNB->cell_type == CELL_MACRO_GNB ? "macro" : "home", + ngap_register_gNB->gNB_id); + } + + DevCheck(ngap_register_gNB->nb_amf <= NGAP_MAX_NB_AMF_IP_ADDRESS, + NGAP_MAX_NB_AMF_IP_ADDRESS, ngap_register_gNB->nb_amf, 0); + + /* Trying to connect to provided list of AMF ip address */ + for (index = 0; index < ngap_register_gNB->nb_amf; index++) { + net_ip_address_t *amf_ip = &ngap_register_gNB->amf_ip_address[index]; + struct ngap_gNB_amf_data_s *amf = NULL; + RB_FOREACH(amf, ngap_amf_map, &new_instance->ngap_amf_head) { + /* Compare whether IPv4 and IPv6 information is already present, in which + * wase we do not register again */ + if (amf->amf_s1_ip.ipv4 == amf_ip->ipv4 && (!amf_ip->ipv4 + || strncmp(amf->amf_s1_ip.ipv4_address, amf_ip->ipv4_address, 16) == 0) + && amf->amf_s1_ip.ipv6 == amf_ip->ipv6 && (!amf_ip->ipv6 + || strncmp(amf->amf_s1_ip.ipv6_address, amf_ip->ipv6_address, 46) == 0)) + break; + } + if (amf) + continue; + ngap_gNB_register_amf(new_instance, + amf_ip, + &ngap_register_gNB->gnb_ip_address, + ngap_register_gNB->sctp_in_streams, + ngap_register_gNB->sctp_out_streams, + ngap_register_gNB->broadcast_plmn_num[index], + ngap_register_gNB->broadcast_plmn_index[index]); + } +} + +void ngap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { + ngap_gNB_instance_t *instance_p; + ngap_gNB_amf_data_t *ngap_amf_data_p; + DevAssert(sctp_new_association_resp != NULL); + instance_p = ngap_gNB_get_instance(instance); + DevAssert(instance_p != NULL); + ngap_amf_data_p = ngap_gNB_get_AMF(instance_p, -1, + sctp_new_association_resp->ulp_cnx_id); + DevAssert(ngap_amf_data_p != NULL); + + if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { + NGAP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", + sctp_new_association_resp->sctp_state, + instance, + sctp_new_association_resp->ulp_cnx_id); + ngap_handle_ng_setup_message(ngap_amf_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); + return; + } + + /* Update parameters */ + ngap_amf_data_p->assoc_id = sctp_new_association_resp->assoc_id; + ngap_amf_data_p->in_streams = sctp_new_association_resp->in_streams; + ngap_amf_data_p->out_streams = sctp_new_association_resp->out_streams; + /* Prepare new NG Setup Request */ + ngap_gNB_generate_ng_setup_request(instance_p, ngap_amf_data_p); +} + +static +void ngap_gNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { + int result; + DevAssert(sctp_data_ind != NULL); +#if defined(TEST_S1C_AMF) + amf_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream, + sctp_data_ind->buffer, sctp_data_ind->buffer_length); +#else + ngap_gNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, + sctp_data_ind->buffer, sctp_data_ind->buffer_length); +#endif + result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); +} + +void ngap_gNB_init(void) { + NGAP_DEBUG("Starting NGAP layer\n"); + ngap_gNB_prepare_internal_data(); + itti_mark_task_ready(TASK_NGAP); + MSC_START_USE(); +} + +void *ngap_gNB_process_itti_msg(void *notUsed) { + MessageDef *received_msg = NULL; + int result; + itti_receive_msg(TASK_NGAP, &received_msg); + + switch (ITTI_MSG_ID(received_msg)) { + case TERMINATE_MESSAGE: + NGAP_WARN(" *** Exiting NGAP thread\n"); + itti_exit_task(); + break; + + case NGAP_REGISTER_GNB_REQ: { + /* Register a new gNB. + * in Virtual mode gNBs will be distinguished using the mod_id/ + * Each gNB has to send an NGAP_REGISTER_GNB message with its + * own parameters. + */ + ngap_gNB_handle_register_gNB(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_REGISTER_GNB_REQ(received_msg)); + } + break; + + case SCTP_NEW_ASSOCIATION_RESP: { + ngap_gNB_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &received_msg->ittiMsg.sctp_new_association_resp); + } + break; + + case SCTP_DATA_IND: { + ngap_gNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind); + } + break; + + case NGAP_NAS_FIRST_REQ: { + ngap_gNB_handle_nas_first_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_NAS_FIRST_REQ(received_msg)); + } + break; + + case NGAP_UPLINK_NAS: { + ngap_gNB_nas_uplink(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_UPLINK_NAS(received_msg)); + } + break; + + case NGAP_UE_CAPABILITIES_IND: { + ngap_gNB_ue_capabilities(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_UE_CAPABILITIES_IND(received_msg)); + } + break; + + case NGAP_INITIAL_CONTEXT_SETUP_RESP: { + ngap_gNB_initial_ctxt_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_INITIAL_CONTEXT_SETUP_RESP(received_msg)); + } + break; + + case NGAP_PDUSESSION_SETUP_RESP: { + ngap_gNB_pdusession_setup_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_PDUSESSION_SETUP_RESP(received_msg)); + } + break; + + case NGAP_PDUSESSION_MODIFY_RESP: { + ngap_gNB_pdusession_modify_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_PDUSESSION_MODIFY_RESP(received_msg)); + } + break; + + case NGAP_NAS_NON_DELIVERY_IND: { + ngap_gNB_nas_non_delivery_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_NAS_NON_DELIVERY_IND(received_msg)); + } + break; + + case NGAP_PATH_SWITCH_REQ: { + ngap_gNB_path_switch_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_PATH_SWITCH_REQ(received_msg)); + } + break; + + case NGAP_PDUSESSION_MODIFICATION_IND: { + ngap_gNB_generate_PDUSESSION_Modification_Indication(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_PDUSESSION_MODIFICATION_IND(received_msg)); + } + break; + + case NGAP_UE_CONTEXT_RELEASE_COMPLETE: { + ngap_ue_context_release_complete(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_UE_CONTEXT_RELEASE_COMPLETE(received_msg)); + } + break; + + case NGAP_UE_CONTEXT_RELEASE_REQ: { + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; // test + struct ngap_gNB_ue_context_s *ue_context_p = NULL; // test + ngap_ue_context_release_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_UE_CONTEXT_RELEASE_REQ(received_msg)); + ngap_gNB_instance_p = ngap_gNB_get_instance(ITTI_MSG_DESTINATION_INSTANCE(received_msg)); // test + DevAssert(ngap_gNB_instance_p != NULL); // test + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, + NGAP_UE_CONTEXT_RELEASE_REQ(received_msg).gNB_ue_ngap_id)) == NULL) { // test + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_ERROR("Failed to find ue context associated with gNB ue ngap id: %u\n", + NGAP_UE_CONTEXT_RELEASE_REQ(received_msg).gNB_ue_ngap_id); // test + } // test + } + break; + + case NGAP_PDUSESSION_RELEASE_RESPONSE: { + ngap_gNB_pdusession_release_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &NGAP_PDUSESSION_RELEASE_RESPONSE(received_msg)); + } + break; + + default: + NGAP_ERROR("Received unhandled message: %d:%s\n", + ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); + break; + } + + result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + received_msg = NULL; + return NULL; +} + + +void *ngap_gNB_task(void *arg) { + ngap_gNB_init(); + + while (1) { + (void) ngap_gNB_process_itti_msg(NULL); + } + + return NULL; +} + +//----------------------------------------------------------------------------- +/* +* gNB generate a NG setup request towards AMF +*/ +static int ngap_gNB_generate_ng_setup_request( + ngap_gNB_instance_t *instance_p, + ngap_gNB_amf_data_t *ngap_amf_data_p) +//----------------------------------------------------------------------------- +{ + NGAP_NGAP_PDU_t pdu; + NGAP_NGSetupRequest_t *out = NULL; + NGAP_NGSetupRequestIEs_t *ie = NULL; + NGAP_SupportedTAItem_t *ta = NULL; + NGAP_BroadcastPLMNItem_t *plmn = NULL; + NGAP_SliceSupportItem_t *ssi = NULL; + uint8_t *buffer = NULL; + uint32_t len = 0; + int ret = 0; + DevAssert(instance_p != NULL); + DevAssert(ngap_amf_data_p != NULL); + ngap_amf_data_p->state = NGAP_GNB_STATE_WAITING; + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = CALLOC(1, sizeof(struct NGAP_InitiatingMessage)); + pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_NGSetup; + pdu.choice.initiatingMessage->criticality = NGAP_Criticality_reject; + pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_NGSetupRequest; + out = &pdu.choice.initiatingMessage->value.choice.NGSetupRequest; + /* mandatory */ + ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_GlobalRANNodeID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_NGSetupRequestIEs__value_PR_GlobalRANNodeID; + ie->value.choice.GlobalRANNodeID.present = NGAP_GlobalRANNodeID_PR_globalGNB_ID; + ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID = CALLOC(1, sizeof(struct NGAP_GlobalGNB_ID)); + MCC_MNC_TO_PLMNID(instance_p->mcc[ngap_amf_data_p->broadcast_plmn_index[0]], + instance_p->mnc[ngap_amf_data_p->broadcast_plmn_index[0]], + instance_p->mnc_digit_length[ngap_amf_data_p->broadcast_plmn_index[0]], + &(ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->pLMNIdentity)); + ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.present = NGAP_GNB_ID_PR_gNB_ID; + MACRO_GNB_ID_TO_BIT_STRING(instance_p->gNB_id, + &ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID); + NGAP_INFO("%u -> %02x%02x%02x%02x\n", instance_p->gNB_id, + ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[0], + ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[1], + ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[2], + ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[3]); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (instance_p->gNB_name) { + ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RANNodeName; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_NGSetupRequestIEs__value_PR_RANNodeName; + OCTET_STRING_fromBuf(&ie->value.choice.RANNodeName, instance_p->gNB_name, + strlen(instance_p->gNB_name)); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* mandatory */ + ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_SupportedTAList; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_NGSetupRequestIEs__value_PR_SupportedTAList; + { + ta = (NGAP_SupportedTAItem_t *)calloc(1, sizeof(NGAP_SupportedTAItem_t)); + INT24_TO_OCTET_STRING(instance_p->tac, &ta->tAC); + { + for (int i = 0; i < ngap_amf_data_p->broadcast_plmn_num; ++i) { + plmn = (NGAP_BroadcastPLMNItem_t *)calloc(1, sizeof(NGAP_BroadcastPLMNItem_t)); + MCC_MNC_TO_TBCD(instance_p->mcc[ngap_amf_data_p->broadcast_plmn_index[i]], + instance_p->mnc[ngap_amf_data_p->broadcast_plmn_index[i]], + instance_p->mnc_digit_length[ngap_amf_data_p->broadcast_plmn_index[i]], + &plmn->pLMNIdentity); + + for(int si = 0; si < instance_p->num_nssai[i]; si++) { + ssi = (NGAP_SliceSupportItem_t *)calloc(1, sizeof(NGAP_SliceSupportItem_t)); + INT8_TO_OCTET_STRING(instance_p->s_nssai[i][si].sST, &ssi->s_NSSAI.sST); + + if(instance_p->s_nssai[i]->sD_flag) { + ssi->s_NSSAI.sD = calloc(1, sizeof(NGAP_SD_t)); + ssi->s_NSSAI.sD->buf = calloc(3, sizeof(uint8_t)); + ssi->s_NSSAI.sD->size = 3; + ssi->s_NSSAI.sD->buf[0] = instance_p->s_nssai[i][si].sD[0]; + ssi->s_NSSAI.sD->buf[1] = instance_p->s_nssai[i][si].sD[1]; + ssi->s_NSSAI.sD->buf[2] = instance_p->s_nssai[i][si].sD[2]; + } + + + ASN_SEQUENCE_ADD(&plmn->tAISliceSupportList.list, ssi); + } + + ASN_SEQUENCE_ADD(&ta->broadcastPLMNList.list, plmn); + } + } + ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAList.list, ta); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_DefaultPagingDRX; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_NGSetupRequestIEs__value_PR_PagingDRX; + ie->value.choice.PagingDRX = instance_p->default_drx; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) { + NGAP_ERROR("Failed to encode NG setup request\n"); + return -1; + } + + /* Non UE-Associated signalling -> stream = 0 */ + ngap_gNB_itti_send_sctp_data_req(instance_p->instance, ngap_amf_data_p->assoc_id, buffer, len, 0); + return ret; +} + + + + diff --git a/openair3/NGAP/ngap_gNB.h b/openair3/NGAP/ngap_gNB.h new file mode 100644 index 0000000000..e6a24acdb4 --- /dev/null +++ b/openair3/NGAP/ngap_gNB.h @@ -0,0 +1,64 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB.h + * \brief NGAP gNB task + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \version 1.0 + * @ingroup _ngap + */ + +#include +#include + +/** @defgroup _ngap_impl_ NGAP Layer Reference Implementation for gNB + * @ingroup _ref_implementation_ + * @{ + */ + +#ifndef NGAP_GNB_H_ +#define NGAP_GNB_H_ + +typedef struct ngap_gNB_config_s { + // MME related params + unsigned char amf_enabled; ///< AMF enabled ? + unsigned char ngap_enabled; ///< NGAP enabled ? +} ngap_gNB_config_t; + +extern ngap_gNB_config_t ngap_config; + +#define AMF_MODE_ENABLED ngap_config.amf_enabled +#define NGAP_CONF_MODE ngap_config.ngap_enabled + + +void *ngap_gNB_process_itti_msg(void*); +void ngap_gNB_init(void); +void *ngap_gNB_task(void *arg); + +uint32_t ngap_generate_gNB_id(void); + +#endif /* NGAP_GNB_H_ */ + +/** + * @} + */ diff --git a/openair3/NGAP/ngap_gNB_context_management_procedures.c b/openair3/NGAP/ngap_gNB_context_management_procedures.c new file mode 100644 index 0000000000..73e4498f19 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_context_management_procedures.c @@ -0,0 +1,287 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_context_management_procedures.c + * \brief NGAP context management procedures + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \version 1.0 + * @ingroup _ngap + */ + + +#include +#include +#include + +#include "assertions.h" +#include "conversions.h" + +#include "intertask_interface.h" + +#include "ngap_common.h" +#include "ngap_gNB_defs.h" + +#include "ngap_gNB_itti_messaging.h" + +#include "ngap_gNB_encoder.h" +#include "ngap_gNB_nnsf.h" +#include "ngap_gNB_ue_context.h" +#include "ngap_gNB_nas_procedures.h" +#include "ngap_gNB_management_procedures.h" +#include "ngap_gNB_context_management_procedures.h" +#include "NGAP_PDUSessionResourceItemCxtRelReq.h" +#include "msc.h" + + +int ngap_ue_context_release_complete(instance_t instance, + ngap_ue_release_complete_t *ue_release_complete_p) +{ + + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu; + NGAP_UEContextReleaseComplete_t *out; + NGAP_UEContextReleaseComplete_IEs_t *ie; + uint8_t *buffer; + uint32_t length; + + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + + DevAssert(ue_release_complete_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + /*RB_FOREACH(ue_context_p, ngap_ue_map, &ngap_gNB_instance_p->ngap_ue_head) { + NGAP_WARN("in ngap_ue_map: UE context gNB_ue_ngap_id %u amf_ue_ngap_id %u state %u\n", + ue_context_p->gNB_ue_ngap_id, ue_context_p->amf_ue_ngap_id, + ue_context_p->ue_state); + }*/ + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, + ue_release_complete_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: %u\n", + ue_release_complete_p->gNB_ue_ngap_id); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = CALLOC(1, sizeof(struct NGAP_SuccessfulOutcome)); + pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_UEContextRelease; + pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject; + pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_UEContextReleaseComplete; + out = &pdu.choice.successfulOutcome->value.choice.UEContextReleaseComplete; + + /* mandatory */ + ie = (NGAP_UEContextReleaseComplete_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseComplete_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_UEContextReleaseComplete_IEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (NGAP_UEContextReleaseComplete_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseComplete_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_UEContextReleaseComplete_IEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = ue_release_complete_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + /* Encode procedure has failed... */ + NGAP_ERROR("Failed to encode UE context release complete\n"); + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + buffer, + length, + MSC_AS_TIME_FMT" UEContextRelease successfulOutcome gNB_ue_ngap_id %u amf_ue_ngap_id %lu", + 0,0, //MSC_AS_TIME_ARGS(ctxt_pP), + ue_release_complete_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + + //LG ngap_gNB_itti_send_sctp_close_association(ngap_gNB_instance_p->instance, + // ue_context_p->amf_ref->assoc_id); + // release UE context + struct ngap_gNB_ue_context_s *ue_context2_p = NULL; + + if ((ue_context2_p = RB_REMOVE(ngap_ue_map, &ngap_gNB_instance_p->ngap_ue_head, ue_context_p)) + != NULL) { + NGAP_WARN("Removed UE context gNB_ue_ngap_id %u\n", + ue_context2_p->gNB_ue_ngap_id); + ngap_gNB_free_ue_context(ue_context2_p); + } else { + NGAP_WARN("Removing UE context gNB_ue_ngap_id %u: did not find context\n", + ue_context_p->gNB_ue_ngap_id); + } + /*RB_FOREACH(ue_context_p, ngap_ue_map, &ngap_gNB_instance_p->ngap_ue_head) { + NGAP_WARN("in ngap_ue_map: UE context gNB_ue_ngap_id %u amf_ue_ngap_id %u state %u\n", + ue_context_p->gNB_ue_ngap_id, ue_context_p->amf_ue_ngap_id, + ue_context_p->ue_state); + }*/ + + return 0; +} + + +int ngap_ue_context_release_req(instance_t instance, + ngap_ue_release_req_t *ue_release_req_p) +{ + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu; + NGAP_UEContextReleaseRequest_t *out; + NGAP_UEContextReleaseRequest_IEs_t *ie; + uint8_t *buffer = NULL; + uint32_t length; + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + + DevAssert(ue_release_req_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, + ue_release_req_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: %u\n", + ue_release_req_p->gNB_ue_ngap_id); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = CALLOC(1, sizeof(struct NGAP_InitiatingMessage)); + pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_UEContextReleaseRequest; + pdu.choice.initiatingMessage->criticality = NGAP_Criticality_ignore; + pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_UEContextReleaseRequest; + out = &pdu.choice.initiatingMessage->value.choice.UEContextReleaseRequest; + + /* mandatory */ + ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UEContextReleaseRequest_IEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UEContextReleaseRequest_IEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = ue_release_req_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (ue_release_req_p->nb_of_pdusessions > 0) { + ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceListCxtRelReq; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UEContextReleaseRequest_IEs__value_PR_PDUSessionResourceListCxtRelReq; + for (int i = 0; i < ue_release_req_p->nb_of_pdusessions; i++) { + NGAP_PDUSessionResourceItemCxtRelReq_t *item; + item = (NGAP_PDUSessionResourceItemCxtRelReq_t *)calloc(1,sizeof(NGAP_PDUSessionResourceItemCxtRelReq_t)); + item->pDUSessionID = ue_release_req_p->pdusessions[i].pdusession_id; + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceListCxtRelReq.list, item); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* mandatory */ + ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_Cause; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_UEContextReleaseRequest_IEs__value_PR_Cause; + + switch (ue_release_req_p->cause) { + case NGAP_Cause_PR_radioNetwork: + ie->value.choice.Cause.present = NGAP_Cause_PR_radioNetwork; + ie->value.choice.Cause.choice.radioNetwork = ue_release_req_p->cause_value; + break; + + case NGAP_Cause_PR_transport: + ie->value.choice.Cause.present = NGAP_Cause_PR_transport; + ie->value.choice.Cause.choice.transport = ue_release_req_p->cause_value; + break; + + case NGAP_Cause_PR_nas: + ie->value.choice.Cause.present = NGAP_Cause_PR_nas; + ie->value.choice.Cause.choice.nas = ue_release_req_p->cause_value; + break; + + case NGAP_Cause_PR_protocol: + ie->value.choice.Cause.present = NGAP_Cause_PR_protocol; + ie->value.choice.Cause.choice.protocol = ue_release_req_p->cause_value; + break; + + case NGAP_Cause_PR_misc: + ie->value.choice.Cause.present = NGAP_Cause_PR_misc; + ie->value.choice.Cause.choice.misc = ue_release_req_p->cause_value; + break; + + case NGAP_Cause_PR_NOTHING: + default: + ie->value.choice.Cause.present = NGAP_Cause_PR_NOTHING; + break; + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + /* Encode procedure has failed... */ + NGAP_ERROR("Failed to encode UE context release complete\n"); + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + buffer, + length, + MSC_AS_TIME_FMT" UEContextReleaseRequest initiatingMessage gNB_ue_ngap_id %u amf_ue_ngap_id %lu", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + ue_release_req_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + + return 0; +} + diff --git a/openair3/NGAP/ngap_gNB_context_management_procedures.h b/openair3/NGAP/ngap_gNB_context_management_procedures.h new file mode 100644 index 0000000000..5eca34e56d --- /dev/null +++ b/openair3/NGAP/ngap_gNB_context_management_procedures.h @@ -0,0 +1,41 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_context_management_procedures.h + * \brief NGAP context management procedures + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \version 1.0 + * @ingroup _ngap + */ + +#ifndef NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_ +#define NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_ + + +int ngap_ue_context_release_complete(instance_t instance, + ngap_ue_release_complete_t *ue_release_complete_p); + +int ngap_ue_context_release_req(instance_t instance, + ngap_ue_release_req_t *ue_release_req_p); + +#endif /* NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_decoder.c b/openair3/NGAP/ngap_gNB_decoder.c new file mode 100644 index 0000000000..b551471a84 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_decoder.c @@ -0,0 +1,188 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_decoder.c + * \brief ngap pdu decode procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ + + +#include + +#include "assertions.h" + +#include "intertask_interface.h" + +#include "ngap_common.h" +#include "ngap_gNB_decoder.h" + +static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) { + asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + DevAssert(pdu != NULL); + + switch(pdu->choice.initiatingMessage->procedureCode) { + case NGAP_ProcedureCode_id_DownlinkNASTransport: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_InitialContextSetup: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_UEContextRelease: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_Paging: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + NGAP_INFO("Paging initiating message\n"); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_PDUSessionResourceSetup: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("PDUSESSIONSetup initiating message\n"); + break; + + case NGAP_ProcedureCode_id_PDUSessionResourceModify: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("PDUSESSIONModify initiating message\n"); + break; + + case NGAP_ProcedureCode_id_PDUSessionResourceRelease: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("TODO PDUSESSIONRelease initiating message\n"); + break; + + case NGAP_ProcedureCode_id_ErrorIndication: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("TODO ErrorIndication initiating message\n"); + break; + + default: + NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n", + (int)pdu->choice.initiatingMessage->procedureCode); + AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n", + (int)pdu->choice.initiatingMessage->procedureCode); + return -1; + } + + return 0; +} + +static int ngap_gNB_decode_successful_outcome(NGAP_NGAP_PDU_t *pdu) { + asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + DevAssert(pdu != NULL); + + switch(pdu->choice.successfulOutcome->procedureCode) { + case NGAP_ProcedureCode_id_NGSetup: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_PathSwitchRequest: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + + default: + NGAP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n", + (int)pdu->choice.successfulOutcome->procedureCode); + return -1; + } + + return 0; +} + +static int ngap_gNB_decode_unsuccessful_outcome(NGAP_NGAP_PDU_t *pdu) { + asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + DevAssert(pdu != NULL); + + switch(pdu->choice.unsuccessfulOutcome->procedureCode) { + case NGAP_ProcedureCode_id_NGSetup: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + case NGAP_ProcedureCode_id_PathSwitchRequest: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + default: + NGAP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n", + (int)pdu->choice.unsuccessfulOutcome->procedureCode); + return -1; + } + + return 0; +} + +int ngap_gNB_decode_pdu(NGAP_NGAP_PDU_t *pdu, const uint8_t *const buffer, + const uint32_t length) { + asn_dec_rval_t dec_ret; + DevAssert(pdu != NULL); + DevAssert(buffer != NULL); + dec_ret = aper_decode(NULL, + &asn_DEF_NGAP_NGAP_PDU, + (void **)&pdu, + buffer, + length, + 0, + 0); + + if (dec_ret.code != RC_OK) { + NGAP_ERROR("Failed to decode pdu\n"); + return -1; + } + + switch(pdu->present) { + case NGAP_NGAP_PDU_PR_initiatingMessage: + return ngap_gNB_decode_initiating_message(pdu); + + case NGAP_NGAP_PDU_PR_successfulOutcome: + return ngap_gNB_decode_successful_outcome(pdu); + + case NGAP_NGAP_PDU_PR_unsuccessfulOutcome: + return ngap_gNB_decode_unsuccessful_outcome(pdu); + + default: + NGAP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present); + break; + } + + return -1; +} diff --git a/common/utils/itti_analyzer/libparser/enum_value_type.h b/openair3/NGAP/ngap_gNB_decoder.h similarity index 65% rename from common/utils/itti_analyzer/libparser/enum_value_type.h rename to openair3/NGAP/ngap_gNB_decoder.h index 997e6cc3fe..9fc8d433c4 100644 --- a/common/utils/itti_analyzer/libparser/enum_value_type.h +++ b/openair3/NGAP/ngap_gNB_decoder.h @@ -18,20 +18,20 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ +/*! \file ngap_gNB_decoder.h + * \brief ngap pdu decode procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ -#include "types.h" +#include -#ifndef ENUM_VALUE_TYPE_H_ -#define ENUM_VALUE_TYPE_H_ +#ifndef NGAP_GNB_DECODER_H_ +#define NGAP_GNB_DECODER_H_ -extern uint32_t last_enum_value; +int ngap_gNB_decode_pdu(NGAP_NGAP_PDU_t *pdu, const uint8_t *const buffer, + const uint32_t length) __attribute__ ((warn_unused_result)); -int enum_value_dissect_from_buffer( - types_t *type, ui_set_signal_text_cb_t ui_set_signal_text_cb, gpointer user_data, - buffer_t *buffer, uint32_t offset, uint32_t parent_offset, int indent, gboolean new_line); - -int enum_value_file_print(types_t *type, int indent, FILE *file); - -int enum_value_type_hr_display(types_t *type, int indent); - -#endif /* ENUM_VALUE_TYPE_H_ */ +#endif /* NGAP_GNB_DECODER_H_ */ diff --git a/common/utils/itti_analyzer/common/logs.h b/openair3/NGAP/ngap_gNB_default_values.h similarity index 61% rename from common/utils/itti_analyzer/common/logs.h rename to openair3/NGAP/ngap_gNB_default_values.h index bd901cc394..afbe91ec7f 100644 --- a/common/utils/itti_analyzer/common/logs.h +++ b/openair3/NGAP/ngap_gNB_default_values.h @@ -18,39 +18,28 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ - -/* - * logs.h - * - * Created on: Nov 22, 2013 - * Author: Laurent Winckel +/*! \file ngap_gNB_default_values.h + * \brief ngap default values + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 */ -#ifndef LOGS_H_ -#define LOGS_H_ +#ifndef NGAP_GNB_DEFAULT_VALUES_H_ +#define NGAP_GNB_DEFAULT_VALUES_H_ -/* Added definition of the g_info log function to complete the set of log functions from "gmessages.h" */ +#define GNB_TAC (1) +#define GNB_MCC (208) +#define GNB_MNC (92) -#include +#define GNB_NAME "Eurecom GNB" +#define GNB_NAME_FORMAT (GNB_NAME" %u") -#ifdef G_HAVE_ISO_VARARGS +#define NGAP_PORT_NUMBER (38412) +#define NGAP_SCTP_PPID (60) -#define g_info(...) g_log (G_LOG_DOMAIN, \ - G_LOG_LEVEL_INFO, \ - __VA_ARGS__) +#define X2AP_PORT_NUMBER (36422) +#define X2AP_SCTP_PPID (27) -#else - -static void -g_info (const gchar *format, - ...) -{ - va_list args; - va_start (args, format); - g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format, args); - va_end (args); -} - -#endif - -#endif /* LOGS_H_ */ +#endif /* NGAP_GNB_DEFAULT_VALUES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_defs.h b/openair3/NGAP/ngap_gNB_defs.h new file mode 100644 index 0000000000..f2bdd646ae --- /dev/null +++ b/openair3/NGAP/ngap_gNB_defs.h @@ -0,0 +1,298 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_defs.h + * \brief ngap define procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ + +#include + +#include "queue.h" +#include "tree.h" + +#ifndef NGAP_GNB_DEFS_H_ +#define NGAP_GNB_DEFS_H_ + +#define NGAP_GNB_NAME_LENGTH_MAX (150) + +typedef enum { + /* Disconnected state: initial state for any association. */ + NGAP_GNB_STATE_DISCONNECTED = 0x0, + /* State waiting for S1 Setup response message if gNB is AMF accepted or + * S1 Setup failure if AMF rejects the gNB. + */ + NGAP_GNB_STATE_WAITING = 0x1, + /* The gNB is successfully connected to AMF, UE contexts can be created. */ + NGAP_GNB_STATE_CONNECTED = 0x2, + /* The AMF has sent an overload start message. Once the AMF disables the + * OVERLOAD marker, the state of the association will be + * NGAP_GNB_STATE_CONNECTED. + */ + NGAP_GNB_OVERLOAD = 0x3, + /* Max number of states available */ + NGAP_GNB_STATE_MAX, +} ngap_gNB_state_t; + +/* If the Overload Action IE in the OVERLOAD START message is set to + * - “reject all RRC connection establishments for non-emergency mobile + * originated data transfer �E(i.e. reject traffic corresponding to RRC cause + * “mo-data �E(TS 36.331 [16])), or + * - “reject all RRC connection establishments for signalling �E(i.e. reject + * traffic corresponding to RRC cause “modata�Eand “mo-signalling�E * (TS 38.331 [16])),or + * - “only permit RRC connection establishments for emergency sessions and + * mobile terminated services�E(i.e. only permit traffic corresponding to RRC + * cause “emergency�Eand “mt-Access�E(TS 36.331 [16])). + * + * NOTE: When the Overload Action IE is set to “only permit RRC connection + * establishments for emergency sessions and mobile terminated services�E + * emergency calls with RRC cause “highPriorityAcess�Efrom high priority users + * are rejected (TS 24.301 [24]). + */ +typedef enum { + NGAP_OVERLOAD_REJECT_MO_DATA = 0x0, + NGAP_OVERLOAD_REJECT_ALL_SIGNALLING = 0x1, + NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT = 0x2, + NGAP_NO_OVERLOAD = 0x3, + NGAP_OVERLOAD_MAX, +} ngap_overload_state_t; + +/* Served PLMN identity element */ +struct plmn_identity_s { + uint16_t mcc; + uint16_t mnc; + uint8_t mnc_digit_length; + STAILQ_ENTRY(plmn_identity_s) next; +}; + +/* Served amf region id for a particular AMF */ +struct served_region_id_s { + uint8_t amf_region_id; + STAILQ_ENTRY(served_region_id_s) next; +}; + +/* Served amf set id for a particular AMF */ +struct amf_set_id_s { + uint16_t amf_set_id; + STAILQ_ENTRY(amf_set_id_s) next; +}; + +/* Served amf pointer for a particular AMF */ +struct amf_pointer_s { + uint8_t amf_pointer; + STAILQ_ENTRY(amf_pointer_s) next; +}; + + +/* Served guami element */ +struct served_guami_s { + /* Number of AMF served PLMNs */ + uint8_t nb_served_plmns; + /* List of served PLMNs by AMF */ + STAILQ_HEAD(served_plmns_s, plmn_identity_s) served_plmns; + + /* Number of region id in list */ + uint8_t nb_region_id; + /* Served group id list */ + STAILQ_HEAD(served_region_ids_s, served_region_id_s) served_region_ids; + + /* Number of AMF set id */ + uint8_t nb_amf_set_id; + /* AMF Set id to uniquely identify an AMF within an AMF pool area */ + STAILQ_HEAD(amf_set_ids_s, amf_set_id_s) amf_set_ids; + + /* Number of AMF pointer */ + uint8_t nb_amf_pointer; + /* AMF pointer to uniquely identify an AMF within an AMF pool area */ + STAILQ_HEAD(amf_pointers_s, amf_pointer_s) amf_pointers; + + /* Next GUAMI element */ + STAILQ_ENTRY(served_guami_s) next; +}; + +/* NSSAI element */ +struct slice_support_s{ + uint8_t sST; + uint8_t sD_flag; + uint8_t sD[3]; + + /* Next slice element */ + STAILQ_ENTRY(slice_support_s) next; +}; + + +/* plmn support element */ +struct plmn_support_s { + struct plmn_identity_s plmn_identity; + + /* Number of slice support in list */ + uint8_t nb_slice_s; + /* Served group id list */ + STAILQ_HEAD(slice_supports_s, slice_support_s) slice_supports; + + /* Next plmn support element */ + STAILQ_ENTRY(plmn_support_s) next; +}; + + +struct ngap_gNB_instance_s; + +/* This structure describes association of a gNB to a AMF */ +typedef struct ngap_gNB_amf_data_s { + /* AMF descriptors tree, ordered by sctp assoc id */ + RB_ENTRY(ngap_gNB_amf_data_s) entry; + + /* This is the optional name provided by the AMF */ + char *amf_name; + + /* AMF NGAP IP address */ + net_ip_address_t amf_s1_ip; + + /* List of served GUAMI per AMF. There is one GUAMI per RAT with a max + * number of 8 RATs but in our case only one is used. The LTE related pool + * configuration is included on the first place in the list. + */ + STAILQ_HEAD(served_guamis_s, served_guami_s) served_guami; + + /* Relative processing capacity of an AMF with respect to the other AMFs + * in the pool in order to load-balance AMFs within a pool as defined + * in TS 23.401. + */ + uint8_t relative_amf_capacity; + + /* + * List of PLMN Support per AMF. + * + */ + STAILQ_HEAD(plmn_supports_s, plmn_support_s) plmn_supports; + + /* Current AMF overload information (if any). */ + ngap_overload_state_t overload_state; + /* Current gNB->AMF NGAP association state */ + ngap_gNB_state_t state; + + /* Next usable stream for UE signalling */ + int32_t nextstream; + + /* Number of input/ouput streams */ + uint16_t in_streams; + uint16_t out_streams; + + /* Connexion id used between SCTP/NGAP */ + uint16_t cnx_id; + + /* SCTP association id */ + int32_t assoc_id; + + /* This is served PLMN IDs communicated to the AMF via an index over the + * MCC/MNC array in ngap_gNB_instance */ + uint8_t broadcast_plmn_num; + uint8_t broadcast_plmn_index[PLMN_LIST_MAX_SIZE]; + + + /* Only meaningfull in virtual mode */ + struct ngap_gNB_instance_s *ngap_gNB_instance; +} ngap_gNB_amf_data_t; + +typedef struct ngap_gNB_NSSAI_s{ + uint8_t sST; + uint8_t sD_flag; + uint8_t sD[3]; +}ngap_gNB_NSSAI_t; + +typedef struct ngap_gNB_instance_s { + /* Next ngap gNB association. + * Only used for virtual mode. + */ + STAILQ_ENTRY(ngap_gNB_instance_s) ngap_gNB_entries; + + /* Number of AMF requested by gNB (tree size) */ + uint32_t ngap_amf_nb; + /* Number of AMF for which association is pending */ + uint32_t ngap_amf_pending_nb; + /* Number of AMF successfully associated to gNB */ + uint32_t ngap_amf_associated_nb; + /* Tree of NGAP AMF associations ordered by association ID */ + RB_HEAD(ngap_amf_map, ngap_gNB_amf_data_s) ngap_amf_head; + + /* TODO: add a map ordered by relative AMF capacity */ + + /* Tree of UE ordered by gNB_ue_ngap_id's */ + RB_HEAD(ngap_ue_map, ngap_gNB_ue_context_s) ngap_ue_head; + + /* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */ + instance_t instance; + + /* Displayable name of gNB */ + char *gNB_name; + + /* Unique gNB_id to identify the gNB within EPC. + * In our case the gNB is a macro gNB so the id will be 20 bits long. + * For Home gNB id, this field should be 36 bits long. + */ + uint32_t gNB_id; + /* The type of the cell */ + enum cell_type_e cell_type; + + /* Tracking area code */ + uint32_t tac; + + /* gNB NGAP IP address */ + net_ip_address_t gNB_ng_ip; + + /* Mobile Country Code + * Mobile Network Code + */ + uint16_t mcc[PLMN_LIST_MAX_SIZE]; + uint16_t mnc[PLMN_LIST_MAX_SIZE]; + uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; + uint8_t num_plmn; + + uint16_t num_nssai[PLMN_LIST_MAX_SIZE]; + ngap_gNB_NSSAI_t s_nssai[PLMN_LIST_MAX_SIZE][8]; + + /* Default Paging DRX of the gNB as defined in TS 38.304 */ + ngap_paging_drx_t default_drx; +} ngap_gNB_instance_t; + +typedef struct { + /* List of served gNBs + * Only used for virtual mode + */ + STAILQ_HEAD(ngap_gNB_instances_head_s, ngap_gNB_instance_s) ngap_gNB_instances_head; + /* Nb of registered gNBs */ + uint8_t nb_registered_gNBs; + + /* Generate a unique connexion id used between NGAP and SCTP */ + uint16_t global_cnx_id; +} ngap_gNB_internal_data_t; + +int ngap_gNB_compare_assoc_id( + struct ngap_gNB_amf_data_s *p1, struct ngap_gNB_amf_data_s *p2); + +/* Generate the tree management functions */ +RB_PROTOTYPE(ngap_amf_map, ngap_gNB_amf_data_s, entry, + ngap_gNB_compare_assoc_id); + +#endif /* NGAP_GNB_DEFS_H_ */ diff --git a/openair3/NGAP/ngap_gNB_encoder.c b/openair3/NGAP/ngap_gNB_encoder.c new file mode 100644 index 0000000000..c69de32467 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_encoder.c @@ -0,0 +1,223 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_encoder.c + * \brief ngap pdu encode procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ + + +#include +#include +#include + +#include "assertions.h" +#include "conversions.h" +#include "intertask_interface.h" +#include "ngap_common.h" +#include "ngap_gNB_encoder.h" + +static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, + uint8_t **buffer, + uint32_t *len); + +static inline int ngap_gNB_encode_successfull_outcome(NGAP_NGAP_PDU_t *pdu, + uint8_t **buffer, uint32_t *len); + +static inline int ngap_gNB_encode_unsuccessfull_outcome(NGAP_NGAP_PDU_t *pdu, + uint8_t **buffer, uint32_t *len); + +int ngap_gNB_encode_pdu(NGAP_NGAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) { + int ret = -1; + DevAssert(pdu != NULL); + DevAssert(buffer != NULL); + DevAssert(len != NULL); + + switch(pdu->present) { + case NGAP_NGAP_PDU_PR_initiatingMessage: + ret = ngap_gNB_encode_initiating(pdu, buffer, len); + break; + + case NGAP_NGAP_PDU_PR_successfulOutcome: + ret = ngap_gNB_encode_successfull_outcome(pdu, buffer, len); + break; + + case NGAP_NGAP_PDU_PR_unsuccessfulOutcome: + ret = ngap_gNB_encode_unsuccessfull_outcome(pdu, buffer, len); + break; + + default: + NGAP_DEBUG("Unknown message outcome (%d) or not implemented", + (int)pdu->present); + return -1; + } + + //ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, pdu); + return ret; +} + +static inline +int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, + uint8_t **buffer, uint32_t *len) { + asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + DevAssert(pdu != NULL); + + switch(pdu->choice.initiatingMessage->procedureCode) { + case NGAP_ProcedureCode_id_NGSetup: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_UplinkNASTransport: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_UERadioCapabilityInfoIndication: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_InitialUEMessage: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_NASNonDeliveryIndication: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_UEContextReleaseRequest: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_PathSwitchRequest: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_PDUSessionResourceModifyIndication: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + default: + NGAP_DEBUG("Unknown procedure ID (%d) for initiating message\n", + (int)pdu->choice.initiatingMessage->procedureCode); + return -1; + } + + if (asn1_xer_print) { + xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, (void *)pdu); + } + + memset(&res, 0, sizeof(res)); + res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_NGAP_PDU, pdu); + *buffer = res.buffer; + *len = res.result.encoded; + return 0; +} + +static inline +int ngap_gNB_encode_successfull_outcome(NGAP_NGAP_PDU_t *pdu, + uint8_t **buffer, uint32_t *len) { + asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + DevAssert(pdu != NULL); + + switch(pdu->choice.successfulOutcome->procedureCode) { + case NGAP_ProcedureCode_id_InitialContextSetup: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_UEContextRelease: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + case NGAP_ProcedureCode_id_PDUSessionResourceSetup: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("PDUSESSIONSetup successful message\n"); + break; + + case NGAP_ProcedureCode_id_PDUSessionResourceModify: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("PDUSESSIONModify successful message\n"); + break; + + case NGAP_ProcedureCode_id_PDUSessionResourceRelease: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("PDUSESSION Release successful message\n"); + break; + + default: + NGAP_WARN("Unknown procedure ID (%d) for successfull outcome message\n", + (int)pdu->choice.successfulOutcome->procedureCode); + return -1; + } + + if (asn1_xer_print) { + xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, (void *)pdu); + } + + memset(&res, 0, sizeof(res)); + res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_NGAP_PDU, pdu); + *buffer = res.buffer; + *len = res.result.encoded; + return 0; +} + +static inline +int ngap_gNB_encode_unsuccessfull_outcome(NGAP_NGAP_PDU_t *pdu, + uint8_t **buffer, uint32_t *len) { + asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + DevAssert(pdu != NULL); + + switch(pdu->choice.unsuccessfulOutcome->procedureCode) { + case NGAP_ProcedureCode_id_InitialContextSetup: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + break; + + default: + NGAP_DEBUG("Unknown procedure ID (%d) for unsuccessfull outcome message\n", + (int)pdu->choice.unsuccessfulOutcome->procedureCode); + return -1; + } + + if (asn1_xer_print) { + xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, (void *)pdu); + } + + memset(&res, 0, sizeof(res)); + res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_NGAP_PDU, pdu); + *buffer = res.buffer; + *len = res.result.encoded; + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_encoder.h b/openair3/NGAP/ngap_gNB_encoder.h new file mode 100644 index 0000000000..bd151405ff --- /dev/null +++ b/openair3/NGAP/ngap_gNB_encoder.h @@ -0,0 +1,36 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_encoder.h + * \brief ngap pdu encode procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ + +#ifndef NGAP_GNB_ENCODER_H_ +#define NGAP_GNB_ENCODER_H_ + +int ngap_gNB_encode_pdu(NGAP_NGAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) +__attribute__ ((warn_unused_result)); + +#endif /* NGAP_GNB_ENCODER_H_ */ diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c new file mode 100644 index 0000000000..2b0e8aab7c --- /dev/null +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -0,0 +1,1927 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_handlers.c + * \brief ngap messages handlers for gNB part + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ + +#include + +#include "intertask_interface.h" + +#include "asn1_conversions.h" + +#include "ngap_common.h" +// #include "ngap_gNB.h" +#include "ngap_gNB_defs.h" +#include "ngap_gNB_handlers.h" +#include "ngap_gNB_decoder.h" + +#include "ngap_gNB_ue_context.h" +#include "ngap_gNB_trace.h" +#include "ngap_gNB_nas_procedures.h" +#include "ngap_gNB_management_procedures.h" + +#include "ngap_gNB_default_values.h" + +#include "assertions.h" +#include "conversions.h" +#include "msc.h" +#include "NGAP_NonDynamic5QIDescriptor.h" + +static +int ngap_gNB_handle_ng_setup_response(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); +static +int ngap_gNB_handle_ng_setup_failure(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_error_indication(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_ue_context_release_command(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_paging(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_ng_path_switch_request_ack(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_ng_path_switch_request_failure(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +static +int ngap_gNB_handle_ng_ENDC_pdusession_modification_confirm(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +/* Handlers matrix. Only gNB related procedure present here */ +ngap_message_decoded_callback ngap_messages_callback[][3] = { + { 0, 0, 0 }, /* AMFConfigurationUpdate */ + { 0, 0, 0 }, /* AMFStatusIndication */ + { 0, 0, 0 }, /* CellTrafficTrace */ + { ngap_gNB_handle_deactivate_trace, 0, 0 }, /* DeactivateTrace */ + { ngap_gNB_handle_nas_downlink, 0, 0 }, /* DownlinkNASTransport */ + { 0, 0, 0 }, /* DownlinkNonUEAssociatedNRPPaTransport */ + { 0, 0, 0 }, /* DownlinkRANConfigurationTransfer */ + { 0, 0, 0 }, /* DownlinkRANStatusTransfer */ + { 0, 0, 0 }, /* DownlinkUEAssociatedNRPPaTransport */ + { ngap_gNB_handle_error_indication, 0, 0 }, /* ErrorIndication */ + { 0, 0, 0 }, /* HandoverCancel */ + { 0, 0, 0 }, /* HandoverNotification */ + { 0, 0, 0 }, /* HandoverPreparation */ + { 0, 0, 0 }, /* HandoverResourceAllocation */ + { ngap_gNB_handle_initial_context_request, 0, 0 }, /* InitialContextSetup */ + { 0, 0, 0 }, /* InitialUEMessage */ + { 0, 0, 0 }, /* LocationReportingControl */ + { 0, 0, 0 }, /* LocationReportingFailureIndication */ + { 0, 0, 0 }, /* LocationReport */ + { 0, 0, 0 }, /* NASNonDeliveryIndication */ + { 0, 0, 0 }, /* NGReset */ + { 0, ngap_gNB_handle_ng_setup_response, ngap_gNB_handle_ng_setup_failure }, /* NGSetup */ + { 0, 0, 0 }, /* OverloadStart */ + { 0, 0, 0 }, /* OverloadStop */ + { ngap_gNB_handle_paging, 0, 0 }, /* Paging */ + { 0, ngap_gNB_handle_ng_path_switch_request_ack, ngap_gNB_handle_ng_path_switch_request_failure }, /* PathSwitchRequest */ + { ngap_gNB_handle_pdusession_modify_request, 0, 0 }, /* PDUSessionResourceModify */ + { 0, ngap_gNB_handle_ng_ENDC_pdusession_modification_confirm, 0 }, /* PDUSessionResourceModifyIndication */ + { ngap_gNB_handle_pdusession_release_command, 0, 0 }, /* PDUSessionResourceRelease */ + { ngap_gNB_handle_pdusession_setup_request, 0, 0 }, /* PDUSessionResourceSetup */ + { 0, 0, 0 }, /* PDUSessionResourceNotify */ + { 0, 0, 0 }, /* PrivateMessage */ + { 0, 0, 0 }, /* PWSCancel */ + { 0, 0, 0 }, /* PWSFailureIndication */ + { 0, 0, 0 }, /* PWSRestartIndication */ + { 0, 0, 0 }, /* RANConfigurationUpdate */ + { 0, 0, 0 }, /* RerouteNASRequest */ + { 0, 0, 0 }, /* RRCInactiveTransitionReport */ + { 0, 0, 0 }, /* TraceFailureIndication */ + { ngap_gNB_handle_trace_start, 0, 0 }, /* TraceStart */ + { 0, 0, 0 }, /* UEContextModification */ + { ngap_gNB_handle_ue_context_release_command, 0, 0 }, /* UEContextRelease */ + { 0, 0, 0 }, /* UEContextReleaseRequest */ + { 0, 0, 0 }, /* UERadioCapabilityCheck */ + { 0, 0, 0 }, /* UERadioCapabilityInfoIndication */ + { 0, 0, 0 }, /* UETNLABindingRelease */ + { 0, 0, 0 }, /* UplinkNASTransport */ + { 0, 0, 0 }, /* UplinkNonUEAssociatedNRPPaTransport */ + { 0, 0, 0 }, /* UplinkRANConfigurationTransfer */ + { 0, 0, 0 }, /* UplinkRANStatusTransfer */ + { 0, 0, 0 }, /* UplinkUEAssociatedNRPPaTransport */ + { 0, 0, 0 }, /* WriteReplaceWarning */ + { 0, 0, 0 }, /* SecondaryRATDataUsageReport */ + +}; +char *ngap_direction2String(int ngap_dir) { + static char *ngap_direction_String[] = { + "", /* Nothing */ + "Originating message", /* originating message */ + "Successfull outcome", /* successfull outcome */ + "UnSuccessfull outcome", /* successfull outcome */ + }; + return(ngap_direction_String[ngap_dir]); +} +void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shutdown) { + if (sctp_shutdown) { + /* A previously connected AMF has been shutdown */ + + /* TODO check if it was used by some gNB and send a message to inform these gNB if there is no more associated AMF */ + if (amf_desc_p->state == NGAP_GNB_STATE_CONNECTED) { + amf_desc_p->state = NGAP_GNB_STATE_DISCONNECTED; + + if (amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb > 0) { + /* Decrease associated AMF number */ + amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb --; + } + + /* If there are no more associated AMF, inform gNB app */ + if (amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb == 0) { + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DEREGISTERED_GNB_IND); + NGAP_DEREGISTERED_GNB_IND(message_p).nb_amf = 0; + itti_send_msg_to_task(TASK_GNB_APP, amf_desc_p->ngap_gNB_instance->instance, message_p); + } + } + } else { + /* Check that at least one setup message is pending */ + DevCheck(amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb > 0, amf_desc_p->ngap_gNB_instance->instance, + amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb, 0); + + if (amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb > 0) { + /* Decrease pending messages number */ + amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb --; + } + + /* If there are no more pending messages, inform gNB app */ + if (amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb == 0) { + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_REGISTER_GNB_CNF); + NGAP_REGISTER_GNB_CNF(message_p).nb_amf = amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb; + itti_send_msg_to_task(TASK_GNB_APP, amf_desc_p->ngap_gNB_instance->instance, message_p); + } + } +} + +int ngap_gNB_handle_message(uint32_t assoc_id, int32_t stream, + const uint8_t *const data, const uint32_t data_length) { + NGAP_NGAP_PDU_t pdu; + int ret; + DevAssert(data != NULL); + memset(&pdu, 0, sizeof(pdu)); + + if (ngap_gNB_decode_pdu(&pdu, data, data_length) < 0) { + NGAP_ERROR("Failed to decode PDU\n"); + return -1; + } + + /* Checking procedure Code and direction of message */ + if (pdu.choice.initiatingMessage->procedureCode >= sizeof(ngap_messages_callback) / (3 * sizeof( + ngap_message_decoded_callback)) + || (pdu.present > NGAP_NGAP_PDU_PR_unsuccessfulOutcome)) { + NGAP_ERROR("[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n", + assoc_id, pdu.choice.initiatingMessage->procedureCode, pdu.present); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return -1; + } + + /* No handler present. + * This can mean not implemented or no procedure for gNB (wrong direction). + */ + if (ngap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1] == NULL) { + NGAP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n", + assoc_id, pdu.choice.initiatingMessage->procedureCode, + ngap_direction2String(pdu.present - 1)); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return -1; + } + + /* Calling the right handler */ + ret = (*ngap_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1]) + (assoc_id, stream, &pdu); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return ret; +} + +static +int ngap_gNB_handle_ng_setup_failure(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + NGAP_NGSetupFailure_t *container; + NGAP_NGSetupFailureIEs_t *ie; + ngap_gNB_amf_data_t *amf_desc_p; + DevAssert(pdu != NULL); + container = &pdu->choice.unsuccessfulOutcome->value.choice.NGSetupFailure; + + /* S1 Setup Failure == Non UE-related procedure -> stream 0 */ + if (stream != 0) { + NGAP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n", + assoc_id, stream); + } + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received S1 setup response for non existing " + "AMF context\n", assoc_id); + return -1; + } + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupFailureIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_Cause,true); + + if ((ie->value.choice.Cause.present == NGAP_Cause_PR_misc) && + (ie->value.choice.Cause.choice.misc == NGAP_CauseMisc_unspecified)) { + NGAP_WARN("Received NG setup failure for AMF... AMF is not ready\n"); + } else { + NGAP_ERROR("Received NG setup failure for AMF... please check your parameters\n"); + } + + amf_desc_p->state = NGAP_GNB_STATE_WAITING; + ngap_handle_ng_setup_message(amf_desc_p, 0); + return 0; +} + +static +int ngap_gNB_handle_ng_setup_response(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + NGAP_NGSetupResponse_t *container; + NGAP_NGSetupResponseIEs_t *ie; + ngap_gNB_amf_data_t *amf_desc_p; + int i; + DevAssert(pdu != NULL); + container = &pdu->choice.successfulOutcome->value.choice.NGSetupResponse; + + /* NG Setup Response == Non UE-related procedure -> stream 0 */ + if (stream != 0) { + NGAP_ERROR("[SCTP %d] Received ng setup response on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received NG setup response for non existing " + "AMF context\n", assoc_id); + return -1; + } + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_ServedGUAMIList, true); + + /* The list of served guami can contain at most 256 elements. + * NR related guami is the first element in the list, i.e with an id of 0. + */ + NGAP_DEBUG("servedGUAMIs.list.count %d\n", ie->value.choice.ServedGUAMIList.list.count); + DevAssert(ie->value.choice.ServedGUAMIList.list.count > 0); + DevAssert(ie->value.choice.ServedGUAMIList.list.count <= NGAP_maxnoofServedGUAMIs); + + for (i = 0; i < ie->value.choice.ServedGUAMIList.list.count; i++) { + NGAP_ServedGUAMIItem_t *guami_item_p; + struct served_guami_s *new_guami_p; + + guami_item_p = ie->value.choice.ServedGUAMIList.list.array[i]; + new_guami_p = calloc(1, sizeof(struct served_guami_s)); + STAILQ_INIT(&new_guami_p->served_plmns); + STAILQ_INIT(&new_guami_p->served_region_ids); + STAILQ_INIT(&new_guami_p->amf_set_ids); + STAILQ_INIT(&new_guami_p->amf_pointers); + + NGAP_PLMNIdentity_t *plmn_identity_p; + struct plmn_identity_s *new_plmn_identity_p; + plmn_identity_p = &guami_item_p->gUAMI.pLMNIdentity; + new_plmn_identity_p = calloc(1, sizeof(struct plmn_identity_s)); + TBCD_TO_MCC_MNC(plmn_identity_p, new_plmn_identity_p->mcc, + new_plmn_identity_p->mnc, new_plmn_identity_p->mnc_digit_length); + STAILQ_INSERT_TAIL(&new_guami_p->served_plmns, new_plmn_identity_p, next); + new_guami_p->nb_served_plmns++; + + NGAP_AMFRegionID_t *amf_region_id_p; + struct served_region_id_s *new_region_id_p; + amf_region_id_p = &guami_item_p->gUAMI.aMFRegionID; + new_region_id_p = calloc(1, sizeof(struct served_region_id_s)); + OCTET_STRING_TO_INT8(amf_region_id_p, new_region_id_p->amf_region_id); + STAILQ_INSERT_TAIL(&new_guami_p->served_region_ids, new_region_id_p, next); + new_guami_p->nb_region_id++; + + NGAP_AMFSetID_t *amf_set_id_p; + struct amf_set_id_s *new_amf_set_id_p; + amf_set_id_p = &guami_item_p->gUAMI.aMFSetID; + new_amf_set_id_p = calloc(1, sizeof(struct amf_set_id_s)); + OCTET_STRING_TO_INT16(amf_set_id_p, new_amf_set_id_p->amf_set_id); + STAILQ_INSERT_TAIL(&new_guami_p->amf_set_ids, new_amf_set_id_p, next); + new_guami_p->nb_amf_set_id++; + + NGAP_AMFPointer_t *amf_pointer_p; + struct amf_pointer_s *new_amf_pointer_p; + amf_pointer_p = &guami_item_p->gUAMI.aMFPointer; + new_amf_pointer_p = calloc(1, sizeof(struct amf_pointer_s)); + OCTET_STRING_TO_INT8(amf_pointer_p, new_amf_pointer_p->amf_pointer); + STAILQ_INSERT_TAIL(&new_guami_p->amf_pointers, new_amf_pointer_p, next); + new_guami_p->nb_amf_pointer++; + + STAILQ_INSERT_TAIL(&amf_desc_p->served_guami, new_guami_p, next); + } + + /* Set the capacity of this AMF */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_RelativeAMFCapacity, true); + + amf_desc_p->relative_amf_capacity = ie->value.choice.RelativeAMFCapacity; + + /* mandatory set the amf name */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_AMFName, true); + + if (ie) { + amf_desc_p->amf_name = calloc(ie->value.choice.AMFName.size + 1, sizeof(char)); + memcpy(amf_desc_p->amf_name, ie->value.choice.AMFName.buf, + ie->value.choice.AMFName.size); + /* Convert the amf name to a printable string */ + amf_desc_p->amf_name[ie->value.choice.AMFName.size] = '\0'; + } + + + /* mandatory set the plmn supports */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_PLMNSupportList, true); + + NGAP_DEBUG("PLMNSupportList.list.count %d\n", ie->value.choice.PLMNSupportList.list.count); + DevAssert(ie->value.choice.PLMNSupportList.list.count > 0); + DevAssert(ie->value.choice.PLMNSupportList.list.count <= NGAP_maxnoofPLMNs); + + STAILQ_INIT(&amf_desc_p->plmn_supports); + + for (i = 0; i < ie->value.choice.ServedGUAMIList.list.count; i++) { + NGAP_PLMNSupportItem_t *plmn_support_item_p; + struct plmn_support_s *new_plmn_support_p; + NGAP_SliceSupportItem_t *slice_support_item_p; + struct slice_support_s *new_slice_support_p; + + plmn_support_item_p = ie->value.choice.PLMNSupportList.list.array[i]; + + new_plmn_support_p = calloc(1, sizeof(struct plmn_support_s)); + + TBCD_TO_MCC_MNC(&plmn_support_item_p->pLMNIdentity, new_plmn_support_p->plmn_identity.mcc, + new_plmn_support_p->plmn_identity.mnc, new_plmn_support_p->plmn_identity.mnc_digit_length); + + NGAP_DEBUG("PLMNSupportList.list.count %d\n", plmn_support_item_p->sliceSupportList.list.count); + DevAssert(plmn_support_item_p->sliceSupportList.list.count > 0); + DevAssert(plmn_support_item_p->sliceSupportList.list.count <= NGAP_maxnoofSliceItems); + + STAILQ_INIT(&new_plmn_support_p->slice_supports); + for(int j=0; jsliceSupportList.list.count; j++) { + slice_support_item_p = plmn_support_item_p->sliceSupportList.list.array[j]; + + new_slice_support_p = calloc(1, sizeof(struct slice_support_s)); + + OCTET_STRING_TO_INT8(&slice_support_item_p->s_NSSAI.sST, new_slice_support_p->sST); + + if(slice_support_item_p->s_NSSAI.sD != NULL) { + new_slice_support_p->sD_flag = 1; + new_slice_support_p->sD[0] = slice_support_item_p->s_NSSAI.sD->buf[0]; + new_slice_support_p->sD[1] = slice_support_item_p->s_NSSAI.sD->buf[1]; + new_slice_support_p->sD[2] = slice_support_item_p->s_NSSAI.sD->buf[2]; + } + STAILQ_INSERT_TAIL(&new_plmn_support_p->slice_supports, new_slice_support_p, next); + } + + STAILQ_INSERT_TAIL(&amf_desc_p->plmn_supports, new_plmn_support_p, next); + } + + /* The association is now ready as gNB and AMF know parameters of each other. + * Mark the association as UP to enable UE contexts creation. + */ + amf_desc_p->state = NGAP_GNB_STATE_CONNECTED; + amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb ++; + ngap_handle_ng_setup_message(amf_desc_p, 0); + + return 0; +} + + +static +int ngap_gNB_handle_error_indication(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + + NGAP_ErrorIndication_t *container; + NGAP_ErrorIndicationIEs_t *ie; + ngap_gNB_amf_data_t *amf_desc_p; + uint64_t amf_ue_ngap_id; + + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.ErrorIndication; + + /* NG Setup Failure == Non UE-related procedure -> stream 0 */ + if (stream != 0) { + NGAP_WARN("[SCTP %d] Received ng Error indication on stream != 0 (%d)\n", + assoc_id, stream); + } + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received ng Error indication for non existing " + "AMF context\n", assoc_id); + return -1; + } + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, false); + + /* optional */ + if (ie != NULL) { + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id); + NGAP_WARN("Received NG Error indication AMF UE NGAP ID 0x%lx\n", amf_ue_ngap_id); + } + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, false); + + /* optional */ + if (ie != NULL) { + NGAP_WARN("Received NG Error indication gNB UE NGAP ID 0x%lx\n", ie->value.choice.RAN_UE_NGAP_ID); + } + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_Cause, false); + + /* optional */ + if (ie) { + switch(ie->value.choice.Cause.present) { + case NGAP_Cause_PR_NOTHING: + NGAP_WARN("Received NG Error indication cause NOTHING\n"); + break; + + case NGAP_Cause_PR_radioNetwork: + switch (ie->value.choice.Cause.choice.radioNetwork) { + case NGAP_CauseRadioNetwork_unspecified: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unspecified\n"); + break; + + case NGAP_CauseRadioNetwork_txnrelocoverall_expiry: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_txnrelocoverall_expiry\n"); + break; + + case NGAP_CauseRadioNetwork_successful_handover: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_successful_handover\n"); + break; + + case NGAP_CauseRadioNetwork_release_due_to_ngran_generated_reason: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_release_due_to_ngran_generated_reason\n"); + break; + + case NGAP_CauseRadioNetwork_release_due_to_5gc_generated_reason: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_release_due_to_5gc_generated_reason\n"); + break; + + case NGAP_CauseRadioNetwork_handover_cancelled: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_handover_cancelled\n"); + break; + + case NGAP_CauseRadioNetwork_partial_handover: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_partial_handover\n"); + break; + + case NGAP_CauseRadioNetwork_ho_failure_in_target_5GC_ngran_node_or_target_system: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ho_failure_in_target_5GC_ngran_node_or_target_system\n"); + break; + + case NGAP_CauseRadioNetwork_ho_target_not_allowed: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ho_target_not_allowed\n"); + break; + + case NGAP_CauseRadioNetwork_tngrelocoverall_expiry: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_tngrelocoverall_expiry\n"); + break; + + case NGAP_CauseRadioNetwork_tngrelocprep_expiry: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_tngrelocprep_expiry\n"); + break; + + case NGAP_CauseRadioNetwork_cell_not_available: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_cell_not_available\n"); + break; + + case NGAP_CauseRadioNetwork_unknown_targetID: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unknown_targetID\n"); + break; + + case NGAP_CauseRadioNetwork_no_radio_resources_available_in_target_cell: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n"); + break; + + case NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID\n"); + break; + + case NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID\n"); + break; + + case NGAP_CauseRadioNetwork_handover_desirable_for_radio_reason: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_handover_desirable_for_radio_reason\n"); + break; + + case NGAP_CauseRadioNetwork_time_critical_handover: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_time_critical_handover\n"); + break; + + case NGAP_CauseRadioNetwork_resource_optimisation_handover: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_resource_optimisation_handover\n"); + break; + + case NGAP_CauseRadioNetwork_reduce_load_in_serving_cell: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_reduce_load_in_serving_cell\n"); + break; + + case NGAP_CauseRadioNetwork_user_inactivity: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_user_inactivity\n"); + break; + + case NGAP_CauseRadioNetwork_radio_connection_with_ue_lost: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_radio_connection_with_ue_lost\n"); + break; + + case NGAP_CauseRadioNetwork_radio_resources_not_available: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_radio_resources_not_available\n"); + break; + + case NGAP_CauseRadioNetwork_invalid_qos_combination: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_invalid_qos_combination\n"); + break; + + case NGAP_CauseRadioNetwork_failure_in_radio_interface_procedure: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_failure_in_radio_interface_procedure\n"); + break; + + case NGAP_CauseRadioNetwork_interaction_with_other_procedure: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_interaction_with_other_procedure\n"); + break; + + case NGAP_CauseRadioNetwork_unknown_PDU_session_ID: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unknown_PDU_session_ID\n"); + break; + + case NGAP_CauseRadioNetwork_unkown_qos_flow_ID: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_unkown_qos_flow_ID\n"); + break; + + case NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances\n"); + break; + + case NGAP_CauseRadioNetwork_multiple_qos_flow_ID_instances: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_multiple_qos_flow_ID_instances\n"); + break; + + case NGAP_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n"); + break; + + case NGAP_CauseRadioNetwork_ng_intra_system_handover_triggered: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ng_intra_system_handover_triggered\n"); + break; + + case NGAP_CauseRadioNetwork_ng_inter_system_handover_triggered: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ng_inter_system_handover_triggered\n"); + break; + + case NGAP_CauseRadioNetwork_xn_handover_triggered: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_xn_handover_triggered\n"); + break; + + case NGAP_CauseRadioNetwork_not_supported_5QI_value: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_not_supported_5QI_value\n"); + break; + + case NGAP_CauseRadioNetwork_ue_context_transfer: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ue_context_transfer\n"); + break; + + case NGAP_CauseRadioNetwork_ims_voice_eps_fallback_or_rat_fallback_triggered: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ims_voice_eps_fallback_or_rat_fallback_triggered\n"); + break; + + case NGAP_CauseRadioNetwork_up_integrity_protection_not_possible: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_up_integrity_protection_not_possible\n"); + break; + + case NGAP_CauseRadioNetwork_up_confidentiality_protection_not_possible: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_up_confidentiality_protection_not_possible\n"); + break; + + case NGAP_CauseRadioNetwork_slice_not_supported: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_slice_not_supported\n"); + break; + + case NGAP_CauseRadioNetwork_ue_in_rrc_inactive_state_not_reachable: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ue_in_rrc_inactive_state_not_reachable\n"); + break; + + case NGAP_CauseRadioNetwork_redirection: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_redirection\n"); + break; + + case NGAP_CauseRadioNetwork_resources_not_available_for_the_slice: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_resources_not_available_for_the_slice\n"); + break; + + case NGAP_CauseRadioNetwork_ue_max_integrity_protected_data_rate_reason: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_ue_max_integrity_protected_data_rate_reason\n"); + break; + + case NGAP_CauseRadioNetwork_release_due_to_cn_detected_mobility: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_release_due_to_cn_detected_mobility\n"); + break; + + case NGAP_CauseRadioNetwork_n26_interface_not_available: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_n26_interface_not_available\n"); + break; + + case NGAP_CauseRadioNetwork_release_due_to_pre_emption: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_release_due_to_pre_emption\n"); + break; + + case NGAP_CauseRadioNetwork_multiple_location_reporting_reference_ID_instances: + NGAP_WARN("Received NG Error indication NGAP_CauseRadioNetwork_multiple_location_reporting_reference_ID_instances\n"); + break; + + default: + NGAP_WARN("Received NG Error indication cause radio network case not handled\n"); + } + + break; + + case NGAP_Cause_PR_transport: + switch (ie->value.choice.Cause.choice.transport) { + case NGAP_CauseTransport_transport_resource_unavailable: + NGAP_WARN("Received NG Error indication NGAP_CauseTransport_transport_resource_unavailable\n"); + break; + + case NGAP_CauseTransport_unspecified: + NGAP_WARN("Received NG Error indication NGAP_CauseTransport_unspecified\n"); + break; + + default: + NGAP_WARN("Received NG Error indication cause transport case not handled\n"); + } + + break; + + case NGAP_Cause_PR_nas: + switch (ie->value.choice.Cause.choice.nas) { + case NGAP_CauseNas_normal_release: + NGAP_WARN("Received NG Error indication NGAP_CauseNas_normal_release\n"); + break; + + case NGAP_CauseNas_authentication_failure: + NGAP_WARN("Received NG Error indication NGAP_CauseNas_authentication_failure\n"); + break; + + case NGAP_CauseNas_deregister: + NGAP_WARN("Received NG Error indication NGAP_CauseNas_deregister\n"); + break; + + case NGAP_CauseNas_unspecified: + NGAP_WARN("Received NG Error indication NGAP_CauseNas_unspecified\n"); + break; + + default: + NGAP_WARN("Received NG Error indication cause nas case not handled\n"); + } + + break; + + case NGAP_Cause_PR_protocol: + switch (ie->value.choice.Cause.choice.protocol) { + case NGAP_CauseProtocol_transfer_syntax_error: + NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_transfer_syntax_error\n"); + break; + + case NGAP_CauseProtocol_abstract_syntax_error_reject: + NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_abstract_syntax_error_reject\n"); + break; + + case NGAP_CauseProtocol_abstract_syntax_error_ignore_and_notify: + NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_abstract_syntax_error_ignore_and_notify\n"); + break; + + case NGAP_CauseProtocol_message_not_compatible_with_receiver_state: + NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_message_not_compatible_with_receiver_state\n"); + break; + + case NGAP_CauseProtocol_semantic_error: + NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_semantic_error\n"); + break; + + case NGAP_CauseProtocol_abstract_syntax_error_falsely_constructed_message: + NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n"); + break; + + case NGAP_CauseProtocol_unspecified: + NGAP_WARN("Received NG Error indication NGAP_CauseProtocol_unspecified\n"); + break; + + default: + NGAP_WARN("Received NG Error indication cause protocol case not handled\n"); + } + + break; + + case NGAP_Cause_PR_misc: + switch (ie->value.choice.Cause.choice.protocol) { + case NGAP_CauseMisc_control_processing_overload: + NGAP_WARN("Received NG Error indication NGAP_CauseMisc_control_processing_overload\n"); + break; + + case NGAP_CauseMisc_not_enough_user_plane_processing_resources: + NGAP_WARN("Received NG Error indication NGAP_CauseMisc_not_enough_user_plane_processing_resources\n"); + break; + + case NGAP_CauseMisc_hardware_failure: + NGAP_WARN("Received NG Error indication NGAP_CauseMisc_hardware_failure\n"); + break; + + case NGAP_CauseMisc_om_intervention: + NGAP_WARN("Received NG Error indication NGAP_CauseMisc_om_intervention\n"); + break; + + case NGAP_CauseMisc_unspecified: + NGAP_WARN("Received NG Error indication NGAP_CauseMisc_unspecified\n"); + break; + + case NGAP_CauseMisc_unknown_PLMN: + NGAP_WARN("Received NG Error indication NGAP_CauseMisc_unknown_PLMN\n"); + break; + + default: + NGAP_WARN("Received NG Error indication cause misc case not handled\n"); + } + + break; + + default: + NGAP_WARN("Received NG Error indication cause NGAP_Cause_PR_choice_Extensions\n"); + break; + + } + } + + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_CriticalityDiagnostics, false); + + if (ie) { + // TODO continue + } + + + // TODO continue + return 0; +} + + +static +int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + + int i; + ngap_gNB_amf_data_t *amf_desc_p = NULL; + ngap_gNB_ue_context_t *ue_desc_p = NULL; + MessageDef *message_p = NULL; + NGAP_InitialContextSetupRequest_t *container; + NGAP_InitialContextSetupRequestIEs_t *ie; + NGAP_RAN_UE_NGAP_ID_t ran_ue_ngap_id; + uint64_t amf_ue_ngap_id; + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.InitialContextSetupRequest; + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received initial context setup request for non " + "existing AMF context\n", assoc_id); + return -1; + } + + /* id-AMF-UE-NGAP-ID */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id); + } else { + return -1; + } + + /* id-RAN-UE-NGAP-ID */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + ran_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + + if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance, + ran_ue_ngap_id)) == NULL) { + NGAP_ERROR("[SCTP %d] Received initial context setup request for non " + "existing UE context 0x%06lx\n", assoc_id, + ran_ue_ngap_id); + return -1; + } + } else { + return -1; + } + + /* Initial context request = UE-related procedure -> stream != 0 */ + //if (stream == 0) { + // NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", + // assoc_id, stream); + // return -1; + //} + + ue_desc_p->rx_stream = stream; + ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id; + + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_INITIAL_CONTEXT_SETUP_REQ); + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + ue_desc_p->ue_initial_id = 0; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; + /* id-UEAggregateMaximumBitRate */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, false); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL), + &(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul)); + asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL), + &(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl)); + } else { + NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate\n"); + } + + + /* id-GUAMI */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_GUAMI, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mcc, + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mnc, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mnc_len); + + OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFRegionID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_region_id); + OCTET_STRING_TO_INT16(&ie->value.choice.GUAMI.aMFSetID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_set_id); + OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFPointer, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_pointer); + } else {/* ie != NULL */ + return -1; + } + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq, false); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_pdusessions = + ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; + + for (i = 0; i < ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; i++) { + NGAP_PDUSessionResourceSetupItemCxtReq_t *item_p; + asn_dec_rval_t dec_rval; + NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer_p = NULL; + NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL; + + item_p = (NGAP_PDUSessionResourceSetupItemCxtReq_t *)ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i]; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].pdusession_id = item_p->pDUSessionID; + + if (item_p->nAS_PDU != NULL) { + /* Only copy NAS pdu if present */ + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.length = item_p->nAS_PDU->size; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer = + malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); + memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer, + item_p->nAS_PDU->buf, item_p->nAS_PDU->size); + NGAP_DEBUG("Received NAS message with the PDUSESSION setup procedure\n"); + } else { + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.length = 0; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer = NULL; + } + + + dec_rval = aper_decode(NULL, + &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, + (void **)&pdusessionTransfer_p, + item_p->pDUSessionResourceSetupRequestTransfer.buf, + item_p->pDUSessionResourceSetupRequestTransfer.size, 0, 0); + + if(dec_rval.code != RC_OK) { + NGAP_ERROR("could not decode PDUSessionResourceSetupRequestTransfer\n"); + return -1; + } + + for(int j=0; j< pdusessionTransfer_p->protocolIEs.list.count; j++) { + pdusessionTransfer_ies = pdusessionTransfer_p->protocolIEs.list.array[j]; + switch(pdusessionTransfer_ies->id) { + /* optional PDUSessionAggregateMaximumBitRate */ + case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate: + break; + + /* mandatory UL-NGU-UP-TNLInformation */ + case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation: + { + NGAP_GTPTunnel_t *gTPTunnel_p; + gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; + + /* Set the transport layer address */ + memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.buffer, + gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.length = + gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; + + /* GTP tunnel endpoint ID */ + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].gtp_teid); + } + + break; + + /* optional AdditionalUL-NGU-UP-TNLInformation */ + case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation: + break; + + /* optional DataForwardingNotPossible */ + case NGAP_ProtocolIE_ID_id_DataForwardingNotPossible: + break; + + /* mandatory PDUSessionType */ + case NGAP_ProtocolIE_ID_id_PDUSessionType: + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; + break; + + /* optional SecurityIndication */ + case NGAP_ProtocolIE_ID_id_SecurityIndication: + break; + + /* optional NetworkInstance */ + case NGAP_ProtocolIE_ID_id_NetworkInstance: + break; + + /* mandatory QosFlowSetupRequestList */ + case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList: + { + NGAP_QosFlowSetupRequestItem_t *qosFlowItem_p; + + NGAP_DEBUG("QosFlowSetupRequestList.list.count %d\n", pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count); + DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count > 0); + DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count <= NGAP_maxnoofQosFlows); + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; + + for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; qosIdx++) { + qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx]; + + /* Set the QOS informations */ + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){ + if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){ + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].fiveQI = + (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI; + } + } + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.priority_level = + qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionVulnerability; + } + } + + break; + + /* optional CommonNetworkInstance */ + case NGAP_ProtocolIE_ID_id_CommonNetworkInstance: + break; + + default: + NGAP_ERROR("could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); + return -1; + } + } + + } /* for i... */ + } else {/* ie != NULL */ + NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq\n"); + } + + /* id-AllowedNSSAI */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_AllowedNSSAI, true); + + //if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + NGAP_AllowedNSSAI_Item_t *allow_nssai_item_p = NULL; + + //NGAP_DEBUG("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count); + //DevAssert(ie->value.choice.AllowedNSSAI.list.count > 0); + //DevAssert(ie->value.choice.AllowedNSSAI.list.count <= NGAP_maxnoofAllowedS_NSSAIs); + + if (ie == NULL) { + NGAP_WARN("AllowedNSSAI not present, forging 2 NSSAI\n"); + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_allowed_nssais = 2; + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sST = 01; + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD_flag = 1; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[0] = 01; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[1] = 02; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[2] = 03; + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sST = 01; + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD_flag = 1; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[0] = 00;//11; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[1] = 00;//22; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[2] = 01;//33; + } else { + NGAP_INFO("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count); + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count; + + for(i = 0; i < ie->value.choice.AllowedNSSAI.list.count; i++) { + allow_nssai_item_p = ie->value.choice.AllowedNSSAI.list.array[i]; + + OCTET_STRING_TO_INT8(&allow_nssai_item_p->s_NSSAI.sST, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sST); + + if(allow_nssai_item_p->s_NSSAI.sD != NULL) { + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD_flag = 1; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[0] = allow_nssai_item_p->s_NSSAI.sD->buf[0]; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[1] = allow_nssai_item_p->s_NSSAI.sD->buf[1]; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[2] = allow_nssai_item_p->s_NSSAI.sD->buf[2]; + } + } + } + //} else {/* ie != NULL */ + // return -1; + //} + + /* id-UESecurityCapabilities */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_UESecurityCapabilities, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.nRencryption_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRencryptionAlgorithms); + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.nRintegrity_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRintegrityProtectionAlgorithms); + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.eUTRAencryption_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAencryptionAlgorithms); + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.eUTRAintegrity_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAintegrityProtectionAlgorithms); + } else {/* ie != NULL */ + return -1; + } + + /* id-SecurityKey : Copy the security key */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_SecurityKey, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + memcpy(&NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, + ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); + + } else {/* ie != NULL */ + return -1; + } + + /* id-MobilityRestrictionList */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_MobilityRestrictionList, false); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + NGAP_MobilityRestrictionList_t *mobility_rest_list_p = NULL; + mobility_rest_list_p = &ie->value.choice.MobilityRestrictionList; + + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction_flag = 1; + TBCD_TO_MCC_MNC(&mobility_rest_list_p->servingPLMN, + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mcc, + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mnc, + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mnc_digit_length); + } + + + /* id-NAS-PDU */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_NAS_PDU, false); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + if(ie->value.choice.NAS_PDU.size > 0) { + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu_flag = 1; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size; + NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); + memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.buffer, + ie->value.choice.NAS_PDU.buf, ie->value.choice.NAS_PDU.size); + } + } + + itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); + + return 0; +} + + +static +int ngap_gNB_handle_ue_context_release_command(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + + ngap_gNB_amf_data_t *amf_desc_p = NULL; + ngap_gNB_ue_context_t *ue_desc_p = NULL; + MessageDef *message_p = NULL; + uint64_t amf_ue_ngap_id; + NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; + NGAP_UEContextReleaseCommand_t *container; + NGAP_UEContextReleaseCommand_IEs_t *ie; + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received UE context release command for non " + "existing AMF context\n", assoc_id); + return -1; + } + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_UEContextReleaseCommand_IEs_t, ie, container, + NGAP_ProtocolIE_ID_id_UE_NGAP_IDs, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + switch (ie->value.choice.UE_NGAP_IDs.present) { + case NGAP_UE_NGAP_IDs_PR_uE_NGAP_ID_pair: + gnb_ue_ngap_id = ie->value.choice.UE_NGAP_IDs.choice.uE_NGAP_ID_pair->rAN_UE_NGAP_ID; + asn_INTEGER2ulong(&(ie->value.choice.UE_NGAP_IDs.choice.uE_NGAP_ID_pair->aMF_UE_NGAP_ID), &amf_ue_ngap_id); + MSC_LOG_RX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + NULL,0, + "0 UEContextRelease/%s gNB_ue_ngap_id "NGAP_UE_ID_FMT" amf_ue_ngap_id "NGAP_UE_ID_FMT" len %u", + ngap_direction2String(pdu->present - 1), + gnb_ue_ngap_id, + amf_ue_ngap_id); + + if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance, + gnb_ue_ngap_id)) == NULL) { + NGAP_ERROR("[SCTP %d] Received UE context release command for non " + "existing UE context 0x%06lx\n", + assoc_id, + gnb_ue_ngap_id); + return -1; + } else { + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_RRC_GNB, + NULL,0, + "0 NGAP_UE_CONTEXT_RELEASE_COMMAND/%d gNB_ue_ngap_id "NGAP_UE_ID_FMT" ", + gnb_ue_ngap_id); + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_UE_CONTEXT_RELEASE_COMMAND); + + if (ue_desc_p->amf_ue_ngap_id == 0) { // case of Detach Request and switch off from RRC_IDLE mode + ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id; + } + + NGAP_UE_CONTEXT_RELEASE_COMMAND(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; + itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); + return 0; + } + + break; + + //#warning "TODO mapping amf_ue_ngap_id gnb_ue_ngap_id?" + + case NGAP_UE_NGAP_IDs_PR_aMF_UE_NGAP_ID: + asn_INTEGER2ulong(&(ie->value.choice.UE_NGAP_IDs.choice.aMF_UE_NGAP_ID), &amf_ue_ngap_id); + NGAP_ERROR("TO DO mapping amf_ue_ngap_id gnb_ue_ngap_id"); + (void)amf_ue_ngap_id; /* TODO: remove - it's to remove gcc warning about unused var */ + + case NGAP_UE_NGAP_IDs_PR_NOTHING: + default: + NGAP_ERROR("NGAP_UE_CONTEXT_RELEASE_COMMAND not processed, missing info elements"); + return -1; + } + } else { + return -1; + } + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_UEContextReleaseCommand_IEs_t, ie, container, + NGAP_ProtocolIE_ID_id_Cause, true); + /* TBD */ + + return 0; +} + +static +int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { +// NGAP_AMF_UE_NGAP_ID_t amf_ue_ngap_id; + uint64_t amf_ue_ngap_id; + NGAP_RAN_UE_NGAP_ID_t ran_ue_ngap_id; + ngap_gNB_amf_data_t *amf_desc_p = NULL; + ngap_gNB_ue_context_t *ue_desc_p = NULL; + MessageDef *message_p = NULL; + NGAP_PDUSessionResourceSetupRequest_t *container; + NGAP_PDUSessionResourceSetupRequestIEs_t *ie; + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.PDUSessionResourceSetupRequest; + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received pdu session resource setup request for non " + "existing AMF context\n", assoc_id); + return -1; + } + + /* id-AMF-UE-NGAP-ID */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id); + } else { + return -1; + } + + /* id-gNB-UE-NGAP-ID */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + ran_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + } else { + return -1; + } + + if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance, + ran_ue_ngap_id)) == NULL) { + NGAP_ERROR("[SCTP %d] Received pdu session resource setup request for non " + "existing UE context 0x%06lx\n", assoc_id, + ran_ue_ngap_id); + return -1; + } + + /* Initial context request = UE-related procedure -> stream != 0 */ + // if (stream == 0) { + // NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", + // assoc_id, stream); + // return -1; + // } + + ue_desc_p->rx_stream = stream; + + if ( ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) { + NGAP_WARN("UE context amf_ue_ngap_id is different form that of the message (%lu != %lu)", + (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); + } + + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_SETUP_REQ); + NGAP_PDUSESSION_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + ue_desc_p->ue_initial_id = 0; + NGAP_PDUSESSION_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; + NGAP_PDUSESSION_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSUReq, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + NGAP_PDUSESSION_SETUP_REQ(message_p).nb_pdusessions_tosetup = + ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; + + for (int i = 0; i < ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; i++) { + NGAP_PDUSessionResourceSetupItemSUReq_t *item_p; + asn_dec_rval_t dec_rval; + NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer_p = NULL; + NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL; + + item_p = (NGAP_PDUSessionResourceSetupItemSUReq_t *)ie->value.choice.PDUSessionResourceSetupListSUReq.list.array[i]; + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID; + + + // check for the NAS PDU + if (item_p->pDUSessionNAS_PDU->size > 0 ) { + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length = item_p->pDUSessionNAS_PDU->size; + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionNAS_PDU->size); + memcpy(NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer, + item_p->pDUSessionNAS_PDU->buf, item_p->pDUSessionNAS_PDU->size); + // NGAP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]); + } else { + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length = 0; + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer = NULL; + NGAP_WARN("NAS PDU is not provided, generate a PDUSESSION_SETUP Failure (TBD) back to AMF \n"); + } + + dec_rval = aper_decode(NULL, + &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, + (void **)&pdusessionTransfer_p, + item_p->pDUSessionResourceSetupRequestTransfer.buf, + item_p->pDUSessionResourceSetupRequestTransfer.size, 0, 0); + + if(dec_rval.code != RC_OK) { + NGAP_ERROR("could not decode PDUSessionResourceSetupRequestTransfer\n"); + return -1; + } + + for(int j=0; j< pdusessionTransfer_p->protocolIEs.list.count; j++) { + pdusessionTransfer_ies = pdusessionTransfer_p->protocolIEs.list.array[j]; + + switch(pdusessionTransfer_ies->id) { + /* optional PDUSessionAggregateMaximumBitRate */ + case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate: + break; + + /* mandatory UL-NGU-UP-TNLInformation */ + case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation: + { + NGAP_GTPTunnel_t *gTPTunnel_p; + gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; + /* The transport layer address for the IP packets */ + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].gtp_teid); + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.length = + gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; + memcpy(NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.buffer , + gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); + } + break; + + /* optional AdditionalUL-NGU-UP-TNLInformation */ + case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation: + break; + + /* optional DataForwardingNotPossible */ + case NGAP_ProtocolIE_ID_id_DataForwardingNotPossible: + break; + + /* mandatory PDUSessionType */ + case NGAP_ProtocolIE_ID_id_PDUSessionType: + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; + break; + + /* optional SecurityIndication */ + case NGAP_ProtocolIE_ID_id_SecurityIndication: + break; + + /* optional NetworkInstance */ + case NGAP_ProtocolIE_ID_id_NetworkInstance: + break; + + /* mandatory QosFlowSetupRequestList */ + case NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList: + { + NGAP_QosFlowSetupRequestItem_t *qosFlowItem_p; + + NGAP_DEBUG("servedGUAMIs.list.count %d\n", pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count); + DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count > 0); + DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count <= NGAP_maxnoofQosFlows); + + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; + + for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; qosIdx++){ + qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx]; + + /* Set the QOS informations */ + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){ + if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){ + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI = + (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI; + } + } + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level = + qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP; + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability; + NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionVulnerability; + } + } + break; + + /* optional CommonNetworkInstance */ + case NGAP_ProtocolIE_ID_id_CommonNetworkInstance: + break; + + default: + NGAP_ERROR("could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); + return -1; + } + }/* for j... */ + } /* for i... */ + itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); + }else {/* ie == NULL */ + NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSUReq\n"); + return -1; + } + return 0; +} + + +static +int ngap_gNB_handle_paging(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + + ngap_gNB_amf_data_t *amf_desc_p = NULL; + ngap_gNB_instance_t *ngap_gNB_instance = NULL; + MessageDef *message_p = NULL; + NGAP_Paging_t *container; + NGAP_PagingIEs_t *ie; + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.Paging; + // received Paging Message from AMF + NGAP_DEBUG("[SCTP %d] Received Paging Message From AMF\n",assoc_id); + + /* Paging procedure -> stream != 0 */ + if (stream == 0) { + LOG_W(NGAP,"[SCTP %d] Received Paging procedure on stream (%d)\n", + assoc_id, stream); + return -1; + } + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received Paging for non " + "existing AMF context\n", assoc_id); + return -1; + } + + ngap_gNB_instance = amf_desc_p->ngap_gNB_instance; + + if (ngap_gNB_instance == NULL) { + NGAP_ERROR("[SCTP %d] Received Paging for non existing AMF context : ngap_gNB_instance is NULL\n", + assoc_id); + return -1; + } + + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PAGING_IND); + /* convert NGAP_PagingIEs_t to ngap_paging_ind_t */ + /* id-UEIdentityIndexValue : convert UE Identity Index value */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_UEPagingIdentity, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + OCTET_STRING_TO_INT16(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFSetID, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id); + OCTET_STRING_TO_INT8(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFPointer, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer); + OCTET_STRING_TO_INT32(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->fiveG_TMSI, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi); + + NGAP_DEBUG("[SCTP %d] Received Paging Identity amf_set_id %d, amf_pointer %d, m_tmsi %d\n", + assoc_id, + NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id, + NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer, + NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi); + } else { + return -1; + } + + + NGAP_PAGING_IND(message_p).paging_drx = NGAP_PAGING_DRX_256; + /* id-pagingDRX */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_PagingDRX, false); + + /* optional */ + if (ie) { + NGAP_PAGING_IND(message_p).paging_drx = ie->value.choice.PagingDRX; + } else { + NGAP_PAGING_IND(message_p).paging_drx = NGAP_PAGING_DRX_256; + } + + memset (&NGAP_PAGING_IND(message_p).plmn_identity[0], 0, sizeof(plmn_identity_t)*256); + memset (&NGAP_PAGING_IND(message_p).tac[0], 0, sizeof(int16_t)*256); + NGAP_PAGING_IND(message_p).tai_size = 0; + /* id-TAIList */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_TAIListForPaging, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + NGAP_INFO("[SCTP %d] Received Paging taiList For Paging: count %d\n", assoc_id, ie->value.choice.TAIListForPaging.list.count); + + for (int i = 0; i < ie->value.choice.TAIListForPaging.list.count; i++) { + NGAP_TAIListForPagingItem_t *item_p; + item_p = (NGAP_TAIListForPagingItem_t *)ie->value.choice.TAIListForPaging.list.array[i]; + TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNIdentity), NGAP_PAGING_IND(message_p).plmn_identity[i].mcc, + NGAP_PAGING_IND(message_p).plmn_identity[i].mnc, + NGAP_PAGING_IND(message_p).plmn_identity[i].mnc_digit_length); + OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), NGAP_PAGING_IND(message_p).tac[i]); + NGAP_PAGING_IND(message_p).tai_size++; + NGAP_DEBUG("[SCTP %d] Received Paging: MCC %d, MNC %d, TAC %d\n", assoc_id, + NGAP_PAGING_IND(message_p).plmn_identity[i].mcc, + NGAP_PAGING_IND(message_p).plmn_identity[i].mnc, + NGAP_PAGING_IND(message_p).tac[i]); + } + } else { + return -1; + } + + //paging parameter values + NGAP_DEBUG("[SCTP %d] Received Paging parameters: Paging Identity amf_set_id %d amf_pointer %d m_tmsi %d paging_drx %d paging_priority %d\n",assoc_id, + NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id, + NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer, + NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi, + NGAP_PAGING_IND(message_p).paging_drx, NGAP_PAGING_IND(message_p).paging_priority); + /* send message to RRC */ + itti_send_msg_to_task(TASK_RRC_GNB, ngap_gNB_instance->instance, message_p); + + return 0; +} + +static +int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + + int i, nb_of_pdusessions_failed; + ngap_gNB_amf_data_t *amf_desc_p = NULL; + ngap_gNB_ue_context_t *ue_desc_p = NULL; + MessageDef *message_p = NULL; + NGAP_PDUSessionResourceModifyRequest_t *container; + NGAP_PDUSessionResourceModifyRequestIEs_t *ie; + NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; + uint64_t amf_ue_ngap_id; + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.PDUSessionResourceModifyRequest; + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received PDUSession Resource modify request for non " + "existing AMF context\n", assoc_id); + return -1; + } + + /* id-AMF-UE-NGAP-ID */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id); + } else { + return -1; + } + + /* id-RAN-UE-NGAP-ID */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + gnb_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + } else { + return -1; + } + + if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance, + gnb_ue_ngap_id)) == NULL) { + NGAP_ERROR("[SCTP %d] Received PDUSession Resource modify request for non " + "existing UE context 0x%08lx\n", assoc_id, + gnb_ue_ngap_id); + return -1; + } + + /* PDUSession Resource modify request = UE-related procedure -> stream != 0 */ + if (stream == 0) { + NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", + assoc_id, stream); + return -1; + } + + ue_desc_p->rx_stream = stream; + + if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) { + NGAP_WARN("UE context amf_ue_ngap_id is different form that of the message (%ld != %ld)", + (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP); + NGAP_PDUSESSION_MODIFY_RESP (message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModReq, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + for(nb_of_pdusessions_failed = 0; nb_of_pdusessions_failed < ie->value.choice.PDUSessionResourceModifyListModReq.list.count; nb_of_pdusessions_failed++) { + NGAP_PDUSessionResourceModifyItemModReq_t *item_p; + item_p = (NGAP_PDUSessionResourceModifyItemModReq_t *)ie->value.choice.PDUSessionResourceModifyListModReq.list.array[nb_of_pdusessions_failed]; + + NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].pdusession_id = item_p->pDUSessionID; + NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].cause = NGAP_Cause_PR_radioNetwork; + NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].cause_value = NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID; + } + } else { + return -1; + } + + NGAP_PDUSESSION_MODIFY_RESP(message_p).nb_of_pdusessions_failed = nb_of_pdusessions_failed; + ngap_gNB_pdusession_modify_resp(amf_desc_p->ngap_gNB_instance->instance, + &NGAP_PDUSESSION_MODIFY_RESP(message_p)); + itti_free(TASK_RRC_GNB,message_p); + message_p = NULL; + return -1; + } + + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_MODIFY_REQ); + NGAP_PDUSESSION_MODIFY_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + NGAP_PDUSESSION_MODIFY_REQ(message_p).amf_ue_ngap_id = amf_ue_ngap_id; + NGAP_PDUSESSION_MODIFY_REQ(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; + /* id-PDUSessionResourceModifyListModReq */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModReq, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + NGAP_PDUSESSION_MODIFY_REQ(message_p).nb_pdusessions_tomodify = + ie->value.choice.PDUSessionResourceModifyListModReq.list.count; + + for (i = 0; i < ie->value.choice.PDUSessionResourceModifyListModReq.list.count; i++) { + NGAP_PDUSessionResourceModifyItemModReq_t *item_p; + asn_dec_rval_t dec_rval; + NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer_p = NULL; + NGAP_PDUSessionResourceModifyRequestTransferIEs_t *pdusessionTransfer_ies = NULL; + + item_p = (NGAP_PDUSessionResourceModifyItemModReq_t *)ie->value.choice.PDUSessionResourceModifyListModReq.list.array[i]; + + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].pdusession_id = item_p->pDUSessionID; + + // check for the NAS PDU + if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0 ) { + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.length = item_p->nAS_PDU->size; + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); + memcpy(NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer, + item_p->nAS_PDU->buf, item_p->nAS_PDU->size); + } else { + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.length = 0; + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer = NULL; + continue; + } + + dec_rval = aper_decode(NULL, + &asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, + (void **)&pdusessionTransfer_p, + item_p->pDUSessionResourceModifyRequestTransfer.buf, + item_p->pDUSessionResourceModifyRequestTransfer.size, 0, 0); + + if(dec_rval.code != RC_OK) { + NGAP_ERROR("could not decode PDUSessionResourceModifyRequestTransfer\n"); + return -1; + } + + for(int j=0; j< pdusessionTransfer_p->protocolIEs.list.count; j++) { + pdusessionTransfer_ies = pdusessionTransfer_p->protocolIEs.list.array[j]; + switch(pdusessionTransfer_ies->id) { + /* optional PDUSessionAggregateMaximumBitRate */ + case NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate: + break; + + /* optional UL-NGU-UP-TNLModifyList */ + case NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList: + break; + + /* optional NetworkInstance */ + case NGAP_ProtocolIE_ID_id_NetworkInstance: + break; + + /* optional QosFlowAddOrModifyRequestList */ + case NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList: + { + NGAP_QosFlowAddOrModifyRequestItem_t *qosFlowItem_p; + + NGAP_DEBUG("QosFlowAddOrModifyRequestList.list.count %d\n", pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count); + DevAssert(pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count > 0); + DevAssert(pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count <= NGAP_maxnoofQosFlows); + + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; + + for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; qosIdx++) { + qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[qosIdx]; + + /* Set the QOS informations */ + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + if(qosFlowItem_p->qosFlowLevelQosParameters) { + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.priority_level = + qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.priorityLevelARP; + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionCapability; + NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionVulnerability; + } + } + } + break; + + /* optional QosFlowToReleaseList */ + case NGAP_ProtocolIE_ID_id_QosFlowToReleaseList: + break; + + /* optional AdditionalUL-NGU-UP-TNLInformation */ + case NGAP_ProtocolIE_ID_id_AdditionalUL_NGU_UP_TNLInformation: + break; + + /* optional CommonNetworkInstance */ + case NGAP_ProtocolIE_ID_id_CommonNetworkInstance: + break; + + default: + NGAP_ERROR("could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); + return -1; + } + } + } + + itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); + } else { /* of if (ie != NULL)*/ + return -1; + } + + return 0; +} +// handle pdu session release command and send it to rrc_end +static +int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + + int i; + ngap_gNB_amf_data_t *amf_desc_p = NULL; + ngap_gNB_ue_context_t *ue_desc_p = NULL; + MessageDef *message_p = NULL; + NGAP_PDUSessionResourceReleaseCommand_t *container; + NGAP_PDUSessionResourceReleaseCommandIEs_t *ie; + NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; + uint64_t amf_ue_ngap_id; + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.PDUSessionResourceReleaseCommand; + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received pdu session release command for non existing AMF context\n", assoc_id); + return -1; + } + + + /* id-AMF-UE-NGAP-ID */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id); + } else { + return -1; + } + + /* id-RAN-UE-NGAP-ID */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + gnb_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + } else { + return -1; + } + + if ((ue_desc_p = ngap_gNB_get_ue_context(amf_desc_p->ngap_gNB_instance, + gnb_ue_ngap_id)) == NULL) { + NGAP_ERROR("[SCTP %d] Received PDUSession Resource release command for non existing UE context 0x%08lx\n", assoc_id, + ie->value.choice.RAN_UE_NGAP_ID); + return -1; + } + + /* Initial context request = UE-related procedure -> stream != 0 */ + // if (stream == 0) { + // NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", + // assoc_id, stream); + // return -1; + // } + + ue_desc_p->rx_stream = stream; + + if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) { + NGAP_WARN("UE context amf_ue_ngap_id is different form that of the message (%lu != %lu)", + (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); + } + + NGAP_DEBUG("[SCTP %d] Received pdu session release command for gNB_UE_NGAP_ID %lu amf_ue_ngap_id %lu\n", + assoc_id, gnb_ue_ngap_id, amf_ue_ngap_id); + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_RELEASE_COMMAND); + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).amf_ue_ngap_id = amf_ue_ngap_id; + /* id-NAS-PDU */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_NAS_PDU, false); + + if(ie && ie->value.choice.NAS_PDU.size > 0) { + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size; + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); + memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer, + ie->value.choice.NAS_PDU.buf, + ie->value.choice.NAS_PDU.size); + } else { + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.length = 0; + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL; + } + + /* id-PDUSessionResourceToReleaseListRelCmd */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_PDUSessionResourceToReleaseListRelCmd, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nb_pdusessions_torelease = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; + + for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) { + NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p; + item_p = (NGAP_PDUSessionResourceToReleaseItemRelCmd_t *)ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i]; + + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].pdusession_id = item_p->pDUSessionID; + if(item_p->pDUSessionResourceReleaseCommandTransfer.size > 0) { + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = item_p->pDUSessionResourceReleaseCommandTransfer.size; + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionResourceReleaseCommandTransfer.size); + memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer, + item_p->pDUSessionResourceReleaseCommandTransfer.buf, + item_p->pDUSessionResourceReleaseCommandTransfer.size); + }else { + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = 0; + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = NULL; + NGAP_ERROR("[NGAP] Received pdu session release command for pDUSessionResourceReleaseCommandTransfer is NULL!\n"); + } + NGAP_DEBUG("[NGAP] Received pdu session release command for pDUSessionID id %ld\n", item_p->pDUSessionID); + } + } else { + return -1; + } + + itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p); + + return 0; +} + +static +int ngap_gNB_handle_ng_path_switch_request_ack(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + // TODO + return 0; +} + +static +int ngap_gNB_handle_ng_path_switch_request_failure(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) { + + // TODO + return 0; +} + +static +int ngap_gNB_handle_ng_ENDC_pdusession_modification_confirm(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu){ + + LOG_W(NGAP, "Implementation of NGAP Pdusession Modification confirm handler is pending...\n"); + return 0; +} + diff --git a/openair3/NGAP/ngap_gNB_handlers.h b/openair3/NGAP/ngap_gNB_handlers.h new file mode 100644 index 0000000000..889946dd44 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_handlers.h @@ -0,0 +1,38 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_handlers.h + * \brief ngap messages handlers for gNB part + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ + +#ifndef NGAP_GNB_HANDLERS_H_ +#define NGAP_GNB_HANDLERS_H_ + +void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shutdown); + +int ngap_gNB_handle_message(uint32_t assoc_id, int32_t stream, + const uint8_t * const data, const uint32_t data_length); + +#endif /* NGAP_GNB_HANDLERS_H_ */ diff --git a/openair3/NGAP/ngap_gNB_itti_messaging.c b/openair3/NGAP/ngap_gNB_itti_messaging.c new file mode 100644 index 0000000000..ab10fa46e2 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_itti_messaging.c @@ -0,0 +1,85 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_itti_messaging.c + * \brief ngap itti messages handlers for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 + * \version 0.1 + */ + +#include "intertask_interface.h" + +#include "ngap_gNB_itti_messaging.h" + +void ngap_gNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer, + uint32_t buffer_length, uint16_t stream) +{ + MessageDef *message_p; + sctp_data_req_t *sctp_data_req; + + message_p = itti_alloc_new_message(TASK_NGAP, 0, SCTP_DATA_REQ); + + sctp_data_req = &message_p->ittiMsg.sctp_data_req; + + sctp_data_req->assoc_id = assoc_id; + sctp_data_req->buffer = buffer; + sctp_data_req->buffer_length = buffer_length; + sctp_data_req->stream = stream; + + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + +void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance, + uint16_t ue_initial_id, + uint32_t gNB_ue_ngap_id, + uint8_t *nas_pdu, + uint32_t nas_pdu_length) +{ + MessageDef *message_p; + ngap_downlink_nas_t *ngap_downlink_nas; + + message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DOWNLINK_NAS); + + ngap_downlink_nas = &message_p->ittiMsg.ngap_downlink_nas; + + ngap_downlink_nas->ue_initial_id = ue_initial_id; + ngap_downlink_nas->gNB_ue_ngap_id = gNB_ue_ngap_id; + ngap_downlink_nas->nas_pdu.buffer = malloc(sizeof(uint8_t) * nas_pdu_length); + memcpy(ngap_downlink_nas->nas_pdu.buffer, nas_pdu, nas_pdu_length); + ngap_downlink_nas->nas_pdu.length = nas_pdu_length; + + itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p); +} + +void ngap_gNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id) +{ + MessageDef *message_p = NULL; + sctp_close_association_t *sctp_close_association_p = NULL; + + message_p = itti_alloc_new_message(TASK_NGAP, 0, SCTP_CLOSE_ASSOCIATION); + sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; + sctp_close_association_p->assoc_id = assoc_id; + + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools_common.c b/openair3/NGAP/ngap_gNB_itti_messaging.h similarity index 56% rename from openair1/PHY/NR_TRANSPORT/nr_dci_tools_common.c rename to openair3/NGAP/ngap_gNB_itti_messaging.h index d26a52f157..94d4058178 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools_common.c +++ b/openair3/NGAP/ngap_gNB_itti_messaging.h @@ -18,45 +18,29 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ - -/*! \file PHY/NR_TRANSPORT/nr_dci_tools_common.c - * \brief - * \author - * \date 2018 + +/*! \file ngap_gNB_itti_messaging.h + * \brief ngap itti messages handlers for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \date 2020 * \version 0.1 - * \company Eurecom - * \email: - * \note - * \warning */ -#include "nr_dci.h" +#ifndef NGAP_GNB_ITTI_MESSAGING_H_ +#define NGAP_GNB_ITTI_MESSAGING_H_ -//#define DEBUG_FILL_DCI +void ngap_gNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer, + uint32_t buffer_length, uint16_t stream); -#include "nr_dlsch.h" +void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance, + uint16_t ue_initial_id, + uint32_t gNB_ue_ngap_id, + uint8_t *nas_pdu, + uint32_t nas_pdu_length); + +void ngap_gNB_itti_send_sctp_close_association(instance_t instance, + int32_t assoc_id); -void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) { - - uint8_t count=0, start=0, start_set=0; - - uint64_t bitmap = (((uint64_t)FreqDomainResource[0])<<37)| - (((uint64_t)FreqDomainResource[1])<<29)| - (((uint64_t)FreqDomainResource[2])<<21)| - (((uint64_t)FreqDomainResource[3])<<13)| - (((uint64_t)FreqDomainResource[4])<<5)| - (((uint64_t)FreqDomainResource[5])>>3); - - for (int i=0; i<45; i++) - if ((bitmap>>(44-i))&1) { - count++; - if (!start_set) { - start = i; - start_set = 1; - } - } - *rb_offset = 6*start; - *n_rb = 6*count; -} - +#endif /* NGAP_GNB_ITTI_MESSAGING_H_ */ diff --git a/openair3/NGAP/ngap_gNB_management_procedures.c b/openair3/NGAP/ngap_gNB_management_procedures.c new file mode 100644 index 0000000000..85167ed7f0 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_management_procedures.c @@ -0,0 +1,193 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_management_procedures.c + * \brief NGAP gNB task + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \version 1.0 + * @ingroup _ngap + */ + +#include +#include +#include + +#include "intertask_interface.h" + +#include "assertions.h" +#include "conversions.h" + +#include "ngap_common.h" +#include "ngap_gNB_defs.h" +#include "ngap_gNB.h" + +ngap_gNB_internal_data_t ngap_gNB_internal_data; + +RB_GENERATE(ngap_amf_map, ngap_gNB_amf_data_s, entry, ngap_gNB_compare_assoc_id); + +int ngap_gNB_compare_assoc_id( + struct ngap_gNB_amf_data_s *p1, struct ngap_gNB_amf_data_s *p2) +{ + if (p1->assoc_id == -1) { + if (p1->cnx_id < p2->cnx_id) { + return -1; + } + + if (p1->cnx_id > p2->cnx_id) { + return 1; + } + } else { + if (p1->assoc_id < p2->assoc_id) { + return -1; + } + + if (p1->assoc_id > p2->assoc_id) { + return 1; + } + } + + /* Matching reference */ + return 0; +} + +uint16_t ngap_gNB_fetch_add_global_cnx_id(void) +{ + return ++ngap_gNB_internal_data.global_cnx_id; +} + +void ngap_gNB_prepare_internal_data(void) +{ + memset(&ngap_gNB_internal_data, 0, sizeof(ngap_gNB_internal_data)); + STAILQ_INIT(&ngap_gNB_internal_data.ngap_gNB_instances_head); +} + +void ngap_gNB_insert_new_instance(ngap_gNB_instance_t *new_instance_p) +{ + DevAssert(new_instance_p != NULL); + + STAILQ_INSERT_TAIL(&ngap_gNB_internal_data.ngap_gNB_instances_head, + new_instance_p, ngap_gNB_entries); +} + +struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF( + ngap_gNB_instance_t *instance_p, + int32_t assoc_id, uint16_t cnx_id) +{ + struct ngap_gNB_amf_data_s temp; + struct ngap_gNB_amf_data_s *found; + + memset(&temp, 0, sizeof(struct ngap_gNB_amf_data_s)); + + temp.assoc_id = assoc_id; + temp.cnx_id = cnx_id; + + if (instance_p == NULL) { + STAILQ_FOREACH(instance_p, &ngap_gNB_internal_data.ngap_gNB_instances_head, + ngap_gNB_entries) { + found = RB_FIND(ngap_amf_map, &instance_p->ngap_amf_head, &temp); + + if (found != NULL) { + return found; + } + } + } else { + return RB_FIND(ngap_amf_map, &instance_p->ngap_amf_head, &temp); + } + + return NULL; +} + +struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF_from_instance( + ngap_gNB_instance_t *instance_p) +{ + + struct ngap_gNB_amf_data_s *amf = NULL; + struct ngap_gNB_amf_data_s *amf_next = NULL; + + for (amf = RB_MIN(ngap_amf_map, &instance_p->ngap_amf_head); amf!=NULL ; amf = amf_next) { + amf_next = RB_NEXT(ngap_amf_map, &instance_p->ngap_amf_head, amf); + if (amf->ngap_gNB_instance == instance_p) { + return amf; + } + } + + return NULL; +} + +ngap_gNB_instance_t *ngap_gNB_get_instance(instance_t instance) +{ + ngap_gNB_instance_t *temp = NULL; + + STAILQ_FOREACH(temp, &ngap_gNB_internal_data.ngap_gNB_instances_head, + ngap_gNB_entries) { + if (temp->instance == instance) { + /* Matching occurence */ + return temp; + } + } + + return NULL; +} + +void ngap_gNB_remove_amf_desc(ngap_gNB_instance_t * instance) +{ + + struct ngap_gNB_amf_data_s *amf = NULL; + struct ngap_gNB_amf_data_s *amfNext = NULL; + struct plmn_identity_s* plmnInfo; + struct served_region_id_s* regionInfo; + struct served_guami_s* guamInfo; + struct amf_set_id_s* amfSet; + struct amf_pointer_s* amfPoint; + for (amf = RB_MIN(ngap_amf_map, &instance->ngap_amf_head); amf; amf = amfNext) { + amfNext = RB_NEXT(ngap_amf_map, &instance->ngap_amf_head, amf); + RB_REMOVE(ngap_amf_map, &instance->ngap_amf_head, amf); + while (!STAILQ_EMPTY(&amf->served_guami)) { + guamInfo = STAILQ_FIRST(&amf->served_guami); + STAILQ_REMOVE_HEAD(&amf->served_guami, next); + + while (!STAILQ_EMPTY(&guamInfo->served_plmns)) { + plmnInfo = STAILQ_FIRST(&guamInfo->served_plmns); + STAILQ_REMOVE_HEAD(&guamInfo->served_plmns, next); + free(plmnInfo); + } + while (!STAILQ_EMPTY(&guamInfo->served_region_ids)) { + regionInfo = STAILQ_FIRST(&guamInfo->served_region_ids); + STAILQ_REMOVE_HEAD(&guamInfo->served_region_ids, next); + free(regionInfo); + } + while (!STAILQ_EMPTY(&guamInfo->amf_set_ids)) { + amfSet = STAILQ_FIRST(&guamInfo->amf_set_ids); + STAILQ_REMOVE_HEAD(&guamInfo->amf_set_ids, next); + free(amfSet); + } + while (!STAILQ_EMPTY(&guamInfo->amf_pointers)) { + amfPoint = STAILQ_FIRST(&guamInfo->amf_pointers); + STAILQ_REMOVE_HEAD(&guamInfo->amf_pointers, next); + free(amfPoint); + } + free(guamInfo); + } + free(amf); + } +} diff --git a/openair3/NGAP/ngap_gNB_management_procedures.h b/openair3/NGAP/ngap_gNB_management_procedures.h new file mode 100644 index 0000000000..e192f71be9 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_management_procedures.h @@ -0,0 +1,50 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_management_procedures.h + * \brief NGAP gNB task + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \version 1.0 + * @ingroup _ngap + */ + +#ifndef NGAP_GNB_MANAGEMENT_PROCEDURES_H_ +#define NGAP_GNB_MANAGEMENT_PROCEDURES_H_ + +struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF( + ngap_gNB_instance_t *instance_p, + int32_t assoc_id, uint16_t cnx_id); + +struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF_from_instance(ngap_gNB_instance_t *instance_p); + +void ngap_gNB_remove_amf_desc(ngap_gNB_instance_t * instance); + +void ngap_gNB_insert_new_instance(ngap_gNB_instance_t *new_instance_p); + +ngap_gNB_instance_t *ngap_gNB_get_instance(uint8_t mod_id); + +uint16_t ngap_gNB_fetch_add_global_cnx_id(void); + +void ngap_gNB_prepare_internal_data(void); + +#endif /* NGAP_GNB_MANAGEMENT_PROCEDURES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c new file mode 100644 index 0000000000..6686f8c19e --- /dev/null +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -0,0 +1,1504 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_nas_procedures.c + * \brief NGAP gNb NAS procedure handler + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \version 1.0 + * @ingroup _ngap + */ + + +#include +#include +#include + +#include "assertions.h" +#include "conversions.h" + +#include "intertask_interface.h" + +#include "ngap_common.h" +#include "ngap_gNB_defs.h" + +#include "ngap_gNB_itti_messaging.h" + +#include "ngap_gNB_encoder.h" +#include "ngap_gNB_nnsf.h" +#include "ngap_gNB_ue_context.h" +#include "ngap_gNB_nas_procedures.h" +#include "ngap_gNB_management_procedures.h" +#include "msc.h" + +//------------------------------------------------------------------------------ +int ngap_gNB_handle_nas_first_req( + instance_t instance, ngap_nas_first_req_t *ngap_nas_first_req_p) +//------------------------------------------------------------------------------ +{ + ngap_gNB_instance_t *instance_p = NULL; + struct ngap_gNB_amf_data_s *amf_desc_p = NULL; + struct ngap_gNB_ue_context_s *ue_desc_p = NULL; + NGAP_NGAP_PDU_t pdu; + NGAP_InitialUEMessage_t *out; + NGAP_InitialUEMessage_IEs_t *ie; + NGAP_UserLocationInformationNR_t *userinfo_nr_p = NULL; + uint8_t *buffer = NULL; + uint32_t length = 0; + DevAssert(ngap_nas_first_req_p != NULL); + /* Retrieve the NGAP gNB instance associated with Mod_id */ + instance_p = ngap_gNB_get_instance(instance); + DevAssert(instance_p != NULL); + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = (NGAP_InitiatingMessage_t *)calloc(1,sizeof(NGAP_InitiatingMessage_t)); + pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_InitialUEMessage; + pdu.choice.initiatingMessage->criticality = NGAP_Criticality_ignore; + pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_InitialUEMessage; + out = &pdu.choice.initiatingMessage->value.choice.InitialUEMessage; + + /* Select the AMF corresponding to the provided GUAMI. */ + //TODO have not be test. it's should be test + if (ngap_nas_first_req_p->ue_identity.presenceMask & NGAP_UE_IDENTITIES_guami) { + amf_desc_p = ngap_gNB_nnsf_select_amf_by_guami( + instance_p, + ngap_nas_first_req_p->establishment_cause, + ngap_nas_first_req_p->ue_identity.guami); + + if (amf_desc_p) { + NGAP_INFO("[gNB %ld] Chose AMF '%s' (assoc_id %d) through GUAMI MCC %d MNC %d AMFRI %d AMFSI %d AMFPT %d\n", + instance, + amf_desc_p->amf_name, + amf_desc_p->assoc_id, + ngap_nas_first_req_p->ue_identity.guami.mcc, + ngap_nas_first_req_p->ue_identity.guami.mnc, + ngap_nas_first_req_p->ue_identity.guami.amf_region_id, + ngap_nas_first_req_p->ue_identity.guami.amf_set_id, + ngap_nas_first_req_p->ue_identity.guami.amf_pointer); + } + } + + if (amf_desc_p == NULL) { + /* Select the AMF corresponding to the provided s-TMSI. */ + //TODO have not be test. it's should be test + if (ngap_nas_first_req_p->ue_identity.presenceMask & NGAP_UE_IDENTITIES_FiveG_s_tmsi) { + amf_desc_p = ngap_gNB_nnsf_select_amf_by_amf_setid( + instance_p, + ngap_nas_first_req_p->establishment_cause, + ngap_nas_first_req_p->selected_plmn_identity, + ngap_nas_first_req_p->ue_identity.s_tmsi.amf_set_id); + + if (amf_desc_p) { + NGAP_INFO("[gNB %ld] Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN Identity index %d MCC %d MNC %d\n", + instance, + amf_desc_p->amf_name, + amf_desc_p->assoc_id, + ngap_nas_first_req_p->ue_identity.s_tmsi.amf_set_id, + ngap_nas_first_req_p->selected_plmn_identity, + instance_p->mcc[ngap_nas_first_req_p->selected_plmn_identity], + instance_p->mnc[ngap_nas_first_req_p->selected_plmn_identity]); + } + } + } + + if (amf_desc_p == NULL) { + /* Select AMF based on the selected PLMN identity, received through RRC + * Connection Setup Complete */ + //TODO have not be test. it's should be test + amf_desc_p = ngap_gNB_nnsf_select_amf_by_plmn_id( + instance_p, + ngap_nas_first_req_p->establishment_cause, + ngap_nas_first_req_p->selected_plmn_identity); + + if (amf_desc_p) { + NGAP_INFO("[gNB %ld] Chose AMF '%s' (assoc_id %d) through selected PLMN Identity index %d MCC %d MNC %d\n", + instance, + amf_desc_p->amf_name, + amf_desc_p->assoc_id, + ngap_nas_first_req_p->selected_plmn_identity, + instance_p->mcc[ngap_nas_first_req_p->selected_plmn_identity], + instance_p->mnc[ngap_nas_first_req_p->selected_plmn_identity]); + } + } + + if (amf_desc_p == NULL) { + /* + * If no AMF corresponds to the GUAMI, the s-TMSI, or the selected PLMN + * identity, selects the AMF with the highest capacity. + */ + //TODO have not be test. it's should be test + amf_desc_p = ngap_gNB_nnsf_select_amf( + instance_p, + ngap_nas_first_req_p->establishment_cause); + + if (amf_desc_p) { + NGAP_INFO("[gNB %ld] Chose AMF '%s' (assoc_id %d) through highest relative capacity\n", + instance, + amf_desc_p->amf_name, + amf_desc_p->assoc_id); + } + } + + if (amf_desc_p == NULL) { + /* + * In case gNB has no AMF associated, the gNB should inform RRC and discard + * this request. + */ + NGAP_WARN("No AMF is associated to the gNB\n"); + // TODO: Inform RRC + return -1; + } + + /* The gNB should allocate a unique gNB UE NGAP ID for this UE. The value + * will be used for the duration of the connectivity. + */ + ue_desc_p = ngap_gNB_allocate_new_UE_context(); + DevAssert(ue_desc_p != NULL); + /* Keep a reference to the selected AMF */ + ue_desc_p->amf_ref = amf_desc_p; + ue_desc_p->ue_initial_id = ngap_nas_first_req_p->ue_initial_id; + ue_desc_p->gNB_instance = instance_p; + ue_desc_p->selected_plmn_identity = ngap_nas_first_req_p->selected_plmn_identity; + + do { + struct ngap_gNB_ue_context_s *collision_p; + /* Peek a random value for the gNB_ue_ngap_id */ + ue_desc_p->gNB_ue_ngap_id = (random() + random()) & 0xffffffff; + + if ((collision_p = RB_INSERT(ngap_ue_map, &instance_p->ngap_ue_head, ue_desc_p)) + == NULL) { + NGAP_DEBUG("Found usable gNB_ue_ngap_id: 0x%08x %u(10)\n", + ue_desc_p->gNB_ue_ngap_id, + ue_desc_p->gNB_ue_ngap_id); + /* Break the loop as the id is not already used by another UE */ + break; + } + } while(1); + + /* mandatory */ + ie = (NGAP_InitialUEMessage_IEs_t *)calloc(1, sizeof(NGAP_InitialUEMessage_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = ue_desc_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_InitialUEMessage_IEs_t *)calloc(1, sizeof(NGAP_InitialUEMessage_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_NAS_PDU; +#if 1 + ie->value.choice.NAS_PDU.buf = ngap_nas_first_req_p->nas_pdu.buffer; +#else + ie->value.choice.NAS_PDU.buf = malloc(ngap_nas_first_req_p->nas_pdu.length); + memcpy(ie->value.choice.NAS_PDU.buf, + ngap_nas_first_req_p->nas_pdu.buffer, + ngap_nas_first_req_p->nas_pdu.length); +#endif + ie->value.choice.NAS_PDU.size = ngap_nas_first_req_p->nas_pdu.length; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (NGAP_InitialUEMessage_IEs_t *)calloc(1, sizeof(NGAP_InitialUEMessage_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_UserLocationInformation; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_UserLocationInformation; + + ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR; + + ie->value.choice.UserLocationInformation.choice.userLocationInformationNR = + CALLOC(1, sizeof(*ie->value.choice.UserLocationInformation.choice.userLocationInformationNR)); + userinfo_nr_p = ie->value.choice.UserLocationInformation.choice.userLocationInformationNR; + + /* Set nRCellIdentity. default userLocationInformationNR */ + MACRO_GNB_ID_TO_CELL_IDENTITY(instance_p->gNB_id, + 0, // Cell ID + &userinfo_nr_p->nR_CGI.nRCellIdentity); + MCC_MNC_TO_TBCD(instance_p->mcc[ue_desc_p->selected_plmn_identity], + instance_p->mnc[ue_desc_p->selected_plmn_identity], + instance_p->mnc_digit_length[ue_desc_p->selected_plmn_identity], + &userinfo_nr_p->nR_CGI.pLMNIdentity); + + /* Set TAI */ + INT24_TO_OCTET_STRING(instance_p->tac, &userinfo_nr_p->tAI.tAC); + MCC_MNC_TO_PLMNID(instance_p->mcc[ue_desc_p->selected_plmn_identity], + instance_p->mnc[ue_desc_p->selected_plmn_identity], + instance_p->mnc_digit_length[ue_desc_p->selected_plmn_identity], + &userinfo_nr_p->tAI.pLMNIdentity); + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + /* Set the establishment cause according to those provided by RRC */ + DevCheck(ngap_nas_first_req_p->establishment_cause < NGAP_RRC_CAUSE_LAST, + ngap_nas_first_req_p->establishment_cause, NGAP_RRC_CAUSE_LAST, 0); + + /* mandatory */ + ie = (NGAP_InitialUEMessage_IEs_t *)calloc(1, sizeof(NGAP_InitialUEMessage_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RRCEstablishmentCause; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_RRCEstablishmentCause; + ie->value.choice.RRCEstablishmentCause = ngap_nas_first_req_p->establishment_cause; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (ngap_nas_first_req_p->ue_identity.presenceMask & NGAP_UE_IDENTITIES_FiveG_s_tmsi) { + NGAP_DEBUG("FIVEG_S_TMSI_PRESENT\n"); + ie = (NGAP_InitialUEMessage_IEs_t *)calloc(1, sizeof(NGAP_InitialUEMessage_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_FiveG_S_TMSI; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_FiveG_S_TMSI; + AMF_SETID_TO_BIT_STRING(ngap_nas_first_req_p->ue_identity.s_tmsi.amf_set_id, + &ie->value.choice.FiveG_S_TMSI.aMFSetID); + AMF_SETID_TO_BIT_STRING(ngap_nas_first_req_p->ue_identity.s_tmsi.amf_pointer, + &ie->value.choice.FiveG_S_TMSI.aMFPointer); + M_TMSI_TO_OCTET_STRING(ngap_nas_first_req_p->ue_identity.s_tmsi.m_tmsi, + &ie->value.choice.FiveG_S_TMSI.fiveG_TMSI); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + + /* optional */ + ie = (NGAP_InitialUEMessage_IEs_t *)calloc(1, sizeof(NGAP_InitialUEMessage_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_UEContextRequest; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_UEContextRequest; + ie->value.choice.UEContextRequest = NGAP_UEContextRequest_requested; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + /* Failed to encode message */ + DevMessage("Failed to encode initial UE message\n"); + } + + /* Update the current NGAP UE state */ + ue_desc_p->ue_state = NGAP_UE_WAITING_CSR; + /* Assign a stream for this UE : + * From 3GPP 38.412 7)Transport layers: + * Within the SCTP association established between one AMF and gNB pair: + * - a single pair of stream identifiers shall be reserved for the sole use + * of NGAP elementary procedures that utilize non UE-associated signalling. + * - At least one pair of stream identifiers shall be reserved for the sole use + * of NGAP elementary procedures that utilize UE-associated signallings. + * However a few pairs (i.e. more than one) should be reserved. + * - A single UE-associated signalling shall use one SCTP stream and + * the stream should not be changed during the communication of the + * UE-associated signalling. + */ + amf_desc_p->nextstream = (amf_desc_p->nextstream + 1) % amf_desc_p->out_streams; + + if ((amf_desc_p->nextstream == 0) && (amf_desc_p->out_streams > 1)) { + amf_desc_p->nextstream += 1; + } + + ue_desc_p->tx_stream = amf_desc_p->nextstream; + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)NULL, + 0, + MSC_AS_TIME_FMT" initialUEMessage initiatingMessage gNB_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + ue_desc_p->gNB_ue_ngap_id); + /* Send encoded message over sctp */ + ngap_gNB_itti_send_sctp_data_req(instance_p->instance, amf_desc_p->assoc_id, + buffer, length, ue_desc_p->tx_stream); + + return 0; +} + +//------------------------------------------------------------------------------ +int ngap_gNB_handle_nas_downlink(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) +//------------------------------------------------------------------------------ +{ + + ngap_gNB_amf_data_t *amf_desc_p = NULL; + ngap_gNB_ue_context_t *ue_desc_p = NULL; + ngap_gNB_instance_t *ngap_gNB_instance = NULL; + NGAP_DownlinkNASTransport_t *container; + NGAP_DownlinkNASTransport_IEs_t *ie; + NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; + uint64_t amf_ue_ngap_id; + DevAssert(pdu != NULL); + + /* UE-related procedure -> stream != 0 */ + // if (stream == 0) { + // NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream == 0\n", + // assoc_id); + // return -1; + // } + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR( + "[SCTP %d] Received NAS downlink message for non existing AMF context\n", + assoc_id); + return -1; + } + + ngap_gNB_instance = amf_desc_p->ngap_gNB_instance; + /* Prepare the NGAP message to encode */ + container = &pdu->choice.initiatingMessage->value.choice.DownlinkNASTransport; + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkNASTransport_IEs_t, ie, container, + NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, true); + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id); + + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkNASTransport_IEs_t, ie, container, + NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, true); + gnb_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + + if ((ue_desc_p = ngap_gNB_get_ue_context(ngap_gNB_instance, + gnb_ue_ngap_id)) == NULL) { + MSC_LOG_RX_DISCARDED_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + NULL, + 0, + MSC_AS_TIME_FMT" downlinkNASTransport gNB_ue_ngap_id %u amf_ue_ngap_id %u", + gnb_ue_ngap_id, + amf_ue_ngap_id); + NGAP_ERROR("[SCTP %d] Received NAS downlink message for non existing UE context gNB_UE_NGAP_ID: 0x%lx\n", + assoc_id, + gnb_ue_ngap_id); + return -1; + } + + if (0 == ue_desc_p->rx_stream) { + ue_desc_p->rx_stream = stream; + } else if (stream != ue_desc_p->rx_stream) { + NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream %u, expecting %u\n", + assoc_id, stream, ue_desc_p->rx_stream); + return -1; + } + + /* Is it the first outcome of the AMF for this UE ? If so store the amf + * UE ngap id. + */ + if (ue_desc_p->amf_ue_ngap_id == 0) { + ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id; + } else { + /* We already have a amf ue ngap id check the received is the same */ + if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) { + NGAP_ERROR("[SCTP %d] Mismatch in AMF UE NGAP ID (0x%lx != 0x%"PRIx64"\n", + assoc_id, + amf_ue_ngap_id, + (uint64_t)ue_desc_p->amf_ue_ngap_id + ); + return -1; + } + } + + MSC_LOG_RX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + NULL, + 0, + MSC_AS_TIME_FMT" downlinkNASTransport gNB_ue_ngap_id %u amf_ue_ngap_id %u", + assoc_id, + amf_ue_ngap_id); + + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkNASTransport_IEs_t, ie, container, + NGAP_ProtocolIE_ID_id_NAS_PDU, true); + /* Forward the NAS PDU to NR-RRC */ + ngap_gNB_itti_send_nas_downlink_ind(ngap_gNB_instance->instance, + ue_desc_p->ue_initial_id, + ue_desc_p->gNB_ue_ngap_id, + ie->value.choice.NAS_PDU.buf, + ie->value.choice.NAS_PDU.size); + + return 0; +} + +//------------------------------------------------------------------------------ +int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_p) +//------------------------------------------------------------------------------ +{ + struct ngap_gNB_ue_context_s *ue_context_p; + ngap_gNB_instance_t *ngap_gNB_instance_p; + NGAP_NGAP_PDU_t pdu; + NGAP_UplinkNASTransport_t *out; + NGAP_UplinkNASTransport_IEs_t *ie; + NGAP_UserLocationInformationNR_t *userinfo_nr_p = NULL; + uint8_t *buffer; + uint32_t length; + DevAssert(ngap_uplink_nas_p != NULL); + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, ngap_uplink_nas_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: %08x\n", + ngap_uplink_nas_p->gNB_ue_ngap_id); + return -1; + } + + /* Uplink NAS transport can occur either during an ngap connected state + * or during initial attach (for example: NAS authentication). + */ + if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || + ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { + NGAP_WARN("You are attempting to send NAS data over non-connected " + "gNB ue ngap id: %u, current state: %d\n", + ngap_uplink_nas_p->gNB_ue_ngap_id, ue_context_p->ue_state); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = (NGAP_InitiatingMessage_t *)calloc(1,sizeof(NGAP_InitiatingMessage_t)); + pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_UplinkNASTransport; + pdu.choice.initiatingMessage->criticality = NGAP_Criticality_ignore; + pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_UplinkNASTransport; + out = &pdu.choice.initiatingMessage->value.choice.UplinkNASTransport; + /* mandatory */ + ie = (NGAP_UplinkNASTransport_IEs_t *)calloc(1, sizeof(NGAP_UplinkNASTransport_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkNASTransport_IEs__value_PR_AMF_UE_NGAP_ID; + //ie->value.choice.AMF_UE_NGAP_ID = ue_context_p->amf_ue_ngap_id; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_UplinkNASTransport_IEs_t *)calloc(1, sizeof(NGAP_UplinkNASTransport_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkNASTransport_IEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = ue_context_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_UplinkNASTransport_IEs_t *)calloc(1, sizeof(NGAP_UplinkNASTransport_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkNASTransport_IEs__value_PR_NAS_PDU; + ie->value.choice.NAS_PDU.buf = ngap_uplink_nas_p->nas_pdu.buffer; + ie->value.choice.NAS_PDU.size = ngap_uplink_nas_p->nas_pdu.length; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_UplinkNASTransport_IEs_t *)calloc(1, sizeof(NGAP_UplinkNASTransport_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_UserLocationInformation; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_UplinkNASTransport_IEs__value_PR_UserLocationInformation; + + ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR; + ie->value.choice.UserLocationInformation.choice.userLocationInformationNR = CALLOC(1,sizeof(struct NGAP_UserLocationInformationNR)); + userinfo_nr_p = ie->value.choice.UserLocationInformation.choice.userLocationInformationNR; + + /* Set nRCellIdentity. default userLocationInformationNR */ + MACRO_GNB_ID_TO_CELL_IDENTITY(ngap_gNB_instance_p->gNB_id, + 0, // Cell ID + &userinfo_nr_p->nR_CGI.nRCellIdentity); + MCC_MNC_TO_TBCD(ngap_gNB_instance_p->mcc[ue_context_p->selected_plmn_identity], + ngap_gNB_instance_p->mnc[ue_context_p->selected_plmn_identity], + ngap_gNB_instance_p->mnc_digit_length[ue_context_p->selected_plmn_identity], + &userinfo_nr_p->nR_CGI.pLMNIdentity); + + /* Set TAI */ + INT24_TO_OCTET_STRING(ngap_gNB_instance_p->tac, &userinfo_nr_p->tAI.tAC); + MCC_MNC_TO_PLMNID(ngap_gNB_instance_p->mcc[ue_context_p->selected_plmn_identity], + ngap_gNB_instance_p->mnc[ue_context_p->selected_plmn_identity], + ngap_gNB_instance_p->mnc_digit_length[ue_context_p->selected_plmn_identity], + &userinfo_nr_p->tAI.pLMNIdentity); + + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode uplink NAS transport\n"); + /* Encode procedure has failed... */ + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)NULL, + 0, + MSC_AS_TIME_FMT" uplinkNASTransport initiatingMessage gNB_ue_ngap_id %u amf_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + + return 0; +} + + +//------------------------------------------------------------------------------ +int ngap_gNB_nas_non_delivery_ind(instance_t instance, + ngap_nas_non_delivery_ind_t *ngap_nas_non_delivery_ind) +//------------------------------------------------------------------------------ +{ + struct ngap_gNB_ue_context_s *ue_context_p; + ngap_gNB_instance_t *ngap_gNB_instance_p; + NGAP_NGAP_PDU_t pdu; + NGAP_NASNonDeliveryIndication_t *out; + NGAP_NASNonDeliveryIndication_IEs_t *ie; + uint8_t *buffer; + uint32_t length; + DevAssert(ngap_nas_non_delivery_ind != NULL); + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, ngap_nas_non_delivery_ind->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: %08x\n", + ngap_nas_non_delivery_ind->gNB_ue_ngap_id); + MSC_LOG_EVENT( + MSC_NGAP_GNB, + MSC_AS_TIME_FMT" Sent of NAS_NON_DELIVERY_IND to AMF failed, no context for gNB_ue_ngap_id %08x", + ngap_nas_non_delivery_ind->gNB_ue_ngap_id); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = (NGAP_InitiatingMessage_t *)calloc(1,sizeof(NGAP_InitiatingMessage_t)); + pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_NASNonDeliveryIndication; + pdu.choice.initiatingMessage->criticality = NGAP_Criticality_ignore; + pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_NASNonDeliveryIndication; + out = &pdu.choice.initiatingMessage->value.choice.NASNonDeliveryIndication; + /* mandatory */ + ie = (NGAP_NASNonDeliveryIndication_IEs_t *)calloc(1, sizeof(NGAP_NASNonDeliveryIndication_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_NASNonDeliveryIndication_IEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_NASNonDeliveryIndication_IEs_t *)calloc(1, sizeof(NGAP_NASNonDeliveryIndication_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_NASNonDeliveryIndication_IEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = ue_context_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_NASNonDeliveryIndication_IEs_t *)calloc(1, sizeof(NGAP_NASNonDeliveryIndication_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_NASNonDeliveryIndication_IEs__value_PR_NAS_PDU; + ie->value.choice.NAS_PDU.buf = ngap_nas_non_delivery_ind->nas_pdu.buffer; + ie->value.choice.NAS_PDU.size = ngap_nas_non_delivery_ind->nas_pdu.length; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_NASNonDeliveryIndication_IEs_t *)calloc(1, sizeof(NGAP_NASNonDeliveryIndication_IEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_Cause; + ie->criticality = NGAP_Criticality_ignore; + /* Send a dummy cause */ + ie->value.present = NGAP_NASNonDeliveryIndication_IEs__value_PR_Cause; + ie->value.choice.Cause.present = NGAP_Cause_PR_radioNetwork; + ie->value.choice.Cause.choice.radioNetwork = NGAP_CauseRadioNetwork_radio_connection_with_ue_lost; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode NAS NON delivery indication\n"); + /* Encode procedure has failed... */ + MSC_LOG_EVENT( + MSC_NGAP_GNB, + MSC_AS_TIME_FMT" Sent of NAS_NON_DELIVERY_IND to AMF failed (encoding)"); + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" NASNonDeliveryIndication initiatingMessage gNB_ue_ngap_id %u amf_ue_ngap_id %lu", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + + return 0; +} + +//------------------------------------------------------------------------------ +int ngap_gNB_initial_ctxt_resp( + instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p) +//------------------------------------------------------------------------------ +{ + + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu; + NGAP_InitialContextSetupResponse_t *out; + NGAP_InitialContextSetupResponseIEs_t *ie; + uint8_t *buffer = NULL; + uint8_t pdusessionTransfer_buffer[1000]; + uint32_t length; + int i; + asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + + + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(initial_ctxt_resp_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, + initial_ctxt_resp_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", + initial_ctxt_resp_p->gNB_ue_ngap_id); + return -1; + } + + /* Uplink NAS transport can occur either during an ngap connected state + * or during initial attach (for example: NAS authentication). + */ + if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || + ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { + NGAP_WARN("You are attempting to send NAS data over non-connected " + "gNB ue ngap id: %08x, current state: %d\n", + initial_ctxt_resp_p->gNB_ue_ngap_id, ue_context_p->ue_state); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = (NGAP_SuccessfulOutcome_t *)calloc(1,sizeof(struct NGAP_SuccessfulOutcome)); + pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_InitialContextSetup; + pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject; + pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_InitialContextSetupResponse; + out = &pdu.choice.successfulOutcome->value.choice.InitialContextSetupResponse; + /* mandatory */ + ie = (NGAP_InitialContextSetupResponseIEs_t *)calloc(1, sizeof(NGAP_InitialContextSetupResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_InitialContextSetupResponseIEs__value_PR_AMF_UE_NGAP_ID; + //ie->value.choice.AMF_UE_NGAP_ID = ue_context_p->amf_ue_ngap_id; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_InitialContextSetupResponseIEs_t *)calloc(1, sizeof(NGAP_InitialContextSetupResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_InitialContextSetupResponseIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = initial_ctxt_resp_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (initial_ctxt_resp_p->nb_of_pdusessions){ + ie = (NGAP_InitialContextSetupResponseIEs_t *)calloc(1, sizeof(NGAP_InitialContextSetupResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_InitialContextSetupResponseIEs__value_PR_PDUSessionResourceSetupListCxtRes; + for (i = 0; i < initial_ctxt_resp_p->nb_of_pdusessions; i++) { + NGAP_PDUSessionResourceSetupItemCxtRes_t *item; + NGAP_PDUSessionResourceSetupResponseTransfer_t *pdusessionTransfer_p = NULL; + + /* mandatory */ + item = (NGAP_PDUSessionResourceSetupItemCxtRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupItemCxtRes_t)); + + /* pDUSessionID */ + item->pDUSessionID = initial_ctxt_resp_p->pdusessions[i].pdusession_id; + + /* dLQosFlowPerTNLInformation */ + pdusessionTransfer_p = (NGAP_PDUSessionResourceSetupResponseTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceSetupResponseTransfer_t)); + + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; + + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel = (NGAP_GTPTunnel_t *)calloc(1, sizeof(NGAP_GTPTunnel_t)); + GTP_TEID_TO_ASN1(initial_ctxt_resp_p->pdusessions[i].gtp_teid, &pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID); + + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf = malloc(initial_ctxt_resp_p->pdusessions[i].gNB_addr.length); + + memcpy(pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf, + initial_ctxt_resp_p->pdusessions[i].gNB_addr.buffer, + initial_ctxt_resp_p->pdusessions[i].gNB_addr.length); + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.size = initial_ctxt_resp_p->pdusessions[i].gNB_addr.length; + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.bits_unused = 0; + + NGAP_DEBUG("initial_ctxt_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld \n", + item->pDUSessionID, + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[0], + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[1], + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[2], + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[3], + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.size); + + /* associatedQosFlowList. number of 1? */ + for(int j=0; j < initial_ctxt_resp_p->pdusessions[i].nb_of_qos_flow; j++) { + NGAP_AssociatedQosFlowItem_t *ass_qos_item_p; + ass_qos_item_p = (NGAP_AssociatedQosFlowItem_t *)calloc(1, sizeof(NGAP_AssociatedQosFlowItem_t)); + + /* qosFlowIdentifier */ + ass_qos_item_p->qosFlowIdentifier = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qfi; + + /* qosFlowMappingIndication */ + //if(initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) { + // ass_qos_item_p->qosFlowMappingIndication = malloc(sizeof(*ass_qos_item_p->qosFlowMappingIndication)); + // *ass_qos_item_p->qosFlowMappingIndication = initial_ctxt_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind; + // } + ASN_SEQUENCE_ADD(&pdusessionTransfer_p->dLQosFlowPerTNLInformation.associatedQosFlowList.list, ass_qos_item_p); + } + + //res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); + //item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer; + //item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded; + + if (asn1_xer_print) { + xer_fprint(stdout, &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); + } + + memset(pdusessionTransfer_buffer, 0, 1000); + asn_enc_rval_t enc_rval = aper_encode_to_buffer(&asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, + NULL, + pdusessionTransfer_p, + pdusessionTransfer_buffer,1000); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + item->pDUSessionResourceSetupResponseTransfer.buf = pdusessionTransfer_buffer; + item->pDUSessionResourceSetupResponseTransfer.size = enc_rval.encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); + + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceSetupListCxtRes.list, item); + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + /* optional */ + if (initial_ctxt_resp_p->nb_of_pdusessions_failed) { + ie = (NGAP_InitialContextSetupResponseIEs_t *)calloc(1, sizeof(NGAP_InitialContextSetupResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListCxtRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_InitialContextSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListCxtRes; + + for (i = 0; i < initial_ctxt_resp_p->nb_of_pdusessions_failed; i++) { + NGAP_PDUSessionResourceFailedToSetupItemCxtRes_t *item= calloc(1, sizeof *item); + NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *pdusessionUnTransfer_p = calloc(1, sizeof *pdusessionUnTransfer_p); + + /* pDUSessionID */ + item->pDUSessionID = initial_ctxt_resp_p->pdusessions_failed[i].pdusession_id; + + /* cause */ + + pdusessionUnTransfer_p->cause.present = initial_ctxt_resp_p->pdusessions_failed[i].cause; + switch(pdusessionUnTransfer_p->cause.present) { + case NGAP_Cause_PR_radioNetwork: + pdusessionUnTransfer_p->cause.choice.radioNetwork = initial_ctxt_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_transport: + pdusessionUnTransfer_p->cause.choice.transport = initial_ctxt_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_nas: + pdusessionUnTransfer_p->cause.choice.nas = initial_ctxt_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_protocol: + pdusessionUnTransfer_p->cause.choice.protocol = initial_ctxt_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_misc: + pdusessionUnTransfer_p->cause.choice.misc = initial_ctxt_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_NOTHING: + default: + break; + } + + NGAP_DEBUG("initial context setup response: failed pdusession ID %ld\n", item->pDUSessionID); + + memset(&res, 0, sizeof(res)); + res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, pdusessionUnTransfer_p); + item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer; + item->pDUSessionResourceSetupUnsuccessfulTransfer.size = res.result.encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, pdusessionUnTransfer_p); + + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceFailedToSetupListCxtRes.list, item); + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (0) { + ie = (NGAP_InitialContextSetupResponseIEs_t *)calloc(1, sizeof(NGAP_InitialContextSetupResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_InitialContextSetupResponseIEs__value_PR_CriticalityDiagnostics; + // ie->value.choice.CriticalityDiagnostics =; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + if (asn1_xer_print) { + xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, &pdu); + } + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode InitialContextSetupResponse\n"); + /* Encode procedure has failed... */ + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" InitialContextSetup successfulOutcome gNB_ue_ngap_id %u amf_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + initial_ctxt_resp_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + /* UE associated signalling -> use the allocated stream */ + LOG_I(NR_RRC,"Send message to sctp: NGAP_InitialContextSetupResponse\n"); + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + + return 0; +} + +//------------------------------------------------------------------------------ +int ngap_gNB_ue_capabilities(instance_t instance, + ngap_ue_cap_info_ind_t *ue_cap_info_ind_p) +//------------------------------------------------------------------------------ +{ + ngap_gNB_instance_t *ngap_gNB_instance_p; + struct ngap_gNB_ue_context_s *ue_context_p; + NGAP_NGAP_PDU_t pdu; + NGAP_UERadioCapabilityInfoIndication_t *out; + NGAP_UERadioCapabilityInfoIndicationIEs_t *ie; + uint8_t *buffer; + uint32_t length; + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(ue_cap_info_ind_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, + ue_cap_info_ind_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: %u\n", + ue_cap_info_ind_p->gNB_ue_ngap_id); + return -1; + } + + /* UE radio capabilities message can occur either during an ngap connected state + * or during initial attach (for example: NAS authentication). + */ + if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || + ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { + NGAP_WARN("You are attempting to send NAS data over non-connected " + "gNB ue ngap id: %u, current state: %d\n", + ue_cap_info_ind_p->gNB_ue_ngap_id, ue_context_p->ue_state); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = (NGAP_InitiatingMessage_t *)calloc(1,sizeof(NGAP_InitiatingMessage_t)); + pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_UERadioCapabilityInfoIndication; + pdu.choice.initiatingMessage->criticality = NGAP_Criticality_ignore; + pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_UERadioCapabilityInfoIndication; + out = &pdu.choice.initiatingMessage->value.choice.UERadioCapabilityInfoIndication; + /* mandatory */ + ie = (NGAP_UERadioCapabilityInfoIndicationIEs_t *)calloc(1, sizeof(NGAP_UERadioCapabilityInfoIndicationIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UERadioCapabilityInfoIndicationIEs__value_PR_AMF_UE_NGAP_ID; + //ie->value.choice.AMF_UE_NGAP_ID = ue_context_p->amf_ue_ngap_id; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_UERadioCapabilityInfoIndicationIEs_t *)calloc(1, sizeof(NGAP_UERadioCapabilityInfoIndicationIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UERadioCapabilityInfoIndicationIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = ue_cap_info_ind_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_UERadioCapabilityInfoIndicationIEs_t *)calloc(1, sizeof(NGAP_UERadioCapabilityInfoIndicationIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_UERadioCapability; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_UERadioCapabilityInfoIndicationIEs__value_PR_UERadioCapability; + ie->value.choice.UERadioCapability.buf = ue_cap_info_ind_p->ue_radio_cap.buffer; + ie->value.choice.UERadioCapability.size = ue_cap_info_ind_p->ue_radio_cap.length; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* optional */ + //NGAP_UERadioCapabilityForPaging TBD + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + /* Encode procedure has failed... */ + NGAP_ERROR("Failed to encode UE radio capabilities indication\n"); + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" UECapabilityInfoIndication initiatingMessage gNB_ue_ngap_id %u amf_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + ue_cap_info_ind_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + return 0; +} + +//------------------------------------------------------------------------------ +int ngap_gNB_pdusession_setup_resp(instance_t instance, + ngap_pdusession_setup_resp_t *pdusession_setup_resp_p) +//------------------------------------------------------------------------------ +{ + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu; + NGAP_PDUSessionResourceSetupResponse_t *out; + NGAP_PDUSessionResourceSetupResponseIEs_t *ie; + uint8_t *buffer = NULL; + uint32_t length; + + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(pdusession_setup_resp_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, + pdusession_setup_resp_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", + pdusession_setup_resp_p->gNB_ue_ngap_id); + return -1; + } + + /* Uplink NAS transport can occur either during an ngap connected state + * or during initial attach (for example: NAS authentication). + */ + if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || + ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { + NGAP_WARN("You are attempting to send NAS data over non-connected " + "gNB ue ngap id: %08x, current state: %d\n", + pdusession_setup_resp_p->gNB_ue_ngap_id, ue_context_p->ue_state); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = calloc(1,sizeof *pdu.choice.successfulOutcome); + pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceSetup; + pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject; + pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceSetupResponse; + out = &pdu.choice.successfulOutcome->value.choice.PDUSessionResourceSetupResponse; + /* mandatory */ + ie = calloc(1, sizeof *ie); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = calloc(1, sizeof *ie ); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = pdusession_setup_resp_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (pdusession_setup_resp_p->nb_of_pdusessions > 0) { + ie = calloc(1, sizeof *ie ); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSURes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceSetupListSURes; + + for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions; i++) { + NGAP_PDUSessionResourceSetupItemSURes_t *item=calloc(1, sizeof *item ); + NGAP_PDUSessionResourceSetupResponseTransfer_t *pdusessionTransfer_p = calloc(1, sizeof *pdusessionTransfer_p ); + + /* pDUSessionID */ + item->pDUSessionID = pdusession_setup_resp_p->pdusessions[i].pdusession_id; + + /* dLQosFlowPerTNLInformation */ + + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.present = NGAP_UPTransportLayerInformation_PR_gTPTunnel; + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel = + calloc(1, sizeof(struct NGAP_GTPTunnel)); + + GTP_TEID_TO_ASN1(pdusession_setup_resp_p->pdusessions[i].gtp_teid, &pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID); + + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf = malloc(pdusession_setup_resp_p->pdusessions[i].gNB_addr.length); + + memcpy(pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf, + pdusession_setup_resp_p->pdusessions[i].gNB_addr.buffer, + pdusession_setup_resp_p->pdusessions[i].gNB_addr.length); + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.size = pdusession_setup_resp_p->pdusessions[i].gNB_addr.length; + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.bits_unused = 0; + + NGAP_DEBUG("pdusession_setup_resp_p: pdusession ID %ld, gnb_addr %d.%d.%d.%d, SIZE %ld \n", + item->pDUSessionID, + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[0], + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[1], + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[2], + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.buf[3], + pdusessionTransfer_p->dLQosFlowPerTNLInformation.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress.size); + + /* associatedQosFlowList. number of 1? */ + for(int j=0; j < pdusession_setup_resp_p->pdusessions[i].nb_of_qos_flow; j++) { + NGAP_AssociatedQosFlowItem_t *ass_qos_item_p = calloc(1, sizeof *ass_qos_item_p); + + /* qosFlowIdentifier */ + ass_qos_item_p->qosFlowIdentifier = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qfi; + + /* qosFlowMappingIndication */ + //if(pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind != QOSFLOW_MAPPING_INDICATION_NON) { + // ass_qos_item_p->qosFlowMappingIndication = malloc(sizeof(*ass_qos_item_p->qosFlowMappingIndication)); + // *ass_qos_item_p->qosFlowMappingIndication = pdusession_setup_resp_p->pdusessions[i].associated_qos_flows[j].qos_flow_mapping_ind; + //} + ASN_SEQUENCE_ADD(&pdusessionTransfer_p->dLQosFlowPerTNLInformation.associatedQosFlowList.list, ass_qos_item_p); + } + + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); + AssertFatal (res.buffer, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); + item->pDUSessionResourceSetupResponseTransfer.buf = res.buffer; + item->pDUSessionResourceSetupResponseTransfer.size = res.result.encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, pdusessionTransfer_p); + + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceSetupListSURes.list, item); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (pdusession_setup_resp_p->nb_of_pdusessions_failed > 0) { + ie = calloc(1, sizeof *ie); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListSURes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes; + + for (int i = 0; i < pdusession_setup_resp_p->nb_of_pdusessions_failed; i++) { + LOG_W(NGAP,"add a failed session\n"); + NGAP_PDUSessionResourceFailedToSetupItemSURes_t *item=calloc(1, sizeof *item); + NGAP_PDUSessionResourceSetupUnsuccessfulTransfer_t *pdusessionUnTransfer_p = calloc(1, sizeof *pdusessionUnTransfer_p); + + /* pDUSessionID */ + item->pDUSessionID = pdusession_setup_resp_p->pdusessions_failed[i].pdusession_id; + + /* cause */ + pdusessionUnTransfer_p->cause.present = pdusession_setup_resp_p->pdusessions_failed[i].cause; + switch(pdusessionUnTransfer_p->cause.present) { + case NGAP_Cause_PR_radioNetwork: + pdusessionUnTransfer_p->cause.choice.radioNetwork = pdusession_setup_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_transport: + pdusessionUnTransfer_p->cause.choice.transport = pdusession_setup_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_nas: + pdusessionUnTransfer_p->cause.choice.nas = pdusession_setup_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_protocol: + pdusessionUnTransfer_p->cause.choice.protocol = pdusession_setup_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_misc: + pdusessionUnTransfer_p->cause.choice.misc = pdusession_setup_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_NOTHING: + default: + break; + } + + NGAP_DEBUG("pdusession setup response: failed pdusession ID %ld\n", item->pDUSessionID); + + asn_encode_to_new_buffer_result_t res = + asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, + &asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, pdusessionUnTransfer_p); + item->pDUSessionResourceSetupUnsuccessfulTransfer.buf = res.buffer; + item->pDUSessionResourceSetupUnsuccessfulTransfer.size = res.result.encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceSetupUnsuccessfulTransfer, pdusessionUnTransfer_p); + + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceFailedToSetupListSURes.list, item); + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (0) { + ie = calloc(1, sizeof *ie); + ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceSetupResponseIEs__value_PR_CriticalityDiagnostics; + // ie->value.choice.CriticalityDiagnostics = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode uplink transport\n"); + /* Encode procedure has failed... */ + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" PduSession Setup successfulOutcome gNB_ue_ngap_id %u amf_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + pdusession_setup_resp_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + return 0; +} + +//------------------------------------------------------------------------------ +int ngap_gNB_pdusession_modify_resp(instance_t instance, + ngap_pdusession_modify_resp_t *pdusession_modify_resp_p) +//------------------------------------------------------------------------------ +{ + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu; + NGAP_PDUSessionResourceModifyResponse_t *out; + NGAP_PDUSessionResourceModifyResponseIEs_t *ie; + uint8_t *buffer = NULL; + uint32_t length; + int i; + asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; + + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(pdusession_modify_resp_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, + pdusession_modify_resp_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", + pdusession_modify_resp_p->gNB_ue_ngap_id); + return -1; + } + + /* Uplink NAS transport can occur either during an ngap connected state + * or during initial attach (for example: NAS authentication). + */ + if (!(ue_context_p->ue_state == NGAP_UE_CONNECTED || + ue_context_p->ue_state == NGAP_UE_WAITING_CSR)) { + NGAP_WARN("You are attempting to send NAS data over non-connected " + "gNB ue ngap id: %08x, current state: %d\n", + pdusession_modify_resp_p->gNB_ue_ngap_id, ue_context_p->ue_state); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = (NGAP_SuccessfulOutcome_t *)calloc(1,sizeof(struct NGAP_SuccessfulOutcome)); + pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceModify; + pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject; + pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceModifyResponse; + out = &pdu.choice.successfulOutcome->value.choice.PDUSessionResourceModifyResponse; + /* mandatory */ + ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = pdusession_modify_resp_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (pdusession_modify_resp_p->nb_of_pdusessions > 0) { + ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceModifyListModRes; + + for (i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions; i++) { + NGAP_PDUSessionResourceModifyItemModRes_t *item; + + item = (NGAP_PDUSessionResourceModifyItemModRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyItemModRes_t)); + item->pDUSessionID = pdusession_modify_resp_p->pdusessions[i].pdusession_id; + + NGAP_DEBUG("pdusession_modify_resp: modified pdusession ID %ld\n", item->pDUSessionID); + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceModifyListModRes.list, item); + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (pdusession_modify_resp_p->nb_of_pdusessions_failed > 0) { + ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToModifyListModRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceFailedToModifyListModRes; + + for (i = 0; i < pdusession_modify_resp_p->nb_of_pdusessions_failed; i++) { + NGAP_PDUSessionResourceFailedToModifyItemModRes_t *item; + NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t *pdusessionTransfer_p = NULL; + + item = (NGAP_PDUSessionResourceFailedToModifyItemModRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceFailedToModifyItemModRes_t)); + item->pDUSessionID = pdusession_modify_resp_p->pdusessions_failed[i].pdusession_id; + + pdusessionTransfer_p = (NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyUnsuccessfulTransfer_t)); + pdusessionTransfer_p->cause.present = pdusession_modify_resp_p->pdusessions_failed[i].cause; + + switch(pdusessionTransfer_p->cause.present) { + case NGAP_Cause_PR_radioNetwork: + pdusessionTransfer_p->cause.choice.radioNetwork = pdusession_modify_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_transport: + pdusessionTransfer_p->cause.choice.transport = pdusession_modify_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_nas: + pdusessionTransfer_p->cause.choice.nas = pdusession_modify_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_protocol: + pdusessionTransfer_p->cause.choice.protocol = pdusession_modify_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_misc: + pdusessionTransfer_p->cause.choice.misc = pdusession_modify_resp_p->pdusessions_failed[i].cause_value; + break; + + case NGAP_Cause_PR_NOTHING: + default: + break; + } + + memset(&res, 0, sizeof(res)); + res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, pdusessionTransfer_p); + item->pDUSessionResourceModifyUnsuccessfulTransfer.buf = res.buffer; + item->pDUSessionResourceModifyUnsuccessfulTransfer.size = res.result.encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_PDUSessionResourceModifyUnsuccessfulTransfer, pdusessionTransfer_p); + + + NGAP_DEBUG("pdusession_modify_resp: failed pdusession ID %ld\n", item->pDUSessionID); + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceFailedToModifyListModRes.list, item); + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (0) { + ie = (NGAP_PDUSessionResourceModifyResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_CriticalityDiagnostics; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_CriticalityDiagnostics; + // ie->value.choice.CriticalityDiagnostics = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + fprintf(stderr, "start encode\n"); + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode uplink transport\n"); + /* Encode procedure has failed... */ + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" E_RAN Modify successful Outcome gNB_ue_ngap_id %u amf_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + pdusession_modify_resp_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + + return 0; +} +//------------------------------------------------------------------------------ +int ngap_gNB_pdusession_release_resp(instance_t instance, + ngap_pdusession_release_resp_t *pdusession_release_resp_p) +//------------------------------------------------------------------------------ +{ + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + NGAP_NGAP_PDU_t pdu; + NGAP_PDUSessionResourceReleaseResponse_t *out; + NGAP_PDUSessionResourceReleaseResponseIEs_t *ie; + uint8_t *buffer = NULL; + uint32_t length; + int i; + /* Retrieve the NGAP gNB instance associated with Mod_id */ + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(pdusession_release_resp_p != NULL); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p, + pdusession_release_resp_p->gNB_ue_ngap_id)) == NULL) { + /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */ + NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: 0x%08x\n", + pdusession_release_resp_p->gNB_ue_ngap_id); + return -1; + } + + /* Prepare the NGAP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = (NGAP_SuccessfulOutcome_t *)calloc(1,sizeof(struct NGAP_SuccessfulOutcome)); + pdu.choice.successfulOutcome->procedureCode = NGAP_ProcedureCode_id_PDUSessionResourceRelease; + pdu.choice.successfulOutcome->criticality = NGAP_Criticality_reject; + pdu.choice.successfulOutcome->value.present = NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceReleaseResponse; + out = &pdu.choice.successfulOutcome->value.choice.PDUSessionResourceReleaseResponse; + /* mandatory */ + ie = (NGAP_PDUSessionResourceReleaseResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceReleaseResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, ue_context_p->amf_ue_ngap_id); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (NGAP_PDUSessionResourceReleaseResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceReleaseResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (pdusession_release_resp_p->nb_of_pdusessions_released > 0) { + ie = (NGAP_PDUSessionResourceReleaseResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceReleaseResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes; + + for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) { + NGAP_PDUSessionResourceReleasedItemRelRes_t *item; + item = (NGAP_PDUSessionResourceReleasedItemRelRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceReleasedItemRelRes_t)); + + item->pDUSessionID = pdusession_release_resp_p->pdusession_release[i].pdusession_id; + if(pdusession_release_resp_p->pdusession_release[i].transfer_length > 0){ + item->pDUSessionResourceReleaseResponseTransfer.size = pdusession_release_resp_p->pdusession_release[i].transfer_length; + item->pDUSessionResourceReleaseResponseTransfer.buf = malloc(sizeof(uint8_t) * pdusession_release_resp_p->pdusession_release[i].transfer_length); + memcpy(item->pDUSessionResourceReleaseResponseTransfer.buf, + pdusession_release_resp_p->pdusession_release[i].transfer_buffer, + pdusession_release_resp_p->pdusession_release[i].transfer_length); + }else { + item->pDUSessionResourceReleaseResponseTransfer.size = 0; + item->pDUSessionResourceReleaseResponseTransfer.buf = NULL; + NGAP_DEBUG("pdusession_release_resp: transfer_buffer is NULL!\n"); +#ifdef ITTI_SIM + //For testing only + item->pDUSessionResourceReleaseResponseTransfer.buf = malloc(sizeof(uint8_t) * 1); + item->pDUSessionResourceReleaseResponseTransfer.size = 1; + uint8_t temp = 0; + memcpy(item->pDUSessionResourceReleaseResponseTransfer.buf, + &temp, + item->pDUSessionResourceReleaseResponseTransfer.size); +#endif + } + NGAP_DEBUG("pdusession_release_resp: pdusession ID %ld\n", item->pDUSessionID); + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceReleasedListRelRes.list, item); + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + NGAP_ERROR("Failed to encode release response\n"); + /* Encode procedure has failed... */ + return -1; + } + + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" E_RAN Release successfulOutcome gNB_ue_ngap_id %u amf_ue_ngap_id %lu", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + pdusession_release_resp_p->gNB_ue_ngap_id, + (uint64_t)ue_context_p->amf_ue_ngap_id); + /* UE associated signalling -> use the allocated stream */ + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); + NGAP_INFO("pdusession_release_response sended gNB_UE_NGAP_ID %u amf_ue_ngap_id %lu nb_of_pdusessions_released %d nb_of_pdusessions_failed %d\n", + pdusession_release_resp_p->gNB_ue_ngap_id, (uint64_t)ue_context_p->amf_ue_ngap_id,pdusession_release_resp_p->nb_of_pdusessions_released,pdusession_release_resp_p->nb_of_pdusessions_failed); + + return 0; +} + +int ngap_gNB_path_switch_req(instance_t instance, + ngap_path_switch_req_t *path_switch_req_p) +//------------------------------------------------------------------------------ +{ + //TODO + + return 0; +} + +int ngap_gNB_generate_PDUSESSION_Modification_Indication( + instance_t instance, + ngap_pdusession_modification_ind_t *pdusession_modification_ind) +//----------------------------------------------------------------------------- +{ + //TODO + return 0; +} + + diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.h b/openair3/NGAP/ngap_gNB_nas_procedures.h new file mode 100644 index 0000000000..e7552cd47e --- /dev/null +++ b/openair3/NGAP/ngap_gNB_nas_procedures.h @@ -0,0 +1,68 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_nas_procedures.h + * \brief NGAP gNb NAS procedure handler + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + * \version 1.0 + * @ingroup _ngap + */ + +#ifndef NGAP_GNB_NAS_PROCEDURES_H_ +#define NGAP_GNB_NAS_PROCEDURES_H_ + +int ngap_gNB_handle_nas_downlink( + uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_p); + +int ngap_gNB_nas_non_delivery_ind(instance_t instance, + ngap_nas_non_delivery_ind_t *ngap_nas_non_delivery_ind); + +int ngap_gNB_handle_nas_first_req( + instance_t instance, ngap_nas_first_req_t *ngap_nas_first_req_p); + +int ngap_gNB_initial_ctxt_resp( + instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p); + +int ngap_gNB_ue_capabilities(instance_t instance, + ngap_ue_cap_info_ind_t *ue_cap_info_ind_p); + +int ngap_gNB_pdusession_setup_resp(instance_t instance, + ngap_pdusession_setup_resp_t *pdusession_setup_resp_p); + +int ngap_gNB_pdusession_modify_resp(instance_t instance, + ngap_pdusession_modify_resp_t *pdusession_modify_resp_p); + +int ngap_gNB_pdusession_release_resp(instance_t instance, + ngap_pdusession_release_resp_t *pdusession_release_resp_p); + +int ngap_gNB_path_switch_req(instance_t instance, + ngap_path_switch_req_t *path_switch_req_p); + +int ngap_gNB_generate_PDUSESSION_Modification_Indication( + instance_t instance, ngap_pdusession_modification_ind_t *pdusession_modification_ind); + +#endif /* NGAP_GNB_NAS_PROCEDURES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_nnsf.c b/openair3/NGAP/ngap_gNB_nnsf.c new file mode 100644 index 0000000000..e9ec66b1b4 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_nnsf.c @@ -0,0 +1,410 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_nnsf.c + * \brief ngap NAS node selection functions + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#include +#include + +#include "intertask_interface.h" + +#include "ngap_common.h" + +#include "ngap_gNB_defs.h" +#include "ngap_gNB_nnsf.h" + +struct ngap_gNB_amf_data_s * +ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p, + ngap_rrc_establishment_cause_t cause) +{ + struct ngap_gNB_amf_data_s *amf_data_p = NULL; + struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL; + uint8_t current_capacity = 0; + + RB_FOREACH(amf_data_p, ngap_amf_map, &instance_p->ngap_amf_head) { + if (amf_data_p->state != NGAP_GNB_STATE_CONNECTED) { + /* The association between AMF and gNB is not ready for the moment, + * go to the next known AMF. + */ + if (amf_data_p->state == NGAP_GNB_OVERLOAD) { + /* AMF is overloaded. We have to check the RRC establishment + * cause and take decision to the select this AMF depending on + * the overload state. + */ + if ((cause == NGAP_RRC_CAUSE_MO_DATA) + && (amf_data_p->overload_state == NGAP_OVERLOAD_REJECT_MO_DATA)) { + continue; + } + + if ((amf_data_p->overload_state == NGAP_OVERLOAD_REJECT_ALL_SIGNALLING) + && ((cause == NGAP_RRC_CAUSE_MO_SIGNALLING) || (cause == NGAP_RRC_CAUSE_MO_DATA))) { + continue; + } + + if ((amf_data_p->overload_state == NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT) + && ((cause == NGAP_RRC_CAUSE_MO_SIGNALLING) || (cause == NGAP_RRC_CAUSE_MO_DATA) + || (cause == NGAP_RRC_CAUSE_HIGH_PRIO_ACCESS))) { + continue; + } + + /* At this point, the RRC establishment can be handled by the AMF + * even if it is in overload state. + */ + } else { + /* The AMF is not overloaded, association is simply not ready. */ + continue; + } + } + + if (current_capacity < amf_data_p->relative_amf_capacity) { + /* We find a better AMF, keep a reference to it */ + current_capacity = amf_data_p->relative_amf_capacity; + amf_highest_capacity_p = amf_data_p; + } + } + + return amf_highest_capacity_p; +} + +struct ngap_gNB_amf_data_s * +ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p, + ngap_rrc_establishment_cause_t cause, + int selected_plmn_identity) +{ + struct ngap_gNB_amf_data_s *amf_data_p = NULL; + struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL; + uint8_t current_capacity = 0; + + RB_FOREACH(amf_data_p, ngap_amf_map, &instance_p->ngap_amf_head) { + struct served_guami_s *guami_p = NULL; + struct plmn_identity_s *served_plmn_p = NULL; + if (amf_data_p->state != NGAP_GNB_STATE_CONNECTED) { + /* The association between AMF and gNB is not ready for the moment, + * go to the next known AMF. + */ + if (amf_data_p->state == NGAP_GNB_OVERLOAD) { + /* AMF is overloaded. We have to check the RRC establishment + * cause and take decision to the select this AMF depending on + * the overload state. + */ + if ((cause == NGAP_RRC_CAUSE_MO_DATA) + && (amf_data_p->overload_state == NGAP_OVERLOAD_REJECT_MO_DATA)) { + continue; + } + + if ((amf_data_p->overload_state == NGAP_OVERLOAD_REJECT_ALL_SIGNALLING) + && ((cause == NGAP_RRC_CAUSE_MO_SIGNALLING) || (cause == NGAP_RRC_CAUSE_MO_DATA))) { + continue; + } + + if ((amf_data_p->overload_state == NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT) + && ((cause == NGAP_RRC_CAUSE_MO_SIGNALLING) || (cause == NGAP_RRC_CAUSE_MO_DATA) + || (cause == NGAP_RRC_CAUSE_HIGH_PRIO_ACCESS))) { + continue; + } + + /* At this point, the RRC establishment can be handled by the AMF + * even if it is in overload state. + */ + } else { + /* The AMF is not overloaded, association is simply not ready. */ + continue; + } + } + + /* Looking for served GUAMI PLMN Identity selected matching the one provided by the UE */ + STAILQ_FOREACH(guami_p, &amf_data_p->served_guami, next) { + STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) { + if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) && + (served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) { + break; + } + } + /* if found, we can stop the outer loop, too */ + if (served_plmn_p) break; + } + /* if we didn't find such a served PLMN, go on with the next AMF */ + if (!served_plmn_p) continue; + + if (current_capacity < amf_data_p->relative_amf_capacity) { + /* We find a better AMF, keep a reference to it */ + current_capacity = amf_data_p->relative_amf_capacity; + amf_highest_capacity_p = amf_data_p; + } + } + + return amf_highest_capacity_p; +} + +struct ngap_gNB_amf_data_s * +ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p, + ngap_rrc_establishment_cause_t cause, + int selected_plmn_identity, + uint8_t amf_setid) +{ + struct ngap_gNB_amf_data_s *amf_data_p = NULL; + + RB_FOREACH(amf_data_p, ngap_amf_map, &instance_p->ngap_amf_head) { + struct served_guami_s *guami_p = NULL; + + if (amf_data_p->state != NGAP_GNB_STATE_CONNECTED) { + /* The association between AMF and gNB is not ready for the moment, + * go to the next known AMF. + */ + if (amf_data_p->state == NGAP_GNB_OVERLOAD) { + /* AMF is overloaded. We have to check the RRC establishment + * cause and take decision to the select this AMF depending on + * the overload state. + */ + if ((cause == NGAP_RRC_CAUSE_MO_DATA) + && (amf_data_p->overload_state == NGAP_OVERLOAD_REJECT_MO_DATA)) { + continue; + } + + if ((amf_data_p->overload_state == NGAP_OVERLOAD_REJECT_ALL_SIGNALLING) + && ((cause == NGAP_RRC_CAUSE_MO_SIGNALLING) || (cause == NGAP_RRC_CAUSE_MO_DATA))) { + continue; + } + + if ((amf_data_p->overload_state == NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT) + && ((cause == NGAP_RRC_CAUSE_MO_SIGNALLING) || (cause == NGAP_RRC_CAUSE_MO_DATA) + || (cause == NGAP_RRC_CAUSE_HIGH_PRIO_ACCESS))) { + continue; + } + + /* At this point, the RRC establishment can be handled by the AMF + * even if it is in overload state. + */ + } else { + /* The AMF is not overloaded, association is simply not ready. */ + continue; + } + } + + /* Looking for AMF code matching the one provided by NAS */ + STAILQ_FOREACH(guami_p, &amf_data_p->served_guami, next) { + struct amf_set_id_s *amf_setid_p = NULL; + struct plmn_identity_s *served_plmn_p = NULL; + + STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) { + if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) && + (served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) { + break; + } + } + STAILQ_FOREACH(amf_setid_p, &guami_p->amf_set_ids, next) { + if (amf_setid_p->amf_set_id == amf_setid) { + break; + } + } + + /* The AMF matches the parameters provided by the NAS layer -> + * the AMF is knwown and the association is ready. + * Return the reference to the AMF to use it for this UE. + */ + if (amf_setid_p && served_plmn_p) { + return amf_data_p; + } + } + } + + /* At this point no AMF matches the selected PLMN and AMF code. In this case, + * return NULL. That way the RRC layer should know about it and reject RRC + * connectivity. */ + return NULL; +} + +struct ngap_gNB_amf_data_s * +ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p, + ngap_rrc_establishment_cause_t cause, + ngap_guami_t guami) +{ + struct ngap_gNB_amf_data_s *amf_data_p = NULL; + + RB_FOREACH(amf_data_p, ngap_amf_map, &instance_p->ngap_amf_head) { + struct served_guami_s *guami_p = NULL; + + if (amf_data_p->state != NGAP_GNB_STATE_CONNECTED) { + /* The association between AMF and gNB is not ready for the moment, + * go to the next known AMF. + */ + if (amf_data_p->state == NGAP_GNB_OVERLOAD) { + /* AMF is overloaded. We have to check the RRC establishment + * cause and take decision to the select this AMF depending on + * the overload state. + */ + if ((cause == NGAP_RRC_CAUSE_MO_DATA) + && (amf_data_p->overload_state == NGAP_OVERLOAD_REJECT_MO_DATA)) { + continue; + } + + if ((amf_data_p->overload_state == NGAP_OVERLOAD_REJECT_ALL_SIGNALLING) + && ((cause == NGAP_RRC_CAUSE_MO_SIGNALLING) || (cause == NGAP_RRC_CAUSE_MO_DATA))) { + continue; + } + + if ((amf_data_p->overload_state == NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT) + && ((cause == NGAP_RRC_CAUSE_MO_SIGNALLING) || (cause == NGAP_RRC_CAUSE_MO_DATA) + || (cause == NGAP_RRC_CAUSE_HIGH_PRIO_ACCESS))) { + continue; + } + + /* At this point, the RRC establishment can be handled by the AMF + * even if it is in overload state. + */ + } else { + /* The AMF is not overloaded, association is simply not ready. */ + continue; + } + } + + /* Looking for AMF guami matching the one provided by NAS */ + STAILQ_FOREACH(guami_p, &amf_data_p->served_guami, next) { + struct served_region_id_s *region_id_p = NULL; + struct amf_set_id_s *amf_set_id_p = NULL; + struct amf_pointer_s *pointer_p = NULL; + struct plmn_identity_s *served_plmn_p = NULL; + + STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) { + if ((served_plmn_p->mcc == guami.mcc) && + (served_plmn_p->mnc == guami.mnc)) { + break; + } + } + + STAILQ_FOREACH(region_id_p, &guami_p->served_region_ids, next) { + if (region_id_p->amf_region_id == guami.amf_region_id) { + break; + } + } + STAILQ_FOREACH(amf_set_id_p, &guami_p->amf_set_ids, next) { + if (amf_set_id_p->amf_set_id == guami.amf_set_id) { + break; + } + } + STAILQ_FOREACH(pointer_p, &guami_p->amf_pointers, next) { + if (pointer_p->amf_pointer == guami.amf_pointer) { + break; + } + } + + /* The AMF matches the parameters provided by the NAS layer -> + * the AMF is knwown and the association is ready. + * Return the reference to the AMF to use it for this UE. + */ + if ((region_id_p != NULL) && + (amf_set_id_p != NULL) && + (pointer_p != NULL) && + (served_plmn_p != NULL)) { + return amf_data_p; + } + } + } + + /* At this point no AMF matches the provided GUAMI. In this case, return + * NULL. That way the RRC layer should know about it and reject RRC + * connectivity. */ + return NULL; +} + + +struct ngap_gNB_amf_data_s * +ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p, + ngap_guami_t guami) +{ + struct ngap_gNB_amf_data_s *amf_data_p = NULL; + struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL; + uint8_t current_capacity = 0; + + + RB_FOREACH(amf_data_p, ngap_amf_map, &instance_p->ngap_amf_head) { + struct served_guami_s *guami_p = NULL; + + if (amf_data_p->state != NGAP_GNB_STATE_CONNECTED) { + /* The association between AMF and gNB is not ready for the moment, + * go to the next known AMF. + */ + if (amf_data_p->state == NGAP_GNB_OVERLOAD) { + /* AMF is overloaded. We have to check the RRC establishment + * cause and take decision to the select this AMF depending on + * the overload state. + */ + } else { + /* The AMF is not overloaded, association is simply not ready. */ + continue; + } + } + + if (current_capacity < amf_data_p->relative_amf_capacity) { + /* We find a better AMF, keep a reference to it */ + current_capacity = amf_data_p->relative_amf_capacity; + amf_highest_capacity_p = amf_data_p; + } + + /* Looking for AMF guami matching the one provided by NAS */ + STAILQ_FOREACH(guami_p, &amf_data_p->served_guami, next) { + struct served_region_id_s *region_id_p = NULL; + struct amf_set_id_s *amf_set_id_p = NULL; + struct plmn_identity_s *served_plmn_p = NULL; + + STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) { + if ((served_plmn_p->mcc == guami.mcc) && + (served_plmn_p->mnc == guami.mnc)) { + break; + } + } + STAILQ_FOREACH(amf_set_id_p, &guami_p->amf_set_ids, next) { + if (amf_set_id_p->amf_set_id == guami.amf_set_id) { + break; + } + } + STAILQ_FOREACH(region_id_p, &guami_p->served_region_ids, next) { + if (region_id_p->amf_region_id == guami.amf_region_id) { + break; + } + } + + /* The AMF matches the parameters provided by the NAS layer -> + * the AMF is knwown and the association is ready. + * Return the reference to the AMF to use it for this UE. + */ + if ((region_id_p != NULL) && + (amf_set_id_p != NULL) && + (served_plmn_p != NULL)) { + return amf_data_p; + } + } + } + + /* At this point no AMF matches the provided GUAMI. Select the one with the + * highest relative capacity. + * In case the list of known AMF is empty, simply return NULL, that way the RRC + * layer should know about it and reject RRC connectivity. + */ + + return amf_highest_capacity_p; +} diff --git a/openair3/NGAP/ngap_gNB_nnsf.h b/openair3/NGAP/ngap_gNB_nnsf.h new file mode 100644 index 0000000000..7d43a890ea --- /dev/null +++ b/openair3/NGAP/ngap_gNB_nnsf.h @@ -0,0 +1,57 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_nnsf.h + * \brief ngap NAS node selection functions + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#ifndef NGAP_GNB_NNSF_H_ +#define NGAP_GNB_NNSF_H_ + +struct ngap_gNB_amf_data_s * +ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p, + ngap_rrc_establishment_cause_t cause); + +struct ngap_gNB_amf_data_s * +ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p, + ngap_rrc_establishment_cause_t cause, + int selected_plmn_identity); + +struct ngap_gNB_amf_data_s* +ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p, + ngap_rrc_establishment_cause_t cause, + int selected_plmn_identity, + uint8_t amf_setid); + +struct ngap_gNB_amf_data_s* +ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p, + ngap_rrc_establishment_cause_t cause, + ngap_guami_t guami); + +struct ngap_gNB_amf_data_s* +ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p, + ngap_guami_t guami); + +#endif /* NGAP_GNB_NNSF_H_ */ diff --git a/openair3/NGAP/ngap_gNB_overload.c b/openair3/NGAP/ngap_gNB_overload.c new file mode 100644 index 0000000000..318a2124bd --- /dev/null +++ b/openair3/NGAP/ngap_gNB_overload.c @@ -0,0 +1,79 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_overload.c + * \brief ngap procedures for overload messages within gNB + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + + +#include +#include +#include + +#include "intertask_interface.h" + +#include "ngap_common.h" +#include "ngap_gNB_defs.h" + +#include "ngap_gNB.h" +#include "ngap_gNB_ue_context.h" +#include "ngap_gNB_encoder.h" +#include "ngap_gNB_overload.h" +#include "ngap_gNB_management_procedures.h" + +#include "assertions.h" + +int ngap_gNB_handle_overload_start(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) +{ + //TODO + return 0; +} + +int ngap_gNB_handle_overload_stop(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) +{ + /* We received Overload stop message, meaning that the AMF is no more + * overloaded. This is an empty message, with only message header and no + * Information Element. + */ + DevAssert(pdu != NULL); + + ngap_gNB_amf_data_t *amf_desc_p; + + /* Non UE-associated signalling -> stream 0 */ + DevCheck(stream == 0, stream, 0, 0); + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + /* No AMF context associated */ + return -1; + } + + amf_desc_p->state = NGAP_GNB_STATE_CONNECTED; + amf_desc_p->overload_state = NGAP_NO_OVERLOAD; + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_overload.h b/openair3/NGAP/ngap_gNB_overload.h new file mode 100644 index 0000000000..0b7ab52c26 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_overload.h @@ -0,0 +1,53 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_overload.h + * \brief ngap procedures for overload messages within gNB + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#ifndef NGAP_GNB_OVERLOAD_H_ +#define NGAP_GNB_OVERLOAD_H_ + +/** + * \brief Handle an overload start message + **/ +// int ngap_gNB_handle_overload_start(gNB_amf_desc_t *gNB_desc_p, +// sctp_queue_item_t *packet_p, +// struct ngap_message_s *message_p); +int ngap_gNB_handle_overload_start(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +/** + * \brief Handle an overload stop message + **/ +// int ngap_gNB_handle_overload_stop(gNB_amf_desc_t *gNB_desc_p, +// sctp_queue_item_t *packet_p, +// struct ngap_message_s *message_p); +int ngap_gNB_handle_overload_stop(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +#endif /* NGAP_GNB_OVERLOAD_H_ */ diff --git a/openair3/NGAP/ngap_gNB_trace.c b/openair3/NGAP/ngap_gNB_trace.c new file mode 100644 index 0000000000..f3e216988c --- /dev/null +++ b/openair3/NGAP/ngap_gNB_trace.c @@ -0,0 +1,66 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_trace.c + * \brief ngap trace procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#include + +#include "assertions.h" + +#include "intertask_interface.h" + +#include "ngap_gNB_default_values.h" + +#include "ngap_common.h" +#include "ngap_gNB_defs.h" + +#include "ngap_gNB.h" +#include "ngap_gNB_ue_context.h" +#include "ngap_gNB_encoder.h" +#include "ngap_gNB_trace.h" +#include "ngap_gNB_itti_messaging.h" +#include "ngap_gNB_management_procedures.h" + + +int ngap_gNB_handle_trace_start(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu) +{ + //TODO + return 0; +} + +int ngap_gNB_handle_deactivate_trace(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *message_p) +{ + // NGAP_DeactivateTraceIEs_t *deactivate_trace_p; + // + // deactivate_trace_p = &message_p->msg.deactivateTraceIEs; + + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_trace.h b/openair3/NGAP/ngap_gNB_trace.h new file mode 100644 index 0000000000..91ea07ae80 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_trace.h @@ -0,0 +1,54 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_trace.h + * \brief ngap trace procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#ifndef NGAP_GNB_TRACE_H_ +#define NGAP_GNB_TRACE_H_ + +// int ngap_gNB_generate_trace_failure(sctp_data_t *sctp_data_p, +// int32_t stream, +// uint32_t gNB_ue_ngap_id, +// uint32_t amf_ue_ngap_id, +// E_UTRAN_Trace_ID_t *trace_id, +// Cause_t *cause_p); + +// int ngap_gNB_handle_trace_start(gNB_amf_desc_t *gNB_desc_p, +// sctp_queue_item_t *packet_p, +// struct ngap_message_s *message_p); +int ngap_gNB_handle_trace_start(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +// int ngap_gNB_handle_deactivate_trace(gNB_amf_desc_t *gNB_desc_p, +// sctp_queue_item_t *packet_p, +// struct ngap_message_s *message_p); +int ngap_gNB_handle_deactivate_trace(uint32_t assoc_id, + uint32_t stream, + NGAP_NGAP_PDU_t *pdu); + +#endif /* NGAP_GNB_TRACE_H_ */ diff --git a/openair3/NGAP/ngap_gNB_ue_context.c b/openair3/NGAP/ngap_gNB_ue_context.c new file mode 100644 index 0000000000..8beb4d9485 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_ue_context.c @@ -0,0 +1,103 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_ue_context.c + * \brief ngap UE context management within gNB + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#include +#include +#include +#include + +#include "tree.h" + +#include "intertask_interface.h" + +#include "ngap_common.h" +#include "ngap_gNB_defs.h" +#include "ngap_gNB_ue_context.h" + +int ngap_gNB_compare_gNB_ue_ngap_id( + struct ngap_gNB_ue_context_s *p1, struct ngap_gNB_ue_context_s *p2) +{ + if (p1->gNB_ue_ngap_id > p2->gNB_ue_ngap_id) { + return 1; + } + + if (p1->gNB_ue_ngap_id < p2->gNB_ue_ngap_id) { + return -1; + } + + return 0; +} + +/* Generate the tree management functions */ +RB_GENERATE(ngap_ue_map, ngap_gNB_ue_context_s, entries, + ngap_gNB_compare_gNB_ue_ngap_id); + +struct ngap_gNB_ue_context_s *ngap_gNB_allocate_new_UE_context(void) +{ + struct ngap_gNB_ue_context_s *new_p; + + new_p = malloc(sizeof(struct ngap_gNB_ue_context_s)); + + if (new_p == NULL) { + NGAP_ERROR("Cannot allocate new ue context\n"); + return NULL; + } + + memset(new_p, 0, sizeof(struct ngap_gNB_ue_context_s)); + + return new_p; +} + +struct ngap_gNB_ue_context_s *ngap_gNB_get_ue_context( + ngap_gNB_instance_t *instance_p, + uint32_t gNB_ue_ngap_id) +{ + ngap_gNB_ue_context_t temp; + + memset(&temp, 0, sizeof(struct ngap_gNB_ue_context_s)); + + /* gNB ue ngap id = 32 bits wide */ + temp.gNB_ue_ngap_id = gNB_ue_ngap_id & 0xFFFFFFFF; + + return RB_FIND(ngap_ue_map, &instance_p->ngap_ue_head, &temp); +} + +void ngap_gNB_free_ue_context(struct ngap_gNB_ue_context_s *ue_context_p) +{ + if (ue_context_p == NULL) { + NGAP_ERROR("Trying to free a NULL context\n"); + return; + } + + /* TODO: check that context is currently not in the tree of known + * contexts. + */ + + free(ue_context_p); +} diff --git a/openair3/NGAP/ngap_gNB_ue_context.h b/openair3/NGAP/ngap_gNB_ue_context.h new file mode 100644 index 0000000000..4b300c6fea --- /dev/null +++ b/openair3/NGAP/ngap_gNB_ue_context.h @@ -0,0 +1,103 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file ngap_gNB_ue_context.h + * \brief ngap UE context management within gNB + * \author Yoshio INOUE, Masayuki HARADA + * \date 2020 + * \version 0.1 + * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com) + */ + +#include "tree.h" +#include "queue.h" + +#include "ngap_gNB_defs.h" + +#ifndef NGAP_GNB_UE_CONTEXT_H_ +#define NGAP_GNB_UE_CONTEXT_H_ + +// Forward declarations +struct ngap_gNB_amf_data_s; +struct ngap_ue_map; +struct gNB_amf_desc_s; + +typedef enum { + /* UE has not been registered to a AMF or UE association has failed. */ + NGAP_UE_DECONNECTED = 0x0, + /* UE ngap state is waiting for initial context setup request message. */ + NGAP_UE_WAITING_CSR = 0x1, + /* UE association is ready and bearers are established. */ + NGAP_UE_CONNECTED = 0x2, + NGAP_UE_STATE_MAX, +} ngap_ue_state; + +typedef struct ngap_gNB_ue_context_s { + /* Tree related data */ + RB_ENTRY(ngap_gNB_ue_context_s) entries; + + /* Uniquely identifies the UE between AMF and gNB within the gNB. + * This id is encoded on 32bits. + */ + uint32_t gNB_ue_ngap_id; + + /* UE id for initial connection to NGAP */ + uint16_t ue_initial_id; + + /* Uniquely identifies the UE within AMF. Encoded on 32 bits. */ + uint64_t amf_ue_ngap_id:40; + + /* Stream used for this particular UE */ + int32_t tx_stream; + int32_t rx_stream; + + /* Current UE state. */ + ngap_ue_state ue_state; + + /* Reference to AMF data this UE is attached to */ + struct ngap_gNB_amf_data_s *amf_ref; + + /* Signaled by the UE in RRC Connection Setup Complete and used in NAS Uplink + * to route NAS messages correctly. 0-based, not 1-based as in TS 36.331 + * 6.2.2 RRC Connection Setup Complete! */ + int selected_plmn_identity; + + /* Reference to gNB data this UE is attached to */ + ngap_gNB_instance_t *gNB_instance; +} ngap_gNB_ue_context_t; + +int ngap_gNB_compare_gNB_ue_ngap_id( + struct ngap_gNB_ue_context_s *p1, struct ngap_gNB_ue_context_s *p2); + +/* Generate the tree management functions prototypes */ +RB_PROTOTYPE(ngap_ue_map, ngap_gNB_ue_context_s, entries, + ngap_gNB_compare_gNB_ue_ngap_id); + +struct ngap_gNB_ue_context_s *ngap_gNB_allocate_new_UE_context(void); + +struct ngap_gNB_ue_context_s *ngap_gNB_get_ue_context( + ngap_gNB_instance_t *instance_p, + uint32_t gNB_ue_ngap_id); + +void ngap_gNB_free_ue_context(struct ngap_gNB_ue_context_s *ue_context_p); + + +#endif /* NGAP_GNB_UE_CONTEXT_H_ */ diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h index 77d03f4ae4..efac0201a3 100644 --- a/openair3/S1AP/s1ap_common.h +++ b/openair3/S1AP/s1ap_common.h @@ -106,7 +106,12 @@ extern int asn1_xer_print; if (ie == NULL ) { \ S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\ } \ - if (mandatory) DevAssert(ie != NULL); \ + if (mandatory) { \ + if (ie == NULL) { \ + S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\ + return -1; \ + } \ + } \ } while(0) /** \brief Function callback prototype. **/ diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index c703501847..e528c9e53e 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -73,6 +73,42 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); +static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p); +void s1ap_eNB_timer_expired(instance_t instance, + timer_has_expired_t *msg_p); + +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id) +{ + uint32_t *timeoutArg=NULL; + int ret=0; + timeoutArg=malloc(sizeof(uint32_t)); + *timeoutArg=timer_kind; + ret=timer_setup(interval_sec, + interval_us, + task_id, + instance, + type, + (void*)timeoutArg, + timer_id); + return ret; +} + +int s1ap_timer_remove(long timer_id) +{ + int ret; + ret=timer_remove(timer_id); + return ret; +} + uint32_t s1ap_generate_eNB_id(void) { char *out; char hostname[50]; @@ -89,6 +125,7 @@ uint32_t s1ap_generate_eNB_id(void) { static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, net_ip_address_t *mme_ip_address, + uint16_t mme_port, net_ip_address_t *local_ip_addr, uint16_t in_streams, uint16_t out_streams, @@ -97,12 +134,12 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, MessageDef *message_p = NULL; sctp_new_association_req_t *sctp_new_association_req_p = NULL; s1ap_eNB_mme_data_t *s1ap_mme_data_p = NULL; - struct s1ap_eNB_mme_data_s *mme = NULL; +// struct s1ap_eNB_mme_data_s *mme = NULL; DevAssert(instance_p != NULL); DevAssert(mme_ip_address != NULL); - message_p = itti_alloc_new_message(TASK_S1AP, SCTP_NEW_ASSOCIATION_REQ); + message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ); sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; - sctp_new_association_req_p->port = S1AP_PORT_NUMBER; + sctp_new_association_req_p->port = mme_port; sctp_new_association_req_p->ppid = S1AP_SCTP_PPID; sctp_new_association_req_p->in_streams = in_streams; sctp_new_association_req_p->out_streams = out_streams; @@ -112,51 +149,33 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, memcpy(&sctp_new_association_req_p->local_address, local_ip_addr, sizeof(*local_ip_addr)); - S1AP_INFO("[eNB %d] check the mme registration state\n",instance_p->instance); - mme = NULL; + S1AP_INFO("[eNB %ld] check the mme registration state\n",instance_p->instance); + /* Create new MME descriptor */ + s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); + DevAssert(s1ap_mme_data_p != NULL); + s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + s1ap_mme_data_p->assoc_id = -1; + s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; + memcpy(&s1ap_mme_data_p->mme_s1_ip, + mme_ip_address, + sizeof(*mme_ip_address)); + s1ap_mme_data_p->mme_port = mme_port; + for (int i = 0; i < broadcast_plmn_num; ++i) + s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; - if ( mme == NULL ) { - /* Create new MME descriptor */ - s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); - DevAssert(s1ap_mme_data_p != NULL); - s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); - sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; - s1ap_mme_data_p->assoc_id = -1; - s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; - memcpy(&s1ap_mme_data_p->mme_s1_ip, - mme_ip_address, - sizeof(*mme_ip_address)); - for (int i = 0; i < broadcast_plmn_num; ++i) - s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; - - s1ap_mme_data_p->s1ap_eNB_instance = instance_p; - STAILQ_INIT(&s1ap_mme_data_p->served_gummei); - /* Insert the new descriptor in list of known MME - * but not yet associated. - */ - RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); - s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; - instance_p->s1ap_mme_nb ++; - instance_p->s1ap_mme_pending_nb ++; - } else if (mme->state == S1AP_ENB_STATE_WAITING) { - instance_p->s1ap_mme_pending_nb ++; - sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; - S1AP_INFO("[eNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", - instance_p->instance, - mme->state, mme->cnx_id, - instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); - /*s1ap_mme_data_p->cnx_id = mme->cnx_id; - sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; - - s1ap_mme_data_p->assoc_id = -1; - s1ap_mme_data_p->s1ap_eNB_instance = instance_p; - */ - } else { - S1AP_WARN("[eNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", - instance_p->instance, - mme->state, mme->cnx_id, - instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); - } + s1ap_mme_data_p->s1ap_eNB_instance = instance_p; + STAILQ_INIT(&s1ap_mme_data_p->served_gummei); + /* Insert the new descriptor in list of known MME + * but not yet associated. + */ + RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + memcpy( &(s1ap_mme_data_p->mme_ip_address), mme_ip_address, sizeof(net_ip_address_t) ); + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->sctp_req_cnt++; + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; + instance_p->s1ap_mme_pending_nb ++; itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); } @@ -194,10 +213,10 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->eNB_id = s1ap_register_eNB->eNB_id; new_instance->cell_type = s1ap_register_eNB->cell_type; new_instance->tac = s1ap_register_eNB->tac; - + memcpy(&new_instance->eNB_s1_ip, - &s1ap_register_eNB->enb_ip_address, - sizeof(s1ap_register_eNB->enb_ip_address)); + &s1ap_register_eNB->enb_ip_address, + sizeof(s1ap_register_eNB->enb_ip_address)); for (int i = 0; i < s1ap_register_eNB->num_plmn; i++) { new_instance->mcc[i] = s1ap_register_eNB->mcc[i]; @@ -205,22 +224,36 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->mnc_digit_length[i] = s1ap_register_eNB->mnc_digit_length[i]; } + memcpy( &(new_instance->enb_ip_address), &(s1ap_register_eNB->enb_ip_address), sizeof(net_ip_address_t) ); + new_instance->s1_setuprsp_wait_timer = s1ap_register_eNB->s1_setuprsp_wait_timer; + new_instance->s1_setupreq_wait_timer = s1ap_register_eNB->s1_setupreq_wait_timer; + new_instance->s1_setupreq_count = s1ap_register_eNB->s1_setupreq_count; + new_instance->sctp_req_timer = s1ap_register_eNB->sctp_req_timer; + new_instance->sctp_req_count = s1ap_register_eNB->sctp_req_count; + new_instance->sctp_in_streams = s1ap_register_eNB->sctp_in_streams; + new_instance->sctp_out_streams = s1ap_register_eNB->sctp_out_streams; + new_instance->num_plmn = s1ap_register_eNB->num_plmn; new_instance->default_drx = s1ap_register_eNB->default_drx; /* Add the new instance to the list of eNB (meaningfull in virtual mode) */ s1ap_eNB_insert_new_instance(new_instance); - S1AP_INFO("Registered new eNB[%d] and %s eNB id %u\n", + S1AP_INFO("Registered new eNB[%ld] and %s eNB id %u\n", instance, s1ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home", s1ap_register_eNB->eNB_id); } - DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, - S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0); + if( s1ap_register_eNB->nb_mme > S1AP_MAX_NB_MME_IP_ADDRESS ) + { + S1AP_ERROR("Invalid MME number = %d\n ", s1ap_register_eNB->nb_mme); + s1ap_register_eNB->nb_mme = S1AP_MAX_NB_MME_IP_ADDRESS; + } + new_instance->s1ap_mme_nb = s1ap_register_eNB->nb_mme; /* Trying to connect to provided list of MME ip address */ for (index = 0; index < s1ap_register_eNB->nb_mme; index++) { net_ip_address_t *mme_ip = &s1ap_register_eNB->mme_ip_address[index]; + uint16_t mme_port = s1ap_register_eNB->mme_port[index]; struct s1ap_eNB_mme_data_s *mme = NULL; RB_FOREACH(mme, s1ap_mme_map, &new_instance->s1ap_mme_head) { /* Compare whether IPv4 and IPv6 information is already present, in which @@ -235,6 +268,7 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * continue; s1ap_eNB_register_mme(new_instance, mme_ip, + mme_port, &s1ap_register_eNB->enb_ip_address, s1ap_register_eNB->sctp_in_streams, s1ap_register_eNB->sctp_out_streams, @@ -246,28 +280,131 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { s1ap_eNB_instance_t *instance_p; s1ap_eNB_mme_data_t *s1ap_mme_data_p; + s1ap_eNB_ue_context_t *ue_p = NULL; + MessageDef *message_p = NULL; + uint32_t timer_kind = 0; + struct plmn_identity_s* plmnInfo; + struct served_group_id_s* groupInfo; + struct served_gummei_s* gummeiInfo; + struct mme_code_s* mmeCode; + int8_t cnt = 0; + unsigned enb_s1ap_id[NUMBER_OF_UE_MAX]; DevAssert(sctp_new_association_resp != NULL); instance_p = s1ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1, sctp_new_association_resp->ulp_cnx_id); DevAssert(s1ap_mme_data_p != NULL); - - if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", - sctp_new_association_resp->sctp_state, - instance, - sctp_new_association_resp->ulp_cnx_id); - s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); - return; + memset(enb_s1ap_id, 0, sizeof(enb_s1ap_id) ); + if( s1ap_mme_data_p->timer_id != S1AP_TIMERID_INIT ) { + s1ap_timer_remove( s1ap_mme_data_p->timer_id ); + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; } + + if( sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED ) { + RB_FOREACH(ue_p, s1ap_ue_map, &instance_p->s1ap_ue_head) { + if( ue_p->mme_ref == s1ap_mme_data_p ) { + if(cnt < NUMBER_OF_UE_MAX) { + enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id; + cnt++; + + message_p = NULL; + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); + + if( message_p != NULL ) { + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = ue_p->eNB_ue_s1ap_id; + + if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) { + S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); + } + } else { + S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); + } + }else{ + S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt); + } + } + } + for( ; cnt > 0 ; ) { + cnt--; + struct s1ap_eNB_ue_context_s *ue_context_p = NULL; + struct s1ap_eNB_ue_context_s *s1ap_ue_context_p = NULL; + ue_context_p = s1ap_eNB_get_ue_context(instance_p, (uint32_t)enb_s1ap_id[cnt]); + if (ue_context_p != NULL) { + s1ap_ue_context_p = RB_REMOVE(s1ap_ue_map, &instance_p->s1ap_ue_head, ue_context_p); + s1ap_eNB_free_ue_context(s1ap_ue_context_p); + } + } + s1ap_mme_data_p->mme_name = 0; + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->nextstream = 0; + s1ap_mme_data_p->in_streams = 0; + s1ap_mme_data_p->out_streams = 0; + s1ap_mme_data_p->assoc_id = -1; + + while (!STAILQ_EMPTY(&s1ap_mme_data_p->served_gummei)) { + gummeiInfo = STAILQ_FIRST(&s1ap_mme_data_p->served_gummei); + STAILQ_REMOVE_HEAD(&s1ap_mme_data_p->served_gummei, next); - /* Update parameters */ - s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; - s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; - s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; - /* Prepare new S1 Setup Request */ - s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p); + while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) { + plmnInfo = STAILQ_FIRST(&gummeiInfo->served_plmns); + STAILQ_REMOVE_HEAD(&gummeiInfo->served_plmns, next); + free(plmnInfo); + } + while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) { + groupInfo = STAILQ_FIRST(&gummeiInfo->served_group_ids); + STAILQ_REMOVE_HEAD(&gummeiInfo->served_group_ids, next); + free(groupInfo); + } + while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) { + mmeCode = STAILQ_FIRST(&gummeiInfo->mme_codes); + STAILQ_REMOVE_HEAD(&gummeiInfo->mme_codes, next); + free(mmeCode); + } + free(gummeiInfo); + } + + STAILQ_INIT(&s1ap_mme_data_p->served_gummei); + + if( s1ap_mme_data_p->state == S1AP_ENB_STATE_DISCONNECTED ) { + if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || + (instance_p->sctp_req_count == 0xffff) ) { + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | SCTP_REQ_WAIT; + + if( s1ap_timer_setup( instance_p->sctp_req_timer, 0, TASK_S1AP, instance_p->instance, + timer_kind, S1AP_TIMER_ONE_SHOT, NULL, &s1ap_mme_data_p->timer_id) < 0 ) { + S1AP_ERROR("Timer Start NG(SCTP retransmission wait timer) : MME=%d\n",s1ap_mme_data_p->cnx_id); + s1ap_sctp_req( instance_p, s1ap_mme_data_p ); + } + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + } else { + S1AP_ERROR("SCTP disconnection reception : MME = %d\n",s1ap_mme_data_p->cnx_id); + + if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || + (instance_p->sctp_req_count == 0xffff) ) { + s1ap_sctp_req( instance_p, s1ap_mme_data_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + } + } else { + /* Update parameters */ + s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; + s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; + s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; + /* Prepare new S1 Setup Request */ + s1ap_mme_data_p->s1_setupreq_cnt = 0; + s1ap_mme_data_p->sctp_req_cnt = 0; + if (s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p) == -1) { + S1AP_ERROR("s1ap eNB generate s1 setup request failed\n"); + return; + } + } } static @@ -278,13 +415,94 @@ void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { mme_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream, sctp_data_ind->buffer, sctp_data_ind->buffer_length); #else - s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, - sctp_data_ind->buffer, sctp_data_ind->buffer_length); + if (s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, + sctp_data_ind->buffer, sctp_data_ind->buffer_length) == -1) { + S1AP_ERROR("Failed to handle s1ap eNB message\n"); + } #endif result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } +void s1ap_eNB_timer_expired( + instance_t instance, + timer_has_expired_t *msg_p) +{ + uint32_t timer_kind = 0; + int16_t line_ind = 0; + s1ap_eNB_mme_data_t *mme_desc_p = NULL; + uint32_t timer_ind = 0; + s1ap_eNB_instance_t *instance_p = NULL; + long timer_id = S1AP_TIMERID_INIT; + + instance_p = s1ap_eNB_get_instance(instance); + if(msg_p->arg!=NULL){ + timer_kind = *((uint32_t*)msg_p->arg); + free(msg_p->arg); + }else{ + S1AP_ERROR("s1 timer timer_kind is NULL\n"); + return; + } + line_ind = (int16_t)(timer_kind & S1AP_LINEIND); + timer_id = msg_p->timer_id; + + if( (timer_kind & S1AP_MMEIND) == S1AP_MMEIND ) { + mme_desc_p = s1ap_eNB_get_MME(instance_p, -1, line_ind); + if(mme_desc_p != NULL) { + if( timer_id == mme_desc_p->timer_id ) { + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + timer_ind = timer_kind & S1AP_TIMERIND; + + switch(timer_ind) + { + case S1_SETRSP_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); + } + break; + } + case S1_SETREQ_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); + } + break; + } + case SCTP_REQ_WAIT: + { + if( (instance_p->sctp_req_count >= mme_desc_p->sctp_req_cnt) || + (instance_p->sctp_req_count == 0xffff) ) { + s1ap_sctp_req( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",line_ind); + } + break; + } + default: + { + S1AP_WARN("Invalid Timer indication\n"); + break; + } + } + } else { + S1AP_DEBUG("Unmatch timer id\n"); + return; + } + } else { + S1AP_WARN("Not applicable MME detected : connection id = %d\n", line_ind); + return; + } + } + return; +} + void s1ap_eNB_init(void) { S1AP_DEBUG("Starting S1AP layer\n"); s1ap_eNB_prepare_internal_data(); @@ -309,13 +527,13 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { * Each eNB has to send an S1AP_REGISTER_ENB message with its * own parameters. */ - s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_handle_register_eNB(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_REGISTER_ENB_REQ(received_msg)); } break; case SCTP_NEW_ASSOCIATION_RESP: { - s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); } break; @@ -326,61 +544,61 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { break; case S1AP_NAS_FIRST_REQ: { - s1ap_eNB_handle_nas_first_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_handle_nas_first_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_NAS_FIRST_REQ(received_msg)); } break; case S1AP_UPLINK_NAS: { - s1ap_eNB_nas_uplink(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_nas_uplink(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_UPLINK_NAS(received_msg)); } break; case S1AP_UE_CAPABILITIES_IND: { - s1ap_eNB_ue_capabilities(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_ue_capabilities(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_UE_CAPABILITIES_IND(received_msg)); } break; case S1AP_INITIAL_CONTEXT_SETUP_RESP: { - s1ap_eNB_initial_ctxt_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_initial_ctxt_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_INITIAL_CONTEXT_SETUP_RESP(received_msg)); } break; case S1AP_E_RAB_SETUP_RESP: { - s1ap_eNB_e_rab_setup_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_e_rab_setup_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_E_RAB_SETUP_RESP(received_msg)); } break; case S1AP_E_RAB_MODIFY_RESP: { - s1ap_eNB_e_rab_modify_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_e_rab_modify_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_E_RAB_MODIFY_RESP(received_msg)); } break; case S1AP_NAS_NON_DELIVERY_IND: { - s1ap_eNB_nas_non_delivery_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_nas_non_delivery_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_NAS_NON_DELIVERY_IND(received_msg)); } break; case S1AP_PATH_SWITCH_REQ: { - s1ap_eNB_path_switch_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_path_switch_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_PATH_SWITCH_REQ(received_msg)); } break; case S1AP_E_RAB_MODIFICATION_IND: { - s1ap_eNB_generate_E_RAB_Modification_Indication(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_generate_E_RAB_Modification_Indication(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_E_RAB_MODIFICATION_IND(received_msg)); } break; case S1AP_UE_CONTEXT_RELEASE_COMPLETE: { - s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_ue_context_release_complete(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg)); } break; @@ -388,9 +606,9 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { case S1AP_UE_CONTEXT_RELEASE_REQ: { s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL; // test struct s1ap_eNB_ue_context_s *ue_context_p = NULL; // test - s1ap_ue_context_release_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_ue_context_release_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_UE_CONTEXT_RELEASE_REQ(received_msg)); - s1ap_eNB_instance_p = s1ap_eNB_get_instance(ITTI_MESSAGE_GET_INSTANCE(received_msg)); // test + s1ap_eNB_instance_p = s1ap_eNB_get_instance(ITTI_MSG_DESTINATION_INSTANCE(received_msg)); // test DevAssert(s1ap_eNB_instance_p != NULL); // test if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, @@ -403,11 +621,18 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { break; case S1AP_E_RAB_RELEASE_RESPONSE: { - s1ap_eNB_e_rab_release_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_e_rab_release_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_E_RAB_RELEASE_RESPONSE(received_msg)); } break; + case TIMER_HAS_EXPIRED: + { + s1ap_eNB_timer_expired(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &received_msg->ittiMsg.timer_has_expired); + } + break; + default: S1AP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); @@ -448,6 +673,7 @@ static int s1ap_eNB_generate_s1_setup_request( uint8_t *buffer = NULL; uint32_t len = 0; int ret = 0; + uint32_t timer_kind = 0; DevAssert(instance_p != NULL); DevAssert(s1ap_mme_data_p != NULL); s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; @@ -522,6 +748,17 @@ static int s1ap_eNB_generate_s1_setup_request( return -1; } + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETRSP_WAIT; + + if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->s1_setupreq_cnt++; + /* Non UE-Associated signalling -> stream = 0 */ s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); return ret; @@ -530,3 +767,55 @@ static int s1ap_eNB_generate_s1_setup_request( +static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p) +{ + MessageDef *message_p = NULL; + sctp_new_association_req_t *sctp_new_association_req_p = NULL; + + if( instance_p == NULL ) + { + S1AP_ERROR("Invalid instance_p\n"); + return -1; + } + + message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ); + sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; + sctp_new_association_req_p->port = S1AP_PORT_NUMBER; + sctp_new_association_req_p->ppid = S1AP_SCTP_PPID; + sctp_new_association_req_p->in_streams = instance_p->sctp_in_streams; + sctp_new_association_req_p->out_streams = instance_p->sctp_out_streams; + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + + if( s1ap_mme_data_p->mme_ip_address.ipv4 != 0 ) { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv4 != 0 ) { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } else { + S1AP_ERROR("Invalid IP Address Format V4(MME):V6\n"); + return -1; + } + } else { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv6 != 0 ) { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } else { + S1AP_ERROR("Invalid IP Address Format V6(MME):V4\n"); + return -1; + } + } + + itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); + + s1ap_mme_data_p->sctp_req_cnt++; + + return 0; +} diff --git a/openair3/S1AP/s1ap_eNB.h b/openair3/S1AP/s1ap_eNB.h index 2abbc53ec9..2183587214 100644 --- a/openair3/S1AP/s1ap_eNB.h +++ b/openair3/S1AP/s1ap_eNB.h @@ -30,6 +30,22 @@ #ifndef S1AP_ENB_H_ #define S1AP_ENB_H_ +#define S1AP_MMEIND 0x80000000 +#define S1AP_UEIND 0x00000000 +#define S1_SETRSP_WAIT 0x00010000 +#define S1_SETREQ_WAIT 0x00020000 +#define SCTP_REQ_WAIT 0x00030000 +#define S1AP_LINEIND 0x0000ffff +#define S1AP_TIMERIND 0x00ff0000 + +#define S1AP_TIMERID_INIT 0xffffffffffffffff + +typedef enum s1ap_timer_type_s { + S1AP_TIMER_PERIODIC, + S1AP_TIMER_ONE_SHOT, + S1AP_TIMER_TYPE_MAX, +} s1ap_timer_type_t; + typedef struct s1ap_eNB_config_s { // MME related params unsigned char mme_enabled; ///< MME enabled ? @@ -43,6 +59,7 @@ void *s1ap_eNB_process_itti_msg(void*); void s1ap_eNB_init(void); void *s1ap_eNB_task(void *arg); +int s1ap_timer_remove(long timer_id); uint32_t s1ap_generate_eNB_id(void); #endif /* S1AP_ENB_H_ */ diff --git a/openair3/S1AP/s1ap_eNB_decoder.c b/openair3/S1AP/s1ap_eNB_decoder.c index 4635946a05..14e4b49238 100644 --- a/openair3/S1AP/s1ap_eNB_decoder.c +++ b/openair3/S1AP/s1ap_eNB_decoder.c @@ -89,8 +89,6 @@ static int s1ap_eNB_decode_initiating_message(S1AP_S1AP_PDU_t *pdu) { default: S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage.procedureCode); - AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n", - (int)pdu->choice.initiatingMessage.procedureCode); return -1; } diff --git a/openair3/S1AP/s1ap_eNB_defs.h b/openair3/S1AP/s1ap_eNB_defs.h index d4bc6cfc0f..ed0909d66e 100644 --- a/openair3/S1AP/s1ap_eNB_defs.h +++ b/openair3/S1AP/s1ap_eNB_defs.h @@ -124,8 +124,9 @@ typedef struct s1ap_eNB_mme_data_s { /* This is the optional name provided by the MME */ char *mme_name; - /* MME S1AP IP address */ + /* MME S1AP IP address and port */ net_ip_address_t mme_s1_ip; + uint16_t mme_port; /* List of served GUMMEI per MME. There is one GUMMEI per RAT with a max * number of 8 RATs but in our case only one is used. The LTE related pool @@ -164,6 +165,12 @@ typedef struct s1ap_eNB_mme_data_s { /* Only meaningfull in virtual mode */ struct s1ap_eNB_instance_s *s1ap_eNB_instance; + + uint32_t nb_calls; + net_ip_address_t mme_ip_address; + long timer_id; + uint16_t s1_setupreq_cnt; + uint16_t sctp_req_cnt; } s1ap_eNB_mme_data_t; typedef struct s1ap_eNB_instance_s { @@ -216,6 +223,14 @@ typedef struct s1ap_eNB_instance_s { /* Default Paging DRX of the eNB as defined in TS 36.304 */ paging_drx_t default_drx; + net_ip_address_t enb_ip_address; + uint16_t s1_setuprsp_wait_timer; + uint16_t s1_setupreq_wait_timer; + uint16_t s1_setupreq_count; + uint16_t sctp_req_timer; + uint16_t sctp_req_count; + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; } s1ap_eNB_instance_t; typedef struct { diff --git a/openair3/S1AP/s1ap_eNB_encoder.c b/openair3/S1AP/s1ap_eNB_encoder.c index 227a3cb6a9..8317f02731 100644 --- a/openair3/S1AP/s1ap_eNB_encoder.c +++ b/openair3/S1AP/s1ap_eNB_encoder.c @@ -137,6 +137,8 @@ int s1ap_eNB_encode_initiating(S1AP_S1AP_PDU_t *pdu, res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_S1AP_S1AP_PDU, pdu); *buffer = res.buffer; *len = res.result.encoded; + if (res.result.encoded == -1) + return -1; return 0; } @@ -189,6 +191,8 @@ int s1ap_eNB_encode_successfull_outcome(S1AP_S1AP_PDU_t *pdu, res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_S1AP_S1AP_PDU, pdu); *buffer = res.buffer; *len = res.result.encoded; + if (res.result.encoded == -1) + return -1; return 0; } @@ -218,5 +222,7 @@ int s1ap_eNB_encode_unsuccessfull_outcome(S1AP_S1AP_PDU_t *pdu, res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_S1AP_S1AP_PDU, pdu); *buffer = res.buffer; *len = res.result.encoded; + if (res.result.encoded == -1) + return -1; return 0; } diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 28ee11187e..9ee3287b94 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -38,6 +38,9 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB_handlers.h" #include "s1ap_eNB_decoder.h" +#include "s1ap_eNB_encoder.h" + +#include "s1ap_eNB_itti_messaging.h" #include "s1ap_eNB_ue_context.h" #include "s1ap_eNB_trace.h" @@ -109,6 +112,20 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as uint32_t stream, S1AP_S1AP_PDU_t *pdu); +static int s1ap_eNB_snd_s1_setup_request( + s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p); + +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id); + /* Handlers matrix. Only eNB related procedure present here */ s1ap_message_decoded_callback messages_callback[][3] = { { 0, 0, 0 }, /* HandoverPreparation */ @@ -188,7 +205,7 @@ void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shut /* If there are no more associated MME, inform eNB app */ if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb == 0) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_DEREGISTERED_ENB_IND); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_DEREGISTERED_ENB_IND); S1AP_DEREGISTERED_ENB_IND(message_p).nb_mme = 0; itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p); } @@ -206,7 +223,7 @@ void s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shut /* If there are no more pending messages, inform eNB app */ if (mme_desc_p->s1ap_eNB_instance->s1ap_mme_pending_nb == 0) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_REGISTER_ENB_CNF); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_REGISTER_ENB_CNF); S1AP_REGISTER_ENB_CNF(message_p).nb_mme = mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb; itti_send_msg_to_task(TASK_ENB_APP, mme_desc_p->s1ap_eNB_instance->instance, message_p); } @@ -260,6 +277,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_S1SetupFailure_t *container; S1AP_S1SetupFailureIEs_t *ie; s1ap_eNB_mme_data_t *mme_desc_p; + uint32_t interval_sec = 0; + uint32_t timer_kind = 0; + s1ap_eNB_instance_t *instance_p; + DevAssert(pdu != NULL); container = &pdu->choice.unsuccessfulOutcome.value.choice.S1SetupFailure; @@ -270,7 +291,7 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing " + S1AP_ERROR("[SCTP %d] Received S1 setup failure for non existing " "MME context\n", assoc_id); return -1; } @@ -278,6 +299,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, S1AP_ProtocolIE_ID_id_Cause,true); + if(ie == NULL) { + return -1; + } + if ((ie->value.choice.Cause.present == S1AP_Cause_PR_misc) && (ie->value.choice.Cause.choice.misc == S1AP_CauseMisc_unspecified)) { S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n"); @@ -285,8 +310,56 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n"); } - mme_desc_p->state = S1AP_ENB_STATE_WAITING; - s1ap_handle_s1_setup_message(mme_desc_p, 0); + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) { + s1ap_timer_remove( mme_desc_p->timer_id ); + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + } + instance_p = mme_desc_p->s1ap_eNB_instance; + if( ( instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + ( instance_p->s1_setupreq_count == 0xffff) ) { + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_TimeToWait, false); + if( ie != NULL ) { + switch(ie->value.choice.TimeToWait) + { + case S1AP_TimeToWait_v1s: + interval_sec = 1; + break; + case S1AP_TimeToWait_v2s: + interval_sec = 2; + break; + case S1AP_TimeToWait_v5s: + interval_sec = 5; + break; + case S1AP_TimeToWait_v10s: + interval_sec = 10; + break; + case S1AP_TimeToWait_v20s: + interval_sec = 20; + break; + case S1AP_TimeToWait_v60s: + interval_sec = 60; + break; + default: + interval_sec = instance_p->s1_setupreq_wait_timer; + break; + } + } else { + interval_sec = instance_p->s1_setupreq_wait_timer; + } + + timer_kind = mme_desc_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETREQ_WAIT; + + if( s1ap_timer_setup(interval_sec, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &mme_desc_p->timer_id) < 0 ) { + S1AP_ERROR("Timer Start NG(S1 Setup Request) : MME=%d\n",mme_desc_p->cnx_id); + s1ap_eNB_snd_s1_setup_request( instance_p, mme_desc_p ); + } + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",mme_desc_p->cnx_id); + } return 0; } @@ -314,9 +387,27 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, return -1; } + /* Set the capacity of this MME */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); + if(ie == NULL) { + return -1; + } + mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_ServedGUMMEIs, true); + if(ie == NULL) { + return -1; + } + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) + { + s1ap_timer_remove( mme_desc_p->timer_id ); + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + } + mme_desc_p->s1_setupreq_cnt = 0; + mme_desc_p->sctp_req_cnt = 0; /* The list of served gummei can contain at most 8 elements. * LTE related gummei is the first element in the list, i.e with an id of 0. */ @@ -368,13 +459,7 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next); } - - /* Set the capacity of this MME */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); - - mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; - + /* Optionaly set the mme name */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_MMEname, false); @@ -392,7 +477,6 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, */ mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++; - s1ap_handle_s1_setup_message(mme_desc_p, 0); return 0; } @@ -725,6 +809,9 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false); if (ie) { + if( ie->value.choice.CriticalityDiagnostics.procedureCode ) { + S1AP_WARN("Received S1 Error indication CriticalityDiagnostics procedureCode = %ld\n", *ie->value.choice.CriticalityDiagnostics.procedureCode); + } // TODO continue } @@ -791,7 +878,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, ue_desc_p->rx_stream = stream; ue_desc_p->mme_ue_s1ap_id = mme_ue_s1ap_id; - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_INITIAL_CONTEXT_SETUP_REQ); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_INITIAL_CONTEXT_SETUP_REQ); S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; ue_desc_p->ue_initial_id = 0; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).eNB_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id; @@ -807,9 +894,11 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, &(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl)); /* id-E-RABToBeSetupListCtxtSUReq */ } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, S1AP_ProtocolIE_ID_id_E_RABToBeSetupListCtxtSUReq, true); @@ -852,6 +941,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability; } /* for i... */ } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -864,21 +954,37 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms); S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms); - /* id-SecurityKey : Copy the security key */ } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } + /* id-SecurityKey : Copy the security key */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, S1AP_ProtocolIE_ID_id_SecurityKey, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); - itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } + + /* id-NRUESecurityCapabilities */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false); + if (ie != NULL) { + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRencryptionAlgorithms); + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRintegrityProtectionAlgorithms); + } else { + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0; + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0; + } + + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; } @@ -904,6 +1010,13 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, return -1; } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, + S1AP_ProtocolIE_ID_id_Cause, true); + if( ie == NULL ) { + S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(Cause)\n" ); + return -1; + } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_UE_S1AP_IDs, true); @@ -935,7 +1048,7 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, NULL,0, "0 S1AP_UE_CONTEXT_RELEASE_COMMAND/%d eNB_ue_s1ap_id "S1AP_UE_ID_FMT" ", enb_ue_s1ap_id); - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); if (ue_desc_p->mme_ue_s1ap_id == 0) { // case of Detach Request and switch off from RRC_IDLE mode ue_desc_p->mme_ue_s1ap_id = mme_ue_s1ap_id; @@ -951,9 +1064,26 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, //#warning "TODO mapping mme_ue_s1ap_id enb_ue_s1ap_id?" case S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID: - mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID; - S1AP_ERROR("TO DO mapping mme_ue_s1ap_id enb_ue_s1ap_id"); - (void)mme_ue_s1ap_id; /* TODO: remove - it's to remove gcc warning about unused var */ + mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.mME_UE_S1AP_ID; + + RB_FOREACH(ue_desc_p, s1ap_ue_map, &mme_desc_p->s1ap_eNB_instance->s1ap_ue_head) + { + if( ue_desc_p->mme_ue_s1ap_id == mme_ue_s1ap_id ) + { + enb_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id; + + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); + + return 0; + } + } + S1AP_ERROR("[SCTP %d] Received UE context release command(mME_UE_S1AP_ID) for non " + "existing UE context 0x%06lx\n", + assoc_id, + mme_ue_s1ap_id); + return -1; case S1AP_UE_S1AP_IDs_PR_NOTHING: default: @@ -961,12 +1091,10 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, return -1; } } else { + S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(UE_S1AP_IDs)\n" ); return -1; } - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, - S1AP_ProtocolIE_ID_id_Cause, true); - /* TBD */ } static @@ -985,7 +1113,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.E_RABSetupRequest; if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non " "existing MME context\n", assoc_id); return -1; } @@ -1012,7 +1140,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance, enb_ue_s1ap_id)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non " "existing UE context 0x%06lx\n", assoc_id, enb_ue_s1ap_id); return -1; @@ -1032,7 +1160,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, ue_desc_p->mme_ue_s1ap_id, mme_ue_s1ap_id); } - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_SETUP_REQ); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_SETUP_REQ); S1AP_E_RAB_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; S1AP_E_RAB_SETUP_REQ(message_p).mme_ue_s1ap_id = mme_ue_s1ap_id; S1AP_E_RAB_SETUP_REQ(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; @@ -1085,6 +1213,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1105,13 +1234,6 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, // received Paging Message from MME S1AP_DEBUG("[SCTP %d] Received Paging Message From MME\n",assoc_id); - /* Paging procedure -> stream != 0 */ - if (stream == 0) { - LOG_W(S1AP,"[SCTP %d] Received Paging procedure on stream (%d)\n", - assoc_id, stream); - return -1; - } - if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { S1AP_ERROR("[SCTP %d] Received Paging for non " "existing MME context\n", assoc_id); @@ -1126,7 +1248,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, return -1; } - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_PAGING_IND); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_PAGING_IND); /* convert S1AP_PagingIEs_t to s1ap_paging_ind_t */ /* id-UEIdentityIndexValue : convert UE Identity Index value */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PagingIEs_t, ie, container, @@ -1139,6 +1261,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code = 0; S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi = 0; } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1166,6 +1289,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, if(i != ie->value.choice.UEPagingID.choice.iMSI.size - 1) { /* invalid paging_p->uePagingID.choise.iMSI.buffer */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI error(i %d 0x0F)\n", assoc_id,i); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { @@ -1176,14 +1300,17 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length >= S1AP_IMSI_LENGTH) { /* invalid paging_p->uePagingID.choise.iMSI.size */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI.size(%d) is over IMSI length(%d)\n", assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length, S1AP_IMSI_LENGTH); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { /* of if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_iMSI) */ /* invalid paging_p->uePagingID.present */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.present(%d) is unknown\n", assoc_id, ie->value.choice.UEPagingID.present); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { /* of ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1216,6 +1343,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, return -1; } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1243,6 +1371,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, S1AP_PAGING_IND(message_p).tac[i]); } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1322,7 +1451,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, if (ue_desc_p->mme_ue_s1ap_id != mme_ue_s1ap_id) { S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)", ue_desc_p->mme_ue_s1ap_id, mme_ue_s1ap_id); - message_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_E_RAB_MODIFY_RESP); + message_p = itti_alloc_new_message (TASK_RRC_ENB, 0, S1AP_E_RAB_MODIFY_RESP); S1AP_E_RAB_MODIFY_RESP (message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABModifyRequestIEs_t, ie, container, S1AP_ProtocolIE_ID_id_E_RABToBeModifiedListBearerModReq, true); @@ -1337,6 +1466,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, S1AP_E_RAB_MODIFY_RESP(message_p).e_rabs_failed[nb_of_e_rabs_failed].cause_value = S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id; } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1348,7 +1478,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, return -1; } - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_MODIFY_REQ); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_MODIFY_REQ); S1AP_E_RAB_MODIFY_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; S1AP_E_RAB_MODIFY_REQ(message_p).mme_ue_s1ap_id = mme_ue_s1ap_id; S1AP_E_RAB_MODIFY_REQ(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; @@ -1389,6 +1519,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else { /* of if (ie != NULL)*/ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1459,9 +1590,27 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, S1AP_DEBUG("[SCTP %d] Received E-RAB release command for eNB_UE_S1AP_ID %ld mme_ue_s1ap_id %ld\n", assoc_id, enb_ue_s1ap_id, mme_ue_s1ap_id); - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_RELEASE_COMMAND); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_RELEASE_COMMAND); S1AP_E_RAB_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; S1AP_E_RAB_RELEASE_COMMAND(message_p).mme_ue_s1ap_id = mme_ue_s1ap_id; + /* id-E-RABToBeReleasedList */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count; + + for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) { + S1AP_E_RABItem_t *item_p; + item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem); + S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; + S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); + } + } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); + return -1; + } + /* id-NAS-PDU */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, S1AP_ProtocolIE_ID_id_NAS_PDU, false); @@ -1477,24 +1626,6 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0; S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL; } - - /* id-E-RABToBeReleasedList */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true); - - if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count; - - for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) { - S1AP_E_RABItem_t *item_p; - item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem); - S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; - S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); - } - } else { - return -1; - } - itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; } @@ -1519,7 +1650,6 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (stream == 0) { S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream (%d)\n", assoc_id, stream); - //return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { @@ -1529,13 +1659,14 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, } // send a message to RRC - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_PATH_SWITCH_REQ_ACK); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_PATH_SWITCH_REQ_ACK); /* mandatory */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge, S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true); if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1558,6 +1689,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1575,6 +1707,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1588,14 +1721,10 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, false); if (ie) { - OCTET_STRING_TO_INT32 ( - &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL, - S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul - ); - OCTET_STRING_TO_INT32 ( - &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL, - S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl - ); + asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL, + &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul); + asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL, + &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl); } else { S1AP_WARN("UEAggregateMaximumBitrate not supported\n"); S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0; @@ -1674,9 +1803,8 @@ int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_ pathSwitchRequestFailure = &pdu->choice.unsuccessfulOutcome.value.choice.PathSwitchRequestFailure; if (stream != 0) { - S1AP_ERROR("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n", + S1AP_WARN("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n", assoc_id, stream); - return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { @@ -1736,7 +1864,148 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as uint32_t stream, S1AP_S1AP_PDU_t *pdu){ - LOG_W(S1AP, "Implementation of S1AP E-RAB Modification confirm handler is pending...\n"); + LOG_I(S1AP, "Received S1AP E-RAB Modification confirm message \n"); return 0; } +//----------------------------------------------------------------------------- +/* +* eNB generate a S1 setup request towards MME +*/ +static int s1ap_eNB_snd_s1_setup_request( + s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p) +//----------------------------------------------------------------------------- +{ + S1AP_S1AP_PDU_t pdu; + S1AP_S1SetupRequest_t *out = NULL; + S1AP_S1SetupRequestIEs_t *ie = NULL; + S1AP_SupportedTAs_Item_t *ta = NULL; + S1AP_PLMNidentity_t *plmn = NULL; + uint8_t *buffer = NULL; + uint32_t len = 0; + int ret = 0; + uint32_t timer_kind = 0; + + DevAssert(instance_p != NULL); + DevAssert(s1ap_mme_data_p != NULL); + s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; + /* Prepare the S1AP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_S1Setup; + pdu.choice.initiatingMessage.criticality = S1AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_S1SetupRequest; + out = &pdu.choice.initiatingMessage.value.choice.S1SetupRequest; + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_Global_ENB_ID; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_Global_ENB_ID; + MCC_MNC_TO_PLMNID(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[0]], + instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[0]], + instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[0]], + &ie->value.choice.Global_ENB_ID.pLMNidentity); + ie->value.choice.Global_ENB_ID.eNB_ID.present = S1AP_ENB_ID_PR_macroENB_ID; + MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id, + &ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID); + S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0], + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1], + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (instance_p->eNB_name) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_eNBname; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_ENBname; + OCTET_STRING_fromBuf(&ie->value.choice.ENBname, instance_p->eNB_name, + strlen(instance_p->eNB_name)); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_SupportedTAs; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_SupportedTAs; + { + ta = (S1AP_SupportedTAs_Item_t *)calloc(1, sizeof(S1AP_SupportedTAs_Item_t)); + INT16_TO_OCTET_STRING(instance_p->tac, &ta->tAC); + { + for (int i = 0; i < s1ap_mme_data_p->broadcast_plmn_num; ++i) { + plmn = (S1AP_PLMNidentity_t *)calloc(1, sizeof(S1AP_PLMNidentity_t)); + MCC_MNC_TO_TBCD(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[i]], + instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[i]], + instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[i]], + plmn); + ASN_SEQUENCE_ADD(&ta->broadcastPLMNs.list, plmn); + } + } + ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAs.list, ta); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_DefaultPagingDRX; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_PagingDRX; + ie->value.choice.PagingDRX = instance_p->default_drx; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_CSG_IdList; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_CSG_IdList; + // ie->value.choice.CSG_IdList = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ +#if (S1AP_VERSION >= MAKE_VERSION(13, 0, 0)) + + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_UE_RetentionInformation; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_UE_RetentionInformation; + // ie->value.choice.UE_RetentionInformation = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_NB_IoT_DefaultPagingDRX; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_NB_IoT_DefaultPagingDRX; + // ie->value.choice.NB_IoT_DefaultPagingDRX = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + +#endif /* #if (S1AP_VERSION >= MAKE_VERSION(14, 0, 0)) */ + + if (s1ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + S1AP_ERROR("Failed to encode S1 setup request\n"); + return -1; + } + + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETRSP_WAIT; + + if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->s1_setupreq_cnt++; + + /* Non UE-Associated signalling -> stream = 0 */ + s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); + return ret; +} diff --git a/openair3/S1AP/s1ap_eNB_itti_messaging.c b/openair3/S1AP/s1ap_eNB_itti_messaging.c index f10c5bc623..8a6539a118 100644 --- a/openair3/S1AP/s1ap_eNB_itti_messaging.c +++ b/openair3/S1AP/s1ap_eNB_itti_messaging.c @@ -29,7 +29,7 @@ void s1ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uin MessageDef *message_p; sctp_data_req_t *sctp_data_req; - message_p = itti_alloc_new_message(TASK_S1AP, SCTP_DATA_REQ); + message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_DATA_REQ); sctp_data_req = &message_p->ittiMsg.sctp_data_req; @@ -50,7 +50,7 @@ void s1ap_eNB_itti_send_nas_downlink_ind(instance_t instance, MessageDef *message_p; s1ap_downlink_nas_t *s1ap_downlink_nas; - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_DOWNLINK_NAS); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_DOWNLINK_NAS); s1ap_downlink_nas = &message_p->ittiMsg.s1ap_downlink_nas; @@ -68,7 +68,7 @@ void s1ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t asso MessageDef *message_p = NULL; sctp_close_association_t *sctp_close_association_p = NULL; - message_p = itti_alloc_new_message(TASK_S1AP, SCTP_CLOSE_ASSOCIATION); + message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_CLOSE_ASSOCIATION); sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; sctp_close_association_p->assoc_id = assoc_id; diff --git a/openair3/S1AP/s1ap_eNB_management_procedures.c b/openair3/S1AP/s1ap_eNB_management_procedures.c index fc7ae70e49..a870e975a2 100644 --- a/openair3/S1AP/s1ap_eNB_management_procedures.c +++ b/openair3/S1AP/s1ap_eNB_management_procedures.c @@ -95,23 +95,43 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME( { struct s1ap_eNB_mme_data_s temp; struct s1ap_eNB_mme_data_s *found; + struct s1ap_eNB_mme_data_s *mme_p; memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s)); temp.assoc_id = assoc_id; temp.cnx_id = cnx_id; - if (instance_p == NULL) { - STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, - s1ap_eNB_entries) { - found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); + if( cnx_id != 0 ) { + if (instance_p == NULL) { + STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, + s1ap_eNB_entries) { + found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); - if (found != NULL) { - return found; + if (found != NULL) { + return found; + } } + } else { + return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); } } else { - return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); + if (instance_p == NULL) { + STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, + s1ap_eNB_entries) { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + if( mme_p->assoc_id == assoc_id ) { + return mme_p; + } + } + } + } else { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + if( mme_p->assoc_id == assoc_id ) { + return mme_p; + } + } + } } return NULL; diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c index c668e32d1b..b55bc06e11 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c @@ -80,7 +80,7 @@ int s1ap_eNB_handle_nas_first_req( s1ap_nas_first_req_p->ue_identity.gummei); if (mme_desc_p) { - S1AP_INFO("[eNB %d] Chose MME '%s' (assoc_id %d) through GUMMEI MCC %d MNC %d MMEGI %d MMEC %d\n", + S1AP_INFO("[eNB %ld] Chose MME '%s' (assoc_id %d) through GUMMEI MCC %d MNC %d MMEGI %d MMEC %d\n", instance, mme_desc_p->mme_name, mme_desc_p->assoc_id, @@ -101,7 +101,7 @@ int s1ap_eNB_handle_nas_first_req( s1ap_nas_first_req_p->ue_identity.s_tmsi.mme_code); if (mme_desc_p) { - S1AP_INFO("[eNB %d] Chose MME '%s' (assoc_id %d) through S-TMSI MMEC %d and selected PLMN Identity index %d MCC %d MNC %d\n", + S1AP_INFO("[eNB %ld] Chose MME '%s' (assoc_id %d) through S-TMSI MMEC %d and selected PLMN Identity index %d MCC %d MNC %d\n", instance, mme_desc_p->mme_name, mme_desc_p->assoc_id, @@ -122,7 +122,7 @@ int s1ap_eNB_handle_nas_first_req( s1ap_nas_first_req_p->selected_plmn_identity); if (mme_desc_p) { - S1AP_INFO("[eNB %d] Chose MME '%s' (assoc_id %d) through selected PLMN Identity index %d MCC %d MNC %d\n", + S1AP_INFO("[eNB %ld] Chose MME '%s' (assoc_id %d) through selected PLMN Identity index %d MCC %d MNC %d\n", instance, mme_desc_p->mme_name, mme_desc_p->assoc_id, @@ -138,11 +138,11 @@ int s1ap_eNB_handle_nas_first_req( * identity, selects the MME with the highest capacity. */ mme_desc_p = s1ap_eNB_nnsf_select_mme( - instance_p, - s1ap_nas_first_req_p->establishment_cause); + instance_p, + s1ap_nas_first_req_p->establishment_cause); if (mme_desc_p) { - S1AP_INFO("[eNB %d] Chose MME '%s' (assoc_id %d) through highest relative capacity\n", + S1AP_INFO("[eNB %ld] Chose MME '%s' (assoc_id %d) through highest relative capacity\n", instance, mme_desc_p->mme_name, mme_desc_p->assoc_id); @@ -358,10 +358,18 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.DownlinkNASTransport; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true); + if(ie == NULL) + { + return -1; + } mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true); + if(ie == NULL) + { + return -1; + } enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID; if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance, @@ -416,6 +424,10 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_NAS_PDU, true); + if(ie == NULL) + { + return -1; + } /* Forward the NAS PDU to RRC */ s1ap_eNB_itti_send_nas_downlink_ind(s1ap_eNB_instance->instance, ue_desc_p->ue_initial_id, @@ -494,9 +506,9 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_ ie->criticality = S1AP_Criticality_ignore; ie->value.present = S1AP_UplinkNASTransport_IEs__value_PR_EUTRAN_CGI; MCC_MNC_TO_PLMNID( - s1ap_eNB_instance_p->mcc[ue_context_p->selected_plmn_identity], - s1ap_eNB_instance_p->mnc[ue_context_p->selected_plmn_identity], - s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->selected_plmn_identity], + s1ap_eNB_instance_p->mcc[ue_context_p->mme_ref->broadcast_plmn_index[0]], + s1ap_eNB_instance_p->mnc[ue_context_p->mme_ref->broadcast_plmn_index[0]], + s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->mme_ref->broadcast_plmn_index[0]], &ie->value.choice.EUTRAN_CGI.pLMNidentity); //#warning "TODO get cell id from RRC" MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id, @@ -935,7 +947,7 @@ int s1ap_eNB_e_rab_setup_resp(instance_t instance, /* Prepare the S1AP message to encode */ memset(&pdu, 0, sizeof(pdu)); pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome; - pdu.choice.successfulOutcome.procedureCode = S1AP_ProcedureCode_id_E_RABModify; + pdu.choice.successfulOutcome.procedureCode = S1AP_ProcedureCode_id_E_RABSetup; pdu.choice.successfulOutcome.criticality = S1AP_Criticality_reject; pdu.choice.successfulOutcome.value.present = S1AP_SuccessfulOutcome__value_PR_E_RABSetupResponse; out = &pdu.choice.successfulOutcome.value.choice.E_RABSetupResponse; @@ -1032,7 +1044,7 @@ int s1ap_eNB_e_rab_setup_resp(instance_t instance, break; } - S1AP_DEBUG("e_rab_modify_resp: failed e_rab ID %ld\n", item->value.choice.E_RABItem.e_RAB_ID); + S1AP_DEBUG("e_rab_setup_resp: failed e_rab ID %ld\n", item->value.choice.E_RABItem.e_RAB_ID); ASN_SEQUENCE_ADD(&ie->value.choice.E_RABList.list, item); } diff --git a/openair3/S1AP/s1ap_eNB_nnsf.c b/openair3/S1AP/s1ap_eNB_nnsf.c index 6319f6e054..a5a4e74734 100644 --- a/openair3/S1AP/s1ap_eNB_nnsf.c +++ b/openair3/S1AP/s1ap_eNB_nnsf.c @@ -36,15 +36,29 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB_nnsf.h" + +typedef struct MME_nnsf_inf { + struct s1ap_eNB_mme_data_s *mme_p; + uint64_t weight; +} MME_nnsf_inf_t; + struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, rrc_establishment_cause_t cause) { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - uint8_t current_capacity = 0; - + + uint16_t capacity_sum = 0; + MME_nnsf_inf_t mme_inf[10]; + int cnt; + int nb_mme = 0; + uint64_t weight = 0; + + memset(mme_inf, 0, sizeof(mme_inf)); + RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + capacity_sum = capacity_sum + mme_data_p->relative_mme_capacity; if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) { /* The association between MME and eNB is not ready for the moment, * go to the next known MME. @@ -69,7 +83,8 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, || (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) { continue; } - + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; /* At this point, the RRC establishment can be handled by the MME * even if it is in overload state. */ @@ -78,14 +93,27 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, continue; } } - - if (current_capacity < mme_data_p->relative_mme_capacity) { - /* We find a better MME, keep a reference to it */ - current_capacity = mme_data_p->relative_mme_capacity; - mme_highest_capacity_p = mme_data_p; - } } - + + if( nb_mme != 0 ) { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) { + mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; + mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); + } + mme_highest_capacity_p = mme_inf[0].mme_p; + weight = mme_inf[0].weight; + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) { + if( weight > mme_inf[cnt].weight ) { + mme_highest_capacity_p = mme_inf[cnt].mme_p; + weight = mme_inf[cnt].weight; + } + } + } else { + mme_highest_capacity_p = NULL; + } + if( mme_highest_capacity_p != NULL ) { + mme_highest_capacity_p->nb_calls++; + } return mme_highest_capacity_p; } @@ -96,8 +124,15 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - uint8_t current_capacity = 0; - + + uint16_t capacity_sum = 0; + MME_nnsf_inf_t mme_inf[10]; + int cnt; + int nb_mme = 0; + uint64_t weight = 0; + + memset(mme_inf, 0, sizeof(mme_inf)); + RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { struct served_gummei_s *gummei_p = NULL; struct plmn_identity_s *served_plmn_p = NULL; @@ -140,6 +175,8 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) { if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) && (served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) { + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; break; } } @@ -148,14 +185,27 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, } /* if we didn't find such a served PLMN, go on with the next MME */ if (!served_plmn_p) continue; - - if (current_capacity < mme_data_p->relative_mme_capacity) { - /* We find a better MME, keep a reference to it */ - current_capacity = mme_data_p->relative_mme_capacity; - mme_highest_capacity_p = mme_data_p; - } } + if( nb_mme != 0 ) { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) { + mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; + mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); + } + mme_highest_capacity_p = mme_inf[0].mme_p; + weight = mme_inf[0].weight; + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) { + if( weight > mme_inf[cnt].weight ) { + mme_highest_capacity_p = mme_inf[cnt].mme_p; + weight = mme_inf[cnt].weight; + } + } + } else { + mme_highest_capacity_p = NULL; + } + if( mme_highest_capacity_p != NULL ) { + mme_highest_capacity_p->nb_calls++; + } return mme_highest_capacity_p; } diff --git a/openair3/S1AP/s1ap_eNB_overload.c b/openair3/S1AP/s1ap_eNB_overload.c index 9358ae62bd..64d3fcdf65 100644 --- a/openair3/S1AP/s1ap_eNB_overload.c +++ b/openair3/S1AP/s1ap_eNB_overload.c @@ -62,8 +62,16 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id, S1AP_OverloadResponse_PR_overloadAction, S1AP_OverloadResponse_PR_overloadAction, 0, 0); } + else + { + return -1; + } /* Non UE-associated signalling -> stream 0 */ - DevCheck(stream == 0, stream, 0, 0); + if (stream != 0) { + S1AP_ERROR("[SCTP %d] Received s1 overload start on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { /* No MME context associated */ @@ -93,7 +101,11 @@ int s1ap_eNB_handle_overload_stop(uint32_t assoc_id, s1ap_eNB_mme_data_t *mme_desc_p; /* Non UE-associated signalling -> stream 0 */ - DevCheck(stream == 0, stream, 0, 0); + if (stream != 0) { + S1AP_ERROR("[SCTP %d] Received s1 overload stop on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { /* No MME context associated */ diff --git a/openair3/S1AP/s1ap_eNB_trace.c b/openair3/S1AP/s1ap_eNB_trace.c index 19f5059238..695eeb4ef8 100644 --- a/openair3/S1AP/s1ap_eNB_trace.c +++ b/openair3/S1AP/s1ap_eNB_trace.c @@ -121,6 +121,10 @@ int s1ap_eNB_handle_trace_start(uint32_t assoc_id, if (ie != NULL) { ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance, ie->value.choice.ENB_UE_S1AP_ID); + } + else + { + return -1; } if (ue_desc_p == NULL) { /* Could not find context associated with this eNB_ue_s1ap_id -> generate diff --git a/openair3/SCTP/sctp_default_values.h b/openair3/SCTP/sctp_default_values.h index 528ffb5a05..0f8f94dca9 100644 --- a/openair3/SCTP/sctp_default_values.h +++ b/openair3/SCTP/sctp_default_values.h @@ -24,8 +24,8 @@ #define SCTP_OUT_STREAMS (16) #define SCTP_IN_STREAMS (16) -#define SCTP_MAX_ATTEMPTS (2) -#define SCTP_TIMEOUT (5) +#define SCTP_MAX_ATTEMPTS (8) +#define SCTP_TIMEOUT (60000) #define SCTP_RECV_BUFFER_SIZE (8192) #endif /* SCTP_DEFAULT_VALUES_H_ */ diff --git a/openair3/SCTP/sctp_eNB_itti_messaging.c b/openair3/SCTP/sctp_eNB_itti_messaging.c index 789af3f8ed..c31d4ba9ed 100644 --- a/openair3/SCTP/sctp_eNB_itti_messaging.c +++ b/openair3/SCTP/sctp_eNB_itti_messaging.c @@ -29,7 +29,7 @@ int sctp_itti_send_init_msg_multi_cnf(task_id_t task_id, instance_t instance, in MessageDef *message_p; sctp_init_msg_multi_cnf_t *sctp_init_msg_multi_cnf_p; - message_p = itti_alloc_new_message(TASK_SCTP, SCTP_INIT_MSG_MULTI_CNF); + message_p = itti_alloc_new_message(TASK_SCTP, 0, SCTP_INIT_MSG_MULTI_CNF); sctp_init_msg_multi_cnf_p = &message_p->ittiMsg.sctp_init_msg_multi_cnf; @@ -45,7 +45,7 @@ int sctp_itti_send_new_message_ind(task_id_t task_id, instance_t instance, MessageDef *message_p; sctp_data_ind_t *sctp_data_ind_p; - message_p = itti_alloc_new_message(TASK_SCTP, SCTP_DATA_IND); + message_p = itti_alloc_new_message(TASK_SCTP, 0, SCTP_DATA_IND); sctp_data_ind_p = &message_p->ittiMsg.sctp_data_ind; @@ -69,7 +69,7 @@ int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance, MessageDef *message_p; sctp_new_association_resp_t *sctp_new_association_resp_p; - message_p = itti_alloc_new_message(TASK_SCTP, SCTP_NEW_ASSOCIATION_RESP); + message_p = itti_alloc_new_message(TASK_SCTP, 0, SCTP_NEW_ASSOCIATION_RESP); sctp_new_association_resp_p = &message_p->ittiMsg.sctp_new_association_resp; @@ -89,7 +89,7 @@ int sctp_itti_send_association_ind(task_id_t task_id, instance_t instance, MessageDef *message_p; sctp_new_association_ind_t *sctp_new_association_ind_p; - message_p = itti_alloc_new_message(TASK_SCTP, SCTP_NEW_ASSOCIATION_IND); + message_p = itti_alloc_new_message(TASK_SCTP, 0, SCTP_NEW_ASSOCIATION_IND); sctp_new_association_ind_p = &message_p->ittiMsg.sctp_new_association_ind; diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index 972bef0a07..a14d4b9780 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -270,7 +270,7 @@ sctp_handle_new_association_req_multi( sctp_new_association_req_p->remote_address.ipv6_address); //close(sd); //return; - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error"); } SCTP_DEBUG("Converted ipv6 address %*s to network type\n", @@ -290,7 +290,7 @@ sctp_handle_new_association_req_multi( sctp_new_association_req_p->remote_address.ipv4_address); //close(sd); //return; - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error"); } SCTP_DEBUG("Converted ipv4 address %*s to network type\n", @@ -329,7 +329,7 @@ sctp_handle_new_association_req_multi( if (ns == -1) { perror("sctp_peeloff"); printf("sctp_peeloff: sd=%d assoc_id=%d\n", sd, assoc_id); - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: sctp_peeloff error"); } sctp_cnx = calloc(1, sizeof(*sctp_cnx)); @@ -364,7 +364,7 @@ sctp_handle_new_association_req( int sd = 0; int32_t assoc_id = 0; - struct sctp_event_subscribe events; + struct sctp_event_subscribe events={0}; struct sctp_cnx_list_elm_s *sctp_cnx = NULL; enum sctp_connection_type_e connection_type = SCTP_TYPE_CLIENT; @@ -413,10 +413,16 @@ sctp_handle_new_association_req( } /* Subscribe to all events */ - memset((void *)&events, 1, sizeof(struct sctp_event_subscribe)); + events.sctp_data_io_event = 1; + events.sctp_association_event = 1; + events.sctp_address_event = 1; + events.sctp_send_failure_event = 1; + events.sctp_peer_error_event = 1; + events.sctp_shutdown_event = 1; + events.sctp_partial_delivery_event = 1; if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &events, - sizeof(struct sctp_event_subscribe)) < 0) { + 8) < 0) { SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n", strerror(errno)); close(sd); @@ -759,10 +765,16 @@ static int sctp_create_new_listener( } } - memset((void *)&event, 1, sizeof(struct sctp_event_subscribe)); + event.sctp_data_io_event = 1; + event.sctp_association_event = 1; + event.sctp_address_event = 1; + event.sctp_send_failure_event = 1; + event.sctp_peer_error_event = 1; + event.sctp_shutdown_event = 1; + event.sctp_partial_delivery_event = 1; if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &event, - sizeof(struct sctp_event_subscribe)) < 0) { + 8) < 0) { SCTP_ERROR("setsockopt: %s:%d\n", strerror(errno), errno); if (sd != -1) { close(sd); @@ -931,10 +943,12 @@ sctp_eNB_read_from_socket( &sinfo, &flags); if (n < 0) { - if (errno == ENOTCONN) { + if( (errno == ENOTCONN) || (errno == ECONNRESET) || (errno == ETIMEDOUT) || (errno == ECONNREFUSED) ) + { itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd); SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd); + SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno); sctp_itti_send_association_resp( sctp_cnx->task_id, sctp_cnx->instance, -1, @@ -957,7 +971,7 @@ sctp_eNB_read_from_socket( if (!(flags & MSG_EOR)) { SCTP_ERROR("fatal: partial SCTP messages are not handled\n"); - exit(1); + exit_fun("fatal: partial SCTP messages are not handled" ); } if (flags & MSG_NOTIFICATION) { @@ -971,6 +985,7 @@ sctp_eNB_read_from_socket( if (SCTP_SHUTDOWN_EVENT == snp->sn_header.sn_type) { itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd); + SCTP_WARN("Received SCTP SHUTDOWN EVENT\n"); close(sctp_cnx->sd); sctp_itti_send_association_resp( @@ -1012,7 +1027,14 @@ sctp_eNB_read_from_socket( break; default: - SCTP_WARN("unhandled: SCTP_ASSOC_CHANGE to %d\n", sctp_assoc_changed->sac_state); + if ( sctp_assoc_changed->sac_state == SCTP_SHUTDOWN_COMP) + SCTP_WARN("SCTP_ASSOC_CHANGE to SSCTP_SHUTDOWN_COMP\n"); + if ( sctp_assoc_changed->sac_state == SCTP_RESTART) + SCTP_WARN("SCTP_ASSOC_CHANGE to SCTP_RESTART\n"); + if ( sctp_assoc_changed->sac_state == SCTP_CANT_STR_ASSOC) + SCTP_ERROR("SCTP_ASSOC_CHANGE to SCTP_CANT_STR_ASSOC\n"); + if ( sctp_assoc_changed->sac_state == SCTP_COMM_LOST) + SCTP_ERROR("SCTP_ASSOC_CHANGE to SCTP_COMM_LOST\n"); break; } } @@ -1104,7 +1126,7 @@ void *sctp_eNB_process_itti_msg(void *notUsed) /* We received a new connection request */ if (sctp_create_new_listener( - ITTI_MESSAGE_GET_INSTANCE(received_msg), + ITTI_MSG_DESTINATION_INSTANCE(received_msg), ITTI_MSG_ORIGIN_ID(received_msg), &received_msg->ittiMsg.sctp_init,0) < 0) { /* SCTP socket creation or bind failed... */ @@ -1119,7 +1141,7 @@ void *sctp_eNB_process_itti_msg(void *notUsed) SCTP_DEBUG("Received SCTP_INIT_MSG_MULTI_REQ\n"); multi_sd = sctp_create_new_listener( - ITTI_MESSAGE_GET_INSTANCE(received_msg), + ITTI_MSG_DESTINATION_INSTANCE(received_msg), ITTI_MSG_ORIGIN_ID(received_msg), &received_msg->ittiMsg.sctp_init_multi,1); /* We received a new connection request */ @@ -1129,27 +1151,27 @@ void *sctp_eNB_process_itti_msg(void *notUsed) } sctp_itti_send_init_msg_multi_cnf( ITTI_MSG_ORIGIN_ID(received_msg), - ITTI_MESSAGE_GET_INSTANCE(received_msg), + ITTI_MSG_DESTINATION_INSTANCE(received_msg), multi_sd); } break; case SCTP_NEW_ASSOCIATION_REQ: { - sctp_handle_new_association_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), + sctp_handle_new_association_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg), ITTI_MSG_ORIGIN_ID(received_msg), &received_msg->ittiMsg.sctp_new_association_req); } break; case SCTP_NEW_ASSOCIATION_REQ_MULTI: { - sctp_handle_new_association_req_multi(ITTI_MESSAGE_GET_INSTANCE(received_msg), + sctp_handle_new_association_req_multi(ITTI_MSG_DESTINATION_INSTANCE(received_msg), ITTI_MSG_ORIGIN_ID(received_msg), &received_msg->ittiMsg.sctp_new_association_req_multi); } break; case SCTP_CLOSE_ASSOCIATION: - sctp_close_association(ITTI_MESSAGE_GET_INSTANCE(received_msg), + sctp_close_association(ITTI_MSG_DESTINATION_INSTANCE(received_msg), ITTI_MSG_ORIGIN_ID(received_msg), &received_msg->ittiMsg.sctp_close_association); break; @@ -1160,7 +1182,7 @@ void *sctp_eNB_process_itti_msg(void *notUsed) break; case SCTP_DATA_REQ: { - sctp_send_data(ITTI_MESSAGE_GET_INSTANCE(received_msg), + sctp_send_data(ITTI_MSG_DESTINATION_INSTANCE(received_msg), ITTI_MSG_ORIGIN_ID(received_msg), &received_msg->ittiMsg.sctp_data_req); } diff --git a/openair3/SCTP/sctp_primitives_client.c b/openair3/SCTP/sctp_primitives_client.c deleted file mode 100644 index bb71a854e1..0000000000 --- a/openair3/SCTP/sctp_primitives_client.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -//WARNING: sctp requires libsctp-dev and -lsctp as linker option -#include -#include - -#include "assertions.h" -#include "sctp_eNB_defs.h" -#include "sctp_common.h" - -#include "sctp_primitives_client.h" - -#if defined(ENB_MODE) -# include "eNB_default_values.h" -#else -# include "mme_default_values.h" -#endif - -/* Send buffer to SCTP association */ -int sctp_send_msg(sctp_data_t *sctp_data_p, uint16_t ppid, uint16_t stream, - const uint8_t *buffer, const uint32_t length) -{ - DevAssert(buffer != NULL); - DevAssert(sctp_data_p != NULL); - - /* Send message on specified stream of the sd association - * NOTE: PPID should be defined in network order - */ - if (sctp_sendmsg(sctp_data_p->sd, (const void *)buffer, length, NULL, 0, - htonl(ppid), 0, stream, 0, 0) < 0) { - SCTP_ERROR("Sctp_sendmsg failed: %s\n", strerror(errno)); - return -1; - } - - SCTP_DEBUG("Successfully sent %d bytes to port %d on stream %d\n", - length, sctp_data_p->remote_port, stream); - - return 0; -} - -static -int sctp_handle_notifications(union sctp_notification *snp) -{ - if (SCTP_SHUTDOWN_EVENT == snp->sn_header.sn_type) { - /* Client deconnection */ - SCTP_DEBUG("Notification received: server deconnected\n"); - } else if (SCTP_ASSOC_CHANGE == snp->sn_header.sn_type) { - /* Association has changed */ - SCTP_DEBUG("Notification received: server association changed\n"); - } else { - SCTP_DEBUG("Notification received: %d TODO\n", snp->sn_header.sn_type); - } - - /* TODO: handle more notif here */ - return 0; -} - -int sctp_run(sctp_data_t *sctp_data_p) -{ - int ret, repeat = 1; - int total_size = 0; - int sd; - struct pollfd fds; - - DevAssert(sctp_data_p != NULL); - - sd = sctp_data_p->sd; - - memset(&fds, 0, sizeof(struct pollfd)); - - fds.fd = sd; - fds.events = POLLIN; - - while (repeat == 1) { - ret = poll(&fds, 1, 0); - - if (ret < 0) { - SCTP_ERROR("[SD %d] Poll has failed (%d:%s)\n", - sd, errno, strerror(errno)); - return errno; - } else if (ret == 0) { - /* No data to read, just leave the loop */ - SCTP_DEBUG("[SD %d] Poll: no data available\n", sd); - repeat = 0; - } else { - /* Socket has some data to read */ - uint8_t buffer[SCTP_RECV_BUFFER_SIZE]; - int flags = 0; - int n; - struct sockaddr_in addr; - struct sctp_sndrcvinfo sinfo; - - socklen_t from_len; - memset((void *)&addr, 0, sizeof(struct sockaddr_in)); - from_len = (socklen_t)sizeof(struct sockaddr_in); - memset((void *)&sinfo, 0, sizeof(struct sctp_sndrcvinfo)); - - n = sctp_recvmsg(sd, (void *)buffer, SCTP_RECV_BUFFER_SIZE, - (struct sockaddr *)&addr, &from_len, - &sinfo, &flags); - - if (n < 0) { - /* Other peer is deconnected */ - SCTP_ERROR("[SD %d] An error occured during read (%d:%s)\n", - sd, errno, strerror(errno)); - return 0; - } - - if (flags & MSG_NOTIFICATION) { - sctp_handle_notifications((union sctp_notification *)buffer); - } else { - struct sctp_queue_item_s *new_item_p; - - new_item_p = calloc(1, sizeof(struct sctp_queue_item_s)); - /* Normal data received */ - SCTP_DEBUG("[SD %d] Msg of length %d received from %s:%u on " - "stream %d, PPID %d, assoc_id %d\n", - sd, n, inet_ntoa(addr.sin_addr), - ntohs(addr.sin_port), sinfo.sinfo_stream, - sinfo.sinfo_ppid, sinfo.sinfo_assoc_id); - - new_item_p->local_stream = sinfo.sinfo_stream; - new_item_p->remote_port = ntohs(addr.sin_port); - new_item_p->remote_addr = addr.sin_addr.s_addr; - new_item_p->ppid = sinfo.sinfo_ppid; - new_item_p->assoc_id = sinfo.sinfo_assoc_id; - new_item_p->length = n; - new_item_p->buffer = malloc(sizeof(uint8_t) * n); - - memcpy(new_item_p->buffer, buffer, n); - - /* Insert the new packet at the tail of queue. */ - TAILQ_INSERT_TAIL(&sctp_data_p->sctp_queue, new_item_p, entry); - - /* Update queue related data */ - sctp_data_p->queue_size += n; - sctp_data_p->queue_length++; - total_size += n; - } - } - } - - return total_size; -} - -int sctp_connect_to_remote_host(char *local_ip_addr[], - int nb_local_addr, - char *remote_ip_addr, - uint16_t port, - int socket_type, - sctp_data_t *sctp_data_p) -{ - int sd = -1; - socklen_t i = 0; - - struct sctp_initmsg init; - struct sctp_event_subscribe events; - struct sockaddr *bindx_add_addr; - - DevAssert(sctp_data_p != NULL); - DevAssert(remote_ip_addr != NULL); - DevAssert(local_ip_addr != NULL); - DevCheck((socket_type == SOCK_STREAM), socket_type, 0, 0); - - SCTP_DEBUG("Creating socket type %d\n", socket_type); - - /* Create new socket */ - if ((sd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) { - SCTP_ERROR("Socket creation failed: %s\n", strerror(errno)); - return -1; - } - - /* Bind to provided IP adresses */ - bindx_add_addr = calloc(nb_local_addr, sizeof(struct sockaddr)); - - for (i = 0; i < nb_local_addr; i++) { - if (inet_pton(AF_INET, local_ip_addr[i], &((struct sockaddr_in*)&bindx_add_addr[i])->sin_addr.s_addr) != 1) { - if (inet_pton(AF_INET6, local_ip_addr[i], &((struct sockaddr_in6*)&bindx_add_addr[i])->sin6_addr.s6_addr) != 1) { - continue; - } else { - ((struct sockaddr_in6*)&bindx_add_addr[i])->sin6_port = 0; - bindx_add_addr[i].sa_family = AF_INET6; - } - } else { - ((struct sockaddr_in*)&bindx_add_addr[i])->sin_port = 0; - bindx_add_addr[i].sa_family = AF_INET; - } - } - - if (sctp_bindx(sd, bindx_add_addr, nb_local_addr, SCTP_BINDX_ADD_ADDR) < 0) { - SCTP_ERROR("Socket bind failed: %s\n", strerror(errno)); - return -1; - } - - memset((void *)&init, 0, sizeof(struct sctp_initmsg)); - - /* Request a number of in/out streams */ - init.sinit_num_ostreams = SCTP_OUT_STREAMS; - init.sinit_max_instreams = SCTP_IN_STREAMS; - init.sinit_max_attempts = SCTP_MAX_ATTEMPTS; - - SCTP_DEBUG("Requesting (%d %d) (in out) streams\n", init.sinit_num_ostreams, - init.sinit_max_instreams); - - if (setsockopt(sd, IPPROTO_SCTP, SCTP_INITMSG, - &init, (socklen_t)sizeof(struct sctp_initmsg)) < 0) { - SCTP_ERROR("Setsockopt IPPROTO_SCTP_INITMSG failed: %s\n", - strerror(errno)); - return -1; - } - - /* Subscribe to all events */ - memset((void *)&events, 1, sizeof(struct sctp_event_subscribe)); - - if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &events, - sizeof(struct sctp_event_subscribe)) < 0) { - SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n", - strerror(errno)); - return -1; - } - - /* SOCK_STREAM socket type requires an explicit connect to the remote host - * address and port. - * Only use IPv4 for the first connection attempt - */ - { - struct sockaddr_in addr; - - memset(&addr, 0, sizeof(struct sockaddr_in)); - - if (inet_pton(AF_INET, remote_ip_addr, &addr.sin_addr.s_addr) != 1) { - SCTP_ERROR("Failed to convert ip address %s to network type\n", remote_ip_addr); - goto err; - } - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - - SCTP_DEBUG("[%d] Sending explicit connect to %s:%u\n", sd, remote_ip_addr, - port); - - /* Connect to remote host and port */ - if (sctp_connectx(sd, (struct sockaddr *)&addr, 1, NULL) < 0) { - SCTP_ERROR("Connect to %s:%u failed: %s\n", remote_ip_addr, - port, strerror(errno)); - goto err; - } - } - - /* Get SCTP status */ - sctp_get_sockinfo(sd, &sctp_data_p->instreams, &sctp_data_p->outstreams, - &sctp_data_p->assoc_id); - - sctp_data_p->sd = sd; - - sctp_get_peeraddresses(sd, &sctp_data_p->remote_ip_addresses, &sctp_data_p->nb_remote_addresses); - sctp_get_localaddresses(sd, NULL, NULL); - - TAILQ_INIT(&sctp_data_p->sctp_queue); - - return sd; - -err: - - if (sd != 0) { - close(sd); - } - - return -1; -} diff --git a/openair3/SCTP/sctp_primitives_client.h b/openair3/SCTP/sctp_primitives_client.h deleted file mode 100644 index bec4d3ed95..0000000000 --- a/openair3/SCTP/sctp_primitives_client.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include - -#include "sctp_eNB_defs.h" - -#ifndef SCTP_PRIMITIVES_CLIENT_H_ -#define SCTP_PRIMITIVES_CLIENT_H_ - -/** @defgroup _sctp_impl_ SCTP Layer Reference Implementation - * @ingroup _ref_implementation_ - * @{ - */ - -/** \brief SCTP recv callback prototype. Will be called every time a message is - * received on socket. - * \param assocId SCTP association ID - * \param stream SCTP stream on which data had been received - * \param buffer Pointer to data (should be freed by user) - * \param length Length of message received - * @return Execution result - */ -typedef int (*sctp_recv_callback)(uint32_t assocId, - uint32_t stream, - uint8_t *buffer, - uint32_t length); - -/** \brief SCTP connected callback prototype. Will be called once the - * association is ready. - * \param args argument provided by upper layer - * \param assocId SCTP association ID - * \param instreams Number of input streams negotiated with remote peer - * \param outstreams Number of output streams negotiated with remote peer - * @return Execution result - */ -typedef int (*sctp_connected_callback)(void *args, - uint32_t assocId, - uint32_t instreams, - uint32_t outstreams); - -/** \brief Perform association to a remote peer - * \param ip_addr Peer IPv4 address - * \param port Remote port to connect to - * \param args Upper layer args that will be provided to connected callback - * \param connected_callback Connected callback - * \param recv_callback Data received callback - * @return < 0 in case of failure - */ -int sctp_connect_to_remote_host(char *local_ip_addr[], - int nb_local_addr, - char *remote_ip_addr, - uint16_t port, - int socket_type, - sctp_data_t *sctp_data_p); - -/** \brief Send message over SCTP - * \param sctp_data_p Pointer to the SCTP desc - * \param ppid Payload Protocol Identifier - * \param stream SCTP stream on which data will be sent - * \param buffer Pointer to buffer - * \param length Buffer length - * @return < 0 in case of failure - */ -int sctp_send_msg(sctp_data_t *sctp_data_p, uint16_t ppid, uint16_t stream, - const uint8_t *buffer, const uint32_t length); - -/** \brief Flush the FIFO of messages from the socket - * \param sctp_data_p - * @return < 0 in case of failure - */ -int sctp_run(sctp_data_t *sctp_data_p); - -/** \brief Properly disconnect the peer - * \param assoc_id The SCTP association ID - * @return < 0 in case of failure - */ -void sctp_disconnect(uint32_t assoc_id); - -void sctp_terminate(void); - -/* @} */ -#endif /* SCTP_PRIMITIVES_CLIENT_H_ */ diff --git a/openair3/TEST/EPC_TEST/play_scenario.c b/openair3/TEST/EPC_TEST/play_scenario.c index 3af47f21a8..ebaffdb39e 100644 --- a/openair3/TEST/EPC_TEST/play_scenario.c +++ b/openair3/TEST/EPC_TEST/play_scenario.c @@ -729,7 +729,7 @@ void *et_eNB_app_task(void *args_p) itti_receive_msg (TASK_ENB_APP, &msg_p); msg_name = ITTI_MSG_NAME (msg_p); - instance = ITTI_MSG_INSTANCE (msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: @@ -1204,7 +1204,7 @@ int main( int argc, char **argv ) logInit(); set_glog(LOG_TRACE, LOG_MED); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + itti_init(TASK_MAX, tasks_info); set_comp_log(ENB_APP, LOG_TRACE, LOG_MED, 1); set_comp_log(S1AP, LOG_TRACE, LOG_MED, 1); diff --git a/openair3/TEST/EPC_TEST/play_scenario_s1ap.c b/openair3/TEST/EPC_TEST/play_scenario_s1ap.c index acc9b18f76..c4674e8901 100644 --- a/openair3/TEST/EPC_TEST/play_scenario_s1ap.c +++ b/openair3/TEST/EPC_TEST/play_scenario_s1ap.c @@ -1101,13 +1101,13 @@ void *et_s1ap_eNB_task(void *arg) * Each eNB has to send an S1AP_REGISTER_ENB message with its * own parameters. */ - et_s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), + et_s1ap_eNB_handle_register_eNB(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_REGISTER_ENB_REQ(received_msg)); } break; case SCTP_NEW_ASSOCIATION_RESP: { - et_s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + et_s1ap_eNB_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); } break; diff --git a/openair3/TEST/oaisim_mme_itti_test.c b/openair3/TEST/oaisim_mme_itti_test.c index 57cfd412ef..ecfbdb0acb 100644 --- a/openair3/TEST/oaisim_mme_itti_test.c +++ b/openair3/TEST/oaisim_mme_itti_test.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) /* Calling each layer init function */ log_init(&mme_config); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + itti_init(TASK_MAX, tasks_info); sctp_init(&mme_config); udp_init(&mme_config); s1ap_mme_init(&mme_config); diff --git a/openair3/TEST/oaisim_mme_test_s1c.c b/openair3/TEST/oaisim_mme_test_s1c.c index 52623463c6..94a554ab5f 100644 --- a/openair3/TEST/oaisim_mme_test_s1c.c +++ b/openair3/TEST/oaisim_mme_test_s1c.c @@ -193,7 +193,7 @@ static void *eNB_app_task(void *args_p) itti_receive_msg (TASK_ENB_APP, &msg_p); msg_name = ITTI_MSG_NAME (msg_p); - instance = ITTI_MSG_INSTANCE (msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: @@ -309,7 +309,7 @@ int main( int argc, char **argv ) /* Read eNB configuration file */ enb_properties = enb_config_init(conf_config_file_name); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + itti_init(TASK_MAX, tasks_info); itti_wait_ready(1); diff --git a/openair3/TEST/oaisim_mme_test_s1c_s1ap.c b/openair3/TEST/oaisim_mme_test_s1c_s1ap.c index 10d43d595d..60da125073 100644 --- a/openair3/TEST/oaisim_mme_test_s1c_s1ap.c +++ b/openair3/TEST/oaisim_mme_test_s1c_s1ap.c @@ -260,13 +260,13 @@ void *s1ap_eNB_task(void *arg) * Each eNB has to send an S1AP_REGISTER_ENB message with its * own parameters. */ - s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_handle_register_eNB(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &S1AP_REGISTER_ENB_REQ(received_msg)); } break; case SCTP_NEW_ASSOCIATION_RESP: { - s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), + s1ap_eNB_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); } break; diff --git a/openair3/TEST/test5Gnas.c b/openair3/TEST/test5Gnas.c new file mode 100644 index 0000000000..5124ad6e4d --- /dev/null +++ b/openair3/TEST/test5Gnas.c @@ -0,0 +1,34 @@ +#include +#include + +volatile int oai_exit; + +int main(int argc, char **argv) { + if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + + logInit(); + char *resp; + nr_user_nas_t UErrc= {0}; + NRUEcontext_t UEnas= {0}; + // Network generate identity request after a sucessfull radio attach + int size=identityRequest((void **)&resp, &UEnas); + log_dump(NAS, resp, size, LOG_DUMP_CHAR," identity Request:\n" ); + // UE process the message that it has received from phy layer in a "DL transfer" message + UEprocessNAS(resp, &UErrc); + // UE Scheduler should later call the response + size=identityResponse((void **)&resp, &UErrc); + log_dump(NAS, resp, size, LOG_DUMP_CHAR," identity Response:\n" ); + // Now the gNB process the identity response + processNAS(resp, &UEnas); + // gNB scheduler should call the next query + size=authenticationRequest((void **)&resp, &UEnas); + log_dump(NAS, resp, size, LOG_DUMP_CHAR," authentication request:\n" ); + // as above + UEprocessNAS(resp, &UErrc); + size=authenticationResponse((void **)&resp, &UErrc); + log_dump(NAS, resp, size, LOG_DUMP_CHAR," authentication response:\n" ); + processNAS(resp, &UEnas); + return 0; +} diff --git a/openair3/UDP/udp_eNB_task.c b/openair3/UDP/udp_eNB_task.c index 90ee87900d..05729ba6b1 100644 --- a/openair3/UDP/udp_eNB_task.c +++ b/openair3/UDP/udp_eNB_task.c @@ -169,8 +169,8 @@ int udp_eNB_create_socket(int port, char *ip_addr, task_id_t task_id) if ((rc = bind(sd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in))) < 0) { close(sd); - AssertFatal(rc >= 0, "UDP: Failed to bind socket: (%s:%d) address %s port %d\n", - strerror(errno), errno, ip_addr, port); + LOG_E(UDP_, "Failed to bind socket: (%s:%d) address %s port %d\n", strerror(errno), errno, ip_addr, port); + return -1; } /* Create a new descriptor for this connection */ @@ -257,7 +257,7 @@ void udp_eNB_receiver(struct udp_socket_desc_s *udp_sock_pP) forwarded_buffer = itti_malloc(TASK_UDP, udp_sock_pP->task_id, n*sizeof(uint8_t)); DevAssert(forwarded_buffer != NULL); memcpy(forwarded_buffer, l_buffer, n); - message_p = itti_alloc_new_message(TASK_UDP, UDP_DATA_IND); + message_p = itti_alloc_new_message(TASK_UDP, 0, UDP_DATA_IND); DevAssert(message_p != NULL); udp_data_ind_p = &message_p->ittiMsg.udp_data_ind; udp_data_ind_p->buffer = forwarded_buffer; @@ -318,7 +318,7 @@ void *udp_eNB_task(void *args_p) if (received_message_p != NULL) { //msg_name = ITTI_MSG_NAME (received_message_p); - //instance = ITTI_MSG_INSTANCE (received_message_p); + //instance = ITTI_MSG_DESTINATION_INSTANCE (received_message_p); switch (ITTI_MSG_ID(received_message_p)) { case UDP_INIT: { diff --git a/openair3/UICC/usim_interface.c b/openair3/UICC/usim_interface.c new file mode 100644 index 0000000000..5d04f88285 --- /dev/null +++ b/openair3/UICC/usim_interface.c @@ -0,0 +1,111 @@ +/* +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* 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. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org +*/ +#include + +#include +#include +extern uint16_t NB_UE_INST; + +#define UICC_SECTION "uicc" +#define UICC_CONFIG_HELP_OPTIONS " list of comma separated options to interface a simulated (real UICC to be developped). Available options: \n"\ + " imsi: user imsi\n"\ + " key: cyphering key\n"\ + " opc: cyphering OPc\n" +/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* configuration parameters for the rfsimulator device */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define UICC_PARAMS_DESC {\ + {"imsi", "USIM IMSI\n", 0, strptr:&(uicc->imsiStr), defstrval:"2089900007487", TYPE_STRING, 0 },\ + {"nmc_size" "number of digits in NMC", 0, iptr:&(uicc->nmc_size), defintval:2, TYPE_INT, 0 },\ + {"key", "USIM Ki\n", 0, strptr:&(uicc->keyStr), defstrval:"fec86ba6eb707ed08905757b1bb44b8f", TYPE_STRING, 0 },\ + {"opc", "USIM OPc\n", 0, strptr:&(uicc->opcStr), defstrval:"c42449363bbad02b66d16bc975d77cc1", TYPE_STRING, 0 },\ + {"amf", "USIM amf\n", 0, strptr:&(uicc->amfStr), defstrval:"8000", TYPE_STRING, 0 },\ + {"sqn", "USIM sqn\n", 0, strptr:&(uicc->sqnStr), defstrval:"000000", TYPE_STRING, 0 },\ + {"dnn", "UE dnn (apn)\n", 0, strptr:&(uicc->dnnStr), defstrval:"oai", TYPE_STRING, 0 },\ + {"nssai_sst", "UE nssai\n", 0, iptr:&(uicc->nssai_sst), defintval:1, TYPE_INT, 0 }, \ + {"nssai_sd", "UE nssai\n", 0, iptr:&(uicc->nssai_sd), defintval:1, TYPE_INT, 0 }, \ + }; + +static uicc_t** uiccArray=NULL; + +const char *hexTable="0123456789abcdef"; +static inline uint8_t mkDigit(unsigned char in) { + for (int i=0; i<16; i++) + if (tolower(in)==hexTable[i]) + return i; + LOG_E(SIM,"Impossible hexa input: %c\n",in); + return 0; +} + +static inline void to_hex(char *in, uint8_t *out, int size) { + for (size_t i=0; in[i]!=0 && i < size*2 ; i+=2) { + *out++=(mkDigit(in[i]) << 4) | mkDigit(in[i+1]); + } +} + +uicc_t *init_uicc(char *sectionName) { + uicc_t *uicc=(uicc_t *)calloc(sizeof(uicc_t),1); + paramdef_t uicc_params[] = UICC_PARAMS_DESC; + // here we call usim simulation, but calling actual usim is quite simple + // the code is in open-cells.com => program_uicc open source + // we can read the IMSI from the USIM + // key, OPc, sqn, amf don't need to be read from the true USIM + int ret = config_get( uicc_params,sizeof(uicc_params)/sizeof(paramdef_t),sectionName); + AssertFatal(ret >= 0, "configuration couldn't be performed for uicc name: %s", sectionName); + LOG_I(SIM, "UICC simulation: IMSI=%s, Ki=%s, OPc=%s\n", uicc->imsiStr, uicc->keyStr, uicc->opcStr); + to_hex(uicc->keyStr,uicc->key, sizeof(uicc->key) ); + to_hex(uicc->opcStr,uicc->opc, sizeof(uicc->opc) ); + to_hex(uicc->sqnStr,uicc->sqn, sizeof(uicc->sqn) ); + to_hex(uicc->amfStr,uicc->amf, sizeof(uicc->amf) ); + return uicc; +} + +void uicc_milenage_generate(uint8_t *autn, uicc_t *uicc) { + // here we call usim simulation, but calling actual usim is quite simple + // the code is in open-cells.com => program_uicc open source + milenage_generate(uicc->opc, uicc->amf, uicc->key, + uicc->sqn, uicc->rand, autn, uicc->ik, uicc->ck, uicc->milenage_res); + log_dump(SIM,uicc->opc,sizeof(uicc->opc), LOG_DUMP_CHAR,"opc:"); + log_dump(SIM,uicc->amf,sizeof(uicc->amf), LOG_DUMP_CHAR,"amf:"); + log_dump(SIM,uicc->key,sizeof(uicc->key), LOG_DUMP_CHAR,"key:"); + log_dump(SIM,uicc->sqn,sizeof(uicc->sqn), LOG_DUMP_CHAR,"sqn:"); + log_dump(SIM,uicc->rand,sizeof(uicc->rand), LOG_DUMP_CHAR,"rand:"); + log_dump(SIM,uicc->ik,sizeof(uicc->ik), LOG_DUMP_CHAR,"milenage output ik:"); + log_dump(SIM,uicc->ck,sizeof(uicc->ck), LOG_DUMP_CHAR,"milenage output ck:"); + log_dump(SIM,uicc->milenage_res,sizeof(uicc->milenage_res), LOG_DUMP_CHAR,"milenage output res:"); + log_dump(SIM,autn,sizeof(autn), LOG_DUMP_CHAR,"milenage output autn:"); +} + +uicc_t * checkUicc(int Mod_id) { + AssertFatal(Mod_id < NB_UE_INST, "Mod_id must be less than NB_UE_INST. Mod_id:%d NB_UE_INST:%d", Mod_id,NB_UE_INST); + if(uiccArray==NULL){ + uiccArray=(uicc_t **)calloc(1,sizeof(uicc_t*)*NB_UE_INST); + } + if (!uiccArray[Mod_id]) { + char uiccName[64]; + sprintf(uiccName,"uicc%d", Mod_id); + uiccArray[Mod_id]=(void*)init_uicc(uiccName); + } + return (uicc_t*) uiccArray[Mod_id]; +} diff --git a/openair3/UICC/usim_interface.h b/openair3/UICC/usim_interface.h new file mode 100644 index 0000000000..eb32a6bfc1 --- /dev/null +++ b/openair3/UICC/usim_interface.h @@ -0,0 +1,76 @@ +/* +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.comopenair3/UICC/usim_interface.h +* +* 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. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org +*/ +#ifndef USIM_INTERFACE_H +#define USIM_INTERFACE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common_lib.h" + +/* 3GPP glossary +RES RESponse +XRES eXpected RESponse +HRES Hash RESponse +HXRES Hash eXpected RESponse +So, RES can be either milenage res, or received response, so hash of milenage res +*/ + +typedef struct { + char *imsiStr; + char *keyStr; + char *opcStr; + char *amfStr; + char *sqnStr; + char *dnnStr; + int nssai_sst; + int nssai_sd; + uint8_t key[16]; + uint8_t opc[16]; + uint8_t amf[2]; + uint8_t sqn[6]; + int nmc_size; + uint8_t rand[16]; + uint8_t autn[16]; + uint8_t ak[6]; + uint8_t akstar[6]; + uint8_t ck[16]; + uint8_t ik[16]; + uint8_t milenage_res[8]; +} uicc_t; + +/* + * Read the configuration file, section name variable to be able to manage several UICC + */ +uicc_t *checkUicc(int Mod_id); +uicc_t *init_uicc(char *sectionName); +void uicc_milenage_generate(uint8_t * autn, uicc_t *uicc); +uicc_t * checkUicc(int Mod_id); +#endif diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index d28c9acccb..cfb2c8cdfc 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -81,6 +81,23 @@ do { \ ((buf)[1]); \ } while(0) +/* Convert an integer on 24 bits to the given bUFFER */ +#define INT24_TO_BUFFER(x, buf) \ +do { \ + (buf)[0] = (x) >> 16; \ + (buf)[1] = (x) >> 8; \ + (buf)[2] = (x); \ +} while(0) + +/* Convert an array of char containing vALUE to x */ +#define BUFFER_TO_INT24(buf, x) \ +do { \ + x = ((buf)[0] << 16) | \ + ((buf)[1] << 8 ) | \ + ((buf)[2]); \ +} while(0) + + /* Convert an integer on 32 bits to the given bUFFER */ #define INT32_TO_BUFFER(x, buf) \ do { \ @@ -126,6 +143,21 @@ do { \ (aSN)->bits_unused = 0; \ } while(0) + +#define INT24_TO_OCTET_STRING(x, aSN) \ +do { \ + (aSN)->buf = calloc(3, sizeof(uint8_t)); \ + INT24_TO_BUFFER(x, ((aSN)->buf)); \ + (aSN)->size = 3; \ +} while(0) + +#define INT24_TO_BIT_STRING(x, aSN) \ +do { \ + INT24_TO_OCTET_STRING(x, aSN); \ + (aSN)->bits_unused = 0; \ +} while(0) + + #define INT8_TO_OCTET_STRING(x, aSN) \ do { \ (aSN)->buf = calloc(1, sizeof(uint8_t)); \ @@ -137,6 +169,25 @@ do { \ #define M_TMSI_TO_OCTET_STRING INT32_TO_OCTET_STRING #define MME_GID_TO_OCTET_STRING INT16_TO_OCTET_STRING +#define AMF_REGION_TO_BIT_STRING(x, aSN) \ + do { \ + INT8_TO_OCTET_STRING(x, aSN); \ + (aSN)->bits_unused = 0; \ +} while(0) + +#define AMF_SETID_TO_BIT_STRING(x, aSN) \ + do { \ + INT16_TO_OCTET_STRING(x, aSN); \ + (aSN)->bits_unused = 6; \ +} while(0) + +#define AMF_POINTER_TO_BIT_STRING(x, aSN) \ + do { \ + INT8_TO_OCTET_STRING(x, aSN); \ + (aSN)->bits_unused = 2; \ +} while(0) + + #define ENCRALG_TO_BIT_STRING(encralg, bitstring) \ do { \ (bitstring)->size=2; \ @@ -197,6 +248,12 @@ do { \ BUFFER_TO_INT16((aSN)->buf, x); \ } while(0) +#define OCTET_STRING_TO_INT24(aSN, x) \ +do { \ + DevCheck((aSN)->size == 2 || (aSN)->size == 3, (aSN)->size, 0, 0); \ + BUFFER_TO_INT24((aSN)->buf, x); \ +} while(0) + #define OCTET_STRING_TO_INT32(aSN, x) \ do { \ DevCheck((aSN)->size == 4, (aSN)->size, 0, 0); \ @@ -445,6 +502,19 @@ do { \ (bITsTRING)->size = 3; \ (bITsTRING)->bits_unused = 4; \ } while(0) + + +#define MACRO_GNB_ID_TO_BIT_STRING(mACRO, bITsTRING) \ +do { \ + (bITsTRING)->buf = calloc(4, sizeof(uint8_t)); \ + (bITsTRING)->buf[0] = ((mACRO) >> 20); \ + (bITsTRING)->buf[1] = (mACRO) >> 12; \ + (bITsTRING)->buf[2] = (mACRO) >> 4; \ + (bITsTRING)->buf[3] = ((mACRO) & 0x0f) << 4; \ + (bITsTRING)->size = 4; \ + (bITsTRING)->bits_unused = 4; \ +} while(0) + /* TS 36.413 v10.9.0 section 9.2.1.38: * E-UTRAN CGI/Cell Identity * The leftmost bits of the Cell @@ -462,6 +532,19 @@ do { \ (bITsTRING)->bits_unused = 4; \ } while(0) +#define MACRO_GNB_ID_TO_CELL_IDENTITY(mACRO, cELL_iD, bITsTRING) \ +do { \ + (bITsTRING)->buf = calloc(5, sizeof(uint8_t)); \ + (bITsTRING)->buf[0] = ((mACRO) >> 20); \ + (bITsTRING)->buf[1] = (mACRO) >> 12; \ + (bITsTRING)->buf[2] = (mACRO) >> 4; \ + (bITsTRING)->buf[3] = (((mACRO) & 0x0f) << 4) | ((cELL_iD) >> 4); \ + (bITsTRING)->buf[4] = ((cELL_iD) & 0x0f) << 4; \ + (bITsTRING)->size = 5; \ + (bITsTRING)->bits_unused = 4; \ +} while(0) + + /* Used to format an uint32_t containing an ipv4 address */ #define IPV4_ADDR "%u.%u.%u.%u" #define IPV4_ADDR_FORMAT(aDDRESS) \ diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp new file mode 100644 index 0000000000..a3eeb26540 --- /dev/null +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -0,0 +1,916 @@ +#include +using namespace std; + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include +#include +#include + +#include +#include +#include "common/utils/LOG/log.h" +#include +#include +#include +#include +#include "openair2/SDAP/nr_sdap/nr_sdap_gnb.h" +//#include + +#pragma pack(1) + +typedef struct Gtpv1uMsgHeader { + uint8_t PN:1; + uint8_t S:1; + uint8_t E:1; + uint8_t spare:1; + uint8_t PT:1; + uint8_t version:3; + uint8_t msgType; + uint16_t msgLength; + teid_t teid; +} __attribute__((packed)) Gtpv1uMsgHeaderT; + +#pragma pack() + +// TS 29.060, table 7.1 defines the possible message types +// here are all the possible messages (3GPP R16) +#define GTP_ECHO_REQ (1) +#define GTP_ECHO_RSP (2) +#define GTP_ERROR_INDICATION (26) +#define GTP_SUPPORTED_EXTENSION_HEADER_INDICATION (31) +#define GTP_END_MARKER (254) +#define GTP_GPDU (255) + + +typedef struct ocp_gtpv1u_bearer_s { + /* TEID used in dl and ul */ + teid_t teid_incoming; ///< eNB TEID + teid_t teid_outgoing; ///< Remote TEID + in_addr_t outgoing_ip_addr; + struct in6_addr outgoing_ip6_addr; + tcp_udp_port_t outgoing_port; + uint16_t seqNum; + uint8_t npduNum; +} ocp_gtpv1u_bearer_t; + +typedef struct { + map bearers; +} teidData_t; + +typedef struct { + rnti_t rnti; + ebi_t incoming_rb_id; + gtpCallback callBack; +} rntiData_t; + +class gtpEndPoint { + public: + openAddr_t addr; + uint8_t foundAddr[20]; + int foundAddrLen; + int ipVersion; + map ue2te_mapping; + map te2ue_mapping; + // we use the same port number for source and destination address + // this allow using non standard gtp port number (different from 2152) + // and so, for example tu run 4G and 5G cores on one system + tcp_udp_port_t get_dstport() { + return (tcp_udp_port_t)atol(addr.destinationService); + } +}; + +class gtpEndPoints { + public: + pthread_mutex_t gtp_lock=PTHREAD_MUTEX_INITIALIZER; + // the instance id will be the Linux socket handler, as this is uniq + map instances; +}; + +gtpEndPoints globGtp; + +// note TEid 0 is reserved for specific usage: echo req/resp, error and supported extensions +static uint32_t gtpv1uNewTeid(void) { +#ifdef GTPV1U_LINEAR_TEID_ALLOCATION + g_gtpv1u_teid = g_gtpv1u_teid + 1; + return g_gtpv1u_teid; +#else + return random() + random() % (RAND_MAX - 1) + 1; +#endif +} + +int legacyInstanceMapping=0; +#define compatInst(a) ((a)==0 || (a)==INSTANCE_DEFAULT?legacyInstanceMapping:a) + +#define GTPV1U_HEADER_SIZE (8) + + +static int gtpv1uCreateAndSendMsg(int h, uint32_t peerIp, uint16_t peerPort, teid_t teid, uint8_t *Msg,int msgLen, + bool seqNumFlag, bool npduNumFlag, bool extHdrFlag, int seqNum, int npduNum, int extHdrType) { + AssertFatal(extHdrFlag==false,"Not developped"); + int headerAdditional=0; + + if ( seqNumFlag || npduNumFlag || extHdrFlag) + headerAdditional=4; + + uint8_t *buffer; + int fullSize=GTPV1U_HEADER_SIZE+headerAdditional+msgLen; + AssertFatal((buffer=(uint8_t *) malloc(fullSize)) != NULL, ""); + Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)buffer ; + // N should be 0 for us (it was used only in 2G and 3G) + msgHdr->PN=npduNumFlag; + msgHdr->S=seqNumFlag; + msgHdr->E=extHdrFlag; + msgHdr->spare=0; + //PT=0 is for GTP' TS 32.295 (charging) + msgHdr->PT=1; + msgHdr->version=1; + msgHdr->msgType=GTP_GPDU; + msgHdr->msgLength=htons(msgLen); + if ( seqNumFlag || extHdrFlag || npduNumFlag) + msgHdr->msgLength+=4; + msgHdr->teid=htonl(teid); + + if(seqNumFlag || extHdrFlag || npduNumFlag) { + *((uint16_t *) (buffer+8)) = seqNumFlag ? htons(seqNum) : 0x0000; + *((uint8_t *) (buffer+10)) = npduNumFlag ? htons(npduNum) : 0x00; + *((uint8_t *) (buffer+11)) = extHdrFlag ? htons(extHdrType) : 0x00; + } + + memcpy(buffer+GTPV1U_HEADER_SIZE+headerAdditional, Msg, msgLen); + // Fix me: add IPv6 support, using flag ipVersion + static struct sockaddr_in to= {0}; + to.sin_family = AF_INET; + to.sin_port = htons(peerPort); + to.sin_addr.s_addr = peerIp ; + LOG_D(GTPU,"sending packet size: %d to %s\n",fullSize, inet_ntoa(to.sin_addr) ); + + if (sendto(h, (void *)buffer, (size_t)fullSize, 0,(struct sockaddr *)&to, sizeof(to) ) != fullSize ) { + LOG_E(GTPU, + "[SD %d] Failed to send data to " IPV4_ADDR " on port %d, buffer size %u\n", + h, IPV4_ADDR_FORMAT(peerIp), peerPort, fullSize); + free(buffer); + return GTPNOK; + } + + free(buffer); + return !GTPNOK; +} + +static void gtpv1uSend(instance_t instance, gtpv1u_enb_tunnel_data_req_t *req, bool seqNumFlag, bool npduNumFlag) { + uint8_t *buffer=req->buffer+req->offset; + size_t length=req->length; + rnti_t rnti=req->rnti; + int rab_id=req->rab_id; + pthread_mutex_lock(&globGtp.gtp_lock); + auto inst=&globGtp.instances[compatInst(instance)]; + auto ptrRnti=inst->ue2te_mapping.find(rnti); + + if ( ptrRnti==inst->ue2te_mapping.end() ) { + LOG_E(GTPU, "gtpv1uSend failed: while getting ue rnti %x in hashtable ue_mapping\n", rnti); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } + + auto ptr=ptrRnti->second.bearers; + + if ( ptr.find(rab_id) == ptr.end() ) { + LOG_E(GTPU,"sending a packet to a non existant RNTI:RAB: %x/%x\n", rnti, rab_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } else + LOG_D(GTPU,"sending a packet to RNTI:RAB:teid %x/%x/%x, len %lu, oldseq %d, oldnum %d\n", + rnti, rab_id,ptr[rab_id].teid_outgoing,length, ptr[rab_id].seqNum,ptr[rab_id].npduNum ); + + if(seqNumFlag) + ptr[rab_id].seqNum++; + + if(npduNumFlag) + ptr[rab_id].npduNum++; + + // We will release the lock, let's copy data before + ocp_gtpv1u_bearer_t tmp=ptr[rab_id]; + pthread_mutex_unlock(&globGtp.gtp_lock); + gtpv1uCreateAndSendMsg(compatInst(instance), + tmp.outgoing_ip_addr, + tmp.outgoing_port, + tmp.teid_outgoing, + buffer, length, seqNumFlag, npduNumFlag, false, tmp.seqNum, tmp.npduNum, 0) ; +} + +static void gtpv1uSend2(instance_t instance, gtpv1u_gnb_tunnel_data_req_t *req, bool seqNumFlag, bool npduNumFlag) { + uint8_t *buffer=req->buffer+req->offset; + size_t length=req->length; + rnti_t rnti=req->rnti; + int rab_id=req->pdusession_id; + pthread_mutex_lock(&globGtp.gtp_lock); + auto inst=&globGtp.instances[compatInst(instance)]; + auto ptrRnti=inst->ue2te_mapping.find(rnti); + + if ( ptrRnti==inst->ue2te_mapping.end() ) { + LOG_E(GTPU, "gtpv1uSend failed: while getting ue rnti %x in hashtable ue_mapping\n", rnti); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } + + auto ptr=ptrRnti->second.bearers; + + if ( ptr.find(rab_id) == ptr.end() ) { + LOG_E(GTPU,"sending a packet to a non existant RNTI:RAB: %x/%x\n", rnti, rab_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } else + LOG_D(GTPU,"sending a packet to RNTI:RAB:teid %x/%x/%x, len %lu, oldseq %d, oldnum %d\n", + rnti, rab_id,ptr[rab_id].teid_outgoing,length, ptr[rab_id].seqNum,ptr[rab_id].npduNum ); + + if(seqNumFlag) + ptr[rab_id].seqNum++; + + if(npduNumFlag) + ptr[rab_id].npduNum++; + + // We will release the lock, let's copy data before + ocp_gtpv1u_bearer_t tmp=ptr[rab_id]; + pthread_mutex_unlock(&globGtp.gtp_lock); + gtpv1uCreateAndSendMsg(compatInst(instance), + tmp.outgoing_ip_addr, + tmp.outgoing_port, + tmp.teid_outgoing, + buffer, length, seqNumFlag, npduNumFlag, false, tmp.seqNum, tmp.npduNum, 0) ; +} + +static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_tunnel_data_req_t *req) { + rnti_t rnti=req->rnti; + int rab_id=req->rab_id; + pthread_mutex_lock(&globGtp.gtp_lock); + auto inst=&globGtp.instances[compatInst(instance)]; + auto ptrRnti=inst->ue2te_mapping.find(rnti); + + if ( ptrRnti==inst->ue2te_mapping.end() ) { + LOG_E(GTPU, "gtpv1uSend failed: while getting ue rnti %x in hashtable ue_mapping\n", rnti); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } + + auto ptr=ptrRnti->second.bearers; + + if ( ptr.find(rab_id) == ptr.end() ) { + LOG_E(GTPU,"sending a packet to a non existant RNTI:RAB: %x/%x\n", rnti, rab_id); + pthread_mutex_unlock(&globGtp.gtp_lock); + return; + } else + LOG_D(GTPU,"sending a end packet packet to RNTI:RAB:teid %x/%x/%x\n", + rnti, rab_id,ptr[rab_id].teid_outgoing); + + ocp_gtpv1u_bearer_t tmp=ptr[rab_id]; + pthread_mutex_unlock(&globGtp.gtp_lock); + Gtpv1uMsgHeaderT msgHdr; + // N should be 0 for us (it was used only in 2G and 3G) + msgHdr.PN=0; + msgHdr.S=0; + msgHdr.E=0; + msgHdr.spare=0; + //PT=0 is for GTP' TS 32.295 (charging) + msgHdr.PT=1; + msgHdr.version=1; + msgHdr.msgType=GTP_END_MARKER; + msgHdr.msgLength=htons(0); + msgHdr.teid=htonl(tmp.teid_outgoing); + // Fix me: add IPv6 support, using flag ipVersion + static struct sockaddr_in to= {0}; + to.sin_family = AF_INET; + to.sin_port = htons(tmp.outgoing_port); + to.sin_addr.s_addr = tmp.outgoing_ip_addr; + + char ip4[INET_ADDRSTRLEN]; + //char ip6[INET6_ADDRSTRLEN]; + LOG_D(GTPU,"sending end packet to %s\n", inet_ntoa(to.sin_addr) ); + + if (sendto(compatInst(instance), (void *)&msgHdr, sizeof(msgHdr), 0,(struct sockaddr *)&to, sizeof(to) ) != sizeof(msgHdr)) { + LOG_E(GTPU, + "[SD %ld] Failed to send data to %s on port %d, buffer size %lu\n", + compatInst(instance), inet_ntop(AF_INET, &tmp.outgoing_ip_addr, ip4, INET_ADDRSTRLEN), tmp.outgoing_port, sizeof(msgHdr)); + } +} + +static int udpServerSocket(openAddr_s addr) { + LOG_I(GTPU, "Initializing UDP for local address %s with port %s\n", addr.originHost, addr.originService); + int status; + struct addrinfo hints= {0}, *servinfo, *p; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; + + if ((status = getaddrinfo(addr.originHost, addr.originService, &hints, &servinfo)) != 0) { + LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); + return -1; + } + int sockfd=-1; + + // loop through all the results and bind to the first we can + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + LOG_W(GTPU,"socket: %s\n", strerror(errno)); + continue; + } + + if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { + close(sockfd); + LOG_W(GTPU,"bind: %s\n", strerror(errno)); + continue; + } else { + // We create the gtp instance on the socket + globGtp.instances[sockfd].addr=addr; + + if (p->ai_family == AF_INET) { + struct sockaddr_in *ipv4=(struct sockaddr_in *)p->ai_addr; + memcpy(globGtp.instances[sockfd].foundAddr, + &ipv4->sin_addr.s_addr, sizeof(ipv4->sin_addr.s_addr)); + globGtp.instances[sockfd].foundAddrLen=sizeof(ipv4->sin_addr.s_addr); + globGtp.instances[sockfd].ipVersion=4; + break; + } else if (p->ai_family == AF_INET6) { + LOG_W(GTPU,"Local address is IP v6\n"); + struct sockaddr_in6 *ipv6=(struct sockaddr_in6 *)p->ai_addr; + memcpy(globGtp.instances[sockfd].foundAddr, + &ipv6->sin6_addr.s6_addr, sizeof(ipv6->sin6_addr.s6_addr)); + globGtp.instances[sockfd].foundAddrLen=sizeof(ipv6->sin6_addr.s6_addr); + globGtp.instances[sockfd].ipVersion=6; + } else + AssertFatal(false,"Local address is not IPv4 or IPv6"); + } + + break; // if we get here, we must have connected successfully + } + + if (p == NULL) { + // looped off the end of the list with no successful bind + LOG_E(GTPU,"failed to bind socket: %s %s \n", addr.originHost, addr.originService); + return -1; + } + + freeaddrinfo(servinfo); // all done with this structure + + if (strlen(addr.destinationHost)>1) { + struct addrinfo hints; + memset(&hints,0,sizeof(hints)); + hints.ai_family=AF_UNSPEC; + hints.ai_socktype=SOCK_DGRAM; + hints.ai_protocol=0; + hints.ai_flags=AI_PASSIVE|AI_ADDRCONFIG; + struct addrinfo *res=0; + int err=getaddrinfo(addr.destinationHost,addr.destinationService,&hints,&res); + + if (err==0) { + for(p = res; p != NULL; p = p->ai_next) { + if ((err=connect(sockfd, p->ai_addr, p->ai_addrlen))==0) + break; + } + } + + if (err) + LOG_E(GTPU,"Can't filter remote host: %s, %s\n", addr.destinationHost,addr.destinationService); + } + + int sendbuff = 1000*1000*10; + AssertFatal(0==setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)),""); + LOG_D(GTPU,"Created listener for paquets to: %s:%s, send buffer size: %d\n", addr.originHost, addr.originService,sendbuff); + return sockfd; +} + +instance_t ocp_gtpv1Init(openAddr_t context) { + pthread_mutex_lock(&globGtp.gtp_lock); + int id=udpServerSocket(context); + + if (id>=0) { + itti_subscribe_event_fd(OCP_GTPV1_U, id); + } else + LOG_E(GTPU,"can't create GTP-U instance\n"); + + pthread_mutex_unlock(&globGtp.gtp_lock); + return id; +} + +teid_t newGtpuCreateTunnel(instance_t instance, rnti_t rnti, int incoming_bearer_id, int outgoing_bearer_id, teid_t outgoing_teid, + transport_layer_addr_t remoteAddr, int port, gtpCallback callBack) { + pthread_mutex_lock(&globGtp.gtp_lock); + auto inst=&globGtp.instances[instance]; + auto it=inst->ue2te_mapping.find(rnti); + + if ( it != inst->ue2te_mapping.end() ) { + LOG_W(GTPU,"Create a config for a already existing GTP tunnel (rnti %x)\n", rnti); + inst->ue2te_mapping.erase(it); + } + + uint32_t incoming_teid=gtpv1uNewTeid(); + + while ( inst->te2ue_mapping.find(incoming_teid) != inst->te2ue_mapping.end() ) { + LOG_W(GTPU, "generated a random Teid that exists, re-generating (%x)\n",incoming_teid); + incoming_teid=gtpv1uNewTeid(); + }; + + inst->te2ue_mapping[incoming_teid].rnti=rnti; + + inst->te2ue_mapping[incoming_teid].incoming_rb_id= incoming_bearer_id; + + inst->te2ue_mapping[incoming_teid].callBack=callBack; + + auto tmp=&inst->ue2te_mapping[rnti].bearers[outgoing_bearer_id]; + + int addrs_length_in_bytes = remoteAddr.length / 8; + + switch (addrs_length_in_bytes) { + case 4: + memcpy(&tmp->outgoing_ip_addr,remoteAddr.buffer,4); + break; + + case 16: + memcpy(tmp->outgoing_ip6_addr.s6_addr,remoteAddr.buffer, + 16); + break; + + case 20: + memcpy(&tmp->outgoing_ip_addr,remoteAddr.buffer,4); + memcpy(&tmp->outgoing_ip6_addr.s6_addr, + remoteAddr.buffer+4, + 16); + + default: + AssertFatal(false, "SGW Address size impossible"); + } + + tmp->teid_incoming = incoming_teid; + tmp->outgoing_port=port; + tmp->teid_outgoing= outgoing_teid; + pthread_mutex_unlock(&globGtp.gtp_lock); + char ip4[INET_ADDRSTRLEN]; + char ip6[INET6_ADDRSTRLEN]; + + LOG_I(GTPU, "Created tunnel for RNTI %x, teid for DL: %d, teid for UL %d to remote IPv4: %s, IPv6 %s\n", + rnti, + tmp->teid_incoming, + tmp->teid_outgoing, + inet_ntop(AF_INET,(void*)&tmp->outgoing_ip_addr, ip4,INET_ADDRSTRLEN ), + inet_ntop(AF_INET6,(void*)&tmp->outgoing_ip6_addr.s6_addr, ip6, INET6_ADDRSTRLEN)); + + return incoming_teid; +} + +int ocp_gtpv1u_create_s1u_tunnel(instance_t instance, + const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, + gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp) { + LOG_D(GTPU, "Start create tunnels for RNTI %x, num_tunnels %d, sgw_S1u_teid %x\n", + create_tunnel_req->rnti, + create_tunnel_req->num_tunnels, + create_tunnel_req->sgw_S1u_teid[0]); + tcp_udp_port_t dstport=globGtp.instances[compatInst(instance)].get_dstport(); + for (int i = 0; i < create_tunnel_req->num_tunnels; i++) { + AssertFatal(create_tunnel_req->eps_bearer_id[i] > 4, + "From legacy code not clear, seems impossible (bearer=%d)\n", + create_tunnel_req->eps_bearer_id[i]); + int incoming_rb_id=create_tunnel_req->eps_bearer_id[i]-4; + + teid_t teid=newGtpuCreateTunnel(compatInst(instance), create_tunnel_req->rnti, + incoming_rb_id, + create_tunnel_req->eps_bearer_id[i], + create_tunnel_req->sgw_S1u_teid[i], + create_tunnel_req->sgw_addr[i], dstport, + pdcp_data_req); + create_tunnel_resp->status=0; + create_tunnel_resp->rnti=create_tunnel_req->rnti; + create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels; + create_tunnel_resp->enb_S1u_teid[i]=teid; + create_tunnel_resp->eps_bearer_id[i] = create_tunnel_req->eps_bearer_id[i]; + memcpy(create_tunnel_resp->enb_addr.buffer,globGtp.instances[compatInst(instance)].foundAddr, + globGtp.instances[compatInst(instance)].foundAddrLen); + create_tunnel_resp->enb_addr.length= globGtp.instances[compatInst(instance)].foundAddrLen; + } + + return !GTPNOK; +} + +int ocp_gtpv1u_update_s1u_tunnel( + const instance_t instance, + const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req, + const rnti_t prior_rnti +) { + LOG_D(GTPU, "Start update tunnels for old RNTI %x, new RNTI %x, num_tunnels %d, sgw_S1u_teid %x, eps_bearer_id %x\n", + prior_rnti, + create_tunnel_req->rnti, + create_tunnel_req->num_tunnels, + create_tunnel_req->sgw_S1u_teid[0], + create_tunnel_req->eps_bearer_id[0]); + pthread_mutex_lock(&globGtp.gtp_lock); + auto inst=&globGtp.instances[compatInst(instance)]; + + if ( inst->ue2te_mapping.find(create_tunnel_req->rnti) == inst->ue2te_mapping.end() ) { + LOG_E(GTPU,"Update not already existing tunnel (new rnti %x, old rnti %x)\n", create_tunnel_req->rnti, prior_rnti); + } + + auto it=inst->ue2te_mapping.find(prior_rnti); + + if ( it != inst->ue2te_mapping.end() ) { + LOG_W(GTPU,"Update a not existing tunnel, start create the new one (new rnti %x, old rnti %x)\n", create_tunnel_req->rnti, prior_rnti); + pthread_mutex_unlock(&globGtp.gtp_lock); + gtpv1u_enb_create_tunnel_resp_t tmp; + (void)ocp_gtpv1u_create_s1u_tunnel(instance, create_tunnel_req, &tmp); + return 0; + } + + inst->ue2te_mapping[create_tunnel_req->rnti]=it->second; + inst->ue2te_mapping.erase(it); + pthread_mutex_unlock(&globGtp.gtp_lock); + return 0; +} + +int gtpv1u_create_ngu_tunnel( const instance_t instance, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req, + gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp) { + LOG_D(GTPU, "Start create tunnels for RNTI %x, num_tunnels %d, sgw_S1u_teid %x\n", + create_tunnel_req->rnti, + create_tunnel_req->num_tunnels, + create_tunnel_req->upf_NGu_teid[0]); + tcp_udp_port_t dstport=globGtp.instances[compatInst(instance)].get_dstport(); + for (int i = 0; i < create_tunnel_req->num_tunnels; i++) { + teid_t teid=newGtpuCreateTunnel(compatInst(instance), create_tunnel_req->rnti, + create_tunnel_req->incoming_rb_id[i], + create_tunnel_req->pdusession_id[i], + create_tunnel_req->upf_NGu_teid[i], + create_tunnel_req->upf_addr[i], dstport, + sdap_gnb_data_req); + create_tunnel_resp->status=0; + create_tunnel_resp->rnti=create_tunnel_req->rnti; + create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels; + create_tunnel_resp->gnb_NGu_teid[i]=teid; + memcpy(create_tunnel_resp->gnb_addr.buffer,globGtp.instances[compatInst(instance)].foundAddr, + globGtp.instances[compatInst(instance)].foundAddrLen); + create_tunnel_resp->gnb_addr.length= globGtp.instances[compatInst(instance)].foundAddrLen; + } + + return !GTPNOK; +} + +int gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +) { + AssertFatal( false, "to be developped\n"); + return GTPNOK; +} + +int ocp_gtpv1u_create_x2u_tunnel( + const instance_t instanceP, + const gtpv1u_enb_create_x2u_tunnel_req_t *const create_tunnel_req_pP, + gtpv1u_enb_create_x2u_tunnel_resp_t *const create_tunnel_resp_pP) { + AssertFatal( false, "to be developped\n"); +} + +int newGtpuDeleteTunnel(instance_t instance, rnti_t rnti) { + LOG_D(GTPU, "Start delete tunnels for RNTI %x\n", + rnti); + pthread_mutex_lock(&globGtp.gtp_lock); + auto inst=&globGtp.instances[compatInst(instance)]; + auto it=inst->ue2te_mapping.find(rnti); + + if ( it == inst->ue2te_mapping.end() ) { + LOG_W(GTPU,"Delete a non existing GTP tunnel\n"); + pthread_mutex_unlock(&globGtp.gtp_lock); + return -1; + } + + int nb=0; + + for (auto j=it->second.bearers.begin(); + j!=it->second.bearers.end(); + ++j) { + inst->te2ue_mapping.erase(j->second.teid_incoming); + nb++; + } + + inst->ue2te_mapping.erase(it); + pthread_mutex_unlock(&globGtp.gtp_lock); + LOG_I(GTPU, "Deleted all tunnels for RNTI %d (%d tunnels deleted)\n", rnti, nb); + return !GTPNOK; +} + +// Legacy delete tunnel finish by deleting all the rnti +// so the list of bearer provided is only a design bug +int ocp_gtpv1u_delete_s1u_tunnel( const instance_t instance, + const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { + return newGtpuDeleteTunnel(instance, req_pP->rnti); +} + +int gtpv1u_delete_x2u_tunnel( const instance_t instanceP, + const gtpv1u_enb_delete_tunnel_req_t *const req_pP, + int enbflag) { + return 0; +} + +static int Gtpv1uHandleEchoReq(int h, + uint8_t *msgBuf, + uint32_t msgBufLen, + uint16_t peerPort, + uint32_t peerIp) { + LOG_E(GTPU,"to be dev\n"); + int rc = GTPNOK; + return rc; +} + +static int Gtpv1uHandleError(int h, + uint8_t *msgBuf, + uint32_t msgBufLen, + uint16_t peerPort, + uint32_t peerIp) { + LOG_E(GTPU,"to be dev\n"); + int rc = GTPNOK; + return rc; +} + +static int Gtpv1uHandleSupportedExt(int h, + uint8_t *msgBuf, + uint32_t msgBufLen, + uint16_t peerPort, + uint32_t peerIp) { + LOG_E(GTPU,"to be dev\n"); + int rc = GTPNOK; + return rc; +} + +// When end marker arrives, we notify the client with buffer size = 0 +// The client will likely call "delete tunnel" +// nevertheless we don't take the initiative +static int Gtpv1uHandleEndMarker(int h, + uint8_t *msgBuf, + uint32_t msgBufLen, + uint16_t peerPort, + uint32_t peerIp) { + Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *) msgBuf; + + if ( msgHdr->version != 1 || msgHdr->PT != 1 ) { + LOG_E(GTPU, "Received a packet that is not GTP header\n"); + return GTPNOK; + } + + pthread_mutex_lock(&globGtp.gtp_lock); + // the socket Linux file handler is the instance id + auto inst=&globGtp.instances[h]; + auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid)); + + if ( tunnel == inst->te2ue_mapping.end() ) { + LOG_E(GTPU,"Received a incoming packet on unknown teid (%x) Dropping!\n", msgHdr->teid); + pthread_mutex_unlock(&globGtp.gtp_lock); + return GTPNOK; + } + + // This context is not good for gtp + // frame, ... has no meaning + // manyother attributes may come from create tunnel + protocol_ctxt_t ctxt; + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = inst->addr.originInstance; + ctxt.rnti = tunnel->second.rnti; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 0; + ctxt.brOption = 0; + const srb_flag_t srb_flag=SRB_FLAG_NO; + const rb_id_t rb_id=tunnel->second.incoming_rb_id; + const mui_t mui=RLC_MUI_UNDEFINED; + const confirm_t confirm=RLC_SDU_CONFIRM_NO; + const pdcp_transmission_mode_t mode=PDCP_TRANSMISSION_MODE_DATA; + const uint32_t sourceL2Id=0; + const uint32_t destinationL2Id=0; + pthread_mutex_unlock(&globGtp.gtp_lock); + + if ( !tunnel->second.callBack(&ctxt, + srb_flag, + rb_id, + mui, + confirm, + 0, + NULL, + mode, + &sourceL2Id, + &destinationL2Id) ) + LOG_E(GTPU,"down layer refused incoming packet\n"); + + LOG_D(GTPU,"Received END marker packet for: teid:%x\n", ntohl(msgHdr->teid)); + return !GTPNOK; +} + +static int Gtpv1uHandleGpdu(int h, + uint8_t *msgBuf, + uint32_t msgBufLen, + uint16_t peerPort, + uint32_t peerIp) { + Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *) msgBuf; + + if ( msgHdr->version != 1 || msgHdr->PT != 1 ) { + LOG_E(GTPU, "Received a packet that is not GTP header\n"); + return GTPNOK; + } + + pthread_mutex_lock(&globGtp.gtp_lock); + // the socket Linux file handler is the instance id + auto inst=&globGtp.instances[h]; + auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid)); + + if ( tunnel == inst->te2ue_mapping.end() ) { + LOG_E(GTPU,"Received a incoming packet on unknown teid (%x) Dropping!\n", msgHdr->teid); + pthread_mutex_unlock(&globGtp.gtp_lock); + return GTPNOK; + } + + int offset=8; + + if( msgHdr->E || msgHdr->S ||msgHdr->PN) + offset+=8; + + // This context is not good for gtp + // frame, ... has no meaning + // manyother attributes may come from create tunnel + protocol_ctxt_t ctxt; + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = inst->addr.originInstance; + ctxt.rnti = tunnel->second.rnti; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 0; + ctxt.brOption = 0; + const srb_flag_t srb_flag=SRB_FLAG_NO; + const rb_id_t rb_id=tunnel->second.incoming_rb_id; + const mui_t mui=RLC_MUI_UNDEFINED; + const confirm_t confirm=RLC_SDU_CONFIRM_NO; + const sdu_size_t sdu_buffer_size=msgBufLen-offset; + unsigned char *const sdu_buffer=msgBuf+offset; + const pdcp_transmission_mode_t mode=PDCP_TRANSMISSION_MODE_DATA; + const uint32_t sourceL2Id=0; + const uint32_t destinationL2Id=0; + pthread_mutex_unlock(&globGtp.gtp_lock); + + if ( !tunnel->second.callBack(&ctxt, + srb_flag, + rb_id, + mui, + confirm, + sdu_buffer_size, + sdu_buffer, + mode, + &sourceL2Id, + &destinationL2Id) ) + LOG_E(GTPU,"down layer refused incoming packet\n"); + + LOG_D(GTPU,"Received a %d bytes packet for: teid:%x\n", + msgBufLen-offset, + ntohl(msgHdr->teid)); + return !GTPNOK; +} + +void gtpv1uReceiver(int h) { + uint8_t udpData[65536]; + int udpDataLen; + socklen_t from_len; + struct sockaddr_in addr; + from_len = (socklen_t)sizeof(struct sockaddr_in); + + if ((udpDataLen = recvfrom(h, udpData, sizeof(udpData), 0, + (struct sockaddr *)&addr, &from_len)) < 0) { + LOG_E(GTPU, "Recvfrom failed on %d (%s)\n", h, strerror(errno)); + return; + } else if (udpDataLen == 0) { + LOG_W(GTPU, "Recvfrom returned 0\n"); + return; + } else { + uint8_t msgType = *((uint8_t *)(udpData + 1)); + LOG_D(GTPU, "Received GTP data, msg type: %x\n", msgType); + + switch(msgType) { + case GTP_ECHO_RSP: + break; + + case GTP_ECHO_REQ: + Gtpv1uHandleEchoReq( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + break; + + case GTP_ERROR_INDICATION: + Gtpv1uHandleError( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + break; + + case GTP_SUPPORTED_EXTENSION_HEADER_INDICATION: + Gtpv1uHandleSupportedExt( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + break; + + case GTP_END_MARKER: + Gtpv1uHandleEndMarker( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + break; + + case GTP_GPDU: + Gtpv1uHandleGpdu( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + break; + + default: + LOG_E(GTPU, "Received a GTP packet of unknown type: %d\n",msgType); + break; + } + } +} + +#include + +void *ocp_gtpv1uTask(void *args) { + while(1) { + /* Trying to fetch a message from the message queue. + If the queue is empty, this function will block till a + message is sent to the task. + */ + MessageDef *message_p = NULL; + itti_receive_msg(OCP_GTPV1_U, &message_p); + + if (message_p != NULL ) { + openAddr_t addr= {0}; + + switch (ITTI_MSG_ID(message_p)) { + // DATA TO BE SENT TO UDP + case GTPV1U_ENB_TUNNEL_DATA_REQ: { + gtpv1uSend(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), + >PV1U_ENB_TUNNEL_DATA_REQ(message_p), false, false); + itti_free(OCP_GTPV1_U, GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer); + } + break; + + case GTPV1U_GNB_TUNNEL_DATA_REQ: { + gtpv1uSend2(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), + >PV1U_GNB_TUNNEL_DATA_REQ(message_p), false, false); + itti_free(OCP_GTPV1_U, GTPV1U_GNB_TUNNEL_DATA_REQ(message_p).buffer); + } + break; + + case TERMINATE_MESSAGE: + break; + + case TIMER_HAS_EXPIRED: + LOG_E(GTPU, "Received unexpected timer expired (no need of timers in this version) %s\n", ITTI_MSG_NAME(message_p)); + break; + + case GTPV1U_ENB_END_MARKER_REQ: + gtpv1uEndTunnel(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), + >PV1U_ENB_TUNNEL_DATA_REQ(message_p)); + itti_free(OCP_GTPV1_U, GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer); + break; + + case GTPV1U_ENB_DATA_FORWARDING_REQ: + case GTPV1U_ENB_DATA_FORWARDING_IND: + case GTPV1U_ENB_END_MARKER_IND: + LOG_E(GTPU, "to be developped %s\n", ITTI_MSG_NAME(message_p)); + abort(); + break; + + case GTPV1U_ENB_S1_REQ: + // to be dev: should be removed, to use API + strcpy(addr.originHost, GTPV1U_ENB_S1_REQ(message_p).addrStr); + strcpy(addr.originService, GTPV1U_ENB_S1_REQ(message_p).portStr); + strcpy(addr.destinationService,addr.originService); + AssertFatal((legacyInstanceMapping=ocp_gtpv1Init(addr))!=0,"Instance 0 reserved for legacy\n"); + break; + + case GTPV1U_GNB_NG_REQ: + // to be dev: should be removed, to use API + strcpy(addr.originHost, GTPV1U_ENB_S1_REQ(message_p).addrStr); + strcpy(addr.originService, GTPV1U_ENB_S1_REQ(message_p).portStr); + strcpy(addr.destinationService,addr.originService); + AssertFatal((legacyInstanceMapping=ocp_gtpv1Init(addr))!=0,"Instance 0 reserved for legacy\n"); + break; + + default: + LOG_E(GTPU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); + abort(); + break; + } + + AssertFatal(EXIT_SUCCESS==itti_free(OCP_GTPV1_U, message_p), "Failed to free memory!\n"); + } + + struct epoll_event *events; + + int nb_events = itti_get_events(OCP_GTPV1_U, &events); + + for (int i = 0; i < nb_events; i++) + if ((events[i].events&EPOLLIN)) + gtpv1uReceiver(events[i].data.fd); + } + + return NULL; +} + +#ifdef __cplusplus +} +#endif diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h new file mode 100644 index 0000000000..dd406e27cd --- /dev/null +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -0,0 +1,71 @@ +#ifndef __GTPUNEW_ITF_H__ +#define __GTPUNEW_ITF_H__ +#define GTPNOK -1 + +# define GTPU_HEADER_OVERHEAD_MAX 64 +#ifdef __cplusplus +extern "C" { +#endif + +#include +#if defined(NEW_GTPU) +#define gtpv1u_create_s1u_tunnel ocp_gtpv1u_create_s1u_tunnel +#define gtpv1u_update_s1u_tunnel ocp_gtpv1u_update_s1u_tunnel +#define gtpv1u_delete_s1u_tunnel ocp_gtpv1u_delete_s1u_tunnel +#define gtpv1u_create_x2u_tunnel ocp_gtpv1u_create_x2u_tunnel +#define gtpv1u_eNB_task ocp_gtpv1uTask +#define nr_gtpv1u_gNB_task ocp_gtpv1uTask +#define TASK_VARIABLE OCP_GTPV1_U +#else +#define TASK_VARIABLE TASK_GTPV1_U +#endif + +typedef boolean_t (*gtpCallback)( + protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id); + +typedef struct openAddr_s { + char originHost[HOST_NAME_MAX]; + char originService[HOST_NAME_MAX]; + char destinationHost[HOST_NAME_MAX]; + char destinationService[HOST_NAME_MAX]; + instance_t originInstance; +} openAddr_t; + +// the init function create a gtp instance and return the gtp instance id +// the parameter originInstance will be sent back in each message from gtp to the creator +void ocp_gtpv1uReceiver(int h); +void ocp_gtpv1uProcessTimeout(int handle,void *arg); +int ocp_gtpv1u_create_s1u_tunnel(const instance_t instance, const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, + gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp); +int ocp_gtpv1u_update_s1u_tunnel(const instance_t instanceP, + const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req_pP, + const rnti_t prior_rnti + ); +int ocp_gtpv1u_delete_s1u_tunnel( const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP); +int gtpv1u_delete_s1u_tunnel( const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP); + +int ocp_gtpv1u_create_x2u_tunnel( + const instance_t instanceP, + const gtpv1u_enb_create_x2u_tunnel_req_t *const create_tunnel_req_pP, + gtpv1u_enb_create_x2u_tunnel_resp_t *const create_tunnel_resp_pP); + + +// New API +teid_t newGtpuCreateTunnel(instance_t instance, rnti_t rnti, int incoming_bearer_id, int outgoing_rb_id, teid_t teid, + transport_layer_addr_t remoteAddr, int port, gtpCallback callBack); +instance_t ocp_gtpv1Init(openAddr_t context); +void *ocp_gtpv1uTask(void *args); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/openshift/README.md b/openshift/README.md new file mode 100644 index 0000000000..b7409ab945 --- /dev/null +++ b/openshift/README.md @@ -0,0 +1,107 @@ + + + + + +
+ + + + + + OpenShift Build and Usage Procedures +
+ +----- + +**CAUTION: this is experimental. Still a lot to be done.** + +----- + +# 1. Build pre-requisites # + +To build our RAN images, we SHALL use the `codeready-builder-for-rhel-8-x86_64-rpms` repository with all the proper development libraries. + +This repository is not directly accessible from the UBI RHEL8 image (`registry.access.redhat.com/ubi8/ubi:latest`). + +So we need to copy from a register RHEL8 machine certificates and subsccription manager configuration files. + +SO on a `RHEL8` physical machine (or a virtual machine) connected to the OpenShift Cluster, recover the entitlement and the RH subscription manager configs: + +```bash +oc create configmap rhsm-conf --from-file /etc/rhsm/rhsm.conf +oc create configmap rhsm-ca --from-file /etc/rhsm/ca/redhat-uep.pem + +oc create secret generic etc-pki-entitlement --from-file /etc/pki/entitlement/{NUMBER_ON_YOUR_COMPUTER}.pem --from-file /etc/pki/entitlement/{NUMBER_ON_YOUR_COMPUTER}-key.pem +``` + +These configmaps and secret will be shared by all the build configs in your OC project. No need to do it each time. + +**CAUTION: these files expire every month or so. If you have done a build on your OC project and try again a few weeks later, you may need to re-copy them**. + +```bash +oc delete secret etc-pki-entitlement +oc delete cm rhsm-conf +oc delete cm rhsm-ca +``` + +**LAST POINT: your OC project SHALL be `oai`.** + +# 2. Build the Builder shared image # + +In our Eurecom/OSA environment we need to pass a GIT proxy. + +2 things are impacted by this situation: + +* In `openshift/oai-ran-rh8-build-config.yml` file + * `httpProxy: http://proxy.eurecom.fr:8080` + * `httpsProxy: https://proxy.eurecom.fr:8080` +* Add a environment variable to the build config + +```bash +oc apply -f openshift/oai-ran-rh8-image-stream.yml +oc apply -f openshift/oai-ran-rh8-build-config.yml +oc set env bc/oai-ran-rhel8-build-config NEEDED_GIT_PROXY=http://proxy.eurecom.fr:8080 +oc start-build oai-ran-rhel8-build-config --follow +``` + +In case you do NOT require a GIT proxy: **you SHALL remove the 2 lines in `openshift/oai-ran-rh8-build-config.yml` file.** + +And no need to add a `NEEDED_GIT_PROXY` variable to the build config. + +```bash +oc apply -f openshift/oai-ran-rh8-image-stream.yml +oc apply -f openshift/modified-oai-ran-rh8-build-config.yml +oc start-build oai-ran-rhel8-build-config --follow +``` + +After a while it should be successful. + +# 3. Build an OAI target image # + +For the example the eNB: + +```bash +oc apply -f openshift/oai-enb-rh8-image-stream.yml +oc apply -f openshift/oai-enb-rh8-build-config.yml +oc start-build oai-enb-rh8-build-config --follow +``` + +**CAUTION: if you are pushing modifications to the branch you are using, it won't be taken into account besides the Dockerfile.** + +**Because the source files are copied during the shared image creation.** + +**Only way to regenerate images w/ modified source code is to re-start from step #2.** + +# 4. Deployment using HELM charts # + +**CAUTION: even more experimental.** + +Helm charts are located in another repository: + +```bash +git clone https://github.com/OPENAIRINTERFACE/openair-k8s.git +cd openair-k8s +git checkout helm-deployment-S6a-S1C-S1U-in-network-18-with-enb +helm install mme /path-to-your-cloned/openair-k8s/charts/oai-mme/ +``` diff --git a/openshift/oai-enb-build-config.yml b/openshift/oai-enb-build-config.yml new file mode 100644 index 0000000000..3f6875c50d --- /dev/null +++ b/openshift/oai-enb-build-config.yml @@ -0,0 +1,55 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +kind: BuildConfig +apiVersion: build.openshift.io/v1 +metadata: + name: "oai-enb-build-config" +spec: + runPolicy: "Serial" + source: + #still needed for the target image + git: + uri: "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + ref: "develop" + httpProxy: http://proxy.eurecom.fr:8080 + httpsProxy: https://proxy.eurecom.fr:8080 + secrets: + - secret: + name: etc-pki-entitlement + destinationDir: etc-pki-entitlement + configMaps: + - configMap: + name: rhsm-conf + destinationDir: rhsm-conf + - configMap: + name: rhsm-ca + destinationDir: rhsm-ca + + strategy: + #using both builder image and target image docker + dockerStrategy: + dockerfilePath: "docker/Dockerfile.eNB.rhel7.oc4-4" + output: + to: + kind: "ImageStreamTag" + name: "oai-enb:latest" diff --git a/openshift/oai-enb-image-stream.yml b/openshift/oai-enb-image-stream.yml new file mode 100644 index 0000000000..94ee13e50f --- /dev/null +++ b/openshift/oai-enb-image-stream.yml @@ -0,0 +1,30 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: v1 +kind: ImageStream +metadata: + name: oai-enb + namespace: oai +status: + tag: latest + diff --git a/openshift/oai-enb-rh8-build-config.yml b/openshift/oai-enb-rh8-build-config.yml new file mode 100644 index 0000000000..e715fc5733 --- /dev/null +++ b/openshift/oai-enb-rh8-build-config.yml @@ -0,0 +1,48 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +kind: BuildConfig +apiVersion: build.openshift.io/v1 +metadata: + name: "oai-enb-rh8-build-config" +spec: + runPolicy: "Serial" + source: + #still needed for the target image + git: + uri: "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + ref: "develop" + httpProxy: http://proxy.eurecom.fr:8080 + httpsProxy: https://proxy.eurecom.fr:8080 + strategy: + #using both builder image and target image docker + dockerStrategy: + dockerfilePath: "docker/Dockerfile.eNB.rhel8.2.oc4-4" + nodeSelector: + kubernetes.io/hostname: dedale.5glab.nsa.eurecom.fr + resources: + requests: + ephemeral-storage: "8Gi" + output: + to: + kind: "ImageStreamTag" + name: "oai-enb:rhel8-latest" diff --git a/openshift/oai-enb-rh8-image-stream.yml b/openshift/oai-enb-rh8-image-stream.yml new file mode 100644 index 0000000000..9d1cfebd54 --- /dev/null +++ b/openshift/oai-enb-rh8-image-stream.yml @@ -0,0 +1,30 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: v1 +kind: ImageStream +metadata: + name: oai-enb + namespace: oai +status: + tag: rhel8-latest + diff --git a/openshift/oai-gnb-build-config.yml b/openshift/oai-gnb-build-config.yml new file mode 100644 index 0000000000..b0c99959d1 --- /dev/null +++ b/openshift/oai-gnb-build-config.yml @@ -0,0 +1,55 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +kind: BuildConfig +apiVersion: build.openshift.io/v1 +metadata: + name: "oai-gnb-build-config" +spec: + runPolicy: "Serial" + source: + #still needed for the target image + git: + uri: "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + ref: "develop" + httpProxy: http://proxy.eurecom.fr:8080 + httpsProxy: https://proxy.eurecom.fr:8080 + secrets: + - secret: + name: etc-pki-entitlement + destinationDir: etc-pki-entitlement + configMaps: + - configMap: + name: rhsm-conf + destinationDir: rhsm-conf + - configMap: + name: rhsm-ca + destinationDir: rhsm-ca + + strategy: + #using both builder image and target image docker + dockerStrategy: + dockerfilePath: "docker/Dockerfile.gNB.rhel7.oc4-4" + output: + to: + kind: "ImageStreamTag" + name: "oai-gnb:latest" diff --git a/openshift/oai-gnb-image-stream.yml b/openshift/oai-gnb-image-stream.yml new file mode 100644 index 0000000000..22a6c157d2 --- /dev/null +++ b/openshift/oai-gnb-image-stream.yml @@ -0,0 +1,30 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: v1 +kind: ImageStream +metadata: + name: oai-gnb + namespace: oai +status: + tag: latest + diff --git a/openshift/oai-gnb-rh8-build-config.yml b/openshift/oai-gnb-rh8-build-config.yml new file mode 100644 index 0000000000..aa3553c1e4 --- /dev/null +++ b/openshift/oai-gnb-rh8-build-config.yml @@ -0,0 +1,48 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +kind: BuildConfig +apiVersion: build.openshift.io/v1 +metadata: + name: "oai-gnb-rh8-build-config" +spec: + runPolicy: "Serial" + source: + #still needed for the target image + git: + uri: "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + ref: "develop" + httpProxy: http://proxy.eurecom.fr:8080 + httpsProxy: https://proxy.eurecom.fr:8080 + strategy: + #using both builder image and target image docker + dockerStrategy: + dockerfilePath: "docker/Dockerfile.gNB.rhel8.2.oc4-4" + nodeSelector: + kubernetes.io/hostname: dedale.5glab.nsa.eurecom.fr + resources: + requests: + ephemeral-storage: "15Gi" + output: + to: + kind: "ImageStreamTag" + name: "oai-gnb:rhel8-latest" diff --git a/openshift/oai-gnb-rh8-image-stream.yml b/openshift/oai-gnb-rh8-image-stream.yml new file mode 100644 index 0000000000..2e04e94f5b --- /dev/null +++ b/openshift/oai-gnb-rh8-image-stream.yml @@ -0,0 +1,30 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: v1 +kind: ImageStream +metadata: + name: oai-gnb + namespace: oai +status: + tag: rhel8-latest + diff --git a/openshift/oai-lte-ue-rh8-build-config.yml b/openshift/oai-lte-ue-rh8-build-config.yml new file mode 100644 index 0000000000..f077e4cb26 --- /dev/null +++ b/openshift/oai-lte-ue-rh8-build-config.yml @@ -0,0 +1,48 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +kind: BuildConfig +apiVersion: build.openshift.io/v1 +metadata: + name: "oai-lte-ue-rh8-build-config" +spec: + runPolicy: "Serial" + source: + #still needed for the target image + git: + uri: "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + ref: "develop" + httpProxy: http://proxy.eurecom.fr:8080 + httpsProxy: https://proxy.eurecom.fr:8080 + strategy: + #using both builder image and target image docker + dockerStrategy: + dockerfilePath: "docker/Dockerfile.lteUE.rhel8.2.oc4-4" + nodeSelector: + kubernetes.io/hostname: dedale.5glab.nsa.eurecom.fr + resources: + requests: + ephemeral-storage: "8Gi" + output: + to: + kind: "ImageStreamTag" + name: "oai-lte-ue:rhel8-latest" diff --git a/openshift/oai-lte-ue-rh8-image-stream.yml b/openshift/oai-lte-ue-rh8-image-stream.yml new file mode 100644 index 0000000000..09aeb2a766 --- /dev/null +++ b/openshift/oai-lte-ue-rh8-image-stream.yml @@ -0,0 +1,30 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: v1 +kind: ImageStream +metadata: + name: oai-lte-ue + namespace: oai +status: + tag: rhel8-latest + diff --git a/openshift/oai-nr-ue-rh8-build-config.yml b/openshift/oai-nr-ue-rh8-build-config.yml new file mode 100644 index 0000000000..b3367f6ab6 --- /dev/null +++ b/openshift/oai-nr-ue-rh8-build-config.yml @@ -0,0 +1,48 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +kind: BuildConfig +apiVersion: build.openshift.io/v1 +metadata: + name: "oai-nr-ue-rh8-build-config" +spec: + runPolicy: "Serial" + source: + #still needed for the target image + git: + uri: "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + ref: "develop" + httpProxy: http://proxy.eurecom.fr:8080 + httpsProxy: https://proxy.eurecom.fr:8080 + strategy: + #using both builder image and target image docker + dockerStrategy: + dockerfilePath: "docker/Dockerfile.nrUE.rhel8.2.oc4-4" + nodeSelector: + kubernetes.io/hostname: dedale.5glab.nsa.eurecom.fr + resources: + requests: + ephemeral-storage: "8Gi" + output: + to: + kind: "ImageStreamTag" + name: "oai-nr-ue:rhel8-latest" diff --git a/openshift/oai-nr-ue-rh8-image-stream.yml b/openshift/oai-nr-ue-rh8-image-stream.yml new file mode 100644 index 0000000000..e61cc0dfde --- /dev/null +++ b/openshift/oai-nr-ue-rh8-image-stream.yml @@ -0,0 +1,30 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: v1 +kind: ImageStream +metadata: + name: oai-nr-ue + namespace: oai +status: + tag: rhel8-latest + diff --git a/openshift/oai-physim-image-stream.yml b/openshift/oai-physim-image-stream.yml new file mode 100644 index 0000000000..9ef338f139 --- /dev/null +++ b/openshift/oai-physim-image-stream.yml @@ -0,0 +1,29 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: image.openshift.io/v1 +kind: ImageStream +metadata: + name: oai-physim +spec: + lookupPolicy: + local: true diff --git a/openshift/oai-ran-build-config.yml b/openshift/oai-ran-build-config.yml new file mode 100644 index 0000000000..39d7a40f6d --- /dev/null +++ b/openshift/oai-ran-build-config.yml @@ -0,0 +1,52 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +kind: BuildConfig +apiVersion: build.openshift.io/v1 +metadata: + name: "oai-ran-build-config" +spec: + runPolicy: "Serial" + source: + git: + uri: "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + ref: "develop" + httpProxy: http://proxy.eurecom.fr:8080 + httpsProxy: https://proxy.eurecom.fr:8080 + secrets: + - secret: + name: etc-pki-entitlement + destinationDir: etc-pki-entitlement + configMaps: + - configMap: + name: rhsm-conf + destinationDir: rhsm-conf + - configMap: + name: rhsm-ca + destinationDir: rhsm-ca + strategy: + dockerStrategy: + dockerfilePath: "docker/Dockerfile.ran.rhel7.oc4-4" + output: + to: + kind: "ImageStreamTag" + name: "oai-ran:latest" diff --git a/openshift/oai-ran-image-stream.yml b/openshift/oai-ran-image-stream.yml new file mode 100644 index 0000000000..e1ef9d0b31 --- /dev/null +++ b/openshift/oai-ran-image-stream.yml @@ -0,0 +1,30 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: v1 +kind: ImageStream +metadata: + name: oai-ran + namespace: oai +status: + tag: latest + diff --git a/openshift/oai-ran-rh8-build-config.yml b/openshift/oai-ran-rh8-build-config.yml new file mode 100644 index 0000000000..3d27b7cb5c --- /dev/null +++ b/openshift/oai-ran-rh8-build-config.yml @@ -0,0 +1,57 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +kind: BuildConfig +apiVersion: build.openshift.io/v1 +metadata: + name: "oai-ran-rhel8-build-config" +spec: + runPolicy: "Serial" + source: + git: + uri: "https://gitlab.eurecom.fr/oai/openairinterface5g.git" + ref: "develop" + httpProxy: http://proxy.eurecom.fr:8080 + httpsProxy: https://proxy.eurecom.fr:8080 + secrets: + - secret: + name: etc-pki-entitlement + destinationDir: etc-pki-entitlement + configMaps: + - configMap: + name: rhsm-conf + destinationDir: rhsm-conf + - configMap: + name: rhsm-ca + destinationDir: rhsm-ca + strategy: + dockerStrategy: + dockerfilePath: "docker/Dockerfile.ran.rhel8.2.oc4-4" + nodeSelector: + kubernetes.io/hostname: dedale.5glab.nsa.eurecom.fr + resources: + requests: + ephemeral-storage: "5Gi" + output: + to: + kind: "ImageStreamTag" + name: "oai-ran:rhel8-latest" diff --git a/openshift/oai-ran-rh8-image-stream.yml b/openshift/oai-ran-rh8-image-stream.yml new file mode 100644 index 0000000000..f6f4f8614f --- /dev/null +++ b/openshift/oai-ran-rh8-image-stream.yml @@ -0,0 +1,30 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 +# * +# * 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. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# +apiVersion: v1 +kind: ImageStream +metadata: + name: oai-ran + namespace: oai +status: + tag: rhel8-latest + diff --git a/rxsigF0.m b/rxsigF0.m new file mode 100644 index 0000000000..3309e1aa6f --- /dev/null +++ b/rxsigF0.m @@ -0,0 +1,57345 @@ +rxsF0 = [173 + j*(-306) +-141 + j*(-130) +-166 + j*(-246) +-107 + j*(-42) +-105 + j*(0) +-179 + j*(-28) +-87 + j*(186) +-95 + j*(151) +-1 + j*(228) +172 + j*(-62) +110 + j*(-5) +-178 + j*(-33) +-18 + j*(57) +9 + j*(146) +-11 + j*(103) +-67 + j*(64) +28 + j*(-375) +-72 + j*(-75) +-14 + j*(-318) +194 + j*(193) +-173 + j*(-228) +295 + j*(119) +203 + j*(-179) +-238 + j*(-276) +-286 + j*(112) +-409 + j*(95) +-260 + j*(84) +72 + j*(40) +105 + j*(-120) +57 + j*(66) +58 + j*(173) +-170 + j*(-189) +192 + j*(-50) +-88 + j*(160) +-187 + j*(-132) +120 + j*(41) +239 + j*(-115) +80 + j*(263) +-45 + j*(-30) +396 + j*(192) +161 + j*(-11) +-325 + j*(296) +-64 + j*(-192) +-181 + j*(-59) +-272 + j*(192) +11 + j*(192) +-215 + j*(50) +122 + j*(177) +-255 + j*(26) +87 + j*(11) +-86 + j*(-129) +-199 + j*(199) +-238 + j*(163) +29 + j*(134) +175 + j*(81) +30 + j*(-214) +-344 + j*(131) +124 + j*(-252) +134 + j*(-325) +224 + j*(-78) +223 + j*(-190) +-15 + j*(88) +-223 + j*(128) +-48 + j*(-223) +-109 + j*(-209) +-17 + j*(-84) +179 + j*(73) +-25 + j*(-81) +6 + j*(88) +8 + j*(83) +-75 + j*(38) +-119 + j*(51) +15 + j*(199) +140 + j*(42) +44 + j*(-132) +-247 + j*(118) +242 + j*(-82) +140 + j*(-258) +-98 + j*(28) +262 + j*(107) +-141 + j*(-21) +137 + j*(382) +64 + j*(-163) +-81 + j*(62) +54 + j*(245) +-132 + j*(75) +196 + j*(-219) +-146 + j*(211) +-64 + j*(64) +-146 + j*(-37) +-37 + j*(-94) +-318 + j*(160) +-237 + j*(112) +-98 + j*(2) +-286 + j*(209) +-69 + j*(192) +-52 + j*(105) +-63 + j*(-35) +119 + j*(59) +-19 + j*(-25) +110 + j*(54) +45 + j*(-37) +42 + j*(-107) +57 + j*(74) +190 + j*(105) +246 + j*(20) +233 + j*(93) +290 + j*(180) +232 + j*(-113) +281 + j*(243) +280 + j*(-250) +47 + j*(-245) +144 + j*(-150) +-272 + j*(25) +-94 + j*(163) +-135 + j*(-334) +16 + j*(-211) +-165 + j*(214) +88 + j*(34) +27 + j*(-36) +-161 + j*(-243) +94 + j*(151) +112 + j*(-66) +-180 + j*(48) +-77 + j*(-64) +-293 + j*(300) +-42 + j*(-139) +-177 + j*(91) +-37 + j*(-39) +-88 + j*(216) +-123 + j*(1) +141 + j*(-250) +100 + j*(-148) +-11 + j*(265) +30 + j*(-212) +-9 + j*(146) +281 + j*(223) +-166 + j*(141) +-7 + j*(-51) +69 + j*(-37) +-91 + j*(45) +198 + j*(-225) +560 + j*(-64) +-245 + j*(-145) +194 + j*(231) +-96 + j*(216) +8 + j*(-158) +117 + j*(42) +-42 + j*(132) +97 + j*(178) +-182 + j*(-65) +-59 + j*(118) +129 + j*(-45) +75 + j*(-6) +-88 + j*(20) +-425 + j*(35) +140 + j*(424) +-40 + j*(116) +27 + j*(-297) +123 + j*(230) +86 + j*(-293) +104 + j*(-127) +47 + j*(-89) +60 + j*(97) +-23 + j*(197) +-7 + j*(-93) +115 + j*(205) +271 + j*(-159) +-56 + j*(159) +-57 + j*(556) +-48 + j*(-196) +-71 + j*(-63) +-353 + j*(-221) +-84 + j*(-173) +30 + j*(45) +-302 + j*(371) +354 + j*(-22) +-233 + j*(35) +-308 + j*(-202) +-433 + j*(-44) +-158 + j*(73) +185 + j*(-150) +48 + j*(124) +-7 + j*(168) +190 + j*(78) +211 + j*(-9) +-71 + j*(-193) +-119 + j*(97) +-234 + j*(-197) +341 + j*(-197) +-346 + j*(74) +105 + j*(17) +57 + j*(-105) +-161 + j*(-138) +-180 + j*(180) +-156 + j*(91) +-9 + j*(-139) +-87 + j*(165) +-64 + j*(-238) +15 + j*(-221) +-113 + j*(8) +-331 + j*(59) +90 + j*(-150) +-136 + j*(-325) +73 + j*(178) +-18 + j*(170) +67 + j*(-96) +85 + j*(-37) +-9 + j*(-114) +-22 + j*(136) +-175 + j*(165) +-87 + j*(-25) +-31 + j*(-152) +-301 + j*(-18) +42 + j*(-54) +-32 + j*(-168) +-74 + j*(163) +-54 + j*(-52) +-76 + j*(-21) +67 + j*(73) +129 + j*(-255) +-270 + j*(203) +-112 + j*(-71) +-106 + j*(13) +175 + j*(-194) +6 + j*(110) +115 + j*(135) +-22 + j*(-50) +143 + j*(220) +-17 + j*(-82) +-65 + j*(204) +-46 + j*(-112) +86 + j*(-199) +3 + j*(-52) +88 + j*(116) +184 + j*(227) +-65 + j*(189) +-54 + j*(-150) +139 + j*(206) +122 + j*(72) +-71 + j*(194) +-134 + j*(287) +44 + j*(-124) +13 + j*(-250) +-100 + j*(95) +-110 + j*(16) +233 + j*(-139) +228 + j*(-39) +-252 + j*(133) +-122 + j*(-129) +21 + j*(-143) +-55 + j*(-144) +-199 + j*(14) +110 + j*(-195) +85 + j*(-45) +-243 + j*(-35) +59 + j*(-86) +-361 + j*(179) +69 + j*(34) +-22 + j*(42) +-267 + j*(-294) +28 + j*(-84) +40 + j*(-247) +-112 + j*(128) +54 + j*(182) +71 + j*(-33) +-40 + j*(448) +-75 + j*(-132) +10 + j*(-37) +272 + j*(-126) +-209 + j*(-100) +-98 + j*(58) +72 + j*(391) +25 + j*(21) +-126 + j*(-110) +-238 + j*(138) +227 + j*(-283) +64 + j*(-523) +-42 + j*(392) +103 + j*(-288) +-131 + j*(-207) +88 + j*(3) +-81 + j*(382) +-4 + j*(119) +177 + j*(-137) +-95 + j*(228) +39 + j*(-127) +-265 + j*(202) +145 + j*(66) +-358 + j*(127) +-320 + j*(-144) +-48 + j*(-260) +119 + j*(37) +-359 + j*(49) +257 + j*(-112) +112 + j*(84) +30 + j*(171) +136 + j*(-186) +-250 + j*(-115) +-274 + j*(-281) +-37 + j*(1) +69 + j*(130) +-125 + j*(-184) +-315 + j*(-75) +-93 + j*(104) +64 + j*(-6) +198 + j*(141) +-88 + j*(18) +248 + j*(-57) +-107 + j*(74) +-71 + j*(26) +-90 + j*(-21) +-282 + j*(-201) +57 + j*(47) +-15 + j*(33) +-144 + j*(153) +-202 + j*(-221) +-124 + j*(-175) +-146 + j*(-276) +-74 + j*(39) +-91 + j*(512) +125 + j*(213) +139 + j*(168) +-233 + j*(-91) +60 + j*(-132) +-36 + j*(-132) +21 + j*(105) +-129 + j*(231) +-283 + j*(191) +320 + j*(134) +-171 + j*(70) +-133 + j*(66) +189 + j*(47) +188 + j*(-88) +-16 + j*(263) +-44 + j*(4) +93 + j*(-2) +33 + j*(2) +30 + j*(211) +-114 + j*(-76) +54 + j*(12) +-128 + j*(-8) +-23 + j*(265) +-235 + j*(224) +-56 + j*(260) +30 + j*(106) +-150 + j*(-223) +-37 + j*(-291) +-175 + j*(177) +-165 + j*(259) +-206 + j*(63) +131 + j*(-61) +-43 + j*(-186) +-90 + j*(14) +79 + j*(-190) +-127 + j*(115) +48 + j*(28) +-5 + j*(17) +-28 + j*(47) +163 + j*(135) +44 + j*(-125) +-86 + j*(275) +1 + j*(117) +49 + j*(-62) +147 + j*(80) +85 + j*(84) +-31 + j*(-101) +243 + j*(150) +-181 + j*(-219) +-138 + j*(-10) +-214 + j*(-151) +27 + j*(-88) +211 + j*(86) +-162 + j*(-350) +-455 + j*(77) +237 + j*(30) +18 + j*(189) +-131 + j*(119) +18 + j*(96) +85 + j*(78) +182 + j*(155) +6 + j*(250) +195 + j*(-153) +-74 + j*(-51) +44 + j*(-60) +-234 + j*(221) +359 + j*(-139) +-228 + j*(291) +-28 + j*(173) +-147 + j*(-59) +-357 + j*(100) +-86 + j*(464) +-113 + j*(-74) +-282 + j*(356) +16 + j*(-52) +204 + j*(-316) +258 + j*(178) +-75 + j*(100) +-113 + j*(83) +158 + j*(309) +65 + j*(-170) +91 + j*(-125) +-151 + j*(318) +-52 + j*(-18) +-138 + j*(176) +-226 + j*(30) +-177 + j*(39) +-150 + j*(-13) +35 + j*(-183) +204 + j*(-308) +186 + j*(-243) +-115 + j*(-71) +66 + j*(55) +-88 + j*(-128) +-109 + j*(195) +-244 + j*(-90) +175 + j*(-177) +231 + j*(-194) +-59 + j*(101) +23 + j*(-8) +-117 + j*(209) +-16 + j*(-97) +4 + j*(190) +-28 + j*(-67) +-94 + j*(3) +-54 + j*(-21) +-27 + j*(83) +-127 + j*(-21) +187 + j*(-289) +3 + j*(-82) +-1 + j*(-223) +-168 + j*(232) +-148 + j*(163) +274 + j*(-324) +-156 + j*(-82) +384 + j*(162) +-91 + j*(94) +-37 + j*(10) +-66 + j*(330) +-85 + j*(-8) +62 + j*(216) +-98 + j*(95) +126 + j*(189) +196 + j*(-243) +81 + j*(-42) +-250 + j*(-2) +118 + j*(146) +-1 + j*(-98) +88 + j*(-234) +-151 + j*(25) +175 + j*(235) +36 + j*(-182) +-108 + j*(69) +105 + j*(-38) +-175 + j*(-36) +-327 + j*(-45) +80 + j*(268) +13 + j*(-43) +-87 + j*(57) +-70 + j*(-112) +192 + j*(71) +-369 + j*(-114) +224 + j*(341) +-144 + j*(-145) +262 + j*(105) +-91 + j*(-185) +-6 + j*(116) +-344 + j*(-245) +90 + j*(-101) +147 + j*(-123) +-76 + j*(-71) +6 + j*(197) +-44 + j*(-130) +21 + j*(-84) +448 + j*(74) +175 + j*(-3) +-175 + j*(-156) +-18 + j*(-110) +-95 + j*(-250) +-107 + j*(172) +-110 + j*(157) +132 + j*(6) +47 + j*(146) +212 + j*(-167) +95 + j*(40) +-239 + j*(-44) +97 + j*(134) +-104 + j*(-193) +-363 + j*(-244) +86 + j*(-1) +72 + j*(-13) +62 + j*(157) +214 + j*(-103) +-161 + j*(-3) +-252 + j*(-139) +147 + j*(39) +30 + j*(-73) +-100 + j*(-203) +159 + j*(-250) +-323 + j*(-118) +-35 + j*(-88) +-76 + j*(-105) +-24 + j*(28) +-194 + j*(-233) +-272 + j*(23) +-204 + j*(89) +-83 + j*(-110) +-88 + j*(110) +254 + j*(-103) +32 + j*(136) +92 + j*(-226) +-92 + j*(-203) +-136 + j*(94) +-283 + j*(-192) +161 + j*(272) +-102 + j*(30) +71 + j*(-71) +158 + j*(58) +-71 + j*(-139) +220 + j*(-131) +225 + j*(-135) +-222 + j*(332) +-296 + j*(-165) +-156 + j*(-104) +-216 + j*(164) +305 + j*(-68) +-102 + j*(47) +-25 + j*(66) +28 + j*(250) +120 + j*(-64) +-120 + j*(-134) +-42 + j*(114) +18 + j*(32) +-83 + j*(157) +115 + j*(-25) +-247 + j*(-110) +-53 + j*(206) +170 + j*(-30) +-86 + j*(100) +384 + j*(119) +-332 + j*(-5) +-37 + j*(163) +74 + j*(285) +139 + j*(-320) +-286 + j*(18) +21 + j*(313) +125 + j*(50) +-30 + j*(530) +153 + j*(24) +115 + j*(-141) +-392 + j*(-131) +194 + j*(-179) +167 + j*(211) +161 + j*(133) +101 + j*(-263) +-185 + j*(-81) +-6 + j*(240) +257 + j*(71) +-30 + j*(68) +-143 + j*(29) +124 + j*(154) +296 + j*(-67) +360 + j*(-25) +187 + j*(-21) +-70 + j*(409) +-95 + j*(39) +53 + j*(161) +-158 + j*(64) +-141 + j*(112) +414 + j*(-13) +-153 + j*(-59) +-189 + j*(-54) +-69 + j*(19) +1 + j*(-12) +191 + j*(192) +-133 + j*(-95) +-245 + j*(232) +86 + j*(-66) +-173 + j*(129) +63 + j*(131) +-348 + j*(-260) +143 + j*(-136) +-97 + j*(-107) +135 + j*(58) +184 + j*(-80) +-7 + j*(363) +-285 + j*(-198) +-103 + j*(290) +134 + j*(87) +-22 + j*(-163) +66 + j*(-226) +182 + j*(54) +-204 + j*(-52) +-194 + j*(161) +-63 + j*(-117) +61 + j*(98) +49 + j*(-33) +-152 + j*(40) +177 + j*(-91) +22 + j*(-106) +89 + j*(-54) +37 + j*(-148) +286 + j*(-67) +-114 + j*(69) +13 + j*(127) +-218 + j*(-8) +-154 + j*(19) +73 + j*(138) +-132 + j*(16) +185 + j*(117) +-136 + j*(351) +-121 + j*(98) +184 + j*(-65) +187 + j*(51) +119 + j*(68) +-85 + j*(-50) +145 + j*(-25) +-8 + j*(61) +137 + j*(325) +-124 + j*(-22) +326 + j*(-175) +-25 + j*(86) +279 + j*(-95) +8 + j*(159) +-4 + j*(186) +390 + j*(-138) +-162 + j*(-42) +-28 + j*(114) +153 + j*(44) +340 + j*(-112) +-300 + j*(-58) +-86 + j*(-173) +267 + j*(-119) +209 + j*(74) +-279 + j*(105) +-37 + j*(-37) +-59 + j*(80) +-148 + j*(-163) +81 + j*(-156) +-163 + j*(80) +-73 + j*(378) +-189 + j*(190) +-35 + j*(-102) +-49 + j*(-172) +-177 + j*(-221) +-4 + j*(215) +-297 + j*(1) +-94 + j*(-299) +129 + j*(-374) +-38 + j*(-16) +-21 + j*(-97) +-215 + j*(-75) +147 + j*(111) +-173 + j*(-72) +92 + j*(-138) +110 + j*(132) +28 + j*(16) +-143 + j*(-182) +-109 + j*(325) +-30 + j*(128) +-200 + j*(-168) +-148 + j*(-261) +132 + j*(-63) +-30 + j*(-14) +-238 + j*(-55) +-67 + j*(26) +-214 + j*(1) +-180 + j*(-286) +-147 + j*(-66) +205 + j*(41) +152 + j*(-89) +35 + j*(148) +-112 + j*(38) +156 + j*(-81) +-177 + j*(104) +-194 + j*(307) +-46 + j*(-199) +-290 + j*(35) +-170 + j*(28) +-23 + j*(214) +-78 + j*(-90) +-52 + j*(249) +-140 + j*(-72) +175 + j*(-34) +103 + j*(115) +266 + j*(-186) +70 + j*(-192) +-204 + j*(94) +18 + j*(287) +-173 + j*(289) +136 + j*(216) +-98 + j*(164) +-37 + j*(185) +-147 + j*(59) +-105 + j*(-132) +51 + j*(139) +68 + j*(165) +-330 + j*(-124) +-30 + j*(-76) +5 + j*(-193) +209 + j*(-233) +63 + j*(117) +-260 + j*(-180) +-34 + j*(182) +40 + j*(-52) +97 + j*(-188) +-62 + j*(-71) +-13 + j*(-250) +-15 + j*(234) +243 + j*(-193) +26 + j*(-392) +-129 + j*(69) +-143 + j*(-115) +-108 + j*(56) +-52 + j*(282) +-7 + j*(-90) +37 + j*(-105) +-615 + j*(-199) +-74 + j*(85) +-322 + j*(-64) +69 + j*(-165) +-70 + j*(101) +29 + j*(92) +-150 + j*(-327) +54 + j*(89) +-398 + j*(186) +-102 + j*(-121) +-269 + j*(-71) +52 + j*(-62) +170 + j*(-125) +6 + j*(-69) +-76 + j*(-327) +35 + j*(139) +-3 + j*(-87) +-322 + j*(167) +4 + j*(-26) +184 + j*(160) +-178 + j*(-75) +109 + j*(62) +50 + j*(54) +-64 + j*(-115) +-371 + j*(-247) +-124 + j*(-45) +-211 + j*(-123) +153 + j*(86) +-222 + j*(-161) +-163 + j*(-173) +-17 + j*(263) +171 + j*(27) +287 + j*(105) +31 + j*(-233) +-8 + j*(-81) +37 + j*(120) +-8 + j*(21) +3 + j*(-138) +95 + j*(202) +511 + j*(81) +-117 + j*(-196) +35 + j*(28) +-136 + j*(-301) +182 + j*(-140) +-60 + j*(-66) +-206 + j*(-111) +231 + j*(27) +48 + j*(49) +206 + j*(315) +86 + j*(93) +131 + j*(-232) +-161 + j*(6) +22 + j*(306) +-307 + j*(-81) +-170 + j*(87) +173 + j*(1) +-286 + j*(-155) +-278 + j*(-192) +10 + j*(-42) +-153 + j*(202) +377 + j*(35) +8 + j*(-47) +-54 + j*(-46) +138 + j*(-201) +26 + j*(-49) +235 + j*(-73) +-143 + j*(-291) +-103 + j*(-30) +18 + j*(-281) +311 + j*(122) +9 + j*(-27) +-240 + j*(50) +-110 + j*(209) +187 + j*(-209) +68 + j*(247) +498 + j*(-59) +161 + j*(-189) +-132 + j*(72) +-127 + j*(18) +-193 + j*(-185) +-127 + j*(-276) +-104 + j*(235) +-26 + j*(165) +148 + j*(-181) +87 + j*(-107) +-177 + j*(136) +173 + j*(2) +-298 + j*(-63) +218 + j*(29) +-330 + j*(-167) +110 + j*(127) +-18 + j*(-42) +-85 + j*(153) +-92 + j*(-119) +23 + j*(115) +149 + j*(-76) +-132 + j*(85) +-163 + j*(-52) +-139 + j*(303) +151 + j*(113) +264 + j*(74) +48 + j*(115) +-38 + j*(-9) +-232 + j*(262) +412 + j*(123) +28 + j*(108) +-53 + j*(-95) +-79 + j*(184) +-252 + j*(192) +170 + j*(39) +220 + j*(249) +-5 + j*(-8) +125 + j*(27) +147 + j*(-80) +25 + j*(-272) +52 + j*(47) +248 + j*(-56) +-84 + j*(-51) +-93 + j*(-395) +-179 + j*(221) +-110 + j*(108) +13 + j*(26) +332 + j*(336) +31 + j*(-141) +-2 + j*(76) +334 + j*(-79) +28 + j*(86) +307 + j*(-129) +-251 + j*(197) +-21 + j*(-36) +-117 + j*(71) +-279 + j*(42) +220 + j*(216) +135 + j*(-161) +345 + j*(-245) +40 + j*(-155) +-61 + j*(159) +105 + j*(52) +278 + j*(-63) +-40 + j*(35) +-47 + j*(326) +-171 + j*(-151) +83 + j*(177) +-250 + j*(-70) +20 + j*(-68) +87 + j*(-123) +-325 + j*(-98) +-3 + j*(81) +-21 + j*(165) +97 + j*(295) +554 + j*(168) +-192 + j*(-154) +14 + j*(-11) +-201 + j*(67) +-163 + j*(153) +-23 + j*(-153) +-44 + j*(-7) +-18 + j*(63) +-110 + j*(-35) +471 + j*(-202) +267 + j*(-194) +-140 + j*(-358) +-204 + j*(-94) +-25 + j*(-147) +59 + j*(199) +58 + j*(-13) +-36 + j*(-114) +115 + j*(-163) +190 + j*(226) +-142 + j*(-144) +51 + j*(-93) +68 + j*(-77) +1 + j*(-323) +95 + j*(-72) +-112 + j*(3) +202 + j*(284) +-261 + j*(18) +-358 + j*(122) +-129 + j*(-37) +80 + j*(-91) +59 + j*(132) +274 + j*(-385) +54 + j*(-131) +-49 + j*(-127) +-94 + j*(-332) +276 + j*(-44) +332 + j*(139) +13 + j*(-103) +-63 + j*(137) +115 + j*(-137) +-117 + j*(233) +10 + j*(-170) +-358 + j*(-182) +-37 + j*(15) +68 + j*(9) +342 + j*(-268) +-127 + j*(-199) +141 + j*(-452) +-265 + j*(1) +-180 + j*(236) +-18 + j*(4) +35 + j*(228) +-30 + j*(8) +182 + j*(-211) +-233 + j*(0) +-79 + j*(-53) +-159 + j*(100) +-29 + j*(-131) +-22 + j*(27) +-136 + j*(165) +44 + j*(146) +-162 + j*(21) +60 + j*(-158) +-127 + j*(-2) +-11 + j*(191) +-139 + j*(9) +315 + j*(115) +175 + j*(-193) +-45 + j*(250) +36 + j*(2) +141 + j*(-198) +-307 + j*(2) +144 + j*(-59) +122 + j*(-27) +-211 + j*(-483) +185 + j*(58) +39 + j*(127) +-238 + j*(-109) +106 + j*(345) +76 + j*(33) +239 + j*(207) +-109 + j*(-249) +-146 + j*(45) +-38 + j*(-150) +78 + j*(-186) +8 + j*(71) +-207 + j*(-255) +85 + j*(16) +-23 + j*(-153) +82 + j*(-11) +-10 + j*(116) +162 + j*(-201) +66 + j*(-116) +277 + j*(163) +102 + j*(-358) +54 + j*(10) +37 + j*(-112) +127 + j*(-64) +-74 + j*(-93) +-54 + j*(214) +149 + j*(-37) +-269 + j*(-66) +-13 + j*(-220) +-120 + j*(76) +97 + j*(75) +238 + j*(-78) +263 + j*(-293) +-57 + j*(-131) +127 + j*(-202) +235 + j*(-105) +226 + j*(-18) +-107 + j*(-286) +194 + j*(-118) +104 + j*(-121) +21 + j*(117) +380 + j*(92) +22 + j*(-190) +79 + j*(37) +175 + j*(180) +42 + j*(-70) +40 + j*(-174) +-36 + j*(-141) +-165 + j*(92) +9 + j*(-335) +328 + j*(-194) +-198 + j*(-147) +342 + j*(-129) +71 + j*(-201) +176 + j*(-66) +16 + j*(-255) +179 + j*(-119) +89 + j*(133) +144 + j*(-78) +106 + j*(235) +175 + j*(-324) +-68 + j*(315) +-265 + j*(-374) +-28 + j*(14) +-213 + j*(106) +106 + j*(-163) +49 + j*(-71) +-151 + j*(6) +-421 + j*(119) +-244 + j*(23) +81 + j*(-57) +-259 + j*(-230) +177 + j*(101) +-48 + j*(-308) +147 + j*(57) +152 + j*(47) +-194 + j*(-25) +-116 + j*(356) +-68 + j*(149) +7 + j*(-132) +-126 + j*(-159) +-177 + j*(272) +226 + j*(-257) +-158 + j*(51) +-73 + j*(214) +47 + j*(-237) +161 + j*(250) +83 + j*(105) +103 + j*(35) +99 + j*(81) +-6 + j*(0) +-122 + j*(39) +-116 + j*(-209) +-172 + j*(-250) +179 + j*(-8) +-174 + j*(134) +-71 + j*(-194) +105 + j*(257) +-124 + j*(100) +33 + j*(-117) +-73 + j*(53) +144 + j*(-12) +-185 + j*(-141) +136 + j*(110) +45 + j*(117) +-7 + j*(-195) +-86 + j*(172) +-23 + j*(-103) +-263 + j*(-26) +-37 + j*(124) +166 + j*(392) +-373 + j*(111) +-34 + j*(-202) +63 + j*(299) +474 + j*(273) +-264 + j*(-284) +-119 + j*(33) +227 + j*(-117) +-98 + j*(135) +-47 + j*(-141) +-158 + j*(-36) +160 + j*(38) +-29 + j*(66) +144 + j*(-272) +-171 + j*(-107) +357 + j*(-86) +-231 + j*(-86) +-75 + j*(-76) +216 + j*(156) +-13 + j*(-187) +-88 + j*(37) +119 + j*(270) +31 + j*(-77) +-140 + j*(37) +21 + j*(-17) +211 + j*(-33) +-287 + j*(101) +-112 + j*(142) +-3 + j*(-140) +-91 + j*(-151) +150 + j*(-243) +-64 + j*(96) +-262 + j*(163) +196 + j*(-39) +-126 + j*(-71) +-161 + j*(102) +-125 + j*(35) +292 + j*(98) +-6 + j*(192) +107 + j*(-71) +83 + j*(-193) +272 + j*(-25) +235 + j*(67) +-87 + j*(-159) +-54 + j*(-118) +-279 + j*(-4) +29 + j*(-20) +132 + j*(314) +-73 + j*(-148) +-470 + j*(86) +262 + j*(-260) +-76 + j*(-42) +256 + j*(64) +-18 + j*(-144) +40 + j*(-151) +75 + j*(-166) +-196 + j*(21) +-45 + j*(184) +121 + j*(18) +-89 + j*(-148) +-170 + j*(-18) +338 + j*(-150) +-276 + j*(221) +-177 + j*(236) +139 + j*(-134) +139 + j*(213) +33 + j*(233) +-53 + j*(16) +-219 + j*(-206) +301 + j*(-21) +83 + j*(-59) +47 + j*(-66) +325 + j*(-275) +53 + j*(10) +-25 + j*(106) +85 + j*(-86) +-150 + j*(-16) +-172 + j*(-122) +317 + j*(-115) +66 + j*(-1) +-176 + j*(4) +-47 + j*(-43) +-122 + j*(-28) +79 + j*(519) +-87 + j*(190) +81 + j*(-124) +149 + j*(-67) +-68 + j*(-148) +-154 + j*(-199) +-127 + j*(94) +-21 + j*(-108) +-185 + j*(155) +-327 + j*(223) +127 + j*(27) +140 + j*(118) +260 + j*(-68) +-228 + j*(200) +-431 + j*(-226) +97 + j*(153) +68 + j*(25) +-226 + j*(245) +-83 + j*(133) +23 + j*(45) +70 + j*(52) +-4 + j*(-66) +-137 + j*(71) +-110 + j*(78) +95 + j*(-11) +93 + j*(-266) +-163 + j*(103) +-246 + j*(-91) +-9 + j*(-296) +177 + j*(-14) +-151 + j*(-157) +60 + j*(73) +54 + j*(308) +165 + j*(-85) +106 + j*(-66) +-205 + j*(-183) +45 + j*(107) +71 + j*(-59) +249 + j*(27) +10 + j*(168) +-153 + j*(-134) +-40 + j*(208) +-214 + j*(156) +77 + j*(220) +115 + j*(103) +52 + j*(-8) +-93 + j*(133) +-163 + j*(78) +283 + j*(22) +-500 + j*(-91) +-42 + j*(-286) +25 + j*(143) +-62 + j*(350) +303 + j*(157) +-164 + j*(-109) +36 + j*(-296) +166 + j*(19) +298 + j*(161) +99 + j*(-253) +37 + j*(-6) +-117 + j*(245) +191 + j*(-123) +153 + j*(-14) +107 + j*(77) +-71 + j*(-195) +266 + j*(-438) +163 + j*(3) +-202 + j*(-173) +-95 + j*(62) +11 + j*(337) +33 + j*(-120) +206 + j*(-425) +-189 + j*(-49) +183 + j*(118) +-66 + j*(144) +-214 + j*(-160) +88 + j*(-28) +-49 + j*(102) +-262 + j*(-225) +-136 + j*(-174) +-87 + j*(265) +-43 + j*(-2) +68 + j*(36) +47 + j*(-197) +-139 + j*(194) +14 + j*(332) +89 + j*(-95) +-348 + j*(-112) +122 + j*(-240) +221 + j*(132) +170 + j*(-24) +310 + j*(-73) +-103 + j*(-392) +61 + j*(-144) +112 + j*(-128) +73 + j*(52) +48 + j*(435) +224 + j*(169) +116 + j*(-322) +91 + j*(-1) +-40 + j*(243) +72 + j*(-96) +159 + j*(-83) +69 + j*(30) +-173 + j*(316) +322 + j*(-42) +99 + j*(208) +76 + j*(-222) +-35 + j*(-66) +4 + j*(-345) +-223 + j*(-115) +-37 + j*(212) +-119 + j*(6) +-23 + j*(-83) +-25 + j*(-12) +-78 + j*(-47) +166 + j*(69) +116 + j*(72) +-60 + j*(105) +165 + j*(53) +83 + j*(-57) +-48 + j*(337) +35 + j*(-71) +-260 + j*(124) +-185 + j*(49) +-117 + j*(-358) +138 + j*(-20) +-103 + j*(-228) +-87 + j*(105) +-141 + j*(-50) +160 + j*(124) +-448 + j*(42) +-87 + j*(36) +-227 + j*(-343) +-188 + j*(-226) +-101 + j*(-183) +-8 + j*(-93) +-264 + j*(-92) +233 + j*(57) +5 + j*(6) +-47 + j*(122) +46 + j*(11) +-13 + j*(-95) +-35 + j*(60) +203 + j*(-5) +-267 + j*(25) +112 + j*(-79) +329 + j*(-30) +111 + j*(-98) +-238 + j*(286) +-76 + j*(-166) +103 + j*(-232) +-41 + j*(-90) +28 + j*(182) +190 + j*(-57) +203 + j*(-90) +-51 + j*(-117) +74 + j*(120) +-161 + j*(-360) +72 + j*(-57) +296 + j*(-36) +146 + j*(-111) +149 + j*(-75) +-59 + j*(-81) +104 + j*(-30) +198 + j*(124) +-120 + j*(-214) +-98 + j*(63) +-127 + j*(-165) +284 + j*(-8) +-92 + j*(-310) +-368 + j*(105) +-314 + j*(-363) +184 + j*(265) +-100 + j*(-36) +-134 + j*(-56) +-158 + j*(121) +72 + j*(-204) +130 + j*(44) +-209 + j*(-211) +62 + j*(-212) +177 + j*(100) +78 + j*(-333) +-42 + j*(-40) +-37 + j*(125) +57 + j*(21) +182 + j*(-21) +3 + j*(-171) +243 + j*(-354) +344 + j*(57) +-157 + j*(-167) +121 + j*(59) +151 + j*(145) +-162 + j*(-107) +181 + j*(-11) +-32 + j*(383) +86 + j*(7) +-135 + j*(-260) +-79 + j*(-11) +-136 + j*(-334) +66 + j*(219) +300 + j*(1) +-116 + j*(-202) +186 + j*(-223) +228 + j*(400) +-150 + j*(-101) +161 + j*(-204) +-10 + j*(53) +-236 + j*(172) +143 + j*(-182) +10 + j*(272) +55 + j*(184) +32 + j*(-390) +-69 + j*(317) +-37 + j*(11) +-74 + j*(30) +140 + j*(-83) +53 + j*(-136) +200 + j*(-285) +-189 + j*(-378) +-101 + j*(-253) +-25 + j*(78) +17 + j*(-104) +-180 + j*(196) +-148 + j*(-309) +-317 + j*(119) +141 + j*(79) +-41 + j*(-72) +-162 + j*(-63) +-65 + j*(-35) +-110 + j*(49) +110 + j*(-48) +19 + j*(92) +-148 + j*(14) +-102 + j*(280) +139 + j*(43) +-36 + j*(-207) +40 + j*(-76) +172 + j*(-279) +-35 + j*(224) +414 + j*(-378) +157 + j*(-112) +529 + j*(-307) +-1 + j*(-74) +-11 + j*(330) +236 + j*(-36) +-158 + j*(-353) +-215 + j*(-29) +185 + j*(174) +-8 + j*(-27) +306 + j*(170) +-214 + j*(-102) +-73 + j*(37) +199 + j*(-156) +230 + j*(-113) +-2 + j*(-106) +-80 + j*(204) +40 + j*(-276) +196 + j*(-459) +-330 + j*(-98) +-267 + j*(83) +-15 + j*(-58) +-163 + j*(403) +-126 + j*(-262) +-215 + j*(178) +89 + j*(121) +-132 + j*(130) +154 + j*(210) +-159 + j*(337) +-264 + j*(161) +25 + j*(201) +-21 + j*(102) +-132 + j*(101) +6 + j*(98) +-19 + j*(-328) +62 + j*(-122) +-151 + j*(-103) +-72 + j*(316) +150 + j*(-520) +438 + j*(378) +144 + j*(462) +161 + j*(15) +42 + j*(-182) +-123 + j*(479) +-248 + j*(145) +-416 + j*(305) +34 + j*(-459) +334 + j*(133) +391 + j*(-385) +-167 + j*(324) +-98 + j*(104) +444 + j*(-168) +151 + j*(-241) +-143 + j*(56) +-148 + j*(281) +-276 + j*(269) +260 + j*(-255) +173 + j*(-64) +534 + j*(206) +-692 + j*(597) +173 + j*(-259) +235 + j*(346) +-59 + j*(-310) +124 + j*(334) +-416 + j*(-148) +438 + j*(66) +-269 + j*(421) +-455 + j*(235) +355 + j*(-293) +-326 + j*(-148) +-332 + j*(-433) +-89 + j*(75) +468 + j*(-103) +376 + j*(-51) +-180 + j*(12) +91 + j*(-346) +-95 + j*(447) +-214 + j*(281) +107 + j*(256) +179 + j*(-77) +-397 + j*(-168) +-208 + j*(528) +-342 + j*(282) +212 + j*(-330) +-327 + j*(119) +339 + j*(-146) +112 + j*(346) +361 + j*(142) +-556 + j*(260) +-226 + j*(-152) +-368 + j*(-221) +-532 + j*(-147) +-494 + j*(-18) +614 + j*(-132) +274 + j*(-102) +-269 + j*(-486) +-263 + j*(134) +-486 + j*(426) +-143 + j*(-286) +-215 + j*(-343) +-383 + j*(-17) +-139 + j*(245) +346 + j*(157) +2 + j*(60) +264 + j*(64) +304 + j*(-49) +298 + j*(-491) +-375 + j*(-129) +170 + j*(109) +-226 + j*(-220) +450 + j*(117) +-173 + j*(221) +-119 + j*(484) +-325 + j*(-109) +-301 + j*(-263) +-227 + j*(-337) +-144 + j*(-313) +-93 + j*(-265) +-14 + j*(-269) +-456 + j*(25) +-330 + j*(127) +-286 + j*(351) +482 + j*(-336) +-387 + j*(436) +-182 + j*(260) +-327 + j*(-333) +-502 + j*(-140) +-131 + j*(-227) +-261 + j*(-309) +183 + j*(195) +-160 + j*(-465) +-325 + j*(-431) +212 + j*(-549) +19 + j*(-120) +73 + j*(-1) +-316 + j*(347) +192 + j*(265) +-192 + j*(-124) +260 + j*(417) +431 + j*(-404) +192 + j*(-508) +-54 + j*(-424) +370 + j*(18) +-393 + j*(-101) +434 + j*(-268) +50 + j*(-37) +504 + j*(-91) +462 + j*(337) +-223 + j*(-328) +298 + j*(-308) +140 + j*(-303) +-208 + j*(-406) +378 + j*(-223) +-325 + j*(105) +-467 + j*(-122) +297 + j*(279) +-589 + j*(-381) +252 + j*(185) +161 + j*(-177) +348 + j*(605) +-329 + j*(116) +122 + j*(-226) +-303 + j*(-57) +357 + j*(-264) +-152 + j*(-261) +-234 + j*(-112) +-66 + j*(37) +239 + j*(446) +-20 + j*(170) +-202 + j*(72) +-132 + j*(-164) +-121 + j*(-69) +-368 + j*(-541) +-16 + j*(356) +-226 + j*(-168) +-274 + j*(-315) +606 + j*(-180) +-187 + j*(-28) +-444 + j*(333) +-466 + j*(-235) +-121 + j*(-71) +-236 + j*(-49) +506 + j*(-332) +218 + j*(248) +-22 + j*(-289) +308 + j*(-8) +-85 + j*(414) +-154 + j*(360) +46 + j*(-332) +199 + j*(10) +-243 + j*(485) +-368 + j*(-624) +-367 + j*(170) +-339 + j*(274) +895 + j*(286) +148 + j*(-251) +167 + j*(156) +195 + j*(205) +27 + j*(-98) +86 + j*(-226) +-197 + j*(-206) +417 + j*(-226) +308 + j*(503) +401 + j*(-250) +-139 + j*(158) +108 + j*(190) +462 + j*(257) +14 + j*(-387) +360 + j*(155) +-435 + j*(-99) +361 + j*(416) +258 + j*(-62) +25 + j*(-333) +66 + j*(352) +546 + j*(-286) +-180 + j*(-458) +280 + j*(-151) +72 + j*(-216) +-368 + j*(403) +464 + j*(527) +-344 + j*(-60) +-129 + j*(516) +-279 + j*(348) +-249 + j*(257) +95 + j*(226) +180 + j*(170) +-97 + j*(-238) +-234 + j*(-164) +148 + j*(-344) +-190 + j*(-359) +152 + j*(537) +187 + j*(-93) +-264 + j*(311) +100 + j*(115) +329 + j*(-129) +-264 + j*(495) +281 + j*(296) +-216 + j*(-100) +255 + j*(635) +-410 + j*(324) +368 + j*(349) +-515 + j*(-427) +-296 + j*(-91) +-89 + j*(-357) +23 + j*(-220) +-39 + j*(-482) +366 + j*(613) +359 + j*(44) +270 + j*(-241) +146 + j*(-653) +-220 + j*(441) +269 + j*(125) +-350 + j*(321) +284 + j*(12) +-209 + j*(-60) +305 + j*(144) +-368 + j*(272) +468 + j*(-231) +176 + j*(12) +-149 + j*(-216) +424 + j*(-84) +-462 + j*(-520) +349 + j*(-377) +-361 + j*(166) +165 + j*(238) +-78 + j*(201) +-188 + j*(330) +-70 + j*(-25) +-220 + j*(330) +-206 + j*(308) +378 + j*(-181) +-203 + j*(-356) +501 + j*(-574) +63 + j*(134) +-493 + j*(-103) +-26 + j*(-341) +-390 + j*(158) +69 + j*(249) +279 + j*(358) +441 + j*(-253) +-142 + j*(142) +-346 + j*(-387) +332 + j*(-606) +187 + j*(240) +431 + j*(-35) +308 + j*(-181) +240 + j*(-338) +240 + j*(-168) +-429 + j*(-134) +161 + j*(-89) +-460 + j*(-346) +-382 + j*(247) +-521 + j*(-66) +99 + j*(318) +-193 + j*(-20) +148 + j*(551) +366 + j*(200) +560 + j*(-170) +281 + j*(280) +-462 + j*(-173) +-424 + j*(66) +190 + j*(354) +-135 + j*(-346) +-283 + j*(-282) +306 + j*(-280) +308 + j*(341) +57 + j*(-380) +-439 + j*(-147) +46 + j*(-188) +-189 + j*(136) +-167 + j*(281) +-73 + j*(-352) +286 + j*(165) +-353 + j*(152) +255 + j*(-443) +458 + j*(300) +126 + j*(-267) +-147 + j*(430) +756 + j*(232) +-462 + j*(-200) +-246 + j*(368) +392 + j*(501) +593 + j*(-118) +-341 + j*(274) +240 + j*(221) +-474 + j*(-129) +277 + j*(418) +-134 + j*(231) +-302 + j*(115) +101 + j*(337) +-122 + j*(-20) +503 + j*(-217) +473 + j*(-235) +-338 + j*(-158) +-43 + j*(472) +-428 + j*(-216) +-344 + j*(75) +-728 + j*(233) +-86 + j*(6) +337 + j*(-549) +-318 + j*(4) +-322 + j*(177) +141 + j*(-152) +445 + j*(85) +260 + j*(178) +54 + j*(128) +-45 + j*(103) +-320 + j*(307) +-640 + j*(-346) +-98 + j*(445) +-356 + j*(-291) +173 + j*(229) +-5 + j*(130) +142 + j*(248) +-248 + j*(412) +-18 + j*(494) +238 + j*(195) +-159 + j*(-196) +338 + j*(211) +767 + j*(-549) +516 + j*(185) +252 + j*(87) +-416 + j*(387) +371 + j*(-352) +-396 + j*(34) +455 + j*(34) +298 + j*(-147) +-377 + j*(119) +214 + j*(-19) +-242 + j*(-141) +115 + j*(305) +542 + j*(292) +58 + j*(-453) +199 + j*(-347) +-431 + j*(-128) +260 + j*(-252) +-175 + j*(491) +535 + j*(-119) +330 + j*(69) +-240 + j*(-301) +499 + j*(525) +-400 + j*(-455) +549 + j*(636) +247 + j*(-328) +-293 + j*(-170) +-178 + j*(270) +-119 + j*(250) +183 + j*(57) +252 + j*(97) +-539 + j*(-34) +-353 + j*(-15) +-105 + j*(-148) +-272 + j*(-336) +-338 + j*(-402) +-396 + j*(57) +292 + j*(41) +-204 + j*(-299) +281 + j*(333) +77 + j*(323) +-190 + j*(-385) +426 + j*(-128) +263 + j*(282) +16 + j*(18) +327 + j*(-40) +-411 + j*(-99) +387 + j*(91) +-238 + j*(166) +-72 + j*(11) +-508 + j*(233) +244 + j*(-490) +-442 + j*(216) +178 + j*(-419) +313 + j*(187) +266 + j*(-521) +390 + j*(-337) +448 + j*(-103) +425 + j*(-349) +-151 + j*(310) +283 + j*(-153) +320 + j*(-281) +56 + j*(99) +-202 + j*(-406) +-141 + j*(-409) +121 + j*(317) +380 + j*(371) +-177 + j*(-47) +361 + j*(-379) +-448 + j*(-28) +296 + j*(-269) +508 + j*(-238) +659 + j*(-47) +-298 + j*(-180) +104 + j*(174) +49 + j*(-67) +233 + j*(-449) +339 + j*(156) +258 + j*(-158) +-181 + j*(426) +278 + j*(-175) +-68 + j*(-334) +327 + j*(-599) +118 + j*(-216) +45 + j*(-304) +-158 + j*(216) +-257 + j*(204) +396 + j*(-415) +338 + j*(229) +-194 + j*(256) +-583 + j*(306) +103 + j*(-457) +185 + j*(-439) +478 + j*(66) +-255 + j*(464) +-145 + j*(346) +-660 + j*(-47) +-511 + j*(-410) +-288 + j*(453) +-258 + j*(250) +-115 + j*(-121) +134 + j*(344) +349 + j*(-287) +-503 + j*(205) +-383 + j*(-410) +-470 + j*(240) +325 + j*(-687) +221 + j*(-151) +426 + j*(418) +134 + j*(206) +88 + j*(-121) +-111 + j*(362) +-305 + j*(-182) +93 + j*(-185) +-174 + j*(406) +-417 + j*(240) +104 + j*(-155) +146 + j*(375) +618 + j*(146) +134 + j*(196) +-393 + j*(343) +-454 + j*(-76) +260 + j*(-24) +132 + j*(-68) +242 + j*(426) +106 + j*(-454) +-266 + j*(-200) +337 + j*(576) +180 + j*(95) +-257 + j*(116) +459 + j*(417) +-129 + j*(-160) +142 + j*(-197) +219 + j*(504) +154 + j*(170) +132 + j*(185) +316 + j*(264) +-440 + j*(200) +97 + j*(-3) +-9 + j*(-173) +249 + j*(-28) +612 + j*(-663) +-484 + j*(-26) +419 + j*(425) +-228 + j*(330) +4 + j*(-297) +445 + j*(201) +519 + j*(37) +333 + j*(158) +362 + j*(45) +333 + j*(-542) +187 + j*(-188) +-148 + j*(-273) +-329 + j*(241) +-148 + j*(-251) +423 + j*(-16) +90 + j*(-232) +-293 + j*(551) +-190 + j*(165) +-256 + j*(-518) +143 + j*(-260) +463 + j*(-392) +-295 + j*(-20) +14 + j*(-130) +2 + j*(293) +-354 + j*(-299) +409 + j*(298) +185 + j*(238) +383 + j*(220) +316 + j*(-39) +177 + j*(-8) +-269 + j*(-223) +-332 + j*(132) +-312 + j*(137) +-254 + j*(-224) +-279 + j*(-206) +103 + j*(276) +-81 + j*(235) +106 + j*(-356) +-250 + j*(170) +146 + j*(-256) +375 + j*(206) +35 + j*(285) +179 + j*(-480) +-4 + j*(262) +286 + j*(339) +349 + j*(3) +262 + j*(-317) +-188 + j*(314) +258 + j*(280) +-60 + j*(-63) +-358 + j*(-431) +355 + j*(-313) +602 + j*(-572) +-97 + j*(29) +-361 + j*(112) +426 + j*(-446) +-334 + j*(-248) +-468 + j*(-301) +-134 + j*(-296) +344 + j*(-398) +-33 + j*(361) +339 + j*(-470) +238 + j*(311) +455 + j*(372) +-419 + j*(47) +-267 + j*(-6) +313 + j*(-315) +-314 + j*(148) +-167 + j*(-559) +371 + j*(-467) +-377 + j*(337) +535 + j*(-262) +170 + j*(-213) +-719 + j*(-409) +-59 + j*(155) +-137 + j*(240) +-403 + j*(-211) +-310 + j*(-119) +405 + j*(-72) +-488 + j*(136) +-270 + j*(-495) +375 + j*(-124) +294 + j*(-73) +494 + j*(406) +423 + j*(311) +-401 + j*(-383) +378 + j*(293) +-290 + j*(-348) +111 + j*(-182) +414 + j*(523) +-121 + j*(746) +129 + j*(-466) +409 + j*(-359) +342 + j*(63) +-325 + j*(174) +-292 + j*(103) +221 + j*(407) +298 + j*(240) +-343 + j*(363) +192 + j*(-296) +-291 + j*(180) +-76 + j*(-33) +-58 + j*(-362) +-260 + j*(-202) +-301 + j*(-129) +86 + j*(400) +-240 + j*(337) +77 + j*(-55) +279 + j*(831) +20 + j*(-13) +305 + j*(-124) +551 + j*(99) +439 + j*(438) +-194 + j*(490) +592 + j*(216) +-382 + j*(228) +-316 + j*(76) +98 + j*(30) +216 + j*(-286) +268 + j*(18) +-13 + j*(233) +-497 + j*(-483) +25 + j*(-332) +168 + j*(227) +301 + j*(143) +73 + j*(-48) +-3 + j*(-291) +588 + j*(16) +192 + j*(-489) +243 + j*(76) +254 + j*(539) +-380 + j*(229) +489 + j*(15) +241 + j*(131) +158 + j*(-295) +306 + j*(195) +-283 + j*(428) +412 + j*(-48) +384 + j*(-260) +-188 + j*(38) +-104 + j*(-159) +64 + j*(142) +-39 + j*(92) +-73 + j*(243) +114 + j*(-292) +-19 + j*(36) +-160 + j*(345) +123 + j*(-62) +-45 + j*(297) +299 + j*(33) +117 + j*(-93) +-214 + j*(44) +-345 + j*(-15) +-11 + j*(-78) +204 + j*(16) +132 + j*(-22) +-45 + j*(59) +-220 + j*(-21) +145 + j*(-76) +-124 + j*(120) +156 + j*(-31) +21 + j*(-187) +-81 + j*(160) +-43 + j*(-79) +114 + j*(7) +247 + j*(-122) +90 + j*(96) +-132 + j*(27) +228 + j*(11) +-179 + j*(40) +78 + j*(89) +-513 + j*(3) +-152 + j*(246) +-60 + j*(211) +-108 + j*(-76) +-30 + j*(-112) +-68 + j*(-276) +18 + j*(42) +-13 + j*(-322) +-76 + j*(-78) +156 + j*(48) +-25 + j*(121) +106 + j*(-127) +-110 + j*(257) +263 + j*(132) +-168 + j*(303) +18 + j*(271) +6 + j*(-148) +133 + j*(-263) +-25 + j*(130) +71 + j*(329) +406 + j*(-14) +-28 + j*(-89) +-214 + j*(40) +-121 + j*(194) +-138 + j*(-7) +107 + j*(97) +213 + j*(-98) +114 + j*(73) +-233 + j*(3) +-34 + j*(290) +18 + j*(-125) +-28 + j*(263) +-121 + j*(12) +53 + j*(-48) +95 + j*(-21) +-461 + j*(13) +213 + j*(110) +223 + j*(98) +-137 + j*(-126) +-167 + j*(30) +-60 + j*(-438) +86 + j*(-72) +94 + j*(-175) +-103 + j*(111) +93 + j*(57) +-177 + j*(-207) +-134 + j*(130) +194 + j*(159) +25 + j*(36) +25 + j*(-231) +134 + j*(7) +117 + j*(-178) +-200 + j*(214) +11 + j*(51) +-337 + j*(-10) +259 + j*(-6) +-61 + j*(129) +-28 + j*(39) +-150 + j*(-81) +67 + j*(1) +-139 + j*(144) +-64 + j*(-216) +107 + j*(-387) +-105 + j*(93) +342 + j*(-31) +-133 + j*(26) +18 + j*(-242) +-230 + j*(-160) +-255 + j*(-103) +288 + j*(70) +45 + j*(18) +91 + j*(-15) +95 + j*(69) +6 + j*(193) +-107 + j*(-19) +264 + j*(-83) +42 + j*(-170) +-48 + j*(-8) +242 + j*(4) +320 + j*(47) +-75 + j*(-93) +-161 + j*(45) +-58 + j*(-127) +112 + j*(66) +193 + j*(224) +-577 + j*(-352) +-33 + j*(142) +117 + j*(72) +1 + j*(-115) +-107 + j*(167) +-45 + j*(187) +29 + j*(-117) +108 + j*(-128) +103 + j*(226) +-436 + j*(-210) +-245 + j*(54) +37 + j*(-62) +1 + j*(-59) +-233 + j*(82) +-101 + j*(299) +74 + j*(46) +59 + j*(-214) +-245 + j*(-179) +153 + j*(-385) +-86 + j*(215) +-105 + j*(-47) +-48 + j*(-337) +51 + j*(153) +118 + j*(159) +-117 + j*(-160) +131 + j*(19) +245 + j*(74) +-171 + j*(86) +-31 + j*(-61) +-144 + j*(179) +35 + j*(-370) +170 + j*(-76) +280 + j*(-52) +-89 + j*(-163) +78 + j*(47) +-345 + j*(-32) +-236 + j*(-15) +204 + j*(-49) +-517 + j*(-52) +-93 + j*(-81) +264 + j*(18) +-144 + j*(-25) +212 + j*(121) +26 + j*(-342) +165 + j*(53) +41 + j*(-14) +-111 + j*(197) +-179 + j*(233) +121 + j*(255) +208 + j*(-71) +187 + j*(293) +110 + j*(-317) +118 + j*(225) +250 + j*(187) +4 + j*(-260) +-48 + j*(72) +-195 + j*(97) +91 + j*(-210) +113 + j*(-173) +-32 + j*(2) +-112 + j*(-9) +373 + j*(-229) +42 + j*(-64) +-106 + j*(-13) +-58 + j*(25) +68 + j*(89) +-93 + j*(-106) +204 + j*(-76) +-177 + j*(13) +-84 + j*(-198) +168 + j*(287) +-218 + j*(220) +-139 + j*(-203) +346 + j*(156) +-194 + j*(-30) +134 + j*(-30) +-124 + j*(147) +-199 + j*(-285) +168 + j*(-201) +122 + j*(-271) +103 + j*(-25) +40 + j*(-42) +-129 + j*(42) +119 + j*(234) +91 + j*(185) +154 + j*(-153) +114 + j*(396) +103 + j*(156) +-127 + j*(-274) +122 + j*(-151) +34 + j*(112) +-236 + j*(-66) +266 + j*(-33) +-177 + j*(-86) +-26 + j*(-129) +52 + j*(164) +-59 + j*(-304) +-383 + j*(-279) +146 + j*(136) +419 + j*(40) +-30 + j*(113) +-105 + j*(142) +213 + j*(-259) +30 + j*(363) +168 + j*(-375) +-107 + j*(60) +128 + j*(199) +-71 + j*(113) +-95 + j*(-124) +-17 + j*(48) +-57 + j*(65) +-76 + j*(23) +-274 + j*(-206) +125 + j*(276) +98 + j*(-57) +-129 + j*(-179) +-58 + j*(311) +54 + j*(52) +-351 + j*(226) +-252 + j*(55) +-142 + j*(-17) +202 + j*(107) +176 + j*(-477) +-71 + j*(18) +-174 + j*(125) +144 + j*(-108) +-10 + j*(-19) +-28 + j*(112) +-26 + j*(132) +-236 + j*(-8) +37 + j*(-214) +111 + j*(216) +260 + j*(70) +-30 + j*(-69) +-91 + j*(157) +221 + j*(-96) +-162 + j*(-126) +-71 + j*(110) +16 + j*(117) +128 + j*(-4) +69 + j*(35) +-62 + j*(177) +143 + j*(88) +-124 + j*(-195) +-118 + j*(-61) +26 + j*(-187) +-76 + j*(262) +-21 + j*(-103) +-164 + j*(-139) +-73 + j*(-175) +262 + j*(-58) +44 + j*(58) +78 + j*(-43) +-245 + j*(336) +-28 + j*(-38) +-124 + j*(-168) +-320 + j*(34) +-175 + j*(-11) +-190 + j*(-241) +119 + j*(-78) +-242 + j*(264) +-91 + j*(234) +-57 + j*(-42) +-189 + j*(11) +130 + j*(103) +217 + j*(-100) +170 + j*(-62) +-327 + j*(82) +-132 + j*(-118) +19 + j*(1) +15 + j*(-6) +-479 + j*(69) +38 + j*(68) +1 + j*(-229) +93 + j*(-98) +54 + j*(-93) +-23 + j*(-100) +1 + j*(-197) +-269 + j*(-126) +177 + j*(23) +-412 + j*(-282) +-78 + j*(88) +-214 + j*(225) +-96 + j*(127) +-40 + j*(181) +276 + j*(175) +-191 + j*(-257) +163 + j*(-84) +-82 + j*(92) +171 + j*(132) +213 + j*(-79) +234 + j*(125) +-62 + j*(-272) +57 + j*(-56) +62 + j*(-363) +-136 + j*(64) +40 + j*(33) +-63 + j*(-95) +-162 + j*(172) +-141 + j*(-281) +-13 + j*(40) +248 + j*(-70) +-104 + j*(-439) +57 + j*(192) +21 + j*(16) +-385 + j*(-86) +86 + j*(-322) +-263 + j*(279) +238 + j*(83) +62 + j*(-112) +-68 + j*(-26) +30 + j*(182) +6 + j*(-152) +100 + j*(-80) +91 + j*(1) +-49 + j*(-240) +88 + j*(19) +74 + j*(98) +87 + j*(234) +5 + j*(-245) +-310 + j*(57) +-78 + j*(-243) +-163 + j*(-32) +114 + j*(-437) +44 + j*(150) +158 + j*(-68) +327 + j*(-263) +-3 + j*(-2) +151 + j*(268) +-274 + j*(-351) +-291 + j*(-420) +-409 + j*(204) +-454 + j*(-66) +66 + j*(26) +-187 + j*(277) +73 + j*(-33) +118 + j*(123) +136 + j*(-40) +87 + j*(138) +264 + j*(47) +93 + j*(288) +113 + j*(107) +-233 + j*(95) +19 + j*(170) +-23 + j*(-486) +30 + j*(-47) +146 + j*(107) +177 + j*(226) +-82 + j*(-301) +155 + j*(58) +78 + j*(-10) +390 + j*(233) +-5 + j*(74) +-33 + j*(25) +-117 + j*(394) +202 + j*(-98) +18 + j*(83) +47 + j*(-127) +230 + j*(-156) +255 + j*(112) +-26 + j*(358) +50 + j*(109) +-56 + j*(-51) +-78 + j*(-240) +-190 + j*(42) +119 + j*(98) +-146 + j*(84) +-37 + j*(-115) +76 + j*(38) +99 + j*(-181) +31 + j*(-63) +69 + j*(61) +-100 + j*(62) +-81 + j*(161) +130 + j*(-101) +134 + j*(-168) +40 + j*(25) +-57 + j*(-278) +-58 + j*(244) +-368 + j*(-64) +214 + j*(367) +43 + j*(104) +347 + j*(-150) +293 + j*(45) +-139 + j*(-16) +198 + j*(120) +286 + j*(255) +342 + j*(-254) +70 + j*(-104) +-275 + j*(-223) +-37 + j*(-50) +-337 + j*(-89) +-74 + j*(-56) +133 + j*(202) +-61 + j*(255) +-209 + j*(-103) +-110 + j*(-83) +130 + j*(244) +-274 + j*(2) +78 + j*(-186) +56 + j*(163) +-122 + j*(-139) +90 + j*(-124) +-6 + j*(-28) +99 + j*(-203) +-340 + j*(-146) +90 + j*(-62) +215 + j*(-257) +42 + j*(-3) +170 + j*(380) +2 + j*(62) +-43 + j*(-52) +-331 + j*(12) +-26 + j*(33) +77 + j*(141) +-184 + j*(-206) +349 + j*(74) +128 + j*(-83) +-309 + j*(213) +233 + j*(22) +155 + j*(-16) +-82 + j*(-190) +-129 + j*(-1) +131 + j*(-341) +182 + j*(-120) +211 + j*(81) +47 + j*(-32) +-79 + j*(233) +-113 + j*(-443) +89 + j*(170) +218 + j*(-257) +-78 + j*(74) +-11 + j*(-57) +-220 + j*(233) +-165 + j*(62) +19 + j*(44) +-121 + j*(-240) +-3 + j*(-156) +272 + j*(11) +-161 + j*(-361) +-133 + j*(-153) +-51 + j*(122) +-30 + j*(56) +-116 + j*(-74) +90 + j*(-298) +97 + j*(-151) +126 + j*(-69) +64 + j*(49) +-18 + j*(-126) +-45 + j*(-190) +72 + j*(-124) +42 + j*(-128) +238 + j*(-228) +18 + j*(-296) +182 + j*(188) +52 + j*(-131) +-25 + j*(47) +66 + j*(-49) +327 + j*(-474) +110 + j*(71) +-76 + j*(-78) +86 + j*(30) +-158 + j*(221) +-16 + j*(-371) +-144 + j*(100) +9 + j*(197) +-65 + j*(-11) +-218 + j*(-257) +278 + j*(75) +-103 + j*(40) +42 + j*(-145) +496 + j*(53) +-161 + j*(-137) +-82 + j*(-205) +116 + j*(-37) +-134 + j*(98) +-26 + j*(392) +221 + j*(-45) +-209 + j*(-288) +-261 + j*(96) +199 + j*(-429) +516 + j*(-110) +18 + j*(112) +106 + j*(-329) +-83 + j*(-117) +-190 + j*(36) +177 + j*(252) +13 + j*(15) +0 + j*(-269) +18 + j*(49) +262 + j*(17) +-161 + j*(154) +71 + j*(-43) +274 + j*(-88) +-167 + j*(67) +192 + j*(-173) +-156 + j*(251) +-127 + j*(31) +53 + j*(112) +-47 + j*(306) +-409 + j*(-194) +70 + j*(172) +-108 + j*(-223) +-54 + j*(6) +215 + j*(283) +281 + j*(-138) +53 + j*(102) +12 + j*(-93) +293 + j*(48) +-223 + j*(-163) +37 + j*(127) +-21 + j*(-30) +122 + j*(139) +-6 + j*(147) +-168 + j*(-25) +-1 + j*(63) +203 + j*(-30) +-184 + j*(-281) +0 + j*(-66) +245 + j*(80) +-3 + j*(-154) +-151 + j*(-327) +-185 + j*(-123) +105 + j*(-202) +-218 + j*(190) +-54 + j*(29) +25 + j*(-47) +-437 + j*(-132) +-42 + j*(-11) +-264 + j*(-191) +-55 + j*(-18) +277 + j*(-223) +69 + j*(-213) +-334 + j*(-90) +185 + j*(-269) +-95 + j*(-21) +-281 + j*(240) +-86 + j*(132) +-134 + j*(-120) +17 + j*(-402) +-30 + j*(-4) +124 + j*(-308) +-21 + j*(-54) +107 + j*(-12) +86 + j*(-109) +23 + j*(53) +-42 + j*(-352) +-68 + j*(-250) +354 + j*(-155) +34 + j*(-111) +-156 + j*(228) +127 + j*(-209) +47 + j*(69) +-118 + j*(298) +33 + j*(-36) +62 + j*(392) +-269 + j*(-88) +-366 + j*(-47) +-127 + j*(-98) +91 + j*(40) +-138 + j*(-253) +-57 + j*(181) +186 + j*(-102) +83 + j*(-89) +-9 + j*(-419) +109 + j*(265) +124 + j*(316) +12 + j*(-206) +-10 + j*(153) +-159 + j*(27) +53 + j*(-252) +-21 + j*(168) +129 + j*(91) +-205 + j*(-82) +85 + j*(143) +-11 + j*(17) +71 + j*(-145) +45 + j*(80) +71 + j*(50) +180 + j*(49) +110 + j*(0) +-60 + j*(233) +24 + j*(-153) +-16 + j*(137) +269 + j*(187) +-115 + j*(156) +29 + j*(81) +-232 + j*(-161) +206 + j*(-56) +-47 + j*(17) +-18 + j*(-177) +-100 + j*(126) +-270 + j*(82) +-180 + j*(42) +238 + j*(366) +69 + j*(236) +182 + j*(-151) +0 + j*(180) +232 + j*(-28) +72 + j*(299) +87 + j*(84) +35 + j*(-416) +-200 + j*(-43) +206 + j*(-60) +-245 + j*(-146) +89 + j*(95) +-127 + j*(250) +-342 + j*(-6) +-5 + j*(342) +-239 + j*(-119) +169 + j*(-29) +-375 + j*(98) +81 + j*(-380) +-65 + j*(4) +-139 + j*(-205) +69 + j*(-94) +-81 + j*(-175) +16 + j*(-124) +-81 + j*(185) +165 + j*(378) +-140 + j*(337) +42 + j*(91) +-156 + j*(201) +-127 + j*(-64) +-35 + j*(-177) +-238 + j*(-87) +-241 + j*(-294) +88 + j*(-289) +-164 + j*(56) +-141 + j*(-109) +64 + j*(29) +-239 + j*(-172) +88 + j*(-416) +-188 + j*(-76) +-222 + j*(103) +7 + j*(-53) +218 + j*(-284) +82 + j*(-288) +111 + j*(40) +-47 + j*(111) +-57 + j*(176) +20 + j*(-96) +-25 + j*(284) +-29 + j*(87) +63 + j*(266) +-67 + j*(-129) +154 + j*(-69) +141 + j*(78) +38 + j*(-177) +-46 + j*(-306) +271 + j*(125) +378 + j*(130) +-303 + j*(-30) +148 + j*(-64) +-124 + j*(-332) +-153 + j*(71) +-49 + j*(18) +-78 + j*(-183) +-334 + j*(-199) +-238 + j*(-58) +-269 + j*(-38) +253 + j*(-426) +-166 + j*(197) +197 + j*(-147) +-33 + j*(-86) +190 + j*(80) +-111 + j*(-462) +-76 + j*(-369) +501 + j*(-119) +192 + j*(-117) +106 + j*(-60) +148 + j*(-238) +10 + j*(79) +97 + j*(53) +64 + j*(-66) +-162 + j*(-535) +60 + j*(83) +-188 + j*(-98) +32 + j*(15) +-74 + j*(-52) +-30 + j*(-102) +61 + j*(300) +-64 + j*(8) +-245 + j*(105) +114 + j*(-330) +83 + j*(141) +98 + j*(98) +-74 + j*(-268) +112 + j*(49) +451 + j*(-61) +-107 + j*(52) +136 + j*(-39) +-157 + j*(350) +33 + j*(-122) +258 + j*(173) +334 + j*(45) +-48 + j*(170) +78 + j*(-82) +59 + j*(-108) +347 + j*(75) +-314 + j*(86) +-387 + j*(275) +6 + j*(132) +-204 + j*(294) +124 + j*(98) +-254 + j*(22) +-89 + j*(-156) +-392 + j*(-168) +141 + j*(-159) +201 + j*(-175) +-28 + j*(5) +132 + j*(116) +4 + j*(-4) +227 + j*(-108) +-268 + j*(-85) +115 + j*(-98) +-57 + j*(139) +200 + j*(-103) +-65 + j*(-194) +-146 + j*(-59) +-314 + j*(45) +146 + j*(-1) +26 + j*(40) +-290 + j*(-56) +-260 + j*(-264) +165 + j*(35) +235 + j*(-228) +149 + j*(-168) +-25 + j*(-196) +33 + j*(-211) +-172 + j*(-173) +-148 + j*(168) +-281 + j*(62) +-56 + j*(-12) +179 + j*(-24) +54 + j*(45) +-128 + j*(-153) +72 + j*(-62) +-12 + j*(343) +214 + j*(-173) +-105 + j*(41) +151 + j*(-11) +-226 + j*(140) +24 + j*(175) +-57 + j*(12) +-25 + j*(86) +-269 + j*(27) +175 + j*(13) +238 + j*(9) +107 + j*(62) +15 + j*(-73) +115 + j*(-37) +80 + j*(-197) +-50 + j*(118) +-206 + j*(123) +23 + j*(35) +-257 + j*(-112) +-66 + j*(183) +-155 + j*(-4) +-161 + j*(135) +132 + j*(-220) +-22 + j*(-358) +197 + j*(277) +339 + j*(8) +-232 + j*(-293) +134 + j*(-162) +-253 + j*(179) +-255 + j*(-197) +-110 + j*(-202) +-216 + j*(-243) +-247 + j*(103) +-16 + j*(-33) +107 + j*(-113) +-93 + j*(-20) +-52 + j*(299) +-43 + j*(-234) +-131 + j*(-33) +135 + j*(207) +88 + j*(-26) +125 + j*(206) +164 + j*(5) +78 + j*(-178) +-151 + j*(-197) +190 + j*(-16) +151 + j*(88) +-52 + j*(255) +19 + j*(-182) +144 + j*(-44) +-16 + j*(-112) +145 + j*(81) +-35 + j*(-1) +-107 + j*(-6) +148 + j*(351) +-156 + j*(421) +-252 + j*(-71) +373 + j*(-182) +228 + j*(51) +-71 + j*(137) +83 + j*(201) +54 + j*(-112) +26 + j*(-145) +-55 + j*(4) +161 + j*(330) +-30 + j*(-250) +-421 + j*(-114) +30 + j*(-16) +69 + j*(106) +-43 + j*(43) +-155 + j*(178) +20 + j*(-208) +-395 + j*(226) +-147 + j*(129) +11 + j*(-42) +-331 + j*(91) +81 + j*(56) +-460 + j*(-49) +-269 + j*(1) +19 + j*(216) +-124 + j*(30) +16 + j*(190) +-293 + j*(-240) +-170 + j*(149) +-101 + j*(95) +130 + j*(-82) +-33 + j*(116) +28 + j*(21) +83 + j*(-83) +-211 + j*(257) +-6 + j*(133) +32 + j*(-163) +44 + j*(-69) +36 + j*(95) +-80 + j*(24) +-17 + j*(-354) +115 + j*(130) +28 + j*(-41) +287 + j*(195) +433 + j*(-71) +-191 + j*(195) +-75 + j*(-296) +-195 + j*(170) +291 + j*(-35) +-164 + j*(128) +271 + j*(50) +132 + j*(-71) +202 + j*(26) +12 + j*(-90) +-260 + j*(25) +165 + j*(29) +-89 + j*(250) +-25 + j*(-21) +-33 + j*(-4) +284 + j*(108) +-162 + j*(-106) +76 + j*(-163) +85 + j*(70) +-106 + j*(61) +-273 + j*(32) +24 + j*(-115) +268 + j*(-297) +-211 + j*(58) +243 + j*(16) +105 + j*(-155) +-36 + j*(-225) +64 + j*(80) +-42 + j*(31) +115 + j*(276) +-332 + j*(-232) +111 + j*(7) +-216 + j*(-134) +-154 + j*(-279) +-182 + j*(76) +121 + j*(-49) +-88 + j*(-52) +167 + j*(-93) +-135 + j*(-245) +-210 + j*(405) +-69 + j*(212) +-48 + j*(-240) +385 + j*(306) +31 + j*(108) +-7 + j*(-222) +30 + j*(-53) +-194 + j*(-183) +-21 + j*(57) +-330 + j*(171) +-42 + j*(-16) +199 + j*(221) +-12 + j*(25) +-70 + j*(458) +-371 + j*(-155) +-78 + j*(100) +49 + j*(-85) +110 + j*(-243) +-23 + j*(40) +12 + j*(-71) +-82 + j*(-624) +-156 + j*(53) +-153 + j*(264) +2 + j*(-132) +63 + j*(86) +133 + j*(40) +129 + j*(221) +192 + j*(-300) +-122 + j*(202) +76 + j*(-155) +94 + j*(28) +-17 + j*(281) +-382 + j*(105) +310 + j*(158) +20 + j*(122) +211 + j*(-99) +217 + j*(-166) +-1 + j*(-130) +32 + j*(-39) +-64 + j*(-286) +365 + j*(-83) +216 + j*(89) +167 + j*(-338) +324 + j*(67) +223 + j*(123) +44 + j*(-21) +66 + j*(79) +-109 + j*(105) +59 + j*(-62) +211 + j*(35) +-165 + j*(-54) +142 + j*(123) +-187 + j*(-115) +76 + j*(100) +-290 + j*(-316) +-78 + j*(162) +156 + j*(49) +-69 + j*(-29) +202 + j*(151) +37 + j*(11) +-40 + j*(-138) +31 + j*(10) +-28 + j*(-112) +-195 + j*(175) +-178 + j*(187) +51 + j*(-35) +112 + j*(-6) +-207 + j*(-35) +-70 + j*(19) +-129 + j*(-331) +99 + j*(-210) +275 + j*(123) +-262 + j*(250) +-9 + j*(129) +156 + j*(223) +59 + j*(42) +-272 + j*(-320) +-107 + j*(-27) +-274 + j*(317) +-271 + j*(238) +74 + j*(-22) +181 + j*(-249) +286 + j*(86) +57 + j*(268) +-69 + j*(-50) +22 + j*(233) +137 + j*(168) +156 + j*(88) +250 + j*(165) +175 + j*(-258) +-250 + j*(-158) +-57 + j*(251) +-192 + j*(98) +88 + j*(208) +-175 + j*(130) +40 + j*(-162) +-237 + j*(-4) +272 + j*(8) +-54 + j*(163) +105 + j*(72) +216 + j*(-69) +-257 + j*(139) +-250 + j*(53) +30 + j*(-439) +78 + j*(-208) +182 + j*(177) +262 + j*(83) +318 + j*(-4) +-6 + j*(214) +-37 + j*(-172) +-144 + j*(-33) +-278 + j*(42) +195 + j*(29) +158 + j*(76) +-30 + j*(-395) +189 + j*(-122) +-165 + j*(-22) +-307 + j*(240) +18 + j*(-73) +11 + j*(422) +-108 + j*(-59) +366 + j*(13) +-81 + j*(-116) +-286 + j*(244) +99 + j*(349) +-102 + j*(-100) +-247 + j*(-32) +2 + j*(175) +-40 + j*(337) +284 + j*(124) +107 + j*(-8) +126 + j*(107) +-348 + j*(-184) +206 + j*(-15) +242 + j*(-8) +248 + j*(9) +83 + j*(65) +-153 + j*(53) +-117 + j*(169) +-359 + j*(41) +-34 + j*(3) +-264 + j*(-237) +42 + j*(-223) +218 + j*(116) +-92 + j*(-192) +-259 + j*(-144) +304 + j*(78) +-10 + j*(337) +8 + j*(122) +-57 + j*(28) +-35 + j*(37) +-46 + j*(13) +55 + j*(261) +-244 + j*(-163) +42 + j*(-45) +-339 + j*(-79) +82 + j*(412) +7 + j*(150) +132 + j*(199) +137 + j*(-323) +269 + j*(-166) +-7 + j*(54) +-243 + j*(232) +-180 + j*(-30) +-78 + j*(-49) +-113 + j*(4) +30 + j*(-32) +95 + j*(64) +-1 + j*(-146) +20 + j*(-11) +91 + j*(194) +51 + j*(-269) +-250 + j*(-105) +-141 + j*(-33) +-114 + j*(310) +177 + j*(211) +-138 + j*(417) +-13 + j*(258) +260 + j*(-113) +47 + j*(169) +11 + j*(-429) +-204 + j*(-11) +-370 + j*(33) +401 + j*(-77) +74 + j*(186) +322 + j*(146) +57 + j*(-364) +18 + j*(-114) +171 + j*(-362) +-86 + j*(66) +11 + j*(-148) +-72 + j*(190) +185 + j*(-168) +-73 + j*(-161) +182 + j*(18) +-256 + j*(-304) +-103 + j*(21) +-41 + j*(358) +-136 + j*(132) +-18 + j*(-144) +267 + j*(102) +76 + j*(146) +-5 + j*(-34) +-105 + j*(29) +-261 + j*(-179) +-86 + j*(63) +106 + j*(280) +-15 + j*(-155) +144 + j*(-52) +-55 + j*(-344) +156 + j*(-20) +161 + j*(-242) +163 + j*(-223) +-354 + j*(64) +-5 + j*(-21) +20 + j*(-246) +210 + j*(-316) +396 + j*(-194) +16 + j*(225) +-228 + j*(165) +46 + j*(21) +-43 + j*(-298) +-129 + j*(-132) +-201 + j*(77) +-32 + j*(21) +-37 + j*(107) +-16 + j*(94) +18 + j*(-93) +207 + j*(-175) +88 + j*(226) +216 + j*(-142) +-170 + j*(102) +21 + j*(-291) +119 + j*(-173) +-236 + j*(-33) +49 + j*(302) +-151 + j*(136) +-284 + j*(-181) +286 + j*(39) +-70 + j*(160) +-56 + j*(122) +5 + j*(320) +-34 + j*(-181) +-272 + j*(83) +33 + j*(-203) +-248 + j*(-199) +146 + j*(255) +-190 + j*(28) +-60 + j*(-340) +13 + j*(-252) +134 + j*(269) +130 + j*(-115) +137 + j*(-25) +292 + j*(141) +171 + j*(82) +14 + j*(49) +11 + j*(23) +-257 + j*(124) +-130 + j*(-160) +-247 + j*(164) +-13 + j*(168) +-62 + j*(-258) +-11 + j*(-66) +291 + j*(274) +42 + j*(224) +-135 + j*(266) +-109 + j*(47) +-37 + j*(-110) +84 + j*(-120) +-73 + j*(322) +-52 + j*(33) +-139 + j*(24) +42 + j*(-132) +41 + j*(259) +-45 + j*(165) +248 + j*(-201) +-334 + j*(-131) +-92 + j*(154) +202 + j*(7) +88 + j*(154) +-100 + j*(42) +-251 + j*(9) +129 + j*(-116) +-187 + j*(82) +134 + j*(-412) +-271 + j*(-181) +-137 + j*(-20) +-57 + j*(79) +136 + j*(95) +81 + j*(157) +-100 + j*(107) +-235 + j*(233) +117 + j*(-72) +388 + j*(-156) +-147 + j*(-264) +0 + j*(-124) +-18 + j*(156) +-119 + j*(-114) +-334 + j*(144) +206 + j*(303) +181 + j*(84) +-198 + j*(-121) +-146 + j*(91) +-49 + j*(-77) +313 + j*(148) +-241 + j*(57) +33 + j*(11) +161 + j*(-20) +-76 + j*(158) +51 + j*(28) +-106 + j*(67) +-6 + j*(-136) +-172 + j*(-97) +77 + j*(112) +0 + j*(59) +34 + j*(-29) +276 + j*(-67) +-209 + j*(-214) +21 + j*(-59) +19 + j*(23) +35 + j*(-177) +-221 + j*(242) +49 + j*(-40) +291 + j*(248) +220 + j*(57) +-193 + j*(65) +129 + j*(101) +-36 + j*(-160) +-431 + j*(-53) +-78 + j*(-492) +147 + j*(-326) +-260 + j*(-37) +322 + j*(-134) +-202 + j*(-203) +58 + j*(40) +45 + j*(-83) +-66 + j*(-205) +-130 + j*(-68) +122 + j*(47) +124 + j*(-115) +-37 + j*(281) +-276 + j*(-77) +-188 + j*(379) +195 + j*(-42) +-4 + j*(110) +-288 + j*(-63) +1 + j*(-96) +69 + j*(-42) +100 + j*(173) +-129 + j*(246) +311 + j*(-30) +-71 + j*(-151) +-368 + j*(-41) +-347 + j*(190) +-173 + j*(-92) +-170 + j*(224) +-40 + j*(-163) +-103 + j*(90) +373 + j*(301) +-206 + j*(55) +-8 + j*(-184) +30 + j*(-18) +-184 + j*(15) +-132 + j*(103) +69 + j*(88) +-115 + j*(-293) +-318 + j*(124) +250 + j*(284) +33 + j*(-127) +193 + j*(317) +-72 + j*(242) +-32 + j*(122) +-214 + j*(277) +78 + j*(-18) +-173 + j*(-41) +-135 + j*(-180) +-31 + j*(-104) +-22 + j*(278) +52 + j*(-16) +204 + j*(-62) +-30 + j*(-24) +171 + j*(-48) +-54 + j*(-339) +-84 + j*(91) +-95 + j*(-288) +40 + j*(-330) +-115 + j*(16) +-451 + j*(-48) +119 + j*(99) +-36 + j*(135) +200 + j*(144) +127 + j*(-43) +252 + j*(91) +105 + j*(218) +29 + j*(176) +139 + j*(-190) +-108 + j*(-139) +144 + j*(-76) +120 + j*(214) +47 + j*(228) +-42 + j*(-4) +279 + j*(3) +-140 + j*(-100) +-16 + j*(49) +-148 + j*(-21) +102 + j*(-150) +-48 + j*(-264) +-204 + j*(-53) +207 + j*(81) +-272 + j*(-115) +-28 + j*(-252) +-61 + j*(-4) +-114 + j*(116) +64 + j*(182) +131 + j*(101) +117 + j*(-1) +148 + j*(-296) +99 + j*(248) +112 + j*(-18) +198 + j*(306) +-63 + j*(13) +-226 + j*(-149) +93 + j*(121) +-233 + j*(140) +-156 + j*(-279) +-182 + j*(-107) +-117 + j*(-240) +-209 + j*(36) +32 + j*(-31) +257 + j*(-126) +-320 + j*(94) +25 + j*(-454) +-35 + j*(81) +-132 + j*(170) +-161 + j*(230) +365 + j*(304) +-53 + j*(-175) +101 + j*(165) +242 + j*(301) +113 + j*(190) +164 + j*(-160) +25 + j*(-512) +343 + j*(31) +-228 + j*(4) +185 + j*(-76) +-13 + j*(272) +69 + j*(6) +45 + j*(-23) +3 + j*(135) +-240 + j*(-105) +124 + j*(143) +-40 + j*(-218) +-35 + j*(-109) +-23 + j*(-3) +-96 + j*(-139) +93 + j*(240) +-193 + j*(-181) +-45 + j*(80) +165 + j*(-144) +-176 + j*(-94) +-85 + j*(-242) +-100 + j*(-11) +-73 + j*(181) +-6 + j*(-151) +98 + j*(109) +-223 + j*(101) +-279 + j*(58) +81 + j*(86) +14 + j*(102) +56 + j*(-215) +-228 + j*(-92) +-165 + j*(-62) +262 + j*(52) +-40 + j*(-160) +-183 + j*(-139) +226 + j*(-66) +-107 + j*(184) +115 + j*(-64) +-129 + j*(139) +90 + j*(-296) +-88 + j*(-1) +-81 + j*(-83) +78 + j*(-35) +68 + j*(-37) +-86 + j*(-149) +-1 + j*(84) +-124 + j*(-24) +-319 + j*(-315) +-105 + j*(-221) +-185 + j*(77) +-211 + j*(28) +-58 + j*(-169) +59 + j*(-424) +97 + j*(222) +-82 + j*(216) +170 + j*(-109) +185 + j*(6) +-328 + j*(202) +-128 + j*(-71) +-34 + j*(-259) +23 + j*(409) +-218 + j*(55) +55 + j*(-269) +-49 + j*(368) +62 + j*(131) +15 + j*(29) +79 + j*(349) +9 + j*(-190) +-188 + j*(232) +194 + j*(153) +74 + j*(291) +-152 + j*(119) +148 + j*(-206) +-110 + j*(-170) +194 + j*(-139) +113 + j*(-100) +-209 + j*(-302) +2 + j*(64) +-128 + j*(-59) +13 + j*(-122) +7 + j*(-200) +25 + j*(-101) +104 + j*(-127) +168 + j*(-125) +93 + j*(-216) +-91 + j*(-49) +-179 + j*(-68) +-95 + j*(117) +267 + j*(-81) +-48 + j*(-41) +-122 + j*(-340) +-91 + j*(216) +104 + j*(142) +-69 + j*(-206) +-82 + j*(-101) +-93 + j*(136) +6 + j*(-57) +-51 + j*(-202) +53 + j*(-167) +-127 + j*(-216) +-292 + j*(-243) +170 + j*(-228) +-241 + j*(-90) +-132 + j*(-216) +-81 + j*(-295) +-40 + j*(96) +-180 + j*(-167) +-404 + j*(42) +-64 + j*(-373) +-190 + j*(100) +75 + j*(-219) +430 + j*(219) +-23 + j*(-146) +-93 + j*(25) +18 + j*(257) +-28 + j*(303) +-209 + j*(261) +748 + j*(271) +177 + j*(154) +352 + j*(577) +-202 + j*(-223) +-177 + j*(11) +327 + j*(256) +346 + j*(-228) +-372 + j*(398) +354 + j*(666) +399 + j*(-1) +406 + j*(-42) +105 + j*(-37) +-281 + j*(523) +-76 + j*(-529) +675 + j*(81) +-245 + j*(418) +333 + j*(275) +-395 + j*(136) +-63 + j*(338) +-166 + j*(-158) +-139 + j*(-445) +-238 + j*(407) +-342 + j*(-115) +-323 + j*(101) +-547 + j*(289) +329 + j*(117) +-255 + j*(-172) +375 + j*(-109) +-52 + j*(-234) +643 + j*(-313) +-18 + j*(258) +11 + j*(168) +-12 + j*(15) +351 + j*(-247) +-199 + j*(334) +387 + j*(21) +-126 + j*(63) +-375 + j*(263) +23 + j*(206) +31 + j*(261) +-211 + j*(334) +633 + j*(210) +-194 + j*(-467) +335 + j*(-243) +368 + j*(-135) +542 + j*(-241) +-190 + j*(-300) +-18 + j*(-262) +279 + j*(-42) +-548 + j*(-407) +107 + j*(-480) +318 + j*(274) +-220 + j*(-252) +142 + j*(66) +-156 + j*(290) +-474 + j*(320) +602 + j*(255) +-226 + j*(187) +-403 + j*(-288) +-443 + j*(-303) +159 + j*(-513) +-480 + j*(-58) +263 + j*(-127) +-346 + j*(537) +187 + j*(-350) +-146 + j*(336) +-175 + j*(-127) +250 + j*(532) +317 + j*(173) +-38 + j*(-279) +339 + j*(-542) +168 + j*(-103) +606 + j*(-121) +128 + j*(-260) +132 + j*(-116) +487 + j*(497) +-177 + j*(-310) +-281 + j*(-375) +-33 + j*(-250) +-459 + j*(37) +13 + j*(-3) +206 + j*(-288) +167 + j*(-218) +225 + j*(163) +-460 + j*(-350) +-422 + j*(-256) +-273 + j*(-288) +145 + j*(-539) +264 + j*(675) +-177 + j*(-416) +-278 + j*(92) +256 + j*(93) +-11 + j*(122) +119 + j*(205) +264 + j*(-350) +267 + j*(320) +628 + j*(115) +-300 + j*(206) +-256 + j*(127) +46 + j*(644) +-257 + j*(174) +397 + j*(-358) +437 + j*(-221) +-404 + j*(-392) +-453 + j*(-234) +211 + j*(-168) +-473 + j*(-173) +378 + j*(297) +206 + j*(280) +-203 + j*(-341) +-251 + j*(-229) +173 + j*(-60) +-311 + j*(-156) +1 + j*(134) +-24 + j*(-322) +-291 + j*(-203) +-424 + j*(127) +134 + j*(-62) +-295 + j*(-141) +-380 + j*(-233) +-83 + j*(320) +-169 + j*(171) +-419 + j*(263) +219 + j*(-126) +-227 + j*(221) +-533 + j*(-33) +139 + j*(162) +-259 + j*(81) +-77 + j*(-316) +-334 + j*(368) +78 + j*(-279) +-127 + j*(-14) +186 + j*(-54) +-317 + j*(-562) +127 + j*(424) +23 + j*(241) +-170 + j*(-218) +533 + j*(511) +-530 + j*(-110) +-246 + j*(576) +151 + j*(-443) +38 + j*(358) +-462 + j*(-40) +-293 + j*(386) +403 + j*(404) +465 + j*(126) +-39 + j*(220) +546 + j*(-482) +187 + j*(267) +-166 + j*(-417) +293 + j*(-158) +190 + j*(-276) +291 + j*(-456) +-256 + j*(177) +236 + j*(83) +-21 + j*(566) +-309 + j*(-536) +-276 + j*(274) +291 + j*(30) +316 + j*(480) +471 + j*(114) +-284 + j*(197) +344 + j*(-291) +-263 + j*(-347) +81 + j*(33) +-381 + j*(-364) +49 + j*(-97) +300 + j*(516) +303 + j*(-48) +192 + j*(499) +115 + j*(-372) +387 + j*(-398) +264 + j*(2) +-104 + j*(286) +643 + j*(-144) +327 + j*(447) +33 + j*(-457) +-221 + j*(-59) +-251 + j*(37) +300 + j*(4) +245 + j*(77) +-199 + j*(-344) +-103 + j*(16) +-275 + j*(596) +226 + j*(-307) +-321 + j*(379) +151 + j*(237) +403 + j*(-258) +292 + j*(-358) +728 + j*(378) +204 + j*(601) +-392 + j*(-49) +205 + j*(56) +-96 + j*(143) +-361 + j*(270) +132 + j*(159) +342 + j*(156) +171 + j*(262) +252 + j*(55) +205 + j*(-261) +272 + j*(-192) +225 + j*(139) +-375 + j*(241) +-179 + j*(325) +-121 + j*(-150) +178 + j*(-279) +532 + j*(-95) +-397 + j*(361) +149 + j*(-227) +-253 + j*(-415) +-622 + j*(-208) +-309 + j*(369) +305 + j*(361) +224 + j*(394) +385 + j*(617) +-238 + j*(-120) +524 + j*(-277) +-209 + j*(-190) +387 + j*(658) +405 + j*(211) +45 + j*(333) +-313 + j*(137) +-313 + j*(-31) +492 + j*(320) +138 + j*(-307) +-240 + j*(364) +316 + j*(204) +177 + j*(-408) +204 + j*(-63) +358 + j*(-165) +-47 + j*(-238) +425 + j*(361) +596 + j*(-56) +409 + j*(-180) +-61 + j*(-536) +-389 + j*(262) +-337 + j*(-270) +-185 + j*(-47) +-414 + j*(-222) +394 + j*(200) +102 + j*(201) +-581 + j*(-57) +312 + j*(118) +284 + j*(421) +171 + j*(242) +385 + j*(-218) +119 + j*(166) +408 + j*(484) +215 + j*(188) +269 + j*(434) +8 + j*(337) +-308 + j*(514) +366 + j*(-49) +167 + j*(-166) +638 + j*(185) +344 + j*(-203) +-331 + j*(174) +315 + j*(-16) +264 + j*(-185) +-389 + j*(382) +-76 + j*(-346) +284 + j*(221) +216 + j*(309) +-296 + j*(-339) +-290 + j*(89) +341 + j*(400) +126 + j*(-108) +267 + j*(288) +-211 + j*(177) +355 + j*(-21) +522 + j*(255) +268 + j*(-234) +436 + j*(392) +703 + j*(57) +-435 + j*(-436) +284 + j*(-130) +-115 + j*(-286) +-614 + j*(-284) +-152 + j*(-368) +219 + j*(-30) +313 + j*(-261) +-134 + j*(-260) +-55 + j*(-498) +-254 + j*(291) +196 + j*(-122) +318 + j*(334) +-264 + j*(366) +13 + j*(-230) +314 + j*(609) +241 + j*(-139) +-88 + j*(347) +323 + j*(-305) +-443 + j*(-257) +-231 + j*(300) +-424 + j*(479) +320 + j*(543) +23 + j*(-188) +-392 + j*(22) +-497 + j*(93) +-218 + j*(-392) +-286 + j*(-441) +-263 + j*(-591) +-153 + j*(-87) +-125 + j*(204) +-385 + j*(54) +92 + j*(269) +-45 + j*(46) +-571 + j*(-607) +-372 + j*(122) +-384 + j*(19) +193 + j*(258) +-22 + j*(377) +-268 + j*(331) +-184 + j*(425) +554 + j*(-243) +-146 + j*(490) +-168 + j*(-530) +180 + j*(38) +-352 + j*(25) +-334 + j*(57) +-215 + j*(188) +57 + j*(89) +196 + j*(182) +397 + j*(491) +-361 + j*(-99) +214 + j*(161) +-84 + j*(346) +112 + j*(364) +-244 + j*(346) +-320 + j*(79) +406 + j*(93) +-196 + j*(-371) +158 + j*(-298) +82 + j*(189) +-342 + j*(-235) +202 + j*(-280) +-194 + j*(-349) +-197 + j*(-312) +-291 + j*(-99) +-171 + j*(283) +87 + j*(-41) +-266 + j*(92) +595 + j*(573) +-362 + j*(-139) +154 + j*(-235) +127 + j*(-603) +191 + j*(663) +387 + j*(-70) +275 + j*(505) +161 + j*(-393) +411 + j*(-243) +-258 + j*(366) +-273 + j*(35) +-436 + j*(-470) +472 + j*(62) +-401 + j*(75) +99 + j*(-165) +180 + j*(421) +270 + j*(-199) +-52 + j*(-218) +-260 + j*(-283) +-527 + j*(277) +-286 + j*(456) +-444 + j*(97) +-276 + j*(309) +132 + j*(-304) +-231 + j*(-378) +-245 + j*(153) +406 + j*(305) +-338 + j*(229) +163 + j*(180) +-281 + j*(290) +477 + j*(-118) +-377 + j*(457) +169 + j*(-161) +-347 + j*(-248) +291 + j*(-45) +-157 + j*(60) +124 + j*(227) +-281 + j*(-433) +513 + j*(-282) +333 + j*(235) +299 + j*(-273) +322 + j*(211) +391 + j*(402) +198 + j*(-60) +-58 + j*(-472) +559 + j*(125) +130 + j*(334) +-93 + j*(245) +471 + j*(-211) +93 + j*(276) +36 + j*(-378) +780 + j*(281) +-291 + j*(301) +286 + j*(334) +227 + j*(-363) +351 + j*(163) +194 + j*(98) +-512 + j*(317) +-47 + j*(197) +-325 + j*(393) +122 + j*(9) +-264 + j*(-231) +339 + j*(141) +-274 + j*(-426) +330 + j*(-318) +625 + j*(-276) +-372 + j*(406) +-253 + j*(-171) +-314 + j*(-271) +159 + j*(161) +264 + j*(-505) +-280 + j*(563) +326 + j*(3) +235 + j*(78) +66 + j*(-384) +368 + j*(156) +-227 + j*(-17) +-409 + j*(-381) +-252 + j*(-306) +108 + j*(218) +-433 + j*(-35) +16 + j*(23) +648 + j*(-353) +296 + j*(47) +-291 + j*(360) +408 + j*(-459) +530 + j*(156) +175 + j*(262) +8 + j*(-363) +57 + j*(221) +142 + j*(161) +-162 + j*(72) +185 + j*(-160) +280 + j*(-128) +-272 + j*(-232) +31 + j*(-88) +-626 + j*(-132) +122 + j*(-325) +-274 + j*(126) +-312 + j*(206) +231 + j*(37) +-261 + j*(-124) +86 + j*(450) +-328 + j*(-586) +-175 + j*(-283) +25 + j*(-170) +340 + j*(372) +385 + j*(181) +354 + j*(-480) +-204 + j*(30) +-368 + j*(273) +-315 + j*(204) +-453 + j*(269) +-433 + j*(173) +532 + j*(258) +351 + j*(-124) +-26 + j*(-1) +208 + j*(83) +84 + j*(141) +-620 + j*(-32) +-229 + j*(34) +-146 + j*(-315) +-143 + j*(-223) +-135 + j*(375) +421 + j*(345) +498 + j*(-307) +425 + j*(-670) +315 + j*(613) +-361 + j*(253) +470 + j*(-390) +-8 + j*(132) +-173 + j*(74) +-375 + j*(317) +278 + j*(-225) +-247 + j*(156) +-371 + j*(-346) +-366 + j*(-146) +417 + j*(-374) +27 + j*(-231) +462 + j*(311) +-147 + j*(385) +433 + j*(-363) +-347 + j*(-521) +-345 + j*(206) +-503 + j*(473) +238 + j*(-395) +159 + j*(-239) +-163 + j*(189) +-468 + j*(-154) +-351 + j*(-30) +-271 + j*(491) +277 + j*(94) +-4 + j*(-162) +331 + j*(-389) +-246 + j*(496) +165 + j*(330) +453 + j*(257) +-64 + j*(-125) +-544 + j*(-247) +135 + j*(-176) +-383 + j*(-524) +-16 + j*(693) +-104 + j*(189) +139 + j*(110) +525 + j*(236) +172 + j*(-342) +313 + j*(223) +307 + j*(-435) +-525 + j*(-231) +317 + j*(-317) +-525 + j*(-696) +245 + j*(-131) +-568 + j*(-351) +71 + j*(-274) +-57 + j*(95) +-313 + j*(-417) +250 + j*(-74) +338 + j*(-238) +270 + j*(-151) +-166 + j*(437) +-414 + j*(460) +-285 + j*(304) +-274 + j*(511) +408 + j*(-422) +25 + j*(-37) +-370 + j*(107) +367 + j*(146) +-135 + j*(-324) +-329 + j*(180) +163 + j*(-82) +-568 + j*(185) +-496 + j*(-288) +-416 + j*(-366) +37 + j*(-95) +70 + j*(-424) +88 + j*(38) +-277 + j*(87) +-44 + j*(404) +-184 + j*(-651) +-304 + j*(-487) +-301 + j*(-136) +-36 + j*(-501) +416 + j*(104) +130 + j*(-443) +127 + j*(-177) +387 + j*(-144) +-186 + j*(6) +-333 + j*(-57) +-101 + j*(-190) +450 + j*(161) +85 + j*(-147) +442 + j*(-466) +-52 + j*(-173) +45 + j*(13) +289 + j*(96) +148 + j*(461) +-49 + j*(330) +-6 + j*(-279) +-44 + j*(152) +279 + j*(-176) +404 + j*(178) +239 + j*(297) +-267 + j*(449) +-371 + j*(-45) +-206 + j*(-267) +144 + j*(-57) +-352 + j*(199) +249 + j*(472) +-87 + j*(136) +-147 + j*(-480) +442 + j*(397) +-30 + j*(129) +-322 + j*(417) +818 + j*(11) +-14 + j*(338) +-257 + j*(-72) +352 + j*(-235) +-411 + j*(82) +348 + j*(-66) +50 + j*(257) +-315 + j*(103) +-394 + j*(-30) +-274 + j*(336) +-436 + j*(-178) +-147 + j*(-202) +173 + j*(264) +-167 + j*(-347) +-430 + j*(-67) +229 + j*(-447) +-255 + j*(771) +29 + j*(-579) +412 + j*(208) +385 + j*(-573) +-523 + j*(-310) +-513 + j*(-223) +148 + j*(-237) +-70 + j*(127) +-346 + j*(12) +-245 + j*(-208) +-146 + j*(204) +-216 + j*(23) +4 + j*(87) +-163 + j*(274) +-146 + j*(-27) +-74 + j*(250) +-97 + j*(69) +18 + j*(85) +-33 + j*(-192) +-84 + j*(-299) +15 + j*(32) +182 + j*(-194) +30 + j*(-209) +-151 + j*(-126) +315 + j*(-103) +-146 + j*(-21) +79 + j*(168) +535 + j*(44) +169 + j*(-331) +-139 + j*(229) +-192 + j*(55) +-84 + j*(-47) +221 + j*(78) +-83 + j*(-228) +86 + j*(-13) +-165 + j*(58) +-315 + j*(72) +-57 + j*(-23) +16 + j*(-209) +-50 + j*(-103) +-206 + j*(-19) +36 + j*(-36) +-78 + j*(-187) +-224 + j*(173) +172 + j*(29) +284 + j*(66) +155 + j*(194) +14 + j*(28) +144 + j*(-105) +-102 + j*(-113) +-132 + j*(-83) +15 + j*(-325) +40 + j*(-86) +203 + j*(-185) +64 + j*(115) +427 + j*(-47) +20 + j*(40) +-71 + j*(127) +238 + j*(44) +112 + j*(-142) +39 + j*(-171) +122 + j*(-204) +62 + j*(-64) +-33 + j*(-149) +-170 + j*(106) +296 + j*(52) +332 + j*(279) +203 + j*(70) +286 + j*(76) +-206 + j*(42) +-11 + j*(298) +129 + j*(-209) +110 + j*(218) +-17 + j*(-75) +198 + j*(15) +153 + j*(256) +-6 + j*(-125) +71 + j*(-89) +64 + j*(-11) +80 + j*(-31) +192 + j*(112) +-196 + j*(-18) +-21 + j*(204) +-54 + j*(305) +10 + j*(292) +30 + j*(238) +-144 + j*(333) +-230 + j*(-60) +-354 + j*(76) +87 + j*(-45) +193 + j*(215) +-170 + j*(204) +143 + j*(93) +-206 + j*(231) +151 + j*(121) +323 + j*(-74) +-132 + j*(-209) +-150 + j*(-150) +-153 + j*(-82) +-243 + j*(-144) +310 + j*(95) +342 + j*(-61) +-155 + j*(-117) +357 + j*(66) +-360 + j*(119) +86 + j*(-33) +209 + j*(40) +-105 + j*(62) +163 + j*(43) +-58 + j*(56) +134 + j*(-247) +14 + j*(84) +-105 + j*(-28) +-193 + j*(-215) +-51 + j*(-180) +97 + j*(-98) +-116 + j*(-25) +422 + j*(107) +105 + j*(62) +-30 + j*(62) +255 + j*(141) +-247 + j*(240) +23 + j*(25) +-163 + j*(6) +0 + j*(308) +-115 + j*(-250) +-83 + j*(-33) +-345 + j*(-57) +495 + j*(-29) +148 + j*(-51) +-203 + j*(144) +-57 + j*(39) +-52 + j*(283) +-7 + j*(218) +300 + j*(-182) +274 + j*(202) +59 + j*(13) +-74 + j*(259) +300 + j*(28) +1 + j*(117) +151 + j*(242) +267 + j*(332) +57 + j*(-315) +38 + j*(-178) +65 + j*(8) +-144 + j*(-271) +213 + j*(-199) +151 + j*(-91) +-252 + j*(-130) +-93 + j*(-66) +74 + j*(69) +-118 + j*(110) +293 + j*(187) +124 + j*(84) +211 + j*(-75) +-40 + j*(-15) +123 + j*(28) +105 + j*(-295) +198 + j*(185) +76 + j*(74) +-236 + j*(203) +-81 + j*(1) +-135 + j*(73) +-333 + j*(-332) +46 + j*(64) +-37 + j*(233) +-17 + j*(37) +321 + j*(182) +146 + j*(307) +98 + j*(-2) +-191 + j*(-138) +-252 + j*(124) +168 + j*(-105) +28 + j*(343) +-59 + j*(-71) +-119 + j*(-351) +18 + j*(-82) +319 + j*(69) +140 + j*(-41) +278 + j*(301) +-142 + j*(166) +-189 + j*(-316) +173 + j*(-260) +-26 + j*(-151) +-94 + j*(-54) +10 + j*(23) +134 + j*(-170) +-45 + j*(-260) +138 + j*(-59) +79 + j*(-220) +2 + j*(102) +163 + j*(74) +-105 + j*(42) +-295 + j*(-200) +184 + j*(-141) +-216 + j*(246) +-66 + j*(-23) +185 + j*(86) +-378 + j*(146) +-137 + j*(250) +233 + j*(190) +-66 + j*(-220) +-30 + j*(-128) +332 + j*(-71) +293 + j*(-6) +-35 + j*(-1) +-58 + j*(247) +252 + j*(-73) +-75 + j*(-220) +-57 + j*(6) +-197 + j*(-8) +321 + j*(149) +-308 + j*(141) +146 + j*(-230) +-168 + j*(-322) +-315 + j*(-190) +120 + j*(-298) +155 + j*(-344) +-15 + j*(146) +-156 + j*(-192) +-91 + j*(-6) +-62 + j*(-40) +-40 + j*(109) +-256 + j*(-19) +118 + j*(-350) +-365 + j*(-211) +-68 + j*(-100) +-86 + j*(-320) +33 + j*(-34) +136 + j*(1) +7 + j*(430) +161 + j*(54) +30 + j*(-78) +-87 + j*(-162) +282 + j*(269) +-277 + j*(260) +-10 + j*(404) +245 + j*(134) +-96 + j*(-129) +-183 + j*(83) +-114 + j*(266) +-3 + j*(-74) +115 + j*(77) +141 + j*(31) +-105 + j*(50) +-20 + j*(-341) +148 + j*(-116) +388 + j*(-106) +-112 + j*(-20) +58 + j*(-6) +207 + j*(-138) +124 + j*(-84) +-174 + j*(71) +-79 + j*(321) +-153 + j*(48) +-171 + j*(-315) +-115 + j*(19) +-73 + j*(-77) +-2 + j*(-59) +71 + j*(-69) +13 + j*(1) +129 + j*(-286) +-316 + j*(162) +303 + j*(210) +32 + j*(136) +-199 + j*(85) +-248 + j*(169) +246 + j*(88) +309 + j*(-105) +83 + j*(-149) +-46 + j*(-25) +-194 + j*(-202) +-88 + j*(-108) +76 + j*(29) +79 + j*(-213) +-90 + j*(14) +-88 + j*(106) +-194 + j*(-71) +-57 + j*(42) +-478 + j*(-83) +269 + j*(-33) +180 + j*(25) +-47 + j*(-96) +-190 + j*(115) +-10 + j*(-342) +-144 + j*(-26) +-264 + j*(4) +-192 + j*(48) +-303 + j*(117) +-49 + j*(268) +95 + j*(-177) +419 + j*(69) +-131 + j*(156) +-170 + j*(-4) +-8 + j*(-139) +-42 + j*(185) +0 + j*(-301) +20 + j*(-200) +397 + j*(-147) +-130 + j*(-238) +-42 + j*(33) +-78 + j*(12) +-59 + j*(-111) +-206 + j*(-145) +-141 + j*(-148) +-94 + j*(-163) +146 + j*(-16) +43 + j*(211) +202 + j*(244) +-67 + j*(-282) +223 + j*(64) +65 + j*(194) +-76 + j*(-1) +14 + j*(240) +-51 + j*(136) +-23 + j*(165) +-44 + j*(64) +110 + j*(132) +-153 + j*(-107) +-20 + j*(-114) +-226 + j*(-141) +-103 + j*(4) +-113 + j*(211) +153 + j*(-9) +252 + j*(-18) +-115 + j*(-216) +-83 + j*(295) +165 + j*(47) +66 + j*(-152) +194 + j*(88) +-46 + j*(-30) +100 + j*(-37) +148 + j*(-224) +167 + j*(84) +-174 + j*(-62) +-333 + j*(-233) +250 + j*(-173) +325 + j*(-9) +36 + j*(-29) +-85 + j*(20) +141 + j*(179) +-13 + j*(15) +-179 + j*(-415) +-358 + j*(87) +-236 + j*(236) +291 + j*(-188) +-114 + j*(268) +-187 + j*(-233) +62 + j*(-151) +-139 + j*(-336) +301 + j*(-37) +-75 + j*(74) +12 + j*(-259) +-351 + j*(-17) +193 + j*(-151) +-4 + j*(105) +206 + j*(5) +-153 + j*(-107) +185 + j*(242) +-5 + j*(-105) +20 + j*(14) +36 + j*(368) +37 + j*(139) +11 + j*(-123) +-218 + j*(-71) +-122 + j*(86) +-95 + j*(95) +-412 + j*(-148) +-218 + j*(-69) +-326 + j*(-87) +-131 + j*(11) +-11 + j*(84) +98 + j*(-194) +-49 + j*(-99) +207 + j*(-170) +-200 + j*(-292) +-46 + j*(152) +-144 + j*(-54) +196 + j*(268) +100 + j*(31) +-132 + j*(157) +-95 + j*(-239) +185 + j*(-6) +-117 + j*(-161) +106 + j*(164) +122 + j*(48) +-47 + j*(45) +47 + j*(83) +195 + j*(361) +68 + j*(207) +43 + j*(17) +-120 + j*(-76) +1 + j*(-81) +-138 + j*(-8) +1 + j*(-15) +10 + j*(-10) +30 + j*(37) +-24 + j*(-55) +-235 + j*(251) +-16 + j*(236) +139 + j*(-286) +62 + j*(86) +183 + j*(-165) +-71 + j*(-117) +57 + j*(-56) +71 + j*(-23) +-518 + j*(52) +189 + j*(-45) +3 + j*(-190) +89 + j*(186) +36 + j*(-11) +-308 + j*(283) +153 + j*(-55) +170 + j*(68) +16 + j*(-214) +141 + j*(223) +13 + j*(163) +-99 + j*(197) +-350 + j*(-84) +361 + j*(-123) +-153 + j*(-35) +184 + j*(-101) +-250 + j*(104) +-256 + j*(147) +-56 + j*(166) +-67 + j*(-78) +1 + j*(-257) +-173 + j*(-69) +-109 + j*(-93) +-17 + j*(71) +243 + j*(-110) +54 + j*(166) +-80 + j*(-250) +-134 + j*(-32) +-169 + j*(-201) +-98 + j*(-239) +339 + j*(-90) +-11 + j*(-78) +25 + j*(45) +109 + j*(-8) +45 + j*(-274) +-215 + j*(-130) +-139 + j*(178) +213 + j*(-269) +-202 + j*(-202) +-221 + j*(-17) +219 + j*(-466) +87 + j*(-278) +358 + j*(-91) +5 + j*(169) +-129 + j*(330) +42 + j*(0) +-86 + j*(-29) +-80 + j*(295) +-154 + j*(-121) +76 + j*(233) +238 + j*(-31) +97 + j*(-160) +23 + j*(-81) +5 + j*(-187) +-39 + j*(-139) +-262 + j*(83) +128 + j*(23) +-274 + j*(-51) +229 + j*(-56) +127 + j*(486) +104 + j*(112) +-46 + j*(257) +-210 + j*(-244) +81 + j*(111) +112 + j*(198) +231 + j*(319) +-86 + j*(103) +-7 + j*(-55) +-6 + j*(-153) +139 + j*(141) +37 + j*(212) +56 + j*(346) +298 + j*(-73) +-4 + j*(-55) +163 + j*(36) +-46 + j*(229) +124 + j*(-144) +-156 + j*(122) +-209 + j*(-109) +117 + j*(-151) +-235 + j*(-193) +-38 + j*(-64) +136 + j*(28) +66 + j*(-388) +-102 + j*(101) +171 + j*(182) +-192 + j*(81) +251 + j*(-343) +261 + j*(-61) +88 + j*(-33) +-158 + j*(408) +305 + j*(-63) +-8 + j*(-103) +565 + j*(250) +-128 + j*(-51) +-211 + j*(-122) +-115 + j*(170) +42 + j*(-29) +-99 + j*(-112) +-30 + j*(-85) +232 + j*(213) +282 + j*(-5) +-86 + j*(113) +-300 + j*(-236) +-132 + j*(-146) +-4 + j*(93) +99 + j*(215) +-70 + j*(-24) +-95 + j*(23) +-104 + j*(-33) +237 + j*(-209) +190 + j*(-75) +15 + j*(73) +106 + j*(86) +3 + j*(-178) +148 + j*(-86) +105 + j*(209) +34 + j*(-276) +10 + j*(204) +135 + j*(-187) +-57 + j*(-210) +69 + j*(93) +-7 + j*(487) +-141 + j*(-340) +33 + j*(13) +106 + j*(-265) +51 + j*(105) +-247 + j*(-185) +-168 + j*(-27) +-46 + j*(-325) +79 + j*(139) +-74 + j*(535) +245 + j*(-96) +334 + j*(-317) +-103 + j*(159) +-204 + j*(-19) +144 + j*(239) +36 + j*(-187) +98 + j*(-91) +-249 + j*(-33) +9 + j*(-223) +326 + j*(-165) +-135 + j*(-42) +-125 + j*(-16) +15 + j*(-2) +-243 + j*(-287) +-33 + j*(182) +-91 + j*(15) +-81 + j*(-71) +-194 + j*(-63) +37 + j*(-23) +-138 + j*(-11) +-54 + j*(100) +50 + j*(31) +-43 + j*(115) +-36 + j*(-128) +153 + j*(-170) +23 + j*(-226) +-72 + j*(13) +130 + j*(-53) +-259 + j*(93) +-315 + j*(-78) +-141 + j*(-96) +241 + j*(112) +-54 + j*(159) +58 + j*(57) +-355 + j*(63) +307 + j*(-132) +192 + j*(88) +-240 + j*(15) +-35 + j*(-6) +123 + j*(291) +-161 + j*(158) +34 + j*(-92) +36 + j*(233) +302 + j*(-199) +71 + j*(56) +-144 + j*(91) +131 + j*(276) +-77 + j*(151) +-110 + j*(214) +12 + j*(-490) +-186 + j*(-77) +308 + j*(84) +-203 + j*(3) +113 + j*(-112) +-222 + j*(-176) +81 + j*(-112) +15 + j*(-14) +-50 + j*(-186) +144 + j*(-47) +-120 + j*(-125) +215 + j*(207) +-32 + j*(-16) +-383 + j*(247) +-96 + j*(81) +-148 + j*(-11) +48 + j*(148) +173 + j*(0) +79 + j*(390) +180 + j*(-223) +274 + j*(40) +-153 + j*(47) +-116 + j*(112) +121 + j*(255) +198 + j*(176) +74 + j*(134) +-170 + j*(168) +91 + j*(129) +105 + j*(-324) +-326 + j*(25) +-109 + j*(74) +174 + j*(-59) +-244 + j*(54) +-314 + j*(279) +-145 + j*(213) +238 + j*(103) +28 + j*(190) +46 + j*(-172) +-28 + j*(-190) +-122 + j*(-110) +-112 + j*(-82) +298 + j*(-21) +-171 + j*(83) +99 + j*(16) +143 + j*(71) +-141 + j*(-247) +-214 + j*(-83) +-9 + j*(14) +-66 + j*(-51) +-175 + j*(-115) +233 + j*(-421) +117 + j*(54) +148 + j*(-204) +-122 + j*(128) +-4 + j*(20) +-139 + j*(-47) +105 + j*(-64) +21 + j*(-56) +-144 + j*(-13) +-238 + j*(-225) +-97 + j*(139) +-83 + j*(15) +45 + j*(80) +-1 + j*(173) +260 + j*(141) +-125 + j*(2) +117 + j*(100) +100 + j*(-3) +255 + j*(-33) +-214 + j*(-199) +243 + j*(344) +85 + j*(158) +-322 + j*(-165) +-214 + j*(296) +-128 + j*(58) +-74 + j*(-222) +-25 + j*(-93) +44 + j*(5) +-63 + j*(-137) +-160 + j*(-328) +29 + j*(12) +-78 + j*(107) +142 + j*(238) +205 + j*(-250) +-207 + j*(191) +165 + j*(-142) +199 + j*(141) +28 + j*(-93) +-141 + j*(175) +-177 + j*(148) +274 + j*(-18) +-224 + j*(-92) +17 + j*(-247) +265 + j*(-45) +-121 + j*(134) +-66 + j*(-78) +253 + j*(-176) +-52 + j*(86) +-156 + j*(13) +-239 + j*(-81) +51 + j*(-115) +-134 + j*(36) +-83 + j*(-69) +-117 + j*(78) +145 + j*(91) +288 + j*(114) +6 + j*(136) +121 + j*(240) +-60 + j*(37) +197 + j*(100) +-275 + j*(78) +57 + j*(321) +-260 + j*(170) +91 + j*(-288) +-168 + j*(-164) +-171 + j*(-35) +-136 + j*(344) +43 + j*(3) +-206 + j*(168) +-343 + j*(124) +-222 + j*(-301) +98 + j*(146) +-30 + j*(-252) +203 + j*(-21) +-42 + j*(-90) +49 + j*(-36) +-62 + j*(-53) +-202 + j*(103) +2 + j*(53) +95 + j*(297) +67 + j*(-303) +183 + j*(-70) +-399 + j*(74) +-272 + j*(-213) +-167 + j*(158) +68 + j*(-21) +-180 + j*(77) +25 + j*(-18) +-57 + j*(-4) +136 + j*(-37) +215 + j*(-322) +322 + j*(34) +-122 + j*(-172) +185 + j*(264) +-144 + j*(247) +5 + j*(-125) +36 + j*(-313) +189 + j*(5) +140 + j*(-150) +7 + j*(69) +-113 + j*(11) +190 + j*(368) +-284 + j*(-105) +-62 + j*(5) +-132 + j*(-367) +-225 + j*(-90) +50 + j*(-269) +134 + j*(243) +-141 + j*(-52) +-226 + j*(53) +342 + j*(-53) +93 + j*(-263) +-92 + j*(-141) +125 + j*(162) +-123 + j*(66) +42 + j*(49) +-93 + j*(-114) +-92 + j*(-310) +-271 + j*(-95) +114 + j*(-197) +322 + j*(158) +-43 + j*(28) +-215 + j*(-171) +173 + j*(204) +332 + j*(213) +94 + j*(67) +328 + j*(23) +392 + j*(-35) +155 + j*(-135) +3 + j*(315) +-211 + j*(50) +226 + j*(-136) +-25 + j*(-26) +-126 + j*(78) +-107 + j*(-45) +24 + j*(227) +-100 + j*(100) +260 + j*(22) +-76 + j*(390) +-288 + j*(49) +66 + j*(110) +-163 + j*(-91) +-273 + j*(-385) +28 + j*(-218) +-231 + j*(156) +47 + j*(-76) +75 + j*(-82) +-43 + j*(133) +3 + j*(-226) +-69 + j*(-83) +231 + j*(-101) +-290 + j*(-52) +47 + j*(57) +-200 + j*(89) +-70 + j*(265) +55 + j*(-255) +-156 + j*(127) +91 + j*(337) +-3 + j*(163) +-129 + j*(-339) +-16 + j*(167) +-245 + j*(291) +-114 + j*(168) +-84 + j*(-148) +-7 + j*(-243) +-47 + j*(-44) +166 + j*(50) +227 + j*(-92) +215 + j*(291) +149 + j*(35) +-109 + j*(-145) +-190 + j*(-100) +-102 + j*(-8) +230 + j*(169) +16 + j*(58) +133 + j*(-169) +-16 + j*(291) +267 + j*(72) +84 + j*(52) +-342 + j*(73) +-101 + j*(228) +-16 + j*(180) +-2 + j*(122) +3 + j*(-344) +-93 + j*(-185) +38 + j*(92) +226 + j*(71) +390 + j*(-98) +179 + j*(-201) +-180 + j*(-31) +-40 + j*(-165) +109 + j*(-119) +105 + j*(-171) +-322 + j*(313) +-1 + j*(-18) +-47 + j*(256) +282 + j*(-29) +-383 + j*(-225) +284 + j*(16) +81 + j*(244) +252 + j*(279) +257 + j*(-23) +-491 + j*(254) +-102 + j*(175) +-46 + j*(269) +102 + j*(91) +5 + j*(123) +55 + j*(69) +29 + j*(105) +-197 + j*(4) +-84 + j*(226) +-12 + j*(95) +-57 + j*(-259) +195 + j*(-243) +134 + j*(133) +25 + j*(-165) +-71 + j*(-205) +91 + j*(-71) +-201 + j*(18) +-135 + j*(-405) +180 + j*(153) +323 + j*(276) +376 + j*(73) +221 + j*(65) +-231 + j*(236) +164 + j*(156) +238 + j*(97) +-18 + j*(-199) +144 + j*(-33) +-231 + j*(33) +-23 + j*(154) +50 + j*(24) +-145 + j*(-113) +32 + j*(138) +110 + j*(-121) +168 + j*(-242) +233 + j*(20) +30 + j*(87) +115 + j*(-67) +221 + j*(-12) +23 + j*(64) +66 + j*(161) +-91 + j*(-159) +-98 + j*(158) +-73 + j*(49) +-74 + j*(-26) +-209 + j*(76) +280 + j*(88) +1 + j*(-30) +474 + j*(136) +-39 + j*(-202) +61 + j*(-49) +-82 + j*(-31) +-25 + j*(267) +110 + j*(286) +-257 + j*(-42) +288 + j*(-35) +16 + j*(324) +449 + j*(-50) +-169 + j*(190) +108 + j*(-13) +-151 + j*(33) +-21 + j*(119) +82 + j*(-81) +132 + j*(-28) +-413 + j*(-19) +-295 + j*(-208) +153 + j*(145) +-7 + j*(194) +-110 + j*(-147) +-145 + j*(-126) +284 + j*(64) +-81 + j*(110) +263 + j*(-72) +12 + j*(-312) +-76 + j*(119) +154 + j*(52) +138 + j*(109) +-98 + j*(-220) +-433 + j*(-9) +267 + j*(-3) +-168 + j*(203) +33 + j*(-329) +129 + j*(-35) +-177 + j*(-58) +-161 + j*(-55) +-161 + j*(108) +-168 + j*(320) +-258 + j*(65) +-165 + j*(30) +-131 + j*(-6) +-98 + j*(25) +136 + j*(410) +1 + j*(332) +6 + j*(117) +-42 + j*(-151) +-15 + j*(-139) +292 + j*(-97) +208 + j*(-216) +113 + j*(-93) +168 + j*(160) +-261 + j*(88) +226 + j*(110) +70 + j*(-298) +-221 + j*(312) +54 + j*(101) +-108 + j*(166) +306 + j*(162) +75 + j*(52) +-129 + j*(-223) +47 + j*(59) +235 + j*(75) +-226 + j*(45) +238 + j*(91) +324 + j*(168) +132 + j*(-354) +-504 + j*(151) +234 + j*(112) +236 + j*(179) +-25 + j*(-47) +136 + j*(-141) +311 + j*(352) +20 + j*(-145) +61 + j*(-187) +146 + j*(-66) +-111 + j*(-25) +238 + j*(-6) +-248 + j*(-57) +255 + j*(169) +368 + j*(-76) +13 + j*(7) +-101 + j*(33) +1 + j*(227) +-243 + j*(-105) +-4 + j*(59) +118 + j*(38) +-23 + j*(57) +85 + j*(-116) +-170 + j*(-131) +-13 + j*(-11) +49 + j*(-61) +-37 + j*(294) +118 + j*(308) +-120 + j*(-21) +-232 + j*(-107) +393 + j*(312) +25 + j*(76) +74 + j*(23) +59 + j*(-136) +306 + j*(86) +-260 + j*(-314) +194 + j*(163) +-199 + j*(257) +-175 + j*(-257) +-232 + j*(13) +240 + j*(-95) +-155 + j*(-172) +361 + j*(-116) +-132 + j*(-152) +-110 + j*(71) +-279 + j*(288) +-4 + j*(-28) +-12 + j*(154) +89 + j*(190) +104 + j*(42) +-221 + j*(-151) +-91 + j*(115) +162 + j*(-30) +-471 + j*(-45) +225 + j*(-34) +161 + j*(199) +136 + j*(164) +-116 + j*(87) +-48 + j*(195) +74 + j*(156) +-23 + j*(7) +204 + j*(166) +-150 + j*(1) +19 + j*(79) +44 + j*(5) +-161 + j*(76) +122 + j*(-240) +151 + j*(-18) +-23 + j*(53) +-227 + j*(97) +-26 + j*(-221) +-358 + j*(-142) +217 + j*(-240) +-139 + j*(-170) +39 + j*(202) +55 + j*(-36) +122 + j*(-217) +65 + j*(242) +23 + j*(13) +-46 + j*(-73) +-81 + j*(-328) +131 + j*(-276) +-136 + j*(186) +158 + j*(204) +100 + j*(-209) +35 + j*(43) +4 + j*(43) +-263 + j*(6) +-16 + j*(159) +316 + j*(139) +336 + j*(-135) +-201 + j*(-235) +-13 + j*(-197) +275 + j*(139) +-188 + j*(13) +-152 + j*(-9) +-61 + j*(-177) +-369 + j*(-195) +160 + j*(-98) +56 + j*(-1) +-276 + j*(-13) +112 + j*(-183) +-231 + j*(206) +42 + j*(-163) +76 + j*(-34) +25 + j*(-84) +62 + j*(-61) +-258 + j*(-87) +-145 + j*(169) +-240 + j*(289) +-204 + j*(-272) +-191 + j*(-68) +45 + j*(91) +-124 + j*(46) +-261 + j*(-18) +144 + j*(340) +-24 + j*(216) +-7 + j*(-41) +239 + j*(52) +-292 + j*(-157) +210 + j*(-414) +-299 + j*(-11) +6 + j*(71) +226 + j*(-406) +27 + j*(187) +-72 + j*(-43) +-115 + j*(-215) +41 + j*(-39) +220 + j*(38) +-158 + j*(-246) +-24 + j*(-111) +-69 + j*(126) +137 + j*(-32) +-279 + j*(11) +-98 + j*(-329) +-38 + j*(68) +-366 + j*(19) +-94 + j*(-104) +197 + j*(-37) +-93 + j*(34) +-352 + j*(-19) +64 + j*(40) +165 + j*(-195) +37 + j*(42) +-177 + j*(-74) +-194 + j*(-129) +269 + j*(174) +55 + j*(-28) +-56 + j*(-37) +-309 + j*(-131) +69 + j*(-18) +-173 + j*(-9) +122 + j*(-270) +64 + j*(-221) +197 + j*(66) +-66 + j*(354) +1 + j*(133) +-125 + j*(129) +-255 + j*(-137) +180 + j*(106) +-223 + j*(385) +335 + j*(42) +-99 + j*(-32) +182 + j*(91) +213 + j*(29) +32 + j*(-33) +-75 + j*(37) +-109 + j*(-296) +134 + j*(99) +-53 + j*(-76) +140 + j*(176) +248 + j*(-379) +-76 + j*(-151) +-132 + j*(-22) +-116 + j*(110) +-82 + j*(-76) +-199 + j*(-174) +118 + j*(240) +-144 + j*(13) +-25 + j*(173) +-230 + j*(-95) +125 + j*(182) +-105 + j*(122) +-101 + j*(195) +20 + j*(-121) +35 + j*(-342) +-119 + j*(-385) +-188 + j*(-165) +-252 + j*(-393) +-269 + j*(-127) +-31 + j*(-12) +336 + j*(-78) +-52 + j*(-105) +-25 + j*(330) +11 + j*(149) +-81 + j*(-163) +-153 + j*(-223) +107 + j*(-33) +-294 + j*(-106) +-189 + j*(247) +-218 + j*(-154) +99 + j*(-35) +127 + j*(-290) +404 + j*(-88) +-135 + j*(268) +316 + j*(313) +206 + j*(161) +-385 + j*(36) +-17 + j*(266) +4 + j*(-23) +-83 + j*(73) +0 + j*(116) +160 + j*(199) +178 + j*(-109) +-69 + j*(-147) +125 + j*(59) +244 + j*(98) +-146 + j*(197) +59 + j*(234) +218 + j*(386) +23 + j*(-74) +438 + j*(90) +259 + j*(55) +181 + j*(214) +-38 + j*(-76) +-182 + j*(55) +-148 + j*(-138) +-130 + j*(281) +125 + j*(-132) +-90 + j*(-105) +183 + j*(255) +-138 + j*(288) +-165 + j*(-25) +-207 + j*(427) +259 + j*(-175) +147 + j*(-359) +116 + j*(-28) +-263 + j*(-146) +-217 + j*(48) +9 + j*(-62) +77 + j*(-11) +61 + j*(-215) +35 + j*(66) +85 + j*(1) +6 + j*(-23) +161 + j*(37) +-124 + j*(280) +111 + j*(-3) +26 + j*(233) +-76 + j*(130) +15 + j*(-241) +-78 + j*(-167) +44 + j*(-25) +-167 + j*(205) +-99 + j*(-188) +-154 + j*(120) +-61 + j*(11) +361 + j*(-10) +236 + j*(-204) +139 + j*(-104) +-106 + j*(44) +-40 + j*(99) +-1 + j*(-134) +-148 + j*(30) +-134 + j*(54) +-239 + j*(85) +-275 + j*(-269) +90 + j*(-83) +-225 + j*(-148) +332 + j*(-88) +-47 + j*(424) +-128 + j*(78) +163 + j*(69) +-175 + j*(88) +-146 + j*(243) +308 + j*(25) +301 + j*(26) +110 + j*(-218) +-139 + j*(-78) +279 + j*(92) +161 + j*(252) +-91 + j*(81) +-100 + j*(11) +-90 + j*(92) +-98 + j*(-146) +404 + j*(216) +178 + j*(-197) +-50 + j*(-149) +165 + j*(-58) +27 + j*(-303) +95 + j*(169) +-108 + j*(52) +294 + j*(-26) +-37 + j*(-3) +-101 + j*(-292) +187 + j*(250) +-71 + j*(339) +42 + j*(-67) +-66 + j*(50) +-37 + j*(-90) +93 + j*(56) +141 + j*(-18) +77 + j*(-32) +74 + j*(28) +248 + j*(223) +232 + j*(-345) +66 + j*(-51) +42 + j*(49) +54 + j*(113) +25 + j*(-40) +-88 + j*(156) +52 + j*(-112) +-214 + j*(325) +144 + j*(122) +-170 + j*(147) +-251 + j*(33) +-195 + j*(-218) +433 + j*(224) +-174 + j*(-269) +-75 + j*(-378) +-30 + j*(-155) +227 + j*(-212) +-1 + j*(-420) +-45 + j*(331) +139 + j*(-228) +114 + j*(438) +313 + j*(-54) +-460 + j*(-39) +125 + j*(-170) +222 + j*(-85) +-127 + j*(-302) +97 + j*(279) +114 + j*(121) +-226 + j*(144) +69 + j*(10) +162 + j*(-109) +206 + j*(-395) +-243 + j*(-5) +-86 + j*(294) +15 + j*(68) +206 + j*(-216) +-190 + j*(151) +-88 + j*(-41) +44 + j*(202) +-36 + j*(-110) +-35 + j*(16) +-29 + j*(85) +0 + j*(155) +-35 + j*(-83) +221 + j*(-148) +18 + j*(-342) +-83 + j*(7) +-8 + j*(-144) +9 + j*(-88) +-103 + j*(-317) +191 + j*(187) +-337 + j*(-266) +-24 + j*(8) +-515 + j*(-130) +-129 + j*(142) +78 + j*(138) +-70 + j*(264) +117 + j*(-196) +214 + j*(263) +45 + j*(-140) +127 + j*(-354) +-16 + j*(-46) +-6 + j*(-17) +-69 + j*(-194) +8 + j*(315) +52 + j*(119) +243 + j*(65) +19 + j*(1) +-163 + j*(-174) +124 + j*(-188) +-438 + j*(25) +102 + j*(-9) +88 + j*(-352) +214 + j*(-132) +150 + j*(-23) +-28 + j*(58) +52 + j*(-147) +-59 + j*(332) +-248 + j*(88) +47 + j*(138) +210 + j*(-60) +129 + j*(-173) +-54 + j*(235) +-190 + j*(284) +-74 + j*(142) +73 + j*(-128) +-46 + j*(-215) +126 + j*(328) +-136 + j*(105) +-32 + j*(-168) +-313 + j*(-133) +59 + j*(-33) +-39 + j*(158) +93 + j*(-158) +-30 + j*(-192) +119 + j*(21) +-8 + j*(180) +177 + j*(-231) +211 + j*(-264) +98 + j*(146) +46 + j*(13) +-170 + j*(98) +93 + j*(18) +-115 + j*(-21) +-86 + j*(-20) +76 + j*(325) +77 + j*(33) +199 + j*(-40) +154 + j*(-236) +-14 + j*(139) +37 + j*(65) +-121 + j*(36) +-206 + j*(247) +-18 + j*(65) +573 + j*(148) +169 + j*(-257) +-64 + j*(40) +53 + j*(-59) +-46 + j*(88) +-197 + j*(176) +18 + j*(-134) +-177 + j*(-109) +-76 + j*(142) +252 + j*(-144) +-2 + j*(-101) +41 + j*(-153) +-109 + j*(-24) +4 + j*(141) +49 + j*(-73) +-151 + j*(134) +-125 + j*(151) +-78 + j*(272) +49 + j*(-177) +-193 + j*(-143) +-164 + j*(-261) +29 + j*(-115) +195 + j*(-140) +85 + j*(13) +-86 + j*(27) +-77 + j*(-128) +378 + j*(114) +-436 + j*(49) +-55 + j*(134) +-144 + j*(-27) +99 + j*(315) +92 + j*(154) +148 + j*(177) +93 + j*(83) +119 + j*(310) +190 + j*(-248) +-259 + j*(-248) +218 + j*(310) +63 + j*(197) +226 + j*(81) +22 + j*(-151) +60 + j*(-168) +-285 + j*(231) +-40 + j*(-78) +144 + j*(-128) +-20 + j*(-402) +66 + j*(-8) +-71 + j*(17) +94 + j*(-111) +-22 + j*(-16) +128 + j*(-156) +-212 + j*(324) +-320 + j*(409) +-137 + j*(235) +52 + j*(-438) +205 + j*(178) +86 + j*(-149) +246 + j*(-124) +129 + j*(-48) +-23 + j*(72) +54 + j*(-18) +-136 + j*(225) +-134 + j*(198) +255 + j*(-239) +-378 + j*(-39) +-23 + j*(110) +35 + j*(-124) +47 + j*(-40) +177 + j*(-16) +178 + j*(-54) +-197 + j*(33) +141 + j*(-42) +134 + j*(245) +68 + j*(101) +-353 + j*(-16) +-375 + j*(47) +129 + j*(-129) +-75 + j*(-96) +192 + j*(66) +116 + j*(41) +-33 + j*(17) +103 + j*(81) +-52 + j*(214) +132 + j*(59) +-342 + j*(375) +-308 + j*(-103) +-68 + j*(140) +460 + j*(110) +-18 + j*(-97) +551 + j*(-522) +243 + j*(69) +534 + j*(264) +-373 + j*(-374) +-543 + j*(503) +292 + j*(223) +494 + j*(-12) +-96 + j*(-122) +600 + j*(-210) +378 + j*(-357) +39 + j*(477) +298 + j*(82) +-46 + j*(604) +-197 + j*(28) +-313 + j*(460) +-57 + j*(168) +368 + j*(-167) +-82 + j*(-532) +12 + j*(-259) +-498 + j*(-542) +567 + j*(190) +18 + j*(-402) +675 + j*(32) +-188 + j*(272) +778 + j*(51) +245 + j*(479) +-82 + j*(-250) +342 + j*(-177) +360 + j*(-356) +279 + j*(286) +-396 + j*(-656) +154 + j*(-335) +-88 + j*(-243) +327 + j*(-137) +488 + j*(274) +322 + j*(-62) +-43 + j*(507) +660 + j*(265) +-264 + j*(81) +-158 + j*(-299) +-449 + j*(-491) +557 + j*(78) +-6 + j*(-75) +569 + j*(135) +478 + j*(-146) +-92 + j*(-381) +-289 + j*(170) +276 + j*(-35) +-373 + j*(-409) +-288 + j*(-107) +173 + j*(-235) +286 + j*(-235) +236 + j*(-559) +52 + j*(164) +-2 + j*(-477) +169 + j*(346) +-322 + j*(-5) +-154 + j*(151) +250 + j*(66) +-477 + j*(79) +281 + j*(-82) +214 + j*(-72) +188 + j*(394) +146 + j*(-163) +-297 + j*(292) +133 + j*(-588) +648 + j*(-378) +285 + j*(453) +377 + j*(-400) +441 + j*(349) +388 + j*(-69) +396 + j*(550) +-27 + j*(-142) +446 + j*(361) +255 + j*(-25) +138 + j*(-252) +443 + j*(162) +471 + j*(-293) +309 + j*(359) +187 + j*(178) +359 + j*(-255) +-251 + j*(292) +-246 + j*(-288) +-402 + j*(427) +77 + j*(211) +-254 + j*(364) +123 + j*(-347) +-223 + j*(-178) +-245 + j*(-308) +392 + j*(192) +-302 + j*(453) +-384 + j*(-284) +-161 + j*(-283) +117 + j*(-281) +-272 + j*(274) +-211 + j*(249) +-530 + j*(-353) +204 + j*(471) +23 + j*(-124) +-119 + j*(-276) +-35 + j*(-373) +443 + j*(-426) +-23 + j*(-441) +149 + j*(-441) +-160 + j*(335) +224 + j*(-366) +-166 + j*(81) +30 + j*(-435) +213 + j*(-171) +337 + j*(364) +-301 + j*(121) +163 + j*(358) +-417 + j*(255) +-170 + j*(-19) +198 + j*(-239) +418 + j*(-470) +187 + j*(225) +-338 + j*(-273) +-581 + j*(87) +167 + j*(-600) +-685 + j*(414) +351 + j*(-370) +6 + j*(-515) +-279 + j*(-240) +45 + j*(-40) +-130 + j*(233) +-637 + j*(-235) +-187 + j*(165) +-135 + j*(386) +16 + j*(355) +-219 + j*(8) +469 + j*(-107) +71 + j*(108) +-16 + j*(15) +-14 + j*(-530) +-252 + j*(68) +288 + j*(536) +288 + j*(-182) +-478 + j*(-6) +-134 + j*(151) +-38 + j*(-388) +-414 + j*(-317) +440 + j*(-426) +-218 + j*(-705) +-304 + j*(-85) +-662 + j*(54) +273 + j*(-4) +268 + j*(211) +18 + j*(315) +141 + j*(292) +116 + j*(268) +-253 + j*(146) +235 + j*(-55) +-259 + j*(-178) +-197 + j*(-585) +-64 + j*(441) +-271 + j*(-188) +358 + j*(506) +13 + j*(-94) +-339 + j*(-167) +329 + j*(400) +50 + j*(-484) +91 + j*(366) +-407 + j*(-144) +-439 + j*(165) +170 + j*(-325) +-479 + j*(355) +237 + j*(-239) +99 + j*(-355) +-122 + j*(281) +515 + j*(148) +-132 + j*(-269) +-174 + j*(34) +11 + j*(-386) +291 + j*(-351) +243 + j*(52) +-300 + j*(129) +344 + j*(-442) +-232 + j*(83) +-10 + j*(2) +300 + j*(733) +-139 + j*(28) +83 + j*(-425) +-403 + j*(-188) +-344 + j*(-337) +345 + j*(144) +-245 + j*(-193) +-552 + j*(105) +433 + j*(-513) +426 + j*(188) +12 + j*(385) +-114 + j*(-211) +-261 + j*(-512) +268 + j*(139) +327 + j*(305) +309 + j*(-86) +366 + j*(407) +-206 + j*(277) +-81 + j*(319) +-21 + j*(108) +33 + j*(-84) +234 + j*(349) +-337 + j*(759) +169 + j*(324) +-183 + j*(333) +1 + j*(-487) +156 + j*(-346) +240 + j*(-270) +224 + j*(-426) +-71 + j*(-328) +117 + j*(-204) +79 + j*(-344) +-361 + j*(113) +-165 + j*(332) +-582 + j*(-463) +504 + j*(204) +-578 + j*(139) +-26 + j*(209) +-121 + j*(378) +-511 + j*(55) +156 + j*(-371) +12 + j*(-390) +231 + j*(-57) +11 + j*(-35) +-498 + j*(-8) +-465 + j*(-315) +-45 + j*(-214) +245 + j*(53) +-460 + j*(-199) +-151 + j*(272) +-453 + j*(-342) +194 + j*(8) +-68 + j*(-393) +-231 + j*(168) +-364 + j*(-337) +-414 + j*(-211) +701 + j*(-303) +-287 + j*(-534) +201 + j*(140) +177 + j*(110) +-54 + j*(-180) +-344 + j*(-205) +280 + j*(53) +432 + j*(-19) +376 + j*(99) +363 + j*(509) +404 + j*(-474) +-279 + j*(28) +-496 + j*(74) +308 + j*(-384) +680 + j*(230) +620 + j*(-209) +295 + j*(444) +194 + j*(411) +-185 + j*(-2) +546 + j*(317) +-5 + j*(313) +-415 + j*(229) +188 + j*(429) +247 + j*(617) +-12 + j*(495) +175 + j*(312) +-170 + j*(-268) +-74 + j*(-233) +-162 + j*(-310) +-210 + j*(156) +395 + j*(-435) +-184 + j*(268) +-24 + j*(-264) +431 + j*(-350) +-389 + j*(453) +-98 + j*(-118) +117 + j*(531) +-165 + j*(358) +74 + j*(-362) +-304 + j*(61) +-199 + j*(158) +228 + j*(167) +397 + j*(170) +266 + j*(-310) +450 + j*(93) +-215 + j*(-63) +-231 + j*(-31) +411 + j*(-336) +443 + j*(173) +288 + j*(240) +70 + j*(208) +-298 + j*(-249) +349 + j*(279) +-82 + j*(-6) +-282 + j*(-40) +227 + j*(-322) +93 + j*(695) +-433 + j*(392) +65 + j*(-356) +-249 + j*(250) +297 + j*(-205) +107 + j*(363) +95 + j*(270) +310 + j*(-12) +-228 + j*(532) +111 + j*(78) +227 + j*(-24) +141 + j*(-596) +-252 + j*(409) +-277 + j*(-249) +-53 + j*(532) +-173 + j*(-244) +519 + j*(402) +18 + j*(234) +-135 + j*(307) +-309 + j*(95) +-289 + j*(264) +289 + j*(-284) +147 + j*(-311) +-377 + j*(460) +-298 + j*(549) +177 + j*(332) +599 + j*(-378) +40 + j*(355) +373 + j*(121) +-266 + j*(-45) +-85 + j*(-47) +-186 + j*(-18) +-8 + j*(-195) +409 + j*(-610) +34 + j*(502) +-576 + j*(78) +298 + j*(164) +409 + j*(-331) +506 + j*(-433) +460 + j*(-700) +-84 + j*(269) +-303 + j*(375) +-5 + j*(-106) +30 + j*(85) +296 + j*(361) +-179 + j*(-178) +-477 + j*(-308) +-141 + j*(-696) +-149 + j*(398) +392 + j*(431) +-300 + j*(206) +-248 + j*(515) +462 + j*(217) +253 + j*(244) +164 + j*(-196) +308 + j*(-40) +28 + j*(124) +-172 + j*(-233) +471 + j*(-272) +332 + j*(445) +-217 + j*(200) +-307 + j*(-209) +503 + j*(207) +499 + j*(378) +-203 + j*(87) +-273 + j*(438) +170 + j*(364) +384 + j*(-122) +291 + j*(-509) +-74 + j*(422) +-571 + j*(126) +76 + j*(264) +-383 + j*(-128) +333 + j*(-436) +-105 + j*(-313) +260 + j*(-61) +404 + j*(465) +-172 + j*(363) +-225 + j*(-317) +185 + j*(-140) +132 + j*(40) +-199 + j*(-365) +470 + j*(-37) +89 + j*(-250) +-94 + j*(256) +0 + j*(397) +-326 + j*(531) +-245 + j*(-2) +-105 + j*(-4) +100 + j*(274) +-392 + j*(-227) +-274 + j*(173) +-93 + j*(-418) +646 + j*(214) +-568 + j*(-668) +582 + j*(16) +-129 + j*(-274) +272 + j*(226) +-8 + j*(-176) +351 + j*(387) +467 + j*(194) +-225 + j*(166) +-40 + j*(-489) +82 + j*(-408) +-168 + j*(268) +-28 + j*(-298) +-503 + j*(-358) +94 + j*(-250) +564 + j*(41) +-468 + j*(-158) +331 + j*(311) +303 + j*(-211) +185 + j*(-366) +-262 + j*(171) +-165 + j*(-372) +-414 + j*(-305) +-334 + j*(-371) +-62 + j*(26) +141 + j*(208) +250 + j*(347) +-256 + j*(-16) +-501 + j*(552) +452 + j*(-195) +-239 + j*(-151) +-426 + j*(-532) +10 + j*(-282) +-412 + j*(414) +-482 + j*(-233) +-321 + j*(256) +-124 + j*(32) +409 + j*(-373) +-568 + j*(-613) +-311 + j*(306) +-81 + j*(-678) +432 + j*(-555) +-374 + j*(376) +231 + j*(-211) +404 + j*(-189) +191 + j*(403) +511 + j*(-279) +-544 + j*(202) +136 + j*(-401) +363 + j*(-269) +-499 + j*(-64) +385 + j*(549) +243 + j*(250) +-209 + j*(393) +-231 + j*(-198) +272 + j*(-286) +133 + j*(-260) +-366 + j*(-317) +-76 + j*(25) +-270 + j*(255) +-267 + j*(118) +-217 + j*(-233) +313 + j*(370) +282 + j*(-179) +-513 + j*(120) +-118 + j*(-400) +286 + j*(-403) +-231 + j*(133) +-175 + j*(-118) +-161 + j*(-173) +-118 + j*(411) +-51 + j*(-93) +-542 + j*(16) +233 + j*(-422) +-13 + j*(-86) +345 + j*(-467) +-296 + j*(-259) +-23 + j*(-313) +74 + j*(476) +182 + j*(-244) +-266 + j*(-231) +-251 + j*(-226) +-395 + j*(-360) +-156 + j*(550) +217 + j*(163) +-486 + j*(433) +-281 + j*(248) +-65 + j*(67) +232 + j*(-296) +-383 + j*(-46) +403 + j*(99) +210 + j*(-325) +-217 + j*(-564) +-328 + j*(169) +-196 + j*(132) +-624 + j*(225) +-480 + j*(200) +-418 + j*(307) +367 + j*(-327) +-365 + j*(-371) +422 + j*(-177) +296 + j*(-316) +-284 + j*(-382) +414 + j*(163) +-542 + j*(-593) +332 + j*(40) +-100 + j*(368) +355 + j*(-380) +542 + j*(-166) +63 + j*(267) +-427 + j*(293) +-83 + j*(206) +-610 + j*(45) +348 + j*(-95) +469 + j*(-153) +235 + j*(-150) +-285 + j*(380) +-399 + j*(-140) +247 + j*(-107) +-556 + j*(472) +-168 + j*(-3) +-204 + j*(-325) +590 + j*(303) +-222 + j*(228) +200 + j*(233) +524 + j*(-117) +-57 + j*(257) +-405 + j*(-373) +-441 + j*(-124) +16 + j*(374) +306 + j*(-499) +-36 + j*(-2) +-103 + j*(-356) +378 + j*(214) +-361 + j*(-255) +-180 + j*(328) +-267 + j*(-305) +204 + j*(-63) +45 + j*(-543) +-134 + j*(-142) +321 + j*(508) +-412 + j*(549) +-240 + j*(182) +-353 + j*(177) +-138 + j*(-158) +165 + j*(-395) +234 + j*(-400) +-256 + j*(373) +37 + j*(-249) +69 + j*(-151) +-211 + j*(-291) +-209 + j*(-90) +-366 + j*(-367) +555 + j*(-146) +-202 + j*(-583) +-280 + j*(-259) +264 + j*(-309) +595 + j*(80) +-318 + j*(-107) +-306 + j*(96) +128 + j*(-289) +149 + j*(65) +265 + j*(-255) +-399 + j*(-277) +325 + j*(-206) +-368 + j*(122) +306 + j*(-187) +-261 + j*(329) +-223 + j*(-4) +443 + j*(477) +-476 + j*(403) +112 + j*(-310) +-124 + j*(93) +-25 + j*(-349) +404 + j*(-98) +-134 + j*(328) +-289 + j*(-192) +151 + j*(137) +431 + j*(301) +-76 + j*(-70) +-161 + j*(-161) +-590 + j*(-261) +276 + j*(291) +232 + j*(-365) +-383 + j*(-45) +409 + j*(-97) +-266 + j*(366) +433 + j*(-146) +-308 + j*(18) +238 + j*(80) +-52 + j*(299) +-250 + j*(499) +-395 + j*(358) +-83 + j*(-467) +173 + j*(284) +43 + j*(-25) +97 + j*(293) +-46 + j*(578) +245 + j*(-372) +-127 + j*(197) +-59 + j*(-461) +301 + j*(358) +-95 + j*(205) +-132 + j*(260) +-337 + j*(286) +-215 + j*(-344) +-224 + j*(256) +748 + j*(-341) +402 + j*(-316) +264 + j*(-693) +18 + j*(115) +127 + j*(-64) +-18 + j*(-102) +-95 + j*(-594) +385 + j*(72) +73 + j*(11) +-237 + j*(58) +-177 + j*(-98) +117 + j*(-21) +-536 + j*(173) +231 + j*(89) +-290 + j*(-238) +176 + j*(-135) +-293 + j*(50) +112 + j*(33) +73 + j*(-214) +89 + j*(-269) +62 + j*(6) +-204 + j*(9) +49 + j*(17) +21 + j*(91) +-170 + j*(49) +-112 + j*(-310) +-247 + j*(168) +-28 + j*(221) +98 + j*(-145) +234 + j*(33) +-22 + j*(-23) +-81 + j*(148) +69 + j*(117) +-144 + j*(-127) +-62 + j*(4) +76 + j*(149) +76 + j*(-45) +-6 + j*(61) +75 + j*(95) +-105 + j*(-210) +-378 + j*(-561) +-334 + j*(86) +309 + j*(-91) +309 + j*(-67) +190 + j*(-124) +91 + j*(23) +8 + j*(-58) +-235 + j*(-55) +57 + j*(-322) +-93 + j*(133) +-189 + j*(-179) +278 + j*(-37) +177 + j*(14) +-4 + j*(-166) +-71 + j*(-71) +310 + j*(-178) +107 + j*(-23) +153 + j*(55) +-146 + j*(350) +17 + j*(70) +-94 + j*(180) +-69 + j*(181) +-124 + j*(-424) +-75 + j*(117) +-124 + j*(-28) +-194 + j*(-111) +45 + j*(58) +12 + j*(-58) +197 + j*(-82) +212 + j*(32) +144 + j*(179) +-9 + j*(56) +-200 + j*(-328) +-64 + j*(70) +-48 + j*(332) +-71 + j*(-75) +-189 + j*(-15) +35 + j*(143) +-3 + j*(148) +-158 + j*(-24) +-69 + j*(165) +74 + j*(73) +149 + j*(-45) +-30 + j*(-211) +-195 + j*(158) +-147 + j*(272) +69 + j*(-50) +-73 + j*(54) +-309 + j*(-164) +-44 + j*(-103) +-401 + j*(132) +-271 + j*(104) +-269 + j*(-28) +-303 + j*(267) +-21 + j*(281) +-47 + j*(34) +-164 + j*(-165) +-110 + j*(241) +-37 + j*(62) +-40 + j*(-134) +2 + j*(19) +241 + j*(-375) +-301 + j*(-67) +204 + j*(-37) +303 + j*(-142) +-8 + j*(184) +60 + j*(-178) +-158 + j*(238) +223 + j*(-71) +63 + j*(-277) +144 + j*(-3) +-375 + j*(-45) +-186 + j*(6) +-36 + j*(-61) +46 + j*(-59) +-22 + j*(191) +-127 + j*(84) +-202 + j*(-13) +519 + j*(253) +-378 + j*(129) +16 + j*(176) +14 + j*(66) +-198 + j*(341) +-16 + j*(-180) +16 + j*(54) +42 + j*(49) +116 + j*(127) +60 + j*(-39) +-100 + j*(-65) +94 + j*(-66) +126 + j*(150) +396 + j*(-101) +-228 + j*(-126) +188 + j*(-42) +-88 + j*(-210) +-1 + j*(-69) +132 + j*(85) +-140 + j*(28) +-165 + j*(162) +-105 + j*(129) +-69 + j*(-122) +-130 + j*(-45) +-35 + j*(-15) +-217 + j*(63) +24 + j*(-269) +67 + j*(103) +-230 + j*(-104) +74 + j*(-202) +-48 + j*(-80) +-175 + j*(-81) +-118 + j*(-93) +-151 + j*(-15) +300 + j*(-88) +-107 + j*(-209) +113 + j*(52) +3 + j*(162) +-64 + j*(-366) +-180 + j*(-201) +291 + j*(65) +56 + j*(-347) +-21 + j*(28) +99 + j*(154) +119 + j*(5) +-18 + j*(-43) +101 + j*(-66) +279 + j*(-172) +210 + j*(-234) +119 + j*(-100) +4 + j*(-65) +-221 + j*(-33) +177 + j*(33) +289 + j*(240) +-134 + j*(261) +-474 + j*(50) +274 + j*(-269) +79 + j*(-84) +-164 + j*(63) +-103 + j*(151) +25 + j*(299) +87 + j*(67) +-302 + j*(93) +378 + j*(22) +230 + j*(-15) +70 + j*(-76) +74 + j*(-161) +-108 + j*(46) +52 + j*(-183) +-117 + j*(20) +351 + j*(-247) +169 + j*(115) +143 + j*(-125) +122 + j*(-360) +173 + j*(199) +337 + j*(-138) +-255 + j*(-175) +76 + j*(108) +256 + j*(-67) +184 + j*(-215) +103 + j*(303) +244 + j*(-360) +-130 + j*(-75) +98 + j*(-192) +-126 + j*(244) +249 + j*(-49) +331 + j*(-116) +-232 + j*(-227) +205 + j*(50) +-46 + j*(156) +274 + j*(153) +-392 + j*(-40) +-111 + j*(-1) +45 + j*(-269) +138 + j*(22) +238 + j*(172) +-24 + j*(-80) +160 + j*(-28) +-56 + j*(280) +-26 + j*(-56) +73 + j*(42) +360 + j*(29) +142 + j*(-410) +-126 + j*(107) +-134 + j*(288) +42 + j*(414) +-83 + j*(-246) +170 + j*(19) +1 + j*(-26) +-31 + j*(-13) +113 + j*(40) +82 + j*(145) +139 + j*(362) +-89 + j*(122) +-133 + j*(-552) +-269 + j*(-70) +-29 + j*(-21) +-161 + j*(-243) +-134 + j*(-10) +16 + j*(117) +13 + j*(-63) +-160 + j*(252) +-27 + j*(77) +-252 + j*(-119) +-65 + j*(167) +-71 + j*(259) +62 + j*(-130) +-223 + j*(117) +-58 + j*(-50) +132 + j*(-72) +21 + j*(157) +56 + j*(-150) +-171 + j*(-102) +-42 + j*(106) +-66 + j*(21) +-83 + j*(119) +158 + j*(252) +-252 + j*(-111) +-47 + j*(92) +46 + j*(-76) +-199 + j*(39) +-5 + j*(-91) +-65 + j*(-152) +308 + j*(-76) +36 + j*(276) +-144 + j*(-122) +382 + j*(330) +212 + j*(-305) +-23 + j*(-304) +-19 + j*(117) +150 + j*(-267) +-317 + j*(-182) +-100 + j*(33) +-23 + j*(92) +-258 + j*(-35) +70 + j*(-20) +-83 + j*(-13) +138 + j*(98) +301 + j*(-17) +448 + j*(289) +126 + j*(176) +284 + j*(12) +-176 + j*(-56) +320 + j*(144) +-188 + j*(-220) +-7 + j*(-40) +164 + j*(-198) +23 + j*(148) +260 + j*(184) +-187 + j*(-52) +-47 + j*(146) +-234 + j*(-148) +66 + j*(141) +243 + j*(-199) +-21 + j*(-17) +178 + j*(42) +204 + j*(93) +106 + j*(135) +14 + j*(88) +135 + j*(-242) +-35 + j*(-99) +-186 + j*(-61) +-167 + j*(-122) +-21 + j*(-138) +-41 + j*(-13) +-83 + j*(-98) +343 + j*(-217) +180 + j*(-9) +-476 + j*(-114) +-110 + j*(-219) +-272 + j*(211) +-47 + j*(-130) +-395 + j*(-134) +-200 + j*(54) +-107 + j*(-376) +47 + j*(298) +84 + j*(-206) +-355 + j*(115) +42 + j*(147) +211 + j*(119) +18 + j*(-42) +-173 + j*(77) +-40 + j*(259) +-168 + j*(193) +-167 + j*(-274) +-182 + j*(-132) +45 + j*(124) +351 + j*(-177) +170 + j*(-41) +44 + j*(90) +183 + j*(-95) +-361 + j*(60) +-24 + j*(-53) +122 + j*(-78) +-129 + j*(-28) +-160 + j*(92) +35 + j*(83) +-105 + j*(41) +-86 + j*(-101) +-228 + j*(120) +-27 + j*(-172) +36 + j*(221) +58 + j*(217) +91 + j*(-128) +-58 + j*(-247) +-78 + j*(270) +221 + j*(-192) +267 + j*(66) +115 + j*(48) +200 + j*(33) +155 + j*(-253) +172 + j*(93) +260 + j*(-219) +241 + j*(-64) +21 + j*(309) +37 + j*(-251) +238 + j*(-236) +-4 + j*(121) +38 + j*(-204) +-116 + j*(-143) +349 + j*(137) +60 + j*(23) +174 + j*(-243) +169 + j*(-221) +-192 + j*(-170) +124 + j*(-182) +43 + j*(-52) +209 + j*(223) +146 + j*(172) +-155 + j*(64) +28 + j*(129) +-118 + j*(232) +79 + j*(-8) +-294 + j*(40) +-414 + j*(-79) +45 + j*(234) +50 + j*(23) +-139 + j*(61) +40 + j*(41) +88 + j*(-35) +94 + j*(11) +-35 + j*(-146) +54 + j*(117) +-107 + j*(5) +-321 + j*(-30) +-190 + j*(-89) +227 + j*(90) +-72 + j*(-39) +-107 + j*(-324) +-117 + j*(71) +-33 + j*(99) +-82 + j*(-171) +75 + j*(-69) +33 + j*(151) +-106 + j*(-52) +35 + j*(-5) +-141 + j*(441) +48 + j*(62) +5 + j*(36) +2 + j*(136) +24 + j*(303) +-137 + j*(-233) +-249 + j*(241) +53 + j*(-79) +92 + j*(-265) +98 + j*(210) +-89 + j*(166) +-18 + j*(-91) +-62 + j*(-67) +74 + j*(-53) +91 + j*(-283) +330 + j*(77) +-16 + j*(-185) +293 + j*(47) +-54 + j*(66) +17 + j*(28) +-34 + j*(49) +190 + j*(-28) +-161 + j*(287) +-99 + j*(187) +5 + j*(34) +21 + j*(116) +-105 + j*(335) +-28 + j*(-32) +-74 + j*(-55) +148 + j*(69) +37 + j*(-168) +-233 + j*(42) +-66 + j*(-16) +115 + j*(-319) +81 + j*(-20) +120 + j*(180) +114 + j*(346) +61 + j*(-107) +143 + j*(-15) +70 + j*(-122) +-119 + j*(-272) +-39 + j*(129) +-163 + j*(103) +76 + j*(169) +-243 + j*(-21) +-145 + j*(-156) +-211 + j*(-214) +127 + j*(340) +79 + j*(-57) +-16 + j*(-45) +-24 + j*(87) +161 + j*(52) +-282 + j*(212) +-62 + j*(91) +-44 + j*(-33) +81 + j*(151) +69 + j*(68) +237 + j*(-74) +-132 + j*(260) +143 + j*(-132) +-11 + j*(-6) +-49 + j*(88) +-28 + j*(138) +-341 + j*(6) +231 + j*(35) +88 + j*(81) +-4 + j*(-156) +296 + j*(79) +-458 + j*(51) +35 + j*(-387) +-32 + j*(-234) +88 + j*(-45) +-173 + j*(-64) +-33 + j*(-172) +-204 + j*(-99) +-202 + j*(228) +105 + j*(-313) +-60 + j*(-256) +-104 + j*(-276) +222 + j*(-34) +-1 + j*(-357) +-98 + j*(-369) +-129 + j*(-107) +344 + j*(312) +-262 + j*(249) +108 + j*(-228) +364 + j*(-30) +-10 + j*(83) +-187 + j*(23) +330 + j*(249) +57 + j*(124) +317 + j*(-185) +-100 + j*(34) +225 + j*(82) +-36 + j*(-7) +-25 + j*(71) +-90 + j*(-27) +-132 + j*(155) +-106 + j*(-190) +-29 + j*(403) +-35 + j*(209) +66 + j*(-105) +137 + j*(-29) +84 + j*(238) +-1 + j*(-75) +-158 + j*(-138) +-120 + j*(349) +-66 + j*(-279) +127 + j*(-31) +-247 + j*(42) +186 + j*(-256) +-69 + j*(-107) +60 + j*(280) +237 + j*(190) +-161 + j*(47) +-104 + j*(173) +29 + j*(11) +59 + j*(177) +-43 + j*(-9) +-207 + j*(248) +115 + j*(-81) +-122 + j*(57) +20 + j*(-103) +-25 + j*(-41) +-13 + j*(66) +-169 + j*(23) +16 + j*(-243) +-83 + j*(-59) +121 + j*(-153) +-38 + j*(-99) +269 + j*(252) +303 + j*(-616) +-87 + j*(218) +-23 + j*(-52) +286 + j*(147) +-146 + j*(28) +185 + j*(88) +181 + j*(88) +58 + j*(300) +-59 + j*(-236) +-152 + j*(-32) +-132 + j*(-127) +-42 + j*(62) +200 + j*(-16) +178 + j*(87) +-10 + j*(-289) +85 + j*(-192) +373 + j*(92) +-641 + j*(26) +-253 + j*(-136) +-87 + j*(38) +7 + j*(-527) +79 + j*(-31) +10 + j*(76) +235 + j*(-160) +78 + j*(-93) +346 + j*(-32) +45 + j*(-271) +-30 + j*(269) +180 + j*(-45) +-39 + j*(125) +-256 + j*(206) +-24 + j*(-163) +98 + j*(317) +-194 + j*(-140) +-76 + j*(-12) +523 + j*(-112) +392 + j*(28) +58 + j*(-8) +-118 + j*(-94) +-129 + j*(17) +-217 + j*(18) +200 + j*(34) +-261 + j*(-148) +43 + j*(284) +-160 + j*(16) +332 + j*(67) +36 + j*(-7) +324 + j*(-185) +-134 + j*(-88) +-43 + j*(-363) +161 + j*(-263) +-59 + j*(-300) +-127 + j*(164) +-178 + j*(123) +-146 + j*(44) +-39 + j*(-35) +-131 + j*(-76) +-23 + j*(-384) +-112 + j*(-11) +86 + j*(177) +127 + j*(107) +-75 + j*(-81) +198 + j*(50) +24 + j*(-1) +-17 + j*(78) +-223 + j*(-136) +257 + j*(152) +-81 + j*(81) +-128 + j*(255) +-16 + j*(201) +16 + j*(187) +-143 + j*(-303) +-144 + j*(-173) +95 + j*(-123) +-264 + j*(177) +449 + j*(-10) +65 + j*(21) +-348 + j*(129) +-72 + j*(-158) +-283 + j*(43) +59 + j*(-156) +113 + j*(20) +-1 + j*(115) +201 + j*(25) +-91 + j*(-21) +46 + j*(140) +-54 + j*(-143) +71 + j*(-136) +-296 + j*(-75) +-202 + j*(293) +-51 + j*(202) +-33 + j*(88) +231 + j*(-65) +165 + j*(23) +-1 + j*(165) +-47 + j*(51) +-4 + j*(-314) +-141 + j*(-169) +53 + j*(-211) +89 + j*(204) +-105 + j*(-218) +61 + j*(-53) +-143 + j*(-284) +-11 + j*(-369) +-54 + j*(-280) +189 + j*(250) +-209 + j*(-136) +-65 + j*(-126) +25 + j*(168) +-137 + j*(165) +41 + j*(-85) +76 + j*(231) +-229 + j*(-282) +45 + j*(122) +-92 + j*(66) +-80 + j*(-161) +57 + j*(-59) +-95 + j*(-53) +-37 + j*(-35) +-20 + j*(103) +-124 + j*(-59) +-75 + j*(21) +-260 + j*(-112) +132 + j*(-57) +183 + j*(6) +243 + j*(-146) +102 + j*(384) +-172 + j*(-175) +21 + j*(-363) +192 + j*(-266) +52 + j*(-297) +-293 + j*(155) +58 + j*(-263) +207 + j*(14) +62 + j*(-169) +-152 + j*(250) +46 + j*(-74) +95 + j*(-74) +-75 + j*(147) +29 + j*(8) +-140 + j*(-167) +206 + j*(-33) +249 + j*(168) +47 + j*(38) +72 + j*(-209) +52 + j*(32) +123 + j*(294) +316 + j*(-170) +-91 + j*(-158) +-132 + j*(-92) +124 + j*(127) +215 + j*(110) +95 + j*(141) +-309 + j*(-30) +231 + j*(-153) +165 + j*(-54) +71 + j*(-115) +-250 + j*(-105) +-8 + j*(-131) +251 + j*(214) +-199 + j*(-33) +92 + j*(-49) +86 + j*(187) +-441 + j*(-16) +303 + j*(46) +163 + j*(-116) +6 + j*(45) +-53 + j*(209) +97 + j*(202) +371 + j*(-264) +-113 + j*(-148) +-70 + j*(-216) +-23 + j*(123) +-88 + j*(91) +-146 + j*(96) +45 + j*(-79) +-67 + j*(-41) +51 + j*(-138) +-203 + j*(-65) +-193 + j*(214) +91 + j*(187) +-246 + j*(-214) +-300 + j*(153) +21 + j*(-79) +-18 + j*(-130) +-165 + j*(256) +88 + j*(182) +-160 + j*(105) +120 + j*(-272) +440 + j*(327) +98 + j*(3) +-104 + j*(107) +215 + j*(84) +398 + j*(-12) +146 + j*(32) +343 + j*(6) +-522 + j*(284) +105 + j*(8) +112 + j*(41) +-263 + j*(84) +-36 + j*(-168) +45 + j*(90) +-111 + j*(-188) +1 + j*(83) +-159 + j*(40) +-345 + j*(59) +-17 + j*(-190) +-84 + j*(134) +201 + j*(-206) +46 + j*(-110) +136 + j*(-88) +144 + j*(92) +-11 + j*(-25) +-102 + j*(233) +-190 + j*(285) +50 + j*(123) +112 + j*(102) +72 + j*(387) +14 + j*(-137) +33 + j*(111) +-60 + j*(-201) +-86 + j*(118) +52 + j*(259) +52 + j*(28) +73 + j*(-199) +284 + j*(215) +296 + j*(-136) +-103 + j*(146) +1 + j*(49) +120 + j*(-55) +38 + j*(187) +-581 + j*(158) +163 + j*(-325) +-129 + j*(-29) +257 + j*(113) +135 + j*(250) +-246 + j*(-14) +-285 + j*(78) +-181 + j*(-91) +311 + j*(0) +75 + j*(68) +18 + j*(-100) +144 + j*(43) +324 + j*(95) +-107 + j*(69) +-133 + j*(-156) +-203 + j*(-366) +-245 + j*(-175) +72 + j*(39) +-6 + j*(-11) +-67 + j*(179) +-26 + j*(-18) +-271 + j*(375) +-201 + j*(-147) +-57 + j*(-52) +139 + j*(-216) +-93 + j*(54) +100 + j*(373) +-148 + j*(33) +-171 + j*(-137) +-43 + j*(98) +-4 + j*(-42) +-115 + j*(213) +22 + j*(-251) +-165 + j*(16) +-177 + j*(-170) +-275 + j*(184) +-153 + j*(-170) +-73 + j*(-168) +11 + j*(130) +48 + j*(121) +173 + j*(125) +1 + j*(37) +66 + j*(321) +365 + j*(-200) +240 + j*(107) +231 + j*(-123) +-115 + j*(41) +-211 + j*(16) +-192 + j*(-125) +-108 + j*(50) +-66 + j*(-6) +-8 + j*(-118) +81 + j*(68) +372 + j*(-31) +-280 + j*(66) +105 + j*(16) +-97 + j*(-85) +-175 + j*(-276) +-52 + j*(204) +-220 + j*(64) +-22 + j*(-260) +-138 + j*(88) +-86 + j*(-236) +0 + j*(13) +40 + j*(-56) +-161 + j*(-40) +-106 + j*(-194) +-265 + j*(-81) +86 + j*(83) +-48 + j*(7) +127 + j*(-83) +218 + j*(-228) +155 + j*(88) +-195 + j*(288) +-69 + j*(-33) +-122 + j*(36) +-195 + j*(-75) +-36 + j*(127) +-54 + j*(119) +95 + j*(-52) +18 + j*(-72) +-44 + j*(-35) +39 + j*(105) +109 + j*(-2) +-190 + j*(79) +171 + j*(301) +67 + j*(-164) +93 + j*(-250) +383 + j*(30) +-233 + j*(148) +64 + j*(25) +-22 + j*(-25) +73 + j*(160) +457 + j*(196) +-23 + j*(6) +154 + j*(35) +-78 + j*(-95) +18 + j*(-118) +-17 + j*(100) +125 + j*(-159) +-107 + j*(47) +18 + j*(342) +-83 + j*(-453) +411 + j*(157) +83 + j*(-192) +143 + j*(-182) +-266 + j*(-77) +124 + j*(-392) +94 + j*(-190) +-200 + j*(261) +-146 + j*(-107) +80 + j*(-24) +-113 + j*(57) +-4 + j*(87) +78 + j*(32) +-257 + j*(-225) +252 + j*(98) +121 + j*(222) +20 + j*(15) +-233 + j*(-42) +-76 + j*(-408) +-141 + j*(40) +146 + j*(-282) +52 + j*(-11) +88 + j*(-210) +93 + j*(157) +112 + j*(270) +45 + j*(34) +3 + j*(-139) +20 + j*(197) +86 + j*(-23) +-154 + j*(-133) +98 + j*(-40) +-356 + j*(-88) +-159 + j*(-144) +235 + j*(289) +7 + j*(-182) +-52 + j*(-290) +589 + j*(-199) +-26 + j*(-64) +14 + j*(-146) +-436 + j*(45) +-8 + j*(339) +-64 + j*(-50) +-325 + j*(53) +83 + j*(223) +-16 + j*(-254) +192 + j*(-69) +251 + j*(-84) +228 + j*(8) +114 + j*(163) +-55 + j*(84) +10 + j*(-61) +193 + j*(84) +-214 + j*(-66) +-49 + j*(69) +-231 + j*(-11) +-22 + j*(-81) +-199 + j*(90) +264 + j*(138) +-331 + j*(71) +132 + j*(122) +147 + j*(7) +-77 + j*(-69) +86 + j*(-34) +-98 + j*(143) +-408 + j*(153) +243 + j*(32) +-192 + j*(45) +210 + j*(-25) +2 + j*(16) +-516 + j*(-149) +80 + j*(-56) +-145 + j*(54) +108 + j*(8) +-151 + j*(59) +-255 + j*(200) +28 + j*(30) +-170 + j*(-214) +-14 + j*(14) +221 + j*(3) +-190 + j*(-98) +-173 + j*(-229) +-131 + j*(-164) +313 + j*(-194) +97 + j*(112) +222 + j*(-268) +13 + j*(-59) +117 + j*(-142) +172 + j*(-177) +67 + j*(221) +-87 + j*(-32) +-144 + j*(93) +-135 + j*(-286) +385 + j*(-101) +-86 + j*(202) +-149 + j*(127) +-56 + j*(195) +-2 + j*(-35) +-5 + j*(-182) +195 + j*(170) +202 + j*(-215) +-213 + j*(-109) +101 + j*(-176) +255 + j*(-240) +-86 + j*(214) +-165 + j*(-35) +242 + j*(-112) +-18 + j*(-156) +81 + j*(-96) +-4 + j*(120) +-97 + j*(8) +217 + j*(195) +256 + j*(-281) +71 + j*(-104) +-125 + j*(153) +-89 + j*(86) +-69 + j*(210) +-45 + j*(4) +445 + j*(-89) +-50 + j*(-165) +-212 + j*(58) +405 + j*(202) +153 + j*(383) +-74 + j*(199) +317 + j*(-228) +-6 + j*(-18) +24 + j*(-126) +234 + j*(141) +-113 + j*(-23) +128 + j*(80) +202 + j*(194) +52 + j*(110) +-8 + j*(-151) +-58 + j*(132) +-171 + j*(115) +54 + j*(49) +-151 + j*(-103) +132 + j*(-243) +276 + j*(-27) +-361 + j*(-115) +-150 + j*(84) +-148 + j*(-176) +-145 + j*(82) +219 + j*(-160) +184 + j*(-7) +33 + j*(-124) +-95 + j*(114) +190 + j*(-218) +141 + j*(-73) +-187 + j*(190) +-1 + j*(9) +149 + j*(6) +254 + j*(-40) +-35 + j*(-286) +151 + j*(303) +-139 + j*(-175) +-104 + j*(49) +-400 + j*(-63) +92 + j*(-197) +-318 + j*(10) +25 + j*(-160) +-183 + j*(-194) +74 + j*(45) +33 + j*(-66) +124 + j*(-181) +-93 + j*(74) +206 + j*(-126) +257 + j*(-97) +18 + j*(9) +-128 + j*(64) +119 + j*(125) +-140 + j*(11) +-257 + j*(7) +-356 + j*(-113) +-295 + j*(287) +-144 + j*(104) +174 + j*(59) +-13 + j*(-155) +-43 + j*(92) +-238 + j*(-49) +-195 + j*(238) +112 + j*(-262) +-103 + j*(37) +45 + j*(-238) +-217 + j*(-295) +-153 + j*(156) +281 + j*(88) +-107 + j*(-43) +293 + j*(47) +-215 + j*(80) +-48 + j*(-238) +-395 + j*(122) +-348 + j*(-60) +11 + j*(40) +216 + j*(56) +-78 + j*(163) +8 + j*(-216) +105 + j*(91) +106 + j*(261) +-95 + j*(-192) +112 + j*(67) +312 + j*(-171) +168 + j*(-223) +-7 + j*(171) +-27 + j*(-176) +166 + j*(206) +40 + j*(89) +-80 + j*(-222) +-120 + j*(-236) +-173 + j*(-10) +-48 + j*(-100) +-228 + j*(-205) +303 + j*(134) +222 + j*(18) +-118 + j*(203) +-35 + j*(40) +29 + j*(-70) +226 + j*(-18) +164 + j*(59) +173 + j*(-224) +45 + j*(-255) +149 + j*(-78) +-10 + j*(-176) +-168 + j*(216) +60 + j*(46) +45 + j*(-16) +-254 + j*(-35) +116 + j*(28) +87 + j*(170) +91 + j*(-139) +204 + j*(-61) +-131 + j*(-184) +158 + j*(184) +-118 + j*(-86) +475 + j*(158) +255 + j*(-69) +54 + j*(-293) +-11 + j*(91) +-74 + j*(-40) +-122 + j*(245) +-371 + j*(-127) +-13 + j*(-100) +-156 + j*(1) +71 + j*(-356) +-117 + j*(1) +-56 + j*(319) +-126 + j*(-319) +-159 + j*(-66) +-115 + j*(188) +-153 + j*(257) +187 + j*(-379) +64 + j*(-60) +-56 + j*(6) +-279 + j*(-78) +437 + j*(-305) +164 + j*(161) +371 + j*(-175) +76 + j*(143) +240 + j*(-185) +14 + j*(187) +381 + j*(134) +65 + j*(-382) +274 + j*(-39) +91 + j*(78) +-284 + j*(24) +115 + j*(82) +-64 + j*(194) +33 + j*(182) +-130 + j*(-107) +-77 + j*(-45) +-229 + j*(-103) +199 + j*(594) +117 + j*(59) +143 + j*(-350) +123 + j*(31) +-86 + j*(-33) +-301 + j*(258) +18 + j*(322) +166 + j*(-163) +157 + j*(-4) +201 + j*(228) +-115 + j*(-309) +-33 + j*(-49) +-257 + j*(1) +75 + j*(-115) +45 + j*(367) +-37 + j*(-36) +-77 + j*(-276) +163 + j*(138) +-42 + j*(103) +13 + j*(-232) +56 + j*(110) +-30 + j*(-88) +-47 + j*(-7) +42 + j*(235) +151 + j*(-332) +257 + j*(-101) +152 + j*(216) +-316 + j*(212) +-92 + j*(115) +127 + j*(-179) +-67 + j*(47) +-197 + j*(26) +441 + j*(-165) +-227 + j*(124) +49 + j*(45) +-81 + j*(368) +-62 + j*(-108) +251 + j*(-332) +-36 + j*(-64) +147 + j*(-291) +-129 + j*(-181) +226 + j*(-194) +-74 + j*(-160) +-250 + j*(-107) +-322 + j*(72) +-95 + j*(15) +-130 + j*(14) +-42 + j*(-41) +23 + j*(-275) +-61 + j*(-23) +-400 + j*(257) +73 + j*(-130) +-119 + j*(-42) +-28 + j*(-104) +27 + j*(-366) +-64 + j*(209) +84 + j*(206) +-176 + j*(-442) +103 + j*(-235) +-76 + j*(-279) +99 + j*(52) +-264 + j*(-8) +-288 + j*(71) +14 + j*(24) +-402 + j*(25) +-299 + j*(156) +-146 + j*(135) +-21 + j*(187) +-255 + j*(-52) +-214 + j*(239) +106 + j*(-19) +63 + j*(-71) +25 + j*(-88) +220 + j*(426) +-358 + j*(91) +-252 + j*(-223) +-54 + j*(-177) +122 + j*(-41) +105 + j*(-161) +-65 + j*(84) +252 + j*(10) +-168 + j*(-198) +183 + j*(-35) +11 + j*(172) +-226 + j*(-230) +-184 + j*(-214) +-151 + j*(-233) +-92 + j*(-59) +31 + j*(100) +16 + j*(331) +125 + j*(81) +-301 + j*(-35) +69 + j*(-139) +-60 + j*(107) +-64 + j*(-63) +-43 + j*(-99) +-130 + j*(-54) +134 + j*(381) +-155 + j*(17) +-499 + j*(223) +-148 + j*(-124) +-95 + j*(226) +247 + j*(-55) +-181 + j*(-183) +-94 + j*(-284) +-287 + j*(-103) +-136 + j*(59) +59 + j*(67) +259 + j*(-352) +-150 + j*(-10) +-43 + j*(119) +69 + j*(30) +-106 + j*(351) +-38 + j*(-85) +366 + j*(249) +71 + j*(197) +215 + j*(-37) +-136 + j*(196) +-231 + j*(75) +97 + j*(-383) +103 + j*(95) +99 + j*(-164) +172 + j*(-106) +93 + j*(177) +42 + j*(-337) +-23 + j*(-7) +199 + j*(262) +-141 + j*(70) +60 + j*(-132) +-5 + j*(-18) +-40 + j*(117) +-18 + j*(127) +-224 + j*(245) +-200 + j*(-121) +-22 + j*(74) +-23 + j*(-212) +129 + j*(119) +42 + j*(286) +18 + j*(261) +-17 + j*(-211) +-72 + j*(84) +327 + j*(-28) +2 + j*(-11) +100 + j*(-301) +-37 + j*(9) +-66 + j*(-165) +16 + j*(-57) +-59 + j*(-22) +49 + j*(158) +338 + j*(144) +11 + j*(87) +-276 + j*(-42) +-20 + j*(226) +-117 + j*(0) +-199 + j*(-294) +-274 + j*(18) +-21 + j*(-148) +-173 + j*(216) +103 + j*(101) +162 + j*(18) +301 + j*(157) +-43 + j*(486) +174 + j*(-354) +-61 + j*(-138) +-62 + j*(-337) +24 + j*(161) +106 + j*(-105) +69 + j*(-204) +247 + j*(166) +-199 + j*(235) +11 + j*(107) +273 + j*(180) +157 + j*(-83) +174 + j*(21) +-88 + j*(192) +-171 + j*(-54) +393 + j*(294) +-23 + j*(-21) +-6 + j*(4) +-73 + j*(-25) +-319 + j*(-282) +-407 + j*(-130) +86 + j*(76) +293 + j*(52) +392 + j*(-10) +-297 + j*(-74) +89 + j*(-230) +-149 + j*(286) +-185 + j*(43) +-91 + j*(-103) +-277 + j*(-305) +-189 + j*(-58) +-190 + j*(-8) +-54 + j*(-74) +99 + j*(26) +-83 + j*(-206) +223 + j*(82) +-60 + j*(-88) +342 + j*(-260) +-350 + j*(-141) +154 + j*(-4) +48 + j*(-197) +153 + j*(211) +223 + j*(118) +52 + j*(-206) +158 + j*(-131) +-368 + j*(49) +-180 + j*(-28) +19 + j*(-435) +112 + j*(83) +-167 + j*(-94) +161 + j*(284) +317 + j*(196) +-108 + j*(-390) +-236 + j*(105) +-287 + j*(-153) +-87 + j*(-1) +-42 + j*(-37) +-77 + j*(-438) +-9 + j*(59) +48 + j*(-317) +395 + j*(133) +-83 + j*(86) +-60 + j*(16) +-31 + j*(-90) +144 + j*(-65) +-80 + j*(-160) +42 + j*(-12) +-260 + j*(247) +-56 + j*(185) +16 + j*(70) +-87 + j*(-107) +74 + j*(187) +-37 + j*(210) +303 + j*(52) +-42 + j*(323) +-40 + j*(-14) +54 + j*(119) +-30 + j*(100) +-129 + j*(-9) +223 + j*(11) +-103 + j*(34) +225 + j*(316) +-11 + j*(-108) +-141 + j*(204) +86 + j*(-39) +50 + j*(361) +-120 + j*(-119) +233 + j*(-174) +-277 + j*(-74) +-126 + j*(169) +58 + j*(-33) +-177 + j*(-51) +-153 + j*(-271) +151 + j*(119) +215 + j*(18) +-69 + j*(-188) +305 + j*(130) +-144 + j*(7) +-210 + j*(50) +190 + j*(148) +78 + j*(-69) +37 + j*(96) +42 + j*(209) +243 + j*(57) +103 + j*(-252) +-69 + j*(101) +-43 + j*(-157) +-168 + j*(-206) +27 + j*(-35) +100 + j*(-18) +6 + j*(33) +-52 + j*(5) +13 + j*(-250) +17 + j*(268) +204 + j*(-153) +210 + j*(-54) +-117 + j*(85) +-30 + j*(22) +-255 + j*(19) +-3 + j*(-106) +-87 + j*(-130) +50 + j*(-207) +340 + j*(143) +-350 + j*(-105) +190 + j*(62) +32 + j*(-141) +21 + j*(289) +-322 + j*(394) +29 + j*(-30) +132 + j*(-94) +114 + j*(-328) +-195 + j*(372) +-228 + j*(-20) +54 + j*(66) +-39 + j*(-59) +186 + j*(10) +153 + j*(258) +12 + j*(45) +4 + j*(-96) +-33 + j*(54) +-210 + j*(116) +-369 + j*(72) +28 + j*(180) +93 + j*(114) +-98 + j*(208) +211 + j*(119) +-148 + j*(-176) +-391 + j*(-227) +-63 + j*(122) +59 + j*(30) +41 + j*(269) +-97 + j*(200) +-49 + j*(-78) +-208 + j*(261) +25 + j*(-16) +-253 + j*(8) +146 + j*(68) +71 + j*(28) +221 + j*(-176) +-281 + j*(-49) +278 + j*(134) +83 + j*(168) +-66 + j*(543) +260 + j*(-264) +-245 + j*(-107) +-205 + j*(669) +-275 + j*(207) +-265 + j*(294) +88 + j*(137) +-162 + j*(-23) +-410 + j*(-24) +-228 + j*(-286) +486 + j*(-153) +-10 + j*(112) +113 + j*(-173) +317 + j*(-373) +-211 + j*(-313) +-163 + j*(-56) +362 + j*(-64) +83 + j*(397) +-247 + j*(312) +385 + j*(-145) +-151 + j*(74) +361 + j*(161) +-247 + j*(451) +-320 + j*(-274) +314 + j*(337) +155 + j*(233) +114 + j*(-267) +115 + j*(201) +377 + j*(-134) +194 + j*(218) +36 + j*(202) +-598 + j*(232) +122 + j*(-301) +411 + j*(256) +260 + j*(-323) +12 + j*(466) +-78 + j*(-218) +267 + j*(-318) +-243 + j*(-390) +573 + j*(441) +-57 + j*(-368) +-492 + j*(141) +-271 + j*(-62) +310 + j*(246) +226 + j*(-334) +-395 + j*(-523) +-323 + j*(166) +-339 + j*(-184) +283 + j*(90) +-737 + j*(-246) +196 + j*(335) +354 + j*(-433) +-33 + j*(13) +-402 + j*(-357) +322 + j*(209) +69 + j*(109) +453 + j*(-119) +245 + j*(34) +296 + j*(-48) +283 + j*(-426) +228 + j*(-288) +86 + j*(185) +453 + j*(-25) +-137 + j*(255) +77 + j*(-154) +-166 + j*(-66) +-342 + j*(179) +-454 + j*(-412) +387 + j*(-252) +292 + j*(122) +334 + j*(0) +-254 + j*(129) +-116 + j*(-10) +-292 + j*(-6) +268 + j*(-445) +-209 + j*(-537) +424 + j*(-64) +279 + j*(-367) +-361 + j*(-91) +-243 + j*(-316) +250 + j*(-355) +238 + j*(-216) +-464 + j*(386) +-296 + j*(150) +-192 + j*(-322) +151 + j*(-255) +341 + j*(361) +-467 + j*(269) +-282 + j*(-421) +180 + j*(-375) +-428 + j*(-371) +211 + j*(272) +65 + j*(-426) +-378 + j*(-335) +158 + j*(-18) +-214 + j*(195) +-12 + j*(-337) +-115 + j*(116) +433 + j*(-126) +228 + j*(-88) +-329 + j*(54) +425 + j*(-19) +-443 + j*(496) +358 + j*(-255) +-401 + j*(272) +285 + j*(172) +-81 + j*(405) +10 + j*(-358) +-370 + j*(102) +-477 + j*(30) +8 + j*(519) +-323 + j*(447) +-527 + j*(-167) +-218 + j*(36) +-116 + j*(-40) +501 + j*(-393) +180 + j*(-192) +-93 + j*(-530) +-57 + j*(-521) +21 + j*(-306) +252 + j*(228) +-330 + j*(-42) +35 + j*(-476) +-482 + j*(-399) +221 + j*(348) +-257 + j*(-202) +-110 + j*(-249) +313 + j*(-1) +-303 + j*(51) +-374 + j*(683) +339 + j*(279) +428 + j*(363) +18 + j*(-341) +355 + j*(508) +-128 + j*(265) +-309 + j*(-98) +-28 + j*(-35) +-439 + j*(231) +499 + j*(458) +-546 + j*(-80) +-31 + j*(395) +-47 + j*(-1) +135 + j*(-437) +299 + j*(126) +161 + j*(424) +275 + j*(-41) +-172 + j*(77) +-433 + j*(57) +477 + j*(-182) +334 + j*(349) +233 + j*(-412) +414 + j*(93) +93 + j*(103) +-146 + j*(-267) +-232 + j*(-346) +324 + j*(204) +-500 + j*(-10) +276 + j*(-453) +23 + j*(-245) +343 + j*(-359) +419 + j*(-468) +517 + j*(83) +332 + j*(583) +355 + j*(-421) +-238 + j*(-115) +729 + j*(-23) +218 + j*(148) +305 + j*(-159) +-265 + j*(102) +-346 + j*(109) +343 + j*(140) +504 + j*(-364) +-424 + j*(-228) +-202 + j*(64) +-35 + j*(265) +-456 + j*(599) +-388 + j*(-223) +83 + j*(-33) +375 + j*(-334) +-115 + j*(53) +383 + j*(387) +110 + j*(-587) +518 + j*(49) +318 + j*(418) +-219 + j*(-455) +-37 + j*(-326) +-233 + j*(182) +-334 + j*(406) +559 + j*(327) +-398 + j*(265) +-517 + j*(-204) +436 + j*(204) +260 + j*(644) +407 + j*(-289) +355 + j*(-119) +377 + j*(-563) +171 + j*(-69) +313 + j*(-574) +228 + j*(-445) +-118 + j*(-154) +-161 + j*(424) +124 + j*(-366) +335 + j*(-135) +-99 + j*(-424) +437 + j*(506) +490 + j*(747) +272 + j*(79) +-28 + j*(-279) +214 + j*(333) +-190 + j*(251) +220 + j*(-320) +18 + j*(298) +292 + j*(136) +-164 + j*(-386) +-437 + j*(373) +-122 + j*(-311) +59 + j*(-512) +115 + j*(-47) +371 + j*(105) +432 + j*(-331) +-418 + j*(247) +-438 + j*(356) +231 + j*(-129) +-334 + j*(178) +-309 + j*(-184) +269 + j*(460) +-460 + j*(118) +537 + j*(36) +550 + j*(224) +275 + j*(-334) +-344 + j*(245) +-120 + j*(-237) +122 + j*(-154) +68 + j*(-146) +68 + j*(-363) +-211 + j*(-162) +-258 + j*(-269) +560 + j*(-274) +145 + j*(-81) +562 + j*(231) +-363 + j*(-486) +429 + j*(-189) +317 + j*(286) +298 + j*(-331) +110 + j*(-121) +4 + j*(-651) +4 + j*(648) +318 + j*(506) +478 + j*(79) +103 + j*(40) +-136 + j*(-419) +412 + j*(-26) +-493 + j*(290) +-364 + j*(513) +158 + j*(35) +-472 + j*(-109) +-293 + j*(-365) +372 + j*(437) +-171 + j*(-282) +-439 + j*(202) +-136 + j*(202) +-196 + j*(427) +-387 + j*(283) +-329 + j*(118) +-320 + j*(-251) +-141 + j*(382) +290 + j*(-96) +262 + j*(-165) +-173 + j*(-39) +126 + j*(-477) +-247 + j*(299) +-247 + j*(382) +-315 + j*(356) +141 + j*(-220) +291 + j*(-223) +281 + j*(448) +287 + j*(90) +457 + j*(-190) +-184 + j*(438) +302 + j*(-472) +-176 + j*(286) +-207 + j*(-400) +439 + j*(-117) +74 + j*(125) +292 + j*(-349) +299 + j*(-208) +-30 + j*(-268) +-59 + j*(-288) +-226 + j*(-315) +-499 + j*(-209) +-340 + j*(423) +-389 + j*(-105) +-170 + j*(-335) +-76 + j*(225) +-312 + j*(88) +379 + j*(303) +284 + j*(-255) +-291 + j*(296) +601 + j*(220) +207 + j*(105) +148 + j*(313) +281 + j*(420) +-402 + j*(382) +-141 + j*(148) +-74 + j*(318) +-618 + j*(-348) +-385 + j*(-310) +448 + j*(233) +471 + j*(-279) +9 + j*(125) +-191 + j*(-74) +559 + j*(529) +-421 + j*(-25) +615 + j*(-308) +-161 + j*(370) +493 + j*(-135) +-39 + j*(-309) +-270 + j*(-256) +527 + j*(8) +-204 + j*(474) +88 + j*(514) +-276 + j*(-429) +238 + j*(277) +-216 + j*(165) +-202 + j*(-349) +-73 + j*(-279) +267 + j*(279) +-186 + j*(-200) +-404 + j*(639) +233 + j*(-351) +304 + j*(-202) +-91 + j*(-161) +383 + j*(-247) +-437 + j*(-287) +-275 + j*(-8) +453 + j*(-290) +305 + j*(-100) +323 + j*(-377) +22 + j*(112) +-371 + j*(-85) +-23 + j*(-8) +276 + j*(173) +226 + j*(120) +-491 + j*(337) +-245 + j*(497) +368 + j*(-130) +77 + j*(190) +378 + j*(34) +-298 + j*(187) +146 + j*(322) +-494 + j*(-216) +-312 + j*(80) +361 + j*(195) +213 + j*(-537) +-49 + j*(-452) +-282 + j*(-228) +-171 + j*(382) +74 + j*(-387) +-382 + j*(378) +513 + j*(-339) +67 + j*(-65) +301 + j*(-3) +438 + j*(-215) +-516 + j*(100) +55 + j*(-149) +-47 + j*(-359) +92 + j*(-285) +-182 + j*(193) +152 + j*(-314) +-270 + j*(255) +-334 + j*(-128) +299 + j*(-450) +-197 + j*(311) +-231 + j*(-173) +458 + j*(-262) +-206 + j*(477) +-338 + j*(202) +-37 + j*(454) +-477 + j*(-1) +-157 + j*(-477) +-339 + j*(-322) +-278 + j*(607) +257 + j*(-292) +-199 + j*(77) +132 + j*(182) +-314 + j*(-312) +-439 + j*(366) +-319 + j*(-279) +358 + j*(74) +-198 + j*(-170) +557 + j*(-256) +-207 + j*(-424) +-472 + j*(-307) +158 + j*(228) +-80 + j*(-64) +395 + j*(383) +-168 + j*(-6) +-40 + j*(-215) +78 + j*(-342) +-28 + j*(97) +357 + j*(73) +-584 + j*(-170) +-510 + j*(296) +-155 + j*(42) +187 + j*(13) +510 + j*(334) +113 + j*(-436) +-448 + j*(265) +-327 + j*(184) +128 + j*(141) +211 + j*(-30) +139 + j*(197) +-36 + j*(65) +546 + j*(220) +473 + j*(-143) +-139 + j*(175) +-473 + j*(243) +247 + j*(-214) +18 + j*(262) +28 + j*(-354) +140 + j*(-25) +-325 + j*(-457) +-284 + j*(-313) +229 + j*(-353) +-337 + j*(-385) +448 + j*(501) +-292 + j*(-126) +484 + j*(-617) +-291 + j*(-453) +-297 + j*(-247) +347 + j*(-323) +204 + j*(-272) +-252 + j*(-155) +-148 + j*(-477) +166 + j*(378) +142 + j*(0) +174 + j*(438) +653 + j*(-51) +259 + j*(458) +-282 + j*(237) +13 + j*(350) +-537 + j*(365) +215 + j*(315) +467 + j*(129) +244 + j*(-213) +285 + j*(1) +182 + j*(-56) +135 + j*(-305) +208 + j*(-312) +612 + j*(-123) +303 + j*(473) +102 + j*(-471) +-190 + j*(-270) +3 + j*(-470) +192 + j*(483) +94 + j*(-435) +-69 + j*(333) +527 + j*(9) +-203 + j*(201) +159 + j*(1) +-428 + j*(333) +54 + j*(-194) +391 + j*(303) +-171 + j*(-295) +315 + j*(-127) +260 + j*(197) +-146 + j*(-67) +297 + j*(446) +-474 + j*(285) +-95 + j*(165) +286 + j*(-295) +-482 + j*(-386) +37 + j*(-359) +-295 + j*(-119) +187 + j*(-374) +359 + j*(-55) +-294 + j*(-349) +301 + j*(301) +148 + j*(-211) +-259 + j*(-183) +-325 + j*(28) +-144 + j*(39) +-403 + j*(-242) +-465 + j*(49) +176 + j*(-325) +262 + j*(-41) +547 + j*(260) +-316 + j*(65) +425 + j*(-1) +310 + j*(-226) +-163 + j*(-569) +-361 + j*(268) +385 + j*(-217) +-474 + j*(-19) +-143 + j*(238) +-280 + j*(-138) +170 + j*(233) +124 + j*(-78) +593 + j*(348) +-291 + j*(-136) +98 + j*(542) +-211 + j*(-704) +431 + j*(-303) +79 + j*(-228) +134 + j*(-62) +-247 + j*(-397) +567 + j*(52) +521 + j*(-226) +368 + j*(-127) +-654 + j*(28) +-457 + j*(595) +-162 + j*(-465) +-161 + j*(-552) +202 + j*(-199) +-409 + j*(-440) +623 + j*(137) +305 + j*(6) +-115 + j*(-160) +206 + j*(-120) +182 + j*(285) +-478 + j*(-85) +-197 + j*(-403) +119 + j*(-354) +-308 + j*(349) +482 + j*(-368) +-296 + j*(96) +-27 + j*(141) +665 + j*(389) +458 + j*(179) +-8 + j*(-435) +-648 + j*(-80) +-403 + j*(192) +-212 + j*(161) +319 + j*(-486) +222 + j*(-178) +308 + j*(338) +-88 + j*(-101) +406 + j*(-424) +-95 + j*(-590) +-412 + j*(-542) +-64 + j*(-274) +-245 + j*(320) +144 + j*(192) +144 + j*(300) +225 + j*(-187) +-200 + j*(352) +-576 + j*(-369) +86 + j*(-57) +243 + j*(-177) +-106 + j*(-433) +275 + j*(361) +85 + j*(164) +-300 + j*(338) +-659 + j*(-456) +-293 + j*(-298) +-453 + j*(209) +-493 + j*(165) +-635 + j*(-501) +-353 + j*(357) +-294 + j*(184) +47 + j*(-356) +251 + j*(37) +490 + j*(250) +-204 + j*(-330) +344 + j*(291) +110 + j*(165) +97 + j*(18) +540 + j*(-192) +-569 + j*(-88) +-135 + j*(95) +-326 + j*(-617) +115 + j*(-14) +263 + j*(-353) +436 + j*(-301) +83 + j*(265) +-94 + j*(269) +-194 + j*(-245) +-6 + j*(-158) +-156 + j*(-540) +476 + j*(313) +308 + j*(-288) +-74 + j*(-361) +-286 + j*(-144) +332 + j*(-60) +327 + j*(147) +-452 + j*(477) +95 + j*(116) +477 + j*(413) +343 + j*(427) +548 + j*(351) +-358 + j*(108) +-147 + j*(-146) +-383 + j*(-209) +-431 + j*(-528) +555 + j*(473) +233 + j*(-53) +-44 + j*(-122) +339 + j*(626) +-10 + j*(-454) +-10 + j*(484) +-222 + j*(225) +-47 + j*(90) +170 + j*(162) +61 + j*(-95) +25 + j*(-11) +74 + j*(269) +-2 + j*(243) +3 + j*(30) +-267 + j*(-80) +59 + j*(374) +-35 + j*(-372) +165 + j*(221) +-102 + j*(-175) +-34 + j*(-115) +-75 + j*(-95) +126 + j*(88) +-245 + j*(194) +-351 + j*(72) +33 + j*(47) +-87 + j*(-266) +-95 + j*(165) +-56 + j*(42) +179 + j*(123) +-30 + j*(170) +5 + j*(-428) +279 + j*(346) +-349 + j*(-42) +-9 + j*(-86) +-62 + j*(293) +344 + j*(-372) +148 + j*(-54) +-160 + j*(-57) +-57 + j*(109) +-88 + j*(128) +-73 + j*(156) +-130 + j*(60) +-206 + j*(472) +-129 + j*(4) +231 + j*(-168) +-84 + j*(-132) +-189 + j*(310) +-64 + j*(-107) +274 + j*(-236) +-53 + j*(-1) +8 + j*(-197) +327 + j*(-13) +85 + j*(321) +41 + j*(158) +134 + j*(267) +53 + j*(129) +42 + j*(-11) +144 + j*(-164) +216 + j*(29) +-70 + j*(-49) +-153 + j*(-78) +303 + j*(91) +248 + j*(-240) +60 + j*(191) +51 + j*(51) +38 + j*(30) +-110 + j*(72) +395 + j*(-380) +-98 + j*(-201) +-21 + j*(-40) +26 + j*(122) +6 + j*(268) +-85 + j*(78) +105 + j*(49) +152 + j*(-69) +277 + j*(134) +59 + j*(-185) +-112 + j*(-143) +-12 + j*(275) +-103 + j*(-44) +-190 + j*(-227) +-245 + j*(105) +-21 + j*(-148) +-67 + j*(45) +154 + j*(128) +-110 + j*(-153) +-33 + j*(-143) +-88 + j*(-81) +163 + j*(-1) +42 + j*(-227) +93 + j*(1) +202 + j*(-52) +305 + j*(58) +-170 + j*(-458) +-181 + j*(418) +291 + j*(402) +-198 + j*(166) +196 + j*(-259) +-263 + j*(186) +77 + j*(137) +59 + j*(-204) +379 + j*(-7) +-19 + j*(64) +235 + j*(35) +81 + j*(-90) +24 + j*(79) +54 + j*(-92) +-119 + j*(-243) +99 + j*(187) +-18 + j*(109) +139 + j*(-76) +-267 + j*(-52) +-111 + j*(92) +6 + j*(-2) +57 + j*(158) +158 + j*(-405) +-224 + j*(242) +271 + j*(-42) +131 + j*(-201) +151 + j*(192) +-50 + j*(42) +333 + j*(-21) +-34 + j*(-134) +-121 + j*(110) +-480 + j*(-63) +40 + j*(-447) +-150 + j*(147) +90 + j*(-212) +-186 + j*(-5) +174 + j*(-49) +-319 + j*(91) +145 + j*(-51) +-251 + j*(-44) +57 + j*(13) +-9 + j*(-190) +-72 + j*(107) +54 + j*(114) +156 + j*(20) +-134 + j*(98) +-89 + j*(-16) +-120 + j*(-82) +-135 + j*(-173) +307 + j*(-235) +-24 + j*(-242) +132 + j*(-212) +-139 + j*(-104) +349 + j*(-211) +23 + j*(146) +65 + j*(25) +-104 + j*(140) +-110 + j*(115) +-97 + j*(-174) +162 + j*(35) +86 + j*(-174) +222 + j*(48) +136 + j*(279) +-100 + j*(-28) +-5 + j*(-159) +49 + j*(-167) +-3 + j*(230) +-57 + j*(12) +136 + j*(-295) +62 + j*(-274) +-178 + j*(-213) +-34 + j*(284) +102 + j*(174) +-112 + j*(83) +99 + j*(161) +-141 + j*(-249) +16 + j*(21) +135 + j*(-135) +62 + j*(162) +23 + j*(-67) +-128 + j*(-1) +-24 + j*(-153) +8 + j*(128) +134 + j*(-47) +-240 + j*(185) +18 + j*(310) +-136 + j*(108) +-266 + j*(-65) +174 + j*(33) +-188 + j*(18) +-146 + j*(180) +128 + j*(-28) +339 + j*(157) +-163 + j*(215) +148 + j*(26) +-57 + j*(-83) +-116 + j*(82) +-91 + j*(110) +-258 + j*(1) +-128 + j*(-60) +26 + j*(-158) +-87 + j*(-183) +1 + j*(12) +-73 + j*(313) +265 + j*(-34) +-39 + j*(-241) +-30 + j*(66) +81 + j*(-78) +97 + j*(-133) +-57 + j*(-127) +94 + j*(-61) +228 + j*(-84) +-77 + j*(276) +76 + j*(86) +-38 + j*(-375) +-130 + j*(136) +-11 + j*(-57) +-182 + j*(25) +40 + j*(-249) +-206 + j*(100) +0 + j*(119) +-240 + j*(-139) +-165 + j*(55) +170 + j*(-28) +361 + j*(-87) +91 + j*(132) +10 + j*(139) +-154 + j*(-103) +37 + j*(39) +-142 + j*(-283) +181 + j*(207) +-1 + j*(-238) +-273 + j*(93) +27 + j*(-272) +-78 + j*(-228) +322 + j*(-95) +-100 + j*(-489) +-257 + j*(-308) +-112 + j*(302) +145 + j*(243) +-69 + j*(88) +-78 + j*(-173) +96 + j*(107) +-100 + j*(178) +-348 + j*(45) +-27 + j*(30) +267 + j*(-211) +52 + j*(-66) +236 + j*(-195) +339 + j*(-69) +351 + j*(125) +-79 + j*(-368) +71 + j*(4) +-151 + j*(159) +-47 + j*(-404) +-266 + j*(209) +175 + j*(46) +-301 + j*(-93) +281 + j*(-106) +-25 + j*(-88) +-96 + j*(-258) +160 + j*(-1) +128 + j*(28) +11 + j*(43) +137 + j*(412) +-276 + j*(141) +64 + j*(-101) +-82 + j*(-85) +-194 + j*(100) +-305 + j*(-136) +45 + j*(175) +-28 + j*(-45) +190 + j*(169) +265 + j*(74) +264 + j*(-54) +-26 + j*(112) +-264 + j*(177) +-255 + j*(320) +127 + j*(70) +184 + j*(-347) +132 + j*(244) +298 + j*(-8) +-182 + j*(-144) +-226 + j*(175) +-40 + j*(323) +200 + j*(-257) +-293 + j*(282) +11 + j*(-280) +-1 + j*(-445) +18 + j*(-180) +134 + j*(10) +-3 + j*(-98) +262 + j*(-4) +45 + j*(153) +376 + j*(84) +-324 + j*(185) +-197 + j*(-124) +-152 + j*(-61) +-40 + j*(-2) +-173 + j*(-68) +98 + j*(108) +261 + j*(-73) +119 + j*(76) +28 + j*(-102) +-305 + j*(-276) +243 + j*(180) +-221 + j*(128) +64 + j*(-102) +-108 + j*(267) +-8 + j*(-108) +-116 + j*(139) +-91 + j*(-62) +24 + j*(25) +-83 + j*(98) +45 + j*(-124) +173 + j*(47) +-124 + j*(-233) +-47 + j*(-125) +-88 + j*(-132) +-21 + j*(277) +-112 + j*(-133) +88 + j*(97) +-320 + j*(354) +338 + j*(259) +-6 + j*(-208) +-8 + j*(-50) +310 + j*(-15) +-33 + j*(-134) +93 + j*(-54) +70 + j*(-214) +10 + j*(-65) +123 + j*(78) +317 + j*(147) +-209 + j*(-153) +513 + j*(-206) +-306 + j*(-128) +27 + j*(-395) +112 + j*(90) +-17 + j*(35) +-57 + j*(-4) +-122 + j*(-385) +30 + j*(-61) +-167 + j*(238) +269 + j*(265) +203 + j*(41) +253 + j*(70) +52 + j*(-152) +-53 + j*(-49) +96 + j*(49) +-202 + j*(-424) +34 + j*(-286) +-505 + j*(-199) +-190 + j*(166) +308 + j*(-265) +-186 + j*(451) +-331 + j*(-117) +115 + j*(64) +-171 + j*(111) +-106 + j*(266) +143 + j*(-148) +-13 + j*(16) +-168 + j*(375) +211 + j*(150) +-470 + j*(104) +-274 + j*(-323) +198 + j*(76) +115 + j*(349) +-244 + j*(129) +-5 + j*(-64) +309 + j*(-34) +18 + j*(107) +482 + j*(76) +136 + j*(245) +-91 + j*(-34) +-130 + j*(153) +83 + j*(-168) +0 + j*(-32) +23 + j*(-372) +-44 + j*(-225) +-228 + j*(-75) +28 + j*(244) +-141 + j*(82) +-149 + j*(-58) +-271 + j*(-217) +-331 + j*(270) +-100 + j*(-6) +185 + j*(-83) +325 + j*(-273) +226 + j*(-206) +240 + j*(86) +-154 + j*(-227) +-48 + j*(-69) +-42 + j*(72) +377 + j*(137) +62 + j*(-402) +-53 + j*(-8) +29 + j*(63) +-30 + j*(204) +-255 + j*(390) +233 + j*(180) +-53 + j*(-97) +-42 + j*(-55) +-32 + j*(-76) +66 + j*(410) +33 + j*(243) +163 + j*(-12) +-195 + j*(-38) +254 + j*(98) +-132 + j*(-132) +7 + j*(-87) +136 + j*(240) +59 + j*(42) +225 + j*(-68) +-159 + j*(152) +-129 + j*(-4) +269 + j*(-86) +-37 + j*(79) +-436 + j*(-71) +-23 + j*(211) +163 + j*(176) +-89 + j*(-98) +-129 + j*(-387) +118 + j*(8) +38 + j*(-47) +337 + j*(-88) +-4 + j*(-1) +231 + j*(-82) +54 + j*(366) +-73 + j*(138) +-8 + j*(-69) +-163 + j*(135) +-159 + j*(-257) +-214 + j*(-268) +-60 + j*(-36) +69 + j*(182) +172 + j*(115) +-105 + j*(288) +77 + j*(-184) +-107 + j*(101) +248 + j*(45) +61 + j*(-101) +292 + j*(-93) +69 + j*(-192) +143 + j*(66) +-279 + j*(138) +-74 + j*(-21) +371 + j*(-74) +134 + j*(300) +-71 + j*(8) +108 + j*(-291) +4 + j*(129) +-373 + j*(-51) +59 + j*(-117) +189 + j*(-206) +206 + j*(28) +-242 + j*(-433) +-98 + j*(-260) +-102 + j*(169) +-82 + j*(33) +-11 + j*(-184) +-24 + j*(-47) +77 + j*(-71) +-117 + j*(-44) +204 + j*(-164) +-10 + j*(-81) +179 + j*(-16) +68 + j*(-293) +22 + j*(37) +202 + j*(104) +30 + j*(45) +192 + j*(180) +-136 + j*(-117) +120 + j*(173) +-202 + j*(148) +-172 + j*(173) +-28 + j*(190) +115 + j*(-58) +-167 + j*(199) +-95 + j*(212) +168 + j*(-260) +-250 + j*(-95) +-35 + j*(100) +-360 + j*(-88) +-163 + j*(75) +335 + j*(-58) +-14 + j*(151) +-169 + j*(104) +334 + j*(105) +-157 + j*(102) +-45 + j*(316) +-64 + j*(-126) +-4 + j*(-431) +-91 + j*(-217) +13 + j*(-134) +52 + j*(409) +160 + j*(14) +89 + j*(9) +-217 + j*(5) +-177 + j*(-442) +225 + j*(-34) +-110 + j*(-98) +130 + j*(-428) +-225 + j*(212) +44 + j*(-217) +40 + j*(-213) +-158 + j*(30) +16 + j*(49) +101 + j*(-322) +-93 + j*(38) +330 + j*(214) +-61 + j*(18) +285 + j*(34) +-228 + j*(-156) +146 + j*(83) +-427 + j*(-93) +-119 + j*(58) +-91 + j*(-428) +-177 + j*(-75) +62 + j*(-10) +-29 + j*(-49) +-76 + j*(95) +62 + j*(-320) +-144 + j*(88) +197 + j*(-121) +243 + j*(-54) +113 + j*(223) +59 + j*(-157) +136 + j*(-99) +145 + j*(-90) +-283 + j*(-42) +-247 + j*(-106) +99 + j*(-380) +-8 + j*(-124) +-28 + j*(-31) +407 + j*(250) +-198 + j*(-94) +244 + j*(154) +119 + j*(501) +82 + j*(315) +16 + j*(122) +-6 + j*(-247) +-162 + j*(300) +103 + j*(-98) +221 + j*(-177) +-80 + j*(207) +43 + j*(105) +8 + j*(2) +251 + j*(-303) +143 + j*(-45) +209 + j*(-18) +-35 + j*(76) +-191 + j*(254) +178 + j*(-18) +66 + j*(-378) +45 + j*(-7) +-159 + j*(-144) +-282 + j*(-106) +-225 + j*(2) +-107 + j*(-255) +92 + j*(226) +-39 + j*(-218) +-102 + j*(139) +184 + j*(77) +-78 + j*(134) +56 + j*(-278) +-35 + j*(-81) +-61 + j*(-204) +-65 + j*(-25) +-202 + j*(163) +310 + j*(-28) +-111 + j*(-95) +-2 + j*(141) +-173 + j*(-51) +-21 + j*(182) +-257 + j*(-57) +-83 + j*(81) +-267 + j*(52) +2 + j*(13) +35 + j*(59) +105 + j*(190) +-306 + j*(-253) +19 + j*(88) +-3 + j*(-221) +234 + j*(-160) +-9 + j*(-108) +-325 + j*(356) +-71 + j*(268) +-308 + j*(364) +-308 + j*(183) +193 + j*(-95) +62 + j*(-12) +107 + j*(42) +-100 + j*(62) +-84 + j*(57) +-90 + j*(-427) +-73 + j*(-35) +-191 + j*(134) +-48 + j*(-85) +193 + j*(-242) +-80 + j*(61) +225 + j*(-24) +-179 + j*(-218) +353 + j*(394) +197 + j*(109) +228 + j*(9) +386 + j*(167) +86 + j*(-8) +55 + j*(-312) +-18 + j*(78) +-32 + j*(-191) +-24 + j*(20) +121 + j*(-126) +-80 + j*(16) +-161 + j*(367) +-64 + j*(109) +-22 + j*(37) +-145 + j*(65) +-197 + j*(-272) +103 + j*(-46) +-98 + j*(99) +-325 + j*(-251) +43 + j*(-93) +-54 + j*(-3) +193 + j*(-82) +91 + j*(57) +80 + j*(-122) +151 + j*(-258) +36 + j*(-443) +-69 + j*(-25) +-116 + j*(-222) +-12 + j*(-306) +-298 + j*(-242) +243 + j*(-248) +94 + j*(-47) +-65 + j*(103) +-246 + j*(128) +-27 + j*(52) +-165 + j*(235) +-88 + j*(41) +-21 + j*(-100) +-2 + j*(222) +-156 + j*(163) +209 + j*(279) +55 + j*(177) +-209 + j*(-136) +132 + j*(-42) +-221 + j*(-51) +91 + j*(62) +-34 + j*(129) +-217 + j*(-257) +6 + j*(-36) +-353 + j*(-90) +-7 + j*(-86) +105 + j*(81) +148 + j*(-40) +-20 + j*(-6) +93 + j*(-156) +145 + j*(120) +-110 + j*(465) +-39 + j*(23) +-54 + j*(138) +-69 + j*(87) +-91 + j*(-74) +361 + j*(26) +513 + j*(-134) +-293 + j*(-134) +18 + j*(-93) +424 + j*(177) +-22 + j*(40) +173 + j*(74) +2 + j*(-207) +-162 + j*(-165) +57 + j*(128) +315 + j*(80) +-102 + j*(117) +238 + j*(-75) +-107 + j*(134) +-204 + j*(-153) +-170 + j*(-9) +2 + j*(50) +88 + j*(110) +-8 + j*(-115) +-92 + j*(-237) +-52 + j*(265) +-40 + j*(16) +-74 + j*(-80) +-150 + j*(-26) +-33 + j*(-29) +383 + j*(-48) +-182 + j*(247) +-192 + j*(260) +108 + j*(133) +175 + j*(-317) +-12 + j*(-103) +-24 + j*(-373) +141 + j*(-220) +170 + j*(-106) +-112 + j*(-248) +180 + j*(-78) +-252 + j*(-380) +-39 + j*(-247) +-152 + j*(39) +28 + j*(-119) +-47 + j*(-174) +101 + j*(87) +127 + j*(77) +103 + j*(-255) +66 + j*(257) +-105 + j*(32) +78 + j*(69) +26 + j*(-54) +-31 + j*(73) +346 + j*(346) +8 + j*(26) +-37 + j*(-59) +21 + j*(194) +-28 + j*(183) +100 + j*(-55) +-157 + j*(175) +-322 + j*(-137) +-33 + j*(132) +-477 + j*(-62) +332 + j*(-111) +83 + j*(282) +-134 + j*(92) +-269 + j*(-296) +-4 + j*(5) +69 + j*(-35) +-299 + j*(14) +154 + j*(-176) +-137 + j*(11) +156 + j*(-180) +-66 + j*(-36) +-10 + j*(57) +-261 + j*(-361) +-36 + j*(74) +-31 + j*(147) +-19 + j*(-169) +149 + j*(256) +-332 + j*(29) +-293 + j*(-197) +117 + j*(-184) +235 + j*(134) +251 + j*(86) +54 + j*(-310) +13 + j*(-11) +-385 + j*(-286) +-2 + j*(-37) +-115 + j*(-48) +197 + j*(-20) +264 + j*(136) +-243 + j*(-59) +-187 + j*(30) +92 + j*(28) +-91 + j*(-238) +-93 + j*(-179) +6 + j*(76) +11 + j*(6) +-96 + j*(78) +25 + j*(59) +110 + j*(523) +141 + j*(-14) +-94 + j*(-10) +22 + j*(-120) +443 + j*(-14) +95 + j*(-174) +-141 + j*(125) +-12 + j*(-354) +-193 + j*(-144) +-156 + j*(-74) +210 + j*(317) +281 + j*(-52) +77 + j*(89) +21 + j*(-80) +332 + j*(-6) +292 + j*(18) +57 + j*(-45) +-65 + j*(113) +-317 + j*(-109) +-378 + j*(-298) +185 + j*(1) +-453 + j*(-45) +123 + j*(279) +27 + j*(57) +-299 + j*(23) +112 + j*(47) +-47 + j*(174) +33 + j*(-227) +-288 + j*(9) +-153 + j*(5) +250 + j*(52) +-119 + j*(-208) +127 + j*(262) +-30 + j*(-109) +55 + j*(-247) +-112 + j*(-44) +-82 + j*(-38) +-297 + j*(-16) +59 + j*(60) +-198 + j*(-55) +204 + j*(-151) +12 + j*(40) +-627 + j*(-236) +-112 + j*(-281) +-91 + j*(-167) +38 + j*(83) +-146 + j*(130) +-228 + j*(29) +-67 + j*(-216) +100 + j*(30) +137 + j*(190) +173 + j*(337) +252 + j*(-108) +431 + j*(-163) +217 + j*(-54) +-156 + j*(-250) +286 + j*(-232) +286 + j*(-181) +-103 + j*(-117) +-177 + j*(81) +-246 + j*(-159) +-254 + j*(58) +69 + j*(157) +-110 + j*(34) +262 + j*(95) +-130 + j*(148) +144 + j*(345) +152 + j*(25) +89 + j*(236) +257 + j*(146) +50 + j*(-297) +109 + j*(207) +105 + j*(-262) +330 + j*(-397) +-221 + j*(-162) +60 + j*(-54) +49 + j*(-194) +24 + j*(-104) +-45 + j*(-18) +-180 + j*(266) +-25 + j*(183) +64 + j*(221) +302 + j*(409) +-55 + j*(3) +226 + j*(-310) +37 + j*(-49) +-116 + j*(66) +115 + j*(-84) +-155 + j*(174) +-134 + j*(100) +-211 + j*(-69) +226 + j*(-11) +397 + j*(43) +170 + j*(81) +-107 + j*(-122) +433 + j*(-25) +115 + j*(-77) +-235 + j*(-4) +-308 + j*(-138) +187 + j*(241) +49 + j*(8) +62 + j*(105) +-296 + j*(122) +33 + j*(497) +334 + j*(-1) +194 + j*(41) +204 + j*(-245) +-49 + j*(15) +-103 + j*(16) +-217 + j*(56) +28 + j*(196) +343 + j*(-173) +173 + j*(164) +-100 + j*(167) +-94 + j*(-25) +-79 + j*(-95) +30 + j*(-276) +144 + j*(61) +-120 + j*(-195) +-213 + j*(-366) +209 + j*(30) +6 + j*(-245) +-43 + j*(-83) +28 + j*(61) +4 + j*(-51) +-167 + j*(52) +-245 + j*(4) +-48 + j*(-92) +-53 + j*(210) +-156 + j*(-160) +-82 + j*(-115) +-198 + j*(-206) +-134 + j*(-6) +203 + j*(-311) +-317 + j*(-81) +-66 + j*(-54) +67 + j*(-153) +-34 + j*(-26) +-14 + j*(-69) +91 + j*(163) +-6 + j*(-6) +-141 + j*(66) +-91 + j*(241) +-42 + j*(196) +-49 + j*(-35) +-175 + j*(-137) +16 + j*(267) +49 + j*(-106) +45 + j*(97) +-351 + j*(119) +-276 + j*(-46) +-109 + j*(94) +3 + j*(170) +-182 + j*(323) +97 + j*(-124) +-203 + j*(307) +-233 + j*(231) +-134 + j*(78) +282 + j*(8) +124 + j*(319) +119 + j*(-40) +-176 + j*(-145) +26 + j*(42) +97 + j*(-273) +-319 + j*(-56) +-148 + j*(-65) +-12 + j*(242) +16 + j*(165) +264 + j*(85) +-181 + j*(-34) +1 + j*(-103) +194 + j*(-12) +14 + j*(260) +-251 + j*(-40) +-280 + j*(81) +-42 + j*(-2) +-6 + j*(152) +155 + j*(245) +-267 + j*(103) +-23 + j*(-334) +-177 + j*(100) +8 + j*(-99) +104 + j*(-202) +168 + j*(94) +59 + j*(-193) +57 + j*(116) +98 + j*(-116) +-96 + j*(-264) +-44 + j*(301) +138 + j*(6) +-168 + j*(187) +-306 + j*(-88) +-163 + j*(-206) +-222 + j*(52) +319 + j*(32) +45 + j*(-178) +-207 + j*(-179) +160 + j*(-24) +84 + j*(460) +91 + j*(-168) +168 + j*(119) +11 + j*(-8) +-145 + j*(195) +-145 + j*(-81) +39 + j*(247) +-66 + j*(203) +208 + j*(-63) +167 + j*(40) +-64 + j*(366) +51 + j*(262) +21 + j*(139) +-38 + j*(-226) +158 + j*(-107) +-109 + j*(566) +100 + j*(-16) +2 + j*(43) +1 + j*(-100) +23 + j*(-98) +-48 + j*(-217) +-64 + j*(218) +105 + j*(-83) +-186 + j*(104) +-64 + j*(-268) +1 + j*(131) +-219 + j*(-175) +-100 + j*(69) +34 + j*(-469) +199 + j*(177) +305 + j*(-176) +-184 + j*(-29) +-332 + j*(50) +309 + j*(93) +-19 + j*(-73) +-21 + j*(-3) +56 + j*(81) +171 + j*(-164) +62 + j*(-228) +-21 + j*(-373) +-88 + j*(-193) +201 + j*(-6) +340 + j*(-322) +207 + j*(7) +-89 + j*(-211) +-206 + j*(12) +-161 + j*(-84) +49 + j*(-272) +132 + j*(-129) +-126 + j*(304) +26 + j*(66) +-39 + j*(84) +-228 + j*(-138) +71 + j*(13) +-27 + j*(-319) +157 + j*(104) +98 + j*(291) +187 + j*(-319) +287 + j*(52) +-91 + j*(228) +-42 + j*(-133) +297 + j*(-35) +28 + j*(-127) +50 + j*(38) +253 + j*(-35) +126 + j*(-69) +153 + j*(-41) +-141 + j*(203) +-63 + j*(-108) +-69 + j*(-134) +274 + j*(273) +255 + j*(-329) +202 + j*(31) +-158 + j*(-15) +240 + j*(122) +-249 + j*(205) +-29 + j*(171) +-209 + j*(28) +146 + j*(-77) +124 + j*(-155) +-21 + j*(-257) +342 + j*(292) +-75 + j*(145) +-37 + j*(199) +124 + j*(317) +198 + j*(48) +197 + j*(35) +-71 + j*(-55) +235 + j*(-358) +-136 + j*(62) +-121 + j*(-194) +-129 + j*(190) +126 + j*(160) +153 + j*(154) +223 + j*(-95) +78 + j*(-270) +447 + j*(60) +-184 + j*(-173) +-121 + j*(-134) +141 + j*(-25) +179 + j*(-190) +26 + j*(305) +-180 + j*(-13) +123 + j*(-4) +130 + j*(-310) +-42 + j*(-91) +71 + j*(286) +-192 + j*(33) +130 + j*(206) +147 + j*(2) +-38 + j*(-156) +1 + j*(327) +-34 + j*(-42) +-254 + j*(-168) +189 + j*(227) +143 + j*(32) +-211 + j*(-264) +-39 + j*(-439) +-24 + j*(271) +-25 + j*(110) +190 + j*(-4) +-102 + j*(-243) +-13 + j*(40) +-87 + j*(55) +156 + j*(89) +295 + j*(-50) +210 + j*(-263) +-303 + j*(70) +86 + j*(-102) +-68 + j*(4) +79 + j*(-426) +-152 + j*(-158) +93 + j*(36) +52 + j*(-144) +27 + j*(-280) +58 + j*(-16) +82 + j*(2) +57 + j*(-151) +-76 + j*(-21) +-67 + j*(125) +233 + j*(-44) +72 + j*(-83) +203 + j*(52) +-35 + j*(0) +140 + j*(-147) +110 + j*(144) +96 + j*(23) +288 + j*(-122) +-67 + j*(85) +300 + j*(-56) +-262 + j*(39) +201 + j*(233) +-20 + j*(151) +-323 + j*(-35) +49 + j*(143) +-89 + j*(-158) +-66 + j*(-216) +-244 + j*(163) +240 + j*(-245) +364 + j*(-71) +-205 + j*(280) +66 + j*(-18) +-58 + j*(144) +141 + j*(-151) +154 + j*(-25) +202 + j*(-83) +33 + j*(-127) +-166 + j*(-157) +451 + j*(-244) +-101 + j*(35) +18 + j*(134) +134 + j*(252) +-95 + j*(-264) +320 + j*(211) +-54 + j*(-52) +-145 + j*(122) +-10 + j*(247) +-359 + j*(164) +-93 + j*(-90) +-141 + j*(199) +-122 + j*(-140) +-384 + j*(-230) +34 + j*(2) +-190 + j*(276) +-49 + j*(185) +197 + j*(-12) +-213 + j*(-105) +-110 + j*(-62) +-1 + j*(163) +54 + j*(12) +74 + j*(-148) +-130 + j*(221) +-86 + j*(161) +86 + j*(50) +-110 + j*(-74) +129 + j*(256) +25 + j*(-84) +-35 + j*(-124) +71 + j*(-105) +274 + j*(-267) +298 + j*(-52) +-1 + j*(116) +220 + j*(-17) +147 + j*(126) +69 + j*(53) +-208 + j*(-60) +197 + j*(115) +-140 + j*(13) +122 + j*(-74) +36 + j*(194) +-40 + j*(-26) +-126 + j*(97) +288 + j*(115) +-142 + j*(127) +-20 + j*(-21) +-117 + j*(79) +-73 + j*(308) +-430 + j*(132) +-129 + j*(161) +83 + j*(56) +-63 + j*(-355) +-139 + j*(132) +206 + j*(8) +19 + j*(-193) +156 + j*(-25) +20 + j*(-277) +74 + j*(207) +-312 + j*(-97) +-264 + j*(127) +219 + j*(69) +-16 + j*(126) +92 + j*(-206) +-227 + j*(164) +-172 + j*(-120) +158 + j*(-31) +110 + j*(83) +-103 + j*(6) +-22 + j*(120) +110 + j*(93) +37 + j*(-170) +-148 + j*(136) +-23 + j*(12) +59 + j*(61) +117 + j*(119) +163 + j*(283) +263 + j*(95) +334 + j*(65) +-169 + j*(80) +-129 + j*(543) +-163 + j*(179) +46 + j*(193) +-177 + j*(232) +206 + j*(13) +203 + j*(67) +42 + j*(31) +119 + j*(-159) +-98 + j*(104) +68 + j*(70) +91 + j*(155) +55 + j*(-175) +88 + j*(-54) +-148 + j*(-14) +405 + j*(30) +250 + j*(-249) +6 + j*(234) +71 + j*(69) +57 + j*(-92) +194 + j*(44) +-104 + j*(175) +136 + j*(-145) +137 + j*(-80) +110 + j*(-363) +240 + j*(-14) +-110 + j*(158) +-57 + j*(28) +-112 + j*(-86) +25 + j*(192) +139 + j*(-252) +-250 + j*(-42) +25 + j*(61) +-235 + j*(-152) +310 + j*(-206) +-341 + j*(-164) +-113 + j*(4) +-62 + j*(-13) +216 + j*(90) +-45 + j*(-161) +-129 + j*(-240) +124 + j*(173) +66 + j*(180) +80 + j*(-23) +-62 + j*(144) +28 + j*(-5) +115 + j*(184) +75 + j*(-197) +-325 + j*(100) +94 + j*(-126) +-78 + j*(-344) +-107 + j*(302) +-243 + j*(-243) +62 + j*(227) +-15 + j*(-337) +-49 + j*(-74) +88 + j*(134) +-91 + j*(81) +-34 + j*(103) +-112 + j*(233) +253 + j*(151) +-45 + j*(-25) +212 + j*(-127) +-363 + j*(66) +251 + j*(12) +267 + j*(27) +280 + j*(-414) +136 + j*(131) +-32 + j*(-176) +136 + j*(31) +-139 + j*(171) +185 + j*(103) +84 + j*(198) +88 + j*(81) +104 + j*(-158) +301 + j*(298) +63 + j*(260) +210 + j*(-169) +112 + j*(-52) +-64 + j*(119) +-169 + j*(-281) +-83 + j*(-310) +274 + j*(-79) +209 + j*(-182) +-107 + j*(-240) +-86 + j*(4) +202 + j*(16) +-387 + j*(75) +-81 + j*(85) +17 + j*(260) +-348 + j*(-243) +-39 + j*(88) +259 + j*(-40) +37 + j*(13) +157 + j*(-121) +40 + j*(-37) +267 + j*(-28) +85 + j*(47) +-310 + j*(52) +25 + j*(33) +-366 + j*(-264) +-58 + j*(120) +36 + j*(-93) +187 + j*(6) +93 + j*(23) +44 + j*(-240) +235 + j*(161) +197 + j*(293) +-153 + j*(126) +211 + j*(-71) +213 + j*(-42) +176 + j*(-6) +-176 + j*(-40) +33 + j*(64) +-81 + j*(-133) +52 + j*(256) +160 + j*(-141) +118 + j*(187) +-212 + j*(26) +-257 + j*(157) +192 + j*(18) +199 + j*(295) +49 + j*(-94) +2 + j*(208) +-83 + j*(-170) +-226 + j*(-139) +-197 + j*(18) +40 + j*(-130) +144 + j*(-136) +107 + j*(19) +-102 + j*(472) +-53 + j*(-39) +5 + j*(265) +173 + j*(256) +-349 + j*(40) +54 + j*(-140) +66 + j*(132) +64 + j*(73) +-141 + j*(95) +327 + j*(-69) +-547 + j*(115) +59 + j*(-115) +-62 + j*(69) +81 + j*(182) +-86 + j*(-208) +-100 + j*(-318) +127 + j*(213) +93 + j*(16) +243 + j*(-7) +-23 + j*(333) +-21 + j*(330) +74 + j*(-50) +-40 + j*(-168) +434 + j*(333) +81 + j*(-143) +230 + j*(163) +209 + j*(-187) +-33 + j*(270) +132 + j*(-217) +-127 + j*(-35) +-59 + j*(40) +187 + j*(32) +-11 + j*(-143) +156 + j*(245) +-18 + j*(-28) +-166 + j*(-27) +332 + j*(145) +8 + j*(-192) +-11 + j*(-185) +-190 + j*(72) +-118 + j*(138) +112 + j*(215) +-26 + j*(52) +137 + j*(29) +-200 + j*(-123) +183 + j*(-187) +93 + j*(35) +-336 + j*(-33) +28 + j*(223) +-1 + j*(-18) +-234 + j*(98) +117 + j*(25) +132 + j*(-174) +-430 + j*(-3) +52 + j*(-205) +95 + j*(148) +-55 + j*(-199) +20 + j*(-107) +-113 + j*(-80) +51 + j*(26) +-13 + j*(79) +-182 + j*(20) +-71 + j*(-19) +-16 + j*(-290) +-197 + j*(204) +42 + j*(-184) +-63 + j*(52) +16 + j*(-112) +164 + j*(-293) +-39 + j*(113) +267 + j*(-49) +259 + j*(-80) +-65 + j*(55) +151 + j*(112) +-21 + j*(113) +64 + j*(-163) +71 + j*(28) +155 + j*(126) +226 + j*(47) +173 + j*(195) +11 + j*(-218) +87 + j*(-64) +126 + j*(-53) +34 + j*(-310) +225 + j*(-183) +-148 + j*(-328) +210 + j*(-400) +289 + j*(49) +3 + j*(-170) +231 + j*(54) +136 + j*(21) +-83 + j*(273) +108 + j*(251) +429 + j*(277) +6 + j*(294) +103 + j*(207) +16 + j*(-199) +187 + j*(28) +16 + j*(51) +232 + j*(51) +-148 + j*(9) +77 + j*(-168) +42 + j*(279) +132 + j*(265) +145 + j*(-90) +-49 + j*(-211) +90 + j*(144) +156 + j*(3) +27 + j*(-264) +302 + j*(23) +148 + j*(-5) +-119 + j*(-27) +-100 + j*(-138) +-182 + j*(-56) +-303 + j*(333) +-101 + j*(162) +311 + j*(-143) +-27 + j*(-283) +-215 + j*(-93) +-64 + j*(120) +-10 + j*(-337) +-204 + j*(48) +-91 + j*(-95) +113 + j*(-223) +-68 + j*(-86) +91 + j*(-162) +383 + j*(534) +331 + j*(-151) +296 + j*(-125) +-534 + j*(195) +68 + j*(341) +-64 + j*(338) +202 + j*(199) +277 + j*(-187) +10 + j*(-149) +-89 + j*(-287) +356 + j*(-535) +136 + j*(225) +221 + j*(-13) +245 + j*(105) +-55 + j*(-260) +-246 + j*(-332) +-146 + j*(315) +-602 + j*(-237) +-329 + j*(238) +-173 + j*(-174) +562 + j*(83) +-189 + j*(-310) +339 + j*(361) +-309 + j*(-162) +81 + j*(317) +445 + j*(-265) +-183 + j*(343) +-302 + j*(33) +-663 + j*(180) +-257 + j*(-70) +515 + j*(252) +192 + j*(334) +-560 + j*(68) +214 + j*(11) +-463 + j*(-437) +66 + j*(286) +-305 + j*(236) +-332 + j*(40) +-180 + j*(-321) +420 + j*(-76) +63 + j*(-168) +243 + j*(-251) +176 + j*(-378) +328 + j*(303) +-270 + j*(353) +-407 + j*(-240) +257 + j*(207) +-107 + j*(-203) +-100 + j*(-153) +635 + j*(335) +45 + j*(52) +251 + j*(-25) +238 + j*(232) +-268 + j*(-144) +183 + j*(-70) +-237 + j*(-222) +231 + j*(274) +-132 + j*(372) +383 + j*(50) +-187 + j*(195) +81 + j*(156) +-145 + j*(-689) +139 + j*(312) +-162 + j*(419) +387 + j*(-187) +-168 + j*(-233) +-344 + j*(184) +-337 + j*(-478) +737 + j*(-88) +-106 + j*(486) +44 + j*(226) +-293 + j*(100) +532 + j*(-33) +534 + j*(-52) +-527 + j*(431) +-438 + j*(-312) +223 + j*(-175) +149 + j*(367) +132 + j*(-694) +406 + j*(306) +222 + j*(-339) +-68 + j*(493) +348 + j*(123) +16 + j*(-402) +125 + j*(-231) +-468 + j*(-245) +304 + j*(74) +439 + j*(423) +-438 + j*(18) +-686 + j*(327) +-150 + j*(98) +303 + j*(147) +411 + j*(-9) +-298 + j*(103) +-185 + j*(-97) +-288 + j*(-369) +393 + j*(-370) +491 + j*(433) +412 + j*(146) +-167 + j*(-435) +199 + j*(-350) +316 + j*(-90) +204 + j*(-154) +-333 + j*(-12) +682 + j*(-197) +-139 + j*(439) +-306 + j*(49) +-281 + j*(-679) +454 + j*(-212) +444 + j*(508) +106 + j*(-67) +-122 + j*(-80) +268 + j*(196) +587 + j*(-342) +-275 + j*(379) +443 + j*(-190) +-606 + j*(199) +-108 + j*(524) +-202 + j*(201) +-395 + j*(-388) +511 + j*(-591) +-265 + j*(-98) +224 + j*(189) +231 + j*(-250) +45 + j*(-397) +-286 + j*(-167) +230 + j*(40) +346 + j*(395) +-400 + j*(635) +43 + j*(-228) +397 + j*(149) +-160 + j*(520) +204 + j*(213) +335 + j*(398) +344 + j*(504) +-11 + j*(-309) +59 + j*(-37) +-390 + j*(-374) +-361 + j*(518) +386 + j*(131) +233 + j*(-187) +356 + j*(23) +-157 + j*(-261) +-451 + j*(-523) +167 + j*(593) +209 + j*(119) +-730 + j*(-56) +-219 + j*(-598) +29 + j*(250) +79 + j*(392) +300 + j*(158) +276 + j*(-165) +72 + j*(-346) +-245 + j*(-170) +455 + j*(-394) +48 + j*(315) +33 + j*(-81) +201 + j*(127) +-37 + j*(51) +196 + j*(180) +-62 + j*(416) +267 + j*(252) +-242 + j*(-452) +-8 + j*(397) +124 + j*(40) +-264 + j*(-126) +42 + j*(404) +558 + j*(103) +-327 + j*(35) +-510 + j*(528) +-561 + j*(-597) +-349 + j*(-397) +41 + j*(214) +-334 + j*(462) +98 + j*(-105) +-75 + j*(229) +245 + j*(-116) +330 + j*(186) +-81 + j*(434) +488 + j*(200) +-124 + j*(-164) +-8 + j*(68) +-88 + j*(373) +-312 + j*(-402) +103 + j*(267) +683 + j*(217) +-341 + j*(67) +-280 + j*(350) +492 + j*(-231) +-211 + j*(-218) +240 + j*(316) +364 + j*(272) +370 + j*(453) +253 + j*(171) +184 + j*(663) +-333 + j*(-392) +-192 + j*(-409) +384 + j*(-292) +220 + j*(-143) +-284 + j*(242) +118 + j*(-272) +170 + j*(-47) +422 + j*(-353) +494 + j*(-685) +-88 + j*(95) +264 + j*(232) +153 + j*(175) +168 + j*(205) +-126 + j*(-213) +-51 + j*(390) +-283 + j*(40) +-361 + j*(689) +171 + j*(-141) +435 + j*(-318) +-141 + j*(-260) +220 + j*(-144) +286 + j*(155) +-310 + j*(299) +78 + j*(-204) +373 + j*(273) +-321 + j*(723) +707 + j*(-203) +324 + j*(102) +-177 + j*(-383) +245 + j*(-99) +-380 + j*(339) +235 + j*(-375) +-292 + j*(77) +23 + j*(-351) +330 + j*(-171) +211 + j*(167) +455 + j*(-540) +-448 + j*(-230) +215 + j*(263) +137 + j*(373) +-66 + j*(-47) +-300 + j*(-85) +302 + j*(177) +-442 + j*(197) +-46 + j*(132) +-419 + j*(214) +-166 + j*(92) +-184 + j*(447) +94 + j*(342) +-328 + j*(-42) +-552 + j*(-458) +374 + j*(-177) +300 + j*(404) +40 + j*(219) +-228 + j*(-505) +272 + j*(266) +-192 + j*(200) +213 + j*(-150) +274 + j*(-355) +492 + j*(54) +541 + j*(-602) +460 + j*(-52) +98 + j*(449) +382 + j*(-380) +-153 + j*(-241) +-250 + j*(-45) +-245 + j*(-315) +264 + j*(-289) +154 + j*(-177) +146 + j*(-441) +-336 + j*(285) +-102 + j*(388) +236 + j*(-18) +-115 + j*(335) +-532 + j*(421) +484 + j*(450) +354 + j*(738) +-416 + j*(523) +-293 + j*(-193) +115 + j*(-764) +-327 + j*(-238) +-425 + j*(-378) +-269 + j*(-413) +-642 + j*(-380) +-43 + j*(-7) +206 + j*(424) +244 + j*(-416) +453 + j*(-545) +-165 + j*(-64) +-138 + j*(-312) +-499 + j*(484) +-307 + j*(-119) +122 + j*(578) +-266 + j*(-390) +-218 + j*(395) +-188 + j*(-14) +373 + j*(-118) +86 + j*(629) +-435 + j*(-107) +390 + j*(-469) +197 + j*(-99) +343 + j*(-344) +-137 + j*(-218) +-252 + j*(354) +-261 + j*(329) +-214 + j*(393) +-247 + j*(274) +214 + j*(158) +74 + j*(315) +434 + j*(-211) +-228 + j*(-161) +-86 + j*(482) +41 + j*(197) +-110 + j*(217) +182 + j*(16) +437 + j*(-583) +446 + j*(-162) +-139 + j*(122) +117 + j*(368) +173 + j*(179) +245 + j*(-228) +78 + j*(450) +-484 + j*(-112) +-375 + j*(-177) +-265 + j*(-155) +185 + j*(-10) +635 + j*(-213) +-59 + j*(223) +306 + j*(-93) +8 + j*(-310) +201 + j*(333) +482 + j*(-70) +-78 + j*(115) +390 + j*(564) +433 + j*(280) +52 + j*(25) +185 + j*(328) +273 + j*(-367) +-156 + j*(255) +177 + j*(-170) +-181 + j*(207) +-466 + j*(-256) +-279 + j*(-97) +444 + j*(-466) +-105 + j*(308) +71 + j*(-127) +-1 + j*(6) +171 + j*(163) +-357 + j*(440) +346 + j*(97) +-366 + j*(-355) +-149 + j*(-342) +-72 + j*(-146) +120 + j*(185) +190 + j*(237) +-53 + j*(-444) +340 + j*(68) +103 + j*(7) +210 + j*(183) +282 + j*(-173) +240 + j*(373) +-112 + j*(463) +-187 + j*(262) +-260 + j*(-234) +-33 + j*(217) +-347 + j*(2) +229 + j*(-414) +163 + j*(284) +121 + j*(61) +-286 + j*(439) +403 + j*(112) +-290 + j*(122) +339 + j*(151) +339 + j*(-290) +349 + j*(-248) +-403 + j*(315) +-318 + j*(-601) +-293 + j*(-348) +279 + j*(-15) +79 + j*(-222) +-458 + j*(-433) +625 + j*(-496) +-81 + j*(204) +-222 + j*(-499) +-486 + j*(-186) +-113 + j*(-105) +-199 + j*(-497) +351 + j*(174) +347 + j*(-373) +233 + j*(49) +-64 + j*(-416) +264 + j*(-139) +33 + j*(494) +281 + j*(180) +-412 + j*(-375) +-318 + j*(502) +-265 + j*(274) +-260 + j*(175) +167 + j*(-491) +647 + j*(236) +-25 + j*(238) +-326 + j*(-495) +100 + j*(-313) +173 + j*(-786) +-98 + j*(231) +-238 + j*(409) +361 + j*(-446) +538 + j*(-350) +-127 + j*(-153) +-576 + j*(-199) +-72 + j*(-510) +363 + j*(-360) +-482 + j*(-238) +-352 + j*(-363) +-295 + j*(-104) +-119 + j*(212) +297 + j*(351) +-268 + j*(-371) +97 + j*(53) +235 + j*(90) +209 + j*(298) +-212 + j*(-276) +-309 + j*(551) +-54 + j*(-273) +225 + j*(457) +37 + j*(-149) +-81 + j*(202) +345 + j*(300) +-322 + j*(247) +202 + j*(425) +-215 + j*(-173) +-123 + j*(297) +-227 + j*(19) +-170 + j*(-366) +344 + j*(-305) +369 + j*(-191) +-318 + j*(525) +332 + j*(-325) +-337 + j*(-318) +-655 + j*(564) +595 + j*(-511) +436 + j*(384) +-515 + j*(40) +243 + j*(-459) +-21 + j*(156) +258 + j*(-438) +-357 + j*(-326) +-433 + j*(583) +-357 + j*(-489) +171 + j*(-34) +122 + j*(402) +-289 + j*(339) +160 + j*(189) +94 + j*(-71) +453 + j*(-301) +292 + j*(-117) +338 + j*(216) +363 + j*(400) +-43 + j*(-35) +217 + j*(85) +33 + j*(241) +173 + j*(-141) +-266 + j*(-306) +-264 + j*(-451) +226 + j*(-296) +350 + j*(-16) +30 + j*(312) +-566 + j*(-133) +-195 + j*(219) +478 + j*(-61) +-612 + j*(-527) +-189 + j*(-585) +-466 + j*(-600) +-288 + j*(445) +-460 + j*(245) +171 + j*(-448) +-258 + j*(520) +-379 + j*(-194) +369 + j*(-410) +-213 + j*(144) +128 + j*(-40) +308 + j*(277) +-37 + j*(-508) +226 + j*(-127) +290 + j*(285) +-506 + j*(-353) +-356 + j*(-194) +298 + j*(307) +161 + j*(499) +267 + j*(157) +117 + j*(-136) +494 + j*(-658) +103 + j*(-286) +415 + j*(465) +233 + j*(-156) +110 + j*(-371) +-428 + j*(196) +-377 + j*(269) +-234 + j*(127) +-321 + j*(-78) +282 + j*(-223) +-310 + j*(-246) +45 + j*(146) +5 + j*(38) +-182 + j*(239) +-430 + j*(453) +414 + j*(-105) +-527 + j*(147) +-12 + j*(554) +-296 + j*(-168) +-147 + j*(-170) +-504 + j*(-331) +-313 + j*(-380) +453 + j*(429) +-463 + j*(-119) +-175 + j*(-387) +251 + j*(403) +-143 + j*(187) +208 + j*(-498) +434 + j*(-214) +600 + j*(-360) +-251 + j*(28) +373 + j*(-204) +-305 + j*(-288) +-243 + j*(356) +53 + j*(-467) +127 + j*(226) +-412 + j*(-91) +325 + j*(371) +347 + j*(-487) +332 + j*(327) +-226 + j*(-306) +482 + j*(-47) +-62 + j*(397) +363 + j*(-184) +192 + j*(257) +-390 + j*(-347) +-15 + j*(-159) +434 + j*(-467) +347 + j*(-162) +374 + j*(-216) +-197 + j*(-21) +195 + j*(679) +317 + j*(451) +206 + j*(400) +420 + j*(421) +-190 + j*(-107) +-141 + j*(192) +452 + j*(364) +-550 + j*(44) +-141 + j*(-274) +-459 + j*(409) +466 + j*(-351) +-178 + j*(103) +-378 + j*(351) +-213 + j*(132) +-322 + j*(102) +-244 + j*(-537) +-252 + j*(-467) +-266 + j*(483) +433 + j*(-273) +-180 + j*(-474) +69 + j*(-356) +412 + j*(-295) +-36 + j*(-529) +-588 + j*(194) +-10 + j*(-25) +-446 + j*(-204) +-380 + j*(1) +-481 + j*(-128) +-271 + j*(151) +-303 + j*(-184) +272 + j*(-253) +102 + j*(284) +-153 + j*(66) +100 + j*(-302) +385 + j*(-581) +259 + j*(605) +205 + j*(-482) +-288 + j*(-276) +197 + j*(-288) +-398 + j*(325) +358 + j*(-357) +104 + j*(-474) +735 + j*(38) +306 + j*(-162) +121 + j*(-267) +-480 + j*(272) +-13 + j*(-94) +-146 + j*(131) +-484 + j*(-257) +-64 + j*(227) +178 + j*(19) +212 + j*(450) +17 + j*(-184) +-406 + j*(-301) +-424 + j*(252) +-194 + j*(444) +-550 + j*(-138) +361 + j*(424) +-308 + j*(-156) +-251 + j*(-183) +293 + j*(-98) +-271 + j*(249) +-317 + j*(-79) +-42 + j*(276) +-88 + j*(217) +1 + j*(327) +-53 + j*(250) +-42 + j*(-334) +154 + j*(70) +262 + j*(-33) +-1 + j*(-104) +35 + j*(-118) +57 + j*(455) +247 + j*(-148) +0 + j*(62) +-200 + j*(193) +62 + j*(-139) +95 + j*(111) +291 + j*(-154) +-135 + j*(118) +66 + j*(-148) +-337 + j*(192) +-247 + j*(-26) +-13 + j*(-40) +-412 + j*(-91) +-66 + j*(-206) +91 + j*(179) +-189 + j*(407) +-152 + j*(35) +187 + j*(28) +206 + j*(7) +242 + j*(-28) +-71 + j*(-75) +-187 + j*(-48) +240 + j*(-105) +-122 + j*(-187) +-156 + j*(163) +225 + j*(102) +52 + j*(198) +-62 + j*(3) +171 + j*(-147) +-84 + j*(-253) +-1 + j*(-402) +264 + j*(140) +-2 + j*(-152) +75 + j*(-168) +-134 + j*(-34) +45 + j*(155) +-164 + j*(135) +334 + j*(281) +-71 + j*(-170) +296 + j*(-413) +44 + j*(260) +197 + j*(204) +71 + j*(2) +119 + j*(-129) +169 + j*(68) +-196 + j*(198) +170 + j*(-124) +-120 + j*(-8) +102 + j*(-120) +-578 + j*(93) +71 + j*(239) +-218 + j*(91) +-206 + j*(9) +-287 + j*(-461) +-260 + j*(-65) +28 + j*(-45) +-26 + j*(132) +-86 + j*(-8) +0 + j*(-16) +-86 + j*(499) +-49 + j*(352) +14 + j*(108) +299 + j*(-55) +-255 + j*(-81) +-375 + j*(228) +-125 + j*(66) +-107 + j*(159) +-199 + j*(-283) +158 + j*(-206) +241 + j*(-91) +-44 + j*(4) +-288 + j*(127) +-19 + j*(-119) +83 + j*(-223) +76 + j*(-191) +-19 + j*(64) +205 + j*(-267) +209 + j*(100) +290 + j*(175) +96 + j*(12) +71 + j*(15) +231 + j*(70) +127 + j*(-37) +-153 + j*(195) +29 + j*(189) +-30 + j*(-94) +-55 + j*(-209) +338 + j*(-214) +122 + j*(-64) +-234 + j*(172) +160 + j*(-110) +142 + j*(114) +157 + j*(136) +-189 + j*(-197) +28 + j*(-45) +-42 + j*(-143) +171 + j*(-12) +-168 + j*(163) +-199 + j*(194) +-265 + j*(-212) +181 + j*(-21) +-267 + j*(-224) +-191 + j*(110) +-77 + j*(-215) +83 + j*(-106) +-52 + j*(451) +-60 + j*(92) +-171 + j*(-199) +233 + j*(-231) +-107 + j*(39) +151 + j*(42) +120 + j*(-6) +-257 + j*(-182) +110 + j*(-52) +-208 + j*(-26) +-130 + j*(-157) +153 + j*(267) +494 + j*(-45) +178 + j*(-91) +-59 + j*(-184) +137 + j*(318) +-315 + j*(254) +-264 + j*(-67) +42 + j*(-4) +102 + j*(62) +-43 + j*(-23) +-132 + j*(79) +-163 + j*(-138) +-132 + j*(-232) +106 + j*(50) +264 + j*(56) +-172 + j*(-100) +318 + j*(147) +84 + j*(-246) +274 + j*(-330) +177 + j*(19) +185 + j*(81) +201 + j*(18) +-306 + j*(110) +81 + j*(-6) +65 + j*(-186) +-278 + j*(-66) +175 + j*(55) +8 + j*(107) +-85 + j*(14) +300 + j*(395) +-65 + j*(-403) +293 + j*(-56) +-187 + j*(103) +66 + j*(-240) +66 + j*(-302) +-82 + j*(-214) +194 + j*(-47) +64 + j*(-235) +-372 + j*(-222) +119 + j*(-341) +-323 + j*(40) +-114 + j*(293) +-208 + j*(-158) +-95 + j*(183) +161 + j*(231) +47 + j*(-131) +102 + j*(-31) +205 + j*(-180) +-40 + j*(-127) +175 + j*(-288) +79 + j*(-272) +-245 + j*(3) +251 + j*(-3) +-119 + j*(243) +-123 + j*(-339) +-290 + j*(85) +-100 + j*(-175) +-205 + j*(477) +-24 + j*(-71) +342 + j*(-185) +66 + j*(13) +-56 + j*(78) +175 + j*(-124) +-228 + j*(117) +-122 + j*(-62) +72 + j*(308) +222 + j*(-223) +85 + j*(47) +-59 + j*(173) +-97 + j*(142) +141 + j*(-108) +-278 + j*(107) +-141 + j*(75) +211 + j*(74) +319 + j*(-107) +-98 + j*(209) +-350 + j*(45) +-468 + j*(-308) +332 + j*(-157) +-10 + j*(-57) +21 + j*(-37) +1 + j*(-71) +151 + j*(18) +-356 + j*(361) +7 + j*(-8) +-87 + j*(-148) +205 + j*(-86) +-9 + j*(85) +419 + j*(64) +80 + j*(60) +199 + j*(197) +-187 + j*(-205) +-119 + j*(228) +11 + j*(187) +-212 + j*(-21) +-160 + j*(121) +45 + j*(-420) +-158 + j*(-173) +49 + j*(286) +204 + j*(54) +158 + j*(206) +-1 + j*(-63) +119 + j*(9) +169 + j*(-116) +325 + j*(145) +-106 + j*(6) +-96 + j*(44) +-140 + j*(253) +138 + j*(23) +-431 + j*(-37) +-72 + j*(5) +-35 + j*(128) +-165 + j*(75) +-45 + j*(-158) +298 + j*(119) +105 + j*(119) +162 + j*(-16) +64 + j*(-173) +-269 + j*(37) +110 + j*(-21) +-16 + j*(30) +113 + j*(129) +-164 + j*(-238) +-189 + j*(62) +66 + j*(-142) +418 + j*(20) +-264 + j*(-245) +-251 + j*(76) +24 + j*(-4) +310 + j*(-84) +-112 + j*(-76) +-20 + j*(27) +270 + j*(-126) +-241 + j*(46) +-258 + j*(123) +-195 + j*(-302) +294 + j*(-168) +83 + j*(-46) +-121 + j*(-111) +-297 + j*(-122) +-269 + j*(32) +-171 + j*(-107) +-89 + j*(336) +-180 + j*(-263) +-163 + j*(-48) +265 + j*(-103) +33 + j*(22) +448 + j*(99) +-49 + j*(85) +259 + j*(-72) +13 + j*(7) +-156 + j*(11) +-112 + j*(186) +91 + j*(-44) +127 + j*(110) +190 + j*(-151) +26 + j*(-373) +115 + j*(177) +99 + j*(-327) +60 + j*(-87) +-42 + j*(-71) +80 + j*(132) +173 + j*(276) +6 + j*(177) +46 + j*(-154) +6 + j*(115) +132 + j*(156) +-303 + j*(257) +105 + j*(-506) +293 + j*(82) +23 + j*(62) +-563 + j*(397) +308 + j*(17) +-16 + j*(-53) +-22 + j*(-210) +256 + j*(190) +-40 + j*(308) +181 + j*(37) +-179 + j*(-71) +-42 + j*(37) +-258 + j*(375) +-81 + j*(115) +-59 + j*(287) +-66 + j*(122) +-1 + j*(-218) +258 + j*(-6) +78 + j*(-95) +97 + j*(-148) +-255 + j*(165) +226 + j*(0) +39 + j*(-141) +175 + j*(111) +21 + j*(110) +-93 + j*(288) +-240 + j*(-11) +-163 + j*(77) +25 + j*(110) +70 + j*(78) +51 + j*(425) +-74 + j*(-186) +121 + j*(-54) +270 + j*(64) +115 + j*(-173) +-143 + j*(281) +88 + j*(-247) +-20 + j*(-112) +156 + j*(-362) +33 + j*(-128) +97 + j*(-328) +28 + j*(-41) +58 + j*(47) +45 + j*(13) +206 + j*(560) +94 + j*(-16) +81 + j*(41) +270 + j*(13) +68 + j*(95) +-33 + j*(-120) +-173 + j*(-166) +-64 + j*(124) +17 + j*(-88) +99 + j*(13) +-380 + j*(6) +-65 + j*(219) +-16 + j*(-51) +35 + j*(146) +138 + j*(74) +453 + j*(-59) +337 + j*(-5) +-218 + j*(-105) +-360 + j*(-43) +99 + j*(-1) +-12 + j*(-76) +-183 + j*(221) +52 + j*(13) +86 + j*(-76) +-265 + j*(-12) +61 + j*(-264) +-29 + j*(91) +20 + j*(-177) +89 + j*(-281) +276 + j*(-13) +243 + j*(-251) +-140 + j*(-55) +173 + j*(23) +-14 + j*(-109) +59 + j*(57) +238 + j*(-78) +50 + j*(124) +132 + j*(70) +-358 + j*(21) +-228 + j*(51) +-16 + j*(-243) +-40 + j*(267) +49 + j*(231) +309 + j*(8) +32 + j*(-109) +-147 + j*(190) +232 + j*(-166) +-190 + j*(-117) +18 + j*(-43) +-54 + j*(129) +145 + j*(110) +-202 + j*(-232) +-16 + j*(64) +-320 + j*(354) +69 + j*(-96) +-233 + j*(165) +-93 + j*(-98) +-182 + j*(-310) +144 + j*(-146) +192 + j*(6) +112 + j*(146) +214 + j*(352) +-153 + j*(44) +-218 + j*(-5) +-76 + j*(110) +18 + j*(-194) +-23 + j*(-85) +-4 + j*(-256) +8 + j*(1) +49 + j*(111) +-108 + j*(-100) +-47 + j*(214) +-72 + j*(143) +-351 + j*(212) +-51 + j*(62) +-96 + j*(173) +-56 + j*(-223) +101 + j*(-143) +245 + j*(-344) +-74 + j*(103) +381 + j*(-153) +76 + j*(271) +-126 + j*(-9) +62 + j*(90) +72 + j*(459) +-132 + j*(-227) +-57 + j*(161) +-294 + j*(48) +-158 + j*(65) +-154 + j*(-49) +21 + j*(156) +-289 + j*(226) +45 + j*(79) +-156 + j*(61) +50 + j*(15) +-368 + j*(-200) +-202 + j*(64) +344 + j*(190) +31 + j*(139) +101 + j*(95) +-446 + j*(74) +254 + j*(-9) +175 + j*(28) +-158 + j*(115) +-173 + j*(-316) +-88 + j*(-179) +-18 + j*(-386) +112 + j*(144) +-368 + j*(250) +-233 + j*(-171) +-165 + j*(16) +-188 + j*(71) +-41 + j*(-57) +422 + j*(47) +62 + j*(-120) +18 + j*(4) +-103 + j*(-131) +-21 + j*(-190) +-205 + j*(-158) +268 + j*(151) +-250 + j*(156) +-142 + j*(-12) +99 + j*(237) +363 + j*(78) +108 + j*(-13) +291 + j*(-148) +-243 + j*(486) +177 + j*(33) +117 + j*(15) +-126 + j*(-1) +-185 + j*(-149) +115 + j*(108) +1 + j*(-47) +58 + j*(-262) +275 + j*(-234) +-83 + j*(155) +291 + j*(72) +-187 + j*(147) +57 + j*(14) +25 + j*(280) +318 + j*(23) +-229 + j*(223) +164 + j*(86) +293 + j*(100) +-52 + j*(-40) +87 + j*(118) +-8 + j*(4) +134 + j*(47) +250 + j*(376) +-73 + j*(64) +104 + j*(-39) +-305 + j*(-147) +-419 + j*(-16) +-41 + j*(8) +-83 + j*(-453) +-19 + j*(201) +-124 + j*(-91) +-175 + j*(-139) +25 + j*(144) +-28 + j*(303) +-339 + j*(57) +-139 + j*(319) +-141 + j*(11) +-109 + j*(-14) +-6 + j*(-254) +-8 + j*(80) +319 + j*(101) +94 + j*(-40) +-202 + j*(-161) +-329 + j*(-263) +-115 + j*(-208) +250 + j*(-221) +214 + j*(29) +297 + j*(-151) +21 + j*(-16) +3 + j*(204) +8 + j*(-18) +302 + j*(-215) +-216 + j*(-25) +-54 + j*(-63) +-113 + j*(-21) +-218 + j*(-19) +102 + j*(-134) +303 + j*(-272) +-199 + j*(-87) +-115 + j*(-137) +-52 + j*(16) +-153 + j*(-173) +228 + j*(428) +-43 + j*(-187) +149 + j*(-149) +-83 + j*(373) +-158 + j*(512) +-306 + j*(64) +-59 + j*(54) +-94 + j*(-110) +240 + j*(-116) +99 + j*(52) +262 + j*(-194) +-152 + j*(85) +-105 + j*(218) +-30 + j*(-55) +187 + j*(98) +308 + j*(-119) +54 + j*(-221) +103 + j*(175) +16 + j*(129) +149 + j*(-23) +95 + j*(7) +-267 + j*(-37) +2 + j*(283) +-237 + j*(30) +-28 + j*(-204) +18 + j*(10) +-25 + j*(-262) +-252 + j*(45) +-7 + j*(64) +139 + j*(325) +-44 + j*(-243) +-94 + j*(194) +132 + j*(192) +74 + j*(-332) +212 + j*(-189) +-20 + j*(83) +56 + j*(-45) +-371 + j*(-122) +10 + j*(134) +-163 + j*(69) +-305 + j*(35) +27 + j*(-186) +106 + j*(54) +226 + j*(8) +-185 + j*(50) +-3 + j*(-26) +11 + j*(136) +-360 + j*(-132) +192 + j*(-67) +189 + j*(-46) +-23 + j*(122) +-119 + j*(-45) +187 + j*(-186) +24 + j*(78) +21 + j*(-125) +433 + j*(-60) +180 + j*(-35) +-166 + j*(3) +44 + j*(134) +79 + j*(26) +-82 + j*(103) +-180 + j*(-40) +11 + j*(49) +147 + j*(132) +10 + j*(-36) +53 + j*(-157) +170 + j*(163) +71 + j*(213) +82 + j*(-135) +-56 + j*(-138) +41 + j*(-115) +-190 + j*(-4) +55 + j*(199) +-144 + j*(-113) +-397 + j*(-207) +-165 + j*(-22) +46 + j*(122) +-151 + j*(-102) +124 + j*(-79) +1 + j*(-262) +313 + j*(-66) +117 + j*(54) +110 + j*(-117) +-254 + j*(-152) +-2 + j*(-24) +-199 + j*(25) +-178 + j*(-133) +-164 + j*(88) +-18 + j*(-30) +-166 + j*(83) +18 + j*(-286) +230 + j*(100) +153 + j*(-115) +49 + j*(-59) +-39 + j*(-12) +-412 + j*(-168) +-151 + j*(293) +81 + j*(-356) +106 + j*(11) +101 + j*(-76) +-103 + j*(489) +60 + j*(327) +-254 + j*(-398) +-96 + j*(-74) +115 + j*(-133) +-114 + j*(91) +105 + j*(23) +-334 + j*(-8) +421 + j*(-191) +-281 + j*(-4) +49 + j*(-26) +83 + j*(-13) +102 + j*(202) +115 + j*(214) +-18 + j*(322) +201 + j*(161) +34 + j*(-37) +-204 + j*(181) +412 + j*(-41) +187 + j*(-15) +-11 + j*(95) +-8 + j*(-322) +-364 + j*(40) +-148 + j*(-52) +351 + j*(-114) +244 + j*(175) +-123 + j*(-182) +-59 + j*(-103) +-60 + j*(98) +-166 + j*(83) +-192 + j*(71) +-187 + j*(223) +-24 + j*(-272) +209 + j*(-320) +-45 + j*(-89) +438 + j*(-54) +-64 + j*(-235) +-346 + j*(-112) +-12 + j*(142) +-331 + j*(-138) +78 + j*(-123) +-274 + j*(28) +-6 + j*(-132) +-64 + j*(258) +159 + j*(-135) +146 + j*(-85) +-69 + j*(-122) +12 + j*(394) +-24 + j*(-233) +194 + j*(144) +105 + j*(-107) +47 + j*(33) +30 + j*(-122) +-27 + j*(-21) +-48 + j*(-248) +354 + j*(91) +-3 + j*(54) +-440 + j*(-37) +-127 + j*(198) +99 + j*(-142) +252 + j*(139) +-150 + j*(-184) +-355 + j*(-5) +192 + j*(243) +-107 + j*(259) +-95 + j*(81) +-345 + j*(40) +-207 + j*(-141) +47 + j*(76) +-118 + j*(66) +-161 + j*(128) +-1 + j*(186) +-45 + j*(-187) +106 + j*(224) +-48 + j*(-237) +35 + j*(-229) +-55 + j*(-293) +-54 + j*(-86) +-183 + j*(79) +-15 + j*(-41) +-122 + j*(231) +69 + j*(-17) +100 + j*(279) +320 + j*(76) +-68 + j*(-83) +107 + j*(-70) +-94 + j*(158) +-93 + j*(122) +-141 + j*(22) +65 + j*(91) +-390 + j*(-91) +-216 + j*(35) +37 + j*(-191) +-57 + j*(14) +57 + j*(-288) +378 + j*(344) +42 + j*(448) +38 + j*(66) +-76 + j*(-260) +298 + j*(-250) +13 + j*(-370) +156 + j*(-169) +72 + j*(-215) +173 + j*(289) +194 + j*(130) +-23 + j*(202) +-22 + j*(298) +148 + j*(-113) +-131 + j*(-168) +339 + j*(107) +172 + j*(245) +-136 + j*(-105) +-186 + j*(-156) +-67 + j*(221) +-139 + j*(-42) +151 + j*(247) +-13 + j*(24) +41 + j*(139) +-165 + j*(185) +-55 + j*(-143) +35 + j*(-252) +-148 + j*(349) +-147 + j*(-26) +36 + j*(-332) +-58 + j*(-306) +-152 + j*(107) +157 + j*(-163) +-195 + j*(68) +241 + j*(282) +18 + j*(-115) +211 + j*(-32) +185 + j*(309) +-76 + j*(122) +114 + j*(6) +-58 + j*(-52) +-161 + j*(-116) +6 + j*(159) +141 + j*(173) +-134 + j*(-146) +-243 + j*(250) +38 + j*(221) +-122 + j*(-24) +-37 + j*(454) +-119 + j*(-127) +122 + j*(-71) +52 + j*(-101) +63 + j*(-133) +8 + j*(-279) +214 + j*(-154) +-467 + j*(110) +78 + j*(6) +-216 + j*(-87) +-147 + j*(-160) +-38 + j*(161) +124 + j*(245) +-56 + j*(-250) +-70 + j*(-132) +-235 + j*(117) +-25 + j*(36) +67 + j*(-18) +115 + j*(-83) +88 + j*(278) +-175 + j*(-8) +285 + j*(-65) +29 + j*(-49) +-42 + j*(-153) +-23 + j*(-26) +153 + j*(-66) +-218 + j*(251) +-37 + j*(228) +-21 + j*(30) +101 + j*(-76) +-5 + j*(-206) +49 + j*(37) +-100 + j*(-129) +3 + j*(-216) +9 + j*(49) +247 + j*(13) +-20 + j*(99) +-19 + j*(134) +-2 + j*(144) +153 + j*(112) +362 + j*(91) +-74 + j*(-28) +211 + j*(-182) +105 + j*(226) +-100 + j*(130) +37 + j*(16) +130 + j*(167) +-88 + j*(-218) +143 + j*(84) +31 + j*(35) +212 + j*(390) +1 + j*(-293) +-12 + j*(-161) +-49 + j*(-143) +-91 + j*(-130) +6 + j*(-74) +-59 + j*(185) +-177 + j*(92) +-19 + j*(25) +-232 + j*(-138) +110 + j*(103) +-40 + j*(131) +3 + j*(-152) +-55 + j*(105) +260 + j*(-247) +286 + j*(-23) +98 + j*(-16) +54 + j*(33) +-358 + j*(-16) +-146 + j*(107) +-249 + j*(-199) +-158 + j*(87) +-72 + j*(-110) +133 + j*(-196) +-141 + j*(354) +71 + j*(-152) +159 + j*(192) +-162 + j*(62) +182 + j*(344) +-2 + j*(14) +-293 + j*(321) +-41 + j*(-82) +-24 + j*(225) +-17 + j*(-158) +-37 + j*(103) +42 + j*(-50) +-33 + j*(229) +-22 + j*(54) +-105 + j*(-125) +343 + j*(298) +-211 + j*(231) +75 + j*(-85) +181 + j*(-33) +194 + j*(205) +-36 + j*(103) +-325 + j*(-103) +-148 + j*(-293) +-143 + j*(-52) +-294 + j*(16) +-147 + j*(-192) +-132 + j*(64) +-75 + j*(-105) +-279 + j*(-113) +15 + j*(-10) +103 + j*(-361) +45 + j*(315) +-8 + j*(-119) +-352 + j*(-97) +-8 + j*(-74) +-363 + j*(112) +-196 + j*(67) +226 + j*(-40) +235 + j*(117) +-140 + j*(47) +33 + j*(161) +149 + j*(162) +-468 + j*(-17) +-270 + j*(-72) +-335 + j*(-178) +-23 + j*(184) +156 + j*(361) +184 + j*(177) +151 + j*(141) +-100 + j*(-231) +-2 + j*(71) +-3 + j*(103) +230 + j*(105) +50 + j*(306) +-194 + j*(216) +101 + j*(-252) +-187 + j*(88) +-114 + j*(43) +6 + j*(124) +-143 + j*(-50) +-237 + j*(33) +115 + j*(144) +-112 + j*(-465) +86 + j*(-54) +-125 + j*(-146) +127 + j*(-179) +175 + j*(-162) +146 + j*(-141) +-272 + j*(-158) +107 + j*(168) +48 + j*(143) +-42 + j*(-18) +33 + j*(83) +-213 + j*(269) +58 + j*(-211) +-140 + j*(100) +29 + j*(-171) +311 + j*(-104) +-13 + j*(127) +-55 + j*(110) +-191 + j*(4) +-16 + j*(93) +-338 + j*(255) +103 + j*(55) +-88 + j*(-111) +41 + j*(49) +191 + j*(124) +145 + j*(163) +18 + j*(-132) +-46 + j*(81) +-59 + j*(-154) +277 + j*(179) +199 + j*(104) +40 + j*(4) +-46 + j*(28) +-13 + j*(-26) +89 + j*(11) +-56 + j*(91) +-228 + j*(-152) +-7 + j*(64) +122 + j*(-274) +151 + j*(-303) +-273 + j*(-251) +-60 + j*(264) +49 + j*(-74) +-56 + j*(-255) +445 + j*(210) +33 + j*(-155) +-271 + j*(-182) +-36 + j*(-136) +8 + j*(-16) +-204 + j*(-123) +-124 + j*(33) +-139 + j*(32) +90 + j*(-192) +282 + j*(83) +48 + j*(-245) +129 + j*(98) +-54 + j*(344) +-18 + j*(252) +-279 + j*(-146) +-115 + j*(-52) +79 + j*(192) +132 + j*(22) +-103 + j*(-162) +-42 + j*(64) +9 + j*(-185) +-132 + j*(-54) +9 + j*(129) +211 + j*(50) +-164 + j*(-13) +258 + j*(-100) +194 + j*(145) +-420 + j*(-276) +27 + j*(-30) +-106 + j*(74) +-71 + j*(378) +-296 + j*(178) +190 + j*(175) +217 + j*(-64) +455 + j*(-68) +69 + j*(144) +216 + j*(6) +25 + j*(39) +39 + j*(78) +-31 + j*(134) +165 + j*(-6) +-160 + j*(-95) +185 + j*(-281) +71 + j*(402) +-155 + j*(414) +159 + j*(-88) +302 + j*(-307) +73 + j*(-36) +-81 + j*(215) +142 + j*(-110) +103 + j*(-156) +195 + j*(-28) +185 + j*(167) +-89 + j*(117) +-147 + j*(-75) +118 + j*(-332) +-7 + j*(104) +211 + j*(-114) +201 + j*(-291) +49 + j*(88) +159 + j*(-75) +-327 + j*(-508) +26 + j*(13) +-387 + j*(-252) +148 + j*(-234) +23 + j*(-49) +78 + j*(-138) +189 + j*(-103) +-20 + j*(117) +-33 + j*(6) +149 + j*(-153) +-85 + j*(-231) +-127 + j*(135) +-136 + j*(-206) +-73 + j*(69) +-134 + j*(7) +-264 + j*(-69) +-82 + j*(89) +-248 + j*(127) +30 + j*(-12) +-138 + j*(-164) +123 + j*(-185) +237 + j*(-33) +-187 + j*(-103) +-115 + j*(-215) +28 + j*(347) +220 + j*(131) +281 + j*(-134) +-107 + j*(110) +133 + j*(-53) +204 + j*(132) +-85 + j*(289) +235 + j*(-135) +-145 + j*(153) +-87 + j*(332) +-213 + j*(-73) +-153 + j*(-220) +-214 + j*(-223) +59 + j*(-12) +48 + j*(-79) +11 + j*(8) +-46 + j*(-181) +94 + j*(141) +39 + j*(-21) +70 + j*(-293) +145 + j*(13) +32 + j*(-18) +134 + j*(129) +-110 + j*(-243) +-127 + j*(292) +4 + j*(209) +-139 + j*(-44) +-21 + j*(-40) +35 + j*(-84) +-316 + j*(-268) +-195 + j*(166) +-95 + j*(-24) +233 + j*(-18) +240 + j*(-88) +-66 + j*(-143) +155 + j*(9) +266 + j*(235) +-94 + j*(-28) +117 + j*(35) +-189 + j*(9) +-205 + j*(40) +-74 + j*(252) +-141 + j*(150) +-29 + j*(-57) +49 + j*(103) +-57 + j*(251) +109 + j*(95) +284 + j*(-16) +11 + j*(-96) +-289 + j*(-351) +-6 + j*(-222) +355 + j*(118) +-139 + j*(179) +-143 + j*(137) +88 + j*(-86) +243 + j*(-131) +117 + j*(-6) +-489 + j*(70) +74 + j*(245) +93 + j*(88) +-62 + j*(54) +218 + j*(176) +-146 + j*(-126) +28 + j*(-53) +86 + j*(13) +203 + j*(153) +150 + j*(74) +200 + j*(320) +95 + j*(142) +58 + j*(156) +345 + j*(-52) +-59 + j*(462) +-22 + j*(-43) +-160 + j*(141) +313 + j*(-104) +-190 + j*(-67) +25 + j*(-103) +-305 + j*(17) +53 + j*(-52) +-36 + j*(-101) +-67 + j*(-47) +-198 + j*(202) +231 + j*(-218) +-62 + j*(146) +68 + j*(-172) +-148 + j*(-134) +-32 + j*(-184) +-378 + j*(88) +-248 + j*(12) +-37 + j*(-68) +11 + j*(44) +-19 + j*(-67) +215 + j*(262) +-190 + j*(229) +-277 + j*(62) +140 + j*(-204) +-219 + j*(-9) +78 + j*(-64) +249 + j*(16) +-1 + j*(-115) +58 + j*(276) +-94 + j*(-193) +80 + j*(-61) +333 + j*(77) +150 + j*(233) +-251 + j*(-255) +0 + j*(340) +-205 + j*(-45) +80 + j*(-305) +112 + j*(-45) +-28 + j*(-1) +-1 + j*(22) +125 + j*(-304) +-276 + j*(-24) +-28 + j*(-177) +117 + j*(197) +192 + j*(-29) +40 + j*(158) +-304 + j*(-122) +-84 + j*(-35) +160 + j*(-28) +36 + j*(110) +119 + j*(7) +-35 + j*(-127) +8 + j*(33) +161 + j*(48) +-65 + j*(158) +-237 + j*(-220) +-65 + j*(-294) +157 + j*(155) +-8 + j*(-296) +18 + j*(-273) +173 + j*(-16) +136 + j*(23) +85 + j*(156) +1 + j*(144) +147 + j*(-281) +-95 + j*(94) +-69 + j*(-103) +165 + j*(-25) +-196 + j*(257) +80 + j*(195) +31 + j*(-11) +-267 + j*(-69) +-208 + j*(-127) +-180 + j*(-87) +-90 + j*(48) +69 + j*(-47) +-163 + j*(-314) +-4 + j*(-166) +-45 + j*(460) +-5 + j*(-4) +105 + j*(-238) +-240 + j*(158) +-145 + j*(72) +95 + j*(-35) +-4 + j*(-213) +14 + j*(182) +-33 + j*(123) +-385 + j*(170) +32 + j*(-27) +-19 + j*(-164) +-245 + j*(68) +-16 + j*(-67) +226 + j*(88) +-130 + j*(-112) +4 + j*(-4) +-320 + j*(54) +-154 + j*(-131) +184 + j*(33) +137 + j*(-269) +148 + j*(-68) +-93 + j*(-13) +94 + j*(-280) +35 + j*(98) +-104 + j*(-165) +-71 + j*(-84) +293 + j*(-71) +247 + j*(159) +-91 + j*(-63) +-95 + j*(246) +-124 + j*(49) +-158 + j*(227) +-146 + j*(-84) +-185 + j*(-206) +101 + j*(129) +-45 + j*(-361) +-140 + j*(115) +8 + j*(-83) +-426 + j*(-45) +365 + j*(-120) +-115 + j*(98) +-247 + j*(192) +23 + j*(39) +-22 + j*(205) +30 + j*(40) +196 + j*(-71) +-74 + j*(193) +76 + j*(-51) +-123 + j*(-93) +-37 + j*(-251) +-26 + j*(170) +-263 + j*(43) +-42 + j*(-224) +214 + j*(153) +-33 + j*(86) +-137 + j*(158) +148 + j*(122) +68 + j*(26) +341 + j*(-75) +121 + j*(96) +74 + j*(-235) +25 + j*(-41) +50 + j*(141) +-183 + j*(69) +74 + j*(-94) +119 + j*(-129) +55 + j*(5) +-132 + j*(267) +-167 + j*(-24) +-273 + j*(139) +270 + j*(59) +-114 + j*(-62) +46 + j*(63) +-74 + j*(42) +378 + j*(-223) +27 + j*(122) +121 + j*(372) +278 + j*(116) +-33 + j*(-276) +9 + j*(-49) +-403 + j*(138) +-5 + j*(342) +-109 + j*(-95) +-31 + j*(-43) +62 + j*(-186) +163 + j*(-233) +-28 + j*(144) +194 + j*(93) +69 + j*(-206) +180 + j*(-120) +-72 + j*(-62) +-52 + j*(-166) +81 + j*(128) +239 + j*(-315) +30 + j*(-97) +194 + j*(-300) +26 + j*(197) +12 + j*(-54) +-13 + j*(146) +322 + j*(55) +-341 + j*(-282) +29 + j*(-225) +-91 + j*(7) +-160 + j*(64) +7 + j*(-127) +28 + j*(-158) +-97 + j*(283) +-276 + j*(62) +-53 + j*(-362) +59 + j*(18) +227 + j*(-390) +-86 + j*(132) +-105 + j*(-513) +-87 + j*(29) +35 + j*(-110) +18 + j*(47) +180 + j*(-45) +-112 + j*(5) +44 + j*(-31) +-144 + j*(66) +-284 + j*(187) +-373 + j*(183) +66 + j*(-160) +378 + j*(209) +-360 + j*(-33) +-181 + j*(-174) +31 + j*(-209) +66 + j*(-187) +-224 + j*(-27) +-118 + j*(-124) +16 + j*(156) +-29 + j*(163) +-112 + j*(69) +-10 + j*(191) +114 + j*(-103) +8 + j*(16) +-132 + j*(105) +-221 + j*(211) +-187 + j*(-11) +100 + j*(-49) +-27 + j*(52) +-62 + j*(1) +48 + j*(-86) +-243 + j*(296) +-307 + j*(-22) +47 + j*(-23) +-126 + j*(-111) +-93 + j*(-12) +-46 + j*(-265) +71 + j*(-1) +-52 + j*(42) +-180 + j*(344) +78 + j*(-95) +-167 + j*(-28) +-293 + j*(196) +247 + j*(63) +112 + j*(383) +225 + j*(-232) +97 + j*(-60) +-57 + j*(-233) +-180 + j*(-136) +130 + j*(-187) +-62 + j*(-65) +13 + j*(14) +-9 + j*(267) +-243 + j*(-458) +21 + j*(267) +-57 + j*(-45) +-148 + j*(130) +86 + j*(251) +-366 + j*(93) +-375 + j*(302) +107 + j*(-11) +-12 + j*(-207) +198 + j*(-397) +-346 + j*(15) +-19 + j*(177) +28 + j*(-23) +-87 + j*(-81) +-164 + j*(-117) +-184 + j*(42) +-43 + j*(231) +-49 + j*(-143) +-209 + j*(-252) +-344 + j*(171) +261 + j*(200) +210 + j*(2) +-78 + j*(18) +120 + j*(-31) +-46 + j*(37) +105 + j*(228) +252 + j*(-62) +76 + j*(190) +-200 + j*(-88) +112 + j*(31) +97 + j*(46) +-14 + j*(191) +122 + j*(70) +-110 + j*(132) +52 + j*(-151) +-161 + j*(69) +74 + j*(228) +-170 + j*(41) +-59 + j*(-354) +-98 + j*(325) +64 + j*(-64) +-235 + j*(175) +-230 + j*(-93) +83 + j*(-48) +-274 + j*(-86) +133 + j*(-92) +-118 + j*(190) +-192 + j*(232) +107 + j*(226) +-178 + j*(-91) +-45 + j*(35) +212 + j*(194) +38 + j*(-66) +2 + j*(142) +156 + j*(296) +-62 + j*(38) +34 + j*(-358) +-133 + j*(-114) +94 + j*(80) +-299 + j*(41) +23 + j*(264) +-223 + j*(515) +-82 + j*(-98) +-180 + j*(175) +-160 + j*(-163) +-42 + j*(81) +-110 + j*(-93) +-95 + j*(-186) +-182 + j*(-190) +29 + j*(-227) +36 + j*(107) +-25 + j*(-239) +-147 + j*(-128) +214 + j*(178) +-144 + j*(-26) +-162 + j*(210) +-1 + j*(-170) +-182 + j*(76) +-214 + j*(272) +209 + j*(112) +-335 + j*(199) +202 + j*(93) +192 + j*(-119) +-160 + j*(65) +231 + j*(-61) +-37 + j*(-151) +77 + j*(114) +293 + j*(34) +-203 + j*(-176) +-164 + j*(142) +-233 + j*(269) +-45 + j*(227) +313 + j*(74) +-52 + j*(210) +-396 + j*(-31) +-111 + j*(-95) +-11 + j*(83) +112 + j*(246) +-59 + j*(95) +196 + j*(121) +-364 + j*(-285) +139 + j*(284) +-301 + j*(-78) +-274 + j*(-334) +-413 + j*(-324) +25 + j*(-57) +-251 + j*(-60) +552 + j*(-140) +98 + j*(559) +452 + j*(-165) +334 + j*(-16) +-477 + j*(-221) +-273 + j*(82) +-170 + j*(127) +600 + j*(348) +412 + j*(187) +392 + j*(393) +356 + j*(-431) +-303 + j*(-270) +-383 + j*(388) +107 + j*(-441) +-371 + j*(155) +385 + j*(398) +-262 + j*(-58) +244 + j*(-265) +494 + j*(359) +-245 + j*(214) +141 + j*(-274) +281 + j*(-645) +252 + j*(222) +-252 + j*(-163) +-350 + j*(371) +143 + j*(-293) +-426 + j*(-419) +107 + j*(-83) +-183 + j*(-363) +431 + j*(-91) +-557 + j*(-171) +-7 + j*(576) +393 + j*(-195) +-415 + j*(387) +95 + j*(-383) +56 + j*(156) +223 + j*(433) +-670 + j*(232) +-78 + j*(192) +327 + j*(187) +-47 + j*(-198) +-47 + j*(379) +158 + j*(-204) +170 + j*(40) +120 + j*(-402) +-57 + j*(-609) +363 + j*(197) +572 + j*(240) +159 + j*(277) +51 + j*(594) +284 + j*(-165) +-221 + j*(406) +-83 + j*(-173) +248 + j*(-268) +-106 + j*(67) +-233 + j*(330) +-208 + j*(-184) +414 + j*(-62) +-170 + j*(609) +-309 + j*(177) +278 + j*(-119) +611 + j*(251) +-67 + j*(438) +354 + j*(87) +344 + j*(225) +388 + j*(190) +386 + j*(273) +-235 + j*(-399) +450 + j*(89) +-129 + j*(-380) +307 + j*(-317) +6 + j*(454) +-21 + j*(683) +382 + j*(607) +26 + j*(269) +397 + j*(394) +525 + j*(-202) +-373 + j*(-337) +607 + j*(363) +142 + j*(235) +320 + j*(-230) +276 + j*(223) +-82 + j*(-39) +-41 + j*(374) +298 + j*(313) +-453 + j*(136) +-487 + j*(-484) +-50 + j*(214) +-265 + j*(259) +-185 + j*(-32) +-268 + j*(6) +335 + j*(414) +-385 + j*(-177) +-438 + j*(-168) +-153 + j*(475) +-93 + j*(223) +-279 + j*(283) +481 + j*(-119) +2 + j*(-363) +571 + j*(346) +342 + j*(143) +-379 + j*(175) +-30 + j*(-334) +-431 + j*(237) +113 + j*(-408) +420 + j*(-398) +-101 + j*(-35) +-363 + j*(77) +-421 + j*(129) +378 + j*(166) +-316 + j*(-40) +402 + j*(-251) +22 + j*(-351) +223 + j*(-376) +273 + j*(599) +-213 + j*(30) +269 + j*(-317) +209 + j*(357) +-156 + j*(517) +97 + j*(504) +296 + j*(-239) +65 + j*(1) +278 + j*(342) +-175 + j*(-567) +325 + j*(-247) +-455 + j*(-64) +512 + j*(-163) +148 + j*(542) +183 + j*(273) +-224 + j*(53) +327 + j*(256) +124 + j*(-139) +63 + j*(124) +-57 + j*(-381) +112 + j*(-13) +269 + j*(-236) +-104 + j*(-487) +-227 + j*(-422) +434 + j*(-423) +387 + j*(-274) +-118 + j*(110) +197 + j*(342) +-96 + j*(300) +413 + j*(-33) +-184 + j*(-374) +451 + j*(68) +435 + j*(-132) +-244 + j*(-332) +482 + j*(296) +500 + j*(-520) +41 + j*(-66) +-137 + j*(678) +-433 + j*(361) +-573 + j*(576) +-350 + j*(255) +-185 + j*(-711) +491 + j*(403) +-203 + j*(-359) +36 + j*(-153) +-199 + j*(-299) +312 + j*(-607) +17 + j*(82) +-284 + j*(311) +-651 + j*(349) +-317 + j*(-525) +461 + j*(-175) +-272 + j*(-30) +-433 + j*(392) +-204 + j*(242) +-132 + j*(330) +37 + j*(-193) +461 + j*(-472) +-188 + j*(-404) +136 + j*(434) +489 + j*(-688) +-261 + j*(-331) +-79 + j*(323) +-181 + j*(-231) +236 + j*(483) +294 + j*(-152) +118 + j*(-52) +286 + j*(299) +353 + j*(-41) +-250 + j*(262) +-332 + j*(385) +-1 + j*(-199) +547 + j*(-29) +135 + j*(307) +150 + j*(348) +-211 + j*(386) +-124 + j*(-317) +197 + j*(289) +6 + j*(224) +-571 + j*(327) +-127 + j*(-331) +164 + j*(-490) +-211 + j*(428) +507 + j*(99) +1 + j*(-32) +-378 + j*(-261) +396 + j*(-520) +-180 + j*(332) +318 + j*(119) +-143 + j*(364) +-177 + j*(527) +-141 + j*(47) +180 + j*(104) +-38 + j*(-321) +185 + j*(353) +-414 + j*(250) +29 + j*(-441) +-202 + j*(247) +16 + j*(62) +432 + j*(467) +-206 + j*(175) +94 + j*(-132) +321 + j*(369) +705 + j*(170) +346 + j*(512) +-368 + j*(-420) +53 + j*(117) +98 + j*(-211) +-267 + j*(251) +366 + j*(144) +630 + j*(144) +-187 + j*(333) +-271 + j*(566) +-344 + j*(-87) +437 + j*(316) +-181 + j*(423) +-280 + j*(90) +497 + j*(226) +-191 + j*(-57) +334 + j*(122) +-228 + j*(309) +412 + j*(-351) +289 + j*(193) +194 + j*(124) +293 + j*(-198) +-175 + j*(343) +-222 + j*(-327) +40 + j*(-205) +357 + j*(-335) +-131 + j*(-187) +5 + j*(-491) +38 + j*(330) +6 + j*(274) +207 + j*(113) +-339 + j*(-238) +245 + j*(-246) +-46 + j*(-59) +-375 + j*(-393) +-231 + j*(515) +53 + j*(262) +-224 + j*(190) +-363 + j*(-43) +224 + j*(150) +122 + j*(-337) +-296 + j*(-264) +73 + j*(445) +-217 + j*(359) +-270 + j*(-305) +-342 + j*(526) +286 + j*(-655) +-216 + j*(410) +606 + j*(368) +540 + j*(347) +-66 + j*(-136) +149 + j*(342) +64 + j*(-315) +-483 + j*(-236) +-313 + j*(-325) +-150 + j*(238) +-175 + j*(-165) +-239 + j*(409) +166 + j*(-18) +282 + j*(-151) +-202 + j*(-446) +452 + j*(360) +-205 + j*(-263) +-283 + j*(320) +-358 + j*(266) +170 + j*(28) +-288 + j*(-393) +97 + j*(423) +122 + j*(425) +-6 + j*(146) +144 + j*(-282) +368 + j*(413) +-320 + j*(410) +-513 + j*(-503) +237 + j*(-528) +-398 + j*(254) +-237 + j*(474) +-128 + j*(499) +233 + j*(396) +262 + j*(404) +240 + j*(-390) +-372 + j*(245) +-313 + j*(-37) +-99 + j*(-187) +-301 + j*(-677) +-321 + j*(120) +294 + j*(-131) +276 + j*(-228) +-313 + j*(-604) +-140 + j*(-262) +-437 + j*(-173) +98 + j*(192) +235 + j*(394) +256 + j*(-503) +336 + j*(383) +138 + j*(277) +-56 + j*(260) +-305 + j*(-528) +206 + j*(59) +221 + j*(191) +552 + j*(-141) +15 + j*(434) +223 + j*(24) +56 + j*(325) +-49 + j*(238) +-410 + j*(270) +11 + j*(-322) +-91 + j*(-492) +-315 + j*(-44) +-165 + j*(-332) +242 + j*(108) +29 + j*(226) +95 + j*(-47) +-218 + j*(-109) +251 + j*(-426) +-332 + j*(213) +33 + j*(443) +207 + j*(-475) +148 + j*(-1) +-147 + j*(-504) +-158 + j*(1) +378 + j*(15) +-612 + j*(-174) +255 + j*(182) +240 + j*(-387) +-206 + j*(176) +523 + j*(-181) +241 + j*(-255) +-362 + j*(-265) +84 + j*(100) +-299 + j*(165) +291 + j*(192) +-109 + j*(-377) +-72 + j*(532) +-86 + j*(-276) +250 + j*(489) +-301 + j*(-421) +187 + j*(401) +-241 + j*(58) +-369 + j*(-199) +23 + j*(501) +-194 + j*(-318) +-278 + j*(578) +552 + j*(223) +-197 + j*(-253) +231 + j*(-304) +-33 + j*(-308) +296 + j*(437) +-462 + j*(445) +57 + j*(-146) +-127 + j*(94) +98 + j*(21) +392 + j*(-337) +-290 + j*(244) +-216 + j*(434) +112 + j*(-111) +1 + j*(-450) +294 + j*(115) +-486 + j*(-211) +-293 + j*(-436) +-181 + j*(315) +231 + j*(375) +192 + j*(-240) +200 + j*(-343) +-310 + j*(34) +-459 + j*(-279) +-173 + j*(-120) +391 + j*(-253) +-197 + j*(-226) +224 + j*(-334) +-604 + j*(325) +-18 + j*(-379) +269 + j*(-285) +454 + j*(483) +-172 + j*(-185) +-479 + j*(135) +319 + j*(275) +423 + j*(-495) +-319 + j*(315) +22 + j*(466) +-86 + j*(-120) +224 + j*(198) +210 + j*(-262) +106 + j*(170) +-293 + j*(220) +491 + j*(524) +128 + j*(525) +-318 + j*(419) +352 + j*(-143) +-196 + j*(130) +-222 + j*(317) +302 + j*(-421) +388 + j*(-199) +-243 + j*(395) +87 + j*(397) +-383 + j*(296) +99 + j*(-499) +-97 + j*(-214) +279 + j*(-408) +-428 + j*(-327) +250 + j*(-131) +260 + j*(110) +-346 + j*(323) +-204 + j*(341) +-344 + j*(-276) +266 + j*(-33) +-482 + j*(-466) +-284 + j*(10) +-331 + j*(236) +66 + j*(272) +-415 + j*(227) +16 + j*(81) +-647 + j*(671) +-20 + j*(93) +-130 + j*(-244) +-272 + j*(74) +-243 + j*(379) +168 + j*(-558) +-49 + j*(264) +-257 + j*(231) +-298 + j*(231) +235 + j*(496) +263 + j*(77) +-192 + j*(250) +110 + j*(87) +-301 + j*(49) +391 + j*(-658) +482 + j*(-317) +267 + j*(-197) +89 + j*(-107) +240 + j*(-375) +-354 + j*(-299) +-441 + j*(-1) +113 + j*(-134) +530 + j*(-79) +405 + j*(-101) +476 + j*(45) +460 + j*(145) +332 + j*(-77) +-86 + j*(-153) +74 + j*(-574) +-298 + j*(-58) +-220 + j*(-371) +438 + j*(192) +-325 + j*(175) +-132 + j*(-379) +225 + j*(96) +307 + j*(-55) +-137 + j*(303) +-112 + j*(423) +-327 + j*(-241) +-329 + j*(351) +62 + j*(-287) +372 + j*(-214) +426 + j*(-216) +176 + j*(-170) +-449 + j*(-296) +522 + j*(-1) +-66 + j*(396) +-223 + j*(92) +228 + j*(165) +-233 + j*(105) +-272 + j*(-164) +248 + j*(121) +-518 + j*(20) +-65 + j*(-497) +-272 + j*(118) +166 + j*(-117) +-279 + j*(-284) +426 + j*(-590) +-317 + j*(346) +197 + j*(421) +552 + j*(181) +-163 + j*(290) +253 + j*(-554) +60 + j*(16) +-336 + j*(-438) +-154 + j*(-322) +-202 + j*(188) +-177 + j*(-8) +-427 + j*(-361) +-353 + j*(27) +406 + j*(119) +-326 + j*(-155) +170 + j*(-190) +-235 + j*(59) +-67 + j*(287) +106 + j*(438) +192 + j*(-505) +173 + j*(-77) +-147 + j*(-275) +-683 + j*(342) +-411 + j*(433) +307 + j*(4) +-506 + j*(44) +322 + j*(-171) +337 + j*(-151) +276 + j*(332) +-269 + j*(293) +-8 + j*(151) +-552 + j*(216) +-168 + j*(-276) +195 + j*(-460) +287 + j*(645) +-132 + j*(-112) +681 + j*(355) +336 + j*(-137) +-539 + j*(-412) +82 + j*(433) +-363 + j*(-254) +-175 + j*(311) +-180 + j*(155) +759 + j*(222) +-756 + j*(387) +598 + j*(11) +-66 + j*(47) +354 + j*(-71) +-262 + j*(-247) +-397 + j*(14) +400 + j*(-116) +141 + j*(132) +387 + j*(38) +269 + j*(-296) +457 + j*(54) +-173 + j*(85) +-370 + j*(191) +53 + j*(-285) +-457 + j*(-389) +60 + j*(-470) +384 + j*(-293) +-405 + j*(139) +-138 + j*(168) +-107 + j*(-69) +334 + j*(-50) +210 + j*(-148) +268 + j*(-327) +-325 + j*(316) +-157 + j*(3) +-202 + j*(-96) +-214 + j*(244) +-336 + j*(-150) +495 + j*(-384) +380 + j*(283) +-184 + j*(-419) +293 + j*(339) +178 + j*(67) +-156 + j*(249) +-563 + j*(407) +-561 + j*(185) +-93 + j*(-275) +-299 + j*(363) +356 + j*(482) +301 + j*(163) +-518 + j*(-438) +-379 + j*(-109) +-474 + j*(438) +486 + j*(180) +204 + j*(648) +-122 + j*(190) +-387 + j*(-214) +10 + j*(238) +124 + j*(406) +420 + j*(-313) +-163 + j*(110) +-330 + j*(-315) +303 + j*(262) +371 + j*(189) +452 + j*(-500) +430 + j*(-48) +-10 + j*(129) +-278 + j*(136) +-366 + j*(420) +163 + j*(-250) +337 + j*(-217) +326 + j*(473) +-353 + j*(-308) +-11 + j*(-25) +106 + j*(-86) +237 + j*(325) +368 + j*(340) +53 + j*(-92) +116 + j*(-206) +163 + j*(206) +-122 + j*(185) +282 + j*(-407) +-41 + j*(35) +-279 + j*(110) +-204 + j*(4) +42 + j*(236) +-190 + j*(66) +2 + j*(-25) +-112 + j*(-47) +35 + j*(-76) +165 + j*(293) +-218 + j*(-17) +-69 + j*(-71) +-158 + j*(48) +88 + j*(-57) +-67 + j*(-9) +-144 + j*(-40) +-216 + j*(218) +-161 + j*(88) +100 + j*(89) +226 + j*(219) +-10 + j*(0) +96 + j*(-326) +79 + j*(-63) +-82 + j*(219) +345 + j*(69) +486 + j*(-264) +-37 + j*(11) +373 + j*(-105) +-292 + j*(-99) +214 + j*(-145) +-187 + j*(-156) +-96 + j*(-194) +-200 + j*(-57) +-134 + j*(-142) +152 + j*(-251) +-112 + j*(25) +-33 + j*(179) +-177 + j*(-7) +-245 + j*(1) +-114 + j*(122) +-9 + j*(-83) +-157 + j*(132) +-173 + j*(-385) +-25 + j*(308) +280 + j*(-180) +-240 + j*(-129) +-286 + j*(-115) +-184 + j*(161) +180 + j*(-82) +-2 + j*(383) +-139 + j*(192) +112 + j*(-71) +178 + j*(-163) +104 + j*(15) +-103 + j*(-185) +-207 + j*(197) +-78 + j*(108) +86 + j*(60) +52 + j*(296) +-240 + j*(-98) +-9 + j*(150) +107 + j*(-222) +281 + j*(223) +-79 + j*(-42) +49 + j*(-105) +-157 + j*(84) +42 + j*(-150) +80 + j*(-23) +178 + j*(-237) +269 + j*(119) +-438 + j*(-72) +-51 + j*(-114) +-279 + j*(-76) +130 + j*(97) +-125 + j*(138) +100 + j*(-168) +-332 + j*(155) +112 + j*(413) +175 + j*(-136) +-450 + j*(77) +34 + j*(51) +-140 + j*(257) +170 + j*(-117) +-275 + j*(-221) +30 + j*(361) +0 + j*(35) +-165 + j*(-214) +227 + j*(186) +326 + j*(363) +175 + j*(11) +-52 + j*(51) +153 + j*(-244) +0 + j*(-8) +-78 + j*(68) +25 + j*(-67) +88 + j*(7) +-204 + j*(216) +117 + j*(127) +-214 + j*(-161) +192 + j*(285) +-366 + j*(13) +185 + j*(92) +-117 + j*(-243) +132 + j*(0) +141 + j*(9) +-138 + j*(-232) +-107 + j*(147) +175 + j*(-41) +35 + j*(47) +175 + j*(-52) +109 + j*(-82) +-18 + j*(-75) +94 + j*(47) +76 + j*(111) +59 + j*(-148) +137 + j*(168) +-24 + j*(171) +-44 + j*(262) +-299 + j*(-66) +130 + j*(-274) +64 + j*(-99) +10 + j*(-214) +-251 + j*(330) +-77 + j*(-100) +-239 + j*(226) +-83 + j*(-61) +-240 + j*(162) +-475 + j*(173) +-32 + j*(-143) +112 + j*(238) +-8 + j*(-178) +-95 + j*(247) +-33 + j*(87) +-302 + j*(298) +202 + j*(69) +33 + j*(-87) +-184 + j*(-31) +234 + j*(220) +122 + j*(-123) +-64 + j*(155) +106 + j*(115) +161 + j*(56) +72 + j*(243) +-27 + j*(47) +-3 + j*(-138) +-302 + j*(-216) +156 + j*(-93) +-139 + j*(-104) +-316 + j*(45) +-161 + j*(345) +-354 + j*(110) +-79 + j*(155) +193 + j*(21) +31 + j*(-125) +-119 + j*(-205) +35 + j*(21) +-75 + j*(241) +23 + j*(-146) +224 + j*(-222) +-171 + j*(231) +-61 + j*(-42) +-372 + j*(102) +-19 + j*(-151) +368 + j*(89) +318 + j*(-52) +-327 + j*(-301) +47 + j*(57) +-243 + j*(-231) +-461 + j*(59) +118 + j*(-65) +67 + j*(202) +402 + j*(-226) +-123 + j*(-42) +-127 + j*(325) +-24 + j*(-166) +185 + j*(161) +111 + j*(-74) +-44 + j*(-95) +-290 + j*(137) +-125 + j*(-220) +54 + j*(-77) +70 + j*(46) +153 + j*(-112) +17 + j*(170) +-185 + j*(77) +193 + j*(140) +-388 + j*(150) +-381 + j*(-216) +-11 + j*(262) +-130 + j*(8) +149 + j*(-19) +240 + j*(134) +101 + j*(-161) +147 + j*(-86) +101 + j*(51) +110 + j*(-91) +67 + j*(126) +122 + j*(-72) +-100 + j*(-166) +146 + j*(-159) +-175 + j*(208) +-90 + j*(-16) +-288 + j*(-130) +-256 + j*(-168) +-29 + j*(62) +68 + j*(95) +18 + j*(95) +147 + j*(-91) +-11 + j*(162) +136 + j*(35) +98 + j*(33) +-180 + j*(308) +171 + j*(-5) +-114 + j*(25) +-30 + j*(-217) +-88 + j*(184) +45 + j*(91) +214 + j*(-21) +91 + j*(348) +-92 + j*(-296) +-58 + j*(96) +38 + j*(-119) +-202 + j*(135) +-28 + j*(-60) +-123 + j*(31) +102 + j*(12) +-132 + j*(217) +-28 + j*(245) +-267 + j*(5) +41 + j*(249) +-21 + j*(-147) +102 + j*(-320) +-274 + j*(-25) +156 + j*(-100) +100 + j*(-124) +-136 + j*(275) +320 + j*(-35) +-115 + j*(104) +-11 + j*(-205) +-254 + j*(-291) +-9 + j*(-318) +-97 + j*(195) +279 + j*(29) +269 + j*(227) +67 + j*(-39) +-136 + j*(241) +-96 + j*(-19) +250 + j*(-127) +84 + j*(-129) +228 + j*(90) +-98 + j*(23) +-46 + j*(-4) +42 + j*(47) +-15 + j*(-37) +-122 + j*(-230) +67 + j*(163) +176 + j*(-43) +82 + j*(-132) +115 + j*(157) +86 + j*(33) +-325 + j*(-20) +-115 + j*(77) +-33 + j*(-4) +197 + j*(161) +88 + j*(33) +-55 + j*(72) +113 + j*(-60) +135 + j*(132) +9 + j*(291) +-468 + j*(99) +122 + j*(-105) +95 + j*(-26) +29 + j*(-37) +40 + j*(-100) +-100 + j*(26) +-369 + j*(228) +86 + j*(-67) +-47 + j*(-98) +52 + j*(-129) +271 + j*(-58) +131 + j*(-315) +-78 + j*(361) +-2 + j*(-98) +143 + j*(-180) +78 + j*(123) +-77 + j*(-190) +-92 + j*(-76) +151 + j*(71) +-47 + j*(13) +246 + j*(-71) +-178 + j*(59) +134 + j*(-88) +243 + j*(-98) +-51 + j*(11) +244 + j*(45) +-66 + j*(127) +44 + j*(223) +145 + j*(-98) +-129 + j*(173) +-226 + j*(330) +264 + j*(168) +-93 + j*(27) +-146 + j*(-133) +-203 + j*(-310) +8 + j*(11) +378 + j*(112) +385 + j*(281) +182 + j*(-64) +35 + j*(158) +-199 + j*(-1) +-168 + j*(120) +192 + j*(-133) +-127 + j*(59) +-130 + j*(-279) +1 + j*(-224) +-70 + j*(-42) +61 + j*(80) +-13 + j*(-11) +-8 + j*(-95) +132 + j*(-240) +-215 + j*(-160) +191 + j*(133) +124 + j*(-373) +-161 + j*(-139) +110 + j*(-134) +-245 + j*(1) +-267 + j*(103) +-13 + j*(-384) +226 + j*(-58) +21 + j*(121) +-45 + j*(-400) +120 + j*(76) +69 + j*(35) +-111 + j*(40) +105 + j*(190) +164 + j*(161) +-268 + j*(-40) +177 + j*(-25) +-61 + j*(-80) +185 + j*(310) +-110 + j*(141) +20 + j*(187) +-299 + j*(-25) +-24 + j*(326) +-92 + j*(-335) +52 + j*(-324) +-342 + j*(-267) +-91 + j*(-10) +332 + j*(-119) +18 + j*(-219) +54 + j*(140) +333 + j*(237) +-201 + j*(207) +-99 + j*(294) +-49 + j*(-26) +306 + j*(-37) +-404 + j*(277) +22 + j*(-156) +348 + j*(-117) +62 + j*(197) +80 + j*(240) +-317 + j*(402) +226 + j*(-252) +-26 + j*(-31) +-107 + j*(65) +-45 + j*(7) +-237 + j*(-146) +-102 + j*(-73) +-199 + j*(63) +-196 + j*(-39) +68 + j*(50) +111 + j*(-71) +86 + j*(-13) +-69 + j*(44) +163 + j*(-116) +181 + j*(-127) +-115 + j*(527) +112 + j*(16) +-135 + j*(122) +124 + j*(28) +140 + j*(-145) +-149 + j*(-218) +51 + j*(-5) +66 + j*(315) +249 + j*(-198) +54 + j*(60) +283 + j*(227) +272 + j*(237) +228 + j*(53) +296 + j*(212) +-255 + j*(-52) +252 + j*(93) +49 + j*(-134) +279 + j*(54) +-21 + j*(-343) +-116 + j*(206) +-52 + j*(-47) +69 + j*(187) +21 + j*(93) +-28 + j*(-166) +-97 + j*(-161) +367 + j*(-90) +-39 + j*(53) +400 + j*(92) +381 + j*(-169) +-303 + j*(219) +2 + j*(58) +21 + j*(248) +-160 + j*(-125) +379 + j*(-387) +62 + j*(-31) +-126 + j*(-76) +-17 + j*(47) +29 + j*(45) +-286 + j*(-181) +21 + j*(103) +-117 + j*(29) +86 + j*(386) +-132 + j*(-129) +83 + j*(178) +243 + j*(-298) +144 + j*(-295) +111 + j*(-109) +-201 + j*(168) +55 + j*(-192) +-13 + j*(41) +-129 + j*(147) +-8 + j*(-37) +-39 + j*(32) +28 + j*(90) +323 + j*(-245) +107 + j*(-77) +-8 + j*(-421) +187 + j*(-118) +-54 + j*(-160) +-91 + j*(54) +215 + j*(267) +239 + j*(-159) +106 + j*(-174) +-106 + j*(349) +-153 + j*(33) +45 + j*(98) +-145 + j*(134) +-101 + j*(-190) +-331 + j*(40) +-167 + j*(-255) +129 + j*(-113) +112 + j*(250) +10 + j*(-317) +125 + j*(-106) +96 + j*(102) +238 + j*(-6) +-108 + j*(222) +-82 + j*(122) +-453 + j*(-377) +-97 + j*(139) +103 + j*(-56) +-425 + j*(28) +164 + j*(154) +152 + j*(-62) +74 + j*(320) +85 + j*(-80) +146 + j*(-23) +-291 + j*(-153) +-5 + j*(-3) +-155 + j*(23) +153 + j*(294) +59 + j*(-132) +5 + j*(153) +59 + j*(-105) +54 + j*(-325) +177 + j*(170) +-223 + j*(-124) +183 + j*(-128) +119 + j*(-180) +332 + j*(71) +-14 + j*(93) +199 + j*(81) +-101 + j*(-75) +7 + j*(-35) +-101 + j*(52) +219 + j*(-284) +-102 + j*(-143) +16 + j*(-176) +132 + j*(-16) +76 + j*(-266) +24 + j*(-6) +-81 + j*(8) +-240 + j*(362) +-54 + j*(-95) +490 + j*(-91) +201 + j*(-194) +-127 + j*(-102) +48 + j*(4) +250 + j*(-54) +146 + j*(-409) +260 + j*(-20) +-40 + j*(50) +-119 + j*(-64) +319 + j*(-222) +-88 + j*(-216) +157 + j*(191) +112 + j*(-34) +-222 + j*(-145) +-129 + j*(175) +71 + j*(134) +27 + j*(-133) +-87 + j*(-340) +-175 + j*(126) +76 + j*(54) +-261 + j*(172) +64 + j*(-37) +-10 + j*(-211) +30 + j*(169) +23 + j*(-247) +-204 + j*(-54) +67 + j*(63) +191 + j*(-223) +22 + j*(454) +-156 + j*(91) +-45 + j*(-122) +-23 + j*(-189) +-31 + j*(139) +138 + j*(-201) +-324 + j*(-299) +-88 + j*(158) +-8 + j*(-104) +93 + j*(-129) +112 + j*(-8) +75 + j*(-82) +279 + j*(182) +118 + j*(-400) +-162 + j*(89) +-398 + j*(58) +4 + j*(101) +-133 + j*(-206) +-42 + j*(-1) +-276 + j*(322) +-385 + j*(5) +56 + j*(43) +281 + j*(107) +-91 + j*(70) +31 + j*(33) +57 + j*(4) +71 + j*(-126) +129 + j*(175) +565 + j*(-270) +-211 + j*(40) +-54 + j*(216) +57 + j*(-281) +255 + j*(-197) +-21 + j*(190) +183 + j*(110) +-123 + j*(46) +111 + j*(45) +-381 + j*(100) +-296 + j*(153) +-214 + j*(-46) +-221 + j*(-68) +348 + j*(231) +247 + j*(24) +-38 + j*(263) +-146 + j*(-361) +51 + j*(271) +146 + j*(-119) +-86 + j*(-81) +-163 + j*(-21) +92 + j*(70) +159 + j*(139) +-301 + j*(54) +-13 + j*(-272) +-105 + j*(25) +-95 + j*(-56) +222 + j*(54) +250 + j*(-56) +354 + j*(-152) +139 + j*(59) +-126 + j*(-175) +332 + j*(-244) +-88 + j*(-8) +-214 + j*(-261) +-282 + j*(-13) +75 + j*(49) +-180 + j*(-13) +-69 + j*(66) +-161 + j*(-1) +51 + j*(-62) +26 + j*(-37) +-54 + j*(323) +264 + j*(-8) +-52 + j*(-44) +86 + j*(341) +-48 + j*(-54) +-469 + j*(167) +-436 + j*(-108) +-132 + j*(-14) +-134 + j*(74) +364 + j*(258) +22 + j*(156) +-40 + j*(293) +41 + j*(98) +-83 + j*(-12) +117 + j*(59) +89 + j*(216) +-9 + j*(146) +40 + j*(-132) +35 + j*(-151) +-178 + j*(-33) +-194 + j*(-57) +-85 + j*(206) +-134 + j*(256) +110 + j*(214) +204 + j*(-109) +236 + j*(-13) +113 + j*(-40) +-409 + j*(52) +-37 + j*(223) +139 + j*(61) +-145 + j*(212) +-97 + j*(161) +340 + j*(-211) +-184 + j*(13) +235 + j*(-4) +-237 + j*(-257) +81 + j*(49) +196 + j*(79) +84 + j*(131) +6 + j*(-95) +-291 + j*(426) +221 + j*(89) +-31 + j*(116) +74 + j*(260) +-156 + j*(47) +-261 + j*(-265) +-8 + j*(-291) +23 + j*(129) +89 + j*(87) +71 + j*(-16) +217 + j*(293) +-402 + j*(-98) +-1 + j*(4) +84 + j*(-253) +39 + j*(108) +175 + j*(301) +-257 + j*(81) +-289 + j*(-86) +-313 + j*(-76) +39 + j*(-79) +146 + j*(136) +218 + j*(33) +-217 + j*(31) +-11 + j*(237) +-117 + j*(56) +130 + j*(100) +178 + j*(416) +99 + j*(84) +165 + j*(-202) +61 + j*(-320) +-215 + j*(186) +-78 + j*(220) +-235 + j*(-151) +-60 + j*(107) +-40 + j*(45) +-119 + j*(-298) +250 + j*(-164) +-129 + j*(-186) +247 + j*(182) +52 + j*(238) +-23 + j*(165) +122 + j*(78) +161 + j*(-262) +-313 + j*(44) +1 + j*(-35) +1 + j*(-36) +13 + j*(-135) +-223 + j*(-115) +-320 + j*(303) +-268 + j*(-66) +-19 + j*(52) +-12 + j*(-124) +-28 + j*(42) +219 + j*(-94) +-272 + j*(-265) +-114 + j*(-81) +-107 + j*(28) +-129 + j*(-131) +-139 + j*(-63) +55 + j*(-259) +241 + j*(-81) +-159 + j*(43) +-125 + j*(221) +119 + j*(-114) +95 + j*(-36) +-213 + j*(-377) +109 + j*(-205) +332 + j*(69) +71 + j*(-182) +-28 + j*(-100) +95 + j*(-33) +134 + j*(201) +-81 + j*(245) +-41 + j*(-175) +-55 + j*(-212) +235 + j*(-14) +123 + j*(21) +-86 + j*(207) +-156 + j*(71) +-115 + j*(363) +339 + j*(-28) +-325 + j*(262) +188 + j*(-102) +112 + j*(189) +19 + j*(-39) +35 + j*(-77) +181 + j*(-13) +-77 + j*(-12) +202 + j*(66) +-254 + j*(-63) +150 + j*(131) +-136 + j*(42) +-238 + j*(-233) +467 + j*(-366) +-125 + j*(202) +-333 + j*(52) +-27 + j*(-125) +-224 + j*(4) +-52 + j*(246) +362 + j*(-105) +-151 + j*(-169) +175 + j*(36) +-5 + j*(-147) +-59 + j*(23) +222 + j*(86) +-9 + j*(-178) +95 + j*(-159) +-40 + j*(-3) +298 + j*(158) +-94 + j*(354) +48 + j*(33) +-42 + j*(-237) +120 + j*(115) +-9 + j*(-30) +172 + j*(42) +158 + j*(153) +-320 + j*(-88) +22 + j*(-382) +-199 + j*(-37) +234 + j*(-310) +-208 + j*(2) +40 + j*(16) +309 + j*(-85) +123 + j*(-172) +77 + j*(77) +-30 + j*(135) +-95 + j*(-40) +72 + j*(-25) +-43 + j*(37) +237 + j*(-185) +-68 + j*(-187) +-298 + j*(55) +105 + j*(-116) +82 + j*(81) +-107 + j*(-53) +18 + j*(156) +-170 + j*(257) +-93 + j*(128) +70 + j*(83) +-8 + j*(-257) +-46 + j*(-182) +-496 + j*(-38) +-16 + j*(-24) +-5 + j*(-170) +152 + j*(-168) +-338 + j*(-136) +-75 + j*(104) +265 + j*(119) +-146 + j*(231) +-310 + j*(0) +-7 + j*(-157) +-48 + j*(-255) +254 + j*(-21) +134 + j*(-4) +-101 + j*(146) +-236 + j*(-372) +-164 + j*(32) +122 + j*(177) +-180 + j*(108) +57 + j*(-165) +-6 + j*(255) +-75 + j*(123) +13 + j*(100) +-170 + j*(-28) +-135 + j*(173) +83 + j*(151) +-379 + j*(16) +-8 + j*(44) +-325 + j*(57) +186 + j*(129) +46 + j*(-37) +-185 + j*(39) +45 + j*(8) +-170 + j*(156) +95 + j*(231) +180 + j*(-313) +-371 + j*(-122) +-106 + j*(112) +23 + j*(303) +-59 + j*(-170) +45 + j*(84) +62 + j*(169) +-292 + j*(-88) +60 + j*(-78) +-204 + j*(-129) +-61 + j*(18) +-118 + j*(-74) +-98 + j*(227) +170 + j*(201) +86 + j*(254) +119 + j*(98) +-173 + j*(129) +-62 + j*(71) +7 + j*(-236) +216 + j*(161) +-129 + j*(-50) +-182 + j*(43) +-54 + j*(-159) +113 + j*(-342) +107 + j*(-122) +-175 + j*(-31) +30 + j*(112) +42 + j*(-136) +123 + j*(-122) +46 + j*(-36) +22 + j*(-10) +124 + j*(356) +297 + j*(-171) +-27 + j*(284) +317 + j*(-117) +-34 + j*(-349) +177 + j*(16) +-259 + j*(112) +-161 + j*(-250) +-232 + j*(43) +-240 + j*(-83) +-162 + j*(370) +-13 + j*(253) +-77 + j*(-49) +-6 + j*(-209) +-88 + j*(219) +-211 + j*(107) +147 + j*(25) +-273 + j*(36) +-139 + j*(-117) +-177 + j*(52) +223 + j*(170) +139 + j*(-26) +168 + j*(-164) +124 + j*(143) +23 + j*(-224) +-54 + j*(-113) +243 + j*(-158) +-97 + j*(42) +-169 + j*(-34) +-30 + j*(110) +317 + j*(6) +173 + j*(317) +-210 + j*(-268) +-126 + j*(11) +56 + j*(-126) +78 + j*(-158) +-82 + j*(133) +-133 + j*(-240) +-180 + j*(-79) +-80 + j*(115) +-25 + j*(-201) +371 + j*(11) +-68 + j*(202) +-231 + j*(-102) +-69 + j*(-87) +-294 + j*(327) +-95 + j*(-16) +-231 + j*(-69) +53 + j*(240) +-58 + j*(84) +-94 + j*(90) +141 + j*(176) +-90 + j*(-110) +-153 + j*(-4) +-58 + j*(126) +-67 + j*(13) +92 + j*(-43) +-13 + j*(-36) +-139 + j*(-202) +-228 + j*(-331) +180 + j*(34) +-257 + j*(458) +-211 + j*(111) +-337 + j*(83) +40 + j*(-76) +40 + j*(-325) +-4 + j*(-22) +-124 + j*(2) +112 + j*(-317) +204 + j*(82) +-4 + j*(-29) +112 + j*(-193) +-70 + j*(-98) +-99 + j*(144) +241 + j*(3) +-74 + j*(-40) +224 + j*(148) +216 + j*(69) +36 + j*(-23) +-28 + j*(-166) +40 + j*(157) +198 + j*(52) +-225 + j*(69) +77 + j*(-260) +-32 + j*(-78) +-313 + j*(-35) +138 + j*(28) +-10 + j*(102) +92 + j*(-91) +267 + j*(-384) +148 + j*(211) +-44 + j*(170) +-30 + j*(207) +125 + j*(51) +175 + j*(-47) +-23 + j*(-171) +-165 + j*(-109) +176 + j*(83) +-62 + j*(148) +124 + j*(-119) +-121 + j*(-276) +54 + j*(-243) +-163 + j*(-109) +1 + j*(-34) +-83 + j*(182) +35 + j*(146) +322 + j*(53) +-175 + j*(34) +-156 + j*(-173) +83 + j*(428) +195 + j*(-110) +70 + j*(-187) +259 + j*(107) +99 + j*(233) +-73 + j*(-90) +-73 + j*(52) +48 + j*(327) +108 + j*(-49) +218 + j*(-158) +-22 + j*(-165) +296 + j*(-61) +-22 + j*(91) +-109 + j*(92) +26 + j*(-6) +-75 + j*(41) +52 + j*(187) +82 + j*(184) +42 + j*(116) +-71 + j*(228) +-72 + j*(190) +-218 + j*(-179) +156 + j*(284) +-151 + j*(0) +191 + j*(-107) +-35 + j*(-240) +245 + j*(-145) +-96 + j*(-74) +146 + j*(168) +-59 + j*(-107) +-114 + j*(115) +60 + j*(-71) +93 + j*(5) +46 + j*(142) +-16 + j*(63) +-232 + j*(151) +-312 + j*(-18) +182 + j*(-24) +227 + j*(221) +-200 + j*(-145) +251 + j*(254) +25 + j*(-163) +-110 + j*(-184) +-256 + j*(173) +-83 + j*(56) +184 + j*(-23) +-12 + j*(-21) +-228 + j*(15) +35 + j*(-117) +-6 + j*(25) +77 + j*(-12) +-243 + j*(-4) +29 + j*(-12) +-221 + j*(71) +-30 + j*(40) +100 + j*(-631) +-146 + j*(-156) +310 + j*(94) +33 + j*(76) +-184 + j*(168) +-2 + j*(56) +-76 + j*(57) +-37 + j*(93) +266 + j*(3) +127 + j*(-191) +284 + j*(-4) +63 + j*(248) +327 + j*(-94) +-276 + j*(119) +-351 + j*(2) +379 + j*(6) +-80 + j*(163) +135 + j*(59) +-156 + j*(0) +228 + j*(-18) +566 + j*(-95) +375 + j*(-13) +-68 + j*(-289) +-250 + j*(-154) +98 + j*(79) +-4 + j*(0) +-165 + j*(153) +-36 + j*(285) +70 + j*(-14) +-155 + j*(74) +45 + j*(8) +123 + j*(14) +-197 + j*(232) +-250 + j*(58) +-124 + j*(319) +125 + j*(0) +10 + j*(-142) +137 + j*(-70) +-180 + j*(146) +280 + j*(77) +-252 + j*(-92) +35 + j*(13) +-135 + j*(366) +104 + j*(37) +-84 + j*(-117) +11 + j*(-238) +74 + j*(-181) +134 + j*(21) +-64 + j*(-122) +-344 + j*(-146) +194 + j*(-158) +-59 + j*(-111) +-286 + j*(-121) +-225 + j*(71) +-93 + j*(-153) +94 + j*(21) +1 + j*(323) +1 + j*(138) +-59 + j*(-13) +5 + j*(-44) +-55 + j*(47) +-45 + j*(126) +-136 + j*(105) +-420 + j*(-415) +-1 + j*(-133) +-259 + j*(-263) +-106 + j*(-181) +-112 + j*(-18) +18 + j*(318) +-173 + j*(162) +-166 + j*(7) +11 + j*(-161) +326 + j*(3) +90 + j*(301) +-198 + j*(-94) +151 + j*(-48) +-272 + j*(103) +97 + j*(15) +-125 + j*(52) +378 + j*(-346) +40 + j*(-30) +-98 + j*(-186) +207 + j*(339) +42 + j*(-130) +-16 + j*(13) +-33 + j*(49) +140 + j*(193) +-49 + j*(233) +-106 + j*(-242) +-207 + j*(-18) +177 + j*(-38) +-520 + j*(-117) +60 + j*(40) +-327 + j*(279) +342 + j*(-58) +-39 + j*(-69) +-127 + j*(-42) +235 + j*(-59) +-267 + j*(46) +71 + j*(130) +-88 + j*(45) +282 + j*(-4) +219 + j*(-82) +-122 + j*(-25) +-76 + j*(169) +284 + j*(124) +4 + j*(-43) +83 + j*(-349) +43 + j*(342) +31 + j*(-173) +345 + j*(250) +-18 + j*(177) +-81 + j*(155) +355 + j*(156) +-93 + j*(-11) +141 + j*(3) +-83 + j*(77) +340 + j*(-164) +-117 + j*(59) +94 + j*(189) +127 + j*(-243) +-284 + j*(-161) +-19 + j*(-133) +182 + j*(86) +-153 + j*(97) +-16 + j*(-69) +197 + j*(-16) +-18 + j*(29) +8 + j*(-72) +-95 + j*(312) +-76 + j*(-127) +93 + j*(-103) +-127 + j*(16) +78 + j*(329) +-69 + j*(111) +182 + j*(192) +43 + j*(-180) +-77 + j*(81) +-91 + j*(-274) +-136 + j*(57) +29 + j*(-122) +291 + j*(-81) +-227 + j*(127) +-165 + j*(227) +61 + j*(-100) +-80 + j*(-31) +-211 + j*(-145) +-168 + j*(-113) +-40 + j*(68) +259 + j*(121) +111 + j*(-69) +245 + j*(47) +11 + j*(-61) +-136 + j*(104) +3 + j*(-161) +-105 + j*(-15) +122 + j*(-453) +-36 + j*(-18) +-148 + j*(243) +78 + j*(-107) +181 + j*(276) +276 + j*(-42) +179 + j*(-117) +-103 + j*(397) +250 + j*(-53) +-25 + j*(184) +108 + j*(-56) +171 + j*(-1) +217 + j*(178) +-149 + j*(-189) +-134 + j*(-218) +76 + j*(402) +-10 + j*(139) +100 + j*(236) +61 + j*(-177) +27 + j*(9) +151 + j*(38) +-110 + j*(-92) +222 + j*(-115) +118 + j*(-158) +94 + j*(118) +494 + j*(197) +-16 + j*(-27) +-307 + j*(-13) +-81 + j*(262) +231 + j*(192) +278 + j*(21) +56 + j*(-35) +-328 + j*(316) +130 + j*(32) +-37 + j*(209) +306 + j*(51) +113 + j*(114) +-228 + j*(-101) +-45 + j*(22) +-106 + j*(-86) +-188 + j*(-74) +124 + j*(57) +-70 + j*(-83) +-216 + j*(-23) +-87 + j*(-109) +97 + j*(-263) +78 + j*(90) +-15 + j*(256) +-103 + j*(350) +21 + j*(-25) +32 + j*(115) +76 + j*(-270) +190 + j*(-41) +8 + j*(195) +127 + j*(-100) +-8 + j*(-132) +253 + j*(-117) +-100 + j*(5) +-57 + j*(-319) +-18 + j*(82) +163 + j*(231) +-127 + j*(-271) +-74 + j*(-243) +39 + j*(-278) +-88 + j*(179) +-100 + j*(-33) +-373 + j*(-333) +-182 + j*(-299) +-117 + j*(-78) +34 + j*(-185) +-117 + j*(155) +-28 + j*(56) +-161 + j*(-70) +-97 + j*(-310) +-30 + j*(13) +-254 + j*(33) +119 + j*(8) +333 + j*(46) +-383 + j*(27) +83 + j*(188) +73 + j*(-217) +59 + j*(60) +-166 + j*(266) +-177 + j*(123) +-356 + j*(-55) +-339 + j*(-30) +-143 + j*(49) +105 + j*(-224) +-173 + j*(305) +-35 + j*(202) +-185 + j*(-152) +-221 + j*(132) +-244 + j*(-58) +104 + j*(276) +-182 + j*(21) +117 + j*(-134) +285 + j*(-66) +33 + j*(-86) +91 + j*(-28) +6 + j*(50) +83 + j*(-8) +-185 + j*(60) +-32 + j*(-94) +-179 + j*(9) +-323 + j*(136) +15 + j*(-417) +197 + j*(-105) +-71 + j*(74) +6 + j*(-117) +184 + j*(407) +123 + j*(-37) +57 + j*(12) +-52 + j*(168) +-188 + j*(-119) +28 + j*(-129) +-78 + j*(-1) +-104 + j*(-83) +1 + j*(-223) +-468 + j*(42) +157 + j*(52) +-144 + j*(-72) +75 + j*(296) +45 + j*(-285) +-221 + j*(301) +-103 + j*(163) +-341 + j*(-457) +105 + j*(23) +-23 + j*(-88) +-264 + j*(-552) +81 + j*(4) +-274 + j*(-131) +214 + j*(-18) +151 + j*(-214) +-1 + j*(-205) +103 + j*(-49) +81 + j*(-8) +-80 + j*(16) +246 + j*(-183) +136 + j*(-100) +35 + j*(-69) +-217 + j*(254) +252 + j*(-156) +-47 + j*(-160) +-162 + j*(167) +-148 + j*(-201) +265 + j*(-240) +-141 + j*(-8) +35 + j*(33) +-99 + j*(-95) +-4 + j*(124) +65 + j*(-206) +-175 + j*(279) +-1 + j*(114) +-52 + j*(71) +-103 + j*(47) +-164 + j*(-41) +206 + j*(216) +-148 + j*(19) +-161 + j*(-187) +-200 + j*(223) +131 + j*(238) +18 + j*(101) +229 + j*(22) +71 + j*(53) +509 + j*(-293) +139 + j*(161) +-322 + j*(180) +119 + j*(196) +12 + j*(103) +10 + j*(-187) +104 + j*(-28) +82 + j*(50) +86 + j*(125) +117 + j*(59) +-225 + j*(129) +167 + j*(-177) +-125 + j*(-100) +-178 + j*(-124) +-144 + j*(-262) +457 + j*(-237) +-267 + j*(22) +240 + j*(22) +155 + j*(89) +-6 + j*(-361) +266 + j*(-358) +-180 + j*(110) +-73 + j*(69) +-42 + j*(93) +-257 + j*(-151) +3 + j*(141) +192 + j*(356) +26 + j*(-76) +103 + j*(340) +83 + j*(70) +75 + j*(-245) +206 + j*(340) +-144 + j*(360) +344 + j*(76) +-74 + j*(325) +-7 + j*(208) +-238 + j*(-206) +25 + j*(83) +57 + j*(-286) +-82 + j*(232) +251 + j*(-76) +-218 + j*(-234) +-170 + j*(-219) +-75 + j*(-252) +-112 + j*(259) +24 + j*(31) +-226 + j*(59) +-67 + j*(-4) +-344 + j*(-240) +-86 + j*(143) +37 + j*(-59) +54 + j*(-173) +-264 + j*(-52) +78 + j*(104) +-337 + j*(-103) +115 + j*(-144) +228 + j*(4) +93 + j*(-54) +15 + j*(-245) +118 + j*(-70) +-8 + j*(-69) +195 + j*(-202) +110 + j*(172) +-214 + j*(-326) +-74 + j*(199) +81 + j*(124) +59 + j*(141) +88 + j*(-178) +-28 + j*(22) +132 + j*(144) +71 + j*(-90) +101 + j*(-243) +-191 + j*(32) +-12 + j*(-52) +134 + j*(18) +-416 + j*(338) +98 + j*(-92) +-122 + j*(-18) +-123 + j*(-100) +-405 + j*(86) +59 + j*(260) +-272 + j*(201) +-129 + j*(320) +-214 + j*(35) +-24 + j*(9) +-137 + j*(88) +-46 + j*(-113) +-99 + j*(105) +-4 + j*(51) +-59 + j*(-19) +267 + j*(56) +77 + j*(-30) +66 + j*(61) +6 + j*(-23) +0 + j*(198) +-4 + j*(-117) +-58 + j*(5) +-141 + j*(143) +-4 + j*(100) +-150 + j*(-117) +88 + j*(-301) +-90 + j*(-31) +247 + j*(58) +-84 + j*(-112) +387 + j*(-145) +-50 + j*(-57) +-117 + j*(-25) +-103 + j*(102) +113 + j*(294) +248 + j*(142) +-61 + j*(-134) +-152 + j*(129) +106 + j*(-170) +-332 + j*(-23) +-168 + j*(206) +240 + j*(36) +-196 + j*(-146) +-400 + j*(67) +40 + j*(-26) +110 + j*(213) +-288 + j*(252) +53 + j*(206) +253 + j*(-489) +-428 + j*(390) +-426 + j*(339) +162 + j*(-463) +278 + j*(159) +-35 + j*(426) +-375 + j*(323) +-243 + j*(186) +230 + j*(325) +-340 + j*(-334) +-193 + j*(148) +-640 + j*(75) +-14 + j*(106) +-49 + j*(233) +93 + j*(225) +-23 + j*(-235) +-560 + j*(-476) +-494 + j*(412) +302 + j*(424) +122 + j*(255) +-317 + j*(320) +-47 + j*(-134) +-411 + j*(412) +-241 + j*(107) +-639 + j*(-566) +427 + j*(-136) +-165 + j*(-217) +515 + j*(471) +-91 + j*(-151) +405 + j*(221) +139 + j*(-260) +-82 + j*(151) +228 + j*(514) +-165 + j*(231) +425 + j*(-11) +-210 + j*(117) +-475 + j*(247) +-291 + j*(500) +18 + j*(-106) +443 + j*(57) +-283 + j*(348) +226 + j*(-305) +-211 + j*(-33) +412 + j*(-233) +-272 + j*(237) +-378 + j*(8) +299 + j*(-136) +182 + j*(-98) +-489 + j*(183) +41 + j*(286) +-64 + j*(226) +102 + j*(351) +375 + j*(471) +-121 + j*(252) +310 + j*(-366) +194 + j*(-442) +67 + j*(-332) +190 + j*(-188) +467 + j*(-81) +-313 + j*(-344) +-49 + j*(-161) +-589 + j*(85) +-91 + j*(187) +127 + j*(11) +-212 + j*(551) +350 + j*(7) +170 + j*(327) +-387 + j*(-363) +-190 + j*(-612) +207 + j*(319) +-121 + j*(315) +-401 + j*(161) +-432 + j*(209) +-467 + j*(-334) +276 + j*(90) +185 + j*(-222) +-506 + j*(490) +-455 + j*(-293) +-49 + j*(-448) +224 + j*(293) +427 + j*(-559) +-267 + j*(-164) +-23 + j*(-156) +-324 + j*(-267) +-215 + j*(-33) +98 + j*(-173) +-209 + j*(-255) +-197 + j*(431) +238 + j*(367) +47 + j*(-198) +-308 + j*(-1) +-173 + j*(119) +-134 + j*(-357) +-186 + j*(71) +198 + j*(-59) +66 + j*(298) +-412 + j*(45) +416 + j*(426) +127 + j*(231) +285 + j*(-231) +81 + j*(-380) +228 + j*(52) +-291 + j*(436) +-28 + j*(91) +331 + j*(-356) +-12 + j*(800) +-144 + j*(303) +-334 + j*(206) +316 + j*(250) +272 + j*(-503) +-192 + j*(-511) +298 + j*(-80) +23 + j*(-566) +480 + j*(-347) +222 + j*(-330) +148 + j*(256) +505 + j*(-419) +270 + j*(-203) +409 + j*(-450) +-115 + j*(325) +-101 + j*(-471) +-74 + j*(23) +-163 + j*(-351) +-3 + j*(354) +8 + j*(-183) +-196 + j*(132) +329 + j*(-443) +342 + j*(334) +-338 + j*(-366) +-143 + j*(-636) +464 + j*(-245) +-168 + j*(204) +216 + j*(252) +252 + j*(-243) +-81 + j*(342) +-196 + j*(233) +277 + j*(-301) +367 + j*(-276) +59 + j*(58) +163 + j*(398) +-68 + j*(144) +47 + j*(335) +504 + j*(-647) +-169 + j*(-404) +343 + j*(-343) +-452 + j*(90) +-189 + j*(175) +-70 + j*(322) +354 + j*(-152) +422 + j*(262) +-247 + j*(-209) +569 + j*(157) +75 + j*(-52) +-169 + j*(-175) +-334 + j*(16) +177 + j*(605) +434 + j*(-502) +-339 + j*(37) +57 + j*(-246) +437 + j*(249) +-235 + j*(-141) +-247 + j*(-356) +-54 + j*(-366) +-305 + j*(-142) +-237 + j*(164) +8 + j*(-373) +204 + j*(107) +-617 + j*(136) +429 + j*(-337) +-337 + j*(-326) +506 + j*(477) +161 + j*(-22) +149 + j*(231) +202 + j*(-274) +-176 + j*(-391) +-252 + j*(-400) +-28 + j*(167) +256 + j*(-452) +419 + j*(188) +-142 + j*(-805) +417 + j*(-392) +10 + j*(197) +-335 + j*(105) +-114 + j*(149) +-170 + j*(265) +-387 + j*(-233) +-444 + j*(-151) +119 + j*(451) +270 + j*(422) +591 + j*(-421) +-250 + j*(-196) +62 + j*(-338) +266 + j*(28) +-476 + j*(69) +71 + j*(-97) +-52 + j*(-268) +-136 + j*(-214) +223 + j*(633) +-518 + j*(220) +595 + j*(184) +160 + j*(124) +-304 + j*(-202) +246 + j*(187) +64 + j*(300) +368 + j*(108) +255 + j*(-130) +-220 + j*(-389) +-424 + j*(41) +508 + j*(16) +-334 + j*(-446) +-89 + j*(81) +-685 + j*(169) +273 + j*(-25) +110 + j*(374) +355 + j*(250) +-29 + j*(-200) +-298 + j*(-629) +-508 + j*(144) +319 + j*(-343) +103 + j*(-57) +-59 + j*(373) +282 + j*(-14) +-102 + j*(350) +147 + j*(14) +-185 + j*(35) +-260 + j*(220) +-337 + j*(-359) +357 + j*(182) +192 + j*(-279) +-293 + j*(-5) +257 + j*(217) +247 + j*(-105) +-5 + j*(-358) +252 + j*(-95) +69 + j*(-534) +-95 + j*(-283) +147 + j*(-37) +170 + j*(409) +394 + j*(452) +-110 + j*(-421) +-257 + j*(190) +-450 + j*(-209) +77 + j*(-546) +161 + j*(16) +337 + j*(-32) +543 + j*(145) +-306 + j*(-438) +-64 + j*(159) +-234 + j*(-197) +-445 + j*(-51) +-208 + j*(-62) +-275 + j*(228) +-445 + j*(-221) +524 + j*(-37) +204 + j*(516) +246 + j*(-404) +624 + j*(-243) +-118 + j*(264) +61 + j*(194) +-132 + j*(-127) +220 + j*(298) +-222 + j*(-282) +167 + j*(-286) +330 + j*(466) +501 + j*(0) +620 + j*(414) +134 + j*(-269) +-212 + j*(193) +373 + j*(-335) +-107 + j*(40) +342 + j*(-279) +-286 + j*(138) +190 + j*(238) +-321 + j*(-240) +-409 + j*(-247) +371 + j*(505) +247 + j*(272) +-223 + j*(-23) +111 + j*(349) +-177 + j*(306) +466 + j*(92) +-267 + j*(322) +301 + j*(231) +460 + j*(-168) +-155 + j*(-254) +-320 + j*(-181) +50 + j*(-330) +283 + j*(-357) +163 + j*(-354) +67 + j*(379) +-105 + j*(-199) +245 + j*(-296) +387 + j*(371) +56 + j*(57) +453 + j*(279) +-324 + j*(33) +-327 + j*(-474) +-238 + j*(308) +-28 + j*(-187) +-252 + j*(-229) +165 + j*(194) +509 + j*(434) +-337 + j*(518) +3 + j*(-243) +275 + j*(378) +237 + j*(-86) +245 + j*(192) +225 + j*(-257) +-325 + j*(-468) +-482 + j*(291) +-266 + j*(63) +-496 + j*(315) +408 + j*(-185) +-536 + j*(102) +-320 + j*(-224) +-404 + j*(16) +302 + j*(246) +-263 + j*(19) +308 + j*(-209) +8 + j*(363) +-605 + j*(-448) +266 + j*(347) +602 + j*(-82) +-276 + j*(-238) +296 + j*(111) +293 + j*(-229) +-233 + j*(-84) +186 + j*(-148) +193 + j*(365) +99 + j*(-303) +117 + j*(454) +-98 + j*(288) +-508 + j*(-424) +-370 + j*(650) +324 + j*(375) +415 + j*(-221) +-211 + j*(40) +258 + j*(-7) +-519 + j*(-225) +-303 + j*(112) +247 + j*(-286) +303 + j*(-456) +179 + j*(244) +29 + j*(-155) +321 + j*(458) +144 + j*(226) +-195 + j*(-434) +-52 + j*(-276) +-339 + j*(203) +-531 + j*(35) +-82 + j*(57) +-717 + j*(-362) +-407 + j*(227) +257 + j*(343) +140 + j*(-224) +403 + j*(195) +-177 + j*(469) +158 + j*(-312) +15 + j*(-269) +-363 + j*(262) +-36 + j*(-339) +342 + j*(-153) +-56 + j*(696) +298 + j*(197) +-93 + j*(134) +-14 + j*(501) +511 + j*(228) +-98 + j*(269) +235 + j*(417) +274 + j*(-367) +-327 + j*(228) +-27 + j*(148) +404 + j*(-207) +411 + j*(332) +449 + j*(276) +716 + j*(725) +42 + j*(429) +-163 + j*(527) +156 + j*(274) +-593 + j*(-375) +496 + j*(419) +277 + j*(-330) +513 + j*(-36) +175 + j*(-386) +134 + j*(-376) +-95 + j*(-299) +-179 + j*(57) +465 + j*(416) +342 + j*(317) +158 + j*(47) +-141 + j*(248) +-173 + j*(206) +-394 + j*(119) +392 + j*(136) +-315 + j*(195) +335 + j*(450) +176 + j*(8) +613 + j*(-317) +150 + j*(-186) +-403 + j*(-643) +133 + j*(-279) +41 + j*(-164) +276 + j*(-46) +298 + j*(396) +-260 + j*(-488) +-390 + j*(114) +32 + j*(375) +-470 + j*(216) +585 + j*(298) +-443 + j*(-373) +251 + j*(306) +-372 + j*(318) +-371 + j*(408) +-92 + j*(-80) +-286 + j*(14) +-351 + j*(59) +-21 + j*(366) +-197 + j*(-182) +-267 + j*(-47) +177 + j*(-265) +-443 + j*(-212) +470 + j*(0) +90 + j*(315) +-68 + j*(-222) +-506 + j*(-289) +-236 + j*(-293) +131 + j*(-98) +-257 + j*(174) +-37 + j*(-494) +-486 + j*(35) +195 + j*(-247) +325 + j*(-836) +-73 + j*(-497) +-91 + j*(531) +642 + j*(-362) +344 + j*(124) +-120 + j*(-199) +-50 + j*(-488) +1 + j*(-345) +285 + j*(103) +206 + j*(452) +176 + j*(433) +-323 + j*(427) +-442 + j*(340) +-362 + j*(-361) +417 + j*(-184) +-148 + j*(251) +-289 + j*(-111) +-426 + j*(-202) +-597 + j*(-365) +409 + j*(199) +227 + j*(339) +-284 + j*(-69) +282 + j*(-156) +40 + j*(473) +-271 + j*(-76) +-228 + j*(-424) +-44 + j*(-64) +28 + j*(371) +494 + j*(-400) +-192 + j*(368) +199 + j*(211) +-148 + j*(-41) +77 + j*(-412) +13 + j*(139) +350 + j*(-71) +40 + j*(117) +-59 + j*(320) +240 + j*(-369) +193 + j*(180) +25 + j*(-484) +416 + j*(-252) +323 + j*(-39) +201 + j*(-394) +-221 + j*(351) +375 + j*(-190) +249 + j*(562) +197 + j*(-238) +235 + j*(336) +296 + j*(-149) +-493 + j*(-477) +310 + j*(-543) +495 + j*(38) +-320 + j*(308) +-496 + j*(130) +-392 + j*(-78) +-478 + j*(103) +-346 + j*(-525) +-134 + j*(-368) +-247 + j*(-150) +-472 + j*(-18) +-354 + j*(40) +349 + j*(131) +-284 + j*(312) +308 + j*(189) +67 + j*(-427) +-1 + j*(-159) +362 + j*(-454) +219 + j*(262) +-53 + j*(-28) +-501 + j*(-225) +-359 + j*(547) +369 + j*(315) +-344 + j*(-361) +-492 + j*(403) +500 + j*(-291) +260 + j*(191) +194 + j*(-170) +324 + j*(280) +595 + j*(120) +185 + j*(123) +222 + j*(670) +-309 + j*(219) +-237 + j*(-138) +338 + j*(-388) +-223 + j*(100) +-140 + j*(-430) +685 + j*(115) +339 + j*(-9) +-100 + j*(-745) +-561 + j*(-101) +360 + j*(446) +191 + j*(-467) +-243 + j*(-378) +-107 + j*(-345) +21 + j*(620) +-223 + j*(-322) +409 + j*(-306) +-23 + j*(499) +-259 + j*(-576) +493 + j*(658) +180 + j*(118) +-378 + j*(198) +378 + j*(-53) +-554 + j*(-61) +-305 + j*(305) +95 + j*(415) +455 + j*(-305) +-275 + j*(-77) +390 + j*(-62) +-15 + j*(151) +-238 + j*(191) +-94 + j*(390) +369 + j*(262) +441 + j*(67) +439 + j*(-121) +315 + j*(66) +282 + j*(216) +-193 + j*(-280) +-194 + j*(625) +-240 + j*(231) +-228 + j*(68) +245 + j*(144) +-467 + j*(64) +23 + j*(523) +46 + j*(-216) +-248 + j*(390) +98 + j*(462) +-378 + j*(329) +410 + j*(211) +-81 + j*(277) +293 + j*(-16) +204 + j*(-506) +-78 + j*(151) +-88 + j*(455) +242 + j*(-62) +-426 + j*(-105) +-320 + j*(221) +84 + j*(-386) +398 + j*(565) +50 + j*(248) +-254 + j*(-37) +-179 + j*(479) +-59 + j*(30) +-225 + j*(253) +630 + j*(-185) +-76 + j*(-363) +136 + j*(-498) +289 + j*(-79) +315 + j*(-177) +367 + j*(60) +-131 + j*(-190) +-482 + j*(-127) +-68 + j*(220) +204 + j*(16) +-175 + j*(45) +421 + j*(180) +231 + j*(-324) +93 + j*(334) +-344 + j*(-599) +-257 + j*(-276) +-134 + j*(-98) +384 + j*(-203) +290 + j*(-177) +-82 + j*(-226) +-367 + j*(-1) +154 + j*(-307) +-155 + j*(576) +216 + j*(279) +229 + j*(196) +35 + j*(138) +-52 + j*(-210) +24 + j*(231) +153 + j*(-117) +-125 + j*(-174) +23 + j*(-64) +-96 + j*(-199) +-167 + j*(16) +158 + j*(93) +-180 + j*(-331) +-42 + j*(-5) +6 + j*(521) +-161 + j*(197) +-6 + j*(-6) +268 + j*(107) +-275 + j*(156) +245 + j*(-13) +-52 + j*(-217) +-221 + j*(355) +84 + j*(-42) +31 + j*(-204) +-117 + j*(523) +211 + j*(268) +-86 + j*(104) +-181 + j*(-62) +-45 + j*(-198) +141 + j*(82) +-373 + j*(122) +-151 + j*(5) +-33 + j*(-191) +69 + j*(21) +-124 + j*(30) +-153 + j*(-206) +-49 + j*(-235) +-246 + j*(-214) +-224 + j*(-144) +-77 + j*(-115) +-242 + j*(-233) +56 + j*(127) +-137 + j*(-156) +-108 + j*(-163) +-60 + j*(-140) +-91 + j*(73) +-85 + j*(-101) +-141 + j*(30) +-144 + j*(34) +82 + j*(-5) +52 + j*(187) +-285 + j*(-59) +62 + j*(271) +-29 + j*(-113) +-1 + j*(225) +101 + j*(-23) +-143 + j*(196) +-168 + j*(158) +-211 + j*(-158) +71 + j*(-28) +-115 + j*(-99) +-49 + j*(-183) +-58 + j*(8) +-187 + j*(303) +-6 + j*(-127) +188 + j*(-136) +-66 + j*(-156) +134 + j*(-123) +-78 + j*(41) +-134 + j*(-218) +-33 + j*(194) +-33 + j*(-91) +15 + j*(326) +187 + j*(336) +9 + j*(21) +143 + j*(-202) +64 + j*(388) +-179 + j*(-59) +149 + j*(-228) +62 + j*(255) +-161 + j*(-35) +-98 + j*(-286) +-282 + j*(243) +-2 + j*(112) +-168 + j*(-325) +-197 + j*(180) +182 + j*(-438) +-193 + j*(-105) +103 + j*(-26) +168 + j*(135) +-91 + j*(266) +-94 + j*(-79) +165 + j*(228) +215 + j*(-136) +-76 + j*(-318) +-177 + j*(-263) +-272 + j*(156) +337 + j*(-240) +310 + j*(95) +116 + j*(-1) +243 + j*(-195) +223 + j*(-48) +-231 + j*(-1) +16 + j*(21) +-153 + j*(66) +16 + j*(176) +-52 + j*(136) +144 + j*(-22) +89 + j*(-197) +161 + j*(252) +-122 + j*(-67) +-258 + j*(127) +-168 + j*(-146) +-155 + j*(-39) +101 + j*(303) +60 + j*(-25) +-305 + j*(67) +-253 + j*(-231) +91 + j*(-173) +71 + j*(81) +23 + j*(186) +-260 + j*(208) +-2 + j*(149) +-95 + j*(-175) +21 + j*(204) +402 + j*(-2) +-8 + j*(-16) +-175 + j*(150) +45 + j*(-235) +200 + j*(260) +-375 + j*(-325) +179 + j*(166) +152 + j*(246) +6 + j*(80) +212 + j*(-17) +-207 + j*(125) +-6 + j*(12) +119 + j*(61) +-115 + j*(320) +35 + j*(342) +-184 + j*(-132) +62 + j*(-43) +-151 + j*(125) +117 + j*(-96) +2 + j*(59) +-90 + j*(-66) +-18 + j*(239) +-175 + j*(-296) +112 + j*(-147) +68 + j*(92) +61 + j*(-134) +8 + j*(-170) +59 + j*(225) +150 + j*(135) +-108 + j*(-182) +120 + j*(340) +-10 + j*(-316) +54 + j*(4) +-40 + j*(29) +7 + j*(58) +-280 + j*(143) +-206 + j*(197) +-183 + j*(181) +-90 + j*(177) +-115 + j*(26) +-42 + j*(168) +-34 + j*(-195) +32 + j*(125) +272 + j*(-323) +-118 + j*(22) +125 + j*(-72) +-164 + j*(296) +260 + j*(37) +133 + j*(228) +30 + j*(-123) +90 + j*(167) +39 + j*(83) +63 + j*(445) +7 + j*(-14) +-21 + j*(83) +-139 + j*(302) +-600 + j*(137) +-149 + j*(-34) +305 + j*(-392) +208 + j*(151) +26 + j*(16) +135 + j*(-170) +-183 + j*(215) +-78 + j*(1) +-131 + j*(206) +202 + j*(356) +187 + j*(-204) +147 + j*(-86) +283 + j*(107) +30 + j*(-57) +182 + j*(36) +-154 + j*(-84) +24 + j*(36) +124 + j*(52) +-237 + j*(114) +-218 + j*(39) +-40 + j*(-302) +-456 + j*(4) +136 + j*(63) +-20 + j*(33) +81 + j*(-118) +-52 + j*(140) +46 + j*(56) +146 + j*(-45) +-85 + j*(-44) +33 + j*(-86) +-76 + j*(-269) +143 + j*(91) +-121 + j*(23) +12 + j*(93) +-57 + j*(-215) +47 + j*(-370) +317 + j*(22) +-103 + j*(16) +179 + j*(-135) +57 + j*(0) +-30 + j*(88) +131 + j*(-74) +207 + j*(-72) +-234 + j*(179) +-226 + j*(-16) +226 + j*(161) +143 + j*(108) +-95 + j*(-100) +-24 + j*(-88) +380 + j*(102) +187 + j*(57) +-23 + j*(188) +174 + j*(-252) +93 + j*(498) +194 + j*(196) +72 + j*(-33) +-112 + j*(20) +-106 + j*(-163) +-93 + j*(-49) +98 + j*(100) +-79 + j*(-144) +-322 + j*(-298) +-160 + j*(-301) +144 + j*(-13) +262 + j*(-20) +-250 + j*(-38) +59 + j*(-44) +-1 + j*(219) +234 + j*(-99) +-3 + j*(-152) +160 + j*(-97) +359 + j*(152) +-6 + j*(-20) +-209 + j*(183) +-36 + j*(192) +-5 + j*(74) +-171 + j*(-285) +11 + j*(49) +-6 + j*(103) +18 + j*(147) +-27 + j*(161) +4 + j*(-77) +193 + j*(-27) +81 + j*(89) +-20 + j*(140) +-253 + j*(-40) +246 + j*(104) +83 + j*(87) +160 + j*(-54) +277 + j*(4) +129 + j*(-228) +89 + j*(-37) +222 + j*(-259) +4 + j*(-252) +-135 + j*(-66) +-7 + j*(228) +190 + j*(133) +-67 + j*(-235) +157 + j*(-184) +126 + j*(-25) +-321 + j*(46) +-291 + j*(-25) +-365 + j*(-303) +83 + j*(-93) +-286 + j*(77) +-1 + j*(-198) +-246 + j*(-414) +64 + j*(-129) +142 + j*(105) +188 + j*(-168) +-139 + j*(-209) +-58 + j*(330) +-16 + j*(-140) +-33 + j*(157) +-77 + j*(-275) +-151 + j*(-147) +-37 + j*(-271) +206 + j*(254) +419 + j*(39) +156 + j*(-215) +-33 + j*(86) +164 + j*(-355) +-202 + j*(231) +-162 + j*(-66) +-112 + j*(-197) +-72 + j*(-170) +-66 + j*(-123) +70 + j*(245) +-182 + j*(-83) +173 + j*(-288) +148 + j*(158) +38 + j*(324) +67 + j*(-69) +18 + j*(-21) +49 + j*(-88) +54 + j*(-108) +-49 + j*(200) +-228 + j*(-81) +-436 + j*(-100) +-21 + j*(-150) +-58 + j*(-40) +368 + j*(-151) +-32 + j*(-195) +30 + j*(-35) +190 + j*(21) +191 + j*(-153) +-322 + j*(95) +-42 + j*(-115) +103 + j*(-181) +-110 + j*(183) +76 + j*(-199) +-103 + j*(285) +81 + j*(271) +214 + j*(81) +10 + j*(6) +19 + j*(7) +149 + j*(42) +-22 + j*(10) +211 + j*(-118) +126 + j*(-46) +276 + j*(163) +86 + j*(155) +-108 + j*(19) +-16 + j*(-174) +104 + j*(-542) +70 + j*(125) +168 + j*(128) +-215 + j*(305) +-2 + j*(35) +-87 + j*(150) +50 + j*(-389) +111 + j*(136) +-211 + j*(-159) +-20 + j*(-172) +240 + j*(-195) +205 + j*(57) +-98 + j*(43) +194 + j*(-65) +-37 + j*(153) +30 + j*(123) +-52 + j*(29) +-266 + j*(8) +-146 + j*(-105) +158 + j*(15) +69 + j*(-259) +304 + j*(176) +96 + j*(160) +-39 + j*(-62) +5 + j*(80) +-24 + j*(214) +152 + j*(61) +119 + j*(-291) +-44 + j*(168) +48 + j*(431) +-17 + j*(66) +-4 + j*(264) +-88 + j*(33) +-160 + j*(-226) +-238 + j*(-113) +42 + j*(-112) +75 + j*(30) +130 + j*(-27) +100 + j*(175) +106 + j*(-87) +-320 + j*(-256) +122 + j*(-37) +-141 + j*(-22) +80 + j*(-106) +301 + j*(-71) +117 + j*(-21) +93 + j*(419) +46 + j*(-291) +-59 + j*(-177) +-76 + j*(47) +-64 + j*(-56) +-12 + j*(74) +-79 + j*(-18) +214 + j*(-89) +122 + j*(-144) +-142 + j*(-150) +-199 + j*(-298) +13 + j*(-134) +-366 + j*(21) +-2 + j*(-26) +-30 + j*(139) +-328 + j*(-211) +-141 + j*(235) +253 + j*(-21) +-219 + j*(-209) +-71 + j*(-62) +82 + j*(-146) +-127 + j*(261) +-319 + j*(-255) +-121 + j*(86) +585 + j*(32) +-54 + j*(-60) +282 + j*(58) +-122 + j*(221) +84 + j*(110) +-153 + j*(1) +44 + j*(209) +229 + j*(110) +313 + j*(69) +202 + j*(-211) +39 + j*(21) +194 + j*(177) +209 + j*(69) +-30 + j*(-167) +127 + j*(38) +-177 + j*(11) +-41 + j*(86) +-15 + j*(243) +78 + j*(11) +-79 + j*(-228) +-116 + j*(-86) +23 + j*(47) +383 + j*(73) +203 + j*(-68) +111 + j*(140) +-63 + j*(68) +-82 + j*(-229) +-157 + j*(-313) +-190 + j*(279) +-104 + j*(61) +-180 + j*(-204) +265 + j*(-153) +-42 + j*(-48) +100 + j*(172) +-147 + j*(-308) +267 + j*(54) +-112 + j*(272) +-264 + j*(-36) +29 + j*(-332) +140 + j*(-86) +400 + j*(-38) +-121 + j*(-231) +-42 + j*(344) +129 + j*(-81) +-111 + j*(226) +3 + j*(150) +-37 + j*(18) +0 + j*(-82) +153 + j*(151) +81 + j*(91) +-136 + j*(184) +503 + j*(-113) +-49 + j*(319) +70 + j*(77) +197 + j*(-66) +-62 + j*(149) +254 + j*(-122) +45 + j*(-32) +3 + j*(9) +25 + j*(89) +6 + j*(-45) +-22 + j*(161) +-40 + j*(83) +103 + j*(23) +110 + j*(278) +8 + j*(-61) +-57 + j*(37) +-99 + j*(86) +-64 + j*(339) +-37 + j*(214) +-84 + j*(6) +303 + j*(-178) +205 + j*(97) +11 + j*(194) +129 + j*(11) +687 + j*(-100) +187 + j*(-238) +40 + j*(-74) +332 + j*(-25) +-94 + j*(165) +64 + j*(246) +-291 + j*(-108) +-121 + j*(-284) +216 + j*(-104) +159 + j*(23) +75 + j*(-47) +70 + j*(4) +-10 + j*(-34) +-155 + j*(34) +-35 + j*(89) +-13 + j*(-134) +-99 + j*(40) +-463 + j*(-13) +-252 + j*(172) +-22 + j*(-351) +-69 + j*(88) +-284 + j*(-21) +13 + j*(-6) +-35 + j*(-71) +-40 + j*(317) +405 + j*(-60) +-358 + j*(104) +56 + j*(-119) +-135 + j*(-156) +-66 + j*(-23) +168 + j*(59) +148 + j*(-76) +-213 + j*(-190) +-190 + j*(-27) +103 + j*(392) +52 + j*(110) +211 + j*(-61) +-165 + j*(218) +3 + j*(-231) +69 + j*(-161) +-263 + j*(54) +98 + j*(-191) +30 + j*(167) +45 + j*(9) +-373 + j*(181) +69 + j*(105) +-23 + j*(-100) +-127 + j*(-9) +-64 + j*(287) +202 + j*(290) +115 + j*(-109) +-72 + j*(-205) +166 + j*(238) +151 + j*(-25) +186 + j*(290) +-108 + j*(33) +-163 + j*(-180) +148 + j*(124) +94 + j*(-270) +-52 + j*(27) +161 + j*(134) +-61 + j*(-25) +-23 + j*(-233) +93 + j*(-245) +57 + j*(162) +-172 + j*(-354) +133 + j*(129) +339 + j*(107) +12 + j*(65) +6 + j*(-80) +-51 + j*(-17) +-13 + j*(-37) +-18 + j*(-258) +-54 + j*(-141) +295 + j*(6) +-215 + j*(-192) +-109 + j*(-73) +105 + j*(43) +-277 + j*(-251) +57 + j*(188) +-38 + j*(390) +-117 + j*(-390) +107 + j*(233) +131 + j*(98) +366 + j*(-215) +-136 + j*(-154) +45 + j*(-112) +-10 + j*(-6) +27 + j*(-114) +-119 + j*(8) +-163 + j*(-4) +78 + j*(261) +221 + j*(-37) +-92 + j*(-23) +4 + j*(221) +-2 + j*(-153) +-76 + j*(-158) +66 + j*(141) +-182 + j*(136) +-446 + j*(-88) +71 + j*(-145) +-75 + j*(-87) +101 + j*(-97) +-177 + j*(146) +93 + j*(21) +324 + j*(397) +281 + j*(-229) +-138 + j*(117) +-188 + j*(112) +39 + j*(-66) +163 + j*(-98) +71 + j*(57) +-65 + j*(187) +125 + j*(197) +-135 + j*(141) +-105 + j*(47) +19 + j*(-86) +66 + j*(-235) +-480 + j*(225) +76 + j*(28) +342 + j*(47) +0 + j*(-366) +-140 + j*(74) +193 + j*(144) +-126 + j*(-43) +-191 + j*(158) +-180 + j*(-55) +63 + j*(-255) +-98 + j*(-2) +-13 + j*(308) +-183 + j*(207) +144 + j*(37) +-51 + j*(-175) +28 + j*(-29) +-211 + j*(356) +-132 + j*(173) +-173 + j*(199) +36 + j*(329) +-139 + j*(228) +-311 + j*(177) +65 + j*(-343) +-217 + j*(-20) +119 + j*(18) +29 + j*(-58) +156 + j*(129) +-41 + j*(23) +202 + j*(-163) +224 + j*(196) +-47 + j*(25) +15 + j*(-122) +-182 + j*(280) +-170 + j*(21) +8 + j*(-144) +20 + j*(246) +-148 + j*(143) +91 + j*(93) +168 + j*(44) +-100 + j*(270) +-51 + j*(-167) +-285 + j*(125) +-93 + j*(63) +-1 + j*(-290) +-214 + j*(-47) +-78 + j*(243) +-156 + j*(-314) +152 + j*(57) +163 + j*(267) +8 + j*(-167) +-262 + j*(114) +132 + j*(49) +199 + j*(-85) +3 + j*(228) +57 + j*(-151) +104 + j*(-98) +-45 + j*(-381) +238 + j*(-59) +-62 + j*(-158) +-96 + j*(-87) +8 + j*(279) +-84 + j*(260) +276 + j*(127) +-142 + j*(-42) +-119 + j*(-185) +67 + j*(134) +-20 + j*(129) +-47 + j*(-30) +-250 + j*(156) +200 + j*(108) +-450 + j*(49) +-30 + j*(87) +205 + j*(-137) +-165 + j*(217) +100 + j*(-165) +-52 + j*(-71) +-232 + j*(-131) +-289 + j*(-36) +310 + j*(-194) +-88 + j*(127) +17 + j*(-71) +50 + j*(232) +181 + j*(21) +-65 + j*(-333) +158 + j*(-238) +176 + j*(-210) +-279 + j*(173) +-21 + j*(-192) +-363 + j*(-361) +6 + j*(185) +-25 + j*(-4) +62 + j*(-21) +33 + j*(-59) +2 + j*(-121) +-192 + j*(-84) +32 + j*(204) +23 + j*(57) +-186 + j*(341) +1 + j*(-191) +-262 + j*(-313) +121 + j*(13) +-211 + j*(-185) +-470 + j*(23) +-221 + j*(94) +50 + j*(25) +-277 + j*(53) +174 + j*(29) +-26 + j*(-297) +-1 + j*(-285) +90 + j*(-249) +50 + j*(214) +72 + j*(-9) +-107 + j*(-288) +-98 + j*(-368) +-146 + j*(-28) +-135 + j*(-53) +-245 + j*(240) +-88 + j*(134) +211 + j*(-91) +-175 + j*(42) +117 + j*(212) +179 + j*(-4) +-96 + j*(202) +-119 + j*(-134) +22 + j*(291) +-515 + j*(119) +36 + j*(-319) +190 + j*(-428) +128 + j*(-48) +458 + j*(-10) +-104 + j*(-23) +-51 + j*(173) +93 + j*(95) +-222 + j*(47) +-141 + j*(-39) +-175 + j*(-116) +35 + j*(-10) +56 + j*(-146) +275 + j*(14) +14 + j*(31) +-105 + j*(-30) +105 + j*(64) +21 + j*(-163) +-33 + j*(-29) +-56 + j*(-397) +-235 + j*(-142) +-91 + j*(-166) +-112 + j*(-132) +342 + j*(116) +76 + j*(-300) +-118 + j*(71) +-137 + j*(196) +83 + j*(204) +89 + j*(-214) +78 + j*(-142) +-82 + j*(-71) +-301 + j*(-57) +141 + j*(111) +-74 + j*(4) +-76 + j*(179) +-545 + j*(209) +121 + j*(-37) +303 + j*(121) +-182 + j*(47) +83 + j*(-137) +251 + j*(118) +60 + j*(36) +134 + j*(221) +257 + j*(245) +30 + j*(-115) +192 + j*(-68) +-280 + j*(-52) +-197 + j*(255) +-106 + j*(23) +-2 + j*(-309) +175 + j*(305) +78 + j*(31) +86 + j*(-110) +-37 + j*(-164) +-28 + j*(135) +29 + j*(-107) +161 + j*(228) +269 + j*(167) +-46 + j*(-32) +-175 + j*(-12) +244 + j*(-436) +-118 + j*(276) +-151 + j*(-311) +-127 + j*(91) +27 + j*(182) +71 + j*(-19) +170 + j*(-5) +-67 + j*(75) +196 + j*(233) +253 + j*(47) +-23 + j*(-124) +10 + j*(-184) +-90 + j*(-4) +-13 + j*(-43) +-248 + j*(-177) +-4 + j*(-153) +192 + j*(-52) +-232 + j*(-206) +238 + j*(138) +-165 + j*(55) +-158 + j*(-70) +77 + j*(55) +-6 + j*(47) +227 + j*(-101) +7 + j*(281) +-52 + j*(156) +137 + j*(-203) +56 + j*(64) +71 + j*(16) +-171 + j*(-17) +-127 + j*(325) +8 + j*(91) +-107 + j*(197) +-25 + j*(22) +-203 + j*(-243) +120 + j*(57) +205 + j*(-311) +117 + j*(30) +-167 + j*(149) +202 + j*(27) +-257 + j*(177) +-293 + j*(76) +-211 + j*(-262) +-106 + j*(-71) +-43 + j*(-121) +-140 + j*(-146) +-118 + j*(138) +114 + j*(-126) +114 + j*(35) +-208 + j*(59) +177 + j*(34) +-18 + j*(-115) +60 + j*(9) +-24 + j*(-62) +288 + j*(66) +-176 + j*(-223) +94 + j*(69) +334 + j*(-168) +281 + j*(-23) +-40 + j*(139) +-59 + j*(-4) +-45 + j*(-16) +100 + j*(-16) +216 + j*(-39) +30 + j*(-128) +-351 + j*(161) +67 + j*(-194) +-213 + j*(-55) +102 + j*(-107) +236 + j*(-30) +317 + j*(-180) +66 + j*(-140) +-4 + j*(157) +-191 + j*(-49) +-101 + j*(-248) +-21 + j*(-175) +-9 + j*(-108) +-268 + j*(-51) +158 + j*(168) +11 + j*(117) +-4 + j*(78) +77 + j*(186) +72 + j*(-84) +-88 + j*(-228) +-66 + j*(-83) +-272 + j*(-322) +-123 + j*(-65) +-105 + j*(25) +368 + j*(-404) +0 + j*(-161) +162 + j*(-31) +96 + j*(232) +236 + j*(-275) +40 + j*(-96) +250 + j*(-218) +-234 + j*(-142) +-10 + j*(63) +-264 + j*(210) +40 + j*(-186) +-290 + j*(4) +176 + j*(-90) +109 + j*(282) +13 + j*(465) +40 + j*(7) +129 + j*(-70) +-30 + j*(7) +-151 + j*(71) +-240 + j*(152) +-238 + j*(-159) +50 + j*(-19) +-81 + j*(76) +132 + j*(-339) +7 + j*(190) +68 + j*(-272) +-231 + j*(199) +-6 + j*(-153) +-71 + j*(224) +-362 + j*(203) +122 + j*(-11) +125 + j*(-11) +40 + j*(-13) +69 + j*(370) +128 + j*(-18) +-73 + j*(77) +-194 + j*(-13) +144 + j*(33) +168 + j*(331) +-224 + j*(-53) +18 + j*(-140) +-47 + j*(232) +20 + j*(-175) +235 + j*(-91) +241 + j*(-113) +-290 + j*(-156) +-180 + j*(-276) +-187 + j*(69) +-25 + j*(-264) +-29 + j*(-21) +-70 + j*(-210) +-301 + j*(-95) +-34 + j*(-162) +-252 + j*(10) +80 + j*(-33) +-62 + j*(-161) +14 + j*(29) +83 + j*(170) +154 + j*(-146) +50 + j*(-245) +112 + j*(82) +-60 + j*(132) +257 + j*(174) +-10 + j*(-168) +147 + j*(-98) +-224 + j*(-255) +-240 + j*(-171) +155 + j*(-137) +-81 + j*(138) +-325 + j*(-52) +247 + j*(141) +-365 + j*(16) +385 + j*(-28) +165 + j*(-25) +-62 + j*(60) +-140 + j*(-218) +426 + j*(178) +-83 + j*(156) +163 + j*(-32) +263 + j*(13) +-159 + j*(45) +-7 + j*(-478) +-43 + j*(221) +37 + j*(-121) +57 + j*(-92) +4 + j*(207) +-91 + j*(-10) +-173 + j*(31) +182 + j*(-86) +153 + j*(59) +-259 + j*(-192) +185 + j*(-95) +155 + j*(169) +136 + j*(-41) +-330 + j*(-250) +-178 + j*(-422) +218 + j*(307) +264 + j*(-365) +317 + j*(-4) +424 + j*(-73) +-162 + j*(-162) +-238 + j*(-79) +-28 + j*(270) +-309 + j*(224) +230 + j*(42) +168 + j*(66) +243 + j*(-93) +-57 + j*(248) +-28 + j*(131) +-1 + j*(173) +-61 + j*(-118) +-35 + j*(104) +156 + j*(-25) +20 + j*(182) +-57 + j*(-141) +-115 + j*(-38) +68 + j*(-209) +97 + j*(-191) +170 + j*(226) +70 + j*(42) +-115 + j*(105) +-105 + j*(167) +-153 + j*(-176) +1 + j*(214) +144 + j*(404) +76 + j*(303) +220 + j*(2) +-428 + j*(-21) +-53 + j*(49) +-35 + j*(262) +29 + j*(-51) +104 + j*(-71) +161 + j*(-219) +57 + j*(-207) +-167 + j*(200) +-170 + j*(174) +-46 + j*(-60) +4 + j*(-160) +117 + j*(50) +390 + j*(21) +-37 + j*(16) +3 + j*(-183) +-27 + j*(194) +93 + j*(42) +-457 + j*(214) +310 + j*(-107) +-8 + j*(-76) +282 + j*(183) +-30 + j*(56) +201 + j*(322) +421 + j*(227) +230 + j*(-49) +156 + j*(-142) +-208 + j*(-272) +-81 + j*(-156) +-293 + j*(-89) +-108 + j*(-82) +225 + j*(73) +-69 + j*(91) +-227 + j*(-105) +350 + j*(-50) +8 + j*(-212) +-149 + j*(234) +-61 + j*(139) +134 + j*(-105) +177 + j*(-169) +-113 + j*(113) +178 + j*(44) +120 + j*(62) +-1 + j*(253) +-45 + j*(-24) +240 + j*(-194) +23 + j*(90) +237 + j*(68) +-13 + j*(83) +-148 + j*(-37) +136 + j*(-278) +-175 + j*(334) +160 + j*(-148) +153 + j*(-133) +60 + j*(124) +-221 + j*(-114) +96 + j*(116) +-43 + j*(30) +38 + j*(-186) +-302 + j*(-27) +93 + j*(-78) +-64 + j*(274) +-75 + j*(-1) +66 + j*(232) +199 + j*(22) +-64 + j*(40) +-199 + j*(66) +168 + j*(-209) +122 + j*(-142) +305 + j*(71) +-11 + j*(-146) +-418 + j*(5) +24 + j*(133) +203 + j*(-218) +394 + j*(165) +-156 + j*(-112) +93 + j*(-129) +-204 + j*(59) +95 + j*(317) +-151 + j*(-274) +-122 + j*(-175) +-115 + j*(-29) +-50 + j*(-112) +224 + j*(-140) +47 + j*(-1) +-80 + j*(-177) +-244 + j*(-238) +-102 + j*(45) +-117 + j*(-63) +62 + j*(8) +-85 + j*(20) +-209 + j*(-100) +-118 + j*(-187) +-158 + j*(57) +-174 + j*(-190) +-23 + j*(389) +-24 + j*(110) +-163 + j*(-100) +45 + j*(234) +-49 + j*(76) +-349 + j*(193) +-40 + j*(-93) +162 + j*(120) +-119 + j*(-11) +-126 + j*(322) +42 + j*(240) +49 + j*(-10) +445 + j*(175) +-243 + j*(78) +95 + j*(-86) +237 + j*(66) +148 + j*(-190) +-105 + j*(37) +112 + j*(40) +-134 + j*(-176) +241 + j*(-241) +-398 + j*(185) +-57 + j*(36) +323 + j*(36) +206 + j*(-162) +-100 + j*(231) +-121 + j*(192) +52 + j*(68) +113 + j*(-16) +-312 + j*(-42) +185 + j*(-37) +-140 + j*(124) +252 + j*(-82) +74 + j*(-66) +-182 + j*(-21) +-168 + j*(-48) +-198 + j*(-36) +-100 + j*(-97) +108 + j*(-23) +16 + j*(-69) +-303 + j*(-143) +-182 + j*(-119) +149 + j*(-485) +279 + j*(110) +-151 + j*(-129) +263 + j*(-245) +166 + j*(28) +216 + j*(74) +25 + j*(96) +-122 + j*(146) +81 + j*(103) +129 + j*(-6) +-167 + j*(-17) +-351 + j*(-259) +3 + j*(-125) +-163 + j*(68) +279 + j*(91) +-49 + j*(-257) +195 + j*(-93) +47 + j*(118) +-197 + j*(-392) +-125 + j*(-238) +284 + j*(48) +218 + j*(-397) +72 + j*(-14) +-46 + j*(223) +-140 + j*(-227) +182 + j*(-205) +-218 + j*(-226) +-57 + j*(-305) +-48 + j*(-37) +-199 + j*(-303) +16 + j*(-168) +38 + j*(-11) +-73 + j*(-53) +-142 + j*(-253) +-83 + j*(246) +77 + j*(-91) +-128 + j*(-83) +-315 + j*(-84) +-229 + j*(-173) +-238 + j*(-5) +118 + j*(-53) +-119 + j*(124) +57 + j*(-78) +33 + j*(-105) +-52 + j*(-35) +-11 + j*(87) +-172 + j*(18) +-40 + j*(-88) +-42 + j*(188) +3 + j*(-257) +-205 + j*(97) +244 + j*(337) +-30 + j*(35) +52 + j*(-91) +-379 + j*(-11) +-187 + j*(-46) +-99 + j*(-209) +-197 + j*(-16) +-168 + j*(-129) +-429 + j*(34) +-54 + j*(-23) +-110 + j*(-78) +328 + j*(98) +-142 + j*(139) +-204 + j*(124) +-123 + j*(-131) +-110 + j*(-260) +47 + j*(-187) +138 + j*(121) +-160 + j*(91) +-414 + j*(-91) +-73 + j*(169) +-91 + j*(-195) +-343 + j*(-139) +-105 + j*(-62) +127 + j*(308) +43 + j*(147) +-381 + j*(40) +-107 + j*(197) +264 + j*(-93) +-170 + j*(122) +156 + j*(-71) +-37 + j*(233) +77 + j*(51) +152 + j*(14) +-35 + j*(76) +-259 + j*(124) +-253 + j*(10) +234 + j*(-71) +562 + j*(-276) +0 + j*(88) +45 + j*(115) +-56 + j*(-43) +262 + j*(25) +-69 + j*(119) +-143 + j*(-172) +176 + j*(-386) +-144 + j*(38) +-18 + j*(170) +259 + j*(-262) +-8 + j*(88) +-113 + j*(-90) +139 + j*(74) +141 + j*(-67) +208 + j*(-146) +118 + j*(46) +-156 + j*(-5) +-69 + j*(-154) +-252 + j*(115) +93 + j*(6) +55 + j*(257) +19 + j*(62) +211 + j*(129) +-421 + j*(107) +120 + j*(77) +-86 + j*(-219) +-292 + j*(-37) +-13 + j*(-209) +-185 + j*(-60) +-71 + j*(163) +-301 + j*(-11) +-138 + j*(188) +110 + j*(6) +310 + j*(356) +101 + j*(-104) +-11 + j*(125) +107 + j*(81) +157 + j*(-269) +-98 + j*(-77) +427 + j*(-223) +-159 + j*(154) +11 + j*(148) +-168 + j*(-61) +19 + j*(-80) +-69 + j*(276) +-376 + j*(283) +23 + j*(91) +-237 + j*(41) +-194 + j*(11) +-209 + j*(-356) +-21 + j*(170) +-204 + j*(92) +180 + j*(89) +-72 + j*(52) +-102 + j*(128) +155 + j*(-105) +-308 + j*(215) +-206 + j*(187) +-31 + j*(27) +-264 + j*(33) +192 + j*(50) +-184 + j*(-98) +-213 + j*(-190) +-296 + j*(-141) +42 + j*(-74) +59 + j*(153) +-2 + j*(-122) +124 + j*(-98) +37 + j*(-61) +-5 + j*(-226) +-327 + j*(-73) +187 + j*(238) +-193 + j*(145) +-49 + j*(199) +12 + j*(-103) +254 + j*(-51) +138 + j*(-86) +166 + j*(-317) +61 + j*(-37) +-264 + j*(37) +-108 + j*(-327) +-274 + j*(312) +-293 + j*(146) +-120 + j*(-36) +153 + j*(-57) +91 + j*(205) +-26 + j*(432) +-310 + j*(168) +137 + j*(171) +-57 + j*(11) +233 + j*(-103) +-19 + j*(-187) +-33 + j*(-207) +-239 + j*(153) +250 + j*(-412) +23 + j*(-238) +218 + j*(-332) +284 + j*(-149) +68 + j*(37) +-3 + j*(303) +145 + j*(90) +7 + j*(-6) +93 + j*(-117) +218 + j*(-139) +-204 + j*(30) +-51 + j*(-193) +-52 + j*(-139) +-104 + j*(-123) +-164 + j*(55) +169 + j*(12) +-155 + j*(-104) +230 + j*(26) +-1 + j*(93) +-243 + j*(-438) +-313 + j*(98) +22 + j*(-40) +-18 + j*(166) +116 + j*(-16) +-221 + j*(156) +10 + j*(-282) +-21 + j*(41) +-111 + j*(-107) +78 + j*(68) +-165 + j*(14) +-99 + j*(16) +315 + j*(66) +11 + j*(-98) +65 + j*(97) +-82 + j*(227) +35 + j*(-300) +-29 + j*(30) +222 + j*(-175) +89 + j*(91) +133 + j*(-55) +-165 + j*(26) +294 + j*(-19) +-134 + j*(173) +-6 + j*(-123) +265 + j*(316) +-37 + j*(-37) +37 + j*(-9) +-28 + j*(54) +66 + j*(52) +-2 + j*(-216) +111 + j*(-18) +144 + j*(153) +46 + j*(17) +-18 + j*(184) +-277 + j*(-111) +136 + j*(-34) +181 + j*(-19) +-358 + j*(42) +112 + j*(24) +-58 + j*(-71) +21 + j*(89) +250 + j*(2) +-151 + j*(7) +-45 + j*(29) +-100 + j*(-1) +-96 + j*(148) +197 + j*(52) +-18 + j*(-540) +7 + j*(-98) +-18 + j*(27) +74 + j*(166) +-16 + j*(-130) +62 + j*(108) +37 + j*(88) +-97 + j*(-153) +-11 + j*(36) +-204 + j*(48) +70 + j*(115) +-161 + j*(142) +-72 + j*(-76) +156 + j*(112) +149 + j*(317) +-163 + j*(193) +353 + j*(-178) +160 + j*(-74) +67 + j*(201) +-218 + j*(146) +111 + j*(42) +-27 + j*(28) +-207 + j*(-126) +115 + j*(68) +178 + j*(95) +110 + j*(-12) +74 + j*(-181) +-38 + j*(-50) +147 + j*(321) +132 + j*(110) +297 + j*(158) +-107 + j*(59) +100 + j*(142) +-35 + j*(252) +122 + j*(69) +105 + j*(-229) +34 + j*(-2) +479 + j*(-9) +-16 + j*(96) +201 + j*(-258) +-104 + j*(133) +129 + j*(-23) +194 + j*(134) +-106 + j*(-35) +-281 + j*(-300) +36 + j*(-212) +-175 + j*(21) +-287 + j*(86) +79 + j*(-139) +173 + j*(133) +16 + j*(-117) +-152 + j*(33) +201 + j*(-59) +-149 + j*(150) +-75 + j*(-175) +-416 + j*(-181) +-64 + j*(-284) +0 + j*(401) +-170 + j*(425) +-214 + j*(-47) +-211 + j*(247) +-98 + j*(8) +-129 + j*(447) +271 + j*(272) +9 + j*(-279) +-64 + j*(-25) +176 + j*(240) +-462 + j*(-388) +-25 + j*(391) +132 + j*(-235) +173 + j*(-240) +371 + j*(-346) +230 + j*(-164) +-228 + j*(18) +-81 + j*(323) +150 + j*(89) +197 + j*(-226) +387 + j*(-117) +170 + j*(-281) +-300 + j*(-19) +-4 + j*(-175) +428 + j*(-17) +523 + j*(419) +168 + j*(455) +-202 + j*(-57) +-372 + j*(-344) +-133 + j*(-50) +87 + j*(-18) +-21 + j*(347) +237 + j*(446) +-267 + j*(-60) +-407 + j*(-203) +-99 + j*(-204) +259 + j*(247) +-342 + j*(342) +273 + j*(330) +-400 + j*(238) +365 + j*(-625) +400 + j*(-322) +5 + j*(168) +371 + j*(329) +148 + j*(443) +134 + j*(-100) +-497 + j*(272) +-395 + j*(400) +-403 + j*(267) +411 + j*(-407) +-341 + j*(-416) +155 + j*(-460) +332 + j*(-323) +-194 + j*(42) +-268 + j*(133) +224 + j*(-124) +535 + j*(478) +143 + j*(-390) +368 + j*(-152) +-110 + j*(-284) +-693 + j*(-241) +-386 + j*(450) +-215 + j*(373) +-156 + j*(189) +349 + j*(-105) +390 + j*(61) +269 + j*(-430) +183 + j*(-207) +-150 + j*(-489) +518 + j*(531) +186 + j*(692) +395 + j*(-305) +166 + j*(249) +243 + j*(-417) +-135 + j*(-226) +103 + j*(46) +281 + j*(125) +182 + j*(351) +-250 + j*(40) +-157 + j*(-467) +-240 + j*(178) +170 + j*(-20) +-379 + j*(-303) +-149 + j*(295) +444 + j*(-149) +595 + j*(231) +-92 + j*(-199) +-362 + j*(-141) +-561 + j*(33) +588 + j*(-375) +-267 + j*(-479) +327 + j*(100) +-598 + j*(-174) +-42 + j*(406) +342 + j*(-147) +336 + j*(-131) +140 + j*(115) +438 + j*(119) +-50 + j*(100) +277 + j*(402) +-230 + j*(-449) +202 + j*(367) +388 + j*(-771) +288 + j*(-619) +204 + j*(-395) +-47 + j*(-322) +-293 + j*(322) +-315 + j*(-171) +-141 + j*(127) +-414 + j*(-54) +36 + j*(366) +-325 + j*(466) +471 + j*(-397) +-284 + j*(-148) +-380 + j*(111) +277 + j*(-126) +252 + j*(220) +81 + j*(-233) +241 + j*(-114) +-260 + j*(417) +462 + j*(-177) +-95 + j*(398) +-182 + j*(-351) +-76 + j*(-392) +-268 + j*(-288) +351 + j*(-228) +501 + j*(62) +51 + j*(273) +-418 + j*(-262) +385 + j*(198) +-156 + j*(497) +185 + j*(-89) +-111 + j*(-339) +-297 + j*(260) +141 + j*(-395) +202 + j*(-265) +291 + j*(-190) +344 + j*(83) +-349 + j*(64) +-132 + j*(284) +361 + j*(363) +212 + j*(241) +527 + j*(514) +69 + j*(530) +403 + j*(281) +-375 + j*(-121) +-355 + j*(-482) +177 + j*(158) +187 + j*(-8) +696 + j*(-346) +132 + j*(-311) +1 + j*(213) +395 + j*(-237) +303 + j*(246) +320 + j*(-262) +308 + j*(187) +527 + j*(18) +-641 + j*(192) +-265 + j*(-494) +703 + j*(446) +412 + j*(116) +-544 + j*(392) +219 + j*(387) +-129 + j*(351) +-192 + j*(187) +-379 + j*(-465) +322 + j*(-293) +192 + j*(-500) +22 + j*(351) +-387 + j*(-301) +-67 + j*(456) +194 + j*(450) +218 + j*(-581) +-276 + j*(-107) +187 + j*(198) +28 + j*(-418) +-85 + j*(292) +-156 + j*(-344) +-214 + j*(-260) +-151 + j*(-267) +41 + j*(-289) +347 + j*(329) +-33 + j*(-435) +76 + j*(298) +202 + j*(222) +-78 + j*(284) +575 + j*(-494) +291 + j*(204) +197 + j*(523) +-494 + j*(-342) +86 + j*(328) +257 + j*(600) +236 + j*(-177) +-128 + j*(-152) +-214 + j*(-280) +251 + j*(352) +-202 + j*(17) +74 + j*(424) +-280 + j*(276) +-160 + j*(293) +337 + j*(310) +-448 + j*(-120) +-243 + j*(-566) +-279 + j*(-2) +298 + j*(483) +-263 + j*(459) +-253 + j*(-158) +-312 + j*(-397) +-192 + j*(228) +-249 + j*(-423) +51 + j*(-308) +526 + j*(-261) +74 + j*(446) +-124 + j*(-276) +-95 + j*(444) +16 + j*(163) +-301 + j*(110) +457 + j*(-303) +-216 + j*(-169) +429 + j*(-260) +-603 + j*(436) +57 + j*(324) +-115 + j*(-294) +313 + j*(295) +470 + j*(-225) +518 + j*(129) +-504 + j*(-204) +-540 + j*(-33) +-177 + j*(-329) +253 + j*(-247) +-467 + j*(-372) +185 + j*(-238) +267 + j*(186) +-384 + j*(141) +250 + j*(-291) +-3 + j*(-309) +-214 + j*(-30) +118 + j*(635) +-256 + j*(327) +312 + j*(-137) +197 + j*(-70) +18 + j*(-503) +317 + j*(367) +181 + j*(-424) +-344 + j*(-240) +57 + j*(-547) +-364 + j*(13) +-27 + j*(-107) +-59 + j*(80) +369 + j*(51) +-217 + j*(-81) +-407 + j*(509) +291 + j*(182) +-293 + j*(334) +28 + j*(-156) +-438 + j*(400) +343 + j*(-96) +477 + j*(371) +-287 + j*(-291) +482 + j*(328) +-282 + j*(-414) +61 + j*(179) +-224 + j*(-69) +-153 + j*(331) +188 + j*(-46) +41 + j*(-78) +-571 + j*(556) +-293 + j*(91) +-260 + j*(90) +239 + j*(-81) +-174 + j*(-201) +262 + j*(189) +-197 + j*(-334) +368 + j*(311) +-501 + j*(88) +-48 + j*(-481) +325 + j*(389) +-238 + j*(86) +-356 + j*(-254) +-293 + j*(-133) +287 + j*(380) +527 + j*(33) +497 + j*(-288) +432 + j*(-242) +409 + j*(-207) +28 + j*(-156) +-240 + j*(181) +-320 + j*(-711) +-104 + j*(-373) +341 + j*(-32) +-406 + j*(-363) +155 + j*(57) +-262 + j*(190) +210 + j*(742) +65 + j*(-220) +-291 + j*(-206) +-197 + j*(352) +-100 + j*(-406) +356 + j*(320) +-412 + j*(217) +-3 + j*(602) +382 + j*(-284) +-122 + j*(93) +-682 + j*(-298) +276 + j*(62) +-551 + j*(75) +607 + j*(474) +26 + j*(235) +252 + j*(-453) +-262 + j*(-438) +-40 + j*(-168) +-53 + j*(71) +192 + j*(431) +435 + j*(-244) +380 + j*(358) +-403 + j*(-416) +-105 + j*(-338) +58 + j*(-154) +-199 + j*(-422) +-193 + j*(391) +281 + j*(-103) +298 + j*(-147) +426 + j*(-414) +398 + j*(100) +165 + j*(140) +126 + j*(-89) +122 + j*(300) +-155 + j*(-434) +-440 + j*(69) +391 + j*(-152) +-307 + j*(-64) +285 + j*(-441) +-154 + j*(-491) +-419 + j*(-529) +-31 + j*(-330) +60 + j*(81) +-173 + j*(132) +488 + j*(338) +-42 + j*(-450) +-159 + j*(-192) +-74 + j*(-560) +235 + j*(-305) +-415 + j*(-184) +-165 + j*(-223) +158 + j*(383) +27 + j*(-197) +-255 + j*(-47) +438 + j*(315) +138 + j*(-294) +-40 + j*(-127) +337 + j*(-310) +257 + j*(239) +25 + j*(385) +-507 + j*(55) +-337 + j*(185) +355 + j*(501) +-223 + j*(258) +161 + j*(-298) +-408 + j*(-71) +-342 + j*(351) +256 + j*(-382) +-455 + j*(194) +-324 + j*(457) +-124 + j*(509) +-184 + j*(209) +51 + j*(-226) +-337 + j*(-282) +-38 + j*(-43) +95 + j*(110) +163 + j*(-158) +-318 + j*(-346) +160 + j*(321) +-257 + j*(310) +305 + j*(-486) +258 + j*(214) +-281 + j*(-214) +293 + j*(9) +-225 + j*(-240) +207 + j*(-445) +-308 + j*(185) +-59 + j*(-70) +-493 + j*(-380) +655 + j*(-197) +-268 + j*(-100) +315 + j*(-30) +382 + j*(-180) +45 + j*(-370) +396 + j*(391) +-488 + j*(-400) +-333 + j*(-64) +-162 + j*(456) +-315 + j*(-665) +229 + j*(205) +-97 + j*(441) +278 + j*(227) +-42 + j*(-278) +-182 + j*(413) +286 + j*(69) +-286 + j*(530) +86 + j*(326) +196 + j*(257) +-218 + j*(161) +444 + j*(-151) +-243 + j*(11) +-325 + j*(329) +648 + j*(55) +546 + j*(632) +-120 + j*(370) +127 + j*(-274) +341 + j*(356) +605 + j*(-571) +129 + j*(441) +-491 + j*(-367) +427 + j*(-232) +-573 + j*(33) +99 + j*(240) +-359 + j*(-138) +229 + j*(165) +309 + j*(119) +242 + j*(284) +-192 + j*(27) +621 + j*(-439) +-198 + j*(181) +-245 + j*(275) +-130 + j*(-330) +286 + j*(187) +295 + j*(-190) +665 + j*(218) +266 + j*(-188) +-49 + j*(-291) +-264 + j*(-29) +156 + j*(-284) +106 + j*(200) +342 + j*(250) +456 + j*(8) +-72 + j*(-268) +132 + j*(385) +190 + j*(-104) +125 + j*(-565) +233 + j*(103) +260 + j*(9) +6 + j*(-413) +358 + j*(-296) +-222 + j*(-221) +-90 + j*(335) +361 + j*(-165) +440 + j*(344) +-477 + j*(81) +-384 + j*(-272) +366 + j*(144) +482 + j*(268) +368 + j*(-361) +270 + j*(-76) +238 + j*(-549) +-412 + j*(-489) +-165 + j*(28) +-234 + j*(303) +53 + j*(263) +-335 + j*(463) +435 + j*(-43) +402 + j*(-403) +573 + j*(438) +-498 + j*(-515) +-197 + j*(243) +456 + j*(28) +-546 + j*(409) +-193 + j*(-208) +66 + j*(417) +-84 + j*(330) +-218 + j*(-150) +378 + j*(202) +177 + j*(-46) +472 + j*(106) +-259 + j*(-188) +291 + j*(-82) +251 + j*(423) +187 + j*(-513) +385 + j*(206) +-281 + j*(-349) +105 + j*(202) +-230 + j*(448) +-470 + j*(-348) +13 + j*(-522) +-318 + j*(-141) +-642 + j*(-298) +82 + j*(-451) +-448 + j*(419) +349 + j*(435) +-437 + j*(618) +-74 + j*(-261) +207 + j*(-99) +-386 + j*(292) +290 + j*(-264) +431 + j*(-342) +346 + j*(-221) +240 + j*(151) +-209 + j*(-525) +-188 + j*(-429) +-590 + j*(-514) +409 + j*(-223) +-315 + j*(285) +-521 + j*(-451) +202 + j*(458) +-221 + j*(-139) +236 + j*(378) +-672 + j*(421) +1 + j*(315) +-83 + j*(-494) +-306 + j*(396) +185 + j*(-515) +-528 + j*(120) +-441 + j*(96) +-17 + j*(-30) +213 + j*(271) +631 + j*(-5) +364 + j*(26) +289 + j*(-235) +-78 + j*(269) +-317 + j*(-59) +-365 + j*(-119) +-433 + j*(439) +524 + j*(208) +-506 + j*(479) +144 + j*(-102) +218 + j*(486) +166 + j*(308) +340 + j*(-202) +195 + j*(376) +-243 + j*(18) +666 + j*(-218) +-438 + j*(-264) +-342 + j*(328) +-4 + j*(-325) +266 + j*(344) +-282 + j*(80) +-177 + j*(581) +-470 + j*(-49) +173 + j*(-510) +-232 + j*(204) +192 + j*(-291) +-95 + j*(-459) +-422 + j*(420) +-381 + j*(442) +-5 + j*(-301) +23 + j*(-64) +-246 + j*(-320) +86 + j*(22) +227 + j*(153) +523 + j*(-78) +-17 + j*(234) +152 + j*(221) +361 + j*(127) +477 + j*(-136) +-260 + j*(-223) +-452 + j*(-424) +-38 + j*(316) +7 + j*(41) +314 + j*(-93) +-199 + j*(-49) +373 + j*(27) +138 + j*(-133) +670 + j*(440) +279 + j*(-281) +651 + j*(-272) +-327 + j*(352) +-197 + j*(-193) +50 + j*(-195) +-464 + j*(169) +91 + j*(299) +-268 + j*(-354) +-175 + j*(243) +209 + j*(-299) +246 + j*(-74) +-211 + j*(32) +-590 + j*(-237) +-349 + j*(-13) +493 + j*(91) +163 + j*(-473) +-229 + j*(-415) +341 + j*(-74) +-523 + j*(-462) +233 + j*(354) +476 + j*(-384) +-311 + j*(429) +-110 + j*(129) +316 + j*(-384) +-472 + j*(187) +276 + j*(-151) +-118 + j*(-93) +290 + j*(212) +427 + j*(168) +-263 + j*(495) +173 + j*(170) +-376 + j*(113) +-264 + j*(252) +-285 + j*(-351) +477 + j*(-281) +-305 + j*(39) +-271 + j*(75) +-76 + j*(113) +-59 + j*(45) +64 + j*(-188) +131 + j*(244) +23 + j*(242) +6 + j*(-276) +34 + j*(-119) +-132 + j*(123) +158 + j*(-139) +-154 + j*(-136) +-228 + j*(-295) +-5 + j*(-81) +-198 + j*(-13) +-163 + j*(-329) +123 + j*(-270) +-20 + j*(-197) +-28 + j*(-51) +145 + j*(-162) +157 + j*(24) +-126 + j*(54) +371 + j*(-254) +-260 + j*(-204) +-182 + j*(-146) +156 + j*(264) +168 + j*(-101) +11 + j*(-81) +-284 + j*(-288) +-79 + j*(-81) +76 + j*(137) +-160 + j*(-287) +165 + j*(-95) +83 + j*(7) +83 + j*(-138) +-11 + j*(134) +-58 + j*(281) +11 + j*(-214) +-231 + j*(-128) +124 + j*(-11) +-13 + j*(-123) +-122 + j*(154) +286 + j*(-387) +-153 + j*(59) +-168 + j*(-157) +-93 + j*(204) +143 + j*(237) +164 + j*(47) +-13 + j*(170) +-236 + j*(-96) +57 + j*(395) +71 + j*(-207) +-18 + j*(-145) +-165 + j*(-25) +-185 + j*(-54) +144 + j*(6) +-3 + j*(202) +-39 + j*(137) +75 + j*(64) +65 + j*(-144) +57 + j*(-88) +130 + j*(-175) +86 + j*(268) +-220 + j*(99) +-303 + j*(-27) +-86 + j*(-230) +0 + j*(-168) +-86 + j*(-19) +-112 + j*(-159) +-46 + j*(-31) +-248 + j*(334) +47 + j*(23) +109 + j*(130) +-86 + j*(-11) +48 + j*(-79) +-115 + j*(35) +-107 + j*(139) +-181 + j*(244) +33 + j*(-192) +72 + j*(235) +13 + j*(-37) +-188 + j*(-218) +-122 + j*(139) +83 + j*(211) +11 + j*(-64) +-1 + j*(80) +6 + j*(296) +-327 + j*(32) +51 + j*(-163) +5 + j*(-147) +89 + j*(-125) +72 + j*(-122) +163 + j*(119) +45 + j*(-27) +-14 + j*(194) +67 + j*(35) +-115 + j*(138) +-69 + j*(352) +-124 + j*(264) +358 + j*(-136) +16 + j*(-250) +-62 + j*(148) +-21 + j*(-112) +100 + j*(-281) +-192 + j*(256) +-50 + j*(113) +83 + j*(-140) +-53 + j*(-184) +26 + j*(226) +-146 + j*(-12) +59 + j*(323) +92 + j*(-313) +74 + j*(182) +-87 + j*(371) +-54 + j*(388) +102 + j*(-137) +-317 + j*(235) +113 + j*(-13) +-125 + j*(-184) +-296 + j*(-134) +-24 + j*(-75) +211 + j*(-616) +-286 + j*(-27) +153 + j*(129) +-287 + j*(221) +139 + j*(-23) +211 + j*(-58) +34 + j*(-3) +68 + j*(58) +-232 + j*(52) +-57 + j*(-89) +30 + j*(-63) +412 + j*(81) +44 + j*(65) +-155 + j*(248) +-379 + j*(57) +226 + j*(-62) +40 + j*(-147) +50 + j*(-100) +223 + j*(-29) +-38 + j*(-45) +-107 + j*(103) +-33 + j*(-237) +-35 + j*(5) +49 + j*(-75) +230 + j*(-153) +36 + j*(-48) +-76 + j*(64) +17 + j*(-260) +-31 + j*(134) +-52 + j*(-53) +-49 + j*(-129) +-400 + j*(531) +103 + j*(29) +-274 + j*(317) +-204 + j*(297) +33 + j*(2) +-34 + j*(27) +-18 + j*(-21) +118 + j*(49) +-165 + j*(-112) +20 + j*(48) +112 + j*(-151) +-61 + j*(-64) +-165 + j*(-1) +-86 + j*(205) +-132 + j*(-49) +227 + j*(115) +-112 + j*(-151) +-229 + j*(208) +-18 + j*(288) +-11 + j*(-17) +-87 + j*(-221) +59 + j*(-103) +178 + j*(34) +-68 + j*(78) +-331 + j*(236) +-50 + j*(202) +-406 + j*(300) +168 + j*(360) +66 + j*(135) +210 + j*(-129) +261 + j*(-44) +-182 + j*(100) +-231 + j*(-123) +-11 + j*(49) +-225 + j*(-245) +299 + j*(-52) +57 + j*(-13) +-121 + j*(342) +-224 + j*(191) +13 + j*(-150) +-9 + j*(-26) +146 + j*(-146) +192 + j*(-49) +-19 + j*(-104) +92 + j*(-254) +214 + j*(-313) +-219 + j*(19) +-65 + j*(-359) +-255 + j*(-38) +65 + j*(177) +-96 + j*(-128) +-78 + j*(6) +16 + j*(-17) +-260 + j*(-66) +-95 + j*(-110) +193 + j*(87) +77 + j*(-107) +-19 + j*(-52) +-70 + j*(-187) +547 + j*(262) +-59 + j*(-39) +126 + j*(46) +-47 + j*(-180) +18 + j*(-137) +18 + j*(-50) +110 + j*(354) +273 + j*(18) +-44 + j*(-349) +97 + j*(-141) +112 + j*(173) +42 + j*(204) +-33 + j*(-132) +157 + j*(-131) +62 + j*(-146) +84 + j*(-30) +-169 + j*(163) +90 + j*(-85) +-211 + j*(215) +-147 + j*(-100) +-325 + j*(17) +11 + j*(132) +-309 + j*(99) +-291 + j*(-136) +183 + j*(32) +25 + j*(-317) +-243 + j*(-312) +115 + j*(129) +-78 + j*(79) +249 + j*(-482) +160 + j*(-260) +-12 + j*(130) +-395 + j*(1) +330 + j*(-161) +21 + j*(9) +-133 + j*(-103) +361 + j*(-362) +222 + j*(204) +-265 + j*(88) +-35 + j*(197) +-187 + j*(123) +-22 + j*(101) +-37 + j*(12) +-42 + j*(-145) +112 + j*(-66) +-208 + j*(-199) +-221 + j*(181) +2 + j*(-8) +-106 + j*(-108) +238 + j*(28) +113 + j*(-265) +-43 + j*(-2) +-194 + j*(151) +485 + j*(0) +-87 + j*(-110) +-52 + j*(-28) +-11 + j*(144) +63 + j*(-206) +75 + j*(292) +-385 + j*(157) +-62 + j*(223) +-265 + j*(-31) +153 + j*(-35) +-298 + j*(-184) +78 + j*(26) +-50 + j*(192) +42 + j*(150) +27 + j*(-25) +310 + j*(175) +48 + j*(-118) +100 + j*(55) +120 + j*(175) +327 + j*(-191) +65 + j*(-161) +-13 + j*(94) +60 + j*(62) +-109 + j*(-181) +-36 + j*(-14) +-128 + j*(-132) +-124 + j*(-5) +88 + j*(-116) +233 + j*(-172) +124 + j*(-318) +93 + j*(-222) +-46 + j*(-119) +25 + j*(115) +-62 + j*(-232) +182 + j*(-144) +115 + j*(-137) +209 + j*(-123) +-194 + j*(156) +141 + j*(-25) +54 + j*(-33) +228 + j*(151) +161 + j*(-208) +-235 + j*(-128) +77 + j*(433) +-103 + j*(186) +-173 + j*(105) +-28 + j*(-249) +199 + j*(255) +-308 + j*(-40) +72 + j*(-93) +-238 + j*(-285) +549 + j*(58) +-267 + j*(-106) +-11 + j*(-100) +95 + j*(41) +112 + j*(185) +17 + j*(-157) +-20 + j*(163) +-278 + j*(8) +-92 + j*(-59) +-197 + j*(37) +-441 + j*(-72) +-11 + j*(68) +4 + j*(-237) +166 + j*(-2) +15 + j*(-119) +-309 + j*(-29) +-144 + j*(-14) +-230 + j*(-114) +-5 + j*(151) +-181 + j*(-371) +18 + j*(-228) +163 + j*(-178) +13 + j*(248) +-243 + j*(-315) +-116 + j*(101) +146 + j*(206) +88 + j*(60) +111 + j*(-144) +0 + j*(281) +10 + j*(-163) +-59 + j*(127) +517 + j*(11) +73 + j*(35) +172 + j*(12) +47 + j*(4) +-83 + j*(-124) +53 + j*(50) +-148 + j*(-124) +-141 + j*(238) +-54 + j*(41) +-139 + j*(-158) +-196 + j*(374) +-301 + j*(265) +-39 + j*(2) +97 + j*(-139) +-106 + j*(133) +-305 + j*(62) +114 + j*(90) +-55 + j*(-114) +-122 + j*(-102) +8 + j*(-168) +-252 + j*(-70) +-70 + j*(42) +-141 + j*(-4) +-69 + j*(226) +56 + j*(244) +49 + j*(2) +-57 + j*(57) +-194 + j*(122) +-329 + j*(-75) +167 + j*(-91) +-197 + j*(279) +117 + j*(-48) +30 + j*(-26) +-132 + j*(159) +332 + j*(76) +36 + j*(230) +-37 + j*(-238) +-40 + j*(-260) +151 + j*(91) +-77 + j*(60) +98 + j*(27) +251 + j*(-101) +-18 + j*(120) +-93 + j*(-235) +-76 + j*(8) +404 + j*(191) +-8 + j*(-64) +30 + j*(58) +-175 + j*(281) +-102 + j*(-7) +-254 + j*(144) +-15 + j*(13) +393 + j*(-165) +-185 + j*(-293) +-86 + j*(59) +-87 + j*(-224) +-60 + j*(-87) +177 + j*(-240) +455 + j*(64) +78 + j*(-25) +41 + j*(-100) +-71 + j*(-47) +8 + j*(138) +18 + j*(-21) +-141 + j*(195) +127 + j*(185) +-158 + j*(-86) +-62 + j*(5) +206 + j*(103) +156 + j*(-23) +46 + j*(0) +83 + j*(119) +-12 + j*(-33) +-260 + j*(-20) +-59 + j*(-342) +159 + j*(52) +112 + j*(228) +137 + j*(212) +-153 + j*(-200) +-134 + j*(-71) +262 + j*(312) +-369 + j*(-21) +129 + j*(-147) +-73 + j*(-161) +-117 + j*(110) +110 + j*(113) +-8 + j*(49) +52 + j*(296) +-158 + j*(-57) +-72 + j*(94) +-134 + j*(-95) +41 + j*(-303) +177 + j*(-135) +-338 + j*(182) +-182 + j*(33) +-183 + j*(97) +144 + j*(-33) +-47 + j*(-262) +139 + j*(95) +-286 + j*(88) +318 + j*(-64) +119 + j*(252) +-46 + j*(-5) +372 + j*(201) +-144 + j*(103) +-52 + j*(165) +59 + j*(214) +232 + j*(-100) +-237 + j*(85) +-396 + j*(-92) +-230 + j*(126) +-81 + j*(-54) +205 + j*(71) +-80 + j*(-67) +322 + j*(-10) +-101 + j*(-81) +-22 + j*(110) +280 + j*(-179) +26 + j*(-250) +49 + j*(143) +-253 + j*(16) +-140 + j*(70) +238 + j*(177) +165 + j*(27) +-12 + j*(233) +281 + j*(147) +49 + j*(-413) +190 + j*(-138) +-115 + j*(280) +184 + j*(-147) +174 + j*(4) +-112 + j*(56) +-163 + j*(-38) +-260 + j*(201) +257 + j*(-362) +344 + j*(141) +-185 + j*(-252) +257 + j*(135) +-119 + j*(-91) +-13 + j*(-37) +133 + j*(21) +72 + j*(58) +71 + j*(368) +276 + j*(279) +-87 + j*(293) +46 + j*(-38) +-127 + j*(-140) +-55 + j*(40) +180 + j*(-16) +-54 + j*(267) +59 + j*(213) +24 + j*(-54) +-160 + j*(-71) +-115 + j*(-206) +0 + j*(-27) +30 + j*(63) +175 + j*(48) +250 + j*(107) +141 + j*(-119) +-46 + j*(-228) +141 + j*(55) +-11 + j*(-161) +71 + j*(-49) +132 + j*(-453) +-171 + j*(134) +-240 + j*(-64) +-238 + j*(-89) +215 + j*(143) +95 + j*(-177) +-115 + j*(12) +-98 + j*(-80) +168 + j*(-66) +83 + j*(33) +-310 + j*(256) +108 + j*(-310) +206 + j*(83) +103 + j*(61) +-42 + j*(-98) +117 + j*(-24) +12 + j*(66) +-107 + j*(-325) +-97 + j*(-29) +279 + j*(-264) +-112 + j*(-161) +-330 + j*(88) +-315 + j*(-161) +-74 + j*(-153) +102 + j*(235) +-49 + j*(358) +298 + j*(-292) +170 + j*(292) +139 + j*(254) +-199 + j*(-175) +238 + j*(181) +-100 + j*(77) +-125 + j*(382) +69 + j*(40) +-155 + j*(-226) +-220 + j*(-99) +-39 + j*(-467) +-185 + j*(-52) +-100 + j*(-15) +-55 + j*(84) +80 + j*(278) +52 + j*(-245) +-37 + j*(-181) +194 + j*(358) +180 + j*(25) +215 + j*(-21) +-254 + j*(128) +208 + j*(43) +148 + j*(-43) +80 + j*(168) +168 + j*(-79) +-107 + j*(-41) +98 + j*(250) +-51 + j*(-281) +81 + j*(-32) +-45 + j*(-207) +95 + j*(31) +29 + j*(60) +-104 + j*(-112) +16 + j*(175) +64 + j*(-142) +-16 + j*(-264) +90 + j*(-200) +106 + j*(-193) +-76 + j*(-26) +-81 + j*(226) +4 + j*(-62) +-105 + j*(-92) +-64 + j*(-13) +-118 + j*(-20) +-76 + j*(-79) +153 + j*(52) +-29 + j*(216) +-237 + j*(305) +-57 + j*(43) +251 + j*(-64) +65 + j*(-22) +-66 + j*(-105) +-46 + j*(30) +-124 + j*(-200) +186 + j*(108) +-303 + j*(98) +127 + j*(-165) +35 + j*(-56) +-58 + j*(30) +150 + j*(155) +-151 + j*(-247) +-194 + j*(-41) +-150 + j*(6) +-230 + j*(92) +-91 + j*(37) +219 + j*(-158) +-185 + j*(44) +97 + j*(-40) +-209 + j*(43) +-160 + j*(44) +111 + j*(-115) +-206 + j*(2) +-380 + j*(-145) +-291 + j*(185) +-16 + j*(211) +65 + j*(73) +-13 + j*(137) +14 + j*(68) +19 + j*(24) +-10 + j*(235) +21 + j*(-56) +36 + j*(-182) +-54 + j*(25) +209 + j*(-83) +-146 + j*(305) +138 + j*(-47) +-152 + j*(-73) +218 + j*(23) +56 + j*(-35) +267 + j*(17) +214 + j*(-84) +-240 + j*(309) +98 + j*(45) +211 + j*(-54) +133 + j*(-213) +1 + j*(87) +-165 + j*(78) +-58 + j*(-218) +10 + j*(-103) +-237 + j*(82) +-180 + j*(17) +-169 + j*(-69) +-100 + j*(-223) +339 + j*(34) +288 + j*(-133) +-148 + j*(-80) +124 + j*(-6) +278 + j*(115) +88 + j*(39) +-99 + j*(-206) +54 + j*(198) +-30 + j*(92) +-75 + j*(-107) +237 + j*(185) +-15 + j*(-160) +141 + j*(182) +129 + j*(169) +72 + j*(9) +-214 + j*(236) +133 + j*(21) +-25 + j*(74) +-122 + j*(-70) +-260 + j*(163) +-24 + j*(-200) +-235 + j*(45) +185 + j*(207) +-279 + j*(54) +-241 + j*(-18) +-153 + j*(-87) +-255 + j*(40) +-113 + j*(-238) +369 + j*(24) +218 + j*(57) +205 + j*(637) +19 + j*(61) +66 + j*(25) +-217 + j*(-431) +62 + j*(208) +269 + j*(-142) +16 + j*(122) +56 + j*(-24) +-279 + j*(-170) +-141 + j*(233) +339 + j*(-234) +-99 + j*(-257) +-145 + j*(263) +57 + j*(-175) +36 + j*(250) +-94 + j*(-114) +-196 + j*(13) +57 + j*(242) +18 + j*(216) +-37 + j*(291) +264 + j*(-162) +-219 + j*(178) +349 + j*(211) +204 + j*(-43) +21 + j*(93) +21 + j*(-221) +41 + j*(-16) +-98 + j*(-230) +-264 + j*(-47) +126 + j*(-108) +268 + j*(-69) +41 + j*(65) +76 + j*(301) +-84 + j*(-194) +-156 + j*(-68) +-6 + j*(-103) +-9 + j*(-292) +-274 + j*(-38) +-128 + j*(-166) +57 + j*(127) +-155 + j*(-173) +-35 + j*(-301) +-120 + j*(390) +-71 + j*(-32) +-16 + j*(-83) +-28 + j*(-132) +146 + j*(-89) +-233 + j*(134) +-136 + j*(-153) +-62 + j*(-111) +0 + j*(-173) +240 + j*(314) +-331 + j*(-113) +215 + j*(99) +-129 + j*(92) +81 + j*(183) +103 + j*(-28) +-305 + j*(25) +64 + j*(165) +31 + j*(-141) +503 + j*(144) +-18 + j*(-52) +-139 + j*(9) +-247 + j*(102) +-14 + j*(-35) +139 + j*(-177) +-218 + j*(1) +-123 + j*(-48) +-13 + j*(152) +164 + j*(342) +-188 + j*(-28) +102 + j*(-18) +-275 + j*(-183) +-140 + j*(105) +-89 + j*(-166) +150 + j*(-127) +153 + j*(202) +-160 + j*(98) +-30 + j*(-16) +136 + j*(36) +164 + j*(165) +-61 + j*(-130) +232 + j*(-411) +-65 + j*(129) +184 + j*(-213) +-237 + j*(134) +-322 + j*(240) +-18 + j*(45) +52 + j*(-71) +202 + j*(-8) +-103 + j*(-185) +-91 + j*(56) +-245 + j*(-260) +-168 + j*(260) +-35 + j*(30) +57 + j*(-226) +57 + j*(49) +199 + j*(-151) +43 + j*(28) +-358 + j*(64) +-94 + j*(-109) +270 + j*(-82) +132 + j*(7) +206 + j*(10) +506 + j*(-12) +-49 + j*(-83) +-315 + j*(-318) +-15 + j*(277) +-157 + j*(-344) +379 + j*(221) +377 + j*(59) +308 + j*(-408) +-211 + j*(228) +16 + j*(-142) +-260 + j*(-234) +-285 + j*(-187) +272 + j*(170) +-99 + j*(209) +-125 + j*(86) +-326 + j*(-369) +-164 + j*(-24) +-109 + j*(388) +-103 + j*(-238) +-169 + j*(-40) +10 + j*(-123) +190 + j*(-354) +-339 + j*(141) +176 + j*(-11) +-105 + j*(4) +-83 + j*(-327) +-14 + j*(-84) +86 + j*(65) +206 + j*(100) +279 + j*(-349) +-328 + j*(191) +21 + j*(-1) +77 + j*(174) +49 + j*(-45) +32 + j*(-206) +-141 + j*(75) +-64 + j*(33) +174 + j*(88) +328 + j*(-105) +222 + j*(400) +-209 + j*(493) +-165 + j*(-93) +-6 + j*(126) +30 + j*(-97) +-117 + j*(-136) +-81 + j*(-33) +12 + j*(2) +261 + j*(93) +11 + j*(-62) +10 + j*(98) +-125 + j*(-16) +141 + j*(226) +182 + j*(-117) +94 + j*(283) +-136 + j*(-20) +455 + j*(-54) +-87 + j*(75) +-151 + j*(226) +-253 + j*(54) +-8 + j*(-204) +-62 + j*(-136) +-182 + j*(148) +-16 + j*(74) +-17 + j*(-224) +-67 + j*(-27) +138 + j*(30) +81 + j*(71) +-7 + j*(-83) +127 + j*(98) +22 + j*(-260) +312 + j*(-258) +-189 + j*(31) +159 + j*(158) +240 + j*(-91) +-32 + j*(-305) +78 + j*(26) +48 + j*(242) +-66 + j*(117) +176 + j*(-287) +-78 + j*(0) +300 + j*(119) +128 + j*(-288) +22 + j*(161) +373 + j*(192) +272 + j*(70) +-50 + j*(84) +3 + j*(54) +26 + j*(86) +49 + j*(182) +46 + j*(-55) +-124 + j*(188) +-196 + j*(277) +37 + j*(26) +-77 + j*(-10) +130 + j*(-244) +-35 + j*(421) +9 + j*(219) +177 + j*(49) +48 + j*(-383) +-43 + j*(141) +-102 + j*(76) +132 + j*(47) +-154 + j*(56) +-26 + j*(-116) +-93 + j*(30) +-99 + j*(-182) +-301 + j*(-375) +47 + j*(-53) +196 + j*(-124) +-271 + j*(-64) +-61 + j*(-177) +-325 + j*(-323) +8 + j*(147) +32 + j*(67) +-158 + j*(-103) +97 + j*(-142) +193 + j*(-113) +168 + j*(-134) +12 + j*(122) +-45 + j*(172) +153 + j*(59) +271 + j*(-115) +296 + j*(-90) +-117 + j*(-60) +-380 + j*(-109) +-173 + j*(-264) +25 + j*(-51) +484 + j*(32) +-175 + j*(52) +-358 + j*(212) +81 + j*(-68) +10 + j*(128) +-103 + j*(-35) +44 + j*(351) +202 + j*(36) +-97 + j*(279) +87 + j*(103) +-70 + j*(27) +133 + j*(235) +109 + j*(199) +146 + j*(88) +-90 + j*(-188) +-433 + j*(-84) +-101 + j*(-179) +202 + j*(-115) +209 + j*(-90) +28 + j*(103) +-146 + j*(168) +128 + j*(134) +273 + j*(158) +-272 + j*(169) +-179 + j*(-197) +-387 + j*(-228) +-86 + j*(-306) +161 + j*(-260) +-61 + j*(-40) +-128 + j*(-26) +-1 + j*(188) +133 + j*(-36) +-50 + j*(41) +-20 + j*(-163) +163 + j*(68) +134 + j*(183) +-278 + j*(-277) +168 + j*(294) +-473 + j*(-18) +25 + j*(364) +61 + j*(-151) +83 + j*(59) +45 + j*(-225) +76 + j*(105) +162 + j*(-346) +101 + j*(94) +-37 + j*(-292) +-23 + j*(-143) +170 + j*(49) +-14 + j*(-16) +22 + j*(71) +-111 + j*(-79) +188 + j*(-58) +-122 + j*(-239) +252 + j*(161) +-45 + j*(-11) +25 + j*(-204) +279 + j*(-64) +-137 + j*(-185) +-114 + j*(23) +133 + j*(185) +188 + j*(212) +-41 + j*(51) +141 + j*(-110) +-96 + j*(-378) +58 + j*(-146) +152 + j*(-47) +35 + j*(30) +144 + j*(-59) +-202 + j*(64) +-265 + j*(-29) +69 + j*(-327) +-15 + j*(54) +13 + j*(-119) +-33 + j*(273) +-203 + j*(81) +-108 + j*(275) +-109 + j*(119) +-165 + j*(-93) +-108 + j*(309) +-100 + j*(-303) +269 + j*(-175) +-293 + j*(95) +-129 + j*(183) +187 + j*(-76) +317 + j*(-244) +131 + j*(30) +-293 + j*(-280) +-96 + j*(170) +11 + j*(219) +-88 + j*(-159) +-386 + j*(-183) +-385 + j*(141) +13 + j*(252) +-184 + j*(-351) +473 + j*(213) +6 + j*(-129) +13 + j*(216) +66 + j*(1) +257 + j*(-221) +332 + j*(164) +-60 + j*(74) +-113 + j*(-6) +-59 + j*(264) +-11 + j*(37) +-74 + j*(263) +80 + j*(-193) +-12 + j*(-102) +74 + j*(-3) +-25 + j*(-152) +358 + j*(121) +134 + j*(69) +-374 + j*(77) +323 + j*(-186) +47 + j*(72) +-14 + j*(-469) +-23 + j*(-97) +-92 + j*(264) +100 + j*(-27) +158 + j*(-268) +32 + j*(55) +291 + j*(-216) +-260 + j*(194) +97 + j*(159) +-21 + j*(-142) +-152 + j*(-19) +-64 + j*(358) +162 + j*(18) +-225 + j*(90) +-127 + j*(234) +64 + j*(43) +141 + j*(45) +-250 + j*(9) +52 + j*(-197) +202 + j*(114) +-103 + j*(90) +306 + j*(-103) +385 + j*(21) +-66 + j*(-288) +-187 + j*(-74) +-9 + j*(-46) +420 + j*(146) +-13 + j*(166) +-168 + j*(81) +-267 + j*(-56) +98 + j*(-157) +-362 + j*(155) +339 + j*(76) +190 + j*(25) +-40 + j*(324) +-40 + j*(135) +-176 + j*(-10) +-62 + j*(-112) +42 + j*(201) +-52 + j*(-45) +290 + j*(-97) +190 + j*(98) +134 + j*(-165) +-162 + j*(-31) +-290 + j*(92) +-80 + j*(-121) +-72 + j*(217) +-151 + j*(-44) +42 + j*(140) +185 + j*(-230) +144 + j*(9) +188 + j*(107) +-9 + j*(174) +32 + j*(-89) +387 + j*(107) +185 + j*(232) +-91 + j*(40) +-83 + j*(137) +114 + j*(14) +180 + j*(12) +-35 + j*(318) +-139 + j*(-17) +-3 + j*(-109) +163 + j*(-286) +-211 + j*(-83) +29 + j*(21) +401 + j*(-445) +-81 + j*(-83) +-98 + j*(-218) +-121 + j*(-2) +115 + j*(17) +78 + j*(-435) +98 + j*(40) +304 + j*(139) +53 + j*(166) +185 + j*(130) +-115 + j*(-383) +-170 + j*(-74) +-49 + j*(-89) +7 + j*(77) +229 + j*(-230) +91 + j*(-82) +19 + j*(60) +-278 + j*(-250) +-127 + j*(25) +229 + j*(-180) +-57 + j*(36) +-25 + j*(163) +84 + j*(-128) +59 + j*(88) +-171 + j*(-7) +114 + j*(255) +35 + j*(109) +-44 + j*(409) +-210 + j*(-250) +-69 + j*(66) +-121 + j*(48) +125 + j*(-195) +107 + j*(55) +-1 + j*(-103) +264 + j*(24) +35 + j*(-345) +-250 + j*(-409) +195 + j*(6) +-60 + j*(-27) +-64 + j*(147) +-33 + j*(92) +-25 + j*(-93) +-228 + j*(-18) +-37 + j*(-191) +78 + j*(-4) +-69 + j*(-494) +-152 + j*(261) +-6 + j*(146) +-361 + j*(-142) +-65 + j*(176) +244 + j*(78) +-58 + j*(-261) +-58 + j*(-259) +-66 + j*(-286) +-186 + j*(181) +-257 + j*(-41) +194 + j*(354) +47 + j*(93) +-121 + j*(31) +136 + j*(-87) +10 + j*(190) +-272 + j*(-148) +-107 + j*(-56) +115 + j*(-47) +-53 + j*(-172) +45 + j*(-48) +347 + j*(-141) +66 + j*(-78) +-156 + j*(122) +50 + j*(-180) +217 + j*(-42) +-210 + j*(-83) +228 + j*(189) +583 + j*(-493) +196 + j*(153) +40 + j*(-85) +105 + j*(8) +-49 + j*(-282) +164 + j*(-246) +-35 + j*(-301) +129 + j*(252) +-268 + j*(125) +-144 + j*(116) +-309 + j*(112) +40 + j*(-140) +42 + j*(-145) +39 + j*(161) +-340 + j*(243) +-55 + j*(-122) +167 + j*(135) +-185 + j*(122) +66 + j*(-51) +200 + j*(46) +67 + j*(-173) +-50 + j*(126) +536 + j*(-277) +66 + j*(-58) +-182 + j*(208) +-59 + j*(-201) +253 + j*(46) +-20 + j*(-202) +66 + j*(269) +395 + j*(128) +-171 + j*(263) +-45 + j*(-102) +-135 + j*(13) +-194 + j*(109) +-115 + j*(313) +21 + j*(310) +-22 + j*(-176) +-59 + j*(-142) +274 + j*(33) +50 + j*(-194) +-39 + j*(210) +-163 + j*(-13) +-247 + j*(316) +163 + j*(-173) +54 + j*(-386) +49 + j*(293) +-6 + j*(286) +-254 + j*(-59) +-308 + j*(-129) +141 + j*(-104) +-262 + j*(-76) +-92 + j*(346) +318 + j*(-88) +134 + j*(248) +-27 + j*(-118) +119 + j*(145) +-185 + j*(-234) +-141 + j*(-91) +-95 + j*(-129) +151 + j*(-233) +-91 + j*(-215) +-105 + j*(-1) +-32 + j*(-80) +133 + j*(-57) +-52 + j*(-29) +-103 + j*(-84) +-65 + j*(-89) +-83 + j*(38) +-42 + j*(-209) +-243 + j*(-137) +-74 + j*(-73) +-167 + j*(33) +-197 + j*(-66) +12 + j*(-21) +88 + j*(-200) +129 + j*(108) +335 + j*(71) +54 + j*(-274) +-129 + j*(-361) +338 + j*(-28) +35 + j*(-118) +-44 + j*(-242) +-66 + j*(-45) +-290 + j*(-136) +-23 + j*(180) +176 + j*(86) +63 + j*(-119) +68 + j*(-148) +-366 + j*(-110) +138 + j*(86) +-22 + j*(80) +72 + j*(28) +-49 + j*(-218) +64 + j*(14) +364 + j*(-48) +221 + j*(-61) +212 + j*(175) +-34 + j*(199) +-25 + j*(135) +239 + j*(-129) +-253 + j*(-223) +103 + j*(148) +100 + j*(199) +331 + j*(103) +256 + j*(-104) +194 + j*(78) +170 + j*(-54) +-51 + j*(83) +-112 + j*(288) +298 + j*(88) +-196 + j*(-251) +-5 + j*(33) +104 + j*(-231) +-233 + j*(-22) +115 + j*(-112) +15 + j*(7) +147 + j*(-501) +223 + j*(60) +-243 + j*(-366) +-35 + j*(100) +-64 + j*(-82) +-236 + j*(-47) +137 + j*(-5) +31 + j*(-117) +401 + j*(436) +-192 + j*(-45) +78 + j*(-392) +-258 + j*(263) +-303 + j*(-162) +119 + j*(169) +211 + j*(58) +-53 + j*(117) +-28 + j*(-269) +107 + j*(-180) +107 + j*(-92) +-80 + j*(22) +356 + j*(127) +-168 + j*(91) +-199 + j*(-310) +-117 + j*(-108) +-193 + j*(-369) +60 + j*(156) +62 + j*(77) +-21 + j*(-73) +-219 + j*(-141) +-418 + j*(11) +-44 + j*(-158) +297 + j*(-14) +183 + j*(285) +-77 + j*(-115) +-92 + j*(-203) +302 + j*(-100) +234 + j*(-197) +275 + j*(88) +57 + j*(-214) +52 + j*(-255) +164 + j*(214) +119 + j*(-187) +117 + j*(86) +-3 + j*(340) +95 + j*(-66) +32 + j*(-25) +-200 + j*(105) +-76 + j*(126) +91 + j*(37) +-245 + j*(-36) +-120 + j*(77) +120 + j*(-119) +-99 + j*(-166) +-4 + j*(137) +41 + j*(151) +-182 + j*(35) +-151 + j*(-89) +-63 + j*(-212) +269 + j*(164) +284 + j*(163) +123 + j*(87) +-55 + j*(-116) +68 + j*(-134) +-62 + j*(-74) +57 + j*(100) +204 + j*(159) +255 + j*(182) +40 + j*(-157) +-81 + j*(118) +-11 + j*(-113) +168 + j*(-326) +158 + j*(8) +-139 + j*(-2) +103 + j*(-64) +54 + j*(606) +202 + j*(32) +-240 + j*(-212) +-236 + j*(-55) +25 + j*(-208) +124 + j*(-163) +127 + j*(-118) +-194 + j*(50) +23 + j*(106) +178 + j*(-280) +92 + j*(-33) +-42 + j*(126) +208 + j*(159) +-103 + j*(-33) +247 + j*(70) +-337 + j*(253) +-83 + j*(-166) +-199 + j*(12) +-92 + j*(542) +178 + j*(-195) +-115 + j*(-338) +146 + j*(82) +-163 + j*(-86) +-88 + j*(-90) +19 + j*(-390) +-59 + j*(-48) +81 + j*(165) +103 + j*(-173) +47 + j*(-240) +-453 + j*(-52) +-102 + j*(234) +-272 + j*(161) +81 + j*(-75) +-143 + j*(-223) +-126 + j*(-250) +134 + j*(-209) +45 + j*(-143) +-290 + j*(-23) +-88 + j*(14) +382 + j*(-177) +-407 + j*(-16) +-9 + j*(-69) +401 + j*(-166) +127 + j*(-6) +149 + j*(-99) +-124 + j*(-21) +17 + j*(-229) +-5 + j*(23) +-173 + j*(34) +34 + j*(59) +204 + j*(-1) +48 + j*(253) +247 + j*(154) +-158 + j*(172) +-81 + j*(340) +-23 + j*(-86) +-18 + j*(26) +6 + j*(-112) +-252 + j*(-152) +186 + j*(148) +-199 + j*(76) +330 + j*(6) +13 + j*(-215) +-279 + j*(-163) +52 + j*(-40) +-167 + j*(-231) +-236 + j*(129) +78 + j*(-25) +147 + j*(-44) +119 + j*(125) +-149 + j*(-324) +1 + j*(-77) +-201 + j*(-49) +250 + j*(-146) +15 + j*(-36) +56 + j*(-78) +-35 + j*(-8) +-110 + j*(14) +170 + j*(-251) +-460 + j*(-7) +-32 + j*(-224) +-18 + j*(86) +-17 + j*(-165) +417 + j*(-276) +-87 + j*(72) +-205 + j*(-112) +0 + j*(-154) +-8 + j*(-245) +147 + j*(27) +89 + j*(-115) +-16 + j*(-88) +-187 + j*(-146) +-93 + j*(8) +-11 + j*(181) +-159 + j*(4) +-132 + j*(92) +-23 + j*(-123) +223 + j*(69) +-5 + j*(249) +-127 + j*(291) +95 + j*(4) +59 + j*(228) +75 + j*(-275) +-171 + j*(11) +-136 + j*(-105) +-198 + j*(204) +-57 + j*(5) +3 + j*(-324) +-538 + j*(-66) +74 + j*(-358) +467 + j*(20) +-421 + j*(-13) +46 + j*(-384) +-553 + j*(-285) +178 + j*(18) +-197 + j*(97) +333 + j*(-331) +-301 + j*(-172) +50 + j*(-204) +291 + j*(331) +-132 + j*(-193) +-199 + j*(382) +-44 + j*(-281) +33 + j*(177) +18 + j*(624) +291 + j*(-469) +-192 + j*(71) +-414 + j*(254) +-331 + j*(-499) +281 + j*(-560) +-112 + j*(-367) +-390 + j*(-414) +274 + j*(-482) +373 + j*(-433) +320 + j*(128) +250 + j*(-570) +-4 + j*(364) +345 + j*(329) +-415 + j*(450) +384 + j*(-269) +-269 + j*(337) +-714 + j*(-90) +-144 + j*(-327) +92 + j*(-220) +-202 + j*(-617) +368 + j*(187) +-391 + j*(445) +-446 + j*(485) +606 + j*(-561) +-156 + j*(266) +346 + j*(262) +44 + j*(288) +6 + j*(132) +199 + j*(107) +517 + j*(165) +59 + j*(218) +371 + j*(-624) +278 + j*(0) +-479 + j*(-395) +390 + j*(-21) +233 + j*(52) +-342 + j*(371) +-434 + j*(473) +-187 + j*(-260) +-327 + j*(412) +-393 + j*(179) +-523 + j*(-187) +-343 + j*(-66) +295 + j*(193) +132 + j*(-379) +298 + j*(-465) +-434 + j*(26) +-532 + j*(284) +-207 + j*(-152) +-286 + j*(412) +-233 + j*(-143) +49 + j*(185) +11 + j*(10) +-176 + j*(527) +395 + j*(203) +-45 + j*(356) +264 + j*(-517) +189 + j*(-214) +325 + j*(-169) +-23 + j*(114) +-362 + j*(190) +-424 + j*(-215) +442 + j*(496) +-311 + j*(-489) +347 + j*(19) +-66 + j*(-206) +-299 + j*(-675) +-133 + j*(-135) +369 + j*(312) +-94 + j*(467) +222 + j*(-23) +177 + j*(240) +-163 + j*(-114) +278 + j*(-13) +168 + j*(523) +-314 + j*(127) +-484 + j*(119) +298 + j*(522) +-288 + j*(-101) +-369 + j*(448) +62 + j*(138) +74 + j*(176) +-442 + j*(-165) +25 + j*(-23) +540 + j*(622) +92 + j*(82) +-477 + j*(187) +134 + j*(-74) +308 + j*(176) +213 + j*(-274) +-223 + j*(-270) +-400 + j*(393) +544 + j*(-454) +337 + j*(-287) +-313 + j*(466) +304 + j*(397) +118 + j*(-298) +-496 + j*(358) +58 + j*(-314) +-18 + j*(56) +-37 + j*(-183) +85 + j*(-219) +470 + j*(-586) +-557 + j*(-581) +425 + j*(194) +-148 + j*(-387) +111 + j*(66) +433 + j*(412) +330 + j*(-301) +284 + j*(-236) +-71 + j*(156) +243 + j*(-194) +323 + j*(692) +49 + j*(547) +-98 + j*(232) +-141 + j*(-212) +57 + j*(250) +313 + j*(-370) +-641 + j*(-368) +-259 + j*(-291) +-16 + j*(-18) +-689 + j*(241) +-308 + j*(-279) +392 + j*(-391) +271 + j*(-156) +40 + j*(334) +84 + j*(-208) +-247 + j*(123) +122 + j*(-320) +293 + j*(-576) +-299 + j*(446) +-459 + j*(-285) +-474 + j*(-351) +119 + j*(129) +-264 + j*(110) +-203 + j*(411) +245 + j*(52) +215 + j*(-194) +-147 + j*(333) +-242 + j*(-580) +255 + j*(140) +107 + j*(-214) +223 + j*(139) +-246 + j*(-601) +219 + j*(-79) +232 + j*(-344) +250 + j*(-248) +76 + j*(64) +380 + j*(-157) +125 + j*(325) +-306 + j*(257) +317 + j*(199) +-364 + j*(435) +-135 + j*(-126) +47 + j*(-95) +-303 + j*(-332) +-411 + j*(416) +-205 + j*(-384) +341 + j*(-59) +-47 + j*(-214) +-64 + j*(-122) +284 + j*(352) +-300 + j*(270) +419 + j*(175) +201 + j*(-445) +269 + j*(409) +381 + j*(225) +262 + j*(487) +-52 + j*(-374) +33 + j*(-332) +-221 + j*(-178) +57 + j*(-252) +-325 + j*(325) +218 + j*(546) +-151 + j*(0) +262 + j*(-284) +240 + j*(428) +144 + j*(123) +254 + j*(-41) +-361 + j*(365) +-5 + j*(288) +392 + j*(-202) +316 + j*(238) +296 + j*(165) +16 + j*(468) +36 + j*(290) +-267 + j*(-337) +119 + j*(396) +-428 + j*(401) +-301 + j*(-145) +288 + j*(-189) +506 + j*(-230) +-116 + j*(-116) +-217 + j*(-225) +171 + j*(-210) +444 + j*(-202) +223 + j*(124) +-432 + j*(522) +133 + j*(235) +-234 + j*(-372) +-84 + j*(-268) +-142 + j*(-271) +189 + j*(148) +67 + j*(16) +342 + j*(278) +355 + j*(319) +115 + j*(-101) +631 + j*(-556) +267 + j*(344) +-472 + j*(-622) +-483 + j*(433) +327 + j*(373) +-462 + j*(457) +-331 + j*(139) +-59 + j*(-136) +276 + j*(-262) +-57 + j*(182) +-319 + j*(168) +-277 + j*(132) +351 + j*(-30) +-111 + j*(260) +-291 + j*(560) +425 + j*(622) +221 + j*(-26) +121 + j*(54) +-103 + j*(271) +-273 + j*(-501) +608 + j*(-200) +-373 + j*(-40) +103 + j*(-91) +33 + j*(107) +-253 + j*(302) +208 + j*(-200) +-401 + j*(78) +-143 + j*(-327) +354 + j*(-397) +-85 + j*(-421) +280 + j*(-222) +320 + j*(-242) +283 + j*(-122) +-399 + j*(407) +-46 + j*(9) +244 + j*(171) +462 + j*(-53) +-617 + j*(-304) +-309 + j*(115) +493 + j*(-261) +-403 + j*(140) +-300 + j*(86) +643 + j*(4) +339 + j*(-296) +-363 + j*(-57) +-72 + j*(472) +199 + j*(-41) +-198 + j*(212) +369 + j*(185) +228 + j*(-564) +-215 + j*(-262) +-423 + j*(-37) +-159 + j*(371) +-373 + j*(-308) +-371 + j*(241) +-204 + j*(-335) +68 + j*(182) +-284 + j*(-345) +-332 + j*(-184) +418 + j*(255) +3 + j*(-298) +437 + j*(219) +66 + j*(-67) +98 + j*(-235) +-384 + j*(288) +-322 + j*(271) +-377 + j*(-383) +517 + j*(-313) +53 + j*(211) +356 + j*(158) +131 + j*(23) +-161 + j*(-13) +284 + j*(-383) +414 + j*(50) +295 + j*(-61) +239 + j*(-342) +289 + j*(-161) +458 + j*(-262) +-348 + j*(-588) +-573 + j*(215) +266 + j*(463) +344 + j*(-51) +4 + j*(383) +226 + j*(-94) +306 + j*(-347) +206 + j*(11) +347 + j*(151) +-305 + j*(337) +433 + j*(302) +-28 + j*(527) +-534 + j*(-516) +248 + j*(206) +33 + j*(70) +-18 + j*(-231) +231 + j*(-226) +-456 + j*(-378) +112 + j*(-158) +-90 + j*(-523) +52 + j*(-177) +-156 + j*(-113) +46 + j*(268) +22 + j*(422) +-191 + j*(-325) +-315 + j*(-511) +-562 + j*(-180) +-69 + j*(-325) +591 + j*(288) +-554 + j*(337) +-305 + j*(358) +-340 + j*(-383) +-443 + j*(412) +98 + j*(-349) +-403 + j*(219) +401 + j*(-107) +209 + j*(-242) +-416 + j*(307) +470 + j*(-292) +249 + j*(344) +84 + j*(520) +-99 + j*(-9) +-381 + j*(240) +52 + j*(-255) +-315 + j*(228) +165 + j*(-340) +-385 + j*(-367) +378 + j*(11) +486 + j*(-447) +574 + j*(-212) +-550 + j*(-66) +296 + j*(443) +-421 + j*(-38) +-15 + j*(334) +156 + j*(-60) +291 + j*(184) +-148 + j*(-100) +-99 + j*(294) +214 + j*(76) +349 + j*(-234) +291 + j*(263) +-121 + j*(-279) +-119 + j*(-69) +187 + j*(204) +340 + j*(-244) +-297 + j*(244) +-8 + j*(-47) +-105 + j*(-7) +-196 + j*(-63) +-105 + j*(35) +405 + j*(69) +423 + j*(219) +-462 + j*(-112) +-197 + j*(-422) +224 + j*(81) +-612 + j*(71) +363 + j*(209) +133 + j*(-302) +235 + j*(418) +-315 + j*(479) +-166 + j*(-6) +-97 + j*(140) +278 + j*(451) +-301 + j*(212) +-412 + j*(-291) +446 + j*(224) +108 + j*(-417) +487 + j*(269) +-527 + j*(156) +-550 + j*(-249) +543 + j*(424) +-126 + j*(57) +-230 + j*(-80) +-40 + j*(-153) +-22 + j*(-342) +-75 + j*(-334) +339 + j*(-45) +-105 + j*(36) +151 + j*(81) +-457 + j*(499) +207 + j*(-512) +-276 + j*(462) +-246 + j*(-299) +-155 + j*(-314) +-18 + j*(-281) +233 + j*(-358) +564 + j*(-344) +-448 + j*(-518) +477 + j*(84) +-371 + j*(-276) +453 + j*(187) +-252 + j*(-148) +459 + j*(370) +-31 + j*(-509) +-215 + j*(-175) +-177 + j*(-291) +-182 + j*(-204) +298 + j*(47) +200 + j*(-255) +-353 + j*(-530) +182 + j*(-202) +-296 + j*(-480) +370 + j*(-175) +-250 + j*(-131) +-74 + j*(-313) +-115 + j*(-626) +326 + j*(274) +-16 + j*(-218) +-151 + j*(-180) +-474 + j*(374) +378 + j*(-107) +141 + j*(245) +113 + j*(-241) +-526 + j*(1) +-300 + j*(-199) +550 + j*(-174) +392 + j*(166) +110 + j*(-38) +301 + j*(-351) +284 + j*(-59) +223 + j*(-526) +-282 + j*(608) +317 + j*(332) +-503 + j*(-453) +-366 + j*(518) +349 + j*(1) +310 + j*(279) +-163 + j*(-223) +-21 + j*(-283) +443 + j*(-171) +262 + j*(-201) +317 + j*(441) +75 + j*(-129) +-223 + j*(223) +296 + j*(91) +-455 + j*(-91) +-651 + j*(175) +359 + j*(-354) +-51 + j*(512) +540 + j*(-234) +-161 + j*(-114) +349 + j*(-91) +-20 + j*(290) +-208 + j*(-203) +-25 + j*(161) +-315 + j*(373) +286 + j*(-8) +125 + j*(395) +-95 + j*(53) +332 + j*(-238) +-211 + j*(-252) +-69 + j*(-207) +-617 + j*(268) +-103 + j*(356) +-131 + j*(393) +-310 + j*(-280) +-245 + j*(-274) +-2 + j*(-759) +-375 + j*(-166) +-215 + j*(182) +315 + j*(230) +-190 + j*(158) +-446 + j*(333) +226 + j*(355) +344 + j*(-258) +16 + j*(-428) +-372 + j*(301) +393 + j*(189) +293 + j*(-177) +455 + j*(-136) +-35 + j*(-170) +16 + j*(-351) +-16 + j*(-304) +-127 + j*(205) +-550 + j*(-288) +-10 + j*(-56) +-173 + j*(-178) +-307 + j*(164) +-329 + j*(175) +-215 + j*(-426) +397 + j*(211) +289 + j*(-257) +-272 + j*(23) +-107 + j*(-281) +179 + j*(168) +26 + j*(-535) +23 + j*(234) +302 + j*(392) +-164 + j*(-396) +52 + j*(231) +194 + j*(-21) +-352 + j*(-203) +-338 + j*(146) +-677 + j*(-162) +-191 + j*(-365) +-387 + j*(493) +-414 + j*(242) +-103 + j*(243) +-315 + j*(-6) +-612 + j*(210) +41 + j*(-360) +-133 + j*(-148) +-368 + j*(241) +54 + j*(-62) +398 + j*(-445) +-71 + j*(-591) +98 + j*(273) +-729 + j*(338) +-323 + j*(-267) +355 + j*(-348) +163 + j*(510) +508 + j*(-466) +-651 + j*(-209) +189 + j*(168) +487 + j*(150) +364 + j*(111) +267 + j*(-54) +427 + j*(211) +-412 + j*(594) +-238 + j*(-31) +-233 + j*(328) +192 + j*(115) +305 + j*(297) +484 + j*(436) +-35 + j*(180) +-129 + j*(-513) +-51 + j*(-513) +-398 + j*(-67) +162 + j*(373) +638 + j*(376) +641 + j*(-561) +-204 + j*(-426) +551 + j*(-218) +-161 + j*(556) +474 + j*(226) +-243 + j*(-293) +16 + j*(-136) +-474 + j*(-295) +-490 + j*(-260) +252 + j*(-169) +-363 + j*(209) +-151 + j*(457) +-361 + j*(-232) +-168 + j*(460) +32 + j*(-496) +-92 + j*(-243) +-503 + j*(-238) +367 + j*(148) +-56 + j*(258) +-156 + j*(98) +-250 + j*(-78) +-107 + j*(-18) +298 + j*(257) +-404 + j*(-225) +-339 + j*(-220) +-61 + j*(-391) +-600 + j*(-141) +304 + j*(-457) +-280 + j*(146) +206 + j*(421) +355 + j*(709) +153 + j*(225) +124 + j*(-206) +373 + j*(-447) +-442 + j*(88) +269 + j*(-115) +-335 + j*(-300) +-158 + j*(-78) +-320 + j*(-414) +491 + j*(-345) +559 + j*(252) +-67 + j*(-332) +-394 + j*(-370) +242 + j*(-639) +-349 + j*(286) +98 + j*(57) +506 + j*(286) +117 + j*(-76) +-506 + j*(47) +-100 + j*(156) +-59 + j*(-168) +162 + j*(363) +-142 + j*(298) +110 + j*(139) +163 + j*(184) +-107 + j*(-296) +40 + j*(231) +-26 + j*(-117) +-184 + j*(8) +156 + j*(-24) +-98 + j*(-288) +192 + j*(-55) +-138 + j*(-66) +161 + j*(276) +337 + j*(-55) +122 + j*(-122) +233 + j*(-233) +-29 + j*(-118) +-36 + j*(0) +-259 + j*(5) +63 + j*(18) +-158 + j*(-301) +-95 + j*(-240) +549 + j*(309) +184 + j*(53) +-141 + j*(328) +-11 + j*(258) +-41 + j*(237) +-107 + j*(35) +-265 + j*(-267) +205 + j*(-198) +-274 + j*(284) +-211 + j*(-33) +-326 + j*(-124) +-64 + j*(-79) +-161 + j*(-294) +122 + j*(32) +-248 + j*(-27) +-3 + j*(-115) +-145 + j*(-153) +-308 + j*(35) +138 + j*(-127) +-254 + j*(-220) +-139 + j*(49) +-33 + j*(-45) +41 + j*(23) +4 + j*(-356) +-192 + j*(50) +-81 + j*(200) +157 + j*(266) +110 + j*(252) +51 + j*(-231) +-297 + j*(-110) +-142 + j*(-7) +-208 + j*(13) +-236 + j*(-299) +-43 + j*(190) +312 + j*(-10) +157 + j*(-322) +171 + j*(-177) +-15 + j*(-80) +-320 + j*(103) +-58 + j*(208) +192 + j*(-77) +424 + j*(-43) +83 + j*(56) +218 + j*(83) +46 + j*(-98) +-73 + j*(74) +-149 + j*(35) +-199 + j*(47) +-54 + j*(-18) +-68 + j*(136) +327 + j*(240) +-45 + j*(337) +-107 + j*(-88) +-52 + j*(224) +238 + j*(58) +-213 + j*(-77) +105 + j*(56) +163 + j*(-331) +119 + j*(-413) +-66 + j*(-121) +-112 + j*(176) +93 + j*(35) +199 + j*(98) +177 + j*(-56) +-216 + j*(-6) +-44 + j*(-34) +-244 + j*(-201) +53 + j*(-68) +133 + j*(149) +85 + j*(179) +-88 + j*(-4) +-91 + j*(28) +-173 + j*(16) +-13 + j*(135) +-147 + j*(120) +-85 + j*(-152) +24 + j*(-194) +-226 + j*(-117) +-8 + j*(120) +301 + j*(350) +110 + j*(-192) +-210 + j*(-33) +-57 + j*(-59) +-57 + j*(-199) +71 + j*(-110) +6 + j*(-235) +-84 + j*(100) +38 + j*(-43) +-40 + j*(151) +-187 + j*(224) +-156 + j*(138) +148 + j*(-41) +204 + j*(-564) +144 + j*(-85) +16 + j*(-325) +-55 + j*(78) +-21 + j*(-2) +77 + j*(152) +-99 + j*(-4) +-256 + j*(228) +221 + j*(0) +-71 + j*(226) +-83 + j*(-78) +-5 + j*(173) +-42 + j*(-68) +116 + j*(-40) +44 + j*(-258) +-39 + j*(-39) +-7 + j*(-173) +-223 + j*(-71) +40 + j*(89) +-86 + j*(-344) +-243 + j*(190) +286 + j*(48) +-284 + j*(227) +156 + j*(98) +180 + j*(-112) +-327 + j*(-141) +180 + j*(11) +-76 + j*(-96) +-55 + j*(-71) +-104 + j*(-48) +276 + j*(-40) +-4 + j*(-30) +281 + j*(-175) +425 + j*(192) +33 + j*(-87) +279 + j*(42) +-97 + j*(-129) +76 + j*(-5) +26 + j*(69) +48 + j*(-472) +-218 + j*(-209) +-143 + j*(-159) +-59 + j*(1) +221 + j*(25) +-95 + j*(32) +-69 + j*(79) +95 + j*(-206) +159 + j*(-54) +-121 + j*(107) +-23 + j*(33) +-68 + j*(-163) +40 + j*(-171) +190 + j*(-384) +-162 + j*(-95) +23 + j*(-211) +-136 + j*(0) +-46 + j*(-2) +381 + j*(-231) +128 + j*(-233) +-30 + j*(-272) +-98 + j*(86) +-109 + j*(-287) +-30 + j*(-47) +-94 + j*(235) +-144 + j*(0) +257 + j*(210) +-68 + j*(-23) +195 + j*(123) +-221 + j*(122) +244 + j*(110) +-126 + j*(-84) +59 + j*(-195) +-64 + j*(305) +186 + j*(74) +85 + j*(-304) +-126 + j*(96) +245 + j*(165) +23 + j*(-156) +267 + j*(-207) +-306 + j*(-105) +-195 + j*(131) +-52 + j*(-120) +13 + j*(-123) +-27 + j*(-401) +51 + j*(-105) +-214 + j*(121) +-68 + j*(-316) +64 + j*(83) +-260 + j*(-67) +-200 + j*(66) +-270 + j*(108) +-496 + j*(-64) +-40 + j*(-259) +-36 + j*(365) +29 + j*(61) +271 + j*(139) +-46 + j*(-204) +112 + j*(301) +73 + j*(-66) +211 + j*(-33) +24 + j*(161) +-153 + j*(-43) +4 + j*(-89) +107 + j*(202) +-52 + j*(-315) +23 + j*(59) +-80 + j*(-99) +115 + j*(-133) +127 + j*(-4) +56 + j*(278) +-90 + j*(17) +-215 + j*(176) +39 + j*(-146) +-180 + j*(21) +-135 + j*(146) +297 + j*(-195) +-173 + j*(13) +227 + j*(153) +107 + j*(-227) +-42 + j*(94) +-177 + j*(176) +157 + j*(40) +-243 + j*(30) +-65 + j*(-271) +-162 + j*(218) +574 + j*(-124) +64 + j*(-87) +-106 + j*(21) +-64 + j*(-85) +105 + j*(78) +170 + j*(252) +171 + j*(-236) +301 + j*(157) +257 + j*(-142) +-198 + j*(127) +8 + j*(402) +-31 + j*(137) +-168 + j*(-62) +331 + j*(-171) +95 + j*(-11) +260 + j*(-33) +358 + j*(-293) +-36 + j*(63) +-6 + j*(151) +177 + j*(-247) +60 + j*(-130) +199 + j*(49) +-54 + j*(83) +0 + j*(27) +-158 + j*(-120) +190 + j*(-147) +-168 + j*(138) +161 + j*(-16) +-5 + j*(14) +-260 + j*(-122) +-65 + j*(118) +-136 + j*(-20) +97 + j*(0) +-78 + j*(0) +89 + j*(-169) +141 + j*(-215) +-119 + j*(191) +114 + j*(-15) +-366 + j*(300) +-267 + j*(373) +-71 + j*(211) +220 + j*(136) +3 + j*(91) +170 + j*(275) +159 + j*(-59) +-163 + j*(-139) +-148 + j*(-9) +161 + j*(321) +167 + j*(26) +-87 + j*(-114) +-143 + j*(33) +47 + j*(145) +30 + j*(-80) +64 + j*(-204) +70 + j*(-93) +-183 + j*(37) +-71 + j*(-274) +-81 + j*(-93) +243 + j*(197) +-277 + j*(-307) +-103 + j*(-231) +32 + j*(168) +18 + j*(-4) +320 + j*(267) +-28 + j*(-4) +64 + j*(195) +-165 + j*(-17) +-72 + j*(-80) +-83 + j*(236) +-95 + j*(-298) +-310 + j*(4) +43 + j*(-100) +219 + j*(-225) +99 + j*(184) +-158 + j*(-57) +-32 + j*(-35) +-405 + j*(-144) +329 + j*(9) +191 + j*(47) +-65 + j*(98) +-28 + j*(-207) +-56 + j*(103) +-9 + j*(30) +-59 + j*(249) +-161 + j*(-89) +105 + j*(-37) +-136 + j*(-25) +-461 + j*(-19) +238 + j*(-184) +-49 + j*(-118) +-171 + j*(-199) +208 + j*(-146) +-117 + j*(-15) +-72 + j*(192) +351 + j*(-381) +-117 + j*(-57) +-37 + j*(-335) +-4 + j*(-30) +-269 + j*(-141) +351 + j*(107) +-214 + j*(-186) +154 + j*(-385) +-10 + j*(-100) +-200 + j*(-194) +120 + j*(-171) +16 + j*(-36) +-6 + j*(64) +53 + j*(-182) +-21 + j*(66) +-244 + j*(-162) +-187 + j*(107) +257 + j*(6) +254 + j*(183) +21 + j*(-123) +-260 + j*(-235) +-198 + j*(208) +67 + j*(-178) +-156 + j*(171) +23 + j*(-328) +50 + j*(-82) +273 + j*(91) +-465 + j*(11) +-252 + j*(-271) +66 + j*(159) +-349 + j*(-22) +-38 + j*(-395) +63 + j*(-30) +-83 + j*(-186) +-167 + j*(-312) +231 + j*(17) +168 + j*(-475) +216 + j*(-16) +-141 + j*(-285) +-185 + j*(72) +88 + j*(-3) +-132 + j*(-122) +63 + j*(245) +158 + j*(-104) +-301 + j*(-276) +-28 + j*(226) +129 + j*(40) +-146 + j*(-64) +-306 + j*(-209) +35 + j*(50) +390 + j*(30) +-264 + j*(-94) +-201 + j*(30) +4 + j*(21) +-325 + j*(-134) +-270 + j*(-317) +402 + j*(4) +-135 + j*(181) +221 + j*(69) +-272 + j*(-63) +-79 + j*(169) +-31 + j*(249) +25 + j*(238) +69 + j*(39) +38 + j*(119) +-13 + j*(54) +218 + j*(-204) +-118 + j*(-271) +-123 + j*(-87) +-215 + j*(-211) +8 + j*(-20) +-113 + j*(-134) +118 + j*(330) +184 + j*(52) +-52 + j*(8) +170 + j*(-322) +59 + j*(-35) +-247 + j*(372) +-42 + j*(-73) +119 + j*(111) +-25 + j*(-49) +-2 + j*(-87) +-310 + j*(-179) +250 + j*(70) +-49 + j*(18) +100 + j*(-186) +-135 + j*(28) +-71 + j*(153) +45 + j*(428) +3 + j*(-249) +-119 + j*(111) +321 + j*(223) +25 + j*(-214) +199 + j*(-301) +36 + j*(-147) +182 + j*(-100) +138 + j*(-7) +-115 + j*(-452) +147 + j*(52) +31 + j*(-32) +-359 + j*(243) +-57 + j*(-26) +288 + j*(-342) +-114 + j*(362) +-314 + j*(-102) +-130 + j*(-46) +90 + j*(184) +46 + j*(-83) +-231 + j*(151) +-25 + j*(-37) +-51 + j*(-51) +-491 + j*(88) +-45 + j*(141) +62 + j*(-93) +-115 + j*(189) +-167 + j*(556) +-111 + j*(-173) +-148 + j*(-122) +-70 + j*(-202) +226 + j*(315) +47 + j*(82) +107 + j*(92) +-71 + j*(159) +-201 + j*(96) +-279 + j*(312) +178 + j*(-182) +21 + j*(30) +93 + j*(-142) +330 + j*(-162) +88 + j*(49) +91 + j*(118) +-88 + j*(186) +157 + j*(76) +-174 + j*(79) +172 + j*(-34) +175 + j*(-133) +-195 + j*(-25) +100 + j*(-73) +237 + j*(213) +-206 + j*(-190) +209 + j*(-362) +-407 + j*(407) +-188 + j*(88) +-54 + j*(264) +-172 + j*(-100) +127 + j*(-121) +-132 + j*(-37) +-45 + j*(96) +221 + j*(111) +167 + j*(-11) +57 + j*(19) +119 + j*(-85) +-74 + j*(69) +12 + j*(-302) +-69 + j*(-177) +-21 + j*(181) +-117 + j*(157) +82 + j*(328) +393 + j*(29) +186 + j*(77) +371 + j*(-147) +93 + j*(-47) +-169 + j*(-63) +-48 + j*(215) +9 + j*(-59) +73 + j*(-226) +-295 + j*(-11) +-247 + j*(158) +-114 + j*(-120) +-83 + j*(-57) +53 + j*(-2) +-151 + j*(-27) +-251 + j*(-245) +-193 + j*(-12) +31 + j*(-63) +235 + j*(208) +53 + j*(-342) +138 + j*(-112) +93 + j*(-262) +5 + j*(65) +-266 + j*(-119) +-149 + j*(-166) +-25 + j*(38) +184 + j*(7) +-290 + j*(-71) +157 + j*(293) +-90 + j*(-56) +458 + j*(-84) +-99 + j*(-19) +164 + j*(153) +224 + j*(174) +-101 + j*(-18) +-81 + j*(154) +158 + j*(154) +-127 + j*(-254) +175 + j*(-91) +292 + j*(21) +-170 + j*(0) +148 + j*(-99) +-146 + j*(133) +136 + j*(121) +114 + j*(-186) +-29 + j*(60) +39 + j*(108) +-83 + j*(-29) +25 + j*(254) +-4 + j*(-291) +28 + j*(199) +-47 + j*(-40) +-95 + j*(203) +-223 + j*(18) +109 + j*(-144) +-82 + j*(-18) +148 + j*(302) +42 + j*(58) +291 + j*(205) +69 + j*(25) +-135 + j*(-63) +73 + j*(-18) +-325 + j*(-216) +-100 + j*(62) +-17 + j*(-175) +-198 + j*(93) +-25 + j*(216) +92 + j*(-165) +122 + j*(-248) +165 + j*(166) +121 + j*(85) +81 + j*(-57) +105 + j*(167) +211 + j*(-134) +18 + j*(-106) +-33 + j*(-170) +73 + j*(-61) +286 + j*(-19) +2 + j*(286) +-436 + j*(426) +-118 + j*(-88) +-47 + j*(-100) +-127 + j*(266) +58 + j*(-47) +-15 + j*(210) +117 + j*(130) +-325 + j*(146) +91 + j*(108) +127 + j*(-89) +41 + j*(-191) +-69 + j*(283) +-24 + j*(-206) +-237 + j*(-129) +24 + j*(1) +-15 + j*(188) +159 + j*(-438) +-153 + j*(177) +91 + j*(84) +196 + j*(99) +-199 + j*(-139) +-26 + j*(161) +-98 + j*(-145) +139 + j*(208) +8 + j*(-177) +106 + j*(83) +107 + j*(-57) +-309 + j*(-213) +-96 + j*(16) +88 + j*(-123) +-114 + j*(145) +238 + j*(-22) +46 + j*(-329) +156 + j*(-65) +-183 + j*(112) +61 + j*(-93) +11 + j*(154) +47 + j*(8) +-110 + j*(-246) +-185 + j*(-25) +383 + j*(-152) +6 + j*(-38) +162 + j*(-64) +-345 + j*(178) +-4 + j*(-176) +-76 + j*(49) +50 + j*(-157) +-230 + j*(-141) +-103 + j*(-71) +286 + j*(134) +-431 + j*(-79) +153 + j*(34) +-320 + j*(-55) +178 + j*(292) +-25 + j*(-117) +189 + j*(57) +158 + j*(105) +-108 + j*(-551) +170 + j*(-34) +-298 + j*(-87) +187 + j*(-165) +69 + j*(59) +-166 + j*(453) +111 + j*(-119) +172 + j*(-110) +-185 + j*(158) +-131 + j*(-267) +-54 + j*(-285) +-57 + j*(65) +94 + j*(-38) +382 + j*(-139) +-119 + j*(-199) +-252 + j*(48) +-190 + j*(421) +-119 + j*(30) +165 + j*(236) +77 + j*(42) +14 + j*(210) +-52 + j*(-196) +144 + j*(-216) +28 + j*(99) +-242 + j*(151) +-19 + j*(-17) +62 + j*(-230) +146 + j*(130) +-67 + j*(-202) +158 + j*(-134) +-318 + j*(192) +48 + j*(-28) +-322 + j*(180) +-263 + j*(187) +58 + j*(226) +-1 + j*(96) +8 + j*(304) +-31 + j*(-8) +214 + j*(-35) +-35 + j*(-71) +-22 + j*(-124) +-321 + j*(-234) +305 + j*(-367) +-170 + j*(-57) +-206 + j*(124) +-64 + j*(-117) +35 + j*(-8) +-74 + j*(-139) +-81 + j*(200) +355 + j*(189) +115 + j*(158) +-22 + j*(1) +-117 + j*(319) +48 + j*(193) +-66 + j*(-28) +-78 + j*(-221) +77 + j*(204) +-308 + j*(187) +-373 + j*(223) +-246 + j*(224) +277 + j*(147) +64 + j*(-37) +-13 + j*(-129) +6 + j*(-28) +80 + j*(15) +173 + j*(60) +-112 + j*(98) +-279 + j*(-98) +103 + j*(29) +115 + j*(13) +49 + j*(-102) +233 + j*(81) +189 + j*(-76) +192 + j*(52) +-54 + j*(-86) +-33 + j*(-18) +-248 + j*(105) +76 + j*(177) +433 + j*(-158) +-190 + j*(-6) +-139 + j*(93) +-57 + j*(-262) +165 + j*(-156) +305 + j*(-173) +-5 + j*(323) +33 + j*(335) +-156 + j*(-53) +-235 + j*(111) +-19 + j*(78) +-34 + j*(-106) +254 + j*(62) +-130 + j*(185) +5 + j*(-9) +53 + j*(-91) +-107 + j*(357) +-16 + j*(-24) +41 + j*(-177) +-18 + j*(135) +102 + j*(223) +-88 + j*(87) +173 + j*(251) +-35 + j*(-85) +-260 + j*(-141) +13 + j*(35) +235 + j*(136) +45 + j*(109) +57 + j*(-5) +59 + j*(-38) +148 + j*(78) +134 + j*(-247) +-215 + j*(40) +243 + j*(-28) +42 + j*(-71) +-59 + j*(-18) +63 + j*(-50) +-286 + j*(-103) +-140 + j*(-54) +43 + j*(-92) +117 + j*(-78) +58 + j*(-70) +-2 + j*(-187) +33 + j*(1) +-328 + j*(189) +-151 + j*(-17) +70 + j*(56) +-33 + j*(110) +-56 + j*(-232) +139 + j*(211) +68 + j*(-8) +-23 + j*(-332) +-84 + j*(-69) +-124 + j*(-66) +238 + j*(-9) +165 + j*(-138) +117 + j*(153) +-3 + j*(-95) +252 + j*(-83) +-146 + j*(81) +-163 + j*(-2) +231 + j*(206) +103 + j*(-237) +14 + j*(-40) +187 + j*(175) +-88 + j*(171) +66 + j*(202) +71 + j*(-172) +-182 + j*(-47) +-193 + j*(96) +158 + j*(197) +-11 + j*(-202) +-110 + j*(86) +-76 + j*(-20) +23 + j*(-204) +-110 + j*(228) +30 + j*(-39) +182 + j*(-27) +104 + j*(30) +-421 + j*(55) +-124 + j*(-89) +275 + j*(140) +-114 + j*(65) +188 + j*(221) +-515 + j*(152) +-315 + j*(-170) +1 + j*(-225) +294 + j*(14) +202 + j*(6) +255 + j*(-163) +-30 + j*(-192) +-179 + j*(141) +148 + j*(-154) +-74 + j*(-300) +-235 + j*(18) +247 + j*(-79) +177 + j*(-129) +-186 + j*(182) +-50 + j*(-11) +356 + j*(-52) +148 + j*(-117) +136 + j*(99) +93 + j*(-328) +-4 + j*(26) +7 + j*(-222) +-58 + j*(-41) +236 + j*(106) +-535 + j*(89) +356 + j*(320) +-111 + j*(38) +58 + j*(-325) +-165 + j*(103) +-176 + j*(-89) +-93 + j*(-48) +-6 + j*(69) +110 + j*(-194) +-19 + j*(1) +18 + j*(-311) +407 + j*(-1) +64 + j*(161) +142 + j*(-227) +-356 + j*(-335) +195 + j*(366) +-200 + j*(-170) +160 + j*(194) +-43 + j*(-305) +168 + j*(-30) +221 + j*(146) +-13 + j*(194) +366 + j*(-336) +-265 + j*(107) +-216 + j*(133) +-73 + j*(124) +-288 + j*(-79) +-6 + j*(78) +359 + j*(126) +-62 + j*(180) +205 + j*(-325) +-21 + j*(-49) +54 + j*(-180) +77 + j*(-340) +-77 + j*(-49) +-87 + j*(166) +129 + j*(115) +-167 + j*(25) +192 + j*(-13) +395 + j*(-304) +358 + j*(-41) +8 + j*(135) +-91 + j*(-146) +-103 + j*(-84) +136 + j*(98) +-123 + j*(-60) +298 + j*(-141) +-117 + j*(-283) +335 + j*(-21) +143 + j*(-44) +-249 + j*(-75) +11 + j*(47) +-146 + j*(-163) +185 + j*(232) +313 + j*(59) +-227 + j*(-141) +-214 + j*(-50) +-64 + j*(143) +73 + j*(-165) +185 + j*(-30) +55 + j*(48) +-152 + j*(-82) +-35 + j*(-16) +49 + j*(-21) +4 + j*(313) +279 + j*(42) +48 + j*(-219) +40 + j*(37) +-71 + j*(99) +-75 + j*(-37) +11 + j*(-197) +118 + j*(40) +-59 + j*(45) +-106 + j*(79) +84 + j*(-100) +-6 + j*(-39) +-144 + j*(418) +52 + j*(351) +187 + j*(264) +-26 + j*(25) +-1 + j*(-44) +-93 + j*(515) +63 + j*(-93) +296 + j*(78) +-311 + j*(363) +4 + j*(-178) +63 + j*(265) +-204 + j*(-132) +59 + j*(-104) +-294 + j*(8) +-167 + j*(76) +-74 + j*(288) +105 + j*(-91) +105 + j*(21) +19 + j*(-169) +132 + j*(-124) +83 + j*(43) +-302 + j*(-35) +155 + j*(206) +151 + j*(100) +-242 + j*(188) +1 + j*(269) +-30 + j*(-129) +387 + j*(-134) +135 + j*(89) +15 + j*(-282) +130 + j*(-124) +387 + j*(10) +136 + j*(74) +-83 + j*(-74) +-450 + j*(-119) +-84 + j*(-28) +-62 + j*(161) +-76 + j*(-78) +75 + j*(-597) +273 + j*(80) +-9 + j*(109) +4 + j*(62) +106 + j*(62) +105 + j*(199) +-132 + j*(158) +-21 + j*(5) +-142 + j*(98) +-282 + j*(170) +180 + j*(131) +211 + j*(-172) +-155 + j*(192) +-393 + j*(-5) +-84 + j*(-328) +-30 + j*(-112) +-71 + j*(-198) +120 + j*(-38) +-223 + j*(-73) +-11 + j*(196) +170 + j*(76) +-129 + j*(67) +-121 + j*(-35) +-66 + j*(103) +-183 + j*(148) +-215 + j*(-71) +-158 + j*(-179) +-211 + j*(13) +-78 + j*(201) +245 + j*(132) +-139 + j*(-11) +-58 + j*(204) +-103 + j*(-175) +-12 + j*(73) +-52 + j*(-126) +29 + j*(40) +67 + j*(-36) +18 + j*(-4) +15 + j*(-45) +268 + j*(-138) +62 + j*(25) +-344 + j*(-20) +16 + j*(93) +-122 + j*(119) +-44 + j*(-205) +137 + j*(-150) +197 + j*(-11) +56 + j*(-64) +25 + j*(-168) +112 + j*(141) +-144 + j*(29) +-170 + j*(-252) +-190 + j*(-37) +-8 + j*(-127) +-10 + j*(247) +193 + j*(-303) +-122 + j*(-218) +165 + j*(-90) +28 + j*(-100) +31 + j*(19) +-96 + j*(-121) +-98 + j*(30) +-281 + j*(-203) +250 + j*(-42) +-244 + j*(109) +-47 + j*(-231) +16 + j*(-291) +40 + j*(-218) +-300 + j*(34) +-152 + j*(173) +-74 + j*(73) +-23 + j*(-93) +-45 + j*(-342) +24 + j*(-52) +-193 + j*(183) +-151 + j*(-307) +-26 + j*(24) +207 + j*(-115) +-58 + j*(139) +-33 + j*(-112) +-409 + j*(149) +-1 + j*(-136) +-288 + j*(-105) +-30 + j*(-198) +187 + j*(39) +71 + j*(33) +-371 + j*(64) +-27 + j*(-169) +40 + j*(4) +-234 + j*(72) +-243 + j*(-18) +29 + j*(71) +189 + j*(-243) +-201 + j*(-335) +-214 + j*(-97) +-161 + j*(185) +-247 + j*(45) +-260 + j*(-303) +-206 + j*(245) +-127 + j*(12) +49 + j*(156) +-52 + j*(-3) +193 + j*(69) +203 + j*(62) +111 + j*(-100) +-105 + j*(-18) +25 + j*(-121) +-134 + j*(104) +-275 + j*(233) +100 + j*(-326) +-230 + j*(-73) +139 + j*(-256) +300 + j*(23) +-189 + j*(-491) +137 + j*(-88) +133 + j*(-263) +-106 + j*(-373) +-18 + j*(-103) +-98 + j*(223) +-4 + j*(-18) +6 + j*(266) +60 + j*(-30) +-188 + j*(-150) +-118 + j*(40) +-140 + j*(-16) +88 + j*(59) +-22 + j*(-28) +110 + j*(-66) +160 + j*(-157) +139 + j*(31) +19 + j*(-97) +69 + j*(101) +-49 + j*(172) +245 + j*(-80) +14 + j*(274) +-71 + j*(1) +-33 + j*(29) +-208 + j*(66) +184 + j*(227) +-239 + j*(-216) +127 + j*(-18) +469 + j*(177) +-91 + j*(263) +4 + j*(46) +-212 + j*(102) +25 + j*(-23) +153 + j*(10) +-97 + j*(-8) +-236 + j*(-30) +-46 + j*(-418) +-104 + j*(288) +78 + j*(-39) +136 + j*(1) +43 + j*(-76) +34 + j*(-223) +110 + j*(-4) +146 + j*(-64) +-5 + j*(45) +89 + j*(44) +-12 + j*(-76) +-5 + j*(-25) +20 + j*(243) +47 + j*(-218) +-81 + j*(71) +-73 + j*(187) +314 + j*(94) +-119 + j*(-69) +136 + j*(88) +158 + j*(75) +-196 + j*(-190) +-5 + j*(-135) +134 + j*(228) +-108 + j*(-257) +-16 + j*(414) +-16 + j*(96) +151 + j*(163) +93 + j*(4) +-204 + j*(-71) +-107 + j*(213) +187 + j*(26) +-30 + j*(242) +89 + j*(-8) +4 + j*(-206) +-54 + j*(-242) +110 + j*(-37) +-175 + j*(-238) +-148 + j*(15) +208 + j*(-152) +-28 + j*(-235) +-183 + j*(-280) +189 + j*(-124) +-19 + j*(8) +-250 + j*(-168) +-24 + j*(-89) +-247 + j*(140) +216 + j*(385) +88 + j*(-119) +356 + j*(-173) +4 + j*(145) +-193 + j*(-115) +109 + j*(-45) +203 + j*(172) +-103 + j*(337) +-80 + j*(187) +-129 + j*(179) +158 + j*(-235) +-52 + j*(-272) +-91 + j*(327) +-25 + j*(117) +-143 + j*(-141) +92 + j*(310) +129 + j*(33) +-202 + j*(159) +86 + j*(43) +-43 + j*(69) +-130 + j*(-140) +-139 + j*(371) +-1 + j*(92) +-301 + j*(-141) +170 + j*(83) +6 + j*(-224) +-183 + j*(132) +-187 + j*(74) +141 + j*(-238) +-102 + j*(346) +-230 + j*(298) +71 + j*(280) +-360 + j*(311) +-85 + j*(173) +117 + j*(-69) +23 + j*(314) +-179 + j*(234) +95 + j*(8) +18 + j*(-133) +-137 + j*(-108) +115 + j*(122) +-23 + j*(-101) +18 + j*(2) +96 + j*(-134) +21 + j*(3) +373 + j*(-148) +162 + j*(41) +240 + j*(244) +-114 + j*(192) +86 + j*(-23) +-55 + j*(67) +-188 + j*(163) +-23 + j*(10) +18 + j*(-76) +-27 + j*(21) +163 + j*(198) +-44 + j*(33) +70 + j*(66) +-132 + j*(356) +-43 + j*(-99) +-134 + j*(165) +225 + j*(-81) +-55 + j*(-30) +143 + j*(88) +64 + j*(-105) +-44 + j*(-93) +-69 + j*(-28) +-184 + j*(-154) +-315 + j*(184) +49 + j*(-148) +-220 + j*(91) +-91 + j*(-29) +-177 + j*(-166) +35 + j*(86) +-190 + j*(-197) +-281 + j*(-106) +-211 + j*(-90) +-185 + j*(27) +50 + j*(298) +71 + j*(-78) +268 + j*(-33) +79 + j*(-139) +218 + j*(125) +400 + j*(190) +-83 + j*(17) +-129 + j*(385) +-5 + j*(-299) +-202 + j*(-363) +233 + j*(24) +13 + j*(-80) +-256 + j*(-156) +194 + j*(-125) +233 + j*(104) +-206 + j*(145) +-181 + j*(137) +-342 + j*(253) +91 + j*(13) +-117 + j*(164) +-138 + j*(58) +227 + j*(-179) +-38 + j*(42) +-46 + j*(-65) +98 + j*(302) +-18 + j*(167) +135 + j*(136) +111 + j*(16) +-107 + j*(-140) +69 + j*(-180) +69 + j*(-49) +-100 + j*(190) +-161 + j*(302) +-57 + j*(261) +78 + j*(-50) +62 + j*(45) +298 + j*(24) +65 + j*(288) +-132 + j*(4) +186 + j*(4) +53 + j*(84) +-94 + j*(177) +258 + j*(-5) +82 + j*(-281) +282 + j*(295) +119 + j*(-278) +-65 + j*(-95) +-216 + j*(-46) +116 + j*(105) +13 + j*(287) +105 + j*(165) +221 + j*(-129) +27 + j*(115) +-284 + j*(5) +-20 + j*(190) +39 + j*(128) +-301 + j*(-53) +-198 + j*(-95) +-39 + j*(129) +-34 + j*(-30) +-25 + j*(280) +134 + j*(176) +-54 + j*(-99) +64 + j*(-139) +-147 + j*(191) +77 + j*(-8) +-140 + j*(1) +29 + j*(6) +-252 + j*(-90) +66 + j*(-373) +-273 + j*(177) +-53 + j*(-73) +426 + j*(209) +303 + j*(-223) +230 + j*(78) +-146 + j*(-151) +32 + j*(169) +408 + j*(48) +149 + j*(54) +-18 + j*(-1) +320 + j*(122) +-23 + j*(28) +89 + j*(-202) +33 + j*(-117) +274 + j*(-25) +23 + j*(-18) +-88 + j*(-291) +-51 + j*(407) +-50 + j*(18) +-4 + j*(-36) +115 + j*(124) +-13 + j*(150) +223 + j*(-66) +-48 + j*(108) +-82 + j*(-92) +40 + j*(219) +-216 + j*(148) +-187 + j*(-291) +-45 + j*(56) +185 + j*(47) +94 + j*(-248) +-107 + j*(-1) +-199 + j*(-47) +20 + j*(60) +117 + j*(141) +-151 + j*(-326) +51 + j*(-210) +121 + j*(-66) +-40 + j*(-173) +-83 + j*(-199) +-54 + j*(-74) +83 + j*(-98) +243 + j*(170) +217 + j*(-255) +242 + j*(-443) +-148 + j*(-34) +42 + j*(201) +29 + j*(-47) +-98 + j*(-1) +45 + j*(141) +-148 + j*(-74) +161 + j*(-137) +116 + j*(169) +49 + j*(-519) +9 + j*(-118) +144 + j*(169) +-106 + j*(77) +-124 + j*(-10) +-298 + j*(303) +268 + j*(-8) +44 + j*(-12) +165 + j*(-390) +-98 + j*(-107) +199 + j*(197) +194 + j*(49) +-206 + j*(412) +68 + j*(-216) +274 + j*(139) +-237 + j*(60) +85 + j*(285) +4 + j*(-130) +168 + j*(-20) +284 + j*(175) +316 + j*(-301) +62 + j*(148) +54 + j*(-270) +95 + j*(266) +-95 + j*(-28) +-46 + j*(29) +-254 + j*(-30) +-159 + j*(117) +-9 + j*(-117) +-64 + j*(-76) +59 + j*(19) +-45 + j*(-144) +-358 + j*(-110) +-302 + j*(218) +140 + j*(335) +233 + j*(12) +386 + j*(96) +-37 + j*(-218) +-187 + j*(-46) +16 + j*(290) +59 + j*(18) +158 + j*(-102) +104 + j*(-3) +-23 + j*(204) +131 + j*(161) +105 + j*(339) +-226 + j*(-220) +-144 + j*(202) +-95 + j*(-191) +-44 + j*(49) +69 + j*(-114) +-105 + j*(221) +12 + j*(58) +264 + j*(-68) +-21 + j*(88) +-357 + j*(15) +-122 + j*(-136) +-35 + j*(129) +139 + j*(-16) +-175 + j*(-110) +24 + j*(67) +17 + j*(56) +-100 + j*(-48) +-75 + j*(-260) +-28 + j*(-51) +52 + j*(-117) +445 + j*(41) +35 + j*(159) +-68 + j*(112) +-208 + j*(158) +-182 + j*(-253) +-3 + j*(-115) +-30 + j*(371) +8 + j*(30) +-223 + j*(-93) +274 + j*(57) +-313 + j*(-148) +244 + j*(195) +10 + j*(-305) +296 + j*(88) +7 + j*(87) +-40 + j*(91) +-315 + j*(-76) +-16 + j*(88) +-83 + j*(-124) +-98 + j*(-20) +-94 + j*(-92) +-143 + j*(-262) +-87 + j*(49) +252 + j*(-49) +-119 + j*(354) +134 + j*(46) +-167 + j*(-270) +-130 + j*(-144) +103 + j*(151) +-87 + j*(243) +70 + j*(132) +-128 + j*(2) +58 + j*(114) +215 + j*(14) +-81 + j*(183) +37 + j*(65) +-151 + j*(38) +-92 + j*(75) +-240 + j*(-64) +-23 + j*(-105) +-359 + j*(-221) +-107 + j*(18) +88 + j*(-301) +-308 + j*(542) +-77 + j*(-313) +221 + j*(-117) +-18 + j*(-79) +118 + j*(-240) +-389 + j*(-11) +57 + j*(0) +-142 + j*(-67) +-115 + j*(-76) +39 + j*(-61) +182 + j*(0) +-65 + j*(46) +57 + j*(-47) +-304 + j*(33) +-430 + j*(489) +-425 + j*(47) +261 + j*(597) +-67 + j*(314) +-337 + j*(167) +-143 + j*(-90) +-353 + j*(-21) +-335 + j*(162) +605 + j*(390) +-31 + j*(-196) +-340 + j*(-206) +-275 + j*(-161) +-332 + j*(120) +422 + j*(202) +316 + j*(192) +-141 + j*(535) +-296 + j*(-251) +209 + j*(-497) +-286 + j*(-75) +165 + j*(470) +-82 + j*(273) +99 + j*(267) +-262 + j*(188) +-15 + j*(172) +-30 + j*(403) +212 + j*(272) +-204 + j*(-431) +-351 + j*(-269) +589 + j*(204) +311 + j*(-122) +391 + j*(-222) +-371 + j*(286) +-566 + j*(-589) +202 + j*(-261) +-151 + j*(-124) +474 + j*(-434) +272 + j*(-49) +359 + j*(75) +129 + j*(-83) +-320 + j*(-96) +140 + j*(-76) +-211 + j*(-550) +305 + j*(417) +-412 + j*(64) +226 + j*(-547) +407 + j*(-380) +-83 + j*(-97) +396 + j*(-173) +255 + j*(-368) +213 + j*(-57) +313 + j*(110) +42 + j*(158) +-93 + j*(-151) +-267 + j*(12) +-50 + j*(119) +-161 + j*(-238) +-6 + j*(-322) +-392 + j*(-337) +472 + j*(-371) +142 + j*(421) +-317 + j*(400) +447 + j*(-417) +487 + j*(-246) +-265 + j*(420) +-237 + j*(279) +-163 + j*(188) +-423 + j*(341) +-38 + j*(-321) +492 + j*(101) +-297 + j*(-282) +-43 + j*(210) +247 + j*(262) +219 + j*(253) +446 + j*(250) +-492 + j*(-336) +272 + j*(-373) +289 + j*(241) +-71 + j*(-12) +-334 + j*(684) +-156 + j*(294) +219 + j*(168) +222 + j*(391) +-127 + j*(585) +458 + j*(-467) +400 + j*(-296) +-229 + j*(1) +-195 + j*(130) +-42 + j*(-72) +-548 + j*(46) +168 + j*(17) +-109 + j*(307) +274 + j*(-205) +181 + j*(-606) +23 + j*(216) +-359 + j*(13) +91 + j*(288) +-216 + j*(141) +-315 + j*(-303) +165 + j*(450) +-474 + j*(64) +450 + j*(-318) +-443 + j*(348) +131 + j*(450) +259 + j*(401) +-464 + j*(-486) +74 + j*(-565) +-122 + j*(-119) +512 + j*(-184) +-305 + j*(201) +199 + j*(-392) +158 + j*(-424) +156 + j*(43) +-610 + j*(289) +172 + j*(-296) +47 + j*(297) +-458 + j*(-441) +222 + j*(-376) +-399 + j*(8) +-208 + j*(371) +-65 + j*(-204) +-322 + j*(663) +-438 + j*(-144) +144 + j*(123) +97 + j*(363) +164 + j*(-170) +-237 + j*(167) +117 + j*(55) +342 + j*(-199) +-254 + j*(226) +-356 + j*(474) +-164 + j*(171) +393 + j*(-431) +-197 + j*(-47) +192 + j*(179) +183 + j*(-356) +377 + j*(-268) +465 + j*(407) +-193 + j*(-66) +-267 + j*(-235) +607 + j*(416) +-198 + j*(310) +403 + j*(542) +182 + j*(-26) +-594 + j*(-251) +-167 + j*(-284) +-265 + j*(667) +171 + j*(-404) +122 + j*(-467) +-266 + j*(57) +-361 + j*(-285) +348 + j*(23) +-206 + j*(-553) +-160 + j*(309) +491 + j*(283) +-422 + j*(-171) +-202 + j*(-250) +-229 + j*(99) +183 + j*(95) +134 + j*(-175) +172 + j*(-517) +147 + j*(385) +-446 + j*(392) +228 + j*(106) +90 + j*(-122) +-284 + j*(-69) +-255 + j*(-495) +99 + j*(-112) +-347 + j*(-191) +355 + j*(173) +-342 + j*(175) +407 + j*(-28) +223 + j*(-71) +-313 + j*(26) +156 + j*(-120) +392 + j*(-379) +-321 + j*(-26) +-399 + j*(160) +187 + j*(228) +-249 + j*(-415) +404 + j*(399) +198 + j*(253) +438 + j*(82) +479 + j*(237) +363 + j*(318) +576 + j*(-229) +-667 + j*(-161) +300 + j*(-527) +92 + j*(596) +-7 + j*(-363) +-397 + j*(414) +142 + j*(220) +535 + j*(395) +306 + j*(418) +-162 + j*(-406) +354 + j*(-330) +-219 + j*(162) +-331 + j*(-506) +496 + j*(225) +133 + j*(115) +214 + j*(218) +197 + j*(-316) +587 + j*(9) +-30 + j*(397) +-547 + j*(-593) +352 + j*(-108) +-219 + j*(142) +-383 + j*(286) +-216 + j*(-329) +390 + j*(276) +-157 + j*(-122) +236 + j*(122) +31 + j*(-37) +174 + j*(-285) +253 + j*(-253) +427 + j*(-403) +-315 + j*(345) +-428 + j*(-682) +15 + j*(-400) +-339 + j*(496) +-588 + j*(91) +229 + j*(-165) +529 + j*(296) +553 + j*(346) +-144 + j*(66) +-397 + j*(452) +445 + j*(406) +-112 + j*(-163) +301 + j*(253) +296 + j*(274) +354 + j*(-94) +-457 + j*(-530) +-373 + j*(-168) +-270 + j*(-178) +-407 + j*(-224) +3 + j*(-22) +177 + j*(288) +-476 + j*(31) +-296 + j*(232) +-331 + j*(-110) +429 + j*(-240) +385 + j*(-395) +-89 + j*(326) +369 + j*(243) +-419 + j*(30) +117 + j*(-298) +-83 + j*(388) +427 + j*(119) +-233 + j*(-222) +-437 + j*(509) +-329 + j*(-51) +184 + j*(238) +383 + j*(-150) +398 + j*(204) +-277 + j*(-255) +-166 + j*(105) +409 + j*(-567) +-312 + j*(-180) +85 + j*(-119) +-353 + j*(52) +-416 + j*(-530) +-59 + j*(-94) +-454 + j*(-723) +321 + j*(148) +-545 + j*(-355) +-286 + j*(-40) +398 + j*(-600) +144 + j*(-344) +199 + j*(-606) +-42 + j*(290) +-328 + j*(-112) +-199 + j*(-245) +303 + j*(-335) +-484 + j*(-413) +-314 + j*(98) +-100 + j*(-88) +-328 + j*(383) +-117 + j*(33) +491 + j*(-299) +320 + j*(426) +124 + j*(320) +-184 + j*(223) +-165 + j*(-230) +280 + j*(-183) +67 + j*(-808) +104 + j*(177) +260 + j*(-230) +454 + j*(-49) +145 + j*(-433) +-284 + j*(-306) +336 + j*(-199) +-338 + j*(-395) +168 + j*(-86) +-537 + j*(-232) +-396 + j*(-558) +587 + j*(-207) +155 + j*(-412) +-122 + j*(185) +-648 + j*(-65) +-167 + j*(-233) +-371 + j*(308) +-449 + j*(-25) +156 + j*(233) +-207 + j*(243) +-474 + j*(313) +325 + j*(6) +-183 + j*(269) +-344 + j*(-54) +-98 + j*(325) +382 + j*(197) +-304 + j*(-89) +100 + j*(-390) +-471 + j*(-12) +237 + j*(255) +247 + j*(-138) +-98 + j*(-78) +63 + j*(199) +-258 + j*(-231) +-470 + j*(-422) +-224 + j*(378) +629 + j*(1) +-255 + j*(-604) +-100 + j*(478) +-19 + j*(430) +663 + j*(213) +222 + j*(181) +-127 + j*(270) +351 + j*(-373) +308 + j*(192) +-149 + j*(240) +80 + j*(-377) +120 + j*(-112) +-96 + j*(-182) +-8 + j*(-73) +477 + j*(-154) +-419 + j*(274) +-496 + j*(256) +-240 + j*(410) +150 + j*(-351) +-243 + j*(-137) +-11 + j*(-345) +100 + j*(197) +67 + j*(52) +247 + j*(276) +106 + j*(404) +-426 + j*(-358) +161 + j*(-528) +211 + j*(233) +-408 + j*(180) +334 + j*(464) +469 + j*(-114) +278 + j*(178) +86 + j*(-257) +78 + j*(-322) +457 + j*(-159) +-275 + j*(328) +-508 + j*(-10) +209 + j*(89) +-301 + j*(291) +-247 + j*(-146) +259 + j*(177) +83 + j*(-61) +-369 + j*(-315) +-206 + j*(-272) +-194 + j*(53) +344 + j*(291) +242 + j*(-343) +433 + j*(-74) +424 + j*(423) +-332 + j*(160) +-345 + j*(675) +209 + j*(-36) +-152 + j*(-247) +-177 + j*(434) +312 + j*(317) +197 + j*(-103) +-355 + j*(112) +-69 + j*(-194) +400 + j*(118) +151 + j*(506) +386 + j*(-337) +451 + j*(228) +40 + j*(-25) +48 + j*(-194) +-218 + j*(-320) +207 + j*(-124) +-117 + j*(-141) +343 + j*(-224) +308 + j*(291) +-247 + j*(-361) +511 + j*(32) +228 + j*(91) +380 + j*(302) +324 + j*(-119) +-413 + j*(463) +292 + j*(281) +-201 + j*(-165) +-303 + j*(-211) +-471 + j*(418) +-69 + j*(-121) +-607 + j*(274) +141 + j*(342) +-339 + j*(-220) +-51 + j*(-165) +229 + j*(-407) +-151 + j*(263) +-238 + j*(-291) +316 + j*(-284) +279 + j*(-5) +530 + j*(231) +362 + j*(-301) +-351 + j*(88) +-110 + j*(-561) +112 + j*(460) +-511 + j*(-83) +465 + j*(-271) +302 + j*(-204) +164 + j*(355) +-293 + j*(-134) +190 + j*(-144) +306 + j*(343) +368 + j*(298) +53 + j*(-6) +-45 + j*(180) +-273 + j*(359) +-361 + j*(58) +-361 + j*(-168) +-212 + j*(-321) +-178 + j*(13) +186 + j*(-363) +-138 + j*(276) +149 + j*(-330) +-303 + j*(291) +427 + j*(-233) +410 + j*(147) +-484 + j*(243) +57 + j*(-330) +357 + j*(-601) +107 + j*(86) +402 + j*(-378) +-295 + j*(-273) +-211 + j*(-189) +264 + j*(360) +525 + j*(78) +414 + j*(161) +-354 + j*(-292) +457 + j*(262) +-247 + j*(284) +316 + j*(-690) +285 + j*(-289) +109 + j*(-199) +-414 + j*(-325) +-316 + j*(151) +-11 + j*(278) +296 + j*(57) +403 + j*(187) +196 + j*(129) +-380 + j*(-382) +-358 + j*(432) +311 + j*(-158) +-141 + j*(-752) +-210 + j*(223) +181 + j*(-170) +-144 + j*(479) +42 + j*(337) +-118 + j*(-448) +222 + j*(-74) +631 + j*(-293) +339 + j*(-683) +-165 + j*(141) +388 + j*(-554) +-211 + j*(358) +-309 + j*(110) +-313 + j*(130) +223 + j*(560) +415 + j*(496) +11 + j*(344) +634 + j*(-202) +226 + j*(-28) +-185 + j*(363) +-289 + j*(107) +43 + j*(301) +91 + j*(-283) +76 + j*(-579) +-298 + j*(95) +31 + j*(84) +-288 + j*(252) +194 + j*(413) +264 + j*(-355) +165 + j*(-302) +-120 + j*(101) +344 + j*(-684) +-288 + j*(52) +-290 + j*(-463) +-135 + j*(286) +-445 + j*(-125) +-263 + j*(97) +-277 + j*(-421) +302 + j*(-375) +455 + j*(412) +-128 + j*(63) +118 + j*(107) +-360 + j*(407) +54 + j*(366) +-74 + j*(-502) +234 + j*(242) +572 + j*(-114) +197 + j*(-351) +518 + j*(128) +477 + j*(462) +-64 + j*(393) +-113 + j*(-435) +303 + j*(-301) +-221 + j*(146) +-116 + j*(-151) +-352 + j*(-286) +-298 + j*(-105) +153 + j*(-247) +539 + j*(7) +360 + j*(144) +110 + j*(74) +328 + j*(28) +-337 + j*(424) +129 + j*(-260) +549 + j*(41) +-368 + j*(378) +-253 + j*(-668) +263 + j*(180) +253 + j*(-273) +-412 + j*(212) +-180 + j*(207) +-329 + j*(-180) +154 + j*(-82) +-102 + j*(197) +-356 + j*(107) +-89 + j*(-513) +-393 + j*(41) +344 + j*(403) +245 + j*(286) +-390 + j*(146) +184 + j*(-487) +132 + j*(-408) +-330 + j*(441) +-28 + j*(579) +197 + j*(-210) +-52 + j*(-171) +317 + j*(201) +-162 + j*(-148) +111 + j*(-285) +-148 + j*(177) +-291 + j*(210) +-358 + j*(-169) +421 + j*(-378) +-173 + j*(52) +19 + j*(-194) +211 + j*(62) +-416 + j*(202) +-296 + j*(194) +-357 + j*(72) +-214 + j*(49) +289 + j*(400) +-182 + j*(349) +-583 + j*(-578) +-322 + j*(232) +-136 + j*(179) +276 + j*(397) +-436 + j*(24) +-224 + j*(-35) +74 + j*(110) +-414 + j*(-103) +-369 + j*(513) +-141 + j*(-160) +309 + j*(346) +276 + j*(763) +-186 + j*(401) +137 + j*(202) +179 + j*(272) +-358 + j*(217) +109 + j*(330) +-497 + j*(70) +-352 + j*(288) +957 + j*(428) +136 + j*(149) +-426 + j*(-522) +91 + j*(52) +-378 + j*(150) +-367 + j*(416) +130 + j*(123) +-260 + j*(361) +-31 + j*(-247) +346 + j*(-375) +166 + j*(-52) +158 + j*(-178) +-497 + j*(201) +376 + j*(-266) +-416 + j*(258) +-198 + j*(175) +-107 + j*(-139) +-255 + j*(77) +-380 + j*(267) +-342 + j*(277) +-279 + j*(-194) +217 + j*(9) +65 + j*(-134) +-23 + j*(-395) +195 + j*(262) +86 + j*(-10) +-37 + j*(278) +-40 + j*(-135) +6 + j*(-1) +144 + j*(163) +-16 + j*(-21) +-5 + j*(147) +-47 + j*(-260) +-321 + j*(172) +238 + j*(-30) +216 + j*(81) +11 + j*(-53) +-47 + j*(-23) +93 + j*(-51) +-1 + j*(-8) +-76 + j*(-121) +-240 + j*(0) +-38 + j*(-183) +0 + j*(163) +234 + j*(-31) +-15 + j*(244) +76 + j*(-4) +-153 + j*(257) +173 + j*(26) +-37 + j*(-276) +-131 + j*(206) +65 + j*(192) +278 + j*(-243) +-161 + j*(-1) +44 + j*(-173) +167 + j*(245) +-102 + j*(122) +-47 + j*(-253) +-21 + j*(-165) +-1 + j*(57) +10 + j*(-13) +48 + j*(188) +-45 + j*(-52) +-17 + j*(-233) +32 + j*(-101) +-295 + j*(-116) +388 + j*(128) +-134 + j*(-117) +-81 + j*(-160) +-45 + j*(-393) +72 + j*(-60) +-24 + j*(-247) +208 + j*(-424) +280 + j*(-19) +-87 + j*(276) +23 + j*(70) +88 + j*(-285) +1 + j*(-189) +121 + j*(-41) +-55 + j*(-153) +-192 + j*(147) +98 + j*(-22) +0 + j*(218) +-347 + j*(138) +-95 + j*(-165) +214 + j*(-88) +-113 + j*(-315) +-131 + j*(390) +-264 + j*(144) +114 + j*(-233) +-54 + j*(-50) +-342 + j*(124) +-173 + j*(-27) +140 + j*(-115) +48 + j*(361) +-327 + j*(187) +-40 + j*(-163) +-104 + j*(229) +144 + j*(-105) +-83 + j*(-214) +183 + j*(117) +-150 + j*(75) +160 + j*(-52) +-6 + j*(-65) +209 + j*(132) +-195 + j*(275) +75 + j*(-323) +-33 + j*(-221) +92 + j*(-206) +8 + j*(-38) +-83 + j*(-167) +68 + j*(198) +31 + j*(13) +-310 + j*(318) +105 + j*(175) +5 + j*(-67) +42 + j*(-11) +107 + j*(29) +79 + j*(-83) +-68 + j*(-226) +366 + j*(92) +-146 + j*(172) +74 + j*(386) +160 + j*(-37) +327 + j*(-145) +-189 + j*(208) +-25 + j*(-168) +93 + j*(-51) +15 + j*(202) +4 + j*(2) +37 + j*(152) +-97 + j*(-64) +276 + j*(257) +-67 + j*(-88) +-58 + j*(-4) +-297 + j*(242) +-194 + j*(-285) +-26 + j*(139) +-220 + j*(271) +27 + j*(-36) +-277 + j*(98) +182 + j*(-327) +314 + j*(211) +-52 + j*(-117) +-92 + j*(64) +-197 + j*(-198) +-291 + j*(16) +45 + j*(100) +7 + j*(-226) +-6 + j*(-90) +-440 + j*(110) +-20 + j*(144) +296 + j*(-84) +-49 + j*(29) +-97 + j*(416) +-202 + j*(-2) +31 + j*(-51) +-156 + j*(-209) +-198 + j*(-40) +66 + j*(82) +-215 + j*(378) +414 + j*(23) +-291 + j*(122) +221 + j*(-47) +-374 + j*(33) +348 + j*(-216) +187 + j*(70) +129 + j*(-145) +-108 + j*(-35) +-100 + j*(-327) +228 + j*(-83) +334 + j*(107) +-380 + j*(-332) +-64 + j*(93) +177 + j*(-193) +-50 + j*(-9) +-325 + j*(152) +-71 + j*(111) +291 + j*(-116) +-158 + j*(229) +-150 + j*(-164) +36 + j*(126) +8 + j*(-73) +190 + j*(-161) +-25 + j*(-20) +130 + j*(99) +35 + j*(276) +242 + j*(171) +-145 + j*(-106) +103 + j*(-179) +127 + j*(-1) +-112 + j*(-151) +-141 + j*(308) +199 + j*(-22) +23 + j*(156) +-23 + j*(-225) +-168 + j*(37) +-245 + j*(83) +145 + j*(40) +-308 + j*(-13) +39 + j*(7) +16 + j*(-214) +87 + j*(-40) +-126 + j*(-33) +371 + j*(313) +80 + j*(-34) +8 + j*(175) +-110 + j*(368) +-66 + j*(130) +124 + j*(-55) +-166 + j*(-139) +119 + j*(126) +-124 + j*(245) +-150 + j*(110) +161 + j*(-21) +52 + j*(-105) +-98 + j*(27) +-139 + j*(125) +38 + j*(76) +-90 + j*(259) +-3 + j*(23) +31 + j*(84) +292 + j*(-22) +-146 + j*(505) +293 + j*(71) +-9 + j*(198) +9 + j*(15) +-60 + j*(-96) +-231 + j*(241) +-232 + j*(-240) +211 + j*(-120) +-145 + j*(54) +3 + j*(16) +-204 + j*(-413) +-373 + j*(-87) +-5 + j*(128) +-222 + j*(-5) +-42 + j*(-223) +-224 + j*(33) +-10 + j*(-8) +-134 + j*(25) +-187 + j*(351) +109 + j*(-105) +114 + j*(-36) +-226 + j*(84) +-168 + j*(-105) +-91 + j*(-60) +55 + j*(-227) +-25 + j*(-95) +-35 + j*(325) +59 + j*(-122) +81 + j*(-134) +-172 + j*(117) +-4 + j*(141) +30 + j*(-124) +-381 + j*(-111) +-119 + j*(-175) +103 + j*(-36) +-96 + j*(-64) +197 + j*(-59) +52 + j*(-100) +-151 + j*(125) +-132 + j*(-57) +-35 + j*(-74) +52 + j*(-267) +139 + j*(4) +-177 + j*(177) +-141 + j*(-110) +-64 + j*(372) +-204 + j*(-33) +113 + j*(187) +-123 + j*(91) +177 + j*(-75) +56 + j*(-164) +-342 + j*(178) +-83 + j*(124) +71 + j*(-26) +-179 + j*(76) +-7 + j*(-199) +-92 + j*(94) +67 + j*(-88) +62 + j*(197) +144 + j*(223) +-164 + j*(25) +148 + j*(-99) +176 + j*(-33) +96 + j*(-22) +4 + j*(-28) +8 + j*(-88) +-38 + j*(69) +20 + j*(27) +-151 + j*(-105) +46 + j*(279) +-182 + j*(-129) +187 + j*(-45) +125 + j*(41) +-105 + j*(260) +139 + j*(-175) +197 + j*(62) +-47 + j*(-6) +8 + j*(-264) +145 + j*(-122) +-71 + j*(-253) +-63 + j*(233) +121 + j*(-4) +-58 + j*(111) +358 + j*(151) +-23 + j*(-28) +11 + j*(-8) +11 + j*(26) +-92 + j*(-46) +-100 + j*(336) +-50 + j*(31) +-165 + j*(-91) +116 + j*(-206) +65 + j*(272) +-177 + j*(163) +-134 + j*(44) +194 + j*(84) +214 + j*(-51) +-225 + j*(210) +88 + j*(158) +120 + j*(-69) +111 + j*(115) +139 + j*(205) +329 + j*(-174) +47 + j*(82) +-327 + j*(-317) +37 + j*(154) +84 + j*(14) +84 + j*(-11) +221 + j*(155) +-364 + j*(194) +113 + j*(43) +4 + j*(21) +-107 + j*(-91) +-89 + j*(26) +-249 + j*(-27) +23 + j*(132) +127 + j*(-84) +-12 + j*(-115) +-71 + j*(-11) +-30 + j*(-1) +-172 + j*(138) +335 + j*(131) +-389 + j*(-301) +-227 + j*(-21) +31 + j*(-216) +-5 + j*(-132) +-144 + j*(-299) +-165 + j*(228) +3 + j*(-140) +-32 + j*(64) +-133 + j*(62) +-59 + j*(-167) +-209 + j*(-176) +313 + j*(-33) +-28 + j*(137) +184 + j*(219) +-16 + j*(294) +-196 + j*(-70) +-86 + j*(38) +-75 + j*(-91) +356 + j*(226) +-60 + j*(390) +22 + j*(-121) +90 + j*(76) +-141 + j*(-10) +87 + j*(57) +-245 + j*(-4) +88 + j*(-81) +-40 + j*(148) +-1 + j*(209) +216 + j*(24) +26 + j*(13) +-249 + j*(45) +251 + j*(-110) +-366 + j*(-232) +13 + j*(130) +17 + j*(271) +-126 + j*(-201) +-52 + j*(-122) +102 + j*(-264) +74 + j*(206) +317 + j*(-79) +122 + j*(13) +186 + j*(132) +-86 + j*(-180) +-253 + j*(-194) +86 + j*(-68) +-88 + j*(-161) +159 + j*(-275) +146 + j*(-74) +-85 + j*(-33) +-16 + j*(-133) +-136 + j*(-61) +-112 + j*(-103) +-156 + j*(57) +43 + j*(-80) +58 + j*(193) +-187 + j*(-203) +197 + j*(191) +277 + j*(26) +4 + j*(-117) +-81 + j*(182) +-8 + j*(-11) +54 + j*(-61) +-351 + j*(64) +-178 + j*(-216) +-4 + j*(-388) +-141 + j*(91) +-140 + j*(-93) +33 + j*(197) +63 + j*(-147) +17 + j*(132) +10 + j*(127) +-253 + j*(192) +-36 + j*(107) +125 + j*(-66) +-131 + j*(-82) +-250 + j*(-14) +-285 + j*(5) +119 + j*(-23) +28 + j*(253) +-49 + j*(330) +73 + j*(24) +82 + j*(40) +4 + j*(179) +44 + j*(-324) +-77 + j*(64) +-16 + j*(-161) +181 + j*(-55) +-248 + j*(-226) +-185 + j*(130) +108 + j*(110) +-337 + j*(-95) +117 + j*(-192) +-18 + j*(104) +185 + j*(204) +-106 + j*(28) +-400 + j*(57) +-91 + j*(47) +-243 + j*(-143) +-141 + j*(37) +216 + j*(79) +-63 + j*(23) +1 + j*(-54) +-258 + j*(254) +-26 + j*(-60) +203 + j*(132) +260 + j*(57) +-13 + j*(209) +46 + j*(-156) +55 + j*(294) +-322 + j*(-226) +101 + j*(118) +163 + j*(-56) +189 + j*(-47) +209 + j*(-12) +140 + j*(146) +-81 + j*(282) +-238 + j*(20) +-152 + j*(180) +-140 + j*(-190) +146 + j*(-109) +-63 + j*(-105) +49 + j*(6) +-37 + j*(-4) +25 + j*(-124) +21 + j*(-45) +214 + j*(209) +6 + j*(-68) +-174 + j*(189) +79 + j*(-70) +103 + j*(167) +-227 + j*(171) +-139 + j*(-351) +245 + j*(-18) +-17 + j*(325) +-490 + j*(-99) +301 + j*(81) +218 + j*(-4) +32 + j*(-16) +274 + j*(-51) +-122 + j*(21) +95 + j*(7) +295 + j*(-64) +-18 + j*(245) +-122 + j*(47) +86 + j*(7) +122 + j*(-269) +35 + j*(-125) +29 + j*(34) +187 + j*(53) +-205 + j*(-129) +-29 + j*(264) +93 + j*(-149) +-36 + j*(-107) +-225 + j*(255) +371 + j*(-177) +-142 + j*(11) +-230 + j*(217) +-100 + j*(-18) +40 + j*(163) +-57 + j*(-83) +-293 + j*(316) +-86 + j*(-52) +111 + j*(21) +-91 + j*(-33) +-121 + j*(-47) +-133 + j*(-12) +-7 + j*(124) +-154 + j*(-30) +-74 + j*(-225) +14 + j*(-54) +-176 + j*(252) +-217 + j*(-202) +65 + j*(-130) +144 + j*(192) +209 + j*(-108) +11 + j*(264) +-10 + j*(-170) +-9 + j*(-129) +-90 + j*(-147) +108 + j*(44) +-19 + j*(99) +-256 + j*(53) +301 + j*(-249) +-164 + j*(124) +-231 + j*(-234) +-64 + j*(-274) +-40 + j*(28) +54 + j*(-162) +99 + j*(72) +78 + j*(135) +-120 + j*(165) +123 + j*(-209) +-23 + j*(306) +-133 + j*(-216) +-35 + j*(121) +260 + j*(264) +134 + j*(25) +-32 + j*(255) +-245 + j*(-106) +-35 + j*(-74) +192 + j*(-317) +-175 + j*(286) +-25 + j*(-154) +-146 + j*(29) +40 + j*(181) +-10 + j*(119) +-47 + j*(-151) +161 + j*(105) +205 + j*(-194) +-270 + j*(28) +-18 + j*(1) +-131 + j*(125) +176 + j*(-149) +21 + j*(80) +13 + j*(-211) +-273 + j*(123) +-182 + j*(176) +-247 + j*(87) +72 + j*(141) +-78 + j*(-149) +-96 + j*(158) +-235 + j*(-231) +-2 + j*(194) +44 + j*(192) +-6 + j*(-80) +37 + j*(-110) +-148 + j*(-328) +-267 + j*(251) +168 + j*(175) +97 + j*(30) +-54 + j*(-40) +-168 + j*(89) +-72 + j*(-33) +-68 + j*(-249) +-100 + j*(48) +64 + j*(-49) +-161 + j*(150) +31 + j*(137) +27 + j*(-29) +243 + j*(28) +-22 + j*(-22) +94 + j*(22) +-238 + j*(-66) +-6 + j*(-87) +-109 + j*(99) +184 + j*(204) +-250 + j*(-3) +263 + j*(-223) +-428 + j*(-54) +155 + j*(-169) +43 + j*(-285) +-182 + j*(-257) +71 + j*(-199) +37 + j*(-130) +51 + j*(41) +-75 + j*(-66) +-95 + j*(105) +33 + j*(-125) +-195 + j*(-38) +281 + j*(-226) +-16 + j*(-185) +85 + j*(64) +-13 + j*(-259) +25 + j*(-330) +342 + j*(218) +91 + j*(331) +-245 + j*(-42) +-240 + j*(224) +-66 + j*(-228) +-37 + j*(182) +128 + j*(214) +109 + j*(129) +-244 + j*(135) +237 + j*(178) +-14 + j*(-62) +-26 + j*(11) +-275 + j*(-257) +99 + j*(-284) +97 + j*(501) +-361 + j*(-166) +-69 + j*(96) +-25 + j*(-182) +227 + j*(94) +157 + j*(445) +-29 + j*(-144) +368 + j*(-150) +40 + j*(-45) +-46 + j*(143) +56 + j*(-343) +-4 + j*(62) +272 + j*(-117) +-291 + j*(83) +-387 + j*(111) +-93 + j*(-18) +250 + j*(-13) +-193 + j*(48) +59 + j*(706) +264 + j*(228) +33 + j*(-315) +404 + j*(-147) +-79 + j*(1) +-296 + j*(-135) +-250 + j*(-423) +36 + j*(27) +64 + j*(-75) +-195 + j*(-198) +-51 + j*(-132) +-103 + j*(204) +261 + j*(-173) +44 + j*(-41) +-77 + j*(55) +-18 + j*(-163) +-241 + j*(106) +76 + j*(-120) +346 + j*(323) +-168 + j*(-142) +83 + j*(-60) +30 + j*(262) +250 + j*(-2) +-146 + j*(-236) +-66 + j*(-267) +-28 + j*(-10) +-58 + j*(-90) +139 + j*(-92) +143 + j*(105) +-192 + j*(525) +119 + j*(158) +15 + j*(-111) +25 + j*(-11) +-103 + j*(144) +-283 + j*(-173) +356 + j*(-98) +-53 + j*(274) +-1 + j*(94) +204 + j*(91) +127 + j*(-239) +-121 + j*(62) +-2 + j*(145) +134 + j*(-30) +-77 + j*(320) +148 + j*(27) +-372 + j*(-130) +274 + j*(8) +71 + j*(-80) +333 + j*(-121) +-292 + j*(-135) +205 + j*(479) +-37 + j*(-227) +62 + j*(61) +83 + j*(-158) +279 + j*(-41) +31 + j*(132) +-54 + j*(472) +-214 + j*(261) +148 + j*(-199) +73 + j*(499) +78 + j*(-23) +108 + j*(-213) +25 + j*(-210) +12 + j*(315) +-42 + j*(63) +-86 + j*(119) +76 + j*(246) +211 + j*(-351) +-42 + j*(-95) +-47 + j*(156) +37 + j*(144) +-249 + j*(-69) +-274 + j*(-139) +110 + j*(-13) +-269 + j*(21) +173 + j*(-42) +55 + j*(110) +-130 + j*(-165) +-187 + j*(-255) +-53 + j*(-127) +262 + j*(-6) +16 + j*(28) +-292 + j*(-63) +-219 + j*(-310) +-93 + j*(404) +-34 + j*(60) +78 + j*(-91) +-74 + j*(146) +-162 + j*(-143) +-127 + j*(64) +400 + j*(-46) +-81 + j*(373) +408 + j*(-136) +-45 + j*(13) +-161 + j*(-119) +39 + j*(310) +50 + j*(-281) +-64 + j*(4) +305 + j*(69) +-59 + j*(45) +-137 + j*(416) +56 + j*(-198) +273 + j*(-237) +141 + j*(173) +18 + j*(-60) +-41 + j*(225) +236 + j*(297) +80 + j*(18) +-388 + j*(277) +180 + j*(-110) +-67 + j*(-74) +-215 + j*(-148) +8 + j*(242) +-293 + j*(-219) +-88 + j*(81) +117 + j*(-18) +78 + j*(-66) +-80 + j*(-532) +141 + j*(21) +-211 + j*(-342) +-204 + j*(-96) +-131 + j*(-108) +124 + j*(-298) +43 + j*(-57) +13 + j*(220) +206 + j*(33) +43 + j*(-93) +-8 + j*(-59) +300 + j*(-127) +-181 + j*(218) +110 + j*(-66) +148 + j*(372) +-188 + j*(66) +28 + j*(-363) +-211 + j*(37) +110 + j*(22) +-132 + j*(110) +-122 + j*(-109) +-124 + j*(241) +-132 + j*(8) +-109 + j*(-1) +-186 + j*(-119) +-202 + j*(-288) +-29 + j*(143) +115 + j*(-307) +-51 + j*(-297) +-89 + j*(-169) +26 + j*(299) +66 + j*(76) +-62 + j*(133) +-110 + j*(-276) +410 + j*(-174) +-315 + j*(-66) +-5 + j*(165) +175 + j*(-115) +-167 + j*(-226) +-148 + j*(273) +197 + j*(-184) +-124 + j*(159) +285 + j*(-25) +221 + j*(13) +102 + j*(-86) +56 + j*(183) +-1 + j*(-25) +71 + j*(-21) +-281 + j*(156) +-62 + j*(40) +-3 + j*(153) +159 + j*(323) +-15 + j*(173) +-105 + j*(-136) +1 + j*(25) +7 + j*(154) +-380 + j*(-333) +-211 + j*(293) +11 + j*(-76) +-137 + j*(-161) +44 + j*(-180) +378 + j*(-2) +322 + j*(-284) +217 + j*(34) +107 + j*(161) +-20 + j*(156) +36 + j*(-98) +-142 + j*(11) +117 + j*(105) +51 + j*(-16) +253 + j*(-144) +-33 + j*(-183) +-190 + j*(-316) +-55 + j*(207) +-121 + j*(440) +-301 + j*(-78) +-73 + j*(-63) +95 + j*(-9) +-110 + j*(196) +329 + j*(-70) +-90 + j*(34) +-246 + j*(177) +-52 + j*(-62) +40 + j*(-156) +13 + j*(67) +-311 + j*(129) +101 + j*(88) +-107 + j*(107) +-245 + j*(-196) +-18 + j*(216) +126 + j*(161) +-21 + j*(194) +-64 + j*(-221) +40 + j*(-85) +107 + j*(168) +24 + j*(84) +-122 + j*(15) +-183 + j*(-73) +133 + j*(-38) +-105 + j*(37) +-154 + j*(35) +100 + j*(150) +500 + j*(-12) +115 + j*(4) +290 + j*(41) +243 + j*(-122) +-17 + j*(-80) +49 + j*(-163) +-144 + j*(-378) +-375 + j*(-136) +35 + j*(-108) +-19 + j*(-320) +-138 + j*(-10) +169 + j*(-57) +-212 + j*(114) +375 + j*(-63) +-171 + j*(117) +205 + j*(-184) +-233 + j*(77) +74 + j*(-168) +-19 + j*(142) +-77 + j*(124) +-53 + j*(-18) +51 + j*(-360) +-148 + j*(-2) +226 + j*(-23) +61 + j*(-165) +-67 + j*(-58) +278 + j*(-44) +412 + j*(-89) +-74 + j*(-80) +-32 + j*(151) +-106 + j*(226) +190 + j*(-121) +-247 + j*(-198) +36 + j*(-45) +-82 + j*(311) +115 + j*(1) +-379 + j*(4) +172 + j*(38) +-187 + j*(134) +-156 + j*(-50) +-126 + j*(-186) +-20 + j*(-57) +312 + j*(-151) +-218 + j*(180) +-42 + j*(-283) +-98 + j*(112) +145 + j*(57) +21 + j*(-140) +223 + j*(119) +71 + j*(-245) +134 + j*(243) +-80 + j*(252) +-33 + j*(-303) +-5 + j*(84) +-161 + j*(-120) +-268 + j*(-303) +-62 + j*(-187) +-151 + j*(-25) +164 + j*(-359) +-130 + j*(293) +-35 + j*(-424) +-359 + j*(368) +79 + j*(235) +344 + j*(-23) +-98 + j*(-108) +157 + j*(221) +-342 + j*(-91) +35 + j*(-46) +-111 + j*(-6) +119 + j*(-21) +-146 + j*(144) +167 + j*(36) +-347 + j*(-155) +238 + j*(4) +37 + j*(249) +-159 + j*(-104) +-79 + j*(348) +58 + j*(199) +-2 + j*(-211) +347 + j*(73) +28 + j*(-163) +-150 + j*(143) +-34 + j*(-91) +-53 + j*(390) +-163 + j*(135) +-274 + j*(-153) +69 + j*(194) +131 + j*(-263) +-412 + j*(177) +-86 + j*(-347) +52 + j*(-134) +264 + j*(84) +91 + j*(161) +-64 + j*(-158) +-34 + j*(-561) +-90 + j*(-67) +-67 + j*(-100) +117 + j*(-13) +16 + j*(-20) +144 + j*(128) +378 + j*(86) +96 + j*(-165) +-218 + j*(-17) +78 + j*(281) +221 + j*(-293) +161 + j*(257) +170 + j*(98) +-197 + j*(82) +-374 + j*(211) +331 + j*(-194) +166 + j*(-191) +233 + j*(-141) +21 + j*(-85) +-260 + j*(20) +-378 + j*(212) +54 + j*(337) +217 + j*(342) +85 + j*(87) +-145 + j*(105) +310 + j*(152) +-69 + j*(137) +138 + j*(-73) +-54 + j*(-25) +-87 + j*(-16) +133 + j*(-134) +137 + j*(-126) +133 + j*(34) +-137 + j*(7) +325 + j*(0) +-141 + j*(185) +89 + j*(-3) +-195 + j*(-91) +137 + j*(121) +-211 + j*(-122) +-57 + j*(88) +-246 + j*(-217) +130 + j*(-260) +-226 + j*(-54) +-120 + j*(-135) +332 + j*(-94) +-28 + j*(-57) +274 + j*(91) +49 + j*(-37) +173 + j*(119) +141 + j*(46) +-79 + j*(-44) +95 + j*(-190) +-48 + j*(-25) +-94 + j*(-227) +-261 + j*(-165) +-60 + j*(87) +-52 + j*(93) +-146 + j*(-202) +24 + j*(-27) +110 + j*(-47) +-88 + j*(-157) +-37 + j*(305) +-108 + j*(11) +-304 + j*(-94) +0 + j*(86) +308 + j*(91) +-243 + j*(121) +156 + j*(-95) +59 + j*(-81) +-126 + j*(138) +177 + j*(32) +-28 + j*(-145) +140 + j*(306) +44 + j*(-207) +4 + j*(-25) +69 + j*(91) +-279 + j*(-240) +-209 + j*(-70) +-236 + j*(-49) +-266 + j*(119) +-29 + j*(40) +246 + j*(-281) +-91 + j*(170) +-66 + j*(-84) +257 + j*(-77) +169 + j*(205) +-49 + j*(-64) +129 + j*(235) +153 + j*(-272) +25 + j*(167) +45 + j*(-199) +160 + j*(-20) +-114 + j*(139) +-255 + j*(-46) +276 + j*(-267) +145 + j*(72) +52 + j*(-160) +-346 + j*(13) +-107 + j*(203) +-278 + j*(286) +-279 + j*(300) +-83 + j*(-110) +40 + j*(69) +77 + j*(-233) +177 + j*(55) +135 + j*(-241) +25 + j*(30) +100 + j*(81) +293 + j*(-232) +-99 + j*(206) +-428 + j*(232) +135 + j*(-12) +227 + j*(-14) +64 + j*(-328) +45 + j*(-37) +-197 + j*(-253) +126 + j*(103) +113 + j*(4) +-6 + j*(-86) +11 + j*(130) +45 + j*(-115) +3 + j*(141) +-295 + j*(228) +-132 + j*(-34) +328 + j*(7) +-10 + j*(-414) +174 + j*(145) +108 + j*(-86) +-244 + j*(10) +-16 + j*(-123) +-77 + j*(-84) +98 + j*(-405) +131 + j*(-130) +-358 + j*(276) +-59 + j*(-46) +-523 + j*(75) +-109 + j*(-81) +-3 + j*(47) +197 + j*(207) +180 + j*(-38) +286 + j*(20) +-299 + j*(-468) +107 + j*(-59) +-273 + j*(-121) +-14 + j*(-8) +-58 + j*(-18) +123 + j*(266) +82 + j*(91) +-117 + j*(70) +328 + j*(213) +165 + j*(-51) +234 + j*(-64) +192 + j*(-102) +25 + j*(81) +-20 + j*(30) +54 + j*(-132) +-57 + j*(91) +6 + j*(101) +-6 + j*(66) +101 + j*(-100) +95 + j*(49) +160 + j*(272) +173 + j*(-262) +134 + j*(106) +-59 + j*(9) +287 + j*(259) +-105 + j*(-248) +-156 + j*(-380) +-287 + j*(141) +-98 + j*(-66) +16 + j*(52) +63 + j*(103) +35 + j*(128) +-104 + j*(-173) +86 + j*(226) +33 + j*(92) +149 + j*(49) +77 + j*(-76) +-126 + j*(23) +-417 + j*(13) +-241 + j*(152) +-30 + j*(-218) +-176 + j*(-159) +93 + j*(105) +150 + j*(79) +163 + j*(66) +209 + j*(27) +21 + j*(-233) +-144 + j*(16) +130 + j*(16) +322 + j*(192) +-192 + j*(50) +230 + j*(-177) +98 + j*(-100) +-127 + j*(-187) +-153 + j*(33) +246 + j*(-37) +147 + j*(-141) +-211 + j*(202) +265 + j*(177) +137 + j*(43) +538 + j*(218) +-583 + j*(125) +52 + j*(42) +165 + j*(-288) +-336 + j*(368) +175 + j*(-170) +-441 + j*(240) +149 + j*(129) +-235 + j*(148) +-38 + j*(-30) +-76 + j*(-467) +213 + j*(-158) +16 + j*(-30) +-51 + j*(-43) +-37 + j*(202) +16 + j*(-47) +199 + j*(-107) +-161 + j*(105) +-114 + j*(175) +-57 + j*(-124) +13 + j*(-55) +148 + j*(-185) +-76 + j*(-110) +-127 + j*(95) +629 + j*(323) +75 + j*(-234) +-103 + j*(-122) +88 + j*(-91) +-88 + j*(-165) +-19 + j*(47) +-55 + j*(197) +-31 + j*(-1) +-206 + j*(52) +-128 + j*(108) +218 + j*(58) +-254 + j*(-185) +-171 + j*(-105) +54 + j*(161) +31 + j*(41) +-173 + j*(210) +-4 + j*(45) +-276 + j*(33) +-270 + j*(92) +136 + j*(-105) +71 + j*(-156) +21 + j*(298) +-134 + j*(284) +138 + j*(8) +-62 + j*(483) +-495 + j*(62) +-231 + j*(-243) +-231 + j*(139) +117 + j*(56) +-121 + j*(-21) +-205 + j*(-68) +46 + j*(-148) +272 + j*(-71) +22 + j*(-134) +-88 + j*(170) +227 + j*(-7) +194 + j*(-216) +-105 + j*(-83) +35 + j*(-38) +-62 + j*(-11) +-25 + j*(-57) +-165 + j*(334) +59 + j*(-33) +-66 + j*(54) +40 + j*(-2) +-113 + j*(87) +61 + j*(-245) +47 + j*(-117) +71 + j*(-265) +177 + j*(298) +28 + j*(-226) +255 + j*(-117) +91 + j*(-88) +-136 + j*(-4) +122 + j*(162) +-66 + j*(156) +-35 + j*(190) +112 + j*(233) +37 + j*(-218) +-210 + j*(136) +-117 + j*(199) +-121 + j*(21) +21 + j*(42) +-133 + j*(-1) +261 + j*(67) +274 + j*(-211) +117 + j*(109) +-59 + j*(-67) +-262 + j*(-350) +49 + j*(29) +-164 + j*(-71) +-7 + j*(148) +-145 + j*(-25) +110 + j*(66) +-63 + j*(-243) +45 + j*(371) +70 + j*(111) +-69 + j*(-186) +170 + j*(-42) +7 + j*(18) +-207 + j*(-57) +52 + j*(-413) +198 + j*(303) +42 + j*(-6) +162 + j*(131) +-103 + j*(-41) +-161 + j*(75) +-18 + j*(137) +63 + j*(192) +317 + j*(201) +-246 + j*(-300) +81 + j*(194) +410 + j*(-223) +168 + j*(109) +-35 + j*(-319) +-192 + j*(-197) +-59 + j*(293) +-138 + j*(-165) +-124 + j*(-127) +161 + j*(-1) +-225 + j*(252) +1 + j*(6) +66 + j*(-69) +-95 + j*(33) +33 + j*(-151) +-37 + j*(332) +38 + j*(-76) +113 + j*(-186) +-132 + j*(-240) +-67 + j*(125) +-87 + j*(-121) +-51 + j*(11) +436 + j*(-5) +5 + j*(4) +319 + j*(-137) +26 + j*(-105) +-58 + j*(251) +49 + j*(-78) +-159 + j*(-67) +82 + j*(177) +-57 + j*(-229) +150 + j*(54) +39 + j*(-21) +23 + j*(-116) +83 + j*(154) +-116 + j*(-146) +35 + j*(35) +129 + j*(66) +-139 + j*(-21) +-247 + j*(-43) +66 + j*(201) +-48 + j*(-122) +115 + j*(-10) +59 + j*(-78) +-135 + j*(325) +186 + j*(94) +321 + j*(64) +-243 + j*(-163) +-21 + j*(219) +92 + j*(18) +-138 + j*(-308) +116 + j*(-98) +-293 + j*(-9) +-483 + j*(-84) +-51 + j*(99) +-34 + j*(-354) +44 + j*(124) +-294 + j*(-137) +-216 + j*(-135) +122 + j*(-151) +-213 + j*(-472) +-165 + j*(134) +184 + j*(-23) +-178 + j*(-216) +71 + j*(-120) +35 + j*(107) +-88 + j*(115) +394 + j*(-350) +261 + j*(-11) +18 + j*(69) +94 + j*(-419) +57 + j*(-196) +-62 + j*(-337) +-86 + j*(-111) +-284 + j*(-116) +-260 + j*(-87) +-50 + j*(-44) +266 + j*(117) +37 + j*(-122) +-249 + j*(80) +59 + j*(108) +151 + j*(-60) +-13 + j*(60) +44 + j*(18) +233 + j*(108) +305 + j*(-136) +-246 + j*(-6) +-122 + j*(-25) +-132 + j*(-170) +-2 + j*(34) +93 + j*(-3) +-87 + j*(93) +190 + j*(16) +192 + j*(314) +122 + j*(184) +185 + j*(272) +-151 + j*(-226) +58 + j*(181) +-39 + j*(-141) +-36 + j*(-188) +-96 + j*(158) +-15 + j*(-67) +-89 + j*(-180) +225 + j*(-103) +233 + j*(-173) +169 + j*(-23) +-7 + j*(-106) +165 + j*(-170) +-112 + j*(-73) +-428 + j*(-307) +-46 + j*(458) +235 + j*(-32) +255 + j*(268) +117 + j*(-291) +45 + j*(99) +-194 + j*(-226) +103 + j*(-133) +107 + j*(-172) +-18 + j*(-30) +-3 + j*(-140) +-146 + j*(-248) +127 + j*(12) +-25 + j*(158) +199 + j*(170) +334 + j*(103) +38 + j*(218) +-57 + j*(270) +-229 + j*(6) +-359 + j*(288) +100 + j*(107) +168 + j*(-62) +127 + j*(-205) +-25 + j*(-194) +60 + j*(-344) +-257 + j*(-204) +205 + j*(47) +63 + j*(6) +286 + j*(-307) +190 + j*(46) +-404 + j*(24) +117 + j*(74) +17 + j*(-186) +-358 + j*(70) +-447 + j*(50) +317 + j*(-105) +-300 + j*(-24) +-170 + j*(-203) +-18 + j*(-217) +401 + j*(59) +-368 + j*(74) +227 + j*(-190) +150 + j*(6) +431 + j*(-158) +251 + j*(-187) +-59 + j*(-158) +-281 + j*(-172) +-202 + j*(-277) +226 + j*(-39) +-74 + j*(-202) +32 + j*(257) +-249 + j*(-104) +-342 + j*(18) +-42 + j*(276) +20 + j*(-174) +-58 + j*(55) +107 + j*(13) +62 + j*(110) +-88 + j*(-8) +-53 + j*(105) +-98 + j*(-82) +40 + j*(-269) +-168 + j*(146) +-91 + j*(-114) +-34 + j*(-367) +-131 + j*(29) +-137 + j*(58) +-79 + j*(-44) +-255 + j*(-166) +-56 + j*(-137) +-202 + j*(-279) +63 + j*(21) +383 + j*(-27) +19 + j*(252) +28 + j*(-19) +-69 + j*(16) +-136 + j*(275) +395 + j*(-137) +107 + j*(351) +-59 + j*(279) +-196 + j*(-284) +165 + j*(45) +68 + j*(-99) +404 + j*(303) +-238 + j*(-18) +245 + j*(-265) +59 + j*(303) +-35 + j*(-162) +-453 + j*(-248) +-334 + j*(163) +-344 + j*(474) +6 + j*(-3) +-201 + j*(269) +134 + j*(-625) +441 + j*(165) +89 + j*(-500) +170 + j*(475) +499 + j*(38) +-637 + j*(-19) +-191 + j*(444) +-91 + j*(369) +129 + j*(270) +103 + j*(112) +-11 + j*(255) +452 + j*(323) +-325 + j*(-290) +485 + j*(-310) +238 + j*(-470) +-148 + j*(-462) +-323 + j*(-13) +175 + j*(-445) +381 + j*(-290) +-479 + j*(-116) +-348 + j*(245) +274 + j*(356) +54 + j*(233) +29 + j*(-153) +556 + j*(420) +88 + j*(27) +-383 + j*(83) +-45 + j*(606) +44 + j*(245) +-272 + j*(-347) +-452 + j*(-182) +35 + j*(165) +179 + j*(-366) +-275 + j*(280) +294 + j*(-340) +-371 + j*(200) +-260 + j*(410) +210 + j*(-378) +-54 + j*(371) +276 + j*(352) +524 + j*(361) +228 + j*(-63) +-296 + j*(-247) +590 + j*(-115) +-23 + j*(234) +71 + j*(255) +-517 + j*(-235) +75 + j*(450) +89 + j*(-307) +180 + j*(313) +247 + j*(448) +197 + j*(98) +163 + j*(160) +-272 + j*(182) +177 + j*(35) +-397 + j*(201) +-122 + j*(-438) +-453 + j*(-634) +-269 + j*(-228) +-167 + j*(-662) +262 + j*(-260) +95 + j*(225) +477 + j*(356) +-121 + j*(216) +77 + j*(161) +-372 + j*(-286) +-375 + j*(-124) +-553 + j*(269) +-320 + j*(-297) +158 + j*(-262) +456 + j*(-231) +-440 + j*(-190) +-234 + j*(182) +47 + j*(269) +122 + j*(54) +-106 + j*(409) +-245 + j*(228) +-1 + j*(196) +-120 + j*(-257) +-173 + j*(80) +-477 + j*(-206) +83 + j*(472) +-611 + j*(176) +47 + j*(239) +-474 + j*(89) +606 + j*(251) +-338 + j*(451) +176 + j*(-199) +-354 + j*(-397) +-89 + j*(-178) +124 + j*(-152) +172 + j*(199) +-367 + j*(-373) +461 + j*(-211) +341 + j*(63) +8 + j*(172) +-398 + j*(109) +6 + j*(132) +422 + j*(139) +-229 + j*(-193) +-118 + j*(163) +-74 + j*(105) +-80 + j*(199) +622 + j*(-87) +206 + j*(-106) +62 + j*(117) +-354 + j*(235) +-129 + j*(-91) +413 + j*(430) +-419 + j*(107) +236 + j*(187) +-494 + j*(-507) +-118 + j*(340) +-25 + j*(335) +528 + j*(-308) +-499 + j*(-47) +-11 + j*(95) +-275 + j*(259) +-395 + j*(128) +35 + j*(264) +-16 + j*(-187) +127 + j*(-355) +358 + j*(323) +517 + j*(13) +-177 + j*(7) +-335 + j*(-337) +-570 + j*(210) +290 + j*(183) +-529 + j*(-514) +-87 + j*(272) +-121 + j*(298) +-682 + j*(-194) +-99 + j*(228) +-216 + j*(-336) +433 + j*(-46) +-585 + j*(-307) +-225 + j*(136) +-92 + j*(-79) +-38 + j*(413) +-22 + j*(201) +272 + j*(311) +258 + j*(67) +19 + j*(-434) +417 + j*(343) +-291 + j*(145) +-197 + j*(173) +539 + j*(430) +-530 + j*(-280) +-69 + j*(276) +-442 + j*(71) +-363 + j*(-136) +-390 + j*(245) +-186 + j*(326) +426 + j*(217) +83 + j*(467) +-613 + j*(281) +146 + j*(-255) +37 + j*(-203) +-504 + j*(49) +-48 + j*(-541) +165 + j*(33) +-302 + j*(296) +-528 + j*(73) +-281 + j*(-112) +455 + j*(547) +245 + j*(-219) +-552 + j*(-479) +-163 + j*(-419) +235 + j*(424) +-527 + j*(240) +25 + j*(-750) +-203 + j*(-203) +-205 + j*(-281) +-88 + j*(88) +353 + j*(597) +362 + j*(287) +-308 + j*(175) +569 + j*(180) +421 + j*(-441) +-382 + j*(76) +-40 + j*(180) +-81 + j*(235) +-308 + j*(169) +364 + j*(-674) +-218 + j*(49) +437 + j*(369) +251 + j*(-216) +395 + j*(-381) +-255 + j*(113) +-411 + j*(300) +-109 + j*(83) +-132 + j*(512) +194 + j*(336) +-83 + j*(283) +340 + j*(-88) +47 + j*(156) +-71 + j*(293) +467 + j*(389) +269 + j*(-11) +-188 + j*(-217) +-266 + j*(220) +-368 + j*(402) +-394 + j*(153) +-148 + j*(-221) +132 + j*(-19) +284 + j*(-238) +-255 + j*(-104) +-399 + j*(-474) +-693 + j*(211) +-318 + j*(97) +-568 + j*(-313) +206 + j*(10) +339 + j*(-526) +-535 + j*(-288) +-4 + j*(-254) +537 + j*(140) +-313 + j*(377) +59 + j*(164) +257 + j*(258) +387 + j*(-396) +252 + j*(650) +144 + j*(-562) +-56 + j*(-597) +-163 + j*(377) +-89 + j*(488) +-245 + j*(-170) +-94 + j*(-573) +-248 + j*(374) +327 + j*(-499) +-438 + j*(89) +228 + j*(-331) +40 + j*(-243) +205 + j*(320) +-280 + j*(-1) +380 + j*(-342) +-539 + j*(176) +37 + j*(-398) +-567 + j*(474) +-322 + j*(319) +118 + j*(222) +-317 + j*(-47) +304 + j*(-267) +355 + j*(-300) +146 + j*(256) +-330 + j*(-215) +23 + j*(435) +354 + j*(83) +231 + j*(90) +152 + j*(-227) +-246 + j*(262) +-451 + j*(341) +-208 + j*(-239) +256 + j*(-187) +-474 + j*(-392) +293 + j*(-143) +397 + j*(273) +349 + j*(150) +211 + j*(62) +-249 + j*(-354) +76 + j*(213) +-129 + j*(-209) +-555 + j*(-134) +264 + j*(-363) +457 + j*(-358) +-165 + j*(-33) +149 + j*(-256) +190 + j*(136) +182 + j*(190) +371 + j*(287) +252 + j*(56) +395 + j*(391) +308 + j*(-521) +45 + j*(-256) +-9 + j*(-543) +323 + j*(407) +486 + j*(-177) +-363 + j*(29) +206 + j*(-639) +-333 + j*(-112) +71 + j*(-152) +21 + j*(-375) +154 + j*(39) +-103 + j*(-450) +-281 + j*(-57) +-215 + j*(428) +-332 + j*(-16) +349 + j*(-7) +-145 + j*(-528) +226 + j*(295) +472 + j*(-151) +56 + j*(241) +144 + j*(75) +-641 + j*(-214) +316 + j*(303) +-523 + j*(-491) +504 + j*(373) +170 + j*(419) +-469 + j*(-817) +76 + j*(163) +204 + j*(-40) +-467 + j*(-346) +-181 + j*(93) +-25 + j*(-513) +204 + j*(446) +525 + j*(229) +-499 + j*(383) +-91 + j*(288) +33 + j*(-115) +8 + j*(-433) +-238 + j*(-446) +156 + j*(496) +207 + j*(17) +-271 + j*(-318) +287 + j*(-330) +-212 + j*(-262) +-62 + j*(-20) +617 + j*(157) +-40 + j*(-72) +-256 + j*(-126) +313 + j*(-422) +-209 + j*(23) +433 + j*(-441) +175 + j*(-378) +-223 + j*(16) +-1 + j*(-623) +441 + j*(-211) +-243 + j*(-511) +-370 + j*(-292) +-114 + j*(-321) +-347 + j*(-197) +-501 + j*(-327) +57 + j*(-296) +-231 + j*(241) +148 + j*(68) +-516 + j*(391) +250 + j*(-153) +-300 + j*(-183) +-9 + j*(-402) +332 + j*(197) +209 + j*(280) +115 + j*(-447) +-167 + j*(66) +455 + j*(105) +307 + j*(98) +409 + j*(-368) +37 + j*(-124) +137 + j*(238) +-402 + j*(-307) +-319 + j*(-198) +37 + j*(-339) +223 + j*(199) +-354 + j*(-160) +-3 + j*(401) +-11 + j*(30) +377 + j*(-197) +-639 + j*(-83) +-15 + j*(296) +79 + j*(-421) +-197 + j*(-234) +-47 + j*(-387) +629 + j*(30) +293 + j*(170) +595 + j*(486) +-391 + j*(256) +-44 + j*(25) +-497 + j*(364) +-74 + j*(198) +127 + j*(322) +-373 + j*(161) +-200 + j*(67) +503 + j*(301) +319 + j*(209) +276 + j*(-260) +-539 + j*(-240) +-53 + j*(356) +340 + j*(-97) +28 + j*(321) +45 + j*(-135) +1 + j*(-404) +319 + j*(-499) +457 + j*(-78) +178 + j*(-281) +-399 + j*(-112) +124 + j*(-13) +-195 + j*(-286) +132 + j*(354) +677 + j*(-21) +-69 + j*(-286) +571 + j*(197) +141 + j*(17) +126 + j*(282) +176 + j*(611) +419 + j*(-260) +202 + j*(-305) +196 + j*(-390) +-696 + j*(547) +226 + j*(-73) +187 + j*(537) +-245 + j*(276) +-508 + j*(139) +364 + j*(235) +438 + j*(-310) +284 + j*(-198) +-246 + j*(616) +346 + j*(-528) +190 + j*(365) +279 + j*(310) +-286 + j*(287) +-128 + j*(-385) +-150 + j*(461) +305 + j*(81) +-167 + j*(305) +177 + j*(310) +-1 + j*(-93) +-322 + j*(450) +-278 + j*(-342) +549 + j*(328) +-168 + j*(540) +351 + j*(-178) +217 + j*(314) +-275 + j*(300) +163 + j*(-137) +-153 + j*(-810) +-314 + j*(457) +279 + j*(-263) +157 + j*(-163) +622 + j*(-212) +70 + j*(-303) +275 + j*(-532) +321 + j*(409) +134 + j*(293) +-91 + j*(-387) +272 + j*(127) +-312 + j*(-547) +-226 + j*(-198) +-518 + j*(583) +117 + j*(218) +658 + j*(19) +317 + j*(691) +-420 + j*(193) +62 + j*(-383) +-79 + j*(-174) +74 + j*(348) +354 + j*(-148) +-478 + j*(-88) +393 + j*(-581) +282 + j*(16) +214 + j*(416) +-163 + j*(-387) +226 + j*(-209) +44 + j*(-400) +345 + j*(-215) +-203 + j*(-110) +269 + j*(301) +-269 + j*(75) +199 + j*(471) +-320 + j*(1) +-648 + j*(-421) +245 + j*(-436) +-57 + j*(183) +-571 + j*(21) +-403 + j*(158) +427 + j*(218) +-327 + j*(-246) +529 + j*(459) +150 + j*(127) +-418 + j*(-54) +412 + j*(369) +116 + j*(-91) +395 + j*(296) +301 + j*(276) +566 + j*(285) +15 + j*(-486) +267 + j*(511) +-98 + j*(-312) +-190 + j*(-24) +-30 + j*(-380) +-484 + j*(-349) +-109 + j*(85) +-43 + j*(-262) +320 + j*(355) +-552 + j*(-317) +-95 + j*(250) +358 + j*(277) +-62 + j*(-587) +128 + j*(-55) +-302 + j*(127) +-338 + j*(-502) +-90 + j*(-230) +-271 + j*(-47) +638 + j*(-255) +330 + j*(-83) +-233 + j*(421) +-182 + j*(-139) +-32 + j*(405) +296 + j*(157) +28 + j*(216) +129 + j*(1) +-267 + j*(-117) +-310 + j*(-152) +-390 + j*(-285) +389 + j*(371) +199 + j*(165) +120 + j*(45) +530 + j*(354) +-42 + j*(-301) +368 + j*(-213) +-28 + j*(-317) +-89 + j*(-516) +-32 + j*(213) +218 + j*(105) +-168 + j*(293) +-261 + j*(225) +158 + j*(221) +-180 + j*(-234) +236 + j*(383) +-63 + j*(-86) +319 + j*(-243) +265 + j*(60) +-63 + j*(149) +191 + j*(-45) +-172 + j*(202) +-212 + j*(616) +-405 + j*(387) +-325 + j*(19) +-18 + j*(149) +-594 + j*(-148) +-387 + j*(460) +-368 + j*(469) +407 + j*(310) +-475 + j*(6) +-474 + j*(30) +-553 + j*(331) +-99 + j*(-116) +265 + j*(-308) +188 + j*(-201) +64 + j*(-253) +-30 + j*(-274) +-364 + j*(322) +309 + j*(-317) +-293 + j*(223) +197 + j*(-407) +433 + j*(-237) +-73 + j*(37) +392 + j*(373) +-235 + j*(-14) +425 + j*(-168) +-192 + j*(49) +15 + j*(-447) +61 + j*(202) +374 + j*(-368) +393 + j*(-243) +383 + j*(-417) +214 + j*(-48) +-228 + j*(148) +-298 + j*(-249) +55 + j*(-243) +269 + j*(-70) +230 + j*(85) +402 + j*(-211) +-491 + j*(-202) +-465 + j*(-66) +556 + j*(352) +105 + j*(473) +358 + j*(-113) +-377 + j*(244) +-344 + j*(-247) +-160 + j*(233) +437 + j*(-361) +288 + j*(184) +94 + j*(-404) +-11 + j*(205) +-216 + j*(-250) +-11 + j*(-221) +-1 + j*(-287) +269 + j*(-443) +244 + j*(-533) +-298 + j*(-8) +-180 + j*(109) +248 + j*(479) +213 + j*(124) +358 + j*(541) +-181 + j*(-170) +-250 + j*(187) +117 + j*(-116) +-319 + j*(226) +206 + j*(124) +-320 + j*(-134) +241 + j*(518) +-218 + j*(6) +-407 + j*(-465) +93 + j*(479) +-550 + j*(275) +112 + j*(623) +-153 + j*(102) +-38 + j*(-216) +125 + j*(-53) +243 + j*(-223) +-298 + j*(-80) +358 + j*(153) +-172 + j*(99) +-166 + j*(-334) +-24 + j*(136) +-269 + j*(83) +-16 + j*(141) +-81 + j*(-37) +288 + j*(-160) +76 + j*(-252) +15 + j*(-38) +52 + j*(-147) +-139 + j*(-18) +-134 + j*(163) +-214 + j*(-61) +-187 + j*(259) +317 + j*(-68) +-102 + j*(-43) +-310 + j*(-237) +28 + j*(-4) +-106 + j*(21) +106 + j*(-231) +-339 + j*(50) +30 + j*(-218) +-42 + j*(-162) +-235 + j*(-288) +-110 + j*(-78) +95 + j*(413) +-305 + j*(67) +238 + j*(279) +124 + j*(196) +-105 + j*(-66) +-495 + j*(-67) +190 + j*(62) +-241 + j*(-206) +99 + j*(3) +-175 + j*(-147) +78 + j*(-20) +-103 + j*(-211) +-167 + j*(-285) +54 + j*(-207) +88 + j*(11) +21 + j*(35) +-62 + j*(13) +317 + j*(199) +113 + j*(122) +-373 + j*(252) +94 + j*(-60) +35 + j*(117) +-180 + j*(194) +-21 + j*(81) +21 + j*(87) +-96 + j*(-382) +-185 + j*(100) +-463 + j*(392) +-78 + j*(-193) +312 + j*(-53) +-126 + j*(-49) +217 + j*(52) +-62 + j*(187) +-66 + j*(76) +-37 + j*(-108) +82 + j*(-197) +37 + j*(-62) +45 + j*(-120) +83 + j*(-103) +-91 + j*(165) +-77 + j*(90) +-224 + j*(160) +-145 + j*(67) +230 + j*(-203) +143 + j*(54) +223 + j*(163) +42 + j*(-2) +39 + j*(-60) +2 + j*(235) +216 + j*(274) +34 + j*(-177) +138 + j*(-175) +-220 + j*(-211) +-15 + j*(36) +-23 + j*(300) +91 + j*(282) +-3 + j*(166) +-193 + j*(-123) +-103 + j*(27) +-5 + j*(28) +-121 + j*(60) +243 + j*(-2) +145 + j*(-293) +-127 + j*(415) +-83 + j*(267) +-95 + j*(47) +35 + j*(96) +-53 + j*(-190) +18 + j*(-146) +-76 + j*(165) +131 + j*(-103) +5 + j*(-44) +57 + j*(-155) +-339 + j*(-77) +8 + j*(-175) +157 + j*(16) +119 + j*(149) +-276 + j*(-163) +23 + j*(107) +69 + j*(-146) +135 + j*(-267) +94 + j*(103) +27 + j*(57) +29 + j*(164) +24 + j*(-66) +-98 + j*(-193) +-9 + j*(51) +-144 + j*(-103) +346 + j*(59) +377 + j*(262) +82 + j*(-277) +60 + j*(143) +88 + j*(107) +192 + j*(-120) +-146 + j*(-35) +-455 + j*(107) +91 + j*(236) +181 + j*(45) +90 + j*(64) +-56 + j*(-392) +-73 + j*(-43) +99 + j*(9) +-270 + j*(-105) +-62 + j*(-435) +-349 + j*(-218) +-298 + j*(-86) +-137 + j*(-90) +76 + j*(28) +235 + j*(-12) +-63 + j*(-119) +-180 + j*(71) +-165 + j*(218) +-96 + j*(-2) +1 + j*(-390) +-1 + j*(5) +59 + j*(-162) +33 + j*(171) +9 + j*(-5) +387 + j*(-101) +-89 + j*(94) +-168 + j*(-165) +-230 + j*(-2) +446 + j*(198) +209 + j*(161) +172 + j*(153) +34 + j*(153) +80 + j*(3) +-238 + j*(245) +-28 + j*(-286) +261 + j*(202) +-277 + j*(139) +76 + j*(148) +321 + j*(-148) +5 + j*(-124) +175 + j*(286) +-22 + j*(95) +14 + j*(-212) +-30 + j*(-224) +-52 + j*(-112) +240 + j*(-124) +-21 + j*(292) +-39 + j*(-235) +81 + j*(262) +3 + j*(-186) +74 + j*(-12) +178 + j*(84) +86 + j*(-62) +238 + j*(-4) +4 + j*(13) +265 + j*(-82) +37 + j*(218) +-187 + j*(71) +-288 + j*(330) +-112 + j*(340) +71 + j*(-57) +-62 + j*(81) +18 + j*(96) +-84 + j*(132) +10 + j*(162) +97 + j*(4) +50 + j*(308) +-25 + j*(442) +-136 + j*(187) +-161 + j*(109) +-50 + j*(54) +210 + j*(-192) +59 + j*(174) +-51 + j*(-252) +139 + j*(-155) +280 + j*(156) +32 + j*(-54) +211 + j*(24) +-198 + j*(-298) +165 + j*(206) +122 + j*(-144) +30 + j*(119) +-21 + j*(281) +74 + j*(-119) +-54 + j*(-23) +-25 + j*(332) +78 + j*(-199) +-125 + j*(-74) +232 + j*(11) +-199 + j*(154) +311 + j*(31) +76 + j*(307) +39 + j*(-23) +-165 + j*(397) +310 + j*(42) +255 + j*(-36) +276 + j*(-68) +-192 + j*(20) +-98 + j*(166) +3 + j*(-489) +41 + j*(177) +-72 + j*(305) +-52 + j*(-67) +66 + j*(-297) +20 + j*(-185) +-270 + j*(-66) +15 + j*(-18) +-71 + j*(-7) +40 + j*(-203) +199 + j*(-431) +316 + j*(-88) +46 + j*(90) +-196 + j*(38) +91 + j*(-21) +-1 + j*(169) +96 + j*(36) +-76 + j*(-205) +289 + j*(76) +-132 + j*(-141) +-145 + j*(-97) +-1 + j*(171) +-51 + j*(182) +19 + j*(-129) +40 + j*(50) +-175 + j*(-300) +21 + j*(74) +51 + j*(142) +-128 + j*(-64) +-43 + j*(-92) +247 + j*(109) +-53 + j*(-28) +-20 + j*(-168) +47 + j*(331) +8 + j*(-158) +-7 + j*(-202) +-51 + j*(-9) +49 + j*(66) +26 + j*(67) +-157 + j*(-441) +82 + j*(-47) +-124 + j*(165) +-134 + j*(201) +-74 + j*(184) +201 + j*(-29) +85 + j*(-272) +68 + j*(-132) +138 + j*(-243) +-44 + j*(170) +-154 + j*(-1) +-93 + j*(79) +132 + j*(-134) +-168 + j*(132) +147 + j*(144) +-113 + j*(-10) +88 + j*(124) +-267 + j*(25) +63 + j*(-53) +156 + j*(-330) +75 + j*(167) +238 + j*(0) +189 + j*(29) +-175 + j*(-159) +110 + j*(-90) +-68 + j*(-70) +36 + j*(-15) +6 + j*(-356) +138 + j*(315) +17 + j*(-114) +-239 + j*(129) +279 + j*(21) +-151 + j*(-25) +103 + j*(-17) +213 + j*(8) +-81 + j*(148) +-171 + j*(24) +-63 + j*(6) +178 + j*(-13) +115 + j*(115) +187 + j*(148) +-191 + j*(-442) +-9 + j*(218) +-60 + j*(101) +-64 + j*(191) +-21 + j*(-170) +78 + j*(110) +-395 + j*(216) +122 + j*(186) +-81 + j*(2) +-324 + j*(237) +26 + j*(-274) +60 + j*(-154) +-54 + j*(-83) +9 + j*(240) +-117 + j*(63) +-10 + j*(3) +109 + j*(124) +55 + j*(-28) +51 + j*(-1) +293 + j*(-194) +-88 + j*(-208) +-58 + j*(-27) +48 + j*(117) +-287 + j*(97) +-105 + j*(-250) +-2 + j*(-269) +-204 + j*(-248) +-189 + j*(-123) +-134 + j*(206) +-114 + j*(-123) +-180 + j*(-58) +-320 + j*(-144) +-265 + j*(-50) +243 + j*(-311) +48 + j*(25) +-69 + j*(-78) +-98 + j*(25) +-3 + j*(-18) +63 + j*(-254) +-182 + j*(-132) +122 + j*(-55) +-43 + j*(161) +-257 + j*(219) +1 + j*(-32) +417 + j*(64) +-131 + j*(199) +-215 + j*(-242) +308 + j*(153) +157 + j*(-10) +-199 + j*(164) +-77 + j*(-54) +-68 + j*(76) +-22 + j*(-71) +101 + j*(95) +-223 + j*(-192) +-94 + j*(113) +-256 + j*(-165) +420 + j*(131) +62 + j*(0) +-168 + j*(95) +-69 + j*(-202) +137 + j*(1) +226 + j*(439) +153 + j*(-33) +-76 + j*(81) +-264 + j*(30) +400 + j*(62) +175 + j*(-37) +343 + j*(-157) +-302 + j*(59) +246 + j*(114) +148 + j*(-61) +112 + j*(74) +-134 + j*(-46) +-243 + j*(41) +255 + j*(-355) +-85 + j*(-38) +-110 + j*(183) +132 + j*(95) +-566 + j*(169) +313 + j*(162) +-31 + j*(-28) +-245 + j*(442) +-64 + j*(-252) +334 + j*(-138) +105 + j*(-85) +-135 + j*(16) +123 + j*(-224) +62 + j*(-48) +-78 + j*(-16) +-272 + j*(74) +66 + j*(222) +49 + j*(269) +-255 + j*(-76) +-192 + j*(-3) +11 + j*(-50) +168 + j*(293) +76 + j*(110) +-43 + j*(99) +187 + j*(61) +-340 + j*(-91) +-110 + j*(-132) +-156 + j*(-99) +149 + j*(103) +203 + j*(-56) +37 + j*(261) +-232 + j*(78) +44 + j*(13) +139 + j*(-14) +-58 + j*(-137) +-52 + j*(-281) +-231 + j*(35) +211 + j*(-35) +42 + j*(65) +-177 + j*(223) +127 + j*(61) +148 + j*(-34) +101 + j*(224) +-8 + j*(91) +-49 + j*(157) +-174 + j*(-173) +-47 + j*(-56) +-55 + j*(115) +-108 + j*(-19) +-147 + j*(-96) +-132 + j*(-86) +-23 + j*(23) +183 + j*(-191) +265 + j*(107) +-83 + j*(306) +50 + j*(239) +137 + j*(-273) +330 + j*(52) +-153 + j*(45) +-191 + j*(306) +171 + j*(-64) +-16 + j*(78) +-298 + j*(-16) +94 + j*(410) +-125 + j*(65) +-154 + j*(112) +81 + j*(69) +-151 + j*(-175) +294 + j*(-264) +-119 + j*(286) +-35 + j*(-293) +49 + j*(221) +-77 + j*(-30) +-170 + j*(407) +-198 + j*(14) +-5 + j*(6) +315 + j*(-35) +41 + j*(282) +241 + j*(25) +148 + j*(168) +34 + j*(196) +-248 + j*(161) +129 + j*(-66) +296 + j*(-42) +-45 + j*(119) +-87 + j*(141) +86 + j*(90) +66 + j*(-45) +-13 + j*(-129) +273 + j*(-148) +-6 + j*(-82) +227 + j*(-168) +32 + j*(-130) +59 + j*(-64) +11 + j*(99) +-91 + j*(-40) +208 + j*(-91) +218 + j*(69) +48 + j*(-325) +6 + j*(47) +6 + j*(-215) +-250 + j*(-271) +-98 + j*(36) +-180 + j*(-23) +-371 + j*(-30) +-242 + j*(-11) +191 + j*(6) +70 + j*(-28) +-90 + j*(171) +208 + j*(-58) +3 + j*(101) +122 + j*(-214) +13 + j*(99) +-80 + j*(217) +-315 + j*(182) +124 + j*(-228) +192 + j*(177) +330 + j*(61) +-270 + j*(-122) +-5 + j*(-162) +182 + j*(31) +-197 + j*(-168) +11 + j*(123) +86 + j*(277) +-37 + j*(-84) +164 + j*(-81) +148 + j*(24) +355 + j*(-25) +149 + j*(54) +-36 + j*(158) +189 + j*(-11) +127 + j*(141) +76 + j*(130) +-32 + j*(33) +-189 + j*(-19) +-35 + j*(-350) +-133 + j*(252) +-139 + j*(-38) +71 + j*(-33) +-42 + j*(-138) +-252 + j*(121) +283 + j*(140) +-50 + j*(135) +-124 + j*(-32) +124 + j*(289) +-84 + j*(153) +197 + j*(134) +-80 + j*(434) +-41 + j*(71) +159 + j*(-46) +30 + j*(321) +165 + j*(-438) +-47 + j*(98) +180 + j*(125) +-144 + j*(-28) +292 + j*(-85) +-129 + j*(168) +-117 + j*(54) +100 + j*(-224) +25 + j*(-146) +397 + j*(-4) +81 + j*(37) +-47 + j*(8) +20 + j*(-333) +110 + j*(-108) +-198 + j*(236) +-209 + j*(-77) +35 + j*(-111) +-82 + j*(78) +-46 + j*(-170) +150 + j*(153) +210 + j*(37) +-378 + j*(-346) +122 + j*(105) +-48 + j*(128) +4 + j*(250) +-42 + j*(233) +-59 + j*(46) +132 + j*(-116) +-69 + j*(51) +-296 + j*(228) +-81 + j*(40) +121 + j*(-190) +111 + j*(60) +-33 + j*(-152) +-71 + j*(145) +-310 + j*(-11) +-144 + j*(-107) +91 + j*(134) +-54 + j*(134) +15 + j*(154) +110 + j*(191) +-214 + j*(-2) +504 + j*(-209) +-42 + j*(-76) +284 + j*(75) +-138 + j*(-303) +-53 + j*(110) +120 + j*(74) +240 + j*(131) +272 + j*(-115) +3 + j*(69) +-32 + j*(18) +259 + j*(-187) +127 + j*(179) +-197 + j*(187) +337 + j*(-229) +-2 + j*(-35) +188 + j*(25) +-348 + j*(177) +138 + j*(-299) +-150 + j*(169) +140 + j*(231) +-232 + j*(92) +-8 + j*(131) +-88 + j*(144) +54 + j*(-169) +-54 + j*(95) +46 + j*(-153) +74 + j*(112) +-187 + j*(-75) +-163 + j*(-105) +-109 + j*(95) +-149 + j*(-81) +-320 + j*(128) +245 + j*(117) +-284 + j*(93) +-26 + j*(-222) +-240 + j*(144) +30 + j*(-30) +-11 + j*(327) +148 + j*(68) +149 + j*(37) +-110 + j*(-209) +348 + j*(7) +-69 + j*(-78) +207 + j*(13) +-160 + j*(-16) +-59 + j*(-75) +70 + j*(7) +203 + j*(220) +301 + j*(210) +-206 + j*(-198) +24 + j*(115) +-163 + j*(-298) +115 + j*(104) +222 + j*(290) +-147 + j*(-90) +-254 + j*(-416) +123 + j*(-111) +11 + j*(-310) +-179 + j*(-358) +334 + j*(-325) +-4 + j*(-132) +35 + j*(134) +5 + j*(-226) +243 + j*(-151) +28 + j*(15) +-40 + j*(62) +37 + j*(179) +308 + j*(-266) +-185 + j*(-283) +116 + j*(107) +374 + j*(-155) +270 + j*(137) +-241 + j*(292) +170 + j*(-226) +55 + j*(-2) +40 + j*(-28) +-175 + j*(8) +-221 + j*(-73) +-51 + j*(-106) +-148 + j*(-103) +109 + j*(143) +6 + j*(203) +149 + j*(239) +-368 + j*(-54) +95 + j*(249) +210 + j*(64) +13 + j*(-30) +302 + j*(80) +409 + j*(-78) +76 + j*(-308) +-71 + j*(-169) +-23 + j*(-222) +33 + j*(80) +-338 + j*(-320) +45 + j*(-105) +-66 + j*(-274) +70 + j*(-21) +48 + j*(27) +189 + j*(257) +-64 + j*(7) +-117 + j*(-42) +-28 + j*(-128) +-148 + j*(-406) +-174 + j*(-208) +198 + j*(-69) +147 + j*(-133) +257 + j*(-138) +-231 + j*(17) +127 + j*(-88) +88 + j*(42) +-126 + j*(36) +-63 + j*(-175) +123 + j*(-173) +-252 + j*(-136) +-198 + j*(122) +-290 + j*(237) +22 + j*(-23) +171 + j*(89) +239 + j*(-141) +11 + j*(-109) +301 + j*(-88) +-216 + j*(1) +14 + j*(-177) +47 + j*(6) +-161 + j*(20) +-186 + j*(-78) +173 + j*(-47) +-289 + j*(-68) +-81 + j*(83) +-77 + j*(164) +220 + j*(-20) +-106 + j*(177) +-292 + j*(-216) +74 + j*(-34) +245 + j*(1) +4 + j*(383) +-30 + j*(-119) +221 + j*(180) +139 + j*(-260) +-160 + j*(95) +58 + j*(361) +-223 + j*(57) +-59 + j*(-59) +-82 + j*(-51) +105 + j*(35) +59 + j*(146) +-158 + j*(-41) +-64 + j*(197) +-202 + j*(-83) +191 + j*(-335) +129 + j*(-421) +-30 + j*(-118) +69 + j*(129) +-116 + j*(-67) +-366 + j*(-18) +279 + j*(235) +-279 + j*(1) +45 + j*(-96) +-13 + j*(-238) +382 + j*(-21) +207 + j*(351) +192 + j*(-107) +-103 + j*(-137) +-90 + j*(110) +-262 + j*(-211) +-127 + j*(162) +109 + j*(40) +-238 + j*(127) +81 + j*(5) +-30 + j*(109) +118 + j*(71) +-12 + j*(26) +40 + j*(-161) +23 + j*(124) +-23 + j*(25) +-374 + j*(-62) +154 + j*(448) +-66 + j*(-63) +152 + j*(-354) +409 + j*(-129) +-469 + j*(96) +-4 + j*(-141) +-13 + j*(142) +276 + j*(12) +-135 + j*(-289) +-50 + j*(181) +-205 + j*(-146) +196 + j*(255) +-200 + j*(23) +279 + j*(52) +-76 + j*(196) +40 + j*(98) +-62 + j*(211) +74 + j*(73) +-161 + j*(-179) +-134 + j*(-2) +-18 + j*(-132) +444 + j*(21) +-194 + j*(69) +-92 + j*(25) +-119 + j*(-431) +121 + j*(136) +-100 + j*(63) +14 + j*(-67) +66 + j*(234) +-35 + j*(288) +356 + j*(-111) +-74 + j*(-60) +215 + j*(206) +-46 + j*(8) +-4 + j*(-153) +-135 + j*(-165) +274 + j*(-99) +-218 + j*(-60) +-7 + j*(145) +-282 + j*(-132) +-21 + j*(-270) +35 + j*(-186) +59 + j*(161) +-148 + j*(-212) +-452 + j*(-222) +203 + j*(-168) +16 + j*(142) +177 + j*(448) +56 + j*(-74) +-37 + j*(119) +-47 + j*(48) +192 + j*(30) +-243 + j*(67) +-199 + j*(78) +197 + j*(103) +164 + j*(-210) +-33 + j*(185) +-55 + j*(35) +-388 + j*(21) +-49 + j*(-101) +-27 + j*(-276) +-197 + j*(-151) +-236 + j*(-178) +-32 + j*(-162) +-78 + j*(257) +-75 + j*(85) +157 + j*(-10) +-147 + j*(-3) +21 + j*(-8) +120 + j*(120) +132 + j*(98) +-140 + j*(-98) +194 + j*(-322) +113 + j*(-51) +177 + j*(-63) +41 + j*(204) +146 + j*(45) +-145 + j*(62) +17 + j*(74) +257 + j*(-247) +-16 + j*(-193) +-33 + j*(-364) +-297 + j*(100) +18 + j*(-268) +-79 + j*(-70) +49 + j*(17) +-61 + j*(-52) +296 + j*(-32) +37 + j*(168) +-117 + j*(-164) +-74 + j*(-211) +-87 + j*(66) +-165 + j*(-38) +18 + j*(136) +14 + j*(74) +187 + j*(172) +99 + j*(22) +95 + j*(-151) +88 + j*(-236) +-201 + j*(92) +91 + j*(214) +280 + j*(200) +254 + j*(-28) +82 + j*(199) +-333 + j*(294) +-64 + j*(-255) +228 + j*(375) +-1 + j*(94) +211 + j*(-207) +299 + j*(-447) +-104 + j*(-17) +-30 + j*(-28) +-164 + j*(-211) +-87 + j*(-76) +-124 + j*(264) +176 + j*(-222) +221 + j*(-322) +158 + j*(148) +-307 + j*(-128) +86 + j*(9) +-10 + j*(-23) +131 + j*(25) +-108 + j*(186) +-144 + j*(132) +67 + j*(121) +11 + j*(-222) +1 + j*(93) +182 + j*(93) +-114 + j*(200) +87 + j*(163) +88 + j*(86) +-73 + j*(-90) +123 + j*(-30) +-16 + j*(-27) +214 + j*(-188) +-36 + j*(25) +-286 + j*(310) +-202 + j*(-54) +-223 + j*(238) +-161 + j*(54) +-62 + j*(170) +-214 + j*(-35) +110 + j*(264) +262 + j*(265) +100 + j*(37) +-488 + j*(305) +-148 + j*(254) +-253 + j*(123) +146 + j*(182) +-332 + j*(-199) +55 + j*(-65) +204 + j*(83) +-1 + j*(-51) +32 + j*(-314) +43 + j*(23) +68 + j*(-412) +78 + j*(-180) +-197 + j*(146) +-76 + j*(-66) +136 + j*(-226) +40 + j*(241) +27 + j*(-177) +-144 + j*(66) +112 + j*(-258) +163 + j*(-74) +-1 + j*(-81) +52 + j*(469) +3 + j*(-276) +148 + j*(107) +-93 + j*(-173) +64 + j*(37) +-231 + j*(124) +61 + j*(-131) +-88 + j*(114) +107 + j*(-32) +-170 + j*(240) +226 + j*(-173) +58 + j*(-247) +22 + j*(47) +168 + j*(181) +16 + j*(158) +-120 + j*(-66) +-81 + j*(296) +-209 + j*(-192) +-75 + j*(-115) +95 + j*(86) +32 + j*(125) +57 + j*(64) +6 + j*(-11) +-367 + j*(-47) +180 + j*(-28) +-443 + j*(-35) +-174 + j*(67) +-83 + j*(-21) +64 + j*(-84) +206 + j*(-67) +25 + j*(-205) +-205 + j*(139) +16 + j*(-135) +-233 + j*(-43) +158 + j*(-4) +-18 + j*(-106) +-87 + j*(129) +-112 + j*(-28) +159 + j*(144) +98 + j*(-110) +-11 + j*(28) +-41 + j*(192) +21 + j*(-199) +-26 + j*(233) +6 + j*(-337) +412 + j*(7) +-136 + j*(-25) +83 + j*(103) +-45 + j*(62) +79 + j*(20) +86 + j*(20) +142 + j*(284) +-45 + j*(-91) +100 + j*(67) +-142 + j*(100) +-223 + j*(248) +-3 + j*(120) +311 + j*(-245) +62 + j*(-47) +91 + j*(-78) +-141 + j*(-132) +4 + j*(-133) +81 + j*(-179) +-13 + j*(166) +20 + j*(180) +182 + j*(-139) +230 + j*(83) +387 + j*(67) +-6 + j*(-113) +63 + j*(161) +-198 + j*(104) +-36 + j*(-129) +-30 + j*(-63) +112 + j*(-41) +127 + j*(189) +156 + j*(62) +-110 + j*(-12) +52 + j*(-182) +-110 + j*(-298) +-151 + j*(180) +234 + j*(-178) +14 + j*(69) +75 + j*(-57) +236 + j*(-168) +-54 + j*(-212) +-194 + j*(15) +80 + j*(347) +190 + j*(412) +11 + j*(-153) +59 + j*(28) +-182 + j*(-11) +54 + j*(145) +69 + j*(78) +166 + j*(-189) +204 + j*(-157) +83 + j*(-216) +87 + j*(-35) +-200 + j*(-156) +455 + j*(141) +7 + j*(-114) +91 + j*(305) +-95 + j*(62) +-254 + j*(-61) +-80 + j*(117) +-30 + j*(-195) +-146 + j*(105) +21 + j*(-25) +305 + j*(23) +-81 + j*(-15) +192 + j*(395) +141 + j*(303) +-52 + j*(-129) +54 + j*(-149) +63 + j*(64) +98 + j*(-260) +132 + j*(19) +-59 + j*(-57) +116 + j*(170) +251 + j*(-284) +42 + j*(208) +51 + j*(-195) +-98 + j*(-44) +-57 + j*(55) +106 + j*(-38) +-243 + j*(16) +153 + j*(-65) +7 + j*(-110) +88 + j*(-73) +-279 + j*(77) +-173 + j*(40) +-112 + j*(0) +-154 + j*(-228) +2 + j*(-147) +-166 + j*(126) +119 + j*(148) +-215 + j*(114) +-155 + j*(23) +-41 + j*(-34) +40 + j*(-300) +-328 + j*(202) +-206 + j*(-212) +59 + j*(-325) +25 + j*(-100) +-208 + j*(-235) +-233 + j*(167) +-243 + j*(20) +-203 + j*(0) +-168 + j*(-173) +-310 + j*(-146) +-148 + j*(398) +-72 + j*(-93) +62 + j*(-152) +28 + j*(128) +-217 + j*(-27) +-222 + j*(-188) +168 + j*(16) +-100 + j*(140) +99 + j*(8) +76 + j*(-57) +139 + j*(-150) +-192 + j*(-49) +-18 + j*(-206) +-16 + j*(-327) +78 + j*(35) +11 + j*(42) +-107 + j*(-82) +-274 + j*(235) +81 + j*(-11) +281 + j*(-61) +-148 + j*(78) +-279 + j*(-51) +-252 + j*(186) +31 + j*(-99) +292 + j*(-155) +-188 + j*(192) +258 + j*(-96) +21 + j*(-92) +-28 + j*(165) +146 + j*(59) +0 + j*(-21) +30 + j*(-192) +82 + j*(14) +-294 + j*(-13) +-150 + j*(137) +-71 + j*(68) +-233 + j*(45) +12 + j*(-62) +-177 + j*(44) +-175 + j*(337) +-41 + j*(1) +363 + j*(-244) +231 + j*(181) +191 + j*(-130) +287 + j*(115) +-69 + j*(221) +-236 + j*(-50) +-393 + j*(-47) +71 + j*(13) +447 + j*(-110) +-76 + j*(316) +42 + j*(71) +-20 + j*(-75) +-17 + j*(82) +-231 + j*(-258) +156 + j*(-174) +-85 + j*(-142) +-165 + j*(-173) +-185 + j*(-25) +173 + j*(137) +303 + j*(-119) +-86 + j*(-105) +-253 + j*(-318) +-68 + j*(142) +-213 + j*(259) +179 + j*(-58) +-93 + j*(122) +135 + j*(-185) +-1 + j*(-180) +261 + j*(-385) +-207 + j*(-315) +6 + j*(-70) +216 + j*(339) +-137 + j*(-129) +35 + j*(15) +16 + j*(127) +71 + j*(-29) +-254 + j*(-211) +-325 + j*(103) +-222 + j*(6) +159 + j*(91) +25 + j*(106) +-139 + j*(101) +-133 + j*(-289) +-124 + j*(-40) +-238 + j*(-183) +-144 + j*(-1) +111 + j*(-64) +63 + j*(-308) +-78 + j*(-153) +324 + j*(-243) +209 + j*(11) +64 + j*(232) +71 + j*(62) +203 + j*(-52) +-161 + j*(129) +-339 + j*(144) +78 + j*(86) +66 + j*(-263) +-78 + j*(-190) +247 + j*(293) +-25 + j*(19) +-267 + j*(-15) +89 + j*(-206) +-64 + j*(120) +83 + j*(165) +-195 + j*(249) +-55 + j*(-379) +-194 + j*(19) +-139 + j*(49) +316 + j*(-139) +-190 + j*(170) +-33 + j*(34) +14 + j*(-44) +-363 + j*(50) +39 + j*(77) +296 + j*(-133) +-183 + j*(289) +-96 + j*(-81) +-74 + j*(-333) +92 + j*(-183) +-99 + j*(167) +-63 + j*(21) +339 + j*(-39) +-175 + j*(-257) +72 + j*(117) +-192 + j*(105) +17 + j*(-17) +-84 + j*(166) +49 + j*(188) +-156 + j*(153) +74 + j*(-169) +-35 + j*(280) +-81 + j*(101) +9 + j*(112) +214 + j*(-38) +254 + j*(-35) +78 + j*(263) +125 + j*(-71) +100 + j*(68) +339 + j*(111) +-10 + j*(134) +-4 + j*(-69) +-98 + j*(74) +-41 + j*(106) +-28 + j*(330) +325 + j*(88) +-59 + j*(41) +-110 + j*(-247) +154 + j*(16) +463 + j*(363) +-112 + j*(-29) +133 + j*(-1) +315 + j*(208) +-102 + j*(-248) +135 + j*(23) +328 + j*(11) +201 + j*(46) +163 + j*(134) +224 + j*(-62) +178 + j*(-89) +136 + j*(107) +69 + j*(-224) +140 + j*(-87) +-112 + j*(254) +-65 + j*(120) +-239 + j*(-35) +80 + j*(30) +-331 + j*(-125) +-71 + j*(45) +31 + j*(417) +-17 + j*(-139) +-54 + j*(49) +246 + j*(-253) +-6 + j*(101) +110 + j*(-138) +-88 + j*(56) +66 + j*(264) +-255 + j*(-18) +-155 + j*(95) +-332 + j*(88) +-103 + j*(25) +-618 + j*(214) +213 + j*(-211) +260 + j*(-49) +-94 + j*(-75) +-9 + j*(12) +97 + j*(171) +74 + j*(219) +-18 + j*(-54) +101 + j*(-135) +-159 + j*(82) +-48 + j*(-196) +408 + j*(275) +-194 + j*(-74) +111 + j*(337) +-13 + j*(409) +-106 + j*(-51) +-178 + j*(-203) +-228 + j*(-69) +-243 + j*(-10) +1 + j*(-8) +177 + j*(-189) +85 + j*(16) +131 + j*(270) +-96 + j*(226) +-4 + j*(336) +-217 + j*(42) +-99 + j*(-82) +-206 + j*(-93) +18 + j*(295) +99 + j*(-189) +-350 + j*(129) +-8 + j*(91) +59 + j*(-274) +-83 + j*(173) +48 + j*(29) +207 + j*(-75) +49 + j*(78) +-65 + j*(-382) +193 + j*(100) +-70 + j*(42) +33 + j*(-206) +228 + j*(49) +53 + j*(208) +-76 + j*(-93) +102 + j*(-103) +-256 + j*(-43) +86 + j*(-13) +-111 + j*(40) +186 + j*(-48) +-2 + j*(498) +-182 + j*(52) +-127 + j*(81) +74 + j*(-54) +38 + j*(-88) +35 + j*(-194) +-173 + j*(112) +-129 + j*(224) +-54 + j*(-2) +191 + j*(113) +-88 + j*(72) +-69 + j*(-259) +84 + j*(240) +-187 + j*(70) +-79 + j*(-11) +259 + j*(206) +123 + j*(365) +92 + j*(103) +-187 + j*(76) +54 + j*(232) +40 + j*(-158) +-212 + j*(-424) +-91 + j*(215) +-112 + j*(138) +-110 + j*(243) +-110 + j*(145) +72 + j*(80) +30 + j*(-110) +180 + j*(26) +63 + j*(5) +232 + j*(238) +199 + j*(-119) +438 + j*(64) +-40 + j*(-139) +-146 + j*(-31) +85 + j*(167) +139 + j*(-206) +45 + j*(66) +98 + j*(-75) +23 + j*(131) +131 + j*(15) +-84 + j*(126) +-64 + j*(-182) +28 + j*(141) +17 + j*(37) +194 + j*(6) +-4 + j*(336) +160 + j*(205) +-259 + j*(113) +-52 + j*(4) +-104 + j*(-249) +-11 + j*(-245) +-66 + j*(86) +30 + j*(-138) +90 + j*(-182) +47 + j*(122) +281 + j*(166) +-230 + j*(13) +-165 + j*(380) +222 + j*(-15) +-247 + j*(113) +-91 + j*(-12) +-88 + j*(200) +-69 + j*(240) +-165 + j*(-6) +-124 + j*(-184) +-327 + j*(296) +-209 + j*(37) +-114 + j*(-329) +238 + j*(-267) +-122 + j*(-149) +-104 + j*(-238) +339 + j*(264) +347 + j*(76) +184 + j*(-87) +272 + j*(-118) +10 + j*(169) +23 + j*(74) +-53 + j*(377) +-180 + j*(-162) +-35 + j*(-269) +73 + j*(280) +-176 + j*(-9) +69 + j*(172) +-14 + j*(101) +-124 + j*(-119) +-54 + j*(-187) +-47 + j*(158) +352 + j*(147) +167 + j*(312) +-187 + j*(-197) +101 + j*(202) +-170 + j*(-168) +140 + j*(39) +132 + j*(40) +29 + j*(-33) +-226 + j*(204) +-341 + j*(-25) +-21 + j*(235) +110 + j*(25) +-176 + j*(40) +-35 + j*(105) +-175 + j*(13) +-85 + j*(-78) +-216 + j*(-102) +147 + j*(43) +370 + j*(-45) +-330 + j*(-246) +-337 + j*(179) +-133 + j*(67) +110 + j*(-80) +92 + j*(-27) +199 + j*(-197) +150 + j*(98) +-129 + j*(79) +-209 + j*(-61) +-128 + j*(406) +472 + j*(301) +-19 + j*(146) +-18 + j*(-83) +-54 + j*(-16) +121 + j*(76) +-417 + j*(77) +-192 + j*(-91) +35 + j*(232) +240 + j*(161) +-132 + j*(-16) +-149 + j*(72) +-26 + j*(-36) +-112 + j*(-83) +-86 + j*(-100) +83 + j*(-132) +-123 + j*(53) +-269 + j*(-47) +-93 + j*(180) +129 + j*(200) +-218 + j*(105) +116 + j*(98) +-157 + j*(-165) +-252 + j*(-54) +87 + j*(91) +309 + j*(-156) +72 + j*(-159) +-16 + j*(-136) +-54 + j*(16) +-103 + j*(170) +76 + j*(182) +-231 + j*(-148) +47 + j*(169) +21 + j*(163) +84 + j*(261) +198 + j*(223) +-277 + j*(100) +-166 + j*(-125) +125 + j*(-30) +-276 + j*(266) +159 + j*(26) +311 + j*(171) +-404 + j*(289) +-104 + j*(-370) +172 + j*(-347) +59 + j*(-465) +-428 + j*(43) +26 + j*(-619) +-139 + j*(192) +213 + j*(469) +395 + j*(104) +146 + j*(-270) +77 + j*(257) +-204 + j*(245) +61 + j*(264) +317 + j*(351) +395 + j*(379) +-250 + j*(-278) +547 + j*(-360) +-296 + j*(-69) +71 + j*(260) +456 + j*(-113) +316 + j*(214) +107 + j*(-390) +313 + j*(228) +-105 + j*(486) +120 + j*(275) +541 + j*(-306) +-351 + j*(-19) +-144 + j*(-456) +103 + j*(-197) +-262 + j*(-299) +305 + j*(62) +-245 + j*(-17) +-219 + j*(472) +200 + j*(-195) +-155 + j*(-257) +-211 + j*(341) +146 + j*(262) +-86 + j*(229) +-245 + j*(-318) +368 + j*(-296) +-375 + j*(305) +-582 + j*(149) +412 + j*(-397) +421 + j*(-441) +434 + j*(-191) +141 + j*(325) +-331 + j*(88) +610 + j*(43) +-328 + j*(305) +351 + j*(-415) +161 + j*(428) +530 + j*(142) +-705 + j*(-324) +-76 + j*(132) +-316 + j*(-183) +-307 + j*(187) +148 + j*(361) +183 + j*(94) +-168 + j*(360) +-266 + j*(129) +-301 + j*(-244) +-252 + j*(232) +-546 + j*(216) +-227 + j*(121) +-35 + j*(-342) +-190 + j*(-325) +-59 + j*(523) +-171 + j*(-315) +297 + j*(183) +194 + j*(148) +-443 + j*(281) +-512 + j*(-66) +532 + j*(250) +-276 + j*(306) +-358 + j*(187) +-477 + j*(518) +-310 + j*(-158) +167 + j*(-405) +66 + j*(-134) +96 + j*(379) +-23 + j*(-460) +-404 + j*(-227) +-14 + j*(-501) +-691 + j*(-200) +-339 + j*(30) +648 + j*(317) +347 + j*(-322) +-260 + j*(597) +-610 + j*(216) +443 + j*(205) +249 + j*(-314) +486 + j*(-170) +-298 + j*(87) +141 + j*(238) +-60 + j*(-71) +67 + j*(-124) +-291 + j*(-540) +174 + j*(-324) +-161 + j*(-228) +193 + j*(-37) +-153 + j*(-331) +235 + j*(293) +-141 + j*(-504) +339 + j*(49) +373 + j*(21) +473 + j*(355) +-270 + j*(268) +-26 + j*(-260) +379 + j*(-419) +178 + j*(-35) +307 + j*(680) +564 + j*(-397) +-474 + j*(-527) +482 + j*(207) +374 + j*(51) +3 + j*(123) +5 + j*(586) +267 + j*(491) +185 + j*(225) +312 + j*(556) +4 + j*(-366) +166 + j*(405) +-346 + j*(422) +-438 + j*(-416) +390 + j*(-59) +30 + j*(-288) +274 + j*(-242) +-114 + j*(-100) +-177 + j*(-375) +-455 + j*(-292) +-272 + j*(301) +-218 + j*(-479) +447 + j*(-296) +-335 + j*(-378) +-427 + j*(-16) +308 + j*(-300) +479 + j*(322) +-170 + j*(82) +-366 + j*(-153) +-701 + j*(-477) +-350 + j*(282) +-327 + j*(344) +-389 + j*(-333) +-450 + j*(-218) +-3 + j*(682) +260 + j*(-402) +70 + j*(305) +588 + j*(520) +-1 + j*(-161) +-292 + j*(-104) +-267 + j*(434) +-195 + j*(404) +-435 + j*(542) +-376 + j*(-235) +-187 + j*(42) +61 + j*(550) +-125 + j*(93) +-262 + j*(217) +512 + j*(234) +405 + j*(358) +52 + j*(-291) +1 + j*(395) +450 + j*(-216) +-172 + j*(432) +-180 + j*(-247) +15 + j*(-400) +-78 + j*(363) +227 + j*(123) +403 + j*(-133) +-124 + j*(258) +-400 + j*(-366) +72 + j*(-175) +-140 + j*(-51) +90 + j*(-166) +-484 + j*(148) +-404 + j*(-392) +-197 + j*(133) +241 + j*(-45) +122 + j*(-306) +-136 + j*(296) +-194 + j*(264) +516 + j*(-226) +-168 + j*(-320) +-14 + j*(-386) +231 + j*(440) +146 + j*(346) +268 + j*(451) +184 + j*(-27) +310 + j*(214) +409 + j*(-258) +-361 + j*(-303) +153 + j*(-127) +-217 + j*(-438) +107 + j*(476) +-204 + j*(403) +-313 + j*(315) +-328 + j*(-307) +-351 + j*(97) +185 + j*(-211) +122 + j*(233) +-445 + j*(-503) +-212 + j*(-397) +-420 + j*(196) +64 + j*(-252) +407 + j*(-336) +-265 + j*(280) +281 + j*(-268) +218 + j*(-292) +-138 + j*(484) +-16 + j*(192) +474 + j*(362) +-399 + j*(-2) +73 + j*(-350) +264 + j*(158) +365 + j*(-137) +71 + j*(-62) +-389 + j*(-485) +-74 + j*(-57) +-281 + j*(252) +299 + j*(258) +1 + j*(200) +252 + j*(44) +95 + j*(-210) +180 + j*(-445) +-356 + j*(228) +90 + j*(-321) +-198 + j*(-281) +441 + j*(-279) +-417 + j*(428) +-317 + j*(-210) +156 + j*(-520) +-59 + j*(-228) +238 + j*(-274) +-299 + j*(-308) +-270 + j*(-294) +-181 + j*(-165) +180 + j*(-48) +-172 + j*(-289) +395 + j*(77) +212 + j*(-88) +361 + j*(378) +-260 + j*(-753) +205 + j*(-86) +-151 + j*(127) +416 + j*(-146) +121 + j*(-566) +65 + j*(-477) +119 + j*(281) +43 + j*(-42) +-172 + j*(182) +-340 + j*(396) +51 + j*(286) +235 + j*(-410) +296 + j*(-146) +-86 + j*(-184) +-59 + j*(-322) +-381 + j*(236) +98 + j*(-173) +-176 + j*(218) +-682 + j*(-62) +-41 + j*(-211) +-525 + j*(-330) +36 + j*(-36) +-578 + j*(-367) +-245 + j*(380) +-305 + j*(301) +333 + j*(-141) +-127 + j*(-254) +308 + j*(-378) +-358 + j*(177) +231 + j*(216) +-112 + j*(459) +-436 + j*(-497) +296 + j*(231) +-276 + j*(-409) +299 + j*(144) +310 + j*(-267) +-309 + j*(-237) +-204 + j*(104) +158 + j*(194) +325 + j*(-127) +140 + j*(260) +52 + j*(131) +29 + j*(-135) +-162 + j*(345) +-5 + j*(132) +69 + j*(-456) +302 + j*(149) +211 + j*(-262) +-506 + j*(-175) +292 + j*(182) +52 + j*(-322) +365 + j*(-232) +312 + j*(-269) +-319 + j*(21) +-315 + j*(-581) +-138 + j*(167) +-43 + j*(197) +-42 + j*(450) +-296 + j*(155) +-540 + j*(358) +-307 + j*(87) +-446 + j*(-250) +97 + j*(116) +140 + j*(-486) +300 + j*(-278) +-419 + j*(163) +-211 + j*(-185) +-194 + j*(367) +291 + j*(250) +312 + j*(-236) +195 + j*(81) +-465 + j*(-375) +482 + j*(115) +116 + j*(120) +122 + j*(320) +-55 + j*(-224) +-280 + j*(177) +542 + j*(-264) +416 + j*(103) +-152 + j*(-113) +-116 + j*(-58) +-139 + j*(-262) +-165 + j*(-510) +-57 + j*(-504) +168 + j*(-228) +474 + j*(-120) +-119 + j*(10) +313 + j*(-328) +-291 + j*(209) +271 + j*(-57) +358 + j*(-245) +419 + j*(-226) +-45 + j*(-529) +344 + j*(-443) +147 + j*(-416) +-105 + j*(-279) +40 + j*(4) +-409 + j*(212) +-322 + j*(-257) +-169 + j*(-639) +-194 + j*(-323) +311 + j*(-214) +-356 + j*(559) +318 + j*(-374) +157 + j*(112) +-339 + j*(76) +-456 + j*(153) +-328 + j*(-325) +504 + j*(113) +-447 + j*(219) +173 + j*(284) +194 + j*(-21) +-136 + j*(-310) +-91 + j*(351) +-112 + j*(-317) +474 + j*(227) +-348 + j*(124) +368 + j*(-102) +395 + j*(-190) +-172 + j*(202) +-148 + j*(-287) +393 + j*(-330) +144 + j*(411) +-259 + j*(238) +371 + j*(-130) +40 + j*(-457) +129 + j*(-453) +-451 + j*(-215) +-333 + j*(242) +353 + j*(334) +-604 + j*(356) +209 + j*(-318) +-358 + j*(-76) +-118 + j*(-313) +439 + j*(-315) +60 + j*(-572) +-457 + j*(282) +-834 + j*(-7) +428 + j*(-140) +325 + j*(215) +42 + j*(263) +301 + j*(151) +140 + j*(-72) +489 + j*(-438) +323 + j*(-402) +194 + j*(-13) +257 + j*(-322) +-334 + j*(267) +231 + j*(409) +-231 + j*(-271) +-265 + j*(394) +-324 + j*(-305) +-588 + j*(-325) +84 + j*(-489) +366 + j*(43) +-291 + j*(108) +533 + j*(-455) +-100 + j*(352) +181 + j*(-187) +287 + j*(-428) +-322 + j*(17) +90 + j*(-332) +413 + j*(-171) +-474 + j*(-153) +-167 + j*(-209) +76 + j*(-141) +395 + j*(201) +-330 + j*(212) +127 + j*(-255) +120 + j*(-15) +-132 + j*(190) +-436 + j*(-209) +-281 + j*(425) +300 + j*(-408) +-162 + j*(-301) +-316 + j*(-458) +166 + j*(-491) +-384 + j*(-423) +568 + j*(-527) +-212 + j*(296) +-204 + j*(-298) +-229 + j*(117) +-159 + j*(-412) +365 + j*(358) +260 + j*(-245) +247 + j*(33) +162 + j*(139) +-332 + j*(284) +-489 + j*(-540) +-221 + j*(-39) +-55 + j*(-142) +-129 + j*(360) +235 + j*(-252) +513 + j*(104) +-58 + j*(-313) +419 + j*(284) +-267 + j*(316) +588 + j*(-197) +-193 + j*(-361) +370 + j*(556) +-269 + j*(106) +153 + j*(-44) +-167 + j*(-265) +-21 + j*(240) +324 + j*(-368) +-233 + j*(-361) +-260 + j*(-260) +-504 + j*(245) +-684 + j*(316) +-13 + j*(-153) +89 + j*(-546) +268 + j*(-261) +392 + j*(448) +359 + j*(397) +448 + j*(-398) +-400 + j*(-225) +-547 + j*(-383) +399 + j*(429) +-360 + j*(-187) +36 + j*(-126) +-384 + j*(291) +158 + j*(-358) +337 + j*(569) +431 + j*(-49) +581 + j*(30) +158 + j*(-206) +361 + j*(-217) +-216 + j*(-233) +309 + j*(-486) +258 + j*(-265) +363 + j*(199) +-440 + j*(309) +-134 + j*(-397) +441 + j*(298) +356 + j*(285) +148 + j*(-550) +207 + j*(86) +537 + j*(395) +-137 + j*(297) +-80 + j*(409) +696 + j*(23) +25 + j*(-275) +402 + j*(129) +334 + j*(219) +79 + j*(271) +-461 + j*(-98) +21 + j*(-23) +-138 + j*(354) +487 + j*(-36) +373 + j*(-1) +-540 + j*(-255) +108 + j*(-153) +232 + j*(249) +262 + j*(136) +-284 + j*(-388) +254 + j*(-303) +4 + j*(-573) +-71 + j*(327) +-25 + j*(-76) +-33 + j*(-450) +248 + j*(362) +61 + j*(-260) +288 + j*(272) +245 + j*(-42) +-204 + j*(277) +-479 + j*(-407) +-165 + j*(451) +409 + j*(445) +-143 + j*(566) +-254 + j*(-428) +-61 + j*(408) +-203 + j*(-141) +-38 + j*(893) +-53 + j*(235) +170 + j*(-614) +217 + j*(180) +499 + j*(-375) +-339 + j*(232) +-112 + j*(-235) +290 + j*(233) +-400 + j*(214) +470 + j*(363) +-634 + j*(-109) +-344 + j*(45) +308 + j*(-479) +-330 + j*(-6) +-141 + j*(-100) +-275 + j*(195) +474 + j*(139) +23 + j*(482) +-501 + j*(-599) +-23 + j*(105) +204 + j*(-323) +220 + j*(119) +471 + j*(-33) +-176 + j*(-472) +-64 + j*(-11) +-98 + j*(158) +94 + j*(-177) +-395 + j*(-368) +106 + j*(106) +-556 + j*(-269) +404 + j*(389) +-13 + j*(-54) +-25 + j*(455) +2 + j*(366) +418 + j*(-81) +390 + j*(-341) +-173 + j*(-397) +364 + j*(-233) +17 + j*(-495) +-489 + j*(86) +-287 + j*(419) +93 + j*(431) +-31 + j*(212) +-218 + j*(-117) +-233 + j*(244) +1 + j*(130) +-180 + j*(-312) +-434 + j*(57) +501 + j*(22) +324 + j*(-359) +-497 + j*(-63) +453 + j*(-11) +225 + j*(-460) +-413 + j*(-100) +-16 + j*(440) +500 + j*(130) +-414 + j*(161) +469 + j*(326) +211 + j*(175) +332 + j*(-65) +407 + j*(13) +207 + j*(467) +-366 + j*(372) +200 + j*(-223) +-301 + j*(-318) +-198 + j*(-273) +-209 + j*(221) +-148 + j*(5) +102 + j*(433) +-107 + j*(-116) +303 + j*(337) +356 + j*(98) +-203 + j*(369) +452 + j*(281) +-542 + j*(421) +54 + j*(371) +222 + j*(-46) +559 + j*(544) +100 + j*(-298) +68 + j*(204) +-264 + j*(-267) +-97 + j*(-311) +-738 + j*(203) +282 + j*(342) +-310 + j*(778) +-209 + j*(102) +154 + j*(-2) +11 + j*(-8) +153 + j*(222) +4 + j*(-33) +309 + j*(283) +-8 + j*(117) +-136 + j*(-322) +35 + j*(33) +-11 + j*(176) +119 + j*(237) +186 + j*(45) +77 + j*(124) +288 + j*(35) +-57 + j*(216) +101 + j*(-8) +119 + j*(-40) +102 + j*(-182) +15 + j*(83) +-88 + j*(74) +187 + j*(388) +-7 + j*(-26) +284 + j*(-194) +235 + j*(-341) +-86 + j*(-122) +-98 + j*(-227) +-177 + j*(-59) +-202 + j*(-35) +-58 + j*(-23) +-12 + j*(-45) +83 + j*(33) +-135 + j*(-110) +-112 + j*(-204) +-404 + j*(-49) +-187 + j*(-67) +-158 + j*(168) +-105 + j*(-175) +13 + j*(-358) +4 + j*(-224) +35 + j*(-62) +120 + j*(-361) +-274 + j*(-179) +-63 + j*(23) +-110 + j*(-18) +-194 + j*(-4) +-61 + j*(-28) +138 + j*(-290) +100 + j*(-38) +-128 + j*(-204) +-246 + j*(-176) +397 + j*(33) +180 + j*(80) +-214 + j*(-113) +-52 + j*(244) +-95 + j*(-3) +-87 + j*(-13) +15 + j*(73) +71 + j*(-78) +110 + j*(-1) +4 + j*(-154) +65 + j*(-86) +-14 + j*(100) +-88 + j*(21) +-117 + j*(120) +-478 + j*(-64) +-50 + j*(-23) +217 + j*(10) +-46 + j*(-238) +60 + j*(-23) +235 + j*(-35) +-79 + j*(339) +-192 + j*(-21) +-89 + j*(135) +-107 + j*(126) +-221 + j*(42) +211 + j*(184) +66 + j*(-160) +-168 + j*(-4) +-105 + j*(85) +132 + j*(-27) +124 + j*(-130) +174 + j*(-112) +151 + j*(76) +249 + j*(-163) +72 + j*(233) +-243 + j*(-77) +-294 + j*(-25) +-281 + j*(61) +112 + j*(67) +-37 + j*(13) +74 + j*(-144) +-168 + j*(-35) +-13 + j*(-313) +-386 + j*(10) +-311 + j*(-79) +-11 + j*(90) +185 + j*(405) +186 + j*(-17) +-127 + j*(-137) +10 + j*(136) +-59 + j*(110) +1 + j*(-83) +-20 + j*(-180) +214 + j*(361) +231 + j*(62) +-104 + j*(-86) +-192 + j*(185) +-108 + j*(170) +-169 + j*(-192) +-104 + j*(-171) +-28 + j*(-57) +-208 + j*(126) +185 + j*(-78) +105 + j*(159) +-228 + j*(-110) +340 + j*(82) +235 + j*(214) +-80 + j*(-14) +234 + j*(-162) +-131 + j*(63) +-43 + j*(60) +-157 + j*(68) +-207 + j*(144) +-77 + j*(53) +214 + j*(147) +-150 + j*(-83) +-100 + j*(90) +-43 + j*(90) +97 + j*(129) +-34 + j*(-44) +14 + j*(86) +-258 + j*(47) +161 + j*(38) +286 + j*(-1) +113 + j*(178) +-124 + j*(-255) +-3 + j*(347) +136 + j*(-137) +62 + j*(-89) +36 + j*(267) +-74 + j*(-311) +-1 + j*(109) +96 + j*(-269) +223 + j*(-111) +298 + j*(-105) +-149 + j*(9) +-303 + j*(36) +-265 + j*(276) +-324 + j*(-81) +-176 + j*(-8) +243 + j*(311) +-18 + j*(-35) +-212 + j*(177) +-35 + j*(158) +20 + j*(121) +70 + j*(64) +-201 + j*(-1) +-76 + j*(258) +-252 + j*(101) +2 + j*(225) +92 + j*(-81) +123 + j*(-123) +-125 + j*(78) +146 + j*(-37) +184 + j*(375) +62 + j*(102) +-294 + j*(196) +-3 + j*(217) +-214 + j*(322) +559 + j*(98) +-136 + j*(173) +47 + j*(-37) +98 + j*(-22) +234 + j*(-21) +36 + j*(-142) +239 + j*(-272) +-58 + j*(198) +390 + j*(37) +-132 + j*(-216) +-95 + j*(-52) +27 + j*(-119) +-8 + j*(143) +122 + j*(110) +145 + j*(-146) +210 + j*(-166) +-73 + j*(-25) +136 + j*(45) +150 + j*(-169) +45 + j*(-17) +122 + j*(-30) +110 + j*(-110) +63 + j*(-232) +330 + j*(312) +-204 + j*(-26) +204 + j*(129) +-87 + j*(88) +240 + j*(73) +129 + j*(-101) +-68 + j*(92) +115 + j*(122) +273 + j*(103) +-320 + j*(-144) +79 + j*(93) +-335 + j*(242) +308 + j*(1) +52 + j*(119) +206 + j*(-37) +106 + j*(-74) +-288 + j*(-274) +-131 + j*(194) +-107 + j*(-123) +-418 + j*(120) +165 + j*(74) +209 + j*(27) +143 + j*(-276) +12 + j*(-70) +33 + j*(-74) +-44 + j*(-145) +1 + j*(-385) +7 + j*(45) +460 + j*(-204) +53 + j*(266) +-216 + j*(-86) +28 + j*(92) +118 + j*(61) +168 + j*(-52) +110 + j*(198) +121 + j*(-107) +98 + j*(75) +-211 + j*(338) +16 + j*(-6) +-261 + j*(346) +101 + j*(-113) +-151 + j*(104) +-111 + j*(-175) +38 + j*(172) +83 + j*(-206) +173 + j*(199) +-34 + j*(66) +-12 + j*(-31) +40 + j*(47) +30 + j*(336) +276 + j*(16) +238 + j*(76) +439 + j*(259) +120 + j*(-16) +125 + j*(37) +139 + j*(104) +-79 + j*(-187) +-431 + j*(219) +-304 + j*(-148) +-4 + j*(-105) +-141 + j*(-92) +194 + j*(-172) +-30 + j*(-248) +-45 + j*(157) +-4 + j*(109) +170 + j*(193) +153 + j*(-243) +-304 + j*(-82) +92 + j*(64) +76 + j*(16) +68 + j*(46) +-146 + j*(144) +219 + j*(222) +-216 + j*(68) +-88 + j*(-248) +-170 + j*(42) +79 + j*(-355) +43 + j*(67) +69 + j*(33) +-137 + j*(-228) +72 + j*(132) +-40 + j*(-29) +-1 + j*(107) +-73 + j*(333) +285 + j*(-302) +252 + j*(-49) +74 + j*(-91) +-83 + j*(156) +-304 + j*(321) +100 + j*(-276) +-182 + j*(-174) +-49 + j*(-325) +78 + j*(-262) +-262 + j*(-26) +134 + j*(83) +-112 + j*(83) +7 + j*(65) +-11 + j*(110) +115 + j*(47) +-45 + j*(-115) +1 + j*(-168) +-112 + j*(-49) +-293 + j*(28) +-351 + j*(-62) +-10 + j*(27) +226 + j*(-30) +-57 + j*(176) +37 + j*(-181) +172 + j*(143) +187 + j*(248) +-205 + j*(1) +187 + j*(-23) +-280 + j*(-25) +200 + j*(-519) +-30 + j*(218) +-90 + j*(220) +-58 + j*(22) +110 + j*(-327) +-165 + j*(30) +-2 + j*(-261) +222 + j*(-47) +-115 + j*(-274) +284 + j*(65) +166 + j*(339) +-2 + j*(192) +-54 + j*(-168) +139 + j*(-147) +202 + j*(-148) +-88 + j*(-42) +-88 + j*(87) +-16 + j*(-157) +-116 + j*(-215) +254 + j*(57) +-135 + j*(-27) +82 + j*(223) +-165 + j*(206) +29 + j*(-119) +-112 + j*(-28) +241 + j*(330) +-164 + j*(-91) +-162 + j*(-92) +39 + j*(57) +-105 + j*(240) +-96 + j*(-112) +266 + j*(274) +272 + j*(-71) +-81 + j*(79) +100 + j*(-11) +-52 + j*(-24) +325 + j*(-252) +-24 + j*(363) +170 + j*(-103) +-224 + j*(263) +229 + j*(123) +62 + j*(-281) +-139 + j*(-92) +-103 + j*(124) +387 + j*(-151) +103 + j*(252) +-52 + j*(-88) +150 + j*(-183) +-508 + j*(47) +16 + j*(-13) +40 + j*(104) +-18 + j*(-61) +436 + j*(25) +-60 + j*(-131) +165 + j*(101) +220 + j*(191) +-254 + j*(-140) +21 + j*(-212) +-81 + j*(-122) +-252 + j*(-175) +11 + j*(124) +-47 + j*(38) +163 + j*(227) +-525 + j*(30) +117 + j*(453) +-137 + j*(-71) +136 + j*(34) +127 + j*(26) +-360 + j*(-185) +247 + j*(-28) +-350 + j*(317) +-262 + j*(151) +58 + j*(-221) +-10 + j*(156) +-387 + j*(64) +-25 + j*(223) +-42 + j*(110) +33 + j*(378) +35 + j*(90) +-264 + j*(78) +-112 + j*(109) +123 + j*(68) +276 + j*(-239) +-11 + j*(-231) +416 + j*(23) +276 + j*(196) +-52 + j*(-30) +-125 + j*(6) +297 + j*(47) +186 + j*(-114) +75 + j*(-99) +379 + j*(1) +-25 + j*(330) +-81 + j*(-228) +-118 + j*(-213) +-45 + j*(-100) +-372 + j*(84) +-93 + j*(-155) +-169 + j*(-9) +245 + j*(-222) +-134 + j*(-5) +-188 + j*(303) +-162 + j*(-185) +132 + j*(-141) +-325 + j*(301) +-42 + j*(-164) +256 + j*(151) +52 + j*(69) +-128 + j*(325) +-165 + j*(134) +-162 + j*(-32) +-117 + j*(-190) +17 + j*(-82) +173 + j*(-173) +298 + j*(-11) +-151 + j*(141) +-327 + j*(147) +-62 + j*(72) +-21 + j*(-19) +-10 + j*(-189) +-36 + j*(50) +95 + j*(-60) +122 + j*(141) +125 + j*(23) +18 + j*(218) +-36 + j*(288) +-127 + j*(81) +21 + j*(-100) +-216 + j*(-237) +85 + j*(-117) +4 + j*(-219) +260 + j*(-119) +154 + j*(132) +-110 + j*(312) +-231 + j*(91) +269 + j*(65) +-62 + j*(-256) +-133 + j*(-183) +84 + j*(-89) +143 + j*(-9) +-245 + j*(11) +-196 + j*(-218) +85 + j*(-211) +-146 + j*(91) +-179 + j*(-57) +-122 + j*(-66) +-112 + j*(45) +-354 + j*(-65) +101 + j*(-99) +362 + j*(243) +-141 + j*(-321) +210 + j*(114) +127 + j*(223) +257 + j*(-35) +-298 + j*(63) +-88 + j*(397) +-272 + j*(72) +44 + j*(387) +-170 + j*(-21) +60 + j*(104) +-310 + j*(-85) +-327 + j*(213) +326 + j*(-179) +-96 + j*(-5) +15 + j*(-286) +-76 + j*(27) +103 + j*(124) +5 + j*(-456) +-133 + j*(-173) +-7 + j*(-293) +-62 + j*(-57) +93 + j*(-42) +282 + j*(-146) +133 + j*(252) +-98 + j*(63) +14 + j*(138) +-192 + j*(108) +100 + j*(216) +-214 + j*(-267) +287 + j*(-177) +138 + j*(-223) +-74 + j*(92) +210 + j*(134) +-143 + j*(40) +119 + j*(-45) +115 + j*(30) +344 + j*(-255) +175 + j*(116) +-238 + j*(98) +-122 + j*(-103) +-223 + j*(378) +213 + j*(103) +23 + j*(163) +-150 + j*(130) +116 + j*(257) +-257 + j*(-51) +-151 + j*(-144) +98 + j*(-243) +-285 + j*(-140) +171 + j*(347) +66 + j*(-49) +294 + j*(-273) +-100 + j*(-174) +-237 + j*(-134) +-459 + j*(320) +-73 + j*(2) +162 + j*(180) +64 + j*(-307) +263 + j*(-46) +-95 + j*(-274) +-50 + j*(103) +191 + j*(170) +-107 + j*(60) +42 + j*(-159) +-35 + j*(-46) +-72 + j*(91) +341 + j*(-216) +112 + j*(249) +-114 + j*(-213) +11 + j*(71) +-42 + j*(-106) +-70 + j*(-117) +-204 + j*(-8) +-30 + j*(59) +-257 + j*(263) +190 + j*(-417) +-6 + j*(152) +-127 + j*(97) +-64 + j*(99) +-428 + j*(144) +-178 + j*(-112) +539 + j*(-2) +338 + j*(-120) +108 + j*(-235) +-324 + j*(-28) +16 + j*(160) +70 + j*(188) +11 + j*(73) +-49 + j*(-291) +206 + j*(197) +237 + j*(136) +83 + j*(216) +54 + j*(-149) +-28 + j*(-105) +-37 + j*(-55) +132 + j*(-138) +138 + j*(-161) +55 + j*(-45) +-99 + j*(168) +173 + j*(175) +7 + j*(49) +-8 + j*(55) +93 + j*(248) +16 + j*(-199) +-104 + j*(324) +-163 + j*(122) +66 + j*(112) +134 + j*(-49) +25 + j*(-253) +-76 + j*(-95) +42 + j*(245) +151 + j*(-187) +-153 + j*(-282) +39 + j*(-135) +4 + j*(-163) +75 + j*(190) +-126 + j*(-10) +171 + j*(55) +-3 + j*(-19) +-59 + j*(76) +-189 + j*(-52) +125 + j*(-81) +254 + j*(-258) +25 + j*(-116) +-359 + j*(333) +-127 + j*(110) +-243 + j*(156) +184 + j*(33) +-265 + j*(5) +-120 + j*(4) +-265 + j*(-8) +168 + j*(-161) +65 + j*(125) +-62 + j*(-164) +-208 + j*(-21) +-142 + j*(-322) +-378 + j*(19) +-73 + j*(76) +-61 + j*(151) +-141 + j*(-202) +132 + j*(133) +228 + j*(-25) +458 + j*(-65) +-133 + j*(-45) +-233 + j*(85) +126 + j*(-35) +81 + j*(-158) +239 + j*(64) +169 + j*(179) +23 + j*(318) +-153 + j*(-144) +92 + j*(-21) +3 + j*(197) +31 + j*(52) +74 + j*(-50) +117 + j*(-38) +-108 + j*(-49) +129 + j*(-19) +-218 + j*(-81) +123 + j*(-25) +326 + j*(-124) +-146 + j*(-104) +-19 + j*(-156) +-30 + j*(-185) +52 + j*(86) +-529 + j*(6) +194 + j*(-97) +109 + j*(278) +-315 + j*(-296) +241 + j*(168) +107 + j*(228) +-103 + j*(219) +79 + j*(238) +91 + j*(-158) +343 + j*(-144) +-165 + j*(-165) +-375 + j*(49) +257 + j*(-81) +223 + j*(160) +-144 + j*(-144) +-11 + j*(252) +70 + j*(-40) +40 + j*(79) +400 + j*(191) +8 + j*(-76) +-98 + j*(-105) +8 + j*(33) +-69 + j*(-42) +270 + j*(-35) +23 + j*(22) +-418 + j*(-221) +-38 + j*(-53) +28 + j*(64) +114 + j*(291) +421 + j*(272) +-222 + j*(250) +-34 + j*(83) +119 + j*(-148) +-141 + j*(136) +-165 + j*(40) +110 + j*(-94) +-341 + j*(105) +-62 + j*(25) +-187 + j*(107) +-132 + j*(221) +-17 + j*(1) +279 + j*(-247) +81 + j*(148) +46 + j*(116) +-448 + j*(-277) +-310 + j*(431) +30 + j*(28) +136 + j*(-87) +8 + j*(24) +257 + j*(-246) +-8 + j*(165) +-49 + j*(-32) +-11 + j*(-11) +34 + j*(-10) +-53 + j*(21) +361 + j*(103) +-284 + j*(-36) +-202 + j*(-190) +62 + j*(88) +-69 + j*(190) +-66 + j*(-338) +54 + j*(31) +-71 + j*(105) +-177 + j*(-55) +235 + j*(-53) +28 + j*(104) +-363 + j*(80) +144 + j*(2) +250 + j*(192) +-60 + j*(1) +-206 + j*(-163) +54 + j*(-66) +-91 + j*(-169) +-78 + j*(-36) +91 + j*(-15) +-30 + j*(107) +85 + j*(14) +-285 + j*(21) +179 + j*(152) +-197 + j*(-69) +86 + j*(-214) +200 + j*(158) +29 + j*(153) +-181 + j*(-278) +-89 + j*(-222) +-172 + j*(-129) +-30 + j*(272) +365 + j*(-10) +-40 + j*(-85) +-8 + j*(-57) +-241 + j*(-301) +-267 + j*(-530) +38 + j*(-85) +-91 + j*(478) +-18 + j*(-260) +-261 + j*(-103) +41 + j*(69) +376 + j*(74) +59 + j*(342) +-450 + j*(-386) +-185 + j*(-6) +399 + j*(284) +69 + j*(128) +-247 + j*(-365) +88 + j*(-74) +182 + j*(16) +-257 + j*(209) +-336 + j*(26) +-260 + j*(-74) +80 + j*(66) +-257 + j*(-243) +139 + j*(-35) +-354 + j*(33) +21 + j*(-107) +-279 + j*(46) +-124 + j*(192) +-474 + j*(-165) +61 + j*(-238) +-114 + j*(182) +-122 + j*(-105) +-265 + j*(192) +209 + j*(-58) +134 + j*(-87) +-124 + j*(-299) +-112 + j*(196) +132 + j*(38) +-180 + j*(303) +-203 + j*(82) +-62 + j*(-222) +37 + j*(371) +128 + j*(148) +194 + j*(198) +11 + j*(-93) +23 + j*(-392) +-9 + j*(213) +284 + j*(-231) +108 + j*(-115) +-86 + j*(-54) +-78 + j*(25) +-66 + j*(-118) +139 + j*(-135) +95 + j*(-66) +-155 + j*(-134) +-136 + j*(13) +37 + j*(147) +105 + j*(-52) +124 + j*(180) +93 + j*(129) +85 + j*(233) +139 + j*(-129) +363 + j*(93) +110 + j*(181) +321 + j*(-131) +-116 + j*(-50) +292 + j*(52) +130 + j*(-219) +-76 + j*(155) +170 + j*(8) +-60 + j*(36) +105 + j*(58) +368 + j*(125) +-136 + j*(-108) +-142 + j*(69) +21 + j*(-49) +10 + j*(-94) +-196 + j*(-4) +488 + j*(313) +86 + j*(-116) +167 + j*(34) +-52 + j*(267) +-132 + j*(273) +-107 + j*(-311) +12 + j*(-185) +148 + j*(-227) +-175 + j*(-88) +68 + j*(40) +44 + j*(-27) +158 + j*(-191) +-6 + j*(122) +315 + j*(-21) +-213 + j*(59) +421 + j*(-175) +-81 + j*(275) +-93 + j*(80) +-29 + j*(-130) +-58 + j*(153) +-246 + j*(-158) +71 + j*(-250) +-354 + j*(120) +37 + j*(195) +460 + j*(-35) +-176 + j*(-60) +109 + j*(30) +-274 + j*(46) +163 + j*(-293) +339 + j*(124) +-288 + j*(103) +256 + j*(-101) +-62 + j*(173) +-130 + j*(288) +137 + j*(-49) +169 + j*(-1) +-69 + j*(-170) +-231 + j*(207) +165 + j*(62) +-147 + j*(102) +-28 + j*(158) +-18 + j*(-250) +58 + j*(-124) +-211 + j*(-76) +-277 + j*(-126) +-288 + j*(281) +-47 + j*(91) +57 + j*(-258) +158 + j*(31) +173 + j*(-93) +64 + j*(-301) +-178 + j*(88) +-129 + j*(518) +144 + j*(-270) +146 + j*(-278) +239 + j*(122) +274 + j*(8) +77 + j*(-119) +-47 + j*(-154) +-2 + j*(219) +-204 + j*(267) +118 + j*(166) +42 + j*(-456) +-47 + j*(29) +-187 + j*(180) +-112 + j*(230) +95 + j*(-22) +120 + j*(381) +244 + j*(-168) +-9 + j*(103) +143 + j*(97) +-337 + j*(1) +228 + j*(18) +-43 + j*(92) +-42 + j*(6) +-16 + j*(483) +35 + j*(257) +100 + j*(-82) +245 + j*(144) +136 + j*(-35) +167 + j*(31) +-45 + j*(129) +-165 + j*(130) +431 + j*(227) +-163 + j*(-289) +157 + j*(-82) +371 + j*(-184) +8 + j*(117) +-247 + j*(-31) +57 + j*(120) +-107 + j*(-310) +-71 + j*(-28) +-234 + j*(-110) +-88 + j*(80) +-275 + j*(75) +-202 + j*(311) +-124 + j*(-170) +1 + j*(-284) +-44 + j*(-331) +-148 + j*(-53) +-11 + j*(8) +156 + j*(255) +302 + j*(170) +-139 + j*(47) +50 + j*(146) +-132 + j*(234) +-40 + j*(0) +31 + j*(-148) +-151 + j*(64) +202 + j*(-64) +207 + j*(42) +-194 + j*(48) +100 + j*(-102) +97 + j*(123) +262 + j*(82) +-321 + j*(-168) +-282 + j*(19) +-35 + j*(201) +257 + j*(114) +-47 + j*(-174) +-59 + j*(-81) +1 + j*(-50) +-180 + j*(-216) +-141 + j*(-33) +-106 + j*(167) +14 + j*(62) +151 + j*(104) +-206 + j*(-145) +132 + j*(-35) +-2 + j*(94) +107 + j*(101) +65 + j*(93) +30 + j*(-250) +175 + j*(159) +16 + j*(202) +-87 + j*(-223) +7 + j*(-244) +58 + j*(-51) +103 + j*(-135) +-168 + j*(-313) +-325 + j*(132) +-136 + j*(-111) +-211 + j*(-162) +35 + j*(-76) +354 + j*(196) +132 + j*(-28) +-12 + j*(-352) +140 + j*(-337) +-144 + j*(-102) +-115 + j*(-63) +-36 + j*(65) +-98 + j*(-89) +-119 + j*(53) +91 + j*(-206) +51 + j*(-476) +160 + j*(-76) +-222 + j*(-345) +-265 + j*(202) +86 + j*(-40) +142 + j*(170) +115 + j*(237) +187 + j*(-6) +-32 + j*(-87) +-379 + j*(175) +-46 + j*(-578) +-116 + j*(-57) +30 + j*(19) +-80 + j*(115) +13 + j*(100) +-116 + j*(121) +30 + j*(237) +-226 + j*(165) +-220 + j*(-202) +70 + j*(-153) +-282 + j*(-106) +-322 + j*(-4) +-46 + j*(7) +176 + j*(41) +195 + j*(132) +-103 + j*(23) +-114 + j*(-115) +153 + j*(317) +-57 + j*(60) +-160 + j*(-151) +-236 + j*(167) +203 + j*(-55) +-18 + j*(7) +-244 + j*(-16) +250 + j*(159) +3 + j*(-170) +-54 + j*(33) +-42 + j*(-67) +334 + j*(149) +-354 + j*(85) +-4 + j*(-64) +-63 + j*(92) +223 + j*(-244) +4 + j*(-47) +125 + j*(-204) +107 + j*(70) +191 + j*(-337) +-331 + j*(185) +-441 + j*(74) +-96 + j*(178) +-70 + j*(83) +152 + j*(100) +-117 + j*(371) +184 + j*(-202) +-223 + j*(200) +-42 + j*(-50) +18 + j*(126) +20 + j*(-46) +-298 + j*(203) +46 + j*(146) +-153 + j*(-19) +268 + j*(-62) +103 + j*(-322) +157 + j*(694) +-23 + j*(105) +-129 + j*(183) +-28 + j*(132) +21 + j*(37) +30 + j*(173) +-101 + j*(121) +-100 + j*(189) +-272 + j*(-186) +211 + j*(-85) +-222 + j*(-71) +-218 + j*(-44) +-98 + j*(38) +88 + j*(113) +249 + j*(-197) +86 + j*(346) +-49 + j*(-60) +235 + j*(230) +62 + j*(-8) +-169 + j*(-186) +304 + j*(-342) +119 + j*(65) +34 + j*(-357) +125 + j*(-96) +-258 + j*(103) +71 + j*(-79) +-179 + j*(193) +-139 + j*(-187) +-236 + j*(-131) +408 + j*(340) +139 + j*(-67) +-29 + j*(21) +-59 + j*(99) +-19 + j*(-37) +377 + j*(107) +-272 + j*(164) +81 + j*(-98) +-44 + j*(-69) +-203 + j*(-243) +-63 + j*(116) +-82 + j*(13) +-4 + j*(-42) +83 + j*(-158) +-216 + j*(-180) +-112 + j*(112) +-232 + j*(-168) +146 + j*(169) +-199 + j*(55) +74 + j*(-52) +-69 + j*(-372) +-64 + j*(-177) +-92 + j*(-14) +1 + j*(-285) +-81 + j*(-277) +57 + j*(-180) +-185 + j*(-419) +-235 + j*(-25) +-298 + j*(117) +-20 + j*(82) +110 + j*(231) +20 + j*(-115) +223 + j*(71) +-54 + j*(18) +-82 + j*(-61) +-54 + j*(88) +112 + j*(-132) +-216 + j*(-183) +144 + j*(135) +-95 + j*(361) +126 + j*(194) +4 + j*(-424) +185 + j*(91) +-4 + j*(-30) +-112 + j*(-177) +-479 + j*(195) +-301 + j*(-36) +-324 + j*(74) +66 + j*(20) +-174 + j*(-128) +57 + j*(-160) +1 + j*(-95) +121 + j*(-1) +78 + j*(-13) +8 + j*(-64) +-83 + j*(46) +-59 + j*(-35) +7 + j*(23) +-100 + j*(168) +-151 + j*(-72) +-171 + j*(-166) +124 + j*(396) +-94 + j*(-126) +136 + j*(-111) +-80 + j*(-441) +136 + j*(268) +358 + j*(69) +11 + j*(-5) +-298 + j*(-37) +-37 + j*(144) +-185 + j*(4) +-16 + j*(282) +-12 + j*(-115) +-4 + j*(-86) +29 + j*(-469) +-443 + j*(-96) +-258 + j*(7) +115 + j*(-133) +-213 + j*(-262) +279 + j*(-81) +129 + j*(-107) +-167 + j*(38) +-91 + j*(-312) +-202 + j*(335) +262 + j*(37) +1 + j*(-13) +135 + j*(319) +127 + j*(297) +130 + j*(115) +-280 + j*(151) +-213 + j*(-125) +-90 + j*(23) +110 + j*(192) +-148 + j*(-175) +-91 + j*(-89) +428 + j*(-33) +122 + j*(-108) +206 + j*(-93) +-56 + j*(-170) +330 + j*(-283) +243 + j*(18) +257 + j*(-235) +95 + j*(-140) +-50 + j*(-323) +-146 + j*(214) +167 + j*(229) +-22 + j*(23) +72 + j*(-136) +265 + j*(-286) +-305 + j*(-121) +6 + j*(165) +124 + j*(-304) +184 + j*(78) +360 + j*(8) +-103 + j*(-96) +99 + j*(-48) +-266 + j*(145) +206 + j*(-59) +313 + j*(58) +-79 + j*(-182) +109 + j*(91) +-360 + j*(-320) +153 + j*(227) +-165 + j*(87) +34 + j*(-18) +3 + j*(229) +1 + j*(49) +245 + j*(140) +-162 + j*(89) +-110 + j*(-125) +-93 + j*(202) +109 + j*(-93) +90 + j*(-56) +358 + j*(151) +286 + j*(-158) +182 + j*(-62) +-204 + j*(49) +20 + j*(279) +-105 + j*(-283) +-83 + j*(43) +-13 + j*(-51) +-68 + j*(176) +-152 + j*(-12) +-129 + j*(231) +9 + j*(143) +102 + j*(-153) +-134 + j*(-113) +34 + j*(174) +-151 + j*(180) +-45 + j*(-171) +206 + j*(-89) +154 + j*(144) +-146 + j*(-276) +216 + j*(57) +495 + j*(30) +-177 + j*(25) +97 + j*(240) +-84 + j*(-176) +-194 + j*(-102) +33 + j*(-204) +181 + j*(-70) +-52 + j*(280) +47 + j*(64) +-77 + j*(67) +408 + j*(27) +171 + j*(74) +-318 + j*(177) +98 + j*(136) +-166 + j*(124) +21 + j*(223) +-105 + j*(143) +-185 + j*(162) +11 + j*(6) +218 + j*(118) +-149 + j*(190) +42 + j*(121) +-117 + j*(100) +-86 + j*(32) +13 + j*(-127) +13 + j*(-260) +102 + j*(49) +173 + j*(210) +110 + j*(-64) +-13 + j*(329) +145 + j*(-61) +44 + j*(-65) +-110 + j*(-280) +226 + j*(-64) +207 + j*(205) +-9 + j*(-98) +-291 + j*(-194) +59 + j*(129) +-104 + j*(-78) +13 + j*(-115) +2 + j*(-84) +47 + j*(-117) +-182 + j*(-156) +371 + j*(66) +-185 + j*(249) +-360 + j*(-141) +74 + j*(-243) +150 + j*(412) +293 + j*(13) +161 + j*(-319) +-52 + j*(250) +-81 + j*(-110) +35 + j*(25) +62 + j*(146) +-134 + j*(-8) +-101 + j*(64) +-213 + j*(206) +49 + j*(27) +-9 + j*(44) +-30 + j*(57) +-185 + j*(-103) +-175 + j*(-29) +-315 + j*(127) +294 + j*(-68) +-98 + j*(390) +76 + j*(-11) +216 + j*(272) +-136 + j*(5) +44 + j*(210) +-3 + j*(-24) +182 + j*(-110) +-61 + j*(40) +-28 + j*(52) +-95 + j*(-206) +-57 + j*(230) +182 + j*(-40) +128 + j*(-143) +102 + j*(-54) +-83 + j*(28) +-37 + j*(-208) +-220 + j*(183) +158 + j*(-382) +88 + j*(-19) +-25 + j*(-37) +75 + j*(60) +-63 + j*(-173) +-230 + j*(-128) +112 + j*(-43) +-158 + j*(-47) +20 + j*(49) +-145 + j*(71) +-297 + j*(68) +-329 + j*(-21) +245 + j*(-95) +-303 + j*(88) +-72 + j*(151) +-126 + j*(-173) +11 + j*(199) +127 + j*(423) +213 + j*(-18) +230 + j*(17) +-110 + j*(-47) +347 + j*(166) +165 + j*(46) +-402 + j*(100) +-34 + j*(-164) +18 + j*(187) +-27 + j*(102) +100 + j*(324) +-43 + j*(-269) +118 + j*(-268) +-69 + j*(187) +192 + j*(-211) +99 + j*(-127) +262 + j*(42) +-93 + j*(-35) +-245 + j*(-249) +-39 + j*(-274) +115 + j*(-197) +179 + j*(8) +395 + j*(33) +324 + j*(-6) +-129 + j*(105) +72 + j*(-66) +-239 + j*(-16) +-112 + j*(189) +-334 + j*(-83) +91 + j*(235) +-139 + j*(91) +-136 + j*(122) +47 + j*(-132) +453 + j*(-16) +-150 + j*(-126) +-255 + j*(86) +146 + j*(-169) +-31 + j*(158) +98 + j*(132) +-260 + j*(86) +-20 + j*(145) +77 + j*(-175) +-227 + j*(271) +-25 + j*(115) +76 + j*(267) +-192 + j*(66) +-274 + j*(-34) +-163 + j*(-132) +-155 + j*(-195) +91 + j*(46) +-137 + j*(-191) +-151 + j*(260) +-8 + j*(29) +-83 + j*(25) +17 + j*(-16) +-430 + j*(494) +212 + j*(55) +134 + j*(86) +188 + j*(-2) +-11 + j*(151) +209 + j*(27) +-37 + j*(40) +-202 + j*(90) +-25 + j*(327) +81 + j*(-401) +-180 + j*(194) +-146 + j*(262) +221 + j*(87) +280 + j*(-118) +-30 + j*(15) +164 + j*(91) +45 + j*(-315) +-325 + j*(43) +-283 + j*(-286) +-63 + j*(-174) +-220 + j*(-100) +190 + j*(-108) +37 + j*(-11) +148 + j*(-88) +-103 + j*(-93) +122 + j*(94) +-124 + j*(-273) +-59 + j*(-193) +13 + j*(77) +3 + j*(-186) +36 + j*(-62) +-219 + j*(232) +103 + j*(71) +54 + j*(47) +13 + j*(52) +-356 + j*(119) +-124 + j*(152) +77 + j*(33) +-83 + j*(148) +-40 + j*(-25) +35 + j*(-64) +-170 + j*(-244) +-301 + j*(-208) +-61 + j*(140) +-197 + j*(-47) +-134 + j*(-243) +34 + j*(269) +-169 + j*(-330) +65 + j*(46) +167 + j*(47) +-118 + j*(-40) +65 + j*(-15) +-16 + j*(211) +-63 + j*(107) +50 + j*(120) +-194 + j*(9) +-97 + j*(90) +-226 + j*(-82) +59 + j*(-375) +123 + j*(-107) +112 + j*(63) +-95 + j*(146) +-209 + j*(91) +278 + j*(-85) +190 + j*(134) +296 + j*(-10) +-175 + j*(-175) +136 + j*(-52) +166 + j*(-25) +129 + j*(107) +-254 + j*(-54) +132 + j*(6) +137 + j*(95) +-457 + j*(-166) +-146 + j*(34) +-46 + j*(-144) +32 + j*(291) +143 + j*(168) +108 + j*(14) +25 + j*(-109) +-262 + j*(148) +-111 + j*(-62) +170 + j*(-84) +-148 + j*(217) +-279 + j*(-161) +-50 + j*(-172) +261 + j*(-89) +-186 + j*(31) +-35 + j*(201) +-392 + j*(-57) +-43 + j*(291) +-125 + j*(65) +157 + j*(-12) +-43 + j*(40) +173 + j*(-97) +231 + j*(-39) +40 + j*(-25) +-184 + j*(-57) +31 + j*(-173) +-262 + j*(74) +6 + j*(214) +37 + j*(-114) +-296 + j*(-238) +115 + j*(-8) +17 + j*(-50) +-165 + j*(134) +-115 + j*(127) +-419 + j*(-182) +-29 + j*(-102) +49 + j*(348) +-173 + j*(-4) +-431 + j*(31) +-60 + j*(21) +-130 + j*(-76) +-278 + j*(-74) +-156 + j*(-45) +383 + j*(187) +241 + j*(-255) +105 + j*(-116) +-6 + j*(-184) +327 + j*(-173) +-32 + j*(39) +23 + j*(78) +35 + j*(0) +116 + j*(-264) +-10 + j*(-5) +-44 + j*(110) +-103 + j*(-112) +-506 + j*(227) +144 + j*(-71) +150 + j*(43) +45 + j*(344) +-286 + j*(-126) +24 + j*(-301) +-136 + j*(-288) +23 + j*(-66) +-247 + j*(-122) +2 + j*(-254) +-434 + j*(-101) +-262 + j*(86) +-265 + j*(-110) +-293 + j*(115) +-11 + j*(361) +249 + j*(-121) +-88 + j*(35) +-232 + j*(-86) +296 + j*(8) +-125 + j*(4) +-14 + j*(-228) +-212 + j*(259) +30 + j*(207) +165 + j*(-69) +454 + j*(0) +-282 + j*(71) +41 + j*(-194) +264 + j*(-13) +-313 + j*(129) +82 + j*(106) +76 + j*(-2) +245 + j*(-102) +-92 + j*(245) +242 + j*(-47) +-132 + j*(-83) +231 + j*(-56) +-64 + j*(-59) +-94 + j*(-115) +241 + j*(154) +-261 + j*(-173) +-56 + j*(157) +-54 + j*(-21) +-180 + j*(28) +144 + j*(104) +64 + j*(23) +-93 + j*(-354) +189 + j*(185) +-110 + j*(-22) +209 + j*(-222) +79 + j*(-39) +217 + j*(-105) +-21 + j*(-139) +91 + j*(205) +195 + j*(-93) +-6 + j*(-144) +-231 + j*(117) +-18 + j*(-35) +87 + j*(190) +152 + j*(56) +248 + j*(66) +-3 + j*(-235) +-81 + j*(132) +-59 + j*(315) +-289 + j*(142) +100 + j*(-118) +-191 + j*(355) +52 + j*(-271) +1 + j*(-161) +-151 + j*(-81) +198 + j*(357) +-202 + j*(-13) +19 + j*(-220) +188 + j*(-258) +90 + j*(105) +-168 + j*(25) +37 + j*(-505) +281 + j*(-93) +-241 + j*(-156) +49 + j*(-28) +16 + j*(-299) +151 + j*(-229) +-42 + j*(136) +-228 + j*(43) +-124 + j*(148) +-7 + j*(19) +250 + j*(-66) +207 + j*(118) +80 + j*(28) +-22 + j*(61) +190 + j*(-61) +206 + j*(-161) +27 + j*(-344) +-176 + j*(-18) +233 + j*(-76) +64 + j*(-87) +334 + j*(-81) +216 + j*(-3) +1 + j*(499) +57 + j*(-66) +-123 + j*(-246) +-329 + j*(-81) +-113 + j*(-94) +41 + j*(204) +-194 + j*(-10) +-52 + j*(116) +-80 + j*(33) +-271 + j*(-388) +-288 + j*(-45) +-65 + j*(-40) +118 + j*(-59) +296 + j*(-220) +-175 + j*(57) +4 + j*(71) +-124 + j*(62) +153 + j*(95) +209 + j*(209) +132 + j*(293) +-72 + j*(-90) +378 + j*(3) +57 + j*(266) +-354 + j*(42) +84 + j*(-270) +-52 + j*(303) +211 + j*(-53) +132 + j*(-156) +375 + j*(37) +-21 + j*(87) +381 + j*(-107) +86 + j*(-33) +98 + j*(21) +-189 + j*(-212) +-138 + j*(-247) +330 + j*(-127) +34 + j*(-63) +181 + j*(139) +-86 + j*(144) +206 + j*(-378) +165 + j*(29) +-133 + j*(183) +52 + j*(-56) +-140 + j*(123) +-123 + j*(68) +-13 + j*(243) +-144 + j*(-129) +-265 + j*(-195) +148 + j*(139) +117 + j*(-42) +-105 + j*(-67) +-64 + j*(-123) +20 + j*(-232) +-250 + j*(85) +-117 + j*(-41) +-474 + j*(269) +76 + j*(-93) +23 + j*(-175) +-138 + j*(191) +13 + j*(-97) +15 + j*(395) +71 + j*(56) +-91 + j*(74) +-180 + j*(134) +-23 + j*(90) +110 + j*(313) +-309 + j*(-167) +13 + j*(44) +146 + j*(276) +105 + j*(-266) +-9 + j*(-158) +69 + j*(-4) +-45 + j*(-214) +148 + j*(69) +95 + j*(98) +322 + j*(-187) +-102 + j*(-109) +-287 + j*(66) +-108 + j*(-247) +62 + j*(112) +86 + j*(-119) +75 + j*(65) +-5 + j*(192) +-112 + j*(0) +301 + j*(-56) +-206 + j*(83) +-30 + j*(192) +-293 + j*(-1) +167 + j*(98) +144 + j*(-275) +76 + j*(80) +-81 + j*(314) +-132 + j*(-187) +-124 + j*(-295) +-412 + j*(339) +49 + j*(-5) +-10 + j*(-172) +-36 + j*(-47) +-112 + j*(-105) +171 + j*(441) +-104 + j*(-93) +128 + j*(211) +-76 + j*(-84) +84 + j*(350) +47 + j*(-100) +-137 + j*(-182) +-22 + j*(-212) +8 + j*(100) +-58 + j*(252) +55 + j*(40) +-95 + j*(127) +252 + j*(-148) +-147 + j*(-35) +202 + j*(-465) +127 + j*(-109) +-136 + j*(-75) +122 + j*(67) +34 + j*(-97) +-622 + j*(-2) +240 + j*(49) +230 + j*(95) +-16 + j*(33) +129 + j*(178) +-92 + j*(131) +-146 + j*(-288) +-11 + j*(-154) +243 + j*(-119) +-293 + j*(-419) +12 + j*(146) +11 + j*(258) +-267 + j*(-30) +378 + j*(180) +-145 + j*(-53) +-152 + j*(-247) +-127 + j*(-30) +244 + j*(-144) +-57 + j*(107) +324 + j*(203) +158 + j*(-66) +308 + j*(-268) +119 + j*(-105) +-98 + j*(127) +-189 + j*(-178) +-35 + j*(-40) +142 + j*(378) +-226 + j*(-28) +273 + j*(-14) +65 + j*(-8) +-95 + j*(-134) +-35 + j*(83) +49 + j*(157) +-52 + j*(-219) +14 + j*(280) +-33 + j*(-86) +86 + j*(-61) +-508 + j*(-100) +161 + j*(-415) +-86 + j*(-105) +65 + j*(-98) +233 + j*(69) +-90 + j*(115) +47 + j*(171) +-141 + j*(-136) +70 + j*(-102) +-40 + j*(-204) +-239 + j*(-93) +192 + j*(155) +-231 + j*(32) +-45 + j*(-419) +20 + j*(-41) +7 + j*(42) +258 + j*(-222) +98 + j*(-2) +-13 + j*(62) +-309 + j*(-131) +158 + j*(96) +-309 + j*(-138) +-322 + j*(-272) +168 + j*(-258) +-395 + j*(131) +187 + j*(-576) +-81 + j*(-438) +-147 + j*(-62) +-220 + j*(-71) +-203 + j*(-38) +184 + j*(113) +0 + j*(-317) +167 + j*(-6) +-226 + j*(78) +-146 + j*(-158) +-223 + j*(21) +-170 + j*(70) +21 + j*(-109) +-54 + j*(103) +407 + j*(-218) +-4 + j*(-20) +207 + j*(-315) +-80 + j*(-86) +180 + j*(-165) +-144 + j*(289) +146 + j*(262) +38 + j*(-47) +352 + j*(281) +290 + j*(-41) +-28 + j*(-112) +38 + j*(323) +-56 + j*(-105) +-68 + j*(74) +249 + j*(117) +13 + j*(223) +-66 + j*(356) +-146 + j*(-142) +-55 + j*(216) +181 + j*(215) +252 + j*(74) +143 + j*(-118) +93 + j*(125) +29 + j*(22) +-83 + j*(-94) +66 + j*(21) +-62 + j*(146) +264 + j*(-65) +-211 + j*(389) +-119 + j*(245) +24 + j*(-66) +71 + j*(22) +-1 + j*(-225) +80 + j*(-397) +-206 + j*(-12) +-6 + j*(158) +87 + j*(251) +-8 + j*(139) +-56 + j*(126) +-327 + j*(45) +37 + j*(-74) +-45 + j*(381) +94 + j*(-11) +-6 + j*(46) +-115 + j*(-161) +171 + j*(-400) +-3 + j*(44) +-228 + j*(208) +-20 + j*(-47) +-117 + j*(-197) +-104 + j*(89) +102 + j*(-254) +76 + j*(-246) +-368 + j*(-77) +49 + j*(107) +47 + j*(53) +87 + j*(-298) +199 + j*(-163) +116 + j*(-85) +25 + j*(-167) +-1 + j*(74) +-2 + j*(-13) +54 + j*(-91) +76 + j*(-262) +72 + j*(-146) +-135 + j*(-182) +6 + j*(-18) +-217 + j*(178) +-46 + j*(69) +-9 + j*(-42) +-65 + j*(-80) +-28 + j*(-10) +-97 + j*(-62) +158 + j*(-168) +106 + j*(2) +-184 + j*(-18) +-233 + j*(16) +158 + j*(294) +-172 + j*(-383) +-199 + j*(-178) +125 + j*(-46) +-41 + j*(17) +-365 + j*(247) +262 + j*(-253) +-105 + j*(72) +-32 + j*(141) +-2 + j*(-19) +143 + j*(-65) +42 + j*(125) +37 + j*(-173) +123 + j*(47) +45 + j*(-98) +-40 + j*(143) +28 + j*(-257) +97 + j*(-254) +170 + j*(-148) +-200 + j*(-47) +-126 + j*(158) +-278 + j*(21) +124 + j*(130) +-147 + j*(-42) +8 + j*(200) +-85 + j*(-76) +237 + j*(37) +-167 + j*(184) +175 + j*(235) +-180 + j*(380) +-506 + j*(-137) +-172 + j*(148) +-28 + j*(23) +18 + j*(-223) +-82 + j*(166) +11 + j*(121) +83 + j*(216) +-210 + j*(-182) +-269 + j*(99) +333 + j*(-19) +-129 + j*(-68) +281 + j*(-123) +-8 + j*(-74) +-146 + j*(36) +91 + j*(-126) +-94 + j*(45) +-42 + j*(-46) +62 + j*(464) +89 + j*(-21) +-281 + j*(67) +101 + j*(-325) +40 + j*(270) +-163 + j*(107) +-337 + j*(-230) +-49 + j*(-117) +94 + j*(200) +-100 + j*(119) +-252 + j*(49) +164 + j*(40) +337 + j*(72) +-47 + j*(-204) +-224 + j*(-218) +-180 + j*(218) +1 + j*(221) +221 + j*(-285) +259 + j*(-113) +-71 + j*(366) +-113 + j*(-133) +59 + j*(-132) +82 + j*(-6) +-69 + j*(21) +-182 + j*(-43) +-27 + j*(-281) +80 + j*(-69) +-54 + j*(-49) +91 + j*(-78) +214 + j*(-64) +-216 + j*(246) +-180 + j*(11) +81 + j*(-48) +-34 + j*(-7) +-8 + j*(57) +-26 + j*(45) +-324 + j*(264) +185 + j*(-170) +-119 + j*(-197) +28 + j*(132) +16 + j*(67) +403 + j*(142) +152 + j*(152) +-22 + j*(388) +44 + j*(0) +42 + j*(11) +35 + j*(-54) +182 + j*(-73) +153 + j*(-13) +159 + j*(-34) +316 + j*(83) +289 + j*(194) +-134 + j*(-163) +87 + j*(117) +95 + j*(-318) +108 + j*(-79) +-322 + j*(431) +-1 + j*(314) +69 + j*(-359) +117 + j*(-21) +-343 + j*(198) +-25 + j*(-99) +-10 + j*(-103) +-76 + j*(182) +-164 + j*(-390) +-95 + j*(40) +-181 + j*(182) +-129 + j*(-161) +-130 + j*(111) +-20 + j*(1) +-223 + j*(49) +-129 + j*(119) +-90 + j*(-31) +163 + j*(-215) +-130 + j*(-217) +111 + j*(30) +40 + j*(63) +-132 + j*(1) +-240 + j*(-94) +301 + j*(-80) +-62 + j*(-7) +85 + j*(-55) +144 + j*(4) +-60 + j*(11) +-43 + j*(-144) +-178 + j*(136) +125 + j*(133) +-44 + j*(124) +41 + j*(190) +75 + j*(223) +-161 + j*(-218) +131 + j*(7) +21 + j*(102) +-467 + j*(-260) +250 + j*(-82) +99 + j*(83) +-223 + j*(349) +-216 + j*(-151) +129 + j*(-349) +243 + j*(-324) +178 + j*(52) +194 + j*(-74) +146 + j*(200) +136 + j*(43) +-378 + j*(-235) +-290 + j*(151) +407 + j*(159) +-139 + j*(-40) +130 + j*(-59) +135 + j*(353) +89 + j*(100) +-30 + j*(-180) +-50 + j*(-217) +76 + j*(-12) +-197 + j*(-5) +-296 + j*(0) +-256 + j*(119) +233 + j*(-107) +16 + j*(-327) +-274 + j*(325) +91 + j*(24) +47 + j*(-30) +211 + j*(-159) +277 + j*(18) +138 + j*(3) +-142 + j*(-59) +212 + j*(-37) +97 + j*(382) +381 + j*(126) +221 + j*(-418) +328 + j*(-99) +-93 + j*(-224) +-30 + j*(-151) +-246 + j*(-29) +230 + j*(13) +97 + j*(242) +8 + j*(-52) +-58 + j*(141) +33 + j*(-67) +-415 + j*(-201) +-23 + j*(-113) +-18 + j*(-187) +245 + j*(-151) +69 + j*(-96) +-143 + j*(117) +179 + j*(47) +87 + j*(-223) +-263 + j*(-198) +-29 + j*(-86) +287 + j*(158) +-59 + j*(113) +184 + j*(95) +264 + j*(42) +-146 + j*(232) +-67 + j*(-57) +19 + j*(-152) +187 + j*(182) +-253 + j*(-218) +134 + j*(207) +91 + j*(-161) +131 + j*(-104) +132 + j*(-75) +95 + j*(427) +-11 + j*(-45) +-13 + j*(-20) +-47 + j*(227) +86 + j*(66) +94 + j*(-35) +-11 + j*(-71) +-160 + j*(56) +36 + j*(255) +276 + j*(-119) +49 + j*(108) +-98 + j*(-81) +-76 + j*(-313) +240 + j*(4) +-160 + j*(21) +8 + j*(-165) +-163 + j*(261) +-270 + j*(-73) +187 + j*(110) +-86 + j*(-165) +214 + j*(134) +-33 + j*(-112) +-421 + j*(278) +19 + j*(46) +53 + j*(228) +-442 + j*(-151) +69 + j*(59) +-86 + j*(55) +50 + j*(-371) +-199 + j*(113) +-13 + j*(172) +168 + j*(52) +384 + j*(291) +-89 + j*(-129) +-343 + j*(-387) +-37 + j*(300) +-37 + j*(-66) +-209 + j*(-116) +112 + j*(2) +87 + j*(-80) +-272 + j*(-38) +-51 + j*(40) +-221 + j*(-138) +-182 + j*(-378) +-461 + j*(-30) +-141 + j*(-149) +269 + j*(-55) +122 + j*(68) +122 + j*(33) +-153 + j*(-116) +-47 + j*(-1) +285 + j*(30) +102 + j*(-137) +50 + j*(-193) +-409 + j*(-35) +-162 + j*(171) +354 + j*(41) +-216 + j*(101) +33 + j*(256) +-114 + j*(203) +-353 + j*(-30) +42 + j*(-177) +-2 + j*(95) +-100 + j*(-156) +-117 + j*(-155) +-144 + j*(-4) +-138 + j*(-194) +33 + j*(-209) +-113 + j*(6) +-361 + j*(190) +153 + j*(-317) +-49 + j*(81) +-70 + j*(-52) +104 + j*(-284) +131 + j*(113) +28 + j*(6) +18 + j*(71) +47 + j*(100) +126 + j*(-6) +-138 + j*(199) +18 + j*(-209) +158 + j*(-37) +237 + j*(-211) +277 + j*(-17) +87 + j*(151) +-173 + j*(-153) +147 + j*(-314) +-79 + j*(247) +128 + j*(-87) +26 + j*(-173) +236 + j*(-258) +-177 + j*(25) +-112 + j*(-148) +-136 + j*(-163) +-16 + j*(-223) +-124 + j*(218) +-49 + j*(-257) +-156 + j*(-51) +-25 + j*(-276) +88 + j*(1) +-191 + j*(-42) +-81 + j*(-92) +138 + j*(419) +2 + j*(88) +-1 + j*(84) +119 + j*(194) +-129 + j*(-187) +-151 + j*(-66) +-141 + j*(11) +107 + j*(-457) +256 + j*(140) +1 + j*(218) +130 + j*(134) +122 + j*(62) +96 + j*(-102) +72 + j*(-88) +59 + j*(-168) +-111 + j*(-354) +189 + j*(-89) +224 + j*(-129) +-127 + j*(88) +1 + j*(357) +139 + j*(163) +147 + j*(244) +100 + j*(94) +269 + j*(6) +13 + j*(-315) +71 + j*(-104) +-110 + j*(30) +18 + j*(-172) +-40 + j*(-19) +-182 + j*(307) +129 + j*(344) +-29 + j*(-144) +-138 + j*(-13) +361 + j*(-96) +-143 + j*(105) +-92 + j*(-118) +16 + j*(52) +-119 + j*(187) +296 + j*(-150) +-188 + j*(-91) +-7 + j*(-250) +83 + j*(-74) +-110 + j*(113) +-170 + j*(331) +-52 + j*(-16) +97 + j*(-301) +-269 + j*(-31) +-89 + j*(69) +84 + j*(-25) +161 + j*(-239) +-80 + j*(156) +148 + j*(-129) +191 + j*(196) +-153 + j*(43) +-117 + j*(-74) +-46 + j*(-340) +-41 + j*(-180) +53 + j*(-113) +182 + j*(195) +208 + j*(221) +6 + j*(14) +144 + j*(73) +-83 + j*(-97) +30 + j*(223) +-98 + j*(-148) +-493 + j*(-247) +-386 + j*(32) +-112 + j*(326) +41 + j*(-60) +155 + j*(-324) +42 + j*(-76) +-39 + j*(-154) +123 + j*(409) +-132 + j*(-122) +209 + j*(-33) +-313 + j*(55) +235 + j*(189) +-382 + j*(339) +87 + j*(-11) +101 + j*(1) +186 + j*(-173) +23 + j*(-135) +427 + j*(74) +280 + j*(-122) +-69 + j*(-35) +247 + j*(-23) +112 + j*(-204) +110 + j*(-6) +-303 + j*(14) +245 + j*(250) +-73 + j*(-16) +35 + j*(123) +49 + j*(49) +-154 + j*(-42) +-281 + j*(-35) +-308 + j*(151) +151 + j*(22) +45 + j*(-136) +-244 + j*(-184) +-175 + j*(-62) +38 + j*(231) +6 + j*(98) +-51 + j*(-29) +-168 + j*(-286) +60 + j*(-317) +53 + j*(221) +-120 + j*(98) +-54 + j*(-115) +93 + j*(-67) +139 + j*(57) +-66 + j*(108) +-183 + j*(54) +-59 + j*(-28) +-165 + j*(35) +-184 + j*(29) +-275 + j*(165) +377 + j*(17) +-283 + j*(-351) +42 + j*(141) +90 + j*(-40) +-74 + j*(-148) +53 + j*(353) +4 + j*(-133) +440 + j*(-84) +-33 + j*(113) +83 + j*(76) +-175 + j*(-44) +69 + j*(-90) +103 + j*(135) +156 + j*(92) +-122 + j*(-37) +48 + j*(-104) +250 + j*(-129) +88 + j*(190) +-170 + j*(335) +-293 + j*(20) +40 + j*(-365) +140 + j*(-265) +340 + j*(49) +-47 + j*(135) +330 + j*(-47) +-25 + j*(-161) +-59 + j*(112) +185 + j*(186) +125 + j*(-295) +-45 + j*(554) +100 + j*(13) +52 + j*(40) +-13 + j*(-54) +-218 + j*(-153) +11 + j*(-43) +-39 + j*(3) +10 + j*(-15) +-298 + j*(9) +123 + j*(-210) +179 + j*(-168) +211 + j*(-169) +250 + j*(216) +74 + j*(-95) +-288 + j*(59) +-35 + j*(135) +23 + j*(127) +-22 + j*(190) +-76 + j*(-112) +180 + j*(-251) +226 + j*(-145) +30 + j*(37) +79 + j*(137) +83 + j*(-292) +209 + j*(-6) +-307 + j*(-122) +119 + j*(-90) +26 + j*(-105) +-28 + j*(-279) +-95 + j*(-34) +-57 + j*(-282) +-361 + j*(-175) +-83 + j*(-77) +-74 + j*(16) +370 + j*(52) +-276 + j*(-269) +285 + j*(-62) +-129 + j*(-197) +-21 + j*(-14) +-3 + j*(45) +371 + j*(43) +-213 + j*(-98) +196 + j*(23) +187 + j*(62) +-165 + j*(173) +61 + j*(-60) +194 + j*(-329) +-269 + j*(-18) +160 + j*(-72) +62 + j*(284) +47 + j*(-228) +-74 + j*(294) +64 + j*(78) +37 + j*(-100) +-81 + j*(50) +18 + j*(-113) +157 + j*(217) +188 + j*(355) +37 + j*(-31) +176 + j*(-282) +190 + j*(28) +81 + j*(-1) +-202 + j*(311) +-52 + j*(120) +-18 + j*(17) +-330 + j*(-110) +-84 + j*(472) +51 + j*(234) +-144 + j*(366) +-25 + j*(12) +-69 + j*(-14) +540 + j*(-155) +52 + j*(81) +174 + j*(-171) +117 + j*(-86) +-15 + j*(-315) +154 + j*(135) +107 + j*(97) +-119 + j*(-209) +67 + j*(-233) +14 + j*(58) +-94 + j*(159) +-81 + j*(1) +107 + j*(-90) +-29 + j*(38) +-565 + j*(-190) +-35 + j*(36) +255 + j*(220) +-25 + j*(18) +-337 + j*(-27) +89 + j*(-148) +-89 + j*(-141) +-12 + j*(20) +69 + j*(-27) +228 + j*(-64) +112 + j*(-27) +-181 + j*(81) +-102 + j*(-2) +61 + j*(257) +-170 + j*(8) +-4 + j*(-171) +-119 + j*(-27) +-156 + j*(10) +315 + j*(-231) +264 + j*(260) +-37 + j*(129) +69 + j*(-72) +121 + j*(146) +-37 + j*(221) +-195 + j*(1) +301 + j*(107) +221 + j*(16) +-313 + j*(-181) +-51 + j*(-94) +140 + j*(-295) +6 + j*(-176) +-135 + j*(4) +-49 + j*(355) +87 + j*(69) +-40 + j*(-108) +81 + j*(187) +51 + j*(-194) +-98 + j*(175) +-280 + j*(127) +194 + j*(-100) +-287 + j*(185) +-28 + j*(14) +57 + j*(55) +-313 + j*(-42) +175 + j*(-13) +-138 + j*(136) +-7 + j*(27) +16 + j*(214) +-4 + j*(70) +-28 + j*(-166) +-91 + j*(214) +-64 + j*(-305) +293 + j*(-61) +268 + j*(182) +153 + j*(23) +-50 + j*(-63) +57 + j*(-17) +-127 + j*(47) +-107 + j*(-67) +68 + j*(83) +38 + j*(-78) +-169 + j*(-76) +132 + j*(134) +202 + j*(197) +-224 + j*(140) +-37 + j*(643) +-233 + j*(16) +-227 + j*(-88) +-168 + j*(-213) +63 + j*(-224) +88 + j*(28) +8 + j*(165) +-273 + j*(-146) +-140 + j*(-8) +-100 + j*(13) +-232 + j*(1) +-223 + j*(93) +-132 + j*(-45) +-20 + j*(248) +156 + j*(-44) +74 + j*(-89) +88 + j*(26) +161 + j*(-94) +-11 + j*(-143) +-145 + j*(124) +-33 + j*(30) +485 + j*(173) +249 + j*(-310) +-246 + j*(164) +-104 + j*(134) +-126 + j*(184) +-135 + j*(259) +18 + j*(79) +-115 + j*(67) +-190 + j*(-126) +-159 + j*(183) +184 + j*(-190) +390 + j*(-129) +-35 + j*(-129) +342 + j*(363) +110 + j*(-233) +158 + j*(-269) +15 + j*(-55) +-204 + j*(-508) +11 + j*(165) +-346 + j*(-145) +-168 + j*(75) +-175 + j*(-120) +-25 + j*(294) +-119 + j*(337) +-119 + j*(111) +11 + j*(-257) +-141 + j*(-127) +116 + j*(57) +-173 + j*(30) +-138 + j*(68) +-71 + j*(-35) +14 + j*(250) +-11 + j*(-57) +57 + j*(-279) +74 + j*(274) +-81 + j*(64) +-378 + j*(-80) +-279 + j*(211) +-79 + j*(194) +-6 + j*(261) +156 + j*(-58) +-8 + j*(-139) +239 + j*(-23) +-117 + j*(-64) +-107 + j*(41) +-198 + j*(-283) +-91 + j*(-135) +-43 + j*(-13) +99 + j*(30) +4 + j*(105) +-276 + j*(319) +-298 + j*(-84) +-7 + j*(-237) +-286 + j*(9) +74 + j*(122) +10 + j*(344) +-185 + j*(161) +139 + j*(187) +-332 + j*(-48) +-35 + j*(-204) +-7 + j*(-144) +-6 + j*(266) +78 + j*(25) +37 + j*(78) +96 + j*(183) +-107 + j*(-141) +66 + j*(-433) +-127 + j*(-27) +-96 + j*(138) +-1 + j*(-129) +-351 + j*(71) +-324 + j*(202) +-93 + j*(-97) +73 + j*(153) +115 + j*(-252) +156 + j*(172) +-312 + j*(-143) +-336 + j*(-115) +-119 + j*(-85) +47 + j*(-141) +300 + j*(174) +-219 + j*(57) +102 + j*(-172) +45 + j*(390) +17 + j*(-127) +31 + j*(135) +344 + j*(83) +-76 + j*(140) +53 + j*(57) +199 + j*(192) +-69 + j*(165) +5 + j*(216) +525 + j*(152) +-233 + j*(-83) +-221 + j*(283) +50 + j*(12) +214 + j*(-559) +-118 + j*(-131) +-77 + j*(-31) +-30 + j*(-192) +130 + j*(-141) +215 + j*(296) +-64 + j*(65) +209 + j*(-41) +81 + j*(219) +-110 + j*(-412) +119 + j*(130) +199 + j*(-42) +72 + j*(-13) +-223 + j*(53) +45 + j*(28) +262 + j*(-16) +11 + j*(78) +182 + j*(-139) +73 + j*(211) +183 + j*(11) +-7 + j*(171) +65 + j*(-11) +-12 + j*(-45) +10 + j*(251) +110 + j*(-240) +187 + j*(-95) +-42 + j*(-128) +26 + j*(117) +-77 + j*(128) +-45 + j*(70) +74 + j*(-117) +-28 + j*(109) +-175 + j*(-98) +119 + j*(204) +8 + j*(298) +-43 + j*(-71) +105 + j*(107) +-46 + j*(31) +-23 + j*(-230) +-141 + j*(-225) +-245 + j*(-98) +-115 + j*(-24) +52 + j*(330) +-5 + j*(218) +-179 + j*(37) +50 + j*(52) +40 + j*(127) +-165 + j*(-45) +199 + j*(-132) +242 + j*(-7) +-489 + j*(-55) +-220 + j*(-413) +80 + j*(-27) +-104 + j*(103) +-245 + j*(383) +-40 + j*(-466) +197 + j*(144) +-98 + j*(13) +-8 + j*(345) +335 + j*(190) +42 + j*(35) +157 + j*(58) +175 + j*(-229) +284 + j*(-218) +421 + j*(283) +272 + j*(-241) +-252 + j*(157) +-209 + j*(22) +-40 + j*(-61) +-30 + j*(84) +293 + j*(-244) +-286 + j*(241) +-197 + j*(-78) +-107 + j*(-2) +-329 + j*(-105) +93 + j*(-472) +187 + j*(-107) +-279 + j*(150) +-337 + j*(211) +117 + j*(-244) +-221 + j*(267) +224 + j*(70) +174 + j*(168) +-124 + j*(-14) +16 + j*(-190) +-207 + j*(305) +143 + j*(54) +-124 + j*(30) +43 + j*(-15) +-67 + j*(-205) +21 + j*(-163) +157 + j*(-183) +-59 + j*(-42) +-53 + j*(-147) +231 + j*(30) +-61 + j*(-77) +4 + j*(-422) +-378 + j*(259) +74 + j*(-154) +36 + j*(153) +-182 + j*(-66) +189 + j*(-37) +-129 + j*(-29) +46 + j*(-117) +-88 + j*(-76) +-23 + j*(164) +-111 + j*(-12) +-228 + j*(-86) +134 + j*(-25) +-142 + j*(93) +-182 + j*(25) +215 + j*(-70) +181 + j*(-52) +212 + j*(156) +421 + j*(-248) +52 + j*(-489) +36 + j*(86) +105 + j*(-277) +283 + j*(-57) +250 + j*(73) +86 + j*(-120) +-230 + j*(-105) +-86 + j*(-75) +-118 + j*(88) +59 + j*(-71) +-106 + j*(-66) +-314 + j*(-8) +-16 + j*(270) +-138 + j*(189) +-151 + j*(-110) +365 + j*(-158) +-216 + j*(-23) +4 + j*(181) +-245 + j*(88) +-132 + j*(202) +-115 + j*(-160) +69 + j*(310) +47 + j*(45) +104 + j*(72) +260 + j*(204) +-190 + j*(46) +-192 + j*(312) +8 + j*(-155) +-162 + j*(90) +-115 + j*(44) +-37 + j*(-298) +-72 + j*(238) +170 + j*(310) +72 + j*(248) +-28 + j*(151) +103 + j*(-130) +78 + j*(-173) +120 + j*(-121) +435 + j*(-305) +-20 + j*(45) +-93 + j*(235) +66 + j*(-35) +204 + j*(4) +-134 + j*(50) +-397 + j*(-16) +91 + j*(166) +112 + j*(-139) +-42 + j*(-366) +25 + j*(223) +79 + j*(-212) +-67 + j*(-242) +-235 + j*(-83) +-160 + j*(62) +124 + j*(347) +110 + j*(-49) +127 + j*(49) +167 + j*(-341) +-427 + j*(-66) +-172 + j*(82) +-130 + j*(-25) +-9 + j*(-11) +99 + j*(252) +-225 + j*(-153) +-220 + j*(175) +141 + j*(122) +110 + j*(288) +-286 + j*(149) +-47 + j*(218) +322 + j*(127) +159 + j*(101) +-252 + j*(185) +-443 + j*(-124) +10 + j*(165) +182 + j*(169) +-32 + j*(-81) +-44 + j*(-41) +-229 + j*(50) +157 + j*(421) +-155 + j*(-18) +-85 + j*(-13) +148 + j*(-432) +-298 + j*(-108) +-260 + j*(219) +272 + j*(-179) +35 + j*(-123) +137 + j*(8) +29 + j*(-116) +84 + j*(167) +308 + j*(-47) +204 + j*(64) +339 + j*(-60) +-224 + j*(-70) +186 + j*(730) +-59 + j*(86) +66 + j*(-30) +-16 + j*(-260) +-309 + j*(200) +-143 + j*(-127) +33 + j*(-50) +12 + j*(-74) +-113 + j*(-52) +-31 + j*(197) +330 + j*(197) +264 + j*(-106) +214 + j*(-164) +-8 + j*(431) +-143 + j*(66) +98 + j*(66) +-65 + j*(92) +233 + j*(145) +-93 + j*(133) +28 + j*(-104) +-283 + j*(89) +91 + j*(-319) +53 + j*(111) +57 + j*(139) +90 + j*(88) +45 + j*(66) +-43 + j*(140) +307 + j*(127) +173 + j*(-86) +115 + j*(-327) +255 + j*(-238) +212 + j*(-170) +173 + j*(279) +49 + j*(142) +6 + j*(3) +218 + j*(184) +-39 + j*(-110) +-10 + j*(-238) +30 + j*(303) +35 + j*(-55) +6 + j*(-54) +140 + j*(-167) +62 + j*(52) +204 + j*(-169) +-64 + j*(163) +-135 + j*(70) +82 + j*(63) +21 + j*(80) +-81 + j*(-139) +-84 + j*(76) +-129 + j*(-13) +-10 + j*(-159) +27 + j*(192) +-158 + j*(118) +81 + j*(-167) +64 + j*(-67) +-82 + j*(48) +-18 + j*(102) +-343 + j*(83) +161 + j*(-159) +-10 + j*(460) +-13 + j*(-252) +148 + j*(-252) +-69 + j*(61) +-152 + j*(48) +38 + j*(137) +90 + j*(40) +39 + j*(-65) +85 + j*(244) +-76 + j*(-138) +-209 + j*(59) +-16 + j*(-194) +424 + j*(175) +-57 + j*(-143) +21 + j*(239) +93 + j*(93) +75 + j*(151) +-66 + j*(-127) +124 + j*(57) +78 + j*(142) +-124 + j*(107) +-184 + j*(-105) +-43 + j*(83) +86 + j*(50) +-46 + j*(1) +108 + j*(-211) +47 + j*(-100) +-136 + j*(-327) +45 + j*(124) +471 + j*(-310) +-72 + j*(52) +-329 + j*(-104) +34 + j*(260) +433 + j*(-45) +-202 + j*(-414) +-115 + j*(-4) +-67 + j*(143) +-21 + j*(462) +74 + j*(-28) +-301 + j*(-155) +107 + j*(-202) +-85 + j*(26) +-31 + j*(322) +416 + j*(352) +-236 + j*(-16) +15 + j*(235) +-250 + j*(120) +-171 + j*(-234) +380 + j*(-51) +301 + j*(91) +118 + j*(79) +20 + j*(-35) +106 + j*(175) +-217 + j*(-156) +146 + j*(156) +-88 + j*(237) +573 + j*(-96) +68 + j*(90) +31 + j*(-156) +-256 + j*(41) +119 + j*(249) +40 + j*(115) +82 + j*(131) +71 + j*(67) +-373 + j*(37) +78 + j*(-76) +-20 + j*(71) +-38 + j*(-23) +117 + j*(-29) +-78 + j*(-358) +-199 + j*(-98) +228 + j*(165) +51 + j*(-88) +-136 + j*(300) +76 + j*(46) +-58 + j*(-200) +82 + j*(-96) +-204 + j*(-250) +209 + j*(462) +-178 + j*(20) +-187 + j*(236) +296 + j*(-223) +-211 + j*(-119) +-232 + j*(199) +-223 + j*(-18) +101 + j*(165) +-349 + j*(-64) +-121 + j*(-27) +-192 + j*(513) +35 + j*(-97) +139 + j*(103) +209 + j*(-49) +97 + j*(73) +105 + j*(3) +54 + j*(-61) +-60 + j*(257) +112 + j*(57) +193 + j*(-144) +88 + j*(24) +150 + j*(-133) +42 + j*(90) +409 + j*(-157) +-37 + j*(-123) +156 + j*(136) +-146 + j*(61) +153 + j*(-356) +-45 + j*(-37) +-69 + j*(198) +-408 + j*(202) +-18 + j*(102) +259 + j*(-2) +220 + j*(-238) +-82 + j*(-42) +68 + j*(65) +-25 + j*(144) +303 + j*(-100) +6 + j*(81) +-25 + j*(47) +106 + j*(245) +-204 + j*(-276) +59 + j*(23) +-472 + j*(161) +-196 + j*(-26) +266 + j*(-304) +132 + j*(-221) +-108 + j*(28) +-82 + j*(-34) +-107 + j*(-3) +-110 + j*(91) +-11 + j*(-317) +106 + j*(76) +28 + j*(-119) +32 + j*(-52) +-256 + j*(33) +-46 + j*(-450) +-10 + j*(-294) +454 + j*(-266) +89 + j*(-168) +100 + j*(-173) +240 + j*(71) +69 + j*(-199) +-110 + j*(71) +-36 + j*(18) +-145 + j*(103) +-317 + j*(-51) +11 + j*(62) +184 + j*(78) +182 + j*(-217) +-168 + j*(-93) +-58 + j*(75) +-173 + j*(-167) +-139 + j*(153) +47 + j*(-235) +128 + j*(-67) +-226 + j*(143) +-220 + j*(-101) +240 + j*(-123) +-86 + j*(-377) +52 + j*(30) +-39 + j*(-147) +236 + j*(-35) +150 + j*(-226) +-52 + j*(-192) +-37 + j*(187) +-201 + j*(52) +-146 + j*(116) +-168 + j*(123) +54 + j*(-331) +-33 + j*(-58) +-139 + j*(-2) +23 + j*(-123) +94 + j*(-83) +127 + j*(158) +-29 + j*(-93) +148 + j*(269) +-21 + j*(227) +-178 + j*(-3) +-72 + j*(-140) +35 + j*(13) +-14 + j*(122) +-113 + j*(63) +-177 + j*(6) +-291 + j*(250) +-184 + j*(260) +-119 + j*(-229) +-255 + j*(-19) +-83 + j*(-202) +14 + j*(-102) +-83 + j*(91) +100 + j*(-115) +-289 + j*(83) +-209 + j*(-58) +-3 + j*(-247) +164 + j*(-134) +380 + j*(18) +40 + j*(-62) +-132 + j*(-80) +-1 + j*(-203) +-175 + j*(-139) +50 + j*(92) +-28 + j*(-29) +181 + j*(40) +-241 + j*(40) +221 + j*(166) +81 + j*(-112) +4 + j*(-86) +-7 + j*(-132) +-78 + j*(-117) +-152 + j*(92) +-62 + j*(-200) +-28 + j*(72) +186 + j*(-240) +-9 + j*(148) +81 + j*(-139) +-62 + j*(-86) +-14 + j*(-98) +125 + j*(-161) +-198 + j*(306) +-57 + j*(33) +122 + j*(-140) +-69 + j*(-103) +-66 + j*(308) +-9 + j*(206) +-63 + j*(33) +175 + j*(15) +-42 + j*(-182) +6 + j*(45) +-218 + j*(15) +-93 + j*(-39) +30 + j*(81) +66 + j*(405) +-52 + j*(373) +467 + j*(55) +17 + j*(81) +145 + j*(226) +-86 + j*(-193) +-112 + j*(-109) +203 + j*(-74) +-12 + j*(-225) +52 + j*(-145) +-61 + j*(330) +98 + j*(-218) +114 + j*(-56) +31 + j*(-127) +-337 + j*(-109) +212 + j*(-71) +-111 + j*(-33) +113 + j*(250) +195 + j*(-205) +-23 + j*(88) +151 + j*(-217) +105 + j*(-339) +139 + j*(275) +-42 + j*(407) +215 + j*(-210) +-390 + j*(-214) +-330 + j*(-141) +-125 + j*(-173) +164 + j*(-199) +262 + j*(43) +172 + j*(355) +69 + j*(151) +-35 + j*(-54) +-218 + j*(-117) +13 + j*(276) +-42 + j*(-181) +176 + j*(-191) +-174 + j*(-44) +-300 + j*(-130) +29 + j*(-37) +-274 + j*(-3) +-23 + j*(57) +122 + j*(-143) +215 + j*(17) +78 + j*(110) +-305 + j*(83) +-4 + j*(43) +92 + j*(-425) +-323 + j*(-36) +-18 + j*(-63) +63 + j*(8) +50 + j*(170) +105 + j*(79) +-18 + j*(-273) +-66 + j*(-273) +86 + j*(-55) +173 + j*(-37) +-87 + j*(30) +107 + j*(-247) +57 + j*(134) +-118 + j*(518) +164 + j*(-260) +155 + j*(-93) +95 + j*(42) +293 + j*(-62) +-26 + j*(250) +129 + j*(216) +86 + j*(69) +191 + j*(1) +214 + j*(-134) +-308 + j*(-433) +-33 + j*(-70) +-98 + j*(57) +116 + j*(19) +-248 + j*(185) +74 + j*(-148) +-2 + j*(-165) +32 + j*(238) +-4 + j*(170) +-112 + j*(-122) +343 + j*(62) +145 + j*(72) +-62 + j*(383) +-105 + j*(-106) +-480 + j*(200) +184 + j*(346) +83 + j*(-158) +187 + j*(170) +-105 + j*(-212) +-326 + j*(140) +240 + j*(-288) +107 + j*(-84) +-231 + j*(-215) +-162 + j*(99) +-205 + j*(202) +-89 + j*(170) +128 + j*(-134) +31 + j*(-245) +-21 + j*(45) +-5 + j*(32) +-71 + j*(138) +-300 + j*(55) +31 + j*(-25) +-2 + j*(153) +163 + j*(-122) +-132 + j*(-221) +192 + j*(62) +-168 + j*(4) +-10 + j*(-241) +193 + j*(-8) +31 + j*(-57) +-58 + j*(-64) +-134 + j*(-218) +78 + j*(-81) +-13 + j*(107) +-163 + j*(-23) +-287 + j*(189) +-226 + j*(-65) +54 + j*(-36) +25 + j*(260) +177 + j*(167) +-83 + j*(245) +-95 + j*(-302) +97 + j*(-70) +135 + j*(-128) +15 + j*(-54) +57 + j*(-5) +33 + j*(9) +196 + j*(297) +-26 + j*(-111) +-112 + j*(211) +-215 + j*(54) +-286 + j*(-7) +157 + j*(81) +626 + j*(96) +157 + j*(170) +-2 + j*(116) +-131 + j*(10) +443 + j*(48) +-343 + j*(-14) +-46 + j*(136) +235 + j*(98) +298 + j*(-99) +27 + j*(-122) +-303 + j*(269) +-65 + j*(-224) +86 + j*(119) +363 + j*(-146) +289 + j*(112) +416 + j*(-343) +23 + j*(62) +359 + j*(-118) +43 + j*(-156) +3 + j*(-25) +-28 + j*(112) +100 + j*(211) +-28 + j*(47) +-169 + j*(18) +107 + j*(-104) +-50 + j*(-117) +269 + j*(-52) +13 + j*(-81) +-108 + j*(12) +-103 + j*(-257) +-258 + j*(93) +-202 + j*(211) +-117 + j*(-83) +5 + j*(-173) +-289 + j*(281) +-30 + j*(175) +-20 + j*(-96) +177 + j*(40) +-42 + j*(-80) +-156 + j*(-88) +-87 + j*(56) +112 + j*(42) +-115 + j*(-334) +121 + j*(123) +-197 + j*(308) +43 + j*(-219) +-191 + j*(-131) +19 + j*(-239) +-103 + j*(-7) +-67 + j*(-83) +-372 + j*(-101) +211 + j*(-40) +-242 + j*(-88) +-66 + j*(-199) +-8 + j*(30) +183 + j*(-58) +59 + j*(220) +288 + j*(62) +233 + j*(109) +23 + j*(127) +-99 + j*(-173) +-48 + j*(-95) +182 + j*(167) +146 + j*(-223) +209 + j*(-64) +23 + j*(243) +65 + j*(78) +-36 + j*(30) +-384 + j*(-61) +187 + j*(9) +-46 + j*(-52) +187 + j*(-119) +26 + j*(199) +-296 + j*(-226) +224 + j*(-408) +-184 + j*(221) +-184 + j*(174) +83 + j*(107) +-125 + j*(-95) +417 + j*(197) +10 + j*(-238) +32 + j*(-39) +-59 + j*(161) +74 + j*(272) +291 + j*(139) +-144 + j*(81) +-321 + j*(0) +125 + j*(-56) +-44 + j*(32) +57 + j*(-141) +-115 + j*(32) +91 + j*(103) +-204 + j*(-151) +-112 + j*(-84) +-49 + j*(42) +67 + j*(-351) +-51 + j*(61) +-269 + j*(54) +-247 + j*(-315) +38 + j*(-28) +17 + j*(-354) +157 + j*(-127) +267 + j*(85) +137 + j*(-86) +-77 + j*(-158) +344 + j*(-275) +-101 + j*(136) +-156 + j*(-459) +-9 + j*(-119) +344 + j*(33) +16 + j*(-237) +74 + j*(-71) +-19 + j*(321) +228 + j*(-115) +-228 + j*(82) +-291 + j*(49) +-216 + j*(-457) +-161 + j*(-90) +-145 + j*(85) +-417 + j*(130) +-32 + j*(51) +-341 + j*(-24) +60 + j*(174) +-70 + j*(220) +-177 + j*(-25) +-42 + j*(-177) +141 + j*(-44) +126 + j*(-156) +180 + j*(-93) +239 + j*(-163) +-242 + j*(-108) +74 + j*(133) +24 + j*(-28) +-310 + j*(242) +134 + j*(201) +-296 + j*(119) +-98 + j*(-12) +69 + j*(71) +-313 + j*(-73) +28 + j*(-25) +62 + j*(-102) +-325 + j*(136) +322 + j*(-87) +64 + j*(247) +-152 + j*(86) +95 + j*(-110) +145 + j*(344) +95 + j*(-163) +-30 + j*(-364) +276 + j*(-101) +104 + j*(-206) +119 + j*(-93) +-153 + j*(324) +-3 + j*(-38) +70 + j*(83) +-1 + j*(-329) +-12 + j*(122) +41 + j*(104) +-51 + j*(-198) +129 + j*(61) +4 + j*(23) +214 + j*(-16) +-95 + j*(90) +-84 + j*(-9) +-159 + j*(78) +-108 + j*(278) +156 + j*(-250) +106 + j*(172) +184 + j*(155) +159 + j*(47) +-63 + j*(87) +-8 + j*(115) +-214 + j*(-180) +-78 + j*(-164) +63 + j*(-165) +-56 + j*(290) +-69 + j*(-195) +-155 + j*(53) +139 + j*(180) +205 + j*(-108) +30 + j*(342) +-103 + j*(37) +-204 + j*(-105) +-125 + j*(-243) +211 + j*(306) +-264 + j*(-107) +-119 + j*(-308) +34 + j*(163) +5 + j*(112) +279 + j*(43) +209 + j*(-43) +15 + j*(157) +262 + j*(-8) +26 + j*(194) +170 + j*(-77) +-65 + j*(-503) +18 + j*(-21) +228 + j*(-116) +-71 + j*(54) +98 + j*(-200) +273 + j*(0) +-126 + j*(-49) +118 + j*(-24) +-1 + j*(21) +-122 + j*(74) +247 + j*(-27) +-94 + j*(252) +31 + j*(-20) +153 + j*(44) +38 + j*(-140) +62 + j*(200) +-21 + j*(-37) +126 + j*(191) +-3 + j*(-28) +261 + j*(284) +-329 + j*(-189) +23 + j*(-105) +200 + j*(-269) +113 + j*(36) +61 + j*(151) +-50 + j*(49) +-150 + j*(-70) +-115 + j*(-88) +-46 + j*(-153) +100 + j*(92) +-61 + j*(138) +-35 + j*(-166) +-185 + j*(189) +254 + j*(-180) +47 + j*(464) +24 + j*(273) +-240 + j*(-223) +-3 + j*(-196) +-204 + j*(189) +-33 + j*(-244) +-112 + j*(-252) +-103 + j*(-173) +-12 + j*(-321) +-150 + j*(-90) +-26 + j*(238) +209 + j*(-52) +217 + j*(262) +-211 + j*(69) +165 + j*(177) +13 + j*(-94) +-110 + j*(-168) +167 + j*(-127) +-100 + j*(64) +98 + j*(164) +138 + j*(-101) +97 + j*(-344) +-255 + j*(33) +-40 + j*(-127) +99 + j*(-166) +-106 + j*(-271) +240 + j*(18) +-58 + j*(-147) +-145 + j*(50) +-203 + j*(-132) +12 + j*(-170) +-270 + j*(175) +-47 + j*(-71) +279 + j*(-226) +181 + j*(202) +24 + j*(13) +65 + j*(148) +-98 + j*(240) +36 + j*(206) +134 + j*(12) +-144 + j*(-184) +-402 + j*(83) +-103 + j*(119) +-62 + j*(-148) +-113 + j*(202) +-266 + j*(41) +185 + j*(-2) +-196 + j*(-76) +-123 + j*(-203) +-195 + j*(-21) +-23 + j*(232) +-156 + j*(225) +219 + j*(152) +155 + j*(-184) +-100 + j*(-13) +-29 + j*(-129) +357 + j*(-53) +192 + j*(-126) +-6 + j*(-172) +57 + j*(114) +183 + j*(-358) +47 + j*(-211) +-42 + j*(131) +-194 + j*(-122) +-171 + j*(304) +31 + j*(95) +-160 + j*(281) +37 + j*(-166) +-142 + j*(37) +6 + j*(342) +-55 + j*(-177) +-20 + j*(-42) +-351 + j*(87) +225 + j*(-8) +92 + j*(258) +71 + j*(83) +103 + j*(-59) +182 + j*(42) +78 + j*(-264) +-153 + j*(-325) +-160 + j*(25) +21 + j*(91) +-123 + j*(-245) +81 + j*(-151) +277 + j*(63) +-86 + j*(-250) +-173 + j*(30) +86 + j*(-86) +11 + j*(95) +61 + j*(-32) +-122 + j*(25) +-52 + j*(-103) +-93 + j*(445) +105 + j*(16) +-68 + j*(-42) +129 + j*(-107) +-199 + j*(-258) +-273 + j*(108) +93 + j*(4) +176 + j*(-44) +98 + j*(-21) +-145 + j*(-4) +-192 + j*(22) +-33 + j*(96) +-176 + j*(-115) +-29 + j*(47) +-221 + j*(98) +139 + j*(249) +260 + j*(-54) +-64 + j*(-2) +252 + j*(-52) +150 + j*(-151) +6 + j*(145) +-78 + j*(136) +315 + j*(91) +30 + j*(91) +-70 + j*(2) +105 + j*(-147) +-159 + j*(380) +475 + j*(-3) +221 + j*(130) +224 + j*(-352) +23 + j*(180) +57 + j*(19) +-322 + j*(94) +-28 + j*(-117) +156 + j*(-285) +68 + j*(109) +-77 + j*(-47) +87 + j*(-23) +392 + j*(44) +-187 + j*(-203) +-108 + j*(-540) +-227 + j*(45) +2 + j*(-269) +-64 + j*(204) +-185 + j*(-205) +-119 + j*(2) +404 + j*(-132) +-144 + j*(20) +160 + j*(181) +-283 + j*(86) +33 + j*(-139) +-195 + j*(69) +117 + j*(-152) +-308 + j*(-221) +337 + j*(127) +-18 + j*(-202) +118 + j*(-132) +13 + j*(-235) +-29 + j*(-47) +206 + j*(41) +-243 + j*(306) +5 + j*(137) +-48 + j*(42) +-547 + j*(-230) +-20 + j*(53) +-49 + j*(0) +20 + j*(211) +-115 + j*(359) +22 + j*(158) +-108 + j*(-13) +169 + j*(-289) +92 + j*(69) +-124 + j*(95) +113 + j*(-54) +-382 + j*(-159) +274 + j*(214) +-21 + j*(224) +29 + j*(59) +496 + j*(233) +-115 + j*(-141) +246 + j*(-170) +-75 + j*(-33) +251 + j*(-71) +7 + j*(144) +119 + j*(-99) +197 + j*(16) +52 + j*(-139) +17 + j*(-294) +-66 + j*(177) +-299 + j*(-142) +139 + j*(142) +34 + j*(126) +16 + j*(260) +90 + j*(44) +-303 + j*(196) +67 + j*(-71) +74 + j*(179) +211 + j*(-202) +349 + j*(378) +444 + j*(3) +31 + j*(98) +-217 + j*(-99) +35 + j*(98) +-111 + j*(211) +253 + j*(69) +312 + j*(-1) +139 + j*(163) +-30 + j*(5) +-177 + j*(112) +-195 + j*(211) +-254 + j*(-32) +-90 + j*(8) +170 + j*(-214) +254 + j*(257) +-179 + j*(6) +-69 + j*(202) +98 + j*(128) +-197 + j*(-299) +-250 + j*(-177) +156 + j*(-23) +-64 + j*(-156) +-35 + j*(-64) +32 + j*(101) +-92 + j*(-60) +180 + j*(22) +21 + j*(134) +166 + j*(-83) +423 + j*(7) +12 + j*(219) +37 + j*(168) +1 + j*(118) +42 + j*(-40) +-148 + j*(-71) +-93 + j*(-12) +-103 + j*(-221) +298 + j*(49) +56 + j*(91) +340 + j*(52) +-117 + j*(132) +10 + j*(24) +-24 + j*(151) +-82 + j*(-61) +126 + j*(-199) +-42 + j*(249) +102 + j*(74) +53 + j*(126) +245 + j*(161) +-50 + j*(285) +106 + j*(136) +235 + j*(-6) +120 + j*(-202) +165 + j*(-13) +-181 + j*(81) +318 + j*(-256) +-25 + j*(137) +153 + j*(128) +123 + j*(-73) +61 + j*(51) +-190 + j*(268) +-363 + j*(214) +11 + j*(42) +75 + j*(-95) +-62 + j*(-16) +-15 + j*(-403) +-33 + j*(-66) +95 + j*(64) +-129 + j*(-220) +-33 + j*(33) +-38 + j*(-90) +103 + j*(-49) +252 + j*(227) +25 + j*(-282) +98 + j*(64) +151 + j*(-88) +-182 + j*(117) +-89 + j*(-91) +-313 + j*(-100) +-117 + j*(-107) +8 + j*(-174) +-83 + j*(-45) +-324 + j*(83) +47 + j*(70) +97 + j*(81) +223 + j*(375) +43 + j*(13) +-156 + j*(103) +-112 + j*(117) +-36 + j*(65) +-18 + j*(174) +-209 + j*(-86) +173 + j*(-186) +130 + j*(-262) +1 + j*(74) +-180 + j*(31) +-285 + j*(295) +-158 + j*(-69) +-165 + j*(86) +-221 + j*(-175) +-166 + j*(47) +-202 + j*(162) +263 + j*(47) +187 + j*(-681) +63 + j*(-173) +74 + j*(119) +23 + j*(-364) +-226 + j*(-106) +-11 + j*(293) +32 + j*(243) +63 + j*(-235) +-28 + j*(42) +-165 + j*(228) +375 + j*(98) +-142 + j*(115) +131 + j*(85) +41 + j*(-390) +202 + j*(339) +-311 + j*(91) +194 + j*(-33) +49 + j*(479) +59 + j*(-524) +310 + j*(266) +131 + j*(-93) +77 + j*(6) +-170 + j*(180) +45 + j*(165) +-6 + j*(151) +291 + j*(-45) +-74 + j*(163) +70 + j*(148) +209 + j*(-54) +-52 + j*(296) +426 + j*(-81) +6 + j*(100) +305 + j*(14) +37 + j*(95) +11 + j*(294) +-152 + j*(-21) +-30 + j*(-151) +47 + j*(-141) +391 + j*(12) +-60 + j*(-167) +16 + j*(110) +161 + j*(6) +213 + j*(158) +35 + j*(-8) +231 + j*(-83) +119 + j*(190) +-35 + j*(191) +35 + j*(339) +-9 + j*(35) +249 + j*(-193) +-153 + j*(162) +175 + j*(-298) +-35 + j*(150) +-11 + j*(-353) +231 + j*(-64) +-139 + j*(-264) +-25 + j*(203) +105 + j*(-223) +94 + j*(125) +150 + j*(-11) +170 + j*(71) +69 + j*(13) +128 + j*(126) +-145 + j*(44) +-33 + j*(166) +-4 + j*(153) +-42 + j*(0) +-281 + j*(40) +-43 + j*(230) +-202 + j*(-315) +210 + j*(-83) +193 + j*(-252) +221 + j*(-6) +-262 + j*(81) +-247 + j*(58) +66 + j*(122) +73 + j*(-110) +-47 + j*(-16) +-62 + j*(54) +153 + j*(-28) +-28 + j*(-310) +55 + j*(-151) +92 + j*(27) +-258 + j*(-75) +206 + j*(-6) +66 + j*(60) +-139 + j*(-156) +50 + j*(134) +-24 + j*(103) +165 + j*(155) +30 + j*(206) +67 + j*(74) +5 + j*(-52) +-168 + j*(-119) +69 + j*(59) +54 + j*(-223) +-196 + j*(1) +217 + j*(-269) +88 + j*(282) +-47 + j*(33) +-124 + j*(-10) +-184 + j*(-282) +-325 + j*(94) +40 + j*(331) +-44 + j*(-128) +56 + j*(163) +-107 + j*(-361) +278 + j*(120) +62 + j*(84) +206 + j*(219) +-192 + j*(-233) +170 + j*(-263) +71 + j*(-114) +260 + j*(293) +-4 + j*(91) +-110 + j*(-105) +-269 + j*(-175) +-282 + j*(210) +213 + j*(-96) +312 + j*(33) +-138 + j*(-117) +18 + j*(-124) +75 + j*(-114) +-409 + j*(21) +-54 + j*(98) +78 + j*(-160) +42 + j*(-13) +-27 + j*(-368) +-54 + j*(191) +87 + j*(95) +-26 + j*(110) +15 + j*(-362) +325 + j*(-46) +-42 + j*(-44) +108 + j*(-125) +-49 + j*(117) +-66 + j*(71) +-21 + j*(-75) +-243 + j*(-115) +-77 + j*(46) +162 + j*(222) +165 + j*(131) +72 + j*(-66) +-47 + j*(21) +112 + j*(-103) +130 + j*(-159) +64 + j*(-24) +124 + j*(-74) +-255 + j*(204) +144 + j*(221) +28 + j*(-227) +-13 + j*(278) +328 + j*(190) +253 + j*(482) +187 + j*(-18) +-191 + j*(-597) +204 + j*(-31) +-57 + j*(144) +-252 + j*(-190) +221 + j*(-197) +35 + j*(139) +43 + j*(-66) +-35 + j*(-119) +288 + j*(-279) +195 + j*(100) +215 + j*(312) +-47 + j*(-114) +-228 + j*(-92) +49 + j*(216) +-376 + j*(82) +-26 + j*(-35) +280 + j*(58) +-412 + j*(-246) +-158 + j*(-41) +-95 + j*(316) +124 + j*(-209) +-127 + j*(105) +69 + j*(89) +-215 + j*(272) +88 + j*(-143) +112 + j*(-29) +69 + j*(40) +-50 + j*(-23) +163 + j*(7) +69 + j*(-132) +60 + j*(115) +25 + j*(-206) +-172 + j*(176) +-535 + j*(-53) +141 + j*(52) +179 + j*(69) +65 + j*(29) +12 + j*(-180) +-205 + j*(64) +82 + j*(136) +62 + j*(-64) +194 + j*(264) +-332 + j*(177) +-65 + j*(373) +34 + j*(107) +-112 + j*(208) +140 + j*(-209) +269 + j*(4) +-247 + j*(-40) +-70 + j*(68) +-179 + j*(-117) +102 + j*(-54) +148 + j*(-216) +446 + j*(35) +281 + j*(-202) +-71 + j*(-89) +180 + j*(161) +-77 + j*(-236) +-33 + j*(-301) +-11 + j*(-132) +71 + j*(-301) +-94 + j*(43) +-209 + j*(-148) +204 + j*(-35) +137 + j*(-66) +8 + j*(54) +-186 + j*(-173) +-82 + j*(-146) +-218 + j*(-95) +202 + j*(-250) +212 + j*(-194) +-2 + j*(-124) +-425 + j*(190) +-10 + j*(-141) +-445 + j*(27) +-66 + j*(-164) +13 + j*(-260) +-109 + j*(132) +79 + j*(165) +39 + j*(259) +173 + j*(110) +35 + j*(264) +-13 + j*(197) +-47 + j*(-209) +-219 + j*(-66) +93 + j*(142) +-129 + j*(-158) +49 + j*(213) +270 + j*(57) +-144 + j*(-371) +-7 + j*(40) +276 + j*(-67) +-144 + j*(94) +-177 + j*(-30) +-61 + j*(-129) +-596 + j*(331) +-67 + j*(214) +-144 + j*(59) +-301 + j*(-268) +-146 + j*(-204) +-117 + j*(-105) +90 + j*(24) +-30 + j*(35) +-166 + j*(-23) +92 + j*(-79) +106 + j*(-62) +127 + j*(400) +-154 + j*(68) +31 + j*(354) +144 + j*(-104) +56 + j*(170) +-74 + j*(25) +-240 + j*(204) +-111 + j*(-112) +-57 + j*(69) +17 + j*(-59) +-76 + j*(86) +-168 + j*(262) +-66 + j*(97) +-360 + j*(224) +-159 + j*(42) +-131 + j*(-4) +-68 + j*(-267) +110 + j*(151) +-110 + j*(-136) +-171 + j*(-18) +-81 + j*(-235) +-236 + j*(173) +378 + j*(-101) +-203 + j*(47) +61 + j*(47) +12 + j*(349) +291 + j*(73) +-470 + j*(73) +339 + j*(48) +-1 + j*(-18) +-132 + j*(-96) +86 + j*(63) +-191 + j*(-190) +-142 + j*(-22) +-134 + j*(-180) +-326 + j*(52) +-198 + j*(-278) +-88 + j*(146) +-207 + j*(33) +-192 + j*(-90) +-55 + j*(-57) +-156 + j*(64) +-332 + j*(327) +235 + j*(-50) +65 + j*(373) +107 + j*(-127) +122 + j*(98) +123 + j*(-29) +-61 + j*(-6) +-35 + j*(58) +96 + j*(-22) +35 + j*(63) +123 + j*(-92) +172 + j*(-159) +240 + j*(57) +-175 + j*(92) +-87 + j*(-8) +122 + j*(-253) +-236 + j*(-38) +-163 + j*(300) +-310 + j*(40) +87 + j*(-207) +454 + j*(68) +-103 + j*(-186) +250 + j*(115) +474 + j*(156) +51 + j*(22) +31 + j*(2) +75 + j*(-193) +-36 + j*(168) +162 + j*(-11) +86 + j*(187) +-86 + j*(-121) +77 + j*(-82) +222 + j*(-158) +-19 + j*(-135) +188 + j*(279) +-4 + j*(198) +54 + j*(30) +-199 + j*(173) +37 + j*(206) +-16 + j*(359) +24 + j*(-164) +211 + j*(-117) +56 + j*(99) +-17 + j*(32) +100 + j*(-287) +-289 + j*(9) +122 + j*(158) +318 + j*(13) +59 + j*(-168) +78 + j*(218) +-42 + j*(191) +-202 + j*(-32) +74 + j*(99) +-167 + j*(98) +64 + j*(343) +119 + j*(-105) +-218 + j*(131) +-116 + j*(-496) +44 + j*(267) +-109 + j*(222) +42 + j*(40) +-15 + j*(164) +-74 + j*(308) +-1 + j*(-144) +-284 + j*(186) +146 + j*(-49) +-244 + j*(240) +-19 + j*(-161) +43 + j*(320) +-136 + j*(20) +247 + j*(0) +69 + j*(-146) +-141 + j*(400) +-21 + j*(-227) +139 + j*(-40) +275 + j*(-26) +-157 + j*(34) +28 + j*(83) +-578 + j*(-7) +-135 + j*(73) +76 + j*(148) +-310 + j*(-154) +210 + j*(123) +52 + j*(-453) +-257 + j*(14) +23 + j*(20) +130 + j*(202) +45 + j*(223) +299 + j*(-381) +-103 + j*(-58) +39 + j*(40) +-42 + j*(86) +161 + j*(-38) +129 + j*(-187) +-84 + j*(-164) +8 + j*(-97) +110 + j*(172) +247 + j*(356) +-310 + j*(-209) +46 + j*(13) +291 + j*(-132) +44 + j*(228) +-43 + j*(166) +-258 + j*(121) +-17 + j*(-28) +327 + j*(-172) +336 + j*(153) +321 + j*(-74) +83 + j*(-168) +3 + j*(-115) +28 + j*(276) +124 + j*(-30) +88 + j*(-173) +341 + j*(-122) +-32 + j*(288) +143 + j*(150) +-389 + j*(-63) +-136 + j*(4) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +]; diff --git a/targets/ARCH/AW2SORI/oaiori.c b/targets/ARCH/AW2SORI/oaiori.c new file mode 100644 index 0000000000..f79e2fad20 --- /dev/null +++ b/targets/ARCH/AW2SORI/oaiori.c @@ -0,0 +1,712 @@ +/*! \file oaiori.c + * \brief AW2S ORI API isolator + * \author Raymond Knopp + * \date 2019 + * \version 0.1 + * \company Eurecom + * \maintainer: raymond.knopp@eurecom.fr + * \note + * \warning + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_lib.h" +#include "ethernet_lib.h" + +#include "ori.h" + +#include "targets/ARCH/COMMON/common_lib.h" + +typedef struct eutra_bandentry_s { + int16_t band; + uint32_t ul_min; + uint32_t ul_max; + uint32_t dl_min; + uint32_t dl_max; + uint32_t N_OFFs_DL; +} eutra_bandentry_t; + +typedef struct band_info_s { + int nbands; + eutra_bandentry_t band_info[100]; +} band_info_t; + + +static const eutra_bandentry_t eutra_bandtable[] = { + {1, 19200, 19800, 21100, 21700, 0 }, + {2, 18500, 19100, 19300, 19900, 6000 }, + {3, 17100, 17850, 18050, 18800, 12000 }, + {4, 17100, 17550, 21100, 21550, 19500 }, + {5, 8240, 8490, 8690, 8940, 24000 }, + {6, 8300, 8400, 8750, 8850, 26500 }, + {7, 25000, 25700, 26200, 26900, 27500 }, + {8, 8800, 9150, 9250, 9600, 34500 }, + {9, 17499, 17849, 18449, 18799, 38000 }, + {10, 17100, 17700, 21100, 21700, 41500 }, + {11, 14279, 14529, 14759, 15009, 47500 }, + {12, 6980, 7160, 7280, 7460, 50100 }, + {13, 7770, 7870, 7460, 7560, 51800 }, + {14, 7880, 7980, 7580, 7680, 52800 }, + {17, 7040, 7160, 7340, 7460, 57300 }, + {18, 8150, 9650, 8600, 10100, 58500 }, + {19, 8300, 8450, 8750, 8900, 60000 }, + {20, 8320, 8620, 7910, 8210, 61500 }, + {21, 14479, 14629, 14959, 15109, 64500 }, + {22, 34100, 34900, 35100, 35900, 66000 }, + {23, 20000, 20200, 21800, 22000, 75000 }, + {24, 16126, 16605, 15250, 15590, 77000 }, + {25, 18500, 19150, 19300, 19950, 80400 }, + {26, 8140, 8490, 8590, 8940, 86900 }, + {27, 8070, 8240, 8520, 8690, 90400 }, + {28, 7030, 7580, 7580, 8130, 92100 }, + {29, 0, 0, 7170, 7280, 96600 }, + {30, 23050, 23250, 23500, 23600, 97700 }, + {31, 45250, 34900, 46250, 35900, 98700 }, + {32, 0, 0, 14520, 14960, 99200 }, + {33, 19000, 19200, 19000, 19200, 360000}, + {34, 20100, 20250, 20100, 20250, 362000}, + {35, 18500, 19100, 18500, 19100, 363500}, + {36, 19300, 19900, 19300, 19900, 369500}, + {37, 19100, 19300, 19100, 19300, 375500}, + {38, 25700, 26200, 25700, 26200, 377500}, + {39, 18800, 19200, 18800, 19200, 382500}, + {40, 23000, 24000, 23000, 24000, 386500}, + {41, 24960, 26900, 24960, 26900, 396500}, + {42, 34000, 36000, 34000, 36000, 415900}, + {43, 36000, 38000, 36000, 38000, 435900}, + {44, 7030, 8030, 7030, 8030, 455900}, + {45, 14470, 14670, 14470, 14670, 465900}, + {46, 51500, 59250, 51500, 59250, 467900}, + {65, 19200, 20100, 21100, 22000, 655360}, + {66, 17100, 18000, 21100, 22000, 664360}, + {67, 0, 0, 7380, 7580, 67336 }, + {68, 6980, 7280, 7530, 7830, 67536 } +}; + + +#define BANDTABLE_SIZE (sizeof(eutra_bandtable)/sizeof(eutra_bandentry_t)) + +uint32_t to_earfcn_DL_aw2s(int eutra_bandP, long long int dl_CarrierFreq, uint32_t bw) { + uint32_t dl_CarrierFreq_by_100k = dl_CarrierFreq / 100000; + int i; + if (eutra_bandP > 68) { printf("eutra_band %d > 68\n", eutra_bandP); exit(-1);} + + for (i = 0; i < BANDTABLE_SIZE && eutra_bandtable[i].band != eutra_bandP; i++); + + printf("AW2S: band %d, index %d\n",eutra_bandP, i); + + if (i >= BANDTABLE_SIZE) { printf(" i = %d , it will trigger out-of-bounds read.\n",i); exit(-1);} + + if (dl_CarrierFreq_by_100k < eutra_bandtable[i].dl_min) { + printf("Band %d, bw %u : DL carrier frequency %u .1 MHz < %u\n", + eutra_bandP, bw, dl_CarrierFreq_by_100k, + eutra_bandtable[i].dl_min); exit(-1);} + + if(dl_CarrierFreq_by_100k > + (eutra_bandtable[i].dl_max - bw)) { + printf("Band %d, bw %u : DL carrier frequency %u .1MHz > %d\n", + eutra_bandP, bw, dl_CarrierFreq_by_100k, + eutra_bandtable[i].dl_max - bw); exit(-1); } + printf("AW2S: dl_CarrierFreq_by_100k %d, dl_min %d\n",dl_CarrierFreq_by_100k,eutra_bandtable[i].dl_min); + + return (dl_CarrierFreq_by_100k - eutra_bandtable[i].dl_min + + (eutra_bandtable[i].N_OFFs_DL / 10)); +} + +uint32_t to_earfcn_UL_aw2s(int eutra_bandP, long long int ul_CarrierFreq, uint32_t bw) { + uint32_t ul_CarrierFreq_by_100k = ul_CarrierFreq / 100000; + int i; + if(eutra_bandP >= 69) { + printf("eutra_band %d > 68\n", eutra_bandP); + exit(-1); + } + + for (i = 0; i < BANDTABLE_SIZE && eutra_bandtable[i].band != eutra_bandP; i++); + + if(i >= BANDTABLE_SIZE) {printf("i = %d , it will trigger out-of-bounds read.\n",i); exit(-1);} + + if(ul_CarrierFreq_by_100k < eutra_bandtable[i].ul_min) { + printf("Band %d, bw %u : UL carrier frequency %u Hz < %u\n", + eutra_bandP, bw, ul_CarrierFreq_by_100k, + eutra_bandtable[i].ul_min); + exit(-1); + } + if(ul_CarrierFreq_by_100k > (eutra_bandtable[i].ul_max - bw)) { + printf("Band %d, bw %u : UL carrier frequency %u Hz > %d\n", + eutra_bandP, bw, ul_CarrierFreq_by_100k, + eutra_bandtable[i].ul_max - bw); + exit(-1); + } + return (ul_CarrierFreq_by_100k - eutra_bandtable[i].ul_min + + ((eutra_bandtable[i].N_OFFs_DL + 180000) / 10)); +} + +int get_mac_addr(const char *iface,unsigned char *mac) + +{ + int fd; + struct ifreq ifr; + int ret=0; + + memset(&ifr, 0, sizeof(ifr)); + fd = socket(AF_INET, SOCK_DGRAM, 0); + ifr.ifr_addr.sa_family = AF_INET; + strncpy(ifr.ifr_name , iface , IFNAMSIZ-1); + if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr)) memcpy((void*)mac,(void *)ifr.ifr_hwaddr.sa_data,6); + else { + printf("No MAC address!\n"); + ret = -1; + } + + printf("%s : %2x:%2x:%2x:%2x:%2x:%2x\n",iface,mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); + close(fd); + return(ret); +} + + +void cb(void * userData, ORI_IndicationType_e type, ORI_IndicationValue_u value) +{ + printf("============> Got indication %s\n", ORI_IndicationType_Print(type)); + if(type == ORI_IndicationType_ObjectStateChange) + { + ORI_Object_s * obj = value.objectStateChange.object; + printf("State change for %s:%d -> %s : %s\n", ORI_ObjectType_Print(obj->typeRef.type), obj->instanceNumber, + ORI_StateType_Print(value.objectStateChange.stateType), + value.objectStateChange.stateType == ORI_StateType_AST ? ORI_AST_Print(obj->ast) : ORI_FST_Print(obj->fst)); + } + else if(type == ORI_IndicationType_FaultChange) + { + ORI_Object_s * obj = value.faultChange.object; + ORI_Fault_s * fault = value.faultChange.fault; + printf("Fault change for %s:%d -> %s : %s\n", ORI_ObjectType_Print(obj->typeRef.type), obj->instanceNumber, + ORI_FaultType_Print(value.faultChange.faultType), + ORI_FaultState_Print(fault->state)); + if(fault->state == ORI_FaultState_Active) + { + printf("\t Fault severity: %s\n", ORI_FaultSeverity_Print(fault->severity)); + printf("\t Timestamp: %s\n", fault->timestamp); + printf("\t Description: %s\n", fault->desc); + } + } + printf("<============\n"); +} + +int aw2s_oricleanup(openair0_device *device) { + + ORI_s * ori = (ORI_s*)device->thirdparty_priv; + + ORI_Disconnect(ori); + ORI_Free(ori); + + return(0); +} + +int aw2s_startstreaming(openair0_device *device) { + + ORI_s * ori = (ORI_s*)device->thirdparty_priv; + ORI_Result_e result; + ORI_Result_e RE_result; + + openair0_config_t *openair0_cfg = device->openair0_cfg; + + ORI_Object_s *tx0= ORI_FindObject(ori, openair0_cfg->duplex_mode == duplex_mode_FDD ? ORI_ObjectType_TxEUtraFDD :ORI_ObjectType_TxEUtraTDD, 0, NULL); + ORI_Object_s *tx1= (openair0_cfg->tx_num_channels > 1) ? ORI_FindObject(ori, openair0_cfg->duplex_mode == duplex_mode_FDD ?ORI_ObjectType_TxEUtraFDD : ORI_ObjectType_TxEUtraTDD, 1, NULL) : NULL; + ORI_Object_s *rx0= ORI_FindObject(ori, openair0_cfg->duplex_mode == duplex_mode_FDD ?ORI_ObjectType_RxEUtraFDD : ORI_ObjectType_RxEUtraTDD, 0, NULL); + ORI_Object_s *rx1= (openair0_cfg->rx_num_channels > 1) ? ORI_FindObject(ori, openair0_cfg->duplex_mode == duplex_mode_FDD ?ORI_ObjectType_RxEUtraFDD : ORI_ObjectType_RxEUtraTDD, 1, NULL) : NULL; + ORI_Object_s *link= ORI_FindObject(ori, ORI_ObjectType_ORILink, 0, NULL); + + if (tx0 == NULL || (tx1 == NULL && openair0_cfg->tx_num_channels > 1) || rx0 == NULL || (rx1 == NULL && openair0_cfg->rx_num_channels > 1) || link == NULL) return (-1); + + /******************************************************************* + * UNLOCK Link + *******************************************************************/ + + + result = ORI_ObjectStateModification(ori, link, ORI_AST_Unlocked, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectStateModify failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + + /******************************************************************* + * UNLOCK TX0 + *******************************************************************/ + + + /* Put Tx0 into service */ + result = ORI_ObjectStateModification(ori, tx0, ORI_AST_Unlocked, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectStateModify failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectStateModify: %s\n", ORI_Result_Print(RE_result)); + + + + /******************************************************************* + * UNLOCK TX1 + *******************************************************************/ + + if (tx1) { + printf("\n\n\n========================================================\n"); + + /* Put Tx1 into service */ + result = ORI_ObjectStateModification(ori, tx1, ORI_AST_Unlocked, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectStateModify failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectStateModify: %s\n", ORI_Result_Print(RE_result)); + } + /******************************************************************* + * UNLOCK RX0 + *******************************************************************/ + + printf("\n\n\n========================================================\n"); + + /* Put Rx0 into service */ + result = ORI_ObjectStateModification(ori, rx0, ORI_AST_Unlocked, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectStateModify failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectStateModify: %s\n", ORI_Result_Print(RE_result)); + + + + + /******************************************************************* + * UNLOCK RX1 + *******************************************************************/ + if (rx1) { + printf("\n\n\n========================================================\n"); + + /* Put Rx1 into service */ + result = ORI_ObjectStateModification(ori, rx1, ORI_AST_Unlocked, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectStateModify failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectStateModify: %s\n", ORI_Result_Print(RE_result)); + } + + while (rx0->fst != ORI_FST_Operational || + (openair0_cfg->rx_num_channels > 1 && rx1->fst != ORI_FST_Operational) || + tx0->fst != ORI_FST_Operational || + (openair0_cfg->tx_num_channels > 1 && tx1->fst != ORI_FST_Operational)) + {} + + // test RX interface + uint64_t TS; + char temp_rx[1024] __attribute__((aligned(32))); + int aid,r0=0,r1=(openair0_cfg->rx_num_channels > 1) ? 0 : 1; + int i; + int Npackets=1024000; + for (i=0;itrx_read_func2(device, + (openair0_timestamp*)&TS, + (void*)temp_rx, + 256, + &aid); + if (aid == 0) r0=1; + if (aid == 1) r1=1; + } + if (r0==1 && r1==1) printf("Streaming started, returning to OAI\n"); + else { + printf("Didn't get anything from one antenna port after %d packets %d,%d\n",Npackets,r0,r1); + return(-1); + } + return(0); + +} +int aw2s_oriinit(openair0_device *device) { + + + ORI_s * ori; + ORI_Result_e result; + ORI_Result_e RE_result; + ORI_Object_s * objects[100]; + uint32_t numObjects; + uint32_t i; + + eth_params_t *eth_params = device->eth_params; + + openair0_config_t *openair0_cfg = device->openair0_cfg; + + + /******************************************************************* + * CREATION AND CONNECTION + *******************************************************************/ + + printf("Initializing the ORI control interface\n"); + + /* Create context */ + ori = ORI_Create(); + if(!ori) + { + printf("Failed to create ORI context\n"); + return -1; + } + device->thirdparty_priv = (void *)ori; + ori->userData = (void *)ori; + ori->indicationCallback = cb; + + /* Connect... */ + printf("Trying to connect to AW2S device on %s : %d\n",eth_params->remote_addr, eth_params->remote_portc); + result = ORI_Connect(ori, eth_params->remote_addr, eth_params->remote_portc, 3000, 0); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_Connect failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + + /* First health check */ + result = ORI_HealthCheck(ori, 6000, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_HealthCheck failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_HealthCheck: %s\n", ORI_Result_Print(RE_result)); + + /* Set RE time */ + result = ORI_SetTime(ori, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_SetTime failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_SetTime: %s\n", ORI_Result_Print(RE_result)); + + + + + /******************************************************************* + * SOFTWARE PARAMETERS ALIGNMENT + *******************************************************************/ + + /* Report all current objects parameters */ + result = ORI_ObjectParamReport(ori, NULL, 0, ORI_ObjectParam_All, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectParamReport failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + + printf("ORI_ObjectParamReport: %s\n", ORI_Result_Print(RE_result)); + + + + + /******************************************************************* + * TX PATHS CREATION + *******************************************************************/ + + /* Prepare parameters */ + ORI_ObjectTypeRef_s txTypeRef = { NULL, openair0_cfg->duplex_mode == duplex_mode_FDD ? ORI_ObjectType_TxEUtraFDD : ORI_ObjectType_TxEUtraTDD}; + ORI_ObjectParams_u txParams; + ORI_ObjectParam_e txParamList[9]; + ORI_Result_e txParamResult[9]; + int num_txparams; + + if (openair0_cfg->duplex_mode == duplex_mode_FDD) { + txParamList[0] = ORI_ObjectParam_SigPath_antPort; + txParamList[1] = ORI_ObjectParam_SigPath_axcW; + txParamList[2] = ORI_ObjectParam_SigPath_axcB; + txParamList[3] = ORI_ObjectParam_SigPath_chanBW; + txParamList[4] = ORI_ObjectParam_SigPath_earfcn; + txParamList[5] = ORI_ObjectParam_TxSigPath_maxTxPwr; + num_txparams = 6; + } + else { + txParamList[0] = ORI_ObjectParam_SigPath_antPort; + txParamList[1] = ORI_ObjectParam_SigPath_axcW; + txParamList[2] = ORI_ObjectParam_SigPath_axcB; + txParamList[3] = ORI_ObjectParam_SigPath_chanBW; + txParamList[4] = ORI_ObjectParam_SigPath_earfcn; + txParamList[5] = ORI_ObjectParam_TxSigPath_maxTxPwr; + txParamList[6] = ORI_ObjectParam_SigPath_tddULDLConfig; + txParamList[7] = ORI_ObjectParam_SigPath_tddSpecialSFConfig; + txParamList[8] = ORI_ObjectParam_TxSigPath_tddCPLengthDL; + num_txparams = 9; + } + + + /* Create tx0 */ + ORI_Object_s * tx0; + printf("AW2S: duplex_mode %d, tx_bw %f, rx_bw %f\n",openair0_cfg->duplex_mode,openair0_cfg->tx_bw,openair0_cfg->rx_bw); + if (openair0_cfg->duplex_mode == duplex_mode_FDD) { + txParams.TxEUtraFDD.antPort = ORI_FindObject(ori, ORI_ObjectType_AntennaPort, 0, NULL); + txParams.TxEUtraFDD.axcW = 1; + txParams.TxEUtraFDD.axcB = 0; + txParams.TxEUtraFDD.chanBW = openair0_cfg->tx_bw/100e3; + txParams.TxEUtraFDD.earfcn = 3350; + txParams.TxEUtraFDD.maxTxPwr = -100; + } + else if (openair0_cfg->duplex_mode == duplex_mode_TDD) { + txParams.TxEUtraTDD.antPort = ORI_FindObject(ori, ORI_ObjectType_AntennaPort, 0, NULL); + txParams.TxEUtraTDD.axcW = 1; + txParams.TxEUtraTDD.axcB = 0; + txParams.TxEUtraTDD.chanBW = openair0_cfg->tx_bw/100e3; + txParams.TxEUtraTDD.earfcn = to_earfcn_DL_aw2s(38,(long long int)openair0_cfg->tx_freq[0],txParams.TxEUtraTDD.chanBW); + txParams.TxEUtraTDD.maxTxPwr = 430-((int)openair0_cfg->tx_gain[0]*10); + txParams.TxEUtraTDD.tddULDLConfig = 1; + txParams.TxEUtraTDD.tddSpecialSFConfig = 0; + txParams.TxEUtraTDD.tddCPLengthDL = ORI_tddCPLength_Normal; + + printf("AW2S: Configuring for TDD, EARFCN %u, Power %d, BW %d\n", + txParams.TxEUtraTDD.earfcn,txParams.TxEUtraTDD.maxTxPwr,txParams.TxEUtraTDD.chanBW); + } + else { + aw2s_oricleanup(device); + return -1; + } + result = ORI_ObjectCreation(ori, txTypeRef, txParams, txParamList, num_txparams, txParamResult, &tx0, &RE_result); + if(RE_result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectCreation (txParams0.TxEUtraFDD/TDD) failed with error: %s (%s,%s,%s,%s,%s,%s,%s,%s,%s\n", ORI_Result_Print(result), + ORI_Result_Print(txParamResult[0]), + ORI_Result_Print(txParamResult[1]), + ORI_Result_Print(txParamResult[2]), + ORI_Result_Print(txParamResult[3]), + ORI_Result_Print(txParamResult[4]), + ORI_Result_Print(txParamResult[5]), + ORI_Result_Print(txParamResult[6]), + ORI_Result_Print(txParamResult[7]), + ORI_Result_Print(txParamResult[8])); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectCreation (txParams0.TxEUtraFDD/TDD): %s\n", ORI_Result_Print(RE_result)); + + + /* Create tx1 */ + if (openair0_cfg->tx_num_channels > 1) { + ORI_Object_s * tx1; + if (openair0_cfg->duplex_mode ==duplex_mode_FDD) txParams.TxEUtraFDD.antPort = ORI_FindObject(ori, ORI_ObjectType_AntennaPort, 1, NULL); + else txParams.TxEUtraTDD.antPort = ORI_FindObject(ori, ORI_ObjectType_AntennaPort, 1, NULL); + result = ORI_ObjectCreation(ori, txTypeRef, txParams, txParamList, num_txparams, txParamResult, &tx1, &RE_result); + if(RE_result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectCreation (txParams1.TxEUtraFDD/TDD) failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectCreation (txParams1.TxEUtraFDD/TDD): %s\n", ORI_Result_Print(RE_result)); + } + + + + /******************************************************************* + * RX PATHS CREATION + *******************************************************************/ + + /* Prepare parameters */ + ORI_ObjectTypeRef_s rxTypeRef = { NULL, openair0_cfg->duplex_mode == duplex_mode_FDD ? ORI_ObjectType_RxEUtraFDD : ORI_ObjectType_RxEUtraTDD}; + ORI_ObjectParams_u rxParams,rxParams1; + ORI_ObjectParam_e rxParamList[8] = { ORI_ObjectParam_SigPath_antPort, ORI_ObjectParam_SigPath_axcW, ORI_ObjectParam_SigPath_axcB, + ORI_ObjectParam_SigPath_chanBW, ORI_ObjectParam_SigPath_earfcn }; + ORI_Result_e rxParamResult[8]; + int num_rxparams = 5; + if (openair0_cfg->duplex_mode == duplex_mode_TDD) { + rxParamList[5] = ORI_ObjectParam_SigPath_tddULDLConfig; + rxParamList[6] = ORI_ObjectParam_SigPath_tddSpecialSFConfig; + rxParamList[7] = ORI_ObjectParam_RxSigPath_tddCPLengthUL; + num_rxparams = 8; + } + /* Create rx0 */ + ORI_Object_s * rx0; + if (openair0_cfg->duplex_mode == duplex_mode_FDD) { + rxParams.RxEUtraFDD.antPort = ORI_FindObject(ori, ORI_ObjectType_AntennaPort, 0, NULL); + rxParams.RxEUtraFDD.axcW = 1; + rxParams.RxEUtraFDD.axcB = 0; + rxParams.RxEUtraFDD.chanBW = 200; + rxParams.RxEUtraFDD.earfcn = 21350; + result = ORI_ObjectCreation(ori, rxTypeRef, rxParams, rxParamList, num_rxparams, rxParamResult, &rx0, &RE_result); + } + else { + rxParams.RxEUtraTDD.antPort = ORI_FindObject(ori, ORI_ObjectType_AntennaPort, 0, NULL); + rxParams.RxEUtraTDD.axcW = 1; + rxParams.RxEUtraTDD.axcB = 0; + rxParams.RxEUtraTDD.chanBW = txParams.TxEUtraTDD.chanBW; + rxParams.RxEUtraTDD.earfcn = txParams.TxEUtraTDD.earfcn; + rxParams.RxEUtraTDD.tddULDLConfig = 1; + rxParams.RxEUtraTDD.tddSpecialSFConfig = 1; + rxParams.RxEUtraTDD.tddCPLengthUL = ORI_tddCPLength_Normal; + + printf("AW2S: Creating RX0 for EARFCN %d\n",rxParams.RxEUtraTDD.earfcn); + + result = ORI_ObjectCreation(ori, rxTypeRef, rxParams, rxParamList, num_rxparams, rxParamResult, &rx0, &RE_result); + + } + + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectCreation (rxParams0.RxEUtraFDD/TDD) failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectCreation (rxParams0.RxEUtraFDD/TDD): %s\n", ORI_Result_Print(RE_result)); + + if (openair0_cfg->rx_num_channels > 1) { + /* Create rx1 */ + ORI_Object_s * rx1; + memcpy((void*)&rxParams1,(void*)&rxParams,sizeof(rxParams)); + if (openair0_cfg->duplex_mode == duplex_mode_FDD) rxParams1.RxEUtraFDD.antPort = ORI_FindObject(ori, ORI_ObjectType_AntennaPort, 1, NULL); + else rxParams1.RxEUtraTDD.antPort = ORI_FindObject(ori, ORI_ObjectType_AntennaPort, 1, NULL); + + result = ORI_ObjectCreation(ori, rxTypeRef, rxParams1, rxParamList, num_rxparams, rxParamResult, &rx1, &RE_result); + + + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectCreation (rxParams1.RxEUtraFDD/TDD) failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectCreation (rxParams1.RxEUtraFDD/TDD): %s\n", ORI_Result_Print(RE_result)); + } + + /* Create link */ + + ORI_ObjectParams_u linkParams; + ORI_ObjectParam_e linkParamList[3] = {ORI_ObjectParam_ORILink_AWS_remoteMAC, ORI_ObjectParam_ORILink_AWS_remoteIP,ORI_ObjectParam_ORILink_AWS_remoteUdpPort}; + ORI_Result_e linkParamResult[3]; + + ORI_Object_s *link= ORI_FindObject(ori, ORI_ObjectType_ORILink, 0, NULL); + linkParams.ORILink.AWS_remoteUdpPort = eth_params->my_portd; + + + if (get_mac_addr(eth_params->local_if_name,linkParams.ORILink.AWS_remoteMAC) < 0) return(-1); + inet_pton(AF_INET,eth_params->my_addr,(struct in_addr*)linkParams.ORILink.AWS_remoteIP); + result = ORI_ObjectParamModify(ori,link,linkParams,linkParamList,3,linkParamResult,&RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectParamModify (linkParams) failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + result = ORI_ObjectStateModification(ori, link, ORI_AST_Locked, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectStateModify failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + + printf("ORI_ObjectParamModify (linkParams): %s (%d,%d,%d)\n", ORI_Result_Print(RE_result),linkParamResult[0],linkParamResult[1],linkParamResult[2]); + + /******************************************************************* + * FULL OBJECT PARAMETERS UPDATE + *******************************************************************/ + + printf("\n\n\n========================================================\n"); + + result = ORI_ObjectParamReport(ori, NULL, 0, ORI_ObjectParam_All, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectParamReport failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectParamReport: %s\n", ORI_Result_Print(RE_result)); + + + + + + /******************************************************************* + * FULL OBJECT STATES UPDATE + *******************************************************************/ + + printf("\n\n\n========================================================\n"); + + result = ORI_ObjectStateReport(ori, NULL, 0, ORI_StateType_All, ORI_EventDrivenReport_True, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectStateReport failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectStateReport: %s\n", ORI_Result_Print(RE_result)); + + /* Print reported states for all objects (some objects have non-applicable states though) */ + numObjects = ORI_GetAllObjects(ori, objects, 100, NULL); + for(i=0; i %s / %s\n", ORI_ObjectType_Print(objects[i]->typeRef.type), objects[i]->instanceNumber, ORI_AST_Print(objects[i]->ast), ORI_FST_Print(objects[i]->fst)); + + + + + + /******************************************************************* + * FULL OBJECT FAULTS UPDATE + *******************************************************************/ + + printf("\n\n\n========================================================\n"); + + result = ORI_ObjectFaultReport(ori, NULL, 0, ORI_EventDrivenReport_True, &RE_result); + if(result != ORI_Result_SUCCESS) + { + printf("ORI_ObjectFaultReport failed with error: %s\n", ORI_Result_Print(result)); + aw2s_oricleanup(device); + return -1; + } + printf("ORI_ObjectFaultReport: %s\n", ORI_Result_Print(RE_result)); + + + /******************************************************************* + * PRINT STATES + *******************************************************************/ + + printf("\n\n\n========================================================\n"); + + /* Due to event driven reporting set to "true", the states modifications of the objects should be reflected back into the model. Print states for all objects (some objects have non-applicable states though) */ + numObjects = ORI_GetAllObjects(ori, objects, 100, NULL); + for(i=0; i %s / %s\n", ORI_ObjectType_Print(objects[i]->typeRef.type), objects[i]->instanceNumber, ORI_AST_Print(objects[i]->ast), ORI_FST_Print(objects[i]->fst)); + + + + + + return 0; +} + + +int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params ) { + + + device->thirdparty_init = aw2s_oriinit; + device->thirdparty_cleanup = aw2s_oricleanup; + device->thirdparty_startstreaming = aw2s_startstreaming; + + return(0); +} diff --git a/targets/ARCH/AW2SORI/ori.h b/targets/ARCH/AW2SORI/ori.h new file mode 100644 index 0000000000..d4a4f2cbbf --- /dev/null +++ b/targets/ARCH/AW2SORI/ori.h @@ -0,0 +1,2381 @@ +/** +* @file ori.h +* @brief Open Radio Interface (ORI) C library header file. +* @author AW2S (http://www.aw2s.com) +* @version 1.6 +* @date July 29, 2019 +* +* This file is the AW2S REC ORI C library header, and contains all necessary +* functions prototypes, enumerations, data structures and type definitions +* to implement the ORI shared library in an user application. +*/ + +#ifndef ORI_H_ +#define ORI_H_ + +#define ORILIB_VERSION_MAJOR 1 +#define ORILIB_VERSION_MINOR 6 + +#include + +/*----------------------------------------------------------------------------------------- + * ORI_RESULT ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_Result_e + * @brief ORI result codes enumeration. + */ +typedef enum +{ + ORI_Result_SUCCESS = 0, /**< */ + ORI_Result_FAIL_SYNTAX_ERROR, /**< */ + ORI_Result_FAIL_UNRECOGNIZED_MESSAGE, /**< */ + ORI_Result_FAIL_RE_BUSY, /**< */ + ORI_Result_FAIL_MISSING_PARAMETER, /**< */ + ORI_Result_FAIL_PARAMETER_ERROR, /**< */ + ORI_Result_FAIL_FRAME_ERROR, /**< */ + ORI_Result_FAIL_INVALID_TIMEDATA, /**< */ + ORI_Result_SUCCESS_SOFTWARE_ALREADY_EXISTING, /**< */ + ORI_Result_FAIL_FTP_ERROR, /**< */ + ORI_Result_FAIL_BROKEN_IMAGE, /**< */ + ORI_Result_FAIL_NO_COMPATIBLE_IMAGE, /**< */ + ORI_Result_FAIL_CANNOT_STORE, /**< */ + ORI_Result_FAIL_NOSUCH_IMAGE, /**< */ + ORI_Result_FAIL_UNKNOWN_OBJECT, /**< */ + ORI_Result_FAIL_UNKNOWN_PARAM, /**< */ + ORI_Result_FAIL_PARAMETER_FAIL, /**< */ + ORI_Result_FAIL_NOSUCH_RESOURCE, /**< */ + ORI_Result_FAIL_PARAM_READONLY, /**< */ + ORI_Result_FAIL_PARAM_LOCKREQUIRED, /**< */ + ORI_Result_FAIL_VALUE_OUTOF_RANGE, /**< */ + ORI_Result_FAIL_VALUE_TYPE_ERROR, /**< */ + ORI_Result_FAIL_UNKNOWN_OBJTYPE, /**< */ + ORI_Result_FAIL_STATIC_OBJTYPE, /**< */ + ORI_Result_FAIL_CHILD_NOTALLOWED, /**< */ + ORI_Result_FAIL_OUTOF_RESOURCES, /**< */ + ORI_Result_FAIL_LOCKREQUIRED, /**< */ + ORI_Result_FAIL_UNKNOWN_STATETYPE, /**< */ + ORI_Result_FAIL_UNKNOWN_STATEVALUE, /**< */ + ORI_Result_FAIL_STATE_READONLY, /**< */ + ORI_Result_FAIL_RESOURCE_UNAVAILABLE, /**< */ + ORI_Result_FAIL_RESOURCE_INUSE, /**< */ + ORI_Result_FAIL_PARENT_CHILD_CONFLICT, /**< */ + ORI_Result_FAIL_PRECONDITION_NOTMET, /**< */ + ORI_Result_FAIL_NOSUCH_FILE, /**< */ + ORI_Result_FAIL_SIZE_LIMIT, /**< */ + ORI_Result_FAIL_ACTIVATION_ERROR, /**< */ + ORI_Result_FAIL_ALD_UNAVAILABLE, /**< */ + ORI_Result_FAIL_BUS_UNAVAILABLE, /**< */ + ORI_Result_OsError, /**< */ + ORI_Result_BadParameter, /**< */ + ORI_Result_InvalidIpAddress, /**< */ + ORI_Result_ConnectionFailed, /**< */ + ORI_Result_ConnectionTimedOut, /**< */ + ORI_Result_NotConnected, /**< */ + ORI_Result_Unknown, /**< */ +} ORI_Result_e; + +/** + * @brief Get a string describing an ::ORI_Result_e. + * @param result The ::ORI_Result_e. + * @return The describing string. + */ +const char * ORI_Result_Print(ORI_Result_e result); + +/** + * @brief Get an ::ORI_Result_e from a string. + * @param resultString The string to match. + * @return The matched ::ORI_Result_e, or ::ORI_Result_Unknown if failure. + */ +ORI_Result_e ORI_Result_Enum(const char * resultString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_INDICATIONTYPE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_IndicationType_e + * @brief ORI indication type enumeration. + */ +typedef enum +{ + ORI_IndicationType_FileTransferComplete = 0, /**< */ + ORI_IndicationType_ObjectStateChange, /**< */ + ORI_IndicationType_FaultChange, /**< */ + ORI_IndicationType_FileAvailable, /**< */ + ORI_IndicationType_UploadFileCmpl, /**< */ + ORI_IndicationType_AisgScanDeviceCompl, /**< */ + ORI_IndicationType_AisgAldRx, /**< */ + ORI_IndicationType_Unknown, /**< */ +} ORI_IndicationType_e; + +/** + * @brief Get a string describing an ::ORI_IndicationType_e. + * @param indicationType The ::ORI_IndicationType_e. + * @return The describing string. + */ +const char * ORI_IndicationType_Print(ORI_IndicationType_e indicationType); + +/** + * @brief Get an ::ORI_IndicationType_e from a string. + * @param indicationTypeString The string to match. + * @return The matched ::ORI_IndicationType_e, or ::ORI_IndicationType_Unknown if failure. + */ +ORI_IndicationType_e ORI_IndicationType_Enum(const char * indicationTypeString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_OBJECTTYPE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_ObjectType_e + * @brief ORI object type enumeration. + */ +typedef enum +{ + ORI_ObjectType_RE = 0, /**< */ + ORI_ObjectType_AntennaPort, /**< */ + ORI_ObjectType_TxUtra, /**< */ + ORI_ObjectType_TxEUtraFDD, /**< */ + ORI_ObjectType_TxEUtraTDD, /**< */ + ORI_ObjectType_TxGSM, /**< */ + ORI_ObjectType_RxUtra, /**< */ + ORI_ObjectType_RxEUtraFDD, /**< */ + ORI_ObjectType_RxEUtraTDD, /**< */ + ORI_ObjectType_RxGSM, /**< */ + ORI_ObjectType_ORILink, /**< */ + ORI_ObjectType_ExternalEventPort, /**< */ + ORI_ObjectType_AISGPort, /**< */ + ORI_ObjectType_AISGALD, /**< */ + ORI_ObjectType_Log, /**< */ + ORI_ObjectType_DLRoutedIQData, /**< */ + ORI_ObjectType_ULRoutedIQData, /**< */ + ORI_ObjectType_DLRoutedCWBlock, /**< */ + ORI_ObjectType_ULRoutedCWBlock, /**< */ + ORI_ObjectType_Invalid, /**< */ +} ORI_ObjectType_e; + +/** + * @brief Get a string describing an ::ORI_ObjectType_e. + * @param objectType The ::ORI_ObjectType_e. + * @return The describing string. + */ +const char * ORI_ObjectType_Print(ORI_ObjectType_e objectType); + +/** + * @brief Get an ::ORI_ObjectType_e from a string. + * @param objectTypeString The string to match. + * @return The matched ::ORI_ObjectType_e, or ::ORI_ObjectType_Invalid if failure. + */ +ORI_ObjectType_e ORI_ObjectType_Enum(const char * objectTypeString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_OBJECTPARAM ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_ObjectParam_e + * @brief ORI object parameter enumeration. + * + * All the parameters of all objects are in this list, but only once + * (therefore some parameters will be used by several object types). + */ +typedef enum +{ + ORI_ObjectParam_RE_VendorID = 0, /**< */ + ORI_ObjectParam_RE_ProductID, /**< */ + ORI_ObjectParam_RE_ProductRevision, /**< */ + ORI_ObjectParam_RE_SerialNumber, /**< */ + ORI_ObjectParam_RE_ProtocolVer, /**< */ + ORI_ObjectParam_RE_AGCTargetLevCfgGran, /**< */ + ORI_ObjectParam_RE_AGCSettlingTimeCfgGran, /**< */ + ORI_ObjectParam_RE_AGCSettlingTimeCap, /**< */ + ORI_ObjectParam_RE_AWS_uptime, /**< */ + ORI_ObjectParam_RE_AWS_inputVoltage, /**< */ + ORI_ObjectParam_RE_AWS_inputCurrent, /**< */ + ORI_ObjectParam_RE_AWS_productTemp, /**< */ + ORI_ObjectParam_RE_AWS_cpuTemp, /**< */ + ORI_ObjectParam_RE_AWS_paTemp, /**< */ + ORI_ObjectParam_RE_AWS_rxPwrOffset, /**< */ + ORI_ObjectParam_Port_portLabel, /**< */ + ORI_ObjectParam_Port_AWS_outputPwr, /**< */ + ORI_ObjectParam_Port_AWS_inputPwr, /**< */ + ORI_ObjectParam_Port_AWS_returnLoss, /**< */ + ORI_ObjectParam_SigPath_axcW, /**< */ + ORI_ObjectParam_SigPath_axcB, /**< */ + ORI_ObjectParam_SigPath_oriLink, /**< */ + ORI_ObjectParam_SigPath_uarfcn, /**< */ + ORI_ObjectParam_SigPath_antPort, /**< */ + ORI_ObjectParam_SigPath_chanBW, /**< */ + ORI_ObjectParam_SigPath_tddSpecialSFConfig, /**< */ + ORI_ObjectParam_SigPath_tddULDLConfig, /**< */ + ORI_ObjectParam_SigPath_earfcn, /**< */ + ORI_ObjectParam_SigPath_freqBandInd, /**< */ + ORI_ObjectParam_SigPath_sigmaIQ, /**< */ + ORI_ObjectParam_SigPath_AWS_enableCompRateChange, /**< */ + ORI_ObjectParam_SigPath_AWS_enableCompBitChange, /**< */ + ORI_ObjectParam_SigPath_AWS_measuredPwr, /**< */ + ORI_ObjectParam_SigPath_AWS_axcIncr, /**< */ + ORI_ObjectParam_TxSigPath_t2a, /**< */ + ORI_ObjectParam_TxSigPath_maxTxPwr, /**< */ + ORI_ObjectParam_TxSigPath_dlCalRE, /**< */ + ORI_ObjectParam_TxSigPath_tddCPLengthDL, /**< */ + ORI_ObjectParam_TxSigPath_dlCalREMax, /**< */ + ORI_ObjectParam_TxSigPath_enableIQDLComp, /**< */ + ORI_ObjectParam_TxSigPath_AWS_enPeakCancel, /**< */ + ORI_ObjectParam_RxSigPath_ulCalREMax, /**< */ + ORI_ObjectParam_RxSigPath_ta3, /**< */ + ORI_ObjectParam_RxSigPath_ulCalRE, /**< */ + ORI_ObjectParam_RxSigPath_rtwpGroup, /**< */ + ORI_ObjectParam_RxSigPath_tddCPLengthUL, /**< */ + ORI_ObjectParam_RxSigPath_ulFeedAdj, /**< */ + ORI_ObjectParam_RxSigPath_ulTgtRMSLvl, /**< */ + ORI_ObjectParam_RxSigPath_ulAGCSetlgTime, /**< */ + ORI_ObjectParam_RxSigPath_TxSigPath, /**< */ + ORI_ObjectParam_RxSigPath_enableIQULComp, /**< */ + ORI_ObjectParam_ORILink_portRoleCapability, /**< */ + ORI_ObjectParam_ORILink_portRole, /**< */ + ORI_ObjectParam_ORILink_bitRateSupport, /**< */ + ORI_ObjectParam_ORILink_bitRateRequested, /**< */ + ORI_ObjectParam_ORILink_bitRateOperational, /**< */ + ORI_ObjectParam_ORILink_localPortID, /**< */ + ORI_ObjectParam_ORILink_remotePortID, /**< */ + ORI_ObjectParam_ORILink_toffset, /**< */ + ORI_ObjectParam_ORILink_oriLinkType, /**< */ + ORI_ObjectParam_ORILink_AWS_localMAC, /**< */ + ORI_ObjectParam_ORILink_AWS_remoteMAC, /**< */ + ORI_ObjectParam_ORILink_AWS_t14, /**< */ + ORI_ObjectParam_ORILink_AWS_remoteIP, /**< */ + ORI_ObjectParam_ORILink_AWS_localIP, /**< */ + ORI_ObjectParam_ORILink_AWS_remoteUdpPort, /**< */ + ORI_ObjectParam_ORILink_AWS_localUdpPort, /**< */ + ORI_ObjectParam_ORILink_AWS_sfpTxPow, /**< */ + ORI_ObjectParam_ORILink_AWS_sfpRxPow, /**< */ + ORI_ObjectParam_AISGPort_busPowerEnable, /**< */ + ORI_ObjectParam_AISGALD_deviceType, /**< */ + ORI_ObjectParam_AISGALD_UID, /**< */ + ORI_ObjectParam_AISGALD_releaseID, /**< */ + ORI_ObjectParam_AISGALD_aisgVersion, /**< */ + ORI_ObjectParam_AISGALD_deviceTypeVersion, /**< */ + ORI_ObjectParam_AISGALD_frameLength, /**< */ + ORI_ObjectParam_AISGALD_hdlcAdress, /**< */ + ORI_ObjectParam_Log_logTypeID, /**< */ + ORI_ObjectParam_Log_description, /**< */ + ORI_ObjectParam_Log_logCategory, /**< */ + ORI_ObjectParam_Log_maxREfileSize, /**< */ + ORI_ObjectParam_Log_maxRECfileSize, /**< */ + ORI_ObjectParam_Log_enableNotification, /**< */ + ORI_ObjectParam_Log_fileAvailable, /**< */ + ORI_ObjectParam_Log_overflowBehaviour, /**< */ + ORI_ObjectParam_Log_recordingEnabled, /**< */ + ORI_ObjectParam_Log_logPeriod, /**< */ + ORI_ObjectParam_Log_timerType, /**< */ + ORI_ObjectParam_Routed_MasterPortOriLink, /**< */ + ORI_ObjectParam_Routed_SlavePortOriLink, /**< */ + ORI_ObjectParam_RoutedIQData_IQsubBlockSize, /**< */ + ORI_ObjectParam_RoutedIQData_MasterPortIQblkW, /**< */ + ORI_ObjectParam_RoutedIQData_MasterPortIQblkB, /**< */ + ORI_ObjectParam_RoutedIQData_SlavePortIQW, /**< */ + ORI_ObjectParam_RoutedIQData_SlavePortIQB, /**< */ + ORI_ObjectParam_RoutedIQData_TBDelayDL, /**< */ + ORI_ObjectParam_RoutedIQData_TBDelayUL, /**< */ + ORI_ObjectParam_RoutedCWBlock_CtrlBlockSize, /**< */ + ORI_ObjectParam_RoutedCWBlock_SubChannelStart, /**< */ + ORI_ObjectParam_RoutedCWBlock_Ydepth, /**< */ + ORI_ObjectParam_RoutedCWBlock_SlavePortYoffset, /**< */ + ORI_ObjectParam_RoutedCWBlock_MasterPortYoffset, /**< */ + ORI_ObjectParam_All, /**< */ + ORI_ObjectParam_Invalid, /**< */ +} ORI_ObjectParam_e; + +/** + * @brief Get a string describing an ::ORI_ObjectParam_e. + * @param objectParam The ::ORI_ObjectParam_e. + * @return The describing string. + */ +const char * ORI_ObjectParam_Print(ORI_ObjectParam_e objectParam); + +/** + * @brief Get an ::ORI_ObjectParam_e from a string. + * @param objectParamString The string to match. + * @return The matched ::ORI_ObjectParam_e, or ::ORI_ObjectParam_Invalid if failure. + */ +ORI_ObjectParam_e ORI_ObjectParam_Enum(const char * objectParamString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_STATETYPE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_StateType_e + * @brief ORI state type enumeration. + */ +typedef enum +{ + ORI_StateType_AST = 0, /**< */ + ORI_StateType_FST, /**< */ + ORI_StateType_All, /**< */ + ORI_StateType_Invalid, /**< */ +} ORI_StateType_e; + +/** + * @brief Get a string describing an ::ORI_StateType_e. + * @param stateType The ::ORI_StateType_e. + * @return The describing string. + */ +const char * ORI_StateType_Print(ORI_StateType_e stateType); + +/** + * @brief Get an ::ORI_StateType_e from a string. + * @param stateTypeString The string to match. + * @return The matched ::ORI_StateType_e, or ::ORI_StateType_Invalid if failure. + */ +ORI_StateType_e ORI_StateType_Enum(const char * stateTypeString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_AST ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_AST_e + * @brief ORI AST enumeration. + */ +typedef enum +{ + ORI_AST_Locked = 0, /**< */ + ORI_AST_Unlocked, /**< */ + ORI_AST_Invalid, /**< */ +} ORI_AST_e; + +/** + * @brief Get a string describing an ::ORI_AST_e. + * @param ast The ::ORI_AST_e. + * @return The describing string. + */ +const char * ORI_AST_Print(ORI_AST_e ast); + +/** + * @brief Get an ::ORI_AST_e from a string. + * @param astString The string to match. + * @return The matched ::ORI_AST_e, or ::ORI_AST_Invalid if failure. + */ +ORI_AST_e ORI_AST_Enum(const char * astString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_FST ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_FST_e + * @brief ORI FST enumeration. + */ +typedef enum +{ + ORI_FST_PreOperational = 0, /**< */ + ORI_FST_Operational, /**< */ + ORI_FST_Degraded, /**< */ + ORI_FST_Failed, /**< */ + ORI_FST_NotOperational, /**< */ + ORI_FST_Disabled, /**< */ + ORI_FST_Invalid, /**< */ +} ORI_FST_e; + +/** + * @brief Get a string describing an ::ORI_FST_e. + * @param fst The ::ORI_FST_e. + * @return The describing string. + */ +const char * ORI_FST_Print(ORI_FST_e fst); + +/** + * @brief Get an ::ORI_FST_e from a string. + * @param fstString The string to match. + * @return The matched ::ORI_FST_e, or ::ORI_FST_Invalid if failure. + */ +ORI_FST_e ORI_FST_Enum(const char * fstString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_AGCGRANULARITY ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_agcGranularity_e + * @brief AGC granularity capability enumeration. + */ +typedef enum +{ + ORI_agcGranularity_RxSigPath = 0, /**< */ + ORI_agcGranularity_RE, /**< */ + ORI_agcGranularity_Invalid, /**< */ +} ORI_agcGranularity_e; + +/** + * @brief Get a string describing an ::ORI_agcGranularity_e. + * @param agcGranularity The ::ORI_agcGranularity_e. + * @return The describing string. + */ +const char * ORI_agcGranularity_Print(ORI_agcGranularity_e agcGranularity); + +/** + * @brief Get an ::ORI_agcGranularity_e from a string. + * @param agcGranularityString The string to match. + * @return The matched ::ORI_agcGranularity_e, or ::ORI_agcGranularity_Invalid if failure. + */ +ORI_agcGranularity_e ORI_agcGranularity_Enum(const char * agcGranularityString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_TDDCPLENGTH ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_tddCPLength_e + * @brief TDD cyclic prefix length enumeration. + */ +typedef enum +{ + ORI_tddCPLength_Normal = 0, /**< */ + ORI_tddCPLength_Extended, /**< */ + ORI_tddCPLength_Invalid, /**< */ +} ORI_tddCPLength_e; + +/** + * @brief Get a string describing an ::ORI_tddCPLength_e. + * @param tddCPLength The ::ORI_tddCPLength_e. + * @return The describing string. + */ +const char * ORI_tddCPLength_Print(ORI_tddCPLength_e tddCPLength); + +/** + * @brief Get a ::ORI_tddCPLength_e from a string. + * @param tddCPLengthString The string to match. + * @return The matched ::ORI_tddCPLength_e, or ::ORI_tddCPLength_Invalid if failure. + */ +ORI_tddCPLength_e ORI_tddCPLength_Enum(const char * tddCPLengthString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_FREQBAND ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_freqBand_e + * @brief GSM frequency band enumeration. + */ +typedef enum +{ + ORI_freqBand_GSM850 = 0, /**< */ + ORI_freqBand_PGSM900, /**< */ + ORI_freqBand_DCS1800, /**< */ + ORI_freqBand_PCS1900, /**< */ + ORI_freqBand_Invalid, /**< */ +} ORI_freqBand_e; + +/** + * @brief Get a string describing an ::ORI_freqBand_e. + * @param freqBand The ::ORI_freqBand_e. + * @return The describing string. + */ +const char * ORI_freqBand_Print(ORI_freqBand_e freqBand); + +/** + * @brief Get a ::ORI_freqBand_e from a string. + * @param freqBandString The string to match. + * @return The matched ::ORI_freqBand_e, or ::ORI_freqBand_Invalid if failure. + */ +ORI_freqBand_e ORI_freqBand_Enum(const char * freqBandString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_PORTROLE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_portRole_e + * @brief ORI link port role enumeration. + */ +typedef enum +{ + ORI_portRole_Master = 0, /**< */ + ORI_portRole_Slave, /**< */ + ORI_portRole_Invalid, /**< */ +} ORI_portRole_e; + +/** + * @brief Get a string describing an ::ORI_portRole_e. + * @param portRole The ::ORI_portRole_e. + * @return The describing string. + */ +const char * ORI_portRole_Print(ORI_portRole_e portRole); + +/** + * @brief Get a ::ORI_portRole_e from a string. + * @param portRoleString The string to match. + * @return The matched ::ORI_portRole_e, or ::ORI_portRole_Invalid if failure. + */ +ORI_portRole_e ORI_portRole_Enum(const char * portRoleString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_PORTROLECAPABILITY ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_portRoleCapability_e + * @brief ORI Link port role capability enumeration. + */ +typedef enum +{ + ORI_portRoleCapability_MO = 0, /**< */ + ORI_portRoleCapability_SO, /**< */ + ORI_portRoleCapability_MS, /**< */ + ORI_portRoleCapability_Invalid, /**< */ +} ORI_portRoleCapability_e; + +/** + * @brief Get a string describing an ::ORI_portRoleCapability_e. + * @param portRoleCapability The ::ORI_portRoleCapability_e. + * @return The describing string. + */ +const char * ORI_portRoleCapability_Print(ORI_portRoleCapability_e portRoleCapability); + +/** + * @brief Get an ::ORI_portRoleCapability_e from a string. + * @param portRoleCapabilityString The string to match. + * @return The matched ::ORI_portRoleCapability_e, or ::ORI_portRoleCapability_Invalid if failure. + */ +ORI_portRoleCapability_e ORI_portRoleCapability_Enum(const char * portRoleCapabilityString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_LINKTYPE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_linkType_e + * @brief ORI Link type enumeration. + */ +typedef enum +{ + ORI_linkType_Active = 0, /**< */ + ORI_linkType_Passive, /**< */ + ORI_linkType_Invalid, /**< */ +} ORI_linkType_e; + + +/** + * @brief Get a string describing an ::ORI_linkType_e. + * @param linkType The ::ORI_linkType_e. + * @return The describing string. + */ +const char * ORI_linkType_Print(ORI_linkType_e linkType); + +/** + * @brief Get an ::ORI_linkType_e from a string. + * @param linkTypeString The string to match. + * @return The matched ::ORI_linkType_e, or ::ORI_linkType_Invalid if failure. + */ +ORI_linkType_e ORI_linkType_Enum(const char * linkTypeString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_BOOLEAN ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_Boolean_e + * @brief ORI boolean enumeration. + */ +typedef enum +{ + ORI_Boolean_False = 0, /**< */ + ORI_Boolean_True, /**< */ + ORI_Boolean_Invalid, /**< */ +} ORI_Boolean_e; + +/** + * @brief Get a string describing an ::ORI_Boolean_e. + * @param boolean The ::ORI_Boolean_e. + * @return The describing string. + */ +const char * ORI_Boolean_Print(ORI_Boolean_e boolean); + +/** + * @brief Get an ::ORI_Boolean_e from a string. + * @param booleanString The string to match. + * @return The matched ::ORI_Boolean_e, or ::ORI_Boolean_Invalid if failure. + */ +ORI_Boolean_e ORI_Boolean_Enum(const char * booleanString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_LOGCATEGORY ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_logCategory_e + * @brief Log category enumeration. + * + */ +typedef enum +{ + ORI_logCategory_Fault = 0, /**< */ + ORI_logCategory_Perf, /**< */ + ORI_logCategory_System, /**< */ + ORI_logCategory_Crash, /**< */ + ORI_logCategory_Application, /**< */ + ORI_logCategory_Debug, /**< */ + ORI_logCategory_Other, /**< */ + ORI_logCategory_Invalid, /**< */ +} ORI_logCategory_e; + +/** + * @brief Get a string describing an ::ORI_logCategory_e. + * @param logCategory The ::ORI_logCategory_e. + * @return The describing string. + */ +const char * ORI_logCategory_Print(ORI_logCategory_e logCategory); + +/** + * @brief Get an ::ORI_logCategory_e from a string. + * @param logCategoryString The string to match. + * @return The matched ::ORI_logCategory_e, or ::ORI_logCategory_Invalid if failure. + */ +ORI_logCategory_e ORI_logCategory_Enum(const char * logCategoryString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_OVERFLOWBEHAVIOUR ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_overflowBehaviour_e + * @brief Log overflow behaviour enumeration. + * + */ +typedef enum +{ + ORI_overflowBehaviour_Stop = 0, /**< */ + ORI_overflowBehaviour_Fifo, /**< */ + ORI_overflowBehaviour_Invalid, /**< */ +} ORI_overflowBehaviour_e; + +/** + * @brief Get a string describing an ::ORI_overflowBehaviour_e. + * @param overflowBehaviour The ::ORI_overflowBehaviour_e. + * @return The describing string. + */ +const char * ORI_overflowBehaviour_Print(ORI_overflowBehaviour_e overflowBehaviour); + +/** + * @brief Get an ::ORI_overflowBehaviour_e from a string. + * @param overflowBehaviourString The string to match. + * @return The matched ::ORI_overflowBehaviour_e, or ::ORI_overflowBehaviour_Invalid if failure. + */ +ORI_overflowBehaviour_e ORI_overflowBehaviour_Enum(const char * overflowBehaviourString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_TIMERTYPE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_timerType_e + * @brief Log timer type enumeration. + */ +typedef enum +{ + ORI_timerType_OneShot = 0, /**< */ + ORI_timerType_Periodic, /**< */ + ORI_timerType_Invalid, /**< */ +} ORI_timerType_e; + +/** + * @brief Get a string describing an ::ORI_timerType_e. + * @param timerType The ::ORI_timerType_e. + * @return The describing string. + */ +const char * ORI_timerType_Print(ORI_timerType_e timerType); + +/** + * @brief Get an ::ORI_timerType_e from a string. + * @param timerTypeString The string to match. + * @return The matched ::ORI_timerType_e, or ::ORI_timerType_Invalid if failure. + */ +ORI_timerType_e ORI_timerType_Enum(const char * timerTypeString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_FAULTTYPE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_FaultType_e + * @brief ORI fault types enumeration. + */ +typedef enum +{ + ORI_FaultType_RE_ExtSupplyUnderVolt = 0, /**< */ + ORI_FaultType_RE_OverTemp, /**< */ + ORI_FaultType_RE_DigInOverdrive, /**< */ + ORI_FaultType_RE_RFOutOverdrive, /**< */ + ORI_FaultType_RE_TXGainFail, /**< */ + ORI_FaultType_RE_RXGainFail, /**< */ + ORI_FaultType_AntennaPort_VSWROutOfRange, /**< */ + ORI_FaultType_AntennaPort_NonAisgTmaMalfct, /**< */ + ORI_FaultType_ORILink_LinkFail, /**< */ + ORI_FaultType_ORILink_PortFail, /**< */ + ORI_FaultType_ORILink_SyncFail, /**< */ + ORI_FaultType_AISGPort_AisgMalfct, /**< */ + ORI_FaultType_Invalid, +} ORI_FaultType_e; + +/** + * @brief Get a string describing an ::ORI_FaultType_e. + * @param faultType The ::ORI_FaultType_e. + * @return The describing string. + */ +const char * ORI_FaultType_Print(ORI_FaultType_e faultType); + +/** + * @brief Get an ::ORI_FaultType_e from a string. + * @param faultTypeString The string to match. + * @return The matched ::ORI_FaultType_e, or ::ORI_FaultType_Invalid if failure. + */ +ORI_FaultType_e ORI_FaultType_Enum(const char * faultTypeString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_FAULTSTATE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_FaultState_e + * @brief ORI RE fault state enumeration. + */ +typedef enum +{ + ORI_FaultState_Cleared = 0, /**< */ + ORI_FaultState_Active, /**< */ + ORI_FaultState_Unknown, /**< */ +} ORI_FaultState_e; + +/** + * @brief Get a string describing an ::ORI_FaultState_e. + * @param faultState The ::ORI_FaultState_e. + * @return The describing string. + */ +const char * ORI_FaultState_Print(ORI_FaultState_e faultState); + +/** + * @brief Get an ::ORI_FaultState_e from a string. + * @param faultStateString The string to match. + * @return The matched ::ORI_FaultState_e, or ::ORI_FaultState_Unknown if failure. + */ +ORI_FaultState_e ORI_FaultState_Enum(const char * faultStateString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_FAULTSEVERITY ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_FaultSeverity_e + * @brief ORI RE fault severity enumeration. + */ +typedef enum +{ + ORI_FaultSeverity_Failed = 0, /**< */ + ORI_FaultSeverity_Degraded, /**< */ + ORI_FaultSeverity_Warning, /**< */ + ORI_FaultSeverity_Unknown, /**< */ +} ORI_FaultSeverity_e; + +/** + * @brief Get a string describing an ::ORI_FaultSeverity_e. + * @param faultSeverity The ::ORI_FaultSeverity_e. + * @return The describing string. + */ +const char * ORI_FaultSeverity_Print(ORI_FaultSeverity_e faultSeverity); + +/** + * @brief Get an ::ORI_FaultSeverity_e from a string. + * @param faultSeverityString The string to match. + * @return The matched ::ORI_FaultSeverity_e, or ::ORI_FaultSeverity_Unknown if failure. + */ +ORI_FaultSeverity_e ORI_FaultSeverity_Enum(const char * faultSeverityString); + + + +/*----------------------------------------------------------------------------------------- + * ORI_EVENTDRIVENREPORT ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_EventDrivenReport_e + * @brief Event driven reporting enumeration. + */ +typedef enum +{ + ORI_EventDrivenReport_NoModify = 0, /**< */ + ORI_EventDrivenReport_True, /**< */ + ORI_EventDrivenReport_False, /**< */ + ORI_EventDrivenReport_Invalid, /**< */ +} ORI_EventDrivenReport_e; + + + +/*----------------------------------------------------------------------------------------- + * ORI_AISGLAYER7COMMAND ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_AisgLayer7Command_e + * @brief Aisg Layer7 commands byte code enumeration. + */ +typedef enum +{ + ORI_AisgLayer7Command_Unknown = 0, /**< */ + /* Common procedures */ + ORI_AisgLayer7Command_Reset = 0x03, /**< */ + ORI_AisgLayer7Command_GetAlarmStatus = 0x04, /**< */ + ORI_AisgLayer7Command_GetInfo = 0x05, /**< */ + ORI_AisgLayer7Command_ClearActiveAlarms = 0x06, /**< */ + ORI_AisgLayer7Command_SelfTest = 0x0A, /**< */ + ORI_AisgLayer7Command_ReadUserData = 0x10, /**< */ + ORI_AisgLayer7Command_WriteUserData = 0x11, /**< */ + ORI_AisgLayer7Command_AlarmSubscribe = 0x12, /**< */ + ORI_AisgLayer7Command_DownloadStart = 0x40, /**< */ + ORI_AisgLayer7Command_DownloadApplication = 0x41, /**< */ + ORI_AisgLayer7Command_DownloadEnd = 0x42, /**< */ + /* Single Antenna RET procedures */ + ORI_AisgLayer7Command_RetSingle_AlarmIndication = 0x07, /**< */ + ORI_AisgLayer7Command_RetSingle_SetDeviceData = 0x0E, /**< */ + ORI_AisgLayer7Command_RetSingle_GetDeviceData = 0x0F, /**< */ + ORI_AisgLayer7Command_RetSingle_Calibrate = 0x31, /**< */ + ORI_AisgLayer7Command_RetSingle_SendConfigData = 0x32, /**< */ + ORI_AisgLayer7Command_RetSingle_SetTilt = 0x33, /**< */ + ORI_AisgLayer7Command_RetSingle_GetTilt = 0x34, /**< */ + /* Multi Antenna RET procedures */ + ORI_AisgLayer7Command_RetMulti_Calibrate = 0x80, /**< */ + ORI_AisgLayer7Command_RetMulti_SetTilt = 0x81, /**< */ + ORI_AisgLayer7Command_RetMulti_GetTilt = 0x82, /**< */ + ORI_AisgLayer7Command_RetMulti_SetDeviceData = 0x83, /**< */ + ORI_AisgLayer7Command_RetMulti_GetDeviceData = 0x84, /**< */ + ORI_AisgLayer7Command_RetMulti_AlarmIndication = 0x85, /**< */ + ORI_AisgLayer7Command_RetMulti_ClearActiveAlarms= 0x86, /**< */ + ORI_AisgLayer7Command_RetMulti_GetAlarmStatus = 0x87, /**< */ + ORI_AisgLayer7Command_RetMulti_GetNbrAntenna = 0x88, /**< */ + ORI_AisgLayer7Command_RetMulti_SendConfigData = 0x89, /**< */ + /* added specific command to check the existence of the aisg port from the model (this is not a real aisg command!) */ + ORI_AisgLayer7Command_CheckAisgPortExist = 0xFE, /**< */ + /* added specific command to get the aisg ALD device type from the model (this is not a real aisg command!) */ + ORI_AisgLayer7Command_GetDeviceType = 0xFF, /**< */ +} ORI_AisgLayer7Command_e; + + +/*----------------------------------------------------------------------------------------- + * ORI_AISGRETURNCODE ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_AisgReturnCode_e + * @brief Aisg return code enumeration. + */ +typedef enum +{ + ORI_AisgReturnCode_OK = 0, /**< */ + ORI_AisgReturnCode_MotorJam = 0x02, /**< */ + ORI_AisgReturnCode_ActuatorJam = 0x03, /**< */ + ORI_AisgReturnCode_Busy = 0x05, /**< */ + ORI_AisgReturnCode_Checksum = 0x06, /**< */ + ORI_AisgReturnCode_FAIL = 0x0B, /**< */ + ORI_AisgReturnCode_NotCalibrated = 0x0E, /**< */ + ORI_AisgReturnCode_NotConfigured = 0x0F, /**< */ + ORI_AisgReturnCode_Hardware = 0x11, /**< */ + ORI_AisgReturnCode_OutOfRange = 0x13, /**< */ + ORI_AisgReturnCode_UnknownProcedure = 0x19, /**< */ + ORI_AisgReturnCode_ReadOnly = 0x1D, /**< */ + ORI_AisgReturnCode_UnknownParameter = 0x1E, /**< */ + ORI_AisgReturnCode_WorkingSWMissing = 0x21, /**< */ + ORI_AisgReturnCode_InvalidFileContent = 0x22, /**< */ + ORI_AisgReturnCode_FormatError = 0x24, /**< */ + ORI_AisgReturnCode_UnsupportedProcedure = 0x25, /**< */ + ORI_AisgReturnCode_InvalidProcedureSeq = 0x26, /**< */ + ORI_AisgReturnCode_ActuatorInterference = 0x27, /**< */ + ORI_AisgReturnCode_Unknown, +} ORI_AisgReturnCode_e; + +/** + * @brief Get a string describing an ::ORI_AisgReturnCode_e. + * @param returnCode The ::ORI_AisgReturnCode_e. + * @return The describing string. + */ +const char * ORI_AisgReturnCode_Print(ORI_AisgReturnCode_e returnCode); + +/** + * @brief Get an ::ORI_AisgReturnCode_e from a string. + * @param returnCodeString The string to match. + * @return The matched ::ORI_AisgReturnCode_e, or ::ORI_AisgReturnCode_Unknown if failure. + */ +ORI_AisgReturnCode_e ORI_AisgReturnCode_Enum(const char * returnCodeString); + + +/*----------------------------------------------------------------------------------------- + * ORI_AISGDEVICEDATA ENUMERATION + *-----------------------------------------------------------------------------------------*/ + +/** + * @enum ORI_AisgDeviceData_e + * @brief Aisg device data fields enumeration. + */ +typedef enum +{ + ORI_AisgDeviceData_AntennaModelNbr = 1, /**< */ + ORI_AisgDeviceData_AntennaSerialNbr = 2, /**< */ + ORI_AisgDeviceData_AntennaFreqBand = 3, /**< */ + ORI_AisgDeviceData_BeamwidthBand = 4, /**< */ + ORI_AisgDeviceData_GainBand = 5, /**< */ + ORI_AisgDeviceData_MaxTilt = 6, /**< */ + ORI_AisgDeviceData_MinTilt = 7, /**< */ + ORI_AisgDeviceData_InstallationDate = 0x21, /**< */ + ORI_AisgDeviceData_InstallerID = 0x22, /**< */ + ORI_AisgDeviceData_BasestationID = 0x23, /**< */ + ORI_AisgDeviceData_SectorID = 0x24, /**< */ + ORI_AisgDeviceData_AntennaBearing = 0x25, /**< */ + ORI_AisgDeviceData_MechanicalTilt = 0x26, /**< */ + ORI_AisgDeviceData_Unknown, +} ORI_AisgDeviceData_e; + +/** + * @brief Get a string describing an ::ORI_AisgDeviceData_e. + * @param field The ::ORI_AisgDeviceData_e. + * @return The describing string. + */ +const char * ORI_AisgDeviceDataField_Print(ORI_AisgDeviceData_e field); + +/** + * @brief Get an ::ORI_AisgDeviceData_e from a string. + * @param fieldString The string to match. + * @return The matched ::ORI_AisgDeviceData_e, or ::ORI_AisgDeviceData_Unknown if failure. + */ +ORI_AisgDeviceData_e ORI_AisgDeviceDataField_Enum(const char * fieldString); + + + +/*----------------------------------------------------------------------------------------- + * OBJECT TYPE REFERENCE + *-----------------------------------------------------------------------------------------*/ + +/* Forward declaration of the ORI_Object_s structure. */ +typedef struct ORI_Object_s ORI_Object_s; + +/** + * @struct ORI_ObjectTypeRef_s + * @brief Object type reference structure. + * + * This structure represents an ORI ObjectTypeRef, which does not fully describe an ORI object + * because it is not associated to an instance number. + */ + typedef struct +{ + ORI_Object_s * parent; /**< Parent object reference, may be NULL if no parent. */ + ORI_ObjectType_e type; /**< Object type. */ +} ORI_ObjectTypeRef_s; + + + + + +/*----------------------------------------------------------------------------------------- + * OBJECT PARAMETERS + *-----------------------------------------------------------------------------------------*/ + +/** + * @struct ORI_ObjectParams_RE_s + * @brief Structure containing the parameters of a RE object. + */ +typedef struct +{ + char vendorID[4]; /**< RO. Vendor ID as signaled in DHCP code 201, normally 3 characters */ + char productID[81]; /**< RO. RE product ID.*/ + char productRev[81]; /**< RO. RE product revision. */ + char serialNumber[41]; /**< RO. RE serial number. */ + char protocolVer[11]; /**< RO. OCP protocol supported. */ + ORI_agcGranularity_e agcTargetLevCfgGran; /**< RO. UL AGC target RMS level config granularity. */ + ORI_agcGranularity_e agcSettlTimeCfgGran; /**< RO. UL AGC settling time config granularity. */ + uint16_t agcSettlTimeCap; /**< RO. UL AGC settling time capability. */ + uint32_t AWS_uptime; /**< RO. AW2S Vendor specific: Uptime since boot in seconds. */ + int32_t AWS_inputVoltage; /**< RO. AW2S Vendor specific: RE input voltage in mV. */ + int32_t AWS_inputCurrent; /**< RO. AW2S Vendor specific: RE input current in mA. */ + int16_t AWS_productTemp; /**< RO. AW2S Vendor specific: RE temperature in degC. */ + int16_t AWS_cpuTemp; /**< RO. AW2S Vendor specific: CPU temperature in degC. */ + int16_t AWS_paTemp; /**< RO. AW2S Vendor specific: Power amplifier temperature in degC. */ + int16_t AWS_rxPwrOffset; /**< RO. AW2S Vendor specific: Receiver dBFS to dBm power conversion offset, unit is dB/10 (e.g. -340 for -34 dB). */ +} ORI_ObjectParams_RE_s; + +/** + * @struct ORI_ObjectParams_AntennaPort_s + * @brief Structure containing the parameters of an Antenna Port object. + */ +typedef struct +{ + char portLabel[81]; /**< RO. Physical antenna port label.*/ + int16_t AWS_outputPwr; /**< RO. AW2S Vendor specific: Measured output power for this antenna, unit is dBm/10 (e.g. 400 for 40 dBm). */ + int16_t AWS_inputPwr; /**< RO. AW2S Vendor specific: Measured input power for this antenna, unit is dBm/10 (e.g. -650 for -65 dBm). */ + int16_t AWS_returnLoss; /**< RO. AW2S Vendor specific: Measured return loss for this antenna, unit is dB/10 (e.g. 50 for 5 dB). */ +} ORI_ObjectParams_AntennaPort_s; + +/** + * @struct ORI_ObjectParams_TxSigPathUtra_s + * @brief Structure containing the parameters of a TxSigPath UTRAFDD object. + */ +typedef struct +{ + uint16_t dlCalREMax; /**< RO. Max possible buffer in RE for DL timing calibration in Tc/16.*/ + uint32_t t2a; /**< RO. RE time delay. */ + uint16_t dlCalRE; /**< RW-Locked. Time delay to enable DL timing calibration in Tc/16. */ + int16_t maxTxPwr; /**< RW. Max tx power for this path, unit is dBm/10 (e.g. 400 for 40 dBm). */ + uint8_t axcW; /**< RW-Locked. AxC W parameter. */ + uint8_t axcB; /**< RW-Locked. AxC B parameter. */ + ORI_Object_s * oriLink; /**< RW-Locked. ORI Link on which the AxC is mapped. */ + uint32_t uarfcn; /**< RW-Locked. Downlink UARFCN. */ + ORI_Object_s * antPort; /**< RW-Locked. Reference Antenna port for this signal. */ + int16_t AWS_measuredPwr; /**< RO. AW2S Vendor specific: Measured Tx power for this path, unit is dBm/10 (e.g. 400 for 40 dBm). */ + uint16_t AWS_axcIncr; /**< RW-Locked. AW2S Vendor specific: AxC increment for each sample, 0 means auto (= packed, no interleaving). */ + ORI_Boolean_e AWS_enPeakCancel; /**< RW-Locked. AW2S Vendor specific: Peak-Cancellation CFR enablement. */ +} ORI_ObjectParams_TxSigPathUtra_s; + +/** + * @struct ORI_ObjectParams_TxSigPathEUtraFDD_s + * @brief Structure containing the parameters of a TxSigPath EUTRAFDD object. + */ +typedef struct +{ + uint16_t chanBW; /**< RW-Locked. Channel bandwith in MHz/10 (14 / 30 / 50 / 100 / 150 / 200). */ + uint16_t dlCalREMax; /**< RO. Max possible buffer in RE for DL timing calibration in Tc/16.*/ + uint32_t t2a; /**< RO. RE time delay. */ + uint16_t dlCalRE; /**< RW-Locked. Time delay to enable DL timing calibration in Tc/16. */ + int16_t maxTxPwr; /**< RW. Max tx power for this path, unit is dBm/10 (e.g. 400 for 40 dBm). */ + uint8_t axcW; /**< RW-Locked. AxC W parameter. */ + uint8_t axcB; /**< RW-Locked. AxC B parameter. */ + ORI_Object_s * oriLink; /**< RW-Locked. ORI Link on which the AxC is mapped. */ + uint32_t earfcn; /**< RW-Locked. Downlink EARFCN. */ + ORI_Object_s * antPort; /**< RW-Locked. Reference Antenna port for this signal. */ + ORI_Boolean_e enableIQDLComp; /**< RW-Locked. IQ data compression enablement. */ + uint32_t sigmaIQ; /**< RW-Locked. Sigma IQ value for IQ data compression. */ + ORI_Boolean_e AWS_enableCompRateChange; /**< RW-Locked. AW2S Vendor specific: Enable IQ data compression sample rate change. */ + ORI_Boolean_e AWS_enableCompBitChange; /**< RW-Locked. AW2S Vendor specific: Enable IQ data compression bit width change. */ + int16_t AWS_measuredPwr; /**< RO. AW2S Vendor specific: Measured Tx power for this path, unit is dBm/10 (e.g. 400 for 40 dBm). */ + uint16_t AWS_axcIncr; /**< RW-Locked. AW2S Vendor specific: AxC increment for each sample, 0 means auto (= packed, no interleaving). */ + ORI_Boolean_e AWS_enPeakCancel; /**< RW-Locked. AW2S Vendor specific: Peak-Cancellation CFR enablement. */ +} ORI_ObjectParams_TxSigPathEUtraFDD_s; + +/** + * @struct ORI_ObjectParams_TxSigPathEUtraTDD_s + * @brief Structure containing the parameters of a TxSigPath EUTRATDD object. + */ +typedef struct +{ + uint16_t chanBW; /**< RW-Locked. Channel bandwith in MHz/10 (14 / 30 / 50 / 100 / 150 / 200). */ + uint8_t tddULDLConfig; /**< RW-Locked. TDD UL/DL config. */ + uint8_t tddSpecialSFConfig; /**< RW-Locked. TDD SSF config. */ + ORI_tddCPLength_e tddCPLengthDL; /**< RW-Locked. TDD Cyclic prefix length. */ + uint16_t dlCalREMax; /**< RO. Max possible buffer in RE for DL timing calibration in Tc/16.*/ + uint32_t t2a; /**< RO. RE time delay. */ + uint16_t dlCalRE; /**< RW-Locked. Time delay to enable DL timing calibration in Tc/16. */ + int16_t maxTxPwr; /**< RW. Max tx power for this path, unit is dBm/10 (e.g. 400 for 40 dBm). */ + uint8_t axcW; /**< RW-Locked. AxC W parameter. */ + uint8_t axcB; /**< RW-Locked. AxC B parameter. */ + ORI_Object_s * oriLink; /**< RW-Locked. ORI Link on which the AxC is mapped. */ + uint32_t earfcn; /**< RW-Locked. Downlink EARFCN. */ + ORI_Object_s * antPort; /**< RW-Locked. Reference Antenna port for this signal. */ + ORI_Boolean_e enableIQDLComp; /**< RW-Locked. IQ data compression enablement. */ + uint32_t sigmaIQ; /**< RW-Locked. Sigma IQ value for IQ data compression. */ + ORI_Boolean_e AWS_enableCompRateChange; /**< RW-Locked. AW2S Vendor specific: Enable IQ data compression sample rate change. */ + ORI_Boolean_e AWS_enableCompBitChange; /**< RW-Locked. AW2S Vendor specific: Enable IQ data compression bit width change. */ + int16_t AWS_measuredPwr; /**< RO. AW2S Vendor specific: Measured Tx power for this path, unit is dBm/10 (e.g. 400 for 40 dBm). */ + uint16_t AWS_axcIncr; /**< RW-Locked. AW2S Vendor specific: AxC increment for each sample, 0 means auto (= packed, no interleaving). */ + ORI_Boolean_e AWS_enPeakCancel; /**< RW-Locked. AW2S Vendor specific: Peak-Cancellation CFR enablement. */ +} ORI_ObjectParams_TxSigPathEUtraTDD_s; + +/** + * @struct ORI_ObjectParams_TxSigPathGSM_s + * @brief Structure containing the parameters of a TxSigPath GSM object. + */ +typedef struct +{ + uint16_t dlCalREMax; /**< RO. Max possible buffer in RE for DL timing calibration in Tc/16.*/ + ORI_freqBand_e freqBandInd; /**< GSM frequency band indicator. */ + uint32_t t2a; /**< RO. RE time delay. */ + uint16_t dlCalRE; /**< RW-Locked. Time delay to enable DL timing calibration in Tc/16. */ + int16_t maxTxPwr; /**< RW. Max tx power for this path, unit is dBm/10 (e.g. 400 for 40 dBm). */ + uint8_t axcW; /**< RW-Locked. AxC W parameter. */ + uint8_t axcB; /**< RW-Locked. AxC B parameter. */ + ORI_Object_s * oriLink; /**< RW-Locked. ORI Link on which the AxC is mapped. */ + ORI_Object_s * antPort; /**< RW-Locked. Reference Antenna port for this signal. */ + int16_t AWS_measuredPwr; /**< RO. AW2S Vendor specific: Measured Tx power for this path, unit is dBm/10 (e.g. 400 for 40 dBm). */ + uint16_t AWS_axcIncr; /**< RW-Locked. AW2S Vendor specific: AxC increment for each sample, 0 means auto (= packed, no interleaving). */ + ORI_Boolean_e AWS_enPeakCancel; /**< RW-Locked. AW2S Vendor specific: Peak-Cancellation CFR enablement. */ +} ORI_ObjectParams_TxSigPathGSM_s; + +/** + * @struct ORI_ObjectParams_RxSigPathUtra_s + * @brief Structure containing the parameters of a RxSigPath UTRAFDD object. + */ +typedef struct +{ + uint16_t ulCalREMax; /**< RO. Max possible buffer in RE for UL timing calibration in Tc/2.*/ + uint32_t ta3; /**< RO. RE time delay. */ + uint16_t ulCalRE; /**< RW-Locked. Time delay to enable UL timing calibration in Tc/2. */ + uint8_t axcW; /**< RW-Locked. AxC W parameter. */ + uint8_t axcB; /**< RW-Locked. AxC B parameter. */ + uint8_t rtwpGroup; /**< RW-Locked. Location of the RTWP measurements for this AxC. */ + ORI_Object_s * oriLink; /**< RW-Locked. ORI Link on which the AxC is mapped. */ + ORI_Object_s * antPort; /**< RW-Locked. Reference Antenna port for this signal. */ + uint32_t uarfcn; /**< RW-Locked. Uplink UARFCN. */ + int16_t ulFeedAdj; /**< RW. Uplink feeder adjustment in dB/10 (e.g. 200 for 20 dB). */ + uint8_t ulTgtRMSLvl; /**< RW-Locked. Uplink target RMS level. */ + uint8_t ulAGCSetlgTime; /**< RW-Locked. Uplink AGC settling time. */ + int16_t AWS_measuredPwr; /**< RO. AW2S Vendor specific: Measured Rx power for this path, unit is dBm/10 (e.g. -650 for -65 dBm). */ + uint16_t AWS_axcIncr; /**< RW-Locked. AW2S Vendor specific: AxC increment for each sample, 0 means auto (= packed, no interleaving). */ +} ORI_ObjectParams_RxSigPathUtra_s; + +/** + * @struct ORI_ObjectParams_RxSigPathEUtraFDD_s + * @brief Structure containing the parameters of a RxSigPath EUTRAFDD object. + * + */ +typedef struct +{ + uint16_t chanBW; /**< RW-Locked. Channel bandwith in MHz/10 (14 / 30 / 50 / 100 / 150 / 200). */ + uint16_t ulCalREMax; /**< RO. Max possible buffer in RE for UL timing calibration in Tc/2.*/ + uint32_t ta3; /**< RO. RE time delay. */ + uint16_t ulCalRE; /**< RW-Locked. Time delay to enable UL timing calibration in Tc/2. */ + uint8_t axcW; /**< RW-Locked. AxC W parameter. */ + uint8_t axcB; /**< RW-Locked. AxC B parameter. */ + ORI_Object_s * oriLink; /**< RW-Locked. ORI Link on which the AxC is mapped. */ + ORI_Object_s * antPort; /**< RW-Locked. Reference Antenna port for this signal. */ + uint32_t earfcn; /**< RW-Locked. Uplink EARFCN. */ + ORI_Boolean_e enableIQULComp; /**< RW-Locked. IQ data compression enablement. */ + uint32_t sigmaIQ; /**< RW-Locked. Sigma IQ value for IQ data compression. */ + ORI_Boolean_e AWS_enableCompRateChange; /**< RW-Locked. AW2S Vendor specific: Enable IQ data compression sample rate change. */ + ORI_Boolean_e AWS_enableCompBitChange; /**< RW-Locked. AW2S Vendor specific: Enable IQ data compression bit width change. */ + int16_t AWS_measuredPwr; /**< RO. AW2S Vendor specific: Measured Rx power for this path, unit is dBm/10 (e.g. -650 for -65 dBm). */ + uint16_t AWS_axcIncr; /**< RW-Locked. AW2S Vendor specific: AxC increment for each sample, 0 means auto (= packed, no interleaving). */ +} ORI_ObjectParams_RxSigPathEUtraFDD_s; + +/** + * @struct ORI_ObjectParams_RxSigPathEUtraTDD_s + * @brief Structure containing the parameters of a RxSigPath EUTRATDD object. + * + */ +typedef struct +{ + uint16_t chanBW; /**< RW-Locked. Channel bandwith in MHz/10 (14 / 30 / 50 / 100 / 150 / 200). */ + uint8_t tddULDLConfig; /**< RW-Locked. TDD UL/DL config. */ + uint8_t tddSpecialSFConfig; /**< RW-Locked. TDD SSF config. */ + ORI_tddCPLength_e tddCPLengthUL; /**< RW-Locked. TDD Cyclic prefix length. */ + uint16_t ulCalREMax; /**< RO. Max possible buffer in RE for UL timing calibration in Tc/2.*/ + uint32_t ta3; /**< RO. RE time delay. */ + uint16_t ulCalRE; /**< RW-Locked. Time delay to enable UL timing calibration in Tc/2. */ + uint8_t axcW; /**< RW-Locked. AxC W parameter. */ + uint8_t axcB; /**< RW-Locked. AxC B parameter. */ + ORI_Object_s * oriLink; /**< RW-Locked. ORI Link on which the AxC is mapped. */ + ORI_Object_s * antPort; /**< RW-Locked. Reference Antenna port for this signal. */ + uint32_t earfcn; /**< RW-Locked. Uplink EARFCN. */ + ORI_Boolean_e enableIQULComp; /**< RW-Locked. IQ data compression enablement. */ + uint32_t sigmaIQ; /**< RW-Locked. Sigma IQ value for IQ data compression. */ + ORI_Boolean_e AWS_enableCompRateChange; /**< RW-Locked. AW2S Vendor specific: Enable IQ data compression sample rate change. */ + ORI_Boolean_e AWS_enableCompBitChange; /**< RW-Locked. AW2S Vendor specific: Enable IQ data compression bit width change. */ + int16_t AWS_measuredPwr; /**< RO. AW2S Vendor specific: Measured Rx power for this path, unit is dBm/10 (e.g. -650 for -65 dBm). */ + uint16_t AWS_axcIncr; /**< RW-Locked. AW2S Vendor specific: AxC increment for each sample, 0 means auto (= packed, no interleaving). */ +} ORI_ObjectParams_RxSigPathEUtraTDD_s; + +/** + * @struct ORI_ObjectParams_RxSigPathGSM_s + * @brief Structure containing the parameters of a RxSigPath GSM object. + */ +typedef struct +{ + uint16_t ulCalREMax; /**< RO. Max possible buffer in RE for UL timing calibration in Tc/2.*/ + ORI_freqBand_e freqBandInd; /**< GSM frequency band indicator. */ + uint32_t ta3; /**< RO. RE time delay. */ + uint16_t ulCalRE; /**< RW-Locked. Time delay to enable UL timing calibration in Tc/2. */ + uint8_t axcW; /**< RW-Locked. AxC W parameter. */ + uint8_t axcB; /**< RW-Locked. AxC B parameter. */ + ORI_Object_s * oriLink; /**< RW-Locked. ORI Link on which the AxC is mapped. */ + ORI_Object_s * antPort; /**< RW-Locked. Reference Antenna port for this signal. */ + int16_t ulFeedAdj; /**< RW. Uplink feeder adjustment in dB/10 (e.g. 200 for 20 dB). */ + ORI_Object_s * TxSigPath; /**< RW-Locked. Associated TxSigPath for frequency hopping information. */ + int16_t AWS_measuredPwr; /**< RO. AW2S Vendor specific: Measured Rx power for this path, unit is dBm/10 (e.g. -650 for -65 dBm). */ + uint16_t AWS_axcIncr; /**< RW-Locked. AW2S Vendor specific: AxC increment for each sample, 0 means auto (= packed, no interleaving). */ +} ORI_ObjectParams_RxSigPathGSM_s; + +/** + * @struct ORI_ObjectParams_ORILink_s + * @brief Structure containing the parameters of an ORI Link object. + */ +typedef struct +{ + char portLabel[81]; /**< RO. Physical ORI link port label. */ + ORI_portRoleCapability_e portRoleCapability; /**< RO. Port role capability. */ + ORI_portRole_e portRole; /**< RW-Locked. Port role. */ + int16_t bitRateSupport; /**< RO. Supported line bit rate. */ + uint8_t bitRateRequested; /**< RW-Locked. Requested line bit rate. 0 for auto-negotitation. */ + uint8_t bitRateOperational; /**< RO. Current line bit rate. 0 for link down. */ + uint64_t localPortID; /**< RO. Local end port ID. */ + uint64_t remotePortID; /**< RO. Remote end port ID. */ + uint32_t toffset; /**< RO. CPRI time delay component. */ + ORI_linkType_e oriLinkType; /**< RW-Locked. ORI Link type. */ + uint8_t AWS_localMAC[6]; /**< R0. AW2S Vendor specific: Local MAC address of the ORI link. */ + uint8_t AWS_remoteMAC[6]; /**< RW. AW2S Vendor specific: Remote MAC address of the ORI link. */ + uint32_t AWS_t14; /**< RO. AW2S Vendor specific: CPRI time delay component. */ + uint8_t AWS_remoteIP[4]; /**< RW. AW2S Vendor specific: REC IP for ECPRI Ethernet frame */ + uint8_t AWS_localIP[4]; /**< R0. AW2S Vendor specific: RE IP for ECPRI Ethernet frame */ + uint16_t AWS_remoteUdpPort; /**< RW. AW2S Vendor specific: REC Udp Port for ECPRI Ethernet frame */ + uint16_t AWS_localUdpPort; /**< R0. AW2S Vendor specific: RE Udp Port for ECPRI Ethernet frame */ + uint32_t AWS_sfpTxPow; /**< RO. AW2S Vendor specific: SFP Tx power. */ + uint32_t AWS_sfpRxPow; /**< RO. AW2S Vendor specific: SFP Rx power. */ +} ORI_ObjectParams_ORILink_s; + +/** + * @struct ORI_ObjectParams_ExternalEventPort_s + * @brief Structure containing the parameters of an External Event Port object. + */ +typedef struct +{ + char portLabel[81]; /**< RO. External event port label. */ +} ORI_ObjectParams_ExternalEventPort_s; + +/** + * @struct ORI_ObjectParams_AISGPort_s + * @brief Structure containing the parameters of an AISG Port object. + */ +typedef struct +{ + char portLabel[81]; /**< RO. AISG port label. */ + ORI_Boolean_e busPowerEnable; /**< RW-Locked. Bus power enablement. */ +} ORI_ObjectParams_AISGPort_s; + +/** + * @struct ORI_ObjectParams_AISGALD_s + * @brief Structure containing the parameters of an AISG ALD object. + */ +typedef struct +{ + uint8_t deviceType; /**< RW-Locked. Device type of the ALD. */ + uint8_t UID[20]; /**< RW-Locked. Unique ID array. */ + uint8_t releaseID; /**< RO. 3GPP protocol release. */ + uint8_t aisgVersion; /**< RO. AISG protocol version. */ + uint8_t deviceTypeVersion[3]; /**< RO. Device type substance version. */ + uint16_t frameLength; /**< RO. Maximum frame length for AISG Layer 7 message payload. */ + uint8_t hdlcAdress; /**< RO. Actual HLDC address. */ +} ORI_ObjectParams_AISGALD_s; + +/** + * @struct ORI_ObjectParams_Log_s + * @brief Structure containing the parameters of a Log object. + */ +typedef struct +{ + char logTypeID[41]; /**< RO. Log type identifier. */ + char description[81]; /**< RO. Log description. */ + ORI_logCategory_e logCategory; /**< RO. Log category. */ + uint32_t maxREfileSize; /**< RO. Max RE file size in kB. */ + uint32_t maxRECfileSize; /**< RW. Max REC file size in kB. */ + ORI_Boolean_e enableNotification; /**< RW. Enable REC notification on file transfer availability. */ + ORI_Boolean_e fileAvailable; /**< RO. File is available. */ + ORI_overflowBehaviour_e overflowBehaviour; /**< RW. Behaviour on overflow. */ + ORI_Boolean_e recordingEnabled; /**< RW. Recording enablement. */ + uint64_t logPeriod; /**< RW. Log expiration period in seconds. */ + ORI_timerType_e timerType; /**< RW. Log expiration behaviour. */ +} ORI_ObjectParams_Log_s; + +/** + * @struct ORI_ObjectParams_DLRoutedIQData_s + * @brief Structure containing the parameters of a DL Routed IQ Data object. + */ +typedef struct +{ + uint16_t IQsubBlockSize; /**< RW-Locked. Number of bits contained in the IQ data sub-block. */ + ORI_Object_s * MasterPortOriLink; /**< RW-Locked. Reference to the master port ORI Link. */ + uint8_t MasterPortIQblkW; /**< RW-Locked. Sub-block start W parameter for master port. */ + uint16_t MasterPortIQblkB; /**< RW-Locked. Sub-block start B parameter for master port. */ + ORI_Object_s * SlavePortOriLink; /**< RW-Locked. Reference to the slave port ORI Link. */ + uint8_t SlavePortIQW; /**< RW-Locked. Sub-block start W parameter for slave port. */ + uint16_t SlavePortIQB; /**< RW-Locked. Sub-block start B parameter for slave port. */ + uint16_t TBDelayDL; /**< RO. Internal RE delay from slave port to master port. */ +} ORI_ObjectParams_DLRoutedIQData_s; + +/** + * @struct ORI_ObjectParams_ULRoutedIQData_s + * @brief Structure containing the parameters of a UL Routed IQ Data object. + */ +typedef struct +{ + uint16_t IQsubBlockSize; /**< RW-Locked. Number of bits contained in the IQ data sub-block. */ + ORI_Object_s * MasterPortOriLink; /**< RW-Locked. Reference to the master port ORI Link. */ + uint8_t MasterPortIQblkW; /**< RW-Locked. Sub-block start W parameter for master port. */ + uint16_t MasterPortIQblkB; /**< RW-Locked. Sub-block start B parameter for master port. */ + ORI_Object_s * SlavePortOriLink; /**< RW-Locked. Reference to the slave port ORI Link. */ + uint8_t SlavePortIQW; /**< RW-Locked. Sub-block start W parameter for slave port. */ + uint16_t SlavePortIQB; /**< RW-Locked. Sub-block start B parameter for slave port. */ + uint16_t TBDelayUL; /**< RO. Internal RE delay from master port to slave port. */ +} ORI_ObjectParams_ULRoutedIQData_s; + +/** + * @struct ORI_ObjectParams_DLRoutedCWBlock_s + * @brief Structure containing the parameters of a DL Routed CW Block object. + */ +typedef struct +{ + uint8_t CtrlBlockSize; /**< RW-Locked. Number of consecutive sub-channels in the CW block. */ + uint8_t SubChannelStart; /**< RW-Locked. Lowest sub-channel of the CW block. */ + uint8_t Ydepth; /**< RW-Locked. Number of consecutive Y locations of the sub-channels in the CW block. */ + uint8_t SlavePortYoffset; /**< RW-Locked. Lowest Y location of the sub-channel(s) at the slave port. */ + uint8_t MasterPortYoffset; /**< RW-Locked. Lowest Y location of the sub-channel(s) at the master port. */ + ORI_Object_s * SlavePortOriLink; /**< RW-Locked. Reference to the slave port ORI Link. */ + ORI_Object_s * MasterPortOriLink; /**< RW-Locked. Reference to the master port ORI Link. */ +} ORI_ObjectParams_DLRoutedCWBlock_s; + +/** + * @struct ORI_ObjectParams_ULRoutedCWBlock_s + * @brief Structure containing the parameters of a UL Routed CW Block object. + */ +typedef struct +{ + uint8_t CtrlBlockSize; /**< RW-Locked. Number of consecutive sub-channels in the CW block. */ + uint8_t SubChannelStart; /**< RW-Locked. Lowest sub-channel of the CW block. */ + uint8_t Ydepth; /**< RW-Locked. Number of consecutive Y locations of the sub-channels in the CW block. */ + uint8_t SlavePortYoffset; /**< RW-Locked. Lowest Y location of the sub-channel(s) at the slave port. */ + uint8_t MasterPortYoffset; /**< RW-Locked. Lowest Y location of the sub-channel(s) at the master port. */ + ORI_Object_s * SlavePortOriLink; /**< RW-Locked. Reference to the slave port ORI Link. */ + ORI_Object_s * MasterPortOriLink; /**< RW-Locked. Reference to the master port ORI Link. */ +} ORI_ObjectParams_ULRoutedCWBlock_s; + +/** + * @union ORI_ObjectParams_u + * @brief Union of all the parameters of the ORI objects. Access each field based on the object type. + */ +typedef union +{ + ORI_ObjectParams_RE_s RE; /**< Parameters for ::ORI_ObjectType_RE. */ + ORI_ObjectParams_AntennaPort_s AntPort; /**< Parameters for ::ORI_ObjectType_AntennaPort. */ + ORI_ObjectParams_TxSigPathUtra_s TxUtra; /**< Parameters for ::ORI_ObjectType_TxUtra. */ + ORI_ObjectParams_TxSigPathEUtraFDD_s TxEUtraFDD; /**< Parameters for ::ORI_ObjectType_TxEUtraFDD. */ + ORI_ObjectParams_TxSigPathEUtraTDD_s TxEUtraTDD; /**< Parameters for ::ORI_ObjectType_TxEUtraTDD. */ + ORI_ObjectParams_TxSigPathGSM_s TxGSM; /**< Parameters for ::ORI_ObjectType_TxGSM. */ + ORI_ObjectParams_RxSigPathUtra_s RxUtra; /**< Parameters for ::ORI_ObjectType_RxUtra. */ + ORI_ObjectParams_RxSigPathEUtraFDD_s RxEUtraFDD; /**< Parameters for ::ORI_ObjectType_RxEUtraFDD. */ + ORI_ObjectParams_RxSigPathEUtraTDD_s RxEUtraTDD; /**< Parameters for ::ORI_ObjectType_RxEUtraTDD. */ + ORI_ObjectParams_RxSigPathGSM_s RxGSM; /**< Parameters for ::ORI_ObjectType_RxGSM. */ + ORI_ObjectParams_ORILink_s ORILink; /**< Parameters for ::ORI_ObjectType_ORILink. */ + ORI_ObjectParams_ExternalEventPort_s ExternalEventPort; /**< Parameters for ::ORI_ObjectType_ExternalEventPort. */ + ORI_ObjectParams_AISGPort_s AISGPort; /**< Parameters for ::ORI_ObjectType_AISGPort. */ + ORI_ObjectParams_AISGALD_s AISGALD; /**< Parameters for ::ORI_ObjectType_AISGALD. */ + ORI_ObjectParams_Log_s Log; /**< Parameters for ::ORI_ObjectType_Log. */ + ORI_ObjectParams_DLRoutedIQData_s DLRoutedIQData; /**< Parameters for ::ORI_ObjectType_DLRoutedIQData. */ + ORI_ObjectParams_ULRoutedIQData_s ULRoutedIQData; /**< Parameters for ::ORI_ObjectType_ULRoutedIQData. */ + ORI_ObjectParams_DLRoutedCWBlock_s DLRoutedCWBlock; /**< Parameters for ::ORI_ObjectType_DLRoutedCWBlock. */ + ORI_ObjectParams_ULRoutedCWBlock_s ULRoutedCWBlock; /**< Parameters for ::ORI_ObjectType_ULRoutedCWBlock. */ +} ORI_ObjectParams_u; + + + +/*----------------------------------------------------------------------------------------- + * OBJECT FAULTS + *-----------------------------------------------------------------------------------------*/ + +#define FAULT_MAX_AFFECTED_OBJ 20 + +/** + * @struct ORI_Fault_s + * @brief Structure detailing a fault, its state, severity, description and affected objects. + */ +typedef struct +{ + ORI_FaultState_e state; /**< Current state of the fault. */ + ORI_FaultSeverity_e severity; /**< Severity of the fault. */ + char timestamp[256]; /**< Time stamp string of the fault (RE time reference). */ + char desc[256]; /**< Short text description associated to the fault. */ + uint32_t numAffectedObjects; /**< Number of additional objects affected by the fault. */ + ORI_Object_s * affectedObjects[FAULT_MAX_AFFECTED_OBJ]; /**< List of additional objects affected by the fault. */ +} ORI_Fault_s; + +/** + * @struct ORI_ObjectFaults_RE_s + * @brief Structure containing the faults of a RE object. + */ +typedef struct +{ + ORI_Fault_s extSuplyUndervolt; /**< Power supply under voltage. FaultType is ::ORI_FaultType_RE_ExtSupplyUnderVolt */ + ORI_Fault_s overTemp; /**< Over temperature. FaultType is ::ORI_FaultType_RE_OverTemp */ + ORI_Fault_s digInOverdrive; /**< Input digital signal level overdrive. FaultType is ::ORI_FaultType_RE_DigInOverdrive */ + ORI_Fault_s rfOutOverdrive; /**< RF output power overdrive. FaultType is ::ORI_FaultType_RE_RFOutOverdrive */ + ORI_Fault_s txGainFail; /**< Tx gain control failure. FaultType is ::ORI_FaultType_RE_TXGainFail */ + ORI_Fault_s rxGainFail; /**< Rx gain control failure. FaultType is ::ORI_FaultType_RE_RXGainFail */ +} ORI_ObjectFaults_RE_s; + +/** + * @struct ORI_ObjectFaults_AntennaPort_s + * @brief Structure containing the faults of an Antenna Port object. + */ +typedef struct +{ + ORI_Fault_s vswrOutOfRange; /**< VSWR at the antenna port exceeded limit. FaultType is ::ORI_FaultType_AntennaPort_VSWROutOfRange */ + ORI_Fault_s nonAisgTmaMalfct; /**< Non AISG TMA malfunction. FaultType is ::ORI_FaultType_AntennaPort_NonAisgTmaMalfct */ +} ORI_ObjectFaults_AntennaPort_s; + +/** + * @struct ORI_ObjectFaults_ORILink_s + * @brief Structure containing the faults of an ORI Link object. + */ +typedef struct +{ + ORI_Fault_s linkFailure; /**< LOS, LOF, SDI or RAI received on the ORI Link. FaultType is ::ORI_FaultType_ORILink_LinkFail */ + ORI_Fault_s portFailure; /**< Local ORI slave port failure. FaultType is ::ORI_FaultType_ORILink_PortFail */ + ORI_Fault_s syncFailure; /**< Synchronization lost on slave port. FaultType is ::ORI_FaultType_ORILink_SyncFail */ +} ORI_ObjectFaults_ORILink_s; + +/** + * @struct ORI_ObjectFaults_AISGPort_s + * @brief Structure containing the faults of an AISG Port object. + */ +typedef struct +{ + ORI_Fault_s aisgMalfct; /**< Hardware malfunction on AISG port. FaultType is ::ORI_FaultType_AISGPort_AisgMalfct */ +} ORI_ObjectFaults_AISGPort_s; + +/** + * @union ORI_ObjectFaults_u + * @brief Union of all the faults of the ORI objects. Access each field based on the object type. + */ +typedef union +{ + ORI_ObjectFaults_RE_s RE; /**< Faults for ::ORI_ObjectType_RE. */ + ORI_ObjectFaults_AntennaPort_s AntPort; /**< Faults for ::ORI_ObjectType_AntennaPort. */ + ORI_ObjectFaults_ORILink_s ORILink; /**< Faults for ::ORI_ObjectType_ORILink. */ + ORI_ObjectFaults_AISGPort_s AISGPort; /**< Faults for ::ORI_ObjectType_AISGPort. */ +} ORI_ObjectFaults_u; + + + +/*----------------------------------------------------------------------------------------- + * INDICATION DATA STRUCTURES + *-----------------------------------------------------------------------------------------*/ + +/** + * @struct ORI_Ind_TransferFileCmplt_s + * @brief ORI file transfer complete indication structure. + * + * This structure is passed on a file transfer complete indication and gives the result + * of a file transfer completion. + */ +typedef struct +{ + ORI_Result_e result; /**< Result of the file transfer. */ + char failInfo[256]; /**< String indicating the file transfer failure reason, if applicable. */ +} ORI_Ind_TransferFileCmplt_s; + +/** + * @struct ORI_Ind_ObjectStateChange_s + * @brief ORI object state change indication structure. + * + * This structure is passed on an object state change indication and gives the affected object and the type of the + * state that changed.
+ * The new state value is updated in the model and can be accessed directly in the object. + */ +typedef struct +{ + ORI_Object_s * object; /**< Object for which the state changed. */ + ORI_StateType_e stateType; /**< Type of the state that changed. */ +} ORI_Ind_ObjectStateChange_s; + +/** + * @struct ORI_Ind_FaultChange_s + * @brief ORI fault change indication structure. + * + * This structure is passed on a fault change indication (activated or cleared) and gives the primary affected object, the fault type and the actual fault structure.
+ * The new fault structure is updated in the model and can be accessed directly in the object based on the fault type. + */ +typedef struct +{ + ORI_Object_s * object; /**< Primary object affected by the fault. */ + ORI_FaultType_e faultType; /**< Type of the fault that changed. */ + ORI_Fault_s * fault; /**< Reference to the object's fault structure for the given fault type. */ +} ORI_Ind_FaultChange_s; + +/** + * @struct ORI_Ind_FileAvailable_s + * @brief ORI File Available indication structure. + * + * This structure is passed on a file available indication and gives the object concerned by the file available. + */ +typedef struct +{ + ORI_Object_s * object; /**< Object concerned by file availability. Valid objects : Log:X. */ +} ORI_Ind_FileAvailable_s; + +/** + * @struct ORI_Ind_UploadFileCmpl_s + * @brief ORI Upload File Complete indication structure. + * + * This structure is passed on an upload file complete indication and gives the result and the object concerned by the file upload. + */ +typedef struct +{ + ORI_Result_e result; /**< Result of the file transfer. */ + ORI_Object_s * object; /**< Object concerned by the file upload. Valid objects : RE:0 or Log:X. */ + char failInfo[256]; /**< String indicating the file transfer failure reason, if applicable. */ +} ORI_Ind_UploadFileCmpl_s; + +/** + * @struct ORI_Ind_DeviceScanCmpl_s + * @brief ORI AISG Device Scan Complete indication structure. + * + * This structure is passed on an aisg device scan complete indication and gives the result and the object concerned by the device scan. + */ +typedef struct +{ + ORI_Object_s * object; /**< Object concerned by the device scan. Valid objects : aisgPort:X. */ + int numAlds; /**< integer indicating the number of ALDs found by the device scan. */ +} ORI_Ind_DeviceScanCmpl_s; + +/** + * @struct ORI_Ind_L7respGetAlarm_s + * @brief ORI AISG Transmit L7 message indication with command Get Alarm Status. + * + * This structure is passed on an aisg ALD receive indication and gives layer 7 message Get Alarm Status fields. + */ +typedef struct +{ + unsigned char returnCode[16]; // returnCode, until 16 values supported +}ORI_Ind_L7respGetAlarm_s; + +/** + * @struct ORI_Ind_L7respGetInfo_s + * @brief ORI AISG Transmit L7 message indication with command Get Info. + * + * This structure is passed on an aisg ALD receive indication and gives layer 7 message Get Info fields. + */ +typedef struct +{ + int PNlen; // Product Number's length + char PN[64]; // Product Number + int SNlen; // Serial Number's length + char SN[64]; // Serial Number + int HWverLen; // Hardware Version's length + char HWver[64]; // Hardware Version + int SWverLen; // Software Version's length + char SWver[64]; // Software Version +}ORI_Ind_L7respGetInfo_s; + +typedef struct +{ + unsigned char data[80]; +}ORI_Ind_L7respReadUserData_s; + +/** +* @struct ORI_Ind_L7respGetAlarm_s +* @brief ORI AISG Transmit L7 message indication with command Get Alarm Status. +* +* This structure is passed on an aisg ALD receive indication and gives layer 7 message Get Alarm Status fields. +*/ +typedef struct +{ + unsigned char alarmCode[16]; // alarmCode, until 16 values supported +}ORI_Ind_L7respSelfTest_s; + + +/** + * @struct ORI_Ind_L7respGetTilt_s + * @brief ORI AISG Transmit L7 message indication with command Get Tilt. + * + * This structure is passed on an aisg ALD receive indication and gives layer 7 message Get Tilt fields. + */ +typedef struct +{ + int Tilt; // tilt value +}ORI_Ind_L7respGetTilt_s; + +/** + * @struct ORI_Ind_L7respGetDeviceData_s + * @brief ORI AISG Transmit L7 message indication with command Get Device Data. + * + * This structure is passed on an aisg ALD receive indication and gives layer 7 message Get Device Data fields. + */ +typedef struct +{ + unsigned char fieldNbr; + char antModelNbr[32]; // Antenna Model Number + char antSerialNbr[32]; // Antenna Serial Number + unsigned short antFreqBand; // Antenna Frequency Band + unsigned short beamwidthBand[4]; // Beamwidth for each Band + unsigned char gainBand[4]; // Gain for each Band + short maxTilt; // Maximum Supported Tilt + short minTilt; // Minimum Supported Tilt + char installationDate[32]; // Installation Date + char installerID[32]; // Installer ID + char basestationID[32]; // BaseStation ID + char sectorID[32]; // sector ID + unsigned short antBearing; // Antenna Bearing + short mechanicalTilt; // Mechanical Tilt +}ORI_Ind_L7respGetDeviceData_s; + +/** + * @struct ORI_Ind_L7indAlarmIndication_s + * @brief ORI AISG Transmit L7 message indication with alarm indication. + * + * This structure is passed on an aisg ALD receive indication and gives layer 7 message Alarm Indication Data fields. + */ +typedef struct +{ + unsigned char returnCode; + unsigned char stateFlag; +}ret_alarm_s; +typedef struct +{ + ret_alarm_s alarm[32]; +}ORI_Ind_L7indAlarmIndication_s; + +/** + * @struct ORI_Ind_L7respAntGetNbr_s + * @brief ORI AISG Transmit L7 message indication with command Antenna Get Number Of Antennas. + * + * This structure is passed on an aisg ALD receive indication and gives layer 7 message Antenna Get Number Of Antennas Data fields. + */ +typedef struct +{ + unsigned char nbr; +}ORI_Ind_L7respAntGetNbr_s; + +/** + * @struct ORI_Ind_respGetParam_s + * @brief ORI AISG getParam message indication . + * + * This structure is passed on a getParam command to obtain the ALD's deviceType. + */ +typedef struct +{ + unsigned char deviceType; +}ORI_Ind_respGetParam_s; + +/** + * @struct ORI_Ind_respCheckPortExist_s + * @brief ORI AISG check AISG Port existence . + * + * This structure is passed on a check aisg port exist command to know if there is an aisg port in this product or not. + */ +typedef struct +{ + ORI_Boolean_e exist; +}ORI_Ind_respCheckPortExist_s; + +/** + * @struct ORI_Ind_L7msg_s + * @brief ORI AISG Transmit L7 message indication struct. + * + * This struct is passed on an aisg ALD receive indication and gives a layer 7 message. + */ +typedef struct +{ + char raw[256]; + ORI_AisgLayer7Command_e command; + ORI_AisgReturnCode_e returnCode; + unsigned char multiAntennaNbr; + ORI_Ind_L7respGetAlarm_s getAlarm; + ORI_Ind_L7respGetInfo_s getInfo; + ORI_Ind_L7respReadUserData_s readUserData; + ORI_Ind_L7respSelfTest_s selfTest; + ORI_Ind_L7respGetTilt_s getTilt; + ORI_Ind_L7respGetDeviceData_s getDeviceData; + ORI_Ind_L7indAlarmIndication_s alarmIndication; + ORI_Ind_L7respAntGetNbr_s getNbrAntennas; + ORI_Ind_respGetParam_s getParam; + ORI_Ind_respCheckPortExist_s checkAisgPortExist; +}ORI_Ind_L7msg_s; + +/** + * @struct ORI_Ind_AisgALDRx_s + * @brief ORI AISG ALD receive indication structure. + * + * This structure is passed on an aisg ALD receive indication and gives a layer 7 message and the object concerned. + */ +typedef struct +{ + ORI_Object_s * object; /**< Object concerned by the device scan. Valid objects : aisgPort:X/aisgALD:Y. */ + ORI_Ind_L7msg_s L7message; /**< string of a layer7 message sent by the ALD. */ +} ORI_Ind_AisgALDRx_s; + +/** + * @union ORI_IndicationValue_u + * @brief ORI indication value union. + * + * This union can be accessed based on the indication type. Its members give details on the received indication. + */ +typedef union +{ + ORI_Ind_TransferFileCmplt_s transferFileCmplt; /**< File transfer complete structure, access it on an ::ORI_IndicationType_FileTransferComplete. */ + ORI_Ind_ObjectStateChange_s objectStateChange; /**< Object state change structure, access it on an ::ORI_IndicationType_ObjectStateChange. */ + ORI_Ind_FaultChange_s faultChange; /**< Fault change structure, access it on an ::ORI_IndicationType_FaultChange. */ + ORI_Ind_FileAvailable_s fileAvailable; /**< File available structure, access it on an ::ORI_IndicationType_FileAvailable. */ + ORI_Ind_UploadFileCmpl_s uploadFileCmpl; /**< Upload file complete structure, access it on an ::ORI_IndicationType_UploadFileCmpl. */ + ORI_Ind_DeviceScanCmpl_s deviceScanCmpl; /**< AISG device scan complete structure, access it on an ::ORI_IndicationType_AisgScanDeviceCompl. */ + ORI_Ind_AisgALDRx_s aisgALDRx; /**< AISG ALD receive structure, access it on an ::ORI_IndicationType_AisgAldRx. */ +} ORI_IndicationValue_u; + +/** + * @typedef ORI_IndCallback_f + * @brief ORI indication callback function prototype. + * + * This is the prototype of the user callback function that is called when an indication has been received on the ORI Link.
+ * The indication callback passes in its arguments the @p type describing the type of the indication, such as file transfer completion, RE fault, etc.
+ * The @p value parameter shall be used to obtain more details on the indication. + * + * @param userData The user data that is from the ORI context structure. + * @param type An ::ORI_IndicationType_e. + * @param value An ::ORI_IndicationValue_u. + * @return Void. + * + * @warning The indication callback is called in a separate thread. + * @warning The state of the model is guaranteed to stay constant during the indication callback. + * @warning ORI functions (except for ORI MODEL functions) must not be called during the indication callback. + */ +typedef void (ORI_IndCallback_f) (void * userData, ORI_IndicationType_e type, ORI_IndicationValue_u value); + + + + + +/*----------------------------------------------------------------------------------------- + * RE VERSION STRUCTURE + *-----------------------------------------------------------------------------------------*/ + +/** + * @struct ORI_REVersion_s + * @brief ORI RE version query information structure. + * + * This structure contains the RE vendor specific version information obtained during a ORI_VersionQuery() procedure. + */ +typedef struct +{ + char vendorID[64]; /**< Vendor ID as signaled in DHCP code 201, normally 3 characters */ + char productID[64]; /**< */ + char productRev[64]; /**< */ + char serialNumber[64]; /**< */ + char hardwareVer[64]; /**< */ + char activeSwUpgradePkgVer[64]; /**< */ + char activeSwImgVer[64]; /**< */ + char passiveSwUpgradePkgVer[64]; /**< */ + char passiveSwImgVer[64]; /**< */ +} ORI_REVersion_s; + + + + +/*----------------------------------------------------------------------------------------- + * ORI OBJECT STRUCTURE + *-----------------------------------------------------------------------------------------*/ + +/** + * @struct ORI_Object_s + * @brief Structure of an ORI Object. + * + * ORI Objects are internally created by the ORI library and represent an object present in the RE.
+ * Those objects represent and define the resource model of the RE, of which an image is present in the REC (via this library).
+ * Such objects can be accessed (for reading and navigating) by the user but must not be modified, created or deleted directly + * as they are an 'image' of the RE objects.
+ * To update the parameters of the object, see ORI_ObjectParamReport().
+ * To modify the parameters of the object, see ORI_ObjectParamModify().
+ * To create an object, see ORI_ObjectCreation().
+ * To delete an object, see ORI_ObjectDeletion().
+ * To update the state of the object, see ORI_ObjectStateReport().
+ * To modify the state of the object, see ORI_ObjectStateModify().
+ * To update the faults of the object, see ORI_ObjectFaultReport().
+ * To find an object in the model, see ORI_FindObject().
+ * To retrieve a specific fault of an object, see ORI_ObjectFault(). + */ +struct ORI_Object_s +{ + ORI_ObjectTypeRef_s typeRef; /**< Type reference of the object. */ + uint8_t instanceNumber; /**< Instance number of the object. */ + ORI_Object_s * prev; /**< Previous sibling. */ + ORI_Object_s * next; /**< Next sibling. */ + ORI_Object_s * children; /**< First child reference. */ + ORI_ObjectParams_u params; /**< Parameters union of this object. */ + ORI_AST_e ast; /**< Administrative state. */ + ORI_FST_e fst; /**< Functional state. */ + ORI_ObjectFaults_u faults; /**< Faults union of this object. */ +}; + + + + + +/*----------------------------------------------------------------------------------------- + * CONTEXT + *-----------------------------------------------------------------------------------------*/ + +/** + * @struct ORI_Version_s + * @brief ORI version structure. + * + * This structure contains ORI library version information. + */ +typedef struct +{ + uint8_t major; /**< Version major number. */ + uint8_t minor; /**< Version minor number. */ +} ORI_Version_s; + +/** + * @struct ORI_s + * @brief ORI context data structure. + * + * This structure represents the context data for the ORI C library and shall be passed in ORI function calls.
+ * The @p opaque field is a library specific field and must not be modified by the user application.
+ * Other fields may be set (and changed) at run-time by the user application. + * + * @warning The indication callback is called in a separate thread. + * @warning The state of the model is guaranteed to stay constant during the indication callback. + * @warning ORI functions (except for ORI MODEL functions) must not be called during the indication callback. + */ +typedef struct +{ + void * opaque; /**< Set by the library, DO NOT MODIFY. */ + ORI_IndCallback_f * indicationCallback; /**< Pointer to user set ORI indication callback, this function is called when an indication is received on the ORI Link. If @c NULL (default), indications are discarded. */ + void * userData; /**< User data for passing into the ORI indication callback */ +} ORI_s; + + + +/*----------------------------------------------------------------------------------------- + * ORI CREATION / DELETION / (DIS)CONNECTION + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Retrieve ORI library version structure. + * + * This functions returns the ORI library version structure (constant). + * + * @return Version structure. + */ +ORI_Version_s ORI_LibVersion(void); + +/** + * @brief Create an ORI context. + * + * This function creates and initializes an ORI context structure that is to be used when calling + * other ORI library functions. This function also starts threads for data receiving and callbacks handling. + * + * @return The ORI context if creation successful, else @c NULL. + * + * @warning The returned ORI context must be free'd with a call to ORI_Free() when the user application is done with ORI. + */ +ORI_s * ORI_Create(void); + +/** + * @brief Delete an ORI context. + * + * This function disconnects from the remote host (if connected), destroys the ORI threads and releases all associated ORI resources. + * + * @param ori The ORI context to delete. + * @return Void. + */ +void ORI_Free(ORI_s * ori); + +/** + * @brief Enable ORI debug outputs. + * + * This function enables the ORI debug prints to stdout. + * + * @param ori The ORI context. + * @return Void. + */ +void ORI_EnableDebug(ORI_s * ori); + +/** + * @brief Disable ORI debug outputs. + * + * This function disables the ORI debug prints to stdout. + * + * @param ori The ORI context. + * @return Void. + */ +void ORI_DisableDebug(ORI_s * ori); + +/** + * @brief Connect to an ORI remote host (RE). + * + * This functions tries to connect the ORI context to a RE for C&M. The IP address @p serverIP of the RE and the network port @p port + * indicates with which host form the TCP link. The @p timeout_ms specifies the timeout (in milliseconds) of the connection attempt.
+ * Once connected, callbacks from the ORI context may be called at any time, and the TCP Link monitoring timer shall be started on both RE and REC side.
+ * The REC side TCP link monitoring timer is integrated in the ORI library and is managed by the ORI_HealthCheck() function. + * + * @param ori The ORI context. + * @param serverIP The IP address of the RE in string format (e.g. "192.168.100.1"). + * @param port The port to use for TCP connection. + * @param timeout_ms The timeout in milliseconds of the connection attempt. + * @param retry_timer_s Request retry timer in seconds when no response has been received from RE, until TCP link times-out, 0 means no retries will happen. + * @return The result of the connection, ::ORI_Result_SUCCESS is returned if the connection is established. + */ +ORI_Result_e ORI_Connect(ORI_s * ori, const char * serverIP, int port, unsigned int timeout_ms, uint16_t retry_timer_s); + +/** + * @brief Disconnect from an ORI remote host (RE). + * + * This function disconnects the ORI context from the RE. This function does nothing if not currently connected.
+ * At disconnection, all buffered ORI response and indication messages are discarded, if any are still waiting to be processed. + * + * @param ori The ORI context. + * @return Void. + */ +void ORI_Disconnect(ORI_s * ori); + +/** + * @brief Retrieve which Ethernet interface is used by the ORI TCP link. + * + * Returns the name of the currently (or last before disconnection) Ethernet interface used by the ORI TCP Link. + * + * @param ori The ORI context. + * @return Name of the Ethernet interface (e.g. "eth2"). + */ +const char * ORI_InterfaceName(ORI_s * ori); + + +/*----------------------------------------------------------------------------------------- + * DEVICE MANAGEMENT + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Perform a RE Health Check procedure. + * + * This function performs the Health Check procedure with the RE to verify that the OCP layer is functioning correctly.
+ * A successful health check will update and re-start the TCP link timeout using the new @p tcpLinkMonTimeout parameter + * of the RE and the ORI library (REC side).
+ * It is the application's responsibility to re-call this function within the specified Health Check Idle Timer which should + * be at least 5 seconds lower than the timeout value of @p tcpLinkMonTimeout. + * + * @param ori The ORI context. + * @param tcpLinkMonTimeout The new TCP Link Monitoring timeout value in seconds to store in the RE. Minimum value: 30 except special value 0 which means no timeout. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_HealthCheck(ORI_s * ori, uint16_t tcpLinkMonTimeout, ORI_Result_e * RE_result); + +/** + * @brief Perform a RE Set Time procedure. + * + * This function performs the Set Time procedure with the RE to set the absolute time reference used by the RE.
+ * The time reference is obtained from the calling application's local time reference. + * + * @param ori The ORI context. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_SetTime(ORI_s * ori, ORI_Result_e * RE_result); + +/** + * @brief Perform a RE Reset procedure. + * + * This function performs the Reset procedure with the RE.
+ * If successful, the RE shall close the TCP Link and reset itself. + * + * @param ori The ORI context. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_Reset(ORI_s * ori, ORI_Result_e * RE_result); + + + +/*----------------------------------------------------------------------------------------- + * SOFTWARE MANAGEMENT + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Perform a RE Version Query procedure. + * + * This function performs the Version Query procedure with the RE.
+ * If successful, the @p REVersion structure shall be filled with all the vendor specific RE version information, + * containing the product information, hardware version and software images stored in the RE. + * + * @param ori The ORI context. + * @param REVersion The RE version information structure. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_VersionQuery(ORI_s * ori, ORI_REVersion_s * REVersion, ORI_Result_e * RE_result); + + +/** + * @brief Perform a RE Software Update Preparation procedure. + * + * This function performs the Software Update Preparation procedure with the RE.
+ * If successful, the RE shall start downloading the specified Software Upgrade Package @p SwUpgradePkgVer file from the specified + * FTP server using the login credentials @p ftpSrvIpAddress, @p ftpSrvUserName and @p ftpSrvPassword.
+ * The Software file format is RE vendor specific.
+ * After download, the RE will store this new software package in non-volatile memory as the passive image.
+ * On completion of the process, the RE shall send a message indicating file transfer completion. If a callback is specified in the ORI context, + * the callback ::ORI_IndCallback_f will be called with the enum ::ORI_IndicationType_FileTransferComplete + * passed as parameter, as well as the file transfer completion result (success, or failure, with additional information). + * + * @param ori The ORI context. + * @param ftpSrvIpAddress The FTP server address as a decimal point notation (e.g. "192.168.1.1"). + * @param ftpSrvUserName The FTP server login used by the RE. + * @param ftpSrvPassword The FTP server password used by the RE. + * @param ftpSrvSwPkgDirPath The FTP server directory location of the software package file. + * @param SwUpgradePkgVer The name of the software package file. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_SoftwareUpdatePrep(ORI_s * ori, const char * ftpSrvIpAddress, const char * ftpSrvUserName, const char * ftpSrvPassword, + const char * ftpSrvSwPkgDirPath, const char * SwUpgradePkgVer, ORI_Result_e * RE_result); + +/** + * @brief Perform a RE Software Activation procedure. + * + * This function performs the Software Activation procedure with the RE.
+ * If successful, the RE shall activate its passive software image, set its previous active image as passive, close the TCP Link then reset itself. + * + * @param ori The ORI context. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_SoftwareActivation(ORI_s * ori, ORI_Result_e * RE_result); + + + +/*----------------------------------------------------------------------------------------- + * CONFIGURATION MANAGEMENT + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Perform a RE Object Parameter Reporting procedure. + * + * This function performs the Object Parameter Reporting procedure with the RE.
+ * The target object or set of objects is specified by the arguments @p object and @p wildcard:
+ * - @p object is not @c NULL and @p wildcard is 0 : the targeted object is @p object.
+ * - @p object is not @c NULL and @p wildcard is not 0 : the targeted objects are all the children of @p object.
+ * - @p object is @c NULL : the targeted objects are all the objects in the model.
+ * + * The parameter to report is defined by @p param. If @p param is ::ORI_ObjectParam_All, then all the parameters of the targeted + * object(s) shall be reported.
+ * On success, the parameters of the targeted objects are updated in the model.
+ * If the RE reported parameters for objects not present in the model image in the REC, the model is internally updated and + * the new objects created (this will be the case at initial software alignment, as the ORI GS specifies + * a Parameter Reporting "ALL objects" and "ALL parameters" shall be done at start-up). + * + * @param ori The ORI context. + * @param object The target object, or parent object, or @c NULL if no specific object; depending on @p wildcard. + * @param wildcard Wildcard for targeting all objects, or all children objects; depending on @p object being @c NULL. + * @param param The parameter to report, or all if ::ORI_ObjectParam_All. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_ObjectParamReport(ORI_s * ori, ORI_Object_s * object, int wildcard, ORI_ObjectParam_e param, ORI_Result_e * RE_result); + +/** + * @brief Perform a RE Object Parameter Modify procedure. + * + * This function performs the Object Parameter Modify procedure with the RE.
+ * The object for which the parameter(s) is(are) to be modified is given by @p object.
+ * The members of the @p params union for the specified target object type shall be set prior to calling this function, and each of the + * parameter to modify must be specified in the @p paramList array. The number of parameters to set must be given by @p numParams.
+ * On procedure completion, the @p paramResult[] array will be filled with the results of each independent parameter modify attempt. + * + * @param ori The ORI context. + * @param object The target object. + * @param params The parameters union with values set for the parameters to modify. + * @param paramList The array of enumerated parameters to modify. ::ORI_ObjectParam_All is not a valid enumeration for this procedure. + * @param numParams The number of parameters to modify, must be > 0. + * @param paramResult The return array for the individual result response for each parameter to modify. + * @param RE_globalResult The RE response global result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_ObjectParamModify(ORI_s * ori, ORI_Object_s * object, ORI_ObjectParams_u params, ORI_ObjectParam_e paramList[], + uint32_t numParams, ORI_Result_e paramResult[], ORI_Result_e * RE_globalResult); + + + +/*----------------------------------------------------------------------------------------- + * OBJECT LIFECYCLE + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Perform a RE Object Creation procedure. + * + * This function performs the Object Creation procedure with the RE.
+ * The object type to create is given by @p typeRef.
+ * The parameters @p params, @p paramList, @p numParams and @p paramResult function in the same maner as in the ORI_ObjectParamModify() procedure + * and can be used to set default parameters for the newly created object. @p numParams can be set to 0, in which case no parameter is applied + * to the new object.
+ * The created object is added in the model.
+ * This function also returns in @p newObject a reference in the model of the newly created object. + * + * @param ori The ORI context. + * @param typeRef The type reference of the object to create. + * @param params The parameters union with values set for the parameters to set. + * @param paramList The array of enumerated parameters to set. ::ORI_ObjectParam_All is not a valid enumeration for this procedure. + * @param numParams The number of parameters to set, can be 0. + * @param paramResult The return array for the individual result response for each parameter to set. + * @param newObject Reference to the newly created object. + * @param RE_globalResult The RE response global result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_ObjectCreation(ORI_s * ori, ORI_ObjectTypeRef_s typeRef, ORI_ObjectParams_u params, ORI_ObjectParam_e paramList[], + uint32_t numParams, ORI_Result_e paramResult[], ORI_Object_s ** newObject, ORI_Result_e * RE_globalResult); + +/** + * @brief Perform a RE Object Deletion procedure. + * + * This function performs the Object Deletion procedure with the RE.
+ * If successful, the object specified by @p object shall be deleted from the RE and removed from the library model. + * + * @param ori The ORI context. + * @param object The object to delete. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_ObjectDeletion(ORI_s * ori, ORI_Object_s * object, ORI_Result_e * RE_result); + + + +/*----------------------------------------------------------------------------------------- + * OBJECT STATE MANAGEMENT + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Perform a RE Object State Reporting procedure. + * + * This function performs the Object State Reporting procedure with the RE.
+ * The target object or set of objects is specified by the arguments @p object and @p wildcard:
+ * - @p object is not @c NULL and @p wildcard is 0 : the targeted object is @p object.
+ * - @p object is not @c NULL and @p wildcard is not 0 : the targeted objects are all the children of @p object.
+ * - @p object is @c NULL : the targeted objects are all the objects in the model.
+ * + * The state type to report is defined by @p stateType. If @p stateType is ::ORI_StateType_All, then all the states of the targeted + * object(s) shall be reported.
+ * On success, the states of the targeted objects are updated in the model.
+ * If the RE reported states for objects not present in the model image in the REC, the model is internally updated and + * the new objects created (this will be the case at initial software alignment, as the ORI GS specifies a State + * Reporting "ALL objects" and "ALL states" shall be done at start-up). + * If @p eventDrivenReport is set to ::ORI_EventDrivenReport_True or ::ORI_EventDrivenReport_False the event driven state reporting of the object is enabled + * or disabled. Pass ::ORI_EventDrivenReport_NoModify to keep the event driven state reporting as is. + * + * @param ori The ORI context. + * @param object The target object, or parent object, or @c NULL if no specific object; depending on @p wildcard. + * @param wildcard Wildcard for targeting all objects, or all children objects; depending on @p object being @c NULL. + * @param stateType The parameter to report, or all if ::ORI_StateType_All. + * @param eventDrivenReport Set event driven state reporting of the object if applicable. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_ObjectStateReport(ORI_s * ori, ORI_Object_s * object, int wildcard, ORI_StateType_e stateType, + ORI_EventDrivenReport_e eventDrivenReport, ORI_Result_e * RE_result); + +/** + * @brief Perform a RE Object State Modification procedure. + * + * This function performs the Object State Modification procedure with the RE.
+ * If successful, the administrative state (AST) of the target object will be set to @p ast. + * + * @param ori The ORI context. + * @param object The object on which to set the state. + * @param ast The administrative state to set. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_ObjectStateModification(ORI_s * ori, ORI_Object_s * object, ORI_AST_e ast, ORI_Result_e * RE_result); + + + +/*----------------------------------------------------------------------------------------- + * FAULT MANAGEMENT + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Perform a RE Object Fault Reporting procedure. + * + * This function performs the Object Fault Reporting procedure with the RE.
+ * The target object or set of objects is specified by the arguments @p object and @p wildcard:
+ * - @p object is not @c NULL and @p wildcard is 0 : the targeted object is @p object.
+ * - @p object is not @c NULL and @p wildcard is not 0 : the targeted objects are all the children of @p object.
+ * - @p object is @c NULL : the targeted objects are all the objects in the model.
+ * + * On success, the faults of the targeted objects are updated in the model.
+ * If the RE reported faults for objects not present in the model image in the REC, the model is internally updated and + * the new objects created (this will be the case at initial software alignment, as the ORI GS specifies a Fault + * Reporting "ALL objects" shall be done at start-up). + * If @p eventDrivenReport is set to ::ORI_EventDrivenReport_True or ::ORI_EventDrivenReport_False the event driven fault reporting of the object is enabled + * or disabled. Pass ::ORI_EventDrivenReport_NoModify to keep the event driven fault reporting as is. + * + * @param ori The ORI context. + * @param object The target object, or parent object, or @c NULL if no specific object; depending on @p wildcard. + * @param wildcard Wildcard for targeting all objects, or all children objects; depending on @p object being @c NULL. + * @param eventDrivenReport Set event driven fault reporting of the object if applicable. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_ObjectFaultReport(ORI_s * ori, ORI_Object_s * object, int wildcard, ORI_EventDrivenReport_e eventDrivenReport, ORI_Result_e * RE_result); + + +/*----------------------------------------------------------------------------------------- + * LOGGING + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Perform a File Upload procedure. + * + * This function performs a File Upload procedure with the RE or with a Log Object.
+ * If successful, a File Upload should be initiated.
+ * On completion of the process, the RE shall send a message indicating file upload completion. If a callback is specified in the ORI context, + * the callback ::ORI_IndCallback_f will be called with the enum ::ORI_IndicationType_UploadFileCmpl + * passed as parameter, as well as the file upload completion result. + * + * @param ori The ORI context. + * @param object The object targeted for the file upload. Must be a RE or Log object. + * @param ftpSrvIpAddress The FTP server address as a decimal point notation (e.g. "192.168.1.1"). + * @param ftpSrvUserName The FTP server login used by the RE. + * @param ftpSrvPassword The FTP server password used by the RE. + * @param ftpSrvFilePath The FTP server path to the file to upload. + * @param REFilePath The RE file path for a generic file upload. Used only in the case of a RE object. + * @param maxUploadFileSize The maximum size in kBytes accepted for uploading the file. Pass 0 for no size limit. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_FileUpload(ORI_s * ori, ORI_Object_s * object, const char * ftpSrvIpAddress, const char * ftpSrvUserName, const char * ftpSrvPassword, + const char * ftpSrvFilePath, const char * REFilePath, uint16_t maxUploadFileSize, ORI_Result_e * RE_result); + + +/*----------------------------------------------------------------------------------------- + * AISG + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Perform an AISG Device Scan procedure. + * + * This function performs an AISG Scan Device procedure with an AISG Port Object.
+ * On completion of the process, the RE shall send a message indicating scan device completion. + * + * @param ori The ORI context. + * @param object The object targeted for the device scan. Must be an AISG Port object. + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_DeviceScan(ORI_s * ori, ORI_Object_s * object, ORI_Result_e * RE_result); + +/** + * @brief Transfer an AISG layer7 message to an ALD. + * + * This function transfers an AISG layer7 message to an ALD. + * On completion of the transfer, the RE shall send a message indicating the ALD's layer7 response. + * + * @param ori The ORI context. + * @param object The object targeted for the layer7 message. Must be an AISG ALD object. + * @param msgLayer7 The AISG layer7 message. + * @param deviceDataFieldNbr The field number to store for GetDeviceData message (used in indication parsing). + * @param RE_result The RE response result of the procedure. + * @return The result of the procedure. + */ +ORI_Result_e ORI_MsgTransfer(ORI_s * ori, ORI_Object_s * object, const char * msgLayer7, uint8_t deviceDataFieldNbr, ORI_Result_e * RE_result); + + + +/*----------------------------------------------------------------------------------------- + * ORI MODEL + *-----------------------------------------------------------------------------------------*/ + +/** + * @brief Find an object in the model. + * + * This function seeks in the model an object that matches the object type @p type + * and the instance number @p instanceNumber.
+ * If @p parent is @c NULL, only parent-less objects will be in the search. Else, the object + * to find shall be a direct descendant of @p parent. + * + * @param ori The ORI context. + * @param type The object type of the object to find. + * @param instanceNumber The instance number of the object to find. + * @param parent The parent of the object to find, or @c NULL if no parent is expected. + * @return The found object if any, or @c NULL if none. + */ +ORI_Object_s * ORI_FindObject(ORI_s * ori, ORI_ObjectType_e type, uint8_t instanceNumber, ORI_Object_s * parent); + +/** + * @brief Gets all objects in the model + * + * This function fills the array @p objects with reference of all the objects in the model that are a child of @p parent. If @p parent is @c NULL, + * all the objects in the model are retrieved.
+ * The maximum size of the @p objects array shall be given in @p maxObjects.
+ * + * @param ori The ORI context. + * @param objects The object array to fill. + * @param maxObjects The maximum number of objects that the array can contain. + * @param parent If not @c NULL, specifies the parent of the objects to get. + * @return The number of objects found. + */ +uint32_t ORI_GetAllObjects(ORI_s * ori, ORI_Object_s * objects[], uint32_t maxObjects, ORI_Object_s * parent); + +/** + * @brief Gets all objects of a given type in the model + * + * This function fills the array @p objects with reference of all the objects of type @p type in the model that are a child of @p parent. If @p parent is @c NULL, + * all the objects of type @p type in the model are retrieved.
+ * The maximum size of the @p objects array shall be given in @p maxObjects.
+ * This functions is the same as ORI_GetAllObjects() but with a type filter. + * + * @param ori The ORI context. + * @param type The type filter of the objects to find. + * @param objects The object array to fill. + * @param maxObjects The maximum number of objects that the array can contain. + * @param parent If not @c NULL, specifies the parent of the objects to get. + * @return The number of objects found. + */ +uint32_t ORI_GetAllObjectsOfType(ORI_s * ori, ORI_ObjectType_e type, ORI_Object_s * objects[], uint32_t maxObjects, ORI_Object_s * parent); + +/** + * @brief Return the fault structure of an object based on a fault type. + * + * This function is a helper function that returns a pointer to a fault structure of an object based on a fault type. + * If the fault type and the object type does not match (as faults are specific to some objects), @c NULL is returned. + * + * @param ori The ORI context. + * @param object The object to delete. + * @param faultType The type of the fault structure to return. + * @return The found fault structure, or @c NULL if none. + */ +ORI_Fault_s * ORI_ObjectFault(ORI_s * ori, ORI_Object_s * object, ORI_FaultType_e faultType); + + + + +#endif /* ORI_H_ */ diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 3066f0906f..2758d01de3 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -40,7 +40,8 @@ #include "assertions.h" #include "common/utils/load_module_shlib.h" #include "common/utils/LOG/log.h" -#include "targets/RT/USER/lte-softmodem.h" +//#include "targets/RT/USER/lte-softmodem.h" +#include "executables/softmodem-common.h" char *get_devname(int devtype) { char *devnames[MAX_RF_DEV_TYPE]=DEVTYPE_NAMES; @@ -112,6 +113,9 @@ int load_lib(openair0_device *device, else deflibname=OAI_RF_LIBNAME; shlib_fdesc[0].fname="device_init"; + } else if (flag == RAU_REMOTE_THIRDPARTY_RADIO_HEAD) { + deflibname=OAI_THIRDPARTY_TP_LIBNAME; + shlib_fdesc[0].fname="transport_init"; } else { deflibname=OAI_TP_LIBNAME; shlib_fdesc[0].fname="transport_init"; diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index d086c0e13a..0c71a9999a 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -33,6 +33,7 @@ #ifndef COMMON_LIB_H #define COMMON_LIB_H #include +#include #include #include #include "record_player.h" @@ -41,6 +42,8 @@ #define OAI_RF_LIBNAME "oai_device" /* name of shared library implementing the transport */ #define OAI_TP_LIBNAME "oai_transpro" +/* name of shared library implementing a third-party transport */ +#define OAI_THIRDPARTY_TP_LIBNAME "thirdparty_transpro" /* name of shared library implementing the rf simulator */ #define OAI_RFSIM_LIBNAME "rfsimulator" /* name of shared library implementing the basic simulator */ @@ -51,13 +54,10 @@ /* flags for BBU to determine whether the attached radio head is local or remote */ #define RAU_LOCAL_RADIO_HEAD 0 #define RAU_REMOTE_RADIO_HEAD 1 - +#define RAU_REMOTE_THIRDPARTY_RADIO_HEAD 2 #define MAX_WRITE_THREAD_PACKAGE 10 #define MAX_WRITE_THREAD_BUFFER_SIZE 8 - -#ifndef MAX_CARDS - #define MAX_CARDS 8 -#endif +#define MAX_CARDS 8 typedef int64_t openair0_timestamp; typedef volatile int64_t openair0_vtimestamp; @@ -90,6 +90,8 @@ typedef enum { USRP_B200_DEV, /*!\brief device is USRP X300/X310*/ USRP_X300_DEV, + /*!\brief device is USRP N300/N310*/ + USRP_N300_DEV, /*!\brief device is BLADE RF*/ BLADERF_DEV, /*!\brief device is LMSSDR (SoDeRa)*/ @@ -102,9 +104,10 @@ typedef enum { ADRV9371_ZC706_DEV, /*!\brief device is UEDv2 */ UEDv2_DEV, + RFSIMULATOR, MAX_RF_DEV_TYPE } dev_type_t; -#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2"} +#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","USRP N300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2", "RFSIMULATOR"} /*!\brief transport protocol types */ typedef enum { @@ -365,12 +368,22 @@ struct openair0_device_t { /*! \brief Called to send samples to the RF target @param device pointer to the device structure specific to the RF hardware target @param timestamp The timestamp at whicch the first sample MUST be sent - @param buff Buffer which holds the samples + @param buff Buffer which holds the samples (2 dimensional) + @param nsamps number of samples to be sent + @param number of antennas + @param flags flags must be set to TRUE if timestamp parameter needs to be applied + */ + int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags); + + /*! \brief Called to send samples to the RF target + @param device pointer to the device structure specific to the RF hardware target + @param timestamp The timestamp at whicch the first sample MUST be sent + @param buff Buffer which holds the samples (1 dimensional) @param nsamps number of samples to be sent @param antenna_id index of the antenna if the device has multiple anteannas @param flags flags must be set to TRUE if timestamp parameter needs to be applied */ - int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags); + int (*trx_write_func2)(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int antenna_id, int flags); /*! \brief Receive samples from hardware. * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for @@ -380,10 +393,24 @@ struct openair0_device_t { * \param[out] ptimestamp the time at which the first sample was received. * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps. * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. - * \param antenna_id Index of antenna for which to receive samples + * \param num_antennas number of antennas from which to receive samples * \returns the number of sample read */ - int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id); + + int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int num_antennas); + + /*! \brief Receive samples from hardware, this version provides a single antenna at a time and returns. + * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for + * the first channel. *ptimestamp is the time at which the first sample + * was received. + * \param device the hardware to use + * \param[out] ptimestamp the time at which the first sample was received. + * \param[out] buff A pointers to a buffer for received samples. The buffer must be large enough to hold the number of samples \ref nsamps. + * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. + * \param antenna_id Index of antenna from which samples were received + * \returns the number of sample read + */ + int (*trx_read_func2)(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps,int *antenna_id); /*! \brief print the device statistics * \param device the hardware to use @@ -429,26 +456,46 @@ struct openair0_device_t { */ void (*configure_rru)(int idx, void *arg); +/*! \brief Pointer to generic RRU private information + */ + + void *thirdparty_priv; + + /*! \brief Callback for Third-party RRU Initialization routine + \param device the hardware configuration to use + */ + int (*thirdparty_init)(openair0_device *device); + /*! \brief Callback for Third-party RRU Cleanup routine + \param device the hardware configuration to use + */ + int (*thirdparty_cleanup)(openair0_device *device); + + /*! \brief Callback for Third-party start streaming routine + \param device the hardware configuration to use + */ + int (*thirdparty_startstreaming)(openair0_device *device); + /*! \brief RRU Configuration callback * \param idx RU index * \param arg pointer to capabilities or configuration */ int (*trx_write_init)(openair0_device *device); + /* \brief Get internal parameter + * \param id parameter to get + * \return a pointer to the parameter + */ + void *(*get_internal_parameter)(char *id); }; /* type of device init function, implemented in shared lib */ typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg); /* type of transport init function, implemented in shared lib */ typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params); -#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record -#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record -#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record -#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record +#define UE_MAGICDL 0xA5A5A5A5A5A5A5A5 // UE DL FDD record +#define UE_MAGICUL 0x5A5A5A5A5A5A5A5A // UE UL FDD record -#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record -#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record -#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record -#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record +#define ENB_MAGICDL 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record +#define ENB_MAGICUL 0x5B5B5B5B5B5B5B5B // eNB UL FDD record #define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size) @@ -465,19 +512,6 @@ typedef struct { uint32_t option_flag; // Option flag } samplesBlockHeader_t; -#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record -#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record -#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record -#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record - -#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record -#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record -#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record -#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record - -#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size) - - #ifdef __cplusplus extern "C" { @@ -525,7 +559,10 @@ extern int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **r extern void iqrecorder_end(openair0_device *device); +#include +#ifndef gettid #define gettid() syscall(__NR_gettid) +#endif /*@}*/ diff --git a/targets/ARCH/COMMON/record_player.c b/targets/ARCH/COMMON/record_player.c index 2dcd61e479..522f6b6d16 100644 --- a/targets/ARCH/COMMON/record_player.c +++ b/targets/ARCH/COMMON/record_player.c @@ -68,8 +68,10 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_ *recplay_conf=NULL; } - if (u_sf_replay == 1) return RECPLAY_REPLAYMODE; - else if (u_sf_record == 1) return RECPLAY_RECORDMODE; + if (u_sf_replay == 1) + return RECPLAY_REPLAYMODE; + else if (u_sf_record == 1) + return RECPLAY_RECORDMODE; return 0; } @@ -80,7 +82,7 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_ */ void iqrecorder_end(openair0_device *device) { if (device->recplay_state != NULL) { // subframes store - iqfile_header_t fh = {device->type,device->openair0_cfg->tx_sample_advance, device->openair0_cfg->rx_bw,OAIIQFILE_ID}; + iqfile_header_t fh = {device->type,device->openair0_cfg->tx_sample_advance, device->openair0_cfg->rx_bw,0,OAIIQFILE_ID}; recplay_state_t *rs = device->recplay_state; recplay_conf_t *rc = device->openair0_cfg[0].recplay_conf; rs->pFile = fopen (rc->u_sf_filename,"wb+"); @@ -91,16 +93,20 @@ void iqrecorder_end(openair0_device *device) { unsigned int i = 0; unsigned int modu = 0; - if ((modu = rs->nb_samples % 10) != 0) { - rs->nb_samples -= modu; // store entire number of frames + if ((modu = rs->nbSamplesBlocks % 10) != 0) { + rs->nbSamplesBlocks -= modu; // store entire number of frames } + fh.nbSamplesBlocks=rs->nbSamplesBlocks; LOG_I(HW,"Writing file header to %s \n", rc->u_sf_filename ); fwrite(&fh, sizeof(fh), 1, rs->pFile); - LOG_UI(HW,"Writing %u subframes to %s \n",rs->nb_samples, rc->u_sf_filename ); + LOG_UI(HW,"Writing %u subframes to %s \n",rs->nbSamplesBlocks, rc->u_sf_filename ); + uint8_t *ptr=(uint8_t *)rs->ms_sample; - for (i = 0; i < rs->nb_samples; i++) { - fwrite(rs->ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), rs->pFile); + for (i = 0; i < rs->nbSamplesBlocks; i++) { + int blockBytes=sizeof(iqrec_t)+((iqrec_t *)ptr)->nbBytes; + fwrite(ptr, sizeof(unsigned char), blockBytes, rs->pFile); + ptr+=blockBytes; } fclose (rs->pFile); @@ -112,4 +118,4 @@ void iqrecorder_end(openair0_device *device) { rs->ms_sample = NULL; } } -} \ No newline at end of file +} diff --git a/targets/ARCH/COMMON/record_player.h b/targets/ARCH/COMMON/record_player.h index 500acdd709..d91da68323 100644 --- a/targets/ARCH/COMMON/record_player.h +++ b/targets/ARCH/COMMON/record_player.h @@ -46,21 +46,22 @@ extern "C" #define BELL_LABS_IQ_HEADER 0xabababababababab #define BELL_LABS_IQ_PER_SF 7680 // Up to 5MHz bw for now #define BELL_LABS_IQ_BYTES_PER_SF (BELL_LABS_IQ_PER_SF * 4) +#define MAX_BELL_LABS_IQ_BYTES_PER_SF BELL_LABS_IQ_BYTES_PER_SF*10 -#define OAIIQFILE_ID "OIQF" +#define OAIIQFILE_ID {'O', 'I','Q','F'} typedef struct { uint64_t devtype; uint64_t tx_sample_advance; double bw; + unsigned int nbSamplesBlocks; char oaiid[4]; } iqfile_header_t; typedef struct { int64_t header; int64_t ts; - int64_t rfu1; + int64_t nbBytes; int64_t rfu2; // pad for 256 bits alignement required by AVX2 - unsigned char samples[BELL_LABS_IQ_BYTES_PER_SF]; // iq's for one subframe } iqrec_t; #define DEF_NB_SF 120000 // default nb of sf or ms to capture (2 minutes at 5MHz) #define DEF_SF_FILE "/tmp/iqfile" // default subframes file name @@ -114,14 +115,16 @@ typedef struct { int use_mmap; // default is to use mmap size_t mapsize; FILE *pFile; - int mmapfd; - int iqfd; + int fd; iqrec_t *ms_sample; // memory for all subframes - unsigned int nb_samples; + unsigned int nbSamplesBlocks; + uint8_t *currentPtr; + uint64_t currentTs; + unsigned int curSamplesBlock; + int64_t wrap_count; + size_t maxSizeBytes; } recplay_state_t; - - #ifdef __cplusplus } #endif diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index d893c66b52..9c0a9e3f65 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -102,23 +102,15 @@ int eth_socket_init_raw(openair0_device *device) { eth->local_addrd_ll.sll_family = AF_PACKET; eth->local_addrd_ll.sll_ifindex = eth->if_index.ifr_ifindex; /* hear traffic from specific protocol*/ - if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - eth->local_addrd_ll.sll_protocol = htons(0xbffe); - } else{ - eth->local_addrc_ll.sll_protocol = htons((short)device->eth_params->my_portc); - eth->local_addrd_ll.sll_protocol = htons((short)device->eth_params->my_portd); - } + eth->local_addrc_ll.sll_protocol = htons((short)device->eth_params->my_portc); + eth->local_addrd_ll.sll_protocol = htons((short)device->eth_params->my_portd); + eth->local_addrc_ll.sll_halen = ETH_ALEN; eth->local_addrc_ll.sll_pkttype = PACKET_OTHERHOST; eth->local_addrd_ll.sll_halen = ETH_ALEN; eth->local_addrd_ll.sll_pkttype = PACKET_OTHERHOST; eth->addr_len = sizeof(struct sockaddr_ll); - if ((eth->flags != ETH_RAW_IF5_MOBIPASS ) && - (bind(eth->sockfdc,(struct sockaddr *)ð->local_addrc_ll,eth->addr_len)<0)) { - perror("ETHERNET: Cannot bind to socket (control)"); - exit(0); - } if (bind(eth->sockfdd,(struct sockaddr *)ð->local_addrd_ll,eth->addr_len)<0) { perror("ETHERNET: Cannot bind to socket (user)"); exit(0); @@ -127,12 +119,9 @@ int eth_socket_init_raw(openair0_device *device) { /* Construct the Ethernet header */ ether_aton_r(local_mac, (struct ether_addr *)(&(eth->ehd.ether_shost))); ether_aton_r(remote_mac, (struct ether_addr *)(&(eth->ehd.ether_dhost))); - if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - eth->ehd.ether_type = htons(0xbffe); - } else { - eth->ehc.ether_type = htons((short)device->eth_params->my_portc); - eth->ehd.ether_type = htons((short)device->eth_params->my_portd); - } + eth->ehc.ether_type = htons((short)device->eth_params->my_portc); + eth->ehd.ether_type = htons((short)device->eth_params->my_portd); + printf("[%s] binding to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"),eth->ehd.ether_shost[0],eth->ehd.ether_shost[1],eth->ehd.ether_shost[2],eth->ehd.ether_shost[3],eth->ehd.ether_shost[4],eth->ehd.ether_shost[5]); return 0; @@ -216,8 +205,6 @@ int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestam packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks); } else if (flags == IF4p5_PULTICK) { packet_size = RAW_IF4p5_PULTICK_SIZE_BYTES; - } else if (flags == IF5_MOBIPASS) { - packet_size = RAW_IF5_MOBIPASS_SIZE_BYTES; } else { packet_size = RAW_IF4p5_PRACH_SIZE_BYTES; } @@ -430,53 +417,6 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam } -int trx_eth_read_raw_IF5_mobipass(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { - // Read nblocks info from packet itself - - int bytes_received=0; - eth_state_t *eth = (eth_state_t*)device->priv; - int ret; - - ssize_t packet_size = 28; //MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t ; -// ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 640*sizeof(int16_t); - - bytes_received = recv(eth->sockfdd, - buff[0], - packet_size, - MSG_PEEK); - - if (bytes_received ==-1) { - eth->num_rx_errors++; - perror("[MOBIPASS]ETHERNET IF5 READ (header): "); - exit(-1); - } - - IF5_mobipass_header_t *test_header = (IF5_mobipass_header_t*)((uint8_t *)buff[0] + MAC_HEADER_SIZE_BYTES); - *timestamp = test_header->time_stamp; - packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 640*sizeof(int16_t); - - while(bytes_received < packet_size) { - ret = recv(eth->sockfdd, - buff[0], - packet_size, - 0); - if (bytes_received ==-1) { - eth->num_rx_errors++; - perror("[MOBIPASS] ETHERNET IF5 READ (payload): "); - return(-1); - } else { - bytes_received+=ret; - eth->rx_actual_nsamps = bytes_received>>1; - eth->rx_count++; - } - } - - eth->rx_nsamps = nsamps; - return(bytes_received); - - -} - int eth_set_dev_conf_raw(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index 473d129aaf..ee0dce48f0 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -45,9 +45,8 @@ #include "common_lib.h" #include "ethernet_lib.h" -#include "common/ran_context.h" -#define DEBUG 0 +//#define DEBUG 1 // These are for IF5 and must be put into the device structure if multiple RUs in the same RAU !!!!!!!!!!!!!!!!! uint16_t pck_seq_num = 1; @@ -142,8 +141,8 @@ int eth_socket_init_udp(openair0_device *device) { perror("ETHERNET: Cannot set SO_REUSEADDR option on socket (control)"); exit(0); } - if (setsockopt(eth->sockfdd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int))) { - perror("ETHERNET: Cannot set SO_REUSEADDR option on socket (user)"); + if (setsockopt(eth->sockfdd, SOL_SOCKET, SO_NO_CHECK, &enable, sizeof(int))) { + perror("ETHERNET: Cannot set SO_NO_CHECK option on socket (user)"); exit(0); } @@ -202,8 +201,9 @@ int trx_eth_read_udp_IF4p5(openair0_device *device, openair0_timestamp *timestam goto again; } } else { - perror("ETHERNET IF4p5 READ"); - printf("(%s):\n", strerror(errno)); + return(-1); + //perror("ETHERNET IF4p5 READ"); + //printf("(%s):\n", strerror(errno)); } } else { *timestamp = test_header->sub_type; @@ -264,36 +264,82 @@ int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestam return (bytes_sent); } -int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int cc, int flags) { int bytes_sent=0; eth_state_t *eth = (eth_state_t*)device->priv; int sendto_flag =0; - int i=0; + //sendto_flag|=flags; eth->tx_nsamps=nsamps; - for (i=0;i>3; + __m256i buff_tx[nsamps2+1]; + __m256i *buff_tx2=buff_tx+1; +#else + nsamps2 = (nsamps+3)>>2; + __m128i buff_tx[nsamps2+2]; + __m128i *buff_tx2=buff_tx+2; +#endif +#elif defined(__arm__) || defined(__aarch64__) + nsamps2 = (nsamps+3)>>2; + int16x8_t buff_tx[nsamps2+2]; + int16x8_t *buff_tx2=buff_tx+2; +#else +#error Unsupported CPU architecture, ethernet device cannot be built +#endif + + + // bring TX data into 12 LSBs for softmodem RX + for (int j=0; jpck_header.seq_num = pck_seq_num; - //eth->pck_header.antenna_id = 1+(i<<1); - //eth->pck_header.timestamp = timestamp; - *(uint16_t *)buff2 = eth->pck_seq_num; - *(uint16_t *)(buff2 + sizeof(uint16_t)) = 1+(i<<1); - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_SEQ_NUM, eth->pck_seq_num); + // ECPRI Protocol revision + reserved bits (1 byte) + *(uint8_t *)buff2 = ECPRIREV; + // ECPRI Message type (1 byte) + *(uint8_t *)(buff2 + 1) = 64; + // ECPRI Payload Size (2 bytes) + AssertFatal(nsamps<16381,"nsamps > 16381\n"); + *(uint8_t *)(buff2 + 2) = (nsamps<<2)>>8; + *(uint8_t *)(buff2 + 3) = (nsamps<<2)&0xff; + // ECPRI PC_ID (2 bytes) + *(uint16_t *)(buff2 + 4) = cc; + // OAI modified SEQ_ID (4 bytes) + *(uint64_t *)(buff2 + 6) = ((uint64_t )timestamp)*6; + + /* + printf("ECPRI TX (REV %x, MessType %d, Payload size %d, PC_ID %d, TS %llu\n", + *(uint8_t *)buff2, + *(uint8_t *)(buff2+1), + *(uint16_t *)(buff2+2), + *(uint16_t *)(buff2+4), + *(uint64_t *)(buff2+6)); + */ int sent_byte; if (eth->compression == ALAW_COMPRESS) { @@ -311,7 +357,7 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi bytes_sent); #endif /* Send packet */ - bytes_sent += sendto(eth->sockfdd, + bytes_sent = sendto(eth->sockfdd, buff2, sent_byte, sendto_flag, @@ -339,17 +385,13 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi } //} - /* tx buffer values restored */ - *(int32_t *)buff2 = temp0; - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; - } - return (bytes_sent-APP_HEADER_SIZE_BYTES)>>2; } +#define NOSHIFT 1 -int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { +int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void *buff, int nsamps, int *cc) { int bytes_received=0; eth_state_t *eth = (eth_state_t*)device->priv; @@ -357,105 +399,98 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi int rcvfrom_flag =0; int block_cnt=0; int again_cnt=0; - int i=0; + static int packet_cnt=0; + int payload_size = UDP_PACKET_SIZE_BYTES(nsamps); +#if defined(__x86_64__) || defined(__i386__) +#ifdef __AVX2__ + int nsamps2 = (payload_size>>5)+1; + __m256i temp_rx[nsamps2]; + char *temp_rx0 = ((char *)&temp_rx[1])-APP_HEADER_SIZE_BYTES; +#else + int nsamps2 = (payload_size>>4)+1; + __m128i temp_rx[nsamps2]; + char *temp_rx0 = ((char *)&temp_rx[1])-APP_HEADER_SIZE_BYTES; +#endif +#elif defined(__arm__) || defined(__aarch64__) + int nsamps2 = (payload_size>>4)+1; + int16x8_t temp_rx[nsamps2]; + char *temp_rx0 = ((char *)&temp_rx[1])-APP_HEADER_SIZE_BYTES; +#else +#error Unsupported CPU architecture device cannot be built + int nsamps2 = (payload_size>>2)+1; + int32_t temp_rx[payload_size>>2]; + char* *temp_rx0 = ((char *)&temp_rx[1]) - APP_HEADER_SIZE_BYTES; +#endif + eth->rx_nsamps=nsamps; - for (i=0;icompression == ALAW_COMPRESS) { - receive_bytes = UDP_PACKET_SIZE_BYTES_ALAW(nsamps); - } else { - receive_bytes = UDP_PACKET_SIZE_BYTES(nsamps); - } - - while(bytes_received < receive_bytes) { - again: -#if DEBUG - printf("------- RX------: buff2 current position=%d remaining_bytes=%d bytes_recv=%d \n", - (void *)(buff2+bytes_received), - receive_bytes - bytes_received, - bytes_received); -#endif - bytes_received +=recvfrom(eth->sockfdd, - buff2, - receive_bytes, - rcvfrom_flag, - (struct sockaddr *)ð->dest_addrd, - (socklen_t *)ð->addr_len); - - if (bytes_received ==-1) { - eth->num_rx_errors++; - if (errno == EAGAIN) { - again_cnt++; - usleep(10); - if (again_cnt == 1000) { + bytes_received=0; + block_cnt=0; + AssertFatal(eth->compression == NO_COMPRESS, "IF5 compression not supported for now\n"); + + while(bytes_received < payload_size) { + again: + bytes_received +=recvfrom(eth->sockfdd, + temp_rx0, + payload_size, + rcvfrom_flag, + (struct sockaddr *)ð->dest_addrd, + (socklen_t *)ð->addr_len); + packet_cnt++; + if (bytes_received ==-1) { + eth->num_rx_errors++; + if (errno == EAGAIN) { + again_cnt++; + usleep(10); + if (again_cnt == 1000) { perror("ETHERNET READ: "); exit(-1); - } else { - printf("AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN \n"); - goto again; - } - } else if (errno == EWOULDBLOCK) { - block_cnt++; - usleep(10); - if (block_cnt == 1000) { - perror("ETHERNET READ: "); - exit(-1); - } else { - printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n"); - goto again; - } + } else { + bytes_received=0; + goto again; + } + } else if (errno == EWOULDBLOCK) { + block_cnt++; + usleep(10); + if (block_cnt == 1000) { + perror("ETHERNET READ: "); + exit(-1); + } else { + printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n"); + goto again; } - } else { -#if DEBUG - printf("------- RX------: nu=%d an_id=%d ts%d bytes_recv=%d\n", - *(int16_t *)buff2, - *(int16_t *)(buff2 + sizeof(int16_t)), - *(openair0_timestamp *)(buff2 + sizeof(int32_t)), - bytes_received); - - dump_packet((device->host_type == RAU_HOST)? "RAU":"RRU", buff2, UDP_PACKET_SIZE_BYTES(nsamps),RX_FLAG); -#endif - - /* store the timestamp value from packet's header */ - *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); - /* store the sequence number of the previous packet received */ - if (eth->pck_seq_num_cur == 0) { - eth->pck_seq_num_prev = *(uint16_t *)buff2; - } else { - eth->pck_seq_num_prev = eth->pck_seq_num_cur; - } - /* get the packet sequence number from packet's header */ - eth->pck_seq_num_cur = *(uint16_t *)buff2; - if ( ( eth->pck_seq_num_cur != (eth->pck_seq_num_prev + 1) ) && !((eth->pck_seq_num_prev==MAX_PACKET_SEQ_NUM(nsamps,device->openair0_cfg->samples_per_frame)) && (eth->pck_seq_num_cur==1 )) && !((eth->pck_seq_num_prev==1) && (eth->pck_seq_num_cur==1))) { - //#if DEBUG - printf("Out of order packet received: current_packet=%d previous_packet=%d timestamp=%"PRId64"\n",eth->pck_seq_num_cur,eth->pck_seq_num_prev,*timestamp); - //#endif - } - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,eth->pck_seq_num_cur); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,eth->pck_seq_num_prev); - eth->rx_actual_nsamps=bytes_received>>2; - eth->rx_count++; - } - } - /* tx buffer values restored */ - *(int32_t *)buff2 = temp0; - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; - - } - return (bytes_received-APP_HEADER_SIZE_BYTES)>>2; + } else { + /* store the timestamp value from packet's header */ + *timestamp = *(openair0_timestamp *)(temp_rx0 + ECPRICOMMON_BYTES+ECPRIPCID_BYTES); + // convert TS to samples, /3 for 30.72 Ms/s, /6 for 15.36 Ms/s, /12 for 7.68 Ms/s, etc. + *timestamp = *timestamp/6; + // handle 1.4,3,5,10,15 MHz cases + *cc = *(uint16_t*)(temp_rx0 + ECPRICOMMON_BYTES); + } + eth->rx_actual_nsamps=payload_size>>2; + eth->rx_count++; + } + +#ifdef NOSHIFT + memcpy(buff,(void*)(temp_rx+1),payload_size); +#else + // populate receive buffer in lower 12-bits from 16-bit representation + for (int j=1; j>2); } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 1d3c280f0e..c15bdc37cb 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -42,7 +42,6 @@ #include #include #include -#include #include "common_lib.h" #include "ethernet_lib.h" @@ -52,11 +51,20 @@ int num_devices_eth = 0; struct sockaddr_in dest_addr[MAX_INST]; int dest_addr_len[MAX_INST]; +int load_lib(openair0_device *device, + openair0_config_t *openair0_cfg, + eth_params_t *cfg, + uint8_t flag); int trx_eth_start(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; + if (eth->flags == ETH_UDP_IF5_ECPRI_MODE) { + AssertFatal(device->thirdparty_init != NULL, "device->thirdparty_init is null\n"); + AssertFatal(device->thirdparty_init(device) == 0, "third-party init failed\n"); + device->openair0_cfg->samples_per_packet = 256; + } /* initialize socket */ if (eth->flags == ETH_RAW_MODE) { printf("Setting ETHERNET to ETH_RAW_IF5_MODE\n"); @@ -121,11 +129,6 @@ int trx_eth_start(openair0_device *device) - } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - printf("Setting ETHERNET to RAW_IF5_MODE\n"); - if (eth_socket_init_raw(device)!=0) return -1; - if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; - } else { printf("Setting ETHERNET to UDP_IF5_MODE\n"); if (eth_socket_init_udp(device)!=0) return -1; @@ -137,8 +140,7 @@ int trx_eth_start(openair0_device *device) if(eth_get_dev_conf_udp(device)!=0) return -1; }*/ - /* adjust MTU wrt number of samples per packet */ - if(ethernet_tune (device,MTU_SIZE,UDP_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; + //if(ethernet_tune (device,MTU_SIZE,UDP_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } @@ -166,9 +168,15 @@ void trx_eth_end(openair0_device *device) } -int trx_eth_stop(openair0_device *device) -{ - return(0); + +int trx_eth_stop(openair0_device *device) { + eth_state_t *eth = (eth_state_t*)device->priv; + + if (eth->flags == ETH_UDP_IF5_ECPRI_MODE) { + AssertFatal(device->thirdparty_cleanup != NULL, "device->thirdparty_cleanup is null\n"); + AssertFatal(device->thirdparty_cleanup(device) == 0, "third-party cleanup failed\n"); + } + return(0); } @@ -210,11 +218,6 @@ int ethernet_tune(openair0_device *device, struct timeval timeout; struct ifreq ifr; char system_cmd[256]; - int rname[] = { CTL_NET, NET_CORE, NET_CORE_RMEM_MAX }; - int wname[] = { CTL_NET, NET_CORE, NET_CORE_WMEM_MAX }; - int namelen=3; - int newval[1]; - int newlen=sizeof(newval); int ret=0; // int i=0; @@ -354,28 +357,36 @@ int ethernet_tune(openair0_device *device, } break; case KERNEL_RCV_BUF_MAX_SIZE: - newval[0] = value; - ret=sysctl(rname, namelen, NULL, 0, newval, newlen); - if (ret) { - fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno)); - } else { - printf("[ETHERNET] Kernel network receive buffer max size is set to %u\n",(unsigned int)newval[0]); - } - break; + ret=snprintf(system_cmd,sizeof(system_cmd),"sysctl -w net.core.rmem_max=%d",value); + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); + } + printf("[ETHERNET] net core rmem %s\n",system_cmd); + } else { + perror("[ETHERNET] Can't set net core rmem\n"); + } + break; case KERNEL_SND_BUF_MAX_SIZE: - newval[0] = value; - ret=sysctl(wname, namelen, NULL, 0, newval, newlen); - if (ret) { - fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno)); - } else { - printf("[ETHERNET] Kernel network send buffer max size is set to %u\n",(unsigned int)newval[0]); - } - break; - + ret=snprintf(system_cmd,sizeof(system_cmd),"sysctl -w net.core.wmem_max=%d",value); + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); + } + printf("[ETHERNET] net core wmem %s\n",system_cmd); + } else { + perror("[ETHERNET] Can't set net core wmem\n"); + } + break; default: break; } - return 0; } @@ -387,20 +398,11 @@ int transport_init(openair0_device *device, eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t)); memset(eth, 0, sizeof(eth_state_t)); - if (eth_params->transp_preference == 1) { - eth->flags = ETH_RAW_MODE; - } else if (eth_params->transp_preference == 0) { - eth->flags = ETH_UDP_MODE; - } else if (eth_params->transp_preference == 3) { - eth->flags = ETH_RAW_IF4p5_MODE; - } else if (eth_params->transp_preference == 2) { - eth->flags = ETH_UDP_IF4p5_MODE; - } else if (eth_params->transp_preference == 4) { - eth->flags = ETH_RAW_IF5_MOBIPASS; - } else { - printf("transport_init: Unknown transport preference %d - default to RAW", eth_params->transp_preference); - eth->flags = ETH_RAW_MODE; - } + eth->flags = eth_params->transp_preference; + + // load third-party driver + if (eth->flags == ETH_UDP_IF5_ECPRI_MODE) load_lib(device,openair0_cfg,eth_params,RAU_REMOTE_THIRDPARTY_RADIO_HEAD); + if (eth_params->if_compress == 0) { eth->compression = NO_COMPRESS; @@ -423,12 +425,17 @@ int transport_init(openair0_device *device, device->trx_set_gains_func = trx_eth_set_gains; device->trx_write_init = trx_eth_write_init; - if (eth->flags == ETH_RAW_MODE) { + device->trx_read_func2 = NULL; + device->trx_read_func = NULL; + device->trx_write_func2 = NULL; + device->trx_write_func = NULL; + + if (eth->flags == ETH_RAW_MODE) { device->trx_write_func = trx_eth_write_raw; device->trx_read_func = trx_eth_read_raw; - } else if (eth->flags == ETH_UDP_MODE) { - device->trx_write_func = trx_eth_write_udp; - device->trx_read_func = trx_eth_read_udp; + } else if (eth->flags == ETH_UDP_MODE || eth->flags == ETH_UDP_IF5_ECPRI_MODE) { + device->trx_write_func2 = trx_eth_write_udp; + device->trx_read_func2 = trx_eth_read_udp; device->trx_ctlsend_func = trx_eth_ctlsend_udp; device->trx_ctlrecv_func = trx_eth_ctlrecv_udp; } else if (eth->flags == ETH_RAW_IF4p5_MODE) { @@ -439,9 +446,6 @@ int transport_init(openair0_device *device, device->trx_read_func = trx_eth_read_udp_IF4p5; device->trx_ctlsend_func = trx_eth_ctlsend_udp; device->trx_ctlrecv_func = trx_eth_ctlrecv_udp; - } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - device->trx_write_func = trx_eth_write_raw_IF4p5; - device->trx_read_func = trx_eth_read_raw_IF5_mobipass; } else { //device->trx_write_func = trx_eth_write_udp_IF4p5; //device->trx_read_func = trx_eth_read_udp_IF4p5; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 65b2def60d..ad64ac1a8a 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -49,7 +49,10 @@ #define RX_FLAG 0 #include "if_defs.h" -#define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp)) +#define ECPRICOMMON_BYTES 4 +#define ECPRIPCID_BYTES 2 +#define APP_HEADER_SIZE_BYTES (ECPRICOMMON_BYTES + ECPRIPCID_BYTES + sizeof(openair0_timestamp)) +#define ECPRIREV 1 // ECPRI Version 1, C=0 - single ECPRI message per OAI TX packet /*!\brief opaque ethernet data structure */ typedef struct { @@ -234,8 +237,8 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value); * @ingroup _oai */ int eth_socket_init_udp(openair0_device *device); -int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); -int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int cc, int flags); +int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void *buff, int nsamps, int *cc); int eth_socket_init_raw(openair0_device *device); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 0f2147847a..47205cf8b8 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -36,15 +36,17 @@ #include #include +#ifndef LITE_COMPILATION #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/LTE_TRANSPORT/if5_tools.h" +#endif // ETH transport preference modes -#define ETH_UDP_MODE 0 -#define ETH_RAW_MODE 1 +#define ETH_UDP_MODE 0 +#define ETH_RAW_MODE 1 #define ETH_UDP_IF4p5_MODE 2 #define ETH_RAW_IF4p5_MODE 3 -#define ETH_RAW_IF5_MOBIPASS 4 +#define ETH_UDP_IF5_ECPRI_MODE 4 // COMMOM HEADER LENGTHS diff --git a/targets/ARCH/ETHERNET/benetel/4g/benetel.c b/targets/ARCH/ETHERNET/benetel/4g/benetel.c new file mode 100644 index 0000000000..d3b72463b4 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/benetel.c @@ -0,0 +1,394 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include + +#include "common_lib.h" +#include "ethernet_lib.h" +#include "shared_buffers.h" +#include "low.h" +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +typedef struct { + eth_state_t e; + shared_buffers buffers; + rru_config_msg_type_t last_msg; + int capabilities_sent; + void *benetel_priv; + char *dpdk_main_command_line; +} benetel_eth_state_t; + +int trx_benetel_start(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return 0; +} + + +void trx_benetel_end(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); +} + + +int trx_benetel_stop(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_set_freq(openair0_device* device, + openair0_config_t *openair0_cfg, + int exmimo_dump_config) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_set_gains(openair0_device* device, + openair0_config_t *openair0_cfg) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_get_stats(openair0_device* device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_reset_stats(openair0_device* device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int ethernet_tune(openair0_device *device, + unsigned int option, + int value) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return 0; +} + +int trx_benetel_write_raw(openair0_device *device, + openair0_timestamp timestamp, + void **buff, int nsamps, int cc, int flags) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return nsamps*4; +} + +int trx_benetel_read_raw(openair0_device *device, + openair0_timestamp *timestamp, + void **buff, int nsamps, int cc) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return nsamps*4; +} + +char *msg_type(int t) +{ + static char *s[12] = { + "RAU_tick", + "RRU_capabilities", + "RRU_config", + "RRU_config_ok", + "RRU_start", + "RRU_stop", + "RRU_sync_ok", + "RRU_frame_resynch", + "RRU_MSG_max_num", + "RRU_check_sync", + "RRU_config_update", + "RRU_config_update_ok", + }; + + if (t < 0 || t > 11) return "UNKNOWN"; + return s[t]; +} + +int trx_benetel_ctlsend(openair0_device *device, void *msg, ssize_t msg_len) +{ + RRU_CONFIG_msg_t *rru_config_msg = msg; + benetel_eth_state_t *s = device->priv; + + printf("BENETEL: %s\n", __FUNCTION__); + + printf(" rru_config_msg->type %d [%s]\n", rru_config_msg->type, + msg_type(rru_config_msg->type)); + + s->last_msg = rru_config_msg->type; + + return msg_len; +} + +int trx_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len) +{ + RRU_CONFIG_msg_t *rru_config_msg = msg; + benetel_eth_state_t *s = device->priv; + + printf("BENETEL: %s\n", __FUNCTION__); + + if (s->last_msg == RAU_tick && s->capabilities_sent == 0) { + RRU_capabilities_t *cap; + rru_config_msg->type = RRU_capabilities; + rru_config_msg->len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); + cap = (RRU_capabilities_t*)&rru_config_msg->msg[0]; + cap->FH_fmt = OAI_IF4p5_only; + cap->num_bands = 1; + cap->band_list[0] = 7; + cap->nb_rx[0] = device->openair0_cfg->rx_num_channels; + cap->nb_tx[0] = device->openair0_cfg->tx_num_channels; + cap->max_pdschReferenceSignalPower[0] = -27; + cap->max_rxgain[0] = 90; + + s->capabilities_sent = 1; + + return rru_config_msg->len; + } + if (s->last_msg == RRU_config) { + rru_config_msg->type = RRU_config_ok; + return 0; + } + if (s->last_msg == RRU_start) { + s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); + } + /* correct? */ + while (1) pause(); + + return 0; +} + +void benetel_fh_if4p5_south_in(RU_t *ru, + int *frame, + int *subframe) +{ + benetel_eth_state_t *s = ru->ifdevice.priv; + PHY_VARS_eNB **eNB_list = ru->eNB_list, *eNB; + LTE_DL_FRAME_PARMS *fp; + int symbol; + int32_t *rxdata; + int antenna; + + lock_ul_buffer(&s->buffers, *subframe); +next: + while (!((s->buffers.ul_busy[0][*subframe] == 0x3fff && + s->buffers.ul_busy[1][*subframe] == 0x3fff) || + s->buffers.prach_busy[*subframe] == 1)) + wait_ul_buffer(&s->buffers, *subframe); + if (s->buffers.prach_busy[*subframe] == 1) { + int i; + int antenna = 0; + uint16_t *in; + uint16_t *out; + in = (uint16_t *)s->buffers.prach[*subframe]; + out = (uint16_t *)ru->prach_rxsigF[0][antenna]; + for (i = 0; i < 840*2; i++) + out[i] = ntohs(in[i]); + s->buffers.prach_busy[*subframe] = 0; + ru->wakeup_prach_eNB(ru->eNB_list[0], ru, *frame, *subframe); + goto next; + } + + eNB = eNB_list[0]; + fp = &eNB->frame_parms; + for (antenna = 0; antenna < ru->nb_rx; antenna++) { + for (symbol = 0; symbol < 14; symbol++) { + int i; + uint16_t *p = (uint16_t *)(&s->buffers.ul[antenna][*subframe][symbol*1200*4]); + for (i = 0; i < 1200*2; i++) { + p[i] = htons(p[i]); + } + rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size]; +#if 1 + memcpy(rxdata + 2048 - 600, + &s->buffers.ul[antenna][*subframe][symbol*1200*4], + 600 * 4); + memcpy(rxdata, + &s->buffers.ul[antenna][*subframe][symbol*1200*4] + 600*4, + 600 * 4); +#endif + } + } + + s->buffers.ul_busy[0][*subframe] = 0; + s->buffers.ul_busy[1][*subframe] = 0; + signal_ul_buffer(&s->buffers, *subframe); + unlock_ul_buffer(&s->buffers, *subframe); + + //printf("BENETEL: %s (f.sf %d.%d)\n", __FUNCTION__, *frame, *subframe); + + RU_proc_t *proc = &ru->proc; + extern uint16_t sf_ahead; + int f = *frame; + int sf = *subframe; + + //calculate timestamp_rx, timestamp_tx based on frame and subframe + proc->tti_rx = sf; + proc->frame_rx = f; + proc->timestamp_rx = ((proc->frame_rx * 10) + proc->tti_rx ) * fp->samples_per_tti ; + + if (get_nprocs()<=4) { + proc->tti_tx = (sf+sf_ahead)%10; + proc->frame_tx = (sf>(9-sf_ahead)) ? (f+1)&1023 : f; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,f); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,sf); + proc->symbol_mask[sf] = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff); + +} + +void benetel_fh_if4p5_south_out(RU_t *ru, + int frame, + int subframe, + uint64_t timestamp) +{ + benetel_eth_state_t *s = ru->ifdevice.priv; + PHY_VARS_eNB **eNB_list = ru->eNB_list, *eNB; + LTE_DL_FRAME_PARMS *fp; + int symbol; + int32_t *txdata; + int aa; + + //printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, subframe, timestamp); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + + lock_dl_buffer(&s->buffers, subframe); + if (s->buffers.dl_busy[0][subframe] || + s->buffers.dl_busy[1][subframe]) { + printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, subframe); + unlock_dl_buffer(&s->buffers, subframe); + return; + } + eNB = eNB_list[0]; + fp = &eNB->frame_parms; + if (ru->num_eNB != 1 || fp->ofdm_symbol_size != 2048 || + fp->Ncp != NORMAL || fp->symbols_per_tti != 14) { + printf("%s:%d:%s: unsupported configuration\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + for (aa = 0; aa < ru->nb_tx; aa++) { + for (symbol = 0; symbol < 14; symbol++) { + txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size]; +#if 1 + memcpy(&s->buffers.dl[aa][subframe][symbol*1200*4], + txdata + 2048 - 600, + 600 * 4); + memcpy(&s->buffers.dl[aa][subframe][symbol*1200*4] + 600*4, + txdata + 1, + 600 * 4); +#endif + int i; + uint16_t *p = (uint16_t *)(&s->buffers.dl[aa][subframe][symbol*1200*4]); + for (i = 0; i < 1200*2; i++) { + p[i] = htons(p[i]); + } + } + } + + s->buffers.dl_busy[0][subframe] = 0x3fff; + s->buffers.dl_busy[1][subframe] = 0x3fff; + unlock_dl_buffer(&s->buffers, subframe); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.frame_tx); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.tti_tx); + +} + +void *get_internal_parameter(char *name) +{ + printf("BENETEL: %s\n", __FUNCTION__); + + if (!strcmp(name, "fh_if4p5_south_in")) + return benetel_fh_if4p5_south_in; + if (!strcmp(name, "fh_if4p5_south_out")) + return benetel_fh_if4p5_south_out; + + return NULL; +} + +__attribute__((__visibility__("default"))) +int transport_init(openair0_device *device, + openair0_config_t *openair0_cfg, + eth_params_t * eth_params ) +{ + benetel_eth_state_t *eth; + + printf("BENETEL: %s\n", __FUNCTION__); + + device->Mod_id = 0; + device->transp_type = ETHERNET_TP; + device->trx_start_func = trx_benetel_start; + device->trx_get_stats_func = trx_benetel_get_stats; + device->trx_reset_stats_func = trx_benetel_reset_stats; + device->trx_end_func = trx_benetel_end; + device->trx_stop_func = trx_benetel_stop; + device->trx_set_freq_func = trx_benetel_set_freq; + device->trx_set_gains_func = trx_benetel_set_gains; + + device->trx_write_func = trx_benetel_write_raw; + device->trx_read_func = trx_benetel_read_raw; + + device->trx_ctlsend_func = trx_benetel_ctlsend; + device->trx_ctlrecv_func = trx_benetel_ctlrecv; + + device->get_internal_parameter = get_internal_parameter; + + eth = calloc(1, sizeof(benetel_eth_state_t)); + if (eth == NULL) { + AssertFatal(0==1, "out of memory\n"); + } + + eth->e.flags = ETH_RAW_IF4p5_MODE; + eth->e.compression = NO_COMPRESS; + eth->e.if_name = eth_params->local_if_name; + device->priv = eth; + device->openair0_cfg=&openair0_cfg[0]; + + if (openair0_cfg->sdr_addrs == NULL) { + printf("benetel: fatal: sdr_addrs not set in configuration file\n"); + exit(1); + } + + eth->dpdk_main_command_line = strdup(openair0_cfg->sdr_addrs); + if (eth->dpdk_main_command_line == NULL) { + AssertFatal(0==1, "out of memory\n"); + } + + eth->last_msg = -1; + + init_buffers(ð->buffers); + + return 0; +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c b/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c new file mode 100644 index 0000000000..2b6ef37e6f --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c @@ -0,0 +1,774 @@ +/* license: to be defined */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "low.h" + +// HEADER DEFINITION +#define ANT_NUM buf[23] +#define PAYLOAD_1 buf[20] +#define PAYLOAD_2 buf[21] +#define ETH_TYPE buf[17] +#define SYMBOL buf[29] +#define SUBFRAME buf[28] +#define FRAME buf[27] + +static volatile bool force_quit; + +unsigned short iq[33600]; +unsigned char iq_swap[67200]; + +unsigned short *iq_ptr[14]; +unsigned int dl_start = 0; + +/* MAC updating enabled by default */ +static int mac_updating = 1; +#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 +#define MAX_PKT_BURST 32 +#define BURST_TX_DRAIN_US 5 /* TX drain every ~100us */ +#define MEMPOOL_CACHE_SIZE 256 +/* + * Configurable number of RX/TX ring descriptors + */ +#define RTE_TEST_RX_DESC_DEFAULT 1024 +#define RTE_TEST_TX_DESC_DEFAULT 1024 +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; +/* ethernet addresses of ports */ +static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; +/* mask of enabled ports */ +static uint32_t l2fwd_enabled_port_mask = 0; +/* list of enabled ports */ +static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; +static unsigned int l2fwd_rx_queue_per_lcore = 1; +#define MAX_RX_QUEUE_PER_LCORE 16 +#define MAX_TX_QUEUE_PER_PORT 16 +struct lcore_queue_conf { + unsigned n_rx_port; + unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; +} __rte_cache_aligned; +struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; +static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; +static struct rte_eth_conf port_conf = { + .rxmode = { + .split_hdr_size = 0, + .offloads = DEV_RX_OFFLOAD_JUMBO_FRAME, + .split_hdr_size = 0, + .max_rx_pkt_len = 9500, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, +}; +struct rte_mempool * l2fwd_pktmbuf_pool = NULL; +/* Per-port statistics struct */ +struct l2fwd_port_statistics { + uint64_t tx; + uint64_t rx; + uint64_t dropped; +} __rte_cache_aligned; +struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; +#define MAX_TIMER_PERIOD 86400 /* 1 day max */ +/* A tsc-based timer responsible for triggering statistics printout */ +static uint64_t timer_period = 10; /* default period is 10 seconds */ +/* Print out statistics on packets dropped */ +static void +print_stats(void) +{ + uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; + unsigned portid; + total_packets_dropped = 0; + total_packets_tx = 0; + total_packets_rx = 0; + const char clr[] = { 27, '[', '2', 'J', '\0' }; + const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); + printf("\nPort statistics ===================================="); + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { + /* skip disabled ports */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + printf("\nStatistics for port %u ------------------------------" + "\nPackets sent: %24"PRIu64 + "\nPackets received: %20"PRIu64 + "\nPackets dropped: %21"PRIu64, + portid, + port_statistics[portid].tx, + port_statistics[portid].rx, + port_statistics[portid].dropped); + total_packets_dropped += port_statistics[portid].dropped; + total_packets_tx += port_statistics[portid].tx; + total_packets_rx += port_statistics[portid].rx; + } + printf("\nAggregate statistics ===============================" + "\nTotal packets sent: %18"PRIu64 + "\nTotal packets received: %14"PRIu64 + "\nTotal packets dropped: %15"PRIu64, + total_packets_tx, + total_packets_rx, + total_packets_dropped); + printf("\n====================================================\n"); +} +static void +l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs) +{ + unsigned char *buf, *buf_tx; + unsigned int len; + struct ether_hdr *eth; + + unsigned dst_port; + int sent, prach_ctrl = 0; + struct rte_eth_dev_tx_buffer *buffer; + + unsigned char * IQ_ptr; + + ul_packet_t p; + + buf = rte_pktmbuf_mtod(m, unsigned char *); + //rte_memdump(stdout, "Rx Packet",buf ,34); + eth = rte_pktmbuf_mtod(m, struct ether_hdr *); + len = rte_pktmbuf_data_len(m); + + IQ_ptr = &buf[34]; + + //destination mac address (RRU MAC) + eth->d_addr.addr_bytes[0] = 0x02; + eth->d_addr.addr_bytes[1] = 0x00; + eth->d_addr.addr_bytes[2] = 0x5e; + eth->d_addr.addr_bytes[3] = 0x01; + eth->d_addr.addr_bytes[4] = 0x01; + eth->d_addr.addr_bytes[5] = 0x01; + + //source mac address (DU MAC) + eth->s_addr.addr_bytes[0] = 0xdd; + eth->s_addr.addr_bytes[1] = 0xdd; + eth->s_addr.addr_bytes[2] = 0xdd; + eth->s_addr.addr_bytes[3] = 0xdd; + eth->s_addr.addr_bytes[4] = 0xdd; + eth->s_addr.addr_bytes[5] = 0xdd; + + dst_port = l2fwd_dst_ports[portid]; + #if 1 + + if (buf[18] == 0xAA) //msg1 check + { + printf("\nHandshake MSG 1 Received\n"); + printf("\n====================================================\n"); + + buf[18] = 0xBB;//change to msg2 after receive msg1 + + printf("Handshake MSG 2 Sent\n"); + printf("\n====================================================\n"); + } + + #else + // Handshake Condition + if (buf[18] == 0x01 || buf[18] == 0x03) // ORAN handshake msgs. + { + if (buf[18] == 0x01) //msg1 check + { + printf("\nHandshake MSG 1 Received\n"); + printf("\n====================================================\n"); + + buf[18] = 0x02;//change to msg2 after receive msg1 + + printf("Handshake MSG 2 Sent\n"); + printf("\n====================================================\n"); + } + + else if(buf[18] == 0x03) //msg3 check + { + printf("Handshake MSG 3 Sent\n"); + printf("\n====================================================\n"); + + buf[18] = 0x04; + + printf("Handshake MSG 4 Sent\n"); + printf("\n====================================================\n"); + } + } + #endif + // Trigger start send DL packets + if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && SYMBOL == 0x09 && ANT_NUM == 0x00 && dl_start == 0){ + + printf("\nU-Plane Started\n"); + printf("\n====================================================\n"); + + dl_start = 1; + } + + + if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce) { + p.frame = FRAME; + p.subframe = SUBFRAME >> 4; + p.slot = 0; /* unused */ + p.symbol = SYMBOL; + p.antenna = ANT_NUM; + memcpy(p.iq, IQ_ptr, 4800); + store_ul(bs, &p); + } + + // U-PLANE UL PROCESSING + if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && dl_start == 1) + { + int a = ANT_NUM; + int tx_frame = FRAME; + int tx_subframe = SUBFRAME >> 4; + int tx_symbol = SYMBOL + 5; + if (tx_symbol > 13) { + tx_symbol -= 14; + tx_subframe++; + if (tx_subframe == 10) { + tx_subframe = 0; + tx_frame = (tx_frame + 1) & 255; + } + } + +// ANT_NUM = 0x00; +// SYMBOL = (SYMBOL + 5) % 14; + PAYLOAD_2 = 0xc8; + + FRAME = tx_frame; + SUBFRAME = tx_subframe << 4; + SYMBOL = tx_symbol; + + /* send actual DL data (if available) */ + lock_dl_buffer(bs->buffers, tx_subframe); + if (!(bs->buffers->dl_busy[a][tx_subframe] & (1 << tx_symbol))) { + printf("%s: warning, DL underflow (antenna %d sf.symbol %d.%d)\n", + __FUNCTION__, + a, + tx_subframe, tx_symbol); + memset(IQ_ptr, 0, 1200 * 4); + } else { + memcpy(IQ_ptr, bs->buffers->dl[a][tx_subframe] + tx_symbol * 1200*4, + 1200*4); + } + bs->buffers->dl_busy[a][tx_subframe] &= ~(1 << tx_symbol); + unlock_dl_buffer(bs->buffers, tx_subframe); + } + + // U-PLANE PRACH PROCESSING + else if(PAYLOAD_1 == 0x0d && PAYLOAD_2 == 0x28){ + if (ANT_NUM == 0) { + store_prach(bs, FRAME, SUBFRAME>>4, IQ_ptr); + } + + rte_pktmbuf_free(m); + return; + } + + // Send Packets + buffer = tx_buffer[dst_port]; + + sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); + + if (sent) + port_statistics[dst_port].tx += sent; + +} +/* main processing loop */ +static void +l2fwd_main_loop(benetel_t *bs) +{ + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + struct rte_mbuf *m; + int sent; + unsigned lcore_id; + uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; + unsigned i, j, portid, nb_rx; + struct lcore_queue_conf *qconf; + const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * + BURST_TX_DRAIN_US; + struct rte_eth_dev_tx_buffer *buffer; + prev_tsc = 0; + timer_tsc = 0; + lcore_id = rte_lcore_id(); + qconf = &lcore_queue_conf[lcore_id]; + if (qconf->n_rx_port == 0) { + RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); + return; + } + RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); + for (i = 0; i < qconf->n_rx_port; i++) { + portid = qconf->rx_port_list[i]; + RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, + portid); + } + while (!force_quit) { + cur_tsc = rte_rdtsc(); + /* + * TX burst queue drain + */ + diff_tsc = cur_tsc - prev_tsc; + if (unlikely(diff_tsc > drain_tsc)) { + for (i = 0; i < qconf->n_rx_port; i++) { + portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; + buffer = tx_buffer[portid]; + sent = rte_eth_tx_buffer_flush(portid, 0, buffer); + if (sent) + port_statistics[portid].tx += sent; + } + /* if timer is enabled */ + if (timer_period > 0) { + /* advance the timer */ + timer_tsc += diff_tsc; + /* if timer has reached its timeout */ + if (unlikely(timer_tsc >= timer_period)) { + /* do this only on master core */ + if (lcore_id == rte_get_master_lcore()) { + //print_stats(); + /* reset the timer */ + timer_tsc = 0; + } + } + } + prev_tsc = cur_tsc; + } + /* + * Read packet from RX queues + */ + for (i = 0; i < qconf->n_rx_port; i++) { + portid = qconf->rx_port_list[i]; + nb_rx = rte_eth_rx_burst(portid, 0, + pkts_burst, MAX_PKT_BURST); + port_statistics[portid].rx += nb_rx; + for (j = 0; j < nb_rx; j++) { + m = pkts_burst[j]; + rte_prefetch0(rte_pktmbuf_mtod(m, void *)); + l2fwd_simple_forward(m, portid, bs); + } + } + } +} +static int +l2fwd_launch_one_lcore(void *bs) +{ + l2fwd_main_loop(bs); + return 0; +} +/* display usage */ +static void +l2fwd_usage(const char *prgname) +{ + printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" + " -p PORTMASK: hexadecimal bitmask of ports to configure\n" + " -q NQ: number of queue (=ports) per lcore (default is 1)\n" + " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n" + " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n" + " When enabled:\n" + " - The source MAC address is replaced by the TX port MAC address\n" + " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n", + prgname); +} +static int +l2fwd_parse_portmask(const char *portmask) +{ + char *end = NULL; + unsigned long pm; + /* parse hexadecimal string */ + pm = strtoul(portmask, &end, 16); + if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (pm == 0) + return -1; + return pm; +} +static unsigned int +l2fwd_parse_nqueue(const char *q_arg) +{ + char *end = NULL; + unsigned long n; + /* parse hexadecimal string */ + n = strtoul(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return 0; + if (n == 0) + return 0; + if (n >= MAX_RX_QUEUE_PER_LCORE) + return 0; + return n; +} +static int +l2fwd_parse_timer_period(const char *q_arg) +{ + char *end = NULL; + int n; + /* parse number string */ + n = strtol(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (n >= MAX_TIMER_PERIOD) + return -1; + return n; +} +static const char short_options[] = + "p:" /* portmask */ + "q:" /* number of queues */ + "T:" /* timer period */ + ; +#define CMD_LINE_OPT_MAC_UPDATING "mac-updating" +#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating" +enum { + /* long options mapped to a short option */ + /* first long only option value must be >= 256, so that we won't + * conflict with short options */ + CMD_LINE_OPT_MIN_NUM = 256, +}; +static const struct option lgopts[] = { + { CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1}, + { CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0}, + {NULL, 0, 0, 0} +}; +/* Parse the argument given in the command line of the application */ +static int +l2fwd_parse_args(int argc, char **argv) +{ + int opt, ret, timer_secs; + char **argvopt; + int option_index; + char *prgname = argv[0]; + argvopt = argv; + while ((opt = getopt_long(argc, argvopt, short_options, + lgopts, &option_index)) != EOF) { + switch (opt) { + /* portmask */ + case 'p': + l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); + if (l2fwd_enabled_port_mask == 0) { + printf("invalid portmask\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* nqueue */ + case 'q': + l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); + if (l2fwd_rx_queue_per_lcore == 0) { + printf("invalid queue number\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* timer period */ + case 'T': + timer_secs = l2fwd_parse_timer_period(optarg); + if (timer_secs < 0) { + printf("invalid timer period\n"); + l2fwd_usage(prgname); + return -1; + } + timer_period = timer_secs; + break; + /* long options */ + case 0: + break; + default: + l2fwd_usage(prgname); + return -1; + } + } + if (optind >= 0) + argv[optind-1] = prgname; + ret = optind-1; + optind = 1; /* reset getopt lib */ + return ret; +} +/* Check the link status of all ports in up to 9s, and print them finally */ +static void +check_all_ports_link_status(uint32_t port_mask) +{ +#define CHECK_INTERVAL 100 /* 100ms */ +#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ + uint16_t portid; + uint8_t count, all_ports_up, print_flag = 0; + struct rte_eth_link link; + printf("\nChecking link status"); + fflush(stdout); + for (count = 0; count <= MAX_CHECK_TIME; count++) { + if (force_quit) + return; + all_ports_up = 1; + RTE_ETH_FOREACH_DEV(portid) { + if (force_quit) + return; + if ((port_mask & (1 << portid)) == 0) + continue; + memset(&link, 0, sizeof(link)); + rte_eth_link_get_nowait(portid, &link); + /* print link status if flag set */ + if (print_flag == 1) { + if (link.link_status) + printf( + "Port%d Link Up. Speed %u Mbps - %s\n", + portid, link.link_speed, + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? + ("full-duplex") : ("half-duplex\n")); + else + printf("Port %d Link Down\n", portid); + continue; + } + /* clear all_ports_up flag if any link down */ + if (link.link_status == ETH_LINK_DOWN) { + all_ports_up = 0; + break; + } + } + /* after finally printing all link status, get out */ + if (print_flag == 1) + break; + if (all_ports_up == 0) { + printf("."); + fflush(stdout); + rte_delay_ms(CHECK_INTERVAL); + } + /* set the print_flag if all ports up or timeout */ + if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { + print_flag = 1; + printf("done\n"); + } + } +} +static void +signal_handler(int signum) +{ + if (signum == SIGINT || signum == SIGTERM) { + printf("\n\nSignal %d received, preparing to exit...\n", + signum); + force_quit = true; + } +} +int +dpdk_main(int argc, char **argv, benetel_t *bs) +{ + struct lcore_queue_conf *qconf; + int ret; + uint16_t nb_ports; + uint16_t nb_ports_available = 0; + uint16_t portid, last_port; + unsigned lcore_id, rx_lcore_id; + unsigned nb_ports_in_mask = 0; + unsigned int nb_lcores = 0; + unsigned int nb_mbufs; + /* init EAL */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); + argc -= ret; + argv += ret; + force_quit = false; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + /* parse application arguments (after the EAL ones) */ + ret = l2fwd_parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); + printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled"); + /* convert to number of cycles */ + timer_period *= rte_get_timer_hz(); + nb_ports = rte_eth_dev_count_avail(); + if (nb_ports == 0) + rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); + /* check port mask to possible port mask */ + if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1)) + rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n", + (1 << nb_ports) - 1); + /* reset l2fwd_dst_ports */ + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) + l2fwd_dst_ports[portid] = 0; + last_port = 0; + /* + * Each logical core is assigned a dedicated TX queue on each port. + */ + RTE_ETH_FOREACH_DEV(portid) { + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + if (nb_ports_in_mask % 2) { + l2fwd_dst_ports[portid] = last_port; + l2fwd_dst_ports[last_port] = portid; + } + else + last_port = portid; + nb_ports_in_mask++; + } + if (nb_ports_in_mask % 2) { + printf("Notice: odd number of ports in portmask.\n"); + l2fwd_dst_ports[last_port] = last_port; + } + rx_lcore_id = 0; + qconf = NULL; + /* Initialize the port/queue configuration of each logical core */ + RTE_ETH_FOREACH_DEV(portid) { + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + /* get the lcore_id for this port */ + while (rte_lcore_is_enabled(rx_lcore_id) == 0 || + lcore_queue_conf[rx_lcore_id].n_rx_port == + l2fwd_rx_queue_per_lcore) { + rx_lcore_id++; + if (rx_lcore_id >= RTE_MAX_LCORE) + rte_exit(EXIT_FAILURE, "Not enough cores\n"); + } + if (qconf != &lcore_queue_conf[rx_lcore_id]) { + /* Assigned a new logical core in the loop above. */ + qconf = &lcore_queue_conf[rx_lcore_id]; + nb_lcores++; + } + qconf->rx_port_list[qconf->n_rx_port] = portid; + qconf->n_rx_port++; + printf("Lcore %u: RX port %u\n", rx_lcore_id, portid); + } + nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST + + nb_lcores * MEMPOOL_CACHE_SIZE), 8192U); + /* create the mbuf pool */ + l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs, + MEMPOOL_CACHE_SIZE, 0, 9680, + rte_socket_id()); + if (l2fwd_pktmbuf_pool == NULL) + rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); + /* Initialise each port */ + RTE_ETH_FOREACH_DEV(portid) { + struct rte_eth_rxconf rxq_conf; + struct rte_eth_txconf txq_conf; + struct rte_eth_conf local_port_conf = port_conf; + struct rte_eth_dev_info dev_info; + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { + printf("Skipping disabled port %u\n", portid); + continue; + } + nb_ports_available++; + /* init port */ + printf("Initializing port %u... ", portid); + fflush(stdout); + rte_eth_dev_info_get(portid, &dev_info); + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) + local_port_conf.txmode.offloads |= + DEV_TX_OFFLOAD_MBUF_FAST_FREE; + ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", + ret, portid); + ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, + &nb_txd); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot adjust number of descriptors: err=%d, port=%u\n", + ret, portid); + rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); + /* init one RX queue */ + fflush(stdout); + rxq_conf = dev_info.default_rxconf; + rxq_conf.offloads = local_port_conf.rxmode.offloads; + ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, + rte_eth_dev_socket_id(portid), + &rxq_conf, + l2fwd_pktmbuf_pool); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", + ret, portid); + /* init one TX queue on each port */ + fflush(stdout); + txq_conf = dev_info.default_txconf; + txq_conf.offloads = local_port_conf.txmode.offloads; + ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, + rte_eth_dev_socket_id(portid), + &txq_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", + ret, portid); + /* Initialize TX buffers */ + tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", + RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, + rte_eth_dev_socket_id(portid)); + if (tx_buffer[portid] == NULL) + rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", + portid); + rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); + ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], + rte_eth_tx_buffer_count_callback, + &port_statistics[portid].dropped); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot set error callback for tx buffer on port %u\n", + portid); + /* Start device */ + ret = rte_eth_dev_start(portid); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", + ret, portid); + printf("done: \n"); + rte_eth_promiscuous_enable(portid); + printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", + portid, + l2fwd_ports_eth_addr[portid].addr_bytes[0], + l2fwd_ports_eth_addr[portid].addr_bytes[1], + l2fwd_ports_eth_addr[portid].addr_bytes[2], + l2fwd_ports_eth_addr[portid].addr_bytes[3], + l2fwd_ports_eth_addr[portid].addr_bytes[4], + l2fwd_ports_eth_addr[portid].addr_bytes[5]); + /* initialize port stats */ + memset(&port_statistics, 0, sizeof(port_statistics)); + } + if (!nb_ports_available) { + rte_exit(EXIT_FAILURE, + "All available ports are disabled. Please set portmask.\n"); + } + check_all_ports_link_status(l2fwd_enabled_port_mask); + ret = 0; + /* launch per-lcore init on every lcore */ + rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, bs, CALL_MASTER); + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (rte_eal_wait_lcore(lcore_id) < 0) { + ret = -1; + break; + } + } + RTE_ETH_FOREACH_DEV(portid) { + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + printf("Closing port %d...", portid); + rte_eth_dev_stop(portid); + rte_eth_dev_close(portid); + printf(" Done\n"); + } + printf("Bye...\n"); + return ret; +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/low.c b/targets/ARCH/ETHERNET/benetel/4g/low.c new file mode 100644 index 0000000000..14783a700b --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/low.c @@ -0,0 +1,94 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "low.h" + +#include +#include +#include + +void store_ul(benetel_t *bs, ul_packet_t *ul) +{ + int a = ul->antenna; + + if (ul->subframe != bs->next_subframe[a] || + ul->symbol != bs->next_symbol[a]) { + printf("%s: fatal, antenna %d expected frame.sf.symbol %d.%d.%d, got %d.%d.%d\n", + __FUNCTION__, + a, + bs->expected_benetel_frame[a], bs->next_subframe[a], bs->next_symbol[a], + ul->frame, ul->subframe, ul->symbol); + exit(1); + } + + lock_ul_buffer(bs->buffers, bs->next_subframe[a]); + if (bs->buffers->ul_busy[a][bs->next_subframe[a]] & (1 << bs->next_symbol[a])) { + printf("%s: warning, UL overflow (sf.symbol %d.%d)\n", __FUNCTION__, + bs->next_subframe[a], bs->next_symbol[a]); + } + memcpy(bs->buffers->ul[a][bs->next_subframe[a]] + bs->next_symbol[a] * 1200*4, + ul->iq, 1200*4); + bs->buffers->ul_busy[a][bs->next_subframe[a]] |= (1 << bs->next_symbol[a]); + signal_ul_buffer(bs->buffers, bs->next_subframe[a]); + unlock_ul_buffer(bs->buffers, bs->next_subframe[a]); + + bs->next_symbol[a]++; + if (bs->next_symbol[a] == 14) { + bs->next_symbol[a] = 0; + bs->next_subframe[a] = (bs->next_subframe[a] + 1) % 10; + if (bs->next_subframe[a] == 0) { + bs->expected_benetel_frame[a]++; + bs->expected_benetel_frame[a] &= 255; + } + } +} + +void store_prach(benetel_t *bs, int frame, int subframe, void *data) +{ + static int last_frame = -1; + static int last_subframe = -1; + /* hack: antenna number is always 0, discard second packet with same f/sf */ + if (frame == last_frame && subframe == last_subframe) return; + last_frame = frame; + last_subframe = subframe; + + lock_ul_buffer(bs->buffers, subframe); + if (bs->buffers->prach_busy[subframe]) { + printf("store_prach: fatal: previous prach buffer not processed\n"); + unlock_ul_buffer(bs->buffers, subframe); + return; + } + bs->buffers->prach_busy[subframe] = 1; + memcpy(bs->buffers->prach[subframe], data, 849*4); + signal_ul_buffer(bs->buffers, subframe); + unlock_ul_buffer(bs->buffers, subframe); + +} + +void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); + +void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) +{ + if (!strcmp(ifname, "dpdk")) + return benetel_start_dpdk(ifname, buffers, dpdk_main_command_line); + printf("benetel: fatal: interface %s not supported, only dpdpk is supported\n", ifname); + exit(1); +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/low.h b/targets/ARCH/ETHERNET/benetel/4g/low.h new file mode 100644 index 0000000000..e74bf89163 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/low.h @@ -0,0 +1,50 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _BENETEL_4G_LOW_H_ +#define _BENETEL_4G_LOW_H_ + +#include "shared_buffers.h" + +typedef struct { + shared_buffers *buffers; + /* [2] is for two antennas */ + int next_subframe[2]; + int next_symbol[2]; + int expected_benetel_frame[2]; + char *dpdk_main_command_line; +} benetel_t; + +typedef struct { + int frame; + int subframe; + int slot; + int symbol; + int antenna; + unsigned char iq[4800]; +} ul_packet_t; + +void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); + +void store_ul(benetel_t *bs, ul_packet_t *ul); +void store_prach(benetel_t *bs, int frame, int subframe, void *data); + +#endif /* _BENETEL_4G_LOW_H_ */ diff --git a/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c b/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c new file mode 100644 index 0000000000..edf62a67e0 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c @@ -0,0 +1,119 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* those 2 lines for CPU_SET */ +#define _GNU_SOURCE +#include + +#include +#include +#include +#include + +#include "low.h" + +int dpdk_main(int argc, char **argv, benetel_t *); + +void *dpdk_thread(void *_bs) +{ + benetel_t *bs = _bs; + int n = 0; + char **v = NULL; // { "softmodem", "-n", "2", "-l", "8", "--", "-p", "0x2" }; + char *s = bs->dpdk_main_command_line; + char *tok; + + while ((tok = strtok(s, " ")) != NULL) { + n++; + v = realloc(v, n * sizeof(char *)); + if (v == NULL) { + printf("%s: out of memory\n", __FUNCTION__); + exit(1); + } + v[n-1] = tok; + s = NULL; + } + + dpdk_main(n, v, bs); + exit(1); + return 0; +} + +void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) +{ + benetel_t *bs; + + bs = calloc(1, sizeof(benetel_t)); + if (bs == NULL) { + printf("%s: out of memory\n", __FUNCTION__); + exit(1); + } + + bs->buffers = buffers; + + bs->expected_benetel_frame[0] = 255; + bs->expected_benetel_frame[1] = 255; + + bs->dpdk_main_command_line = dpdk_main_command_line; + + pthread_attr_t attr; + + if (pthread_attr_init(&attr) != 0) { + printf("pthread_attr_init failed\n"); + exit(1); + } + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(12,&cpuset); + if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset) != 0) { + printf("pthread_attr_setaffinity_np failed\n"); + exit(1); + } + + if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { + printf("pthread_attr_setschedpolicy failed\n"); + exit(1); + } + + struct sched_param params; + params.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (sched_get_priority_max(SCHED_FIFO) == -1) { + printf("sched_get_priority_max failed\n"); + exit(1); + } + if (pthread_attr_setschedparam(&attr, ¶ms) != 0) { + printf("pthread_setschedparam failed\n"); + exit(1); + } + + pthread_t t; + if (pthread_create(&t, &attr, dpdk_thread, bs) != 0) { + printf("%s: thread creation failed\n", __FUNCTION__); + exit(1); + } + + if (pthread_attr_destroy(&attr) != 0) { + printf("pthread_attr_init failed\n"); + exit(1); + } + + return bs; +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c new file mode 100644 index 0000000000..380cbabc73 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c @@ -0,0 +1,117 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "shared_buffers.h" + +#include +#include +#include + +void init_buffers(shared_buffers *s) +{ + int subframe; + + memset(s, 0, sizeof(*s)); + + for (subframe = 0; subframe < 10; subframe++) { + if (pthread_mutex_init(&s->m_dl[subframe], NULL) != 0 || + pthread_cond_init(&s->c_dl[subframe], NULL) != 0 || + pthread_mutex_init(&s->m_ul[subframe], NULL) != 0 || + pthread_cond_init(&s->c_ul[subframe], NULL) != 0) { + printf("%s: error initializing mutex/cond\n", __FUNCTION__); + exit(1); + } + } + + /* in FDD the eNB's first transmitted DL subframe is 4 but the device + * needs to have subframes 1, 2 and 3 ready. Let's pretend there are ready. + */ + s->dl_busy[0][1] = 0x3fff; + s->dl_busy[0][2] = 0x3fff; + s->dl_busy[0][3] = 0x3fff; + s->dl_busy[1][1] = 0x3fff; + s->dl_busy[1][2] = 0x3fff; + s->dl_busy[1][3] = 0x3fff; +} + +void lock_dl_buffer(shared_buffers *s, int subframe) +{ + if (pthread_mutex_lock(&s->m_dl[subframe]) != 0) { + printf("%s: fatal: lock fails\n", __FUNCTION__); + exit(1); + } +} + +void unlock_dl_buffer(shared_buffers *s, int subframe) +{ + if (pthread_mutex_unlock(&s->m_dl[subframe]) != 0) { + printf("%s: fatal: unlock fails\n", __FUNCTION__); + exit(1); + } +} + +void wait_dl_buffer(shared_buffers *s, int subframe) +{ + if (pthread_cond_wait(&s->c_dl[subframe], &s->m_dl[subframe]) != 0) { + printf("%s: fatal: cond_wait fails\n", __FUNCTION__); + exit(1); + } +} + +void signal_dl_buffer(shared_buffers *s, int subframe) +{ + if (pthread_cond_broadcast(&s->c_dl[subframe]) != 0) { + printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); + exit(1); + } +} + +void lock_ul_buffer(shared_buffers *s, int subframe) +{ + if (pthread_mutex_lock(&s->m_ul[subframe]) != 0) { + printf("%s: fatal: lock fails\n", __FUNCTION__); + exit(1); + } +} + +void unlock_ul_buffer(shared_buffers *s, int subframe) +{ + if (pthread_mutex_unlock(&s->m_ul[subframe]) != 0) { + printf("%s: fatal: unlock fails\n", __FUNCTION__); + exit(1); + } +} + +void wait_ul_buffer(shared_buffers *s, int subframe) +{ + if (pthread_cond_wait(&s->c_ul[subframe], &s->m_ul[subframe]) != 0) { + printf("%s: fatal: cond_wait fails\n", __FUNCTION__); + exit(1); + } +} + +void signal_ul_buffer(shared_buffers *s, int subframe) +{ + if (pthread_cond_broadcast(&s->c_ul[subframe]) != 0) { + printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); + exit(1); + } +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h new file mode 100644 index 0000000000..ed174265c5 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h @@ -0,0 +1,61 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _BENETEL_4G_SHARED_BUFFERS_H_ +#define _BENETEL_4G_SHARED_BUFFERS_H_ + +#include +#include + +typedef struct { + /* [2] is for two antennas */ + unsigned char dl[2][10][14*1200*4]; + unsigned char ul[2][10][14*1200*4]; + uint16_t dl_busy[2][10]; + uint16_t ul_busy[2][10]; + + pthread_mutex_t m_ul[10]; + pthread_cond_t c_ul[10]; + + pthread_mutex_t m_dl[10]; + pthread_cond_t c_dl[10]; + + unsigned char prach[10][849*4]; + unsigned char prach_busy[10]; + + /* statistics/error counting */ + int ul_overflow; + int dl_underflow; +} shared_buffers; + +void init_buffers(shared_buffers *s); + +void lock_dl_buffer(shared_buffers *s, int subframe); +void unlock_dl_buffer(shared_buffers *s, int subframe); +void wait_dl_buffer(shared_buffers *s, int subframe); +void signal_dl_buffer(shared_buffers *s, int subframe); + +void lock_ul_buffer(shared_buffers *s, int subframe); +void unlock_ul_buffer(shared_buffers *s, int subframe); +void wait_ul_buffer(shared_buffers *s, int subframe); +void signal_ul_buffer(shared_buffers *s, int subframe); + +#endif /* _BENETEL_4G_SHARED_BUFFERS_H_ */ diff --git a/targets/ARCH/ETHERNET/benetel/5g/benetel.c b/targets/ARCH/ETHERNET/benetel/5g/benetel.c new file mode 100644 index 0000000000..cededa968e --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/benetel.c @@ -0,0 +1,402 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include + +#include "common_lib.h" +#include "ethernet_lib.h" +#include "shared_buffers.h" +#include "low.h" +#include "openair1/PHY/defs_gNB.h" + +typedef struct { + eth_state_t e; + shared_buffers buffers; + rru_config_msg_type_t last_msg; + int capabilities_sent; + void *benetel_priv; + char *dpdk_main_command_line; +} benetel_eth_state_t; + +int trx_benetel_start(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return 0; +} + + +void trx_benetel_end(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); +} + + +int trx_benetel_stop(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_set_freq(openair0_device* device, + openair0_config_t *openair0_cfg, + int exmimo_dump_config) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_set_gains(openair0_device* device, + openair0_config_t *openair0_cfg) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_get_stats(openair0_device* device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_reset_stats(openair0_device* device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int ethernet_tune(openair0_device *device, + unsigned int option, + int value) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return 0; +} + +int trx_benetel_write_raw(openair0_device *device, + openair0_timestamp timestamp, + void **buff, int nsamps, int cc, int flags) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return nsamps*4; +} + +int trx_benetel_read_raw(openair0_device *device, + openair0_timestamp *timestamp, + void **buff, int nsamps, int cc) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return nsamps*4; +} + +char *msg_type(int t) +{ + static char *s[12] = { + "RAU_tick", + "RRU_capabilities", + "RRU_config", + "RRU_config_ok", + "RRU_start", + "RRU_stop", + "RRU_sync_ok", + "RRU_frame_resynch", + "RRU_MSG_max_num", + "RRU_check_sync", + "RRU_config_update", + "RRU_config_update_ok", + }; + + if (t < 0 || t > 11) return "UNKNOWN"; + return s[t]; +} + +int trx_benetel_ctlsend(openair0_device *device, void *msg, ssize_t msg_len) +{ + RRU_CONFIG_msg_t *rru_config_msg = msg; + benetel_eth_state_t *s = device->priv; + + printf("BENETEL: %s\n", __FUNCTION__); + + printf(" rru_config_msg->type %d [%s]\n", rru_config_msg->type, + msg_type(rru_config_msg->type)); + + s->last_msg = rru_config_msg->type; + + return msg_len; +} + +int trx_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len) +{ + RRU_CONFIG_msg_t *rru_config_msg = msg; + benetel_eth_state_t *s = device->priv; + + printf("BENETEL: %s\n", __FUNCTION__); + + if (s->last_msg == RAU_tick && s->capabilities_sent == 0) { + RRU_capabilities_t *cap; + rru_config_msg->type = RRU_capabilities; + rru_config_msg->len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); + cap = (RRU_capabilities_t*)&rru_config_msg->msg[0]; + cap->FH_fmt = OAI_IF4p5_only; + cap->num_bands = 1; + cap->band_list[0] = 78; + /* TODO: hardcoded to 1 for the moment, get the real value somehow... */ + cap->nb_rx[0] = 1; //device->openair0_cfg->rx_num_channels; + cap->nb_tx[0] = 1; //device->openair0_cfg->tx_num_channels; + cap->max_pdschReferenceSignalPower[0] = -27; + cap->max_rxgain[0] = 90; + + s->capabilities_sent = 1; + + return rru_config_msg->len; + } +#if 0 + if (s->last_msg == RRU_config) { + rru_config_msg->type = RRU_config_ok; + return 0; + } + if (s->last_msg == RRU_start) { +printf("***************** benetel start\n"); + s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); + } +#endif + if (s->last_msg == RRU_config) { + rru_config_msg->type = RRU_config_ok; + s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); + } + /* correct? */ +//printf("***************** benetel pause\n"); +// while (1) pause(); + + return 0; +} + +void benetel_fh_if4p5_south_in(RU_t *ru, + int *frame, + int *slot) +{ +//printf("XXX benetel_fh_if4p5_south_in %d %d\n", *frame, *slot); + benetel_eth_state_t *s = ru->ifdevice.priv; + NR_DL_FRAME_PARMS *fp; + int symbol; + int32_t *rxdata; + int antenna; + + lock_ul_buffer(&s->buffers, *slot); +#if 1 +next: + while (!((s->buffers.ul_busy[0][*slot] == 0x3fff && + s->buffers.ul_busy[1][*slot] == 0x3fff) || + s->buffers.prach_busy[*slot] == 1)) + wait_ul_buffer(&s->buffers, *slot); + if (s->buffers.prach_busy[*slot] == 1) { + int i; + int antenna = 0; + uint16_t *in; + uint16_t *out; + in = (uint16_t *)s->buffers.prach[*slot]; + out = (uint16_t *)ru->prach_rxsigF[0][antenna]; + for (i = 0; i < 839*2; i++) + out[i] = ntohs(in[i]); + s->buffers.prach_busy[*slot] = 0; + //printf("prach for f.sl %d.%d\n", *frame, *slot); + //ru->wakeup_prach_gNB(ru->gNB_list[0], ru, *frame, *slot); + goto next; + } +#endif + + fp = ru->nr_frame_parms; + for (antenna = 0; antenna < ru->nb_rx; antenna++) { + for (symbol = 0; symbol < 14; symbol++) { + int i; + int16_t *p = (int16_t *)(&s->buffers.ul[antenna][*slot][symbol*1272*4]); + for (i = 0; i < 1272*2; i++) { + p[i] = (int16_t)(ntohs(p[i])) / 16; + } + rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size]; +#if 0 +if (*slot == 0 && symbol == 0) +printf("rxdata in benetel_fh_if4p5_south_in %p\n", &ru->common.rxdataF[antenna][0]); +#endif +#if 1 + memcpy(rxdata + 2048 - 1272/2, + &s->buffers.ul[antenna][*slot][symbol*1272*4], + (1272/2) * 4); + memcpy(rxdata, + &s->buffers.ul[antenna][*slot][symbol*1272*4] + (1272/2)*4, + (1272/2) * 4); +#endif + } + } + + s->buffers.ul_busy[0][*slot] = 0; + s->buffers.ul_busy[1][*slot] = 0; + signal_ul_buffer(&s->buffers, *slot); + unlock_ul_buffer(&s->buffers, *slot); + + //printf("BENETEL: %s (f.sf %d.%d)\n", __FUNCTION__, *frame, *slot); + + RU_proc_t *proc = &ru->proc; + extern uint16_t sl_ahead; + int f = *frame; + int sl = *slot; + + //calculate timestamp_rx, timestamp_tx based on frame and slot + proc->tti_rx = sl; + proc->frame_rx = f; + /* TODO: be sure of samples_per_slot0 + FK: should use get_samples_per_slot(slot) + but for mu=1 its ok + */ + proc->timestamp_rx = ((proc->frame_rx * 20) + proc->tti_rx ) * fp->samples_per_slot0; + + if (get_nprocs()<=4) { + // why? what if there are more? + proc->tti_tx = (sl+sl_ahead)%20; + proc->frame_tx = (sl>(19-sl_ahead)) ? (f+1)&1023 : f; + } +} + +void benetel_fh_if4p5_south_out(RU_t *ru, + int frame, + int slot, + uint64_t timestamp) +{ + +//printf("XXX benetel_fh_if4p5_south_out %d %d %ld\n", frame, slot, timestamp); + benetel_eth_state_t *s = ru->ifdevice.priv; + NR_DL_FRAME_PARMS *fp; + int symbol; + int32_t *txdata; + int aa; + + //printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, slot, timestamp); + + lock_dl_buffer(&s->buffers, slot); + if (s->buffers.dl_busy[0][slot] || + s->buffers.dl_busy[1][slot]) { + printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, slot); + unlock_dl_buffer(&s->buffers, slot); + return; + } + + fp = ru->nr_frame_parms; + if (ru->num_gNB != 1 || fp->ofdm_symbol_size != 2048 || + fp->Ncp != NORMAL || fp->symbols_per_slot != 14) { + printf("%s:%d:%s: unsupported configuration\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + for (aa = 0; aa < ru->nb_tx; aa++) { + for (symbol = 0; symbol < 14; symbol++) { + txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size]; +#if 1 + memcpy(&s->buffers.dl[aa][slot][symbol*1272*4], + txdata + 2048 - (1272/2), + (1272/2) * 4); + memcpy(&s->buffers.dl[aa][slot][symbol*1272*4] + (1272/2)*4, + txdata, + (1272/2) * 4); +#endif + int i; + uint16_t *p = (uint16_t *)(&s->buffers.dl[aa][slot][symbol*1272*4]); + for (i = 0; i < 1272*2; i++) { + p[i] = htons(p[i]); + } + } + } + + s->buffers.dl_busy[0][slot] = 0x3fff; + s->buffers.dl_busy[1][slot] = 0x3fff; + unlock_dl_buffer(&s->buffers, slot); +} + +void *get_internal_parameter(char *name) +{ + printf("BENETEL: %s\n", __FUNCTION__); + + if (!strcmp(name, "fh_if4p5_south_in")) + return benetel_fh_if4p5_south_in; + if (!strcmp(name, "fh_if4p5_south_out")) + return benetel_fh_if4p5_south_out; + + return NULL; +} + +__attribute__((__visibility__("default"))) +int transport_init(openair0_device *device, + openair0_config_t *openair0_cfg, + eth_params_t * eth_params ) +{ + benetel_eth_state_t *eth; + + printf("BENETEL: %s\n", __FUNCTION__); + + device->Mod_id = 0; + device->transp_type = ETHERNET_TP; + device->trx_start_func = trx_benetel_start; + device->trx_get_stats_func = trx_benetel_get_stats; + device->trx_reset_stats_func = trx_benetel_reset_stats; + device->trx_end_func = trx_benetel_end; + device->trx_stop_func = trx_benetel_stop; + device->trx_set_freq_func = trx_benetel_set_freq; + device->trx_set_gains_func = trx_benetel_set_gains; + + device->trx_write_func = trx_benetel_write_raw; + device->trx_read_func = trx_benetel_read_raw; + + device->trx_ctlsend_func = trx_benetel_ctlsend; + device->trx_ctlrecv_func = trx_benetel_ctlrecv; + + device->get_internal_parameter = get_internal_parameter; + + eth = calloc(1, sizeof(benetel_eth_state_t)); + if (eth == NULL) { + AssertFatal(0==1, "out of memory\n"); + } + + eth->e.flags = ETH_RAW_IF4p5_MODE; + eth->e.compression = NO_COMPRESS; + eth->e.if_name = eth_params->local_if_name; + device->priv = eth; + device->openair0_cfg=&openair0_cfg[0]; + + if (openair0_cfg->sdr_addrs == NULL) { + printf("benetel: fatal: sdr_addrs not set in configuration file\n"); + exit(1); + } + + eth->dpdk_main_command_line = strdup(openair0_cfg->sdr_addrs); + if (eth->dpdk_main_command_line == NULL) { + AssertFatal(0==1, "out of memory\n"); + } + + eth->last_msg = -1; + + init_buffers(ð->buffers); + + return 0; +} diff --git a/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c b/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c new file mode 100644 index 0000000000..9b398e9bd9 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c @@ -0,0 +1,835 @@ +/* license: to be defined */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "low.h" + +// HEADER DEFINITION +#define ANT_NUM buf[23] +#define PAYLOAD_1 buf[20] +#define PAYLOAD_2 buf[21] +#define ETH_TYPE buf[17] +#define SYMBOL buf[29] +#define SUBFRAME buf[28] +#define FRAME buf[27] + +static volatile bool force_quit; + +unsigned short iq[712320]; +unsigned char iq_swap[1424640]; + +unsigned short *iq_ptr[14]; +unsigned int dl_start = 0, slot_id_ctrl = 0, count_symbol = 0, sf = 0x10; + +/* MAC updating enabled by default */ +static int mac_updating = 1; +#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 +#define MAX_PKT_BURST 32 +#define BURST_TX_DRAIN_US 5 /* TX drain every ~100us */ +#define MEMPOOL_CACHE_SIZE 256 +/* + * Configurable number of RX/TX ring descriptors + */ +#define RTE_TEST_RX_DESC_DEFAULT 1024 +#define RTE_TEST_TX_DESC_DEFAULT 1024 +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; +/* ethernet addresses of ports */ +static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; +/* mask of enabled ports */ +static uint32_t l2fwd_enabled_port_mask = 0; +/* list of enabled ports */ +static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; +static unsigned int l2fwd_rx_queue_per_lcore = 1; +#define MAX_RX_QUEUE_PER_LCORE 16 +#define MAX_TX_QUEUE_PER_PORT 16 +struct lcore_queue_conf { + unsigned n_rx_port; + unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; +} __rte_cache_aligned; +struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; +static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; +static struct rte_eth_conf port_conf = { + .rxmode = { + .split_hdr_size = 0, + .offloads = DEV_RX_OFFLOAD_JUMBO_FRAME, + .split_hdr_size = 0, + .max_rx_pkt_len = 9500, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, +}; +struct rte_mempool * l2fwd_pktmbuf_pool = NULL; +/* Per-port statistics struct */ +struct l2fwd_port_statistics { + uint64_t tx; + uint64_t rx; + uint64_t dropped; +} __rte_cache_aligned; +struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; +#define MAX_TIMER_PERIOD 86400 /* 1 day max */ +/* A tsc-based timer responsible for triggering statistics printout */ +static uint64_t timer_period = 10; /* default period is 10 seconds */ +/* Print out statistics on packets dropped */ +static void +print_stats(void) +{ + uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; + unsigned portid; + total_packets_dropped = 0; + total_packets_tx = 0; + total_packets_rx = 0; + const char clr[] = { 27, '[', '2', 'J', '\0' }; + const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); + printf("\nPort statistics ===================================="); + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { + /* skip disabled ports */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + printf("\nStatistics for port %u ------------------------------" + "\nPackets sent: %24"PRIu64 + "\nPackets received: %20"PRIu64 + "\nPackets dropped: %21"PRIu64, + portid, + port_statistics[portid].tx, + port_statistics[portid].rx, + port_statistics[portid].dropped); + total_packets_dropped += port_statistics[portid].dropped; + total_packets_tx += port_statistics[portid].tx; + total_packets_rx += port_statistics[portid].rx; + } + printf("\nAggregate statistics ===============================" + "\nTotal packets sent: %18"PRIu64 + "\nTotal packets received: %14"PRIu64 + "\nTotal packets dropped: %15"PRIu64, + total_packets_tx, + total_packets_rx, + total_packets_dropped); + printf("\n====================================================\n"); +} +static void +l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs) +{ + unsigned char *buf, *buf_tx; + unsigned int len; + struct ether_hdr *eth; + + unsigned dst_port; + int sent, prach_ctrl = 0; + struct rte_eth_dev_tx_buffer *buffer; + + unsigned char * IQ_ptr; + + ul_packet_t p; + + buf = rte_pktmbuf_mtod(m, unsigned char *); + //DD Debug + //rte_memdump(stdout, "Rx Packet",buf ,34); + eth = rte_pktmbuf_mtod(m, struct ether_hdr *); + len = rte_pktmbuf_data_len(m); + + IQ_ptr = &buf[34]; + if (portid == 0) + { + //destination mac address (RRU MAC) + /*eth->d_addr.addr_bytes[0] = 0x02; + eth->d_addr.addr_bytes[1] = 0x00; + eth->d_addr.addr_bytes[2] = 0x5e; + eth->d_addr.addr_bytes[3] = 0x01; + eth->d_addr.addr_bytes[4] = 0x01; + eth->d_addr.addr_bytes[5] = 0x01;*/ + + eth->d_addr.addr_bytes[0] = buf[6]; + eth->d_addr.addr_bytes[1] = buf[7]; + eth->d_addr.addr_bytes[2] = buf[8]; + eth->d_addr.addr_bytes[3] = buf[9]; + eth->d_addr.addr_bytes[4] = buf[10]; + eth->d_addr.addr_bytes[5] = buf[11]; + + //source mac address (DU MAC) + eth->s_addr.addr_bytes[0] = 0xdd; + eth->s_addr.addr_bytes[1] = 0xdd; + eth->s_addr.addr_bytes[2] = 0xdd; + eth->s_addr.addr_bytes[3] = 0xdd; + eth->s_addr.addr_bytes[4] = 0xdd; + eth->s_addr.addr_bytes[5] = 0xdd; + } + else + { + //destination mac address (RRU MAC) + /*eth->d_addr.addr_bytes[0] = 0x02; + eth->d_addr.addr_bytes[1] = 0x00; + eth->d_addr.addr_bytes[2] = 0x5e; + eth->d_addr.addr_bytes[3] = 0x01; + eth->d_addr.addr_bytes[4] = 0x01; + eth->d_addr.addr_bytes[5] = 0x01;*/ + + eth->d_addr.addr_bytes[0] = buf[6]; + eth->d_addr.addr_bytes[1] = buf[7]; + eth->d_addr.addr_bytes[2] = buf[8]; + eth->d_addr.addr_bytes[3] = buf[9]; + eth->d_addr.addr_bytes[4] = buf[10]; + eth->d_addr.addr_bytes[5] = buf[11]; + //source mac address (DU MAC) + eth->s_addr.addr_bytes[0] = 0xdd; + eth->s_addr.addr_bytes[1] = 0xdd; + eth->s_addr.addr_bytes[2] = 0xdd; + eth->s_addr.addr_bytes[3] = 0xdd; + eth->s_addr.addr_bytes[4] = 0xdd; + eth->s_addr.addr_bytes[5] = 0xde; + + } + dst_port = l2fwd_dst_ports[portid]; + //DD Debug + //printf("dstPort =%d\n", dst_port); + // Handshake Condition + if (buf[18] == 0xAA ) // ORAN handshake msgs. + { + printf("\n Start UP Request Received\n"); + printf("\n====================================================\n"); + + buf[18] = 0xBB;//change to msg2 after receive msg1 + + printf(" Start Up Response Sent\n"); + printf("\n====================================================\n"); + + } + + // Trigger start send DL packets + if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && SYMBOL == 0x44 && ANT_NUM == 0x00 && SUBFRAME == 0x00 && dl_start == 0){ + + printf("\nU-Plane Started\n"); + printf("\n====================================================\n"); + + dl_start = 1; + count_symbol = 28; + } + + + if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4) { + int subframe = SUBFRAME >> 4; + int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); + p.frame = FRAME; + p.slot = subframe * 2 + slot; + p.symbol = SYMBOL & 0x3f; + p.antenna = ANT_NUM; + memcpy(p.iq, IQ_ptr, 5088); + store_ul(bs, &p); + // if (p.symbol==0) printf("store ul f.sl.sy %d.%d.%d\n", p.frame, p.slot, p.symbol); + } + + // U-PLANE UL PROCESSING + if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && dl_start == 1) + { + int a = ANT_NUM & 0x01; + int frame = FRAME; + int subframe = SUBFRAME >> 4; + int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); + int symbol = SYMBOL & 0x3f; + int oai_slot; + + int tx_frame = frame; + int tx_subframe = subframe; + int tx_slot = slot; + int tx_symbol = symbol + 10; + + if (tx_symbol > 13) { + tx_symbol -= 14; + tx_slot++; + if (tx_slot == 2) { + tx_slot = 0; + tx_subframe++; + if (tx_subframe == 10) { + tx_subframe = 0; + tx_frame = (tx_frame + 1) & 255; + } + } + } + + // Mask the symbol bits from UL packet received and apply the shift. + SYMBOL = ((SYMBOL & 0b00111111) + 10) % 14; + + ANT_NUM = a; + SUBFRAME = sf; + + if (a == 1) + slot_id_ctrl++; + + // Slot id control for DL + if (slot_id_ctrl > 13) { + SYMBOL = SYMBOL | 0b01000000; + + if (a == 1) { + if (slot_id_ctrl > 27) { + slot_id_ctrl = 0; + sf = sf + 0x10; + + if (sf > 0x90){ + sf = 0; + } + } + } + } + + /* send actual DL data (if available) */ + oai_slot = tx_subframe * 2 + tx_slot; + lock_dl_buffer(bs->buffers, oai_slot); + if (!(bs->buffers->dl_busy[a][oai_slot] & (1 << tx_symbol))) { + //printf("%s: warning, DL underflow (antenna %d sl.symbol %d.%d)\n", __FUNCTION__,a, oai_slot, tx_symbol); + memset(IQ_ptr, 0, 1272 * 4); + } else { + memcpy(IQ_ptr, bs->buffers->dl[a][oai_slot] + tx_symbol * 1272*4, + 1272*4); + } + //printf("DL buffer f sf slot symbol %d %d %d %d (sf %d)\n", tx_frame, tx_subframe, tx_slot, tx_symbol, (int)sf); + bs->buffers->dl_busy[a][oai_slot] &= ~(1 << tx_symbol); + unlock_dl_buffer(bs->buffers, oai_slot); + } + + // U-PLANE PRACH PROCESSING + else if(PAYLOAD_1 == 0x0d && PAYLOAD_2 == 0x28){ + if (ANT_NUM == 0) { + int subframe = SUBFRAME >> 4; + //int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); + if (subframe==9) { + //printf("store prach f.sf.sl %d.%d.%d %d\n", FRAME, subframe, slot, subframe * 2 + slot); + store_prach(bs, FRAME, subframe * 2 + 1, IQ_ptr); + } + } + rte_pktmbuf_free(m); + return; + } + + // Send Packets + buffer = tx_buffer[dst_port]; + + sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); + + if (sent) + port_statistics[dst_port].tx += sent; + +} +/* main processing loop */ +static void +l2fwd_main_loop(benetel_t *bs) +{ + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + struct rte_mbuf *m; + int sent; + unsigned lcore_id; + uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; + unsigned i, j, portid, nb_rx; + struct lcore_queue_conf *qconf; + const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * + BURST_TX_DRAIN_US; + struct rte_eth_dev_tx_buffer *buffer; + prev_tsc = 0; + timer_tsc = 0; + lcore_id = rte_lcore_id(); + qconf = &lcore_queue_conf[lcore_id]; + if (qconf->n_rx_port == 0) { + RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); + return; + } + RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); + for (i = 0; i < qconf->n_rx_port; i++) { + portid = qconf->rx_port_list[i]; + RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, + portid); + } + while (!force_quit) { + cur_tsc = rte_rdtsc(); + /* + * TX burst queue drain + */ + diff_tsc = cur_tsc - prev_tsc; + if (unlikely(diff_tsc > drain_tsc)) { + for (i = 0; i < qconf->n_rx_port; i++) { + portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; + buffer = tx_buffer[portid]; + sent = rte_eth_tx_buffer_flush(portid, 0, buffer); + if (sent) + port_statistics[portid].tx += sent; + } + /* if timer is enabled */ + if (timer_period > 0) { + /* advance the timer */ + timer_tsc += diff_tsc; + /* if timer has reached its timeout */ + if (unlikely(timer_tsc >= timer_period)) { + /* do this only on master core */ + if (lcore_id == rte_get_master_lcore()) { + print_stats(); + /* reset the timer */ + timer_tsc = 0; + } + } + } + prev_tsc = cur_tsc; + } + /* + * Read packet from RX queues + */ + for (i = 0; i < qconf->n_rx_port; i++) { + portid = qconf->rx_port_list[i]; + nb_rx = rte_eth_rx_burst(portid, 0, + pkts_burst, MAX_PKT_BURST); + port_statistics[portid].rx += nb_rx; + for (j = 0; j < nb_rx; j++) { + m = pkts_burst[j]; + rte_prefetch0(rte_pktmbuf_mtod(m, void *)); + l2fwd_simple_forward(m, portid, bs); + } + } + } +} +static int +l2fwd_launch_one_lcore(void *bs) +{ + l2fwd_main_loop(bs); + return 0; +} +/* display usage */ +static void +l2fwd_usage(const char *prgname) +{ + printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" + " -p PORTMASK: hexadecimal bitmask of ports to configure\n" + " -q NQ: number of queue (=ports) per lcore (default is 1)\n" + " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n" + " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n" + " When enabled:\n" + " - The source MAC address is replaced by the TX port MAC address\n" + " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n", + prgname); +} +static int +l2fwd_parse_portmask(const char *portmask) +{ + char *end = NULL; + unsigned long pm; + /* parse hexadecimal string */ + pm = strtoul(portmask, &end, 16); + if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (pm == 0) + return -1; + return pm; +} +static unsigned int +l2fwd_parse_nqueue(const char *q_arg) +{ + char *end = NULL; + unsigned long n; + /* parse hexadecimal string */ + n = strtoul(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return 0; + if (n == 0) + return 0; + if (n >= MAX_RX_QUEUE_PER_LCORE) + return 0; + return n; +} +static int +l2fwd_parse_timer_period(const char *q_arg) +{ + char *end = NULL; + int n; + /* parse number string */ + n = strtol(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (n >= MAX_TIMER_PERIOD) + return -1; + return n; +} +static const char short_options[] = + "p:" /* portmask */ + "q:" /* number of queues */ + "T:" /* timer period */ + ; +#define CMD_LINE_OPT_MAC_UPDATING "mac-updating" +#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating" +enum { + /* long options mapped to a short option */ + /* first long only option value must be >= 256, so that we won't + * conflict with short options */ + CMD_LINE_OPT_MIN_NUM = 256, +}; +static const struct option lgopts[] = { + { CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1}, + { CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0}, + {NULL, 0, 0, 0} +}; +/* Parse the argument given in the command line of the application */ +static int +l2fwd_parse_args(int argc, char **argv) +{ + int opt, ret, timer_secs; + char **argvopt; + int option_index; + char *prgname = argv[0]; + argvopt = argv; + while ((opt = getopt_long(argc, argvopt, short_options, + lgopts, &option_index)) != EOF) { + switch (opt) { + /* portmask */ + case 'p': + l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); + if (l2fwd_enabled_port_mask == 0) { + printf("invalid portmask\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* nqueue */ + case 'q': + l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); + if (l2fwd_rx_queue_per_lcore == 0) { + printf("invalid queue number\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* timer period */ + case 'T': + timer_secs = l2fwd_parse_timer_period(optarg); + if (timer_secs < 0) { + printf("invalid timer period\n"); + l2fwd_usage(prgname); + return -1; + } + timer_period = timer_secs; + break; + /* long options */ + case 0: + break; + case 'proc-type': + break; + case 'socket-mem': + break; + case 'file-prefix': + l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); + if (l2fwd_rx_queue_per_lcore == 0) { + printf("invalid queue number\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* timer period */ + /* timer period */ + /* timer period */ + default: + l2fwd_usage(prgname); + return -1; + } + } + if (optind >= 0) + argv[optind-1] = prgname; + ret = optind-1; + optind = 1; /* reset getopt lib */ + return ret; +} +/* Check the link status of all ports in up to 9s, and print them finally */ +static void +check_all_ports_link_status(uint32_t port_mask) +{ +#define CHECK_INTERVAL 100 /* 100ms */ +#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ + uint16_t portid; + uint8_t count, all_ports_up, print_flag = 0; + struct rte_eth_link link; + printf("\nChecking link status"); + fflush(stdout); + for (count = 0; count <= MAX_CHECK_TIME; count++) { + if (force_quit) + return; + all_ports_up = 1; + RTE_ETH_FOREACH_DEV(portid) { + if (force_quit) + return; + if ((port_mask & (1 << portid)) == 0) + continue; + memset(&link, 0, sizeof(link)); + rte_eth_link_get_nowait(portid, &link); + /* print link status if flag set */ + if (print_flag == 1) { + if (link.link_status) + printf( + "Port%d Link Up. Speed %u Mbps - %s\n", + portid, link.link_speed, + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? + ("full-duplex") : ("half-duplex\n")); + else + printf("Port %d Link Down\n", portid); + continue; + } + /* clear all_ports_up flag if any link down */ + if (link.link_status == ETH_LINK_DOWN) { + all_ports_up = 0; + break; + } + } + /* after finally printing all link status, get out */ + if (print_flag == 1) + break; + if (all_ports_up == 0) { + printf("."); + fflush(stdout); + rte_delay_ms(CHECK_INTERVAL); + } + /* set the print_flag if all ports up or timeout */ + if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { + print_flag = 1; + printf("done\n"); + } + } +} +static void +signal_handler(int signum) +{ + if (signum == SIGINT || signum == SIGTERM) { + printf("\n\nSignal %d received, preparing to exit...\n", + signum); + force_quit = true; + } +} +int +dpdk_main(int argc, char **argv, benetel_t *bs) +{ + struct lcore_queue_conf *qconf; + int ret; + uint16_t nb_ports; + uint16_t nb_ports_available = 0; + uint16_t portid, last_port; + unsigned lcore_id, rx_lcore_id; + unsigned nb_ports_in_mask = 0; + unsigned int nb_lcores = 0; + unsigned int nb_mbufs; + /* init EAL */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); + argc -= ret; + argv += ret; + force_quit = false; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + /* parse application arguments (after the EAL ones) */ + ret = l2fwd_parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); + printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled"); + /* convert to number of cycles */ + timer_period *= rte_get_timer_hz(); + nb_ports = rte_eth_dev_count_avail(); + if (nb_ports == 0) + rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); + /* check port mask to possible port mask */ + if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1)) + rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n", + (1 << nb_ports) - 1); + /* reset l2fwd_dst_ports */ + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) + l2fwd_dst_ports[portid] = 0; + last_port = 0; + /* + * Each logical core is assigned a dedicated TX queue on each port. + */ + RTE_ETH_FOREACH_DEV(portid) { + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + if (nb_ports_in_mask % 2) { + l2fwd_dst_ports[portid] = last_port; + l2fwd_dst_ports[last_port] = portid; + } + else + last_port = portid; + nb_ports_in_mask++; + } + if (nb_ports_in_mask % 2) { + printf("Notice: odd number of ports in portmask.\n"); + l2fwd_dst_ports[last_port] = last_port; + } + rx_lcore_id = 0; + qconf = NULL; + /* Initialize the port/queue configuration of each logical core */ + RTE_ETH_FOREACH_DEV(portid) { + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + /* get the lcore_id for this port */ + while (rte_lcore_is_enabled(rx_lcore_id) == 0 || + lcore_queue_conf[rx_lcore_id].n_rx_port == + l2fwd_rx_queue_per_lcore) { + rx_lcore_id++; + if (rx_lcore_id >= RTE_MAX_LCORE) + rte_exit(EXIT_FAILURE, "Not enough cores\n"); + } + if (qconf != &lcore_queue_conf[rx_lcore_id]) { + /* Assigned a new logical core in the loop above. */ + qconf = &lcore_queue_conf[rx_lcore_id]; + nb_lcores++; + } + qconf->rx_port_list[qconf->n_rx_port] = portid; + qconf->n_rx_port++; + printf("Lcore %u: RX port %u\n", rx_lcore_id, portid); + } + nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST + + nb_lcores * MEMPOOL_CACHE_SIZE), 8192U); + /* create the mbuf pool */ + //DD Debug + //printf ("Proc Type %d \n", rte_eal_process_type()); + l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs, + MEMPOOL_CACHE_SIZE, 0, 9680, + rte_socket_id()); + if (l2fwd_pktmbuf_pool == NULL) + rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); + /* Initialise each port */ + RTE_ETH_FOREACH_DEV(portid) { + struct rte_eth_rxconf rxq_conf; + struct rte_eth_txconf txq_conf; + struct rte_eth_conf local_port_conf = port_conf; + struct rte_eth_dev_info dev_info; + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { + printf("Skipping disabled port %u\n", portid); + continue; + } + nb_ports_available++; + /* init port */ + printf("Initializing port %u... ", portid); + fflush(stdout); + rte_eth_dev_info_get(portid, &dev_info); + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) + local_port_conf.txmode.offloads |= + DEV_TX_OFFLOAD_MBUF_FAST_FREE; + ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", + ret, portid); + ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, + &nb_txd); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot adjust number of descriptors: err=%d, port=%u\n", + ret, portid); + rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); + /* init one RX queue */ + fflush(stdout); + rxq_conf = dev_info.default_rxconf; + rxq_conf.offloads = local_port_conf.rxmode.offloads; + ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, + rte_eth_dev_socket_id(portid), + &rxq_conf, + l2fwd_pktmbuf_pool); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", + ret, portid); + /* init one TX queue on each port */ + fflush(stdout); + txq_conf = dev_info.default_txconf; + txq_conf.offloads = local_port_conf.txmode.offloads; + ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, + rte_eth_dev_socket_id(portid), + &txq_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", + ret, portid); + /* Initialize TX buffers */ + tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", + RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, + rte_eth_dev_socket_id(portid)); + if (tx_buffer[portid] == NULL) + rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", + portid); + rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); + ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], + rte_eth_tx_buffer_count_callback, + &port_statistics[portid].dropped); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot set error callback for tx buffer on port %u\n", + portid); + /* Start device */ + ret = rte_eth_dev_start(portid); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", + ret, portid); + printf("done: \n"); + rte_eth_promiscuous_enable(portid); + printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", + portid, + l2fwd_ports_eth_addr[portid].addr_bytes[0], + l2fwd_ports_eth_addr[portid].addr_bytes[1], + l2fwd_ports_eth_addr[portid].addr_bytes[2], + l2fwd_ports_eth_addr[portid].addr_bytes[3], + l2fwd_ports_eth_addr[portid].addr_bytes[4], + l2fwd_ports_eth_addr[portid].addr_bytes[5]); + /* initialize port stats */ + memset(&port_statistics, 0, sizeof(port_statistics)); + } + if (!nb_ports_available) { + rte_exit(EXIT_FAILURE, + "All available ports are disabled. Please set portmask.\n"); + } + check_all_ports_link_status(l2fwd_enabled_port_mask); + ret = 0; + /* launch per-lcore init on every lcore */ + rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, bs, CALL_MASTER); + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (rte_eal_wait_lcore(lcore_id) < 0) { + ret = -1; + break; + } + } + RTE_ETH_FOREACH_DEV(portid) { + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + printf("Closing port %d...", portid); + rte_eth_dev_stop(portid); + rte_eth_dev_close(portid); + printf(" Done\n"); + } + printf("Bye...\n"); + return ret; +} diff --git a/targets/ARCH/ETHERNET/benetel/5g/low.c b/targets/ARCH/ETHERNET/benetel/5g/low.c new file mode 100644 index 0000000000..b34d69784f --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/low.c @@ -0,0 +1,128 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "low.h" + +#include +#include +#include + +void store_ul(benetel_t *bs, ul_packet_t *ul) +{ +#if 0 +struct timespec t; +static struct timespec old; +clock_gettime(CLOCK_REALTIME, &t); +printf("store_ul %d.%ld (%ld)\n", (int)(t.tv_sec % 60), t.tv_nsec, t.tv_nsec - old.tv_nsec); +old = t; +#endif + + int a = ul->antenna; + + if (ul->slot != bs->next_slot[a] || + ul->symbol != bs->next_symbol[a]) { + printf("%s: error, antenna %d expected frame.sl.symbol %d.%d.%d, got %d.%d.%d\n", + __FUNCTION__, + a, bs->expected_benetel_frame[a], bs->next_slot[a], bs->next_symbol[a], + ul->frame, ul->slot, ul->symbol); + } + + /* fill missing data with 0s */ + while (ul->slot != bs->next_slot[a] || + ul->symbol != bs->next_symbol[a]) { + lock_ul_buffer(bs->buffers, bs->next_slot[a]); + if (bs->buffers->ul_busy[a][bs->next_slot[a]] & (1 << bs->next_symbol[a])) { + printf("%s: warning, antenna %d UL overflow (sl.symbol %d.%d)\n", __FUNCTION__, + a, bs->next_slot[a], bs->next_symbol[a]); + } + + memset(bs->buffers->ul[a][bs->next_slot[a]] + bs->next_symbol[a] * 1272*4, + 0, 1272*4); + bs->buffers->ul_busy[a][bs->next_slot[a]] |= (1 << bs->next_symbol[a]); + signal_ul_buffer(bs->buffers, bs->next_slot[a]); + unlock_ul_buffer(bs->buffers, bs->next_slot[a]); + + bs->next_symbol[a]++; + if (bs->next_symbol[a] == 14) { + bs->next_symbol[a] = 0; + bs->next_slot[a] = (bs->next_slot[a] + 1) % 20; + if (bs->next_slot[a] == 0) { + bs->expected_benetel_frame[a]++; + bs->expected_benetel_frame[a] &= 255; + } + } + } + + lock_ul_buffer(bs->buffers, bs->next_slot[a]); + if (bs->buffers->ul_busy[a][bs->next_slot[a]] & (1 << bs->next_symbol[a])) { + printf("%s: warning, antenna %d UL overflow (sl.symbol %d.%d)\n", __FUNCTION__, + a, bs->next_slot[a], bs->next_symbol[a]); + } + + memcpy(bs->buffers->ul[a][bs->next_slot[a]] + bs->next_symbol[a] * 1272*4, + ul->iq, 1272*4); + bs->buffers->ul_busy[a][bs->next_slot[a]] |= (1 << bs->next_symbol[a]); + signal_ul_buffer(bs->buffers, bs->next_slot[a]); + unlock_ul_buffer(bs->buffers, bs->next_slot[a]); + + bs->next_symbol[a]++; + if (bs->next_symbol[a] == 14) { + bs->next_symbol[a] = 0; + bs->next_slot[a] = (bs->next_slot[a] + 1) % 20; + if (bs->next_slot[a] == 0) { + bs->expected_benetel_frame[a]++; + bs->expected_benetel_frame[a] &= 255; + } + } +} + +void store_prach(benetel_t *bs, int frame, int slot, void *data) +{ + static int last_frame = -1; + static int last_slot = -1; + /* hack: antenna number is always 0, discard second packet with same f/sf */ + //if (frame == last_frame && slot == last_slot) return; + if (frame == last_frame && slot == last_slot) { printf("got f.sl %d.%d twice\n", frame, slot); return; } + last_frame = frame; + last_slot = slot; + + lock_ul_buffer(bs->buffers, slot); + if (bs->buffers->prach_busy[slot]) { + printf("store_prach: fatal: previous prach buffer not processed\n"); + unlock_ul_buffer(bs->buffers, slot); + return; + } + bs->buffers->prach_busy[slot] = 1; + memcpy(bs->buffers->prach[slot], data, 839*4); + signal_ul_buffer(bs->buffers, slot); + unlock_ul_buffer(bs->buffers, slot); + +} + +void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); + +void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) +{ + if (!strcmp(ifname, "dpdk")) + return benetel_start_dpdk(ifname, buffers, dpdk_main_command_line); + printf("benetel: fatal: interface %s not supported, only dpdpk is supported\n", ifname); + exit(1); +} diff --git a/common/utils/itti_analyzer/libui/ui_signal_dissect_view.h b/targets/ARCH/ETHERNET/benetel/5g/low.h similarity index 62% rename from common/utils/itti_analyzer/libui/ui_signal_dissect_view.h rename to targets/ARCH/ETHERNET/benetel/5g/low.h index a5ccf6a9eb..659819296a 100644 --- a/common/utils/itti_analyzer/libui/ui_signal_dissect_view.h +++ b/targets/ARCH/ETHERNET/benetel/5g/low.h @@ -19,18 +19,31 @@ * contact@openairinterface.org */ -#ifndef UI_SIGNAL_DISSECT_VIEW_H_ -#define UI_SIGNAL_DISSECT_VIEW_H_ +#ifndef _BENETEL_5G_LOW_H_ +#define _BENETEL_5G_LOW_H_ + +#include "shared_buffers.h" typedef struct { - GtkWidget *text_view; - PangoFontDescription *text_view_font; -} ui_text_view_t; + shared_buffers *buffers; + /* [2] is for two antennas */ + int next_slot[2]; + int next_symbol[2]; + int expected_benetel_frame[2]; + char *dpdk_main_command_line; +} benetel_t; -ui_text_view_t *ui_signal_dissect_new(GtkWidget *hbox); +typedef struct { + int frame; + int slot; + int symbol; + int antenna; + unsigned char iq[5088]; +} ul_packet_t; -int ui_signal_dissect_clear_view(ui_text_view_t *text_view); +void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); -gboolean ui_signal_set_text(gpointer user_data, gchar *text, gint length); +void store_ul(benetel_t *bs, ul_packet_t *ul); +void store_prach(benetel_t *bs, int frame, int slot, void *data); -#endif /*UI_SIGNAL_DISSECT_VIEW_H_ */ +#endif /* _BENETEL_5G_LOW_H_ */ diff --git a/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c b/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c new file mode 100644 index 0000000000..b26df07723 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c @@ -0,0 +1,119 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* those 2 lines for CPU_SET */ +#define _GNU_SOURCE +#include + +#include +#include +#include +#include + +#include "low.h" + +int dpdk_main(int argc, char **argv, benetel_t *); + +void *dpdk_thread(void *_bs) +{ + benetel_t *bs = _bs; + int n = 0; + char **v = NULL; // = { "softmodem", "-n", "2", "--file-prefix", "pg2", "-l", "6", "--", "-p", "0x1" }; + char *s = bs->dpdk_main_command_line; + char *tok; + + while ((tok = strtok(s, " ")) != NULL) { + n++; + v = realloc(v, n * sizeof(char *)); + if (v == NULL) { + printf("%s: out of memory\n", __FUNCTION__); + exit(1); + } + v[n-1] = tok; + s = NULL; + } + + dpdk_main(n, v, bs); + exit(1); + return 0; +} + +void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) +{ + benetel_t *bs; + + bs = calloc(1, sizeof(benetel_t)); + if (bs == NULL) { + printf("%s: out of memory\n", __FUNCTION__); + exit(1); + } + + bs->buffers = buffers; + + bs->expected_benetel_frame[0] = 255; + bs->expected_benetel_frame[1] = 255; + + bs->dpdk_main_command_line = dpdk_main_command_line; + + pthread_attr_t attr; + + if (pthread_attr_init(&attr) != 0) { + printf("pthread_attr_init failed\n"); + exit(1); + } + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(10,&cpuset); + if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset) != 0) { + printf("pthread_attr_setaffinity_np failed\n"); + exit(1); + } + + if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { + printf("pthread_attr_setschedpolicy failed\n"); + exit(1); + } + + struct sched_param params; + params.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (sched_get_priority_max(SCHED_FIFO) == -1) { + printf("sched_get_priority_max failed\n"); + exit(1); + } + if (pthread_attr_setschedparam(&attr, ¶ms) != 0) { + printf("pthread_setschedparam failed\n"); + exit(1); + } + + pthread_t t; + if (pthread_create(&t, &attr, dpdk_thread, bs) != 0) { + printf("%s: thread creation failed\n", __FUNCTION__); + exit(1); + } + + if (pthread_attr_destroy(&attr) != 0) { + printf("pthread_attr_init failed\n"); + exit(1); + } + + return bs; +} diff --git a/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c new file mode 100644 index 0000000000..a302400eb4 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c @@ -0,0 +1,123 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 + * + * 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. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "shared_buffers.h" + +#include +#include +#include + +void init_buffers(shared_buffers *s) +{ + int slot; + + memset(s, 0, sizeof(*s)); + + for (slot = 0; slot < 20; slot++) { + if (pthread_mutex_init(&s->m_dl[slot], NULL) != 0 || + pthread_cond_init(&s->c_dl[slot], NULL) != 0 || + pthread_mutex_init(&s->m_ul[slot], NULL) != 0 || + pthread_cond_init(&s->c_ul[slot], NULL) != 0) { + printf("%s: error initializing mutex/cond\n", __FUNCTION__); + exit(1); + } + } + + /* the gNB's first transmitted DL slot is 6 but the device + * needs to have slots 1, 2 and 3, 4 and 5 ready. Let's pretend + * they are ready. + */ + s->dl_busy[0][1] = 0x3fff; + s->dl_busy[0][2] = 0x3fff; + s->dl_busy[0][3] = 0x3fff; + s->dl_busy[0][4] = 0x3fff; + s->dl_busy[0][5] = 0x3fff; + s->dl_busy[1][1] = 0x3fff; + s->dl_busy[1][2] = 0x3fff; + s->dl_busy[1][3] = 0x3fff; + s->dl_busy[1][4] = 0x3fff; + s->dl_busy[1][5] = 0x3fff; +} + +void lock_dl_buffer(shared_buffers *s, int slot) +{ + if (pthread_mutex_lock(&s->m_dl[slot]) != 0) { + printf("%s: fatal: lock fails\n", __FUNCTION__); + exit(1); + } +} + +void unlock_dl_buffer(shared_buffers *s, int slot) +{ + if (pthread_mutex_unlock(&s->m_dl[slot]) != 0) { + printf("%s: fatal: unlock fails\n", __FUNCTION__); + exit(1); + } +} + +void wait_dl_buffer(shared_buffers *s, int slot) +{ + if (pthread_cond_wait(&s->c_dl[slot], &s->m_dl[slot]) != 0) { + printf("%s: fatal: cond_wait fails\n", __FUNCTION__); + exit(1); + } +} + +void signal_dl_buffer(shared_buffers *s, int slot) +{ + if (pthread_cond_broadcast(&s->c_dl[slot]) != 0) { + printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); + exit(1); + } +} + +void lock_ul_buffer(shared_buffers *s, int slot) +{ + if (pthread_mutex_lock(&s->m_ul[slot]) != 0) { + printf("%s: fatal: lock fails\n", __FUNCTION__); + printf("%s: fatal: lock fails slot %d\n", __FUNCTION__, slot); + exit(1); + } +} + +void unlock_ul_buffer(shared_buffers *s, int slot) +{ + if (pthread_mutex_unlock(&s->m_ul[slot]) != 0) { + printf("%s: fatal: unlock fails\n", __FUNCTION__); + exit(1); + } +} + +void wait_ul_buffer(shared_buffers *s, int slot) +{ + if (pthread_cond_wait(&s->c_ul[slot], &s->m_ul[slot]) != 0) { + printf("%s: fatal: cond_wait fails\n", __FUNCTION__); + exit(1); + } +} + +void signal_ul_buffer(shared_buffers *s, int slot) +{ + if (pthread_cond_broadcast(&s->c_ul[slot]) != 0) { + printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); + exit(1); + } +} diff --git a/openair2/UTIL/TRACE/fifo_printf_proto_extern.h b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h similarity index 51% rename from openair2/UTIL/TRACE/fifo_printf_proto_extern.h rename to targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h index 0855a8da93..9d51b8138d 100644 --- a/openair2/UTIL/TRACE/fifo_printf_proto_extern.h +++ b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h @@ -19,23 +19,43 @@ * contact@openairinterface.org */ -/*************************************************************************** - fifo_printf_proto_extern.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr +#ifndef _BENETEL_5G_SHARED_BUFFERS_H_ +#define _BENETEL_5G_SHARED_BUFFERS_H_ +#include +#include +typedef struct { + /* [2] is for two antennas */ + unsigned char dl[2][20][14*1272*4]; + unsigned char ul[2][20][14*1272*4]; + uint16_t dl_busy[2][20]; + uint16_t ul_busy[2][20]; - ***************************************************************************/ -#ifndef __FIFO_PRINTF_PROTO_EXTERN_H__ -# define __FIFO_PRINTF_PROTO_EXTERN_H__ -#ifdef FIFO_PRINTF -extern void fifo_printf_init (void); -extern void fifo_printf_clean_up (void); -extern int fifo_printf (const char *fmt, ...); -#else -extern int fifo_printf_null (const char *fmt, ...); -#endif -#endif + pthread_mutex_t m_ul[20]; + pthread_cond_t c_ul[20]; + + pthread_mutex_t m_dl[20]; + pthread_cond_t c_dl[20]; + + unsigned char prach[20][849*4]; + unsigned char prach_busy[20]; + + /* statistics/error counting */ + int ul_overflow; + int dl_underflow; +} shared_buffers; + +void init_buffers(shared_buffers *s); + +void lock_dl_buffer(shared_buffers *s, int slot); +void unlock_dl_buffer(shared_buffers *s, int slot); +void wait_dl_buffer(shared_buffers *s, int slot); +void signal_dl_buffer(shared_buffers *s, int slot); + +void lock_ul_buffer(shared_buffers *s, int slot); +void unlock_ul_buffer(shared_buffers *s, int slot); +void wait_ul_buffer(shared_buffers *s, int slot); +void signal_ul_buffer(shared_buffers *s, int slot); + +#endif /* _BENETEL_5G_SHARED_BUFFERS_H_ */ diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 6e94717a6f..d268855566 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -69,7 +69,7 @@ /** @addtogroup _USRP_PHY_RF_INTERFACE_ * @{ */ - +int gpio789=0; extern int usrp_tx_thread; @@ -108,7 +108,8 @@ typedef struct { int64_t rx_count; int wait_for_first_pps; int use_gps; - int first_tx; + //int first_tx; + //int first_rx; //! timestamp of RX packet openair0_timestamp rx_timestamp; } usrp_state_t; @@ -152,7 +153,7 @@ int check_ref_locked(usrp_state_t *s,size_t mboard) { } static int sync_to_gps(openair0_device *device) { - uhd::set_thread_priority_safe(); + //uhd::set_thread_priority_safe(); //std::string args; //Set up program options //po::options_description desc("Allowed options"); @@ -275,38 +276,35 @@ static int trx_usrp_start(openair0_device *device) { // setup GPIO for TDD, GPIO(4) = ATR_RX //set data direction register (DDR) to output s->usrp->set_gpio_attr("FP0", "DDR", 0xfff, 0xfff); - //set lower 7 bits to be controlled automatically by ATR (the rest 5 bits are controlled manually) + //set lower 7 bits to be controlled automatically by ATR (the rest 5 bits are controlled manually) s->usrp->set_gpio_attr("FP0", "CTRL", 0x7f,0xfff); //set pins 4 (RX_TX_Switch) and 6 (Shutdown PA) to 1 when the radio is only receiving (ATR_RX) s->usrp->set_gpio_attr("FP0", "ATR_RX", (1<<4)|(1<<6), 0x7f); // set pin 5 (Shutdown LNA) to 1 when the radio is transmitting and receiveing (ATR_XX) // (we use full duplex here, because our RX is on all the time - this might need to change later) s->usrp->set_gpio_attr("FP0", "ATR_XX", (1<<5), 0x7f); - // set the output pins to 0 + // set the output pins to 1 s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80); - // init recv and send streaming - uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - LOG_I(HW,"Time in secs now: %llu \n", s->usrp->get_time_now().to_ticks(s->sample_rate)); - LOG_I(HW,"Time in secs last pps: %llu \n", s->usrp->get_time_last_pps().to_ticks(s->sample_rate)); - - if (s->use_gps == 1 || device->openair0_cfg[0].time_source == external) { - s->wait_for_first_pps = 1; - cmd.time_spec = s->usrp->get_time_last_pps() + uhd::time_spec_t(1.0); - } else { - s->wait_for_first_pps = 0; - cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.005); - } - - cmd.stream_now = false; // start at constant delay - s->rx_stream->issue_stream_cmd(cmd); - /*s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate); - s->tx_md.has_time_spec = true; - s->tx_md.start_of_burst = true; - s->tx_md.end_of_burst = false;*/ + s->wait_for_first_pps = 1; s->rx_count = 0; s->tx_count = 0; + //s->first_tx = 1; + //s->first_rx = 1; s->rx_timestamp = 0; + + s->usrp->set_time_next_pps(uhd::time_spec_t(0.0)); + // wait for the pps to change + uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps(); + while (time_last_pps == s->usrp->get_time_last_pps()) { + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + + uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + cmd.time_spec = uhd::time_spec_t(1.0); + cmd.stream_now = false; // start at constant delay + s->rx_stream->issue_stream_cmd(cmd); + return 0; } /*! \brief Terminate operation of the USRP transceiver -- free all associated resources @@ -317,7 +315,7 @@ static void trx_usrp_end(openair0_device *device) { return; usrp_state_t *s = (usrp_state_t *)device->priv; - + if (s == NULL) return; iqrecorder_end(device); @@ -387,14 +385,14 @@ static int trx_usrp_write(openair0_device *device, #if defined(__x86_64) || defined(__i386__) #ifdef __AVX2__ nsamps2 = (nsamps+7)>>3; - __m256i buff_tx[8][nsamps2]; + __m256i buff_tx[cc<2?2:cc][nsamps2]; #else nsamps2 = (nsamps+3)>>2; - __m128i buff_tx[8][nsamps2]; + __m128i buff_tx[cc<2?2:cc][nsamps2]; #endif #elif defined(__arm__) nsamps2 = (nsamps+3)>>2; - int16x8_t buff_tx[8][nsamps2]; + int16x8_t buff_tx[cc<2?2:cc][nsamps2]; #else #error Unsupported CPU architecture, USRP device cannot be built #endif @@ -438,7 +436,7 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI buff_ptrs.push_back(&(((int16_t *)buff_tx[i])[0])); ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); - } + } else { ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md); } @@ -466,6 +464,7 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI write_package[end].buff[i] = buff[i]; write_thread->count_write++; write_thread->end = (write_thread->end + 1)% MAX_WRITE_THREAD_PACKAGE; + LOG_D(HW,"Signaling TX TS %llu\n",(unsigned long long)timestamp); pthread_cond_signal(&write_thread->cond_write); pthread_mutex_unlock(&write_thread->mutex_write); return 0; @@ -482,7 +481,7 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI @param antenna_id index of the antenna if the device has multiple antennas @param flags flags must be set to TRUE if timestamp parameter needs to be applied */ -void *trx_usrp_write_thread(void * arg){ +void *trx_usrp_write_thread(void * arg){ int ret=0; openair0_device *device=(openair0_device *)arg; openair0_thread_t *write_thread = &device->write_thread; @@ -524,14 +523,14 @@ void *trx_usrp_write_thread(void * arg){ #if defined(__x86_64) || defined(__i386__) #ifdef __AVX2__ nsamps2 = (nsamps+7)>>3; - __m256i buff_tx[8][nsamps2]; + __m256i buff_tx[cc<2?2:cc][nsamps2]; #else nsamps2 = (nsamps+3)>>2; - __m128i buff_tx[8][nsamps2]; + __m128i buff_tx[cc<2?2:cc][nsamps2]; #endif #elif defined(__arm__) nsamps2 = (nsamps+3)>>2; - int16x8_t buff_tx[8][nsamps2]; + int16x8_t buff_tx[cc<2?2:cc][nsamps2]; #else #error Unsupported CPU architecture, USRP device cannot be built #endif @@ -551,11 +550,12 @@ void *trx_usrp_write_thread(void * arg){ } } - + s->tx_md.has_time_spec = true; s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet; s->tx_md.end_of_burst = last_packet; s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); + LOG_D(PHY,"usrp_tx_write: tx_count %llu SoB %d, EoB %d, TS %llu\n",(unsigned long long)s->tx_count,s->tx_md.start_of_burst,s->tx_md.end_of_burst,(unsigned long long)timestamp); s->tx_count++; // bit 3 enables gpio (for backward compatibility) @@ -574,7 +574,7 @@ void *trx_usrp_write_thread(void * arg){ buff_ptrs.push_back(&(((int16_t *)buff_tx[i])[0])); ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); - } + } else { ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md); } @@ -583,7 +583,6 @@ void *trx_usrp_write_thread(void * arg){ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_USRP_SEND_RETURN, ret ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_THREAD, 0 ); - if(0) break; } return NULL; @@ -591,7 +590,7 @@ void *trx_usrp_write_thread(void * arg){ int trx_usrp_write_init(openair0_device *device){ - uhd::set_thread_priority_safe(1.0); + //uhd::set_thread_priority_safe(1.0); openair0_thread_t *write_thread = &device->write_thread; printf("initializing tx write thread\n"); @@ -599,7 +598,8 @@ int trx_usrp_write_init(openair0_device *device){ write_thread->end = 0; write_thread->count_write = 0; printf("end of tx write thread\n"); - + pthread_mutex_init(&write_thread->mutex_write, NULL); + pthread_cond_init(&write_thread->cond_write, NULL); pthread_create(&write_thread->pthread_write,NULL,trx_usrp_write_thread,(void *)device); return(0); @@ -625,42 +625,53 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp #if defined(__x86_64) || defined(__i386__) #ifdef __AVX2__ nsamps2 = (nsamps+7)>>3; - __m256i buff_tmp[2][nsamps2]; + __m256i buff_tmp[cc<2 ? 2 : cc][nsamps2]; #else nsamps2 = (nsamps+3)>>2; - __m128i buff_tmp[2][nsamps2]; + __m128i buff_tmp[cc<2 ? 2 : cc][nsamps2]; #endif #elif defined(__arm__) nsamps2 = (nsamps+3)>>2; - int16x8_t buff_tmp[2][nsamps2]; + int16x8_t buff_tmp[cc<2 ? 2 : cc][nsamps2]; #endif - if (device->type == USRP_B200_DEV) { - if (cc>1) { + int rxshift; + switch (device->type) { + case USRP_B200_DEV: + rxshift=4; + break; + case USRP_X300_DEV: + case USRP_N300_DEV: + rxshift=2; + break; + default: + AssertFatal(1==0,"Shouldn't be here\n"); + } + + samples_received=0; + while (samples_received != nsamps) { + + if (cc>1) { // receive multiple channels (e.g. RF A and RF B) - std::vector buff_ptrs; + std::vector buff_ptrs; - for (int i=0; irx_stream->recv(buff_ptrs, nsamps, s->rx_md); - } else { + samples_received += s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md); + } else { // receive a single channel (e.g. from connector RF A) - samples_received=0; - while (samples_received != nsamps) { - samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received, + samples_received += s->rx_stream->recv((void*)((int32_t*)buff_tmp[0]+samples_received), nsamps-samples_received, s->rx_md); - - if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE)) - break; - - if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) { - printf("sleep...\n"); //usleep(100); - } } + if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE)) + break; - if (samples_received == nsamps) s->wait_for_first_pps=0; + if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) { + printf("sleep...\n"); //usleep(100); + } } + if (samples_received == nsamps) s->wait_for_first_pps=0; // bring RX data into 12 LSBs for softmodem RX for (int i=0; itype == USRP_X300_DEV) { - if (cc>1) { - // receive multiple channels (e.g. RF A and RF B) - std::vector buff_ptrs; - for (int i=0; irx_stream->recv(buff_ptrs, nsamps, s->rx_md,1.0); - } else { - // receive a single channel (e.g. from connector RF A) - samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md,1.0); + if (samples_received < nsamps) { + LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps); } - } - - if (samples_received < nsamps) - LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps); if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) LOG_E(HW, "%s\n", s->rx_md.to_pp_string(true).c_str()); @@ -708,14 +707,28 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); *ptimestamp = s->rx_timestamp; - if (device->recplay_state != NULL) { // record mode + // push GPIO bits 7-9 from flags_msb + /*s->usrp->set_command_time(uhd::time_spec_t::from_ticks((s->rx_timestamp+(2*nsamps)),s->sample_rate)); + s->usrp->set_gpio_attr("FP0", "OUT", gpio789<<7, 0x380); + s->usrp->clear_command_time(); + gpio789 = (gpio789+1)&7;*/ + recplay_state_t *recPlay=device->recplay_state; + + if ( recPlay != NULL) { // record mode // Copy subframes to memory (later dump on a file) - if (device->recplay_state->nb_samples < device->openair0_cfg->recplay_conf->u_sf_max) { - (device->recplay_state->ms_sample+device->recplay_state->nb_samples)->header = BELL_LABS_IQ_HEADER; - (device->recplay_state->ms_sample+device->recplay_state->nb_samples)->ts = *ptimestamp; - memcpy((device->recplay_state->ms_sample+device->recplay_state->nb_samples)->samples, buff[0], nsamps*4); - device->recplay_state->nb_samples++; - } else exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n"); + if (recPlay->nbSamplesBlocks < device->openair0_cfg->recplay_conf->u_sf_max && + recPlay->maxSizeBytes > (recPlay->currentPtr-(uint8_t *)recPlay->ms_sample) + + sizeof(iqrec_t) + nsamps*4 ) { + iqrec_t *hdr=(iqrec_t *)recPlay->currentPtr; + hdr->header = BELL_LABS_IQ_HEADER; + hdr->ts = *ptimestamp; + hdr->nbBytes=nsamps*4; + memcpy(hdr+1, buff[0], nsamps*4); + recPlay->currentPtr+=sizeof(iqrec_t)+nsamps*4; + recPlay->nbSamplesBlocks++; + LOG_D(HW,"recorded %d samples, for TS %lu, shift in buffer %ld\n", nsamps, hdr->ts, recPlay->currentPtr-(uint8_t *)recPlay->ms_sample); + } else + exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n"); } return samples_received; @@ -835,6 +848,17 @@ rx_gain_calib_table_t calib_table_x310[] = { {-1,0} }; +/*! \brief USRPB210 RX calibration table */ +rx_gain_calib_table_t calib_table_n310[] = { + {3500000000.0,0.0}, + {2660000000.0,0.0}, + {2300000000.0,0.0}, + {1880000000.0,0.0}, + {816000000.0, 0.0}, + {-1,0} +}; + + /*! \brief Set RX gain offset * \param openair0_cfg RF frontend parameters set by application * \param chain_index RF chain to apply settings to @@ -914,9 +938,10 @@ int trx_usrp_reset_stats(openair0_device *device) { extern "C" { int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { - LOG_D(HW, "openair0_cfg[0].sdr_addrs == '%s'\n", openair0_cfg[0].sdr_addrs); - LOG_D(HW, "openair0_cfg[0].clock_source == '%d'\n", openair0_cfg[0].clock_source); + LOG_I(HW, "openair0_cfg[0].sdr_addrs == '%s'\n", openair0_cfg[0].sdr_addrs); + LOG_I(HW, "openair0_cfg[0].clock_source == '%d' (internal = %d, external = %d)\n", openair0_cfg[0].clock_source,internal,external); usrp_state_t *s ; + int choffset = 0; if ( device->priv == NULL) { s=(usrp_state_t *)calloc(sizeof(usrp_state_t),1); @@ -939,29 +964,29 @@ extern "C" { // hotfix! to be checked later - uhd::set_thread_priority_safe(1.0); + //uhd::set_thread_priority_safe(1.0); // Initialize USRP device int vers=0,subvers=0,subsubvers=0; int bw_gain_adjust=0; - + if (device->openair0_cfg->recplay_mode == RECPLAY_RECORDMODE) { std::cerr << "USRP device initialized in subframes record mode" << std::endl; } - + sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers); LOG_I(HW,"UHD version %s (%d.%d.%d)\n", uhd::get_version_string().c_str(),vers,subvers,subsubvers); std::string args; - + if (openair0_cfg[0].sdr_addrs == NULL) { args = "type=b200"; } else { args = openair0_cfg[0].sdr_addrs; LOG_I(HW,"Checking for USRP with args %s\n",openair0_cfg[0].sdr_addrs); } - + uhd::device_addrs_t device_adds = uhd::device::find(args); - + if (device_adds.size() == 0) { LOG_E(HW,"No USRP Device Found.\n "); free(s); @@ -971,52 +996,52 @@ extern "C" { free(s); return -1; } - + LOG_I(HW,"Found USRP %s\n", device_adds[0].get("type").c_str()); double usrp_master_clock; - + if (device_adds[0].get("type") == "b200") { device->type = USRP_B200_DEV; usrp_master_clock = 30.72e6; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=7680, recv_frame_size=7680" ; } - + if (device_adds[0].get("type") == "n3xx") { printf("Found USRP n300\n"); - device->type=USRP_X300_DEV; //treat it as X300 for now + device->type=USRP_N300_DEV; usrp_master_clock = 122.88e6; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); //args += ", send_buff_size=33554432"; } - + if (device_adds[0].get("type") == "x300") { printf("Found USRP x300\n"); device->type=USRP_X300_DEV; usrp_master_clock = 184.32e6; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); - + // USRP recommended: https://files.ettus.com/manual/page_usrp_x3x0_config.html if ( 0 != system("sysctl -w net.core.rmem_max=33554432 net.core.wmem_max=33554432") ) LOG_W(HW,"Can't set kernel parameters for X3xx\n"); } - + s->usrp = uhd::usrp::multi_usrp::make(args); - + if (args.find("clock_source")==std::string::npos) { if (openair0_cfg[0].clock_source == internal) { s->usrp->set_clock_source("internal"); - LOG_D(HW,"Setting clock source to internal\n"); + LOG_I(HW,"Setting clock source to internal\n"); } else if (openair0_cfg[0].clock_source == external ) { s->usrp->set_clock_source("external"); - LOG_D(HW,"Setting clock source to external\n"); + LOG_I(HW,"Setting clock source to external\n"); } else if (openair0_cfg[0].clock_source==gpsdo) { s->usrp->set_clock_source("gpsdo"); - LOG_D(HW,"Setting clock source to gpsdo\n"); + LOG_I(HW,"Setting clock source to gpsdo\n"); } - else { + else { LOG_W(HW,"Clock source set neither in usrp_args nor on command line, using default!\n"); } } @@ -1029,17 +1054,17 @@ extern "C" { if (args.find("time_source")==std::string::npos) { if (openair0_cfg[0].time_source == internal) { s->usrp->set_time_source("internal"); - LOG_D(HW,"Setting time source to internal\n"); + LOG_I(HW,"Setting time source to internal\n"); } else if (openair0_cfg[0].time_source == external ) { s->usrp->set_time_source("external"); - LOG_D(HW,"Setting time source to external\n"); + LOG_I(HW,"Setting time source to external\n"); } else if (openair0_cfg[0].time_source==gpsdo) { s->usrp->set_time_source("gpsdo"); - LOG_D(HW,"Setting time source to gpsdo\n"); + LOG_I(HW,"Setting time source to gpsdo\n"); } - else { + else { LOG_W(HW,"Time source set neither in usrp_args nor on command line, using default!\n"); } } @@ -1049,10 +1074,10 @@ extern "C" { } } - + if (s->usrp->get_clock_source(0) == "gpsdo") { s->use_gps = 1; - + if (sync_to_gps(device)==EXIT_SUCCESS) { LOG_I(HW,"USRP synced with GPS!\n"); } else { @@ -1067,12 +1092,22 @@ extern "C" { exit(EXIT_FAILURE); } } - + if (device->type==USRP_X300_DEV) { openair0_cfg[0].rx_gain_calib_table = calib_table_x310; - std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; // Bell Labs info + std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; + s->usrp->set_rx_dc_offset(true); + } + + if (device->type==USRP_N300_DEV) { + openair0_cfg[0].rx_gain_calib_table = calib_table_n310; + std::cerr << "-- Using calibration table: calib_table_n310" << std::endl; + } + + + if (device->type==USRP_N300_DEV || device->type==USRP_X300_DEV) { LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate); - + switch ((int)openair0_cfg[0].sample_rate) { case 122880000: // from usrp_time_offset @@ -1081,7 +1116,7 @@ extern "C" { openair0_cfg[0].tx_bw = 80e6; openair0_cfg[0].rx_bw = 80e6; break; - + case 92160000: // from usrp_time_offset //openair0_cfg[0].samples_per_packet = 2048; @@ -1089,7 +1124,7 @@ extern "C" { openair0_cfg[0].tx_bw = 80e6; openair0_cfg[0].rx_bw = 80e6; break; - + case 61440000: // from usrp_time_offset //openair0_cfg[0].samples_per_packet = 2048; @@ -1097,14 +1132,14 @@ extern "C" { openair0_cfg[0].tx_bw = 40e6; openair0_cfg[0].rx_bw = 40e6; break; - + case 46080000: //openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].tx_bw = 40e6; openair0_cfg[0].rx_bw = 40e6; break; - + case 30720000: // from usrp_time_offset //openair0_cfg[0].samples_per_packet = 2048; @@ -1112,35 +1147,35 @@ extern "C" { openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; - + case 15360000: //openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 45; openair0_cfg[0].tx_bw = 10e6; openair0_cfg[0].rx_bw = 10e6; break; - + case 7680000: //openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 50; openair0_cfg[0].tx_bw = 5e6; openair0_cfg[0].rx_bw = 5e6; break; - + case 1920000: //openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 50; openair0_cfg[0].tx_bw = 1.25e6; openair0_cfg[0].rx_bw = 1.25e6; break; - + default: LOG_E(HW,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); exit(-1); break; } } - + if (device->type == USRP_B200_DEV) { if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) { openair0_cfg[0].rx_gain_calib_table = calib_table_b210; @@ -1151,7 +1186,7 @@ extern "C" { bw_gain_adjust=1; std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info } - + switch ((int)openair0_cfg[0].sample_rate) { case 46080000: s->usrp->set_master_clock_rate(46.08e6); @@ -1160,7 +1195,7 @@ extern "C" { openair0_cfg[0].tx_bw = 40e6; openair0_cfg[0].rx_bw = 40e6; break; - + case 30720000: s->usrp->set_master_clock_rate(30.72e6); //openair0_cfg[0].samples_per_packet = 1024; @@ -1168,7 +1203,7 @@ extern "C" { openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; - + case 23040000: s->usrp->set_master_clock_rate(23.04e6); //to be checked //openair0_cfg[0].samples_per_packet = 1024; @@ -1176,7 +1211,7 @@ extern "C" { openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; - + case 15360000: s->usrp->set_master_clock_rate(30.72e06); //openair0_cfg[0].samples_per_packet = 1024; @@ -1184,7 +1219,7 @@ extern "C" { openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; - + case 7680000: s->usrp->set_master_clock_rate(30.72e6); //openair0_cfg[0].samples_per_packet = 1024; @@ -1192,7 +1227,7 @@ extern "C" { openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; - + case 1920000: s->usrp->set_master_clock_rate(30.72e6); //openair0_cfg[0].samples_per_packet = 1024; @@ -1200,51 +1235,55 @@ extern "C" { openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; break; - + default: LOG_E(HW,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); exit(-1); break; } } - + /* device specific */ //openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered //openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered openair0_cfg[0].iq_txshift = 4;//shift openair0_cfg[0].iq_rxrescale = 15;//rescale iqs - + for(int i=0; i<((int) s->usrp->get_rx_num_channels()); i++) { if (iusrp->set_rx_rate(openair0_cfg[0].sample_rate,i); - s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); + s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i+choffset); + s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i+choffset); set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); - ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); + ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i+choffset); // limit to maximum gain - AssertFatal( openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] <= gain_range.stop(), - "RX Gain too high, lower by %f dB\n", - openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop()); - s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i); + double gain=openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i]; + if ( gain > gain_range.stop()) { + LOG_E(HW,"RX Gain too high, lower by %f dB\n", + gain - gain_range.stop()); + gain=gain_range.stop(); + } + + s->usrp->set_rx_gain(gain,i+choffset); LOG_I(HW,"RX Gain %d %f (%f) => %f (max %f)\n",i, openair0_cfg[0].rx_gain[i],openair0_cfg[0].rx_gain_offset[i], openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop()); } } - + LOG_D(HW, "usrp->get_tx_num_channels() == %zd\n", s->usrp->get_tx_num_channels()); LOG_D(HW, "openair0_cfg[0].tx_num_channels == %d\n", openair0_cfg[0].tx_num_channels); - + for(int i=0; i<((int) s->usrp->get_tx_num_channels()); i++) { ::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(i); - + if (iusrp->set_tx_rate(openair0_cfg[0].sample_rate,i); - s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i); - s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[i],i); + s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i+choffset); + s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i+choffset); + s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[i],i+choffset); LOG_I(HW,"USRP TX_GAIN:%3.2lf gain_range:%3.2lf tx_gain:%3.2lf\n", gain_range_tx.stop()-openair0_cfg[0].tx_gain[i], gain_range_tx.stop(), openair0_cfg[0].tx_gain[i]); } } - + //s->usrp->set_clock_source("external"); //s->usrp->set_time_source("external"); // display USRP settings @@ -1258,77 +1297,81 @@ extern "C" { int max=s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps(); samples/=10000; LOG_I(HW,"RF board max packet size %u, size for 100µs jitter %d \n", max, samples); - + if ( samples < max ) { stream_args_rx.args["spp"] = str(boost::format("%d") % samples ); } - + LOG_I(HW,"rx_max_num_samps %zu\n", s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps()); - - for (int i = 0; irx_stream = s->usrp->get_rx_stream(stream_args_rx); uhd::stream_args_t stream_args_tx("sc16", "sc16"); - + for (int i = 0; itx_stream = s->usrp->get_tx_stream(stream_args_tx); - + /* Setting TX/RX BW after streamers are created due to USRP calibration issue */ for(int i=0; i<((int) s->usrp->get_tx_num_channels()) && iusrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); - + s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i+choffset); + for(int i=0; i<((int) s->usrp->get_rx_num_channels()) && iusrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); - + s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i+choffset); + for (int i=0; iusrp->get_rx_rate(i)/1e6); - LOG_I(HW," Actual RX frequency: %fGHz...\n", s->usrp->get_rx_freq(i)/1e9); - LOG_I(HW," Actual RX gain: %f...\n", s->usrp->get_rx_gain(i)); - LOG_I(HW," Actual RX bandwidth: %fM...\n", s->usrp->get_rx_bandwidth(i)/1e6); - LOG_I(HW," Actual RX antenna: %s...\n", s->usrp->get_rx_antenna(i).c_str()); + LOG_I(HW," Actual RX sample rate: %fMSps...\n",s->usrp->get_rx_rate(i+choffset)/1e6); + LOG_I(HW," Actual RX frequency: %fGHz...\n", s->usrp->get_rx_freq(i+choffset)/1e9); + LOG_I(HW," Actual RX gain: %f...\n", s->usrp->get_rx_gain(i+choffset)); + LOG_I(HW," Actual RX bandwidth: %fM...\n", s->usrp->get_rx_bandwidth(i+choffset)/1e6); + LOG_I(HW," Actual RX antenna: %s...\n", s->usrp->get_rx_antenna(i+choffset).c_str()); } - + for (int i=0; iusrp->get_tx_rate(i)/1e6); - LOG_I(HW," Actual TX frequency: %fGHz...\n", s->usrp->get_tx_freq(i)/1e9); - LOG_I(HW," Actual TX gain: %f...\n", s->usrp->get_tx_gain(i)); - LOG_I(HW," Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i)/1e6); - LOG_I(HW," Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i).c_str()); + LOG_I(HW," Actual TX sample rate: %fMSps...\n", s->usrp->get_tx_rate(i+choffset)/1e6); + LOG_I(HW," Actual TX frequency: %fGHz...\n", s->usrp->get_tx_freq(i+choffset)/1e9); + LOG_I(HW," Actual TX gain: %f...\n", s->usrp->get_tx_gain(i+choffset)); + LOG_I(HW," Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i+choffset)/1e6); + LOG_I(HW," Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i+choffset).c_str()); LOG_I(HW," Actual TX packet size: %lu\n",s->tx_stream->get_max_num_samps()); } - + LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs()); device->trx_write_func = trx_usrp_write; device->trx_read_func = trx_usrp_read; s->sample_rate = openair0_cfg[0].sample_rate; - + // TODO: // init tx_forward_nsamps based usrp_time_offset ex if(is_equal(s->sample_rate, (double)30.72e6)) s->tx_forward_nsamps = 176; - + if(is_equal(s->sample_rate, (double)15.36e6)) s->tx_forward_nsamps = 90; - + if(is_equal(s->sample_rate, (double)7.68e6)) s->tx_forward_nsamps = 50; - - - if (device->recplay_state != NULL) { // record mode - device->recplay_state->ms_sample = (iqrec_t *) malloc(openair0_cfg[0].recplay_conf->u_sf_max * sizeof(iqrec_t)); - - if (device->recplay_state->ms_sample == NULL) { + + recplay_state_t *recPlay=device->recplay_state; + + if (recPlay != NULL) { // record mode + recPlay->maxSizeBytes=openair0_cfg[0].recplay_conf->u_sf_max * + (sizeof(iqrec_t)+BELL_LABS_IQ_BYTES_PER_SF); + recPlay->ms_sample = (iqrec_t *) malloc(recPlay->maxSizeBytes); + recPlay->currentPtr= (uint8_t *)recPlay->ms_sample; + + if (recPlay->ms_sample == NULL) { std::cerr<< "Memory allocation failed for subframe record or replay mode." << std::endl; exit(-1); } - - memset(device->recplay_state->ms_sample, 0, openair0_cfg[0].recplay_conf->u_sf_max * BELL_LABS_IQ_BYTES_PER_SF); } return 0; } diff --git a/targets/ARCH/iqplayer/iqplayer_lib.c b/targets/ARCH/iqplayer/iqplayer_lib.c index c4133d1b11..8b6844f9d3 100644 --- a/targets/ARCH/iqplayer/iqplayer_lib.c +++ b/targets/ARCH/iqplayer/iqplayer_lib.c @@ -25,7 +25,6 @@ */ #define _LARGEFILE_SOURCE #define _FILE_OFFSET_BITS 64 -#define NB_ANTENNAS_RX 2 #include #include #include @@ -40,18 +39,15 @@ #include "assertions.h" #include "common/utils/LOG/log.h" - - - - - static void parse_iqfile_header(openair0_device *device, iqfile_header_t *iq_fh) { - AssertFatal((memcmp(iq_fh->oaiid,OAIIQFILE_ID,sizeof(OAIIQFILE_ID)) == 0), - "iqfile doesn't seem to be compatible with oai (invalid id %.4s in header)\n", - iq_fh->oaiid); + char tmp[4]=OAIIQFILE_ID; + AssertFatal((memcmp(iq_fh->oaiid,tmp,sizeof(iq_fh->oaiid)) == 0), + "iqfile doesn't seem to be compatible with oai (invalid id %.4s in header)\n", + iq_fh->oaiid); device->type = iq_fh->devtype; device->openair0_cfg[0].tx_sample_advance=iq_fh->tx_sample_advance; device->openair0_cfg[0].tx_bw = device->openair0_cfg[0].rx_bw = iq_fh->bw; + device->recplay_state->nbSamplesBlocks=iq_fh->nbSamplesBlocks; LOG_UI(HW,"Replay iqs from %s device, bandwidth %e\n",get_devname(iq_fh->devtype),iq_fh->bw); } @@ -63,89 +59,73 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair recplay_state_t *s = device->recplay_state; recplay_conf_t *c = openair0_cfg->recplay_conf; + struct stat sb; + s->fd = open(c->u_sf_filename, O_RDONLY ); + if (s->fd >= 0 ) { + fstat(s->fd, &sb); + } else { + LOG_E( HW,"Cannot open %s exiting.\n", c->u_sf_filename ); + exit(-1); + } + if (s->use_mmap) { // use mmap - s->mmapfd = open(c->u_sf_filename, O_RDONLY ); - - if (s->mmapfd != 0) { - struct stat sb; - fstat(s->mmapfd, &sb); s->mapsize=sb.st_size; LOG_I(HW,"Loading subframes using mmap() from %s size=%lu bytes ...\n",c->u_sf_filename, (uint64_t)sb.st_size ); - void *mptr = mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->mmapfd, 0) ; - s->ms_sample = (iqrec_t *) ( mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->mmapfd, 0) + sizeof(iqfile_header_t)); + void *mptr = mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->fd, 0) ; + s->ms_sample = (iqrec_t *) ( mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->fd, 0) + sizeof(iqfile_header_t)); if (mptr != MAP_FAILED) { parse_iqfile_header(device, (iqfile_header_t *)mptr); s->ms_sample = (iqrec_t *)((char *)mptr + sizeof(iqfile_header_t)); - s->nb_samples = ((sb.st_size-sizeof(iqfile_header_t)) / sizeof(iqrec_t)); - int aligned = (((unsigned long)s->ms_sample & 31) == 0)? 1:0; - LOG_I(HW,"Loaded %u subframes.\n",s->nb_samples ); - - if (aligned == 0) { - LOG_E(HW, "mmap address is not 32 bytes aligned, exiting.\n" ); - close(s->mmapfd); - exit(-1); - } + LOG_I(HW,"Loaded %u subframes.\n",s->nbSamplesBlocks ); } else { LOG_E(HW,"Cannot mmap file, exiting.\n"); - close(s->mmapfd); + close(s->fd); exit(-1); } - } else { - LOG_E( HW,"Cannot open %s exiting.\n", c->u_sf_filename ); - exit(-1); - } } else { - s->iqfd = open(c->u_sf_filename, O_RDONLY); + iqfile_header_t fh; + size_t hs = read(s->fd,&fh,sizeof(fh)); - if (s->iqfd != 0) { - struct stat sb; - iqfile_header_t fh; - size_t hs = read(s->iqfd,&fh,sizeof(fh)); - - if (hs == sizeof(fh)) { - parse_iqfile_header(device, &fh); - fstat(s->iqfd, &sb); + if (hs == sizeof(fh)) { + parse_iqfile_header(device, &fh); + fstat(s->fd, &sb); s->mapsize=sb.st_size; - s->nb_samples = ((sb.st_size-sizeof(iqfile_header_t))/ sizeof(iqrec_t)); - LOG_I(HW, "Loading %u subframes from %s,size=%lu bytes ...\n",s->nb_samples, c->u_sf_filename,(uint64_t)sb.st_size); + LOG_I(HW, "Loading %u subframes from %s,size=%lu bytes ...\n",s->nbSamplesBlocks, c->u_sf_filename,(uint64_t)sb.st_size); // allocate buffer for 1 sample at a time - s->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t)); + s->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t)+MAX_BELL_LABS_IQ_BYTES_PER_SF*4); if (s->ms_sample == NULL) { LOG_E(HW,"Memory allocation failed for individual subframe replay mode.\n" ); - close(s->iqfd); + close(s->fd); exit(-1); } memset(s->ms_sample, 0, sizeof(iqrec_t)); // point at beginning of iqs in file - if (lseek(s->iqfd,sizeof(iqfile_header_t), SEEK_SET) == 0) { + if (lseek(s->fd,sizeof(iqfile_header_t), SEEK_SET) == 0) { LOG_I(HW,"Initial seek at beginning of the file\n" ); } else { LOG_I(HW,"Problem initial seek at beginning of the file\n"); } } else { LOG_E(HW,"Cannot read header in %s exiting.\n",c->u_sf_filename ); - close(s->iqfd); + close(s->fd); exit(-1); } - } else { - LOG_E(HW,"Cannot open %s exiting.\n",c->u_sf_filename ); - exit(-1); - } } + s->currentPtr=(uint8_t *)s->ms_sample; return 0; } /*! \brief start the oai iq player * \param device, the hardware used */ -static int trx_iqplayer_start(openair0_device *device){ - return 0; +static int trx_iqplayer_start(openair0_device *device) { + return 0; } /*! \brief Terminate operation of the oai iq player @@ -157,28 +137,22 @@ static void trx_iqplayer_end(openair0_device *device) { if (device->recplay_state == NULL) return; - + if (device->recplay_state->use_mmap) { if (device->recplay_state->ms_sample != MAP_FAILED) { munmap(device->recplay_state->ms_sample, device->recplay_state->mapsize); - device->recplay_state->ms_sample = NULL; - } - - if (device->recplay_state->mmapfd != 0) { - close(device->recplay_state->mmapfd); - device->recplay_state->mmapfd = 0; - } + } } else { if (device->recplay_state->ms_sample != NULL) { free(device->recplay_state->ms_sample); - device->recplay_state->ms_sample = NULL; - } - - if (device->recplay_state->iqfd != 0) { - close(device->recplay_state->iqfd); - device->recplay_state->iqfd = 0; - } + } } + device->recplay_state->ms_sample = NULL; + if (device->recplay_state->fd >= 0) { + close(device->recplay_state->fd); + device->recplay_state->fd = -1; + } + } /*! \brief Write iqs function when in replay mode, just introduce a delay, as configured at init time, @param device pointer to the device structure specific to the RF hardware target @@ -208,93 +182,68 @@ static int trx_iqplayer_write(openair0_device *device, openair0_timestamp timest * \returns the number of sample read */ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { - int samples_received=0; - static unsigned int cur_samples; - static int64_t wrap_count; - static int64_t wrap_ts; recplay_state_t *s = device->recplay_state; - if (cur_samples == s->nb_samples) { - cur_samples = 0; - wrap_count++; + if (s->curSamplesBlock==0 && s->wrap_count==0 ) + s->currentTs=s->ms_sample->ts; + + if (s->curSamplesBlock == s->nbSamplesBlocks) { + LOG_I(HW, "wrapping on iq file (%ld)\n", s->wrap_count); + s->curSamplesBlock = 0; + s->wrap_count++; - if (wrap_count == device->openair0_cfg->recplay_conf->u_sf_loops) { - LOG_W(HW, "iqplayer device terminating subframes replay after %u iteration\n",device->openair0_cfg->recplay_conf->u_sf_loops); + if (s->wrap_count == device->openair0_cfg->recplay_conf->u_sf_loops) { + LOG_W(HW, "iqplayer device terminating subframes replay after %u iteration\n", + device->openair0_cfg->recplay_conf->u_sf_loops); exit_function(__FILE__, __FUNCTION__, __LINE__,"replay ended, triggering process termination\n"); } - wrap_ts = wrap_count * (s->nb_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)); + LOG_I(HW,"go back at the beginning of IQ file"); + device->recplay_state->currentPtr=(uint8_t *)device->recplay_state->ms_sample; - if (!device->recplay_state->use_mmap) { - if (lseek(device->recplay_state->iqfd, 0, SEEK_SET) == 0) { - LOG_I(HW,"Seeking at the beginning of IQ file"); - } else { - LOG_I(HW, "Problem seeking at the beginning of IQ file"); + if (!s->use_mmap) { + if (lseek(device->recplay_state->fd, 0, SEEK_SET) != 0) { + LOG_E(HW, "Problem seeking at the beginning of IQ file"); } } } - if (s->use_mmap) { - if (cur_samples < s->nb_samples) { - *ptimestamp = (s->ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts; - - if (cur_samples == 0) { - LOG_I(HW,"starting subframes file with wrap_count=%lu wrap_ts=%lu ts=%lu\n", wrap_count,wrap_ts,*ptimestamp); - } - - memcpy(buff[0], &s->ms_sample[cur_samples].samples[0], nsamps*4); - cur_samples++; - } - } else { + if (!s->use_mmap) { // read sample from file - if (read(s->iqfd, s->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) { - LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*cur_samples ); - close(s->iqfd); - free(s->ms_sample); - s->ms_sample = NULL; - s->iqfd = 0; + if (read(s->fd, s->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) { + LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*s->curSamplesBlock ); exit(-1); - } - - if (cur_samples < s->nb_samples) { - static int64_t ts0 = 0; - - if ((cur_samples == 0) && (wrap_count == 0)) { - ts0 = s->ms_sample->ts; - } - - *ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts; - - if (cur_samples == 0) { - LOG_I(HW, "starting subframes file with wrap_count=%lu wrap_ts=%lu ts=%lu ",wrap_count,wrap_ts, *ptimestamp); - } - - memcpy(buff[0], &s->ms_sample->samples[0], nsamps*4); - cur_samples++; - // Prepare for next read - off_t where = lseek(s->iqfd, cur_samples * sizeof(iqrec_t), SEEK_SET); - - if (where < 0) { - LOG_E(HW,"Cannot lseek in iqfile: %s\n",strerror(errno)); + } else { + if (read(s->fd, s->ms_sample+1, s->ms_sample->nbBytes) != s->ms_sample->nbBytes) { + LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*s->curSamplesBlock ); exit(-1); } } } + iqrec_t *curHeader=(iqrec_t *)s->currentPtr; + AssertFatal(curHeader->header==BELL_LABS_IQ_HEADER,"" ); + // the current timestamp is the stored timestamp until we wrap on input + // USRP shifts 1 sample time to time + AssertFatal(s->wrap_count !=0 || abs(curHeader->ts-s->currentTs) < 5 ,""); + AssertFatal(nsamps*4==curHeader->nbBytes,""); + *ptimestamp = s->currentTs; + memcpy(buff[0], curHeader+1, nsamps*4); + s->curSamplesBlock++; + // Prepare for next read + s->currentTs+=nsamps; + + if (s->use_mmap) + s->currentPtr+=sizeof(iqrec_t)+s->ms_sample->nbBytes; + struct timespec req; - req.tv_sec = 0; - req.tv_nsec = (device->openair0_cfg[0].recplay_conf->u_sf_read_delay) * 1000; - nanosleep(&req, NULL); - + LOG_D(HW, "returning %d samples at ts %lu\n", nsamps, *ptimestamp); return nsamps; - - return samples_received; } - int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->openair0_cfg = openair0_cfg; device->trx_start_func = trx_iqplayer_start; @@ -313,5 +262,4 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { LOG_UI(HW,"iqplayer device initialized, replay %s for %i iterations",openair0_cfg->recplay_conf->u_sf_filename,openair0_cfg->recplay_conf->u_sf_loops); return 0; } - /*@}*/ diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md index 9ec0ae5065..4a8d5ff79a 100644 --- a/targets/ARCH/rfsimulator/README.md +++ b/targets/ARCH/rfsimulator/README.md @@ -59,6 +59,29 @@ The RF simulator is using the configuration module, and its parameters are defin Setting the env variable RFSIMULATOR can be used instead of using the serveraddr parameter; it is to preserve compatibility with previous version. +## How to use the RF simulator options + +Add the following options to the command line to enable the channel model and the IQ samples saving for future replay: +```bash +--rfsimulator.options chanmod,saviq +``` +or just: +```bash +--rfsimulator.options chanmod +``` +to enable the channel model. + +set the model with: +```bash +--rfsimulator.modelname AWGN +``` + +Example run: + +```bash +sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN +``` + ## 4G case For the UE, it should be set to the IP address of the eNB. For example: @@ -165,5 +188,50 @@ Only the input noise can be changed on command line with the `-s` parameter. With path loss = 0 set `-s 5` to see a little noise. `-s` is a shortcut to `channelmod.s`. It is expected to enhance the channel modelization flexibility by the addition of more parameters in the channelmod section. +Example to add a very small noise: +```bash +-s 30 +``` +to add a lot of noise: +```bash +-s 5 +``` + +Example run commands: +```bash +sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN + +``` +# Real time control and monitoring + +Add the `--telnetsrv` option to the command line. Then in a new shell, connect to the telnet server, example: +```bash +telnet 127.0.0.1 9090 +``` +once connected it is possible to monitor the current status: +```bash +channelmod show current +``` + +see the available channel models: +```bash +channelmod show predef +``` + +or modify the channel model, for example setting a new model: +```bash +rfsimu setmodel AWGN +``` +setting the pathloss, etc...: +```bash +channelmod modify +channelmod modify 0 ploss 15 +``` +where: +```bash + can be one of "riceanf", "aoa", "randaoa", "ploss", "offset", "forgetf" +``` + # Caveats Still issues in power control: txgain, rxgain are not used. + diff --git a/targets/ARCH/rfsimulator/apply_channelmod.c b/targets/ARCH/rfsimulator/apply_channelmod.c index 7aa5d78bf8..d7d3a68965 100644 --- a/targets/ARCH/rfsimulator/apply_channelmod.c +++ b/targets/ARCH/rfsimulator/apply_channelmod.c @@ -65,17 +65,8 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si // Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...) const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0); // Energy in one sample to calibrate input noise - //Fixme: modified the N0W computation, not understand the origin value - const double KT=1.38e-23*290; //Boltzman*temperature - // sampling rate is linked to acquisition band (the input pass band filter) - const double noise_figure_watt = KT*channelDesc->sampling_rate; - // Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ? - // the parameter "-s" is declared as SNR, but the input power is not well defined - // −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise) - const double rxGain= 132.24 - channelmod_get_snr_dB(); - // sqrt(4*noise_figure_watt) is the thermal noise factor (volts) - // fixme: the last constant is pure trial results to make decent noise - const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10; + // the normalized OAI value seems to be 256 as average amplitude (numerical amplification = 1) + const double noise_per_sample = pow(10,channelDesc->noise_power_dB/10.0) * 256; // Fixme: we don't fill the offset length samples at begining ? // anyway, in today code, channel_offset=0 const int dd = abs(channelDesc->channel_offset); @@ -83,10 +74,10 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si for (int i=0; i<((int)nbSamples-dd); i++) { struct complex16 *out_ptr=after_channel_sig+dd+i; - struct complex rx_tmp= {0}; + struct complexd rx_tmp= {0}; for (int txAnt=0; txAnt < nbTx; txAnt++) { - const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)]; + const struct complexd *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)]; //const struct complex *channelModelEnd=channelModel+channelDesc->channel_length; for (int l = 0; l<(int)channelDesc->channel_length; l++) { @@ -97,13 +88,14 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si // it would be better to split out each antenna in a separate flow // that will allow to mix ru antennas freely struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize]; - rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y; - rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y; + rx_tmp.r += tx16.r * channelModel[l].r - tx16.i * channelModel[l].i; + rx_tmp.i += tx16.i * channelModel[l].r + tx16.r * channelModel[l].i; } //l } - out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); - out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); + // Fixme: lround(), rount(), ... is detected by valgrind as error, not found why + out_ptr->r += lround(rx_tmp.r*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); + out_ptr->i += lround(rx_tmp.i*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); out_ptr++; } diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 81ea1cf8ba..13945998d7 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -54,50 +54,50 @@ #include #define PORT 4043 //default TCP port for this simulator -#define CirSize 307200 // 100ms is enough +#define CirSize 6144000 // 100ms is enough #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) #define MAX_SIMULATION_CONNECTED_NODES 5 #define GENERATE_CHANNEL 10 //each frame in DL -// Fixme: datamodel, external variables in .h files, ... -#include -extern RAN_CONTEXT_t RC; // #define RFSIMU_SECTION "rfsimulator" #define RFSIMU_OPTIONS_PARAMNAME "options" -# define RFSIM_CONFIG_HELP_OPTIONS " list of comma separated options to enable rf simulator functionalities. Available options: \n"\ + + +#define RFSIM_CONFIG_HELP_OPTIONS " list of comma separated options to enable rf simulator functionalities. Available options: \n"\ " chanmod: enable channel modelisation\n"\ " saviq: enable saving written iqs to a file\n" /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* configuration parameters for the rfsimulator device */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define RFSIMULATOR_PARAMS_DESC {\ - {"serveraddr", "\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ - {"serverport", "\n", 0, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\ - {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0 },\ - {"IQfile", "\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ - {"modelname", "\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\ - {"ploss", "\n", 0, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\ - {"forgetfact", "\n", 0, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\ - {"offset", "\n", 0, iptr:&(rfsimulator->chan_offset), defintval:0, TYPE_INT, 0 }\ +#define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED +#define RFSIMULATOR_PARAMS_DESC { \ + {"serveraddr", "\n", simOpt, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ + {"serverport", "\n", simOpt, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\ + {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0 },\ + {"IQfile", "\n",simOpt, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ + {"modelname", "\n", simOpt, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\ + {"ploss", "\n", simOpt, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\ + {"forgetfact", "\n", simOpt, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\ + {"offset", "\n", simOpt, iptr:&(rfsimulator->chan_offset), defintval:0, TYPE_INT, 0 }\ }; static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); static telnetshell_cmddef_t rfsimu_cmdarray[] = { - {"setmodel","",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, + {"setmodel"," ",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, {"","",NULL}, }; static telnetshell_vardef_t rfsimu_vardef[] = { {"",0,NULL} -}; +}; pthread_mutex_t Sockmutex; typedef struct complex16 sample_t; // 2*16 bits complex number @@ -132,12 +132,13 @@ typedef struct { double chan_pathloss; double chan_forgetfact; int chan_offset; + float noise_power_dB; void *telnetcmd_qid; poll_telnetcmdq_func_t poll_telnetcmdq; } rfsimulator_state_t; -void allocCirBuf(rfsimulator_state_t *bridge, int sock) { +static void allocCirBuf(rfsimulator_state_t *bridge, int sock) { buffer_t *ptr=&bridge->buf[sock]; AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, ""); ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1); @@ -170,29 +171,26 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { static bool init_done=false; if (!init_done) { - uint64_t rand; - FILE *h=fopen("/dev/random","r"); + uint64_t rand; + FILE *h=fopen("/dev/random","r"); + if ( 1 != fread(&rand,sizeof(rand),1,h) ) LOG_W(HW, "Simulator can't read /dev/random\n"); - fclose(h); + + fclose(h); randominit(rand); tableNor(rand); init_done=true; } - - ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, - bridge->channelmod, - bridge->sample_rate, - bridge->tx_bw, - bridge->chan_forgetfact, // forgetting_factor - bridge->chan_offset, // maybe used for TA - bridge->chan_pathloss); // path_loss in dB + char *modelname = (bridge->typeStamp == ENB_MAGICDL) ? "rfsimu_channel_ue0":"rfsimu_channel_enB0"; + ptr->channel_model=find_channel_desc_fromname(modelname); // path_loss in dB + AssertFatal((ptr->channel_model!= NULL),"Channel model %s not found, check config file\n",modelname); set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID); random_channel(ptr->channel_model,false); } } -void removeCirBuf(rfsimulator_state_t *bridge, int sock) { +static void removeCirBuf(rfsimulator_state_t *bridge, int sock) { AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, ""); close(sock); free(bridge->buf[sock].circularBuf); @@ -203,12 +201,12 @@ void removeCirBuf(rfsimulator_state_t *bridge, int sock) { bridge->buf[sock].conn_sock=-1; } -void socketError(rfsimulator_state_t *bridge, int sock) { +static void socketError(rfsimulator_state_t *bridge, int sock) { if (bridge->buf[sock].conn_sock!=-1) { LOG_W(HW,"Lost socket \n"); removeCirBuf(bridge, sock); - if (bridge->typeStamp==UE_MAGICDL_FDD) + if (bridge->typeStamp==UE_MAGICDL) exit(1); } } @@ -226,7 +224,7 @@ enum blocking_t { blocking }; -void setblocking(int sock, enum blocking_t active) { +static void setblocking(int sock, enum blocking_t active) { int opts; AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,""); @@ -240,7 +238,7 @@ void setblocking(int sock, enum blocking_t active) { static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps); -void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { +static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { if (t->saveIQfile != -1) { if (write(t->saveIQfile, _buf, count) != count ) LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno)); @@ -274,7 +272,7 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { } } -void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { +static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { char *saveF=NULL; char *modelname=NULL; paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC; @@ -295,7 +293,8 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { break; } else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) { init_channelmod(); - rfsimulator->channelmod=modelid_fromname(modelname); + load_channellist(rfsimulator->tx_num_channels, rfsimulator->rx_num_channels, rfsimulator->sample_rate, rfsimulator->tx_bw); + rfsimulator->channelmod=true; } else { fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]); exit(-1); @@ -309,49 +308,70 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || strncasecmp(rfsimulator->ip,"server",3) == 0 ) - rfsimulator->typeStamp = ENB_MAGICDL_FDD; + rfsimulator->typeStamp = ENB_MAGICDL; else - rfsimulator->typeStamp = UE_MAGICDL_FDD; + rfsimulator->typeStamp = UE_MAGICDL; } static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) { - char *modelname=NULL; - int s = sscanf(buff,"%ms\n",&modelname); - if (s == 1) { - int channelmod=modelid_fromname(modelname); + char *modelname=NULL; + char *modeltype=NULL; + if (debug) + prnt("rfsimu_setchanmod_cmd buffer \"%s\"\n",buff); + int s = sscanf(buff,"%m[^ ] %ms\n",&modelname, &modeltype); + + if (s == 2) { + int channelmod=modelid_fromstrtype(modeltype); + if (channelmod<0) - prnt("ERROR: model %s unknown\n",modelname); + prnt("ERROR: model type %s unknown\n",modeltype); else { - rfsimulator_state_t *t = (rfsimulator_state_t *)arg; - for (int i=0; ibuf[i]; - if (b->conn_sock >= 0 ) { + if ( b->channel_model==NULL) + continue; + if (b->channel_model->model_name==NULL) + continue; + if (b->conn_sock >= 0 && (strcmp(b->channel_model->model_name,modelname)==0)) { + channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels, - channelmod, - t->sample_rate, - t->tx_bw, - t->chan_forgetfact, // forgetting_factor - t->chan_offset, // maybe used for TA - t->chan_pathloss); // path_loss in dB + channelmod, + t->sample_rate, + t->tx_bw, + 30e-9, // TDL delay-spread parameter + t->chan_forgetfact, // forgetting_factor + t->chan_offset, // maybe used for TA + t->chan_pathloss, + t->noise_power_dB + ); // path_loss in dB set_channeldesc_owner(newmodel, RFSIMU_MODULEID); + set_channeldesc_name(newmodel,modelname); random_channel(newmodel,false); channel_desc_t *oldmodel=b->channel_model; b->channel_model=newmodel; free_channel_desc_scm(oldmodel); - prnt("New model %s applied to channel connected to sock %d\n",modelname,i); + prnt("New model type %s applied to channel %s connected to sock %d\n",modeltype,modelname,i); + found=1; + break; } - } + } /* for */ + if (found==0) + prnt("Channel %s not found or not currently used\n",modelname); } } else { - prnt("ERROR: no model specified\n"); + prnt("ERROR: 2 parameters required: model name and model type (%i found)\n",s); } + free(modelname); + free(modeltype); return CMDSTATUS_FOUND; } -int server_start(openair0_device *device) { +static int startServer(openair0_device *device) { rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; - t->typeStamp=ENB_MAGICDL_FDD; + t->typeStamp=ENB_MAGICDL; AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); int enable = 1; AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, ""); @@ -365,16 +385,16 @@ sin_addr: }; bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr)); AssertFatal(listen(t->listen_sock, 5) == 0, ""); - struct epoll_event ev={0}; + struct epoll_event ev= {0}; ev.events = EPOLLIN; ev.data.fd = t->listen_sock; AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != -1, ""); return 0; } -int start_ue(openair0_device *device) { +static int startClient(openair0_device *device) { rfsimulator_state_t *t = device->priv; - t->typeStamp=UE_MAGICDL_FDD; + t->typeStamp=UE_MAGICDL; int sock; AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); struct sockaddr_in addr = { @@ -437,7 +457,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp if (t->lastWroteTS > timestamp+nsamps) LOG_E(HW,"Not supported to send Tx out of order (same in USRP) %lu, %lu\n", - t->lastWroteTS, timestamp); + t->lastWroteTS, timestamp); t->lastWroteTS=timestamp+nsamps; @@ -449,14 +469,14 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp return nsamps; } -int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { +static int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags, false); } static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initial) { // Process all incoming events on sockets // store the data in lists - struct epoll_event events[FD_SETSIZE]= {0}; + struct epoll_event events[FD_SETSIZE]= {{0}}; int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, timeout); if ( nfds==-1 ) { @@ -474,7 +494,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, ""); setblocking(conn_sock, notBlocking); allocCirBuf(t, conn_sock); - LOG_I(HW,"A ue connected, sending the current time\n"); + LOG_I(HW,"A client connected, sending the current time\n"); struct complex16 v= {0}; void *samplesVoid[t->tx_num_channels]; @@ -502,9 +522,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi if ( b->headerMode) blockSz=b->remainToTransfer; else - blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ? + blockSz= b->transferPtr + b->remainToTransfer <= b->circularBufEnd ? b->remainToTransfer : - b->circularBufEnd - 1 - b->transferPtr ; + b->circularBufEnd - b->transferPtr ; ssize_t sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); @@ -520,43 +540,42 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi AssertFatal((b->remainToTransfer-=sz) >= 0, ""); b->transferPtr+=sz; - if (b->transferPtr==b->circularBufEnd - 1) + if (b->transferPtr==b->circularBufEnd ) b->transferPtr=(char *)b->circularBuf; // check the header and start block transfer if ( b->headerMode==true && b->remainToTransfer==0) { - AssertFatal( (t->typeStamp == UE_MAGICDL_FDD && b->th.magic==ENB_MAGICDL_FDD) || - (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol"); + AssertFatal( (t->typeStamp == UE_MAGICDL && b->th.magic==ENB_MAGICDL) || + (t->typeStamp == ENB_MAGICDL && b->th.magic==UE_MAGICDL), "Socket Error in protocol"); b->headerMode=false; if ( t->nextTimestamp == 0 ) { // First block in UE, resync with the eNB current TS - t->nextTimestamp=b->th.timestamp> nsamps_for_initial ? - b->th.timestamp - nsamps_for_initial : - 0; - b->lastReceivedTS=b->th.timestamp> nsamps_for_initial ? - b->th.timestamp : - nsamps_for_initial; - LOG_W(HW,"UE got first timestamp: starting at %lu\n", t->nextTimestamp); - b->trashingPacket=true; - } else if ( b->lastReceivedTS < b->th.timestamp) { + t->nextTimestamp=b->th.timestamp> nsamps_for_initial ? + b->th.timestamp - nsamps_for_initial : + 0; + b->lastReceivedTS=b->th.timestamp> nsamps_for_initial ? + b->th.timestamp : + nsamps_for_initial; + LOG_W(HW,"UE got first timestamp: starting at %lu\n", t->nextTimestamp); + b->trashingPacket=true; + } else if ( b->lastReceivedTS < b->th.timestamp) { int nbAnt= b->th.nbAnt; if ( b->th.timestamp-b->lastReceivedTS < CirSize ) { - for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { - for (int a=0; a < nbAnt; a++) { - b->circularBuf[(index*nbAnt+a)%CirSize].r = 0; - b->circularBuf[(index*nbAnt+a)%CirSize].i = 0; + for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { + for (int a=0; a < nbAnt; a++) { + b->circularBuf[(index*nbAnt+a)%CirSize].r = 0; + b->circularBuf[(index*nbAnt+a)%CirSize].i = 0; + } } - } } else { - memset(b->circularBuf, 0, sampleToByte(CirSize,1)); - } + memset(b->circularBuf, 0, sampleToByte(CirSize,1)); + } - if (b->lastReceivedTS != 0 && b->th.timestamp-b->lastReceivedTS > 50 ) + if (b->lastReceivedTS != 0 && b->th.timestamp-b->lastReceivedTS < 1000) LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS ); b->lastReceivedTS=b->th.timestamp; - } else if ( b->lastReceivedTS > b->th.timestamp && b->th.size == 1 ) { LOG_W(HW,"Received Rx/Tx synchro out of order\n"); b->trashingPacket=true; @@ -564,7 +583,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi // normal case } else { LOG_E(HW, "received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); - b->trashingPacket=true; + b->trashingPacket=true; } pthread_mutex_lock(&Sockmutex); @@ -598,9 +617,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi return nfds>0; } -int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { - if (nbAnt != 1) { - LOG_W(HW, "rfsimulator: only 1 antenna tested\n"); +static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { + if (nbAnt > 4) { + LOG_W(HW, "rfsimulator: only 4 antenna tested\n"); } rfsimulator_state_t *t = device->priv; @@ -625,7 +644,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo t->nextTimestamp+=nsamps; if ( ((t->nextTimestamp/nsamps)%100) == 0) - LOG_W(HW,"No UE, Generated void samples for Rx: %ld\n", t->nextTimestamp); + LOG_D(HW,"No UE, Generated void samples for Rx: %ld\n", t->nextTimestamp); *ptimestamp = t->nextTimestamp-nsamps; return nsamps; @@ -643,27 +662,27 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo // We can never write is the past from the received time // So, the node perform receive but will never write these symbols // let's tell this to the opposite node - // We send timestamp for nb samples required - // assuming this should have been done earlier if a Tx would exist + // We send timestamp for nb samples required + // assuming this should have been done earlier if a Tx would exist pthread_mutex_unlock(&Sockmutex); struct complex16 v= {0}; - void *samplesVoid[t->tx_num_channels]; + void *dummyS[t->tx_num_channels]; for ( int i=0; i < t->tx_num_channels; i++) - samplesVoid[i]=(void *)&v; + dummyS[i]=(void *)&v; - LOG_I(HW, "No samples Tx occured, so we send 1 sample to notify it: Tx:%lu, Rx:%lu\n", - t->lastWroteTS, t->nextTimestamp); + LOG_I(HW, "No samples Tx occured, so we send 1 sample to notify it: Tx:%lu, Rx:%lu\n", + t->lastWroteTS, t->nextTimestamp); rfsimulator_write_internal(t, t->nextTimestamp, - samplesVoid, 1, + dummyS, 1, t->tx_num_channels, 1, true); } else { - pthread_mutex_unlock(&Sockmutex); + pthread_mutex_unlock(&Sockmutex); LOG_W(HW, "trx_write came from another thread\n"); } } else pthread_mutex_unlock(&Sockmutex); - + bool have_to_wait; do { @@ -703,8 +722,9 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo // it seems legacy behavior is: never in UL, each frame in DL if (reGenerateChannel) random_channel(ptr->channel_model,0); + if (t->poll_telnetcmdq) - t->poll_telnetcmdq(t->telnetcmd_qid,t); + t->poll_telnetcmdq(t->telnetcmd_qid,t); for (int a=0; achannel_model != NULL ) // apply a channel model @@ -716,14 +736,20 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo CirSize ); else { // no channel modeling + double H_awgn_mimo[4][4] ={{1.0, 0.5, 0.25, 0.125},//rx 0 + {0.5, 1.0, 0.5, 0.25}, //rx 1 + {0.25, 0.5, 1.0, 0.5}, //rx 2 + {0.125, 0.25, 0.5, 1.0}};//rx 3 + sample_t *out=(sample_t *)samplesVoid[a]; int nbAnt_tx = ptr->th.nbAnt;//number of Tx antennas + //LOG_I(HW, "nbAnt_tx %d\n",nbAnt_tx); for (int i=0; i < nsamps; i++) {//loop over nsamps - for (int a_tx=0; a_txcircularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].r; - out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].i; - } // end for a_tx + for (int a_tx=0; a_txcircularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].r*H_awgn_mimo[a][a_tx]); + out[i].i += (short)(ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].i*H_awgn_mimo[a][a_tx]); + } // end for a_tx } // end for i (number of samps) } // end of no channel modeling } // end for a (number of rx antennas) @@ -738,31 +764,24 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo signal_energy(samplesVoid[0], nsamps)); return nsamps; } -int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) { - abort(); + +static int rfsimulator_get_stats(openair0_device *device) { return 0; } -int rfsimulator_reply(openair0_device *device, void *msg, ssize_t msg_len) { - abort(); +static int rfsimulator_reset_stats(openair0_device *device) { return 0; } -int rfsimulator_get_stats(openair0_device *device) { +static void rfsimulator_end(openair0_device *device) {} +static int rfsimulator_stop(openair0_device *device) { return 0; } -int rfsimulator_reset_stats(openair0_device *device) { +static int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { return 0; } -void rfsimulator_end(openair0_device *device) {} -int rfsimulator_stop(openair0_device *device) { +static int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { return 0; } -int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { - return 0; -} -int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { - return 0; -} -int rfsimulator_write_init(openair0_device *device){ +static int rfsimulator_write_init(openair0_device *device) { return 0; } __attribute__((__visibility__("default"))) @@ -770,12 +789,17 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { // to change the log level, use this on command line // --log_config.hw_log_level debug rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1); + // initialize channel simulation + rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels; + rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels; + rfsimulator->sample_rate=openair0_cfg->sample_rate; + rfsimulator->tx_bw=openair0_cfg->tx_bw; rfsimulator_readconfig(rfsimulator); pthread_mutex_init(&Sockmutex, NULL); - LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE"); - device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ? - server_start : - start_ue; + LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL ? "server waiting opposite rfsimulators to connect" : "client: will connect to a rfsimulator server side"); + device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL ? + startServer : + startClient; device->trx_get_stats_func = rfsimulator_get_stats; device->trx_reset_stats_func = rfsimulator_reset_stats; device->trx_end_func = rfsimulator_end; @@ -785,7 +809,8 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->trx_write_func = rfsimulator_write; device->trx_read_func = rfsimulator_read; /* let's pretend to be a b2x0 */ - device->type = USRP_B200_DEV; + device->type = RFSIMULATOR; + openair0_cfg[0].rx_gain[0] = 0; device->openair0_cfg=&openair0_cfg[0]; device->priv = rfsimulator; device->trx_write_init = rfsimulator_write_init; @@ -794,25 +819,23 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->buf[i].conn_sock=-1; AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,""); - // initialize channel simulation - rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels; - rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels; - rfsimulator->sample_rate=openair0_cfg->sample_rate; - rfsimulator->tx_bw=openair0_cfg->tx_bw; + //randominit(0); set_taus_seed(0); - /* look for telnet server, if it is loaded, add the channel modeling commands to it */ + /* look for telnet server, if it is loaded, add the channel modeling commands to it */ add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); - + if (addcmd != NULL) { - rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME); + rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME); addcmd("rfsimu",rfsimu_vardef,rfsimu_cmdarray); + for(int i=0; rfsimu_cmdarray[i].cmdfunc != NULL; i++) { - if ( rfsimu_cmdarray[i].qptr != NULL) { + if ( rfsimu_cmdarray[i].qptr != NULL) { rfsimulator->telnetcmd_qid = rfsimu_cmdarray[i].qptr; break; } - } - } + } + } + return 0; } diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c index 73f6321ffe..cf025680cd 100644 --- a/targets/ARCH/rfsimulator/stored_node.c +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -34,7 +34,8 @@ int fullread(int fd, void *_buf, int count) { while (count) { l = read(fd, buf, count); - if (l <= 0) return -1; + if (l <= 0) + return -1; count -= l; buf += l; @@ -43,6 +44,44 @@ int fullread(int fd, void *_buf, int count) { return ret; } +#define shift 4 +int32_t signal_energy(int32_t *input,uint32_t length) { + int32_t i; + int32_t temp,temp2; + register __m64 mm0,mm1,mm2,mm3; + __m64 *in = (__m64 *)input; + mm0 = _mm_setzero_si64();//pxor(mm0,mm0); + mm3 = _mm_setzero_si64();//pxor(mm3,mm3); + + for (i=0; i>1; i++) { + mm1 = in[i]; + mm2 = mm1; + mm1 = _m_pmaddwd(mm1,mm1); + mm1 = _m_psradi(mm1,shift);// shift any 32 bits blocs of the word by the value shift + mm0 = _m_paddd(mm0,mm1);// add the two 64 bits words 4 bytes by 4 bytes + // mm2 = _m_psrawi(mm2,shift_DC); + mm3 = _m_paddw(mm3,mm2);// add the two 64 bits words 2 bytes by 2 bytes + } + + mm1 = mm0; + mm0 = _m_psrlqi(mm0,32); + mm0 = _m_paddd(mm0,mm1); + temp = _m_to_int(mm0); + temp/=length; + temp<<=shift; // this is the average of x^2 + // now remove the DC component + mm2 = _m_psrlqi(mm3,32); + mm2 = _m_paddw(mm2,mm3); + mm2 = _m_pmaddwd(mm2,mm2); + temp2 = _m_to_int(mm2); + temp2/=(length*length); + // temp2<<=(2*shift_DC); + temp -= temp2; + _mm_empty(); + _m_empty(); + return((temp>0)?temp:1); +} + void fullwrite(int fd, void *_buf, int count) { char *buf = _buf; @@ -131,8 +170,8 @@ void setblocking(int sock, enum blocking_t active) { } int main(int argc, char *argv[]) { - if(argc != 4) { - printf("Need parameters: source file, server or destination IP, TCP port\n"); + if(argc < 4) { + printf("Need parameters: source file, server or destination IP, TCP port (4043), 'UL|DL' if raw 2*16bits format: UL for UL IQ, DL for DL IQs \n"); exit(1); } @@ -147,10 +186,23 @@ int main(int argc, char *argv[]) { serviceSock=client_start(argv[2],atoi(argv[3])); } + uint64_t typeStamp=ENB_MAGICDL; + boolean_t raw=false; + + if ( argc == 5 ) { + raw=true; + + if (strcmp(argv[4],"UL") == 0 ) + typeStamp=UE_MAGICDL; + } + samplesBlockHeader_t header; int bufSize=100000; void *buff=malloc(bufSize); - uint64_t readTS=0; + uint64_t timestamp=0; + const int blockSize=1920; + // If fileSize is not multiple of blockSize*4 then discard remaining samples + fileSize = (fileSize/(blockSize<<2))*(blockSize<<2); while (1) { //Rewind the file to loop on the samples @@ -159,10 +211,21 @@ int main(int argc, char *argv[]) { // Read one block and send it setblocking(serviceSock, blocking); - AssertFatal(read(fd,&header,sizeof(header)), ""); + + if ( raw ) { + header.magic=typeStamp; + header.size=blockSize; + header.nbAnt=1; + header.timestamp=timestamp; + timestamp+=blockSize; + header.option_value=0; + header.option_flag=0; + } else { + AssertFatal(read(fd,&header,sizeof(header)), ""); + } + fullwrite(serviceSock, &header, sizeof(header)); int dataSize=sizeof(int32_t)*header.size*header.nbAnt; - uint64_t wroteTS=header.timestamp; if (dataSize>bufSize) { void *new_buff = realloc(buff, dataSize); @@ -176,21 +239,28 @@ int main(int argc, char *argv[]) { } AssertFatal(read(fd,buff,dataSize) == dataSize, ""); + + if (raw) // UHD shifts the 12 ADC values in MSB + for (int i=0; i 0 ) ; } return 0; diff --git a/targets/COMMON/create_nr_tasks.c b/targets/COMMON/create_nr_tasks.c deleted file mode 100644 index 13f72b3876..0000000000 --- a/targets/COMMON/create_nr_tasks.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - - -# include "intertask_interface.h" -# include "create_nr_tasks.h" -# include "common/utils/LOG/log.h" - -# ifdef OPENAIR2 -#include "sctp_eNB_task.h" -#include "s1ap_eNB.h" -#include "nas_ue_task.h" -#include "udp_eNB_task.h" -#include "gtpv1u_eNB_task.h" -# if ENABLE_RAL -# include "lteRALue.h" -# include "lteRALenb.h" -# endif -#include "RRC/NR/nr_rrc_defs.h" -# endif -# include "gnb_app.h" - -extern int emulate_rf; - -int create_gNB_tasks(uint32_t gnb_nb) -{ - LOG_D(GNB_APP, "%s(gnb_nb:%d\n", __FUNCTION__, gnb_nb); - - itti_wait_ready(1); - if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) { - LOG_E(PDCP, "Create task for L2L1 failed\n"); - return -1; - } - - if (gnb_nb > 0) { - // Last task to create, others task must be ready before its start - if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { - LOG_E(GNB_APP, "Create task for gNB APP failed\n"); - return -1; - } - } - - - if (EPC_MODE_ENABLED) { - if (gnb_nb > 0) { - /*if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) { - LOG_E(SCTP, "Create task for SCTP failed\n"); - return -1; - } - - if (itti_create_task (TASK_S1AP, s1ap_eNB_task, NULL) < 0) { - LOG_E(S1AP, "Create task for S1AP failed\n"); - return -1; - }*/ - if(!emulate_rf){ - if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) { - LOG_E(UDP_, "Create task for UDP failed\n"); - return -1; - } - } - - if (itti_create_task (TASK_GTPV1_U, >pv1u_eNB_task, NULL) < 0) { - LOG_E(GTPU, "Create task for GTPV1U failed\n"); - return -1; - } - } - - } - - /*if (gnb_nb > 0) { - // Last task to create, others task must be ready before its start - if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { - LOG_E(GNB_APP, "Create task for gNB APP failed\n"); - return -1; - } - }*/ - - - if (gnb_nb > 0) { - LOG_I(NR_RRC,"Creating NR RRC gNB Task\n"); - - if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) { - LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n"); - return -1; - } - } - - - itti_wait_ready(0); - - return 0; -} -//#endif diff --git a/targets/COMMON/create_nr_tasks.h b/targets/COMMON/create_nr_tasks.h index ca259a2b34..23dd23e7db 100644 --- a/targets/COMMON/create_nr_tasks.h +++ b/targets/COMMON/create_nr_tasks.h @@ -22,8 +22,6 @@ #ifndef CREATE_NR_TASKS_H_ #define CREATE_NR_TASKS_H_ -/* External declaration of L2L1 task that depend on the target */ -extern void *l2l1_task(void *arg); int create_gNB_tasks(uint32_t gnb_nb); diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c index 4d57ab4e16..ffeb368e73 100644 --- a/targets/COMMON/create_tasks.c +++ b/targets/COMMON/create_tasks.c @@ -25,7 +25,6 @@ # include "targets/RT/USER/lte-softmodem.h" # include "common/ran_context.h" -#ifdef OPENAIR2 #include "sctp_eNB_task.h" #include "x2ap_eNB.h" #include "s1ap_eNB.h" @@ -36,12 +35,12 @@ #include "lteRALenb.h" #endif #include "RRC/LTE/rrc_defs.h" -#endif # include "f1ap_cu_task.h" # include "f1ap_du_task.h" # include "enb_app.h" # include "openair2/LAYER2/MAC/mac_proto.h" #include +#include extern RAN_CONTEXT_t RC; diff --git a/targets/COMMON/create_tasks.h b/targets/COMMON/create_tasks.h index 843897cefb..e3f871964a 100644 --- a/targets/COMMON/create_tasks.h +++ b/targets/COMMON/create_tasks.h @@ -22,9 +22,6 @@ #ifndef CREATE_TASKS_H_ #define CREATE_TASKS_H_ -/* External declaration of L2L1 task that depend on the target */ -extern void *l2l1_task(void *arg); - int create_tasks(uint32_t enb_nb); int create_tasks_ue(uint32_t ue_nb); int create_tasks_mbms(uint32_t enb_nb); diff --git a/targets/COMMON/create_tasks_mbms.c b/targets/COMMON/create_tasks_mbms.c index 5f81592b96..8b1736853f 100644 --- a/targets/COMMON/create_tasks_mbms.c +++ b/targets/COMMON/create_tasks_mbms.c @@ -25,7 +25,6 @@ # include "targets/RT/USER/lte-softmodem.h" # include "common/ran_context.h" -#ifdef OPENAIR2 #include "sctp_eNB_task.h" #include "x2ap_eNB.h" #include "s1ap_eNB.h" @@ -40,13 +39,13 @@ #include "lteRALenb.h" #endif #include "RRC/LTE/rrc_defs.h" -#endif # include "f1ap_cu_task.h" # include "f1ap_du_task.h" # include "enb_app.h" # include "mce_app.h" # include "mme_app.h" +#include //extern RAN_CONTEXT_t RC; int create_tasks_mbms(uint32_t enb_nb) { diff --git a/targets/COMMON/create_tasks_ue.c b/targets/COMMON/create_tasks_ue.c index 06f36641e7..3b9b7cf7bb 100644 --- a/targets/COMMON/create_tasks_ue.c +++ b/targets/COMMON/create_tasks_ue.c @@ -23,7 +23,6 @@ # include "create_tasks.h" # include "common/utils/LOG/log.h" -#ifdef OPENAIR2 #include "sctp_eNB_task.h" #include "s1ap_eNB.h" #include "openair3/NAS/UE/nas_ue_task.h" @@ -34,7 +33,6 @@ #include "lteRALenb.h" #endif #include "RRC/LTE/rrc_defs.h" -#endif # include "enb_app.h" int create_tasks_ue(uint32_t ue_nb) { diff --git a/targets/COMMON/openairinterface5g_limits.h b/targets/COMMON/openairinterface5g_limits.h index aa99eee048..9260fe2701 100644 --- a/targets/COMMON/openairinterface5g_limits.h +++ b/targets/COMMON/openairinterface5g_limits.h @@ -6,34 +6,40 @@ # define NUMBER_OF_gNB_MAX 1 # define NUMBER_OF_RU_MAX 2 # define NUMBER_OF_NR_RU_MAX 2 +# define NUMBER_OF_UCI_MAX 16 +# define NUMBER_OF_ULSCH_MAX 8 +# define NUMBER_OF_DLSCH_MAX 8 +# define NUMBER_OF_SRS_MAX 16 +# define NUMBER_OF_NR_ULSCH_MAX 8 +# define NUMBER_OF_NR_DLSCH_MAX 8 +# define NUMBER_OF_NR_UCI_MAX 16 +# define NUMBER_OF_NR_SRS_MAX 16 +# define NUMBER_OF_NR_CSIRS_MAX 16 +# define NUMBER_OF_SCH_STATS_MAX 16 + +# define NUMBER_OF_NR_SCH_STATS_MAX 16 + +# define NUMBER_OF_NR_PUCCH_MAX 16 +# define NUMBER_OF_NR_SR_MAX 16 +# define NUMBER_OF_NR_PDCCH_MAX 16 + +#define MAX_MANAGED_ENB_PER_MOBILE 2 +#define MAX_MANAGED_GNB_PER_MOBILE 2 + # ifndef PHYSIM # ifndef UE_EXPANSION -// TODO:L2 FAPI simulator. -// UESIM_EXPANSION is used to be same value of NUMBER_OF_UE_MAX -// in eNB and UE. -// now , if we use --mu option in UE, compiling error will occur. -// This problem will be fixed in the future. -# ifndef UESIM_EXPANSION # define NUMBER_OF_UE_MAX 4 # define NUMBER_OF_NR_UE_MAX 4 -# define NUMBER_OF_UCI_VARS_MAX 14 # define NUMBER_OF_CONNECTED_eNB_MAX 1 # define NUMBER_OF_CONNECTED_gNB_MAX 1 -# else -# define NUMBER_OF_UE_MAX 256 -# define NUMBER_OF_UCI_VARS_MAX 256 -# define NUMBER_OF_CONNECTED_eNB_MAX 1 -# define NUMBER_OF_CONNECTED_gNB_MAX 3 -# endif # else # define NUMBER_OF_UE_MAX 256 -# define NUMBER_OF_UCI_VARS_MAX 256 # define NUMBER_OF_CONNECTED_eNB_MAX 1 # define NUMBER_OF_CONNECTED_gNB_MAX 1 # endif # else -# define NUMBER_OF_UE_MAX 1 -# define NUMBER_OF_UCI_VARS_MAX 56 +# define NUMBER_OF_UE_MAX 4 +# define NUMBER_OF_NR_UE_MAX 4 # define NUMBER_OF_CONNECTED_eNB_MAX 1 # define NUMBER_OF_CONNECTED_gNB_MAX 1 # endif @@ -48,17 +54,10 @@ eNB process will exit because unexpected access happens. Now some parts are using NUMBER_OF_UE_MAX and the other are using MAX_MOBILES_PER_ENB in for-loop. */ -# ifndef UESIM_EXPANSION # define NUMBER_OF_UE_MAX 16 # define NUMBER_OF_UCI_VARS_MAX 56 # define NUMBER_OF_CONNECTED_eNB_MAX 3 # define NUMBER_OF_CONNECTED_gNB_MAX 3 -# else -# define NUMBER_OF_UE_MAX 256 -# define NUMBER_OF_UCI_VARS_MAX 256 -# define NUMBER_OF_CONNECTED_eNB_MAX 1 -# define NUMBER_OF_CONNECTED_gNB_MAX 3 -# endif # else # define NUMBER_OF_UE_MAX 256 # define NUMBER_OF_UCI_VARS_MAX 256 diff --git a/targets/COMMON/threads_t.h b/targets/COMMON/threads_t.h index 0671f40988..5fb1645444 100644 --- a/targets/COMMON/threads_t.h +++ b/targets/COMMON/threads_t.h @@ -1,5 +1,5 @@ -#ifndef _THREADS_T_H_ -#define _THREADS_T_H_ +#ifndef _TARGETS_COMMON_THREADS_T_H_ +#define _TARGETS_COMMON_THREADS_T_H_ typedef struct threads_s { int main; @@ -18,4 +18,4 @@ typedef struct threads_s { //int dlsch_td1_three; } threads_t; -#endif /* _THREADS_T_H_ */ +#endif /* _TARGETS_COMMON_THREADS_T_H_ */ diff --git a/targets/Makefile.common b/targets/Makefile.common deleted file mode 100644 index ecd5f3821a..0000000000 --- a/targets/Makefile.common +++ /dev/null @@ -1,248 +0,0 @@ -# This file gathers compilation directive shared between lte-softmodem and oaisim -export COMMON_UTILS_DIR = $(OPENAIR_DIR)/common/utils -export UE_NAS_DIR = $(OPENAIR_DIR)/openair3/NAS -export S1AP_DIR = $(OPENAIR_DIR)/openair3/S1AP -export X2AP_DIR = $(OPENAIR_DIR)/openair2/X2AP -export SCTP_DIR = $(OPENAIR_DIR)/openair3/SCTP -export UDP_DIR = $(OPENAIR_DIR)/openair3/UDP -export GTPV1U_DIR = $(OPENAIR_DIR)/openair3/GTPV1-U -export SECU_DIR = $(OPENAIR_DIR)/openair3/SECU - -UE_NAS_OBJ_DIR = $(subst $(OPENAIR_DIR),$(OBJS_DIR),$(UE_NAS_DIR)) -SECU_OBJ_DIR = $(subst $(OPENAIR_DIR),$(OBJS_DIR),$(SECU_DIR)) -S1AP_OBJ_DIR = $(subst $(OPENAIR_DIR),$(OBJS_DIR),$(S1AP_DIR)) -X2AP_OBJ_DIR = $(subst $(OPENAIR_DIR),$(OBJS_DIR),$(X2AP_DIR)) -SCTP_OBJ_DIR = $(subst $(OPENAIR_DIR),$(OBJS_DIR),$(SCTP_DIR)) -UDP_OBJ_DIR = $(subst $(OPENAIR_DIR),$(OBJS_DIR),$(UDP_DIR)) -GTPV1U_OBJ_DIR = $(subst $(OPENAIR_DIR),$(OBJS_DIR),$(GTPV1U_DIR)) - -#Export common cflags (between softmodem and oaisim) -COMMON_CFLAGS = \ - -D'FIRMWARE_VERSION="$(SVN_REV) - $(DATE_REV)"' \ - -Wall \ - -fno-strict-aliasing \ - -O2 \ - -Werror=implicit-function-declaration - -# the code already uses C99 integer type (like int32_t) -# switch on full support for C99 + GNU extensions -CFLAGS += -std=gnu99 - -ITTI_MESSAGES_H = messages_xml.h -ITTI_MESSAGES_XML = messages.xml -ITTI_MESSAGES_FILE = $(ITTI_DIR)/intertask_interface_types.h - -include $(COMMON_UTILS_DIR)/Makefile.inc -include $(OPENAIR_TARGETS)/COMMON/Makefile.inc -include $(OPENAIR2_DIR)/NAS/Makefile.inc - -ifeq ($(SECU), 1) -ifeq ($(NETTLE_FOUND), 0) -@(warning "Nettle library >= 2.5 is not installed on your system, nettle-dev lib needed, continuing with security disabled") -SECU=0 -else -ifeq ($(OPENSSL_FOUND), 0) -@(warning "openssl library is not installed on your system, openssl lib needed, continuing with security disabled") -SECU=0 -else -LIBS += $(OPENSSL_LIBS) $(NETTLE_LIBS) -endif -endif -endif - -CFLAGS += -DJUMBO_FRAME - -ifdef MAX_NUM_CCs -CFLAGS += -DMAX_NUM_CCs=$(MAX_NUM_CCs) -COMMON_CFLAGS += -DMAX_NUM_CCs=$(MAX_NUM_CCs) -else -CFLAGS += -DMAX_NUM_CCs=1 -COMMON_CFLAGS += -DMAX_NUM_CCs=1 -endif - -ifeq ($(ENABLE_RAL), 1) -CFLAGS += -DENABLE_RAL -endif - -ifeq ($(PDCP_USE_NETLINK),1) -CFLAGS += -DPDCP_USE_NETLINK -endif -ifeq ($(LIBCONFIG_LONG),1) -CFLAGS += -DLIBCONFIG_LONG -endif - -# add R9 -ifeq ($(USE_MME), R10) -COMMON_CFLAGS += -DENABLE_USE_MME -ENABLE_ITTI = 1 -ifeq ($(LINK_ENB_PDCP_TO_GTPV1U), 1) - COMMON_CFLAGS += -DLINK_ENB_PDCP_TO_GTPV1U -# COMMON_CFLAGS += -I$(UDP_DIR) -# COMMON_CFLAGS += -I$(GTPV1U_DIR) -# COMMON_CFLAGS += -I$(GTPV1U_DIR)/nw-gtpv1u/shared -endif -endif - -ifeq ($(ENABLE_ITTI),1) -COMMON_CFLAGS += -DENABLE_ITTI -COMMON_CFLAGS += -I$(OPENAIR1_DIR) -COMMON_CFLAGS += -I$(OPENAIR2_DIR)/NAS -COMMON_CFLAGS += $(L2_incl) -COMMON_CFLAGS += $(UTILS_incl) -SHARED_DEPENDENCIES += $(ITTI_MESSAGES_H) -endif - -ifeq ($(USE_MME), R10) -LIBS += $(UE_NAS_OBJ_DIR)/libuenas.a $(SECU_OBJ_DIR)/libsecu.a -LIBS += $(S1AP_OBJ_DIR)/libs1ap.a $(SCTP_OBJ_DIR)/libsctp.a -lsctp -lcrypt -LIBS += $(UDP_OBJ_DIR)/libudp.a $(GTPV1U_OBJ_DIR)/libgtpv1u.a - -ifdef X2AP -LIBS += $(X2AP_OBJ_DIR)/libx2ap.a -SHARED_DEPENDENCIES += $(UE_NAS_OBJ_DIR)/libuenas.a $(SECU_OBJ_DIR)/libsecu.a $(X2AP_OBJ_DIR)/libx2ap.a $(S1AP_OBJ_DIR)/libs1ap.a $(SCTP_OBJ_DIR)/libsctp.a $(UDP_OBJ_DIR)/libudp.a $(GTPV1U_OBJ_DIR)/libgtpv1u.a -else -SHARED_DEPENDENCIES += $(UE_NAS_OBJ_DIR)/libuenas.a $(SECU_OBJ_DIR)/libsecu.a $(S1AP_OBJ_DIR)/libs1ap.a $(SCTP_OBJ_DIR)/libsctp.a $(UDP_OBJ_DIR)/libudp.a $(GTPV1U_OBJ_DIR)/libgtpv1u.a -endif - -COMMON_CFLAGS += -DLOG_NO_THREAD -#-DEMIT_ASN_DEBUG - -openair_cn_available := $(shell if [ -d "$(UE_NAS_DIR)" ]; then echo "0" ; else echo "1" ; fi ) -ifeq ($(openair_cn_available), 0) -COMMON_CFLAGS += -DENABLE_NAS_UE_LOGGING -COMMON_CFLAGS += -I$(OPENAIR_DIR)/openair3/NAS/EURECOM-NAS/src/api/network -COMMON_CFLAGS += -I$(OPENAIR_DIR)/openair3/NAS/EURECOM-NAS/src/include -COMMON_CFLAGS += -I$(OPENAIR_DIR)/openair3/NAS/EURECOM-NAS/src/ies -COMMON_CFLAGS += -I$(OPENAIR_DIR)/openair3/NAS/EURECOM-NAS/src/emm/msg -COMMON_CFLAGS += -I$(OPENAIR_DIR)/openair3/NAS/EURECOM-NAS/src/esm/msg -COMMON_CFLAGS += -I$(OPENAIR_DIR)/openair3/NAS/EURECOM-NAS/src/util -endif - -UENAS_CFLAGS = $(COMMON_CFLAGS) -UENAS_CFLAGS += -I$(SECU_DIR) -export UENAS_CFLAGS - -SECU_CFLAGS = $(COMMON_CFLAGS) -SECU_CFLAGS += -I$(OPENAIR_DIR)/openair3/COMMON -SECU_CFLAGS += -I$(OPENAIR_DIR)/openair3/UTILS -SECU_CFLAGS += -I$(SECU_DIR) -export SECU_CFLAGS - -COMMON_MME_CFLAGS = -I$(SECU_DIR) -COMMON_MME_CFLAGS += -I$(SCTP_DIR) -COMMON_MME_CFLAGS += -I$(X2AP_DIR) -COMMON_MME_CFLAGS += -I$(S1AP_DIR) -COMMON_MME_CFLAGS += -I$(UDP_DIR) -COMMON_MME_CFLAGS += -I$(GTPV1U_DIR) - -S1AP_CFLAGS = $(COMMON_CFLAGS) $(COMMON_MME_CFLAGS) -S1AP_CFLAGS += -DENB_MODE -S1AP_CFLAGS += -I$(TOP_DIR) -S1AP_CFLAGS += $(UTIL_incl) -export S1AP_CFLAGS - -X2AP_CFLAGS = $(COMMON_CFLAGS) -X2AP_CFLAGS += -DENB_MODE -X2AP_CFLAGS += -I$(TOP_DIR) -X2AP_CFLAGS += $(UTIL_incl) -export X2AP_CFLAGS - -UDP_CFLAGS = $(COMMON_CFLAGS) $(COMMON_MME_CFLAGS) -UDP_CFLAGS += -DENB_MODE -UDP_CFLAGS += -I$(TOP_DIR) -UDP_CFLAGS += $(UTIL_incl) -UDP_CFLAGS += -I$(OPENAIR_DIR)/openair2/ENB_APP -export UDP_CFLAGS - -GTPV1U_CFLAGS = $(COMMON_CFLAGS) $(COMMON_MME_CFLAGS) -GTPV1U_CFLAGS += -DENB_MODE -GTPV1U_CFLAGS += -I$(TOP_DIR) -GTPV1U_CFLAGS += -I$(GTPV1U_DIR)/nw-gtpv1u/include -GTPV1U_CFLAGS += -I$(GTPV1U_DIR)/nw-gtpv1u/shared -GTPV1U_CFLAGS += -I$(OPENAIR_DIR)/openair2/ENB_APP -GTPV1U_CFLAGS += $(UTIL_incl) -I$(OPENAIR3_DIR)/UTILS -export GTPV1U_CFLAGS - -GTPV1U_ENB_CFLAGS = $(COMMON_CFLAGS) -GTPV1U_ENB_CFLAGS += $(OPENAIR_DIR)/openair2/COMMON -GTPV1U_ENB_CFLAGS += -I$(X2AP_DIR) -GTPV1U_ENB_CFLAGS += -I$(S1AP_DIR) -GTPV1U_ENB_CFLAGS += -I$(UDP_DIR) -GTPV1U_ENB_CFLAGS += -I$(GTPV1U_DIR) -GTPV1U_ENB_CFLAGS += -DENB_MODE -GTPV1U_ENB_CFLAGS += -I$(TOP_DIR) -GTPV1U_ENB_CFLAGS += -I$(GTPV1U_DIR)/nw-gtpv1u/include -GTPV1U_ENB_CFLAGS += -I$(GTPV1U_DIR)/nw-gtpv1u/shared -GTPV1U_ENB_CFLAGS += -I$(OPENAIR_DIR)/openair2/ENB_APP -GTPV1U_ENB_CFLAGS += $(UTIL_incl) -I$(OPENAIR3_DIR)/UTILS -export GTPV1U_ENB_CFLAGS - - -$(UE_NAS_OBJ_DIR)/libuenas.a: force_look - @$(MAKE) -C $(UE_NAS_DIR) -f Makefile.UE $(UE_NAS_OBJ_DIR)/libuenas.a OUTDIR=$(UE_NAS_OBJ_DIR) -$(SECU_OBJ_DIR)/libsecu.a: force_look - @$(MAKE) -C $(SECU_DIR) -f Makefile.eNB $(SECU_OBJ_DIR)/libsecu.a OUTDIR=$(SECU_OBJ_DIR) -$(X2AP_OBJ_DIR)/libx2ap.a: force_look - @$(MAKE) -C $(X2AP_DIR) -f Makefile.inc $(X2AP_OBJ_DIR)/libx2ap.a OUTDIR=$(X2AP_OBJ_DIR) -$(S1AP_OBJ_DIR)/libs1ap.a: force_look - @$(MAKE) -C $(S1AP_DIR) -f Makefile.eNB $(S1AP_OBJ_DIR)/libs1ap.a OUTDIR=$(S1AP_OBJ_DIR) -$(SCTP_OBJ_DIR)/libsctp.a: force_look - @$(MAKE) -C $(SCTP_DIR) -f Makefile.eNB $(SCTP_OBJ_DIR)/libsctp.a OUTDIR=$(SCTP_OBJ_DIR) -$(UDP_OBJ_DIR)/libudp.a: force_look - @$(MAKE) -C $(UDP_DIR) -f Makefile.eNB $(UDP_OBJ_DIR)/libudp.a OUTDIR=$(UDP_OBJ_DIR) -$(GTPV1U_OBJ_DIR)/libgtpv1u.a: force_look - @$(MAKE) -C $(GTPV1U_DIR) -f Makefile.eNB $(GTPV1U_OBJ_DIR)/libgtpv1u.a OUTDIR=$(GTPV1U_OBJ_DIR) - -OBJ = $(NAS_UE_OBJS) $(SECU_OBJS) -endif - -export COMMON_CFLAGS - -ifeq ($(ENABLE_ITTI),1) -CFLAGS += $(COMMON_CFLAGS) $(COMMON_MME_CFLAGS) $(TARGETS_COMMON_incl) -OBJ += $(TARGETS_COMMON_OBJS) - -gccxml_available = $(shell if [ `gccxml --version | grep GCC-XML -c` = "0" ]; then echo "0" ; else echo "1" ; fi ) -ifeq ($(gccxml_available), 0) -$(error gccxml is missing, please install) -endif -CFLAGS += -I$(OPENAIR2_DIR)/COMMON -DENABLE_ITTI $(UTILS_incl) -endif - -$(ITTI_MESSAGES_XML): $(ITTI_MESSAGES_FILE) - @echo "Generating messages.xml ..." - @gccxml $(COMMON_CFLAGS) $< -fxml=$@ -I$(ITTI_DIR) - @$(CC) -MM $(COMMON_CFLAGS) $< > $(basename $@).d - @mv -f $(basename $@).d $(basename $@).d.tmp - @sed -e 's|.*:|$@:|' < $(basename $@).d.tmp > $(basename $@).d - @sed -e 's/.*://' -e 's/\\$$//' < $(basename $@).d.tmp | fmt -1 | \ - sed -e 's/^ *//' -e 's/$$/:/' >> $(basename $@).d - @rm -f $(basename $@).d.tmp - -$(ITTI_MESSAGES_H): $(ITTI_MESSAGES_XML) - @echo "Generating messages_xml.h ..." - @sed -e 's/[ ]*//' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ - -force_look: - @true - -common-clean: - @$(RM_F_V) $(ITTI_MESSAGES_H) $(ITTI_MESSAGES_XML) $(ITTI_MESSAGES_XML:.xml=.d) - @$(MAKE) -C $(LFDS_DIR) -f makefile.linux clean OUTDIR=$(LFDS_OBJ_DIR) - @if [ -d $(UE_NAS_OBJ_DIR) ]; then $(MAKE) -C $(UE_NAS_DIR) -f Makefile.UE clean OUTDIR=$(UE_NAS_OBJ_DIR); fi - @if [ -d $(SECU_OBJ_DIR) ]; then $(MAKE) -C $(SECU_DIR) -f Makefile.eNB clean OUTDIR=$(SECU_OBJ_DIR); fi - @if [ -d $(X2AP_OBJ_DIR) ]; then $(MAKE) -C $(X2AP_DIR) -f Makefile.inc clean OUTDIR=$(X2AP_OBJ_DIR); fi - @if [ -d $(S1AP_OBJ_DIR) ]; then $(MAKE) -C $(S1AP_DIR) -f Makefile.eNB clean OUTDIR=$(S1AP_OBJ_DIR); fi - @if [ -d $(SCTP_OBJ_DIR) ]; then $(MAKE) -C $(SCTP_DIR) -f Makefile.eNB clean OUTDIR=$(SCTP_OBJ_DIR); fi - @if [ -d $(UDP_OBJ_DIR) ]; then $(MAKE) -C $(UDP_DIR) -f Makefile.eNB clean OUTDIR=$(UDP_OBJ_DIR); fi - @if [ -d $(GTPV1U_OBJ_DIR) ]; then $(MAKE) -C $(GTPV1U_DIR) -f Makefile.eNB clean OUTDIR=$(GTPV1U_OBJ_DIR); fi - -common-cleanall: - @if [ -d $(UE_NAS_OBJ_DIR) ]; then $(MAKE) -C $(UE_NAS_DIR) -f Makefile.UE cleanall OUTDIR=$(UE_NAS_OBJ_DIR); fi - @if [ -d $(SECU_OBJ_DIR) ]; then $(MAKE) -C $(SECU_DIR) -f Makefile.eNB cleanall OUTDIR=$(SECU_OBJ_DIR); fi - @if [ -d $(X2AP_OBJ_DIR) ]; then $(MAKE) -C $(X2AP_DIR) -f Makefile.inc cleanall OUTDIR=$(X2AP_OBJ_DIR); fi - @if [ -d $(S1AP_OBJ_DIR) ]; then $(MAKE) -C $(S1AP_DIR) -f Makefile.eNB cleanall OUTDIR=$(S1AP_OBJ_DIR); fi - @if [ -d $(SCTP_OBJ_DIR) ]; then $(MAKE) -C $(SCTP_DIR) -f Makefile.eNB cleanall OUTDIR=$(SCTP_OBJ_DIR); fi - @if [ -d $(UDP_OBJ_DIR) ]; then $(MAKE) -C $(UDP_DIR) -f Makefile.eNB cleanall OUTDIR=$(UDP_OBJ_DIR); fi - @if [ -d $(GTPV1U_OBJ_DIR) ]; then $(MAKE) -C $(GTPV1U_DIR) -f Makefile.eNB cleanall OUTDIR=$(GTPV1U_OBJ_DIR); fi - diff --git a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.calisson.conf b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.calisson.conf index d619ab2958..e1360c1f45 100644 --- a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.calisson.conf +++ b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.calisson.conf @@ -43,6 +43,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.memphis.conf b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.memphis.conf index 558676e99b..84c669571c 100644 --- a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.memphis.conf +++ b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.memphis.conf @@ -55,6 +55,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.nord.conf b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.nord.conf index 9a4a863419..bc41de1874 100644 --- a/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.nord.conf +++ b/targets/PROJECTS/CENTOS-LTE-EPC-INTEGRATION/CONF/enb.centos.nord.conf @@ -42,6 +42,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf new file mode 100644 index 0000000000..aab3876d96 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf @@ -0,0 +1,285 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2655000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 90; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -10; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 640000; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "yes"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.196"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.18.196"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.1"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 150; + } +); + +RUs = ( + { + //local_if_name = "enp129s0f0"; + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 35 -n 2 -b 0000:81:00.3 --proc-type auto --file-prefix ggg -- -p 0x1"; + #sdr_addrs = "softmodem -l 8 -n 2 -- -p 0x2"; + #remote_address = "127.0.0.2"; + #local_address = "127.0.0.1"; + #local_portc = 50000; + #remote_portc = 50000; + #local_portd = 50001; + #remote_portd = 50001; + local_rf = "no" + tr_preference = "raw_if4p5" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + eNB_instances = [0]; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + #parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf new file mode 100644 index 0000000000..c6a4a90a14 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf @@ -0,0 +1,280 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + #plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + plmn_list = ({mcc = 208; mnc = 99; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is is the central frequency of SSB + absoluteFrequencySSB = 640000; //641272 + dl_frequencyBand = 78; + # the carrier frequency is assumed to be in the middle of the carrier, i.e. dl_absoluteFrequencyPointA_kHz + dl_carrierBandwidth*12*SCS_kHz/2 + dl_absoluteFrequencyPointA = 638728; //640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 4; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 74; + zeroCorrelationZoneConfig = 13; + #preambleReceivedTargetPower = -118; + #preambleReceivedTargetPower = -104; + preambleReceivedTargetPower = -108; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 2; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 1; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + #msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + #p0_NominalWithGrant =-90; + p0_NominalWithGrant =-118; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + #p0_nominal = -90; + p0_nominal = -118; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + #ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -35; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.150"; #"192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "127.0.0.1"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.187/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.187/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "127.0.0.2/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "no" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + //clock_src = "internal"; + clock_src = "external"; + + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 34 -n 3 -b 0000:81:00.2 --proc-type auto --file-prefix hhh -- -p 0x1"; + remote_address = "127.0.0.2"; + local_address = "127.0.0.1"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + tr_preference = "raw_if4p5" + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + //parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.emtc.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.emtc.conf index a761579018..67044f38d9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.emtc.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.emtc.conf @@ -367,6 +367,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.100PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.100PRB.usrpx310.conf index f248f515b8..e044c186b9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.100PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.100PRB.usrpx310.conf @@ -148,6 +148,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.25PRB.iris030.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.25PRB.iris030.conf index dee6c298a7..5a547622ab 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.25PRB.iris030.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.25PRB.iris030.conf @@ -184,6 +184,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpx310.conf index 231581574a..27826e5ce2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm1.usrpx310.conf @@ -148,6 +148,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band42.tm1.25PRB.iris030.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band42.tm1.25PRB.iris030.conf index 54c12835ef..5df0f107ea 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band42.tm1.25PRB.iris030.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band42.tm1.25PRB.iris030.conf @@ -184,6 +184,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.master.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.master.conf index c0decd362f..cb50cccf2b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.master.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.master.conf @@ -183,6 +183,8 @@ eNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf index feab0d6926..245e4ecf94 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf @@ -151,6 +151,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.iris030.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.iris030.conf index 1a0466aad3..86b481f9d8 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.iris030.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.iris030.conf @@ -184,6 +184,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.replay.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.replay.conf index 753c2d8b5c..1eb5da6a18 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.replay.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpb210.replay.conf @@ -185,6 +185,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf index 20646681d2..a929c439be 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf @@ -185,6 +185,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index d6f44e2b96..43288ba324 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -185,6 +185,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf index 8971633ce0..92f2d4e6f1 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210_ue_expansion.conf @@ -152,6 +152,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf deleted file mode 100644 index 5fd4b465b3..0000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf +++ /dev/null @@ -1,289 +0,0 @@ -Active_gNBs = ( "gNB-Eurecom-5GNRBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -gNBs = -( - { - ////////// Identification parameters: - gNB_ID = 0xe00; - - cell_type = "CELL_MACRO_GNB"; - - gNB_name = "gNB-Eurecom-5GNRBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - - plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); - - tr_s_preference = "local_mac" - - ////////// Physical parameters: - - component_carriers = ( - { - node_function = "3GPP_gNODEB"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "TDD"; - DL_prefix_type = "NORMAL"; - UL_prefix_type = "NORMAL"; - eutra_band = 78; - downlink_frequency = 3510000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 106; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - MIB_subCarrierSpacingCommon = 30; - MIB_ssb_SubcarrierOffset = 0; - MIB_dmrs_TypeA_Position = 2; - pdcch_ConfigSIB1 = 0; - SIB1_frequencyOffsetSSB = "khz5"; - SIB1_ssb_PeriodicityServingCell = 5; - SIB1_ss_PBCH_BlockPower = -60; - absoluteFrequencySSB = 0; - DL_FreqBandIndicatorNR = 15; - DL_absoluteFrequencyPointA = 15; - DL_offsetToCarrier = 15; - DL_SCS_SubcarrierSpacing = "kHz30"; - DL_SCS_SpecificCarrier_k0 = 0; - DL_carrierBandwidth = 15; - DL_locationAndBandwidth = 15; - DL_BWP_SubcarrierSpacing = "kHz30"; - DL_BWP_prefix_type = "NORMAL"; - UL_FreqBandIndicatorNR = 15; - UL_absoluteFrequencyPointA = 13; - UL_additionalSpectrumEmission = 3; - UL_p_Max = -1; - UL_frequencyShift7p5khz = "TRUE"; - UL_offsetToCarrier = 10; - UL_SCS_SubcarrierSpacing = "kHz30"; - UL_SCS_SpecificCarrier_k0 = 0; - UL_carrierBandwidth = 15; - UL_locationAndBandwidth = 15; - UL_BWP_SubcarrierSpacing = "kHz30"; - UL_BWP_prefix_type = "NORMAL"; - UL_timeAlignmentTimerCommon = "infinity"; - ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; - ServingCellConfigCommon_ssb_periodicityServingCell = 10; - ServingCellConfigCommon_dmrs_TypeA_Position = 2; - NIA_SubcarrierSpacing = "kHz15"; - ServingCellConfigCommon_ss_PBCH_BlockPower = -60; - referenceSubcarrierSpacing = "kHz15"; - dl_UL_TransmissionPeriodicity = "ms0p5"; - nrofDownlinkSlots = 10; - nrofDownlinkSymbols = 10; - nrofUplinkSlots = 10; - nrofUplinkSymbols = 10; - rach_totalNumberOfRA_Preambles = 63; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice = "oneEighth"; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf = 16; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one = 24; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two = 32; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen = 2; - rach_groupBconfigured = "ENABLE"; - rach_ra_Msg3SizeGroupA = 56; - rach_messagePowerOffsetGroupB = "dB0"; - rach_numberOfRA_PreamblesGroupA = 32; - rach_ra_ContentionResolutionTimer = 8; - rsrp_ThresholdSSB = 64; - rsrp_ThresholdSSB_SUL = 64; - prach_RootSequenceIndex_choice = "l839"; - prach_RootSequenceIndex_l839 = 0; - prach_RootSequenceIndex_l139 = 0; - prach_msg1_SubcarrierSpacing = "kHz30"; - restrictedSetConfig = "unrestrictedSet"; - msg3_transformPrecoding = "ENABLE"; - prach_ConfigurationIndex = 10; - prach_msg1_FDM = "one"; - prach_msg1_FrequencyStart = 10; - zeroCorrelationZoneConfig = 10; - preambleReceivedTargetPower = -150; - preambleTransMax = 6; - powerRampingStep = "dB0"; - ra_ResponseWindow = 8; - groupHoppingEnabledTransformPrecoding = "ENABLE"; - msg3_DeltaPreamble = 0; - p0_NominalWithGrant = 0; - PUSCH_TimeDomainResourceAllocation_k2 = 0; - PUSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PUSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - pucch_ResourceCommon = 0; - pucch_GroupHopping = "neither"; - hoppingId = 0; - p0_nominal = -30; - PDSCH_TimeDomainResourceAllocation_k0 = 2; - PDSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PDSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - rateMatchPatternId = 0; - RateMatchPattern_patternType = "bitmaps"; - symbolsInResourceBlock = "oneSlot"; - periodicityAndPattern = 2; - RateMatchPattern_controlResourceSet = 5; - RateMatchPattern_subcarrierSpacing = "kHz30"; - RateMatchPattern_mode = "dynamic"; - controlResourceSetZero = 0; - searchSpaceZero = 0; - searchSpaceSIB1 = 10; - searchSpaceOtherSystemInformation = 10; - pagingSearchSpace = 10; - ra_SearchSpace = 10; - PDCCH_common_controlResourceSetId = 5; - PDCCH_common_ControlResourceSet_duration = 2; - PDCCH_cce_REG_MappingType = "nonInterleaved"; - PDCCH_reg_BundleSize = 3; - PDCCH_interleaverSize = 3; - PDCCH_shiftIndex = 10; - PDCCH_precoderGranularity = "sameAsREG-bundle"; - PDCCH_TCI_StateId = 32; - tci_PresentInDCI = "ENABLE"; - PDCCH_DMRS_ScramblingID = 0; - SearchSpaceId = 10; - commonSearchSpaces_controlResourceSetId = 5; - SearchSpace_monitoringSlotPeriodicityAndOffset_choice = "sl1"; - SearchSpace_monitoringSlotPeriodicityAndOffset_value = 0; - SearchSpace_duration = 2; - SearchSpace_nrofCandidates_aggregationLevel1 = 0; - SearchSpace_nrofCandidates_aggregationLevel2 = 0; - SearchSpace_nrofCandidates_aggregationLevel4 = 0; - SearchSpace_nrofCandidates_aggregationLevel8 = 0; - SearchSpace_nrofCandidates_aggregationLevel16 = 0; - SearchSpace_searchSpaceType = "common"; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16 = 1; - Common_dci_Format2_3_monitoringPeriodicity = 1; - Common_dci_Format2_3_nrofPDCCH_Candidates = 1; - ue_Specific__dci_Formats = "formats0-0-And-1-0"; - RateMatchPatternLTE_CRS_carrierFreqDL = 6; - RateMatchPatternLTE_CRS_carrierBandwidthDL = 6; - RateMatchPatternLTE_CRS_nrofCRS_Ports = 1; - RateMatchPatternLTE_CRS_v_Shift = 0; - RateMatchPatternLTE_CRS_radioframeAllocationPeriod = 1; - RateMatchPatternLTE_CRS_radioframeAllocationOffset = 0; - RateMatchPatternLTE_CRS_subframeAllocation_choice = "oneFrame"; - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.26"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - NETWORK_INTERFACES : - { - - GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; - GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - } -); - -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - } -); - -L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 114; - eNB_instances = [0]; - sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,mgmt_addr=192.168.100.8"; - - } -); - -NETWORK_CONTROLLER : -{ - FLEXRAN_ENABLED = "no"; - FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; - FLEXRAN_PORT = 2210; - FLEXRAN_CACHE = "/mnt/oai_agent_cache"; - FLEXRAN_AWAIT_RECONF = "no"; -}; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf new file mode 100644 index 0000000000..fd9399f89e --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf @@ -0,0 +1,282 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 92; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is pointA + 23 PRBs@120kHz SCS (same as initial BWP) + absoluteFrequencySSB = 2071241; + dl_frequencyBand = 257; + # this is 27.900 GHz + dl_absoluteFrequencyPointA = 2070833; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 32; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=32 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 8525; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 261; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 3; + ul_carrierBandwidth = 32; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 8525; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 3; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 52; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 7; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 7; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 3; + ssb_PositionsInBurst_Bitmap = 0x0001000100010001L; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 3; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 3; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 3; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; + if_freq = 5124520000L; + clock_src = "external"; + time_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf index d5bc492644..59e71a6225 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -33,10 +34,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is pointA + 23 PRBs@120kHz SCS (same as initial BWP) - absoluteFrequencySSB = 2077907; + absoluteFrequencySSB = 2071241; dl_frequencyBand = 257; # this is 27.900 GHz - dl_absoluteFrequencyPointA = 2077499; + dl_absoluteFrequencyPointA = 2070833; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -53,24 +54,7 @@ gNBs = #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 12; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=2,L=3 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 257; @@ -89,7 +73,7 @@ gNBs = initialULBWPsubcarrierSpacing = 3; #rach-ConfigCommon #rach-ConfigGeneric - prach_ConfigurationIndex = 98; + prach_ConfigurationIndex = 52; #prach_msg1_FDM #0 = one, 1=two, 2=four, 3=eight prach_msg1_FDM = 0; @@ -103,12 +87,12 @@ gNBs = powerRampingStep = 1; #ra_ReponseWindow #1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; + ra_ResponseWindow = 7; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; #oneHalf (0..15) 4,8,12,16,...60,64 - ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 7; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 ra_ContentionResolutionTimer = 7; @@ -119,22 +103,11 @@ gNBs = prach_RootSequenceIndex = 1; # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex # - msg1_SubcarrierSpacing = 1, + msg1_SubcarrierSpacing = 3, # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -148,7 +121,7 @@ gNBs = # ssb_PositionsInBurs_BitmapPR # 1=short, 2=medium, 3=long ssb_PositionsInBurst_PR = 3; - ssb_PositionsInBurst_Bitmap = 0x100000001L; + ssb_PositionsInBurst_Bitmap = 0x0001000100010001L; # ssb_periodicityServingCell # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 @@ -170,13 +143,13 @@ gNBs = # pattern1 # dl_UL_TransmissionPeriodicity # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 - dl_UL_TransmissionPeriodicity = 5; - nrofDownlinkSlots = 10; - nrofDownlinkSymbols = 0; - nrofUplinkSlots = 10; - nrofUplinkSymbols = 0; + dl_UL_TransmissionPeriodicity = 3; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -207,22 +180,27 @@ gNBs = GNB_INTERFACE_NAME_FOR_S1U = "eth0"; GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; } ); MACRLCs = ( { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - } + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } ); L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); @@ -235,10 +213,12 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; - if_freq = 5300000000; + if_freq = 5124520000L; + clock_src = "external"; + time_src = "external"; } ); @@ -251,6 +231,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf index 93a6c7fbc9..3fc81c0d6c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -53,24 +54,7 @@ gNBs = #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 12; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=2,L=3 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 257; @@ -124,17 +108,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -176,7 +149,7 @@ gNBs = nrofUplinkSlots = 10; nrofUplinkSymbols = 0; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -221,8 +194,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); @@ -235,7 +210,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "type=n300"; } @@ -250,6 +225,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf index 72a27cc1e7..a40a93c789 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf @@ -13,7 +13,7 @@ gNBs = gNB_name = "gNB-Eurecom-5GNRBox"; // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 600; + tracking_area_code = 1; plmn_list = ({mcc = 311; mnc = 480; mnc_length = 3;}); @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -45,7 +46,7 @@ gNBs = dl_carrierBandwidth = 32; #initialDownlinkBWP #genericParameters - # this is RBstart=0,L=50 (275*(L-1))+RBstart + # this is RBstart=0,L=32 (275*(L-1))+RBstart initialDLBWPlocationAndBandwidth = 8525; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 @@ -53,24 +54,7 @@ gNBs = #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 12; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=2,L=3 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 261; @@ -89,7 +73,7 @@ gNBs = initialULBWPsubcarrierSpacing = 3; #rach-ConfigCommon #rach-ConfigGeneric - prach_ConfigurationIndex = 98; + prach_ConfigurationIndex = 52; #prach_msg1_FDM #0 = one, 1=two, 2=four, 3=eight prach_msg1_FDM = 0; @@ -103,38 +87,27 @@ gNBs = powerRampingStep = 1; #ra_ReponseWindow #1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; + ra_ResponseWindow = 7; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR -#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; #oneHalf (0..15) 4,8,12,16,...60,64 - ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 7; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 ra_ContentionResolutionTimer = 7; rsrp_ThresholdSSB = 19; #prach-RootSequenceIndex_PR -#0 = 839, 1 = 139 - prach_RootSequenceIndex_PR = 1; +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; prach_RootSequenceIndex = 1; # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex # - msg1_SubcarrierSpacing = 1, + msg1_SubcarrierSpacing = 3, # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -148,7 +121,7 @@ gNBs = # ssb_PositionsInBurs_BitmapPR # 1=short, 2=medium, 3=long ssb_PositionsInBurst_PR = 3; - ssb_PositionsInBurst_Bitmap = 0x100000001L; + ssb_PositionsInBurst_Bitmap = 0x0001000100010001L; # ssb_periodicityServingCell # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 @@ -170,13 +143,13 @@ gNBs = # pattern1 # dl_UL_TransmissionPeriodicity # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 - dl_UL_TransmissionPeriodicity = 5; - nrofDownlinkSlots = 10; - nrofDownlinkSymbols = 0; - nrofUplinkSlots = 10; - nrofUplinkSymbols = 0; + dl_UL_TransmissionPeriodicity = 3; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -192,37 +165,56 @@ gNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.26"; + mme_ip_address = ( { ipv4 = "192.168.18.99"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; } ); + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + NETWORK_INTERFACES : { GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24"; GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 }; } ); MACRLCs = ( { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - } + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } ); L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); @@ -235,10 +227,12 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; if_freq = 5124520000L; + clock_src = "external"; + time_src = "external"; } ); @@ -251,6 +245,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf new file mode 100644 index 0000000000..3860aba935 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf @@ -0,0 +1,274 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 2150 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 433096; + dl_frequencyBand = 66; + # this is 2150 MHz + dl_absoluteFrequencyPointA = 430000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 66; + ul_absoluteFrequencyPointA = 350000; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf new file mode 100644 index 0000000000..7c527e07c8 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf @@ -0,0 +1,274 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 2150 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 433096; + dl_frequencyBand = 66; + # this is 2150 MHz + dl_absoluteFrequencyPointA = 430000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 66; + ul_absoluteFrequencyPointA = 350000; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; + clock_src = "external"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf index ff8e261783..a171f2aae0 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 31; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -46,31 +47,14 @@ gNBs = #initialDownlinkBWP #genericParameters # this is RBstart=84,L=13 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 6366; + initialDLBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 0; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=2,L=3 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -83,7 +67,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 6366; + initialULBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -124,17 +108,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -176,7 +149,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -203,6 +176,8 @@ gNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ target_enb_x2_ip_address = ( { ipv4 = "192.168.12.196"; ipv6 = "192:168:30::17"; @@ -263,6 +238,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf index 81796ada2c..4f8c785baa 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -46,36 +47,13 @@ gNBs = #initialDownlinkBWP #genericParameters # this is RBstart=0,L=50 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 6366; + initialDLBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 12; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=4 - initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon #frequencyInfoUL @@ -89,7 +67,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 6366; + initialULBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -130,22 +108,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - - initialULBWPk2_2 = 7; - initialULBWPmappingType_2 = 1; - # this is SS=10 L=4 - initialULBWPstartSymbolAndLength_2 = 52; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -214,6 +176,8 @@ gNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ target_enb_x2_ip_address = ( { ipv4 = "192.168.12.188"; ipv6 = "192:168:30::17"; @@ -246,8 +210,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); @@ -276,6 +242,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf index 771f5d1839..012f46401e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -53,24 +54,7 @@ gNBs = #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 12; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=2,L=3 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -124,17 +108,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -203,6 +176,8 @@ gNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ target_enb_x2_ip_address = ( { ipv4 = "192.168.12.188"; ipv6 = "192:168:30::17"; @@ -265,6 +240,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf new file mode 100644 index 0000000000..b6b9252560 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf @@ -0,0 +1,319 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + + # downlinkConfigCommon + # frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; + #prach_msg1_FDM + #0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; + #preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; + #powerRampingStep + # 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; + #ra_ReponseWindow + #1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; + #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR + #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; + #oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; + #ra_ContentionResolutionTimer + #(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; + #prach-RootSequenceIndex_PR + #1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + # restrictedSetConfig + # 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + + # pucch-ConfigCommon setup : + # pucchGroupHopping + # 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + # ssb_PositionsInBurs_BitmapPR + # 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + + # ssb_periodicityServingCell + # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + + # dmrs_TypeA_position + # 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + # Dedicated Serving Cell Configuration + servingCellConfigDedicated = ( + { + # DL PTRS related parameters. + # 3GPP TS 38.331 PTRS-DownlinkConfig + + # frequencyDensity value range: 1-276 + dl_ptrsFreqDensity0_0 = 25; + dl_ptrsFreqDensity1_0 = 75; + + # timeDensity value range: 0-29 + dl_ptrsTimeDensity0_0 = 2; + dl_ptrsTimeDensity1_0 = 4; + dl_ptrsTimeDensity2_0 = 10; + + # epre_Ratio + # 0 = "00", 1 = "01" in TS 38.214, table 4.1-2 + dl_ptrsEpreRatio_0 = 0; + + # resourceElementOffset + # 0 = offset01 1 = offset02, 2 = offset02 + # 3GPP TS 38.331 PTRS-DownlinkConfig; TS 38.211 sec. 7.4.1.2.2 + dl_ptrsReOffset_0 = 0; + + # UL PTRS related parameters. + # 3GPP TS 38.331 PTRS-UplinkConfig + + # frequencyDensity value range: 1-276 + ul_ptrsFreqDensity0_0 = 25; + ul_ptrsFreqDensity1_0 = 75; + + # timeDensity value range: 0-29 + ul_ptrsTimeDensity0_0 = 2; + ul_ptrsTimeDensity1_0 = 4; + ul_ptrsTimeDensity2_0 = 10; + + # resourceElementOffset + # 0 = offset01 1 = offset02, 2 = offset02 + # TS 38.331 PTRS-UplinkConfig; TS 38.211 sec. 6.4.1.2.2.1 + ul_ptrsReOffset_0 = 0; + + # maxNrofPorts + # 0 = n1, 1 = n2 + ul_ptrsMaxPorts_0 = 0; + + # ptrs-Power + # 0 = p00, 1 = p01, 2 = p10, 3 = p11 + #ul_ptrsPower_0 = 0; + } + ); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; +}; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.adrv9371zc706.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.adrv9371zc706.conf deleted file mode 100644 index 5610694d7d..0000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.adrv9371zc706.conf +++ /dev/null @@ -1,288 +0,0 @@ -Active_gNBs = ( "gNB-Eurecom-5GNRBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -gNBs = -( - { - ////////// Identification parameters: - gNB_ID = 0xe00; - - cell_type = "CELL_MACRO_GNB"; - - gNB_name = "gNB-Eurecom-5GNRBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - - plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); - - tr_s_preference = "local_mac" - - ////////// Physical parameters: - - component_carriers = ( - { - node_function = "3GPP_gNODEB"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "TDD"; - DL_prefix_type = "NORMAL"; - UL_prefix_type = "NORMAL"; - eutra_band = 78; - downlink_frequency = 3510000000L; - uplink_frequency_offset = 0; - Nid_cell = 0; - N_RB_DL = 106; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - MIB_subCarrierSpacingCommon = 30; - MIB_ssb_SubcarrierOffset = 0; - MIB_dmrs_TypeA_Position = 2; - pdcch_ConfigSIB1 = 0; - SIB1_frequencyOffsetSSB = "khz5"; - SIB1_ssb_PeriodicityServingCell = 5; - SIB1_ss_PBCH_BlockPower = -60; - absoluteFrequencySSB = 0; - DL_FreqBandIndicatorNR = 15; - DL_absoluteFrequencyPointA = 15; - DL_offsetToCarrier = 15; - DL_SCS_SubcarrierSpacing = "kHz30"; - DL_SCS_SpecificCarrier_k0 = 0; - DL_carrierBandwidth = 15; - DL_locationAndBandwidth = 15; - DL_BWP_SubcarrierSpacing = "kHz30"; - DL_BWP_prefix_type = "NORMAL"; - UL_FreqBandIndicatorNR = 15; - UL_absoluteFrequencyPointA = 13; - UL_additionalSpectrumEmission = 3; - UL_p_Max = -1; - UL_frequencyShift7p5khz = "TRUE"; - UL_offsetToCarrier = 10; - UL_SCS_SubcarrierSpacing = "kHz30"; - UL_SCS_SpecificCarrier_k0 = 0; - UL_carrierBandwidth = 15; - UL_locationAndBandwidth = 15; - UL_BWP_SubcarrierSpacing = "kHz30"; - UL_BWP_prefix_type = "NORMAL"; - UL_timeAlignmentTimerCommon = "infinity"; - ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; - ServingCellConfigCommon_ssb_periodicityServingCell = 10; - ServingCellConfigCommon_dmrs_TypeA_Position = 2; - NIA_SubcarrierSpacing = "kHz15"; - ServingCellConfigCommon_ss_PBCH_BlockPower = -60; - referenceSubcarrierSpacing = "kHz15"; - dl_UL_TransmissionPeriodicity = "ms0p5"; - nrofDownlinkSlots = 10; - nrofDownlinkSymbols = 10; - nrofUplinkSlots = 10; - nrofUplinkSymbols = 10; - rach_totalNumberOfRA_Preambles = 63; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice = "oneEighth"; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf = 16; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one = 24; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two = 32; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen = 2; - rach_groupBconfigured = "ENABLE"; - rach_ra_Msg3SizeGroupA = 56; - rach_messagePowerOffsetGroupB = "dB0"; - rach_numberOfRA_PreamblesGroupA = 32; - rach_ra_ContentionResolutionTimer = 8; - rsrp_ThresholdSSB = 64; - rsrp_ThresholdSSB_SUL = 64; - prach_RootSequenceIndex_choice = "l839"; - prach_RootSequenceIndex_l839 = 0; - prach_RootSequenceIndex_l139 = 0; - prach_msg1_SubcarrierSpacing = "kHz30"; - restrictedSetConfig = "unrestrictedSet"; - msg3_transformPrecoding = "ENABLE"; - prach_ConfigurationIndex = 10; - prach_msg1_FDM = "one"; - prach_msg1_FrequencyStart = 10; - zeroCorrelationZoneConfig = 10; - preambleReceivedTargetPower = -150; - preambleTransMax = 6; - powerRampingStep = "dB0"; - ra_ResponseWindow = 8; - groupHoppingEnabledTransformPrecoding = "ENABLE"; - msg3_DeltaPreamble = 0; - p0_NominalWithGrant = 0; - PUSCH_TimeDomainResourceAllocation_k2 = 0; - PUSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PUSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - pucch_ResourceCommon = 0; - pucch_GroupHopping = "neither"; - hoppingId = 0; - p0_nominal = -30; - PDSCH_TimeDomainResourceAllocation_k0 = 2; - PDSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PDSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - rateMatchPatternId = 0; - RateMatchPattern_patternType = "bitmaps"; - symbolsInResourceBlock = "oneSlot"; - periodicityAndPattern = 2; - RateMatchPattern_controlResourceSet = 5; - RateMatchPattern_subcarrierSpacing = "kHz30"; - RateMatchPattern_mode = "dynamic"; - controlResourceSetZero = 0; - searchSpaceZero = 0; - searchSpaceSIB1 = 10; - searchSpaceOtherSystemInformation = 10; - pagingSearchSpace = 10; - ra_SearchSpace = 10; - PDCCH_common_controlResourceSetId = 5; - PDCCH_common_ControlResourceSet_duration = 2; - PDCCH_cce_REG_MappingType = "nonInterleaved"; - PDCCH_reg_BundleSize = 3; - PDCCH_interleaverSize = 3; - PDCCH_shiftIndex = 10; - PDCCH_precoderGranularity = "sameAsREG-bundle"; - PDCCH_TCI_StateId = 32; - tci_PresentInDCI = "ENABLE"; - PDCCH_DMRS_ScramblingID = 0; - SearchSpaceId = 10; - commonSearchSpaces_controlResourceSetId = 5; - SearchSpace_monitoringSlotPeriodicityAndOffset_choice = "sl1"; - SearchSpace_monitoringSlotPeriodicityAndOffset_value = 0; - SearchSpace_duration = 2; - SearchSpace_nrofCandidates_aggregationLevel1 = 0; - SearchSpace_nrofCandidates_aggregationLevel2 = 0; - SearchSpace_nrofCandidates_aggregationLevel4 = 0; - SearchSpace_nrofCandidates_aggregationLevel8 = 0; - SearchSpace_nrofCandidates_aggregationLevel16 = 0; - SearchSpace_searchSpaceType = "common"; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16 = 1; - Common_dci_Format2_3_monitoringPeriodicity = 1; - Common_dci_Format2_3_nrofPDCCH_Candidates = 1; - ue_Specific__dci_Formats = "formats0-0-And-1-0"; - RateMatchPatternLTE_CRS_carrierFreqDL = 6; - RateMatchPatternLTE_CRS_carrierBandwidthDL = 6; - RateMatchPatternLTE_CRS_nrofCRS_Ports = 1; - RateMatchPatternLTE_CRS_v_Shift = 0; - RateMatchPatternLTE_CRS_radioframeAllocationPeriod = 1; - RateMatchPatternLTE_CRS_radioframeAllocationOffset = 0; - RateMatchPatternLTE_CRS_subframeAllocation_choice = "oneFrame"; - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.26"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - NETWORK_INTERFACES : - { - - GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; - GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - } -); - -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - } -); - -L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 114; - eNB_instances = [0]; - sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,mgmt_addr=192.168.100.8"; - - } -); - -NETWORK_CONTROLLER : -{ - FLEXRAN_ENABLED = "no"; - FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; - FLEXRAN_PORT = 2210; - FLEXRAN_CACHE = "/mnt/oai_agent_cache"; - FLEXRAN_AWAIT_RECONF = "no"; -}; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf index fdc4894da6..0817d7373e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf @@ -21,183 +21,139 @@ gNBs = ////////// Physical parameters: - component_carriers = ( - { - node_function = "3GPP_gNODEB"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "TDD"; - DL_prefix_type = "NORMAL"; - UL_prefix_type = "NORMAL"; - eutra_band = 78; - downlink_frequency = 3510000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 106; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - MIB_subCarrierSpacingCommon = 30; - MIB_ssb_SubcarrierOffset = 0; - MIB_dmrs_TypeA_Position = 2; - pdcch_ConfigSIB1 = 0; - SIB1_frequencyOffsetSSB = "khz5"; - SIB1_ssb_PeriodicityServingCell = 5; - SIB1_ss_PBCH_BlockPower = -60; - absoluteFrequencySSB = 0; - DL_FreqBandIndicatorNR = 15; - DL_absoluteFrequencyPointA = 15; - DL_offsetToCarrier = 15; - DL_SCS_SubcarrierSpacing = "kHz30"; - DL_SCS_SpecificCarrier_k0 = 0; - DL_carrierBandwidth = 15; - DL_locationAndBandwidth = 15; - DL_BWP_SubcarrierSpacing = "kHz30"; - DL_BWP_prefix_type = "NORMAL"; - UL_FreqBandIndicatorNR = 15; - UL_absoluteFrequencyPointA = 13; - UL_additionalSpectrumEmission = 3; - UL_p_Max = -1; - UL_frequencyShift7p5khz = "TRUE"; - UL_offsetToCarrier = 10; - UL_SCS_SubcarrierSpacing = "kHz30"; - UL_SCS_SpecificCarrier_k0 = 0; - UL_carrierBandwidth = 15; - UL_locationAndBandwidth = 15; - UL_BWP_SubcarrierSpacing = "kHz30"; - UL_BWP_prefix_type = "NORMAL"; - UL_timeAlignmentTimerCommon = "infinity"; - ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; - ServingCellConfigCommon_ssb_periodicityServingCell = 10; - ServingCellConfigCommon_dmrs_TypeA_Position = 2; - NIA_SubcarrierSpacing = "kHz15"; - ServingCellConfigCommon_ss_PBCH_BlockPower = -60; - referenceSubcarrierSpacing = "kHz15"; - dl_UL_TransmissionPeriodicity = "ms0p5"; - nrofDownlinkSlots = 10; - nrofDownlinkSymbols = 10; - nrofUplinkSlots = 10; - nrofUplinkSymbols = 10; - rach_totalNumberOfRA_Preambles = 63; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice = "oneEighth"; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf = 16; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one = 24; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two = 32; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen = 2; - rach_groupBconfigured = "ENABLE"; - rach_ra_Msg3SizeGroupA = 56; - rach_messagePowerOffsetGroupB = "dB0"; - rach_numberOfRA_PreamblesGroupA = 32; - rach_ra_ContentionResolutionTimer = 8; - rsrp_ThresholdSSB = 64; - rsrp_ThresholdSSB_SUL = 64; - prach_RootSequenceIndex_choice = "l839"; - prach_RootSequenceIndex_l839 = 0; - prach_RootSequenceIndex_l139 = 0; - prach_msg1_SubcarrierSpacing = "kHz30"; - restrictedSetConfig = "unrestrictedSet"; - msg3_transformPrecoding = "ENABLE"; - prach_ConfigurationIndex = 10; - prach_msg1_FDM = "one"; - prach_msg1_FrequencyStart = 10; - zeroCorrelationZoneConfig = 10; - preambleReceivedTargetPower = -150; - preambleTransMax = 6; - powerRampingStep = "dB0"; - ra_ResponseWindow = 8; - groupHoppingEnabledTransformPrecoding = "ENABLE"; - msg3_DeltaPreamble = 0; - p0_NominalWithGrant = 0; - PUSCH_TimeDomainResourceAllocation_k2 = 0; - PUSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PUSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - pucch_ResourceCommon = 0; - pucch_GroupHopping = "neither"; - hoppingId = 0; - p0_nominal = -30; - PDSCH_TimeDomainResourceAllocation_k0 = 2; - PDSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PDSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - rateMatchPatternId = 0; - RateMatchPattern_patternType = "bitmaps"; - symbolsInResourceBlock = "oneSlot"; - periodicityAndPattern = 2; - RateMatchPattern_controlResourceSet = 5; - RateMatchPattern_subcarrierSpacing = "kHz30"; - RateMatchPattern_mode = "dynamic"; - controlResourceSetZero = 0; - searchSpaceZero = 0; - searchSpaceSIB1 = 10; - searchSpaceOtherSystemInformation = 10; - pagingSearchSpace = 10; - ra_SearchSpace = 10; - PDCCH_common_controlResourceSetId = 5; - PDCCH_common_ControlResourceSet_duration = 2; - PDCCH_cce_REG_MappingType = "nonInterleaved"; - PDCCH_reg_BundleSize = 3; - PDCCH_interleaverSize = 3; - PDCCH_shiftIndex = 10; - PDCCH_precoderGranularity = "sameAsREG-bundle"; - PDCCH_TCI_StateId = 32; - tci_PresentInDCI = "ENABLE"; - PDCCH_DMRS_ScramblingID = 0; - SearchSpaceId = 10; - commonSearchSpaces_controlResourceSetId = 5; - SearchSpace_monitoringSlotPeriodicityAndOffset_choice = "sl1"; - SearchSpace_monitoringSlotPeriodicityAndOffset_value = 0; - SearchSpace_duration = 2; - SearchSpace_nrofCandidates_aggregationLevel1 = 0; - SearchSpace_nrofCandidates_aggregationLevel2 = 0; - SearchSpace_nrofCandidates_aggregationLevel4 = 0; - SearchSpace_nrofCandidates_aggregationLevel8 = 0; - SearchSpace_nrofCandidates_aggregationLevel16 = 0; - SearchSpace_searchSpaceType = "common"; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16 = 1; - Common_dci_Format2_3_monitoringPeriodicity = 1; - Common_dci_Format2_3_nrofPDCCH_Candidates = 1; - ue_Specific__dci_Formats = "formats0-0-And-1-0"; - RateMatchPatternLTE_CRS_carrierFreqDL = 6; - RateMatchPatternLTE_CRS_carrierBandwidthDL = 6; - RateMatchPatternLTE_CRS_nrofCRS_Ports = 1; - RateMatchPatternLTE_CRS_v_Shift = 0; - RateMatchPatternLTE_CRS_radioframeAllocationPeriod = 1; - RateMatchPatternLTE_CRS_radioframeAllocationOffset = 0; - RateMatchPatternLTE_CRS_subframeAllocation_choice = "oneFrame"; - } - ); - - - srb1_parameters : + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; + #spCellConfigCommon - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; + physCellId = 0; - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#0 = 839, 1 = 139 + prach_RootSequenceIndex_PR = 1; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } # ------- SCTP definitions SCTP : @@ -238,14 +194,16 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); RUs = ( { - local_rf = "yes" + local_rf = "yes" nb_tx = 1 nb_rx = 1 att_tx = 0 @@ -254,8 +212,16 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - sdr_addrs = "type=b200"; - + ## beamforming 1x2 matrix: 1 layer x 2 antennas + #bf_weights = [0x00007fff, 0x00007fff]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=b200"; + #clock_src = "external"; } ); @@ -264,18 +230,25 @@ THREAD_STRUCT = ( #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_SINGLE_THREAD"; #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" - worker_config = "WORKER_DISABLE"; + worker_config = "WORKER_ENABLE"; } ); -NETWORK_CONTROLLER : -{ - FLEXRAN_ENABLED = "no"; - FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; - FLEXRAN_PORT = 2210; - FLEXRAN_CACHE = "/mnt/oai_agent_cache"; - FLEXRAN_AWAIT_RECONF = "no"; +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; }; log_config : diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index dbcbb2ed4f..fd4c23cfdb 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -23,7 +23,8 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; - + pusch_AntennaPorts = 1; + servingCellConfigCommon = ( { #spCellConfigCommon @@ -32,7 +33,7 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP), points to Subcarrier 0 of RB#10 of SSB block absoluteFrequencySSB = 641032; dl_frequencyBand = 78; # this is 3600 MHz @@ -45,37 +46,14 @@ gNBs = dl_carrierBandwidth = 106; #initialDownlinkBWP #genericParameters - # this is RBstart=0,L=50 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 6366; + # this is RBstart=33 (Start RB of SSB block),L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6358; #6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPcontrolResourceSetZero = 0; #12; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=4 - initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon #frequencyInfoUL @@ -89,7 +67,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 6366; + initialULBWPlocationAndBandwidth = 6358;#6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -130,23 +108,6 @@ gNBs = # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - - initialULBWPk2_2 = 7; - initialULBWPmappingType_2 = 1; - # this is SS=10 L=4 - initialULBWPstartSymbolAndLength_2 = 52; - - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -159,7 +120,7 @@ gNBs = # ssb_PositionsInBurs_BitmapPR # 1=short, 2=medium, 3=long ssb_PositionsInBurst_PR = 2; - ssb_PositionsInBurst_Bitmap = 1; + ssb_PositionsInBurst_Bitmap = 0x1; # ssb_periodicityServingCell # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 @@ -187,7 +148,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -227,29 +188,37 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( { - local_rf = "yes" + local_rf = "yes" nb_tx = 1 nb_rx = 1 att_tx = 0 att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 50; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + #bf_weights = [0x00007fff, 0x00007fff]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; } @@ -264,6 +233,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf index 0b04dc82d1..965408332c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf @@ -23,7 +23,8 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; - + pusch_AntennaPorts = 1; + servingCellConfigCommon = ( { #spCellConfigCommon @@ -32,7 +33,7 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP). points to Subcarrier 0 of RB#10 of SSB block absoluteFrequencySSB = 641032; dl_frequencyBand = 78; # this is 3600 MHz @@ -45,37 +46,15 @@ gNBs = dl_carrierBandwidth = 106; #initialDownlinkBWP #genericParameters - # this is RBstart=0,L=50 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 13475; + # this is RBstart=33 (Start RB of SSB block),L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6358; #6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPcontrolResourceSetZero = 0; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=5 - initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -88,7 +67,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 13475; + initialULBWPlocationAndBandwidth = 6358; #6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -125,21 +104,9 @@ gNBs = # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex # msg1_SubcarrierSpacing = 1, - # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -181,7 +148,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; // -25 dBm/RE is the maximum measured power from USRP corresponding to att_tx = 0 dB } ); @@ -221,14 +188,16 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( @@ -242,6 +211,14 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; sdr_addrs = "type=x300"; clock_src = "external"; } @@ -256,6 +233,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf index ae17efc9bd..e36748a3a9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -32,8 +33,8 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) - absoluteFrequencySSB = 642364; + # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP). Points to Subcarrier 0 of RB#10 of SSB block + absoluteFrequencySSB = 642016;#642364; dl_frequencyBand = 78; # this is 3600 MHz dl_absoluteFrequencyPointA = 640000; @@ -45,37 +46,15 @@ gNBs = dl_carrierBandwidth = 217; #initialDownlinkBWP #genericParameters - # this is RBstart=84,L=50 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 13559; + # this is RBstart=74 (Start RB of SSB block),L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13549; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPcontrolResourceSetZero = 0; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=5 - initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -88,7 +67,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 13559; + initialULBWPlocationAndBandwidth = 13549; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -129,17 +108,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -181,7 +149,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -208,6 +176,8 @@ gNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ target_enb_x2_ip_address = ( { ipv4 = "192.168.12.108"; ipv6 = "192:168:30::17"; @@ -239,10 +209,12 @@ MACRLCs = ( ); L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( @@ -254,7 +226,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2"; clock_src = "external"; @@ -278,13 +250,30 @@ THREAD_STRUCT = ( # modelname = "AWGN"; #}; +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; global_log_verbosity ="medium"; hw_log_level ="info"; hw_log_verbosity ="medium"; - phy_log_level ="debug"; + phy_log_level ="info"; phy_log_verbosity ="medium"; mac_log_level ="info"; mac_log_verbosity ="high"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf index c907dcfe8d..7b2d369919 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -45,37 +46,15 @@ gNBs = dl_carrierBandwidth = 217; #initialDownlinkBWP #genericParameters - # this is RBstart=84,L=50 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 13559; + # this is RBstart=74,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13549; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPcontrolResourceSetZero = 0; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=5 - initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -88,7 +67,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 13559; + initialULBWPlocationAndBandwidth = 13549; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -129,17 +108,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -181,7 +149,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -225,10 +193,12 @@ MACRLCs = ( ); L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( @@ -255,6 +225,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf new file mode 100644 index 0000000000..dbf4f58348 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf @@ -0,0 +1,272 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=b200"; + #"addr=192.168.18.207"; + #"addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf new file mode 100644 index 0000000000..6d23726a78 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf @@ -0,0 +1,270 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf new file mode 100644 index 0000000000..c3fa56f15e --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf @@ -0,0 +1,270 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf index 464ce6b9aa..15aa368fdf 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf @@ -23,6 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; servingCellConfigCommon = ( { @@ -45,37 +46,15 @@ gNBs = dl_carrierBandwidth = 273; #initialDownlinkBWP #genericParameters - # this is RBstart=84,L=50 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 13559; + # this is RBstart=74,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13549; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPcontrolResourceSetZero = 0; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=5 - initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -88,7 +67,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 13559; + initialULBWPlocationAndBandwidth = 13549; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -129,17 +108,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -181,7 +149,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -25; } ); @@ -225,10 +193,12 @@ MACRLCs = ( ); L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( @@ -240,7 +210,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; @@ -256,6 +226,23 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf new file mode 100644 index 0000000000..06ae5af066 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf @@ -0,0 +1,49 @@ +log_config = { + global_log_level ="debug"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="debug"; + mac_log_verbosity ="medium"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="debug"; + rrc_log_verbosity ="full"; +}; + + + +L1s = ( + { + num_cc = 1; + tr_n_preference = "nfapi"; + local_n_if_name = "lo"; + remote_n_address = "127.0.0.2"; // vnf addr + local_n_address = "127.0.0.1"; // pnf addr + local_n_portc = 50000; // pnf p5 port [!] + remote_n_portc = 50001; // vnf p5 port + local_n_portd = 50010; // pnf p7 port + remote_n_portd = 50011; // vnf p7 port + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sdr_addrs = "type=x300"; // USRP type + clock_src = "external"; + time_src = "external"; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf index d2c1aac31e..e05c64b4e8 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band38.tm1.if4p5.50PRB.lo.conf @@ -154,6 +154,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf index 7c2c2e0170..1ef71bedc2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf @@ -154,6 +154,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf index 723147daeb..9ce9f28cc2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf @@ -185,6 +185,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.conf index 13fd5fdb75..30cb852a28 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.conf @@ -154,6 +154,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf index b72e4c59d7..519305b68d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf @@ -155,6 +155,8 @@ eNBs = enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf new file mode 100644 index 0000000000..1583e07ca1 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf @@ -0,0 +1,252 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + + ); + + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + + +MACRLCs = ( + { + num_cc = 1; + local_s_if_name = "lo:"; + remote_s_address = "127.0.0.1"; // pnf addr [!] + local_s_address = "127.0.0.2"; // vnf addr + local_s_portc = 50001; // vnf p5 port + remote_s_portc = 50000; // pnf p5 port [!] + local_s_portd = 50011; // vnf p7 port [!] + remote_s_portd = 50010; // pnf p7 port [!] + tr_s_preference = "nfapi"; + tr_n_preference = "local_RRC"; + } +) + + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +log_config = + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc_b38_if5_ENDC.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc_b38_if5_ENDC.conf new file mode 100644 index 0000000000..9b611b3f07 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc_b38_if5_ENDC.conf @@ -0,0 +1,243 @@ +Active_eNBs = ( "eNB_Eurecom_VCO_B38"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_VCO_B38"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 1; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2585000000L; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 5; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = 10; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -106; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.150"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "no"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; + t_dc_overall = 2000; + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "bond0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.203/24"; + ENB_INTERFACE_NAME_FOR_S1U = "bond0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.18.203/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "192.168.18.203/24"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + + log_config : + { + global_log_level ="debug"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + scheduler_mode = "fairRR"; + puSch10xSnr = 100; + puCch10xSnr = 100; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 150; + } +); + +RUs = ( + { + local_if_name = "bond0"; + remote_address = "192.168.18.222"; + local_address = "192.168.18.203"; + local_portc = 50000; + remote_portc = 55444; + local_portd = 52001; + remote_portd = 52183; + local_rf = "no" + tr_preference = "udp_ecpri_if5" + nb_tx = 1 + nb_rx = 1 + att_tx = 5 + att_rx = 0; + eNB_instances = [0]; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_eNB_band13.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_eNB_band13.conf new file mode 100644 index 0000000000..1d8f61e442 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_eNB_band13.conf @@ -0,0 +1,285 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + ////////// Identification parameters: + eNB_ID = 0xe01; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( + { mcc = 311; mnc = 480; mnc_length = 3; } + ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + nb_antenna_ports = 1; + ue_TransmissionMode = 1; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 13; + downlink_frequency = 751000000L; + uplink_frequency_offset = 31000000; + Nid_cell = 0; + N_RB_DL = 25; //100; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + prach_root = 0; + tx_gain = 90; + rx_gain = 115; + pbch_repetition = "FALSE"; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -26; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 2071241; + + } + ); + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + enable_measurement_reports = "yes"; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.199/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth1"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.18.199/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + + ENB_IPV4_ADDRESS_FOR_X2C = "192.168.18.199/24"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="high"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="debug"; + rlc_log_verbosity ="high"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="high"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } +); + +THREAD_STRUCT = ( + { + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + worker_config = "WORKER_ENABLE"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -26; + max_rxgain = 130; + eNB_instances = [0]; + clock_src = "external"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="high"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="high"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="high"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf index ea105d86b6..6df25273c8 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf @@ -140,6 +140,9 @@ eNBs = discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 641272; } ); @@ -187,6 +190,8 @@ eNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ NETWORK_INTERFACES : { @@ -235,8 +240,8 @@ MACRLCs = ( THREAD_STRUCT = ( { - parallel_config = "PARALLEL_RU_L1_TRX_SPLITaaaaaa"; - worker_config = "ENABLE"; + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + worker_config = "WORKER_ENABLE"; } ); @@ -258,7 +263,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 118; eNB_instances = [0]; - clock_src = "external"; + clock_src = "internal"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf index b63939add2..8dfcfb2b88 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf @@ -23,7 +23,8 @@ gNBs = ssb_SubcarrierOffset = 31; //0; pdsch_AntennaPorts = 1; - + pusch_AntennaPorts = 1; + servingCellConfigCommon = ( { #spCellConfigCommon @@ -46,36 +47,14 @@ gNBs = #initialDownlinkBWP #genericParameters # this is RBstart=84,L=13 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; + initialDLBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; #pdcch-ConfigCommon initialDLBWPcontrolResourceSetZero = 0; initialDLBWPsearchSpaceZero = 0; - #pdsch-ConfigCommon - #pdschTimeDomainAllocationList (up to 16 entries) - initialDLBWPk0_0 = 0; - #initialULBWPmappingType - #0=typeA,1=typeB - initialDLBWPmappingType_0 = 0; - #this is SS=1,L=13 - initialDLBWPstartSymbolAndLength_0 = 40; - initialDLBWPk0_1 = 0; - initialDLBWPmappingType_1 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_1 = 53; - - initialDLBWPk0_2 = 0; - initialDLBWPmappingType_2 = 0; - #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 54; - - initialDLBWPk0_3 = 0; - initialDLBWPmappingType_3 = 0; - #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) - initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -88,7 +67,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; + initialULBWPlocationAndBandwidth = 6368; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; @@ -129,21 +108,6 @@ gNBs = # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, - # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; - initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 - initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; - initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 - initialULBWPstartSymbolAndLength_1 = 69; - - initialULBWPk2_2 = 7; - initialULBWPmappingType_2 = 1; - # this is SS=10 L=4 - initialULBWPstartSymbolAndLength_2 = 52; msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -201,7 +165,7 @@ gNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.18.99"; + amf_ip_address = ( { ipv4 = "192.168.69.131"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -212,6 +176,8 @@ gNBs = enable_x2 = "yes"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ target_enb_x2_ip_address = ( { ipv4 = "192.168.18.199"; ipv6 = "192:168:30::17"; @@ -222,10 +188,10 @@ gNBs = NETWORK_INTERFACES : { - GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24"; - GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24"; + GNB_INTERFACE_NAME_FOR_NG_AMF = "eth0"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.18.198/24"; + GNB_INTERFACE_NAME_FOR_NGU = "eth0"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.18.198/24"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24"; GNB_PORT_FOR_X2C = 36422; # Spec 36422 @@ -235,16 +201,20 @@ gNBs = MACRLCs = ( { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - } + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } ); L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); @@ -259,20 +229,37 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - clock_src = "external"; + clock_src = "internal"; } ); THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" - //parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; - parallel_config = "PARALLEL_SINGLE_THREAD"; + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" worker_config = "WORKER_ENABLE"; } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf new file mode 100644 index 0000000000..d01b0947c0 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf @@ -0,0 +1,289 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 12 PRBs@30kHz SCS + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -100; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf new file mode 100644 index 0000000000..198ad8471c --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf @@ -0,0 +1,278 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641272; //641032; #641968; 641968=start of ssb at 3600MHz + 82 RBs 641032=center of SSB at center of cell + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -90; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = 0; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.196/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.196/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.196/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + time_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_nsa_n310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_nsa_n310.conf new file mode 100644 index 0000000000..2f4839fd3b --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_nsa_n310.conf @@ -0,0 +1,275 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641272; //641032; #641968; 641968=start of ssb at 3600MHz + 82 RBs 641032=center of SSB at center of cell + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6368; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -100; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + amf_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "eth0"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.18.198/24"; + GNB_INTERFACE_NAME_FOR_NGU = "eth0"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.18.198/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.18.252,addr=192.168.80.50,clock_source=internal,time_source= internal" + #clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0", "nea2" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia0" ); +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf new file mode 100644 index 0000000000..680a6cb4ae --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf @@ -0,0 +1,99 @@ +Active_gNBs = ( "gNB-Eurecom-CU"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; +Num_Threads_PUSCH = 8; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-CU"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x010203; // 0 false, else true + }, + { + sst = 1; + sd = 0x1; #112233; // 0 false, else true + } + ); + + }); + + + nr_cellid = 12345678L + + tr_s_preference = "f1"; + + local_s_if_name = "lo"; + local_s_address = "127.0.0.4"; + remote_s_address = "127.0.0.3"; + local_s_portc = 501; + local_s_portd = 2152; + remote_s_portc = 501; + remote_s_portd = 2152; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.69.131"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "bond0"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.18.207/24"; + GNB_INTERFACE_NAME_FOR_NGU = "bond0"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.18.207/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="debug"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; + ngap_log_level ="debug"; + ngap_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf new file mode 100644 index 0000000000..7f9e4d2d44 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf @@ -0,0 +1,273 @@ +Active_gNBs = ( "gNB-Eurecom-DU"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-DU"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x010203; // 0 false, else true + }, + { + sst = 1; + sd = 0x1; #112233; // 0 false, else true + } + ); + + }); + + + nr_cellid = 12345678L + +# tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + sib1_tda = 0; + + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 12952; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 12952; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "f1"; + local_n_if_name = "lo"; + local_n_address = "127.0.0.3"; + remote_n_address = "127.0.0.4"; + local_n_portc = 601; + local_n_portd = 2152; + remote_n_portc = 600; + remote_n_portd = 2152; + + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 2; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="debug"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; + ngap_log_level ="debug"; + ngap_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf new file mode 100644 index 0000000000..ab4713f8b5 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf @@ -0,0 +1,284 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 100; + + plmn_list = ({ + mcc = 208; + mnc = 93; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x010203; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + + }); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + sib1_tda = 0; + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.199.223"; + ipv6 = "192:168:199::223"; + active = "yes"; + preference = "ipv4"; + } + ); + + + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_NG_AMF = "eno1"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.199.222/24"; + GNB_INTERFACE_NAME_FOR_NGU = "enx000ec6c0a3ac"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.10.100/24"; + GNB_PORT_FOR_NGU = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.20.20/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + ngap_log_level ="info"; + ngap_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf new file mode 100644 index 0000000000..9238ea1809 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf @@ -0,0 +1,300 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x1; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + + }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + sib1_tda = 0; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 518670; + dl_frequencyBand = 41; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 514854; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 12952; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 41; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 12952; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.70.132"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [41]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sf_extension = 0; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; +} +); + +THREAD_STRUCT = ( +{ + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + ngap_log_level ="debug"; + ngap_log_verbosity ="medium"; +}; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf new file mode 100644 index 0000000000..9717462176 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf @@ -0,0 +1,301 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x1; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + + }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 2; + ul_prbblacklist = "51,52,53,54" + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 11; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB = 621312; # 641280 + dl_frequencyBand = 78; + # this is 3300.60 MHz + dl_absoluteFrequencyPointA = 620040; # 640008 + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -104; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -70; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.70.132"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + #pusch_TargetSNRx10 = 150; + #pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 4; + prach_dtx_threshold = 120; + #pucch0_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 2 + nb_rx = 2 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + sf_extension = 0; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + #clock_src = "internal"; + sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal" +} +); + +THREAD_STRUCT = ( +{ + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + ngap_log_level ="debug"; + ngap_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; +}; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf new file mode 100644 index 0000000000..d9b62064c1 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -0,0 +1,300 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 208; + mnc = 99; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0x1; // 0 false, else true + }, + { + sst = 1; + sd = 0x112233; // 0 false, else true + } + ); + + }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + sib1_tda = 0; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.70.132"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sf_extension = 0; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; +} +); + +THREAD_STRUCT = ( +{ + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + ngap_log_level ="debug"; + ngap_log_verbosity ="medium"; +}; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.sabox.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.sabox.conf new file mode 100644 index 0000000000..e9577ee265 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.sabox.conf @@ -0,0 +1,306 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 450; + mnc = 05; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + sd = 0xd143a5; // 0 false, else true + } + ); + + }); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 12952; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 12952; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + amf_ip_address = ( { ipv4 = "192.168.5.233"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "eth0"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.5.200/24"; + GNB_INTERFACE_NAME_FOR_NGU = "eth0"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.5.200/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.5.200/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + ngap_log_level ="debug"; + ngap_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf new file mode 100644 index 0000000000..545b44f888 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf @@ -0,0 +1,8 @@ +uicc0 = { +imsi = "2089900007487"; +key = "fec86ba6eb707ed08905757b1bb44b8f"; +opc= "C42449363BBAD02B66D16BC975D77CC1"; +dnn= "oai"; +nssai_sst=1; +nssai_sd=1; +} diff --git a/targets/RT/USER/eNB_usrp.gtkw b/targets/RT/USER/eNB_usrp.gtkw index 074e3b1324..8f3aeaac62 100644 --- a/targets/RT/USER/eNB_usrp.gtkw +++ b/targets/RT/USER/eNB_usrp.gtkw @@ -1,13 +1,13 @@ [*] [*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI -[*] Sun May 19 21:39:57 2019 +[*] Tue Jan 26 21:45:57 2021 [*] -[dumpfile] "/tmp/openair_dump_eNB.vcd" -[dumpfile_mtime] "Sun May 19 21:30:25 2019" -[dumpfile_size] 11590554 -[savefile] "/home/sphex/raymond/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw" -[timestart] 7629910000 -[size] 1840 795 +[dumpfile] "/home/eurecom/raymond/gtkw/openair_dump_eNB.vcd" +[dumpfile_mtime] "Tue Jan 26 21:26:33 2021" +[dumpfile_size] 180869253 +[savefile] "/home/eurecom/raymond/openairinterface5g_2/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw" +[timestart] 11468800000 +[size] 1693 785 [pos] -1 -1 *-21.832302 7639830000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [sst_width] 386 @@ -16,17 +16,22 @@ [sst_vpaned_height] 303 @28 functions.trx_read +@29 +functions.trx_write_thread +@28 functions.trx_write @24 variables.trx_ts[63:0] variables.trx_tst[63:0] +variables.trx_write_flags[63:0] @28 functions.eNB_thread_rxtx0 +@420 +variables.l1_proc_tx_ic[63:0] +variables.l1_proc_ic[63:0] @24 variables.frame_number_RX0_RU[63:0] -@25 variables.tti_number_RX0_RU[63:0] -@24 variables.frame_number_TX0_RU[63:0] variables.tti_number_TX0_RU[63:0] @28 diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 147bc955ae..632a47707b 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -70,6 +70,7 @@ #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/LTE_TRANSPORT/if5_tools.h" +#include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/phy_extern.h" @@ -87,15 +88,14 @@ #include "enb_config.h" #include "targets/RT/USER/lte-softmodem.h" -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_extern.h" -#endif - #include "s1ap_eNB.h" #include "SIMULATION/ETH_TRANSPORT/proto.h" #include "T.h" +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 @@ -261,7 +261,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB, eNB->UL_INFO.subframe = proc->subframe_rx; eNB->UL_INFO.module_id = eNB->Mod_id; eNB->UL_INFO.CC_id = eNB->CC_id; - eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); + eNB->if_inst->UL_indication(&eNB->UL_INFO, (void*)proc); AssertFatal((ret= pthread_mutex_unlock(&eNB->UL_INFO_mutex))==0,"error unlocking UL_INFO_mutex, return %d\n",ret); /* this conflict resolution may be totally wrong, to be tested */ /* CONFLICT RESOLUTION: BEGIN */ @@ -323,7 +323,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB, static void *L1_thread_tx(void *param) { L1_proc_t *eNB_proc = (L1_proc_t *)param; L1_rxtx_proc_t *proc = &eNB_proc->L1_proc_tx; - PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id]; + PHY_VARS_eNB *eNB = eNB_proc->eNB; char thread_name[100]; sprintf(thread_name,"TXnp4_%d\n",&eNB->proc.L1_proc == proc ? 0 : 1); thread_top_init(thread_name,1,470000,500000,500000); @@ -331,6 +331,7 @@ static void *L1_thread_tx(void *param) { //wait_sync("tx_thread"); + proc->respEncode = eNB->proc.L1_proc.respEncode; while (!oai_exit) { LOG_D(PHY,"Waiting for TX (IC %d)\n",proc->instance_cnt); @@ -351,21 +352,19 @@ static void *L1_thread_tx(void *param) { LOG_D(PHY,"L1 TX processing %d.%d\n",proc->frame_tx,proc->subframe_tx); phy_procedures_eNB_TX(eNB, proc, 1); AssertFatal((ret= pthread_mutex_lock( &proc->mutex ))==0,"error locking L1_proc_tx mutex, return %d\n",ret); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,proc->instance_cnt); int subframe_tx = proc->subframe_tx; int frame_tx = proc->frame_tx; uint64_t timestamp_tx = proc->timestamp_tx; proc->instance_cnt = -1; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,proc->instance_cnt); LOG_D(PHY,"L1 TX signaling done for %d.%d\n",proc->frame_tx,proc->subframe_tx); // the thread can now be woken up LOG_D(PHY,"L1_thread_tx: signaling completion in %d.%d\n",proc->frame_tx,proc->subframe_tx); - if (pthread_cond_signal(&proc->cond) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - } - + AssertFatal((ret=pthread_cond_signal(&proc->cond))== 0, "ERROR pthread_cond_signal for eNB TXnp4 thread ret %d\n",ret); AssertFatal((ret= pthread_mutex_unlock( &proc->mutex ))==0,"error unlocking L1_proc_tx mutex, return %d\n",ret); + + wakeup_txfh(eNB,proc,frame_tx,subframe_tx,timestamp_tx); } @@ -391,6 +390,8 @@ static void *L1_thread( void *param ) { } PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id]; + + char thread_name[100]; cpu_set_t cpuset; CPU_ZERO(&cpuset); @@ -402,7 +403,7 @@ static void *L1_thread( void *param ) { LOG_I(PHY,"thread rxtx created id=%ld\n", syscall(__NR_gettid)); while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0, 0 ); T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); LOG_D(PHY,"L1RX waiting for RU RX\n"); @@ -410,7 +411,7 @@ static void *L1_thread( void *param ) { LOG_D(PHY,"L1RX starting in %d.%d\n",proc->frame_rx,proc->subframe_rx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,sched_getcpu()); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0, 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB,proc->subframe_tx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB,proc->subframe_rx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB,proc->frame_tx); @@ -424,6 +425,8 @@ static void *L1_thread( void *param ) { LOG_D(PHY,"L1 RX %d.%d done\n",proc->frame_rx,proc->subframe_rx); + if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC, proc->instance_cnt); if (NFAPI_MODE!=NFAPI_MODE_VNF) { if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(eNB,proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx); else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) { @@ -432,9 +435,7 @@ static void *L1_thread( void *param ) { } } - if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break; } // while !oai_exit - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); LOG_D(PHY, " *** Exiting eNB thread RXn_TXnp4\n"); eNB_thread_rxtx_status = 0; @@ -461,10 +462,9 @@ void eNB_top(PHY_VARS_eNB *eNB, L1_proc->subframe_rx = ru_proc->tti_rx; L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10; - + if (rxtx(eNB,L1_proc,string) < 0) - LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); - + LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); ru_proc->timestamp_tx = L1_proc->timestamp_tx; ru_proc->tti_tx = L1_proc->subframe_tx; ru_proc->frame_tx = L1_proc->frame_tx; @@ -531,6 +531,7 @@ int wakeup_txfh(PHY_VARS_eNB *eNB, AssertFatal(pthread_cond_signal(&ru_proc->cond_eNBs) == 0, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n"); AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_eNBs))==0,"mutex_unlock returned %d\n",ret); + } return(0); @@ -543,19 +544,19 @@ int wakeup_tx(PHY_VARS_eNB *eNB, int frame_tx, int subframe_tx, uint64_t timestamp_tx) { - L1_rxtx_proc_t *L1_proc = &eNB->proc.L1_proc; L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx; int ret; LOG_D(PHY,"ENTERED wakeup_tx (IC %d)\n",L1_proc_tx->instance_cnt); + // check if subframe is a has TX else return + if (subframe_select(&eNB->frame_parms,subframe_tx) == SF_UL) return 0; AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); - LOG_D(PHY,"L1 RX %d.%d Waiting to wake up L1 TX %d.%d (IC L1TX %d)\n",L1_proc->frame_rx,L1_proc->subframe_rx,L1_proc->frame_tx,L1_proc->subframe_tx,L1_proc_tx->instance_cnt); + LOG_D(PHY,"L1 RX %d.%d Waiting to wake up L1 TX %d.%d (IC L1TX %d)\n",frame_rx,subframe_rx,frame_tx,subframe_tx,L1_proc_tx->instance_cnt); while(L1_proc_tx->instance_cnt == 0) { pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex); } LOG_D(PHY,"L1 RX Got signal that TX %d.%d is done\n",L1_proc_tx->frame_tx,L1_proc_tx->subframe_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt); L1_proc_tx->instance_cnt = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt); L1_proc_tx->subframe_rx = subframe_rx; @@ -564,9 +565,11 @@ int wakeup_tx(PHY_VARS_eNB *eNB, L1_proc_tx->frame_tx = frame_tx; L1_proc_tx->timestamp_tx = timestamp_tx; // the thread can now be woken up - LOG_D(PHY,"L1 RX Waking up L1 TX %d.%d\n",L1_proc->frame_tx,L1_proc->subframe_tx); + LOG_D(PHY,"L1 RX Waking up L1 TX %d.%d\n",frame_tx,subframe_tx); + AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for eNB L1 thread tx\n"); AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); + return(0); } @@ -586,10 +589,16 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB, if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret); LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); +/* AssertFatal(1==0,"L1_thread isn't ready in %d.%d (L1RX %d.%d), aborting RX, exiting\n", + ru_proc->frame_rx,ru_proc->tti_rx,L1_proc->frame_rx,L1_proc->subframe_rx); +*/ return(0); + } ++L1_proc->instance_cnt; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC, L1_proc->instance_cnt); + // We have just received and processed the common part of a subframe, say n. // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired // transmitted timestamp of the next TX slot (first). @@ -607,14 +616,12 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB, VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->frame_tx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->subframe_tx); - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc->cond) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } + // the thread can now be woken up + AssertFatal((ret=pthread_cond_signal(&L1_proc->cond))== 0, "ERROR pthread_cond_signal for eNB RXn-TXnp4 thread, ret %d\n",ret); AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret); + + return(0); } @@ -838,6 +845,21 @@ static void *process_stats_thread(void *param) { return(NULL); } +void *L1_stats_thread(void *param) { + PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param; + wait_sync("L1_stats_thread"); + FILE *fd; + while (!oai_exit) { + sleep(1); + fd=fopen("L1_stats.log","w"); + AssertFatal(fd!=NULL,"Cannot open L1_stats.log\n"); + dump_I0_stats(fd,eNB); + dump_ulsch_stats(fd,eNB,eNB->proc.L1_proc_tx.frame_tx); + dump_uci_stats(fd,eNB,eNB->proc.L1_proc_tx.frame_tx); + fclose(fd); + } + return(NULL); +} void init_eNB_proc(int inst) { /*int i=0;*/ @@ -859,6 +881,7 @@ void init_eNB_proc(int inst) { L1_proc_tx->instance_cnt = -1; L1_proc->instance_cnt_RUs = 0; L1_proc_tx->instance_cnt_RUs = 0; + proc->eNB = eNB; proc->instance_cnt_prach = -1; proc->instance_cnt_asynch_rxtx = -1; proc->instance_cnt_synch = -1; @@ -931,6 +954,7 @@ void init_eNB_proc(int inst) { AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach); if (opp_enabled == 1) pthread_create(&proc->process_stats_thread,NULL,process_stats_thread,(void *)eNB); + pthread_create(&proc->L1_stats_thread,NULL,L1_stats_thread,(void*)eNB); } //for multiple CCs: setup master and slaves @@ -1061,60 +1085,47 @@ void print_opp_meas(void) { void free_transport(PHY_VARS_eNB *eNB) { - for (int i=0; idlsch[i][j]); - - LOG_D(PHY, "Freeing Transport Channel Buffer for ULSCH, UE %d\n",i); - free_eNB_ulsch(eNB->ulsch[1+i]); } - - free_eNB_ulsch(eNB->ulsch[0]); + for (int i=0;iulsch[i]); + } } void init_transport(PHY_VARS_eNB *eNB) { - int i; - int j; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; LOG_I(PHY, "Initialise transport\n"); if (NFAPI_MODE!=NFAPI_MODE_VNF) { - for (i=0; idlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp); - + LOG_I(PHY,"eNB->dlsch[%d][%d] %p\n",i,j,eNB->dlsch[i][j]); if (!eNB->dlsch[i][j]) { - LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i); + LOG_E(PHY,"Can't get eNB dlsch structures for DLSCH %d \n", i); exit(-1); } else { eNB->dlsch[i][j]->rnti=0; LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti); } } + } + for (int i=0;iulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0); + LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH %d/%d\n",i,NUMBER_OF_ULSCH_MAX); + eNB->ulsch[i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0); - if (!eNB->ulsch[1+i]) { + if (!eNB->ulsch[i]) { LOG_E(PHY,"Can't get eNB ulsch structures\n"); exit(-1); } - - // this is the transmission mode for the signalling channels - // this will be overwritten with the real transmission mode by the RRC once the UE is connected - eNB->transmission_mode[i] = fp->nb_antenna_ports_eNB==1 ? 1 : 2; - } - - // ULSCH for RA - eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0); - - if (!eNB->ulsch[0]) { - LOG_E(PHY,"Can't get eNB ulsch structures\n"); - exit(-1); } eNB->dlsch_SI = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); @@ -1127,7 +1138,7 @@ void init_transport(PHY_VARS_eNB *eNB) { eNB->rx_total_gain_dB=130; - for(i=0; imu_mimo_mode[i].dl_pow_off = 2; eNB->check_for_total_transmissions = 0; @@ -1135,11 +1146,13 @@ void init_transport(PHY_VARS_eNB *eNB) { eNB->FULL_MUMIMO_transmissions = 0; eNB->check_for_SUMIMO_transmissions = 0; fp->pucch_config_common.deltaPUCCH_Shift = 1; + if (eNB->use_DTX == 0) fill_subframe_mask(eNB); + } void init_eNB_afterRU(void) { - int inst,CC_id,ru_id,i,aa; + int inst,CC_id,i; PHY_VARS_eNB *eNB; LOG_I(PHY,"%s() RC.nb_inst:%d\n", __FUNCTION__, RC.nb_inst); @@ -1149,13 +1162,14 @@ void init_eNB_afterRU(void) { for (CC_id=0; CC_idnum_RU>0,"Number of RU attached to eNB %d is zero\n",eNB->Mod_id); - + // map antennas and PRACH signals to eNB RX LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id); eNB->frame_parms.nb_antennas_rx = 0; + LOG_I(PHY,"eNB->num_RU:%d\n", eNB->num_RU); + if (NFAPI_MODE==NFAPI_MODE_PNF) AssertFatal(eNB->num_RU>0,"Number of RU attached to eNB %d is zero\n",eNB->Mod_id); + for (int ru_id=0; ru_idnum_RU; ru_id++) + eNB->frame_parms.nb_antennas_rx += eNB->RU_list[ru_id]->nb_rx; + phy_init_lte_eNB(eNB,0,0); LOG_I(PHY,"Overwriting eNB->prach_vars.rxsigF[0]:%p\n", eNB->prach_vars.rxsigF[0]); eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *)); @@ -1164,10 +1178,9 @@ void init_eNB_afterRU(void) { eNB->prach_vars_br.rxsigF[ce_level] = (int16_t **)malloc16(64*sizeof(int16_t *)); } - LOG_I(PHY,"eNB->num_RU:%d\n", eNB->num_RU); - for (ru_id=0,aa=0; ru_idnum_RU; ru_id++) { - eNB->frame_parms.nb_antennas_rx += eNB->RU_list[ru_id]->nb_rx; + for (int ru_id=0,aa=0; ru_idnum_RU; ru_id++) { + AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL, "RU %d : common.rxdataF is NULL\n", eNB->RU_list[ru_id]->idx); @@ -1177,7 +1190,7 @@ void init_eNB_afterRU(void) { for (i=0; iRU_list[ru_id]->nb_rx; aa++,i++) { LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa); - eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[i]; + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[0][i]; for (int ce_level=0; ce_level<4; ce_level++) eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i]; @@ -1214,7 +1227,7 @@ void init_eNB_afterRU(void) { init_eNB_proc(inst); } - for (ru_id=0; ru_idwakeup_rxtx = wakeup_rxtx; RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_eNB; @@ -1239,7 +1252,8 @@ void init_eNB(int single_thread_flag, if (RC.eNB[inst] == NULL) RC.eNB[inst] = (PHY_VARS_eNB **) malloc(RC.nb_CC[inst]*sizeof(PHY_VARS_eNB *)); for (CC_id=0; CC_idabstraction_flag = 0; diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 4d89020077..10ba121c44 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -51,7 +51,6 @@ #include "assertions.h" #include "msc.h" #include "PHY/defs_common.h" -#include "PHY/phy_extern.h" #include "PHY/types.h" #include "PHY/INIT/phy_init.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" @@ -59,23 +58,11 @@ #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/LTE_TRANSPORT/if5_tools.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" -#include "PHY_INTERFACE/phy_interface.h" -#include "LAYER2/MAC/mac.h" -#include "LAYER2/MAC/mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" -#include "RRC/LTE/rrc_extern.h" -#include "SCHED/sched_eNB.h" -#include "UTIL/OPT/opt.h" -#include "UTIL/OTG/otg_tx.h" -#include "UTIL/OTG/otg_externs.h" -#include "UTIL/MATH/oml.h" +#include "SCHED/sched_common.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include "nfapi/oai_integration/vendor_ext.h" -#include "enb_config.h" #include "targets/ARCH/COMMON/common_lib.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" -#include "targets/RT/USER/lte-softmodem.h" //#include "PHY/TOOLS/time_meas.h" /* these variables have to be defined before including ENB_APP/enb_paramdef.h */ @@ -86,29 +73,25 @@ static int DEFBFW[] = {0x00007fff}; #include "ENB_APP/enb_paramdef.h" #include "common/config/config_userapi.h" -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_extern.h" -#endif - -#include "s1ap_eNB.h" #include "SIMULATION/ETH_TRANSPORT/proto.h" #include "T.h" -#include "pdcp.h" +#include "executables/softmodem-common.h" #define MBMS_EXPERIMENTAL extern volatile int oai_exit; -extern int emulate_rf; -extern int numerology; extern clock_source_t clock_source; #include "executables/thread-common.h" //extern PARALLEL_CONF_t get_thread_parallel_conf(void); //extern WORKER_CONF_t get_thread_worker_conf(void); extern void phy_init_RU(RU_t *); -void stop_RU(int nb_ru); +void prach_procedures(PHY_VARS_eNB *eNB,int br_flag); + +void stop_RU(RU_t **rup,int nb_ru); + void do_ru_synch(RU_t *ru); void configure_ru(int idx, @@ -120,15 +103,28 @@ void configure_rru(int idx, void reset_proc(RU_t *ru); int connect_rau(RU_t *ru); +void wait_eNBs(void); + const char ru_states[6][9] = {"RU_IDLE","RU_CONFIG","RU_READY","RU_RUN","RU_ERROR","RU_SYNC"}; +extern const char NB_functions[7][20]; +extern const char NB_timing[2][20]; + extern uint16_t sf_ahead; +extern const char ru_if_types[MAX_RU_IF_TYPES][20]; + + #if defined(PRE_SCD_THREAD) +#include "common/ran_context.h" +#include "nfapi/oai_integration/vendor_ext.h" +#include "openair2/LAYER2/MAC/mac_extern.h" extern uint8_t dlsch_ue_select_tbl_in_use; void init_ru_vnf(void); + extern RAN_CONTEXT_t RC; #endif +RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond); /*************************************************************/ /* Functions to attach and configure RRU */ @@ -139,26 +135,20 @@ extern uint16_t sf_ahead; // southbound IF5 fronthaul for 16-bit OAI format static inline void fh_if5_south_out(RU_t *ru,int frame, int subframe, uint64_t timestamp) { - if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + + ru->south_out_cnt++; send_IF5(ru, timestamp, subframe, &ru->seqno, IF5_RRH_GW_DL); } -// southbound IF5 fronthaul for Mobipass packet format -static inline void fh_if5_mobipass_south_out(RU_t *ru,int frame, int subframe, uint64_t timestamp) { - if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); - - send_IF5(ru, timestamp, subframe, &ru->seqno, IF5_MOBIPASS); -} - - // southbound IF4p5 fronthaul static inline void fh_if4p5_south_out(RU_t *ru, int frame, int subframe, uint64_t timestamp) { - if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); LOG_D(PHY,"ENTERED fh_if4p5_south_out Sending IF4p5 for frame %d subframe %d ru %d\n",ru->proc.frame_tx,ru->proc.tti_tx,ru->idx); @@ -168,7 +158,7 @@ static inline void fh_if4p5_south_out(RU_t *ru, LOG_D(PHY,"south_out_cnt %d\n",ru->south_out_cnt); } - /*if (ru == RC.ru[0] || ru == RC.ru[1]) { + /*if (ru->idx == 0 || ru->idx == ru) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU+ru->idx, ru->proc.frame_tx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU+ru->idx, ru->proc.subframe_tx ); }*/ @@ -189,11 +179,12 @@ void fh_if5_south_in(RU_t *ru, recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->tti_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - + if (proc->first_rx == 0) { if (proc->tti_rx != *subframe) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*subframe); - exit_fun("Exiting"); + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d), resynching\n",proc->tti_rx,*subframe); + *frame=proc->frame_rx; + *subframe=proc->tti_rx; } if (proc->frame_rx != *frame) { @@ -228,31 +219,30 @@ void fh_if4p5_south_in(RU_t *ru, symbol_mask_full = (1<symbols_per_tti)-1; LOG_D(PHY,"fh_if4p5_south_in: RU %d, frame %d, subframe %d, ru %d, mask %x\n",ru->idx,*frame,*subframe,ru->idx,proc->symbol_mask[*subframe]); - AssertFatal(proc->symbol_mask[*subframe]==0 || proc->symbol_mask[*subframe]==symbol_mask_full,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*subframe,proc->symbol_mask[*subframe]); + //AssertFatal(proc->symbol_mask[*subframe]==0 || proc->symbol_mask[*subframe]>=symbol_mask_full,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*subframe,proc->symbol_mask[*subframe]); // >= because PULTICK for S-subframe could have been received during normal subframe - if (proc->symbol_mask[*subframe]==0) { // this is normal case, if not true then we received a PULTICK before the previous subframe was finished + if (proc->symbol_mask[*subframe]idx,*frame,*subframe,f,sf); + LOG_D(PHY,"fh_if4p5_south_in (%s/%d): RU %d, frame %d, subframe %d, f %d, sf %d, symbol %d\n",packet_type == IF4p5_PULFFT ? "PULFFT" : "PULTICK",packet_type,ru->idx,*frame,*subframe,f,sf,symbol_number); if (oai_exit == 1 || ru->cmd== STOP_RU) break; if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sf] = proc->symbol_mask[sf] | (1<symbol_mask[sf] = symbol_mask_full; + proc->symbol_mask[sf] = 0xffff; pultick_received++; - /* if ((proc->first_rx==0) && (f!=*frame)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d (RU %d) \n",f,*frame, ru->idx); else if ((proc->first_rx==0) && (sf!=*subframe)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n",sf,*subframe,proc->first_rx); else break; */ - if (f==*frame || sf==*subframe) break; + //if (f==*frame || sf==*subframe) break; } else if (packet_type == IF4p5_PRACH) { // nothing in RU for RAU } - LOG_D(PHY,"rx_fh_if4p5 for RU %d: subframe %d, sf %d, symbol mask %x\n",ru->idx,*subframe,sf,proc->symbol_mask[sf]); - } while(proc->symbol_mask[sf] != symbol_mask_full); + LOG_D(PHY,"rx_fh_if4p5 for RU %d: subframe %d, sf %d, symbol %d, symbol mask %x\n",ru->idx,*subframe,sf,symbol_number,proc->symbol_mask[sf]); + } while(proc->symbol_mask[*subframe] < symbol_mask_full); } else { f = *frame; sf = *subframe; @@ -264,7 +254,7 @@ void fh_if4p5_south_in(RU_t *ru, proc->timestamp_rx = ((proc->frame_rx * 10) + proc->tti_rx ) * fp->samples_per_tti ; // proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti); - if (get_nprocs()<=4) { + if (get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { proc->tti_tx = (sf+sf_ahead)%10; proc->frame_tx = (sf>(9-sf_ahead)) ? (f+1)&1023 : f; } @@ -292,7 +282,7 @@ void fh_if4p5_south_in(RU_t *ru, *subframe = proc->tti_rx; } - /*if (ru == RC.ru[0] || ru == RC.ru[1]) { + /*if (ru->idx == 0 || ru->idx == 1) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU+ru->idx, f ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU+ru->idx, sf ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f ); @@ -324,48 +314,6 @@ void fh_slave_south_in(RU_t *ru, } -// asynchronous inbound if5 fronthaul from south (Mobipass) -void fh_if5_south_asynch_in_mobipass(RU_t *ru, - int *frame, - int *subframe) { - RU_proc_t *proc = &ru->proc; - LTE_DL_FRAME_PARMS *fp = ru->frame_parms; - recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_MOBIPASS); - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - int offset_mobipass = 40120; - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->tti_rx = ((proc->timestamp_rx-offset_mobipass)/fp->samples_per_tti)%10; - proc->frame_rx = ((proc->timestamp_rx-offset_mobipass)/(fp->samples_per_tti*10))&1023; - proc->tti_rx = (proc->timestamp_rx/fp->samples_per_tti)%10; - proc->frame_rx = (proc->timestamp_rx/(10*fp->samples_per_tti))&1023; - - if (proc->first_rx == 1) { - proc->first_rx =2; - *subframe = proc->tti_rx; - *frame = proc->frame_rx; - LOG_E(PHY,"[Mobipass]timestamp_rx:%llu, frame_rx %d, subframe: %d\n",(unsigned long long int)proc->timestamp_rx,proc->frame_rx,proc->tti_rx); - } else { - if (proc->tti_rx != *subframe) { - proc->first_rx++; - LOG_E(PHY,"[Mobipass]timestamp:%llu, tti_rx %d is not what we expect %d, first_rx:%d\n",(unsigned long long int)proc->timestamp_rx, proc->tti_rx,*subframe, proc->first_rx); - //exit_fun("Exiting"); - } - - if (proc->frame_rx != *frame) { - proc->first_rx++; - LOG_E(PHY,"[Mobipass]timestamp:%llu, frame_rx %d is not what we expect %d, first_rx:%d\n",(unsigned long long int)proc->timestamp_rx,proc->frame_rx,*frame, proc->first_rx); - // exit_fun("Exiting"); - } - - // temporary solution - *subframe = proc->tti_rx; - *frame = proc->frame_rx; - } - - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); -} // eNodeB_3GPP_BBU - - // asynchronous inbound if4p5 fronthaul from south void fh_if4p5_south_asynch_in(RU_t *ru, int *frame, @@ -442,7 +390,7 @@ void fh_if4p5_north_in(RU_t *ru, ru->north_in_cnt++; // dump VCD output for first RU in list - if (ru == RC.ru[0]) { + if (ru->idx == 0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, *frame ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, *subframe ); } @@ -456,7 +404,7 @@ void fh_if5_north_asynch_in(RU_t *ru, int tti_tx,frame_tx; openair0_timestamp timestamp_tx; recv_IF5(ru, ×tamp_tx, *subframe, IF5_RRH_GW_DL); - // printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); + // LOG_I(PHY,"Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); tti_tx = (timestamp_tx/fp->samples_per_tti)%10; frame_tx = (timestamp_tx/(fp->samples_per_tti*10))&1023; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx ); @@ -534,7 +482,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru, LOG_D(PHY,"RU %d/%d TST %llu, frame %d, subframe %d\n",ru->idx,0,(long long unsigned int)proc->timestamp_tx,frame_tx,tti_tx); // dump VCD output for first RU in list - if (ru == RC.ru[0]) { + if (ru->idx == 0) { /*VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx );*/ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_NORTH_ASYNCH_IN, frame_tx); @@ -600,8 +548,8 @@ volatile late_control_e late_control=STATE_BURST_NORMAL; static void *emulatedRF_thread(void *param) { RU_proc_t *proc = (RU_proc_t *) param; int microsec = 500; // length of time to sleep, in miliseconds + int numerology = 0 ; struct timespec req = {0}; - int numerology = get_softmodem_params()->numerology; req.tv_sec = 0; req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2; cpu_set_t cpuset; @@ -652,7 +600,7 @@ void rx_rf(RU_t *ru, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); old_ts = proc->timestamp_rx; - if(get_softmodem_params()->emulate_rf) { + if(ru->emulate_rf) { wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); rxs = fp->samples_per_tti; @@ -696,7 +644,7 @@ void rx_rf(RU_t *ru, ru->ts_offset = proc->timestamp_rx; proc->timestamp_rx = 0; } else if (resynch==0 && (proc->timestamp_rx - old_ts != fp->samples_per_tti)) { - LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,ru->ts_offset); + LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,ru->ts_offset); ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); proc->timestamp_rx = ts-ru->ts_offset; } @@ -705,7 +653,7 @@ void rx_rf(RU_t *ru, proc->tti_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; // synchronize first reception to frame 0 subframe 0 - if (ru->fh_north_asynch_in == NULL) { + if (get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD && ru->fh_north_asynch_in == NULL) { #ifdef PHY_TX_THREAD proc->timestamp_phy_tx = proc->timestamp_rx+((sf_ahead-1)*fp->samples_per_tti); proc->subframe_phy_tx = (proc->tti_rx+(sf_ahead-1))%10; @@ -733,16 +681,12 @@ void rx_rf(RU_t *ru, proc->frame_rx, proc->tti_rx); - // dump VCD output for first RU in list - if (ru == RC.ru[0]) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); + } - if (ru->fh_north_asynch_in == NULL) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx ); - } - } + // dump VCD output for first RU in list + if (ru->idx == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); } if (proc->first_rx == 0) { @@ -761,7 +705,7 @@ void rx_rf(RU_t *ru, *subframe = proc->tti_rx; } - //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); + //LOG_I(PHY,"timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); if (rxs != fp->samples_per_tti) { @@ -833,6 +777,7 @@ void tx_rf(RU_t *ru, /* add fail safe for late command */ if(late_control!=STATE_BURST_NORMAL) { //stop burst + LOG_E(PHY,"%d.%d late_control : %d\n",frame,subframe,late_control); switch (late_control) { case STATE_BURST_TERMINATE: flags=10; // end of burst and no time spec @@ -861,12 +806,13 @@ void tx_rf(RU_t *ru, break; } } - - /* add fail safe for late command end */ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, subframe); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS,flags); + + /* add fail safe for late command end */ + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers txs = ru->rfdevice.trx_write_func(&ru->rfdevice, timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, @@ -884,7 +830,7 @@ void tx_rf(RU_t *ru, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); // AssertFatal(txs == siglen+sf_extension,"TX : Timeout (sent %d/%d)\n",txs, siglen); - if( (txs != siglen+sf_extension) && (late_control==STATE_BURST_NORMAL) ) { /* add fail safe for late command */ + if( usrp_tx_thread == 0 && (txs != siglen+sf_extension) && (late_control==STATE_BURST_NORMAL) ) { /* add fail safe for late command */ late_control=STATE_BURST_TERMINATE; LOG_E(PHY,"TX : Timeout (sent %d/%d) state =%d\n",txs, siglen,late_control); } @@ -912,7 +858,6 @@ static void *ru_thread_asynch_rxtx( void *param ) { LOG_I(PHY, "devices ok (ru_thread_asynch_rxtx)\n"); while (!oai_exit) { - if (oai_exit) break; if (ru->state != RU_RUN) { subframe=0; @@ -929,12 +874,8 @@ static void *ru_thread_asynch_rxtx( void *param ) { LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); - // asynchronous receive from south (Mobipass) - if (ru->fh_south_asynch_in) { - ru->fh_south_asynch_in(ru, &frame, &subframe); - } // asynchronous receive from north (RRU IF4/IF5) - else if (ru->fh_north_asynch_in) { + if (ru->fh_north_asynch_in) { if (subframe_select(ru->frame_parms,subframe)!=SF_UL) ru->fh_north_asynch_in(ru, &frame, &subframe); } else @@ -1002,7 +943,7 @@ void *ru_thread_prach( void *param ) { thread_top_init("ru_thread_prach",1,500000,1000000,20000000); //wait_sync("ru_thread_prach"); - while (RC.ru_mask>0 && ru->function!=eNodeB_3GPP) { + while (*ru->ru_mask>0 && ru->function!=eNodeB_3GPP) { usleep(1e6); LOG_D(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__); } @@ -1185,21 +1126,22 @@ void wakeup_L1s(RU_t *ru) { L1_proc_t *proc = &eNB->proc; struct timespec t; LOG_D(PHY, "wakeup_L1s (num %d) for RU %d (%d.%d) ru->eNB_top:%p\n", ru->num_eNB, ru->idx, ru->proc.frame_rx, ru->proc.tti_rx, ru->eNB_top); - // call eNB function directly char string[20]; sprintf(string, "Incoming RU %d", ru->idx); + + // call eNB function directly VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.tti_rx); AssertFatal(0==pthread_mutex_lock(&proc->mutex_RU),""); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 1); - //printf("wakeup_L1s: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask[%d] %x\n", - // ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,ru->wait_cnt,ru->proc.subframe_rx,proc->RU_mask[ru->proc.subframe_rx]); + //LOG_I(PHY,"wakeup_L1s: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask[%d] %x\n", + // ru->proc.frame_rx,ru->proc.tti_rx,ru->idx,ru->wait_cnt,ru->proc.tti_rx,proc->RU_mask[ru->proc.tti_rx]); //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx); - //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.subframe_rx); + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.tti_rx); clock_gettime(CLOCK_MONOTONIC, &ru->proc.t[ru->proc.tti_rx]); if (proc->RU_mask[ru->proc.tti_rx] == 0) { - //clock_gettime(CLOCK_MONOTONIC,&proc->t[ru->proc.subframe_rx]); + //clock_gettime(CLOCK_MONOTONIC,&proc->t[ru->proc.tti_rx]); proc->t[ru->proc.tti_rx] = ru->proc.t[ru->proc.tti_rx]; //start_meas(&proc->ru_arrival_time); LOG_D(PHY,"RU %d starting timer for frame %d subframe %d\n", ru->idx, ru->proc.frame_rx, ru->proc.tti_rx); @@ -1212,13 +1154,13 @@ void wakeup_L1s(RU_t *ru) { eNB->RU_list[i]->idx, eNB->RU_list[i]->proc.frame_rx, eNB->RU_list[i]->proc.tti_rx, ru_states[eNB->RU_list[i]->state]); if (ru == eNB->RU_list[i] && eNB->RU_list[i]->wait_cnt == 0) { - //AssertFatal((proc->RU_mask&(1<Mod_id,ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask); + //AssertFatal((proc->RU_mask&(1<Mod_id,ru->proc.frame_rx,ru->proc.tti_rx,ru->idx,eNB->num_RU,proc->RU_mask); proc->RU_mask[ru->proc.tti_rx] |= (1<RU_list[i]->state == RU_SYNC ||*/(eNB->RU_list[i]->is_slave==1 && eNB->RU_list[i]->wait_cnt>0 && ru!=eNB->RU_list[i] && ru->is_slave==0) ) { + } else if (eNB->RU_list[i]->state == RU_SYNC ||(eNB->RU_list[i]->is_slave==1 && eNB->RU_list[i]->wait_cnt>0 && ru!=eNB->RU_list[i] /*&& ru->is_slave==0*/) ) { proc->RU_mask[ru->proc.tti_rx] |= (1<cnt %d, i->cnt %d\n",ru->idx,ru->proc.subframe_rx,proc->RU_mask[ru->proc.subframe_rx],i,ru->proc.frame_rx,ru->is_slave,ru->wait_cnt,eNB->RU_list[i]->wait_cnt); + //LOG_I(PHY,"RU %d, RU_mask[%d] %d, i %d, frame %d, slave %d, ru->cnt %d, i->cnt %d\n",ru->idx,ru->proc.tti_rx,proc->RU_mask[ru->proc.tti_rx],i,ru->proc.frame_rx,ru->is_slave,ru->wait_cnt,eNB->RU_list[i]->wait_cnt); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_RU, proc->RU_mask[ru->proc.tti_rx]); if (ru->is_slave == 0 && ( (proc->RU_mask[ru->proc.tti_rx]&(1<RU_list[i]->state == RU_RUN) { //This is master & the RRU has already been received @@ -1233,21 +1175,21 @@ void wakeup_L1s(RU_t *ru) { } //clock_gettime(CLOCK_MONOTONIC,&t); - //LOG_I(PHY,"RU mask is now %x, time is %lu\n",proc->RU_mask[ru->proc.subframe_rx], t.tv_nsec - proc->t[ru->proc.subframe_rx].tv_nsec); + //LOG_I(PHY,"RU mask is now %x, time is %lu\n",proc->RU_mask[ru->proc.tti_rx], t.tv_nsec - proc->t[ru->proc.tti_rx].tv_nsec); if (proc->RU_mask[ru->proc.tti_rx] == (1<num_RU)-1) { // all RUs have provided their information so continue on and wakeup eNB top LOG_D(PHY,"ru_mask is %d \n ", proc->RU_mask[ru->proc.tti_rx]); LOG_D(PHY,"the number of RU is %d, the current ru is RU %d \n ", (1<num_RU)-1, ru->idx); - LOG_D(PHY,"ru->proc.subframe_rx is %d \n", ru->proc.tti_rx); + LOG_D(PHY,"ru->proc.tti_rx is %d \n", ru->proc.tti_rx); LOG_D(PHY,"Resetting mask frame %d, subframe %d, this is RU %d\n", ru->proc.frame_rx, ru->proc.tti_rx, ru->idx); proc->RU_mask[ru->proc.tti_rx] = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_RU, proc->RU_mask[ru->proc.tti_rx]); clock_gettime(CLOCK_MONOTONIC,&t); //stop_meas(&proc->ru_arrival_time); - /*AssertFatal(t.tv_nsec < proc->t[ru->proc.subframe_rx].tv_nsec+5000000, "Time difference for subframe %d (Frame %d) => %lu > 5ms, this is RU %d\n", - ru->proc.subframe_rx, ru->proc.frame_rx, t.tv_nsec - proc->t[ru->proc.subframe_rx].tv_nsec, ru->idx);*/ + /*AssertFatal(t.tv_nsec < proc->t[ru->proc.tti_rx].tv_nsec+5000000, "Time difference for subframe %d (Frame %d) => %lu > 5ms, this is RU %d\n", + ru->proc.tti_rx, ru->proc.frame_rx, t.tv_nsec - proc->t[ru->proc.tti_rx].tv_nsec, ru->idx);*/ //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx); - //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.subframe_rx); + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.tti_rx); AssertFatal(0==pthread_mutex_unlock(&proc->mutex_RU),""); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 0 ); // unlock RUs that are waiting for eNB processing to be completed @@ -1280,8 +1222,8 @@ void wakeup_L1s(RU_t *ru) { } // pthread_mutex_unlock(&proc->mutex_RU); - // LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.subframe_rx); - // ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string); + // LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.tti_rx); + // ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string); ru->proc.emulate_rf_busy = 0; } @@ -1350,34 +1292,34 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { LTE_DL_FRAME_PARMS *fp = ru->frame_parms; openair0_config_t *cfg = &ru->openair0_cfg; - //printf("////////////////numerology in config = %d\n",numerology); + //LOG_I(PHY,"////////////////numerology in config = %d\n",numerology); int numerology = get_softmodem_params()->numerology; if(fp->N_RB_DL == 100) { - if(numerology == 0) { + if(ru->numerology == 0) { if (fp->threequarter_fs) { cfg->sample_rate=23.04e6; cfg->samples_per_frame = 230400; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; } else { cfg->sample_rate=30.72e6; cfg->samples_per_frame = 307200; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; } - } else if(numerology == 1) { + } else if(ru->numerology == 1) { cfg->sample_rate=61.44e6; cfg->samples_per_frame = 307200; cfg->tx_bw = 20e6; cfg->rx_bw = 20e6; - } else if(numerology == 2) { + } else if(ru->numerology == 2) { cfg->sample_rate=122.88e6; cfg->samples_per_frame = 307200; cfg->tx_bw = 40e6; cfg->rx_bw = 40e6; } else { - printf("Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology); + LOG_I(PHY,"Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology); cfg->sample_rate=30.72e6; cfg->samples_per_frame = 307200; cfg->tx_bw = 10e6; @@ -1386,13 +1328,13 @@ void fill_rf_config(RU_t *ru, } else if(fp->N_RB_DL == 50) { cfg->sample_rate=15.36e6; cfg->samples_per_frame = 153600; - cfg->tx_bw = 5e6; - cfg->rx_bw = 5e6; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; } else if (fp->N_RB_DL == 25) { cfg->sample_rate=7.68e6; cfg->samples_per_frame = 76800; - cfg->tx_bw = 2.5e6; - cfg->rx_bw = 2.5e6; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; } else if (fp->N_RB_DL == 6) { cfg->sample_rate=1.92e6; cfg->samples_per_frame = 19200; @@ -1416,7 +1358,7 @@ void fill_rf_config(RU_t *ru, cfg->tx_gain[i] = (double)ru->att_tx; cfg->rx_gain[i] = ru->max_rxgain-(double)ru->att_rx; cfg->configFilename = rf_config_file; - printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", + LOG_I(PHY,"channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", i, cfg->tx_gain[i], cfg->rx_gain[i], cfg->tx_freq[i], @@ -1437,9 +1379,9 @@ int setup_RU_buffers(RU_t *ru) { if (ru) { frame_parms = ru->frame_parms; - printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + LOG_I(PHY,"setup_RU_buffers: frame_parms = %p\n",frame_parms); } else { - printf("RU not initialized (NULL pointer)\n"); + LOG_I(PHY,"RU not initialized (NULL pointer)\n"); return(-1); } @@ -1462,7 +1404,7 @@ int setup_RU_buffers(RU_t *ru) { ru->sf_extension /= 4; ru->end_of_burst_delay /= 4; } else { - printf("not handled, todo\n"); + LOG_I(PHY,"not handled, todo\n"); exit(1); } } else { @@ -1476,13 +1418,13 @@ int setup_RU_buffers(RU_t *ru) { for (i=0; inb_rx; i++) { card = i/4; ant = i%4; - printf("Mapping RU id %d, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + LOG_I(PHY,"Mapping RU id %d, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); free(ru->common.rxdata[i]); ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain+ant]; - printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); + LOG_I(PHY,"rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); for (j=0; j<16; j++) { - printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); + LOG_I(PHY,"rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); ru->common.rxdata[i][j] = 16-j; } } @@ -1490,13 +1432,13 @@ int setup_RU_buffers(RU_t *ru) { for (i=0; inb_tx; i++) { card = i/4; ant = i%4; - printf("Mapping RU id %d, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + LOG_I(PHY,"Mapping RU id %d, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); free(ru->common.txdata[i]); ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant]; - printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); + LOG_I(PHY,"txdata[%d] @ %p\n",i,ru->common.txdata[i]); for (j=0; j<16; j++) { - printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); + LOG_I(PHY,"txbuffer %d: %x\n",j,ru->common.txdata[i][j]); ru->common.txdata[i][j] = 16-j; } } @@ -1570,36 +1512,43 @@ static void *ru_thread_tx( void *param ) { LOG_D(PHY,"ru_thread_tx (ru %d): Waiting for TX processing\n",ru->idx); // wait until eNBs are finished subframe RX n and TX n+4 wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx"); - LOG_D(PHY,"ru_thread_tx: TX in %d.%d\n",ru->proc.frame_tx,ru->proc.tti_tx); + ret = pthread_mutex_lock(&proc->mutex_eNBs); + AssertFatal(ret == 0,"mutex_lock return %d\n",ret); + int frame_tx=proc->frame_tx; + int tti_tx =proc->tti_tx; + uint64_t timestamp_tx = proc->timestamp_tx; + ret = pthread_mutex_unlock(&proc->mutex_eNBs); + AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + if (oai_exit) break; // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); + if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); // do OFDM if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx); + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx); - if(!(get_softmodem_params()->emulate_rf)) { //if(!emulate_rf){ + if(!(ru->emulate_rf)) { //if(!emulate_rf){ // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx); if (ru->fh_north_out) ru->fh_north_out(ru); } else { for (int i=0; inb_tx; i++) { - if(proc->frame_tx == 2) { - sprintf(filename,"txdataF%d_frame%d_sf%d.m",i,proc->frame_tx,proc->tti_tx); + if(frame_tx == 2) { + sprintf(filename,"txdataF%d_frame%d_sf%d.m",i,frame_tx,tti_tx); LOG_M(filename,"txdataF_frame",ru->common.txdataF_BF[i],fp->symbols_per_tti*fp->ofdm_symbol_size, 1, 1); } - if(proc->frame_tx == 2 && proc->tti_tx==0) { - sprintf(filename,"txdata%d_frame%d.m",i,proc->frame_tx); + if(frame_tx == 2 && tti_tx==0) { + sprintf(filename,"txdata%d_frame%d.m",i,frame_tx); LOG_M(filename,"txdata_frame",ru->common.txdata[i],fp->samples_per_tti*10, 1, 1); } } } - LOG_D(PHY,"ru_thread_tx: releasing RU TX in %d.%d\n", proc->frame_tx, proc->tti_tx); + LOG_D(PHY,"ru_thread_tx: releasing RU TX in %d.%d\n", frame_tx, tti_tx); release_thread(&proc->mutex_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx"); for(int i = 0; inum_eNB; i++) { @@ -1615,7 +1564,7 @@ static void *ru_thread_tx( void *param ) { eNB->Mod_id,eNB_proc->frame_rx,eNB_proc->subframe_rx,ru->idx,eNB->num_RU,eNB_proc->RU_mask_tx); eNB_proc->RU_mask_tx |= (1<RU_list[j]->state==RU_SYNC ||*/ (eNB->RU_list[j]->is_slave==1 && eNB->RU_list[j]->wait_cnt>0 && ru!=eNB->RU_list[j] && ru->is_slave==0)) { + } else if (eNB->RU_list[j]->state==RU_SYNC ||(eNB->RU_list[j]->is_slave==1 && eNB->RU_list[j]->wait_cnt>0 && ru!=eNB->RU_list[j])) { eNB_proc->RU_mask_tx |= (1<RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return - //printf("Not all RUs have provided their info (mask = %d), RU %d, num_RUs %d\n", eNB_proc->RU_mask_tx,ru->idx,eNB->num_RU); + //LOG_I(PHY,"Not all RUs have provided their info (mask = %d), RU %d, num_RUs %d\n", eNB_proc->RU_mask_tx,ru->idx,eNB->num_RU); AssertFatal((ret=pthread_mutex_unlock(&eNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); } else { // all RUs TX are finished so send the ready signal to eNB processing eNB_proc->RU_mask_tx = 0; @@ -1631,7 +1580,7 @@ static void *ru_thread_tx( void *param ) { AssertFatal((ret=pthread_mutex_unlock(&eNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); AssertFatal((ret=pthread_mutex_lock( &L1_proc->mutex_RUs))==0,"mutex_lock returns %d\n",ret); L1_proc->instance_cnt_RUs = 0; - LOG_D(PHY,"ru_thread_tx: Signaling RU TX done in %d.%d\n", proc->frame_tx, proc->tti_tx); + LOG_D(PHY,"ru_thread_tx: Signaling RU TX done in %d.%d\n", frame_tx, tti_tx); // the thread can now be woken up LOG_D(PHY,"ru_thread_tx: clearing mask and Waking up L1 thread\n"); @@ -1644,7 +1593,7 @@ static void *ru_thread_tx( void *param ) { } } - //printf("ru_thread_tx: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask_tx %d\n", + //LOG_I(PHY,"ru_thread_tx: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask_tx %d\n", //eNB_proc->frame_rx,eNB_proc->subframe_rx,ru->idx,ru->wait_cnt,eNB_proc->RU_mask_tx); } @@ -1676,47 +1625,41 @@ static void *ru_thread( void *param ) { LOG_I(PHY,"Starting RU %d (%s,%s),\n", ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]); if(get_softmodem_params()->emulate_rf) { - fill_rf_config(ru,ru->rf_config_file); - init_frame_parms(ru->frame_parms,1); phy_init_RU(ru); if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); + LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); exit(-1); } LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); - AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(ru->ru_mutex))==0,"mutex_lock returns %d\n",ret); + *ru->ru_mask &= ~(1<idx); + pthread_cond_signal(ru->ru_cond); + AssertFatal((ret=pthread_mutex_unlock(ru->ru_mutex))==0,"mutex_unlock returns %d\n",ret); ru->state = RU_RUN; } else if (ru->has_ctrl_prt == 0) { // There is no control port: start everything here - LOG_I(PHY, "RU %d has not ctrl port\n",ru->idx); + LOG_I(PHY, "RU %d has no OAI ctrl port\n",ru->idx); - if (ru->if_south == LOCAL_RF) { - fill_rf_config(ru,ru->rf_config_file); - init_frame_parms(ru->frame_parms,1); - ru->frame_parms->nb_antennas_rx = ru->nb_rx; - phy_init_RU(ru); - openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + ru->frame_parms->nb_antennas_rx = ru->nb_rx; - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } + if (ru->if_south == LOCAL_RF) openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret); + phy_init_RU(ru); + + + if (setup_RU_buffers(ru)!=0) { + LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); + exit(-1); } - AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(ru->ru_mutex))==0,"mutex_lock returns %d\n",ret); + *ru->ru_mask &= ~(1<idx); + pthread_cond_signal(ru->ru_cond); + AssertFatal((ret=pthread_mutex_unlock(ru->ru_mutex))==0,"mutex_unlock returns %d\n",ret); ru->state = RU_RUN; } @@ -1725,6 +1668,17 @@ static void *ru_thread( void *param ) { pthread_cond_signal(&proc->cond_FH1); AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_FH1))==0,"mutex_unlock returns %d\n",ret); + if(usrp_tx_thread == 1){ + if (ru->start_write_thread){ + if(ru->start_write_thread(ru) != 0){ + LOG_E(HW,"Could not start tx write thread\n"); + } + else{ + LOG_I(PHY,"tx write thread ready\n"); + } + } + } + while (!oai_exit) { if (ru->if_south != LOCAL_RF && ru->is_slave==1) { ru->wait_cnt = 100; @@ -1735,19 +1689,21 @@ static void *ru_thread( void *param ) { // wait to be woken up if (ru->function!=eNodeB_3GPP && ru->has_ctrl_prt == 1) { + LOG_D(PHY,"RU %d: Waiting for control thread to say go\n",ru->idx); if (wait_on_condition(&ru->proc.mutex_ru,&ru->proc.cond_ru_thread,&ru->proc.instance_cnt_ru,"ru_thread")<0) break; - } else wait_sync("ru_thread"); + } else wait_sync("ru_thread"); + LOG_D(PHY,"RU %d: Got start from control thread\n",ru->idx); - if(!(get_softmodem_params()->emulate_rf)) { + if(!(ru->emulate_rf)) { if (ru->is_slave == 0) AssertFatal(ru->state == RU_RUN,"ru-%d state = %s != RU_RUN\n",ru->idx,ru_states[ru->state]); else if (ru->is_slave == 1) AssertFatal(ru->state == RU_SYNC || ru->state == RU_RUN || ru->state == RU_CHECK_SYNC,"ru %d state = %s != RU_SYNC or RU_RUN or RU_CHECK_SYNC\n",ru->idx,ru_states[ru->state]); // Start RF device if any if (ru->start_rf) { - if (ru->start_rf(ru) != 0) - LOG_E(HW,"Could not start the RF device\n"); - else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + if (ru->start_rf(ru) != 0) + AssertFatal(1==0,"Could not start the RF device\n"); + else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_D(PHY,"RU %d no rf device\n",ru->idx); } @@ -1764,7 +1720,7 @@ static void *ru_thread( void *param ) { // if this is a slave RRU, try to synchronize on the DL frequency if ((ru->is_slave == 1) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); - LOG_D(PHY,"Starting steady-state operation\n"); + if (ru->state == RU_RUN || ru->state == RU_CHECK_SYNC) LOG_I(PHY,"RU %d Starting steady-state operation\n",ru->idx); // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (ru->state == RU_RUN || ru->state == RU_CHECK_SYNC) { @@ -1781,7 +1737,6 @@ static void *ru_thread( void *param ) { // synchronization on input FH interface, acquire signals/data and block if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&subframe); else AssertFatal(1==0, "No fronthaul interface at south port"); - #ifdef PHY_TX_THREAD if(first_phy_tx == 0) { @@ -1826,14 +1781,14 @@ static void *ru_thread( void *param ) { ru->wait_cnt--; LOG_D(PHY,"RU thread %d, frame %d, subframe %d, wait_cnt %d \n",ru->idx, frame, subframe, ru->wait_cnt); - if (ru->if_south!=LOCAL_RF && ru->wait_cnt <=20 && subframe == 5 && frame != RC.ru[0]->proc.frame_rx && resynch_done == 0) { + if (ru->if_south!=LOCAL_RF && ru->wait_cnt <=20 && subframe == 5 && frame != ru->ru0->proc.frame_rx && resynch_done == 0) { // Send RRU_frame adjust RRU_CONFIG_msg_t rru_config_msg; rru_config_msg.type = RRU_frame_resynch; rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len - ((uint16_t *)&rru_config_msg.msg[0])[0] = RC.ru[0]->proc.frame_rx; + ((uint16_t *)&rru_config_msg.msg[0])[0] = ru->ru0->proc.frame_rx; ru->cmd=WAIT_RESYNCH; - LOG_I(PHY,"Sending Frame Resynch %d to RRU %d\n", RC.ru[0]->proc.frame_rx,ru->idx); + LOG_I(PHY,"Sending Frame Resynch %d to RRU %d\n", ru->ru0->proc.frame_rx,ru->idx); AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),"Failed to send msg to RAU\n"); resynch_done=1; } @@ -1891,9 +1846,9 @@ static void *ru_thread( void *param ) { #ifdef MBMS_EXPERIMENTAL //Workaround ... this must be properly handled - if(ru->if_south==LOCAL_RF && ru->function==eNodeB_3GPP && RC.eNB[0][0]!=NULL){ - if(ru->frame_parms->num_MBSFN_config!=RC.eNB[0][0]->frame_parms.num_MBSFN_config){ - ru->frame_parms = &RC.eNB[0][0]->frame_parms;//->frame_parms; + if(ru->if_south==LOCAL_RF && ru->function==eNodeB_3GPP && ru->eNB_list[0]!=NULL){ + if(ru->frame_parms->num_MBSFN_config!=ru->eNB_list[0]->frame_parms.num_MBSFN_config){ + ru->frame_parms = &ru->eNB_list[0]->frame_parms;//->frame_parms; LOG_W(PHY,"RU MBSFN SF PARAMS Updated\n"); } } @@ -1908,7 +1863,7 @@ static void *ru_thread( void *param ) { // do OFDM if needed if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru, proc->frame_tx, proc->tti_tx); - if(!(get_softmodem_params()->emulate_rf)) { //if(!emulate_rf){ + if(!(ru->emulate_rf)) { //if(!emulate_rf){ // do outgoing fronthaul (south) if needed if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru, proc->frame_tx, proc->tti_tx, proc->timestamp_tx); @@ -1942,12 +1897,12 @@ static void *ru_thread( void *param ) { #endif } // else wait_cnt == 0 - } // ru->state = RU_RUN + } // ru->state = RU_RUN || RU_CHECK_SYNC } // while !oai_exit - printf( "Exiting ru_thread \n"); + LOG_I(PHY, "Exiting ru_thread \n"); - if (!(get_softmodem_params()->emulate_rf)) { + if (!(ru->emulate_rf)) { if (ru->stop_rf != NULL) { if (ru->stop_rf(ru) != 0) LOG_E(HW,"Could not stop the RF device\n"); @@ -1962,7 +1917,7 @@ static void *ru_thread( void *param ) { // This thread run the initial synchronization like a UE void *ru_thread_synch(void *arg) { RU_t *ru = (RU_t *)arg; - LTE_DL_FRAME_PARMS *fp = ru->frame_parms; + LTE_DL_FRAME_PARMS *fp; int64_t peak_val, avg; static int ru_thread_synch_status = 0; int cnt=0; @@ -1971,6 +1926,8 @@ void *ru_thread_synch(void *arg) { // initialize variables for PSS detection ru_sync_time_init(ru); //lte_sync_time_init(ru->frame_parms); + fp = ru->frame_parms; + int last_rxoff=0; while (!oai_exit) { // wait to be woken up if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break; @@ -1984,17 +1941,18 @@ void *ru_thread_synch(void *arg) { &avg); LOG_I(PHY,"RU synch cnt %d: %d, val %llu (%d dB,%d dB)\n",cnt,ru->rx_offset,(unsigned long long)peak_val,dB_fixed64(peak_val),dB_fixed64(avg)); cnt++; - - //if (/*ru->rx_offset >= 0*/dB_fixed(peak_val)>=85 && cnt>10) { - if (ru->rx_offset >= 0 && avg>0 && dB_fixed(peak_val/avg)>=15 && cnt>10) { + int abs_diff= ru->rx_offset - last_rxoff; + if (abs_diff<0) abs_diff=-abs_diff; + if (ru->rx_offset >= 0 && abs_diff<6 && avg>0 && dB_fixed(peak_val/avg)>=15 && cnt>10) { LOG_I(PHY,"Estimated peak_val %d dB, avg %d => timing offset %llu\n",dB_fixed(peak_val),dB_fixed(avg),(unsigned long long int)ru->rx_offset); ru->in_synch = 1; - /* + /* LOG_M("ru_sync_rx.m","rurx",&ru->common.rxdata[0][0],LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,1); LOG_M("ru_sync_corr.m","sync_corr",ru->dmrs_corr,LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_tti,1,6); LOG_M("ru_dmrs.m","rudmrs",&ru->dmrssync[0],fp->ofdm_symbol_size,1,1); - */ - //exit(-1); + + exit(-1); + */ } // sync_pos > 0 else { //AssertFatal(cnt<1000,"Cannot find synch reference\n"); if (cnt>200) { @@ -2004,6 +1962,7 @@ void *ru_thread_synch(void *arg) { exit(-1); } } + last_rxoff=ru->rx_offset; } // ru->in_synch==0 if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break; @@ -2017,6 +1976,7 @@ void *ru_thread_synch(void *arg) { #if defined(PRE_SCD_THREAD) void *pre_scd_thread( void *param ) { + void rlc_tick(int, int); static int eNB_pre_scd_status; protocol_ctxt_t ctxt; int frame; @@ -2051,6 +2011,7 @@ void *pre_scd_thread( void *param ) { AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"mutex_unlock returns %d\n",ret); PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, Mod_id, ENB_FLAG_YES, NOT_A_RNTI, frame, subframe,Mod_id); + rlc_tick(frame, subframe); pdcp_run(&ctxt); for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { @@ -2165,7 +2126,7 @@ static void *rf_tx( void *param ) { // do OFDM if needed if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx); - if(!emulate_rf) { + if(!ru->emulate_rf) { // do outgoing fronthaul (south) if needed if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); @@ -2188,6 +2149,12 @@ static void *rf_tx( void *param ) { #endif + +int start_streaming(RU_t *ru) { + LOG_I(PHY,"Starting streaming on third-party RRU\n"); + return(ru->ifdevice.thirdparty_startstreaming(&ru->ifdevice)); +} + int start_if(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB) { return(ru->ifdevice.trx_start_func(&ru->ifdevice)); } @@ -2231,9 +2198,12 @@ void reset_proc(RU_t *ru) { for (i=0; i<10; i++) proc->symbol_mask[i]=0; } +int start_write_thread(RU_t *ru) { + return(ru->rfdevice.trx_write_init(&ru->rfdevice)); +} void init_RU_proc(RU_t *ru) { - int i=0, ret; + int i=0; RU_proc_t *proc; pthread_attr_t *attr_FH=NULL, *attr_FH1=NULL, *attr_prach=NULL, *attr_asynch=NULL, *attr_synch=NULL, *attr_emulateRF=NULL, *attr_ctrl=NULL, *attr_prach_br=NULL; //pthread_attr_t *attr_fep=NULL; @@ -2302,7 +2272,17 @@ void init_RU_proc(RU_t *ru) { attr_prach_br = &proc->attr_prach_br; #endif - if (ru->function!=eNodeB_3GPP) pthread_create( &proc->pthread_ctrl, attr_ctrl, ru_thread_control, (void *)ru ); + if (ru->has_ctrl_prt == 1) pthread_create( &proc->pthread_ctrl, attr_ctrl, ru_thread_control, (void*)ru ); + else { + if (ru->start_if) { + LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx); + AssertFatal( + ru->start_if(ru,NULL) == 0, "Could not start the IF device\n"); + + if (ru->if_south != LOCAL_RF) wait_eNBs(); + } + } + pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void *)ru ); #if defined(PRE_SCD_THREAD) @@ -2318,7 +2298,7 @@ void init_RU_proc(RU_t *ru) { pthread_create( &proc->pthread_rf_tx, NULL, rf_tx, (void *)ru ); #endif - if (get_softmodem_params()->emulate_rf) + if (ru->emulate_rf) pthread_create( &proc->pthread_emulateRF, attr_emulateRF, emulatedRF_thread, (void *)proc ); if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) @@ -2341,23 +2321,6 @@ void init_RU_proc(RU_t *ru) { LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void *)ru ); ru->state=RU_RUN; - if(!get_softmodem_params()->emulate_rf) - { - fill_rf_config(ru,ru->rf_config_file); - init_frame_parms(ru->frame_parms,1); - ru->frame_parms->nb_antennas_rx = ru->nb_rx; - phy_init_RU(ru); - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - if (ret < 0) { - LOG_I(PHY,"Exiting, cannot load device. Make sure that your SDR board is connected!\n"); - exit(1); - } - - if (setup_RU_buffers(ru)!=0) { - LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); - exit(1); - } - } } if (get_thread_worker_conf() == WORKER_ENABLE) { @@ -2366,15 +2329,16 @@ void init_RU_proc(RU_t *ru) { } if (opp_enabled == 1) pthread_create(&ru->ru_stats_thread,NULL,ru_stats_thread,(void *)ru); - +/* if (ru->function == eNodeB_3GPP) { usleep(10000); LOG_I(PHY, "Signaling main thread that RU %d (is_slave %d,send_dmrs %d) is ready in state %s\n",ru->idx,ru->is_slave,ru->generate_dmrs_sync,ru_states[ru->state]); - AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(ru->ru_mutex))==0,"mutex_lock returns %d\n",ret); + *ru->ru_mask &= ~(1<idx); + pthread_cond_signal(ru->ru_cond); + AssertFatal((ret=pthread_mutex_unlock(ru->ru_mutex))==0,"mutex_unlock returns %d\n",ret); } + */ } @@ -2500,22 +2464,22 @@ void kill_RU_proc(RU_t *ru) { } -void init_precoding_weights(PHY_VARS_eNB *eNB) { - int layer,ru_id,aa,re,ue,tb; +void init_precoding_weights(RU_t **rup,int nb_RU,PHY_VARS_eNB *eNB) { + int layer,ru_id,aa,re,tb; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; RU_t *ru; LTE_eNB_DLSCH_t *dlsch; // init precoding weigths - for (ue=0; uedlsch[ue][tb]; + dlsch = eNB->dlsch[dlsch_id][tb]; for (layer=0; layer<4; layer++) { int nb_tx=0; - for (ru_id=0; ru_idnb_tx; } @@ -2537,6 +2501,7 @@ void init_precoding_weights(PHY_VARS_eNB *eNB) { void set_function_spec_param(RU_t *ru) { int ret; + switch (ru->if_south) { case LOCAL_RF: // this is an RU with integrated RF (RRU, eNB) if (ru->function == NGFI_RRU_IF5) { // IF5 RRU @@ -2557,10 +2522,10 @@ void set_function_spec_param(RU_t *ru) { reset_meas(&ru->compression); reset_meas(&ru->transport); ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); + LOG_I(PHY,"NGFI_RRU_IF5: openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); + LOG_I(PHY,"Exiting, cannot initialize transport protocol\n"); exit(-1); } } else if (ru->function == NGFI_RRU_IF4p5) { @@ -2581,10 +2546,10 @@ void set_function_spec_param(RU_t *ru) { reset_meas(&ru->compression); reset_meas(&ru->transport); ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); + LOG_I(PHY,"NGFI_RRU_if4p5 : openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); + LOG_I(PHY,"Exiting, cannot initialize transport protocol\n"); exit(-1); } @@ -2598,13 +2563,14 @@ void set_function_spec_param(RU_t *ru) { ru->fh_north_out = NULL; // no outgoing fronthaul to north ru->start_if = NULL; // no if interface ru->rfdevice.host_type = RAU_HOST; + ru->start_write_thread = start_write_thread; } ru->fh_south_in = rx_rf; // local synchronous RF RX ru->fh_south_out = tx_rf; // local synchronous RF TX ru->start_rf = start_rf; // need to start the local RF interface ru->stop_rf = stop_rf; - printf("configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf); + LOG_I(PHY,"NFGI_RRU_IF4p5: configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf); /* if (ru->function == eNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise fill_rf_config(ru,rf_config_file); @@ -2614,7 +2580,7 @@ void set_function_spec_param(RU_t *ru) { ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); + LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); exit(-1); }*/ break; @@ -2627,25 +2593,22 @@ void set_function_spec_param(RU_t *ru) { if (ru->if_timing == synch_to_other) { ru->fh_south_in = fh_slave_south_in; // synchronize to master - ru->fh_south_out = fh_if5_mobipass_south_out; // use send_IF5 for mobipass - ru->fh_south_asynch_in = fh_if5_south_asynch_in_mobipass; // UL is asynchronous } else { ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission ru->fh_south_asynch_in = NULL; // no asynchronous UL } - - ru->start_rf = NULL; // no local RF + ru->start_rf = ru->eth_params.transp_preference == ETH_UDP_IF5_ECPRI_MODE ? start_streaming : NULL; ru->stop_rf = NULL; ru->start_if = start_if; // need to start if interface for IF5 ru->ifdevice.host_type = RAU_HOST; ru->ifdevice.eth_params = &ru->eth_params; ru->ifdevice.configure_rru = configure_ru; ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); + LOG_I(PHY,"REMOTE_IF5: openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); + LOG_I(PHY,"Exiting, cannot initialize transport protocol\n"); exit(-1); } @@ -2668,76 +2631,88 @@ void set_function_spec_param(RU_t *ru) { ru->ifdevice.eth_params = &ru->eth_params; ru->ifdevice.configure_rru = configure_ru; ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); + LOG_I(PHY,"REMOTE IF4p5: openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); + LOG_I(PHY,"Exiting, cannot initialize transport protocol\n"); exit(-1); } + if (ru->ifdevice.get_internal_parameter != NULL) { + void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in"); + if (t != NULL) + ru->fh_south_in = t; + t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out"); + if (t != NULL) + ru->fh_south_out = t; + } + malloc_IF4p5_buffer(ru); + break; default: LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); break; } // switch on interface type + } -//extern void RCconfig_RU(void); +void init_RU0(RU_t *ru,int ru_id,char *rf_config_file, int send_dmrssync) { + ru->rf_config_file = rf_config_file; + ru->idx = ru_id; + ru->ts_offset = 0; + + if (ru->is_slave == 1) { + ru->in_synch = 0; + ru->generate_dmrs_sync = 0; + } else { + ru->in_synch = 1; + ru->generate_dmrs_sync = send_dmrssync; + } + + ru->cmd = EMPTY; + ru->south_out_cnt = 0; + // use eNB_list[0] as a reference for RU frame parameters + // NOTE: multiple CC_id are not handled here yet! + + //ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0; + if ((ru->is_slave == 0) && (ru->ota_sync_enable == 1)) + ru->generate_dmrs_sync = 1; + else + ru->generate_dmrs_sync = 0; + + ru->wakeup_L1_sleeptime = 2000; + ru->wakeup_L1_sleep_cnt_max = 3; + -void init_RU(char *rf_config_file, int send_dmrssync) { +} + +// This part if on eNB side +void init_RU(RU_t **rup,int nb_RU,PHY_VARS_eNB ***eNBp,int nb_L1,int *nb_CC,char *rf_config_file, int send_dmrssync) { int ru_id, i, CC_id; RU_t *ru; PHY_VARS_eNB *eNB0 = (PHY_VARS_eNB *)NULL; LTE_DL_FRAME_PARMS *fp = (LTE_DL_FRAME_PARMS *)NULL; // create status mask - RC.ru_mask= (1 << RC.nb_RU) - 1; - pthread_mutex_init(&RC.ru_mutex,NULL); - pthread_cond_init(&RC.ru_cond,NULL); + if (nb_CC != NULL) + for (i=0; inum_RU=0; - if (RC.nb_CC != 0) - for (i=0; inum_RU=0; - - LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); - - for (ru_id=0; ru_idrf_config_file = rf_config_file; - ru->idx = ru_id; - ru->ts_offset = 0; - - if (ru->is_slave == 1) { - ru->in_synch = 0; - ru->generate_dmrs_sync = 0; - } else { - ru->in_synch = 1; - ru->generate_dmrs_sync = send_dmrssync; - } - - ru->cmd = EMPTY; - ru->south_out_cnt = 0; - // use eNB_list[0] as a reference for RU frame parameters - // NOTE: multiple CC_id are not handled here yet! - - //ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0; - if ((ru->is_slave == 0) && (ru->ota_sync_enable == 1)) - ru->generate_dmrs_sync = 1; - else - ru->generate_dmrs_sync = 0; - - ru->wakeup_L1_sleeptime = 2000; - ru->wakeup_L1_sleep_cnt_max = 3; + LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",nb_RU); + for (ru_id=0; ru_idru0 = rup[0]; if (ru->num_eNB > 0) { - LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file); - + LOG_D(PHY, "%s() ru[%d].num_eNB:%d ru->eNB_list[0]:%p eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], eNBp[0][0], ru->rf_config_file); + if (ru->eNB_list[0] == 0) { - LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n", __FUNCTION__); - ru->eNB_list[0] = RC.eNB[0][0]; + LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n", __FUNCTION__); + ru->eNB_list[0] = eNBp[0][0]; ru->num_eNB=1; // // DJP - feptx_prec() / feptx_ofdm() parses the eNB_list (based on num_eNB) and copies the txdata_F to txdata in RU @@ -2746,7 +2721,7 @@ void init_RU(char *rf_config_file, int send_dmrssync) { LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__); } } - + eNB0 = ru->eNB_list[0]; fp = ru->frame_parms; LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south); @@ -2771,6 +2746,11 @@ void init_RU(char *rf_config_file, int send_dmrssync) { LOG_I(PHY, "Initializing RRU descriptor %d : (%s,%s,%d)\n", ru_id, ru_if_types[ru->if_south], NB_timing[ru->if_timing], ru->function); set_function_spec_param(ru); + if (ru->function != NGFI_RRU_IF4p5 && ru->function != NGFI_RRU_IF5) { + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + } + LOG_I(PHY, "Starting ru_thread %d, is_slave %d, send_dmrs %d\n", ru_id, ru->is_slave, ru->generate_dmrs_sync); init_RU_proc(ru); } // for ru_id @@ -2784,7 +2764,7 @@ void stop_ru(RU_t *ru) { #if defined(PRE_SCD_THREAD) || defined(PHY_TX_THREAD) int *status; #endif - printf("Stopping RU %p processing threads\n",(void *)ru); + LOG_I(PHY,"Stopping RU %p processing threads\n",(void *)ru); #if defined(PRE_SCD_THREAD) if(ru) { @@ -2815,10 +2795,10 @@ void stop_ru(RU_t *ru) { } -void stop_RU(int nb_ru) { +void stop_RU(RU_t **rup,int nb_ru) { for (int inst = 0; inst < nb_ru; inst++) { LOG_I(PHY, "Stopping RU %d processing threads\n", inst); - kill_RU_proc(RC.ru[inst]); + kill_RU_proc(rup[inst]); } } @@ -2838,8 +2818,8 @@ void init_ru_vnf(void) { pthread_mutex_init(&RC.ru_mutex,NULL); pthread_cond_init(&RC.ru_cond,NULL); // read in configuration file) - printf("configuring RU from file\n"); - RCconfig_RU(); + LOG_I(PHY,"configuring RU from file\n"); + RC.ru = RCconfig_RU(RC.nb_RU,RC.nb_L1_inst,RC.eNB,&RC.ru_mask,&RC.ru_mutex,&RC.ru_cond); LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_L1_inst,RC.nb_RU,get_nprocs()); if (RC.nb_CC != 0) @@ -2915,180 +2895,185 @@ void init_ru_vnf(void) { /* --------------------------------------------------------*/ /* from here function to use configuration module */ -void RCconfig_RU(void) { +RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond) { int i = 0; paramdef_t RUParams[] = RUPARAMS_DESC; paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL); - + RU_t **ru=NULL; if ( RUParamList.numelt > 0) { - RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); + ru = (RU_t **)malloc(nb_RU*sizeof(RU_t *)); - for (int j = 0; j < RC.nb_RU; j++) { - RC.ru[j] = (RU_t *)malloc(sizeof(RU_t)); - memset((void *)RC.ru[j],0,sizeof(RU_t)); - RC.ru[j]->idx = j; - printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]); - RC.ru[j]->if_timing = synch_to_ext_device; + for (int j = 0; j < nb_RU; j++) { + ru[j] = (RU_t *)malloc(sizeof(RU_t)); + memset((void *)ru[j],0,sizeof(RU_t)); + ru[j]->idx = j; + LOG_I(PHY,"Creating ru[%d]:%p\n", j, ru[j]); + ru[j]->if_timing = synch_to_ext_device; - if (RC.nb_L1_inst >0) - RC.ru[j]->num_eNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt; + ru[j]->ru_mask = ru_mask; + ru[j]->ru_mutex = ru_mutex; + ru[j]->ru_cond = ru_cond; + if (nb_L1_inst >0) + ru[j]->num_eNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt; else - RC.ru[j]->num_eNB = 0; + ru[j]->num_eNB = 0; - for (i=0; inum_eNB; i++) RC.ru[j]->eNB_list[i] = RC.eNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0]; + for (i=0; inum_eNB; i++) ru[j]->eNB_list[i] = eNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0]; - RC.ru[j]->has_ctrl_prt = 1; + ru[j]->has_ctrl_prt = 0; if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { - RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); + ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); } if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { - RC.ru[j]->openair0_cfg.clock_source = internal; + ru[j]->openair0_cfg.clock_source = internal; LOG_D(PHY, "RU clock source set as internal\n"); } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { - RC.ru[j]->openair0_cfg.clock_source = external; + ru[j]->openair0_cfg.clock_source = external; LOG_D(PHY, "RU clock source set as external\n"); } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { - RC.ru[j]->openair0_cfg.clock_source = gpsdo; + ru[j]->openair0_cfg.clock_source = gpsdo; LOG_D(PHY, "RU clock source set as gpsdo\n"); } else { LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); } } else { - RC.ru[j]->openair0_cfg.clock_source = unset; + ru[j]->openair0_cfg.clock_source = unset; } if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { - RC.ru[j]->openair0_cfg.time_source = internal; + ru[j]->openair0_cfg.time_source = internal; LOG_D(PHY, "RU time source set as internal\n"); } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { - RC.ru[j]->openair0_cfg.time_source = external; + ru[j]->openair0_cfg.time_source = external; LOG_D(PHY, "RU time source set as external\n"); } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { - RC.ru[j]->openair0_cfg.time_source = gpsdo; + ru[j]->openair0_cfg.time_source = gpsdo; LOG_D(PHY, "RU time source set as gpsdo\n"); } else { LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); } } else { - RC.ru[j]->openair0_cfg.time_source = unset; + ru[j]->openair0_cfg.time_source = unset; } + LOG_I(PHY,"RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr)); + + if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) ru[j]->is_slave=1; + else ru[j]->is_slave=0; + + LOG_I(PHY,"RU %d ota_sync_enabled=%s\n",j,*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr)); + + if (strcmp(*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr), "yes") == 0) ru[j]->ota_sync_enable=1; + else ru[j]->ota_sync_enable=0; + if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = eNodeB_3GPP; - RC.ru[j]->state = RU_RUN; + ru[j]->if_south = LOCAL_RF; + ru[j]->function = eNodeB_3GPP; + ru[j]->state = RU_RUN; printf("Setting function for RU %d to eNodeB_3GPP\n",j); } else { - RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); + ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); + ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); + ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); + ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); + ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); // Check if control port set if (!(config_isparamset(RUParamList.paramarray[j],RU_REMOTE_PORTC_IDX)) ) { - printf("Removing control port for RU %d\n",j); - RC.ru[j]->has_ctrl_prt = 0; + LOG_I(PHY,"Removing control port for RU %d\n",j); + ru[j]->has_ctrl_prt = 0; } else { - RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - printf(" Control port %u \n",RC.ru[j]->eth_params.my_portc); + ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); + ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); + LOG_I(PHY," Control port %u \n",ru[j]->eth_params.my_portc); } if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j); + ru[j]->if_south = LOCAL_RF; + ru[j]->function = NGFI_RRU_IF5; + ru[j]->eth_params.transp_preference = ETH_UDP_MODE; + LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j); } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j); + ru[j]->if_south = LOCAL_RF; + ru[j]->function = NGFI_RRU_IF5; + ru[j]->eth_params.transp_preference = ETH_RAW_MODE; + LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j); } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j); + ru[j]->if_south = LOCAL_RF; + ru[j]->function = NGFI_RRU_IF4p5; + ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + ru[j]->has_ctrl_prt =1; + LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j); } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j); + ru[j]->if_south = LOCAL_RF; + ru[j]->function = NGFI_RRU_IF4p5; + ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + ru[j]->has_ctrl_prt =1; + LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j); } - - printf("RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr)); - - if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1; - else RC.ru[j]->is_slave=0; - - printf("RU %d ota_sync_enabled=%s\n",j,*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr)); - - if (strcmp(*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr), "yes") == 0) RC.ru[j]->ota_sync_enable=1; - else RC.ru[j]->ota_sync_enable=0; } - RC.ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; - RC.ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); - RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; + ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; + ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); + ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ - RC.ru[j]->sf_extension = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr); + ru[j]->sf_extension = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr); - for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; + for (i=0; inum_bands; i++) ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; } //strcmp(local_rf, "yes") == 0 else { - printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); - RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); - + LOG_I(PHY,"RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); + ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); + ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); + ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); + ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); + ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); + ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); + ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); + if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; + ru[j]->if_south = REMOTE_IF5; + ru[j]->function = NGFI_RAU_IF5; + ru[j]->eth_params.transp_preference = ETH_UDP_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_ecpri_if5") == 0) { + ru[j]->if_south = REMOTE_IF5; + ru[j]->function = NGFI_RAU_IF5; + ru[j]->eth_params.transp_preference = ETH_UDP_IF5_ECPRI_MODE; } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; + ru[j]->if_south = REMOTE_IF5; + ru[j]->function = NGFI_RAU_IF5; + ru[j]->eth_params.transp_preference = ETH_RAW_MODE; } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { - RC.ru[j]->if_south = REMOTE_IF4p5; - RC.ru[j]->function = NGFI_RAU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + ru[j]->if_south = REMOTE_IF4p5; + ru[j]->function = NGFI_RAU_IF4p5; + ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + ru[j]->has_ctrl_prt = 1; } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { - RC.ru[j]->if_south = REMOTE_IF4p5; - RC.ru[j]->function = NGFI_RAU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if5_mobipass") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->if_timing = synch_to_other; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF5_MOBIPASS; + ru[j]->if_south = REMOTE_IF4p5; + ru[j]->function = NGFI_RAU_IF4p5; + ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + ru[j]->has_ctrl_prt = 1; + + if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) ru[j]->is_slave=1; + else ru[j]->is_slave=0; } - - if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1; - else RC.ru[j]->is_slave=0; } /* strcmp(local_rf, "yes") != 0 */ - - RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); - RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); - RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); - RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); + + ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); + ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); + ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); + ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); + *ru_mask= (*ru_mask)|(1< #include "rt_wrapper.h" +#include #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all @@ -56,6 +57,8 @@ //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all +#include + #include "PHY/phy_vars.h" #include "SCHED/sched_common_vars.h" #include "LAYER2/MAC/mac_vars.h" @@ -79,10 +82,6 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "enb_config.h" //#include "PHY/TOOLS/time_meas.h" -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_vars.h" -#endif - #include "create_tasks.h" @@ -100,7 +99,6 @@ pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex - uint16_t sf_ahead=4; pthread_cond_t sync_cond; @@ -161,16 +159,17 @@ void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI * AssertFatal(false, "Must not be called in this context\n"); } +RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond); + extern void reset_opp_meas(void); extern void print_opp_meas(void); -extern void init_eNB_afterRU(void); +RU_t **RCconfig_RU(int nb_RU,int nb_L1_inst,PHY_VARS_eNB ***eNB,uint64_t *ru_mask,pthread_mutex_t *ru_mutex,pthread_cond_t *ru_cond); int transmission_mode=1; int emulate_rf = 0; int numerology = 0; -int usrp_tx_thread = 0; THREAD_STRUCT thread_struct; /* struct for ethernet specific parameters given in eNB conf file */ @@ -179,6 +178,7 @@ eth_params_t *eth_params; double cpuf; int oaisim_flag=0; +uint8_t proto_agent_flag = 0; /* forward declarations */ @@ -386,7 +386,7 @@ void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) { LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n", itti_get_task_name(from), from, itti_get_task_name(to), to); MessageDef *msg; - msg = itti_alloc_new_message (from, TERMINATE_MESSAGE); + msg = itti_alloc_new_message (from, 0, TERMINATE_MESSAGE); itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); } @@ -424,7 +424,6 @@ int stop_L1L2(module_id_t enb_id) { * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2() */ int restart_L1L2(module_id_t enb_id) { - RU_t *ru = RC.ru[enb_id]; int cc_id; MessageDef *msg_p = NULL; LOG_W(ENB_APP, "restarting lte-softmodem\n"); @@ -435,10 +434,12 @@ int restart_L1L2(module_id_t enb_id) { for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) { RC.eNB[enb_id][cc_id]->configured = 0; + for (int ru_id=0;ru_idnum_RU;ru_id++) { + int ru_idx = RC.eNB[enb_id][cc_id]->RU_list[ru_id]->idx; + RC.ru_mask |= (1 << ru_idx); + set_function_spec_param(RC.ru[ru_idx]); + } } - - RC.ru_mask |= (1 << ru->idx); - set_function_spec_param(RC.ru[enb_id]); /* reset the list of connected UEs in the MAC, since in this process with * loose all UEs (have to reconnect) */ init_UE_info(&RC.mac[enb_id]->UE_info); @@ -453,15 +454,21 @@ int restart_L1L2(module_id_t enb_id) { /* pass a reconfiguration request which will configure everything down to * RC.eNB[i][j]->frame_parms, too */ - msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ); + msg_p = itti_alloc_new_message(TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ); RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); /* TODO XForms might need to be restarted, but it is currently (09/02/18) * broken, so we cannot test it */ wait_eNBs(); - init_RU_proc(ru); - ru->rf_map.card = 0; - ru->rf_map.chain = 0; /* CC_id + chain_offset;*/ + for (int cc_id=0;cc_idnum_RU;ru_id++) { + int ru_idx = RC.eNB[enb_id][cc_id]->RU_list[ru_id]->idx; + + init_RU_proc(RC.ru[ru_idx]); + RC.ru[ru_idx]->rf_map.card = 0; + RC.ru[ru_idx]->rf_map.chain = 0; /* CC_id + chain_offset;*/ + } + } wait_RUs(); init_eNB_afterRU(); printf("Sending sync to all threads\n"); @@ -514,6 +521,8 @@ int main ( int argc, char **argv ) int ru_id; int node_type = ngran_eNB; + start_background_system(); + if ( load_configmodule(argc,argv,0) == NULL) { exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); } @@ -544,14 +553,14 @@ int main ( int argc, char **argv ) cpuf=get_cpu_freq_GHz(); printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + itti_init(TASK_MAX, tasks_info); // allows to forward in wireshark L2 protocol for decoding // initialize mscgen log after ITTI if (get_softmodem_params()->start_msc) { load_module_shlib("msc",NULL,0,&msc_interface); } - MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); + MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX); init_opt(); // to make a graceful exit when ctrl-c is pressed set_softmodem_sighandler(); @@ -574,7 +583,7 @@ int main ( int argc, char **argv ) /* We need to read RU configuration before FlexRAN starts so it knows what * splits to report. Actual RU start comes later. */ if (RC.nb_RU > 0 && NFAPI_MODE != NFAPI_MODE_VNF) { - RCconfig_RU(); + RC.ru = RCconfig_RU(RC.nb_RU,RC.nb_L1_inst,RC.eNB,&RC.ru_mask,&RC.ru_mutex,&RC.ru_cond); LOG_I(PHY, "number of L1 instances %d, number of RU %d, number of CPU cores %d\n", RC.nb_L1_inst, RC.nb_RU, get_nprocs()); @@ -583,6 +592,7 @@ int main ( int argc, char **argv ) if (RC.nb_inst > 0) { /* Start the agent. If it is turned off in the configuration, it won't start */ for (i = 0; i < RC.nb_inst; i++) { + if(NFAPI_MODE != NFAPI_MODE_PNF) flexran_agent_start(i); } @@ -596,7 +606,7 @@ int main ( int argc, char **argv ) } for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) { - MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ); + MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, 0, RRC_CONFIGURATION_REQ); RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); } @@ -650,6 +660,7 @@ int main ( int argc, char **argv ) for (int x=0; x < RC.nb_L1_inst; x++) for (int CC_id=0; CC_idproc.L1_proc; + L1_rxtx_proc_t *L1proctx= &RC.eNB[x][CC_id]->proc.L1_proc_tx; L1proc->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); L1proc->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); @@ -657,9 +668,11 @@ int main ( int argc, char **argv ) initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true); else initTpool("n", L1proc->threadPool, true); - initNotifiedFIFO(L1proc->respEncode); - initNotifiedFIFO(L1proc->respDecode); - RC.eNB[x][CC_id]->proc.L1_proc_tx.threadPool = L1proc->threadPool; + initNotifiedFIFO(L1proc->respEncode); + initNotifiedFIFO(L1proc->respDecode); + L1proctx->threadPool=L1proc->threadPool; + L1proctx->respEncode=L1proc->respEncode; + L1proctx->nbEncode=L1proc->nbEncode; } @@ -674,7 +687,7 @@ int main ( int argc, char **argv ) // some initialization is necessary and init_ru_vnf do this. if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) { printf("Initializing RU threads\n"); - init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync); + init_RU(RC.ru,RC.nb_RU,RC.eNB,RC.nb_L1_inst,RC.nb_L1_CC,get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync); for (ru_id=0; ru_idrf_map.card=0; @@ -726,7 +739,7 @@ int main ( int argc, char **argv ) fflush(stderr); // end of CI modifications //getchar(); - if(IS_SOFTMODEM_DOFORMS) + if(IS_SOFTMODEM_DOSCOPE) load_softscope("enb",NULL); itti_wait_tasks_end(); oai_exit=1; @@ -734,7 +747,7 @@ int main ( int argc, char **argv ) // stop threads if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) { - if(IS_SOFTMODEM_DOFORMS) + if(IS_SOFTMODEM_DOSCOPE) end_forms(); LOG_I(ENB_APP,"stopping MODEM threads\n"); diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index 1c537dabe3..a1b261f263 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -97,7 +97,6 @@ /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_UEPARAMS_DESC { \ - {"siml1", CONFIG_HLP_SIML1, PARAMFLAG_BOOL, iptr:&simL1flag, defintval:0, TYPE_INT, 0}, \ {"U", CONFIG_HLP_NUMUE, 0, u16ptr:&NB_UE_INST, defuintval:1, TYPE_UINT16, 0}, \ {"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:130, TYPE_DOUBLE, 0}, \ {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \ @@ -171,7 +170,7 @@ extern void init_RU_proc(RU_t *ru); extern void stop_RU(int nb_ru); extern void kill_RU_proc(RU_t *ru); extern void set_function_spec_param(RU_t *ru); -extern void init_RU(char *, int send_dmrssync); +extern void init_RU(RU_t **rup,int nb_RU,PHY_VARS_eNB ***eNBp,int nb_L1,int *nb_CC,char *rf_config_file, int send_dmrssync); // In lte-ue.c extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg); @@ -199,7 +198,6 @@ extern void init_te_thread(PHY_VARS_eNB *); extern void kill_td_thread(PHY_VARS_eNB *); extern void kill_te_thread(PHY_VARS_eNB *); -extern void RCConfig_sim(void); extern void init_ocm(void); extern void init_ue_devices(PHY_VARS_UE *); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 0962bb6a2d..1fae6c1e66 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -32,6 +32,7 @@ #include "lte-softmodem.h" #include "rt_wrapper.h" +#include "system.h" #include "LAYER2/MAC/mac.h" #include "RRC/LTE/rrc_extern.h" @@ -95,6 +96,7 @@ extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); extern int multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP); +int tx_req_num_elems; extern uint16_t sf_ahead; //extern int tx_req_UE_MAC1(); @@ -181,9 +183,8 @@ PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t abstraction_flag) { - PHY_VARS_UE *ue = (PHY_VARS_UE *)malloc(sizeof(PHY_VARS_UE)); - memset(ue,0,sizeof(PHY_VARS_UE)); - + PHY_VARS_UE *ue = (PHY_VARS_UE *)calloc(1,sizeof(PHY_VARS_UE)); + AssertFatal(ue,""); if (frame_parms!=(LTE_DL_FRAME_PARMS *)NULL) { // if we want to give initial frame parms, allocate the PHY_VARS_UE structure and put them in memcpy(&(ue->frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS)); } @@ -230,14 +231,23 @@ void init_thread(int sched_runtime, } #else + int settingPriority = 1; - if (CPU_COUNT(cpuset) > 0) - AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), ""); + if (checkIfFedoraDistribution()) + if (checkIfGenericKernelOnFedora()) + if (checkIfInsideContainer()) + settingPriority = 0; + + if (settingPriority) { + if (CPU_COUNT(cpuset) > 0) + AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), ""); + + struct sched_param sp; + sp.sched_priority = sched_fifo; + AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0, + "Can't set thread priority, Are you root?\n"); + } - struct sched_param sp; - sp.sched_priority = sched_fifo; - AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0, - "Can't set thread priority, Are you root?\n"); /* Check the actual affinity mask assigned to the thread */ cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE); @@ -283,13 +293,7 @@ void init_UE(int nb_inst, LOG_I(PHY,"Allocating UE context %d\n",inst); - if ( !IS_SOFTMODEM_SIML1 ) PHY_vars_UE_g[inst][0] = init_ue_vars(fp0,inst,0); - else { - // needed for memcopy below. these are not used in the RU, but needed for UE - RC.ru[0]->frame_parms->nb_antennas_rx = fp0->nb_antennas_rx; - RC.ru[0]->frame_parms->nb_antennas_tx = fp0->nb_antennas_tx; - PHY_vars_UE_g[inst][0] = init_ue_vars(RC.ru[0]->frame_parms,inst,0); - } + PHY_vars_UE_g[inst][0] = init_ue_vars(fp0,inst,0); // turn off timing control loop in UE PHY_vars_UE_g[inst][0]->no_timing_correction = timing_correction; @@ -371,17 +375,13 @@ void init_UE(int nb_inst, */ UE->N_TA_offset = 0; - if (IS_SOFTMODEM_SIML1 ) init_ue_devices(UE); - LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]); init_UE_threads(inst); - if (!IS_SOFTMODEM_SIML1 ) { - ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]); + ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]); - if (ret !=0) { - exit_fun("Error loading device library"); - } + if (ret !=0) { + exit_fun("Error loading device library"); } UE->rfdevice.host_type = RAU_HOST; @@ -787,10 +787,10 @@ static void *UE_thread_rxn_txnp4(void *arg) if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 ) CPU_SET(threads.one, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 ) + if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 ) CPU_SET(threads.two, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 ) + if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 ) CPU_SET(threads.three, &cpuset); //CPU_SET(threads.three, &cpuset); @@ -1596,7 +1596,7 @@ void *UE_thread(void *arg) wait_sync("UE thread"); #ifdef NAS_UE MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE); + message_p = itti_alloc_new_message(TASK_NAS_UE, 0, INITIALIZE_MESSAGE); itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p); #endif int sub_frame=-1; @@ -1976,7 +1976,7 @@ void init_UE_single_thread_stub(int nb_inst) if(NFAPI_MODE==NFAPI_UE_STUB_PNF) { #ifdef NAS_UE MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE); + message_p = itti_alloc_new_message(TASK_NAS_UE, 0, INITIALIZE_MESSAGE); itti_send_msg_to_task (TASK_NAS_UE, i + NB_eNB_INST, message_p); #endif } @@ -2067,7 +2067,6 @@ void init_UE_threads_stub(int inst) } -#ifdef OPENAIR2 void fill_ue_band_info(void) { LTE_UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability; @@ -2092,7 +2091,6 @@ void fill_ue_band_info(void) } } } -#endif int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg) diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index 54a9f4a669..da9b0fdfba 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -75,10 +75,6 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "UTIL/OPT/opt.h" -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_vars.h" -#endif - #include "create_tasks.h" #include "system.h" @@ -95,9 +91,6 @@ pthread_mutex_t nfapi_sync_mutex; int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex -#ifdef UESIM_EXPANSION - uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX]; -#endif uint16_t sf_ahead=2; int tddflag; char *emul_iface; @@ -171,7 +164,6 @@ extern void get_uethreads_params(void); int transmission_mode=1; -int usrp_tx_thread = 0; char *usrp_args=NULL; @@ -196,6 +188,9 @@ int oaisim_flag=0; */ uint8_t abstraction_flag=0; +// needed for pdcp.c +RAN_CONTEXT_t RC; + /* forward declarations */ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); @@ -289,7 +284,6 @@ static void get_options(void) { int dumpframe=0; int timingadv=0; uint8_t nfapi_mode = NFAPI_MONOLITHIC; - int simL1flag =0; set_default_frame_parms(frame_parms); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); @@ -303,8 +297,6 @@ static void get_options(void) { config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL); nfapi_setmode(nfapi_mode); - if (simL1flag) - set_softmodem_optmask(SOFTMODEM_SIML1_BIT); if (loopfile != NULL) { printf("Input file for hardware emulation: %s",loopfile); @@ -503,7 +495,7 @@ void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) { void terminate_task(task_id_t task_id, module_id_t mod_id) { LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id); MessageDef *msg; - msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE); + msg = itti_alloc_new_message (ENB_APP, 0, TERMINATE_MESSAGE); itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); } @@ -543,12 +535,15 @@ void init_pdcp(void) { pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); } +// Stupid function addition because UE itti messages queues definition is common with eNB +void *rrc_enb_process_msg(void *notUsed) { +AssertFatal(false,""); + return NULL; +} + int main( int argc, char **argv ) { int CC_id; uint8_t abstraction_flag=0; -#ifdef UESIM_EXPANSION - memset(inst_pdcp_list, 0, sizeof(inst_pdcp_list)); -#endif // Default value for the number of UEs. It will hold, // if not changed from the command line option --num-ues NB_UE_INST=1; @@ -574,11 +569,6 @@ int main( int argc, char **argv ) { EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; printf("Running with %d UE instances\n",NB_UE_INST); - if (NB_UE_INST > 1 && (!IS_SOFTMODEM_SIML1) && NFAPI_MODE!=NFAPI_UE_STUB_PNF) { - printf("Running with more than 1 UE instance and simL1 is not active, this will result in undefined behaviour for now, exiting.\n"); - abort(); - } - // Checking option of nums_ue_thread. if(NB_THREAD_INST < 1) { printf("Running with 0 UE rxtx thread, exiting.\n"); @@ -601,14 +591,14 @@ int main( int argc, char **argv ) { pthread_mutex_init(&sync_mutex, NULL); printf("ITTI init\n"); - itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + itti_init(TASK_MAX, tasks_info); // initialize mscgen log after ITTI if (get_softmodem_params()->start_msc) { load_module_shlib("msc",NULL,0,&msc_interface); } - MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); + MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX); init_opt(); init_pdcp(); //TTN for D2D @@ -649,9 +639,6 @@ int main( int argc, char **argv ) { } } else init_openair0(frame_parms[0],(int)rx_gain[0][0]); - if (IS_SOFTMODEM_SIML1 ) { - RCConfig_sim(); - } cpuf=get_cpu_freq_GHz(); @@ -753,12 +740,8 @@ int main( int argc, char **argv ) { //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; - if (IS_SOFTMODEM_SIML1 ) { - init_ocm(); - PHY_vars_UE_g[0][0]->no_timing_correction = 1; - } - if(IS_SOFTMODEM_DOFORMS) + if(IS_SOFTMODEM_DOSCOPE) load_softscope("ue",NULL); config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); @@ -770,6 +753,7 @@ int main( int argc, char **argv ) { printf("sync sent\n"); /* printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); + We have to set properly PARAMFLAG_NOFREE end_configmodule(); printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); */ @@ -783,7 +767,7 @@ int main( int argc, char **argv ) { printf("oai_exit=%d\n",oai_exit); // stop threads - if(IS_SOFTMODEM_DOFORMS) + if(IS_SOFTMODEM_DOSCOPE) end_forms(); printf("stopping MODEM threads\n"); diff --git a/targets/RT/USER/rcc_if5.gtkw b/targets/RT/USER/rcc_if5.gtkw index d64a9ca0fb..34c6bab5d1 100644 --- a/targets/RT/USER/rcc_if5.gtkw +++ b/targets/RT/USER/rcc_if5.gtkw @@ -1,41 +1,67 @@ [*] -[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Sun Jul 31 13:30:42 2016 +[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI +[*] Tue Sep 24 06:59:08 2019 [*] [dumpfile] "/tmp/openair_dump_eNB.vcd" -[dumpfile_mtime] "Sun Jul 31 13:21:59 2016" -[dumpfile_size] 18273240 -[savefile] "/home/fourmi/openairinterface5g/targets/RT/USER/rcc_if5.gtkw" -[timestart] 24070893000 -[size] 1301 716 -[pos] 309 0 -*-19.793451 29026062100 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -[sst_width] 284 -[signals_width] 262 +[dumpfile_mtime] "Mon Sep 23 20:04:56 2019" +[dumpfile_size] 1625759 +[savefile] "/home/orange/aw2s/openairinterface5g/targets/RT/USER/rcc_if5.gtkw" +[timestart] 12600104000 +[size] 1215 1000 +[pos] 0 22 +*-19.506693 12600920638 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[sst_width] 386 +[signals_width] 344 [sst_expanded] 1 -[sst_vpaned_height] 294 +[sst_vpaned_height] 303 +@29 +functions.send_if5 +@28 +functions.recv_if5 @24 variables.trx_ts[63:0] variables.trx_tst[63:0] @28 -functions.send_if5 -functions.recv_if5 functions.eNB_thread_rxtx0 @24 +variables.frame_number_RX0_RU[63:0] +variables.subframe_number_RX0_RU[63:0] +variables.frame_number_TX0_RU[63:0] +variables.subframe_number_TX0_RU[63:0] +@28 +functions.mac_schedule_dlsch +functions.macxface_eNB_dlsch_ulsch_scheduler +functions.macxface_ue_scheduler +functions.phy_eNB_ofdm_mod_l +@24 variables.frame_number_RX0_eNB[63:0] variables.subframe_number_RX0_eNB[63:0] variables.frame_number_TX0_eNB[63:0] variables.subframe_number_TX0_eNB[63:0] -@28 -functions.eNB_thread_rxtx1 -@24 variables.frame_number_RX1_eNB[63:0] variables.subframe_number_RX1_eNB[63:0] variables.frame_number_TX1_eNB[63:0] variables.subframe_number_TX1_eNB[63:0] @28 +functions.phy_eNB_dlsch_modulation +functions.phy_eNB_dlsch_encoding +functions.phy_eNB_dlsch_scrambling +functions.phy_eNB_beam_precoding +functions.phy_enb_pdcch_tx +functions.phy_enb_prach_rx +functions.phy_procedures_ru_feprx0 +functions.phy_procedures_eNb_rx_uespec0 +functions.phy_procedures_eNb_rx_uespec1 +functions.phy_enb_sfgen +functions.phy_procedures_eNb_tx0 +functions.phy_procedures_eNb_tx1 +functions.phy_procedures_ru_feprx1 +functions.phy_procedures_ru_feptx_ofdm0 +functions.phy_procedures_ru_feptx_ofdm1 +functions.phy_procedures_ru_feptx_prec0 +functions.phy_procedures_ru_feptx_prec1 +functions.eNB_thread_rxtx1 functions.phy_enb_sfgen -functions.phy_eNB_slot_fep functions.phy_enb_prach_rx @24 variables.dci_info[63:0] diff --git a/targets/RT/USER/rfsim.c b/targets/RT/USER/rfsim.c index a9a0912433..2bd95507c3 100644 --- a/targets/RT/USER/rfsim.c +++ b/targets/RT/USER/rfsim.c @@ -337,6 +337,7 @@ void init_ue_devices(PHY_VARS_UE *UE) { void init_ocm(void) { module_id_t UE_id, ru_id; int CC_id; + double DS_TDL = .03; randominit(0); set_taus_seed(0); init_channelmod(); @@ -357,8 +358,10 @@ void init_ocm(void) { AWGN, N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_DL), N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_DL), + DS_TDL, 0.0, 0, + 0, 0); random_channel(sim.RU2UE[ru_id][UE_id][CC_id],0); LOG_D(OCM,"[SIM] Initializing channel (%s) from UE %d to ru %d\n", "AWGN", UE_id, ru_id); @@ -369,8 +372,10 @@ void init_ocm(void) { AWGN, N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_UL), N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_UL), + DS_TDL, 0.0, 0, + 0, 0); random_channel(sim.UE2RU[UE_id][ru_id][CC_id],0); // to make channel reciprocal uncomment following line instead of previous. However this only works for SISO at the moment. For MIMO the channel would need to be transposed. diff --git a/targets/RT/USER/rfsim.h b/targets/RT/USER/rfsim.h deleted file mode 100644 index 801ab5eb56..0000000000 --- a/targets/RT/USER/rfsim.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698 - * - * 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. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ -#ifndef __RFSIM__H__ -#define __RFSIM__H__ -#include "lte-softmodem.h" -#include "openair1/SIMULATION/TOOLS/sim.h" -#include "platform_constants.h" -#include "common/ran_context.h" -#include "PHY/defs_UE.h" -#include "PHY/defs_eNB.h" - -void init_ocm(void); - -void update_ocm(double snr_dB,double sinr_dB); - -//extern pthread_mutex_t async_server_lock; -//extern pthread_cond_t async_server_notify; -//extern int async_server_shutdown; - -void init_channel_vars(void); - -#endif diff --git a/targets/RT/USER/rt_wrapper.c b/targets/RT/USER/rt_wrapper.c index 5bdbbb36e3..da3a2d3cfe 100644 --- a/targets/RT/USER/rt_wrapper.c +++ b/targets/RT/USER/rt_wrapper.c @@ -43,7 +43,9 @@ #include #include #include "rt_wrapper.h" +#include "system.h" #include +#include #include "openair1/PHY/defs_common.h" @@ -293,6 +295,7 @@ void thread_top_init(char *thread_name, struct sched_param sparam; char cpu_affinity[1024]; cpu_set_t cpuset; + int settingPriority = 1; /* Set affinity mask to include CPUs 2 to MAX_CPUS */ /* CPU 0 is reserved for UHD threads */ @@ -339,30 +342,37 @@ void thread_top_init(char *thread_name, } } - memset(&sparam, 0, sizeof(sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - } + if (checkIfFedoraDistribution()) + if (checkIfGenericKernelOnFedora()) + if (checkIfInsideContainer()) + settingPriority = 0; - pthread_setname_np(pthread_self(), thread_name); + if (settingPriority) { + memset(&sparam, 0, sizeof(sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + policy = SCHED_FIFO; + + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) { + perror("pthread_getschedparam : "); + exit_fun("Error getting thread priority"); + } - LOG_I(HW, "[SCHED][eNB] %s started on CPU %d, sched_policy = %s , priority = %d, CPU Affinity=%s \n",thread_name,sched_getcpu(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity ); + pthread_setname_np(pthread_self(), thread_name); + + LOG_I(HW, "[SCHED][eNB] %s started on CPU %d, sched_policy = %s , priority = %d, CPU Affinity=%s \n",thread_name,sched_getcpu(), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + sparam.sched_priority, cpu_affinity ); + } #endif //LOW_LATENCY diff --git a/targets/RT/USER/ru_control.c b/targets/RT/USER/ru_control.c index 6daf0f4dfa..95b5ce6155 100644 --- a/targets/RT/USER/ru_control.c +++ b/targets/RT/USER/ru_control.c @@ -61,30 +61,17 @@ #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/LTE_TRANSPORT/if5_tools.h" -#include "PHY/phy_extern.h" -#include "LAYER2/MAC/mac_extern.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" #include "SCHED/sched_eNB.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/INIT/phy_init.h" -#include "LAYER2/MAC/mac.h" -#include "LAYER2/MAC/mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" -#include "RRC/LTE/rrc_extern.h" -#include "PHY_INTERFACE/phy_interface.h" - #include "common/utils/LOG/log.h" -#include "UTIL/OTG/otg_tx.h" -#include "UTIL/OTG/otg_externs.h" -#include "UTIL/MATH/oml.h" -#include "UTIL/OPT/opt.h" -#include "enb_config.h" int attach_rru(RU_t *ru); -void configure_ru(int idx, void *arg); -void configure_rru(int idx, void *arg); +void configure_ru(RU_t *ru, void *arg); +void configure_rru(RU_t *ru, void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); void* ru_thread_control( void* param ); @@ -164,7 +151,7 @@ int send_capab(RU_t *ru) cap->FH_fmt = MBP_IF5; break; default: - AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function); + AssertFatal(1==0,"RU_function is unknown %d\n",ru->function); break; } cap->num_bands = ru->num_bands; @@ -224,7 +211,7 @@ int attach_rru(RU_t *ru) LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); } } - configure_ru(ru->idx, + configure_ru(ru, (RRU_capabilities_t *)&rru_config_msg.msg[0]); rru_config_msg.type = RRU_config; @@ -296,7 +283,7 @@ int connect_rau(RU_t *ru) cap->FH_fmt = MBP_IF5; break; default: - AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function); + AssertFatal(1==0,"RU_function is unknown %d\n",ru->function); break; } cap->num_bands = ru->num_bands; @@ -335,7 +322,7 @@ int connect_rau(RU_t *ru) ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0], ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); - configure_rru(ru->idx, + configure_rru(ru, (void*)&rru_config_msg.msg[0]); configuration_received = 1; } @@ -388,21 +375,20 @@ int check_capabilities(RU_t *ru, return(-1); } -void configure_ru(int idx, +void configure_ru(RU_t *ru, void *arg) { - RU_t *ru = RC.ru[idx]; RRU_config_t *config = (RRU_config_t *)arg; RRU_capabilities_t *capabilities = (RRU_capabilities_t*)arg; int ret; - LOG_I(PHY, "Received capabilities from RRU %d\n",idx); + LOG_I(PHY, "Received capabilities from RRU %d\n",ru->idx); if (capabilities->FH_fmt < MAX_FH_FMTs) LOG_I(PHY, "RU FH options %s\n",rru_format_options[capabilities->FH_fmt]); AssertFatal((ret=check_capabilities(ru,capabilities)) == 0, - "Cannot configure RRU %d, check_capabilities returned %d\n", idx,ret); + "Cannot configure RRU %d, check_capabilities returned %d\n", ru->idx,ret); // take antenna capabilities of RRU ru->nb_tx = capabilities->nb_tx[0]; ru->nb_rx = capabilities->nb_rx[0]; @@ -440,11 +426,10 @@ void configure_ru(int idx, phy_init_RU(ru); } -void configure_rru(int idx, +void configure_rru(RU_t *ru, void *arg) { RRU_config_t *config = (RRU_config_t *)arg; - RU_t *ru = RC.ru[idx]; ru->frame_parms->eutra_band = config->band_list[0]; ru->frame_parms->dl_CarrierFreq = config->tx_freq[0]; @@ -486,7 +471,6 @@ void configure_rru(int idx, static int send_update_rru(RU_t * ru, LTE_DL_FRAME_PARMS * fp){ //ssize_t msg_len/*,len*/; int i; - //LTE_DL_FRAME_PARMS *fp = &RC.eNB[0][0]->frame_parms; RRU_CONFIG_msg_t rru_config_msg; memset((void *)&rru_config_msg,0,sizeof(rru_config_msg)); rru_config_msg.type = RRU_config_update; @@ -524,7 +508,7 @@ void* ru_thread_control( void* param ) } - ru->state = (ru->function==eNodeB_3GPP)? RU_RUN : RU_IDLE; + ru->state = (ru->function==eNodeB_3GPP || ru->if_south == REMOTE_IF5)? RU_RUN : RU_IDLE; LOG_I(PHY,"Control channel ON for RU %d\n", ru->idx); while (!oai_exit) // Change the cond @@ -535,7 +519,7 @@ void* ru_thread_control( void* param ) send_tick(ru); if (ru->state == RU_RUN && ru->if_south != LOCAL_RF){ - LTE_DL_FRAME_PARMS *fp = &RC.eNB[0][0]->frame_parms; + LTE_DL_FRAME_PARMS *fp = &ru->eNB_list[0]->frame_parms; LOG_D(PHY,"Check MBSFN SF changes\n"); if(fp->num_MBSFN_config != ru_sf_update){ ru_sf_update = fp->num_MBSFN_config; @@ -579,7 +563,7 @@ void* ru_thread_control( void* param ) ((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_tx[0], ((RRU_capabilities_t*)&rru_config_msg.msg[0])->nb_rx[0]); - configure_ru(ru->idx,(RRU_capabilities_t *)&rru_config_msg.msg[0]); + configure_ru(ru,(RRU_capabilities_t *)&rru_config_msg.msg[0]); // send config if (send_config(ru,rru_config_msg) == 0) ru->state = RU_CONFIG; @@ -603,7 +587,7 @@ void* ru_thread_control( void* param ) ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); ru->frame_parms = calloc(1, sizeof(*ru->frame_parms)); - configure_rru(ru->idx, (void*)&rru_config_msg.msg[0]); + configure_rru(ru, (void*)&rru_config_msg.msg[0]); fill_rf_config(ru,ru->rf_config_file); @@ -652,10 +636,10 @@ void* ru_thread_control( void* param ) LOG_I(PHY, "Signaling main thread that RU %d (is_slave %d) is ready in state %s\n",ru->idx,ru->is_slave,ru_states[ru->state]); - pthread_mutex_lock(&RC.ru_mutex); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - pthread_mutex_unlock(&RC.ru_mutex); + pthread_mutex_lock(ru->ru_mutex); + *ru->ru_mask &= ~(1<idx); + pthread_cond_signal(ru->ru_cond); + pthread_mutex_unlock(ru->ru_mutex); wait_sync("ru_thread_control"); @@ -710,10 +694,10 @@ void* ru_thread_control( void* param ) if (ru->state == RU_READY){ LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); - pthread_mutex_lock(&RC.ru_mutex); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - pthread_mutex_unlock(&RC.ru_mutex); + pthread_mutex_lock(ru->ru_mutex); + *ru->ru_mask &= ~(1<idx); + pthread_cond_signal(ru->ru_cond); + pthread_mutex_unlock(ru->ru_mutex); wait_sync("ru_thread_control"); @@ -736,7 +720,7 @@ void* ru_thread_control( void* param ) break; case RRU_sync_ok: //RAU - if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_config_ok msg...Ignoring\n"); + if (ru->if_south == LOCAL_RF) LOG_E(PHY,"Received RRU_sync_ok msg...Ignoring\n"); else{ if (ru->is_slave == 1){ printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Received RRU_sync_ok from RRU %d\n",ru->idx); diff --git a/targets/RT/USER/stats.h b/targets/RT/USER/stats.h index 264c8f7af0..15ee4a8087 100644 --- a/targets/RT/USER/stats.h +++ b/targets/RT/USER/stats.h @@ -21,8 +21,8 @@ /* Header file generated by fdesign on Thu Aug 28 12:13:51 2014 */ -#ifndef FD_stats_form_h_ -#define FD_stats_form_h_ +#ifndef _TARGETS_RT_USER_STATS_H_ +#define _TARGETS_RT_USER_STATS_H_ #include @@ -43,4 +43,4 @@ typedef struct { extern FD_stats_form * create_form_stats_form( void ); -#endif /* FD_stats_form_h_ */ +#endif /* _TARGETS_RT_USER_STATS_H_ */ diff --git a/txsig0.m b/txsig0.m new file mode 100644 index 0000000000..e795208a15 --- /dev/null +++ b/txsig0.m @@ -0,0 +1,61441 @@ +txs0 = [-194 + j*(-202) +-136 + j*(186) +248 + j*(59) +61 + j*(-331) +-327 + j*(-134) +-161 + j*(205) +70 + j*(64) +-84 + j*(-35) +-82 + j*(168) +170 + j*(116) +105 + j*(-159) +-163 + j*(-94) +-102 + j*(147) +100 + j*(89) +31 + j*(-79) +-114 + j*(4) +-25 + j*(144) +112 + j*(64) +41 + j*(-65) +-84 + j*(9) +-18 + j*(151) +137 + j*(129) +190 + j*(9) +163 + j*(-89) +85 + j*(-173) +-68 + j*(-154) +-93 + j*(26) +119 + j*(64) +183 + j*(-209) +-139 + j*(-343) +-365 + j*(-29) +-107 + j*(252) +180 + j*(51) +11 + j*(-232) +-279 + j*(-96) +-200 + j*(193) +42 + j*(170) +37 + j*(-5) +-93 + j*(13) +-81 + j*(137) +21 + j*(187) +158 + j*(174) +303 + j*(-10) +155 + j*(-324) +-275 + j*(-277) +-348 + j*(180) +57 + j*(327) +197 + j*(1) +-89 + j*(-71) +-107 + j*(244) +254 + j*(283) +382 + j*(-61) +137 + j*(-263) +-69 + j*(-141) +-19 + j*(32) +138 + j*(8) +135 + j*(-159) +-20 + j*(-175) +-9 + j*(-51) +126 + j*(-153) +-52 + j*(-384) +-409 + j*(-234) +-389 + j*(165) +-78 + j*(276) +81 + j*(133) +94 + j*(11) +42 + j*(-99) +-103 + j*(-112) +-155 + j*(25) +-57 + j*(74) +-47 + j*(23) +-64 + j*(69) +36 + j*(51) +-16 + j*(-105) +-230 + j*(-46) +-211 + j*(189) +-51 + j*(221) +-39 + j*(208) +67 + j*(312) +308 + j*(188) +240 + j*(-112) +-30 + j*(-91) +-16 + j*(126) +153 + j*(117) +170 + j*(12) +156 + j*(-11) +173 + j*(-64) +130 + j*(-112) +123 + j*(-123) +100 + j*(-220) +-86 + j*(-247) +-170 + j*(-43) +21 + j*(40) +64 + j*(-161) +-175 + j*(-176) +-196 + j*(100) +91 + j*(138) +151 + j*(-144) +-111 + j*(-234) +-230 + j*(-19) +-85 + j*(96) +-11 + j*(9) +-78 + j*(-10) +-66 + j*(57) +-17 + j*(30) +-70 + j*(21) +-45 + j*(133) +139 + j*(109) +154 + j*(-121) +-70 + j*(-189) +-165 + j*(-28) +-98 + j*(46) +-93 + j*(60) +-33 + j*(136) +93 + j*(59) +-5 + j*(-81) +-144 + j*(55) +36 + j*(194) +176 + j*(-16) +-49 + j*(-146) +-166 + j*(75) +32 + j*(179) +109 + j*(33) +25 + j*(9) +74 + j*(42) +80 + j*(-77) +-93 + j*(-79) +-105 + j*(128) +111 + j*(162) +170 + j*(-36) +-4 + j*(-98) +-60 + j*(74) +142 + j*(148) +281 + j*(-80) +70 + j*(-296) +-184 + j*(-135) +-49 + j*(103) +166 + j*(-62) +-46 + j*(-301) +-354 + j*(-80) +-202 + j*(281) +147 + j*(244) +206 + j*(-15) +78 + j*(-109) +20 + j*(-95) +-17 + j*(-116) +-112 + j*(-98) +-159 + j*(30) +-44 + j*(146) +110 + j*(66) +59 + j*(-88) +-69 + j*(-35) +13 + j*(67) +104 + j*(-51) +-37 + j*(-129) +-83 + j*(6) +40 + j*(-13) +-67 + j*(-129) +-181 + j*(74) +120 + j*(185) +238 + j*(-213) +-223 + j*(-363) +-411 + j*(107) +-2 + j*(288) +109 + j*(-43) +-169 + j*(-46) +-73 + j*(214) +182 + j*(56) +-7 + j*(-186) +-223 + j*(5) +-57 + j*(177) +38 + j*(27) +-137 + j*(19) +-122 + j*(259) +152 + j*(303) +272 + j*(86) +172 + j*(-42) +145 + j*(-28) +195 + j*(-117) +64 + j*(-272) +-177 + j*(-182) +-171 + j*(71) +32 + j*(98) +31 + j*(-51) +-99 + j*(11) +8 + j*(153) +159 + j*(35) +35 + j*(-93) +-64 + j*(65) +149 + j*(186) +355 + j*(-29) +238 + j*(-317) +-43 + j*(-356) +-204 + j*(-183) +-149 + j*(-11) +-34 + j*(-13) +-62 + j*(-84) +-139 + j*(-6) +-34 + j*(103) +103 + j*(-2) +18 + j*(-142) +-96 + j*(-79) +-27 + j*(-25) +-26 + j*(-159) +-263 + j*(-175) +-385 + j*(125) +-127 + j*(377) +177 + j*(252) +168 + j*(13) +60 + j*(5) +144 + j*(21) +160 + j*(-194) +-136 + j*(-288) +-318 + j*(5) +-82 + j*(217) +93 + j*(27) +-91 + j*(-98) +-199 + j*(90) +-41 + j*(188) +8 + j*(95) +-67 + j*(132) +27 + j*(257) +204 + j*(201) +247 + j*(55) +214 + j*(-49) +131 + j*(-134) +-10 + j*(-97) +16 + j*(65) +221 + j*(31) +221 + j*(-237) +-64 + j*(-323) +-230 + j*(-107) +-126 + j*(61) +-33 + j*(42) +-40 + j*(42) +20 + j*(91) +120 + j*(29) +89 + j*(-100) +-38 + j*(-103) +-58 + j*(13) +58 + j*(46) +122 + j*(-83) +0 + j*(-199) +-163 + j*(-120) +-140 + j*(45) +-11 + j*(53) +-18 + j*(-31) +-82 + j*(17) +11 + j*(74) +59 + j*(-59) +-120 + j*(-101) +-171 + j*(128) +76 + j*(203) +172 + j*(-20) +10 + j*(-92) +9 + j*(9) +75 + j*(-86) +-111 + j*(-147) +-175 + j*(105) +122 + j*(173) +203 + j*(-151) +-111 + j*(-262) +-245 + j*(-17) +-110 + j*(93) +-74 + j*(53) +-79 + j*(90) +-29 + j*(81) +-96 + j*(72) +-87 + j*(255) +197 + j*(303) +325 + j*(8) +103 + j*(-132) +39 + j*(30) +215 + j*(1) +166 + j*(-223) +-55 + j*(-224) +-98 + j*(-93) +-86 + j*(-68) +-130 + j*(-1) +-34 + j*(97) +81 + j*(-18) +-69 + j*(-147) +-237 + j*(30) +-83 + j*(245) +132 + j*(166) +120 + j*(25) +91 + j*(37) +170 + j*(-23) +83 + j*(-180) +-124 + j*(-100) +-45 + j*(129) +206 + j*(34) +113 + j*(-245) +-176 + j*(-175) +-128 + j*(87) +92 + j*(37) +29 + j*(-153) +-144 + j*(-103) +-128 + j*(23) +-92 + j*(30) +-112 + j*(88) +-8 + j*(170) +122 + j*(83) +81 + j*(-45) +-4 + j*(-42) +-18 + j*(-16) +-43 + j*(-1) +-42 + j*(64) +40 + j*(78) +47 + j*(6) +-19 + j*(44) +76 + j*(154) +281 + j*(49) +264 + j*(-238) +-18 + j*(-369) +-266 + j*(-198) +-245 + j*(78) +-7 + j*(177) +168 + j*(-5) +40 + j*(-248) +-272 + j*(-207) +-366 + j*(132) +-85 + j*(356) +208 + j*(202) +177 + j*(-63) +3 + j*(-96) +-23 + j*(-18) +-3 + j*(-49) +-109 + j*(-69) +-184 + j*(77) +-69 + j*(223) +105 + j*(208) +198 + j*(93) +202 + j*(-50) +97 + j*(-165) +-67 + j*(-153) +-146 + j*(-14) +-83 + j*(126) +72 + j*(153) +183 + j*(23) +98 + j*(-141) +-86 + j*(-95) +-59 + j*(91) +134 + j*(71) +122 + j*(-134) +-97 + j*(-146) +-147 + j*(77) +66 + j*(191) +257 + j*(23) +194 + j*(-226) +-39 + j*(-298) +-208 + j*(-178) +-243 + j*(-25) +-216 + j*(119) +-76 + j*(247) +144 + j*(186) +151 + j*(-23) +4 + j*(-19) +91 + j*(98) +249 + j*(-80) +41 + j*(-301) +-199 + j*(-124) +-54 + j*(63) +53 + j*(-95) +-144 + j*(-161) +-214 + j*(38) +-77 + j*(104) +-69 + j*(55) +-69 + j*(140) +83 + j*(153) +127 + j*(-1) +25 + j*(-45) +27 + j*(0) +44 + j*(-57) +-45 + j*(-78) +-70 + j*(5) +-9 + j*(15) +-13 + j*(-43) +-80 + j*(-61) +-170 + j*(-14) +-212 + j*(145) +-59 + j*(313) +175 + j*(250) +221 + j*(59) +145 + j*(-12) +130 + j*(-25) +116 + j*(-76) +69 + j*(-121) +-23 + j*(-160) +-188 + j*(-76) +-166 + j*(193) +141 + j*(249) +243 + j*(-24) +41 + j*(-97) +64 + j*(44) +183 + j*(-84) +-27 + j*(-175) +-50 + j*(114) +363 + j*(58) +303 + j*(-504) +-333 + j*(-527) +-450 + j*(41) +-40 + j*(153) +-25 + j*(-122) +-240 + j*(-37) +-124 + j*(148) +-1 + j*(45) +-100 + j*(14) +-57 + j*(126) +62 + j*(41) +-56 + j*(-71) +-175 + j*(71) +-45 + j*(213) +107 + j*(142) +114 + j*(21) +66 + j*(-37) +-12 + j*(-71) +-130 + j*(-15) +-141 + j*(177) +85 + j*(297) +323 + j*(107) +219 + j*(-204) +-95 + j*(-180) +-118 + j*(100) +119 + j*(148) +185 + j*(-22) +117 + j*(-76) +129 + j*(-119) +34 + j*(-238) +-174 + j*(-164) +-153 + j*(57) +23 + j*(79) +60 + j*(-21) +45 + j*(-59) +23 + j*(-130) +-110 + j*(-151) +-168 + j*(-12) +-75 + j*(34) +-113 + j*(-22) +-182 + j*(123) +25 + j*(248) +192 + j*(50) +38 + j*(-102) +-52 + j*(12) +51 + j*(23) +1 + j*(-83) +-116 + j*(-6) +-47 + j*(104) +17 + j*(71) +16 + j*(99) +153 + j*(109) +215 + j*(-111) +-33 + j*(-237) +-202 + j*(0) +14 + j*(183) +216 + j*(-10) +61 + j*(-235) +-169 + j*(-145) +-139 + j*(46) +-11 + j*(21) +-91 + j*(-76) +-228 + j*(60) +-99 + j*(269) +136 + j*(210) +139 + j*(28) +42 + j*(33) +100 + j*(93) +185 + j*(6) +139 + j*(-114) +26 + j*(-142) +-59 + j*(-71) +-20 + j*(39) +111 + j*(11) +86 + j*(-144) +-77 + j*(-129) +-51 + j*(8) +54 + j*(-62) +-78 + j*(-164) +-202 + j*(-3) +-66 + j*(136) +41 + j*(61) +23 + j*(25) +78 + j*(16) +68 + j*(-111) +-93 + j*(-116) +-100 + j*(38) +25 + j*(27) +-13 + j*(-73) +-98 + j*(-31) +-88 + j*(21) +-105 + j*(69) +-13 + j*(190) +216 + j*(78) +108 + j*(-244) +-277 + j*(-153) +-214 + j*(264) +196 + j*(235) +199 + j*(-131) +-99 + j*(-150) +-117 + j*(66) +24 + j*(66) +-5 + j*(-31) +-98 + j*(15) +-83 + j*(126) +14 + j*(186) +138 + j*(156) +200 + j*(43) +163 + j*(-57) +107 + j*(-97) +49 + j*(-122) +-23 + j*(-93) +-13 + j*(-21) +56 + j*(-54) +-11 + j*(-151) +-169 + j*(-84) +-148 + j*(123) +69 + j*(170) +175 + j*(-24) +16 + j*(-158) +-123 + j*(-22) +7 + j*(114) +156 + j*(-19) +43 + j*(-183) +-119 + j*(-129) +-136 + j*(-23) +-138 + j*(41) +-78 + j*(157) +117 + j*(136) +134 + j*(-84) +-78 + j*(-120) +-107 + j*(64) +33 + j*(69) +-13 + j*(-21) +-76 + j*(95) +91 + j*(178) +231 + j*(29) +181 + j*(-138) +58 + j*(-223) +-117 + j*(-201) +-183 + j*(-8) +-10 + j*(71) +25 + j*(-103) +-186 + j*(-88) +-157 + j*(153) +59 + j*(127) +13 + j*(-8) +-35 + j*(103) +158 + j*(102) +157 + j*(-132) +-30 + j*(-143) +-12 + j*(-71) +-68 + j*(-188) +-312 + j*(-68) +-202 + j*(255) +106 + j*(181) +32 + j*(-31) +-72 + j*(78) +74 + j*(97) +14 + j*(-49) +-103 + j*(99) +141 + j*(182) +200 + j*(-136) +-147 + j*(-175) +-165 + j*(148) +81 + j*(121) +-36 + j*(-28) +-121 + j*(200) +169 + j*(290) +270 + j*(55) +179 + j*(21) +314 + j*(-1) +285 + j*(-309) +-81 + j*(-343) +-148 + j*(-45) +36 + j*(-34) +-51 + j*(-122) +-74 + j*(53) +172 + j*(23) +110 + j*(-277) +-204 + j*(-220) +-161 + j*(42) +7 + j*(-23) +-116 + j*(-115) +-186 + j*(62) +4 + j*(139) +91 + j*(-23) +-27 + j*(-114) +-117 + j*(-51) +-107 + j*(23) +-71 + j*(40) +-76 + j*(35) +-93 + j*(89) +-12 + j*(156) +100 + j*(99) +95 + j*(0) +68 + j*(-22) +71 + j*(-80) +-33 + j*(-146) +-141 + j*(-59) +-110 + j*(25) +-114 + j*(23) +-142 + j*(128) +8 + j*(211) +113 + j*(82) +28 + j*(33) +90 + j*(103) +182 + j*(-69) +-69 + j*(-202) +-224 + j*(82) +57 + j*(229) +154 + j*(-28) +-82 + j*(-46) +-26 + j*(180) +177 + j*(80) +50 + j*(-60) +-1 + j*(112) +234 + j*(100) +214 + j*(-171) +-30 + j*(-161) +-8 + j*(3) +81 + j*(-49) +11 + j*(-83) +39 + j*(-25) +76 + j*(-131) +-100 + j*(-167) +-144 + j*(49) +84 + j*(95) +136 + j*(-136) +-80 + j*(-215) +-209 + j*(-57) +-156 + j*(109) +3 + j*(178) +167 + j*(73) +132 + j*(-123) +-33 + j*(-134) +-35 + j*(-33) +21 + j*(-82) +-76 + j*(-132) +-132 + j*(-34) +-72 + j*(-1) +-93 + j*(-41) +-139 + j*(23) +-83 + j*(71) +-75 + j*(44) +-97 + j*(95) +-10 + j*(140) +38 + j*(66) +-10 + j*(60) +47 + j*(98) +87 + j*(-15) +-70 + j*(-41) +-76 + j*(173) +202 + j*(187) +267 + j*(-129) +-20 + j*(-264) +-206 + j*(-71) +-133 + j*(107) +-13 + j*(140) +75 + j*(89) +69 + j*(-3) +-16 + j*(7) +30 + j*(97) +139 + j*(17) +36 + j*(-110) +-91 + j*(18) +63 + j*(139) +184 + j*(-37) +4 + j*(-156) +-102 + j*(13) +51 + j*(100) +123 + j*(-25) +40 + j*(-88) +-7 + j*(-67) +-64 + j*(-44) +-83 + j*(100) +135 + j*(192) +322 + j*(-47) +141 + j*(-305) +-98 + j*(-221) +-71 + j*(-95) +-74 + j*(-156) +-224 + j*(-89) +-173 + j*(126) +46 + j*(119) +59 + j*(-66) +-92 + j*(-74) +-102 + j*(55) +17 + j*(83) +78 + j*(-22) +-5 + j*(-134) +-163 + j*(-98) +-198 + j*(73) +-69 + j*(168) +25 + j*(117) +40 + j*(82) +81 + j*(57) +89 + j*(-18) +42 + j*(-52) +33 + j*(-74) +-54 + j*(-149) +-226 + j*(-48) +-151 + j*(182) +61 + j*(127) +-40 + j*(-22) +-134 + j*(177) +169 + j*(257) +239 + j*(-114) +-183 + j*(-148) +-180 + j*(333) +346 + j*(337) +386 + j*(-156) +13 + j*(-190) +69 + j*(57) +272 + j*(-112) +67 + j*(-338) +-147 + j*(-214) +-138 + j*(-105) +-197 + j*(-58) +-168 + j*(129) +66 + j*(134) +58 + j*(-88) +-147 + j*(-33) +-42 + j*(170) +154 + j*(37) +13 + j*(-136) +-124 + j*(11) +17 + j*(112) +87 + j*(-14) +-11 + j*(-47) +-3 + j*(23) +49 + j*(-22) +-16 + j*(-62) +-42 + j*(8) +30 + j*(13) +21 + j*(-71) +-76 + j*(-71) +-110 + j*(18) +-71 + j*(82) +-9 + j*(115) +81 + j*(99) +123 + j*(-4) +43 + j*(-77) +-13 + j*(-18) +59 + j*(-4) +41 + j*(-132) +-149 + j*(-117) +-168 + j*(110) +54 + j*(157) +94 + j*(-24) +-43 + j*(-18) +30 + j*(95) +135 + j*(-37) +-33 + j*(-132) +-107 + j*(57) +92 + j*(104) +111 + j*(-83) +-29 + j*(-65) +56 + j*(11) +83 + j*(-171) +-190 + j*(-189) +-227 + j*(131) +93 + j*(187) +159 + j*(-101) +-77 + j*(-175) +-156 + j*(-15) +-83 + j*(51) +-49 + j*(43) +-36 + j*(27) +-81 + j*(19) +-98 + j*(130) +69 + j*(174) +136 + j*(-19) +-67 + j*(-74) +-95 + j*(139) +124 + j*(143) +112 + j*(-52) +-35 + j*(-11) +42 + j*(84) +90 + j*(-14) +-3 + j*(-4) +95 + j*(69) +164 + j*(-132) +-128 + j*(-231) +-281 + j*(105) +27 + j*(307) +236 + j*(92) +127 + j*(-53) +91 + j*(-12) +117 + j*(-66) +21 + j*(-92) +17 + j*(26) +163 + j*(13) +181 + j*(-146) +79 + j*(-215) +19 + j*(-230) +-83 + j*(-263) +-221 + j*(-168) +-188 + j*(5) +-35 + j*(-1) +-52 + j*(-155) +-252 + j*(-163) +-347 + j*(56) +-194 + j*(232) +-23 + j*(169) +-54 + j*(60) +-143 + j*(129) +-72 + j*(266) +100 + j*(289) +249 + j*(188) +310 + j*(-8) +184 + j*(-207) +-50 + j*(-197) +-107 + j*(-20) +9 + j*(33) +37 + j*(-66) +-71 + j*(-104) +-163 + j*(-24) +-169 + j*(118) +-42 + j*(227) +118 + j*(168) +116 + j*(40) +59 + j*(55) +148 + j*(66) +160 + j*(-96) +-42 + j*(-122) +-75 + j*(100) +170 + j*(142) +241 + j*(-99) +49 + j*(-201) +-41 + j*(-86) +25 + j*(-41) +37 + j*(-102) +-24 + j*(-126) +-75 + j*(-99) +-100 + j*(-59) +-117 + j*(-15) +-122 + j*(64) +-17 + j*(167) +188 + j*(89) +176 + j*(-187) +-116 + j*(-242) +-204 + j*(13) +1 + j*(68) +-25 + j*(-117) +-233 + j*(-18) +-103 + j*(222) +136 + j*(86) +-18 + j*(-122) +-207 + j*(60) +-23 + j*(254) +156 + j*(115) +74 + j*(1) +53 + j*(74) +169 + j*(38) +151 + j*(-116) +9 + j*(-153) +-66 + j*(-77) +-56 + j*(-2) +1 + j*(18) +27 + j*(-35) +-42 + j*(-64) +-83 + j*(21) +1 + j*(78) +62 + j*(10) +25 + j*(-33) +25 + j*(-25) +24 + j*(-86) +-94 + j*(-115) +-179 + j*(21) +-87 + j*(153) +40 + j*(136) +84 + j*(81) +120 + j*(39) +149 + j*(-49) +94 + j*(-165) +-58 + j*(-222) +-250 + j*(-126) +-292 + j*(157) +-4 + j*(361) +327 + j*(146) +220 + j*(-244) +-158 + j*(-236) +-211 + j*(86) +41 + j*(154) +88 + j*(-45) +-88 + j*(-61) +-89 + j*(115) +85 + j*(123) +98 + j*(-33) +-39 + j*(-42) +-38 + j*(100) +124 + j*(104) +147 + j*(-66) +-16 + j*(-96) +-28 + j*(74) +194 + j*(75) +242 + j*(-210) +-58 + j*(-366) +-318 + j*(-151) +-255 + j*(142) +-24 + j*(223) +139 + j*(105) +119 + j*(-82) +-71 + j*(-118) +-136 + j*(92) +116 + j*(196) +286 + j*(-92) +3 + j*(-344) +-312 + j*(-116) +-159 + j*(211) +137 + j*(116) +62 + j*(-134) +-164 + j*(-58) +-81 + j*(167) +156 + j*(90) +97 + j*(-168) +-182 + j*(-148) +-221 + j*(134) +23 + j*(240) +168 + j*(72) +91 + j*(-66) +-8 + j*(-58) +-41 + j*(-9) +-33 + j*(50) +40 + j*(79) +105 + j*(7) +54 + j*(-72) +-13 + j*(-45) +8 + j*(-11) +19 + j*(-43) +-23 + j*(-54) +-45 + j*(-25) +-45 + j*(-5) +-40 + j*(20) +-13 + j*(32) +-4 + j*(18) +0 + j*(25) +30 + j*(4) +-22 + j*(-54) +-124 + j*(45) +15 + j*(223) +294 + j*(79) +206 + j*(-286) +-193 + j*(-308) +-334 + j*(42) +-115 + j*(271) +130 + j*(213) +218 + j*(28) +136 + j*(-144) +-40 + j*(-163) +-117 + j*(-43) +-76 + j*(32) +-50 + j*(56) +8 + j*(89) +77 + j*(14) +-23 + j*(-69) +-119 + j*(71) +39 + j*(196) +177 + j*(67) +111 + j*(-15) +162 + j*(22) +255 + j*(-180) +-35 + j*(-395) +-370 + j*(-116) +-168 + j*(276) +217 + j*(171) +198 + j*(-155) +-37 + j*(-199) +-114 + j*(-66) +-65 + j*(12) +12 + j*(21) +74 + j*(-71) +-16 + j*(-208) +-224 + j*(-183) +-316 + j*(28) +-198 + j*(214) +-19 + j*(222) +58 + j*(128) +44 + j*(74) +54 + j*(69) +66 + j*(15) +-12 + j*(-14) +-53 + j*(98) +100 + j*(182) +267 + j*(35) +209 + j*(-199) +-7 + j*(-283) +-209 + j*(-177) +-248 + j*(46) +-88 + j*(182) +49 + j*(96) +-12 + j*(27) +-16 + j*(144) +192 + j*(141) +260 + j*(-132) +6 + j*(-308) +-255 + j*(-176) +-310 + j*(85) +-154 + j*(310) +153 + j*(320) +295 + j*(34) +78 + j*(-156) +-93 + j*(13) +53 + j*(149) +153 + j*(42) +105 + j*(16) +206 + j*(45) +294 + j*(-177) +48 + j*(-372) +-206 + j*(-206) +-146 + j*(11) +-28 + j*(11) +-23 + j*(-14) +11 + j*(-11) +11 + j*(-80) +-82 + j*(-71) +-68 + j*(40) +57 + j*(23) +50 + j*(-105) +-58 + j*(-122) +-83 + j*(-64) +-75 + j*(-74) +-138 + j*(-86) +-218 + j*(-9) +-206 + j*(144) +-28 + j*(240) +173 + j*(89) +70 + j*(-199) +-288 + j*(-182) +-414 + j*(196) +-140 + j*(471) +180 + j*(421) +344 + j*(233) +393 + j*(-2) +255 + j*(-228) +6 + j*(-238) +-80 + j*(-84) +-32 + j*(-26) +-45 + j*(-15) +-14 + j*(54) +83 + j*(-1) +-13 + j*(-116) +-156 + j*(29) +28 + j*(211) +238 + j*(10) +42 + j*(-211) +-158 + j*(-20) +36 + j*(136) +151 + j*(-74) +-80 + j*(-159) +-156 + j*(83) +73 + j*(162) +150 + j*(-23) +24 + j*(-78) +12 + j*(1) +81 + j*(-30) +38 + j*(-105) +-42 + j*(-90) +-61 + j*(-25) +-17 + j*(21) +47 + j*(-12) +19 + j*(-93) +-73 + j*(-64) +-35 + j*(26) +56 + j*(-37) +-26 + j*(-142) +-135 + j*(-66) +-85 + j*(6) +-86 + j*(-47) +-186 + j*(16) +-110 + j*(165) +38 + j*(110) +-9 + j*(1) +-79 + j*(61) +-27 + j*(107) +-32 + j*(104) +21 + j*(213) +260 + j*(155) +242 + j*(-181) +-134 + j*(-202) +-160 + j*(181) +224 + j*(190) +216 + j*(-189) +-139 + j*(-156) +-69 + j*(175) +260 + j*(72) +172 + j*(-259) +-123 + j*(-233) +-154 + j*(-45) +-105 + j*(-16) +-145 + j*(29) +-96 + j*(141) +24 + j*(151) +79 + j*(110) +144 + j*(78) +197 + j*(-41) +103 + j*(-162) +-15 + j*(-137) +-24 + j*(-78) +-23 + j*(-83) +-43 + j*(-78) +-48 + j*(-87) +-113 + j*(-107) +-196 + j*(-16) +-129 + j*(103) +-30 + j*(62) +-91 + j*(1) +-163 + j*(100) +-78 + j*(225) +67 + j*(235) +181 + j*(153) +216 + j*(4) +111 + j*(-110) +-6 + j*(-66) +16 + j*(-4) +25 + j*(-49) +-65 + j*(-36) +-69 + j*(85) +42 + j*(132) +122 + j*(88) +175 + j*(18) +159 + j*(-100) +31 + j*(-126) +30 + j*(-3) +199 + j*(-62) +119 + j*(-332) +-223 + j*(-313) +-296 + j*(4) +-91 + j*(117) +-18 + j*(42) +1 + j*(54) +105 + j*(-19) +12 + j*(-202) +-216 + j*(-123) +-162 + j*(92) +-13 + j*(24) +-153 + j*(-72) +-262 + j*(153) +-11 + j*(321) +198 + j*(113) +51 + j*(-77) +-103 + j*(44) +4 + j*(185) +151 + j*(115) +144 + j*(-12) +74 + j*(-54) +22 + j*(-39) +2 + j*(20) +88 + j*(78) +228 + j*(-34) +148 + j*(-286) +-177 + j*(-305) +-310 + j*(6) +-71 + j*(195) +112 + j*(17) +-47 + j*(-148) +-235 + j*(1) +-142 + j*(242) +117 + j*(265) +272 + j*(52) +167 + j*(-184) +-72 + j*(-199) +-171 + j*(-28) +-112 + j*(79) +-78 + j*(122) +5 + j*(219) +218 + j*(185) +282 + j*(-69) +71 + j*(-206) +-76 + j*(-67) +15 + j*(54) +127 + j*(-10) +110 + j*(-136) +-12 + j*(-192) +-136 + j*(-111) +-108 + j*(28) +11 + j*(23) +-10 + j*(-81) +-129 + j*(-52) +-131 + j*(86) +-10 + j*(163) +151 + j*(122) +234 + j*(-81) +56 + j*(-294) +-225 + j*(-198) +-224 + j*(59) +-66 + j*(95) +-71 + j*(54) +-40 + j*(144) +126 + j*(98) +96 + j*(-96) +-75 + j*(-85) +-69 + j*(23) +-50 + j*(-3) +-115 + j*(64) +8 + j*(177) +144 + j*(28) +-23 + j*(-90) +-106 + j*(107) +122 + j*(170) +179 + j*(-56) +0 + j*(-101) +4 + j*(23) +95 + j*(-48) +-16 + j*(-141) +-111 + j*(-45) +-58 + j*(23) +-47 + j*(-2) +-88 + j*(36) +-48 + j*(116) +69 + j*(120) +136 + j*(-18) +-23 + j*(-159) +-256 + j*(24) +-80 + j*(365) +330 + j*(245) +287 + j*(-135) +37 + j*(-103) +168 + j*(-3) +186 + j*(-301) +-249 + j*(-327) +-316 + j*(146) +108 + j*(220) +131 + j*(-115) +-116 + j*(-52) +32 + j*(124) +145 + j*(-91) +-105 + j*(-140) +-87 + j*(123) +180 + j*(47) +63 + j*(-209) +-160 + j*(-81) +-38 + j*(88) +64 + j*(-7) +20 + j*(-28) +115 + j*(-38) +99 + j*(-277) +-234 + j*(-341) +-409 + j*(-42) +-264 + j*(163) +-161 + j*(181) +-78 + j*(243) +97 + j*(187) +78 + j*(-12) +-109 + j*(10) +-78 + j*(188) +74 + j*(170) +57 + j*(90) +52 + j*(166) +225 + j*(163) +296 + j*(-59) +115 + j*(-217) +-72 + j*(-135) +-82 + j*(17) +-6 + j*(81) +66 + j*(100) +185 + j*(84) +301 + j*(-90) +166 + j*(-356) +-186 + j*(-339) +-274 + j*(-1) +9 + j*(103) +66 + j*(-180) +-290 + j*(-209) +-366 + j*(228) +91 + j*(401) +346 + j*(-5) +26 + j*(-292) +-251 + j*(-59) +-98 + j*(175) +66 + j*(78) +-12 + j*(8) +-7 + j*(115) +160 + j*(83) +155 + j*(-130) +-54 + j*(-180) +-153 + j*(-28) +-89 + j*(84) +-6 + j*(110) +89 + j*(86) +142 + j*(-53) +-13 + j*(-197) +-251 + j*(-72) +-217 + j*(242) +96 + j*(346) +317 + j*(132) +251 + j*(-104) +109 + j*(-132) +105 + j*(-97) +118 + j*(-192) +-37 + j*(-279) +-204 + j*(-156) +-153 + j*(13) +-40 + j*(-14) +-92 + j*(-90) +-186 + j*(-26) +-175 + j*(81) +-127 + j*(153) +-21 + j*(222) +151 + j*(170) +187 + j*(-21) +50 + j*(-118) +-42 + j*(-59) +-39 + j*(-8) +-21 + j*(18) +40 + j*(1) +13 + j*(-132) +-224 + j*(-133) +-315 + j*(181) +-11 + j*(388) +260 + j*(185) +177 + j*(-47) +52 + j*(-30) +74 + j*(-1) +69 + j*(-54) +11 + j*(-70) +-47 + j*(-48) +-98 + j*(51) +21 + j*(202) +278 + j*(107) +259 + j*(-214) +-47 + j*(-292) +-184 + j*(-76) +-87 + j*(51) +-16 + j*(53) +48 + j*(52) +106 + j*(-47) +0 + j*(-146) +-110 + j*(-61) +-61 + j*(11) +-78 + j*(-21) +-138 + j*(102) +61 + j*(233) +269 + j*(23) +98 + j*(-221) +-117 + j*(-100) +-11 + j*(49) +83 + j*(-84) +-86 + j*(-168) +-194 + j*(12) +-35 + j*(151) +134 + j*(22) +34 + j*(-185) +-217 + j*(-127) +-222 + j*(148) +38 + j*(204) +94 + j*(-13) +-94 + j*(-19) +-34 + j*(184) +206 + j*(78) +87 + j*(-186) +-176 + j*(-74) +-70 + j*(165) +139 + j*(65) +45 + j*(-117) +-125 + j*(-42) +-93 + j*(124) +66 + j*(168) +198 + j*(37) +115 + j*(-163) +-119 + j*(-122) +-93 + j*(118) +155 + j*(82) +110 + j*(-169) +-119 + j*(-132) +-86 + j*(26) +-31 + j*(-42) +-178 + j*(-10) +-111 + j*(211) +130 + j*(144) +46 + j*(-66) +-131 + j*(70) +38 + j*(249) +221 + j*(107) +157 + j*(-16) +155 + j*(-5) +179 + j*(-116) +18 + j*(-182) +-58 + j*(-21) +92 + j*(47) +168 + j*(-78) +130 + j*(-164) +100 + j*(-258) +-71 + j*(-373) +-326 + j*(-263) +-372 + j*(6) +-234 + j*(173) +-55 + j*(218) +138 + j*(98) +81 + j*(-190) +-284 + j*(-191) +-366 + j*(220) +19 + j*(387) +223 + j*(95) +37 + j*(-59) +-33 + j*(66) +74 + j*(77) +67 + j*(-16) +18 + j*(-8) +35 + j*(-17) +-20 + j*(-47) +-59 + j*(38) +51 + j*(74) +84 + j*(-63) +-71 + j*(-116) +-163 + j*(29) +-78 + j*(157) +45 + j*(167) +136 + j*(98) +145 + j*(-29) +32 + j*(-86) +-31 + j*(0) +45 + j*(35) +37 + j*(-54) +-79 + j*(-17) +-37 + j*(136) +124 + j*(117) +135 + j*(4) +116 + j*(9) +202 + j*(-54) +114 + j*(-238) +-129 + j*(-163) +-43 + j*(97) +244 + j*(-28) +110 + j*(-376) +-279 + j*(-310) +-317 + j*(26) +-120 + j*(119) +-50 + j*(67) +-16 + j*(54) +-6 + j*(-23) +-122 + j*(-19) +-99 + j*(146) +88 + j*(121) +55 + j*(-42) +-49 + j*(33) +95 + j*(83) +111 + j*(-130) +-130 + j*(-122) +-85 + j*(98) +86 + j*(-28) +-152 + j*(-158) +-274 + j*(185) +112 + j*(320) +233 + j*(-37) +-53 + j*(-80) +35 + j*(146) +236 + j*(-71) +-59 + j*(-267) +-232 + j*(49) +74 + j*(153) +74 + j*(-140) +-220 + j*(-44) +-60 + j*(252) +216 + j*(71) +47 + j*(-149) +-83 + j*(-3) +47 + j*(13) +-41 + j*(-135) +-235 + j*(13) +-110 + j*(233) +67 + j*(183) +64 + j*(119) +117 + j*(146) +194 + j*(61) +143 + j*(-20) +128 + j*(15) +204 + j*(-31) +170 + j*(-153) +68 + j*(-177) +22 + j*(-149) +-2 + j*(-132) +5 + j*(-116) +-2 + j*(-176) +-142 + j*(-200) +-238 + j*(-6) +-39 + j*(161) +194 + j*(-13) +81 + j*(-310) +-246 + j*(-333) +-436 + j*(-70) +-335 + j*(222) +-67 + j*(279) +45 + j*(95) +-96 + j*(21) +-137 + j*(187) +50 + j*(249) +135 + j*(106) +70 + j*(63) +136 + j*(97) +212 + j*(-73) +5 + j*(-238) +-239 + j*(-66) +-150 + j*(211) +103 + j*(215) +163 + j*(35) +57 + j*(-25) +30 + j*(62) +146 + j*(84) +233 + j*(-52) +152 + j*(-210) +-9 + j*(-251) +-136 + j*(-193) +-221 + j*(-83) +-220 + j*(81) +-87 + j*(194) +66 + j*(155) +107 + j*(48) +74 + j*(-18) +21 + j*(-40) +-28 + j*(-1) +13 + j*(69) +110 + j*(30) +85 + j*(-83) +-18 + j*(-68) +13 + j*(9) +90 + j*(-57) +10 + j*(-161) +-117 + j*(-118) +-137 + j*(-20) +-113 + j*(33) +-80 + j*(78) +-25 + j*(77) +-42 + j*(56) +-46 + j*(147) +124 + j*(187) +217 + j*(-13) +31 + j*(-104) +2 + j*(95) +279 + j*(64) +256 + j*(-303) +-119 + j*(-344) +-187 + j*(-61) +-23 + j*(-69) +-168 + j*(-178) +-296 + j*(68) +-33 + j*(220) +90 + j*(-9) +-116 + j*(-49) +-62 + j*(161) +171 + j*(33) +8 + j*(-227) +-273 + j*(-74) +-165 + j*(191) +39 + j*(132) +1 + j*(-1) +-91 + j*(30) +-94 + j*(113) +-35 + j*(174) +59 + j*(161) +62 + j*(87) +10 + j*(141) +151 + j*(231) +321 + j*(64) +194 + j*(-141) +42 + j*(-47) +175 + j*(44) +270 + j*(-148) +98 + j*(-295) +-53 + j*(-226) +-73 + j*(-174) +-142 + j*(-168) +-224 + j*(-60) +-188 + j*(91) +-53 + j*(160) +82 + j*(100) +92 + j*(-41) +-30 + j*(-74) +-54 + j*(42) +82 + j*(57) +119 + j*(-100) +-28 + j*(-187) +-156 + j*(-103) +-156 + j*(23) +-69 + j*(81) +-1 + j*(32) +-45 + j*(-26) +-103 + j*(35) +-39 + j*(94) +-1 + j*(37) +-69 + j*(52) +-14 + j*(148) +107 + j*(83) +38 + j*(-28) +-47 + j*(65) +69 + j*(149) +162 + j*(56) +148 + j*(-6) +187 + j*(-57) +151 + j*(-212) +-47 + j*(-245) +-120 + j*(-114) +-88 + j*(-104) +-215 + j*(-94) +-254 + j*(150) +25 + j*(280) +215 + j*(49) +75 + j*(-141) +-57 + j*(-86) +-49 + j*(-52) +-116 + j*(-78) +-218 + j*(32) +-154 + j*(216) +44 + j*(256) +159 + j*(120) +93 + j*(11) +29 + j*(79) +168 + j*(136) +289 + j*(-55) +121 + j*(-248) +-80 + j*(-144) +-9 + j*(2) +95 + j*(-88) +-16 + j*(-204) +-158 + j*(-133) +-169 + j*(-13) +-126 + j*(45) +-87 + j*(78) +-39 + j*(97) +15 + j*(76) +16 + j*(18) +-62 + j*(27) +-51 + j*(170) +177 + j*(209) +314 + j*(-57) +86 + j*(-280) +-158 + j*(-137) +-91 + j*(60) +25 + j*(33) +6 + j*(-6) +29 + j*(25) +83 + j*(-34) +33 + j*(-112) +-38 + j*(-119) +-115 + j*(-112) +-223 + j*(7) +-120 + j*(232) +189 + j*(190) +219 + j*(-157) +-121 + j*(-256) +-274 + j*(45) +-37 + j*(234) +153 + j*(59) +25 + j*(-115) +-133 + j*(-16) +-61 + j*(133) +59 + j*(97) +47 + j*(34) +62 + j*(63) +148 + j*(-17) +33 + j*(-173) +-186 + j*(-53) +-88 + j*(214) +206 + j*(169) +242 + j*(-101) +56 + j*(-220) +-110 + j*(-164) +-190 + j*(8) +-42 + j*(207) +250 + j*(103) +214 + j*(-243) +-114 + j*(-279) +-187 + j*(-39) +-49 + j*(-1) +-78 + j*(-83) +-148 + j*(-26) +-132 + j*(13) +-185 + j*(52) +-146 + j*(223) +103 + j*(230) +155 + j*(-30) +-83 + j*(-110) +-197 + j*(76) +-116 + j*(229) +21 + j*(315) +247 + j*(280) +337 + j*(28) +148 + j*(-100) +95 + j*(46) +279 + j*(8) +224 + j*(-229) +4 + j*(-213) +19 + j*(-83) +58 + j*(-142) +-37 + j*(-124) +52 + j*(-28) +164 + j*(-220) +-91 + j*(-414) +-366 + j*(-209) +-298 + j*(42) +-187 + j*(81) +-144 + j*(138) +12 + j*(137) +37 + j*(-57) +-192 + j*(-78) +-225 + j*(185) +33 + j*(250) +116 + j*(46) +-38 + j*(-6) +-51 + j*(135) +100 + j*(148) +154 + j*(6) +57 + j*(-79) +-26 + j*(-34) +-6 + j*(18) +17 + j*(-15) +-52 + j*(-29) +-91 + j*(77) +27 + j*(167) +163 + j*(81) +145 + j*(-67) +37 + j*(-111) +-34 + j*(-67) +-49 + j*(-6) +-13 + j*(38) +33 + j*(25) +28 + j*(-11) +10 + j*(5) +55 + j*(19) +85 + j*(-62) +-13 + j*(-122) +-99 + j*(-35) +-28 + j*(44) +11 + j*(-31) +-107 + j*(-26) +-80 + j*(164) +177 + j*(151) +196 + j*(-140) +-95 + j*(-177) +-123 + j*(104) +161 + j*(116) +181 + j*(-173) +-81 + j*(-233) +-182 + j*(-49) +-103 + j*(49) +-45 + j*(55) +-7 + j*(40) +-18 + j*(9) +-38 + j*(62) +76 + j*(97) +147 + j*(-59) +1 + j*(-163) +-95 + j*(-69) +-64 + j*(-48) +-163 + j*(-59) +-209 + j*(148) +40 + j*(250) +170 + j*(28) +2 + j*(-81) +-56 + j*(37) +15 + j*(49) +-16 + j*(30) +20 + j*(98) +111 + j*(29) +21 + j*(-49) +-20 + j*(66) +112 + j*(75) +100 + j*(-32) +85 + j*(42) +291 + j*(-49) +173 + j*(-420) +-298 + j*(-370) +-324 + j*(59) +-48 + j*(74) +-159 + j*(-41) +-181 + j*(245) +249 + j*(251) +287 + j*(-256) +-209 + j*(-344) +-335 + j*(52) +-99 + j*(153) +-103 + j*(59) +-148 + j*(183) +20 + j*(267) +143 + j*(168) +164 + j*(77) +154 + j*(-22) +39 + j*(-74) +-16 + j*(31) +81 + j*(57) +69 + j*(-30) +8 + j*(27) +122 + j*(63) +148 + j*(-88) +8 + j*(-102) +31 + j*(-4) +88 + j*(-91) +-49 + j*(-115) +-43 + j*(47) +124 + j*(12) +73 + j*(-129) +17 + j*(-69) +127 + j*(-136) +-30 + j*(-349) +-322 + j*(-190) +-207 + j*(65) +-92 + j*(-72) +-361 + j*(-65) +-357 + j*(356) +94 + j*(453) +255 + j*(125) +100 + j*(25) +146 + j*(93) +240 + j*(-49) +127 + j*(-201) +-4 + j*(-204) +-99 + j*(-184) +-204 + j*(-93) +-183 + j*(53) +-101 + j*(95) +-60 + j*(116) +37 + j*(127) +93 + j*(2) +-21 + j*(-56) +-40 + j*(37) +48 + j*(-22) +-98 + j*(-139) +-279 + j*(56) +-123 + j*(288) +81 + j*(230) +97 + j*(149) +161 + j*(140) +210 + j*(7) +93 + j*(-68) +64 + j*(6) +116 + j*(-44) +-8 + j*(-90) +-49 + j*(92) +177 + j*(143) +261 + j*(-70) +144 + j*(-159) +139 + j*(-167) +78 + j*(-310) +-162 + j*(-307) +-234 + j*(-112) +-184 + j*(-62) +-274 + j*(4) +-209 + j*(250) +97 + j*(261) +163 + j*(23) +49 + j*(-13) +113 + j*(1) +88 + j*(-163) +-120 + j*(-135) +-76 + j*(54) +69 + j*(-40) +-93 + j*(-144) +-165 + j*(64) +66 + j*(83) +15 + j*(-163) +-262 + j*(-41) +-98 + j*(272) +240 + j*(97) +84 + j*(-248) +-245 + j*(-141) +-202 + j*(138) +-9 + j*(141) +-1 + j*(28) +-83 + j*(39) +-77 + j*(132) +23 + j*(163) +81 + j*(83) +12 + j*(46) +16 + j*(149) +179 + j*(144) +218 + j*(-46) +69 + j*(-117) +20 + j*(-46) +28 + j*(-66) +-68 + j*(-49) +-46 + j*(98) +112 + j*(77) +72 + j*(-54) +-12 + j*(48) +187 + j*(113) +289 + j*(-169) +-6 + j*(-335) +-197 + j*(-103) +-42 + j*(43) +20 + j*(-68) +-81 + j*(-54) +-11 + j*(52) +110 + j*(-62) +-29 + j*(-222) +-240 + j*(-105) +-187 + j*(134) +35 + j*(152) +90 + j*(-28) +-54 + j*(-78) +-71 + j*(60) +93 + j*(36) +40 + j*(-177) +-226 + j*(-124) +-188 + j*(163) +86 + j*(129) +23 + j*(-124) +-231 + j*(-31) +-148 + j*(234) +86 + j*(197) +88 + j*(45) +25 + j*(46) +52 + j*(56) +45 + j*(24) +30 + j*(45) +59 + j*(49) +66 + j*(45) +127 + j*(57) +200 + j*(-73) +43 + j*(-219) +-136 + j*(-70) +16 + j*(93) +148 + j*(-98) +-89 + j*(-221) +-221 + j*(32) +6 + j*(159) +101 + j*(-30) +-57 + j*(-80) +-86 + j*(57) +13 + j*(91) +62 + j*(70) +149 + j*(31) +168 + j*(-148) +-50 + j*(-239) +-175 + j*(-48) +-16 + j*(45) +9 + j*(-124) +-214 + j*(-118) +-241 + j*(146) +-8 + j*(228) +90 + j*(82) +18 + j*(32) +32 + j*(85) +107 + j*(50) +110 + j*(-39) +56 + j*(-98) +-40 + j*(-115) +-132 + j*(-23) +-74 + j*(122) +91 + j*(100) +89 + j*(-47) +-24 + j*(-38) +23 + j*(49) +101 + j*(-47) +-33 + j*(-129) +-115 + j*(35) +75 + j*(115) +168 + j*(-95) +-33 + j*(-216) +-160 + j*(-74) +-98 + j*(11) +-95 + j*(-8) +-118 + j*(54) +-52 + j*(83) +-64 + j*(42) +-121 + j*(134) +11 + j*(265) +197 + j*(185) +222 + j*(35) +206 + j*(-37) +188 + j*(-154) +32 + j*(-243) +-110 + j*(-148) +-96 + j*(-51) +-106 + j*(-40) +-139 + j*(66) +8 + j*(163) +144 + j*(21) +14 + j*(-112) +-97 + j*(24) +70 + j*(129) +204 + j*(-57) +37 + j*(-243) +-178 + j*(-142) +-157 + j*(46) +-51 + j*(66) +-57 + j*(59) +1 + j*(157) +222 + j*(100) +239 + j*(-216) +-88 + j*(-344) +-288 + j*(-112) +-199 + j*(47) +-189 + j*(48) +-208 + j*(198) +13 + j*(298) +150 + j*(100) +-20 + j*(11) +-41 + j*(216) +219 + j*(242) +327 + j*(5) +231 + j*(-164) +106 + j*(-264) +-136 + j*(-272) +-288 + j*(7) +-48 + j*(240) +183 + j*(67) +69 + j*(-98) +8 + j*(-6) +122 + j*(-62) +-15 + j*(-235) +-255 + j*(-78) +-135 + j*(192) +119 + j*(133) +104 + j*(-75) +-58 + j*(-89) +-105 + j*(45) +6 + j*(143) +162 + j*(75) +156 + j*(-111) +-13 + j*(-154) +-62 + j*(-30) +33 + j*(-12) +28 + j*(-91) +-11 + j*(-88) +13 + j*(-136) +-122 + j*(-258) +-389 + j*(-124) +-364 + j*(233) +-42 + j*(342) +110 + j*(139) +2 + j*(38) +-25 + j*(129) +90 + j*(124) +81 + j*(5) +-28 + j*(35) +36 + j*(149) +177 + j*(70) +100 + j*(-72) +-10 + j*(13) +117 + j*(105) +227 + j*(-49) +110 + j*(-186) +2 + j*(-158) +-42 + j*(-147) +-136 + j*(-84) +-80 + j*(61) +59 + j*(-19) +-93 + j*(-139) +-214 + j*(105) +108 + j*(238) +248 + j*(-132) +-146 + j*(-269) +-270 + j*(115) +57 + j*(209) +85 + j*(-21) +-40 + j*(62) +174 + j*(110) +185 + j*(-214) +-194 + j*(-202) +-136 + j*(186) +248 + j*(59) +61 + j*(-331) +-327 + j*(-134) +-161 + j*(205) +70 + j*(64) +-84 + j*(-35) +-82 + j*(168) +170 + j*(116) +105 + j*(-159) +-163 + j*(-94) +-102 + j*(147) +100 + j*(89) +31 + j*(-79) +-114 + j*(4) +-25 + j*(144) +112 + j*(64) +41 + j*(-65) +-84 + j*(9) +-18 + j*(151) +137 + j*(129) +190 + j*(9) +163 + j*(-89) +85 + j*(-173) +-68 + j*(-154) +-93 + j*(26) +119 + j*(64) +183 + j*(-209) +-139 + j*(-343) +-365 + j*(-29) +-107 + j*(252) +180 + j*(51) +11 + j*(-232) +-279 + j*(-96) +-200 + j*(193) +42 + j*(170) +37 + j*(-5) +-93 + j*(13) +-81 + j*(137) +21 + j*(187) +158 + j*(174) +303 + j*(-10) +155 + j*(-324) +-275 + j*(-277) +-348 + j*(180) +57 + j*(327) +197 + j*(1) +-89 + j*(-71) +-107 + j*(244) +254 + j*(283) +382 + j*(-61) +137 + j*(-263) +-69 + j*(-141) +-19 + j*(32) +138 + j*(8) +135 + j*(-159) +-20 + j*(-175) +-9 + j*(-51) +126 + j*(-153) +-52 + j*(-384) +-409 + j*(-234) +-389 + j*(165) +-78 + j*(276) +81 + j*(133) +94 + j*(11) +42 + j*(-99) +-103 + j*(-112) +-155 + j*(25) +-57 + j*(74) +-47 + j*(23) +-64 + j*(69) +36 + j*(51) +-16 + j*(-105) +-230 + j*(-46) +-211 + j*(189) +-51 + j*(221) +-39 + j*(208) +67 + j*(312) +308 + j*(188) +240 + j*(-112) +-30 + j*(-91) +-16 + j*(126) +153 + j*(117) +170 + j*(12) +156 + j*(-11) +173 + j*(-64) +130 + j*(-112) +123 + j*(-123) +100 + j*(-220) +-86 + j*(-247) +-170 + j*(-43) +21 + j*(40) +64 + j*(-161) +-175 + j*(-176) +-196 + j*(100) +91 + j*(138) +151 + j*(-144) +-111 + j*(-234) +-230 + j*(-19) +-85 + j*(96) +-11 + j*(9) +-78 + j*(-10) +-66 + j*(57) +-17 + j*(30) +-70 + j*(21) +-45 + j*(133) +139 + j*(109) +154 + j*(-121) +-70 + j*(-189) +-165 + j*(-28) +-98 + j*(46) +-93 + j*(60) +-33 + j*(136) +93 + j*(59) +-5 + j*(-81) +-144 + j*(55) +36 + j*(194) +176 + j*(-16) +-49 + j*(-146) +-166 + j*(75) +32 + j*(179) +109 + j*(33) +25 + j*(9) +74 + j*(42) +80 + j*(-77) +-93 + j*(-79) +-105 + j*(128) +111 + j*(162) +170 + j*(-36) +-4 + j*(-98) +-60 + j*(74) +142 + j*(148) +281 + j*(-80) +70 + j*(-296) +-184 + j*(-135) +-49 + j*(103) +166 + j*(-62) +-46 + j*(-301) +-354 + j*(-80) +-202 + j*(281) +147 + j*(244) +206 + j*(-15) +78 + j*(-109) +20 + j*(-95) +-17 + j*(-116) +-112 + j*(-98) +-159 + j*(30) +-44 + j*(146) +110 + j*(66) +59 + j*(-88) +-69 + j*(-35) +13 + j*(67) +104 + j*(-51) +-37 + j*(-129) +-83 + j*(6) +40 + j*(-13) +-67 + j*(-129) +-181 + j*(74) +120 + j*(185) +238 + j*(-213) +-223 + j*(-363) +-411 + j*(107) +-2 + j*(288) +109 + j*(-43) +-169 + j*(-46) +-73 + j*(214) +182 + j*(56) +-7 + j*(-186) +-223 + j*(5) +-57 + j*(177) +38 + j*(27) +-137 + j*(19) +-122 + j*(259) +152 + j*(303) +272 + j*(86) +-58 + j*(-93) +-100 + j*(0) +-47 + j*(62) +-12 + j*(48) +-19 + j*(68) +38 + j*(112) +134 + j*(77) +177 + j*(-38) +98 + j*(-164) +-70 + j*(-146) +-91 + j*(26) +86 + j*(44) +100 + j*(-155) +-105 + j*(-187) +-153 + j*(-31) +-88 + j*(-11) +-148 + j*(4) +-104 + j*(144) +77 + j*(93) +1 + j*(-83) +-163 + j*(29) +-42 + j*(179) +59 + j*(88) +6 + j*(103) +173 + j*(161) +295 + j*(-125) +-27 + j*(-320) +-240 + j*(-48) +-51 + j*(89) +-64 + j*(-56) +-240 + j*(108) +-5 + j*(366) +302 + j*(178) +229 + j*(-81) +117 + j*(-100) +71 + j*(-159) +-107 + j*(-115) +-44 + j*(127) +263 + j*(4) +87 + j*(-390) +-380 + j*(-223) +-282 + j*(247) +94 + j*(209) +51 + j*(-11) +-28 + j*(110) +204 + j*(122) +228 + j*(-181) +-72 + j*(-256) +-180 + j*(-27) +-45 + j*(78) +35 + j*(24) +47 + j*(-24) +25 + j*(-95) +-91 + j*(-107) +-139 + j*(34) +9 + j*(113) +112 + j*(-32) +-18 + j*(-163) +-177 + j*(-57) +-107 + j*(117) +78 + j*(79) +77 + j*(-130) +-155 + j*(-194) +-317 + j*(21) +-192 + j*(254) +25 + j*(245) +75 + j*(124) +42 + j*(116) +113 + j*(134) +172 + j*(31) +92 + j*(-42) +69 + j*(21) +177 + j*(-21) +120 + j*(-209) +-117 + j*(-191) +-136 + j*(36) +48 + j*(42) +5 + j*(-117) +-158 + j*(-22) +-24 + j*(159) +185 + j*(-5) +11 + j*(-269) +-325 + j*(-140) +-317 + j*(235) +-3 + j*(373) +219 + j*(210) +212 + j*(26) +151 + j*(-43) +105 + j*(-101) +-23 + j*(-127) +-122 + j*(30) +38 + j*(196) +255 + j*(71) +202 + j*(-150) +57 + j*(-155) +62 + j*(-115) +39 + j*(-182) +-60 + j*(-165) +-47 + j*(-109) +-64 + j*(-175) +-222 + j*(-132) +-204 + j*(82) +8 + j*(83) +1 + j*(-105) +-180 + j*(-86) +-175 + j*(76) +-64 + j*(91) +-54 + j*(36) +-90 + j*(42) +-106 + j*(91) +-60 + j*(166) +63 + j*(159) +100 + j*(40) +21 + j*(1) +16 + j*(33) +9 + j*(-4) +-69 + j*(47) +34 + j*(168) +188 + j*(21) +13 + j*(-138) +-121 + j*(76) +148 + j*(175) +223 + j*(-135) +-93 + j*(-193) +-115 + j*(88) +107 + j*(58) +14 + j*(-93) +-54 + j*(69) +182 + j*(64) +148 + j*(-245) +-184 + j*(-229) +-210 + j*(34) +-93 + j*(59) +-148 + j*(106) +-1 + j*(295) +303 + j*(149) +215 + j*(-178) +-49 + j*(-133) +8 + j*(54) +163 + j*(-39) +81 + j*(-192) +-59 + j*(-179) +-118 + j*(-100) +-118 + j*(-17) +-53 + j*(13) +-23 + j*(-49) +-103 + j*(-74) +-150 + j*(24) +-73 + j*(118) +40 + j*(91) +52 + j*(-34) +-111 + j*(-65) +-180 + j*(177) +151 + j*(338) +451 + j*(-25) +139 + j*(-444) +-315 + j*(-242) +-226 + j*(152) +42 + j*(132) +35 + j*(14) +57 + j*(62) +177 + j*(-66) +-3 + j*(-282) +-297 + j*(-113) +-188 + j*(219) +132 + j*(180) +148 + j*(-101) +-95 + j*(-163) +-209 + j*(33) +-90 + j*(197) +86 + j*(182) +173 + j*(62) +156 + j*(-76) +34 + j*(-168) +-134 + j*(-119) +-182 + j*(73) +-31 + j*(220) +190 + j*(178) +297 + j*(-51) +141 + j*(-304) +-197 + j*(-269) +-278 + j*(76) +25 + j*(207) +144 + j*(-59) +-113 + j*(-132) +-148 + j*(136) +122 + j*(145) +107 + j*(-110) +-127 + j*(-78) +-93 + j*(135) +77 + j*(127) +96 + j*(30) +80 + j*(14) +95 + j*(-9) +99 + j*(-38) +117 + j*(-107) +3 + j*(-215) +-190 + j*(-97) +-77 + j*(134) +146 + j*(0) +-30 + j*(-206) +-221 + j*(6) +1 + j*(166) +99 + j*(-44) +-90 + j*(-54) +-4 + j*(112) +129 + j*(-68) +-141 + j*(-153) +-177 + j*(202) +255 + j*(204) +247 + j*(-276) +-231 + j*(-282) +-257 + j*(129) +39 + j*(151) +18 + j*(-12) +-31 + j*(76) +124 + j*(52) +65 + j*(-145) +-137 + j*(-75) +-69 + j*(94) +24 + j*(14) +-105 + j*(13) +-45 + j*(247) +314 + j*(206) +386 + j*(-235) +-34 + j*(-457) +-368 + j*(-156) +-218 + j*(197) +83 + j*(174) +133 + j*(-45) +3 + j*(-134) +-103 + j*(-102) +-164 + j*(-21) +-149 + j*(93) +-49 + j*(140) +1 + j*(98) +-2 + j*(107) +66 + j*(122) +112 + j*(45) +75 + j*(13) +108 + j*(7) +89 + j*(-122) +-135 + j*(-112) +-146 + j*(194) +220 + j*(252) +347 + j*(-121) +47 + j*(-301) +-122 + j*(-133) +-78 + j*(-59) +-132 + j*(-39) +-121 + j*(107) +43 + j*(123) +65 + j*(3) +0 + j*(6) +28 + j*(19) +-25 + j*(-3) +-30 + j*(155) +253 + j*(176) +336 + j*(-194) +-51 + j*(-327) +-173 + j*(32) +180 + j*(102) +216 + j*(-272) +-151 + j*(-323) +-221 + j*(-20) +2 + j*(30) +21 + j*(-152) +-139 + j*(-194) +-252 + j*(-92) +-257 + j*(56) +-141 + j*(144) +-59 + j*(66) +-171 + j*(40) +-189 + j*(245) +78 + j*(329) +228 + j*(83) +52 + j*(-64) +-35 + j*(65) +88 + j*(93) +81 + j*(-29) +-19 + j*(4) +51 + j*(73) +91 + j*(-49) +-89 + j*(-61) +-86 + j*(194) +256 + j*(208) +338 + j*(-194) +-61 + j*(-372) +-310 + j*(-57) +-134 + j*(196) +39 + j*(155) +78 + j*(124) +184 + j*(71) +158 + j*(-110) +-35 + j*(-86) +41 + j*(105) +264 + j*(-45) +71 + j*(-322) +-231 + j*(-133) +-52 + j*(143) +177 + j*(-59) +-62 + j*(-261) +-265 + j*(-12) +-57 + j*(189) +100 + j*(47) +11 + j*(-28) +30 + j*(59) +171 + j*(-17) +115 + j*(-232) +-136 + j*(-275) +-298 + j*(-68) +-198 + j*(163) +26 + j*(162) +63 + j*(-18) +-88 + j*(-41) +-87 + j*(114) +82 + j*(100) +62 + j*(-83) +-148 + j*(-65) +-165 + j*(178) +78 + j*(281) +283 + j*(105) +230 + j*(-146) +14 + j*(-204) +-83 + j*(-59) +19 + j*(8) +47 + j*(-107) +-103 + j*(-122) +-119 + j*(39) +34 + j*(43) +8 + j*(-108) +-144 + j*(-64) +-92 + j*(64) +-23 + j*(-25) +-202 + j*(-58) +-268 + j*(207) +-1 + j*(356) +174 + j*(184) +100 + j*(89) +133 + j*(158) +271 + j*(72) +241 + j*(-103) +148 + j*(-155) +100 + j*(-218) +-76 + j*(-274) +-255 + j*(-100) +-162 + j*(118) +-14 + j*(100) +-36 + j*(74) +29 + j*(173) +219 + j*(96) +190 + j*(-135) +-16 + j*(-155) +-52 + j*(0) +69 + j*(35) +124 + j*(-68) +57 + j*(-160) +-52 + j*(-144) +-59 + j*(-53) +17 + j*(-84) +-78 + j*(-204) +-276 + j*(-84) +-190 + j*(167) +47 + j*(124) +13 + j*(-64) +-138 + j*(-23) +-124 + j*(95) +-76 + j*(151) +35 + j*(229) +257 + j*(121) +202 + j*(-192) +-126 + j*(-186) +-129 + j*(104) +112 + j*(78) +50 + j*(-122) +-115 + j*(-42) +-47 + j*(78) +13 + j*(50) +39 + j*(70) +154 + j*(0) +69 + j*(-195) +-146 + j*(-127) +-76 + j*(21) +-59 + j*(-121) +-358 + j*(-37) +-269 + j*(436) +284 + j*(436) +382 + j*(-49) +68 + j*(-164) +28 + j*(-40) +11 + j*(-114) +-161 + j*(-1) +25 + j*(226) +277 + j*(-13) +2 + j*(-267) +-229 + j*(18) +38 + j*(206) +164 + j*(-23) +-12 + j*(-69) +23 + j*(59) +113 + j*(-27) +19 + j*(-70) +52 + j*(20) +153 + j*(-98) +1 + j*(-229) +-131 + j*(-111) +-78 + j*(-48) +-129 + j*(-68) +-166 + j*(77) +5 + j*(139) +53 + j*(0) +-34 + j*(21) +91 + j*(74) +140 + j*(-159) +-173 + j*(-236) +-292 + j*(107) +22 + j*(258) +171 + j*(2) +-24 + j*(-113) +-100 + j*(34) +14 + j*(82) +34 + j*(-3) +-37 + j*(-2) +-23 + j*(80) +86 + j*(86) +136 + j*(-40) +23 + j*(-136) +-95 + j*(-59) +-56 + j*(43) +0 + j*(30) +-11 + j*(40) +77 + j*(76) +170 + j*(-75) +3 + j*(-244) +-219 + j*(-118) +-163 + j*(91) +-27 + j*(72) +-74 + j*(15) +-110 + j*(128) +45 + j*(200) +165 + j*(61) +72 + j*(-80) +-64 + j*(-24) +-37 + j*(105) +81 + j*(119) +138 + j*(49) +156 + j*(-16) +142 + j*(-117) +9 + j*(-184) +-108 + j*(-65) +-1 + j*(55) +105 + j*(-69) +-52 + j*(-182) +-187 + j*(-1) +-2 + j*(153) +178 + j*(-25) +27 + j*(-255) +-250 + j*(-187) +-313 + j*(76) +-156 + j*(240) +-13 + j*(222) +21 + j*(215) +143 + j*(276) +366 + j*(147) +343 + j*(-151) +117 + j*(-214) +105 + j*(-119) +141 + j*(-264) +-132 + j*(-344) +-269 + j*(-49) +-8 + j*(69) +23 + j*(-182) +-247 + j*(-142) +-164 + j*(129) +55 + j*(-15) +-192 + j*(-189) +-375 + j*(148) +-27 + j*(369) +183 + j*(85) +-32 + j*(-37) +-41 + j*(161) +185 + j*(100) +115 + j*(-148) +-120 + j*(-119) +-140 + j*(70) +-25 + j*(124) +41 + j*(73) +18 + j*(6) +-73 + j*(35) +-45 + j*(182) +153 + j*(185) +195 + j*(-16) +21 + j*(-59) +9 + j*(117) +218 + j*(127) +294 + j*(-98) +137 + j*(-260) +-60 + j*(-227) +-136 + j*(-63) +-22 + j*(70) +148 + j*(-11) +111 + j*(-217) +-107 + j*(-260) +-231 + j*(-105) +-192 + j*(38) +-115 + j*(89) +-54 + j*(93) +-22 + j*(81) +1 + j*(84) +52 + j*(76) +77 + j*(13) +37 + j*(-25) +25 + j*(8) +88 + j*(-7) +87 + j*(-119) +-45 + j*(-185) +-189 + j*(-96) +-198 + j*(83) +-51 + j*(183) +87 + j*(113) +77 + j*(4) +25 + j*(16) +90 + j*(40) +155 + j*(-81) +42 + j*(-221) +-137 + j*(-199) +-225 + j*(-76) +-243 + j*(45) +-204 + j*(182) +-61 + j*(288) +133 + j*(248) +224 + j*(81) +153 + j*(-76) +4 + j*(-97) +-74 + j*(21) +14 + j*(138) +168 + j*(95) +193 + j*(-69) +64 + j*(-153) +-27 + j*(-81) +20 + j*(-16) +66 + j*(-81) +-18 + j*(-142) +-101 + j*(-75) +-67 + j*(-4) +-41 + j*(-32) +-103 + j*(-24) +-98 + j*(81) +29 + j*(103) +74 + j*(-22) +-47 + j*(-78) +-127 + j*(41) +-26 + j*(160) +125 + j*(113) +160 + j*(-31) +75 + j*(-139) +-60 + j*(-154) +-174 + j*(-51) +-153 + j*(119) +6 + j*(189) +113 + j*(96) +94 + j*(30) +121 + j*(30) +172 + j*(-88) +10 + j*(-219) +-187 + j*(-54) +-39 + j*(184) +237 + j*(52) +151 + j*(-251) +-156 + j*(-244) +-231 + j*(13) +-58 + j*(145) +87 + j*(50) +42 + j*(-88) +-91 + j*(-62) +-61 + j*(79) +98 + j*(30) +33 + j*(-157) +-182 + j*(-86) +-115 + j*(130) +73 + j*(50) +-46 + j*(-101) +-185 + j*(64) +5 + j*(214) +159 + j*(35) +18 + j*(-108) +-103 + j*(-11) +-60 + j*(83) +-4 + j*(95) +47 + j*(91) +85 + j*(33) +40 + j*(-16) +4 + j*(17) +15 + j*(41) +26 + j*(81) +150 + j*(123) +303 + j*(-62) +138 + j*(-344) +-212 + j*(-277) +-256 + j*(30) +-73 + j*(128) +-6 + j*(70) +5 + j*(75) +61 + j*(65) +85 + j*(18) +101 + j*(-24) +77 + j*(-115) +-62 + j*(-132) +-110 + j*(13) +10 + j*(68) +47 + j*(-10) +30 + j*(-11) +99 + j*(-71) +-31 + j*(-247) +-332 + j*(-99) +-231 + j*(294) +177 + j*(280) +240 + j*(-62) +8 + j*(-164) +-102 + j*(-46) +-88 + j*(66) +23 + j*(156) +206 + j*(66) +171 + j*(-167) +-32 + j*(-187) +-60 + j*(-83) +-61 + j*(-118) +-185 + j*(-63) +-129 + j*(107) +15 + j*(49) +-84 + j*(-28) +-100 + j*(136) +112 + j*(112) +54 + j*(-110) +-141 + j*(-11) +1 + j*(137) +76 + j*(-54) +-173 + j*(-47) +-104 + j*(264) +245 + j*(156) +110 + j*(-190) +-223 + j*(-24) +-37 + j*(310) +304 + j*(158) +242 + j*(-159) +-3 + j*(-188) +-87 + j*(-29) +23 + j*(78) +160 + j*(-24) +63 + j*(-215) +-173 + j*(-147) +-156 + j*(84) +15 + j*(103) +30 + j*(21) +25 + j*(35) +62 + j*(-1) +10 + j*(-11) +81 + j*(68) +237 + j*(-103) +16 + j*(-366) +-320 + j*(-170) +-194 + j*(140) +1 + j*(51) +-114 + j*(-6) +-73 + j*(151) +81 + j*(52) +-91 + j*(-49) +-141 + j*(226) +212 + j*(274) +280 + j*(-65) +42 + j*(-98) +131 + j*(21) +194 + j*(-222) +-152 + j*(-291) +-223 + j*(76) +125 + j*(115) +122 + j*(-217) +-176 + j*(-213) +-190 + j*(-3) +-119 + j*(-14) +-219 + j*(14) +-203 + j*(210) +-6 + j*(287) +149 + j*(202) +209 + j*(55) +133 + j*(-83) +2 + j*(-46) +74 + j*(49) +179 + j*(-95) +3 + j*(-258) +-199 + j*(-132) +-170 + j*(35) +-119 + j*(71) +-83 + j*(136) +38 + j*(141) +54 + j*(34) +-25 + j*(61) +61 + j*(153) +182 + j*(53) +131 + j*(-63) +85 + j*(-67) +73 + j*(-127) +-61 + j*(-151) +-122 + j*(-9) +-18 + j*(52) +4 + j*(-5) +-14 + j*(23) +58 + j*(1) +-18 + j*(-116) +-194 + j*(16) +-37 + j*(268) +283 + j*(143) +243 + j*(-203) +-57 + j*(-267) +-205 + j*(-64) +-112 + j*(121) +74 + j*(116) +119 + j*(-62) +-58 + j*(-122) +-123 + j*(66) +80 + j*(141) +176 + j*(-57) +19 + j*(-171) +-87 + j*(-83) +-71 + j*(-20) +-68 + j*(3) +-41 + j*(40) +-4 + j*(32) +-2 + j*(34) +58 + j*(47) +114 + j*(-51) +21 + j*(-151) +-78 + j*(-112) +-97 + j*(-73) +-161 + j*(-37) +-148 + j*(109) +38 + j*(129) +73 + j*(-78) +-150 + j*(-136) +-269 + j*(67) +-170 + j*(247) +-1 + j*(320) +208 + j*(259) +281 + j*(28) +121 + j*(-89) +81 + j*(-4) +174 + j*(-98) +-25 + j*(-274) +-297 + j*(-57) +-144 + j*(271) +159 + j*(225) +216 + j*(40) +196 + j*(-65) +116 + j*(-190) +-76 + j*(-161) +-54 + j*(21) +95 + j*(-53) +-59 + j*(-198) +-228 + j*(7) +-27 + j*(187) +124 + j*(35) +44 + j*(-49) +60 + j*(-37) +15 + j*(-174) +-230 + j*(-104) +-174 + j*(205) +130 + j*(169) +79 + j*(-66) +-72 + j*(47) +117 + j*(155) +221 + j*(-62) +61 + j*(-147) +62 + j*(-91) +47 + j*(-239) +-243 + j*(-231) +-281 + j*(124) +54 + j*(195) +121 + j*(-86) +-101 + j*(-129) +-133 + j*(22) +-74 + j*(42) +-87 + j*(78) +10 + j*(142) +106 + j*(36) +32 + j*(-50) +4 + j*(-21) +-4 + j*(-89) +-188 + j*(-73) +-204 + j*(218) +144 + j*(295) +277 + j*(-48) +-11 + j*(-194) +-123 + j*(30) +61 + j*(74) +34 + j*(-107) +-177 + j*(-31) +-98 + j*(231) +204 + j*(197) +244 + j*(-111) +-33 + j*(-225) +-197 + j*(-1) +-30 + j*(187) +153 + j*(67) +63 + j*(-95) +-81 + j*(-9) +12 + j*(141) +190 + j*(67) +177 + j*(-129) +13 + j*(-197) +-107 + j*(-113) +-117 + j*(-1) +-60 + j*(71) +23 + j*(88) +100 + j*(35) +88 + j*(-69) +-11 + j*(-82) +-11 + j*(6) +96 + j*(-40) +5 + j*(-206) +-248 + j*(-99) +-163 + j*(227) +199 + j*(185) +191 + j*(-167) +-119 + j*(-162) +-76 + j*(105) +180 + j*(8) +55 + j*(-266) +-228 + j*(-161) +-160 + j*(80) +11 + j*(8) +-114 + j*(-124) +-274 + j*(42) +-139 + j*(257) +96 + j*(208) +119 + j*(18) +-11 + j*(-27) +-40 + j*(74) +57 + j*(83) +52 + j*(-25) +-79 + j*(-2) +-48 + j*(165) +156 + j*(155) +175 + j*(-50) +-1 + j*(-70) +21 + j*(83) +192 + j*(18) +117 + j*(-190) +-97 + j*(-135) +-58 + j*(47) +81 + j*(-12) +-18 + j*(-130) +-134 + j*(4) +12 + j*(124) +128 + j*(-17) +5 + j*(-112) +-49 + j*(-5) +57 + j*(1) +31 + j*(-127) +-113 + j*(-108) +-129 + j*(9) +-81 + j*(48) +-56 + j*(81) +28 + j*(83) +38 + j*(-24) +-100 + j*(-11) +-66 + j*(181) +176 + j*(162) +204 + j*(-91) +9 + j*(-158) +-65 + j*(-59) +-69 + j*(-22) +-90 + j*(67) +57 + j*(156) +198 + j*(-14) +37 + j*(-180) +-115 + j*(-44) +4 + j*(60) +52 + j*(-54) +-56 + j*(-61) +-39 + j*(26) +-1 + j*(-2) +-39 + j*(29) +76 + j*(92) +187 + j*(-96) +-28 + j*(-264) +-224 + j*(-92) +-122 + j*(61) +-80 + j*(-1) +-158 + j*(60) +-59 + j*(183) +66 + j*(103) +13 + j*(32) +11 + j*(85) +72 + j*(45) +11 + j*(-5) +-17 + j*(65) +42 + j*(86) +44 + j*(95) +161 + j*(163) +363 + j*(-30) +178 + j*(-357) +-187 + j*(-235) +-96 + j*(74) +130 + j*(-52) +-52 + j*(-229) +-209 + j*(-28) +-30 + j*(89) +23 + j*(-59) +-107 + j*(-59) +-92 + j*(40) +-68 + j*(20) +-115 + j*(91) +22 + j*(194) +168 + j*(57) +70 + j*(-71) +26 + j*(-2) +120 + j*(-66) +-8 + j*(-235) +-249 + j*(-124) +-223 + j*(129) +-40 + j*(185) +47 + j*(116) +68 + j*(49) +35 + j*(-7) +-30 + j*(8) +-28 + j*(79) +33 + j*(113) +123 + j*(102) +204 + j*(-24) +76 + j*(-203) +-170 + j*(-90) +-69 + j*(195) +245 + j*(95) +158 + j*(-240) +-174 + j*(-190) +-177 + j*(107) +42 + j*(163) +142 + j*(49) +151 + j*(-68) +50 + j*(-195) +-172 + j*(-136) +-173 + j*(142) +119 + j*(221) +278 + j*(-36) +114 + j*(-250) +-102 + j*(-200) +-130 + j*(-32) +-1 + j*(11) +24 + j*(-122) +-148 + j*(-151) +-196 + j*(33) +-47 + j*(76) +-72 + j*(-30) +-170 + j*(101) +50 + j*(231) +221 + j*(-35) +-45 + j*(-224) +-215 + j*(4) +-42 + j*(105) +-57 + j*(-28) +-194 + j*(96) +-16 + j*(271) +156 + j*(112) +44 + j*(19) +76 + j*(128) +238 + j*(-6) +78 + j*(-228) +-148 + j*(-119) +-98 + j*(23) +-104 + j*(-27) +-246 + j*(102) +-106 + j*(381) +239 + j*(347) +337 + j*(71) +212 + j*(-62) +150 + j*(-42) +183 + j*(-61) +163 + j*(-170) +12 + j*(-219) +-98 + j*(-71) +46 + j*(55) +183 + j*(-117) +-18 + j*(-289) +-238 + j*(-91) +-73 + j*(152) +176 + j*(39) +127 + j*(-198) +-57 + j*(-233) +-146 + j*(-152) +-180 + j*(-85) +-200 + j*(1) +-144 + j*(107) +1 + j*(119) +73 + j*(-41) +-114 + j*(-161) +-310 + j*(48) +-119 + j*(334) +217 + j*(216) +178 + j*(-86) +-22 + j*(-79) +32 + j*(16) +74 + j*(-133) +-153 + j*(-197) +-279 + j*(30) +-129 + j*(180) +-37 + j*(119) +-78 + j*(130) +-8 + j*(230) +156 + j*(186) +185 + j*(20) +64 + j*(-52) +2 + j*(38) +104 + j*(86) +163 + j*(-53) +3 + j*(-146) +-120 + j*(19) +37 + j*(163) +194 + j*(24) +87 + j*(-128) +-36 + j*(-46) +44 + j*(45) +132 + j*(-40) +68 + j*(-155) +-65 + j*(-154) +-138 + j*(-47) +-95 + j*(70) +10 + j*(97) +74 + j*(43) +95 + j*(-16) +81 + j*(-103) +-44 + j*(-167) +-199 + j*(-45) +-132 + j*(197) +158 + j*(233) +322 + j*(-40) +137 + j*(-305) +-164 + j*(-239) +-192 + j*(28) +18 + j*(87) +59 + j*(-82) +-100 + j*(-79) +-55 + j*(91) +147 + j*(14) +74 + j*(-220) +-156 + j*(-181) +-140 + j*(-11) +-47 + j*(-61) +-153 + j*(-135) +-257 + j*(-30) +-238 + j*(66) +-244 + j*(126) +-209 + j*(260) +-46 + j*(312) +22 + j*(236) +9 + j*(281) +201 + j*(363) +430 + j*(145) +317 + j*(-176) +32 + j*(-187) +-30 + j*(-4) +60 + j*(49) +90 + j*(29) +136 + j*(47) +245 + j*(-40) +196 + j*(-244) +-38 + j*(-298) +-174 + j*(-123) +-88 + j*(11) +-17 + j*(-28) +-68 + j*(-49) +-83 + j*(29) +-5 + j*(65) +43 + j*(22) +53 + j*(-15) +59 + j*(-69) +-15 + j*(-142) +-151 + j*(-98) +-187 + j*(67) +-66 + j*(193) +110 + j*(187) +238 + j*(45) +207 + j*(-169) +2 + j*(-263) +-160 + j*(-136) +-109 + j*(12) +-6 + j*(-22) +-65 + j*(-117) +-212 + j*(-54) +-209 + j*(144) +-12 + j*(242) +166 + j*(105) +113 + j*(-104) +-93 + j*(-127) +-184 + j*(53) +-57 + j*(207) +129 + j*(167) +175 + j*(4) +84 + j*(-77) +45 + j*(-45) +97 + j*(-89) +6 + j*(-246) +-279 + j*(-209) +-381 + j*(130) +-100 + j*(376) +206 + j*(229) +187 + j*(-40) +-4 + j*(-87) +-64 + j*(35) +8 + j*(90) +42 + j*(54) +29 + j*(59) +69 + j*(88) +132 + j*(49) +135 + j*(-20) +111 + j*(-54) +91 + j*(-91) +34 + j*(-111) +-1 + j*(-77) +13 + j*(-76) +-38 + j*(-104) +-95 + j*(-18) +4 + j*(59) +75 + j*(-46) +-35 + j*(-94) +-40 + j*(23) +91 + j*(-29) +-1 + j*(-185) +-167 + j*(-86) +-81 + j*(33) +-61 + j*(-68) +-223 + j*(7) +-105 + j*(243) +148 + j*(127) +32 + j*(-69) +-72 + j*(95) +171 + j*(127) +173 + j*(-175) +-131 + j*(-167) +-89 + j*(83) +95 + j*(-29) +-90 + j*(-171) +-210 + j*(43) +-22 + j*(119) +-40 + j*(-27) +-184 + j*(100) +2 + j*(282) +200 + j*(127) +130 + j*(-17) +111 + j*(-9) +117 + j*(-129) +-94 + j*(-177) +-190 + j*(54) +12 + j*(165) +109 + j*(14) +8 + j*(-57) +-64 + j*(-12) +-117 + j*(70) +-55 + j*(274) +291 + j*(320) +506 + j*(-68) +216 + j*(-407) +-111 + j*(-269) +-52 + j*(-72) +22 + j*(-175) +-177 + j*(-229) +-292 + j*(14) +-74 + j*(188) +116 + j*(2) +-67 + j*(-202) +-332 + j*(-25) +-221 + j*(295) +78 + j*(299) +143 + j*(116) +87 + j*(101) +180 + j*(128) +279 + j*(-5) +235 + j*(-170) +111 + j*(-284) +-101 + j*(-310) +-286 + j*(-110) +-165 + j*(149) +86 + j*(95) +54 + j*(-112) +-113 + j*(-77) +-71 + j*(54) +33 + j*(-2) +-43 + j*(-102) +-169 + j*(-28) +-141 + j*(131) +21 + j*(176) +119 + j*(57) +62 + j*(-42) +23 + j*(-21) +62 + j*(-74) +-66 + j*(-185) +-256 + j*(-33) +-129 + j*(194) +70 + j*(87) +-54 + j*(-48) +-144 + j*(112) +21 + j*(165) +12 + j*(29) +-115 + j*(135) +61 + j*(291) +226 + j*(127) +120 + j*(44) +197 + j*(144) +371 + j*(-76) +93 + j*(-339) +-199 + j*(-67) +62 + j*(204) +298 + j*(-40) +105 + j*(-233) +-4 + j*(-117) +64 + j*(-120) +-18 + j*(-175) +-41 + j*(-80) +53 + j*(-147) +-121 + j*(-286) +-337 + j*(-67) +-146 + j*(177) +47 + j*(35) +-89 + j*(-62) +-99 + j*(100) +95 + j*(51) +17 + j*(-166) +-212 + j*(-88) +-161 + j*(119) +-18 + j*(93) +-62 + j*(25) +-94 + j*(119) +40 + j*(178) +163 + j*(55) +100 + j*(-137) +-139 + j*(-170) +-284 + j*(79) +-76 + j*(322) +199 + j*(191) +124 + j*(-40) +-28 + j*(47) +128 + j*(159) +260 + j*(-51) +57 + j*(-220) +-107 + j*(-76) +-18 + j*(35) +21 + j*(-42) +-72 + j*(-40) +-78 + j*(76) +26 + j*(135) +158 + j*(83) +202 + j*(-102) +0 + j*(-253) +-227 + j*(-74) +-90 + j*(181) +142 + j*(74) +46 + j*(-95) +-36 + j*(17) +120 + j*(2) +25 + j*(-218) +-256 + j*(-74) +-93 + j*(234) +197 + j*(65) +5 + j*(-176) +-179 + j*(49) +68 + j*(189) +176 + j*(-54) +-35 + j*(-127) +-68 + j*(35) +38 + j*(34) +17 + j*(-4) +62 + j*(30) +120 + j*(-97) +-59 + j*(-191) +-181 + j*(-20) +-69 + j*(86) +-48 + j*(62) +-11 + j*(187) +285 + j*(157) +341 + j*(-256) +-76 + j*(-428) +-305 + j*(-126) +-152 + j*(51) +-106 + j*(-14) +-175 + j*(42) +-112 + j*(139) +-47 + j*(139) +-3 + j*(173) +124 + j*(151) +150 + j*(21) +98 + j*(-5) +159 + j*(-37) +103 + j*(-225) +-169 + j*(-203) +-190 + j*(72) +42 + j*(92) +26 + j*(-97) +-136 + j*(-57) +-112 + j*(64) +-71 + j*(72) +-46 + j*(134) +115 + j*(112) +98 + j*(-119) +-182 + j*(-112) +-197 + j*(175) +30 + j*(197) +-2 + j*(75) +-61 + j*(226) +189 + j*(305) +315 + j*(74) +192 + j*(-13) +255 + j*(34) +334 + j*(-185) +63 + j*(-341) +-110 + j*(-105) +100 + j*(14) +175 + j*(-221) +-57 + j*(-315) +-185 + j*(-172) +-187 + j*(-81) +-210 + j*(38) +-52 + j*(190) +195 + j*(50) +103 + j*(-244) +-187 + j*(-214) +-216 + j*(17) +-74 + j*(57) +-68 + j*(-6) +-95 + j*(25) +-50 + j*(40) +-60 + j*(-6) +-115 + j*(25) +-94 + j*(90) +-54 + j*(87) +-71 + j*(102) +-31 + j*(175) +88 + j*(174) +153 + j*(68) +116 + j*(-25) +47 + j*(-53) +-10 + j*(-28) +-8 + j*(33) +66 + j*(31) +66 + j*(-81) +-95 + j*(-101) +-158 + j*(102) +57 + j*(216) +211 + j*(13) +25 + j*(-153) +-134 + j*(28) +48 + j*(187) +210 + j*(25) +92 + j*(-111) +34 + j*(-24) +149 + j*(-68) +56 + j*(-260) +-198 + j*(-196) +-202 + j*(29) +-91 + j*(60) +-122 + j*(81) +-25 + j*(231) +221 + j*(131) +146 + j*(-146) +-112 + j*(-62) +26 + j*(181) +291 + j*(2) +134 + j*(-296) +-140 + j*(-214) +-124 + j*(-47) +-105 + j*(-64) +-187 + j*(31) +-49 + j*(195) +172 + j*(66) +89 + j*(-181) +-160 + j*(-173) +-251 + j*(30) +-158 + j*(216) +66 + j*(269) +252 + j*(84) +152 + j*(-173) +-115 + j*(-153) +-155 + j*(78) +22 + j*(159) +121 + j*(59) +110 + j*(-18) +107 + j*(-64) +78 + j*(-160) +-71 + j*(-231) +-272 + j*(-127) +-298 + j*(153) +-40 + j*(322) +209 + j*(154) +129 + j*(-89) +-78 + j*(-45) +-30 + j*(139) +154 + j*(100) +146 + j*(-78) +5 + j*(-105) +-30 + j*(-6) +42 + j*(25) +78 + j*(-33) +49 + j*(-81) +10 + j*(-93) +-25 + j*(-88) +-45 + j*(-66) +-37 + j*(-63) +-71 + j*(-98) +-168 + j*(-62) +-174 + j*(75) +-57 + j*(114) +-51 + j*(44) +-114 + j*(128) +53 + j*(245) +244 + j*(46) +56 + j*(-189) +-183 + j*(-27) +-54 + j*(180) +86 + j*(95) +33 + j*(69) +147 + j*(130) +258 + j*(-103) +-43 + j*(-267) +-233 + j*(59) +105 + j*(238) +250 + j*(-105) +-94 + j*(-200) +-133 + j*(144) +221 + j*(134) +185 + j*(-224) +-156 + j*(-179) +-106 + j*(123) +157 + j*(67) +100 + j*(-156) +-79 + j*(-107) +-30 + j*(28) +83 + j*(-28) +36 + j*(-136) +-61 + j*(-124) +-77 + j*(-66) +-62 + j*(-59) +-79 + j*(-62) +-92 + j*(-49) +-110 + j*(-57) +-182 + j*(-35) +-214 + j*(95) +-91 + j*(204) +60 + j*(141) +56 + j*(3) +-45 + j*(-40) +-129 + j*(17) +-141 + j*(137) +-25 + j*(233) +122 + j*(161) +86 + j*(21) +-23 + j*(67) +54 + j*(190) +211 + j*(124) +212 + j*(-29) +135 + j*(-88) +77 + j*(-112) +-6 + j*(-95) +-18 + j*(2) +88 + j*(3) +71 + j*(-130) +-93 + j*(-113) +-89 + j*(60) +63 + j*(59) +40 + j*(-63) +-64 + j*(4) +46 + j*(124) +199 + j*(3) +110 + j*(-165) +-14 + j*(-121) +27 + j*(-78) +-1 + j*(-172) +-158 + j*(-121) +-114 + j*(62) +56 + j*(11) +-25 + j*(-129) +-136 + j*(-5) +47 + j*(67) +91 + j*(-194) +-243 + j*(-243) +-317 + j*(116) +11 + j*(177) +3 + j*(-127) +-325 + j*(-47) +-234 + j*(315) +100 + j*(265) +64 + j*(33) +-65 + j*(122) +97 + j*(205) +181 + j*(7) +-6 + j*(-79) +-92 + j*(75) +12 + j*(163) +88 + j*(139) +138 + j*(116) +185 + j*(54) +168 + j*(-6) +181 + j*(-8) +240 + j*(-107) +139 + j*(-284) +-102 + j*(-268) +-188 + j*(-57) +-70 + j*(79) +58 + j*(59) +124 + j*(-29) +103 + j*(-166) +-71 + j*(-239) +-239 + j*(-76) +-129 + j*(154) +112 + j*(103) +102 + j*(-105) +-44 + j*(-100) +5 + j*(-24) +39 + j*(-165) +-192 + j*(-214) +-280 + j*(54) +-28 + j*(146) +11 + j*(-100) +-272 + j*(-77) +-240 + j*(257) +103 + j*(257) +129 + j*(-45) +-126 + j*(-84) +-192 + j*(124) +-57 + j*(243) +98 + j*(217) +176 + j*(70) +47 + j*(-66) +-117 + j*(63) +3 + j*(264) +213 + j*(202) +236 + j*(78) +286 + j*(42) +349 + j*(-157) +115 + j*(-352) +-127 + j*(-173) +20 + j*(19) +157 + j*(-155) +-40 + j*(-293) +-196 + j*(-150) +-152 + j*(-35) +-146 + j*(-13) +-134 + j*(73) +-30 + j*(105) +13 + j*(47) +10 + j*(41) +62 + j*(22) +60 + j*(-71) +-35 + j*(-108) +-110 + j*(-59) +-139 + j*(27) +-74 + j*(130) +66 + j*(100) +47 + j*(-45) +-98 + j*(-1) +-24 + j*(165) +166 + j*(89) +119 + j*(-95) +-11 + j*(-73) +14 + j*(-10) +33 + j*(-52) +-2 + j*(-54) +25 + j*(-62) +-21 + j*(-153) +-182 + j*(-127) +-233 + j*(45) +-139 + j*(170) +1 + j*(206) +148 + j*(111) +108 + j*(-99) +-129 + j*(-91) +-134 + j*(153) +90 + j*(165) +76 + j*(2) +-10 + j*(93) +205 + j*(142) +282 + j*(-177) +-66 + j*(-310) +-218 + j*(-15) +1 + j*(78) +-14 + j*(-107) +-235 + j*(-4) +-125 + j*(271) +153 + j*(228) +177 + j*(35) +113 + j*(18) +173 + j*(6) +194 + j*(-136) +57 + j*(-248) +-127 + j*(-214) +-227 + j*(-45) +-142 + j*(150) +74 + j*(161) +149 + j*(-24) +10 + j*(-123) +-74 + j*(-17) +27 + j*(42) +69 + j*(-86) +-99 + j*(-143) +-210 + j*(53) +-30 + j*(233) +194 + j*(115) +153 + j*(-89) +27 + j*(-88) +62 + j*(-47) +72 + j*(-163) +-100 + j*(-204) +-189 + j*(-44) +-81 + j*(39) +-68 + j*(-37) +-172 + j*(21) +-89 + j*(191) +129 + j*(135) +123 + j*(-83) +-49 + j*(-111) +-71 + j*(-8) +-25 + j*(-44) +-149 + j*(-86) +-254 + j*(98) +-92 + j*(288) +134 + j*(214) +148 + j*(37) +54 + j*(-8) +28 + j*(28) +52 + j*(37) +73 + j*(12) +54 + j*(-32) +0 + j*(-33) +-11 + j*(12) +13 + j*(13) +-25 + j*(10) +-30 + j*(112) +132 + j*(161) +252 + j*(-8) +144 + j*(-168) +29 + j*(-141) +30 + j*(-132) +-53 + j*(-196) +-215 + j*(-105) +-197 + j*(113) +-7 + j*(194) +131 + j*(92) +123 + j*(-40) +34 + j*(-86) +-18 + j*(-30) +45 + j*(15) +116 + j*(-76) +27 + j*(-212) +-169 + j*(-191) +-255 + j*(8) +-118 + j*(182) +92 + j*(132) +102 + j*(-62) +-54 + j*(-100) +-85 + j*(8) +-28 + j*(4) +-95 + j*(-16) +-102 + j*(118) +75 + j*(128) +71 + j*(-64) +-132 + j*(-17) +-40 + j*(214) +228 + j*(106) +140 + j*(-165) +-86 + j*(-104) +-25 + j*(43) +59 + j*(-49) +-69 + j*(-115) +-153 + j*(-3) +-126 + j*(90) +-95 + j*(182) +64 + j*(298) +332 + j*(189) +383 + j*(-132) +158 + j*(-334) +-75 + j*(-292) +-163 + j*(-157) +-159 + j*(-76) +-169 + j*(-34) +-181 + j*(57) +-85 + j*(127) +-28 + j*(52) +-142 + j*(67) +-79 + j*(303) +290 + j*(274) +351 + j*(-153) +-33 + j*(-279) +-140 + j*(3) +62 + j*(5) +-73 + j*(-185) +-316 + j*(36) +-100 + j*(343) +207 + j*(205) +150 + j*(-18) +44 + j*(9) +76 + j*(36) +62 + j*(19) +93 + j*(89) +264 + j*(37) +279 + j*(-225) +16 + j*(-364) +-221 + j*(-199) +-173 + j*(59) +66 + j*(86) +129 + j*(-153) +-130 + j*(-253) +-272 + j*(4) +-43 + j*(154) +59 + j*(-58) +-181 + j*(-96) +-188 + j*(203) +158 + j*(231) +231 + j*(-121) +-78 + j*(-242) +-231 + j*(-1) +-73 + j*(164) +84 + j*(79) +61 + j*(-66) +-76 + j*(-97) +-165 + j*(21) +-100 + j*(154) +40 + j*(170) +131 + j*(82) +130 + j*(-43) +13 + j*(-129) +-132 + j*(-51) +-111 + j*(118) +43 + j*(163) +134 + j*(69) +128 + j*(-24) +84 + j*(-93) +-4 + j*(-115) +-61 + j*(-58) +-43 + j*(-29) +-78 + j*(-49) +-159 + j*(25) +-115 + j*(165) +18 + j*(211) +129 + j*(172) +212 + j*(86) +221 + j*(-52) +125 + j*(-137) +45 + j*(-125) +16 + j*(-107) +-10 + j*(-80) +27 + j*(-62) +37 + j*(-163) +-149 + j*(-210) +-275 + j*(22) +-55 + j*(215) +170 + j*(40) +67 + j*(-195) +-156 + j*(-200) +-302 + j*(-58) +-322 + j*(194) +-71 + j*(402) +238 + j*(243) +168 + j*(-30) +2 + j*(40) +160 + j*(127) +233 + j*(-122) +-49 + j*(-212) +-134 + j*(47) +83 + j*(91) +67 + j*(-90) +-89 + j*(-14) +31 + j*(129) +164 + j*(5) +69 + j*(-88) +65 + j*(-21) +152 + j*(-116) +13 + j*(-266) +-174 + j*(-155) +-125 + j*(-5) +-59 + j*(-30) +-108 + j*(-16) +-58 + j*(72) +64 + j*(13) +32 + j*(-130) +-104 + j*(-166) +-220 + j*(-107) +-293 + j*(26) +-243 + j*(204) +-74 + j*(280) +58 + j*(226) +134 + j*(148) +170 + j*(0) +11 + j*(-155) +-245 + j*(-18) +-176 + j*(311) +156 + j*(342) +262 + j*(116) +193 + j*(44) +262 + j*(13) +243 + j*(-202) +-38 + j*(-252) +-123 + j*(7) +99 + j*(65) +106 + j*(-138) +-89 + j*(-102) +-18 + j*(80) +149 + j*(-20) +48 + j*(-172) +-64 + j*(-101) +-25 + j*(-78) +-115 + j*(-115) +-180 + j*(65) +54 + j*(159) +156 + j*(-105) +-135 + j*(-199) +-218 + j*(101) +74 + j*(163) +98 + j*(-118) +-190 + j*(-112) +-197 + j*(192) +77 + j*(262) +214 + j*(89) +193 + j*(-59) +103 + j*(-161) +-49 + j*(-148) +-66 + j*(-4) +71 + j*(-13) +25 + j*(-175) +-161 + j*(-125) +-121 + j*(42) +-14 + j*(-19) +-148 + j*(-78) +-216 + j*(136) +24 + j*(252) +177 + j*(52) +52 + j*(-83) +-16 + j*(-22) +18 + j*(-40) +-71 + j*(-76) +-123 + j*(59) +44 + j*(127) +129 + j*(-62) +-69 + j*(-186) +-238 + j*(-18) +-142 + j*(175) +23 + j*(151) +30 + j*(36) +-66 + j*(38) +-69 + j*(160) +87 + j*(211) +202 + j*(57) +70 + j*(-105) +-125 + j*(11) +-36 + j*(258) +256 + j*(247) +360 + j*(-23) +197 + j*(-205) +21 + j*(-161) +-1 + j*(-37) +98 + j*(21) +211 + j*(-69) +178 + j*(-262) +-44 + j*(-342) +-214 + j*(-179) +-140 + j*(-1) +-15 + j*(-43) +-81 + j*(-137) +-187 + j*(-45) +-99 + j*(74) +3 + j*(-13) +-115 + j*(-96) +-217 + j*(71) +-26 + j*(221) +170 + j*(42) +25 + j*(-180) +-197 + j*(-85) +-160 + j*(109) +-40 + j*(117) +-26 + j*(94) +37 + j*(112) +98 + j*(-15) +-82 + j*(-117) +-240 + j*(110) +-1 + j*(338) +275 + j*(139) +134 + j*(-122) +-68 + j*(-4) +70 + j*(153) +226 + j*(2) +109 + j*(-165) +-36 + j*(-118) +-52 + j*(-29) +-26 + j*(29) +66 + j*(57) +154 + j*(-70) +16 + j*(-228) +-197 + j*(-118) +-143 + j*(106) +51 + j*(93) +57 + j*(-57) +-50 + j*(-73) +-76 + j*(-7) +-59 + j*(15) +-70 + j*(35) +-49 + j*(91) +35 + j*(104) +85 + j*(16) +-7 + j*(-52) +-91 + j*(71) +88 + j*(199) +296 + j*(-21) +82 + j*(-317) +-267 + j*(-149) +-164 + j*(194) +119 + j*(135) +63 + j*(-51) +-30 + j*(45) +124 + j*(87) +167 + j*(-99) +21 + j*(-161) +-25 + j*(-115) +-90 + j*(-147) +-234 + j*(-19) +-102 + j*(209) +148 + j*(103) +43 + j*(-117) +-130 + j*(21) +50 + j*(173) +204 + j*(-17) +57 + j*(-162) +-29 + j*(-80) +25 + j*(-93) +-62 + j*(-186) +-221 + j*(-114) +-245 + j*(52) +-156 + j*(170) +-15 + j*(185) +43 + j*(71) +-71 + j*(38) +-92 + j*(211) +127 + j*(278) +246 + j*(107) +192 + j*(24) +250 + j*(10) +283 + j*(-182) +70 + j*(-308) +-66 + j*(-182) +-13 + j*(-148) +-116 + j*(-216) +-252 + j*(-37) +-62 + j*(138) +112 + j*(-57) +-100 + j*(-228) +-281 + j*(-28) +-136 + j*(136) +-43 + j*(33) +-157 + j*(18) +-152 + j*(171) +-5 + j*(194) +13 + j*(103) +-39 + j*(147) +66 + j*(231) +209 + j*(132) +166 + j*(-13) +83 + j*(9) +156 + j*(37) +194 + j*(-104) +38 + j*(-194) +-76 + j*(-85) +-24 + j*(-7) +-20 + j*(-30) +-55 + j*(39) +60 + j*(112) +179 + j*(-3) +111 + j*(-139) +19 + j*(-146) +-33 + j*(-150) +-140 + j*(-105) +-130 + j*(66) +59 + j*(73) +48 + j*(-127) +-174 + j*(-85) +-111 + j*(163) +148 + j*(89) +57 + j*(-166) +-199 + j*(-43) +-42 + j*(231) +268 + j*(74) +163 + j*(-266) +-154 + j*(-243) +-196 + j*(-18) +-93 + j*(25) +-111 + j*(3) +-117 + j*(85) +-22 + j*(112) +-1 + j*(53) +-16 + j*(87) +100 + j*(93) +138 + j*(-99) +-95 + j*(-192) +-242 + j*(38) +-50 + j*(209) +101 + j*(59) +-30 + j*(-54) +-123 + j*(69) +-38 + j*(158) +14 + j*(148) +58 + j*(201) +231 + j*(191) +325 + j*(-23) +185 + j*(-195) +45 + j*(-173) +7 + j*(-163) +-122 + j*(-169) +-247 + j*(42) +-34 + j*(297) +319 + j*(155) +280 + j*(-231) +-61 + j*(-281) +-139 + j*(-29) +41 + j*(18) +45 + j*(-135) +-93 + j*(-124) +-81 + j*(-28) +-38 + j*(-63) +-110 + j*(-82) +-141 + j*(-9) +-116 + j*(16) +-156 + j*(40) +-140 + j*(154) +-14 + j*(196) +58 + j*(135) +78 + j*(104) +120 + j*(43) +58 + j*(-41) +-25 + j*(34) +86 + j*(121) +199 + j*(-7) +112 + j*(-131) +44 + j*(-110) +33 + j*(-158) +-121 + j*(-179) +-187 + j*(18) +6 + j*(85) +30 + j*(-119) +-228 + j*(-107) +-243 + j*(201) +52 + j*(291) +208 + j*(91) +141 + j*(-68) +42 + j*(-112) +-58 + j*(-93) +-100 + j*(0) +-47 + j*(62) +-12 + j*(48) +-19 + j*(68) +38 + j*(112) +134 + j*(77) +177 + j*(-38) +98 + j*(-164) +-70 + j*(-146) +-91 + j*(26) +86 + j*(44) +100 + j*(-155) +-105 + j*(-187) +-153 + j*(-31) +-88 + j*(-11) +-148 + j*(4) +-104 + j*(144) +77 + j*(93) +1 + j*(-83) +-163 + j*(29) +-42 + j*(179) +59 + j*(88) +6 + j*(103) +173 + j*(161) +295 + j*(-125) +-27 + j*(-320) +-240 + j*(-48) +-51 + j*(89) +-64 + j*(-56) +-240 + j*(108) +-5 + j*(366) +302 + j*(178) +229 + j*(-81) +117 + j*(-100) +71 + j*(-159) +-107 + j*(-115) +-44 + j*(127) +263 + j*(4) +87 + j*(-390) +-380 + j*(-223) +-282 + j*(247) +94 + j*(209) +51 + j*(-11) +-28 + j*(110) +204 + j*(122) +228 + j*(-181) +-72 + j*(-256) +-180 + j*(-27) +-45 + j*(78) +35 + j*(24) +47 + j*(-24) +25 + j*(-95) +-91 + j*(-107) +-139 + j*(34) +9 + j*(113) +112 + j*(-32) +-18 + j*(-163) +-177 + j*(-57) +-107 + j*(117) +78 + j*(79) +77 + j*(-130) +-155 + j*(-194) +-317 + j*(21) +-192 + j*(254) +25 + j*(245) +75 + j*(124) +42 + j*(116) +113 + j*(134) +172 + j*(31) +92 + j*(-42) +69 + j*(21) +177 + j*(-21) +120 + j*(-209) +-117 + j*(-191) +-136 + j*(36) +48 + j*(42) +5 + j*(-117) +-158 + j*(-22) +-24 + j*(159) +185 + j*(-5) +11 + j*(-269) +-325 + j*(-140) +-317 + j*(235) +-3 + j*(373) +219 + j*(210) +212 + j*(26) +151 + j*(-43) +105 + j*(-101) +-23 + j*(-127) +-122 + j*(30) +38 + j*(196) +255 + j*(71) +202 + j*(-150) +57 + j*(-155) +62 + j*(-115) +39 + j*(-182) +-60 + j*(-165) +-47 + j*(-109) +-64 + j*(-175) +-222 + j*(-132) +-204 + j*(82) +8 + j*(83) +1 + j*(-105) +-180 + j*(-86) +-175 + j*(76) +-64 + j*(91) +-54 + j*(36) +-90 + j*(42) +-106 + j*(91) +-60 + j*(166) +63 + j*(159) +100 + j*(40) +21 + j*(1) +16 + j*(33) +9 + j*(-4) +-69 + j*(47) +34 + j*(168) +188 + j*(21) +13 + j*(-138) +-121 + j*(76) +148 + j*(175) +223 + j*(-135) +-93 + j*(-193) +-115 + j*(88) +107 + j*(58) +14 + j*(-93) +-54 + j*(69) +182 + j*(64) +148 + j*(-245) +-184 + j*(-229) +-210 + j*(34) +-93 + j*(59) +-148 + j*(106) +-1 + j*(295) +303 + j*(149) +215 + j*(-178) +-49 + j*(-133) +8 + j*(54) +163 + j*(-39) +81 + j*(-192) +-59 + j*(-179) +-118 + j*(-100) +-118 + j*(-17) +254 + j*(-10) +76 + j*(-153) +-18 + j*(-66) +47 + j*(-84) +-64 + j*(-223) +-321 + j*(-112) +-313 + j*(218) +-22 + j*(334) +153 + j*(167) +99 + j*(27) +22 + j*(46) +63 + j*(111) +179 + j*(66) +187 + j*(-107) +5 + j*(-195) +-132 + j*(-49) +-30 + j*(89) +84 + j*(16) +40 + j*(-76) +-21 + j*(-76) +-74 + j*(-69) +-136 + j*(7) +-70 + j*(119) +35 + j*(62) +-59 + j*(2) +-95 + j*(186) +182 + j*(254) +316 + j*(-60) +25 + j*(-243) +-161 + j*(4) +49 + j*(172) +197 + j*(2) +77 + j*(-119) +9 + j*(-37) +89 + j*(-21) +93 + j*(-126) +-8 + j*(-157) +-58 + j*(-104) +-63 + j*(-88) +-116 + j*(-65) +-126 + j*(49) +14 + j*(114) +130 + j*(-16) +37 + j*(-168) +-119 + j*(-136) +-157 + j*(-20) +-112 + j*(59) +-28 + j*(83) +31 + j*(3) +-67 + j*(-66) +-148 + j*(71) +28 + j*(179) +158 + j*(-12) +-24 + j*(-141) +-117 + j*(20) +31 + j*(50) +-12 + j*(-100) +-171 + j*(-1) +-35 + j*(156) +93 + j*(-4) +-98 + j*(-98) +-174 + j*(116) +35 + j*(187) +96 + j*(18) +-18 + j*(-19) +-39 + j*(40) +-48 + j*(51) +-66 + j*(136) +66 + j*(216) +198 + j*(115) +176 + j*(-5) +137 + j*(-35) +116 + j*(-69) +88 + j*(-67) +142 + j*(-100) +82 + j*(-290) +-246 + j*(-293) +-373 + j*(76) +-87 + j*(290) +103 + j*(158) +93 + j*(109) +226 + j*(86) +247 + j*(-175) +-47 + j*(-240) +-90 + j*(38) +199 + j*(8) +119 + j*(-333) +-255 + j*(-281) +-264 + j*(42) +-71 + j*(64) +-111 + j*(-4) +-120 + j*(132) +69 + j*(139) +86 + j*(-52) +-85 + j*(-52) +-62 + j*(112) +108 + j*(74) +86 + j*(-99) +-75 + j*(-96) +-78 + j*(42) +48 + j*(34) +23 + j*(-105) +-137 + j*(-85) +-141 + j*(82) +-5 + j*(100) +-5 + j*(16) +-49 + j*(69) +77 + j*(88) +92 + j*(-113) +-182 + j*(-150) +-276 + j*(168) +23 + j*(330) +208 + j*(107) +64 + j*(-23) +19 + j*(103) +180 + j*(107) +218 + j*(-68) +98 + j*(-160) +4 + j*(-145) +-81 + j*(-99) +-108 + j*(50) +88 + j*(154) +288 + j*(-64) +101 + j*(-367) +-256 + j*(-279) +-276 + j*(37) +-73 + j*(96) +-68 + j*(-6) +-135 + j*(78) +10 + j*(161) +100 + j*(9) +-40 + j*(-54) +-47 + j*(86) +120 + j*(31) +17 + j*(-182) +-261 + j*(-69) +-202 + j*(252) +85 + j*(308) +233 + j*(171) +313 + j*(39) +313 + j*(-197) +59 + j*(-351) +-148 + j*(-180) +-38 + j*(-49) +-19 + j*(-190) +-227 + j*(-170) +-216 + j*(52) +-65 + j*(30) +-182 + j*(-33) +-238 + j*(215) +83 + j*(325) +241 + j*(23) +12 + j*(-115) +-50 + j*(55) +91 + j*(32) +-6 + j*(-98) +-127 + j*(57) +63 + j*(179) +190 + j*(-16) +9 + j*(-130) +-76 + j*(42) +98 + j*(110) +183 + j*(-63) +37 + j*(-179) +-99 + j*(-83) +-46 + j*(57) +93 + j*(35) +106 + j*(-106) +-13 + j*(-163) +-94 + j*(-113) +-136 + j*(-58) +-165 + j*(54) +-32 + j*(177) +162 + j*(64) +71 + j*(-158) +-149 + j*(-78) +-66 + j*(133) +136 + j*(49) +71 + j*(-140) +-71 + j*(-119) +-86 + j*(-66) +-157 + j*(-65) +-223 + j*(89) +-69 + j*(231) +83 + j*(136) +29 + j*(52) +28 + j*(136) +187 + j*(112) +212 + j*(-88) +43 + j*(-182) +-72 + j*(-89) +-44 + j*(-6) +-4 + j*(-25) +-49 + j*(-52) +-112 + j*(14) +-66 + j*(126) +68 + j*(138) +146 + j*(37) +121 + j*(-84) +-1 + j*(-151) +-154 + j*(-57) +-107 + j*(158) +141 + j*(159) +177 + j*(-77) +-22 + j*(-104) +13 + j*(62) +192 + j*(-56) +21 + j*(-290) +-262 + j*(-132) +-165 + j*(151) +51 + j*(113) +37 + j*(-5) +8 + j*(18) +48 + j*(-3) +5 + j*(-36) +13 + j*(17) +94 + j*(-44) +-9 + j*(-171) +-174 + j*(-58) +-77 + j*(116) +74 + j*(33) +-8 + j*(-82) +-98 + j*(-1) +-31 + j*(72) +20 + j*(40) +21 + j*(30) +64 + j*(12) +51 + j*(-73) +-57 + j*(-83) +-91 + j*(29) +23 + j*(86) +109 + j*(-33) +-9 + j*(-166) +-200 + j*(-70) +-149 + j*(159) +74 + j*(156) +83 + j*(-26) +-53 + j*(5) +53 + j*(127) +204 + j*(-57) +-27 + j*(-267) +-308 + j*(-41) +-140 + j*(284) +176 + j*(204) +175 + j*(-47) +9 + j*(-84) +-35 + j*(17) +29 + j*(69) +103 + j*(41) +121 + j*(-43) +66 + j*(-91) +41 + j*(-82) +42 + j*(-129) +-63 + j*(-180) +-174 + j*(-76) +-117 + j*(28) +-91 + j*(-16) +-206 + j*(47) +-128 + j*(283) +193 + j*(266) +258 + j*(-54) +-4 + j*(-167) +-118 + j*(26) +6 + j*(127) +75 + j*(84) +110 + j*(81) +209 + j*(21) +190 + j*(-151) +24 + j*(-204) +-61 + j*(-107) +-36 + j*(-48) +-18 + j*(-37) +16 + j*(-31) +38 + j*(-91) +-39 + j*(-144) +-117 + j*(-92) +-119 + j*(-35) +-132 + j*(4) +-97 + j*(93) +38 + j*(78) +30 + j*(-82) +-153 + j*(-69) +-146 + j*(127) +32 + j*(129) +7 + j*(-2) +-95 + j*(94) +70 + j*(228) +284 + j*(57) +206 + j*(-215) +-42 + j*(-288) +-244 + j*(-165) +-298 + j*(76) +-113 + j*(277) +151 + j*(194) +148 + j*(-52) +-52 + j*(-83) +-88 + j*(83) +62 + j*(131) +139 + j*(-5) +27 + j*(-122) +-129 + j*(-40) +-79 + j*(156) +146 + j*(141) +173 + j*(-105) +-63 + j*(-176) +-173 + j*(10) +-83 + j*(117) +-54 + j*(129) +-1 + j*(231) +201 + j*(235) +281 + j*(44) +183 + j*(-27) +228 + j*(15) +324 + j*(-140) +168 + j*(-317) +9 + j*(-233) +95 + j*(-191) +66 + j*(-401) +-260 + j*(-458) +-479 + j*(-179) +-404 + j*(89) +-280 + j*(207) +-132 + j*(310) +119 + j*(280) +226 + j*(27) +56 + j*(-135) +-73 + j*(-43) +-4 + j*(4) +-29 + j*(-98) +-199 + j*(-45) +-175 + j*(177) +49 + j*(215) +124 + j*(40) +13 + j*(-30) +-31 + j*(44) +29 + j*(79) +76 + j*(40) +74 + j*(-19) +21 + j*(-52) +-27 + j*(-10) +15 + j*(32) +49 + j*(-23) +-18 + j*(-55) +-40 + j*(7) +6 + j*(-1) +-54 + j*(-41) +-117 + j*(76) +35 + j*(183) +183 + j*(40) +79 + j*(-119) +-56 + j*(-58) +-21 + j*(38) +50 + j*(14) +41 + j*(-52) +-28 + j*(-80) +-106 + j*(-21) +-86 + j*(90) +12 + j*(117) +50 + j*(80) +88 + j*(90) +192 + j*(17) +143 + j*(-177) +-98 + j*(-196) +-193 + j*(33) +-33 + j*(197) +168 + j*(150) +250 + j*(-32) +138 + j*(-204) +-47 + j*(-156) +9 + j*(-8) +151 + j*(-147) +-70 + j*(-351) +-349 + j*(-124) +-182 + j*(161) +18 + j*(32) +-139 + j*(-53) +-158 + j*(165) +86 + j*(170) +72 + j*(-34) +-64 + j*(42) +110 + j*(148) +255 + j*(-100) +24 + j*(-322) +-247 + j*(-218) +-320 + j*(-6) +-276 + j*(197) +-72 + j*(337) +158 + j*(236) +158 + j*(52) +81 + j*(40) +131 + j*(45) +138 + j*(-57) +52 + j*(-81) +54 + j*(-54) +50 + j*(-128) +-89 + j*(-151) +-167 + j*(-4) +-62 + j*(112) +55 + j*(58) +35 + j*(-46) +-64 + j*(-44) +-78 + j*(58) +19 + j*(84) +42 + j*(1) +-32 + j*(1) +-6 + j*(69) +49 + j*(25) +-19 + j*(8) +16 + j*(121) +192 + j*(54) +127 + j*(-167) +-102 + j*(-120) +-66 + j*(75) +74 + j*(30) +8 + j*(-43) +1 + j*(54) +139 + j*(17) +100 + j*(-153) +-66 + j*(-147) +-98 + j*(-37) +-68 + j*(16) +-15 + j*(61) +84 + j*(8) +28 + j*(-129) +-129 + j*(-59) +-46 + j*(98) +94 + j*(-8) +-35 + j*(-121) +-118 + j*(24) +33 + j*(71) +48 + j*(-83) +-100 + j*(-80) +-98 + j*(34) +-57 + j*(25) +-103 + j*(65) +-9 + j*(173) +144 + j*(78) +78 + j*(-78) +-37 + j*(-34) +0 + j*(20) +-2 + j*(-29) +-74 + j*(18) +-7 + j*(117) +107 + j*(59) +73 + j*(-45) +1 + j*(-21) +39 + j*(28) +100 + j*(-18) +72 + j*(-114) +-42 + j*(-136) +-112 + j*(-36) +-37 + j*(57) +66 + j*(1) +25 + j*(-115) +-92 + j*(-118) +-153 + j*(-37) +-148 + j*(53) +-81 + j*(117) +6 + j*(95) +-6 + j*(8) +-119 + j*(34) +-115 + j*(215) +116 + j*(305) +327 + j*(112) +244 + j*(-161) +6 + j*(-180) +-41 + j*(-23) +54 + j*(-16) +8 + j*(-91) +-58 + j*(-13) +45 + j*(30) +57 + j*(-109) +-122 + j*(-103) +-122 + j*(91) +43 + j*(95) +12 + j*(-2) +-17 + j*(115) +218 + j*(117) +244 + j*(-215) +-125 + j*(-296) +-244 + j*(61) +66 + j*(191) +192 + j*(-68) +-1 + j*(-185) +-94 + j*(-71) +-57 + j*(-23) +-71 + j*(-9) +-31 + j*(62) +89 + j*(21) +81 + j*(-135) +-74 + j*(-192) +-194 + j*(-103) +-212 + j*(11) +-192 + j*(98) +-140 + j*(192) +-10 + j*(256) +150 + j*(190) +185 + j*(32) +104 + j*(-49) +66 + j*(-52) +30 + j*(-100) +-106 + j*(-81) +-137 + j*(122) +101 + j*(227) +299 + j*(7) +167 + j*(-274) +-129 + j*(-287) +-291 + j*(-65) +-211 + j*(175) +12 + j*(243) +161 + j*(110) +141 + j*(-30) +76 + j*(-87) +0 + j*(-122) +-113 + j*(-66) +-84 + j*(83) +66 + j*(64) +27 + j*(-73) +-97 + j*(8) +37 + j*(119) +139 + j*(-71) +-106 + j*(-170) +-213 + j*(111) +76 + j*(228) +186 + j*(-36) +-42 + j*(-121) +-96 + j*(71) +56 + j*(107) +79 + j*(19) +66 + j*(16) +92 + j*(-28) +16 + j*(-65) +13 + j*(39) +163 + j*(-16) +59 + j*(-238) +-233 + j*(-105) +-89 + j*(243) +305 + j*(105) +205 + j*(-313) +-194 + j*(-281) +-226 + j*(44) +-6 + j*(103) +47 + j*(-24) +-11 + j*(-57) +-18 + j*(-42) +-17 + j*(-63) +-56 + j*(-95) +-145 + j*(-77) +-183 + j*(60) +-34 + j*(148) +72 + j*(-6) +-105 + j*(-104) +-199 + j*(105) +18 + j*(197) +80 + j*(-12) +-137 + j*(-14) +-93 + j*(242) +199 + j*(199) +197 + j*(-86) +-37 + j*(-129) +-113 + j*(28) +-45 + j*(131) +69 + j*(158) +174 + j*(63) +106 + j*(-69) +-1 + j*(5) +128 + j*(93) +242 + j*(-97) +55 + j*(-266) +-127 + j*(-158) +-124 + j*(-42) +-134 + j*(18) +-73 + j*(149) +127 + j*(127) +139 + j*(-74) +-11 + j*(-93) +-3 + j*(-16) +10 + j*(-75) +-98 + j*(-40) +-27 + j*(89) +96 + j*(-18) +-55 + j*(-123) +-149 + j*(67) +45 + j*(164) +137 + j*(19) +86 + j*(-37) +105 + j*(-89) +-21 + j*(-194) +-181 + j*(-13) +57 + j*(156) +234 + j*(-164) +-155 + j*(-371) +-403 + j*(13) +-110 + j*(256) +44 + j*(81) +-47 + j*(73) +78 + j*(133) +125 + j*(-73) +-116 + j*(-96) +-110 + j*(153) +117 + j*(132) +90 + j*(-28) +31 + j*(24) +131 + j*(-12) +42 + j*(-148) +-80 + j*(-46) +35 + j*(4) +-16 + j*(-148) +-221 + j*(-10) +-23 + j*(239) +247 + j*(18) +35 + j*(-240) +-163 + j*(-67) +-24 + j*(13) +-80 + j*(-137) +-294 + j*(2) +-169 + j*(264) +54 + j*(219) +59 + j*(127) +112 + j*(136) +174 + j*(1) +14 + j*(-87) +-62 + j*(85) +124 + j*(143) +178 + j*(-30) +48 + j*(-71) +57 + j*(12) +126 + j*(-59) +17 + j*(-147) +-106 + j*(-33) +-15 + j*(132) +194 + j*(95) +240 + j*(-132) +50 + j*(-254) +-88 + j*(-122) +29 + j*(-28) +99 + j*(-187) +-95 + j*(-300) +-267 + j*(-153) +-228 + j*(6) +-156 + j*(41) +-122 + j*(45) +-116 + j*(18) +-200 + j*(42) +-203 + j*(222) +21 + j*(305) +157 + j*(124) +35 + j*(19) +1 + j*(133) +151 + j*(129) +161 + j*(-35) +23 + j*(-59) +8 + j*(44) +104 + j*(49) +136 + j*(-48) +61 + j*(-132) +-68 + j*(-103) +-92 + j*(47) +61 + j*(115) +170 + j*(-22) +78 + j*(-151) +-27 + j*(-126) +-45 + j*(-93) +-95 + j*(-88) +-137 + j*(16) +-23 + j*(93) +66 + j*(-27) +-81 + j*(-129) +-231 + j*(39) +-94 + j*(255) +139 + j*(207) +181 + j*(49) +168 + j*(5) +231 + j*(-105) +105 + j*(-317) +-192 + j*(-274) +-228 + j*(-6) +-57 + j*(23) +-119 + j*(-89) +-247 + j*(63) +-71 + j*(233) +102 + j*(82) +-31 + j*(-52) +-136 + j*(80) +-28 + j*(187) +78 + j*(155) +148 + j*(89) +148 + j*(-62) +-52 + j*(-130) +-185 + j*(100) +29 + j*(301) +266 + j*(177) +280 + j*(9) +292 + j*(-85) +248 + j*(-291) +-40 + j*(-396) +-267 + j*(-170) +-177 + j*(76) +-1 + j*(95) +80 + j*(14) +73 + j*(-90) +-40 + j*(-127) +-90 + j*(-12) +42 + j*(26) +76 + j*(-139) +-103 + j*(-202) +-210 + j*(-71) +-193 + j*(36) +-164 + j*(129) +-33 + j*(216) +126 + j*(130) +117 + j*(-5) +87 + j*(-40) +73 + j*(-141) +-123 + j*(-200) +-259 + j*(21) +-77 + j*(185) +45 + j*(64) +-32 + j*(29) +25 + j*(78) +39 + j*(-61) +-186 + j*(-27) +-119 + j*(289) +267 + j*(222) +222 + j*(-170) +-119 + j*(-139) +-74 + j*(124) +100 + j*(53) +10 + j*(-36) +6 + j*(71) +132 + j*(1) +15 + j*(-147) +-148 + j*(-28) +-78 + j*(127) +16 + j*(134) +77 + j*(156) +214 + j*(111) +246 + j*(-65) +144 + j*(-152) +95 + j*(-178) +-23 + j*(-248) +-216 + j*(-129) +-152 + j*(127) +95 + j*(122) +135 + j*(-69) +17 + j*(-143) +-75 + j*(-119) +-157 + j*(-23) +-88 + j*(161) +169 + j*(155) +256 + j*(-113) +64 + j*(-281) +-111 + j*(-223) +-162 + j*(-124) +-154 + j*(-61) +-140 + j*(-59) +-221 + j*(-59) +-289 + j*(105) +-129 + j*(254) +20 + j*(151) +-62 + j*(88) +-39 + j*(217) +130 + j*(165) +64 + j*(25) +-11 + j*(163) +244 + j*(229) +377 + j*(-88) +127 + j*(-293) +-59 + j*(-196) +-95 + j*(-131) +-170 + j*(-47) +-93 + j*(93) +25 + j*(1) +-151 + j*(-75) +-233 + j*(204) +87 + j*(337) +245 + j*(80) +103 + j*(-13) +141 + j*(52) +190 + j*(-105) +-16 + j*(-148) +-7 + j*(62) +220 + j*(-32) +76 + j*(-298) +-201 + j*(-168) +-111 + j*(37) +-32 + j*(-49) +-175 + j*(-12) +-93 + j*(198) +136 + j*(139) +124 + j*(-34) +64 + j*(-37) +95 + j*(-90) +-20 + j*(-189) +-171 + j*(-74) +-114 + j*(78) +-15 + j*(88) +44 + j*(83) +137 + j*(1) +63 + j*(-166) +-142 + j*(-103) +-74 + j*(103) +123 + j*(6) +-6 + j*(-195) +-221 + j*(-57) +-105 + j*(156) +79 + j*(72) +19 + j*(-69) +-80 + j*(-19) +-35 + j*(44) +6 + j*(-13) +-87 + j*(-61) +-192 + j*(52) +-112 + j*(243) +129 + j*(253) +236 + j*(35) +91 + j*(-115) +-44 + j*(-27) +28 + j*(87) +164 + j*(11) +116 + j*(-182) +-134 + j*(-210) +-259 + j*(60) +-3 + j*(262) +236 + j*(19) +-20 + j*(-234) +-297 + j*(56) +16 + j*(375) +365 + j*(76) +103 + j*(-260) +-189 + j*(-14) +66 + j*(234) +293 + j*(-16) +82 + j*(-218) +-50 + j*(-61) +93 + j*(-19) +71 + j*(-188) +-122 + j*(-160) +-113 + j*(14) +15 + j*(16) +16 + j*(-71) +-30 + j*(-85) +-64 + j*(-98) +-147 + j*(-69) +-159 + j*(56) +-42 + j*(100) +-10 + j*(16) +-82 + j*(27) +-41 + j*(112) +51 + j*(78) +37 + j*(17) +42 + j*(22) +63 + j*(-54) +-76 + j*(-110) +-168 + j*(71) +37 + j*(191) +164 + j*(-25) +-70 + j*(-147) +-192 + j*(117) +93 + j*(267) +295 + j*(3) +106 + j*(-244) +-141 + j*(-170) +-177 + j*(23) +-72 + j*(125) +36 + j*(92) +20 + j*(3) +-78 + j*(56) +6 + j*(214) +238 + j*(158) +263 + j*(-87) +98 + j*(-170) +50 + j*(-124) +33 + j*(-194) +-156 + j*(-219) +-292 + j*(2) +-151 + j*(224) +63 + j*(221) +158 + j*(116) +206 + j*(26) +218 + j*(-108) +115 + j*(-239) +-49 + j*(-247) +-142 + j*(-158) +-155 + j*(-78) +-161 + j*(-39) +-186 + j*(23) +-165 + j*(136) +-27 + j*(216) +141 + j*(137) +158 + j*(-59) +-6 + j*(-153) +-134 + j*(-54) +-101 + j*(64) +-33 + j*(65) +-40 + j*(52) +-20 + j*(94) +48 + j*(69) +9 + j*(-5) +-81 + j*(67) +15 + j*(206) +206 + j*(132) +190 + j*(-62) +49 + j*(-74) +56 + j*(9) +117 + j*(-29) +82 + j*(-70) +109 + j*(-51) +172 + j*(-185) +-23 + j*(-366) +-314 + j*(-216) +-270 + j*(88) +-56 + j*(100) +-87 + j*(-6) +-153 + j*(111) +8 + j*(194) +96 + j*(55) +1 + j*(24) +62 + j*(109) +177 + j*(-33) +-5 + j*(-171) +-139 + j*(36) +106 + j*(148) +213 + j*(-146) +-103 + j*(-272) +-249 + j*(13) +-27 + j*(144) +54 + j*(-21) +-76 + j*(-47) +-66 + j*(56) +-2 + j*(21) +-71 + j*(-16) +-115 + j*(82) +-36 + j*(163) +71 + j*(156) +151 + j*(59) +82 + j*(-78) +-102 + j*(-16) +-26 + j*(233) +302 + j*(174) +305 + j*(-202) +-49 + j*(-272) +-136 + j*(16) +96 + j*(71) +115 + j*(-139) +-86 + j*(-150) +-104 + j*(27) +35 + j*(42) +37 + j*(-70) +-75 + j*(-55) +-54 + j*(78) +115 + j*(75) +156 + j*(-124) +-50 + j*(-234) +-222 + j*(-63) +-117 + j*(148) +104 + j*(119) +156 + j*(-89) +-21 + j*(-228) +-242 + j*(-114) +-213 + j*(168) +88 + j*(238) +245 + j*(-41) +39 + j*(-260) +-187 + j*(-162) +-201 + j*(-8) +-169 + j*(58) +-125 + j*(132) +-17 + j*(139) +13 + j*(47) +-62 + j*(23) +-98 + j*(83) +-105 + j*(158) +-29 + j*(301) +257 + j*(325) +447 + j*(-21) +163 + j*(-355) +-231 + j*(-200) +-208 + j*(164) +71 + j*(241) +204 + j*(75) +139 + j*(-61) +31 + j*(-52) +40 + j*(45) +155 + j*(26) +152 + j*(-117) +21 + j*(-144) +-9 + j*(-71) +-6 + j*(-77) +-78 + j*(-23) +15 + j*(126) +240 + j*(30) +194 + j*(-238) +-36 + j*(-265) +-91 + j*(-148) +-93 + j*(-141) +-160 + j*(-93) +-126 + j*(-5) +-101 + j*(-31) +-165 + j*(47) +11 + j*(185) +234 + j*(-70) +-75 + j*(-383) +-466 + j*(-63) +-175 + j*(363) +235 + j*(107) +8 + j*(-264) +-322 + j*(-86) +-228 + j*(157) +-153 + j*(132) +-203 + j*(249) +27 + j*(402) +252 + j*(170) +44 + j*(-29) +-88 + j*(217) +237 + j*(332) +385 + j*(-18) +80 + j*(-173) +-9 + j*(91) +257 + j*(102) +236 + j*(-187) +-31 + j*(-152) +47 + j*(62) +228 + j*(-81) +47 + j*(-245) +-74 + j*(-57) +150 + j*(-21) +128 + j*(-331) +-258 + j*(-325) +-310 + j*(66) +21 + j*(145) +88 + j*(-127) +-151 + j*(-194) +-251 + j*(-11) +-170 + j*(112) +-82 + j*(139) +-10 + j*(121) +11 + j*(64) +-31 + j*(62) +-7 + j*(124) +93 + j*(112) +126 + j*(6) +42 + j*(-59) +-32 + j*(-1) +19 + j*(89) +142 + j*(49) +147 + j*(-100) +18 + j*(-167) +-82 + j*(-115) +-127 + j*(-44) +-140 + j*(68) +-24 + j*(180) +145 + j*(122) +173 + j*(-27) +119 + j*(-105) +63 + j*(-177) +-92 + j*(-196) +-182 + j*(-29) +-30 + j*(71) +28 + j*(-77) +-143 + j*(-95) +-134 + j*(83) +23 + j*(35) +-97 + j*(-97) +-238 + j*(85) +-45 + j*(245) +86 + j*(83) +-67 + j*(37) +-52 + j*(232) +197 + j*(238) +286 + j*(17) +182 + j*(-133) +50 + j*(-175) +-86 + j*(-118) +-106 + j*(40) +28 + j*(112) +120 + j*(37) +129 + j*(-43) +112 + j*(-134) +-9 + j*(-215) +-161 + j*(-141) +-180 + j*(-4) +-148 + j*(71) +-98 + j*(168) +72 + j*(206) +185 + j*(52) +101 + j*(-66) +54 + j*(-49) +39 + j*(-105) +-122 + j*(-78) +-98 + j*(180) +253 + j*(181) +315 + j*(-221) +-54 + j*(-357) +-211 + j*(-95) +-59 + j*(-6) +-71 + j*(-112) +-192 + j*(-51) +-170 + j*(62) +-144 + j*(98) +-115 + j*(206) +75 + j*(272) +245 + j*(103) +181 + j*(-96) +48 + j*(-134) +-18 + j*(-117) +-96 + j*(-97) +-159 + j*(6) +-98 + j*(127) +32 + j*(123) +52 + j*(21) +-45 + j*(25) +-13 + j*(169) +207 + j*(154) +260 + j*(-107) +22 + j*(-226) +-115 + j*(-51) +6 + j*(68) +105 + j*(-15) +75 + j*(-115) +-16 + j*(-165) +-156 + j*(-121) +-179 + j*(66) +6 + j*(146) +101 + j*(-12) +-24 + j*(-93) +-80 + j*(9) +5 + j*(45) +41 + j*(-20) +14 + j*(-86) +-86 + j*(-133) +-232 + j*(-35) +-189 + j*(170) +-17 + j*(186) +-16 + j*(129) +40 + j*(239) +302 + j*(142) +232 + j*(-231) +-175 + j*(-193) +-135 + j*(192) +209 + j*(107) +62 + j*(-202) +-229 + j*(6) +7 + j*(298) +291 + j*(92) +164 + j*(-139) +38 + j*(-79) +85 + j*(-69) +36 + j*(-137) +-35 + j*(-97) +-25 + j*(-71) +-74 + j*(-62) +-58 + j*(52) +118 + j*(33) +110 + j*(-211) +-180 + j*(-263) +-324 + j*(4) +-163 + j*(216) +29 + j*(197) +110 + j*(105) +139 + j*(16) +114 + j*(-91) +-4 + j*(-152) +-122 + j*(-69) +-78 + j*(74) +77 + j*(49) +64 + j*(-122) +-115 + j*(-130) +-146 + j*(22) +-57 + j*(50) +-74 + j*(18) +-73 + j*(103) +56 + j*(91) +34 + j*(-60) +-123 + j*(-23) +-85 + j*(131) +33 + j*(101) +-1 + j*(56) +42 + j*(124) +165 + j*(4) +-16 + j*(-183) +-284 + j*(33) +-88 + j*(383) +301 + j*(281) +313 + j*(-45) +132 + j*(-107) +120 + j*(-59) +117 + j*(-146) +-25 + j*(-164) +-78 + j*(-21) +50 + j*(42) +121 + j*(-77) +15 + j*(-170) +-95 + j*(-87) +-25 + j*(22) +95 + j*(-66) +-10 + j*(-231) +-231 + j*(-156) +-216 + j*(67) +-58 + j*(75) +-108 + j*(-13) +-192 + j*(141) +27 + j*(284) +223 + j*(67) +39 + j*(-119) +-94 + j*(57) +118 + j*(142) +185 + j*(-107) +-74 + j*(-174) +-129 + j*(74) +108 + j*(103) +122 + j*(-139) +-121 + j*(-174) +-208 + j*(45) +-54 + j*(185) +111 + j*(119) +115 + j*(-40) +-29 + j*(-81) +-82 + j*(69) +83 + j*(148) +202 + j*(0) +124 + j*(-132) +52 + j*(-143) +6 + j*(-183) +-119 + j*(-177) +-158 + j*(-59) +-113 + j*(-46) +-206 + j*(-45) +-221 + j*(156) +25 + j*(206) +66 + j*(-45) +-206 + j*(-42) +-188 + j*(257) +80 + j*(268) +86 + j*(122) +84 + j*(221) +343 + j*(170) +361 + j*(-197) +23 + j*(-321) +-142 + j*(-121) +-106 + j*(-8) +-95 + j*(71) +39 + j*(152) +164 + j*(8) +15 + j*(-106) +-46 + j*(63) +163 + j*(71) +142 + j*(-177) +-112 + j*(-150) +-83 + j*(72) +87 + j*(40) +53 + j*(-65) +25 + j*(-30) +74 + j*(-76) +-7 + j*(-144) +-54 + j*(-71) +3 + j*(-107) +-147 + j*(-208) +-345 + j*(4) +-169 + j*(287) +110 + j*(211) +119 + j*(41) +110 + j*(19) +148 + j*(-118) +-73 + j*(-258) +-314 + j*(-25) +-127 + j*(276) +167 + j*(165) +117 + j*(-55) +-4 + j*(-7) +100 + j*(40) +143 + j*(-129) +-39 + j*(-216) +-150 + j*(-91) +-101 + j*(-23) +-125 + j*(-52) +-200 + j*(29) +-144 + j*(153) +-40 + j*(166) +11 + j*(151) +85 + j*(118) +91 + j*(-7) +-61 + j*(-33) +-100 + j*(148) +93 + j*(218) +199 + j*(59) +112 + j*(-40) +63 + j*(-27) +28 + j*(-44) +-54 + j*(28) +35 + j*(182) +256 + j*(131) +306 + j*(-94) +187 + j*(-243) +21 + j*(-292) +-157 + j*(-193) +-129 + j*(25) +83 + j*(13) +42 + j*(-211) +-204 + j*(-165) +-187 + j*(63) +-46 + j*(74) +-51 + j*(54) +43 + j*(98) +112 + j*(-78) +-137 + j*(-135) +-150 + j*(200) +284 + j*(163) +214 + j*(-362) +-363 + j*(-276) +-255 + j*(302) +293 + j*(146) +83 + j*(-375) +-423 + j*(-147) +-228 + j*(315) +134 + j*(178) +39 + j*(-47) +-64 + j*(32) +-3 + j*(41) +-75 + j*(15) +-71 + j*(171) +154 + j*(167) +175 + j*(-86) +-69 + j*(-142) +-149 + j*(66) +4 + j*(169) +115 + j*(78) +75 + j*(-21) +-17 + j*(6) +23 + j*(125) +205 + j*(89) +219 + j*(-150) +-26 + j*(-232) +-145 + j*(-30) +8 + j*(84) +98 + j*(-42) +-12 + j*(-126) +-103 + j*(-57) +-100 + j*(23) +-71 + j*(86) +13 + j*(136) +128 + j*(88) +135 + j*(-43) +35 + j*(-82) +3 + j*(-13) +74 + j*(-7) +74 + j*(-98) +-23 + j*(-114) +-48 + j*(-29) +23 + j*(-13) +37 + j*(-82) +-19 + j*(-112) +-54 + j*(-98) +-83 + j*(-95) +-122 + j*(-71) +-146 + j*(-47) +-209 + j*(-8) +-245 + j*(141) +-91 + j*(293) +115 + j*(228) +140 + j*(78) +114 + j*(45) +153 + j*(-23) +64 + j*(-152) +-105 + j*(-92) +-72 + j*(58) +28 + j*(18) +-56 + j*(-42) +-107 + j*(85) +36 + j*(156) +123 + j*(37) +47 + j*(-40) +1 + j*(1) +21 + j*(21) +24 + j*(16) +45 + j*(29) +75 + j*(-9) +35 + j*(-57) +-26 + j*(-11) +36 + j*(71) +168 + j*(4) +137 + j*(-182) +-62 + j*(-215) +-121 + j*(-64) +-18 + j*(-70) +-149 + j*(-198) +-399 + j*(23) +-184 + j*(413) +272 + j*(271) +185 + j*(-159) +-191 + j*(-66) +-62 + j*(284) +279 + j*(151) +170 + j*(-151) +-56 + j*(-49) +82 + j*(110) +231 + j*(-54) +95 + j*(-223) +-56 + j*(-167) +-69 + j*(-92) +-76 + j*(-71) +-86 + j*(-23) +-50 + j*(15) +-8 + j*(13) +24 + j*(-11) +33 + j*(-72) +-23 + j*(-122) +-91 + j*(-112) +-129 + j*(-92) +-197 + j*(-66) +-251 + j*(42) +-188 + j*(165) +-86 + j*(171) +-81 + j*(136) +-107 + j*(202) +-6 + j*(310) +184 + j*(270) +243 + j*(90) +127 + j*(6) +94 + j*(98) +244 + j*(95) +273 + j*(-111) +74 + j*(-185) +13 + j*(-28) +173 + j*(-26) +148 + j*(-244) +-113 + j*(-246) +-159 + j*(-1) +40 + j*(54) +84 + j*(-108) +-50 + j*(-150) +-100 + j*(-60) +-72 + j*(-21) +-64 + j*(3) +-14 + j*(33) +53 + j*(-29) +1 + j*(-134) +-134 + j*(-132) +-203 + j*(-6) +-136 + j*(125) +16 + j*(111) +16 + j*(-48) +-190 + j*(-33) +-182 + j*(265) +206 + j*(314) +344 + j*(-115) +-71 + j*(-330) +-330 + j*(21) +-79 + j*(273) +98 + j*(139) +45 + j*(103) +168 + j*(148) +262 + j*(-77) +10 + j*(-212) +-114 + j*(34) +141 + j*(115) +204 + j*(-159) +-43 + j*(-242) +-132 + j*(-90) +-115 + j*(-62) +-211 + j*(23) +-103 + j*(257) +225 + j*(193) +228 + j*(-151) +-64 + j*(-209) +-135 + j*(-3) +-9 + j*(37) +-16 + j*(-38) +-65 + j*(2) +-9 + j*(28) +-17 + j*(-59) +-173 + j*(-44) +-218 + j*(197) +60 + j*(376) +379 + j*(150) +269 + j*(-243) +-109 + j*(-243) +-162 + j*(63) +66 + j*(113) +81 + j*(-51) +-37 + j*(-18) +35 + j*(69) +100 + j*(-15) +40 + j*(-34) +110 + j*(-2) +157 + j*(-185) +-97 + j*(-291) +-256 + j*(-37) +-44 + j*(111) +45 + j*(-82) +-172 + j*(-120) +-209 + j*(113) +-8 + j*(174) +56 + j*(55) +19 + j*(27) +41 + j*(8) +-13 + j*(-49) +-89 + j*(33) +17 + j*(125) +119 + j*(4) +6 + j*(-98) +-88 + j*(-2) +-11 + j*(70) +25 + j*(18) +-7 + j*(28) +58 + j*(59) +112 + j*(-53) +-15 + j*(-151) +-150 + j*(-53) +-114 + j*(76) +-48 + j*(92) +-37 + j*(117) +45 + j*(177) +184 + j*(117) +210 + j*(-41) +116 + j*(-142) +1 + j*(-157) +-101 + j*(-91) +-107 + j*(54) +39 + j*(117) +136 + j*(-5) +49 + j*(-109) +-28 + j*(-47) +35 + j*(-3) +76 + j*(-88) +-8 + j*(-164) +-124 + j*(-138) +-185 + j*(-31) +-127 + j*(90) +-1 + j*(72) +-35 + j*(-47) +-191 + j*(39) +-83 + j*(275) +226 + j*(209) +233 + j*(-107) +-24 + j*(-156) +-54 + j*(23) +73 + j*(-1) +4 + j*(-107) +-91 + j*(-16) +14 + j*(49) +49 + j*(-82) +-109 + j*(-105) +-136 + j*(57) +6 + j*(71) +-23 + j*(-66) +-205 + j*(0) +-170 + j*(249) +99 + j*(314) +259 + j*(119) +187 + j*(-54) +83 + j*(-64) +80 + j*(-42) +74 + j*(-91) +-12 + j*(-110) +-60 + j*(-23) +15 + j*(33) +69 + j*(-41) +-9 + j*(-100) +-71 + j*(-27) +-15 + j*(25) +7 + j*(-19) +-36 + j*(-1) +28 + j*(59) +127 + j*(-49) +-5 + j*(-206) +-233 + j*(-87) +-170 + j*(190) +111 + j*(216) +231 + j*(-8) +119 + j*(-180) +-25 + j*(-201) +-130 + j*(-160) +-214 + j*(-70) +-226 + j*(76) +-125 + j*(190) +18 + j*(189) +89 + j*(100) +66 + j*(33) +50 + j*(39) +93 + j*(19) +85 + j*(-71) +-31 + j*(-95) +-86 + j*(21) +30 + j*(101) +147 + j*(-8) +78 + j*(-171) +-108 + j*(-180) +-200 + j*(-35) +-151 + j*(91) +-68 + j*(125) +-8 + j*(127) +56 + j*(101) +77 + j*(23) +11 + j*(-21) +-42 + j*(26) +-31 + j*(79) +-11 + j*(127) +71 + j*(201) +253 + j*(163) +330 + j*(-45) +214 + j*(-199) +112 + j*(-206) +83 + j*(-250) +-57 + j*(-326) +-268 + j*(-235) +-325 + j*(4) +-178 + j*(190) +42 + j*(175) +108 + j*(-13) +-57 + j*(-97) +-132 + j*(84) +90 + j*(159) +181 + j*(-96) +-88 + j*(-200) +-194 + j*(58) +47 + j*(148) +115 + j*(-77) +-90 + j*(-131) +-146 + j*(30) +-64 + j*(77) +-58 + j*(88) +11 + j*(163) +161 + j*(100) +155 + j*(-69) +41 + j*(-119) +-9 + j*(-103) +-74 + j*(-113) +-176 + j*(-38) +-165 + j*(134) +11 + j*(231) +211 + j*(119) +199 + j*(-142) +-76 + j*(-228) +-226 + j*(30) +9 + j*(209) +200 + j*(-6) +21 + j*(-205) +-164 + j*(-93) +-141 + j*(21) +-167 + j*(45) +-193 + j*(214) +25 + j*(373) +298 + j*(247) +339 + j*(-19) +193 + j*(-187) +6 + j*(-186) +-74 + j*(-49) +9 + j*(35) +66 + j*(-16) +44 + j*(-30) +100 + j*(-42) +60 + j*(-196) +-193 + j*(-154) +-158 + j*(175) +229 + j*(144) +200 + j*(-293) +-264 + j*(-284) +-288 + j*(158) +83 + j*(194) +88 + j*(-88) +-126 + j*(-33) +-25 + j*(153) +156 + j*(48) +86 + j*(-111) +-18 + j*(-86) +-4 + j*(-40) +15 + j*(-69) +-14 + j*(-108) +-82 + j*(-122) +-151 + j*(-66) +-136 + j*(14) +-91 + j*(25) +-88 + j*(16) +-79 + j*(6) +-142 + j*(-51) +-326 + j*(49) +-298 + j*(388) +96 + j*(531) +383 + j*(238) +268 + j*(-56) +84 + j*(-71) +29 + j*(-13) +1 + j*(42) +54 + j*(143) +218 + j*(122) +266 + j*(-61) +140 + j*(-158) +66 + j*(-114) +79 + j*(-106) +57 + j*(-148) +2 + j*(-156) +-47 + j*(-148) +-113 + j*(-105) +-115 + j*(8) +15 + j*(54) +98 + j*(-83) +-35 + j*(-215) +-214 + j*(-125) +-200 + j*(57) +-76 + j*(100) +-28 + j*(53) +-25 + j*(40) +-6 + j*(14) +-44 + j*(-23) +-100 + j*(23) +-60 + j*(91) +-9 + j*(66) +-38 + j*(46) +-46 + j*(100) +6 + j*(135) +68 + j*(144) +162 + j*(107) +194 + j*(-35) +66 + j*(-109) +26 + j*(-7) +151 + j*(-57) +23 + j*(-262) +-274 + j*(-100) +-108 + j*(252) +257 + j*(83) +76 + j*(-270) +-252 + j*(-71) +-45 + j*(216) +184 + j*(10) +-11 + j*(-144) +-75 + j*(35) +95 + j*(13) +1 + j*(-161) +-164 + j*(-30) +-23 + j*(100) +51 + j*(-47) +-111 + j*(-62) +-88 + j*(113) +86 + j*(73) +46 + j*(-92) +-112 + j*(-87) +-181 + j*(48) +-118 + j*(214) +111 + j*(260) +245 + j*(37) +64 + j*(-98) +10 + j*(86) +279 + j*(38) +194 + j*(-350) +-269 + j*(-301) +-269 + j*(151) +103 + j*(166) +97 + j*(-110) +-85 + j*(-75) +-29 + j*(7) +-47 + j*(-75) +-155 + j*(13) +-47 + j*(115) +-23 + j*(8) +-161 + j*(115) +73 + j*(341) +402 + j*(43) +104 + j*(-348) +-291 + j*(-73) +-41 + j*(291) +286 + j*(80) +141 + j*(-188) +-30 + j*(-125) +-25 + j*(-79) +-93 + j*(-71) +-95 + j*(68) +67 + j*(79) +82 + j*(-76) +-42 + j*(-91) +-57 + j*(-19) +-46 + j*(-17) +-73 + j*(24) +-16 + j*(76) +40 + j*(37) +27 + j*(22) +93 + j*(28) +146 + j*(-124) +-43 + j*(-261) +-264 + j*(-112) +-212 + j*(122) +-37 + j*(161) +26 + j*(78) +6 + j*(52) +33 + j*(64) +81 + j*(0) +-1 + j*(-100) +-160 + j*(-18) +-111 + j*(191) +105 + j*(204) +164 + j*(69) +171 + j*(43) +288 + j*(-88) +132 + j*(-406) +-337 + j*(-333) +-398 + j*(167) +19 + j*(324) +200 + j*(46) +62 + j*(-95) +-21 + j*(-85) +-133 + j*(-71) +-204 + j*(156) +99 + j*(325) +346 + j*(9) +52 + j*(-248) +-148 + j*(45) +208 + j*(187) +358 + j*(-264) +-139 + j*(-507) +-506 + j*(-58) +-180 + j*(391) +290 + j*(215) +249 + j*(-226) +-124 + j*(-294) +-255 + j*(-22) +-95 + j*(107) +-29 + j*(27) +-74 + j*(37) +-13 + j*(66) +-13 + j*(-32) +-161 + j*(-1) +-132 + j*(199) +66 + j*(206) +91 + j*(81) +59 + j*(102) +163 + j*(83) +148 + j*(-71) +2 + j*(-67) +16 + j*(41) +86 + j*(13) +69 + j*(-12) +115 + j*(-17) +103 + j*(-153) +-99 + j*(-158) +-127 + j*(71) +85 + j*(114) +129 + j*(-27) +112 + j*(-34) +218 + j*(-152) +32 + j*(-427) +-383 + j*(-278) +-339 + j*(162) +15 + j*(195) +56 + j*(-23) +-36 + j*(-38) +-22 + j*(-61) +-161 + j*(-107) +-261 + j*(129) +12 + j*(298) +224 + j*(59) +70 + j*(-136) +-52 + j*(-70) +-47 + j*(-59) +-140 + j*(-52) +-154 + j*(98) +-23 + j*(129) +-24 + j*(57) +-47 + j*(139) +116 + j*(153) +151 + j*(-49) +-37 + j*(-100) +-79 + j*(33) +-25 + j*(25) +-133 + j*(35) +-129 + j*(269) +173 + j*(357) +363 + j*(115) +275 + j*(-83) +205 + j*(-116) +185 + j*(-214) +9 + j*(-309) +-196 + j*(-190) +-194 + j*(33) +-32 + j*(125) +95 + j*(32) +40 + j*(-100) +-120 + j*(-52) +-76 + j*(165) +205 + j*(163) +271 + j*(-156) +-33 + j*(-278) +-160 + j*(-15) +83 + j*(70) +123 + j*(-186) +-147 + j*(-210) +-156 + j*(40) +52 + j*(11) +-41 + j*(-169) +-214 + j*(-28) +-52 + j*(142) +107 + j*(-16) +-21 + j*(-165) +-147 + j*(-124) +-230 + j*(-78) +-342 + j*(105) +-146 + j*(390) +249 + j*(259) +194 + j*(-158) +-195 + j*(-152) +-223 + j*(187) +37 + j*(253) +122 + j*(97) +56 + j*(23) +-13 + j*(51) +5 + j*(165) +209 + j*(189) +316 + j*(-83) +35 + j*(-265) +-167 + j*(-19) +47 + j*(158) +181 + j*(-25) +46 + j*(-106) +53 + j*(-27) +105 + j*(-142) +-91 + j*(-211) +-183 + j*(-4) +-4 + j*(66) +-1 + j*(-104) +-207 + j*(-59) +-187 + j*(189) +39 + j*(249) +162 + j*(117) +140 + j*(-4) +64 + j*(-35) +35 + j*(21) +118 + j*(47) +178 + j*(-62) +99 + j*(-157) +27 + j*(-137) +33 + j*(-146) +-40 + j*(-216) +-193 + j*(-161) +-205 + j*(27) +-36 + j*(80) +11 + j*(-88) +-214 + j*(-137) +-328 + j*(147) +-54 + j*(356) +190 + j*(168) +86 + j*(-4) +30 + j*(81) +143 + j*(59) +93 + j*(-39) +91 + j*(59) +321 + j*(-57) +171 + j*(-471) +-364 + j*(-392) +-382 + j*(114) +-21 + j*(144) +-91 + j*(-66) +-223 + j*(142) +67 + j*(259) +170 + j*(-28) +-49 + j*(-78) +-8 + j*(59) +57 + j*(-97) +-209 + j*(-124) +-242 + j*(199) +52 + j*(252) +82 + j*(60) +1 + j*(119) +163 + j*(142) +177 + j*(-79) +-37 + j*(-81) +-11 + j*(94) +128 + j*(43) +76 + j*(-49) +56 + j*(-5) +112 + j*(-57) +29 + j*(-132) +-37 + j*(-64) +15 + j*(-53) +-33 + j*(-123) +-136 + j*(-69) +-132 + j*(37) +-85 + j*(86) +-25 + j*(117) +38 + j*(82) +11 + j*(58) +51 + j*(136) +216 + j*(64) +161 + j*(-162) +-64 + j*(-133) +-36 + j*(40) +72 + j*(-15) +-13 + j*(-60) +1 + j*(43) +103 + j*(-13) +25 + j*(-83) +36 + j*(16) +181 + j*(-104) +-18 + j*(-312) +-258 + j*(-88) +-38 + j*(113) +69 + j*(-120) +-192 + j*(-119) +-91 + j*(164) +205 + j*(-31) +-57 + j*(-346) +-381 + j*(-87) +-197 + j*(186) +-54 + j*(93) +-95 + j*(115) +54 + j*(133) +33 + j*(-93) +-244 + j*(-11) +-107 + j*(305) +207 + j*(138) +18 + j*(-119) +-147 + j*(105) +119 + j*(175) +96 + j*(-133) +-253 + j*(-41) +-149 + j*(344) +222 + j*(285) +220 + j*(11) +82 + j*(6) +124 + j*(48) +144 + j*(-33) +71 + j*(-71) +6 + j*(-41) +-13 + j*(59) +137 + j*(151) +328 + j*(-30) +182 + j*(-309) +-106 + j*(-240) +-87 + j*(-27) +31 + j*(-71) +-78 + j*(-133) +-141 + j*(31) +40 + j*(122) +172 + j*(-39) +65 + j*(-214) +-133 + j*(-192) +-195 + j*(-4) +-39 + j*(106) +78 + j*(-33) +-74 + j*(-144) +-187 + j*(40) +24 + j*(165) +167 + j*(-59) +-47 + j*(-227) +-223 + j*(-54) +-111 + j*(86) +-56 + j*(2) +-182 + j*(34) +-129 + j*(248) +155 + j*(257) +254 + j*(-10) +76 + j*(-153) +-18 + j*(-66) +47 + j*(-84) +-64 + j*(-223) +-321 + j*(-112) +-313 + j*(218) +-22 + j*(334) +153 + j*(167) +99 + j*(27) +22 + j*(46) +63 + j*(111) +179 + j*(66) +187 + j*(-107) +5 + j*(-195) +-132 + j*(-49) +-30 + j*(89) +84 + j*(16) +40 + j*(-76) +-21 + j*(-76) +-74 + j*(-69) +-136 + j*(7) +-70 + j*(119) +35 + j*(62) +-59 + j*(2) +-95 + j*(186) +182 + j*(254) +316 + j*(-60) +25 + j*(-243) +-161 + j*(4) +49 + j*(172) +197 + j*(2) +77 + j*(-119) +9 + j*(-37) +89 + j*(-21) +93 + j*(-126) +-8 + j*(-157) +-58 + j*(-104) +-63 + j*(-88) +-116 + j*(-65) +-126 + j*(49) +14 + j*(114) +130 + j*(-16) +37 + j*(-168) +-119 + j*(-136) +-157 + j*(-20) +-112 + j*(59) +-28 + j*(83) +31 + j*(3) +-67 + j*(-66) +-148 + j*(71) +28 + j*(179) +158 + j*(-12) +-24 + j*(-141) +-117 + j*(20) +31 + j*(50) +-12 + j*(-100) +-171 + j*(-1) +-35 + j*(156) +93 + j*(-4) +-98 + j*(-98) +-174 + j*(116) +35 + j*(187) +96 + j*(18) +-18 + j*(-19) +-39 + j*(40) +-48 + j*(51) +-66 + j*(136) +66 + j*(216) +198 + j*(115) +176 + j*(-5) +137 + j*(-35) +116 + j*(-69) +88 + j*(-67) +142 + j*(-100) +82 + j*(-290) +-246 + j*(-293) +-373 + j*(76) +-87 + j*(290) +103 + j*(158) +93 + j*(109) +226 + j*(86) +247 + j*(-175) +-47 + j*(-240) +-90 + j*(38) +199 + j*(8) +119 + j*(-333) +-255 + j*(-281) +-264 + j*(42) +-71 + j*(64) +-111 + j*(-4) +-120 + j*(132) +69 + j*(139) +86 + j*(-52) +-85 + j*(-52) +-62 + j*(112) +108 + j*(74) +86 + j*(-99) +-75 + j*(-96) +-78 + j*(42) +48 + j*(34) +23 + j*(-105) +-137 + j*(-85) +-141 + j*(82) +-5 + j*(100) +-5 + j*(16) +-49 + j*(69) +77 + j*(88) +92 + j*(-113) +-182 + j*(-150) +-276 + j*(168) +23 + j*(330) +208 + j*(107) +64 + j*(-23) +19 + j*(103) +180 + j*(107) +218 + j*(-68) +98 + j*(-160) +4 + j*(-145) +-81 + j*(-99) +-108 + j*(50) +88 + j*(154) +288 + j*(-64) +101 + j*(-367) +-256 + j*(-279) +-276 + j*(37) +-73 + j*(96) +-68 + j*(-6) +-135 + j*(78) +10 + j*(161) +100 + j*(9) +-40 + j*(-54) +-47 + j*(86) +120 + j*(31) +17 + j*(-182) +-261 + j*(-69) +-202 + j*(252) +85 + j*(308) +233 + j*(171) +313 + j*(39) +313 + j*(-197) +59 + j*(-351) +-148 + j*(-180) +-38 + j*(-49) +-81 + j*(-46) +-16 + j*(85) +103 + j*(-8) +-16 + j*(-98) +-54 + j*(54) +149 + j*(39) +102 + j*(-221) +-192 + j*(-181) +-167 + j*(105) +78 + j*(81) +42 + j*(-127) +-145 + j*(-88) +-132 + j*(79) +8 + j*(108) +81 + j*(4) +7 + j*(-110) +-141 + j*(-67) +-123 + j*(97) +32 + j*(84) +-13 + j*(-54) +-156 + j*(39) +-35 + j*(213) +158 + j*(103) +86 + j*(-72) +-36 + j*(-31) +-8 + j*(33) +12 + j*(3) +-18 + j*(3) +-26 + j*(21) +-40 + j*(49) +-1 + j*(110) +91 + j*(77) +57 + j*(-6) +1 + j*(72) +150 + j*(144) +295 + j*(-41) +176 + j*(-265) +-59 + j*(-291) +-229 + j*(-135) +-201 + j*(130) +114 + j*(213) +281 + j*(-125) +-55 + j*(-348) +-282 + j*(-45) +-9 + j*(112) +31 + j*(-186) +-354 + j*(-137) +-294 + j*(325) +173 + j*(303) +168 + j*(-91) +-138 + j*(-62) +-81 + j*(177) +95 + j*(133) +79 + j*(59) +144 + j*(83) +242 + j*(-95) +37 + j*(-299) +-247 + j*(-161) +-223 + j*(132) +5 + j*(216) +146 + j*(88) +110 + j*(-48) +15 + j*(-57) +13 + j*(1) +62 + j*(-21) +42 + j*(-80) +-10 + j*(-93) +-57 + j*(-95) +-132 + j*(-48) +-117 + j*(71) +-4 + j*(81) +-21 + j*(-1) +-98 + j*(76) +10 + j*(199) +175 + j*(142) +238 + j*(12) +245 + j*(-152) +62 + j*(-344) +-260 + j*(-221) +-199 + j*(131) +117 + j*(80) +23 + j*(-192) +-208 + j*(-39) +-1 + j*(132) +88 + j*(-134) +-250 + j*(-153) +-228 + j*(236) +160 + j*(183) +52 + j*(-163) +-254 + j*(30) +9 + j*(329) +326 + j*(51) +100 + j*(-272) +-187 + j*(-156) +-197 + j*(35) +-144 + j*(139) +-6 + j*(221) +158 + j*(98) +41 + j*(-88) +-153 + j*(50) +-9 + j*(281) +256 + j*(204) +310 + j*(-22) +224 + j*(-184) +53 + j*(-279) +-167 + j*(-194) +-196 + j*(51) +-12 + j*(165) +132 + j*(88) +176 + j*(-17) +170 + j*(-149) +28 + j*(-263) +-156 + j*(-184) +-144 + j*(-11) +-22 + j*(-8) +-47 + j*(-112) +-171 + j*(-77) +-164 + j*(60) +-51 + j*(81) +-47 + j*(-8) +-152 + j*(21) +-140 + j*(176) +28 + j*(229) +139 + j*(130) +151 + j*(42) +165 + j*(-37) +103 + j*(-161) +-70 + j*(-179) +-158 + j*(-38) +-97 + j*(66) +-30 + j*(76) +13 + j*(75) +59 + j*(37) +47 + j*(-21) +20 + j*(-23) +34 + j*(-53) +-50 + j*(-124) +-206 + j*(-18) +-139 + j*(218) +118 + j*(235) +202 + j*(41) +112 + j*(-37) +115 + j*(-7) +166 + j*(-97) +58 + j*(-223) +-95 + j*(-175) +-90 + j*(-58) +-28 + j*(-78) +-98 + j*(-123) +-185 + j*(-47) +-167 + j*(49) +-157 + j*(98) +-117 + j*(235) +140 + j*(299) +325 + j*(19) +93 + j*(-212) +-86 + j*(-13) +160 + j*(75) +199 + j*(-272) +-233 + j*(-331) +-342 + j*(107) +18 + j*(229) +87 + j*(-29) +-98 + j*(6) +40 + j*(168) +213 + j*(-25) +25 + j*(-207) +-131 + j*(-75) +-62 + j*(12) +-69 + j*(-28) +-123 + j*(47) +-41 + j*(129) +35 + j*(94) +56 + j*(64) +83 + j*(13) +10 + j*(-50) +-74 + j*(51) +56 + j*(165) +204 + j*(49) +142 + j*(-91) +78 + j*(-69) +125 + j*(-101) +64 + j*(-228) +-124 + j*(-233) +-235 + j*(-74) +-181 + j*(107) +-5 + j*(154) +80 + j*(28) +-16 + j*(-20) +17 + j*(107) +236 + j*(8) +134 + j*(-330) +-291 + j*(-291) +-337 + j*(137) +24 + j*(231) +107 + j*(-56) +-137 + j*(-117) +-220 + j*(99) +-74 + j*(236) +87 + j*(215) +190 + j*(102) +170 + j*(-55) +44 + j*(-113) +-37 + j*(-57) +-55 + j*(-3) +-64 + j*(71) +32 + j*(159) +192 + j*(98) +202 + j*(-74) +95 + j*(-137) +58 + j*(-116) +57 + j*(-165) +-45 + j*(-228) +-190 + j*(-177) +-257 + j*(-37) +-233 + j*(117) +-110 + j*(246) +111 + j*(260) +280 + j*(59) +185 + j*(-203) +-71 + j*(-223) +-153 + j*(-43) +-52 + j*(22) +-49 + j*(-45) +-122 + j*(-13) +-112 + j*(59) +-109 + j*(77) +-118 + j*(186) +57 + j*(296) +267 + j*(158) +236 + j*(-60) +112 + j*(-116) +49 + j*(-120) +-46 + j*(-100) +-64 + j*(30) +73 + j*(61) +98 + j*(-70) +-2 + j*(-81) +14 + j*(-40) +-16 + j*(-98) +-130 + j*(4) +43 + j*(180) +282 + j*(-47) +43 + j*(-334) +-238 + j*(-124) +-54 + j*(81) +45 + j*(-129) +-231 + j*(-156) +-253 + j*(165) +40 + j*(216) +103 + j*(1) +-19 + j*(-45) +-43 + j*(-1) +-65 + j*(13) +-57 + j*(88) +45 + j*(73) +1 + j*(-36) +-126 + j*(59) +-6 + j*(226) +196 + j*(142) +196 + j*(-37) +100 + j*(-117) +-24 + j*(-124) +-115 + j*(30) +78 + j*(194) +328 + j*(-31) +119 + j*(-364) +-248 + j*(-228) +-198 + j*(104) +54 + j*(115) +112 + j*(-59) +21 + j*(-175) +-156 + j*(-185) +-276 + j*(3) +-127 + j*(174) +-3 + j*(57) +-167 + j*(33) +-131 + j*(307) +233 + j*(283) +233 + j*(-86) +-93 + j*(-55) +10 + j*(262) +358 + j*(125) +259 + j*(-226) +-8 + j*(-181) +48 + j*(-40) +110 + j*(-176) +-99 + j*(-247) +-218 + j*(-33) +-54 + j*(109) +65 + j*(-14) +-57 + j*(-100) +-139 + j*(45) +28 + j*(158) +182 + j*(0) +69 + j*(-180) +-88 + j*(-124) +-69 + j*(-43) +-74 + j*(-78) +-165 + j*(-21) +-103 + j*(114) +45 + j*(63) +-7 + j*(-81) +-170 + j*(-40) +-177 + j*(142) +-13 + j*(234) +148 + j*(132) +103 + j*(-50) +-79 + j*(-21) +-26 + j*(179) +214 + j*(95) +111 + j*(-183) +-202 + j*(-62) +-65 + j*(286) +315 + j*(166) +247 + j*(-214) +-81 + j*(-214) +-130 + j*(21) +3 + j*(99) +97 + j*(65) +159 + j*(-36) +64 + j*(-176) +-128 + j*(-100) +-64 + j*(124) +179 + j*(76) +174 + j*(-169) +-23 + j*(-226) +-122 + j*(-134) +-151 + j*(-48) +-122 + j*(69) +34 + j*(99) +103 + j*(-63) +-43 + j*(-161) +-153 + j*(-62) +-126 + j*(22) +-119 + j*(59) +-62 + j*(153) +116 + j*(122) +127 + j*(-105) +-116 + j*(-155) +-199 + j*(83) +21 + j*(189) +140 + j*(-9) +-33 + j*(-146) +-199 + j*(-18) +-157 + j*(160) +-21 + j*(222) +100 + j*(185) +158 + j*(81) +110 + j*(-5) +48 + j*(25) +108 + j*(71) +187 + j*(-6) +154 + j*(-117) +86 + j*(-159) +15 + j*(-206) +-144 + j*(-207) +-269 + j*(-13) +-130 + j*(208) +117 + j*(156) +132 + j*(-68) +-62 + j*(-125) +-164 + j*(41) +-47 + j*(194) +119 + j*(163) +163 + j*(57) +165 + j*(20) +226 + j*(-57) +159 + j*(-233) +-67 + j*(-223) +-69 + j*(-4) +162 + j*(-57) +66 + j*(-364) +-327 + j*(-300) +-351 + j*(98) +-35 + j*(180) +35 + j*(-36) +-113 + j*(-70) +-138 + j*(25) +-122 + j*(54) +-122 + j*(134) +18 + j*(202) +151 + j*(71) +77 + j*(-88) +-50 + j*(-88) +-115 + j*(-35) +-170 + j*(60) +-103 + j*(218) +100 + j*(221) +163 + j*(52) +70 + j*(0) +94 + j*(52) +177 + j*(-44) +76 + j*(-206) +-129 + j*(-180) +-207 + j*(-13) +-145 + j*(124) +-36 + j*(175) +72 + j*(143) +110 + j*(42) +35 + j*(-27) +-54 + j*(42) +8 + j*(174) +184 + j*(151) +238 + j*(-20) +127 + j*(-120) +41 + j*(-89) +18 + j*(-49) +14 + j*(13) +120 + j*(69) +255 + j*(-63) +156 + j*(-270) +-48 + j*(-243) +-50 + j*(-122) +-13 + j*(-175) +-153 + j*(-200) +-223 + j*(-23) +-74 + j*(87) +52 + j*(-10) +15 + j*(-144) +-121 + j*(-197) +-276 + j*(-108) +-284 + j*(95) +-121 + j*(185) +-32 + j*(103) +-72 + j*(75) +-62 + j*(121) +-23 + j*(132) +16 + j*(161) +151 + j*(142) +204 + j*(-68) +-15 + j*(-202) +-190 + j*(-33) +-98 + j*(127) +-8 + j*(94) +-21 + j*(100) +47 + j*(135) +111 + j*(59) +66 + j*(-3) +42 + j*(13) +32 + j*(-7) +-28 + j*(33) +42 + j*(144) +214 + j*(71) +183 + j*(-139) +-11 + j*(-169) +-77 + j*(-37) +-13 + j*(28) +28 + j*(4) +6 + j*(-13) +-9 + j*(39) +87 + j*(86) +190 + j*(-39) +71 + j*(-185) +-72 + j*(-78) +59 + j*(27) +148 + j*(-169) +-95 + j*(-299) +-284 + j*(-90) +-183 + j*(114) +-41 + j*(128) +42 + j*(76) +41 + j*(-37) +-104 + j*(-27) +-61 + j*(190) +254 + j*(127) +204 + j*(-261) +-199 + j*(-235) +-174 + j*(119) +93 + j*(52) +-48 + j*(-120) +-139 + j*(107) +165 + j*(136) +159 + j*(-217) +-197 + j*(-197) +-162 + j*(107) +62 + j*(37) +-49 + j*(-124) +-175 + j*(-10) +-124 + j*(65) +-156 + j*(110) +-60 + j*(294) +245 + j*(221) +237 + j*(-116) +-35 + j*(-135) +-19 + j*(35) +81 + j*(-70) +-105 + j*(-158) +-230 + j*(45) +-98 + j*(192) +4 + j*(180) +74 + j*(200) +221 + j*(139) +243 + j*(-57) +95 + j*(-151) +-8 + j*(-93) +-18 + j*(-30) +0 + j*(6) +32 + j*(16) +68 + j*(11) +120 + j*(-41) +82 + j*(-187) +-162 + j*(-208) +-276 + j*(105) +57 + j*(322) +353 + j*(23) +128 + j*(-309) +-186 + j*(-168) +-115 + j*(102) +116 + j*(84) +170 + j*(-120) +5 + j*(-276) +-236 + j*(-190) +-244 + j*(74) +-15 + j*(129) +18 + j*(-59) +-169 + j*(-57) +-166 + j*(146) +8 + j*(187) +89 + j*(97) +104 + j*(8) +26 + j*(-96) +-151 + j*(-27) +-93 + j*(222) +204 + j*(211) +271 + j*(-60) +118 + j*(-177) +35 + j*(-197) +-118 + j*(-234) +-296 + j*(-45) +-152 + j*(199) +51 + j*(112) +-34 + j*(23) +-15 + j*(175) +233 + j*(110) +190 + j*(-203) +-110 + j*(-227) +-203 + j*(-18) +-148 + j*(100) +-77 + j*(214) +154 + j*(251) +313 + j*(-6) +112 + j*(-228) +-91 + j*(-103) +2 + j*(36) +103 + j*(-71) +-13 + j*(-194) +-187 + j*(-126) +-211 + j*(74) +-35 + j*(177) +103 + j*(34) +-38 + j*(-107) +-194 + j*(48) +-54 + j*(236) +139 + j*(153) +111 + j*(17) +49 + j*(28) +78 + j*(55) +118 + j*(41) +170 + j*(-4) +170 + j*(-122) +45 + j*(-183) +-30 + j*(-103) +19 + j*(-76) +-4 + j*(-136) +-82 + j*(-109) +-69 + j*(-55) +-71 + j*(-72) +-119 + j*(-47) +-114 + j*(8) +-107 + j*(29) +-91 + j*(101) +47 + j*(107) +65 + j*(-80) +-173 + j*(-102) +-209 + j*(184) +93 + j*(252) +185 + j*(-21) +-38 + j*(-115) +-121 + j*(50) +-29 + j*(117) +-6 + j*(107) +30 + j*(156) +132 + j*(152) +189 + j*(82) +221 + j*(23) +244 + j*(-66) +218 + j*(-163) +179 + j*(-264) +26 + j*(-409) +-295 + j*(-341) +-363 + j*(37) +-18 + j*(168) +91 + j*(-151) +-255 + j*(-233) +-349 + j*(125) +-42 + j*(233) +11 + j*(0) +-204 + j*(31) +-136 + j*(288) +141 + j*(272) +200 + j*(45) +67 + j*(-45) +-9 + j*(32) +59 + j*(119) +215 + j*(54) +209 + j*(-194) +-94 + j*(-302) +-320 + j*(-16) +-112 + j*(284) +194 + j*(171) +148 + j*(-88) +-57 + j*(-61) +-19 + j*(124) +183 + j*(101) +230 + j*(-124) +29 + j*(-272) +-207 + j*(-153) +-192 + j*(122) +68 + j*(192) +184 + j*(-30) +1 + j*(-141) +-74 + j*(33) +127 + j*(67) +157 + j*(-180) +-114 + j*(-251) +-228 + j*(-17) +-82 + j*(104) +-14 + j*(49) +-8 + j*(66) +86 + j*(42) +71 + j*(-99) +-79 + j*(-98) +-80 + j*(25) +-6 + j*(4) +-71 + j*(-25) +-71 + j*(88) +77 + j*(71) +49 + j*(-103) +-151 + j*(-70) +-147 + j*(149) +59 + j*(213) +199 + j*(84) +207 + j*(-97) +67 + j*(-251) +-182 + j*(-228) +-293 + j*(14) +-147 + j*(204) +23 + j*(180) +74 + j*(98) +80 + j*(47) +62 + j*(-4) +2 + j*(-7) +-12 + j*(57) +57 + j*(87) +107 + j*(38) +102 + j*(0) +119 + j*(-10) +156 + j*(-88) +71 + j*(-206) +-96 + j*(-164) +-83 + j*(-8) +54 + j*(-48) +-49 + j*(-215) +-287 + j*(-91) +-204 + j*(205) +94 + j*(183) +115 + j*(-76) +-100 + j*(-132) +-210 + j*(28) +-159 + j*(198) +22 + j*(296) +242 + j*(185) +238 + j*(-55) +69 + j*(-94) +85 + j*(-11) +148 + j*(-138) +-55 + j*(-249) +-222 + j*(-41) +-63 + j*(134) +74 + j*(28) +4 + j*(-62) +-53 + j*(-33) +-95 + j*(4) +-113 + j*(147) +127 + j*(271) +388 + j*(-3) +170 + j*(-368) +-207 + j*(-255) +-165 + j*(28) +-20 + j*(-34) +-176 + j*(-87) +-212 + j*(161) +56 + j*(214) +88 + j*(-25) +-130 + j*(20) +-13 + j*(269) +270 + j*(145) +179 + j*(-109) +32 + j*(-13) +214 + j*(32) +240 + j*(-249) +-54 + j*(-318) +-115 + j*(-124) +-49 + j*(-179) +-281 + j*(-192) +-308 + j*(177) +122 + j*(210) +110 + j*(-257) +-413 + j*(-193) +-341 + j*(371) +194 + j*(319) +129 + j*(-114) +-196 + j*(16) +9 + j*(273) +226 + j*(30) +-14 + j*(-144) +-143 + j*(71) +37 + j*(160) +98 + j*(29) +11 + j*(-23) +-62 + j*(30) +-59 + j*(172) +170 + j*(260) +374 + j*(-22) +91 + j*(-315) +-235 + j*(-52) +17 + j*(264) +308 + j*(32) +112 + j*(-209) +-40 + j*(-46) +129 + j*(11) +146 + j*(-182) +-29 + j*(-237) +-134 + j*(-165) +-228 + j*(-64) +-201 + j*(183) +124 + j*(269) +307 + j*(-57) +36 + j*(-274) +-158 + j*(-65) +25 + j*(76) +141 + j*(-103) +-4 + j*(-233) +-125 + j*(-177) +-166 + j*(-139) +-263 + j*(-87) +-305 + j*(98) +-144 + j*(253) +52 + j*(184) +46 + j*(33) +-37 + j*(44) +24 + j*(87) +57 + j*(-37) +-132 + j*(-75) +-199 + j*(168) +64 + j*(276) +189 + j*(35) +-25 + j*(-61) +-81 + j*(156) +144 + j*(209) +223 + j*(22) +127 + j*(-48) +130 + j*(-33) +136 + j*(-127) +8 + j*(-185) +-102 + j*(-104) +-106 + j*(10) +-30 + j*(91) +103 + j*(66) +124 + j*(-93) +-32 + j*(-141) +-78 + j*(-13) +25 + j*(-13) +-52 + j*(-115) +-190 + j*(29) +-10 + j*(219) +214 + j*(38) +43 + j*(-186) +-152 + j*(-14) +47 + j*(155) +214 + j*(-83) +-40 + j*(-281) +-275 + j*(-59) +-132 + j*(180) +62 + j*(122) +66 + j*(18) +66 + j*(-15) +33 + j*(-124) +-178 + j*(-131) +-274 + j*(151) +3 + j*(363) +296 + j*(180) +255 + j*(-107) +62 + j*(-172) +-33 + j*(-97) +-42 + j*(-28) +-8 + j*(23) +67 + j*(13) +92 + j*(-84) +-1 + j*(-163) +-136 + j*(-114) +-154 + j*(33) +-37 + j*(105) +46 + j*(37) +23 + j*(-28) +-10 + j*(-42) +-65 + j*(-58) +-161 + j*(40) +-48 + j*(238) +242 + j*(153) +208 + j*(-176) +-96 + j*(-171) +-71 + j*(79) +141 + j*(0) +22 + j*(-195) +-145 + j*(-69) +-23 + j*(32) +1 + j*(-106) +-158 + j*(-91) +-144 + j*(37) +-114 + j*(6) +-225 + j*(88) +-99 + j*(313) +187 + j*(224) +156 + j*(-27) +6 + j*(-21) +26 + j*(18) +-44 + j*(-21) +-110 + j*(156) +166 + j*(279) +373 + j*(-39) +102 + j*(-322) +-210 + j*(-171) +-206 + j*(98) +-38 + j*(230) +175 + j*(190) +238 + j*(-39) +24 + j*(-137) +-42 + j*(72) +193 + j*(92) +178 + j*(-170) +-78 + j*(-119) +30 + j*(127) +289 + j*(-23) +171 + j*(-293) +-29 + j*(-264) +-54 + j*(-238) +-212 + j*(-272) +-380 + j*(-33) +-190 + j*(227) +57 + j*(135) +23 + j*(-16) +-23 + j*(14) +38 + j*(-11) +-19 + j*(-117) +-170 + j*(-73) +-187 + j*(109) +-20 + j*(211) +161 + j*(103) +127 + j*(-109) +-69 + j*(-141) +-123 + j*(8) +-30 + j*(41) +-50 + j*(-23) +-117 + j*(51) +-20 + j*(134) +69 + j*(46) +-4 + j*(-28) +-60 + j*(30) +-26 + j*(81) +18 + j*(88) +84 + j*(67) +106 + j*(-46) +-32 + j*(-121) +-155 + j*(11) +-52 + j*(162) +104 + j*(91) +49 + j*(-57) +-107 + j*(-10) +-84 + j*(162) +78 + j*(184) +108 + j*(79) +66 + j*(119) +233 + j*(180) +402 + j*(-80) +151 + j*(-373) +-197 + j*(-202) +-103 + j*(110) +122 + j*(50) +57 + j*(-78) +13 + j*(30) +183 + j*(25) +190 + j*(-180) +16 + j*(-221) +-12 + j*(-131) +28 + j*(-171) +-58 + j*(-234) +-159 + j*(-191) +-208 + j*(-126) +-233 + j*(-35) +-175 + j*(46) +-124 + j*(7) +-218 + j*(2) +-249 + j*(175) +-74 + j*(280) +54 + j*(189) +38 + j*(134) +87 + j*(160) +177 + j*(76) +134 + j*(-44) +55 + j*(-45) +66 + j*(-36) +42 + j*(-107) +-86 + j*(-110) +-147 + j*(40) +-18 + j*(158) +138 + j*(78) +116 + j*(-87) +-26 + j*(-118) +-91 + j*(-23) +-45 + j*(52) +23 + j*(49) +59 + j*(-13) +6 + j*(-88) +-102 + j*(-58) +-103 + j*(64) +0 + j*(80) +0 + j*(1) +-79 + j*(38) +-22 + j*(141) +101 + j*(96) +76 + j*(-18) +-18 + j*(6) +22 + j*(97) +136 + j*(53) +112 + j*(-92) +-50 + j*(-98) +-86 + j*(70) +83 + j*(131) +158 + j*(-28) +12 + j*(-99) +-45 + j*(52) +128 + j*(119) +250 + j*(-48) +161 + j*(-238) +-41 + j*(-281) +-210 + j*(-143) +-170 + j*(83) +44 + j*(117) +103 + j*(-55) +-17 + j*(-90) +6 + j*(-11) +67 + j*(-115) +-100 + j*(-185) +-186 + j*(7) +6 + j*(85) +59 + j*(-106) +-128 + j*(-150) +-174 + j*(-2) +-106 + j*(23) +-146 + j*(30) +-115 + j*(137) +16 + j*(115) +-12 + j*(10) +-88 + j*(73) +11 + j*(140) +76 + j*(25) +-41 + j*(-23) +-69 + j*(100) +61 + j*(120) +73 + j*(-14) +-76 + j*(-17) +-76 + j*(166) +146 + j*(190) +203 + j*(-59) +-65 + j*(-141) +-179 + j*(158) +127 + j*(331) +366 + j*(92) +271 + j*(-130) +192 + j*(-168) +129 + j*(-303) +-170 + j*(-330) +-313 + j*(18) +4 + j*(231) +230 + j*(-30) +35 + j*(-240) +-133 + j*(-135) +-115 + j*(-52) +-153 + j*(-35) +-172 + j*(101) +-16 + j*(192) +129 + j*(86) +98 + j*(-69) +-40 + j*(-105) +-125 + j*(18) +-9 + j*(138) +136 + j*(25) +25 + j*(-136) +-140 + j*(-26) +-40 + j*(128) +86 + j*(42) +8 + j*(-37) +-24 + j*(43) +59 + j*(53) +67 + j*(-8) +61 + j*(-6) +91 + j*(-59) +16 + j*(-127) +-57 + j*(-59) +2 + j*(-24) +-6 + j*(-105) +-116 + j*(-82) +-112 + j*(23) +-62 + j*(28) +-76 + j*(44) +-19 + j*(91) +38 + j*(19) +-56 + j*(-11) +-56 + j*(129) +135 + j*(124) +157 + j*(-80) +3 + j*(-127) +-21 + j*(-65) +-49 + j*(-135) +-255 + j*(-85) +-267 + j*(240) +88 + j*(366) +314 + j*(74) +134 + j*(-172) +-48 + j*(-84) +16 + j*(-5) +13 + j*(-124) +-199 + j*(-104) +-243 + j*(177) +21 + j*(323) +231 + j*(174) +241 + j*(6) +211 + j*(-120) +67 + j*(-256) +-177 + j*(-171) +-163 + j*(88) +32 + j*(101) +6 + j*(3) +-6 + j*(133) +254 + j*(110) +267 + j*(-250) +-100 + j*(-334) +-221 + j*(-70) +-113 + j*(-4) +-188 + j*(12) +-129 + j*(237) +175 + j*(192) +129 + j*(-105) +-121 + j*(4) +83 + j*(243) +358 + j*(-13) +136 + j*(-320) +-134 + j*(-193) +-85 + j*(-28) +-25 + j*(-49) +-39 + j*(-59) +-42 + j*(-81) +-126 + j*(-83) +-144 + j*(44) +-16 + j*(53) +-59 + j*(-66) +-182 + j*(48) +-15 + j*(173) +83 + j*(-40) +-190 + j*(-96) +-234 + j*(235) +103 + j*(293) +141 + j*(22) +-61 + j*(75) +105 + j*(276) +367 + j*(68) +211 + j*(-231) +-35 + j*(-161) +0 + j*(-14) +74 + j*(-76) +-12 + j*(-136) +-82 + j*(-64) +-36 + j*(-12) +-21 + j*(-69) +-129 + j*(-76) +-170 + j*(76) +-22 + j*(163) +64 + j*(42) +-47 + j*(8) +-32 + j*(148) +131 + j*(115) +85 + j*(-23) +4 + j*(89) +236 + j*(157) +371 + j*(-161) +77 + j*(-395) +-167 + j*(-233) +-142 + j*(-103) +-190 + j*(-85) +-221 + j*(99) +-4 + j*(197) +113 + j*(18) +-13 + j*(-54) +-8 + j*(36) +69 + j*(-48) +-64 + j*(-131) +-150 + j*(8) +-42 + j*(59) +-83 + j*(-22) +-187 + j*(132) +33 + j*(313) +291 + j*(114) +173 + j*(-157) +-25 + j*(-118) +-11 + j*(-26) +-4 + j*(-68) +-82 + j*(-47) +-72 + j*(32) +-42 + j*(31) +-70 + j*(67) +2 + j*(145) +115 + j*(83) +69 + j*(-19) +2 + j*(51) +117 + j*(122) +245 + j*(2) +214 + j*(-159) +125 + j*(-253) +-7 + j*(-340) +-247 + j*(-320) +-415 + j*(-74) +-314 + j*(210) +-62 + j*(283) +95 + j*(155) +68 + j*(13) +-33 + j*(16) +-16 + j*(117) +112 + j*(99) +112 + j*(-35) +4 + j*(-37) +42 + j*(50) +138 + j*(-35) +48 + j*(-168) +-95 + j*(-132) +-135 + j*(-46) +-175 + j*(45) +-99 + j*(234) +212 + j*(230) +308 + j*(-136) +-42 + j*(-317) +-255 + j*(-39) +-71 + j*(141) +24 + j*(26) +-61 + j*(32) +14 + j*(115) +88 + j*(12) +-23 + j*(-21) +12 + j*(112) +178 + j*(14) +47 + j*(-193) +-189 + j*(-53) +-62 + j*(185) +148 + j*(84) +74 + j*(-69) +-12 + j*(-4) +55 + j*(35) +66 + j*(-12) +81 + j*(13) +192 + j*(-59) +122 + j*(-283) +-159 + j*(-285) +-238 + j*(-45) +-95 + j*(30) +-93 + j*(-46) +-166 + j*(18) +-97 + j*(98) +-63 + j*(34) +-175 + j*(78) +-115 + j*(289) +161 + j*(317) +301 + j*(96) +231 + j*(-69) +163 + j*(-127) +91 + j*(-209) +-72 + j*(-214) +-153 + j*(-78) +-91 + j*(0) +-83 + j*(-28) +-144 + j*(37) +-59 + j*(159) +102 + j*(96) +62 + j*(-69) +-101 + j*(-29) +-47 + j*(142) +145 + j*(75) +66 + j*(-145) +-194 + j*(-59) +-121 + j*(255) +226 + j*(237) +284 + j*(-82) +60 + j*(-177) +6 + j*(-68) +46 + j*(-112) +-89 + j*(-147) +-141 + j*(33) +42 + j*(86) +74 + j*(-95) +-98 + j*(-101) +-79 + j*(47) +28 + j*(-16) +-104 + j*(-104) +-210 + j*(83) +-21 + j*(232) +139 + j*(103) +92 + j*(-8) +67 + j*(-16) +40 + j*(-74) +-71 + j*(-34) +2 + j*(122) +231 + j*(6) +110 + j*(-317) +-290 + j*(-269) +-358 + j*(111) +-109 + j*(267) +21 + j*(192) +65 + j*(185) +185 + j*(136) +192 + j*(-16) +103 + j*(-41) +150 + j*(-35) +134 + j*(-185) +-76 + j*(-198) +-94 + j*(1) +70 + j*(-44) +-75 + j*(-212) +-285 + j*(13) +-35 + j*(257) +196 + j*(19) +-34 + j*(-148) +-113 + j*(96) +163 + j*(103) +129 + j*(-198) +-148 + j*(-154) +-99 + j*(44) +-8 + j*(-47) +-171 + j*(-51) +-137 + j*(169) +82 + j*(134) +39 + j*(-27) +-40 + j*(47) +66 + j*(49) +6 + j*(-69) +-103 + j*(54) +69 + j*(132) +98 + j*(-70) +-124 + j*(-29) +-10 + j*(222) +260 + j*(67) +114 + j*(-181) +-49 + j*(-58) +71 + j*(-25) +-18 + j*(-165) +-169 + j*(13) +81 + j*(142) +180 + j*(-171) +-167 + j*(-261) +-250 + j*(37) +-76 + j*(62) +-204 + j*(18) +-202 + j*(334) +235 + j*(380) +347 + j*(-47) +23 + j*(-152) +3 + j*(66) +168 + j*(-11) +37 + j*(-153) +-72 + j*(-21) +45 + j*(47) +83 + j*(-41) +49 + j*(-69) +35 + j*(-114) +-78 + j*(-126) +-99 + j*(24) +77 + j*(13) +19 + j*(-216) +-276 + j*(-156) +-284 + j*(150) +-77 + j*(244) +25 + j*(216) +167 + j*(210) +296 + j*(-6) +105 + j*(-216) +-93 + j*(-66) +57 + j*(64) +146 + j*(-127) +-79 + j*(-224) +-211 + j*(-19) +-73 + j*(138) +80 + j*(81) +96 + j*(-46) +1 + j*(-110) +-70 + j*(-42) +5 + j*(-4) +1 + j*(-139) +-228 + j*(-139) +-295 + j*(160) +-11 + j*(317) +194 + j*(139) +155 + j*(-28) +108 + j*(-105) +-11 + j*(-213) +-255 + j*(-135) +-271 + j*(165) +-18 + j*(264) +84 + j*(119) +25 + j*(99) +105 + j*(161) +235 + j*(39) +151 + j*(-148) +-40 + j*(-140) +-90 + j*(16) +25 + j*(94) +120 + j*(14) +75 + j*(-83) +5 + j*(-74) +2 + j*(-60) +-56 + j*(-86) +-141 + j*(25) +-11 + j*(178) +184 + j*(57) +73 + j*(-150) +-120 + j*(-24) +37 + j*(170) +266 + j*(-8) +126 + j*(-279) +-144 + j*(-231) +-191 + j*(-41) +-134 + j*(50) +-66 + j*(119) +76 + j*(112) +122 + j*(-46) +-18 + j*(-110) +-66 + j*(10) +49 + j*(23) +34 + j*(-105) +-104 + j*(-74) +-68 + j*(72) +86 + j*(34) +71 + j*(-132) +-91 + j*(-177) +-204 + j*(-71) +-194 + j*(69) +-88 + j*(142) +6 + j*(93) +-11 + j*(27) +-46 + j*(41) +-32 + j*(51) +-63 + j*(48) +-66 + j*(142) +88 + j*(167) +131 + j*(-28) +-103 + j*(-74) +-167 + j*(211) +144 + j*(334) +329 + j*(72) +173 + j*(-104) +86 + j*(-20) +187 + j*(-28) +176 + j*(-183) +21 + j*(-251) +-116 + j*(-192) +-187 + j*(-69) +-146 + j*(75) +-13 + j*(116) +58 + j*(46) +50 + j*(-4) +40 + j*(-40) +-24 + j*(-63) +-74 + j*(33) +59 + j*(116) +192 + j*(-36) +55 + j*(-223) +-163 + j*(-145) +-164 + j*(65) +-1 + j*(142) +137 + j*(43) +119 + j*(-133) +-65 + j*(-199) +-193 + j*(-47) +-95 + j*(98) +14 + j*(49) +-11 + j*(-2) +-1 + j*(20) +31 + j*(-43) +-79 + j*(-95) +-156 + j*(33) +-37 + j*(119) +28 + j*(18) +-74 + j*(-13) +-95 + j*(91) +-21 + j*(122) +-11 + j*(119) +47 + j*(191) +222 + j*(151) +265 + j*(-71) +82 + j*(-185) +-40 + j*(-66) +66 + j*(24) +174 + j*(-113) +35 + j*(-313) +-267 + j*(-271) +-388 + j*(52) +-160 + j*(308) +133 + j*(223) +158 + j*(-12) +13 + j*(-76) +-36 + j*(-8) +-13 + j*(6) +-27 + j*(-4) +-44 + j*(18) +-49 + j*(32) +-75 + j*(81) +-13 + j*(182) +148 + j*(168) +200 + j*(19) +131 + j*(-46) +139 + j*(-54) +121 + j*(-175) +-78 + j*(-204) +-154 + j*(7) +37 + j*(87) +86 + j*(-81) +-64 + j*(-85) +-6 + j*(43) +111 + j*(-93) +-103 + j*(-233) +-294 + j*(11) +-91 + j*(235) +106 + j*(117) +64 + j*(27) +110 + j*(53) +191 + j*(-95) +31 + j*(-250) +-144 + j*(-170) +-157 + j*(-76) +-209 + j*(-36) +-236 + j*(128) +-69 + j*(251) +84 + j*(177) +125 + j*(95) +177 + j*(-8) +71 + j*(-192) +-204 + j*(-117) +-164 + j*(200) +153 + j*(187) +148 + j*(-98) +-88 + j*(-79) +-40 + j*(113) +110 + j*(35) +11 + j*(-76) +-71 + j*(46) +70 + j*(124) +175 + j*(-5) +114 + j*(-146) +-22 + j*(-192) +-167 + j*(-117) +-182 + j*(71) +-16 + j*(154) +81 + j*(30) +-27 + j*(-45) +-94 + j*(90) +71 + j*(202) +274 + j*(52) +215 + j*(-234) +-93 + j*(-301) +-268 + j*(-52) +-110 + j*(161) +73 + j*(81) +32 + j*(-45) +-45 + j*(-16) +-29 + j*(23) +-31 + j*(35) +9 + j*(85) +100 + j*(33) +43 + j*(-78) +-61 + j*(1) +64 + j*(94) +168 + j*(-78) +-13 + j*(-205) +-144 + j*(-61) +-56 + j*(13) +-86 + j*(-42) +-156 + j*(94) +42 + j*(208) +191 + j*(-6) +-13 + j*(-153) +-127 + j*(37) +59 + j*(109) +88 + j*(-75) +-93 + j*(-64) +-45 + j*(118) +148 + j*(40) +61 + j*(-171) +-164 + j*(-104) +-133 + j*(106) +27 + j*(103) +9 + j*(1) +-65 + j*(74) +59 + j*(178) +222 + j*(57) +158 + j*(-132) +12 + j*(-125) +33 + j*(-59) +55 + j*(-160) +-129 + j*(-214) +-256 + j*(-8) +-85 + j*(175) +112 + j*(47) +15 + j*(-156) +-210 + j*(-97) +-221 + j*(140) +-15 + j*(230) +112 + j*(87) +8 + j*(-23) +-72 + j*(98) +100 + j*(187) +235 + j*(-24) +18 + j*(-221) +-236 + j*(-31) +-109 + j*(274) +211 + j*(248) +299 + j*(-25) +122 + j*(-179) +-27 + j*(-86) +56 + j*(40) +208 + j*(-78) +81 + j*(-318) +-235 + j*(-260) +-277 + j*(49) +-59 + j*(149) +13 + j*(44) +-18 + j*(52) +71 + j*(60) +81 + j*(-71) +-65 + j*(-76) +-45 + j*(76) +122 + j*(35) +91 + j*(-156) +-100 + j*(-170) +-175 + j*(-18) +-83 + j*(103) +70 + j*(66) +72 + j*(-126) +-162 + j*(-174) +-268 + j*(81) +-34 + j*(223) +95 + j*(27) +-81 + j*(-58) +-129 + j*(103) +-10 + j*(121) +-62 + j*(67) +-89 + j*(242) +182 + j*(332) +387 + j*(71) +248 + j*(-204) +-4 + j*(-214) +-124 + j*(-41) +-28 + j*(148) +207 + j*(115) +240 + j*(-131) +43 + j*(-199) +14 + j*(-80) +99 + j*(-156) +-59 + j*(-278) +-228 + j*(-122) +-134 + j*(25) +-71 + j*(-31) +-134 + j*(-13) +-91 + j*(50) +-78 + j*(2) +-161 + j*(66) +-52 + j*(206) +125 + j*(95) +28 + j*(-72) +-110 + j*(14) +-52 + j*(128) +25 + j*(127) +94 + j*(114) +146 + j*(-5) +-8 + j*(-91) +-98 + j*(117) +173 + j*(220) +301 + j*(-74) +52 + j*(-197) +16 + j*(-13) +180 + j*(-112) +-13 + j*(-313) +-245 + j*(-104) +-64 + j*(89) +49 + j*(-84) +-145 + j*(-141) +-194 + j*(45) +-72 + j*(105) +-32 + j*(76) +17 + j*(74) +37 + j*(-18) +-81 + j*(-42) +-104 + j*(80) +-23 + j*(100) +-51 + j*(107) +42 + j*(243) +305 + j*(128) +233 + j*(-210) +-93 + j*(-184) +-76 + j*(74) +112 + j*(35) +50 + j*(-95) +-22 + j*(-21) +63 + j*(-1) +66 + j*(-93) +1 + j*(-117) +-45 + j*(-119) +-119 + j*(-73) +-69 + j*(36) +47 + j*(-61) +-136 + j*(-212) +-364 + j*(19) +-169 + j*(305) +76 + j*(196) +14 + j*(92) +61 + j*(190) +235 + j*(61) +98 + j*(-155) +-96 + j*(-29) +35 + j*(119) +154 + j*(-23) +37 + j*(-140) +-79 + j*(-98) +-150 + j*(-16) +-151 + j*(161) +73 + j*(278) +285 + j*(93) +202 + j*(-139) +32 + j*(-159) +-49 + j*(-87) +-57 + j*(21) +84 + j*(85) +197 + j*(-92) +2 + j*(-245) +-152 + j*(-64) +23 + j*(43) +71 + j*(-156) +-158 + j*(-175) +-177 + j*(49) +2 + j*(60) +-1 + j*(-68) +-82 + j*(-66) +-103 + j*(-56) +-190 + j*(-33) +-222 + j*(119) +-102 + j*(221) +-3 + j*(219) +112 + j*(226) +266 + j*(72) +149 + j*(-171) +-91 + j*(-102) +-21 + j*(69) +61 + j*(-51) +-136 + j*(-63) +-110 + j*(204) +182 + j*(163) +125 + j*(-103) +-85 + j*(6) +95 + j*(177) +266 + j*(-32) +110 + j*(-194) +34 + j*(-147) +1 + j*(-245) +-282 + j*(-225) +-354 + j*(159) +15 + j*(309) +162 + j*(33) +-21 + j*(-33) +23 + j*(92) +115 + j*(-56) +-123 + j*(-117) +-177 + j*(212) +219 + j*(306) +383 + j*(-83) +90 + j*(-290) +-67 + j*(-128) +14 + j*(-94) +-74 + j*(-182) +-212 + j*(-44) +-86 + j*(112) +40 + j*(11) +-71 + j*(-66) +-117 + j*(74) +45 + j*(103) +53 + j*(-76) +-162 + j*(-62) +-153 + j*(212) +172 + j*(257) +296 + j*(-73) +11 + j*(-260) +-197 + j*(-38) +-28 + j*(155) +134 + j*(14) +11 + j*(-101) +-45 + j*(18) +98 + j*(8) +37 + j*(-184) +-190 + j*(-105) +-107 + j*(119) +73 + j*(1) +-116 + j*(-134) +-236 + j*(137) +83 + j*(258) +188 + j*(-74) +-141 + j*(-133) +-141 + j*(196) +178 + j*(144) +77 + j*(-153) +-197 + j*(-9) +-36 + j*(248) +184 + j*(119) +115 + j*(-14) +110 + j*(16) +146 + j*(-99) +-31 + j*(-158) +-87 + j*(29) +91 + j*(44) +52 + j*(-133) +-122 + j*(-55) +-30 + j*(98) +74 + j*(4) +-31 + j*(-33) +-4 + j*(100) +165 + j*(47) +131 + j*(-136) +-23 + j*(-144) +-62 + j*(-45) +-7 + j*(18) +103 + j*(-16) +102 + j*(-202) +-154 + j*(-264) +-269 + j*(8) +-14 + j*(118) +39 + j*(-144) +-268 + j*(-148) +-272 + j*(185) +19 + j*(200) +-1 + j*(0) +-125 + j*(96) +30 + j*(173) +55 + j*(-4) +-146 + j*(56) +-10 + j*(319) +322 + j*(182) +257 + j*(-162) +-13 + j*(-180) +-65 + j*(-35) +-40 + j*(-1) +-58 + j*(54) +21 + j*(128) +138 + j*(82) +168 + j*(-33) +116 + j*(-145) +-39 + j*(-184) +-156 + j*(-38) +-47 + j*(105) +68 + j*(25) +-13 + j*(-14) +35 + j*(111) +247 + j*(3) +142 + j*(-295) +-182 + j*(-240) +-173 + j*(28) +1 + j*(16) +-51 + j*(-80) +-89 + j*(-8) +-27 + j*(-38) +-166 + j*(-100) +-269 + j*(147) +30 + j*(319) +247 + j*(24) +-16 + j*(-187) +-190 + j*(47) +23 + j*(173) +90 + j*(-25) +-108 + j*(-33) +-93 + j*(188) +130 + j*(202) +206 + j*(45) +183 + j*(-49) +161 + j*(-170) +-33 + j*(-283) +-267 + j*(-117) +-189 + j*(159) +41 + j*(152) +41 + j*(3) +-54 + j*(52) +41 + j*(136) +129 + j*(34) +35 + j*(-28) +20 + j*(85) +183 + j*(83) +219 + j*(-107) +69 + j*(-186) +3 + j*(-112) +37 + j*(-106) +4 + j*(-153) +-51 + j*(-147) +-91 + j*(-144) +-175 + j*(-95) +-158 + j*(46) +-6 + j*(42) +-35 + j*(-116) +-227 + j*(-52) +-151 + j*(165) +64 + j*(83) +-52 + j*(-116) +-252 + j*(39) +-90 + j*(250) +103 + j*(104) +-49 + j*(-39) +-174 + j*(150) +37 + j*(317) +267 + j*(153) +196 + j*(-101) +-31 + j*(-114) +-81 + j*(76) +90 + j*(135) +138 + j*(-33) +-36 + j*(-49) +-8 + j*(163) +263 + j*(107) +215 + j*(-211) +-100 + j*(-178) +-57 + j*(99) +180 + j*(23) +81 + j*(-173) +-51 + j*(-57) +98 + j*(-8) +91 + j*(-219) +-158 + j*(-207) +-163 + j*(16) +-11 + j*(6) +-74 + j*(-83) +-141 + j*(24) +-35 + j*(77) +-21 + j*(10) +-57 + j*(75) +102 + j*(112) +183 + j*(-119) +-65 + j*(-275) +-282 + j*(-79) +-187 + j*(134) +-65 + j*(109) +-110 + j*(112) +-45 + j*(265) +230 + j*(242) +305 + j*(-80) +11 + j*(-239) +-171 + j*(6) +42 + j*(171) +181 + j*(-25) +2 + j*(-136) +-69 + j*(27) +86 + j*(60) +97 + j*(-74) +13 + j*(-67) +77 + j*(-61) +39 + j*(-223) +-218 + j*(-214) +-292 + j*(66) +-76 + j*(206) +69 + j*(94) +37 + j*(-4) +-6 + j*(-4) +2 + j*(16) +38 + j*(-16) +-6 + j*(-115) +-191 + j*(-93) +-235 + j*(159) +21 + j*(279) +175 + j*(70) +17 + j*(-56) +-59 + j*(85) +85 + j*(141) +148 + j*(23) +102 + j*(-33) +99 + j*(-64) +39 + j*(-146) +-107 + j*(-110) +-124 + j*(42) +-4 + j*(92) +40 + j*(16) +-25 + j*(-8) +-51 + j*(77) +54 + j*(139) +168 + j*(46) +113 + j*(-96) +-28 + j*(-76) +-30 + j*(47) +65 + j*(81) +136 + j*(57) +230 + j*(-17) +228 + j*(-216) +7 + j*(-314) +-117 + j*(-148) +7 + j*(-106) +-64 + j*(-285) +-361 + j*(-161) +-272 + j*(223) +129 + j*(195) +146 + j*(-167) +-153 + j*(-218) +-223 + j*(-16) +-141 + j*(37) +-156 + j*(42) +-127 + j*(127) +-32 + j*(117) +-32 + j*(57) +-54 + j*(74) +-26 + j*(62) +-93 + j*(35) +-158 + j*(176) +22 + j*(332) +271 + j*(197) +228 + j*(-80) +-19 + j*(-112) +-82 + j*(104) +122 + j*(197) +270 + j*(11) +146 + j*(-187) +-59 + j*(-143) +-78 + j*(24) +31 + j*(86) +126 + j*(44) +180 + j*(-72) +92 + j*(-243) +-170 + j*(-241) +-284 + j*(40) +-55 + j*(232) +149 + j*(73) +33 + j*(-94) +-103 + j*(19) +11 + j*(149) +144 + j*(65) +103 + j*(-41) +56 + j*(-19) +107 + j*(-18) +112 + j*(-110) +12 + j*(-151) +-49 + j*(-78) +7 + j*(-21) +65 + j*(-89) +-4 + j*(-190) +-156 + j*(-168) +-218 + j*(-20) +-136 + j*(106) +-19 + j*(116) +57 + j*(67) +105 + j*(-18) +68 + j*(-156) +-119 + j*(-213) +-281 + j*(-46) +-193 + j*(177) +11 + j*(179) +53 + j*(48) +-5 + j*(34) +45 + j*(67) +104 + j*(-28) +14 + j*(-131) +-103 + j*(-93) +-124 + j*(-23) +-140 + j*(9) +-147 + j*(88) +-59 + j*(136) +-20 + j*(49) +-163 + j*(47) +-187 + j*(293) +126 + j*(425) +369 + j*(152) +197 + j*(-113) +-4 + j*(-4) +114 + j*(127) +217 + j*(-8) +110 + j*(-86) +119 + j*(-16) +207 + j*(-158) +-29 + j*(-351) +-351 + j*(-115) +-214 + j*(274) +127 + j*(270) +202 + j*(71) +164 + j*(25) +209 + j*(-23) +180 + j*(-123) +125 + j*(-127) +163 + j*(-175) +66 + j*(-309) +-121 + j*(-241) +-70 + j*(-93) +13 + j*(-209) +-196 + j*(-296) +-332 + j*(-61) +-144 + j*(71) +-88 + j*(-83) +-279 + j*(-66) +-269 + j*(167) +-64 + j*(204) +-10 + j*(82) +-59 + j*(57) +-69 + j*(72) +-88 + j*(90) +-69 + j*(161) +24 + j*(179) +76 + j*(122) +96 + j*(81) +103 + j*(7) +4 + j*(-44) +-62 + j*(68) +54 + j*(134) +95 + j*(29) +12 + j*(61) +164 + j*(158) +338 + j*(-107) +28 + j*(-395) +-340 + j*(-124) +-163 + j*(250) +137 + j*(159) +92 + j*(-22) +24 + j*(29) +103 + j*(35) +98 + j*(-47) +66 + j*(-48) +89 + j*(-93) +-3 + j*(-174) +-129 + j*(-92) +-98 + j*(28) +-38 + j*(42) +-7 + j*(63) +78 + j*(34) +50 + j*(-86) +-81 + j*(-46) +-16 + j*(85) +103 + j*(-8) +-16 + j*(-98) +-54 + j*(54) +149 + j*(39) +102 + j*(-221) +-192 + j*(-181) +-167 + j*(105) +78 + j*(81) +42 + j*(-127) +-145 + j*(-88) +-132 + j*(79) +8 + j*(108) +81 + j*(4) +7 + j*(-110) +-141 + j*(-67) +-123 + j*(97) +32 + j*(84) +-13 + j*(-54) +-156 + j*(39) +-35 + j*(213) +158 + j*(103) +86 + j*(-72) +-36 + j*(-31) +-8 + j*(33) +12 + j*(3) +-18 + j*(3) +-26 + j*(21) +-40 + j*(49) +-1 + j*(110) +91 + j*(77) +57 + j*(-6) +1 + j*(72) +150 + j*(144) +295 + j*(-41) +176 + j*(-265) +-59 + j*(-291) +-229 + j*(-135) +-201 + j*(130) +114 + j*(213) +281 + j*(-125) +-55 + j*(-348) +-282 + j*(-45) +-9 + j*(112) +31 + j*(-186) +-354 + j*(-137) +-294 + j*(325) +173 + j*(303) +168 + j*(-91) +-138 + j*(-62) +-81 + j*(177) +95 + j*(133) +79 + j*(59) +144 + j*(83) +242 + j*(-95) +37 + j*(-299) +-247 + j*(-161) +-223 + j*(132) +5 + j*(216) +146 + j*(88) +110 + j*(-48) +15 + j*(-57) +13 + j*(1) +62 + j*(-21) +42 + j*(-80) +-10 + j*(-93) +-57 + j*(-95) +-132 + j*(-48) +-117 + j*(71) +-4 + j*(81) +-21 + j*(-1) +-98 + j*(76) +10 + j*(199) +175 + j*(142) +238 + j*(12) +245 + j*(-152) +62 + j*(-344) +-260 + j*(-221) +-199 + j*(131) +117 + j*(80) +23 + j*(-192) +-208 + j*(-39) +-1 + j*(132) +88 + j*(-134) +-250 + j*(-153) +-228 + j*(236) +160 + j*(183) +52 + j*(-163) +-254 + j*(30) +9 + j*(329) +326 + j*(51) +100 + j*(-272) +-187 + j*(-156) +-197 + j*(35) +-144 + j*(139) +-6 + j*(221) +158 + j*(98) +41 + j*(-88) +-153 + j*(50) +-9 + j*(281) +256 + j*(204) +310 + j*(-22) +224 + j*(-184) +53 + j*(-279) +-167 + j*(-194) +-196 + j*(51) +-12 + j*(165) +132 + j*(88) +176 + j*(-17) +170 + j*(-149) +28 + j*(-263) +-156 + j*(-184) +-144 + j*(-11) +-22 + j*(-8) +-47 + j*(-112) +-171 + j*(-77) +-164 + j*(60) +-51 + j*(81) +-47 + j*(-8) +-152 + j*(21) +-140 + j*(176) +28 + j*(229) +139 + j*(130) +151 + j*(42) +165 + j*(-37) +103 + j*(-161) +-70 + j*(-179) +-158 + j*(-38) +-97 + j*(66) +-30 + j*(76) +13 + j*(75) +59 + j*(37) +47 + j*(-21) +20 + j*(-23) +34 + j*(-53) +-50 + j*(-124) +-206 + j*(-18) +-139 + j*(218) +118 + j*(235) +202 + j*(41) +112 + j*(-37) +115 + j*(-7) +166 + j*(-97) +34 + j*(-267) +-239 + j*(-119) +-108 + j*(65) +-68 + j*(-85) +-296 + j*(1) +-157 + j*(327) +224 + j*(201) +135 + j*(-182) +-231 + j*(-141) +-275 + j*(192) +-20 + j*(354) +240 + j*(245) +291 + j*(-37) +54 + j*(-195) +-135 + j*(-11) +25 + j*(170) +205 + j*(23) +100 + j*(-162) +-71 + j*(-133) +-131 + j*(-20) +-115 + j*(113) +40 + j*(216) +250 + j*(104) +235 + j*(-154) +15 + j*(-248) +-147 + j*(-132) +-148 + j*(35) +-17 + j*(121) +110 + j*(30) +44 + j*(-112) +-106 + j*(-56) +-55 + j*(97) +101 + j*(49) +62 + j*(-112) +-109 + j*(-88) +-120 + j*(91) +51 + j*(150) +152 + j*(11) +57 + j*(-103) +-35 + j*(-41) +23 + j*(16) +52 + j*(-61) +-41 + j*(-70) +-28 + j*(37) +96 + j*(8) +76 + j*(-127) +-33 + j*(-134) +-47 + j*(-99) +-90 + j*(-128) +-177 + j*(-52) +-112 + j*(59) +-25 + j*(-8) +-124 + j*(-69) +-187 + j*(62) +-61 + j*(129) +-21 + j*(21) +-146 + j*(18) +-155 + j*(183) +16 + j*(247) +124 + j*(129) +52 + j*(31) +-17 + j*(124) +143 + j*(221) +337 + j*(25) +185 + j*(-251) +-93 + j*(-180) +-52 + j*(13) +37 + j*(-83) +-168 + j*(-117) +-214 + j*(187) +127 + j*(282) +261 + j*(-25) +44 + j*(-146) +-10 + j*(-31) +24 + j*(-95) +-183 + j*(-95) +-222 + j*(240) +168 + j*(390) +433 + j*(71) +298 + j*(-221) +113 + j*(-276) +-38 + j*(-285) +-211 + j*(-148) +-129 + j*(102) +140 + j*(42) +71 + j*(-243) +-246 + j*(-169) +-197 + j*(172) +141 + j*(163) +176 + j*(-131) +-39 + j*(-188) +-71 + j*(-68) +-6 + j*(-113) +-122 + j*(-194) +-250 + j*(-72) +-182 + j*(49) +-130 + j*(2) +-233 + j*(1) +-279 + j*(167) +-152 + j*(306) +4 + j*(311) +115 + j*(258) +196 + j*(161) +183 + j*(35) +96 + j*(2) +91 + j*(52) +163 + j*(17) +135 + j*(-98) +13 + j*(-98) +6 + j*(10) +126 + j*(-1) +124 + j*(-168) +-72 + j*(-218) +-180 + j*(-43) +-50 + j*(76) +38 + j*(-34) +-102 + j*(-103) +-193 + j*(77) +-8 + j*(222) +180 + j*(76) +91 + j*(-114) +-70 + j*(-62) +-25 + j*(64) +83 + j*(8) +17 + j*(-104) +-108 + j*(-43) +-68 + j*(95) +66 + j*(85) +87 + j*(-28) +7 + j*(-65) +-32 + j*(-13) +8 + j*(21) +50 + j*(-14) +21 + j*(-77) +-58 + j*(-66) +-64 + j*(24) +18 + j*(32) +10 + j*(-45) +-84 + j*(0) +-7 + j*(138) +182 + j*(66) +154 + j*(-149) +-35 + j*(-161) +-43 + j*(-35) +47 + j*(-86) +-53 + j*(-212) +-228 + j*(-121) +-199 + j*(75) +-38 + j*(105) +-4 + j*(0) +-91 + j*(-20) +-118 + j*(69) +-45 + j*(129) +31 + j*(110) +70 + j*(59) +72 + j*(-11) +1 + j*(-50) +-55 + j*(21) +40 + j*(91) +129 + j*(-38) +-18 + j*(-161) +-184 + j*(-22) +-86 + j*(154) +49 + j*(109) +23 + j*(70) +81 + j*(145) +249 + j*(54) +211 + j*(-182) +-6 + j*(-238) +-119 + j*(-112) +-94 + j*(-16) +-45 + j*(4) +-40 + j*(-24) +-111 + j*(-7) +-115 + j*(140) +83 + j*(215) +242 + j*(36) +144 + j*(-174) +-55 + j*(-186) +-177 + j*(-56) +-151 + j*(151) +97 + j*(248) +300 + j*(8) +105 + j*(-250) +-141 + j*(-107) +-28 + j*(91) +112 + j*(-6) +44 + j*(-77) +77 + j*(-43) +118 + j*(-206) +-136 + j*(-317) +-323 + j*(-78) +-179 + j*(105) +-104 + j*(43) +-173 + j*(98) +-71 + j*(229) +88 + j*(177) +116 + j*(83) +140 + j*(18) +84 + j*(-103) +-86 + j*(-54) +-16 + j*(139) +209 + j*(42) +120 + j*(-204) +-91 + j*(-161) +-88 + j*(-69) +-161 + j*(-97) +-286 + j*(111) +-36 + j*(347) +242 + j*(135) +69 + j*(-81) +-37 + j*(124) +262 + j*(174) +354 + j*(-204) +2 + j*(-390) +-237 + j*(-170) +-171 + j*(34) +-58 + j*(66) +-5 + j*(24) +-40 + j*(-21) +-98 + j*(57) +17 + j*(168) +192 + j*(62) +145 + j*(-131) +6 + j*(-157) +-46 + j*(-134) +-132 + j*(-122) +-197 + j*(14) +-73 + j*(123) +19 + j*(25) +-85 + j*(-29) +-125 + j*(93) +-18 + j*(140) +16 + j*(88) +4 + j*(108) +71 + j*(125) +114 + j*(65) +103 + j*(39) +145 + j*(17) +142 + j*(-93) +8 + j*(-139) +-78 + j*(-27) +-11 + j*(73) +76 + j*(73) +147 + j*(40) +218 + j*(-68) +157 + j*(-252) +-81 + j*(-305) +-247 + j*(-103) +-129 + j*(117) +89 + j*(69) +76 + j*(-133) +-103 + j*(-138) +-116 + j*(15) +-3 + j*(2) +-71 + j*(-87) +-168 + j*(54) +42 + j*(187) +231 + j*(-71) +-33 + j*(-334) +-361 + j*(-124) +-255 + j*(204) +-13 + j*(185) +-21 + j*(64) +-66 + j*(123) +37 + j*(165) +95 + j*(77) +58 + j*(33) +67 + j*(37) +74 + j*(-26) +-30 + j*(-59) +-108 + j*(63) +1 + j*(209) +211 + j*(170) +277 + j*(-49) +127 + j*(-202) +-37 + j*(-149) +-49 + j*(-40) +-4 + j*(-18) +2 + j*(-22) +18 + j*(-16) +25 + j*(-37) +17 + j*(-31) +79 + j*(-47) +69 + j*(-206) +-183 + j*(-267) +-346 + j*(2) +-140 + j*(216) +21 + j*(79) +-124 + j*(21) +-123 + j*(237) +144 + j*(259) +203 + j*(23) +47 + j*(-21) +65 + j*(90) +180 + j*(37) +152 + j*(-79) +76 + j*(-94) +55 + j*(-66) +95 + j*(-49) +170 + j*(-146) +53 + j*(-356) +-285 + j*(-315) +-371 + j*(47) +-97 + j*(212) +49 + j*(59) +-17 + j*(-6) +-7 + j*(9) +-35 + j*(-49) +-129 + j*(38) +21 + j*(176) +208 + j*(-23) +5 + j*(-260) +-254 + j*(-107) +-191 + j*(100) +-117 + j*(107) +-118 + j*(190) +64 + j*(272) +217 + j*(83) +73 + j*(-70) +-32 + j*(52) +101 + j*(117) +176 + j*(-16) +87 + j*(-118) +-18 + j*(-108) +-82 + j*(-35) +-58 + j*(65) +35 + j*(84) +73 + j*(41) +102 + j*(31) +163 + j*(-49) +85 + j*(-190) +-89 + j*(-156) +-95 + j*(-13) +-11 + j*(-6) +-22 + j*(-48) +-49 + j*(-43) +-93 + j*(-39) +-145 + j*(78) +29 + j*(209) +235 + j*(17) +60 + j*(-231) +-168 + j*(-93) +-69 + j*(47) +-81 + j*(-54) +-246 + j*(132) +73 + j*(419) +487 + j*(60) +174 + j*(-421) +-269 + j*(-190) +-85 + j*(129) +81 + j*(-65) +-154 + j*(-115) +-136 + j*(141) +96 + j*(64) +-59 + j*(-118) +-215 + j*(124) +84 + j*(286) +255 + j*(-15) +-16 + j*(-170) +-146 + j*(68) +57 + j*(194) +195 + j*(58) +163 + j*(-68) +100 + j*(-120) +36 + j*(-140) +-8 + j*(-136) +-66 + j*(-155) +-198 + j*(-103) +-226 + j*(107) +-17 + j*(230) +150 + j*(91) +87 + j*(-49) +8 + j*(-22) +44 + j*(16) +93 + j*(-31) +83 + j*(-126) +-42 + j*(-206) +-228 + j*(-101) +-180 + j*(163) +112 + j*(176) +170 + j*(-102) +-66 + j*(-179) +-119 + j*(-8) +2 + j*(-32) +-122 + j*(-159) +-315 + j*(13) +-185 + j*(263) +39 + j*(226) +61 + j*(107) +42 + j*(103) +80 + j*(82) +66 + j*(42) +73 + j*(47) +92 + j*(-11) +-8 + j*(-42) +-36 + j*(92) +136 + j*(116) +161 + j*(-85) +-52 + j*(-107) +-78 + j*(107) +115 + j*(158) +198 + j*(37) +206 + j*(-30) +233 + j*(-147) +105 + j*(-296) +-91 + j*(-243) +-107 + j*(-116) +-93 + j*(-111) +-156 + j*(-58) +-100 + j*(51) +-8 + j*(5) +-76 + j*(-36) +-76 + j*(80) +89 + j*(67) +88 + j*(-130) +-109 + j*(-154) +-163 + j*(4) +-71 + j*(72) +-11 + j*(50) +28 + j*(6) +4 + j*(-98) +-163 + j*(-115) +-266 + j*(84) +-107 + j*(284) +148 + j*(235) +229 + j*(-1) +65 + j*(-182) +-173 + j*(-113) +-206 + j*(139) +15 + j*(269) +215 + j*(127) +177 + j*(-83) +16 + j*(-129) +-66 + j*(-47) +-53 + j*(12) +-54 + j*(39) +-33 + j*(121) +116 + j*(142) +199 + j*(-38) +25 + j*(-173) +-127 + j*(-29) +-23 + j*(112) +71 + j*(55) +71 + j*(41) +174 + j*(1) +127 + j*(-229) +-209 + j*(-211) +-235 + j*(178) +154 + j*(242) +226 + j*(-96) +-25 + j*(-138) +-1 + j*(19) +86 + j*(-87) +-87 + j*(-129) +-107 + j*(76) +92 + j*(91) +117 + j*(-59) +75 + j*(-100) +46 + j*(-206) +-205 + j*(-226) +-292 + j*(119) +88 + j*(243) +202 + j*(-139) +-165 + j*(-208) +-170 + j*(136) +146 + j*(70) +25 + j*(-223) +-239 + j*(-89) +-125 + j*(107) +-38 + j*(11) +-151 + j*(28) +-81 + j*(168) +54 + j*(91) +-25 + j*(-14) +-119 + j*(71) +-67 + j*(187) +62 + j*(231) +211 + j*(141) +182 + j*(-53) +4 + j*(-33) +92 + j*(132) +301 + j*(-38) +110 + j*(-316) +-187 + j*(-183) +-132 + j*(46) +-33 + j*(34) +-54 + j*(67) +66 + j*(127) +159 + j*(-26) +22 + j*(-117) +-34 + j*(-18) +18 + j*(-16) +-23 + j*(-11) +64 + j*(69) +196 + j*(-114) +-57 + j*(-320) +-330 + j*(-72) +-152 + j*(192) +-2 + j*(98) +-83 + j*(132) +121 + j*(293) +404 + j*(18) +167 + j*(-352) +-204 + j*(-215) +-169 + j*(91) +43 + j*(148) +187 + j*(39) +197 + j*(-179) +-52 + j*(-305) +-244 + j*(-71) +-23 + j*(115) +124 + j*(-132) +-166 + j*(-276) +-333 + j*(7) +-122 + j*(169) +-35 + j*(35) +-150 + j*(45) +-89 + j*(186) +71 + j*(132) +36 + j*(-23) +-124 + j*(-6) +-153 + j*(177) +23 + j*(295) +215 + j*(187) +194 + j*(6) +92 + j*(1) +140 + j*(35) +164 + j*(-89) +0 + j*(-136) +-56 + j*(47) +154 + j*(107) +251 + j*(-138) +10 + j*(-301) +-205 + j*(-109) +-66 + j*(111) +130 + j*(-16) +-21 + j*(-204) +-230 + j*(-14) +-6 + j*(218) +248 + j*(-33) +-30 + j*(-313) +-336 + j*(-28) +-74 + j*(287) +214 + j*(66) +23 + j*(-171) +-169 + j*(6) +-18 + j*(186) +165 + j*(110) +215 + j*(-51) +141 + j*(-221) +-84 + j*(-267) +-209 + j*(-71) +-64 + j*(42) +-12 + j*(-101) +-207 + j*(-122) +-271 + j*(94) +-121 + j*(217) +-10 + j*(194) +59 + j*(175) +134 + j*(99) +99 + j*(0) +27 + j*(18) +67 + j*(83) +180 + j*(54) +252 + j*(-110) +118 + j*(-344) +-245 + j*(-345) +-413 + j*(30) +-139 + j*(291) +91 + j*(139) +-4 + j*(32) +15 + j*(153) +206 + j*(59) +92 + j*(-194) +-200 + j*(-92) +-145 + j*(218) +156 + j*(247) +284 + j*(16) +176 + j*(-186) +-37 + j*(-201) +-136 + j*(-23) +21 + j*(102) +150 + j*(-71) +-67 + j*(-228) +-292 + j*(19) +-73 + j*(336) +310 + j*(216) +332 + j*(-157) +56 + j*(-287) +-94 + j*(-136) +-10 + j*(-37) +43 + j*(-132) +-78 + j*(-206) +-198 + j*(-115) +-190 + j*(-6) +-173 + j*(41) +-153 + j*(139) +8 + j*(206) +163 + j*(44) +36 + j*(-164) +-196 + j*(-98) +-203 + j*(114) +-78 + j*(181) +-26 + j*(182) +62 + j*(232) +237 + j*(156) +251 + j*(-74) +62 + j*(-168) +-41 + j*(-62) +3 + j*(-13) +-21 + j*(-46) +-76 + j*(36) +42 + j*(139) +205 + j*(18) +135 + j*(-199) +-91 + j*(-214) +-186 + j*(-43) +-100 + j*(76) +-15 + j*(37) +-72 + j*(-13) +-146 + j*(102) +-11 + j*(252) +202 + j*(170) +194 + j*(-18) +103 + j*(-23) +181 + j*(-23) +166 + j*(-228) +-115 + j*(-272) +-225 + j*(10) +1 + j*(140) +100 + j*(-16) +-1 + j*(-50) +47 + j*(25) +138 + j*(-90) +16 + j*(-223) +-127 + j*(-161) +-138 + j*(-84) +-164 + j*(-64) +-204 + j*(10) +-188 + j*(89) +-175 + j*(176) +-53 + j*(317) +230 + j*(272) +305 + j*(-43) +55 + j*(-187) +-64 + j*(-13) +90 + j*(30) +88 + j*(-156) +-129 + j*(-174) +-196 + j*(16) +-98 + j*(94) +-83 + j*(88) +-60 + j*(185) +122 + j*(215) +223 + j*(18) +56 + j*(-102) +-25 + j*(59) +197 + j*(101) +256 + j*(-204) +-93 + j*(-337) +-296 + j*(-22) +-63 + j*(194) +100 + j*(45) +-1 + j*(-23) +26 + j*(77) +159 + j*(-20) +41 + j*(-190) +-141 + j*(-94) +-85 + j*(64) +17 + j*(31) +-13 + j*(-13) +-18 + j*(30) +35 + j*(13) +6 + j*(-37) +-47 + j*(8) +11 + j*(77) +110 + j*(32) +112 + j*(-88) +20 + j*(-143) +-46 + j*(-119) +-78 + j*(-110) +-158 + j*(-88) +-196 + j*(45) +-78 + j*(132) +3 + j*(45) +-91 + j*(6) +-100 + j*(129) +20 + j*(136) +-5 + j*(57) +-52 + j*(176) +173 + j*(255) +332 + j*(-16) +96 + j*(-234) +-121 + j*(-66) +-5 + j*(100) +100 + j*(18) +38 + j*(-21) +70 + j*(42) +169 + j*(-37) +86 + j*(-180) +-71 + j*(-134) +-54 + j*(-3) +48 + j*(-19) +24 + j*(-111) +-67 + j*(-94) +-61 + j*(-22) +-18 + j*(-33) +-43 + j*(-50) +-28 + j*(-21) +10 + j*(-98) +-150 + j*(-191) +-346 + j*(9) +-187 + j*(305) +134 + j*(229) +122 + j*(-38) +-75 + j*(-45) +-81 + j*(108) +35 + j*(128) +87 + j*(60) +73 + j*(-12) +-1 + j*(-37) +-43 + j*(38) +37 + j*(85) +69 + j*(6) +-5 + j*(9) +47 + j*(98) +168 + j*(11) +84 + j*(-131) +-36 + j*(-69) +14 + j*(-11) +0 + j*(-80) +-106 + j*(-10) +-7 + j*(136) +168 + j*(38) +94 + j*(-140) +-55 + j*(-88) +1 + j*(16) +88 + j*(-73) +-23 + j*(-194) +-198 + j*(-105) +-177 + j*(92) +-8 + j*(129) +30 + j*(16) +-53 + j*(25) +8 + j*(119) +132 + j*(45) +78 + j*(-69) +28 + j*(-37) +82 + j*(-84) +-40 + j*(-209) +-239 + j*(-71) +-139 + j*(154) +50 + j*(103) +24 + j*(-12) +-9 + j*(5) +-3 + j*(-36) +-116 + j*(-28) +-100 + j*(141) +89 + j*(119) +43 + j*(-52) +-103 + j*(43) +37 + j*(163) +112 + j*(13) +-36 + j*(25) +91 + j*(203) +330 + j*(-5) +105 + j*(-291) +-171 + j*(-92) +3 + j*(132) +169 + j*(-21) +66 + j*(-124) +59 + j*(-92) +61 + j*(-216) +-166 + j*(-260) +-288 + j*(-28) +-144 + j*(124) +-42 + j*(82) +-34 + j*(65) +1 + j*(53) +-16 + j*(18) +-38 + j*(60) +28 + j*(83) +56 + j*(20) +27 + j*(11) +66 + j*(15) +75 + j*(-78) +-39 + j*(-118) +-107 + j*(-30) +-64 + j*(39) +-19 + j*(25) +-37 + j*(-17) +-118 + j*(4) +-134 + j*(147) +31 + j*(228) +143 + j*(97) +49 + j*(32) +76 + j*(151) +277 + j*(72) +225 + j*(-197) +-33 + j*(-203) +-60 + j*(-19) +44 + j*(-20) +-1 + j*(-74) +-28 + j*(-5) +49 + j*(11) +67 + j*(-62) +25 + j*(-95) +-18 + j*(-107) +-86 + j*(-66) +-52 + j*(37) +77 + j*(2) +51 + j*(-151) +-102 + j*(-160) +-155 + j*(-52) +-123 + j*(10) +-77 + j*(35) +-37 + j*(-19) +-151 + j*(-78) +-279 + j*(107) +-80 + j*(320) +166 + j*(162) +40 + j*(-37) +-87 + j*(115) +116 + j*(214) +234 + j*(-7) +59 + j*(-147) +-79 + j*(-52) +-74 + j*(62) +0 + j*(154) +177 + j*(139) +238 + j*(-76) +45 + j*(-194) +-65 + j*(-65) +10 + j*(-18) +-23 + j*(-69) +-79 + j*(30) +66 + j*(104) +166 + j*(-57) +38 + j*(-192) +-109 + j*(-149) +-170 + j*(-40) +-140 + j*(96) +20 + j*(132) +81 + j*(-31) +-105 + j*(-83) +-165 + j*(148) +92 + j*(245) +236 + j*(13) +61 + j*(-146) +-80 + j*(-19) +27 + j*(107) +159 + j*(11) +81 + j*(-136) +-73 + j*(-70) +13 + j*(98) +228 + j*(-10) +141 + j*(-288) +-147 + j*(-269) +-175 + j*(-65) +-96 + j*(-78) +-225 + j*(-78) +-224 + j*(160) +59 + j*(181) +83 + j*(-113) +-226 + j*(-141) +-305 + j*(163) +-93 + j*(317) +67 + j*(287) +216 + j*(245) +365 + j*(32) +216 + j*(-264) +-116 + j*(-228) +-151 + j*(48) +54 + j*(88) +63 + j*(-82) +-107 + j*(-66) +-95 + j*(116) +88 + j*(127) +116 + j*(-40) +-36 + j*(-79) +-89 + j*(66) +40 + j*(155) +170 + j*(84) +196 + j*(-43) +141 + j*(-147) +37 + j*(-197) +-66 + j*(-172) +-134 + j*(-96) +-136 + j*(9) +-40 + j*(70) +35 + j*(-16) +-76 + j*(-89) +-170 + j*(64) +11 + j*(190) +152 + j*(13) +-12 + j*(-109) +-90 + j*(52) +77 + j*(80) +54 + j*(-91) +-123 + j*(-16) +-5 + j*(180) +223 + j*(46) +123 + j*(-204) +-119 + j*(-177) +-174 + j*(16) +-52 + j*(139) +118 + j*(87) +125 + j*(-110) +-74 + j*(-159) +-132 + j*(8) +-10 + j*(21) +-101 + j*(-79) +-238 + j*(122) +15 + j*(330) +260 + j*(115) +121 + j*(-69) +85 + j*(38) +250 + j*(-74) +77 + j*(-341) +-238 + j*(-199) +-146 + j*(61) +8 + j*(-41) +-161 + j*(-130) +-271 + j*(75) +-132 + j*(226) +-8 + j*(225) +101 + j*(228) +247 + j*(119) +230 + j*(-91) +74 + j*(-165) +-19 + j*(-128) +-75 + j*(-95) +-127 + j*(-25) +-117 + j*(65) +-79 + j*(142) +49 + j*(235) +298 + j*(139) +308 + j*(-222) +-73 + j*(-368) +-323 + j*(-56) +-135 + j*(231) +115 + j*(166) +129 + j*(3) +47 + j*(-31) +39 + j*(25) +129 + j*(23) +165 + j*(-124) +3 + j*(-222) +-131 + j*(-92) +-35 + j*(14) +15 + j*(-88) +-119 + j*(-105) +-146 + j*(41) +-48 + j*(86) +-21 + j*(86) +78 + j*(122) +211 + j*(-35) +49 + j*(-244) +-173 + j*(-111) +-52 + j*(62) +48 + j*(-91) +-158 + j*(-151) +-210 + j*(82) +1 + j*(119) +-11 + j*(-60) +-188 + j*(6) +-103 + j*(201) +93 + j*(146) +90 + j*(-23) +-31 + j*(-64) +-115 + j*(-6) +-129 + j*(91) +-73 + j*(156) +-34 + j*(175) +8 + j*(250) +199 + j*(287) +373 + j*(81) +259 + j*(-160) +71 + j*(-150) +55 + j*(-83) +28 + j*(-115) +-59 + j*(-50) +13 + j*(64) +136 + j*(-8) +74 + j*(-134) +-45 + j*(-95) +-34 + j*(8) +62 + j*(33) +138 + j*(-57) +73 + j*(-204) +-126 + j*(-192) +-165 + j*(19) +34 + j*(80) +88 + j*(-112) +-105 + j*(-161) +-154 + j*(27) +13 + j*(75) +53 + j*(-72) +-76 + j*(-108) +-110 + j*(0) +-18 + j*(25) +4 + j*(-70) +-103 + j*(-115) +-195 + j*(-31) +-182 + j*(82) +-122 + j*(148) +-19 + j*(197) +145 + j*(121) +130 + j*(-141) +-204 + j*(-209) +-380 + j*(159) +-49 + j*(431) +254 + j*(199) +109 + j*(-46) +-40 + j*(69) +76 + j*(146) +103 + j*(42) +23 + j*(88) +150 + j*(185) +306 + j*(30) +202 + j*(-156) +64 + j*(-117) +97 + j*(-59) +127 + j*(-127) +59 + j*(-185) +-7 + j*(-177) +-52 + j*(-165) +-100 + j*(-148) +-152 + j*(-111) +-204 + j*(-42) +-206 + j*(82) +-100 + j*(183) +35 + j*(167) +95 + j*(85) +105 + j*(21) +103 + j*(-40) +58 + j*(-119) +-71 + j*(-144) +-182 + j*(-22) +-114 + j*(151) +64 + j*(158) +118 + j*(35) +75 + j*(-1) +117 + j*(-11) +117 + j*(-136) +-44 + j*(-187) +-122 + j*(-53) +-40 + j*(-3) +-56 + j*(-62) +-124 + j*(5) +-46 + j*(85) +11 + j*(18) +-49 + j*(7) +-18 + j*(71) +37 + j*(21) +-21 + j*(4) +23 + j*(83) +139 + j*(-21) +6 + j*(-177) +-162 + j*(-49) +-58 + j*(91) +13 + j*(4) +-66 + j*(15) +26 + j*(85) +84 + j*(-81) +-144 + j*(-136) +-197 + j*(111) +9 + j*(126) +-88 + j*(-19) +-234 + j*(235) +132 + j*(465) +454 + j*(116) +223 + j*(-209) +18 + j*(-98) +71 + j*(-66) +-54 + j*(-120) +-129 + j*(120) +187 + j*(238) +367 + j*(-93) +122 + j*(-313) +-61 + j*(-222) +-101 + j*(-175) +-223 + j*(-97) +-185 + j*(135) +59 + j*(154) +94 + j*(-38) +-36 + j*(-45) +-3 + j*(41) +57 + j*(-8) +19 + j*(-36) +42 + j*(-23) +47 + j*(-97) +-47 + j*(-107) +-39 + j*(-42) +-11 + j*(-113) +-172 + j*(-134) +-220 + j*(83) +5 + j*(147) +57 + j*(-65) +-144 + j*(-103) +-192 + j*(58) +-134 + j*(111) +-146 + j*(188) +15 + j*(324) +254 + j*(173) +148 + j*(-80) +-52 + j*(23) +94 + j*(183) +257 + j*(17) +134 + j*(-141) +34 + j*(-82) +66 + j*(-64) +51 + j*(-109) +25 + j*(-139) +-74 + j*(-213) +-311 + j*(-86) +-231 + j*(309) +259 + j*(319) +364 + j*(-181) +-62 + j*(-348) +-226 + j*(-56) +-77 + j*(29) +-122 + j*(-21) +-134 + j*(138) +69 + j*(139) +33 + j*(-44) +-113 + j*(81) +110 + j*(214) +250 + j*(-69) +-32 + j*(-199) +-103 + j*(50) +117 + j*(23) +-11 + j*(-203) +-255 + j*(-18) +-77 + j*(229) +121 + j*(95) +27 + j*(-4) +33 + j*(86) +142 + j*(11) +57 + j*(-103) +-25 + j*(-51) +-18 + j*(-39) +-105 + j*(-1) +-42 + j*(191) +243 + j*(138) +227 + j*(-188) +-71 + j*(-205) +-73 + j*(17) +75 + j*(-42) +-54 + j*(-156) +-165 + j*(5) +-11 + j*(103) +47 + j*(-25) +-75 + j*(-35) +-68 + j*(111) +99 + j*(136) +199 + j*(-17) +103 + j*(-174) +-64 + j*(-142) +-41 + j*(-4) +87 + j*(-76) +-41 + j*(-238) +-248 + j*(-98) +-129 + j*(101) +1 + j*(-13) +-146 + j*(-62) +-127 + j*(126) +78 + j*(33) +-100 + j*(-194) +-372 + j*(47) +-139 + j*(343) +95 + j*(155) +-95 + j*(54) +-81 + j*(323) +264 + j*(278) +234 + j*(-66) +-50 + j*(-19) +48 + j*(223) +284 + j*(112) +224 + j*(-91) +134 + j*(-91) +138 + j*(-142) +-8 + j*(-211) +-136 + j*(-45) +19 + j*(98) +153 + j*(-49) +11 + j*(-176) +-105 + j*(-61) +-22 + j*(21) +2 + j*(-51) +-99 + j*(-24) +-56 + j*(127) +128 + j*(113) +160 + j*(-46) +81 + j*(-84) +115 + j*(-97) +65 + j*(-268) +-238 + j*(-262) +-328 + j*(115) +54 + j*(303) +318 + j*(-23) +104 + j*(-321) +-145 + j*(-260) +-211 + j*(-163) +-313 + j*(-78) +-312 + j*(160) +-65 + j*(249) +25 + j*(66) +-114 + j*(55) +-45 + j*(205) +119 + j*(95) +-11 + j*(-44) +-98 + j*(122) +107 + j*(158) +88 + j*(-76) +-170 + j*(13) +-18 + j*(310) +313 + j*(129) +136 + j*(-189) +-126 + j*(-7) +83 + j*(190) +230 + j*(-31) +31 + j*(-122) +38 + j*(31) +165 + j*(-95) +-62 + j*(-211) +-161 + j*(81) +185 + j*(142) +208 + j*(-250) +-206 + j*(-253) +-192 + j*(141) +153 + j*(92) +63 + j*(-202) +-186 + j*(-95) +-95 + j*(91) +0 + j*(26) +-43 + j*(40) +65 + j*(83) +115 + j*(-91) +-76 + j*(-152) +-131 + j*(6) +-35 + j*(12) +-111 + j*(-40) +-175 + j*(98) +-62 + j*(197) +20 + j*(194) +148 + j*(226) +348 + j*(36) +168 + j*(-298) +-222 + j*(-152) +-85 + j*(243) +297 + j*(108) +188 + j*(-240) +-70 + j*(-167) +7 + j*(-41) +28 + j*(-183) +-185 + j*(-180) +-223 + j*(41) +-71 + j*(119) +10 + j*(57) +11 + j*(-16) +-75 + j*(-59) +-168 + j*(67) +-23 + j*(224) +180 + j*(88) +67 + j*(-110) +-99 + j*(-6) +11 + j*(132) +138 + j*(37) +91 + j*(-74) +19 + j*(-91) +-42 + j*(-75) +-66 + j*(5) +25 + j*(30) +19 + j*(-80) +-114 + j*(-31) +-13 + j*(120) +162 + j*(-45) +-66 + j*(-266) +-356 + j*(-14) +-152 + j*(330) +183 + j*(220) +167 + j*(-35) +26 + j*(-68) +-13 + j*(-28) +-38 + j*(4) +-9 + j*(59) +47 + j*(23) +-9 + j*(-20) +-32 + j*(76) +98 + j*(88) +107 + j*(-59) +-37 + j*(-49) +12 + j*(94) +174 + j*(8) +88 + j*(-179) +-100 + j*(-131) +-91 + j*(10) +-30 + j*(9) +-70 + j*(28) +-10 + j*(131) +158 + j*(77) +141 + j*(-124) +-57 + j*(-151) +-112 + j*(18) +19 + j*(88) +95 + j*(-1) +59 + j*(-68) +23 + j*(-81) +-15 + j*(-88) +-47 + j*(-52) +-13 + j*(-25) +2 + j*(-80) +-78 + j*(-100) +-107 + j*(-23) +-51 + j*(-14) +-87 + j*(-75) +-187 + j*(-18) +-170 + j*(98) +-112 + j*(129) +-97 + j*(177) +15 + j*(250) +170 + j*(165) +148 + j*(12) +64 + j*(20) +124 + j*(47) +161 + j*(-74) +35 + j*(-153) +-64 + j*(-81) +-49 + j*(-13) +-33 + j*(-3) +-28 + j*(11) +-21 + j*(12) +-44 + j*(30) +-15 + j*(107) +117 + j*(91) +134 + j*(-70) +-36 + j*(-107) +-75 + j*(66) +117 + j*(116) +204 + j*(-89) +24 + j*(-230) +-148 + j*(-127) +-139 + j*(30) +-41 + j*(98) +69 + j*(69) +103 + j*(-61) +-25 + j*(-137) +-119 + j*(-23) +-18 + j*(52) +8 + j*(-64) +-153 + j*(-33) +-83 + j*(189) +197 + j*(93) +86 + j*(-235) +-293 + j*(-129) +-226 + j*(281) +158 + j*(278) +195 + j*(-12) +13 + j*(-35) +42 + j*(86) +158 + j*(42) +163 + j*(-66) +129 + j*(-132) +66 + j*(-199) +-32 + j*(-218) +-116 + j*(-207) +-245 + j*(-177) +-373 + j*(11) +-266 + j*(280) +18 + j*(331) +182 + j*(159) +158 + j*(-23) +15 + j*(-107) +-128 + j*(-4) +-47 + j*(170) +136 + j*(105) +69 + j*(-54) +-55 + j*(49) +98 + j*(155) +208 + j*(-11) +83 + j*(-102) +73 + j*(-41) +92 + j*(-145) +-116 + j*(-157) +-128 + j*(124) +205 + j*(135) +236 + j*(-214) +-62 + j*(-278) +-117 + j*(-98) +-63 + j*(-123) +-197 + j*(-114) +-185 + j*(81) +-5 + j*(66) +-50 + j*(-69) +-143 + j*(8) +-59 + j*(42) +-122 + j*(-60) +-296 + j*(93) +-145 + j*(368) +175 + j*(320) +255 + j*(62) +122 + j*(-95) +-64 + j*(-74) +-113 + j*(142) +149 + j*(253) +330 + j*(-47) +31 + j*(-283) +-222 + j*(-14) +6 + j*(216) +192 + j*(39) +72 + j*(-78) +43 + j*(-16) +64 + j*(-79) +-71 + j*(-67) +-28 + j*(125) +212 + j*(54) +131 + j*(-217) +-133 + j*(-146) +-68 + j*(70) +76 + j*(-16) +-59 + j*(-91) +-95 + j*(104) +144 + j*(139) +205 + j*(-93) +36 + j*(-150) +50 + j*(-59) +124 + j*(-183) +-73 + j*(-305) +-228 + j*(-122) +-81 + j*(-23) +-100 + j*(-214) +-424 + j*(-128) +-380 + j*(317) +73 + j*(366) +153 + j*(8) +-98 + j*(-6) +-1 + j*(191) +185 + j*(2) +-50 + j*(-177) +-202 + j*(67) +40 + j*(162) +50 + j*(-89) +-235 + j*(-28) +-160 + j*(301) +161 + j*(273) +180 + j*(40) +69 + j*(28) +107 + j*(59) +119 + j*(-6) +87 + j*(-18) +110 + j*(-49) +35 + j*(-127) +-82 + j*(-34) +22 + j*(100) +173 + j*(-21) +50 + j*(-208) +-171 + j*(-125) +-165 + j*(105) +37 + j*(181) +170 + j*(35) +77 + j*(-113) +-60 + j*(-45) +16 + j*(80) +151 + j*(-3) +94 + j*(-148) +-14 + j*(-153) +-68 + j*(-142) +-179 + j*(-107) +-211 + j*(71) +-58 + j*(149) +-26 + j*(57) +-117 + j*(155) +84 + j*(344) +407 + j*(170) +378 + j*(-184) +158 + j*(-296) +35 + j*(-284) +-87 + j*(-274) +-168 + j*(-157) +-114 + j*(-103) +-168 + j*(-168) +-328 + j*(-48) +-250 + j*(185) +-42 + j*(190) +-8 + j*(85) +-21 + j*(76) +-8 + j*(45) +-76 + j*(54) +-27 + j*(190) +190 + j*(132) +170 + j*(-142) +-105 + j*(-183) +-204 + j*(33) +-92 + j*(165) +28 + j*(173) +127 + j*(103) +102 + j*(-33) +-23 + j*(-9) +51 + j*(109) +190 + j*(-38) +-11 + j*(-218) +-225 + j*(-1) +-25 + j*(212) +148 + j*(43) +-7 + j*(-45) +1 + j*(132) +233 + j*(62) +165 + j*(-228) +-132 + j*(-211) +-180 + j*(21) +-56 + j*(96) +-8 + j*(82) +44 + j*(94) +104 + j*(25) +35 + j*(-51) +-43 + j*(27) +45 + j*(134) +209 + j*(76) +254 + j*(-117) +107 + j*(-292) +-150 + j*(-268) +-263 + j*(-11) +-60 + j*(197) +191 + j*(55) +93 + j*(-218) +-197 + j*(-148) +-148 + j*(162) +184 + j*(128) +178 + j*(-226) +-180 + j*(-267) +-271 + j*(51) +-34 + j*(158) +41 + j*(13) +-38 + j*(0) +1 + j*(40) +6 + j*(-18) +-59 + j*(40) +88 + j*(136) +261 + j*(-80) +59 + j*(-350) +-248 + j*(-250) +-266 + j*(-21) +-182 + j*(36) +-177 + j*(53) +-161 + j*(85) +-193 + j*(107) +-207 + j*(268) +27 + j*(402) +247 + j*(209) +129 + j*(17) +56 + j*(136) +258 + j*(120) +229 + j*(-168) +-78 + j*(-160) +-64 + j*(113) +170 + j*(59) +77 + j*(-148) +-108 + j*(-31) +15 + j*(130) +151 + j*(8) +51 + j*(-105) +-40 + j*(-45) +-42 + j*(8) +-46 + j*(79) +69 + j*(174) +252 + j*(73) +219 + j*(-144) +48 + j*(-170) +27 + j*(-79) +76 + j*(-110) +14 + j*(-173) +-57 + j*(-125) +-37 + j*(-83) +-28 + j*(-112) +-76 + j*(-127) +-127 + j*(-107) +-182 + j*(-55) +-190 + j*(67) +-52 + j*(153) +88 + j*(37) +-12 + j*(-134) +-209 + j*(-48) +-156 + j*(166) +36 + j*(158) +42 + j*(40) +16 + j*(83) +163 + j*(47) +121 + j*(-222) +-246 + j*(-230) +-334 + j*(179) +50 + j*(338) +243 + j*(25) +16 + j*(-159) +-142 + j*(-8) +-72 + j*(122) +25 + j*(144) +138 + j*(94) +143 + j*(-86) +-79 + j*(-124) +-121 + j*(132) +185 + j*(173) +239 + j*(-182) +-132 + j*(-284) +-294 + j*(43) +-78 + j*(240) +91 + j*(185) +195 + j*(122) +308 + j*(-75) +124 + j*(-369) +-279 + j*(-296) +-353 + j*(95) +-79 + j*(262) +76 + j*(132) +30 + j*(67) +55 + j*(129) +194 + j*(81) +192 + j*(-132) +-52 + j*(-206) +-191 + j*(40) +42 + j*(218) +232 + j*(6) +36 + j*(-152) +-55 + j*(59) +214 + j*(88) +226 + j*(-250) +-139 + j*(-286) +-190 + j*(41) +70 + j*(71) +55 + j*(-124) +-89 + j*(-54) +37 + j*(49) +132 + j*(-125) +-43 + j*(-244) +-177 + j*(-129) +-149 + j*(-38) +-137 + j*(-24) +-142 + j*(4) +-150 + j*(25) +-171 + j*(105) +-52 + j*(214) +131 + j*(100) +37 + j*(-120) +-204 + j*(-43) +-158 + j*(200) +51 + j*(194) +59 + j*(61) +1 + j*(87) +82 + j*(112) +108 + j*(1) +-3 + j*(-28) +-23 + j*(77) +76 + j*(83) +66 + j*(-2) +-14 + j*(46) +72 + j*(158) +244 + j*(79) +236 + j*(-113) +114 + j*(-178) +60 + j*(-178) +-21 + j*(-221) +-165 + j*(-146) +-140 + j*(19) +-21 + j*(2) +-102 + j*(-72) +-185 + j*(98) +42 + j*(233) +225 + j*(3) +28 + j*(-192) +-140 + j*(-33) +-7 + j*(78) +38 + j*(-54) +-113 + j*(-42) +-71 + j*(146) +151 + j*(107) +143 + j*(-125) +-66 + j*(-162) +-119 + j*(-9) +-29 + j*(5) +-102 + j*(-79) +-268 + j*(76) +-108 + j*(378) +293 + j*(308) +334 + j*(-91) +11 + j*(-167) +0 + j*(102) +304 + j*(29) +221 + j*(-356) +-197 + j*(-358) +-294 + j*(-16) +-108 + j*(108) +-43 + j*(82) +37 + j*(127) +197 + j*(-4) +68 + j*(-255) +-235 + j*(-165) +-197 + j*(137) +63 + j*(132) +61 + j*(-66) +-91 + j*(-42) +-37 + j*(91) +100 + j*(26) +60 + j*(-134) +-96 + j*(-156) +-182 + j*(-64) +-192 + j*(13) +-215 + j*(84) +-202 + j*(231) +-19 + j*(366) +247 + j*(267) +278 + j*(-31) +21 + j*(-142) +-112 + j*(76) +100 + j*(225) +283 + j*(19) +115 + j*(-186) +-77 + j*(-58) +45 + j*(105) +199 + j*(-28) +84 + j*(-192) +-70 + j*(-128) +-62 + j*(-35) +-59 + j*(-8) +-18 + j*(86) +176 + j*(46) +160 + j*(-254) +-221 + j*(-291) +-323 + j*(122) +72 + j*(262) +206 + j*(-103) +-147 + j*(-211) +-238 + j*(141) +100 + j*(235) +200 + j*(-59) +-37 + j*(-152) +-114 + j*(34) +33 + j*(107) +126 + j*(5) +100 + j*(-115) +-15 + j*(-191) +-179 + j*(-140) +-224 + j*(51) +-86 + j*(173) +54 + j*(123) +80 + j*(24) +42 + j*(-43) +-30 + j*(-70) +-118 + j*(-21) +-136 + j*(110) +-18 + j*(228) +181 + j*(202) +283 + j*(4) +170 + j*(-181) +2 + j*(-163) +-1 + j*(-71) +43 + j*(-122) +-56 + j*(-192) +-161 + j*(-115) +-156 + j*(-45) +-197 + j*(-29) +-255 + j*(115) +-100 + j*(283) +112 + j*(202) +103 + j*(40) +40 + j*(46) +104 + j*(28) +45 + j*(-110) +-158 + j*(-43) +-114 + j*(212) +162 + j*(218) +224 + j*(-30) +39 + j*(-115) +-30 + j*(13) +65 + j*(57) +101 + j*(-19) +54 + j*(-53) +42 + j*(-27) +81 + j*(-44) +65 + j*(-117) +-36 + j*(-137) +-88 + j*(-47) +-27 + j*(-2) +-19 + j*(-59) +-105 + j*(-21) +-44 + j*(110) +124 + j*(50) +86 + j*(-128) +-64 + j*(-110) +-41 + j*(-31) +-33 + j*(-107) +-197 + j*(-87) +-207 + j*(129) +-13 + j*(190) +45 + j*(83) +28 + j*(101) +155 + j*(90) +182 + j*(-108) +-11 + j*(-187) +-96 + j*(-67) +-54 + j*(-40) +-118 + j*(-52) +-151 + j*(76) +-30 + j*(140) +28 + j*(68) +-1 + j*(66) +59 + j*(91) +106 + j*(13) +63 + j*(-46) +30 + j*(-65) +-52 + j*(-95) +-160 + j*(30) +-26 + j*(209) +195 + j*(98) +116 + j*(-109) +-30 + j*(-35) +85 + j*(37) +122 + j*(-138) +-80 + j*(-183) +-139 + j*(-16) +-52 + j*(21) +-83 + j*(8) +-54 + j*(124) +121 + j*(78) +69 + j*(-126) +-141 + j*(-68) +-84 + j*(131) +74 + j*(79) +15 + j*(-7) +12 + j*(95) +184 + j*(45) +122 + j*(-194) +-146 + j*(-146) +-102 + j*(121) +168 + j*(62) +98 + j*(-232) +-227 + j*(-185) +-233 + j*(142) +51 + j*(192) +104 + j*(-26) +-62 + j*(-37) +-11 + j*(115) +159 + j*(13) +35 + j*(-194) +-204 + j*(-81) +-124 + j*(170) +105 + j*(130) +91 + j*(-57) +-46 + j*(-47) +-34 + j*(46) +18 + j*(25) +-19 + j*(13) +-1 + j*(90) +125 + j*(73) +142 + j*(-82) +-7 + j*(-134) +-57 + j*(-12) +56 + j*(1) +25 + j*(-146) +-174 + j*(-100) +-139 + j*(134) +93 + j*(115) +64 + j*(-90) +-108 + j*(-28) +-1 + j*(120) +132 + j*(-34) +-59 + j*(-165) +-207 + j*(35) +-47 + j*(202) +100 + j*(136) +141 + j*(77) +220 + j*(-18) +155 + j*(-210) +-57 + j*(-214) +-86 + j*(-76) +-43 + j*(-117) +-204 + j*(-126) +-249 + j*(128) +28 + j*(229) +165 + j*(-16) +-25 + j*(-170) +-192 + j*(-66) +-209 + j*(88) +-129 + j*(233) +81 + j*(271) +209 + j*(80) +72 + j*(-46) +18 + j*(77) +187 + j*(63) +157 + j*(-168) +-95 + j*(-155) +-91 + j*(73) +98 + j*(53) +54 + j*(-110) +-90 + j*(-47) +-23 + j*(76) +80 + j*(1) +1 + j*(-93) +-100 + j*(-33) +-98 + j*(78) +-21 + j*(166) +151 + j*(190) +321 + j*(1) +203 + j*(-288) +-123 + j*(-281) +-194 + j*(-1) +13 + j*(88) +78 + j*(-65) +-23 + j*(-102) +-22 + j*(-69) +-57 + j*(-141) +-228 + j*(-72) +-181 + j*(177) +86 + j*(182) +119 + j*(-33) +4 + j*(-56) +50 + j*(-43) +-4 + j*(-202) +-270 + j*(-153) +-286 + j*(146) +-64 + j*(211) +-37 + j*(127) +-25 + j*(225) +196 + j*(214) +241 + j*(-38) +58 + j*(-103) +51 + j*(-18) +80 + j*(-117) +-96 + j*(-141) +-125 + j*(45) +23 + j*(34) +-79 + j*(-83) +-216 + j*(120) +38 + j*(322) +293 + j*(91) +132 + j*(-173) +-103 + j*(-79) +-69 + j*(127) +124 + j*(176) +286 + j*(19) +222 + j*(-245) +-86 + j*(-308) +-252 + j*(-31) +-45 + j*(192) +200 + j*(66) +170 + j*(-175) +-29 + j*(-252) +-189 + j*(-151) +-204 + j*(22) +-84 + j*(115) +18 + j*(67) +18 + j*(1) +-2 + j*(-13) +-11 + j*(-31) +-57 + j*(-40) +-103 + j*(17) +-69 + j*(106) +46 + j*(123) +122 + j*(16) +49 + j*(-89) +-46 + j*(-57) +-28 + j*(-10) +-50 + j*(-45) +-136 + j*(37) +-18 + j*(188) +182 + j*(63) +70 + j*(-157) +-140 + j*(-64) +-78 + j*(111) +35 + j*(95) +66 + j*(81) +185 + j*(32) +162 + j*(-202) +-117 + j*(-233) +-161 + j*(8) +6 + j*(-26) +-165 + j*(-170) +-362 + j*(101) +-98 + j*(355) +115 + j*(180) +-6 + j*(114) +75 + j*(283) +329 + j*(164) +286 + j*(-95) +141 + j*(-126) +104 + j*(-136) +-6 + j*(-132) +7 + j*(22) +205 + j*(-46) +93 + j*(-307) +-196 + j*(-183) +-59 + j*(74) +151 + j*(-113) +-83 + j*(-315) +-296 + j*(-106) +-171 + j*(77) +-71 + j*(35) +-72 + j*(4) +-87 + j*(-40) +-209 + j*(-25) +-231 + j*(175) +-37 + j*(239) +-9 + j*(131) +-40 + j*(248) +265 + j*(286) +378 + j*(-141) +-78 + j*(-327) +-289 + j*(93) +57 + j*(281) +181 + j*(31) +14 + j*(23) +139 + j*(173) +344 + j*(-11) +225 + j*(-270) +10 + j*(-289) +-103 + j*(-218) +-167 + j*(-113) +-125 + j*(-10) +-69 + j*(-30) +-124 + j*(-33) +-103 + j*(62) +4 + j*(15) +-92 + j*(-112) +-288 + j*(6) +-251 + j*(276) +4 + j*(411) +286 + j*(305) +386 + j*(-4) +161 + j*(-228) +-64 + j*(-95) +54 + j*(63) +171 + j*(-109) +-41 + j*(-246) +-227 + j*(-56) +-119 + j*(155) +76 + j*(156) +170 + j*(5) +58 + j*(-159) +-158 + j*(-61) +-49 + j*(208) +276 + j*(100) +196 + j*(-252) +-112 + j*(-204) +-63 + j*(-6) +14 + j*(-114) +-177 + j*(-100) +-102 + j*(158) +188 + j*(33) +34 + j*(-267) +-239 + j*(-119) +-108 + j*(65) +-68 + j*(-85) +-296 + j*(1) +-157 + j*(327) +224 + j*(201) +135 + j*(-182) +-231 + j*(-141) +-275 + j*(192) +-20 + j*(354) +240 + j*(245) +291 + j*(-37) +54 + j*(-195) +-135 + j*(-11) +25 + j*(170) +205 + j*(23) +100 + j*(-162) +-71 + j*(-133) +-131 + j*(-20) +-115 + j*(113) +40 + j*(216) +250 + j*(104) +235 + j*(-154) +15 + j*(-248) +-147 + j*(-132) +-148 + j*(35) +-17 + j*(121) +110 + j*(30) +44 + j*(-112) +-106 + j*(-56) +-55 + j*(97) +101 + j*(49) +62 + j*(-112) +-109 + j*(-88) +-120 + j*(91) +51 + j*(150) +152 + j*(11) +57 + j*(-103) +-35 + j*(-41) +23 + j*(16) +52 + j*(-61) +-41 + j*(-70) +-28 + j*(37) +96 + j*(8) +76 + j*(-127) +-33 + j*(-134) +-47 + j*(-99) +-90 + j*(-128) +-177 + j*(-52) +-112 + j*(59) +-25 + j*(-8) +-124 + j*(-69) +-187 + j*(62) +-61 + j*(129) +-21 + j*(21) +-146 + j*(18) +-155 + j*(183) +16 + j*(247) +124 + j*(129) +52 + j*(31) +-17 + j*(124) +143 + j*(221) +337 + j*(25) +185 + j*(-251) +-93 + j*(-180) +-52 + j*(13) +37 + j*(-83) +-168 + j*(-117) +-214 + j*(187) +127 + j*(282) +261 + j*(-25) +44 + j*(-146) +-10 + j*(-31) +24 + j*(-95) +-183 + j*(-95) +-222 + j*(240) +168 + j*(390) +433 + j*(71) +298 + j*(-221) +113 + j*(-276) +-38 + j*(-285) +-211 + j*(-148) +-129 + j*(102) +140 + j*(42) +71 + j*(-243) +-246 + j*(-169) +-197 + j*(172) +141 + j*(163) +176 + j*(-131) +-39 + j*(-188) +-71 + j*(-68) +-6 + j*(-113) +-122 + j*(-194) +-250 + j*(-72) +-182 + j*(49) +-130 + j*(2) +-233 + j*(1) +-279 + j*(167) +-152 + j*(306) +4 + j*(311) +115 + j*(258) +196 + j*(161) +183 + j*(35) +96 + j*(2) +91 + j*(52) +163 + j*(17) +135 + j*(-98) +13 + j*(-98) +6 + j*(10) +126 + j*(-1) +124 + j*(-168) +-72 + j*(-218) +-180 + j*(-43) +-50 + j*(76) +38 + j*(-34) +-102 + j*(-103) +-193 + j*(77) +-8 + j*(222) +180 + j*(76) +91 + j*(-114) +-70 + j*(-62) +-25 + j*(64) +83 + j*(8) +17 + j*(-104) +-108 + j*(-43) +-68 + j*(95) +66 + j*(85) +87 + j*(-28) +7 + j*(-65) +-32 + j*(-13) +8 + j*(21) +50 + j*(-14) +21 + j*(-77) +-58 + j*(-66) +-64 + j*(24) +18 + j*(32) +10 + j*(-45) +-84 + j*(0) +-7 + j*(138) +182 + j*(66) +154 + j*(-149) +-35 + j*(-161) +-43 + j*(-35) +289 + j*(-105) +48 + j*(-267) +-117 + j*(-80) +29 + j*(9) +35 + j*(-146) +-147 + j*(-115) +-127 + j*(57) +-21 + j*(53) +-33 + j*(38) +35 + j*(74) +91 + j*(-54) +-83 + j*(-115) +-143 + j*(86) +59 + j*(139) +90 + j*(-30) +-27 + j*(-8) +72 + j*(67) +134 + j*(-110) +-86 + j*(-178) +-147 + j*(43) +63 + j*(65) +36 + j*(-163) +-241 + j*(-127) +-261 + j*(175) +-10 + j*(271) +105 + j*(127) +33 + j*(82) +76 + j*(185) +282 + j*(139) +342 + j*(-134) +117 + j*(-313) +-91 + j*(-217) +-93 + j*(-85) +-62 + j*(-66) +-66 + j*(-48) +-45 + j*(-54) +-103 + j*(-93) +-198 + j*(10) +-96 + j*(158) +62 + j*(83) +-5 + j*(-36) +-83 + j*(56) +40 + j*(118) +115 + j*(-21) +-5 + j*(-117) +-124 + j*(-46) +-124 + j*(76) +-24 + j*(152) +101 + j*(85) +59 + j*(-54) +-82 + j*(-16) +-40 + j*(128) +96 + j*(98) +89 + j*(8) +78 + j*(14) +117 + j*(-49) +11 + j*(-134) +-95 + j*(-16) +24 + j*(91) +124 + j*(-26) +34 + j*(-121) +-38 + j*(-86) +-65 + j*(-70) +-132 + j*(-6) +-73 + j*(136) +105 + j*(129) +165 + j*(-20) +114 + j*(-127) +27 + j*(-206) +-149 + j*(-214) +-279 + j*(-35) +-199 + j*(165) +-30 + j*(222) +127 + j*(180) +237 + j*(3) +117 + j*(-216) +-130 + j*(-172) +-134 + j*(24) +-23 + j*(24) +-66 + j*(-16) +-55 + j*(66) +30 + j*(5) +-110 + j*(-68) +-191 + j*(171) +123 + j*(295) +298 + j*(-30) +11 + j*(-223) +-153 + j*(-2) +4 + j*(105) +43 + j*(1) +-23 + j*(31) +62 + j*(81) +114 + j*(-18) +42 + j*(-70) +21 + j*(-55) +-17 + j*(-88) +-118 + j*(-25) +-51 + j*(135) +152 + j*(98) +173 + j*(-116) +-1 + j*(-206) +-134 + j*(-121) +-135 + j*(-4) +-72 + j*(30) +-74 + j*(0) +-143 + j*(57) +-77 + j*(211) +144 + j*(200) +202 + j*(-10) +59 + j*(-81) +58 + j*(10) +178 + j*(-93) +22 + j*(-322) +-337 + j*(-206) +-330 + j*(221) +78 + j*(327) +239 + j*(-14) +-35 + j*(-155) +-123 + j*(98) +151 + j*(136) +168 + j*(-165) +-141 + j*(-185) +-166 + j*(93) +47 + j*(113) +43 + j*(-6) +30 + j*(49) +165 + j*(-33) +17 + j*(-255) +-269 + j*(-81) +-86 + j*(231) +225 + j*(40) +30 + j*(-259) +-252 + j*(-91) +-139 + j*(146) +13 + j*(98) +14 + j*(58) +77 + j*(35) +42 + j*(-102) +-147 + j*(-42) +-55 + j*(191) +230 + j*(76) +115 + j*(-262) +-256 + j*(-185) +-249 + j*(168) +25 + j*(216) +93 + j*(48) +23 + j*(21) +58 + j*(40) +56 + j*(-28) +-37 + j*(-1) +32 + j*(119) +198 + j*(11) +76 + j*(-219) +-213 + j*(-105) +-132 + j*(235) +230 + j*(217) +286 + j*(-113) +52 + j*(-210) +-11 + j*(-78) +75 + j*(-99) +-7 + j*(-212) +-186 + j*(-150) +-212 + j*(49) +-55 + j*(184) +151 + j*(121) +186 + j*(-97) +4 + j*(-198) +-103 + j*(-67) +1 + j*(5) +44 + j*(-101) +-55 + j*(-142) +-87 + j*(-94) +-101 + j*(-129) +-243 + j*(-112) +-301 + j*(93) +-132 + j*(234) +18 + j*(151) +-12 + j*(62) +-49 + j*(107) +35 + j*(147) +117 + j*(44) +16 + j*(-88) +-175 + j*(0) +-128 + j*(248) +146 + j*(272) +226 + j*(30) +36 + j*(-52) +-14 + j*(125) +177 + j*(180) +288 + j*(15) +226 + j*(-129) +146 + j*(-189) +43 + j*(-238) +-108 + j*(-192) +-154 + j*(-26) +-35 + j*(66) +40 + j*(-11) +-47 + j*(-35) +-35 + j*(124) +231 + j*(130) +330 + j*(-210) +6 + j*(-432) +-267 + j*(-223) +-188 + j*(-30) +-155 + j*(-62) +-239 + j*(41) +-90 + j*(183) +37 + j*(34) +-144 + j*(-7) +-110 + j*(267) +263 + j*(215) +240 + j*(-197) +-127 + j*(-203) +-124 + j*(60) +16 + j*(-4) +-152 + j*(-30) +-110 + j*(262) +289 + j*(213) +280 + j*(-238) +-146 + j*(-282) +-222 + j*(64) +23 + j*(141) +82 + j*(-6) +25 + j*(-49) +6 + j*(-81) +-108 + j*(-105) +-194 + j*(47) +-64 + j*(187) +83 + j*(114) +59 + j*(8) +0 + j*(14) +-1 + j*(57) +37 + j*(90) +122 + j*(75) +168 + j*(-39) +73 + j*(-146) +-55 + j*(-95) +-36 + j*(14) +54 + j*(-6) +14 + j*(-96) +-99 + j*(-51) +-68 + j*(88) +85 + j*(91) +134 + j*(-51) +41 + j*(-154) +-95 + j*(-151) +-206 + j*(-25) +-144 + j*(183) +107 + j*(202) +188 + j*(-37) +-20 + j*(-119) +-62 + j*(71) +147 + j*(68) +124 + j*(-173) +-122 + j*(-161) +-127 + j*(53) +21 + j*(59) +6 + j*(-20) +-13 + j*(25) +59 + j*(1) +4 + j*(-86) +-95 + j*(-6) +8 + j*(105) +144 + j*(-4) +68 + j*(-172) +-110 + j*(-169) +-196 + j*(-29) +-133 + j*(106) +-3 + j*(113) +34 + j*(15) +-41 + j*(-21) +-91 + j*(33) +-90 + j*(110) +-18 + j*(216) +197 + j*(218) +314 + j*(-42) +87 + j*(-242) +-115 + j*(-71) +33 + j*(80) +140 + j*(-82) +-29 + j*(-170) +-99 + j*(-30) +-1 + j*(-6) +-40 + j*(-76) +-98 + j*(8) +1 + j*(52) +15 + j*(-54) +-93 + j*(-42) +-65 + j*(50) +-20 + j*(-1) +-129 + j*(8) +-103 + j*(194) +134 + j*(193) +154 + j*(-35) +-39 + j*(-37) +11 + j*(146) +216 + j*(68) +156 + j*(-149) +-17 + j*(-116) +37 + j*(-21) +90 + j*(-150) +-112 + j*(-232) +-263 + j*(-30) +-138 + j*(153) +8 + j*(112) +-6 + j*(47) +-35 + j*(86) +14 + j*(156) +151 + j*(177) +316 + j*(31) +255 + j*(-251) +-49 + j*(-311) +-167 + j*(-69) +13 + j*(4) +6 + j*(-192) +-267 + j*(-154) +-273 + j*(182) +54 + j*(267) +185 + j*(0) +-18 + j*(-135) +-144 + j*(32) +2 + j*(172) +166 + j*(59) +109 + j*(-117) +-37 + j*(-109) +-45 + j*(-27) +-28 + j*(-60) +-139 + j*(-47) +-143 + j*(141) +78 + j*(190) +168 + j*(-18) +1 + j*(-113) +-71 + j*(6) +6 + j*(42) +5 + j*(3) +-3 + j*(49) +91 + j*(45) +108 + j*(-82) +-16 + j*(-148) +-133 + j*(-73) +-136 + j*(76) +23 + j*(173) +211 + j*(23) +102 + j*(-249) +-216 + j*(-225) +-303 + j*(62) +-138 + j*(218) +-2 + j*(214) +100 + j*(173) +144 + j*(47) +25 + j*(-8) +6 + j*(151) +246 + j*(177) +357 + j*(-109) +131 + j*(-318) +-112 + j*(-233) +-158 + j*(-30) +-19 + j*(103) +180 + j*(0) +107 + j*(-271) +-215 + j*(-262) +-282 + j*(39) +-81 + j*(137) +-29 + j*(65) +1 + j*(115) +158 + j*(27) +47 + j*(-217) +-241 + j*(-107) +-150 + j*(170) +54 + j*(88) +-59 + j*(-16) +-83 + j*(154) +124 + j*(134) +70 + j*(-66) +-105 + j*(45) +65 + j*(219) +265 + j*(42) +152 + j*(-168) +-22 + j*(-149) +-83 + j*(-40) +-25 + j*(85) +170 + j*(56) +179 + j*(-217) +-138 + j*(-293) +-273 + j*(-1) +-75 + j*(133) +-13 + j*(32) +-70 + j*(78) +46 + j*(151) +146 + j*(57) +153 + j*(-16) +195 + j*(-137) +28 + j*(-334) +-276 + j*(-197) +-188 + j*(105) +34 + j*(-1) +-150 + j*(-147) +-267 + j*(112) +5 + j*(197) +16 + j*(-44) +-216 + j*(57) +-28 + j*(312) +238 + j*(98) +31 + j*(-144) +-156 + j*(45) +-7 + j*(180) +56 + j*(98) +30 + j*(136) +173 + j*(168) +258 + j*(-6) +145 + j*(-132) +42 + j*(-111) +1 + j*(-65) +16 + j*(-4) +90 + j*(-25) +50 + j*(-115) +-30 + j*(-59) +59 + j*(-30) +15 + j*(-192) +-250 + j*(-86) +-112 + j*(277) +327 + j*(137) +206 + j*(-332) +-237 + j*(-243) +-171 + j*(117) +79 + j*(52) +-7 + j*(-91) +-53 + j*(17) +75 + j*(-9) +6 + j*(-153) +-129 + j*(-91) +-99 + j*(-10) +-106 + j*(-25) +-136 + j*(52) +-40 + j*(88) +-48 + j*(1) +-161 + j*(84) +-45 + j*(264) +179 + j*(209) +245 + j*(39) +233 + j*(-105) +105 + j*(-275) +-171 + j*(-233) +-192 + j*(54) +74 + j*(65) +41 + j*(-211) +-262 + j*(-182) +-293 + j*(94) +-141 + j*(161) +-134 + j*(158) +-73 + j*(276) +132 + j*(254) +175 + j*(54) +16 + j*(-18) +-84 + j*(126) +39 + j*(310) +330 + j*(296) +501 + j*(-6) +334 + j*(-305) +71 + j*(-325) +-45 + j*(-229) +-115 + j*(-142) +-98 + j*(11) +86 + j*(33) +119 + j*(-179) +-106 + j*(-235) +-180 + j*(-46) +-73 + j*(-6) +-128 + j*(-57) +-189 + j*(103) +11 + j*(227) +194 + j*(70) +141 + j*(-124) +-1 + j*(-195) +-173 + j*(-159) +-265 + j*(54) +-91 + j*(255) +147 + j*(177) +175 + j*(-4) +122 + j*(-93) +39 + j*(-185) +-155 + j*(-162) +-191 + j*(64) +11 + j*(116) +21 + j*(-49) +-126 + j*(13) +-3 + j*(163) +136 + j*(6) +-46 + j*(-89) +-78 + j*(132) +209 + j*(125) +206 + j*(-209) +-115 + j*(-246) +-169 + j*(-5) +-25 + j*(13) +-78 + j*(-70) +-147 + j*(35) +-38 + j*(98) +-1 + j*(-1) +-103 + j*(-11) +-120 + j*(90) +-57 + j*(137) +-13 + j*(147) +47 + j*(153) +107 + j*(101) +100 + j*(24) +37 + j*(-1) +-18 + j*(52) +26 + j*(156) +185 + j*(162) +270 + j*(-8) +148 + j*(-137) +51 + j*(-60) +148 + j*(-20) +189 + j*(-180) +4 + j*(-284) +-164 + j*(-153) +-118 + j*(13) +3 + j*(23) +24 + j*(-56) +-43 + j*(-78) +-88 + j*(-6) +-18 + j*(78) +110 + j*(32) +114 + j*(-117) +-15 + j*(-175) +-87 + j*(-96) +-46 + j*(-64) +-71 + j*(-127) +-206 + j*(-91) +-226 + j*(105) +-23 + j*(203) +134 + j*(45) +30 + j*(-124) +-115 + j*(-62) +-65 + j*(28) +-31 + j*(-54) +-179 + j*(-63) +-210 + j*(136) +-16 + j*(198) +36 + j*(40) +-106 + j*(38) +-68 + j*(192) +78 + j*(156) +47 + j*(64) +39 + j*(136) +185 + j*(86) +110 + j*(-131) +-153 + j*(-52) +-91 + j*(232) +165 + j*(208) +156 + j*(53) +134 + j*(125) +352 + j*(78) +346 + j*(-262) +-13 + j*(-349) +-147 + j*(-60) +64 + j*(48) +127 + j*(-127) +-36 + j*(-159) +-47 + j*(2) +148 + j*(4) +195 + j*(-245) +-71 + j*(-416) +-358 + j*(-235) +-324 + j*(68) +-119 + j*(122) +-91 + j*(37) +-129 + j*(89) +-40 + j*(146) +21 + j*(93) +28 + j*(99) +151 + j*(76) +176 + j*(-152) +-89 + j*(-262) +-268 + j*(-39) +-136 + j*(136) +-42 + j*(90) +-69 + j*(110) +40 + j*(185) +185 + j*(63) +122 + j*(-134) +-73 + j*(-173) +-218 + j*(-44) +-208 + j*(163) +-20 + j*(275) +141 + j*(173) +112 + j*(64) +101 + j*(95) +206 + j*(52) +184 + j*(-124) +-6 + j*(-166) +-108 + j*(-8) +-1 + j*(148) +205 + j*(106) +245 + j*(-127) +27 + j*(-231) +-72 + j*(-45) +124 + j*(-6) +107 + j*(-274) +-233 + j*(-255) +-246 + j*(96) +51 + j*(117) +33 + j*(-96) +-96 + j*(-16) +52 + j*(31) +20 + j*(-190) +-269 + j*(-102) +-158 + j*(219) +146 + j*(103) +16 + j*(-148) +-162 + j*(-1) +-6 + j*(86) +-26 + j*(-93) +-250 + j*(21) +-105 + j*(300) +186 + j*(184) +116 + j*(-55) +-38 + j*(-11) +-4 + j*(71) +16 + j*(56) +22 + j*(95) +110 + j*(95) +133 + j*(8) +105 + j*(-18) +121 + j*(-63) +32 + j*(-133) +-62 + j*(-13) +107 + j*(81) +227 + j*(-165) +-63 + j*(-356) +-326 + j*(-103) +-173 + j*(166) +21 + j*(103) +-13 + j*(16) +-28 + j*(69) +35 + j*(64) +17 + j*(31) +24 + j*(100) +172 + j*(95) +235 + j*(-98) +76 + j*(-238) +-76 + j*(-169) +-74 + j*(-90) +-94 + j*(-104) +-181 + j*(-21) +-91 + j*(144) +133 + j*(70) +83 + j*(-201) +-218 + j*(-201) +-285 + j*(86) +-70 + j*(182) +-14 + j*(47) +-133 + j*(74) +-64 + j*(236) +134 + j*(196) +145 + j*(21) +33 + j*(-3) +31 + j*(71) +93 + j*(63) +103 + j*(27) +136 + j*(8) +159 + j*(-101) +6 + j*(-204) +-166 + j*(-51) +-32 + j*(163) +197 + j*(45) +89 + j*(-181) +-113 + j*(-66) +34 + j*(115) +224 + j*(-70) +40 + j*(-300) +-203 + j*(-174) +-153 + j*(20) +-46 + j*(-1) +-86 + j*(-54) +-144 + j*(-4) +-142 + j*(78) +-77 + j*(152) +35 + j*(143) +64 + j*(58) +30 + j*(57) +103 + j*(73) +147 + j*(-69) +-13 + j*(-156) +-113 + j*(-19) +-8 + j*(49) +1 + j*(-51) +-122 + j*(-18) +-88 + j*(131) +46 + j*(125) +52 + j*(45) +18 + j*(74) +99 + j*(122) +229 + j*(40) +226 + j*(-179) +-26 + j*(-305) +-270 + j*(-82) +-103 + j*(228) +225 + j*(115) +159 + j*(-190) +-81 + j*(-153) +-35 + j*(-6) +34 + j*(-107) +-125 + j*(-144) +-168 + j*(22) +-47 + j*(45) +-95 + j*(-20) +-159 + j*(114) +14 + j*(233) +197 + j*(102) +174 + j*(-106) +-4 + j*(-222) +-247 + j*(-124) +-266 + j*(206) +88 + j*(342) +296 + j*(18) +17 + j*(-190) +-146 + j*(75) +149 + j*(204) +288 + j*(-123) +-25 + j*(-312) +-264 + j*(-69) +-137 + j*(181) +74 + j*(180) +169 + j*(55) +150 + j*(-76) +47 + j*(-137) +-26 + j*(-86) +4 + j*(-62) +-24 + j*(-129) +-163 + j*(-97) +-177 + j*(95) +24 + j*(166) +134 + j*(-13) +-17 + j*(-141) +-153 + j*(-25) +-85 + j*(95) +-29 + j*(76) +-37 + j*(125) +110 + j*(194) +278 + j*(7) +135 + j*(-240) +-113 + j*(-179) +-115 + j*(-4) +-42 + j*(2) +-67 + j*(11) +-9 + j*(69) +59 + j*(-32) +-93 + j*(-112) +-205 + j*(74) +-33 + j*(229) +126 + j*(125) +100 + j*(23) +87 + j*(9) +70 + j*(-52) +-30 + j*(-29) +18 + j*(99) +185 + j*(21) +101 + j*(-180) +-99 + j*(-108) +-31 + j*(54) +78 + j*(-33) +-46 + j*(-89) +-52 + j*(81) +185 + j*(49) +157 + j*(-255) +-177 + j*(-282) +-271 + j*(8) +-87 + j*(125) +-6 + j*(40) +-25 + j*(14) +-21 + j*(-10) +-103 + j*(-24) +-145 + j*(128) +56 + j*(224) +201 + j*(26) +47 + j*(-132) +-82 + j*(-22) +-1 + j*(52) +16 + j*(-13) +-42 + j*(16) +16 + j*(66) +49 + j*(-5) +-40 + j*(-9) +-18 + j*(112) +144 + j*(107) +204 + j*(-70) +72 + j*(-212) +-123 + j*(-176) +-181 + j*(23) +-6 + j*(134) +121 + j*(-31) +-50 + j*(-162) +-195 + j*(7) +-65 + j*(153) +37 + j*(91) +40 + j*(92) +170 + j*(61) +163 + j*(-193) +-170 + j*(-240) +-288 + j*(107) +-1 + j*(282) +185 + j*(114) +162 + j*(-13) +153 + j*(-107) +-3 + j*(-224) +-206 + j*(-63) +-57 + j*(169) +165 + j*(22) +11 + j*(-170) +-147 + j*(-13) +1 + j*(107) +85 + j*(-23) +-13 + j*(-83) +-57 + j*(-38) +-77 + j*(-19) +-95 + j*(47) +-35 + j*(86) +-41 + j*(71) +-32 + j*(205) +263 + j*(254) +446 + j*(-144) +64 + j*(-469) +-317 + j*(-196) +-170 + j*(134) +43 + j*(57) +-21 + j*(-52) +-77 + j*(8) +-59 + j*(57) +-23 + j*(123) +140 + j*(134) +221 + j*(-90) +-5 + j*(-235) +-171 + j*(-45) +-26 + j*(109) +98 + j*(6) +53 + j*(-85) +20 + j*(-107) +-38 + j*(-162) +-164 + j*(-141) +-222 + j*(-29) +-217 + j*(60) +-197 + j*(170) +-65 + j*(260) +76 + j*(199) +81 + j*(114) +95 + j*(112) +139 + j*(42) +67 + j*(-21) +35 + j*(58) +151 + j*(43) +117 + j*(-108) +-39 + j*(-65) +33 + j*(71) +153 + j*(-46) +3 + j*(-164) +-120 + j*(-2) +28 + j*(127) +170 + j*(25) +165 + j*(-112) +88 + j*(-227) +-107 + j*(-260) +-238 + j*(-64) +-82 + j*(87) +16 + j*(-58) +-175 + j*(-95) +-187 + j*(146) +65 + j*(148) +33 + j*(-88) +-204 + j*(-8) +-112 + j*(245) +112 + j*(188) +80 + j*(72) +94 + j*(163) +308 + j*(91) +301 + j*(-218) +12 + j*(-330) +-177 + j*(-164) +-170 + j*(13) +-62 + j*(122) +107 + j*(92) +132 + j*(-90) +-40 + j*(-125) +-41 + j*(42) +165 + j*(-6) +113 + j*(-285) +-213 + j*(-308) +-335 + j*(-26) +-180 + j*(148) +-30 + j*(113) +8 + j*(11) +-77 + j*(-79) +-247 + j*(-12) +-247 + j*(233) +-6 + j*(336) +141 + j*(191) +93 + j*(113) +146 + j*(161) +292 + j*(35) +192 + j*(-216) +-88 + j*(-197) +-121 + j*(41) +64 + j*(60) +31 + j*(-109) +-173 + j*(-31) +-81 + j*(224) +200 + j*(147) +132 + j*(-132) +-136 + j*(-41) +-18 + j*(240) +288 + j*(127) +226 + j*(-165) +8 + j*(-162) +-4 + j*(-52) +6 + j*(-53) +-10 + j*(20) +144 + j*(53) +215 + j*(-162) +6 + j*(-276) +-84 + j*(-134) +16 + j*(-155) +-129 + j*(-308) +-391 + j*(-144) +-329 + j*(155) +-134 + j*(208) +-63 + j*(195) +69 + j*(210) +174 + j*(31) +-1 + j*(-110) +-136 + j*(81) +98 + j*(218) +280 + j*(-43) +37 + j*(-285) +-244 + j*(-103) +-130 + j*(182) +132 + j*(116) +78 + j*(-113) +-134 + j*(-38) +-12 + j*(190) +277 + j*(32) +137 + j*(-336) +-269 + j*(-279) +-306 + j*(73) +-84 + j*(141) +-79 + j*(33) +-160 + j*(114) +-60 + j*(229) +64 + j*(197) +116 + j*(135) +141 + j*(62) +92 + j*(-4) +40 + j*(38) +105 + j*(69) +138 + j*(-11) +86 + j*(-39) +103 + j*(-30) +90 + j*(-114) +-45 + j*(-99) +-21 + j*(61) +155 + j*(28) +143 + j*(-152) +14 + j*(-182) +-38 + j*(-177) +-177 + j*(-168) +-257 + j*(71) +22 + j*(226) +203 + j*(-59) +-80 + j*(-229) +-218 + j*(40) +30 + j*(115) +11 + j*(-123) +-260 + j*(-18) +-127 + j*(306) +204 + j*(222) +184 + j*(-29) +74 + j*(-21) +145 + j*(-28) +97 + j*(-173) +-65 + j*(-141) +-32 + j*(-24) +42 + j*(-103) +-76 + j*(-190) +-200 + j*(-114) +-247 + j*(-19) +-295 + j*(141) +-132 + j*(388) +254 + j*(333) +330 + j*(-62) +25 + j*(-201) +-71 + j*(1) +73 + j*(-6) +-41 + j*(-155) +-235 + j*(30) +-35 + j*(269) +218 + j*(110) +127 + j*(-100) +16 + j*(-71) +24 + j*(-86) +-116 + j*(-117) +-199 + j*(104) +41 + j*(250) +223 + j*(57) +123 + j*(-101) +54 + j*(-88) +33 + j*(-143) +-110 + j*(-144) +-150 + j*(2) +-69 + j*(37) +-112 + j*(37) +-70 + j*(188) +166 + j*(158) +164 + j*(-104) +-70 + j*(-116) +-74 + j*(55) +14 + j*(47) +-10 + j*(61) +119 + j*(114) +215 + j*(-118) +-82 + j*(-257) +-247 + j*(54) +39 + j*(202) +122 + j*(-38) +-81 + j*(-23) +25 + j*(167) +210 + j*(18) +73 + j*(-124) +33 + j*(-14) +141 + j*(-105) +-53 + j*(-239) +-199 + j*(8) +69 + j*(123) +135 + j*(-160) +-154 + j*(-180) +-127 + j*(86) +100 + j*(2) +-37 + j*(-207) +-245 + j*(-57) +-139 + j*(126) +-26 + j*(81) +-37 + j*(59) +4 + j*(56) +-21 + j*(-15) +-119 + j*(55) +-18 + j*(194) +148 + j*(102) +82 + j*(-47) +-7 + j*(17) +97 + j*(55) +132 + j*(-103) +-51 + j*(-179) +-177 + j*(-28) +-92 + j*(119) +30 + j*(105) +57 + j*(37) +43 + j*(4) +25 + j*(-22) +-23 + j*(-17) +-28 + j*(54) +62 + j*(68) +92 + j*(-38) +-19 + j*(-83) +-71 + j*(21) +14 + j*(81) +79 + j*(25) +70 + j*(-34) +31 + j*(-78) +-53 + j*(-79) +-98 + j*(21) +-20 + j*(96) +56 + j*(66) +81 + j*(31) +117 + j*(-33) +43 + j*(-134) +-94 + j*(-61) +-4 + j*(74) +112 + j*(-68) +-100 + j*(-173) +-209 + j*(107) +116 + j*(230) +250 + j*(-109) +-65 + j*(-243) +-179 + j*(18) +12 + j*(88) +21 + j*(-33) +-46 + j*(14) +36 + j*(38) +23 + j*(-49) +-44 + j*(4) +50 + j*(33) +29 + j*(-98) +-134 + j*(-14) +22 + j*(192) +293 + j*(-10) +109 + j*(-337) +-204 + j*(-235) +-176 + j*(-43) +-158 + j*(-93) +-324 + j*(-2) +-251 + j*(276) +33 + j*(293) +100 + j*(108) +23 + j*(74) +47 + j*(98) +50 + j*(59) +31 + j*(103) +155 + j*(132) +241 + j*(-50) +63 + j*(-202) +-117 + j*(-78) +-51 + j*(88) +74 + j*(75) +110 + j*(15) +144 + j*(-58) +79 + j*(-200) +-139 + j*(-191) +-190 + j*(33) +-8 + j*(96) +7 + j*(-53) +-159 + j*(1) +-78 + j*(213) +152 + j*(168) +161 + j*(-13) +86 + j*(-45) +86 + j*(-71) +-5 + j*(-117) +-72 + j*(0) +64 + j*(57) +101 + j*(-98) +-54 + j*(-114) +-33 + j*(19) +74 + j*(-61) +-57 + j*(-158) +-146 + j*(-16) +-35 + j*(30) +-71 + j*(-45) +-130 + j*(91) +86 + j*(144) +123 + j*(-132) +-199 + j*(-146) +-197 + j*(214) +173 + j*(206) +166 + j*(-143) +-147 + j*(-138) +-156 + j*(122) +28 + j*(158) +74 + j*(79) +92 + j*(67) +139 + j*(16) +139 + j*(-55) +127 + j*(-139) +9 + j*(-258) +-230 + j*(-187) +-246 + j*(93) +-12 + j*(165) +50 + j*(8) +-50 + j*(1) +4 + j*(67) +45 + j*(-31) +-97 + j*(-49) +-100 + j*(129) +100 + j*(128) +93 + j*(-74) +-117 + j*(-50) +-92 + j*(185) +175 + j*(204) +278 + j*(-47) +117 + j*(-231) +-79 + j*(-203) +-175 + j*(-86) +-193 + j*(62) +-84 + j*(206) +129 + j*(198) +231 + j*(-6) +102 + j*(-179) +-88 + j*(-148) +-156 + j*(2) +-88 + j*(147) +98 + j*(192) +267 + j*(23) +168 + j*(-235) +-110 + j*(-236) +-180 + j*(1) +-2 + j*(80) +46 + j*(-66) +-109 + j*(-97) +-160 + j*(77) +1 + j*(176) +139 + j*(74) +117 + j*(-64) +33 + j*(-117) +-59 + j*(-117) +-161 + j*(-37) +-133 + j*(150) +104 + j*(219) +291 + j*(-16) +139 + j*(-310) +-199 + j*(-314) +-378 + j*(-46) +-284 + j*(239) +-25 + j*(341) +194 + j*(214) +214 + j*(10) +110 + j*(-87) +23 + j*(-93) +-47 + j*(-53) +-41 + j*(39) +58 + j*(28) +17 + j*(-89) +-136 + j*(-11) +-37 + j*(188) +182 + j*(91) +91 + j*(-105) +-46 + j*(6) +108 + j*(94) +180 + j*(-86) +37 + j*(-130) +85 + j*(-60) +135 + j*(-260) +-185 + j*(-387) +-421 + j*(-73) +-231 + j*(197) +-42 + j*(148) +-9 + j*(95) +47 + j*(28) +-54 + j*(-99) +-247 + j*(40) +-104 + j*(290) +146 + j*(186) +71 + j*(12) +3 + j*(115) +165 + j*(115) +146 + j*(-84) +-47 + j*(-49) +16 + j*(131) +212 + j*(54) +180 + j*(-160) +-13 + j*(-214) +-140 + j*(-92) +-93 + j*(52) +25 + j*(36) +-27 + j*(-58) +-121 + j*(58) +49 + j*(178) +180 + j*(-21) +-45 + j*(-127) +-101 + j*(151) +255 + j*(185) +320 + j*(-228) +-79 + j*(-355) +-247 + j*(-40) +-45 + j*(126) +95 + j*(31) +101 + j*(-80) +32 + j*(-185) +-139 + j*(-178) +-192 + j*(-7) +-73 + j*(47) +-81 + j*(-33) +-180 + j*(51) +-69 + j*(201) +110 + j*(124) +83 + j*(-42) +-50 + j*(-42) +-71 + j*(80) +69 + j*(144) +213 + j*(-8) +88 + j*(-250) +-221 + j*(-203) +-274 + j*(106) +-42 + j*(234) +100 + j*(119) +87 + j*(26) +66 + j*(-14) +21 + j*(-45) +-20 + j*(-9) +13 + j*(8) +4 + j*(-40) +-59 + j*(-20) +-49 + j*(38) +-25 + j*(42) +-22 + j*(71) +52 + j*(76) +53 + j*(-28) +-86 + j*(-1) +-26 + j*(194) +226 + j*(132) +187 + j*(-146) +-77 + j*(-126) +-53 + j*(110) +164 + j*(88) +166 + j*(-105) +30 + j*(-148) +-29 + j*(-98) +-57 + j*(-61) +-66 + j*(14) +28 + j*(76) +149 + j*(-6) +115 + j*(-182) +-88 + j*(-221) +-185 + j*(-33) +-21 + j*(79) +82 + j*(-96) +-125 + j*(-214) +-287 + j*(-10) +-146 + j*(173) +-12 + j*(116) +-25 + j*(76) +11 + j*(93) +31 + j*(28) +-45 + j*(43) +14 + j*(156) +173 + j*(86) +139 + j*(-89) +6 + j*(-100) +-23 + j*(-38) +-27 + j*(-8) +13 + j*(44) +117 + j*(-16) +51 + j*(-180) +-146 + j*(-136) +-134 + j*(37) +-23 + j*(21) +-78 + j*(-34) +-112 + j*(47) +-48 + j*(56) +-108 + j*(28) +-144 + j*(182) +54 + j*(279) +195 + j*(128) +129 + j*(27) +136 + j*(62) +218 + j*(-19) +161 + j*(-156) +49 + j*(-178) +-12 + j*(-179) +-121 + j*(-172) +-220 + j*(-45) +-171 + j*(123) +-26 + j*(193) +110 + j*(132) +129 + j*(3) +39 + j*(-29) +65 + j*(55) +211 + j*(-35) +109 + j*(-274) +-185 + j*(-220) +-183 + j*(54) +26 + j*(59) +-7 + j*(-98) +-143 + j*(-27) +-61 + j*(94) +26 + j*(10) +-83 + j*(-47) +-158 + j*(103) +-2 + j*(258) +251 + j*(173) +300 + j*(-131) +28 + j*(-305) +-199 + j*(-117) +-73 + j*(78) +47 + j*(-50) +-134 + j*(-120) +-199 + j*(110) +38 + j*(192) +126 + j*(-15) +-35 + j*(-98) +-124 + j*(2) +-126 + j*(100) +-49 + j*(239) +209 + j*(235) +294 + j*(-68) +13 + j*(-176) +-31 + j*(79) +262 + j*(23) +144 + j*(-357) +-298 + j*(-252) +-250 + j*(172) +72 + j*(168) +68 + j*(1) +73 + j*(57) +232 + j*(-107) +-36 + j*(-400) +-446 + j*(-110) +-196 + j*(342) +204 + j*(129) +-45 + j*(-166) +-267 + j*(185) +194 + j*(424) +521 + j*(-70) +105 + j*(-478) +-304 + j*(-208) +-165 + j*(102) +0 + j*(15) +-111 + j*(-33) +-99 + j*(129) +104 + j*(97) +68 + j*(-135) +-190 + j*(-107) +-194 + j*(148) +14 + j*(179) +18 + j*(48) +-71 + j*(122) +74 + j*(238) +245 + j*(97) +179 + j*(-89) +52 + j*(-107) +-18 + j*(-81) +-87 + j*(2) +-12 + j*(144) +167 + j*(89) +122 + j*(-79) +-1 + j*(-8) +138 + j*(82) +232 + j*(-118) +33 + j*(-228) +-41 + j*(-73) +85 + j*(-91) +-19 + j*(-235) +-194 + j*(-97) +-62 + j*(70) +66 + j*(-56) +-55 + j*(-144) +-111 + j*(-49) +-57 + j*(-36) +-92 + j*(-65) +-105 + j*(-19) +-88 + j*(-44) +-190 + j*(-34) +-196 + j*(132) +-33 + j*(165) +-22 + j*(61) +-68 + j*(141) +124 + j*(167) +168 + j*(-108) +-149 + j*(-180) +-244 + j*(127) +-2 + j*(221) +33 + j*(65) +-71 + j*(139) +95 + j*(257) +263 + j*(78) +151 + j*(-98) +33 + j*(-74) +5 + j*(-63) +-97 + j*(-25) +-93 + j*(167) +140 + j*(245) +302 + j*(45) +200 + j*(-151) +46 + j*(-136) +48 + j*(-49) +122 + j*(-85) +79 + j*(-211) +-98 + j*(-222) +-182 + j*(-57) +-70 + j*(57) +24 + j*(-21) +-59 + j*(-98) +-161 + j*(4) +-69 + j*(160) +134 + j*(116) +154 + j*(-108) +-57 + j*(-182) +-161 + j*(-10) +-42 + j*(93) +23 + j*(33) +18 + j*(42) +133 + j*(21) +133 + j*(-211) +-172 + j*(-284) +-332 + j*(1) +-152 + j*(195) +-28 + j*(141) +-17 + j*(161) +130 + j*(177) +220 + j*(-8) +100 + j*(-139) +10 + j*(-124) +-48 + j*(-148) +-190 + j*(-85) +-171 + j*(121) +27 + j*(141) +56 + j*(-9) +-40 + j*(-22) +-37 + j*(16) +-66 + j*(1) +-113 + j*(91) +0 + j*(174) +98 + j*(89) +57 + j*(23) +44 + j*(35) +30 + j*(5) +-23 + j*(73) +120 + j*(161) +271 + j*(-38) +64 + j*(-243) +-151 + j*(-73) +-24 + j*(100) +72 + j*(12) +13 + j*(2) +74 + j*(50) +113 + j*(-50) +20 + j*(-53) +93 + j*(24) +184 + j*(-129) +-1 + j*(-242) +-82 + j*(-81) +67 + j*(-92) +-29 + j*(-284) +-260 + j*(-185) +-206 + j*(-7) +-161 + j*(-64) +-305 + j*(-4) +-243 + j*(209) +-74 + j*(191) +-119 + j*(148) +-81 + j*(298) +144 + j*(272) +154 + j*(89) +76 + j*(119) +211 + j*(135) +238 + j*(-69) +45 + j*(-116) +28 + j*(28) +146 + j*(1) +110 + j*(-107) +45 + j*(-105) +16 + j*(-117) +-69 + j*(-81) +-28 + j*(48) +132 + j*(-17) +42 + j*(-207) +-167 + j*(-116) +-84 + j*(81) +78 + j*(-4) +-19 + j*(-136) +-136 + j*(-39) +-55 + j*(69) +43 + j*(12) +22 + j*(-86) +-69 + j*(-117) +-155 + j*(-61) +-162 + j*(35) +-115 + j*(83) +-90 + j*(102) +-52 + j*(128) +-16 + j*(120) +-25 + j*(138) +55 + j*(226) +257 + j*(161) +288 + j*(-102) +76 + j*(-227) +-66 + j*(-138) +-85 + j*(-68) +-132 + j*(-14) +-106 + j*(112) +21 + j*(136) +40 + j*(70) +32 + j*(154) +274 + j*(192) +470 + j*(-161) +147 + j*(-558) +-358 + j*(-407) +-404 + j*(30) +-165 + j*(161) +-110 + j*(119) +-52 + j*(228) +209 + j*(174) +204 + j*(-175) +-187 + j*(-217) +-269 + j*(175) +78 + j*(296) +209 + j*(49) +89 + j*(-22) +134 + j*(-6) +108 + j*(-174) +-145 + j*(-147) +-117 + j*(135) +160 + j*(94) +94 + j*(-165) +-141 + j*(-80) +-43 + j*(127) +132 + j*(31) +54 + j*(-102) +-30 + j*(-47) +19 + j*(-6) +48 + j*(-57) +17 + j*(-117) +-84 + j*(-141) +-181 + j*(-30) +-98 + j*(112) +36 + j*(63) +11 + j*(-26) +-16 + j*(-16) +-29 + j*(-71) +-196 + j*(-40) +-182 + j*(252) +190 + j*(307) +325 + j*(-54) +77 + j*(-206) +13 + j*(-109) +13 + j*(-216) +-254 + j*(-208) +-281 + j*(120) +9 + j*(128) +-92 + j*(-108) +-335 + j*(128) +-39 + j*(413) +235 + j*(158) +40 + j*(-4) +47 + j*(185) +272 + j*(43) +58 + j*(-199) +-151 + j*(68) +185 + j*(223) +320 + j*(-168) +-80 + j*(-320) +-244 + j*(13) +-34 + j*(158) +46 + j*(89) +90 + j*(115) +222 + j*(21) +141 + j*(-165) +-11 + j*(-110) +69 + j*(-47) +57 + j*(-207) +-177 + j*(-183) +-182 + j*(69) +19 + j*(83) +4 + j*(-45) +-62 + j*(29) +73 + j*(46) +56 + j*(-146) +-194 + j*(-108) +-160 + j*(185) +148 + j*(170) +151 + j*(-126) +-126 + j*(-132) +-126 + j*(131) +123 + j*(138) +142 + j*(-78) +-23 + j*(-88) +12 + j*(37) +146 + j*(-54) +37 + j*(-241) +-188 + j*(-173) +-185 + j*(35) +-38 + j*(55) +-45 + j*(-38) +-124 + j*(16) +-33 + j*(112) +83 + j*(-2) +-41 + j*(-153) +-229 + j*(-45) +-171 + j*(152) +-30 + j*(144) +-42 + j*(91) +-32 + j*(158) +83 + j*(134) +56 + j*(16) +-47 + j*(80) +69 + j*(199) +236 + j*(71) +161 + j*(-123) +-4 + j*(-136) +-93 + j*(-64) +-148 + j*(62) +-47 + j*(245) +218 + j*(224) +298 + j*(-30) +145 + j*(-163) +47 + j*(-138) +-21 + j*(-137) +-120 + j*(-38) +-23 + j*(128) +176 + j*(43) +117 + j*(-156) +-56 + j*(-127) +-53 + j*(-14) +-11 + j*(-1) +14 + j*(35) +124 + j*(-1) +84 + j*(-180) +-141 + j*(-144) +-107 + j*(107) +157 + j*(79) +155 + j*(-175) +-37 + j*(-204) +-59 + j*(-121) +-61 + j*(-178) +-214 + j*(-185) +-306 + j*(-16) +-241 + j*(144) +-115 + j*(222) +52 + j*(216) +165 + j*(67) +101 + j*(-112) +-72 + j*(-145) +-185 + j*(-23) +-122 + j*(134) +55 + j*(108) +33 + j*(-105) +-250 + j*(-77) +-265 + j*(286) +128 + j*(386) +296 + j*(48) +64 + j*(-122) +-53 + j*(13) +15 + j*(66) +23 + j*(66) +108 + j*(94) +180 + j*(-81) +-65 + j*(-205) +-232 + j*(86) +78 + j*(267) +239 + j*(-42) +-71 + j*(-153) +-117 + j*(177) +238 + j*(168) +198 + j*(-204) +-176 + j*(-141) +-97 + j*(228) +262 + j*(150) +208 + j*(-185) +-86 + j*(-157) +-82 + j*(98) +142 + j*(136) +242 + j*(-37) +164 + j*(-181) +35 + j*(-193) +2 + j*(-112) +82 + j*(-119) +57 + j*(-270) +-162 + j*(-302) +-274 + j*(-95) +-132 + j*(29) +-64 + j*(-79) +-197 + j*(-99) +-213 + j*(50) +-98 + j*(53) +-172 + j*(-28) +-287 + j*(146) +-75 + j*(344) +168 + j*(168) +29 + j*(-42) +-130 + j*(121) +88 + j*(276) +290 + j*(46) +116 + j*(-192) +-108 + j*(-100) +-81 + j*(66) +20 + j*(63) +8 + j*(11) +-29 + j*(52) +40 + j*(115) +158 + j*(41) +110 + j*(-136) +-104 + j*(-132) +-139 + j*(93) +78 + j*(148) +141 + j*(-59) +-54 + j*(-121) +-123 + j*(51) +1 + j*(128) +66 + j*(78) +93 + j*(68) +163 + j*(-1) +104 + j*(-146) +-76 + j*(-124) +-93 + j*(61) +79 + j*(119) +188 + j*(-23) +113 + j*(-179) +-43 + j*(-187) +-100 + j*(-78) +-45 + j*(-51) +-98 + j*(-113) +-233 + j*(1) +-123 + j*(232) +156 + j*(174) +148 + j*(-90) +-66 + j*(-91) +-35 + j*(91) +155 + j*(33) +121 + j*(-197) +-119 + j*(-256) +-310 + j*(-78) +-269 + j*(197) +3 + j*(300) +182 + j*(91) +19 + j*(-75) +-105 + j*(106) +130 + j*(225) +284 + j*(-35) +54 + j*(-224) +-133 + j*(-47) +-6 + j*(124) +160 + j*(51) +171 + j*(-109) +57 + j*(-223) +-130 + j*(-194) +-180 + j*(4) +-11 + j*(92) +74 + j*(-50) +-52 + j*(-118) +-97 + j*(-11) +-3 + j*(7) +8 + j*(-91) +-86 + j*(-139) +-194 + j*(-109) +-279 + j*(10) +-231 + j*(179) +-83 + j*(216) +-47 + j*(160) +-45 + j*(217) +106 + j*(235) +167 + j*(57) +-2 + j*(1) +-26 + j*(185) +186 + j*(215) +257 + j*(21) +141 + j*(-59) +119 + j*(-13) +165 + j*(-59) +110 + j*(-144) +8 + j*(-139) +-33 + j*(-65) +11 + j*(-12) +63 + j*(-57) +-11 + j*(-122) +-100 + j*(-14) +40 + j*(100) +182 + j*(-69) +-8 + j*(-233) +-179 + j*(-41) +19 + j*(117) +161 + j*(-88) +-35 + j*(-218) +-136 + j*(-60) +-17 + j*(-28) +-75 + j*(-149) +-241 + j*(-43) +-153 + j*(168) +45 + j*(142) +80 + j*(20) +69 + j*(-28) +76 + j*(-134) +-96 + j*(-247) +-325 + j*(-105) +-283 + j*(164) +-85 + j*(204) +-66 + j*(121) +-98 + j*(215) +92 + j*(301) +265 + j*(112) +143 + j*(-83) +3 + j*(-4) +103 + j*(76) +180 + j*(-63) +59 + j*(-177) +-62 + j*(-136) +-111 + j*(-74) +-144 + j*(11) +-81 + j*(103) +1 + j*(78) +-28 + j*(57) +13 + j*(127) +128 + j*(42) +-3 + j*(-99) +-172 + j*(89) +55 + j*(308) +307 + j*(102) +168 + j*(-109) +77 + j*(-8) +207 + j*(-42) +105 + j*(-216) +-57 + j*(-90) +122 + j*(7) +168 + j*(-257) +-159 + j*(-298) +-193 + j*(23) +97 + j*(0) +6 + j*(-298) +-320 + j*(-202) +-291 + j*(93) +-113 + j*(110) +-132 + j*(59) +-149 + j*(163) +-18 + j*(245) +150 + j*(180) +192 + j*(-21) +-12 + j*(-139) +-167 + j*(93) +133 + j*(296) +422 + j*(-64) +78 + j*(-441) +-328 + j*(-182) +-164 + j*(155) +32 + j*(40) +-94 + j*(-28) +-88 + j*(132) +64 + j*(98) +8 + j*(21) +30 + j*(139) +245 + j*(49) +146 + j*(-260) +-206 + j*(-195) +-180 + j*(150) +134 + j*(155) +177 + j*(-130) +-66 + j*(-232) +-235 + j*(-58) +-152 + j*(147) +47 + j*(132) +57 + j*(-49) +-119 + j*(-60) +-140 + j*(104) +-33 + j*(127) +-69 + j*(110) +-46 + j*(278) +240 + j*(312) +383 + j*(20) +192 + j*(-167) +70 + j*(-82) +132 + j*(-64) +102 + j*(-156) +2 + j*(-146) +-12 + j*(-86) +6 + j*(-78) +10 + j*(-89) +1 + j*(-121) +-66 + j*(-136) +-112 + j*(-70) +-74 + j*(-28) +-65 + j*(-53) +-93 + j*(-38) +-75 + j*(-33) +-134 + j*(-76) +-257 + j*(40) +-152 + j*(264) +122 + j*(228) +159 + j*(-25) +-31 + j*(-98) +-112 + j*(28) +-53 + j*(109) +6 + j*(115) +55 + j*(113) +119 + j*(81) +160 + j*(-12) +98 + j*(-134) +-69 + j*(-132) +-108 + j*(42) +71 + j*(84) +102 + j*(-123) +-149 + j*(-164) +-233 + j*(99) +-30 + j*(226) +82 + j*(144) +124 + j*(140) +285 + j*(53) +253 + j*(-241) +-65 + j*(-312) +-187 + j*(-81) +-78 + j*(-13) +-146 + j*(-58) +-225 + j*(144) +30 + j*(315) +274 + j*(113) +185 + j*(-124) +39 + j*(-122) +31 + j*(-100) +-21 + j*(-143) +-119 + j*(-92) +-108 + j*(5) +-59 + j*(8) +-90 + j*(-4) +-119 + j*(73) +-38 + j*(153) +69 + j*(119) +79 + j*(35) +44 + j*(34) +98 + j*(56) +162 + j*(-49) +58 + j*(-182) +-121 + j*(-129) +-134 + j*(50) +6 + j*(117) +101 + j*(33) +76 + j*(-61) +10 + j*(-74) +-4 + j*(-46) +1 + j*(-69) +-63 + j*(-79) +-99 + j*(14) +19 + j*(67) +86 + j*(-82) +-101 + j*(-184) +-262 + j*(23) +-74 + j*(246) +199 + j*(108) +130 + j*(-200) +-197 + j*(-220) +-322 + j*(87) +-86 + j*(292) +134 + j*(148) +47 + j*(-25) +-66 + j*(71) +64 + j*(151) +130 + j*(-6) +-42 + j*(-47) +-55 + j*(150) +165 + j*(156) +183 + j*(-57) +16 + j*(-71) +38 + j*(48) +134 + j*(-11) +57 + j*(-99) +-16 + j*(-20) +64 + j*(59) +183 + j*(12) +243 + j*(-139) +146 + j*(-344) +-136 + j*(-390) +-310 + j*(-160) +-190 + j*(20) +-101 + j*(-61) +-244 + j*(-89) +-314 + j*(119) +-135 + j*(274) +37 + j*(193) +9 + j*(93) +-30 + j*(167) +136 + j*(244) +330 + j*(52) +206 + j*(-245) +-100 + j*(-232) +-156 + j*(-1) +-20 + j*(57) +-2 + j*(-8) +-21 + j*(8) +9 + j*(-23) +-84 + j*(-71) +-172 + j*(70) +-40 + j*(197) +71 + j*(134) +69 + j*(122) +204 + j*(131) +289 + j*(-105) +48 + j*(-267) +-117 + j*(-80) +29 + j*(9) +35 + j*(-146) +-147 + j*(-115) +-127 + j*(57) +-21 + j*(53) +-33 + j*(38) +35 + j*(74) +91 + j*(-54) +-83 + j*(-115) +-143 + j*(86) +59 + j*(139) +90 + j*(-30) +-27 + j*(-8) +72 + j*(67) +134 + j*(-110) +-86 + j*(-178) +-147 + j*(43) +63 + j*(65) +36 + j*(-163) +-241 + j*(-127) +-261 + j*(175) +-10 + j*(271) +105 + j*(127) +33 + j*(82) +76 + j*(185) +282 + j*(139) +342 + j*(-134) +117 + j*(-313) +-91 + j*(-217) +-93 + j*(-85) +-62 + j*(-66) +-66 + j*(-48) +-45 + j*(-54) +-103 + j*(-93) +-198 + j*(10) +-96 + j*(158) +62 + j*(83) +-5 + j*(-36) +-83 + j*(56) +40 + j*(118) +115 + j*(-21) +-5 + j*(-117) +-124 + j*(-46) +-124 + j*(76) +-24 + j*(152) +101 + j*(85) +59 + j*(-54) +-82 + j*(-16) +-40 + j*(128) +96 + j*(98) +89 + j*(8) +78 + j*(14) +117 + j*(-49) +11 + j*(-134) +-95 + j*(-16) +24 + j*(91) +124 + j*(-26) +34 + j*(-121) +-38 + j*(-86) +-65 + j*(-70) +-132 + j*(-6) +-73 + j*(136) +105 + j*(129) +165 + j*(-20) +114 + j*(-127) +27 + j*(-206) +-149 + j*(-214) +-279 + j*(-35) +-199 + j*(165) +-30 + j*(222) +127 + j*(180) +237 + j*(3) +117 + j*(-216) +-130 + j*(-172) +-134 + j*(24) +-23 + j*(24) +-66 + j*(-16) +-55 + j*(66) +30 + j*(5) +-110 + j*(-68) +-191 + j*(171) +123 + j*(295) +298 + j*(-30) +11 + j*(-223) +-153 + j*(-2) +4 + j*(105) +43 + j*(1) +-23 + j*(31) +62 + j*(81) +114 + j*(-18) +42 + j*(-70) +21 + j*(-55) +-17 + j*(-88) +-118 + j*(-25) +-51 + j*(135) +152 + j*(98) +173 + j*(-116) +-1 + j*(-206) +-134 + j*(-121) +-135 + j*(-4) +-72 + j*(30) +-74 + j*(0) +-143 + j*(57) +-77 + j*(211) +144 + j*(200) +202 + j*(-10) +59 + j*(-81) +58 + j*(10) +178 + j*(-93) +22 + j*(-322) +-337 + j*(-206) +-330 + j*(221) +78 + j*(327) +239 + j*(-14) +-35 + j*(-155) +-123 + j*(98) +151 + j*(136) +168 + j*(-165) +-141 + j*(-185) +-166 + j*(93) +47 + j*(113) +43 + j*(-6) +30 + j*(49) +165 + j*(-33) +17 + j*(-255) +-269 + j*(-81) +-86 + j*(231) +225 + j*(40) +30 + j*(-259) +-252 + j*(-91) +-139 + j*(146) +13 + j*(98) +14 + j*(58) +77 + j*(35) +42 + j*(-102) +-147 + j*(-42) +-55 + j*(191) +230 + j*(76) +115 + j*(-262) +-256 + j*(-185) +-249 + j*(168) +-23 + j*(28) +142 + j*(89) +243 + j*(-152) +-11 + j*(-301) +-160 + j*(-95) +-9 + j*(-13) +-18 + j*(-156) +-180 + j*(-100) +-137 + j*(49) +-59 + j*(32) +-93 + j*(57) +9 + j*(139) +139 + j*(30) +85 + j*(-95) +49 + j*(-113) +-1 + j*(-236) +-292 + j*(-232) +-390 + j*(163) +18 + j*(347) +232 + j*(-16) +-69 + j*(-199) +-178 + j*(31) +-9 + j*(29) +-153 + j*(-123) +-350 + j*(132) +-78 + j*(395) +177 + j*(175) +-3 + j*(17) +-54 + j*(233) +233 + j*(250) +274 + j*(-47) +47 + j*(-99) +62 + j*(39) +161 + j*(-92) +-80 + j*(-226) +-301 + j*(77) +-18 + j*(404) +385 + j*(230) +369 + j*(-156) +106 + j*(-264) +-22 + j*(-159) +-18 + j*(-98) +-25 + j*(-91) +-62 + j*(-67) +-71 + j*(3) +14 + j*(64) +128 + j*(-19) +71 + j*(-185) +-119 + j*(-175) +-159 + j*(-13) +-60 + j*(39) +-55 + j*(-1) +-75 + j*(60) +33 + j*(105) +115 + j*(1) +66 + j*(-100) +3 + j*(-122) +-59 + j*(-150) +-186 + j*(-126) +-264 + j*(36) +-168 + j*(209) +22 + j*(231) +126 + j*(107) +83 + j*(4) +36 + j*(27) +107 + j*(28) +112 + j*(-110) +-60 + j*(-147) +-120 + j*(21) +26 + j*(76) +58 + j*(-45) +-23 + j*(-40) +44 + j*(-8) +48 + j*(-170) +-195 + j*(-199) +-287 + j*(54) +-105 + j*(174) +-40 + j*(91) +-74 + j*(122) +21 + j*(158) +40 + j*(59) +-60 + j*(115) +76 + j*(275) +334 + j*(137) +289 + j*(-160) +68 + j*(-228) +-31 + j*(-156) +-88 + j*(-124) +-161 + j*(-33) +-124 + j*(107) +8 + j*(153) +107 + j*(76) +85 + j*(-28) +-11 + j*(-13) +36 + j*(100) +209 + j*(28) +150 + j*(-202) +-91 + j*(-184) +-93 + j*(16) +47 + j*(-1) +-6 + j*(-98) +-74 + j*(-21) +4 + j*(15) +9 + j*(-45) +-18 + j*(-18) +45 + j*(-42) +-28 + j*(-154) +-188 + j*(-57) +-95 + j*(119) +54 + j*(37) +-26 + j*(-59) +-64 + j*(36) +48 + j*(21) +4 + j*(-108) +-123 + j*(-68) +-115 + j*(13) +-122 + j*(18) +-150 + j*(101) +-64 + j*(182) +11 + j*(168) +74 + j*(197) +255 + j*(128) +258 + j*(-156) +-20 + j*(-245) +-132 + j*(-64) +-83 + j*(-25) +-188 + j*(30) +-97 + j*(302) +292 + j*(246) +298 + j*(-159) +-21 + j*(-179) +32 + j*(19) +153 + j*(-161) +-119 + j*(-269) +-227 + j*(11) +1 + j*(71) +-40 + j*(-97) +-175 + j*(52) +53 + j*(170) +153 + j*(-105) +-145 + j*(-195) +-250 + j*(85) +-49 + j*(207) +48 + j*(129) +69 + j*(92) +109 + j*(19) +41 + j*(-40) +16 + j*(28) +91 + j*(10) +21 + j*(-59) +-27 + j*(63) +158 + j*(100) +209 + j*(-114) +35 + j*(-167) +47 + j*(-66) +111 + j*(-199) +-112 + j*(-295) +-257 + j*(-64) +-81 + j*(86) +22 + j*(-27) +-33 + j*(-78) +-40 + j*(-95) +-135 + j*(-163) +-308 + j*(-43) +-243 + j*(182) +-76 + j*(193) +-74 + j*(161) +-16 + j*(262) +194 + j*(226) +250 + j*(6) +122 + j*(-113) +16 + j*(-117) +-87 + j*(-83) +-140 + j*(62) +-11 + j*(180) +116 + j*(110) +89 + j*(40) +112 + j*(82) +233 + j*(13) +198 + j*(-182) +-1 + j*(-221) +-87 + j*(-75) +7 + j*(4) +69 + j*(-75) +-1 + j*(-138) +-55 + j*(-95) +-35 + j*(-101) +-127 + j*(-163) +-291 + j*(-27) +-199 + j*(238) +83 + j*(233) +132 + j*(16) +-4 + j*(-6) +42 + j*(98) +173 + j*(21) +136 + j*(-142) +4 + j*(-189) +-103 + j*(-150) +-156 + j*(-56) +-114 + j*(25) +-72 + j*(-2) +-146 + j*(-1) +-158 + j*(125) +-50 + j*(185) +4 + j*(173) +88 + j*(221) +277 + j*(117) +223 + j*(-158) +-43 + j*(-142) +3 + j*(74) +201 + j*(-54) +4 + j*(-277) +-254 + j*(-63) +-64 + j*(196) +165 + j*(43) +50 + j*(-132) +-64 + j*(-62) +-34 + j*(-21) +-73 + j*(-23) +-63 + j*(88) +105 + j*(88) +138 + j*(-120) +-75 + j*(-207) +-221 + j*(-44) +-150 + j*(121) +-31 + j*(136) +4 + j*(95) +-1 + j*(103) +50 + j*(145) +151 + j*(125) +222 + j*(25) +218 + j*(-111) +110 + j*(-235) +-87 + j*(-225) +-169 + j*(-39) +-33 + j*(73) +58 + j*(-28) +-32 + j*(-81) +-56 + j*(-4) +0 + j*(-13) +-52 + j*(-40) +-47 + j*(54) +88 + j*(6) +-13 + j*(-171) +-248 + j*(-30) +-103 + j*(257) +195 + j*(141) +110 + j*(-98) +-19 + j*(-1) +159 + j*(16) +120 + j*(-291) +-305 + j*(-276) +-378 + j*(201) +63 + j*(371) +286 + j*(28) +67 + j*(-182) +-76 + j*(-67) +-17 + j*(-21) +-61 + j*(-85) +-170 + j*(4) +-101 + j*(160) +56 + j*(147) +92 + j*(47) +78 + j*(16) +103 + j*(-33) +47 + j*(-131) +-84 + j*(-116) +-113 + j*(-16) +-83 + j*(1) +-139 + j*(10) +-166 + j*(136) +-43 + j*(240) +93 + j*(202) +138 + j*(125) +150 + j*(73) +153 + j*(25) +153 + j*(-23) +118 + j*(-97) +-18 + j*(-105) +-68 + j*(83) +180 + j*(184) +353 + j*(-104) +77 + j*(-334) +-151 + j*(-103) +63 + j*(66) +168 + j*(-168) +-89 + j*(-233) +-119 + j*(25) +132 + j*(16) +107 + j*(-228) +-86 + j*(-214) +-54 + j*(-138) +-92 + j*(-265) +-349 + j*(-207) +-356 + j*(107) +-93 + j*(160) +-73 + j*(-28) +-248 + j*(10) +-212 + j*(209) +-37 + j*(228) +18 + j*(128) +-33 + j*(85) +-90 + j*(137) +-46 + j*(281) +199 + j*(336) +417 + j*(77) +261 + j*(-259) +-77 + j*(-247) +-156 + j*(1) +-24 + j*(88) +17 + j*(42) +16 + j*(64) +92 + j*(48) +74 + j*(-57) +-51 + j*(-31) +-7 + j*(107) +146 + j*(42) +68 + j*(-126) +-114 + j*(-33) +-16 + j*(158) +170 + j*(69) +87 + j*(-78) +-1 + j*(31) +176 + j*(82) +247 + j*(-149) +19 + j*(-266) +-98 + j*(-95) +27 + j*(-35) +33 + j*(-168) +-127 + j*(-173) +-180 + j*(-40) +-136 + j*(45) +-74 + j*(109) +67 + j*(114) +138 + j*(-57) +-23 + j*(-173) +-140 + j*(-45) +-43 + j*(23) +-66 + j*(-90) +-259 + j*(13) +-144 + j*(330) +278 + j*(287) +363 + j*(-161) +-17 + j*(-372) +-299 + j*(-127) +-216 + j*(142) +-33 + j*(185) +62 + j*(124) +99 + j*(53) +91 + j*(-22) +33 + j*(-68) +-33 + j*(-50) +-51 + j*(11) +7 + j*(47) +59 + j*(-15) +-10 + j*(-90) +-110 + j*(-23) +-59 + j*(87) +34 + j*(46) +-17 + j*(-21) +-74 + j*(53) +9 + j*(121) +81 + j*(61) +57 + j*(22) +82 + j*(31) +119 + j*(-49) +18 + j*(-129) +-86 + j*(-42) +-18 + j*(55) +60 + j*(-11) +-16 + j*(-70) +-66 + j*(14) +22 + j*(47) +23 + j*(-51) +-113 + j*(-11) +-48 + j*(196) +238 + j*(147) +247 + j*(-192) +-85 + j*(-257) +-155 + j*(30) +103 + j*(41) +40 + j*(-253) +-333 + j*(-172) +-313 + j*(243) +45 + j*(299) +109 + j*(74) +-7 + j*(95) +122 + j*(183) +224 + j*(11) +69 + j*(-73) +57 + j*(95) +303 + j*(52) +310 + j*(-268) +7 + j*(-387) +-173 + j*(-211) +-130 + j*(-76) +-92 + j*(-74) +-115 + j*(-60) +-124 + j*(-13) +-91 + j*(41) +-10 + j*(51) +42 + j*(-41) +-47 + j*(-139) +-182 + j*(-78) +-173 + j*(54) +-92 + j*(66) +-122 + j*(40) +-153 + j*(150) +-4 + j*(240) +147 + j*(111) +57 + j*(-50) +-78 + j*(25) +3 + j*(144) +118 + j*(59) +32 + j*(-44) +-53 + j*(49) +57 + j*(134) +166 + j*(28) +100 + j*(-100) +-23 + j*(-94) +-69 + j*(-5) +-24 + j*(75) +73 + j*(71) +105 + j*(-28) +19 + j*(-87) +-48 + j*(-28) +-14 + j*(33) +34 + j*(14) +28 + j*(-35) +-40 + j*(-55) +-118 + j*(28) +-57 + j*(181) +138 + j*(190) +226 + j*(35) +182 + j*(-69) +153 + j*(-136) +42 + j*(-231) +-151 + j*(-138) +-90 + j*(93) +134 + j*(37) +58 + j*(-165) +-120 + j*(-41) +66 + j*(122) +249 + j*(-115) +25 + j*(-331) +-183 + j*(-188) +-133 + j*(-76) +-165 + j*(-93) +-202 + j*(42) +-27 + j*(93) +-12 + j*(-100) +-242 + j*(-66) +-185 + j*(194) +54 + j*(130) +-50 + j*(-53) +-193 + j*(125) +37 + j*(274) +191 + j*(54) +31 + j*(-66) +-7 + j*(38) +71 + j*(-16) +-44 + j*(-88) +-101 + j*(44) +20 + j*(53) +-57 + j*(-65) +-210 + j*(97) +-16 + j*(304) +215 + j*(141) +97 + j*(-46) +-6 + j*(60) +120 + j*(99) +136 + j*(-38) +18 + j*(-38) +42 + j*(48) +107 + j*(1) +57 + j*(-47) +26 + j*(5) +81 + j*(33) +141 + j*(0) +173 + j*(-95) +95 + j*(-210) +-70 + j*(-194) +-105 + j*(-44) +3 + j*(1) +30 + j*(-78) +-32 + j*(-98) +-53 + j*(-66) +-62 + j*(-49) +-61 + j*(-18) +-31 + j*(-13) +-39 + j*(-23) +-13 + j*(19) +91 + j*(-51) +-1 + j*(-260) +-320 + j*(-216) +-397 + j*(143) +-115 + j*(337) +115 + j*(214) +139 + j*(40) +49 + j*(-75) +-118 + j*(-44) +-129 + j*(173) +124 + j*(238) +250 + j*(3) +105 + j*(-143) +11 + j*(-124) +-68 + j*(-156) +-247 + j*(-36) +-146 + j*(260) +207 + j*(206) +195 + j*(-151) +-132 + j*(-167) +-176 + j*(112) +36 + j*(192) +151 + j*(66) +110 + j*(-78) +-63 + j*(-106) +-148 + j*(112) +112 + j*(264) +325 + j*(5) +118 + j*(-218) +-31 + j*(-66) +116 + j*(-28) +83 + j*(-211) +-91 + j*(-182) +-86 + j*(-112) +-183 + j*(-161) +-344 + j*(81) +-52 + j*(357) +272 + j*(78) +11 + j*(-212) +-203 + j*(57) +82 + j*(208) +194 + j*(-78) +-54 + j*(-166) +-121 + j*(7) +-37 + j*(44) +-34 + j*(38) +3 + j*(48) +-25 + j*(-1) +-94 + j*(120) +136 + j*(245) +339 + j*(-54) +30 + j*(-305) +-209 + j*(-25) +49 + j*(156) +170 + j*(-87) +-35 + j*(-169) +-88 + j*(-43) +-66 + j*(-39) +-115 + j*(36) +23 + j*(114) +80 + j*(-83) +-192 + j*(-81) +-143 + j*(287) +305 + j*(229) +269 + j*(-241) +-158 + j*(-226) +-134 + j*(123) +133 + j*(91) +112 + j*(-100) +21 + j*(-112) +-12 + j*(-141) +-151 + j*(-126) +-176 + j*(70) +25 + j*(135) +128 + j*(-49) +-12 + j*(-217) +-269 + j*(-181) +-410 + j*(129) +-139 + j*(447) +255 + j*(280) +152 + j*(-53) +-63 + j*(101) +237 + j*(246) +395 + j*(-192) +-105 + j*(-402) +-348 + j*(83) +75 + j*(325) +288 + j*(1) +97 + j*(-154) +42 + j*(-95) +8 + j*(-169) +-168 + j*(-93) +-78 + j*(130) +153 + j*(20) +26 + j*(-214) +-209 + j*(-102) +-149 + j*(105) +-20 + j*(105) +6 + j*(71) +43 + j*(59) +47 + j*(8) +25 + j*(18) +91 + j*(8) +78 + j*(-132) +-117 + j*(-150) +-182 + j*(47) +-35 + j*(133) +28 + j*(59) +6 + j*(62) +74 + j*(63) +69 + j*(-37) +-41 + j*(-14) +18 + j*(109) +173 + j*(21) +81 + j*(-160) +-103 + j*(-80) +-34 + j*(78) +88 + j*(11) +18 + j*(-66) +-6 + j*(19) +110 + j*(-4) +63 + j*(-157) +-106 + j*(-113) +-64 + j*(42) +68 + j*(-10) +10 + j*(-130) +-93 + j*(-92) +-92 + j*(-38) +-109 + j*(-23) +-107 + j*(44) +-27 + j*(44) +-62 + j*(-31) +-153 + j*(49) +-58 + j*(158) +23 + j*(69) +-84 + j*(64) +-25 + j*(244) +223 + j*(180) +191 + j*(-71) +10 + j*(-33) +115 + j*(78) +214 + j*(-107) +6 + j*(-233) +-123 + j*(-74) +-34 + j*(-1) +-45 + j*(-49) +-81 + j*(33) +39 + j*(55) +24 + j*(-92) +-163 + j*(-40) +-100 + j*(196) +172 + j*(156) +171 + j*(-119) +-78 + j*(-161) +-156 + j*(51) +6 + j*(148) +101 + j*(45) +38 + j*(-13) +35 + j*(58) +165 + j*(34) +175 + j*(-161) +-36 + j*(-250) +-189 + j*(-88) +-101 + j*(69) +21 + j*(22) +-23 + j*(-78) +-138 + j*(-33) +-126 + j*(103) +-8 + j*(134) +12 + j*(66) +-43 + j*(127) +112 + j*(260) +383 + j*(100) +330 + j*(-258) +23 + j*(-337) +-91 + j*(-199) +-110 + j*(-185) +-264 + j*(-117) +-245 + j*(149) +30 + j*(205) +112 + j*(-11) +-33 + j*(-68) +-39 + j*(21) +15 + j*(-33) +-98 + j*(-83) +-180 + j*(64) +-58 + j*(203) +113 + j*(162) +166 + j*(11) +74 + j*(-98) +-35 + j*(-45) +30 + j*(42) +125 + j*(-70) +-13 + j*(-211) +-194 + j*(-110) +-166 + j*(54) +-81 + j*(71) +-74 + j*(62) +-68 + j*(71) +-101 + j*(92) +-91 + j*(233) +141 + j*(305) +310 + j*(66) +131 + j*(-126) +1 + j*(6) +140 + j*(49) +129 + j*(-116) +-45 + j*(-67) +49 + j*(110) +257 + j*(-18) +165 + j*(-269) +-75 + j*(-278) +-187 + j*(-138) +-194 + j*(9) +-90 + j*(130) +77 + j*(91) +92 + j*(-62) +-18 + j*(-95) +-43 + j*(-37) +-19 + j*(-49) +-71 + j*(-74) +-126 + j*(-21) +-115 + j*(54) +-66 + j*(91) +-29 + j*(91) +-13 + j*(107) +62 + j*(142) +178 + j*(54) +115 + j*(-120) +-73 + j*(-76) +-18 + j*(118) +209 + j*(47) +165 + j*(-208) +-64 + j*(-236) +-146 + j*(-114) +-171 + j*(-52) +-197 + j*(86) +-19 + j*(215) +181 + j*(56) +65 + j*(-170) +-143 + j*(-106) +-127 + j*(49) +-51 + j*(53) +-61 + j*(43) +-43 + j*(68) +-45 + j*(40) +-124 + j*(97) +-59 + j*(291) +234 + j*(317) +419 + j*(34) +269 + j*(-258) +0 + j*(-274) +-101 + j*(-117) +-46 + j*(-37) +-21 + j*(-72) +-90 + j*(-83) +-137 + j*(1) +-93 + j*(83) +-21 + j*(95) +9 + j*(76) +27 + j*(77) +75 + j*(76) +117 + j*(24) +112 + j*(-40) +88 + j*(-76) +69 + j*(-136) +-57 + j*(-201) +-231 + j*(-71) +-143 + j*(190) +165 + j*(153) +162 + j*(-180) +-190 + j*(-209) +-260 + j*(144) +57 + j*(249) +159 + j*(-2) +-35 + j*(-54) +-25 + j*(131) +188 + j*(100) +193 + j*(-130) +9 + j*(-199) +-107 + j*(-110) +-122 + j*(3) +-39 + j*(104) +126 + j*(49) +95 + j*(-164) +-158 + j*(-164) +-190 + j*(103) +61 + j*(153) +91 + j*(-58) +-81 + j*(-35) +20 + j*(119) +177 + j*(-62) +-69 + j*(-240) +-276 + j*(49) +34 + j*(281) +285 + j*(-22) +19 + j*(-272) +-194 + j*(-66) +-27 + j*(69) +28 + j*(-104) +-188 + j*(-129) +-248 + j*(105) +-57 + j*(221) +81 + j*(108) +33 + j*(-18) +-84 + j*(-7) +-110 + j*(110) +-21 + j*(176) +41 + j*(153) +64 + j*(177) +202 + j*(193) +331 + j*(9) +216 + j*(-207) +10 + j*(-214) +-82 + j*(-117) +-124 + j*(-12) +-60 + j*(143) +165 + j*(153) +257 + j*(-86) +69 + j*(-237) +-88 + j*(-146) +-94 + j*(-47) +-86 + j*(23) +16 + j*(106) +173 + j*(-12) +57 + j*(-231) +-211 + j*(-134) +-149 + j*(158) +141 + j*(144) +181 + j*(-113) +-13 + j*(-198) +-105 + j*(-86) +-56 + j*(-25) +-36 + j*(-57) +-80 + j*(-63) +-96 + j*(-18) +-71 + j*(-6) +-88 + j*(-24) +-124 + j*(11) +-108 + j*(51) +-127 + j*(59) +-153 + j*(185) +56 + j*(325) +334 + j*(108) +181 + j*(-267) +-224 + j*(-204) +-241 + j*(168) +48 + j*(234) +113 + j*(47) +2 + j*(36) +62 + j*(136) +213 + j*(46) +154 + j*(-175) +-127 + j*(-190) +-233 + j*(129) +107 + j*(342) +432 + j*(21) +193 + j*(-389) +-214 + j*(-258) +-167 + j*(44) +-10 + j*(-9) +-145 + j*(-54) +-161 + j*(165) +77 + j*(206) +124 + j*(30) +33 + j*(39) +134 + j*(86) +187 + j*(-78) +29 + j*(-138) +6 + j*(-11) +123 + j*(-55) +44 + j*(-189) +-88 + j*(-116) +-22 + j*(-35) +0 + j*(-133) +-151 + j*(-132) +-167 + j*(40) +-13 + j*(62) +-16 + j*(-68) +-141 + j*(-30) +-83 + j*(93) +20 + j*(7) +-124 + j*(-78) +-226 + j*(129) +3 + j*(272) +150 + j*(62) +-44 + j*(-34) +-73 + j*(190) +191 + j*(197) +207 + j*(-57) +29 + j*(-50) +119 + j*(46) +187 + j*(-148) +-65 + j*(-232) +-148 + j*(8) +50 + j*(37) +-4 + j*(-137) +-182 + j*(-20) +-45 + j*(158) +105 + j*(30) +-4 + j*(-66) +-45 + j*(23) +9 + j*(13) +-52 + j*(4) +-19 + j*(126) +153 + j*(77) +108 + j*(-109) +-53 + j*(-69) +4 + j*(52) +96 + j*(-33) +2 + j*(-112) +-69 + j*(-32) +-9 + j*(22) +33 + j*(-21) +0 + j*(-68) +-62 + j*(-46) +-46 + j*(37) +66 + j*(11) +30 + j*(-150) +-177 + j*(-118) +-157 + j*(100) +45 + j*(60) +-61 + j*(-139) +-303 + j*(23) +-157 + j*(322) +144 + j*(255) +147 + j*(33) +25 + j*(8) +7 + j*(61) +13 + j*(86) +44 + j*(142) +145 + j*(150) +210 + j*(77) +241 + j*(18) +287 + j*(-81) +238 + j*(-244) +66 + j*(-323) +-96 + j*(-256) +-141 + j*(-104) +-23 + j*(-13) +90 + j*(-146) +-77 + j*(-325) +-341 + j*(-188) +-293 + j*(81) +-135 + j*(83) +-202 + j*(64) +-162 + j*(275) +168 + j*(275) +245 + j*(-84) +-76 + j*(-218) +-229 + j*(35) +-60 + j*(180) +47 + j*(89) +11 + j*(42) +16 + j*(64) +44 + j*(25) +-13 + j*(-21) +-99 + j*(47) +-55 + j*(198) +146 + j*(237) +291 + j*(61) +218 + j*(-129) +86 + j*(-161) +35 + j*(-143) +-24 + j*(-154) +-101 + j*(-112) +-124 + j*(-42) +-135 + j*(21) +-102 + j*(127) +57 + j*(161) +150 + j*(1) +18 + j*(-112) +-95 + j*(-10) +-21 + j*(100) +87 + j*(67) +116 + j*(-28) +54 + j*(-124) +-98 + j*(-109) +-133 + j*(77) +69 + j*(161) +203 + j*(-35) +54 + j*(-216) +-146 + j*(-167) +-224 + j*(-10) +-188 + j*(171) +14 + j*(291) +250 + j*(158) +218 + j*(-100) +19 + j*(-132) +-16 + j*(-2) +76 + j*(18) +112 + j*(-52) +95 + j*(-116) +40 + j*(-169) +-35 + j*(-170) +-69 + j*(-151) +-129 + j*(-165) +-239 + j*(-93) +-221 + j*(59) +-125 + j*(80) +-156 + j*(69) +-143 + j*(208) +67 + j*(241) +147 + j*(46) +19 + j*(-22) +22 + j*(44) +44 + j*(-50) +-145 + j*(-43) +-127 + j*(237) +229 + j*(223) +235 + j*(-165) +-151 + j*(-180) +-155 + j*(177) +153 + j*(168) +124 + j*(-74) +-42 + j*(-8) +70 + j*(91) +132 + j*(-57) +-16 + j*(-89) +-14 + j*(28) +62 + j*(-24) +-44 + j*(-62) +-59 + j*(84) +106 + j*(90) +103 + j*(-62) +-1 + j*(-36) +63 + j*(8) +52 + j*(-102) +-98 + j*(-39) +11 + j*(155) +250 + j*(24) +140 + j*(-243) +-105 + j*(-181) +-74 + j*(-2) +33 + j*(-24) +21 + j*(-81) +16 + j*(-94) +-13 + j*(-163) +-137 + j*(-158) +-172 + j*(-35) +-105 + j*(8) +-95 + j*(-8) +-82 + j*(9) +-61 + j*(-47) +-184 + j*(-91) +-302 + j*(69) +-197 + j*(250) +-46 + j*(255) +18 + j*(230) +116 + j*(202) +153 + j*(69) +47 + j*(14) +29 + j*(103) +125 + j*(91) +109 + j*(3) +63 + j*(23) +106 + j*(21) +71 + j*(-32) +40 + j*(49) +194 + j*(54) +204 + j*(-183) +-79 + j*(-221) +-124 + j*(70) +163 + j*(100) +186 + j*(-181) +-60 + j*(-213) +-83 + j*(-37) +16 + j*(-55) +-47 + j*(-115) +-82 + j*(-51) +-53 + j*(-66) +-161 + j*(-73) +-185 + j*(126) +58 + j*(189) +151 + j*(-55) +-72 + j*(-164) +-196 + j*(13) +-115 + j*(155) +0 + j*(219) +228 + j*(195) +358 + j*(-156) +-49 + j*(-463) +-512 + j*(-72) +-199 + j*(486) +371 + j*(288) +278 + j*(-197) +-54 + j*(-151) +15 + j*(26) +78 + j*(-95) +-64 + j*(-87) +24 + j*(35) +124 + j*(-163) +-172 + j*(-277) +-321 + j*(49) +-28 + j*(185) +27 + j*(-65) +-226 + j*(-18) +-119 + j*(266) +170 + j*(151) +62 + j*(-108) +-163 + j*(-12) +-113 + j*(191) +39 + j*(240) +192 + j*(206) +313 + j*(23) +193 + j*(-197) +-11 + j*(-159) +4 + j*(-62) +-11 + j*(-136) +-180 + j*(-67) +-119 + j*(165) +107 + j*(136) +76 + j*(-18) +13 + j*(76) +216 + j*(109) +313 + j*(-185) +30 + j*(-404) +-285 + j*(-245) +-296 + j*(75) +-49 + j*(220) +146 + j*(54) +26 + j*(-124) +-112 + j*(8) +83 + j*(111) +186 + j*(-162) +-133 + j*(-306) +-315 + j*(-18) +-127 + j*(135) +-94 + j*(33) +-190 + j*(153) +16 + j*(314) +231 + j*(128) +124 + j*(-67) +6 + j*(-33) +-10 + j*(6) +-33 + j*(81) +122 + j*(173) +308 + j*(-51) +71 + j*(-327) +-252 + j*(-132) +-125 + j*(173) +107 + j*(110) +95 + j*(-14) +96 + j*(-24) +103 + j*(-139) +-78 + j*(-181) +-139 + j*(-2) +4 + j*(33) +-23 + j*(-80) +-119 + j*(13) +23 + j*(93) +81 + j*(-90) +-136 + j*(-134) +-177 + j*(100) +45 + j*(131) +47 + j*(-78) +-180 + j*(-56) +-181 + j*(211) +100 + j*(286) +260 + j*(47) +89 + j*(-166) +-144 + j*(-52) +-66 + j*(201) +208 + j*(168) +238 + j*(-100) +21 + j*(-173) +-49 + j*(-18) +68 + j*(19) +83 + j*(-82) +11 + j*(-84) +57 + j*(-57) +86 + j*(-197) +-140 + j*(-319) +-407 + j*(-100) +-293 + j*(264) +62 + j*(272) +123 + j*(-11) +-105 + j*(-58) +-134 + j*(163) +80 + j*(209) +155 + j*(46) +71 + j*(-19) +59 + j*(8) +74 + j*(-35) +5 + j*(-65) +-40 + j*(6) +34 + j*(63) +116 + j*(-18) +32 + j*(-153) +-170 + j*(-86) +-151 + j*(177) +139 + j*(230) +243 + j*(-25) +66 + j*(-116) +74 + j*(6) +221 + j*(-123) +40 + j*(-356) +-243 + j*(-229) +-197 + j*(-8) +-124 + j*(-42) +-238 + j*(3) +-178 + j*(206) +31 + j*(197) +49 + j*(81) +47 + j*(99) +131 + j*(35) +40 + j*(-76) +-39 + j*(45) +158 + j*(82) +191 + j*(-202) +-130 + j*(-276) +-243 + j*(3) +-60 + j*(94) +-45 + j*(-2) +-97 + j*(67) +23 + j*(94) +18 + j*(-47) +-141 + j*(-11) +-109 + j*(154) +14 + j*(155) +25 + j*(129) +100 + j*(160) +185 + j*(37) +62 + j*(-59) +3 + j*(79) +188 + j*(106) +227 + j*(-115) +23 + j*(-181) +-41 + j*(-38) +45 + j*(1) +62 + j*(-45) +61 + j*(-53) +73 + j*(-99) +13 + j*(-140) +-21 + j*(-116) +-33 + j*(-151) +-171 + j*(-154) +-229 + j*(52) +-4 + j*(153) +103 + j*(-88) +-177 + j*(-197) +-326 + j*(118) +-32 + j*(326) +197 + j*(108) +51 + j*(-71) +-46 + j*(61) +132 + j*(113) +211 + j*(-117) +-11 + j*(-269) +-214 + j*(-139) +-204 + j*(35) +-146 + j*(99) +-97 + j*(165) +25 + j*(192) +98 + j*(83) +19 + j*(37) +25 + j*(147) +209 + j*(139) +269 + j*(-86) +95 + j*(-238) +-99 + j*(-180) +-173 + j*(-10) +-62 + j*(173) +209 + j*(134) +254 + j*(-197) +-91 + j*(-333) +-283 + j*(-34) +-62 + j*(144) +40 + j*(-25) +-119 + j*(-35) +-71 + j*(138) +100 + j*(65) +6 + j*(-73) +-84 + j*(53) +74 + j*(112) +125 + j*(-59) +-14 + j*(-108) +-41 + j*(-36) +-42 + j*(-70) +-158 + j*(-33) +-133 + j*(139) +28 + j*(144) +23 + j*(42) +-23 + j*(112) +120 + j*(163) +221 + j*(-5) +98 + j*(-145) +-37 + j*(-106) +-77 + j*(-18) +-59 + j*(86) +88 + j*(149) +236 + j*(-10) +112 + j*(-234) +-153 + j*(-170) +-163 + j*(105) +103 + j*(191) +279 + j*(-30) +151 + j*(-290) +-133 + j*(-298) +-257 + j*(-75) +-139 + j*(90) +-11 + j*(49) +-37 + j*(-28) +-92 + j*(16) +-48 + j*(84) +35 + j*(72) +73 + j*(-1) +42 + j*(-86) +-60 + j*(-117) +-154 + j*(-37) +-120 + j*(92) +1 + j*(97) +3 + j*(-5) +-102 + j*(25) +-38 + j*(170) +160 + j*(95) +95 + j*(-149) +-180 + j*(-106) +-170 + j*(175) +74 + j*(199) +105 + j*(33) +28 + j*(47) +117 + j*(69) +129 + j*(-82) +-30 + j*(-98) +-29 + j*(21) +37 + j*(-44) +-129 + j*(-81) +-194 + j*(180) +102 + j*(317) +298 + j*(81) +173 + j*(-95) +102 + j*(-45) +161 + j*(-87) +81 + j*(-207) +-82 + j*(-163) +-88 + j*(-7) +56 + j*(30) +127 + j*(-134) +-72 + j*(-274) +-305 + j*(-72) +-132 + j*(230) +192 + j*(95) +82 + j*(-211) +-176 + j*(-114) +-77 + j*(59) +-11 + j*(-83) +-235 + j*(-65) +-198 + j*(243) +132 + j*(240) +163 + j*(-30) +12 + j*(-59) +31 + j*(-41) +-71 + j*(-137) +-261 + j*(53) +-30 + j*(332) +298 + j*(107) +107 + j*(-206) +-142 + j*(-31) +54 + j*(141) +179 + j*(-92) +-74 + j*(-200) +-170 + j*(34) +23 + j*(98) +40 + j*(-74) +-140 + j*(-59) +-141 + j*(135) +32 + j*(186) +118 + j*(77) +79 + j*(4) +48 + j*(21) +94 + j*(35) +141 + j*(-46) +68 + j*(-148) +-57 + j*(-112) +-39 + j*(-5) +47 + j*(-55) +-49 + j*(-160) +-205 + j*(-52) +-132 + j*(129) +9 + j*(98) +-30 + j*(44) +-6 + j*(156) +211 + j*(107) +202 + j*(-187) +-104 + j*(-248) +-214 + j*(-8) +-91 + j*(83) +-95 + j*(62) +-86 + j*(191) +116 + j*(219) +183 + j*(42) +83 + j*(14) +173 + j*(68) +264 + j*(-135) +28 + j*(-305) +-180 + j*(-119) +-67 + j*(59) +47 + j*(-4) +14 + j*(-62) +-4 + j*(-70) +-54 + j*(-95) +-126 + j*(-25) +-64 + j*(67) +6 + j*(30) +-21 + j*(11) +15 + j*(41) +45 + j*(-38) +-64 + j*(-52) +-44 + j*(86) +132 + j*(28) +57 + j*(-187) +-176 + j*(-132) +-165 + j*(63) +-75 + j*(78) +-80 + j*(124) +78 + j*(195) +228 + j*(-22) +-4 + j*(-223) +-209 + j*(0) +10 + j*(181) +164 + j*(-49) +-78 + j*(-202) +-262 + j*(8) +-151 + j*(211) +1 + j*(238) +120 + j*(220) +247 + j*(115) +237 + j*(-69) +106 + j*(-139) +52 + j*(-100) +54 + j*(-134) +-59 + j*(-187) +-202 + j*(-62) +-113 + j*(153) +134 + j*(106) +117 + j*(-168) +-192 + j*(-185) +-261 + j*(141) +46 + j*(265) +199 + j*(12) +1 + j*(-146) +-157 + j*(-1) +-92 + j*(164) +56 + j*(206) +194 + j*(130) +205 + j*(-42) +58 + j*(-83) +63 + j*(59) +267 + j*(-2) +223 + j*(-295) +-92 + j*(-331) +-177 + j*(-91) +-37 + j*(-39) +-65 + j*(-134) +-171 + j*(-64) +-117 + j*(47) +-39 + j*(30) +-30 + j*(-4) +-33 + j*(-50) +-153 + j*(-89) +-280 + j*(112) +-45 + j*(370) +330 + j*(176) +233 + j*(-250) +-165 + j*(-257) +-235 + j*(44) +-67 + j*(118) +-48 + j*(67) +-37 + j*(130) +82 + j*(110) +69 + j*(-7) +-2 + j*(18) +66 + j*(23) +4 + j*(-115) +-230 + j*(-1) +-110 + j*(342) +310 + j*(286) +354 + j*(-125) +48 + j*(-234) +-42 + j*(-73) +11 + j*(-70) +-78 + j*(-76) +-73 + j*(71) +103 + j*(57) +84 + j*(-134) +-106 + j*(-129) +-124 + j*(27) +-36 + j*(40) +-80 + j*(10) +-114 + j*(134) +54 + j*(240) +247 + j*(107) +209 + j*(-124) +13 + j*(-175) +-80 + j*(-55) +-42 + j*(37) +24 + j*(83) +164 + j*(77) +269 + j*(-146) +24 + j*(-402) +-358 + j*(-215) +-275 + j*(216) +124 + j*(223) +179 + j*(-100) +-56 + j*(-172) +-129 + j*(-26) +-68 + j*(35) +-28 + j*(37) +10 + j*(16) +-11 + j*(-30) +-37 + j*(6) +37 + j*(-8) +-33 + j*(-153) +-266 + j*(-46) +-162 + j*(266) +182 + j*(187) +122 + j*(-136) +-151 + j*(-84) +-108 + j*(118) +-5 + j*(82) +-60 + j*(91) +23 + j*(199) +167 + j*(116) +136 + j*(15) +152 + j*(13) +181 + j*(-128) +-24 + j*(-211) +-124 + j*(-5) +68 + j*(65) +100 + j*(-121) +-51 + j*(-142) +-59 + j*(-98) +-165 + j*(-158) +-366 + j*(54) +-148 + j*(388) +223 + j*(250) +158 + j*(-40) +1 + j*(21) +99 + j*(75) +97 + j*(-37) +21 + j*(12) +141 + j*(35) +142 + j*(-153) +-66 + j*(-161) +-83 + j*(11) +17 + j*(23) +25 + j*(18) +141 + j*(21) +177 + j*(-226) +-158 + j*(-329) +-309 + j*(18) +6 + j*(153) +71 + j*(-148) +-248 + j*(-166) +-279 + j*(146) +-52 + j*(199) +-49 + j*(99) +-93 + j*(208) +93 + j*(319) +321 + j*(184) +340 + j*(-88) +131 + j*(-234) +-27 + j*(-103) +121 + j*(-9) +181 + j*(-267) +-188 + j*(-376) +-365 + j*(25) +10 + j*(214) +159 + j*(-136) +-173 + j*(-258) +-288 + j*(6) +-164 + j*(73) +-237 + j*(85) +-181 + j*(339) +178 + j*(332) +226 + j*(-12) +-47 + j*(-44) +-12 + j*(185) +211 + j*(103) +128 + j*(-105) +-33 + j*(-25) +66 + j*(81) +156 + j*(-54) +0 + j*(-157) +-127 + j*(-10) +-4 + j*(132) +139 + j*(40) +79 + j*(-74) +23 + j*(-24) +107 + j*(-37) +53 + j*(-196) +-178 + j*(-147) +-179 + j*(122) +74 + j*(182) +185 + j*(-1) +119 + j*(-127) +28 + j*(-185) +-113 + j*(-173) +-170 + j*(-17) +-35 + j*(49) +-16 + j*(-71) +-151 + j*(-37) +-85 + j*(115) +68 + j*(21) +-51 + j*(-130) +-218 + j*(-13) +-162 + j*(153) +-63 + j*(190) +18 + j*(219) +161 + j*(182) +217 + j*(19) +130 + j*(-104) +2 + j*(-137) +-141 + j*(-49) +-119 + j*(186) +168 + j*(240) +290 + j*(-35) +86 + j*(-157) +57 + j*(-26) +190 + j*(-136) +-6 + j*(-339) +-279 + j*(-161) +-187 + j*(89) +-35 + j*(71) +-34 + j*(38) +9 + j*(36) +-21 + j*(-38) +-119 + j*(59) +58 + j*(194) +231 + j*(-33) +-16 + j*(-212) +-141 + j*(44) +158 + j*(81) +125 + j*(-313) +-374 + j*(-289) +-446 + j*(250) +17 + j*(442) +265 + j*(146) +147 + j*(-57) +49 + j*(-35) +74 + j*(-35) +49 + j*(-120) +-98 + j*(-146) +-208 + j*(21) +-69 + j*(197) +124 + j*(98) +37 + j*(-71) +-103 + j*(37) +32 + j*(169) +162 + j*(35) +54 + j*(-69) +-1 + j*(23) +96 + j*(36) +104 + j*(-56) +58 + j*(-69) +78 + j*(-97) +1 + j*(-203) +-190 + j*(-150) +-219 + j*(67) +-55 + j*(164) +41 + j*(95) +35 + j*(70) +101 + j*(92) +202 + j*(-23) +112 + j*(-209) +-103 + j*(-188) +-135 + j*(-6) +-16 + j*(25) +-25 + j*(-49) +-83 + j*(2) +-8 + j*(53) +23 + j*(-26) +-57 + j*(-25) +-11 + j*(57) +82 + j*(-37) +-43 + j*(-152) +-170 + j*(-37) +-93 + j*(54) +-96 + j*(-8) +-214 + j*(91) +-90 + j*(313) +190 + j*(255) +225 + j*(22) +115 + j*(-39) +119 + j*(-33) +105 + j*(-135) +-41 + j*(-175) +-135 + j*(-68) +-116 + j*(19) +-103 + j*(53) +-94 + j*(129) +4 + j*(206) +153 + j*(180) +245 + j*(44) +206 + j*(-132) +28 + j*(-211) +-133 + j*(-80) +-57 + j*(109) +135 + j*(76) +141 + j*(-91) +40 + j*(-116) +51 + j*(-105) +4 + j*(-216) +-210 + j*(-176) +-216 + j*(76) +6 + j*(90) +-40 + j*(-96) +-239 + j*(27) +-95 + j*(268) +145 + j*(173) +111 + j*(28) +119 + j*(60) +221 + j*(-74) +40 + j*(-259) +-171 + j*(-100) +-47 + j*(68) +50 + j*(-38) +-37 + j*(-72) +-7 + j*(-37) +-42 + j*(-154) +-260 + j*(-73) +-182 + j*(211) +93 + j*(139) +1 + j*(-67) +-121 + j*(69) +54 + j*(108) +-10 + j*(-86) +-221 + j*(101) +77 + j*(344) +349 + j*(-26) +-51 + j*(-301) +-306 + j*(91) +35 + j*(310) +177 + j*(62) +26 + j*(54) +174 + j*(157) +295 + j*(-98) +20 + j*(-240) +-98 + j*(-3) +103 + j*(49) +100 + j*(-137) +-69 + j*(-115) +-49 + j*(13) +22 + j*(-11) +-23 + j*(-35) +-29 + j*(40) +65 + j*(64) +139 + j*(-15) +112 + j*(-129) +4 + j*(-163) +-49 + j*(-100) +-20 + j*(-83) +-41 + j*(-118) +-83 + j*(-96) +-82 + j*(-107) +-192 + j*(-139) +-315 + j*(43) +-140 + j*(250) +73 + j*(127) +-40 + j*(-17) +-107 + j*(146) +124 + j*(192) +196 + j*(-69) +-19 + j*(-176) +-128 + j*(-65) +-133 + j*(-17) +-197 + j*(58) +-139 + j*(213) +13 + j*(219) +35 + j*(163) +75 + j*(223) +249 + j*(183) +296 + j*(-32) +154 + j*(-146) +62 + j*(-116) +40 + j*(-108) +-14 + j*(-113) +-75 + j*(-64) +-81 + j*(28) +11 + j*(87) +102 + j*(11) +26 + j*(-83) +-47 + j*(13) +97 + j*(66) +144 + j*(-139) +-105 + j*(-196) +-170 + j*(65) +74 + j*(124) +102 + j*(-91) +-80 + j*(-80) +-29 + j*(71) +97 + j*(2) +42 + j*(-81) +35 + j*(-62) +48 + j*(-177) +-178 + j*(-238) +-325 + j*(26) +-100 + j*(229) +79 + j*(75) +-45 + j*(-35) +-101 + j*(106) +62 + j*(166) +164 + j*(25) +97 + j*(-110) +-28 + j*(-144) +-144 + j*(-75) +-161 + j*(84) +-7 + j*(173) +120 + j*(52) +18 + j*(-78) +-114 + j*(42) +45 + j*(204) +273 + j*(22) +107 + j*(-272) +-217 + j*(-142) +-112 + j*(176) +195 + j*(71) +88 + j*(-234) +-211 + j*(-156) +-177 + j*(99) +-6 + j*(92) +-29 + j*(5) +-69 + j*(59) +-11 + j*(93) +20 + j*(63) +31 + j*(49) +30 + j*(6) +-49 + j*(11) +-37 + j*(144) +149 + j*(153) +198 + j*(-51) +23 + j*(-128) +-43 + j*(4) +64 + j*(35) +70 + j*(-76) +-52 + j*(-81) +-86 + j*(45) +15 + j*(118) +117 + j*(75) +143 + j*(-13) +119 + j*(-71) +87 + j*(-121) +4 + j*(-158) +-98 + j*(-84) +-44 + j*(57) +132 + j*(25) +141 + j*(-175) +-33 + j*(-253) +-145 + j*(-178) +-187 + j*(-118) +-250 + j*(-28) +-211 + j*(132) +-40 + j*(179) +53 + j*(59) +-20 + j*(-36) +-122 + j*(10) +-110 + j*(148) +61 + j*(212) +224 + j*(52) +129 + j*(-190) +-135 + j*(-187) +-214 + j*(35) +-81 + j*(148) +1 + j*(98) +-6 + j*(98) +69 + j*(136) +181 + j*(28) +91 + j*(-155) +-130 + j*(-107) +-113 + j*(127) +132 + j*(112) +103 + j*(-163) +-225 + j*(-134) +-235 + j*(238) +124 + j*(314) +231 + j*(42) +78 + j*(-9) +156 + j*(80) +275 + j*(-119) +40 + j*(-315) +-192 + j*(-129) +-70 + j*(52) +16 + j*(-64) +-165 + j*(-95) +-232 + j*(161) +25 + j*(338) +308 + j*(185) +317 + j*(-112) +103 + j*(-245) +-50 + j*(-148) +-11 + j*(-56) +17 + j*(-116) +-97 + j*(-125) +-129 + j*(23) +25 + j*(85) +115 + j*(-62) +-6 + j*(-184) +-159 + j*(-110) +-139 + j*(45) +-1 + j*(64) +28 + j*(-65) +-100 + j*(-98) +-138 + j*(18) +-51 + j*(27) +-122 + j*(-42) +-230 + j*(123) +-16 + j*(313) +245 + j*(122) +118 + j*(-151) +-115 + j*(-88) +-102 + j*(78) +-15 + j*(105) +45 + j*(103) +127 + j*(21) +37 + j*(-133) +-170 + j*(-50) +-119 + j*(180) +85 + j*(175) +108 + j*(61) +115 + j*(46) +151 + j*(-66) +-31 + j*(-154) +-152 + j*(68) +88 + j*(200) +204 + j*(-35) +-8 + j*(-97) +10 + j*(114) +246 + j*(33) +162 + j*(-222) +-52 + j*(-168) +-8 + j*(-47) +22 + j*(-113) +-56 + j*(-87) +23 + j*(-35) +49 + j*(-194) +-185 + j*(-232) +-262 + j*(21) +-47 + j*(101) +8 + j*(-89) +-191 + j*(-145) +-322 + j*(28) +-266 + j*(245) +-43 + j*(359) +177 + j*(213) +93 + j*(-14) +-114 + j*(91) +46 + j*(342) +381 + j*(202) +356 + j*(-164) +76 + j*(-260) +-67 + j*(-126) +-42 + j*(-6) +54 + j*(9) +84 + j*(-112) +-93 + j*(-175) +-216 + j*(41) +-4 + j*(220) +187 + j*(48) +62 + j*(-99) +-8 + j*(18) +151 + j*(32) +170 + j*(-167) +1 + j*(-237) +-81 + j*(-171) +-116 + j*(-170) +-235 + j*(-134) +-296 + j*(37) +-192 + j*(194) +-21 + j*(214) +74 + j*(98) +-1 + j*(-1) +-93 + j*(92) +38 + j*(225) +244 + j*(106) +206 + j*(-135) +13 + j*(-202) +-122 + j*(-124) +-175 + j*(12) +-77 + j*(171) +138 + j*(122) +132 + j*(-113) +-93 + j*(-131) +-113 + j*(52) +14 + j*(35) +-81 + j*(-54) +-184 + j*(119) +7 + j*(270) +177 + j*(148) +148 + j*(47) +192 + j*(47) +250 + j*(-116) +63 + j*(-264) +-123 + j*(-127) +-39 + j*(22) +52 + j*(-51) +-25 + j*(-103) +-47 + j*(-40) +-6 + j*(-68) +-97 + j*(-120) +-204 + j*(-2) +-122 + j*(153) +33 + j*(144) +76 + j*(43) +42 + j*(-7) +21 + j*(-5) +32 + j*(-12) +24 + j*(-70) +-91 + j*(-107) +-226 + j*(40) +-106 + j*(296) +238 + j*(284) +373 + j*(-71) +105 + j*(-325) +-190 + j*(-192) +-182 + j*(65) +-12 + j*(129) +65 + j*(48) +39 + j*(-4) +18 + j*(13) +54 + j*(33) +107 + j*(-6) +110 + j*(-91) +38 + j*(-165) +-86 + j*(-168) +-182 + j*(-47) +-103 + j*(130) +128 + j*(115) +190 + j*(-144) +-47 + j*(-298) +-258 + j*(-156) +-246 + j*(28) +-178 + j*(105) +-101 + j*(175) +53 + j*(149) +76 + j*(-33) +-113 + j*(-80) +-179 + j*(104) +-24 + j*(184) +38 + j*(68) +-64 + j*(44) +-83 + j*(166) +38 + j*(235) +155 + j*(177) +173 + j*(84) +158 + j*(74) +257 + j*(64) +337 + j*(-165) +70 + j*(-406) +-300 + j*(-202) +-197 + j*(201) +158 + j*(170) +151 + j*(-98) +-24 + j*(-82) +13 + j*(11) +29 + j*(-41) +-23 + j*(28) +142 + j*(89) +243 + j*(-152) +-11 + j*(-301) +-160 + j*(-95) +-9 + j*(-13) +-18 + j*(-156) +-180 + j*(-100) +-137 + j*(49) +-59 + j*(32) +-93 + j*(57) +9 + j*(139) +139 + j*(30) +85 + j*(-95) +49 + j*(-113) +-1 + j*(-236) +-292 + j*(-232) +-390 + j*(163) +18 + j*(347) +232 + j*(-16) +-69 + j*(-199) +-178 + j*(31) +-9 + j*(29) +-153 + j*(-123) +-350 + j*(132) +-78 + j*(395) +177 + j*(175) +-3 + j*(17) +-54 + j*(233) +233 + j*(250) +274 + j*(-47) +47 + j*(-99) +62 + j*(39) +161 + j*(-92) +-80 + j*(-226) +-301 + j*(77) +-18 + j*(404) +385 + j*(230) +369 + j*(-156) +106 + j*(-264) +-22 + j*(-159) +-18 + j*(-98) +-25 + j*(-91) +-62 + j*(-67) +-71 + j*(3) +14 + j*(64) +128 + j*(-19) +71 + j*(-185) +-119 + j*(-175) +-159 + j*(-13) +-60 + j*(39) +-55 + j*(-1) +-75 + j*(60) +33 + j*(105) +115 + j*(1) +66 + j*(-100) +3 + j*(-122) +-59 + j*(-150) +-186 + j*(-126) +-264 + j*(36) +-168 + j*(209) +22 + j*(231) +126 + j*(107) +83 + j*(4) +36 + j*(27) +107 + j*(28) +112 + j*(-110) +-60 + j*(-147) +-120 + j*(21) +26 + j*(76) +58 + j*(-45) +-23 + j*(-40) +44 + j*(-8) +48 + j*(-170) +-195 + j*(-199) +-287 + j*(54) +-105 + j*(174) +-40 + j*(91) +-74 + j*(122) +21 + j*(158) +40 + j*(59) +-60 + j*(115) +76 + j*(275) +334 + j*(137) +289 + j*(-160) +68 + j*(-228) +-31 + j*(-156) +-88 + j*(-124) +-161 + j*(-33) +-124 + j*(107) +8 + j*(153) +107 + j*(76) +85 + j*(-28) +-11 + j*(-13) +36 + j*(100) +209 + j*(28) +150 + j*(-202) +-91 + j*(-184) +-93 + j*(16) +47 + j*(-1) +-6 + j*(-98) +-74 + j*(-21) +4 + j*(15) +9 + j*(-45) +-18 + j*(-18) +45 + j*(-42) +-28 + j*(-154) +-188 + j*(-57) +-95 + j*(119) +54 + j*(37) +-26 + j*(-59) +-64 + j*(36) +48 + j*(21) +4 + j*(-108) +-123 + j*(-68) +-115 + j*(13) +-122 + j*(18) +-150 + j*(101) +-64 + j*(182) +11 + j*(168) +74 + j*(197) +255 + j*(128) +258 + j*(-156) +-20 + j*(-245) +-132 + j*(-64) +-83 + j*(-25) +-188 + j*(30) +-97 + j*(302) +292 + j*(246) +298 + j*(-159) +-21 + j*(-179) +32 + j*(19) +153 + j*(-161) +-119 + j*(-269) +-227 + j*(11) +1 + j*(71) +-40 + j*(-97) +-175 + j*(52) +53 + j*(170) +153 + j*(-105) +-145 + j*(-195) +-250 + j*(85) +-49 + j*(207) +48 + j*(129) +20 + j*(-16) +-153 + j*(39) +-67 + j*(248) +168 + j*(204) +190 + j*(6) +79 + j*(-42) +55 + j*(11) +116 + j*(11) +151 + j*(-91) +37 + j*(-217) +-189 + j*(-141) +-180 + j*(150) +139 + j*(216) +272 + j*(-98) +0 + j*(-273) +-162 + j*(-72) +-13 + j*(18) +-18 + j*(-144) +-253 + j*(-80) +-201 + j*(224) +119 + j*(223) +158 + j*(-62) +-76 + j*(-111) +-123 + j*(72) +-8 + j*(115) +5 + j*(85) +42 + j*(146) +187 + j*(103) +190 + j*(-75) +51 + j*(-117) +18 + j*(-45) +43 + j*(-53) +4 + j*(-48) +48 + j*(8) +132 + j*(-81) +28 + j*(-197) +-75 + j*(-110) +22 + j*(-79) +-21 + j*(-257) +-312 + j*(-221) +-363 + j*(127) +-65 + j*(267) +102 + j*(74) +8 + j*(-53) +-57 + j*(-21) +-49 + j*(-23) +-98 + j*(-45) +-168 + j*(1) +-192 + j*(103) +-134 + j*(218) +10 + j*(260) +124 + j*(185) +151 + j*(85) +132 + j*(1) +42 + j*(-52) +-50 + j*(34) +49 + j*(156) +209 + j*(53) +132 + j*(-117) +2 + j*(-72) +53 + j*(-21) +35 + j*(-124) +-127 + j*(-79) +-94 + j*(112) +71 + j*(101) +65 + j*(6) +58 + j*(45) +162 + j*(-21) +55 + j*(-196) +-175 + j*(-70) +-47 + j*(199) +252 + j*(92) +190 + j*(-209) +-69 + j*(-199) +-71 + j*(-8) +73 + j*(-34) +11 + j*(-181) +-168 + j*(-110) +-112 + j*(105) +133 + j*(71) +139 + j*(-204) +-138 + j*(-275) +-276 + j*(-60) +-179 + j*(93) +-94 + j*(119) +18 + j*(148) +162 + j*(6) +26 + j*(-228) +-247 + j*(-132) +-196 + j*(110) +-56 + j*(52) +-201 + j*(25) +-186 + j*(303) +185 + j*(322) +255 + j*(-55) +-76 + j*(-139) +-141 + j*(135) +88 + j*(190) +140 + j*(19) +35 + j*(-28) +-6 + j*(30) +34 + j*(95) +163 + j*(86) +219 + j*(-117) +-15 + j*(-264) +-230 + j*(-56) +-86 + j*(169) +83 + j*(84) +21 + j*(7) +28 + j*(96) +162 + j*(54) +146 + j*(-94) +45 + j*(-119) +13 + j*(-106) +-49 + j*(-112) +-103 + j*(-21) +-24 + j*(58) +58 + j*(6) +44 + j*(-64) +-5 + j*(-103) +-108 + j*(-93) +-155 + j*(63) +35 + j*(171) +190 + j*(-23) +7 + j*(-206) +-175 + j*(-45) +-35 + j*(121) +113 + j*(-3) +18 + j*(-146) +-119 + j*(-103) +-148 + j*(11) +-88 + j*(97) +18 + j*(88) +26 + j*(-2) +-47 + j*(23) +50 + j*(112) +197 + j*(-47) +23 + j*(-272) +-256 + j*(-141) +-197 + j*(119) +-28 + j*(103) +-75 + j*(49) +-61 + j*(182) +146 + j*(168) +159 + j*(-66) +-41 + j*(-97) +-52 + j*(81) +131 + j*(78) +152 + j*(-101) +-6 + j*(-171) +-116 + j*(-80) +-110 + j*(36) +-23 + j*(101) +86 + j*(69) +116 + j*(-40) +59 + j*(-113) +-4 + j*(-137) +-81 + j*(-152) +-188 + j*(-98) +-225 + j*(40) +-157 + j*(156) +-58 + j*(203) +49 + j*(203) +142 + j*(134) +159 + j*(27) +109 + j*(-42) +33 + j*(-64) +-49 + j*(4) +13 + j*(147) +227 + j*(116) +262 + j*(-137) +35 + j*(-221) +-35 + j*(-57) +105 + j*(-54) +57 + j*(-218) +-124 + j*(-179) +-112 + j*(-45) +-62 + j*(-72) +-150 + j*(-71) +-165 + j*(53) +-93 + j*(107) +-51 + j*(159) +119 + j*(214) +309 + j*(1) +148 + j*(-280) +-118 + j*(-215) +-103 + j*(-68) +-106 + j*(-115) +-245 + j*(-18) +-124 + j*(192) +93 + j*(70) +-49 + j*(-119) +-227 + j*(47) +-80 + j*(221) +50 + j*(139) +16 + j*(105) +64 + j*(148) +132 + j*(102) +154 + j*(76) +253 + j*(1) +211 + j*(-228) +-62 + j*(-268) +-141 + j*(-52) +-21 + j*(-23) +-99 + j*(-81) +-146 + j*(102) +98 + j*(163) +176 + j*(-89) +-30 + j*(-168) +-74 + j*(-58) +-72 + j*(-105) +-255 + j*(-44) +-206 + j*(249) +106 + j*(258) +140 + j*(19) +6 + j*(35) +111 + j*(107) +173 + j*(-62) +7 + j*(-121) +-20 + j*(1) +59 + j*(-44) +-64 + j*(-100) +-124 + j*(90) +105 + j*(177) +235 + j*(-37) +90 + j*(-192) +-28 + j*(-144) +-42 + j*(-128) +-148 + j*(-137) +-256 + j*(38) +-103 + j*(261) +194 + j*(200) +233 + j*(-95) +-8 + j*(-198) +-115 + j*(-16) +40 + j*(62) +106 + j*(-97) +-47 + j*(-189) +-173 + j*(-98) +-190 + j*(20) +-149 + j*(123) +-37 + j*(182) +63 + j*(129) +74 + j*(73) +105 + j*(53) +122 + j*(-39) +19 + j*(-87) +-16 + j*(11) +98 + j*(8) +78 + j*(-145) +-92 + j*(-151) +-136 + j*(-19) +-94 + j*(37) +-70 + j*(81) +18 + j*(103) +47 + j*(9) +-56 + j*(27) +33 + j*(182) +274 + j*(57) +168 + j*(-253) +-151 + j*(-201) +-143 + j*(74) +79 + j*(80) +96 + j*(-104) +-49 + j*(-161) +-158 + j*(-77) +-153 + j*(47) +-65 + j*(85) +-58 + j*(42) +-104 + j*(119) +37 + j*(215) +175 + j*(63) +37 + j*(-49) +5 + j*(101) +208 + j*(50) +102 + j*(-205) +-168 + j*(-50) +47 + j*(210) +306 + j*(-73) +-16 + j*(-332) +-255 + j*(-18) +41 + j*(160) +139 + j*(-130) +-158 + j*(-171) +-180 + j*(115) +55 + j*(134) +56 + j*(-25) +-40 + j*(18) +54 + j*(101) +173 + j*(-6) +116 + j*(-182) +-86 + j*(-226) +-232 + j*(-57) +-132 + j*(143) +54 + j*(100) +23 + j*(-40) +-83 + j*(20) +1 + j*(123) +117 + j*(54) +103 + j*(-50) +57 + j*(-96) +-11 + j*(-141) +-128 + j*(-109) +-163 + j*(13) +-107 + j*(88) +-53 + j*(115) +16 + j*(123) +62 + j*(72) +40 + j*(47) +73 + j*(71) +129 + j*(-10) +32 + j*(-91) +-40 + j*(18) +92 + j*(69) +134 + j*(-86) +-20 + j*(-116) +-22 + j*(19) +113 + j*(-21) +64 + j*(-169) +-74 + j*(-158) +-113 + j*(-92) +-147 + j*(-40) +-122 + j*(71) +29 + j*(62) +12 + j*(-122) +-220 + j*(-116) +-272 + j*(134) +-90 + j*(245) +-1 + j*(192) +25 + j*(218) +171 + j*(227) +279 + j*(64) +198 + j*(-95) +87 + j*(-100) +73 + j*(-67) +80 + j*(-100) +35 + j*(-149) +-53 + j*(-163) +-153 + j*(-111) +-209 + j*(27) +-129 + j*(186) +68 + j*(223) +205 + j*(86) +179 + j*(-74) +88 + j*(-138) +5 + j*(-157) +-96 + j*(-119) +-115 + j*(1) +-16 + j*(38) +-15 + j*(-49) +-125 + j*(6) +-32 + j*(174) +199 + j*(79) +140 + j*(-194) +-129 + j*(-188) +-168 + j*(26) +-37 + j*(71) +-35 + j*(20) +-45 + j*(83) +76 + j*(84) +86 + j*(-76) +-113 + j*(-103) +-179 + j*(133) +62 + j*(269) +273 + j*(88) +204 + j*(-132) +66 + j*(-167) +2 + j*(-162) +-103 + j*(-144) +-148 + j*(13) +28 + j*(86) +103 + j*(-114) +-116 + j*(-188) +-182 + j*(15) +-18 + j*(18) +-134 + j*(-136) +-347 + j*(89) +-95 + j*(383) +220 + j*(180) +69 + j*(-60) +-48 + j*(91) +146 + j*(103) +101 + j*(-139) +-162 + j*(-80) +-118 + j*(158) +24 + j*(144) +-9 + j*(153) +144 + j*(295) +445 + j*(102) +343 + j*(-304) +-41 + j*(-339) +-161 + j*(-82) +-35 + j*(47) +82 + j*(1) +88 + j*(-138) +-106 + j*(-212) +-285 + j*(14) +-85 + j*(303) +262 + j*(192) +267 + j*(-119) +84 + j*(-187) +59 + j*(-170) +-18 + j*(-281) +-279 + j*(-235) +-345 + j*(93) +-56 + j*(264) +149 + j*(54) +-6 + j*(-124) +-141 + j*(19) +14 + j*(121) +86 + j*(-53) +-107 + j*(-88) +-104 + j*(133) +148 + j*(91) +79 + j*(-190) +-215 + j*(-110) +-141 + j*(163) +71 + j*(98) +-9 + j*(-30) +-50 + j*(76) +74 + j*(47) +-21 + j*(-69) +-111 + j*(97) +124 + j*(161) +175 + j*(-124) +-117 + j*(-168) +-140 + j*(79) +18 + j*(42) +-129 + j*(-30) +-170 + j*(247) +187 + j*(317) +292 + j*(-23) +37 + j*(-107) +30 + j*(71) +175 + j*(-1) +69 + j*(-127) +-26 + j*(-14) +93 + j*(53) +172 + j*(-49) +153 + j*(-153) +76 + j*(-268) +-137 + j*(-300) +-285 + j*(-99) +-179 + j*(86) +-56 + j*(67) +-50 + j*(33) +-41 + j*(37) +-47 + j*(40) +-22 + j*(98) +101 + j*(63) +71 + j*(-103) +-99 + j*(-73) +-39 + j*(54) +16 + j*(-78) +-238 + j*(-69) +-216 + j*(317) +238 + j*(336) +301 + j*(-74) +30 + j*(-109) +119 + j*(-5) +102 + j*(-274) +-336 + j*(-198) +-234 + j*(338) +317 + j*(203) +107 + j*(-310) +-373 + j*(9) +39 + j*(494) +548 + j*(83) +259 + j*(-392) +-59 + j*(-276) +-50 + j*(-222) +-245 + j*(-243) +-345 + j*(76) +-46 + j*(217) +41 + j*(0) +-101 + j*(28) +41 + j*(107) +47 + j*(-132) +-296 + j*(-61) +-186 + j*(387) +322 + j*(310) +317 + j*(-164) +-23 + j*(-210) +-63 + j*(-51) +-68 + j*(-73) +-175 + j*(40) +-20 + j*(210) +158 + j*(66) +35 + j*(-66) +-25 + j*(49) +91 + j*(58) +83 + j*(-30) +75 + j*(-8) +147 + j*(-103) +-15 + j*(-257) +-227 + j*(-94) +-94 + j*(96) +3 + j*(-42) +-209 + j*(-49) +-199 + j*(257) +140 + j*(306) +250 + j*(40) +117 + j*(-65) +97 + j*(-48) +59 + j*(-125) +-77 + j*(-87) +-37 + j*(62) +100 + j*(11) +37 + j*(-114) +-59 + j*(-43) +25 + j*(4) +25 + j*(-114) +-153 + j*(-93) +-145 + j*(137) +109 + j*(171) +191 + j*(-75) +-13 + j*(-193) +-144 + j*(-52) +-71 + j*(59) +-11 + j*(46) +20 + j*(59) +115 + j*(11) +86 + j*(-164) +-141 + j*(-180) +-206 + j*(53) +-4 + j*(141) +72 + j*(-33) +-84 + j*(-98) +-161 + j*(37) +-96 + j*(133) +-21 + j*(173) +110 + j*(175) +214 + j*(13) +74 + j*(-158) +-111 + j*(-55) +-28 + j*(112) +115 + j*(41) +57 + j*(-75) +-24 + j*(-36) +-1 + j*(-3) +-20 + j*(-16) +-31 + j*(53) +78 + j*(77) +124 + j*(-49) +11 + j*(-101) +-12 + j*(-10) +84 + j*(-37) +29 + j*(-175) +-149 + j*(-140) +-162 + j*(32) +-39 + j*(63) +-34 + j*(-16) +-105 + j*(19) +-59 + j*(109) +41 + j*(71) +3 + j*(-23) +-98 + j*(30) +-42 + j*(162) +121 + j*(127) +112 + j*(-46) +-64 + j*(-49) +-78 + j*(147) +136 + j*(196) +232 + j*(0) +93 + j*(-115) +-5 + j*(-24) +59 + j*(53) +144 + j*(33) +218 + j*(-44) +221 + j*(-222) +6 + j*(-361) +-238 + j*(-199) +-153 + j*(69) +88 + j*(24) +55 + j*(-197) +-150 + j*(-198) +-190 + j*(-41) +-102 + j*(-2) +-101 + j*(-59) +-194 + j*(-53) +-261 + j*(78) +-156 + j*(254) +87 + j*(235) +144 + j*(-18) +-100 + j*(-113) +-231 + j*(132) +-11 + j*(312) +197 + j*(161) +122 + j*(-5) +43 + j*(53) +148 + j*(74) +173 + j*(-95) +-18 + j*(-148) +-86 + j*(41) +116 + j*(92) +151 + j*(-148) +-134 + j*(-187) +-187 + j*(127) +143 + j*(188) +202 + j*(-142) +-109 + j*(-194) +-141 + j*(74) +67 + j*(52) +-37 + j*(-107) +-177 + j*(85) +66 + j*(231) +214 + j*(-20) +-19 + j*(-139) +-97 + j*(74) +100 + j*(126) +143 + j*(-30) +59 + j*(-60) +67 + j*(-48) +49 + j*(-99) +-6 + j*(-85) +2 + j*(-83) +-78 + j*(-118) +-170 + j*(35) +22 + j*(202) +261 + j*(16) +144 + j*(-269) +-115 + j*(-267) +-222 + j*(-120) +-230 + j*(24) +-117 + j*(153) +61 + j*(76) +-21 + j*(-107) +-218 + j*(6) +-86 + j*(230) +141 + j*(103) +21 + j*(-98) +-153 + j*(20) +-58 + j*(168) +37 + j*(133) +56 + j*(142) +192 + j*(128) +230 + j*(-85) +17 + j*(-165) +-42 + j*(20) +144 + j*(10) +78 + j*(-226) +-221 + j*(-146) +-165 + j*(190) +173 + j*(174) +194 + j*(-137) +-57 + j*(-189) +-112 + j*(-10) +4 + j*(12) +-13 + j*(-78) +-116 + j*(-51) +-128 + j*(61) +-35 + j*(141) +119 + j*(104) +158 + j*(-125) +-125 + j*(-265) +-395 + j*(30) +-168 + j*(416) +249 + j*(329) +288 + j*(0) +127 + j*(-76) +122 + j*(-61) +76 + j*(-166) +-107 + j*(-134) +-115 + j*(67) +70 + j*(103) +136 + j*(-47) +35 + j*(-147) +-89 + j*(-117) +-135 + j*(0) +-57 + j*(94) +35 + j*(58) +16 + j*(11) +26 + j*(54) +121 + j*(8) +77 + j*(-132) +-66 + j*(-115) +-62 + j*(-21) +-44 + j*(-54) +-147 + j*(-11) +-90 + j*(163) +119 + j*(127) +98 + j*(-64) +-51 + j*(-28) +23 + j*(93) +136 + j*(-2) +59 + j*(-98) +25 + j*(-46) +92 + j*(-109) +-35 + j*(-244) +-247 + j*(-124) +-176 + j*(107) +21 + j*(59) +-58 + j*(-110) +-253 + j*(-2) +-168 + j*(241) +71 + j*(222) +96 + j*(59) +28 + j*(57) +93 + j*(68) +86 + j*(-60) +-78 + j*(-46) +-54 + j*(137) +134 + j*(111) +105 + j*(-52) +-15 + j*(-2) +73 + j*(86) +153 + j*(-13) +109 + j*(-70) +141 + j*(-113) +49 + j*(-303) +-291 + j*(-239) +-296 + j*(175) +111 + j*(217) +139 + j*(-158) +-216 + j*(-148) +-193 + j*(179) +64 + j*(148) +-6 + j*(-11) +-98 + j*(140) +112 + j*(226) +215 + j*(31) +93 + j*(-42) +110 + j*(34) +212 + j*(-61) +122 + j*(-230) +-73 + j*(-220) +-151 + j*(-72) +-80 + j*(49) +42 + j*(33) +48 + j*(-71) +-34 + j*(-74) +-5 + j*(-15) +45 + j*(-105) +-96 + j*(-188) +-226 + j*(-47) +-139 + j*(88) +-63 + j*(54) +-95 + j*(61) +-36 + j*(117) +24 + j*(41) +-85 + j*(0) +-132 + j*(162) +52 + j*(274) +237 + j*(158) +254 + j*(-29) +160 + j*(-160) +0 + j*(-185) +-93 + j*(-59) +9 + j*(45) +118 + j*(-73) +-11 + j*(-226) +-217 + j*(-146) +-233 + j*(57) +-114 + j*(142) +-49 + j*(125) +-33 + j*(145) +49 + j*(185) +175 + j*(114) +163 + j*(-51) +4 + j*(-78) +-24 + j*(78) +165 + j*(107) +232 + j*(-113) +29 + j*(-233) +-103 + j*(-90) +-6 + j*(2) +33 + j*(-94) +-83 + j*(-117) +-119 + j*(-3) +-40 + j*(37) +-17 + j*(-3) +-37 + j*(-3) +-30 + j*(6) +-42 + j*(1) +-52 + j*(42) +6 + j*(63) +35 + j*(1) +-27 + j*(-25) +-57 + j*(37) +-6 + j*(85) +65 + j*(64) +93 + j*(-26) +-6 + j*(-112) +-162 + j*(-6) +-62 + j*(223) +232 + j*(156) +214 + j*(-170) +-101 + j*(-198) +-153 + j*(74) +57 + j*(127) +87 + j*(-12) +13 + j*(11) +103 + j*(54) +158 + j*(-85) +23 + j*(-167) +-68 + j*(-73) +-16 + j*(6) +66 + j*(-13) +106 + j*(-112) +16 + j*(-253) +-206 + j*(-235) +-287 + j*(-20) +-161 + j*(94) +-115 + j*(45) +-179 + j*(110) +-66 + j*(265) +177 + j*(206) +229 + j*(-56) +29 + j*(-212) +-180 + j*(-122) +-211 + j*(67) +-111 + j*(175) +-7 + j*(196) +98 + j*(174) +173 + j*(52) +76 + j*(-78) +-70 + j*(-5) +-7 + j*(144) +130 + j*(100) +120 + j*(18) +137 + j*(25) +191 + j*(-89) +27 + j*(-209) +-123 + j*(-37) +49 + j*(95) +144 + j*(-89) +-53 + j*(-139) +-40 + j*(62) +180 + j*(-23) +50 + j*(-293) +-267 + j*(-175) +-211 + j*(141) +48 + j*(148) +93 + j*(-32) +-21 + j*(-88) +-88 + j*(-21) +-52 + j*(52) +20 + j*(28) +-15 + j*(-39) +-94 + j*(19) +-23 + j*(121) +88 + j*(68) +71 + j*(-22) +28 + j*(-31) +0 + j*(-36) +-36 + j*(21) +67 + j*(81) +156 + j*(-72) +-31 + j*(-177) +-110 + j*(28) +133 + j*(40) +74 + j*(-280) +-330 + j*(-195) +-272 + j*(250) +146 + j*(238) +168 + j*(-88) +-37 + j*(-124) +-72 + j*(-48) +-106 + j*(-19) +-66 + j*(86) +80 + j*(-11) +-115 + j*(-216) +-410 + j*(63) +-127 + j*(443) +249 + j*(223) +89 + j*(-33) +8 + j*(133) +240 + j*(65) +91 + j*(-233) +-233 + j*(-70) +-98 + j*(220) +87 + j*(124) +2 + j*(88) +93 + j*(220) +280 + j*(86) +178 + j*(-92) +82 + j*(-25) +150 + j*(-11) +131 + j*(-62) +169 + j*(-24) +284 + j*(-177) +86 + j*(-409) +-194 + j*(-261) +-110 + j*(-54) +-40 + j*(-146) +-190 + j*(-113) +-112 + j*(75) +57 + j*(-34) +-89 + j*(-157) +-156 + j*(21) +44 + j*(25) +-8 + j*(-208) +-265 + j*(-150) +-250 + j*(71) +-143 + j*(82) +-176 + j*(101) +-104 + j*(218) +48 + j*(175) +52 + j*(69) +42 + j*(62) +76 + j*(-13) +-42 + j*(-117) +-218 + j*(-21) +-216 + j*(183) +-65 + j*(296) +95 + j*(268) +155 + j*(155) +118 + j*(115) +166 + j*(144) +257 + j*(42) +170 + j*(-81) +105 + j*(-21) +202 + j*(-64) +71 + j*(-257) +-216 + j*(-83) +-33 + j*(272) +344 + j*(103) +203 + j*(-236) +-35 + j*(-91) +180 + j*(45) +285 + j*(-255) +-16 + j*(-395) +-144 + j*(-194) +-54 + j*(-185) +-204 + j*(-263) +-358 + j*(-25) +-134 + j*(192) +87 + j*(17) +-61 + j*(-190) +-274 + j*(-67) +-202 + j*(146) +-24 + j*(114) +-71 + j*(-14) +-197 + j*(93) +-50 + j*(267) +165 + j*(129) +54 + j*(-76) +-102 + j*(35) +39 + j*(137) +101 + j*(-47) +-115 + j*(-85) +-144 + j*(139) +53 + j*(161) +45 + j*(17) +-57 + j*(78) +47 + j*(170) +136 + j*(62) +45 + j*(-3) +9 + j*(91) +122 + j*(133) +210 + j*(30) +152 + j*(-102) +6 + j*(-80) +28 + j*(83) +249 + j*(54) +253 + j*(-223) +-12 + j*(-285) +-82 + j*(-117) +-32 + j*(-133) +-198 + j*(-104) +-148 + j*(222) +318 + j*(199) +364 + j*(-360) +-198 + j*(-505) +-407 + j*(-36) +-81 + j*(146) +15 + j*(-82) +-185 + j*(-115) +-231 + j*(62) +-135 + j*(154) +-32 + j*(180) +85 + j*(121) +83 + j*(-10) +-6 + j*(-30) +-6 + j*(5) +-22 + j*(-37) +-99 + j*(20) +-8 + j*(119) +107 + j*(-13) +-62 + j*(-148) +-233 + j*(29) +-110 + j*(229) +69 + j*(205) +139 + j*(107) +148 + j*(-12) +15 + j*(-99) +-117 + j*(44) +35 + j*(213) +230 + j*(81) +153 + j*(-101) +45 + j*(-81) +46 + j*(-70) +-18 + j*(-79) +-33 + j*(27) +107 + j*(33) +115 + j*(-139) +-54 + j*(-181) +-138 + j*(-85) +-167 + j*(-8) +-170 + j*(141) +24 + j*(254) +207 + j*(93) +97 + j*(-66) +15 + j*(45) +188 + j*(88) +281 + j*(-124) +144 + j*(-306) +-56 + j*(-351) +-270 + j*(-260) +-339 + j*(7) +-134 + j*(148) +-58 + j*(4) +-243 + j*(64) +-98 + j*(387) +372 + j*(268) +358 + j*(-269) +-140 + j*(-374) +-326 + j*(1) +-108 + j*(205) +54 + j*(144) +113 + j*(67) +145 + j*(-55) +17 + j*(-186) +-179 + j*(-106) +-173 + j*(105) +6 + j*(173) +120 + j*(52) +62 + j*(-79) +-54 + j*(-76) +-91 + j*(-2) +-81 + j*(37) +-84 + j*(86) +-18 + j*(156) +94 + j*(109) +66 + j*(1) +-30 + j*(43) +35 + j*(156) +177 + j*(122) +224 + j*(-8) +184 + j*(-121) +73 + j*(-189) +-50 + j*(-130) +-21 + j*(-18) +64 + j*(-62) +3 + j*(-136) +-38 + j*(-88) +1 + j*(-141) +-177 + j*(-245) +-417 + j*(-3) +-223 + j*(356) +144 + j*(274) +133 + j*(2) +-23 + j*(29) +54 + j*(130) +156 + j*(40) +117 + j*(-54) +80 + j*(-83) +22 + j*(-125) +-69 + j*(-81) +-42 + j*(8) +26 + j*(-35) +-51 + j*(-103) +-154 + j*(-21) +-129 + j*(120) +-1 + j*(198) +175 + j*(153) +254 + j*(-54) +97 + j*(-231) +-97 + j*(-167) +-103 + j*(-42) +-78 + j*(-31) +-126 + j*(18) +-64 + j*(139) +108 + j*(125) +172 + j*(-43) +69 + j*(-180) +-100 + j*(-182) +-194 + j*(-36) +-94 + j*(103) +51 + j*(16) +-61 + j*(-156) +-307 + j*(-35) +-250 + j*(295) +100 + j*(351) +247 + j*(54) +11 + j*(-116) +-156 + j*(104) +71 + j*(301) +324 + j*(105) +209 + j*(-163) +2 + j*(-124) +25 + j*(-20) +53 + j*(-74) +-29 + j*(-71) +-11 + j*(-1) +18 + j*(-50) +-83 + j*(-41) +-61 + j*(117) +119 + j*(110) +141 + j*(-40) +78 + j*(-63) +103 + j*(-100) +-4 + j*(-199) +-146 + j*(-67) +11 + j*(60) +96 + j*(-160) +-206 + j*(-229) +-296 + j*(124) +49 + j*(225) +127 + j*(-81) +-148 + j*(-121) +-178 + j*(133) +12 + j*(196) +109 + j*(129) +199 + j*(47) +197 + j*(-168) +-59 + j*(-260) +-194 + j*(-43) +-33 + j*(56) +-24 + j*(-89) +-209 + j*(-33) +-154 + j*(204) +91 + j*(205) +155 + j*(6) +28 + j*(-95) +-91 + j*(-32) +-73 + j*(102) +71 + j*(110) +86 + j*(-47) +-96 + j*(-49) +-97 + j*(175) +162 + j*(208) +236 + j*(-28) +86 + j*(-104) +83 + j*(-31) +144 + j*(-143) +-41 + j*(-261) +-227 + j*(-84) +-100 + j*(122) +78 + j*(37) +5 + j*(-104) +-107 + j*(-34) +-36 + j*(46) +-1 + j*(-52) +-163 + j*(-68) +-221 + j*(161) +13 + j*(306) +222 + j*(154) +190 + j*(-35) +95 + j*(-87) +23 + j*(-92) +-39 + j*(-25) +51 + j*(57) +160 + j*(-88) +-40 + j*(-257) +-277 + j*(-37) +-72 + j*(240) +201 + j*(61) +33 + j*(-181) +-167 + j*(-4) +23 + j*(164) +177 + j*(-35) +-9 + j*(-182) +-146 + j*(-37) +-55 + j*(64) +-23 + j*(12) +-80 + j*(59) +23 + j*(174) +213 + j*(78) +189 + j*(-164) +-45 + j*(-227) +-160 + j*(-63) +-71 + j*(49) +1 + j*(5) +-30 + j*(-38) +-71 + j*(-27) +-113 + j*(4) +-131 + j*(110) +4 + j*(221) +197 + j*(117) +167 + j*(-107) +-25 + j*(-143) +-84 + j*(-18) +-26 + j*(17) +-46 + j*(-12) +-90 + j*(59) +-5 + j*(156) +136 + j*(110) +164 + j*(-22) +103 + j*(-94) +66 + j*(-124) +-8 + j*(-197) +-194 + j*(-173) +-287 + j*(54) +-124 + j*(237) +52 + j*(200) +112 + j*(145) +231 + j*(81) +262 + j*(-181) +-52 + j*(-349) +-326 + j*(-77) +-149 + j*(221) +91 + j*(129) +30 + j*(-11) +-32 + j*(62) +56 + j*(96) +81 + j*(35) +79 + j*(51) +174 + j*(16) +170 + j*(-146) +-2 + j*(-214) +-122 + j*(-100) +-80 + j*(30) +39 + j*(37) +77 + j*(-76) +-37 + j*(-143) +-120 + j*(-40) +-34 + j*(30) +1 + j*(-59) +-99 + j*(-75) +-117 + j*(10) +-101 + j*(12) +-173 + j*(83) +-59 + j*(276) +235 + j*(181) +185 + j*(-144) +-124 + j*(-111) +-71 + j*(191) +264 + j*(134) +277 + j*(-245) +-90 + j*(-402) +-404 + j*(-138) +-311 + j*(268) +90 + j*(347) +272 + j*(21) +45 + j*(-173) +-86 + j*(-25) +25 + j*(-8) +-83 + j*(-120) +-233 + j*(86) +33 + j*(272) +226 + j*(-22) +-98 + j*(-202) +-271 + j*(151) +78 + j*(340) +279 + j*(57) +95 + j*(-117) +-16 + j*(-28) +-4 + j*(8) +-40 + j*(69) +78 + j*(198) +313 + j*(81) +272 + j*(-214) +9 + j*(-281) +-112 + j*(-127) +-78 + j*(-23) +-30 + j*(23) +56 + j*(36) +119 + j*(-63) +35 + j*(-156) +-47 + j*(-92) +40 + j*(-49) +76 + j*(-214) +-148 + j*(-326) +-365 + j*(-142) +-317 + j*(88) +-206 + j*(148) +-161 + j*(208) +-7 + j*(267) +136 + j*(120) +17 + j*(-25) +-86 + j*(106) +84 + j*(185) +154 + j*(1) +-25 + j*(-38) +-8 + j*(156) +233 + j*(115) +233 + j*(-157) +8 + j*(-231) +-100 + j*(-129) +-130 + j*(-64) +-159 + j*(37) +-62 + j*(146) +66 + j*(83) +18 + j*(-22) +-67 + j*(44) +8 + j*(146) +142 + j*(98) +158 + j*(-36) +64 + j*(-110) +-27 + j*(-71) +-23 + j*(11) +54 + j*(26) +107 + j*(-57) +52 + j*(-185) +-147 + j*(-221) +-330 + j*(-16) +-221 + j*(300) +131 + j*(345) +312 + j*(74) +192 + j*(-150) +23 + j*(-168) +-71 + j*(-105) +-102 + j*(1) +-19 + j*(91) +97 + j*(45) +91 + j*(-66) +22 + j*(-88) +5 + j*(-83) +-33 + j*(-119) +-137 + j*(-95) +-184 + j*(43) +-74 + j*(170) +91 + j*(133) +119 + j*(-13) +25 + j*(-51) +32 + j*(11) +110 + j*(-62) +6 + j*(-186) +-143 + j*(-97) +-69 + j*(28) +4 + j*(-74) +-153 + j*(-144) +-278 + j*(28) +-190 + j*(209) +-28 + j*(267) +151 + j*(206) +205 + j*(-18) +-10 + j*(-141) +-157 + j*(59) +28 + j*(205) +158 + j*(63) +80 + j*(-13) +98 + j*(9) +91 + j*(-105) +-86 + j*(-76) +-18 + j*(132) +211 + j*(1) +16 + j*(-245) +-234 + j*(1) +52 + j*(231) +251 + j*(-89) +-86 + j*(-255) +-217 + j*(79) +84 + j*(165) +110 + j*(-91) +-110 + j*(-47) +-6 + j*(163) +218 + j*(46) +154 + j*(-189) +-40 + j*(-220) +-156 + j*(-128) +-184 + j*(17) +-69 + j*(131) +78 + j*(55) +26 + j*(-98) +-136 + j*(-69) +-156 + j*(100) +-10 + j*(195) +146 + j*(112) +135 + j*(-62) +-30 + j*(-98) +-86 + j*(69) +99 + j*(153) +250 + j*(-33) +122 + j*(-255) +-124 + j*(-231) +-188 + j*(-32) +-55 + j*(51) +-4 + j*(-64) +-158 + j*(-104) +-240 + j*(84) +-83 + j*(220) +44 + j*(142) +14 + j*(95) +55 + j*(151) +163 + j*(98) +175 + j*(-11) +154 + j*(-71) +121 + j*(-178) +-61 + j*(-245) +-223 + j*(-83) +-134 + j*(109) +23 + j*(90) +40 + j*(-26) +-63 + j*(-75) +-184 + j*(28) +-112 + j*(262) +214 + j*(273) +328 + j*(-78) +25 + j*(-257) +-150 + j*(-34) +-2 + j*(88) +49 + j*(14) +53 + j*(50) +209 + j*(-34) +84 + j*(-334) +-343 + j*(-233) +-317 + j*(254) +139 + j*(308) +239 + j*(-45) +21 + j*(-132) +0 + j*(-38) +14 + j*(-110) +-142 + j*(-103) +-156 + j*(95) +34 + j*(137) +92 + j*(-17) +-23 + j*(-77) +-86 + j*(4) +-31 + j*(71) +35 + j*(28) +-18 + j*(-49) +-136 + j*(23) +-76 + j*(206) +143 + j*(209) +216 + j*(33) +142 + j*(-41) +165 + j*(-47) +182 + j*(-200) +-25 + j*(-333) +-278 + j*(-192) +-284 + j*(89) +-81 + j*(228) +116 + j*(163) +187 + j*(-5) +106 + j*(-158) +-52 + j*(-189) +-170 + j*(-98) +-185 + j*(35) +-110 + j*(132) +-6 + j*(145) +54 + j*(98) +74 + j*(59) +112 + j*(23) +127 + j*(-89) +-16 + j*(-196) +-223 + j*(-80) +-173 + j*(192) +114 + j*(220) +196 + j*(-34) +-5 + j*(-118) +-51 + j*(45) +115 + j*(42) +88 + j*(-138) +-77 + j*(-112) +-34 + j*(0) +28 + j*(-119) +-189 + j*(-197) +-359 + j*(57) +-176 + j*(310) +58 + j*(261) +83 + j*(140) +59 + j*(148) +132 + j*(187) +263 + j*(144) +366 + j*(-21) +301 + j*(-267) +38 + j*(-374) +-177 + j*(-218) +-143 + j*(-13) +6 + j*(8) +45 + j*(-118) +-83 + j*(-208) +-263 + j*(-126) +-303 + j*(107) +-120 + j*(285) +124 + j*(221) +164 + j*(6) +16 + j*(-66) +-30 + j*(45) +92 + j*(52) +81 + j*(-104) +-105 + j*(-95) +-105 + j*(107) +95 + j*(117) +110 + j*(-64) +-30 + j*(-69) +-7 + j*(24) +49 + j*(-38) +-51 + j*(-72) +-76 + j*(49) +45 + j*(69) +59 + j*(-28) +1 + j*(-32) +18 + j*(-15) +1 + j*(-49) +-28 + j*(1) +68 + j*(8) +63 + j*(-148) +-140 + j*(-156) +-158 + j*(49) +18 + j*(35) +-69 + j*(-136) +-291 + j*(12) +-151 + j*(303) +156 + j*(231) +154 + j*(-16) +4 + j*(-32) +25 + j*(35) +49 + j*(-44) +-81 + j*(-60) +-117 + j*(100) +45 + j*(158) +107 + j*(18) +-14 + j*(-22) +-25 + j*(106) +119 + j*(108) +124 + j*(-33) +1 + j*(-24) +39 + j*(105) +204 + j*(71) +243 + j*(-117) +103 + j*(-262) +-107 + j*(-233) +-186 + j*(-18) +9 + j*(117) +169 + j*(-78) +-38 + j*(-264) +-255 + j*(-65) +-93 + j*(146) +71 + j*(24) +-35 + j*(-64) +-45 + j*(53) +103 + j*(7) +45 + j*(-185) +-169 + j*(-179) +-259 + j*(-13) +-221 + j*(146) +-75 + j*(259) +122 + j*(190) +117 + j*(1) +-24 + j*(11) +30 + j*(129) +163 + j*(53) +115 + j*(-79) +39 + j*(-78) +24 + j*(-94) +-67 + j*(-115) +-146 + j*(-1) +-71 + j*(117) +44 + j*(117) +119 + j*(50) +122 + j*(-75) +-22 + j*(-142) +-129 + j*(-4) +-5 + j*(119) +114 + j*(24) +69 + j*(-62) +50 + j*(-61) +43 + j*(-132) +-81 + j*(-155) +-127 + j*(-49) +-80 + j*(-35) +-148 + j*(-53) +-191 + j*(80) +-61 + j*(153) +-11 + j*(72) +-51 + j*(94) +46 + j*(123) +75 + j*(-23) +-107 + j*(-56) +-169 + j*(133) +-46 + j*(234) +39 + j*(260) +209 + j*(301) +429 + j*(98) +305 + j*(-234) +-11 + j*(-199) +-4 + j*(39) +181 + j*(17) +167 + j*(-130) +95 + j*(-141) +110 + j*(-161) +57 + j*(-264) +-107 + j*(-279) +-221 + j*(-151) +-187 + j*(2) +-64 + j*(31) +-30 + j*(-67) +-136 + j*(-105) +-219 + j*(-16) +-222 + j*(110) +-134 + j*(257) +118 + j*(292) +275 + j*(26) +51 + j*(-173) +-101 + j*(43) +176 + j*(127) +243 + j*(-247) +-187 + j*(-356) +-349 + j*(45) +-35 + j*(218) +104 + j*(-2) +-42 + j*(-104) +-130 + j*(-30) +-140 + j*(59) +-53 + j*(153) +100 + j*(58) +-21 + j*(-139) +-265 + j*(11) +-124 + j*(286) +123 + j*(177) +21 + j*(18) +-54 + j*(158) +110 + j*(206) +146 + j*(98) +148 + j*(144) +346 + j*(78) +331 + j*(-241) +21 + j*(-313) +-62 + j*(-134) +-5 + j*(-163) +-192 + j*(-202) +-315 + j*(64) +-100 + j*(282) +128 + j*(213) +204 + j*(84) +226 + j*(-52) +133 + j*(-189) +-13 + j*(-185) +-60 + j*(-127) +-117 + j*(-110) +-192 + j*(11) +-81 + j*(163) +76 + j*(117) +71 + j*(33) +98 + j*(65) +218 + j*(-32) +136 + j*(-245) +-103 + j*(-230) +-140 + j*(-43) +-17 + j*(-5) +2 + j*(-107) +-103 + j*(-146) +-204 + j*(-68) +-201 + j*(74) +-77 + j*(156) +43 + j*(87) +18 + j*(-26) +-78 + j*(-23) +-92 + j*(71) +-6 + j*(110) +65 + j*(51) +54 + j*(-28) +3 + j*(-69) +-63 + j*(-95) +-188 + j*(-63) +-260 + j*(119) +-112 + j*(305) +105 + j*(266) +153 + j*(124) +122 + j*(88) +158 + j*(67) +161 + j*(-8) +119 + j*(-23) +158 + j*(-27) +180 + j*(-141) +59 + j*(-246) +-91 + j*(-214) +-161 + j*(-121) +-182 + j*(-28) +-158 + j*(57) +-108 + j*(107) +-62 + j*(150) +40 + j*(182) +164 + j*(95) +141 + j*(-78) +-38 + j*(-122) +-150 + j*(40) +-28 + j*(221) +210 + j*(173) +235 + j*(-68) +36 + j*(-117) +44 + j*(62) +269 + j*(-25) +148 + j*(-341) +-221 + j*(-246) +-154 + j*(107) +140 + j*(24) +11 + j*(-214) +-194 + j*(-41) +-2 + j*(136) +152 + j*(-42) +34 + j*(-159) +0 + j*(-144) +-70 + j*(-254) +-342 + j*(-173) +-310 + j*(194) +59 + j*(204) +55 + j*(-135) +-282 + j*(-95) +-249 + j*(260) +87 + j*(286) +177 + j*(19) +3 + j*(-105) +-130 + j*(-4) +-79 + j*(127) +51 + j*(107) +32 + j*(-21) +-107 + j*(11) +-69 + j*(170) +93 + j*(142) +66 + j*(13) +-25 + j*(60) +45 + j*(134) +104 + j*(72) +62 + j*(64) +124 + j*(116) +233 + j*(27) +179 + j*(-120) +54 + j*(-121) +39 + j*(-40) +120 + j*(-28) +174 + j*(-146) +57 + j*(-303) +-192 + j*(-267) +-262 + j*(-21) +-100 + j*(103) +-4 + j*(28) +-45 + j*(-1) +-27 + j*(39) +15 + j*(4) +-26 + j*(-27) +-45 + j*(16) +-8 + j*(23) +-14 + j*(3) +-22 + j*(30) +24 + j*(40) +49 + j*(-11) +18 + j*(-54) +-32 + j*(-62) +-83 + j*(-26) +-80 + j*(49) +-13 + j*(76) +18 + j*(38) +1 + j*(34) +29 + j*(61) +78 + j*(30) +78 + j*(-23) +62 + j*(-53) +33 + j*(-89) +-33 + j*(-95) +-72 + j*(-38) +-35 + j*(1) +-16 + j*(-37) +-78 + j*(-54) +-124 + j*(26) +-56 + j*(110) +44 + j*(68) +13 + j*(-25) +-82 + j*(21) +-27 + j*(143) +125 + j*(108) +138 + j*(-32) +62 + j*(-75) +40 + j*(-86) +-35 + j*(-128) +-145 + j*(-28) +-37 + j*(131) +164 + j*(13) +54 + j*(-241) +-240 + j*(-185) +-275 + j*(87) +-105 + j*(175) +-54 + j*(129) +-41 + j*(175) +83 + j*(185) +124 + j*(48) +2 + j*(26) +26 + j*(180) +254 + j*(150) +280 + j*(-119) +47 + j*(-206) +-38 + j*(-61) +35 + j*(-46) +-37 + j*(-86) +-65 + j*(52) +115 + j*(58) +78 + j*(-153) +-162 + j*(-54) +6 + j*(223) +328 + j*(5) +98 + j*(-344) +-228 + j*(-127) +-13 + j*(134) +175 + j*(-97) +-51 + j*(-226) +-109 + j*(-45) +19 + j*(-105) +-165 + j*(-229) +-330 + j*(17) +-105 + j*(196) +25 + j*(25) +-117 + j*(-30) +-136 + j*(91) +-75 + j*(111) +-64 + j*(157) +81 + j*(193) +156 + j*(-6) +-69 + j*(-76) +-107 + j*(180) +178 + j*(200) +199 + j*(-71) +-4 + j*(-74) +49 + j*(42) +105 + j*(-75) +-48 + j*(-87) +-8 + j*(64) +129 + j*(-42) +-34 + j*(-173) +-140 + j*(16) +51 + j*(69) +30 + j*(-128) +-188 + j*(-42) +-73 + j*(185) +127 + j*(80) +44 + j*(-42) +45 + j*(36) +153 + j*(-95) +-71 + j*(-272) +-311 + j*(-13) +-74 + j*(242) +141 + j*(32) +-62 + j*(-125) +-179 + j*(77) +-16 + j*(167) +16 + j*(71) +-38 + j*(141) +119 + j*(219) +250 + j*(59) +155 + j*(-83) +79 + j*(-50) +105 + j*(-57) +56 + j*(-115) +-28 + j*(-63) +15 + j*(38) +155 + j*(28) +233 + j*(-149) +82 + j*(-362) +-228 + j*(-315) +-295 + j*(-9) +-49 + j*(83) +-19 + j*(-139) +-301 + j*(-110) +-281 + j*(252) +97 + j*(297) +186 + j*(-23) +-48 + j*(-92) +-55 + j*(87) +105 + j*(33) +14 + j*(-136) +-166 + j*(-42) +-105 + j*(145) +69 + j*(142) +126 + j*(14) +69 + j*(-76) +-10 + j*(-82) +-33 + j*(-52) +-43 + j*(-77) +-158 + j*(-76) +-227 + j*(112) +-27 + j*(276) +199 + j*(119) +109 + j*(-119) +-103 + j*(-88) +-129 + j*(78) +-34 + j*(158) +71 + j*(153) +141 + j*(63) +81 + j*(-21) +36 + j*(50) +183 + j*(53) +187 + j*(-201) +-153 + j*(-245) +-253 + j*(144) +149 + j*(292) +339 + j*(-86) +25 + j*(-294) +-154 + j*(-68) +-1 + j*(33) +15 + j*(-88) +-103 + j*(-47) +-32 + j*(57) +37 + j*(-40) +-107 + j*(-82) +-166 + j*(107) +23 + j*(222) +186 + j*(107) +190 + j*(-50) +103 + j*(-158) +-57 + j*(-165) +-136 + j*(8) +44 + j*(134) +214 + j*(-54) +40 + j*(-269) +-199 + j*(-137) +-110 + j*(89) +91 + j*(24) +50 + j*(-169) +-138 + j*(-184) +-230 + j*(-40) +-163 + j*(98) +-31 + j*(94) +-35 + j*(-19) +-166 + j*(23) +-93 + j*(205) +140 + j*(119) +37 + j*(-144) +-257 + j*(-19) +-130 + j*(305) +187 + j*(207) +112 + j*(-46) +-50 + j*(41) +73 + j*(127) +92 + j*(-15) +-51 + j*(43) +88 + j*(204) +276 + j*(23) +107 + j*(-150) +25 + j*(11) +241 + j*(-28) +145 + j*(-346) +-242 + j*(-277) +-223 + j*(87) +62 + j*(66) +-9 + j*(-175) +-272 + j*(-85) +-260 + j*(204) +-30 + j*(338) +209 + j*(269) +321 + j*(43) +205 + j*(-158) +29 + j*(-143) +21 + j*(-46) +69 + j*(-63) +43 + j*(-95) +40 + j*(-97) +26 + j*(-156) +-83 + j*(-180) +-163 + j*(-90) +-137 + j*(-2) +-98 + j*(28) +-65 + j*(42) +-40 + j*(33) +-45 + j*(40) +2 + j*(71) +71 + j*(3) +12 + j*(-86) +-49 + j*(-52) +-18 + j*(-75) +-158 + j*(-172) +-394 + j*(39) +-216 + j*(417) +215 + j*(356) +267 + j*(-4) +39 + j*(-91) +-21 + j*(19) +14 + j*(40) +23 + j*(61) +95 + j*(56) +98 + j*(-49) +4 + j*(-43) +59 + j*(7) +77 + j*(-148) +-192 + j*(-173) +-273 + j*(172) +69 + j*(319) +239 + j*(54) +88 + j*(-60) +86 + j*(-1) +102 + j*(-127) +-129 + j*(-129) +-141 + j*(173) +198 + j*(213) +281 + j*(-101) +58 + j*(-202) +4 + j*(-91) +53 + j*(-126) +-39 + j*(-185) +-129 + j*(-119) +-148 + j*(-39) +-126 + j*(63) +30 + j*(96) +95 + j*(-108) +-163 + j*(-204) +-314 + j*(91) +-50 + j*(296) +163 + j*(134) +129 + j*(0) +139 + j*(-59) +47 + j*(-234) +-250 + j*(-158) +-202 + j*(202) +178 + j*(155) +110 + j*(-235) +-288 + j*(-155) +-218 + j*(224) +96 + j*(153) +-20 + j*(-86) +-237 + j*(98) +-28 + j*(359) +277 + j*(214) +241 + j*(-70) +39 + j*(-107) +-6 + j*(23) +114 + j*(50) +146 + j*(-100) +-25 + j*(-165) +-116 + j*(1) +40 + j*(86) +90 + j*(-74) +-91 + j*(-78) +-48 + j*(143) +234 + j*(71) +175 + j*(-279) +-200 + j*(-285) +-286 + j*(40) +-75 + j*(151) +-17 + j*(57) +-71 + j*(105) +59 + j*(202) +235 + j*(68) +175 + j*(-158) +-39 + j*(-190) +-136 + j*(-37) +-61 + j*(75) +27 + j*(76) +87 + j*(53) +165 + j*(-28) +125 + j*(-212) +-119 + j*(-264) +-262 + j*(-40) +-106 + j*(139) +42 + j*(45) +-30 + j*(-46) +-74 + j*(23) +-8 + j*(40) +-19 + j*(-18) +-76 + j*(11) +-53 + j*(69) +-13 + j*(94) +71 + j*(114) +192 + j*(-9) +81 + j*(-239) +-222 + j*(-189) +-243 + j*(119) +6 + j*(170) +20 + j*(-16) +-153 + j*(39) +-67 + j*(248) +168 + j*(204) +190 + j*(6) +79 + j*(-42) +55 + j*(11) +116 + j*(11) +151 + j*(-91) +37 + j*(-217) +-189 + j*(-141) +-180 + j*(150) +139 + j*(216) +272 + j*(-98) +0 + j*(-273) +-162 + j*(-72) +-13 + j*(18) +-18 + j*(-144) +-253 + j*(-80) +-201 + j*(224) +119 + j*(223) +158 + j*(-62) +-76 + j*(-111) +-123 + j*(72) +-8 + j*(115) +5 + j*(85) +42 + j*(146) +187 + j*(103) +190 + j*(-75) +51 + j*(-117) +18 + j*(-45) +43 + j*(-53) +4 + j*(-48) +48 + j*(8) +132 + j*(-81) +28 + j*(-197) +-75 + j*(-110) +22 + j*(-79) +-21 + j*(-257) +-312 + j*(-221) +-363 + j*(127) +-65 + j*(267) +102 + j*(74) +8 + j*(-53) +-57 + j*(-21) +-49 + j*(-23) +-98 + j*(-45) +-168 + j*(1) +-192 + j*(103) +-134 + j*(218) +10 + j*(260) +124 + j*(185) +151 + j*(85) +132 + j*(1) +42 + j*(-52) +-50 + j*(34) +49 + j*(156) +209 + j*(53) +132 + j*(-117) +2 + j*(-72) +53 + j*(-21) +35 + j*(-124) +-127 + j*(-79) +-94 + j*(112) +71 + j*(101) +65 + j*(6) +58 + j*(45) +162 + j*(-21) +55 + j*(-196) +-175 + j*(-70) +-47 + j*(199) +252 + j*(92) +190 + j*(-209) +-69 + j*(-199) +-71 + j*(-8) +73 + j*(-34) +11 + j*(-181) +-168 + j*(-110) +-112 + j*(105) +133 + j*(71) +139 + j*(-204) +-138 + j*(-275) +-276 + j*(-60) +-179 + j*(93) +-94 + j*(119) +18 + j*(148) +162 + j*(6) +26 + j*(-228) +-247 + j*(-132) +-196 + j*(110) +-56 + j*(52) +-201 + j*(25) +-186 + j*(303) +185 + j*(322) +255 + j*(-55) +-76 + j*(-139) +-141 + j*(135) +88 + j*(190) +140 + j*(19) +35 + j*(-28) +-6 + j*(30) +34 + j*(95) +163 + j*(86) +219 + j*(-117) +-15 + j*(-264) +-230 + j*(-56) +-86 + j*(169) +83 + j*(84) +21 + j*(7) +28 + j*(96) +162 + j*(54) +146 + j*(-94) +45 + j*(-119) +13 + j*(-106) +-49 + j*(-112) +-103 + j*(-21) +-24 + j*(58) +58 + j*(6) +44 + j*(-64) +-5 + j*(-103) +-108 + j*(-93) +-155 + j*(63) +35 + j*(171) +190 + j*(-23) +7 + j*(-206) +-175 + j*(-45) +-35 + j*(121) +113 + j*(-3) +18 + j*(-146) +-119 + j*(-103) +-148 + j*(11) +-88 + j*(97) +18 + j*(88) +26 + j*(-2) +-47 + j*(23) +50 + j*(112) +197 + j*(-47) +23 + j*(-272) +-256 + j*(-141) +-197 + j*(119) +-28 + j*(103) +-75 + j*(49) +-61 + j*(182) +146 + j*(168) +223 + j*(-352) +-117 + j*(-362) +-214 + j*(-116) +-118 + j*(-18) +-79 + j*(3) +4 + j*(16) +34 + j*(-110) +-133 + j*(-130) +-123 + j*(67) +101 + j*(-2) +-35 + j*(-277) +-377 + j*(-114) +-243 + j*(260) +86 + j*(173) +13 + j*(-74) +-164 + j*(1) +-120 + j*(128) +-76 + j*(166) +41 + j*(252) +271 + j*(109) +152 + j*(-218) +-205 + j*(-132) +-139 + j*(202) +138 + j*(141) +63 + j*(-48) +-29 + j*(73) +163 + j*(103) +194 + j*(-156) +-71 + j*(-252) +-256 + j*(-65) +-218 + j*(179) +21 + j*(313) +284 + j*(127) +158 + j*(-184) +-140 + j*(-66) +32 + j*(200) +288 + j*(-52) +-25 + j*(-322) +-303 + j*(11) +8 + j*(266) +199 + j*(1) +-21 + j*(-95) +-13 + j*(100) +170 + j*(16) +52 + j*(-146) +-64 + j*(-15) +80 + j*(44) +100 + j*(-100) +-12 + j*(-95) +40 + j*(-29) +87 + j*(-139) +-32 + j*(-217) +-127 + j*(-185) +-219 + j*(-163) +-351 + j*(-13) +-260 + j*(244) +8 + j*(251) +52 + j*(61) +-82 + j*(55) +-55 + j*(198) +103 + j*(207) +172 + j*(102) +163 + j*(34) +175 + j*(-6) +187 + j*(-92) +112 + j*(-191) +-13 + j*(-187) +-48 + j*(-117) +-37 + j*(-129) +-129 + j*(-146) +-194 + j*(-21) +-95 + j*(64) +-56 + j*(-2) +-133 + j*(26) +-59 + j*(139) +74 + j*(41) +-53 + j*(-100) +-219 + j*(56) +-78 + j*(266) +144 + j*(188) +136 + j*(12) +25 + j*(2) +35 + j*(95) +173 + j*(95) +249 + j*(-93) +69 + j*(-274) +-174 + j*(-158) +-117 + j*(83) +91 + j*(48) +60 + j*(-139) +-109 + j*(-133) +-146 + j*(-28) +-153 + j*(18) +-174 + j*(133) +-21 + j*(262) +191 + j*(147) +131 + j*(-84) +-91 + j*(-60) +-91 + j*(168) +141 + j*(219) +254 + j*(37) +179 + j*(-83) +151 + j*(-97) +132 + j*(-204) +-59 + j*(-262) +-197 + j*(-70) +-52 + j*(82) +57 + j*(-21) +-24 + j*(-64) +4 + j*(2) +58 + j*(-95) +-100 + j*(-137) +-112 + j*(71) +148 + j*(45) +110 + j*(-274) +-224 + j*(-282) +-287 + j*(-44) +-231 + j*(-8) +-341 + j*(89) +-217 + j*(372) +134 + j*(326) +149 + j*(50) +1 + j*(65) +110 + j*(130) +159 + j*(-41) +-1 + j*(-98) +-35 + j*(-6) +-40 + j*(-34) +-161 + j*(46) +-49 + j*(272) +239 + j*(190) +215 + j*(-86) +18 + j*(-94) +22 + j*(13) +71 + j*(-9) +58 + j*(-19) +90 + j*(-33) +60 + j*(-100) +-13 + j*(-57) +71 + j*(-2) +117 + j*(-132) +-30 + j*(-194) +-86 + j*(-75) +-5 + j*(-81) +-77 + j*(-177) +-211 + j*(-114) +-216 + j*(12) +-179 + j*(95) +-92 + j*(181) +43 + j*(148) +42 + j*(47) +11 + j*(85) +128 + j*(83) +135 + j*(-89) +-26 + j*(-108) +-13 + j*(-4) +34 + j*(-100) +-165 + j*(-124) +-202 + j*(153) +97 + j*(221) +173 + j*(-41) +-33 + j*(-90) +-23 + j*(67) +114 + j*(-3) +16 + j*(-141) +-141 + j*(-59) +-120 + j*(104) +6 + j*(171) +139 + j*(124) +180 + j*(-7) +117 + j*(-78) +108 + j*(-89) +84 + j*(-193) +-108 + j*(-221) +-190 + j*(-8) +10 + j*(79) +62 + j*(-123) +-175 + j*(-160) +-235 + j*(95) +-3 + j*(199) +134 + j*(30) +48 + j*(-132) +-129 + j*(-153) +-287 + j*(-12) +-277 + j*(249) +-39 + j*(432) +274 + j*(365) +433 + j*(85) +322 + j*(-204) +59 + j*(-260) +-57 + j*(-103) +18 + j*(-27) +33 + j*(-77) +-15 + j*(-50) +49 + j*(-8) +103 + j*(-109) +4 + j*(-202) +-118 + j*(-167) +-178 + j*(-77) +-171 + j*(42) +-45 + j*(113) +62 + j*(-1) +-47 + j*(-123) +-185 + j*(-22) +-116 + j*(124) +4 + j*(99) +1 + j*(15) +-64 + j*(18) +-69 + j*(95) +28 + j*(132) +93 + j*(33) +-4 + j*(-34) +-49 + j*(76) +84 + j*(90) +58 + j*(-60) +-105 + j*(33) +72 + j*(223) +306 + j*(-32) +3 + j*(-308) +-298 + j*(17) +28 + j*(320) +315 + j*(13) +51 + j*(-237) +-146 + j*(-25) +-1 + j*(113) +62 + j*(49) +73 + j*(97) +251 + j*(71) +310 + j*(-189) +95 + j*(-368) +-134 + j*(-315) +-258 + j*(-168) +-263 + j*(39) +-74 + j*(165) +98 + j*(18) +-33 + j*(-171) +-260 + j*(-57) +-216 + j*(215) +39 + j*(288) +199 + j*(135) +175 + j*(-11) +128 + j*(-47) +139 + j*(-87) +107 + j*(-184) +-12 + j*(-233) +-125 + j*(-194) +-191 + j*(-104) +-168 + j*(8) +-58 + j*(2) +-112 + j*(-141) +-364 + j*(-62) +-354 + j*(296) +-7 + j*(395) +122 + j*(168) +4 + j*(133) +89 + j*(241) +245 + j*(127) +202 + j*(-16) +177 + j*(-44) +158 + j*(-179) +-78 + j*(-233) +-194 + j*(-3) +-25 + j*(98) +-21 + j*(-19) +-141 + j*(86) +23 + j*(247) +190 + j*(107) +105 + j*(16) +142 + j*(83) +241 + j*(-56) +65 + j*(-168) +5 + j*(20) +246 + j*(1) +198 + j*(-315) +-134 + j*(-306) +-176 + j*(-57) +-74 + j*(-21) +-92 + j*(25) +76 + j*(118) +253 + j*(-148) +-59 + j*(-423) +-412 + j*(-146) +-233 + j*(209) +33 + j*(124) +-13 + j*(-18) +-54 + j*(36) +2 + j*(25) +-38 + j*(-10) +-30 + j*(65) +95 + j*(10) +16 + j*(-184) +-251 + j*(-123) +-256 + j*(179) +20 + j*(262) +134 + j*(60) +3 + j*(-25) +-24 + j*(76) +87 + j*(51) +25 + j*(-78) +-124 + j*(8) +-28 + j*(175) +152 + j*(83) +81 + j*(-86) +-64 + j*(-41) +-49 + j*(65) +-4 + j*(88) +44 + j*(122) +156 + j*(86) +158 + j*(-56) +40 + j*(-72) +57 + j*(4) +123 + j*(-68) +23 + j*(-143) +-40 + j*(-57) +34 + j*(-45) +-11 + j*(-144) +-154 + j*(-81) +-125 + j*(83) +10 + j*(102) +62 + j*(28) +48 + j*(-32) +-8 + j*(-69) +-83 + j*(-17) +-49 + j*(91) +76 + j*(95) +133 + j*(-16) +76 + j*(-117) +-46 + j*(-124) +-100 + j*(-6) +15 + j*(78) +121 + j*(-42) +18 + j*(-172) +-105 + j*(-120) +-112 + j*(-68) +-171 + j*(-49) +-202 + j*(98) +-40 + j*(182) +48 + j*(47) +-74 + j*(1) +-91 + j*(130) +13 + j*(153) +28 + j*(134) +112 + j*(191) +283 + j*(66) +190 + j*(-181) +-50 + j*(-140) +-25 + j*(47) +116 + j*(8) +77 + j*(-105) +-1 + j*(-88) +-8 + j*(-64) +-26 + j*(-51) +-6 + j*(-22) +13 + j*(-75) +-98 + j*(-91) +-134 + j*(87) +96 + j*(171) +262 + j*(-78) +49 + j*(-341) +-283 + j*(-235) +-309 + j*(95) +-49 + j*(218) +96 + j*(40) +-30 + j*(-72) +-94 + j*(37) +9 + j*(51) +-33 + j*(-47) +-124 + j*(53) +39 + j*(127) +79 + j*(-116) +-263 + j*(-139) +-325 + j*(289) +103 + j*(416) +244 + j*(88) +29 + j*(35) +117 + j*(213) +332 + j*(40) +176 + j*(-206) +-27 + j*(-109) +34 + j*(4) +69 + j*(-52) +26 + j*(-38) +86 + j*(-21) +98 + j*(-133) +-35 + j*(-187) +-146 + j*(-99) +-163 + j*(30) +-75 + j*(153) +102 + j*(144) +151 + j*(-22) +29 + j*(-74) +21 + j*(30) +142 + j*(8) +147 + j*(-128) +60 + j*(-193) +-25 + j*(-213) +-138 + j*(-165) +-137 + j*(-36) +-25 + j*(-57) +-117 + j*(-185) +-313 + j*(-41) +-186 + j*(215) +73 + j*(129) +10 + j*(-91) +-188 + j*(-33) +-156 + j*(150) +-1 + j*(170) +66 + j*(65) +9 + j*(-28) +-105 + j*(-4) +-117 + j*(129) +7 + j*(177) +62 + j*(92) +2 + j*(70) +-1 + j*(146) +91 + j*(202) +249 + j*(173) +368 + j*(-40) +200 + j*(-308) +-124 + j*(-233) +-95 + j*(58) +148 + j*(-4) +25 + j*(-247) +-243 + j*(-95) +-110 + j*(173) +111 + j*(69) +13 + j*(-80) +-71 + j*(30) +45 + j*(75) +62 + j*(-25) +-4 + j*(-7) +66 + j*(32) +112 + j*(-86) +-21 + j*(-180) +-173 + j*(-95) +-192 + j*(79) +-62 + j*(213) +132 + j*(177) +175 + j*(3) +57 + j*(-47) +61 + j*(55) +217 + j*(21) +240 + j*(-191) +69 + j*(-334) +-145 + j*(-303) +-267 + j*(-139) +-214 + j*(37) +-87 + j*(57) +-81 + j*(0) +-100 + j*(49) +-11 + j*(47) +-57 + j*(-75) +-234 + j*(18) +-134 + j*(261) +125 + j*(190) +74 + j*(-13) +-49 + j*(70) +92 + j*(134) +115 + j*(-39) +-58 + j*(3) +84 + j*(188) +326 + j*(-57) +28 + j*(-380) +-365 + j*(-95) +-148 + j*(321) +235 + j*(210) +224 + j*(-69) +118 + j*(-110) +112 + j*(-178) +-54 + j*(-281) +-257 + j*(-122) +-157 + j*(101) +25 + j*(32) +-56 + j*(-122) +-231 + j*(-43) +-213 + j*(147) +-79 + j*(205) +-19 + j*(182) +27 + j*(203) +136 + j*(184) +176 + j*(63) +98 + j*(25) +138 + j*(98) +284 + j*(-20) +152 + j*(-266) +-157 + j*(-163) +-75 + j*(167) +272 + j*(98) +243 + j*(-262) +-79 + j*(-310) +-180 + j*(-104) +-121 + j*(-22) +-129 + j*(17) +-73 + j*(122) +73 + j*(115) +127 + j*(-4) +89 + j*(-89) +13 + j*(-136) +-88 + j*(-99) +-75 + j*(14) +24 + j*(-11) +-43 + j*(-105) +-148 + j*(16) +12 + j*(148) +184 + j*(-37) +13 + j*(-256) +-235 + j*(-158) +-253 + j*(63) +-132 + j*(175) +7 + j*(188) +121 + j*(86) +82 + j*(-61) +-48 + j*(-65) +-71 + j*(22) +-37 + j*(45) +-30 + j*(61) +25 + j*(79) +67 + j*(5) +-13 + j*(-47) +-65 + j*(34) +18 + j*(83) +67 + j*(-1) +-18 + j*(-66) +-122 + j*(-3) +-121 + j*(146) +42 + j*(250) +243 + j*(139) +220 + j*(-100) +18 + j*(-141) +-32 + j*(-6) +63 + j*(11) +41 + j*(-72) +-39 + j*(-31) +7 + j*(40) +64 + j*(-4) +33 + j*(-47) +13 + j*(-38) +-11 + j*(-57) +-86 + j*(-13) +-52 + j*(140) +160 + j*(158) +261 + j*(-52) +122 + j*(-205) +4 + j*(-161) +17 + j*(-146) +-57 + j*(-216) +-218 + j*(-132) +-185 + j*(71) +6 + j*(81) +26 + j*(-89) +-151 + j*(-119) +-225 + j*(56) +-95 + j*(184) +45 + j*(132) +45 + j*(26) +-18 + j*(23) +0 + j*(76) +54 + j*(44) +15 + j*(1) +-4 + j*(78) +135 + j*(101) +208 + j*(-83) +43 + j*(-216) +-100 + j*(-126) +-80 + j*(-51) +-107 + j*(-56) +-152 + j*(42) +-45 + j*(132) +49 + j*(54) +0 + j*(1) +0 + j*(45) +58 + j*(7) +15 + j*(-72) +-64 + j*(-62) +-104 + j*(-23) +-142 + j*(49) +-80 + j*(156) +31 + j*(118) +-28 + j*(48) +-75 + j*(192) +141 + j*(274) +272 + j*(69) +136 + j*(-35) +148 + j*(63) +301 + j*(-52) +177 + j*(-295) +-89 + j*(-259) +-163 + j*(-65) +-95 + j*(74) +64 + j*(137) +232 + j*(-18) +102 + j*(-238) +-108 + j*(-122) +47 + j*(31) +162 + j*(-208) +-146 + j*(-344) +-315 + j*(-50) +-107 + j*(96) +-50 + j*(-24) +-119 + j*(23) +-1 + j*(54) +-10 + j*(-113) +-206 + j*(-80) +-172 + j*(90) +-112 + j*(31) +-278 + j*(105) +-152 + j*(428) +272 + j*(356) +274 + j*(-40) +-8 + j*(-49) +43 + j*(140) +188 + j*(39) +100 + j*(-66) +71 + j*(-19) +104 + j*(-89) +-40 + j*(-136) +-99 + j*(35) +70 + j*(86) +100 + j*(-71) +-41 + j*(-81) +-35 + j*(41) +64 + j*(29) +54 + j*(-48) +4 + j*(-39) +16 + j*(-15) +30 + j*(-28) +23 + j*(-38) +37 + j*(-33) +69 + j*(-82) +5 + j*(-177) +-146 + j*(-139) +-141 + j*(26) +6 + j*(3) +-82 + j*(-157) +-302 + j*(-16) +-176 + j*(260) +77 + j*(187) +21 + j*(42) +0 + j*(155) +213 + j*(106) +161 + j*(-171) +-105 + j*(-142) +-74 + j*(41) +-6 + j*(-48) +-200 + j*(-20) +-127 + j*(281) +233 + j*(215) +174 + j*(-139) +-139 + j*(-53) +-16 + j*(238) +275 + j*(110) +204 + j*(-158) +18 + j*(-156) +-12 + j*(-95) +-54 + j*(-97) +-115 + j*(-15) +-56 + j*(88) +47 + j*(91) +103 + j*(29) +100 + j*(-44) +52 + j*(-76) +48 + j*(-64) +62 + j*(-144) +-107 + j*(-223) +-295 + j*(-20) +-124 + j*(269) +211 + j*(180) +210 + j*(-136) +-30 + j*(-187) +-75 + j*(-37) +23 + j*(-43) +-26 + j*(-152) +-160 + j*(-112) +-173 + j*(-1) +-141 + j*(27) +-179 + j*(72) +-134 + j*(211) +62 + j*(235) +153 + j*(57) +18 + j*(-49) +-91 + j*(59) +-9 + j*(190) +154 + j*(190) +287 + j*(50) +264 + j*(-194) +-6 + j*(-338) +-285 + j*(-137) +-204 + j*(201) +122 + j*(242) +264 + j*(-21) +90 + j*(-225) +-133 + j*(-137) +-104 + j*(73) +94 + j*(60) +81 + j*(-141) +-124 + j*(-130) +-107 + j*(52) +30 + j*(-14) +-123 + j*(-132) +-267 + j*(105) +-4 + j*(286) +173 + j*(42) +-68 + j*(-75) +-126 + j*(203) +191 + j*(258) +284 + j*(-37) +79 + j*(-140) +24 + j*(-43) +53 + j*(-62) +-16 + j*(-51) +40 + j*(43) +168 + j*(-70) +23 + j*(-254) +-206 + j*(-125) +-115 + j*(107) +86 + j*(30) +-8 + j*(-153) +-216 + j*(-48) +-146 + j*(204) +122 + j*(213) +206 + j*(-9) +70 + j*(-124) +-12 + j*(-57) +35 + j*(-30) +35 + j*(-92) +-35 + j*(-102) +-54 + j*(-55) +-30 + j*(-59) +-64 + j*(-103) +-161 + j*(-87) +-221 + j*(37) +-135 + j*(186) +44 + j*(175) +94 + j*(25) +1 + j*(-35) +-40 + j*(4) +-54 + j*(4) +-107 + j*(71) +4 + j*(193) +194 + j*(51) +24 + j*(-204) +-309 + j*(-17) +-148 + j*(399) +307 + j*(319) +320 + j*(-84) +30 + j*(-134) +13 + j*(58) +161 + j*(40) +166 + j*(-69) +151 + j*(-122) +107 + j*(-256) +-153 + j*(-310) +-333 + j*(-22) +-107 + j*(238) +148 + j*(95) +56 + j*(-95) +-53 + j*(-16) +44 + j*(20) +18 + j*(-106) +-148 + j*(-36) +-59 + j*(171) +180 + j*(93) +134 + j*(-147) +-69 + j*(-138) +-74 + j*(8) +19 + j*(6) +6 + j*(-56) +-35 + j*(-47) +-35 + j*(-32) +-45 + j*(-34) +-56 + j*(-30) +-88 + j*(-30) +-137 + j*(29) +-98 + j*(129) +4 + j*(142) +40 + j*(108) +86 + j*(119) +192 + j*(45) +163 + j*(-137) +-23 + j*(-178) +-109 + j*(-47) +-45 + j*(38) +23 + j*(16) +29 + j*(-38) +-18 + j*(-78) +-82 + j*(-54) +-97 + j*(-8) +-124 + j*(24) +-136 + j*(148) +54 + j*(250) +238 + j*(50) +54 + j*(-159) +-132 + j*(24) +81 + j*(172) +197 + j*(-84) +-91 + j*(-178) +-169 + j*(130) +138 + j*(212) +238 + j*(-50) +71 + j*(-148) +27 + j*(-93) +21 + j*(-141) +-101 + j*(-151) +-175 + j*(-35) +-143 + j*(88) +-20 + j*(175) +168 + j*(91) +126 + j*(-157) +-150 + j*(-144) +-145 + j*(139) +122 + j*(133) +107 + j*(-90) +-35 + j*(-45) +81 + j*(3) +63 + j*(-230) +-289 + j*(-218) +-350 + j*(189) +14 + j*(330) +170 + j*(72) +-1 + j*(-24) +-21 + j*(124) +160 + j*(117) +177 + j*(-96) +-41 + j*(-163) +-151 + j*(40) +27 + j*(177) +166 + j*(32) +45 + j*(-67) +13 + j*(75) +225 + j*(71) +252 + j*(-197) +13 + j*(-288) +-76 + j*(-163) +-52 + j*(-177) +-203 + j*(-203) +-318 + j*(5) +-170 + j*(200) +23 + j*(168) +77 + j*(37) +5 + j*(-57) +-119 + j*(-8) +-84 + j*(159) +120 + j*(156) +163 + j*(-39) +38 + j*(-105) +2 + j*(-85) +-69 + j*(-130) +-208 + j*(-8) +-69 + j*(190) +144 + j*(28) +-67 + j*(-190) +-315 + j*(65) +-78 + j*(351) +194 + j*(199) +129 + j*(35) +116 + j*(79) +212 + j*(-13) +105 + j*(-165) +-42 + j*(-103) +-18 + j*(-26) +-33 + j*(-53) +-98 + j*(36) +28 + j*(151) +187 + j*(27) +95 + j*(-152) +-76 + j*(-102) +-53 + j*(45) +81 + j*(30) +79 + j*(-110) +-73 + j*(-139) +-142 + j*(-1) +-56 + j*(91) +11 + j*(70) +44 + j*(74) +137 + j*(27) +115 + j*(-141) +-91 + j*(-153) +-125 + j*(53) +66 + j*(93) +107 + j*(-72) +-11 + j*(-115) +-41 + j*(-74) +-77 + j*(-88) +-153 + j*(-8) +-74 + j*(104) +13 + j*(44) +-59 + j*(32) +12 + j*(166) +238 + j*(53) +144 + j*(-252) +-177 + j*(-214) +-190 + j*(52) +-13 + j*(71) +-35 + j*(-33) +-102 + j*(30) +-28 + j*(89) +14 + j*(33) +-23 + j*(18) +-9 + j*(43) +12 + j*(16) +-22 + j*(-2) +-42 + j*(20) +-49 + j*(36) +-61 + j*(78) +-13 + j*(137) +71 + j*(127) +106 + j*(69) +105 + j*(23) +86 + j*(-14) +47 + j*(-19) +42 + j*(12) +81 + j*(4) +81 + j*(-41) +54 + j*(-64) +29 + j*(-87) +-44 + j*(-96) +-117 + j*(-6) +-57 + j*(128) +97 + j*(144) +198 + j*(35) +192 + j*(-114) +61 + j*(-221) +-120 + j*(-144) +-91 + j*(68) +144 + j*(69) +187 + j*(-185) +-45 + j*(-290) +-186 + j*(-134) +-126 + j*(-23) +-78 + j*(-33) +-77 + j*(-47) +-109 + j*(-83) +-236 + j*(-37) +-226 + j*(202) +79 + j*(271) +223 + j*(-45) +-52 + j*(-234) +-246 + j*(-39) +-148 + j*(95) +-148 + j*(66) +-197 + j*(212) +18 + j*(345) +206 + j*(161) +88 + j*(6) +4 + j*(106) +112 + j*(158) +176 + j*(88) +209 + j*(41) +247 + j*(-77) +134 + j*(-211) +-4 + j*(-175) +-25 + j*(-144) +-153 + j*(-154) +-265 + j*(98) +23 + j*(327) +317 + j*(71) +131 + j*(-193) +-20 + j*(-42) +173 + j*(-32) +96 + j*(-317) +-264 + j*(-239) +-225 + j*(116) +62 + j*(96) +35 + j*(-115) +-110 + j*(-95) +-129 + j*(-40) +-211 + j*(5) +-209 + j*(233) +86 + j*(327) +258 + j*(68) +91 + j*(-89) +32 + j*(23) +170 + j*(-24) +79 + j*(-250) +-222 + j*(-204) +-284 + j*(109) +-35 + j*(264) +156 + j*(127) +106 + j*(-33) +9 + j*(1) +76 + j*(74) +187 + j*(-17) +138 + j*(-182) +-18 + j*(-234) +-148 + j*(-174) +-220 + j*(-49) +-185 + j*(90) +-85 + j*(149) +-6 + j*(161) +112 + j*(158) +230 + j*(0) +107 + j*(-209) +-117 + j*(-146) +-82 + j*(18) +-1 + j*(-53) +-151 + j*(-81) +-170 + j*(132) +49 + j*(147) +28 + j*(-42) +-135 + j*(54) +24 + j*(213) +176 + j*(22) +-32 + j*(-86) +-86 + j*(156) +201 + j*(181) +238 + j*(-119) +-22 + j*(-173) +-73 + j*(19) +60 + j*(59) +112 + j*(-21) +105 + j*(-103) +6 + j*(-199) +-177 + j*(-119) +-129 + j*(101) +83 + j*(54) +-2 + j*(-140) +-205 + j*(7) +-2 + j*(243) +291 + j*(10) +77 + j*(-358) +-356 + j*(-235) +-397 + j*(187) +-103 + j*(388) +156 + j*(310) +265 + j*(131) +234 + j*(-39) +114 + j*(-98) +68 + j*(-42) +121 + j*(-46) +118 + j*(-134) +43 + j*(-175) +-6 + j*(-183) +-94 + j*(-211) +-239 + j*(-127) +-238 + j*(78) +-62 + j*(156) +25 + j*(55) +-22 + j*(17) +-8 + j*(59) +60 + j*(25) +52 + j*(-66) +-31 + j*(-122) +-165 + j*(-97) +-246 + j*(84) +-81 + j*(274) +169 + j*(173) +129 + j*(-61) +-41 + j*(-42) +-1 + j*(53) +28 + j*(-37) +-127 + j*(-18) +-95 + j*(196) +140 + j*(185) +142 + j*(-6) +23 + j*(27) +132 + j*(103) +218 + j*(-57) +79 + j*(-162) +8 + j*(-87) +34 + j*(-99) +-49 + j*(-119) +-70 + j*(-13) +31 + j*(-25) +-42 + j*(-132) +-174 + j*(-13) +-49 + j*(132) +66 + j*(23) +-40 + j*(-21) +-6 + j*(108) +163 + j*(21) +55 + j*(-175) +-128 + j*(-65) +-13 + j*(71) +65 + j*(-69) +-99 + j*(-96) +-74 + j*(76) +100 + j*(-28) +-100 + j*(-233) +-386 + j*(34) +-129 + j*(409) +279 + j*(222) +163 + j*(-144) +-134 + j*(-53) +-40 + j*(199) +188 + j*(122) +153 + j*(-63) +43 + j*(-46) +86 + j*(-2) +121 + j*(-87) +28 + j*(-152) +-52 + j*(-89) +-8 + j*(-25) +50 + j*(-85) +-23 + j*(-180) +-165 + j*(-146) +-204 + j*(-16) +-154 + j*(54) +-144 + j*(88) +-98 + j*(173) +43 + j*(182) +98 + j*(55) +8 + j*(6) +-11 + j*(95) +104 + j*(115) +175 + j*(6) +135 + j*(-130) +-28 + j*(-204) +-218 + j*(-63) +-127 + j*(205) +177 + j*(165) +170 + j*(-130) +-81 + j*(-122) +-25 + j*(62) +99 + j*(-93) +-175 + j*(-198) +-305 + j*(164) +71 + j*(327) +210 + j*(6) +-46 + j*(-25) +81 + j*(217) +372 + j*(-47) +49 + j*(-410) +-353 + j*(-103) +-105 + j*(274) +185 + j*(89) +45 + j*(-71) +21 + j*(68) +194 + j*(-9) +76 + j*(-224) +-145 + j*(-120) +-81 + j*(67) +43 + j*(45) +63 + j*(8) +141 + j*(-40) +125 + j*(-245) +-159 + j*(-333) +-387 + j*(-76) +-262 + j*(242) +52 + j*(285) +228 + j*(51) +97 + j*(-194) +-165 + j*(-156) +-192 + j*(86) +6 + j*(148) +72 + j*(6) +-21 + j*(-44) +-42 + j*(8) +-21 + j*(-8) +-69 + j*(-26) +-122 + j*(25) +-125 + j*(115) +-47 + j*(216) +127 + j*(212) +209 + j*(37) +93 + j*(-69) +43 + j*(0) +126 + j*(-35) +35 + j*(-187) +-184 + j*(-109) +-168 + j*(132) +25 + j*(175) +89 + j*(71) +62 + j*(46) +91 + j*(54) +129 + j*(8) +129 + j*(-59) +84 + j*(-127) +-25 + j*(-149) +-112 + j*(-56) +-74 + j*(61) +32 + j*(75) +75 + j*(9) +45 + j*(-30) +35 + j*(-6) +99 + j*(-19) +99 + j*(-148) +-78 + j*(-198) +-180 + j*(-15) +-16 + j*(105) +88 + j*(-45) +-67 + j*(-121) +-122 + j*(45) +47 + j*(96) +112 + j*(-54) +18 + j*(-138) +-59 + j*(-147) +-173 + j*(-126) +-249 + j*(50) +-78 + j*(206) +102 + j*(76) +4 + j*(-79) +-115 + j*(8) +-25 + j*(96) +45 + j*(4) +-52 + j*(-67) +-154 + j*(13) +-117 + j*(154) +38 + j*(181) +104 + j*(40) +-29 + j*(-26) +-80 + j*(121) +78 + j*(172) +119 + j*(44) +52 + j*(59) +178 + j*(81) +203 + j*(-158) +-105 + j*(-211) +-176 + j*(105) +100 + j*(158) +86 + j*(-57) +-78 + j*(70) +170 + j*(234) +381 + j*(-73) +115 + j*(-324) +-103 + j*(-158) +-21 + j*(-47) +-13 + j*(-86) +-24 + j*(-48) +26 + j*(-95) +-98 + j*(-156) +-170 + j*(23) +34 + j*(74) +33 + j*(-156) +-228 + j*(-105) +-163 + j*(162) +49 + j*(91) +-55 + j*(-23) +-78 + j*(143) +136 + j*(117) +88 + j*(-100) +-74 + j*(-24) +45 + j*(58) +47 + j*(-107) +-160 + j*(-49) +-60 + j*(171) +133 + j*(49) +-1 + j*(-78) +-38 + j*(78) +146 + j*(24) +27 + j*(-180) +-169 + j*(-9) +54 + j*(150) +183 + j*(-133) +-143 + j*(-261) +-291 + j*(56) +-34 + j*(204) +76 + j*(14) +-81 + j*(-49) +-136 + j*(98) +-8 + j*(189) +109 + j*(116) +85 + j*(4) +-1 + j*(27) +54 + j*(110) +161 + j*(28) +81 + j*(-88) +-9 + j*(-13) +81 + j*(32) +89 + j*(-84) +-42 + j*(-56) +25 + j*(90) +211 + j*(2) +165 + j*(-228) +-50 + j*(-291) +-224 + j*(-180) +-269 + j*(36) +-84 + j*(199) +123 + j*(67) +13 + j*(-132) +-170 + j*(-20) +-52 + j*(141) +76 + j*(28) +-49 + j*(-59) +-116 + j*(81) +17 + j*(170) +146 + j*(95) +168 + j*(-48) +49 + j*(-161) +-111 + j*(-78) +-35 + j*(81) +108 + j*(-36) +-85 + j*(-177) +-255 + j*(91) +52 + j*(313) +323 + j*(22) +112 + j*(-261) +-116 + j*(-156) +-99 + j*(-52) +-137 + j*(-53) +-193 + j*(76) +-76 + j*(194) +32 + j*(173) +106 + j*(176) +270 + j*(93) +274 + j*(-181) +8 + j*(-296) +-151 + j*(-134) +-101 + j*(-42) +-129 + j*(-54) +-191 + j*(64) +-76 + j*(199) +84 + j*(156) +115 + j*(51) +105 + j*(1) +103 + j*(-62) +23 + j*(-135) +-111 + j*(-93) +-134 + j*(71) +18 + j*(165) +168 + j*(69) +170 + j*(-89) +86 + j*(-190) +-62 + j*(-257) +-286 + j*(-156) +-298 + j*(162) +30 + j*(271) +175 + j*(-34) +-128 + j*(-179) +-298 + j*(134) +-25 + j*(361) +221 + j*(213) +233 + j*(49) +245 + j*(-49) +184 + j*(-243) +-98 + j*(-312) +-303 + j*(-71) +-190 + j*(200) +52 + j*(226) +160 + j*(67) +76 + j*(-42) +1 + j*(37) +141 + j*(112) +286 + j*(-86) +103 + j*(-325) +-180 + j*(-226) +-165 + j*(12) +-15 + j*(30) +-6 + j*(-50) +-42 + j*(-57) +-66 + j*(-71) +-141 + j*(-52) +-167 + j*(64) +-81 + j*(138) +-5 + j*(130) +53 + j*(117) +122 + j*(42) +70 + j*(-81) +-72 + j*(-55) +-62 + j*(87) +76 + j*(93) +98 + j*(-37) +-18 + j*(-68) +-57 + j*(47) +69 + j*(101) +165 + j*(-36) +36 + j*(-178) +-132 + j*(-77) +-51 + j*(88) +105 + j*(7) +21 + j*(-148) +-135 + j*(-89) +-132 + j*(34) +-95 + j*(84) +-34 + j*(168) +147 + j*(148) +190 + j*(-71) +-7 + j*(-144) +-42 + j*(10) +92 + j*(-43) +-45 + j*(-206) +-257 + j*(-30) +-90 + j*(206) +115 + j*(66) +-11 + j*(-71) +-69 + j*(61) +85 + j*(42) +-3 + j*(-151) +-255 + j*(-30) +-164 + j*(272) +136 + j*(253) +180 + j*(23) +35 + j*(-36) +-21 + j*(70) +77 + j*(161) +246 + j*(105) +296 + j*(-127) +86 + j*(-293) +-139 + j*(-175) +-122 + j*(16) +-23 + j*(62) +29 + j*(76) +148 + j*(69) +228 + j*(-103) +88 + j*(-265) +-78 + j*(-213) +-85 + j*(-136) +-115 + j*(-165) +-247 + j*(-107) +-253 + j*(92) +-76 + j*(185) +58 + j*(76) +3 + j*(-54) +-125 + j*(-25) +-125 + j*(115) +2 + j*(161) +76 + j*(91) +89 + j*(49) +140 + j*(-18) +88 + j*(-181) +-148 + j*(-204) +-255 + j*(20) +-112 + j*(158) +-23 + j*(98) +-56 + j*(100) +-4 + j*(156) +62 + j*(124) +68 + j*(116) +159 + j*(119) +223 + j*(-42) +63 + j*(-168) +-75 + j*(-52) +-2 + j*(51) +45 + j*(11) +22 + j*(23) +86 + j*(39) +112 + j*(-45) +52 + j*(-62) +90 + j*(-48) +91 + j*(-175) +-97 + j*(-210) +-167 + j*(-32) +-47 + j*(19) +-75 + j*(-48) +-134 + j*(64) +28 + j*(141) +114 + j*(-26) +-23 + j*(-104) +-72 + j*(-25) +-67 + j*(-39) +-186 + j*(16) +-132 + j*(243) +148 + j*(263) +255 + j*(40) +181 + j*(-93) +116 + j*(-193) +-99 + j*(-260) +-295 + j*(-11) +-73 + j*(253) +186 + j*(70) +24 + j*(-122) +-80 + j*(49) +122 + j*(68) +71 + j*(-155) +-151 + j*(-36) +57 + j*(177) +284 + j*(-136) +-108 + j*(-418) +-460 + j*(-14) +-102 + j*(373) +259 + j*(76) +0 + j*(-238) +-278 + j*(4) +-77 + j*(258) +132 + j*(125) +50 + j*(5) +30 + j*(89) +156 + j*(59) +136 + j*(-91) +25 + j*(-89) +60 + j*(-50) +67 + j*(-173) +-136 + j*(-235) +-296 + j*(-33) +-186 + j*(202) +47 + j*(213) +152 + j*(32) +25 + j*(-130) +-182 + j*(-38) +-134 + j*(219) +156 + j*(234) +235 + j*(-38) +19 + j*(-140) +-61 + j*(23) +84 + j*(67) +126 + j*(-87) +-25 + j*(-165) +-162 + j*(-55) +-124 + j*(133) +90 + j*(179) +211 + j*(-38) +13 + j*(-212) +-182 + j*(-48) +-60 + j*(128) +51 + j*(36) +-46 + j*(10) +-1 + j*(147) +177 + j*(74) +106 + j*(-110) +-42 + j*(-34) +55 + j*(71) +138 + j*(-32) +71 + j*(-79) +117 + j*(-62) +138 + j*(-248) +-153 + j*(-356) +-378 + j*(-59) +-158 + j*(226) +103 + j*(93) +21 + j*(-108) +-128 + j*(-50) +-100 + j*(57) +-52 + j*(62) +-37 + j*(88) +56 + j*(103) +120 + j*(-14) +18 + j*(-119) +-86 + j*(-52) +-49 + j*(19) +-28 + j*(-16) +-78 + j*(4) +-28 + j*(66) +40 + j*(-21) +-94 + j*(-110) +-235 + j*(46) +-122 + j*(244) +82 + j*(224) +149 + j*(86) +103 + j*(-18) +2 + j*(-36) +-35 + j*(56) +57 + j*(84) +52 + j*(-11) +-54 + j*(59) +101 + j*(197) +290 + j*(-27) +21 + j*(-250) +-200 + j*(57) +144 + j*(256) +317 + j*(-111) +-35 + j*(-231) +-62 + j*(93) +255 + j*(8) +97 + j*(-315) +-196 + j*(-134) +-5 + j*(62) +65 + j*(-169) +-229 + j*(-138) +-146 + j*(197) +177 + j*(89) +48 + j*(-173) +-131 + j*(-8) +79 + j*(94) +136 + j*(-148) +-89 + j*(-189) +-98 + j*(-37) +-33 + j*(-115) +-235 + j*(-156) +-340 + j*(135) +-59 + j*(346) +229 + j*(163) +170 + j*(-139) +-100 + j*(-177) +-182 + j*(55) +35 + j*(134) +83 + j*(-104) +-205 + j*(-132) +-235 + j*(199) +92 + j*(236) +101 + j*(-49) +-137 + j*(12) +4 + j*(226) +203 + j*(23) +-34 + j*(-153) +-190 + j*(95) +35 + j*(227) +117 + j*(71) +25 + j*(83) +146 + j*(158) +243 + j*(-14) +93 + j*(-117) +33 + j*(-8) +132 + j*(-5) +119 + j*(-95) +81 + j*(-100) +89 + j*(-154) +-29 + j*(-220) +-136 + j*(-104) +-52 + j*(-29) +-68 + j*(-131) +-256 + j*(-42) +-174 + j*(246) +167 + j*(237) +245 + j*(-77) +22 + j*(-215) +-128 + j*(-107) +-121 + j*(9) +-64 + j*(64) +8 + j*(53) +4 + j*(-2) +-37 + j*(31) +57 + j*(78) +134 + j*(-76) +-64 + j*(-196) +-221 + j*(20) +-8 + j*(187) +134 + j*(-31) +-113 + j*(-128) +-178 + j*(175) +181 + j*(239) +266 + j*(-146) +-107 + j*(-251) +-209 + j*(91) +103 + j*(182) +199 + j*(-104) +-37 + j*(-228) +-179 + j*(-75) +-117 + j*(39) +-67 + j*(19) +-123 + j*(6) +-182 + j*(136) +-29 + j*(314) +270 + j*(224) +297 + j*(-118) +5 + j*(-243) +-147 + j*(-53) +-59 + j*(62) +-13 + j*(42) +6 + j*(65) +78 + j*(22) +16 + j*(-84) +-120 + j*(-11) +-54 + j*(141) +86 + j*(102) +69 + j*(6) +18 + j*(23) +39 + j*(59) +78 + j*(63) +129 + j*(35) +130 + j*(-42) +67 + j*(-43) +124 + j*(16) +233 + j*(-110) +101 + j*(-299) +-107 + j*(-228) +-93 + j*(-87) +-44 + j*(-103) +-73 + j*(-93) +-12 + j*(-100) +-74 + j*(-272) +-402 + j*(-230) +-477 + j*(182) +-138 + j*(373) +49 + j*(196) +-4 + j*(135) +72 + j*(177) +160 + j*(41) +48 + j*(-70) +-42 + j*(-15) +-48 + j*(32) +-59 + j*(100) +64 + j*(181) +217 + j*(40) +97 + j*(-146) +-69 + j*(-56) +16 + j*(49) +51 + j*(-58) +-100 + j*(-43) +-62 + j*(161) +190 + j*(142) +240 + j*(-128) +1 + j*(-267) +-202 + j*(-106) +-123 + j*(113) +81 + j*(69) +27 + j*(-138) +-227 + j*(-65) +-180 + j*(252) +156 + j*(284) +272 + j*(17) +142 + j*(-124) +55 + j*(-136) +-46 + j*(-150) +-151 + j*(-18) +-26 + j*(148) +173 + j*(47) +125 + j*(-160) +-49 + j*(-190) +-146 + j*(-95) +-146 + j*(23) +-39 + j*(73) +-4 + j*(-42) +-192 + j*(-47) +-214 + j*(250) +153 + j*(349) +335 + j*(-4) +52 + j*(-206) +-117 + j*(13) +78 + j*(148) +223 + j*(-25) +107 + j*(-204) +-91 + j*(-177) +-137 + j*(24) +80 + j*(119) +240 + j*(-135) +-16 + j*(-385) +-337 + j*(-204) +-276 + j*(81) +-131 + j*(95) +-144 + j*(98) +-69 + j*(190) +58 + j*(122) +11 + j*(36) +-13 + j*(97) +72 + j*(85) +51 + j*(5) +15 + j*(36) +71 + j*(20) +8 + j*(-52) +-58 + j*(57) +110 + j*(100) +132 + j*(-136) +-168 + j*(-152) +-199 + j*(187) +130 + j*(242) +191 + j*(-30) +-13 + j*(-49) +32 + j*(131) +248 + j*(64) +243 + j*(-201) +-5 + j*(-322) +-230 + j*(-169) +-196 + j*(75) +-16 + j*(98) +-35 + j*(-2) +-109 + j*(129) +127 + j*(247) +310 + j*(-20) +88 + j*(-214) +-17 + j*(-38) +181 + j*(-79) +35 + j*(-376) +-369 + j*(-230) +-305 + j*(204) +51 + j*(236) +142 + j*(31) +117 + j*(-63) +76 + j*(-205) +-181 + j*(-262) +-340 + j*(21) +-110 + j*(234) +94 + j*(80) +-3 + j*(-83) +-133 + j*(-50) +-197 + j*(47) +-180 + j*(219) +45 + j*(315) +223 + j*(128) +105 + j*(-37) +23 + j*(57) +156 + j*(66) +145 + j*(-112) +-32 + j*(-117) +-41 + j*(13) +35 + j*(-1) +-9 + j*(-37) +-20 + j*(28) +58 + j*(18) +37 + j*(-65) +-47 + j*(-47) +-27 + j*(33) +58 + j*(1) +15 + j*(-119) +-175 + j*(-94) +-216 + j*(169) +78 + j*(308) +295 + j*(36) +76 + j*(-201) +-128 + j*(-14) +61 + j*(145) +202 + j*(-52) +37 + j*(-194) +-88 + j*(-111) +-111 + j*(-56) +-168 + j*(45) +-43 + j*(217) +190 + j*(112) +100 + j*(-115) +-81 + j*(7) +115 + j*(171) +320 + j*(-76) +110 + j*(-345) +-170 + j*(-251) +-202 + j*(-48) +-118 + j*(45) +-31 + j*(53) +4 + j*(-3) +-32 + j*(0) +56 + j*(38) +139 + j*(-158) +-148 + j*(-346) +-462 + j*(-49) +-251 + j*(342) +106 + j*(250) +93 + j*(13) +-2 + j*(1) +-17 + j*(-29) +-165 + j*(-13) +-170 + j*(245) +145 + j*(297) +227 + j*(16) +27 + j*(-17) +124 + j*(132) +296 + j*(-95) +11 + j*(-325) +-241 + j*(-57) +-6 + j*(150) +126 + j*(-81) +-124 + j*(-161) +-195 + j*(89) +9 + j*(161) +58 + j*(30) +-7 + j*(32) +46 + j*(65) +68 + j*(-27) +-42 + j*(-48) +-82 + j*(63) +6 + j*(127) +64 + j*(95) +73 + j*(83) +127 + j*(93) +195 + j*(22) +158 + j*(-81) +71 + j*(-58) +144 + j*(21) +292 + j*(-108) +192 + j*(-371) +-107 + j*(-387) +-221 + j*(-170) +-129 + j*(-66) +-102 + j*(-100) +-140 + j*(-81) +-131 + j*(-42) +-135 + j*(-43) +-150 + j*(-1) +-105 + j*(19) +-119 + j*(-37) +-231 + j*(11) +-203 + j*(185) +-24 + j*(214) +26 + j*(82) +-66 + j*(65) +-45 + j*(161) +74 + j*(134) +50 + j*(-1) +-112 + j*(23) +-123 + j*(243) +134 + j*(355) +374 + j*(153) +311 + j*(-141) +69 + j*(-212) +-59 + j*(-82) +-23 + j*(46) +91 + j*(78) +191 + j*(-21) +141 + j*(-179) +-24 + j*(-198) +-78 + j*(-90) +-41 + j*(-75) +-111 + j*(-91) +-164 + j*(45) +-13 + j*(144) +105 + j*(21) +13 + j*(-90) +-83 + j*(-31) +-72 + j*(54) +-16 + j*(114) +120 + j*(117) +209 + j*(-67) +25 + j*(-232) +-168 + j*(-74) +-19 + j*(94) +112 + j*(-90) +-132 + j*(-218) +-303 + j*(52) +-74 + j*(267) +127 + j*(127) +59 + j*(10) +42 + j*(67) +127 + j*(27) +88 + j*(-70) +38 + j*(-35) +120 + j*(-59) +69 + j*(-244) +-210 + j*(-252) +-332 + j*(38) +-124 + j*(254) +103 + j*(177) +129 + j*(16) +62 + j*(-56) +-5 + j*(-55) +-28 + j*(-5) +31 + j*(23) +71 + j*(-66) +-43 + j*(-142) +-154 + j*(-28) +-56 + j*(91) +49 + j*(-14) +-91 + j*(-120) +-241 + j*(49) +-97 + j*(265) +147 + j*(204) +175 + j*(4) +71 + j*(-74) +1 + j*(-69) +-74 + j*(-44) +-116 + j*(86) +41 + j*(211) +260 + j*(69) +173 + j*(-223) +-151 + j*(-216) +-218 + j*(95) +50 + j*(211) +184 + j*(-8) +11 + j*(-132) +-96 + j*(4) +8 + j*(103) +95 + j*(48) +112 + j*(-3) +138 + j*(-74) +71 + j*(-193) +-90 + j*(-191) +-160 + j*(-76) +-156 + j*(2) +-149 + j*(106) +6 + j*(211) +207 + j*(63) +96 + j*(-185) +-151 + j*(-116) +-106 + j*(91) +28 + j*(43) +-65 + j*(-14) +-70 + j*(153) +167 + j*(157) +202 + j*(-108) +-39 + j*(-171) +-103 + j*(11) +18 + j*(47) +8 + j*(-15) +-13 + j*(47) +106 + j*(54) +124 + j*(-97) +-13 + j*(-128) +-19 + j*(-32) +59 + j*(-93) +-58 + j*(-210) +-235 + j*(-93) +-173 + j*(105) +-12 + j*(91) +-19 + j*(-16) +-87 + j*(3) +-59 + j*(40) +-63 + j*(-13) +-190 + j*(8) +-238 + j*(218) +-28 + j*(414) +288 + j*(330) +379 + j*(11) +155 + j*(-177) +-21 + j*(-29) +142 + j*(110) +308 + j*(-112) +76 + j*(-364) +-228 + j*(-204) +-165 + j*(69) +11 + j*(55) +-9 + j*(-9) +11 + j*(54) +137 + j*(-18) +57 + j*(-210) +-174 + j*(-170) +-202 + j*(40) +-80 + j*(119) +-4 + j*(99) +57 + j*(72) +91 + j*(-23) +2 + j*(-104) +-105 + j*(-46) +-95 + j*(64) +-4 + j*(102) +67 + j*(42) +27 + j*(-38) +-49 + j*(8) +37 + j*(84) +137 + j*(-60) +-59 + j*(-211) +-276 + j*(-4) +-111 + j*(245) +100 + j*(150) +39 + j*(45) +44 + j*(131) +165 + j*(78) +103 + j*(-25) +91 + j*(86) +328 + j*(23) +293 + j*(-351) +-117 + j*(-438) +-303 + j*(-141) +-199 + j*(38) +-134 + j*(95) +3 + j*(163) +148 + j*(17) +15 + j*(-133) +-74 + j*(6) +112 + j*(-8) +0 + j*(-288) +-395 + j*(-139) +-284 + j*(327) +161 + j*(292) +171 + j*(-38) +-12 + j*(-35) +43 + j*(32) +42 + j*(-57) +-28 + j*(-5) +96 + j*(-1) +39 + j*(-228) +-286 + j*(-150) +-209 + j*(217) +135 + j*(122) +-25 + j*(-186) +-325 + j*(42) +-75 + j*(346) +185 + j*(126) +-11 + j*(-35) +-67 + j*(190) +208 + j*(199) +223 + j*(-86) +-15 + j*(-120) +-46 + j*(49) +71 + j*(74) +103 + j*(-5) +66 + j*(-67) +-37 + j*(-75) +-94 + j*(66) +62 + j*(173) +192 + j*(35) +88 + j*(-50) +105 + j*(66) +313 + j*(-35) +223 + j*(-352) +-117 + j*(-362) +-214 + j*(-116) +-118 + j*(-18) +-79 + j*(3) +4 + j*(16) +34 + j*(-110) +-133 + j*(-130) +-123 + j*(67) +101 + j*(-2) +-35 + j*(-277) +-377 + j*(-114) +-243 + j*(260) +86 + j*(173) +13 + j*(-74) +-164 + j*(1) +-120 + j*(128) +-76 + j*(166) +41 + j*(252) +271 + j*(109) +152 + j*(-218) +-205 + j*(-132) +-139 + j*(202) +138 + j*(141) +63 + j*(-48) +-29 + j*(73) +163 + j*(103) +194 + j*(-156) +-71 + j*(-252) +-256 + j*(-65) +-218 + j*(179) +21 + j*(313) +284 + j*(127) +158 + j*(-184) +-140 + j*(-66) +32 + j*(200) +288 + j*(-52) +-25 + j*(-322) +-303 + j*(11) +8 + j*(266) +199 + j*(1) +-21 + j*(-95) +-13 + j*(100) +170 + j*(16) +52 + j*(-146) +-64 + j*(-15) +80 + j*(44) +100 + j*(-100) +-12 + j*(-95) +40 + j*(-29) +87 + j*(-139) +-32 + j*(-217) +-127 + j*(-185) +-219 + j*(-163) +-351 + j*(-13) +-260 + j*(244) +8 + j*(251) +52 + j*(61) +-82 + j*(55) +-55 + j*(198) +103 + j*(207) +172 + j*(102) +163 + j*(34) +175 + j*(-6) +187 + j*(-92) +112 + j*(-191) +-13 + j*(-187) +-48 + j*(-117) +-37 + j*(-129) +-129 + j*(-146) +-194 + j*(-21) +-95 + j*(64) +-56 + j*(-2) +-133 + j*(26) +-59 + j*(139) +74 + j*(41) +-53 + j*(-100) +-219 + j*(56) +-78 + j*(266) +144 + j*(188) +136 + j*(12) +25 + j*(2) +35 + j*(95) +173 + j*(95) +249 + j*(-93) +69 + j*(-274) +-174 + j*(-158) +-117 + j*(83) +91 + j*(48) +60 + j*(-139) +-109 + j*(-133) +-146 + j*(-28) +-153 + j*(18) +-174 + j*(133) +-21 + j*(262) +191 + j*(147) +131 + j*(-84) +-91 + j*(-60) +-91 + j*(168) +141 + j*(219) +254 + j*(37) +179 + j*(-83) +151 + j*(-97) +132 + j*(-204) +-59 + j*(-262) +-197 + j*(-70) +-52 + j*(82) +57 + j*(-21) +-24 + j*(-64) +4 + j*(2) +58 + j*(-95) +-100 + j*(-137) +-112 + j*(71) +148 + j*(45) +110 + j*(-274) +-224 + j*(-282) +-287 + j*(-44) +-231 + j*(-8) +-341 + j*(89) +-217 + j*(372) +134 + j*(326) +149 + j*(50) +1 + j*(65) +110 + j*(130) +159 + j*(-41) +-1 + j*(-98) +-35 + j*(-6) +-40 + j*(-34) +-161 + j*(46) +-49 + j*(272) +239 + j*(190) +215 + j*(-86) +18 + j*(-94) +22 + j*(13) +71 + j*(-9) +58 + j*(-19) +90 + j*(-33) +60 + j*(-100) +-13 + j*(-57) +71 + j*(-2) +117 + j*(-132) +-30 + j*(-194) +-86 + j*(-75) +-5 + j*(-81) +138 + j*(169) +171 + j*(-16) +31 + j*(-37) +76 + j*(78) +231 + j*(-36) +105 + j*(-274) +-192 + j*(-209) +-205 + j*(77) +11 + j*(123) +16 + j*(-23) +-105 + j*(62) +64 + j*(218) +275 + j*(9) +74 + j*(-238) +-168 + j*(-60) +-8 + j*(139) +133 + j*(-11) +-16 + j*(-84) +-25 + j*(78) +161 + j*(52) +138 + j*(-136) +-6 + j*(-127) +21 + j*(-45) +83 + j*(-111) +18 + j*(-208) +-103 + j*(-223) +-221 + j*(-151) +-252 + j*(-1) +-166 + j*(93) +-98 + j*(93) +-58 + j*(98) +-4 + j*(57) +-63 + j*(-6) +-138 + j*(103) +16 + j*(211) +146 + j*(52) +10 + j*(-53) +-27 + j*(73) +110 + j*(28) +-1 + j*(-129) +-175 + j*(21) +-14 + j*(196) +130 + j*(52) +11 + j*(-21) +27 + j*(103) +193 + j*(16) +107 + j*(-202) +-131 + j*(-188) +-225 + j*(0) +-151 + j*(190) +72 + j*(253) +236 + j*(65) +118 + j*(-120) +0 + j*(-57) +58 + j*(-48) +-39 + j*(-142) +-183 + j*(23) +5 + j*(203) +180 + j*(36) +63 + j*(-68) +97 + j*(18) +214 + j*(-175) +-72 + j*(-381) +-351 + j*(-119) +-185 + j*(129) +-79 + j*(41) +-179 + j*(95) +-40 + j*(252) +127 + j*(124) +24 + j*(40) +58 + j*(175) +269 + j*(78) +195 + j*(-171) +1 + j*(-156) +-3 + j*(-79) +-44 + j*(-112) +-129 + j*(-7) +-21 + j*(110) +84 + j*(32) +48 + j*(-4) +119 + j*(15) +174 + j*(-157) +-36 + j*(-284) +-210 + j*(-117) +-117 + j*(38) +-27 + j*(-5) +-57 + j*(-45) +-81 + j*(-31) +-107 + j*(-19) +-129 + j*(36) +-92 + j*(88) +-56 + j*(98) +-28 + j*(129) +60 + j*(140) +129 + j*(58) +108 + j*(-37) +47 + j*(-77) +-11 + j*(-66) +-13 + j*(-17) +44 + j*(-52) +-26 + j*(-168) +-223 + j*(-115) +-238 + j*(111) +-64 + j*(192) +21 + j*(105) +-16 + j*(61) +-45 + j*(96) +-6 + j*(173) +145 + j*(181) +225 + j*(-13) +28 + j*(-133) +-81 + j*(72) +163 + j*(156) +250 + j*(-125) +-13 + j*(-226) +-88 + j*(-43) +2 + j*(-64) +-158 + j*(-110) +-231 + j*(163) +66 + j*(300) +243 + j*(77) +145 + j*(-66) +91 + j*(-82) +-3 + j*(-118) +-97 + j*(46) +150 + j*(188) +357 + j*(-127) +28 + j*(-403) +-263 + j*(-116) +-34 + j*(139) +162 + j*(-49) +13 + j*(-190) +-71 + j*(-94) +-10 + j*(-69) +-17 + j*(-113) +-30 + j*(-117) +-39 + j*(-168) +-137 + j*(-205) +-234 + j*(-144) +-278 + j*(-71) +-324 + j*(36) +-268 + j*(194) +-107 + j*(233) +-40 + j*(147) +-77 + j*(115) +-82 + j*(144) +-68 + j*(184) +1 + j*(250) +151 + j*(223) +182 + j*(59) +47 + j*(4) +1 + j*(134) +144 + j*(217) +321 + j*(108) +336 + j*(-132) +124 + j*(-289) +-108 + j*(-170) +-71 + j*(62) +132 + j*(80) +207 + j*(-77) +137 + j*(-212) +-21 + j*(-270) +-189 + j*(-154) +-143 + j*(55) +40 + j*(48) +29 + j*(-76) +-23 + j*(-30) +86 + j*(-61) +-16 + j*(-259) +-301 + j*(-136) +-191 + j*(176) +76 + j*(64) +-82 + j*(-138) +-248 + j*(69) +-47 + j*(208) +20 + j*(65) +-73 + j*(123) +99 + j*(208) +180 + j*(-16) +-52 + j*(-37) +25 + j*(211) +308 + j*(54) +112 + j*(-242) +-138 + j*(-21) +132 + j*(167) +282 + j*(-146) +-18 + j*(-290) +-132 + j*(-64) +-1 + j*(-25) +-52 + j*(-86) +-66 + j*(31) +93 + j*(6) +41 + j*(-172) +-129 + j*(-120) +-83 + j*(-8) +-58 + j*(-74) +-164 + j*(-30) +-86 + j*(102) +34 + j*(-6) +-129 + j*(-104) +-228 + j*(110) +-2 + j*(228) +122 + j*(19) +-69 + j*(-95) +-194 + j*(75) +-91 + j*(233) +55 + j*(252) +185 + j*(220) +327 + j*(85) +330 + j*(-186) +59 + j*(-378) +-275 + j*(-226) +-273 + j*(152) +69 + j*(266) +235 + j*(-11) +22 + j*(-172) +-91 + j*(0) +83 + j*(44) +72 + j*(-172) +-193 + j*(-160) +-221 + j*(110) +-21 + j*(165) +-10 + j*(71) +-45 + j*(179) +176 + j*(250) +351 + j*(4) +187 + j*(-248) +-58 + j*(-215) +-134 + j*(-49) +-70 + j*(90) +96 + j*(116) +197 + j*(-52) +59 + j*(-202) +-98 + j*(-122) +-70 + j*(-14) +-54 + j*(-15) +-69 + j*(80) +129 + j*(153) +303 + j*(-96) +85 + j*(-378) +-241 + j*(-274) +-278 + j*(-6) +-146 + j*(123) +7 + j*(137) +139 + j*(-3) +30 + j*(-230) +-274 + j*(-177) +-313 + j*(152) +-42 + j*(278) +115 + j*(126) +76 + j*(6) +21 + j*(-25) +-47 + j*(-20) +-79 + j*(77) +37 + j*(151) +155 + j*(52) +115 + j*(-82) +19 + j*(-114) +-53 + j*(-88) +-88 + j*(-23) +-47 + j*(28) +-21 + j*(-10) +-91 + j*(-20) +-108 + j*(88) +8 + j*(125) +48 + j*(22) +-56 + j*(-13) +-115 + j*(101) +-33 + j*(222) +136 + j*(245) +288 + j*(110) +260 + j*(-110) +67 + j*(-175) +-20 + j*(-52) +64 + j*(-1) +83 + j*(-84) +-3 + j*(-98) +-11 + j*(-27) +53 + j*(-38) +29 + j*(-122) +-88 + j*(-127) +-158 + j*(-10) +-103 + j*(127) +46 + j*(177) +194 + j*(92) +219 + j*(-91) +73 + j*(-203) +-47 + j*(-112) +50 + j*(-37) +113 + j*(-226) +-173 + j*(-369) +-459 + j*(-75) +-267 + j*(309) +103 + j*(266) +158 + j*(7) +39 + j*(-69) +-4 + j*(-54) +-42 + j*(-57) +-64 + j*(-7) +-15 + j*(-8) +-68 + j*(-75) +-190 + j*(26) +-75 + j*(214) +159 + j*(127) +119 + j*(-120) +-113 + j*(-125) +-154 + j*(73) +-1 + j*(133) +53 + j*(23) +-35 + j*(-5) +-37 + j*(91) +76 + j*(78) +54 + j*(-48) +-77 + j*(-11) +-22 + j*(120) +104 + j*(47) +5 + j*(-65) +-92 + j*(55) +28 + j*(141) +81 + j*(59) +44 + j*(87) +179 + j*(117) +244 + j*(-84) +56 + j*(-171) +18 + j*(-42) +110 + j*(-112) +-64 + j*(-203) +-151 + j*(35) +129 + j*(78) +115 + j*(-264) +-286 + j*(-228) +-276 + j*(174) +35 + j*(175) +-31 + j*(3) +-115 + j*(204) +204 + j*(310) +392 + j*(-6) +218 + j*(-228) +87 + j*(-224) +16 + j*(-268) +-153 + j*(-245) +-214 + j*(-83) +-144 + j*(-13) +-146 + j*(-17) +-177 + j*(42) +-155 + j*(139) +-41 + j*(238) +184 + j*(183) +202 + j*(-103) +-98 + j*(-148) +-96 + j*(172) +290 + j*(103) +187 + j*(-378) +-361 + j*(-303) +-335 + j*(233) +112 + j*(228) +70 + j*(-117) +-220 + j*(-16) +-105 + j*(269) +175 + j*(218) +240 + j*(-1) +139 + j*(-170) +-76 + j*(-202) +-206 + j*(-1) +-41 + j*(163) +97 + j*(21) +-49 + j*(-71) +-110 + j*(96) +61 + j*(147) +104 + j*(8) +9 + j*(-8) +31 + j*(57) +87 + j*(23) +74 + j*(-18) +83 + j*(-41) +50 + j*(-121) +-93 + j*(-125) +-170 + j*(37) +-49 + j*(194) +160 + j*(169) +248 + j*(-33) +101 + j*(-201) +-77 + j*(-106) +16 + j*(42) +153 + j*(-100) +-37 + j*(-273) +-260 + j*(-90) +-132 + j*(139) +43 + j*(68) +-6 + j*(-21) +-18 + j*(41) +70 + j*(1) +-1 + j*(-109) +-128 + j*(-21) +-35 + j*(126) +136 + j*(49) +116 + j*(-148) +-77 + j*(-223) +-245 + j*(-94) +-228 + j*(111) +-66 + j*(186) +25 + j*(107) +-4 + j*(63) +-1 + j*(93) +39 + j*(82) +38 + j*(65) +63 + j*(76) +94 + j*(30) +45 + j*(6) +70 + j*(89) +226 + j*(30) +187 + j*(-206) +-70 + j*(-217) +-106 + j*(1) +54 + j*(12) +25 + j*(-103) +-43 + j*(-42) +50 + j*(-44) +-26 + j*(-195) +-242 + j*(-65) +-86 + j*(187) +168 + j*(5) +-59 + j*(-237) +-286 + j*(36) +18 + j*(249) +221 + j*(-82) +-111 + j*(-298) +-361 + j*(-28) +-236 + j*(218) +-90 + j*(258) +46 + j*(279) +197 + j*(146) +99 + j*(-45) +-68 + j*(61) +70 + j*(210) +206 + j*(71) +90 + j*(-3) +121 + j*(132) +343 + j*(42) +306 + j*(-258) +44 + j*(-334) +-93 + j*(-221) +-117 + j*(-137) +-129 + j*(-74) +-117 + j*(-31) +-138 + j*(6) +-113 + j*(123) +61 + j*(161) +150 + j*(2) +51 + j*(-83) +28 + j*(-44) +50 + j*(-108) +-72 + j*(-148) +-126 + j*(-25) +-35 + j*(-13) +-116 + j*(-93) +-243 + j*(79) +-44 + j*(286) +213 + j*(133) +146 + j*(-103) +-11 + j*(-98) +-22 + j*(-30) +-7 + j*(-33) +-11 + j*(-42) +-28 + j*(-73) +-112 + j*(-69) +-141 + j*(33) +-66 + j*(71) +-74 + j*(28) +-130 + j*(108) +-23 + j*(220) +121 + j*(146) +100 + j*(47) +80 + j*(74) +177 + j*(49) +192 + j*(-122) +4 + j*(-225) +-177 + j*(-88) +-115 + j*(122) +74 + j*(116) +81 + j*(-32) +-33 + j*(-11) +33 + j*(89) +124 + j*(-4) +15 + j*(-59) +33 + j*(91) +272 + j*(5) +190 + j*(-344) +-204 + j*(-337) +-279 + j*(-7) +-79 + j*(77) +-61 + j*(-11) +-98 + j*(45) +-18 + j*(73) +-5 + j*(12) +-30 + j*(23) +-7 + j*(-3) +-117 + j*(-27) +-175 + j*(190) +113 + j*(332) +339 + j*(58) +153 + j*(-180) +-6 + j*(-69) +95 + j*(-9) +112 + j*(-137) +5 + j*(-180) +-50 + j*(-175) +-165 + j*(-189) +-298 + j*(-45) +-235 + j*(155) +-98 + j*(201) +-30 + j*(216) +103 + j*(233) +236 + j*(89) +165 + j*(-84) +43 + j*(-76) +48 + j*(-39) +39 + j*(-93) +-65 + j*(-92) +-103 + j*(33) +16 + j*(115) +131 + j*(11) +40 + j*(-123) +-109 + j*(-20) +25 + j*(151) +238 + j*(-4) +93 + j*(-249) +-129 + j*(-137) +-25 + j*(4) +26 + j*(-148) +-188 + j*(-151) +-175 + j*(78) +18 + j*(22) +-127 + j*(-142) +-316 + j*(84) +-95 + j*(322) +147 + j*(190) +126 + j*(31) +100 + j*(-28) +6 + j*(-132) +-205 + j*(-31) +-122 + j*(247) +168 + j*(197) +136 + j*(-45) +-29 + j*(11) +76 + j*(120) +163 + j*(-8) +53 + j*(-73) +34 + j*(-1) +80 + j*(-33) +23 + j*(-58) +38 + j*(-1) +97 + j*(-74) +-21 + j*(-153) +-113 + j*(-23) +-6 + j*(59) +35 + j*(-18) +-14 + j*(3) +79 + j*(45) +146 + j*(-105) +-11 + j*(-223) +-163 + j*(-120) +-147 + j*(15) +-73 + j*(63) +-5 + j*(44) +-18 + j*(-26) +-122 + j*(21) +-46 + j*(200) +216 + j*(142) +220 + j*(-159) +-49 + j*(-223) +-127 + j*(-42) +-32 + j*(-11) +-76 + j*(-63) +-124 + j*(33) +-28 + j*(82) +-2 + j*(9) +-49 + j*(31) +21 + j*(60) +26 + j*(-55) +-136 + j*(-30) +-95 + j*(194) +192 + j*(163) +202 + j*(-169) +-139 + j*(-247) +-292 + j*(45) +-106 + j*(243) +64 + j*(181) +78 + j*(105) +98 + j*(102) +156 + j*(51) +143 + j*(-47) +60 + j*(-82) +14 + j*(-37) +42 + j*(-9) +54 + j*(-51) +-11 + j*(-55) +-8 + j*(37) +132 + j*(31) +141 + j*(-167) +-99 + j*(-227) +-214 + j*(21) +16 + j*(170) +176 + j*(-35) +1 + j*(-192) +-143 + j*(-53) +-38 + j*(50) +16 + j*(-36) +-76 + j*(-49) +-75 + j*(47) +4 + j*(50) +15 + j*(9) +35 + j*(7) +62 + j*(-85) +-89 + j*(-181) +-284 + j*(-24) +-200 + j*(250) +75 + j*(296) +235 + j*(119) +209 + j*(-78) +54 + j*(-180) +-109 + j*(-104) +-86 + j*(60) +50 + j*(40) +-7 + j*(-86) +-163 + j*(18) +-50 + j*(236) +219 + j*(178) +261 + j*(-81) +93 + j*(-204) +-46 + j*(-151) +-62 + j*(-53) +9 + j*(-37) +-6 + j*(-150) +-204 + j*(-142) +-251 + j*(129) +44 + j*(235) +179 + j*(-49) +-92 + j*(-185) +-224 + j*(63) +-23 + j*(180) +44 + j*(37) +-61 + j*(49) +11 + j*(160) +138 + j*(74) +73 + j*(-49) +-30 + j*(-4) +-8 + j*(94) +106 + j*(132) +247 + j*(18) +187 + j*(-228) +-112 + j*(-264) +-233 + j*(19) +-22 + j*(182) +129 + j*(60) +98 + j*(-37) +78 + j*(-68) +28 + j*(-122) +-53 + j*(-83) +-20 + j*(-33) +-34 + j*(-88) +-128 + j*(-16) +-5 + j*(105) +121 + j*(-70) +-107 + j*(-190) +-213 + j*(73) +61 + j*(124) +12 + j*(-165) +-330 + j*(-8) +-106 + j*(413) +366 + j*(186) +166 + j*(-272) +-235 + j*(-93) +-61 + j*(252) +247 + j*(101) +165 + j*(-173) +-52 + j*(-185) +-144 + j*(-51) +-87 + j*(78) +44 + j*(53) +-8 + j*(-77) +-158 + j*(33) +-1 + j*(223) +214 + j*(47) +35 + j*(-146) +-105 + j*(49) +132 + j*(135) +194 + j*(-134) +-62 + j*(-203) +-132 + j*(-12) +-42 + j*(33) +-53 + j*(45) +37 + j*(127) +180 + j*(4) +67 + j*(-156) +-43 + j*(-66) +58 + j*(-57) +-21 + j*(-222) +-253 + j*(-117) +-170 + j*(121) +4 + j*(33) +-148 + j*(-78) +-264 + j*(141) +-60 + j*(298) +76 + j*(199) +69 + j*(198) +254 + j*(226) +409 + j*(-74) +118 + j*(-368) +-250 + j*(-156) +-117 + j*(216) +229 + j*(144) +211 + j*(-153) +4 + j*(-170) +17 + j*(-78) +25 + j*(-194) +-210 + j*(-213) +-315 + j*(76) +-71 + j*(266) +132 + j*(136) +108 + j*(-1) +71 + j*(-26) +48 + j*(-62) +-4 + j*(-49) +31 + j*(-17) +52 + j*(-103) +-76 + j*(-139) +-118 + j*(-13) +-18 + j*(-8) +-95 + j*(-107) +-242 + j*(40) +-76 + j*(244) +146 + j*(102) +25 + j*(-105) +-175 + j*(8) +-96 + j*(219) +109 + j*(235) +243 + j*(102) +238 + j*(-103) +35 + j*(-230) +-175 + j*(-71) +-66 + j*(175) +197 + j*(110) +174 + j*(-141) +-46 + j*(-141) +-14 + j*(55) +214 + j*(-29) +127 + j*(-362) +-308 + j*(-368) +-463 + j*(72) +-127 + j*(339) +137 + j*(142) +37 + j*(-33) +-33 + j*(45) +71 + j*(40) +31 + j*(-100) +-148 + j*(-56) +-133 + j*(151) +80 + j*(188) +175 + j*(-13) +-8 + j*(-161) +-218 + j*(16) +-62 + j*(306) +307 + j*(204) +282 + j*(-192) +-77 + j*(-222) +-102 + j*(70) +148 + j*(46) +76 + j*(-195) +-163 + j*(-113) +-102 + j*(98) +49 + j*(60) +26 + j*(-11) +32 + j*(3) +41 + j*(-80) +-122 + j*(-91) +-158 + j*(142) +111 + j*(235) +263 + j*(-9) +100 + j*(-180) +-24 + j*(-112) +-10 + j*(-76) +-56 + j*(-92) +-91 + j*(-4) +8 + j*(40) +39 + j*(-65) +-73 + j*(-80) +-68 + j*(33) +44 + j*(-6) +-33 + j*(-130) +-175 + j*(-30) +-64 + j*(118) +66 + j*(-15) +-110 + j*(-141) +-264 + j*(64) +-81 + j*(255) +96 + j*(142) +45 + j*(30) +16 + j*(57) +28 + j*(26) +-52 + j*(40) +-20 + j*(188) +189 + j*(180) +245 + j*(-30) +107 + j*(-127) +26 + j*(-82) +10 + j*(-51) +16 + j*(-8) +87 + j*(-27) +52 + j*(-146) +-113 + j*(-113) +-96 + j*(65) +66 + j*(48) +40 + j*(-81) +-51 + j*(-44) +-7 + j*(-4) +-27 + j*(-67) +-122 + j*(-4) +-56 + j*(119) +57 + j*(86) +60 + j*(37) +102 + j*(34) +138 + j*(-71) +28 + j*(-156) +-66 + j*(-100) +-81 + j*(-52) +-119 + j*(24) +-2 + j*(164) +234 + j*(32) +120 + j*(-280) +-211 + j*(-208) +-163 + j*(80) +48 + j*(6) +-82 + j*(-158) +-237 + j*(8) +-83 + j*(151) +16 + j*(23) +-105 + j*(-33) +-162 + j*(88) +-88 + j*(173) +-7 + j*(180) +49 + j*(146) +41 + j*(116) +52 + j*(172) +192 + j*(187) +280 + j*(25) +190 + j*(-87) +165 + j*(-76) +192 + j*(-189) +2 + j*(-319) +-212 + j*(-167) +-150 + j*(40) +-28 + j*(29) +-51 + j*(-14) +-64 + j*(33) +-37 + j*(63) +-5 + j*(105) +121 + j*(116) +203 + j*(-59) +33 + j*(-202) +-124 + j*(-63) +-6 + j*(66) +93 + j*(-57) +-46 + j*(-152) +-161 + j*(-16) +-57 + j*(126) +104 + j*(80) +132 + j*(-82) +4 + j*(-183) +-140 + j*(-127) +-165 + j*(3) +-103 + j*(65) +-59 + j*(71) +-27 + j*(72) +-1 + j*(49) +-18 + j*(29) +-30 + j*(56) +-1 + j*(76) +23 + j*(69) +44 + j*(73) +88 + j*(52) +102 + j*(-11) +66 + j*(-52) +34 + j*(-64) +-6 + j*(-72) +-51 + j*(-47) +-64 + j*(-3) +-70 + j*(43) +-40 + j*(127) +103 + j*(165) +236 + j*(36) +203 + j*(-141) +91 + j*(-225) +-43 + j*(-272) +-245 + j*(-207) +-314 + j*(58) +-100 + j*(226) +71 + j*(105) +6 + j*(12) +8 + j*(86) +137 + j*(24) +72 + j*(-169) +-155 + j*(-161) +-243 + j*(38) +-152 + j*(206) +35 + j*(274) +239 + j*(147) +209 + j*(-130) +-77 + j*(-184) +-187 + j*(78) +30 + j*(220) +177 + j*(68) +86 + j*(-40) +37 + j*(33) +138 + j*(57) +199 + j*(-63) +119 + j*(-182) +-6 + j*(-187) +-65 + j*(-117) +-58 + j*(-79) +-84 + j*(-76) +-130 + j*(1) +-47 + j*(105) +95 + j*(50) +74 + j*(-98) +-52 + j*(-102) +-61 + j*(-11) +1 + j*(-19) +-22 + j*(-62) +-42 + j*(-39) +-13 + j*(-65) +-95 + j*(-143) +-254 + j*(-52) +-218 + j*(170) +-1 + j*(207) +68 + j*(42) +-62 + j*(-22) +-127 + j*(99) +-28 + j*(198) +100 + j*(168) +161 + j*(67) +137 + j*(-53) +23 + j*(-115) +-88 + j*(-56) +-102 + j*(47) +-71 + j*(115) +-13 + j*(189) +136 + j*(218) +274 + j*(76) +213 + j*(-101) +94 + j*(-103) +122 + j*(-74) +119 + j*(-194) +-63 + j*(-236) +-153 + j*(-74) +-51 + j*(-9) +-75 + j*(-94) +-219 + j*(11) +-104 + j*(242) +171 + j*(182) +173 + j*(-53) +30 + j*(-60) +84 + j*(1) +123 + j*(-148) +-86 + j*(-216) +-199 + j*(-1) +-18 + j*(121) +79 + j*(-26) +-52 + j*(-82) +-74 + j*(56) +83 + j*(62) +101 + j*(-119) +-90 + j*(-180) +-211 + j*(-8) +-95 + j*(165) +104 + j*(121) +125 + j*(-66) +-21 + j*(-136) +-109 + j*(-46) +-74 + j*(21) +-54 + j*(21) +-50 + j*(49) +8 + j*(59) +33 + j*(-11) +-33 + j*(-55) +-105 + j*(-14) +-122 + j*(79) +-34 + j*(183) +147 + j*(138) +163 + j*(-91) +-69 + j*(-154) +-146 + j*(50) +21 + j*(95) +-13 + j*(-51) +-182 + j*(74) +-1 + j*(296) +258 + j*(112) +97 + j*(-134) +-93 + j*(26) +86 + j*(161) +185 + j*(-30) +3 + j*(-100) +-35 + j*(62) +97 + j*(78) +108 + j*(9) +132 + j*(20) +209 + j*(-88) +66 + j*(-243) +-126 + j*(-114) +-15 + j*(74) +154 + j*(-27) +83 + j*(-182) +-23 + j*(-168) +-54 + j*(-163) +-157 + j*(-145) +-198 + j*(7) +-65 + j*(86) +-8 + j*(4) +-59 + j*(11) +16 + j*(64) +93 + j*(-59) +-44 + j*(-173) +-175 + j*(-67) +-128 + j*(35) +-103 + j*(34) +-101 + j*(98) +22 + j*(112) +37 + j*(-44) +-161 + j*(-40) +-138 + j*(218) +171 + j*(208) +193 + j*(-130) +-136 + j*(-187) +-226 + j*(96) +-24 + j*(198) +43 + j*(97) +25 + j*(105) +112 + j*(83) +74 + j*(-59) +-106 + j*(-1) +-40 + j*(228) +238 + j*(198) +291 + j*(-81) +85 + j*(-223) +-102 + j*(-134) +-134 + j*(42) +-7 + j*(164) +153 + j*(119) +189 + j*(-5) +176 + j*(-74) +160 + j*(-194) +-38 + j*(-299) +-253 + j*(-97) +-90 + j*(166) +163 + j*(25) +18 + j*(-195) +-168 + j*(-37) +6 + j*(115) +129 + j*(-74) +-57 + j*(-192) +-192 + j*(-52) +-152 + j*(83) +-61 + j*(173) +138 + j*(174) +239 + j*(-86) +-32 + j*(-259) +-235 + j*(6) +30 + j*(211) +244 + j*(-52) +16 + j*(-287) +-218 + j*(-146) +-188 + j*(21) +-148 + j*(50) +-149 + j*(127) +-40 + j*(220) +122 + j*(177) +188 + j*(19) +91 + j*(-129) +-91 + j*(-100) +-105 + j*(88) +85 + j*(121) +137 + j*(-74) +-48 + j*(-150) +-143 + j*(8) +-28 + j*(99) +43 + j*(16) +-33 + j*(-38) +-91 + j*(52) +11 + j*(128) +108 + j*(16) +-25 + j*(-107) +-197 + j*(54) +-35 + j*(287) +231 + j*(175) +180 + j*(-54) +37 + j*(-19) +104 + j*(53) +146 + j*(-32) +103 + j*(-37) +197 + j*(-47) +201 + j*(-274) +-88 + j*(-373) +-273 + j*(-151) +-202 + j*(18) +-151 + j*(68) +-64 + j*(161) +115 + j*(89) +55 + j*(-106) +-114 + j*(-28) +2 + j*(107) +102 + j*(-45) +-75 + j*(-107) +-86 + j*(72) +73 + j*(25) +-35 + j*(-103) +-129 + j*(71) +110 + j*(129) +143 + j*(-177) +-216 + j*(-223) +-318 + j*(144) +-21 + j*(317) +190 + j*(157) +169 + j*(-28) +50 + j*(-92) +-35 + j*(-16) +55 + j*(55) +124 + j*(-91) +-76 + j*(-184) +-195 + j*(43) +23 + j*(168) +127 + j*(-21) +-24 + j*(-86) +-48 + j*(16) +-13 + j*(1) +-77 + j*(50) +61 + j*(185) +277 + j*(-13) +76 + j*(-301) +-230 + j*(-147) +-134 + j*(109) +17 + j*(51) +-36 + j*(18) +34 + j*(83) +119 + j*(-69) +-88 + j*(-181) +-231 + j*(35) +-56 + j*(187) +56 + j*(81) +0 + j*(47) +33 + j*(84) +54 + j*(20) +-30 + j*(49) +67 + j*(183) +291 + j*(59) +209 + j*(-247) +-123 + j*(-255) +-218 + j*(47) +18 + j*(204) +210 + j*(45) +127 + j*(-150) +-28 + j*(-127) +-19 + j*(-28) +41 + j*(-64) +-23 + j*(-112) +-67 + j*(-49) +-11 + j*(-40) +-58 + j*(-117) +-178 + j*(-32) +-90 + j*(123) +77 + j*(41) +-18 + j*(-128) +-199 + j*(-32) +-130 + j*(159) +25 + j*(129) +2 + j*(50) +-11 + j*(135) +169 + j*(147) +255 + j*(-99) +20 + j*(-288) +-238 + j*(-140) +-201 + j*(104) +-42 + j*(139) +-18 + j*(82) +-24 + j*(129) +86 + j*(163) +189 + j*(54) +141 + j*(-90) +16 + j*(-121) +-60 + j*(-47) +-37 + j*(35) +34 + j*(42) +54 + j*(-21) +1 + j*(-56) +-64 + j*(-23) +-86 + j*(66) +-4 + j*(176) +185 + j*(168) +293 + j*(-25) +189 + j*(-211) +37 + j*(-234) +-41 + j*(-211) +-153 + j*(-193) +-257 + j*(-36) +-156 + j*(163) +59 + j*(153) +124 + j*(-12) +31 + j*(-100) +-38 + j*(-74) +-36 + j*(-50) +-52 + j*(-71) +-115 + j*(-49) +-112 + j*(33) +-35 + j*(22) +-97 + j*(-69) +-265 + j*(47) +-158 + j*(327) +183 + j*(303) +255 + j*(-6) +49 + j*(-117) +-35 + j*(-29) +-37 + j*(-11) +-100 + j*(52) +-19 + j*(184) +144 + j*(127) +116 + j*(0) +74 + j*(40) +171 + j*(14) +134 + j*(-144) +-31 + j*(-127) +-19 + j*(-9) +37 + j*(-53) +-46 + j*(-69) +-46 + j*(33) +40 + j*(25) +20 + j*(-9) +61 + j*(40) +169 + j*(-71) +25 + j*(-241) +-170 + j*(-106) +-41 + j*(49) +47 + j*(-108) +-164 + j*(-161) +-221 + j*(74) +-23 + j*(134) +0 + j*(1) +-84 + j*(45) +12 + j*(110) +64 + j*(-10) +-69 + j*(-43) +-93 + j*(108) +71 + j*(156) +163 + j*(8) +57 + j*(-125) +-102 + j*(-61) +-56 + j*(121) +161 + j*(79) +127 + j*(-186) +-178 + j*(-166) +-173 + j*(155) +146 + j*(148) +126 + j*(-161) +-166 + j*(-127) +-125 + j*(134) +91 + j*(84) +23 + j*(-89) +-124 + j*(-6) +-51 + j*(129) +67 + j*(97) +84 + j*(18) +59 + j*(-33) +6 + j*(-53) +-37 + j*(-18) +-30 + j*(18) +-25 + j*(32) +-8 + j*(62) +33 + j*(58) +24 + j*(46) +67 + j*(115) +241 + j*(51) +215 + j*(-228) +-107 + j*(-264) +-177 + j*(41) +102 + j*(90) +109 + j*(-188) +-174 + j*(-182) +-178 + j*(73) +10 + j*(71) +-40 + j*(-48) +-136 + j*(58) +-13 + j*(171) +109 + j*(90) +91 + j*(7) +77 + j*(-2) +96 + j*(-32) +83 + j*(-88) +29 + j*(-134) +-59 + j*(-119) +-66 + j*(-29) +28 + j*(-53) +-49 + j*(-205) +-292 + j*(-125) +-271 + j*(165) +-31 + j*(194) +-34 + j*(57) +-119 + j*(175) +101 + j*(296) +293 + j*(71) +163 + j*(-140) +30 + j*(-122) +-22 + j*(-136) +-182 + j*(-74) +-144 + j*(190) +173 + j*(177) +170 + j*(-153) +-148 + j*(-142) +-109 + j*(144) +128 + j*(57) +-21 + j*(-135) +-193 + j*(74) +42 + j*(246) +203 + j*(37) +45 + j*(-69) +21 + j*(54) +144 + j*(16) +93 + j*(-97) +38 + j*(-51) +118 + j*(-80) +45 + j*(-235) +-166 + j*(-204) +-220 + j*(-24) +-149 + j*(75) +-78 + j*(117) +16 + j*(105) +23 + j*(11) +-76 + j*(37) +-7 + j*(185) +194 + j*(125) +190 + j*(-84) +45 + j*(-119) +28 + j*(-83) +-14 + j*(-139) +-162 + j*(-71) +-115 + j*(148) +133 + j*(147) +187 + j*(-83) +16 + j*(-179) +-76 + j*(-82) +-33 + j*(-36) +-30 + j*(-78) +-91 + j*(-79) +-127 + j*(-24) +-125 + j*(30) +-112 + j*(84) +-52 + j*(161) +103 + j*(162) +213 + j*(-22) +71 + j*(-232) +-186 + j*(-186) +-230 + j*(35) +-110 + j*(97) +-126 + j*(50) +-202 + j*(181) +-38 + j*(369) +234 + j*(290) +279 + j*(59) +192 + j*(-30) +180 + j*(-76) +80 + j*(-197) +-156 + j*(-118) +-127 + j*(197) +230 + j*(240) +357 + j*(-110) +89 + j*(-301) +-90 + j*(-158) +-49 + j*(-65) +-64 + j*(-64) +-56 + j*(29) +84 + j*(9) +41 + j*(-170) +-170 + j*(-97) +-65 + j*(140) +202 + j*(-10) +26 + j*(-335) +-357 + j*(-192) +-310 + j*(196) +-2 + j*(245) +78 + j*(64) +8 + j*(8) +-12 + j*(19) +-44 + j*(29) +-33 + j*(104) +85 + j*(107) +105 + j*(-25) +-24 + j*(-45) +-27 + j*(93) +144 + j*(96) +188 + j*(-94) +28 + j*(-198) +-100 + j*(-114) +-93 + j*(-23) +-74 + j*(-4) +-90 + j*(39) +-28 + j*(117) +111 + j*(85) +137 + j*(-92) +-47 + j*(-187) +-205 + j*(-25) +-78 + j*(178) +155 + j*(92) +112 + j*(-166) +-160 + j*(-181) +-235 + j*(68) +-44 + j*(175) +44 + j*(33) +-103 + j*(-21) +-174 + j*(165) +8 + j*(320) +242 + j*(232) +292 + j*(9) +166 + j*(-132) +25 + j*(-111) +-6 + j*(-17) +49 + j*(25) +98 + j*(0) +110 + j*(-52) +78 + j*(-95) +43 + j*(-95) +57 + j*(-105) +17 + j*(-192) +-161 + j*(-177) +-211 + j*(55) +24 + j*(159) +147 + j*(-49) +-27 + j*(-159) +-86 + j*(-21) +30 + j*(-39) +-74 + j*(-160) +-217 + j*(10) +6 + j*(170) +178 + j*(-110) +-146 + j*(-326) +-436 + j*(-13) +-206 + j*(317) +84 + j*(190) +-2 + j*(-10) +-135 + j*(107) +26 + j*(238) +175 + j*(51) +-33 + j*(-112) +-230 + j*(151) +72 + j*(428) +441 + j*(163) +285 + j*(-211) +31 + j*(-141) +122 + j*(-71) +59 + j*(-276) +-257 + j*(-174) +-159 + j*(170) +137 + j*(47) +-65 + j*(-188) +-270 + j*(93) +35 + j*(292) +190 + j*(24) +-17 + j*(-28) +60 + j*(139) +204 + j*(-42) +-46 + j*(-151) +-100 + j*(155) +249 + j*(170) +259 + j*(-165) +19 + j*(-155) +119 + j*(-50) +136 + j*(-286) +-193 + j*(-291) +-197 + j*(45) +93 + j*(-6) +-42 + j*(-261) +-276 + j*(-72) +-58 + j*(115) +63 + j*(-158) +-290 + j*(-265) +-474 + j*(115) +-182 + j*(390) +96 + j*(258) +81 + j*(59) +-41 + j*(51) +-43 + j*(172) +125 + j*(212) +248 + j*(37) +133 + j*(-148) +-28 + j*(-124) +-58 + j*(-66) +-134 + j*(-73) +-265 + j*(95) +-115 + j*(383) +272 + j*(359) +402 + j*(-1) +164 + j*(-211) +-20 + j*(-98) +35 + j*(7) +76 + j*(-46) +15 + j*(-50) +42 + j*(10) +103 + j*(-47) +29 + j*(-105) +1 + j*(-14) +133 + j*(-28) +109 + j*(-211) +-85 + j*(-211) +-73 + j*(-80) +-12 + j*(-185) +-257 + j*(-252) +-415 + j*(74) +-114 + j*(316) +127 + j*(92) +-46 + j*(-83) +-161 + j*(90) +21 + j*(185) +119 + j*(18) +-19 + j*(-86) +-134 + j*(21) +-71 + j*(149) +52 + j*(132) +54 + j*(53) +23 + j*(91) +148 + j*(122) +232 + j*(-80) +6 + j*(-236) +-189 + j*(-35) +-30 + j*(151) +110 + j*(29) +18 + j*(-44) +18 + j*(25) +71 + j*(-54) +-92 + j*(-98) +-150 + j*(140) +132 + j*(248) +313 + j*(-16) +139 + j*(-256) +-113 + j*(-218) +-223 + j*(-1) +-79 + j*(244) +271 + j*(206) +365 + j*(-177) +55 + j*(-370) +-127 + j*(-204) +-74 + j*(-156) +-203 + j*(-210) +-339 + j*(19) +-121 + j*(228) +83 + j*(73) +-7 + j*(-76) +-74 + j*(-42) +-105 + j*(-87) +-296 + j*(-25) +-277 + j*(303) +100 + j*(375) +226 + j*(42) +-40 + j*(-61) +-86 + j*(187) +175 + j*(223) +258 + j*(-19) +107 + j*(-147) +-11 + j*(-129) +-97 + j*(-93) +-180 + j*(18) +-139 + j*(190) +23 + j*(274) +184 + j*(236) +315 + j*(129) +383 + j*(-73) +267 + j*(-321) +-45 + j*(-396) +-294 + j*(-148) +-168 + j*(194) +203 + j*(185) +301 + j*(-173) +-1 + j*(-367) +-240 + j*(-165) +-136 + j*(38) +1 + j*(-26) +-81 + j*(-139) +-235 + j*(-66) +-253 + j*(145) +-54 + j*(307) +235 + j*(204) +265 + j*(-140) +-65 + j*(-286) +-284 + j*(-6) +-80 + j*(246) +168 + j*(127) +129 + j*(-69) +18 + j*(-79) +10 + j*(-55) +-6 + j*(-84) +-62 + j*(-88) +-127 + j*(-64) +-195 + j*(52) +-80 + j*(241) +212 + j*(180) +235 + j*(-160) +-88 + j*(-255) +-211 + j*(1) +-27 + j*(86) +-21 + j*(-64) +-187 + j*(-4) +-112 + j*(192) +86 + j*(136) +46 + j*(-40) +-119 + j*(-14) +-132 + j*(142) +-19 + j*(224) +86 + j*(201) +132 + j*(159) +184 + j*(144) +286 + j*(71) +287 + j*(-121) +101 + j*(-206) +8 + j*(-66) +159 + j*(-26) +183 + j*(-241) +-70 + j*(-322) +-205 + j*(-115) +-80 + j*(1) +-47 + j*(-96) +-193 + j*(-70) +-182 + j*(145) +61 + j*(205) +191 + j*(-12) +30 + j*(-181) +-134 + j*(-75) +-66 + j*(42) +-21 + j*(-38) +-177 + j*(-21) +-162 + j*(250) +190 + j*(324) +389 + j*(-1) +202 + j*(-268) +-9 + j*(-250) +-85 + j*(-190) +-165 + j*(-132) +-175 + j*(-1) +-69 + j*(38) +-55 + j*(-35) +-124 + j*(-18) +-110 + j*(44) +-94 + j*(37) +-130 + j*(83) +-62 + j*(179) +81 + j*(139) +98 + j*(-9) +-30 + j*(-78) +-156 + j*(11) +-132 + j*(190) +69 + j*(250) +196 + j*(72) +58 + j*(-65) +-54 + j*(53) +72 + j*(150) +165 + j*(21) +50 + j*(-70) +-45 + j*(34) +35 + j*(168) +235 + j*(170) +391 + j*(-54) +242 + j*(-366) +-132 + j*(-349) +-209 + j*(-13) +61 + j*(66) +103 + j*(-178) +-140 + j*(-204) +-170 + j*(10) +-18 + j*(20) +-69 + j*(-89) +-191 + j*(18) +-77 + j*(186) +122 + j*(123) +134 + j*(-72) +-21 + j*(-153) +-157 + j*(-62) +-147 + j*(90) +-30 + j*(162) +78 + j*(128) +128 + j*(52) +129 + j*(-39) +54 + j*(-112) +-57 + j*(-70) +-37 + j*(69) +148 + j*(86) +257 + j*(-141) +59 + j*(-385) +-279 + j*(-310) +-349 + j*(4) +-136 + j*(132) +-54 + j*(-13) +-226 + j*(-44) +-296 + j*(187) +-86 + j*(364) +149 + j*(270) +174 + j*(87) +90 + j*(40) +105 + j*(76) +181 + j*(-5) +86 + j*(-147) +-91 + j*(-65) +-9 + j*(110) +159 + j*(-8) +-11 + j*(-176) +-190 + j*(42) +68 + j*(233) +261 + j*(-37) +21 + j*(-206) +-69 + j*(-16) +96 + j*(-71) +-120 + j*(-277) +-433 + j*(43) +-113 + j*(453) +306 + j*(214) +134 + j*(-105) +-35 + j*(83) +228 + j*(158) +294 + j*(-152) +21 + j*(-230) +-8 + j*(-52) +100 + j*(-127) +-74 + j*(-223) +-178 + j*(4) +83 + j*(98) +169 + j*(-205) +-161 + j*(-320) +-317 + j*(-17) +-81 + j*(132) +8 + j*(-56) +-179 + j*(-90) +-199 + j*(103) +-43 + j*(113) +-83 + j*(4) +-197 + j*(112) +-80 + j*(269) +73 + j*(223) +95 + j*(174) +190 + j*(176) +292 + j*(6) +148 + j*(-172) +-16 + j*(-81) +67 + j*(17) +118 + j*(-107) +-34 + j*(-157) +-94 + j*(-16) +16 + j*(43) +71 + j*(-37) +34 + j*(-95) +-16 + j*(-122) +-96 + j*(-127) +-170 + j*(-51) +-168 + j*(58) +-98 + j*(134) +1 + j*(136) +44 + j*(64) +-2 + j*(47) +29 + j*(110) +141 + j*(53) +81 + j*(-95) +-76 + j*(-31) +3 + j*(137) +197 + j*(63) +176 + j*(-136) +30 + j*(-194) +-62 + j*(-160) +-128 + j*(-101) +-132 + j*(-6) +-75 + j*(22) +-81 + j*(8) +-88 + j*(57) +-30 + j*(64) +-62 + j*(31) +-95 + j*(136) +72 + j*(214) +193 + j*(50) +74 + j*(-64) +23 + j*(25) +122 + j*(24) +123 + j*(-87) +58 + j*(-127) +1 + j*(-174) +-169 + j*(-155) +-218 + j*(85) +28 + j*(179) +113 + j*(-44) +-93 + j*(-81) +-86 + j*(119) +101 + j*(91) +65 + j*(-50) +4 + j*(-4) +80 + j*(-27) +-8 + j*(-143) +-153 + j*(-26) +-38 + j*(117) +76 + j*(17) +-6 + j*(-52) +-33 + j*(6) +-18 + j*(-1) +-59 + j*(51) +66 + j*(141) +221 + j*(-31) +57 + j*(-251) +-185 + j*(-149) +-173 + j*(52) +-64 + j*(115) +47 + j*(105) +112 + j*(-37) +-73 + j*(-145) +-216 + j*(90) +59 + j*(261) +247 + j*(-18) +-3 + j*(-190) +-117 + j*(4) +4 + j*(30) +-83 + j*(-12) +-57 + j*(210) +305 + j*(148) +264 + j*(-318) +-233 + j*(-344) +-327 + j*(86) +-46 + j*(213) +59 + j*(112) +123 + j*(61) +132 + j*(-136) +-174 + j*(-194) +-283 + j*(185) +114 + j*(347) +311 + j*(16) +122 + j*(-151) +63 + j*(-121) +-25 + j*(-228) +-282 + j*(-91) +-136 + j*(250) +212 + j*(86) +-5 + j*(-243) +-327 + j*(39) +-32 + j*(371) +282 + j*(131) +129 + j*(-94) +45 + j*(4) +151 + j*(-32) +63 + j*(-173) +-78 + j*(-105) +-53 + j*(-16) +-42 + j*(-6) +-19 + j*(64) +116 + j*(46) +123 + j*(-122) +-24 + j*(-168) +-87 + j*(-91) +-96 + j*(-54) +-105 + j*(11) +-15 + j*(45) +6 + j*(-69) +-151 + j*(-69) +-148 + j*(140) +89 + j*(154) +129 + j*(-83) +-83 + j*(-156) +-197 + j*(5) +-127 + j*(157) +31 + j*(202) +190 + j*(87) +156 + j*(-146) +-85 + j*(-204) +-216 + j*(-30) +-155 + j*(107) +-95 + j*(154) +-13 + j*(214) +136 + j*(175) +153 + j*(21) +40 + j*(-1) +65 + j*(89) +175 + j*(22) +105 + j*(-119) +-43 + j*(-61) +13 + j*(91) +191 + j*(42) +188 + j*(-163) +1 + j*(-242) +-140 + j*(-134) +-145 + j*(11) +-46 + j*(112) +123 + j*(88) +182 + j*(-113) +-4 + j*(-250) +-164 + j*(-119) +-84 + j*(-23) +-111 + j*(-127) +-332 + j*(-11) +-223 + j*(346) +188 + j*(330) +250 + j*(-14) +39 + j*(-63) +91 + j*(49) +187 + j*(-119) +-20 + j*(-245) +-148 + j*(-88) +-70 + j*(-34) +-145 + j*(-76) +-208 + j*(101) +6 + j*(201) +101 + j*(0) +-80 + j*(-46) +-74 + j*(122) +69 + j*(79) +-21 + j*(-8) +-45 + j*(161) +223 + j*(167) +260 + j*(-165) +-73 + j*(-249) +-171 + j*(35) +70 + j*(114) +132 + j*(-117) +-102 + j*(-209) +-268 + j*(-11) +-166 + j*(224) +73 + j*(252) +189 + j*(76) +90 + j*(-40) +28 + j*(37) +148 + j*(68) +208 + j*(-92) +79 + j*(-209) +-41 + j*(-173) +-88 + j*(-124) +-132 + j*(-63) +-104 + j*(26) +-31 + j*(5) +-103 + j*(-40) +-168 + j*(113) +37 + j*(241) +228 + j*(40) +66 + j*(-176) +-133 + j*(-46) +-21 + j*(117) +107 + j*(22) +41 + j*(-64) +28 + j*(-28) +63 + j*(-115) +-113 + j*(-202) +-288 + j*(13) +-102 + j*(262) +165 + j*(146) +112 + j*(-84) +-59 + j*(-62) +-39 + j*(65) +69 + j*(44) +68 + j*(-50) +-1 + j*(-81) +-45 + j*(-60) +-72 + j*(-40) +-107 + j*(0) +-97 + j*(94) +23 + j*(130) +104 + j*(6) +-19 + j*(-107) +-163 + j*(2) +-98 + j*(163) +32 + j*(159) +57 + j*(105) +67 + j*(107) +103 + j*(98) +129 + j*(96) +221 + j*(78) +284 + j*(-74) +160 + j*(-206) +58 + j*(-151) +107 + j*(-152) +34 + j*(-272) +-140 + j*(-206) +-98 + j*(-59) +-9 + j*(-129) +-130 + j*(-213) +-245 + j*(-123) +-288 + j*(-35) +-350 + j*(134) +-155 + j*(395) +218 + j*(272) +158 + j*(-80) +-105 + j*(11) +93 + j*(211) +281 + j*(-88) +-50 + j*(-284) +-209 + j*(13) +38 + j*(69) +-41 + j*(-163) +-296 + j*(27) +-74 + j*(295) +156 + j*(88) +-33 + j*(-39) +-42 + j*(158) +167 + j*(74) +14 + j*(-136) +-183 + j*(77) +65 + j*(263) +221 + j*(14) +-19 + j*(-74) +-25 + j*(204) +338 + j*(187) +400 + j*(-231) +31 + j*(-421) +-223 + j*(-202) +-164 + j*(-1) +-90 + j*(11) +-108 + j*(50) +-28 + j*(141) +110 + j*(79) +81 + j*(-49) +1 + j*(-29) +44 + j*(-4) +22 + j*(-83) +-86 + j*(-19) +19 + j*(105) +155 + j*(-39) +-16 + j*(-174) +-126 + j*(8) +58 + j*(71) +61 + j*(-107) +-94 + j*(-41) +53 + j*(81) +152 + j*(-152) +-134 + j*(-249) +-212 + j*(27) +13 + j*(31) +-108 + j*(-165) +-331 + j*(65) +-63 + j*(331) +197 + j*(100) +23 + j*(-91) +-70 + j*(56) +72 + j*(66) +44 + j*(-62) +-47 + j*(-30) +-16 + j*(-4) +-71 + j*(-36) +-115 + j*(84) +42 + j*(141) +95 + j*(-24) +-60 + j*(-59) +-73 + j*(71) +12 + j*(56) +-54 + j*(25) +-49 + j*(161) +138 + j*(169) +171 + j*(-16) +31 + j*(-37) +76 + j*(78) +231 + j*(-36) +105 + j*(-274) +-192 + j*(-209) +-205 + j*(77) +11 + j*(123) +16 + j*(-23) +-105 + j*(62) +64 + j*(218) +275 + j*(9) +74 + j*(-238) +-168 + j*(-60) +-8 + j*(139) +133 + j*(-11) +-16 + j*(-84) +-25 + j*(78) +161 + j*(52) +138 + j*(-136) +-6 + j*(-127) +21 + j*(-45) +83 + j*(-111) +18 + j*(-208) +-103 + j*(-223) +-221 + j*(-151) +-252 + j*(-1) +-166 + j*(93) +-98 + j*(93) +-58 + j*(98) +-4 + j*(57) +-63 + j*(-6) +-138 + j*(103) +16 + j*(211) +146 + j*(52) +10 + j*(-53) +-27 + j*(73) +110 + j*(28) +-1 + j*(-129) +-175 + j*(21) +-14 + j*(196) +130 + j*(52) +11 + j*(-21) +27 + j*(103) +193 + j*(16) +107 + j*(-202) +-131 + j*(-188) +-225 + j*(0) +-151 + j*(190) +72 + j*(253) +236 + j*(65) +118 + j*(-120) +0 + j*(-57) +58 + j*(-48) +-39 + j*(-142) +-183 + j*(23) +5 + j*(203) +180 + j*(36) +63 + j*(-68) +97 + j*(18) +214 + j*(-175) +-72 + j*(-381) +-351 + j*(-119) +-185 + j*(129) +-79 + j*(41) +-179 + j*(95) +-40 + j*(252) +127 + j*(124) +24 + j*(40) +58 + j*(175) +269 + j*(78) +195 + j*(-171) +1 + j*(-156) +-3 + j*(-79) +-44 + j*(-112) +-129 + j*(-7) +-21 + j*(110) +84 + j*(32) +48 + j*(-4) +119 + j*(15) +174 + j*(-157) +-36 + j*(-284) +-210 + j*(-117) +-117 + j*(38) +-27 + j*(-5) +-57 + j*(-45) +-81 + j*(-31) +-107 + j*(-19) +-129 + j*(36) +-92 + j*(88) +-56 + j*(98) +-28 + j*(129) +60 + j*(140) +129 + j*(58) +108 + j*(-37) +47 + j*(-77) +-11 + j*(-66) +-13 + j*(-17) +44 + j*(-52) +-26 + j*(-168) +-223 + j*(-115) +-238 + j*(111) +-64 + j*(192) +21 + j*(105) +-16 + j*(61) +-45 + j*(96) +-6 + j*(173) +145 + j*(181) +225 + j*(-13) +28 + j*(-133) +-81 + j*(72) +163 + j*(156) +250 + j*(-125) +-13 + j*(-226) +-88 + j*(-43) +2 + j*(-64) +-158 + j*(-110) +-231 + j*(163) +66 + j*(300) +243 + j*(77) +145 + j*(-66) +91 + j*(-82) +-3 + j*(-118) +-97 + j*(46) +150 + j*(188) +357 + j*(-127) +28 + j*(-403) +-263 + j*(-116) +-34 + j*(139) +162 + j*(-49) +13 + j*(-190) +-71 + j*(-94) +-10 + j*(-69) +-17 + j*(-113) +-30 + j*(-117) +-39 + j*(-168) +-137 + j*(-205) +-234 + j*(-144) +-278 + j*(-71) +-324 + j*(36) +-268 + j*(194) +-107 + j*(233) +-40 + j*(147) +144 + j*(100) +114 + j*(-139) +-59 + j*(-81) +41 + j*(-2) +23 + j*(-161) +-189 + j*(-74) +-52 + j*(148) +144 + j*(-46) +-123 + j*(-207) +-264 + j*(122) +91 + j*(254) +206 + j*(-91) +-107 + j*(-187) +-196 + j*(83) +6 + j*(176) +105 + j*(62) +81 + j*(-24) +15 + j*(-57) +-35 + j*(6) +52 + j*(47) +86 + j*(-85) +-80 + j*(-120) +-107 + j*(52) +46 + j*(39) +-36 + j*(-94) +-171 + j*(52) +12 + j*(190) +124 + j*(6) +-62 + j*(-54) +-77 + j*(151) +130 + j*(168) +180 + j*(26) +166 + j*(-25) +178 + j*(-141) +-4 + j*(-233) +-127 + j*(-46) +69 + j*(38) +97 + j*(-207) +-206 + j*(-209) +-213 + j*(114) +80 + j*(118) +58 + j*(-122) +-129 + j*(-64) +-42 + j*(75) +59 + j*(-29) +-37 + j*(-95) +-54 + j*(-34) +-23 + j*(-101) +-174 + j*(-157) +-306 + j*(5) +-240 + j*(180) +-135 + j*(243) +-26 + j*(291) +132 + j*(257) +208 + j*(124) +208 + j*(8) +157 + j*(-139) +-93 + j*(-210) +-298 + j*(95) +19 + j*(426) +450 + j*(151) +264 + j*(-317) +-165 + j*(-221) +-127 + j*(117) +110 + j*(104) +114 + j*(-34) +76 + j*(-50) +64 + j*(-108) +-61 + j*(-112) +-74 + j*(44) +88 + j*(50) +76 + j*(-103) +-59 + j*(-65) +11 + j*(50) +115 + j*(-42) +33 + j*(-141) +-35 + j*(-100) +-25 + j*(-98) +-86 + j*(-113) +-129 + j*(-36) +-80 + j*(10) +-71 + j*(-4) +-76 + j*(33) +-16 + j*(42) +-2 + j*(-22) +-56 + j*(-44) +-93 + j*(-27) +-144 + j*(9) +-151 + j*(122) +-30 + j*(186) +37 + j*(105) +-25 + j*(115) +68 + j*(235) +293 + j*(144) +298 + j*(-127) +99 + j*(-245) +-52 + j*(-191) +-116 + j*(-89) +-85 + j*(19) +25 + j*(21) +33 + j*(-80) +-43 + j*(-100) +-53 + j*(-90) +-119 + j*(-156) +-303 + j*(-93) +-355 + j*(148) +-214 + j*(329) +-27 + j*(395) +199 + j*(349) +314 + j*(112) +151 + j*(-49) +52 + j*(86) +244 + j*(121) +284 + j*(-127) +49 + j*(-185) +27 + j*(2) +211 + j*(-42) +151 + j*(-265) +-82 + j*(-264) +-145 + j*(-88) +-41 + j*(-4) +49 + j*(-73) +-9 + j*(-200) +-190 + j*(-180) +-232 + j*(2) +-119 + j*(68) +-112 + j*(33) +-122 + j*(126) +45 + j*(161) +108 + j*(-21) +-56 + j*(-84) +-106 + j*(52) +-6 + j*(88) +16 + j*(47) +35 + j*(50) +67 + j*(-11) +-2 + j*(-44) +1 + j*(21) +67 + j*(-56) +-99 + j*(-135) +-204 + j*(109) +81 + j*(243) +216 + j*(-44) +-47 + j*(-130) +-43 + j*(114) +233 + j*(11) +84 + j*(-315) +-265 + j*(-170) +-150 + j*(167) +147 + j*(76) +84 + j*(-208) +-208 + j*(-217) +-339 + j*(59) +-137 + j*(312) +177 + j*(216) +168 + j*(-83) +-66 + j*(-107) +-75 + j*(45) +-13 + j*(2) +-144 + j*(21) +-92 + j*(252) +191 + j*(226) +193 + j*(-28) +28 + j*(-5) +127 + j*(87) +182 + j*(-74) +2 + j*(-99) +33 + j*(83) +234 + j*(-5) +139 + j*(-223) +-50 + j*(-148) +25 + j*(-31) +87 + j*(-139) +-49 + j*(-194) +-114 + j*(-74) +-28 + j*(-21) +13 + j*(-83) +-19 + j*(-139) +-81 + j*(-182) +-221 + j*(-189) +-378 + j*(-21) +-302 + j*(275) +32 + j*(345) +192 + j*(62) +-36 + j*(-93) +-155 + j*(137) +107 + j*(244) +225 + j*(-13) +21 + j*(-123) +-39 + j*(11) +32 + j*(-8) +-66 + j*(-26) +-44 + j*(143) +177 + j*(104) +151 + j*(-119) +-4 + j*(-110) +28 + j*(-82) +-83 + j*(-192) +-298 + j*(13) +-53 + j*(310) +272 + j*(63) +35 + j*(-238) +-210 + j*(-17) +-16 + j*(141) +29 + j*(-34) +-162 + j*(33) +-40 + j*(267) +216 + j*(182) +217 + j*(-12) +163 + j*(-77) +107 + j*(-164) +-49 + j*(-154) +-57 + j*(-6) +54 + j*(-30) +-21 + j*(-124) +-98 + j*(-25) +-4 + j*(8) +-48 + j*(-83) +-159 + j*(32) +-23 + j*(166) +86 + j*(62) +21 + j*(54) +163 + j*(147) +370 + j*(-109) +130 + j*(-465) +-307 + j*(-383) +-434 + j*(-24) +-293 + j*(241) +-41 + j*(349) +219 + j*(228) +253 + j*(-38) +90 + j*(-149) +0 + j*(-105) +-21 + j*(-91) +-54 + j*(-76) +-62 + j*(-71) +-137 + j*(-81) +-226 + j*(62) +-79 + j*(230) +105 + j*(127) +32 + j*(-2) +-16 + j*(91) +112 + j*(83) +72 + j*(-52) +-34 + j*(34) +112 + j*(119) +197 + j*(-66) +29 + j*(-139) +23 + j*(-28) +93 + j*(-136) +-129 + j*(-206) +-209 + j*(88) +128 + j*(161) +176 + j*(-214) +-231 + j*(-250) +-276 + j*(163) +103 + j*(216) +162 + j*(-110) +-103 + j*(-170) +-168 + j*(8) +-94 + j*(54) +-115 + j*(67) +-83 + j*(164) +49 + j*(171) +99 + j*(70) +49 + j*(5) +-25 + j*(11) +-71 + j*(113) +41 + j*(254) +279 + j*(206) +356 + j*(-46) +205 + j*(-207) +76 + j*(-194) +20 + j*(-175) +-49 + j*(-140) +-44 + j*(-54) +33 + j*(-76) +-28 + j*(-177) +-183 + j*(-119) +-182 + j*(59) +-43 + j*(129) +66 + j*(73) +86 + j*(-34) +5 + j*(-106) +-82 + j*(-42) +-15 + j*(33) +47 + j*(-59) +-76 + j*(-122) +-139 + j*(6) +-29 + j*(49) +-35 + j*(-45) +-131 + j*(8) +-66 + j*(96) +-30 + j*(40) +-101 + j*(95) +33 + j*(218) +203 + j*(63) +78 + j*(-99) +5 + j*(-5) +102 + j*(-70) +-103 + j*(-209) +-305 + j*(100) +66 + j*(353) +339 + j*(-42) +-57 + j*(-307) +-301 + j*(69) +21 + j*(284) +190 + j*(57) +82 + j*(-44) +60 + j*(-49) +-45 + j*(-98) +-144 + j*(104) +140 + j*(253) +336 + j*(-73) +31 + j*(-284) +-132 + j*(-40) +67 + j*(16) +7 + j*(-181) +-216 + j*(-55) +-95 + j*(177) +87 + j*(103) +58 + j*(34) +124 + j*(73) +238 + j*(-86) +78 + j*(-296) +-180 + j*(-224) +-221 + j*(8) +-57 + j*(126) +105 + j*(9) +-1 + j*(-199) +-282 + j*(-111) +-247 + j*(228) +83 + j*(258) +134 + j*(0) +-55 + j*(-5) +2 + j*(168) +202 + j*(102) +206 + j*(-102) +62 + j*(-202) +-98 + j*(-160) +-134 + j*(5) +27 + j*(59) +62 + j*(-136) +-194 + j*(-168) +-259 + j*(117) +-12 + j*(205) +42 + j*(38) +-71 + j*(74) +40 + j*(184) +169 + j*(58) +74 + j*(-47) +27 + j*(14) +86 + j*(18) +86 + j*(-35) +77 + j*(-62) +31 + j*(-113) +-66 + j*(-48) +53 + j*(76) +242 + j*(-124) +-1 + j*(-432) +-417 + j*(-264) +-421 + j*(142) +-186 + j*(296) +-6 + j*(315) +218 + j*(226) +247 + j*(-93) +-90 + j*(-182) +-182 + j*(164) +179 + j*(245) +259 + j*(-111) +-62 + j*(-174) +-81 + j*(103) +185 + j*(71) +134 + j*(-216) +-175 + j*(-194) +-214 + j*(105) +35 + j*(205) +169 + j*(27) +64 + j*(-98) +-13 + j*(-45) +30 + j*(-47) +-57 + j*(-122) +-204 + j*(22) +-45 + j*(244) +211 + j*(115) +117 + j*(-112) +-33 + j*(-10) +135 + j*(69) +196 + j*(-180) +-95 + j*(-271) +-214 + j*(4) +13 + j*(116) +98 + j*(-71) +-56 + j*(-140) +-122 + j*(-34) +-77 + j*(11) +-88 + j*(7) +-112 + j*(77) +-31 + j*(173) +130 + j*(153) +206 + j*(-4) +139 + j*(-139) +52 + j*(-182) +-37 + j*(-235) +-233 + j*(-211) +-333 + j*(33) +-136 + j*(209) +6 + j*(76) +-130 + j*(20) +-127 + j*(216) +112 + j*(206) +97 + j*(-23) +-114 + j*(33) +-18 + j*(248) +208 + j*(163) +162 + j*(-18) +74 + j*(20) +156 + j*(33) +157 + j*(-88) +54 + j*(-106) +54 + j*(-64) +59 + j*(-120) +-37 + j*(-133) +-66 + j*(-51) +-35 + j*(-43) +-90 + j*(-32) +-62 + j*(88) +112 + j*(53) +64 + j*(-175) +-239 + j*(-116) +-204 + j*(276) +263 + j*(312) +400 + j*(-181) +-59 + j*(-414) +-345 + j*(-23) +-17 + j*(279) +287 + j*(-2) +54 + j*(-317) +-267 + j*(-153) +-187 + j*(132) +25 + j*(112) +10 + j*(-30) +-101 + j*(14) +-50 + j*(140) +96 + j*(128) +144 + j*(-4) +58 + j*(-91) +-30 + j*(-45) +-2 + j*(36) +90 + j*(21) +115 + j*(-74) +66 + j*(-150) +-4 + j*(-198) +-127 + j*(-223) +-272 + j*(-129) +-288 + j*(60) +-172 + j*(156) +-106 + j*(139) +-111 + j*(180) +-2 + j*(269) +180 + j*(195) +193 + j*(-4) +47 + j*(-75) +-20 + j*(1) +14 + j*(30) +-6 + j*(3) +-56 + j*(64) +12 + j*(162) +153 + j*(139) +195 + j*(6) +124 + j*(-74) +64 + j*(-59) +65 + j*(-44) +59 + j*(-62) +30 + j*(-60) +30 + j*(-37) +40 + j*(-38) +44 + j*(-30) +95 + j*(-29) +142 + j*(-123) +58 + j*(-236) +-76 + j*(-217) +-99 + j*(-147) +-112 + j*(-163) +-206 + j*(-144) +-247 + j*(-40) +-233 + j*(20) +-268 + j*(112) +-160 + j*(294) +119 + j*(248) +119 + j*(-46) +-166 + j*(-35) +-129 + j*(279) +225 + j*(253) +252 + j*(-98) +-35 + j*(-184) +-156 + j*(-9) +-127 + j*(107) +-74 + j*(223) +131 + j*(286) +298 + j*(88) +164 + j*(-94) +57 + j*(7) +195 + j*(31) +187 + j*(-161) +-21 + j*(-151) +23 + j*(42) +228 + j*(-50) +130 + j*(-291) +-111 + j*(-240) +-89 + j*(-58) +41 + j*(-115) +-55 + j*(-274) +-294 + j*(-221) +-366 + j*(43) +-172 + j*(231) +43 + j*(133) +-14 + j*(-48) +-181 + j*(25) +-89 + j*(216) +122 + j*(141) +79 + j*(-52) +-66 + j*(-21) +-28 + j*(63) +-8 + j*(-1) +-116 + j*(37) +-42 + j*(202) +159 + j*(124) +83 + j*(-76) +-100 + j*(16) +22 + j*(194) +196 + j*(66) +77 + j*(-83) +-19 + j*(47) +152 + j*(118) +251 + j*(-88) +80 + j*(-239) +-86 + j*(-166) +-109 + j*(-57) +-93 + j*(1) +-73 + j*(54) +-21 + j*(100) +72 + j*(111) +172 + j*(20) +124 + j*(-136) +-50 + j*(-129) +-43 + j*(38) +132 + j*(0) +69 + j*(-211) +-181 + j*(-151) +-145 + j*(109) +105 + j*(105) +136 + j*(-108) +-2 + j*(-182) +-82 + j*(-158) +-173 + j*(-144) +-274 + j*(-18) +-214 + j*(171) +-36 + j*(211) +54 + j*(119) +42 + j*(52) +20 + j*(42) +28 + j*(47) +45 + j*(26) +29 + j*(4) +18 + j*(19) +47 + j*(9) +21 + j*(-30) +-14 + j*(29) +117 + j*(64) +194 + j*(-156) +-80 + j*(-331) +-351 + j*(-86) +-207 + j*(208) +8 + j*(154) +-31 + j*(71) +-18 + j*(165) +136 + j*(132) +124 + j*(-31) +2 + j*(-37) +-8 + j*(30) +4 + j*(45) +24 + j*(95) +135 + j*(85) +139 + j*(-47) +35 + j*(-35) +120 + j*(34) +194 + j*(-156) +-86 + j*(-270) +-250 + j*(62) +107 + j*(274) +376 + j*(-83) +81 + j*(-404) +-240 + j*(-239) +-210 + j*(-13) +-152 + j*(24) +-155 + j*(121) +13 + j*(231) +222 + j*(92) +180 + j*(-144) +1 + j*(-199) +-95 + j*(-138) +-144 + j*(-87) +-191 + j*(10) +-120 + j*(147) +57 + j*(143) +117 + j*(-29) +-23 + j*(-131) +-144 + j*(-45) +-124 + j*(57) +-93 + j*(82) +-83 + j*(140) +27 + j*(192) +135 + j*(89) +48 + j*(-26) +-49 + j*(83) +102 + j*(208) +302 + j*(53) +222 + j*(-209) +-25 + j*(-246) +-151 + j*(-85) +-100 + j*(69) +42 + j*(111) +156 + j*(-3) +81 + j*(-167) +-112 + j*(-141) +-125 + j*(42) +30 + j*(71) +41 + j*(-50) +-55 + j*(-14) +54 + j*(79) +187 + j*(-110) +-51 + j*(-331) +-372 + j*(-107) +-217 + j*(260) +122 + j*(160) +20 + j*(-132) +-268 + j*(17) +-103 + j*(351) +269 + j*(233) +226 + j*(-110) +-33 + j*(-105) +-6 + j*(63) +107 + j*(-15) +-10 + j*(-103) +-88 + j*(27) +31 + j*(91) +69 + j*(8) +44 + j*(25) +150 + j*(0) +107 + j*(-216) +-198 + j*(-200) +-223 + j*(147) +117 + j*(201) +166 + j*(-112) +-123 + j*(-139) +-135 + j*(134) +117 + j*(157) +165 + j*(-52) +25 + j*(-124) +-57 + j*(-50) +-33 + j*(39) +78 + j*(47) +110 + j*(-95) +-59 + j*(-139) +-91 + j*(61) +158 + j*(62) +148 + j*(-249) +-190 + j*(-263) +-224 + j*(35) +-13 + j*(33) +-105 + j*(-115) +-235 + j*(47) +-71 + j*(166) +-21 + j*(40) +-129 + j*(108) +42 + j*(244) +213 + j*(25) +-16 + j*(-142) +-153 + j*(88) +67 + j*(202) +175 + j*(26) +91 + j*(-64) +47 + j*(-93) +-87 + j*(-119) +-182 + j*(95) +90 + j*(248) +279 + j*(-56) +-25 + j*(-264) +-223 + j*(11) +-1 + j*(165) +72 + j*(1) +-47 + j*(19) +42 + j*(117) +108 + j*(-4) +-17 + j*(0) +78 + j*(148) +271 + j*(-11) +112 + j*(-221) +-30 + j*(-89) +124 + j*(-91) +-13 + j*(-344) +-397 + j*(-146) +-210 + j*(320) +266 + j*(155) +98 + j*(-298) +-337 + j*(-121) +-184 + j*(305) +194 + j*(218) +178 + j*(-49) +65 + j*(-50) +132 + j*(-78) +56 + j*(-267) +-237 + j*(-258) +-377 + j*(42) +-192 + j*(322) +141 + j*(327) +325 + j*(55) +189 + j*(-217) +-54 + j*(-221) +-131 + j*(-95) +-144 + j*(-40) +-175 + j*(66) +-47 + j*(191) +121 + j*(77) +18 + j*(-81) +-108 + j*(42) +54 + j*(137) +127 + j*(-64) +-112 + j*(-124) +-172 + j*(144) +100 + j*(218) +187 + j*(-15) +14 + j*(-90) +-21 + j*(30) +62 + j*(21) +18 + j*(-42) +-34 + j*(35) +68 + j*(101) +170 + j*(2) +119 + j*(-130) +6 + j*(-136) +-16 + j*(-76) +10 + j*(-100) +-74 + j*(-148) +-179 + j*(-42) +-91 + j*(98) +42 + j*(25) +-37 + j*(-88) +-147 + j*(-1) +-86 + j*(103) +-18 + j*(102) +36 + j*(106) +126 + j*(17) +11 + j*(-145) +-206 + j*(-6) +-47 + j*(245) +207 + j*(66) +-15 + j*(-161) +-214 + j*(128) +122 + j*(326) +318 + j*(7) +70 + j*(-118) +91 + j*(78) +311 + j*(-99) +57 + j*(-383) +-241 + j*(-135) +-14 + j*(94) +115 + j*(-156) +-186 + j*(-227) +-252 + j*(89) +21 + j*(159) +73 + j*(-37) +-58 + j*(-59) +-62 + j*(23) +-24 + j*(32) +8 + j*(34) +42 + j*(-37) +-79 + j*(-105) +-193 + j*(67) +2 + j*(228) +190 + j*(57) +70 + j*(-106) +-11 + j*(-27) +69 + j*(-54) +-45 + j*(-185) +-231 + j*(-43) +-115 + j*(156) +37 + j*(57) +-93 + j*(-25) +-156 + j*(170) +78 + j*(279) +248 + j*(86) +146 + j*(-98) +6 + j*(-70) +16 + j*(18) +95 + j*(-5) +75 + j*(-119) +-78 + j*(-141) +-161 + j*(25) +-20 + j*(162) +144 + j*(63) +93 + j*(-98) +-44 + j*(-76) +-37 + j*(32) +53 + j*(35) +81 + j*(-43) +35 + j*(-105) +-49 + j*(-117) +-122 + j*(-47) +-89 + j*(52) +-2 + j*(38) +-39 + j*(-33) +-122 + j*(45) +-23 + j*(166) +119 + j*(76) +28 + j*(-49) +-66 + j*(86) +141 + j*(190) +303 + j*(-67) +58 + j*(-293) +-188 + j*(-107) +-60 + j*(103) +87 + j*(5) +-7 + j*(-75) +-25 + j*(29) +105 + j*(-1) +59 + j*(-175) +-141 + j*(-156) +-177 + j*(27) +-63 + j*(100) +4 + j*(71) +35 + j*(47) +62 + j*(-2) +26 + j*(-59) +-28 + j*(-43) +-9 + j*(-8) +21 + j*(-62) +-70 + j*(-139) +-241 + j*(-59) +-252 + j*(199) +17 + j*(357) +298 + j*(173) +252 + j*(-141) +3 + j*(-206) +-95 + j*(-69) +-40 + j*(-15) +-54 + j*(-54) +-133 + j*(-16) +-143 + j*(107) +-35 + j*(205) +133 + j*(177) +202 + j*(1) +71 + j*(-123) +-56 + j*(-41) +13 + j*(59) +94 + j*(-21) +19 + j*(-98) +-47 + j*(-52) +-40 + j*(-37) +-110 + j*(-35) +-149 + j*(111) +23 + j*(215) +165 + j*(74) +76 + j*(-56) +-11 + j*(1) +30 + j*(45) +23 + j*(37) +51 + j*(127) +254 + j*(113) +326 + j*(-168) +64 + j*(-348) +-156 + j*(-192) +-112 + j*(-25) +-44 + j*(-9) +-15 + j*(15) +85 + j*(-18) +57 + j*(-182) +-154 + j*(-184) +-199 + j*(30) +-31 + j*(102) +40 + j*(6) +31 + j*(-35) +49 + j*(-125) +-118 + j*(-252) +-381 + j*(-74) +-271 + j*(275) +63 + j*(257) +85 + j*(16) +-61 + j*(23) +-1 + j*(112) +55 + j*(21) +-43 + j*(4) +-15 + j*(107) +101 + j*(37) +-3 + j*(-95) +-155 + j*(18) +-65 + j*(187) +84 + j*(152) +90 + j*(71) +85 + j*(79) +158 + j*(64) +202 + j*(-56) +105 + j*(-194) +-98 + j*(-185) +-185 + j*(19) +-22 + j*(162) +120 + j*(41) +18 + j*(-66) +-49 + j*(47) +81 + j*(86) +91 + j*(-52) +-56 + j*(-18) +25 + j*(170) +280 + j*(81) +242 + j*(-219) +-45 + j*(-251) +-104 + j*(-11) +115 + j*(41) +188 + j*(-203) +-66 + j*(-356) +-310 + j*(-163) +-231 + j*(110) +-1 + j*(123) +53 + j*(-40) +-52 + j*(-109) +-141 + j*(-64) +-173 + j*(28) +-115 + j*(134) +21 + j*(132) +54 + j*(7) +-55 + j*(-27) +-80 + j*(75) +13 + j*(101) +42 + j*(37) +21 + j*(30) +62 + j*(24) +64 + j*(-76) +-80 + j*(-126) +-209 + j*(16) +-119 + j*(219) +111 + j*(224) +198 + j*(27) +74 + j*(-86) +3 + j*(-23) +49 + j*(-32) +-34 + j*(-107) +-163 + j*(16) +-45 + j*(180) +108 + j*(92) +33 + j*(-2) +5 + j*(95) +135 + j*(96) +144 + j*(-18) +107 + j*(-13) +182 + j*(-74) +67 + j*(-247) +-175 + j*(-125) +-54 + j*(132) +190 + j*(-6) +40 + j*(-233) +-161 + j*(-98) +-61 + j*(39) +-20 + j*(-42) +-102 + j*(4) +-11 + j*(105) +84 + j*(20) +41 + j*(-22) +104 + j*(-15) +120 + j*(-202) +-148 + j*(-276) +-279 + j*(-10) +-69 + j*(116) +-6 + j*(-48) +-163 + j*(-61) +-185 + j*(83) +-119 + j*(146) +-56 + j*(219) +141 + j*(226) +251 + j*(-26) +21 + j*(-221) +-214 + j*(-74) +-190 + j*(148) +-60 + j*(253) +116 + j*(282) +306 + j*(153) +316 + j*(-95) +158 + j*(-246) +-43 + j*(-279) +-268 + j*(-133) +-239 + j*(223) +180 + j*(308) +349 + j*(-122) +-64 + j*(-347) +-322 + j*(26) +-8 + j*(297) +247 + j*(64) +94 + j*(-145) +-49 + j*(-45) +32 + j*(45) +108 + j*(-38) +32 + j*(-130) +-74 + j*(-74) +-28 + j*(23) +49 + j*(-39) +-59 + j*(-112) +-149 + j*(50) +41 + j*(172) +185 + j*(-4) +66 + j*(-120) +44 + j*(-49) +133 + j*(-151) +-36 + j*(-321) +-262 + j*(-193) +-228 + j*(-13) +-184 + j*(-14) +-239 + j*(48) +-181 + j*(162) +-107 + j*(170) +-72 + j*(226) +110 + j*(231) +163 + j*(-16) +-125 + j*(-67) +-160 + j*(276) +224 + j*(334) +330 + j*(-10) +110 + j*(-105) +117 + j*(-16) +158 + j*(-151) +-41 + j*(-218) +-127 + j*(-69) +-90 + j*(-40) +-190 + j*(7) +-132 + j*(233) +139 + j*(206) +105 + j*(-23) +-70 + j*(91) +141 + j*(276) +378 + j*(51) +246 + j*(-183) +138 + j*(-158) +154 + j*(-242) +-54 + j*(-347) +-252 + j*(-144) +-119 + j*(59) +10 + j*(-28) +-83 + j*(-84) +-122 + j*(31) +-16 + j*(100) +103 + j*(54) +160 + j*(-99) +23 + j*(-279) +-250 + j*(-215) +-277 + j*(72) +-40 + j*(152) +33 + j*(-25) +-109 + j*(-80) +-172 + j*(23) +-148 + j*(94) +-120 + j*(180) +33 + j*(251) +209 + j*(100) +108 + j*(-134) +-139 + j*(-85) +-134 + j*(147) +62 + j*(185) +126 + j*(57) +85 + j*(6) +94 + j*(-25) +28 + j*(-120) +-146 + j*(-66) +-144 + j*(151) +54 + j*(213) +146 + j*(105) +148 + j*(69) +239 + j*(5) +206 + j*(-204) +-40 + j*(-253) +-141 + j*(-56) +-26 + j*(25) +-9 + j*(-23) +-25 + j*(31) +88 + j*(24) +68 + j*(-133) +-115 + j*(-102) +-71 + j*(83) +107 + j*(17) +22 + j*(-158) +-146 + j*(-75) +-86 + j*(59) +-18 + j*(10) +-89 + j*(6) +-71 + j*(113) +38 + j*(118) +62 + j*(61) +79 + j*(71) +175 + j*(26) +182 + j*(-141) +27 + j*(-250) +-154 + j*(-200) +-242 + j*(-35) +-169 + j*(148) +28 + j*(182) +119 + j*(23) +-4 + j*(-71) +-80 + j*(55) +78 + j*(136) +201 + j*(-40) +51 + j*(-215) +-136 + j*(-129) +-115 + j*(15) +-48 + j*(14) +-65 + j*(13) +-32 + j*(52) +6 + j*(-6) +-92 + j*(-28) +-108 + j*(125) +95 + j*(154) +145 + j*(-75) +-81 + j*(-149) +-168 + j*(36) +-63 + j*(98) +-88 + j*(78) +-85 + j*(232) +168 + j*(283) +300 + j*(21) +99 + j*(-140) +-28 + j*(1) +87 + j*(86) +153 + j*(6) +146 + j*(-33) +196 + j*(-98) +144 + j*(-267) +-88 + j*(-317) +-242 + j*(-145) +-199 + j*(22) +-127 + j*(65) +-105 + j*(106) +-24 + j*(184) +145 + j*(170) +253 + j*(-1) +181 + j*(-197) +1 + j*(-265) +-160 + j*(-197) +-226 + j*(-42) +-148 + j*(98) +-10 + j*(91) +0 + j*(-11) +-71 + j*(-3) +-41 + j*(52) +-11 + j*(0) +-92 + j*(-5) +-85 + j*(107) +28 + j*(93) +-16 + j*(7) +-84 + j*(111) +69 + j*(193) +167 + j*(37) +43 + j*(-35) +47 + j*(66) +161 + j*(-15) +35 + j*(-163) +-132 + j*(-27) +-15 + j*(130) +108 + j*(49) +64 + j*(-9) +86 + j*(22) +136 + j*(-57) +55 + j*(-124) +25 + j*(-78) +64 + j*(-126) +-51 + j*(-210) +-187 + j*(-104) +-148 + j*(22) +-120 + j*(35) +-128 + j*(148) +94 + j*(257) +345 + j*(11) +172 + j*(-356) +-223 + j*(-314) +-296 + j*(6) +-100 + j*(103) +-70 + j*(-10) +-178 + j*(45) +-81 + j*(194) +84 + j*(86) +-57 + j*(-71) +-226 + j*(136) +33 + j*(346) +279 + j*(84) +23 + j*(-144) +-164 + j*(141) +165 + j*(317) +367 + j*(-18) +89 + j*(-231) +-88 + j*(-35) +35 + j*(93) +132 + j*(57) +219 + j*(1) +264 + j*(-218) +-21 + j*(-406) +-325 + j*(-150) +-140 + j*(187) +168 + j*(58) +76 + j*(-210) +-147 + j*(-161) +-148 + j*(-8) +-74 + j*(6) +-89 + j*(-23) +-144 + j*(18) +-127 + j*(123) +2 + j*(157) +58 + j*(49) +-41 + j*(27) +-10 + j*(156) +165 + j*(92) +88 + j*(-93) +-71 + j*(11) +91 + j*(141) +202 + j*(-65) +-13 + j*(-148) +-18 + j*(62) +214 + j*(-37) +35 + j*(-320) +-281 + j*(-126) +-102 + j*(167) +122 + j*(-16) +-92 + j*(-170) +-205 + j*(63) +10 + j*(156) +71 + j*(-11) +-37 + j*(-30) +-14 + j*(35) +26 + j*(-16) +-26 + j*(-56) +-78 + j*(-49) +-167 + j*(5) +-163 + j*(206) +111 + j*(287) +266 + j*(14) +36 + j*(-153) +-81 + j*(48) +132 + j*(109) +180 + j*(-126) +-32 + j*(-206) +-134 + j*(-86) +-135 + j*(-16) +-150 + j*(71) +-54 + j*(168) +60 + j*(118) +49 + j*(54) +72 + j*(72) +124 + j*(-14) +5 + j*(-96) +-78 + j*(39) +68 + j*(103) +100 + j*(-56) +-78 + j*(-47) +-35 + j*(161) +194 + j*(110) +156 + j*(-115) +-33 + j*(-79) +11 + j*(81) +156 + j*(53) +188 + j*(-41) +220 + j*(-119) +189 + j*(-305) +-71 + j*(-407) +-284 + j*(-194) +-153 + j*(18) +1 + j*(-100) +-168 + j*(-241) +-371 + j*(-59) +-262 + j*(197) +-33 + j*(185) +-1 + j*(25) +-129 + j*(-14) +-205 + j*(121) +-92 + j*(288) +154 + j*(258) +230 + j*(4) +18 + j*(-135) +-125 + j*(29) +9 + j*(150) +98 + j*(33) +-13 + j*(-10) +-10 + j*(112) +136 + j*(90) +122 + j*(-68) +-18 + j*(-75) +-45 + j*(35) +28 + j*(87) +118 + j*(69) +181 + j*(-52) +69 + j*(-202) +-136 + j*(-134) +-113 + j*(66) +42 + j*(57) +8 + j*(-47) +-66 + j*(23) +25 + j*(87) +83 + j*(7) +42 + j*(-22) +74 + j*(-25) +54 + j*(-136) +-122 + j*(-134) +-162 + j*(60) +3 + j*(125) +60 + j*(15) +-7 + j*(-12) +-16 + j*(25) +-18 + j*(44) +15 + j*(123) +188 + j*(107) +230 + j*(-129) +-8 + j*(-223) +-100 + j*(-18) +85 + j*(27) +83 + j*(-168) +-118 + j*(-143) +-72 + j*(44) +106 + j*(-39) +4 + j*(-240) +-216 + j*(-181) +-240 + j*(-13) +-204 + j*(47) +-207 + j*(129) +-109 + j*(250) +64 + j*(228) +132 + j*(100) +86 + j*(10) +14 + j*(3) +-6 + j*(80) +102 + j*(127) +205 + j*(6) +120 + j*(-132) +23 + j*(-95) +71 + j*(-92) +2 + j*(-221) +-213 + j*(-148) +-161 + j*(94) +59 + j*(23) +-74 + j*(-202) +-357 + j*(-33) +-240 + j*(288) +18 + j*(272) +37 + j*(175) +105 + j*(233) +291 + j*(98) +181 + j*(-177) +-100 + j*(-116) +-73 + j*(117) +91 + j*(106) +87 + j*(23) +88 + j*(41) +129 + j*(-18) +35 + j*(-51) +51 + j*(93) +299 + j*(35) +273 + j*(-335) +-156 + j*(-414) +-351 + j*(-25) +-69 + j*(227) +180 + j*(63) +119 + j*(-141) +-9 + j*(-163) +-68 + j*(-130) +-117 + j*(-95) +-148 + j*(-23) +-117 + j*(53) +-54 + j*(87) +18 + j*(79) +74 + j*(8) +27 + j*(-95) +-106 + j*(-81) +-122 + j*(64) +18 + j*(103) +67 + j*(-23) +-38 + j*(-62) +-52 + j*(15) +-5 + j*(-18) +-100 + j*(-43) +-124 + j*(118) +87 + j*(151) +124 + j*(-83) +-111 + j*(-116) +-126 + j*(108) +68 + j*(95) +16 + j*(-65) +-108 + j*(23) +4 + j*(105) +25 + j*(-23) +-137 + j*(26) +-43 + j*(242) +209 + j*(152) +157 + j*(-90) +-29 + j*(-62) +-1 + j*(57) +65 + j*(22) +33 + j*(-6) +37 + j*(25) +71 + j*(4) +57 + j*(-27) +45 + j*(-31) +33 + j*(-45) +14 + j*(-37) +20 + j*(-40) +-26 + j*(-62) +-83 + j*(25) +33 + j*(124) +168 + j*(6) +71 + j*(-131) +-31 + j*(-49) +61 + j*(-3) +76 + j*(-119) +-37 + j*(-129) +-37 + j*(-59) +-21 + j*(-105) +-117 + j*(-103) +-119 + j*(0) +-52 + j*(-21) +-143 + j*(-62) +-216 + j*(88) +-84 + j*(226) +62 + j*(204) +172 + j*(158) +307 + j*(4) +238 + j*(-293) +-97 + j*(-386) +-315 + j*(-170) +-280 + j*(40) +-205 + j*(124) +-131 + j*(193) +-19 + j*(206) +49 + j*(155) +71 + j*(120) +98 + j*(83) +88 + j*(44) +91 + j*(46) +132 + j*(-2) +78 + j*(-77) +6 + j*(-24) +94 + j*(13) +116 + j*(-141) +-91 + j*(-177) +-135 + j*(46) +101 + j*(64) +78 + j*(-226) +-296 + j*(-205) +-355 + j*(235) +74 + j*(406) +328 + j*(66) +108 + j*(-200) +-114 + j*(-77) +-45 + j*(81) +49 + j*(34) +9 + j*(-13) +-10 + j*(21) +1 + j*(23) +-32 + j*(61) +52 + j*(161) +234 + j*(83) +208 + j*(-136) +31 + j*(-148) +47 + j*(-47) +117 + j*(-138) +-10 + j*(-226) +-93 + j*(-142) +-71 + j*(-156) +-241 + j*(-191) +-377 + j*(94) +-81 + j*(344) +216 + j*(110) +48 + j*(-162) +-172 + j*(-31) +-73 + j*(142) +57 + j*(87) +47 + j*(13) +22 + j*(-12) +-25 + j*(-16) +-24 + j*(68) +117 + j*(53) +107 + j*(-164) +-175 + j*(-194) +-265 + j*(111) +1 + j*(253) +161 + j*(64) +62 + j*(-62) +4 + j*(-42) +-28 + j*(-76) +-167 + j*(-33) +-160 + j*(195) +110 + j*(252) +217 + j*(-8) +-30 + j*(-126) +-147 + j*(141) +146 + j*(299) +387 + j*(37) +243 + j*(-246) +35 + j*(-247) +-33 + j*(-213) +-173 + j*(-204) +-295 + j*(11) +-115 + j*(234) +114 + j*(135) +74 + j*(-23) +9 + j*(18) +79 + j*(5) +8 + j*(-88) +-105 + j*(53) +108 + j*(214) +368 + j*(-23) +211 + j*(-374) +-131 + j*(-378) +-259 + j*(-180) +-253 + j*(-60) +-255 + j*(34) +-210 + j*(148) +-110 + j*(215) +11 + j*(240) +160 + j*(177) +216 + j*(-8) +86 + j*(-150) +-68 + j*(-105) +-78 + j*(-5) +-49 + j*(3) +-88 + j*(13) +-98 + j*(117) +33 + j*(196) +191 + j*(102) +180 + j*(-88) +23 + j*(-161) +-81 + j*(-76) +-59 + j*(-5) +-49 + j*(-9) +-93 + j*(25) +-62 + j*(125) +76 + j*(147) +159 + j*(25) +98 + j*(-92) +0 + j*(-98) +-47 + j*(-64) +-97 + j*(-25) +-108 + j*(90) +31 + j*(173) +175 + j*(49) +82 + j*(-114) +-69 + j*(-41) +-1 + j*(96) +131 + j*(36) +105 + j*(-78) +41 + j*(-94) +9 + j*(-105) +-73 + j*(-95) +-102 + j*(18) +3 + j*(81) +83 + j*(25) +106 + j*(-34) +129 + j*(-136) +4 + j*(-281) +-235 + j*(-223) +-278 + j*(6) +-155 + j*(91) +-127 + j*(73) +-122 + j*(136) +-34 + j*(174) +15 + j*(154) +86 + j*(183) +236 + j*(89) +199 + j*(-133) +11 + j*(-152) +20 + j*(-77) +4 + j*(-209) +-286 + j*(-191) +-341 + j*(189) +17 + j*(314) +130 + j*(55) +-38 + j*(45) +91 + j*(190) +264 + j*(-47) +-21 + j*(-260) +-262 + j*(22) +-18 + j*(275) +221 + j*(108) +154 + j*(-83) +52 + j*(-103) +-15 + j*(-94) +-64 + j*(-11) +44 + j*(52) +108 + j*(-109) +-117 + j*(-198) +-267 + j*(60) +-30 + j*(270) +205 + j*(99) +99 + j*(-131) +-123 + j*(-71) +-119 + j*(173) +160 + j*(271) +397 + j*(8) +227 + j*(-342) +-134 + j*(-293) +-158 + j*(-21) +2 + j*(-22) +-86 + j*(-103) +-139 + j*(74) +104 + j*(113) +129 + j*(-175) +-195 + j*(-192) +-213 + j*(151) +124 + j*(177) +165 + j*(-131) +-93 + j*(-189) +-161 + j*(-6) +-66 + j*(54) +-33 + j*(25) +-26 + j*(12) +-36 + j*(-13) +-82 + j*(9) +-55 + j*(66) +-14 + j*(37) +-62 + j*(30) +-41 + j*(111) +63 + j*(80) +17 + j*(-19) +-72 + j*(60) +42 + j*(157) +161 + j*(45) +98 + j*(-74) +28 + j*(-83) +-31 + j*(-104) +-149 + j*(-33) +-94 + j*(147) +101 + j*(103) +35 + j*(-83) +-158 + j*(25) +-26 + j*(250) +224 + j*(148) +187 + j*(-78) +29 + j*(-98) +-18 + j*(-13) +12 + j*(62) +127 + j*(79) +210 + j*(-69) +71 + j*(-202) +-48 + j*(-101) +40 + j*(-66) +-28 + j*(-208) +-261 + j*(-81) +-141 + j*(224) +177 + j*(142) +123 + j*(-127) +-58 + j*(-62) +45 + j*(30) +76 + j*(-122) +-115 + j*(-110) +-59 + j*(100) +177 + j*(4) +77 + j*(-275) +-228 + j*(-226) +-267 + j*(42) +-95 + j*(151) +31 + j*(91) +57 + j*(-20) +-27 + j*(-105) +-147 + j*(-56) +-144 + j*(71) +-50 + j*(106) +-7 + j*(58) +-29 + j*(24) +-67 + j*(45) +-49 + j*(118) +65 + j*(116) +86 + j*(-36) +-112 + j*(-77) +-193 + j*(165) +64 + j*(317) +276 + j*(114) +177 + j*(-104) +25 + j*(-93) +-6 + j*(-34) +-25 + j*(0) +8 + j*(62) +98 + j*(21) +41 + j*(-95) +-111 + j*(-27) +-52 + j*(167) +162 + j*(155) +220 + j*(-29) +118 + j*(-123) +54 + j*(-117) +21 + j*(-127) +-53 + j*(-118) +-95 + j*(-32) +-35 + j*(44) +45 + j*(13) +33 + j*(-52) +-14 + j*(-35) +33 + j*(7) +99 + j*(-81) +2 + j*(-207) +-172 + j*(-160) +-208 + j*(-7) +-146 + j*(72) +-112 + j*(112) +-35 + j*(176) +103 + j*(151) +158 + j*(18) +99 + j*(-81) +11 + j*(-106) +-61 + j*(-59) +-44 + j*(31) +65 + j*(18) +53 + j*(-113) +-81 + j*(-117) +-83 + j*(-16) +-30 + j*(-77) +-202 + j*(-127) +-324 + j*(141) +-44 + j*(362) +228 + j*(146) +90 + j*(-93) +-62 + j*(8) +55 + j*(76) +70 + j*(-87) +-134 + j*(-94) +-181 + j*(119) +-22 + j*(212) +74 + j*(162) +115 + j*(141) +197 + j*(92) +218 + j*(-27) +170 + j*(-106) +127 + j*(-173) +2 + j*(-251) +-190 + j*(-165) +-203 + j*(62) +-20 + j*(153) +93 + j*(51) +58 + j*(-40) +6 + j*(-46) +-22 + j*(-21) +-3 + j*(30) +86 + j*(17) +95 + j*(-126) +-79 + j*(-179) +-173 + j*(-15) +-42 + j*(74) +-4 + j*(-47) +-164 + j*(-27) +-126 + j*(191) +116 + j*(171) +101 + j*(-45) +-76 + j*(13) +52 + j*(183) +247 + j*(13) +79 + j*(-192) +-83 + j*(-44) +78 + j*(41) +103 + j*(-173) +-161 + j*(-172) +-162 + j*(106) +95 + j*(105) +82 + j*(-119) +-99 + j*(-95) +-67 + j*(33) +-4 + j*(-14) +-74 + j*(-21) +-40 + j*(69) +55 + j*(6) +-31 + j*(-93) +-138 + j*(-1) +-71 + j*(106) +7 + j*(80) +4 + j*(54) +16 + j*(66) +38 + j*(67) +89 + j*(71) +165 + j*(-13) +92 + j*(-161) +-76 + j*(-122) +-33 + j*(4) +47 + j*(-105) +-160 + j*(-189) +-305 + j*(81) +-49 + j*(291) +180 + j*(107) +85 + j*(-82) +-24 + j*(-65) +-71 + j*(-59) +-182 + j*(24) +-113 + j*(245) +162 + j*(235) +211 + j*(-2) +82 + j*(-57) +105 + j*(-40) +57 + j*(-190) +-214 + j*(-143) +-218 + j*(195) +119 + j*(257) +211 + j*(-23) +-3 + j*(-104) +-58 + j*(68) +81 + j*(122) +161 + j*(34) +153 + j*(-53) +96 + j*(-107) +34 + j*(-81) +81 + j*(-36) +146 + j*(-136) +33 + j*(-271) +-147 + j*(-221) +-185 + j*(-76) +-133 + j*(-6) +-98 + j*(9) +-80 + j*(22) +-57 + j*(44) +0 + j*(50) +52 + j*(-19) +-2 + j*(-106) +-92 + j*(-95) +-130 + j*(-57) +-187 + j*(-7) +-173 + j*(144) +32 + j*(171) +71 + j*(-71) +-226 + j*(-107) +-287 + j*(241) +47 + j*(349) +146 + j*(107) +4 + j*(114) +156 + j*(236) +326 + j*(-4) +98 + j*(-211) +-76 + j*(-43) +40 + j*(45) +30 + j*(-45) +-41 + j*(55) +136 + j*(119) +220 + j*(-103) +8 + j*(-214) +-111 + j*(-71) +-53 + j*(21) +-6 + j*(43) +85 + j*(30) +97 + j*(-129) +-117 + j*(-163) +-171 + j*(70) +44 + j*(124) +54 + j*(-39) +-52 + j*(37) +140 + j*(110) +220 + j*(-192) +-144 + j*(-316) +-315 + j*(39) +-25 + j*(219) +111 + j*(18) +-19 + j*(-42) +4 + j*(44) +74 + j*(-40) +-48 + j*(-110) +-127 + j*(16) +-18 + j*(100) +57 + j*(18) +-7 + j*(-45) +-74 + j*(11) +-25 + j*(96) +80 + j*(71) +81 + j*(-37) +-18 + j*(-50) +-22 + j*(45) +85 + j*(44) +107 + j*(-78) +-13 + j*(-150) +-145 + j*(-63) +-115 + j*(125) +119 + j*(172) +253 + j*(-79) +37 + j*(-286) +-185 + j*(-141) +-96 + j*(16) +-42 + j*(-79) +-195 + j*(-61) +-161 + j*(144) +57 + j*(105) +-1 + j*(-112) +-246 + j*(-51) +-245 + j*(218) +-22 + j*(330) +162 + j*(235) +211 + j*(70) +119 + j*(-49) +3 + j*(-13) +25 + j*(96) +150 + j*(94) +206 + j*(-46) +86 + j*(-180) +-112 + j*(-100) +-64 + j*(151) +252 + j*(136) +301 + j*(-232) +-54 + j*(-372) +-244 + j*(-119) +-134 + j*(26) +-115 + j*(15) +-107 + j*(129) +71 + j*(166) +145 + j*(18) +98 + j*(-38) +134 + j*(-103) +-1 + j*(-272) +-283 + j*(-120) +-150 + j*(210) +165 + j*(83) +21 + j*(-183) +-189 + j*(-12) +-2 + j*(131) +64 + j*(-58) +-126 + j*(-49) +-59 + j*(136) +103 + j*(37) +-17 + j*(-81) +-87 + j*(56) +59 + j*(99) +103 + j*(-33) +22 + j*(-93) +-52 + j*(-93) +-134 + j*(-23) +-73 + j*(110) +72 + j*(34) +-58 + j*(-106) +-211 + j*(92) +29 + j*(271) +210 + j*(41) +16 + j*(-95) +-42 + j*(75) +119 + j*(57) +55 + j*(-96) +-86 + j*(-13) +-23 + j*(100) +32 + j*(108) +118 + j*(181) +371 + j*(95) +402 + j*(-281) +74 + j*(-475) +-175 + j*(-357) +-277 + j*(-229) +-358 + j*(-48) +-234 + j*(166) +-27 + j*(107) +-109 + j*(-28) +-217 + j*(129) +-30 + j*(271) +136 + j*(125) +71 + j*(-9) +-1 + j*(-15) +-70 + j*(-4) +-133 + j*(132) +42 + j*(294) +303 + j*(142) +223 + j*(-158) +-55 + j*(-142) +-59 + j*(102) +181 + j*(112) +231 + j*(-144) +-11 + j*(-252) +-147 + j*(-62) +1 + j*(39) +33 + j*(-119) +-177 + j*(-115) +-193 + j*(136) +23 + j*(185) +57 + j*(69) +38 + j*(128) +215 + j*(129) +273 + j*(-96) +122 + j*(-198) +69 + j*(-190) +-35 + j*(-276) +-267 + j*(-134) +-122 + j*(179) +229 + j*(28) +83 + j*(-345) +-271 + j*(-250) +-245 + j*(-14) +-210 + j*(-30) +-313 + j*(112) +-86 + j*(327) +173 + j*(93) +-69 + j*(-135) +-255 + j*(141) +42 + j*(303) +182 + j*(20) +-82 + j*(-75) +-145 + j*(193) +121 + j*(270) +237 + j*(54) +108 + j*(-70) +25 + j*(-13) +55 + j*(12) +28 + j*(-23) +-34 + j*(63) +120 + j*(189) +352 + j*(4) +215 + j*(-322) +-115 + j*(-276) +-127 + j*(-49) +-33 + j*(-69) +-134 + j*(-77) +-108 + j*(78) +27 + j*(11) +-137 + j*(-69) +-186 + j*(235) +243 + j*(309) +369 + j*(-182) +-112 + j*(-344) +-274 + j*(80) +69 + j*(216) +162 + j*(-28) +27 + j*(-59) +87 + j*(-18) +86 + j*(-177) +-136 + j*(-192) +-197 + j*(26) +-31 + j*(121) +74 + j*(19) +27 + j*(-87) +-86 + j*(-85) +-127 + j*(34) +-18 + j*(105) +66 + j*(24) +24 + j*(-49) +-16 + j*(-54) +-59 + j*(-66) +-125 + j*(-4) +-54 + j*(88) +26 + j*(-8) +-124 + j*(-73) +-205 + j*(136) +11 + j*(251) +134 + j*(88) +36 + j*(11) +19 + j*(73) +58 + j*(71) +84 + j*(89) +207 + j*(41) +176 + j*(-191) +-116 + j*(-194) +-131 + j*(103) +144 + j*(100) +114 + j*(-139) +-59 + j*(-81) +41 + j*(-2) +23 + j*(-161) +-189 + j*(-74) +-52 + j*(148) +144 + j*(-46) +-123 + j*(-207) +-264 + j*(122) +91 + j*(254) +206 + j*(-91) +-107 + j*(-187) +-196 + j*(83) +6 + j*(176) +105 + j*(62) +81 + j*(-24) +15 + j*(-57) +-35 + j*(6) +52 + j*(47) +86 + j*(-85) +-80 + j*(-120) +-107 + j*(52) +46 + j*(39) +-36 + j*(-94) +-171 + j*(52) +12 + j*(190) +124 + j*(6) +-62 + j*(-54) +-77 + j*(151) +130 + j*(168) +180 + j*(26) +166 + j*(-25) +178 + j*(-141) +-4 + j*(-233) +-127 + j*(-46) +69 + j*(38) +97 + j*(-207) +-206 + j*(-209) +-213 + j*(114) +80 + j*(118) +58 + j*(-122) +-129 + j*(-64) +-42 + j*(75) +59 + j*(-29) +-37 + j*(-95) +-54 + j*(-34) +-23 + j*(-101) +-174 + j*(-157) +-306 + j*(5) +-240 + j*(180) +-135 + j*(243) +-26 + j*(291) +132 + j*(257) +208 + j*(124) +208 + j*(8) +157 + j*(-139) +-93 + j*(-210) +-298 + j*(95) +19 + j*(426) +450 + j*(151) +264 + j*(-317) +-165 + j*(-221) +-127 + j*(117) +110 + j*(104) +114 + j*(-34) +76 + j*(-50) +64 + j*(-108) +-61 + j*(-112) +-74 + j*(44) +88 + j*(50) +76 + j*(-103) +-59 + j*(-65) +11 + j*(50) +115 + j*(-42) +33 + j*(-141) +-35 + j*(-100) +-25 + j*(-98) +-86 + j*(-113) +-129 + j*(-36) +-80 + j*(10) +-71 + j*(-4) +-76 + j*(33) +-16 + j*(42) +-2 + j*(-22) +-56 + j*(-44) +-93 + j*(-27) +-144 + j*(9) +-151 + j*(122) +-30 + j*(186) +37 + j*(105) +-25 + j*(115) +68 + j*(235) +293 + j*(144) +298 + j*(-127) +99 + j*(-245) +-52 + j*(-191) +-116 + j*(-89) +-85 + j*(19) +25 + j*(21) +33 + j*(-80) +-43 + j*(-100) +-53 + j*(-90) +-119 + j*(-156) +-303 + j*(-93) +-355 + j*(148) +-214 + j*(329) +-27 + j*(395) +199 + j*(349) +314 + j*(112) +151 + j*(-49) +52 + j*(86) +244 + j*(121) +284 + j*(-127) +49 + j*(-185) +27 + j*(2) +211 + j*(-42) +151 + j*(-265) +-82 + j*(-264) +-145 + j*(-88) +-41 + j*(-4) +49 + j*(-73) +-9 + j*(-200) +-190 + j*(-180) +-232 + j*(2) +-119 + j*(68) +-112 + j*(33) +-122 + j*(126) +45 + j*(161) +108 + j*(-21) +-56 + j*(-84) +-106 + j*(52) +-6 + j*(88) +16 + j*(47) +35 + j*(50) +67 + j*(-11) +-2 + j*(-44) +1 + j*(21) +67 + j*(-56) +-99 + j*(-135) +-204 + j*(109) +81 + j*(243) +216 + j*(-44) +-47 + j*(-130) +64 + j*(-24) +41 + j*(-137) +-82 + j*(-142) +-141 + j*(-64) +-153 + j*(28) +-67 + j*(131) +93 + j*(62) +26 + j*(-125) +-173 + j*(-42) +-63 + j*(158) +138 + j*(8) +-60 + j*(-206) +-307 + j*(6) +-136 + j*(267) +69 + j*(159) +-29 + j*(66) +-37 + j*(230) +202 + j*(243) +265 + j*(5) +98 + j*(-65) +90 + j*(48) +213 + j*(-6) +160 + j*(-149) +56 + j*(-121) +119 + j*(-106) +91 + j*(-280) +-187 + j*(-302) +-305 + j*(-4) +-69 + j*(175) +116 + j*(18) +30 + j*(-141) +-93 + j*(-135) +-163 + j*(-81) +-216 + j*(28) +-139 + j*(171) +18 + j*(165) +49 + j*(78) +57 + j*(83) +155 + j*(21) +103 + j*(-164) +-122 + j*(-168) +-175 + j*(40) +-28 + j*(109) +23 + j*(23) +-23 + j*(6) +-10 + j*(32) +2 + j*(1) +-35 + j*(-1) +-23 + j*(35) +13 + j*(-4) +-66 + j*(-68) +-210 + j*(28) +-175 + j*(274) +111 + j*(379) +349 + j*(170) +293 + j*(-82) +161 + j*(-128) +151 + j*(-157) +40 + j*(-276) +-187 + j*(-195) +-172 + j*(47) +14 + j*(54) +-13 + j*(-79) +-132 + j*(-13) +-64 + j*(110) +35 + j*(85) +52 + j*(49) +99 + j*(15) +79 + j*(-91) +-39 + j*(-89) +-27 + j*(5) +39 + j*(-52) +-76 + j*(-105) +-136 + j*(44) +11 + j*(106) +51 + j*(-4) +-18 + j*(1) +37 + j*(23) +4 + j*(-74) +-138 + j*(35) +53 + j*(249) +366 + j*(14) +157 + j*(-379) +-248 + j*(-250) +-188 + j*(83) +41 + j*(38) +-22 + j*(-115) +-141 + j*(-55) +-129 + j*(31) +-105 + j*(80) +-28 + j*(122) +49 + j*(49) +-32 + j*(-14) +-62 + j*(99) +91 + j*(110) +94 + j*(-57) +-52 + j*(-32) +41 + j*(77) +134 + j*(-120) +-168 + j*(-247) +-377 + j*(124) +-13 + j*(419) +333 + j*(126) +125 + j*(-203) +-144 + j*(-54) +-21 + j*(157) +153 + j*(50) +77 + j*(-89) +-10 + j*(-42) +33 + j*(-24) +-8 + j*(-95) +-121 + j*(-30) +-54 + j*(96) +50 + j*(21) +-81 + j*(-54) +-167 + j*(165) +110 + j*(319) +340 + j*(62) +156 + j*(-168) +14 + j*(-24) +199 + j*(27) +245 + j*(-236) +-26 + j*(-341) +-163 + j*(-165) +-98 + j*(-92) +-140 + j*(-118) +-202 + j*(-4) +-97 + j*(97) +-11 + j*(29) +-64 + j*(-8) +-75 + j*(61) +6 + j*(84) +62 + j*(32) +72 + j*(-46) +13 + j*(-127) +-112 + j*(-111) +-132 + j*(13) +-25 + j*(25) +-56 + j*(-96) +-250 + j*(-49) +-264 + j*(226) +14 + j*(361) +247 + j*(173) +189 + j*(-72) +2 + j*(-122) +-89 + j*(-29) +-75 + j*(69) +-3 + j*(126) +95 + j*(119) +141 + j*(39) +118 + j*(-20) +115 + j*(-37) +116 + j*(-103) +31 + j*(-166) +-64 + j*(-118) +-65 + j*(-54) +-66 + j*(-45) +-90 + j*(16) +6 + j*(77) +94 + j*(-42) +-61 + j*(-146) +-194 + j*(41) +13 + j*(211) +212 + j*(1) +8 + j*(-216) +-228 + j*(-27) +-75 + j*(230) +174 + j*(141) +160 + j*(-45) +83 + j*(-62) +115 + j*(-94) +39 + j*(-226) +-177 + j*(-192) +-229 + j*(41) +-44 + j*(156) +86 + j*(37) +6 + j*(-76) +-101 + j*(-11) +-45 + j*(110) +105 + j*(72) +92 + j*(-110) +-130 + j*(-128) +-197 + j*(137) +96 + j*(279) +316 + j*(0) +93 + j*(-269) +-172 + j*(-113) +-61 + j*(115) +125 + j*(30) +73 + j*(-115) +4 + j*(-102) +11 + j*(-150) +-149 + j*(-238) +-384 + j*(-59) +-305 + j*(295) +54 + j*(376) +254 + j*(119) +124 + j*(-99) +-45 + j*(-50) +-22 + j*(57) +33 + j*(26) +-25 + j*(24) +21 + j*(144) +226 + j*(79) +194 + j*(-200) +-114 + j*(-233) +-198 + j*(49) +19 + j*(156) +126 + j*(13) +56 + j*(-76) +-11 + j*(-73) +-66 + j*(-25) +-28 + j*(86) +134 + j*(58) +122 + j*(-135) +-61 + j*(-136) +-48 + j*(8) +57 + j*(-56) +-45 + j*(-141) +-107 + j*(-39) +-30 + j*(-52) +-159 + j*(-131) +-292 + j*(89) +-57 + j*(279) +117 + j*(89) +-38 + j*(10) +1 + j*(186) +231 + j*(69) +86 + j*(-197) +-174 + j*(-53) +-38 + j*(173) +136 + j*(46) +21 + j*(-68) +-37 + j*(43) +69 + j*(60) +68 + j*(-39) +-21 + j*(-29) +-25 + j*(62) +76 + j*(116) +218 + j*(29) +185 + j*(-206) +-100 + j*(-251) +-214 + j*(39) +54 + j*(186) +209 + j*(-40) +37 + j*(-188) +-83 + j*(-73) +-18 + j*(6) +35 + j*(-20) +56 + j*(-64) +25 + j*(-142) +-98 + j*(-144) +-122 + j*(-19) +-17 + j*(-11) +-58 + j*(-113) +-182 + j*(-39) +-112 + j*(105) +23 + j*(50) +-20 + j*(-59) +-103 + j*(-37) +-104 + j*(3) +-135 + j*(6) +-189 + j*(83) +-144 + j*(216) +12 + j*(267) +136 + j*(172) +117 + j*(60) +77 + j*(79) +180 + j*(68) +186 + j*(-144) +-102 + j*(-214) +-239 + j*(102) +61 + j*(281) +254 + j*(25) +56 + j*(-141) +-49 + j*(6) +57 + j*(30) +-7 + j*(-59) +-101 + j*(93) +103 + j*(225) +279 + j*(25) +134 + j*(-156) +2 + j*(-59) +90 + j*(11) +130 + j*(-89) +39 + j*(-122) +33 + j*(-61) +78 + j*(-105) +-21 + j*(-170) +-120 + j*(-28) +64 + j*(127) +313 + j*(-81) +153 + j*(-427) +-210 + j*(-384) +-231 + j*(-131) +-118 + j*(-202) +-387 + j*(-298) +-633 + j*(100) +-279 + j*(514) +172 + j*(310) +67 + j*(-50) +-197 + j*(56) +-66 + j*(297) +193 + j*(192) +164 + j*(-54) +-28 + j*(-98) +-116 + j*(18) +-81 + j*(117) +-19 + j*(151) +37 + j*(168) +129 + j*(162) +209 + j*(63) +163 + j*(-70) +45 + j*(-78) +25 + j*(6) +100 + j*(17) +131 + j*(-62) +88 + j*(-138) +-5 + j*(-174) +-111 + j*(-132) +-146 + j*(-30) +-123 + j*(44) +-94 + j*(106) +11 + j*(177) +171 + j*(91) +123 + j*(-115) +-89 + j*(-86) +-54 + j*(130) +180 + j*(79) +123 + j*(-181) +-157 + j*(-134) +-135 + j*(154) +141 + j*(170) +193 + j*(-69) +15 + j*(-131) +-30 + j*(-1) +87 + j*(23) +130 + j*(-98) +33 + j*(-192) +-98 + j*(-163) +-141 + j*(-40) +-41 + j*(35) +35 + j*(-76) +-122 + j*(-187) +-322 + j*(-10) +-206 + j*(290) +116 + j*(298) +231 + j*(49) +106 + j*(-91) +16 + j*(-54) +35 + j*(-28) +39 + j*(-62) +7 + j*(-80) +-8 + j*(-82) +-33 + j*(-113) +-124 + j*(-127) +-225 + j*(-24) +-181 + j*(148) +-6 + j*(187) +78 + j*(68) +18 + j*(-5) +-16 + j*(27) +11 + j*(34) +21 + j*(15) +33 + j*(-19) +-19 + j*(-102) +-199 + j*(-66) +-223 + j*(192) +48 + j*(288) +165 + j*(59) +-33 + j*(-6) +-26 + j*(218) +255 + j*(191) +272 + j*(-114) +8 + j*(-186) +-96 + j*(-7) +-14 + j*(115) +115 + j*(137) +253 + j*(25) +185 + j*(-202) +-76 + j*(-175) +-47 + j*(91) +243 + j*(33) +178 + j*(-313) +-200 + j*(-301) +-272 + j*(54) +-1 + j*(194) +169 + j*(40) +136 + j*(-121) +37 + j*(-179) +-43 + j*(-160) +-63 + j*(-138) +-114 + j*(-163) +-235 + j*(-103) +-231 + j*(80) +-65 + j*(129) +-11 + j*(6) +-116 + j*(-33) +-173 + j*(54) +-153 + j*(148) +-80 + j*(243) +95 + j*(272) +233 + j*(119) +171 + j*(-49) +55 + j*(-51) +62 + j*(1) +98 + j*(-42) +52 + j*(-112) +-40 + j*(-102) +-72 + j*(-16) +1 + j*(43) +81 + j*(-20) +53 + j*(-125) +-43 + j*(-179) +-188 + j*(-168) +-325 + j*(2) +-218 + j*(263) +74 + j*(243) +76 + j*(-13) +-163 + j*(36) +-66 + j*(303) +223 + j*(214) +158 + j*(-27) +11 + j*(62) +166 + j*(144) +234 + j*(-49) +67 + j*(-89) +112 + j*(40) +257 + j*(-106) +83 + j*(-316) +-161 + j*(-204) +-150 + j*(-12) +-67 + j*(54) +35 + j*(88) +170 + j*(-28) +55 + j*(-238) +-200 + j*(-151) +-151 + j*(99) +42 + j*(74) +9 + j*(-31) +-1 + j*(45) +143 + j*(-13) +63 + j*(-231) +-192 + j*(-179) +-185 + j*(47) +-30 + j*(47) +-66 + j*(-51) +-162 + j*(28) +-84 + j*(158) +79 + j*(127) +111 + j*(-55) +-77 + j*(-161) +-276 + j*(13) +-178 + j*(303) +132 + j*(349) +320 + j*(135) +297 + j*(-108) +119 + j*(-267) +-125 + j*(-216) +-168 + j*(18) +16 + j*(81) +48 + j*(-74) +-92 + j*(-81) +-94 + j*(18) +-81 + j*(-3) +-179 + j*(80) +-57 + j*(281) +202 + j*(188) +150 + j*(-26) +40 + j*(47) +203 + j*(78) +226 + j*(-163) +0 + j*(-209) +-13 + j*(-86) +6 + j*(-194) +-262 + j*(-181) +-286 + j*(189) +80 + j*(265) +151 + j*(-21) +-35 + j*(-16) +78 + j*(108) +181 + j*(-91) +-48 + j*(-185) +-113 + j*(24) +58 + j*(37) +21 + j*(-93) +-57 + j*(-22) +38 + j*(-23) +-54 + j*(-161) +-253 + j*(-11) +-105 + j*(243) +149 + j*(144) +117 + j*(-54) +15 + j*(-83) +-57 + j*(-91) +-180 + j*(6) +-98 + j*(235) +189 + j*(204) +222 + j*(-64) +36 + j*(-125) +-2 + j*(-39) +12 + j*(-47) +-20 + j*(-14) +54 + j*(13) +81 + j*(-112) +-78 + j*(-156) +-151 + j*(-22) +-98 + j*(49) +-86 + j*(112) +76 + j*(211) +308 + j*(4) +122 + j*(-337) +-262 + j*(-223) +-233 + j*(119) +6 + j*(144) +40 + j*(33) +45 + j*(11) +43 + j*(-90) +-130 + j*(-105) +-162 + j*(110) +53 + j*(146) +67 + j*(-40) +-78 + j*(-10) +-3 + j*(91) +42 + j*(-25) +-122 + j*(-4) +-47 + j*(221) +228 + j*(124) +138 + j*(-163) +-124 + j*(-83) +-40 + j*(128) +112 + j*(25) +-30 + j*(-65) +-81 + j*(145) +210 + j*(213) +359 + j*(-129) +35 + j*(-382) +-292 + j*(-139) +-144 + j*(200) +153 + j*(124) +97 + j*(-101) +-52 + j*(-10) +112 + j*(100) +239 + j*(-129) +11 + j*(-296) +-152 + j*(-137) +-54 + j*(-61) +-98 + j*(-168) +-269 + j*(-66) +-192 + j*(139) +-30 + j*(98) +-91 + j*(12) +-161 + j*(124) +-47 + j*(248) +115 + j*(233) +236 + j*(119) +250 + j*(-72) +95 + j*(-197) +-52 + j*(-136) +-57 + j*(-49) +-47 + j*(-37) +-54 + j*(-12) +-31 + j*(-16) +-93 + j*(-37) +-151 + j*(93) +11 + j*(206) +153 + j*(60) +35 + j*(-54) +-14 + j*(54) +110 + j*(35) +32 + j*(-99) +-103 + j*(47) +114 + j*(197) +316 + j*(-71) +65 + j*(-332) +-214 + j*(-156) +-134 + j*(71) +-4 + j*(54) +1 + j*(30) +66 + j*(43) +121 + j*(-80) +-9 + j*(-190) +-156 + j*(-113) +-150 + j*(11) +-104 + j*(44) +-106 + j*(69) +-71 + j*(145) +52 + j*(167) +144 + j*(62) +97 + j*(-61) +-7 + j*(-66) +-28 + j*(-11) +-20 + j*(-7) +-63 + j*(14) +-44 + j*(110) +88 + j*(124) +147 + j*(-8) +36 + j*(-94) +-58 + j*(1) +39 + j*(115) +204 + j*(23) +161 + j*(-202) +-83 + j*(-239) +-188 + j*(-33) +-38 + j*(81) +49 + j*(-44) +-83 + j*(-132) +-227 + j*(-7) +-192 + j*(210) +33 + j*(340) +315 + j*(206) +324 + j*(-126) +49 + j*(-216) +-6 + j*(-18) +190 + j*(-70) +64 + j*(-332) +-242 + j*(-202) +-119 + j*(66) +68 + j*(-121) +-240 + j*(-272) +-431 + j*(117) +-62 + j*(359) +168 + j*(81) +-14 + j*(-62) +-42 + j*(56) +35 + j*(-28) +-143 + j*(-83) +-199 + j*(154) +36 + j*(207) +38 + j*(9) +-150 + j*(108) +25 + j*(344) +317 + j*(180) +221 + j*(-98) +23 + j*(-40) +105 + j*(94) +245 + j*(-13) +183 + j*(-194) +4 + j*(-231) +-112 + j*(-112) +-64 + j*(18) +39 + j*(7) +29 + j*(-66) +-8 + j*(-44) +40 + j*(-46) +14 + j*(-140) +-119 + j*(-122) +-127 + j*(6) +-47 + j*(11) +-90 + j*(-26) +-123 + j*(74) +-8 + j*(132) +60 + j*(39) +-11 + j*(-6) +-38 + j*(69) +47 + j*(123) +156 + j*(77) +216 + j*(-64) +124 + j*(-233) +-90 + j*(-257) +-214 + j*(-104) +-177 + j*(40) +-98 + j*(95) +-26 + j*(106) +40 + j*(76) +68 + j*(6) +35 + j*(-67) +-59 + j*(-93) +-153 + j*(0) +-78 + j*(149) +103 + j*(101) +69 + j*(-101) +-152 + j*(-82) +-163 + j*(154) +59 + j*(207) +144 + j*(28) +11 + j*(-62) +-85 + j*(35) +-25 + j*(155) +107 + j*(158) +172 + j*(62) +152 + j*(-12) +137 + j*(-38) +126 + j*(-89) +62 + j*(-109) +65 + j*(-64) +127 + j*(-144) +-11 + j*(-286) +-241 + j*(-156) +-163 + j*(96) +54 + j*(46) +-8 + j*(-119) +-135 + j*(-46) +-76 + j*(45) +-47 + j*(12) +-54 + j*(60) +71 + j*(45) +36 + j*(-161) +-245 + j*(-125) +-243 + j*(197) +57 + j*(221) +52 + j*(-16) +-157 + j*(70) +-7 + j*(316) +300 + j*(180) +240 + j*(-146) +-49 + j*(-164) +-121 + j*(78) +91 + j*(207) +287 + j*(41) +203 + j*(-204) +-25 + j*(-200) +-50 + j*(-33) +74 + j*(-29) +61 + j*(-146) +-47 + j*(-156) +-89 + j*(-97) +-93 + j*(-52) +-59 + j*(-19) +-25 + j*(-72) +-133 + j*(-123) +-226 + j*(28) +-69 + j*(151) +38 + j*(-12) +-158 + j*(-95) +-256 + j*(132) +-58 + j*(262) +54 + j*(157) +24 + j*(139) +112 + j*(168) +187 + j*(37) +86 + j*(-59) +16 + j*(0) +59 + j*(20) +46 + j*(-21) +-2 + j*(8) +18 + j*(72) +103 + j*(110) +242 + j*(49) +283 + j*(-177) +63 + j*(-349) +-171 + j*(-238) +-180 + j*(-73) +-181 + j*(-31) +-218 + j*(127) +13 + j*(308) +317 + j*(100) +180 + j*(-249) +-138 + j*(-177) +-78 + j*(81) +146 + j*(-2) +57 + j*(-236) +-176 + j*(-192) +-194 + j*(-18) +-125 + j*(-6) +-196 + j*(-15) +-239 + j*(140) +-93 + j*(263) +40 + j*(199) +26 + j*(161) +98 + j*(230) +284 + j*(135) +255 + j*(-117) +28 + j*(-158) +-29 + j*(-4) +69 + j*(37) +98 + j*(-4) +141 + j*(-21) +175 + j*(-158) +-8 + j*(-275) +-180 + j*(-100) +-18 + j*(64) +117 + j*(-118) +-94 + j*(-255) +-248 + j*(-61) +-112 + j*(74) +-43 + j*(-29) +-158 + j*(-42) +-182 + j*(93) +-77 + j*(161) +21 + j*(132) +57 + j*(35) +-44 + j*(-43) +-165 + j*(81) +-31 + j*(267) +203 + j*(157) +128 + j*(-79) +-87 + j*(-9) +-4 + j*(209) +245 + j*(149) +262 + j*(-107) +58 + j*(-215) +-103 + j*(-107) +-89 + j*(53) +44 + j*(110) +147 + j*(25) +136 + j*(-93) +44 + j*(-163) +-94 + j*(-143) +-162 + j*(35) +33 + j*(192) +276 + j*(1) +118 + j*(-319) +-238 + j*(-221) +-201 + j*(113) +76 + j*(107) +74 + j*(-97) +-54 + j*(-91) +-29 + j*(-59) +-99 + j*(-143) +-282 + j*(-12) +-161 + j*(262) +140 + j*(199) +129 + j*(-60) +-64 + j*(-62) +-53 + j*(68) +25 + j*(51) +6 + j*(24) +28 + j*(52) +80 + j*(-8) +14 + j*(-88) +-90 + j*(-59) +-140 + j*(35) +-114 + j*(186) +98 + j*(286) +330 + j*(91) +204 + j*(-202) +-58 + j*(-122) +52 + j*(80) +236 + j*(-100) +20 + j*(-310) +-190 + j*(-115) +-12 + j*(36) +76 + j*(-176) +-187 + j*(-270) +-344 + j*(-37) +-238 + j*(147) +-126 + j*(180) +-33 + j*(186) +35 + j*(103) +-52 + j*(49) +-85 + j*(202) +136 + j*(264) +256 + j*(45) +103 + j*(-90) +21 + j*(-9) +54 + j*(-2) +-6 + j*(-4) +35 + j*(121) +237 + j*(49) +168 + j*(-221) +-132 + j*(-182) +-128 + j*(100) +96 + j*(123) +135 + j*(-8) +127 + j*(-30) +165 + j*(-132) +10 + j*(-247) +-133 + j*(-87) +42 + j*(19) +100 + j*(-223) +-222 + j*(-286) +-333 + j*(62) +-33 + j*(204) +95 + j*(-21) +-64 + j*(-117) +-130 + j*(-28) +-133 + j*(-2) +-188 + j*(76) +-101 + j*(226) +95 + j*(206) +155 + j*(47) +94 + j*(-64) +-34 + j*(-110) +-178 + j*(15) +-74 + j*(246) +210 + j*(184) +187 + j*(-86) +-14 + j*(-54) +100 + j*(81) +223 + j*(-134) +-47 + j*(-290) +-216 + j*(-41) +-10 + j*(69) +-2 + j*(-136) +-267 + j*(-77) +-235 + j*(247) +64 + j*(313) +211 + j*(148) +238 + j*(6) +191 + j*(-171) +-45 + j*(-252) +-218 + j*(-37) +-59 + j*(169) +144 + j*(66) +88 + j*(-122) +-86 + j*(-115) +-136 + j*(40) +-5 + j*(144) +148 + j*(40) +75 + j*(-150) +-138 + j*(-115) +-154 + j*(91) +-1 + j*(159) +87 + j*(103) +144 + j*(42) +158 + j*(-103) +-23 + j*(-199) +-171 + j*(-38) +-54 + j*(110) +37 + j*(25) +-58 + j*(23) +9 + j*(170) +218 + j*(90) +172 + j*(-133) +-3 + j*(-113) +45 + j*(-8) +119 + j*(-112) +-10 + j*(-196) +-89 + j*(-106) +-42 + j*(-93) +-127 + j*(-153) +-262 + j*(-16) +-144 + j*(182) +47 + j*(115) +-1 + j*(-23) +-86 + j*(62) +46 + j*(127) +110 + j*(-31) +-53 + j*(-82) +-69 + j*(88) +113 + j*(64) +59 + j*(-134) +-136 + j*(-60) +-41 + j*(107) +82 + j*(-21) +-89 + j*(-90) +-97 + j*(122) +169 + j*(59) +45 + j*(-286) +-397 + j*(-161) +-355 + j*(334) +84 + j*(410) +231 + j*(128) +119 + j*(5) +63 + j*(3) +4 + j*(25) +30 + j*(139) +221 + j*(116) +240 + j*(-124) +23 + j*(-187) +-40 + j*(-53) +13 + j*(-55) +-84 + j*(-57) +-74 + j*(125) +165 + j*(130) +197 + j*(-127) +-37 + j*(-181) +-86 + j*(2) +45 + j*(20) +16 + j*(-74) +-71 + j*(1) +35 + j*(109) +179 + j*(11) +139 + j*(-147) +26 + j*(-174) +-8 + j*(-152) +-52 + j*(-191) +-188 + j*(-172) +-266 + j*(3) +-136 + j*(168) +52 + j*(132) +100 + j*(-23) +17 + j*(-127) +-110 + j*(-131) +-202 + j*(-24) +-151 + j*(117) +-20 + j*(118) +-13 + j*(30) +-76 + j*(63) +-2 + j*(139) +105 + j*(52) +33 + j*(-74) +-95 + j*(-33) +-92 + j*(82) +-8 + j*(115) +42 + j*(70) +19 + j*(27) +-23 + j*(67) +59 + j*(145) +216 + j*(42) +144 + j*(-204) +-153 + j*(-209) +-245 + j*(70) +-40 + j*(204) +59 + j*(79) +-44 + j*(63) +1 + j*(219) +226 + j*(186) +257 + j*(-53) +64 + j*(-124) +5 + j*(14) +122 + j*(37) +124 + j*(-71) +35 + j*(-55) +83 + j*(21) +177 + j*(-45) +146 + j*(-151) +92 + j*(-190) +26 + j*(-250) +-139 + j*(-231) +-185 + j*(-25) +24 + j*(56) +122 + j*(-159) +-81 + j*(-301) +-264 + j*(-180) +-276 + j*(-36) +-257 + j*(64) +-177 + j*(170) +-37 + j*(166) +-4 + j*(84) +-8 + j*(76) +38 + j*(30) +-32 + j*(-66) +-163 + j*(13) +-101 + j*(153) +1 + j*(117) +-42 + j*(90) +-12 + j*(180) +119 + j*(151) +118 + j*(46) +96 + j*(48) +146 + j*(-9) +49 + j*(-115) +-74 + j*(-1) +65 + j*(105) +148 + j*(-71) +-60 + j*(-138) +-116 + j*(88) +109 + j*(135) +158 + j*(-69) +0 + j*(-125) +-55 + j*(-34) +-37 + j*(9) +-11 + j*(54) +79 + j*(37) +63 + j*(-92) +-106 + j*(-74) +-110 + j*(134) +105 + j*(196) +244 + j*(34) +192 + j*(-152) +17 + j*(-219) +-125 + j*(-83) +-1 + j*(95) +216 + j*(-44) +77 + j*(-322) +-231 + j*(-233) +-198 + j*(36) +-13 + j*(4) +-98 + j*(-134) +-258 + j*(-17) +-184 + j*(182) +8 + j*(197) +91 + j*(61) +1 + j*(-35) +-86 + j*(46) +16 + j*(127) +89 + j*(-1) +-80 + j*(-47) +-95 + j*(187) +206 + j*(194) +231 + j*(-133) +-62 + j*(-153) +-21 + j*(76) +164 + j*(-67) +-66 + j*(-256) +-270 + j*(-5) +-62 + j*(169) +6 + j*(22) +-118 + j*(103) +91 + j*(258) +290 + j*(-17) +15 + j*(-226) +-156 + j*(23) +66 + j*(129) +97 + j*(-69) +-72 + j*(-26) +34 + j*(121) +175 + j*(-28) +25 + j*(-163) +-91 + j*(-52) +-42 + j*(16) +-49 + j*(22) +-19 + j*(124) +164 + j*(124) +243 + j*(-84) +98 + j*(-250) +-100 + j*(-234) +-218 + j*(-77) +-147 + j*(123) +78 + j*(139) +161 + j*(-71) +4 + j*(-197) +-129 + j*(-128) +-143 + j*(-45) +-141 + j*(2) +-122 + j*(45) +-107 + j*(54) +-117 + j*(101) +-40 + j*(161) +40 + j*(84) +-67 + j*(37) +-97 + j*(231) +188 + j*(313) +370 + j*(17) +158 + j*(-226) +-66 + j*(-129) +-54 + j*(23) +35 + j*(68) +139 + j*(27) +158 + j*(-143) +-45 + j*(-235) +-185 + j*(-54) +-51 + j*(61) +-35 + j*(-49) +-178 + j*(45) +-4 + j*(259) +267 + j*(54) +59 + j*(-241) +-228 + j*(-37) +-34 + j*(224) +180 + j*(54) +35 + j*(-87) +-25 + j*(50) +119 + j*(49) +84 + j*(-80) +0 + j*(-6) +139 + j*(39) +206 + j*(-162) +13 + j*(-283) +-124 + j*(-184) +-116 + j*(-117) +-155 + j*(-119) +-226 + j*(-56) +-247 + j*(66) +-173 + j*(209) +42 + j*(250) +177 + j*(32) +-29 + j*(-141) +-209 + j*(83) +45 + j*(274) +258 + j*(11) +16 + j*(-204) +-165 + j*(-1) +-2 + j*(117) +32 + j*(-23) +-111 + j*(28) +-8 + j*(192) +165 + j*(91) +99 + j*(-37) +73 + j*(5) +147 + j*(-90) +-31 + j*(-238) +-258 + j*(-49) +-117 + j*(214) +118 + j*(139) +89 + j*(-19) +11 + j*(0) +40 + j*(21) +35 + j*(-11) +9 + j*(13) +49 + j*(36) +94 + j*(3) +107 + j*(-69) +24 + j*(-164) +-161 + j*(-100) +-141 + j*(158) +157 + j*(201) +267 + j*(-76) +83 + j*(-209) +10 + j*(-151) +-16 + j*(-212) +-202 + j*(-191) +-211 + j*(35) +-29 + j*(13) +-168 + j*(-146) +-388 + j*(119) +-94 + j*(441) +273 + j*(221) +144 + j*(-82) +-36 + j*(16) +87 + j*(100) +141 + j*(-43) +18 + j*(-96) +-24 + j*(-37) +-25 + j*(-23) +-53 + j*(13) +-23 + j*(74) +40 + j*(106) +163 + j*(103) +291 + j*(-91) +100 + j*(-375) +-272 + j*(-255) +-221 + j*(100) +53 + j*(44) +-82 + j*(-169) +-295 + j*(35) +-92 + j*(264) +97 + j*(131) +34 + j*(59) +103 + j*(104) +171 + j*(-62) +-25 + j*(-145) +-67 + j*(46) +138 + j*(-2) +1 + j*(-266) +-345 + j*(-102) +-222 + j*(293) +151 + j*(245) +151 + j*(-49) +-62 + j*(-60) +-69 + j*(107) +81 + j*(129) +144 + j*(-4) +32 + j*(-121) +-141 + j*(-47) +-134 + j*(176) +87 + j*(270) +281 + j*(137) +303 + j*(-72) +185 + j*(-235) +-19 + j*(-260) +-150 + j*(-108) +-71 + j*(45) +59 + j*(11) +47 + j*(-105) +-69 + j*(-129) +-163 + j*(-31) +-121 + j*(141) +97 + j*(195) +257 + j*(-18) +95 + j*(-258) +-180 + j*(-167) +-146 + j*(113) +137 + j*(120) +197 + j*(-177) +-105 + j*(-314) +-317 + j*(-47) +-110 + j*(209) +154 + j*(55) +45 + j*(-206) +-199 + j*(-161) +-227 + j*(14) +-176 + j*(76) +-161 + j*(139) +-66 + j*(207) +28 + j*(161) +32 + j*(127) +88 + j*(130) +134 + j*(21) +21 + j*(-32) +13 + j*(87) +168 + j*(25) +63 + j*(-192) +-204 + j*(-83) +-122 + j*(182) +84 + j*(126) +18 + j*(18) +-4 + j*(131) +150 + j*(105) +93 + j*(-37) +-3 + j*(91) +233 + j*(173) +367 + j*(-139) +78 + j*(-336) +-112 + j*(-143) +-4 + j*(-45) +-9 + j*(-131) +-103 + j*(-71) +-32 + j*(-3) +-30 + j*(-91) +-170 + j*(-27) +-76 + j*(189) +197 + j*(115) +184 + j*(-183) +-89 + j*(-236) +-194 + j*(-35) +-69 + j*(81) +33 + j*(7) +-21 + j*(-98) +-161 + j*(-71) +-204 + j*(107) +-37 + j*(241) +161 + j*(144) +149 + j*(-46) +23 + j*(-83) +-8 + j*(-36) +-11 + j*(-44) +-68 + j*(-16) +-21 + j*(86) +132 + j*(37) +116 + j*(-173) +-110 + j*(-238) +-264 + j*(-83) +-255 + j*(90) +-177 + j*(215) +-18 + j*(296) +179 + j*(214) +214 + j*(6) +68 + j*(-100) +-61 + j*(-35) +-76 + j*(94) +28 + j*(204) +221 + j*(187) +339 + j*(-5) +269 + j*(-218) +93 + j*(-317) +-90 + j*(-290) +-208 + j*(-153) +-174 + j*(-4) +-92 + j*(18) +-100 + j*(8) +-82 + j*(83) +41 + j*(72) +41 + j*(-76) +-122 + j*(-94) +-178 + j*(50) +-107 + j*(134) +-55 + j*(170) +46 + j*(211) +180 + j*(128) +154 + j*(-30) +33 + j*(-28) +62 + j*(72) +199 + j*(27) +215 + j*(-164) +37 + j*(-307) +-204 + j*(-242) +-288 + j*(-9) +-171 + j*(158) +-47 + j*(177) +31 + j*(182) +157 + j*(148) +211 + j*(-5) +117 + j*(-101) +71 + j*(-81) +66 + j*(-141) +-81 + j*(-169) +-163 + j*(18) +25 + j*(127) +137 + j*(-39) +8 + j*(-131) +-37 + j*(-42) +28 + j*(-64) +-48 + j*(-138) +-127 + j*(-55) +-64 + j*(-16) +-105 + j*(-90) +-244 + j*(19) +-136 + j*(239) +115 + j*(183) +109 + j*(-37) +-54 + j*(-30) +-6 + j*(98) +125 + j*(0) +-4 + j*(-169) +-224 + j*(-39) +-127 + j*(221) +142 + j*(183) +163 + j*(-52) +3 + j*(-110) +-57 + j*(-47) +-82 + j*(-33) +-137 + j*(42) +-74 + j*(148) +19 + j*(119) +-8 + j*(95) +24 + j*(173) +148 + j*(144) +152 + j*(57) +177 + j*(71) +301 + j*(-57) +147 + j*(-323) +-212 + j*(-216) +-170 + j*(158) +158 + j*(166) +208 + j*(-74) +96 + j*(-134) +68 + j*(-169) +-72 + j*(-209) +-172 + j*(-21) +32 + j*(85) +112 + j*(-146) +-152 + j*(-204) +-201 + j*(76) +69 + j*(110) +78 + j*(-144) +-173 + j*(-148) +-206 + j*(94) +5 + j*(179) +146 + j*(25) +59 + j*(-169) +-175 + j*(-153) +-226 + j*(95) +10 + j*(196) +125 + j*(-16) +-63 + j*(-127) +-161 + j*(30) +-50 + j*(101) +-45 + j*(33) +-116 + j*(107) +6 + j*(240) +213 + j*(154) +223 + j*(-80) +44 + j*(-195) +-124 + j*(-118) +-154 + j*(23) +-95 + j*(109) +-25 + j*(144) +65 + j*(130) +93 + j*(28) +-23 + j*(3) +-41 + j*(175) +191 + j*(228) +316 + j*(4) +185 + j*(-139) +129 + j*(-107) +139 + j*(-197) +-44 + j*(-263) +-156 + j*(-78) +-8 + j*(11) +12 + j*(-128) +-142 + j*(-95) +-98 + j*(57) +14 + j*(12) +-44 + j*(-38) +-41 + j*(38) +37 + j*(-1) +-17 + j*(-58) +-8 + j*(2) +69 + j*(-117) +-173 + j*(-255) +-416 + j*(61) +-106 + j*(380) +202 + j*(123) +-37 + j*(-95) +-159 + j*(194) +202 + j*(280) +305 + j*(-110) +-48 + j*(-237) +-175 + j*(40) +17 + j*(151) +99 + j*(49) +89 + j*(11) +108 + j*(-40) +42 + j*(-106) +-22 + j*(-56) +32 + j*(-42) +-19 + j*(-139) +-181 + j*(-54) +-98 + j*(169) +161 + j*(101) +119 + j*(-177) +-168 + j*(-175) +-224 + j*(81) +-42 + j*(186) +69 + j*(107) +79 + j*(40) +71 + j*(-13) +8 + j*(-39) +-18 + j*(30) +74 + j*(40) +71 + j*(-88) +-93 + j*(-84) +-103 + j*(117) +117 + j*(165) +234 + j*(-37) +115 + j*(-219) +-88 + j*(-229) +-228 + j*(-66) +-147 + j*(160) +113 + j*(151) +153 + j*(-106) +-80 + j*(-168) +-131 + j*(13) +-11 + j*(6) +-115 + j*(-80) +-220 + j*(122) +30 + j*(283) +231 + j*(51) +51 + j*(-148) +-115 + j*(-27) +-54 + j*(92) +1 + j*(101) +71 + j*(133) +204 + j*(47) +149 + j*(-150) +-49 + j*(-141) +-57 + j*(23) +74 + j*(31) +106 + j*(-79) +54 + j*(-171) +-86 + j*(-245) +-306 + j*(-141) +-325 + j*(156) +-70 + j*(288) +83 + j*(156) +46 + j*(88) +86 + j*(115) +158 + j*(23) +77 + j*(-86) +-24 + j*(-36) +1 + j*(38) +54 + j*(31) +68 + j*(4) +74 + j*(-21) +71 + j*(-45) +72 + j*(-72) +45 + j*(-136) +-73 + j*(-156) +-146 + j*(-31) +-47 + j*(54) +6 + j*(-28) +-95 + j*(-40) +-88 + j*(93) +56 + j*(94) +69 + j*(-23) +12 + j*(-25) +54 + j*(-30) +16 + j*(-139) +-152 + j*(-108) +-157 + j*(76) +-4 + j*(113) +44 + j*(16) +5 + j*(-21) +-18 + j*(-37) +-75 + j*(-35) +-98 + j*(37) +-44 + j*(64) +-59 + j*(38) +-85 + j*(127) +62 + j*(199) +191 + j*(50) +99 + j*(-103) +-20 + j*(-98) +-95 + j*(-77) +-221 + j*(28) +-174 + j*(302) +161 + j*(393) +378 + j*(131) +269 + j*(-100) +143 + j*(-91) +175 + j*(-71) +202 + j*(-180) +83 + j*(-320) +-159 + j*(-292) +-243 + j*(-25) +6 + j*(103) +125 + j*(-158) +-182 + j*(-278) +-330 + j*(53) +-28 + j*(209) +87 + j*(-44) +-133 + j*(-98) +-148 + j*(98) +-8 + j*(100) +-25 + j*(47) +15 + j*(103) +116 + j*(-4) +-33 + j*(-134) +-166 + j*(30) +-9 + j*(145) +65 + j*(6) +-54 + j*(-18) +-39 + j*(66) +-13 + j*(16) +-127 + j*(62) +-58 + j*(260) +182 + j*(251) +255 + j*(86) +262 + j*(12) +310 + j*(-136) +165 + j*(-339) +-88 + j*(-323) +-206 + j*(-184) +-265 + j*(-32) +-186 + j*(199) +124 + j*(227) +233 + j*(-72) +2 + j*(-201) +-70 + j*(-66) +-18 + j*(-109) +-199 + j*(-134) +-247 + j*(142) +52 + j*(219) +122 + j*(-47) +-98 + j*(-73) +-71 + j*(100) +48 + j*(25) +-83 + j*(-39) +-117 + j*(148) +96 + j*(191) +163 + j*(14) +69 + j*(-51) +52 + j*(-48) +-1 + j*(-100) +-112 + j*(-35) +-72 + j*(105) +53 + j*(110) +95 + j*(47) +127 + j*(4) +151 + j*(-115) +1 + j*(-254) +-248 + j*(-164) +-279 + j*(143) +-1 + j*(298) +228 + j*(104) +124 + j*(-119) +-37 + j*(-70) +9 + j*(3) +-1 + j*(-85) +-151 + j*(-22) +-82 + j*(185) +129 + j*(152) +133 + j*(8) +112 + j*(22) +209 + j*(-59) +104 + j*(-248) +-107 + j*(-182) +-71 + j*(-43) +-45 + j*(-108) +-172 + j*(-52) +-74 + j*(115) +83 + j*(-25) +-111 + j*(-149) +-212 + j*(94) +50 + j*(164) +59 + j*(-96) +-214 + j*(-33) +-108 + j*(274) +221 + j*(184) +180 + j*(-109) +-30 + j*(-104) +-18 + j*(21) +74 + j*(-22) +15 + j*(-140) +-161 + j*(-123) +-222 + j*(91) +-16 + j*(219) +119 + j*(31) +-93 + j*(-53) +-136 + j*(249) +267 + j*(321) +422 + j*(-106) +83 + j*(-326) +-103 + j*(-133) +-19 + j*(-66) +-76 + j*(-122) +-156 + j*(-10) +-61 + j*(81) +4 + j*(31) +-7 + j*(6) +-9 + j*(-18) +-76 + j*(-28) +-103 + j*(77) +8 + j*(109) +-6 + j*(26) +-76 + j*(143) +158 + j*(265) +379 + j*(-24) +124 + j*(-326) +-173 + j*(-161) +-82 + j*(57) +29 + j*(-19) +-76 + j*(-59) +-96 + j*(74) +27 + j*(110) +71 + j*(33) +47 + j*(18) +88 + j*(33) +153 + j*(-46) +93 + j*(-183) +-85 + j*(-192) +-160 + j*(-37) +-65 + j*(51) +-23 + j*(8) +-49 + j*(45) +68 + j*(91) +153 + j*(-83) +-45 + j*(-222) +-215 + j*(-39) +-76 + j*(128) +57 + j*(24) +-31 + j*(-62) +-94 + j*(17) +-35 + j*(77) +25 + j*(60) +62 + j*(13) +48 + j*(-77) +-66 + j*(-117) +-169 + j*(-25) +-148 + j*(110) +-46 + j*(175) +66 + j*(153) +118 + j*(61) +73 + j*(-13) +18 + j*(15) +72 + j*(76) +202 + j*(-4) +170 + j*(-243) +-148 + j*(-337) +-383 + j*(-37) +-180 + j*(274) +90 + j*(170) +14 + j*(19) +-11 + j*(147) +204 + j*(98) +129 + j*(-184) +-167 + j*(-109) +-95 + j*(139) +38 + j*(57) +-108 + j*(78) +52 + j*(354) +470 + j*(147) +305 + j*(-340) +-129 + j*(-233) +-25 + j*(78) +165 + j*(-70) +-12 + j*(-168) +-20 + j*(11) +165 + j*(-69) +56 + j*(-277) +-128 + j*(-223) +-151 + j*(-162) +-265 + j*(-139) +-330 + j*(69) +-180 + j*(206) +-98 + j*(208) +23 + j*(308) +322 + j*(173) +234 + j*(-235) +-176 + j*(-170) +-61 + j*(183) +243 + j*(-21) +-40 + j*(-298) +-281 + j*(18) +28 + j*(190) +106 + j*(-104) +-175 + j*(-97) +-111 + j*(153) +73 + j*(53) +-63 + j*(-48) +-102 + j*(122) +65 + j*(134) +61 + j*(25) +47 + j*(66) +148 + j*(-6) +30 + j*(-163) +-146 + j*(-35) +-18 + j*(112) +71 + j*(-20) +-81 + j*(-45) +-62 + j*(141) +157 + j*(104) +135 + j*(-134) +-111 + j*(-157) +-197 + j*(73) +-11 + j*(230) +194 + j*(111) +134 + j*(-102) +-62 + j*(-59) +-3 + j*(141) +239 + j*(83) +249 + j*(-192) +9 + j*(-319) +-204 + j*(-199) +-226 + j*(18) +-57 + j*(117) +35 + j*(-24) +-144 + j*(-77) +-189 + j*(177) +117 + j*(246) +204 + j*(-59) +-71 + j*(-129) +-109 + j*(110) +74 + j*(128) +74 + j*(46) +125 + j*(105) +293 + j*(-47) +124 + j*(-316) +-171 + j*(-190) +-82 + j*(49) +76 + j*(-41) +-20 + j*(-145) +-95 + j*(-79) +-88 + j*(-45) +-96 + j*(4) +-4 + j*(19) +-30 + j*(-130) +-269 + j*(-49) +-153 + j*(281) +231 + j*(144) +61 + j*(-247) +-316 + j*(-23) +-40 + j*(334) +289 + j*(28) +-18 + j*(-257) +-237 + j*(28) +10 + j*(163) +55 + j*(-52) +-143 + j*(-21) +-86 + j*(154) +36 + j*(115) +16 + j*(90) +100 + j*(114) +154 + j*(-57) +-74 + j*(-144) +-199 + j*(110) +39 + j*(281) +238 + j*(115) +183 + j*(-55) +107 + j*(-86) +57 + j*(-136) +-100 + j*(-133) +-185 + j*(79) +18 + j*(264) +272 + j*(126) +228 + j*(-124) +57 + j*(-138) +52 + j*(-62) +74 + j*(-105) +11 + j*(-100) +70 + j*(-62) +100 + j*(-229) +-173 + j*(-303) +-309 + j*(14) +-11 + j*(165) +88 + j*(-107) +-182 + j*(-122) +-108 + j*(158) +177 + j*(-9) +-81 + j*(-312) +-420 + j*(10) +-87 + j*(375) +267 + j*(65) +-15 + j*(-252) +-297 + j*(1) +-99 + j*(247) +85 + j*(129) +24 + j*(45) +37 + j*(105) +133 + j*(47) +86 + j*(-66) +2 + j*(-36) +59 + j*(-3) +82 + j*(-129) +-110 + j*(-208) +-272 + j*(-12) +-133 + j*(203) +57 + j*(128) +-1 + j*(5) +-67 + j*(95) +56 + j*(132) +55 + j*(2) +-104 + j*(74) +21 + j*(325) +397 + j*(245) +479 + j*(-168) +187 + j*(-424) +-112 + j*(-354) +-223 + j*(-171) +-210 + j*(-34) +-180 + j*(40) +-151 + j*(127) +-30 + j*(218) +151 + j*(151) +162 + j*(-45) +-1 + j*(-98) +-57 + j*(28) +45 + j*(92) +136 + j*(23) +131 + j*(-99) +6 + j*(-171) +-126 + j*(-63) +-30 + j*(97) +153 + j*(-6) +38 + j*(-223) +-206 + j*(-115) +-122 + j*(133) +104 + j*(64) +32 + j*(-139) +-155 + j*(-63) +-92 + j*(118) +71 + j*(85) +76 + j*(-45) +3 + j*(-83) +-49 + j*(-84) +-129 + j*(-49) +-145 + j*(93) +30 + j*(165) +148 + j*(-16) +-26 + j*(-164) +-193 + j*(-4) +-58 + j*(157) +66 + j*(52) +-34 + j*(-5) +-21 + j*(121) +144 + j*(62) +71 + j*(-129) +-114 + j*(-54) +-28 + j*(91) +74 + j*(-21) +-74 + j*(-101) +-159 + j*(49) +-75 + j*(139) +-42 + j*(163) +66 + j*(264) +320 + j*(168) +315 + j*(-167) +11 + j*(-255) +-103 + j*(-51) +8 + j*(26) +26 + j*(-25) +5 + j*(4) +61 + j*(14) +71 + j*(-38) +62 + j*(-42) +102 + j*(-91) +30 + j*(-209) +-154 + j*(-167) +-170 + j*(28) +-4 + j*(84) +75 + j*(-52) +-42 + j*(-158) +-196 + j*(-76) +-167 + j*(122) +52 + j*(160) +147 + j*(-67) +-71 + j*(-224) +-288 + j*(-60) +-233 + j*(160) +-115 + j*(214) +-53 + j*(279) +156 + j*(344) +403 + j*(129) +305 + j*(-223) +-13 + j*(-255) +-86 + j*(-47) +35 + j*(-33) +-35 + j*(-149) +-202 + j*(-40) +-119 + j*(170) +86 + j*(138) +84 + j*(-18) +-21 + j*(-8) +10 + j*(69) +79 + j*(35) +62 + j*(-9) +64 + j*(6) +117 + j*(-38) +78 + j*(-147) +-62 + j*(-166) +-147 + j*(-49) +-96 + j*(75) +23 + j*(88) +79 + j*(8) +55 + j*(-57) +28 + j*(-82) +-13 + j*(-128) +-125 + j*(-137) +-226 + j*(-23) +-197 + j*(148) +-41 + j*(251) +158 + j*(197) +228 + j*(-18) +69 + j*(-161) +-68 + j*(-64) +13 + j*(20) +49 + j*(-93) +-93 + j*(-119) +-125 + j*(1) +-74 + j*(-6) +-194 + j*(5) +-200 + j*(272) +164 + j*(381) +399 + j*(35) +170 + j*(-278) +-124 + j*(-202) +-181 + j*(1) +-99 + j*(130) +40 + j*(155) +115 + j*(48) +47 + j*(-8) +49 + j*(64) +170 + j*(11) +112 + j*(-161) +-74 + j*(-132) +-78 + j*(27) +31 + j*(60) +92 + j*(13) +125 + j*(-69) +62 + j*(-180) +-76 + j*(-174) +-123 + j*(-94) +-156 + j*(-50) +-170 + j*(93) +50 + j*(170) +159 + j*(-115) +-197 + j*(-238) +-335 + j*(179) +103 + j*(320) +206 + j*(-99) +-185 + j*(-123) +-128 + j*(246) +194 + j*(129) +23 + j*(-105) +-100 + j*(143) +235 + j*(190) +255 + j*(-187) +-83 + j*(-195) +-48 + j*(43) +90 + j*(-62) +-66 + j*(-126) +-54 + j*(26) +61 + j*(-91) +-182 + j*(-188) +-292 + j*(146) +59 + j*(268) +154 + j*(-42) +-104 + j*(-69) +-62 + j*(144) +95 + j*(56) +-24 + j*(-26) +-31 + j*(132) +156 + j*(95) +112 + j*(-81) +-4 + j*(-31) +79 + j*(8) +69 + j*(-118) +-75 + j*(-99) +-64 + j*(18) +-15 + j*(8) +-44 + j*(33) +38 + j*(95) +130 + j*(-11) +35 + j*(-104) +-21 + j*(-25) +64 + j*(-24) +41 + j*(-137) +-82 + j*(-142) +-141 + j*(-64) +-153 + j*(28) +-67 + j*(131) +93 + j*(62) +26 + j*(-125) +-173 + j*(-42) +-63 + j*(158) +138 + j*(8) +-60 + j*(-206) +-307 + j*(6) +-136 + j*(267) +69 + j*(159) +-29 + j*(66) +-37 + j*(230) +202 + j*(243) +265 + j*(5) +98 + j*(-65) +90 + j*(48) +213 + j*(-6) +160 + j*(-149) +56 + j*(-121) +119 + j*(-106) +91 + j*(-280) +-187 + j*(-302) +-305 + j*(-4) +-69 + j*(175) +116 + j*(18) +30 + j*(-141) +-93 + j*(-135) +-163 + j*(-81) +-216 + j*(28) +-139 + j*(171) +18 + j*(165) +49 + j*(78) +57 + j*(83) +155 + j*(21) +103 + j*(-164) +-122 + j*(-168) +-175 + j*(40) +-28 + j*(109) +23 + j*(23) +-23 + j*(6) +-10 + j*(32) +2 + j*(1) +-35 + j*(-1) +-23 + j*(35) +13 + j*(-4) +-66 + j*(-68) +-210 + j*(28) +-175 + j*(274) +111 + j*(379) +349 + j*(170) +293 + j*(-82) +161 + j*(-128) +151 + j*(-157) +40 + j*(-276) +-187 + j*(-195) +-172 + j*(47) +14 + j*(54) +-13 + j*(-79) +-132 + j*(-13) +-64 + j*(110) +35 + j*(85) +52 + j*(49) +99 + j*(15) +79 + j*(-91) +-39 + j*(-89) +-27 + j*(5) +39 + j*(-52) +-76 + j*(-105) +-136 + j*(44) +11 + j*(106) +51 + j*(-4) +-18 + j*(1) +37 + j*(23) +4 + j*(-74) +-138 + j*(35) +53 + j*(249) +366 + j*(14) +157 + j*(-379) +-248 + j*(-250) +-188 + j*(83) +41 + j*(38) +-22 + j*(-115) +-141 + j*(-55) +-129 + j*(31) +-105 + j*(80) +-28 + j*(122) +49 + j*(49) +-32 + j*(-14) +-62 + j*(99) +91 + j*(110) +94 + j*(-57) +-52 + j*(-32) +41 + j*(77) +134 + j*(-120) +-168 + j*(-247) +-377 + j*(124) +-13 + j*(419) +333 + j*(126) +125 + j*(-203) +-144 + j*(-54) +-21 + j*(157) +153 + j*(50) +77 + j*(-89) +-10 + j*(-42) +33 + j*(-24) +-8 + j*(-95) +-121 + j*(-30) +-54 + j*(96) +50 + j*(21) +-81 + j*(-54) +-167 + j*(165) +110 + j*(319) +340 + j*(62) +156 + j*(-168) +14 + j*(-24) +199 + j*(27) +245 + j*(-236) +-26 + j*(-341) +-163 + j*(-165) +-98 + j*(-92) +-140 + j*(-118) +-202 + j*(-4) +-97 + j*(97) +-11 + j*(29) +-64 + j*(-8) +-75 + j*(61) +6 + j*(84) +62 + j*(32) +72 + j*(-46) +13 + j*(-127) +-112 + j*(-111) +-132 + j*(13) +-25 + j*(25) +-56 + j*(-96) +-250 + j*(-49) +-264 + j*(226) +14 + j*(361) +247 + j*(173) +189 + j*(-72) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +0 + j*(0) +];